File:  [Local Repository] / badi / public_scripts / canardien / canardien
Revision 1.6: download - view: text, annotated - select for diffs - revision graph
Sun Aug 6 20:06:51 2023 UTC (10 months, 1 week ago) by adi
Branches: MAIN
CVS tags: HEAD
Parallel execution when guarding multiple hosts.

    1: #!/bin/bash
    2: 
    3: # canardien 0.0.6
    4: # (c) 2005-2021 under GPL by Adrian Zaugg
    5: 
    6: 
    7: # canardien [<host> [<host> ...]]
    8: 
    9: # canardiens pings a machine, originally ente.limmat.ch thus its name,
   10: # to determine wether she is gone diving.
   11: 
   12: 
   13: ## Settings
   14: #
   15: 
   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=""
   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.
   24: ALERT_TO="root"
   25: 
   26: # Subject of alert email
   27: ALERT_SUBJECT='"Attention: no answer from $HOST anymore!"'
   28: 
   29: # Text of Message (Put variables in 'single quotes' to protect them. They
   30: # should get expanded at the time the message is sent!)
   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."'
   32: 
   33: # Path to fping
   34: PING=""
   35: 
   36: # Answer of fping to reachable hosts
   37: ALIVE_ANSWER="is alive"
   38: 
   39: # Max number of pakets to send before giving up. Time increases exponentially,
   40: # use a number < 7.
   41: RETRIES=5
   42: 
   43: # Temporary file path
   44: TMPDIR="/tmp"
   45: 
   46: # This hosts name
   47: PINGHOST="$(uname -n)"
   48: 
   49: # Set to an empty string to avoid debug output,
   50: # to "low" for a few, output and to anything else
   51: # for verbose output
   52: DEBUG=verbose
   53: 
   54: # For silent (non-error) operation set to anything,
   55: # comment out to enable text output
   56: #SILENT=shshsh
   57: 
   58: 
   59: # -----------functions-----------
   60: 
   61: # Initialize.
   62: function init() {
   63: 
   64: 	# check fping existence
   65: 	if [ -z "$PING" ]; then
   66: 		PING="$(which fping)"
   67: 	fi
   68: 	if [ ${#PING} -eq 0 ]; then
   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
   74: 		exit 1
   75: 	fi
   76: 
   77: 	# get hostset
   78: 	if [ -n "$*" ]; then
   79: 		HOSTS="$*"
   80: 	fi
   81: 
   82: 	# remove multiple spaces and trim
   83: 	HOSTS="$(echo "$HOSTS" | sed -e "s/ \{1,\}/ /g" -e "s/^ //" -e "s/ $//")"
   84: 
   85: 	if [ -z "$HOSTS" ]; then
   86: 		echo "Error: No host to ping." >&2
   87: 		exit 1
   88: 	fi
   89: }
   90: 
   91: 
   92: # If a host responds to pings, it is considered up.
   93: function checkconnection() {
   94: 
   95: 	unset UP
   96: 
   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."
  113: 		fi
  114: 	else
  115: 		if [ -n "$DEBUG" ]; then
  116: 			shout "The connection to $HOST is down."
  117: 		fi
  118: 	fi
  119: 
  120: 	# remember a hosts state
  121: 	rememberstate
  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
  129: 		if [ ! -e "$TMPDIR/.canardien-$PINGHOST-$HOST" ]; then
  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
  137: 	else
  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
  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
  147: 			# delete tmp file
  148: 			rm "$TMPDIR/.canardien-$PINGHOST-$HOST"
  149: 		else
  150: 			# still running
  151: 			if [ ! "$DEBUG" = "low" ] && [ -n "$DEBUG"  ]; then
  152: 				shout "$HOST is up."
  153: 			fi
  154: 		fi
  155: 	fi
  156: }
  157: 
  158: 
  159: # Send an email alert
  160: function sendalert() {
  161: 	# send mail
  162: 	if [ ! -z "$ALERT_TO" ]; then
  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
  169: 	fi
  170: }
  171: 
  172: 
  173: # To avoid any output in case of a silent operation,
  174: # shout instead of echo.
  175: function shout() {
  176: 	if [ -z "$SILENT" ]; then
  177: 		echo -e "$1"
  178: 	fi
  179: }
  180: 
  181: 
  182: # -----------main-----------
  183: 
  184: init "$*"
  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: 
  198: exit 0
  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>