Subversion Repositories sysadmin_scripts

Rev

Blame | Last modification | View Log | Download | RSS feed

#! /usr/bin/env perl

# finds missing drives, telling you what bay they are in.
# Author: R. W. Rodolico
# Date: 2025-04-04
#
# run smartctl --scan to determine what drives are in the system, then
# again for each drive to get the serial number off of the drives.
# These end up in @active
#
# If there is stuff in STDIN, will assume that is the input and 
# search it for lines which do not match the list of serial numbers
# from @active.
#
# If STDIN is not active, looks for either of the files 'drive_bays', 
# then 'drives.tsv' in both /etc and /usr/local/etc. If one of those
# is found, will read it in, searching lines which do not match the list
# of serial numbers in @active
# 
# Any matching lines (those not found in @active) are printed to the
# screen
#
use strict;
use warnings;

use IO::Select; # this appears to be available in base Perl installs

sub loadFile {
   my ( $filename, $regex, @paths ) = @_;
   my @return;
   while ( my $path = shift @paths ) {
      if ( -f "$path\/$filename" ) {
         open DATA, "<$path\/$filename" or die "Could not open $path\/$filename: $!\n";
         @return = grep{ ! /$regex/ } <DATA>;
         chomp @return;
         return @return;
      }
   }
   return undef;
}

# get list of active drives from smartctl
my @drives = qx( smartctl --scan | cut -d' ' -f1 );
chomp @drives;

my @active;
# for each drive found, get its serial number. Note: using geom might be faster
foreach  my $drive ( @drives ) {
   push @active, qx( smartctl -a $drive | grep 'Serial Number:' | rev | cut -d' ' -f1 | rev );
}
chomp @active;
# build a regex that contains all of the serial numbers found
my $regex = '(' . join( '|', @active ) . ')';
my @lines; # a place to put our input
# turn off STDIN for blocking read
my $selector = IO::Select->new();
$selector->add(\*STDIN);
if ( $selector->can_read(0) ) { # This is true only if there is something on STDIN, ie a pipe
   @lines = grep{ ! /$regex/ } <>;
} 
# if STDIN didn't work, look for file drive_bays
@lines = &loadFile( 'drive_bays', $regex, '/etc', '/usr/local/etc' ) unless @lines;
# if we still didn't do it, try the file drives.tsv
@lines = &loadFile( 'drives.tsv', $regex, '/etc', '/usr/local/etc' ) unless @lines;
# OMG, nothing worked. Tell the user
push @lines, "Could not find STDIN, drive_bays or drives.tsv, no values" unless @lines;

chomp @lines;
print join("\n", @lines) . "\n";
1;