写在前面

在前面学习Nginx目录结构的时候,可以发现它有一个logs目录,这是nginx日志的默认目录,里面包括访问日志(access.log)、错误日志(error.log)以及nginx.pid文件。nginx.pid文件就是nginx进程在启动后会将其pid写入这个文件中,这个没什么好学习的。现在学习的重点就是访问日志(access.log)和错误日志(error.log)。

访问日志(access.log)

访问日志文件(access.log)记录了每个用户对网站的访问请求,这个功能是ngx_http_log_module模块提供的,access.log文件可以帮助站长分析用户的浏览行为。

日志格式

首先打开access.log文件,查看一下其中的内容,如下所示:

可以看到日志文件的记录格式为“访问IP+访问时间+请求方法+请求路径+HTTP版本+状态码+代理信息”,这些都是我们从日志文件中能获取到的,但是这些肯定是可以定制的。

回忆之前的Nginx主配置文件nginx.conf,可以发现里面有如下一段代码:

也就是下面的代码片段其实就是用来定义日志文件的输出格式,这是默认的格式。其中log_format 是日志格式的关键参数,不能修改;main是为日志格式指定的标签,通过这个main标签可以在记录日志的时候选择指定的格式;之后的所有变量都是可以记录的日志信息,请注意所有的日志段都以空格进行分隔,且一行可以记录多个值:

1
2
3
#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

接下来通过一个表格来对上述日志格式中的参数进行介绍:
Nginx日志变量|说明|
:-:|:-:|
$remote_addr|记录访问网站的客户端IP地址|
$remote_user|远程客户端的名称|
$time_local|访问时间和时区|
$request|用户http请求起始行信息|
$status|http状态码,记录返回的状态|
$body_bytes_sent|服务器发给客户端响应的body字节数|
$http_referer|记录此次的请求是从哪个链接访问过来的,可以根据referer进行防盗链设置|
$http_user_agent|记录客户端访问信息,比如浏览器等|
$http_x_forwarded_for|当前端有代理服务时,设置web节点记录客户端地址的配置,此参数生效的前提是在代理服务器上也进行了相关的x_forwarded_for设置|

上面都是一些基本的日志格式配置变量,除此之外还有一些对日志进行优化的参数,这些参数一般使用默认的值即可,除非是有特殊的要求。这些配置语法格式如下所示:

1
2
3
access_log path [format [buffer=size [flush=time]] [if=condition];
access_log path format gzip[=level] [buffer=size] [flush=time] [if=condition];
access_log syslog:server=address[,parameter=value] [format [if=condition]];

其中buffer=size是存放访问日志的缓冲区大小;flush=time是将缓冲区的日志刷到硬盘的时间;gzip[=level]表示压缩的级别;[if=condition]表示其他条件;access_log off中的off表示不记录日志。


而访问日志文件的存储路径及使用格式则由access_log来控制:

1
#access_log  logs/access.log  main;

接下来将通过实战来学习access_log日志的使用。

第一步,去掉nginx.conf主配置文件中与log_format相关代码前面的注释,言外之意log_format相关代码必须放在http区块中。

第二步,在/usr/local/nginx/conf/vhost目录下新建一个think.com.conf文件,里面的代码为:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name www.think.com think.com;

location / {
root /usr/share/nginx/html/think;
index index.html index.htm index.php;
}

access_log /usr/local/nginx/logs/think.log main;
}

第三步,新建/usr/share/nginx/html/think目录,并在该目录下新建index.html文件,其中的代码为:

1
<p style="color:red">welcome to think.com!</p>

第四步,打开本地宿主机Windows系统内C:\Windows\System32\drivers\etc的文件,并在里面新增如下DNS映射:

1
192.168.73.100  www.think.com  think.com

第五步,使用nginx -t来检查语法,如果没有出现语法问题,就使用nginx -s reload命令来平滑重启nginx,之后在浏览器访问http://think.com连接,可以看到页面出现如下所示的信息:

之后在DOS命令中使用curl www.think.com命令来访问该链接。

第六步,查看/usr/local/nginx/logs/think.log文件,如下所示(日志内容没有的可以使用-来填充):

1
2
3
192.168.73.1 - - [18/Nov/2020:09:41:11 +0800] "GET / HTTP/1.1" 200 47 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "-"   # windows访问日志
192.168.73.1 - - [18/Nov/2020:09:41:11 +0800] "GET /favicon.ico HTTP/1.1" 404 555 "http://www.think.com/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "-" # windows访问日志
192.168.73.1 - - [18/Nov/2020:09:45:07 +0800] "GET / HTTP/1.1" 200 47 "-" "curl/7.55.1" "-" # Linux访问日志

当然了,开发者也可以在日志参数中添加buffer和flush,这样在高并发场景下能提升网站的访问性能。

第七步,修改/usr/local/nginx/conf/vhost/think.com.conf文件中的代码为:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name www.think.com think.com;

location / {
root /usr/share/nginx/html/think;
index index.html index.htm index.php;
}

access_log /usr/local/nginx/logs/think.log main gzip buffer=128k flush=5s;
}

