Условное выполнение на основе вывода команд оболочки
Одной из самых мощных возможностей в Ansible является способность принимать решения на основе вывода команд оболочки. На этом шаге мы узнаем, как использовать условия и фильтры для обработки вывода команд оболочки и сделать плейбуки более динамичными.
Использование условий с выводом команд оболочки
Давайте создадим плейбук, который принимает решения на основе вывода команд оболочки:
- Создайте новый файл с именем
conditional_playbook.yml в каталоге /home/labex/project.
- Добавьте следующее содержимое:
---
- 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:
- Создайте новый файл с именем
json_output.yml в каталоге /home/labex/project.
- Добавьте следующее содержимое:
---
- 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, извлекает определенную информацию и фильтрует данные на основе условий.
Обработка ошибок с помощью команд оболочки
При выполнении команд оболочки важно корректно обрабатывать потенциальные ошибки:
- Создайте новый файл с именем
error_handling.yml в каталоге /home/labex/project.
- Добавьте следующее содержимое:
---
- 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
Это демонстрирует, как можно захватывать и реагировать на различные условия ошибок при выполнении команд оболочки.