Bash Tab 补全似乎读取了不需要的文件系统信息?

Bash Tab 补全似乎读取了不需要的文件系统信息?

假设我有一个 NFS 客户端,其 NFS 共享安装在 /nfs_share。

假设我拔掉 NFS 服务器的电源,导致服务器非正常关机。

现在我的客户端的 /nfs_share 已经过时了。

如果我在客户端进入 bash 提示符并输入,ls /nfs_<TAB>我的 bash shell 就会冻结。它似乎卡在了系统调用中。

仅读取 / 来查找哪些条目可能与“/nfs_”匹配不应该在无响应的文件系统上阻塞,因为我们正在读取 / 文件系统中的条目,而不是安装在 /nfs_share 上的 NFS 文件系统中的条目。

仅当制表符补全导致 bash(或其他程序)读取 NFS F/S 的道具时,才会发生冻结。

所以我想知道是否有人知道是什么影响了 NFS 文件系统?* 我可以将系统配置为在仅进行字符串匹配以进行制表符补全时不尝试读取已挂载文件系统的属性吗?

我记得在过去(几​​年前),也许是在不同的发行版上,击中过时的 NFS 挂载会生成一条错误消息和一个非零的退出代码,并且会立即生成。

*) 我觉得这种行为就像 systemd 的某些部分试图通过缓存文件系统信息来“优化”事物。如果是这样,那好 - 但我该如何关闭它呢?

答案1

Bash 中的补全过程分为两个阶段 - 一部分由 bash 完成,一部分由 readline 完成。对于文件名补全,bash 获取目录条目列表,然后将文件名传递给 readline,其中我们有

mark-directories
如果设置为“ on”,则完整的目录名称会附加一个斜线。默认值为“ on”。

然后使用 Readlinestat文件名决定是否附加斜线。在某些系统上,对于某些文件系统,当 bash 获取目录条目时,此信息已经可用,但情况可能并非总是如此。

无论如何,快速检查一下strace -o log bash是否有内因set mark-directories off就会.inputrc发现这可能是主要原因。

没有set mark-directories off

read(0, "\t", 1)                        = 1
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0
write(2, "\n", 1)                       = 1
stat64("/bin", {st_mode=S_IFDIR|0755, st_size=53248, ...}) = 0
stat64("/bin", {st_mode=S_IFDIR|0755, st_size=53248, ...}) = 0
stat64("/boot", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/boot", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
write(2, "bin/  boot/ \n", 13)          = 13
write(2, "bash-5.0$ ls /b", 15)         = 15

和:

read(0, "\t", 1)                        = 1
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0
write(2, "\n", 1)                       = 1
write(2, "bin   boot  \n", 13)          = 13
write(2, "bash-5.0$ ls /b", 15)         = 15

答案2

这是由于客户端处理 NFS 挂载的方式所致。它们被视为远程连接,客户端将向ls远程 NFS 主机发送请求并等待响应。如果在timeo选项设置的指定超时期限内或默认超时期限(60 秒)内未收到响应,则客户端将再次重试 NFS 请求,从而使 shell 提示符保持忙碌状态以等待响应。

NFS此行为是预期行为,因为您的 中存在共享条目fstab。这就是完成的来源(因为 NFS 共享已经挂载) 当您按下时,它与此事Tab没有任何特定联系。systemdbash

这也是这些选项存在的原因。在客户端上soft,bg安装共享时尝试使用它们。此外,您可能希望添加该选项,因为默认超时时间为 600(60 秒),因此您可能希望缩短它。NFStimeo=30

软硬

确定 NFS 请求超时后 NFS 客户端的恢复行为。如果未指定任何选项(或者指定了 hard 选项),则 NFS 请求将无限期重试。如果指定了 soft 选项,则 NFS 客户端在发送重传后将无法再发送 NFS 请求,从而导致 NFS 客户端向调用应用程序返回错误。

背景 / 背景

确定挂载导出失败时 mount(8) 命令的行为方式。如果挂载请求的任何部分超时或彻底失败,fg 选项会导致 mount(8) 以错误状态退出。这称为“前台”挂载,如果未指定 fg 或 bg 挂载选项,则这是默认行为。

人NFS了解更多信息。

相关内容