最近,我需要解决一个我负责监控的服务器上,根分区显示 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 编辑的测试。