之后进行语法检测和nginx平滑重启。

日志轮询切割

通过前面的学习,大家知道在默认情况下Nginx的访问日志都会存到access_log文件中,但是时间长了这个文件体积会变得很大,且不利于后续的分析,因此有必要对访问日志按照天或者小时进行分割,将其保存为不同的文件。通常情况下都是按照天为单位进行分割,除非在极特殊情况下才考虑按照小时,甚至是分钟的情况。

我们可以编写脚本来实现Nginx日志文件的切割,将正在写入的日志存入名称为“年月日-日期格式”的文件,之后再平滑重启Nginx,其实这个是可以添加到计划任务列表中的。

第一步,编写日志分割文件segmentation.sh。按照如下操作依次进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@envythink ~]# mkdir /usr/local/nginx/script
[root@envythink ~]# cd /usr/local/nginx/script
[root@envythink script]# vi segmentation.sh
[root@envythink script]# cat segmentation.sh
# !/bin/bash
Dateformat=`date +%Y%m%d`
Basedir="/usr/local/nginx"
Nginxlogdir="$Basedir/logs"
Logname="access"
[ -d $Nginxlogdir ] && cd $Nginxlogdir || exit 1
[ -f ${Logname}.log ] || exit 1
/bin/mv ${Logname}.log ${Dateformat}_${Logname}.log
$Basedir/sbin/nginx -s reload

第二步,将其添加到计划任务中,如下所示:

1
2
3
4
5
[root@envythink script]#  cat >>/var/spool/cron/root <<EOF
> 00 00 * * * /bin/sh /usr/local/nginx/script/segmentation.sh > /dev/null 2>&1
> EOF
[root@envythink script]# crontab -l
00 00 * * * /bin/sh /usr/local/nginx/script/segmentation.sh > /dev/null 2>&1

第三步,启动日志切割脚本,观察日志访问文件名称和信息是否写入正确:

1
2
3
4
5
6
7
8
[root@envythink script]# bash segmentation.sh 
[root@envythink script]# ll /usr/local/nginx/logs/
总用量 68
-rw-r--r-- 1 nobody root 40995 05月 18 09:41 20200518_access.log
-rw-r--r-- 1 root root 0 05月 18 10:26 access.log
-rw-r--r-- 1 nobody root 13463 05月 18 10:26 error.log
-rw-r--r-- 1 root root 6 05月 17 16:28 nginx.pid
-rw-r--r-- 1 root root 506 05月 18 09:45 think.log

错误日志(error.log)

错误日志文件(error.log)记录了Nginx自身运行故障信息和用户访问Nginx的日志信息。错误日志非常重要,它是后续进行故障排查和分析的重要手段,它是Nginx核心模块ngx_core_module中的参数,可以放在main区块或者不同的虚拟机中。

错误日志配置语法格式为:

1
2
error_log       file        level
关键字 日志文件 错误级别

打开Nginx主配置文件nginx.conf,可以发现里面有如下一段代码:

同样error_log是错误日志关键字,不能修改;file是日志存放文件路径,可以是任意路径;level是错误级别,错误级别按照严重性从小到大依次为:debug–>info–>notice–>warn–>error–>crit–>alert–>emerg等8个级别,注意级别越高意味着记录的信息越少。一般情况下会使用warn、error和crit这三个级别,默认级别是crit。合理使用日志级别,可以减少磁盘I/O的消耗和提升系统性能。

日志过滤

在实际工作中,并不是所有的日志信息都需要记录下来,如对于某些负载均衡健康节点的检查,或者是特定文件的访问记录。而且频繁的日志写入会消耗大量的I/O,降低服务器的性能,因此合理对日志文件的记录信息进行过滤也是优化Nginx的一种手段。

我们以之前的think.com.conf为例进行介绍,在该文件中新增如下配置:

1
2
3
location ~.*\.(js|css|jpg|JPG|jpeg|JPEG|bmp|gif|GIF)$ {
access_log off; #日志过滤策略
}

注意代码的放置位置,如下所示:

之后进行语法检查和平滑重启Nginx,对上述配置的策略进行测试,发现没问题。

日志权限设置

由于日志文件的特殊性,因此需要给日志目录设置特殊权限,只有特定的人才能访问,如超级管理员root用户:

1
2
[root@envythink logs]# chown -R root.root /usr/local/nginx/logs
[root@envythink logs]# chmod 700 /usr/local/nginx/logs

上面第一行代码表示将logs目录的属主和属组设置为root用户;第二行代码表示只有root用户才能对logs目录进行访问和修改操作。

实时日志解析

ngxtop实时日志解析

开发者可以使用ngxtop来实时解析Nginx日志,并将处理结果输出到终端,其功能非常类似于Centos系统命令top。

第一步,安装ngxtop软件。这里比较推荐用户直接使用源码进行安装,相应的步骤如下所示:

1
2
3
4
5
yum install python3 -y
wget https://github.com/lebinh/ngxtop/archive/master.zip -O ngxtop-master.zip
unzip ngxtop-master.zip
cd ngxtop-master
python3 setup.py install

第二步,配置Nginx主配置文件。