Cron 表达式速查表 - Cron 定时任务配置常用命令大全
写 Cron 表达式不难,难的是表达式看起来完全正确却不执行,而绝大多数原因并不在表达式里。这张表从五段格式、特殊符号、时间宏讲到常用示例,再补上环境变量、权限管理、故障排查三组,正好覆盖从「写出来」到「真跑起来」。高频陷阱都在表里点出:cron 的环境与交互 shell 完全不同,PATH 通常只剩几个系统目录,所以命令找不到要在脚本内显式 export PATH 或直接写绝对路径(node、python 尤其如此);输出默认走本地邮件,多数机器没配 MTA,失败信息直接蒸发,所以必须 2>&1 进日志;日和周同时指定是「或」不是「与」,0 0 13 * 5 是每月 13 号或每周五。排查先看日志有没有产生:没有就是环境或权限问题,日志有但内容为空通常是路径或重定向写错。
典型使用场景
面向需要让脚本定时跑起来的开发者。crontab 的失败几乎都源于两个环境差异而非语法:cron 的 PATH 极精简导致「手动能跑定时跑不了」,以及默认输出发邮件导致磁盘/邮箱被日志塞满。本表按「表达式 → 特殊符号 → 时间宏 → 环境变量 → 权限 → 排查」组织,把这两类坑放在最显眼的位置,并给出调试用的最小可复现写法。
表达式格式 6
* * * * * command分钟 (0-59)小时 (0-23)日 (1-31)月 (1-12)周 (0-7)特殊符号 6
**/NA-BA,B,CA-B/NL特殊时间宏 6
@reboot@yearly / @annually@monthly@weekly@daily / @midnight@hourly常用示例 8
*/5 * * * * command0 * * * * command0 3 * * * command0 0 * * 1 command0 0 1 * * command0 9-18 * * 1-5 command*/30 * * * * command0 0 * * 0 command环境变量 6
SHELL=/bin/bashPATH=/usr/local/bin:/usr/bin:/binMAILTO="admin@example.com"MAILTO=""HOME=/home/userCRON_TZ=Asia/Shanghai权限管理 6
/etc/cron.allow/etc/cron.denycrontab -u user -ecrontab -u user -lcrontab -u user -rls /var/spool/cron/故障排查 5
grep CRON /var/log/sysloggrep cron /var/log/cronsystemctl status crondsystemctl status cron* * * * * echo test >> /tmp/cron-test 2>&1参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
分钟(0-59) | 每小时内的第几分钟 | 0 * * * * command |
小时(0-23) | 一天内第几小时,0 为午夜 | 0 3 * * * command |
日(1-31) | 每月第几天 | 0 0 1 * * command |
月(1-12) | 每年第几月 | 0 0 * 6 * command |
周(0-7) | 0 和 7 都是周日 | 0 0 * * 1 command |
*/N | 每 N 个单位一次 | */5 * * * * command |
A-B/N | 范围内步进 | 0 9-18 * * 1-5 command |
A,B,C | 枚举多个值 | 0 0 * * 1,3,5 |
@reboot | 开机执行一次 | @reboot /opt/start.sh |
@daily / @hourly | 每天 / 每小时一次 | @daily /opt/backup.sh |
PATH=... | cron 默认 PATH 很精简,需显式声明 | PATH=/usr/local/bin:/usr/bin:/bin |
MAILTO="" | 关闭邮件通知 | MAILTO="" |
CRON_TZ | 指定时区 | CRON_TZ=Asia/Shanghai |
重定向 | 输出写日志而非发邮件 | command >> /var/log/job.log 2>&1 |
易错点与避坑指南
现象手动执行脚本正常,放进 crontab 却报 command not found。
原因cron 的 PATH 极精简,不含 /usr/local/bin 等交互式 shell 里配置的路径。
处置在 crontab 顶部显式写 PATH=...;或全部使用绝对路径。
现象node / python 脚本在 cron 里执行到一半失败。
原因conda / pyenv / nvm 这类环境靠交互式 shell 的初始化脚本设置 PATH,cron 下不会加载。
处置在脚本开头写全解释器绝对路径,或在 crontab 里直接 source 对应的初始化脚本。
现象任务没有任何输出,也看不到失败原因。
原因cron 把输出发邮件,而服务器往往没配 MTA,输出被直接丢弃。
处置显式重定向:command >> /var/log/job.log 2>&1,或设 MAILTO="" 关闭通知。
现象日志目录被撑满,或邮件里塞满重复内容。
原因输出长期累积没有轮转。
处置重定向到日志文件并配 logrotate;不需要输出时用 command > /dev/null 2>&1。
现象以为某天会执行,实际没跑。
原因日和周同时指定时是「或」不是「与」,且当月天数不足时会跳过。
处置记住 0 0 13 * 5 表示 13 号或每周五;月天数不足的日子不会执行,用 L 或前一天兜底。
现象cron 里写的相对路径找不到文件。
原因cron 的工作目录是用户 HOME,不是你 cd 到的目录。
处置crontab 中用 cd /opt/app && command,或全部写绝对路径。
现象删除用户 crontab 后想恢复,但已无备份。
原因crontab -u user -r 会直接删除全部条目且不提示。
处置删除前先 crontab -u user -l > /root/crontab-user.bak 备份;改用 crontab -e 逐条编辑更安全。
现象改完 crontab 不生效。
原因多数情况下保存即生效,但脚本本身没有执行权限。
处置无需重启 cron 服务;确认脚本 chmod +x,或在命令里用 bash /path/script.sh 显式调用。
排障路径
1先用最小任务验证 cron 是否工作
* * * * * echo test >> /tmp/cron-test 2>&1等一分钟看文件是否有内容;有则 cron 正常,问题在原脚本。
2检查 cron 服务是否在跑
systemctl status crond || systemctl status cronRHEL/CentOS 是 crond,Debian/Ubuntu 是 cron,名字不同。
3查看 cron 的执行日志
grep CRON /var/log/syslogDebian/Ubuntu 记在 syslog;RHEL/CentOS 改为 grep cron /var/log/cron。
4查看当前用户的 crontab
crontab -lroot 编辑他人用 crontab -u user -l / -e,注意备份后再删。
5确认解释器脚本的绝对路径
which node && which python3把输出的绝对路径写进 crontab,绕开 PATH 与环境初始化问题。
命令示例
调试:先确认 cron 链路本身是通的
* * * * * echo "cron ok $(date)" >> /tmp/cron-test 2>&1不要一上来就调试正式任务。先用这条每分钟写一行并重定向 stderr——cron 最常见的故障是 PATH 太精简导致找不到命令,输出没重定向就什么都看不到。确认链路通了再换正式任务。
每天凌晨 3 点执行并记录日志
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1顶部必须显式声明 SHELL 与 PATH,否则 cron 的极简环境会让脚本找不到相对路径的命令。日志重定向到文件比用 MAILTO 发邮件更便于事后排查。
用 systemd timer 替代(推荐)
systemctl list-timerssystemd timer 能看到下次执行时间与上次执行时间,排查「任务到底跑没跑」比翻日志直接得多;输出也能进 journalctl 而不是邮件。
输出
NEXT LEFT LAST PASSED UNIT Tue 2026-09-30 03:00:00 CST 9h left Mon 2026-09-29 03:00:00 CST 23h ago backup.timer Tue 2026-09-30 00:30:00 CST 6h left Mon 2026-09-29 00:30:00 CST 23h ago logrotate.timer
常见坑与注意事项
- cron 的默认 PATH 极简,手动能跑的命令在 cron 里常找不到;务必在 crontab 顶部声明 PATH 与 SHELL。
- 任务输出未重定向时,报错会走 MAILTO 或被丢弃;始终加 >> log 2>&1。
- 日字段与周字段同时为 * 时任务会在两者都匹配的日子触发,某些月份会执行两次,务必核对预期次数。
- crontab -u user -r 会删除该用户全部定时任务且无确认,执行前先用 -l 导出备份。
- cron 不检查命令是否存在,脚本路径没写绝对权限或 shebang 有误时任务静默失败。
提示
- cron 环境变量与交互 shell 不同,PATH 可能不完整,命令找不到时在脚本里显式 export PATH。
- 命令建议用绝对路径,避免 cron 环境找不到可执行文件,尤其是 node/python 等解释器。
- 输出默认会发邮件,建议重定向到日志文件,如 command >> /var/log/job.log 2>&1。
- 周和日同时指定时是"或"关系不是"与"关系,0 0 13 * 5 表示每月 13 号或每周五执行。
- 修改 crontab 后无需重启 cron 服务,保存即自动生效,但脚本本身需要确保有执行权限。
- cron.allow 和 cron.deny 同时存在时只看 allow,两者都不存在时取决于发行版默认策略。
- 用 crontab -l 后确认条目里的行尾没有多余空格或 CRLF 换行符,这两种都会让表达式整体不生效且没有任何报错。
- 测试时间表达式时把分和时临时改成 * * * * *,跑通后再改回真实频率,比等真实时间点省下几小时。
- 写 */5 这样的步长表达式时注意它是从区间左端起算而非从整点算起,日志时间与预期不符往往就是这个原因。
常见问题
Cron 任务表达式看起来对却完全不执行,最可能是什么原因?
九成是默认 PATH 太精简——cron 的环境变量极简,手动能跑的命令在 cron 里找不到。解决办法是在 crontab 顶部显式声明 PATH 和 SHELL。其次是没有做输出重定向,报错被丢弃你看不到。建议调试时先加一条 * * * * * echo test >> /tmp/cron-test 2>&1 每分钟写一行,确认链路通了再改正式任务。
0 0 * * 1 和 0 0 1 * * 分别代表什么?
五个字段依次是「分 时 日 月 周」。0 0 * * 1 是每月任意日但限定周一、0 点执行,即每周一零点;0 0 1 * * 是每月 1 日零点执行,即按月。容易出错的是日和周的叠加——两者都会被匹配时会导致任务在某些月份执行两次,需要留意预期次数。
crontab 的环境变量和我在终端里看到的不一样怎么办?
这是预期行为,cron 用的是极简环境,不读你的 .bashrc 或 .zshrc。解决方式是在 crontab 文件顶部手动声明所需变量,例如 PATH=/usr/local/bin:/usr/bin:/bin 和 SHELL=/bin/bash。另一个常用技巧是用 MAILTO="" 关闭输出邮件,避免任务频繁执行时邮箱被刷屏。
如何确认定时任务到底有没有被执行?
先看 cron 自身的日志:Debian/Ubuntu 是 grep CRON /var/log/syslog,RHEL/CentOS 是 grep cron /var/log/cron;再确认 cron 服务在跑,systemctl status cron 或 systemctl status crond。若任务本身是 systemd timer 管理的,则用 systemctl list-timers 看它是否启用、下次执行时间是什么。
* / 5 和 0 * * * * 分别代表什么频率?
*/5 * * * * 是「从 0 开始每 5 个单位执行一次」,在分钟字段上就是每 5 分钟一次。0 * * * * 是分钟固定为 0,即每小时整点执行一次。两者常用于日志轮转和定时备份,写的时候记得配套设置 PATH,否则脚本里调用相对路径的命令会失败。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。