Docker容器状态监控与自动重启

代码脚本 · 容器

监控Docker容器运行状态,容器异常退出时自动重启,支持重启次数统计、资源使用监控和告警通知

详细内容

#!/bin/bash # ========================================== # Docker容器状态监控与自动重启脚本 # 用途:监控Docker容器,异常退出自动重启 # 使用方法: # 1. 修改 CONTAINERS 配置 # 2. bash docker_monitor.sh # 3. 建议用systemd或nohup后台运行 # ========================================== # ========== 配置 ========== # 监控的容器名(留空则监控所有容器) CONTAINERS=() # 例如: CONTAINERS=("nginx" "mysql" "redis") CHECK_INTERVAL=30 # 检测间隔(秒) MAX_RESTART=5 # 单个容器最大重启次数(超过后告警) RESTART_WINDOW=300 # 重启统计窗口(秒) CPU_WARN=80 # CPU使用率告警阈值(%) MEM_WARN=80 # 内存使用率告警阈值(%) LOG_FILE="/var/log/docker_monitor.log" ALERT_EMAIL="" WECOM_WEBHOOK="" # ========================== mkdir -p "$(dirname "$LOG_FILE")" declare -A RESTART_COUNT declare -A LAST_RESTART log_msg() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } send_alert() { local title="$1" local content="$2" log_msg "【告警】$title: $content" if [ -n "$ALERT_EMAIL" ]; then echo -e "$content" | mail -s "【Docker告警】$title" "$ALERT_EMAIL" 2>/dev/null fi if [ -n "$WECOM_WEBHOOK" ]; then curl -s "$WECOM_WEBHOOK" -H "Content-Type: application/json" -d "{ "msgtype": "text", "text": {"content": "【Docker告警】$title\n$content\n主机: $(hostname)"} }" >/dev/null 2>&1 fi } check_docker_available() { if ! command -v docker >/dev/null 2>&1; then log_msg "❌ Docker未安装" exit 1 fi if ! docker info >/dev/null 2>&1; then log_msg "❌ Docker服务未运行" send_alert "Docker服务未运行" "Docker daemon未启动,请检查Docker服务状态" exit 1 fi } get_monitor_containers() { if [ ${#CONTAINERS[@]} -eq 0 ]; then docker ps -a --format "{{.Names}}" 2>/dev/null else printf "%s\n" "${CONTAINERS[@]}" fi } check_container_status() { local container="$1" # 检查容器是否存在 if ! docker inspect "$container" >/dev/null 2>&1; then log_msg "⚠️ 容器 $container 不存在,跳过" return fi local status=$(docker inspect -f '{{.State.Status}}' "$container" 2>/dev/null) local restart_count=$(docker inspect -f '{{.RestartCount}}' "$container" 2>/dev/null) case "$status" in running) log_msg "🟢 $container: 运行中 (重启次数: $restart_count)" ;; exited) local exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$container" 2>/dev/null) log_msg "🔴 $container: 已退出 (退出码: $exit_code, 重启次数: $restart_count)" # 检查重启计数窗口 local now=$(date +%s) local last=${LAST_RESTART[$container]:-0} if [ $((now - last)) -gt $RESTART_WINDOW ]; then RESTART_COUNT[$container]=0 fi local count=${RESTART_COUNT[$container]:-0} if [ "$count" -ge "$MAX_RESTART" ]; then send_alert "容器 $container 重启次数超限" "已自动重启 $count 次,超过最大限制 $MAX_RESTART 次,请人工检查!\n最近日志:\n$(docker logs --tail 20 "$container" 2>&1)" return fi # 尝试重启 log_msg " 尝试重启容器 $container..." if docker start "$container" >> "$LOG_FILE" 2>&1; then sleep 3 local new_status=$(docker inspect -f '{{.State.Status}}' "$container" 2>/dev/null) if [ "$new_status" = "running" ]; then RESTART_COUNT[$container]=$((count + 1)) LAST_RESTART[$container]=$now log_msg " ✓ 容器 $container 重启成功 (第${RESTART_COUNT[$container]}次)" send_alert "容器 $container 已自动重启" "容器异常退出(退出码:$exit_code),已自动重启成功 (第${RESTART_COUNT[$container]}次)" else log_msg " ✗ 容器 $container 重启后仍未运行" send_alert "容器 $container 重启失败" "重启后容器状态: $new_status,请人工检查!\n最近日志:\n$(docker logs --tail 20 "$container" 2>&1)" fi else log_msg " ✗ 容器 $container 重启命令失败" send_alert "容器 $container 重启命令失败" "docker start命令执行出错" fi ;; *) log_msg "🟡 $container: $status" ;; esac } check_container_resources() { local container="$1" local stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemPerc}}" "$container" 2>/dev/null) if [ -z "$stats" ]; then return fi local cpu=$(echo "$stats" | awk '{print $1}' | tr -d '%') local mem=$(echo "$stats" | awk '{print $2}' | tr -d '%') cpu=${cpu:-0} mem=${mem:-0} if (( $(echo "$cpu > $CPU_WARN" | bc -l) )); then log_msg " ⚠️ $container CPU使用率: ${cpu}% (超过阈值${CPU_WARN}%)" send_alert "容器 $container CPU过高" "CPU使用率: ${cpu}% (阈值: ${CPU_WARN}%)" fi if (( $(echo "$mem > $MEM_WARN" | bc -l) )); then log_msg " ⚠️ $container 内存使用率: ${mem}% (超过阈值${MEM_WARN}%)" send_alert "容器 $container 内存过高" "内存使用率: ${mem}% (阈值: ${MEM_WARN}%)" fi } check_docker_available log_msg "===== Docker容器监控启动 =====" log_msg "检测间隔: ${CHECK_INTERVAL}秒" log_msg "最大重启次数: $MAX_RESTART" if [ ${#CONTAINERS[@]} -eq 0 ]; then log_msg "监控范围: 所有容器" else log_msg "监控容器: ${CONTAINERS[*]}" fi while true; do log_msg "--- $(date '+%H:%M:%S') 检测 ---" while read -r container; do [ -z "$container" ] && continue check_container_status "$container" if docker inspect -f '{{.State.Status}}' "$container" 2>/dev/null | grep -q running; then check_container_resources "$container" fi done < <(get_monitor_containers) sleep "$CHECK_INTERVAL" done

适配环境

适配系统:CentOS 7+,Ubuntu 18.04+,Debian 10+

依赖环境:bash 4.0+

参数说明

[{"name": "CONTAINERS", "label": "\u76d1\u63a7\u5bb9\u5668\u540d(\u7a7a\u683c\u5206\u9694\uff0c\u7559\u7a7a\u76d1\u63a7\u6240\u6709)", "default": ""}, {"name": "CHECK_INTERVAL", "label": "\u68c0\u6d4b\u95f4\u9694(\u79d2)", "default": "30"}, {"name": "MAX_RESTART", "label": "\u6700\u5927\u91cd\u542f\u6b21\u6570", "default": "5"}, {"name": "ALERT_EMAIL", "label": "\u544a\u8b66\u90ae\u7bb1(\u53ef\u9009)", "default": ""}]
Docker容器监控自动重启高可用

更多容器