众所周知,线上如果出现事故我们通常都是查看日志去进行问题定位并且进行修复。使用好Nginx日志有利于我们线上进行修复异常问题。在Nginx中日志主要分为两种:access\_log(访问日志)和error\_log(错误日志)。通过查看access\_log我们可以查看用户ip,浏览器信息及请求时间等信息,通过查看error\_log我们可以查看线上出错的具体信息,可以帮助我们定位异常的原因。本篇文章主要带领大家详细了解Nginx如何配置日志。本文将会涉及到的日志配置指令: * access\_log * log\_format * open\_log\_file\_cache * log\_not\_found * log\_subrequest * rewrite\_log * error\_log **access\_log指令** 首先,我们可以先看看access\_log指令。access\_log命令可以配置访问日志。我们可以先看下access\_log指令的语法结构: * access\_log path \[format \[buffer=size\] \[gzip\[=level\]\] \[flush=time\] \[if=condition\]\]; # 设置访问日志 * access\_log off; # 关闭访问日志 我们先来看看语法结构中的参数的含义: * path: 指定日志的存放位置 * format: 指定日志的格式,非必填,默认为预定义的combined * buffer:指定日志写入时的缓存大小,非必填,默认64k * gzip: 日志写入前先进行压缩 * flush: 设置缓存的有效期 * if: 设置条件判断,当天剑成立时才会写入日志 * off: 值为off表示不开启日志,值为on表示开启日志 access\_log指令可以使用于http根节点,虚拟服务器server节点,上下文配置location以及limit\_except中。无法在其他作用域使用access\_log指令,否则Nginx会报错。我们可以看一个简单的配置access\_log的小例子: * access\_log /root/.pm2/logs/niyueling.log buffer=32k gzip flush=5m 这个配置指定日志存储路径为/root/.pm2/logs/niyueling.log,日志使用默认格式combined。日志缓存大小为32k,日志写入前会进行gzip压缩,缓存有效期为5分钟。 **log\_format指令** 刚才有讲过如果未指定日志格式,Nginx会使用combined日志格式为默认格式。combined日志格式默认使用格式为: * log\_format combined '![remote_addr -](https://math.jianshu.com/math?formula=remote_addr%20-)remote\_user \[![time_local] ' '"](https://math.jianshu.com/math?formula=time_local%5D%20'%20'%22)request" ![status](https://math.jianshu.com/math?formula=status)body\_bytes\_sent ' '"![http_referer" "](https://math.jianshu.com/math?formula=http_referer%22%20%22)http\_user\_agent"'; 但是如果不想使用combined日志格式,就可以使用log\_format指令来自定义格式内容。log\_format指令需要在http节点下进行配置。我们先来看下log\_format指令的语法结构: * log\_format name \[escape=default|json\] string; 我们先来看看log\_format的参数对应的用法: * name: 指定日志格式名称,因为在access\_log指令中需要指定日志格式 * escape: 设置字符编码方式,可以选择default或者json * string: 要写入日志的内容,可以有多个参数,可以使用Nginx变量。 下面贴一下log\_format指令中常用的一些变量: ![](//upload-images.jianshu.io/upload_images/17781779-87221331fb643b29.jpeg?imageMogr2/auto-orient/strip|imageView2/2/w/800/format/webp) file 我们可以接着看个自定义日志格式的**小案例**: http { log\_format main '![remote_addr -](https://math.jianshu.com/math?formula=remote_addr%20-)remote\_user \[![time_local] "](https://math.jianshu.com/math?formula=time_local%5D%20%22)request" ' '"![status"](https://math.jianshu.com/math?formula=status%22)body\_bytes\_sent "![http_referer" ' '"](https://math.jianshu.com/math?formula=http_referer%22%20'%20'%22)http\_user\_agent" "![http_x_forwarded_for" ' '"](https://math.jianshu.com/math?formula=http_x_forwarded_for%22%20'%20'%22)gzip\_ratio" ![request_time](https://math.jianshu.com/math?formula=request_time)bytes\_sent $request\_length'; server { server\_name [www.niyueling.cn](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.niyueling.cn); access\_log /root/.pm2/logs/niyueling.log main; } } **open\_log\_file\_cache指令** 对于网站的访问记录,通常操作都是首先打开日志文件,然后写入日志记录,最后关闭文件。默认情况下日志文件不进行缓存的,我们可以通过open\_log\_file\_cache指令设置日志文件缓存。open\_log\_file\_cache指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。我们先看下open\_log\_file\_cache指令的语法结构: * open\_log\_file\_cache max=X \[inactive=time\] \[min\_uses=N\] \[valid=time\]; * open\_log\_file\_cache off; 首先先贴下参数对应的含义: * max: 设置缓存中的最大文件描述符 * inactive: 设置存活时间 * min\_uses: 在存活时间内,日志文件最少被使用几次后将日志文件描述符写入缓存。 * valid: 设置检查频率 * off: 禁用日志缓存 可以看一个简单配置日志缓存的小例子: * open\_log\_file\_cache max=100 inactive=30s valid=5m min\_uses=3; **log\_not\_found指令** 这个命令用于指定是否在error\_log错误日志中记录不存在的错误,如文件不存在等。默认值为是。我们可以先看下语法结构: * log\_not\_found on | off; log\_not\_found指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。设置为on表示记录不存在的错误,设置为off表示不记录不存在的错误。 **log\_subrequest指令** log\_subrequest指令用于指定在access\_log访问日志中是否记录子请求的访问记录。默认情况为不记录,贴下语法结构: * log\_subrequest on | off; log\_subrequest指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。设置为on表示记录子请求访问记录,设置为off表示不记录子请求访问记录。 **rewrite\_log指令** rewrite\_log指令由ngx\_http\_rewrite\_module模块提供服务,用来记录日志重写。可以在error\_log错误日志中记录notice级别的重写日志。默认是不启用状态,贴下语法结构: * rewrite\_log on | off; rewrite\_log指令可以配置在http根节点,虚拟服务器server节点以及上下文location以及if条件判断中。设置为on表示在错误日志中记录notice级别的重写日志,设置为off表示在错误日志中不记录notice级别的重写日志。 **error\_log指令** error\_log指令顾名思义,就是用来指定错误日志的,一般来说线上出现bug都是通过error\_log日志来定位问题所在而加以解决的。error\_log指令可以记录服务器和请求处理过程中的错误信息。我们先看下error\_log指令的语法结构: * error\_log file \[level\]; 参数含义其实很容易可以理解: * file: error\_log 存放路径 * level: 日志级别,只有日志级别高于指定级别才会记录到error\_log中 * error\_log指令可以配置在http节点,main节点,虚拟服务器server节点以及上下文location中。 **日志切割** Nginx记录日志默认情况下是访问日志全部写入access\_log中,错误日志全部写入error\_log中。这样会导致日志文件原来越大,不利于查看日志分析问题异常,所以我们可以将日志以日期为单位进行切割。首先需要写一个脚本实现Nginx按天切割: > **日志保存位置** * base\_path='/root/.pm2/logs/niyueling.log' > **获取当前年信息和月信息** * log\_path=$(date -d yesterday +"%Y%m") > **获取昨天的日信息** * day=$(date -d yesterday +"%d") > **按年月创建文件夹** * mkdir -p ![base_path/](https://math.jianshu.com/math?formula=base_path%2F)log\_path > **备份昨天的日志到当月的文件夹** * mv ![base_path/access.log](https://math.jianshu.com/math?formula=base_path%2Faccess.log)base\_path/![log_path/access_](https://math.jianshu.com/math?formula=log_path%2Faccess_)day.log > **输出备份日志文件名** * echo ![base_path/](https://math.jianshu.com/math?formula=base_path%2F)log\_path/access\_$day.log > **通过Nginx信号量控制重读日志** * kill -USR1 `cat /opt/nginx/logs/nginx.pid` **然后给脚本添加可执行权限,最后添加Linux定时任务:** * crontab -e **每天凌晨两点半进行日志分割** * 30 02 0 \* \* \* /root/.pm2/logs/splitLog.sh \*\* 重启Linux定时任务\*\* * crond restart 通过上面的讲解差不多可以知道Nginx对于日志是如何进行配置的,实际上就是通过log\_format配置日志格式,如果log\_format中使用了Nginx变量,则可以通过open\_log\_file\_cache指令来设置缓存提高性能。然后通过access\_log进行设置访问日志,通过error\_log指令设置错误日志。最后实现定时任务定时切割每天的日志,有利于我们后期维护。