Lesson 10 of 11 ↓
- 1.Ansible Basic Setup Guide
- 2.Ansible Inventory Guide (hosts)
- 3.Ansible Configuration Guide (ansible.cfg)
- 4.Ansible Ad-hoc Commands Guide
- 5.Ansible Playbook Guide (playbook.yml)
- 6.Ansible Variables & Precedence Guide
- 7.Ansible Loops Guide
- 8.Ansible Conditionals Guide (when)
- 9.Ansible Vault Guide
- 10.Ansible Handlers Guide
- 11.Ansible Custom Roles Guide
4 min read
Ansible Handlers Guide
A comprehensive guide to understanding and using Handlers in Ansible. This document covers basic usage, multiple triggers, and advanced control techniques like listen and flush_handlers.
What are Handlers?
Handlers are special tasks that only run when they are triggered by another task.
-
They are lazy: They usually run at the very end of the play.
-
They are unique: Even if notified 10 times, a handler will run only once.
-
They are conditional: They only run if the notifying task reports a "Changed" state. If the task is "Green" (OK/No Change), the handler is skipped.
Common Use Case: Restarting a service (like Nginx or SSH) only when the configuration file has been updated.
Part 1: Basic Usage (the Nginx Example)
This is the most classic example. We copy a config file, and if it changes, we restart the web server.
- name: Deploy NGINX config and restart if changed
hosts: web
become: true
tasks:
- name: Copy nginx config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: Restart nginx # <--- This triggers the handler
handlers:
- name: Restart nginx # <--- Name must match EXACTLY
service:
name: nginx
state: restartedDetailed Explanation
-
notify: Restart nginx-
This line tells Ansible: "If this copy task actually changes the file on the remote server, verify the handler named 'Restart nginx' needs to run."
-
If the file on the server is already identical to
src, Ansible returns "OK" (Green), and the handler is NOT notified.
-
-
handlers:Section-
Defined at the same indentation level as
tasks. -
Contains a list of tasks just like the main logic.
-
-
serviceModule-
name: nginx: The name of the service on the OS. -
state: restarted: Stops and starts the service. This is preferred overstartedfor config changes becausestartedwon't do anything if the service is already running.
-
Part 2: Multiple Handlers (chaining Triggers)
Sometimes, one change requires multiple actions (e.g., restarting the app AND reloading the system daemon).
- name: Apply configuration changes
hosts: all
become: true
tasks:
- name: Copy file
copy:
src: example.conf
dest: /etc/example.conf
notify:
- Restart example service # Trigger 1
- Reload systemd # Trigger 2
handlers:
- name: Restart example service
service:
name: example
state: restarted
- name: Reload systemd
command: systemctl daemon-reexecDetailed Explanation
-
notifyas a List- You can list multiple handlers. Ansible will flag all of them to run at the end of the play.
-
command: systemctl daemon-reexec-
commandModule: Executes a raw Linux command. -
Why?: Sometimes there isn't a dedicated Ansible module for a specific system action (like re-executing the systemd daemon), so we use the raw command.
-
Note:
systemdmodule usually handles reloads automatically, but this is a good example of running arbitrary commands as handlers.
-
Part 3: Advanced Handler Features (pro Tips)
Here are the advanced concepts that separate beginners from pros.
The listen Keyword (grouping Handlers)
Instead of notifying 5 different handler names, you can make multiple handlers "listen" to one generic topic.
tasks:
- name: Update App Config
copy:
src: app.conf
dest: /etc/app/app.conf
notify: "Restart Web Stack" # Generic Topic
handlers:
- name: Restart Nginx
service:
name: nginx
state: restarted
listen: "Restart Web Stack"
- name: Restart Memcached
service:
name: memcached
state: restarted
listen: "Restart Web Stack"- Benefit: Decouples your tasks from specific handler names. You just notify a topic, and any handler interested in that topic will run.
Forcing Handlers (force_handlers: Yes)
By default, if a task fails in the middle of a play, Ansible stops, and handlers do not run. This leaves your system in a bad state (config changed, but service not restarted).
To fix this, add force_handlers: yes to the Play.
- name: Critical Playbook
hosts: web
force_handlers: yes # <--- CRITICAL SETTING
tasks:
- name: Change config
template:
src: ...
notify: Restart Service
- name: Task that might fail
command: /bin/false- Result: Even though
/bin/falsefails, Ansible will still run "Restart Service" at the end.
Running Handlers Immediately (meta: Flush_handlers)
Handlers run at the end of the play. Sometimes, you need the service to restart right now before the next task runs.
tasks:
- name: Update Apache Config
copy: ...
notify: Restart Apache
- name: Force Restart NOW
meta: flush_handlers # <--- Stops here, runs all queued handlers, then continues
- name: Check Apache Status
uri:
url: http://localhost- Use Case: If the next task (like an HTTP check) depends on the new configuration being active, you must flush handlers first.
Summary Cheat Sheet
| Keyword | Description |
|---|---|
notify |
The trigger used in a task. Can be a string or a list. |
handlers |
The section where handler tasks are defined. |
listen |
Allows multiple handlers to subscribe to a single notification topic. |
meta: flush_handlers |
Forces pending handlers to run immediately, not at the end. |
force_handlers: yes |
Ensures handlers run even if the playbook crashes/fails later. |
state: restarted |
The most common state for service handlers (Bounce the service). |
state: reloaded |
Use if the service supports config reload without downtime (e.g., Nginx). |
Comments
Loading the discussion…