Linux教程网

nginx 编译运行

对 nginx 有一定了解之后,接下来把 nginx 运行环境搭建起来,以便我们更好地学习和理解。

nginx 的安装方式有很多,可以通过 aptyum 方式直接安装对应的包程序。有时我们需要使用更新的版本,或需要更丰富的特性或配置,这种方式就满足不了。

对于想深入理解 nginx 的开发者来说,编译安装的方式可以让我们深入代码层面,学习理解会更加高效和透彻。

编译安装

系统环境

  • 系统:ubuntu 22.04.03
  • 架构:x64

安装依赖

  • 安装编译工具
1
2
apt-get update
apt-get install build-essential
  • 安装依赖包
1
2
3
4
5
6
# 正则表达式库,用于处理 HTTP 请求
apt-get install libpcre3 libpcre3-dev
# 压缩库,用于压缩 HTTP 响应
apt-get install zlib1g zlib1g-dev
# 安全套接字层协议库,用于支持 HTTPS 协议
apt-get install openssl libssl-dev

通过上述命令,可以安装 nginx 所需要的基本依赖包,安装完这些依赖包后,接下来就可以通过源码编译的方式进行安装了

编译安装

  • 下载 nginx 源代码
1
2
3
4
5
6
# 从官方下载源码包
wget http://nginx.org/download/nginx-1.22.1.tar.gz

# 解压并进入目录
tar -zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1
  • 执行编译配置
1
2
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module --with-stream_ssl_module
  1. --prefix:指定安装目录
  2. --with-http_ssl_module:支持 HTTPS
  3. --with-stream_ssl_module:支持 TLS
  • 执行编译和安装
1
2
# 编译并安装
make && make install

编译过程可能需要较长时间,请耐心等待,如果编译成功会看到如下信息

1
2
3
4
5
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx configuration prefix: "/usr/local/nginx/conf"
... ...
nginx http scgi temporary files: "scgi_temp"

运行验证

安装完毕后,可以先看下 nginx 的版本信息,如果安装正常的话,可以看到如下信息

1
2
$ /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.22.1

可以看到版本信息,接下来可以启动 nginx 了

1
$ /usr/local/nginx/sbin/nginx

执行 nginx 命令后,就启动了 nginx,确认 nginx 是否正常启动

1
2
3
4
5
6
7
8
# 查看 nginx 进程
$ ps aux | grep nginx
root Ss 13:39 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody S 13:39 0:00 nginx: worker process

# 查看 nginx 侦听端口
$ ss -nlpt | grep nginx
LISTEN 0.0.0.0:* users:(("nginx",pid=9550,fd=6),("nginx",pid=9549,fd=6))

至此 nginx 成功安装

编译选项

在执行 make 命令时,首先执行了 configure 脚本,该脚本其实做了很多工作,其中一项就是编译选项和配置参数的设置。

configure 脚本支持很多选项,可以通过 --help 来查看,下面尝试总结梳理一些重要的选项参数:

路径相关参数

参数名称 意义 默认值
–prefix=PATH Nginx安装部署后的根目录 /usr/local/nginx
–sbin-path=PATH 可执行文件的放置路径 ${prefix}/sbin/nginx
–conf-path=PATH 配置文件的放置路径 ${prefix}/conf/nginx.conf
–error-log-path=PATH 错误日志放置路径 ${prefix}/logs/error.log
–pid-path=PATH pid文件的存放路径 ${prefix}/logs/nginx.pid
–lock-path=PATH lock文件路径 ${prefix}/logs/nginx.lock
–builddir=DIR 编译期间临时文件目录 src/objs
–http-log-path=PATH 访问日志放置的位置 ${prefix}/logs/access.log
–http-client-body-temp-path=PATH 请求缓存临时磁盘文件路径 ${prefix}/client_body_temp
–http-proxy-temp-path=PATH 上游服务器产生临时存放磁盘位置 ${prefix}/proxy_temp

编译相关参数

编译参数 意义
–with-cc=PATH C 编译器的路径
–with-cpp=PATH C++ 编译器的路径
–with-cc-opt=OPTIONS 编译期增加编译选项,如指定宏或使用 -I 加入某些包含目录
–with-ld-opt=OPTIONS 加入链接参数
–with-cpu-opt=CPU 指定CPU处理架构

