watch runs a command every N seconds and displays the output. It’s the simplest form of real-time monitoring — no setup, no configuration, just instant feedback loops.
Basic Usage#
1
2
3
4
5
6
7
8
| # Run command every 2 seconds (default)
watch date
# Run every 5 seconds
watch -n 5 date
# Run every 0.5 seconds
watch -n 0.5 date
|
Highlight Changes#
1
2
3
4
5
| # Highlight differences between updates
watch -d df -h
# Highlight changes permanently (cumulative)
watch -d=cumulative df -h
|
Common Options#
1
2
3
4
5
6
7
| -n, --interval Seconds between updates (default: 2)
-d, --differences Highlight changes
-t, --no-title Hide the header
-b, --beep Beep on command error
-e, --errexit Exit on command error
-c, --color Interpret ANSI color sequences
-x, --exec Pass command to exec instead of sh -c
|
Practical Examples#
Disk Space#
1
2
3
4
5
6
7
8
| # Watch disk usage
watch df -h
# Watch specific mount
watch 'df -h | grep /dev/sda1'
# Watch directory size
watch 'du -sh /var/log'
|
Memory#
1
2
3
4
5
| # Memory stats
watch free -h
# Memory with buffers/cache detail
watch 'free -h && echo && cat /proc/meminfo | head -10'
|
Processes#
1
2
3
4
5
6
7
8
| # Process count
watch 'ps aux | wc -l'
# Specific process
watch 'ps aux | grep nginx'
# Process memory
watch 'ps aux --sort=-%mem | head -10'
|
Network#
1
2
3
4
5
6
7
8
9
10
11
| # Network connections
watch 'netstat -tuln'
# Connection count
watch 'netstat -an | wc -l'
# Active connections
watch 'ss -s'
# Interface stats
watch 'cat /proc/net/dev'
|
Files and Directories#
1
2
3
4
5
6
7
8
9
10
11
| # File list
watch ls -la
# Directory size changes
watch 'du -sh *'
# File count
watch 'find . -type f | wc -l'
# Recent files
watch 'ls -lt | head -10'
|
Docker#
1
2
3
4
5
6
7
8
| # Container status
watch docker ps
# Container stats
watch 'docker stats --no-stream'
# Image list
watch docker images
|
Kubernetes#
1
2
3
4
5
6
7
8
| # Pod status
watch kubectl get pods
# All resources
watch 'kubectl get pods,svc,deploy'
# Pod logs (last 5 lines)
watch 'kubectl logs -l app=myapp --tail=5'
|
Git#
1
2
3
4
5
6
7
8
| # Branch status
watch git status
# Log (one line per commit)
watch 'git log --oneline -10'
# Diff stats
watch git diff --stat
|
Logs#
1
2
3
4
5
6
7
8
| # Last log lines
watch 'tail -5 /var/log/syslog'
# Error count
watch 'grep -c ERROR /var/log/app.log'
# Recent errors
watch 'grep ERROR /var/log/app.log | tail -5'
|
APIs and Services#
1
2
3
4
5
6
7
8
| # HTTP health check
watch 'curl -s localhost:8080/health'
# API response time
watch 'curl -s -w "%{time_total}\n" -o /dev/null http://localhost/api'
# Service status
watch systemctl status nginx
|
Database#
1
2
3
4
5
6
7
8
| # PostgreSQL connections
watch 'psql -c "SELECT count(*) FROM pg_stat_activity"'
# MySQL process list
watch 'mysql -e "SHOW PROCESSLIST"'
# Table row count
watch 'psql -c "SELECT count(*) FROM users"'
|
Quoting and Complex Commands#
For commands with pipes or special characters, quote the entire command:
1
2
3
4
5
6
7
8
| # Single quotes (preferred)
watch 'ps aux | grep nginx | wc -l'
# Double quotes (allows variable expansion)
watch "df -h | grep $MOUNT"
# Multiple commands
watch 'echo "=== Disk ===" && df -h && echo "=== Memory ===" && free -h'
|
Using with –exec#
For commands with their own arguments:
1
2
3
4
5
| # Without exec: may have quoting issues
watch ls -la /tmp
# With exec: cleaner
watch -x ls -la /tmp
|
Exit Conditions#
1
2
3
4
5
6
7
8
| # Exit when command fails
watch -e 'curl -f http://localhost/health'
# Beep on error (non-zero exit)
watch -b 'systemctl is-active myservice'
# Exit when output changes (use with diff)
watch -g 'cat /etc/passwd | md5sum'
|
With grep for filtering#
1
| watch 'dmesg | tail -20 | grep -i error'
|
1
| watch "free | awk '/Mem:/ {printf \"%.1f%%\n\", \$3/\$2*100}'"
|
With jq for JSON#
1
| watch 'curl -s localhost:8080/metrics | jq .requests_total'
|
Alternatives#
while loop#
1
2
3
4
5
6
| while true; do
clear
date
df -h
sleep 2
done
|
viddy (modern watch)#
1
2
3
4
5
6
| # Install
brew install viddy # macOS
go install github.com/sachaos/viddy@latest
# Use (better diff, time machine, etc.)
viddy -d df -h
|
entr (run on file change)#
1
2
3
4
5
| # Run command when files change
ls *.py | entr python test.py
# Clear screen and run
ls *.py | entr -c python test.py
|
Tips#
Disable Title for Clean Output#
1
| watch -t 'date +%H:%M:%S'
|
Use Color Output#
1
2
| watch -c 'ls --color=always'
watch -c 'grep --color=always ERROR /var/log/app.log | tail -10'
|
Precision Timing#
1
2
| # Exact intervals (compensates for command runtime)
watch -p -n 1 date +%s.%N
|
Redirect Output#
1
2
| # Can't redirect watch output directly, but can log the command
watch 'df -h | tee -a disk.log'
|
Quick Reference#
| Option | Purpose |
|---|
-n N | Interval in seconds |
-d | Highlight differences |
-t | No title/header |
-c | Interpret colors |
-e | Exit on error |
-b | Beep on error |
-g | Exit when output changes |
-x | Use exec instead of shell |
watch is deceptively simple. No dashboards, no configuration — just watch <command> and you have real-time monitoring. It’s the first tool I reach for when I need to see something change over time.
📬 Get the Newsletter
Weekly insights on DevOps, automation, and CLI mastery. No spam, unsubscribe anytime.