0.前提,部署到make run那一步,还未进行pm2保活
1.开始,参考下面讲的passenger保活进程,
2.app.js代码(旧):
总结
const express = require("express");
const path = require("path");
const exec = require("child_process").exec;
const app = express();
const port = port;//前提里面设置的端口
const user = ""; // Serv00 用户名
const pName = "gpt-load-server"; // 我保活了这个
// 完整路径到二进制程序(注意:不需要 go run,直接运行编译后的文件)
//const Process = `/home/${user}/gpt-load/${pName}`;//这里我手动kill了gpt-load-server之后没有触发app.js里面重启gpt-load-server的逻辑
const Process = "gpt-load/gpt-load-server"; // 匹配路径中包含这一段
// 日志文件路径
const LogFile = `/home/${user}/gpt-load/gpt-load.log`;
function keepWebAlive() {
const currentDate = new Date();
const formattedDate = currentDate.toLocaleDateString();
const formattedTime = currentDate.toLocaleTimeString();
// 精确查找该进程是否在运行
exec(`pgrep -f "${Process}"`, (err, stdout) => {
if (stdout.trim()) {
console.log(`${formattedDate}, ${formattedTime}: ${pName} is Running (PID: ${stdout.trim()})`);
} else {
console.log(`${formattedDate}, ${formattedTime}: ${pName} is NOT Running, attempting to restart...`);
// 使用 nohup 启动,输出日志
exec(`cd /home/${user}/gpt-load && nohup ${Process} > ${LogFile} 2>&1 &`, (err) => {
if (err) {
console.error(`${formattedDate}, ${formattedTime}: Restart failed: ${err}`);
} else {
console.log(`${formattedDate}, ${formattedTime}: Restarted ${pName} successfully!`);
}
});
}
});
}
// 初始执行一次
keepWebAlive();
// 每 10 秒检查一次
setInterval(keepWebAlive, 10 * 1000);
app.use(express.static(path.join(__dirname, 'static')));
app.listen(port, () => {
console.log(`Web server is listening on port ${port}!`);
});
app.js新
const express = require("express");
const path = require("path");
const { exec } = require("child_process");
const fs = require("fs");
const app = express();
// ========== 配置部分 ==========
const PORT = ; // 替换为你的实际端口
const USER = ""; // Serv00用户名
const PROCESS_NAME = "gpt-load-server";
const PROCESS_PATH = `/home/${USER}/gpt-load/${PROCESS_NAME}`; // 绝对路径
const LOG_PATH = `/home/${USER}/gpt-load/gpt-load.log`;
// ========== 进程锁防止重复启动 ==========
let isRestarting = false;
let restartAttempts = 0;
const MAX_RETRIES = 3;
// ========== 优化后的进程守护函数 ==========
async function keepProcessAlive() {
if (isRestarting) return;
const timestamp = new Date().toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
}).replace(/\//g, '-');
try {
// 更可靠的进程检测方式
const isRunning = await new Promise((resolve) => {
exec(`ps aux | grep "[${PROCESS_NAME[0]}]${PROCESS_NAME.slice(1)}"`, (err, stdout) => {
resolve(!!stdout.trim());
});
});
if (isRunning) {
console.log(`[${timestamp}] ${PROCESS_NAME} is running`);
restartAttempts = 0; // 重置重试计数器
return;
}
// 进程崩溃处理
if (restartAttempts >= MAX_RETRIES) {
console.error(`[${timestamp}] Maximum restart attempts reached. Stopping...`);
return;
}
isRestarting = true;
restartAttempts++;
console.log(`[${timestamp}] Attempting to restart ${PROCESS_NAME} (attempt ${restartAttempts}/${MAX_RETRIES})`);
// 确保日志目录存在
if (!fs.existsSync(path.dirname(LOG_PATH))) {
fs.mkdirSync(path.dirname(LOG_PATH), { recursive: true });
}
// 使用绝对路径启动进程
exec(`cd /home/${USER}/gpt-load && nohup ${PROCESS_PATH} >> ${LOG_PATH} 2>&1 &`,
(err) => {
isRestarting = false;
if (err) {
console.error(`[${timestamp}] Restart failed: ${err.message}`);
} else {
console.log(`[${timestamp}] ${PROCESS_NAME} restarted successfully`);
}
});
} catch (error) {
console.error(`[${timestamp}] Monitoring error: ${error.message}`);
isRestarting = false;
}
}
// ========== 服务器配置 ==========
app.use(express.static(path.join(__dirname, 'static')));
// 健康检查接口
app.get('/health', (req, res) => {
res.status(200).json({
status: 'healthy',
process: PROCESS_NAME,
lastRestartAttempt: restartAttempts
});
});
// ========== 启动服务 ==========
app.listen(PORT, () => {
console.log(`[${new Date().toLocaleString()}] Web server listening on port ${PORT}`);
// 初始检查 + 每30秒检测一次(降低频率)
keepProcessAlive();
setInterval(keepProcessAlive, 30 * 1000);
});
3.启动程序(要以绝对路径启动,不然…app.js没办法重启gpt-load-server)
启动gpt-load-server
cd /home/username/gpt-load
nohup ./gpt-load-server > gpt-load.log 2>&1 &
启动app.js
cd /home/username/domains/username.serv00.net/public_nodejs
nohup node app.js > app.log 2>&1 &
4.验证
手动杀掉gpt-load-server
pkill -f gpt-load-server
在public_nodejs目录
[id@s9]:<~/domains/id.serv00.net/public_nodejs>$ pkill -f gpt-load-server
[id@s9]:<~/domains/id.serv00.net/public_nodejs>$ tail -f app.log
查看app.log
tail -f app.log
显示下面则成功:
5.serv00母鸡重启的话,需要重启app.js
写一个start.sh脚本
#!/bin/bash
cd /home/username/gpt-load
nohup ./gpt-load-server > gpt-load.log 2>&1 &
cd /home/username/domains/username.serv00.net/public_nodejs
nohup node app.js > app.log 2>&1 &
赋权并运行
chmod +x start.sh
./start.sh
之后登陆则运行
./start.sh
即可
PS:最简单的还是pm2保活,官方也没看到说禁止,说的是最好用passenger,访问我用的域名+端口,可以自己试试passenger反代去掉端口


