Shell脚本如何配置容器日志轮转

wen 实用脚本 2

本文目录导读:

Shell脚本如何配置容器日志轮转

  1. Docker内置日志轮转配置
  2. 使用logrotate工具
  3. 自定义日志轮转脚本
  4. 配置环境变量方式
  5. Docker Compose批量配置
  6. 监控和告警脚本
  7. 推荐的最佳实践

在Shell脚本中配置容器日志轮转主要有以下几种方法:

Docker内置日志轮转配置

创建日志轮转配置文件

#!/bin/bash
# 创建Docker daemon配置文件
cat > /etc/docker/daemon.json <<EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF
# 重启Docker服务使配置生效
systemctl restart docker

针对单个容器的日志配置

#!/bin/bash
# 运行容器时指定日志轮转参数
docker run -d \
  --name myapp \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:latest

使用logrotate工具

安装logrotate

#!/bin/bash
# 检查并安装logrotate
if ! command -v logrotate &> /dev/null; then
    apt-get update && apt-get install -y logrotate
    # 或 yum install -y logrotate
fi

配置logrotate规则

#!/bin/bash
# 创建Docker容器日志轮转配置
cat > /etc/logrotate.d/docker-containers <<EOF
# Docker容器日志轮转配置
/var/lib/docker/containers/*/*.log {
    rotate 7
    daily
    compress
    missingok
    delaycompress
    copytruncate
    notifempty
    maxsize 100M
    dateext
    dateformat -%Y%m%d
    postrotate
        # 触发Docker重新打开日志文件
        docker container ls -q | xargs -I {} docker inspect {} --format '{{.LogPath}}' | while read logfile; do
            if [ -f "$logfile" ]; then
                kill -USR1 $(docker inspect $(docker ps -q) --format '{{.State.Pid}}' 2>/dev/null) 2>/dev/null
            fi
        done
    endscript
}
EOF
# 立即测试轮转配置
logrotate -vf /etc/logrotate.d/docker-containers

自定义日志轮转脚本

基础日志轮转脚本

#!/bin/bash
# 日志轮转函数
rotate_container_logs() {
    local CONTAINER_NAME=$1
    local MAX_SIZE=${2:-100M}
    local MAX_FILES=${3:-5}
    echo "开始轮转容器日志: $CONTAINER_NAME"
    # 获取容器日志路径
    LOG_PATH=$(docker inspect --format='{{.LogPath}}' "$CONTAINER_NAME" 2>/dev/null)
    if [ -z "$LOG_PATH" ]; then
        echo "错误: 找不到容器 $CONTAINER_NAME 的日志路径"
        return 1
    fi
    # 检查日志文件大小
    CURRENT_SIZE=$(stat -c%s "$LOG_PATH" 2>/dev/null || echo 0)
    MAX_BYTES=$(numfmt --from=iec "$MAX_SIZE" 2>/dev/null || echo 104857600)
    if [ "$CURRENT_SIZE" -gt "$MAX_BYTES" ]; then
        echo "当前日志大小: $(numfmt --to=iec $CURRENT_SIZE)"
        # 轮转旧日志
        for i in $(seq $((MAX_FILES-1)) -1 1); do
            if [ -f "${LOG_PATH}.${i}" ]; then
                mv "${LOG_PATH}.${i}" "${LOG_PATH}.$((i+1))"
            fi
        done
        # 重命名当前日志
        if [ -f "$LOG_PATH" ]; then
            cp "$LOG_PATH" "${LOG_PATH}.1"
            : > "$LOG_PATH"
        fi
        # 通知Docker重新打开日志文件
        docker kill --signal=USR1 "$CONTAINER_NAME" 2>/dev/null
        echo "日志轮转完成"
    else
        echo "日志大小未超过限制,跳过轮转"
    fi
}
# 使用示例
rotate_container_logs "myapp" "50M" 3

高级日志管理脚本

#!/bin/bash
# 容器日志管理器
CONTAINER_LOG_MANAGER() {
    local ACTION=$1
    case "$ACTION" in
        setup)
            # 设置定时任务
            (crontab -l 2>/dev/null; echo "*/30 * * * * /usr/local/bin/container-log-rotate.sh rotate") | crontab -
            echo "定时任务已设置"
            ;;
        rotate)
            # 遍历所有运行容器
            docker ps --format '{{.Names}}' | while read container; do
                if [ -n "$container" ]; then
                    echo "处理容器: $container"
                    rotate_container_logs "$container" "100M" 5
                fi
            done
            ;;
        cleanup)
            # 清理超过7天的压缩日志
            find /var/lib/docker/containers/ -name "*.log.*.gz" -mtime +7 -delete
            echo "清理完成"
            ;;
        status)
            # 显示日志状态
            echo "=== 容器日志状态 ==="
            docker ps --format 'table {{.Names}}\t{{.Status}}' | while read line; do
                container=$(echo "$line" | awk '{print $1}')
                if [ "$container" != "NAMES" ]; then
                    log_path=$(docker inspect --format='{{.LogPath}}' "$container" 2>/dev/null)
                    if [ -f "$log_path" ]; then
                        size=$(stat -c%s "$log_path" 2>/dev/null || echo 0)
                        echo "$container: $(numfmt --to=iec $size)"
                    fi
                fi
            done
            ;;
        *)
            echo "用法: $0 {setup|rotate|cleanup|status}"
            exit 1
            ;;
    esac
}
# 主程序入口
if [ "${BASH_SOURCE[0]}" -ef "$0" ]; then
    CONTAINER_LOG_MANAGER "$@"
