51

I'm using Ansible to provision my development server.

I want it to always start some services for me. I have handlers for this purpose but what is the best way to trigger handler execution without condition, e.g. make it always work?

Something like this:

tasks:
    - name: Trigger handler
      run_handler: name=nginx-restart
2
  • 6
    If you want a task to always run you should make it a task rather than a handler.
    – Jordan
    Feb 12, 2015 at 15:21
  • @Jordan - sometimes you may want to have a handler that's conditionally triggered in most scenarios except this particular one.
    – silverdr
    Jul 30, 2017 at 19:15

3 Answers 3

87

If you absolutely need to trigger a handler every time then here are two options:

1) run a noop shell command which will always report as changed

-  name: trigger nginx-restart
   command: /bin/true
   notify: nginx-restart

2) use debug along with changed_when: to trigger a handler

-  debug: msg="trigger nginx-restart"
   notify: nginx-restart
   changed_when: true

Also of note for Option 1 and Check Mode: You may want to use check_mode: no if using Ansible version 2.2 or higher or always_run: yes if using earlier versions than that so that the task does not get skipped over in check mode. From my manual testing it looks like the handlers remain in check mode, but please be careful as your case may differ.

5
  • 9
    Nowadays, you can ` --force-handlers run handlers even if a task fails`
    – conny
    May 7, 2015 at 8:34
  • 6
    Yes though that will force all handlers to run
    – jarv
    May 8, 2015 at 9:45
  • i found this post useful regarding the changed status, that lead me here. serverfault.com/a/799282/173002. ty.
    – sonjz
    Jan 10, 2018 at 1:38
  • Thanks, I used option 2 and a changed_when with more logic in it to implement a non-idempotent task [which may be invoked more than once in some cases] as a handler rather than a task.
    – Sammitch
    Nov 29, 2018 at 0:27
  • For me a combination of both options did it, as I needed the task itself to check a variable using when. Thanks!
    – Thorian93
    Aug 12, 2020 at 11:32
21

Ansible provides several options for forcing handlers:

  1. To always force all handlers, run ansible-playbook playbook.yml --force-handlers, as documented here: https://github.com/ansible/ansible/issues/4777

  2. To force handlers that have been notified at a specific point within a playbook, you can use a meta task https://docs.ansible.com/playbooks_intro.html:

    tasks: 
      - shell: some tasks go here
      - meta: flush_handlers
      - shell: some other tasks
  1. However, it sounds like you just want to make sure a service is running or restarted, regardless of the outcome of another task. In that case, don't use a handler, use a new task that calls Ansible's service module: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_module.html
    tasks: 
      - name: ensure ntp is running
        service: name=ntp state=started enabled=yes

      - name: always reload nginx
        service: name=nginx state=reloaded

      - name: always restart MySQL
        service: name=mysql state=restarted
8
  • 2
    The problem with (3) is that one might have several tasks which notify the handler, and I don't want the handler to run (restarting the service) several times. Oct 7, 2015 at 10:51
  • Multiple tasks can notify the same handler, and the handler will only execute once. That's the whole point of handlers. Dec 2, 2015 at 19:37
  • Hey Jeff. This answer is about not using handlers, specifying all actions just using tasks. Dec 4, 2015 at 23:38
  • 1
    I don't need a new question. The OQ asked "How can I make sure a handler ALWAYS runs", and this answer, part 3, suggested "Use tasks instead", and my comment points out "Your task might then run several times in some circumstances." Dec 7, 2015 at 14:17
  • 2
    I believe the documentation you refer to in issue #4777 is incorrect: --force-handlers does not unconditionally run all handlers. unix.stackexchange.com/a/327595/29483 The behaviour of --force-handlers, which is correctly documented nearly everywhere else e.g. in the man page and the ansible user guide, is that notified handlers will be run even if the play stops early due to a failed task.
    – sourcejedi
    May 17, 2018 at 11:24
11

Restarting a service is one thing; ensuring it is running is another. If you want ansible to make sure nginx is running, you do this:

tasks:
  - name: Ensure nginx is running
    service: name=nginx state=started

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .