Nginx 日志分为两种,一种是错误日志(error log),记录 Nginx 运行过程中遇到的异常,一种是访问日志(access log),记录的是 WEB 服务被用户访问时留下的一些信息。例如哪些文件被访问过、Nginx 如何响应、用户使用的 IP 地址等等。
要开启访问日志,在 nginx.conf 文件中的 http 或 server 字段添加以下参数:
access_log log_file log_format;
其中 log_file 为日志要保存的路径,log_format 为日志记录格式。记录格式可以采用默认,也可以在 http 字段中自定义:
log_format format_name 'set_of_variables_to_define_format';
其中 format_name 表示这个日志格式的名称,在引用时需要用到。set_of_variables_to_define_format 表示此日志格式所记录的信息及顺序。
访问日志格式详解可见此官方文档。
小提示:
• server 字段如果未设置访问日志,则该 server 访问日志会继承 http 字段中的设置。
• server 字段中的 location 字段也可单独设置访问日志。
• 每个字段中都可以设置多个不同格式的日志。
要开启错误日志,在 nginx.conf 文件中 http 字段添加以下参数:
error_log log_file log_level;
其中 log_file 为日志要保存的路径,log_level 为要记录的日志级别,设置某个级别后,该级别及以上级别的错误日志都将被记录。
错误日志共分为 8 个级别,从高到低分别是:
• emerg: 紧急,可能导致服务不可用。
• alert: 告警,严重问题告警。
• crit: 严重,需要关注的严重问题。
• error: 错误,发生错误,例如某个页面处理错误。
• warn: 警示,可能需要关注的问题。
• notice: 通知,简单的通知日志,大多数情况下可以忽略。
• info: 信息,运行中的普通信息。
• debug: 调试,用于分析错误的调试信息。
通常配置情况下,Nginx 所有访问日志存放在同一个 log 文件中,时间一长,日志文件将变得巨大,导致备份、分析都不方便。因此需要将日志按一定时间间隔分开存放,例如每天、每月或其它时间间隔。要实现这个目的主要由两种方式:
• 一种是在 nginx.conf 配置文件中进行配置
• 一种是使用系统定时任务脚本定期对日志进行分割
3.1 在 nginx.conf 中配置日志存放规则
在这里,我们需要用到 map 指令,map 指令是由 ngx_http_map_module 模块提供的,默认情况下安装 nginx 都会安装该模块。map 指令只能位于 nginx.conf 的 http 字段内。具体代码如下:
http {
......
......
#设置日志按日期或月份滚动
map $time_iso8601 $year {
default 'date';
'~^(?<yyyy>d{4})-' $yyyy;
}
map $time_iso8601 $month {
default 'not';
'~^d{4}-(?<mm>d{2})-' $mm;
}
map $time_iso8601 $day {
default 'found';
'~^d{4}-d{2}-(?<dd>d{2})' $dd;
}
#日志按年-月-日名称格式存放
#map $time_iso8601 $logfile_date {
# default 'date-not-found';
# '~^(?<year>d{4})-(?<month>d{2})-(?<day>d{2})' $year-$month-$day;
#}
#日志按年-月名称格式存放
map $time_iso8601 $logfile_month {
default 'date-not-found';
'~^(?<year>d{4})-(?<month>d{2})' $year-$month;
}
}
使用 map 定义好变量之后,即可在配置访问日志记录时使用该变量:
access_log logs/$logfile_month.access.log;
access_log 指令可以在 http 字段内,也可以在 server 字段内。
配置好后,如果遇到日志文件并没有生成的问题,则可能是 logs 目录权限导致,需要赋予 logs 目录 nginx 启动用户的权限(这是在日志路径中使用变量的一些限制,参考官方:Nginx 日志模块说明)。假设 nginx 以 www 组的 www 用户启动,则:
chown -R www:www logs/
最终生成的日志效果如下:
关于在日志路径中使用变量的限制,包括:
日志文件路径可以包含变量 (0.7.6+),但这类设置存在以下限制:
• 启动 Nginx worker 进程的用户必须拥有日志目录的写权限;
• 写缓存将不起作用;
• 每条日志写入都会造成日志文件的打开和关闭。然而,由于频繁读写的文件的文件描述符可能会被存储与缓存中,根据 open_log_file_cache 指令的时间参数设置,日志可能继续写入到旧文件中;
• 每条日志写入时都会检测站点根目录是否存在,如果不存在则日志不会创建,因此最好在 access_log 设置的同级别指令段中指定站点根目录,例如:
server {
root /spool/vhost/data/$host;
access_log /spool/vhost/logs/$host;
...
也有使用 if 判断语句来定义上面的变量,但据说可能引发问题,建议使用 map 指令。
3.2 通过定时脚本分割日志
创建日志分割脚本 splitLog.sh :
# /bin/bash
# 日志保存位置
base_path='/usr/local/nginx/logs/'
# 获取当前年信息和月信息
log_path=$(date -d yesterday +"%Y%m")
# 获取昨天的日信息
day=$(date -d yesterday +"%d")
# 按年月创建文件夹
mkdir -p $base_path/$log_path
# 备份昨天的日志到当月的文件夹
mv $base_path/access.log $base_path/$log_path/access_$day.log
# 输出备份日志文件名
# echo $base_path/$log_path/access_$day.log
# 通过Nginx信号量控制重读日志
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
添加linux定时任务:
crontab -e
# 每天0时1分进行日志分割(建议在02-04点之间,系统负载小)
01 00 * * * /usr/local/nginx/logs/splitLog.sh
重启Linux定时任务:
crond restart
如果提示以下错误 crond: can't lock /var/run/crond.pid, otherpid may be 4141:资源暂时不可用,删除 /var/run/crond.pid 重新执行命令即可。
作者:李凌