我正在运行此命令来获取服务器的登录尝试失败次数,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
,但必须运行两个命令才能获取这些数据,这有点麻烦。有没有办法将cat
和zcat
命令合并为一个命令,以便我可以获得合并的结果?我知道我可以编写一些 Bash 脚本来过滤压缩文件和未压缩文件,但我在各种服务器上使用这个当前的单行命令,我希望有一个可以在需要时快速参考和使用的单行命令。
更多细节。
我一直在做一些安全审计和防火墙调整,并运行这个命令,它可以给我提供来自auth.log
Ubuntu 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
做
zcat -f /var/log/auth.log*