From 3ce4bb8514eb93e14d93396bd9b171fb97c0ad68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Apr 2026 18:03:11 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20=E4=BF=AE=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=A1=E6=9F=A5=E5=8F=8D=E9=A6=88=C2=B7=E7=A3=81?= =?UTF-8?q?=E7=9B=98=E9=AA=8C=E8=AF=81=C2=B7=E6=97=A5=E5=BF=97=E6=88=AA?= =?UTF-8?q?=E6=96=AD=C2=B7SSH=E5=AE=89=E5=85=A8=C2=B7=E5=8D=B1=E9=99=A9?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=C2=B7=E5=8A=A8=E6=80=81=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/29df49f6-bbbb-49af-8e63-96704b11d9c5 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- scripts/deploy-log-collector.js | 34 ++++++++++++++++++++++++++++++++- scripts/deputy-auto-repair.js | 7 ++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/scripts/deploy-log-collector.js b/scripts/deploy-log-collector.js index ece64c0d..8f2b0d5f 100644 --- a/scripts/deploy-log-collector.js +++ b/scripts/deploy-log-collector.js @@ -50,6 +50,16 @@ function ensureDir(dir) { } } +// 智能截断日志:保留头部和尾部,确保错误信息不丢失 +function truncateLog(content, maxLen) { + if (!content || content.length <= maxLen) return content; + const headSize = Math.floor(maxLen * 0.3); // 30%给头部 + const tailSize = maxLen - headSize - 100; // 70%给尾部(错误通常在末尾) + const head = content.slice(0, headSize); + const tail = content.slice(-tailSize); + return `${head}\n\n... [截断 ${content.length - headSize - tailSize} 字符] ...\n\n${tail}`; +} + // ── GitHub API 请求 ──────────────────────────── function githubApi(endpoint) { const token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN; @@ -225,7 +235,7 @@ async function collectLogs() { conclusion: s.conclusion, number: s.number })), - log_content: logContent.slice(0, 10000) // 限制日志大小 + log_content: truncateLog(logContent, 10000) // 智能截断:保留头部和尾部 }); console.log(` ✅ 日志采集成功 (${logContent.length} 字符)`); } catch (err) { @@ -330,6 +340,7 @@ async function collectLogs() { // ── 简单错误分析 (模式匹配) ──────────────────── function simpleAnalysis(logContent) { + // 基础错误模式 + 动态加载经验库中的错误模式 const patterns = [ { regex: /EADDRINUSE/i, name: '端口被占用', fix: '重启PM2进程释放端口', severity: 'medium' }, { regex: /ECONNREFUSED/i, name: '服务连接被拒绝', fix: '检查PM2进程是否运行', severity: 'high' }, @@ -349,6 +360,27 @@ function simpleAnalysis(logContent) { { regex: /exit code [1-9]/i, name: '命令执行失败', fix: '查看上方具体错误信息', severity: 'medium' } ]; + // 尝试从经验数据库动态加载错误模式 + try { + const errPatternsDb = JSON.parse(fs.readFileSync(ERROR_PATTERNS_DB, 'utf8')); + if (errPatternsDb.patterns) { + for (const p of errPatternsDb.patterns) { + // 提取经验库中的关键词作为匹配模式 + const keywords = p.pattern.split(/[·\s+]/g).filter(k => k.length > 3); + if (keywords.length > 0) { + patterns.push({ + regex: new RegExp(keywords.join('|'), 'i'), + name: `[经验库] ${p.pattern}`, + fix: (p.prevention || []).join(' → ') || '参考经验库', + severity: p.severity || 'medium' + }); + } + } + } + } catch { + // 经验库加载失败不影响基础分析 + } + const matched = []; for (const p of patterns) { if (p.regex.test(logContent)) { diff --git a/scripts/deputy-auto-repair.js b/scripts/deputy-auto-repair.js index 56ae8966..911ee411 100644 --- a/scripts/deputy-auto-repair.js +++ b/scripts/deputy-auto-repair.js @@ -99,7 +99,7 @@ const REPAIR_STRATEGIES = [ 'sudo find /tmp -type f -mtime +1 -delete 2>/dev/null || true', 'df -h /' ], - verify: 'AVAIL=$(df / | tail -1 | awk \'{print $5}\' | tr -d \'%\'); [ "$AVAIL" -lt 90 ] || exit 1', + verify: 'USED=$(df / | tail -1 | awk \'{print $5}\' | tr -d \'%\'); [ "$USED" -lt 90 ] || exit 1', severity: 'high', success_rate: '中 · 取决于可清理的文件量' }, @@ -132,7 +132,7 @@ function sshExec(command) { } try { - const sshCmd = `ssh -i ~/.ssh/zy_key -o ConnectTimeout=10 -o StrictHostKeyChecking=no ${user}@${host} '${command.replace(/'/g, "'\\''")}'`; + const sshCmd = `ssh -i ~/.ssh/zy_key -o ConnectTimeout=10 ${user}@${host} '${command.replace(/'/g, "'\\''")}'`; const output = execSync(sshCmd, { timeout: 60000, // 60秒超时 encoding: 'utf8', @@ -463,7 +463,7 @@ async function repair() { // ── 危险命令检测 ──────────────────────────── function isDangerousCommand(cmd) { const dangerous = [ - /rm\s+-rf\s+\//, // rm -rf / + /rm\s+-r[fF]*\s+(\/|~|\$HOME)/, // rm -rf / or ~ or $HOME /mkfs/, // 格式化 /dd\s+if=/, // 磁盘写入 /shutdown/, // 关机 @@ -474,6 +474,7 @@ function isDangerousCommand(cmd) { /chmod\s+-R\s+777\s+\//, // 全局777 /userdel/, // 删除用户 /passwd/, // 修改密码 + /rm\s+-r[fF]*\s+\/\w/, // rm -rf /home etc ]; return dangerous.some(regex => regex.test(cmd)); }