Processes and jobs
watch
Rerun a command every few seconds and show its output full-screen, optionally highlighting changes or exiting when they happen.
watch [OPTION...] COMMAND
watch 'ls -l /var/backups' clears the terminal, runs the command, shows its output under a
header line (Every 2.0s: ls -l /var/backups host: date), and repeats every two seconds until
you press Ctrl-C. It turns any one-shot command into a live dashboard: a file growing during a
download, a queue draining, df -h while a disk fills, ss -tn during a load test. -n sets the
interval, -d highlights what changed since the last run (-d=permanent keeps everything that
ever changed highlighted), -t hides the header.
The command is passed to sh -c, so pipes and quotes work if you quote the whole thing:
watch 'ps aux | grep [n]ginx'. Without the quotes, your own shell takes the | and pipes
watch's screen output into grep.
watch needs a terminal to draw on. The examples run without one, where its screen output is
unreadable, so they discard it and use the options that make watch useful in scripts too:
-g exits when the output changes, -e when the command fails, and -q when the output stops
changing. The full-screen display itself is described in the first example, which cannot run
here.
Examples
Rerun a command every two seconds
watch -n 2 -d 'ls -l logs'
Not run in the sandbox: needs an interactive terminal for its full-screen display, and runs until Ctrl-C. No output is shown because none was captured.
Redraws the directory listing every 2 seconds, with -d highlighting characters that changed
since the previous run, such as a growing file size. The header shows the interval, the
command, the host name and the time. Press Ctrl-C to leave.
Wait until a command's output changes
(sleep 1; touch new-report.csv) &
watch -g -n 0.2 ls > /dev/null
echo "watch exit status: $?, the directory changed:"
ls new-report.csv
watch exit status: 0, the directory changed: new-report.csv
-g (--chgexit) makes watch exit as soon as the output differs from the previous run,
turning it into a "block until something happens" tool. Here a background job creates a
file after a second. The screen output is discarded because there is no terminal.
Stop when the command fails
(sleep 1; touch stop.flag) &
watch -n 0.2 -e 'test ! -e stop.flag' > /dev/null
echo "watch exit status: $?"
watch exit status: 8
-e (--errexit) stops when the command returns a non-zero status, here once stop.flag
exists. In a terminal, watch then waits for a key press; the exit status is 8.
Wait until output stops changing
(for i in 1 2 3; do echo "chunk $i" >> download.part; sleep 0.3; done) &
watch -q 3 -n 0.3 'wc -c < download.part' > /dev/null
echo "size stable at $(wc -c < download.part) bytes"
size stable at 24 bytes
-q N (--equexit, procps 4) exits once the output has stayed the same for N runs. The
background loop stands in for a download; when it stops writing, the size stays put for three
intervals and watch returns.
Wait for a server to start listening
(sleep 1; exec python3 -m http.server 9000 > /dev/null 2>&1) &
watch -g -n 0.3 'ss -ltn | grep -c :9000' > /dev/null
ss -ltn | grep :9000
LISTEN 0 5 0.0.0.0:9000 0.0.0.0:*
The count of listening sockets on port 9000 changes from 0 to 1 when the server comes up,
and -g returns at that moment, so the next command can safely connect.
Give up if the change never comes
timeout 2 watch -g -n 0.5 'ls *.done' > /dev/null
echo "exit status: $?"
exit status: 124
Nothing creates a .done file, so watch -g would wait forever. Wrapped in timeout, it
is stopped after two seconds and the status 124 tells the script the wait timed out.
The script-friendly alternative, a loop
for i in 1 2 3; do
printf '%s %s lines\n' "$(date +%T)" "$(wc -l < logs/app.log)"
sleep 1
done
20:22:03 12 lines 20:22:04 12 lines 20:22:05 12 lines
For logs or anything without a terminal, print one timestamped line per iteration instead of
redrawing a screen. while sleep 1; do ...; done is the endless version.
Common pitfalls
Not quoting a pipeline:
watch ls | wc -lpipes watch's screen intowc. Quote the whole command:watch 'ls | wc -l'.Shell aliases and functions are not available, because the command runs in a fresh
sh -c.watch llfails; writewatch ls -l.Using double quotes for commands containing
$:watch "echo $RANDOM"expands once, before watch starts, and shows the same number forever. Use single quotes sosh -cexpands it each time.Wrapping
watchin a script or cron job for its display. Without a terminal it writes screen-control output; use-g,-e,-qwith the output discarded, or a loop.
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).
watchcomes from procps and is not installed on macOS;brew install watchprovides it, or usewhile :; do clear; cmd; sleep 2; done. FreeBSD has an unrelatedwatchthat snoops on terminal sessions.-q/--equexitis new in procps 4 and missing from older Linux distributions.
Options worth knowing
A selection, described in our own words. For the full list, see watch(1) or watch --help.
| Option | What it does |
|---|---|
-n, --interval SECONDS | Run the command every SECONDS (default 2, fractions allowed). |
-d, --differences[=permanent] | Highlight changes since the last run; =permanent keeps all changes highlighted. |
-t, --no-title | Hide the header line. |
-g, --chgexit | Exit when the command's output changes. |
-e, --errexit | Stop when the command exits with a non-zero status. |
-q, --equexit CYCLES | Exit when the output has not changed for CYCLES runs. |
-b, --beep | Beep when the command exits with a non-zero status. |
-c, --color | Interpret ANSI color sequences in the output. |
-C, --no-color | Do not interpret ANSI color sequences. |
-p, --precise | Start runs at exact intervals, not interval after each run ends. |
-w, --no-wrap | Truncate long lines instead of wrapping them. |
-x, --exec | Run the command directly instead of through sh -c. |
-r, --no-rerun | Do not rerun the command when the window is resized. |
Related
sleepPause for a given amount of time, in seconds by default, with m, h and d suffixes and fractions allowed.topShow a live, sorted view of processes and system load; batch mode prints snapshots for logs and scripts.tailPrint the last lines of files, or follow a file as it grows with -f.timeoutRun a command with a time limit, and kill it if it is still running when the time is up.- 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.
- QuotingSingle quotes, double quotes, backslashes and $'...', what each protects, and the unquoted-variable bugs they prevent, each shown failing and then fixed.