37603


【追記】  
コメントをいただき、以下の方法で指定期間内（例は10分前～現在）のログを抽出することはできました。  
しかし、これでは月をまたいだ抽出ができません。  
度々失礼して申し訳ないですが、他の手法をご存知の方がいらっしゃいましたらご教授お願いします。

[code]

    #!/bin/bash
    
    nowtime=`date +'%b %d %H:%M:%S'`
    agotime=`date -d '10 minutes ago' +'%b %d %H:%M:%S'`
    
    cat /var/log/maillog |awk -F - -v nowtime="$nowtime" -v agotime="$agotime" 'agotime < $1 && $1 <= nowtime'
    
[/code]

* * *

お世話になります。  
OS:CentOS 6.9  
メールログを定期的に抽出したいと思っています。  
例えば8月23日12:00～12:10のメールログを抽出したい場合、以下のコマンドで抽出できました。

[code]

    cat /var/log/maillog |awk -F - '"Aug 23 12:00:00" < $1 && $1 <= "Aug 23 12:10:00"'
    
[/code]

しかし、以下のように変数に代入し、実行してもメールログを抽出することができませんでした（エラーも出ません）

[code]

    #!/bin/bash
    
    nowtime="Aug 23 12:10:00"
    agotime="Aug 23 12:00:00"
    
    cat /var/log/maillog |awk -F - '"$agotime" < $1 && $1 <= "$nowtime"'
    
[/code]

以下のようにシングルクォートとダブルクォートを変更してみたり色々と試してはみましたが、エラーになるなどして全てダメでした。

[code]

    cat /var/log/maillog |awk -F - "'$agotime' < $1 && $1 <= '$nowtime'"
    
[/code]

最終的には以下のように常に最新の日時を取得し、crontabで数分おきに実行したいと考えております。

[code]

    nowtime=`date +'%b %d %H:%M:%S'`
    agotime=`date -d '10 minutes ago' +'%b %d %H:%M:%S'`
    
[/code]

純粋に10分単位のログを抽出するのであれば以下のようにすれば抽出することはできました

[code]

    #!/bin/bash
    
    agotime10=`date -d '10 minutes ago' +'%b %d %H:'`
    minedigit10=`date -d '10 minutes ago' | awk -v FS='' '{print $15}'`
    
    cat /var/log/maillog |grep "${agotime10}${minedigit10}[0-9]"
    
[/code]

しかし、ちょうど10分単位の繰り返しとは限らない場合もあったり、その他諸事情も重なり、日時を指定する形の時間範囲で抽出したいと考えております。  
上記以外の方法でも、特定の時間～現在の時間（特定の時間以降）のログを抽出できる方法があればご教示いただければと思います。  
尚、これらが整えば更にgrepなどで最小限のログを抽出してファイルに出力する予定なので、例としてcatを使っています。

以上、よろしくお願いします。


CC BY-SA 3.0
2017-08-23T13:06:46.643
37440
2017-09-06T03:37:18.380
2017-08-24T08:10:50.060
76
25016
question
bash sh awk
awkを使用して指定期間内のメールログを抽出したい


月をまたいで抽出できないのは、月の名前が単純にソートできないためです。  
月の名前でソートできないなら、ソートできる文字列(数値など)を先頭に足しましょう。

たとえば、月の文字列を `0.01Jan, 0.02Feb, ... , 0.12Dec` と選べば順に並べることができます。

date コマンドでは `0.%m` という書式で、  
awk では `index("..JanFebMarAprMayJunJulAugSepOctNovDec", substr($1, 1, 3))/300`
などとすることで  
数値を得ることができます。

[code]

    #!/bin/bash
    
    nowtime=`date +'0.%m%b %d %H:%M:%S'`
    agotime=`date -d '10 minutes ago' +'0.%m%b %d %H:%M:%S'`
    
    cat /var/log/maillog |awk -F - -v nowtime="$nowtime" -v agotime="$agotime" '{ CONVFMT="%.2f"; d=sub(/^/, index("..JanFebMarAprMayJunJulAugSepOctNovDec", substr($1, 1, 3))/300) } agotime < $d && $d <= nowtime'
    
[/code]

上記のサンプルに入れていませんが、条件に合致した文字列から先頭4文字を避けて切り出してやれば、希望の通りに抽出できると思います。


CC BY-SA 3.0
2017-08-25T12:25:40.680
37489
2017-08-29T03:06:17.030
2017-08-29T03:06:17.030
8431
8431
37440
answer


時間の比較を行う場合、epochからの秒数を求めるのがいちばんシンプルではないかと思います。  
年またぎの処理も比較的容易になります。

[code]

    #!/bin/bash
    
    nowtime=`date +%s`
    agotime=`date -d '10 minutes ago' +%s`
    thisyear=`date +%Y`
    thismonth=`date +%m`
    
    localstr=`date "+%D %T"`
    gmstr=`date "+%D %T" -u`
    localtime=`date -d "$localstr" +%s`
    gmtime=`date -d "$gmstr" +%s`
    timediff=$(($localtime - $gmtime))
    
    cat /var/log/maillog | awk -F - -v nowtime="$nowtime" -v agotime="$agotime" \
        -v thisyear="$thisyear" -v thismonth="$thismonth" \
        -v timediff="$timediff" '{
        m = substr($1, 1, 3)
        mon = (index("JanFebMarAprMayJunJulAugSepOctNovDec", m) + 2) / 3
        year = mon <= thismonth ? thisyear : thisyear - 1
        day = substr($1, 5, 2)
        hh = substr($1, 8, 2)
        mm = substr($1, 11, 2)
        ss = substr($1, 14, 2)
    
        if (mon < 3) {mon += 12; year--}
        epochtime = (365 * year + int(year / 4) - int(year / 100) + int(year / 400) \
            + int(306 * (mon + 1) / 10) - 428 + day - 719163) * 86400 \
            + (hh * 3600) + (mm * 60) + ss - timediff;
    } agotime < epochtime && epochtime <= nowtime'
    
[/code]


CC BY-SA 3.0
2017-08-30T05:43:30.143
37603
2017-09-06T03:37:18.380
2017-09-06T03:37:18.380
25106
25106
37440
answer