如何终止Bash脚本中的两个后台进程?求并行执行替代方案
解决Ctrl+C终止后台进程的问题
你原来的trap命令失效的原因是,kill -- -$$尝试终止当前shell的进程组,但后台启动的script1.py和script2.py可能不在这个进程组内,导致无法被捕获。更可靠的方式是记录每个后台进程的PID,在中断信号触发时直接终止这些PID:
# 启动两个脚本并保存各自的PID python3 script1.py & PID1=$! python3 script2.py & PID2=$! # 定义清理函数,负责终止进程并退出 cleanup() { echo "正在终止脚本进程..." # 尝试终止两个进程,忽略不存在进程的错误 kill $PID1 $PID2 2>/dev/null # 等待进程完全退出,避免僵尸进程 wait $PID1 $PID2 2>/dev/null # 清除陷阱并退出shell trap - SIGINT SIGTERM EXIT exit 0 } # 设置陷阱,捕获Ctrl+C(SIGINT)、终止信号(SIGTERM)和退出事件 trap cleanup SIGINT SIGTERM EXIT # 等待所有后台进程自然结束(如果没收到中断信号) wait
无需后台运行的脚本并行执行方案
除了后台运行&的方式,还有几种更可控的并行执行方案:
- 使用xargs -P:借助
xargs的并行参数直接启动多个进程,按下Ctrl+C会自动终止所有子进程:
echo -e "script1.py\nscript2.py" | xargs -P 2 -I {} python3 {}
-P 2指定同时运行2个进程,-I {}用文件名替换占位符。
- 使用parallel命令:如果系统安装了
parallel(多数Linux发行版可通过包管理器安装),语法更简洁:
parallel python3 ::: script1.py script2.py
默认按CPU核心数并行,也可以用-j 2指定并行数量,该工具会自动处理进程的终止和退出。
- 使用shell函数+子shell并行:把脚本执行逻辑放在函数里,用子shell同时启动,这种方式不需要额外工具:
run_script() { python3 "$1" } # 同时启动两个子shell执行函数 run_script script1.py & run_script script2.py wait
这种方式本质还是后台运行,但封装后更清晰,同样可以配合前面的trap方案实现Ctrl+C终止。
内容的提问来源于stack exchange,提问作者lbsmart
相关产品推荐
相关产品推荐

