irb
我正在尝试使用以下命令从文件中进入具有特定环境变量的会话:
$ env $(cat env.sh) irb
但是当我输入完成Tab
后尝试按下时,出现以下错误:env.
$ env $(cat env.-bash: unexpected EOF while looking for matching `)'
-bash: syntax error: unexpected end of file
另一件有趣的事情是,如果我以 root 身份登录,则不会发生此错误。
以下是 的输出find ~ -uid 0
:
$ find ~ -uid 0
/home/(redacted)/.rpmdb
/home/(redacted)/.rpmdb/Group
/home/(redacted)/.rpmdb/Conflictname
/home/(redacted)/.rpmdb/Installtid
/home/(redacted)/.rpmdb/Sha1header
/home/(redacted)/.rpmdb/Providename
/home/(redacted)/.rpmdb/__db.002
/home/(redacted)/.rpmdb/Requirename
/home/(redacted)/.rpmdb/Sigmd5
/home/(redacted)/.rpmdb/__db.001
/home/(redacted)/.rpmdb/Obsoletename
/home/(redacted)/.rpmdb/.dbenv.lock
/home/(redacted)/.rpmdb/Name
/home/(redacted)/.rpmdb/Basenames
/home/(redacted)/.rpmdb/Triggername
/home/(redacted)/.rpmdb/Packages
/home/(redacted)/.rpmdb/Dirnames
/home/(redacted)/.rpmdb/__db.003
有人能向我解释为什么会发生这种情况吗?如果是这样,当我不是 root 用户时,我该如何解决这个问题?
答案1
你发现了一个错误Bash 补全Ubuntu 使用的库。
这是什么意思?
Ubuntu 使用 bash 补全库来使 bash 补全变得智能。此库位于/usr/share/bash-completion/bash_completion
。
本质上,这个库声明了一些聪明的函数,它们知道典型的命令以及如何完成它们。每当您按下 时Tab,这个库中的函数就会被调用并尝试完成您当前的命令行。例如,如果您输入apt-get i
Tab它将完成apt-get install
。如果您不 source 该库,您只能使用标准的、原始的 bash 完成 - 例如,如果您输入apt-get i
Tab而不 source 它,bash 将简单地在当前目录中查找以 开头的文件i
并尝试根据这些文件名完成您的命令。
为什么它不能以 root 身份发生?
因为当你使用sudo su
make yourself时,bash 完成库不会被引用。如果你使用make yourself root
,情况会有所不同。我敢打赌你会看到这个错误,不是吗?例如sudo -i
root
'sudo su -' 与 'sudo -i' 与 'sudo /bin/bash' - 什么时候使用哪个重要,或者根本不重要吗?如果您不熟悉其中的区别。
就我而言,作为普通用户,当我启动 Bash shell 时,该库就会被获取,因为~/.bashrc
来源/etc/bash_completion
是哪些来源/usr/share/bash-completion/bash_completion
。
如果我使用sudo -i
以 身份登录root
,则库将获取来源,因为/etc/profile
来源/etc/profile.d/bash_completion.sh
是 哪些来源/usr/share/bash-completion/bash_completion
。
为什么会发生这个错误?
尝试执行这个命令:
$ eval 'quoted=$(cat' env.
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file
看起来很熟悉?;-) 事实上,这正是您在描述的上下文中遇到时幕后发生的事情Tab。更准确地说,错误是在_quote_readline_by_ref
声明的函数中/usr/share/bash-completion/bash_completion
。如果您获取该文件,则应该可以使用该函数。接下来尝试以下操作:
$ _quote_readline_by_ref '$(cat env.' quoted
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file
给定这些参数,该函数_quote_readline_by_ref
将执行上述操作eval
。您可以查看一下。当您输入 时env $(cat env.
Tab,该函数会在后台使用那些参数被调用。这就是发生的事情。
这次eval
黑客攻击本来应该修复另一个问题,但我猜测它在过程中引入了另一个错误。
我如何解决它?
事实证明这个错误已经报告读完那个错误报告后,我发现了三种修复方法:
修补:在该错误报告的一条评论中,有人建议将以下行替换为
[[ ${!2} == \$* ]] && eval $2=${!2}
_quote_readline_by_ref
在文件中的/usr/share/bash-completion/bash_completion
函数内[[ ${!2} == \$\'* ]] && eval $2=${!2}
我建议不要这样做。写这条评论的人并没有出现成为 bash-completion 的开发者。此修补程序将导致语句的左操作数计算结果为 false,从而防止这种情况
eval
发生。但是,如果不了解该函数应该做什么以及在什么上下文中调用它,就不清楚这是否可能破坏其他预期功能。获取最新版本:正如该错误报告中所述,此错误在 git head 中不存在(除其他更改外,该功能
_quote_readline_by_ref
已简化)。您可以简单地从 Git 克隆当前修订版:git clone https://salsa.debian.org/debian/bash-completion.git
...然后将
bash_completion
脚本的最新版本复制到/usr/share/bash-completion
(没有必要紧急备份旧版本,除非它让您感觉更安全 - 如果您遇到一些问题,sudo apt-get install --reinstall bash-completion
应该恢复您所做的任何更改。)如果您急于解决这个问题,这是我推荐的方法。:-)
请注意,这些解决方案都无法使命令替换中的 bash 完成功能正常工作:正如同一个错误报告中所提到的,这在 Bash 4.3 中被破坏了。
- 坐下来等待:迟早会发布新版本(甚至可能修复命令替换中的 bash 补全),您将在未来的某个 Ubuntu 版本中获得它。这就是我想要的 ;-)