Как отображать вывод команд оболочки в плейбуках Ansible

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

Введение

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

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

Настройка первого плейбука Ansible с командами оболочки

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

Установка Ansible

Сначала установим Ansible в нашей системе:

sudo apt update
sudo apt install -y ansible

Теперь убедимся, что Ansible установлен правильно:

ansible --version

Вы должны увидеть вывод, похожий на этот:

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 15 2022, 12:22:08) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

Создание файла инвентаризации

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

  1. Откройте свою WebIDE и создайте новый файл с именем inventory.ini в каталоге /home/labex/project.
  2. Добавьте следующее содержимое в файл:
[local]
localhost ansible_connection=local

Эта инвентаризация определяет группу с именем local, которая содержит только localhost, и сообщает Ansible подключаться напрямую без SSH.

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

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

  1. Создайте новый файл с именем first_playbook.yml в каталоге /home/labex/project.
  2. Добавьте следующее YAML-содержимое в файл:
---
- name: Shell Command Example
  hosts: local
  gather_facts: no

  tasks:
    - name: Run a simple shell command
      shell: echo "Hello from Ansible shell command"
      register: hello_output

    - name: Display the output
      debug:
        msg: "{{ hello_output.stdout }}"

Этот плейбук делает следующее:

  • Нацелен на группу local, которую мы определили в нашей инвентаризации.
  • Пропускает сбор фактов (информации о системе), чтобы упростить задачу.
  • Выполняет команду оболочки, которая выводит приветственное сообщение.
  • Сохраняет вывод в переменной, используя ключевое слово register.
  • Отображает вывод, используя модуль debug.

Запуск вашего плейбука

Теперь давайте запустим плейбук:

ansible-playbook -i inventory.ini first_playbook.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Shell Command Example] **************************************************

TASK [Run a simple shell command] *********************************************
changed: [localhost]

TASK [Display the output] *****************************************************
ok: [localhost] => {
    "msg": "Hello from Ansible shell command"
}

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

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

Ключевые концепции для понимания

Из этого упражнения обратите внимание на следующие важные концепции:

  1. Модуль shell позволяет выполнять команды оболочки.
  2. Директива register захватывает вывод задачи в переменную.
  3. Модуль debug помогает отображать значения переменных.
  4. Вывод команды оболочки содержит как stdout (стандартный вывод), так и stderr (вывод ошибок).

На следующем шаге мы рассмотрим, как более эффективно обрабатывать и форматировать вывод команд оболочки.

Работа со структурированным выводом команд оболочки

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

Обработка информации о системе

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

  1. Создайте новый файл с именем system_info.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Gather and Display System Information
  hosts: local
  gather_facts: no

  tasks:
    - name: Gather system information
      shell: |
        echo "OS Information: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)"
        echo "Kernel Version: $(uname -r)"
        echo "CPU Information: $(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
        echo "Memory Information: $(free -h | grep Mem | awk '{print $2}')"
      register: system_info

    - name: Display raw system information
      debug:
        msg: "{{ system_info.stdout }}"

    - name: Display information as a list
      debug:
        msg: "{{ system_info.stdout_lines }}"

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

  • Выполняет многострочный скрипт оболочки, который собирает различные сведения о системе.
  • Сохраняет вывод в переменной system_info.
  • Отображает вывод сначала как необработанную строку, а затем как список строк.

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

ansible-playbook -i inventory.ini system_info.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Gather and Display System Information] **********************************

TASK [Gather system information] **********************************************
changed: [localhost]

TASK [Display raw system information] *****************************************
ok: [localhost] => {
    "msg": "OS Information: \"Ubuntu 22.04.1 LTS\"\nKernel Version: 5.15.0-1023-azure\nCPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz\nMemory Information: 4.0Gi"
}

TASK [Display information as a list] *****************************************
ok: [localhost] => {
    "msg": [
        "OS Information: \"Ubuntu 22.04.1 LTS\"",
        "Kernel Version: 5.15.0-1023-azure",
        "CPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
        "Memory Information: 4.0Gi"
    ]
}

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

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

Работа с результатами команд и кодами возврата

