Como fazer um script shell multilinha no Ansible

125

agora estou usando um script de shell em ansible que seria muito mais legível se estivesse em várias linhas

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

Só não tenho certeza de como permitir script de várias linhas no módulo de shell Ansible

Edgar Martinez
fonte
1
Considere também o uso do comando ansible 'script' e um arquivo externo
Jason

Respostas:

273

A Ansible usa a sintaxe YAML em seus manuais. YAML tem vários operadores de bloco:

  • O >é um operador de bloco dobrável. Ou seja, ele une várias linhas por espaços. A seguinte sintaxe:

    key: >
      This text
      has multiple
      lines

    Atribuiria o valor This text has multiple lines\na key.

  • O |personagem é um operador de bloco literal. Isso é provavelmente o que você deseja para scripts de shell de várias linhas. A seguinte sintaxe:

    key: |
      This text
      has multiple
      lines

    Atribuiria o valor This text\nhas multiple\nlines\na key.

Você pode usar isso para scripts de shell de várias linhas 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 }}"

Há uma ressalva: o Ansible faz alguma manipulação desajeitada de argumentos para o shellcomando, portanto, embora o acima funcione normalmente, o seguinte não:

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

Na verdade, o Ansible renderizará esse texto com espaços à esquerda, o que significa que o shell nunca encontrará a string EOFno início de uma linha. Você pode evitar as heurísticas inúteis do Ansible usando o cmdparâmetro como este:

- shell:
    cmd: |
      cat <<EOF
      This is a test.
      EOF
larsks
fonte
27
Resposta 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 continuações de linha YAML.

Como exemplo (experimentado com ansible 2.0.0.2):

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

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

O comando do shell é reduzido em uma única linha, como em ls --color /home

Marcello Romani
fonte
3
Sim, mas no shell >tem um significado muito específico. Tentei fazer isso e não funcionou como esperado.
Edgar Martinez,
6
É por isso que está apenas na primeira linha, não nas subsequentes. Funcionou bem para mim com o ansible 2.0 conforme escrevi, embora não tenha impresso a saída ls completa com o ansible 1.9.4. Qual versão do Ansible você usou?
Marcello Romani
O link está morto.
kenorb
É a partir de 2016, essas coisas acontecem.
Marcello Romani
3

Adicionar um espaço antes do delimitador EOF permite evitar o cmd:

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