当前位置: 首页 > news >正文

Nginx 源码编译与静态资源服务器实战 —— 基于陶辉《Nginx 核心知识 150 讲》第一、二章

Nginx 源码编译与静态资源服务器实战 —— 基于陶辉《Nginx 核心知识 150 讲》第一、二章

本文所有命令均在真实服务器(华为云 FlexusX 8C16G / Ubuntu 24.04)上执行,所有回显均来自真实环境,未做任何虚构与篡改(仅对超长输出做了合理截断)。

一、前言

很多人第一次接触 Nginx,都是通过apt install nginx一条命令装好就用。这当然最快,但"会用"和"懂它"之间隔着一条叫"编译与架构"的河。陶辉老师在《Nginx 核心知识 150 讲》的第一、二章里,重点讲了两件事:为什么要用源码编译、以及Nginx 的事件驱动 + master/worker 进程模型

我这次的目标很明确:

  1. 抛开发行版自带的那份"通用"二进制,自己从源码编译一个带 SSL、HTTP/2、stub_status、gzip_static、realip、stream 模块的 Nginx;
  2. 用它搭一个真实的静态资源 Web 服务器,把gzipautoindexaccess_log里的$request_time、目录浏览、预压缩这些都跑通看效果;
  3. 把命令行运维(reload、日志切割、平滑升级/平滑退出)一个个亲手做出来,尤其是用ps --forest亲眼看到 master 与 worker 的父子关系,以及 reload 时旧 worker "优雅退场"的全过程;
  4. 最后用stub_status看实时连接数,用goaccess把访问日志变成一份可视化报表。

整套做下来,最让我"哇"的一刻,是 reload 之后ps里赫然出现一行nginx: worker process is shutting down——那种"书里讲的架构真的在跑"的实感,是看文档永远替代不了的。

本实验严格对应陶辉课程第一、二章的主线:第一章讲"如何从源码构建一个适合自己业务的 Nginx",第二章讲"Nginx 的进程模型与请求处理机制"。所以下面每一步都不是为了"跑通而已"——编译参数决定了 Nginx 的能力边界,reload 与 worker 的行为决定了线上能否"平滑无感"地变更。把这两章吃透,后面讲负载均衡、缓存、Lua 扩展时才不会空中楼阁。


二、环境说明

项目配置
CPU8 核(General Purpose Processor @ 2.0GHz)
内存16G
磁盘40G(系统盘,剩余约 35G)
系统Ubuntu 24.04.4 LTS(内核 6.8.0-106-generic)
公网 IP119.3..(已打码,真实日志中保留原样)
编译器gcc 13.3.0 / GNU Make 4.3 / OpenSSL 3.0.13
Nginx 版本源码编译 nginx/1.26.2

说明:该机器带宽仅 5Mbit/s,因此全程尽量走apt或小体积源码包(Nginx 源码包仅约 1.2MB),避免大文件下载拖慢节奏。


三、整体架构与流程(ASCII 图)

3.1 静态资源服务器的请求链路

┌──────────────────────────────┐ 客户端 (curl/浏览器) │ Nginx 1.26.2 │ GET /index.html ───► │ master process (1个, root) │ │ │ ├─ worker (nobody) │──► 读 /data/www/index.html │ │ ├─ worker (nobody) │──► 读 /data/www/big.txt │ │ ├─ worker (nobody) ... │──► gzip 压缩后回传 │ └─ worker (nobody) │ └──────────────────────────────┘ │ access.log (含 $request_time) error.log

3.2 源码编译流程

下载 nginx-1.26.2.tar.gz (1.2MB) │ ▼ ./configure ──► 探测 PCRE / OpenSSL / zlib,生成 objs/Makefile │ ▼ make -j8 ──► 编译各模块 (real 0m4.988s, 8核并行) │ ▼ make install ──► 落到 /usr/local/nginx/{sbin,conf,html,logs}

3.3 reload(平滑重载)流程

