我正在运行两个脚本,它们都输出一个日志文件。我想制作第三个脚本,它可以按时间戳对这些日志进行排序,并在创建它们时将它们合并到一个文件中。有什么好方法可以做到这一点,最好不要不断覆盖文件?
答案1
如果您使用tail -f
tail 2 个或更多文件,则该命令将逐行显示数据,并在每次数据源更改时输出文件名。使用此功能,您可以编写一个脚本,通过保留每一行,根据时间戳合并来自 tail 的交错输出,直到看到另一个文件中具有较晚时间戳的行。
例如,使用两个标准日志文件(/var/log/messages
和/var/log/cron
),它们在我的系统上具有相同的行开头时间戳格式(例如Jun 9 02:55:01
),您可以执行以下操作:
tail -f /var/log/messages /var/log/cron |
awk '
BEGIN { num[0] = 0; num[1] = 0; }
/^==> /{
file = $2; aa = file~/messages/?0:1; bb = 1-aa;
aanum = num[aa]; bbnum = num[bb];
next }
/^$/{ next }
{ "date --date \"" $1 " " $2 " " $3 "\" +%s" | getline date
lines[aa,aanum] = $0
dates[aa,aanum++] = date
maxes[aa] = date
minmax = maxes[aa]
if(maxes[bb]<minmax)minmax = maxes[bb]
i = 0; j = 0;
while(1){
aaok = (i<aanum && dates[aa,i]<=minmax)
bbok = (j<bbnum && dates[bb,j]<=minmax)
if(aaok && bbok){
if(dates[aa,i]<=dates[bb,j]){
print lines[aa,i]; dates[aa,i++] = ""
}else{
print lines[bb,j]; dates[bb,j++] = ""
}
}else if(aaok){
print lines[aa,i]; dates[aa,i++] = ""
}else if(bbok){
print lines[bb,j]; dates[bb,j++] = ""
}else break
}
i = 0
for(j = 0; j<aanum;j++)
if(dates[aa,j]!=""){
dates[aa,i] = dates[aa,j]; lines[aa,i++] = lines[aa,j]
}
aanum = num[aa] = i
i = 0
for(j = 0; j<bbnum;j++)
if(dates[bb,j]!=""){
dates[bb,i] = dates[bb,j]; lines[bb,i++] = lines[bb,j]
}
bbnum = num[bb] = i
}'
当 awk 看到文件头从尾部开始时,它会在两个文件之间翻转==>
。它将数据保存在 4 个数组中,分别为每个文件,任意调用aa
andbb
并编号为 0 和 1。dates
保存时间戳(以从纪元开始的秒数为单位),lines
保存输入日志行,num
保存行数以及maxes
最高日期一份文件。前 2 个数组是按文件(0 或 1)和保留行数进行二维索引的。
读取每个日志行时,时间戳会转换为秒,并保存在 末尾的新条目中dates
,并且该行也会被保存。当前两个日期中的最小值设置在 中minmax
。根据时间戳顺序扫描并打印整个保存的数据,直至达到该最小值。打印的条目被清除,并且在 while 循环结束时,数组被压缩以删除这些清除的条目。
答案2
假设日志文件具有相同的时间戳源,每个日志都是在创建日志条目时按时间顺序写入的,并且时间戳领先,您可以执行如下简单的操作:
tail -qF log1 log2 > summarylog
如果这些假设不适合您的情况,请更新您的问题以提供说明和示例。