Ansible: сохранить стандартный вывод команды в новой переменной?

86

Внутри моей playbook я хотел бы создать переменную, содержащую вывод внешней команды. Впоследствии я хочу использовать эту переменную в паре шаблонов.

Вот соответствующие части учебника:

  tasks:
    - name: Create variable from command
      command: "echo Hello"
      register: command_output
    - debug: msg="{{command_output.stdout}}"

    - name: Copy test service
      template: src=../templates/test.service.j2 dest=/tmp/test.service
    - name: Enable test service
      shell: systemctl enable /tmp/test.service
    - name: Start test service
      shell: systemctl start test.service

и допустим, это мой шаблон:

[Unit]
Description=MyApp
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/sh -c "while true; do echo {{ string_to_echo }}; sleep 1; done"

[Install]
WantedBy=multi-user.target

(Обратите внимание на {{ string_to_echo }})

Итак, в основном я ищу способ сохранить содержимое command_output.stdout(которое создается / извлекается во время первой задачи) в новой переменной string_to_echo.
Эту переменную я хотел бы впоследствии использовать в нескольких шаблонах.

Думаю, я мог бы просто использовать {{command_output.stdout}}в своих шаблонах, но я хочу избавиться от этого .stdoutдля удобства чтения.

Форивин
источник

Ответы:

71

Нет необходимости устанавливать факт.

    - shell: cat "hello"
      register: cat_contents

    - shell: echo "I cat hello"
      when: cat_contents.stdout == "hello"
Карел Стригель
источник
14
Это полезно, но это означает, что позже, когда вы будете использовать переменную, вы также должны не забыть ее использовать .stdout.
Тим Мэлоун
21

Небольшая модификация помимо ответа @ udondan. Мне нравится повторно использовать зарегистрированные имена переменных, set_factчтобы свести беспорядок к минимуму.

Поэтому, если бы мне пришлось регистрироваться с использованием переменной, pskя бы использовал то же имя переменной при создании файла set_fact.

пример

- name: generate PSK
  shell: openssl rand -base64 48
  register: psk
  delegate_to: 127.0.0.1
  run_once: true

- set_fact: 
    psk={{ psk.stdout }}

- debug: var=psk
  run_once: true

Затем, когда я его запускаю:

$ ansible-playbook -i inventory setup_ipsec.yml

 PLAY                                                                                                                                                                                [all] *************************************************************************************************************************************************************************

 TASK [Gathering                                                                                                                                                                     Facts] *************************************************************************************************************************************************************
 ok: [hostc.mydom.com]
 ok: [hostb.mydom.com]
 ok: [hosta.mydom.com]

 TASK [libreswan : generate                                                                                                                                                          PSK] ****************************************************************************************************************************************************
 changed: [hosta.mydom.com -> 127.0.0.1]

 TASK [libreswan :                                                                                                                                                                   set_fact] ********************************************************************************************************************************************************
 ok: [hosta.mydom.com]
 ok: [hostb.mydom.com]
 ok: [hostc.mydom.com]

 TASK [libreswan :                                                                                                                                                                   debug] ***********************************************************************************************************************************************************
 ok: [hosta.mydom.com] => {
     "psk": "6Tx/4CPBa1xmQ9A6yKi7ifONgoYAXfbo50WXPc1kGcird7u/pVso/vQtz+WdBIvo"
 }

 PLAY                                                                                                                                                                                RECAP *************************************************************************************************************************************************************************
 hosta.mydom.com    : ok=4    changed=1    unreachable=0    failed=0
 hostb.mydom.com    : ok=2    changed=0    unreachable=0    failed=0
 hostc.mydom.com    : ok=2    changed=0    unreachable=0    failed=0
slm
источник
8

Я новичок в Ansible, но предлагаю следующее решение:

playbook.yml

...
vars:
  command_output_full:
    stdout: will be overriden below
  command_output: {{ command_output_full.stdout }}
...
...
...
tasks:
  - name: Create variable from command
    command: "echo Hello"
    register: command_output_full
  - debug: msg="{{ command_output }}"

Это должно работать (и работает для меня), потому что Ansible использует ленивую оценку. Но, похоже, он проверяет действительность перед запуском, поэтому мне нужно определить command_output_full.stdoutв vars.

И, конечно, если таких варов в varsразделе будет слишком много , это будет выглядеть некрасиво.

Дмитрий
источник
7

Если вы хотите сохранить сложную команду для сравнения текстового результата, например, для сравнения версии ОС, возможно, это может вам помочь:

tasks:
       - shell: echo $(cat /etc/issue | awk {'print $7'})
         register: echo_content

       - shell: echo "It works"
         when: echo_content.stdout == "12"
         register: out
       - debug: var=out.stdout_lines
BrennQuin
источник
1

Если вы хотите пойти дальше и извлечь точную информацию из результатов Playbook, используйте язык запросов JSON, например jmespath, например:

  - name: Sample Playbook
    // Fill up your task
    no_log: True
    register: example_output

  - name: Json Query
    set_fact:
      query_result:
        example_output:"{{ example_output | json_query('results[*].name') }}"
Санти
источник