当前位置:首页>Linux>每天学一个Linux命令系列(40):watch - 实时监控命令输出,不用反复敲

每天学一个Linux命令系列(40):watch - 实时监控命令输出,不用反复敲

  • 2026-10-11 06:09:32
每天学一个Linux命令系列(40):watch - 实时监控命令输出,不用反复敲
运
运维少年 · 科技观察

这个命令是干啥的

做运维监控,很多情况需要反复看同一个命令的输出。比如:

  • ·磁盘空间还剩多少,过一会儿再看有没有涨
  • ·进程有没有挂掉,过几秒再刷一次
  • ·日志里有没有新报错,等着看它出来

刚开始我都是手动敲,过一会儿 df -h,再过一会儿 ps aux | grep java。后来发现 watch 这个命令,感觉打开了新世界的大门。它帮你自动反复执行同一命令,还能用高亮标出变化的部分。

简单说:watch 就是你跟命令行之间的"自动刷新按钮"。

基本用法(3分钟上手)

最简单的用法

# 每隔2秒执行一次 ls,默认间隔就是2秒
watch ls -la

屏幕会分成两部分:
- 顶部第一行:显示刷新间隔和执行命令
- 下面的内容:命令输出,每隔2秒刷新一次

按 Ctrl+C 退出。

指定刷新间隔

# 每隔1秒刷新一次
watch -n 1 df -h

# 每隔5秒刷新一次
watch -n 5 free -m

高亮变化的内容

这是 watch 最实用的功能:

# 用 -d 高亮出两次执行之间变化的部分
watch -d -n 1 free -h

跑了之后你会看到,内存数字变化的地方会自动高亮,一眼就能看到"哪变了"。

保留命令输出颜色

很多命令(如 ls --color、grep --color)的输出自带颜色,但 watch 默认不保留颜色:

# 加上 -c 参数保留颜色输出
watch -c -n 2 'ls -la --color=auto'

进阶骚操作

持续监控磁盘空间

# 监控所有挂载点的磁盘使用率
watch -d -n 5 'df -h | grep -v tmpfs'

解释一下:-d 高亮变化的百分比,-n 5 每5秒刷新,grep -v tmpfs 过滤掉tmpfs虚拟文件系统,只看真正的磁盘。

监控进程变化

# 每隔2秒监控 Nginx 进程数量
watch -d -n 2 'ps aux | grep nginx | grep -v grep | wc -l'

# 监控某个端口是否在监听
watch -n 3 'ss -tlnp | grep :8080'

# 监控 MySQL 连接数
watch -d -n 5 'mysql -u root -p"password" -e "show processlist;" 2>/dev/null | wc -l'

监控网络连接

# 实时监控连接状态
watch -d -n 2 'netstat -ant | grep -E "ESTABLISHED|TIME_WAIT" | head -20'

# 监控特定IP的连接
watch -d -n 1 'ss -ant | grep 192.168.1.100'

监控日志尾部

# 相当于带自动刷新的 tail -f
watch -d -n 2 'tail -20 /var/log/nginx/access.log'

# 监控错误日志
watch -d -n 3 'tail -n 20 /var/log/syslog | grep -i error'

注意:watch 是清屏重新执行,不是像 tail -f 那样追加。数据量大的日志用 tail -f 更合适,watch 适合看结构化的统计输出。

管道和引号的处理

复杂的命令需要用引号包起来:

# 单条简单命令可以不用引号
watch df -h

# 包含管道、变量的命令,必须用引号
watch 'ps aux | grep nginx | grep -v grep | wc -l'

# 包含环境变量的,建议用双引号
watch "echo '当前用户:' \$USER"

# 用单引号可以防止变量展开
watch 'echo "当前时间: $(date)"'

精确到微秒的刷新

# 每隔0.5秒刷新一次
watch -n 0.5 'date +%H:%M:%S.%N'

执行长命令时注意

watch 默认在当前命令执行完毕后才开始计算下个间隔。如果命令本身要跑3秒,-n 2 实际间隔可能不是2秒:

# 这条命令本身要跑3秒
watch -n 2 'sleep 3; df -h'
# 实际执行间隔至少3秒,不是2秒

-p(precise)参数可以让固定间隔执行,但命令超时了可能重叠:

# 尝试精确2秒间隔执行(即使命令超时)
watch -p -n 2 'df -h'

避坑指南

坑1:引号问题(最常见!)

这是我踩过最多的坑:

# 这么写会报错!因为 shell 先解释了管道
watch ps aux | grep nginx

# 正确写法:用引号包起来
watch 'ps aux | grep nginx'

不加引号时,shell会把 watch ps aux 当作完整命令,然后 | grep nginx 是对 watch 的输出做过滤,而不是过滤 ps 的输出。

坑2:特殊字符被提前解析

# 这个不行,$ 被 shell 提前替换了
watch "echo $PATH"

