Flask Python应用:如何执行远程脚本不等待POST响应?
解决Flask中远程执行无限循环脚本导致请求阻塞的问题
我明白你的困扰——当你在Flask的POST路由里执行那个带无限循环的远程脚本时,Python会一直等着ssh命令结束,但脚本永远不会终止,导致请求一直挂着。要解决这个问题,核心是让远程脚本在后台独立运行,同时让本地的Python进程不用等待命令完成。
下面是具体的实现方案:
关键思路
要达成两个核心目标:
- 让ssh命令立刻返回,不等待远程脚本执行完毕
- 确保远程脚本在ssh会话断开后依然能持续运行(避免ssh退出时杀掉脚本进程)
具体实现步骤
1. 用subprocess.Popen替代os.system
os.system会一直阻塞到命令执行完成,而subprocess.Popen是异步启动进程,调用后立刻返回,不会等待结果。这是解决本地请求阻塞的关键。
2. 让远程脚本脱离终端后台运行
在远程的ssh命令里,我们需要结合nohup和后台符号&,同时重定向输出,确保脚本不受ssh会话影响:
nohup:让脚本忽略挂起信号(SIGHUP),即使ssh连接关闭,脚本依然继续运行> /dev/null 2>&1:把标准输出和错误输出重定向到空设备,避免占用远程机器的终端资源&:让远程命令在后台执行,这样ssh会立刻完成并返回
3. Flask路由示例代码
from flask import Flask, request import subprocess app = Flask(__name__) @app.route('/launch-script', methods=['POST']) def launch_remote_script(): # 构造远程执行的命令 remote_cmd = "nohup /home/pi/script.sh > /dev/null 2>&1 &" # 用Popen异步执行ssh命令 subprocess.Popen( ["ssh", "pizerow", remote_cmd], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # 立刻返回响应,不用等待脚本执行 return "远程脚本启动请求已提交", 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
重要注意事项
- 配置SSH免密登录:如果你的Flask运行用户还不能免密登录到pizerow,执行ssh命令时会弹出密码输入提示,导致请求再次阻塞。你需要生成SSH密钥对,并把公钥添加到pizerow的
~/.ssh/authorized_keys文件中。 - 给脚本加可执行权限:确保远程的
script.sh有执行权限,执行chmod +x /home/pi/script.sh。 - 可选:记录脚本日志:如果需要排查脚本运行情况,可以把输出重定向到日志文件,比如把命令改成
nohup /home/pi/script.sh > /home/pi/script_run.log 2>&1 &,之后可以通过ssh查看这个日志文件。
为什么不用其他方法?
os.system:本质上会等待命令执行完成,无法异步处理。subprocess.run/subprocess.call:同样是阻塞式调用,会一直等命令结束。- 仅加
&而不用nohup:ssh会话关闭后,远程脚本会收到SIGHUP信号被终止,无法持续运行。
内容的提问来源于stack exchange,提问作者Bart
相关产品推荐
相关产品推荐

