Webhook触发Node.js部署时PM2 Reload中断,如何保障脚本完整执行?
问题解决:Webhook触发时PM2 Reload未完成的修复方案
核心原因
手动执行脚本正常,但Webhook触发时PM2 reload只完成部分,本质是脚本进程的生命周期管理不当,加上PM2 reload的异步特性未被正确等待,导致脚本提前终止,PM2的重载流程被打断。
具体修复步骤
1. 让脚本完整捕获PM2输出并稳定后台运行
当前Webhook的stdio: 'ignore'会忽略PM2的所有输出,既无法排查错误,也可能导致PM2因缺少会话上下文提前终止。修改Webhook代码,将PM2输出重定向到部署日志:
const fs = require('fs'); const { spawn } = require('child_process'); app.post('/git-push', async (req, res) => { let start = new Date().toISOString(); console.log(`🚢 Server deployment started ${start}`) // 打开日志文件,以追加模式写入 const logStream = fs.openSync('./deploy.log', 'a'); const deployScript = spawn('bash', ['scripts/deploy.sh'], { cwd: process.cwd(), detached: true, // 重定向标准输出/错误到日志,忽略标准输入 stdio: ['ignore', logStream, logStream] }); deployScript.unref(); res.status(200).json({message: `ok ${start}`}); })
2. 强制PM2等待实例就绪再完成重载
PM2默认重载逻辑不会等待实例完全启动就返回,导致脚本提前退出。在deploy.sh的PM2命令中添加等待参数,确保所有实例启动完成后脚本才继续:
#!/bin/bash LOG_FILE="deploy.log" echo '📦 Fetching changes from server' >> "$LOG_FILE" git pull >> "$LOG_FILE" 2>&1 echo '🛠️ Building project' >> "$LOG_FILE" npm run build >> "$LOG_FILE" 2>&1 echo '♻️️ Reloading server' >> "$LOG_FILE" # 添加--wait-ready等待实例发送ready信号,--listen-timeout设置超时时间(单位:毫秒) pm2 reload server --wait-ready --listen-timeout 30000 >> "$LOG_FILE" 2>&1
注意:你的Express应用需要添加
process.send('ready')触发PM2的就绪检测,比如在服务器启动完成后:app.listen(3000, () => { console.log('Server running on port 3000'); process.send('ready'); // 向PM2发送就绪信号 });
3. 避免脚本因非致命错误提前终止
原脚本的set -e会在任何命令返回非零值时立即退出,而PM2重载过程中如果某个实例重启较慢,可能临时返回非零码导致脚本中断。可以去掉set -e,改为单独处理关键命令的错误:
#!/bin/bash LOG_FILE="deploy.log" echo '📦 Fetching changes from server' >> "$LOG_FILE" if ! git pull >> "$LOG_FILE" 2>&1; then echo '❌ Git pull failed' >> "$LOG_FILE" exit 1 fi echo '🛠️ Building project' >> "$LOG_FILE" if ! npm run build >> "$LOG_FILE" 2>&1; then echo '❌ Build failed' >> "$LOG_FILE" exit 1 fi echo '♻️️ Reloading server' >> "$LOG_FILE" # 即使PM2返回非零,也让脚本执行完以保留完整日志 pm2 reload server --wait-ready --listen-timeout 30000 >> "$LOG_FILE" 2>&1 echo '🔄 Reload process completed' >> "$LOG_FILE"
4. 确保PM2命令的环境一致性
Webhook进程的环境变量可能和手动终端不同,导致PM2命令路径错误或配置加载异常。可以在deploy.sh中使用PM2的绝对路径(通过which pm2查询实际路径):
# 替换为你的PM2绝对路径 PM2_PATH="/usr/local/bin/pm2" $PM2_PATH reload server --wait-ready --listen-timeout 30000 >> "$LOG_FILE" 2>&1
验证方法
修改后触发Webhook,查看deploy.log末尾是否出现[PM2] All processes reloaded successfully,再执行pm2 list确认所有实例的uptime均为新的时间。
内容的提问来源于stack exchange,提问作者Alex Styl
相关产品推荐
相关产品推荐

