쉘 스크립트 - Awk 최적화

쉘 스크립트 - Awk 최적화

Bro 네트워크 로그 구문 분석 스크립트를 최적화하는 데 도움을 찾고 있습니다. 배경은 다음과 같습니다.

나는 수많은 형제 로그를 가지고 있지만 내 범위(다중 가변 길이 서브넷)의 IP를 쿼리하는 데에만 관심이 있습니다.

그래서 내가 찾고 있는 IP 범위와 일치하는 정규식 패턴이 포함된 텍스트 파일이 있습니다.

/^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/

(scope.txt에는 정규식 패턴의 추가 IP 범위에 대한 최대 20줄이 포함되어 있습니다.) findInScope.sh:

#!bin/sh
for file in /data/bro_logs/2016-11-26/conn.*.log.gz
do
    echo "$file"
    touch /tmp/$file
    for nets in $(cat scope.txt)
    do
        echo "$nets"
        zcat $file | bro-cut -d | awk '$3 ~ '$nets' || $5 ~ '$nets'' >> /tmp/$file
    done
    sort /tmp/$file | uniq > ~/$file
    rm /tmp/$file
done

추가 배경 지식으로 원시 bro conn 로그는 시간당 약 100MB이므로 현재 스크립트는 1시간 분량의 로그 데이터를 구문 분석하는 데 약 10-20분이 걸립니다. 하루의 기록은 최대 3시간이 걸릴 수 있습니다.

나는 40개의 단일 awk 문을 사용하는 것을 고려했지만, 다른 IP 범위에 대해 동일한 스크립트를 사용할 수 있도록 별도의scope.txt 파일을 원했기 때문에 그렇게 하지 않기로 결정했습니다.

또한 여러 conn.log 파일(예: zcat conn.*.log.gz)에서 zcat를 시도했지만 출력 파일이 1GB를 초과하여 시간별 로그를 그대로 유지하고 싶었습니다.

답변1

awk를 통해 로그 파일을 한 번만 전달하면 많은 이점을 얻을 수 있습니다. 이는 모든 정규 표현식을 하나로 결합하는 것을 의미합니다. scope.txt파일에서 이 작업을 수행 하지 않으려면 awk를 호출하기 전에 수행하십시오. 예를 들어,

sed <scope.txt 's|^/\^|(|; s|\$/$|)|; $!s/$/|/' | tr -d '\n' >pattern

zcat $file | bro-cut -d |
awk '
BEGIN{ getline pat <"pattern"; pat = "^(" pat ")$" }
$3 ~ pat || $5 ~ pat
'  >~/$file

sed는 각 정규식 줄 주변의 합계를 닫는 쌍으로 /^바꾸고 줄 끝에 1을 추가한 다음 한 줄의 결과를 모두 파일에 저장합니다. 따라서 파일은 모두 OR로 연결된 패턴입니다. 누락된 콘텐츠는 스키마 파일을 변수로 읽는 awk 스크립트 문에 추가됩니다.$()|pattern^(...)$BEGINpat

위의 내용은 내부 for루프를 대체하고 sort|uniq.

답변2

scope.txt가장 간단한 대답은 약간 수정된 파일을 스키마 파일로 사용 하고 zcat | grep(또는 그냥 zgrep)을 사용하여 필요한 라인을 얻는 것입니다.

먼저 scope파일을 수정하여 다음을 변경합니다.

/^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/

입력하다:

(^|[^0-9.])(10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5]))($|[^0-9.])

이 작업을 쉽게 수행하려면 다음을 사용할 수 있습니다.

sed -e 's:^/\^:(^|[^0-9.])(:' -e 's:\$/$:)($|[^0-9.]):' scope.txt > grepscope.txt

그런 다음 다음을 검색하세요.

zgrep -Ehf grepscope.txt /data/bro_logs/2016-11-26/conn.*.log.gz | less

또는 각 파일의 출력을 별도로 저장하기를 원하기 때문에:

for f in /data/bro_logs/2016-11-26/conn.*.log.gz; do
    zgrep -Ehf grepscope.txt "$f" | sort -u > ~/"${f##*/}"
done

또한 "for" 루프 변수에는 다음이 $f포함됩니다.모두각 파일의 경로를 차례로 지정합니다. ~/"$f"(존재하지 않을 수 있는 홈 디렉터리의 하위 디렉터리를 참조하는) 출력을 지시할 때 오류를 방지하기 위해 ~/data/bro_logs/2016-11-26경로 이름에서 마지막 슬래시 앞의 모든 항목을 제거하고 기본 이름만 사용합니다. 각 로그 파일.


언급할만한 징후 zgrep:

-E패턴의 괄호를 이스케이프할 필요가 없도록 확장 정규식을 지정합니다.

-h일치하는 각 줄의 접두어로 파일 이름을 인쇄하지 않습니다. ( for루프 버전에서는 이 옵션을 생략할 수 있습니다. 기본적으로 grep제가 지정한 첫 번째 명령에서처럼 여러 파일을 검색할 때 파일 이름만 인쇄하지만 두 버전 모두에 그대로 놔둬도 손상이 발생하지 않기 때문입니다.)

-f당신이 할 수 있도록스키마 파일을 지정합니다. 귀하의 질문에 따르면 이것이 바로 귀하에게 필요한 것이며 을 사용하면 grep -f많은 "or"가 포함된 Awk 명령을 작성할 필요 없이 파일에서 가져온 여러 검색 패턴을 사용할 수 있습니다.


sort | uniq특정 옵션 플래그를 sort -u사용해야 하는 경우가 아니면 일반적으로 로 대체할 수 있습니다 . uniq이 경우에는 그럴 필요가 없으므로 더 간단한 형식을 사용했습니다 sort -u.

관련 정보