ログファイルを監視し、特定のエントリに基づいてアクションを実行します。

ログファイルを監視し、特定のエントリに基づいてアクションを実行します。

私は次のことをしたいと思います:

tail -f 一部のファイル { 改行文字が一致または含まれている場合

somestring(タスク1の実行、タスク2の実行、...;追加のタスク)

somestring2(他の操作を実行)...

somestring999(他の操作も可能)}

これは今まで私が見たものの最も近いものです。

Tail -f /mnt/zandrologs/* | awk '/GRRFIELD/ { system("echo \"test\"") }'

ただし、これは1つのパラメータのみを認識し、1つのコマンドのみを実行します。複数のパターンを認識し、複数のコマンドを実行する必要があります。最後にbashスクリプトに入れました。

おそらくそれはただ行くべき道を超えているかもしれませんが、それが私が得たばかりです。今、文字列が見つかるまでログを読み、いくつかのゴミをコンソールに印刷します(テスト)。もっと詳しく説明したいのですが、私がやりたいことの本質に関する質問に制限します。

いくつかの基本的な構文問題にご協力いただきありがとうございます。

答え1

必要に応じて、その方法を引き続き使用できます。
もちろん、各一致に対して複数のコマンドを実行でき、さまざまなコマンドの順序でさまざまな行を一致させることができます(より具体的なコマンドを実行しながら、さまざまな種類の行に対していくつかのコマンドを共有することもできます)。
前任者:

tail -f /mnt/zandrologs/* | awk '
/GRRFIELD/{ system("echo \"test\""); system("echo \"testG\""); }
/FRRFIELD/{ system("echo \"test2\""); system("echo \"testF\""); }
/FIELD/{ system("echo \"shared command for all lines containing FIELD\"");}'

必要に応じて、改行文字を省略してスペースに置き換えることもできます。または、より複雑なマッチングを実行できます。例のように$ 0(フル行)のみが一致する場合は、行をフィールドに分割するオーバーヘッドを避けるために、固定フィールドとwitdhモードでawkを使用することをお勧めします。

答え2

真珠ファイル::尾モジュールはこれらの作業に最適です。ディストリビューションに事前にパッケージ化されている可能性があります(例:Debian や派生製品sudo apt-get install libfile-tail-perl

例えば

#!/usr/bin/perl

use strict;
use File::Tail;

my $dir='/mnt/zandrologs';

# Get the list of logfiles in the target directory
my @logfiles = glob("$dir/*");

# Set up an array of File::Tail objects, one for each filename.
my @logs=();
foreach (@logfiles) {
  push(@logs,File::Tail->new(name => $_));
}

# Now watch those logs and do stuff when the script sees matching patterns
while (1) {
  my ($nfound,$timeleft,@pending)= File::Tail::select(undef,undef,undef,undef,@logs);

  if ($nfound) {
    foreach my $input (@pending) {

      # read the line of data from the current File::Tail object into $_
      $_ = $input->read;
      chomp;

      # Get the filename of the current File::Tail object.
      # This script doesn't use it, so it's commented out.
      # my $fn = $input->{'input'};

      if (m/somestring/) {
         # do stuff here
         # any perl code, including executing external programs with system().
      } elsif (m/somestring2/) {
         # do different stuff here
      } elsif (m/somestring3/) {
         # and more different stuff
      } elsif (m/somestring999/) {
         # yet more different stuff
      }
    }
  }
};

これにより、ログファイルが永久に(または終了するまで)繰り返されます。入力ファイルが回転すると、File::Tailファイルは自動的に閉じて再び開きます(例:に似ていますtail -F)。

1 つ以上のログに新しいデータがある場合、このFile::Tail::select()メソッドは次を返します。

  • $nfound- 処理するデータがある File::Tail オブジェクトの数 (つまり、配列の要素数@pending)。
  • $timeleft- timeout以前に残った時間select()。ただし、このスクリプトはタイムアウト値を渡しません(配列を除くすべてをselect渡します)。undef@logs
  • @pending- 未読の新しいデータを含むFile::Tailオブジェクトの配列

の各要素は、@pendingさまざまなメソッド(read()オブジェクトの保留中のテキスト行を返す)とハッシュキー({'input'}ファイル名など)を含むFile :: Tailオブジェクトです。

詳細については、およびを参照してくださいman File::Tailperldoc -f select


書かれているように、スクリプトはスクリプトが開始される前にファイルに存在していたすべての行を無視します。最後の内容を読んで変更できます。Nこの行を変更すると、ファイル全体を最初から変更することもできます。

push(@logs,File::Tail->new(name => $_));

(最初にログファイルの最後の10行を読んでください):

push(@logs,File::Tail->new(name => $_, tail => 10));

または(最初からすべてのログファイルを読む):

push(@logs,File::Tail->new(name => $_, tail => -1));

これは、このモジュールを効率的で簡単に使用することです。man File::Tail詳細と代替用途については参考資料を参照してください。このモジュールにはいくつかの素晴らしいサンプルスクリプトも付属しています。


PS:私は長年このモジュールを定期的に使用してきました。たとえば、私はFile::Tail1990年代にipchains悪いことをしたいIPアドレスを自動的にブロックするために呼び出される独自のスクリプトを維持しようとしました。それからfail2banそれが来て、私はそれに切り替えました。私は今日までロギングスクリプトを監視するためにこれを使用しています。

関連情報