在Cygwin的bash中的加载速度缓慢(Slow load time of bash in cyg

2019-07-22 05:47发布

目前的bash大约需要2秒加载。 我已经跑了使用bash -x标志和我看到的输出,它好像PATH中Cygwin的加载多次。 有趣的是,我用在Linux环境中的同一个文件,但它工作正常,没有重载问题。 可能由以下原因引起的问题?

if [ `uname -o` = "Cygwin" ]; then
    ....
fi

Answer 1:

正如你在你的答案说明,问题是Cygwin的bash的完成包。 快速和简单的解决方法是禁用的bash完成,而要做到正确的方法是运行Cygwin的SETUP.EXE( 重新下载,如果需要),然后选择要卸载该程序包。

较长的解决方案是通过文件工作/etc/bash_completion.d并禁用不需要的人。 在我的系统,用于减缓bash的加载时间(邮递员,阴影,dsniff和e2fsprogs的)所有的最大元凶究竟做了什么,因为没有安装它们被创造完成的工具。

如果您在重命名文件/etc/bash_completion.d有一个.bak扩展,它会停止加载该脚本。 已经禁用所有,但我以这种方式其中一个系统中选择37个脚本,我剪的平均时间bash_completion 95%(6.5秒至0.3秒),加载。



Answer 2:

就我而言,这是Windows域控制器。 我这样做是为了找到问题:

我开始用一个简单的,窗户cmd.exe和,键入如下:
c:\cygwin\bin\strace.exe c:\cygwin\bin\bash

就我而言,我注意到一个顺序如下:

    218   12134 [main] bash 11304 transport_layer_pipes::connect: Try to connect to named pipe: \\.\pipe\cygwin-c5e39b7a9d22bafb-lpc
     45   12179 [main] bash 11304 transport_layer_pipes::connect: Error opening the pipe (2)
     39   12218 [main] bash 11304 client_request::make_request: cygserver un-available
1404719 1416937 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#1>
    495 1417432 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#2>
    380 1417812 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#3>

    etc...

事情的关键是确定client_request::make_request: cygserver un-available行。 你可以看到,如何在这之后,cygwin的试图从窗口取每一个组,执行时间去疯狂。

快速谷歌透露了什么cygserver是: https://cygwin.com/cygwin-ug-net/using-cygserver.html

Cygserver是其目的是作为后台服务运行的程序。 它提供了Cygwin的应用与安全性要求仲裁或需要,而没有其他的cygwin应用程序运行于持续的服务。

解决的办法是,运行cygserver-config ,然后net start cygserver启动Windows服务。 Cygwin的启动时间之后显著回落。



Answer 3:

所有的答案都涉及到旧版本bash_completion的,并且是无关最近bash_completion

现代bash_completion移动大部分完成的文件,以/usr/share/bash-completion/completions默认情况下,通过运行检查你的系统上的路径

# pkg-config --variable=completionsdir bash-completion
/usr/share/bash-completion/completions

有许多文件在那里,每一个命令,但是这不是一个问题,因为他们是在按需加载使用完成每个命令的第一次。 老/etc/bash_completion.d仍支持兼容性,当从那里的所有文件都加载bash_completion开始。

# pkg-config --variable=compatdir bash-completion
/etc/bash_completion.d

使用这个脚本,以检查是否有剩余的旧目录的任何陈旧的文件。

#!/bin/sh
COMPLETIONS_DIR="$(pkg-config --variable=completionsdir bash-completion)"
COMPAT_DIR="$(pkg-config --variable=compatdir bash-completion)"
for file in "${COMPLETIONS_DIR}"/*; do
    file="${COMPAT_DIR}/${file#${COMPLETIONS_DIR}/}"
    [ -f "$file" ] && printf '%s\n' $file
done

它打印在COMPAT DIR是也存在于新的(按需)落成目录的文件列表。 除非你有特别的理由让他们中的一些,审核,备份并删除所有这些文件。

其结果是,在compat的目录应该是大部分是空的。

现在,最有趣的部分-检查为什么bash启动会很缓慢。 如果你只是运行bash ,它会启动一个非登录,交互的 shell -这一个在Cygwin源/etc/bash.bashrc ,然后~/.bashrc 。 这极有可能不包括bash补,除非你的RC文件的来源之一吧。 如果您运行bash -lbash --login ),启动Cygwin Terminal (取决于你cygwin.bat ),或通过SSH登录,就会启动一个登录,交互的 shell -这将输出/etc/profile~/.bash_profile ,和前面提到的RC文件。 在/etc/profile脚本本身来源的所有可执行.sh文件中/etc/profile.d

您可以检查每一个文件需要多长时间来源。 查找这个代码/etc/profile

for file in /etc/profile.d/*.$1; do
  [ -e "${file}" ] && . "${file}"
done

其备份,然后用此替代它:

for file in /etc/profile.d/*.$1; do
  TIMEFORMAT="%3lR ${file}"
  [ -e "${file}" ] && time . "${file}"
done

启动bash ,你会看到每个文件所用的时间。 调查是需要很长时间显著数量的文件。 就我而言,这是bash_completion.shfzf.sh (FZF是模糊的取景器,一个非常好的补充bash_completion)。 现在的选择是禁用或进一步调查。 因为我想用保持fzf在bash的快捷键,我调查,发现增速放缓,优化它的来源,并提交我的补丁FZF的回购(希望它会被接受)。

现在最大的一次消费国- bash_completion.sh 。 基本上,该脚本来源/usr/share/bash-completion/bash_completion 。 我备份该文件,然后修改它。 在最后一页上有for循环,源中的所有文件compat DIR - /etc/bash_completion.d 。 同样,我增加TIMEFORMATtime ,以及锯哪个脚本是造成慢启动。 这是zzz-fzffzf包)。 我一查,发现一个子shell( $()中)被执行多次for循环,改写了该部分不使用子shell,使脚本工作迅速。 我已经提交了我的补丁FZF的回购。

所有这些放缓最大的原因是: fork不受Windows过程模型的支持,Cygwin的表现非常出色模仿它,但比起真正的UNIX它是痛苦的缓慢。 这本身确实很少的工作子外壳或管道花费大部分的执行时间fork -ing。 例如,比较的执行时间time echo msg (0.000s我的Cygwin)对time echo $(echo msg)在我的Cygwin 0.042s) -白天和黑夜。 该echo命令本身不带任何可观的时间来执行,但创建一个子shell是非常昂贵的。 在我的Linux系统,这些命令采取分别0.000s和0.001S。 许多软件包的Cygwin已经被谁使用Linux或其它UNIX人开发的,可以在Cygwin未修改运行。 所以很自然,这些开发者随意使用子shell,管道等功能方便的地方,因为他们不觉得他们的系统上的任何显著的性能损失,但在Cygwin的shell脚本可能会遇到几十几百倍慢。

底线,如果一个shell脚本慢腾腾Cygwin中-尝试找到源fork调用和重写剧本,以消除他们尽可能多地。 例如cmd="$(printf "$1" "$2")"用来子shell一个叉)可以替换printf -v cmd "$1" "$2"

男孩,就出来了很长的。 任何人还阅读了这里是真正的英雄。 谢谢 :)



Answer 4:

我知道这是一个古老的线程,但在新的这周我还是有这个问题安装Cygwin的。

相反亲手挑选所有bash_completion文件的,我用这条线来实现@ me_and对那不是我的机器上安装任何东西的方法。 这显著减少庆典的启动时间对我来说。

/etc/bash_completion.d ,执行以下命令:

for i in $(ls|grep -v /); do type $i >/dev/null 2>&1 || mv $i $i.bak; done


Answer 5:

在旧的帖子有新的答案,涉及到PATH原来的问题的。

大多数其他的答案应付的bash启动。 如果你看到一个缓慢的加载时间,当你运行bash -i外壳内,它们可以适用。

就我而言, bash -i跑得快,但只要我开了一个新的shell(无论是在终端或xterm中),花了很长一段时间。 如果bash -l花费很长的时间,这意味着它的登录时间。

有在Cygwin的常见问题解答一些方法https://cygwin.com/faq/faq.html#faq.using.startup-slow但他们没有为我工作。

楼主问的PATH ,这是他用诊断bash -x 。 我也发现,虽然bash -i很快, bash -xl缓慢,表现出了许多关于信息PATH

有这样一个可笑的长窗PATH的登录过程中保持上运行的程序和搜索整个PATH的正确程序。

我的解决办法:编辑Windows PATH删除任何多余的。 我不知道我删除这一块做的伎俩,但登录shell启动时从6秒就到1秒以内。

因人而异。



Answer 6:

我的答案是一样的NPE的上方。 但是,因为我刚刚加入,我不能评论,甚至给予好评吧! 我希望这篇文章,因为它为寻找一个答案,同样的问题,提供放心不会被删除。

NPE的解决方案为我工作。 这里只有一个警告 - 我不得不关闭所有cygwin的过程之前,我得到了最好的出来。 这包括运行cygwin的服务,如sshd的,和SSH代理,我从我的登录脚本启动。 在此之前,为cygwin的终端窗口会立即出现,但挂几秒钟就给出了提示之前。 它在关闭窗口挂几秒钟。 之后,我杀死了所有的过程和启动cygserver服务(顺便说一句,我宁愿使用Cygwin的方式 - “cygrunsrv -S cygserver”,不是“NET START cygserver”;我不知道这有什么实际差别)立即启动。 因此,由于再次NPE!



Answer 7:

我是一个企业网络与一个相当复杂的设置上,它似乎是真的杀死Cygwin的启动时间。 有关NPE的回答,我也只好跟着一些在这里布局的步骤: https://cygwin.com/faq/faq.html#faq.using.startup-slow

对AD的客户端系统的另一个原因是慢DC答复,在与远程DC访问配置通常观察到的。 Cygwin的DLL查询大约每隔你在填充在启动时的本地缓存组的信息。 您可能会加速这个过程有点通过缓存在本地文件自己的信息。 与写访问到/ etc运行在一个Cygwin的终端这些命令:

getent passwd的$(ID -u)> / etc / passwd中getent组$(ID -G)>的/ etc /组

此外,设置/etc/nsswitch.conf中,如下所示:

passwd文件:文件DB组:文件DB

这将限制需要Cygwin来接触所述AD域控制器(DC),同时仍然允许的附加信息将被从DC,检索这样列出远程目录时。

这样做,再加上启动cygserver后,我的cygwin的启动时间显著回落。



Answer 8:

这实在不是一个问题,因为在第二根i7处理器和固态硬盘的加载时间2秒其实很正常。 的更长的加载时间比本机Linux bash外壳罪魁祸首是/etc/bash_completion这是作为Cygwin包的一部分。 因此,这是在cygwin特定问题。 我可能是完全错误的位置,但是从我所看到的,每个程序安装的通过安装程序安装正在分析。 更多的讨论是怎么回事这里 。



Answer 9:

正如有人如上所述,一个可能的问题是PATH环境变量中包含了太多的路径下,cygwin会搜索所有的人。 我更喜欢直接编辑/ etc / profile文件,只是简单地覆盖PATH变量Cygwin的相关路径,例如PATH="/usr/local/bin:/usr/bin" 。 如果你想添加其他路径。



Answer 10:

我写了一个名为“minimizecompletion”灭活不需要完成脚本Bash的功能。

完成脚本可以添加多个规格完成或有壳buildins完成的规格,因此不足以比较$ PATH中找到的可执行文件脚本名称。

我的解决方法是删除所有加载完成的规格,装载完成脚本,并检查其是否添加了新的补全规范。 根据这一点,是通过添加.bak的脚本文件名灭活或者是通过去除.bak的激活。 这样做对/etc/bash_completion.d结果所有182个脚本36个活跃和不活跃146完成脚本减少猛砸了50%开始时间(但应该很清楚这取决于安装的软件包)。

该功能还检查灭活完成脚本,以便它可以激活他们需要新安装了Cygwin包时他们。 所有的变化可以激活所有脚本参数-a被撤销。

# Enable or disable global completion scripts for speeding up Bash start.
#
# Script files in directory '/etc/bash_completion.d' are inactived
# by adding the suffix '.bak' to the file name; they are activated by
# removing the suffix '.bak'. After processing all completion scripts
# are reloaded by calling '/etc/bash_completion'
#
# usage:  [-a]
#         -a  activate all completion scripts
# output: statistic about total number of completion scripts, number of
#         activated, and number of inactivated completion scripts; the
#         statistic for active and inactive completion scripts can be
#         wrong when 'mv' errors occure
# return: 0   all scripts are checked and completion loading was
#             successful; this does not mean that every call of 'mv'
#             for adding or removing the suffix was successful
#         66  the completion directory or loading script is missing
#
minimizecompletion() {
  local arg_activate_all=${1-}
  local completion_load=/etc/bash_completion
  local completion_dir=/etc/bash_completion.d

  (
    # Needed for executing completion scripts.
    #
    local UNAME='Cygwin'
    local USERLAND='Cygwin'
    shopt -s extglob progcomp
    have() {
      unset -v have
      local PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"
      type -- "$1" &>/dev/null && have='yes'
    }

    # Print initial statistic.
    #
    printf 'Completion scripts status:\n'
    printf '  total:       0\n'
    printf '  active:      0\n'
    printf '  inactive:    0\n'
    printf 'Completion scripts changed:\n'
    printf '  activated:   0\n'
    printf '  inactivated: 0\n'

    # Test the effect of execution for every completion script by
    # checking the number of completion specifications after execution.
    # The completion scripts are renamed depending on the result to
    # activate or inactivate them.
    #
    local completions total=0 active=0 inactive=0 activated=0 inactivated=0
    while IFS= read -r -d '' f; do
      ((++total))
      if [[ $arg_activate_all == -a ]]; then
        [[ $f == *.bak ]] && mv -- "$f" "${f%.bak}" && ((++activated))
        ((++active))
      else
        complete -r
        source -- "$f"
        completions=$(complete | wc -l)
        if (( $completions > 0 )); then
          [[ $f == *.bak ]] && mv -- "$f" "${f%.bak}" && ((++activated))
          ((++active))
        else
          [[ $f != *.bak ]] && mv -- "$f" "$f.bak" && ((++inactivated))
          ((++inactive))
        fi
      fi
      # Update statistic.
      #
      printf '\r\e[6A\e[15C%s' "$total"
      printf '\r\e[1B\e[15C%s' "$active"
      printf '\r\e[1B\e[15C%s' "$inactive"
      printf '\r\e[2B\e[15C%s' "$activated"
      printf '\r\e[1B\e[15C%s' "$inactivated"
      printf '\r\e[1B'
    done < <(find "$completion_dir" -maxdepth 1 -type f -print0)

    if [[ $arg_activate_all != -a ]]; then
      printf '\nYou can activate all scripts with %s.\n' "'$FUNCNAME -a'"
    fi
    if ! [[ -f $completion_load && -r $completion_load ]]; then
      printf 'Cannot reload completions, missing %s.\n' \
             "'$completion_load'" >&2
      return 66
    fi
  )

  complete -r
  source -- "$completion_load"
}

这是一个示例输出,所得倍:

$ minimizecompletion -a
Completion scripts status:
  total:       182
  active:      182
  inactive:    0
Completion scripts changed:
  activated:   146
  inactivated: 0

$ time bash -lic exit
logout

real    0m0.798s
user    0m0.263s
sys     0m0.341s

$ time minimizecompletion
Completion scripts status:
  total:       182
  active:      36
  inactive:    146
Completion scripts changed:
  activated:   0
  inactivated: 146

You can activate all scripts with 'minimizecompletion -a'.

real    0m17.101s
user    0m1.841s
sys     0m6.260s

$ time bash -lic exit
logout

real    0m0.422s
user    0m0.092s
sys     0m0.154s


文章来源: Slow load time of bash in cygwin