cron 如何每周运行一次任务?
每周跑一次 cron 的写法:第五个字段填星期几(0/7=周日),如 0 0 * * 0;附 @weekly 简写、周一到周日对照表、时间字段详解与 FAQ。
把第五个字段(星期)设成目标星期几即可。例如每周日零点执行:
0 0 * * 0 /path/to/command
字段拆解
┌─────────── 分钟 (0-59) → 0:整点
│ ┌───────── 小时 (0-23) → 0:零点
│ │ ┌─────── 日 (1-31) → *:每天
│ │ │ ┌───── 月 (1-12) → *:每月
│ │ │ │ ┌─── 星期 (0-6,0=周日) → 0:只在周日
│ │ │ │ │
0 0 * * 0 /path/to/command
- 星期字段中 0 和 7 都表示周日,1=周一 …… 6=周六;多数实现也接受
sun、mon等缩写。 - 想周一凌晨 4 点半跑:
30 4 * * 1。 - 想每周多个日子跑:用逗号,如
0 0 * * 1,4(周一和周四)。
更简洁的写法:@weekly
多数 cron 实现支持宏:
@weekly /path/to/command
等价于 0 0 * * 0(每周日零点)。同类宏还有 @daily(0 0 * * *)、@hourly、@monthly、@reboot。
注意事项
- 周任务的"静默失败"周期长:一周才跑一次,写错了要等七天才发现。上线前手动把命令原样跑一遍验证。
- 输出要落盘:
>> /var/log/weekly-job.log 2>&1,否则报错只能烂在邮件 spool 里。 - 跨时区:cron 用系统本地时区,服务器时区改了任务时间跟着变。
观测云对照
周任务往往是备份、报表、清理这类"漏跑一周就是大事故"的作业。把任务输出统一采集到观测云,配一条"心跳式"监控器:周一凌晨检查过去 24 小时是否存在成功日志,没有就告警。任务没触发、脚本中途报错、机器宕机,三种情况一条规则全覆盖。
常见问题(FAQ)
Q:0 0 * * 0 和 0 0 * * 7 有区别吗?
A:没有,都表示周日。Vixie cron 及主流实现同时接受 0 和 7。团队内部统一用一种即可。
Q:为什么周日任务没跑,日志里找不到记录?
A:先 grep CRON /var/log/syslog(Ubuntu)或看 /var/log/cron(CentOS)确认 cron 是否触发;再检查脚本本身输出是否重定向到了你能找到的地方。
Q:能按"每隔一周"(双周)跑吗?
A:cron 表达式做不到,需要命令里加判断,如 [ $(( $(date +\%V) \% 2 )) -eq 0 ] && cmd 按周数奇偶过滤,或改用 systemd timer 的日历表达式。