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

aus*_*inn 5 linux bash ping

在ping主机时,我希望我的输出只显示收到的数据包的百分比(已发送5个).我假设我需要以grep某种方式使用,但我无法弄清楚如何(我是bash编程的新手).我就在这里:ping -c 5 -q $host | grep ?.grep应该怎么做?我想我必须做一些算术来获得收到的百分比,但我可以处理.如何从ping将输出的摘要中提取出我需要的信息?

Exi*_*ide 10

到目前为止,我们已经得到了使用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 }'
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)

但是,我发现查看原始输入也很有用.为此,您只需添加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; }'
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)

这一切都有用吗?

你读了命令,尝试过它,它的工作原理!究竟发生了什么?

$ ping google.com | awk '...'
Run Code Online (Sandbox Code Playgroud)

我们首先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;
}
Run Code Online (Sandbox Code Playgroud)

我们可以将其分为三个部分:

{ gather data } { calculate loss } { output }
Run Code Online (Sandbox Code Playgroud)

每次ping输出信息时,AWK脚本将使用它并对其运行此逻辑.

收集资料

{ sent=NR-1; received+=/^.*(time=.+ ms).*$/; loss=0; }
Run Code Online (Sandbox Code Playgroud)

这个有三个动作; 定义sent,receivedloss变量.

sent=NR-1;
Run Code Online (Sandbox Code Playgroud)

NR是当前记录数的AWK变量.在AWK中,记录对应于一条线.在我们的例子中,ping的一行输出.ping的第一行输出是标头,不代表实际的ICMP请求.因此,我们创建一个变量,sent并为其分配当前行号减1.

received+=/^.*(time=.+ ms).*$/;
Run Code Online (Sandbox Code Playgroud)

这里我们使用一个普通Expresssion,^.*(time=.+ ms).*$以确定是否ICMP回应请求是成功还是失败.由于每次成功的ping都会返回它所花费的时间长度,因此我们将其用作关键字.

对于那些不具备正则表达式模式的人来说,这就是我们的意思:

  1. ^ 从行的开头开始
  2. .* 匹配任何东西直到下一个规则
  3. (time=.+ ms) 匹配"time = N ms",其中N可以是任何字符中的一个或多个
  4. .* 匹配任何东西直到下一个规则
  5. $ 停在最后一行

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

计算损失

{ if (sent>0) loss=100-((received/sent)*100) }
Run Code Online (Sandbox Code Playgroud)

现在我们知道发送和接收了多少ICMP请求,我们可以开始进行数学运算以确定丢包.为避免除以零错误,我们确保在进行任何计算之前已发送请求.计算本身很简单:

  1. received/sent =十进制格式的成功百分比
  2. *100 =从十进制转换为整数格式
  3. 100- =将成功的百分比反转为失败

产量

{ print $0; printf "sent:%d received:%d loss:%d%%\n", sent, received, loss; }
Run Code Online (Sandbox Code Playgroud)

最后,我们只需要打印相关信息.


我不想记住这一切

您可以将脚本保存到文件中(例如packet_loss.awk),而不是每次都输入该内容,或者搜索此答案.然后您需要输入的是:

$ ping google.com | awk -f packet_loss.awk
Run Code Online (Sandbox Code Playgroud)


Mar*_*tin 9

和往常一样,有很多不同的方法可以做到这一点.但是这里有一个选择:

此表达式将捕获"X%数据包丢失"中的百分比数字

ping -c 5 -q $host | grep -oP '\d+(?=% packet loss)'
Run Code Online (Sandbox Code Playgroud)

然后,您可以从100中减去"损失"百分比,以获得"成功"百分比:

packet_loss=$(ping -c 5 -q $host | grep -oP '\d+(?=% packet loss)')
echo $[100 - $packet_loss]
Run Code Online (Sandbox Code Playgroud)