Cron 定时任务速查表 - Cron 定时任务配置命令大全

定时任务的语法只有五个字段加三个符号,十分钟就能学会;真正让人卡住的是它跑起来之后的环境和归属。cron 的执行环境不是你的终端环境:PATH 通常只有三条目录,shell 里 alias 和 pyenv、nvm 带来的路径一个都没有,于是任务"没报错但没效果"或干脆 command not found。第二个坑是用户:放进 /etc/cron.d/ 的按文件属主跑,放进 crontab 的按该用户跑,同一条命令换位置结果就不同。这张表把时间格式与特殊字符串(@daily、@reboot)、系统级目录、用户级 crontab 命令、环境变量、日志重定向和排查顺序归在一起。什么时候该翻它:任务"确认被调用了但产物没有",先 grep syslog 确认调度发生,再 systemctl status cron 确认守护进程,两处都空说明 crond 没起

系统与运维·共 43 条命令·最后更新 2026-07-21
cron定时任务crontab自动化

典型使用场景

面向必须让某件事「在没人盯着的时候也发生」的运维与后端工程师,具体是四类场景。一是备份与清理:凌晨 2 点跑 backup.sh、每月 1 号跑 cleanup.sh、日志交给 logrotate。二是健康探测与告警:*/5 * * * * curl -s https://example.com/health,比外部拨测系统更早发现本机进程挂掉。三是业务节律:工作日 9 点发日报(0 9 * * 1-5)、每周日 0 点出周报(0 0 * * 0),这类任务最容易被时区和「周日的 0 与 7」弄错。四是自愈:@reboot 在机器重启后拉起常驻进程,替代裸写 rc.local。真正掌握 cron 的关键不在记格式,而在三件事:cron 的环境变量极简(没有 PATH、没有你的 shell 交互配置),输出默认走 MAILTO 所以「脚本没跑但你没收到任何东西」是常态,时区取决于系统 TZ 而不是你的本地设置。

时间格式与特殊字符 7

* * * * * command
格式:分 时 日 月 周
*/15 * * * *
每 15 分钟执行(步进)
0 */2 * * *
每 2 小时执行
0 18 * * 0-6
每天 18:00 执行(0-6 范围)
10 2 * * 6,7
周六日 2:10 执行(逗号列表)
0 0 * * 0
每周日午夜执行
0 0 1 * *
每月 1 号午夜执行

特殊字符串 6

@reboot
系统启动时执行一次
@hourly
每小时(同 0 * * * *)
@daily / @midnight
每天午夜(同 0 0 * * *)
@weekly
每周日午夜(同 0 0 * * 0)
@monthly
每月 1 号午夜(同 0 0 1 * *)
@yearly / @annually
每年 1 月 1 日(同 0 0 1 1 *)

系统级 cron 6

/etc/crontab
系统主 crontab 文件,格式比用户级多一列用户名
/etc/cron.d/
存放独立的 cron 任务文件,格式同 /etc/crontab
/etc/cron.hourly/
每小时执行的脚本目录
/etc/cron.daily/
每天执行的脚本目录
/etc/cron.weekly/
每周执行的脚本目录
/etc/cron.monthly/
每月执行的脚本目录

用户级 crontab 命令 7

crontab -e
编辑当前用户的 crontab
crontab -l
列出当前用户的定时任务
crontab -r
删除当前用户的所有定时任务
crontab -ri
删除前确认提示
crontab -u user -e
root 编辑指定用户的 crontab
crontab -u user -l
查看指定用户的定时任务
echo "@reboot echo hi" | crontab
管道方式快速设置任务

环境变量配置 6

SHELL=/bin/bash
指定 cron 执行命令时使用的 shell
PATH=/usr/local/bin:/usr/bin:/bin
设置命令搜索路径,cron 默认 PATH 很精简
MAILTO="admin@example.com"
任务输出通过邮件发送给指定地址
MAILTO=""
关闭邮件通知,不发送任何输出
HOME=/root
设置执行时的 HOME 目录
CRON_TZ=Asia/Shanghai
设置 cron 使用的时区

