Question

I have 5 Solaris servers present across different locations. Sometimes some of these servers are not reachable from my location due to various reasons (either because of network problems or the server itself goes down suddenly).

So I would like to write a Bash shell script to check wether they are reachable. What I have tried is:

ssh ipaddress "uname -a"

Password less authentication is set. If I don't get any any output I will generate a mail.

  1. Are there any otherways to check server reachability?
  2. Which one is the best way?
  3. Is what I have tried correct?
Was it helpful?

Solution

You can use ping -c4 $ip_address where $ip_address is the ip of your remote server and parse the output to capture the successful packets and/or failed packets and use mail -s to send the log via email.

Here is something to get you started and you can build on it.

ping -c4 www.google.com | awk '/---/,0'

This will give an output like this -

[jaypal:~/Temp] ping -c4 www.google.com | awk '/---/,0'
--- www.l.google.com ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 36.638/36.870/37.159/0.196 ms

I checked the Solaris man-page for ping. Output from ping on Solaris box is different. Also, on Linux you limit the packets by stating -c and number of packets. On Solaris you would have to do -

ping -s www.google.com 2 4

/usr/sbin/ping -s [-l | -U] [-adlLnrRv] [-A addr_family]
[-c traffic_class] [-g gateway [ -g gateway...]] [-
F flow_label] [-I interval] [-i interface] [-P tos] [-
p port] [-t ttl] host [data_size] [npackets]
                           ^           ^
                           |           |
---------------------------------------  

Unfortunately I don't have a solaris box handy to help you out with.

OTHER TIPS

The most barebones check you can do is probably to use netcat to check for open ports.

to check for SSH (port 22) reachability, you can do

if nc -z $server 22 2>/dev/null; then
    echo "$server ✓"
else
    echo "$server ✗"
fi

from the manpage:

-z   Specifies that nc should just scan for listening daemons, without sending any data to them.

Your ssh command will test for more than if the server is reachable - for it to work, the ssh server must be running, and everything must be right with authentication.

To just see if the servers are up, how about just a simple ping?

ping -c1 -W1 $ip_addr && echo 'server is up' || echo 'server is down'

You could use these options from the ping man page:

  • only send one packet ("c1"),
  • quiet mode ("q"),
  • (optional) Wait for 1 second for a response ("W1")

    ping -c1 -W1 -q $server

Ping returns different exit codes depending on the type of error. So, to test if it worked or not, just do "echo $?" to get the exit code. Like this:

ping 256.256.256.256 ; echo $?
# 68

ping -c 1 127.0.0.1 ; echo $?
# 0

ping -c 1 192.168.1.5 ; echo $?
# 2

Where

0 means host reachable
>0 means unreachable

So, to test this in a bash script, you could do something like:

ping -c1 -W1 -q $server &>/dev/null
status=$( echo $? )
if [[ $status == 0 ]] ; then
     #Connection success!
else
     #Connection failure
fi

Some more food for thought : Use nmap or nc, never ping.

Ping: Why should you not use ping ? (1) It is better to check the system and the port at the same time. (2) Ping is unreliable as icmp echo is blocked in many situations.

Nmap: This is very quick, very reliable but requires nmap to be installed Preferred method NMAP (ex host ip 127.0.0.1) :

nmap 127.0.0.1 -PN -p ssh | grep open

Nc: nc is usually installed already , however on some systems such as Mac OS X, the command hangs on unreachable systems. (see workaround)

nc -v -z -w 3 127.0.0.1 22 &> /dev/null && echo "Online" || echo "Offline"

Mac OSX Workaround :

bash -c '(sleep 3; kill $$) & exec nc -z 127.0.0.1 22' &> /dev/null
echo $?
0
bash -c '(sleep 3; kill $$) & exec nc -z 1.2.3.4 22' &> /dev/null
echo $?
143

(examples illustrate connecting to port 22 ssh over a good and bad host example, use the $? to determine if it reached the host with the sleep time of 3 seconds)

For Mac Users (mainly) etc, you can use the command in the script like so :

    # -- use NMAP, if not avail. go with nc --
    if command -v nmap | grep -iq nmap ; then
        nmap ${ip} -PN -p ${ssh_port} | grep -iq "open"
        res=$?
    elif command -v nc | grep -iq nc ; then
        # -- run command if fails to complete in 3 secs assume host unreachable --
        ( nc -z ${ip} ${ssh_port} ) & pid=$!
        ( sleep 3 && kill -HUP $pid ) 2>/dev/null & watcher=$!
        if wait $pid 2>/dev/null; then
            pkill -HUP -P $watcher
            wait $watcher
            # -- command finished (we have connection) --
            res=0
        else
            # -- command failed (no connection) --
            res=1
        fi
    else
        echo "Error: You must have NC or NMAP installed"
    fi

    if [[ ${res} -lt 1 ]] ;then
        success=1
        echo "testing  => $ip SUCCESS connection over port ${ssh_port}"
        break;
    else
        echo "testing => $ip FAILED connection over port ${ssh_port}"
    fi

You can use the nc -z -G 2 SERVER_HOST PORT approach with G instead of W. G being used for timeout before connection established , so if host is unreachable , you'll know faster

You can use below command,

ping -c1 -W1 ip_addr || echo 'server is down'  

you can't use $ip_addr as it will remove first number of your IP.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top