Python subprocess执行含nohup的bash脚本时阻塞的原因及解决方法
Python subprocess执行含nohup的bash脚本时阻塞的原因及解决方法
嗨,这个问题我之前也碰到过,给你理清楚原因和解决办法哈!
为什么会阻塞10秒?
你用sp.run执行bash脚本时,虽然脚本里把sleep 10放到了后台,但关键问题出在输出重定向和capture_output=True的组合:
nohup命令默认会把后台进程的标准输出、标准错误重定向到nohup.out,但如果当前shell(也就是subprocess启动的bash进程)的标准输出/错误不是终端(这里是subprocess创建的管道,因为你开了capture_output=True),nohup会保留对这些管道的引用。- 后台的
sleep 10进程会一直持有这些管道,直到它结束才会释放。而sp.run会一直等待这些管道的读端收到EOF,所以就会阻塞到sleep进程跑完10秒才结束。
怎么解决?
有几种简单的办法,按需选就行:
方法1:在nohup里明确重定向输出
修改你的bash脚本,把sleep的输出直接丢到/dev/null,避免占用subprocess的管道:
nohup sleep 10 >/dev/null 2>&1 &
这样后台进程的输出不会关联到bash进程的stdout/stderr,bash脚本执行完就立刻退出,sp.run自然也就不会阻塞了。
方法2:关闭subprocess的输出捕获
如果不需要捕获bash脚本的输出,直接把subprocess的stdout和stderr都重定向到DEVNULL,替代capture_output=True:
cp = sp.run('bash test.sh', shell=True, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
这样subprocess不会等待输出管道的EOF,bash进程退出后就会立刻返回。
方法3:结合使用(更稳妥)
如果需要保留部分输出捕获,同时避免阻塞,也可以在脚本里重定向nohup的输出,同时按需处理subprocess的输出。
备注:内容来源于stack exchange,提问作者link89
相关产品推荐
相关产品推荐

