Bash:在while循环中睡眠获得自己的pid

时间:2010-12-15 16:29:02

标签: linux bash process-control

我有一个bash脚本,它在循环中执行一些并行处理。我不希望并行进程加速CPU,所以我使用sleep命令。这是一个简化版本。

(while true;do sleep 99999;done)&

所以我从bash提示符执行上面的行,得到类似的东西: [1] 12345

其中[1]是作业编号,12345是while循环的进程ID(pid)。我做了kill 12345并得到:

[1]+  Terminated              ( while true; do
    sleep 99999;
done )

看起来整个脚本已经终止。但是,我做了一个ps aux|grep sleep并发现sleep命令仍然很强大,但有自己的pid!我可以杀死sleep,一切似乎都很好。但是,如果我先杀死睡眠,则while循环会启动一个新的sleep pid。这对我来说是一个惊喜,因为睡眠与while循环并不平行。循环本身就是一条执行路径。

所以我有两个问题:

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

6 个答案:

答案 0 :(得分:5)

  1. Sleep有自己的PID,因为它是一个正在运行的进程,只是在等待。请尝试which sleep查看它的位置。
  2. 您可以使用ps -uf查看系统上的进程树。从那里你可以确定睡眠的shell(运行循环的那个)的PPID(父PID)是什么。

答案 1 :(得分:1)

您是否尝试过kill %1,其中1是您在后台启动命令后获得的数字?

我在启动(while true;do sleep 99999;done)&后立即执行了此操作并正确终止了它。

答案 2 :(得分:1)

“ps --ppid”选择具有指定父pid的所有进程,例如:

$ (while true;do sleep 99999;done)&
[1] 12345

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)

答案 3 :(得分:1)

您可以终止进程组。

要查找流程运行的流程组:

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 )

答案 4 :(得分:1)

  1. 因为"睡眠"是一个过程,而不是内置函数或类似的

  2. 您可以执行以下操作:

    (while true;do sleep 99999;done)&
    whilepid=$!
    kill -- -$whilepid
    
  3. 上述代码会终止进程组,因为PID被指定为负数(例如-123而不是123)。此外,它使用变量$!,它存储最近执行的进程的PID。

    注意: 当您在交互模式下在后台执行任何进程时(即使用命令行提示符),它会创建一个新的进程组,这就是您正在发生的事情。这样,它可以相对容易地杀死所有人,因为你只需杀死整个进程组。但是,当在脚本中完成相同操作时,它不会创建任何新组,因为所有新进程都属于脚本PID,即使它们是在后台执行的(默认情况下禁用作业控制)。要在脚本中启用作业控制,只需将以下内容放在脚本的开头:

    #!/bin/bash
    
    set -m
    

答案 5 :(得分:0)

要使用while来终止sleep循环和$!,您还可以在子shell中使用trap信号处理程序。

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}