Você encontrou um bug na biblioteca Bash Completion usada pelo Ubuntu.
O que isto significa?
O Ubuntu usa uma biblioteca de conclusão do bash para torná-lo inteligente. Esta biblioteca mora /usr/share/bash-completion/bash_completion
.
Essencialmente, esta biblioteca declara algumas funções inteligentes que sabem sobre comandos típicos e como concluí-los. Sempre que você pressiona Tab, as funções desta biblioteca são chamadas e tentam concluir sua linha de comando atual. Por exemplo, se você digitar, apt-get i
Tabisso será concluído apt-get install
. Se você não obtiver a fonte dessa biblioteca, terá apenas a conclusão padrão e primitiva do bash - por exemplo, se você digitar apt-get i
Tabsem a ter originado, o bash simplesmente procurará arquivos no diretório atual começando com i
e tentará concluir seu comando de acordo com esses nomes de arquivos.
Por que isso não está acontecendo como raiz?
Porque quando você usa sudo su
para fazer a si mesmo root
, a biblioteca de conclusão do bash não é originada. Isso seria diferente se você costumava sudo -i
fazer a si mesmo root
. Aposto que você vê o bug, não é? Veja, por exemplo, 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash' - quando importa o que é usado ou importa? se você não estiver familiarizado com as diferenças.
No meu caso, como usuário normal, a biblioteca é originada quando eu inicio um shell Bash porque ~/.bashrc
origina /etc/bash_completion
quais origens /usr/share/bash-completion/bash_completion
.
Se eu usar o sudo -i
login como root
, a biblioteca será originada porque /etc/profile
origina /etc/profile.d/bash_completion.sh
quais origens /usr/share/bash-completion/bash_completion
.
Por que esse bug está acontecendo?
Tente executar este comando:
$ eval 'quoted=$(cat' env.
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file
Parece familiar? ;-) De fato, foi exatamente o que aconteceu nos bastidores quando você acessou Tabo contexto que descreveu. Mais precisamente, o bug está na função _quote_readline_by_ref
declarada por /usr/share/bash-completion/bash_completion
. Se você originou esse arquivo, deveria ter essa função disponível. Então, tente o seguinte:
$ _quote_readline_by_ref '$(cat env.' quoted
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file
Diante desses argumentos, a função _quote_readline_by_ref
executa, entre outras coisas, a eval
mencionada acima. Você pode dar uma olhada, se quiser. E quando você digitou env $(cat env.
Tab, nos bastidores, essa função foi chamada exatamente com esses argumentos. Então foi o que aconteceu.
Este eval
truque deveria corrigir outro problema , mas acho que introduziu esse outro bug no processo.
Como faço para corrigir isso?
Acontece que esse bug já foi relatado . Depois de ler o relatório de erros, vejo três maneiras de corrigi-lo:
Corrigir: em um dos comentários nesse relatório de bug, alguém sugere substituir a linha
[[ ${!2} == \$* ]] && eval $2=${!2}
dentro da função _quote_readline_by_ref
no arquivo /usr/share/bash-completion/bash_completion
pela linha
[[ ${!2} == \$\'* ]] && eval $2=${!2}
Eu recomendo não fazer isso. A pessoa que escreveu esse comentário não parece ser um desenvolvedor de conclusão do bash . Esse hotfix simplesmente fará com que o operando esquerdo da instrução seja avaliado como falso e, assim, evite que isso eval
aconteça. No entanto, sem um bom conhecimento do que essa função deve fazer e em quais contextos ela é chamada, não está claro se isso não irá potencialmente quebrar alguma outra funcionalidade pretendida.
Obtenha a versão mais recente: Como também mencionado no relatório de erros, esse bug não está presente no git head (em que, entre outras alterações, a função _quote_readline_by_ref
foi simplificada). Você pode simplesmente clonar a revisão atual do Git:
git clone https://salsa.debian.org/debian/bash-completion.git
... e copie a versão mais recente do bash_completion
script para /usr/share/bash-completion
(não há necessidade urgente de fazer backup da versão antiga, a menos que isso a faça se sentir mais segura - se você tiver alguns problemas, sudo apt-get install --reinstall bash-completion
deve reverter todas as alterações feitas.) recomendo se você estiver com pressa para corrigir isso. :-)
Observe que nenhuma dessas soluções fará com que a conclusão do bash dentro da substituição de comandos funcione: conforme mencionado no mesmo relatório de erros, isso está quebrado no Bash 4.3.
- Sente-se e espere: mais cedo ou mais tarde, uma nova versão será lançada (o que pode até corrigir a conclusão do bash na substituição de comandos) e você a obterá em alguma versão futura do Ubuntu. É para isso que eu estou indo ;-)