Команды оболочки в Linux возвращают коды выхода, чтобы указать на успех (0) или неудачу (ненулевое значение). Ansible захватывает их в атрибуте rc (return code - код возврата) зарегистрированной переменной.

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

  1. Создайте новый файл с именем command_results.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Working with Command Results
  hosts: local
  gather_facts: no

  tasks:
    - name: Check if a file exists
      shell: test -f /etc/hosts
      register: file_check
      ignore_errors: yes

    - name: Show command result details
      debug:
        msg: |
          Return code: {{ file_check.rc }}
          Succeeded: {{ file_check.rc == 0 }}
          Failed: {{ file_check.rc != 0 }}

    - name: Check if a non-existent file exists
      shell: test -f /file/does/not/exist
      register: missing_file
      ignore_errors: yes

    - name: Show command result for missing file
      debug:
        msg: |
          Return code: {{ missing_file.rc }}
          Succeeded: {{ missing_file.rc == 0 }}
          Failed: {{ missing_file.rc != 0 }}

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

  • Выполняет две тестовые команды для проверки существования файлов.
  • Использует ignore_errors: yes, чтобы предотвратить остановку плейбука в случае сбоя команды.
  • Отображает подробную информацию о результатах команды, включая код возврата и статус успеха/неудачи.

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

ansible-playbook -i inventory.ini command_results.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Working with Command Results] *******************************************

TASK [Check if a file exists] *************************************************
changed: [localhost]

TASK [Show command result details] ********************************************
ok: [localhost] => {
    "msg": "Return code: 0\nSucceeded: True\nFailed: False\n"
}

TASK [Check if a non-existent file exists] ************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "test -f /file/does/not/exist", "delta": "0:00:00.003183", "end": "2023-07-14 15:24:33.931406", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 15:24:33.928223", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Show command result for missing file] ***********************************
ok: [localhost] => {
    "msg": "Return code: 1\nSucceeded: False\nFailed: True\n"
}

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

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

Понимание структуры зарегистрированной переменной

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

  • stdout: Стандартный вывод в виде одной строки
  • stdout_lines: Стандартный вывод, разделенный на список строк
  • stderr: Стандартный вывод ошибок в виде одной строки
  • stderr_lines: Стандартный вывод ошибок, разделенный на список строк
  • rc: Код возврата (0 для успеха, ненулевое значение для неудачи)
  • cmd: Выполненная команда
  • start и end: Метки времени начала и окончания команды
  • delta: Продолжительность выполнения команды

Понимание этой структуры имеет решающее значение для эффективной работы с выводом команд оболочки в Ansible.

Условное выполнение на основе вывода команд оболочки

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

Использование условий с выводом команд оболочки

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

  1. Создайте новый файл с именем conditional_playbook.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Conditional Tasks Based on Command Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Check disk space
      shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
      register: disk_usage

    - name: Display disk usage
      debug:
        msg: "Current disk usage: {{ disk_usage.stdout }}%"

    - name: Disk usage warning
      debug:
        msg: "WARNING: Disk usage is high"
      when: disk_usage.stdout|int > 50

    - name: Disk usage normal
      debug:
        msg: "Disk usage is normal"
      when: disk_usage.stdout|int <= 50

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

  • Запускает команду оболочки для проверки процента использования дискового пространства в корневой файловой системе.
  • Использует условие when на основе вывода команды.
  • Использует фильтр int для преобразования строкового вывода в целое число для сравнения.

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

ansible-playbook -i inventory.ini conditional_playbook.yml

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

PLAY [Conditional Tasks Based on Command Output] ******************************

TASK [Check disk space] *******************************************************
changed: [localhost]

TASK [Display disk usage] *****************************************************
ok: [localhost] => {
    "msg": "Current disk usage: 38%"
}

TASK [Disk usage warning] *****************************************************
skipped: [localhost]

TASK [Disk usage normal] ******************************************************
ok: [localhost] => {
    "msg": "Disk usage is normal"
}

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

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

Обработка вывода JSON из команд

Многие современные инструменты командной строки возвращают данные в формате JSON. Ansible имеет встроенные возможности для обработки вывода JSON:

  1. Создайте новый файл с именем json_output.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Handling JSON Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Create a JSON file for testing
      copy:
        dest: /tmp/services.json
        content: |
          {
            "services": [
              {
                "name": "web",
                "status": "running",
                "port": 80
              },
              {
                "name": "database",
                "status": "stopped",
                "port": 5432
              },
              {
                "name": "cache",
                "status": "running",
                "port": 6379
              }
            ]
          }

    - name: Read JSON file with shell
      shell: cat /tmp/services.json
      register: json_output

    - name: Parse and display JSON content
      debug:
        msg: "{{ json_output.stdout | from_json }}"

    - name: Extract and display service information
      debug:
        msg: "Service: {{ item.name }}, Status: {{ item.status }}, Port: {{ item.port }}"
      loop: "{{ (json_output.stdout | from_json).services }}"

    - name: Show only running services
      debug:
        msg: "Running service: {{ item.name }} on port {{ item.port }}"
      loop: "{{ (json_output.stdout | from_json).services }}"
      when: item.status == "running"

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

  • Создает пример JSON-файла для демонстрации.
  • Считывает JSON-файл с помощью команды оболочки.
  • Использует фильтр from_json для преобразования строки JSON в структуру данных.
  • Перебирает структуру данных для отображения информации.
  • Использует условную логику для фильтрации только запущенных служб.

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

ansible-playbook -i inventory.ini json_output.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Handling JSON Output] ***************************************************

TASK [Create a JSON file for testing] *****************************************
changed: [localhost]

TASK [Read JSON file with shell] **********************************************
changed: [localhost]

TASK [Parse and display JSON content] *****************************************
ok: [localhost] => {
    "msg": {
        "services": [
            {
                "name": "web",
                "port": 80,
                "status": "running"
            },
            {
                "name": "database",
                "port": 5432,
                "status": "stopped"
            },
            {
                "name": "cache",
                "port": 6379,
                "status": "running"
            }
        ]
    }
}

TASK [Extract and display service information] ********************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
    "msg": "Service: web, Status: running, Port: 80"
}
ok: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432}) => {
    "msg": "Service: database, Status: stopped, Port: 5432"
}
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
    "msg": "Service: cache, Status: running, Port: 6379"
}

TASK [Show only running services] *********************************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
    "msg": "Running service: web on port 80"
}
skipped: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432})
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
    "msg": "Running service: cache on port 6379"
}

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

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

Обработка ошибок с помощью команд оболочки

При выполнении команд оболочки важно корректно обрабатывать потенциальные ошибки:

  1. Создайте новый файл с именем error_handling.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Error Handling with Shell Commands
  hosts: local
  gather_facts: no

  tasks:
    - name: Run a potentially failing command
      shell: grep "nonexistent_pattern" /etc/passwd
      register: command_result
      ignore_errors: yes

    - name: Display success or failure
      debug:
        msg: "Command {{ 'succeeded' if command_result.rc == 0 else 'failed with return code ' + command_result.rc|string }}"

    - name: Run a custom failing command
      shell: exit 3
      register: exit_command
      ignore_errors: yes

    - name: Display detailed error information
      debug:
        msg: |
          Return code: {{ exit_command.rc }}
          Error message: {{ exit_command.stderr if exit_command.stderr else 'No error message' }}

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

  • Запускает команды, которые, как ожидается, завершатся неудачей.
  • Использует ignore_errors: yes, чтобы продолжить выполнение плейбука, даже если команды завершаются неудачей.
  • Показывает различные методы обработки и отображения информации об ошибках.

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

ansible-playbook -i inventory.ini error_handling.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Error Handling with Shell Commands] *************************************

TASK [Run a potentially failing command] **************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "grep \"nonexistent_pattern\" /etc/passwd", "delta": "0:00:00.002916", "end": "2023-07-14 16:10:23.671519", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 16:10:23.668603", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Display success or failure] *********************************************
ok: [localhost] => {
    "msg": "Command failed with return code 1"
}

TASK [Run a custom failing command] *******************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "exit 3", "delta": "0:00:00.002447", "end": "2023-07-14 16:10:23.906121", "msg": "non-zero return code", "rc": 3, "start": "2023-07-14 16:10:23.903674", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Display detailed error information] *************************************
ok: [localhost] => {
    "msg": "Return code: 3\nError message: No error message\n"
}

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

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

Создание практичного инструмента для обработки вывода команд оболочки

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

Создание инструмента для отчетов о системе

