如何通过Python SSH在远程主机后台启动Python脚本且不阻塞本地进程
解决SSH启动远程后台脚本导致本地阻塞的问题
方案1:给SSH添加-f参数,让会话后台运行
SSH的-f参数会在执行远程命令前将SSH进程转入后台,本地脚本无需等待远程命令完成即可继续执行。配合nohup和输出重定向,确保远程脚本彻底脱离终端:
def call_command(target, command): # 添加-f参数让SSH后台执行 command = f'ssh -f -o ProxyJump={CONFIG["proxy"]}:{CONFIG["port"]} {target} "{command}"' try: subprocess.call(command, shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: raise Exception(f"Failed to execute command on {target}: {e.output}") call_command("server_1", "cd ~/Script/ && nohup python3 Client.py > /dev/null 2>&1 & disown")
方案2:修改远程命令,确保bash进程执行后立即退出
问题根源是远程启动的bash -c进程未及时退出,导致SSH会话持续阻塞。可以在远程命令末尾添加exit强制bash退出,同时彻底重定向所有输出:
call_command("server_1", "cd ~/Script/ && nohup python3 Client.py > /dev/null 2>&1 & disown; exit")
或者将远程命令放入子shell后台执行,完全隔离与SSH会话的关联:
call_command("server_1", "(cd ~/Script/ && nohup python3 Client.py > /dev/null 2>&1 &) > /dev/null 2>&1")
方案3:用subprocess.Popen替代subprocess.call,不等待命令完成
如果不需要确认SSH命令的执行结果,直接使用subprocess.Popen启动进程,本地脚本会立即继续后续操作:
def call_command(target, command): command = f'ssh -o ProxyJump={CONFIG["proxy"]}:{CONFIG["port"]} {target} "{command}"' try: # 使用Popen不阻塞等待进程结束 subprocess.Popen(command, shell=True, stderr=subprocess.STDOUT) except Exception as e: raise Exception(f"Failed to execute command on {target}: {str(e)}") call_command("server_1", "cd ~/Script/ && nohup python3 Client.py > /dev/null 2>&1 & disown")
验证方式
执行脚本后登录远程服务器,运行ps aux | grep python3,应仅看到python3 Client.py的进程,无残留的bash -c进程。
内容的提问来源于stack exchange,提问作者Finn Eggers
相关产品推荐
相关产品推荐

