Files
MoFin/archive/hermes-dead-tools-20260820/audit_data.py
T
xxm c68f987653 chore(cleansweep): 代码大扫除——归档hermes 111个死工具+4个废弃scanner,收敛MoFin/scripts重复副本,删除根旧版mo_models
- archive/hermes-dead-tools-20260820/: hermes独有不在cron不被import的111个一次性排查/测试工具
- archive/hermes-dead-tools-20260820/: 4个废弃scanner(btd1_v3/market_scanner/market_thermometer已废弃/s2v2)
- archive/legacy-cleanup-20260820/: MoFin根2旧版(mo_models/technical_analysis)+/home/hmo/scripts无引用旧项目+MoFin/scripts重复prepare_report_data
- 删除MoFin根mo_models.py(根旧版,deploy/profile-scripts权威保留)
- 保留: mofin_db.py/mo_data.py硬链接(server.py多层sys.path需各目录访问同一inode,非冗余)
- fix_gateway.py保留(Gateway看门狗fix_gateway_port.py的活跃依赖,勿误删)
- 验证: cron所有脚本引用无缺失, key模块import正常
- hermes独有从116收敛到5核心(alert_logger/market_screener/prepare_report_data/self_todo_executor_v2/xmpp_zhiwei_bot)
2026-08-20 10:36:25 +08:00

84 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""audit_data.py — 数据存储碎片化审计:三个数据目录 + 遗留JSON + 旧库"""
import os, json, sqlite3
from datetime import datetime
DATA_DIRS = [
'/home/hmo/MoFin/data',
'/home/hmo/web-dashboard/data',
'/home/hmo/.hermes/profiles/position-analyst/scripts/data',
'/home/hmo/.hermes/profiles/position-analyst/data',
'/home/hmo/.hermes/data',
]
now = datetime.now()
print("=== 1. 各数据目录内容与时效 ===")
for dd in DATA_DIRS:
if not os.path.isdir(dd):
print(f"\n{dd}: 不存在")
continue
print(f"\n{dd}:")
try:
entries = []
for f in sorted(os.listdir(dd)):
p = os.path.join(dd, f)
if os.path.isfile(p):
mt = datetime.fromtimestamp(os.path.getmtime(p))
age_h = (now - mt).total_seconds() / 3600
entries.append((f, os.path.getsize(p), mt, age_h))
# 只显示 >7天 或 >100KB 的
for f, size, mt, age_h in entries:
flag = '🔴' if age_h > 24*14 else ('🟡' if age_h > 24*3 else '🟢')
print(f" {flag} {f:45s} {size//1024:6d}KB {mt.strftime('%m-%d %H:%M')} ({age_h/24:.0f}d)")
except Exception as e:
print(f" ERR: {e}")
print("\n=== 2. 三个 mofin.db 对比 ===")
for label, path in [('canonical', '/home/hmo/MoFin/data/mofin.db'),
('profile-local', '/home/hmo/.hermes/profiles/position-analyst/scripts/data/mofin.db'),
('profile-data', '/home/hmo/.hermes/profiles/position-analyst/data/mofin.db')]:
if not os.path.exists(path):
print(f" {label}: 不存在")
continue
c = sqlite3.connect(path, timeout=5)
tables = {r[0]: r[1] for r in c.execute(
"SELECT name, (SELECT COUNT(*) FROM sqlite_master m2 WHERE m2.name=m1.name) FROM sqlite_master m1 WHERE type='table'")}
cnts = {}
for t in tables:
try:
cnts[t] = c.execute(f"SELECT COUNT(*) FROM {t}").fetchone()[0]
except Exception:
cnts[t] = -1
nonempty = {k: v for k, v in cnts.items() if v > 0}
print(f" {label} ({os.path.getsize(path)//1024}KB): {len(nonempty)} 张非空表")
for t, n in sorted(nonempty.items(), key=lambda x: -x[1])[:8]:
print(f" {t}: {n}")
c.close()
print("\n=== 3. 遗留 JSON 文件(web-dashboard/data,按最后修改排序)===")
wd = '/home/hmo/web-dashboard/data'
jfiles = []
for f in os.listdir(wd):
if f.endswith('.json') and os.path.isfile(os.path.join(wd, f)):
p = os.path.join(wd, f)
mt = datetime.fromtimestamp(os.path.getmtime(p))
jfiles.append((f, os.path.getsize(p), mt))
jfiles.sort(key=lambda x: x[2])
for f, size, mt in jfiles:
age_d = (now - mt).total_seconds() / 86400
flag = '🔴' if age_d > 14 else ('🟡' if age_d > 3 else '🟢')
print(f" {flag} {f:45s} {size//1024:5d}KB {mt.strftime('%m-%d')} ({age_d:.0f}d前)")
print("\n=== 4. trashbox / archive / 旧日志 ===")
for d in ['/home/hmo/trashbox', '/home/hmo/MoFin/archive', '/home/hmo/MoFin/data/archive']:
if os.path.isdir(d):
total = sum(os.path.getsize(os.path.join(r, f)) for r, _, fs in os.walk(d) for f in fs if os.path.isfile(os.path.join(r, f)))
cnt = sum(len(fs) for _, _, fs in os.walk(d))
print(f" {d}: {cnt} 个文件, {total//1024//1024}MB")
logs = [f for f in os.listdir('/home/hmo') if f.endswith('.log') and os.path.isfile(f'/home/hmo/{f}')]
print(f"\n /home/hmo 根目录 .log 文件: {len(logs)} 个")
for f in sorted(logs):
p = f'/home/hmo/{f}'
mt = datetime.fromtimestamp(os.path.getmtime(p))
print(f" {f} {os.path.getsize(p)//1024}KB {mt.strftime('%m-%d')}")