How to poll existence of a background script correctly

7,173

Solution 1

pidof won't find scripts, since it only looks at the first part of the process name (argv[0]).

You could use pidof -m, but that will find any long_running_script.sh, not just the one started by this script.

A better way is to use the $! variable, which holds the PID of the most recent background job.

#!/bin/bash

long_running_script.sh &  
pid=$!

while ps -p $pid >/dev/null
do
    echo "."
    sleep 1
done

Solution 2

In the case you don't want a blocking wait i would tackle this problem with bash's builtin job-control feature. For only one forked and executed process it is really simple and my approach looks like this

#!/bin/sh

sleep 1 &

while jobs | grep -q "Running" ; do
    echo -n "."     # no trailing newline
    sleep 0.1
done

echo 

Solution 3

Use wait instead :

#!/bin/sh
  long_running_script.sh &  
  wait
  echo "done"

More details.

Share:
7,173

Related videos on Youtube

SKi
Author by

SKi

Updated on September 18, 2022

Comments

  • SKi
    SKi almost 2 years

    I have a problem with the following kind of script:

      #!/bin/sh
    
      long_running_script.sh &  
    
      while [ `pidof long_running_script.sh` ]
      do
        echo "."
        sleep 1
      done
    

    The sript will start a new script to background, and it should print dots until the backgroud script will exit. It works when CPU load is not high.

    But, when there is high CPU load, it won't work: long_running_script.sh will start, but the 'parent' script will exit from while loop before the long_running_script.sh exits.

    Seems that pidof is executed before the long_running_script.sh is really started (execved).

    What is the best way to solve this problem?

    1 seconds sleep before the while statement didn't help. So I don't want to use any magic delays, because it may be unreliable.

  • SKi
    SKi almost 12 years
    Hmm, I have problem with this. Some reason I can not grep output of jobs: <br/> # jobs | grep R <br/> # jobs <br/> [3] + Running sleep 100 <br/> [2] - Running sleep 100 <br/> # <br/>
  • user1146332
    user1146332 almost 12 years
    Probably you misinterpret the output. Of course you get a line like [3] + Running sleep 100 [2] - Running sleep 100 prompted on stdout, since grep finds your search pattern R and prints the corresponding line. The important point is what grep returns. If you invoke echo $? immediatly after grepping you should see 0 which signals success. A 1 would mean that grep didn't find anything. Have you tried my example on your system?
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 12 years
    @User1 Depending on your shell, you might not be able to use jobs in a subshell (e.g. in the left-hand side of a pipe jobs | … or in a command substitution $(jobs)). Bash supports it, but not dash.
  • SKi
    SKi almost 12 years
    @user1146332 : Yes I try your example in 2 host. It work in Fedora PC, but not in my embedded Linux box with bysybox /bin/sh.
  • SKi
    SKi almost 12 years
    Ok, that $! works. ps command of busybox does not have -p option. But I replaced 'ps -p' to 'kill -0'. Now it works. Thanks.
  • StampyCode
    StampyCode over 9 years
    pidof -x $0 finds instances of the currently running script.