1: #!/bin/bash
2:
3: # canardien 0.0.4
4: # (c) 2005-2019 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=4
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: if [ -z "$HOSTS" ]; then
82: echo "Error: No host to ping." >&2
83: exit 0
84: fi
85: }
86:
87:
88: # If a host responds to pings, it is considered up.
89: function checkconnection() {
90:
91: while read -r HOST; do
92: unset UP
93:
94: # ping host
95: PING_ANSWER="$($PING -R -B 2 -r $RETRIES -p 50 "$HOST" 2>&1)"
96: PING_ERRNUM=$?
97: if [ $PING_ERRNUM -gt 2 ]; then
98: echo "Error: Got error $PING_ERRNUM from fping $(head -1 "$PING_ANSWER"). Disregarding $HOST." >&2
99: continue;
100: fi
101:
102: # parse answer
103: if [ $(echo "$PING_ANSWER" | grep -c "$ALIVE_ANSWER") -gt 0 ]; then
104: UP=true
105: fi
106: TIME_STAMP="$(date +"%a %e.%m.%y %H:%M:%S")"
107: if [ -n "$UP" ]; then
108: if [ ! "$DEBUG" = "low" ] && [ -n "$DEBUG" ]; then
109: shout "The connection to $HOST is up."
110: fi
111: else
112: if [ -n "$DEBUG" ]; then
113: shout "The connection to $HOST is down."
114: fi
115: fi
116:
117: # remember a hosts state
118: rememberstate
119:
120: done <<< "$(echo "$HOSTS" | tr ' ' '\n')"
121: }
122:
123:
124: # Rember recent state of host, trigger alert
125: function rememberstate() {
126: # Put a simple time stamp in a tmp file, when host is detected as down for the first time
127: if [ -z "$UP" ]; then
128: if [ ! -e "$TMPDIR/.canardien-$PINGHOST-$HOST" ]; then
129: # set time stamp
130: echo -ne "$TIME_STAMP" > "$TMPDIR/.canardien-$PINGHOST-$HOST"
131: # send alert
132: sendalert
133: elif [ -n "$DEBUG" ]; then
134: shout "Down since `cat $TMPDIR/.canardien-$PINGHOST-$HOST`."
135: fi
136: else
137: # Host is up
138: if [ -e "$TMPDIR/.canardien-$PINGHOST-$HOST" ]; then
139: if [ -n "$DEBUG" ]; then
140: shout "$HOST is up again."
141: fi
142: # send alert
143: ALERT_SUBJECT="The host $HOST answers again!!"
144: 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."'
145: sendalert
146: # delete tmp file
147: rm "$TMPDIR/.canardien-$PINGHOST-$HOST"
148: else
149: # still running
150: if [ ! "$DEBUG" = "low" ] && [ -n "$DEBUG" ]; then
151: shout "$HOST is up."
152: fi
153: fi
154: fi
155: }
156:
157:
158: # Send an email alert
159: function sendalert() {
160: # send mail
161: if [ ! -z "$ALERT_TO" ]; then
162: eval alert_subject=\$$ALERT_SUBJECT
163: eval MSG=\$$ALERT_TEXT
164: echo -e -n "$MSG" | mail -s "$alert_subject" "$ALERT_TO"
165: if [ -n "$DEBUG" ]; then
166: shout "Alert sent to $ALERT_TO."
167: fi
168: fi
169: }
170:
171:
172: # To avoid any output in case of a silent operation,
173: # shout instead of echo.
174: function shout() {
175: if [ -z "$SILENT" ]; then
176: echo -e "$1"
177: fi
178: }
179:
180:
181: # -----------main-----------
182:
183: init "$*"
184: checkconnection
185: exit 0
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>