Nginx 自动安装脚本

Nginx 自动安装脚本

功能说明

自动化编译安装 Nginx 的 Shell 脚本,支持标准安装和 ngx-brotli 模块安装,适用于单机部署和 Ansible 批量部署场景。

支持模式

  • 标准模式 (standard):不含 ngx-brotli 压缩模块
  • Brotli 模式 (brotli):包含 ngx-brotli 压缩模块

支持架构

脚本会自动检测系统架构,理论上支持所有 Linux 架构。

已验证系统

脚本已在以下 Linux 发行版上测试通过:

  • CentOS 7
  • CentOS 8
  • Rocky Linux 8
  • Kylin Linux Advanced Server V10 (Halberd) – 麒麟操作系统

理论上支持所有基于 RHEL 和 Debian 的 Linux 发行版。

目录结构

nginx_install/
├── conf/                           # 配置文件目录
│   ├── dummy_ssl/                  # 自签名证书目录
│   │   ├── dummy.crt               # 自签名证书
│   │   └── dummy.key               # 自签名证书私钥
│   └── default.conf                # 默认配置示例(不会被复制)
├── nginx-1.28.1.tar.gz             # Nginx 源码包(必需)
├── ngx_brotli.zip                  # ngx-brotli 模块源码(brotli 模式必需)
├── nginx.conf                      # 主配置文件(可选)
├── nginx.service                   # Systemd 服务文件(可选)
├── install_nginx.sh                # 安装脚本(必需)
└── README.md                       # 说明文档

编译特性

标准模式包含的模块

  • HTTP SSL 模块 (–with-http_ssl_module)
  • HTTP/2 支持 (–with-http_v2_module)
  • Gzip 静态压缩 (–with-http_gzip_static_module)
  • HTTP 状态监控 (–with-http_stub_status_module)
  • HTTP 替换模块 (–with-http_sub_module)
  • HTTP 真实 IP 模块 (–with-http_realip_module)
  • TCP/UDP 代理 (–with-stream)
  • Stream SSL 模块 (–with-stream_ssl_module)
  • Stream 真实 IP 模块 (–with-stream_realip_module)
  • TLS 1.3 支持 (–with-openssl-opt=’enable-tls1_3 enable-weak-ssl-ciphers’)

Brotli 模式额外包含

  • ngx-brotli 压缩模块(比 gzip 压缩率更高)

使用方法

重要提示

在 Ubuntu/Debian 系统中,请使用 bash 运行脚本:

# Ubuntu/Debian 推荐方式
bash install_nginx.sh standard
./install_nginx.sh standard

# CentOS/RHEL 系统可以使用 sh
sh install_nginx.sh standard

1. 交互式安装

# 添加执行权限
chmod +x install_nginx.sh

# 以 root 用户运行
sudo ./install_nginx.sh

# 根据提示选择安装模式
# 1. standard - 标准安装(不含 ngx-brotli)
# 2. brotli   - 安装带 ngx-brotli 模块

2. 命令行自动安装

# 标准模式安装
bash install_nginx.sh standard

# Brotli 模式安装
bash install_nginx.sh brotli

3. Ansible 批量部署

# playbook 示例
- name: 批量安装 Nginx
  hosts: webservers
  tasks:
    - name: 上传 Nginx 安装脚本和源码包
      copy:
        src: nginx_install/
        dest: /tmp/nginx_install/
        mode: '0755'

    - name: 执行安装脚本(标准模式)
      shell: /tmp/nginx_install/install_nginx.sh standard
      args:
        chdir: /tmp/nginx_install

或使用 script 模块:

- name: 安装 Nginx(标准模式)
  script: nginx_install/install_nginx.sh standard

安装过程

脚本会自动完成以下操作:

  1. 环境检查
    • 检查 root 权限
    • 检查并创建运行用户和组(gzapps)
    • 检查安装包是否存在
  2. 安装依赖
    • 自动检测包管理器(dnf/yum/apt-get)
    • 安装编译工具(gcc、make、pcre、zlib、openssl)
    • Brotli 模式额外安装 brotli 相关包
  3. 编译安装
    • 解压源码到临时目录
    • 执行 configure 配置
    • 多核并行编译(使用所有 CPU 核心)
    • 安装到 /AppHome/nginx
  4. 配置系统
    • 应用自定义配置文件(如果提供)
    • 标准模式自动注释 brotli 配置
    • 创建必要的目录结构
    • 复制自签名证书
    • 创建默认安全配置(拦截未配置的域名)
    • 配置 systemd 服务
    • 创建命令软链接
  5. 清理和验证
    • 清理编译临时目录
    • 验证安装是否成功
    • 测试配置文件语法

