feat: F健康cron来源标记+开发原则横幅——pipelines加source字段(hermes/system_crontab),扫描系统crontab的MoFin任务标红'系统cron(违规)',顶部横幅'禁止系统crontab部署自动任务统一hermes'+违规统计
This commit is contained in:
@@ -132,10 +132,51 @@ def load_cron_jobs():
|
||||
if jid in seen: continue
|
||||
seen.add(jid)
|
||||
j["profile"] = profile_tag
|
||||
j["source"] = "hermes" # 2026-08-12 cron来源标记:统一 hermes 体系
|
||||
jobs.append(j)
|
||||
except: pass
|
||||
return jobs
|
||||
|
||||
|
||||
def load_system_crontab_tasks():
|
||||
"""扫描系统 crontab 里 MoFin 相关任务(2026-08-12 老莫要求:显著提示违规系统 cron)。
|
||||
开发原则:自动任务必须部署在 hermes(position-analyst),禁止系统 crontab。
|
||||
返回含 MoFin/profile-scripts 路径的 crontab 条目,source='system_crontab'(违规警告)。"""
|
||||
import subprocess as _sp
|
||||
tasks = []
|
||||
try:
|
||||
out = _sp.run(["crontab", "-l"], capture_output=True, text=True, timeout=10).stdout
|
||||
for line in out.splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
# 只关心 MoFin 相关(含 MoFin 或 profile-scripts 路径)
|
||||
if "MoFin" not in line and "profile-scripts" not in line:
|
||||
continue
|
||||
# 提取调度(前 5 个字段或 @reboot)和命令/脚本
|
||||
script = ""
|
||||
m = line.split("python3")[-1].split("python")[-1].strip()
|
||||
import re as _re
|
||||
sm = _re.search(r'([\w./-]*profile-scripts/([\w.-]+\.py)|([\w.-]+\.py))', line)
|
||||
if sm:
|
||||
script = sm.group(2) or sm.group(3) or ""
|
||||
sched = " ".join(line.split()[:5]) if not line.startswith("@") else line.split()[0]
|
||||
tasks.append({
|
||||
"name": f"[系统cron] {script or line[:40]}",
|
||||
"script": script,
|
||||
"schedule": sched,
|
||||
"status": "unknown",
|
||||
"last_run": "",
|
||||
"profile": "system",
|
||||
"source": "system_crontab", # 违规:应迁移到 hermes
|
||||
"no_agent": True,
|
||||
"type": "no_agent",
|
||||
"enabled": True,
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
return tasks
|
||||
|
||||
def get_db_stats():
|
||||
conn = get_conn()
|
||||
tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").fetchall()
|
||||
@@ -1018,6 +1059,7 @@ def build_report():
|
||||
"type": "no_agent" if no_agent else "LLM",
|
||||
"script": script,
|
||||
"layer": _pipeline_layer(script, name), # 2026-08-12 三层架构层归属
|
||||
"source": j.get("source", "hermes"), # 2026-08-12 cron来源(hermes 统一体系)
|
||||
"schedule": schedule,
|
||||
"status": status,
|
||||
"last_run": last_run,
|
||||
@@ -1029,6 +1071,17 @@ def build_report():
|
||||
feature_tree["status"] = "fail"
|
||||
feature_tree.setdefault("warn_detail", {})[name] = output_missing_reason
|
||||
|
||||
# ── 2026-08-12 系统 crontab 违规任务(老莫要求:显著提示。开发原则:自动任务统一 hermes,禁止系统 crontab)──
|
||||
_sys_tasks = load_system_crontab_tasks()
|
||||
for _t in _sys_tasks:
|
||||
_t["layer"] = _pipeline_layer(_t.get("script", ""), _t.get("name", ""))
|
||||
_t["output_missing"] = False
|
||||
_t["output_missing_reason"] = ""
|
||||
pipelines.append(_t)
|
||||
if _sys_tasks:
|
||||
feature_tree.setdefault("warn_detail", {})["system_crontab"] = (
|
||||
f"发现 {len(_sys_tasks)} 个系统 crontab 部署的 MoFin 任务(违规:应迁移到 hermes)")
|
||||
|
||||
# ── 自检体系状态(L1功能健康/L3修复记录/L4元监控/L2卫生)──
|
||||
self_check = {}
|
||||
LOGS = Path('/home/hmo/MoFin/gateway/logs')
|
||||
|
||||
@@ -347,7 +347,16 @@ function renderPipelineTable(pipelines) {
|
||||
['monitor', '🩺 监控运维层', '健康检查/审计/备份/推送/自修复'],
|
||||
];
|
||||
const selStyle = 'background:#21262d;color:#c9d1d9;border:1px solid #30363d;border-radius:4px;padding:5px 8px;font-size:12px';
|
||||
let html = '<div style="display:flex;gap:8px;margin-bottom:8px;align-items:center">';
|
||||
// 2026-08-12 系统 crontab 违规统计(老莫:显著提示)
|
||||
const sysCnt = pipelines.filter(p => p.source === 'system_crontab').length;
|
||||
let html = '';
|
||||
// 显著横幅:开发原则——禁止系统 crontab 部署自动任务,统一 hermes
|
||||
html += `<div style="background:#3d1f1f;border:1px solid #f85149;border-left:4px solid #f85149;border-radius:6px;padding:10px 14px;margin-bottom:12px">` +
|
||||
`<div style="font-weight:bold;color:#f85149;font-size:14px">🚫 开发原则(强制):自动任务必须部署在 hermes(position-analyst),严禁使用系统 crontab</div>` +
|
||||
`<div style="color:#d29922;font-size:12px;margin-top:4px">来源标记:✅ hermes(合规)| ⚠️ 系统cron(违规,需迁移)。当前检测到 <strong>${sysCnt}</strong> 个系统 crontab 部署的 MoFin 任务。</div>` +
|
||||
(sysCnt > 0 ? `<div style="color:#f85149;font-size:12px;margin-top:2px">⚠️ 存在违规系统 cron,请迁移到 hermes 后从系统 crontab 移除(统一体系,避免新旧一起跑)。</div>` : `<div style="color:#3fb950;font-size:12px;margin-top:2px">✅ 无违规系统 cron,体系统一。</div>`) +
|
||||
`</div>`;
|
||||
html += '<div style="display:flex;gap:8px;margin-bottom:8px;align-items:center">';
|
||||
html += '<input class="search-box" id="pipeSearch" placeholder="搜索流程..." oninput="filterPipes()" style="flex:1">';
|
||||
html += `<select id="pipeLayer" onchange="filterPipes()" style="${selStyle}">`;
|
||||
html += '<option value="all">全部层</option><option value="collect">📥 采集层</option><option value="process">⚙️ 加工层</option><option value="use">📊 使用层</option><option value="monitor">🩺 监控层</option></select>';
|
||||
@@ -367,10 +376,16 @@ function renderPipelineTable(pipelines) {
|
||||
const tagCls = p.status==='ok'?'ok':p.status==='error'?'error':'warn';
|
||||
const statusDisplay = p.last_run ? p.status : '待首次运行';
|
||||
const profileBadge = p.profile==='position-analyst' ? '📋' : '📦';
|
||||
// 2026-08-12 cron来源标记:系统 crontab 违规用红色警告(老莫要求显著提示)
|
||||
const isSys = p.source === 'system_crontab';
|
||||
const srcBadge = isSys
|
||||
? '<span style="color:#f85149;font-weight:bold">⚠️ 系统cron(违规)</span>'
|
||||
: '<span style="color:#3fb950">✅ hermes</span>';
|
||||
const rowStyle = isSys ? ' style="background:#2d1515;border-left:3px solid #f85149"' : '';
|
||||
const encName = encodeURIComponent(p.name || '');
|
||||
const encScript = encodeURIComponent(p.script || '');
|
||||
html += `<tr class="pipe-row" data-profile="${p.profile||'default'}" data-layer="${p.layer||'use'}" data-name="${(p.name||'').toLowerCase()}"><td>${p.name||p.script||'LLM'}</td>`;
|
||||
html += `<td style="font-size:11px">${profileBadge} ${p.profile||'?'}</td>`;
|
||||
html += `<tr class="pipe-row" data-profile="${p.profile||'default'}" data-layer="${p.layer||'use'}" data-name="${(p.name||'').toLowerCase()}"${rowStyle}><td>${p.name||p.script||'LLM'}</td>`;
|
||||
html += `<td style="font-size:11px">${srcBadge} <span style="color:#8b949e">${profileBadge}${p.profile||'?'}</span></td>`;
|
||||
html += `<td style="font-size:11px">${p.script||'LLM'}</td>`;
|
||||
html += `<td><span class="cron-tag ${tagCls}">${p.type||'cron'}</span></td>`;
|
||||
html += `<td style="font-size:11px">${p.schedule||'-'}</td>`;
|
||||
|
||||
Reference in New Issue
Block a user