如何从远程主机获取最近10分钟的日志

时间:2019-01-08 13:19:32

标签: bash awk ssh sed grep

我正试图从远程主机上的x获取最近/var/log/maillog分钟的日志(我在icinga2中使用此脚本),但是没有运气。

我尝试了awk,sed和grep的几种组合,但似乎都没有用。我以为这是双引号与单引号的问题,但我玩弄它们却无济于事。

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}"

使用bash -x运行脚本时,得到以下输出:

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 myUser@host.domain 'sed -n /^Jan' 8 '12:56/,$p /var/log/maillog'
+ hour_segment=
+ echo ''

Maillog日志文件输出。我希望$hour_segment也看起来像下面的输出,以便可以对其应用过滤器:

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]

2 个答案:

答案 0 :(得分:2)

要想出一个能够百分百防弹的可靠解决方案非常困难,因为我们错过了最重要的信息,即

想象一下,您想获得2020年3月1日在 00:05:00 的最后10分钟的可用数据。自 2020年2月29日存在以来,这有点令人讨厌。但是到了2019年,情况并非如此。

我在这里提出一个丑陋的解决方案,它只关注第三个字段(时间),并且我将做出以下假设:

  • 日志文件按时间排序
  • 每天至少有一个日志!

在这些情况下,我们可以从第一个可用时间开始跟踪滑动窗口

如果您将以下内容保存在文件extractLastLog.awk

中,
{ t=substr($3,1,2)*3600 + substr($3,4,2)*60 + substr($3,7,2) + offset}
(t < to) { t+=86400; offset+=86400 }
{ to = t }
(NR==1) { startTime = t; startIndex = NR }
{ a[NR]=$0; b[NR]=t }
{ while ( startTime+timeSpan*60 <= t ) { 
      delete a[startIndex]
      delete b[startIndex]
      startIndex++; startTime=b[startIndex]
  }
}
END { for(i=startIndex; i<=NR; ++i) print a[i] }

然后您可以通过以下方式提取最后23分钟:

awk -f extractLastLog.awk -v timeSpan=23 logfile.log

我给出的第二个条件(每天至少有一个日志!)需要不弄乱结果。在上面的代码中,我计算时间非常简单,HH*3600 + MM*60 + SS + offset。但是我要声明的是,如果当前时间小于以前的时间,则意味着我们在不同的日期,因此我们将偏移量更新为86400秒。因此,如果您有两个条目,例如:

Jan 09 12:01:02 xxx 
Jan 10 12:01:01 xxx 

它可以工作,但这

Jan 09 12:01:00 xxx 
Jan 10 12:01:01 xxx 

不起作用。它不会意识到日子变了。其他可能失败的情况是:

Jan 08 12:01:02 xxx 
Jan 10 12:01:01 xxx 

,因为它不知道它跳了两天。由于需要几个月的时间(要感谢年),要对此进行校正并不容易。

就像我说的那样,这很丑陋,但可能会起作用。

答案 1 :(得分:2)

使用GNU awk的时间函数:

$ 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

假定当前年份。如果是一月,日志为十二月,则从mktime的日期规范:(nowm=="Jan" && $1=="Dec"?nowy-1:nowy)中减去一年。 Datespec:Jan 6 04:03:37-> 2019 1 6 04 03 37,以比较形式:1546740217

编辑:由于没有人在评论中实现我的规格,因此我将自己完成。 tac反向输出文件,awk在给定时间范围内(t-现在或将来)打印记录,并在遇到时间范围以外的日期后退出:

$ 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
}' 
相关问题