Nginx 日志管理、配置及切割

安素 2019年07月27日 960次浏览

Nginx日志

Nginx日志描述

日志对于统计排错和日常服务器维护来说是非常有利的。通过访问日志,你可以得到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息;通过错误日志,你可以得到系统某个服务或server的性能瓶颈等。因此,将日志好好利用,你可以得到很多有价值的信息。

Nginx日志格式

打开nginx.conf配置文件

main 日志格式
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      '$connection $upstream_addr'
		      'upstream_response_time $upstream_response_time request_time $request_time';
# 日志生成的到Nginx根目录/var/log/nginx/access.log文件,默认使用"main"日志格式,也可以自定义格式。
access_log  /var/log/nginx/access.log  main;

日志参数明细表:

字段说明
$remote_addr客户端的ip地址(代理服务器,显示代理服务ip)
$remote_user用于记录远程客户端的用户名称(一般为"-")
$time_local用于记录访问时间和时区
$request用于记录请求的url以及请求方法
$http_host请求地址,即浏览器中你输入的地址(IP或域名)
$status响应状态码,例如:200成功、404页面找不到等
$body_bytes_sent给客户端发送的文件主体内容字节数
$http_user_agent用户所使用的代理(一般为浏览器)
$http_x_forwarded_for可以记录客户端IP,通过代理服务器来记录客户端的ip地址
$http_referer可以记录用户是从哪个链接访问过来的
$upstream_statusupstream状态
$ssl_protocolSSL协议版本
$ssl_cipher交换数据中的算法
$upstream_addr后台upstream的地址,即真正提供服务的主机地址
$request_time整个请求的总时间
$upstream_response_time请求过程中,upstream响应时间

Nginx日志配置

access_log  /var/log/nginx/blog/blog.ansudevops.com-$logdate-access.log  main;
error_log  	/var/log/nginx/blog/blog.ansudevops-error.log  info;
open_log_file_cache max=10;

Nginx日志分隔

nginx日志分割是很常见的运维工作,从nginx 0.7.6版本开始access_log的路径配置可以包含变量,我们可以利用这个特性来实现日志分割。例如,我们想按天来分割日志,那么我们可以这样配置:

access_log logs/access-$logdate.log main;

那么接下来的问题是我们怎么提取出$logdate这个变量? 可以使用正则表达式来获取所需时间的数据。

if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})")
{
    set $year $1;
    set $month $2;
    set $day $3;
    set $hour $4;
    set $minutes $5;
    set $seconds $6;
}

access_log logs/access-$year-$month-$day-$hour:$minutes:$seconds.log main;

也可以使用Perl语法来捕获,如下:

if ($time_iso8601 ~ "^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})") {}

access_log /data/logs/nginx/www.ttlsa.com-$year-$month-$day-access.log;

上面的方法有两个问题:一是如果if条件不成立,那么$year、$month和$month这三个变量将不会被设置,那么日志将会记录到access-$year-$month-$day.log这个文件中;二是if只能出现在server和location块中,而access_log通常会配置到顶层的http块中,这时候if就不适用。

如果要在http块中设置access_log,更好的方法是使用map指令:

map $time_iso8601 $logdate {
  '~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd;
  default                       'date-not-found';
}

access_log logs/access-$logdate.log main;

map指令通过设置默认值,保证$logdate始终有值,并且可以出现在http块中,完美地解决了if指令的问题。

最后,为了提高日志的效率,建议配置open_log_file_cache,完整的日志分割配置如下:

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

map $time_iso8601 $logdate {
  '~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd;
  default                       'date-not-found';
}

access_log logs/access-$logdate.log main;
open_log_file_cache max=10;