Shell脚本如何配置容器监控归档

wen 实用脚本 1

本文目录导读:

Shell脚本如何配置容器监控归档

  1. 基础监控脚本框架
  2. 增强版监控(包含健康检查)
  3. 日志归档函数
  4. 性能监控增强
  5. 主循环和调度
  6. 配置文件和用法
  7. Systemd 服务配置
  8. 使用示例

我来详细介绍Shell脚本配置容器监控归档的方法:

基础监控脚本框架

#!/bin/bash
# 容器监控归档脚本
# 版本: 1.0
# 功能: 监控容器状态并归档日志
# 配置参数
CONTAINER_NAMES=("nginx" "mysql" "redis")  # 需要监控的容器
LOG_DIR="/var/log/container_monitor"
ARCHIVE_DIR="/var/log/container_archive"
RETENTION_DAYS=30
INTERVAL=60  # 监控间隔(秒)
# 创建必要目录
mkdir -p "$LOG_DIR" "$ARCHIVE_DIR"
# 日志函数
log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" | tee -a "$LOG_DIR/monitor.log"
}
log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" | tee -a "$LOG_DIR/monitor.log"
}
# 检查Docker是否运行
check_docker() {
    if ! docker info &>/dev/null; then
        log_error "Docker服务未运行"
        return 1
    fi
    return 0
}
# 监控单个容器
monitor_container() {
    local container_name=$1
    local container_status
    local cpu_usage
    local memory_usage
    # 获取容器状态
    container_status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
    if [ $? -ne 0 ]; then
        log_error "无法获取容器 $container_name 的状态"
        return 1
    fi
    # 获取资源使用情况
    if [ "$container_status" = "running" ]; then
        cpu_usage=$(docker stats --no-stream --format "{{.CPUPerc}}" "$container_name" | sed 's/%//')
        memory_usage=$(docker stats --no-stream --format "{{.MemPerc}}" "$container_name" | sed 's/%//')
    else
        cpu_usage=0
        memory_usage=0
    fi
    # 记录监控数据
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "$timestamp,$container_name,$container_status,$cpu_usage,$memory_usage" >> "$LOG_DIR/${container_name}_metrics.csv"
    # 输出状态
    echo "容器: $container_name | 状态: $container_status | CPU: ${cpu_usage}% | 内存: ${memory_usage}%"
}

增强版监控(包含健康检查)

#!/bin/bash
# 增强监控函数
enhanced_monitor() {
    local container_name=$1
    local restart_count
    local last_start
    local health_status
    # 获取重启次数
    restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
    # 获取最后启动时间
    last_start=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
    # 健康检查(如果容器定义HEALTHCHECK)
    health_status=$(docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}N/A{{end}}' "$container_name" 2>/dev/null)
    # 记录到日志
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "$timestamp,$container_name,$restart_count,$last_start,$health_status" >> "$LOG_DIR/${container_name}_health.csv"
}
# 告警函数
send_alert() {
    local container_name=$1
    local alert_type=$2
    local message="容器告警: $container_name - $alert_type"
    # 这里可以集成各种告警方式
    # 1. 发送邮件
    # echo "$message" | mail -s "容器告警" admin@example.com
    # 2. 发送到Slack
    # curl -X POST -H "Content-type: application/json" \
    #     --data "{\"text\":\"$message\"}" \
    #     YOUR_SLACK_WEBHOOK_URL
    # 3. 写入系统日志
    logger -t container_monitor "$message"
    log_error "$message"
}

日志归档函数

#!/bin/bash
# 归档日志
archive_logs() {
    local archive_date=$1
    local archive_file="$ARCHIVE_DIR/monitor_archive_${archive_date}.tar.gz"
    log_info "开始归档日志..."
    # 归档CSV文件
    find "$LOG_DIR" -name "*_metrics.csv" -mtime +1 -exec tar -rzf "$archive_file" {} \;
    find "$LOG_DIR" -name "*_health.csv" -mtime +1 -exec tar -rzf "$archive_file" {} \;
    # 归档日志文件
    if [ -f "$LOG_DIR/monitor.log" ]; then
        cp "$LOG_DIR/monitor.log" "$ARCHIVE_DIR/monitor_${archive_date}.log"
        > "$LOG_DIR/monitor.log"
    fi
    # 清理7天前的归档文件
    find "$ARCHIVE_DIR" -name "*.tar.gz" -mtime +7 -delete
    log_info "日志归档完成: $archive_file"
}
# 压缩旧的监控数据
compress_old_data() {
    local days=$1
    for container in "${CONTAINER_NAMES[@]}"; do
        local csv_file="$LOG_DIR/${container}_metrics.csv"
        if [ -f "$csv_file" ]; then
            # 提取旧数据
            local old_data=$(awk -v days="$days" 'BEGIN{cutoff=systime()-days*86400} {gsub(/[-:]/," ",$1); t=mktime($1" 00 00 00"); if(t<cutoff) print}' "$csv_file")
            if [ -n "$old_data" ]; then
                # 归档旧数据
                echo "$old_data" >> "$ARCHIVE_DIR/${container}_old_metrics.csv"
                # 从主文件删除
                awk -v days="$days" 'BEGIN{cutoff=systime()-days*86400} {gsub(/[-:]/," ",$1); t=mktime($1" 00 00 00"); if(t>=cutoff) print}' "$csv_file" > "${csv_file}.tmp"
                mv "${csv_file}.tmp" "$csv_file"
            fi
        fi
    done
    log_info "已压缩 $days 天前的监控数据"
}

