Annotation of badi/public_scripts/canardien/canardien, revision 1.6

1.1       adi         1: #!/bin/bash
                      2: 
1.6     ! adi         3: # canardien 0.0.6
        !             4: # (c) 2005-2021 under GPL by Adrian Zaugg
1.1       adi         5: 
                      6: 
1.4       adi         7: # canardien [<host> [<host> ...]]
                      8: 
1.6     ! adi         9: # canardiens pings a machine, originally ente.limmat.ch thus its name,
1.4       adi        10: # to determine wether she is gone diving.
                     11: 
1.1       adi        12: 
                     13: ## Settings
                     14: #
                     15: 
1.4       adi        16: # Hosts to ping. use a space separated list for multiple targets. All
                     17: # hosts of the list are checked and their results reported individually.
                     18: # Hosts given on the command line overwrite this setting.
                     19: HOSTS=""
1.1       adi        20: 
                     21: # eMail Alerts
                     22: # Send alert email messages to the following address(es). Leave empty
                     23: # for no alert. For multiple destinations use a comma separated list.
1.3       adi        24: ALERT_TO="root"
1.1       adi        25: 
                     26: # Subject of alert email
1.4       adi        27: ALERT_SUBJECT='"Attention: no answer from $HOST anymore!"'
1.1       adi        28: 
1.4       adi        29: # Text of Message (Put variables in 'single quotes' to protect them. They
                     30: # should get expanded at the time the message is sent!)
1.3       adi        31: ALERT_TEXT='"\n[$TIME_STAMP]\n\nALERT!!\n\n\t$HOST is down!\n\nYou should probably do something, please.\n\nKind regards, $PINGHOST."'
1.1       adi        32: 
1.4       adi        33: # Path to fping
                     34: PING=""
1.1       adi        35: 
1.4       adi        36: # Answer of fping to reachable hosts
1.1       adi        37: ALIVE_ANSWER="is alive"
                     38: 
1.4       adi        39: # Max number of pakets to send before giving up. Time increases exponentially,
                     40: # use a number < 7.
1.6     ! adi        41: RETRIES=5
1.4       adi        42: 
1.1       adi        43: # Temporary file path
                     44: TMPDIR="/tmp"
                     45: 
                     46: # This hosts name
1.4       adi        47: PINGHOST="$(uname -n)"
1.1       adi        48: 
1.4       adi        49: # Set to an empty string to avoid debug output,
1.1       adi        50: # to "low" for a few, output and to anything else
                     51: # for verbose output
1.4       adi        52: DEBUG=verbose
1.1       adi        53: 
1.4       adi        54: # For silent (non-error) operation set to anything,
1.1       adi        55: # comment out to enable text output
1.4       adi        56: #SILENT=shshsh
1.1       adi        57: 
                     58: 
                     59: # -----------functions-----------
                     60: 