Давайте создадим комплексный инструмент для сбора информации о системе:

  1. Создайте новый файл с именем system_report.yml в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
---
- name: Comprehensive System Report
  hosts: local
  gather_facts: no

  vars:
    report_file: /tmp/system_report.txt

  tasks:
    - name: Collect basic system information
      shell: |
        echo "SYSTEM REPORT" > {{ report_file }}
        echo "=============" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "HOSTNAME: $(hostname)" >> {{ report_file }}
        echo "TIMESTAMP: $(date)" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "SYSTEM INFORMATION" >> {{ report_file }}
        echo "------------------" >> {{ report_file }}
        echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)" >> {{ report_file }}
        echo "KERNEL: $(uname -r)" >> {{ report_file }}
        echo "UPTIME: $(uptime -p)" >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "RESOURCE UTILIZATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "CPU LOAD: $(uptime | awk -F'load average:' '{print $2}')" >> {{ report_file }}
        echo "MEMORY USAGE:" >> {{ report_file }}
        free -h >> {{ report_file }}
        echo "" >> {{ report_file }}
        echo "DISK USAGE:" >> {{ report_file }}
        df -h >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "NETWORK INFORMATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "IP ADDRESSES:" >> {{ report_file }}
        ip addr | grep "inet " | awk '{print $2}' >> {{ report_file }}
        echo "" >> {{ report_file }}

        echo "PROCESS INFORMATION" >> {{ report_file }}
        echo "-------------------" >> {{ report_file }}
        echo "TOP 5 CPU CONSUMING PROCESSES:" >> {{ report_file }}
        ps aux --sort=-%cpu | head -6 >> {{ report_file }}
        echo "" >> {{ report_file }}
        echo "TOP 5 MEMORY CONSUMING PROCESSES:" >> {{ report_file }}
        ps aux --sort=-%mem | head -6 >> {{ report_file }}
      register: report_generation

    - name: Check if report was generated successfully
      stat:
        path: "{{ report_file }}"
      register: report_stat

    - name: Display report generation status
      debug:
        msg: "Report generated successfully at {{ report_file }}"
      when: report_stat.stat.exists

    - name: Display report content
      shell: cat {{ report_file }}
      register: report_content
      when: report_stat.stat.exists

    - name: Show report content
      debug:
        msg: "{{ report_content.stdout_lines }}"
      when: report_stat.stat.exists

    - name: Analyze disk usage
      shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
      register: disk_usage
      when: report_stat.stat.exists

    - name: Generate disk usage alert if needed
      debug:
        msg: "ALERT: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 80% threshold!"
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int > 80

    - name: Generate disk usage warning if needed
      debug:
        msg: "WARNING: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 60% threshold."
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int > 60
        - disk_usage.stdout|int <= 80

    - name: Confirm normal disk usage
      debug:
        msg: "Disk usage on / is normal at {{ disk_usage.stdout }}%."
      when:
        - report_stat.stat.exists
        - disk_usage.stdout|int <= 60

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

  • Собирает исчерпывающую информацию о системе, используя ряд команд оболочки.
  • Записывает информацию в файл отчета.
  • Проверяет, был ли отчет создан успешно.
  • Отображает содержимое отчета.
  • Анализирует данные об использовании диска.
  • Генерирует соответствующие оповещения на основе анализа.

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

ansible-playbook -i inventory.ini system_report.yml

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

PLAY [Comprehensive System Report] ********************************************

TASK [Collect basic system information] ***************************************
changed: [localhost]

TASK [Check if report was generated successfully] *****************************
ok: [localhost]

TASK [Display report generation status] ***************************************
ok: [localhost] => {
    "msg": "Report generated successfully at /tmp/system_report.txt"
}

TASK [Display report content] *************************************************
changed: [localhost]