常用示例 6

0 2 * * * /path/backup.sh
每天凌晨 2 点执行备份脚本
*/5 * * * * curl -s https://example.com/health
每 5 分钟健康检查
0 9 * * 1-5 mail -s "Report" team@example.com
工作日 9 点发送邮件
0 0 1 * * /path/cleanup.sh
每月 1 号清理临时文件
30 3 * * * /usr/bin/logrotate /etc/logrotate.conf
每天 3:30 轮转日志
0 0 * * 0 /path/weekly-report.sh >> /var/log/report.log 2>&1
每周日生成报告并记录日志

调试与排查 5

grep CRON /var/log/syslog
查看 Debian/Ubuntu 的 cron 执行日志
grep cron /var/log/cron
查看 RHEL/CentOS 的 cron 执行日志
date
确认系统时区是否正确,cron 按服务器时区执行
systemctl status cron
检查 cron 服务是否正常运行
* * * * * echo test >> /tmp/cron-test 2>&1
调试:每分钟写一行测试 cron 是否工作

参数矩阵

参数作用示例
* * * * *五个字段分别是 分 时 日 月 周,每分钟执行一次,是验证 cron 是否生效的标准探针* * * * * command
*/15 * * * *步长语法,分字段可用;「分」用 */15 表示每 15 分钟,比写四条 */5 更不易漏*/15 * * * *
0 */2 * * *小时字段用步长表示每 2 小时一次;注意这是 0,2,4…22 点,不是「每两小时从当前时刻起算」0 */2 * * *
0 18 * * 0-6用范围列举多天,逗号隔开;字段取值为 0-6(周日可用 0 或 7)0 18 * * 0-6
10 2 * * 6,7逗号列举多个取值,周六周日的 02:10;比写两条规则更不容易出现重复或漏跑10 2 * * 6,7
0 0 1 * *「日」字段取 1,表示每月 1 号零点;月度任务的常用写法0 0 1 * *
@reboot开机后执行一次,替代 rc.local,是最省事的「重启后自动拉起」方案@reboot
@hourly / @daily / @weekly / @monthly预设宏,分别等价于 0 * * * *、0 0 * * *、0 0 * * 0、0 0 1 * *;@midnight/@annually 是同义别名@daily
SHELL=/bin/bash指定执行命令所用的 shell;不写就用 /bin/sh,而 sh 不认 source、[[ ]]、pipefailSHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bincron 的 PATH 极简,不含 nvm、pyenv、homebrew 路径,node/python 等命令常因此 not foundPATH=/usr/local/bin:/usr/bin:/bin
CRON_TZ=Asia/Shanghai为单个 crontab 指定时区,优先于系统 TZ;跨时区团队里这是唯一可靠做法CRON_TZ=Asia/Shanghai
MAILTO=""把 cron 的输出投递清空,避免每次执行都往邮箱发一封空邮件MAILTO=""
crontab -e / crontab -l编辑与列出当前用户的 crontab;改完必须 crontab -e 保存才会被重新加载crontab -e
crontab -r / crontab -ri-r 直接删除全部 crontab 且不确认,-ri 才会交互确认;误用 -r 的后果无法撤销crontab -ri
crontab -u user -e / -l以 root 身份管理其他用户的 crontab,vip 与 sudo 用户的任务只能这样改crontab -u user -l
/etc/crontab 与 /etc/cron.d/系统级位置;/etc/cron.d/ 下的文件必须以非登录用户为属主且权限 644,且需要用户名字段/etc/crontab
>> /var/log/report.log 2>&1把标准输出与错误输出重定向进文件,是排查「cron 到底跑了没」最有效的手段0 0 * * 0 /path/weekly-report.sh >> /var/log/report.log 2>&1

易错点与避坑指南

现象crontab -e 里写好的任务手动执行正常,到点却完全不跑,且没有任何报错。

原因五字段写错位置(比如把月份写在最前面)或分隔符用了多个空格/制表符混排,cron 静默忽略整行;也可能是环境差异——交互 shell 有 PATH 而 cron 没有。

