-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsysWatcher.sh
373 lines (305 loc) · 10.4 KB
/
sysWatcher.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#! /bin/sh
# The MIT License (MIT)
#
# Copyright (c) 2015-2016 Nicholas Niro
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# this script uses a configuration file sysWatcher.conf and
# a directory containing special scripts that set the events
# that need to be watched.
# If an event is triggered, we do the action related to the
# event like emailing to the system administrator.
# This script is meant to be ran as a cron job as often as
# possible to ensure faster response.
# A special time out variable is also meant to avoid spam of
# event consequences.
defaultConfigName="sysWatcher.conf"
# sysWatcher.conf
#
# email=<email> # the default system administrator's email
# eventDir=<path to script with events> # something like : /etc/sysWatcher.d/
# varDir=<path to var dir> # this contains temporary values like PID and timeout values.
#
#
# the event scripts need to contain minimum 2 functions (these are called by this script,
# the rest can be anything as this script won't access them) :
# eventName # the name of the event for logging and emailing
# eventIsTrue # this function should return 1 when it is triggered and the event should be called
# # and return 0 when no event should be triggered
# triggerEventType # this function sets which type of action needs to be done,
# # currently supported actions are : email and script
# triggerEventScript # the script to run if triggerEventType = script. The script
# # needs to accept an argument : the content of triggerEventScriptContent.
# triggerEventScriptContent # specific data sent to the script
# triggerEventEmail # the email address to send the report to (leave empty for default)
# triggerEventEmailContent # specific data to send in the email
# triggerTimeout # The name of the variable is a bit misleading because it is
# # in fact the date and time at which the event shall be reactivated
# # time the event can be retriggered format is : YYYY-MM-DD hh:mm:ss
# # a value of -1 makes the event trigger only once.
# # a value of 0 makes the event trigger not use any timeout
#
debugging=1
# argument type
# 0 is error
# 1 is -N
# 2 is --N
function argumentType() {
result1="`echo $1 | sed -n -e '/^-[^-]/ p'`"
result2="`echo $1 | sed -n -e '/^--/ p'`"
if [ "$result1" != "" ]; then
echo -n 1
return
fi
if [ "$result2" != "" ]; then
echo -n 2
return
fi
echo -n 0
}
function parseArgument() {
first=$1
second=$2
case "`argumentType $first`" in
1)
#the second argument contains the data
echo -n $second
return
;;
2)
#the data is after the '=' symbol
echo -n $first | sed -e 's/[^\=]*\=\(.*\)/\1/'
return
;;
esac
echo -n ""
}
while [[ 1 -eq 1 ]]; do
if [ "$1" = "" ]; then
# no more arguments to parse
break
fi
case "$1" in
-c|--config=*)
mainConfig=`parseArgument $1 $2`
if [ `argumentType $1` = 1 ]; then shift 1; fi
;;
-s|--standalone)
standalone=1
;;
-*|--*)
echo "Invalid argument '$1\` used, bailing out"
exit 1
;;
*)
echo "Invalid data entered, bailing out"
exit 1
;;
esac
shift 1
done
if [ "$mainConfig" = "" ]; then
# we'll check in the default places for the main config
if [ -e "./$defaultConfigName" ]; then
mainConfig="./$defaultConfigName"
else
if [ -e "/etc/$defaultConfigName" ]; then
mainConfig="/etc/$defaultConfigName"
else
if [ -e "/usr/local/etc/$defaultConfigName" ]; then
mainConfig="/usr/local/etc/$defaultConfigName"
else
echo "Error: no configuration found."
exit 1
fi
fi
fi
fi
if [ ! -r "$mainConfig" ]; then
echo "Error: Configuration file \`$mainConfig' does not exist or is not readable."
exit 1
fi
. $mainConfig
# we check the validity of what is set inside the configuration
if [ ! -d $eventDir ]; then
echo "the events Directory '$eventDir\` does not exist, please input a valid directory in the configuration file."
exit 1
else
if [ ! -r $eventDir ] || [ ! -x $eventDir ]; then
echo "the events Directory '$eventDir\` is not readable or executable, please fix the permissions of the directory."
exit 1
fi
fi
if [ ! -d $varDir ]; then
mkdir $varDir
if [ ! -d $varDir ]; then
echo "the variable Directory '$varDir\` does not exist and we don't have the permission to create it. Please input a valid directory in the configuration file."
exit 1
else
if [ ! -w $varDir ] || [ ! -r $varDir ]; then
echo "We created the variable Directory '$varDir\` but it is not writable or readable, please fix the permissions of the directory."
exit 1
fi
fi
else
if [ ! -w $varDir ] || [ ! -r $varDir ]; then
echo "the variable Directory '$varDir\` is not writable or readable, please fix the permissions of the directory."
exit 1
fi
fi
if [ -d /usr/share/sysWatcher ]; then
sharedDir="/usr/share/sysWatcher"
else
echo "Could not find the shared script directory."
echo "Please install them first to use this script."
echo "(These contain scripts that are also useful for the plugins.)"
exit 1
fi
. $sharedDir/utils.sh
#scripts=`ls -B $eventDir/*`
# only normal files, no files starting with . and no files containing the symbol ~
scripts=`find -L $eventDir -maxdepth 1 -type f -regex '[^\/]*\/[^\.][^~]*'`
# run Script's function
runSFunc() {
script=$1
function=$2
# It seems that the 'declare' bultin can not be used when called from the generic
# /bin/sh shell. So we call this script with the current SHELL.
result=`/bin/sh $sharedDir/runScriptFunc.sh $mainConfig $sharedDir/utils.sh $script $function`
if [ $? = 1 ]; then
[ $debugging = 1 ] && echo "An error happened when running a script" || echo ""
else
echo $result
fi
}
isScriptValid() {
script=$1
getErrorType=$2
# check if the script is valid or not
# we check if certain important functions are
# set for that. (And if they contain valid values)
if [ ! -e $script ]; then
[ "$getErrorType" != "" ] && echo "script file does not exist" || echo 0; return
fi
if [ "`runSFunc \"$script\" \"eventName\"`" = "" ]; then
[ "$getErrorType" != "" ] && echo "eventName is empty" || echo 0; return
fi
case "`runSFunc \"$script\" \"triggerEventType\"`" in
script)
triggerEventScript="`runSFunc \"$script\" \"triggerEventScript\"`"
if [ "$triggerEventScript" = "" ]; then
[ "$getErrorType" != "" ] && echo "triggerEventScript is empty for triggerEventType script" || echo 0; return
else
if [ ! -e $triggerEventScript ]; then
[ "$getErrorType" != "" ] && echo "the script \`$triggerEventScript' to run on triggerEvent does not exist" || echo 0; return
fi
fi
;;
email)
;;
*)
[ "$getErrorType" != "" ] && echo "Invalid triggerEventType, must be script or email" || echo 0; return
;;
esac
echo 1
}
# remove any newline or superflux spaces
scripts=`echo $scripts | sed -n -e 'H; $ b e' -e 'b; : e {x; s/\n/ /g; p;q}' | sed -e '1 s/^ *\(.*\)/\1/'`
handleTriggerEvent() {
script=$1
eventName="`runSFunc \"$script\" \"eventName\"`"
timeout="`runSFunc \"$script\" \"triggerTimeout\"`"
if [ "$timeout" != "0" ]; then
cat > $varDir/_${eventName}-timeout << EOF
$timeout
EOF
fi
case "`runSFunc \"$script\" \"triggerEventType\"`" in
script)
triggerScript="`runSFunc \"$script\" \"triggerEventScript\"`"
triggerEventScriptContent="`runSFunc \"$script\" \"triggerEventScriptContent\"`"
/bin/sh $triggerScript "$triggerEventScriptContent"
;;
email)
triggerEventEmailContent="`runSFunc \"$script\" \"triggerEventEmailContent\"`"
hostname=`hostname`
if [ "$triggerEventEmailContent" != "" ]; then
emailContent="$hostname `now` - This is the content of the event :\n\n$triggerEventEmailContent"
else
emailContent="$hostname `now` - There were no specific content released for this event."
fi
echo "$emailContent" | mail -s "$hostname: sysWatcher \`$eventName' event triggered" $email
;;
esac
}
handleScripts() {
if [ "$1" = "" ]; then
return
fi
tuple=`sep "$1"`
script=`fst $tuple`
xs=`snd $tuple`
[ $debugging = 1 ] && echo $script
if [ `isScriptValid $script` = 0 ]; then
[ $debugging = 1 ] && echo "The script \`$script' contains an error and is thus invalid."
[ $debugging = 1 ] && echo "error message : `isScriptValid $script 1`"
handleScripts $xs
return
fi
eventName="`runSFunc \"$script\" \"eventName\"`"
if [ -e $varDir/_${eventName}-timeout ]; then
timeout=`cat $varDir/_${eventName}-timeout`
if [ "$timeout" = "" ]; then
timeout="0"
fi
else
timeout="0"
fi
[ $debugging = 1 ] && echo "Checking \`$script' script for \`$eventName'"
# if $timeout = -1 we never run that event again
[ "$timeout" = "0" ] && checkTimeout=`echo 0` || checkTimeout=`cmpDateTime "$(now)" "$timeout"`
if [ "$checkTimeout" = "-1" ]; then
echo "An error was detected with the timeout for the script \`$script'"
echo "either '$timeout' is wrong or '`now`'"
handleScripts $xs
return
fi
if [ "$timeout" = "0" ] || [ $(( $checkTimeout <= 1)) = 1 ]; then
if [ `runSFunc "$script" "eventIsTrue"` = 1 ]; then
handleTriggerEvent $script
else
[ $debugging = 1 ] && [ $timeout != 0 ] && echo "\`cmpDateTime '`now`' '$timeout' '\` == `cmpDateTime \"$(now)\" \"$timeout\"`"
[ $debugging = 1 ] && echo "Trigger is off"
[ -e $varDir/_${eventName}-timeout ] && rm $varDir/_${eventName}-timeout
fi
fi
handleScripts $xs
}
#echo `cmpDateTime "houba" "zim"`
#exit 0
#echo $((`cmpDateTime "$(now)" "2015-06-24 02:50:00"` <= 1))
#exit 0
if [ "$standalone" = "1" ]; then
while [ 1 = 1 ]; do
handleScripts "$scripts"
sleep 5
done
else
handleScripts "$scripts"
fi