Achèvement de l'onglet Bash: '-bash: EOF inattendu lors de la recherche de la correspondance `)' -bash: erreur de syntaxe: fin de fichier inattendue

18

J'essaie d'entrer dans une irbsession avec des variables d'environnement spécifiques à partir d'un fichier avec cette commande:

$ env $(cat env.sh) irb

Mais lorsque j'essaie d'appuyer sur Tabaprès avoir tapé env.pour le terminer, j'obtiens l'erreur suivante:

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

Une autre chose intéressante est que si je suis connecté en tant que root, cette erreur ne se produit pas.

Voici la sortie 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

Quelqu'un peut-il m'expliquer pourquoi cela se produit et si oui, comment puis-je le corriger lorsque je ne suis pas un utilisateur root?

eldosoa
la source
Comment vous connectez-vous en tant que root?
muru
@muru Je me suis connecté à root en utilisant sudo su.
eldosoa
Veuillez modifier votre question pour ajouter la sortie de find ~ -uid 0.
muru
@muru Done. Ajout de la sortie dans ma question.
eldosoa
Désolé, mais pas en tant que root! Je voulais dire en tant qu'utilisateur normal, donc ça l' ~est /home/something.
muru

Réponses:

33

Vous avez trouvé un bogue dans la bibliothèque de complétion de Bash utilisée par Ubuntu.

Qu'est-ce que ça veut dire?

Ubuntu utilise une bibliothèque de complétion bash pour rendre la complétion bash intelligente. Cette bibliothèque vit /usr/share/bash-completion/bash_completion.

Essentiellement, cette bibliothèque déclare quelques fonctions intelligentes qui connaissent les commandes typiques et comment les exécuter. Chaque fois que vous appuyez sur Tab, les fonctions de cette bibliothèque sont appelées et tentent de terminer votre ligne de commande actuelle. Ainsi, par exemple, si vous tapez, apt-get iTabcela se terminera apt-get install. Si vous ne sourcez pas cette bibliothèque, vous n'avez que la complétion bash primitive standard - donc par exemple si vous tapez apt-get iTabsans l'avoir obtenue, bash recherchera simplement les fichiers dans le répertoire courant en commençant par iet tentera de terminer votre commande selon ces noms de fichiers.

Pourquoi cela ne se produit-il pas en tant que root?

Parce que lorsque vous utilisez sudo supour vous fabriquer root, la bibliothèque de complétion bash n'est pas sourcée. Ce serait différent si vous vous sudo -ifaisiez vous-même root. Je parie que vous voyez le bug alors, n'est-ce pas? Voir par exemple 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash' - quand est-ce important ou qui est-il important? si vous n'êtes pas familier avec les différences.

Dans mon cas, en tant qu'utilisateur normal, la bibliothèque est sourcée lorsque je démarre un shell Bash parce que les ~/.bashrcsources sont les /etc/bash_completionsources /usr/share/bash-completion/bash_completion.

Si j'utilise sudo -ipour me connecter en tant que root, la bibliothèque est sourcée parce que les /etc/profilesources /etc/profile.d/bash_completion.shquelles sources /usr/share/bash-completion/bash_completion.

Pourquoi ce bug se produit-il?

Essayez d'exécuter cette commande:

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

Ça vous semble familier? ;-) En effet, c'est exactement ce qui s'est passé dans les coulisses lorsque vous avez frappé Tabdans le contexte que vous avez décrit. Plus précisément, le bug se trouve dans la fonction _quote_readline_by_refdéclarée par /usr/share/bash-completion/bash_completion. Si vous avez trouvé ce fichier, vous devriez avoir cette fonction disponible. Alors, essayez ceci:

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

Compte tenu de ces arguments, la fonction _quote_readline_by_refeffectue, entre autres, celle evalmentionnée ci-dessus. Vous pouvez jeter un œil si vous le souhaitez. Et lorsque vous avez tapé env $(cat env.Tab, dans les coulisses, cette fonction a été appelée avec exactement ces arguments. Voilà donc ce qui s'est passé.

Ce evalhack était censé résoudre un autre problème , mais je suppose qu'il a introduit cet autre bug dans le processus.

Comment je le répare?

Il s'avère que ce bogue a déjà été signalé . Après avoir lu ce rapport de bogue, je vois trois façons de le corriger:

  1. Corrigez-le: dans l'un des commentaires de ce rapport de bogue, quelqu'un suggère de remplacer la ligne

    [[ ${!2} == \$* ]] && eval $2=${!2}

    dans la fonction _quote_readline_by_refdans le fichier /usr/share/bash-completion/bash_completionpar la ligne

    [[ ${!2} == \$\'* ]] && eval $2=${!2}

    Je déconseille de faire cela. La personne qui a écrit ce commentaire ne semble pas être un développeur de bash-complètement . Ce correctif entraînera simplement l'opérande gauche de l'instruction à évaluer à faux et empêchera ainsi que cela se evalproduise. Cependant, sans une bonne connaissance de ce que cette fonction est censée faire et dans quels contextes elle est appelée, il est difficile de savoir si cela ne risque pas de casser certaines autres fonctionnalités prévues.

  2. Obtenez la dernière version: Comme également mentionné dans ce rapport de bogue, ce bogue n'est pas présent dans git head (dans lequel, entre autres changements, la fonction _quote_readline_by_refa été simplifiée). Vous pouvez simplement cloner la révision actuelle depuis Git:

    git clone https://salsa.debian.org/debian/bash-completion.git

    ... puis copiez la dernière version du bash_completionscript dans /usr/share/bash-completion(pas de besoin urgent de sauvegarder l'ancienne version à moins que cela ne vous rende plus en sécurité - si vous rencontrez des problèmes, sudo apt-get install --reinstall bash-completionvous devez annuler toutes les modifications que vous avez apportées.) C'est ainsi que je recommander si vous êtes pressé de résoudre ce problème. :-)

Notez qu'aucune de ces solutions ne fera fonctionner bash à l'intérieur de la substitution de commandes: comme mentionné dans ce même rapport de bogue, cela est cassé dans Bash 4.3.

  1. Asseyez-vous et attendez: Tôt ou tard, une nouvelle version sera publiée (ce qui peut même corriger l'achèvement de bash dans la substitution de commandes) et vous l'obtiendrez avec une future version d'Ubuntu. C'est ce que je veux faire ;-)
Malte Skoruppa
la source
1
@ con-f-use Yep, c'est tout! Le dépôt Git est également lié à partir du site principal de bash-complétion, c'est pourquoi je ne l'avais pas lié dans ma réponse.
Malte Skoruppa
2
@ con-f-use Votre commentaire m'a fait faire plus de recherches sur ce bug. Il s'avère que ce n'est pas, et n'a jamais été, un bug en amont. Au lieu de cela, il s'agit en fait d'un bogue introduit par un correctif Ubuntu appliqué à la version en amont. Jusqu'à présent, personne ne semble avoir réduit ce bogue à ce correctif particulier. J'ai donc signalé ma découverte dans le rapport de bogue Ubuntu correspondant: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Beau travail Malte.
Barry Kelly
1
Merci pour l'explication. Au moment d'écrire ces lignes, la version git head a supprimé le bogue et la saisie semi - automatique comme souhaité. EDIT: en fait, peu importe, ce n'est pas le cas.
user3391564
1
@MaxvonHippel J'ai dit que lorsque vous utilisez sudo supour devenir root, il ne source pas la bibliothèque, mais il sera sourcé lorsque vous l'utiliserez à la sudo -iplace, ce qui est le moyen prévu pour obtenir une session root interactive. Quant à votre question: étant donné que tout shell bash lit ~/.bashrcqui finit par sources la bibliothèque, et qu'il n'y a aucun moyen de "dé-source" un fichier, je ne vois pas de manière complètement simple. Voici un piratage possible: subordonnez le sourcing de la bibliothèque à une variable d'environnement, par exemple NOCOMPL, non définie dans votre ~/.bashrc, ...
Malte Skoruppa