Você encontrou um bug na biblioteca Bash Completion usada pelo Ubuntu.
O que isso significa?
O Ubuntu usa uma biblioteca de conclusão bash para tornar a conclusão do bash inteligente. Esta biblioteca vive em /usr/share/bash-completion/bash_completion
.
Essencialmente, esta biblioteca declara algumas funções inteligentes que conhecem os comandos típicos e como completá-los. Sempre que você pressionar Tab , as funções dentro desta biblioteca serão chamadas e tentarão completar sua linha de comando atual. Então, por exemplo, se você digitar apt-get i
Tab , ele completará isso em apt-get install
. Se você não fonte dessa biblioteca, você só tem o bash padrão, primitivo - assim, por exemplo, se você digitar apt-get i
Tab sem ter originado, o bash simplesmente procurará por arquivos no arquivo atual. diretório começando com i
e tente completar seu comando de acordo com esses nomes de arquivo.
Por que isso não está acontecendo como root?
Porque quando você usa sudo su
para se tornar root
, a biblioteca de conclusão bash não é originada. Isso seria diferente se você usasse sudo -i
para se tornar root
. Eu aposto que você vê o inseto então, não é? Veja por exemplo 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash' - quando importa qual é usado, ou importa mesmo? se você não estiver familiarizado com o diferenças.
No meu caso, como um usuário normal, a biblioteca é originada quando eu inicio um shell Bash porque ~/.bashrc
sources /etc/bash_completion
que origina /usr/share/bash-completion/bash_completion
.
Se eu usar sudo -i
para fazer login como root
, a biblioteca será originada porque /etc/profile
sources /etc/profile.d/bash_completion.sh
, que origina /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 isso que aconteceu nos bastidores quando você clicou em Tab no contexto que você descreveu. Mais precisamente, o erro está na função _quote_readline_by_ref
declarada por /usr/share/bash-completion/bash_completion
. Se você comprou esse arquivo, você deve ter essa função disponível. Então, tente isso:
$ _quote_readline_by_ref '$(cat env.' quoted
bash: unexpected EOF while looking for matching ')'
bash: syntax error: unexpected end of file
Com esses argumentos, a função _quote_readline_by_ref
executa, entre outras coisas, 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
hack deveria corrigir outro problema , mas acho que ele introduziu esse outro bug no processo.
Como corrijo isso?
Acontece que esse bug já foi denunciado . Depois de ler esse relatório de bug, vejo três maneiras de corrigi-lo:
-
Patch it: Em um dos comentários do relatório de bug, alguém sugere a substituição da 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 não recomendo fazer isso. A pessoa que escreveu esse comentário não aparece para ser um desenvolvedor do bash-completion . Esse hotfix simplesmente fará com que o operando à esquerda da instrução seja avaliado como false, evitando assim que
eval
ocorra. No entanto, sem um bom conhecimento do que essa função deve fazer e em que 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 bug, este bug não está presente no git head (em que entre outras mudanças 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 script
bash_completion
para/usr/share/bash-completion
(sem necessidade urgente de fazer backup da versão antiga, a menos que você se sinta mais seguro - se tiver alguns problemas,sudo apt-get install --reinstall bash-completion
deve reverter qualquer mudanças que você fez muito bem.) Esta é a maneira que eu recomendo se você está com pressa para consertar isso. : -)
Note que nenhuma dessas soluções fará o bash completion dentro do trabalho de substituição de comandos: como mencionado no mesmo relatório de bugs, 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é consertar a conclusão do bash dentro da substituição de comandos) e você a obterá com alguma versão futura do Ubuntu. É para isso que eu vou;)