1.4       adi        61: # Initialize.
                     62: function init() {
                     63: 
                     64:        # check fping existence
                     65:        if [ -z "$PING" ]; then
                     66:                PING="$(which fping)"
                     67:        fi
1.1       adi        68:        if [ ${#PING} -eq 0 ]; then
1.4       adi        69:                echo "Error: fping external program not found or not set. Exitting." >&2
                     70:                exit 1
                     71:        fi
                     72:        if [ ! -x "$PING" ]; then
                     73:                echo "Error: Can't execute the program set to use as fping. Please enter the correct path to \"fping\"." >&2
1.1       adi        74:                exit 1
                     75:        fi
1.3       adi        76: 
1.4       adi        77:        # get hostset
                     78:        if [ -n "$*" ]; then
                     79:                HOSTS="$*"
                     80:        fi
1.6     ! adi        81: 
        !            82:        # remove multiple spaces and trim
        !            83:        HOSTS="$(echo "$HOSTS" | sed -e "s/ \{1,\}/ /g" -e "s/^ //" -e "s/ $//")"
        !            84: 
1.4       adi        85:        if [ -z "$HOSTS" ]; then
                     86:                echo "Error: No host to ping." >&2
1.6     ! adi        87:                exit 1
1.4       adi        88:        fi
1.1       adi        89: }
                     90: 
1.4       adi        91: 
                     92: # If a host responds to pings, it is considered up.
                     93: function checkconnection() {
                     94: 
1.6     ! adi        95:        unset UP
1.4       adi        96: 
1.6     ! adi        97:        # ping host
        !            98:        PING_ANSWER="$($PING -R -B 2 -r $RETRIES -p 50 "$HOST" 2>&1)"
        !            99:        PING_ERRNUM=$?
        !           100:        if [ $PING_ERRNUM -gt 2 ]; then
        !           101:                echo "Error: Got error $PING_ERRNUM from fping $(head -1 "$PING_ANSWER"). Disregarding $HOST." >&2
        !           102:                continue;
        !           103:        fi
        !           104: 
        !           105:        # parse answer
        !           106:        if [ $(echo "$PING_ANSWER" | grep -c "$ALIVE_ANSWER") -gt 0 ]; then
        !           107:                UP=true
        !           108:        fi
        !           109:        TIME_STAMP="$(date +"%a %e.%m.%y %H:%M:%S")"
        !           110:        if [ -n "$UP" ]; then
        !           111:                if [ ! "$DEBUG" = "low" ] && [ -n "$DEBUG"  ]; then
        !           112:                        shout "The connection to $HOST is up."
1.4       adi       113:                fi
1.6     ! adi       114:        else
        !           115:                if [ -n "$DEBUG" ]; then
        !           116:                        shout "The connection to $HOST is down."
1.4       adi       117:                fi
1.6     ! adi       118:        fi
        !           119: 
        !           120:        # remember a hosts state
        !           121:        rememberstate
1.4       adi       122: }
                    123: 
                    124: 
                    125: # Rember recent state of host, trigger alert
                    126: function rememberstate() {
                    127:        # Put a simple time stamp in a tmp file, when host is detected as down for the first time
                    128:        if [ -z "$UP" ]; then
1.6     ! adi       129:                if [ ! -e "$TMPDIR/.canardien-$PINGHOST-$HOST" ]; then
1.4       adi       130:                                # set time stamp
                    131:                                echo -ne "$TIME_STAMP" > "$TMPDIR/.canardien-$PINGHOST-$HOST"
                    132:                                # send alert
                    133:                                sendalert
                    134:                        elif [ -n "$DEBUG" ]; then
                    135:                                shout "Down since `cat $TMPDIR/.canardien-$PINGHOST-$HOST`."
                    136:                        fi
1.6     ! adi       137:        else
1.4       adi       138:          # Host is up
                    139:                if [ -e "$TMPDIR/.canardien-$PINGHOST-$HOST" ]; then
                    140:                        if [ -n "$DEBUG" ]; then
                    141:                                shout "$HOST is up again."
                    142:                        fi
1.6     ! adi       143:                        # send alert
        !           144:                        ALERT_SUBJECT='"The host $HOST answers again!"'
        !           145:                        ALERT_TEXT='"[$(date +"%a %e.%m.%y %H:%M:%S")]\n\n\n$HOST is up again.\n--------------------------------------\n(downtime began $(cat "$TMPDIR/.canardien-$PINGHOST-$HOST"))\n\n\n              Kind regards, $PINGHOST."'
        !           146:                        sendalert
1.4       adi       147:                        # delete tmp file
                    148:                        rm "$TMPDIR/.canardien-$PINGHOST-$HOST"
1.6     ! adi       149:                else
1.4       adi       150:                        # still running
                    151:                        if [ ! "$DEBUG" = "low" ] && [ -n "$DEBUG"  ]; then
                    152:                                shout "$HOST is up."
                    153:                        fi
                    154:                fi
                    155:        fi
1.1       adi       156: }
                    157: 
1.4       adi       158: 
1.1       adi       159: # Send an email alert
1.4       adi       160: function sendalert() {
                    161:        # send mail
1.1       adi       162:        if [ ! -z "$ALERT_TO" ]; then
1.4       adi       163:                        eval alert_subject=\$$ALERT_SUBJECT
                    164:                        eval MSG=\$$ALERT_TEXT
                    165:                        echo -e -n "$MSG" | mail -s "$alert_subject" "$ALERT_TO"
                    166:                        if [ -n "$DEBUG" ]; then
                    167:                                shout "Alert sent to $ALERT_TO."
                    168:                        fi
1.1       adi       169:        fi
                    170: }
                    171: 
1.4       adi       172: 
1.1       adi       173: # To avoid any output in case of a silent operation,
                    174: # shout instead of echo.
1.4       adi       175: function shout() {
                    176:        if [ -z "$SILENT" ]; then
                    177:                echo -e "$1"
                    178:        fi
1.1       adi       179: }
                    180: 
                    181: 
                    182: # -----------main-----------
                    183: 
1.4       adi       184: init "$*"
1.6     ! adi       185: 
        !           186: # call an instance for each host, when multiple hosts are given
        !           187: if [[ "$HOSTS" =~ " " ]]; then
        !           188:        while read -r HOST; do
        !           189:                "$0" "$HOST" &
        !           190:        done <<< "$(echo "$HOSTS" | tr ' ' '\n')"
        !           191:        exit 0
        !           192: else
        !           193:        # process a single host
        !           194:        HOST="$HOSTS"
        !           195:        checkconnection
        !           196: fi
        !           197: 
1.1       adi       198: exit 0
1.6     ! adi       199: 
        !           200: # todo: Switches ( -q, --debug, ...)
        !           201: #      grace period: do not send a mail if down time shorter than X minutes
        !           202: #      repeat down info after x hours
        !           203: #      test port instead of ping or in addition
        !           204: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>