Nginx 安装及升级

本文档主要做为需要安装或升级 Nginx 版本或者需要重新编译 Nginx 为其添加新模块时的参考。Nginx 服务常用配置说明

环境信息

  • Centos 7 5.4.225-1
  • nginx stable 1.24.0

编译安装 Nginx

编译安装 Nginx 之前,首先需要安装依赖包 [1]

pcre

cd /tmp
wget github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.gz
tar -zxf pcre2-10.42.tar.gz
cd pcre2-10.42
./configure
make
sudo make install

zlib

cd /tmp
wget http://zlib.net/zlib-1.2.13.tar.gz
tar -zxf zlib-1.2.13.tar.gz
cd zlib-1.2.13
./configure
make
sudo make install

openssl

cd /tmp
wget --no-check-certificate http://www.openssl.org/source/openssl-1.1.1t.tar.gz
tar -zxf openssl-1.1.1t.tar.gz
cd openssl-1.1.1t
./config shared zlib
make install

编译安装 Nginx

下载 Nginx stable 版本编译安装

wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar zxf nginx-1.24.0.tar.gz
cd nginx-1.24.0

要启用或者停用指定的 Nginx 自带模块,参考 Nginx 编译配置选项说明

此处编译配置添加第三方模块 nginx-module-vts 以支持 Prometheus。执行以下命令编译 Nginx 并添加第三方模块 nginx-module-vtsNginx 和 nginx-module-vts 版本兼容列表

wget https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2.2.tar.gz
tar -xf v0.2.2.tar.gz

./configure --prefix=/usr/local/nginx-1.24.0 \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream --with-stream_ssl_module \
--with-openssl=/tmp/openssl-1.1.1t \
--with-http_v2_module \
--add-module=nginx-module-vts-0.2.2/

make
make install

编译安装后的软件包,只需要安装好依赖,便可以迁移到其他机器上面使用,本文档编译安装后的软件包下载链接

为 Nginx 配置 systemd 管理配置文件

为了能使用 systemctl 管理源码编译安装的 nginx,可以为其使用以下配置文件将其托管到 systemd

/usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/local/nginx-1.24.0/sbin/nginx -t
ExecStart=/usr/local/nginx-1.24.0/sbin/nginx
ExecReload=/usr/local/nginx-1.24.0/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Prometheus 采集 Nginx 监控数据

参考步骤安装 nginx-module-vts 模块,以支持 Prometheus 采集 Nginx 统计数据。

如果要统计 Nginx 所有的 vhost 数据,则将 nginx-module-vts 模块相关配置放置于 http 模块内,否则可以在只想要监控(统计)的 vhost (server 配置段) 中添加配置。

nginx-module-vts 模块相关配置命令说明:

命令 说明 用法示例
vhost_traffic_status_zone 定义 vhost_traffic_status 模块使用的共享内存区域。用于存储虚拟主机的流量统计信息 vhost_traffic_status_zone shared_memory_name size;
shared_memory_name 是共享内存区域的名称,size 是共享内存区域的大小。
vhost_traffic_status_filter_by_host 按主机名过滤虚拟主机状态信息
默认会将流量全部计算到第一个 server_name 上;启用后,只会显示与请求的主机名匹配的虚拟主机状态信息。
vhost_traffic_status_filter_by_host on;
vhost_traffic_status_filter_by_set_key 根据自定义键值对来过滤虚拟主机的状态信息 vhost_traffic_status_filter_by_set_key $host$request_uri;
vhost_traffic_status_filter_by_set_zone 过滤器使用的共享内存区域
vhost_traffic_status_display 用于显示虚拟主机状态信息的格式
支持 jsonCSVhtml
vhost_traffic_status_display_format html;
vhost_traffic_status_display_format 用于显示虚拟主机状态信息的字段格式。
可以选择显示的字段有:request、status、request_time、request_length、request_method、request_uri、request_length、request_time、request_time_counter、request_time_counter_overflows、request_time_min、request_time_max、request_time_avg、request_time_median、request_time_percentile。
vhost_traffic_status_display_format field1 field2 ...;

为了获取所有域名的统计信息,在 Nginx 的 http 模块内添加以下配置:

nginx.con
http {
...
vhost_traffic_status_zone;

vhost_traffic_status_filter_by_host on;

server {
listen 8888;
server_name localhost;
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format json;
}

}
}

重载配置后查看请求内容:

