March 28, 2005

CLI Magic: Wait or Sleep?

Author: Jim Westbrook

Usually, you want a shell script to just run to completion, one command after another. There are times, however, when a sequence of events includes a step upon which subsequent steps depend for successful execution. For these times, two useful commands are wait and sleep, both of which cause a delay in the script execution. Updated code samplesThe wait command man page simply states that it pauses script execution until a specified process ID completes. The man page for the sleep command is a single line stating that it causes a script to pause for specified period of time.

How do you decide which is appropriate for the script at hand? In some cases it won't make any difference to the successful completion of
the script. Other times it can be the difference between success and total failure to produce the expected results.

As an example of a script in which the difference is potentially significant, let's use a root cron script that runs every day to update a
database of file locations. (Please note that this is an example only, not something I have debugged and actually run.)

  #! /bin/sh 
cd /stuff/flix 
ftp  
updatedb 
locate mpg |grep /stuff/flix 
exit 0

While this would appear to be a valid construction, it will fail if
executed, because the line beginning with locate
would be called before the previous line had run to completion. On a large
system the updatedb process can take several minutes. This is the perfect
time to use the wait command.

  #! /bin/sh 
cd /stuff/flix 
sftp  &
wait 
updatedb &
wait 
locate mpg |grep /stuff/flix 
exit 0 

A call to wait after the sftp command delays the script until all file transfer activity has completed. Similarly, inserting wait after the updatedb call delays further processing until the updatedb process finishes.

Why not use the sleep command instead? In the above illustration, having
the script delay for only a specified amount of time would work only if the
amount of time specified was sufficiently long for the task to complete.
You would have to guess how much time would be required for the longest
transfer of files. Since that time can vary significantly due to many
factors, even if the file size(s) are exactly the same every day, the use of
wait insures that the process has completed.

So when is the sleep command the right choice?
Let's look at another example, this time snipped from the /etc/init.d/smb
script, to illustrate the choice. Note: these code samples are for illustration only!

# wait for cupsd to be ready 
function wait_for_cupsd 
{ 
        echo -n "Samba SMB: Waiting for cupsd to get ready" 
        SAMBA_CUPSD_TIMEOUT=30 
        rc_timer_on ${SAMBA_CUPSD_TIMEOUT} 42 
        START=$( date +%s) 
        while [ $(( $( date +%s) - ${START} )) -lt ${SAMBA_CUPSD_TIMEOUT} ]; 
do 
                lpstat -r &>/dev/null 
                LPSTAT_RC=$? 
                if [ ${LPSTAT_RC} -eq 0 ]; then break 
                else sleep 2 
                fi 
        done 
        rc_timer_off 

        test ${LPSTAT_RC} -eq 0 && rc_status -v || rc_status -s 
        rc_reset 
} 

This script calls the sleep command within a while/do/done loop
with a parameter of two seconds as the else branch of an if/then/else test.
This causes the loop to re-execute every two seconds until the printer
daemon is ready to accept print jobs. Here we know exactly how long we wish
to wait before testing the status again.

That's the real difference in making the choice between wait and sleep -- knowing the amount of time to delay the script.

Now, armed with the knowledge of what the wait and sleep commands can do, and
how to decide which to use, we come to the fun part of script usage -- finding
applications for what we have learned that can make the computing experience
more productive or just less hassle. Any multi-step computing task that you
perform frequently is a good candidate for becoming a script.

A cron tip

Because I mentioned the use of a cron job earlier, here's a little comment
header that can make life a lot easier when setting your crontab. I use a
file called cronset that I can edit easily. I then call
crontab passing it cronset as a command-line parameter.

 
MAILTO="" 
#################################################################### 
#minute (0-59),                                                    # 
#|      hour (0-23),                                               # 
#|      |       day of the month (1-31),                           # 
#|      |       |       month of the year (1-12),                  # 
#|      |       |       |       day of the week (0-6 with 0=Sunday)# 
#|      |       |       |       |       commands                   # 
#################################################################### 
30      01      *       *       *       /home/jim/bin/cleartmp 

Jim Westbrook has been BBS sysop for seventeen years, a network admin
since 1983, and a Linux user and advocate since 1999. He is the current
president of the Austin Linux Group, in Austin, Texas.

Category:

  • Linux