第335集定时任务架构实战:crontab自动化运维、清理脚本与企业级任务调度完整解决方案 | 字数总计: 3.5k | 阅读时长: 16分钟 | 阅读量:
定时任务架构实战:crontab自动化运维、清理脚本与企业级任务调度 一、crontab基础 1.1 crontab语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 crontab时间格式: 分钟 小时 日期 月份 星期 命令 0 -59 0 -23 1 -31 1 -12 0 -7 特殊字符: * : 任意值 , : 列表值(例如: 1 ,3,5) - : 范围值(例如: 1 -5 ) / : 步长值(例如: */10) @yearly : 每年 @monthly : 每月 @weekly : 每周 @daily : 每天 @hourly : 每小时
1.2 crontab命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 crontab -e crontab -l crontab -r crontab -u username -e crontab -u username -l cat /var/spool/cron/crontabs/*tail -f /var/log/cronjournalctl -u cron
二、定时清理脚本 2.1 日志清理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #!/bin/bash LOG_DIRS=( "/var/log" "/opt/app/logs" "/tmp" ) DAYS_TO_KEEP=7 log () { echo "[$(date '+%Y-%m-%d %H:%M:%S') ] $@ " >> /var/log/log_cleanup.log } cleanup_logs () { for dir in "${LOG_DIRS[@]} " ; do if [ -d "$dir " ]; then log "清理目录: $dir " find "$dir " -type f -name "*.log" -mtime +$DAYS_TO_KEEP -delete find "$dir " -type f -name "*.log" -size 0 -delete find "$dir " -type f -name "*.log" -size +100M -exec gzip {} \; log "完成清理: $dir " fi done } main () { log "开始日志清理" cleanup_logs log "日志清理完成" echo "日志文件数: $(find ${LOG_DIRS[@]} -name "*.log" 2>/dev/null | wc -l) " echo "磁盘使用: $(df -h /var/log | tail -1) " } main "$@ "
2.2 备份清理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #!/bin/bash BACKUP_ROOT="/opt/backups" DAYS_TO_KEEP=30 cleanup_backups () { log "清理过期备份..." find "$BACKUP_ROOT " -type f -name "*.tar.gz" -mtime +$DAYS_TO_KEEP -delete find "$BACKUP_ROOT " -type f -name "*.sql.gz" -mtime +$DAYS_TO_KEEP -delete find "$BACKUP_ROOT /db" -name "*.sql" -mtime +$DAYS_TO_KEEP -delete find "$BACKUP_ROOT " -name "*.tar.gz" -type f | \ sort -t_ -k4 | \ head -n -30 | \ xargs -r rm log "备份清理完成" } check_disk_usage () { local usage=$(df -h "$BACKUP_ROOT " | tail -1 | awk '{print $5}' | sed 's/%//' ) if [ "$usage " -gt 80 ]; then log "警告: 备份磁盘使用率 ${usage} %" fi } main () { cleanup_backups check_disk_usage } main "$@ "
2.3 缓存清理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #!/bin/bash cleanup_system_cache () { log "清理系统缓存..." if command -v apt &> /dev/null; then apt-get clean apt-get autoclean fi if command -v yum &> /dev/null; then yum clean all fi find /tmp -type f -mtime +7 -delete find /var/tmp -type f -mtime +7 -delete find /home -name ".cache" -type d -mtime +30 -exec rm -rf {} + } cleanup_application_cache () { log "清理应用缓存..." CACHE_DIRS=( "/opt/app/cache" "/var/www/html/cache" ) for dir in "${CACHE_DIRS[@]} " ; do if [ -d "$dir " ]; then find "$dir " -type f -mtime +3 -delete fi done } main () { cleanup_system_cache cleanup_application_cache log "缓存清理完成" } main "$@ "
三、系统维护脚本 3.1 磁盘空间监控 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #!/bin/bash THRESHOLD=85 check_disk_usage () { df -h | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{print $5 " " $1 " " $6}' | \ while read output; do usage=$(echo $output | awk '{print $1}' | cut -d'%' -f1) partition=$(echo $output | awk '{print $2}' ) mount_point=$(echo $output | awk '{print $3}' ) if [ $usage -ge $THRESHOLD ]; then echo "磁盘空间警告: $mount_point ($partition ) 使用率 ${usage} %" send_alert "磁盘空间不足" "$mount_point (${usage} %)" auto_cleanup "$mount_point " fi done } auto_cleanup () { local mount_point=$1 case "$mount_point " in /var/log) find /var/log -name "*.log" -mtime +7 -delete journalctl --vacuum-time=7d ;; /tmp) find /tmp -type f -mtime +7 -delete ;; /opt/backups) find /opt/backups -name "*.tar.gz" -mtime +30 -delete ;; esac log "自动清理完成: $mount_point " } send_alert () { local subject=$1 local message=$2 echo "$message " | mail -s "$subject " admin@example.com curl -X POST "$WEBHOOK_URL " \ -H 'Content-Type: application/json' \ -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$subject : $message \"}}" } main () { check_disk_usage } main "$@ "
3.2 进程监控 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #!/bin/bash CRITICAL_PROCESSES=( "nginx" "mysql" "redis" ) check_process () { local process=$1 if ! pgrep -x "$process " > /dev/null; then log "错误: $process 进程未运行" case "$process " in nginx) systemctl restart nginx ;; mysql) systemctl restart mysql ;; redis) systemctl restart redis ;; esac send_alert "进程重启" "$process 已重启" fi } monitor_all () { for process in "${CRITICAL_PROCESSES[@]} " ; do check_process "$process " done } main () { monitor_all } main "$@ "
3.3 数据库维护 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #!/bin/bash DB_HOST="localhost" DB_USER="root" DB_PASS="password" mysql_maintenance () { log "MySQL维护任务..." mysql -h$DB_HOST -u$DB_USER -p$DB_PASS -e " PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY); " 2>/dev/null mysql -h$DB_HOST -u$DB_USER -p$DB_PASS -e " SET GLOBAL slow_query_log = 0; TRUNCATE TABLE mysql.slow_log; SET GLOBAL slow_query_log = 1; " 2>/dev/null mysql -h$DB_HOST -u$DB_USER -p$DB_PASS -e " OPTIMIZE TABLE table1, table2; " 2>/dev/null log "MySQL维护完成" } postgresql_maintenance () { log "PostgreSQL维护任务..." pg_archivecleanup /var/lib/postgresql/10/main/archive/ oldest_archived_wal psql -U postgres -c "VACUUM ANALYZE;" log "PostgreSQL维护完成" } main () { mysql_maintenance } main "$@ "
四、crontab最佳实践 4.1 任务组织 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 mkdir -p /etc/cron.hourlymkdir -p /etc/cron.daily/custommkdir -p /etc/cron.weekly/custommkdir -p /etc/cron.monthly/customcat > /etc/cron.daily/log-cleanup << 'EOF' /usr/local/bin/log_cleanup.sh EOF chmod +x /etc/cron.daily/log-cleanup
4.2 完整任务配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 * * * * * /usr/local/bin/monitor.sh 0 * * * * /usr/local/bin/health_check.sh 0 2 * * * /usr/local/bin/backup.sh 0 3 * * * /usr/local/bin/cleanup.sh 0 1 * * 0 /usr/local/bin/weekly_maintenance.sh 0 0 1 * * /usr/local/bin/monthly_report.sh 0 9 * * 1-5 /usr/local/bin/workday_task.sh */10 * * * * /usr/local/bin/frequent_task.sh 0 2 * * * user1 /usr/local/bin/task.sh
4.3 系统级任务配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */5 * * * * root /usr/sbin/ntpdate -s pool.ntp.org 0 0 * * * root logrotate /etc/logrotate.conf 0 3 * * 0 root apt-get update && apt-get upgrade -y */30 * * * * root /usr/local/bin/disk_monitor.sh 0 2 * * * root /usr/local/bin/service_restart.sh
五、高级应用 5.1 互斥任务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #!/bin/bash LOCK_FILE="/tmp/task.lock" if [ -f "$LOCK_FILE " ]; then local pid=$(cat "$LOCK_FILE " ) if ps -p $pid > /dev/null 2>&1; then echo "任务正在运行中,跳过本次执行" exit 0 else rm -f "$LOCK_FILE " fi fi echo $$ > "$LOCK_FILE " trap "rm -f $LOCK_FILE " EXITmain_task () { echo "执行任务..." sleep 10 echo "任务完成" } main_task
5.2 任务结果通知 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #!/bin/bash SEND_NOTIFICATION=true task () { echo "执行任务..." if [ $? -eq 0 ]; then notify_success else notify_failure fi } notify_success () { if [ "$SEND_NOTIFICATION " = true ]; then echo "任务执行成功" | mail -s "任务成功" admin@example.com fi } notify_failure () { if [ "$SEND_NOTIFICATION " = true ]; then echo "任务执行失败,请检查" | mail -s "⚠️ 任务失败" admin@example.com curl -X POST "$DINGTALK_WEBHOOK " \ -H 'Content-Type: application/json' \ -d '{"msgtype":"text","text":{"content":"任务执行失败"}}' fi } main () { task } main "$@ "
5.3 任务日志管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #!/bin/bash SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]} " ) " && pwd) " LOG_DIR="$SCRIPT_DIR /logs" TASK_NAME="my_task" TIMESTAMP=$(date +%Y%m%d%H%M%S) LOG_FILE="$LOG_DIR /${TASK_NAME} _${TIMESTAMP} .log" MAX_LOG_SIZE=10M MAX_LOG_COUNT=30 mkdir -p "$LOG_DIR " log () { echo "[$(date '+%Y-%m-%d %H:%M:%S') ] $@ " | tee -a "$LOG_FILE " } log_info () { log "[INFO] $@ " } log_error () { log "[ERROR] $@ " >&2 } rotate_logs () { find "$LOG_DIR " -name "${TASK_NAME} _*.log" -type f | sort -r | tail -n +$((MAX_LOG_COUNT + 1 )) | xargs -r rm find "$LOG_DIR " -name "${TASK_NAME} _*.log" -mtime +7 -exec gzip {} \; } main_task () { log_info "任务开始" log_info "执行任务..." if [ $? -eq 0 ]; then log_info "任务成功" return 0 else log_error "任务失败" return 1 fi } main () { rotate_logs main_task local exit_code=$? if [ $exit_code -ne 0 ]; then log_error "任务执行失败,退出码: $exit_code " fi exit $exit_code } main "$@ "
六、企业级任务调度 6.1 任务调度系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cron任务调度最佳实践: 1 . 任务分类: - 关键任务: 数据库备份 - 维护任务: 日志清理 - 监控任务: 健康检查 2 . 时间选择: - 避开高峰期 - 分散执行时间 - 考虑跨时区 3 . 错误处理: - 重试机制 - 告警通知 - 日志记录 4 . 资源管理: - 避免资源竞争 - 限制并发数 - 监控资源使用
6.2 任务依赖管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #!/bin/bash TASK_STATUS_FILE="/tmp/task_status.json" check_dependency () { local dependency=$1 if [ -f "$TASK_STATUS_FILE " ]; then local status=$(jq -r ".$dependency .status" "$TASK_STATUS_FILE " 2>/dev/null) if [ "$status " != "success" ]; then log_error "前置任务 $dependency 未完成" return 1 fi fi return 0 } record_status () { local task=$1 local status=$2 if [ -f "$TASK_STATUS_FILE " ]; then jq ".$task = {\"status\": \"$status \", \"time\": \"$(date -Iseconds) \"}" \ "$TASK_STATUS_FILE " > "$TASK_STATUS_FILE .tmp" && \ mv "$TASK_STATUS_FILE .tmp" "$TASK_STATUS_FILE " else echo "{\"$task \": {\"status\": \"$status \", \"time\": \"$(date -Iseconds) \"}}" > \ "$TASK_STATUS_FILE " fi } task_backup () { log_info "执行备份..." if check_dependency "monitor" ; then backup_database if [ $? -eq 0 ]; then record_status "backup" "success" else record_status "backup" "failed" fi fi } task_cleanup () { log_info "执行清理..." if check_dependency "backup" ; then cleanup_old_files record_status "cleanup" "success" fi } main () { task_backup task_cleanup } main "$@ "
七、监控和维护 7.1 任务监控 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #!/bin/bash check_cron_status () { if ! systemctl is-active --quiet cron; then echo "❌ Cron服务未运行" systemctl start cron else echo "✓ Cron服务运行正常" fi } check_recent_executions () { echo "最近的cron执行:" tail -20 /var/log/cron 2>/dev/null || journalctl -u cron -n 20 } check_failed_tasks () { echo "检查失败的任务..." grep -i "error\|fail" /var/log/cron 2>/dev/null | tail -10 } main () { check_cron_status check_recent_executions check_failed_tasks } main "$@ "
7.2 任务审计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #!/bin/bash generate_report () { local report_file="/tmp/cron_report_$(date +%Y%m%d) .txt" cat > "$report_file " << EOF Cron任务审计报告 生成时间: $(date) ======================================== 1. 所有用户的任务: EOF for user in $(cut -f1 -d: /etc/passwd); do tasks=$(crontab -u $user -l 2>/dev/null | grep -v '^#' | wc -l) if [ $tasks -gt 0 ]; then echo "$user : $tasks 个任务" >> "$report_file " fi done echo " 2. 系统级任务: " >> "$report_file " ls -la /etc/cron.* >> "$report_file " mail -s "Cron任务审计报告" admin@example.com < "$report_file " } main () { generate_report } main "$@ "
八、最佳实践 8.1 cron配置规范 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 cron最佳实践: 1 . 任务命名: - 使用有意义的名称 - 包含用途说明 - 时间戳记录 2 . 日志管理: - 统一日志目录 - 定期清理旧日志 - 记录执行结果 3 . 错误处理: - 所有命令添加错误处理 - 使用set -e - 发送失败告警 4 . 资源控制: - 避免在高峰期执行 - 限制任务并发 - 监控资源使用 5 . 安全考虑: - 最小权限原则 - 敏感信息加密 - 定期审计任务
8.2 任务模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #!/bin/bash set -e set -u SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]} " ) " && pwd) " LOG_DIR="$SCRIPT_DIR /logs" LOG_FILE="$LOG_DIR /task_$(date +%Y%m%d) .log" mkdir -p "$LOG_DIR " log () { echo "[$(date '+%Y-%m-%d %H:%M:%S') ] $@ " | tee -a "$LOG_FILE " } error () { log "ERROR: $@ " >&2 } success () { log "SUCCESS: $@ " } cleanup () { log "清理临时文件..." } main_task () { log "任务开始" if [ $? -eq 0 ]; then success "任务完成" return 0 else error "任务失败" return 1 fi } trap 'error "任务失败于: $LINENO, 错误码: $?"; cleanup; exit 1' ERRtrap 'cleanup' EXITmain () { main_task } main "$@ "
九、总结 crontab是企业自动化运维的核心工具。本文涵盖:
核心要点
基础配置 :crontab语法、常用命令
清理脚本 :日志、备份、缓存
维护脚本 :磁盘监控、进程监控、数据库维护
任务管理 :互斥任务、通知、日志
技术要点
定时调度 :crontab配置、任务分类
脚本编写 :模板、错误处理、日志
任务监控 :执行状态、审计
最佳实践 :规范、安全、可维护
实践建议
任务分类 :按优先级与频率分类
日志管理 :统一目录与轮转
错误处理 :捕获错误并告警
安全审计 :定期审查任务
性能监控 :避免资源竞争
通过合理的crontab配置,可提高运维效率与可靠性。