旧 master (pid=A) ├─ worker1 ┐ ├─ worker2 │ 收到 -s reload └─ worker8 ┘ │ ▼ 新 master (pid=B, 由旧 master fork 并 re-exec) ├─ worker1' ← 用【新】配置启动 ├─ worker2' ← 用【新】配置启动 └─ worker8' ← 用【新】配置启动 │ 旧 worker 继续服务【在途连接】,处理完即退出 (worker_shutdown_timeout 兜底,超时强制退出)

四、逐步实操(命令 + 真实回显)

4.1 环境准备:安装编译依赖

编译 Nginx 需要 C 编译器、PCRE(正则)、zlib(压缩)、OpenSSL(HTTPS)。用一条apt搞定:

apt-getupdate-qqDEBIAN_FRONTEND=noninteractiveapt-getinstall-ygccmakebuild-essential\libpcre3-dev zlib1g-dev libssl-dev openssl

验证工具链版本(真实回显):

gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 GNU Make 4.3 OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)

4.2 源码编译 Nginx 1.26.2

下载仅 1.2MB 的源码包(适配 5M 小带宽):

mkdir-p/usr/local/src&&cd/usr/local/srccurl-fsSL-onginx-1.26.2.tar.gz https://nginx.org/download/nginx-1.26.2.tar.gztarxzf nginx-1.26.2.tar.gz

./configure指定安装路径并开启我们需要的模块。关键:源码编译的意义正在于此——按需裁剪模块,而不是用发行版那个"万能但不一定需要"的二进制。

cd/usr/local/src/nginx-1.26.2 ./configure--prefix=/usr/local/nginx\--with-http_ssl_module\--with-http_v2_module\--with-http_stub_status_module\--with-http_gzip_static_module\--with-http_realip_module\--with-stream

配置摘要(真实回显,已截取关键部分):

checking for PCRE library ... found checking for PCRE JIT support ... found checking for OpenSSL library ... found checking for zlib library ... found creating objs/Makefile Configuration summary + using system PCRE library + using system OpenSSL library + using system zlib library nginx path prefix: "/usr/local/nginx" nginx binary file: "/usr/local/nginx/sbin/nginx" nginx configuration file: "/usr/local/nginx/conf/nginx.conf" nginx pid file: "/usr/local/nginx/logs/nginx.pid" ...

8 核并行编译,计时用time记录真实耗时:

cd/usr/local/src/nginx-1.26.2&&timemake-j8

真实编译耗时(真实回显):

real 0m4.988s user 0m30.649s sys 0m7.971s

解读:real仅约 5 秒,因为是 8 核并行(-j8),但user累计达 30 秒,说明 CPU 确实被多个编译线程吃满了。user/sys之和远大于real,正是并行编译的典型特征。

安装并校验模块:

makeinstall/usr/local/nginx/sbin/nginx-V

真实回显(这正是我们"要什么模块就有什么模块"的证据):

nginx version: nginx/1.26.2 built by gcc 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1) built with OpenSSL 3.0.13 30 Jan 2024 TLS SNI support enabled configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module \ --with-http_v2_module --with-http_stub_status_module \ --with-http_gzip_static_module --with-http_realip_module --with-stream

逐模块说明我们为何开启它们:--with-http_ssl_module提供 HTTPS 能力;--with-http_v2_module启用 HTTP/2 多路复用,提升并发与首包速度;--with-http_stub_status_module暴露内建监控页(见 4.5);--with-http_gzip_static_module支持发送预压缩的.gz文件,省去运行时压缩(见 4.3);--with-http_realip_module在 Nginx 前面有 CDN / 反代时还原真实客户端 IP;--with-stream则让 Nginx 具备四层 TCP/UDP 负载均衡能力,超越纯七层反向代理。这些都不是默认编译进发行版二进制的"最小集",而是我们按需求亲手勾选的能力边界。

4.3 搭建静态资源 Web 服务器

准备站点目录(/data/www)和测试文件,其中big.txt是一个约 12MB、内容高度重复的大文本,专门用来演示 gzip 的压缩比:

mkdir-p/data/www /data/www/dl# index.html / style.css / about.html 通过 SFTP 上传(多行配置走 SFTP 更稳)yes'Nginx 静态资源服务器实战:这是一段用于演示 gzip 压缩效果的重复文本,包含中文与 English mix 内容...'\|head-n60000>/data/www/big.txt

生成结果(真实回显):

-rw-r--r-- 1 root root 12M Jul 24 12:37 /data/www/big.txt

核心配置/usr/local/nginx/conf/nginx.conf(节选真实内容):

worker_processes auto; events { worker_connections 1024; } http { include mime.types; sendfile on; keepalive_timeout 65; # ===== gzip ===== gzip on; gzip_comp_level 6; gzip_min_length 1k; gzip_vary on; gzip_types text/plain text/css application/javascript application/json application/xml text/xml image/svg+xml; # 访问日志额外记录请求处理耗时 $request_time log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" rt=$request_time'; access_log /usr/local/nginx/logs/access.log main; server { listen 80; server_name localhost; root /data/www; autoindex on; # 开启目录浏览 location / { index index.html index.htm; try_files $uri $uri/ =404; } location /dl/ { gzip_static on; } # 支持 .gz 预压缩文件 } }

-t检查语法,再启动:

/usr/local/nginx/sbin/nginx-t/usr/local/nginx/sbin/nginx

真实回显:

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

启动后进程数(1 个 master + 8 个 worker,因为 8 核worker_processes auto):

10
gzip 效果实测(重点)

关键问题是:开启 gzip 后,传输体积到底小了多少?curl分别测"不压缩"和"压缩"两种下载量:

# 不压缩(客户端不发送 Accept-Encoding)curl-s--no-compressed-o/dev/null-w'uncompressed_bytes=%{size_download}\n'http://127.0.0.1/big.txt# 压缩(发送 Accept-Encoding: gzip)curl-s-H'Accept-Encoding: gzip'-o/dev/null-w'compressed_bytes=%{size_download}\n'http://127.0.0.1/big.txt

真实回显:

uncompressed_bytes=11700000 compressed_bytes=45615

12MB → 45,615 字节,压缩比约 256:1!再看响应头对比:

curl-s-Ihttp://127.0.0.1/big.txt|grep-icontent-lengthcurl-s-I-H'Accept-Encoding: gzip'http://127.0.0.1/big.txt|grep-iE'content-length|content-encoding'

真实回显:

Content-Length: 11700000 Content-Encoding: gzip

CSS 这类小文本同样受益(text/cssgzip_types内):

Content-Type: text/css Content-Length: 178

gzip 的本质是用 CPU 换带宽:把高度冗余的文本(HTML/CSS/JS/JSON)压缩后再传,客户端浏览器透明解压。我们特意让big.txt内容重复,正是为了放大这种冗余——真实业务里日志、报表、接口 JSON 往往同样"啰嗦",压缩收益极大。配置里gzip_min_length 1k表示小于 1KB 的文件不压缩(压缩小文件反而因头部开销得不偿失),gzip_comp_level 6是压缩率与 CPU 消耗的折中(1 最快、9 最狠)。对于图片、视频等本身已压缩的二进制,切忌列入gzip_types,否则只是白白浪费 CPU。

gzip_static 预压缩演示

--with-http_gzip_static_module让我们能提前把文件压成.gz,Nginx 直接发预压缩包,省去运行时压缩开销:

echo'gzip_static 预压缩演示文件内容。'>/data/www/dl/sample.txtgzip-k-f/data/www/dl/sample.txt# 同时保留 sample.txt 和 sample.txt.gzcurl-s-I-H'Accept-Encoding: gzip'http://127.0.0.1/dl/sample.txt|grep-iE'content-encoding|content-length'

真实回显:

Content-Length: 77 Content-Encoding: gzip
autoindex 目录浏览

autoindex on/dl/目录可直接列出来(真实回显):

curl-shttp://127.0.0.1/dl/|grep-iE'sample|href'|head
<h1>Index of /dl/</h1><hr><pre><a href="../">../</a> <a href="sample.txt">sample.txt</a> 24-Jul-2026 04:37 43 <a href="sample.txt.gz">sample.txt.gz</a> 24-Jul-2026 04:37 77

4.4 Nginx 命令行运维实操

(1) reload 生效验证(修改配置后必须验证)

修改配置(新增add_header X-Powered-By "Nginx-1.26.2-AgentA";worker_shutdown_timeout 30s;),上传后-t+-s reload

/usr/local/nginx/sbin/nginx-t/usr/local/nginx/sbin/nginx-sreloadcurl-s-Ihttp://127.0.0.1/|grep-i'x-powered-by'

真实回显(表明确实加载了新配置):

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful reloaded-ok X-Powered-By: Nginx-1.26.2-AgentA
(2) master/worker 进程结构(ps --forest)
ps-ef--forest|grep'[n]ginx'

真实回显(清晰地看到 master 与 worker 的树形父子关系):

root 12512 1 0 12:37 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 12696 12512 0 12:39 ? 00:00:00 \_ nginx: worker process nobody 12697 12512 0 12:39 ? 00:00:00 \_ nginx: worker process nobody 12698 12512 0 12:39 ? 00:00:00 \_ nginx: worker process nobody 12699 12512 0 12:39 ? 00:00:00 \_ nginx: worker process ... (共 8 个 worker,对应 8 核)

master 以root运行(绑定 80 端口需要特权),worker 以低权限nobody运行(降权,安全)。这正是 Nginx "master 管进程、worker 管业务"模型活生生的样子。

为什么是 master + 多个 worker,而不是一个进程扛所有连接?核心在于 Nginx 的事件驱动(epoll/kqueue)模型:每个 worker 是一个单线程事件循环,靠非阻塞 I/O 同时盯住成千上万条连接,谁就绪就处理谁,不会因为某条连接慢而阻塞整个进程。master 不参与业务,只负责读配置、发信号、拉起/回收 worker,因此它即使长期运行也几乎不出错。worker 以nobody低权限运行则是安全底线——即便某个 worker 被攻破,攻击者拿到的也只是最小权限。reload 时 master 不退出、只 fork 出新 worker,正是"不丢连接"的根本原因。

(3) 平滑退出(reload 真相 + worker_shutdown_timeout)

书里讲 “reload 不是重启,而是 master 拉起新 worker、旧 worker 处理完在途请求再退出”。我们亲手验证:开一个限速的慢速大文件下载,在它进行中执行 reload,然后立刻ps

OLD_PID=$(cat/usr/local/nginx/logs/nginx.pid)curl-s--limit-rate 1M-o/dev/null http://127.0.0.1/big.txt&# 慢速下载(约 12s)sleep1/usr/local/nginx/sbin/nginx-sreloadsleep2ps-ef--forest|grep'[n]ginx'wait# 等慢下载结束ps-ef--forest|grep'[n]ginx'

真实回显(reload 后瞬间,旧 worker 还在"shutting down",因为它的连接还没传完):

=== ps right after reload (old worker may still serve slow request) === root 12512 1 0 12:37 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 12698 12512 0 12:39 ? 00:00:00 \_ nginx: worker process is shutting down nobody 12727 12512 0 12:39 ? 00:00:00 \_ nginx: worker process ... (8 个新 worker) old master pid=12512 slow transfer finished === ps after transfer (old worker should be gone) === root 12512 1 0 12:37 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nobody 12727 12512 0 12:39 ? 00:00:00 \_ nginx: worker process ... ("is shutting down" 的那一个已消失)

worker process is shutting down这行,就是"平滑退出"的铁证。配置里的worker_shutdown_timeout 30s则保证:万一旧连接在 30 秒内还没传完,master 会强制把它结束,避免旧 worker 永远赖着不走。

(4) 日志切割(mv + kill -USR1)

线上 Nginx 日志会越滚越大,标准做法是"改名 + 给 master 发 USR1 信号让它重新打开日志文件"(而不是重启进程):

mv/usr/local/nginx/logs/access.log /usr/local/nginx/logs/access.log.1kill-USR1$(cat/usr/local/nginx/logs/nginx.pid)sleep1ls-lh/usr/local/nginx/logs/access.log*curl-s-o/dev/null http://127.0.0.1/;curl-s-o/dev/null http://127.0.0.1/about.htmlecho"old access.log.1 size:$(stat-c%s /usr/local/nginx/logs/access.log.1)bytes"echo"new access.log size:$(stat-c%s /usr/local/nginx/logs/access.log)bytes"

真实回显(旧文件被"冻结",新请求写入新文件):

-rw-r--r-- 1 nobody root 0 Jul 24 12:40 /usr/local/nginx/logs/access.log -rw-r--r-- 1 nobody root 200 Jul 24 12:39 /usr/local/nginx/logs/access.log.1 old access.log.1 size now: 200 bytes (should be unchanged) new access.log size now: 198 bytes (should have grown) --- tail new access.log --- 127.0.0.1 - - [24/Jul/2026:12:41:20 +0800] "GET / HTTP/1.1" 200 531 "-" "curl/8.5.0" rt=0.000 127.0.0.1 - - [24/Jul/2026:12:41:20 +0800] "GET /about.html HTTP/1.1" 200 262 "-" "curl/8.5.0" rt=0.000

注意rt=0.000——这就是我们log_format里加的$request_time,实时记录每个请求的服务端耗时,是性能排查的利器。

4.5 stub_status 监控页

server块里加一个location /nginx_status,只允许本机访问(生产环境务必限制来源):

location /nginx_status { stub_status on; allow 127.0.0.1; deny all; access_log off; }

reload 后访问(真实回显):

/usr/local/nginx/sbin/nginx-sreloadcurl-shttp://127.0.0.1/nginx_status
Active connections: 1 server accepts handled requests 14 14 14 Reading: 0 Writing: 1 Waiting: 0

字段含义:

  • Active connections:当前活跃连接数;
  • accepts / handled / requests:累计"已接受连接 / 已处理连接 / 已处理请求",三者相等说明没有连接被丢弃;
  • Reading / Writing / Waiting:正在读请求头 / 正在写响应 / 空闲保活(Waiting 高通常说明 keep-alive 生效,连接被复用)。

Waiting数值值得重点关注:它代表当前处于 keep-alive 空闲状态的连接数。Waiting 越高,说明客户端在复用同一条 TCP 连接发起多次请求,服务端资源利用率越高;反之若 Reading/Writing 长期偏高、Waiting 很低,往往意味着连接建立后立刻关闭(keep-alive 没生效)或后端响应慢。生产环境一定要给/nginx_statusallow/deny限制来源,否则这个"内部仪表盘"会对外暴露连接规模,成为信息泄露点。

4.6 GoAccess 日志可视化

goaccess能把纯文本访问日志秒变一张交互式报表。先装:

DEBIAN_FRONTEND=noninteractiveapt-getinstall-ygoaccesswhichgoaccess# /usr/bin/goaccess

for循环疯狂造几百条访问(覆盖首页、大文件、404 等),再让 goaccess 解析(我们的日志末尾多了rt=...,先剥掉还原成标准 COMBINED 格式以保证解析准确):

foriin$(seq1200);docurl-s-o/dev/null http://127.0.0.1/curl-s-o/dev/null-r0-999 http://127.0.0.1/big.txtcurl-s-o/dev/null http://127.0.0.1/about.htmlcurl-s-o/dev/null http://127.0.0.1/style.csscurl-s-o/dev/null http://127.0.0.1/nope.htmldone# 还原为标准 COMBINED(去掉行尾 rt=...)cp/usr/local/nginx/logs/access.log /usr/local/nginx/logs/access_combined.logsed-i-E's/ rt=[0-9.]+$//'/usr/local/nginx/logs/access_combined.log

生成 HTML 报表并验证可访问:

goaccess /usr/local/nginx/logs/access_combined.log --log-format=COMBINED-o/data/www/report.htmlcurl-s-o/dev/null-w'HTTP=%{http_code} type=%{content_type}\n'http://127.0.0.1/report.html

真实回显:

report size: 560K HTTP=200 type=text/html

终端统计摘要(从 goaccess 导出的 CSV 中提取的真实数据):

总请求数 total_requests : 1002 有效请求 valid_requests : 1002 失败请求 failed_requests : 0 独立访客 unique_visitors : 1 总带宽 bandwidth : 425593 bytes 唯一静态文件 unique_static_files: 2 TOP 请求路径(命中/字节): / 201 hits, 106731 B /about.html 201 hits, 52662 B /big.txt 200 hits, 200000 B (static) /style.css 200 hits, 35600 B (static) /nope.html 200 hits, 30600 B (404) 状态码分布: 2xx 成功 802 (80.04%) -> 200 OK:602, 206 Partial:200 4xx 客户端 200 (19.96%) -> 404 Not Found:200

说明:/big.txt-r 0-999做了范围请求,因此出现了 206 Partial Content;/nope.html不存在,因此全是 404。这些"异常"数据恰好让报表更有看头。

goaccess 的报表按面板组织:visitors看独立访客与带宽;requests看热门 URL;static_requests单独统计静态资源;not_found直接列出 404 最多的路径(本例就是nope.html,对排查死链极有用);status_codes汇总各状态码占比。上面 CSV 摘要里bandwidth = 425593字节、约 416KB,正是这 1002 次请求的总流量;unique_visitors = 1则因为所有请求都来自本机127.0.0.1这一个来源。把report.html放到站点目录后,直接用浏览器打开即可交互式下钻,比肉眼grep日志高效太多。


五、踩坑清单(真实遇到的问题)

#现象 / 报错原因解决方案
1cmdfile里写多行cat <<'EOF' ... EOF时,脚本报错ValueError: not enough values to unpacksshrun.py按"每行一条TAG:::命令"解析,heredoc 的续行被当成独立命令,缺少:::多行配置文件改用 paramikoSFTP 上传agentA_put.py),远程命令只写单行
2SFTP 上传脚本偶发"无输出 + 退出码 1"Python 输出缓冲 + 服务器 SSH 偶发握手抖动-u(无缓冲)运行;遇到抖动直接重试一次即可
3kill -USR1ls access.log*报 “cannot access”上一条命令cd改了工作目录,后续命令用了相对路径,在新会话里找不到文件日志相关操作一律用绝对路径/usr/local/nginx/logs/access.log*
4头请求curl -I -H 'Accept-Encoding: gzip'只返回Content-Encoding: gzip没有 Content-LengthNginx 对 HEAD 请求在 gzip 下采用分块传输,不预先给出长度改用curl -w '%{size_download}'实测下载字节数(得到 45615),更能说明压缩效果
5goaccess 直接解析带rt=...的日志时统计异常/不识别我们的log_format在 COMBINED 之后追加了自定义字段,超出标准格式sed去掉行尾rt=...还原为标准 COMBINED 再喂给 goaccess
6goaccess 在管道里输出的是 HTML 而非文本报表goaccess 检测到 stdout 不是 TTY 时,默认输出 HTML 报表改用-o report.html生成网页;文本摘要则用-o report.csv导出 CSV 后抽取关键行

