저는 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
다음 한 줄의 코드를 사용하여 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
청크를 임시 파일로 추출합니다. 그런 다음 두 필드를 제거한 다음 grep
오류와 경고를 제거하십시오. 마지막 두 단계를 연결하려고 시도했지만 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