질문
결과에서 문자열을 생략하면서 재귀 병렬 zgrep을 수행할 수 없습니다.
약 640GB의 압축된 방화벽 로그를 zgrepping하고 있으며 거의 30개 줄에 "Duplicate SYN" 문자열이 있습니다(생략하려고 했습니다).
재귀 병렬 Zgrep(문자열 생략 없음) - 성공
이와 같은 병렬 재귀 grep을 성공적으로 수행할 수 있습니다.
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt > /tmp/bar.txt
foo.txt의 내용:
10\.10\.0\.28
10\.10\.3\.41
10\.10\.0\.46
10\.10\.5\.47
10\.11\.0\.48
10\.10\.0\.49
10\.144\.41\.145
10\.122\.41\.241
예제 출력
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
May 31 02:58:46 ASAFW01 : %ASA-6-302014: Teardown TCP connection 461681145 for DMZ_EXP_INSIDE:10.122.41.241/7400 to inside:10.5.91.50/30378 duration 0:00:00 bytes 0 Failover primary closed
May 31 02:58:47 ASAFW01 : %ASA-6-302013: Built outbound TCP connection 1962428108 for DMZ_EXP_INSIDE:10.122.41.241/7400 (10.122.41.241/7400) to inside:10.11.0.48/33990 (10.11.0.48/33990)
May 31 02:58:47 ASAFW01 : %ASA-6-302014: Teardown TCP connection 1962428108 for DMZ_EXP_INSIDE:10.122.41.241/7400 to inside:10.11.0.48/33990 duration 0:00:00 bytes 3188 TCP Reset-O from DMZ_EXP_INSIDE
May 31 02:58:49 ASAFW01 : %ASA-6-106015: Deny TCP (no connection) from 10.11.0.48/35976 to 10.122.41.241/7400 flags RST on interface inside
May 31 02:58:49 ASAFW01 : %ASA-6-106015: Deny TCP (no connection) from 10.11.0.48/35976 to 10.122.41.241/7400 flags RST on interface inside
출력을 생략하고 싶습니다
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
Apr 18 01:39:33 ASAFW01 : %ASA-4-419002: Duplicate TCP SYN from inside:10.10.0.28/61763 to inside:10.122.41.241/8443 with different initial sequence number
아이디어
- "Duplicate"라는 단어를 생략하는 정규식을 사용하도록 foo.txt를 수정합니다(이 작업을 수행하는 방법을 잘 모르겠습니다).
- 모든 640GB gzip 압축 로그 파일에서 "Duplicate"라는 단어가 포함된 모든 줄을 반복적으로 삭제합니다(sed 사용?)
재귀 병렬 Zgrep(문자열 생략) - 실패
그런데 결과에서 어떤 항목을 제외하려고 하면 오류가 발생합니다.
오류를 일으키는 명령:
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt -v Duplicate > /tmp/bar.txt
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
gzip: Duplicate.gz: No such file or directory
답변1
가장 간단한 방법쓰다grep
이 추가 조건은 파일에 쓰기 전에 다른 호출을 통해 출력을 파이프하는 것뿐입니다.
find /var/logs/syslog -name \* -print0 | xargs -0 -n 1 -P 36 zgrep -f foo.txt | grep -v Duplicate > /tmp/bar.txt
별도의 단일 스레드 프로세스에서 이 작업을 수행하는 성능은 검색에서 반환된 레코드 수에 따라 달라집니다. 초기 검색과 일치하는 행 수가 640GB 로그의 일부일 경우에는 문제가 되지 않습니다.
근본적인 질문은 부분적으로 이 검색을 전체적으로 최적화하는 것에 관한 것이기 때문에 두 가지 중요한 추가 개선 사항을 언급하겠습니다.
- grep 검색 용어로 정규식 대신 고정 문자열을 사용하십시오. 패턴 파일에서 백슬래시를 제거하고
-F
zgrep에 스위치를 추가하십시오. (-w
전체 단어만 일치하도록 전환하는 것도 좋은 생각일 수 있습니다.) 리터럴 문자열을 검색하는 것이 정규식을 검색하는 것보다 훨씬 빠릅니다. - 시스템 로케일이 UTF-8을 사용하지만 데이터 세트가 ASCII 전용인 경우
LC_ALL=C
명령 환경에서 이를 설정하십시오. 128자 ASCII 세트에서 검색하는 것은 대략 1000배 더 큰 UTF-8 문자 세트에서 검색하는 것보다 훨씬 빠릅니다.
답변2
GNU Parallel이 있으면 다음을 수행할 수 있습니다.
find /var/logs/syslog -name \* -print0 |
parallel --lb -0 'zgrep -f foo.txt {} | grep -v Duplicate' > /tmp/bar.txt
대조적으로, xargs -P
GNU Parallel을 사용한 출력은 행을 혼합하지 않는 것이 보장됩니다(mywiki.wooledge.org/BashPitfalls#Non-atomic_writes_with_xargs_-P에 따라).