# curl localhost:8888/status
{"hostName":"testhost","moduleVersion":"v0.2.2","nginxVersion":"1.24.0","loadMsec":1713418497362,"nowMsec":1713418504352,"connections":{"active":7,"reading":0,"writing":1,"waiting":6,"accepted":7,"handled":7,"requests":14},"sharedZones":{"name":"ngx_http_vhost_traffic_status","maxSize":1048575,"usedSize":10587,"usedNode":3},"serverZones":{"api.testdomain.com":{"requestCounter":12,"inBytes":9330,"outBytes":6249,"responses":{"1xx":0,"2xx":12,"3xx":0,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0},"requestMsecCounter":11,"requestMsec":0,"requestMsecs":{"times":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1713418503612,1713418503612,1713418503612,1713418503612,1713418503612,1713418503962,1713418503965,1713418503965,1713418503966,1713418503966,1713418504330,1713418504331],"msecs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,3,0,0]},"requestBuckets":{"msecs":[],"counters":[]},"overCounts":{"maxIntegerSize":18446744073709551615,"requestCounter":0,"inBytes":0,"outBytes":0,"1xx":0,"2xx":0,"3xx":0,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0,"requestMsecCounter":0}},"src.testdomain.ph":{"requestCounter":1,"inBytes":393,"outBytes":309,"responses":{"1xx":0,"2xx":0,"3xx":1,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0},"requestMsecCounter":0,"requestMsec":0,"requestMsecs":{"times":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1713418500180],"msecs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},"requestBuckets":{"msecs":[],"counters":[]},"overCounts":{"maxIntegerSize":18446744073709551615,"requestCounter":0,"inBytes":0,"outBytes":0,"1xx":0,"2xx":0,"3xx":0,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0,"requestMsecCounter":0}},"*":{"requestCounter":13,"inBytes":9723,"outBytes":6558,"responses":{"1xx":0,"2xx":12,"3xx":1,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0},"requestMsecCounter":11,"requestMsec":0,"requestMsecs":{"times":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1713418500180,1713418503612,1713418503612,1713418503612,1713418503612,1713418503612,1713418503962,1713418503965,1713418503965,1713418503966,1713418503966,1713418504330,1713418504331],"msecs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,3,0,0]},"requestBuckets":{"msecs":[],"counters":[]},"overCounts":{"maxIntegerSize":18446744073709551615,"requestCounter":0,"inBytes":0,"outBytes":0,"1xx":0,"2xx":0,"3xx":0,"4xx":0,"5xx":0,"miss":0,"bypass":0,"expired":0,"stale":0,"updating":0,"revalidated":0,"hit":0,"scarce":0,"requestMsecCounter":0}}},"upstreamZones":{"::nogroups":[{"server":"127.0.0.1:12000","requestCounter":5,"inBytes":4154,"outBytes":3351,"responses":{"1xx":0,"2xx":5,"3xx":0,"4xx":0,"5xx":0},"requestMsecCounter":11,"requestMsec":2,"requestMsecs":{"times":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1713418503962,1713418503965,1713418503965,1713418503966,1713418503966],"msecs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,3]},"requestBuckets":{"msecs":[],"counters":[]},"responseMsecCounter":11,"responseMsec":2,"responseMsecs":{"times":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1713418503962,1713418503965,1713418503965,1713418503966,1713418503966],"msecs":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,3]},"responseBuckets":{"msecs":[],"counters":[]},"weight":0,"maxFails":0,"failTimeout":0,"backup":false,"down":false,"overCounts":{"maxIntegerSize":18446744073709551615,"requestCounter":0,"inBytes":0,"outBytes":0,"1xx":0,"2xx":0,"3xx":0,"4xx":0,"5xx":0,"requestMsecCounter":0,"responseMsecCounter":0}}]}}

统计信息输出结果支持多种格式:

  • localhost:8888/status/format/json - Json
  • localhost:8888/status/format/html - Html
  • localhost:8888/status/format/jsonp - Jsonp
  • localhost:8888/status/format/prometheus - Prometheus
  • localhost:8888/status/format/control - control

在 Prometheus 中添加以下 Targets 配置抓取 nginx-module-vts 模块暴露出的统计信息

- job_name: "Nginx"
metrics_path: '/status/format/prometheus'
static_configs:
- targets: ['IPADDRESS:8888']
labels:
Department : 'OP'

在 Prometheus 中检查抓取到的数据

常见错误

error while loading shared libraries

Nginx 编译安装成功后,启动报错

$ /usr/local/nginx-1.24.0/sbin/nginx -t
/usr/local/nginx-1.24.0/sbin/nginx: error while loading shared libraries: libpcre2-8.so.0: cannot open shared object file: No such file or directory

