sleep, time and measuring a command
Pause on purpose with sleep, measure how long a command takes with time, read real, user and sys correctly, and know the quirks of time when it is a program rather than a shell keyword.
What you will learn
- Use `sleep` with fractions, suffixes and several arguments, and in polling loops.
- Measure a command with `time` and interpret real, user and sys.
- Capture the report with `2>`, `-o` or `-p`, and time pipelines through `sh -c`.
sleep: doing nothing, precisely
You have used sleep all through this module as a harmless process to look at. Its real job is to wait: a script that retries a download every ten seconds, a loop that polls until a file appears, a pause between two steps that must not overlap. sleep N waits N seconds and costs no CPU while it does; the kernel simply does not schedule it until the timer fires. BusyBox sleep accepts fractions (0.5), the suffixes s, m, h and d, and several arguments that are added together, so sleep 1m 30s waits ninety seconds. For really short pauses there is also usleep, which takes microseconds.
~% sleep 0.5
~% sleep 1m 30s &
~% ps -o args | grep '[s]leep 1m'
sleep 1m 30s
~% until [ -f /tmp/ready ]; do sleep 1; done; echo ready
time: how long did that take?
~% time sleep 2
real 0m 2.00s
user 0m 0.00s
sys 0m 0.00s
~% time wc -l /etc/passwd
9 /etc/passwd
real 0m 0.00s
user 0m 0.00s
sys 0m 0.00s
time CMD runs the command and, when it exits, reports three numbers. real is wall-clock time, what a stopwatch would show. user is CPU time spent running the program's own code, and sys is CPU time the kernel spent on its behalf (reading files, allocating memory). Comparing them is the useful part. sleep 2 shows real 2 and almost zero CPU: it was waiting, not working. A CPU-bound job shows real close to user plus sys. When real is much larger than user plus sys, the command spent its time waiting: for the disk, the network, a lock, or for the CPU itself because something with a better nice value was running (lesson 57).
Here, time is a program
In bash, time is a shell keyword that can time anything, pipelines and loops included. In this VM's ash it is the BusyBox applet /usr/bin/time (type time says so), an ordinary program that runs one other program. That has consequences. It cannot time builtins: time cd / fails with *can't execute 'cd'*. In time sort big | uniq -c, only sort is timed. The fix for both is to hand the whole thing to a shell: time sh -c 'sort big | uniq -c > /dev/null'. And the report is written to standard error, so time CMD > out.txt still prints it on the screen, while time CMD 2> t.txt captures it (along with any error messages of CMD).
~% time -p sleep 1
real 1.01
user 0.00
sys 0.00
~% time -p -o /tmp/t.txt sleep 1
~% cat /tmp/t.txt
real 1.01
user 0.00
sys 0.00
~% time -f '%e s' sleep 1
1.00 s
~% time cd /
time: can't execute 'cd': No such file or directory
| Option | Effect |
|---|---|
-p | POSIX format: real 1.01, plain seconds, easy to parse |
-o FILE | Write the report to FILE instead of stderr |
-a | With -o, append instead of overwrite |
-f FMT | Custom format: %e real, %U user, %S sys seconds |
-v | Verbose: memory, page faults, context switches… |
Measuring by hand
~% start=$(date +%s); sleep 3; end=$(date +%s)
~% echo "took $((end - start)) s"
took 3 s
Inside a script you often want to time a whole section, not one command. Saving date +%s (seconds since 1970, lesson 68) before and after and subtracting is crude, whole seconds only, but works anywhere and is perfectly good for jobs that take minutes.
Commands in this lesson
| Command | What it does |
|---|---|
sleep 5 / sleep 0.5 / sleep 2m | Wait seconds, fractions, or with a suffix (s, m, h, d). |
sleep 1m 30s | Arguments are added: 90 seconds. |
time CMD | Run CMD and report real, user and sys time on stderr. |
time CMD 2> file | Capture the report in a file. |
time -p -o file CMD | POSIX format, written straight to a file. |
time sh -c 'a | b' | Time a pipeline, loop or builtin. |
date +%s | Seconds since 1970; subtract two of them to time a section. |
Quiz
`time` reports real 10.2 s, user 0.1 s, sys 0.1 s. What was the command doing?
- Computing hard
- Mostly waiting: disk, network, a timer or the CPU queue
- Running in the kernel
After `time ls > out.txt`, where is the timing report?
- At the end of out.txt
- On the screen: time writes to standard error
- Nowhere
How long does `sleep 1m 30s` wait?
- 1 minute
- 90 seconds
- It is an error
Why does `time cd /tmp` fail in the lab VM?
- /tmp does not exist
- Here time is an external program and cd is a shell builtin it cannot execute
- cd is too fast to measure
Which option prints the report as `real 1.01` with plain seconds?
- `-v`
- `-p`
- `-a`
Practice
Time `sleep 2` and save the timing report (not the screen) into `/root/lab/l58/time.txt`.
Time `wc -l /etc/passwd` in POSIX format and have `time` itself write the report to `/root/lab/l58/posix.txt`.
Start in the background a `sleep` that lasts two hours, written with the `h` suffix.
Open this lesson in the app to do the tasks in a real Linux machine and have them checked.