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": ""}]