function keepAlive() { // ============================================================ // 🛑 新增:维护模式检测 // 如果目录下存在 stop.txt,直接跳过后续所有检查 if (fs.existsSync(STOP_FILE)) { // 为了防止日志刷屏,这里可以选择不打印,或者每次跳过时打印 // 这里设置为每次周期都记录一下,方便确认状态 log("🛑 Maintenance Mode Active (stop.txt found). Skipping checks."); return; } // ============================================================
// 1. 核心检测:查端口 (保持原有逻辑) exec(`sockstat -4 -l -P tcp | grep ${TARGET_PORT}`, (err, stdout) => { if (stdout && stdout.includes(TARGET_PORT)) { log(`Port ${TARGET_PORT} is UP. Service is healthy.`); } else { log(`Port ${TARGET_PORT} is DOWN. Initiating restart sequence...`); // 2. 清理旧进程 log(`Cleaning up any stuck '${PROCESS_NAME}' processes...`); exec(`pkill -f "${PROCESS_NAME}"`, () => { // 3. 启动新进程 log(`Starting new instance...`); // 注意:gpt-load 自身的日志依然写到它自己的 gpt-load.log 里 exec(`cd ${WORK_DIR} && ${CMD} > gpt-load.log 2>&1 &`, (startErr) => { if (startErr) log(`Start failed: ${startErr}`); else log(`Start command sent successfully.`); }); }); } }); }
// 启动时立即检查 log("Keeper Service Started."); keepAlive();
// 每 60 秒检查一次 setInterval(keepAlive, 60 * 1000);
// 修改:Web 访问时也能看到状态 app.get("/", (req, res) => { if (fs.existsSync(STOP_FILE)) { res.send("🛑 Service is in MAINTENANCE MODE (stop.txt detected)."); } else { res.send(`✅ Keeper is watching port ${TARGET_PORT}`); } });
app.listen(port, () => log(`Keeper listening on port ${port}`));
function log(message) { const time = new Date().toLocaleString(); const logMsg = `[${time}] ${message}\n`; try { fs.appendFileSync(LOG_FILE, logMsg); } catch (e) {} console.log(logMsg.trim()); }
function keepAlive() { if (fs.existsSync(STOP_FILE)) { log("🛑 Maintenance Mode Active (stop.txt found). Skipping checks."); return; }
exec(`sockstat -4 -l -P tcp | grep ${TARGET_PORT}`, (err, stdout) => { if (stdout && stdout.includes(TARGET_PORT)) { log(`Port ${TARGET_PORT} is UP. Service is healthy.`); } else { log(`Port ${TARGET_PORT} is DOWN. Initiating restart sequence...`); log(`Cleaning up any stuck '${PROCESS_NAME}' processes...`); exec(`pkill -f "${PROCESS_NAME}"`, () => { log(`Starting new instance...`); exec(`cd ${WORK_DIR} && ${CMD} > gpt-load.log 2>&1 &`, (startErr) => { if (startErr) log(`Start failed: ${startErr}`); else log(`Start command sent successfully.`); }); }); } }); }
// 启动保活逻辑 log("Keeper Service Started."); keepAlive(); setInterval(keepAlive, 60 * 1000);
// ================== 路由配置 ==================
// 1. 特殊页面:查看保活状态 (访问 /keeper-status) app.get("/keeper-status", (req, res) => { if (fs.existsSync(STOP_FILE)) { res.send("🛑 Service is in MAINTENANCE MODE (stop.txt detected)."); } else { res.send(`✅ Keeper is watching port ${TARGET_PORT}. Service acts as Reverse Proxy.`); } });
// 2. 反向代理:把所有其他请求转发给 gpt-load (30345) // 这样你直接访问域名,就等于访问了 30345,但不用担心代理节点屏蔽端口 app.use("/", createProxyMiddleware({ target: `http://127.0.0.1:${TARGET_PORT}`, changeOrigin: true, ws: true, // 支持 WebSocket (如果 gpt-load 需要) onError: (err, req, res) => { res.status(502).send(` <h1>502 Bad Gateway</h1> <p>Keeper is running, but gpt-load-server (Port ${TARGET_PORT}) seems down or starting.</p> <p>Check <a href="/keeper-status">/keeper-status</a> for details.</p> `); } }));
app.listen(port, () => log(`Keeper & Proxy listening on port ${port}`));
3.启动程序(要以绝对路径启动,不然……app.js没办法重启gpt-load-server)
启动gpt-load-server
1 2
cd /home/username/gpt-load nohup ./gpt-load-server > gpt-load.log 2>&1 &