From da47aaf970e5721a2c6f12591bb22842847250a3 Mon Sep 17 00:00:00 2001 From: xzx3344521 Date: Wed, 29 Oct 2025 21:26:17 +0800 Subject: [PATCH] Update nginx --- nginx | 492 +++++++++++++++------------------------------------------- 1 file changed, 123 insertions(+), 369 deletions(-) diff --git a/nginx b/nginx index 57addda..6a29d69 100644 --- a/nginx +++ b/nginx @@ -1,411 +1,165 @@ #!/bin/bash -# 设置变量 -DATA_DIR="/data" -SCRIPT_DIR="/boot/脚本" -COMPOSE_FILE="$SCRIPT_DIR/ru.yaml" -LOG_FILE="/var/log/npm-deploy.log" +# 设置颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color -# 日志函数 -log_message() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" +# 打印颜色信息 +print_info() { + echo -e "${GREEN}[INFO]${NC} $1" } -# 检查是否以 root 权限运行 -if [ "$EUID" -ne 0 ]; then - echo "请使用 sudo 运行此脚本" - exit 1 -fi +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} -# 检查必要命令 -check_requirements() { - local missing=() +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# 检查端口是否被占用 +check_port() { + local port=$1 + if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null ; then + print_error "端口 $port 已被占用,请释放该端口或修改配置" + return 1 + else + print_info "端口 $port 可用" + return 0 + fi +} + +# 检查所有需要的端口 +check_ports() { + print_info "检查端口占用情况..." - for cmd in docker netstat ss lsof; do - if ! command -v "$cmd" &> /dev/null; then - missing+=("$cmd") + local ports=(80 81 443 800 1443) + local conflict_found=0 + + for port in "${ports[@]}"; do + if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null ; then + print_error "端口 $port 已被占用" + conflict_found=1 fi done - if [ ${#missing[@]} -ne 0 ]; then - echo "缺少必要命令: ${missing[*]}" - echo "请安装: apt-get update && apt-get install -y ${missing[*]}" + if [ $conflict_found -eq 1 ]; then + print_error "检测到端口冲突,请解决冲突后重新运行脚本" + exit 1 + else + print_info "所有端口检查通过" + fi +} + +# 创建必要的目录 +create_directories() { + print_info "创建数据目录..." + mkdir -p ./data + mkdir -p ./letsencrypt + + if [ $? -eq 0 ]; then + print_info "目录创建成功" + else + print_error "目录创建失败" exit 1 fi } -# 函数:彻底清理 Docker 资源 -cleanup_docker() { - log_message "开始清理 Docker 资源..." +# 创建 docker-compose.yml 文件 +create_docker_compose() { + print_info "创建 docker-compose.yml 文件..." - # 停止并删除所有相关容器 - docker stop nginx-proxy-manager 2>/dev/null || true - docker rm nginx-proxy-manager 2>/dev/null || true - - # 删除 Docker Compose 项目 - docker compose -p nginx down 2>/dev/null || true - - # 强制清理可能残留的容器 - docker ps -a --filter name=nginx --format "{{.ID}}" | xargs -r docker rm -f 2>/dev/null || true - - # 清理网络 - docker network prune -f - - # 清理未使用的镜像 - docker image prune -af 2>/dev/null || true - - log_message "Docker 资源清理完成" -} - -# 函数:更准确的端口检查 -check_port_advanced() { - local port=$1 - local protocol=${2:-tcp} - - log_message "深度检查端口 $port/$protocol ..." - - # 检查端口是否在有效范围内 - if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then - echo "错误: 端口 $port 不在有效范围内 (1-65535)" - return 2 - fi - - local is_occupied=0 - - # 方法1: netstat - if netstat -tulpn 2>/dev/null | grep -q ":${port} "; then - log_message "netstat 发现端口 $port 被占用" - netstat -tulpn | grep ":${port} " | head -5 - is_occupied=1 - fi - - # 方法2: ss - if ss -tulpn 2>/dev/null | grep -q ":${port} "; then - log_message "ss 发现端口 $port 被占用" - ss -tulpn | grep ":${port} " | head -5 - is_occupied=1 - fi - - # 方法3: lsof - if lsof -i :${port} 2>/dev/null | grep -q "LISTEN"; then - log_message "lsof 发现端口 $port 被占用" - lsof -i :${port} | head -5 - is_occupied=1 - fi - - # 方法4: 检查 Docker 容器映射 - if docker ps --format "table {{.Names}}\t{{.Ports}}" 2>/dev/null | grep -q ":${port}->"; then - log_message "Docker 容器正在使用端口 $port" - docker ps --format "table {{.Names}}\t{{.Ports}}" | grep ":${port}->" - is_occupied=1 - fi - - # 方法5: 使用 /proc 检查 - if [ -d /proc ]; then - for pid in /proc/[0-9]*; do - if [ -d "$pid" ] && ls -la "$pid/fd" 2>/dev/null | grep -q "socket:.*:${port}"; then - local process_pid=$(basename "$pid") - local process_name=$(ps -p "$process_pid" -o comm= 2>/dev/null) - log_message "进程 $process_name (PID: $process_pid) 正在使用端口 $port" - is_occupied=1 - fi - done - fi - - if [ $is_occupied -eq 0 ]; then - log_message "端口 $port 可用" - return 0 - else - return 1 - fi -} - -# 函数:检查端口可用性 -check_ports_availability() { - local http_port=$1 - local admin_port=$2 - local https_port=$3 - - local all_available=0 - - log_message "检查端口可用性: HTTP=$http_port, Admin=$admin_port, HTTPS=$https_port" - - check_port_advanced $http_port - local http_available=$? - - check_port_advanced $admin_port - local admin_available=$? - - check_port_advanced $https_port - local https_available=$? - - if [ $http_available -ne 0 ] || [ $admin_available -ne 0 ] || [ $https_available -ne 0 ]; then - return 1 - fi - - return 0 -} - -# 函数:使用备用端口部署 -deploy_with_alternate_ports() { - local http_port="8080" - local admin_port="8081" - local https_port="8443" - - # 检查备用端口是否可用 - if ! check_ports_availability $http_port $admin_port $https_port; then - log_message "备用端口也被占用,尝试自动寻找可用端口..." - - # 自动寻找可用端口 - for base_port in 8080 8082 8084 8880 8888; do - http_port=$((base_port)) - admin_port=$((base_port + 1)) - https_port=$((base_port + 2)) - - if check_ports_availability $http_port $admin_port $https_port; then - log_message "找到可用端口: HTTP=$http_port, Admin=$admin_port, HTTPS=$https_port" - break - fi - done - fi - - log_message "使用端口部署: HTTP=$http_port, 管理界面=$admin_port, HTTPS=$https_port" - - create_compose_file $http_port $admin_port $https_port - deploy_service $http_port $admin_port $https_port -} - -# 函数:创建 Compose 文件 -create_compose_file() { - local http_port=$1 - local admin_port=$2 - local https_port=$3 - - cat > "$COMPOSE_FILE" << EOF -# Nginx Proxy Manager 配置 + cat > docker-compose.yml << 'EOF' services: app: image: 'docker.io/jc21/nginx-proxy-manager:latest' - container_name: nginx-proxy-manager restart: unless-stopped ports: - - '${http_port}:80' - - '${admin_port}:81' - - '${https_port}:443' + - '800:80' + - '81:81' + - '1443:443' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt - environment: - - DISABLE_IPV6=false - networks: - - npm-network - -networks: - npm-network: - driver: bridge EOF - log_message "创建 Docker Compose 文件: $COMPOSE_FILE" -} - -# 函数:部署服务 -deploy_service() { - local http_port=$1 - local admin_port=$2 - local https_port=$3 - - # 切换到脚本目录 - cd "$SCRIPT_DIR" || { - log_message "错误: 无法切换到目录 $SCRIPT_DIR" - return 1 - } - - # 检查 Docker 是否运行 - if ! systemctl is-active --quiet docker; then - log_message "启动 Docker 服务..." - systemctl start docker - sleep 5 - - # 再次检查 - if ! systemctl is-active --quiet docker; then - log_message "错误: Docker 服务启动失败" - return 1 - fi - fi - - # 拉取最新镜像 - log_message "拉取 Docker 镜像..." - docker pull jc21/nginx-proxy-manager:latest || { - log_message "警告: 镜像拉取失败,尝试使用本地镜像" - } - - # 部署服务 - log_message "启动 Nginx Proxy Manager..." - if docker compose -p nginx -f "$COMPOSE_FILE" up -d; then - log_message "等待服务启动..." - - # 等待服务完全启动 - local max_attempts=30 - local attempt=1 - - while [ $attempt -le $max_attempts ]; do - if docker ps --filter name=nginx-proxy-manager --filter status=running --format "{{.Names}}" | grep -q nginx-proxy-manager; then - if curl -s http://localhost:${admin_port} > /dev/null; then - break - fi - fi - - log_message "等待服务启动... ($attempt/$max_attempts)" - sleep 2 - ((attempt++)) - done - - if [ $attempt -gt $max_attempts ]; then - log_message "警告: 服务启动超时,但容器已运行" - fi - - show_success_message $http_port $admin_port $https_port - return 0 + if [ -f "docker-compose.yml" ]; then + print_info "docker-compose.yml 文件创建成功" else - log_message "错误: 容器启动失败" - log_message "检查 Docker 日志:docker logs nginx-proxy-manager" - return 1 + print_error "docker-compose.yml 文件创建失败" + exit 1 fi } -# 显示成功信息 -show_success_message() { - local http_port=$1 - local admin_port=$2 - local https_port=$3 +# 启动服务 +start_services() { + print_info "启动 Nginx Proxy Manager..." - SERVER_IP=$(hostname -I | awk '{print $1}') + if command -v docker-compose &> /dev/null; then + docker-compose up -d + elif command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose up -d + else + print_error "未找到 docker-compose 或 docker compose 命令" + exit 1 + fi - echo "==================================================" - echo "✅ Nginx Proxy Manager 部署成功!" - echo "管理界面: http://${SERVER_IP}:${admin_port}" - echo "默认账号: admin@example.com" - echo "默认密码: changeme" - echo "" - echo "HTTP 端口: ${http_port}" - echo "HTTPS 端口: ${https_port}" - echo "" - echo "常用命令:" - echo "查看日志: docker logs nginx-proxy-manager" - echo "停止服务: docker compose -p nginx -f $COMPOSE_FILE down" - echo "重启服务: docker compose -p nginx -f $COMPOSE_FILE restart" - echo "==================================================" - - log_message "部署完成 - 管理界面: http://${SERVER_IP}:${admin_port}" + if [ $? -eq 0 ]; then + print_info "Nginx Proxy Manager 启动成功" + else + print_error "Nginx Proxy Manager 启动失败" + exit 1 + fi } -# 显示系统信息 -show_system_info() { - echo "=== 系统信息 ===" - echo "主机名: $(hostname)" - echo "IP 地址: $(hostname -I | awk '{print $1}')" - echo "操作系统: $(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '\"')" - echo "内核版本: $(uname -r)" - echo "Docker 版本: $(docker --version 2>/dev/null | cut -d' ' -f3 | tr -d ',')" - echo "" +# 显示安装完成信息 +show_completion_info() { + echo + print_info "=== Nginx Proxy Manager 安装完成 ===" + echo + print_info "访问地址: http://你的服务器IP:81" + print_info "默认登录信息:" + print_info " 邮箱: admin@example.com" + print_info " 密码: changeme" + echo + print_warning "首次登录后请立即修改默认密码!" + echo + print_info "服务端口映射:" + print_info " - 管理界面: 81" + print_info " - HTTP 代理: 800 → 80" + print_info " - HTTPS 代理: 1443 → 443" + echo } -# 主程序 +# 主函数 main() { - log_message "开始 Nginx Proxy Manager 部署流程" + echo + print_info "开始安装 Nginx Proxy Manager..." + echo - show_system_info - check_requirements + # 检查 Docker 是否安装 + if ! command -v docker &> /dev/null; then + print_error "Docker 未安装,请先安装 Docker" + exit 1 + fi - log_message "创建必要的目录..." - mkdir -p "$DATA_DIR" - mkdir -p "$SCRIPT_DIR" - mkdir -p "$(dirname "$LOG_FILE")" - - # 显示当前状态 - log_message "检查系统状态..." - check_port_advanced 80 - check_port_advanced 81 - check_port_advanced 443 - - echo "" - log_message "检查现有 Docker 容器..." - docker ps -a --filter name=nginx | grep nginx && echo "发现现有 nginx 容器" || echo "未发现 nginx 相关容器" - - echo "" - echo "请选择部署方案:" - echo "1) 彻底清理后使用默认端口重试" - echo "2) 直接使用备用端口 (8080, 8081, 8443) - 推荐" - echo "3) 手动指定端口" - echo "4) 仅清理不部署" - echo "5) 退出" - - read -p "请输入选择 (1-5): " choice - - case $choice in - 1) - log_message "用户选择: 彻底清理后使用默认端口" - cleanup_docker - sleep 3 - - if check_ports_availability 80 81 443; then - create_compose_file 80 81 443 - deploy_service 80 81 443 - else - log_message "默认端口不可用,自动切换到备用端口" - deploy_with_alternate_ports - fi - ;; - 2) - log_message "用户选择: 使用备用端口" - cleanup_docker - deploy_with_alternate_ports - ;; - 3) - log_message "用户选择: 手动指定端口" - echo "请手动指定端口:" - read -p "HTTP 端口 (推荐 8080): " custom_http - read -p "管理界面端口 (推荐 8081): " custom_admin - read -p "HTTPS 端口 (推荐 8443): " custom_https - - HTTP_PORT=${custom_http:-8080} - ADMIN_PORT=${custom_admin:-8081} - HTTPS_PORT=${custom_https:-8443} - - # 验证端口输入 - if ! [[ "$HTTP_PORT" =~ ^[0-9]+$ ]] || ! [[ "$ADMIN_PORT" =~ ^[0-9]+$ ]] || ! [[ "$HTTPS_PORT" =~ ^[0-9]+$ ]]; then - echo "错误: 端口必须是数字" - exit 1 - fi - - cleanup_docker - - if check_ports_availability $HTTP_PORT $ADMIN_PORT $HTTPS_PORT; then - create_compose_file $HTTP_PORT $ADMIN_PORT $HTTPS_PORT - deploy_service $HTTP_PORT $ADMIN_PORT $HTTPS_PORT - else - log_message "指定端口不可用,请重新选择" - exit 1 - fi - ;; - 4) - log_message "用户选择: 仅清理不部署" - cleanup_docker - echo "✅ 清理完成" - ;; - 5) - log_message "用户选择: 退出脚本" - exit 0 - ;; - *) - log_message "无效选择,使用备用端口" - cleanup_docker - deploy_with_alternate_ports - ;; - esac + # 检查端口 + check_ports - log_message "部署流程结束" + # 创建目录 + create_directories + + # 创建 docker-compose 文件 + create_docker_compose + + # 启动服务 + start_services + + # 显示完成信息 + show_completion_info } -# 执行主程序 +# 运行主函数 main "$@"