我有两个脚本正在运行,它们都输出一个日志文件。我想制作第三个脚本,可以按时间戳对这些日志进行排序,并在创建它们时将它们合并到一个文件中。什么是最好的方法来做到这一点,最好不要不断覆盖文件?
如果您使用tail -ftail 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
}'
Run Code Online (Sandbox Code Playgroud)
当 awk 看到==>文件头从尾部开始时,它会在两个文件之间翻转。它将数据保存在 4 个数组中,分别为每个文件,任意调用aaandbb并编号为 0 和 1。dates保存时间戳(以从纪元开始的秒数为单位),lines保存输入日志行,num保存行数以及maxes最高日期一份文件。前 2 个数组是按文件(0 或 1)和保留行数进行二维索引的。
读取每个日志行时,时间戳会转换为秒,并保存在 末尾的新条目中dates,并且该行也会被保存。当前两个日期中的最小值设置在 中minmax。根据时间戳顺序扫描并打印整个保存的数据,直至达到该最小值。打印的条目被清除,并且在 while 循环结束时,数组被压缩以删除这些清除的条目。
| 归档时间: |
|
| 查看次数: |
1113 次 |
| 最近记录: |