Files
kefu/im/server-fix-20260831/deploy_guard.py
T
2026-09-03 08:38:17 +08:00

79 lines
2.9 KiB
Python

import hashlib
import json
import os
import shutil
import stat
import subprocess
import tempfile
BASE = '/www/backup/txiaw-mysql-fix-20260831'
STAGE = BASE + '/stage'
WEB = '/www/wwwroot/www.txiaw.com'
NGINX = '/www/server/panel/vhost/nginx'
BIN = '/www/server/nginx/sbin/nginx'
PHP = '/www/server/php/56/bin/php'
def run(args):
subprocess.run(args, check=True, timeout=20)
def atomic_copy(src, dst, metadata=None):
info = metadata or os.stat(src)
fd, tmp = tempfile.mkstemp(prefix='.txiaw-repair-', suffix='.tmp', dir=os.path.dirname(dst))
try:
with os.fdopen(fd, 'wb') as target, open(src, 'rb') as source:
shutil.copyfileobj(source, target)
target.flush()
os.fsync(target.fileno())
os.chmod(tmp, stat.S_IMODE(info.st_mode))
os.chown(tmp, info.st_uid, info.st_gid)
os.replace(tmp, dst)
finally:
if os.path.exists(tmp):
os.unlink(tmp)
manifest = json.load(open(STAGE + '/baseline.json'))
for item in manifest:
data = open(item['remote'], 'rb').read()
if hashlib.sha256(data).hexdigest() != item['sha256']:
raise RuntimeError('Source changed since inspection: ' + item['remote'])
shutil.copy2(item['remote'], BASE + '/originals/' + item['backup'])
os.chmod(BASE + '/originals/' + item['backup'], 0o600)
for name in ['HomeRequestProtection.php', 'index.php', 'test_home_guard.php']:
run([PHP, '-l', STAGE + '/' + name])
run([PHP, STAGE + '/test_home_guard.php'])
changes = [
('HomeRequestProtection.php', WEB + '/Lib/HomeRequestProtection.php', None),
('index.php', WEB + '/index.php', 'original-index.php'),
('txiaw-home-protection-http.inc', NGINX + '/txiaw-home-protection-http.inc', None),
('txiaw-home-protection-server.inc', NGINX + '/txiaw-home-protection-server.inc', None),
('www.txiaw.com.conf', NGINX + '/www.txiaw.com.conf', 'original-www.txiaw.com.conf'),
]
for source, target, backup in changes:
if backup is None and os.path.exists(target):
raise RuntimeError('Refusing to overwrite unexpected file: ' + target)
installed = []
metadata = {}
try:
for source, target, backup in changes:
metadata[target] = os.stat(target) if backup else None
if not backup:
os.chmod(STAGE + '/' + source, 0o644)
atomic_copy(STAGE + '/' + source, target, metadata[target])
installed.append((target, backup))
run([BIN, '-t'])
run([BIN, '-s', 'reload'])
except Exception:
for target, backup in reversed(installed):
if backup:
atomic_copy(BASE + '/originals/' + backup, target, metadata[target])
else:
os.unlink(target)
run([BIN, '-t'])
raise
json.dump({'files': [p for p, _ in installed], 'status': 'installed'}, open(BASE + '/guard-installed.json', 'w'), indent=2)
print('GUARD_DEPLOYED; PHP guard passed; nginx configuration passed and gracefully reloaded.', flush=True)