3

I have a script that ask if the ping of a certain array of macs is online.

#!/bin/bash

#Array of Mac hostnames separated by spaces
my_macs=( Mac111 Mac121 Mac122 Mac123 Mac124 Mac125 Mac126 Mac127 Mac128 Mac129 )

# Number of days the remote Mac is allowed to be up
MAX_UPDAYS=7

CURR_TIME=$(date +%s)
MAX_UPTIME=$(( MAX_UPDAYS * 86400 ))
ADMINUSER="admusr"

#Steps through each hostname and issues SSH command to that host
#Loops through the elements of the Array

echo "Remote shutdown check started at $(date)"
for MAC in "${my_macs[@]}"
do
    echo -n "Checking ${MAC}... "
    # -q quiet
    # -c nb of pings to perform

    if ping -q -c3 "${MAC}" >/dev/null; then
        echo "is up. Getting boot time... "

        BOOT_TIME=0
        # Get time of boot from remote Mac
        BOOT_TIME=$(ssh "${ADMINUSER}@${MAC}" sysctl -n kern.boottime | sed -e 's/.* sec = \([0-9]*\).*/\1/')

        if [ "$BOOT_TIME" -gt 0 ] && [ $(( CURR_TIME - BOOT_TIME )) -ge $MAX_UPTIME ]; then
            echo "${MAC} uptime is beyond MAX_UPDAYS limit.  Sending shutdown command"
            ssh "${ADMINUSER}@${MAC}" 'sudo /sbin/shutdown -h now'
        else
            echo "${MAC} uptime is below limit.  Skipping shutdown."
        fi

    else
        echo "is down (ping failed)"
    fi
done

The problem is that the script stops if it can't resolve the hostname of one of those machines (yes this can happen quite often, I don't want to go into details why) The hostnames are definitely right, so I want to tell the script to first search for the hostname and if he can be resolved it will resume. Otherwise it will cancel it for this one mac. Is this possible?

  • I might need glasses, but I don't see any exit or set -e or anything in this code that make this script abort if a name resolution fails. What I see in that case is a spurious "Mac is down" and the loop then continues with the next Mac. So my question is: where and why does this script stop if it can't resolve the hostname? – xhienne Jan 10 '17 at 10:36
  • @xhienne the script checks for mac124 (for example) but if mac124 doesn't exist it will just stop. So after it thinks that mac124 doesn't exist it will just stop – Gunter Jan 10 '17 at 13:32
3

Why don't you set up static Private IP Address in you router by adding your device's MAC Addresses instead of using your router as DHCP? If you do so, you'll be sure that they won't go wrong on hostnames anymore. On the other hand, you can add lines to your /etc/hosts if you're not setting hosts in your router or if your router does not support further things. You can have your /etc/hosts as the following:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1           localhost Mac1
255.255.255.255     broadcasthost Mac1
::1                 localhost Mac1
fe80::1%lo0         localhost Mac1
172.16.11.43        Mac2
172.16.11.43        Mac3
172.16.11.43        Mac4
172.16.11.43        Mac5
.
.
.

It's not a big deal, the reason your script goes wrong is depending on your network configuration, not the script or even Mac devices. You could have written your script much easier, but it's OK. Just check your network, and try to set up things statically so they can find each other.

The reason they fail is that they are not using Public Static IP Addresses, so you should make sure you've set up right and static private ones so they will be able to resolve hostnames.


BTW, if you want to tell your script to continue even if a hostname was not resolvable, the other option that might help you is to use and add continue in your loop and conditional statements. So if it could resolve X, it will check if it was up for more than 7 days or less, and if it couldn't, it will continue to check the next hostname and will announce that X was down. You have many options, but as mentioned earlier, the problem is not your script mate. Good luck.

  • The problem is that I am not in charge to make such decisions – Gunter Jan 10 '17 at 9:51
  • 1
    @Gunter Okeydokey, that's different. You can play around with MAC addresses and arp requests, but it's not recommended. Do you have physical access to Mac devices? If yes so, you can use crontab, and if not, please add further details to your question so I and the others will know much about your situation and so we can help your more. – FarazX Jan 10 '17 at 11:13
  • 1
    @Gunter BTW, by "playing around with MACs", I meant - for instance - collect MAC adds that your targets have and list them in your script as variables, and check what IP Addresses are assigned to those MAC adds by using arp -a to send an arp request and then by checking lines including the variables that you have set. So whenever their IP Addresses get change, you know what IP Address is assigned to them and you're not worried about hostnames anymore since you will find them before checking if they are alive or not, and then they are 100% resolvable - unless down, and if down you can skip. – FarazX Jan 10 '17 at 11:27
  • I have physical access to all of the Macs. I actually run this script remotely at night with a cronjob, so nobody works on those macs. – Gunter Jan 10 '17 at 13:37
  • @Gunter so why don't you handle it respectively for each Mac device? Adding a cron job for each will ease your job since you say that you have no right to change network configuration of the place that you're working at, but you have physical access to machines. Since you've written a good script, I'm sure you are not unfamiliar with Unix, so you know nothing is wrong with your machines and your script. But for doing things properly whilst you need a remote access, you should be able to know and change the network architecture so as to it suits your purpose. – FarazX Jan 10 '17 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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