Вопрос или проблема
Я пытаюсь напечатать stdout зарегистрированных элементов в соответствии с документацией документации. Вот мой yaml файл:
- name: network-check
tags: stats
shell: "tail -n 3 {{ ansible_facts['nodename'] }}_{{ item }}.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'"
loop: "{{ groups['all'] }}"
when: ansible_facts['nodename'] != item
register: check
- name: network-check
tags: stats
shell: "echo {{ item.stdout }}"
loop: "{{ check.results }}"
И я все еще получаю ошибку “атрибут stdout”, как ниже:
TASK [pretests : network-stat] ***************************************************************************************************************************************************************************************************************************************************************************************************************
fatal: [card-kub000]: FAILED! => {"msg": "Задача включает опцию с неопределенной переменной. Ошибка: 'dict object' не имеет атрибута 'stdout'\n\nОшибка, похоже, была в '/home/holo/cardinality/source/sysop/ansible/roles/pretests/tasks/main.yaml': строка 21, столбец 3, но может\nнаходиться в другом месте файла в зависимости от точной проблемы с синтаксисом.\n\nПростой строкой, вызывающей ошибку, является:\n\n\n- name: network-stat\n ^ здесь\n"}
Что я делаю не так?
Вот как выглядит мой вывод для:
- debug: msg="{{ item.item }}"
loop: "{{ check.results }}"
выглядит так
ok: [card-kub000] => (item={'changed': True, 'end': '2019-01-31 00:36:50.479743', 'stdout': '128', 'cmd': "tail -n 3 card-kub000_card-kub004.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'", 'rc': 0, 'start': '2019-01-31 00:36:50.470371', 'stderr': '', 'delta': '0:00:00.009372', 'invocation': {'module_args': {'creates': None, 'executable': None, '_uses_shell': True, '_raw_params': "tail -n 3 card-kub000_card-kub004.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'", 'removes': None, 'argv': None, 'warn': True, 'chdir': None, 'stdin': None}}, '_ansible_parsed': True, 'stdout_lines': ['128'], 'stderr_lines': [], '_ansible_no_log': False, 'failed': False, 'item': 'card-kub004', '_ansible_item_result': True, '_ansible_ignore_errors': None, '_ansible_item_label': 'card-kub004'}) => {
"msg": "card-kub004"
В конечном счете, я выяснил, где была проблема. У меня было условие “when”, которое сказало ansible пропустить некоторые элементы, если они совпадают с nodename, из-за этого первый элемент не имел поля stdout. Я добавил условие, чтобы проверить, что элемент не пропускается, и это начало работать.
- name: network-check
tags: stats
shell: "echo {{ item.stdout }}"
loop: "{{ check.results }}"
when: item.changed != False
Ответ или решение
Ansible: Обработка stdout зарегистрированных элементов с использованием циклов
В процессе работы с Ansible возникают ситуации, когда необходимо получать данные, зарегистрированные в результате выполнения задач в цикле. В вашем случае вы столкнулись с проблемой, связанной с отсутствием поля stdout
у некоторых элементов. Давайте подробно разберем, как можно решить эту проблему.
Описание проблемы
Вы создали задачу Ansible для выполнения команды shell
, которая использует цикл loop
для обхода группы хостов. Далее вы регистрируете результаты выполнения в переменной check
. Однако, когда вы пытаетесь обратиться к stdout
результатов выполнения задач, возникает ошибка "dict object has no attribute 'stdout'"
, указывающая на отсутствие данного поля у некоторых итемов.
Проблема с условием
Вы правильно отметили, что причина возникновения этой ошибки заключается в условии when
, которое контролирует выполнение задач. Это условие пропускает итемы, для которых имя узла совпадает с текущим узлом. В результате, для этих пропущенных элементов не создается запись о stdout
, что и приводит к ошибке.
Решение проблемы
Чтобы избежать данной ошибки, вам следует добавить проверку в ваше условие when
, которая будет удостоверяться в том, что элемент действительно был изменен, прежде чем пытаться получить его stdout
. Вы уже внесли изменения подобным образом:
- name: network-check
tags: stats
shell: "echo {{ item.stdout }}"
loop: "{{ check.results }}"
when: item.changed != False
Эта правка позволяет убедиться в том, что вы работаете только с итемами, которые прошли проверку и содержат необходимые данные.
Полный пример
Вот как выглядит обновленный код с правильным условием:
- name: network-check
tags: stats
shell: "tail -n 3 {{ ansible_facts['nodename'] }}_{{ item }}.out | awk '/Mbits/ { sum += $7; n++} END { print sum / n }'"
loop: "{{ groups['all'] }}"
when: ansible_facts['nodename'] != item
register: check
- name: Display Network Check Results
tags: stats
shell: "echo {{ item.stdout }}"
loop: "{{ check.results }}"
when: item.changed != False
Заключение
Проблема с отсутствием поля stdout
в результате выполнения задач Ansible может быть решена с помощью корректного использования условия when
. Проверьте свой код на наличие условий и логики обработки данных, чтобы избежать подобных ошибок в будущем. Как всегда, важно обучаться на таких ошибках, чтобы улучшить свои навыки работы с Ansible.
Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их. Мы всегда рады помочь!