ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Nginx离线安装完全指南:依赖准备、编译配置与内网部署实战

2026/9/19 0:24:09 拓冰建站 浏览量
Nginx离线安装完全指南:依赖准备、编译配置与内网部署实战 1. 为什么要做离线安装和在线安装差在哪先说结论离线安装Nginx这件事往往不是“想不想”的问题而是“只能这么干”的问题。我在一线运维这几年真正动手做离线安装的场景基本都是同一类服务器在内网隔离区、生产环境不允许直接连外网、或者客户现场的网络策略卡得很死。这种情况下yum、apt、wget这些平时用得行云流水的操作全部失效你只能靠优盘、内网FTP或者堡垒机上传递文件把安装包“人肉”带进服务器。在线安装和离线安装的本质差异不在Nginx本身而在“依赖”两个字。在线安装时包管理器会自动帮你把PCRE、zlib、openssl这些依赖一并拉下来离线安装时这些依赖一个都不会自己出现必须你亲手准备齐全。这就像出门吃饭在线安装是去食堂刷卡就行离线安装是去野外露营锅碗瓢盆、米面油盐、打火机全得自己背包里带上。少带一样饭就做不成。还有一个经常被忽略的点是“版本一致性”。在线安装你看到的依赖版本是软件仓库里当前最新的那一批离线安装你手里拿到的是在有网机器上下载时固定的那一批。这个差异会直接影响编译是否顺利。所以我现在做离线安装第一步永远是先把环境信息摸清楚再决定用哪些版本的包而不是随手拿个安装包就往生产服务器上怼。另外要提醒一句如果你只是在自己笔记本的虚拟机上实验网络又是通的那完全不需要离线安装直接yum install nginx或者apt install nginx就完事。这篇文章是给那些“必须离线、而且还得编译安装”的人准备的。我下面分享的过程是我在CentOS 7.x和银河麒麟这类系统上反复验证过的你把命令照抄过去踩坑概率会低很多。2. 动手前的准备版本选型与依赖盘点2.1 先确认你的服务器基础信息不管装在什么系统上第一件事不是下载安装包而是先看目标机器的“底细”。先执行下面这三条命令cat /etc/os-release uname -m cat /proc/version/etc/os-release告诉你操作系统发行版和版本号uname -m告诉你架构是x86_64还是aarch64/proc/version里能看到内核编译信息有的老机器内核版本比较低这会影响你选Nginx版本。比如你在aarch64的机器上装了x86_64编译出来的二进制那肯定跑不起来这种低级错误我见过不止一次。还有一个很容易被忽略的检查项是看目标机器上是否已经装了gcc和make。Nginx官方提供的源码包是C语言写的编译必须靠gcc构建过程要靠make。如果目标机器连编译工具链都没有你就得多带两个RPM包进去。可以用下面的命令快速判断gcc --version make --version如果提示command not found那你还需要额外准备gcc、make相关的RPM安装包或者干脆找一台架构相同的机器把编译好的整个Nginx目录打包拷过去。后者是很多老运维的土办法但说实话后续升级和管理都不如编译安装来得清爽所以我更推荐老老实实把依赖带齐。2.2 Nginx离线安装的四大依赖Nginx编译安装时最重要的依赖有四个PCRE、zlib、OpenSSL以及一个隐藏依赖——C编译器工具链。前三个分别承担不同的职责PCRE库Nginx的rewrite模块重度依赖正则表达式PCRE就是这个正则引擎。在Nginx 1.17之前基本都是用PCRE 8.x系列新版官方建议用PCRE2但要注意编译参数的写法会有变化下面实操里我会详细说。zlib库提供gzip压缩能力。如果你不在编译参数里指定--with-http_gzip_static_module或者--with-http_gzip_modulezlib不是强制的但生产环境你几乎一定会开gzip所以这个依赖基本属于必带。OpenSSL库提供HTTPS支持。只要你想配置ssl监听、颁发自签名证书或者做TLS反向代理就必须有OpenSSL。很多生产环境要求HTTPS加密传输这个依赖不能省。依赖的获取方式有两种。一种是在有网机器上直接下载源码包PCRE去官网找tar.gzzlib去官网找tar.gzOpenSSL去官网找tar.gz。另一种是直接下载RPM包。我在实际项目里更推荐源码包因为RPM包比较依赖系统版本比如CentOS 7的RPM用到CentOS 6上经常装不上而源码包只要编译器能做交叉编译基本都能适配。2.3 有网机器上准备离线安装包假设你现在有台能上外网的机器或者自己在本地电脑上操作先把下面这些包下载好备用。具体版本号以我当时实操为准不一定最新但稳定组合验证过nginx-1.24.0.tar.gzpcre2-10.42.tar.gzzlib-1.3.tar.gzopenssl-3.0.13.tar.gz如果你不确定去哪里找下载地址就直接去官网对应的下载目录页面找Nginx官网提供的是nginx.org/download/pcre.org是PCRE的官方网站zlib.net是zlib官网openssl.org是OpenSSL的官网。把这些tar.gz打包放到一个目录下比如我习惯建一个/opt/nginx-offline-packages/。除此之外强烈建议再准备两个东西一个是有网机器上执行过的安装命令记录方便你后面核对编译参数另一个是Nginx官方文档的离线版或者PDF版万一内网环境打不开官网你还能查参数说明。别笑实战中“查不了文档”是离线环境最大的痛点我因为记错指令去试错浪费过不少时间。3. 完整实操离线环境编译安装Nginx3.1 将离线包拷贝到目标机器的三种方式包里准备好之后怎么把文件安全地弄进内网机器也有讲究。我先说三种我实测过的方式大家按自己环境选择。第一种如果有内网FTP或者HTTP文件服务器直接让运维开个临时目录用curl或wget拉取wget http://192.168.1.100/pub/nginx-offline.tar.gz第二种只允许SSH访问的话用scp或者sftpscp -P 22 /opt/nginx-offline-packages.tar.gz root目标IP:/opt/第三种实在不行就用堡垒机的文件上传功能我遇到很多保密要求高的项目只能走这条路。拷完之后先校验一下文件完整性免得传输过程中文件损坏md5sum /opt/nginx-offline-packages.tar.gz把输出的MD5值和有网机器上算出来的对比一下一致再继续。这一步看起来很鸡肋但我真的遇到过一次传完了最后编译报错排查半天发现是文件在传输时被截断了。3.2 解压并配置编译参数进入目标机器的/opt目录先把压缩包解开cd /opt tar -xzf nginx-offline-packages.tar.gz cd nginx-offline-packages解开后你会看到四个源码目录。然后进入Nginx源码目录配置编译参数。这里直接给出我常用的一套参数你可以根据自己的实际需求增删cd nginx-1.24.0 ./configure \ --prefix/usr/local/nginx \ --sbin-path/usr/sbin/nginx \ --conf-path/etc/nginx/nginx.conf \ --pid-path/var/run/nginx.pid \ --error-log-path/var/log/nginx/error.log \ --http-log-path/var/log/nginx/access.log \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_gzip_static_module \ --with-pcre../pcre2-10.42 \ --with-zlib../zlib-1.3 \ --with-openssl../openssl-3.0.13每条参数后面都是有讲究的。--prefix指定安装根目录--sbin-path把可执行文件直接放到/usr/sbin下这样你在任何目录直接输入nginx就能执行不用加路径--conf-path把配置文件放在/etc/nginx下这更符合Linux的FHS习惯三个--with参数是离线安装时最关键的它们告诉编译系统“PCRE、zlib和OpenSSL我放在这里你编译时直接引用。”这里有个大坑如果你用了PCRE2而且你的Nginx版本比较老比如1.20.x可能会报错说找不到PCRE因为老版本源码里的一些头文件引用还是PCRE 8.x的写法。我用1.24.0配合PCRE2 10.42实测没问题但如果你的Nginx是1.18或者更早建议还是下载PCRE 8.45这个版本省得折腾。3.3 编译安装与动态链接库处理配置成功后屏幕会打印出一大堆摘要信息最后一句一般是“Configuration summary”加“Support the following modules”看到这些说明configure这一步过了。接着执行编译和安装make -j4 make install-j4是让make并行编译用几个核看你服务器的CPU配置nproc命令可以查。并行编译能明显缩短时间但如果你内存只有1G建议别开太多并行任务不然内存会被撑爆。编译过程中可能出现一个非常典型的报错找不到libpcre.so或者libssl.so。这往往不是真的没装而是动态链接库路径没有更新。处理办法是修改/etc/ld.so.conf把动态库所在的目录加进去然后执行ldconfigecho /usr/local/lib /etc/ld.so.conf ldconfig如果编译完之后你直接运行/usr/local/nginx/sbin/nginx提示找不到某些动态库也可以用这个办法解决。安装完成后验证一下二进制文件是否能正常执行/usr/local/nginx/sbin/nginx -V这条命令会把编译参数和版本信息打印出来看到你之前配置的那一串--with参数都在说明编译安装成功了。3.4 注册systemd服务并设置开机自启编译安装完的Nginx默认不会开机自启。生产环境里服务器重启之后Nginx没起来那可是事故。所以我建议直接把systemd服务文件写好。在/usr/lib/systemd/system/nginx.service里新建一个文件[Unit] Descriptionnginx - high performance web server Afternetwork.target remote-fs.target nss-lookup.target [Service] Typeforking PIDFile/var/run/nginx.pid ExecStartPre/usr/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart/usr/sbin/nginx -c /etc/nginx/nginx.conf ExecReload/usr/sbin/nginx -s reload ExecStop/usr/sbin/nginx -s quit PrivateTmptrue [Install] WantedBymulti-user.target写完之后依次执行systemctl daemon-reload systemctl enable nginx.service systemctl start nginx.service systemctl status nginx.service看到Active: active (running)就说明服务起来且开机自启已经设置好了。这里的ExecStartPre会在启动前先做一次配置语法检查如果配置文件写错了服务根本不会启动这个设计能避免把线上服务搞挂。如果是老一点的内网系统systemd还没有普及那你可以走传统方式在/etc/rc.d/rc.local里加一行/usr/sbin/nginx然后给rc.local加执行权限chmod x /etc/rc.d/rc.local这条方法在CentOS 6、7早期版本以及某些国产系统上都还适用。4. Nginx核心配置与上线前验证4.1 先理解nginx.conf的骨架结构安装完成了服务也起来了接下来就是配置了。我见过很多新手上来就改nginx.conf结果改完一执行nginx -t就报错。想少踩坑先把配置文件的结构搞清楚。Nginx的配置文件核心是“块”的概念。整个文件从外到内依次是main块、events块、http块、server块、location块。层级关系像一个俄罗斯套娃外层配置默认作用在全局内层配置只作用于它那一个范围。事件模型、worker进程数、日志文件路径通常在main级或http级配置具体某个域名或端口的监听参数放在server块针对不同URL路径的处理规则放在location块。一份最精简的nginx.conf长这样worker_processes auto; worker_rlimit_nofile 65535; events { worker_connections 2048; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; server_tokens off; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } } }worker_processes auto是让Nginx根据CPU核心数自动决定worker进程数省得手动算。worker_rlimit_nofile是提升文件描述符上限在线上的高并发场景非常关键不然连接数一多就会报too many open files。sendfile on是提升静态文件传输效率的利用内核的sendfile系统调用直接拷贝数据减少用户态和内核态的切换。4.2 一份最常用的server配置示例实际工作中大多数场景是把Nginx当作网站服务器或者反向代理。我贴一份适合测试环境的完整server块配置你直接替换上面配置里的server部分即可server { listen 8080; server_name your.domain.com; charset utf-8; access_log /var/log/nginx/your.domain.access.log main; error_log /var/log/nginx/your.domain.error.log; location / { root /var/www/yourproject; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }这里有些细节值得注意try_files $uri $uri/ /index.html是前端单页应用部署常见的写法路由是history模式时刷新页面不会404这行配置能把所有未命中的请求都返回给index.html。proxy_set_header三行是必要的否则后端拿不到真实客户端IP日志排查时会很痛苦。我的习惯是把不同项目的access_log和error_log分开整个内网的应用都是各记各的排查问题比全堆在一个主日志里方便多了。4.3 配置语法检查与平滑重载改完配置千万别直接重启Nginx先做语法检查/usr/sbin/nginx -t如果输出syntax is ok和test is successful说明配置没问题。然后执行平滑重载/usr/sbin/nginx -s reload平滑重载的原理是master进程收到信号后重新读取配置文件并创建新的worker进程处理完当前请求后旧worker会自动退出。这个过程中已有的连接不会中断这是Nginx在运维体验上最大的优势之一。所以在生产环境改完配置永远是reload而不是restart除非你改了listen端口或server_name这类无法热加载的属性。4.4 反向代理与负载均衡配置速览做反向代理和负载均衡是Nginx在内网环境里最常见的使用场景。上游有多台后端服务时用upstream块做负载均衡upstream backend_servers { server 192.168.1.11:8080 weight3; server 192.168.1.12:8080 weight1; } server { listen 80; server_name proxy.internal; location / { proxy_pass http://backend_servers; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }weight3表示相对权重意思是第一台服务器承受的请求量大约是三倍于第二台。如果不写weight默认每台权重相同Nginx会按轮询策略分发请求。离线环境内部署这种代理结构的人不少很多业务系统做服务拆分后各个服务的入口统一走Nginx维护起来很省心。另外如果后端是HTTPS接口Nginx需要在上游请求时做SSL转发你可以在proxy_pass后面加上https或者在upstream里增加SSL相关参数。这个场景配置复杂一点但思路是清晰的客户端用HTTP访问NginxNginx回源时再走HTTPS。只要你编译时有--with-http_ssl_module这些都能支持。5. 高频踩坑实录与排查方法5.1 编译阶段的三大报错我在离线安装过程中碰到最多的编译报错就三类这里把排查思路写出来。第一类是checking for pcre library... not found或者C compiler cannot create executables。前者说明configure没找到PCRE要么是路径没写对要么是用错了PCRE版本。后者说明gcc编译器本身有问题可能没装或者环境变量不对。解决方式是先重跑configure确认--with-pcre../pcre2-10.42的路径确实存在再检查gcc --version是否有输出。离线环境最容易出现“源码包没拷全”的情况我就经历过把Nginx和zlib带进去了PCRE忘带configure报错又回去重新传文件特别折腾。第二类是make: *** No rule to make target build这类报错。这通常是configure过程没跑完就中断导致make没有生成正确的Makefile。之所以configure没跑完大概率是依赖检查时某个库找不到你直接跳过了错误信息。所以遇到这个报错我的建议是回到configure那一步把最后几行日志认真看完找出它到底卡在哪个库上。第三类是undefined reference to pcre_free_study。这个报错很典型版本匹配问题。你在老版本Nginx里传了太新的PCRE2两个版本的接口对不上。解决方式很直接换PCRE 8.45重新编译别硬刚。5.2 启动阶段的问题编译安装成功后执行nginx不报错但浏览器访问不了这种问题也很常见。我的排查顺序是固定的先看进程有没有起来ps -ef | grep nginx再看日志tail -100 /var/log/nginx/error.log如果进程起来但页面打不开大概率是防火墙拦截了端口。内网环境经常有安全组策略放行规则不归你管这时候你需要联系运维确认80或者8080端口是否放通。如果日志里报[emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)说明你没有权限监听1024以下端口需要以root身份启动。还有一个隐蔽的坑SELinux。很多CentOS系统默认开着SELinux它会在权限层面对进程进行额外限制。如果Nginx启动正常、防火墙端口也放行了但仍然访问不了就需要检查SELinuxgetenforce输出Enforcing的话可以把Nginx的端口加入允许列表或者临时先setenforce 0做测试。注意setenforce 0只是临时的重启后SELinux会恢复生产环境还是建议在SELinux里配置白名单而不是直接关掉它。5.3 端口冲突与权限问题端口冲突也是高频问题。bind() to 0.0.0.0:80 failed (98: Address already in use)这行日志一出基本上就是80端口被别的东西占了。用下面的命令查看谁占用了端口netstat -tlnp | grep :80或者更新的写法ss -tlnp | grep :80如果是Apache或者其它Web服务占了80你需要在重启操作之前决定是停掉旧服务还是让Nginx换端口。千万别在生产环境直接kill进程先确认那个进程是什么再决定动作。权限相关的另一个坑是文件描述符限制。一旦接入的连接数超过系统默认的ulimit值Nginx会报Too many open files。这时候需要调整两个地方在nginx.conf里设置worker_rlimit_nofile同时修改系统的/etc/security/limits.confroot soft nofile 65535 root hard nofile 65535 nginx soft nofile 65535 nginx hard nofile 65535改完要退出重新登录终端才生效。5.4 离线环境依赖缺失的排查思路离线环境最大的麻烦就是你没法用yum install或apt-get install来现场补依赖。如果configure阶段发现缺少某个系统库你只能回有网机器上去下载对应的RPM或deb包再传进去。这就需要一套判断方法。我的实操习惯是编译Nginx之前先在有网机器上把同样版本的系统拉起来在外网环境完整跑一遍安装流程记录下它依赖的底层库。然后回到离线机器逐个检查这些库是否已存在。用ldconfig -p | grep 库名可以快速查看动态库是否在系统缓存里。缺哪个库就去有网机器下载对应的软件包。比如缺libpcre你在CentOS上下载pcre和pcre-devel两个RPM传进离线机器后执行rpm -Uvh pcre-*.rpm pcre-devel-*.rpm这里有个很关键的细节一定要连-devel包一起装。编译Nginx需要的是头文件光有运行时动态库是不够的。很多新手就是少了这一步编译时一直提示找不到头文件。如果你需要安装多个RPM包可以用yum localinstall的方式它会尝试解析本地目录里的RPM依赖yum localinstall -y /opt/rpms/*.rpm6. 个人实操体会与补充建议离线安装Nginx这件事看起来是一串命令做多了你就会发现它考验的是你对整个系统依赖关系的理解程度。我最开始做的时候也踩过不少坑比如在configure那一步漏掉了--with-http_ssl_module导致后面配HTTPS的时候发现不支持SSL只能重新编译再比如在一个国产系统上装完了才发现系统内核太老Nginx 1.24的某些特性跑不起来最后换了旧版本才稳定。我的建议是在准备离线包之前先花五分钟把目标机器的系统版本、架构、内核信息记下来再决定用哪个版本的Nginx。这五分钟省下来的时间可能比后面排查报错花的两小时还多。另外离线环境下一定要养成记录命令和参数的习惯因为没法上网查自己的笔记就是唯一的参考资料。还有一个小技巧编译之前先把configure的参数存成一个文件放在/opt目录下下次重新编译时直接复制执行不用靠记忆敲。毕竟内网机器一旦多了每台的系统环境还有些微差异有个参数备份能省太多事。最后给几个实用的小建议。第一安装完成之后用curl -I http://127.0.0.1测试一下本地访问确认有HTTP响应再告诉业务方。第二把Nginx日志做切割不然时间久了access.log会涨到几个G排查问题拖都拖不动。第三定期备份/etc/nginx/nginx.conf改配置前先cp一份带日期的备份改挂了还可以快速回滚。这几个习惯看着不起眼但在项目现场能帮你少挨很多骂。