定时任务 — Crontab 从入门到生产实战

📖 知识点简介

上一篇学了 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 挂了立刻告警

相关推荐
ServBay2 小时前
Laravel Herd MCP 的替代,多语言与跨平台的 AI 本地开发选择
后端·ai编程·mcp
GoGeekBaird3 小时前
Prompt、Context、Harness 工程全景图
后端
SimonKing4 小时前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
AskHarries4 小时前
MCP 基础:Server、Tool、Resource 和 Prompt
后端·程序员
长栎4 小时前
你写的 DCL 单例,在反序列化面前就是个弟弟——单例模式的破局与重建
后端
长栎4 小时前
命令模式和策略模式代码长一样——你分不清是因为你没看穿它们的本质
后端
用户298698530144 小时前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
苍何4 小时前
开源个狠活,世界杯 AI 模型竞技场!
后端