SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

How to Use the watch Command for Linux Well

Learn how watch reruns commands every 2 seconds, set a sane interval, highlight changes, exit on change, and quote pipes so commands run correctly.

Wetin the watch command dey do

The watch command dey run another command again at a fixed interval and redraw its output for the same place for screen. The default interval na two seconds. Use am when you dey wait for number to change: disk wey dey fill up, container wey dey settle, certificate renewal wey dey complete, or queue wey dey empty.

watch come from procps-ng and e dey already installed for fresh Ubuntu or Debian VPS as part of the procps package. Check your version before you trust any flag below, because two useful options na recent additions.

watch --version

For Ubuntu 24.04, e go print line like watch from procps-ng 4.0.4. Now make we see the simplest useful example.

watch df -h /

The screen go clear and show header line, blank line, then the output of df -h /:

Every 2.0s: df -h /                          server1: Sun Aug  9 10:21:44 2026

For left side na the interval and the exact command wey watch dey run. For right side na the hostname and current time. The clock na the useful part, because e prove say the screen still dey refresh even when the numbers below no dey change. Press Ctrl+C to quit.

watch dey draw one frame wey fit inside the terminal. Long lines dey wrap, but -w go truncate dem instead, and anything wey pass the bottom row no go draw at all. No scrollback dey inside the frame, because every cycle dey overwrite the previous one. Na this fact dey decide most things wey watch good for.

How often watch suppose re-run the command?

Two seconds na only default. Choose the interval based on how fast the value dey change and how much one run dey cost.

  • -n 0.5 for counters wey dey move constantly, like ss -s or interface byte count. The smallest interval wey watch accepts na 0.1 seconds.
  • -n 30 or -n 60 for disks and certificates. Filesystem wey dey fill over one day no need thirty frames every minute.

watch dey run the command, wait make e finish, then e sleep for the interval. The runtime dey add to the gap, so command wey take eight seconds under -n 2 go give you one frame every ten seconds and keep the machine busy throughout. Add -p (--precise), and watch go try start one run every interval seconds instead. E dey measure from the start of one run to the start of the next one.

If you always want different default, export WATCH_INTERVAL for your shell profile. Explicit -n still get priority over am. Run watch --help to confirm say your build dey read that variable.

Wetin change with -d

To read plenty identical text find the one field wey move no easy. -d (--differences) go do am for you.

watch -n 30 -d 'df -h / /var'

Characters wey different from the previous frame go show for reverse video. So, Use% cell go light up as soon as e move, while every other thing remain quiet. If /var no be separate filesystem, you go see root filesystem listed two times. This one na quick way to learn how dem partition the box.

The comparison dey use position. This mean say watch go compare the new frame with the old one character by character. Output wey columns dey change width fit light up almost complete. So, prefer commands wey get stable layout. Current procps-ng still accept watch --differences=permanent. This one keep every position wey don ever change highlighted, instead of only the latest change. Confirm am with watch --help before you depend on am.

How I fit make watch comot when output change?

-g (--chgexit) dey stop watch the first time output no match wetin e show for the run before. Your prompt go come back, so you fit put another command after am for the same line.

watch -n 10 -g 'systemctl is-active myapp' ; echo 'state changed'

Na this flag dey turn watch to tool wey go tell you when deployment don land. E get one trap, and e dey catch everybody: comparison dey cover the whole output. So any clock or PID (process identifier) wey dey inside go change for the first refresh, and watch go comot immediately. systemctl status myapp dey print elapsed time and memory use, so -g on top am no useful. Reduce the command to only the one stable fact wey you dey wait for. Na systemctl is-active dey give you this.

Newer procps-ng get the opposite test, --equexit <cycles>. E go comot after output don remain the same for that number of cycles. E dey answer, “tell me when this don quiet.” Check watch --help, because older builds no get am.

Why watch dey ignore my pipe and glob?

