Linux watch: Repeating Commands Periodically

The `watch` command is one of those Unix utilities that seems deceptively simple until you realize how much time it saves. Instead of repeatedly hammering the up arrow and Enter key to re-run a...

Key Insights

  • The watch command executes a command repeatedly at fixed intervals (default 2 seconds), making it essential for monitoring system state without writing custom scripts.
  • Use -d to highlight differences between iterations and -n to customize intervals—combining these flags transforms watch into a powerful change-detection tool for deployments and debugging.
  • Quote complex commands properly: single quotes for literal strings, double quotes when you need variable expansion, and escape dollar signs when you want watch to evaluate them each iteration.

Introduction to the watch Command

The watch command is one of those Unix utilities that seems deceptively simple until you realize how much time it saves. Instead of repeatedly hammering the up arrow and Enter key to re-run a command, watch does it for you automatically, displaying the output in a clean, updating interface.

At its core, watch executes a command at regular intervals and displays the results. The screen updates in place, so you get a real-time view of changing data. This makes it invaluable for monitoring system resources, tracking deployment progress, observing log files, and debugging issues where timing matters.

The basic syntax is straightforward:

watch [options] command

Here’s the simplest possible example:

watch date

This displays the current date and time, updating every two seconds. You’ll see a header showing the interval, the command being executed, and the current time. Press Ctrl+C to exit.

Basic Usage and Syntax

When you run watch, it clears the screen and displays three pieces of information at the top:

  • The update interval (default: 2.0 seconds)
  • The command being executed
  • The current timestamp

Below that, you see the command’s output, which refreshes at the specified interval. The default two-second refresh is a reasonable balance between responsiveness and system load.

Let’s look at practical examples:

watch date

This shows the current date and time updating every two seconds. Simple, but it demonstrates the core behavior.

For something more useful, monitor disk usage:

watch df -h

This displays your filesystem usage, updating continuously. You can watch disk space decrease as you download files or run builds.

Monitor memory usage:

watch free -m

This shows memory and swap usage in megabytes. It’s particularly useful when you’re running memory-intensive operations and want to ensure you’re not hitting swap.

The output remains stable on screen—only the changing values update. This makes it easy to spot trends and anomalies.

Essential Options and Flags

The watch command becomes significantly more powerful with a few key flags.

Custom Intervals with -n

The -n flag sets the update interval in seconds:

watch -n 5 uptime

This updates every five seconds instead of two. Use longer intervals for commands that are expensive to run or when you don’t need rapid updates. Use shorter intervals (down to 0.1 seconds) when monitoring fast-changing data:

watch -n 0.5 'ps aux | grep nginx | wc -l'

Highlighting Differences with -d

The -d flag highlights what changed since the last iteration:

watch -d 'ls -l /var/log'

Changed values appear in reverse video (usually highlighted). This is incredibly useful when you’re waiting for a specific file to appear or for a value to change.

Removing the Header with -t

The -t flag removes the header, giving you a cleaner output:

watch -t df -h

This is useful when piping output or when the header is distracting.

Precise Intervals with -p

The -p flag attempts to run the command at precise intervals, accounting for command execution time:

watch -p -n 1 'date +%s.%N'

Without -p, if your command takes 0.3 seconds to run, a 1-second interval means 1.3 seconds between starts. With -p, watch tries to maintain exactly 1 second between executions.

Combine flags for maximum utility:

watch -n 1 -d 'ps aux | grep python | grep -v grep'

This monitors Python processes every second and highlights any changes—perfect for debugging process spawning or crashes.

Practical Real-World Scenarios

Here’s where watch shines in actual development and operations work.

Monitoring Log File Growth

watch 'tail -n 20 /var/log/syslog'

This shows the last 20 lines of syslog, updating continuously. You see new log entries appear in real-time. It’s more convenient than tail -f when you want to see a fixed window of recent entries.

Tracking Deployment Progress

watch 'kubectl get pods -n production'

