45

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 '15 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 '17 at 19:15
74

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 '15 at 8:34
  • 5
    Yes though that will force all handlers to run – jarv May 8 '15 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 '18 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 '18 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 '20 at 11:32
19

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
  3. 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. – Jonathan Hartley Oct 7 '15 at 10:51
  • Multiple tasks can notify the same handler, and the handler will only execute once. That's the whole point of handlers. – Jeff Widman Dec 2 '15 at 19:37
  • Hey Jeff. This answer is about not using handlers, specifying all actions just using tasks. – Jonathan Hartley Dec 4 '15 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." – Jonathan Hartley Dec 7 '15 at 14:17
  • 1
    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 '18 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.