Na failure wey almost everybody dey hit at least once, and the cause dey your shell, no be for watch.

watch docker compose ps | grep web

Your interactive shell dey read the whole line before anything run, then e split the line for the pipe. E start watch docker compose ps and connect watch own screen output go grep. watch no dey write to terminal again, so the display go spoil or remain empty, and grep dey filter redraw output instead of container list.

Quote the whole pipeline make e reach am as one argument.

watch 'docker compose ps | grep web'

watch pass that string go sh -c, and that shell run the pipeline once every cycle. Globs follow the same rule, but the symptom quieter.

watch ls -l /var/log/*.log
watch 'ls -l /var/log/*.log'

The first line expand the glob once for your shell, exactly when you press Enter. watch then dey run frozen list of filenames again and again, so log file wey dem create one minute later no go appear. The second line hand the glob to watch, wey expand am inside sh every cycle, so new files go show by themselves.

Quotes also decide when variable or command substitution go evaluate. watch "echo $(date)" run date once for your shell, then e echo that fixed string forever. watch 'echo $(date)' run date every cycle. Single quotes mean later. Double quotes mean now.

Two more things follow from that sh -c:

  • Aliases and shell functions no dey exist inside am. watch ll fail with sh: 1: ll: not found, because sh -c never read your .bashrc. Write the real command, or give the full path to binary wey dey only for your interactive PATH.
  • Standard error dey worth capturing. Put 2>&1 inside the quotes when you want error text to show inside the frame instead of scattering across am.

When quoting don hard, -x (--exec) run the command directly instead of through sh -c. Arguments wey get spaces become easier, and pipes plus globs stop working completely, because no shell remain to interpret dem.

Privileges follow the same logic, because watch na ordinary process. watch 'sudo ss -tulpn' reach password prompt wey you no fit see or type into. Run sudo watch 'ss -tulpn' instead, and remember say the whole loop go run as root until you press Ctrl+C.

Four things wey worth monitoring for a VPS

Disk wey dey fill up

watch -n 30 -d 'df -h / /var'

df dey ask the kernel for figures wey e don already hold, so e cheap enough to repeat forever. du -sh /var/log no be like that, because e dey walk through every file for the tree on every cycle. Under watch, e dey read the disk continuously and slow down the machine wey you dey diagnose. Run du once, or use ncdu, then leave df under watch to show you whether the number still dey climb.

Container wey dey restart again and again

cd /srv/myapp
watch -n 5 -d 'docker compose ps'

The status column dey show how long each container don dey up. Container wey dey inside crash loop go keep resetting to "Up 2 seconds", and -d go make that clear at a glance. Change directory first, because watch inherits the working directory of the shell wey start am, and docker compose needs the project directory. watch dey tell you say restart dey happen. docker compose logs -f web dey tell you why. Once you know the reason, encode the answer as Compose healthcheck wey go restart the container for you so nobody need sit down dey stare screen.

Certificate renewal wey just land

sudo -i
watch -n 60 -g 'openssl x509 -noout -enddate -in /etc/letsencrypt/live/example.com/fullchain.pem'

The command dey print one line, notAfter=Nov 7 09:14:22 2026 GMT, and nothing else, so -g go fire exactly when the file don replace with renewed one. Only root fit read the files under /etc/letsencrypt/live, na why this dey run inside root shell. Note say e dey watch the certificate for disk. Web server wey dey run go keep the old certificate for memory until e reload, so check wetin e really dey serve with echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate, and no put that command for two-second interval against public host. The renewal itself belong to systemd service and timer, and systemctl list-timers dey show when e go run next.

Queue wey dey drain

watch -n 15 'postqueue -p | tail -n 1'

That one dey print summary line like -- 24 Kbytes in 6 Requests., or Mail queue is empty once e don finish. The same pattern work for any queue wey you fit count: watch -n 5 'find /srv/queue/incoming -type f | wc -l'.

For here watch don reach im limit. E dey compare one frame with the frame before am, and e no fit test condition, so e no go ever tell you "the count reach zero". Plain shell loop fit do am, by using command substitution to capture the count for every pass:

until [ "$(find /srv/queue/incoming -type f | wc -l)" -eq 0 ]; do sleep 5; done; echo 'queue drained'

When watch command no be the right tool

watch dey run your command again without remembering wetin happen for the previous run, and e no understand wetin the command dey do. This dey okay for df. But e no correct for four situations.

  • Logs. watch dey redraw one fixed frame, so any line wey appear and scroll away between two cycles go lost. Use journalctl -fu nginx or tail -f; dem dey stream new lines as dem dey write.
  • Expensive commands. du -sh / or query wey dey hit busy database go become permanent background load for any interval, because watch dey start am again and again.
  • Anything with side effects. Command wey dey write, post, restart, or install go do am again for every cycle. One curl against API every two seconds na 43,200 requests per day. Na so free API key fit get suspended.
  • Long-lived checks. watch dey run for your terminal and go die when your session close. E no alert anybody, and e no keep history after you close the laptop. For that one, you need real status monitor like Uptime Kuma, or scheduled check wey dey live for the server.

The honest boundary na time. watch na for the ten minutes wey you spend waiting for one specific thing to happen. Anything wey suppose still dey check tomorrow belong inside scheduled timer or real monitor.

Run watch inside tmux when you dey use SSH

For SSH, watch dey only last as long as the connection. When the link drop, your shell go receive SIGHUP and e go carry watch down with am. tmux dey solve this problem, and na wetin make watch really useful for remote box.

tmux new -As ops
watch -n 30 -d 'df -h /'

Press Ctrl+b then d to detach. The loop go continue to run for the server. Connect again later with tmux attach -t ops and the frame still dey update; the header clock go prove am. Split the window and you fit keep watch for one side and journalctl -f for the other side. Na the main idea behind tmux-based terminal workbench. When you need ask the same question for several boxes at once, use tool wey dey manage plenty Linux servers instead of wall of watch panes.

The screens we quote here na examples. Column layout and version strings fit different between distributions and procps-ng releases, so read man watch for your own machine to see the flags wey your build really get.

FAQ

Watch dey ignore pipe for watch mycmd | grep foo why?

Your shell dey split the line for the pipe before watch even start. So e dey pipe watch own screen drawing go grep, and e no dey filter the command output. Put quote around the whole pipeline instead: watch 'mycmd | grep foo'. watch go pass that one argument go sh -c, and e go run the pipeline once for every cycle. Same rule dey apply to globs and command substitution.

Which interval I suppose use with watch?

Match am with how fast the value dey change and how much one run dey cost. Half a second fit fast counters, while 0.1 seconds na the smallest interval wey watch accept. Thirty to sixty seconds fit disks and certificates. The command runtime dey add to the gap unless you pass -p. So, slow command under -n 1 go just run back-to-back and e no go pause.

watch fit follow log file?

No. watch dey redraw one frame and e no keep history. So any line wey appear and scroll away between two cycles don disappear permanently. journalctl -fu <unit> and tail -f dey stream new lines as dem arrive, and na that logs need. Use watch for values wey get current state, like disk percentage or queue length.

How I go make watch stop when the thing wey I dey wait for happen?

Use -g (--chgexit) and give am command wey output remain the same until that event happen. Output wey contain clock or PID go change for the first refresh and exit immediately. So systemctl is-active myapp work for where systemctl status myapp no work. For real condition like count reaching zero, use shell until loop, because watch fit only detect say the output change.

Why watch dey show command not found for something wey dey work for my shell?

watch dey pass the command go sh -c, and that shell no dey read .bashrc. So your aliases and shell functions no dey exist there. The message usually na sh: 1: ll: not found. Write the real command fully, or use the full path for binary wey dey only for your interactive PATH.