Cómo hacer un script de shell multilínea en Ansible

125

ahora mismo estoy usando un script de shell en ansible que sería mucho más legible si estuviera en varias líneas

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

Simplemente no estoy seguro de cómo permitir un script de varias líneas en el módulo de shell de Ansible

Edgar Martinez
fuente
1
También considere usar el comando ansible 'script' y use un archivo externo
Jason

Respuestas:

273

Ansible usa la sintaxis YAML en sus libros de jugadas. YAML tiene varios operadores de bloque:

  • El >es un operador de bloque plegable. Es decir, une varias líneas mediante espacios. La siguiente sintaxis:

    key: >
      This text
      has multiple
      lines
    

    Asignaría el valor This text has multiple lines\na key.

  • El |personaje es un operador de bloque literal. Esto es probablemente lo que desea para los scripts de shell de varias líneas. La siguiente sintaxis:

    key: |
      This text
      has multiple
      lines
    

    Asignaría el valor This text\nhas multiple\nlines\na key.

Puede usar esto para scripts de shell de varias líneas como este:

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

Hay una advertencia: Ansible realiza una manipulación tonta de los argumentos del shellcomando, por lo que, si bien lo anterior generalmente funcionará como se esperaba, lo siguiente no lo hará:

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

Ansible en realidad representará ese texto con espacios EOFiniciales , lo que significa que el shell nunca encontrará la cadena al comienzo de una línea. Puede evitar las inútiles heurísticas de Ansible utilizando el cmdparámetro como este:

- shell:
    cmd: |
      cat <<EOF
      This is a test.
      EOF
larsks
fuente
27
Respuesta fantástica
Bryan Hunt
18

https://support.ansible.com/hc/en-us/articles/201957837-How-do-I-split-an-action-into-a-multi-line-format-

menciona continuaciones de línea YAML.

Como ejemplo (probado con ansible 2.0.0.2):

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

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

El comando de shell se contrae en una sola línea, como en ls --color /home

Marcello Romani
fuente
3
Sí, pero en el caparazón >tiene un significado muy específico. Intenté esto y no funcionó como se esperaba.
Edgar Martinez
6
Por eso está solo en la primera línea, no en las siguientes. Funcionó bien para mí con ansible 2.0 como escribí, aunque no imprimió la salida completa de ls con ansible 1.9.4. ¿Qué versión de Ansible usaste?
Marcello Romani
El vínculo está muerto.
kenorb
Es de 2016, estas cosas pasan.
Marcello Romani
3

Agregar un espacio antes del delimitador EOF permite evitar cmd:

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