处置先加一行 * * * * * echo test >> /tmp/cron-test 2>&1 验证调度器本身,通了再排查业务行;同时在 crontab 顶部显式写 SHELL 与 PATH。

现象在 macOS 上设的凌晨 2 点任务,实际在下午某个时间才执行。

原因cron 按系统本地时区解释字段,笔记本/服务器时区与预期不一致;macOS 上 Laptop 睡眠期间任务会被推迟到唤醒后补跑。

处置用 date 确认系统时区,并在 crontab 里加 CRON_TZ=Asia/Shanghai 显式声明,与 date 输出对照确认。

现象以为 0 0 * * 7 是「每周日」,结果周日的任务和周日的其它任务跑重了或根本没跑。

原因cron 的周字段 0 与 7 都表示周日,写 7 与写 0 等价;更常见的是把「周日」误解成 1(那是周一)。

处置统一用 0 表示周日,写 0 0 * * 0,需要周六周日就写 0 0 * * 6,0。

现象脚本里调用 node / python / gcloud 报 command not found,而终端里同样的命令没问题。

原因cron 的 PATH 只有 /usr/bin:/bin,nvm、pyenv、homebrew、asdf 装出来的二进制都不在其中。

处置在 crontab 顶部写全 PATH,或直接在规则里调用绝对路径(例如 /usr/local/bin/node),最稳的是包一层 . /path/to/env.sh。

现象用 crontab -r 清理测试任务,第二天发现整份生产 crontab 全没了。

原因crontab -r 不做任何确认,直接删除当前用户的全部任务,且不保留备份文件。

处置养成用 crontab -ri 的习惯;重要任务用 crontab -l > ~/crontab.bak 先备份,再做增删。

现象把日志清理任务写进 crontab 后日志没被清,反而生成了一堆 0 字节文件。

原因logrotate 依赖 /etc/logrotate.conf 里的状态文件与运行用户,直接在 cron 里手工调 logrotate 会绕过轮转判断,重复轮转或路径写错。

处置交给 logrotate 自身的 timer/cron 机制,规则里用 30 3 * * * /usr/bin/logrotate /etc/logrotate.conf 并确保脚本内 exit 0。

现象在 /etc/cron.d/ 下新建的文件不执行。

原因/etc/cron.d/ 要求文件属主必须是 root 之外的用户、权限 644,且每行末尾需要写运行用户字段;权限 600 或漏写用户都会让 cron 拒绝该文件。

处置chmod 644 /etc/cron.d/myjob 并 chown root:root 之外的用户名规范,同时在命令后补上用户列(如 * * * * * deploy /path/x.sh)。

现象两个任务几乎同时启动,互相抢占同一个文件/端口,偶尔其中一个失败。

原因相邻的时间字段让两个任务在同一分钟内并发执行,缺少互斥机制。

处置错开分钟字段(如 0 2 与 5 2),或在脚本开头用 flock 排他执行:flock -n /var/lock/backup.lock /path/backup.sh。

排障路径

  1. 1先用一分钟探针确认调度器本身活着

    * * * * * echo test >> /tmp/cron-test 2>&1

    一分钟后看 /tmp/cron-test 有没有新行;没有就查 daemon 状态,而不是查业务脚本。

  2. 2确认 cron 服务在跑

    systemctl status cron

    Debian/Ubuntu 单元名是 cron,RHEL/CentOS 是 crond;未启动则任务不会解析。

  3. 3查系统日志里 cron 的加载与执行记录

    grep CRON /var/log/syslog

    能看到 CRON 的调度记录说明规则已被解析;完全无记录说明规则语法被拒或文件未被读取。

  4. 4RHEL/CentOS 系日志路径

    grep cron /var/log/cron

    同一批信息在 RHEL 系写在这个文件,而不是 /var/log/syslog。

  5. 5确认机器当前时区与期望时区一致

    date

    cron 按系统本地时区执行;与 CRON_TZ=Asia/Shanghai 声明不符说明任务时间整体偏移。

  6. 6列出并备份当前用户的 crontab

    crontab -l

    输出为空说明当前用户根本没有任务;改之前先 crontab -l > ~/crontab.bak 留底。

