
1. 为什么我还在用 tar 包手动编译 Nginx 1.16.1如果你在搜索引擎里敲下“Linux 安装 Nginx”大概率会看到铺天盖地的教程教你用apt-get install nginx或者yum install nginx。一键安装方便快捷这确实是大多数场景下的首选。那我为什么还要大费周章地写一篇关于用 tar 包手动编译安装一个“老版本” Nginx 1.16.1 的指南呢这背后其实有几个非常实际的考量也是很多运维和开发老手在特定场景下的真实选择。首先版本控制与定制化。系统包管理器提供的 Nginx 版本往往是发行版维护者选定的某个稳定版它可能不是最新的也几乎肯定不是某个你项目依赖的特定版本。比如一些遗留系统或特定框架可能对 Nginx 的模块版本有严格要求1.16.1 就是一个在历史上相当稳定且被广泛使用的版本。通过源码编译你可以精确锁定到这个版本确保环境的一致性避免因自动升级带来的意外问题。更重要的是编译安装让你拥有了完全的模块定制权。Nginx 的强大很大程度上源于其模块化架构但发行版提供的预编译包通常只包含最通用的模块。如果你需要用到如ngx_http_lua_module用于嵌入Lua脚本、ngx_http_headers_more_module更灵活的头部控制等第三方模块或者需要调整一些核心的编译参数比如调整worker_processes的默认值或者修改文件路径源码编译是唯一的选择。其次对生产环境更深层次的理解与掌控。手动走一遍“下载 - 解压 - 配置 - 编译 - 安装”的完整流程绝不仅仅是为了得到一个可执行文件。这个过程强迫你去思考依赖库齐不齐编译参数合不合理安装目录规划在哪里服务如何管理这能帮你建立起对软件在系统中完整生命周期的认知。当出现问题时你不会只停留在“服务起不来”的层面而能更深入地排查是依赖缺失、配置错误还是权限问题。这种掌控感是直接apt-get install无法给予的。最后应对特殊环境。在一些离线的内网环境、安全要求极高的环境或者需要对二进制文件进行深度定制的场景比如静态链接某些库、去除不必要的调试信息源码编译是标准做法。虽然本文以 Nginx 1.16.1 为例但方法论适用于绝大多数需要从源码安装的软件。理解了这套流程你就掌握了在 Linux 世界自由部署软件的一项核心技能。所以这篇指南的目标不是教你最“简单”的方法而是教你最“透彻”和“自主”的方法。我们会从最基础的准备开始一步步拆解直到将 Nginx 1.16.1 打造成一个完全受你控制的生产级服务。过程中我会穿插我这些年积累的实操心得和避坑指南这些往往是官方文档不会明说但又至关重要的细节。2. 战前准备理清依赖与规划目录在动手下载和编译之前充分的准备工作能避免后续绝大多数“莫名其妙”的错误。这个阶段的核心是两件事解决编译依赖和规划安装目录。2.1 编译依赖库的完整清单与安装Nginx 是用 C 语言写的它的编译过程依赖于一些基础的开发工具和特定的函数库。不同 Linux 发行版的包管理命令不同但思路一致。以下清单我按功能做了分类你可以对照检查。基础编译工具链这是任何源码编译的基石相当于你的“施工队”。gcc/g: GNU C/C 编译器将源代码转换成机器码。make: 构建自动化工具根据Makefile文件来指挥编译流程。automake,autoconf,libtool: 用于生成配置脚本虽然 Nginx 不使用标准的 GNU Autotools它有自己的configure脚本但某些第三方模块的编译可能会依赖。核心依赖库这些是 Nginx 运行和提供核心功能所必需的“建筑材料”。pcre: Perl Compatible Regular Expressions 库。Nginx 的location指令中的正则表达式匹配、rewrite模块等功能重度依赖它。务必安装开发版-dev或-devel因为编译时需要头文件.h和链接库.so或.a。zlib: 提供 gzip 压缩功能。Nginx 的gzip模块用它来压缩响应内容节省带宽。openssl: 提供 HTTPS 所需的 SSL/TLS 加密功能。如果你想启用ssl模块现在这几乎是必须的就必须安装它。同样需要开发版。可选但强烈推荐的依赖gd: 图形库。如果你需要 Nginx 的image_filter模块来处理图片如生成缩略图则需要它。根据你的发行版使用以下命令一次性安装请以 root 或 sudo 权限执行对于CentOS/RHEL/Fedora系列yum groupinstall -y Development Tools yum install -y pcre pcre-devel zlib zlib-devel openssl openssl-devel # 可选安装gd库 yum install -y gd gd-devel对于Ubuntu/Debian系列apt-get update apt-get install -y build-essential apt-get install -y libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev # 可选安装gd库 apt-get install -y libgd-dev实操心得在安装openssl-devel时你可能会遇到版本冲突或找不到包的情况。特别是在一些较老的系统或特定的云镜像中。一个可靠的备选方案是从openssl.org官网下载源码并编译安装到自定义目录如/opt/openssl然后在后续配置 Nginx 时通过--with-openssl/opt/openssl参数指定其路径。这虽然麻烦点但能保证你获得所需的确切版本。2.2 规划你的 Nginx 王国目录结构设计Linux 的哲学是一切皆文件并且文件各归其位。直接make install的默认安装路径可能不符合你的管理习惯。提前规划好能让后续的维护、备份、升级清晰很多。我通常采用以下结构你可以参考并调整源码目录 (/usr/local/src/)存放下载的nginx-1.16.1.tar.gz和解压后的源码。这里只是临时工作区编译完成后可以清理。安装目录 (/usr/local/nginx)这是 Nginx 的“家”。所有二进制文件、配置文件、模块、日志都将以此为基础。选择/usr/local是遵循 Unix 系统管理本地安装软件的惯例与系统自带的包管理器安装的软件通常在/usr隔离。/usr/local/nginx/sbin/存放可执行文件nginx。/usr/local/nginx/conf/存放主配置文件nginx.conf及其他子配置文件。/usr/local/nginx/logs/存放访问日志access.log和错误日志error.log。/usr/local/nginx/html/默认的网站根目录。服务运行目录 (/var相关)虽然 Nginx 可以运行在安装目录下但更规范的做法是将运行时的数据如日志放在/var下。我们可以通过配置或软链接来实现。/var/log/nginx/将日志实际存储在这里便于统一的日志管理如logrotate。/var/cache/nginx/用于代理缓存等。在开始前建议先创建好日志目录mkdir -p /var/log/nginx清晰的目录规划是系统管理专业性的体现也能在出问题时帮你快速定位。3. 核心战役下载、配置与编译安装准备工作就绪现在进入核心操作阶段。这个过程环环相扣每一步的决策都会影响最终的 Nginx。3.1 获取源码并解压到正确位置首先我们进入规划好的源码工作目录下载 Nginx 1.16.1 的源码包。我推荐从 Nginx 的官方站点下载以确保代码的纯净和安全。cd /usr/local/src # 使用wget下载如果系统没有wget请先安装yum install wget 或 apt-get install wget wget http://nginx.org/download/nginx-1.16.1.tar.gz下载完成后使用tar命令解压。这里-zxvf是一组常用选项的组合z: 自动调用gzip解压.gz文件。x: 解压extract模式。v: 显示解压过程的详细信息verbose让你看到正在解压哪些文件。f: 指定要操作的文件file后面必须紧跟文件名。tar -zxvf nginx-1.16.1.tar.gz解压后会生成一个nginx-1.16.1的目录进入它开始配置。cd nginx-1.16.13.2 理解并执行./configure定制的艺术./configure脚本是编译安装的“大脑”。它会检查你的系统环境比如我们刚才安装的依赖库是否存在并允许你通过参数来定制最终生成的 Nginx。直接运行./configure --help可以查看所有可用参数但这里我们聚焦最核心和实用的部分。一个兼顾性能、功能和可维护性的基础配置命令如下./configure \ --prefix/usr/local/nginx \ --usernginx \ --groupnginx \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_stub_status_module \ --with-http_auth_request_module \ --with-threads \ --with-stream \ --with-stream_ssl_module \ --with-mail \ --with-mail_ssl_module \ --with-file-aio \ --with-http_v2_module \ --with-cc-opt-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE2 -fexceptions -fstack-protector-strong --paramssp-buffer-size4 -grecord-gcc-switches -m64 -mtunegeneric \ --with-ld-opt-Wl,-z,relro -Wl,-z,now -Wl,--as-needed看起来很长我们来拆解一下关键部分--prefix/usr/local/nginx这是最重要的参数指定了安装的根目录。所有其他路径如sbin,conf都会基于此目录生成。--usernginx --groupnginx指定 Nginx 工作进程运行时使用的用户和组。为了安全不应该使用root。你需要先创建这个用户和组useradd -r -s /sbin/nologin nginx。-r创建系统用户-s /sbin/nologin禁止其登录 shell。模块相关参数--with-http_ssl_module启用 HTTPS 支持必须。--with-http_v2_module启用 HTTP/2 协议支持现代网站推荐。--with-http_stub_status_module启用状态页用于监控 Nginx 的基本运行状态如活跃连接数、请求数对运维很有用。--with-stream启用 TCP/UDP 代理模块这样 Nginx 就不仅能做 HTTP 反向代理还能代理数据库如 MySQL、Redis 等四层协议。--with-file-aio启用异步文件 I/O在高并发静态文件服务场景下能提升性能。--without-http_gzip_module如果你确定不需要压缩可以用这个禁用。但我们上面启用了更高级的gzip_static。编译器优化参数 (--with-cc-opt和--with-ld-opt)这些参数会传递给 C 编译器和链接器用于优化生成的可执行文件。上面给出的是一组在 x86_64 架构上比较通用的优化和安全加固参数如-O2优化级别-fstack-protector-strong栈保护。对于生产环境值得花时间根据你的 CPU 架构通过gcc -marchnative查看进行微调例如针对 Intel 的-marchskylake或 AMD 的-marchznver2可以带来小幅性能提升。执行./configure命令后终端会输出大量的检查信息。你需要仔细阅读最后几行确保没有出现error字样。常见的错误是某个依赖库没找到比如checking for PCRE library ... not found checking for PCRE library in /usr/local/ ... not found如果遇到请返回 2.1 节确认对应的-devel或-dev包是否已正确安装。避坑指南configure过程会生成一个重要的中间文件objs/ngx_modules.c它决定了哪些模块会被编译进 Nginx。如果你后续想增删模块必须重新执行./configure并重新编译安装而不能仅仅替换二进制文件。这是一个常见的误解点。3.3 编译 (make) 与安装 (make install)配置成功后就可以开始编译了。这个过程就是把 C 源码变成二进制可执行文件。makemake命令会读取当前目录下的Makefile文件由configure生成并调用gcc等工具进行编译。根据机器性能这个过程可能需要几十秒到几分钟。如果编译成功不会有错误信息最终会在objs目录下生成nginx二进制文件。接下来是安装这会把编译好的文件、配置文件、默认网页等复制到--prefix指定的目录/usr/local/nginx。make install执行成功后你可以到/usr/local/nginx目录下查看成果ls -la /usr/local/nginx/你应该能看到sbin,conf,html,logs等目录。重要提示make install通常需要 root 权限因为它会向系统目录写入文件。如果你当前不是 root 用户请使用sudo make install。4. 战后整顿配置、服务化与基础调优软件安装完成只是“能用”。要让它“好用”且“耐用”还需要进行服务化整合和基础配置。4.1 初步配置与启动测试首先检查一下安装生成的默认配置文件/usr/local/nginx/sbin/nginx -t这个-t参数代表测试test配置文件的语法是否正确。这是启动前必须做的一步可以避免因为配置文件的笔误导致服务启动失败。如果输出syntax is ok和test is successful说明配置文件语法没问题。现在可以尝试启动/usr/local/nginx/sbin/nginx没有报错的话Nginx 应该已经在后台运行了。你可以用ps命令查看进程或者用curl测试ps aux | grep nginx curl http://localhost如果看到 Nginx 的欢迎页面一段 HTML 代码说明安装和启动成功。4.2 创建 Systemd 服务单元以 CentOS 7/Ubuntu 16.04 为例使用二进制文件直接启动和管理服务很不方便。现代 Linux 系统普遍使用systemd来管理服务。我们需要创建一个服务单元文件。创建文件/usr/lib/systemd/system/nginx.serviceUbuntu 可能在/etc/systemd/system/内容如下[Unit] DescriptionThe nginx HTTP and reverse proxy server Afternetwork.target remote-fs.target nss-lookup.target [Service] Typeforking PIDFile/usr/local/nginx/logs/nginx.pid ExecStartPre/usr/local/nginx/sbin/nginx -t ExecStart/usr/local/nginx/sbin/nginx ExecReload/bin/kill -s HUP $MAINPID ExecStop/bin/kill -s QUIT $MAINPID PrivateTmptrue Usernginx Groupnginx [Install] WantedBymulti-user.target关键点解析After: 定义启动顺序确保网络等基础服务就绪后再启动 Nginx。Typeforking: 因为 Nginx 主进程会 fork 出子进程所以服务类型是 forking。PIDFile: 指明 Nginx 主进程的 PID 文件位置systemd靠它来跟踪服务。ExecStartPre: 在正式启动前执行配置测试这是一个非常好的安全实践。ExecReload: 定义重载配置的命令发送 HUP 信号给 Nginx 主进程使其平滑重载配置而不中断服务。User/Group: 指定服务运行身份与我们configure时指定的保持一致增强安全性。保存文件后执行以下命令让systemd识别并启用这个服务systemctl daemon-reload systemctl enable nginx # 设置开机自启 systemctl start nginx # 启动服务 systemctl status nginx # 查看状态现在你就可以用熟悉的systemctl start|stop|restart|reload|status nginx来管理 Nginx 了这才是生产环境应有的管理方式。4.3 基础性能与安全调优修改 nginx.conf默认的nginx.conf配置比较保守。根据你的服务器硬件主要是 CPU 核心数和内存进行一些基础调优是必要的。打开/usr/local/nginx/conf/nginx.conf工作进程数worker_processes参数应该设置为等于或略大于你的 CPU 核心数。你可以通过grep processor /proc/cpuinfo | wc -l查看核心数。对于高并发场景可以设置为auto让 Nginx 自动检测。worker_processes auto;每个进程的连接数events块下的worker_connections定义了每个工作进程同时处理的最大连接数。这个值受系统最大打开文件数限制ulimit -n。一个合理的设置是worker_connections 10240;。你需要确保系统的nofile限制足够大可以通过修改/etc/security/limits.conf并重启会话来实现。启用高效事件模型在events块中根据你的系统选择高效的事件处理模型。对于 Linux 2.6 内核epoll是最佳选择。events { use epoll; worker_connections 10240; multi_accept on; # 告诉worker进程一次性接受所有新连接 }调整缓冲区大小在http块中适当增大一些缓冲区可以提升性能但会消耗更多内存。需要根据实际情况权衡。http { client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m; # 允许上传的最大文件大小按需调整 large_client_header_buffers 4 4k; ... }关闭服务器令牌在http块或server块中添加server_tokens off;。这可以隐藏 Nginx 的版本号增加一点安全性避免攻击者针对特定版本漏洞进行扫描。修改完配置后务必先测试再重载/usr/local/nginx/sbin/nginx -t systemctl reload nginx5. 进阶模块管理与故障排查入门5.1 如何添加第三方模块以echo-nginx-module为例有时你需要官方未包含的模块。第三方模块通常也是源码形式。添加它们需要在编译前的configure步骤通过--add-module参数指定模块源码路径。假设我们要添加一个用于调试的、非常流行的echo模块在/usr/local/src目录下载模块源码cd /usr/local/src git clone https://github.com/openresty/echo-nginx-module.git如果没有 git用wget下载 release 包并解压重新配置。这是关键你必须回到 Nginx 源码目录在原有的./configure命令后面追加--add-module参数。cd /usr/local/src/nginx-1.16.1 ./configure [你之前所有的参数] --add-module/usr/local/src/echo-nginx-module重要[你之前所有的参数]必须和第一次编译时完全一致否则新编译的 Nginx 配置可能会丢失原有模块。重新编译和安装make # 安装前建议备份旧的nginx二进制文件 cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak make installmake install会覆盖旧的二进制文件。由于配置参数一致它不会覆盖你的nginx.conf等配置文件。验证模块是否被加入/usr/local/nginx/sbin/nginx -V 21 | grep echo如果输出中包含--add-module/usr/local/src/echo-nginx-module说明添加成功。然后你就可以在nginx.conf中使用echo指令了。核心教训Nginx 不支持运行时动态加载模块。任何模块的增删都必须重新编译整个 Nginx。因此在生产环境规划阶段就应尽量考虑周全一次性将可能用到的模块都编译进去避免频繁重新编译上线。5.2 初次启动常见问题排查即使按照教程一步步来第一次启动也可能遇到问题。这里列出几个最常见的nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)原因80 端口已被其他程序如 Apache、另一个 Nginx 实例、或者某些系统服务占用。解决找出占用者sudo netstat -tlnp | grep :80停止那个服务或者修改 Nginx 配置文件中的listen端口。nginx: [emerg] open() /usr/local/nginx/logs/access.log failed (13: Permission denied)原因Nginx 工作进程以nginx用户运行没有权限在指定路径创建或写入日志文件。解决确保日志目录如/usr/local/nginx/logs或/var/log/nginx存在并且其所有者是nginx用户或者至少有写入权限。chown -R nginx:nginx /usr/local/nginx/logs # 或者如果日志在/var/log/nginx chown -R nginx:nginx /var/log/nginxnginx: [emerg] getpwnam(nginx) failed原因在配置中指定了user nginx;但系统中不存在名为nginx的用户。解决创建nginx系统用户和组useradd -r -s /sbin/nologin nginx。使用systemctl start nginx失败但手动执行/usr/local/nginx/sbin/nginx可以启动原因通常是systemd服务文件nginx.service中的路径、用户或PIDFile设置错误。解决检查服务文件中ExecStart、PIDFile的路径是否正确。检查User和Group是否存在。通过journalctl -xe -u nginx查看详细的启动日志这是排查systemd服务问题的利器。5.3 基础运维命令与日志查看测试配置文件任何时候修改nginx.conf后第一件事就是运行nginx -t。平滑重载配置nginx -s reload或systemctl reload nginx。这不会中断正在处理的连接。平滑停止服务nginx -s quit会等待工作进程处理完当前请求后再退出。立即停止nginx -s stop或systemctl stop nginx。重新打开日志文件nginx -s reopen。这在日志切割使用logrotate或手动移动日志后时非常有用通知 Nginx 重新打开新的日志文件。查看错误日志这是排错最重要的依据。默认路径在logs/error.log。使用tail -f /usr/local/nginx/logs/error.log可以实时查看日志输出。查看状态页如果你编译时启用了--with-http_stub_status_module可以在配置文件中添加一个location来暴露状态信息然后用浏览器或curl访问可以快速了解当前的连接数、请求率等关键指标。手动编译安装 Nginx 的旅程到这里就基本完成了。从解决依赖、规划目录到配置、编译、安装再到服务化管理和基础调优这套流程不仅适用于 Nginx其核心思想——通过源码获得完全控制权通过规划实现可维护性通过系统集成实现规范化管理——可以迁移到绝大多数 Linux 开源软件的部署中。它赋予你的不仅仅是软件本身更是一种深入理解系统运作方式的能力。下次当你再遇到需要定制化部署的场景时这套方法论将会是你的得力工具。