When deploying to Kubernetes, this shows pod status updates. You can watch pods transition from Pending to Running, or catch CrashLoopBackOff errors immediately.

For Docker Compose:

watch 'docker-compose ps'

Observing Network Connections

watch -n 2 'netstat -tuln | grep LISTEN'

This displays listening ports on your system. Useful when starting services to verify they’re binding to the correct ports.

For active connections:

watch -n 1 'netstat -an | grep ESTABLISHED | wc -l'

This counts active connections, helping you monitor connection pool usage or detect connection leaks.

Monitoring Directory Changes

watch 'ls -lh /tmp/uploads | tail -n 10'

This shows the newest files in a directory. Perfect for monitoring upload directories or build output folders.

Tracking Build Progress

watch 'du -sh /var/lib/docker'

Monitor Docker’s disk usage during builds. Combine with -d to highlight when the size changes:

watch -d -n 5 'du -sh /var/lib/docker'

Monitoring System Resources

watch -n 1 'ps aux | sort -nrk 3,3 | head -n 5'

This shows the top 5 processes by CPU usage, updating every second. Essential for identifying CPU hogs.

For memory:

watch -n 1 'ps aux | sort -nrk 4,4 | head -n 5'

Advanced Techniques and Gotchas

Quoting Requirements

Complex commands need proper quoting. Use single quotes to pass the entire command as-is:

watch 'ps aux | grep nginx | grep -v grep'

Without quotes, watch only monitors ps aux, and the shell interprets the pipes before watch sees them.

Use double quotes when you need variable expansion at watch startup:

USER=$(whoami)
watch "ps aux | grep $USER"

But be careful—this expands $USER once when you run watch, not on each iteration.

Variable Expansion per Iteration

To expand variables on each iteration, escape the dollar sign:

watch "echo \$RANDOM"

This generates a new random number each time. Without the backslash, $RANDOM expands once when you start watch.

Complex Piping and Sorting

You can build sophisticated monitoring commands:

watch 'ps aux | awk "{print \$3, \$11}" | sort -rn | head -n 5'

This shows the top 5 processes by CPU with just their CPU percentage and command name. Note the escaped dollar signs in the awk command.

Exit on Change with -g

The -g flag exits when output changes:

watch -g 'pgrep myapp'

This runs until myapp appears or disappears, then exits. Useful in scripts:

watch -g 'test -f /tmp/deployment.complete' && echo "Deployment finished!"

Performance Considerations

Be mindful of command execution time. If your command takes 3 seconds to run but you set a 1-second interval, watch will run continuously without pausing. This can overload your system.

For expensive commands, use longer intervals:

watch -n 10 'find /var/log -type f -size +100M'

Exit Codes

Watch returns the exit code of the last command execution. You can use this in scripts:

if watch -g -n 1 'pgrep -f "my-service"'; then
    echo "Service stopped"
fi

Alternatives and When Not to Use watch

While watch is excellent for interactive monitoring, it’s not always the right tool.

For File Changes: entr

The entr utility is better for reacting to file changes:

ls *.py | entr pytest

This runs tests whenever Python files change—more efficient than polling with watch.

For Scheduled Tasks: cron

Use cron for periodic execution that doesn’t need interactive display:

*/5 * * * * /usr/local/bin/backup.sh

Custom Shell Loops

Sometimes a while loop is more appropriate:

while true; do
    date
    sleep 2
done

This is equivalent to watch date, but you have more control over output formatting and error handling. However, it doesn’t clear the screen or provide the clean interface watch offers.

When to Use What

  • Use watch for interactive monitoring where you want to see updates in place
  • Use entr for file-change triggered actions
  • Use cron for scheduled background tasks
  • Use while loops when you need complex logic between iterations

The watch command excels at its specific purpose: providing a clean, updating view of command output. Master it, and you’ll find yourself using it daily for debugging, monitoring, and understanding system behavior in real-time.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.