📖 知识点简介
上一篇学了 Shell 脚本编写,脚本写好了谁来按时执行?Crontab 是 Linux 下最经典的定时任务管理工具,运维日常 80% 的自动化工作(日志清理、数据备份、健康巡检、证书监控)都依赖它。理解 crontab 的语法规则、环境变量陷阱、日志排错方法,是运维工程师的必修课。
🔧 核心命令整理
1. 基本管理命令
| 命令 | 用途 | 说明 |
|---|---|---|
crontab -l |
列出当前用户的任务列表 | 无任务时输出 no crontab for xxx |
crontab -e |
编辑当前用户的 crontab | 默认使用 vim,自动校验语法 |
crontab -r |
删除当前用户全部任务 | ⚠️ 危险操作,删除后不可恢复 |
crontab -u user -l |
查看指定用户的任务 | 仅 root 可用 |
crontab -i |
删除前先确认 | 配合 -r 使用:crontab -i -r |
2. 时间语法(5 段式)
scss
* * * * * command
┬ ┬ ┬ ┬ ┬
│ │ │ │ └── 星期 (0-7, 0和7均代表周日)
│ │ │ └──── 月份 (1-12)
│ │ └────── 日期 (1-31)
│ └──────── 小时 (0-23)
└────────── 分钟 (0-59)
常用示例:
| 表达式 | 含义 |
|---|---|
0 3 * * * |
每天凌晨 3 点执行 |
*/10 * * * * |
每 10 分钟执行一次 |
0 1 * * 0 |
每周日凌晨 1 点执行 |
30 2 1 * * |
每月 1 号凌晨 2:30 执行 |
0 0,12 * * * |
每天 0 点和 12 点各执行一次 |
0 9-18/2 * * 1-5 |
工作日 9:00-18:00 每 2 小时执行 |
3. 特殊字符串(简写)
| 关键字 | 等价表达式 | 说明 |
|---|---|---|
@reboot |
--- | 系统启动时执行一次 |
@daily |
0 0 * * * |
每天午夜 |
@weekly |
0 0 * * 0 |
每周日午夜 |
@monthly |
0 0 1 * * |
每月 1 号午夜 |
@yearly |
0 0 1 1 * |
每年 1 月 1 日 |
💻 实操示例
场景 1:每天凌晨清理 7 天前的日志
bash
# 1. 编写清理脚本
cat > /usr/local/bin/clean_logs.sh << 'EOF'
#!/bin/bash
LOG_DIR="/var/log/myapp"
find "$LOG_DIR" -name "*.log" -mtime +7 -exec rm -f {} ;
echo "$(date): cleaned logs older than 7 days" >> /var/log/cleanup.log
EOF
chmod +x /usr/local/bin/clean_logs.sh
# 2. 添加定时任务
crontab -e
# 添加一行:
0 4 * * * /usr/local/bin/clean_logs.sh
场景 2:每 5 分钟监控服务存活状态
bash
# 监控 Nginx 是否存活,挂了自动重启
crontab -e
*/5 * * * * /usr/bin/curl -sf -o /dev/null http://localhost || systemctl restart nginx
场景 3:每周打包备份数据库
bash
# 每周日凌晨 3 点备份 MySQL
cat > /usr/local/bin/backup_db.sh << 'SHELL'
#!/bin/bash
BACKUP_DIR="/data/backup/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
mysqldump -u root myapp | gzip > "$BACKUP_DIR/db_$(date +%H%M).sql.gz"
find /data/backup -type d -mtime +30 -exec rm -rf {} ;
SHELL
chmod +x /usr/local/bin/backup_db.sh
crontab -e
0 3 * * 0 /usr/local/bin/backup_db.sh
场景 4:日志查看与排错
bash
# 查看 cron 服务状态
systemctl status cron # Debian/Ubuntu
systemctl status crond # CentOS/RHEL
# 查看任务执行日志
grep CRON /var/log/syslog # Debian
grep CRON /var/log/cron # CentOS
journalctl -u cron -f # 实时追踪
# 检查命令是否可执行
which mysqldump # 确保路径正确
echo $PATH # cron 环境 PATH 有限,默认仅 /usr/bin:/bin
⚠️ 常见坑点 / 注意事项
❌ 坑 1:PATH 环境变量不同
Cron 执行时的环境是最小环境 (PATH=/usr/bin:/bin),不会加载 .bashrc/.bash_profile。
bash
# ❌ 会报错 --- mysqldump 不在默认 PATH 中
0 3 * * * mysqldump -u root myapp > /tmp/backup.sql
# ✅ 正确做法:使用绝对路径
0 3 * * * /usr/bin/mysqldump -u root myapp > /tmp/backup.sql
# ✅ 或者在脚本开头设置 PATH
0 3 * * * PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin /usr/local/bin/backup.sh
❌ 坑 2:% 号需要转义
bash
# ❌ 报错 Syntax error
0 3 * * * echo "$(date +%Y-%m-%d)" > /tmp/date.log
# ✅ 正确:% 前加反斜杠
0 3 * * * echo "$(date +%Y-%m-%d)" > /tmp/date.log
❌ 坑 3:输出重定向
bash
# ❌ 输出会发邮件到本地邮箱,积攒大量邮件导致磁盘满
*/10 * * * * /usr/local/bin/check.sh
# ✅ 将标准输出和错误都丢弃(或重定向到日志文件)
*/10 * * * * /usr/local/bin/check.sh > /dev/null 2>&1
# ✅ 追加到日志文件(推荐)
*/10 * * * * /usr/local/bin/check.sh >> /var/log/check.log 2>&1
❌ 坑 4:任务未执行排查 checklist
bash
□ 检查 cron/crond 服务是否在运行
□ 检查 crontab 语法是否正确 (echo 一行到 crontab 不会报语法错)
□ 检查脚本是否有执行权限 (chmod +x)
□ 检查日志文件是否有写入权限
□ 检查命令是否使用绝对路径
□ 检查脚本是否包含 shebang (#!/bin/bash)
□ 检查系统时间与时区 (timedatectl)
💡 生产建议
-
每条任务单独开一个 crontab 条目,不要写到大脚本里,方便排查
-
关键任务添加锁机制 :用
flock防止任务重叠bash*/5 * * * * /usr/bin/flock -n /tmp/deploy.lock /usr/local/bin/deploy.sh -
系统级定时任务用
/etc/crontab(支持用户列),用户级用crontab -e -
定期审计:每月检查一次所有定时任务,清理废弃条目
-
监控 crond 服务:配合监控系统,crond 挂了立刻告警