logrotate 期间 gunzip 出错

Gar*_*son 6 debian gzip logrotate

我正在使用 logrotate 在我的网络服务器上轮换我的 Symfony2 日志。
一切正常,但我希望通过电子邮件将旧日志发送给我。
所以,我在我的 logrotate conf 文件中添加了一些行,如下所示

日志旋转配置

/var/www/symfony/app/logs/prod.log {
        daily
        missingok
        rotate 5
        compress
        notifempty
        mail myemail@example.com
        su www-data www-data
}
Run Code Online (Sandbox Code Playgroud)

现在我确实收到了电子邮件,但内容并不是我所期望的。

收到电子邮件

/etc/cron.daily/logrotate:
错误:/var/www/symfony/app/logs/prod.log.6.gz 的邮件命令失败
错误:解压缩命令失败邮件/var/www/symfony/app/logs/ prod.log.6.gz
运行部分:/etc/cron.daily/logrotate 退出并返回代码 1

我对这个错误做了很多研究,但没有找到任何有用的东西。我已经启动了一个 strace,希望对这个问题有一些了解,但它没有按预期工作。

跟踪命令

strace -f -o ./strace.txt logrotate -d /etc/logrotate.d/symfony2
Run Code Online (Sandbox Code Playgroud)

生成的文件相当大,但我认为相关部分如下

跟踪输出

6842 execve("/usr/bin/mail", ["/usr/bin/mail", "-s", "/var/www/symfony/app/logs/prod."..., .com"], [/* 18 vars /]
6841 <... setgid resumed> ) = 0
6842 <... execve resumed> ) = -1 ENOENT(没有这样的文件或目录)
6841 setuid(0) = 0
6841 execve("/bin/gunzip", ["/bin/gunzip"], [/
18 vars */]
6842 exit_group(1) = ?
6841 <... execve resumed> ) = 0
6842 +++ 退出1 +++
6841 brk(0
6840 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 1}], 0, NULL) = 6842
6841 <...brk 恢复> ) = 0x85f010
6840 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6842, si_uid=0, si_status=1, si_utime=0, si_stime=0} ---
6840 write(2, "error:",
access 7 6841 ("/etc/ld.so.nohwcap", F_OK
6840 <... write resumed> ) = 7
6841 <... access resumed> ) = -1 ENOENT (没有这样的文件或目录)
6840 write(2, "邮件命令失败 /var/www"..., 65

如您所见,gunzip 命令以错误代码 1 和一些非常明确的问号 (?) 退出,以帮助我更好地了解正在发生的事情。我得到的唯一错误是“没有这样的文件或目录”,我觉得这很奇怪,因为 logrotate 应该在发送电子邮件之前处理文件轮换。

我的问题是,如何使用 gunzip/logrotate 解决此问题,以便在删除之前通过电子邮件接收轮换的日志文件?

以下是我的服务器上可能与问题相关的一些信息

root@someServer:/home/someUser# cat /etc/debian_version
8.1
root@someServer:/home/someUser# logrotate --version
logrotate 3.8.7
root@someServer:/home/someUser# gzip --version
gzip 1.6

此外,我的日志文件非常小(~300-400 字节),如果我手动使用 gunzip,它工作得很好。


编辑 - 添加 logrotate 输出

处理 1 个日志

轮换模式:/var/www/symfony/app/logs/prod.log 从命令行强制执行(5 轮轮换)
空日志文件不会轮换,旧日志邮寄到 someEmail@example.com,将 euid
切换为 1000 和 egid到 33
考虑日志 /var/www/symfony/app/logs/prod.log
    日志需要旋转
旋转日志 /var/www/symfony/app/logs/prod.log, log->rotateCount 是 5
dateext 后缀 '-2016011811'
全局模式'-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][ 0-9]'
将 /var/www/symfony/app/logs/prod.log.5.gz 重命名为 /var/www/symfony/app/logs/prod.log.6.gz (rotatecount 5, logstart 1,我 5),
将 /var/www/symfony/app/logs/prod.log.4.gz 重命名为 /var/www/symfony/app/logs/prod.log.5.gz (rotatecount 5, logstart 1, i 4),
重命名/var/www/symfony/app/logs/prod.log.3.gz 到 /var/www/symfony/app/logs/prod.log.4.gz (rotatecount 5, logstart 1, i 3),
重命名 / var/www/symfony/app/logs/prod.log.2.gz 到 /var/www/symfony/app/logs/prod.log.3.gz (rotatecount 5, logstart 1, i 2),
重命名 /var /www/symfony/app/logs/prod.log.1.gz 到 /var/www/symfony/app/logs/prod.log.2.gz (rotatecount 5, logstart 1, i 1),
重命名 /var/ www/symfony/app/logs/prod.log.0.gz 到 /var/www/symfony/app/logs/prod.log.1.gz (rotatecount 5, logstart 1, i 0),
old log /var/ www/symfony/app/logs/prod.log.0.gz 不存在
将 /var/www/symfony/app/logs/prod.log 重命名为 /var/www/symfony/app/logs/prod.log.1
压缩日志:/bin/gzip
将 uid 切换为 1000,将 gid
切换为 33切换 uid到 1000 和 gid 到 33
切换 euid 到 0 和 egid 到 0
错误:邮件命令失败 /var/www/symfony/app/logs/prod.log.6.gz
错误:解压缩命令失败邮件 /var/www/symfony /app/logs/prod.log.6.gz
将euid切换为 0,将 egid 切换为 0

完整的跟踪如下:

 strace -vf -s 128 -e verbose=all -o ./strace.txt logrotate -d /etc/logrotate.d/symfony2
Run Code Online (Sandbox Code Playgroud)

http://pastebin.com/C0uj0419

Mat*_*Ife 3

根据你的 strace,你的问题实际上不是 gzip。

这就是 gzip 失败的原因。

14972 write(1, "<Here is the content of my prod.log file>"..., 32768) = -1 EPIPE (Broken pipe)
Run Code Online (Sandbox Code Playgroud)

该进程正在写入 stdout,但其实际输出是 mail 命令的输入。如果我们检查一下:

14973 execve("/usr/bin/mail", ["/usr/bin/mail", "-s", "/var/www/symfony/app/logs/prod.log", "someUser@example.com"], ["SHELL=/bin/bash", "TERM=xterm", "USER=root", "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41"..., "SUDO_USER=none", "SUDO_UID=1000", "USERNAME=root", "MAIL=/var/mail/root", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "PWD=/home/none", "LANG=en_GB.UTF-8", "SHLVL=1", "SUDO_COMMAND=/bin/bash", "HOME=/root", "LANGUAGE=en_GB:en", "LOGNAME=root", "SUDO_GID=1000", "_=/usr/bin/strace"] <unfinished ...>
14973 <... execve resumed> )            = -1 ENOENT (No such file or directory)
Run Code Online (Sandbox Code Playgroud)

当您尝试执行 mail 命令时,它会失败,因为它/usr/bin/mail不存在。程序退出,stdoutofgzip返回,SIGPIPE因为管道的另一端已经消失。因此 gzip 以 1 退出。

您需要做的是安装mail命令。这可能是bsd-mailx在 debianesque 系统或mailx基于 Redhat 的系统上。