一、为什么需要定时任务
运维工作中大量工作带有"周期性":日志切割、数据备份、缓存清理、监控巡检、证书续期检查。靠人工每天重复执行既不现实也不可靠,定时任务就是把这类工作自动化托管给系统的核心手段。Linux 下主流方案有两个:Crontab(传统、普及、简单)和 Systemd Timer(现代、可控、适合服务化场景),本文从入门到生产实践逐一讲透。
二、Crontab 基础:语法与常用写法
# 编辑当前用户的定时任务 crontab -e # 查看当前用户的定时任务 crontab -l # 删除所有定时任务 crontab -r
Crontab 每行由"时间表达式 + 命令"组成,时间表达式共 5 个字段:
分 时 日 月 周 命令 * * * * * /usr/local/bin/backup.sh
常用示例:
# 每天凌晨 2:30 执行备份 30 2 * * * /opt/scripts/backup.sh # 每 10 分钟执行一次健康检查 */10 * * * * /opt/scripts/healthcheck.sh # 每天 8-18 点之间每隔 2 小时执行 0 8-18/2 * * * /opt/scripts/sync.sh # 每周一至周五早上 9 点执行 0 9 * * 1-5 /opt/scripts/report.sh # 每月 1 号和 15 号凌晨执行 0 0 1,15 * * /opt/scripts/cleanup.sh
注意:crontab -e 编辑的是当前用户的表;系统级任务放在 /etc/crontab(多一个"用户"字段)或 /etc/cron.d/ 目录下,root 权限即可管理全局任务。
三、Crontab 进阶:环境变量、日志与常见坑
1. 环境变量问题(最高频的坑):cron 执行时的 PATH 极其精简,很多命令找不到。脚本内务必使用绝对路径,或脚本开头显式声明环境:
#!/bin/bash # 脚本内推荐写法 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin export LANG=en_US.UTF-8
2. 输出与日志:默认 cron 把输出用邮件发给用户(多数服务器没配邮件,输出就丢了),建议手动重定向:
30 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
3. 脚本要有锁,防止上次没跑完下次又启动:
#!/bin/bash
LOCKFILE=/tmp/backup.lock
if [ -f "$LOCKFILE" ]; then
echo "已有备份任务在运行,退出"
exit 1
fi
touch "$LOCKFILE"
trap 'rm -f "$LOCKFILE"' EXIT
# 业务逻辑...
sleep 6004. 注意系统时区:cron 按系统时区执行,服务器时区不一致会导致任务时间错乱,务必统一 timedatectl set-timezone Asia/Shanghai。
四、Systemd Timer:更现代的替代方案
Systemd Timer 由两个单元组成:service 单元(定义要执行的任务)和 timer 单元(定义触发时间)。优点:支持精确到秒、支持随机延迟避免风暴、支持依赖与资源限制、日志统一走 journald。
# /etc/systemd/system/backup.service [Unit] Description=Daily Backup [Service] Type=oneshot ExecStart=/opt/scripts/backup.sh
# /etc/systemd/system/backup.timer [Unit] Description=Run backup daily at 02:30 [Timer] OnCalendar=*-*-* 02:30:00 RandomizedDelaySec=60 Persistent=true [Install] WantedBy=timers.target
# 启用并查看 systemctl daemon-reload systemctl enable --now backup.timer systemctl list-timers
几个关键指令:Persistent=true 表示错过的任务在开机后补跑;RandomizedDelaySec 随机延迟防止多机同时执行造成负载尖峰;OnCalendar 支持 Mon..Fri 09:00、*/15min 等人类可读写法,比 cron 表达式直观得多。
五、Crontab vs Systemd Timer 如何选择
选 Crontab:任务简单、追求兼容性(老系统/容器内无 systemd)、只想要一行表达式。
选 Systemd Timer:需要精确控制(秒级、随机延迟、错过后补跑)、希望日志统一进 journald、任务较多需要独立管理,或者任务依赖某个服务启动状态。生产环境建议:系统级维护任务尽量迁移到 Systemd Timer,业务脚本按团队习惯保持 Crontab 亦可,但务必统一规范。
六、生产环境最佳实践清单
1. 所有脚本路径、命令用绝对路径,避免环境变量坑 2. 输出必须落日志文件,并配置 logrotate 防止日志撑爆磁盘 3. 耗时任务加锁防重入 4. 关键任务(备份、同步)执行后做结果校验并告警,例如失败时发送通知 5. 定时任务变更走版本管理(脚本入库),禁止在服务器上直接裸改 6. 定期用 crontab -l 和 systemctl list-timers 审计服务器上的全部定时任务 7. 服务器时区统一,避免因时区导致任务时间漂移
定时任务是运维自动化的基石,把"人肉执行"变成"系统托管",再配合监控告警,就能把重复劳动彻底释放掉。掌握 Crontab 与 Systemd Timer,是每个运维工程师的基本功。
评论