最近更新(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 列出了进程执行的系统调用。查看它是否似乎正在访问不应该访问的文件,或者对某些文件的访问是否很慢。将选项添加-T
到strace
命令行可以显示每个系统调用所花费的时间。
答案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
一模一样。因此,完成代码被包含了两次,并且在部分完成不明确的目录名称时不知何故增加了速度。