Sleep in a while loop gets its own pid

元气小坏坏 提交于 2020-01-13 12:09:10

问题


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?

回答1:


  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.



回答2:


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.




回答3:


"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)



回答4:


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 )



回答5:


  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



回答6:


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


来源:https://stackoverflow.com/questions/4452299/sleep-in-a-while-loop-gets-its-own-pid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!