AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Multiple Handlers: Run Handlers in Sequence (listen, notify)

By Luca Berton · Published 2024-01-01 · Category: installation

How to run multiple Ansible handlers from a single task. Use listen groups and multiple notify entries to chain handler execution with practical examples.

Ansible Multiple Handlers: Run Handlers in Sequence (listen, notify)

Two ways to run multiple Ansible handlers

How to execute two Ansible handlers on a changed status of Ansible Playbook.

See also: Ansible Handlers Explained: How to Use and Flush Handlers

What is an Ansible handler?

> Handler runs tasks on change.

Handlers execute some tasks only when the previous task returns a changed status. If not necessary, they don't execute.

Links

• https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html

See also: Ansible ansible.builtin vs ansible.legacy: Collection Namespaces Explained

Demo

Let's jump into two real-life examples of how to run multiple Ansible handlers. First of all, we need a task changed status. The simplest Ansible module returning a "changed" status is the command module with a Linux command, like "uptime". Let's suppose we would like to execute two handlers on the screen, for example, two messages on the screen.

Solution 1

code

• two-1.yml
---
- name: handler Playbook
  hosts: all
  tasks:
    - name: Test connection
      ansible.builtin.command: "uptime"
      notify: message

handlers: - name: message 1 ansible.builtin.debug: msg: message 1 listen: message

- name: message 2 ansible.builtin.debug: msg: message 2 listen: message

• inventory

localhost ansible_connection=local

See also: Ansible troubleshooting - VMware Unknown error while connecting to vCenter or ESXi

execution

$ ansible-playbook -i inventory two-1.yml

PLAY [handler Playbook] *********************************************************************

TASK [Gathering Facts] ****************************************************************** ok: [localhost]

TASK [Test connection] ****************************************************************** changed: [localhost]

RUNNING HANDLER [message 1] ************************************************************* ok: [localhost] => { "msg": "message 1" }

RUNNING HANDLER [message 2] ************************************************************* ok: [localhost] => { "msg": "message 2" }

PLAY RECAP ****************************************************************************** localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Solution 2

code

• two-2.yml
---
- name: handler Playbook
  hosts: all
  tasks:
    - name: Test connection
      ansible.builtin.command: "uptime"
      notify:
        - message 1
        - message 2

handlers: - name: message 1 ansible.builtin.debug: msg: message 1

- name: message 2 ansible.builtin.debug: msg: message 2

execution

$ ansible-playbook -i inventory two-1.yml

PLAY [handler Playbook] *********************************************************************

TASK [Gathering Facts] ****************************************************************** ok: [localhost]

TASK [Test connection] ****************************************************************** changed: [localhost]

RUNNING HANDLER [message 1] ************************************************************* ok: [localhost] => { "msg": "message 1" }

RUNNING HANDLER [message 2] ************************************************************* ok: [localhost] => { "msg": "message 2" }

PLAY RECAP ****************************************************************************** localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 PLAY [handler Playbook] *********************************************************************

Conclusion

Now you know Two ways to run multiple Ansible handlers.

Method 1: Multiple notify entries

tasks:
  - name: Update nginx config
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify:
      - Validate nginx config
      - Restart nginx

handlers: - name: Validate nginx config ansible.builtin.command: nginx -t changed_when: false

- name: Restart nginx ansible.builtin.service: name: nginx state: restarted

tasks:
  - name: Update nginx config
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: restart web stack

handlers: - name: Validate config ansible.builtin.command: nginx -t listen: restart web stack

- name: Restart nginx ansible.builtin.service: name: nginx state: restarted listen: restart web stack

- name: Clear cache ansible.builtin.file: path: /var/cache/nginx state: absent listen: restart web stack

Handler Rules

| Rule | Description | |------|-------------| | Run once | Even if notified multiple times | | End of play | Run after all tasks, not after each | | Order | Run in order defined, not notified | | Conditional | Only if notified (something changed) |

Force handlers mid-play

- name: Update config
  template:
    src: config.j2
    dest: /etc/myapp/config.yml
  notify: restart myapp

- meta: flush_handlers # Runs handlers NOW

- name: Verify service uri: url: http://localhost:8080/health

Chained Handlers

handlers:
  - name: Validate config
    command: nginx -t
    notify: Reload nginx  # Only reloads if validation passes

- name: Reload nginx service: name: nginx state: reloaded

Deployment Pattern

tasks:
  - name: Deploy code
    ansible.builtin.git:
      repo: https://github.com/myorg/myapp.git
      dest: /opt/myapp
    notify: deploy application

handlers: - name: Install deps command: pip install -r requirements.txt args: chdir: /opt/myapp listen: deploy application

- name: Run migrations command: python manage.py migrate args: chdir: /opt/myapp listen: deploy application

- name: Restart app systemd: name: myapp state: restarted listen: deploy application

FAQ

Why didn't my handler run?

Handlers only run when a task reports changed. If the task shows ok, the handler is not notified.

Can handlers from different roles listen to the same topic?

Yes - that's a key advantage of listen over direct notify.

Related Articles

the Ansible inventory deep-diveusing handlers in Ansible playbooks

Category: installation

Watch the video: Ansible Multiple Handlers: Run Handlers in Sequence (listen, notify) — Video Tutorial

Browse all Ansible tutorials · AnsiblePilot Home