依赖软件参数

–without-pcre –with-pcre=DIR
–with-pcre –with-pcre-opt=OPTIONS
–with-openssl=DIR –with-openssl-opt=OPTIONS
–with-libatomic –with-libatomic=DIR
–with-MD5=DIR –with-MD5-opt=OPTIONS

模块相关参数

  • 事件模块
    • --with-poll_module
    • --with-aio_module
    • ... ...
  • 默认编译进 nginx 的 http 模块
    • --without-http_gzip_module
    • --without-http_access_module
    • --without-http_auth_basic_module
    • --without-http_rewrite_module
    • ... ...
  • 默认不会编译进 nginx 的 http 模块
    • --with-http_ssl_module
    • --with-http_geoip_module
    • --with-http_gzip_static_module
    • ... ...
  • 邮件代理服务器相关的 mail 模块
    • --with-mail
    • --with-mail_ssl_module
    • ... ...
  • 其它参数
    • --with-debug:开启调试选项
    • --add-module=PATH:指定三方模块
    • --without-http:关闭 http 功能
    • --with-ipv6:开启 IPv6

编译流程

make 命令根据 configure 命令生成的 Makefile 文件编译 nginx 工程,并生成目标文件、最终的二进制文件。

其实 configure 做了大量的幕后工作,包括检测操作系统内核和已经安装的软件,参数的解析,中间目录的生成以及根据各种参数生成一些 C 源码文件、Makefile 文件等。

  • . auto/options

处理 configure 命令的参数,options 脚本会定义后续工作将要用到的变量,根据本次参数以及默认值设置这些变量

  • . auto/init

脚本初始化后续将产生的文件路径,比如 Makefile、ngx_module.c 等文件默认情况下将会在 objs

  • . auto/sources

脚本将分析 nginx 源码结构,这样才能构造后续的 Makefile 文件

  • test -d $NGX_OBJS || mkdir $NGX_OBJS

编译过程中所有目标文件生成的路径由 –builddir=DIR 参数指定,默认情况下为 objs 此时这个目录将会被创建

  • 创建必要编译文件
1
2
echo > $NGX_AUTO_HEADERS_H
echo > $NGX_AUTOCONF_ERR

开始准备建立 ngx_auto_headers.h、autoconf.err 等必要的编译文件

  • objs/ngx_auto_config.h 写入命令行带的参数
1
echo "#define NGX_CONFIGURE \"$NGX_CONFIGURE\"" > $NGX_AUTO_CONFIG_H
  • 判断 DEBUG 标志,如果有向 objs/ngx_auto_config.h 文件写入 DEBUG 宏
1
2
3
if [ $NGX_DEBUG = YES ]; then
have=NGX_DEBUG . auto/have
fi
  • 检查操作系统参数是否支持后续编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if test -z "$NGX_PLATFORM"; then
echo "checking for OS"
NGX_SYSTEM=`uname -s 2>/dev/null`
NGX_RELEASE=`uname -r 2>/dev/null`
NGX_MACHINE=`uname -m 2>/dev/null`

echo " + $NGX_SYSTEM $NGX_RELEASE $NGX_MACHINE"
NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE"

case "$NGX_SYSTEM" in
MINGW32_*)
NGX_PLATFORM=win32
;;
esac
else
echo "building for $NGX_PLATFORM"
NGX_SYSTEM=$NGX_PLATFORM
fi
  • . auto/cc/conf

检查并设置编译器,如 GCC 是否安装、GCC 版本是否支持后续编译 nginx

  • . auto/headers

对非 windows 操作系统定义一些必要的头文件,并检查其是否存在,以此决定 configure 后续步骤是否可以成功

  • . auto/os/conf

对于当前操作系统,定义一些特定的操作系统相关的方法并检查当前环境是否支持。例如,对于 Linux,在这里使用 sched_setaffinity 设置进程优先级,使用 Linux 特有的 sendfile 系统调用来加速向网络中发送文件块

  • . auto/unix

定义类 UNIX 操作系统中通用的头文件和系统调用等,并检查当前环境是否支持

  • . auto/modules

