Shell脚本如何实现日志轮转功能

wen 实用脚本 1

本文目录导读:

Shell脚本如何实现日志轮转功能

  1. 基础日志轮转脚本
  2. 带压缩功能的日志轮转
  3. 基于大小的日志轮转(支持后缀编号)
  4. 基于时间的日志轮转
  5. 完整的企业级日志轮转脚本
  6. 使用crontab自动执行
  7. 使用建议

Shell脚本实现日志轮转可以通过多种方式,这里提供几种常见的实现方案:

基础日志轮转脚本

#!/bin/bash
# 日志轮转配置
LOG_DIR="/var/log/myapp"
LOG_FILE="app.log"
MAX_SIZE="10M"  # 单个日志最大大小
KEEP_DAYS=7     # 保留天数
# 确保日志目录存在
mkdir -p "$LOG_DIR"
# 日志轮转函数
rotate_log() {
    local log_path="$LOG_DIR/$LOG_FILE"
    # 检查日志文件是否存在且大小超过限制
    if [ -f "$log_path" ]; then
        local file_size=$(stat -f%z "$log_path" 2>/dev/null || stat -c%s "$log_path" 2>/dev/null)
        local max_bytes=$((10 * 1024 * 1024))  # 10M = 10*1024*1024
        if [ "$file_size" -gt "$max_bytes" ]; then
            # 备份当前日志
            local timestamp=$(date +%Y%m%d_%H%M%S)
            cp "$log_path" "$LOG_DIR/${LOG_FILE}.${timestamp}.bak"
            # 清空原日志
            > "$log_path"
            # 删除过期备份
            find "$LOG_DIR" -name "${LOG_FILE}.*.bak" -mtime +$KEEP_DAYS -delete
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] 日志轮转完成" >> "$log_path"
        fi
    fi
}
# 运行日志轮转
rotate_log

带压缩功能的日志轮转

#!/bin/bash
# 配置
LOG_FILE="/var/log/myapp/application.log"
MAX_SIZE="10M"
MAX_FILES=5  # 保留的最大日志文件数
COMPRESS=true
# 转换大小
convert_size() {
    local size=$1
    local unit=${size: -1}
    local num=${size%?}
    case $unit in
        M|m) echo $((num * 1024 * 1024)) ;;
        G|g) echo $((num * 1024 * 1024 * 1024)) ;;
        K|k) echo $((num * 1024)) ;;
        *) echo "$size" ;;
    esac
}
# 执行日志轮转
rotate_with_compression() {
    local max_bytes=$(convert_size "$MAX_SIZE")
    local log_dir=$(dirname "$LOG_FILE")
    local log_name=$(basename "$LOG_FILE")
    # 检查文件大小
    if [ -f "$LOG_FILE" ]; then
        local current_size=$(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null)
        if [ "$current_size" -gt "$max_bytes" ]; then
            # 轮转现有日志
            for ((i=MAX_FILES-1; i>=0; i--)); do
                local old_file="$LOG_FILE.$i"
                if [ "$i" -eq 0 ]; then
                    # 最新备份
                    cp "$LOG_FILE" "$old_file"
                else
                    local prev_file="$LOG_FILE.$((i-1))"
                    if [ -f "$prev_file" ]; then
                        mv "$prev_file" "$old_file"
                    fi
                fi
            done
            # 压缩旧日志
            if [ "$COMPRESS" = true ]; then
                for ((i=1; i<MAX_FILES; i++)); do
                    local file_to_compress="$LOG_FILE.$i"
                    if [ -f "$file_to_compress" ]; then
                        gzip -f "$file_to_compress"
                    fi
                done
            fi
            # 清空原日志
            > "$LOG_FILE"
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] 日志轮转完成 (压缩: $COMPRESS)" >> "$LOG_FILE"
        fi
    fi
}
# 执行
rotate_with_compression

基于大小的日志轮转(支持后缀编号)

#!/bin/bash
# 配置
LOG_DIR="/var/log/app"
BASE_NAME="app"
LOG_EXTENSION=".log"
MAX_SIZE="5M"
MAX_BACKUPS=3
# 日志轮转函数
rotate_by_size() {
    local log_file="$LOG_DIR/${BASE_NAME}${LOG_EXTENSION}"
    local max_bytes=$(echo "$MAX_SIZE" | sed 's/M$/*1024*1024/' | sed 's/K$/*1024/' | bc)
    # 检查日志文件
    if [ -f "$log_file" ]; then
        local file_size=$(stat -c%s "$log_file" 2>/dev/null)
        if [ "$file_size" -gt "$max_bytes" ]; then
            # 轮转备份文件
            for ((i=MAX_BACKUPS-1; i>=0; i--)); do
                local old_backup="${LOG_DIR}/${BASE_NAME}.${i}${LOG_EXTENSION}"
                if [ "$i" -eq 0 ]; then
                    mv "$log_file" "$old_backup" 2>/dev/null
                else
                    local new_backup="${LOG_DIR}/${BASE_NAME}.${i}${LOG_EXTENSION}"
                    if [ -f "$old_backup" ]; then
                        mv "$old_backup" "$new_backup" 2>/dev/null
                    fi
                fi
            done
            # 创建新的空日志文件
            > "$log_file"
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] 日志已轮转" >> "$log_file"
        fi
    fi
}
# 执行
rotate_by_size

基于时间的日志轮转