安装后的目录结构

/AppHome/nginx/
├── sbin/
│   └── nginx                       # Nginx 可执行文件
├── conf/
│   ├── nginx.conf                  # 主配置文件
│   ├── conf.d/                     # 模块化配置目录
│   │   └── 00-default.conf         # 默认安全配置
│   ├── dummy_ssl/                  # 自签名证书目录
│   │   ├── dummy.crt
│   │   └── dummy.key
│   ├── mime.types
│   └── ...
├── logs/
│   ├── access.log                  # 访问日志
│   ├── error.log                   # 错误日志
│   └── nginx.pid                   # PID 文件
└── html/                           # 默认网站根目录

/usr/local/bin/
└── nginx -> /AppHome/nginx/sbin/nginx  # 命令软链接

/etc/systemd/system/
└── nginx.service                   # Systemd 服务文件

配置说明

默认安全配置

脚本会自动创建 /AppHome/nginx/conf/conf.d/00-default.conf,用于拦截未配置的域名和 IP 直接访问:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    # 返回 444 表示直接关闭连接,不返回任何响应
    return 444;
}

作用
– 防止恶意域名指向你的服务器
– 防止 IP 直接访问暴露服务
– 提高安全性,符合安全基线要求

启用 HTTPS 拦截

编辑配置文件,取消 HTTPS 部分的注释:

vi /AppHome/nginx/conf/conf.d/00-default.conf

# 取消下面部分的注释(删除 # 号)
# server {
#     listen 443 ssl http2 default_server;
#     listen [::]:443 ssl http2 default_server;
#     
#     server_name _;
#     
#     ssl_certificate     /AppHome/nginx/conf/dummy_ssl/dummy.crt;
#     ssl_certificate_key /AppHome/nginx/conf/dummy_ssl/dummy.key;
#     
#     return 444;
# }

# 重载配置
nginx -t && nginx -s reload

自定义配置

如果提供了 nginx.conf 文件,脚本会:
– 标准模式:自动注释掉 brotli 相关配置
– Brotli 模式:直接使用完整配置

Systemd 服务配置

