如果启用了自动完成功能,Shell 将不会给出任何提示(而是闪烁光标)

如果启用了自动完成功能,Shell 将不会给出任何提示(而是闪烁光标)

我尝试通过取消注释以下几行来启用 shell 自动完成功能.bashrc

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /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

然而,这有副作用。尽管自动完成功能似乎有效,但当我打开一个新终端时,只会出现一个闪烁的光标:

在此处输入图片描述

user@machine:~$按下 后我才返回到通常的提示Ctrl+C

如果我注释掉以上几行,就会恢复正常行为(但不再有自动完成功能)。

我不明白问题是什么。

--更新 1--

代码的作用如下:

在此处输入图片描述

--更新 2--

这是建议命令的输出。有些东西不断循环,终端被输出淹没。

++++++ : /etc/bash_completion.d
++++++ readonly BASH_COMPLETION_COMPAT_DIR
++++++ _blacklist_glob='@(acroread.sh)'
++++++ shopt -s extglob progcomp
++++++ complete -d pushd
++++++ complete -u write chfn groups slay w sux runuser
++++++ complete -A stopped -P '"%' -S '"' bg
++++++ complete -j -P '"%' -S '"' fg jobs disown
++++++ complete -v readonly unset
++++++ complete -A setopt set
++++++ complete -A shopt shopt
++++++ complete -A helptopic help
++++++ complete -a unalias
++++++ complete -A binding bind
++++++ complete -c command type which
++++++ complete -b builtin
++++++ [[ linux-gnu == *@(solaris|aix)* ]]
++++++ [[ linux-gnu == *@(solaris|aix)* ]]
++++++ [[ linux-gnu == *@(solaris|aix)* ]]
++++++ _backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'
++++++ complete -F _service service
++++++ _sysvdirs
++++++ sysvdirs=()
++++++ [[ -d /etc/rc.d/init.d ]]
++++++ [[ -d /etc/init.d ]]
++++++ sysvdirs+=(/etc/init.d)
++++++ [[ -f /etc/slackware-version ]]
++++++ for svcdir in '${sysvdirs[@]}'
++++++ for svc in '$svcdir/!($_backup_glob)'
++++++ [[ -x /etc/init.d/acpid ]]
++++++ complete -F _service /etc/init.d/acpid
++++++ for svc in '$svcdir/!($_backup_glob)'
++++++ [[ -x /etc/init.d/anacron ]]
++++++ complete -F _service /etc/init.d/anacron
++++++ for svc in '$svcdir/!($_backup_glob)'
++++++ [[ -x /etc/init.d/apparmor ]]

--更新 3--

这是所要求的输出:

ac@ac:~$ grep -r bash_completion /etc/bash_completion.d
/etc/bash_completion.d/bash.bashrc:#  if [ -f /usr/share/bash-completion/bash_completion ]; then
/etc/bash_completion.d/bash.bashrc:#    . /usr/share/bash-completion/bash_completion
/etc/bash_completion.d/bash.bashrc:#  elif [ -f /etc/bash_completion ]; then
/etc/bash_completion.d/bash.bashrc:#    . /etc/bash_completion
/etc/bash_completion.d/bash.bashrc.bak:#  if [ -f /usr/share/bash-completion/bash_completion ]; then
/etc/bash_completion.d/bash.bashrc.bak:#    . /usr/share/bash-completion/bash_completion
/etc/bash_completion.d/bash.bashrc.bak:#  elif [ -f /etc/bash_completion ]; then
/etc/bash_completion.d/bash.bashrc.bak:#    . /etc/bash_completion
/etc/bash_completion.d/inkscape:# put this file in /etc/bash_completion.d/ 
/etc/bash_completion.d/desktop-file-validate:# put this file in /etc/bash_completion.d/
/etc/bash_completion.d/bash_completion~:. /usr/share/bash-completion/bash_completion
/etc/bash_completion.d/git-completion.bash:#   bash_completion - programmable completion functions for bash 3.2+
/etc/bash_completion.d/libreoffice.sh:# Programmable bash_completion file for the main office applications
/etc/bash_completion.d/bash_completion:# . /usr/share/bash-completion/bash_completion

确实,最后一行显示了您所预测的内容。但我不知道如何处理该文件:我应该删除它,还是我错误地覆盖了它?如果是这样,原始内容是什么?

答案1

您得到的输出set -x包含很多加号 ( ++++++),这意味着/usr/share/bash-completion/bash_completion正在以递归方式重新获取资源。

换句话说,/usr/share/bash-completion/bash_completion正在“呼叫”自己,导致一种无限循环,正如您注意到的。

如果我是你,我会检查/etc/bash_completion.d寻找参考/usr/share/bash-completion/bash_completion。具体来说,我会这样做:

  1. ls -l /etc/bash_completion.d(不得有​​符号链接到/usr/share/bash-completion/bash_completion(英文):
  2. grep -r bash_completion /etc/bash_completion.d(没有文件在/etc/bash_completion.d应该来源/usr/share/bash-completion/bash_completion)。

或者,你可以在 shell 中运行这两个命令(当然,没有启用 bash 完成功能):

set -x
. /usr/share/bash-completion/bash_completion |& grep -E "^\++ (\.|source)"

这将打印所有“导入”,并帮助我们识别导致问题的令人讨厌的代码片段。


从输出中grep -r bash_completion /etc/bash_completion.d你可以看到很多匹配项。它们大多数都是注释(因为它们以 开头#),但有一行很有趣:

/etc/bash_completion.d/bash_completion~:. /usr/share/bash-completion/bash_completion

/etc/bash_completion.d/bash_completion~是罪魁祸首。这是导致递归资源的文件。

/usr/share/bash-completion/bash_completion事实上会自动获取/etc/bash_completion.d目录。但对于你的情况,这个目录包含bash_completion〜文件,即采购/usr/share/bash-completion/bash_completion再次。这会导致您遇到的那种循环。

因此请继续删除它!

sudo rm /etc/bash_completion.d/bash_completion~

(或者如果您认为它包含一些有用的东西,也许可以阅读它。)

我无法告诉你为什么该文件位于该目录中。我能告诉你的是,后缀~表示这是一个备份文件。许多文本编辑器(包括 Gedit)在保存时都会创建备份副本。可能是你在进行更改时不小心把它留在那里了。

答案2

为了调试,您可以添加几echo行代码来查看代码执行情况。我假设它在某个地方中断了,但声音不会很大。

用类似下面的内容替换它:

 if ! shopt -oq posix; then
   echo Entering bash-completion load
   if [ -f /usr/share/bash-completion/bash_completion ]; then
     echo Sourcing /usr/share/bash-completion/bash_completion
     . /usr/share/bash-completion/bash_completion
     echo Sourced
   elif [ -f /etc/bash_completion ]; then
     echo Sourcing /etc/bash_completion
     . /etc/bash_completion
     echo Sourced
   fi
 fi
 echo Done

在理想世界中你会看到:

Entering bash-completion load
Sourcing /usr/share/bash-completion/bash_completion
Sourced
Done

如果它陷入了 bash_completion 脚本,请打开调试并手动获取它(假设您的终端仍然有效):

set -x
. /usr/share/bash-completion/bash_completion

这应该输出直到它中断(或退出)为止的内容,并且应该为您提供有关实际问题的另一个指标。

相关内容