├── README.md └── zpadmin.pl /README.md: -------------------------------------------------------------------------------- 1 | zpadmin 2 | ======= 3 | 4 | ZFS pool scrubber and monitor script 5 | 6 | 7 | Use this script with argument --scrub to invoke scrubbing of your ZFS pools, and without any arguments to inspect the status of the pools. 8 | -------------------------------------------------------------------------------- /zpadmin.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3 | # Author : Paul.Errington@northtyneside.gov.uk 4 | # Date : 10 Sept 2007 5 | # Description : manage your zpools! 6 | # 7 | # # ZPOOL MONITOR -> 8 | # 0,30 * * * * /pathtobin/zpadmin.pl 9 | # 10 | # # ZPOOL WEEKLY SCRUB -> 11 | # 0 1 * * 1 /pathtobin/zpadmin.pl -scrub 12 | # 13 | #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 14 | 15 | use strict; 16 | use Time::localtime; 17 | use Getopt::Long; 18 | use Sys::Hostname; 19 | 20 | my $log_path="/var/log/zpool_adm.log"; 21 | my $hostname = hostname; 22 | my $mailfrom = "zfs\@$hostname"; 23 | my $mailto = "root"; 24 | 25 | sub log_event { 26 | my $event = shift; 27 | my @abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); 28 | 29 | open(EVENT_ZLOG, ">> $log_path") or die "can't open $log_path: $!"; 30 | flock(EVENT_ZLOG, 2) or die "can't flock $log_path: $!"; 31 | 32 | printf EVENT_ZLOG "%s %d %02d:%02d:%02d %s: %s\n", @abbr[localtime->mon()], 33 | localtime->mday(), 34 | localtime->hour(), 35 | localtime->min(), 36 | localtime->sec(), 37 | $hostname, 38 | $event; 39 | 40 | close(EVENT_ZLOG) or die "can't close $log_path: $!"; 41 | } 42 | 43 | sub get_zp_list { 44 | # zpool list -H -o name 45 | my $pool_names = `zpool list -H -o name`; 46 | if ($pool_names eq "no pools available\n") { 47 | return $pool_names; 48 | } 49 | my @pool_names = split("\n",$pool_names); 50 | return @pool_names; 51 | } 52 | 53 | sub get_zp_health { 54 | # zpool list -H -o health $pool_name 55 | my $pool_name = shift; 56 | my $result = `zpool list -H -o health $pool_name`; 57 | chomp $result; 58 | return $result; 59 | } 60 | 61 | sub get_zp_status { 62 | # zpool status -v $pool_name 63 | my $pool_name = shift; 64 | my $result = `zpool status -v $pool_name`; 65 | chomp $result; 66 | return $result; 67 | } 68 | 69 | sub get_zp_scrub { 70 | } 71 | 72 | sub get_zp_errors { 73 | } 74 | 75 | sub scrub_pool { 76 | # zpool scrub $pool_name 77 | my $pool_name = shift; 78 | system("zpool scrub $pool_name") == 0 or 79 | die "zpool scrub $pool_name failed: $?"; 80 | my $result = $? >> 8; 81 | 82 | if ($? == -1) { 83 | print "failed to execute: $!\n"; 84 | log_event("[ERROR] scrub_pool: failed to execute: $!"); 85 | return $result; 86 | } elsif ($? & 127) { 87 | printf "child died with signal %d, %s coredump\n", 88 | ($? & 127), ($? & 128) ? 'with' : 'without'; 89 | log_event("[ERROR] scrub_pool: child died and coredumped"); 90 | return $result; 91 | } else { 92 | #printf "child exited with value %d\n", $? >> 8; 93 | return $result; 94 | } 95 | } 96 | 97 | sub mailme { 98 | my $pool_name = shift; 99 | my $pool_status = shift; 100 | my ($message) = @_; 101 | 102 | #my $sendmail = "/bin/cat >/tmp/mailtest"; 103 | #my $reply_to = "Reply-to: $from"; 104 | 105 | my $sendmail = "/usr/sbin/sendmail -t"; 106 | open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!"; 107 | print SENDMAIL "From: $mailfrom\n"; 108 | print SENDMAIL "To: $mailto\n"; 109 | print SENDMAIL "Subject: Zpool '$pool_name' on $hostname is $pool_status\n"; 110 | print SENDMAIL "Content-type: text/plain\n\n"; 111 | print SENDMAIL $message . "\n"; 112 | close(SENDMAIL) 113 | } 114 | 115 | #START PROCESS>>> 116 | if ( ! -f "/sbin/zpool") { 117 | print "ZFS not installed on this system.\n"; 118 | exit 1; 119 | } 120 | 121 | zpcheck(); 122 | 123 | sub zpcheck { 124 | my ($scrub, $check, $verbose); 125 | GetOptions("scrub" => \$scrub, "check" => \$check, "verbose" => \$verbose); 126 | my @zpools = get_zp_list(); 127 | 128 | if ($zpools[0] eq "no pools available\n") { 129 | print "no pools defined!\n" if(defined($verbose)); 130 | return 0; 131 | } 132 | 133 | foreach my $pool (@zpools) { 134 | my $health = get_zp_health($pool); 135 | if ( $health eq "ONLINE" ) { 136 | print "zpool $pool status is $health, ok.\n" if(defined ($verbose)); 137 | #log_event("[STATUS] zpool $pool status is $health, ok."); 138 | if(defined($scrub)) { 139 | print "Starting scrub of pool $pool..." if(defined ($verbose)); 140 | if (scrub_pool($pool)) { 141 | print "error initiating scrub.\n" if(defined ($verbose)); 142 | log_event("[ERROR] Could not start scrub on zpool $pool."); 143 | } else { 144 | log_event("[VERIFY] Scrub started on zpool $pool."); 145 | print "running.\n" if(defined($verbose)); 146 | } 147 | } 148 | } else { 149 | $health = "unknown" if (!$health); 150 | print "Problem with zpool $pool detected, status is $health\n" if(defined($verbose)); 151 | log_event("[ERROR] Problem with zpool $pool detected, status is $health."); 152 | mailme($pool, $health, get_zp_status($pool)); 153 | } 154 | } 155 | } 156 | 157 | 158 | ############################################################################## 159 | ### This script is submitted to BigAdmin by a user of the BigAdmin community. 160 | ### Sun Microsystems, Inc. is not responsible for the 161 | ### contents or the code enclosed. 162 | ### 163 | ### 164 | ### Copyright 2008 Sun Microsystems, Inc. ALL RIGHTS RESERVED 165 | ### Use of this software is authorized pursuant to the 166 | ### terms of the license found at 167 | ### http://www.sun.com/bigadmin/common/berkeley_license.html 168 | ############################################################################## 169 | --------------------------------------------------------------------------------