����JFIF��x�x����'403WebShell
403Webshell
Server IP : 78.140.185.180  /  Your IP : 3.15.31.240
Web Server : LiteSpeed
System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64
User : builderbox ( 1072)
PHP Version : 7.3.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /usr/lib64/nagios/plugins/base/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/lib64/nagios/plugins/base/check_smart_custom
#!/usr/bin/env perl

use strict;
use warnings;

no if $] >= 5.018, warnings => 'experimental::smartmatch';

use Getopt::Long;
use Pod::Usage;

my $path    = '/usr/sbin/smartctl';
my %E_STATE = (
    'OK'       => 0,
    'WARNING'  => 1,
    'CRITICAL' => 2,
    'UNKNOWN'  => 3,
);
my (
    $type, $drives,  $sudo,     $verbose,
    $help, $device,  $devmath,  $temp,
    $raid, $warning, $critical, $exclude_failed,
);
GetOptions(
    'device=s'            => \$device,
    'devmath=s'           => \$devmath,
    't|type=s'            => \$type,
    'd|drives=s'          => \$drives,
    's|sudo'              => \$sudo,
    'p|path=s'            => \$path,
    'h|help'              => \$help,
    'r|raid=s'            => \$raid,
    'temp'                => \$temp,
    'w|warning=i'         => \$warning,
    'c|critical=i'        => \$critical,
    'ef|exclude-failed=s' => \$exclude_failed,
);

pod2usage( -verbose => 2 )
  if $help;
pod2usage(1)
  if !defined $raid
  and (!defined $type
    or !defined( $device or $devmath ) );

=head1 SYNOPSIS

$ check_smart [options] [--device device or --devmath math]

=head1 OPTIONS

=over 5

=item B<--device>

Set device. Example /dev/sda

=item B<--devmath>

Set device. Example "/dev/sg[1-9]" or "/dev/sg[1..9]"

=item B<--type> or B<-t>

Set device type. For additional info use smartctl --help

=item B<--drives> or B<-d>

Set drive numbers for check smart. Allow format: 1,2,3..7,24-27.

=item B<--path> or B<-p>

Set path to smartctl. Default /usr/sbin/smartctl

=item B<--sudo> or B<-s>

Use sudo for smartctl command or need run script as root

=item B<--temp>

print only status string and temperature data

=item B<--raid> or B<-r>

autodetected all disks connected to raid controller. Example --raid perc

Now support only perc raid controllers.

=item B<--warning> or B<-w>

Warning hard drive temp

=item B<--critical> or B<-c>

Critical hard drive temp

=item B<--exclude-failed> or B<-e>

Exclude failed smart attribute, value for attribute or value for all attributes

=item B<--help> or B<-h>

this help information

=back

=head1 DESCRIPTION

Examples for some raid-controllers:

Adaptec: check_smart -t sat --devmath "/dev/sg[1..27]"

MegaRaid: check_smart -t sat+megaraid --drives 6-9 --device /dev/sda

Perc:

  sas: check_smart_custom --device /dev/sda --type megaraid --drives 6,7

  ssd: check_smart_custom --device /dev/sda --type sat+megaraid --drives 1-5

  Autodetect all perc disks
    check_smart_custom --raid perc

    Required installed omreport util and started srvadmin-services.sh

Examples use --exclude-failed option:

  --exclude-failed="Airflow_Temperature_Cel=In_the_past,Reallocated_Event_Count=,=In_the_past"

  Airflow_Temperature_Cel=In_the_past  - skip failed value In_the_past for Airflow_Temperature_Cel
  Reallocated_Event_Count=             - skip any value for Reallocated_Event_Count
  =In_the_past                         - skip this value for any attributes

=cut

# validate args and prepare data
if ( $> and !$sudo ) {
    print "you are not root\n";
    exit $E_STATE{'UNKNOWN'};
}
if ( !-X $path ) {
    print "smartctl not found, please set path to executable smartctl file";
    exit $E_STATE{'UNKNOWN'};
}

