Files
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
2.7 KiB
Python

#!/usr/bin/env python3
"""audit_duplication.py — 扫描 MoFin 相关目录的文件重复情况"""
import os, hashlib, json
from collections import defaultdict
LOCATIONS = [
'/home/hmo/MoFin',
'/home/hmo/MoFin/scripts',
'/home/hmo/MoFin/deploy/profile-scripts',
'/home/hmo/MoFin/deploy/bot',
'/home/hmo/.hermes/profiles/position-analyst/scripts',
'/home/hmo/.hermes/scripts',
'/home/hmo/web-dashboard',
]
def md5(p):
try:
with open(p, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()[:10]
except Exception:
return 'ERR'
def ino(p):
try:
return os.stat(p).st_ino
except Exception:
return 0
# 收集所有 .py 文件
files = defaultdict(list) # name -> [(loc, path, md5, inode, is_link)]
for loc in LOCATIONS:
if not os.path.isdir(loc):
continue
for f in os.listdir(loc):
if not f.endswith('.py'):
continue
p = os.path.join(loc, f)
if not os.path.isfile(p):
continue
files[f].append({
'loc': loc, 'path': p, 'md5': md5(p), 'inode': ino(p),
'is_link': os.path.islink(p),
'size': os.path.getsize(p),
'mtime': int(os.path.getmtime(p)),
})
print("=== 重复文件(同名出现在2+位置)===")
dups = {k: v for k, v in files.items() if len(v) > 1}
identical = 0
hardlinked = 0
diverged = 0
for name in sorted(dups):
entries = dups[name]
md5s = set(e['md5'] for e in entries)
inodes = set(e['inode'] for e in entries)
if len(inodes) == 1:
status = 'HARDLINK(同一文件)'
hardlinked += 1
elif len(md5s) == 1:
status = 'COPY(内容相同,多份独立)'
identical += 1
else:
status = 'DIVERGED(内容不同!)'
diverged += 1
print(f"{status} {name}")
for e in entries:
print(f" {e['path']} md5={e['md5']} ino={e['inode']} size={e['size']}")
print(f"\n汇总: {len(dups)} 个重复文件名 | hardlink={hardlinked} 内容相同副本={identical} 内容分叉={diverged}")
print("\n=== deploy/profile-scripts 中有但 position-analyst/scripts 中缺失的 ===")
pa_dir = '/home/hmo/.hermes/profiles/position-analyst/scripts'
deploy_dir = '/home/hmo/MoFin/deploy/profile-scripts'
pa_files = set(os.listdir(pa_dir)) if os.path.isdir(pa_dir) else set()
for f in sorted(os.listdir(deploy_dir)):
if f.endswith('.py') and f not in pa_files:
print(f" {f}")
print("\n=== position-analyst/scripts 中有但 deploy 中没有的(可能孤儿)===")
deploy_files = set(os.listdir(deploy_dir))
for f in sorted(pa_files):
if f.endswith('.py') and f not in deploy_files:
p = os.path.join(pa_dir, f)
print(f" {f} size={os.path.getsize(p)}")