一、Cron 基础与命令
1.1 什么是 Cron
Cron 是 Linux/Unix 系统下的定时任务管理工具,允许用户按固定时间自动执行命令或脚本。
1.2 常用命令
| 命令 | 说明 | 风险等级 |
|---|---|---|
crontab -e | 编辑当前用户的 cron 任务(使用默认编辑器) | 低 |
crontab -l | 查看当前用户的 cron 任务列表 | 低 |
crontab -r | 删除当前用户的所有 cron 任务 | ⚠️ 高危(无确认) |
crontab -i -r | 删除前确认(推荐替代 -r) | 低 |
crontab <filename> | 从文件导入 cron 任务 | 中 |
systemctl status crond | 检查 cron 服务是否运行(CentOS/RHEL) | 低 |
systemctl restart crond | 重启 cron 服务(修改配置后可选) | 低 |
1.3 用户级与系统级 Cron
| 类型 | 配置文件位置 | 说明 |
|---|---|---|
| 用户级 | crontab -e | 每个用户独立,推荐日常使用 |
| 系统级 | /etc/crontab | 需 root 权限,可指定执行用户 |
| 系统片段 | /etc/cron.d/* | 软件包安装的定时任务 |
| 小时任务 | /etc/cron.hourly/ | 每小时执行(放入脚本) |
| 日任务 | /etc/cron.daily/ | 每天执行 |
| 周任务 | /etc/cron.weekly/ | 每周执行 |
| 月任务 | /etc/cron.monthly/ | 每月执行 |
二、Cron 时间格式详解
2.1 基础格式(5 个字段)
┌─────────── 分钟 (0-59)
│ ┌───────── 小时 (0-23)
│ │ ┌─────── 日期 (1-31)
│ │ │ ┌───── 月份 (1-12 或 JAN-DEC)
│ │ │ │ ┌─── 星期几 (0-7,0和7均为周日,或 SUN-SAT)
│ │ │ │ │
* * * * * 要执行的命令
2.2 特殊符号说明
| 符号 | 说明 | 示例 |
|---|---|---|
* | 所有值 | * * * * * 每分钟 |
, | 列举多个值 | 0 8,12,18 * * * 每天8、12、18点 |
- | 范围 | 0 9-17 * * * 9点到17点每小时 |
/ | 步长 | */5 * * * * 每5分钟 |
? | 不指定(仅日期/星期) | 部分实现支持 |
L | 最后一天/最后一个星期几 | 0 23 L * * 每月最后一天23点 |
W | 最近工作日 | 0 9 1W * * 最接近1号的工作日 |
# | 第几个星期几 | 0 9 * * 1#3 每月第三个周一 |
2.3 常用时间示例
基础定时
# 每分钟执行一次
* * * * *
# 每5分钟执行一次
*/5 * * * *
# 每小时整点执行
0 * * * *
# 每天凌晨0点执行
0 0 * * *
# 每周日凌晨0点执行
0 0 * * 0
# 每月1日凌晨0点执行
0 0 1 * *
# 每年1月1日凌晨0点执行
0 0 1 1 *
组合与范围
# 每天9点到18点每小时执行
0 9-18 * * *
# 每天9:30和17:30执行
30 9,17 * * *
# 工作日(周一到周五)9点执行
0 9 * * 1-5
# 工作日的9点到17点每30分钟执行
0,30 9-17 * * 1-5
# 每小时的第0、15、30、45分钟执行
0,15,30,45 * * * *
高级示例
# 每月最后一天的23点执行
0 23 L * *
# 每月第三个星期一的9点执行
0 9 * * 1#3
# 每月1日的最近工作日的9点执行
0 9 1W * *
# 每12小时的第20分钟执行(8:20, 20:20)
20 */12 * * *
2.4 秒级精度(扩展格式)
标准 Cron 不支持秒,但部分系统(如 Java Quartz)支持 6 字段格式:
# 每10秒执行一次(Quartz格式)
*/10 * * * * *
# 每分钟的第30秒执行
30 * * * * *
三、Cron 日志与调试
3.1 查看 Cron 执行日志
# 实时监控 cron 日志
tail -f /var/log/cron # CentOS/RHEL
tail -f /var/log/syslog | grep CRON # Ubuntu/Debian
# 查看今天的 cron 记录
grep "$(date '+%b %d')" /var/log/cron
# 查看特定时间段
grep "Mar 25" /var/log/cron
3.2 任务输出重定向
Cron 任务的输出默认会发送邮件给用户,建议重定向到文件:
# 将输出写入日志文件(追加)
* * * * * /path/to/script.sh >> /var/log/script.log 2>&1
# 丢弃所有输出(不记录)
* * * * * /path/to/script.sh >/dev/null 2>&1
# 分别记录标准输出和错误
* * * * * /path/to/script.sh >> /var/log/script.log 2>> /var/log/script.err
3.3 测试 Cron 任务
# 方法1:临时设置为1分钟后运行
(crontab -l ; echo "$(date '+%M %H %d %m *' -d '1 minute') /path/to/script.sh") | crontab -
# 方法2:使用 at 命令立即测试
echo "/path/to/script.sh" | at now
# 方法3:手动执行验证
/path/to/script.sh
四、日志保留与轮转策略
4.1 默认保留策略
Cron 日志由 logrotate 管理,默认配置在 /etc/logrotate.d/syslog:
/var/log/cron {
rotate 4 # 保留 4 个旧日志
weekly # 每周轮转一次
compress # 压缩旧日志(.gz 格式)
missingok
sharedscripts
postrotate
/usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
}
实际保留情况:
- 当前日志 + 4 个归档 = 5 个文件
- 保留天数:约 4~5 周(每周轮转一次)
4.2 查看现有日志文件
ls -lht /var/log/cron*
输出示例:
-rw-------. 1 root root 2.3M Mar 25 09:00 /var/log/cron
-rw-------. 1 root root 1.8M Mar 18 00:00 /var/log/cron-20240318.gz
-rw-------. 1 root root 2.1M Mar 11 00:00 /var/log/cron-20240311.gz
-rw-------. 1 root root 1.9M Mar 04 00:00 /var/log/cron-20240304.gz
-rw-------. 1 root root 2.0M Feb 26 00:00 /var/log/cron-20240226.gz
4.3 修改日志保留策略
方法1:修改全局默认配置(影响所有日志)
编辑 /etc/logrotate.conf:
rotate 12 # 保留12个旧日志
weekly # 每周轮转(或改为 monthly/daily)
方法2:仅修改 cron 日志配置
编辑 /etc/logrotate.d/syslog,为 /var/log/cron 单独添加规则:
/var/log/cron {
missingok
rotate 30 # 保留30个旧日志
daily # 每天轮转一次
compress
sharedscripts
postrotate
/usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
}
方法3:手动清理旧日志
# 删除 30 天前的 cron 日志
find /var/log -name "cron-*.gz" -mtime +30 -delete
五、最佳实践
5.1 使用绝对路径
Cron 的环境变量与终端不同,建议所有命令和脚本使用完整路径:
# 不推荐(可能找不到命令)
* * * * * python3 /home/user/script.py
# 推荐
* * * * * /usr/bin/python3 /home/user/script.py
# 或加载环境变量
* * * * * . /etc/profile; /usr/bin/python3 /home/user/script.py
5.2 脚本添加执行权限
chmod +x /path/to/script.sh
5.3 避免任务重叠执行
如果任务执行时间可能超过间隔,建议加锁:
# 使用 flock 防止重叠
* * * * * /usr/bin/flock -n /tmp/script.lock /path/to/script.sh
# 或使用 mkdir 实现锁
* * * * * mkdir /tmp/script.lock 2>/dev/null && /path/to/script.sh; rmdir /tmp/script.lock
5.4 记录关键任务日志
# 重要任务建议记录日志
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# 添加时间戳
0 3 * * * echo "$(date): Starting backup" >> /var/log/backup.log; /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
5.5 使用注释说明
# 每天凌晨3点备份数据库
0 3 * * * /usr/local/bin/backup.sh
# 工作日每30分钟检查服务状态
*/30 9-17 * * 1-5 /usr/local/bin/health_check.sh
六、常见问题与故障排查
Q1:Cron 任务未执行?
排查步骤:
# 1. 检查 cron 服务是否运行
systemctl status crond # CentOS/RHEL
systemctl status cron # Ubuntu/Debian
# 2. 查看 cron 日志是否有错误
tail -50 /var/log/cron
# 3. 确认脚本有执行权限
ls -l /path/to/script.sh
chmod +x /path/to/script.sh
# 4. 检查命令路径是否正确
which python3 # 获取绝对路径
# 5. 查看邮件(如果有输出)
mail
Q2:Cron 执行但脚本部分失败?
原因:环境变量不同(PATH、JAVA_HOME 等)
解决方案:
# 方法1:在脚本中加载环境变量
#!/bin/bash
source /etc/profile
source ~/.bashrc
# 方法2:在 cron 中指定环境变量
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * /path/to/script.sh
# 方法3:在命令前加载
0 3 * * * . /etc/profile; /path/to/script.sh
Q3:如何备份和恢复 Cron 任务?
# 备份当前用户的所有 cron 任务
crontab -l > cron_backup.txt
# 恢复备份
crontab cron_backup.txt
# 备份其他用户的(需要 root)
crontab -u username -l > username_cron_backup.txt
Q4:如何临时禁用 Cron 任务?
# 方法1:注释掉任务(编辑 crontab -e)
# 0 3 * * * /path/to/script.sh
# 方法2:重命名脚本文件
mv /path/to/script.sh /path/to/script.sh.disabled
# 方法3:删除所有任务前先备份
crontab -l > /tmp/cron_backup.txt
crontab -r
Q5:Cron 时区问题?
# 查看系统时区
timedatectl
# 修改时区(需重启 cron 服务)
sudo timedatectl set-timezone Asia/Shanghai
sudo systemctl restart crond
# 或在脚本中指定时区
0 3 * * * TZ=Asia/Shanghai /path/to/script.sh
七、快速参考速查表
7.1 常用命令速查
| 操作 | 命令 |
|---|---|
| 编辑任务 | crontab -e |
| 查看任务 | crontab -l |
| 删除任务 | crontab -i -r |
| 查看日志 | tail -f /var/log/cron |
| 重启服务 | systemctl restart crond |
| 修改保留策略 | vim /etc/logrotate.d/syslog |
| 测试任务 | echo "命令" | at now |
7.2 时间表达式速查
| 需求 | 表达式 |
|---|---|
| 每分钟 | * * * * * |
| 每5分钟 | */5 * * * * |
| 每小时 | 0 * * * * |
| 每天凌晨3点 | 0 3 * * * |
| 每周一9点 | 0 9 * * 1 |
| 每月1号0点 | 0 0 1 * * |
| 工作日9点 | 0 9 * * 1-5 |
| 9-17点每30分钟 | 0,30 9-17 * * * |
7.3 重定向速查
| 需求 | 写法 |
|---|---|
| 记录所有输出 | >> /var/log/app.log 2>&1 |
| 丢弃所有输出 | >/dev/null 2>&1 |
| 分别记录 | >> app.log 2>> err.log |
7.4 故障排查检查清单
- cron 服务是否运行(
systemctl status crond) - 脚本是否有执行权限(
chmod +x) - 是否使用绝对路径(
which command) - 日志是否有错误(
tail /var/log/cron) - 环境变量是否正确(在脚本中加载 profile)