Linux安装Nginx全流程详解:源码编译与包管理器实战指南
我接触 Linux 的第一台服务器装的就是 Nginx。从那以后差不多十年时间里不管给客户搭 Web 服务、做反向代理还是自己折腾静态博客Nginx 都是最先装的那批组件。今天这篇不聊虚的就把“linux 系统下载安装 nginx”这条主线理清楚源码编译和包管理器两种方式到底怎么选、安装时那些 configure 参数改不改、装完之后的目录结构和第一个站点怎么配、以及我这些年踩过的坑和排查思路。不管你是刚接触 Linux 的运维新人还是准备在云服务器上部署项目的开发者这篇文章都能给你一份可以直接照着抄的作业。1. 安装方案选型与准备工作1.1 源码编译和系统包管理器到底选哪个很多人第一次装 Nginx 都会纠结一件事到底是用yum install nginx或者apt install nginx直接装还是去官网下载源码包自己编译。我说一下我的选择逻辑。系统包管理器安装的优势是快、干净、依赖自动处理。CentOS 上用 yumUbuntu 上用 apt命令敲完服务脚本、默认配置、日志轮转全都给你安排好了。缺点是版本往往偏旧比如你在 CentOS 7 的默认源里装的 Nginx版本可能还停在 1.16 或者 1.18而且部分模块默认没编译进去。CentOS 官方源甚至没有 nginx 包你得先启用 EPEL 源这一步对新手来说就是第一个坑。源码编译安装的过程虽然长一点但可控性最强。你可以自己指定安装目录、选择需要的模块、使用较新的版本生产环境里定制化程度高的场景基本都会走这条路。它需要你手动装好 gcc、pcre、zlib、openssl 等依赖装完之后也没有现成的 systemd 管理脚本得自己写一个。我的建议很简单如果只是内网快速搭一个应用、为了跑通功能直接用系统包管理器省时间如果是要上生产环境、需要对版本和模块有明确要求或者公司规范里要求统一安装路径那就源码编译。两种方式下文都会给完整流程。1.2 环境和依赖准备一个都不能少不管是哪种安装方式装依赖都是第一步。源码编译对依赖的要求最严格缺失任何一个编译时都会报错。下面以 CentOS 系和 Ubuntu 系分别给出准备命令。CentOS / RHEL 系yum install -y gcc gcc-c make pcre pcre-devel zlib zlib-devel openssl openssl-develUbuntu / Debian 系apt update apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev这里重点说下每个依赖是干嘛的gcc 是编译器没有它没法把 C 源码变成可执行文件pcre 是正则表达式库Nginx 的 location 匹配、rewrite 规则都依赖它zlib 负责 gzip 压缩静态资源压缩传输靠它openssl 是 HTTPS 的基础ssl 模块、证书加载都离不开它。编译时如果缺了某个库通常缺的是xxx-develCentOS或xxx-devUbuntu这种带开发头的包而不只是运行库本身这个是新手最常忽略的。另外在进安装流程之前建议先做两个检查。一是看系统里是不是已经装过 Nginxwhich nginx nginx -v如果已经存在先想清楚是要覆盖升级还是卸载重来不要直接开始新的编译后面会出现同名文件覆盖、路径混乱的问题。二是检查 80 端口是否被占用ss -lntp | grep :80端口被 Apache 或者其他 Web 服务占用是启动失败最常见的坑提前发现能省很多排查时间。1.3 版本选择与国内镜像加速Nginx 官网提供三个版本线Mainline 主线版、Stable 稳定版、Legacy 历史版。生产环境我强烈建议选 Stable功能迭代比主线版慢但经过更长时间的测试出了问题也好搜解决方案。主线版通常带有新特性适合测试环境尝鲜不建议直接上生产。下载地址是https://nginx.org/download/文件格式一般类似nginx-1.26.2.tar.gz。国内服务器直接访问官网有时候速度不太稳定可以用国内的开源镜像站下载同名文件。下载完成后最好做一下文件校验确保压缩包完整。wget https://nginx.org/download/nginx-1.26.2.tar.gz tar -zxvf nginx-1.26.2.tar.gz cd nginx-1.26.2版本号不是越新越好我见过有人为了追新版本装了个主线版结果某个旧模块不兼容折腾半天又回退了。选一个你所在团队其他人用过的稳定版本往往比选最新版本更稳妥。2. 源码编译安装 Nginx 全流程2.1 configure 参数逐个说清楚进入解压后的源码目录第一步是执行./configure。很多第一次接触源码编译的人看到满屏的参数就懵了。其实参数就两类一类是决定功能模块的--with-xxx一类是决定路径和身份的--prefix、--user、--group。我下面给一个生产环境常用的配置你直接抄就能用./configure \ --prefix/usr/local/nginx \ --usernginx \ --groupnginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-http_gzip_static_module \ --with-stream \ --with-stream_ssl_module \ --with-pcre逐个说一下这些参数为什么重要。--prefix/usr/local/nginx是安装根目录。默认也是这个路径但显式写出来能让后续维护的人一眼知道 Nginx 装在哪里。路径一旦定下来后面升级时要保持前缀不变否则会遇到配置文件、日志、二进制文件分散在两个目录的问题非常痛苦。--usernginx和--groupnginx是让 Nginx 的 worker 进程以普通用户身份运行。默认会用 nobody但在编译前先创建一个专用的 nginx 用户权限颗粒度更细也更安全。创建命令是useradd -s /sbin/nologin -M nginx。--with-http_ssl_module必须加。不加这个后面你想配置 HTTPS、加载 SSL 证书的时候配置能写但 Nginx 会报错说不认识listen 443 ssl到时候只能重新编译加模块非常麻烦。--with-http_v2_module是 HTTP/2 支持。网站打开速度、并发能力都会受益尤其是有大量小文件的 Web 场景。注意这个模块在新版本 Nginx 里是默认开启的但老版本需要显式加上。--with-http_realip_module在做反向代理时非常关键。没有它后端应用拿到的一律是 Nginx 所在服务器的 IP有了它才能把真实客户端 IP 传过去日志分析和风控都依赖这个。--with-http_stub_status_module提供一个/nginx_status页面可以看到当前活跃连接数、请求总数等信息排障的时候特别有用。--with-stream是四层 TCP/UDP 代理模块。如果你计划用 Nginx 转发数据库端口、SSH 端口或者做 TCP 负载均衡就必须编译这个模块。--with-stream_ssl_module则是在四层代理中支持 SSL 透传或者终止。这里插一句经验不要什么模块都往上加加的模块越多编译时间越长二进制体积越大暴露在外的攻击面也越大。按需开启才是正解。2.2 make 编译与 make install以及常见报错configure 执行成功后会生成 Makefile 文件。接下来就是编译和安装make -j 4 make install-j参数是并行编译后面的数字通常是 CPU 核数的一半或者等于核数。比如四核机器用-j 4八核机器用-j 8能明显缩短编译时间。如果编译过程中报错先别慌看报错信息缺什么就补什么然后重新执行 configure 和 make。最常见的两个报错都是依赖缺失引起的the HTTP rewrite module requires the PCRE library说明没装 pcre-devel补上后重新 configure。the HTTP gzip module requires the zlib library说明没装 zlib-devel同样补包。还有一种情况是 openssl 版本过低或者路径找不到checking for OpenSSL library ... not found。这时候先确认openssl version能正常输出再检查openssl-devel是否安装。CentOS 7 上尤其容易遇到这种问题。安装完成后Nginx 二进制默认在/usr/local/nginx/sbin/nginx。运行nginx -V注意是大写 V可以看到编译时的所有参数和版本号这是后续排障和升级时最重要的信息之一。验证启动/usr/local/nginx/sbin/nginx -t /usr/local/nginx/sbin/nginxnginx -t是测试配置文件的语法输出syntax is ok和test is successful就说明没问题。启动后访问服务器 IP看到 Welcome to nginx 页面就成功了。2.3 写一个 systemd 管理脚本源码编译安装的 Nginx 默认没有 systemd 服务文件导致你没法用systemctl start nginx来管理杀进程和开机自启都得手动搞。我建议装完立刻补上这个文件。新建/etc/systemd/system/nginx.service[Unit] Descriptionnginx - high performance web server Documentationhttps://nginx.org/en/docs/ Afternetwork-online.target remote-fs.target nss-lookup.target Wantsnetwork-online.target [Service] Typeforking PIDFile/usr/local/nginx/logs/nginx.pid ExecStartPre/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf ExecStart/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload/usr/local/nginx/sbin/nginx -s reload ExecStop/usr/local/nginx/sbin/nginx -s quit PrivateTmptrue [Install] WantedBymulti-user.target保存后执行systemctl daemon-reload systemctl enable nginx systemctl start nginx systemctl status nginxTypeforking对应 Nginx 启动时 master 进程 fork 出 worker 进程的行为。PIDFile指向的 pid 文件要真实存在路径别写错否则 systemd 会认为启动失败。这个脚本是我经过多台服务器验证过的直接拿去用没问题。3. 用系统包管理器安装的差异化流程3.1 CentOS 与 Ubuntu 的包管理器安装如果你决定用包管理器流程比源码编译快得多但不同发行版的细节差异值得单独说一下。CentOS / RHEL 7/8/9 的官方源里默认没有 nginx需要先安装 EPEL 源yum install -y epel-release yum install -y nginx装完之后配置文件的分布是主配置在/etc/nginx/nginx.conf子配置默认加载/etc/nginx/conf.d/*.conf网站的根目录在/usr/share/nginx/html日志在/var/log/nginx/。启动方式是用 systemd。Ubuntu / Debian 系的安装更直接官方源里就有apt update apt install -y nginxUbuntu 安装完会自动启动服务并设置开机自启。它的配置结构多了一层/etc/nginx/sites-available和/etc/nginx/sites-enabled允许你像管理多个站点一样管理虚拟主机。如果你不熟悉这种结构新手最容易蒙圈的就是明明写好了配置却不生效因为没在sites-enabled里建软链接。验证包管理器安装结果nginx -v systemctl status nginx curl -I http://127.0.0.1看到 HTTP/1.1 200 OK 的返回头基本就确认服务正常了。3.2 两种方式的路径差异与选型建议包管理器安装和源码编译安装的目录结构差异很大我用一张表把它们的关键路径摆出来方便对照项目包管理器安装yum/apt源码编译安装二进制文件/usr/sbin/nginx/usr/local/nginx/sbin/nginx主配置/etc/nginx/nginx.conf/usr/local/nginx/conf/nginx.conf子配置目录/etc/nginx/conf.d/需自行创建 conf.d默认站点目录/usr/share/nginx/html/usr/local/nginx/html日志目录/var/log/nginx//usr/local/nginx/logs/进程管理systemctl 直接可用需自建 service 文件升级方式yum 或 apt 更新重新编译并平滑升级从这张表能看出来包管理器把文件分散到系统各个标准目录符合 FHS 规范和 selinux、logrotate 这些系统组件联动方便。源码编译则把所有东西集中在/usr/local/nginx一个目录下多实例部署、整体迁移、按团队规范管理都更方便。我个人在生产环境里更倾向于源码编译安装。原因有三个一是版本可控不会因为一次yum update把 Nginx 意外升级掉二是模块可控编译了什么模块一目了然三是路径统一团队成员换了一拨又一拨但nginx -V一看就能了解这台机器的 Nginx 是怎么来的。当然如果只是临时搭个环境玩一下包管理器完全够用没必要为了一个测试服务折腾编译。4. 安装后的核心配置与首个站点4.1 Nginx 目录结构与关键文件解读装完之后先别急着写配置把目录结构摸清楚再动手效率会高得多。源码编译安装的目录结构大概是这样的/usr/local/nginx/ ├── conf/ │ ├── nginx.conf │ ├── mime.types │ └── fastcgi_params ├── html/ │ ├── index.html │ └── 50x.html ├── logs/ │ ├── access.log │ ├── error.log │ └── nginx.pid └── sbin/ └── nginxconf/nginx.conf是主配置几乎所有的行为都由它控制。mime.types定义了文件后缀和 Content-Type 的映射关系默认不用动。html/是默认站点目录刚装完可以通过访问服务器 IP 看到官方欢迎页。logs/下三个文件很重要access.log 记录所有访问日志error.log 记录错误信息nginx.pid 存 master 进程的 PID后面平滑升级和平滑退出都要用到这个 pid 文件。包管理器安装的目录虽然分散但结构逻辑一致主配置里同样会有http、server、location这些层级块。理解一个另一个自然就通了。建议安装完成后做一次备份把原始的nginx.conf复制一份存为nginx.conf.bak。别小看这个动作在你把配置改得面目全非又不知道怎么恢复的时候这个备份就是救命稻草。4.2 配置第一台虚拟主机安装并确认服务能跑之后就可以配置第一台虚拟主机了。我在conf.d下创建一个站点配置文件内容如下server { listen 80; server_name example.com www.example.com; root /var/www/example; index index.html index.htm; access_log /var/log/nginx/example.access.log main; error_log /var/log/nginx/example.error.log warn; location / { try_files $uri $uri/ 404; } }逐行解释一下。listen 80是监听端口如果你的机器上已经有别的 Web 服务占用了 80这里会冲突。server_name是域名匹配的关键多个域名用空格分隔。root指定站点文件所在目录实际访问时映射到/var/www/example下的对应文件。index是默认首页文件按顺序匹配。location /匹配所有路径try_files $uri $uri/ 404的意思是优先找真实文件找不到就找目录再找不到直接返回 404。写完配置之后一定要测试语法nginx -t nginx -s reloadnginx -t只做语法检查不实际加载reload是平滑重载不会中断现有连接。每次改配置都要走这两步我已经养成肌肉记忆了。如果直接改完就重启进程万一配置有误会导致服务挂掉在线用户全部断连。4.3 worker 进程与基础性能参数设置一个刚装好的 Nginx默认配置是单 worker 进程跑在 nobody 用户下。对于真实业务来说这个状态肯定不行。我在配置 HTTP 块里通常会调整这么几个参数。user nginx; worker_processes auto; worker_rlimit_nofile 65535; events { worker_connections 1024; } http { sendfile on; tcp_nopush on; keepalive_timeout 65; gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; }user nginx必须和编译时--usernginx对应如果是包管理器安装默认通常也是 nginx。worker_processes auto让 Nginx 自动根据 CPU 核心数创建 worker 进程。worker_rlimit_nofile是每个 worker 能打开的文件描述符上限高并发下不够用会报too many open files错误。worker_connections 1024是单 worker 的最大连接数一般够用。sendfile on开启高效文件传输静态文件分发性能提升明显。gzip on开启压缩配gzip_types指定哪些类型要压缩能显著减小页面体积。这些都是基础参数真正到业务场景还得按需调。但把这些默认值调好至少能保证 Nginx 在大多数场景下不会成为瓶颈。5. 常见问题排查与运维技巧实录5.1 启动失败八成是端口被占用或权限问题先排查端口。最经典的情况是端口被占用报错信息类似bind() to 0.0.0.0:80 failed (98: Address already in use)。执行ss -lntp | grep :80 lsof -i:80找到占用进程要么停掉旧服务要么把 Nginx 的 listen 端口换掉。在云服务器上还要确认安全组规则是否放行了对应端口否则外部访问不了但本机 curl 却正常这种情况和安全组有关。还有一个经常被忽略的问题nginx 用户对站点目录没有读权限。比如你手动创建的网站目录归属 root权限是 700Nginx worker 进程跑在 nginx 用户下就会报Permission denied。排查时可以看 error.log里面会有具体的路径和权限提示。解决方法很简单把站点目录的属主改成 nginx或者加chmod -R 755。5.2 nginx -t 通过但网站 404多半是 root 路径写错了这个坑我踩过不止一次。配置文件语法检查完全通过reload 也成功但访问网站就是 404。查日志发现在 Nginx 的日志里只记录了访问请求没有后端报错。这时候九成是root或alias路径配置有问题。一个是路径本身不存在比如你写的是/var/www/example但实际目录只建到/var/www/example/html写成/var/www/example自然什么都找不到。另一个是 Nginx 默认用户对路径没有执行权限能读文件但进入不了目录也会表现为 404。排查方法很直接ls -ld /var/www/example sudo -u nginx ls /var/www/example后者模拟 nginx 用户去访问目录如果输出权限不足就调整目录权限和属主。再补充一个点如果你用了alias做目录映射后面必须精确匹配。比如location /static/ { alias /data/static/; }访问/static/xxx时会映射到/data/static/xxx如果 alias 后面少了结尾斜杠路径拼接就会出错出现一堆奇怪的 404。这类问题不是语法错是语义错所以nginx -t根本查不出来。5.3 如何平滑升级 Nginx 版本而不中断服务生产环境升级 Nginx不能直接把进程杀掉再启动最简单可靠的办法是利用 Nginx 的平滑升级机制。升级流程说白了就是让新版本二进制替换旧版本通过信号量控制新旧进程切换整个过程连接不断开。大致步骤是这样的下载并编译新版本 Nginx编译参数和旧版本保持一致但注意 prefix 一定相同。备份旧二进制mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old把编译好的新二进制复制到原位置。对旧的 master 进程发USR2信号让它启动新的 master 进程kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid)此时新旧进程并行旧 worker 还在处理请求。发WINCH信号给旧 master让它逐步关闭旧 worker。确认新进程正常工作后再发QUIT信号让旧 master 退出kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid)执行完流程之后用ps -ef | grep nginx确认只剩新的 master 和 worker 进程。平滑升级的好处是用户无感知不会出现在线掉线。我第一次做平滑升级的时候内心还有点慌但流程测过几次之后再遇到版本迭代就很淡定了。5.4 SSL 证书替换不生效怎么排查热词榜单里有“nginx 替换 ssl 证书不生效”这个坑几乎每个人都会遇到。我遇到过四种典型情况第一种是证书链不完整。下载证书时如果只拿到一张证书文件没有把中间证书也配上Nginx 启动没问题但浏览器会提示证书无效。解决办法是检查证书文件内容把中间证书和域名证书按顺序拼接成一个证书链文件。Nginx 里ssl_certificate指向的文件应该包含完整链不只是域名证书本身。第二种是改错了 server 块。如果你的 Nginx 配置里多个 server 块都监听了 443而且server_name匹配规则又比较模糊比如存在default_server那么新证书可能根本没用在你真正对外提供服务的那个 server 块上。这个一定要通过实际访问来验证不要只看你觉得在改的那个文件。第三种是 CDN 缓存。如果站点前面挂了 CDNCDN 节点会缓存旧的证书链。这种情况下源站 Nginx 已经换好了但客户端访问时经过的 CDN 节点还在用旧证书。处理方式是先确认源站证书没问题再在 CDN 控制台刷新证书缓存然后就正常了。第四种是浏览器缓存。替换证书后浏览器端可能还保留着旧的证书信息。用无痕模式访问就能确认是不是这个原因。重点是一套有效的验证命令避免全靠猜# 查看实际连接拿到的证书 openssl s_client -connect example.com:443 -servername example.com -showcerts /dev/null # 查看证书有效期开始和结束时间 openssl x509 -in /usr/local/nginx/conf/ssl/example.com.pem -noout -dates # 查看证书指纹对比是否是最新版本 openssl x509 -in /usr/local/nginx/conf/ssl/example.com.pem -noout -fingerprint第一条命令输出的是浏览器实际建立 HTTPS 连接时收到的证书如果这个证书还是旧的说明问题出在 Nginx 或中间链路如果这个证书已经是新的问题就在客户端缓存。记得有一次用户说证书不生效我远程看了半天 Nginx 配置都没发现问题最后发现他改完配置之后根本没有执行nginx -s reload新证书一直没被加载。所以替换证书之后第一步永远是nginx -t nginx -s reload然后才谈得上排查其他环节。我个人在实际操作中的体会是安装 Nginx 这件事真正的难度不在make那一下而在于你对这台服务器后面要怎么用的推演。很多时候一个看似复杂的故障最后查出来的原因只是路径写错、权限不足、改完配置没 reload 而已。所以我建议每次装完 Nginx先不改任何业务配置用默认页裸跑一遍确认进程、端口、日志都正常再做自定义配置。这样出了问题你能清楚是哪一步引入的排查路径会短得多。最后再分享一个小习惯所有自定义配置都放到单独的conf.d子文件里每个虚拟主机一个文件命名按域名来。这样后续维护时看到文件名就知道这个 Nginx 上跑了哪些站点比全部堆在主配置文件里要清爽得多。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →