성능 향상을 위해 여러 zgreps 실행

성능 향상을 위해 여러 zgreps 실행

.gz 형식의 일부 로그 파일을 검색하는 스크립트가 있습니다. 스크립트에 검색어를 제공하면 해당 용어에 대해 zgreps를 수행한 다음 줄의 시작 부분에서 트랜잭션 ID를 가져온 다음 동일한 파일을 다시 zgreps하여 해당 트랜잭션 ID에 대한 모든 줄을 가져옵니다. 출력에서 약간의 노이즈를 제거합니다.

while read -r line
do
        rgx="^(.*?)(\.log\.gz)"
        fn=$(echo $line | grep -oP $rgx)
        rgx="(\d{11})"
        trid=$(echo $line | grep -oP $rgx)
        rgx="(\w{3} \d{2} ).*($trid).*"
        zgrep -ohP "$rgx" $fn
done < <(zgrep -oP $regex $path)

여기서 문제는 속도가 느리다는 것입니다. zgrep이 실제로 실행 중이므로 gzip -cdfq파일의 압축을 두 번 푼다는 것입니다. 이러한 파일의 크기는 100MB에서 500MB까지입니다.

속도를 높일 수 있는 방법이 있나요? 또한 쓸모가 없는 점은 로그 파일이 여러 폴더에 걸쳐 분할되어 있다는 것입니다. 이는 Kubernetes와 관련이 있으므로 하루 동안의 모든 로그가 거의 하나의 파일에 있는 경우가 거의 없습니다. 이것이 제가 파일 이름도 잡는 이유입니다. 트랜잭션 ID이므로 각 파일을 너무 많이 확인하지 않습니다.

회사에서 관리하는 서버이므로 추가로 설치할 수 없습니다.

로그의 각 줄은 다음 형식으로 시작하고 그 뒤에 메시지가 옵니다.

2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785)

이 예에서는 11자리 숫자 26122393785가 거래 ID입니다. 로그 메시지는 대부분 XML로 구성되어 있습니다. XML 콘텐츠에서 일반적으로 URL이나 이와 유사한 항목을 검색하고 있는데 한 줄에만 나타나는 것 같습니다. 그래서 XML의 각 링크 줄 앞에 오는 11자리 숫자인 트랜잭션 ID를 얻습니다.

따라서 궁극적으로 행 중 하나에 초기 검색어가 포함된 거래 ID가 포함된 모든 행을 찾고 싶습니다.

그래서 검색어가 google이면 반환하고 싶습니다.

2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) <xml>here
2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) <url>google.co.uk</url>
2022-07-12T17:21:34+00:00 filename log 2022-07-12T17:21:30.490880384+01:00 stdout F Jul 12 17:21:30 *  192.168.0.1 (NAME, 482, 26122393785) end</xml>

답변1

XML 파서가 실제로 없다면 NUL 바이트로 XML 청크를 장식한 다음 .grep 키워드를 사용하는 것이 좋습니다 -z.

#!/bin/bash
KEYWORD=google

for file in *.log.gz ; do
    zcat "$file"  |\
    sed -e 's|^.*<xml>|\x00&|' -e 's|</xml>$|&\x00|' |\
    grep -z "$KEYWORD" | tr -d '\0'
done

이렇게 하면 각 파일의 압축이 한 번만 풀립니다. 여러 키워드를 일치시키려면(각 키워드에 대해 프로그램을 한 번 실행하지 않기 위해) -fin을 사용한 grep다음 출력을 분할하십시오. 예를 들어 awk.

관련 정보