0

次のような行を含むログファイルがあります。

...timestamp...(id=1234)..GO...
...timestamp...(id=1234)..DONE...

事実:

  • タイムスタンプの形式はHH:MM:SS.ssss(秒の一部の場合はs)です。
  • 各「id」番号には、「GO」と「DONE」の2つの関連行があります。
  • 2つの関連する線は、必ずしも互いに隣接しているとは限りません。ファイルは時系列です

私が欲しいもの:

  • 関連するGO/DONE行を一致させる
  • タイムスタンプを比較する
  • (理想的には)次の形式の新しいファイルを作成します。

    diffTime <GO line> <DONE line>
    

私の主なこだわりは、タイムスタンプの違いです。これは本当に便利で、それを書くためのsort / sed/awkスキルが不足しています。この種のハッキングに役立つログファイルツールはありますか?

4

2 に答える 2

3

そのようなツールは知りませんが、シェルで書くことは可能です。たとえば、次のログ:

11:18:51(id = 123)GO
11:18:52(id = 124)GO
11:18:53(id = 123)完了
11:18:54(id = 125)GO
11:18:55(id = 125)完了
11:18:55(id = 124)完了

に変換することができます

2 123
3 124
1 125

ここで、最初の列は秒単位の時間で、2番目の列はトランザクションIDです。

コマンドは:

cat example.log
| sed 's|\([^ ]\+\) (id=\([^)]\+\)) \(.\+\)|\1 \2 \3|;s|GO|1|;s|DONE|2|'
| sort -k2,3
| paste - -
| tr ':' ' '
| awk '{printf("%d %d\n", ((($6-$1)*60*60)+(($7-$2)*60)+($8-$3)), $4)}'

このワンライナーはおそらくさらに単純化されるかもしれません。

使い方:

  • 行形式を「11:18:51123GO」に変更します
  • GOを1に、DONEを2に置き換えます(後で適切に並べ替えることができるため)
  • 結果行をトランザクションIDとステータスで並べ替えます
  • 各2行を結合します(各結果行はトランザクションの開始と終了を示します)
  • すべてのコロンをスペースに置き換えます(awk後で説明を簡略化するため)
  • 手動で除算して時間差を計算する
  • 結果を出力します
于 2011-09-19T05:41:23.110 に答える
2

途中まで到達するスクリプトは次のとおりです。

#!/bin/bash

# Script must be called with one parameter, the name of the file to process
if [ $# -ne 1 ]; then
  echo "Usage: $0 filename"
  exit
fi

filename=$1


# Use sed to put the timestamp after the id
#    10:46:01:0000 (id=20) GO
#    10:46:02:0000 (id=10) GO
#    10:46:03:0000 (id=10) DONE
#    10:46:04:0000 (id=20) DONE
#
#  becomes
#
#    (id=20) 10:46:01:0000 GO
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:04:0000 DONE
#
# \1 timestamp
# \2 id
# \3 status (GO or DONE)
#         \1          \2              \3
sed -e "s/\([0-9:]*\) \((id=[0-9]*)\) \(.*\)/\2 \1 \3/" $filename > temp1


# Now sort the file. This will cause timestamps to be sorted, grouped by id
#    (id=20) 10:46:01:0000 GO
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:04:0000 DONE
#
#  becomes
#
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:01:0000 GO
#    (id=20) 10:46:04:0000 DONE
sort temp1 > temp2


# Use sed to put the id after the timestamp
#    (id=10) 10:46:02:0000 GO
#    (id=10) 10:46:03:0000 DONE
#    (id=20) 10:46:01:0000 GO
#    (id=20) 10:46:04:0000 DONE
#
#  becomes
#
#    10:46:02:0000 (id=10) GO
#    10:46:03:0000 (id=10) DONE
#    10:46:01:0000 (id=20) GO
#    10:46:04:0000 (id=20) DONE
# \1 id
# \2 timestamp
# \3 status (GO or DONE)
sed -e "s/\((id=[0-9]*)\) \([0-9:]*\) \(.*\)/\2 \1 \3/" temp2 > temp3

そして残りの部分...このスクリプトを実行した後、そのようなDONE行が存在すると仮定すると、各GO行の後に同じIDのDONE行が続きます。

次に、行の各ペアを読み取り、タイムスタンプを抽出して差分をとることができます(Johnsywebが提案したタイムスタンプ関数を確認してください)。次に、2つの行を1つの行に統合します。結果は次のようになります。

#    1s 10:46:02:0000 (id=10) GO 10:46:03:0000 (id=10) DONE
#    3s 10:46:01:0000 (id=20) GO 10:46:04:0000 (id=20) DONE

開始タイムスタンプによってエントリがどのように順序が狂っているかに注意してください。これは、以前にidで並べ替えたために発生しました。正しい順序でエントリを取得する方法を理解するための演習として残しておきます。id=20はid=10の前に開始されたため、id=20のエントリをid=10の前に配置する必要があります。

#    3s 10:46:01:0000 (id=20) GO 10:46:04:0000 (id=20) DONE
#    1s 10:46:02:0000 (id=10) GO 10:46:03:0000 (id=10) DONE

これは紛らわしいと思いますので、ご不明な点がございましたらお知らせください。これらすべてを行うためのより効率的な方法があると確信していますが、これは私が頭のてっぺんから考えたものです。

于 2011-09-19T05:06:54.413 に答える