nginx 配置日志滚动

Ever since I discovered PostgreSQL allowed to embed variables in log_filename allowing to split logs without using logrotate or cronolog, I've been wanting to do the same with Nginx.

As it turns out, it's not only possible but also pretty easy to achieve, since Nginx introduced the possibility to use variables in access_log directives (added in 0.7.4), and the $time_iso8601 variable providing time in ISO 8601 format (added in 0.9.6).

Please note, that it's not possible to embed variables in error_log directives, as any potential error would not be able to be logged if the file cannot be written.

Here is an example showing $time_iso8601 format:

2014-05-04T18:12:02+02:00

All there is to do is use an "if" block to split required data using a regular expression and set time variables.

For splitting logs by day, one would use the following snippet in the server block:

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;

Alternatively, we can also use the Perl compatible syntax for named regular expression capture:

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

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

To also create variables for hours, minutes and seconds, we can use the following snippet:

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;
}

Lastly, and I cannot stress it enough, please make sure the Nginx workers have proper permissions to access and write to the log directory.

This method is currently used in production on a busy Nginx server and has been running flawlessly for almost a month now. The only drawback is that buffered writes do not work when the access_log file path contain variables, so it isn't possible to gzip logs on the fly.

实际上,,,,上面并不是滚动的,因为nginx日志是追加写模式,,,如果要日志滚动,,,需要借助

logrotate,这个工具:

logrotate机制&原理

centos系统中默认安装logrotate,logrotate主配置文件:/etc/logrotate.conf,其中定义了系统默认的logrotate规则,当系统中安装了RPM 软件包时,使用include定义其子配置文件的位置:/etc/logrotate.d/*,include选项十分重要,一些应用把日志转储参数存放在/etc/logrotate.d ,典型的应用有:apache,nginx,cron,syslog等,这样,只要管理一个 /etc/logrotate.conf 文件就可以了。

使用时配合crontab定期执行logrotate命令,cron的主配置文件/etc/anacrontab中定义了crontab的默认执行规则,其中系统自带的每1天执行的cron计划配置文件放在/etc/cron.daily/目录下,在该目录下的logrotate文件内容如下:

#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi

该脚本每天定时执行一次,即系统默认的logrotate时间计划。如果想更改系统默认的logrotate时间计划,可以将该文件挪走,然后在crontab中指定自己的时间计划,如:

#每两天执行一次系统日志切割
* * */2 * * /usr/sbin/logrotate -f /etc/logrotate.conf

详细配置

/var/log/nginx/*.log /var/log/tomcat/*log {   # 可以指定多个路径
    daily                      # 日志轮询周期,weekly,monthly,yearly
    rotate 30                  # 保存30天数据,超过的则删除
    size 100M                 # 超过100M时分割,单位K,M,G,优先级高于daily
    dateext
    dateformat -%Y-%m-%d       # 切割后文件格式:igame_qq_com_access.3.log-2019-03-13.gz
    compress                   # 切割后压缩,也可以为nocompress
    delaycompress              # 切割时对上次的日志文件进行压缩
    dateext                    # 日志文件切割时添加日期后缀
    missingok                  # 如果没有日志文件也不报错
    notifempty                 # 日志为空时不进行切换,默认为ifempty
    create 640 nginx nginx     # 使用该模式创建日志文件
    sharedscripts              # 所有的文件切割之后只执行一次下面脚本
    postrotate
        [! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`  #nginx进程pid文件
    endscript
}

原文链接:https://www.cambus.net/log-rotation-directly-within-nginx-configuration-file/

原文作者:Nginx

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区