Nginx 命令行
格式:
nginx -c config_file
与平时的Linux命令没有什么两样。帮助命令:
-h
/-?
没啥好说的,帮助命令你没有用过吗?nginx -c config_file
使用指定的配置文件nginx -c config_file -p prefix/for/relative/paths
-p
后面指定的是运行目录
。nginx -t
测试配置文件,但是不会立即生效。专门用来在应用新配置
前的测试命令。-s 信号
-s
拿来发送信号的,常见的信号参数:stop quit reload reopen
nginx -s reload
不宕机,平滑地加载配置文件;在升级/修改配置的时候,平滑过度到新配置。nginx -s stop
立即停止Nginx服务nginx -s quit
潇洒地停止Nginx服务nginx -s reopen
重新开始记录Nginx日志nginx -g
覆盖默认的一些参数nginx -v -V
前一个是打印版本信息
,后一个是打印编译信息
。
1[jane@centos7 sbin]$ ./nginx -v
2nginx version: nginx/1.14.2
3[jane@centos7 sbin]$ ./nginx -V
4nginx version: nginx/1.14.2
5built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
6configure arguments: --prefix=/home/jane/preview
重载配置文件
简单总结一句,就是不宕机(不停止对外服务),重新加载配置文件以应用新的配置。
参照之前的编译安装文章,找到你的安装目录。
1preview/
2├── conf
3│ ├── fastcgi.conf
4│ ├── fastcgi.conf.default
5│ ├── fastcgi_params
6│ ├── fastcgi_params.default
7│ ├── koi-utf
8│ ├── koi-win
9│ ├── mime.types
10│ ├── mime.types.default
11│ ├── nginx.conf <<< nginx的默认配置文件位置
12│ ├── nginx.conf.default
13│ ├── scgi_params
14│ ├── scgi_params.default
15│ ├── uwsgi_params
16│ ├── uwsgi_params.default
17│ └── win-utf
18├── html
19│ ├── 50x.html
20│ └── index.html
21├── logs
22└── sbin
23 └── nginx <<< 二进制执行文件
我是没有把Nginx加入到环境变量的,所以执行命令的时候都是在文件的目录里面执行的。./nginx
这样的命令模式,在本篇中很常见。
先启动Nginx。
1自己进目录
2
3sudo ./nginx ##不用sudo提权可能监听不了默认的80端口
启动后,可以用下面的命令看看进程ID
1ps -ef | grep nginx
修改配置文件
在你初次启动的时候,应该会在旁边生成很多目录的。只要根据上面的目录找到配置文件即可。
这里的演示就是去掉这里的注释以打开gzip压缩
,稍作修改。
1#gzip on;
2
3↓↓↓↓↓
4
5gzip on;
检查配置文件是否正确
现在我就当你已经修改好了。
修改完之后,当然要检查你写的新配置对不对啦。
1sudo ./nginx -t
只要没有报error
的错误,有successful
,基本就OK。
有报错,自己Google+百度。
加载新的配置文件
1sudo ./nginx -s reload
没报错,就是加载成功了。
热部署
如果你对Nginx的信号集不了解,可以参考另外一篇文章看来–Nginx-master信号处理流程以及其信号集(热更新/日志切割)。
版本升级,仅更换二进制文件。
!!!这个时候千万别搞什么新的配置文件来一起更新啊。
大致流程:
这里全部使用kill
来发送命令到指定的进程。
备份旧的二进制文件
采用新的二进制文件覆盖旧的二进制文件
发送
USR2
到老的master进程
发送
WINCH
到老的master进程
发送
QUIT
到老的master进程
后面有版本回退的操作演示
在这里,我准备了两个不同的Nginx版本。
一个是已经使用make install
安装好的Nginx
,版本为1.12.2
。
另一个是仅仅是编译好
的Nginx,在objs目录
放着,版本为1.14.2
。
!!!!! 注意: 新编译的Nginx的prefix目录参数
,一定要与原来的一致。不然在你发送USR2
的时候,你会发现新的master进程起不来。。。心酸泪。。。
可以在编译新版本之前,使用nginx -V
,看看之前的编译参数。确保新编译的prefix参数
与原来的一致。
不会编译的可以看—-编译适合自己的Nginx。
目标是从运行中的Nginx 1.12.2
,升级到 1.14.2
,其中不停止对外服务。
现在把1.12.2
的跑起来~~~
1[root@centos7 sbin]# ./nginx -V
2nginx version: nginx/1.12.2
3built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
4configure arguments: --prefix=/root/nginx/
5
6[root@centos7 sbin]# ./nginx
7
8[root@centos7 sbin]# ps -ef | grep nginx
9root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
10nobody 12295 12294 0 08:38 ? 00:00:00 nginx: worker process
11root 12297 6498 0 08:38 pts/0 00:00:00 grep --color=auto nginx
访问下该服务的端口,我的是默认的80端口。地址后面输个错的,可以看到服务器的版本号。
现在备份旧的Nginx
1mv nginx nginx.old #我这里直接重命名了。
如果你担心这个操作对于现在的Nginx有影响,没关系,看到文章最后,有解释。
不过你要是知道inode,就不会有这个疑问了。2333
移动
新版本1.14.2
的二进制可执行的Nginx文件到老版本的Nginx那个目录。
要是你对目录结构不清楚,看这个 – 介绍各目录以及部分文件
1[root@centos7 objs]# ./nginx -V
2nginx version: nginx/1.14.2
3built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
4configure arguments: --prefix=/root/nginx/
5
6[root@centos7 objs]# cp ./nginx /root/nginx/sbin/
7
8[root@centos7 objs]# ls /root/nginx/sbin/
9nginx nginx.old
给进程中的Nginx-master
发送信号USR2
,告诉其要进行版本升级,热更新,热部署。
master进程首先重命名PID文件,在文件名后添加.oldbin后缀,比如nginx.pid会被重命名为nginx.pid.oldbin。
然后会新起一个master进程以及worker进程,使用了最新的Nginx进程。
这里稍微解释下PID和PPID(免得一些萌新懵逼):
每个进程都会拥有 PID 和 PPID。
PID 就是现在进程的一个ID,你给他发送信号的时候就是用这ID。
PPID 这个就是启动它的程序的PID。可以让你知道这个进程是那一个进程启动的。混乱?没关系,看下面,有例子。
1Nginx-worker是由Nginx-master启动的,再看看仔细看看下面的PID和PPID,体会下。
2
3[root@centos7 objs]# ps -ef | grep nginx
4UID PID PPID #这一行我手动加的,实际上执行该命令,没这行
5root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
6nobody 12295 12294 0 08:38 ? 00:00:00 nginx: worker process
7root 14807 6498 0 08:50 pts/0 00:00:00 grep --color=auto nginx
8
9
10[root@centos7 objs]# kill -USR2 12294 #发送信号给Nginx的master进程(老的)
11
12从下面的输出,我们可以看出新的master是由老的master启动的。
13
14然后新的master又启动了一个属于自己的worker。
15
16[root@centos7 objs]# ps -ef | grep nginx
17UID PID PPID #这一行我手动加的,实际上执行该命令,没这行
18root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
19nobody 12295 12294 0 08:38 ? 00:00:00 nginx: worker process
20root 14809 12294 0 08:51 ? 00:00:00 nginx: master process ./nginx
21nobody 14810 14809 0 08:51 ? 00:00:00 nginx: worker process
22root 14812 6498 0 08:51 pts/0 00:00:00 grep --color=auto nginx
老的master/worker进程已经不再监听原来的端口了。
新的请求,新的连接,只会进入到新的Nginx里面。
发送信号 WINCH
给老的master进程,潇洒地关闭老的worker进程
1[root@centos7 objs]# ps -ef | grep nginx
2root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
3nobody 12295 12294 0 08:38 ? 00:00:00 nginx: worker process #将会被退出
4root 14809 12294 0 08:51 ? 00:00:00 nginx: master process ./nginx
5nobody 14810 14809 0 08:51 ? 00:00:00 nginx: worker process
6root 14835 6498 0 09:17 pts/0 00:00:00 grep --color=auto nginx
7
8
9[root@centos7 objs]# kill -WINCH 12294 #发送信号给Nginx的master进程(老的)
10
11
12[root@centos7 objs]# ps -ef | grep nginx
13root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
14root 14809 12294 0 08:51 ? 00:00:00 nginx: master process ./nginx
15nobody 14810 14809 0 08:51 ? 00:00:00 nginx: worker process
16root 14837 6498 0 09:18 pts/0 00:00:00 grep --color=auto nginx
老的master进程,不会自己退出,留作版本回退。就怕你翻车23333
如果你觉得新版本OK,没有问题(建议跑上几天看看效果再说)。那么就可以退出老的master进程了。
发送 QUIT
信号,让他潇洒地走人。
1kill -QUIT [Nginx-master-old-PID]
1⮀ ps -ef | grep nginx
2 0 55268 1 0 9:00PM ?? 0:00.00 nginx: master process ./nginx
3 0 58796 55268 0 9:07PM ?? 0:00.00 nginx: master process ./nginx
4 -2 58801 58796 0 9:07PM ?? 0:00.00 nginx: worker process
5
6⮀ sudo kill -QUIT 55268
7
8⮀ ps -ef | grep nginx
9 0 58796 1 0 9:07PM ?? 0:00.00 nginx: master process ./nginx
10 -2 58801 58796 0 9:07PM ?? 0:00.00 nginx: worker process
不要在意这里的PID
和上面的演示不连贯,原理都一样的。我好多机子的2333
版本回退
突然发现这个编译的版本翻车了,赶紧回滚,那该怎么做呢?
方案一(推荐)
给老的master发送
HUP信号
给新的master发送
QUIT信号
1[root@centos7 objs]# ps -ef | grep nginx
2root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
3root 14809 12294 0 08:51 ? 00:00:00 nginx: master process ./nginx
4nobody 14810 14809 0 08:51 ? 00:00:00 nginx: worker process
5root 14866 6498 0 09:35 pts/0 00:00:00 grep --color=auto nginx
6
7[root@centos7 objs]# kill -HUP 12294 #重新读取配置文件,启动新的worker,并且优雅地退出老的worker(虽然这里没有什么worker可以让他退罢了)
8
9HUP信号相当于reload
10
11[root@centos7 objs]# ps -ef | grep nginx
12root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
13root 14809 12294 0 08:51 ? 00:00:00 nginx: master process ./nginx
14nobody 14810 14809 0 08:51 ? 00:00:00 nginx: worker process
15nobody 14867 12294 0 09:36 ? 00:00:00 nginx: worker process
16root 14869 6498 0 09:36 pts/0 00:00:00 grep --color=auto nginx
17
18[root@centos7 objs]# kill -QUIT 14809 #优雅地关闭整个服务
19
20[root@centos7 objs]# ps -ef | grep nginx
21root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
22nobody 14867 12294 0 09:36 ? 00:00:00 nginx: worker process
23root 14872 6498 0 09:37 pts/0 00:00:00 grep --color=auto nginx
24
方案二
给新的master发送
TERM信号
或者INT信号
或者QUIT
信号老的master进程,会自己启动worker
1[root@centos7 objs]# ps -ef | grep nginx
2root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
3root 14876 12294 0 09:45 ? 00:00:00 nginx: master process ./nginx
4nobody 14877 14876 0 09:45 ? 00:00:00 nginx: worker process
5root 14882 6498 0 09:45 pts/0 00:00:00 grep --color=auto nginx
6[root@centos7 objs]# kill -QUIT 14876
7[root@centos7 objs]# ps -ef | grep nginx
8root 12294 1 0 08:38 ? 00:00:00 nginx: master process ./nginx
9nobody 14883 12294 0 09:46 ? 00:00:00 nginx: worker process
10root 14885 6498 0 09:46 pts/0 00:00:00 grep --color=auto nginx
日志切割
如果你对Nginx的信号集不了解,可以参考另外一篇文章看来–Nginx-master信号处理流程以及其信号集(热更新/日志切割)。
做日志切割很正常啦,特别是部署在生产环境。基本上一天一割。
1[root@centos7 logs]# ll
2total 24
3-rw-r--r--. 1 root root 4691 Feb 20 10:03 access.log
4-rw-r--r--. 1 root root 6114 Feb 20 10:03 error.log
5-rw-r--r--. 1 root root 6 Feb 20 09:49 nginx.pid
6-rw-r--r--. 1 root root 6 Feb 20 08:38 nginx.pid.oldbin
7
8[root@centos7 logs]# tail -2 access.log
9192.168.1.116 - - [20/Feb/2019:10:03:58 -0500] "GET / HTTP/1.1" 403 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:66.0) Gecko/20100101 Firefox/66.0"
10192.168.1.116 - - [20/Feb/2019:10:03:58 -0500] "GET / HTTP/1.1" 403 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:66.0) Gecko/20100101 Firefox/66.0"
11
12[root@centos7 logs]# tail -2 error.log
132019/02/20 10:03:58 [error] 14902#0: *3 "/root/nginx//html/index.html" is forbidden (13: Permission denied), client: 192.168.1.116, server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.119"
142019/02/20 10:03:58 [error] 14902#0: *3 "/root/nginx//html/index.html" is forbidden (13: Permission denied), client: 192.168.1.116, server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.119"
- 使用
mv
直接重命名日志(不会影响现在Nginx的日志写入的)
千万别用cp,不然丢日志的2333
1[root@centos7 logs]# ls
2access.log error.log nginx.pid nginx.pid.oldbin
3
4[root@centos7 logs]# mv access.log access.log$(date +"%Y-%m-%dT%H:%M:%SZ")
5
6[root@centos7 logs]# ls
7access.log2019-02-20T10:10:12Z error.log nginx.pid nginx.pid.oldbin
- 发送
USR1信号
给Nginx-master
kill -USR1 master.nginx.pid
或者
nginx -s reopen
1[root@centos7 sbin]# ./nginx -s reopen
2[root@centos7 sbin]# cd ../logs/
3[root@centos7 logs]# ls
4access.log access.log2019-02-20T10:10:12Z error.log nginx.pid nginx.pid.oldbin
- 如果你需要对
mv出来的日志
进一步操作,务必等一秒以上。
很多人认为,一发送指令到worker,worker就会立即执行。实际上并不是的。造成这种错觉,完全是因为CPU的运行太特么快了。实际上,master发送指令到worker的时候,只是做了一些标记,而worker实际上非常之繁忙,这可能就是为啥Nginx那么高效。当他完成一轮的事件调度之后,才会真正去执行master下达的指令。特别是业务量巨大的时候。一旦业务量大,这个时间就能扩大很多倍啦。
所以,你切割的时候,虽然你下达了reopen的命令,实际上worker可能压根还没有执行呢。23333
然后你设定的脚本就对日志进行下一步操作了,这可能就会造成日志有损坏或者遗漏。
1$ mv access.log access.log.old
2$ kill -USR1 master.nginx.pid 或者 nginx -s reopen
3$ sleep 1 #务必
4$ gzip access.log.old # do something with access.log.old
为什么改名字不会影响正在写入的文件?
实际上,在Linux/Unix里面,文件名只是inode的一个绰号/别称,实际上是靠inode来识别文件的。
inode是指在许多“类Unix文件系统”中的一种数据结构。每个inode保存了文件系统中的一个文件系统对象(包括文件、目录、设备文件、socket、管道, 等等)的元信息数据,但不包括数据内容或者文件名[1]。
表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。
正在写入的那些文件,系统内核其实已经拿到他的inode了,你改个名字压根是没有影响的。
1[root@centos7 ~]# touch test
2[root@centos7 ~]# ls -i test
334179485 test
4[root@centos7 ~]# mv test test2
5[root@centos7 ~]# ls -i test2
634179485 test2
当Nginx使用reopen
的时候,
寻找指定位置有没有默认的日志文件
没有,创一个
有,调用系统的内核,拿他的inode值
然后Nginx的日志记录就全用上面inode值。
自己想一想,感觉有点绕。