Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

152 рядки
4.2 KiB

  1. #!/usr/bin/env perl
  2. #
  3. # Find out who is hogging disk space and where.
  4. #
  5. # Argument is the directory to start from. Only calculates size of files.
  6. # Adds the size of files in a directory to the size of the parent directory only.
  7. #
  8. # Defaults to top 10 directories/files.
  9. #
  10. # Override with -n num to list whatever amount of large things you desire.
  11. # Or if you want to abuse the parser, use -1 for all files/directories.
  12. #
  13. # Defaults to pwd for space.
  14. #
  15. use File::Find;
  16. use Getopt::Long;
  17. use Cwd;
  18. my $debug;
  19. my $statbug;
  20. (exists($ENV{"DEBUG"})) ? $debug++ : undef;
  21. my $dir = Cwd::abs_path($ARGV[-1] || Cwd::getcwd());
  22. my %diskhogs = ();
  23. my %inodes = ();
  24. my ($topdev,undef,undef,undef,undef,undef,undef,undef) = lstat($dir);
  25. local $opt_displaynum = 10;
  26. GetOptions( 'n=i', => \$opt_displaynum,
  27. );
  28. find(\&sieve, $dir);
  29. #
  30. # For outputing the size of a bunch of bytes in g/m/k depending upon the size
  31. #
  32. sub byte_print {
  33. my $byte_k = 1_024;
  34. my $byte_m = $byte_k**2;
  35. my $byte_g = $byte_k**3;
  36. my $bytes = pop;
  37. my $base = $bytes;
  38. my $suffix = "nil";
  39. my $out_string = "BUG";
  40. if($bytes > $byte_g){
  41. $base = $bytes / $byte_g;
  42. $suffix = "g";
  43. }elsif($bytes > $byte_m){
  44. $base = $bytes / $byte_m;
  45. $suffix = "m";
  46. }else{
  47. $base = $bytes / $byte_k;
  48. $suffix = "k";
  49. };
  50. $out_string = sprintf("%.2f%s", $base, $suffix);
  51. return $out_string;
  52. };
  53. #
  54. # Dumb function to return if an inode has already been seen.
  55. # So we handle hard links sane(er-ish-ly) in size calculations.
  56. # This has more truthiness(tm).
  57. #
  58. sub seeninode{
  59. my $what = pop();
  60. my $ret = 0;
  61. unless(exists($inodes{$what})){
  62. $inodes{$what} = 0;
  63. print "New inode $what added to seen inodes.\n" if $debug;
  64. }else{
  65. $inodes{$what}++;
  66. $ret++;
  67. print "Found a hardlink for $what.\n" if $debug;
  68. };
  69. return $ret;
  70. };
  71. sub sieve {
  72. my $file = $File::Find::name;
  73. my $filedir = $File::Find::dir;
  74. my @statinfo = lstat($file);
  75. my $dev = $statinfo[0];
  76. my $inode = $statinfo[1];
  77. my $size = $statinfo[7];
  78. my $blocksize = 512; # field 11 is the "preferred" block size, which appears
  79. # to not match the actual blocksize of the filesystems
  80. # in use. For now every hard drive uses 512bytes/block.
  81. # Will revisit this when 4096byte/block hard drives arrive
  82. my $apparentsize = $statinfo[12] * $blocksize;
  83. print "$file\@$filedir \<$topdev\>\=\<$dev\>\n" if $debug;
  84. print "size,apparentsize,blocksize = <$statinfo[7],$apparentsize\,$blocksize\>\n" if $debug;
  85. #
  86. # Try to handle sparse files.
  87. #
  88. if ($size > $apparentsize) {
  89. print "Sparse file $file!\n" if $debug;
  90. $size = $apparentsize;
  91. };
  92. $dev = (-l $file) ? 0xdeadbeef : $dev;
  93. if (($file =~ m/\/proc|\/chroot|udev\/devices/) ||
  94. ($dev != $topdev) || seeninode($inode)){
  95. print "Pruned $file.\n" if $debug;
  96. $File::Find::prune = 1;
  97. next;
  98. };
  99. unless ($dev){
  100. # Yay, we can't l(stat) files. This version of perl is broken.
  101. # Snag information from ls, assume it's a file. Thanks Solaris 8, you suck.
  102. $statbug++;
  103. warn "Hit empty device statbug while stat()ing file <$file>.\n";
  104. my $ls = qx(ls -ld $file);
  105. my @raw = split(/\s+/, $ls);
  106. $diskhogs{"$file"} = $raw[4];
  107. $diskhogs{"$filedir"} += $raw[4];
  108. }elsif (-f){
  109. if ($debug){
  110. print "Adding $file size ", &byte_print($size), " to $filedir.\n";
  111. print "Adding $file size ", &byte_print($size), "\n";
  112. };
  113. $diskhogs{"$file"} = $size;
  114. $diskhogs{"$filedir"} += $size;
  115. }elsif (-d){
  116. print "Adding $file size ".&byte_print($size)."\n" if $debug;
  117. $diskhogs{"$file"} += $size;
  118. };
  119. if ($debug) {
  120. print "$file from $filedir has size ".&byte_print($diskhogs{"$file"})."\n";
  121. };
  122. };
  123. #
  124. # Reverse sort the keys by size.
  125. #
  126. my @sorted = sort {$diskhogs{$b} <=> $diskhogs{$a}} keys %diskhogs;
  127. splice @sorted, $opt_displaynum if @sorted > $opt_displaynum;
  128. warn "Found one or more instances of the stat() call statbug. This is normally only present on Solaris 8 with stock perl.\n" if $statbug;
  129. foreach (@sorted){
  130. printf "%-9s%s\n", &byte_print($diskhogs{$_}), $_;
  131. };
  132. if ($debug){
  133. print "DEBUG INFORMATION:\n";
  134. foreach (keys %diskhogs){
  135. printf "%-9s%s\n", &byte_print($diskhogs{$_}), $_;
  136. };
  137. };