crontab 是 Linux 的定时任务系统,可以按设定的时间自动执行命令或脚本。它是自动化运维的核心工具,广泛用于备份、日志清理、数据同步等场景。
cron 是一个守护进程,每分钟检查一次是否有任务需要执行。crontab 是管理定时任务的命令,每个用户都可以有自己的 crontab 文件。
crontab 时间表达式由 5 个字段组成:
* * * * * 命令
│ │ │ │ │
│ │ │ │ └── 星期几 (0-7,0和7都是周日)
│ │ │ └──── 月份 (1-12)
│ │ └────── 日期 (1-31)
│ └──────── 小时 (0-23)
└────────── 分钟 (0-59)
| 字符 | 含义 |
|---|---|
| * | 任意值 |
| , | 列举多个值 |
| - | 范围 |
| / | 步长 |
# 每分钟执行
* * * * * /path/to/script.sh
# 每小时执行
0 * * * * /path/to/script.sh
# 每天凌晨 2 点执行
0 2 * * * /path/to/script.sh
# 每周一早上 8 点执行
0 8 * * 1 /path/to/script.sh
# 每月 1 日凌晨执行
0 0 1 * * /path/to/script.sh
# 每 5 分钟执行
*/5 * * * * /path/to/script.sh
# 每小时第 5、15、25 分钟执行
5,15,25 * * * * /path/to/script.sh
# 工作日早上 9 点执行
0 9 * * 1-5 /path/to/script.sh
# 每季度第一天执行
0 0 1 1,4,7,10 * /path/to/script.sh
crontab -e
首次使用会提示选择编辑器。
crontab -l
crontab -r
删除前确认:
crontab -ri
sudo crontab -u username -e
sudo crontab -u username -l
一些系统支持特殊的时间字符串:
| 字符串 | 含义 |
|---|---|
| @yearly | 每年(0 0 1 1 *) |
| @monthly | 每月(0 0 1 * *) |
| @weekly | 每周(0 0 * * 0) |
| @daily | 每天(0 0 * * *) |
| @hourly | 每小时(0 * * * *) |
| @reboot | 重启后执行一次 |
@daily /path/to/backup.sh
@reboot /path/to/startup.sh
cron 执行时的环境变量与登录 Shell 不同,PATH 可能不完整。建议在脚本中使用绝对路径:
# 在 crontab 中设置环境变量
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
# 或在脚本中使用绝对路径
0 2 * * * /usr/bin/python3 /home/user/script.py
cron 任务默认会把输出发送到用户邮箱。建议重定向输出:
# 重定向到文件
0 2 * * * /path/to/script.sh >> /var/log/script.log 2>&1
# 丢弃输出
0 2 * * * /path/to/script.sh > /dev/null 2>&1
# 只记录错误
0 2 * * * /path/to/script.sh > /dev/null
检查 cron 服务是否运行:
systemctl status cron
systemctl status crond
检查日志:
grep CRON /var/log/syslog
tail -f /var/log/cron
确保脚本有执行权限:
chmod +x /path/to/script.sh
使用绝对路径:
0 2 * * * cd /home/user/project && /home/user/project/script.sh
在脚本开头加载环境:
#!/bin/bash
source ~/.bashrc
或在 crontab 中设置:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 2 * * * tar -czf /backup/data_$(date +\%Y\%m\%d).tar.gz /data
注意 % 在 crontab 中需要转义。
0 3 * * * find /var/log -name "*.log" -mtime +7 -delete
*/30 * * * * rsync -avz /data/ backup@remote:/backup/
*/5 * * * * pgrep nginx > /dev/null || systemctl restart nginx
0 8 * * 1 /home/user/send_report.sh | mail -s "Weekly Report" admin@example.com
crontab -e 编辑,crontab -l 查看,crontab -r 删除