# parse drives or devices
my %devices;
if ( $raid && $raid eq 'perc' ) {
    my $omreport = '/opt/dell/srvadmin/bin/omreport';
    if ( !-x $omreport ) {
        my $run = `which omreport`;
        $omreport = $run if !$?;
        if ( -x $omreport or $? ) {
            print "omreport not installed on this server\n";
            exit $E_STATE{'UNKNOWN'};
        }
    }
    require XML::LibXML;
    my ( $out, $xml );
    my $cmd_prefix = $sudo ? "sudo $omreport" : "$omreport";
    $out = `$cmd_prefix storage controller -fmt xml`;
    $xml = XML::LibXML->new( '1.0', 'UTF-8' );
    $xml = $xml->load_xml( string => $out );
    for my $controller (
        $xml->findnodes('/OMA/Controllers/DCStorageObject/ControllerNum') )
    {
        my $c = $controller->textContent;
        $xml = XML::LibXML->new( '1.0', 'UTF-8' );
        $out = `$cmd_prefix storage vdisk controller=$c -fmt xml`;
        $xml = $xml->load_xml( string => $out );
        for my $dev ( $xml->findnodes('/OMA/VirtualDisks/DCStorageObject') ) {
            next if !$dev->getElementsByTagName('DeviceID');
            my $devid   = $dev->getElementsByTagName('DeviceID');
            my $devname = $dev->getElementsByTagName('DeviceName');
            $xml = XML::LibXML->new( '1.0', 'UTF-8' );
            $out
              = `$cmd_prefix storage pdisk controller=$c vdisk=$devid -fmt xml`;
            $xml = $xml->load_xml( string => $out );
            for my $pd ( $xml->findnodes('/OMA/ArrayDisks/DCStorageObject') )
            {
                my $pdid    = $pd->getElementsByTagName('DeviceID');
                my $pdproto = $pd->getElementsByTagName('BusProtocol');

                # 7-sata, 8-sas
                my $pdtype
                  = "$pdproto" == 7 ? 'sat+megaraid'
                  : "$pdproto" == 8 ? 'megaraid'
                  :                   die 'disk type not defined';

                $devices{$pdid}{'type'}   = $pdtype;
                $devices{$pdid}{'device'} = $devname;
                $drives                   = 1;
            }
        }
    }
}
else {
    if ( defined $drives ) {
        my @prep_drives = split /,/, $drives;
        for my $drive (@prep_drives) {

            # push @devices, $drive if $drive =~ m/^\d+$/;
            # push @devices, $1 .. $5
            #   if $drive =~ m/^(\d+)\s?((\.\.)|(-))\s?(\d+)$/;
            if ( $drive =~ m/^\d+$/ ) {
                $devices{$drive}{'type'}   = $type;
                $devices{$drive}{'device'} = $device;
            }
            elsif ( $drive =~ m/^(\d+)\s?((\.\.)|(-))\s?(\d+)$/ ) {
                for ( $1 .. $5 ) {
                    $devices{$_}{'type'}   = $type;
                    $devices{$_}{'device'} = $device;
                }
            }
        }
    }
    elsif ( !defined $drives and $device ) {

        #push @devices, $device;
        my @devices = split( ',', $device );
        map { $devices{$_}{'device'} = $_; $devices{$_}{'type'} = $type }
          @devices;
    }
    elsif ($devmath) {
        my ( $dev_prefix, $dev_premath ) = ( $1, $2 )
          if $devmath =~ m/(\S+)(\[\S+\]|\(\S+\))/;
        if ( !$dev_premath ) {
            print "Device not matched";
            exit $E_STATE{'UNKNOWN'};
        }
        my ( $dev_start, $dev_end ) = ( $1, $5 )
          if $dev_premath =~ m/\(?\[?(\w+)\s?((\.\.)|(-))\s?(\w+)\]?\)?/;

        #push @devices, "$dev_prefix$_" for $dev_start .. $dev_end;
        $devices{"$dev_prefix$_"}{'type'} = $type for $dev_start .. $dev_end;
        $devices{"$dev_prefix$_"}{'device'} = $device
          for $dev_start .. $dev_end;
    }
}
if ( !%devices ) {
    print "Device not found\n";
    exit $E_STATE{'UNKNOWN'};
}

# parse exclude
my %exclude_failed;
if ($exclude_failed) {
    my @excludes = split /,/, $exclude_failed;
    for my $exclude (@excludes) {
        my ( $attr, $value ) = split /=/, $exclude;
        if ( $attr && $value ) {
            push @{ $exclude_failed{$attr} }, $value;
        }
        elsif ( $attr && !$value ) {
            push @{ $exclude_failed{attrs} }, $attr;
        }
        elsif ( !$attr && $value ) {
            push @{ $exclude_failed{values} }, $value;
        }
    }
}

# set default temp
$warning  = 60 unless $warning;
$critical = 70 unless $critical;

# work
my $exit_status       = 'OK';
my $exit_status_local = 'OK';
my $exit_status_temp  = 'OK';
my $status_string     = '';
my $perfdata_string   = '';

sub return_status {
    my $request_status = shift;
    if ( $request_status eq 'WARNING' ) {
        return if ( $exit_status or $exit_status_local ) eq 'CRITICAL';
    }
    if ( $request_status eq 'UNKNOWN' ) {
        return if ( $exit_status or $exit_status_local ) eq 'WARNING';
        return if ( $exit_status or $exit_status_local ) eq 'CRITICAL';
    }
    $exit_status       = $request_status;
    $exit_status_local = $request_status;
}

sub temp_status {
    my $temp_value = shift;
    my $temp_status
      = ( $temp_value >= $critical ) ? 'CRITICAL'
      : ( $temp_value >= $warning ) ? 'WARNING'
      : ( $temp_value <= 0 )        ? 'UNKNOWN'
      :                               'OK';
    return if $temp_status eq 'OK';

    if ( $temp_status eq 'WARNING' ) {
        return if ( $exit_status or $exit_status_local ) eq 'CRITICAL';
    }
    if ( $temp_status eq 'UNKNOWN' ) {
        return if ( $exit_status or $exit_status_local ) eq 'WARNING';
        return if ( $exit_status or $exit_status_local ) eq 'CRITICAL';
    }
    $exit_status_temp = $temp_status;
}

