#!/usr/local/bin/perl #boot-check # only prints a list of the boot devices # and checks if they are configured correctly # if given an argument that contains a q -- the run in "quiet mode" # quiet mode" only prints output if there is an error -- useful as a cronjob # read_format # builds @devices from output of format command # read_vfstab # builds/updates %used with data from vfstab file -- $used{cXtXdXsX} = "/" # run_metadb # builds/updates %used with data from metadb command -- $used{cXtXdXsX} = "metadb" # run_metastat # builds/updates %used with data from metastat command - $used{cXtXdXsX} = "submirror..." # find_devices # builds %mappings from contents of /dev/rdsk -- $mappings{cXtXdXsX} = "/sbus..." # find_entry # builds %aliases based on output of prtconf command -- $aliases{pri-boot} = "/sbus...".\t."cXtXdXsX" # find_boot_devices # compares entries in %aliases with %used $debug = 0; $verbose = 0; if ($ARGV[0] =~ m#q#i) { $quietmode = 1; } $user = (getpwuid($<))[0]; #print "USER: $user\n"; my (@devices,%mappings,%used); if ($#ARGV != -1) { $bootflag = 1; } # ## find the installed drives # $format = "/tmp/format.output"; read_format($format); foreach $dev (@devices) { $slice = $dev."s0"; $used{$slice} = ""; } read_vfstab(); run_metadb(); run_metastat(); #find relationship between /dev/rdsk/c0t0d0s0 and ../../devices/pci@1f,4000/scsi@3/sd@0,0:a,raw find_devices(); $prtconf = "/tmp/prtconf.output"; if ((-f $prtconf) && ($user ne "root")) { if (! $quietmode) { print "using existing $prtconf\n"; } } else { system("/usr/sbin/prtconf -vp > $prtconf"); } foreach $dev (sort keys %mappings) { $flag = 0; # aliases only apply to silce 0 (zero) if ($dev =~ m#s0#) { find_entry($mappings{$dev}); if ($flag == 0) { if ($verbose) { printf "%18s\t%-65s\t%s\n"," ",$mappings{$dev},$dev; } } } } find_boot_devices(); if (! $quietmode) { foreach $dev (sort keys %used) { print "$dev\t$mappings{$dev}\t$used{$dev}\n"; } } ################################################################################ sub find_devices ################################################################################ # builds %mappings from contents of /dev/rdsk { # print "find_devices\n"; $dir = "/dev/rdsk"; # ## read a directory $dir ( ignoring . and .. ) # opendir(DIR,"$dir") || die "opendir $dir failed"; @files = grep(!/^\.\.?$/,readdir(DIR)); # @files = grep(m#s0#,readdir(DIR)); closedir(DIR); foreach $file (@files) { $file = $dir."/".$file; $link = readlink($file); if ($verbose) { print " $file maps to $link\n"; } ($front,$string) = split(m#devices#,$link); if ($string =~ m#(.*?)(,[0-9]+):#) { $string2 = $1.$2; # ($string2,$j) = split(m#(,[0-9]:)#,$string); # $string2 = $string2.$1; } # for 3000's we need to leave "sd" as "sd" # /dev/rdsk/c0t0d0s0 -> ../../devices/sbus@3,0/SUNW,fas@3,8800000/sd@0,0:a,raw # # for 3500's we need to change "sdisk" to "ssd" # /dev/rdsk/c0t0d0s0 -> ../../devices/sbus@2,0/SUNW,socal@d,10000/sf@0,0/ssd@w21000020379cebf9,0:a,raw # if (($string2 =~ m#^/sbus#) || ($string2 =~ m#socal#)) # { # $string2 =~ s#sdisk#ssd#; # } # for 450's we need to change "sd" to "disk" # /dev/rdsk/c0t0d0s0 -> ../../devices/pci@1f,4000/scsi@3/sd@0,0:a,raw if ($string2 =~ m#^/pci#) { $string2 =~ s#sd#disk#; } # for Ultra 10's we need to change "dad" to "disk" # /dev/rdsk/c0t0d0s0 -> ../../devices/pci@1f,0/pci@1,1/ide@3/dad@0,0:a,raw if ($string2 =~ m#^/pci#) { $string2 =~ s#dad#disk#; } if ($debug) { print " look for $string2 in prtconf output\n"; } $dev = $file; $dev =~ s#/dev/rdsk/##; # $mappings{$file} = $string2; if (! defined($mappings{$dev})) { $mappings{$dev} = $string2; } } } ################################################################################ sub find_entry ################################################################################ # builds %aliases based on output of prtconf command { if ($verbose) { print "find_entry\n"; } ($string2) = @_; if ($string2 eq "") { # print "disk not found\n"; # exit(); } if ($string2 =~ m#fibre-channel#) { # print " non-local fibre-channel device $file\n"; } else { open(IN,"$prtconf"); { while ($line = ) { chomp($line); if ($line =~ m#$string2#) { if ($debug) { print "$line\n"; } $line =~ s#^\s+##; ($alias,$device) = split(m#:#,$line); $device =~ s#^\s+##; $device =~ s#'##g; $short_dev = $dev; $short_dev =~ s#/dev/rdsk/##; if ($verbose) { printf "%18s\t%-65s\t%s\n",$alias,$device,$short_dev; } $flag = 1; $aliases{$alias} = $device."\t".$short_dev; } else { #if ($line =~ m#socal#) #{ # $line =~ s#^\s+##; # ($alias,$device) = split(m#:#,$line); # $device =~ s#^\s+##; # $device =~ s#'##g; ## printf "%15s\t%s\t%s\n",$alias,$device,$dev; #printf "%15s\t%s\n%15s\t%s\n",$alias, $device, "=>", $string2; #} } } } close(IN); } } ################################################################################ sub find_boot_devices ################################################################################ # compares entries in %aliases with %used { # print "find_boot_devices\n"; $eeprom = "/tmp/eeprom.output"; if ((-f $eeprom) && ($user ne "root")) { if (! $quietmode) { print "using existing $eeprom\n"; } } else { system("/usr/sbin/eeprom > $eeprom"); } open(IN,"$eeprom"); while ($line = ) { chomp($line); if ($line =~ m#boot-device#) { if (! $quietmode) { print "$line\n"; } if (($line =~ m#pri#) && ($line =~ m#mir#) && ($line =~ m#bck#)) { } else { print "ERROR: boot-device does not include 'pri-bootdisk' 'mir-bootdisk' and 'bck-bootdisk'\n"; } ($name,$vals) = split(m#=#,$line); @names = split(m#\s+#,$vals); foreach $alias (@names) { if (defined($aliases{$alias})) { $string = "$alias\t$aliases{$alias}\t"; ($machine,$human) = split(m#\t#,$aliases{$alias}); $human =~ s#/dev/rdsk/##; $err = ""; if (defined($used{$human})) { if (($alias =~ m#pri#) && (!($used{$human} =~ m#\(/\)#))) { $err = "\tERROR: not mounted as root"; } elsif (($alias =~ m#mir#) && (!($used{$human} =~ m#\(/\)#))) { $err = "\tERROR: not mounted as root"; } elsif (($alias =~ m#bck#) && (!($used{$human} =~ m#bck#i))) { $err = "\tERROR: not mounted as bck_root"; } $string = $string."$used{$human}$err\n"; } else { $string = $string."ERROR: device not mounted\n"; } if ($quietmode) { if ($string =~ m#ERROR#) { print "$string"; } } else { print "$string"; } } else { print "$alias\tERROR: alias '$alias' not defined\n"; } } } } close(IN); } ################################################################################ sub run_get_dev_info2 ################################################################################ { # print "run_get_dev_info2\n"; my (%cf,%data); read_vfstab(); run_metadb(); run_metastat(); } ################################################################################ sub run_format ################################################################################ { ($formatfile) = @_; if (! defined($ENV{SUDO_USER})) { print "USAGE: sudo $0\n"; exit(1); } else { $formatfile = "/tmp/format.output"; $input = "/tmp/format.input"; open(OUT,">$input"); print OUT "0\nq\n"; close(OUT); @res = `/usr/sbin/format < $input > $formatfile`; } } ################################################################################ sub read_format ################################################################################ # builds @devices from output of format command { my ($formatfile) = @_; # ## get disk information from format # if ($debug) { print "data from format\n"; } if (( ! -f $formatfile) || ($user eq "root")) { run_format($formatfile); } open(IN,"$formatfile"); while ($line = ) { chomp($line); if ($line =~ m#^\s+(\d+)\.\s+(.*?)\s+<(.*?)>#) { if ($debug) { print "$1 - $2\n"; } push(@devices,$2); } } close(IN); if ($debug) { print "\n"; } } ################################################################################ sub run_metadb ################################################################################ # builds/updates %used with data from metadb command { # print "run_metadb\n"; # ## get meta-device information from metadb # if (-f "/usr/opt/SUNWmd/sbin/metadb") { $execdir = "/usr/opt/SUNWmd/sbin"; } elsif (-f "/usr/sbin/metadb") { $execdir = "/usr/sbin"; } if ($debug) { print "data from metadb\n"; } $cmd = $execdir."/metadb"; open(METADB,"$cmd |"); while ($line = ) { chomp($line); ($flags,$first,$count,$unk,$unk2,$file) = split(m#\t#,$line); if ($file =~ m#/#) { @parts = split(m#/#,$file); $devname = pop(@parts); $used{$devname} = "metadb"; } } close(METADB); } ################################################################################ sub run_metastat ################################################################################ # builds/updates %used with data from metastat command { # print "run_metastat\n"; # ## get meta-device information from metastat # if (-f "/usr/opt/SUNWmd/sbin/metastat") { $execdir = "/usr/opt/SUNWmd/sbin"; } if (-f "/usr/sbin/metastat") { $execdir = "/usr/sbin"; } # /usr/opt/SUNWmd/sbin/metastat # /usr/sbin/metastat if ($debug) { print "data from metastat\n"; } $metafile = "/tmp/metastat.output"; if ((-f $metafile) && ($user ne "root")) { if (! $quietmode) { print "using existing $metafile\n"; } } else { @res = system($execdir."/metastat > $metafile"); } # ### TESTING ################################ # $metafile = "/tmp/metastat.output.website1"; $size = (-s $metafile); open(IN,"$metafile"); read(IN,$buf,$size); close(IN); # join the multi-line outup for each meta device $buf =~ s#\s+Invoke:#\tInvoke:#g; $buf =~ s#\s+State:#\tState:#g; $buf =~ s#\s+Size:#\tSize:#g; $buf =~ s#\s+Submirror#\tSubmirror#g; $buf =~ s#\s+Stripe#\tStripe#g; $buf =~ s#\s+Device\s+Start\s+Block\s+Dbase\s+State\s+Hot\s+Spare\s+# #g; while ($buf =~ m#\n\t(c\d+t\d+d\d+s\d)#) { $buf =~ s#\n\t(c\d+t\d+d\d+s\d)# $1#; } @data = split(m#[\n\r]+#,$buf); # @devs = grep(m#c\d+t\d+d\d+s\d#,$buf); foreach $line (@data) { chomp($line); # print "$line\n"; $line =~ s#^\s+##; @words = split(m#\s+#,$line); # print "$#words\t$line\n"; if (($line =~ m#^d#) && ($words[1] =~ m#Mirror#)) { # print "mirror - $line\n"; $volume = $words[0]; $voltype = $words[1]; @parts = split(m#\t#,$line); foreach $pair (@parts) { ($name,$val) = split(m#:#,$pair,2); if ($name =~ m#Submirror#) { # print " Submirror: $val\n"; } elsif ($name =~ m#State#) { # print " State: $val\n"; } elsif ($name =~ m#Size#) { # print " Size: $val\n"; } elsif ($name =~ m#Stripe#) { # print " $name: $val\n"; } } } if (($line =~ m#^d#) && ($words[1] =~ m#Submirror#)) { # print "submirror - $line\n"; $volume = $words[0]; $volume =~ s#:$##; $voltype = $words[1]; $parent = $words[3]; @parts = split(m#\t#,$line); foreach $pair (@parts) { if ($pair =~ m#(.*?):(.*?)$#) { $name = $1; $val = $2; # ($name,$val) = split(m#:#,$pair,2); if ($name =~ m#Submirror#) { # print " Submirror: $val\n"; } elsif ($name =~ m#State#) { # print " State: $val\n"; } elsif ($name =~ m#Size#) { # print " Size: $val\n"; } elsif ($name =~ m#Stripe#) { # print " $pair] [$name:] [$val\n"; if ($val =~ m#\)#) { ($front,$back) = split(m#\)#,$val); # print "[$front] [$back]\n"; $val = $back; } $val =~ s#\s+c#XYzzYc#g; @slices = split(m#XYzzY#,$val); foreach $slice (@slices) { ($dev,$start,$dbase,$state,$spare) = split(m#\s+#,$slice); if ($dev ne "") { if (($debug) or ($state =~ m#Maintenance#)) { print " Dev: $dev\t$state\t$spare\tsubmirror $volume of $parent\n"; } $string = "submirror $volume of $parent ($used{$parent})\t$state\t$spare"; $used{$dev} = $string; } } } } if ($pair =~ m#^c#) { ($dev,$start,$dbase,$state,$spare) = split(m#\s+#,$pair); print " dev: $dev] [$start][$dbase]\n"; } } } } if ($debug) { print "\n"; } } #exit(); ################################################################################ sub read_vfstab ################################################################################ # builds/updates %used with data from vfstab file { # print "read_vfstab\n"; # ## get mount point info from vfstab # if ($debug) { print "data from vfstab\n"; } $vfstab = "/etc/vfstab"; open(IN,"$vfstab"); read(IN,$buf,$size); while ($line = ) { chomp($line); if ($line =~ m/^#/) { #ignore comments } else { # if ($line =~ m#/dev/dsk#) { ($vdevice,$vrawdevice,$vmountpoint,$vfsck,$vpass,$vboot,$vopt) = split(m#\s+#,$line); @dparts = split(m#/#,$vdevice); $dev = pop(@dparts); if ($vfsck =~ m#swap#) { $vmountpoint = $vfsck; } if (($vfsck ne "proc") && ($vfsck ne "nfs")) { $used{$dev} = $vmountpoint; if ($debug) { print "$dev -> $vmountpoint\n"; } } } } } close(IN); if ($debug) { print "\n"; } } ################################################################################ sub parse_cf ################################################################################ # not called? { print "parse_cf\n"; my ($devname); open(CF,"/etc/lvm/md.cf"); while ($line = ) { if ($line =~ m#\s+-m\s+#) { chomp($line); ($mir,$j,$rest) = split(m#\s+#,$line,3); # print "[$mir][$j][$rest]\n"; } elsif ($line =~ m#(.*?)\s+\d+\s+\d+\s+(.*?)$#) { $submir = $1; $devname = $2; # print "[$submir] [$devname]\n"; if (($dir eq "") && (defined($used{$devname}))) { $dir = $used{$devname}; } $string = sprintf "%12s\t\tmounted as\tsubmirror $submir of $mir ($used{$mir})\t[Maintenance?]",$foo; $cf{$devname} = $string; # print "$devname => $string\n"; } } close(CF); } ################################################################################ sub add_commas ################################################################################ { local($num) = @_; $wholenumber = (split(m#\.#,$num))[0]; while ($wholenumber =~ s#(.*\d)(\d\d\d)#$1,$2#) { # print "$wholenumber\n"; } return($wholenumber); }