为什么 ls 命令在包含大量文件的 NFS 目录上中断速度很慢?

为什么 ls 命令在包含大量文件的 NFS 目录上中断速度很慢?

我注意到 NFS 上有很多文件的目录

ls *

然后按 Ctrl-C 可能需要一段时间(比如 20 秒)ls 才会回来。

为什么?可以修复 ls 命令以提高响应速度吗?

答案1

当您运行时ls *,首先发生的事情是 shell 获取当前目录的列表。如果目录很大并且服务器很慢,这可能需要一段时间。

一旦 shell 获得了当前目录中的文件名列表,它就会对该列表进行排序(与任何网络交互相比,这非常快),然后调用ls.该ls命令依次查找每个文件并检索其元数据(stat调用)检查是否是一个目录;如果文件是目录,则ls列出其内容而不是目录本身。

当您按Ctrl+时C,不会中断当前的 NFS 操作。您不能在任何地方中断文件系统操作,因为这可能会使系统处于不一致的状态。即使读取文件也可能会更新其访问时间。大多数时候,按照人类标准,对文件的基本读取或写入操作都是瞬时的,但 NFS 是一个例外,尤其是在慢速网络上传输大量数据的情况下。

因此按Ctrl+C只会生效:

  • 如果 shell 当前正在生成文件名列表,则在完全检索该列表时;
  • ls当服务器提供元数据时,如果已启动并且当前正在获取有关文件的元数据;
  • ifls已经启动并且当前正在列出一个目录,当列表被完全检索时,或者至少在它的一部分之后。

这不是命令的错误ls(该命令甚至可能尚未启动)。这甚至不是 shell 的错:这是 NFS 的错。 NFS 相当慢。

答案2

假设:通过 NFS 遍历目录可能会一次性加载比您预期更多的数据。服务器端 IO 过多,导致单个 NFS 调用需要超过 20 秒。 mount withintr选项可能允许 Ctrl-C 中断正在进行的呼叫。

Google 发现了一个 NFS 调用列表,其中包括 READDIRPLUS。基本上是 readdir + 然后是每个文件的 stat 。还有 getacl。换句话说,有一个 NFS 调用基本上可以做到这一点ls -l(对于一定数量的文件)。而不是为每个文件发送单独的统计请求。

谷歌搜索 nfs readdirplus - 这看起来很合理。第一个结果是(付费)错误报告。

RHEL6:NFSv3 READDIRPLUS 极大地减慢了 NFS 目录的通配速度,从而导致性能问题

  • 使用标准挂载的 RHEL 6.2,包含超过 3000 个目录的目录中的 glob 需要 218 秒(近四分钟)。
  • 使用nordirplus选项挂载同一目录以禁用readdirplus调用,同一目录上的glob仅需要1.7秒

所以这似乎是一个有趣的调查方向。


编辑:请注意,您的示例ls *也是通配符的使用。 ls .会避免全球。如果这对您的具体问题有影响,可能是因为通配符发生在 shell 中,而不是 ls 中,这可能会影响 Ctrl-C 的处理方式。我怀疑这是否重要,但我觉得这是一个有趣的问题。

答案3

ls该命令在 NFS 目录上运行缓慢可能有多种原因。

  • 该目录可能不会自动挂载。
  • 这些机器可能不在同一网络中。

然而,这是一个更普遍的想法,而不是特定的网络文件系统。要列出不排序的文件,您可以尝试ls -U列出不排序的文件。从 的手册页来看ls

-U 不排序;按目录顺序列出条目。与 one_per_line 格式“-1”结合使用,它将立即显示文件并且没有内存限制。

有几种变体可以避免排序。您可以检查系统的手册页并尝试以下任一选项。

ls -f
ls -U
ls --sort=none

答案4

如果您有 ls 的别名也可能会导致速度变慢,请尝试 \ls 甚至 \ls -altr 或 ls 的任何其他选项。

相关内容