Nginx学习:命令行参数
对于 Nginx 来说,它不像其它很多别的工具一样,有很多的命令行参数,比如我们刚刚学习完的 Redis 中的 redis-cli 或者 redis-server 。Nginx 的命令行参数只有几个,相信不少同学也经常会用到,所以总体来说,今天学习的内容并不是特别的复杂。
关于 Nginx 是什么,怎么安装,咱们也不多解释了,直接就开始正式的学习。毕竟现在 Nginx 已经是事实上的主流服务器应用了。可能很多国外的排行上它还比 Apache 低,但是,就我们目前的行业情况来看,使用 Apache 的才是凤毛麟角,甚至我在找工作的过程中,已经很多年没见过有哪个公司是使用 Apache 的了。不得不说,我们永远的朋友(俄罗斯)们做的软件真的是简单粗暴,但却那么好用,值得学习。
启动运行
安装完成之后,如果是手动安装的,需要自己添加环境变量,如果不添加,那就找到安装目录,然后直接运行 nginx 这个命令就可以了。
代码语言:javascript复制➜ ~ nginx
➜ ~ ps -ef | grep nginx
501 12719 1 0 9:34上午 ?? 0:00.00 nginx: master process nginx
501 12720 12719 0 9:34上午 ?? 0:00.00 nginx: worker process
现在服务已经启动了。默认情况下,它会监听一个 8080 端口,然后指向的程序目录会是自己安装目录下的一个 www 目录。如果你和我一们使用的是 Mac 的话,那么可以使用 brew 方便地安装。安装之后它指向的文件目录是 /usr/local/var/www/ ,配置文件目录是 /usr/local/etc/nginx/ ,程序目录是 /usr/local/Cellar/nginx/1.21.6_1/bin/ 。
默认情况下,它会加载一个配置文件,这个配置文件的目录如果是编译安装的,可以在 configure 时通过 --conf-path=/usr/local/etc/nginx/nginx.conf
指定。当然,你也可以在运行时通过 -c
这个参数指定。
nginx -c </path/to/config>
命令行参数
对于要查看某个软件的命令行参数,通常来说都是通过 help 之类的命令来查看,Nginx 也不例外。
代码语言:javascript复制➜ ~ nginx -h
nginx version: nginx/1.23.0
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
[-e filename] [-c filename] [-g directives]
Options:
-?,-h : this help
-v : show version and exit
-V : show version and configure options then exit
-t : test configuration and exit
-T : test configuration, dump it and exit
-q : suppress non-error messages during configuration testing
-s signal : send signal to a master process: stop, quit, reopen, reload
-p prefix : set prefix path (default: /usr/local/Cellar/nginx/1.21.6_1/)
-e filename : set error log file (default: /usr/local/var/log/nginx/error.log)
-c filename : set configuration file (default: /usr/local/etc/nginx/nginx.conf)
-g directives : set global directives out of configuration file
是的,你没看错,就这么一点,没了。接下来我们就一个一个的学习一下。
查看版本信息
通过 -v
参数,就可以看到当前 nginx 的版本信息。
➜ ~ nginx -v
nginx version: nginx/1.23.0
另外还有一个大写的 -V
可以看到更完整的信息,以及编译时的 configure 信息。
➜ ~ nginx -V
nginx version: nginx/1.21.6
built by clang 13.0.0 (clang-1300.0.29.30)
built with OpenSSL 1.1.1m 14 Dec 2021
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/nginx/1.21.6_1 --sbin-path=/usr/local/Cellar/nginx/1.21.6_1/bin/nginx --with-cc-opt='-I/usr/local/opt/pcre2/include -I/usr/local/opt/openssl@1.1/include' --with-ld-opt='-L/usr/local/opt/pcre2/lib -L/usr/local/opt/openssl@1.1/lib' --conf-path=/usr/local/etc/nginx/nginx.conf --pid-path=/usr/local/var/run/nginx.pid --lock-path=/usr/local/var/run/nginx.lock --http-client-body-temp-path=/usr/local/var/run/nginx/client_body_temp --http-proxy-temp-path=/usr/local/var/run/nginx/proxy_temp --http-fastcgi-temp-path=/usr/local/var/run/nginx/fastcgi_temp --http-uwsgi-temp-path=/usr/local/var/run/nginx/uwsgi_temp --http-scgi-temp-path=/usr/local/var/run/nginx/scgi_temp --http-log-path=/usr/local/var/log/nginx/access.log --error-log-path=/usr/local/var/log/nginx/error.log --with-compat --with-debug --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-ipv6 --with-mail --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module
从这里,我们就可以看到当前 Nginx 默认的一些配置目录在哪里,也能看到当前的 Nginx 中都安装了哪些模块。不同的模块的配置将是我们未来学习的重点。
检查配置文件
对于 Nginx 来说,配置文件非常重要,刚刚也说了,未来的学习主要就是针对配置文件中各种配置的学习。如果配置文件出现了问题,那么 Nginx 的运行也会有各种问题。因此,它专门提供了一个 -t
参数用来检查配置文件是否有错误。
➜ ~ nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
这两行信息表示配置文件是正常的,没有任何问题。现在我们来模拟测试一下写错了配置文件会怎么样,直接打开我们的配置文件,然后随便乱写点东西。
代码语言:javascript复制➜ ~ vim /usr/local/etc/nginx/nginx.conf
………………
jj # 随便乱加
………………
接着再次运行 -t
进行测试。
➜ ~ nginx -t
nginx: [emerg] unknown directive "jj" in /usr/local/etc/nginx/nginx.conf:12
nginx: configuration file /usr/local/etc/nginx/nginx.conf test failed
很明显,配置文件中的错误语法被识别了出来。记住,每次自己手动修改完配置文件之后,一定要使用 -t
测试一下,否则服务启动不起来了,或者出现严重问题了,那可就吃不了兜着走了。
对于配置文件检查来说,也有一个大写的 -T
参数,它的作用也是类似的,只不过它还会把当前所有加载到的配置文件内容也打印出来。
➜ ~ nginx -T
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
# configuration file /usr/local/etc/nginx/nginx.conf:
#user nobody;
worker_processes 1;
………………
# configuration file /usr/local/etc/nginx/mime.types:
………………
# configuration file /usr/local/etc/nginx/servers/huanbao.conf:
………………
# configuration file /usr/local/etc/nginx/fastcgi_params:
………………
# configuration file /usr/local/etc/nginx/servers/xxx.conf:
………………
………………
关于这些配置是干嘛的,我们后面再慢慢学习,现在你只要知道这个参数能够看到所有的配置文件信息就好了。
信号控制(重启、停止)
接下来,我们学习 Nginx 的重启和停止。前面我们已经学过了 Nginx 如何启动运行,记住,没有什么 start 之类的参数,直接不带参数的运行 nginx 命令就是启动服务了。这时,如果你再次运行 nginx ,它会显示出一些端口已被绑定的信息。
代码语言:javascript复制➜ ~ nginx
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
其实从这里也可以看出,如果我们再指定一个新的配置文件,只要配置文件中的端口号和之前已经运行的 Nginx 服务中的端口号不同,那么是可以再开新的 Nginx 实例的,是这样吗?大家可以自己试试,但今天咱们还是以命令行参数为主。
好吧,明显的,nginx 命令直接运行是不能去重启或者关闭服务的。那么我们要怎么重启和关闭呢?其实不少小伙伴应该早就知道了:-s
参数嘛。
nginx -s <signal>
注意到后面这个 ,它是信号的意思。它有下面这些值。
stop
快速关闭quit
优雅关闭reload
重截配置文件reopen
重新打开日志文件
小伙伴们用得最多的应该就是 nginx -s reload
这个命令吧,毕竟大家没事的时候可不会直接去关闭服务玩。如果自己写过日志分割的,应该也用过 reopen 。咱们还是一个一个好好来解释下。
stop 和 quit 都是停止服务,退出 Nginx 程序,但是,stop 是直接关闭,而 quit 是优雅的关闭。如果你学习过 Go 语言,那一定会接触过优雅停机这个概念。意思就是在关闭服务的时候,如果有未执行完成的请求,那么这个请求还会继续执行完成,新的请求不会再进来。当所有请求都执行完毕后,正式关闭服务。对应的,stop 就是不管你的请求有没有执行完,直接就关闭服务,你的页面马上就会展示出报错信息。生产环境中,当然是推荐 quit 啦,但某些特殊情况下,比如网站在被爬,或者已经严重拖累数据库了,马上需要关闭服务的情况下,就不用考虑那么多了。可以使用 php 进行 sleep() 操作来测试 quit 和 stop 的不同。
reload 是当你的配置文件有修改后,直接重裁这个配置文件,同样的,如果你学习过 Go ,那么 Viper 也是可以支持配置文件的监听的,意思是一样的。Nginx 会让新的请求开一个新的工作进程,它们会走新的配置文件,同时老的请求也会通过优雅的方式在处理完成之后被关闭。注意,再次提醒,reload 之前 ,一定要先 -t
检查啊。
reopen 就是重新打开对日志文件的读写句柄,常用于日志分割时。特别是对于访问日志,也就是默认的那个 access_log ,如果你的网站访问量比较大,这个日志文件每天也会生成非常多的信息,这时,就可以写一个定时脚本,每天半夜去进行日志分割,然后再 reopen 让今天的日志记录到新的文件中。后面我们也会学习到怎样自己写一个简单的日志分割脚本。
好用吧,也非常方便吧,但其实,这些命令的底层其实是走的 Nginx 的信号控制流程。关于 Linux 程序的信号控制,在之前学习 Swoole 的时候我们就接触过,不记得的小伙伴可以移步 【Swoole3.4】进程间通信https://mp.weixin.qq.com/s/uftbLUHeQ1hzChpN2D-g7A 。当时我们是使用信号来进行进程间通信,同样的,信号也可以通过编码,让程序来执行许多功能。
代码语言:javascript复制➜ ~ ps -ef | grep nginx
501 12789 1 0 9:35上午 ?? 0:00.00 nginx: master process nginx
501 12790 12789 0 9:35上午 ?? 0:00.00 nginx: worker process
➜ ~ kill -s QUIT 12789
我们给 Nginx 的主进程发送了一个 QUIT 信号,其实它的意思就和 nginx -s quit
一样,让 Nginx 优雅关机。我们还可以这样写,用原生的信号语法。
➜ ~ kill -QUIT 12985
是不是感觉很高大上。还有其它的信号参数。
- TERM, INT 快速关闭,相当于
nginx -s stop
- QUIT 从容关闭,相当于
nginx -s quit
- HUP 重载配置,相当于
nginx -s reload
- USR1 重新打开日志文件 ,相当于
nginx -s reopen
- USR2 平滑升级可执行程序,直接平滑替换整个 Nginx 程序,比如版本升级
- WINCH 从容关闭工作进程,和 USR2 配合使用,让旧的进程退出
大家注意到没,下面的两个信号是我们 -s
命令中所没有的。USR2 可以用于平滑升级 Nginx 版本,相当强大。WINCH 则可以用于优雅关闭主进程。这两个配置是需要配合使用的,先编译安装好新的 Nginx ,然后 USR2 让正在运行的主进程 A 生成以新的版本文件运行的一个进程 B ,这个 B 进程目前还是老的进程 A 的子进程,但它会标识为 master 。接着,使用 WINCH 去关闭老的进程 A 。在这中间,整个 Nginx 的服务是不会中断的,如果有老的请求还没有完成,那么老的进程还会继续处理完,就像 reload 一样平滑的完成整个程序版本的升级重启。
不过,说实话,很少有去升级 Nginx 的,真的非常少,为什么呢?就像 2/8 定律一样。其实我们大部分情况下用到的只是 Nginx 中最核心的那 20% 功能,这些功能很少会更新的,漏洞也比较少。反而如果你经常用一些非常新的功能,则有可能因为各种问题而带来经常的更新切换。
当然,也不是说新版本不好,如果是线上环境,使用最新的稳定版本就好了。大部分情况下,用个几年升不升级的也没啥影响。
其它参数
另外还有几个参数,咱们简单看一下,平常使用的不多。
-e file
使用指定的错误日志文件来存储日志,而不是默认文件(1.19.5)。特殊值 stderr 选择标准错误文件。-g directives
动态设置一些配置文件中的全局配置信息-p prefix
设置 Nginx 程序的运行目录,一般是起保护作用-q
在测试期间抑制非错误的信息
总结
今天的内容重点就是信号控制以及配置文件检查,这两块相信也是大家经常会使用到的部分。关于 Nginx 中,命令行的部分就学完了,是的,就这么一篇,就这么一点点内容。后面我们将学习到的内容基本都是配置文件里面的东西,如果有牵涉到命令行相关的内容,也会直接给出示例。
后续的学习就是 Nginx 中各个模块的配置,有的配置可能一篇文章写不完,反正还是以官方文档为基础,例行刷文档。没有进阶部分,直接就在学习的过程中穿插一些原理和常见面试八股文的学习,大家不要急,夯实基础才是不断向上最稳妥的方案。
好了,Nginx 的学习旅程就这样愉快的开始了,没别的废话,上来就是干,加油吧,少年们!