Nginx将日志记录到access.log.1而不是access.log。

4

我知道这个问题之前已经被问过了,但我认为这是一个不同的问题。

Nginx运行在www-data下:

$ ps -eo "%U %G %a" | grep nginx
root     root     nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data www-data nginx: worker process

/var/log/nginx/* 必须具备正确的权限:

$ ls -lah /var/log/nginx/
total 291M
drwxr-x---  2 www-data adm     4.0K Jul 25 06:25 .
drwxrwxr-x 14 root     syslog  4.0K Aug 28 06:25 ..
-rw-r-----  1 www-data adm      12K Aug 28 19:03 access.log
-rw-r-----  1 www-data adm     250M Aug 28 18:50 access.log.1

Logrotate会以正确的权限创建日志文件:

/var/log/nginx/*.log {
        ( ... )
        create 0640 www-data adm

当Nginx重启时,将日志记录到access.log,但在logrotate第一次运行后,将移动到access.log.1。之后,总是将日志记录到access.log.1,并且日志文件此后不再进行轮换。
编辑:正如评论中指出的那样,你看到access.log的访问时间比access.log.1晚,是因为我在那之前重新启动了nginx,只是为了自己确认,在发布这篇文章之前,确实重启nginx可以解决问题(直到下一次logrotate)。但在那之前,nginx已经将日志记录到access.log.1大约3周...
编辑2:这里是/etc/nginx/nginx.conf,其中包含头部和提及日志记录的部分。
user www-data;
worker_processes auto;
pid /run/nginx.pid;

( ... )

http {

        ( ... )
        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ( ... )

那为什么我们看到access.log的更新时间比acces.log.1晚呢?从你展示给我们的内容来看,它似乎是正常工作的。 - Alex
因为我刚刚重启了nginx,然后才执行了那个ls命令。 - user1950164
你可以把你的nginx配置文件的一部分贴出来吗?其中涉及到日志记录的内容。 - Neal Magee
1
@Neal,已完成,请检查。 - user1950164
2个回答

6

问题已解决。

我的问题几乎与这个问题相似,但不完全一样。在那个问题中,作者最终解决了问题,并说问题是因为“nginx没有在收到来自kill的-USR1信号时释放日志文件的文件句柄。长话短说,它无法重新加载日志文件的原因是/var/log/nginx文件夹的所有者与nginx工作进程(由web下运行的www-data拥有)不同。” 正如我们所看到的,这不是我的问题,因为我的权限是正确的。然而,我查看了我的logrotate日志和那个问题上的日志进行了比较,并找到了一些线索。在那个问题中,kill信号成功终止,但由于权限问题,nginx未释放文件句柄。在我的情况下,invoke-rc.d命令未能成功终止。Nginx的logrotate配置如下:

/var/log/nginx/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                invoke-rc.d nginx rotate >/dev/null 2>&1
        endscript
}

请注意postrotate脚本,它告诉nginx执行它的功能,对于另一个线程的作者来说,这个功能是kill信号。在我的logrotate日志中,我得到了以下错误(顺便说一下,你可以通过sudo logrotate -f -v /etc/logrotate.d/nginx命令强制执行logrotate):
( last two lines ... )
running postrotate script
error: error running shared postrotate script for '/var/log/nginx/*.log '

当我手动执行logrotate/nginx配置文件中看到的postrotate脚本时,出现错误:

$ invoke-rc.d nginx rotate
initctl: invalid command: rotate
Try `initctl --help' for more information.
invoke-rc.d: initscript nginx, action "rotate" failed.

这是Nginx中的一个漏洞。所以我用另一篇文章中提到的命令替换了该命令。因此,我的日志轮换/Nginx后旋转脚本在配置文件中如下:

postrotate
        kill -USR1 `cat /run/nginx.pid`
endscript

这解决了问题。


很高兴你找到了这个!我当时(非常模糊地)想到了与logrotate相关的东西,但很高兴问题已经解决了。 - Neal Magee
kill -USR1 cat /run/nginx.pid -- 它不会重新启动nginx吗?它只是重新打开日志文件,对吧? - vijay b
实际旋转日志的命令是“kill -USR1 /var/run/nginx.pid”。这不会终止Nginx进程,而是发送一个信号使其重新加载其日志文件。这将导致新请求被记录到已刷新的日志文件中。 - openHBP

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接