cron 如何每 5 秒、10 秒或 30 秒运行一次?
cron 最小粒度是 1 分钟,秒级调度要用变通方案:分钟级任务内嵌 sleep 循环、或 systemd timer 的 OnUnitActiveSec;附完整脚本示例与 FAQ。
cron 原生做不到——它每分钟才扫一次 crontab,最小调度粒度就是 1 分钟。 秒级需求的标准变通是:让 cron 每分钟启动一个脚本,脚本内部用 sleep 循环按 N 秒间隔多次执行。
方案一:sleep 循环(最常用)
每 5 秒一次——脚本版(script.sh):
#!/bin/bash
i=0
while [ $i -lt 12 ]; do # 1 分钟 = 12 个 5 秒间隔
/command/to/run &
sleep 5
i=$(( i + 1 ))
done
crontab 里每分钟拉起这个脚本:
* * * * * /path/to/script.sh
每 10 秒:循环 6 次、sleep 10;每 30 秒:循环 2 次、sleep 30。
要点:
- 命令后加
&后台执行,避免命令本身的耗时把间隔拖歪。 - 若命令耗时不稳定,宁可让循环次数略少于理论值,防止脚本跨过整分钟与下一轮 cron 实例重叠(或用
flock防重入)。
方案二:systemd timer(更干净)
秒级调度其实是 systemd timer 的强项:
# /etc/systemd/system/myjob.timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=10s
[Install]
WantedBy=timers.target
# /etc/systemd/system/myjob.service
[Service]
Type=oneshot
ExecStart=/path/to/command
systemctl enable --now myjob.timer 后每 10 秒触发一次,日志直接进 journal,比 sleep 循环可靠、可观测性好得多。
先想清楚:真的需要秒级吗?
每 5 秒执行一次往往意味着应该换个工具:
- 需要持续运行的采集/消费任务 → 写成常驻进程(systemd service 带
Restart=always)。 - 事件驱动 → 消息队列、inotify 之类,而不是轮询。
观测云对照
秒级轮询任务的失败特征是高频率、难肉眼盯。观测云里给这类任务配监控器时,把检测窗口设为 1-2 分钟、用"日志数量低于阈值"条件——任何一轮没跑都会立刻告警;脚本日志统一由 DataKit 采集,还能顺带统计每轮耗时趋势,发现"越跑越慢"这类渐变故障。
常见问题(FAQ)
Q:cron 表达式支持秒字段吗?
A:标准 Vixie cron 不支持(五字段,最小分钟)。某些扩展实现(Quartz、Spring 的 cron、部分容器调度器)有六字段含秒的格式,但那不是系统 crontab。
Q:sleep 循环里命令执行超过间隔会怎样?
A:如果命令加了 &,下一轮照常启动,会出现并发实例;不加 &,间隔会被拉长。两种情况都可能踩坑,重要任务建议上 systemd timer。
Q:多个秒级任务会互相干扰吗?
A:会。每分钟的 cron 实例叠加上一轮未结束的进程,负载可能雪崩。同一台机器上的秒级任务尽量合并到一个脚本里串行调度。