5

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

(虽然是真的;睡觉 99999;完成)&

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

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

[1]+ 终止(虽然为真;做
    睡觉99999;
完毕 )

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

所以我有两个问题:

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

6 回答 6

5
  1. 睡眠有它自己的PID原因,因为它是一个正在运行并且只是等待的进程。试着which sleep看看它在哪里。
  2. 您可以使用ps -uf查看系统上的进程树。从那里您可以确定PPID睡眠的外壳(运行循环的那个)的(父 PID)是什么。
于 2010-12-15T16:42:43.387 回答
2
  1. 因为“睡眠”是一个过程,而不是一个内置函数或类似的

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

    (while true;do sleep 99999;done)&
    whilepid=$!
    kill -- -$whilepid
    

上面的代码杀死了进程组,因为 PID 被指定为一个负数(例如 -123 而不是 123)。此外,它使用变量$!,该变量存储最近执行的进程的 PID。

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

#!/bin/bash

set -m
于 2016-08-17T18:51:11.730 回答
1

"ps --ppid" selects all processes with the specified parent pid, eg:

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

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
于 2010-12-15T16:42:40.947 回答
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 )
于 2010-12-15T16:59:49.937 回答
1

您是否尝试过kill %11在后台启动命令后得到的数字在哪里?

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

于 2010-12-15T16:37:35.530 回答
0

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

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}
于 2013-03-11T16:10:23.473 回答