From faf2f28c7c9b22e4a8f1fd765b268bdfd650d0f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Apr 2026 09:04:51 +0000 Subject: [PATCH] =?UTF-8?q?=E9=93=B8=E6=B8=8A=E4=B8=93=E7=BA=BF=E5=85=A8?= =?UTF-8?q?=E9=9D=A2=E6=8E=92=E6=9F=A5=E4=BF=AE=E5=A4=8D:=20Shell=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E9=98=B2=E6=8A=A4+SMTP=E6=8C=81=E4=B9=85=E5=8C=96+loa?= =?UTF-8?q?dConfig=E9=80=9A=E7=94=A8=E5=8C=96+ecosystem=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E8=A1=A5=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/f9b09d73-b949-4f02-b3b9-2e69f90cd8b6 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/workflows/deploy-proxy-service.yml | 2 ++ server/proxy/deploy-proxy.sh | 22 +++++++++++++++++++++- server/proxy/ecosystem.proxy.config.js | 6 ++++-- server/proxy/service/proxy-guardian.js | 11 ++++++----- server/proxy/service/send-subscription.js | 18 ++++++++++++++---- server/proxy/service/traffic-monitor.js | 11 ++++++----- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/.github/workflows/deploy-proxy-service.yml b/.github/workflows/deploy-proxy-service.yml index a26423ad..44f08981 100644 --- a/.github/workflows/deploy-proxy-service.yml +++ b/.github/workflows/deploy-proxy-service.yml @@ -91,6 +91,8 @@ jobs: "cd /opt/zhuyuan/proxy-deploy && \ export ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \ export ZY_CN_RELAY_HOST='${{ secrets.ZY_CN_SERVER_HOST }}' && \ + export ZY_SMTP_USER='${{ secrets.ZY_SMTP_USER }}' && \ + export ZY_SMTP_PASS='${{ secrets.ZY_SMTP_PASS }}' && \ bash deploy-proxy.sh ${{ github.event.inputs.action }}" - name: '🧹 清理SSH密钥' diff --git a/server/proxy/deploy-proxy.sh b/server/proxy/deploy-proxy.sh index c44d1c6c..feafbcda 100644 --- a/server/proxy/deploy-proxy.sh +++ b/server/proxy/deploy-proxy.sh @@ -51,7 +51,7 @@ ensure_log_permissions() { chmod 755 "$PROXY_DIR/logs" } -# ── 共用: 保存ZY_SERVER_HOST到.env.keys ── +# ── 共用: 保存环境变量到.env.keys ── save_server_host() { KEYS_FILE="$PROXY_DIR/.env.keys" if [ -n "${ZY_SERVER_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then @@ -84,6 +84,26 @@ save_server_host() { fi echo " ✅ ZY_CN_RELAY_HOST 已保存到 .env.keys" fi + + # 保存SMTP凭据 (如果有) — 使守护Agent和流量监控可发送告警邮件 + if [ -n "${ZY_SMTP_USER:-}" ] && [ -f "$KEYS_FILE" ]; then + if grep -q "^ZY_SMTP_USER=" "$KEYS_FILE" 2>/dev/null; then + sed -i "s|^ZY_SMTP_USER=.*|ZY_SMTP_USER=${ZY_SMTP_USER}|" "$KEYS_FILE" + else + echo "" >> "$KEYS_FILE" + echo "# SMTP凭据 (部署时自动写入·守护Agent告警用)" >> "$KEYS_FILE" + echo "ZY_SMTP_USER=${ZY_SMTP_USER}" >> "$KEYS_FILE" + fi + echo " ✅ ZY_SMTP_USER 已保存到 .env.keys" + fi + if [ -n "${ZY_SMTP_PASS:-}" ] && [ -f "$KEYS_FILE" ]; then + if grep -q "^ZY_SMTP_PASS=" "$KEYS_FILE" 2>/dev/null; then + sed -i "s|^ZY_SMTP_PASS=.*|ZY_SMTP_PASS=${ZY_SMTP_PASS}|" "$KEYS_FILE" + else + echo "ZY_SMTP_PASS=${ZY_SMTP_PASS}" >> "$KEYS_FILE" + fi + echo " ✅ ZY_SMTP_PASS 已保存到 .env.keys" + fi } # ── install: 首次完整安装 ───────────────────── diff --git a/server/proxy/ecosystem.proxy.config.js b/server/proxy/ecosystem.proxy.config.js index 39f68acd..ee805d36 100644 --- a/server/proxy/ecosystem.proxy.config.js +++ b/server/proxy/ecosystem.proxy.config.js @@ -28,7 +28,8 @@ module.exports = { instances: 1, env: { NODE_ENV: 'production', - ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data' + ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data', + ZY_PROXY_KEYS_FILE: '/opt/zhuyuan/proxy/.env.keys' }, max_memory_restart: '64M', log_file: '/opt/zhuyuan/proxy/logs/monitor.log', @@ -43,7 +44,8 @@ module.exports = { env: { NODE_ENV: 'production', ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data', - ZY_PROXY_LOG_DIR: '/opt/zhuyuan/proxy/logs' + ZY_PROXY_LOG_DIR: '/opt/zhuyuan/proxy/logs', + ZY_PROXY_KEYS_FILE: '/opt/zhuyuan/proxy/.env.keys' }, max_memory_restart: '128M', log_file: '/opt/zhuyuan/proxy/logs/guardian.log', diff --git a/server/proxy/service/proxy-guardian.js b/server/proxy/service/proxy-guardian.js index 36da79f6..6812db8f 100644 --- a/server/proxy/service/proxy-guardian.js +++ b/server/proxy/service/proxy-guardian.js @@ -24,7 +24,7 @@ 'use strict'; -const { execSync, exec } = require('child_process'); +const { execSync, execFileSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const https = require('https'); @@ -275,10 +275,11 @@ async function consultLLM(issue) { function sendAlertEmail(subject, body) { try { const sendScript = path.join(__dirname, 'send-subscription.js'); - execSync( - `node "${sendScript}" alert "${subject}\n\n${body}"`, - { encoding: 'utf8', timeout: 30000 } - ); + // 使用execFileSync避免Shell命令注入 (不经过shell解释器) + execFileSync('node', [sendScript, 'alert', `${subject}\n\n${body}`], { + encoding: 'utf8', + timeout: 30000 + }); console.log('[守护Agent] 告警邮件已发送'); } catch (err) { console.error('[守护Agent] 邮件发送失败:', err.message); diff --git a/server/proxy/service/send-subscription.js b/server/proxy/service/send-subscription.js index 7b773ff8..c8cfd249 100644 --- a/server/proxy/service/send-subscription.js +++ b/server/proxy/service/send-subscription.js @@ -29,6 +29,8 @@ const path = require('path'); const KEYS_FILE = process.env.ZY_PROXY_KEYS_FILE || '/opt/zhuyuan/proxy/.env.keys'; // ── 加载配置 ───────────────────────────────── +// 优先级: 环境变量 > .env.keys文件 +// 通用读取所有键值对,确保guardian/monitor等服务也能获取完整配置 function loadConfig() { const config = { smtp_user: process.env.ZY_SMTP_USER || '', @@ -37,13 +39,21 @@ function loadConfig() { sub_token: process.env.ZY_PROXY_SUB_TOKEN || '' }; - // 尝试从本地密钥文件读取Token + // 从.env.keys文件读取所有键值对(环境变量未设置时回退) try { const content = fs.readFileSync(KEYS_FILE, 'utf8'); for (const line of content.split('\n')) { - if (line.startsWith('ZY_PROXY_SUB_TOKEN=')) { - config.sub_token = line.split('=')[1].trim(); - } + if (line.startsWith('#') || !line.includes('=')) continue; + const [key, ...vals] = line.split('='); + const k = key.trim(); + const v = vals.join('=').trim(); + if (!v) continue; + + // 仅在环境变量未设置时使用文件中的值 + if (k === 'ZY_PROXY_SUB_TOKEN' && !config.sub_token) config.sub_token = v; + if (k === 'ZY_SERVER_HOST' && !config.server_host) config.server_host = v; + if (k === 'ZY_SMTP_USER' && !config.smtp_user) config.smtp_user = v; + if (k === 'ZY_SMTP_PASS' && !config.smtp_pass) config.smtp_pass = v; } } catch { /* ignore */ } diff --git a/server/proxy/service/traffic-monitor.js b/server/proxy/service/traffic-monitor.js index 6853d062..307191d1 100644 --- a/server/proxy/service/traffic-monitor.js +++ b/server/proxy/service/traffic-monitor.js @@ -15,7 +15,7 @@ 'use strict'; -const { execSync } = require('child_process'); +const { execSync, execFileSync } = require('child_process'); const fs = require('fs'); const path = require('path'); @@ -177,10 +177,11 @@ async function sendAlert(alert, quota) { const usedGB = ((quota.upload_bytes + quota.download_bytes) / (1024 ** 3)).toFixed(2); const totalGB = (quota.total_bytes / (1024 ** 3)).toFixed(0); - execSync( - `node "${sendScript}" alert "${alert.message} 已用 ${usedGB}GB / ${totalGB}GB"`, - { encoding: 'utf8', timeout: 30000 } - ); + // 使用execFileSync避免Shell命令注入 (不经过shell解释器) + execFileSync('node', [sendScript, 'alert', `${alert.message} 已用 ${usedGB}GB / ${totalGB}GB`], { + encoding: 'utf8', + timeout: 30000 + }); console.log(`[流量监控] 告警邮件已发送: ${alert.level}`); } catch (err) { console.error('[流量监控] 告警邮件发送失败:', err.message);