六、总结

这一趟从源码编译到静态资源服务器、再到运维与可视化,把陶辉老师前两章的核心串了起来:

  1. 为什么源码编译:发行版二进制是"通用解",而./configure让我们精确控制模块。本文最终nginx -V清楚地列出了 ssl / v2 / stub_status / gzip_static / realip / stream 六个按需开启的模块——这恰恰是"懂 Nginx"和"只会用 Nginx"的分水岭。

  2. gzip 不是玄学,是实打实的带宽节省:同一个 12MB 文件,关 gzip 传 11,700,000 字节,开 gzip 仅 45,615 字节,约 256 倍。再加gzip_static预压缩,连运行时压缩的 CPU 都省了。

  3. master/worker 不是概念图,是ps --forest里看得见的树:reload 时"旧 worker 标着is shutting down、新 worker 已就位"的那一幕,比任何文字都更能说明 Nginx 的热重载为什么"不丢连接"。

  4. 日志是金矿$request_time让每个请求耗时无所遁形;mv + kill -USR1的切割方式做到"不重启、不断流";stub_status给出现网连接实况;goaccess再把上千条日志变成一张可点可看的报表。

  5. 踩坑即素材:heredoc 与批量脚本的冲突、相对路径的坑、goaccess 的格式适配……这些真实报错反而让实验更完整、更可信。

