LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
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 07-21-2010, 06:12 AM   #1
manya
Member
 
Registered: Apr 2004
Posts: 194

Rep: Reputation: 15
Bash Script - Help needed


Hey Guys,

I have written a bash script to perform a traceroute for more than 500 IPs and I will be performing further operations on a output I am receiving.
The only issue I am facing here is, if the IP is not reachable it keep on giving me * * * and I need to eliminate those by some means.
Instead I am looking a way by which as soon as "*" encounters it should kill or jump to the next IP and start the traceroute again.

Does any one aware of any such method?
 
Old 07-21-2010, 06:18 AM   #2
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Traceroute has some options for skipping or working-around those hops which produce the "* * *" output. The man-page for traceroute explains why those "* * *" occur, and what to do about it.

To demonstrate:
Code:
root@reactor: traceroute 204.235.208.17
traceroute to 204.235.208.17 (204.235.208.17), 30 hops max, 60 byte packets
 1  * * *
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  * * *
 7  * * *
 8  * * *
 9  * * *
10  * * *
11  * * *
12  * * *
13  * * *
<snip>
30  * * *
root@reactor:
Becomes this with a couple options:
Code:
root@reactor: traceroute -I -N 1  204.235.208.17
traceroute to 204.235.208.17 (204.235.208.17), 30 hops max, 60 byte packets
 1  2.153.118.216.cpe.seasidehighspeed.com (216.118.153.2)  30.442 ms  29.193 ms  30.033 ms
 2  204.235.208.17 (204.235.208.17)  59.900 ms  39.678 ms  35.001 ms
root@reactor:
If instead, you want your traceroute to output the results (including the asterisks) to screen or file, and use some `sed` or something to filter the asterisks from the output, then show us the script and we may be able to suggest a method of filtering them out.

Hope that helps!

EDIT: But, if this doesn't quite resolve the issue the way you like (as in, if you really want to just quit that IP upon encountering one asterisk, and move to the next IP), some scripting may be necessary if traceroute doesn't have built-in functionality for quitting upon getting some asterisks; check the man page, and if that doesn't help, then show us your code and we can try to work something into it to do what you need.

Last edited by GrapefruiTgirl; 07-21-2010 at 06:21 AM.
 
Old 07-21-2010, 06:46 AM   #3
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
Absolutely...my traceroute doesn't provide any such option which could strip off * and any way my requirement is pretty different.
as you identified it correctly I need to cut or break the sequence as soon as it encounters single "*" and jump to next IP.

Here are my codes and please suggest if you have any bright plan



LIST = "10.1.1.1
192.168.1.5
20.202.202.2
202.54.87.34
.
.
.
.
"

for i in $LIST
do
traceroute -I -z 5 -w 2 $i | awk '{print $2}' | grep -v '.domain.com' | grep -v '*' | grep -v 'traceroute to'

done
 
Old 07-21-2010, 07:33 AM   #4
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Unfortunately, it does not look like there's a way to do this using traceroute alone. Since traceroute doesn't appear to have an option to abort on occurrence of a "*", you are probably doing the best way you can do it already, using grep to filter out the "*" results. The way I see it, traceroute has to actually complete the entire operation before YOU can decide that there are asterisks and then toss the result.

I've come up with a rather brutal way of killing traceroute while it's running, if an asterisk is found in a line of output:

Code:
#!/bin/bash


LIST="204.235.208.17
"

for IP in $LIST; do
  # $count is for debugging only:
  count=0

  traceroute -I -z 5 -w 2 $IP | while read line; do

# next line for debugging only:
    count=$((count+1)); echo "count: $count"

    if [ "$(echo "$line" | grep '*')" ]; then
      killall traceroute || :
      break
    else
      echo $line | awk '{print $2}' | grep -v '.domain.com' | grep -v '*' | grep -v 'traceroute to'
    fi

  done

done
As you can see, I did not test it with your real list of IP addresses, so stick your real IP's in there and see if this works for you. When I tested it on a single IP, it appears to work as you desire. If it "sort of" works, but not quite right, show us what is not working right and I'll try to adjust it.

Basically what it does, is feed the output of traceroute line by line into a while/do loop, which examines each line as it comes; if an "*" is present, traceroute is forcefully killed, the loop while loop exits, and the next IP is chosen and the process starts again.

EDIT: NOTE that a whole line must be received by the while/do loop before that line can be examined; this means that if I line of output from traceroute will contain three "*", then the killing will happen after all three * are generated, because the line is not complete until all three are there. So, it means that the killing will happen after one line containing *, which is better than waiting for the entire traceroute (and line after line of *) completes. If you want to abort sooner again, you'd probably want to add "-q 1" option to the traceroute command, which tells it to only to one query instead of three (hence one asterisk maximum instead of three) but this might also decrease the effectiveness of the traceroute.

Hope this helps.

Last edited by GrapefruiTgirl; 07-21-2010 at 07:55 AM. Reason: Adjusted silly code mistake.
 
Old 07-21-2010, 08:34 AM   #5
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
yeah that looks good but any way I need to carry few tests with it before I could comment on that.

