如何调试和修复 bash 中缓慢的自动完成功能?

如何调试和修复 bash 中缓慢的自动完成功能?

最近更新(Ubuntu 12.04 LTS)后,命令行上的 TAB 完成速度很慢。输入部分命令(例如evi [TAB])或部分文件名(例如evince somedocu[TAB])后,shell 有时(但并非总是)会挂起几秒钟。

就我个人而言,我更喜欢功能较弱的自动完成功能,而不是速度较慢的自动完成功能。有一个简单的修复方法吗?

编辑:与评论相关的附加信息:

  • PATH 非常标准。 ~/bin 有一些 bash 脚本

    $ echo $PATH
    /home/USERNAME/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
    
  • 工作目录下的文件数量小于100。

  • 在异常磁盘活动(系统升级)之后,自动完成功能特别慢。因此,重新读取 /usr/bin 和其他目录可能会导致延迟。

答案1

我不知道如何修复——有各种各样的事情可能会导致延误。但我可以提供一些调查建议。

作为猜测,也许搜索路径中的某个目录($PATH或者 bash 查找完成数据的某个地方)位于响应缓慢的文件系统上。通常是远程文件系统速度慢,但也可能是硬盘故障、挂起的 FUSE 驱动程序等。

调查的第一步是运行set -x以跟踪 shell 执行以生成补全的命令。观察它在哪里暂停。完成后,使用 关闭跟踪set +x

如果这还不能提供足够的信息,请带上大枪。记下 shell 的进程 ID ( echo $$)。在另一个终端中,运行strace -f -s9999 -p$$(或相当于斯特雷斯如果运行在另一种 Unix 风格上)。 Strace 列出了进程执行的系统调用。查看它是否似乎正在访问不应该访问的文件,或者对某些文件的访问是否很慢。将选项添加-Tstrace命令行可以显示每个系统调用所花费的时间。

答案2

如果您的 *nix 机器设置为 LDAP 客户端,即使以本地用户身份登录,您也可能会遇到此问题。

无聊的调试信息:使用 进行调试set-x,我发现完成状态挂在:

> set -x
> ls foo<tab>
...                     <--- lots of output removed
...
+ _quote_readline_by_ref foo quoted
+ '[' -z foo ']'
+ [[ foo == \'* ]]      <--- froze here
+ [[ foo == ~* ]]       <--- actually causing the trouble

确认:我确认了这一点,ls ~*也挂了。事实证明我的 ldap 服务器速度很慢,但这不应该影响 bash 完成和 ls! 之类的事情!

解决方案:啊哈,有一个错误提交针对 bash-completion + ldap,它将在较新的版本中修复,并且简单的补丁如果你不想等。制表符完成速度又快了,万岁!

这是补丁文件,以防链接消失。它只是转义第 545 行和第 547 行的 ~:

--- /usr/share/bash-completion/bash_completion.orig 2014-11-06 10:36:14.981888369 +0100
+++ /usr/share/bash-completion/bash_completion  2014-11-06 10:36:25.142070963 +0100
@@ -542,9 +542,9 @@
     elif [[ $1 == \'* ]]; then
         # Leave out first character
         printf -v $2 %s "${1:1}"
-    elif [[ $1 == ~* ]]; then
+    elif [[ $1 == \~* ]]; then
         # avoid escaping first ~
-        printf -v $2 ~%q "${1:1}"
+        printf -v $2 \~%q "${1:1}"
     else
         printf -v $2 %q "$1"
     fi

您需要退出当前的 ssh 会话并重新登录才能使此补丁生效。

答案3

我建议检查你的系统音频工作正常。终端铃声无法正确播放可能是暂时冻结的原因。例如:PulseAudio Daemon 崩溃/工作不正常。

在我的终端中,当我第一次按 Tab 键时,它卡住了几秒钟。之后就好了。如果删除终端中的所有文本并按下退格键,也会发生这种情况。

我尝试了以上所有方法,但都没有成功。

关闭航站楼铃声

Ctrl+ Alt+ T--> 编辑 --> 首选项 --> {用户配置文件,通常未命名} --> 文本 --> 声音 --> 取消选中航站楼铃声

答案4

另一个策略是检查 Bash 配置文件并停用所有完成功能。然后测试是否更快。如果速度不快,则可能与慢速(远程)磁盘有关。但如果速度更快,您可以一点一点地启用完成,直到找到导致速度缓慢的原因。

我发现我/etc/bash.bashrc有这部分:

if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

和我当地的~/.bashrc一模一样。因此,完成代码被包含了两次,并且在部分完成不明确的目录名称时不知何故增加了速度。

相关内容