#!/usr/bin/perl # # (c) 2003, Scott Kaiser, all rights reserved. # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # Redistributions of source code must retain the above copyright notice, this list # of conditions and the following disclaimer. # The name of the author may not be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT # SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # This script returns a recommendation on whether or not to defragment. # This script takes a file system mount point as an argument. # If the -a (auto) option is used, the script defragments the file system # if defragmentation is necessary. #main #initialize $arg_cnt=0; $arg=""; $fs="none"; $auto_defrag=0; # set default to do not defrag $sm_extents=-1; # set the fragmentation levels low so as not to trigger a false positive in event of an error $vsm_extents=-1; $lg_extents=1000; $frag=0; # parse the arguments, fail if arguments don't conform. foreach $arg (@ARGV) { $arg_cnt++; if ($arg_cnt = 1) { if ($arg eq "-a") { $auto_defrag=1; } elsif ($arg =~ /\//) { $fs=$arg; } else { die "Usage: vxdefrag [-a] /mount_point\n"; } } elsif ($arg_cnt = 2) { if ($autodefrag == 0) { die "Usage: vxdefrag [-a] /mount_point\n"; } elsif ($arg =~ /\//) { $fs=$arg; } else { die "Usage: vxdefrag [-a] /mount_point\n"; } } else { die "Usage: vxdefrag [-a] /mount_point\n"; } } if ($fs eq "none") { die "Usage: vxdefrag [-a] /mount_point\n"; } $flag = &getFlag; $cmdDir = &getDir; @defrag = `$cmdDir/fsadm -$flag vxfs -E $fs`; #parse the output to determine if fragmented foreach $line (@defrag) { if ($line =~ /.*smaller.*64.*/) { $sm_extents=$line; } elsif ($line =~ /.*smaller.*8.*/) { $vsm_extents=$line; } elsif ($line =~ /.*64.*larger.*/) { $lg_extents=$line; } } #strip line down to just the "string value" #\s removes 'whitespace', [A-Za-z] removes alpha characters $sm_extents=~ s/\s//g; $sm_extents=~ s/[A-Za-z]//g; $sm_extents=~ s/%64://g; $vsm_extents=~ s/\s//g; $vsm_extents=~ s/[A-Za-z]//g; $vsm_extents=~ s/%8://g; $lg_extents=~ s/\s//g; $lg_extents=~ s/[A-Za-z]//g; $lg_extents=~ s/%64://g; #convert from string and percentage to numeric and decimal $sm_extents= $sm_extents/100; $vsm_extents= $vsm_extents/100; $lg_extents= $lg_extents/100; #issue a recommendation based on the VERITAS File System documentation if ($sm_extents < .05 && $vsm_extents < .01 && $lg_extents > .05) { $frag = 0; } elsif ($sm_extents > .5 || $vsm_extents > .05 || $lg_extents < .05) { $frag = 2; } else { $frag = 1; } if ($frag == 0) { print "$fs is not fragmented. Defragmentation is not recommended.\n"; } elsif ($frag == 1) { print "$fs is somewhat fragmented. Defragmentation is not necessary.\n"; } elsif ($frag == 2) { print "$fs is badly fragmented. Defragmentation is recommended.\n"; # Autodefrag. Note that, for good measure, directories are defragmented too. if ($auto_defrag == 1) { print "Defragmentation starting.\n"; system("$cmdDir/fsadm -$flag vxfs -de $fs"); } } #end ############## # Subroutine to get operating system-specific file system 'flag' sub getFlag { $os = `/usr/bin/uname`; if ($os = "SunOS" or $os = "HP-UX") { $flag="F"; } elsif ($os = "AIX") { $flag="V"; } elsif ($os = "linux" or $os = "Linux") { $flag="t"; } else { die "\n This script does not support $os\n"; } $flag; } ############## ############## # Subroutine to get the command location # note that with VxFS 3.5 and higher (3.4 for AIX and Linux), symlinks # to all commands are located in /opt/VRTS/bin sub getDir { $os = `/usr/bin/uname`; if ($os = "SunOS") { $cmdDir="/opt/VRTSvxfs/sbin"; } elsif ($os = "HP-UX") { $cmdDir="/usr/sbin/fsadm"; } elsif ($os = "linux" or $os = "Linux" or $os = "AIX") { $cmdDir="/opt/VRTS/sbin"; } else { die "\n This script does not support $os\n"; } $cmdDir; } ##############