我们有一个java应用程序,log4j2可以生成日志文件,并且在用另一个脚本重新启动进程之前,脚本可以停止它。在每天午夜停止和重新启动之间有5分钟的暂停。在启动脚本中,我们使用"mv“命令将日志文件重命名为时间戳作为扩展名。问题是,其中一个日志文件在文件开头包含空字符(几MB),而日志文件变成二进制。为这个问题提供更多上下文的一些观察注意事项:1.同一启动脚本在其他具有相同版本的java应用程序的主机中使用。根本没有这个问题。2.-偶见。一个星期,所有5个日志文件都被损坏,而另一个星期,日志文件是安全的。3.-不能在类似的开发者Linux主机上复制;只能在生产Linux主机上进行。日志文件的大小通常为每天4-6 GB。5.-应用程序将在每天午夜停止+5分钟暂停+脚本启动。6.-使用十六进制文件窥视二进制日志文件的内容。它在开头有几MB的空字符,然后是普通的典型ASCII内容。
如有任何建议,将不胜感激。谢谢!
发布于 2021-07-27 20:36:47
当您使用ls -l查看“二进制”日志文件的大小并将其与使用du -k获得的大小进行比较时,您可能会注意到一些有趣的内容:该文件似乎比它在磁盘上占用的空间更大!
您可能已经运行了该java应用程序进程的第二份副本,或者生产应用程序有时需要超过5分钟才能完成其关闭。
因此,当空字符出现时,仍有一个应用程序进程正在运行,该进程会记住它以前对日志文件的写在哪里。它打开文件写,seek()s到那个位置,并写它的日志消息。和平常一样。
但是如果这个文件以前不存在(因为它是mvd),那么这正是生成稀疏文件的方法,这是一个非常老的Unix文件系统特性。
稀疏文件本质上是最简单的数据压缩原型:仅包含空字节的整个磁盘块实际上并不作为数据存储在磁盘上,但是通知文件块所在系统的文件系统元数据只会得到一个特殊标记,该标记有效地表示“在此文件位置插入X个空字节块”。
创建稀疏文件的方法是打开一个用于写入的文件,然后在不实际编写任何东西的情况下寻找当前文件的末尾,然后编写一些东西。大多数Unix风格的文件系统将自动将旧EOF和新写入的数据之间的块添加为稀疏块,而不是显式地将中间的nulls写入块添加到磁盘中。当您读取该文件时,文件系统驱动程序将自动将稀疏块填充为空字节块,因此应用程序根本不必知道这一点。
您可能需要向应用程序启动脚本添加测试,以使用fuser查看日志文件是否已打开,如果已打开,则停止使用错误消息。就像这样:
LOGFILE=/some/where/log4j2.log
if fuser -s $LOGFILE; then
echo "ERROR: $LOGFILE is still in use. Maybe the app is still running. Make it stop." >&2
exit 1
fi
# add here your commands to rotate the logs and start the application.log4j2实际上有自己的日志文件旋转工具:最好的解决方案可能是使用这些工具,而不是使用外部脚本。
https://unix.stackexchange.com/questions/660207
复制相似问题