Restarting services on every run causes needless downtime; handlers restart only when needed.
A handler is a task that runs only when notified by another task that reported changed. The classic case: when the nginx config file changes, reload nginx; when it doesn't, do nothing.
- Define handlers in the play's
handlers:section (or a role'shandlers/main.yml). - A task adds
notify: Reload nginx(the handler's name, or alistentopic). - Handlers run once, at the end of the play (after all tasks), no matter how many tasks notified them, and in the order they are defined in the handlers section.
Details worth knowing:
- If a later task fails on a host, pending handlers for that host don't run, so the config may have changed while the service wasn't reloaded.
--force-handlersorforce_handlers: trueruns them anyway. ansible.builtin.meta: flush_handlersruns pending handlers immediately, for example to restart a service before a health-check task later in the same play.listen: "restart web stack"lets several handlers respond to one topic.
Prefer reloaded over restarted when the service supports it, and validate configuration before applying it: the template and copy modules have a validate: option, such as nginx -t -c %s, which refuses to install a broken file.
Example
- name: Configure nginx
hosts: web
become: true
tasks:
- name: Install site config
ansible.builtin.template:
src: site.conf.j2
dest: /etc/nginx/conf.d/site.conf
validate: nginx -t -c /etc/nginx/nginx.conf # whole-config syntax test
notify: Reload nginx
- name: Install TLS certificate
ansible.builtin.copy: {src: site.pem, dest: /etc/nginx/site.pem, mode: "0600"}
notify: Reload nginx # still only one reload
handlers:
- name: Reload nginx
ansible.builtin.service: {name: nginx, state: reloaded}
# first run: both tasks changed -> RUNNING HANDLER [Reload nginx] once
# second run: nothing changed -> handler not runRemember
- Handlers run only when a notifying task changed
- They run once, at the end of the play
- flush_handlers runs them early; validate configs before reloading
Watch out for
- Expecting a handler to run when a later task failed on that host; use force_handlers if needed.