로그에 특정 텍스트가 나타날 때 로그를 따르고 명령을 실행하는 가장 좋은 방법

로그에 특정 텍스트가 나타날 때 로그를 따르고 명령을 실행하는 가장 좋은 방법

서버 로그가 있고 서버가 시작되면 로그 파일에 특정 텍스트 줄을 출력합니다. 서버가 시작된 후에 명령을 실행하고 싶기 때문에 다음과 같이 합니다.

tail -f /path/to/serverLog | grep "server is up" ...(now, e.g., wget on server)?

이를 수행하는 가장 좋은 방법은 무엇입니까?

답변1

간단한 방법은 awk입니다.

tail -f /path/to/serverLog | awk '
                    /Printer is on fire!/ { system("shutdown -h now") }
                    /new USB high speed/  { system("echo \"New USB\" | mail admin") }'

예, 둘 다 커널 로그의 실제 메시지입니다. Perl을 사용하는 것이 더 우아할 수 있으며 tail의 필요성을 대체할 수도 있습니다. Perl을 사용하면 다음과 같습니다.

open(my $fd, "<", "/path/to/serverLog") or die "Can't open log";
while(1) {
    if(eof $fd) {
        sleep 1;
        $fd->clearerr;
        next;
    }
    my $line = <$fd>;
    chomp($line);
    if($line =~ /Printer is on fire!/) {
        system("shutdown -h now");
    } elsif($line =~ /new USB high speed/) {
        system("echo \"New USB\" | mail admin");
    }
}

답변2

한 가지 가능성만 찾고 있고 awkor 를 사용하는 대신 대부분 셸에 머물고 싶다면 perl다음을 수행할 수 있습니다.

tail -F /path/to/serverLog | 
grep --line-buffered 'server is up' | 
while read ; do my_command ; done

my_command...매번 실행됩니다."서버가 시작되었습니다grep" 가 로그 파일에 나타납니다. 여러 가지 가능성 으로 case.while

대문자를 사용하면 어떤 로그 파일이 순환되는지 주의를 기울여야 합니다 -F.tail현재 파일의 이름이 바뀌고 동일한 이름의 다른 파일이 이를 대체하는 경우 tail새 파일로 전환됩니다.

--line-buffered옵션은 grep버퍼가 각 라인 후에 플러시되도록 지시합니다. 그렇지 않으면 제 my_command시간에 도착하지 못할 수 있습니다(로그에 적절한 크기의 라인이 있다고 가정).

답변3

이상하게도 multitail이 기능을 즉시 사용할 수 있는 유틸리티에 대해 언급한 사람은 아무도 없습니다. 사용 예 중 하나:

ping 명령의 출력을 표시하고 시간 초과가 나타나면 현재 로그인된 모든 사용자에게 메시지를 보냅니다.

multitail -ex timeout "echo timeout | wall" -l "ping 192.168.0.1"

당신은 또한 볼 수 있습니다다른 예시용법 multitail.

답변4

일을 스스로 할 수 있다

얼마나 간단하고 읽기 쉬운지 살펴보겠습니다.

mylog() {
    echo >>/path/to/myscriptLog "$@"
}

while read line;do
    case "$line" in
        *"Printer on fire"* )
            mylog Halting immediately
            shutdown -h now
            ;;
        *DHCPREQUEST* )
            [[ "$line" =~ DHCPREQUEST\ for\ ([^\ ]*)\  ]]
            mylog Incomming or refresh for ${BASH_REMATCH[1]}
            $HOME/SomethingWithNewClient ${BASH_REMATCH[1]}
            ;;
        * )
            mylog "untrapped entry: $line"
            ;;
    esac
  done < <(tail -f /path/to/logfile)

bash 를 사용하지 않더라도 regex매우 빠를 수 있습니다!

하지만+매우 효율적이고 흥미로운 탠덤입니다

그러나 부하가 높은 서버의 경우 sed매우 빠르고 확장 가능하기 때문에 다음을 자주 사용합니다.

while read event target lost ; do
    case $event in
        NEW )
            ip2int $target intTarget
            ((count[intTarget]++))
        ...

    esac
done < <(tail -f /path/logfile | sed -une '
  s/^.*New incom.*from ip \([0-9.]\+\) .*$/NEW \1/p;
  s/^.*Auth.*ip \([0-9.]\+\) failed./FAIL \1/p;
  ...
')

관련 정보