fi

配置环境变量方式

#!/bin/bash
# 通过Docker环境变量配置(适用于使用特定日志驱动的容器)
docker run -d \
  --name myapp \
  -e "LOG_MAX_SIZE=10m" \
  -e "LOG_MAX_FILE=3" \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:latest
# 在docker-compose.yml中配置
cat > docker-compose.yml <<EOF
version: '3.8'
services:
  web:
    image: nginx:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
EOF
# 启动服务
docker-compose up -d

Docker Compose批量配置

#!/bin/bash
# 批量配置所有容器的日志轮转
configure_all_containers_logging() {
    local MAX_SIZE=${1:-50m}
    local MAX_FILE=${2:-3}
    # 更新所有容器的日志配置
    docker ps -q | while read container_id; do
        echo "更新容器日志配置: $container_id"
        docker update \
            --log-opt max-size=$MAX_SIZE \
            --log-opt max-file=$MAX_FILE \
            $container_id
    done
}
# 使用示例
configure_all_containers_logging "10m" 3

监控和告警脚本

#!/bin/bash
# 日志大小监控脚本
check_container_logs() {
    local WARN_SIZE=${1:-500M}
    local CRIT_SIZE=${2:-1G}
    local WARN_BYTES=$(numfmt --from=iec "$WARN_SIZE")
    local CRIT_BYTES=$(numfmt --from=iec "$CRIT_SIZE")
    echo "开始检查容器日志大小..."
    docker ps --format '{{.Names}}' | while read container; do
        log_path=$(docker inspect --format='{{.LogPath}}' "$container" 2>/dev/null)
        if [ -f "$log_path" ]; then
            current_size=$(stat -c%s "$log_path")
            if [ "$current_size" -gt "$CRIT_BYTES" ]; then
                echo "严重警告: 容器 $container 日志大小 $(numfmt --to=iec $current_size) 超过临界值 $CRIT_SIZE"
                # 可以在这里添加发送告警的代码
            elif [ "$current_size" -gt "$WARN_BYTES" ]; then
                echo "警告: 容器 $container 日志大小 $(numfmt --to=iec $current_size) 超过预警值 $WARN_SIZE"
            fi
        fi
    done
}
# 使用示例
check_container_logs "200M" "500M"

推荐的最佳实践

  1. 优先使用Docker内置配置:效率最高,资源消耗最小
  2. 结合logrotate:当需要更复杂的轮转策略时
  3. 设置合理的限制:建议 max-size=10m100mmax-file=37
  4. 定期检查:添加监控告警,防止日志爆满
  5. 使用copytruncate:避免需要重启容器

选择哪种方式取决于你的具体需求,推荐优先使用Docker内置的日志轮转功能。

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