将会生成 ngx_module.c 文件,它定义了 ngx_modules 数组,会被编译进 nginx 中。

ngx_modules 指明 nginx 运行期间有哪些模块会参与到请求处理中,它对数组元素的顺序非常敏感。

另外,在 –add-module= 参数加入的第三方模块也在此步骤写入到 ngx_module.c 文件中了。

  • . auto/lib/conf

用来检查 nginx 在链接期间需要链接的第三方静态库、动态库或目标文件是否存在

  • 处理 nginx 安装后的路径
1
2
3
4
5
6
7
8
9
10
11
case ".$NGX_PREFIX" in
.)
NGX_PREFIX=${NGX_PREFIX:-/usr/local/nginx}
have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
;;
.!)
NGX_PREFIX=
*)
have=NGX_PREFIX value="\"$NGX_PREFIX/\"" . auto/define
;;
esac
  • 处理 nginx 安装后的文件路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if [ ".$NGX_CONF_PREFIX" != "." ]; then
have=NGX_CONF_PREFIX value="\"$NGX_CONF_PREFIX/\"" . auto/have
fi

# 处理 nginx 安装后,二进制文件、pid、lock 等文件的路径可参考路径类选项说明
have=NGX_SBIN_PATH value="\"NGX_SBIN_PATH\"" . auto/define
have=NGX_CONF_PATH value="\"NGX_CONF_PATH\"" . auto/define
have=NGX_PID_PATH value="\"NGX_PID_PATH\"" . auto/define
have=NGX_LOCK_PATH value="\"NGX_LOCK_PATH\"" . auto/define
have=NGX_ERROR_LOG_PATH value="\"NGX_ERROR_LOG_PATH\"" . auto/define

have=NGX_HTTP_LOG_PATH value="\"NGX_HTTP_LOG_PATH\"" . auto/define
have=NGX_CLIENT_TEMP_PATH value="\"NGX_CLIENT_TEMP_PATH\"" . auto/define
have=NGX_PROXY_TEMP_PATH value="\"NGX_PROXY_TEMP_PATH\"" . auto/define
have=NGX_FASTCGI_TEMP_PATH value="\"NGX_FASTCGI_TEMP_PATH\"" . auto/define
have=NGX_UWSGI_TEMP_PATH value="\"NGX_UWSGI_TEMP_PATH\"" . auto/define
have=NGX_SCGI_TEMP_PATH value="\"NGX_SCGI_TEMP_PATH\"" . auto/define
  • . auto/make

创建编译时使用的 objs/Makefiel 文件

  • . auto/lib/make

objs/Makefile 加入需要连接的第三方静态库、动态库或目标文件

  • . auto/install

objs/Makefile 加入 install 功能

  • . auto/stubs

ngx_auto_config.h 文件中加入 NGX_SUPPRESS_WARN 宏、NGX_SMP

  • . auto/summary

显示 configure 执行的结果,如果失败,则给出原因

  • 执行 configure 成功后的文件与目录
1
2
3
4
5
6
├── configure           # 编译配置脚本
├── Makefile # configure脚本执行完毕动态生成的
├── ngx_auto_headers.h
├── autoconf.err # 保存configure过程中产生的结果
├── ngx_modules.c # 保存定义模块的数组
└── src # 源代码

其中 ngx_modules.c 是一个关键文件,默认配置下生成的 ngx_modules.c 文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
#include <ngx_config.h>

//......

ngx_module_t *ngx_modules[] = {
&ngx_core_module,
&ngx_errlog_module,
&ngx_conf_module,
&ngx_events_module,
// ......
NULL
};

ngx_modules 数组非常关键,它指明了每个模块在 nginx 中的优先级,对于 HTTP 模块而言,在 ngx_modules 数组中越是靠后的模块反而会首先处理 HTTP 响应

磁盘目录

make install 命令根据 configure 执行时的参数将 nginx 部署到指定的安装目录,包括相关目录的建立和二进制文件、配置文件的复制。

我们通过简单的方式对 nginx 进行了编译,下面我们来学习相关目录的作用

源代码目录