[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/AppHome/nginx/logs/nginx.pid
ExecStartPre=/AppHome/nginx/sbin/nginx -t
ExecStart=/AppHome/nginx/sbin/nginx -c /AppHome/nginx/conf/nginx.conf
ExecReload=/AppHome/nginx/sbin/nginx -s reload
ExecStop=/AppHome/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

服务管理

基本操作

# 启动服务
systemctl start nginx

# 停止服务
systemctl stop nginx

# 重启服务
systemctl restart nginx

# 重载配置(不中断服务)
systemctl reload nginx

# 查看状态
systemctl status nginx

# 查看日志
journalctl -u nginx -f

# 开机自启
systemctl enable nginx

# 禁用自启
systemctl disable nginx

Nginx 命令

# 测试配置文件语法
nginx -t

# 查看版本信息
nginx -v
nginx -V  # 查看编译参数

# 重载配置
nginx -s reload

# 优雅停止
nginx -s quit

# 快速停止
nginx -s stop

# 重新打开日志文件
nginx -s reopen

验证安装

1. 检查服务状态

# 查看服务状态
systemctl status nginx

# 查看端口监听
ss -tlnp | grep nginx
# 或
netstat -tlnp | grep nginx

2. 测试 default_server

# 使用 IP 访问(会被 default_server 拦截)
curl -v http://127.0.0.1
# 预期结果: Empty reply from server (这是正常的,return 444 的效果)

# 使用域名访问(会被 default_server 拦截)
curl -H "Host: unknown.domain" http://127.0.0.1
# 预期结果: Empty reply from server

3. 创建测试站点

# 创建测试配置
cat > /AppHome/nginx/conf/conf.d/test.conf << 'EOF'
server {
    listen 80;
    server_name test.local;

    location / {
        return 200 "Nginx is working!\n";
        add_header Content-Type text/plain;
    }
}
EOF

# 重载配置
nginx -t && nginx -s reload

# 测试
curl -H "Host: test.local" http://127.0.0.1
# 预期输出: Nginx is working!

4. 验证编译模块

# 查看编译参数
nginx -V

# 标准模式应该看到
# --with-http_ssl_module
# --with-http_v2_module
# --with-stream
# 等模块

# Brotli 模式额外看到
# --add-module=/path/to/ngx_brotli

故障排查

问题 1:编译失败

症状:configure 或 make 失败

排查步骤

# 查看编译日志
tail -50 /tmp/nginx_build_*.log

# 检查依赖是否安装
rpm -qa | grep -E "gcc|make|pcre|zlib|openssl"  # CentOS/RHEL
dpkg -l | grep -E "gcc|make|libpcre|zlib|libssl"  # Ubuntu/Debian

常见原因
– 缺少编译依赖
– OpenSSL 版本过低
– 磁盘空间不足

问题 2:服务启动失败

症状:systemctl start nginx 失败

排查步骤

# 查看 systemd 日志
journalctl -u nginx -n 50

# 查看 Nginx 错误日志
tail -100 /AppHome/nginx/logs/error.log

# 手动启动测试
/AppHome/nginx/sbin/nginx -t
/AppHome/nginx/sbin/nginx

常见原因
– 配置文件语法错误
– 端口被占用
– 权限问题

问题 3:配置文件冲突

症状:nginx -t 报错 “duplicate default server”

原因:存在多个 default_server 配置

解决方法

# 查找所有 default_server 配置
grep -r "default_server" /AppHome/nginx/conf/

# 删除多余的配置文件
rm -f /AppHome/nginx/conf/conf.d/default.conf

# 测试配置
nginx -t

问题 4:Brotli 模块加载失败

症状:标准模式下启动失败,日志显示 “unknown directive brotli”

原因:配置文件包含 brotli 指令,但未编译 brotli 模块

解决方法

# 方法 1:手动注释 brotli 配置
vi /AppHome/nginx/conf/nginx.conf
# 注释掉所有 brotli 开头的行

# 方法 2:重新安装为 brotli 模式
bash install_nginx.sh brotli

问题 5:权限问题

症状:日志显示权限错误

排查步骤

# 检查目录权限
ls -la /AppHome/nginx/

# 检查运行用户
ps aux | grep nginx

# 修复权限
chown -R gzapps:gzapps /AppHome/nginx/

性能优化建议

1. Worker 进程数

# 设置为 CPU 核心数
worker_processes auto;

2. Worker 连接数

events {
    worker_connections 65535;
    use epoll;
    multi_accept on;
}

3. 文件缓存

http {
    open_file_cache max=65535 inactive=60s;
    open_file_cache_valid 80s;
    open_file_cache_min_uses 1;
}

4. Gzip 压缩

http {
    gzip on;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript;
}

5. Brotli 压缩(仅 Brotli 模式)

http {
    brotli on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/json application/javascript;
}

安全加固

1. 隐藏版本号

http {
    server_tokens off;
}

2. 限制请求方法

server {
    if ($request_method !~ ^(GET|POST|HEAD)$) {
        return 405;
    }
}

3. 防止点击劫持

add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";

4. SSL 配置

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

卸载 Nginx

# 停止服务
systemctl stop nginx
systemctl disable nginx

# 删除 systemd 服务文件
rm -f /etc/systemd/system/nginx.service
systemctl daemon-reload

# 删除安装目录
rm -rf /AppHome/nginx

# 删除软链接
rm -f /usr/local/bin/nginx

# 删除编译临时文件(如果存在)
rm -rf /usr/local/src/nginx_build_*

升级 Nginx

平滑升级(不中断服务)

# 1. 备份当前版本
cp -r /AppHome/nginx /AppHome/nginx.bak

# 2. 编译新版本(不要 make install)
cd /path/to/new/nginx/source
./configure [相同的编译参数]
make

# 3. 备份旧的二进制文件
mv /AppHome/nginx/sbin/nginx /AppHome/nginx/sbin/nginx.old

# 4. 复制新的二进制文件
cp objs/nginx /AppHome/nginx/sbin/nginx

# 5. 测试新版本
/AppHome/nginx/sbin/nginx -t

# 6. 发送 USR2 信号(启动新的 master 进程)
kill -USR2 `cat /AppHome/nginx/logs/nginx.pid`

# 7. 优雅关闭旧的 worker 进程
kill -WINCH `cat /AppHome/nginx/logs/nginx.pid.oldbin`

# 8. 如果新版本正常,关闭旧的 master 进程
kill -QUIT `cat /AppHome/nginx/logs/nginx.pid.oldbin`

简单升级(会中断服务)

# 1. 停止服务
systemctl stop nginx

# 2. 备份当前版本
mv /AppHome/nginx /AppHome/nginx.bak.$(date +%Y%m%d)

# 3. 重新运行安装脚本
bash install_nginx.sh standard

# 4. 恢复配置文件
cp /AppHome/nginx.bak.*/conf/nginx.conf /AppHome/nginx/conf/
cp -r /AppHome/nginx.bak.*/conf/conf.d/* /AppHome/nginx/conf/conf.d/

# 5. 测试并启动
nginx -t
systemctl start nginx

注意事项

  1. 系统要求
    • 必须使用 root 权限运行
    • 确保系统有足够的磁盘空间(至少 500MB)
    • 确保系统可以访问软件源
  2. 用户和组
    • 默认使用 gzapps 用户运行
    • 脚本会自动创建用户和组
    • 如需修改,请编辑脚本中的 NGINX_USER 和 NGINX_GROUP 变量
  3. 端口占用
    • 默认监听 80 端口
    • 如果端口被占用,需要先停止占用端口的服务
  4. 防火墙
    • 记得开放 80 和 443 端口
    firewall-cmd --permanent --add-service=http
    firewall-cmd --permanent --add-service=https
    firewall-cmd --reload
    
  5. SELinux
    • 如果启用了 SELinux,可能需要配置策略
    setsebool -P httpd_can_network_connect 1
    

更新日志

  • 2026-03-09: 初始版本
    • 支持标准模式和 Brotli 模式安装
    • 自动安装编译依赖
    • 自动配置 systemd 服务
    • 自动创建默认安全配置
    • 支持自定义配置文件
    • 编译输出重定向到日志文件
    • 支持命令行参数和 Ansible 批量部署

下载地址

  • Nginx 官方下载:https://nginx.org/en/download.html
  • ngx_brotli 模块:https://github.com/google/ngx_brotli

脚本如下

#!/bin/bash
# Nginx 自动安装脚本
# 支持标准安装和带 ngx-brotli 模块的安装
#
# 重要提示:
#   Ubuntu/Debian: 必须使用 bash 运行(sh 指向 dash)
#   CentOS/RHEL:   可以使用 sh 或 bash(sh 是 bash 的链接)
#
# 使用方法:
#   交互式安装: ./install_nginx.sh
#   自动安装:   ./install_nginx.sh [模式]
#
# 模式参数:
#   standard -> 标准安装(不含 ngx-brotli)
#   brotli   -> 安装带 ngx-brotli 模块
#
# 示例:
#   bash install_nginx.sh standard  # 自动标准安装
#   bash install_nginx.sh brotli    # 自动安装带 brotli 模块
#
# Ansible 批量部署示例:
#   ansible all -m script -a "install_nginx.sh standard"
#
# 开启严格模式,遇到错误立即退出
set -e

# 定义当前脚本所在目录
DIR=$(cd "$(dirname "$0")" && pwd)

# 定义安装配置
NGINX_VERSION="1.28.1"
NGINX_PACKAGE="nginx-${NGINX_VERSION}.tar.gz"
NGINX_DIR_NAME="nginx-${NGINX_VERSION}"
INSTALL_PREFIX="/AppHome/nginx"
NGINX_USER="gzapps"
NGINX_GROUP="gzapps"

# 定义日志函数,方便输出日志信息
log() {
    echo "$(date +'%Y-%m-%d %H:%M:%S') - $1"
}

# 检查是否为 root 用户
check_root() {
    if [ "$EUID" -ne 0 ]; then
        log "错误: 请使用 root 用户运行此脚本。"
        exit 1
    fi
}

# 检查并创建用户和组
check_user_group() {
    log "检查用户和组..."

    # 检查组是否存在
    if ! getent group "$NGINX_GROUP" > /dev/null 2>&1; then
        log "创建组: $NGINX_GROUP"
        groupadd "$NGINX_GROUP"
    else
        log "组 $NGINX_GROUP 已存在"
    fi

    # 检查用户是否存在
    if ! id "$NGINX_USER" > /dev/null 2>&1; then
        log "创建用户: $NGINX_USER"
        useradd -r -g "$NGINX_GROUP" -s /sbin/nologin -M "$NGINX_USER"
    else
        log "用户 $NGINX_USER 已存在"
    fi
}

# 选择安装模式
select_install_mode() {
    # 如果通过命令行参数指定了模式,直接使用
    if [ -n "$1" ]; then
        choice="$1"
        log "通过命令行参数指定安装模式: $choice"
    else
        # 交互式选择模式
        echo ""
        echo "=========================================="
        echo "请选择 Nginx 安装模式:"
        echo "1. standard - 标准安装(不含 ngx-brotli)"
        echo "2. brotli   - 安装带 ngx-brotli 模块"
        echo "=========================================="
        read -p "请输入安装模式 (standard/brotli): " choice
    fi

    case "$choice" in
        standard|1)
            INSTALL_MODE="standard"
            log "已选择: 标准安装模式"
            ;;
        brotli|2)
            INSTALL_MODE="brotli"
            log "已选择: 带 ngx-brotli 模块安装"
            ;;
        *)
            log "错误: 无效的安装模式 '$choice',退出安装。"
            log "支持的模式: standard, brotli"
            exit 1
            ;;
    esac
}

# 检查安装包是否存在
check_packages() {
    log "检查安装包..."

    # 检查 Nginx 安装包
    NGINX_FILE="${DIR}/${NGINX_PACKAGE}"
    if [ ! -f "$NGINX_FILE" ]; then
        log "错误: Nginx 安装包 $NGINX_FILE 不存在。"
        exit 1
    fi
    log "找到 Nginx 安装包: $NGINX_FILE"

    # 如果选择 brotli 模式,检查 ngx_brotli 包
    if [ "$INSTALL_MODE" = "brotli" ]; then
        BROTLI_FILE="${DIR}/ngx_brotli.zip"
        if [ ! -f "$BROTLI_FILE" ]; then
            log "错误: ngx_brotli 安装包 $BROTLI_FILE 不存在。"
            exit 1
        fi
        log "找到 ngx_brotli 安装包: $BROTLI_FILE"
    fi

    # 检查配置文件
    NGINX_CONF_FILE="${DIR}/nginx.conf"
    if [ ! -f "$NGINX_CONF_FILE" ]; then
        log "警告: nginx.conf 配置文件不存在,将使用默认配置"
    else
        log "找到 nginx.conf 配置文件"
    fi

    # 检查 systemd 服务文件
    NGINX_SERVICE_FILE="${DIR}/nginx.service"
    if [ ! -f "$NGINX_SERVICE_FILE" ]; then
        log "警告: nginx.service 文件不存在,将手动创建"
    else
        log "找到 nginx.service 文件"
    fi
}

# 安装依赖包
install_dependencies() {
    log "=========================================="
    log "安装编译依赖..."
    log "=========================================="

    # 检测包管理器
    if command -v dnf &> /dev/null; then
        PKG_MANAGER="dnf"
    elif command -v yum &> /dev/null; then
        PKG_MANAGER="yum"
    elif command -v apt-get &> /dev/null; then
        PKG_MANAGER="apt-get"
    else
        log "错误: 未找到支持的包管理器 (dnf/yum/apt-get)"
        exit 1
    fi

    log "使用包管理器: $PKG_MANAGER"

    # 安装基础编译工具
    if [ "$PKG_MANAGER" = "apt-get" ]; then
        $PKG_MANAGER install -y gcc g++ make libpcre3-dev zlib1g-dev libssl-dev

        # 如果是 brotli 模式,安装 brotli 相关包
        if [ "$INSTALL_MODE" = "brotli" ]; then
            $PKG_MANAGER install -y brotli libbrotli-dev unzip
        fi
    else
        $PKG_MANAGER install -y gcc gcc-c++ make pcre-devel zlib-devel openssl-devel

        # 如果是 brotli 模式,安装 brotli 相关包
        if [ "$INSTALL_MODE" = "brotli" ]; then
            $PKG_MANAGER install -y brotli brotli-devel unzip
        fi
    fi

    log "依赖安装完成"
}

# 检查是否已安装 Nginx
check_existing_nginx() {
    if command -v nginx &> /dev/null; then
        CURRENT_NGINX_VERSION=$(nginx -v 2>&1)
        log "警告: 系统中已存在 Nginx: $CURRENT_NGINX_VERSION"

        # 如果是非交互模式(通过命令行参数),自动跳过确认
        if [ -n "$AUTO_INSTALL" ]; then
            log "自动安装模式,继续安装..."
            return 0
        fi

        read -p "是否继续安装? (y/n): " continue_install
        if [ "$continue_install" != "y" ] && [ "$continue_install" != "Y" ]; then
            log "用户取消安装,退出。"
            exit 0
        fi
    fi
}

# 准备编译环境
prepare_build_environment() {
    log "=========================================="
    log "准备编译环境..."
    log "=========================================="

    # 创建临时编译目录
    BUILD_DIR="/usr/local/src/nginx_build_$(date +%Y%m%d%H%M%S)"
    mkdir -p "$BUILD_DIR"
    log "创建编译目录: $BUILD_DIR"

    # 复制并解压 Nginx 源码
    log "解压 Nginx 源码..."
    cp "$NGINX_FILE" "$BUILD_DIR/"
    cd "$BUILD_DIR"
    tar -zxf "$NGINX_PACKAGE"

    # 如果是 brotli 模式,解压 ngx_brotli
    if [ "$INSTALL_MODE" = "brotli" ]; then
        log "解压 ngx_brotli 模块..."
        unzip -q "$BROTLI_FILE" -d "$BUILD_DIR/"
        # 假设解压后的目录名为 ngx_brotli 或 ngx_brotli-master
        if [ -d "$BUILD_DIR/ngx_brotli-master" ]; then
            BROTLI_MODULE_PATH="$BUILD_DIR/ngx_brotli-master"
        elif [ -d "$BUILD_DIR/ngx_brotli" ]; then
            BROTLI_MODULE_PATH="$BUILD_DIR/ngx_brotli"
        else
            log "错误: 无法找到 ngx_brotli 模块目录"
            exit 1
        fi
        log "ngx_brotli 模块路径: $BROTLI_MODULE_PATH"
    fi
}

# 编译 Nginx
compile_nginx() {
    log "=========================================="
    log "开始编译 Nginx..."
    log "=========================================="

    cd "$BUILD_DIR/$NGINX_DIR_NAME"

    # 定义编译日志文件
    local BUILD_LOG="/tmp/nginx_build_$(date +%Y%m%d%H%M%S).log"

    # 执行配置
    log "执行 configure..."

    # 根据安装模式构建配置命令
    if [ "$INSTALL_MODE" = "brotli" ]; then
        log "使用 brotli 模式编译配置"
        ./configure \
            --prefix=$INSTALL_PREFIX \
            --user=$NGINX_USER \
            --group=$NGINX_GROUP \
            --with-http_ssl_module \
            --with-http_stub_status_module \
            --with-pcre \
            --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' \
            --with-http_gzip_static_module \
            --with-http_v2_module \
            --with-http_sub_module \
            --with-http_realip_module \
            --with-stream \
            --with-stream_ssl_module \
            --with-stream_realip_module \
            --with-http_stub_status_module \
            --add-module=$BROTLI_MODULE_PATH >> "$BUILD_LOG" 2>&1
    else
        log "使用标准模式编译配置"
        ./configure \
            --prefix=$INSTALL_PREFIX \
            --user=$NGINX_USER \
            --group=$NGINX_GROUP \
            --with-http_ssl_module \
            --with-http_stub_status_module \
            --with-pcre \
            --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' \
            --with-http_gzip_static_module \
            --with-http_v2_module \
            --with-http_sub_module \
            --with-http_realip_module \
            --with-stream \
            --with-stream_ssl_module \
            --with-stream_realip_module \
            --with-http_stub_status_module >> "$BUILD_LOG" 2>&1
    fi

    # 检查 configure 是否成功
    if [ $? -ne 0 ]; then
        log "错误: configure 失败,查看日志: $BUILD_LOG"
        tail -n 50 "$BUILD_LOG"
        exit 1
    fi

    log "configure 完成"

    # 编译
    log "执行 make 编译(使用 $(nproc) 核心,请稍候...)"
    make -j$(nproc) >> "$BUILD_LOG" 2>&1

    # 检查编译是否成功
    if [ $? -ne 0 ]; then
        log "错误: 编译失败,查看日志: $BUILD_LOG"
        tail -n 50 "$BUILD_LOG"
        exit 1
    fi

    log "编译完成"

    # 清理日志文件(可选,如果需要保留日志可以注释掉)
    rm -f "$BUILD_LOG"
}

# 安装 Nginx
install_nginx() {
    log "=========================================="
    log "安装 Nginx..."
    log "=========================================="

    cd "$BUILD_DIR/$NGINX_DIR_NAME"

    # 定义安装日志文件
    local INSTALL_LOG="/tmp/nginx_install_$(date +%Y%m%d%H%M%S).log"

    # 如果已存在安装目录,进行备份
    if [ -d "$INSTALL_PREFIX" ]; then
        BACKUP_DIR="${INSTALL_PREFIX}.bak.$(date +%Y%m%d%H%M%S)"
        log "检测到已存在的 Nginx 安装,备份到: $BACKUP_DIR"
        mv "$INSTALL_PREFIX" "$BACKUP_DIR"
    fi

    # 执行安装
    log "执行 make install..."
    make install >> "$INSTALL_LOG" 2>&1

    # 检查安装是否成功
    if [ $? -ne 0 ]; then
        log "错误: 安装失败,查看日志: $INSTALL_LOG"
        tail -n 50 "$INSTALL_LOG"
        exit 1
    fi

    log "Nginx 安装完成: $INSTALL_PREFIX"

    # 清理日志文件
    rm -f "$INSTALL_LOG"
}

# 配置 Nginx
configure_nginx() {
    log "=========================================="
    log "配置 Nginx..."
    log "=========================================="

    # 如果提供了自定义配置文件,使用自定义配置
    if [ -f "$NGINX_CONF_FILE" ]; then
        log "使用自定义 nginx.conf 配置文件..."

        # 如果是标准模式且配置文件包含 brotli,需要注释掉
        if [ "$INSTALL_MODE" = "standard" ]; then
            if grep -q "brotli" "$NGINX_CONF_FILE"; then
                log "检测到配置文件包含 brotli 指令,标准模式下将自动注释..."
                sed 's/^[[:space:]]*brotli/#&/' "$NGINX_CONF_FILE" > "$INSTALL_PREFIX/conf/nginx.conf"
                log "已注释 brotli 相关配置"
            else
                cp "$NGINX_CONF_FILE" "$INSTALL_PREFIX/conf/nginx.conf"
            fi
        else
            # brotli 模式直接复制
            cp "$NGINX_CONF_FILE" "$INSTALL_PREFIX/conf/nginx.conf"
        fi

        log "配置文件已应用: $INSTALL_PREFIX/conf/nginx.conf"
    else
        log "使用 Nginx 默认配置文件"
    fi

    # 创建必要的目录
    mkdir -p "$INSTALL_PREFIX/logs"
    mkdir -p "$INSTALL_PREFIX/conf/conf.d"
    mkdir -p "$INSTALL_PREFIX/conf/dummy_ssl"

    # 复制自签名证书(如果存在)
    if [ -d "${DIR}/conf/dummy_ssl" ]; then
        log "复制自签名证书文件..."
        cp -r "${DIR}/conf/dummy_ssl"/* "$INSTALL_PREFIX/conf/dummy_ssl/"
        log "证书文件已复制到: $INSTALL_PREFIX/conf/dummy_ssl/"
    fi

    # 复制 conf 目录下的配置文件(如果存在)
    if [ -d "${DIR}/conf" ]; then
        log "检查额外的配置文件..."
        # 只复制非 default.conf 的配置文件到 conf.d
        if ls "${DIR}/conf"/*.conf > /dev/null 2>&1; then
            for conf_file in "${DIR}/conf"/*.conf; do
                filename=$(basename "$conf_file")
                # 跳过 default.conf,因为我们会自动生成
                if [ "$filename" != "default.conf" ]; then
                    cp "$conf_file" "$INSTALL_PREFIX/conf/conf.d/"
                    log "已复制配置文件: $filename"
                fi
            done
        fi
    fi

    # 创建默认的安全配置(可选)
    create_default_security_config

    # 设置目录权限
    chown -R "$NGINX_USER:$NGINX_GROUP" "$INSTALL_PREFIX"

    log "Nginx 配置完成"
}

# 创建默认安全配置
create_default_security_config() {
    log "创建默认安全配置..."

    # 创建一个简单的 default server 配置(仅 HTTP,用于拦截未配置的域名)
    cat > "$INSTALL_PREFIX/conf/conf.d/00-default.conf" << 'EOF'
# 默认 server 配置 - 用于拦截未配置的域名和 IP 直接访问
# 这是一个安全最佳实践,防止恶意域名解析到本服务器

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    # 返回 444 表示直接关闭连接,不返回任何响应
    return 444;
}

# 如果启用了 HTTPS,取消下面的注释
# server {
#     listen 443 ssl http2 default_server;
#     listen [::]:443 ssl http2 default_server;
#     
#     server_name _;
#     
#     # 使用自签名证书(dummy 证书)
#     ssl_certificate     /AppHome/nginx/conf/dummy_ssl/dummy.crt;
#     ssl_certificate_key /AppHome/nginx/conf/dummy_ssl/dummy.key;
#     
#     return 444;
# }
EOF

    log "默认安全配置已创建: $INSTALL_PREFIX/conf/conf.d/00-default.conf"
    log "提示: 这个配置会拦截所有未配置的域名访问,提高安全性"
    log "提示: 如需启用 HTTPS 拦截,请取消 00-default.conf 中 HTTPS 部分的注释"
}

# 配置 systemd 服务
configure_systemd_service() {
    log "=========================================="
    log "配置 systemd 服务..."
    log "=========================================="

    # 如果提供了服务文件,使用提供的文件
    if [ -f "$NGINX_SERVICE_FILE" ]; then
        log "使用提供的 nginx.service 文件..."
        cp "$NGINX_SERVICE_FILE" /etc/systemd/system/nginx.service
    else
        # 创建默认的服务文件
        log "创建默认 nginx.service 文件..."
        cat > /etc/systemd/system/nginx.service << EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${INSTALL_PREFIX}/logs/nginx.pid
ExecStartPre=${INSTALL_PREFIX}/sbin/nginx -t
ExecStart=${INSTALL_PREFIX}/sbin/nginx -c ${INSTALL_PREFIX}/conf/nginx.conf
ExecReload=${INSTALL_PREFIX}/sbin/nginx -s reload
ExecStop=${INSTALL_PREFIX}/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF
    fi

    # 重新加载 systemd 配置
    systemctl daemon-reload
    log "systemd 服务配置完成"
}

# 创建命令软链接
create_symlink() {
    log "创建 nginx 命令软链接..."

    # 如果已存在软链接,先删除
    if [ -L /usr/local/bin/nginx ]; then
        rm -f /usr/local/bin/nginx
    fi

    ln -s "$INSTALL_PREFIX/sbin/nginx" /usr/local/bin/nginx
    log "软链接已创建: /usr/local/bin/nginx -> $INSTALL_PREFIX/sbin/nginx"
}

# 清理编译目录
cleanup_build_directory() {
    log "清理编译目录..."

    if [ -d "$BUILD_DIR" ]; then
        rm -rf "$BUILD_DIR"
        log "编译目录已清理: $BUILD_DIR"
    fi
}

# 验证安装
verify_installation() {
    log "=========================================="
    log "验证 Nginx 安装..."
    log "=========================================="

    # 验证 nginx 命令是否可用
    if command -v nginx &> /dev/null; then
        log "Nginx 安装成功!"
        echo ""
        echo "=========================================="
        echo "Nginx 版本信息:"
        echo "=========================================="
        nginx -v
        echo ""
        echo "=========================================="
        echo "Nginx 配置测试:"
        echo "=========================================="
        nginx -t
        echo ""

        echo "=========================================="
        echo "安装信息:"
        echo "=========================================="
        echo "安装路径: $INSTALL_PREFIX"
        echo "配置文件: $INSTALL_PREFIX/conf/nginx.conf"
        echo "日志目录: $INSTALL_PREFIX/logs"
        echo "运行用户: $NGINX_USER"
        echo "运行组: $NGINX_GROUP"
        echo "安装模式: $INSTALL_MODE"
        echo ""

        echo "=========================================="
        echo "常用命令:"
        echo "=========================================="
        echo "启动服务:   systemctl start nginx"
        echo "停止服务:   systemctl stop nginx"
        echo "重启服务:   systemctl restart nginx"
        echo "查看状态:   systemctl status nginx"
        echo "开机自启:   systemctl enable nginx"
        echo "配置测试:   nginx -t"
        echo "重载配置:   systemctl reload nginx"
        echo "=========================================="

        log "安装完成!"
    else
        log "错误: Nginx 安装失败,nginx 命令不可用。"
        exit 1
    fi
}

# 主函数
main() {
    log "=========================================="
    log "Nginx 自动安装脚本"
    log "=========================================="

    # 检查是否为 root 用户
    check_root

    # 解析命令行参数
    INSTALL_MODE_ARG=""
    if [ $# -gt 0 ]; then
        INSTALL_MODE_ARG="$1"
        AUTO_INSTALL="yes"
        log "检测到命令行参数,启用自动安装模式"
    fi

    # 选择安装模式(支持命令行参数)
    select_install_mode "$INSTALL_MODE_ARG"

    # 检查安装包
    check_packages

    # 检查并创建用户和组
    check_user_group

    # 检查已存在的 Nginx
    check_existing_nginx

    # 安装依赖
    install_dependencies

    # 准备编译环境
    prepare_build_environment

    # 编译 Nginx
    compile_nginx

    # 安装 Nginx
    install_nginx

    # 配置 Nginx
    configure_nginx

    # 配置 systemd 服务
    configure_systemd_service

    # 创建命令软链接
    create_symlink

    # 清理编译目录
    cleanup_build_directory

    # 验证安装
    verify_installation

    log "=========================================="
    log "Nginx 安装完成!"
    log "=========================================="
}

# 执行主函数
main "$@"

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