文章原创于公众号:程序猿周先森。本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号。
众所周知,线上如果出现事故我们通常都是查看日志去进行问题定位并且进行修复。使用好Nginx日志有利于我们线上进行修复异常问题。在Nginx中日志主要分为两种:accesslog(访问日志)和errorlog(错误日志)。通过查看accesslog我们可以查看用户ip,浏览器信息及请求时间等信息,通过查看errorlog我们可以查看线上出错的具体信息,可以帮助我们定位异常的原因。本篇文章主要带领大家详细了解Nginx如何配置日志。本文将会涉及到的日志配置指令:
- access_log
- log_format
- openlogfile_cache
- lognotfound
- log_subrequest
- rewrite_log
- error_log
access_log指令
首先,我们可以先看看accesslog指令。accesslog命令可以配置访问日志。我们可以先看下access_log指令的语法结构:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; # 设置访问日志access_log off; # 关闭访问日志
我们先来看看语法结构中的参数的含义:
path: 指定日志的存放位置format: 指定日志的格式,非必填,默认为预定义的combinedbuffer:指定日志写入时的缓存大小,非必填,默认64kgzip: 日志写入前先进行压缩flush: 设置缓存的有效期if: 设置条件判断,当天剑成立时才会写入日志off: 值为off表示不开启日志,值为on表示开启日志
accesslog指令可以使用于http根节点,虚拟服务器server节点,上下文配置location以及limitexcept中。无法在其他作用域使用accesslog指令,否则Nginx会报错。我们可以看一个简单的配置accesslog的小例子:
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 '$remoteaddr - $remoteuser [$timelocal] ' '"$request" $status $bodybytessent ' '"$httpreferer" "$httpuser_agent"';
但是如果不想使用combined日志格式,就可以使用logformat指令来自定义格式内容。logformat指令需要在http节点下进行配置。我们先来看下log_format指令的语法结构:
log_format name [escape=default|json] string;
我们先来看看log_format的参数对应的用法:
name: 指定日志格式名称,因为在access_log指令中需要指定日志格式escape: 设置字符编码方式,可以选择default或者jsonstring: 要写入日志的内容,可以有多个参数,可以使用Nginx变量。
下面贴一下log_format指令中常用的一些变量:
我们可以接着看个自定义日志格式的小案例:
http { logformat main '$remoteaddr - $remoteuser [$timelocal] "$request" ' '"$status" $bodybytessent "$http_referer" ' '"$httpuseragent" "$httpxforwarded_for" ' '"$gzipratio" $requesttime $bytessent $requestlength'; server { server_name www.niyueling.cn; access_log /root/.pm2/logs/niyueling.log main; } }
openlogfile_cache指令
对于网站的访问记录,通常操作都是首先打开日志文件,然后写入日志记录,最后关闭文件。默认情况下日志文件不进行缓存的,我们可以通过openlogfilecache指令设置日志文件缓存。openlogfilecache指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。我们先看下openlogfile_cache指令的语法结构:
openlogfilecache max=X [inactive=time] [minuses=N] [valid=time];openlogfile_cache off;
首先先贴下参数对应的含义:
max: 设置缓存中的最大文件描述符inactive: 设置存活时间min_uses: 在存活时间内,日志文件最少被使用几次后将日志文件描述符写入缓存。valid: 设置检查频率off: 禁用日志缓存
可以看一个简单配置日志缓存的小例子:
openlogfilecache max=100 inactive=30s valid=5m minuses=3;
lognotfound指令
这个命令用于指定是否在error_log错误日志中记录不存在的错误,如文件不存在等。默认值为是。我们可以先看下语法结构:
lognotfound on | off;
lognotfound指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。设置为on表示记录不存在的错误,设置为off表示不记录不存在的错误。
log_subrequest指令
logsubrequest指令用于指定在accesslog访问日志中是否记录子请求的访问记录。默认情况为不记录,贴下语法结构:
log_subrequest on | off;
log_subrequest指令可以配置在http根节点,虚拟服务器server节点以及上下文location中。设置为on表示记录子请求访问记录,设置为off表示不记录子请求访问记录。
rewrite_log指令
rewritelog指令由ngxhttprewritemodule模块提供服务,用来记录日志重写。可以在error_log错误日志中记录notice级别的重写日志。默认是不启用状态,贴下语法结构:
rewrite_log on | off;
rewrite_log指令可以配置在http根节点,虚拟服务器server节点以及上下文location以及if条件判断中。设置为on表示在错误日志中记录notice级别的重写日志,设置为off表示在错误日志中不记录notice级别的重写日志。
error_log指令
errorlog指令顾名思义,就是用来指定错误日志的,一般来说线上出现bug都是通过errorlog日志来定位问题所在而加以解决的。errorlog指令可以记录服务器和请求处理过程中的错误信息。我们先看下errorlog指令的语法结构:
error_log file [level];
参数含义其实很容易可以理解:
file: error_log 存放路径level: 日志级别,只有日志级别高于指定级别才会记录到error_log中error_log指令可以配置在http节点,main节点,虚拟服务器server节点以及上下文location中。
日志切割
Nginx记录日志默认情况下是访问日志全部写入accesslog中,错误日志全部写入errorlog中。这样会导致日志文件原来越大,不利于查看日志分析问题异常,所以我们可以将日志以日期为单位进行切割。首先需要写一个脚本实现Nginx按天切割:
日志保存位置
base_path='/root/.pm2/logs/niyueling.log'
获取当前年信息和月信息
log_path=$(date -d yesterday +"%Y%m")
获取昨天的日信息
day=$(date -d yesterday +"%d")
按年月创建文件夹
mkdir -p $basepath/$logpath
备份昨天的日志到当月的文件夹
mv $basepath/access.log $basepath/$logpath/access$day.log
输出备份日志文件名
echo $basepath/$logpath/access_$day.log
通过Nginx信号量控制重读日志
kill -USR1 cat /opt/nginx/logs/nginx.pid
然后给脚本添加可执行权限,最后添加Linux定时任务:
crontab -e
每天凌晨两点半进行日志分割
0 02 0 * /root/.pm2/logs/splitLog.sh
重启Linux定时任务
crond restart
通过上面的讲解差不多可以知道Nginx对于日志是如何进行配置的,实际上就是通过logformat配置日志格式,如果logformat中使用了Nginx变量,则可以通过openlogfilecache指令来设置缓存提高性能。然后通过accesslog进行设置访问日志,通过error_log指令设置错误日志。最后实现定时任务定时切割每天的日志,有利于我们后期维护。
如果喜欢我的文章,欢迎关注个人公众号:程序猿周先森。