Sleep 在 while 循环中获取自己的 pid

发布于 2024-10-07 18:06:35 字数 647 浏览 4 评论 0原文

我有一个 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!我可以终止睡眠,一切看起来都很好。但是,如果我先终止睡眠,则 while 循环会启动一个新的睡眠 pid。这对我来说真是一个惊喜,因为睡眠与 while 循环并不平行。循环本身是一条执行路径。

所以我有两个问题:

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

I have a bash script that does some parallel processing in a loop. I don't want the parallel process to spike the CPU, so I use a sleep command. Here's a simplified version.

(while true;do sleep 99999;done)&

So I execute the above line from a bash prompt and get something like:
[1] 12345

Where [1] is the job number and 12345 is the process ID (pid) of the while loop. I do a kill 12345 and get:

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

It looks like the entire script was terminated. However, I do a ps aux|grep sleep and find the sleep command is still going strong but with its own pid! I can kill the sleep and everything seems fine. However, if I were to kill the sleep first, the while loop starts a new sleep pid. This is such a surprise to me since the sleep is not parallel to the while loop. The loop itself is a single path of execution.

So I have two questions:

  1. Why did the sleep command get its own process ID?
  2. How do I easily kill the while loop and the sleep?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你穿错了嫁妆 2024-10-14 18:06:35
  1. Sleep 拥有自己的PID,因为它是一个正在运行且只是等待的进程。尝试 which sleep 看看它在哪里。
  2. 您可以使用 ps -uf 来查看系统上的进程树。从那里您可以确定睡眠 shell(运行循环的 shell)的 PPID(父 PID)是什么。
  1. Sleep gets its own PID because it is a process running and just waiting. Try which sleep to see where it is.
  2. You can use ps -uf to see the process tree on your system. From there you can determine what the PPID (parent PID) of the shell (the one running the loop) of the sleep is.
迷你仙 2024-10-14 18:06:35
  1. 因为“sleep”是一个进程,而不是内置函数或类似函数

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

    p>

    (while true;do sleep 99999;done)&
    而pid=$!
    杀死 -- -$whilepid
    

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

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

#!/bin/bash

set -m
  1. Because "sleep" is a process, not a build-in function or similar

  2. You could do the following:

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

The above code kills the process group, because the PID is specified as a negative number (e.g. -123 instead of 123). In addition, it uses the variable $!, which stores the PID of the most recently executed process.

Note:
When you execute any process in background on interactive mode (i.e. using the command line prompt) it creates a new process group, which is what is happening to you. That way, it's relatively easy to "kill 'em all", because you just have to kill the whole process group. However, when the same is done within a script, it doesn't create any new group, because all new processes belong to the script PID, even if they are executed in background (jobs control is disabled by default). To enable jobs control in a script, you just have to put the following at the beginning of the script:

#!/bin/bash

set -m
青衫儰鉨ミ守葔 2024-10-14 18:06:35

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

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

Have you tried doing kill %1, where 1 is the number you get after launching the command in background?

I did it right now after launching (while true;do sleep 99999;done)& and it correctly terminated it.

弄潮 2024-10-14 18:06:35

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

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

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

"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)
冰葑 2024-10-14 18:06:35

您可以杀死该进程组。

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

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 )

You can kill the process group.

To find the process group of your process run:

ps --no-headers -o "%r" -p 15864

Then kill the process group using:

kill -- -[PGID]

You can do it all in one command. Let's try it out:

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

$ kill -- -$(ps --no-headers -o "%r" -p 16151)
[1]+  Terminated              ( while true; do
    sleep 99999;
done )
东风软 2024-10-14 18:06:35

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

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

To kill the while loop and the sleep using $! you can also use a trap signal handler inside the subshell.

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文