UNIX의 대용량 로그 파일에서 정보를 얻는 빠른 방법

UNIX의 대용량 로그 파일에서 정보를 얻는 빠른 방법

6GB의 응용 프로그램 로그 파일이 있습니다. 로그의 형식은 다음과 같습니다(축약됨).

[...]
timestamp;hostname;sessionid-ABC;type=m
timestamp;hostname;sessionid-ABC;set_to_TRUE
[...]
timestamp;hostname;sessionid-HHH;type=m
timestamp;hostname;sessionid-HHH;set_to_FALSE
[...]
timestamp;hostname;sessionid-ZZZ;type=m
timestamp;hostname;sessionid-ZZZ;set_to_FALSE
[...]
timestamp;hostname;sessionid-WWW;type=s
timestamp;hostname;sessionid-WWW;set_to_TRUE

이 두 줄 외에도 회의를 많이 해요. type=m와 관련된 모든 세션을 찾아야 합니다 .set_to_TRUE

나의 첫 번째 시도는 모든 sessionID를 grep하여 type=m파일에 쓰는 것이었습니다. 그런 다음 큰 로그 파일을 반복하고 파일의 각 줄에 대해 grep을 수행합니다(줄당 1개의 sessionID).sessionID;set_to_TRUE

이 방법은 시간이 많이 걸립니다. 누구든지 이 문제를 해결하는 더 좋고 빠른 방법에 대한 힌트를 줄 수 있습니까?

답변1

각 세션에 해당 typeand is set_to또는 이 TRUE있는 경우 and 범위를 FALSE사용하여 sed다음을 수행할 수 있습니다.

sed '/type=m/,/set_to_/!d;/set_to_TRUE$/!d;s/.*\(sessionid-.*\);.*/\1/' infile

/type=m/,/set_to_/범위에 포함되지 않은 모든 행이 삭제됩니다 . 또한 범위가 로 끝나지 않는 줄을 삭제합니다 set_to_TRUE. sessionid그런 다음 나머지 행(있는 경우)에서 추출합니다.
또는,

sed -n '/type=/h;/set_to_TRUE$/{
x;s/.*\(sessionid-.*\);type=m$/\1/p
}' infile

똑같이 인쇄해야합니다.
후자는 일치하는 각 줄의 보유 버퍼를 덮어쓰는 방식으로 작동합니다 type=
. 그런 다음 일치하는 각 줄에서 set_to_TRUE버퍼를 교체하고 교체를 시도합니다. 즉, sessionid로 끝나는 줄에서 추출 type=m하고 성공하면 결과를 인쇄합니다 p. 그렇지 않으면 자동 인쇄가 비활성화되므로 아무 일도 일어나지 않습니다 -n.
위의 내용은 줄에 후행 공백이 없다고 가정합니다.

답변2

다음 awk명령을 사용하십시오.

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag)' infile.txt

두 개의 sessionID가 동일하고 필수 조건이 동일하면 일치합니다.

timestamp;hostname;sessionid-ABC;set_to_TRUE

print $3위의 내용은 전체 행을 인쇄합니다. 다음과 같이 sessionID만 갖도록 추가하여 원하는 열만 인쇄할 수 있습니다 .

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag){print $3}' infile.txt

답변3

grep을 사용하면 쉽게 수행할 수 있습니다.

grep -E "(type=|set_to_)" file.txt | grep -A 1 "type=m" | grep -B 1 "set_to_TRUE" > file1.txt &

배경에 두고 커피 한 잔을 마시고 작업을 완료하세요. "awk" 또는 "sed"가 더 빠른지 확실하지 않습니다. 6GB는 일반 텍스트를 저장하기에는 너무 많은 공간이므로 무엇을 하려고 해도 시간이 오래 걸립니다.

어쨌든 Enter 키를 누르거나 다른 명령을 입력하면 완료되면 콘솔에 표시됩니다.

[1]+  Done                    grep --color=auto -E '(type=|set_to_)' file.txt | grep --color=auto -A 1 "type=m" | grep --color=auto -B 1 "set_to_TRUE" > file1.txt

답변4

awk -F';' '/type=m/ { seen[$3]=1 };
           /set_to_TRUE/ && seen[$3] { print $3 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

이는 다음과 유사합니다.αГsнιn의 답변, 그러나 단일 변수( flag)를 사용하는 대신 배열( seen)을 사용하여 일치하는 세션 ID를 추적합니다 type=m.

type=m즉 , 임의의 세션 라인 타겟팅과 해당 세션 라인 타겟팅 사이에 다른 세션의 다른 라인이 있어도 type=m작동한다는 의미입니다 set_to_.

스크립트의 메모리 요구 사항을 최소화하기 위해 seen일치하는 또는를 발견하는 즉시 지정된 세션 ID에 대한 배열 요소를 삭제합니다.set_to_TRUEset_to_FALSE

참고: 위 스크립트는 일치하는 세션 ID만 인쇄합니다. 실제 type=m합계 줄을 인쇄하려면 set_to_TRUEawk 스크립트는 다음과 같습니다.

awk -F';' '/type=m/ { seen[$3]=$0 };
           /set_to_TRUE/ && seen[$3] { print seen[$3]"\n"$0 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

이로 인해 더 많은 메모리를 사용할 가능성이 있습니다. 전체 입력 라인을 배열에 저장하려면 정수를 저장하는 것보다 더 많은 RAM이 필요합니다.

참고 2: 이 스크립트는 세션 ID가 고유하다고 가정합니다. 예를 들어, 서로 다른 호스트 이름(필드 2)이 동일한 세션 ID를 생성할 수 있는 경우 다음을 시도하십시오.

awk -F';' '/type=m/ { seen[$3$2]=1 };
           /set_to_TRUE/ && seen[$3$2] { print $3 ; delete seen[$3$2] };
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

또는

awk -F';' '/type=m/ { seen[$3$2]=$0 };
           /set_to_TRUE/ && seen[$3$2] {print seen[$3$2]"\n"$0;delete seen[$3$2]};
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

관련 정보