6

I'm testing stability of a machine and I need way to simply write a Bash script to determine if a host is online or not. How could I script this?

if [ ! $(hostisonline) ]; then
    # profit
fi

2 Answers 2

7

If the host answers ping then test if its on line by (just an example):

ping -c 10 $host

If pings are not returned/forbidden, I'd check for individual services through nmap:

nmap $host -p $known_port --max-retries 10 | grep -q open

For example to test if ssh is expected to be opened, replace known_port by 22

as for the script it could be (the example -- it's Sunday morning and I'm bored so it has grown a bit after some edits -- is aimed for testing a bunch of hosts, not just one):

declare -A SERVER
# SERVER["NAME - Description"]="IP KNOWNPORT"
SERVER["SERVER1 - Client foo"]="111.111.111.111 22"
SERVER["SERVER2 - Client bar"]="222.222.222.222 80"
# ...
# add as many server/port combinations as you'd like

NMAP_MAX_RETRIES=10

printf "========================= ========================= ========== ==========\n"
printf "%25s %25s %10s %10s\n" "Host Description" "IP" "Port" "Status"
printf "========================= ========================= ========== ==========\n"


for server in "${!SERVER[@]}"; do
    set -- ${SERVER["$server"]}
    eval nmap \$1 -p \$2 --max-retries $NMAP_MAX_RETRIES | grep -q open
    if [ "$?" == "0" ]; then
        STATUS="[OK]"
    else
        STATUS="*DOWN*" 
    fi
    printf "%25s %25s %10s %10s\n" "$server" "$1" "$2" "$STATUS" 
done

 printf "========================= ========================= ========== ==========\n"

When executed it returns (fake ips, so servers are down):

 ~$ bash /tmp/foo.sh
 ========================= ========================= ========== ==========
          Host Description                        IP       Port     Status
 ========================= ========================= ========== ==========
      SERVER2 - Client bar           222.222.222.222         80     *DOWN*
      SERVER1 - Client foo           111.111.111.111         22     *DOWN*
 ========================= ========================= ========== ==========
2
  • This requires bash 4.0 or higher.
    – jordanm
    Commented Jan 13, 2013 at 17:39
  • true, but just for the array stuff.
    – hmontoliu
    Commented Jan 14, 2013 at 11:01
5

A simple solution would be:

ping -W 1 $ip

where -W specifies a timeout in seconds.

Make sure its a capital W. You can also use -i to specify a waiting time in seconds.

4
  • 1
    -w works as well. linux.die.net/man/8/ping Commented Apr 1, 2014 at 14:04
  • (Thanks for the edit though, still, the answer was not wrong ;) Commented Apr 1, 2014 at 14:05
  • 1
    I want something with a shorter timeout than 1 second... decimal values for '-W' don't work
    – isaaclw
    Commented Apr 13, 2015 at 16:20
  • The original answer using lowercase -w works perfectly. The updated answer with uppercase -W does not specify the timeout for the whole command but for the individual pings instead and therefore keeps running indefinitely in the absence of a -c parameter. I would suggest reverting the answer to use the original lowercase -w as the updated command does not do what it is supposed to.
    – Zoltan
    Commented Nov 7, 2021 at 21:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .