解决方案

解决方案

在我的 ubuntu 系统上启动 bash 大约需要 2 秒钟。如果我删除 .bashrc 中的加载 /etc/bash_completition,它就会立即启动。当然我不想放弃完成,我不认为加载该文件是延迟 2 秒的正当理由。

有什么想法可以让我找出问题所在或如何加快速度。

答案1

2013 年更新:大部分 bash-completion 都经过重写,只在需要时自动加载补全。核心脚本现在更轻量了。


完成脚本有时可能巨大的符合 shell 脚本标准。在我访问的一台服务器上,它有将近 1700 行(57 KB),这只是核心脚本。其中/etc/bash_completion.d有大约 200 个用于其他各种命令的附加脚本(openssl、、 ...) muttmount总计 25537 行或 1.2 MB。每个脚本在调用时都会在定义完成处理程序之前检查命令是否实际可用;在这种情况下大约 330 次,每次都涉及检查$PATH具有给定名称的可执行文件。(虽然我希望/usr/bin缓存在内存中...)

诚然,即使加载仅需半秒钟,而不是整整两秒钟。但这可能至少是问题的一部分。运行du -hs /etc/bash_completion*或者wc -l /etc/bash_completion{,.d/*} | grep total如果你想检查的话。


您可以尝试在“跟踪”模式下手动获取脚本:

set -x
. /etc/bash_completion

您将看到每行代码的执行情况。如果某个命令执行时间较长,您应该会注意到。

set +x禁用跟踪模式。)

答案2

我发现了一个有点黑客的解决方案,但似乎效果很好。

解决方案

在底部~/.bashrc添加:

陷阱'源 /etc/bash_completion;陷阱 USR1' USR1
{ sleep 0.1 ; 内置 kill -USR1 $$ ; } & disown

解释

trap 'source /etc/bash_completion ; trap USR1' USR1

设置一个处理程序,当 shell 接收到信号时运行SIGUSR1;处理程序将加载完成,因此它将自行停用。

{ sleep 0.1 ; builtin kill -USR1 $$ ; } & disown

异步等待一会儿,然后将信号发送到当前 shell。disown需要抑制bash过程控制反馈。sleep需要异步工作。

问题

由于某种原因,向该 shell 发出的第一个命令不会记录在历史记录中。

答案3

您应该使用最新版本 (2.0) 的 bash_completion。如果您使用的是 Debian,它位于 wheezy 中,但它不依赖于任何其他 wheezy 包,因此您可以毫无问题地在 squeeze 上安装它。

最新版本可动态地即时加载完成,因此它将我的快速加载时间缩短了至少 10 倍。

答案4

您可以在加载补全时使用占位符;这应该足以欺骗您的眼睛。这显然只有在所需的时间source /etc/bash_completion小于您输入和发出第一个 shell 命令所需的时间时才有效,否则它也会被延迟。

这个想法是呼应一个假象PS1,提供完成的信息,最后擦除终端。

假设你的PS1\u@\h:\w\$,那么你可能会写类似这样的内容:

echo -ne "$USER@$HOSTNAME:${PWD/$HOME/\~}\$ "
source /etc/bash_completion
echo -ne '\e[2J\e[H'

在哪里:

  • 2J擦除终端;
  • H将光标移到右上角。

笔记:您可能需要检查用户是否是 root,并使用#而不是$保持一致性:

echo -ne "...$([ $UID = 0 ] && echo '#' || echo '$') "

笔记:删除\e[2J可以避免闪烁,但如果占位符比实际提示长,则会留下垃圾字符。

相关内容