Logs

合併不同時間戳格式的日誌文件

  • December 21, 2015

我有兩種類型的日誌文件

標準系統日誌格式

時間戳如下所示

5:2015 Dec 21 07:35:06:ABC:foo1:1559: common.c:946:Enabling filter
6:2015 Dec 21 07:35:08:ABC:bar1:1461: api.c:124:Trigger activated
6:2015 Dec 21 07:35:16:BMC:kernel:-:<6>drivers/usb1_1.c:598:Error processing request on endpoint 0

自定義日誌格式

日期時間在文件的第一行給出。以下幾行與第一行“相對”。範例如下:

Timestamp H:M:S 15:4:1 D:M:Y 16:1:2015
Firmware Version: 121020150140
[04:01]------------[ Logs ]------------
[04:03]Device Data: -> Supported Attributes -> 0x8033B
[04:01]Device Cleanup

[04:19]SendClearMsg ...
[04:23]Param:GetData failed
[04:51]Current Update Count:7
[05:01]MODECHK:Normal mode

時間戳 4:01 是 4 分鐘,自 15:4:1 起 1 秒,應翻譯為 15:08:2。

有什麼建議可以實現這一目標嗎?

  • 將相對時間轉化為絕對時間
  • 與 syslog 合併為一個大文件,按時間排序

此解決方案使用 awk 腳本將第一個文件中的日期轉換為自紀元以來的秒數,並將此數字預置到輸出中。我們用來做艱苦的工作,並通過呼叫 awk 的函式date +%s --date將命令的輸出擷取到 awk 變數中。(awk 語法是:命令**變數)。secs``getline | getline

awk <log1 >log1.new '
{ y = substr($0,3,4); m = $2; d = $3; hms = substr($0,15,8)
 "date \"+%s\" --date \"" d " " m " " y " " hms "\"" | getline secs
 print secs " " $0
}'

第二個 awk 腳本對第二個文件執行相同的操作,但僅針對帶有時間戳的第一行,該時間戳保存在 awk 變數base中。在其他行中,我們只需將分鐘和秒偏移量添加到此基數,並使用date第一個文件的格式將自紀元以來的秒數轉換為真實日期。

awk <log2 >log2.new '
/^Timestamp/{ split($5,x,":"); dmy = sprintf("%04d/%02d/%02d",x[3],x[2],x[1])
             split($3,x,":"); hms = sprintf("%02d:%02d:%02d",x[1],x[2],x[3])
             "date \"+%s\" --date \"" dmy " " hms "\"" | getline base
}
/^\[/ { mins = substr($0,2,2); secs = substr($0,5,2);
       tot = base + mins*60+secs
       "date \"+%Y %b %d %H:%M:%S\" --date @" tot | getline date
       print tot " -:" date " " substr($0,8)
}'

然後通過對數字欄位的排序合併這兩個文件,最後通過 sed 刪除數字。

sort -m -n -k1,1 log1.new log2.new |
sed 's/^[^ ]* //'

引用自:https://unix.stackexchange.com/questions/250660