Skip to content

Instantly share code, notes, and snippets.

@thonixx
Last active May 10, 2017 13:23
Show Gist options
  • Save thonixx/647f2a2bee9ae381a88bfd08f15d9ece to your computer and use it in GitHub Desktop.
Save thonixx/647f2a2bee9ae381a88bfd08f15d9ece to your computer and use it in GitHub Desktop.
Wait for a server and try to log in via SSH (public key)
#!/bin/bash
# global ssh arguments
SSHARG="-o StrictHostKeyChecking=false -o UserKnownHostsFile=/dev/null"
TIMEOUT="$(uname | grep -q Darwin && echo gtimeout || echo timeout)"
# get IP address from hostname
getIP() {
# return with failure if no server given
test -z "$1" && return 1
# query IP
ip="$(dig +short +search -t a $1 | tail -n 1)"
test -z "$ip" && ip="$(ping -c1 -W 1000 $1 | egrep -m1 -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")"
test -z "$ip" \
&& {
# check if it is an ip already
echo "$1" | egrep "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" -q \
&& {
# print if its ip
echo "$1"
return 0
} \
|| return 1
} \
|| {
# print queried ip
echo "$ip"
return 0
}
return 1
}
# ping loop to wait for the server to be booted up
waitforserver() {
# wait until server is ready to log in via ssh
ip="$(getIP $1)"
test -z "$ip" && return 1
# ping the server
i=0
i2=0
ifail=0
noloop=""
# check if server already responds to ping
$TIMEOUT 1 ping -c1 $ip &> /dev/null \
&& noloop="true"
# loop through ping
if [[ "$noloop" != "true" ]]
then
while true
do
# timeout config
timeoutcmd=1
timeoutsuccess=10
timeoutfails=300
# timeout if server is not pingable
# count one up if ping succeeded
# reset counter if ping failed
$TIMEOUT $timeoutcmd ping -c1 $ip &> /dev/null \
&& i=$((i+1)) \
|| i=0
# only sleep a second if ping succeeds
# otherwise it "sleeps" a second due to timeout command
test "$i" -gt 0 && sleep 1 || sleep 0.1
# introduce fail count
test "$i" = 0 && ifail=$((ifail+1)) || ifail=0
# check if minimum of tries reached
if [[ "$i" -le $timeoutsuccess ]] && [[ "$ifail" -le $timeoutfails ]]
then
# if ping does not reach minimum go on and print tries
test "$i2" = 0 && printf "\rServer alive for ${i}s (${ifail}s failing). "
test "$i2" = 1 && printf "\rServer alive for ${i}s (${ifail}s failing).. "
test "$i2" = 2 && printf "\rServer alive for ${i}s (${ifail}s failing)..."
# counter for dots
test "$i2" -lt 2 && i2=$((i2+1)) || i2=0
elif [[ "$ifail" -ge $timeoutfails ]]
then
# stop if maximum is reached
echo -e "\n${Red}Server not alive (tried for ${ifail}s)."
return 1
else
# stop loop if minimum is reached
echo -e "\nServer alive."
break
fi
done
else
echo "Server alive."
fi
# sshing the server
i=0
i2=0
ifail=0
noloop=""
# check if server already responds to ping
ssh -o BatchMode=yes -o ConnectTimeout=1 $SSHARG $ip "echo hello world" &> /dev/null \
&& noloop="true"
# loop through ping
if [[ "$noloop" != "true" ]]
then
while true
do
# timeout config
timeoutcmd=1
timeoutsuccess=3
timeoutfails=120
# timeout if server is not able to log in
# count one up if ssh succeeded
# reset counter if ssh failed
ssh -o BatchMode=yes -o ConnectTimeout=1 $SSHARG $ip "echo hello world" &> /dev/null \
&& i=$((i+1)) \
|| i=0
# always sleep 1 second
sleep 1
# introduce fail count
test "$i" = 0 && ifail=$((ifail+1)) || ifail=0
# check if minimum of tries reached
if [[ "$i" -le $timeoutsuccess ]] && [[ "$ifail" -le $timeoutfails ]]
then
# if ssh does not reach minimum go on and print tries
test "$i2" = 0 && printf "\rHost is responding to SSH for $i seconds ($ifail seconds failing). "
test "$i2" = 1 && printf "\rHost is responding to SSH for $i seconds ($ifail seconds failing).. "
test "$i2" = 2 && printf "\rHost is responding to SSH for $i seconds ($ifail seconds failing)..."
# counter for dots
test "$i2" -lt 2 && i2=$((i2+1)) || i2=0
elif [[ "$ifail" -ge $timeoutfails ]]
then
# stop if maximum is reached
echo -e "\n${Red}Server is not responding to ssh even after $ifail seconds."
return 1
else
# stop loop if minimum is reached
echo -e "\nHost can be logged in."
break
fi
done
else
echo "Server already responding to SSH login."
return 0
fi
}
test -z "$1" && echo "Provide hostname, servername, IP or domain to wait for." || waitforserver $1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment