我会为您提供几种自动重启异常容器的脚本方案,适用于不同的使用场景。

Shell脚本 + Docker(基础版)
#!/bin/bash
# restart-unhealthy-containers.sh
# 定义检查间隔(秒)
CHECK_INTERVAL=60
# 日志文件
LOG_FILE="/var/log/container-restart.log"
while true; do
# 获取所有异常状态的容器
UNHEALTHY_CONTAINERS=$(docker ps --filter "health=unhealthy" --format "{{.Names}}")
if [ -n "$UNHEALTHY_CONTAINERS" ]; then
echo "$(date) [INFO] 发现异常容器: $UNHEALTHY_CONTAINERS" >> "$LOG_FILE"
for CONTAINER in $UNHEALTHY_CONTAINERS; do
echo "$(date) [ACTION] 重启容器: $CONTAINER" >> "$LOG_FILE"
docker restart "$CONTAINER"
if [ $? -eq 0 ]; then
echo "$(date) [SUCCESS] 容器 $CONTAINER 重启成功" >> "$LOG_FILE"
else
echo "$(date) [ERROR] 容器 $CONTAINER 重启失败" >> "$LOG_FILE"
fi
done
fi
sleep "$CHECK_INTERVAL"
done
监控退出状态码(兼容性更强)
#!/bin/bash
# restart-exited-containers.sh
LOG_FILE="/var/log/container-restart.log"
MAX_RESTART_ATTEMPTS=3
check_and_restart() {
# 查找状态为exited的容器(排除手动停止的)
local EXITED_CONTAINERS=$(docker ps -a --filter "status=exited" --filter "name=!" --format "{{.ID}} {{.Names}} {{.ExitCode}}")
while IFS= read -r line; do
[ -z "$line" ] && continue
CONTAINER_ID=$(echo $line | awk '{print $1}')
CONTAINER_NAME=$(echo $line | awk '{print $2}')
EXIT_CODE=$(echo $line | awk '{print $3}')
# 排除正常退出的容器(exit code 0)
if [ "$EXIT_CODE" != "0" ]; then
RESTART_COUNT=$(docker inspect "$CONTAINER_NAME" --format '{{.RestartCount}}' 2>/dev/null || echo 0)
if [ "$RESTART_COUNT" -lt "$MAX_RESTART_ATTEMPTS" ]; then
echo "$(date) [ACTION] 重启异常退出的容器: $CONTAINER_NAME (退出码: $EXIT_CODE)" >> "$LOG_FILE"
docker start "$CONTAINER_ID" >> "$LOG_FILE" 2>&1
else
echo "$(date) [WARN] 容器 $CONTAINER_NAME 已达到最大重启次数: $MAX_RESTART_ATTEMPTS" >> "$LOG_FILE"
fi
fi
done <<< "$EXITED_CONTAINERS"
}
# 持续监控
while true; do
check_and_restart
sleep 30 # 每30秒检查一次
done
Docker Compose环境自动修复
#!/bin/bash
# docker-compose-auto-heal.sh
COMPOSE_FILE="docker-compose.yml"
PROJECT_NAME="myapp"
LOG_FILE="/var/log/compose-heal.log"
# 检查服务状态并重启异常服务
fix_unhealthy_services() {
# 获取所有服务的健康状态
docker-compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" ps --format "{{.Name}} {{.Status}}" | while read SERVICE LINE; do
if echo "$LINE" | grep -q "unhealthy\|exit\|dead"; then
echo "$(date) [ACTION] 修复异常服务: $SERVICE" >> "$LOG_FILE"
# 尝试重启特定服务
docker-compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" up -d --no-deps "$SERVICE" >> "$LOG_FILE" 2>&1
# 如果失败,尝试重新创建
if [ $? -ne 0 ]; then
echo "$(date) [INFO] 尝试重新创建服务: $SERVICE" >> "$LOG_FILE"
docker-compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" rm -f -s "$SERVICE" >> "$LOG_FILE" 2>&1
docker-compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" create "$SERVICE" >> "$LOG_FILE" 2>&1
docker-compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" start "$SERVICE" >> "$LOG_FILE" 2>&1
fi
fi
done
}
# 主循环
echo "$(date) [START] 启动Docker Compose自动修复服务" >> "$LOG_FILE"
while true; do
fix_unhealthy_services
sleep 60 # 每分钟检查一次
done
高级版(带通知和重试策略)
#!/bin/bash
# advanced-container-restart.sh
# 配置
LOG_FILE="/var/log/container-restart.log"
NOTIFY_CMD="" # 通知命令,如: curl -X POST https://api.telegram.org/...
MAX_RETRIES=3
CHECK_INTERVAL=30
# 初始化日志
[ ! -f "$LOG_FILE" ] && touch "$LOG_FILE"
log() {
local LEVEL=$1
local MESSAGE=$2
echo "$(date '+%Y-%m-%d %H:%M:%S') [$LEVEL] $MESSAGE" | tee -a "$LOG_FILE"
}
send_notification() {
local MESSAGE=$1
if [ -n "$NOTIFY_CMD" ]; then
$NOTIFY_CMD "$MESSAGE" &
fi
}
check_container_health() {
local CONTAINER=$1
# 支持健康检查的容器
local HEALTH_STATUS=$(docker inspect "$CONTAINER" --format '{{.State.Health.Status}}' 2>/dev/null)
# 不支持健康检查的容器,检查进程存活
if [ -z "$HEALTH_STATUS" ] || [ "$HEALTH_STATUS" = "<nil>" ]; then
local RUNNING=$(docker inspect "$CONTAINER" --format '{{.State.Running}}')
if [ "$RUNNING" != "true" ]; then
return 1 # 异常
fi
return 0 # 正常
fi
# 有健康检查配置
if [ "$HEALTH_STATUS" = "unhealthy" ]; then
return 1 # 异常
fi
return 0 # 正常
}
restart_container_with_retry() {
local CONTAINER=$1
local ATTEMPT=0
while [ $ATTEMPT -lt $MAX_RETRIES ]; do
ATTEMPT=$((ATTEMPT + 1))
log "ACTION" "尝试重启容器 $CONTAINER (第 $ATTEMPT 次)"
if docker restart "$CONTAINER" > /dev/null 2>&1; then
log "SUCCESS" "容器 $CONTAINER 重启成功"
# 等待容器启动并检查状态
sleep 5
if check_container_health "$CONTAINER"; then
log "SUCCESS" "容器 $CONTAINER 健康检查通过"
return 0
else
log "WARN" "容器 $CONTAINER 重启后仍不健康"
fi
else
log "ERROR" "容器 $CONTAINER 重启失败"
fi
sleep 3
done
log "CRITICAL" "容器 $CONTAINER 经过 $MAX_RETRIES 次尝试仍无法恢复"
send_notification "关键告警: 容器 $CONTAINER 无法自动恢复,请手动检查"
return 1
}
# 主监控循环
log "INFO" "启动容器自动修复服务"
log "INFO" "检查间隔: ${CHECK_INTERVAL}s, 最大重试: ${MAX_RETRIES}"
while true; do
# 获取所有容器
ALL_CONTAINERS=$(docker ps -a --format "{{.Names}}" 2>/dev/null)
if [ -n "$ALL_CONTAINERS" ]; then
while IFS= read -r CONTAINER; do
[ -z "$CONTAINER" ] && continue
if ! check_container_health "$CONTAINER"; then
log "WARN" "发现异常容器: $CONTAINER"
send_notification "容器 $CONTAINER 状态异常,开始自动修复"
restart_container_with_retry "$CONTAINER"
fi
done <<< "$ALL_CONTAINERS"
fi
sleep "$CHECK_INTERVAL"
done
使用说明
- 基础使用(方案一):
# 保存脚本 sudo nano /usr/local/bin/restart-unhealthy-containers.sh sudo chmod +x /usr/local/bin/restart-unhealthy-containers.sh
运行
sudo nohup /usr/local/bin/restart-unhealthy-containers.sh &
2. **作为Systemd服务运行**:
```ini
# /etc/systemd/system/container-restart.service
[Unit]
Description=Container Auto Restart Service
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/local/bin/advanced-container-restart.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable container-restart.service sudo systemctl start container-restart.service
- 使用Docker的restart策略(推荐先使用Docker原生功能):
# docker-compose.yml services: web: image: nginx restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3
注意事项
- Docker原生restart策略是最简单的方式,优先使用
- 健康检查配置能更精确地识别容器是否正常
- 避免重启循环:设置最大重试次数和冷却时间
- 日志记录:记录所有操作以便排查问题
- 通知机制:关键故障时发送告警通知
选择适合您场景的方案,建议先从方案一或Docker原生restart策略开始。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播