命令示例

带日志与错误重定向的备份任务

0 2 * * * /path/backup.sh >> /var/log/backup.log 2>&1 crontab -l

cron 的环境极其精简,脚本里 PATH、HOME、语言变量都可能缺失,能用绝对路径就全部写绝对路径。>> 追加、2>&1 把 stderr 并入日志——不重定向的话失败只会静默发生,你只会看到「任务没跑」。

先写调试任务验证 cron 真的在跑

* * * * * echo test >> /tmp/cron-test 2>&1 sleep 65 cat /tmp/cron-test rm -f /tmp/cron-test

排查「任务不执行」的标准第一步:先用一个每分钟写文件的最小任务区分是「cron 服务没跑」还是「你的命令本身有问题」。这一条过了再去查业务脚本,能省掉大量在错误方向上的排查。

输出

test

PATH / SHELL / CRON_TZ 写在 crontab 顶部

SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin CRON_TZ=Asia/Shanghai MAILTO=""

cron 的默认 PATH 常常只有 /bin:/usr/bin,自己装的 go、node、python 全部找不到——这是「手动跑正常,cron 里 command not found」的标准原因。CRON_TZ 让跨时区团队的任务不必去改服务器时区;MAILTO="" 直接关掉邮件。

输出

* * * * * /usr/bin/logrotate /etc/logrotate.conf

用管道快速设置任务

echo "@reboot /path/start-app.sh" | crontab crontab -l

crontab 命令从 stdin 读新内容,所以 echo | crontab 会整体覆盖现有任务。适合脚本化初始化,但先 crontab -l 备份一份——这是最容易在自动化脚本里丢掉全部任务的操作。

在 /etc/cron.d 放独立任务文件

SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin 0 3 * * * root /usr/local/bin/nightly.sh >> /var/log/nightly.log 2>&1

/etc/cron.d/ 里的文件格式比用户 crontab 多一列用户名,漏掉这一列该文件会被 cron 直接忽略,且不报错。每个任务独立成文件、带 .run 之类的非标准后缀可避免被 cron 主动执行,权限也必须是 644 且属主 root。

常见坑与注意事项

  • crontab 里的 % 不是普通字符,而是「换行」转义符。未转义的 % 会截断命令行导致任务静默失败——日期格式必须写成 date +\%Y-\%m-\%d,路径含 % 的同样要转义。
  • crontab -r 直接删除当前用户的全部定时任务,没有任何确认和回收站。用 crontab -ri 才会先问一次;自动化脚本里更该用 crontab -l > backup.txt 留底。
  • 命令里的 % 必须转义,而命令里写 redirect 与 && 在部分 cron 实现下行为不一致。可靠写法是全部包进脚本文件,crontab 里只留一行绝对路径调用。
  • 本表只讲 crontab(定时任务);页面里若同时出现「cron 与 crontab 两表」,务必先分清:cron 是守护进程(systemctl status cron),crontab 是编辑用户计划任务的命令,二者不可混用。
  • cron 按服务器时区执行,容器、虚拟机和夏令时切换都可能让任务提前或推迟一小时。用 CRON_TZ 显式指定时区,或先 date 确认系统时区。
  • 系统重启后错过的任务不会补跑(除非用 anacron 类机制);同时 MAILTO 未关闭时,任务里每一条 stdout 都会变成一封邮件,几百行日志会塞爆邮箱或触发退信。

