You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SSH会话在运行后台启动脚本时持续保持连接的问题排查

解决SSH远程执行启动后台进程后会话不退出的问题

这个问题我之前也碰到过,核心原因不是sys.exit()的问题——你的start.py已经正常退出(退出码0),问题出在SSH会话会一直保持到所有关联的文件描述符(标准输入、输出、错误)都被关闭,而你启动的后台进程可能还在继承start.py的这些流,导致SSH不会断开。

先搞清楚两种执行方式的差异

  • 交互式SSH登录后运行脚本:此时脚本的标准流绑定到终端,脚本退出后,后台进程虽然可能还在运行,但终端属于你的交互式会话,你可以主动退出SSH(后台进程如果做了脱离处理就不会被终止)。
  • 直接远程执行命令:SSH会话是和这个命令绑定的,只要该命令(包括它启动的子进程)还持有SSH会话的标准流,SSH就不会断开,直到所有这些流都被关闭。

解决方案分两种情况:

1. 修改start.py,让后台进程彻底脱离关联

如果你的start.py是用subprocess启动后台进程,一定要确保:

  • 重定向后台进程的标准输入、输出、错误到/dev/null或日志文件,避免继承父进程的流
  • 让后台进程脱离当前会话组,切断和SSH会话的绑定

举个Python代码示例:

import subprocess

# 启动后台进程的正确姿势
def start_background_process():
    subprocess.Popen(
        ["your_background_command_here"],
        # 重定向所有标准流到/dev/null,避免占用SSH的流
        stdin=subprocess.DEVNULL,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
        # 启动新会话,让进程脱离当前SSH会话的控制组
        start_new_session=True,
        shell=False  # 尽量不用shell=True,减少安全风险
    )

# 执行启动逻辑后,直接退出即可,不需要额外的sys.exit()(脚本执行完自然退出)
start_background_process()

这样修改后,start.py退出时,后台进程已经完全脱离了SSH的文件描述符,SSH会话会立即断开。

2. 不修改start.py,在SSH命令层处理

如果暂时没法改脚本,可以在远程命令里用nohup+重定向+后台执行的组合:

ssh -o StrictHostKeyChecking=no -i /tmp/tmpqcz5l5il user@remote_host -p 22 "nohup python start.py --config_file /data/workload.pg > /dev/null 2>&1 &"

解释下各个部分:

  • nohup:让进程忽略HUP信号(避免SSH断开时终止后台进程),同时默认会把输出写到nohup.out
  • > /dev/null 2>&1:把标准输出和错误都重定向到/dev/null,彻底切断和SSH会话的流关联
  • 最后的&:让命令在远程主机的后台执行,SSH会在启动命令后立即断开连接

总结

不需要给start.py加特殊的sys.exit()信号,问题的核心是后台进程没有和SSH会话的文件描述彻底脱离。优先修改脚本里的后台进程启动逻辑,这样最可靠;如果改不了脚本,用SSH命令层的重定向+nohup+&组合也能解决。

内容的提问来源于stack exchange,提问作者Joel Doerr

火山引擎 最新活动