Ansible - Exception handling fatal errors using Block Rescue Always
by
Jeremy Canfield |
Updated: July 28 2023
| Ansible articles
There are a number of ways to handle fatal errors.
- Use fail to end a play and return "failed"
- Use the --check command line flag to run the playbook in a dry run mode
- Use check_mode to determine if any fatal errors would be returned
- Use failed_when to continue based on the task return code
- Use ignore_errors to ignore errors returned by a task
- Use meta: clear_host_errors to clear errors so that subsequent tasks are run
- Use meta: end_play to end a play for all hosts
- Use meta: end_host to end a play for certain hosts and return "skipped"
- Use block rescue always to run tasks even after a fatal error is returned (this article)
- Use stat to determine if /tmp/foo.txt exists and the when parameter to skip the lineinfile module if /tmp/foo.txt does not exist.
- Use stat to determine if /tmp/foo.txt exists and then use the file module and the when parameter to create /tmp/foo.txt if the file does not exist
There are two similar to distinct parameters that can be used with block, rescue and always.
- Tasks in rescue will only be invoked if a task in block fails with a fatal error. It's important to recongize that the tasks in rescue will not be run for invalid task definitions and unreachable hosts.
- Tasks in always will always be run, no matter what
Take for example the following. Since the shell "ls" command should be success, the task in rescue should not be run.
---
- hosts: localhost
tasks:
- block:
- shell: ls
rescue:
- debug:
msg: rescue task
always:
- debug:
msg: always task
...
Something like this should be returned.
~]$ ansible-playbook example.yml
TASK [shell]
changed: [localhost]
TASK [debug]
ok: [localhost] => {
"msg": "always task"
}
On the other hand, the "ls /bogus" command should fail fatal.
---
- hosts: localhost
tasks:
- block:
- shell: ls /bogus
rescue:
- debug:
msg: rescue task
always:
- debug:
msg: always task
...
And the rescue tasks should be run.
~]$ ansible-playbook example.yml
TASK [shell]
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "ls /bogus", "delta": "0:00:00.004014", "end": "2023-07-27 21:47:00.511620", "msg": "non-zero return code", "rc": 2, "start": "2023-07-27 21:47:00.507606", "stderr": "ls: cannot access /bogus: No such file or directory", "stderr_lines": ["ls: cannot access /bogus: No such file or directory"], "stdout": "", "stdout_lines": []}
TASK [debug]
ok: [localhost] => {
"msg": "rescue task"
}
TASK [debug]
ok: [localhost] => {
"msg": "always task"
}
Did you find this article helpful?
If so, consider buying me a coffee over at