foreach my $dev ( sort keys %devices ) {
    my $type   = $devices{$dev}{'type'};
    my $device = $devices{$dev}{'device'};

    my @error_messages = qw//;
    $exit_status_local = 'OK';
    my ( $label,, $perfdata_label, $smart_overall_state, $smart_silent_check,
        $smart_detailed_state, );
    if ( defined $drives ) {
        $label                = "$device: $type,$dev - ";
        $perfdata_label       = "$device,$dev";
        $smart_overall_state  = "$path -d $type,$dev -H $device";
        $smart_silent_check   = "$path -d $type,$dev -q silent -A $device";
        $smart_detailed_state = "$path -d $type,$dev -A $device";
    }
    else {
        $label                = "$dev: $type - ";
        $perfdata_label       = "$dev";
        $smart_overall_state  = "$path -d $type -H $dev";
        $smart_silent_check   = "$path -d $type -q silent -A $dev";
        $smart_detailed_state = "$path -d $type -A $dev";
    }

    # overall status
    my @result = $sudo ? `sudo $smart_overall_state` : `$smart_overall_state`;
    my $output_mode  = "";
    my $found_status = 0;

    my $line_str_ata
      = 'SMART overall-health self-assessment test result: ';    # ATA
    my $ok_str_ata    = 'PASSED';                   # ATA SMART OK string
    my $line_str_scsi = 'SMART Health Status: ';    # SCSI
    my $ok_str_scsi = 'OK';    #SCSI and CCISS SMART OK string

    foreach my $line (@result) {
        if ( $line =~ /$line_str_scsi(.+)/ ) {
            $found_status = 1;
            $output_mode  = "scsi";
            if ( $1 ne $ok_str_scsi ) {
                push( @error_messages, "Health status: $1" );
                return_status('WARNING');
            }
        }
        if ( $line =~ /$line_str_ata(.+)/ ) {
            $found_status = 1;
            $output_mode  = "ata";
            if ( $1 ne $ok_str_ata ) {
                push( @error_messages, "Health status: $1" );
                return_status('WARNING');
            }
        }
    }
    unless ($found_status) {
        push( @error_messages, 'No health status line found' );
        return_status('UNKNOWN');
    }

    # silent SMART health check
    # https://www.smartmontools.org/browser/trunk/smartmontools/smartctl.8.in
    $sudo ? system("sudo $smart_silent_check") : system($smart_silent_check);
    my $return_code = $? >> 8;

    if ( $return_code & ( 1 << 0 ) ) {
        push( @error_messages, 'Command line did not parse.' );
        return_status('UNKNOWN');
    }
    if ( $return_code & ( 1 << 1 ) ) {
        push( @error_messages, 'Device open failed' );
        return_status('UNKNOWN');
    }
    if ( $return_code & ( 1 << 2 ) ) {
        push( @error_messages, 'Checksum error in a SMART data structure.' );
        return_status('WARNING');
    }
    if ( $return_code & ( 1 << 3 ) ) {
        push( @error_messages, 'Disk failing.' );
        return_status('WARNING');
    }
    if ( $return_code & ( 1 << 4 ) ) {
        push( @error_messages, 'We found prefail Attributes <= threshold.' );
        return_status('WARNING');
    }
    if ( $return_code & ( 1 << 5 ) ) {
        push( @error_messages, 'Smart ok but below threshold.' );
        return_status('WARNING');
    }
    if ( $return_code & ( 1 << 6 ) ) {
        push( @error_messages,
            'The device error log contains records of errors.' );
        return_status('WARNING');
    }
    if ( $return_code & ( 1 << 7 ) ) {
        push( @error_messages,
            'The device self-test log contains records of errors.' );
        return_status('WARNING');
    }
    if ( $return_code && !$exit_status_local ) {
        push( @error_messages, 'Unknown return code.' );
        return_status('UNKNOWN');
    }

    # detailed statistics
    @result = $sudo ? `sudo $smart_detailed_state` : `$smart_detailed_state`;

    if ( $output_mode =~ "ata" ) {
        my $reallocated_sector_ct;
        my %temp;

        foreach my $line (@result) {
            next
              unless $line
              =~ /^\s*(\d+)\s(\S+)\s+(?:\S+\s+)\s+(\d+)\s+(?:\S+\s+)\s+(\d+)\s+(?:\S+\s+){2}(\S+)\s+(\d+)/;
            my (
                $attribute_id, $attribute_name, $current_value,
                $thresh_value, $when_failed,    $raw_value
            ) = ( $1, $2, $3, $4, $5, $6 );

            # skip some attributes
            next
              if ( grep { $_ eq $attribute_name }
                qw(Power_On_Minutes Unknown_Attribute) );

       # skip Reallocated_Event_Count if Reallocated_Sector_Ct in normal state
       # 30 magic number
            $reallocated_sector_ct = $current_value - $thresh_value
              if ( $attribute_name eq 'Reallocated_Sector_Ct' );
            next
              if ( $attribute_name eq 'Reallocated_Event_Count'
                && $current_value <= $thresh_value
                && $reallocated_sector_ct > 30 );

            if ( $attribute_name
                =~ /Airflow_Temperature_Cel|Temperature_Celsius/
                && $attribute_id != 231 )
            {
                $temp{$perfdata_label}{$attribute_name}
                  = sprintf( "%d", $raw_value );
            }
            if ( $when_failed ne '-' ) {
                push( @error_messages,
                    "Attribute $attribute_name failed at $when_failed" );

                my $status
                  = $attribute_name ~~ @{ $exclude_failed{attrs} }  ? 'OK'
                  : $when_failed    ~~ @{ $exclude_failed{values} } ? 'OK'
                  : $when_failed ~~ @{ $exclude_failed{$attribute_name} }
                  ? 'OK'
                  : 'WARNING';
                return_status($status);
            }
            if ( $current_value <= $thresh_value ) {
                push( @error_messages,
                    "Attribute $attribute_name failed: value ($current_value) less thresh_value ($thresh_value)"
                );

                my $status
                  = $attribute_name ~~ @{ $exclude_failed{attrs} }  ? 'OK'
                  : 'WARNING';
                return_status($status);
            }
        }

        # build perfdata string
        foreach my $label ( keys %temp ) {
            $perfdata_string .=
              $temp{$label}{'Temperature_Celsius'}
              ? "\'$label"
              . '_temp\'='
              . $temp{$label}{'Temperature_Celsius'} . ';'
              . $warning . ';'
              . $critical . ';; '
              : $temp{$label}{'Airflow_Temperature_Cel'} ? "\'$label"
              . '_tempAir\'='
              . $temp{$label}{'Airflow_Temperature_Cel'} . ';'
              . $warning . ';'
              . $critical . ';; '
              : "\'$label" . '_temp\'=0;;;; ';
            temp_status(
                  $temp{$label}{'Temperature_Celsius'}
                ? $temp{$label}{'Temperature_Celsius'}
                : $temp{$label}{'Airflow_Temperature_Cel'}
                ? $temp{$label}{'Airflow_Temperature_Cel'}
                : 0
            );
        }

    }
    elsif ( $output_mode =~ "scsi" ) {
        foreach my $line (@result) {
            my (
                $current_temperature, $max_temperature,
                $current_start_stop,  $max_start_stop
            ) = qw//;
            if ( $line =~ /Current Drive Temperature:\s+(\d+)/ ) {
                $current_temperature = $1;
            }
            elsif ( $line =~ /Drive Trip Temperature:\s+(\d+)/ ) {
                $max_temperature = $1;
            }
            elsif ( $line =~ /Current start stop count:\s+(\d+)/ ) {
                $current_start_stop = $1;
            }
            elsif ( $line =~ /Recommended maximum start stop count:\s+(\d+)/ )
            {
                $max_start_stop = $1;
            }
            elsif ( $line =~ /Elements in grown defect list:\s+(\d+)/ ) {
                my $defectlist = $1;
                if ( $defectlist > 0 ) {
                    push( @error_messages,
                        "$defectlist Elements in grown defect list" );
                    return_status('OK');
                }
            }
            if ($current_temperature) {
                $perfdata_string
                  .= "\'$perfdata_label"
                  . '_temp\'='
                  . sprintf( "%d", $current_temperature ) . ';'
                  . $warning . ';'
                  . $critical . ';; ';
                temp_status($current_temperature);
            }
            if (   ( $current_temperature && $max_temperature )
                && ( $current_temperature >= $max_temperature ) )
            {
                push( @error_messages,
                    'Disk temperature is higher than maximum' );
                return_status('WARNING');
            }
            if (   ( $current_start_stop && $max_start_stop )
                && ( $current_start_stop >= $max_start_stop ) )
            {
                push( @error_messages,
                    'Disk start_stop is higher than maximum' );
                return_status('WARNING');
            }
        }
    }
    else {
        push( @error_messages, 'Device mode not math' );
        return_status('UNKNOWN');
    }

    if ( $exit_status_local ne 'OK' ) {
        $status_string .= $label . join( ', ', @error_messages ) . ".\n";
    }
    else {
        $status_string .= $label . "no SMART errors detected" . ".\n";
        $status_string .= $label . join( ', ', @error_messages ) . ".\n"
          if @error_messages;
    }
}

if ($temp) {
    print "$exit_status_temp";
    print "|$perfdata_string\n";
    exit $E_STATE{$exit_status_temp};
}
else {
    $exit_status
      = $E_STATE{$exit_status} > $E_STATE{$exit_status_temp}
      ? $exit_status
      : $exit_status_temp;
    print "$exit_status";
    print ": \n$status_string";
    print "|$perfdata_string\n";
    exit $E_STATE{$exit_status};
}

1;

Youez - 2016 - github.com/yon3zu
LinuXploit