LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
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 06-19-2008, 03:13 PM   #1
BinWondrin
Member
 
Registered: Jun 2008
Distribution: Fedora, RHEL, Ubuntu
Posts: 33

Rep: Reputation: 15
bash child process


Hi folks,
I regularly run scripts that access up to 100 servers to modify, query, install or whatever.
The script steps through a file containing the names of all the servers and then does its thing on one after another (using ssh sudo ...).
It happens sometimes that a server does not respond. In that case the script usually hangs.
I would like to run each server access as a kind of child process so that the script doesn't die just because one server out of a bunch did not respond.
Maybe I should spawn child processes, keep track of the PID and kill them if they don't finish within a certain amount of time.

Here is part of my script template:

Code:
until [ $done ]
do
read <&3 servername
        if [ $? != 0 ]; then
                done=1
                continue
        fi
        RESULT1=`ssh $servername "sudo command goes here " 2> /dev/null`
        RESULT2=`ssh $servername "sudo command goes here " 2> /dev/null`
        echo $RESULT1 $RESULT2 $servername
done



Any ideas, sample code etc. would be welcome.

Just BinWondrin
 
Old 06-19-2008, 03:18 PM   #2
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
I usually ping the remote server before attempting any operation:
Code:
if ping -c1 -W1 $servername > /dev/null
then
    echo remote server is up and running
else
    echo remote server is down
fi
just to illustrate.
 
Old 06-19-2008, 04:08 PM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,467

Rep: Reputation: 846Reputation: 846Reputation: 846Reputation: 846Reputation: 846Reputation: 846Reputation: 846
Quote:
Maybe I should spawn child processes, keep track of the PID and kill them if they don't finish within a certain amount of time.
That sounds like a good idea, as a bonus if none of servers are down, you would get a x100 speed up, on the other hand, I think you would have to collect the output into a file, or do the processing in the child process. The ping option is certainly easier as long the server doesn't fail after the ping but before the ssh command finishes.

Also I think that loop could be rewritten as
Code:
while read servername ; do
        RESULT1=`ssh $servername "sudo command goes here " 2> /dev/null`
        RESULT2=`ssh $servername "sudo command goes here " 2> /dev/null`
        echo $RESULT1 $RESULT2 $servername
done <&3
 
Old 06-19-2008, 04:45 PM   #4
BinWondrin
Member
 
Registered: Jun 2008
Distribution: Fedora, RHEL, Ubuntu
Posts: 33

Original Poster
Rep: Reputation: 15
Thanks for the replies.
Unfortunately I cannot ping the servers because most of them are firewalled and will only accept traffic on port 22.
 
Old 06-19-2008, 05:01 PM   #5
BinWondrin
Member
 
Registered: Jun 2008
Distribution: Fedora, RHEL, Ubuntu
Posts: 33

Original Poster
Rep: Reputation: 15
I tried that shorter cleaner loop but it only reads the 1st servername, executes the commands and exits.
Here is part of my echotime script. I wrote this initially to check if all servers are reachable before I run any other scripts. Kind of like the "ping" idea mentioned above.

I modified the loop as you suggested but it reads only the first servername before it exits. What am I missing?
Code:
# read til the end of the file
while read servername ; do
    printf '%15s' "$servername"
    /usr/bin/time -o temp.$$ -f %e ssh $servername exit 2> /dev/null
    RESULT1=`awk ' { print $1 } ' temp.$$`
    COMPARE=`awk ' { print $1 * 1000 } ' temp.$$`
    let "DASHES"="($COMPARE / 25) - 2"
    printf '%10s' "$RESULT1   |"
    cnt=0
    while [ $cnt -lt $DASHES ]; do
        printf "-"
        let cnt=$cnt+1
    done
    printf '>\n'
done <&3
 
Old 06-19-2008, 05:07 PM   #6
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,374
Blog Entries: 54

Rep: Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872Reputation: 2872
Quote:
Originally Posted by BinWondrin View Post
Maybe I should spawn child processes, keep track of the PID and kill them if they don't finish within a certain amount of time.
You could let the child kill itself:
Code:
child() { function killSelf() { sleep ${sleep:=10s}; kill $$; }; killSelf & disown %1; $someCommand; }


Quote:
Originally Posted by BinWondrin View Post
Unfortunately I cannot ping the servers because most of them are firewalled and will only accept traffic on port 22.
Try netcat:
Code:
nc -w 2 -z remoteHost 22 >/dev/null && doSomething || dont
 
Old 06-19-2008, 05:25 PM   #7
BinWondrin
Member
 
Registered: Jun 2008
Distribution: Fedora, RHEL, Ubuntu
Posts: 33

Original Poster
Rep: Reputation: 15
Hey UnSpawn,

I am really impressed by the "nc" option. This is a function that I was marginally aware of but it did not really occur to me to use it. It just wasn't part of my day-2-day toolkit.
I love it! I checked out the man page for "nc" and I can already see all kinds of uses for it.
So, thank you for pointing that one out to me. It will certainly be used.

I have to wrap my mind around the child() function. I will try it out and if I can make it work it will be way quicker than what I am doing now.
 
Old 06-19-2008, 05:26 PM   #8
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by BinWondrin View Post
Thanks for the replies.
Unfortunately I cannot ping the servers because most of them are firewalled and will only accept traffic on port 22.
You have a few options:
  1. You can “ping” on port 22 using netcat or similar.
  2. You might change the ConnectTimeout option if you are using OpenSSH.
  3. You can use the following construct:
    Code:
    RESULT1=`ssh $servername "sudo command goes here " 2> /dev/null & sleep 10 && kill %1`
    The reason this works is that you already start a subshell with “``”.

Edit: Wow, I need to refresh more often. 3 posts before I hit submit!

Last edited by osor; 06-19-2008 at 05:27 PM.
 
Old 06-19-2008, 05:34 PM   #9
BinWondrin
Member
 
Registered: Jun 2008
Distribution: Fedora, RHEL, Ubuntu
Posts: 33

Original Poster
Rep: Reputation: 15
All of them GREAT ANSWERS.

I am really impressed with this forum!

It is a very active forum and the quality of the replies is very high. I am very glad that I joined, folks.

I hope I can pay back somehow.

So thanks again for all of your answers.

Got to go and improve a bunch of scripts!

BinWondrin ( and now I know!)
 
Old 06-19-2008, 06:25 PM   #10
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by BinWondrin View Post
I modified the loop as you suggested but it reads only the first servername before it exits. What am I missing?
For further reference, this is a known issue with ssh. By default it tries to read from the standard input and sends a SIGTTIN signal (stop tty input) when exits. If the ssh command is inside a while loop taking input from stdin, the SIGTTIN stops the input and prevents further processing. To avoid this behaviour use the -n option:
Code:
ssh -n user@host
which explicitly redirects stdin from /dev/null, leaving the standard input of the loop untouched.
 
  


Reply

Tags
child, netcat, timeout


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
how a father process know which child process send the signal SIGCHLD icoming Programming 10 07-20-2010 07:26 AM
How to kill a Child and all its subsequent child process in C shayer009 Programming 3 12-04-2007 12:40 AM
Bash child process in foreground while parent dies kborgnis Programming 3 11-09-2007 06:50 AM
Killing a child process from another child marri Programming 6 10-01-2004 07:08 PM
Bash Scripting - child process affecting parent process mthaddon Linux - General 1 05-02-2004 01:19 PM


All times are GMT -5. The time now is 07:42 AM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration