The Shell Scripting Tutorial


Sleepy

A 'sleep' substitute which gives regular updates

19 Jan 2018

The sleep command can be quite useful in an interactive shell. If you want to check something in 5 minutes time, or even just want a timer for a while, a simple "sleep 5m ; curl http://localhost/test.php" or just "sleep 5m ; echo Ready" can be handy terminal tricks.

However, once you've set it off, it's not easy to tell how long it's been running for.

This shell script takes a second parameter, which allows you to specify how often you want to get updates on the sleep process. You can also add a message to display each time it checks in.

Here, we ask it to sleep for 20 seconds, and give an update every 9 seconds. Every 9 seconds, until the 20 seconds are up, it says "Waiting for the ghost in the shell...", because that is the message we asked it to display:

sleepy example

(Note: The original Unix sleep only took an integer number of seconds, eg "sleep 300" to sleep for 5 minutes (300 seconds). Most current sleep implementations can understand "10s", or "20m" or "2h" as "10 seconds," "20 minutes," and "2 hours" respectively).

How it works

The script is shown below. The script spawns two child processes which are run in the background; the first is the main "sleep" command. The "$!" variable stores the Process ID (PID) of the last backgrounded process. The script stores this in $SLEEP_PID. It then starts an infinite loop ("while :" will loop forever), which also runs in the background (note the ampersand (&) after the "done" - this causes the whole loop to be a background process).

It makes a note of the Loop's PID so that the loop can be killed as soon as the script ends (even if you terminate the script abruptly).

The "wait $SLEEP_PID" causes the whole script to block until the sleep has finished; the two background processes keep on running.

The loop will display a message (including the current time), and sleep until its next message is due. It will keep doing this forever, or until it is killed.

The "trap 'kill -9 $LOOP_PID' 0" will kill the Loop if the script is terminated for any reason. Otherwise, the loop might keep writing to your terminal forever!

Once the main sleep has finished, the "wait $SLEEP_PID" is signalled by the operating system, and the script continues to the next command, which is to echo a final "Done" message to tell you that it has finished.

The code

Download sleepy.sh
#!/bin/bash
if [ "$#" -eq "0" ] || [ "$1" == "-?" ]; then
  echo "Usage: `basename $0` sleeptime frequency [message]"
  echo "Sleep for , notify every "
  exit 2
fi
SLEEPTIME=$1
FREQUENCY=$2
shift 2
MESSAGE=$@

# Start the main sleep process
sleep "$SLEEPTIME" &
# Note the PID of the sleep process
SLEEP_PID=$!

while :
do
  echo "`date` $MESSAGE"
  sleep $FREQUENCY
done &
# The while loop runs in its own subshell, and
# has its own PID. Make a note of the loop's PID:
LOOP_PID=$!

# Kill the loop if we exit for any reason
trap 'kill -9 $LOOP_PID' 0

# Wait for the main sleep to finish
wait $SLEEP_PID

# Finished.
echo "`date` $MESSAGE : Done."

Getting the timing right

Note in the example above, that the script started at 27 seconds past the minute, and finished 20 seconds later, at 47 seconds past the minute, even though it was reporting in 9 second intervals; 27+9=36, then 45, then 2 seconds later, the 20 seconds have elapsed. Because the script is put together in the way it is, the "wait $SLEEP_PID" is triggered immediately, and the loop is killed via the trap which was set for it. The trap is needed in case the script is interrupted, but it also neatly kills the loop for us on a normal completion, so there is no need to kill the loop even on a clean exit.

Tying it all up

At the top of the article, it was suggested to use this in tandem with another command; here is an example of this in use. After the sleep has finished, it does a curl to inspect the HTTP headers from www.shellscript.sh:

another sleepy example


My Paperbacks and eBooks

My Shell Scripting books, available in Paperback and eBook formats. This tutorial is more of a general introduction to Shell Scripting, the longer Shell Scripting: Expert Recipes for Linux, Bash and more book covers every aspect of Bash in detail.

Shell Scripting Tutorial

Shell Scripting Tutorial
is this tutorial, in 88-page Paperback and eBook formats. Convenient to read on the go, and in paperback format good to keep by your desk as an ever-present companion.

Also available in PDF form from Gumroad:Get this tutorial as a PDF
Shell Scripting: Expert Recipes for Linux, Bash and more

Shell Scripting: Expert Recipes for Linux, Bash and more
is my 564-page book on Shell Scripting. The first half covers all of the features of the shell in every detail; the second half has real-world shell scripts, organised by topic, along with detailed discussion of each script.