Subversion Repositories sysadmin_scripts

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
174 rodolico 1
#! /usr/bin/env perl
2
 
3
# finds missing drives, telling you what bay they are in.
4
# Author: R. W. Rodolico
5
# Date: 2025-04-04
6
#
7
# run smartctl --scan to determine what drives are in the system, then
8
# again for each drive to get the serial number off of the drives.
9
# These end up in @active
10
#
11
# If there is stuff in STDIN, will assume that is the input and 
12
# search it for lines which do not match the list of serial numbers
13
# from @active.
14
#
15
# If STDIN is not active, looks for either of the files 'drive_bays', 
16
# then 'drives.tsv' in both /etc and /usr/local/etc. If one of those
17
# is found, will read it in, searching lines which do not match the list
18
# of serial numbers in @active
19
# 
20
# Any matching lines (those not found in @active) are printed to the
21
# screen
22
#
23
use strict;
24
use warnings;
25
 
26
use IO::Select; # this appears to be available in base Perl installs
27
 
28
sub loadFile {
29
   my ( $filename, $regex, @paths ) = @_;
30
   my @return;
31
   while ( my $path = shift @paths ) {
32
      if ( -f "$path\/$filename" ) {
33
         open DATA, "<$path\/$filename" or die "Could not open $path\/$filename: $!\n";
34
         @return = grep{ ! /$regex/ } <DATA>;
35
         chomp @return;
36
         return @return;
37
      }
38
   }
39
   return undef;
40
}
41
 
42
# get list of active drives from smartctl
43
my @drives = qx( smartctl --scan | cut -d' ' -f1 );
44
chomp @drives;
45
 
46
my @active;
47
# for each drive found, get its serial number. Note: using geom might be faster
48
foreach  my $drive ( @drives ) {
49
   push @active, qx( smartctl -a $drive | grep 'Serial Number:' | rev | cut -d' ' -f1 | rev );
50
}
51
chomp @active;
52
# build a regex that contains all of the serial numbers found
53
my $regex = '(' . join( '|', @active ) . ')';
54
my @lines; # a place to put our input
55
# turn off STDIN for blocking read
56
my $selector = IO::Select->new();
57
$selector->add(\*STDIN);
58
if ( $selector->can_read(0) ) { # This is true only if there is something on STDIN, ie a pipe
59
   @lines = grep{ ! /$regex/ } <>;
60
} 
61
# if STDIN didn't work, look for file drive_bays
62
@lines = &loadFile( 'drive_bays', $regex, '/etc', '/usr/local/etc' ) unless @lines;
63
# if we still didn't do it, try the file drives.tsv
64
@lines = &loadFile( 'drives.tsv', $regex, '/etc', '/usr/local/etc' ) unless @lines;
65
# OMG, nothing worked. Tell the user
66
push @lines, "Could not find STDIN, drive_bays or drives.tsv, no values" unless @lines;
67
 
68
chomp @lines;
69
print join("\n", @lines) . "\n";
70
1;