配置文件中的 NginX 日志轮换

配置文件中的 NginX 日志轮换

我试过了无需外部软件即可旋转日志文件的教程,但似乎不起作用,我的配置如下server {

if ($time_iso8601 ~ "^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})") {}
access_log /var/log/access-$year-$month-$day.log;
error_log /var/log/error-$year-$month-$day.log;

并创建文件,名为:

-rw-r--r-- 1 root root    0 May 28 17:46 error-$year-$month-$day.log

我的 NginX 版本:

nginx 版本:nginx/1.8.0

使用 OpenSSL 1.0.2a 构建 2015 年 3 月 19 日

已启用 TLS SNI 支持

配置参数:--prefix=/etc/nginx--conf-path=/etc/nginx/nginx.conf--sbin-path=/usr/bin/nginx--pid-path=/run/nginx.pid--lock-path=/run/lock/nginx.lock--user=http--group=http-http-log-path=/var/log/nginx/access.log--error-log-path=stderr--http-client-body-temp-path=/var/lib/nginx/client-body--http-proxy-temp-path=/var/lib/nginx/proxy--http-fastcgi-temp-path=/var/lib/nginx/fastcgi--http-scgi-temp-path=/var/lib/nginx/scgi--http-uwsgi-temp-path=/var/lib/nginx/uwsgi--with-imap--with-imap_ssl_module--with-ipv6 --带有-pcre-jit --带有-file-aio --带有-http_dav_module --带有-http_gunzip_module --带有-http_gzip_static_module --带有-http_realip_module --带有-http_spdy_module --带有-http_ssl_module --带有-http_stub_status_module --带有-http_addition_module --带有-http_degradation_module --带有-http_flv_module --带有-http_mp4_module --带有-http_secure_link_module --带有-http_sub_module

答案1

请参阅我上面的评论和 cpburnz 的理由,但如果您真的想继续:

您可以编写一个脚本,只将日志命令写入包含文件,并将当前日期硬编码。您可以将该include日期写入 nginx 配置文件,并且您的脚本会在将日志命令写入包含文件后重新启动或重新加载 nginx。

就像是:

#!/bin/bash

date=`date -Id`

cat > /etc/nginx/includes/log_by_date.inc <<EOF
access_log /var/log/access-${date}.log;
error_log /var/log/error-${date}.log;
EOF

/etc/init.d/nginx restart

您可以从 cron 运行该程序,很可能接近午夜。

另外,当然您还需要知道include /etc/nginx/includes/log_by_date.inc当前的日志命令在哪里。

答案2

根据那篇博客文章,

请注意,无法嵌入error_log 中的变量指令,因为如果无法写入文件,任何潜在错误都将无法被记录。

考虑到这一点,使用该 Nginx 方法不可能让错误日志以命名格式自动轮换error-$year-$month-$day.log


但是,设置错误日志的日志轮换并不是很困难。在以下位置创建一个简单的 shell (bash) 脚本/usr/local/bin/rotate_nginx_error_log.sh

#!/bin/sh
# /usr/local/bin/rotate_nginx_error_log.sh

# Get yesterday's date as YYYY-MM-DD
YESTERDAY=$(date -d 'yesterday' '+%Y-%m-%d') 

PID_FILE=/run/nginx.pid
LOG_FILE=/var/log/error.log
OLD_FILE=/var/log/error-$YESTERDAY.log

# Rotate yesterday's log.
mv $LOG_FILE $OLD_FILE

# Tell nginx to reopen the log file.
kill -USR1 $(cat $PID_FILE)

确保它具有可执行权限:

chmod +x /usr/local/bin/rotate_nginx_error_log.sh

然后向您的 crontab 添加一个 cronjob,以便在每晚午夜轮换日志:

0 0 * * * /usr/local/bin/rotate_nginx_error_log.sh

答案3

以下是我的服务器上的内容:

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

access_log /path/to/logs/nginx-access-$year-$month.log;

现在,有时$time_iso8601没有预期的格式,然后日志被写入一个名为的文件中nginx-access--.log(实际上,$year$month没有设置)。

因此我会考虑将这些行改为如下形式:

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

    access_log /path/to/logs/nginx-access-$year-$month.log;
}
else {
    access_log /path/to/logs/nginx-access-notime.log;
}

但是,正如@cpburnz 所说,您无法对错误日志执行此操作。

答案4

以下适用于 nginx 1.13.x 的访问日志

我们希望在“http”块中进行访问日志配置,但那里不允许使用“if”,因此改用“map”:

http {
    ...

    # Variable for access log filename date
    map $time_iso8601 $logdate {
        '~^(?<ymd>\d{4}-\d{2}-\d{2})'   $ymd;
        default                         'nodate';
    }

    log_format    acfmt    '$remote_addr "$request" "$query_string" "$http_referer" $request_time $status';
    access_log    'logs/access_${logdate}.log'    acfmt;

    ...
}

日志轮换在每天第一次请求时发生。与其他地方的文档相反,SIGUSR1 似乎不是必需的。

相关内容