For*_*ker 18 debugging bash cygwin bash-completion
目前bash需要大约2秒才能加载.我用-x旗帜运行bash,我看到输出,似乎PATH在cygwin中被多次加载.有趣的是我在linux环境中使用相同的文件,但它工作正常,没有重载问题.以下可能导致问题吗?
if [ `uname -o` = "Cygwin" ]; then
....
fi
Run Code Online (Sandbox Code Playgroud)
me_*_*and 21
正如您在答案中所提到的,问题是Cygwin的bash-completion包.快速简便的解决方法是禁用bash-completion,正确的方法是运行Cygwin的setup.exe(如果需要,再次下载)并选择卸载该软件包.
更长的解决方案是处理文件/etc/bash_completion.d并禁用您不需要的文件.在我的系统上,减慢Bash加载时间的最大罪魁祸首(mailman,shadow,dsniff和e2fsprogs)都没有做任何事情,因为他们创建完成的工具没有安装.
如果您将文件重命名/etc/bash_completion.d为具有.bak扩展名,则会停止加载该脚本.除了以这种方式在我的一个系统上禁用了所有37个脚本之外,我已经将bash_completion的平均加载时间减少了95%(6.5秒到0.3秒).
npe*_*npe 14
在我的情况下,这是Windows域控制器.我这样做是为了找到问题:
我从一个简单的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...
Run Code Online (Sandbox Code Playgroud)
关键是确定client_request::make_request: cygserver un-available线.你可以看到,在此之后,cygwin试图从windows中获取每个组,并且执行时间变得疯狂.
快速谷歌透露了什么cygserver是:https:
//cygwin.com/cygwin-ug-net/using-cygserver.html
Cygserver是一个旨在作为后台服务运行的程序.它为Cygwin应用程序提供了需要安全仲裁的服务,或者在没有其他cygwin应用程序运行时需要持久保存的服务.
解决方案是,运行cygserver-config然后net start cygserver启动Windows服务.之后,Cygwin的启动时间显着下降.
所有答案都指向较旧的bash_completion版本,与最新版本无关bash_completion。
Modern bash_completion默认将大多数完成文件移动到/usr/share/bash-completion/completions,通过运行以下命令检查系统上的路径
# pkg-config --variable=completionsdir bash-completion
/usr/share/bash-completion/completions
Run Code Online (Sandbox Code Playgroud)
那里有很多文件,每个命令一个文件,但这不是问题,因为它们是在您第一次对每个命令使用完成时按需加载的。/etc/bash_completion.d仍然支持旧版本的兼容性,并且bash_completion启动时会加载旧版本中的所有文件。
# pkg-config --variable=compatdir bash-completion
/etc/bash_completion.d
Run Code Online (Sandbox Code Playgroud)
使用此脚本检查旧目录中是否还有任何过时的文件。
#!/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
Run Code Online (Sandbox Code Playgroud)
它打印compat目录中的文件列表,这些文件也存在于较新的(按需)完成目录中。除非有特殊原因要保留其中一些文件,否则请查看,备份并删除所有这些文件。
结果,compat目录应该大部分为空。
现在,对于最有趣的部分-检查bash启动缓慢的原因。如果您只是运行bash,它将启动一个非登录的交互式外壳程序-该程序在Cygwin源代码上/etc/bash.bashrc,然后在~/.bashrc。这很可能不包括bash补全,除非您从rc文件之一中获取它。如果你运行bash -l(bash --login),启动Cygwin Terminal(取决于你cygwin.bat),或登录通过SSH,就会启动一个登录,互动的外壳-这将输出/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
Run Code Online (Sandbox Code Playgroud)
备份它,然后替换为:
for file in /etc/profile.d/*.$1; do
TIMEFORMAT="%3lR ${file}"
[ -e "${file}" ] && time . "${file}"
done
Run Code Online (Sandbox Code Playgroud)
单击开始bash,您将看到每个文件花费了多长时间。调查花费大量时间的文件。就我而言,它是bash_completion.sh和fzf.sh(fzf是模糊查找器,是对bash_completion的非常好的补充)。现在的选择是禁用它或进一步调查。由于我想继续fzf在bash中使用快捷方式,因此我进行了调查,找到了减速的源头,对其进行了优化,然后将补丁提交给了fzf的仓库(希望它会被接受)。
现在是最大的花费时间- bash_completion.sh。基本上就是脚本源/usr/share/bash-completion/bash_completion。我备份了该文件,然后对其进行了编辑。在最后一页上,存在for循环,该循环在compatdir-中提供所有文件/etc/bash_completion.d。再次,我添加了TIMEFORMAT和time,然后查看是哪个脚本导致启动缓慢。是zzz-fzf(fzf包)。我进行了调查,发现一个子shell($())在一个for循环中被执行了多次,无需使用子shell就重写了该部分,从而使脚本可以快速工作。我已经将补丁提交给fzf的仓库。
所有这些速度下降的最大原因是:forkWindows进程模型不支持Cygwin在模拟它方面做得很好,但是与真正的UNIX相比,它的速度非常慢。仅执行很少工作的子外壳程序或管道就将其大部分执行时间用于fork-ing。例如,比较time echo msg(Cygwin上的0.000s)和time echo $(echo msg)(Cygwin上的0.042s )的执行时间-日夜。的echo命令本身不需要花费很多时间来执行,但是创建子外壳非常昂贵。在我的Linux系统上,这些命令分别花费0.000s和0.001s。Cygwin的许多软件包都是由使用Linux或其他UNIX的人开发的,并且可以在未经修改的Cygwin上运行。因此,这些开发人员自然会在方便的地方随意使用子shell,管道和其他功能,因为他们不会觉得系统性能有任何显着降低,但是在Cygwin上,这些shell脚本的运行速度可能慢几十倍甚至数百倍。
底线是,如果Shell脚本在Cygwin中运行缓慢,请尝试查找fork调用源并重写脚本以尽可能消除它们。例如cmd="$(printf "$1" "$2")"(用一个前叉作为子壳)可以替换为printf -v cmd "$1" "$2"。
男孩,它出来的时间很长。仍然在这里读书的任何人都是真正的英雄。谢谢 :)