定时任务总不跑?crontab 五段表达式一次讲清
服务器上很多活都靠定时任务:每天凌晨备份数据库、每小时清一次临时文件、每周生成一次报表。这些活交给 crontab 最省事,但新手第一次写定时表达式经常翻车:任务不跑、跑的时机不对、跑了却没留下任何痕迹。问题多半不在任务本身,而在表达式和运行环境这两处。
先看表达式。crontab 一行有五个时间段,依次是分、时、日、月、星期,后面跟要执行的命令。比如 0 2 * * * /home/user/backup.sh,意思是每天凌晨 2 点整跑一次备份脚本。星号代表“每一个”,*/15 代表“每隔 15”,1,15 代表“1 号和 15 号”,1-5 代表“1 到 5”。0 9 * * 1-5 就是工作日早上 9 点,30 3 1 * * 就是每月 1 号凌晨 3 点半。五个位置别写反了,最常见的错误是把“分”和“时”颠倒,结果任务在完全不对的时间跑。
再说一个容易踩的坑:crontab 里星期的 0 和 7 都代表星期日,写 0 或 7 都可以,但别写成“星期 8”。另外“日”和“星期”同时写了具体值时,规则是满足任一即可执行,不是同时满足——比如 0 0 1 * 1 会在每月 1 号和每周一都跑,很多人以为是“每月第一个周一”,其实不是。真要“每月第一个周一”,得在命令里用 date 判断,或者改用 systemd timer。
表达式写对了,任务还可能“跑了等于没跑”。第一个原因是环境变量:cron 执行时的 PATH 很短,脚本里直接写 python3、docker 这类命令可能找不到。稳妥做法是在脚本里写命令的绝对路径,或者在 crontab 文件开头补一行 PATH=/usr/local/bin:/usr/bin:/bin。第二个原因是工作目录:cron 默认在用户家目录下跑,脚本里用相对路径读写文件很容易写错地方,路径一律写绝对路径最保险。第三个原因是输出没地方去:cron 默认把命令的输出发邮件,服务器上没配邮件就会悄悄丢掉,排错时加 >> /var/log/myjob.log 2>&1 把标准输出和错误都写进日志,出了问题有据可查。
改完定时任务要确认两件事:一是用 crontab -l 看当前生效的表,确认改的是当前用户的表而不是 root 的表——普通用户和 root 的 crontab 是分开的;二是别急着等到明天验证,临时把时间改成未来两三分钟后,确认日志里有输出再改回正式时间。线上任务最怕“以为配好了”,验证一次只要几分钟,值得。
最后留个习惯:每条定时任务都写上注释,说明它是干什么的、产出在哪里。比如 # 每天凌晨2点备份数据库到 /backup 写在命令上一行。半年后回来看,你会感谢当初写注释的自己。定时任务的本质不是“设好就忘”,而是“设好、验证过、留了日志、出了问题能找到人”。
- 点赞
- 收藏
- 关注作者
评论(0)