로그 파일을 모니터링하고 특정 항목을 기반으로 조치를 취합니다.

로그 파일을 모니터링하고 특정 항목을 기반으로 조치를 취합니다.

나는 다음을 수행하고 싶습니다 :

tail -f 일부 파일 { 개행 문자가 일치하거나 포함하는 경우

somestring(작업 1 수행, 작업 2 수행, ...; 추가 작업)

somestring2(다른 작업 수행)...

somestring999(다른 작업 수행도 가능)}

이것은 지금까지 내가 본 것 중 가장 가까운 것입니다.

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

그러나 이는 하나의 매개변수만 인식하고 하나의 명령만 실행합니다. 여러 패턴을 인식하고 여러 명령을 실행하도록 해야 합니다. 마지막으로 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

진주파일::꼬리모듈은 이러한 작업에 이상적입니다. 배포판에 미리 패키지되어 있을 수 있습니다(예: 데비안 및 파생 제품 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).

하나 이상의 로그에 새 데이터가 있으면 이 File::Tail::select()메서드는 다음을 반환합니다.

  • $nfound- 처리할 데이터가 있는 File::Tail 개체의 수(즉, 배열의 요소 수 @pending)입니다.
  • $timeleft- timeout 이전에 남은 시간 select(). 그러나 이 스크립트는 시간 초과 값을 전달하지 않습니다 (배열을 제외한 모든 것을 select전달함 ).undef@logs
  • @pending- 읽지 않은 새 데이터를 포함하는 File::Tail 객체의 배열

의 각 요소는 @pending다양한 메서드(예: read()객체의 보류 중인 텍스트 줄 반환)와 해시 키(예: {'input'}파일 이름 포함)를 포함하는 File::Tail 객체입니다.

자세한 내용은 및 를 참조하세요 man File::Tail.perldoc -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자세한 내용과 대체 용도는 참고자료를 참조하세요 . 이 모듈에는 몇 가지 훌륭한 예제 스크립트도 함께 제공됩니다.


추신: 저는 수년 동안 이 모듈을 정기적으로 사용해 왔습니다. 예를 들어, 나는 File::Tail1990년대에 ipchains나쁜 일을 하려는 IP 주소를 자동으로 차단하기 위해 호출되는 자체 스크립트를 유지 관리하곤 했습니다. 그러다가 fail2ban그것이 와서 나는 그것으로 전환했습니다. 나는 오늘날까지도 로깅 스크립트를 모니터링하는 데 이를 사용하고 있습니다.

관련 정보