Processes and jobs
sleep
Pause for a given amount of time, in seconds by default, with m, h and d suffixes and fractions allowed.
sleep NUMBER[SUFFIX]...
sleep 5 does nothing for five seconds and exits 0. It is the delay in retry loops, polling
loops and rate-limited scripts, and the stand-in for "some long-running process" in examples
across this site. GNU sleep accepts fractions (0.25), the suffixes s, m, h and d,
several arguments that are added together (sleep 1m 30s), and infinity.
sleep is an external program, not a builtin, so in a shell it can be killed and interrupted
like any process: Ctrl-C stops it, and a script blocked in sleep does not run its signal traps
until sleep returns. The sleep N & wait $! idiom fixes that, as shown below.
For waiting until something is true (a file appears, a port opens), a loop with a short
sleep and a test is the usual shape; add a counter or wrap it in timeout so it cannot loop
forever. To wait for your own background jobs, use wait instead of guessing a duration.
Examples
Pause between two commands
date +%T
sleep 2
date +%T
20:20:49 20:20:51
Two seconds pass between the timestamps. sleep prints nothing; its whole effect is the
delay.
Sleep for a fraction of a second
start=$(date +%s%N)
sleep 0.25
echo "slept $(( ($(date +%s%N) - start) / 1000000 )) ms"
slept 254 ms
GNU sleep takes decimal fractions. The measured time is slightly over 250 ms because
starting the processes takes a moment too.
Use units and add durations together
time sleep 0.5s 0.25 0.005m
real 0m1.052s user 0m0.000s sys 0m0.002s
Each argument may carry a suffix (s, m, h, d), and multiple arguments are summed:
0.5 s + 0.25 s + 0.3 s (0.005 minutes) = 1.05 s, as the bash time report shows.
Retry a command with a delay
for attempt in 1 2 3 4 5; do
if [ -e ready.flag ]; then echo "ready after $attempt attempts"; break; fi
echo "attempt $attempt: not ready, waiting"
[ "$attempt" -eq 2 ] && touch ready.flag
sleep 0.5
done
attempt 1: not ready, waiting attempt 2: not ready, waiting ready after 3 attempts
The standard poll-and-wait loop: test, sleep, try again, with a fixed number of attempts so
it cannot hang. The touch on attempt 2 stands in for another process creating the file.
Back off exponentially between retries
delay=0.1
for attempt in 1 2 3 4; do
echo "attempt $attempt failed, sleeping ${delay}s"
sleep "$delay"
delay=$(echo "$delay * 2" | bc)
done
attempt 1 failed, sleeping 0.1s attempt 2 failed, sleeping .2s attempt 3 failed, sleeping .4s attempt 4 failed, sleeping .8s
Doubling the delay after each failure is kinder to a struggling server than hammering it.
Shell arithmetic is integer-only, so bc doubles the fractional value. bc drops the
leading zero (.2), which sleep accepts as it is.
Slow down a loop over many items
for host in web01 web02 db01; do
echo "$(date +%T.%N | cut -c1-12) checking $host"
sleep 0.3
done
20:20:55.260 checking web01 20:20:55.567 checking web02 20:20:55.871 checking db01
A short sleep per iteration keeps a loop from flooding an API or a log. The timestamps are about 0.3 seconds apart.
Make a sleeping script respond to signals at once
#!/bin/bash
trap 'echo "got TERM, exiting"; exit 0' TERM
sleep 30 &
wait $!
bash waiter.sh &
sleep 0.3
time { kill $!; wait $!; }
got TERM, exiting real 0m0.001s user 0m0.001s sys 0m0.003s
A script in a plain foreground sleep 30 runs its trap only after sleep ends. Sleeping in
the background and blocking in wait lets the trap fire immediately, as the near-zero
time shows. The background sleep is left to finish on its own; kill it in the trap if
that matters.
Sleep forever
sleep infinity &
ps -o pid,args -p $!
kill $!
PID COMMAND 2604 sleep infinity
infinity (GNU) never returns on its own. It is common as a container's main process to
keep it alive, and as a placeholder that something else will kill.
Invalid durations
sleep 5x
sleep: invalid time interval ‘5x’ Try 'sleep --help' for more information.
An unknown suffix or non-number is rejected with invalid time interval and exit status 1.
Negative numbers are rejected too (the - is read as an option).
Common pitfalls
Polling with no upper bound.
while ! test; do sleep 1; donehangs forever when the condition never comes true; count attempts or wrap the loop intimeout.Using a fixed
sleepto wait for a background job you started. Usewait $pid: it returns exactly when the job ends and gives you its exit status.Expecting traps to run while a script sits in a foreground
sleep. Bash runs the trap only after thesleepends; usesleep N & wait $!.Writing
sleep 1m30s. The suffix applies to one number per argument; writesleep 1m 30sorsleep 90.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
POSIX only guarantees whole seconds. GNU, macOS and FreeBSD
sleepaccept fractions, but suffixes (5m), several arguments andinfinityare GNU features.sleep 300works everywhere.
Related
timeoutRun a command with a time limit, and kill it if it is still running when the time is up.waitWait for background jobs of the current shell to finish, and return their exit status.watchRerun a command every few seconds and show its output full-screen, optionally highlighting changes or exiting when they happen.timeMeasure how long a command takes (wall-clock, user and system CPU time); GNU /usr/bin/time also reports memory and I/O.datePrint the current date and time in any format, or convert and calculate dates.- Loopsfor over lists, files and ranges, C-style for, while and until, break and continue, retry loops, and redirecting a whole loop's input or output.
- Traps and signalsRunning cleanup code with trap on EXIT, handling INT and TERM, the ERR pseudo-signal, and the timing and scoping rules that trip people up.