在Linux系统管理中,定时任务调度是每个运维人员必须掌握的核心技能。at和crontab这两个看似简单的命令,实际上构成了Unix-like系统中最基础也最强大的自动化任务管理体系。我至今记得刚入行时因为不熟悉crontab语法,导致整点执行的日志切割脚本在午夜疯狂输出报警邮件的惨痛经历。
at命令适合执行一次性任务,比如你需要在2小时后重启某个服务,或者明天早上9点给团队发提醒邮件。而crontab则是周期性任务的瑞士军刀,从每分钟执行的监控脚本到每月1号凌晨的数据库备份,都离不开它的精准调度。这两个工具共同覆盖了从临时性到周期性的所有任务调度场景。
at命令的基本语法看似简单:
bash复制at 时间
然后会进入交互式界面等待输入要执行的命令。但实际使用时有许多细节需要注意:
bash复制echo "shutdown -h now" | at 23:00 2023-12-31
这个命令会在指定日期时间执行关机操作。时间格式非常灵活,支持:
重要提示:默认情况下at命令的输出会通过邮件发送给用户,建议在命令末尾添加 >/dev/null 2>&1 避免邮箱被塞满。
atq命令可以查看待执行的任务队列,每个任务都有唯一的队列编号。如果需要取消某个任务:
bash复制atrm 队列编号
在实际运维中,我经常用at来做这些事:
一个典型的生产案例:当发现数据库需要维护但又不能立即停机时,可以用:
bash复制echo "/usr/local/bin/db_maintenance.sh" | at 02:00 tomorrow
crontab的语法由五个时间字段和一个命令字段组成:
code复制* * * * * command
分别表示:分钟(0-59) 小时(0-23) 日(1-31) 月(1-12) 周几(0-7) 命令
常见示例:
bash复制# 每天凌晨3点执行备份
0 3 * * * /home/user/backup.sh
# 每5分钟检查一次服务状态
*/5 * * * * /usr/bin/check_service.sh
环境变量问题:cron执行环境与用户shell环境不同,建议在脚本中显式设置PATH等变量
日志记录:总是重定向输出到日志文件
bash复制* * * * * /path/to/command >> /var/log/cron.log 2>&1
当cron任务没有按预期执行时,按这个顺序检查:
bash复制* * * * * /usr/bin/flock -n /tmp/myjob.lock /path/to/script.sh
bash复制0 3 * * * nice -n 19 /path/to/cpu_intensive_task.sh
bash复制# 每周一凌晨清理临时文件
0 0 * * 1 find /tmp -type f -mtime +7 -delete
# 每天检查磁盘空间
0 6 * * * /usr/bin/df -h > /var/log/disk_usage.log
bash复制# 工作日每2小时运行测试套件
0 */2 * * 1-5 cd /project && make test
# 每分钟监控某个进程
* * * * * pgrep -f "python3 app.py" || /usr/bin/systemctl restart myapp
bash复制# 电商大促前1小时预热缓存
0 19 11 11 * /usr/bin/curl -X POST http://localhost:8000/warmup
# 每季度第一天生成报表
0 8 1 */3 * /usr/local/bin/generate_report.sh Q$(date +\%q)
bash复制# 错误写法
* * * * * date +%Y-%m-%d > /tmp/date.log
# 正确写法
* * * * * date +\%Y-\%m-\%d > /tmp/date.log
bash复制PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
bash复制timedatectl set-timezone Asia/Shanghai
bash复制chmod +x /path/to/script.sh
bash复制# 只收集错误日志
* * * * * /path/to/script.sh >/dev/null