为何关闭SSH连接后pm2 logs进程仍持续运行?
问题描述
我用这段bash脚本通过SSH查看服务器上的pm2日志:
ssh user@hostname source ./activate-node-env.sh && pm2 logs my-app
脚本运行正常,日志会像tail -f一样持续输出,我按Ctrl+C退出。但最近发现服务器上残留了大量pm2 logs进程:
ps ax | grep node 1509 ? Ssl 8:18 node /root/.nvm/versions/node/v14.16.0/bin/pm2 logs my-app --lines 20 4133 ? Ssl 0:34 node /root/.nvm/versions/node/v14.16.0/bin/pm2 logs my-app --lines 20 5369 ? Ssl 8:15 node /root/.nvm/versions/node/v14.16.0/bin/pm2 logs my-app --lines 20 7466 ? Ssl 8:21 node /root/.nvm/versions/node/v14.16.0/bin/pm2 logs my-app --lines 20 8408 ? Ssl 19:37 node /root/.nvm/versions/node/v14.16.0/bin/pm2 logs my-app --lines 20
按Ctrl+C退出SSH会话时,pm2 logs进程并未终止,请问原因是什么?如何确保退出时进程被清理?
原因分析
核心问题出在命令执行逻辑和信号传递上:
- 原命令的写法会让本地shell解析
&&,实际是先通过SSH执行远程的source ./activate-node-env.sh,然后在本地执行pm2 logs my-app——这显然不符合你的预期,若实际是远程执行pm2 logs,则是因为命令拆分导致信号无法正确传递。 - 即便命令在远程执行,当按Ctrl+C时,SIGINT信号可能没传递给
pm2 logs进程:如果远程进程被放入后台进程组,或者SSH会话断开时未触发SIGHUP信号,进程会成为孤儿进程继续运行。
解决方法
1. 修正SSH命令的执行逻辑
将所有命令用引号包裹,确保在远程shell的同一个会话中执行:
ssh user@hostname 'source ./activate-node-env.sh && pm2 logs my-app'
这样Ctrl+C发送的SIGINT信号会直接传递给远程的pm2 logs进程,触发终止。
2. 强制分配伪终端确保信号传递
如果修正命令后仍有残留,给SSH加上-t参数,强制分配伪终端,让远程进程作为前台进程组接收信号:
ssh -t user@hostname 'source ./activate-node-env.sh && pm2 logs my-app'
-t参数会保证SSH会话断开时,前台进程收到SIGHUP信号并终止。
3. 清理已存在的残留进程
对于服务器上已有的pm2 logs残留进程,可批量终止:
ssh user@hostname 'pkill -f "pm2 logs my-app"'
内容的提问来源于stack exchange,提问作者bennlich
相关产品推荐
相关产品推荐

