特定の時間より大きい特定のログエントリをgrep

特定の時間より大きい特定のログエントリをgrep

特定のテキストを使用して、現在の日付より後の特定の時間のログをフィルタリングしたいと思います。現在の日付を含むテキストのログを正常にフィルタリングしました。これはコマンドです:

grep "$(date +"%d/%b/%Y")" test.log | grep -i "failed login"

サンプルログは次のとおりです。

[04/Dec/2019 02:05:13 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

[04/Dec/2019 02:05:15 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

[04/Dec/2019 02:04:59 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/check_status HTTP/1.1" returned in 759ms

[04/Dec/2019 02:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2

[04/Dec/2019 03:05:00 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/close_statement HTTP/1.1" returned in 1345ms

[04/Dec/2019 03:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2

[04/Dec/2019 03:05:18 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

しかし、特定の時間よりも大きな条件を適用する方法がわかりません。

答え1

tsfromを使用すると、moreutilsこれらのタイムスタンプをより便利な形式に簡単に変換できます。

ts -r %FT%T%z < file.log |
  awk '$0 > "[2019-12-04T02:50" && tolower($0) ~ /failed login/'

あなたの入力(とタイムゾーンAmerica/Los_Angeles)を考えると、次のようになります。

[2019-12-04T03:05:18-0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

tsそのタイムスタンプを解析し、-r指定された%FT%T%z strftime形式(タイムゾーン)に変換します。

書式は語彙と時系列で等しくソートされるため、指定された日付より後の項目を見つけるYYYY-MM-DDTHH:MM:SSには文字列比較のみが必要です。それでも仕事をすることができます。ここでは、大文字と小文字を区別しない標準一致方法が使用されます。 GNUを使用すると、次のこともできます。awkawkgrep -itolower()awk

gawk -v IGNORECASE=1 '$0 > "[2019-12-04T02:50" && /failed login/'

ない場合は、'sを使用してmoreutils解析を実行できます('sを使用するPerlスクリプトですが、'sとは対照的にコアモジュールの1つではないため、システムにインストールされない可能性があります)。perlTime::PiecetsDate::ParseTime::Pieceperl

CUT=2019-12-04T02:50:00-0800 perl -MTime::Piece -F'[][]' -ale '
  BEGIN{$cut = Time::Piece->strptime($ENV{CUT}, "%FT%T%z")}
  print if /failed login/i &&
           Time::Piece->strptime($F[1], "%d/%b/%Y %T %z") >= $cut' < file.log

1 DSTを適用するタイムゾーンで冬/夏の時計の変更時間を無視する場合

答え2

誰かが役に立つと思う場合に備えて残しておきます。しかし、それを使用してください。この回答代わりに。よりシンプルで効率的です。


Perlメソッドは次のとおりです。

$ perl -lne 'if(/^\[([^]]+)/){$d=$1; chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); $d=~s|/| |g; chomp($d=`date -d "$d" +%s`); print if $d >= $dateThreshold;} ' test.log 
[04/Dec/2019 02:05:13 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser
[04/Dec/2019 02:05:15 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser
[04/Dec/2019 02:04:59 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/check_status HTTP/1.1" returned in 759ms
[04/Dec/2019 02:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2
[04/Dec/2019 03:05:00 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/close_statement HTTP/1.1" returned in 1345ms
[04/Dec/2019 03:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2
[04/Dec/2019 03:05:18 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

そしてもっと明確に言えば:

perl -lne 'if(/^\[([^]]+)/){ ## skip lines that do not match
            ## Save the date of the current line as $d
            $d=$1; 
            ## Replace all slashes with pipes so the 'date' command
            ## can read this as a date.
            $d=~s|/| |g; 
            ## Now, translate $d into seconds since the epoch
            chomp($d=`date -d "$d" +%s`); 
            ## Set the threshold date in seconds since the epoch.
            chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); 
            ## Print this line if its date is greater than or equal to the threshold
            print if $d >= $dateThreshold;
           } ' test.log 

BEGIN最後に、スクリプトの起動時に一度だけ実行されるようにしきい値設定ステップをブロックに移動して、効率を向上させることができます。

perl -lne 'BEGIN{chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); } if(/^\[([^]]+)/){$d=$1; $d=~s|/| |g; chomp($d=`date -d "$d" +%s`); print if $d >= $dateThreshold;} ' test.log 

答え3

awkGNUコマンドを呼び出すGNUを使用した別の答えは次のとおりですdate

awk(私たちが呼ぶ)プログラムは次find_after_timestamp.awkのとおりです。

BEGIN{
    gsub("/"," ",start_datetime)
    extcmd=sprintf("date -d \"%s\" +\"%%Y %%m %%d %%H %%M %%S\"",start_datetime)
    extcmd | getline startstring
    close(extcmd)
    start_ts=mktime(startstring)
    print "Lines will be matched starting with timestamp",start_ts

    printf("Will look for: \"%s\"\n",searchpat)
}


{
    if (match($0,/^\[([[:print:]]*)\][[:print:]]*$/,line_datetime)==0) next
    gsub("/"," ",line_datetime[1])
    extcmd=sprintf("date -d \"%s\" +\"%%Y %%m %%d %%H %%M %%S\"",line_datetime[1])
    extcmd | getline line_dtstring
    close(extcmd)
    line_ts=mktime(line_dtstring)
    if (line_ts > start_ts && $0 ~ searchpat) print
}

あなたはそれを呼ぶでしょう

awk -v start_datetime="04/Dec/2019 02:05:21 -0800" -v searchpat="[Ff]ailed login" -f find_after_timestamp.awk test.log

ここで変数はstart_datetime検索範囲の先頭になります。つまり、日付/時刻がこの時点と同じかそれ以降のすべての項目が考慮されます。値はstart_datetimeログファイルと同じ形式でなければなりませんが、それ以外はランダムであり、ファイルに実際に存在する値である必要はありません。この変数には、searchpat探しているパターンが含まれます。

説明する

  • DD/MONTH/YYYY HH:MM:SS TIMEZONEこの構造は日付部分dateの。を空白に置き換えて(「非標準」ではなく)日付/時刻仕様をGNUが理解できるものに変換することを中心に進みます。/gsub

  • 次に、シェルで文字列を実行し、結果を文字列変数として読み込みdate(設定ステップ、ファイル解析ステップで)外部コマンドを呼び出します。組み込み関数がistを解析できるようにフォーマットされています。extcmdstartstringline_dtstringawkmktime

  • このmktimeコマンドは、人間が読める日時仕様を算術比較を使用して比較できる純粋な数値UNIX時間に変換します。

  • ステップはBEGIN開始日の仕様を変換するために実行され、本文では現在の行に関連付けられているタイムスタンプを変換するために実行されます。タイムスタンプのない行は無視されます(if (match(...)==0) next)。

  • 現在の行に参照開始タイムスタンプより大きい(=以降)タイムスタンプがあり、そのsearchpat行で見つかった場合は、その行が印刷されます。

awkプログラムが外部プログラムに依存する必要があることは少し目を引くことを知っていますが、これはほとんどすべてのインストールで利用可能な基本的なツールを使用して行うことができます。

答え4

sedを使用してください:

sed -n "/$(date +'%d\/%b\/%Y')/,/*/p" test.log | grep -i "failed login"
  • 一致(日付)以降のすべての内容を印刷します。

注:現在の日付はログファイルで確認できる必要があります。

関連情報