我正试图从远程主机上的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]
答案 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
}'