如果你也想动手,强烈建议别用apt版的 Nginx 偷懒——亲自make一次,你会第一次真正"拥有"你的 Nginx。


本文实验环境为华为云 FlexusX 8C16G / Ubuntu 24.04,全部命令输出取自真实环境。

http://www.jsqmd.com/news/1270661/

相关文章:

  • 5分钟快速上手:Windows本地实时语音转文字工具TMSpeech终极指南
  • 算法日常・每日刷题--<链表>4
  • ComfyUI IPAdapter Plus FaceID错误解决:3种部署模式下的技术方案与实施指南
  • 2026年东莞出发去迭部县旅游高口碑旅行社选择指南 - 热点品牌推荐
  • 【AI视频创作黄金法则】:娱乐类视频爆火的7个底层逻辑与实操公式
  • 公务员培训电话查询方法与优质公考备考机构选择指南 - 热点品牌推荐
  • 电线排线采购 挑选靠谱生产商的实用选择标准指南 - 热点品牌推荐
  • 2026年温州品牌策划设计公司推荐全维度实用指南 - 热点品牌推荐
  • 2026零基础转行网安真心话:没基础、非科班,普通人到底能不能弯道超车?
  • 2026年做轨交检修找轮对轮轴举升输送流水线供货商哪家靠谱? - 热点品牌推荐
  • Video DownloadHelper CoApp终极指南:5个技巧轻松下载网络视频
  • Rust 在功能安全领域的应用前景:形式化验证与编译期不变量检查的协同
  • 三合一协议支持:LuckyLilliaBot如何重新定义QQ机器人开发体验
  • 深入解析Sunshine游戏串流架构:5种高效部署方案实战指南
  • 技术博客全流程:从选题、架构设计、代码验证到图表的完整体验复盘
  • FRP平板热门厂家如何选择 实用建材选型避坑全指南 - 热点品牌推荐
  • 2026年柔性排水管生产商推荐,怎么选才稳妥? - 热点品牌推荐
  • EMIF中断机制:从硬件信号到软件响应的桥梁
  • 天津婚姻家庭律师怎么选?坤石律所婚家团队值得关注 - 本地品牌推荐
  • 2026年潍坊卫生间装修厂家哪家好 本地服务商挑选指南 - 热点品牌推荐
  • Nginx 反向代理与负载均衡实战(基于陶辉《深入理解 Nginx》第三章)
  • 通州区外墙漏水维修电话及专业服务指南 - 热点品牌推荐
  • Midscene:3大核心技术优势重塑跨平台AI自动化测试体验
  • MoneyPrinterTurbo:零门槛AI短视频革命,3分钟打造爆款内容
  • 【剪映AI音量均衡实战指南】:20年音视频工程师亲授3步搞定人声与背景音自动平衡
  • 宝鸡离婚纠纷中夫妻共同债务如何认定?5位专业婚姻家事律师详细解读 - 本地品牌推荐
  • 俄 APT 组织 Laundry Bear 零点击钓鱼攻击技术机理与防御体系研究
  • 2026年常州遗产继承律师怎么选?陈志豪律师15年家事经验,复杂遗产纠纷有章法 - 本地品牌推荐
  • 2026年淮北酒店隔断推拉门生产厂商实用选购指南 - 热点品牌推荐
  • 面向对象与异常处理:从自动咖啡机看 Python 类设计