190 votes

Comment faire un shell multiligne script dans Ansible

En ce moment j'utilise un shell script dans ansible qui serait beaucoup plus lisible s'il était sur plusieurs lignes

- name: iterate user groups
  shell: groupmod -o -g {{ item['guid'] }} {{ item['username'] }} ....more stuff to do
  with_items: "{{ users }}"

Je ne sais pas comment autoriser les script multilignes dans le module shell d'Ansible.

2 votes

Vous pouvez également envisager d'utiliser la commande ansible 'script' et d'utiliser un fichier externe.

409voto

larsks Points 23184

Ansible utilise la syntaxe YAML dans ses playbooks. YAML possède un certain nombre d'opérateurs de bloc :

  • El > est un opérateur de bloc de pliage. C'est-à-dire qu'il joint plusieurs lignes ensemble par des espaces. La syntaxe suivante :

    key: >
      This text
      has multiple
      lines

    Assignerait la valeur This text has multiple lines\n a key .

  • El | est un opérateur de bloc littéral. C'est probablement ce que vous voulez pour les scripts shell multi-lignes. La syntaxe suivante :

    key: |
      This text
      has multiple
      lines

    Assignerait la valeur This text\nhas multiple\nlines\n a key .

Vous pouvez l'utiliser pour les scripts shell multilignes comme celui-ci :

- name: iterate user groups
  shell: |
    groupmod -o -g {{ item['guid'] }} {{ item['username'] }} 
    do_some_stuff_here
    and_some_other_stuff
  with_items: "{{ users }}"

Il y a une mise en garde : Ansible fait quelques manipulations bizarres des arguments de la fonction shell Ainsi, alors que la commande ci-dessus fonctionne généralement comme prévu, la commande suivante ne fonctionne pas :

- shell: |
    cat <<EOF
    This is a test.
    EOF

Ansible rendra en fait ce texte avec des espaces en tête, ce qui signifie que le shell ne trouvera jamais la chaîne de caractères EOF au début d'une ligne. Vous pouvez éviter l'heuristique peu utile d'Ansible en utilisant l'attribut cmd comme ceci :

- shell:
    cmd: |
      cat <<EOF
      This is a test.
      EOF

3 votes

C'est l'une des meilleures réponses que j'ai trouvées sur stack overflow... pas étonnant que @larsks ait un score aussi élevé.

26voto

Marcello Romani Points 443

J'ai essayé avec ansible 2.0.0.2 :

---
- hosts: all
  tasks:
    - name: multiline shell command
      shell: >
        ls --color
        /home
      register: stdout

    - name: debug output
      debug: msg={{ stdout }}

La commande de l'interpréteur de commandes est comprimée en une seule ligne, comme dans ls --color /home

Référence (visitée en 2021) : https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html \==> formulaire de recherche "lignes multiples" dans la page.

5 votes

Oui, mais dans la coquille > a une signification très spécifique. J'ai essayé et cela n'a pas fonctionné comme prévu.

6 votes

C'est pourquoi il n'est que dans la première ligne, pas dans les suivantes. Cela a bien fonctionné pour moi avec ansible 2.0 comme je l'ai écrit, bien que cela n'ait pas imprimé la sortie ls complète avec ansible 1.9.4. Quelle version d'Ansible avez-vous utilisée ?

8voto

Id2ndR Points 83

L'ajout d'un espace avant le délimiteur EOF permet d'éviter cmd :

- shell: |
    cat <<' EOF'
    This is a test.
    EOF

6voto

alfredocambera Points 539

Je préfère cette syntaxe car elle permet de définir des paramètres de configuration pour le shell :

---
- name: an example
  shell:
    cmd: |
      docker build -t current_dir .
      echo "Hello World"
      date

    chdir: /home/vagrant/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X