32

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
  • 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
61

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.

  • 7
    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
16

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: http://docs.ansible.com/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
  • 1
    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
  • Sorry, I'm afraid I still don't understand the use case you're trying to solve for... Maybe open a new question with an example of what you're trying to accomplish? If you add a comment with a link to it I'll try to answer it. – Jeff Widman Dec 5 '15 at 0:36
  • 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
6

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.