原创

centos7.6 系统nginx检测重启服务

温馨提示:
本文最后更新于 2025年09月20日,已超过 266 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我


nginx检测重启服务.sh

#!/bin/bash
# docker_nginx_port_monitor.sh

PORTS=()
NGINX_CONF=""
CHECK_INTERVAL=5
DOCKER_IMAGE="nginx:alpine"
DOCKER_NETWORK="nginx-proxy-network"
LOG_FILE="/data/nginx-configs/nginx-lb-secure.txt"
MAX_LOG_SIZE=10485760  # 10MB in bytes

# 解析参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -p|--ports)
            IFS=',' read -ra PORTS <<< "$2"
            shift 2
            ;;
        -c|--config)
            NGINX_CONF="$2"
            shift 2
            ;;
        -i|--interval)
            CHECK_INTERVAL="$2"
            shift 2
            ;;
        -d|--docker-image)
            DOCKER_IMAGE="$2"
            shift 2
            ;;
        -n|--network)
            DOCKER_NETWORK="$2"
            shift 2
            ;;
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

if [ ${#PORTS[@]} -eq 0 ]; then
    echo "Error: No ports specified."
    exit 1
fi

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志管理函数
function manage_log_file() {
    # 确保日志目录存在
    local log_dir=$(dirname "$LOG_FILE")
    if [ ! -d "$log_dir" ]; then
        mkdir -p "$log_dir" 2>/dev/null || {
            echo "Failed to create log directory: $log_dir"
            return 1
        }
    fi
    
    # 如果日志文件不存在,创建空文件
    if [ ! -f "$LOG_FILE" ]; then
        touch "$LOG_FILE" 2>/dev/null || {
            echo "Failed to create log file: $LOG_FILE"
            return 1
        }
        return 0
    fi
    
    # 检查文件大小
    local file_size=$(stat -c %s "$LOG_FILE" 2>/dev/null || stat -f %z "$LOG_FILE" 2>/dev/null)
    
    # 如果文件大小超过10MB,则重命名并创建新文件
    if [ "$file_size" -gt "$MAX_LOG_SIZE" ]; then
        local timestamp=$(date +%Y%m%d_%H%M%S)
        local backup_file="${LOG_FILE}.${timestamp}"
        
        # 重命名当前日志文件
        mv "$LOG_FILE" "$backup_file" 2>/dev/null && {
            # 创建新的空日志文件
            touch "$LOG_FILE"
            echo "Log file rotated: $LOG_FILE -> $backup_file" >> "$LOG_FILE"
        }
    fi
}

# 重定向输出到日志文件的echo函数
function log_echo() {
    # 管理日志文件大小
    manage_log_file
    
    # 输出到控制台和日志文件
    echo -e "$@" | tee -a "$LOG_FILE"
}

# 检查Docker是否可用
function check_docker() {
    if ! command -v docker >/dev/null 2>&1; then
        log_echo "${RED}Docker is not installed or not in PATH${NC}"
        return 1
    fi
    
    if ! docker info >/dev/null 2>&1; then
        log_echo "${RED}Docker daemon is not running${NC}"
        return 1
    fi
    
    return 0
}

# 创建Docker网络(如果不存在)
function create_docker_network() {
    if ! docker network ls | grep -q "$DOCKER_NETWORK"; then
        log_echo "${BLUE}Creating Docker network: $DOCKER_NETWORK${NC}"
        docker network create "$DOCKER_NETWORK" >/dev/null 2>&1
    fi
}

# 删除未启动的 nginx-lb 开头的容器
function cleanup_stopped_containers() {
    log_echo "${BLUE}Checking for stopped nginx-lb containers...${NC}"
    
    # 查找所有未启动的 nginx-lb 开头的容器
    stopped_containers=$(docker ps -a --filter "status=exited" --filter "name=nginx-lb" --format "{{.Names}}")
    
    if [ -n "$stopped_containers" ]; then
        log_echo "${YELLOW}Found stopped nginx-lb containers:${NC}"
        log_echo "$stopped_containers"
        
        # 删除这些容器
        while IFS= read -r container; do
            if [ -n "$container" ]; then
                log_echo "${BLUE}Removing stopped container: $container${NC}"
                if docker rm "$container" >/dev/null 2>&1; then
                    log_echo "${GREEN}Successfully removed container: $container${NC}"
                else
                    log_echo "${RED}Failed to remove container: $container${NC}"
                fi
            fi
        done <<< "$stopped_containers"
    else
        log_echo "${GREEN}No stopped nginx-lb containers found${NC}"
    fi
}

# 启动Nginx容器来代理指定端口
function start_proxy_container() {
    local port=$1
    # 使用新的命名规则: nginx-lb-secure-{port}-{雪花ID}
    local timestamp=$(date +%s%3N)  # 基于时间的雪花ID
    local container_name="nginx-lb-secure-$port-$timestamp"
    local active_ports=("${@:2}")
    
    # 检查是否有同端口的容器正在运行
    if docker ps --format '{{.Names}}' | grep -q "^nginx-lb-secure-$port-"; then
        log_echo "${GREEN}Container for port $port is already running${NC}"
        return 0
    fi
    
    # 检查是否有同端口的容器存在但未运行
    if docker ps -a --format '{{.Names}}' | grep -q "^nginx-lb-secure-$port-"; then
        log_echo "${YELLOW}Container for port $port exists but is not running. Starting container...${NC}"
        
        # 获取最新的容器名称
        local existing_container=$(docker ps -a --format '{{.Names}}' | grep "^nginx-lb-secure-$port-" | head -n 1)
        
        # 尝试启动现有容器
        if docker start "$existing_container" >/dev/null 2>&1; then
            log_echo "${GREEN}Successfully started existing container: $existing_container${NC}"
            return 0
        else
            log_echo "${RED}Failed to start existing container: $existing_container. Removing and recreating...${NC}"
            docker rm "$existing_container" >/dev/null 2>&1
        fi
    fi
    
    # 容器不存在或启动失败,创建新容器
    log_echo "${BLUE}Creating new container $container_name...${NC}"
    recreate_container "$container_name" "$DOCKER_IMAGE" "$port" "${active_ports[@]}"
    return $?
}

# 新增函数:重建容器
function recreate_container() {
    local container_name=$1
    local container_image=$2
    local port=$3
    local active_ports=("${@:4}")
    
    # 生成Nginx配置
    local proxy_conf=$(mktemp)
    cat > "$proxy_conf" << EOF
events {
    worker_connections 1024;
}

http {
    upstream backend {
EOF

    for active_port in "${active_ports[@]}"; do
        cat >> "$proxy_conf" << EOF
        server host.docker.internal:$active_port max_fails=3 fail_timeout=30s;
EOF
    done

    cat >> "$proxy_conf" << EOF
    }

    server {
        listen $port;
        
        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Host \$host;
            proxy_set_header X-Real-IP \$remote_addr;
            proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto \$scheme;
        }
    }
}
EOF

    # 启动容器,使用关闭的端口号
    log_echo "${BLUE}Starting proxy container for port $port${NC}"
    docker run -d \
        --name "$container_name" \
        --network "$DOCKER_NETWORK" \
        -p "$port:$port" \
        -v "$proxy_conf:/etc/nginx/nginx.conf:ro" \
        --add-host=host.docker.internal:host-gateway \
        "$container_image" >/dev/null 2>&1
    
    local result=$?
    rm -f "$proxy_conf"
    
    if [ $result -eq 0 ]; then
        log_echo "${GREEN}Successfully started proxy container: $container_name${NC}"
    else
        log_echo "${RED}Failed to start proxy container for port $port${NC}"
    fi
    
    return $result
}

# 检查端口状态
function check_port() {
    local port=$1
    local result=1
    
    # 方法1: 使用 nc 命令
    if command -v nc >/dev/null 2>&1; then
        if nc -z localhost $port 2>/dev/null; then
            result=0
        fi
    fi
    
    # 方法2: 使用 telnet 命令
    if [ $result -ne 0 ] && command -v telnet >/dev/null 2>&1; then
        timeout 3 telnet localhost $port 2>&1 | grep -q "Connected" && result=0
    fi
    
    # 方法3: 使用 bash 内置功能
    if [ $result -ne 0 ]; then
        if </dev/tcp/localhost/$port 2>/dev/null; then
            result=0
        fi 2>/dev/null
    fi
    
    # 方法4: 检查进程是否监听端口
    if [ $result -ne 0 ]; then
        if ss -tuln | grep -q ":$port " 2>/dev/null || netstat -tuln | grep -q ":$port " 2>/dev/null; then
            result=0
        fi
    fi
    
    # 方法5: 检查是否有代理容器在运行
    if [ $result -ne 0 ]; then
        # 修改为新的容器命名规则
        if docker ps --format '{{.Names}}' | grep -q "^nginx-lb-secure-$port-"; then
            result=0
        fi
    fi
    
    return $result
}

function check_ports() {
    local available_ports=()
    local closed_ports=()
    
    log_echo "${BLUE}==== Checking port status ==== ${NC}"
    
    for port in "${PORTS[@]}"; do
        if check_port $port; then
            log_echo "${GREEN}✓ Port $port is available${NC}"
            available_ports+=($port)
        else
            log_echo "${RED}✗ Port $port is not available${NC}"
            closed_ports+=($port)
        fi
    done
    
    # 处理关闭的端口 - 启动代理容器
    if [ ${#closed_ports[@]} -gt 0 ] && [ ${#available_ports[@]} -gt 0 ]; then
        log_echo "${YELLOW}Starting proxy containers for closed ports...${NC}"
        for port in "${closed_ports[@]}"; do
            start_proxy_container "$port" "${available_ports[@]}"
        done
    elif [ ${#closed_ports[@]} -gt 0 ] && [ ${#available_ports[@]} -eq 0 ]; then
        log_echo "${RED}No available ports to proxy to.${NC}"
    fi
    
    # 注意:不再停止已启动的容器
}

# 格式化时间显示函数
function format_datetime() {
    date '+%Y年%m月%d日 %H时%M分%S秒'
}

# 主程序
log_echo "${BLUE}==== DOCKER NGINX PORT MONITOR STARTED ==== ${NC}"
log_echo "${BLUE}Monitoring ports: ${PORTS[*]}${NC}"
if [ -n "$NGINX_CONF" ]; then
    log_echo "${BLUE}Nginx config file: $NGINX_CONF${NC}"
fi
log_echo "${BLUE}Check interval: ${CHECK_INTERVAL}s${NC}"
log_echo "${BLUE}Docker image: $DOCKER_IMAGE${NC}"
log_echo "${BLUE}Docker network: $DOCKER_NETWORK${NC}"
log_echo "${BLUE}Log file: $LOG_FILE${NC}"
log_echo "${BLUE}=========================================${NC}"

# 检查Docker
if ! check_docker; then
    log_echo "${RED}Docker is required for this script to work properly${NC}"
    exit 1
fi

# 创建Docker网络
create_docker_network

# 清理已停止的容器
cleanup_stopped_containers

# 立即执行一次检查
check_ports

# 定时检查
while true; do
    log_echo "${YELLOW}==== Checking ports at $(format_datetime) ==== ${NC}"
    check_ports
    log_echo "${YELLOW}==== Check completed ==== ${NC}"
    
    # 每次检查后清理已停止的容器
    cleanup_stopped_containers
    
    sleep $CHECK_INTERVAL
done

nginx检测重启服务说明 

 # Docker Nginx 端口监控脚本使用说明

 ## 简介

 这是一个自动化监控和管理 Docker Nginx 容器的 Bash 脚本,用于监控指定端口状态并在端口不可用时自动创建 Nginx 代理容器。

 ## 功能特性

 - 实时监控多个端口的可用性
 - 自动为不可用端口创建 Nginx 负载均衡代理容器
 - 智能容器管理(创建、启动、清理)
 - 日志记录和自动轮转
 - 可自定义检查间隔和 Docker 配置

 ## 使用方法

 ### 基本语法
 ```bash
 ./docker_nginx_port_monitor.sh [选项]
 ```


 ### 必需参数
 - `-p, --ports PORTS`:指定要监控的端口列表,多个端口用逗号分隔(例如:8080,8081,8082)

 ### 可选参数
 - `-c, --config CONFIG`:指定 Nginx 配置文件路径
 - `-i, --interval INTERVAL`:设置检查间隔(秒),默认为 5 秒
 - `-d, --docker-image IMAGE`:指定使用的 Docker 镜像,默认为 nginx:alpine
 - `-n, --network NETWORK`:指定 Docker 网络名称,默认为 nginx-proxy-network

 ### 使用示例

 1. 监控单个端口:
    ```bash
    ./docker_nginx_port_monitor.sh -p 8080
    ```


 2. 监控多个端口:
    ```bash
    ./docker_nginx_port_monitor.sh -p 8080,8081,8082
    ```


 3. 自定义检查间隔:
    ```bash
    ./docker_nginx_port_monitor.sh -p 8080,8081 -i 10
    ```


 4. 指定 Docker 镜像和网络:
    ```bash
    ./docker_nginx_port_monitor.sh -p 8080 -d nginx:latest -n my-network
    ```


 ## 工作原理

 1. 脚本启动时会检查 Docker 环境是否正常
 2. 创建指定的 Docker 网络(如果不存在)
 3. 清理已停止的 nginx-lb 容器
 4. 检查所有指定端口的状态
 5. 对于不可用的端口,创建 Nginx 容器进行代理
 6. 按设定间隔重复检查过程

 ## 容器管理

 - 容器命名格式:nginx-lb-secure-{port}-{timestamp}
 - 自动清理已停止的容器
 - 避免重复创建相同端口的容器

 ## 日志管理

 - 日志文件路径:/data/nginx-configs/nginx-lb-secure.txt
 - 日志文件大小超过 10MB 时自动轮转
 - 记录所有重要操作和状态变化

 ## 环境要求

 - Linux 或 macOS 操作系统
 - Docker 已安装并正常运行
 - 足够的权限执行 Docker 命令
 - bash 4.0 或更高版本

 ## 注意事项

 - 确保监控的端口没有被其他服务占用
 - 脚本会持续运行,使用 Ctrl+C 停止
 - 定期检查日志文件以监控系统状态
 - 根据实际需求调整检查间隔以平衡性能和实时性


nohup ./jcng.sh -p 8080,8081,8082 -i 5 > /data/nginx-configs/nginx-lb-secure.txt 2>&1 &
正文到此结束