如何在调用的Bash脚本中断时终止Python后台进程
问题:Ctrl+C无法终止后台运行的Python进程
相关脚本
Python脚本(test.py)
try: import sys import time while True: print("test: {}".format(sys.argv[1])) time.sleep(1) except KeyboardInterrupt: print("process terminated!")
注:单独运行该脚本时,按下Ctrl+C可正常终止程序。
Bash启动脚本
#!/bin/bash export PYENV="/home/AA/.venv/env1/bin/python3" cd /home/AA/test sudo $PYENV test.py 1 & sudo $PYENV test.py 2 & wait
问题:执行上述Bash脚本后,按下Ctrl+C无法终止后台运行的Python进程。
解决方法
方法1:移除sudo(若权限允许)
sudo会让Python进程脱离当前Shell的进程组,导致Ctrl+C发送的SIGINT信号无法传递给它们。如果无需sudo权限即可运行脚本,直接去掉sudo即可:
#!/bin/bash export PYENV="/home/AA/.venv/env1/bin/python3" cd /home/AA/test $PYENV test.py 1 & $PYENV test.py 2 & wait
此时按下Ctrl+C,Shell会将SIGINT信号发送给所有后台子进程,Python脚本就能捕获信号并终止。
方法2:用trap捕获SIGINT并手动终止进程
如果必须使用sudo,可在Bash脚本中记录后台进程的PID,通过trap捕获SIGINT信号后手动杀死这些进程:
#!/bin/bash export PYENV="/home/AA/.venv/env1/bin/python3" cd /home/AA/test # 记录后台进程PID pids=() sudo $PYENV test.py 1 & pids+=($!) sudo $PYENV test.py 2 & pids+=($!) # 捕获Ctrl+C信号,终止所有记录的进程 trap 'echo "Stopping all processes..."; sudo kill "${pids[@]}"; exit 0' SIGINT wait
按下Ctrl+C时,Bash会触发trap中的命令,用kill终止所有后台Python进程。
方法3:将进程放入同一进程组
将后台进程纳入当前Shell的进程组,确保SIGINT信号能传递到所有进程:
#!/bin/bash export PYENV="/home/AA/.venv/env1/bin/python3" cd /home/AA/test # 启用作业控制,将进程放入前台进程组 set -m sudo $PYENV test.py 1 & sudo $PYENV test.py 2 & set +m # 捕获SIGINT并发送到当前进程组所有进程 trap 'kill -INT 0' SIGINT wait
kill -INT 0会向当前进程组的所有进程发送SIGINT信号,包含后台的Python进程。
内容的提问来源于stack exchange,提问作者A.Yang
相关产品推荐
相关产品推荐