#!/bin/bash
# 配置
LOG_FILE="/var/log/app/application.log"
ROTATE_HOURLY=true
ROTATE_DAILY=true
DAILY_ROTATE_TIME="00:00"  # 每天轮转时间
# 时间轮转
rotate_by_time() {
    local log_dir=$(dirname "$LOG_FILE")
    local log_name=$(basename "$LOG_FILE")
    local current_hour=$(date +%H)
    local current_date=$(date +%Y%m%d)
    # 每天轮转
    if [ "$ROTATE_DAILY" = true ] && [ "$current_hour" = "00" ]; then
        local backup_name="${log_dir}/${log_name%.*}_${current_date}.log"
        if [ -f "$LOG_FILE" ] && [ -s "$LOG_FILE" ]; then
            mv "$LOG_FILE" "$backup_name"
            > "$LOG_FILE"
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] 每日日志轮转" >> "$LOG_FILE"
            # 压缩旧的日志
            gzip -f "$backup_name" 2>/dev/null
        fi
    fi
    # 每小时轮转(可选)
    if [ "$ROTATE_HOURLY" = true ]; then
        # 可以在这里添加每小时轮转逻辑
        :
    fi
}
# 清理过期日志
cleanup_old_logs() {
    local log_dir=$(dirname "$LOG_FILE")
    # 保留30天的日志
    find "$log_dir" -name "*.log.gz" -mtime +30 -delete
    find "$log_dir" -name "*.log.*" -mtime +30 -delete
}
# 执行
rotate_by_time
cleanup_old_logs

完整的企业级日志轮转脚本

#!/bin/bash
# 完整的日志轮转系统
LOGGING_SYSTEM() {
    # 配置
    local LOG_FILE="/var/log/enterprise/app.log"
    local MAX_SIZE="50M"
    local MAX_FILES=10
    local COMPRESS_OLD=true
    local ROTATE_INTERVAL="daily"
    # 日志配置
    mkdir -p /var/log/enterprise/backups
    # 日志轮转主函数
    log_rotation_main() {
        case "$1" in
            "check")
                check_log_size
                ;;
            "rotate")
                perform_rotation
                ;;
            "cleanup")
                cleanup_old_logs
                ;;
            "status")
                show_log_status
                ;;
            *)
                echo "使用方法: $0 {check|rotate|cleanup|status}"
                exit 1
                ;;
        esac
    }
    # 检查日志大小
    check_log_size() {
        if [ -f "$LOG_FILE" ]; then
            local size=$(stat -c%s "$LOG_FILE")
            local max=$(echo "$MAX_SIZE" | sed 's/M$/*1024*1024/' | bc)
            echo "当前大小: $(echo "scale=2; $size/1024/1024" | bc)M"
            echo "最大限制: $MAX_SIZE"
            if [ "$size" -gt "$max" ]; then
                echo "需要轮转"
                return 0
            else
                echo "正常"
                return 1
            fi
        fi
    }
    # 执行轮转
    perform_rotation() {
        if check_log_size >/dev/null 2>&1; then
            local timestamp=$(date +%Y%m%d_%H%M%S)
            local backup_file="/var/log/enterprise/backups/app_${timestamp}.log"
            echo "$(date) - 开始日志轮转" >> /var/log/enterprise/rotation.log
            # 复制当前日志
            cp "$LOG_FILE" "$backup_file"
            # 压缩
            if [ "$COMPRESS_OLD" = true ]; then
                gzip -f "$backup_file"
            fi
            # 清空当前日志
            > "$LOG_FILE"
            echo "$(date) - 日志轮转完成: $backup_file" >> /var/log/enterprise/rotation.log
        fi
    }
    # 清理旧日志
    cleanup_old_logs() {
        echo "清理30天前的日志..."
        find /var/log/enterprise/backups -name "*.log*" -mtime +30 -delete
        echo "清理完成"
    }
    # 显示日志状态
    show_log_status() {
        echo "=== 日志状态 ==="
        echo "主日志: $LOG_FILE"
        echo "大小: $(ls -lh "$LOG_FILE" | awk '{print $5}')"
        echo "备份数量: $(ls /var/log/enterprise/backups/*.log* 2>/dev/null | wc -l)"
        echo "配置:"
        echo "  MAX_SIZE=$MAX_SIZE"
        echo "  MAX_FILES=$MAX_FILES"
        echo "  COMPRESS=$COMPRESS_OLD"
    }
    # 执行
    log_rotation_main "$@"
}
# 运行
LOGGING_SYSTEM "$@"

使用crontab自动执行

# 添加定时任务,每6小时检查一次
# crontab -e 添加以下内容
0 */6 * * * /path/to/rotate.sh
# 或者使用systemd timer
# 创建服务文件 /etc/systemd/system/log-rotate.service
[Unit]
Description=Custom Log Rotation Service
[Service]
Type=oneshot
ExecStart=/path/to/rotate.sh
User=root
# 创建定时器 /etc/systemd/system/log-rotate.timer
[Unit]
Description=Run log rotation every 6 hours
[Timer]
OnCalendar=*-*-* 00,06,12,18:00:00
Persistent=true
[Install]
WantedBy=timers.target

使用建议

  1. 选择合适的轮转策略:根据日志增长速度和重要性选择按大小或时间轮转
  2. 测试脚本:在生产环境使用前充分测试
  3. 监控日志轮转:添加日志记录轮转操作的执行情况
  4. 资源考虑:大型日志文件轮转会消耗CPU和I/O资源
  5. 权限管理:确保脚本有适当权限访问和修改日志文件

这些脚本可以根据具体需求调整配置,如修改大小限制、保留天数、压缩选项等。

抱歉,评论功能暂时关闭!