Как отображать вывод скриптов в плейбуке Ansible

AnsibleAnsibleBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

Ansible – это мощный инструмент автоматизации, который помогает системным администраторам и разработчикам эффективно управлять инфраструктурой. При выполнении скриптов или команд через плейбуки Ansible часто критически важно захватывать и отображать их вывод для мониторинга и устранения неполадок.

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

К концу этой лабораторной работы вы получите практический опыт работы с различными подходами к обработке вывода скриптов в Ansible, что позволит вам создавать более информативные и простые в отладке рабочие процессы автоматизации.

Настройка вашего первого плейбука Ansible

Прежде чем мы сможем изучить, как отображать вывод скриптов, нам нужно настроить базовую среду Ansible и создать наш первый плейбук.

Установка Ansible

Давайте начнем с проверки установки Ansible в нашей системе:

sudo apt update
sudo apt install -y ansible

Эта команда установит Ansible в вашей системе Ubuntu. После завершения установки проверьте ее, проверив версию Ansible:

ansible --version

Вы должны увидеть вывод, аналогичный следующему, который подтверждает, что Ansible установлен правильно:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 14 2023, 14:50:41) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True

Понимание инвентаря Ansible (Ansible Inventory)

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

Создайте каталог для нашего проекта Ansible:

mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab

Теперь создайте файл инвентаря с именем inventory.ini:

echo "localhost ansible_connection=local" > inventory.ini

Этот файл инвентаря сообщает Ansible запускать команды на локальной машине без использования SSH.

Создание вашего первого плейбука

Теперь давайте создадим базовый плейбук Ansible. В WebIDE создайте новый файл с именем first_playbook.yml в каталоге ~/project/ansible-lab со следующим содержимым:

---
- name: My First Ansible Playbook
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Display a simple message
      debug:
        msg: "Hello from Ansible!"

    - name: Display system information
      debug:
        msg: "You are running {{ ansible_distribution }} {{ ansible_distribution_version }}"

Этот простой плейбук имеет две задачи:

  1. Отобразить простое приветственное сообщение
  2. Отобразить информацию об операционной системе, которую вы используете

Давайте запустим этот плейбук, чтобы увидеть, как он работает:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini first_playbook.yml

Вы должны увидеть вывод, аналогичный этому:

PLAY [My First Ansible Playbook] *********************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [Display a simple message] **********************************************************
ok: [localhost] => {
    "msg": "Hello from Ansible!"
}

TASK [Display system information] ********************************************************
ok: [localhost] => {
    "msg": "You are running Ubuntu 22.04"
}

PLAY RECAP *******************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Этот вывод показывает:

  • Плейбук выполнен успешно
  • Все задачи завершены со статусом "ok"
  • Отображается вывод каждой задачи debug

Теперь, когда у нас есть работающий базовый плейбук, мы можем более подробно изучить, как запускать скрипты и отображать их вывод.

Запуск скриптов и захват вывода

Теперь, когда у нас настроена базовая среда Ansible, давайте рассмотрим, как запускать скрипты и захватывать их вывод, используя модули command и shell.

Разница между модулями Command и Shell

Ansible предоставляет два основных модуля для выполнения команд:

  • command (команда): Выполняет команду на удаленном узле, не проходя через оболочку, что означает, что операторы оболочки, такие как |, >, <, и &, не работают.
  • shell (оболочка): Выполняет команду через оболочку, позволяя использовать операторы оболочки и переменные окружения.

Создание простого скрипта для запуска

Сначала давайте создадим простой скрипт оболочки, который мы можем запустить с помощью Ansible. Создайте файл с именем system_info.sh в вашем каталоге ~/project/ansible-lab:

cd ~/project/ansible-lab

В WebIDE создайте файл со следующим содержимым:

#!/bin/bash

echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Kernel Version: $(uname -r)"
echo "CPU Info: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)"
echo "Memory Info: $(free -h | grep Mem | awk '{print $2 " total, " $3 " used, " $4 " free"}')"
echo "Disk Usage: $(df -h / | grep / | awk '{print $5 " of " $2 " used"}')"

Сделайте скрипт исполняемым:

chmod +x ~/project/ansible-lab/system_info.sh

Теперь давайте запустим этот скрипт вручную, чтобы увидеть, какой вывод он выдает:

./system_info.sh

Вы должны увидеть вывод, аналогичный:

