How to get the percentage of packets received from Ping in bash?

When checking the host, I want my output to show the percentage of packets received (5 sent). I suppose I need to use grep somehow, but I can't figure out how (I'm new to bash programming). This is where I am: ping -c 5 -q $host | grep ? ping -c 5 -q $host | grep ? . What should go in grep? I think I will need to do some arithmetic to get the interest received, but I can handle it. How can I get the information I need from the resume that ping displays?

+4
source share
6 answers

As always, there are many different ways to do this. But here is one option:

This expression will record the percentage of the "loss of X% packets"

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

You can then subtract the percentage loss from 100 to get the percentage of "success":

 packet_loss=$(ping -c 5 -q $host | grep -oP '\d+(?=% packet loss)') echo $[100 - $packet_loss] 
+6
source

So far, we have received the answer using grep, sed, perl, bc and bash. Here is one example of AWK , "an interpreted programming language designed for word processing." This approach is for viewing / recording real-time loss information using ping .

To see packet loss information only :

Command

 $ 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 }' 

Output

 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 

However, it’s also useful for me to see the original input. To do this, simply add print $0; to the last block in the script:

Command

 $ 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; }' 

Output

 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 

How does it all work?

You read the team, tried it, and it works! So what exactly is going on?

 $ ping google.com | awk '...' 

We start with pinging google.com and outputting the output to the awk interpreter. Everything in single quotes defines the logic of our script.

Here it is in a friendly format in the whitespace format:

 # 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; } 

We can break it down into three components:

 { gather data } { calculate loss } { output } 

Each time ping prints information, the AWK script will consume it and run this logic against it.

Data collection

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

It has three actions; defining the variables sent , received and loss .

 sent=NR-1; 

NR is the AWK variable for the current number of records. In AWK, the entry corresponds to a string. In our case, one line of output from ping. The first line of output from ping is the header and does not represent the actual ICMP request. Therefore, we create the variable sent and assign it the current line number minus one.

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

Here we use Regular Expresssion , ^.*(time=.+ ms).*$ To determine if the ICMP request was successful or not. Since every successful ping returns the time it takes, we use this as our key.

For those that are not very good with regex patterns, this is what ours means:

  • ^ starting at the beginning of a line
  • .* matches anything until the next rule
  • (time=.+ ms) matches "time = N ms", where N can be one or more characters
  • .* matches anything until the next rule
  • $ stop at end of line

When the pattern matches, we increment the received variable.

Calculate loss

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

Now that we know how many ICMP requests have been sent and received, we can begin to do the math to determine packet loss. To avoid dividing by zero , we check to see if a request has been sent before performing any calculations. The calculation itself is quite simple:

  • received/sent = percent success rate in decimal
  • *100 = convert from decimal to integer format
  • 100- = invert percent success to error

Output

 { print $0; printf "sent:%d received:%d loss:%d%%\n", sent, received, loss; } 

Finally, we just need to print the relevant information.


I do not want to remember all this

Instead of typing this in each time or looking for this answer, you can save the script to a file (e.g. packet_loss.awk ). Then all you need to enter:

 $ ping google.com | awk -f packet_loss.awk 
+8
source

Assuming your ping results look like this:

  PING host.example (192.168.0.10) 56 (84) bytes of data.

 --- host.example ping statistics ---
 5 packets transmitted, 5 received, 0% packet loss, time 4000ms
 rtt min / avg / max / mdev = 0.209 / 0.217 / 0.231 / 0.018 ms

ping -c 5 -q through:

 grep -E -o '[0-9]+ received' | cut -f1 -d' ' 

Productivity:

  5 

And then you can do your arithmetic.

+3
source
 echo $((100-$(ping -c 5 -q www.google.hu | sed -rn "/packet loss/ s@. *([0-9]+)%.*@\ 1@p "))) 
+1
source

Try running the script:

 /bin/bash rec=ping -c $1 -q $2 | grep -c "$2" | sed -r 's_$_ / \$1_' | xargs expr 

Save it and run it with two command line arguments. The first is the number of packets, the second is the host.

0
source

Does this work for you?

 bc -l <<<100-$(ping -c 5 -q $host | grep -o '[0-9]% packet loss' | cut -f1 -d% ) 

It takes the percentage reported by ping and subtracts it from 100 to get the percentage of packets received.

0
source

Source: https://habr.com/ru/post/1383681/


All Articles