如何用Paramiko启动需交互输入的远程后台长期运行程序?
解决Paramiko启动需交互式输入的后台长期运行程序问题
方案1:用Shell脚本封装交互与后台逻辑
把程序的启动、输入传递和后台化逻辑封装到Shell脚本中,通过Paramiko执行脚本,避免在Python代码中处理复杂的终端交互,同时确保进程脱离会话存活。
示例脚本start_program.sh:
#!/bin/bash # 用nohup让程序忽略挂断信号,通过here-document传递所有输入 nohup MyCommand << EOF MyData # 若有多个输入,每行填写一个内容 EOF
Paramiko执行代码:
# 上传脚本(若脚本已在远程服务器可跳过此步) sftp = ssh.open_sftp() sftp.put('start_program.sh', '/path/to/start_program.sh') sftp.close() # 赋予执行权限并运行脚本 ssh.exec_command('chmod +x /path/to/start_program.sh && /path/to/start_program.sh') ssh.close()
方案2:在同一个PTY会话内完成所有操作
多次调用exec_command会创建独立的SSH通道,后续命令无法作用于之前的进程。需在同一个PTY通道内完成输入发送、进程挂起、后台化和脱离会话操作:
修改后的Python代码:
stdin, stdout, stderr = ssh.exec_command('MyCommand', get_pty=True) # 发送交互输入,每个输入后加换行符 stdin.write('MyData\r') stdin.flush() # 发送Ctrl+Z挂起进程 stdin.write('\x1A') stdin.flush() # 在同一个会话内执行后台化与脱离会话命令 stdin.write('bg\r') stdin.write('disown -h\r') # -h让进程忽略HUP信号 stdin.flush() # 关闭输入流,告知远程shell输入结束 stdin.close() ssh.close()
方案3:使用screen/tmux(持久化会话方案)
如果需要后续重新连接查看程序状态,用screen或tmux创建持久化后台会话更可靠:
# 用screen创建后台会话并执行带输入的命令 cmd = 'screen -dmS my_session bash -c "MyCommand << EOF\nMyData\nEOF"' stdin, stdout, stderr = ssh.exec_command(cmd) stdin.close() ssh.close()
后续可通过screen -r my_session重新连接到会话查看程序状态,即使SSH断开,会话仍会保留。
原代码失效原因
两次exec_command调用创建了独立的SSH通道,第二个通道中的bg; disown无法影响第一个通道内的MyCommand进程,当SSH连接关闭时,第一个通道的进程会收到挂断信号(HUP)并终止。
内容的提问来源于stack exchange,提问作者Alph0r
相关产品推荐
相关产品推荐

