导读:翻翻本站过往教程会发现一个规律:定时备份、证书自动续期、日志定期切割、健康检查告警,所有"到点自动执行"的活,最后都落在同一句"加一条crontab"上,但cron本身从来没被正面讲过。这篇补上这块拼图:五行语法口诀、用户级和系统级的区别、站长最该配上的五个实战任务、环境变量这个坑了无数人的暗礁、以及三招确认任务真的跑了。看完这篇,cron这台"永不下班的老钟表",会变成你手里最省心的员工。
一、cron是什么:系统里工龄最长的自动化工种
cron是类Unix系统的定时任务守护进程,1975年就诞生了,比Linux内核还年长十六岁。它的设计哲学简单到只剩一句话:按你登记的时间表,到点执行命令——这个核心逻辑五十年没变过,也正因为简单到没有意外,它成了最可靠的系统组件之一。
Debian/Ubuntu上服务名叫cron,CentOS/RHEL上叫crond,都是发行版预装的标准组件,无需安装:
systemctl status cron
看到active (running)说明这台钟表已经在走。有个有趣的层级关系:本站systemd那篇讲过"systemd是所有进程的祖宗",cron恰好就是被systemd管着的服务之一——祖宗管钟表,钟表管你的脚本,一层层委托下去。
二、五行口诀:五分钟记住crontab语法
一条cron任务就两部分:时间表+命令。时间表固定五个字段,从左到右依次是:
分 时 日 月 周
取值范围:分0-59、时0-23、日1-31、月1-12、周0-7(0和7都算周日)。四个符号覆盖所有表达:星号表示"每",逗号表示列举,短横线表示范围,斜杠表示步进。直接背五个实用案例:
0 3 * * * /opt/scripts/backup.sh */10 * * * * /opt/scripts/check.sh 0 4 * * 0 /opt/scripts/weekly.sh 0 0 1 * * /opt/scripts/monthly.sh 30 2 14,28 * * /opt/scripts/bimonthly.sh
对照翻译:每天凌晨3点跑备份;每10分钟跑健康检查;每周日凌晨4点做周维护;每月1号零点跑月度任务;每月14号和28号的凌晨2点半跑半月任务。九成的定时需求,就这五行的变体。
提前打两个预防针。第一,想表达"每小时第30分",写30 * * * *,别顺手写成* */1 * * *再加个30,语义会变。第二,周和日月是"或"关系:同时指定了日和周,满足任意一个就会执行,这是历史包袱,记不住就干脆别混用,只留一个生效。
三、上手:三条命令管好任务清单
crontab -e crontab -l crontab -r
三条命令分别负责编辑、查看、删除当前用户的任务表。第一次执行-e会让你选默认编辑器,选nano最省事;保存退出后cron自动加载新配置,不需要重启任何服务,这是它比很多调度系统优雅的地方。
-r是著名的危险键:和-l只隔一个键位,一按下去整个任务表直接清空且无确认。稳妥的习惯是动手前先导出备份:
crontab -l > ~/crontab_backup_$(date +%F).txt
用户级之外还有系统级入口:/etc/crontab文件和/etc/cron.d/目录下的配置片段。系统级格式多一个用户字段,适合管理员统一下发任务;个人VPS场景用crontab -e完全够用,还不用担心误伤系统文件。
四、实战:站长最该配上的五个定时任务
第一个,证书自动续期。Let's Encrypt证书90天有效,靠人记是遗忘灾难,一行cron解决:
0 3 * * * certbot renew --quiet
renew自带到期判断,没到续期窗口就空转,所以每天跑也无副作用。需要续期后重载Nginx的话,加个renew hook执行systemctl reload nginx即可。
第二个,数据库每日备份加七天自动轮转,一行顶一套小型备份系统:
0 4 * * * mysqldump -ubackup_user -pYourPass mysite | gzip > /backup/db_$(date +\%Y\%m\%d).sql.gz && find /backup -name "db_*.sql.gz" -mtime +7 -delete
特别注意:cron配置里百分号是特殊字符,date里的%必须写成\%,这是新手最常撞的暗坑,没有之一。
第三个,journal日志体积控制,呼应本站systemd篇提过的"日志中央水库":
0 5 * * 0 journalctl --vacuum-size=200M
每周日凌晨把journal压回200M以内,小磁盘机器的救命符。
第四个,网站健康检查带自动拉起:
*/5 * * * * curl -s -o /dev/null -w "%{http_code}" https://example.com | grep -q 200 || systemctl restart myapp
五分钟一问"你还活着吗",答不上来就扶它起来。配合本站监控篇的告警通道,就是一个简易自愈系统。
第五个,备份文件异地同步。本地备份只是半套方案,另一半是离开这台机器:
0 6 * * * rsync -az /backup/ offsite:/backup/this-vps/
每天早上把昨天的备份增量推到异机,rsync的用法细节本站VPS搬家篇讲过,这里直接复用。
五、最大的坑:cron的环境和你终端的环境不是同一个世界
十个人写cron,九个栽在这一条:脚本手动跑得好好的,进了cron就哑火。原因不是玄学——cron执行任务时用的是极简环境,PATH往往只有/usr/bin:/bin,你终端里随手能敲的命令,cron根本找不到。
三条铁律根治:
第一,绝对路径走天下。which curl查出的完整路径直接写进脚本;脚本第一行的#!/bin/bash解释器声明别省。
第二,脚本自带环境。把依赖的环境变量显式写进脚本开头,别指望继承:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
第三,输出必须重定向。cron默认把任务的stdout和stderr发给本机邮件,而很多VPS根本没配邮件服务,输出就此人间蒸发——你以为任务没跑,其实跑了但报错没人看见:
*/5 * * * * /opt/scripts/check.sh >> /var/log/check.log 2>&1
六、三招确认任务真的跑了
由轻到重三个手段,对应三种怀疑。
怀疑cron没触发?看cron自己的日志:
grep CRON /var/log/syslog
Debian系记录在syslog,CentOS看/var/log/cron,systemd体系用journalctl -u cron也行。每次任务触发都会留一行带时间戳的记录,先确认"到点了它动了"。
怀疑脚本执行了但结果不对?看第五节铁律三配的应用日志:
tail -f /var/log/check.log
有记录说明任务跑了,内容对不对在这里见分晓。
终极保险,任务行首打时间戳:
*/5 * * * * date >> /tmp/cron_alive.txt && /opt/scripts/check.sh >> /var/log/check.log 2>&1
/tmp/cron_alive.txt停止增长,说明cron压根没执行到这一行——范围瞬间锁定在语法错误、用户不对、cron服务停了三种情况,排查方向立刻清晰。
七、什么时候该换工具:cron的三个短板
cron够老够稳,但有三个力不从心的场景,对应三个替代品。
要秒级精度:cron最小粒度是分钟。需要秒级就用systemd timer,OnCalendar精确到秒,OnUnitActiveSec=30s这种相对时间也行,写法参考本站systemd篇,它还能免费拿到日志归口和依赖管理。
错过要补跑:机器关机时任务错过了,cron不补。anacron专治这个漏,更适合不是24小时开机的设备;常开VPS用systemd timer加Persistent=true同样能补上错过的执行。
任务有依赖和重试:A成功才跑B、失败自动重试三次,这种编排逻辑cron表达不了。要么上专业的调度工具,要么写个常驻守护脚本交给systemd管,后者在个人规模下往往更简单直接。
结论不复杂:九成场景cron依然是最优解,剩下一成是systemd timer的主场,两个都熟,按需切换。
八、安全底线:别什么都用root跑
crontab -e登记的是当前用户的任务,很多人图省事全程root。更稳的做法:给具体用途建独立用户,比如数据库备份专门建个backup用户,用它的crontab跑,权限边界清晰,脚本被攻破也摸不到别的目录。备份脚本里有数据库密码,文件权限chmod 700收紧,绝不放进web目录。
多用户的管理机上,还可以用/etc/cron.allow白名单锁死"谁能建定时任务":没列进文件的用户一律禁止。被入侵后攻击者最爱留定时后门做持久化,这一招能提前堵住一整类——安全这件事,本站安全系列反复强调过:纵深防御,每一层都设卡。
结语
把备份、续期、清理、巡检四件事写成cron任务之后,VPS才真正从"一台电脑"变成"一台服务":它会在你睡觉时备份数据库,在证书到期前默默续命,在磁盘将满前清掉旧日志,在每一个你没盯着的整点照常运转。运维的终极目标是让自己失业,cron就是你聘下的第一个员工——便宜、沉默、永不迟到。




