watch无法直接监控多个文件,需结合stat、md5sum等命令周期性检查;高频或生产环境应改用inotifywait或journalctl/tail-F。

watch 本身不支持直接监控多个文件,得靠 shell 组合实现
watch 的核心逻辑是定期执行命令并刷新输出,它自己没有文件变更监听能力,更不识别通配符或目录递归。想“监控多个文件”,本质是让 watch 周期性运行一个能汇总多个文件状态的命令,比如 ls -l、stat 或 md5sum。
常见错误是直接写 watch ls file1 file2 —— 这只能看到文件列表,但时间戳变化不明显;或者用 watch cat file1 file2,一旦文件含二进制内容或换行混乱,输出会错位甚至阻塞。
- 推荐用
stat按固定格式输出修改时间:watch -n 2 'stat -c "%n %y" file1 file2 2>/dev/null' - 若文件名含空格或特殊字符,必须用数组 +
for循环,不能依赖 word splitting -
-n 2表示每 2 秒执行一次,太短(如-n 0.5)易触发系统负载抖动,尤其在 NFS 或老旧磁盘上
用 inotifywait 替代 watch 更可靠,尤其对高频变更
当文件被频繁写入(如日志轮转、调试输出),watch 的轮询机制会漏掉中间状态,且无法区分“修改”“创建”“删除”。这时应切换到事件驱动工具:inotifywait(来自 inotify-tools 包)。
它能监听多个路径,并支持通配符(需用 -m 持续监听 + --include 过滤):
inotifywait -m -e modify,create,delete_self /path/to/dir --include '\.(log|conf)$'
注意点:
-
inotifywait默认只监听一级目录,子目录需加-r,但深度大时 fd 占用高,建议限定层级或用--exclude排除node_modules类目录 - 输出是纯文本流,不适合直接丢给
watch;如需带时间戳和高亮,可管道接awk '{print strftime(), $0}' | grep --color=always - 某些容器环境(如 rootless Podman)默认禁用 inotify,会报
Failed to watch,需检查/proc/sys/fs/inotify/max_user_watches
watch + diff 实现“变化高亮”,但要注意文件大小和编码
想直观看出哪一行变了,可用 watch 调用 diff 对比前后快照。典型做法是先保存 baseline,再周期性比对:
echo "file1 file2" | xargs md5sum > /tmp/sum.bak; watch -n 3 'echo "file1 file2" | xargs md5sum | diff -u /tmp/sum.bak -'
这比单纯看 ls 时间戳更敏感,但有硬伤:
- 大文件(>10MB)反复算
md5sum会吃 CPU,改用sha256sum更慢,不如用stat -c "%Y" file看 inode 修改时间(秒级精度已够用) - 如果文件是 Windows 编码(CRLF)或含 ANSI 转义符,
diff输出可能乱码;加iconv -f gbk -t utf8或先dos2unix预处理 -
diff -u输出含上下文,容易撑满终端;加| head -20截断,但会丢失末尾变化
真正要监控生产日志,别硬套 watch,优先用 journalctl 或 tail -F
日常调试用 watch 快速扫一眼还行,但监控服务日志(如 /var/log/nginx/access.log)时,轮询方式完全不适用:文件可能被 logrotate 切走、硬链接失效、权限突变导致读取失败。
正确姿势是:
- systemd 服务日志统一用
journalctl -u servicename -f,天然支持按优先级过滤、时间范围回溯、JSON 输出 - 传统日志文件用
tail -F(大写 F),它能自动跟踪 rename 后的新文件,比watch tail稳定得多 - 若必须用
watch,至少加--color=always和-d(高亮差异),并用2>/dev/null屏蔽 Permission denied 报错,否则屏幕会被错误刷屏
最常被忽略的是信号处理:watch 在收到 SIGINT(Ctrl+C)时会杀掉子进程,但某些命令(如未加 -q 的 inotifywait)会残留后台任务,下次运行前得手动 pkill inotifywait。

















