2 種類のログファイルがあります。
標準システムログ形式
タイムスタンプは次のとおりです。
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は15:4:1から4分1秒なので、15:08:2に変換する必要があります。
これを達成するための提案はありますか?
- 相対時間を絶対時間に変換
- syslogと時間でソートされた1つの大きなファイルにマージ
答え1
このソリューションは、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
}'
2番目のawkスクリプトは2番目のファイルで同じことを行いますが、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)
}'
次に、数値フィールドをソートして2つのファイルをマージし、最後にsedを介して数値を削除します。
sort -m -n -k1,1 log1.new log2.new |
sed 's/^[^ ]* //'
答え2
これにより、カスタムログファイルで生成された相対番号が元のベースに追加され、すべての行が更新されます。
#!/usr/bin/env bash
f=$(head -n 1 custom_log_format.log)
base=$(sed 's/.*H:M:S \(.*\) D:M:Y.*/\1/' <<<$f)
OLDIFS=$IFS
IFS=$'n'
readarray lines < custom_log_format.log
IFS=$OLDIFS
for i in ${!lines[@]}
do
b="${lines[$i]}"
if [[ $b == "["* ]]
then
rel_time=$(sed 's/^\[\(.*[^ ]\)\].*/\1/' <<<$b)
time=$(echo $rel_time | awk -F: '{ print ($1 * 60) + $2 * 60 }')
# convert base to seconds
base_seconds=$(date -d"$base" +"%s")
new_time_seconds=$(( base_seconds + time ))
new_time=$(date -d"@$new_time_seconds" +"%H:%M:%S")
fi
echo ${b/$rel_time/$new_time}
done
出力
Timestamp H:M:S 15:4:1 D:M:Y 16:1:2015
Firmware Version: 121020150140
[15:09:01]------------[ Logs ]------------
[15:11:01]Device Data: -> Supported Attributes -> 0x8033B
[15:09:01]Device Cleanup
[15:27:01]SendClearMsg ...
[15:31:01]Param:GetData failed
[15:59:01]Current Update Count:7
[15:10:01]MODECHK:Normal mode
答え3
Rustベースのツールをお試しください超高速システムログ検索
(あなたが持っていると仮定ラストインストール済み)
cargo install super_speedy_syslog_searcher
それから
s4 log1 log2
超高速システムログ検索さまざまなログメッセージの日付/時刻形式は、解釈された日付/時刻に基づいてソートされます。