1
2
3
4
5
6
7
8
9
10
11
12
13
├── auto        # configure脚本执行时,通过shell检测系统环境
├── CHANGES # Change Log 文件
├── CHANGES.ru
├── conf # 默认配置
├── configure # 编译配置脚本
├── contrib
├── html # 默认静态html文件
├── LICENSE
├── Makefile # configure脚本执行完毕动态生成的
├── man # 相关手册配置
├── objs # 编译后产生的中间文件、二进制等
├── README
└── src # 源代码

中间文件目录

执行 make 编译命令后,在当前目录生成 objs 目录

1
2
3
4
5
6
7
8
9
├── autoconf.err        # 记录自动检查过程中的错误
├── Makefile # 执行configure脚本生成的
├── nginx # 执行make编译命令生成的二进制
├── nginx.8
├── ngx_auto_config.h # 动态生成的头文件
├── ngx_auto_headers.h # 动态生成的头文件
├── ngx_modules.c # 动态生成的模块相关的c文件
├── ngx_modules.o # 中间文件
└── src # 编译过程产生的中间.o文件

部署目录

在执行 ./configure 脚本时,指定了 --prefix=/usr/local/nginx 参数,是希望 nginx 将此目录作为主工作目录,也就是安装的目录。

在执行 make install 命令之后,脚本会将相关的编译产物和配置文件拷贝到 /usr/local/nginx 目录

1
2
3
4
├── conf    # 配置目录
├── html # 静态文件目录
├── logs # 日志目录
└── sbin # 二进制程序目录

日志目录

在我们这个环境中,nginx 日志目录是 ${prefix}/logs$prefix/usr/local/nginx

如果在编译时不指定 --prefix 选项,nginx 默认将 /var/log/nginx/logs 作为日志目录。

在运行中,访问日志错误日志、pid 文件等会存放在该目录中。

命令操作

在 Linux 中,可以行来控制 nginx 服务器的启动与停止、重载配置文件、回滚日志文件、平滑升级等行为。

启动运行

  • 直接启动
1
2
/usr/local/nginx/sbin/nginx
# 默认配置文件路径:/usr/local/nginx/conf/nginx.conf
  • 启动时指定配置文件
1
/usr/local/nginx/sbin/nginx -c /tmp/nginx.conf
  • 启动时指定主目录(安装目录)
1
/usr/local/nginx/sbin/nginx -p /usr/local/nginx
  • 启动时指定全局配置项
1
2
3
/usr/local/nginx/sbin/nginx -g "pid /var/nginx/test.pid;"
# "-g" 参数的约束条件是指定的配置项不能与默认路径下的nginx.conf中的配置项相冲突,否则无法启动
# "-g" 方式启动的nginx服务执行其他命令行时,需要把"-g"参数也带上,否则可能出现配置项不匹配的情形

配置测试

测试配置文件是否存在错误

1
2
/usr/local/nginx/sbin/nginx -t
# 使用"-q"参数可以不把error级别以下的信息输出到屏幕

打印信息

  • 显示版本信息
1
/usr/local/nginx/sbin/nginx -v
  • 显示编译阶段参数
1
2
$ /usr/local/nginx/sbin/nginx -V
# 如gcc编译器的版本、操作系统的版本、执行configure时的参数

停止服务

  • 快速地停止服务
1
/usr/local/nginx/sbin/nginx -s stop
  • 优雅地停止服务
1
/usr/local/nginx/sbin/nginx -s quit

配置重载

1
/usr/local/nginx/sbin/nginx -s reload

日志回滚

1
/usr/local/nginx/sbin/nginx -s reopen

平滑升级

  1. 通知旧版 nginx 准备升级
1
kill -s SIGUSR2 <nginx master pid>
  1. 启动新版本的 nginx

  2. 通过 kill 命令向旧版本 master 进程发送 SIGQUIT 信号,以优雅的方式关闭旧版本的 nginx


专题:

本文发表于 2023-01-06,最后修改于 2024-07-03。

本站永久域名「 golinuxblog.com 」,也可搜索「 Linux教程网 」找到我。


上一篇 « nginx 准备工作 下一篇 » 使用vscode搭建Go开发环境

推荐阅读

Big Image