Refactoring: Changed all check parameters starting with an 'o' to the new rulespec...
[check_mk.git] / agents / check_mk_agent.aix
blob9e0ba21d9050bb1ec93b364b1a8f3498c5af3624
1 #!/usr/bin/ksh93
2 # Check_MK Agent for AIX
3 # +------------------------------------------------------------------+
4 # |             ____ _               _        __  __ _  __           |
5 # |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
6 # |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
7 # |           | |___| | | |  __/ (__|   <    | |  | | . \            |
8 # |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
9 # |                                                                  |
10 # | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software;  you can redistribute it and/or modify it
17 # under the  terms of the  GNU General Public License  as published by
18 # the Free Software Foundation in version 2.  check_mk is  distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
20 # out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
21 # PARTICULAR PURPOSE. See the  GNU General Public License for more de-
22 # tails. You should have  received  a copy of the  GNU  General Public
23 # License along with GNU Make; see the file  COPYING.  If  not,  write
24 # to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # force load of environment
28 if [ -e $HOME/.profile ]
29 then
30     . $HOME/.profile >/dev/null 2>&1
33 # Remove locale settings to eliminate localized outputs where possible
34 export LC_ALL=C
35 unset LANG
37 export MK_LIBDIR=${MK_LIBDIR:-/usr/check_mk/lib}
38 export MK_CONFDIR=${MK_CONFDIR:-/usr/check_mk/conf}
39 export MK_VARDIR=${MK_VARDIR:-/tmp/check_mk}
41 # Optionally set a tempdir for all subsequent calls
42 #export TMPDIR=
44 # All executables in PLUGINSDIR will simply be executed and their
45 # ouput appended to the output of the agent. Plugins define their own
46 # sections and must output headers with '<<<' and '>>>'
47 PLUGINSDIR=$MK_LIBDIR/plugins
49 # All executables in LOCALDIR will by executabled and their
50 # output inserted into the section <<<local>>>. Please refer
51 # to online documentation for details.
52 LOCALDIR=$MK_LIBDIR/local
54 # All files in SPOOLDIR will simply appended to the agent
55 # output if they are not outdated (see below)
56 SPOOLDIR=$MK_VARDIR/spool
58 #Avoid problems with wrong decimal separators in other language verions of aix
59 export LC_NUMERIC="en_US"
61 # close standard input (for security reasons) and stderr
62 if [ "$1" = -d ]
63 then
64     set -xv
65 else
66     exec <&- 2>/dev/null
69 # Shell version of the waitmax utility, that limits the runtime of
70 # commands. This version does not conserve the original exit code
71 # of the command. It is successfull if the command terminated
72 # in time.
73 function waitmax
75    TIMEOUT=${1}0
76    SIGNAL=9
77    shift
79    # Run command in background
80    ksh -c "$*" &
81    PID=$!
83    # Wait for termination within TIMOUT seconds
84    while [ $TIMEOUT -gt 0 ]
85    do
86        TIMEOUT=$((TIMEOUT - 1))
87        if [ ! -e /proc/$PID ] ; then
88            return 0
89        fi
90        perl -e "select(undef, undef, undef, 0.1);"
91    done
93    # Process did not terminate in time. Kill and
94    # return with an error
95    kill -9 $PID
96    return 255
99 function run_cached {
100     NAME=$1
101     # Be aware: Maxage was expected to be given in minutes but this was
102     # confusing because all other agents use seconds here. So this has
103     # been changed to be compatible.
104     MAXAGE=$2
105     shift 2
106     CMDLINE=$*
108     if [ ! -e $MK_VARDIR/cache ] ; then mkdir -p $MK_VARDIR/cache ; fi
109     CACHE_FILE=$MK_VARDIR/cache/$NAME.cache
111     USE_CACHE_FILE=""
112     # Check if file exists and is recent enough
113     if [ -s $CACHE_FILE ]
114     then
115         MTIME=$(/usr/bin/perl -e 'if (! -f $ARGV[0]){die "0000000"};$mtime=(stat($ARGV[0]))[9];print ($^T-$mtime);' $CACHE_FILE )
116         if (( $MTIME < $MAXAGE )) ; then
117             USE_CACHE_FILE=1
118         fi
119     fi
120     if [ -s "$CACHE_FILE" ]
121     then
122         cat $CACHE_FILE
123     fi
124     if [ -z "$USE_CACHE_FILE" -a ! -e "$CACHE_FILE.new" ]
125     then
126         nohup sh -c $CMDLINE > $CACHE_FILE.new 2> /dev/null && mv $CACHE_FILE.new $CACHE_FILE  &
127     fi
130 echo "<<<check_mk>>>"
131 echo "Version: 1.6.0i1"
132 echo "AgentOS: aix"
133 echo "Hostname: $(hostname)"
134 echo "AgentDirectory: $MK_CONFDIR"
135 echo "DataDirectory: $MK_VARDIR"
136 echo "SpoolDirectory: $SPOOLDIR"
137 echo "PluginsDirectory: $PLUGINSDIR"
138 echo "LocalDirectory: $LOCALDIR"
140 echo '<<<df>>>'
141 if [ -x /usr/opt/freeware/bin/df ] ; then
142     excludefs="-x smbfs -x cifs -x iso9660 -x udf -x nfsv4 -x nfs -x mvfs -x zfs -x cdrfs"
143     # shellcheck disable=SC2086
144     /usr/opt/freeware/bin/df -PTlk $excludefs | sed 1d
146     # df inodes information
147     echo '<<<df>>>'
148     echo '[df_inodes_start]'
149     # shellcheck disable=SC2086
150     /usr/opt/freeware/bin/df -PTli $excludefs | sed 1d
151     echo '[df_inodes_end]'
152 else
153     df -kP | sed 's/ / - /' | grep -v ^/proc | grep -v ^Filesystem | grep -v :
156 # Check for hanging NFS mounts. This needs a GNU stat installed in the PATH
157 if type stat >/dev/null 2>&1 ; then
158     echo '<<<nfsmounts>>>'
159     mount | grep ' nfs' | awk '{print $3;}' | \
160         while read MP
161     do
162         waitmax 5 stat -f -c '"'$MP' ok - - - -"' "$MP" || \
163             echo "$MP hanging 0 0 0 0"
164     done
165     echo '<<<cifsmounts>>>'
166     mount | grep ' cifs' | awk '{print $3;}' | \
167         while read MP
168     do
169         if [ ! -r $MP ]; then
170             echo "$MP Permission denied"
171         else
172             waitmax 2 stat -f -c '"'$MP' ok - - - -"' "$MP" || \
173                 echo "$MP hanging 0 0 0 0"
174         fi
175     done
178 echo '<<<ps>>>'
179 ps -ef -F user,vszsize,rssize,pcpu,args | sed -e 1d -e 's/ *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) */(\1,\2,\3,\4) /'
181 if type lparstat >/dev/null 2>&1
182 then
183   echo '<<<lparstat_aix>>>'
184   lparstat 1 1
187 echo '<<<vmstat_aix>>>'
188 vmstat | tail -n1
190 echo '<<<aix_diskiod>>>'
191 iostat -d | tr -s ' ' | grep hdisk
193 echo '<<<aix_memory>>>'
194 vmstat -v  | tr -s ' '
195 swap -s
197 echo '<<<mpstat_aix>>>'
198 mpstat -a | tail -n1
200 # CPU output of Linux agent simulated
201 # (thanks to Cameron Pierce)
202 echo '<<<cpu>>>'
203 load=`uptime|sed -e 's;.*average: \([[:digit:]]\{1,\}\.[[:digit:]]\{1,\}\), \([[:digit:]]\{1,\}\.[[:digit:]]\{1,\}\), \([[:digit:]]\{1,\}\.[[:digit:]]\{1,\}\);\1 \2 \3;'`
204 ps=`ps -eo thcount | awk '{SUM+=$1} END {print SUM}'`
205 procs=`vmstat|grep lcpu|sed -e 's;.*lcpu=\([[:digit:]]\{1,4\}\).*;\1;'`
206 echo $load 1/$ps $$ $procs
209 echo "<<<aix_if>>>"
210 for ent in $(ifconfig -a | grep '^en' | cut -d ":" -f 1)
212     echo "[$ent]"
213     entstat "$ent" | grep -E "(^Hardware|^Bytes:|^Packets:|^Transmit|^Broadcast:|^Multicast:)"
214     entstat "$ent" | grep -p "Driver Flags:"
215 done
218 if which ntpq > /dev/null 2>&1 ; then
219     if [ $(lssrc -s xntpd|grep -c active) -gt 0 ] ; then
220         echo '<<<ntp>>>'
221         ntpq -np | sed -e 1,2d -e 's/^\(.\)/\1 /' -e 's/^ /%/'
222     fi
226 echo '<<<aix_multipath>>>'
227     lspath -F"name parent status"
230 echo '<<<aix_lvm>>>'
231     # -L disables LVM lock for the query. Avoids blocking while LVM is
232     # doing changes. For rootvg that is fine.
233     lsvg -L -l rootvg
236 echo '<<<tcp_conn_stats>>>'
237 netstat -ntfinet | awk ' /^tcp/ { c[$6]++; } END { for (x in c) { print x, c[x]; } }'
239 # Libelle Business Shadow
240 if type trd >/dev/null 2>&1
241 then
242   echo '<<<libelle_business_shadow:sep(58)>>>'
243   $(which trd) -s
246 if [ -x /usr/sbin/sendmail ] ; then
247     echo '<<<postfix_mailq>>>';
248     mailq 2>&1 | tail -n 6
251 # uptime formats
252 # 12:55pm  up 105 days, 21 hrs,  2 users, load average: 0.26, 0.26, 0.26 --> 9147600
253 # 1:41pm   up 105 days, 21:46,   2 users, load average: 0.28, 0.28, 0.27 --> 9150360
254 # 05:26PM  up           1:16,    1 user,  load average: 0.33, 0.21, 0.20 --> 4560
255 # 06:13PM  up           2:03,    1 user,  load average: 1.16, 1.07, 0.91 --> 7380
256 # 08:43AM  up 29 mins,           1 user,  load average: 0.09, 0.18, 0.21 --> 1740
257 # 08:47AM  up 66 days,  18:34,   1 user,  load average: 2.25, 2.43, 2.61 --> 5769240
258 # 08:45AM  up 76 days,  34 mins, 1 user,  load average: 2.25, 2.43, 2.61 --> 5769240
259 echo '<<<uptime>>>'
260 UPTIME=$(uptime | sed -e 's/^.*up//g' -e 's/[0-9]* user.*//g')
261 case $UPTIME in
262     *day* ) DAYS=$(echo $UPTIME | sed -e 's/days\{0,1\},.*//g') ;;
263     * ) DAYS="0" ;;
264 esac
266 case $UPTIME in
267     *:* )
268         HOURS=$(echo $UPTIME | sed -e 's/.*days\{0,1\},//g' -e 's/:.*//g')
269         MINS=$(echo $UPTIME | sed -e 's/.*days\{0,1\},//g' -e 's/.*://g' -e 's/,.*//g') ;;
270     *hr* )
271         HOURS=$(echo $UPTIME | sed -e 's/hrs\{0,1\},.*//g' -e 's/.*,//g')
272         MINS=0 ;;
273     *min* )
274         HOURS=0
275         MINS=$(echo $UPTIME | sed -e 's/mins\{0,1\},.*//g' -e 's/.*hrs\{0,1\},//g' -e 's/.*days\{0,1\},//g') ;;
276     * )
277         HOURS="0"
278         MINS=0 ;;
279 esac
281 echo $(((DAYS*86400)+(HOURS*3600)+(MINS*60)))
284 if cd $PLUGINSDIR 2>/dev/null
285 then
286     for skript in $(ls)
287     do
288         if [ -x "$skript" ] ; then
289             ./$skript
290     fi
291   done
293   # Call some plugins only every X'th second
294   for skript in [1-9]*/* ; do
295       if [ -x "$skript" ] ; then
296           run_cached plugins_${skript//\//\#} ${skript%/*} "$skript"
297       fi
298   done
302 # Fileinfo-Check: put patterns for files into /etc/check_mk/fileinfo.cfg
303 if [ -r "$MK_CONFDIR/fileinfo.cfg" ]; then
304     echo '<<<fileinfo:sep(124)>>>'
306     old_state=$(set +o)
307     set +f
309     # let the shell do all the expansion, and pipe all files to perl
310     (cat "$MK_CONFDIR/fileinfo.cfg" "$MK_CONFDIR/fileinfo.d/*" 2>/dev/null) | while read -r pattern; do
311         case $pattern in
312             /*) for f in $pattern; do echo $f; done
313                 ;;
314         esac
315     done | perl -e  '
316            print time."\n";
317            print "[[[header]]]\n";
318            print "name|status|size|time\n";
319            print "[[[content]]]\n";
320            while (<>) {
321                chomp $_;
322                if (-d $_) { next; }
323                if (not -f $_) {
324                    print "$_|missing\n";
325                    next;
326                }
327                ($device, $inode, $mode, $nlink, $uid, $gid, $rdev, $size,
328                 $atime, $mtime, $ctime, $blksize, $blocks) = stat($_);
329                if ($!) {
330                    print "$_|stat failed\n";
331                } else {
332                    print "$_|ok|$size|$mtime\n";
333                }
334            }'
335     set +vx; eval "$old_state"
339 # powerHA
340 if type lslpp >/dev/null 2>&1
341 then
342     cluster_cmd_output=$(lslpp -l cluster.es.server.rte)
343     if ! echo $cluster_cmd_output | grep -q "not installed"
344     then
345         # now the following commands should be available
346         nodes=$(cllsnode | grep "NODE" | sed -e s/NODE//g -e s/://g)
347         list_active_nodes=""
348         for node in $nodes
349         do
350             active_nodes=$(clgetactivenodes -n $node)
351             if echo $active_nodes | grep -q $node
352             then
353                 list_active_nodes=$list_active_nodes"\n$node"
354             fi
355         done
357         if [ "$list_active_nodes" ]
358         then
359             echo '<<<aix_hacmp_nodes>>>'
360             echo -e $list_active_nodes
361             cllsnode
362         fi
364         echo '<<<aix_hacmp_services>>>'
365         if type clshowsrv ; then
366             waitmax 5 clshowsrv -v
367         else # fallback, hardcoded base installation path
368             waitmax 5 /usr/es/sbin/cluster/utilities/clshowsrv -v
369         fi
371         echo '<<<aix_hacmp_resources:sep(58)>>>'
372         waitmax 5 clRGinfo -s
373     fi
376 echo '<<<local>>>'
377 if cd $LOCALDIR 2>/dev/null
378 then
379   for skript in $(ls)
380   do
381     if [ -x "$skript" ] ; then
382         ./$skript
383     fi
384   done
386   # Call some local checks only every X'th second
387   for skript in [1-9]*/* ; do
388       if [ -x "$skript" ] ; then
389           run_cached local_${skript//\//\#} ${skript%/*} "$skript"
390       fi
391   done
394 # MK's Remote Plugin Executor
395 if [ -e "$MK_CONFDIR/mrpe.cfg" ]
396 then
397     echo '<<<mrpe>>>'
398     grep -Ev '^[[:space:]]*($|#)' "$MK_CONFDIR/mrpe.cfg" | \
399     while read descr cmdline
400     do
401         PLUGIN=${cmdline%% *}
402         OUTPUT=$(eval "$cmdline")
403         echo "(${PLUGIN##*/}) $descr $? $OUTPUT" | tr \\n \\1
404         echo
405     done
408 # Agent output snippets created by cronjobs, etc.
409 if [ -d "$SPOOLDIR" ]
410 then
411     cd "$SPOOLDIR" > /dev/null
412     now=$(date +%s)
414     for file in *
415     do
416         # output every file in this directory. If the file is prefixed
417         # with a number, then that number is the maximum age of the
418         # file in seconds. If the file is older than that, it is ignored.
419         maxage=""
420         part="$file"
422         # Each away all digits from the front of the filename and
423         # collect them in the variable maxage.
424         while [ "${part/#[0-9]/}" != "$part" ]
425         do
426             maxage=$maxage${part:0:1}
427             part=${part:1}
428         done
430         # If there is at least one digit, than we honor that.
431         if [ "$maxage" ] ; then
432             mtime=$(stat -c %Y "$file")
433             if [ $((now - mtime)) -gt $maxage ] ; then
434                 continue
435             fi
436         fi
438         # Output the file
439         cat "$file"
440     done
441     cd - > /dev/null