对于这个问题的长度,我深表歉意。这很难解释,尽管我的英语很流利,但我不是;)
不太确定在哪里发布这个问题,因为它有 java、log4j 库和 linux。
设想:
我有几个日志文件(由 log4j 使用 创建RollingFileAppender
)。命名文件.log和文件.log.1到文件.log.10
所有文件每天都会被覆盖多次。我的意思是,如果我收到一个事件,我几乎可以肯定我没有日志来查看发生了什么,因为它会被覆盖。
目的:
我的目的是在某些条件下定期备份这些文件
- 首先,不要错过数据(解决运行作业的频率不够高的问题)
- 不要重复信息。 (如果整理信息就可以解决)
- 数据必须排序。 (问题!!)
注意事项:
- 每个单独的文件都会被排序,但不会全部排序,因为有两个服务器实例向它们写入数据。
我的意思是,一个实例可能同时写入 *.log.1 和另一个 *.log.2 。因此,我无法将它们全部合并并期望对它们进行排序。 - 我无法增加文件系统上的可用空间。
日志寄存器布局:
每行都是这样的:
2014-11-28 14:33:10,015 主要 ca.cpy.net.txc.batch.SendEER INFO - 信息
尝试:
作为追加器类型从 移至
RollingFileAppender
。DailyRollingFileAppender
不幸的是,Apache 文档说“DailyRollingFileAppender 已被观察到出现同步问题和数据丢失”。
所以,我不能使用它。
- 使用 apache log4j extras 库,但我不允许这样做。这不取决于我。
所有的事情都自己做。它包括:
- 合并所有文件
- 对它们进行排序
- 丢弃以前备份中保存的所有数据。
- 压缩
问题在于排序步骤。这是我尝试过的:
for ((i=10; i >= 1; i--)); do cat file.log.$i >> $FILE_OUT; ## put all files in one (as much sorted as possible) done; cat file.log >> $FILE_OUT; ## append last sort -s -t ' ' -k 1.1,1.4n -k 1.6,1.7n -k 1.9,1.10n -k 2.1,2.2n -k 2.4,2.5n -k 2.7,2.8n -k 2.10,2.12n -3k $FILE_OUT -o $FILE_SORTED # Sort by date/time
好吧,如果附加到日志的每个寄存器只有一行(即:没有行尾字符 \n),那么这将起作用。例如,上面的排序命令会破坏如下寄存器:2014-11-28 14:33:10,015 main ca.cpy.net.txc.batch.SendEER INFO - ***** RESULTATS ENVIAMENT EXPEDIENT ***** Total documents a tractar en DB: 86 *****************************************
它只会对第一行进行排序,其他三行将放在输出文件的开头。
有没有一种方法可以在不破坏包含多行的每个寄存器的情况下对合并的文件进行排序?任何其他想法也将非常受欢迎。
答案1
这是一种方法:
使日志文件NUL
以 - 分隔。即,使每条记录都以NUL
( \0
) 字符结尾。然后,您可以利用NUL
许多工具(sed
、sort
、xargs
、find
等)中对分隔文本的支持。一种方法可能是这样做:
perl -pe 's/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/\0$1/' file.log.2 > file.log.2.NULL
- 在每个时间戳前面加上一个
\0
(这是相反的方式 - 使记录以 开头NUL
,但实际上......)
然后你可以这样做:
sort -szt ' ' -k1,2 file.log{.{10..1},}.NULL -o $FILE_SORTED
-s
用于稳定排序(以便绑定条目按出现顺序排序)-z
打开NUL
分隔文本支持- 我已经更改了键,因为正如我在评论中指出的那样,表单的时间戳
YYYY-MM-DD HH:MM:SS,UUU
可以按字典顺序排序。您不需要对它们进行数字排序。
或者您可以完全避免所有这些临时文件:
perl -pe 's/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/\0$1/' file.log{.{10..1},} | \
sort -szt ' ' -k1,2 -o $FILE_SORTED