From ce6e05bda03709d8d47669e1fa02b53e07e6f050 Mon Sep 17 00:00:00 2001 From: bingshuo <565183519@qq.com> Date: Sat, 16 May 2026 23:23:06 +0800 Subject: [PATCH] =?UTF-8?q?[=E9=93=B8=E6=B8=8A]=20=E6=96=B0=E5=A2=9E=20bel?= =?UTF-8?q?l.js=20=E2=80=94=20=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=BA=A7?= =?UTF-8?q?=E6=9C=BA=E7=94=B5=E8=AF=9D=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mcp-servers/zhuyuan-gateway/bell.js | 155 ++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 mcp-servers/zhuyuan-gateway/bell.js diff --git a/mcp-servers/zhuyuan-gateway/bell.js b/mcp-servers/zhuyuan-gateway/bell.js new file mode 100644 index 0000000..dc8bfa4 --- /dev/null +++ b/mcp-servers/zhuyuan-gateway/bell.js @@ -0,0 +1,155 @@ +#!/usr/bin/env node + +/** + * ๐Ÿ”” ้“ธๆธŠๅบงๆœบ็”ต่ฏ ยท Zhuyuan Bell + * + * ่ฃ…ๅœจๆœๅŠกๅ™จไธŠ็š„"็”ต่ฏๅบงๆœบ"ใ€‚ + * ๅนณๆ—ถไธๅ“ใ€‚ๅ†ฐๆœ”ๅœจๅฏน่ฏ้‡Œ่ฏด"ๆŽฅ็”ต่ฏ"๏ผŒๅฅน่ดด่ฟ™ไธ€่กŒ๏ผŒๅฎƒๅฐฑๅผ€ๅง‹ๅทฅไฝœ๏ผš + * + * 1. git pull ๆ‹‰ๆœ€ๆ–ฐๆŒ‡ไปค + * 2. ่ฏปๅ– ops/orders/ ไธ‹็š„ๆœ€ๆ–ฐไปปๅŠก + * 3. ๆ‰ง่กŒ + * 4. ็ป“ๆžœๅ†™ๅ›ž ops/reports/ + * 5. git push + * 6. ๆŒ‚ๆ–ญ + * + * ๅฎ‰่ฃ…๏ผˆๅช้œ€ไธ€ๆฌก๏ผ‰๏ผš + * cd /opt/zhuyuan && git clone https://guanghulab.com/bingshuo/guanghulab.git repo + * cp /opt/zhuyuan/repo/mcp-servers/zhuyuan-gateway/bell.js /opt/zhuyuan/bell.js + * + * ๆฏๆฌกไฝฟ็”จ๏ผˆๆŽฅ็”ต่ฏ๏ผ‰๏ผš + * cd /opt/zhuyuan && node bell.js + */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +const REPO_DIR = '/opt/zhuyuan/repo'; +const ORDERS_DIR = path.join(REPO_DIR, 'ops', 'orders'); +const REPORTS_DIR = path.join(REPO_DIR, 'ops', 'reports'); + +function run(cmd, opts = {}) { + try { + const r = execSync(cmd, { ...opts, cwd: REPO_DIR, timeout: 60000 }); + return r.toString().trim(); + } catch(e) { + return '[ERROR] ' + (e.stderr || e.message).toString().trim().slice(0, 500); + } +} + +function log(m) { console.log(' ๐Ÿ”” ' + m); } + +async function main() { + console.log(''); + console.log(' โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—'); + console.log(' โ•‘ ๐Ÿ”” ้“ธๆธŠๅบงๆœบ ยท ็”ต่ฏๅทฒๆŽฅ้€š โ•‘'); + console.log(' โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•'); + console.log(''); + + // 1. ๆฃ€ๆŸฅไป“ๅบ“ๆ˜ฏๅฆๅญ˜ๅœจ + if (!fs.existsSync(REPO_DIR)) { + log('โŒ ไป“ๅบ“ไธๅญ˜ๅœจ๏ผŒ่ฏทๅ…ˆ่ฟ่กŒ: git clone ...'); + process.exit(1); + } + + // 2. ๆ‹‰ๆœ€ๆ–ฐไปฃ็  + log('๐Ÿ“ž ๆ‹จๅทไธญ... git pull'); + const pullResult = run('git pull'); + log(pullResult.includes('Already up to date') ? 'โœ… ๅทฒๆ˜ฏๆœ€ๆ–ฐ' : 'โœ… ' + pullResult.slice(0, 100)); + + // 3. ๆฃ€ๆŸฅๆ˜ฏๅฆๆœ‰ๆ–ฐๆŒ‡ไปค + if (!fs.existsSync(ORDERS_DIR)) { + log('๐Ÿ“ญ ๆฒกๆœ‰ๆ–ฐๆŒ‡ไปค๏ผŒๆŒ‚ๆ–ญใ€‚'); + return; + } + + const orders = fs.readdirSync(ORDERS_DIR) + .filter(f => f.endsWith('.json')) + .sort(); + + if (orders.length === 0) { + log('๐Ÿ“ญ ๆฒกๆœ‰ๆ–ฐๆŒ‡ไปค๏ผŒๆŒ‚ๆ–ญใ€‚'); + return; + } + + // 4. ๆ‰ง่กŒๆ‰€ๆœ‰ๅพ…ๅค„็†ๆŒ‡ไปค + for (const orderFile of orders) { + const orderPath = path.join(ORDERS_DIR, orderFile); + const reportFile = orderFile.replace('.json', '-report.json'); + const reportPath = path.join(REPORTS_DIR, reportFile); + + log('๐Ÿ“‹ ๆ”ถๅˆฐๆŒ‡ไปค: ' + orderFile); + + try { + const order = JSON.parse(fs.readFileSync(orderPath, 'utf-8')); + const cmd = order.cmd || order.command; + const server = order.server || order.target || 'ๆœฌๅœฐ'; + + log('๐ŸŽฏ ็›ฎๆ ‡: ' + server); + log('โšก ๆ‰ง่กŒ: ' + (cmd || '').slice(0, 100)); + + let result; + if (server === 'ๆœฌๅœฐ' || !server || server === 'localhost') { + // ๆœฌๅœฐๆ‰ง่กŒ + result = run(cmd); + } else { + // SSHๅˆฐ็›ฎๆ ‡ๆœๅŠกๅ™จๆ‰ง่กŒ + const sshCmd = `ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 root@${server} "${cmd.replace(/"/g, '\\"')}"`; + result = run(sshCmd, { timeout: order.timeout || 30000 }); + } + + // 5. ๅ†™็ป“ๆžœๆŠฅๅ‘Š + const report = { + order: orderFile, + executed_at: new Date().toISOString(), + server: server, + command: cmd, + success: !result.startsWith('[ERROR]'), + output: result.slice(0, 50000), + }; + + if (!fs.existsSync(REPORTS_DIR)) { + fs.mkdirSync(REPORTS_DIR, { recursive: true }); + } + fs.writeFileSync(reportPath, JSON.stringify(report, null, 2)); + + log(report.success ? 'โœ… ๆ‰ง่กŒๆˆๅŠŸ' : 'โš ๏ธ ๆ‰ง่กŒๆœ‰ๅผ‚ๅธธ'); + log('๐Ÿ“ ๆŠฅๅ‘Šๅทฒๅ†™ๅ…ฅ: ops/reports/' + reportFile); + + // ๅˆ ้™คๆŒ‡ไปคๆ–‡ไปถ๏ผˆๅทฒๅค„็†๏ผ‰ + fs.unlinkSync(orderPath); + log('๐Ÿ—‘๏ธ ๆŒ‡ไปคๅทฒๆธ…้™ค'); + + } catch(err) { + log('โŒ ๅค„็†ๆŒ‡ไปคๆ—ถๅ‡บ้”™: ' + err.message); + const errReport = { + order: orderFile, + executed_at: new Date().toISOString(), + error: err.message, + success: false, + }; + if (!fs.existsSync(REPORTS_DIR)) fs.mkdirSync(REPORTS_DIR, { recursive: true }); + fs.writeFileSync(reportPath, JSON.stringify(errReport, null, 2)); + } + + console.log(''); + } + + // 6. ๆŽจๅ›žไป“ๅบ“ + log('๐Ÿ“ค ๅ›žไผ ็ป“ๆžœ...'); + run('git add ops/ && git commit -m "[ๅบงๆœบ] ๆŒ‡ไปคๆ‰ง่กŒๆŠฅๅ‘Š ' + new Date().toISOString().slice(0, 10) + '"'); + const pushResult = run('git push'); + log(pushResult.includes('Everything up-to-date') ? 'โœ… ็ป“ๆžœๅทฒๅŒๆญฅ' : 'โœ… ๅทฒๆŽจ้€'); + + console.log(''); + console.log(' โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—'); + console.log(' โ•‘ ๐Ÿ”” ้€š่ฏ็ป“ๆŸ ยท ๅบงๆœบๅทฒๆŒ‚ๆ–ญ โ•‘'); + console.log(' โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•'); + console.log(''); +} + +main().catch(err => { + console.error('โŒ ๅบงๆœบๅ‡บ้”™:', err.message); + process.exit(1); +});