特定のテキストを使用して、現在の日付より後の特定の時間のログをフィルタリングしたいと思います。現在の日付を含むテキストのログを正常にフィルタリングしました。これはコマンドです:
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
ts
fromを使用すると、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を使用すると、次のこともできます。awk
awk
grep -i
tolower()
awk
gawk -v IGNORECASE=1 '$0 > "[2019-12-04T02:50" && /failed login/'
ない場合は、'sを使用してmoreutils
解析を実行できます('sを使用するPerlスクリプトですが、'sとは対照的にコアモジュールの1つではないため、システムにインストールされない可能性があります)。perl
Time::Piece
ts
Date::Parse
Time::Piece
perl
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
awk
GNUコマンドを呼び出す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を解析できるようにフォーマットされています。extcmd
startstring
line_dtstring
awk
mktime
この
mktime
コマンドは、人間が読める日時仕様を算術比較を使用して比較できる純粋な数値UNIX時間に変換します。ステップは
BEGIN
開始日の仕様を変換するために実行され、本文では現在の行に関連付けられているタイムスタンプを変換するために実行されます。タイムスタンプのない行は無視されます(if (match(...)==0) next
)。現在の行に参照開始タイムスタンプより大きい(=以降)タイムスタンプがあり、その
searchpat
行で見つかった場合は、その行が印刷されます。
awk
プログラムが外部プログラムに依存する必要があることは少し目を引くことを知っていますが、これはほとんどすべてのインストールで利用可能な基本的なツールを使用して行うことができます。
答え4
sedを使用してください:
sed -n "/$(date +'%d\/%b\/%Y')/,/*/p" test.log | grep -i "failed login"
- 一致(日付)以降のすべての内容を印刷します。
注:現在の日付はログファイルで確認できる必要があります。