Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I would like to create a shell script for rebooting a linux machine in a way that the script just ends when the machine is up and running again (by up and running I mean accepting ssh connections).

The script should perform like (pseudocode):

reboot machine #sth like 'ssh root@MACHINE reboot'
respecting a timeout of 120 secods do:
    try to connect to machine by ssh
    sleep one second if it could not connect
return an error if timed out
return ok if machine is ready for ssh connections

The thing is that I would really like to avoid long sleep commands so that my reboot script gives a result as soon as possible (if it is not a timeout, of course).

Anyone has done something like that?

UPDATE: Starting from adamo's idea I did:

timeout=120
start=$(date +%s)
ssh root@$FAST_HOST reboot
do
  nc -z $1 22
  if [ $? eq 0]; then
    echo host is ready
    exit 0
  fi
  end=$(date +%s)
  diff=$(( $end - $start ))
  if [ $diff -gt timeout ]
    echo timeout
    exit 1
  fi
  sleep 1
done 

My problem is that the nc command takes a long while to return when it can not connect. Any way just to check if the port is open with a very short timeout?

share|improve this question
add comment

4 Answers

up vote 1 down vote accepted

I use something similar to the following to connect to machines during reboots. It expects you to have public key authentication (or some other passwordless authentication) setup.

#!/bin/sh
if [ -z "$1" ] ; then
    echo "You must pass a host to reboot."
fi

HOST="$1"

USER="USER TO SSH AS"
# if the user has the right to reboot a machine without sudo,
# the following can be empty.
SUDO="/usr/bin/sudo"
SSH="/usr/bin/ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=1 $USER@$HOST"

echo -n "Rebooting $HOST..."
if ! $SSH $SUDO reboot ; then
    echo 'FAILED!'
    exit 1
fi
echo "ok."

echo -n "Sleeping 30 seconds..."    
sleep 30
echo "done."

echo -n "Waiting for $HOST..."
while ! $SSH echo -n > /dev/null 2>/dev/null ; do
    echo -n '.'
done
echo "ok."
echo "Machine rebooted successfully."
share|improve this answer
    
It seems to work almost 'out-of-the-box'. Minor changes were on SSH=... it is $HOST instead of $TARGET_HOST and my ssh did not accept --batch option. I will do some testing on both solutions and publish the one I use. Appreciated it! Thanks!! –  Edu Nov 8 '10 at 17:16
    
Er, whoops. I've made the appropriate changes to the above. --batch should have been -o BatchMode=yes and fixed the TARGET_HOST business. –  mark Nov 8 '10 at 17:27
    
It works perfectly. Thank you. –  Edu Nov 9 '10 at 10:13
add comment

Try something like this:

#!/bin/bash
sleep 120
while true
do
  nc -z $1 22
  if [ $? eq 0 ]; then
    echo host is ready
    exit 0
  fi
  sleep 1
done

You need to perfect it (like checking whether an argument was given to the script and stuff...)

share|improve this answer
    
Below there is a try based on the nc -z idea. My problem is the long delay nc has when it can not connect. –  Edu Nov 8 '10 at 14:48
    
The timeout for netcat can be set by the -w 2 parameter (2 seconds in this example). –  weeheavy Nov 8 '10 at 15:07
    
Neat! Works like a charm and made me take out the sleep 1 delay. –  Edu Nov 8 '10 at 16:50
add comment

Try using nmap -p 22 for that. It can be combined with the --*-rtt-timeout set of options if you need to.

On the other hand, what about trying a totally different approach such as SNMP? It seems to be closer to what you need, and it has solved many of the problems you will encounter in trying to reinvent the wheel...

share|improve this answer
    
SNMP seems to be a good idea but I never used it. Any hint on where to start from? –  Edu Nov 8 '10 at 16:49
    
Some good links linux.com/archive/articles/113774 and linuxhomenetworking.com/wiki/index.php/… (albeit a bit more web- and performance-oriented) –  lorenzog Nov 8 '10 at 20:58
add comment

You can use ping inside a loop with a timeout similar to what you have presented above in the question.

You can do one ping at a time and then check its exit status. After getting a successful ping (exit status 0), you can check for SSH.

EDIT:

As another alternative, you can make the remote machine notify you when it is up and running with SSH enabled. For example, you can add a command like this to be executed during the system startup. It can be added in the SSH daemon startup file.

scp /root/dummy_file root@your_machine:~

Of course, this should be done after creating a trust between the two machines (from the remote one to the monitoring one) to avoid asking for a password.

On the monitoring machine, you can delete the file if it exists at the beginning of your script. After rebooting, you can check for the file. If the file exists, the machine is up and running again.

share|improve this answer
    
My problem with ping is that it returns ok for a few times. I can do a sleep before but, for how long is it safe? –  Edu Nov 8 '10 at 14:45
    
I edited my answer to include another way to do it. –  Khaled Nov 8 '10 at 15:16
    
The scp is a good approach but I don't feel comfortable on changing the sshd script that will keep changed if the machine fails rebooting. –  Edu Nov 8 '10 at 16:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.