jdalrymple wrote:Interesting for sure...
Can you post the output of
Code: Select all
ll /usr/local/nagios/libexec | grep wmi
Hi, here's the code:
Code: Select all
[nagios@NagiosCentOS6 root]$ ll /usr/local/nagios/libexec | grep wmi
-rwxr-xr-x. 1 nagios nagios 2405 Feb 4 15:51 check_wmi_plus.conf
-rwxr-xr-x. 1 nagios nagios 64477 Feb 4 15:51 check_wmi_plus.ini
-rwxr-xr-x. 1 nagios nagios 237155 Feb 4 15:51 check_wmi_plus.pl
Sorry I'm still a newbie in this, please advise...
check_wmi_plus.conf
Code: Select all
[root@NagiosCentOS6 libexec]# cat check_wmi_plus.conf
# Check WMI Plus Config file
# This is read in-line into the perl program, so the syntax has to be just right.
# The settings in here override the default settings in the plugin code
# This file is only required if you want to change the default settings in the plugin
# It is provided in the release package as check_wmi_plus.conf.sample
# Rename it to check_wmi_plus.conf and/or set its location right at the top of the check_wmi_plus.pl script
# this file makes it easier to upgrade the plugin since you can keep your old settings in your own copy of this file
# ---------------------- FILE LOCATIONS -------------------------
# 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"; # CHANGE THIS IF NEEDED
# Set the full path where the plugin is installed
# You might not even use this variable if you have different locations for everything
# as a first guess, grab the directory that this conf file lives in
$base_dir="$conf_file_dir"; # CHANGE THIS IF NEEDED
# This is the full path location of the wmic command
# - standard value "$base_dir/wmic"
$wmic_command="/usr/bin/wmic"; # CHANGE THIS IF NEEDED
# you do not need to use this if you are using $wmi_ini_dir
# normally you would only use this if you had a single specific ini file you wanted to use
# 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 "$base_dir/check_wmi_plus.ini"
$wmi_ini_file='/usr/local/nagios/libexec/check_wmi_plus.ini'; # CHANGE THIS IF NEEDED
# 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
# you might like to use "$base_dir/wmic"
# - standard value "$base_dir/check_wmi_plus.d"
$wmi_ini_dir="/usr/local/nagios/libexec"; # CHANGE THIS IF NEEDED,
# set the location of temporary directory - used for keep state option
$tmp_dir='/tmp'; # CHANGE THIS IF NEEDED
# this script helps with making the manpage help. By default it is in the same directory as the plugin itself
$make_manpage_script="$base_dir/check_wmi_plus.makeman.sh"; # CHANGE THIS IF NEEDED
# this is the directory where the manpage is stored when created, defaults to the same directory as the ini files
$manpage_dir="$wmi_ini_dir"; # CHANGE THIS IF NEEDED
check_wmi_plus.ini
Code: Select all
Gives a lot of output!
Works for XP, Server 2008.
This is probably the best software lister (as it list software at a Product level) if it works for your OS version.
EOT
query = SELECT Caption,Version FROM Win32_Product
# create a list of the software features found
#createlist=_softwarelist|LINEDELIM|FIELDDELIM|UNIQUE|FIELD1,FIELD2,etc
createlist = _softwarelist| |,|0|Caption,Version
display = _ItemCount||Number of Items||~||. Items -
display = _softwarelist||~|~|~||
processallrows = 0
# this does the same thing
#predisplay=_ItemCount||Number of Instances||~||. Features -
#display=Caption|||~|||
#display=Version|||~|\n||
#----------------------------------------------------------
[info listsoftwarefeatures2008]
requires = 1.45
inihelp = <<EOT
Lists all the instances of software installed. Used during testing/debuging/helping others.
Gives a lot of output!
Works for XP, Server 2008.
This will add a lot of bits that listsoftware2008 will miss.
EOT
query = SELECT ProductName,Version FROM Win32_softwarefeature
# create a list of the software features found
#createlist=_softwarelist|LINEDELIM|FIELDDELIM|UNIQUE|FIELD1,FIELD2,etc
createlist = _softwarelist|\n|,|0|ProductName,Version
display = _ItemCount||Number of Instances||~||. Features -
display = _softwarelist||~|~|~||
processallrows = 0
#----------------------------------------------------------
[info listsoftware2003]
requires = 1.45
inihelp = <<EOT
Lists all the instances of software installed. Used during testing/debuging/helping others.
Gives a lot of output!
Works for XP, Server 2003 and Server 2008.
You are better off using listsoftware2008 if you can.
EOT
# for 2003 this is the closest we can get at the moment
query =SELECT Name,InstallDate FROM Win32_LogicalProgramGroupItem
# create a list of the software features found
#createlist=_softwarelist|LINEDELIM|FIELDDELIM|UNIQUE|FIELD1,FIELD2,etc
createlist = _softwarelist| |,|0|Name,InstallDate
display = _ItemCount||Number of Items||~||. Items -
display = _softwarelist||~|~|~||
processallrows = 0
#predisplay=_ItemCount||Number of Instances||~||. Items -
#display=Name|||~|||
#display=InstallDate|||~| ||
#----------------------------------------------------------
[info os]
requires = 1.451
inihelp = <<EOT
This check shows the Operating System Name and Service Pack version.
It also shows the Installation Date timestamp and age in days.
You can check warn/critical against the age of the Installation Date. The warn/critical specification should be in seconds.
Use the time multipliers to make this simpler. See the section "WARNING and CRITICAL Specification".
eg -w 2yr to test if the installation is older than 2 years.
EOT
query = Select * From Win32_OperatingSystem
customfield= _InstallSec,WMITimestampToAgeSec,InstallDate
# have to do this one after _InstallSec has been calculated
customfield = _InstallDays,SectoDay,_InstallSec,%.1f
test = _InstallSec
# the first display field is the standard one we use for the core plugin checks. It includes the status of the check and what triggered a warning/critical state (if any)
display =_DisplayMsg||~|~| - ||
display = Caption||OS is |~|||
display = CSDVersion||~|~|||
display = InstallDate||Installation Timestamp|| ||
display = _InstallDays||~|~|~|(| days old)
perf = _InstallDays|days|OS Installation Age
#----------------------------------------------------------
[info net]
# not sure if this is useful
requires = 1.451
inihelp = <<EOT
This check shows basic networking information (sometimes includes duplicate information).
Looks OK in Nagios with multi-line plugin output and not so good on the command line!
EOT
query = Select DNSDomain,DNSHostName,IPAddress,IPSubnet,MACAddress,Description from Win32_NetworkAdapterConfiguration where MACAddress Like "%:%:%:%:%:%"
#createlist=NEWFIELDNAME|LINEDELIM|FIELDDELIM|UNIQUE|FIELD1,FIELD2,etc
createlist= _NetInfo|\n|, |1|DNSHostName,DNSDomain,IPAddress,IPSubnet,MACAddress,Description
predisplay = _DisplayMsg||~|~||| - Network information shown is DNSHostName,DNSDomain,IPAddress,IPSubnet,MACAddress,Description - may include Null data (results shown on next line)\n
display = _NetInfo||~|~|~||
#display=DNSHostName||~|~|, ||
#display=DNSDomain||~|~|, ||
#display=IPAddress||~|~|, ||
#display=IPSubnet||~|~|, ||
#display=MACAddress||~|~|, ||
#display=Description||~|~|, ||\n
processallrows =0
#----------------------------------------------------------
[checkusers count]
requires = 1.451
inihelp = <<EOT
Check the count of users. You can specify the attributes of the users using ARG1.
ARG1 You must specify everything that follows the "where" clause in the WMI query. You can use any combination of valid WMI fields for the Win32_UserAccount class. Use ' ' to quote strings. Use --nodatamode and/or NODATAEXIT settings to control what happens if no matching users are found.
Valid WMI Fields for Server 2003 R2/2008 R2 AccountType, Caption, Description, Disabled, Domain, FullName, InstallDate, LocalAccount, Lockout, Name, PasswordChangeable, PasswordExpires, PasswordRequired, SID, SIDType, Status
ARG1 Example List all users : -a "status like '%'"
ARG1 Example Show users where the Status is OK : -a "status='OK'"
ARG1 Example Show usernames that contains the string "EX" : -a "name like '%EX%'"
ARG1 Example Show usernames that start with the string "Admin" : -a "name like 'Admin%'"
ARG1 Example Show usernames that end with the string "test" : -a "name like '%test'"
ARG1 Example Show users whose full name contains the String "Exchange" : -a "fullname like '%Exchange%'"
ARG1 Example Show users that belong to the Domain called "TEST": -a "Domain='TEST'"
ARG1 Example Show users where a password is not required : -a "PasswordRequired!='True'"
ARG1 Example Show users that belong to the Domain called "TEST" and that where a password is not required : -a "PasswordRequired!='True' AND Domain='TEST'"
ARG1 Example Show users that do not belong to the Domain called "TEST" : -a "Domain!='TEST'"
ARG1 Example Show users that have local accounts : -a "LocalAccount='True'"
EOT
# must use ARG1 to complete the Query otherwise it will fail
query = Select * from Win32_UserAccount Where {_arg1}
#createlist=NEWFIELDNAME|LINEDELIM|FIELDDELIM|UNIQUE|FIELD1,FIELD2,etc
createlist =_UserInfo|), |(|1|Name,FullName
test = _ItemCount
predisplay = _DisplayMsg||~|~| - ||
predisplay = _ItemCount||Number of Users|||| - User information shown on next line is: Name(FullName) \n
display = _UserInfo||~|~|~||)
perf = _ItemCount||Number of Users
processallrows = 0
#----------------------------------------------------------
[checkpower state]
requires = 1.451
inihelp = <<EOT
This check shows the state of one or more power supplies. Only appears to work on Server 2008. Not tested on physical hardware. It would be really helpful of someone using this on physical hardware can send me the output of this check adding the -d option to the command line.
ARG1 The power supply number to view stats for. Power supplies start at 0.
Use % for wildcards. Use only a single % to include stats for all power supplies.
EOT
query = SELECT * FROM Win32_PowerSupply where DeviceID LIKE "Power Supply {_arg1}"
namespace = root/cimv2/power
customfield = _InstallSec,WMITimestampToAgeSec,InstallDate
# this check could benefit from being able to specify strings as warn/crit criteria
test= ActiveInputVoltage
test = TotalOutputPower
test = TotalPowerOnHours
predisplay =_DisplayMsg||Overall Status - |~| - ||
# will show the status of each item returned
#FIELD|UNITS|DISPLAY|SEP|DELIM|START|END
display = DeviceID||~|~|~||
display = _DisplayMsg||~|~| - |(|)
display = ActiveInputVoltage
display = DetailedStatus
display = HealthState
display = IsACInput
display= IsSwitchingSupply
display = OperatingStatus
display = OperationalStatus
display =PrimaryStatus
display = Status
display = TotalOutputPower
display = TotalPowerOnHours
perf = ActiveInputVoltage
perf = TotalOutputPower
perf = TotalPowerOnHours
#----------------------------------------------------------
[checkad replication]
requires = 1.461
inihelp = <<EOT
Check the full replication of an Active Directory. Tested with AD v2003. Shows the number of failed replicas.
Use --nodatamode and/or NODATAEXIT settings to control what happens if no failed replicas are found.
Developed and tested by Patrick Fratczak. Typically run with -c 0, to go critical when any failed replicas are found.
EOT
namespace = Root/MicrosoftActiveDirectory
query = select * from MSAD_NamingContext WHERE IsFullReplica<>'True'
createlist = _ReplicaInfo|), |(|1|DistinguishedName,IsFullReplica
test= _ItemCount
predisplay = _DisplayMsg||~|~| - ||
predisplay = _ItemCount||Full Replication at False|||| - Replication Statuses : if False, info on next line is : DistinguishedName(IsFullReplica) \n
display =_ReplicaInfo||~|~|~||
perf = _ItemCount||Number of Failed Replicas
processallrows = 0
check_wmi_plus.pl
Code: Select all
@{$spec_result_list}=(); # ensure that this array starts empty
foreach my $spec (@{$spec_list}) {
my ($result,$perf,$display,$test_field)=parse_limits($spec,$test_value);
# store the performance data in a hash against the test field
# since this is for performance data we really only want to keep one of the warn/critical specs per test field
# since this is in a loop we will effectively just keep the last one that was defined
$$perf_specs_parsed{$test_field}=$perf;
# store all the information about what was triggered
push(@{$spec_result_list},$display);
if ($result>1) {
print "Critical specification ($spec) not defined correctly\n";
} elsif ($result==1) {
$count++;
}
}
return $count;
}
#-------------------------------------------------------------------------
sub test_limits {
my ($warn_spec_list,$critical_spec_list,$test_value,$warn_perf_specs_parsed,$critical_perf_specs_parsed,$warn_spec_result_list,$critical_spec_result_list)=@_;
# pass in
# an array containing the list of warn specifications
# an array containing the list of critical specifications
# a hash reference containing all the values we have that we might test against
# a hash reference where we return the parsed specifications (multiplier multiplied up) for performance data for warnings
# a hash reference where we return the parsed specifications (multiplier multiplied up) for performance data for criticals
# an array ref where we return some text telling us about what was triggered for warnings
# an array ref where we return some text telling us about what was triggered for criticals
# eg $test_value = {
# '_Free%' => '99.4',
# 'VolumeName' => 'Temp Disk 2',
# '_UsedSpace' => 13383680,
# '_FreeGB' => '1.98',
# and $warn_spec_list = [
# '1:',
# ':2',
# '3'
# most of this stuff we pass in just gets passed off to test_multiple_limits
# we call test_multiple_limits twice, once for warnings and once for criticals
$debug && print "Testing TEST VALUES " . Dumper($test_value);
$debug && print "WARNING SPECS: " . Dumper($warn_spec_list);
$debug && print "CRITICAL SPECS: " . Dumper($critical_spec_list);
# assume it is ok unless we find otherwise
my $test_result=$ERRORS{'OK'};
$debug && print "------------ Critical Check ------------\n";
my $critical_count=test_multiple_limits($critical_perf_specs_parsed,$test_value,$critical_spec_result_list,$critical_spec_list);
$debug && print "------------ Warning Check ------------\n";
my $warn_count=test_multiple_limits($warn_perf_specs_parsed,$test_value,$warn_spec_result_list,$warn_spec_list);
$debug && print "------------ End Check ------------\n";
# determine the result type, and load up some other values that can be used for display etc
$$test_value{'_StatusType'}='';
if (defined($$test_value{'_KeepStateSamplePeriod'})) {
# this will only ever get added to Row 0 of any query since that is the only place we set the SamplePeriod value
$$test_value{'_StatusType'}=" (Sample Period $$test_value{'_KeepStateSamplePeriod'} sec)";
}
if ($critical_count>0) {
$test_result=$ERRORS{'CRITICAL'};
$$test_value{'_TestResult'}=$ERRORS{'CRITICAL'};
$$test_value{'_StatusType'}="CRITICAL$$test_value{'_StatusType'}";
$$test_value{'_Triggers'}='[Triggered by ' . join(',',grep(/.+/,@{$critical_spec_result_list})) . ']';
$$test_value{'_DisplayMsg'}="$$test_value{'_StatusType'} - $$test_value{'_Triggers'}";
} elsif ($warn_count>0) {
$test_result=$ERRORS{'WARNING'};
$$test_value{'_TestResult'}=$ERRORS{'WARNING'};
$$test_value{'_StatusType'}="WARNING$$test_value{'_StatusType'}";
$$test_value{'_Triggers'}='[Triggered by ' . join(',',grep(/.+/,@{$warn_spec_result_list})) . ']';
$$test_value{'_DisplayMsg'}="$$test_value{'_StatusType'} - $$test_value{'_Triggers'}";
} else {
$test_result=$ERRORS{'OK'};
$$test_value{'_TestResult'}=$ERRORS{'OK'};
$$test_value{'_StatusType'}="OK$$test_value{'_StatusType'}";
$$test_value{'_Triggers'}='';
$$test_value{'_DisplayMsg'}="$$test_value{'_StatusType'}";
}
# only show this debug if there was any warn or crit specs
if ($#$critical_spec_list>=0 || $#$warn_spec_list>=0) {
$debug && print "Test Results:\nWarn Perf Specs=" . Dumper($warn_perf_specs_parsed) . "Warn Results=" . Dumper($warn_spec_result_list) . "Critical Perf Spec=" . Dumper($critical_perf_specs_parsed) . "Critical Results=" . Dumper($critical_spec_result_list);
}
$debug && print "Data Passed back from check: " . Dumper($test_value);
return $test_result;
}
#-------------------------------------------------------------------------
sub work_out_overall_exit_code {
my ($wmidata,$process_each_row,$query_index)=@_;
# only look at query #0
# but look at each row - look for the _TestResult value
my $max_status='OK';
my $max_result=$ERRORS{$max_status};
my @triggers=();
if ($process_each_row eq '0') {
# only take what is already in ROW 0
# we only need to set the max result variable so that this sub exits properly
$max_result=$$wmidata[$query_index][0]{'_TestResult'};
} else {
foreach my $row (@{$$wmidata[$query_index]}) {
$debug && print "Row Result $$row{'_TestResult'}\n";
if ($$row{'_TestResult'}>$max_result) {
$max_result=$$row{'_TestResult'};
}
# store any triggers for this row
push(@triggers,$$row{'_Triggers'});
}
if ($max_result==$ERRORS{'OK'}) {
$max_status='OK';
} elsif ($max_result==$ERRORS{'WARNING'}) {
$max_status='WARNING';
} elsif ($max_result==$ERRORS{'CRITICAL'}) {
$max_status='CRITICAL';
} else {
}
# get only the unique triggers and show them
my %seen=();
my @unique_triggers=grep{ ! $seen{$_} ++ } @triggers;
my $unique_trigger_list=join('',@unique_triggers);
my $display_msg="$max_status";
if (defined($$wmidata[$query_index][0]{'_KeepStateSamplePeriod'})) {
$display_msg="$display_msg (Sample Period $$wmidata[$query_index][0]{'_KeepStateSamplePeriod'} sec)";
}
if ($unique_trigger_list) {
# if there are some triggers then show them on the end of the display msg
$display_msg="$display_msg - $unique_trigger_list";
}
# overwrite the following fields in collected WMI data in query 0 row 0 only
# this assumes that everything else that wanted to use the orignal data has already done so
$$wmidata[$query_index][0]{'_TestResult'}=$max_result;
$$wmidata[$query_index][0]{'_StatusType'}=$max_status;
$$wmidata[$query_index][0]{'_Triggers'}=$unique_trigger_list;
$$wmidata[$query_index][0]{'_DisplayMsg'}=$display_msg;
$debug && print "Overall Result: $max_result ($max_status) with Triggers: $unique_trigger_list\n";
}
return $max_result;
}
##-------------------------------------------------------------------------
#sub initialise_perf_specs {
## initialise a performance spec hash to ensure that we do not see any "Use of uninitialized value" errors if it gets used
## pass in
## the hash to initialise
## the hash to copy from (but we make the values all '');
#my ($spec_hashref,$test_value)=@_;
#foreach my $key (keys %{$test_value}) {
# $$spec_hashref{$key}='';
#}
#
#}
#-------------------------------------------------------------------------
sub get_files_from_dir {
# return an array which contains all the files in $dir matching $pattern
# pass in
# $dir should be a full pathname
# $pattern a regex to match file names against
my ($dir,$pattern)=@_;
my @list;
opendir(DIR,"$dir");
foreach my $file (readdir DIR) {
# only take files
if ( -f "$dir/$file" && $file=~/$pattern/i) {
push(@list,$file);
}
}
closedir(DIR);
return @list;
}
#-------------------------------------------------------------------------
sub max {
# passed in a list of numbers
# determaxe the maximum one
my($max_so_far) = shift @_; # the first one is the smallest yet seen
foreach (@_) { # look at the remaining arguments
if ($_ > $max_so_far) { # could this one be smaller
$max_so_far = $_;
}
}
return $max_so_far;
}
#-------------------------------------------------------------------------
sub convert_WMI_timestamp_to_seconds {
# pass in a WMI Timestamp like 20100528105127.000000+600
use DateTime;
my ($wmi_timestamp)=@_;
my $sec='';
my $age_sec='';
my $current_dt='';
my $current_sec='';
$debug && print "Converting WMI Timestamp $wmi_timestamp to seconds = ";
if ($wmi_timestamp=~/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).(\d*)([+\-])+(\d*)$/) {
# now convert that fileage to seconds
my $dt = DateTime->new(
year => $1,
month => $2,
day => $3,
hour => $4,
minute => $5,
second => $6,
nanosecond => $7,
# we initially think that we don't care about the timezone
# its possible that this might be wrong if the systems are in different timezones?
# if we need to we have the WMI returned timezone as $8 . sprintf("%04d",$9) (it has to be padded with leading zeros)
time_zone => 'floating'
);
$sec=$dt->epoch();
$current_dt=DateTime->now( time_zone => 'local' )->set_time_zone('floating');
$current_sec=$current_dt->epoch();
$age_sec=$current_sec-$sec;
}
$debug && print "$sec. Now=$current_dt ($current_sec sec). Age=$age_sec sec\n";
return $sec,$age_sec;
}
#-------------------------------------------------------------------------
sub show_ini_section {
my ($ini,$ini_section)=@_;
# pass in
# ini object (already open)
# ini section name
my $output="-------------------------------------------------------------------\n";
foreach my $setting (sort $ini->Parameters($ini_section)) {
my $value=$ini->val($ini_section,$setting);
$output.=sprintf("%15s => %s\n",$setting,$value);
}
$output.="-------------------------------------------------------------------\n";
return $output;
}
#-------------------------------------------------------------------------
The files above at all at default. Is there anything that I should change?