Bash:在一个while循环中的睡眠得到它自己的PID

我有一个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。

所以我有两个问题:

  1. 为什么睡眠命令会得到自己的进程ID?
  2. 我如何轻松杀死while循环和睡眠?

  1. 睡眠获得自己的PID因为它是一个进程正在运行,只是在等待。 尝试which sleep ,看看它在哪里。
  2. 您可以使用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 ) 
  1. 因为“睡眠”是一个过程,而不是一个内置函数或类似的东西

  2. 你可以做到以下几点:

     (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 ${!}