181 lines
6.2 KiB
Python
181 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Utility for building and installing nginx mod_rewrite module.
|
|
This script handles downloading, extracting, building, and installing the module.
|
|
Returns None on success, or error message string on failure.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import subprocess
|
|
import zipfile
|
|
import datetime
|
|
import re
|
|
|
|
|
|
def _get_nginx_version(log_file):
|
|
"""
|
|
Detect nginx version from /usr/sbin/nginx -V output.
|
|
|
|
Args:
|
|
log_file: File object to write log messages to
|
|
|
|
Returns:
|
|
str or None: Version string (e.g., '1.30.2') if found, None otherwise
|
|
"""
|
|
nginx_binary = '/usr/sbin/nginx'
|
|
if not os.path.exists(nginx_binary):
|
|
log_file.write('Nginx binary not found at /usr/sbin/nginx, using default version detection.\n')
|
|
return None
|
|
|
|
try:
|
|
result = subprocess.run([nginx_binary, '-V'], capture_output=True, text=True, timeout=30)
|
|
if result.returncode != 0:
|
|
log_file.write(f'Failed to run nginx -V with exit code {result.returncode}\n')
|
|
if result.stderr:
|
|
log_file.write(f'nginx stderr: {result.stderr.strip()}\n')
|
|
return None
|
|
|
|
log_file.write(f'nginx stdout:\n{result.stderr.strip()}\n')
|
|
|
|
# First line contains "nginx version: nginx/X.Y.Z"
|
|
first_line = result.stderr.strip().split('\n')[0]
|
|
|
|
# Parse the version from the first line
|
|
# Expected format: "nginx version: nginx/1.30.2 ..."
|
|
match = re.search(r'nginx/(\d+\.\d+\.?\d*)', first_line)
|
|
if match:
|
|
version = match.group(1)
|
|
log_file.write(f'Detected nginx version: {version}\n')
|
|
return version
|
|
else:
|
|
log_file.write(f'Could not parse nginx version from: {first_line}\n')
|
|
return None
|
|
except subprocess.TimeoutExpired:
|
|
log_file.write('nginx -V command timed out.\n')
|
|
return None
|
|
except Exception as e:
|
|
log_file.write(f'Error running nginx -V: {e}\n')
|
|
return None
|
|
|
|
|
|
def build_mod_rewrite():
|
|
"""
|
|
Build and install the nginx mod_rewrite module.
|
|
|
|
Returns:
|
|
str: Error message on failure, None on success
|
|
"""
|
|
tmp_dir = '/tmp/nginx-mod-rewrite'
|
|
log_path = '/usr/local/mgr5/var/nginx-mod-rewrite-plugin.log'
|
|
|
|
# Check for --nodeps argument - skip installdeps stage if provided
|
|
nodeps = False
|
|
args = sys.argv[1:]
|
|
if '--nodeps' in args:
|
|
nodeps = True
|
|
|
|
try:
|
|
# Ensure log directory exists
|
|
log_dir = os.path.dirname(log_path)
|
|
if log_dir and not os.path.exists(log_dir):
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
|
|
# Setup temporary directory: create or clean
|
|
if os.path.isdir(tmp_dir):
|
|
shutil.rmtree(tmp_dir)
|
|
os.makedirs(tmp_dir, exist_ok=True)
|
|
|
|
with open(log_path, 'a') as log_file:
|
|
log_file.write(f'=== Starting module download and install: {datetime.datetime.now()} ===\n')
|
|
|
|
# Copy the ZIP file into the temporary directory
|
|
src_zip = '/usr/local/ispmanager-mod_rewrite/mod_rewrite.zip'
|
|
dst_zip = os.path.join(tmp_dir, 'mod_rewrite.zip')
|
|
try:
|
|
shutil.copy(src_zip, dst_zip)
|
|
log_file.write(f'Copied zip to {dst_zip}\n')
|
|
except Exception as e:
|
|
return f'Failed to copy zip: {e}'
|
|
|
|
# Extract the ZIP file
|
|
try:
|
|
with zipfile.ZipFile(dst_zip, 'r') as zip_ref:
|
|
zip_ref.extractall(tmp_dir)
|
|
log_file.write('Extracted zip contents.\n')
|
|
except Exception as e:
|
|
return f'Failed to extract zip: {e}'
|
|
|
|
# Locate the extracted root directory
|
|
extracted_root = None
|
|
for entry in os.listdir(tmp_dir):
|
|
full_path = os.path.join(tmp_dir, entry)
|
|
if os.path.isdir(full_path):
|
|
extracted_root = full_path
|
|
break
|
|
if not extracted_root:
|
|
return 'Extracted folder not found.'
|
|
log_file.write(f'Using extracted root: {extracted_root}\n')
|
|
|
|
# Define the sequence of commands to run
|
|
if nodeps:
|
|
commands = []
|
|
else:
|
|
commands = [['bash', 'package_preparer.sh', 'installdeps']]
|
|
|
|
# Detect nginx version and decide on download target
|
|
nginx_version_to_use = '.' # Default fallback
|
|
|
|
detected_version = _get_nginx_version(log_file)
|
|
if detected_version is not None:
|
|
nginx_version_to_use = detected_version
|
|
log_file.write(f'Using detected nginx version: {nginx_version_to_use} for download\n')
|
|
else:
|
|
log_file.write('Nginx version detection failed, using default (.).\n')
|
|
|
|
if nginx_version_to_use == '.':
|
|
commands.extend([
|
|
['bash', 'package_preparer.sh', 'download', nginx_version_to_use, 'system']
|
|
])
|
|
else:
|
|
commands.extend([
|
|
['bash', 'package_preparer.sh', 'download', nginx_version_to_use]
|
|
])
|
|
|
|
commands.extend([
|
|
['bash', 'package_preparer.sh', 'build'],
|
|
['bash', 'package_preparer.sh', 'installmod']
|
|
])
|
|
|
|
for cmd in commands:
|
|
log_file.write(f'Running command: {" ".join(cmd)}\n')
|
|
result = subprocess.run(cmd, cwd=extracted_root, stdout=log_file, stderr=log_file)
|
|
if result.returncode != 0:
|
|
return f'Command {" ".join(cmd)} failed with exit code {result.returncode}'
|
|
|
|
log_file.write('All commands executed successfully.\n')
|
|
except Exception as exc:
|
|
return f'Unexpected error: {exc}'
|
|
finally:
|
|
# Clean up temporary directory
|
|
try:
|
|
if os.path.isdir(tmp_dir):
|
|
shutil.rmtree(tmp_dir)
|
|
except Exception:
|
|
pass
|
|
|
|
return None
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Run the build process and output result to stdout
|
|
result = build_mod_rewrite()
|
|
if result is not None:
|
|
# On error, write error message to stderr
|
|
print(result, file=sys.stderr)
|
|
sys.exit(1)
|
|
else:
|
|
# On success, exit with 0 (no output)
|
|
sys.exit(0)
|