Wednesday, October 27, 2021

[SOLVED] How to get last 10 minutes of logs from remote host

Issue

I'm trying to get the last x minutes of logs from /var/log/maillog from a remote host (I'm using this script within icinga2) but having no luck.

I have tried a few combinations of awk, sed, and grep but none have seemed to work. I thought it was an issue with double quotes vs single quotes but I played around with them and nothing helped.

host=$1
LOG_FILE=/var/log/maillog

hour_segment=$(ssh -o 'StrictHostKeyChecking=no' myUser@${host} 2>/dev/null "sed -n "/^$(date --date='10 minutes ago' '+%b %_d %H:%M')/,\$p" ${LOG_FILE}")

echo "${hour_segment}"

When running the script with bash -x, I get the following output:

bash -x ./myScript.sh host.domain
+ host=host.domain
+ readonly STATE_OK=0
+ STATE_OK=0
+ readonly STATE_WARN=1
+ STATE_WARN=1
+ LOG_FILE=/var/log/maillog
+++ date '--date=10 minutes ago' '+%b %_d %H:%M'
++ ssh -o StrictHostKeyChecking=no [email protected] 'sed -n /^Jan' 8 '12:56/,$p /var/log/maillog'
+ hour_segment=
+ echo ''

Maillog log file output. I'd like $hour_segment to look like the below output also so I can apply filters to it:

head -n 5 /var/log/maillog
Jan  6 04:03:36 hostname imapd: Disconnected, ip=[ip_address], time=5
Jan  6 04:03:36 hostname postfix/smtpd[9501]: warning: unknown[ip_address]: SASL LOGIN authentication failed: authentication failure
Jan  6 04:03:37 hostname imapd: Disconnected, ip=[ip_address], time=5
Jan  6 04:03:37 hostname postfix/smtpd[7812]: warning: unknown[ip_address]: SASL LOGIN authentication failed: authentication failure
Jan  6 04:03:37 hostname postfix/smtpd[7812]: disconnect from unknown[ip_address]

Solution

Using GNU awk's time functions:

$ awk '
BEGIN {
    m["Jan"]=1               # convert month abbreviations to numbers 
    # fill in the rest       # fill in the rest of the months
    m["Dec"]=12
    nowy=strftime("%Y")      # assume current year, deal with Dec/Jan below
    nowm=strftime("%b")      # get the month, see above comment
    nows=strftime("%s")      # current epoch time
}
{                            # below we for datespec for mktime
    dt=(nowm=="Jan" && $1=="Dec"?nowy-1:nowy) " " m[$1] " " $2 " " gensub(/:/," ","g",$3)
    if(mktime(dt)>=nows-600) # if timestamp is less than 600 secs away
        print                # print it
}' file

Current year is assumed. If it's January and log has Dec we subtract one year from mktime's datespec: (nowm=="Jan" && $1=="Dec"?nowy-1:nowy). Datespec: Jan 6 04:03:37 -> 2019 1 6 04 03 37 and for comparison in epoch form: 1546740217.

Edit: As no one implemeted my specs in the comments I'll do it myself. tac outputs file in reverse and the awk prints records while they are in given time frame (t-now or future) and exits once it meets a date outside of the time frame:

$ tac file | awk -v t=600 '   # time in seconds go here
BEGIN {
    m["Jan"]=1
    # add more months
    m["Dec"]=12
    nowy=strftime("%Y")
    nowm=strftime("%b")
    nows=strftime("%s")
} {
    dt=(nowm=="Jan" && $1=="Dec"?nowy-1:nowy) " " m[$1] " " $2 " " gensub(/:/," ","g",$3)
    if(mktime(dt)<nows-t)     # this changed some
        exit                
    else 
        print
}' 


Answered By - James Brown