This repository has been archived by the owner on Oct 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
check_wmi_plus.pl
executable file
·6698 lines (5943 loc) · 321 KB
/
check_wmi_plus.pl
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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/perl -w
#
# check_wmi_plus.pl - nagios plugin for agentless checking of Windows
#
# Copyright (C) 2011 Matthew Jurgens
# You can email me using: mjurgens (the at goes here) edcint.co.nz
# Download link can be found at http://www.edcint.co.nz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ----------------------------------------------------------
# ---------------- CHANGE THESE SETTINGS -------------------
# Location of the conf file for the remainder of the settings
# the full path is required since when Nagios runs this whole plugin becomes a subroutine of /usr/sbin/p1.pl
# and when it becomes a subroutine there is no such thing as the current directory or the same directory as this script
# eg $0 becomes /usr/sbin/p1.pl no matter where you install this script
my $conf_file='/etc/check_wmi_plus/check_wmi_plus.conf';
# we are looking for the dir where utils.pm is located. This is normally installed as part of Nagios
use lib "/usr/lib/nagios/plugins";
use lib "/usr/lib64/nagios/plugins";
# you shouldn't need to change anything else below this line
# change the settings in the $conf_file itself
# ---------------- END CHANGE THESE SETTINGS ---------------
# ----------------------------------------------------------
#==============================================================================
#================================= DECLARATIONS ===============================
#==============================================================================
our $VERSION=1.66;
# which version of PRO (if used does this require)
our $requires_PRO_VERSION=1.30;
use strict;
use Getopt::Long;
use Scalar::Util qw(looks_like_number reftype);
use Number::Format qw(:subs);
use Data::Dumper;
use Storable;
use Config::IniFiles;
use DateTime;
# command line option declarations
our $opt_auth_file='';
our $opt_Version='';
our $opt_help='';
our $opt_mode='';
our $opt_submode='';
our $opt_username='';
our $opt_password='';
our $opt_show_fields='';
our $opt_wminamespace='root/cimv2'; # this is the default namespace
our $opt_warn=(); # this becomes an array reference
our $opt_critical=(); # this becomes an array reference
our @opt_include_data=(); # this becomes an array reference
our @opt_exclude_data=(); # this becomes an array reference
our @opt_map_exit_status=();
our $debug=0; # default value
our $opt_value='';
our $opt_z='';
our $opt_inihelp='';
our $opt_package='';
our $opt_keep_state=1;
our $opt_keep_state_id='';
our $opt_helper_state_expiry='3600'; # default number of seconds after which helper state results are considered expired
our $opt_keep_state_expiry='3600'; # default number of seconds after which keep state results are considered expired
our $opt_join_state_expiry='3600'; # default number of seconds after which join state results are considered expired
our $opt_texthelp=0;
our $opt_command_examples='';
our $opt_ignore_versions='';
our $opt_ignore_auth_file_warnings='';
our $opt_installmodule_dir='';
our $opt_collect_usage='';
our $opt_show_usage='';
our $opt_use_cached_wmic_response='';
our $opt_log_usage_show='';
our $opt_log_usage_switch='';
our $opt_log_usage_suffix='';
our $opt_log_usage_keep='';
our $test_wmic_file_base='';
our $test_number=1;
our $test_generate='';
our $test_run='';
our $test_ignorejoinstatefiles='';
our $test_ignorehelperstatefiles='';
our $test_ignorekeepstatefiles='';
our $opt_filter_ini_rows_by_status='';
our $opt_disable_pro='';
# they all start with _ since later they are copied into the data array/hash and this reduces the chance they clash
# then we have consistent usage throughout
my %the_original_arguments=(); # used to store the original user specified command line arguments - sometimes we change the arguments
our %the_arguments = (
_mode => '', # just for duplicate storage of the mode (Since we actually modify the actual mode variable for ini files)
_submode => '', # just for duplicate storage of the submode
_arg1 => '',
_arg2 => '',
_arg3 => '',
_arg4 => undef, # we need this undef for checkeventlog so we know if something was specified or not - take care with other checks that use this
_arg5 => undef,
_bytefactor => '',
_delay => '',
_forcevariablescriteriaspec => '',
_host => '',
_ignorezerosizedrives => '',
_nodatamode => '',
_nodataexit => '',
_nodatastring => "WMI Query returned no data. The item you were looking for may NOT exist or the software that creates the WMI Class may not be running, or all data has been excluded.\n",
_staticsubcriteria => '1',
_timeout => '',
_truncate_output => 8192,
);
# arrays/hashes where we will store information about warn/critical specs/checks
my %warn_perf_specs_parsed; # list of parsed warn specs - a hash
my %critical_perf_specs_parsed; # list of parsed critical specs - a hash
my @warn_spec_result_list; # list of warn spec results
my @critical_spec_result_list; # list of critical spec results
our $wmic_delimiter='|';
our $wmic_split_delimiter='\|';
# key is the full name of the Module Version variable
# value is the minimum module version we'd like to use
my %good_module_versions=(
']',5.01,
'DateTime::VERSION',0.66,
'Getopt::Long::VERSION',2.38,
'Scalar::Util::VERSION',1.22,
'Number::Format::VERSION',1.73,
'Data::Dumper::VERSION',2.125,
'Config::IniFiles::VERSION',2.58,
'Storable::VERSION',2.22
);
my %displaywhatwhen_mode_list=();
# define some "string" constants
our %string_constant=(
ok => 0,
warning => 1,
critical => 2,
unknown => 3,
CRITERIA => 1,
EVENT => 2,
);
# for mode=checkeventlog
our %event_modes=(
ANY => 1,
INCLUDEALL => 2,
);
our %event_counts=(
CRITERIA => 1,
EVENT => 2,
);
#==============================================================================
#=================================== CONFIG ===================================
#==============================================================================
my $PROGNAME="check_wmi_plus";
my $default_bytefactor=1024;
# work out the conf file dir
our $conf_file_dir=$conf_file;
# remove the filename from the end of the conf_file to get the dir
$conf_file_dir=~s/^(.*)\/(.*?)$/$1/;
# ================================== DEFAULT CONFIGURATION ================================
# override these settings using the $conf_file (which is defined right near the top of this script)
# ---------------------- DEFAULT FILE LOCATIONS -------------------------
# Developed and tested with everything installed in /opt/nagios/bin/plugins
# You might not even use this variable if you have different locations for everything
our $base_dir='/opt/nagios/bin/plugins';
# This is the full path location of the wmic command
# - standard value "/usr/bin/wmic" since this is where it goes when it is compiled
our $wmic_command="/usr/bin/wmic"; # CHANGE THIS IF NEEDED
# set the location of the ini file. Set to '' if not using it or specify using the --inifile parameter
# set this to something else if you want
# - standard value "$conf_file_dir/check_wmi_plus.ini"
our $wmi_ini_file='';
# set the location of the ini dir. Set to '' if not using it or specify using the --inidir parameter
# set this to something else if you want
# - standard value "$conf_file_dir/check_wmi_plus.d"
our $wmi_ini_dir="$conf_file_dir/check_wmi_plus.d";
# set the location of temporary directory - used for keep state option
# if running on Windows then $ENV{'TMP'} will be set and hence used
our $tmp_dir=$ENV{"TMP"} || '/tmp';
# this script helps with making the manpage help. By default it is in the same directory as the plugin itself
our $make_manpage_script="$base_dir/check_wmi_plus.makeman.sh";
# this is the directory where the manpage is stored when created, defaults to the same directory as the ini files
our $manpage_dir="$wmi_ini_dir";
# PRO only: set the location of where the check_wmi_plus will store some persistent data
# - standard value "$conf_file_dir/check_wmi_plus.data"
our $wmi_data_dir="$conf_file_dir/check_wmi_plus.data";
# PRO only: this is the file where the usage stats are stored (if using it via $collect_usage_info or --icollectusage)
our $usage_db_file="$wmi_data_dir/check_wmi_plus.usagedb";
# PRO only: this is the file where the compiled ini files are stored
our $compiled_ini_file="$wmi_data_dir/check_wmi_plus.compiledini";
# ---------------------- OTHER CONFIGURATION -------------------------
# Disable the check of Perl Module versions
# The module versions are checked because the are often the cause of the plugin not working correctly
# If you want support you will need to reproduce the fault with the supported versions of the modules ie enable this check
# Set to 1 to ignore the version check, Set to 0 to perform the check
# Setting this to 1 has the same effect as the command line option --IgnoreMyOutDatedPerlModuleVersions
# Setting either this to 1 or the command line option will disable the check
our $ignore_my_outdated_perl_module_versions=0;
# force the use of the wmic command line binary. Set to 1 to force
# this is used if you have the wmiclient library installed but want to use the command line version
our $force_wmic_command=0;
# used cached wmic responses
# you don't really want this on unless you want to totally bypass wmic
# some checks will totally fail with this set
# all your check response will be inaccurate
our $use_cached_wmic_responses=0;
# extra wmic args
# specify standard additional arguments to pass directly to the wmic command line for ALL invocations of wmic
# Note that the command line parameter --extrawmicarg is also available if you need this on a case by case basis
# This is an array so you need to put each argument into a separate array index
# eg @opt_extra_wmic_args=( "argument1=value1", "argument2=value2" );
# should be set to @opt_extra_wmic_args=() if not used
# extra wmic arguments specified on the command line are added to the ones specified here
our @opt_extra_wmic_args=( ); # extra arguments to pass to wmic
# force reading of the ini files - you may want to do this if you are doing a non-ini file check and you are using variables defined in an ini file
# only use this if you really needed it since it makes each invocation of the plugin a lot slower
our $force_ini_open=0;
# PRO Only:
# collect various usage info and store it in $usage_db_file for later analysis
# also available by using the --icollectusage command line parameter
# requires additional perl modules if invoked
our $collect_usage_info=1;
# PRO Only:
# show various usage info at end of plugin output (more info than is collected)
# also available by using the --ishowusage command line parameter
# requires additional perl modules if invoked
our $show_usage_info=1;
# Pro Only:
# Generate a Nagios error if there is a problem updating the usage stats
# If set to 0, errors updating usage stats will be shown in the plugin output but will not impact the Nagios alert type
our $generate_nagios_error_for_usage_stats_problem=1;
# Pro Only:
# use compiled ini files for additional speed
our $use_compiled_ini_files=1;
# ============================= END OF DEFAULT CONFIGURATION ================================
our $host_os='';
eval {
# get the Config module if it is available (so we can get the ostype)
require Config;
$host_os = $Config::Config{'osname'};
};
# try and open the conf file to get any user set variables
# if it does not work, just ignore and carry on
if (-f "$conf_file") {
if (!defined(do "$conf_file")) {
die "Configuration File Error with $conf_file (mostly likely a syntax error)";
}
}
# check the base_dir
# if it does not work die
if (! -d "$base_dir") {
die "The variable '\$base_dir' in $conf_file is not set to a valid directory";
}
# do this use here since the user might have changed the directory we in the conf file
use utils qw ($TIMEOUT %ERRORS &print_revision &support);
# list all valid modes with dedicated subroutines here
# all the modes that can take a critical/warning specification set to value of 1
my %mode_list = (
checkcpu => 1,
checkcpuq => 1,
checkdnsrecords => 1,
checkdrivesize => 1,
checkeventlog => 1,
checkfileage => 1,
checkfilesize => 1,
checkfoldersize => 1,
checkgeneric => 1,
checkgroup => 1,
checkgroupuser => 1,
checklogon => 1,
checkmem => 1,
checknetwork => 1,
checkpage => 1,
checkprintjob => 1,
checkprocess => 1,
checkquota => 1,
checkservice => 1,
checkshare => 1,
checksmart => 1,
checkstartupcommand => 1,
checktime => 1,
checkuptime => 1,
checkuseraccount => 1,
checkvolsize => 1,
checkwsusserver => 0,
);
# multipliers are calculated as BYTEFACTOR^mulitpler eg m = x * 1000^2 or x * 1024^2
my %multipliers=(
k => 1,
m => 2,
g => 3,
t => 4,
p => 5,
e => 6,
);
our %time_multipliers=( # use "our" so that the help.pl library can access it
sec => 1,
min => 60,
hr => 3600,
day => 86400,
wk => 604800,
mth => 2629800, # this one is not exact. We assume that there are 365.25/12=30.4375 days in a month on average
yr => 31557600, # this one is also approximate. We assume that there are 365.25 days per year
);
my %include_mode_text = (
0 => 'Exclude',
1 => 'Include',
);
# this regex finds if a multiplier is valid - just list all multiplier options in here
my $multiplier_regex="[KMGTPE|min|hr|day|wk|mth|yr]";
# defined smart attribute code to names mappings - these are the SMART attributes we extract in checksmart
my %smartattributes=(
5 => 'Reallocated_Sector_Count',
9 => 'Power_On_Hours',
12 => 'Power_Cycle_Count',
194=> 'Temperature',
197=> 'Current_Pending_Sector',
198=> 'Offline_Uncorrectable',
);
# this hash contains lists of the fields that can be used in the warning/critical specs for specific modes
our %valid_test_fields = (
# key name is the name of the mode
# value is an array of fields names to check against
# the first one in the list is the default if none is specified in a warn/crit specification
# you should always specify at least one per mode that uses warning/critical checking so that it knows what to check against
checkcpu => [ qw(_AvgCPU) ],
checkcpuq => [ qw(_AvgCPUQLen) ],
checkdrivesize => [ qw(_Used% _UsedSpace _UsedGB _Free% FreeSpace_FreeGB) ],
checkeventlog => [ qw(_ItemCount) ],
checkfileage => [ qw(_FileAge) ],
checkfilesize => [ qw(FileSize _ItemCount) ],
checkfoldersize => [ qw(_FolderSize _ItemCount) ],
checkgeneric => [ qw(FileControlBytesPersec FileControlOperationsPersec FileDataOperationsPersec FileReadBytesPersec FileReadOperationsPersec FileWriteBytesPersec FileWriteOperationsPersec) ],
checkgroup => [ qw(_ItemCount _ItemChange LocalAccount Status) ],
checkgroupuser => [ qw(_ItemCount _ItemChange) ],
checklogon => [ qw(_ItemCount _ItemChange) ],
checkmem => [ qw(_MemUsed% _MemFree% _MemUsed _MemFree _MemTotal) ],
checknetwork => [ qw(CurrentBandwidth _PacketsSentPersec _PacketsReceivedPersec OutputQueueLength PacketsReceivedErrors _BytesSentPersec _BytesReceivedPersec _SendBytesUtilisation _ReceiveBytesUtilisation) ],
checkpage => [ qw(_Used% _Used _Free _Free% _PeakUsed% _PeakUsed _PeakFree _PeakFree% _Total) ],
checkprintjob => [ qw(_ItemCount _ItemChange Color Status TotalPages Owner Document DataType) ],
checkprocess => [ qw(_ItemCount _NumExcluded) ],
checkquota => [ qw(_ItemCount _ItemChange DiskSpaceUsed Limit Status WarningLimit) ],
checkservice => [ qw(_NumBad _NumGood _NumExcluded _Total) ],
checkshare => [ qw(_ItemCount _ItemChange) ],
checksmart => [ qw(_DiskFailing _ItemCount Temperature) ],
checkstartupcommand=>[ qw(_ItemCount _ItemChange Command Description Name User) ],
checktime => [ qw(_DiffSec _CWPSec _WindowsSec) ],
checkuptime => [ qw(_UptimeSec) ],
checkuseraccount => [ qw(_ItemCount _ItemChange Disabled LocalAccount Lockout PasswordChangeable PasswordExpires PasswordRequired SIDType Status) ],
checkvolsize => [ qw(_Used% _UsedSpace _UsedGB _Free% FreeSpace_FreeGB) ],
);
# this hash contains lists of the fields that are displayed for specific modes before any per row display starts
# documentation on format for this is the same as for %display_fields
our %pre_display_fields = (
checknetwork => [ '_DisplayMsg||~|~| - ||', '_NumInterfaces||Number of Interfaces||~||. Interface Details - ' ],
checkpage => [ '_OverallResult||Overall Status - |~|: ||. Individual Page Files Detail' ],
checksmart => [ '_DisplayMsg||Overall Status - |~| - ||', '_Total| Disks(s)| Found |~|||', '_NumGood| OK|~|~| and ||', '_NumBad| failing |~|~|~||' ],
);
# this hash contains lists of the fields that are displayed for specific modes
our %display_fields = (
# key name is the name of the mode
# value is an array of fields names to display
# the value can be in 2 formats -
# 1) FIELD (where we just display this field like FIELD=xx,
# 2) FIELD|UNITS (where we just display this field like FIELD=xxUNITS,
# 3) FIELD|UNITS|DISPLAY|SEP|DELIM|START|END
# where we display this FIELD like STARTDISPLAYSEPxxUNITSENDDELIM
# the default DELIM is comma space, if DELIM is set to ~ then none will be used
# the default SEP is =, if SEP is set to ~ then none will be used
# DISPLAY normally shows FIELD or whatever you specify as DISPLAY. Set DISPLAY to ~ to show nothing.
# if units is prefixed with # then we use a function to convert it to a scaled based figure using prefixes like K, M, G etc - the calculation is influenced by the BYTEFACTOR setting
# In DISPLAY/START/END anything enclosed in {} will be substituted by the value of that item of that name eg {DeviceID} will replace by the value contained in DeviceID eg C:
# eg BytesSentPersec will be shown as BytesSentPersec=XX,
# eg BytesSentPersec|BYTES will be shown as BytesSentPersec=XXBytes,
# eg _Used%|%|.|.||(|) will be shown as (45.2%)
# I was going to use qw() but it makes it way harder to read. You could still use it for the most basic format
checkcpu => [ '_DisplayMsg||~|~| - ||', '_AvgCPU|%|Average CPU Utilisation| |~||' ],
checkcpuq => [ '_DisplayMsg||~|~| - ||', '_AvgCPUQLen||Average CPU Queue Length| | ||', '_arg1| points|~|~|~|(| with', '_delay| sec delay|~| | ||', '_CPUQPoints||~|~|~|gives values: |)' ],
checkdnsrecords => [ '_DisplayMsg||~|~| - ||', '_DNSDetails||~|~|~||. ', '_WMIDetails||~|~|~||. ' ],
checkdrivesize => [ '_DisplayMsg||~|~| - ||', 'DiskDisplayName||~|~| ||', 'Size|#B|Total||||', '_UsedSpace|#B|Used|| ||', '_Used%|%|~|~||(|)', 'FreeSpace|#B|Free|| ||', '_Free%|%|~|~||(|)' ],
checkeventlog => [ '_DisplayMsg||~|~| - ||', '_ItemCount| event(s)|~|~| ||', '_SeverityType||~|~||of Severity Level: "|"', '_arg3| hours|~|~|~|were recorded in the last |', '_arg1||~|~|~| from the | Event Log.', "_EventList||~|~|~||" ],
checkfileage => [ '_DisplayMsg||~|~| - ||', '_arg1||Age of File| |~|| is ', '_NicelyFormattedFileAge||~|~|~|| or ', '_DisplayFileAge||~|~|~||', '_PerfDataUnit||~|~|||(s).' ],
checkfilesize => [ '_DisplayMsg||~|~| - ||', '_arg1||File| |~|| is ', 'FileSize|#B|~|~|. ||', '_ItemCount| instance(s)|Found| |.||' ],
checkfoldersize => [ '_DisplayMsg||~|~| - ||', '_arg1||Folder| |~|| is ', '_FolderSize|#B|~|~|. ||', '_ItemCount| files(s)|Found| |.||', '_FileList||~|~|~||' ],
checkgeneric => [ '_DisplayMsg||~|~| - ||', 'FileControlBytesPersec', 'FileControlOperationsPersec', 'FileDataOperationsPersec', 'FileReadBytesPersec', 'FileReadOperationsPersec', 'FileWriteBytesPersec', 'FileWriteOperationsPersec' ],
checkgroup => [ '_DisplayMsg||~|~| - ||', '_ItemCount| group(s). |Found |~|~||', '_ItemChange||Groups changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checkgroupuser => [ '_DisplayMsg||~|~| - ||', '_ItemCount| group user(s). |Found |~|~||', '_ItemChange||Group users changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checklogon => [ '_DisplayMsg||~|~| - ||', '_ItemCount| logon(s). |Found |~|~||', '_ItemChange||Logons changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checkmem => [ '_DisplayMsg||~|~| - ||', 'MemType||~|~|~||: ', '_MemTotal|#B|Total|: | - ||', '_MemUsed|#B|Used|: | ||', '_MemUsed%|%|~|~| - |(|)', '_MemFree|#B|Free|: | ||', '_MemFree%|%|~|~||(|)' ],
checknetwork => [ '_DisplayMsg||~|~| - ||', '_DisplayName||Interface:|~|||', 'IPAddress||IP Address:|~|||', 'MACAddress||MAC Address |~|||', 'CurrentBandwidth|#bit/s|Speed:|~|||', 'DHCPEnabled', '_BytesSentPersec|#B/sec|Byte Send Rate|| (||', '_SendBytesUtilisation|%|Utilisation||), ||', '_BytesReceivedPersec|#B/sec|Byte Receive Rate||(||', '_ReceiveBytesUtilisation|%|Utilisation||) ||', '_PacketsSentPersec|#packet/sec|Packet Send Rate||||', '_PacketsReceivedPersec|#packet/sec|Packet Receive Rate||||', 'OutputQueueLength||Output Queue Length||||', 'PacketsReceivedErrors||Packets Received Errors||||' ],
checkquota => [ '_DisplayMsg||~|~| - ||', '_ItemCount| quota(s). |Found |~|~||', '_ItemChange||Quotas changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checkpage => [ '_DisplayMsg||~|~| - ||', 'Name||~|~| ||', '_Total|#B|Total|: | - ||', '_Used|#B|Used|: | ||', '_Used%|%|~|~| - |(|)', '_Free|#B|Free|: | ||', '_Free%|%|~|~||(|)', '_PeakUsed|#B|Peak Used|: | ||', '_PeakUsed%|%|~|~| - |(|)', '_PeakFree|#B|Peak Free|: | ||', '_PeakFree%|%|~|~||(|)' ],
checkprintjob => [ '_DisplayMsg||~|~| - ||', '_ItemCount| print jobs(s). |Found |~|~||', '_ItemChange||Print Job Queue changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checkprocess => [ '_DisplayMsg||~|~| - ||', '_ItemCount| Instance(s)|Found |~|~|| of "{_arg1}" running ', '_NumExcluded| excluded|~|~|~|(|). ', 'ProcessList||~|~|~||' ],
checkservice => [ '_DisplayMsg||~|~| - ||', '_Total| Services(s)|Found |~|||', '_NumGood| OK|~|~| and ||', '_NumBad| with problems |~|~|~||', '_NumExcluded| excluded|~|~|~|(|). ', '_ServiceList||~|~|~||' ],
checkshare => [ '_DisplayMsg||~|~| - ||', '_ItemCount| shares(s). |Found |~|~||', '_ItemChange||Shares changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checksmart => [ '_DisplayMsg||~|~| - ||', '_PhysicalDeviceID||Dev#|~|||', 'Model||~|~|||', 'SerialNumber||Serial#|~|||', 'PredictFailure', 'Temperature' ],
checkstartupcommand=>[ '_DisplayMsg||~|~| - ||', '_ItemCount| startup command(s). |Found |~|~||', '_ItemChange||Startup Commands changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checktime => [ '_DisplayMsg||~|~| - ||', '_DiffSec| seconds|Time Difference is |~|||', '_WindowsTime||Time from Windows is |~|||(UTC)', '_CWPTime||Check WMI Plus time is |~|||(UTC)' ],
checkuptime => [ '_DisplayMsg||~|~| - ||', '_DisplayTime||System Uptime is |~|.||' ],
checkuseraccount => [ '_DisplayMsg||~|~| - ||', '_ItemCount| user account(s). |Found |~|~||', '_ItemChange||User Accounts changed since last check=|~|~||', '_ItemList||~|~|~||' ],
checkvolsize => [ '_DisplayMsg||~|~| - ||', 'VolumeDisplayName||~|~| ||', 'Capacity|#B|Total||||', '_UsedSpace|#B|Used|| ||', '_Used%|%|~|~||(|)', 'FreeSpace|#B|Free|| ||', '_Free%|%|~|~||(|)' ],
);
# this hash contains lists of the fields that are used as performance data for specific modes
our %performance_data_fields = (
# key name is the name of the mode
# value is an array of fields names to display
# the value can be in 2 formats -
# 1) FIELD
# 2) FIELD|UNITS
# 3) FIELD|UNITS|DISPLAY
# In DISPLAY/UNITS anything enclosed in {} will be substituted by the value of that item of that name eg {DeviceID} will replace by the value contained in DeviceID eg C:
checkcpu => [ '_AvgCPU|%|Avg CPU Utilisation' ],
checkcpuq => [ '_AvgCPUQLen||Avg CPU Queue Length' ],
checkdrivesize => [ '_UsedSpace|B|{DiskDisplayName} Space', '_Used%|%|{DiskDisplayName} Utilisation', 'Size|B|{DiskDisplayName} Size' ],
checkeventlog => [ '_ItemCount||Event Count' ],
checkfileage => [ '_DisplayFileAge|{_PerfDataUnit}|{_arg1} Age' ],
checkfilesize => [ 'FileSize|B|{_arg1} Size', '_ItemCount||File Count' ],
checkfoldersize => [ '_FolderSize|B|{_arg1} Size', '_ItemCount||File Count' ],
checkgeneric => [ 'FileControlBytesPersec', 'FileControlOperationsPersec', 'FileDataOperationsPersec', 'FileReadBytesPersec', 'FileReadOperationsPersec', 'FileWriteBytesPersec', 'FileWriteOperationsPersec' ],
checkgroup => [ '_ItemCount||Group Count' ],
checkgroupuser => [ '_ItemCount||Group User Count' ],
checklogon => [ '_ItemCount||Logon Count' ],
checkmem => [ '_MemUsed|B|{MemType} Used', '_MemUsed%|%|{MemType} Utilisation' ],
checknetwork => [ '_BytesSentPersec||{_DisplayName} BytesSentPersec', '_SendBytesUtilisation|%|{_DisplayName} Send Utilisation', '_BytesReceivedPersec||{_DisplayName} BytesReceivedPersec', '_ReceiveBytesUtilisation|%|{_DisplayName} Receive Utilisation', '_PacketsSentPersec||{_DisplayName} PacketsSentPersec', '_PacketsReceivedPersec||{_DisplayName} PacketsReceivedPersec', 'OutputQueueLength||{_DisplayName} OutputQueueLength', 'PacketsReceivedErrors||{_DisplayName} PacketsReceivedErrors' ],
checkpage => [ '_Total|B|{Name} Page File Size', '_Used|B|{Name} Used', '_Used%|%|{Name} Utilisation', '_PeakUsed|B|{Name} Peak Used', '_PeakUsed%|%|{Name} Peak Utilisation' ],
checkprintjob => [ '_ItemCount||Print Job Count' ],
checkprocess => [ '_ItemCount||Process Count', '_NumExcluded||Excluded Process Count' ],
checkquota => [ '_ItemCount||Share Count', ],
checkservice => [ '_Total||Total Service Count', '_NumGood||Service Count OK State', '_NumBad||Service Count Problem State', '_NumExcluded||Excluded Service Count' ],
checkshare => [ '_ItemCount||Share Count' ],
checksmart => [ 'Reallocated_Sector_Count||{_DiskDisplayName}_Reallocated_Sector_Count','Power_On_Hours||{_DiskDisplayName}_Power_On_Hours','Power_Cycle_Count||{_DiskDisplayName}_Power_Cycle_Count','Temperature||{_DiskDisplayName}_Temperature','Current_Pending_Sector||{_DiskDisplayName}_Current_Pending_Sector','Offline_Uncorrectable||{_DiskDisplayName}_Offline_Uncorrectable' ],
checkstartupcommand=>[ '_ItemCount||Startup Command Count' ],
checktime => [ '_DiffSec' ],
checkuptime => [ '_UptimeSec|s|Uptime Seconds', '_UptimeMin|min|Uptime Minutes', '_UptimeHours|hours|Uptime Hours', '_UptimeDays|days|Uptime Days' ],
checkuseraccount => [ '_ItemCount||User Account Count' ],
checkvolsize => [ '_UsedSpace|B|{VolumeDisplayName} Space', '_Used%|%|{VolumeDisplayName} Utilisation' ],
);
# a couple of defaults we use for ini files
my $default_inifile_number_wmi_samples=1;
my $default_inifile_delay=5;
# some default help text
our $default_help_text_delay="DELAY (optional) specifies the number of seconds over which the utilisation is calculated. The longer you can make this without timing out, the more accurate it will be. If specifying longer values. You may also need to use the -t parameter to set a longer script timeout. Only valid if also specifying --nokeepstate ie you are not using the state keeping feature. We recommend that you do keep state and hence do not use --nokeepstate.";
# name of command example ini file - not named as .ini so that it does not get read as part of reading other ini files
# assumed to be in the same dir as the other ini files
my %command_examples_ini_file=(
1 => 'CommandExamples.chtml',
2 => 'WarnCritExamples.chtml',
);
# counters for the number of wmic calls via specific methods
our $wmic_calls=0;
our $wmic_library_calls=0;
# and for the testing modes we also need a counter to just count the number of calls we make to get wmi data
our $global_wmic_call_counter=0;
our $ini_based_check=0;
our $final_exit_code='';
our $plugin_output='';
# PRO only: this is the file where we control the usage file currently written to
our $current_usage_db_suffix_file="$wmi_data_dir/check_wmi_plus.usagedb.suffix";
# Pro flags for final decisions on usage stats
our $i_will_show_usage_stats=0;
our $i_will_collect_usage_info=0;
# list of static ini variables
our %ini_static_variables=();
# disable the use of static variables
my $opt_disable_static_variables=0;
# flag to tell us if we have opened the ini files already
my $ini_files_already_opened=0;
# name of the keep state file
our $keep_state_file='';
#==============================================================================
#================================== PARAMETERS ================================
#==============================================================================
my @saved_ARGV=@ARGV;
# if the user is using a DOS type file for their nagios command/service definitions then we may see a CR character at the end of the command line
# remove it by doing a regex on the last character of the last parameter (if it is set)
if ($ARGV[$#ARGV]) {
$ARGV[$#ARGV]=~s/\r$//;
}
if ($host_os =~ m/win32$/i) {
# if running on Windows we have to remove any ' from the start and end of all command line arguments
# For windows, the ' is not used to delimit a string, the " is used instead.
for (my $i=0;$i<=$#ARGV;$i++) {
$ARGV[$i] =~s/^\'(.*)\'$/$1/;
}
}
Getopt::Long::Configure('no_ignore_case');
GetOptions(
"Authenticationfile=s" => \$opt_auth_file,
"arguments=s" => \$the_arguments{'_arg1'},
"bytefactor=s" => \$the_arguments{'_bytefactor'},
"Convertslash" => \$the_arguments{'_convertslash'},
"critical=s@" => \$opt_critical,
"debug+" => \$debug,
"excludedata=s@" => \@opt_exclude_data,
"extrawmicargs=s@" => \@opt_extra_wmic_args,
"fieldshow" => \$opt_show_fields,
"filterinirowsbystatus=s" => \$opt_filter_ini_rows_by_status,
"forceiniopen" => \$force_ini_open,
"forcewmiccommand" => \$force_wmic_command,
"forcetruncateoutput=s" => \$the_arguments{'_truncate_output'},
"forceVariablesCriteriaSpec" => \$the_arguments{'_forcevariablescriteriaspec'},
# --- g ---
"help" => \$opt_help,
"helperexpiry=s" => \$opt_helper_state_expiry,
"Hostname=s" => \$the_arguments{'_host'},
"icollectusage!" => \$opt_collect_usage,
"iexamples=s" => \$opt_command_examples,
"IgnoreMyOutDatedPerlModuleVersions" => \$opt_ignore_versions,
"IgnoreAuthFileWarnings" => \$opt_ignore_auth_file_warnings,
"IgnoreZeroSizedDrives" => \$the_arguments{'_ignorezerosizedrives'},
"includedata=s@" => \@opt_include_data,
"idisablepro" => \$opt_disable_pro,
"inidir=s" => \$wmi_ini_dir,
"inifile=s" => \$wmi_ini_file,
"inihelp" => \$opt_inihelp,
"installmoduledir" => \$opt_installmodule_dir,
"ipackage" => \$opt_package,
"itexthelp" => \$opt_texthelp,
"ishowusage!" => \$opt_show_usage,
"iusecachewmicresponse" => \$opt_use_cached_wmic_response,
"itestwmicfilebase=s" => \$test_wmic_file_base,
"itestnumber=s" => \$test_number,
"itestgenerate" => \$test_generate,
"itestrun" => \$test_run,
"itestignorehelperstatefiles" => \$test_ignorehelperstatefiles,
"itestignorejoinstatefiles" => \$test_ignorejoinstatefiles,
"itestignorekeepstatefiles" => \$test_ignorekeepstatefiles,
"iRequireAllCriticals" => \$the_arguments{'_requireallcriticals'},
"iRequireAllWarnings" => \$the_arguments{'_requireallwarnings'},
"joinexpiry=s" => \$opt_join_state_expiry,
"keepexpiry=s" => \$opt_keep_state_expiry,
"keepid=s" => \$opt_keep_state_id,
"keepstate!" => \$opt_keep_state,
"logkeep" => \$opt_log_usage_keep,
"logshow" => \$opt_log_usage_show,
"logsuffix=s" => \$opt_log_usage_suffix,
"logswitch" => \$opt_log_usage_switch,
"Mapexitstatus=s@" => \@opt_map_exit_status,
"mode=s" => \$opt_mode,
"namespace=s" => \$opt_wminamespace,
"nodataexit=s" => \$the_arguments{'_nodataexit'},
"nodatamode" => \$the_arguments{'_nodatamode'},
"nodatastring=s" => \$the_arguments{'_nodatastring'},
"otheraguments=s" => \$the_arguments{'_arg2'},
"password=s" => \$opt_password,
# --- q ---
# --- r ---
"submode=s" => \$opt_submode,
"timeout=i" => \$the_arguments{'_timeout'},
"username=s" => \$opt_username,
"value=s" => \$opt_value,
"variablesdisabled" => \$opt_disable_static_variables,
"version" => \$opt_Version,
"warning=s@" => \$opt_warn,
"ydelay=s" => \$the_arguments{'_delay'},
"z" => \$opt_z,
"3arg=s" => \$the_arguments{'_arg3'},
"4arg=s" => \$the_arguments{'_arg4'},
"5arg=s" => \$the_arguments{'_arg5'},
);
if ($test_run) {
# if both options supplied, ignore generate
$test_generate=0;
}
# see if the check_wmi_plus_lib module is available
our $use_wmilib=0;
# to see if the pro library is being used
our $use_pro_library=0;
if (-f "$base_dir/check_wmi_plus_pro.pl") {
if (do "$base_dir/check_wmi_plus_pro.pl") {
if ($opt_disable_pro) {
$debug && print "Pro Library is present - but disabled by command line option\n";
} else {
$debug && print "Pro Library is present\n";
init_pro_module();
}
} else {
print "Pro Library exists but does not compile: $@\n";
exit 1;
}
}
if ($opt_installmodule_dir) {
# look for a nagios looking path in the @INC
# if there is one, link the perl module to that dir
# if not tell the user to pick another one themselves
my $install_dir='';
foreach my $inc_path (@INC) {
if ($inc_path=~/nagios|icinga/i) {
$install_dir=$inc_path;
last;
}
}
if ($install_dir) {
print "Linking the Pro Library to $install_dir\n";
`ln -s "$wmi_ini_dir/check_wmi_plus_pro.pl" "$install_dir"`;
# check its ok
if ( ! -l "$install_dir/check_wmi_plus_pro.pl") {
print "Could not successfully link the Pro Library!\n";
$install_dir='';
}
}
if (! $install_dir) {
print "Could not automatically find a suitable directory to install the module to.\nCopy or link the Pro Library to one of the following directories:\n" . join(", ",@INC);
}
exit 1;
}
if ($opt_log_usage_switch && $use_pro_library) {
switch_current_usage_db();
exit;
}
if ($opt_log_usage_show && $use_pro_library) {
if ($i_will_collect_usage_info) {
my ($current_usage_db_file,$suffix)=get_current_usage_db_file();
print "Current Usage DB File:$current_usage_db_file\n";
} else {
print "Collection of Usage Stats is not currently enabled.\n";
}
exit;
}
# check module versions as they very often cause problems if older than developed with
# unless ignored by command line option
if ($opt_ignore_versions || $ignore_my_outdated_perl_module_versions) {
# the user has to configure this so they get warned at least once if it is a problem
# ignore perl module version checks
} else {
# check the versions
my $versions_ok=check_module_versions(0);
if (!$versions_ok) {
finish_program($ERRORS{'UNKNOWN'});
}
}
if ($debug || $test_generate) {
my $command_line=join(' ',@saved_ARGV);
if ($test_generate) {
my $test_commandline=$command_line;
# remove some specific --itest parameters
$test_commandline=~s/--itestg\w*//g;
$test_commandline=~s/--itestn\w*[= ]*\d+//g;
print "\n# ---------------------------------------------------------------------------------------------\n[" . int(rand()*10000000) . "]\ndescription=\ncmd=$0 $test_commandline\n";
} else {
if (! $opt_z) {
# try and mask any user/password
$command_line=~s/-u\s*(\S*?)\s/-u USER /;
$command_line=~s/-p\s*(\S*?)\s/-p PASS /;
}
print "Command Line (v$VERSION): $0 $command_line\n";
print "Base Dir: $base_dir\n";
print "Conf File Dir: $conf_file_dir\n";
print "Loaded Conf File $conf_file\n";
print "WMI Ini Dir: $wmi_ini_dir\n";
if ($debug>=2) {
no warnings;
# get some info about the system
$wmic_delimiter='!';
$wmic_split_delimiter='!';
print "======================================== SYSTEM INFO =====================================================\n";
print "--------------------- Module Versions ---------------------\n";
check_module_versions(1);
print "Net::DNS - $Net::DNS::VERSION\n";
print "--------------------- Environment ---------------------\n";
print "ENV=" . Dumper(\%ENV);
print "--------------------- Computer System ---------------------\n";
get_wmi_data(1,'',"SELECT * FROM Win32_ComputerSystem",
'','',my $dummy1,\$the_arguments{'_delay'},undef,0,0);
print "--------------------- Operating System ---------------------\n";
get_wmi_data(1,'',"SELECT * FROM Win32_OperatingSystem",
'','',my $dummy2,\$the_arguments{'_delay'},undef,0,0);
$wmic_delimiter='|';
$wmic_split_delimiter='\|';
print "-------------------------- Time ---------------------\n";
my $gmt = DateTime->now(time_zone => 'gmt');
my $local = DateTime->now(time_zone=>'local');
print `date`;
print "GMT=$gmt, LOCAL=$local\n";
print "======================================= END SYSTEM INFO ===================================================\n";
}
}
}
if ($opt_package) {
print "Creating Check WMI Plus Bundle\n";
my $tarfile="check_wmi_plus.v$VERSION.tar.gz";
# tar up the files and dir, exclude subversion directory
# run the plugin and put its help screen in a readme
my $output=`$0 --itexthelp --noishowusage --noicollectusage`;
open(README,'>',"$base_dir/check_wmi_plus.README.txt");
print README "check_wmi_plus v$VERSION\nFor installation details and more downloads see http://www.edcint.co.nz/checkwmiplus\nThe --help output follows - \n\n";
print README $output;
close(README);
# a bit of hard coding here .....
my $cmd="
cd $base_dir;
cp $conf_file_dir/check_wmi_plus.conf $conf_file_dir/check_wmi_plus.conf.sample;
sed -i 's#/opt/nagios/bin/plugins#CHANGE ME TO THE DIRECTORY WHERE THE PLUGIN IS INSTALLED#' $conf_file_dir/check_wmi_plus.conf.sample;
# make the compiled ini file zero so that it forces a recompile
rm $wmi_data_dir/check_wmi_plus.compiledini;
touch $wmi_data_dir/check_wmi_plus.compiledini;
chown -R nagios:nagios $conf_file_dir $base_dir;
tar czvf $tarfile --no-recursion --exclude=.svn --exclude=man1 --exclude=check_wmi_plus_pro.ini check_wmi_plus.pl check_wmi_plus_help.pl check_wmi_plus.README.txt $conf_file_dir/check_wmi_plus.conf.sample $wmi_ini_dir/* $wmi_data_dir $wmi_data_dir/check_wmi_plus.compiledini event_generic.pl check_wmi_plus.makeman.sh
# make the txt versions of commonly emailed files
mkdir cwp_txt_versions
cd cwp_txt_versions
cp ../check_wmi_plus.pl check_wmi_plus.pl.txt
cp ../check_wmi_plus_help.pl check_wmi_plus_help.pl.txt
cp ../check_wmi_plus_pro.pl check_wmi_plus_pro.pl.txt
";
$output=`$cmd 2>&1`;
print "CMD:$cmd\n\nOUTPUT:$output\n\n";
print "Created $base_dir/$tarfile\n";
$output=`rm $conf_file_dir/check_wmi_plus.conf.sample`;
exit 0;
}
if ($opt_command_examples) {
if (exists($command_examples_ini_file{$opt_command_examples})) {
$debug && print "Example file for '$opt_command_examples' is $wmi_ini_dir/$command_examples_ini_file{$opt_command_examples}\n";
show_command_examples("$wmi_ini_dir/$command_examples_ini_file{$opt_command_examples}");
} else {
print "You need to supply a parameter argument from one of the following: " . Dumper(keys %command_examples_ini_file) . "\n";
}
exit 0;
}
# check up on the ini file
if ($wmi_ini_file && ! -f $wmi_ini_file) {
print "This plugin requires an INI file. Configure its location by setting the \$wmi_ini_file variable in '$conf_file' or by using the --inifile parameter to override the default setting. Ini File currently set to '$wmi_ini_file'";
finish_program($ERRORS{'UNKNOWN'});
} elsif ($wmi_ini_dir && ! -d $wmi_ini_dir) {
print "This plugin requires an INI directory. Configure its location by setting the \$wmi_ini_dir variable in '$conf_file' or by using the --inidir parameter to override the default setting. Ini Directory currently set to '$wmi_ini_dir'. ";
finish_program($ERRORS{'UNKNOWN'});
}
if ($the_arguments{'_timeout'}) {
$TIMEOUT=$the_arguments{'_timeout'};
}
if (!$opt_help && !$opt_texthelp && !$opt_inihelp) {
# Setup the trap for a timeout only if not showing the help info
$SIG{'ALRM'} = sub {
$plugin_output.="UNKNOWN - Plugin Timed out ($TIMEOUT sec). There are multiple possible reasons for this, some of them include - The host $the_arguments{_host} might just be really busy, it might not even be running Windows.\n";
finish_program($ERRORS{'UNKNOWN'});
};
alarm($TIMEOUT);
}
if ($the_arguments{'_bytefactor'}) {
if ($the_arguments{'_bytefactor'} ne '1024' && $the_arguments{'_bytefactor'} ne '1000') {
print "The BYTEFACTOR option must be 1024 or 1000. '$the_arguments{'_bytefactor'}' is not valid.\n";
include_help();
short_usage();
}
}
my $actual_bytefactor=$the_arguments{'_bytefactor'} || $default_bytefactor;
# store the original specified command line bytefactor for later use (we need it for checknetwork)
$the_arguments{'_savedbytefactor'}=$the_arguments{'_bytefactor'} || '';
# reload the arguments hash bytefactor setting with the actual value used
# this allows use to substitute it into custom calculation fields
$the_arguments{'_bytefactor'}=$actual_bytefactor;
if ($opt_help || $opt_texthelp) {
include_help();
usage();
}
if ($opt_inihelp && !$opt_mode) {
# only show the overview of inihelp if no mode is specified
show_ini_help_overview();
}
if ($opt_Version) {
print "Version: $VERSION\n";
finish_program($ERRORS{'OK'});
}
if ($opt_warn && $opt_critical && $opt_value) {
# making it easier to test warning/critical values
# pass in -w SPEC -c SPEC and -v VALUE
my ($test_result,$neww,$newc)=test_limits($opt_warn,$opt_critical,$opt_value);
print "Overall Status Generated = $test_result ($neww,$newc)\n";
finish_program($test_result);
}
if (! $the_arguments{'_host'} && !$opt_inihelp) {
# they did not specify a hostname and they are not trying to get inihelp either
# we need the inihelp bit here so that we drop through to load the inifile and read the inihelp
print "No Hostname specified\n\n";
include_help();
short_usage();
}
# take a look at the username and if it is in the format USER@DOMAIN, change it to DOMAIN/USER
if ($opt_username=~/^(.*?)\@(.*?)$/) {
$opt_username="$2/$1";
$debug && print "Username specified as USER\@DOMAIN, altering to DOMAIN/USER\n";
}
# take a copy of the original arguments
%the_original_arguments=%the_arguments; # not really used at the moment
# object for holding the ini file content
my $wmi_ini=();
#==============================================================================
#===================================== MAIN ===================================
#==============================================================================
# most of the time if we are running within NAGIOS then this env variable gets set
# if it is not there we are probably running from the command line
my $running_within_nagios=$ENV{'NAGIOS_PLUGIN'} || '';
if (! -x $wmic_command) {
print "This plugin requires the linux implementation of wmic eg from zenoss.\nOnce wmic is installed, configure its location by setting the \$wmic_command variable in '$conf_file'.";
finish_program($ERRORS{'UNKNOWN'});
}
$use_pro_library && endtimer('Preparation');
# save the mode and submode
$the_arguments{'_mode'}=$opt_mode;
$the_arguments{'_submode'}=$opt_submode;
if ($force_ini_open) {
$wmi_ini=open_ini_file($wmi_ini);
}
# now run the appropriate sub for the check
if (defined($mode_list{$opt_mode})) {
# have to set a reference to the subroutine since strict ref is set
my $subref=\&$opt_mode;
&$subref('');
} else {
if ($wmi_ini_file || $wmi_ini_dir || $force_ini_open) {
# maybe the mode is defined in the ini file
# read the ini file and check
$use_pro_library && starttimer('Read INI Files');
$wmi_ini=open_ini_file($wmi_ini);
my $ini_section='';
if (defined($wmi_ini)) {
# there are 2 ways a section in the ini file is matched
# 1) [MODE] - $opt_mode matches the whole section name
# 2) [MODE SUBMODE] = $opt_mode is a Config::IniFiles Group and $opt_submode is a MemberName
# first see if there is a section named $opt_mode
if ($wmi_ini->SectionExists($opt_mode)) {
$debug && print "Found Section $opt_mode\n";
$ini_section=$opt_mode;
} else {
# now check for a group and a member
# load the ini file groups into an array - a group is a mode
my @ini_modes=$wmi_ini->Groups();
# see if we have found the mode
# $debug && print "INI FILE MODES " . Dumper(\@ini_modes);
my @found_modes=grep(/^$opt_mode$/,@ini_modes);
if ($#found_modes==0) {
$debug && print "Found Group $opt_mode\n";
# now use $opt_submode to match a membername
my @group_members=$wmi_ini->GroupMembers($opt_mode);
$debug && print "GROUP MEMBERS " . Dumper(\@group_members);
my @found_members=grep(/^$opt_mode +$opt_submode$/,@group_members); # could be any number of spaces between group and member
if ($#found_members==0) {
$debug && print "Found Member $opt_submode\n";
$ini_section=$found_members[0];
}
}
}
} else {
print "INIFILE and/or INIDIR are set but there were no ini file(s) or an error occurred trying to read them.\n";
}
$use_pro_library && endtimer('Read INI Files');
if ($ini_section) {
checkini($wmi_ini,$ini_section);
} elsif ($opt_inihelp) {
show_ini_help_overview();
} else {
print "A valid MODE and/or SUBMODE must be specified\n";
include_help();
short_usage();
}
}
print "A valid MODE and/or SUBMODE must be specified\n";
include_help();
short_usage();
}
# if we get to here we default to an OK exit
finish_program($ERRORS{'OK'});
#==============================================================================
#================================== FUNCTIONS =================================