=== System Information ===
Hostname: labex-xxxxxxxx
Kernel Version: 5.15.0-xx-generic
CPU Info: Intel(R) Xeon(R) xxxxxx
Memory Info: 8.0G total, 1.2G used, 5.8G free
Disk Usage: 15% of 50G used

Запуск скрипта с помощью Ansible

Теперь давайте создадим новый плейбук, который запустит этот скрипт и захватит его вывод. Создайте файл с именем script_output.yml в вашем каталоге ~/project/ansible-lab:

---
- name: Run Script and Capture Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display script output
      debug:
        msg: "{{ script_result.stdout }}"

Этот плейбук делает две вещи:

  1. Запускает наш скрипт system_info.sh с помощью модуля command
  2. Сохраняет вывод в переменную с именем script_result с использованием ключевого слова register
  3. Отображает захваченный вывод с помощью модуля debug

Давайте запустим этот плейбук:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini script_output.yml

Вы должны увидеть вывод, аналогичный:

PLAY [Run Script and Capture Output] ***************************************************

TASK [Run system info script] ***********************************************************
changed: [localhost]

TASK [Display script output] ************************************************************
ok: [localhost] => {
    "msg": "=== System Information ===\nHostname: labex-xxxxxxxx\nKernel Version: 5.15.0-xx-generic\nCPU Info: Intel(R) Xeon(R) xxxxxx\nMemory Info: 8.0G total, 1.2G used, 5.8G free\nDisk Usage: 15% of 50G used"
}

PLAY RECAP *****************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Обратите внимание, как вывод отображается как одна строка с символами новой строки (\n). Давайте улучшим отображение в следующем разделе.

Понимание переменной Register

Ключевое слово register создает переменную, которая содержит несколько атрибутов, а не только вывод команды. Давайте создадим новый плейбук, чтобы изучить эти атрибуты.

Создайте файл с именем register_details.yml в вашем каталоге ~/project/ansible-lab:

---
- name: Explore Register Variable
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display all register properties
      debug:
        var: script_result

    - name: Display just stdout
      debug:
        var: script_result.stdout

    - name: Display stdout as a list of lines
      debug:
        var: script_result.stdout_lines

Запустите этот плейбук:

ansible-playbook -i inventory.ini register_details.yml

Вы увидите более подробный вывод, который показывает все свойства переменной script_result, включая:

  • stdout: Стандартный вывод в виде одной строки
  • stderr: Стандартная ошибка (если есть)
  • rc: Код возврата (0 означает успех)
  • stdout_lines: Стандартный вывод, разделенный на список строк

Последняя задача особенно полезна, поскольку она форматирует вывод как список строк, делая его гораздо более читаемым.

Продвинутые методы обработки вывода

Теперь, когда мы понимаем основы захвата вывода скриптов, давайте рассмотрим некоторые более продвинутые методы обработки и отображения вывода в плейбуках Ansible.

Обработка ошибок скриптов

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

Создайте файл с именем error_handling.yml в вашем каталоге ~/project/ansible-lab:

---
- name: Handling Script Errors
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run a command that might fail
      command: ls /nonexistent_directory
      register: cmd_result
      ignore_errors: yes

    - name: Show error message if command failed
      debug:
        msg: "Command failed with error: {{ cmd_result.stderr }}"
      when: cmd_result.rc != 0

    - name: Show success message if command succeeded
      debug:
        msg: "Command succeeded with output: {{ cmd_result.stdout }}"
      when: cmd_result.rc == 0

В этом плейбуке:

  1. Мы пытаемся перечислить каталог, который не существует
  2. Мы используем ignore_errors: yes, чтобы предотвратить остановку плейбука в случае сбоя команды
  3. Мы проверяем код возврата (cmd_result.rc), чтобы определить, успешно ли выполнена команда или нет
  4. Мы отображаем соответствующие сообщения в зависимости от результата

Давайте запустим этот плейбук:

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini error_handling.yml

Вы должны увидеть вывод, аналогичный:

PLAY [Handling Script Errors] ***********************************************************

TASK [Run a command that might fail] ***************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.003398", "end": "2023-09-15 12:34:56.789012", "msg": "non-zero return code", "rc": 2, "start": "2023-09-15 12:34:56.785614", "stderr": "ls: cannot access '/nonexistent_directory': No such file or directory", "stderr_lines": ["ls: cannot access '/nonexistent_directory': No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Show error message if command failed] *********************************************
ok: [localhost] => {
    "msg": "Command failed with error: ls: cannot access '/nonexistent_directory': No such file or directory"
}

