如何组合两个命令来统计压缩和未压缩日志文件的数据?

如何组合两个命令来统计压缩和未压缩日志文件的数据?

我正在运行此命令来获取服务器的登录尝试失败次数,auth.log并且效果良好:

sudo cat /var/log/auth.{log,log.1} | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

但问题是 - 就像世界上的每个服务器一样 - 我有一些由日志轮换创建的 GZipped 档案,该命令无法解析这些档案:

-rw-r----- 1 syslog adm  7822722 Oct 31 13:44 /var/log/auth.log
-rw-r----- 1 syslog adm 12532511 Oct 25 06:59 /var/log/auth.log.1
-rw-r----- 1 syslog adm  2250939 Oct 18 06:55 /var/log/auth.log.2.gz
-rw-r----- 1 syslog adm  2139669 Oct 11 07:06 /var/log/auth.log.3.gz
-rw-r----- 1 syslog adm  2769919 Oct  4 06:54 /var/log/auth.log.4.gz

为了处理这些问题,我有一个使用zcat而不是的命令变体cat,但必须运行两个命令才能获取这些数据,这有点麻烦。有没有办法将catzcat命令合并为一个命令,以便我可以获得合并的结果?我知道我可以编写一些 Bash 脚本来过滤压缩文件和未压缩文件,但我在各种服务器上使用这个当前的单行命令,我希望有一个可以在需要时快速参考和使用的单行命令。

更多细节。

我一直在做一些安全审计和防火墙调整,并运行这个命令,它可以给我提供来自auth.logUbuntu Linux 机器上的文件的“失败密码”尝试次数的详细记录:

sudo cat /var/log/auth.{log,log.1} | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

效果很好!输出如下所示:

 5909 Oct 18
13444 Oct 19
  351 Oct 20
  162 Oct 21
  499 Oct 22
  377 Oct 23
  145 Oct 24
10897 Oct 25
   76 Oct 26
   54 Oct 27
  310 Oct 28
 1024 Oct 29
  208 Oct 30
   30 Oct 31

虽然这种方法对未压缩的日志很有效,但由于日志会轮换并被压缩,因此总会有一些 GZip 压缩文件,这些文件也值得统计。因此,我运行了上述命令的这个变体,它使用zcat

sudo zcat -q /var/log/auth.log* | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

输出如下:

gzip: /var/log/auth.log: not in gzip format

gzip: /var/log/auth.log.1: not in gzip format
  10413 Sep 27
  15977 Sep 28
  12297 Sep 29
  14438 Sep 30
  23394 Oct 1
  12912 Oct 2
  15844 Oct 3
  19697 Oct 4
  15350 Oct 5
  12358 Oct 6
  12692 Oct 7
   8377 Oct 8
  10875 Oct 9
    565 Oct 10
  16027 Oct 11
  10422 Oct 12
   6808 Oct 13
  26891 Oct 14
   9493 Oct 15
   5138 Oct 16
   9415 Oct 17
   2226 Oct 18

cat如您所见,输出在有效时有效,但如果可以将此命令的和变体简单地组合成一个命令,那就太好了zcat。如何做到这一点?

奖励积分:

这些都不是关键问题,但如果能以某种方式解决它们就更好了:

  • 请注意,在输出的顶部,zcat有两个错误是由于zcat尝试处理两个未压缩的文件而产生的。最好能抑制这些错误。
  • cat还请注意和命令如何zcat显示 10 月 18 日的数据;这是发生日志轮换的一天。有没有办法在命令中将这两个值相加?如果没有,我可以接受两行 10 月 18 日的数据,它们有不同的值,我必须手动将它们相加。

答案1

可以使用zgrep,如果需要,它将解压缩,因此既适用于纯文本,也适用于压缩输入。此外,grep/zgrep 可以直接处理多个文件,这是本例所需要的,因为混合压缩和文本到标准输入并不总是按预期工作。使用-h或抑制 grep 输出中的文件名--no-filename

sudo zgrep -h 'Failed password' /var/log/auth.* | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

手册页:

ZGREP(1)                                                              ZGREP(1)

NAME
       zgrep - search possibly compressed files for a regular expression

SYNOPSIS
       zgrep [ grep_options ] [ -e ] pattern filename...

DESCRIPTION
       Zgrep  invokes grep on compressed or gzipped files.  All options specified
       are passed directly to grep.  If no file is specified, then  the  standard
       input  is  decompressed if necessary and fed to grep.  Otherwise the given
       files are uncompressed if necessary and fed to grep.

       If the GREP environment variable is set, zgrep uses it as the grep program
       to be invoked.

AUTHOR
       Charles Levert ([email protected])

SEE ALSO
       grep(1), gzexe(1), gzip(1), zdiff(1), zforce(1), zmore(1), znew(1)

答案2

虽然每次输入都很丑陋,但你可以这样做:

for log in /var/log/auth.log*; do if ! sudo zcat "$log" 2>/dev/null; then sudo cat "$log"; fi; done | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

也许最好至少为该cat部分创建一个函数,例如:

getLogs() {
    for log in /var/log/auth.log*; do
        if ! sudo zcat "$log" 2>&/dev/null; then
            sudo cat "$log"
        fi
    done
}

然后你的命令可以是

getLogs | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c

或者你可以把整个事情变成一个函数:

getSSHFailures() {
    for log in /var/log/auth.log*; do
        if ! sudo zcat "$log" 2>/dev/null; then
            sudo cat "$log"
        fi
    done | grep 'Failed password' | grep sshd | awk '{print $1,$2}' | sort -k 1,1M -k 2n | uniq -c
}

然后你只需打电话

getSSHFailures

然后,您可以在您的函数中定义该函数.bashrc,并在您启动的每个 shell 中使用该函数。

此外,这还应该解决您对尝试非压缩文件的错误的观察zcat(因为我们将zcat错误重定向到/dev/null)并摆脱重复的条目,因为我们在处理它们之前将所有结果作为单个流一起打印。

最后,awk实际上可以为我们进行模式匹配,因此我们也可以摆脱 2,grep例如:

getSSHFailures() {
    for log in /var/log/auth.log*; do
        if ! sudo zcat "$log" 2>/dev/null; then
            sudo cat "$log"
        fi
    done | awk '/sshd.*Failed password/ {print $1,$2}' | sort -k 1,1M -k 2n | uniq -c
}

答案3

相关内容