本文目录导读:

我来详细介绍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
这个监控系统提供了完整的容器监控、日志归档和告警功能,可以根据实际需求进行扩展和定制。