重击完成使重击开始缓慢


15

在我的ubuntu系统上启动bash大约需要2秒钟。如果我删除了.bashrc中的/ etc / bash_completition加载,它将立即启动。当然,我不想放弃竞争,也不认为加载该文件是2秒钟延迟的合法原因。

关于如何找出问题所在或如何加快速度的任何想法。


是/ bin / bash吗?-尝试/ bin / dash可能会更快一些。
Sirex

3
这就是为什么我卸载了bash-completion
Vi。

Answers:


8

2013年更新:仅在需要时,大多数bash-completion都重写为自动加载完成。现在,核心脚本更加模糊了。


在Shell脚本标准中,完成脚本有时可能非常庞大。在我可以访问的一台服务器上,这几乎是1700行(57 KB),这只是核心脚本。在/etc/bash_completion.d有〜关于各种其他命令200个额外的脚本(opensslmuttmount...),共计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禁用跟踪模式。)


即使在简单的文本模式下也可以爬行?比您想像的可能性更大。
六。

@Vi:看到zsh将其启动脚本编译为字节码...
2011年

1
谢谢。那真的很容易。遗憾的是,所有命令都没有明显的不同。因此,看起来确实是造成问题的大量原因。
user75250 2011年

12

我发现了一个有点骇人听闻的解决方案,似乎可以正常工作。

在底部~/.bashrc添加:

陷阱'源/ etc / bash_completion; 陷阱USR1'USR1
{睡眠0.1; 内置kill -USR1 $$; }并拒绝

说明

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

设置一个处理程序,使其在外壳程序收到信号时运行SIGUSR1;处理程序将加载完成内容,因此将使其自身停用。

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

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

问题

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


1
这似乎并没有给启动带来提振- time bash -lc true无论有没有报告,报告约为0.12s,即使time source /etc/bash_completion报告的数字更高,如0.26s。这个问题有效地解决了吗?
13年

我不知道time bash -lc true这里是否可以正常工作,因为true之前已经完成了,~0.1s所以它没有任何来源。无论如何,time source /etc/bash_completion这里报告的时间约为0.17秒,这就是我需要等待外观的时间PS1
cYrus

2
巧妙!在解释中,陷阱命令USR1的末尾缺少a 。
Fish Monitor

使用SIGUSR,在我在shell提示符下按Enter之前,不会调用信号处理程序。它在运行时会暂停。我切换到SIGQUIT,它似乎工作正常。
乔恩·纳利

5

您应该使用bash_completion的最新版本(2.0)。如果您使用的是Debian,则它处于wheezy模式,但它不依赖于任何其他wheezy软件包,因此您可以毫无问题地将其安装在压缩状态。

最新版本动态地动态加载完成,因此它为我分配的即时加载时间至少是10倍。


1

您可以在完成内容加载时使用占位符;它应该足以欺骗您的眼睛。仅当所需的时间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可避免闪烁,但是如果占位符比实际提示长,它将留下垃圾字符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.