完整的根分区

作者:LJ Staff,发布于 2007 年 10 月 18 日

最近,我需要解决一个我负责监控的服务器上,根分区显示 100% 占用的问题。 这是意料之外且突然发生的,因为分区的用量已经稳定在 30% 一段时间了。

从这次经历中,我了解到 Linux 内核处理打开文件/进程的一个简单但有用的事实,我想分享它,希望能帮助其他人节省一些时间来解决类似的问题。 总结如下:如果一个进程打开一个文件,然后该文件被删除,但仍被该进程打开,该文件将继续存在,并在物理上消耗磁盘空间,直到进程结束。 这种 unlink() 系统调用的工作方式可能会令人困惑,因为 df 命令会认为该空间仍在被使用,但 du 和类似的命令会认为它是空闲的。

1.) 根据 df 检查挂载点和分区可用空间

# df -h
   Filesystem            Size  Used Avail Use% Mounted on
   /dev/sda6             373M  373M     0 100% /

...df 说我的根分区空间已满!

2.) 检查 / 下目录条目的磁盘使用情况(如果同一个文件存在多个硬链接,则只在总数中计算其大小一次)

$ du -bc 'find / -type f -links 1 -print'

注意 1:不要忘记排除可能挂载在其他分区上的目录,例如 /home、/var、/usr

注意 2:此命令应该有效,但在我的系统上,如果文件数量很多,它会报错并失败。 因此,我使用了一个 Perl 脚本,该脚本将执行与上面的 du 命令等效的操作

 ############################  disk_usage.pl   ############################
   #! /usr/bin/perl

   #=-
   #=- Print total bytes used by files beneath the specified directory.

   #=- Only unique inode numbers are counted, so that multiple hard links
   #=- to the same file only count once toward the total file size for the
 dir. #=-

   use strict;
   use warnings;



   my $verbose = 0;

   # open a pipe to a find command to locate files starting in the specified
   # directory and print a simply-formatted string for each...
   my $find_targets = join ' ', @ARGV;

   open my $found_list, '-|', qq{find $find_targets -type f -printf
 "%s\tinode: %i\tlink count: %n\t%p\n"} or die "Can't open find command";

   # process our simple output, keeping track of inode numbers and file

 sizes... my %h;
   while( my $output_line =  ) {
       my ($size, $inode) = $output_line =~ m/^(\d+)\s+(inode: \d+)/;
       $h{$inode} = $size;
       print $output_line if $verbose;

   }

   # calculate and display total...
   my @ordered = sort values %h;
   my $total = 0;
   map { $total += $_ } @ordered;
   print "-" x 25 . "\nTOTAL SIZE (UNIQUE FILES): " . $total . "\n";

   ##########################################################################

$ sudo disk_usage.pl /
...
TOTAL SIZE (UNIQUE FILES): 33747784

此总计约 34M 是使用以目录条目为基础的磁盘使用命令计算得出的。 但是为什么 df 命令会显示没有可用空间了呢? 如果只使用了 34M,我们应该还有大约 339M 可用空间(加上为超级用户保留的块)!

答案是,一个进程已经打开了一个文件,该文件随后被 unlink()(例如,通过 rm 命令)。 文件的内容将保留,直到进程释放其与文件的链接。 在我的例子中,一个错误的进程导致数据保留在磁盘上。 下一步:查找被进程打开但没有被目录条目引用的文件

   # lsof | grep deleted
   gpm        1081     someuser    1u   REG        8,7         5     38166
 /var/run/gpmcDrT4c (deleted) gnome-ses  1274     someuser    1w   REG       

 8,6 280546304     68281 /home/someuser/.xsession-errors (deleted) gnome-ses 
 1274     someuser    2w   REG        8,6 280546304     68281
 /home/someuser/.xsession-errors (deleted) metacity   1367     someuser    1w

   REG        8,6 280546304     68281 /home/someuser/.xsession-errors
 (deleted) ...additional lines ommitted

在这里,X 服务器的一些核心进程似乎占用了大约 280M。 通过让“someuser”注销 X,很容易解决这个问题。

这个技术提示来自美国肯塔基州的 Karl。 谢谢你,Karl!

Linux Journal 轻松成名。 只需 给我们发送 您有用的技术提示,与 Linux 社区分享,我们会送您一件很酷的 T 恤!

请注意:LinuxJournal.com 特定部分中刊登的技术提示由读者友好提供,不一定经过 LinuxJournal.com 编辑的测试。