性能监控增强

#!/bin/bash
# 磁盘使用监控
monitor_storage() {
    local container_name=$1
    # 获取容器磁盘使用
    local disk_usage=$(docker system df --format "{{.Size}}" | head -1)
    local disk_size=$(docker system df --format "{{.TotalSize}}" | head -1)
    echo "$(date '+%Y-%m-%d %H:%M:%S'),$container_name,$disk_usage,$disk_size" >> "$LOG_DIR/${container_name}_storage.csv"
    # 检查磁盘使用率
    local usage_percent=$(echo "$disk_usage" | sed 's/[A-Za-z]//g' | awk '{print $1}')
    if [ "$usage_percent" -gt 80 ]; then
        send_alert "$container_name" "存储使用率超过80%: ${usage_percent}%"
    fi
}
# 网络监控
monitor_network() {
    local container_name=$1
    # 获取网络统计
    local network_stats=$(docker stats --no-stream --format "{{.NetIO}}" "$container_name" 2>/dev/null)
    if [ -n "$network_stats" ]; then
        local input=$(echo "$network_stats" | awk '{print $1}')
        local output=$(echo "$network_stats" | awk '{print $3}')
        echo "$(date '+%Y-%m-%d %H:%M:%S'),$container_name,$input,$output" >> "$LOG_DIR/${container_name}_network.csv"
    fi
}

主循环和调度

#!/bin/bash
# 主监控循环
main_monitor_loop() {
    while true; do
        if ! check_docker; then
            sleep 60
            continue
        fi
        for container in "${CONTAINER_NAMES[@]}"; do
            monitor_container "$container"
            enhanced_monitor "$container"
            monitor_storage "$container"
            monitor_network "$container"
        done
        # 每天归档一次
        local current_hour=$(date +%H)
        if [ "$current_hour" = "00" ]; then
            archive_logs "$(date +%Y%m%d)"
            compress_old_data 7
        fi
        sleep "$INTERVAL"
    done
}
# 清理函数
cleanup() {
    log_info "接收到终止信号,正在清理..."
    # 记录最后状态
    for container in "${CONTAINER_NAMES[@]}"; do
        docker inspect "$container" &>/dev/null && \
            echo "$(date '+%Y-%m-%d %H:%M:%S'),SHUTDOWN" >> "$LOG_DIR/${container}_health.csv"
    done
    # 归档当前数据
    archive_logs "final_$(date +%Y%m%d_%H%M%S)"
    exit 0
}
# 设置信号处理
trap cleanup SIGINT SIGTERM
# 启动监控
log_info "容器监控系统启动"
log_info "监控容器: ${CONTAINER_NAMES[*]}"
main_monitor_loop

配置文件和用法

#!/bin/bash
# config.sh - 配置文件
MONITOR_CONFIG="/etc/container_monitor/config.conf"
# 默认配置
if [ ! -f "$MONITOR_CONFIG" ]; then
    cat > "$MONITOR_CONFIG" << 'EOF'
# 容器监控配置
# 监控的容器列表
CONTAINERS=(nginx mysql redis)
# 监控间隔(秒)
INTERVAL=60
# 日志目录
LOG_DIR=/var/log/container_monitor
# 归档目录
ARCHIVE_DIR=/var/log/container_archive
# 日志保留天数
RETENTION_DAYS=30
# 告警阈值(%)
CPU_ALERT_THRESHOLD=80
MEMORY_ALERT_THRESHOLD=80
DISK_ALERT_THRESHOLD=80
# 告警方式: email, slack, webhook
ALERT_METHOD=email
ALERT_EMAIL=admin@example.com
SLACK_WEBHOOK_URL=
WEBHOOK_URL=
EOF
    echo "配置文件已创建: $MONITOR_CONFIG"
fi
# 加载配置
source "$MONITOR_CONFIG"
# 验证配置
validate_config() {
    local errors=0
    # 检查Docker是否可用
    if ! command -v docker &>/dev/null; then
        echo "错误: Docker未安装"
        errors=1
    fi
    # 检查必要目录
    for dir in "$LOG_DIR" "$ARCHIVE_DIR"; do
        if [ ! -d "$dir" ]; then
            mkdir -p "$dir" || {
                echo "错误: 无法创建目录 $dir"
                errors=1
            }
        fi
    done
    # 验证容器存在
    for container in "${CONTAINERS[@]}"; do
        if ! docker ps -a --format '{{.Names}}' | grep -q "^${container}$"; then
            echo "警告: 容器 $container 不存在"
        fi
    done
    return $errors
}

Systemd 服务配置

# /etc/systemd/system/container-monitor.service
[Unit]
Description=Container Monitoring Service
After=docker.service
Requires=docker.service
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/container-monitor.sh
ExecStop=/usr/local/bin/container-monitor.sh stop
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

使用示例

# 启动监控
./container-monitor.sh
# 或使用Systemd
systemctl start container-monitor
systemctl enable container-monitor
# 查看监控数据
cat /var/log/container_monitor/nginx_metrics.csv
# 查看归档
ls -la /var/log/container_archive/
# 手动归档
./container-monitor.sh --archive
# 查看状态
./container-monitor.sh --status

这个监控系统提供了完整的容器监控、日志归档和告警功能,可以根据实际需求进行扩展和定制。

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