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; }
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 format100-
= 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