Вопрос или проблема
Я использую Ansible для сканирования хостов с помощью антивируса Clam и получаю отчеты по электронной почте. Отчеты содержат все, и я хочу получать только строки stdout. Есть ли способ достичь этого? Я написал шаблон электронной почты в соответствии с https://gist.github.com/halberom/0aea275632d2b47af0536e5def01d4d2, но единственное, что отличается, это то, что я использовал nice json:
The {{ host }} says {{ hostvars[host]['result']['stdout'] | to_nice_json }}
Ошибка, которую я получаю:
Не удается преобразовать данные с помощью to_nice_json, возвращаясь к to_json: у объекта ‘dict’ нет атрибута ‘stdout’. Задача включает опцию с неопределенной переменной. Ошибка была ansible no_log:false
Если я удаляю ['stdout']
, то отчет по электронной почте выглядит так:
Сканирование ClamAV было выполнено на сервере host_server
{
"changed": true,
"msg": "Все элементы завершены",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"cmd": [
"clamscan",
"-r",
"-i",
"/usr/bin"
],
"delta": "0:00:37.293719",
"end": "2021-09-09 18:47:55.626094",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "clamscan -r -i /usr/bin",
"_uses_shell": false,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "/usr/bin",
"rc": 0,
"start": "2021-09-09 18:47:18.332375",
"stderr": "",
"stderr_lines": [],
"stdout": "\n----------- РЕЗЮМЕ СКАНИРОВАНИЯ -----------\nИзвестные вирусы: 8563204\nВерсия движка: 0.103.2\nСканированные каталоги: 1\nСканированные файлы: 701\nИнфицированные файлы: 0\nПросканированные данные: 110.08 MB\nПрочитанные данные: 109.50 MB (соотношение 1.01:1)\nВремя: 37.113 сек (0 м 37 с)\nДата начала: 2021:09:09 18:47:18\nДата окончания: 2021:09:09 18:47:55",
"stdout_lines": [
"",
"----------- РЕЗЮМЕ СКАНИРОВАНИЯ -----------",
"Известные вирусы: 8563204",
"Версия движка: 0.103.2",
"Сканированные каталоги: 1",
"Сканированные файлы: 701",
"Инфицированные файлы: 0",
"Просканированные данные: 110.08 MB",
"Прочитанные данные: 109.50 MB (соотношение 1.01:1)",
"Время: 37.113 сек (0 м 37 с)",
"Дата начала: 2021:09:09 18:47:18",
"Дата окончания: 2021:09:09 18:47:55 "
]
}
]
}
Есть ли способ получать только stdout_lines в моем отчете? Я пробовал использовать grep в командной оболочке, но не удалось
Из вашего отладочного вывода, result
является зарегистрированной переменной из задания shell, где выполняется clamav
в цикле по списку путей.
Как описано в документации по циклам Ansible, зарегистрированная переменная модифицируется и содержит список results
, где каждый элемент является индивидуальным результатом выполнения модуля с текущим итерационным элементом (например, /usr/bin
в вашем примере).
В этом случае result.stdout
не существует (как ясно сообщается в вашем сообщении об ошибке), но в вашем примере “result.results.0.stdout” существует.
Хотя это будет работать, если у вас всегда в цикле только один путь, вероятно, вы хотите получить список всех stdout из каждого результата. В этом случае вы можете использовать:
result.results | map(attribute="stdout")
Если мы вставим это обратно в ваш конкретный шаблон, способный выдавать вывод для любого данного host
, это будет выглядеть следующим образом:
The {{ host }} says {{ hostvars[host].result.results | map(attribute="stdout") | to_nice_json }}
Обратите внимание, что преобразование в json здесь может не быть лучшим вариантом для электронной почты, и что вышеупомянутое теряет информацию об исходном пути, который был просканирован. Альтернативным вариантом может быть просто перебор результатов и вывод только нужной информации:
Это отчет для хоста {{ host }}
----------------------------------
{% for scan_result in hostvars[host].result.results %}
Сканирование выполнено в каталоге {{ scan_result.item }}:
{{ scan_result.stdout }}
{% endfor %}
.
Ответ или решение
Чтобы получить только stdout_lines
в отчете Ansible, необходимо внимательно настроить обработку результатов выполнения задачи сканирования с помощью ClamAV и модуль отправки электронной почты. Давайте разберем, как это можно реализовать.
Теория
В Ansible, когда вы используете цикл для выполнения команды на нескольких путях, переменная, в которую регистрируется результат выполнения задачи, содержит список результатов (results
). Каждый элемент этого списка представляет собой результат выполнения команды для одного из путей. Для получения строк вывода (stdout_lines
) из каждого результата, нужно обратиться к этому списку и выбрать соответствующее значение.
Пример
В вашей настройке сообщения хотите, чтобы отчет содержал только stdout_lines
. Переменная result
, которая регистрируется в вашей задаче, имеет структуру, включающую такие поля, как stdout
, stderr
, stdout_lines
и другие для каждого элемента.
Предположим, что result
— это регистрируемая переменная из задачи оболочки, которая выполняет команды антивирусного сканирования в цикле по списку путей. Вот как можно получить нужные данные:
- name: Сканирование с помощью ClamAV
shell: clamscan -r -i {{ item }}
register: result
loop:
- /usr/bin
# Добавьте другие директории, если необходимо
- name: Отправка отчета по электронной почте
ansible.builtin.mail:
to: "your_email@example.com"
subject: "Отчет ClamAV сканирования для {{ inventory_hostname }}"
body: |
Это отчет для хоста {{ inventory_hostname }}
----------------------------------------
{% for scan_result in result.results %}
Сканирование выполнено в директории {{ scan_result.item }}:
{{ scan_result.stdout_lines | join('\n') }}
{% endfor %}
Применение
На выходе вы получите хорошо структурированные письма, содержащие только строки из stdout_lines
, для каждого из проверенных путей. Такой подход также позволит сохранить информацию о том, какие директории сканировались, что важно для понимания контекста сканирования.
Убедитесь, что функция join('\n')
используется для преобразования списка строк в строку с разрывами, что сделает вывод более читаемым в письме.
Правильная настройка шаблона и использование возможностей Ansible для доступа к сохраненным значениям дают гибкость в представлении данных и обеспечивают четкость и краткость отчетов, отправляемых по электронной почте.