《Linux 定时任务 crontab 入门:语法、示例与常见坑》
一、什么是 crontab
在 Linux 里,如果你希望某个命令或脚本按固定时间自动运行——比如每天凌晨备份数据库、每 5 分钟检查服务状态、每月 1 号清理日志——就不需要人工盯着终端一条条敲。crontab(cron table)就是 Linux 最常用的定时任务工具。
cron 守护进程(crond)会读取每个用户的定时任务表,在到达指定时间时自动执行对应的命令。你可以把它理解为「给 Linux 设闹钟」:时间一到,命令就跑。
1.1 相关文件
/etc/crontab:系统级 crontab,通常由 root 维护。/etc/cron.d/目录:存放按文件拆分的系统定时任务。/var/spool/cron/或/var/spool/cron/crontabs/:存放每个用户的 crontab 文件(不要直接编辑,要用crontab -e)。
日常使用中,普通用户基本只需要操作
crontab -e/crontab -l/crontab -r三个命令。
二、crontab 基本语法
crontab 的核心只有一行一行的规则,每行代表一条定时任务。格式如下:
* * * * * command_to_execute
│ │ │ │ │
│ │ │ │ └── 星期(0-7,0 和 7 都表示周日)
│ │ │ └──── 月份(1-12)
│ │ └────── 日期(1-31)
│ └──────── 小时(0-23)
└────────── 分钟(0-59)
五个星号从左到右依次表示分、时、日、月、周,后面紧跟要执行的命令。
*表示「任意 / 不限制」。,表示枚举,如1,15表示第 1 和第 15。-表示范围,如1-5表示 1 到 5。/表示步长,如*/10表示每 10 个单位一次。
几个直观的例子:
*/5 * * * *:每 5 分钟执行一次。0 2 * * *:每天凌晨 2 点整执行。30 8 * * 1-5:周一到周五早上 8:30 执行。0 0 1 * *:每月 1 号 00:00 执行。0 3 * * 0:每周日(也可以写7)凌晨 3 点执行。
三、常用 crontab 命令
管理 crontab 的命令非常简单,日常用的就是三个:
-
编辑定时任务:
crontab -e
打开当前用户的 crontab 编辑器(默认打开vi或nano),在里面逐行写入规则即可。 -
查看定时任务:
crontab -l
列出当前用户的所有 crontab 条目。 -
删除所有定时任务:
crontab -r
清空当前用户的全部 crontab 记录。加-i会先弹窗确认,推荐crontab -ri以防误删。
如果需要以其他用户身份管理,例如 crontab -u username -l,通常需要 root 权限。
四、示例实践
下面用真实可运行的场景把语法串起来。
4.1 每 5 分钟检查一次服务并记录日志
*/5 * * * * /usr/bin/systemctl is-active --quiet nginx || echo "nginx 异常 $(date)" >> /home/user/nginx_check.log
每 5 分钟检查 nginx 是否 active,如果异常就把时间戳写入日志。
4.2 每天凌晨 2:00 备份数据库到 /backup
0 2 * * * /usr/bin/mysqldump -u root -p'your_password' mydb | gzip > /backup/mydb_$(date +\%Y\%m\%d).sql.gz
注意:crontab 里的 % 是特殊字符(被当作物换行符),要写成 \% 才能正常出现在命令中。这是最容易踩的坑之一。
4.3 每月 1 号清理 30 天前的日志文件
0 3 1 * * find /var/log/myapp -name '*.log' -mtime +30 -delete
每月 1 号凌晨 3 点,删除 /var/log/myapp 中 30 天以上的 .log 文件。
4.4 工作日每天早上 9:00 和下午 6:00 各执行一次同步
0 9,18 * * 1-5 /home/user/scripts/sync_data.sh
利用 , 枚举小时、1-5 限定周一到周五。
4.5 把命令输出同时打印到终端和日志文件
实际使用中更推荐在脚本里做好日志,但如果只想在 crontab 一行里完成,可以用 tee:
30 2 * * * /home/user/scripts/nightly_task.sh 2>&1 | tee -a /home/user/logs/nightly.log
五、环境变量与常见坑
5.1 环境不同:PATH 和变量很少继承
这是 crontab 最经典的大坑。你在终端里能跑的命令,放到 crontab 经常「找不到命令」。
原因:cron 启动时只会给一个极简的环境(默认 PATH 通常只有 /usr/bin:/bin),不会加载 ~/.bashrc / ~/.profile。
解法:
- 命令一律写绝对路径(
/usr/bin/python3、/home/user/scripts/xxx.sh)。 - 在 crontab 顶部显式声明需要的环境变量:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
- 或者在脚本第一行写 shebang 并用绝对路径调用解释器:
#!/bin/bash,然后chmod +x。
5.2 % 特殊字符
在 crontab 时间字段之后,第一个未转义的 % 会被解释为换行符,后面的内容被当作命令的标准输入。
- 想输出
100%,必须写成100\%。 - 日期格式化
$(date +\%Y-\%m-\%d)同理,每个%都要加\。
5.3 输出去哪儿了?默认会发邮件
cron 默认会把命令的标准输出和标准错误作为邮件发给任务所属用户。如果服务器没有配置邮件服务(很多云主机默认没装 sendmail/postfix),邮件发不出去,日志就「消失」了,排查起来非常痛苦。
建议写法:在命令末尾显式重定向,把日志写到文件:
* * * * * /home/user/scripts/check.sh >> /home/user/logs/cron.log 2>&1
或者在 crontab 头部设置 MAILTO="" 关闭邮件,自己负责日志。
5.4 任务重叠:上一步还没跑完,下一步又到时间
crontab 本身没有防重叠机制。如果任务要跑 10 分钟,你设的是每分钟执行一次,第 2 分钟到来时它会再开一个副本,最后可能同时跑很多个。
解法:
- 用
flock加互斥锁:
* * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/scripts/myjob.sh
- 在脚本开头自己用 PID 文件或
pgrep判断。
5.5 周和日同时限制时是「或」不是「与」
如果你写:
0 2 * * 1
意思是每天都满足(日=任意)且周一满足(周=1),cron 会把它当成「或」:只要其中一个条件命中就会执行。
所以这条实际效果是「每天都执行」,而不是「每周一」。想要「每周一」,日字段填 *、周字段填 1 即可;不要两个都限定具体数字。
5.6 权限与 umask
cron 的 umask 默认通常是 022,这可能导致脚本创建的文件权限和你预期不一样(比如数据库备份文件其他用户可读)。在 crontab 头部显式指定:
UMASK=0077
对涉及敏感数据的脚本尤其重要。
5.7 时区问题
cron 使用系统的时区设置。如果在容器或云主机里时区被设成了 UTC,而你按北京时间写的 0 2 * * *,实际触发时间就差了 8 小时。
确认时区:timedatectl(systemd)或 date。需要时可通过环境变量 TZ 覆盖:
TZ=Asia/Shanghai
0 2 * * * /home/user/scripts/backup.sh
六、调试 crontab 的小技巧
- 用
date输出到日志快速验证任务有没有按时跑:
* * * * * echo "cron tick at $(date)" >> /home/user/logs/cron_test.log
先跑一两条最简单的,确认 cron 服务正常、路径和日志都能工作,再接真正任务。
-
查看系统 cron 日志:
- systemd 系统:
journalctl -u cron或journalctl -u crond - 传统 syslog:
/var/log/cron或/var/log/syslog中搜索CRON
- systemd 系统:
-
确认 crond 是否在运行:
systemctl status crond
# 或
systemctl status cron
很多容器里 crond 默认不装也不开机自启,需要先 apt install cron / yum install cronie 并启动。
- 编辑完成后一定要
crontab -l确认内容落盘,别只看 vi 退出没报错就以为生效了。
七、总结
- crontab 的精髓就是五颗星 + 命令,分钟到周,配合
*,,,-,/几乎能表达任何周期。 - 新手最常踩的坑:命令没有用绝对路径、
%没转义、输出被发到无处投递的邮件、任务重叠、日与周的「或」逻辑、时区不一致。 - 排错三板斧:写死绝对路径 + 显式重定向日志 + 用
flock防重叠,能解决九成以上的「crontab 为什么没执行」问题。
把上面这些习惯养成之后,crontab 就是你运维和日常自动化里最省心的工具之一。
- 点赞
- 收藏
- 关注作者
评论(0)