On a side note, would you be able to tell me how too achieve or terminate file by pressing certain key sequence.
Like Press CTRL+D to finish or CTRL+F
 
Old 07-21-2010, 08:43 AM   #6
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
You mean to kill a script? CTRL-C or CTRL-Z are the standard key-codes for killing a running script. You *might* be able to use the `set` bash built-in function to define a different code, but I'm not sure about this as I don't use it much. The bash manpage should have a pretty detailed description of what you can do with `set`, but I don't know if you can do exactly this with it.

If CTRL-C or CTRL-Z work for you, will that do? Or must you use some other key combination?

EDIT: P.S. you may also be able to use the `read` bash builtin with "-t 0" within your loop, to see if a key has been pressed recently, and if it's the "stop" key (whatever key you want to stop the script) then exit. I don't think `read` works well with CTRL codes though, and haven't tested this.

Last edited by GrapefruiTgirl; 07-21-2010 at 08:50 AM.
 
Old 07-21-2010, 09:00 AM   #7
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
Oh no, this is not what I wanted to convey. basically I need to have user enter something in file and want them to keep entering unless they press certain key sequence which would come out of that file and file will be saved. I can use the same file later for other operations.

E.g.
Please Enter all the IP addresses. Press CTRL+F once you are finish
 
Old 07-21-2010, 09:07 AM   #8
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Aha!

OK, well what I do when I need that sort of functionality, is just call an external text editor from my script. You could for example do from you script:

Code:
kwrite /some/path/to/some/file
And at this point, kwrite pops open and the user types stuff and saves it, and upon exiting kwrite, the script continues.

If you don't like that idea, you could just use bash's `read` command in a loop, reading line by line of text entered by the user and echoing the text to a file as they enter it. To terminate the operation, check to see if the line entered is something like "EOF", and if it is, move on to the next part of the script; if it isn't an "EOF" run the loop again and read more entered text. This method isn't much of an editor (it isn't an editor at all) and doesn't allow for corrections-on-the-fly if the user enters an error and hits ENTER, but it's simple. You could ask each time they hit ENTER if the line they typed is correct; if it is, save it and continue; if it is not, get them to enter it again.
 
Old 07-21-2010, 09:38 AM   #9
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
hmm...that's an good idea but not the exact way I was looking for.
I have pasted the exact output below. Please do let me know if you are aware of any such method by which I can achieve it.

You can add GUI Clients using any of the following formats:
1. IP address.
2. Machine name.
3. "Any" - Any IP without restriction.
4. IP/Netmask - A range of addresses, for example 192.168.10.0/255.255.255.0
5. A range of addresses - for example 192.168.10.8-192.168.10.16
6. Wild cards (IP only) - for example 192.168.10.*

Enter GUI Client(Press CTRL+D To Exit): 10.1.1.1
10.1.1.5
10.1.1.6
10.1.1.9
<CTRL+D> Pressed ---> Its hidden though
 
Old 07-21-2010, 09:42 AM   #10
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
I am not aware of a method to grab a CTRL-D as the end signal. There may well be a way, but I don't know it or have forgotten it .

Rather than use the `read` + "EOF" method I gave, you could use `read` and simply have the text session exit upon getting a blank line: "Add GUI Clients .. blah blah .. Press ENTER on a blank line when done"

PS - To facilitate fixing errors as they are entered, I recommend the external text editor method.

Last edited by GrapefruiTgirl; 07-21-2010 at 09:44 AM.
 
Old 07-21-2010, 09:59 AM   #11
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
oh cool....thnks bro for all your help.
 
Old 07-21-2010, 10:03 AM   #12
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
That would be "Sis", not "bro", and you're most welcome. I hope you get it working well. Let us know how it goes in the end.
 
Old 07-21-2010, 12:52 PM   #13
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by GrapefruiTgirl View Post
I am not aware of a method to grab a CTRL-D as the end signal. There may well be a way, but I don't know it or have forgotten it
Hi Sasha

Ctrl+D ends the input so there is no need to code anything explicitly as this code can be used to show
Code:
#!/bin/bash

while read line
do 
	echo "DEBUG: line is '$line'"
done
echo "DEBUG: read loop terminated"
 
Old 07-21-2010, 12:58 PM   #14
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Hi catkin nice to see you.

Thanks for that! I had no idea :/
 
Old 07-22-2010, 03:38 AM   #15
manya
Member
 
Registered: Apr 2004
Posts: 194

Original Poster
Rep: Reputation: 15
Thanks both of you..even I had no idea about it

And Sasha my apologies...
 
  


Reply



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
[SOLVED] Bash script needed to move files to another folder. No_one_knows_me Linux - General 28 01-07-2010 10:29 PM
Bash script needed with 2 variables for AIX . rajveervashisth Programming 3 08-05-2008 12:31 AM
Bash script. help needed tazthecat Linux - General 2 09-30-2005 01:54 AM
bash script help needed Henster Linux - General 4 08-21-2005 09:54 AM
Wrapper needed for BASH Script outspoken Programming 0 01-12-2005 09:04 AM

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

All times are GMT -5. The time now is 07:55 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