为什么命令 df 和 du 报告不同的输出?
您永远不会在 FreeBSD、Linux 桌面主系统或 UNIX 或 Linux 工作站上注意到类似的事情。但是,有时在生产 UNIX 服务器上,您会注意到df 命令(显示可用磁盘空间)和 du 命令(显示磁盘使用情况统计信息)报告不同的输出。通常,df 输出的磁盘使用情况比 du 更大。
作为一名 Unix 系统管理员,有时我会注意到 df 和 du 的输出彼此不同。那么当 df 和 du 报告不同的用法时该怎么办?
教程详细信息 | |
---|---|
难度等级 | 先进的 |
Root 权限 | 是的 |
要求 | Linux 或 Unix 终端 |
类别 | 系统管理 |
操作系统兼容性 | AIX • Alma • Alpine • Arch • BSD • Debian • Fedora • FreeBSD • HP-UX • Linux • macOS • Mint • NetBSD • OpenBSD • openSUSE • Pop!_OS • RHEL • Rocky • Stream • SUSE • Ubuntu • Unix • WSL |
预计阅读时间 | 7 分钟 |
为什么命令 df 和 du 报告不同的输出?
如果Linux 或 UNIX inode被释放,您将看到此问题。如果您使用集群系统(文件系统,如 GFS),您可能会经常看到这种情况:
- 如您所知,du 命令可估算文件空间使用情况,而 df 命令可显示文件系统磁盘空间使用情况。
- 在Unix/Linux下删除一个文件时,有些情况下该文件占用的磁盘空间不会立即释放(见下面的例子)。
- du命令的执行结果中不包含删除文件的大小,但是df命令对删除文件大小的影响由于磁盘空间占用不会立即释放。
- 因此,删除文件后,直到释放磁盘空间后,df 和 du 的结果是不同的。
以下示例特定于 FreeBSD 和 GNU/Linux,但也适用于其他类 Unix 系统。
示例
以下是我的 Linux 服务器上 /tmp 文件系统的df和 du 命令的正常输出:
# df -h /tmp
这是我所看到的:
Filesystem Size Used Avail Capacity Mounted on /dev/ad0s1e 496M 22M 434M 5% /tmp
现在输入 du 命令:
# du -d 0 -h /tmp/
输出:
22M /tmp/
为什么 df 和 du 输出不匹配?
但是,有时它会报告不同的输出(更大的磁盘使用量),例如:
# df -h /tmp/
输出:
Filesystem Size Used Avail Capacity Mounted on /dev/ad0s1e 496M 39M 417M 9% /tmp
现在,输入 du 命令:
# du -d 0 -h /tmp/
输出:
22M /tmp/
如您所见,df 和 du 都报告了不同的输出。不幸的是,许多新的 UNIX 管理员和开发人员混淆了输出(39M vs 22M)。打开文件描述符是导致此类错误信息的主要原因。例如,如果第三方应用程序或用户打开了名为 /tmp/application.log 的文件,并且删除了同一个文件,则 df 和 du 都会报告不同的输出。您可以使用 lsof 命令来验证这一点:
# lsof | grep tmp
输出:
bash 594 root cwd VDIR 0,86 512 2 /tmp bash 634 root cwd VDIR 0,86 512 2 /tmp pwebd 635 root cwd VDIR 0,86 512 2 /tmp pwebd 635 root 3rW VREG 0,86 17993324 68 /tmp (/dev/ad0s1e) pwebd 635 root 5u VREG 0,86 0 69 /tmp (/dev/ad0s1e) lsof 693 root cwd VDIR 0,86 512 2 /tmp grep 694 root cwd VDIR 0,86 512 2 /tmp
您可以看到 pwebd(我们的内部软件)在 /tmp 文件系统上打开了 17993324K 文件,但被我意外删除了。因此,您可以按照如下方式在您的 Linux、FreeBSD 或 Unixish 系统中重现上述场景。首先,记下 /home/ 文件系统的输出:
如果您使用的是 Linux,则使用 du 如下:现在使用cat 命令和重定向
创建一个大文件:
登录其他控制台并使用 vi 文本编辑器打开文件 demo.txt:
请不要退出 vi(保持它运行)。返回另一个控制台并使用 rm 命令删除文件demo.txt:
现在运行 du 和 df 来查看差异。例如:
如果您使用的是 Linux,则使用 du 如下:
最后,登录到上一个终端并关闭正在运行的 vi/vim。当您关闭 vi 文本编辑器时,问题的根本原因应该得到解决。猜怎么着?du 和 df 命令输出也应该得到更正。简而言之,df 和 du 在这里存在分歧,因为 df 命令会看到这些已删除的文件及其替换文件并计算总磁盘使用量,而另一方面,du 命令只看到新文件。
# df -h /home
# du -d 0 -h /home
# du -s -h /tmp
# cd /home/user
# cat /bin/* >> demo.txt
# cat /sbin/* >> demo.txt
# vi /home/user/demo.txt
# rm demo.txt
# df -h /home
# du -d 0 -h /home
# du -s -h /home
使用 lsof 列出已删除的文件
键入grep 命令和 lsof 命令的组合,如下所示,列出可能被其他用户或应用程序打开的已删除文件。例如:
# lsof | grep -i deleted
使用 fuser 命令收集信息
我们可以查看使用目录的进程,并了解在文件打开时是否有东西锁定了目录和文件系统。例如,以下是如何检查 /tmp/test/:
# fuser -v /tmp/test/
输出:
USER PID ACCESS COMMAND /tmp/test: vivek 1434306 ..c.. bash vivek 1447257 ..c.. vim
在AIX 和其他类 Unix 系统上,fuser 可以使用以下语法报告任何已从文件系统取消链接并从父目录中删除的打开文件:
在 Linux 上尝试 lsof 命令:
# fuser -dV /
# fuser -dV /tmp/
# lsof -nP | grep '(deleted)'
# lsof -nP | grep -i 'deleted' | less
# find /proc/*/fd -ls | grep '(deleted)'
当 df 和 du 显示不同的输出时,我该如何解决问题?
- 使用上面讨论的 lsof 命令查找其他用户和应用程序打开的已删除文件。有关更多信息,请参阅如何列出系统中的所有用户。
- 然后,关闭这些应用程序并注销这些 Linux 和 Unix 用户。
- 作为系统管理员,您可以使用kill 命令或 pkill 命令或killall 命令重新启动任何进程或终止 Linux 和 Unix 下未释放已删除文件的进程。
- 使用同步命令刷新文件系统,将缓存的写入同步到持久磁盘存储。
- 如果其他所有方法都失败,请尝试使用reboot 命令或shutdown 命令重新启动系统
求助,df 和 du 仍然没有返回匹配的结果
首先,我想澄清一下这篇 2000 年代的博客文章。df 和 du 命令输出之间的差异并不意味着您的硬盘驱动器存在问题。相反,我坚信系统管理员和开发人员必须使用正确的工具。例如:
- 使用 du 来分析一小部分文件/目录。
- 使用 df 命令获取有关整个文件 Linux 和 Unix 系统的详细信息。
换句话说,df 和 du 不是为返回相同的数据而创建的。每个 Unix 工具都是不同的,并且用于特定的任务。例如,您使用 df 来汇总其磁盘空间使用情况。另一方面,du 扫描目录(包括所有文件和子目录)以提供最终结果。当文件被删除或打开或属于另一个文件系统的一部分或对 du 不直接可见时,du 可能会失败。例如,您有一个 /opt/finacleapp/。在此之下,有许多子目录。我从 NetApp 设备的 /opt/finacleapp/sharedasset/ 获得了第二个 NFS 挂载文件系统。当我运行“df /”时,我获得了有关根文件系统的原始 /opt/finacleapp/ 中使用的空间的信息。但是,du 命令无法看到该区域并计算那里的使用情况,因为另一个 NFS 文件系统正在覆盖该目录。
这种情况有很多,具体取决于您的 Unix 和 Linux 服务器的配置方式。因此,在某些情况下,df 和 du 无法提供相同的结果。使用 mount、lsof、fuser 和其他命令检查您的系统。
总结
根据我的经验,报告大小差异的原因是 df 命令不区分在 Unix/Linux 服务器内存中打开但可能在服务器磁盘上被删除或更改的文件。相反,du 命令只会看到磁盘上的文件。如果您认识到这些工具具有不同的功能并且不是磁盘上某些东西损坏或故障的最终证据,那将有所帮助。使用 man 命令阅读以下手册页以获取更多信息:
$ man df
$ man du
$ man lsof
$ man fuser