整理 NAS 部署目录并归档迁移工具

更新 Compose 和部署更新脚本以使用新的状态、凭据及日历目录布局;新增目录迁移、诊断和历史清理工具及本机演练测试,并记录 NAS 迁移与清理结果。
This commit is contained in:
weiyuqing committed 2026-10-17 22:32:58 +08:00
1 parent 1af63ff83a
commit 6e2a53ad20
14 files changed
+838 -8

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
"""只读诊断迁移失败;不停止容器,不读取健康数据或输出环境凭据。"""
import json
import subprocess
import tempfile
from pathlib import Path
ROOT = Path('/vol2/1000/Soft/mi-fitness-health')
NAMES = ['mi-fitness-health-' + x + '-1' for x in ['backend', 'web', 'worker']]
def run(*args):
return subprocess.check_output(args, stderr=subprocess.PIPE, timeout=90)
items = json.loads(run('docker', 'inspect', *NAMES))
for item in items:
print(json.dumps({'container': item['Name'], 'status': item['State']['Status'],
'health': item['State'].get('Health', {}).get('Status'),
'mounts': [{'source': m.get('Source'), 'destination': m['Destination']}
for m in item['Mounts'] if m.get('Type') == 'bind']}, ensure_ascii=False))
events = run('docker', 'events', '--since', '2026-10-17T16:40:00+08:00',
'--until', '2026-10-17T16:45:00+08:00', '--filter', 'type=container',
'--filter', 'label=com.docker.compose.project=mi-fitness-health', '--format', '{{json .}}')
for line in events.splitlines():
event = json.loads(line)
action = event.get('Action', '')
if action in {'create', 'start', 'stop', 'die', 'destroy', 'kill'} or action.startswith('health_status'):
attrs = event.get('Actor', {}).get('Attributes', {})
print(json.dumps({'event': action, 'time': event.get('time'),
'name': attrs.get('name'), 'exit_code': attrs.get('exitCode')}, ensure_ascii=False))
with tempfile.TemporaryDirectory(prefix='health-migration-readonly-') as directory:
base = (ROOT/'compose.yml').read_text(encoding='utf-8')
over = (ROOT/'compose.override.yml').read_text(encoding='utf-8')
base = base.replace('./state:', './shared/state:').replace('./state/data:', './shared/state/data:').replace('./secrets/', './backend/secrets/')
over = over.replace('./calendar:', './web/calendar:')
paths = []
for name, text in [('compose.yml', base), ('compose.override.yml', over)]:
path = Path(directory)/name
path.write_text(text, encoding='utf-8')
paths.extend(['-f', str(path)])
try:
run('docker', 'compose', '--project-directory', str(ROOT), '--env-file', str(ROOT/'.env'),
'-p', 'mi-fitness-health', *paths, 'config', '--quiet')
print('候选挂载配置静态解析通过(未应用)。')
except subprocess.CalledProcessError:
print('候选挂载配置静态解析失败。')
print('只读诊断完成。')