#!/usr/bin/perl -- # # smartmontools + csv output # Thu,02 Jan,2020 # Copyright(C)2020 G-HAL (fenix.ne.jp) # # Reference: # "smartmontools + rrdtools" # https://blog.goo.ne.jp/nhh0/d/20060709 # Copyright(C)2006 getttyent # local @config_param; local $HOSTNAME; local $DISK; local $DEVICE; local $DB_DIR; local $MONITOR_ID; local $SMARTCTL; local $ATTR_FILE; local $DISKNAME; local @monitor_id; local @Attribute_name; local @Value; local @Worst; local @Thresh; local @Raw_value; if ( $#ARGV == 0 && -f $ARGV[0] ) { read_config( $ARGV[0] ); } else { @config_param[ 0 ] = [ @ARGV ]; } initialize(); argument( @{$config_param[0]} ); { for ( my $i = 0; $i <= $#config_param; $i ++ ) { initialize(); if ( @{$config_param[$i]} == () ) { } else { argument( @{$config_param[$i]} ); initialize2(); update(); } } } 0; ############################################################################## sub initialize { if ( $ENV{HOST} ne "" ) { $HOSTNAME = $ENV{HOST}; $HOSTNAME =~ s/\..*//g; } else { $HOSTNAME = "unknown"; } $DISK = "/dev/ad0"; $DEVICE = ""; $DB_DIR = "/var/db"; $MONITOR_ID = "5, 8, 9, 12, 194, 195, 201, 203"; $SMARTCTL = "/usr/local/sbin/smartctl"; $ATTR_FILE = ""; } sub initialize2 { $DISKNAME = $DISK; $DISKNAME =~ s/\/dev\///g; $DISKNAME =~ s/\//_/g; if ( $DEVICE ne "" ) { $DISKNAME .= "_${DEVICE}"; $DISKNAME =~ s/,/_/g; } if ( $ATTR_FILE eq "" ) { $ATTR_FILE="${DB_DIR}/smart.${HOSTNAME}.${DISKNAME}.log"; } $MONITOR_ID =~ s/ //g; @monitor_id = split( /,/, $MONITOR_ID ); } sub read_config { my $config_file = $_[0]; my @arg; my $i = 0; open( FH, "<$config_file" ) || die "$config_file"; while ( ) { chop; s/\r$//; next if /^#/; @arg = split( /[ \t]+/ ); $config_param[$i ++] = [ @arg ]; } close FH; } sub argument { my @arg = @_; for( my $i = 0; $i <= $#arg ; $i ++ ) { $arg[$i] =~ s/^['"]//; $arg[$i] =~ s/['"]$//; } while ( $_ = $arg[0], /^-/ ) { shift @arg; last if /^--$/; if( /^-he.*/ ) { help(); exit; } elsif( /^-h$/ ) { help(); exit; } elsif( /^-db.*/ ) { $DB_DIR = $arg[0]; shift @arg; } elsif( /^-de.*/ ) { $DEVICE = $arg[0]; shift @arg; } elsif( /^-di.*/ ) { $DISK = $arg[0]; shift @arg; } elsif( /^-f.*/ ) { $ATTR_FILE = $arg[0]; shift @arg; } elsif( /^-ho.*/ ) { $HOSTNAME = $arg[0]; shift @arg; } elsif( /^-mo.*/ ) { $MONITOR_ID = $arg[0]; shift @arg; } elsif( /^-sm.*/ ) { $SMARTCTL = $arg[0]; shift @arg; } elsif( /^-/ ) { print "ERROR: unknown argument: $_\n"; die; } } # error check if ( ! -x ${SMARTCTL} ) { print "ERROR: smartctl not found: ${SMARTCTL}\n"; exit; } if ( ! -e ${DISK} ) { print "ERROR: disk not found: ${DISK}\n"; exit; } } sub help { print <> ${CSV_file}" ) || die "Error: ${CSV_file}\n"; print( OUT $output_data ); close( OUT ); } } } sub run_smartctl { my $log_file = $_[0]; my $found = 0; my $write_file = 0; my $cmd; @Attribute_name = (); @Value = (); @Worst = (); @Thresh = (); @Raw_value = (); $cmd = "${SMARTCTL} -A ${DISK}"; if ( $DEVICE ne "" ) { $cmd = "${SMARTCTL} -A --device ${DEVICE} ${DISK}"; } open( IN, "${cmd} |" ) || die "Error: ${cmd}\n"; if ( ! -f ${log_file} ) { open( OUT, "> ${log_file}" ) || die "Error: ${log_file}\n"; $write_file = 1; } while( ) { print OUT $_; chop; if ( /^SMART Attributes Data Structure/ ) { $found = 1; next; } if ( /^ID#/ ) { $found = 2; next; } next if ( $found != 2 ); if ( /^$/ ) { last; } s/^ *//; my @data = split( / */ ); my $id = $data[0]; $Attribute_name[ $id ] = $data[1]; $Value[ $id ] = $data[3]; $Worst[ $id ] = $data[4]; $Thresh[ $id ] = $data[5]; if ( $data[1] =~ /Power_On_Minutes/ ) { if ( $data[9] =~ /[0-9]*h\+[0-9]*m/ ) { $data[9] =~ s/\+//; ($hour,$min) = split( /[hm]/, $data[9] ); $data[9] = $hour * 60 + $min; } } $Raw_value[ $id ] = $data[9]; } close( IN ); if ( $write_file != 0 ) { close( OUT ); } if ( $found == 0 ) { die "Error: cannot read smartctl output\n"; } } # [ End of File ]