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
安装过程
脚本会自动完成以下操作:
- 环境检查
- 检查 root 权限
- 检查并创建运行用户和组(gzapps)
- 检查安装包是否存在
- 安装依赖
- 自动检测包管理器(dnf/yum/apt-get)
- 安装编译工具(gcc、make、pcre、zlib、openssl)
- Brotli 模式额外安装 brotli 相关包
- 编译安装
- 解压源码到临时目录
- 执行 configure 配置
- 多核并行编译(使用所有 CPU 核心)
- 安装到 /AppHome/nginx
- 配置系统
- 应用自定义配置文件(如果提供)
- 标准模式自动注释 brotli 配置
- 创建必要的目录结构
- 复制自签名证书
- 创建默认安全配置(拦截未配置的域名)
- 配置 systemd 服务
- 创建命令软链接
- 清理和验证
- 清理编译临时目录
- 验证安装是否成功
- 测试配置文件语法
安装后的目录结构
/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
注意事项
- 系统要求:
- 必须使用 root 权限运行
- 确保系统有足够的磁盘空间(至少 500MB)
- 确保系统可以访问软件源
- 用户和组:
- 默认使用 gzapps 用户运行
- 脚本会自动创建用户和组
- 如需修改,请编辑脚本中的 NGINX_USER 和 NGINX_GROUP 变量
- 端口占用:
- 默认监听 80 端口
- 如果端口被占用,需要先停止占用端口的服务
- 防火墙:
- 记得开放 80 和 443 端口
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload - 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 "$@"