之前有人遇到过 logrotate 的问题吗?它会导致日志文件旋转,然后恢复到原来的大小?以下是我的发现:
Logrotate脚本:
/var/log/mylogfile.log { 旋转 7 日常的 压缩 旧目录 /log_archives missok 通知为空 复制截断 }
Logrotate 的详细输出:
将 /var/log/mylogfile.log 复制到 /log_archives/mylogfile.log.1 截断 /var/log/mylogfile.log 使用/bin/gzip 压缩日志 删除旧日志 /log_archives/mylogfile.log.8.gz
截断发生后的日志文件
[root@server ~]# ls -lh /var/log/mylogfile.log -rw-rw-r-- 1 part1 part1 0 1月 11 17:32 /var/log/mylogfile.log
几秒钟后:
[root@server ~]# ls -lh /var/log/mylogfile.log -rw-rw-r-- 1 part1 part1 3.5G 1 月 11 日 17:32 /var/log/mylogfile.log
RHEL 版本:
[root@server ~]# cat /etc/redhat-release Red Hat Enterprise Linux ES 版本 4(Nahant 更新 4)
Logrotate版本:
[root@DAA21529WWW370 ~]# rpm -qa | grep logrotate logrotate-3.7.1-10.RHEL4
几点说明:
- 服务无法即时重启,因此我使用 copytruncate
- 日志每晚都会轮换,根据
olddir
每晚包含日志文件的目录进行轮换。
答案1
这可能是因为即使您截断了文件,写入文件的进程仍会继续从最后的偏移量写入。因此,logrotate 会截断文件,大小为零,进程会再次写入文件,从上次的偏移量继续写入,现在您有一个文件,其中包含截断点之前的 NULL 字节以及写入日志的新条目。
od -c 截断+突然增长后,生成如下输出:
0000000 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
*
33255657600 \0 C K B - s e r v e r [ h t t
33255657620 <more log output>
这说明从偏移量 0 到 33255657600,您的文件由空字节和一些可读数据组成。达到此状态所花的时间与实际写入所有那些空字节所花的时间不同。ext{2,3,4} 文件系统支持一种称为稀疏文件的东西,因此如果您搜索文件中不包含任何内容的区域,则该区域将被视为包含空字节且不会占用磁盘空间。那些空字节实际上不会被写入,只是假定存在,因此从 0 到 3.5GB 所花的时间不会花费太多。(您可以通过执行类似操作来测试所需的时间dd if=${HOME}/.bashrc of=largefile.bin seek=3432343264 bs=1
,这应该在几毫秒内生成一个超过 3GB 的文件)。
如果您ls -ls
在日志文件被截断后运行它,并且它再次突然增长,它现在应该在行开头报告一个数字,该数字代表实际大小(以磁盘上占用的块为单位),该数字可能比报告的大小小几个数量级ls -l
。
答案2
我是极其确信 Kjetil 已经成功了。Drew,你可能还不相信他的解释,但我强烈建议你仔细阅读他所说的内容。
如果您接受它,那么解决方法是,在日志轮换时停止并重新启动应用程序,或者使用 apache 的“rotatelogs”之类的工具,通过管道将日志输出提供给工具,然后该工具会负责不时轮换日志文件。例如,我的一个 apache 实例使用以下代码记录日志:
ErrorLog "|/usr/sbin/rotatelogs /www/logs/error_log 604800"
这会导致大量的日志文件名称如下
-rw-r--r-- 1 root root 4078 Dec 21 01:04 error_log.1292457600
-rw-r--r-- 1 root root 4472 Dec 29 08:41 error_log.1293062400
-rw-r--r-- 1 root root 78630 Jan 4 12:57 error_log.1293667200
-rw-r--r-- 1 root root 15753 Jan 12 01:10 error_log.1294272000
无需重新启动 apache 即可显示;然后我可以事后手动压缩它们。请注意轮换是每周进行的,即每 604800 秒,这是传递给 的参数rotatelogs
。
如果您无法停止并重新启动应用程序,并且无法通过管道记录,那么我认为您遇到了真正的问题。也许其他人会提出建议。
答案3
如果您可以发送整个 logrotate,那就太好了。
为什么要尝试使用 kill -HUP ?(经典的重新加载不重启) 方法。
另外...检查lsof
谁在访问该文件。
答案4
只需使用“>>”表示追加,而不是“>”,后者表示从写入此文件的脚本中创建。我遇到了完全相同的问题,我使用脚本中的追加修复了它。
SomeScript.sh >> 输出.txt
希望这更清楚一些。