如何解决Paramiko exec_command启动远程服务器后通道销毁致进程终止问题
嘿,这个问题我太熟了!你碰到的情况是因为Paramiko的Channel对象和远程进程的终端会话绑定在一起了——一旦Channel被销毁,远程终端会关闭,进程就收到SIGHUP信号直接终止了。给你几个实用的解决思路:
方法1:用
nohup让进程脱离终端控制 这是最直接的办法,nohup可以让进程忽略SIGHUP信号,即使终端关闭也能继续运行。把你的启动命令改成这样:
nohup /home/server/your_server_program > /dev/null 2>&1 &
> /dev/null 2>&1是把标准输出和错误输出都重定向到空设备,避免生成nohup.out日志文件- 末尾的
&让进程在后台运行
对应的Paramiko代码调整成:
ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect(hostname='10.0.0.1', username='username', password='pw') # 直接用exec_command执行带nohup的命令 stdin, stdout, stderr = ssh_client.exec_command('nohup /home/server/your_server_program > /dev/null 2>&1 &') # 不需要等待输出,直接关闭客户端(进程已经在后台跑了) ssh_client.close()
方法2:用
screen/tmux创建持久化会话 如果需要后续还能重新连接到进程的终端,用终端复用工具更合适。比如用screen:
screen -dmS server_session /home/server/your_server_program
-d表示后台启动screen会话-m强制创建新会话server_session是会话名称,方便后续用screen -r server_session重新连接
对应的Paramiko代码:
ssh_client.exec_command('screen -dmS server_session /home/server/your_server_program') ssh_client.close()
方法3:修改Paramiko Channel的终端配置
你也可以通过配置Channel,让它不发送SIGHUP信号,不过这个方法稳定性不如前两个。示例代码:
transport = ssh_client.get_transport() channel_server = transport.open_session() # 分配伪终端并启动shell channel_server.get_pty() channel_server.invoke_shell() # 发送启动命令并后台运行 channel_server.send('nohup /home/server/your_server_program > /dev/null 2>&1 &\n') # 退出shell,避免会话残留 channel_server.send('exit\n') channel_server.close() ssh_client.close()
最后记得验证一下:远程登录机器后用ps aux | grep your_server_program看看进程是否还在运行。
内容的提问来源于stack exchange,提问作者JohannesW
相关产品推荐
相关产品推荐