# 正确:用单引号阻止变量展开
watch 'echo $PATH'

单引号里所有字符都是字面量,双引号仍然会展开变量。复杂的命令建议一律用单引号。

坑3:命令中有交互提示

# 如果命令中途要等输入,watch 会卡住
watch 'rm -i /tmp/*'

# 更好的是用非交互版本
watch 'rm -f /tmp/*'

坑4:大量输出导致界面闪烁

# 这样输出刷屏,什么都看不清
watch 'find / -name "*.log"'

# 限制输出行数
watch 'find / -name "*.log" 2>/dev/null | tail -20'

坑5:性能问题

watch -n 1(每秒刷一次)看起来爽,但如果是查数据库、查大日志的生产服务器,频繁执行会产生不必要的负载。特别是在白天业务高峰期,别开太多 watch 窗口。

监控类的 watch 间隔设到5-10秒足够了,想看精细变化用专门的监控工具。

实战场景(重点!结合真实运维场景)

场景1:发布时观察状态

上线发布新版本时,需要观察各个指标是否正常:

# 第一个终端:看服务进程
watch -d -n 2 'ps aux | grep java | grep -v grep'

# 第二个终端:看日志报错
watch -d -n 3 'tail -10 /var/log/app/error.log | grep -i "exception\|error\|timeout"'

# 第三个终端:看端口监听
watch -d -n 1 'ss -tlnp | grep -E ":8080|:443"'

我一般开个 tmux 分屏,同时盯着这几个窗口。一旦发现有进程挂了或者报错突增,马上回滚。

场景2:磁盘空间预警

写个"三合一"监控命令:

# 同时监控磁盘、内存、CPU
watch -d -n 5 '
echo "=== 磁盘 ===" && df -h / /data /backup 2>/dev/null
echo ""
echo "=== 内存 ===" && free -h
echo ""
echo "=== 负载 ===" && uptime && echo "进程数:" && ps aux | wc -l
'

放到一个单独的终端窗口里,一边干活一边瞟一眼,比一个个命令敲快多了。

场景3:等待某个条件出现

比如在等一个文件生成、等某个端口开放、等某个进程启动:

# 等脚本生成报告文件
watch -n 2 'ls -la /tmp/report_*.csv 2>/dev/null'

# 等服务端口开放
watch -n 1 'curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health'

# 等网卡接收流量
watch -d -n 2 'ip -s link show eth0 | grep "RX packets\|TX packets"'

一旦看到预期的变化,就说明条件满足了。

场景4:watch + crontab 组合

watch 管"实时观察",crontab 管"定期执行",两者互补。

先写个脚本做检查:

#!/bin/bash
# /usr/local/bin/check_disk.sh
# 检查磁盘使用率
DISK_USAGE=$(df / | tail -1 | awk "{print \$5}" | sed 's/%//')
if [ $DISK_USAGE -gt 85 ]; then
    echo "磁盘使用率: $DISK_USAGE !!!"
else
    echo "磁盘使用率: $DISK_USAGE% 正常"
fi

crontab 定期跑,把结果写文件:

# crontab 每5分钟检查一次,写结果到临时文件
*/5 * * * * /usr/local/bin/check_disk.sh > /tmp/disk_status 2>&1

然后 watch 读这个文件:

# 另一个终端 watch 读结果文件
watch -d -n 10 'cat /tmp/disk_status'

这样 crontab 负责后台定时检查,watch 让你实时看到最新结果。

场景5:排查网络连接异常

有次服务器出现大量 TIME_WAIT 连接,用 watch 实时追踪:

# 各个状态的连接数
watch -d -n 2 '
echo "=== 连接状态统计 ==="
netstat -ant | awk "{print \$6}" | sort | uniq -c | sort -rn
echo ""
echo "=== TOP10 远程地址 ==="
netstat -ant | grep ESTABLISHED | awk "{print \$5}" | cut -d: -f1 | sort | uniq -c | sort -rn | head -10
'

同一个窗口里同时看到连接分布和来源IP TOP10,排查问题非常直观。

今日作业

1. 打开两个终端,在第一个终端里运行:
  `bash
  watch -d -n 2 'ps aux | grep "$$" | grep -v grep'
  `

2. 在第二个终端里执行一些简单命令(sleep 5, ls -R /tmp 等等)

3. 观察第一个终端里的进程变化

4. 再试试这个组合监控命令:
  `bash
  watch -d -n 3 '
  echo "进程数: $(ps aux | wc -l)"
  echo "内存: $(free -m | awk "/Mem:/{print \$3\"M / \"\$2\"M\"}")"
  echo "磁盘: $(df -h / | tail -1 | awk "{print \$5}")"
  '
  `

5. 在第二个终端里打开 Chrome 或者启动一个程序,观察监控数据的变化

做完后,说说你在不同场景下会设置多少秒的刷新间隔,以及为什么。

E N D

运维少年 · 科技观察

最新文章

随机文章