로컬 로그 검사 규칙을 유지할 때 어떤 규칙이 더 이상 사용되지 않는지 아는 것이 좋습니다. 나는 이것을 수행하는 합리적으로 효율적인 방법을 찾으려고 노력하고 있습니다.
즉, 상당히 많은 수의 GNU grep 확장 regexp( grep -E
) 패턴(약 700개)과 많은 양의 syslog 출력(수십억 줄)이 주어지면 약 700개 패턴 중 어느 패턴이 일치하는지 확인하고 싶습니다.전혀시스템 로그 라인 수. 더 좋은 방법은 각 패턴이 일치하는 syslog 행 수를 알아내는 것입니다.
가장 확실한 방법은 grep -c -E "$pattern" «massive-logfile»
각 패턴마다 한 번씩 약 700번 정도 실행하는 것입니다. 그러나 이는 특히 RAM에 많은 수의 로그 파일을 저장할 수 없는 경우 비효율적으로 보입니다.
이를 수행하는 효율적인 방법이 있습니까?
답변1
awk
's'와 매우 유사한 who 정규식을 사용할 수 있습니다 .grep -E
awk '!patterns_read{patterns[$0]; next}
{for (p in patterns) if ($0 ~ p) c[p]++}
END {
for (p in patterns) printf "'%s' was matched %d times\n", p, c[p]
}' patterns patterns_read=1 log files
답변2
각 모드에 대해:
if ! grep -q "$pattern" /path/to/input; then
echo "/${pattern}/ not found."
fi
AFAIK 그게 유일한 방법입니다. 한 번에 여러 패턴을 검색하는 경우에만 일치했다는 것을 알 수 있기 때문입니다.적어도그들 중 하나. 논리적 OR이 많은 경우(예: /(needle|pin)/
각 OR에서 반복)그것들하지만 여전히 한 번에 하나의 표현식을 테스트해야 합니다.
답변3
RE의 복잡성에 따라 Python(테스트되지 않음)과 같은 언어를 사용할 수 있습니다.
#! /usr/bin/env python3
import re, sys
res = ["re1", "re2", ... ] # or read from a file
recs = [re.compile(r) for r in res]
matches = {}
for line in sys.stdin:
for r in recs:
if r.match(line):
matches[r] += 1
for r in matches:
if matches[r] == 0:
print(r.pattern)
물론, 정규식에 Python의 고급 정규식 지원이 문자 그대로 이해하지 못할 수 있는 문자열이 포함된 경우에는 작동하지 않습니다. 출력을 제공하여 많은 작업을 제거할 수 있습니다 grep
(이후 정규식 일치가 없는 행을 제거했습니다).
답변4
perl -lne '
# read in the patterns into a hash
@ARGV and $h{$_}=s|/|\\/|gr,next;
# delete pattern if matched, so we wont have to
# expend efforts on it for the subsequent lines
while (my($pat) = each %h) {
delete $h{$pat} if /$h{$pat}/;
}
# what remains are those that did not match
END {
print "These patterns did not match:";
print for keys %h;
}
' patterns_file log_file