Ubuntu定时任务实战:5个生产级脚本与高阶技巧
当你已经掌握crontab -e的基本操作后,是否遇到过这些场景:日志文件撑爆磁盘、服务意外崩溃却无人察觉、数据库备份不完整导致恢复失败?本文将带你突破基础用法,通过5个可直接部署的生产环境脚本,解决实际运维中的高频痛点问题。
1. 日志管理:智能切割与归档方案
日志轮转是系统管理的必修课。原始方案往往简单粗暴地使用logrotate,但缺乏灵活性。下面这个脚本实现了按大小自动切割+压缩归档+过期清理的全套流程:
#!/bin/bash # 日志切割脚本:/usr/local/bin/log_rotate.sh LOG_DIR="/var/log/myapp" MAX_SIZE="200M" # 单个日志文件最大200MB KEEP_DAYS=30 # 保留最近30天日志 find $LOG_DIR -name "*.log" -type f | while read LOGFILE; do # 检查文件大小是否超过阈值 if [ $(du -m "$LOGFILE" | cut -f1) -ge $(echo $MAX_SIZE | sed 's/M//') ]; then TIMESTAMP=$(date +%Y%m%d%H%M%S) mv "$LOGFILE" "${LOGFILE%.*}_${TIMESTAMP}.log" gzip "${LOGFILE%.*}_${TIMESTAMP}.log" & fi done # 清理过期归档 find $LOG_DIR -name "*.gz" -mtime +$KEEP_DAYS -delete关键改进点:
- 动态检测文件大小而非固定周期
- 使用并行压缩(
&)提升处理速度 - 精确控制保留周期而非简单保留固定份数
配置到crontab每小时运行一次:
0 * * * * /usr/local/bin/log_rotate.sh > /dev/null 2>&12. 服务监控:自动重启与告警集成
基础监控工具如Nagios往往有延迟,这个脚本实现了秒级检测+自动恢复+多通道告警:
#!/bin/bash # 服务监控脚本:/usr/local/bin/service_watchdog.sh SERVICE="nginx" MAX_RETRY=3 SMS_API="https://api.alertservice.com/send" EMAIL="admin@example.com" check_service() { systemctl is-active --quiet $SERVICE } send_alert() { MESSAGE="$SERVICE 服务异常,已尝试自动恢复失败" # 短信通知 curl -X POST $SMS_API -d "content=$MESSAGE" # 邮件通知 echo "$MESSAGE" | mail -s "服务告警" $EMAIL } retry_count=0 while [ $retry_count -lt $MAX_RETRY ]; do if ! check_service; then systemctl restart $SERVICE ((retry_count++)) sleep 5 else exit 0 fi done send_alert高级技巧:
- 使用
systemd原生命令而非ps检测更可靠 - 内置重试机制避免误判
- 支持多种通知渠道组合
建议每分钟检测一次:
* * * * * /usr/local/bin/service_watchdog.sh3. 数据库备份:全量+增量+校验三保险
多数备份脚本只做简单dump,缺乏完整性保障。这个MySQL备份方案包含:
#!/bin/bash # 数据库备份脚本:/usr/local/bin/mysql_backup.sh BACKUP_DIR="/backup/mysql" DATE=$(date +%Y%m%d) USER="backup" PASS="securepassword" CONFIG="/etc/mysql/backup.cnf" # 包含敏感信息的配置文件 # 全量备份(每周日) if [ $(date +%u) -eq 7 ]; then mysqldump --defaults-extra-file=$CONFIG --all-databases --single-transaction | gzip > $BACKUP_DIR/full_$DATE.sql.gz # 生成校验码 md5sum $BACKUP_DIR/full_$DATE.sql.gz > $BACKUP_DIR/full_$DATE.md5 else # 增量备份(其他日期) mysqlbinlog --defaults-extra-file=$CONFIG --read-from-remote-server --raw mysql-bin.0* > $BACKUP_DIR/incr_$DATE.binlog fi # 自动清理旧备份 find $BACKUP_DIR -name "*.gz" -mtime +30 -delete find $BACKUP_DIR -name "*.binlog" -mtime +7 -delete生产环境要点:
- 使用配置文件存储密码而非命令行参数
--single-transaction确保备份一致性- 定期清理旧备份避免磁盘爆满
- 校验码验证备份完整性
配套crontab配置:
0 2 * * * /usr/local/bin/mysql_backup.sh4. 网络资源抓取:反爬策略与异常处理
简单wget抓取常被屏蔽,这个脚本模拟浏览器行为并处理各种异常:
#!/bin/bash # 网页抓取脚本:/usr/local/bin/web_fetcher.sh URL="https://example.com/data" OUTPUT_DIR="/data/download" USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" COOKIE_FILE="/tmp/cookies.txt" RETRY_DELAY=60 # 失败后等待60秒重试 fetch_with_retry() { for i in {1..3}; do if wget -q --user-agent="$USER_AGENT" --load-cookies $COOKIE_FILE \ --header="Accept-Language: en-US" --tries=3 --timeout=30 \ -O "$OUTPUT_DIR/data_$(date +%s).json" "$URL"; then # 下载成功后的处理 process_data "$OUTPUT_DIR/data_$(date +%s).json" return 0 else sleep $RETRY_DELAY fi done echo "Failed to fetch $URL after 3 attempts" >> /var/log/web_fetcher.error } process_data() { # 数据清洗和格式转换 jq '.items[] | select(.value > 100)' $1 > "${1%.*}_filtered.json" # 触发后续分析流程 /usr/local/bin/analyze_data.sh "${1%.*}_filtered.json" } fetch_with_retry反爬策略:
- 轮换User-Agent
- 维持会话Cookies
- 随机延迟请求
- 处理HTTP错误码
定时任务配置示例:
*/30 * * * * /usr/local/bin/web_fetcher.sh5. 错失任务处理:anacron与systemd双保险
对于可能因关机错过的重要任务,这个方案结合了两种补偿机制:
方案A:anacron传统方式
#!/bin/bash # 每日任务脚本:/etc/cron.daily/daily_job LOG_FILE="/var/log/daily_job.log" echo "$(date) - 开始执行每日任务" >> $LOG_FILE # 实际任务内容 /usr/local/bin/generate_report.sh /usr/local/bin/clean_tmp_files.sh echo "$(date) - 任务完成" >> $LOG_FILE方案B:systemd定时器(更现代的方式)
# /etc/systemd/system/daily-job.service [Unit] Description=Daily Maintenance Job [Service] Type=oneshot ExecStart=/usr/local/bin/daily_job.sh# /etc/systemd/system/daily-job.timer [Unit] Description=Run daily job with persistence [Timer] OnCalendar=daily Persistent=true # 关键配置:补偿错过的执行 RandomizedDelaySec=1h [Install] WantedBy=timers.target对比选择:
| 特性 | anacron | systemd timer |
|---|---|---|
| 时间精度 | 天级 | 分钟级 |
| 错失任务补偿 | 内置支持 | 需Persistent=true |
| 资源控制 | 有限 | 支持CPU/内存限制 |
| 日志管理 | 需手动记录 | 集成journalctl |
启用systemd定时器:
systemctl enable --now daily-job.timer高阶调试技巧
当定时任务未按预期执行时,按此流程排查:
检查执行环境
# 查看cron服务状态 systemctl status cron # 检查日志(Ubuntu默认日志位置) grep CRON /var/log/syslog环境变量问题
# 在脚本开头显式设置PATH export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin权限控制
# 检查脚本权限 chmod +x /path/to/script.sh # 测试以cron用户身份运行 sudo -u nobody /path/to/script.sh错误捕获
# 在crontab中重定向错误输出 * * * * * /path/to/script.sh >> /var/log/cron.log 2>&1 # 脚本内部设置错误陷阱 trap 'echo "ERROR at line $LINENO" >> /var/log/script.error' ERR
特别提醒:对于需要交互的任务(如密码输入),考虑使用expect脚本或配置免密认证。生产环境中,所有密码应通过配置文件或密钥管理服务获取,切勿硬编码在脚本中。