直接在nginx配置文件中配置切分日志

最近我们nginx上来容器,日志实时传走,但是本地还需要留一份另作他用,这样用原来logrotate或cronolog方式切分日志就很麻烦了, 我就开始再nginx配置文件中想办法。

发现可以利用 $time_iso8601 变量来切分日志, 它就是每条日志的时间戳,取它的年、月、日、小时做变量,生成带时间戳得日志文件。就可以每小时、每天输出到不同文件里了。

  • 请注意,不可能在error_log指令中嵌入变量,因为如果无法写入文件,则无法记录任何潜在错误。 这种方法只适用于access得日志

time_iso8601 时间格式

这是一个显示 $time_iso8601格式的示例:

1
2019-05-04T18:12:02+02:00

配置方法

所有要做的就是使用“if”块来使用正则表达式分割所需的数据并设置时间变量。
要按日拆分日志,可以在服务器块中使用以下代码段:

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

access_log /var/log/nginx/$year-$month-$day-access.log;

或者,我们也可以使用Perl兼容语法进行命名正则表达式捕获:

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

access_log /var/log/nginx/$year-$month-$day-access.log;

要创建小时,分钟和秒的变量,我们可以使用以下代码段:

1
2
3
4
5
6
7
8
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文件路径包含变量时,缓冲写入不起作用,因此无法动态gzip日志。

  • if 模块无法再全局变量中使用,只能在 server {} 下 配置,

例子

所以我的用法是, 每个域名都按小时单独生成自己的文件。 再外面写好配置, 每个server里include日志得配置即可。

再nginx配置目录中生成一个配置文件

1
2
3
4
5
6
7
8
9
vim log_format.conf

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;
}
access_log /home/nginx/logs/${server_name}_${year}-${month}-${day}-${hour}_access.log main;

每个Server中include这个配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream test-shining.com {
server 192.168.1.2:9250;
}

################## server name ################
server {
listen 80;
server_name test.shining.com;
include log_format.conf;
proxy_connect_timeout 30; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 600; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_send_timeout 600; #后端服务器数据回传时间(代理发送超时)
location / {
include proxy_set_header.conf;
proxy_pass http://test-shining.com.com/;
proxy_redirect off;
}
}
感谢您的支持!