我有一个bash脚本,在循环中做一些并行处理。 我不希望并行进程刺激CPU,所以我使用睡眠命令。 这是一个简化的版本。
(虽然真的,做睡觉99999;完成)
所以我从bash提示符执行上面的行,得到如下所示: [1] 12345
其中[1]
是作业编号, 12345
是while循环的进程ID(pid)。 我kill 12345
,得到:
[1] +终止(虽然真的;做 睡99999; 完成)
看起来整个脚本被终止了。 但是,我做了一个ps aux|grep sleep
并发现睡眠命令仍然强大,但与自己的PID! 我可以杀死sleep
,一切似乎都很好。 但是,如果我要先杀死睡眠,则while循环会启动一个新的sleep
pid。 这对我来说是一个惊喜,因为睡眠不是平行于while循环。 循环本身是一个单一的执行path。
所以我有两个问题:
PID
因为它是一个进程正在运行,只是在等待。 尝试which sleep
,看看它在哪里。 ps -uf
来查看系统上的进程树。 从那里你可以确定睡眠的shell(运行循环的那个)的PPID
(父PID)是什么。 你是否尝试过kill %1
,其中1
是你在后台启动命令后得到的数字?
我启动后立即执行(while true;do sleep 99999;done)&
它正确地终止它。
“ps –ppid”选择具有指定父pid的所有进程,例如:
$ (while true;do sleep 99999;done)& [1] 12345 $ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
你可以杀死进程组。
要找到您的进程运行的进程组:
ps --no-headers -o "%r" -p 15864
然后杀死进程组:
kill -- -[PGID]
你可以在一个命令中完成这一切。 让我们试试看:
$ (while true;do sleep 99999;done)& [1] 16151 $ kill -- -$(ps --no-headers -o "%r" -p 16151) [1]+ Terminated ( while true; do sleep 99999; done )
因为“睡眠”是一个过程,而不是一个内置函数或类似的东西
你可以做到以下几点:
(while true;do sleep 99999;done)& whilepid=$! kill -- -$whilepid
上面的代码杀死进程组,因为PID被指定为负数(例如-123而不是123)。 另外,它使用变量$!
,它存储最近执行的进程的PID。
注意:当你在交互模式下(即使用命令行提示符)在后台执行任何进程时,它会创建一个新的进程组,这就是发生在你身上的事情。 这样,“杀死所有人”就相对容易了,因为你只需要杀死整个进程组。 但是,如果在脚本中完成同样的操作,则不会创建任何新的组,因为即使在后台执行所有新进程(作业控制在默认情况下都是禁用的),所有新进程都属于脚本PID。 要在脚本中启用作业控制,只需在脚本开始处添加以下内容:
#!/bin/bash set -m
杀死while
循环和sleep
使用$!
您也可以在子shell中使用trap
信号处理程序。
(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)& kill -TERM ${!}