Conclusão da guia Bash: '-bash: EOF inesperado ao procurar o correspondente') '-bash: erro de sintaxe: final inesperado do arquivo

18

Estou tentando entrar em uma irbsessão com variáveis ​​de ambiente específicas de um arquivo com este comando:

$ env $(cat env.sh) irb

Mas quando tento pressionar Tabdepois de digitar env.para concluí-lo, recebo o seguinte erro:

$ env $(cat env.-bash: unexpected EOF while looking for matching `)'
-bash: syntax error: unexpected end of file

Outra coisa interessante é que, se eu estiver logado como root, esse erro não ocorrerá.

Aqui está a saída de 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

Alguém pode me explicar por que isso está acontecendo? Em caso afirmativo, como corrigi-lo quando não sou um usuário root?

eldosoa
fonte
Como você efetua login como root?
muru
@ muru Entrei no root usando sudo su.
eldosoa
Edite sua pergunta para adicionar a saída de find ~ -uid 0.
muru
@muru Concluído. Adicionado a saída na minha pergunta.
eldosoa
Desculpe por isso, mas não como raiz! Eu quis dizer como seu usuário normal, então ~é isso /home/something.
muru

Respostas:

33

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 iTabisso 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 iTabsem a ter originado, o bash simplesmente procurará arquivos no diretório atual começando com ie 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 supara fazer a si mesmo root, a biblioteca de conclusão do bash não é originada. Isso seria diferente se você costumava sudo -ifazer 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 ~/.bashrcorigina /etc/bash_completionquais origens /usr/share/bash-completion/bash_completion.

Se eu usar o sudo -ilogin como root, a biblioteca será originada porque /etc/profileorigina /etc/profile.d/bash_completion.shquais 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_refdeclarada 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_refexecuta, entre outras coisas, a evalmencionada 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 evaltruque 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:

  1. 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_refno arquivo /usr/share/bash-completion/bash_completionpela 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 evalaconteç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.

  2. 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_reffoi 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_completionscript 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-completiondeve 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.

  1. 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 ;-)
Malte Skoruppa
fonte
11
@ con-f-use Sim, é isso! O repositório Git também está vinculado no site principal de conclusão do bash, e é por isso que eu não o vinculei na minha resposta.
Malte Skoruppa
2
@ con-f-use Seu comentário me levou a fazer mais algumas pesquisas sobre esse bug. Acontece que não é, e nunca foi, um bug do upstream. Em vez disso, é na verdade um bug introduzido por um patch do Ubuntu aplicado à versão upstream. Parece que ninguém reduziu esse bug a esse patch específico até o momento. Então, eu relatei minha descoberta no relatório de bug correspondente do Ubuntu: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Bom trabalho, Malte.
Barry Kelly
11
Obrigada pelo esclarecimento. Até o momento em que este artigo foi escrito, a versão do git head removeu o bug e o preenchimento automático conforme desejado. EDIT: na verdade, deixa pra lá, isso não acontece.
user3391564
11
@MaxvonHippel Eu disse que quando você sudo suse torna root, ela não gera a biblioteca, mas será obtida quando você o usa sudo -i, que é a maneira pretendida de obter uma sessão raiz interativa. Quanto à sua pergunta: como qualquer shell bash lê, o ~/.bashrcque eventualmente origina a biblioteca, e não há como "cancelar a fonte" de um arquivo, não vejo uma maneira completamente direta. Aqui está um possível corte: Faça o fornecimento da condicional biblioteca em alguma variável de ambiente, por exemplo, NOCOMPL, não sendo definida no seu ~/.bashrc...
Malte Skoruppa