提示

  • 时间格式:分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-6, 0=周日)。
  • * 表示所有值,, 分隔多个值,- 表示范围,/ 表示步长。
  • 脚本路径必须用绝对路径,否则可能找不到命令。
  • cron 环境变量 minimal,建议在脚本里显式设置 PATH。
  • 日志输出:command >> /var/log/cron.log 2>&1 重定向 stdout 和 stderr。
  • 周日和周天都可用 0 或 7 表示,不同发行版可能不同,建议统一用 0。
  • CRON_TZ=Asia/Shanghai 让任务按指定时区触发,服务器跑在 UTC 上时不必再换算时间。
  • crontab -r 直接删掉整个 crontab 且不留备份,要删单条请用 crontab -e 逐行删。
  • @reboot 只在开机瞬间跑一次,开机自启的服务交给 systemd 单元更可靠且有日志。

常见问题

写进 crontab 的任务到点完全不执行,先查什么?

按这个顺序排查最省时。第一步确认服务本身活着:systemctl status cron 看 cron 守护进程是否 running。第二步确认任务确实写进去了:crontab -l 列出当前用户的所有任务,空输出说明根本没保存上(用 crontab -e 时编辑器里写完没退出保存同样会丢)。第三步看调度器有没有触发:Debian/Ubuntu 用 grep CRON /var/log/syslog,RHEL/CentOS 用 grep cron /var/log/cron,能看到具体哪一分钟调起了哪条命令。第四步用 date 确认服务器时区,因为 cron 按系统时区执行,跟你本地时间不一致时就会以为「没跑」。

为什么任务手动执行没问题,放进 cron 就失败?

根因是 cron 的环境极为精简:它不是登录 shell,不加载你的 .bashrc 或 .zshrc,PATH 往往只剩几个系统目录,HOME、SHELL 也可能不是你预期的值。结果是脚本里调 node、python、curl、git 这类非系统目录下的命令时找不到,或者找不到依赖、环境变量为空。两条修法:一是把命令和脚本全部写成绝对路径;二是在 crontab 顶部显式声明环境,SHELL=/bin/bash、PATH=/usr/local/bin:/usr/bin:/bin、HOME=/root,日志排查时把 MAILTO 设为空可关掉邮件通知,避免错误信息被吞掉。

任务跑了但没有任何输出,怎么留住现场?

cron 默认把任务的输出发到本地邮箱,看不到就得显式重定向。常用组合是 >> /var/log/cron.log 2>&1:>> 追加而不是覆盖历史日志,2>&1 把错误输出并到同一文件,这样脚本异常退出的原因也在内。写在命令末尾即可,例如 0 0 * * 0 /path/weekly-report.sh >> /var/log/report.log 2>&1。想做定时清理时也可直接交给 logrotate:30 3 * * * /usr/bin/logrotate /etc/logrotate.conf。若只是确认调度链路是否通,可先加一条最小任务:* * * * * echo test >> /tmp/cron-test 2>&1,一分钟后看文件是否多了一行。

我写的时间明明对,为什么总是差一小时?

因为 cron 按服务器的系统时区解释时间,而不是你的本地时区。先执行 date 看服务器当前时间和时区,如果服务器跑在 UTC 而你在 UTC+8,那么「每天 0 点」在服务器上是 UTC 0 点,也就是你本地早上 8 点。两个解决办法:要么把服务器时区配成你所在的时区,要么在 crontab 顶部写 CRON_TZ=Asia/Shanghai 单独为 cron 指定时区,这样既不动系统时区,也不会影响其它依赖系统时间的程序。特殊字符串 @daily / @midnight 等同样受该时区影响,含义是「该时区的午夜」。

想表达「每天一次」和「工作日一次」,字段该怎么填?

crontab 是五列:分 时 日 月 周,分别取 0-59、0-23、1-31、1-12、0-6(0 表示周日)。所以「每天凌晨 2 点」写 0 2 * * *,前三段分/时固定,* 表示日、月、周每天都执行。「工作日 9 点」写 0 9 * * 1-5,末段用 1-5 只覆盖周一到周五。每小时执行是 0 * * * *,也可用等价简写 @hourly。多个不连续取值用逗号并列,如 10 2 * * 6,7 表示周六周日 2:10。步长用斜杠:*/15 * * * * 是每 15 分钟,0 */2 * * * 是每 2 小时。注意周字段建议统一用 0,别混用 7。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们