pgrep能找到进程,为何pkill却无法终止该子进程?
问题原因分析
核心问题出在pkill -f的匹配规则上:当使用-f参数时,pkill会匹配整个进程的命令行字符串,而你执行pkill -f 30这个命令时,启动的shell进程本身的命令行里就包含"30"(命令就是pkill -f 30),所以pkill在杀死目标的sleep 30和对应的shell进程后,会误杀自己所在的shell进程,导致subprocess.check_output检测到命令被SIGTERM终止,抛出CalledProcessError。
具体过程拆解:
- 执行
run_instance()时,shell=True会启动一个bash进程,这个bash又启动了sleep 30进程,所以pgrep -f 30会找到这两个进程(输出里的17483和17484)。 - 调用
kill_instance()时,pkill -f 30会遍历所有进程的命令行,匹配包含"30"的进程:包括之前的bash、sleep,还有当前执行pkill -f 30的bash进程。 pkill会向这些进程发送SIGTERM,其中当前执行pkill的bash进程被杀死后,subprocess.check_output因为设置了check=True,会检查到命令异常退出(被信号终止),于是抛出错误。
解决方法:
- 精准匹配命令:把
pkill -f 30改成pkill -f "sleep 30",缩小匹配范围,避免命中自身进程。 - 排除自身PID:用
pgrep筛选出目标PID后,排除当前shell的PID再执行杀死操作,比如:pgrep -f 30 | grep -v $$ | xargs kill - 直接管理进程PID:在启动进程时保存PID,不用
pgrep/pkill,比如修改run_instance返回PID,然后用subprocess.call(["kill", pid])来终止。
内容的提问来源于stack exchange,提问作者AlwaysLearning
相关产品推荐
相关产品推荐

