到目前为止,我们已经使用grep、sed、perl、bc和bash得到了一个答案。这里有一种
AWK味道的方法,“一种专为文本处理设计的解释性编程语言”。这种方法旨在使用
ping观察/捕获实时数据包丢失信息。
要仅查看数据包丢失信息:
命令
$ ping google.com | awk '{ sent=NR-1; received+=/^.*(time=.+ ms).*$/; loss=0; } { if (sent>0) loss=100-((received/sent)*100) } { printf "sent:%d received:%d loss:%d%%\n", sent, received, loss }'
输出
sent:0 received:0 loss:0%
sent:1 received:1 loss:0%
sent:2 received:2 loss:0%
sent:3 received:2 loss:33%
sent:4 received:2 loss:50%
sent:5 received:3 loss:40%
^C
然而,我发现查看原始输入也很有用。为此,您只需在脚本的最后一个块中添加
print $0;
即可:
命令
$ ping google.com | awk '{ sent=NR-1; received+=/^.*(time=.+ ms).*$/; loss=0; } { if (sent>0) loss=100-((received/sent)*100) } { print $0; printf "sent:%d received:%d loss:%d%%\n", sent, received, loss; }'
输出
PING google.com (173.194.33.104): 56 data bytes
sent:0 received:0 loss:0%
64 bytes from 173.194.33.46: icmp_seq=0 ttl=55 time=18.314 ms
sent:1 received:1 loss:0%
64 bytes from 173.194.33.46: icmp_seq=1 ttl=55 time=31.477 ms
sent:2 received:2 loss:0%
Request timeout for icmp_seq 2
sent:3 received:2 loss:33%
Request timeout for icmp_seq 3
sent:4 received:2 loss:50%
64 bytes from 173.194.33.46: icmp_seq=4 ttl=55 time=20.397 ms
sent:5 received:3 loss:40%
^C
这一切是如何运作的?
您阅读了命令,尝试了一下,它起作用了!那么到底发生了什么?
$ ping google.com | awk '...'
我们首先通过ping google.com并将输出内容
管道传输到解释器
awk
中。单引号中的所有内容定义了脚本的逻辑。
以下是以友好的空格格式呈现的脚本:
# Gather Data
{
sent=NR-1;
received+=/^.*(time=.+ ms).*$/;
loss=0;
}
# Calculate Loss
{
if (sent>0) loss=100-((received/sent)*100)
}
# Output
{
print $0; # remove this line if you don't want the original input displayed
printf "sent:%d received:%d loss:%d%%\n", sent, received, loss;
}
我们可以将其分解成三个组件:
{ gather data } { calculate loss } { output }
每次 ping 输出信息时,AWK 脚本将会消耗它并对其运行此逻辑。
收集数据
{ sent=NR-1
这个例子有三个动作:定义
sent
、
received
和
loss
变量。
sent=NR-1
NR
是AWK变量,用于表示当前记录数。在AWK中,一条记录对应一行。在我们的例子中,一次ping操作输出的单行即为一条记录。而ping的第一行输出是一个标题,不代表实际的ICMP请求。因此,我们创建一个变量sent
,并将其赋值为当前行号减一。
received+=/^.*(time=.+ ms).*$/
这里我们使用一个
正则表达式^.*(time=.+ ms).*$
来判断ICMP请求是否成功。由于每个成功的ping都会返回所用时间,因此我们将其作为关键词。
对于那些不太熟悉正则表达式模式的人,这就是我们的意思:
^
从行首开始
.*
匹配任何内容直到下一条规则
(time=.+ ms)
匹配“time=N ms”,其中N可以是一个或多个任意字符
.*
匹配任何内容直到下一条规则
$
匹配行尾
当匹配到该模式时,我们会增加变量
received
的值。
计算丢失率
{ if (sent>0) loss=100-((received/sent)*100) }
现在我们知道发送和接收的ICMP请求数量,我们可以开始进行数学计算以确定数据包丢失情况。为了避免
除以零错误,在进行任何计算之前,我们要确保已经发送了请求。计算本身非常简单:
received/sent
= 十进制格式下的成功率百分比
*100
= 从十进制转换到整数格式
100-
= 将成功率百分比反转为失败率百分比
输出
{ print $0; printf "sent:%d received:%d loss:%d%%\n", sent, received, loss; }
最后我们只需要打印相关信息。
我不想记住这些
你可以将脚本保存到文件中(例如packet_loss.awk
),而不是每次都输入或查找答案。然后,你只需要输入:
$ ping google.com | awk -f packet_loss.awk