squeegy/wipe.pl

166 lines
5.6 KiB
Perl
Raw Normal View History

2019-06-12 09:22:28 -06:00
#!/usr/bin/perl -w
use strict;
use warnings;
use Digest::MD5 "md5_base64";
use POSIX;
# create our random data and store it in ram so we can keep reusing it
2019-06-12 09:22:28 -06:00
open (my $drand, "<", "/dev/urandom");
my $clobber;
read($drand, $clobber, 10240000);
close($drand);
my $clobsum = md5_base64($clobber);
# define some colors for conviniance
2019-06-12 09:22:28 -06:00
my %color = (
"red" => "\e[0;31m",
"green" => "\e[0;32m",
"reset" => "\e[0m"
);
my @failed = ();
my @good = ();
2019-06-12 09:22:28 -06:00
my $term = POSIX::Termios->new;
# for providing a waiting prompt
2019-06-12 09:22:28 -06:00
sub anykey {
print shift;
my $key;
my $oldflag = $term->getlflag;
$term->setlflag(ICANON);
system "stty", '-icanon', 'eol', "\001"; #ISNT POSIX compliant
$key = getc(STDIN);
$term->setlflag($oldflag);
system "stty", 'icanon', 'eol', "^@";
return $key
}
# to handle errors without using die
2019-06-12 09:22:28 -06:00
sub warning {
print shift;
return 0;
}
# home made uniqu function
sub uniq {
my %seen;
return grep { !$seen{$_}++} @_;
}
# To get the list of devices we will be cleaning
2019-06-12 09:22:28 -06:00
sub getdisks {
my $devices = `find /dev/sd*`;
my %listhash = ();
foreach(split("\n",$devices)) {
my $devicepath = $_;
my $serial = `udevadm info --query=all --name=$_ | grep SERIAL_SHORT | sed -e 's/^.*=//'`;
chomp( $serial );
if ( $serial ) {
print $devicepath."\t".$serial."\n";
$listhash{$_}{"path"} = $devicepath;
$listhash{$_}{"serial"} = $serial;
} else { next; }
}
return %listhash;
}
# To while a drive
2019-06-12 09:22:28 -06:00
sub wipethemdrives {
my $diskid = shift;
my $disks = shift;
print $disks->{$diskid}{"path"}." - Serial:".$disks->{$diskid}{"serial"}." is being wiped...\n";
open(my $diskw, ">", $disks->{$diskid}{"path"}) or return warning("could not open ".$disks->{$diskid}{"path"});
2019-06-12 09:22:28 -06:00
# open(my $diskw, ">", "./test") or warning("could not open "."./test");
print $diskw $clobber;
close($diskw);
system("sync");
print "Wipe attempt complete, checking...\n";
open(my $diskr, "<", $disks->{$diskid}{"path"}) or return warning("could not open ".$disks->{$diskid}{"path"});
2019-06-12 09:22:28 -06:00
# open(my $diskr, "<", "./test") or warning("could not open "."./test");
my $diskdata;
read($diskr, $diskdata, 10240000);
my $disksum = md5_base64($diskdata);
close($diskr);
print "Disk Checksum: ".$disksum."\n";
if ($disksum eq $clobsum) {
print "Checksum ".$color{"green"}."PASSED!!!".$color{"reset"}."\n";
print $disks->{$diskid}{"path"}." is clean.\n";
return 1;
} else {
print "Wipe Checksum: ".$clobsum."\n";
print "Checksum ".$color{"red"}."FAILED!!!".$color{"reset"}."\n";
print $disks->{$diskid}{"path"}." did not take, it could be bad.\n";
return 0;
}
}
# to test a drive
2019-06-12 09:22:28 -06:00
sub smartcheck {
# Do our smart disk thing...
my $diskid = shift;
my $disks = shift;
print "Checking S.M.A.R.T. variables...\n";
print 'smartctl '.$disks->{$diskid}{"path"}.' -A -f hex,id | grep "^0x"'."\n";
(my $smartcommand = `smartctl $disks->{$diskid}{"path"} -A -f hex,id | grep "^0x"`) or (print $!."\ncould not check smart data, skipping\n" and return 1);
for (split("\n",$smartcommand)) {
my @smartdata = split(/\s+/,$_);
$disks->{$diskid}{"smart"}{$smartdata[0]}{"id"} = $smartdata[0];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"name"} = $smartdata[1];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"flag"} = $smartdata[2];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"value"} = $smartdata[3];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"worst"} = $smartdata[4];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"thresh"} = $smartdata[5];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"type"} = $smartdata[6];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"updated"} = $smartdata[7];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"when_failed"} = $smartdata[8];
$disks->{$diskid}{"smart"}{$smartdata[0]}{"raw_value"} = $smartdata[9];
}
close( $smartcommand );
for my $smartentry (keys %{$disks->{$diskid}{"smart"}}) {
if ($disks->{$diskid}{"smart"}{$smartentry}{"id"} =~ /0x05|0x07|0xc4|0xc5|0xc6|0xc7/) {
print $disks->{$diskid}{"smart"}{$smartentry}{"id"}." ".$disks->{$diskid}{"smart"}{$smartentry}{"name"}."\t".$disks->{$diskid}{"smart"}{$smartentry}{"raw_value"}."\t";
if ($disks->{$diskid}{"smart"}{$smartentry}{"raw_value"} =~ /0|0\/0/) {
print $color{"green"}."Passed".$color{"reset"}."\n";
}else { print $color{"red"}."Failed".$color{"reset"}."\n"; return 0}
}
}
return 1;
}
# main loop
2019-06-12 09:22:28 -06:00
while () {
my %disks = getdisks();
my $batchcount = keys %disks;
print "About to wipe ".$batchcount." drives with the following serial numbers:\n";
foreach my $diskid (keys %disks) {
print $disks{$diskid}{"serial"}."\n";
}
anykey("Hit any key to continue...\n");
foreach my $diskid (keys %disks) {
print "\e[J";
print "="x33;
printf '[ %-10s ]', $diskid;
print "="x33;
print "\n";
$disks{$diskid}{"wipe"} = wipethemdrives($diskid,\%disks);
if ($disks{$diskid}{"wipe"} == 1) {
$disks{$diskid}{"smartpass"} = smartcheck($diskid,\%disks);
if ($disks{$diskid}{"smartpass"} == 1) {
print "Smart looks good.\n";
push(@good, $disks{$diskid}{"serial"});
2019-06-12 09:22:28 -06:00
} else { push(@failed, $disks{$diskid}{"serial"}); }
} else { push(@failed, $disks{$diskid}{"serial"}); }
print "="x80;
print "\n"x5;
}
print "These drives were successfully wiped and passed SMART, they may be put back into production:\n";
print join("\n",sort {$a cmp $b} uniq(@good));
anykey("Hit any key to see the list of failed drives. Please also note any drives that do not appear\non ether list. Those should be tried again (if they do not show up after three times assume falure).");
print "The folowing drives are bad, RMA or shred:\n";
print join("\n",sort {$a cmp $b} uniq(@failed));
2019-06-12 09:22:28 -06:00
@failed = ();
@good = ();
2019-06-12 09:22:28 -06:00
print "\nWipe complete, insert more drives.\n";
anykey("Hit any key when ready to continue...\n");
}