Update nginx

This commit is contained in:
2025-10-29 21:26:17 +08:00
committed by GitHub
parent 9e9c4accea
commit da47aaf970

472
nginx
View File

@@ -1,411 +1,165 @@
#!/bin/bash #!/bin/bash
# 设置变量 # 设置颜色输出
DATA_DIR="/data" RED='\033[0;31m'
SCRIPT_DIR="/boot/脚本" GREEN='\033[0;32m'
COMPOSE_FILE="$SCRIPT_DIR/ru.yaml" YELLOW='\033[1;33m'
LOG_FILE="/var/log/npm-deploy.log" NC='\033[0m' # No Color
# 日志函数 # 打印颜色信息
log_message() { print_info() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" echo -e "${GREEN}[INFO]${NC} $1"
} }
# 检查是否以 root 权限运行 print_warning() {
if [ "$EUID" -ne 0 ]; then echo -e "${YELLOW}[WARNING]${NC} $1"
echo "请使用 sudo 运行此脚本"
exit 1
fi
# 检查必要命令
check_requirements() {
local missing=()
for cmd in docker netstat ss lsof; do
if ! command -v "$cmd" &> /dev/null; then
missing+=("$cmd")
fi
done
if [ ${#missing[@]} -ne 0 ]; then
echo "缺少必要命令: ${missing[*]}"
echo "请安装: apt-get update && apt-get install -y ${missing[*]}"
exit 1
fi
} }
# 函数:彻底清理 Docker 资源 print_error() {
cleanup_docker() { echo -e "${RED}[ERROR]${NC} $1"
log_message "开始清理 Docker 资源..."
# 停止并删除所有相关容器
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() { check_port() {
local port=$1 local port=$1
local protocol=${2:-tcp} if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null ; then
print_error "端口 $port 已被占用,请释放该端口或修改配置"
log_message "深度检查端口 $port/$protocol ..." return 1
# 检查端口是否在有效范围内
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 else
return 1 print_info "端口 $port 可用"
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 return 0
fi
} }
# 函数:使用备用端口部署 # 检查所有需要的端口
deploy_with_alternate_ports() { check_ports() {
local http_port="8080" print_info "检查端口占用情况..."
local admin_port="8081"
local https_port="8443"
# 检查备用端口是否可用 local ports=(80 81 443 800 1443)
if ! check_ports_availability $http_port $admin_port $https_port; then local conflict_found=0
log_message "备用端口也被占用,尝试自动寻找可用端口..."
# 自动寻找可用端口 for port in "${ports[@]}"; do
for base_port in 8080 8082 8084 8880 8888; do if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null ; then
http_port=$((base_port)) print_error "端口 $port 已被占用"
admin_port=$((base_port + 1)) conflict_found=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 fi
done done
if [ $conflict_found -eq 1 ]; then
print_error "检测到端口冲突,请解决冲突后重新运行脚本"
exit 1
else
print_info "所有端口检查通过"
fi 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() { create_directories() {
local http_port=$1 print_info "创建数据目录..."
local admin_port=$2 mkdir -p ./data
local https_port=$3 mkdir -p ./letsencrypt
cat > "$COMPOSE_FILE" << EOF if [ $? -eq 0 ]; then
# Nginx Proxy Manager 配置 print_info "目录创建成功"
else
print_error "目录创建失败"
exit 1
fi
}
# 创建 docker-compose.yml 文件
create_docker_compose() {
print_info "创建 docker-compose.yml 文件..."
cat > docker-compose.yml << 'EOF'
services: services:
app: app:
image: 'docker.io/jc21/nginx-proxy-manager:latest' image: 'docker.io/jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped restart: unless-stopped
ports: ports:
- '${http_port}:80' - '800:80'
- '${admin_port}:81' - '81:81'
- '${https_port}:443' - '1443:443'
volumes: volumes:
- ./data:/data - ./data:/data
- ./letsencrypt:/etc/letsencrypt - ./letsencrypt:/etc/letsencrypt
environment:
- DISABLE_IPV6=false
networks:
- npm-network
networks:
npm-network:
driver: bridge
EOF EOF
log_message "创建 Docker Compose 文件: $COMPOSE_FILE" if [ -f "docker-compose.yml" ]; then
} print_info "docker-compose.yml 文件创建成功"
# 函数:部署服务
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
else else
log_message "错误: 容器启动失败" print_error "docker-compose.yml 文件创建失败"
log_message "检查 Docker 日志docker logs nginx-proxy-manager" exit 1
return 1
fi fi
} }
# 显示成功信息 # 启动服务
show_success_message() { start_services() {
local http_port=$1 print_info "启动 Nginx Proxy Manager..."
local admin_port=$2
local https_port=$3
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 "==================================================" if [ $? -eq 0 ]; then
echo "Nginx Proxy Manager 部署成功" print_info "Nginx Proxy Manager 启动成功"
echo "管理界面: http://${SERVER_IP}:${admin_port}" else
echo "默认账号: admin@example.com" print_error "Nginx Proxy Manager 启动失败"
echo "默认密码: changeme" exit 1
echo "" fi
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}"
} }
# 显示系统信息 # 显示安装完成信息
show_system_info() { show_completion_info() {
echo "=== 系统信息 ===" echo
echo "主机名: $(hostname)" print_info "=== Nginx Proxy Manager 安装完成 ==="
echo "IP 地址: $(hostname -I | awk '{print $1}')" echo
echo "操作系统: $(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '\"')" print_info "访问地址: http://你的服务器IP:81"
echo "内核版本: $(uname -r)" print_info "默认登录信息:"
echo "Docker 版本: $(docker --version 2>/dev/null | cut -d' ' -f3 | tr -d ',')" print_info " 邮箱: admin@example.com"
echo "" print_info " 密码: changeme"
echo
print_warning "首次登录后请立即修改默认密码!"
echo
print_info "服务端口映射:"
print_info " - 管理界面: 81"
print_info " - HTTP 代理: 800 → 80"
print_info " - HTTPS 代理: 1443 → 443"
echo
} }
# 主程序 # 主函数
main() { main() {
log_message "开始 Nginx Proxy Manager 部署流程" echo
print_info "开始安装 Nginx Proxy Manager..."
echo
show_system_info # 检查 Docker 是否安装
check_requirements if ! command -v docker &> /dev/null; then
print_error "Docker 未安装,请先安装 Docker"
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 exit 1
fi fi
cleanup_docker # 检查端口
check_ports
if check_ports_availability $HTTP_PORT $ADMIN_PORT $HTTPS_PORT; then # 创建目录
create_compose_file $HTTP_PORT $ADMIN_PORT $HTTPS_PORT create_directories
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
log_message "部署流程结束" # 创建 docker-compose 文件
create_docker_compose
# 启动服务
start_services
# 显示完成信息
show_completion_info
} }
# 行主程序 # 行主函数
main "$@" main "$@"