LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-20-2012, 09:44 AM   #1
ali2011
Member
 
Registered: Nov 2011
Location: USA, CA
Distribution: Ubuntu+Fedora
Posts: 80

Rep: Reputation: Disabled
Looping with until and grep:


I am confused about the reason why the following script is reaching the "red" printf for some IPs in the file. This happens although the string "packet loss" that grep looks for ALWAYS exists in with all IPS! In otherwords, ALL hosts should stop from the first until loop (i.e., TRIES = 2).


Code:
#!/bin/sh

INDEX=1;
while read loop; do
TRIES=2;
printf '[%d]\tIP = %-15s\t[%d]\n' $INDEX $loop `expr $TRIES - 1`;
	until sudo ping -i 0.025 -c 2 $loop > $loop.loss && grep -q "packet loss" $loop.loss; do
		if [ "$TRIES" -ge 3 ]; then
			printf '[%d]\tIP = %-15s\t[-]\n' $INDEX $loop;
			break;
			echo "";
		fi;
		printf '[%d]\tIP = %-15s\t[%d]\n' $INDEX $loop $TRIES;
		TRIES=`expr $TRIES + 1`;
	done;
INDEX=`expr $INDEX + 1`;
done < host_ip

Last edited by ali2011; 08-20-2012 at 09:48 AM.
 
Old 08-20-2012, 10:17 AM   #2
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
My question would be ..what the???

I am not understanding how you ever enter the loop? As you are using 'until' and the string "packet loss" is always in the data it will always return true hence you should never enter the loop?

Ahhhh ... a little testing has revealed a light bulb. When ping finds an ip that it cannot reach it will error, however the grep will always find "packet loss" in the resulting file as it
always exists, hence, the anded (&&) statement is false so until will process the loop again. As this ip will never change until the next is read from the file after the completion
of the until loop, the TRIES will eventually be greater than 3 and so the if is launched.

Firstly I would think it better to simply pipe the ping output to grep as a temporary file serves no purpose here, however, it may be prudent to think about what it is you are actually trying to test for??
 
Old 08-20-2012, 11:18 AM   #3
ali2011
Member
 
Registered: Nov 2011
Location: USA, CA
Distribution: Ubuntu+Fedora
Posts: 80

Original Poster
Rep: Reputation: Disabled
grail: The ping if you are not aware enough, even with unreachable hosts it reports 100% packet loss so the statement is there. In contrary, the RTT value will not be there.

Regarding using until and grep, this is working with reachable hosts (i.e., less than 100% packet loss), BUT not working with unreachable hosts!
 
Old 08-20-2012, 12:04 PM   #4
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Try using packet\ loss instead of "packet loss" in you grep command.

And, per grail's comment, here's a somewhat simpler bash version of your script:
Code:
#!/bin/bash
# Initialize the line counter at zero
INDEX=0
# Read the list of IP addresses
while read IP
do
# Increment the line counter
  INDEX=$((++INDEX))
# Write out the line number and IP
  printf '[%d]\tIP = %-15s' ${INDEX} ${IP}
# Try to ping the address a couple of times
  for ((try=1;try<3;++try))
  do
# Ping the IP from a child process.
    (sudo ping -i 0.025 -c 2 ${IP} | grep -q packet\ loss)
# Did the grep command succeed?
    [ $? -eq 0 ] && break
    printf ' (%d failed)' ${try}
  done
  printf '\n'
done < host_ip
<edit>
And here's the output for a segment of my local network
Code:
]$ bash ali2011.sh
[1]     IP = 192.168.1.101  
[2]     IP = 192.168.1.102  
[3]     IP = 192.168.1.103  
[4]     IP = 192.168.1.104  
[5]     IP = 192.168.1.105  
[6]     IP = 192.168.1.106  
[7]     IP = 192.168.1.107  
[8]     IP = 192.168.1.108  
[9]     IP = 192.168.1.109
</edit>

Last edited by PTrenholme; 08-20-2012 at 12:10 PM.
 
Old 08-20-2012, 01:53 PM   #5
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
Here's another look, with an unreachable host in the list. (Note the redirection of the ping error output.)
Code:
#!/bin/bash
# Initialize the line counter at zero
INDEX=0
# Read the list of IP addresses
while read IP
do
# Increment the line counter
  INDEX=$((++INDEX))
# Write out the line number and IP
  printf '[%d]\tIP = %-15s' ${INDEX} ${IP}
# Try to ping the address a couple of times
  for ((try=1;try<3;++try))
  do
# Ping the IP from a child process.
    (sudo ping -i 0.025 -c 2 ${IP} 2>/dev/null | grep -q packet\ loss)
# Did the grep command succeed?
    [ $? -eq 0 ] && break
    printf ' (%d failed)' ${try}
  done
  printf '\n'
done < host_ip
Code:
$ bash ali2011.sh
[1]     IP = 192.168.1.101  
[2]     IP = 192.168.1.102  
[3]     IP = 192.168.1.103  
[4]     IP = 192.168.1.104  
[5]     IP = 192.168.1.105  
[6]     IP = 192.168.1.106  
[7]     IP = www.google.com 
[8]     IP = www.AReallyStrangeIS.nonsense (1 failed) (2 failed)
[9]     IP = www.msn.com
 
Old 08-20-2012, 02:25 PM   #6
ali2011
Member
 
Registered: Nov 2011
Location: USA, CA
Distribution: Ubuntu+Fedora
Posts: 80

Original Poster
Rep: Reputation: Disabled
Thanks PTrenholme:

1- I didn't see the point of piping the error message?
2- I need to pipe the ping's output to a ${IP}.loss whether it succeeded or not.
3- Does the [ $? -eq 0 ] && break act as if statement?

Last edited by ali2011; 08-20-2012 at 02:27 PM.
 
Old 08-20-2012, 02:42 PM   #7
ali2011
Member
 
Registered: Nov 2011
Location: USA, CA
Distribution: Ubuntu+Fedora
Posts: 80

Original Poster
Rep: Reputation: Disabled
Also the string "packet loss" should always appear no matter ping reached the host or not as I mentioned above! Because of that I can't understand why you have in your output "[8] IP = www.AReallyStrangeIS.nonsense (1 failed) (2 failed)"!

If you pipe the output of that host, you should find the string "packet loss"; however if you replace this string by "rtt" your current output makes sense.

Last edited by ali2011; 08-20-2012 at 02:45 PM.
 
Old 08-20-2012, 11:29 PM   #8
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
First off, I'd like to point out that you can probably replace your script with a one line call to nmap. It will not only be simpler, but faster too.


Quote:
Originally Posted by ali2011 View Post
Also the string "packet loss" should always appear no matter ping reached the host or not as I mentioned above! Because of that I can't understand why you have in your output "[8] IP = www.AReallyStrangeIS.nonsense (1 failed) (2 failed)"!
Maybe not:
Code:
~$ ping -c 2 -i 0.025 www.AReallyStrangeIS.nonsense
ping: unknown host www.AReallyStrangeIS.nonsense
~$
Quote:
Originally Posted by ali2011
grail: The ping if you are not aware enough, even with unreachable hosts it reports 100% packet loss so the statement is there. In contrary, the RTT value will not be there.
The ping command returns a failed status code if it can't reach the host, since you put && the grep command is not executed in this case. Note that PTrenholme put |, so the grep is always executed.


Quote:
Originally Posted by PTrenholme
Try using packet\ loss instead of "packet loss" in you grep command.
There is no difference between those two.

Last edited by ntubski; 08-21-2012 at 01:38 PM. Reason: added more context to ali2011's first quote
 
Old 08-21-2012, 01:57 AM   #9
ali2011
Member
 
Registered: Nov 2011
Location: USA, CA
Distribution: Ubuntu+Fedora
Posts: 80

Original Poster
Rep: Reputation: Disabled
ntubski
Regarding the statement I stated "Also the string "packet loss" should always appear no matter ping reached the host or not as I mentioned above!" You said that the string "packet loss may not appear" as in:

Quote:
~$ ping -c 2 -i 0.025 www.AReallyStrangeIS.nonsense
ping: unknown host www.AReallyStrangeIS.nonsense
Your argument is correct in some sense, and in another no. The error in here is not a ping failure as it might appear; IT IS a DNS failure to translate the domain-name to a valid IP address (e.g., not a hidden, private or invalid IP) so the ping didn't even get the chance to be executed, right? Otherwise, ping Always sends packets no matter if they reach destination or not.

In my experiment, however, all hosts in the form of public and numeric IPs (i.e., no DNS task is required on them) under my network so this sort of error will not exist.

Last edited by ali2011; 08-21-2012 at 02:03 AM.
 
Old 08-21-2012, 01:43 PM   #10
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by ali2011 View Post
In my experiment, however, all hosts in the form of public and numeric IPs (i.e., no DNS task is required on them) under my network so this sort of error will not exist.
Yeah, PTrenholme's experiment was a bit different though, and it seemed like you were commenting on that. I've added more context to where I quoted you, to make that clearer.
 
Old 08-23-2012, 11:02 AM   #11
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Quote:
Originally Posted by ali2011 View Post
grail: The ping if you are not aware enough, even with unreachable hosts it reports 100% packet loss so the statement is there. In contrary, the RTT value will not be there.

Regarding using until and grep, this is working with reachable hosts (i.e., less than 100% packet loss), BUT not working with unreachable hosts!
So I was away for a couple of days and others have already filled on my behalf, but I thought I would just reiterate:

1. If you read my post again you might see that I agreed with your first point that "packet loss" will always be there (barring ntubski's example)
Quote:
As you are using 'until' and the string "packet loss" is always in the data
2. The reason it works for reachable hosts is because the boolean logic is being satisfied, ie the ping returns success AND (&&) the grep returns success hence the until lip is exited.
However, in the even that the ping is unsuccessful, ie IP not reachable, the grep is never executed as the AND is false if the first expression is false, hence you will receive
an infinite loop and therefore pass TRIES >= 3 so the 'if' is executed

I hope this helps along with the other suggestions of how to fix

btw. In PTrenholme's code, you do not need to separately test the exit code as until (or if in his example) can test it for you
Code:
until sudo ping -i 0.025 -c 2 ${IP} | grep -q 'packet loss'
do
    (( ++TRIES == 3 )) && break
done
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating an alias in ksh that uses grep and includes 'grep -v grep' doug248 Linux - Newbie 2 08-05-2012 02:07 PM
Could someone help me with looping in vb cobrien Programming 9 11-12-2010 08:17 AM
Trying to understand pipes - Can't pipe output from tail -f to grep then grep again lostjohnny Linux - Newbie 15 03-12-2009 10:31 PM
how to grep multiple filters with grep LinuxLover Linux - Enterprise 1 10-18-2007 07:12 AM
ps -ef|grep -v root|grep apache<<result maelstrombob Linux - Newbie 1 09-24-2003 11:38 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:30 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration