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