Root cause analysis of the 2026-07-20 redundancy incident: 1. No single-source-of-truth rule -> same file legitimately lived in 4+ locations, diverging silently 2. Relative path resolution (Path(__file__).parent/'data') -> each hardlinked copy of mofin_db.py pointed to a DIFFERENT database 3. 'Backup habit' left .bak/legacy files in production dirs, which monitoring then scanned and reported as false alarms 4. Half-done migrations: DB tables created but old JSON writers/readers stayed (price_events), old files stayed 5. Dead modules never got buried: xiaoguo 'dead' but bot ran 8 days as root eating 2.5GB 6. Monitoring checked 'does it exist' not 'is it alive' -> stale file mtime reported as 'pipeline stalled 14 days' (false alarm) 7. No 'system hygiene' as a check category at all Prevention implemented: - dev-spec.md v2.0: 五条红线 -> 十条红线 #6 single source of truth (hardlink only, no independent copies) #7 absolute data paths only (no __file__-relative data resolution) #8 no backups/legacy in production data dirs (archive immediately) #9 dead module burial checklist (6 mandatory steps) #10 monitor liveness (DB table freshness) not existence - File Location Constitution: canonical location per content type - NEW system_hygiene_audit.py: weekly Monday 07:30 cron checking diverged copies / broken hardlinks / zombie processes / orphan data files / dead cron scripts / DB freshness -> hygiene_report.json + XMPP - specs/hygiene.json: module spec per red line #1 - Verified: audit found 5 real issues on first run, all fixed, re-run clean
30 lines
1.1 KiB
Python
30 lines
1.1 KiB
Python
import os, shutil, glob
|
|
from datetime import datetime
|
|
|
|
ARCHIVE = '/home/hmo/MoFin/archive/old-files-20260720'
|
|
os.makedirs(ARCHIVE, exist_ok=True)
|
|
|
|
# 1. /home/hmo 根目录旧日志(>10天)
|
|
count = 0
|
|
for f in glob.glob('/home/hmo/*.log'):
|
|
age_d = (datetime.now().timestamp() - os.path.getmtime(f)) / 86400
|
|
if age_d > 10:
|
|
shutil.move(f, os.path.join(ARCHIVE, os.path.basename(f)))
|
|
count += 1
|
|
print(f' log: {os.path.basename(f)} ({age_d:.0f}d)')
|
|
print(f'logs archived: {count}')
|
|
|
|
# 2. 旧 bot 文件
|
|
for f in ['/home/hmo/xmpp_zhiwei_bot.py.bak', '/home/hmo/run_zhiwei_bot.py', '/home/hmo/xmpp_bot_rest.py']:
|
|
if os.path.exists(f):
|
|
shutil.move(f, os.path.join(ARCHIVE, os.path.basename(f)))
|
|
print(f' bot: {os.path.basename(f)}')
|
|
|
|
# 3. 数据目录 bak 文件
|
|
for f in ['/home/hmo/web-dashboard/data/watchlist.json.bak2',
|
|
'/home/hmo/.hermes/profiles/position-analyst/data/mofin.db.bak']:
|
|
if os.path.exists(f):
|
|
shutil.move(f, os.path.join(ARCHIVE, os.path.basename(f)))
|
|
print(f' bak: {os.path.basename(f)}')
|
|
|
|
print('DONE ->', ARCHIVE) |