Обработка ошибок в Playbook
- Игнорирование неудачных команд
- Сброс недоступных хостов
- Обработчики и ошибки
- Управление определением ошибки
- Переопределение результата изменения
- Прерывание выполнения Playbook
- Использование блоков
Ansible обычно имеет значения по умолчанию, которые гарантируют проверку кодов возврата команд и модулей, и он завершает выполнение при ошибке – вынуждая обработать ошибку, если вы не решите иначе.
Иногда команда, возвращающая значение отличное от 0, не является ошибкой. Иногда команде не нужно сообщать, что она «изменила» удаленную систему. Этот раздел описывает, как изменить стандартное поведение Ansible для определённых задач, чтобы поведение вывода и обработки ошибок было желаемым.
Игнорирование неудачных команд
В общем случае Playbook прекратит выполнение дальнейших шагов на хосте, на котором задача завершилась с ошибкой. Однако иногда необходимо продолжить выполнение. Для этого напишите задачу, которая выглядит так:
- name: this will not be counted as a failure command: /bin/false ignore_errors: yes
Обратите внимание, что указанная система управляет только значением возврата ошибки конкретной задачи, поэтому, если используется неопределённая переменная или синтаксическая ошибка, всё равно будет выброшено сообщение об ошибке, которое пользователи должны будут обработать. Обратите внимание, что это не предотвратит ошибки при подключении или выполнении.
Этот функционал работает только когда задача может быть выполнена и вернуть значение «failed».
Сброс недоступных хостов
Новая функция в версии 2.2.
Ошибки подключения устанавливают хосты как «НЕДОСТУПНЫЕ», что удалит их из списка активных хостов для выполнения. Чтобы восстановиться от этих проблем, вы можете использовать meta: clear_host_errors для повторной активации всех помеченных в настоящее время хостов, чтобы последующие задачи могли снова их использовать.
Обработчики и ошибки
Когда задача завершается с ошибкой на хосте, обработчики, которые были ранее уведомлены, не будут запущены на этом хосте. Это может привести к ситуациям, когда несвязанная ошибка может оставить хост в неожиданном состоянии. Например, задача может обновить файл конфигурации и уведомить обработчик о перезапуске некоторой службы. Если впоследствии в рамках того же Playbook задача завершится с ошибкой, служба не будет перезапущена, несмотря на изменение конфигурации.
Вы можете изменить это поведение с помощью параметра командной строки --force-handlers, или включив force_handlers: True в Playbook, или force_handlers = True в ansible.cfg. Принудительное выполнение обработчиков приведет к их запуску при уведомлении, даже если задача завершится с ошибкой на данном хосте. (Обратите внимание, что некоторые ошибки все ещё могут помешать обработчику запуститься, например, если хост станет недоступным.)
Управление определением ошибки
Ansible позволяет определять, что означает «ошибка» в каждой задаче, используя условное выражение failed_when. Как и со всеми условными выражениями в Ansible, списки нескольких failed_when условий объединяются с неявным and, что означает, что задача завершается с ошибкой только тогда, когда все условия выполнены. Если вы хотите вызвать ошибку, когда выполнено любое из условий, вам необходимо определить условия в строке с явным оператором or.
Вы можете проверить ошибку, выполнив поиск слова или фразы в выводе команды:
- name: Fail task when the command error output prints FAILED command: /usr/bin/example-command -x -y -z register: command_result failed_when: "'FAILED' in command_result.stderr"
или на основе кода возврата:
- name: Fail task when both files are identical raw: diff foo/file1 bar/file2 register: diff_cmd failed_when: diff_cmd.rc == 0 or diff_cmd.rc >= 2
В предыдущих версиях Ansible это можно было сделать следующим образом:
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
ignore_errors: True
- name: fail the play if the previous command did not succeed
fail:
msg: "the command failed"
when: "'FAILED' in command_result.stderr"
Вы также можете объединить несколько условий для проверки ошибки. Эта задача завершится с ошибкой, если оба условия истинны:
- name: Check if a file exists in temp and fail task if it does
command: ls /tmp/this_should_not_be_here
register: result
failed_when:
- result.rc == 0
- '"No such" not in result.stdout'
Если вы хотите, чтобы задача завершилась с ошибкой, когда выполняется только одно условие, измените определение failed_when на:
failed_when: result.rc == 0 or "No such" not in result.stdout
Если у вас слишком много условий, чтобы уместить их в одну строку, вы можете разбить их на несколько строк с помощью >.
- name: example of many failed_when conditions with OR
shell: "./myBinary"
register: ret
failed_when: >
("No such file or directory" in ret.stdout) or
(ret.stderr != '') or
(ret.rc == 10)
Переопределение результата изменения
При выполнении оболочки/команды или другого модуля обычно сообщается о статусе «изменено» в зависимости от того, считает ли он, что он повлиял на состояние машины.
Иногда, на основе кода возврата или вывода, вы будете знать, что никаких изменений не было, и захотите переопределить результат «изменено», чтобы он не отображался в отчёте или не вызывал обработчики:
tasks:
- shell: /usr/bin/billybass --mode="take me to the river"
register: bass_result
changed_when: "bass_result.rc != 2"
# this will never report 'changed' status
- shell: wall 'beep'
changed_when: False
Вы также можете объединить несколько условий для переопределения результата «изменено»:
- command: /bin/fake_command
register: result
ignore_errors: True
changed_when:
- '"ERROR" in result.stderr'
- result.rc == 2
Прерывание выполнения Playbook
Иногда желательно прервать весь Playbook при ошибке, а не просто пропустить оставшиеся задачи для хоста.
Параметр any_errors_fatal завершит Playbook и предотвратит выполнение последующих Playbook. При возникновении ошибки все хосты в текущей группе получат возможность завершить выполнение фатальной задачи, а затем выполнение Playbook остановится. any_errors_fatal может быть установлен на уровне Playbook или блока:
- hosts: somehosts
any_errors_fatal: true
roles:
- myrole
- hosts: somehosts
tasks:
- block:
- include_tasks: mytasks.yml
any_errors_fatal: true
Для более точного управления max_fail_percentage может быть использовано для прерывания выполнения после того, как определённый процент хостов завершится с ошибкой.
Использование блоков
Большинство из того, что можно применить к отдельной задаче (за исключением циклов), может быть применено на уровне блоков, что также значительно облегчает установку данных или директив, общих для задач. Блоки также вводят возможность обработки ошибок аналогично исключениям в большинстве языков программирования. Блоки обрабатывают только статус «failed» задачи. Ошибки в определении задачи или недоступный хост не являются «восстанавливаемыми» ошибками:
tasks:
- name: Handle the error
block:
- debug:
msg: 'I execute normally'
- name: i force a failure
command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- debug:
msg: 'I caught an error, can do stuff here to fix it, :-)'
Это «вернёт» статус ошибки внешней block задачи для выполнения, и Playbook продолжится так, как если бы она завершилась успешно. Дополнительные примеры см. в разделе обработки ошибок в блоках.
См. также
- О Playbook
- Введение в Playbook
- Рекомендации по использованию
- Рекомендации по использованию Playbook
- Условные операторы
- Условные операторы в Playbook
- Использование переменных
- Всё о переменных
- Список рассылки пользователей
- У вас есть вопрос? Зайдите на google группу!
- irc.freenode.net
- #ansible IRC чат канал
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.9/user_guide/playbooks_error_handling.html