linux - 如何在 bash 中获取从 Ping 收到的数据包的百分比?

标签 linux bash ping

当对主机执行 ping 操作时,我希望我的输出仅显示接收到的数据包(已发送 5 个)的百分比。我假设我需要以某种方式使用 grep 但我不知道如何使用(我是 bash 编程的新手)。这是我所在的位置:ping -c 5 -q $host | grep ?。 grep 应该放些什么?我想我将不得不做一些算术来获得收到的百分比,但我可以处理这个问题。如何从 ping 输出的摘要中提取我需要的信息?

最佳答案

到目前为止,我们已经使用 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; 添加到脚本的最后一个 block :

命令

$ 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 和 piping the output进入解释器 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; received+=/^.*(time=.+ ms).*$/; loss=0; }

这个有三个 Action ;定义 sentreceivedloss 变量。

sent=NR-1;

NR 是当前记录数的 AWK 变量。在 AWK 中,一条记录对应一行。在我们的例子中,只有一行来自 ping 的输出。 ping 的第一行输出是一个 header ,并不代表实际的 ICMP 请求。因此,我们创建了一个变量,sent,并将当前行号减一赋值给它。

received+=/^.*(time=.+ ms).*$/;

这里我们使用 Regular Expresssion , ^.*(time=.+ ms).*$,判断ICMP请求是否成功。由于每次成功的 ping 都会返回所花费的时间长度,因此我们将其用作我们的 key 。

对于那些不擅长正则表达式模式的人,这就是我们的意思:

  1. ^ 从行首开始
  2. .* 匹配任何内容直到下一个规则
  3. (time=.+ ms)匹配“time=N ms”,其中N可以是一个或多个任意字符
  4. .* 匹配任何内容直到下一个规则
  5. $停在行尾

当模式匹配时,我们增加 received 变量。

计算损失

{ if (sent>0) loss=100-((received/sent)*100) }

现在我们知道发送和接收了多少 ICMP 请求,我们可以开始计算以确定数据包丢失。为了避免 divide by zero错误,我们确保在进行任何计算之前已发送请求。计算本身非常简单:

  1. received/sent = 十进制格式的成功百分比
  2. *100 = 从十进制格式转换为整数格式
  3. 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

关于linux - 如何在 bash 中获取从 Ping 收到的数据包的百分比?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8314219/

相关文章:

linux - 当字节数写入标准输入或标准输出时,write() 系统调用的哪个参数在 if block 中被评估

linux - shell脚本重命名文件夹中的文件保持顺序

networking - Traceroute:发送的所有探测包路径是否相同?

安卓子网扫描

linux - 我想从命令输出到 shell expect 中的变量

linux - 从文件 shell 脚本中获取子字符串

linux - 在 linux 内核中,free_irq 会使系统处于危险之中吗?

python - 如何将错误消息从 shell 脚本传递到 Python 脚本?

linux - 尝试加入 ps 和 pwdx linux 命令的输出

macos - 如何让 OS X 读取 .bash_profile 而不是 .profile 文件