URL: https://linuxfr.org/forums/programmation-shell/posts/resolu-ai-je-detecte-un-bug-ou-bien-suis-je-mauvais-avec-gnu-bash-et-ansible-lint Title: [Résolu] Ai-je détecté un bug ou bien suis-je mauvais avec GNU Bash et ansible-lint ? Authors: Flyounet Date: 2021年01月29日T14:25:21+01:00 License: CC By-SA Tags: bash, ansible, ansible-lint et ubuntu Score: 2 Bonjour, La question est posée, cependant, laissez moi vous conter toute l'histoire : Il était une fois un travailleur sympa qui voulait aider ses collègues (qui débutent) en leur faisant un petit script pour utiliser un [linter](https://fr.wikipedia.org/wiki/Lint_(logiciel)) sur leurs sources. Les sources étant des roles et playbooks [Ansible](https://fr.wikipedia.org/wiki/Ansible_(logiciel)), il trouve fort intéressant d'utiliser [ansible-lint](https://github.com/ansible-community/ansible-lint). Pour l'encapsulage [Gnu Bash](https://www.gnu.org/software/bash/) est largement suffisant. Hélas les résultats ne sont pas ceux à quoi il s'attendaient. ## Le soucis Lorsque `ansible-lint` est appelé dans une boucle `while read ... done` le résultat affiché de la commande n'est pas correcte. Il l'est dans tout autre cas. ## Un point sur les versions - Environnement 1 : - RHEL : 7.9 - Gnu Bash : 4.2.46 - ansible-lint : 3.5.1 - ansible : 2.9.25 (python 2.7.5) - Environnement 2 : - Ubuntu : 18.04 - Gnu Bash : 4.4.20 - ansible-lint : 3.4.20 - ansible : 2.9.17 (python 2.7.17) Hélas, il n'est pas ici question de pouvoir changer les versions installées sur ces systèmes. En tout cas, pas à court terme. ## Fichier yaml d'exemple Le fichier suivant (que l'on pourra facilement appeler `test.yml`) comporte une erreur _dupiclate entry_. Dans les fichiers des collègues du travailleur, c'était involontaire, mais pas ici, puisque c'est dans ce cas que les soucis se posent. ```yaml g_test_1: children: g_test_2: vars: test: "titi" g_test_2: vars: test: "toto" g_test_1: children: g_test_2: vars: test: "titi" ``` ### Example avec résulat correcte ```sh $: ANSIBLE_NOCOLOR=true ansible-lint -R -p /tmp/test.yml [WARNING]: While constructing a mapping from /tmp/test.yml, line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. [WARNING]: While constructing a mapping from , line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. ``` Le résultat s'affiche sur deux lignes (c'est à dire que `[WARNING]` à `only.` ne représente qu'une ligne). ### Example avec résultat incorrecte ```sh $: while read a; do ANSIBLE_NOCOLOR=true ansible-lint -R -p /tmp/test.yml; done <<< "1" [WARNING]: While constructing a mapping from /tmp/test.yml, line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. [WARNING]: While constructing a mapping from , line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. ``` Comprenez que la valeur donnée ici au `while read` n'est pas ce qui est utilisé dans le script. Mais l'effet est identique. J'aurais tout aussi pu bien mettre `echo '1' | while read a; do ANSIBLE_NOCOLOR=true ansible-lint -R -p /tmp/test.yml; done` L'affichage peut sembler identique, cependant l'effet dépend de la longueur du path et de la clef. Ci dessous un exemple avec des données un peu plus proche de ce que rencontre l'utilisateur : ```sh [WARNING]: While constructing a mapping from /srv/nfs/userdata/myuser/dev/_Ansible_/project-playbooks- 2021/new_ansible_role/inventory/grps_ap_unk.yml, line 12, column 1, found a duplicate dict key (g_grps_ap_unk_en_tst_vs_2). Using last defined value only. ``` Dans ce cas le résultat au travers du `while read` prend 4 lignes (au lieu d'une). ### Encore deux exemples qui fonctionnent ```sh $: for i in 1; do read a <<< "1"; ANSIBLE_NOCOLOR=true ansible-lint -R -p /tmp/test.yml; done [WARNING]: While constructing a mapping from /tmp/test.yml, line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. [WARNING]: While constructing a mapping from , line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. $: while true; do ANSIBLE_NOCOLOR=true ansible-lint -R -p /tmp/test.yml; break; done [WARNING]: While constructing a mapping from /tmp/test.yml, line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. [WARNING]: While constructing a mapping from , line 2, column 1, found a duplicate dict key (g_test_1). Using last defined value only. ``` ## Analyse D'après les tests effectués, il semble que le problème ne survient que dans une boucle `while read`, un `while` sans le `read` fonctionne, de même qu'un `for`. En outre appeler un `read` juste avant l'appel `ansible-lint` ne change rien. Le `while read ` a été agrémenté de différents paramètres pour tester (comme `-a`, `-e`, `-r` et même `-s`). Il fût même question de tester un `IFS=$'\n'`, sans aucun changement. ## Questions - Ami visiteur/codeur toi qui a souvent la joie de découvrir comment résoudre les problèmes d'autrui, voudrais-tu bien aider un travailleur (qui voudrait aider ses collègues) ? - Est-ce réellement un bug ? - Auprès de qui l'ouvrir ? Gnu Bash ? ansible ? ansible-lint ? RedHat ? Ubuntu ? - Est-ce que le susdit travailleur va devoir se tailler son problème en pointe et se le carrer ? - Oui avec le `for` ça fonctionne, mais ça oblige à tricher pour les fichiers/chemins avec `espace`, doit-il vraiment en passer par là ? ## Remerciements Merci ami visiteur/codeur, car si tu n'as pas la réponse tu as déjà perdu ton temps à lire ceci. Et ça ami visiteur/codeur ça me touche (enfin pas moi, mais le travailleur).

AltStyle によって変換されたページ (->オリジナル) /