问题原因 为 Nginx 在系统的库文件路径中未找到已经安装的 libpcre2-8.so.0 库文件。可以通过以下方式验证

  1. 搜索 libpcre2-8.so.0,可以看到系统上已经存在此库文件 /usr/local/lib/libpcre2-8.so.0
    $ find / -name libpcre2-8.so.0
    /usr/local/lib/libpcre2-8.so.0
  2. 检查此库文件是否在系统已加载的库文件中。执行以下命令搜索系统已经加载的库文件,发现没有 /usr/local/lib/libpcre2-8.so.0
    $ ldconfig -p | grep libpcre
    libpcre32.so.0 (libc6,x86-64) => /lib64/libpcre32.so.0
    libpcre16.so.0 (libc6,x86-64) => /lib64/libpcre16.so.0
    libpcreposix.so.0 (libc6,x86-64) => /lib64/libpcreposix.so.0
    libpcrecpp.so.0 (libc6,x86-64) => /lib64/libpcrecpp.so.0
    libpcre.so.1 (libc6,x86-64) => /lib64/libpcre.so.1
  3. 检查系统共享库文件的查找路径的配置文件 /etc/ld.so.conf,发现其中不包括路径 /usr/local/lib/,因此位于此路径下的共享库文件无法被搜索到
    $ cat /etc/ld.so.conf
    include ld.so.conf.d/*.conf


要解决此问题,可以使用以下方法之一:

  • 添加 /usr/local/lib/ 到系统共享库查找路径配置文件 /etc/ld.so.conf

    /etc/ld.so.conf
    include ld.so.conf.d/*.conf
    /usr/local/lib/

    执行以下命令,使配置生效

    ldconfig
  • 设置系统环境变量 LD_LIBRARY_PATH,这个变量定义了系统共享库的查找目录。将 /usr/local/lib 添加到此变量的值中,要永久生效需要将其写入配置文件,如 ~/.bash_profile

    export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
  • 创建符号链接

    ln -s /usr/local/lib/libpcre2-8.so.0 /usr/local/nginx-1.24.0/sbin/libpcre2-8.so.0

    或者

    ln -s /usr/local/lib/libpcre2-8.so.0 /lib64/libpcre2-8.so.0

SSL modules require the OpenSSL library

执行以下命令执行编译前配置时报错 ./configure: error: SSL modules require the OpenSSL library.

# ./configure --prefix=/usr/local/nginx-1.24.0 \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream --with-stream_ssl_module \
--with-http_v2_module \
--add-module=nginx-module-vts-0.2.2/

checking for PCRE2 library ... found
checking for OpenSSL library ... not found
checking for OpenSSL library in /usr/local/ ... not found
checking for OpenSSL library in /usr/pkg/ ... not found
checking for OpenSSL library in /opt/local/ ... not found

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.

此报错原因为未找到 OpenSSL 的库文件。

针对此场景,可以通过在编译配置时指定 OpenSSL 的源码中库文件的具体位置(--with-openssl=/tmp/openssl-1.1.1t),参考以下命令

./configure --prefix=/usr/local/nginx-1.24.0 \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream --with-stream_ssl_module \
--with-openssl=/tmp/openssl-1.1.1t \
--with-http_v2_module \
--add-module=nginx-module-vts-0.2.2/

Error 127

Nginx 执行 make 命令时报错: /bin/sh: line 2: ./config: No such file or directory

# ./configure --prefix=/usr/local/nginx-1.24.0 \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream --with-stream_ssl_module \
--with-openssl=/usr/local/lib64/ \
--with-http_v2_module \
--add-module=nginx-module-vts-0.2.2/

# make
make -f objs/Makefile
make[1]: Entering directory `/root/nginx-1.24.0'
cd /usr/local/lib64/ \
&& if [ -f Makefile ]; then make clean; fi \
&& ./config --prefix=/usr/local/lib64//.openssl no-shared no-threads \
&& make \
&& make install_sw LIBDIR=lib
/bin/sh: line 2: ./config: No such file or directory
make[1]: *** [/usr/local/lib64//.openssl/include/openssl/ssl.h] Error 127
make[1]: Leaving directory `/root/nginx-1.24.0'
make: *** [build] Error 2

错误信息表明在编译 nginx 时,make 命令无法找到 OpenSSL 的配置脚本 config。此脚本位于 OpenSSL 的源码目录中。可以通过 --with-openssl=/tmp/openssl-1.1.1t 指定。
修改编译前的配置命令如下:

./configure --prefix=/usr/local/nginx-1.24.0 \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream --with-stream_ssl_module \
--with-openssl=/tmp/openssl-1.1.1t \
--with-http_v2_module \
--add-module=nginx-module-vts-0.2.2/

make
make install

getpwnam(“nginx”) failed

nginx 报错

nginx: the configuration file /usr/local/nginx-1.24.0/conf/nginx.conf syntax is ok
nginx: [emerg] getpwnam("nginx") failed
nginx: configuration file /usr/local/nginx-1.24.0/conf/nginx.conf test failed

问题原因nginx 用户不存在,创建 nginx 用户或者修改配置文件,使用已有的用户运行 nginx

参考链接

Nginx 官网文档

脚注