如何让Python服务启动的Bash脚本在服务被杀死后仍能完整执行
问题根源
你当前使用的subprocess.call是阻塞式调用,启动的update.sh进程属于Python服务的子进程,默认归属到myproject.service对应的systemd控制组(cgroup)中。当执行systemctl stop myproject.service时,systemd会终止该控制组下的所有进程,因此更新脚本会和Python服务一起被杀死,无法执行后续逻辑。
解决方案
方法1:修改Python调用逻辑(推荐)
调整subprocess启动参数,让更新脚本启动为独立会话的进程,脱离原服务的进程组/控制组,修改后的Python代码如下:
import subprocess # 不阻塞等待脚本执行完成,启动为独立会话进程 subprocess.Popen( ["setsid", "sudo", "/home/pi/myproject/update.sh"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True )
参数说明:
start_new_session=True:让子进程成为新会话的首进程,不再属于原Python服务的会话和进程组setsid:进一步确保子进程脱离当前终端关联,PID归属到systemd(PPID=1)- 输出重定向到
DEVNULL避免进程因为输出缓冲区满被挂起
方法2:修改Bash脚本调用方式(无需改Python代码可选)
如果不方便调整Python代码,可以直接修改调用的命令,用nohup加后台运行的方式让脚本脱离父进程:
import subprocess subprocess.Popen("sudo nohup /home/pi/myproject/update.sh > /dev/null 2>&1 &", shell=True)
修改后更新脚本会作为独立进程运行,即便原Python服务被停止,脚本也会完整执行拉取代码、重启服务的全流程。
内容的提问来源于stack exchange,提问作者user2351471
相关产品推荐
相关产品推荐

