Sleep in a while loop gets its own pid
- Sleep gets its own
PID
because it is a process running and just waiting. Trywhich sleep
to see where it is. - You can use
ps -uf
to 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.
Using while or until to wait until a PID doesn't exist
You should be simply doing:
while kill -0 $PID >/dev/null 2>&1
do
# Code to kill process
done
The loop condition tests the exit status of the last command — in this case, kill
. The -0
option (used in the question) doesn't actually send any signal to the process, but it does check whether a signal could be sent — and it can't be sent if the process no longer exists.
(See the POSIX specification of the kill()
function and the POSIX kill
utility.)
The significance of 'last' is that you could write:
while sleep 1
echo Testing again
kill -0 $PID >/dev/null 2>&1
do
# Code to kill process
done
This too tests the exit status of kill
(and kill
alone).
Killing a while loop that's running in the background without a PID
I wrote the sentence in a script file which named while.sh, and ran it by shell:
[edemon@CentOS workspace]$ ./while.sh
[edemon@CentOS workspace]$
There is not PID.
I used top command tool to search my while.sh, it told me:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4036 edemon 20 0 5268 756 436 R 97.3 0.0 0:07.93 bash
2469 root 20 0 94412 29m 10m S 7.8 2.0 1:49.19 Xorg
2788 edemon 20 0 74300 12m 10m S 1.9 0.9 1:38.79 nm-applet
4040 edemon 20 0 2708 1072 796 R 1.9 0.1 0:00.01 top
The while's father process is bash, so I killed 4036. The size of alive.log didn't grow any more.
Kill PIDs created in while loop background processes
Right now you're collecting only the last PID, not the PIDs of all your background processes.
If you collect the PIDs, you can wait on them individually -- which lets you check whether the individual jobs failed, or to see which one of them isn't actually finishing:
pids=( )
while read bar; do
foo "$bar" & pids+=( "$!" )
done < bars.txt
for pid in "${pids[@]}"; do
echo "Checking exit status of $pid..."
if wait "$pid"; then
echo "$pid succeeded!"
else
echo "$pid failed!"
fi
done
If you want to track down which specific values processing succeeded or failed for, you can do even better (with bash 4.0 or later):
declare -A pids=( )
while read -r bar; do
foo "$bar" & pids[$!]="$bar"
done < bars.txt
for pid in "${!pids[@]}"; do
bar=${pids[$pid]}
echo "Checking exit status of $pid (processing value $bar)..."
if wait "$pid"; then
echo "$pid (for $bar) succeeded!"
else
echo "$pid (for $bar) failed!"
fi
done
In either of the above cases, each invocation of wait
is responsible for returning after the corresponding PID has exited. Thus, when all your background tasks have exited, your script will exit on its own.
Finally, to force your children to exit, you can build a signal handler that takes advantage of the PID list:
shutdown() { kill "${pids[@]}"; } # or "${!pids[@]}" for the second example
trap shutdown 0
Bash kill sleep by parent's PID not working in loop
Bash loops start new process id's as a child. The shell variable $PPID should represent the parent PID. However, I read your prior question as well and I think the better question would be what are you really trying to accomplish? All of this smells hacky...
The statements before wait() aren't being executed, even though the loop isn't infinite (but the children are). Why is that?
I'm not myself an expert, but I have the impression that nothing is being printed because the text is not being flushed to stdout. In some programming languages when you print something, the text is not directly printed but instead it is saved in memory (also known as buffer in some contexts like this one). This is for performance reasons. Sometimes it is more performant to print lots of text to stdout at once than it would be to print small amounts of texts many times.
When you "flush" the text you are removing it from the buffer and printing it to stdout. This is usually done automatically for instance before the process ends or when the buffer is full. If I recall correctly you can also flush the text by printing a line break "\n" because (I am not 100% sure if this is the actual reason, I'm speculating here) in some systems like linux some programs process input line by line and this way the program doesn't have to wait the buffer to be filled or the process finished to start working on the input.
The problem is then that the text is being stored in memory but not printed because it is not being flushed. Try the following:
- Printing a newline "\n" after the text
- Printing a really long string that wouldn't fit in the buffer.
If I'm right in both cases the text should be displayed in screen. You can also use the fflush()
function @pmg suggested in the comment section to explicitly flush the text.
Signalling a bash script running in the background in an infinite loop
This works for me.
EDITED 2014-01-20: This edit avoids the frequent waking up. Also see this question:
Bash: a sleep in a while loop gets its own pid
#!/bin/bash
MY_PID=$$
echo $MY_PID > test.pid
trap 'kill ${!}; run' SIGUSR1
run()
{
echo "signal!"
}
while true
do
sleep 1000 & wait ${!}
done
Running:
> ./test.sh &
[1] 14094
> kill -SIGUSR1 `cat test.pid`
> signal!
>
when is echo after done in a while loop executed
Because the echo " halted ! "
is called after done
, it is outside of the while loop. This means that "halted!" will only be echoed on the condition that we have broken out of the time-keeping loop, which would happen anytime the script goes back to the "top" of the loop, and checks if test -f /tmp/stop
is true. If it is, the time-keeping stops, leading the script to the echo statement, and announcing the time-keeping has stopped (as we aren't in the loop anymore).
Related Topics
How to Test My Bash Script on Older Versions of Bash
How to Setup Cron Job on Amazon Linux Ami
How to Set Folder Permissions for a Particular Container on Elastic Beanstalk
Check The Output of "Make" and Exit Bash Script If It Fails
Create Infinite Looping Repeating File Cat in Linux/Bash
Setup Sftp to Use Public-Key Authentication
The Difference Between Wait_Queue_Head and Wait_Queue in Linux Kernel
Automatically Adjusting Process Priorities Under Linux
Open-Source Opengl Profiler for Linux
How to Rewrite If File Not Found Using Nginx
Gui Svn Client for Debian Linux
Elastic Beanstalk: Log Task Customization on Amazon Linux 2 Platforms
How Run Different Versions of Node.Js in Same Time
Compare Checksum of Files Between Two Servers and Report Mismatch
How to Split Two Vertical Pane Inside a Horizontal Pane in Tmux Using Tmuxinator
How to Start a Nodejs Process on a Remote Server
How to Delete All Files Starting with ._ from The Shell in Linux