私はUnixに初めてアクセスし、分析する必要があるログファイルがあります。以下は私のサンプルログファイルです。
Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:45 +0100 2020
LogLength:0
Log Contents:
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initiated
at.apache.java.org.Exception(132)
20/06/25 12:19:40 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
20/06/25 12:20:41 WARN Warning as the node is accessed without started
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
期待される出力
stderr
Thu Jun 25 12:24:52 +0100 2020
3000
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initiated
at.apache.java.org.Exception(132)
20/06/25 12:20:41 WARN Warning as the node is accessed without started
出力には、ERROR、WARN、および上記の他の詳細のみを含める必要があります。
ログファイル:
Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:45 +0100 2020
LogLength:0
Log Contents:
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/masked_data/parquet/FRAUD_CUSTOMER_INFORMATION/rcd_crt_dttm_yyyymmdd=20200523/part-0042-ed52abc2w.c000.snapp.parquet, range:0-27899, partition values :[20200523]
20/06/25 12:19:39 ERROR Exception found
java.io.Exception:Not initated
at.apache.java.org........
20/06/25 12:19:40 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
20/06/25 12:20:41 WARN Warning as the node is accessed without started
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
Container:container_e182_1234
=============================
LogType:container-localizer-syslog
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
LogType:stderr
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:3000
Log Contents:
20/06/25 12:19:33 INFO datasources.FileScanRDD: Reading File path: hdfs://bpaiddev/dev/data/warehouse/clean/falcon/ukc/masked_data/parquet/FRAUD_CUSTOMER_INFORMATION/rcd_crt_dttm_yyyymmdd=20200523/part-0042-ed52abc2w.c000.snapp.parquet, range:0-27899, partition values :[20200523]
20/06/25 12:19:34 INFO executor.EXECUTOR: Finished task 18.0 in stage 0.0 (TID 18),18994 bytes result sent to driver.
LogType:stdout
Log Upload Time :Thu Jun 25 12:24:52 +0100 2020
LogLength:0
Log Contents:
どうすればいいですか?この問題を解決するのに役立ちます。ありがとうございます!
答え1
次の1行のコードを使用してsed
同じ結果を得ることができます(ファイル名が仮定されますfile
)。
sed -n 's/^.*LogType:\(stderr\)$/\1/p; s/^.*Log Upload Time :\(.*\)/\1/p; s/^.*LogLength:\(.*\)$/\1/p; s/^.*\(ERROR\|WARN\).*$/\0/p' file
その後、リダイレクト(>
)を使用して出力を別のファイルに保存できます。
読みやすくするために、複数行に分けてください。
sed -n -e 's/^.*LogType:\(stderr\)$/\1/p' \
-e 's/^.*Log Upload Time :\(.*\)/\1/p' \
-e 's/^.*LogLength:\(.*\)$/\1/p' \
-e 's/^.*\(ERROR\|WARN\).*$/\0/p' file
修正する
上記の解決策は、OPによって要求された「LogType:stderr」の一部ではないチャンクを除外しません。これsed
には、単独処理に適していない非ローカル情報(同じ行にはありません)が必要です。
次のスクリプトはとawk
を使用しますsed
(このawk
セクションではこの投稿)、次の作業を完了してください。
#!/bin/bash
file=$1
awk '{
if($0 ~ /LogType/){
if(hold ~ /LogType:stderr/){
print hold;
}
hold=$0
}else{
hold=hold "\n" $0
}
}END{
if(hold ~ /LogType:stderr/){
print hold
}
}' $file | sed -n -e 's/^.*LogType:\(stderr\)$/\1/p' \
-e 's/^.*Log Upload Time :\(.*\)/\1/p' \
-e 's/^.*LogLength:\(.*\)$/\1/p' \
-e 's/^.*\(ERROR\|WARN\).*$/\0/p'
答え2
短いスクリプトを使用して行うことができます。ソースログはこのファイルに含まれていますlogdata
。
#!/bin/bash
tmpfile="/tmp/$0.$$"
sed -n '/stderr/,/^ *$/p' logdata > "$tmpfile"
sed -n 's/^.*LogType:\(.*\)/\1/p
s/^.*Log Upload Time :\(.*\)/\1/p
s/^.*LogLength:\(.*\)/\1/p' "$tmpfile"
grep -E "(ERROR|WARN)" "$tmpfile"
rm "$tmpfile"
まずstderr
チャンクを一時ファイルに抽出します。次に、2 つのフィールドを削除し、エラーgrep
と警告を削除します。最後の2つのステップを接続しようとしましたが、tee
成功しませんでした。
一時ファイルがなくてもできます。
sed -n '/stderr/,/^ *$/p' logdata | \
sed -n 's/^.*LogType:\(.*\)/\1/p
s/^.*Log Upload Time :\(.*\)/\1/p
s/^.*LogLength:\(.*\)/\1/p
/ERROR/p
/WARN/p'
答え3
そしてawk
:
awk '
/LogType:stderr/ || (p && /Log( Upload Time|Length)/){
p=1 # set flag for stderr block
sub(/^[^:]+:/, "") # replace content before `:` including `:`
print # print (modified) line
}
p && / (WARN|ERROR) /{
sub(/^[^0-9]*/, "") # remove unknown prefix
print
}
/LogType:stdout/{ exit } # exit the script
' file
答え4
GNU sed
拡張正規表現パターンを使用して活用してください。
sed -Ee '
/LogType:stderr/,/^\s*$/!d
/Log Contents:/,/^\s*$/!{
s/^[^:]*://;b
}
/\s(ERROR|WARN)\s/!d
' logfile
説明する:
ファイルを範囲(ログタイプは空白行)に分割し、各範囲を(事前ログコンテンツと後ログコンテンツ)に分割します。
サブ範囲 前のブロックから最初のコロン文字まで削除します。しかし、サブスコープのバックブロックにエラーや警告があるかどうかはまだわからないので、まだ印刷しないでください。だから私たちはそれを予約されたスペースに入れました。
下位範囲の後部ブロックに達すると、エラーまたは警告ラインが検出されます。これにより、保留がすぐに検索され、印刷されます。
結果:
stderr
Thu Jun 25 12:24:52 +0100 2020
3000
20/06/25 12:19:39 ERROR Exception found
20/06/25 12:20:41 WARN Warning as the node is accessed without started
エラー/警告メッセージの行番号も必要な場合は上記で修正し、sedコマンドを使用します。
sed -Ee '
/LogType:stderr/,/^\s*$/!d
/Log Contents:/,/^\s*$/!{
s/^[^:]*://;b
}
/\s(ERROR|WARN)\s/!d
p;=;d
' logfile |
sed -Ee '/\s(ERROR|WARN)\s/N;s/\n/ on line #/'
awk n perlなどの他のツールを使用してこれを実行することもできます。注:まず、空白行の末尾のスペースを削除します。
awk '
BEGIN {
RS = "\n\n"
FS = "\nLog Contents:\n"
OFS = "\n"
ORS = OFS
spc = "[[:blank:]]"
str = "(ERROR|WARN)"
pat = spc str spc
}
/^LogType:stderr/ &&
NF == 2 {
p = $1; gsub(/(^|\n)[^:]+:/, "\n", p);sub(/./, "", p)
N = split($2, a, /\n/)
print p
for ( i=1; i<=N; i++ )
if ( a[i] ~ pat )
print a[i]
}
' logfile
perl -F'/^Log\hContents:$/m,$_,2' -00 -ne '
next if ! /\ALogType:stderr$/m;
(my $pre = $F[0])=~ s/.*?://gm;
my $post = join "\n",
grep { /\s(?:ERROR|WARN)/ }
split /\n/, $F[1];
print($pre,$post);
' logfile