Shell脚本自动化部署Nginx实战指南
1. Shell脚本与Nginx一键部署实战指南
在Linux系统管理中,Shell脚本就像瑞士军刀一样不可或缺。最近在帮朋友部署Web服务时,我重新整理了一套经过实战检验的Nginx一键部署脚本,这个过程中发现很多新手容易在基础环节踩坑。今天就把这些年积累的Shell编程经验和Nginx部署技巧系统梳理出来,特别是那些官方文档不会告诉你的"野路子"。
这个方案最大的特点是"开箱即用"——只需一个脚本就能完成从环境检测到服务启用的全过程,同时内置了7种常见错误的自动修复机制。我还会分享如何用Shell实现服务状态监控、日志轮转等进阶功能,这些技巧同样适用于其他服务的自动化部署。无论你是刚接触Linux系统管理,还是需要批量部署Web环境的老手,这套方法都能节省你大量重复劳动的时间。
2. 环境准备与基础检测
2.1 系统兼容性处理
先来看脚本开头的环境检测部分,这是很多简易脚本会忽略的关键环节:
#!/bin/bash set -euo pipefail # 系统发行版检测 if [ -f /etc/os-release ]; then . /etc/os-release OS=$ID VER=$VERSION_ID elif type lsb_release >/dev/null 2>&1; then OS=$(lsb_release -si | tr '[:upper:]' '[:lower:]') VER=$(lsb_release -sr) else OS=$(uname -s) VER=$(uname -r) fi这个检测模块之所以重要,是因为不同Linux发行版的包管理器和Nginx安装方式差异很大。比如在CentOS上需要用yum安装EPEL源,而Ubuntu则直接apt-get就行。我特别添加了set -euo pipefail这行,它能实现三个防护:
-e:命令失败时立即退出-u:遇到未定义变量时报错-pipefail:管道中任意命令失败则整个管道失败
经验:在线上环境运行的脚本务必加上这些参数,能避免很多灵异问题。曾经有个坑是脚本在缺少依赖时继续执行,最后把测试环境的配置推到了线上...
2.2 依赖项自动化检查
接下来是依赖检查的进阶写法:
# 定义依赖项数组 DEPS=("gcc" "make" "wget" "perl" "tar") MISSING_DEPS=() # 检查依赖项 for dep in "${DEPS[@]}"; do if ! command -v $dep >/dev/null 2>&1; then MISSING_DEPS+=("$dep") fi done # 自动安装缺失依赖 if [ ${#MISSING_DEPS[@]} -ne 0 ]; then echo "[INFO] Installing missing dependencies: ${MISSING_DEPS[*]}" case $OS in "centos"|"rhel"|"fedora") yum install -y "${MISSING_DEPS[@]}" || { echo "[ERROR] Failed to install dependencies" exit 1 } ;; "ubuntu"|"debian") apt-get update && apt-get install -y "${MISSING_DEPS[@]}" || { echo "[ERROR] Failed to install dependencies" exit 1 } ;; *) echo "[ERROR] Unsupported OS: $OS" exit 1 ;; esac fi这种写法比逐个检查优雅得多,而且容易扩展。注意几个细节:
- 使用
command -v而不是which,兼容性更好 - 数组存储缺失项,避免重复安装
- 每种包管理器都有错误处理逻辑
3. Nginx安装与配置自动化
3.1 智能安装策略
我推荐从源码编译安装而不是直接使用包管理器,原因有三:
- 可以自定义模块(如HTTP/2支持)
- 避免发行版维护者修改的默认配置
- 方便多版本并存
NGINX_VERSION="1.25.3" INSTALL_DIR="/usr/local/nginx" PCRE_VERSION="8.45" ZLIB_VERSION="1.3" download_and_extract() { local url=$1 local dir=$2 echo "[INFO] Downloading ${url##*/}" wget -q --show-progress "$url" -O "${url##*/}" || { echo "[ERROR] Download failed" exit 1 } tar xzf "${url##*/}" || { echo "[ERROR] Extraction failed" exit 1 } rm -f "${url##*/}" } # 并行下载依赖 download_and_extract "https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz" "nginx-$NGINX_VERSION" & download_and_extract "https://sourceforge.net/projects/pcre/files/pcre/$PCRE_VERSION/pcre-$PCRE_VERSION.tar.gz" "pcre-$PCRE_VERSION" & download_and_extract "https://zlib.net/zlib-$ZLIB_VERSION.tar.gz" "zlib-$ZLIB_VERSION" & wait这里用了并行下载技巧,通过&后台执行和wait命令,三个组件的下载解压同时进行,比串行操作快2-3倍。注意每个下载任务都有错误处理,避免部分失败导致后续步骤异常。
3.2 编译参数优化
编译阶段是最容易出问题的环节,这个配置经过生产环境验证:
cd "nginx-$NGINX_VERSION" || exit ./configure \ --prefix=$INSTALL_DIR \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ --with-pcre="../pcre-$PCRE_VERSION" \ --with-zlib="../zlib-$ZLIB_VERSION" \ --with-threads \ --with-file-aio \ --with-http_addition_module \ --with-http_sub_module || { echo "[ERROR] Configure failed" exit 1 } make -j$(nproc) && make install || { echo "[ERROR] Make failed" exit 1 }关键参数说明:
-j$(nproc):根据CPU核心数并行编译--with-threads:启用线程池提升性能--with-file-aio:异步文件I/O支持- status模块用于监控(后面会用到)
踩坑记录:曾经在ARM服务器上编译时忘了指定pcre路径,导致正则性能下降50%。现在脚本里显式关联了依赖路径。
4. 服务化与开机自启
4.1 Systemd服务配置
源码安装的Nginx默认没有服务管理,需要手动创建systemd单元:
cat > /etc/systemd/system/nginx.service <<EOF [Unit] Description=The NGINX HTTP and reverse proxy server After=syslog.target network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=$INSTALL_DIR/logs/nginx.pid ExecStartPre=$INSTALL_DIR/sbin/nginx -t ExecStart=$INSTALL_DIR/sbin/nginx ExecReload=$INSTALL_DIR/sbin/nginx -s reload ExecStop=/bin/kill -s QUIT \$MAINPID PrivateTmp=true Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target EOF几个值得注意的配置项:
After:确保网络就绪后再启动Type=forking:Nginx以daemon方式运行Restart=on-failure:崩溃后自动重启PrivateTmp:服务使用独立临时目录
4.2 权限与SELinux适配
处理权限问题的一站式方案:
# 创建nginx用户 if ! id -u nginx >/dev/null 2>&1; then useradd -r -s /sbin/nologin nginx fi # 调整目录权限 chown -R nginx:nginx $INSTALL_DIR find $INSTALL_DIR -type d -exec chmod 755 {} \; find $INSTALL_DIR -type f -exec chmod 644 {} \; # SELinux上下文设置 if command -v semanage >/dev/null 2>&1; then semanage fcontext -a -t httpd_sys_content_t "$INSTALL_DIR/html(/.*)?" semanage fcontext -a -t httpd_log_t "$INSTALL_DIR/logs(/.*)?" restorecon -Rv $INSTALL_DIR fi这段脚本处理了三个层面的权限:
- 系统账户创建
- 基础文件权限
- SELinux上下文(如果启用)
5. 高级功能实现
5.1 日志轮转配置
用logrotate实现自动化日志管理:
cat > /etc/logrotate.d/nginx <<EOF $INSTALL_DIR/logs/*.log { daily missingok rotate 30 compress delaycompress notifempty create 0640 nginx nginx sharedscripts postrotate [ -f $INSTALL_DIR/logs/nginx.pid ] && kill -USR1 \$(cat $INSTALL_DIR/logs/nginx.pid) endscript } EOF参数优化点:
delaycompress:延迟压缩昨天的日志create:保持正确的文件属主USR1信号:通知Nginx重新打开日志文件
5.2 状态监控接口
利用stub_status模块实现基础监控:
cat > $INSTALL_DIR/conf/conf.d/status.conf <<EOF server { listen 127.0.0.1:8080; server_name localhost; location /nginx_status { stub_status; access_log off; allow 127.0.0.1; deny all; } } EOF配置完成后可以通过curl http://127.0.0.1:8080/nginx_status获取如下信息:
Active connections: 3 server accepts handled requests 100 100 200 Reading: 0 Writing: 1 Waiting: 26. 完整脚本与使用说明
将上述所有功能整合后的脚本结构如下:
#!/bin/bash set -euo pipefail # 第一部分:环境检测 [环境检测代码...] # 第二部分:依赖安装 [依赖安装代码...] # 第三部分:源码编译 [下载编译代码...] # 第四部分:配置生成 [配置文件生成...] # 第五部分:服务注册 [systemd配置...] # 第六部分:权限处理 [权限设置代码...] # 第七部分:辅助功能 [日志轮转等代码...]使用方式:
- 保存为
install_nginx.sh - 添加执行权限:
chmod +x install_nginx.sh - 直接运行:
./install_nginx.sh
7. 常见问题排查手册
7.1 端口冲突处理
如果启动时报bind() to 0.0.0.0:80 failed错误:
# 检查占用进程 ss -tulnp | grep ':80\b' # 临时释放端口 systemctl stop apache2 # 或其他占用进程 # 或者修改Nginx监听端口 sed -i 's/listen.*80;/listen 8080;/' $INSTALL_DIR/conf/nginx.conf7.2 模块加载失败
出现unknown directive错误时,通常是编译时缺少对应模块:
- 查看已编译模块:
nginx -V 2>&1 | grep --color=always module - 重新编译添加缺失模块,例如stream支持:
./configure --with-stream [...原有参数...]7.3 性能调优建议
在高并发场景下建议调整以下参数:
events { worker_connections 65536; multi_accept on; use epoll; } http { keepalive_timeout 30s; keepalive_requests 1000; sendfile on; tcp_nopush on; }8. 脚本安全增强建议
生产环境使用前建议添加以下安全检查:
- 下载完整性验证:
wget_verify() { local url=$1 local checksum=$2 local filename=${url##*/} wget -q --show-progress "$url" -O "$filename" || return 1 echo "$checksum $filename" | sha256sum -c --quiet || { rm -f "$filename" return 1 } }- 敏感操作确认:
read -rp "This will install Nginx to $INSTALL_DIR. Continue? [y/N] " confirm [[ $confirm == [yY] ]] || exit 0- 操作日志记录:
exec > >(tee -a nginx_install.log) exec 2>&1 echo "[$(date)] Starting installation"这套脚本经过CentOS 7/8、Ubuntu 18.04/20.04等多个环境的测试验证,累计部署次数超过200+。最让我自豪的是其中包含的7种自动修复逻辑,比如遇到缺少编译器时会自动安装开发工具包,检测到旧版本Nginx时会先执行清理等。把这些经验固化到脚本里,至少能为每个新手节省8小时的排错时间。
