Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何从远程主机获取最后10分钟的日志_Bash_Awk_Ssh_Sed_Grep - Fatal编程技术网

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

Bash 如何从远程主机获取最后10分钟的日志,bash,awk,ssh,sed,grep,Bash,Awk,Ssh,Sed,Grep,我试图从远程主机(我在icinga2中使用此脚本)获取最后一次x分钟的日志(代码>/var/log/maildog) 我尝试过awk、sed和grep的几种组合,但似乎都不起作用。我认为双引号和单引号是一个问题,但我一直在玩弄它们,没有任何帮助 host=$1 LOG_FILE=/var/log/maillog hour_segment=$(ssh -o 'StrictHostKeyChecking=no' myUser@${host} 2>/dev/null "sed -n "/^$(

我试图从远程主机(我在icinga2中使用此脚本)获取最后一次
x
分钟的日志(代码>/var/log/maildog)

我尝试过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 ''
邮件日志文件输出。我希望
$hour\u段
看起来也像下面的输出,以便我可以对其应用过滤器:

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]

提出一个100%防弹的健壮解决方案是非常困难的,因为我们错过了最关键的信息,

假设您想要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] }
我给出的第二个条件(每天至少有一个日志!)是为了不把结果搞砸。在上面的代码中,我计算时间非常简单,
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 
因为它不知道它跳了两天。由于月份的原因,纠正这一点并不容易(这一切都要归功于闰年)


正如我所说,这很难看,但可能会起作用。

使用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
假设为本年度。如果是一月,log有十二月,我们从
mktime
的日期spec:
(nowm==“Jan”和&$1==“Dec”?nowy-1:nowy)
。日期规格:
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
}' 
$tac file | awk-v t=600'#时间(秒)到这里
开始{
m[“一月”]=1
#再加上几个月
m[“Dec”]=12
nowy=strftime(“%Y”)
nowm=strftime(“%b”)
nows=strftime(“%s”)
} {
dt=(nowm==“一月”和&$1==“十二月”?nowy-1:nowy)“m[$1]”“$2”gensub(/:/,”“,”g“,$3)

if(mktime(dt)请发布一些具有预期输出的示例数据。我已将maillog输出添加到帖子中。此格式存在很多问题:表单的日期
Jan 6 04:03:36
不可排序为
Feb 29
,并且没有年份,这意味着很难确定您需要哪一个一月。2019年的一个或从1919年开始,我查看了我必须使用的邮件日志,它们是轮换的。可以安全地说,在给定的日志文件中只会有“1”个1月吗?非常好!只是要明确一点,只有当您的日志文件具有最多1年的数据时,这才有效。是的。正确的方法是使用
tac
进行反向操作一旦有超过10分钟的时间戳,就记录并退出。我会将此规范留在这里,让其他人来实际实现它。谢谢!没有年份似乎真的很痛苦。我会尝试一下,看看会发生什么:)用另一个版本更新。喜欢最后的评论。它很难看,但可能有用。:DNice one!另一个尝试选项,谢谢你的输入!
$ 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
}'