TASK [Show report content] ****************************************************
ok: [localhost] => {
    "msg": [
        "SYSTEM REPORT",
        "=============",
        "",
        "HOSTNAME: ubuntu-vm",
        "TIMESTAMP: Fri Jul 14 16:35:42 UTC 2023",
        "",
        "SYSTEM INFORMATION",
        "------------------",
        "OS: \"Ubuntu 22.04.1 LTS\"",
        "KERNEL: 5.15.0-1023-azure",
        "UPTIME: up 3 hours, 25 minutes",
        ...

Изучение отчета

Давайте рассмотрим отчет о системе, который мы сгенерировали:

cat /tmp/system_report.txt

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

Создание пользовательского скрипта оболочки и вызов его из Ansible

Для более сложных операций иногда проще создать выделенный скрипт оболочки и вызвать его из Ansible:

  1. Создайте новый файл с именем disk_analyzer.sh в каталоге /home/labex/project.
  2. Добавьте следующее содержимое:
#!/bin/bash

## disk_analyzer.sh - A simple script to analyze disk usage

echo "DISK USAGE ANALYSIS"
echo "------------------"

## Get overall disk usage
ROOT_USAGE=$(df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//')
echo "Root filesystem usage: ${ROOT_USAGE}%"

## Categorize the usage
if [ $ROOT_USAGE -gt 80 ]; then
  echo "STATUS: CRITICAL - Immediate action required"
elif [ $ROOT_USAGE -gt 60 ]; then
  echo "STATUS: WARNING - Consider cleaning up disk space"
else
  echo "STATUS: OK - Disk usage is within normal parameters"
fi

echo ""

## Find largest directories
echo "Top 5 largest directories in /var:"
du -h /var --max-depth=1 2> /dev/null | sort -hr | head -5

echo ""

## Find largest files
echo "Top 5 largest files in /var/log:"
find /var/log -type f -exec du -h {} \; 2> /dev/null | sort -hr | head -5

exit 0
  1. Сделайте скрипт исполняемым:
chmod +x /home/labex/project/disk_analyzer.sh
  1. Создайте новый плейбук для вызова этого скрипта:
touch /home/labex/project/call_script.yml
  1. Добавьте следующее содержимое в плейбук:
---
- name: Call Custom Shell Script
  hosts: local
  gather_facts: no

  tasks:
    - name: Run disk analyzer script
      shell: /home/labex/project/disk_analyzer.sh
      register: script_output

    - name: Display script output
      debug:
        msg: "{{ script_output.stdout_lines }}"

    - name: Check for critical status
      debug:
        msg: "CRITICAL DISK USAGE DETECTED! Immediate action required."
      when: script_output.stdout is search("STATUS: CRITICAL")
  1. Запустите плейбук:
ansible-playbook -i inventory.ini call_script.yml

Вы должны увидеть вывод, похожий на этот:

PLAY [Call Custom Shell Script] ***********************************************

TASK [Run disk analyzer script] ***********************************************
changed: [localhost]

TASK [Display script output] **************************************************
ok: [localhost] => {
    "msg": [
        "DISK USAGE ANALYSIS",
        "------------------",
        "Root filesystem usage: 38%",
        "STATUS: OK - Disk usage is within normal parameters",
        "",
        "Top 5 largest directories in /var:",
        "60M\t/var/lib",
        "60M\t/var/cache",
        "12M\t/var/log",
        "4.0K\t/var/tmp",
        "4.0K\t/var/mail",
        "",
        "Top 5 largest files in /var/log:",
        "4.0M\t/var/log/journal/c75af53674ce472fb9654a1d5cf8cc37/system.journal",
        "2.3M\t/var/log/auth.log",
        "1.3M\t/var/log/syslog",
        "724K\t/var/log/kern.log",
        "428K\t/var/log/cloud-init.log"
    ]
}

TASK [Check for critical status] **********************************************
skipped: [localhost]

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

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

Основные выводы

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

  1. Как выполнять команды оболочки и захватывать их вывод
  2. Как обрабатывать и форматировать вывод команд для отображения
  3. Как использовать условное выполнение на основе результатов команд
  4. Как обрабатывать вывод JSON и условия ошибок
  5. Как создавать практичные инструменты, которые сочетают команды оболочки с возможностями автоматизации Ansible

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

Резюме

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

Вы освоили несколько ключевых навыков:

  • Выполнение команд оболочки в плейбуках Ansible с использованием модуля shell
  • Захват вывода команд с помощью директивы register
  • Отображение вывода с использованием модуля debug
  • Обработка вывода с помощью фильтров и условий Jinja2
  • Создание практичных инструментов автоматизации, которые сочетают Ansible со скриптами оболочки

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

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