You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:27:06