5

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.

4

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
|improve this answer|||||
  • 1
    Ok, that $! works. ps command of busybox does not have -p option. But I replaced 'ps -p' to 'kill -0'. Now it works. Thanks. – SKi Sep 21 '12 at 6:43
  • pidof -x $0 finds instances of the currently running script. – StampyCode Nov 26 '14 at 9:11
3

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 
|improve this answer|||||
  • 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/> – SKi Sep 20 '12 at 12:06
  • 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? – user1146332 Sep 20 '12 at 12:30
  • @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. – Gilles 'SO- stop being evil' Sep 21 '12 at 0:09
  • @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 Sep 21 '12 at 6:02
2

Use wait instead :

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

More details.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.