第 8 章 · 04 :传统定时任务 本节摘要:上一节讲了现代化的 ,这一节讲它仍在广泛使用的前辈—— 。cron 是 Unix 世界最古老的定时任务机制:用一条「五段式时间表达式」声明「什么时候跑什么命令」。本节要把这个表达式彻底讲清——怎么读、怎么写「每天凌晨3点」「每15分钟」「每月1号」这类常见规则。还要讲 cron 在生产中的几个经典坑(环境变量缺失、路径不全、输出无处去),让你写的定时任务真正可靠。 内容来源:综合 cron 与 知识整理,套用体系化模板。 学习目标 阅读完本节,你应当能够: 读懂五段式时间表达式(分 时 日 月 周),写出常见规则。 用 (编辑)、 (列出)、 (删除)管理自己的定时任务。 说清每段的取值范围与特殊符号( 任意、 列表、 范围、 步长)。
crontab:传统定时任务本节摘要:上一节讲了现代化的
.timer,这一节讲它仍在广泛使用的前辈——crontab。cron 是 Unix 世界最古老的定时任务机制:用一条「五段式时间表达式」声明「什么时候跑什么命令」。本节要把这个表达式彻底讲清——怎么读、怎么写「每天凌晨3点」「每15分钟」「每月1号」这类常见规则。还要讲 cron 在生产中的几个经典坑(环境变量缺失、路径不全、输出无处去),让你写的定时任务真正可靠。
内容来源:综合 cron 与
crontab知识整理,套用体系化模板。
阅读完本节,你应当能够:
crontab -e(编辑)、-l(列出)、-r(删除)管理自己的定时任务。* 任意、, 列表、- 范围、/ 步长)。/etc/crontab//etc/cron.d/。cron 的设计极简:一个文本文件,每行一条规则,格式是「五段时间 + 要跑的命令」:
分 时 日 月 周 命令
这种简洁是 cron 的优点(易学易记),但也带来了几个坑——它跑的命令处于一个极简的环境(没有你登录 Shell 的那些环境变量、PATH 不全),输出默认发邮件(如果没有 mail agent 就丢)。这些坑让无数新手写的 cron 任务「手动跑没问题,定时跑就失败」。理解 cron 的表达式不难,难的是避开这些环境坑。
* * * * * 命令 │ │ │ │ │ │ │ │ │ └─ 周(0-7, 0和7都是周日) │ │ │ └──── 月(1-12) │ │ └─────── 日(1-31) │ └────────── 时(0-23) └───────────── 分(0-59)
每段可用四种符号:
* —— 任意值(「每个」), —— 列表(「这些值」),如 1,15- —— 范围,如 1-5/ —— 步长,如 */15(每15)、1-30/10(1到30每10)| 表达式 | 含义 |
|---|---|
0 3 * * * |
每天 3:00 |
*/15 * * * * |
每 15 分钟(0,15,30,45) |
0 * * * * |
每小时整点 |
0 0 * * 0 |
每周日 0:00(每周一次) |
0 0 1 * * |
每月 1 号 0:00(每月一次) |
30 8 * * 1-5 |
周一到周五 8:30(工作日) |
0 0,12 * * * |
每天 0:00 和 12:00 |
记不住时,用搜索引擎搜「crontab guru」这类在线工具,可视化生成表达式。但常见规则应该背下来。
crontab -e # 编辑当前用户的 crontab(默认用 vi, 可改 EDITOR) crontab -l # 列出当前用户的定时任务 crontab -r # 删除当前用户的所有任务(危险!)
编辑时每行一条规则:
# 每天凌晨 3 点跑备份脚本 0 3 * * * /home/user/backup.sh >> /home/user/backup.log 2>&1 # 每 15 分钟同步一次 */15 * * * * /home/user/sync.sh
系统管理员用的两种方式:
# 方式 1: /etc/crontab(带用户名那列) # 分 时 日 月 周 用户 命令 0 3 * * * root /opt/backup.sh # 方式 2: /etc/cron.d/xxx(推荐, 一个文件一个任务包) # 格式同 /etc/crontab(带用户列)
/etc/cron.d/ 的好处:每个任务一个独立文件,便于脚本管理(部署/卸载只是复制/删除文件)。
# crontab 里写: 0 3 * * * myapp --config=$APP_HOME/config.yml # 失败! cron 环境里没有 APP_HOME, 也没有你的 .bashrc
cron 跑的命令只有极简的 PATH 和几个变量,不加载你的 .bashrc/.profile。解决:
APP_HOME=/home/user/myapp/home/user/myapp 而非 $APP_HOME)。source ~/.bashrc(若依赖其中变量)。0 3 * * * docker backup ... # 失败! cron 的 PATH 没有 docker 0 3 * * * /usr/bin/docker backup ... # 用绝对路径!
cron 的 PATH 通常只有 /usr/bin:/bin,很多程序在 /usr/local/bin、/opt/...。cron 里的命令一律用绝对路径,或在 crontab 顶部 PATH=/usr/local/bin:/usr/bin:/bin。
0 3 * * * myscript.sh # 输出默认发邮件! 没装 mail 就丢, 错误也丢 0 3 * * * myscript.sh >> /var/log/myscript.log 2>&1 # 重定向到文件!
cron 默认把命令的 stdout/stderr 发邮件给用户。没装 mail agent 时,邮件堆积(占磁盘)且你看不到错误。始终 >> log 2>&1 重定向到文件,才能排查问题。
0 3 * * * /home/user/backup.sh # backup.sh 没有 #!/bin/bash? # cron 可能用 sh 而非 bash 执行, bash 语法报错
确保脚本第一行有 #!/bin/bash(或对应解释器),否则 cron 用默认 sh(可能是 dash)执行,bash 特有语法会失败。
*(任意),(列表)-(范围)/(步长)。0 3 * * *、每15分钟 */15 * * * *、每周日 0 0 * * 0、每月1号 0 0 1 * *、工作日 30 8 * * 1-5。crontab -e/-l/-r;系统级 /etc/crontab 或 /etc/cron.d/(带用户列,推荐后者)。>> log 2>&1)、脚本无 #!/bin/bash。.timer 替代(日志集成、错过补偿),但 cron 仍广泛使用,必须会。下一节讲一次性定时任务——at,它与 cron(周期)互补,适合「明天提醒」这类单次任务。