ログに特定のテキストが表示されたときにログに従い、コマンドを実行する最良の方法

ログに特定のテキストが表示されたときにログに従い、コマンドを実行する最良の方法

サーバーログがあり、サーバーが起動すると、ログファイルに特定のテキスト行が出力されます。サーバーの起動後にコマンドを実行したいので、次のようにします。

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を使用すると、よりエレガントになり、テールの必要性を置き換えることができます。 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

1つの可能性のみを探していて、awkorを使用するのではなく、ほとんどの場合シェルに滞在したい場合は、perl次のようにします。

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

my_command...毎回実行されます。」サーバーが起動しましたgrep「がログファイルに表示されます。さまざまな可能性がありますcasewhile

大文字を使用する場合は、どのログファイルが循環するのかに注意を払う必要があります-Ftailつまり現在のファイルの名前が変更され、同じ名前の別のファイルがそれを置き換えると、新しいファイルtailに切り替えられます。

この--line-bufferedオプションは、grepバッファが各ラインの後にフラッシュされるように指示します。そうしないと、my_command時間に到着できない可能性があります(ログに適切なサイズの行があると仮定)。

答え3

奇妙なことに、multitailこの機能をすぐに使用できるユーティリティについて言及した人はいません。使用例の1つ:

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;
  ...
')

関連情報