为什么每次使用logrotate时Apache都会导致段错误?

每次运行logrotate时,Apache/2.4.7 (Ubuntu)都会发生段错误并且无法重新启动。
[Wed Sep 10 06:35:54.266018 2014] [mpm_event:notice] [pid 20599:tid 140630283466624] AH00493: SIGUSR1 received.  Doing graceful restart
[Wed Sep 10 06:35:54.885118 2014] [core:notice] [pid 20599] AH00060: seg fault or similar nasty error detected in the parent process
我的Apache日志轮转脚本如下:
/var/log/apache2/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        /usr/sbin/apachectl graceful
    endscript
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi; \
    endscript
}

/srv/apache/log/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        /usr/sbin/apachectl graceful
    endscript
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi; \
    endscript
}
我将默认日志保存在/var/log/apache2目录下,但是我将特定虚拟主机的日志(对于此服务器上托管的三个不同虚拟主机)保存在/srv/apache/log目录中(例如mysite1_error.log,mysite1_access.log,mysite2_error.log,mysite2_access.log...)。 /etc/apache2/apache.conf文件的相关部分:
#/etc/apache2/apache.conf
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel trace8   # I set to try and get more info about this problem.
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
在我的虚拟主机配置文件中,例如/etc/apache2/sites-enabled/mysite1.conf,我有这样的一行代码:

where export APACHE_LOG_DIR=/var/log/apache2$SUFFIX

#/etc/apache2/sites-enabled/mysite1.conf
LogLevel debug
ErrorLog  /srv/apache/log/mysite1_error.log
CustomLog /srv/apache/log/mysite2_access.log combined
其他网站也是类似的情况。 有人知道为什么logrotate会导致这个崩溃吗? 还有一件事: 以root权限手动强制执行logrotate:
logrotate -v -f /etc/logrotate.d/apache2

不会导致段错误,但我知道这是logrotate的问题,因为我尝试过更改时间(每周、每天),而段错误总是在日志被轮转时发生。

如何随时复现

# Set a crontab to run each minute (simulating cron.daily run of logrotate)
crontab -e
*/1 * * * * root /usr/sbin/logrotate -v -f /etc/logrotate.d/apache2 > /home/myuser/logrotate.log 2>&1

终于

如果我在/etc/logrotate.d/apache中注释掉/srv/apache/log/*.log旋转块,段错误也不会发生。


从错误消息来看,/usr/sbin/apachectl graceful 似乎是罪魁祸首(理论上,/etc/logrotate.d/httpd-prerotate 中的脚本也是可能的候选人)。您可以通过手动运行 /usr/sbin/apachectl graceful 来确认吗? 当这种情况发生在 Apache 的全局错误日志(或全局系统日志)中时,是否有更多的提示?也许当您在 <VirtualHost> 内部增加 LogLevel 时,不仅在全局范围内增加? - Nils Toedtmann
在命令行手动执行/usr/sbin/apachectl graceful不会引起任何问题(还要注意,这一行最初是/etc/init.d/apache2 reload > /dev/null,但在遇到段错误后,我根据网上的建议改成了apachectl,显然并没有解决问题)。apache.conf文件中已经将全局的日志级别设置为最高级别trace8 - fpghost
只是为了排除这个可能性:/etc/logrotate.d/httpd-prerotate 不存在。 - fpghost
通常情况下,这是由于某个模块没有正确关闭所导致的。您是否使用了一些特殊的模块?最近有添加过什么吗?第三方模块?请尝试禁用它们。 - Giovanni Tirloni
所以当logrotate执行/usr/sbin/apachectl graceful时会导致段错误,但是手动执行时却没有问题?很奇怪。 - Nils Toedtmann
@NilsToedtmann 实际上更具体。手动运行 logrotate 不会出现问题(logrotate -f -v /etc/logrotate.d/apache2),但通过 cron 运行时会导致段错误。我将在我的原始帖子中更新一些进一步的发现。 - fpghost
@gtirloni apachectl -M 显示了我载入的模块,网址为 http://paste.ubuntu.com/8309365/ - fpghost
你能尝试通过strace启动Apache,以便准确捕获它发生段错误的位置吗?先完全停止它,然后运行strace -ff -o trace.log -r apachectl start,并尝试优雅地关闭它,这将导致段错误。 - Giovanni Tirloni
如果你创建一个 /etc/cron.d/logrotate-test 文件,并在其中添加 */1 * * * * root /usr/sbin/logrotate -v -f /etc/logrotate.d/apache2 > /home/myuser/logrotate.log 2>&1 的命令,那么复制这个过程会更加容易。 - Nils Toedtmann
@NilsToedtmann 是的,说得好,我会更新我的帖子。根据我目前的实验,如果我只是将logrotate脚本更改为一个单独的块,即/var/log/apache2/*.log, /srv/apache/logs/*.log {....},我就不会遇到段错误。所以也许只是两个块在第一次重启期间导致了第二次重启尝试... - fpghost
有趣。在我的系统上,apache2ctl graceful & apache2ctl graceful & apache2ctl graceful & apache2ctl graceful &不会导致段错误。这是4个同时进行的优雅重启。你也是这样吗? - Ian Macintosh
(删除了一个愚蠢的想法) - Nils Toedtmann
@NilsToedtmann 如果我输入 apache2ctl graceful & apache2ctl graceful & apache2ctl graceful & apache2ctl graceful & 我的系统会崩溃!奇怪,不知道为什么我的会崩溃而你的不会。哎呀,我猜这个谜团解开了...如果有人想要给出一个解释,我很乐意接受。 - fpghost
@fpghost 你可能想自己添加答案(似乎有一个糟糕的模块阻止了重新加载,基本上迫使你停止/启动Apache)。 - Dennis Nolte
1个回答

似乎如果我只将logrotate脚本更改为一个单独的块,即/var/log/apache2/*.log, /srv/apache/logs/*.log {....},就不会出现段错误。所以只是这两个块在第一次重启期间导致了第二次重启尝试... 如果我在命令行输入apache2ctl graceful & apache2ctl graceful & apache2ctl graceful & apache2ctl graceful &,我的系统确实会出现段错误,这似乎证实了这一点。

1我有同样的问题,但是我的logrotate脚本只有一个块。你有什么想法吗? - kontextify