TASK [Show success message if command succeeded] ****************************************
skipping: [localhost]

PLAY RECAP *******************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1

Обратите внимание, что, несмотря на сбой команды, плейбук продолжает выполняться и отображает сообщение об ошибке.

Форматирование многострочного вывода

Давайте создадим более сложный скрипт, который генерирует многострочный вывод, а затем отформатируем его красиво в нашем плейбуке.

Создайте файл с именем package_info.sh в вашем каталоге ~/project/ansible-lab:

#!/bin/bash

echo "TOP 5 LARGEST INSTALLED PACKAGES"
echo "================================"
dpkg-query -W -f='${Installed-Size}\t${Package}\n' | sort -n -r | head -5

Сделайте его исполняемым:

chmod +x ~/project/ansible-lab/package_info.sh

Теперь создайте плейбук для запуска этого скрипта и красивого форматирования вывода. Создайте файл с именем formatted_output.yml:

---
- name: Format Script Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run package info script
      shell: ./package_info.sh
      register: pkg_info

    - name: Display raw output
      debug:
        msg: "{{ pkg_info.stdout }}"

    - name: Display formatted output with a title
      debug:
        msg: |
          Below is the package information:
          --------------------------------
          {% for line in pkg_info.stdout_lines %}
          {{ line }}
          {% endfor %}
          --------------------------------
          Total lines: {{ pkg_info.stdout_lines | length }}

Этот плейбук:

  1. Запускает наш скрипт package_info.sh
  2. Отображает необработанный вывод
  3. Использует шаблон Jinja2 для форматирования вывода с заголовком и нижним колонтитулом

Давайте запустим его:

ansible-playbook -i inventory.ini formatted_output.yml

Вы должны увидеть красиво отформатированный вывод:

PLAY [Format Script Output] ***********************************************************

TASK [Run package info script] ********************************************************
changed: [localhost]

TASK [Display raw output] *************************************************************
ok: [localhost] => {
    "msg": "TOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n"
}

TASK [Display formatted output with a title] ******************************************
ok: [localhost] => {
    "msg": "Below is the package information:\n--------------------------------\nTOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n--------------------------------\nTotal lines: 7"
}

PLAY RECAP ****************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Условное отображение вывода

Иногда вы хотите отображать вывод только при определенных условиях, например, при работе в подробном режиме. Давайте посмотрим, как это сделать.

Создайте файл с именем conditional_output.yml в вашем каталоге ~/project/ansible-lab:

---
- name: Conditional Output Display
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Get disk usage information
      shell: df -h
      register: disk_info

    - name: Display disk usage (always shown)
      debug:
        msg: "{{ disk_info.stdout_lines[0:2] }}"

    - name: Display detailed disk usage (only in verbose mode)
      debug:
        msg: "{{ disk_info.stdout_lines }}"
        verbosity: 1

В этом плейбуке:

  1. Мы захватываем информацию об использовании диска
  2. Мы всегда отображаем сводку (первые две строки)
  3. Мы отображаем полные сведения только при работе в подробном режиме (с флагом -v)

Давайте сначала запустим его в обычном режиме:

ansible-playbook -i inventory.ini conditional_output.yml

Теперь давайте запустим его в подробном режиме:

ansible-playbook -i inventory.ini conditional_output.yml -v

Вы заметите, что в подробном режиме вы получаете полную информацию об использовании диска, а в обычном режиме вы видите только сводку.

Эта техника полезна для скрытия потенциально конфиденциального или ошеломляющего вывода по умолчанию, при этом делая его доступным при необходимости для отладки.

Резюме

В этой лабораторной работе вы изучили различные методы захвата и отображения вывода скриптов в плейбуках Ansible:

  1. Вы настроили базовую среду Ansible и создали свой первый плейбук
  2. Вы узнали, как запускать скрипты, используя модули command и shell
  3. Вы захватили вывод скрипта, используя директиву register
  4. Вы отобразили вывод, используя модуль debug в разных форматах
  5. Вы обработали условия ошибок и реализовали условное отображение вывода
  6. Вы применили методы форматирования, чтобы сделать вывод более читаемым

Эти навыки позволяют вам создавать более информативные плейбуки Ansible, которые обеспечивают четкую обратную связь во время выполнения. Эта видимость имеет решающее значение как для мониторинга автоматизированных процессов, так и для устранения неполадок при возникновении проблем.

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