533 字
3 分钟
Linux `watch` 的 2 秒间隔,原来是“执行完再等 2 秒”

今天才注意到一个很容易被 watch 顶部那句 Every 2.0s 误导的细节:

Terminal window
watch some-command

watch 的默认间隔就是 2 秒。

但它默认的逻辑并不是:

0s 2s 4s 6s
| run | run | run | run

而更接近:

run command
wait command exits
sleep 2s
run command again

也就是说,如果命令本身执行需要 0.8 秒,那么两次启动之间大约是:

0.8s + 2.0s = 2.8s

如果命令需要 5 秒,那就大约每 7 秒才启动一次。

这不是猜测。procps-ng 的 watch(1) 手册对 -p, --precise 的描述已经把两种行为区分得很明确:默认情况下,下一次执行发生在上一次执行完成后的 interval 秒;加上 --precise 后,才按照上一次执行开始的时间计算周期。

源码里的主循环逻辑也很直接:

if (run_command(command, command_argv))
break;
if (precise_timekeeping) {
...
} else {
usleep(interval * USECS_PER_SEC);
}

也就是先同步执行完命令,普通模式随后直接 sleep(interval)

所以直接写:

Terminal window
watch some-command

并不代表:

每隔 2 秒启动一次 some-command

更准确的理解是:

每次 some-command 执行结束后,再等默认的 2 秒,然后开始下一次。

如果真正想要“每 2 秒一个时间点”这种更接近固定周期的行为,可以使用:

Terminal window
watch -p some-command

因为默认 interval 本来就是 2 秒,所以这里也不需要额外写 -n 2

假设命令运行 0.8 秒,那么 watch 会再等大约 1.2 秒,从而尽量保持:

0s 2s 4s 6s
| run | run | run | run

当然,如果命令自己就执行了 5 秒,而周期是 2 秒,watch 也不会并发启动多份命令。它仍然会等当前命令结束,只是下一次会尽量按照 precise 模式的时间计算方式继续运行。

所以这其实就是 scheduler 里很经典的两种语义:

普通 watch
fixed-delay
watch -p
fixed-rate / fixed-period

watch 顶部显示的 Every 2.0s,严格来说有点容易让人产生误解。默认行为其实是:

任务之间至少间隔 2 秒,而不是任务每隔 2 秒准时启动。

Linux `watch` 的 2 秒间隔,原来是“执行完再等 2 秒”
https://blog.lishuyu.app/posts/2026-09-07-linux-watch-default-2s-after-command-finishes/
作者
猫猫魔女
发布于
2026-09-07
许可协议
CC BY-NC-SA 4.0