bash 在 while 循环中睡眠会获得自己的 pid
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4452299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sleep in a while loop gets its own pid
提问by User1
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.
我有一个 bash 脚本,它在循环中执行一些并行处理。我不希望并行进程占用 CPU,所以我使用了 sleep 命令。这是一个简化版本。
(while true;do sleep 99999;done)&
So I execute the above line from a bash prompt and get something like:
[1] 12345
所以我从 bash 提示符执行上面的行并得到类似的结果:
[1] 12345
Where [1]is the job number and 12345is the process ID (pid) of the while loop. I do a kill 12345and get:
其中[1]是作业编号,12345是 while 循环的进程 ID (pid)。我做了一个kill 12345并得到:
[1]+ Terminated ( while true; do
sleep 99999;
done )
It looks like the entire script was terminated. However, I do a ps aux|grep sleepand find the sleep command is still going strong but with its own pid! I can kill the sleepand everything seems fine. However, if I were to kill the sleep first, the while loop starts a new sleeppid. 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.
看起来整个脚本都被终止了。但是,我做了一个ps aux|grep sleep,发现 sleep 命令仍然很强大,但它有自己的 pid!我可以杀死sleep,一切似乎都很好。但是,如果我要先终止睡眠,while 循环会启动一个新的sleeppid。这让我很惊讶,因为睡眠与 while 循环并不平行。循环本身是一个单一的执行路径。
So I have two questions:
所以我有两个问题:
- Why did the sleep command get its own process ID?
- How do I easily kill the while loop and the sleep?
- 为什么 sleep 命令会获得自己的进程 ID?
- 如何轻松终止 while 循环和睡眠?
回答by Marcus Borkenhagen
- Sleep gets its own
PIDbecause it is a process running and just waiting. Trywhich sleepto see where it is. - You can use
ps -ufto see the process tree on your system. From there you can determine what thePPID(parent PID) of the shell (the one running the loop) of the sleep is.
- 睡眠有它自己的
PID原因,因为它是一个正在运行并等待的进程。试着which sleep看看它在哪里。 - 您可以使用
ps -uf来查看系统上的进程树。从那里您可以确定PPID睡眠的 shell(运行循环的那个)的(父 PID)是什么。
回答by Alberto Zaccagni
Have you tried doing kill %1, where 1is the number you get after launching the command in background?
你有没有试过kill %1,1在后台启动命令后你得到的数字在哪里?
I did it right now after launching (while true;do sleep 99999;done)&and it correctly terminated it.
我在启动后立即执行(while true;do sleep 99999;done)&并正确终止了它。
回答by matja
"ps --ppid" selects all processes with the specified parent pid, eg:
"ps --ppid" 选择具有指定父 pid 的所有进程,例如:
$ (while true;do sleep 99999;done)&
[1] 12345
$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
回答by dogbane
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 )
回答by Luisg123v
Because "sleep" is a process, not a build-in function or similar
You could do the following:
(while true;do sleep 99999;done)& whilepid=$! kill -- -$whilepid
因为“睡眠”是一个过程,而不是内置函数或类似的
您可以执行以下操作:
(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.
上面的代码杀死了进程组,因为PID被指定为负数(例如-123而不是123)。此外,它使用变量$!,该变量存储最近执行的进程的 PID。
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:
注意:当您在后台以交互模式(即使用命令行提示符)执行任何进程时,它会创建一个新的进程组,这就是您正在发生的事情。这样,“全部杀死”相对容易,因为您只需要杀死整个进程组。但是,当在脚本中执行相同操作时,它不会创建任何新组,因为所有新进程都属于脚本 PID,即使它们在后台执行(默认情况下禁用作业控制)。要在脚本中启用作业控制,您只需将以下内容放在脚本的开头:
#!/bin/bash
set -m
回答by monz
To kill the whileloop and the sleepusing $!you can also use a trapsignal handler inside the subshell.
要终止while循环并sleep使用,$!您还可以trap在子外壳内使用信号处理程序。
(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}

