GitHub Action执行结束后PM2启动的应用自动停止问题排查
问题描述
我编写了deploy.sh脚本,将其作为.github/deploy.yml工作流中的一个执行步骤。
以下是yaml文件中执行该shell脚本的配置片段:
- name: Execute script uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST_DNS }} username: ${{ secrets.USERNAME }} key: ${{ secrets.EC2_SSH_KEY }} script: | cd server/ chmod 755 deploy.sh ./deploy.sh
对应的shell脚本内容如下:
echo "Kill pm2" sudo pm2 kill echo "Install app dependencies" sudo rm -rf node_modules package-lock.json sudo npm run get echo "Start app with pm2" sudo pm2 start index.js -i max sudo pm2 list
在GitHub Action的日志中,可以清晰看到PM2已成功启动我的应用:
out: [PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 out: [PM2] PM2 Successfully daemonized out: [PM2] Starting /home/***/server/index.js in cluster_mode (0 instance) out: [PM2] Done. out: ┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ out: │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ out: ├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ out: │ 0 │ index │ default │ 1.0.1 │ cluster │ 4807 │ 0s │ 0 │ online │ 0% │ 35.1mb │ root │ disabled │ out: └─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ out: ┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ out: │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ out: ├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ out: │ 0 │ index │ default │ 1.0.1 │ cluster │ 4807 │ 0s │ 0 │ online │ 0% │ 52.2mb │ root │ disabled │ out: └─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ ============================================== ✅ Successfully executed commands to all host. ==============================================
但工作流执行完成后,我通过SSH登录服务器执行pm2 list命令,却看不到任何运行中的PM2进程。
问题原因
这是appleboy/ssh-action的默认行为导致的:该Action执行远程命令时,会在SSH会话结束后主动杀掉该会话启动的所有关联子进程,你在脚本里用sudo启动的PM2进程属于当前SSH会话的子进程,会话断开就会被直接清理,所以Action日志里能看到启动成功,等手动登上去的时候进程已经被杀掉了。
另外还有一个容易忽略的权限问题:如果你手动SSH登录用的是非root用户,直接执行pm2 list查看的是当前普通用户的PM2实例列表,而你脚本里用sudo启动的是root用户的PM2实例,就算进程没被杀,不加sudo执行pm2 list也看不到root启动的进程。
解决方法
- 给SSH Action加参数,禁用会话结束后杀关联子进程的行为,在
with配置块里加一行kill_ssh_agent: false即可。 - 固定PM2的运行用户,不要随意切换sudo:要么全程用同一个普通用户部署、启动PM2,所有命令都不加sudo;如果必须用root启动,手动登录查看的时候也要执行
sudo pm2 list才能看到对应进程。 - 更稳妥的做法是配置PM2持久化,第一次部署时执行
sudo pm2 startup生成开机自启配置,每次启动应用后执行sudo pm2 save保存进程列表,就算服务器重启PM2也会自动拉起应用,不会因为SSH会话断开丢失进程。
修改后的Workflow配置片段参考:
- name: Execute script uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST_DNS }} username: ${{ secrets.USERNAME }} key: ${{ secrets.EC2_SSH_KEY }} kill_ssh_agent: false # 新增该行禁用会话结束杀子进程逻辑 script: | cd server/ chmod 755 deploy.sh ./deploy.sh
配置持久化后的deploy.sh参考:
echo "Kill pm2" sudo pm2 kill echo "Install app dependencies" sudo rm -rf node_modules package-lock.json sudo npm run get echo "Start app with pm2" sudo pm2 start index.js -i max sudo pm2 save # 新增该行保存当前PM2进程列表 sudo pm2 list
内容的提问来源于stack exchange,提问作者hkisthebest
相关产品推荐
相关产品推荐

