响应事件Handler

什么是handler?

每个主流的编程语言都会有event机制,那么handler就是playbook的event。

Handlers里面的每一个handler,也是对module的一次调用。而handlers与tasks不同,tasks会默认的按定义顺序执行每一个task,handlers则不会,它需要在tasks中被调用,才有可能被执行。

Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler,这也是handler与普通的event机制不同的地方。

应用场景

什么情况下使用handlers呢?

如果你在tasks中修改了apache的配置文件。需要重起apache。此外还安装了apache的插件。那么还需要重起apache。像这样的应该场景中,重起apache就可以设计成一个handler.

一个handler最多只执行一次

在所有的任务里表执行之后执行,如果有多个task notify同一个handler,那么只执行一次。

在下面的例子里apache只执行一次

https://github.com/ansible-book/ansible-first-book-examples/blob/master/handlers_state.yml

  1. ---
  2. - hosts: lb
  3. remote_user: root
  4. vars:
  5. random_number1: "{{ 10000 | random }}"
  6. random_number2: "{{ 10000000000 | random }}"
  7. tasks:
  8. - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
  9. copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
  10. notify:
  11. - call in every action
  12. - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number2 }}
  13. copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number2 }}
  14. notify:
  15. - call in every action
  16. handlers:
  17. - name: call in every action
  18. debug: msg="call in every action, but execute only one time"

action是Changed ,才会执行handler

只有当TASKS种的action的执行状态是changed时,才会触发notify handler的执行。

下面的脚本执行两次,执行结果是不同的:

  • 第一次执行是,tasks的状态都是changed,会触发两个handler

  • 第二次执行是,

    • 第一个task的状态是OK,那么不会触发handlers”call by /tmp/hosts”,
    • 第二个task的状态是changed,触发了handler”call by /tmp/hosts.random_number”

测试代码见:

https://github.com/shijingjing1221/ansible-first-book-examples/blob/master/handlers_execution_time.yml

  1. ---
  2. - hosts: lb
  3. remote_user: root
  4. vars:
  5. random_number: "{{ 10000 | random }}"
  6. tasks:
  7. - name: Copy the /etc/hosts to /tmp/hosts
  8. copy: src=/etc/hosts dest=/tmp/hosts
  9. notify:
  10. - call by /tmp/hosts
  11. - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number }}
  12. copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number }}
  13. notify:
  14. - call by /tmp/hosts.random_number
  15. handlers:
  16. - name: call by /tmp/hosts
  17. debug: msg="call first time"
  18. - name: call by /tmp/hosts.random_number
  19. debug: msg="call by /tmp/hosts.random_number"

按Handler的定义顺序执行

handlers是按照在handlers中定义个顺序执行的,而不是安装notify的顺序执行的。

下面的例子定义的顺序是1>2>3,notify的顺序是3>2>1,实际执行顺序:1>2>3.

  1. ---
  2. - hosts: lb
  3. remote_user: root
  4. gather_facts: no
  5. vars:
  6. random_number1: "{{ 10000 | random }}"
  7. random_number2: "{{ 10000000000 | random }}"
  8. tasks:
  9. - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
  10. copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
  11. notify:
  12. - define the 3nd handler
  13. - name: Copy the /etc/hosts to /tmp/hosts.{{ random_number2 }}
  14. copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number2 }}
  15. notify:
  16. - define the 2nd handler
  17. - define the 1nd handler
  18. handlers:
  19. - name: define the 1nd handler
  20. debug: msg="define the 1nd handler"
  21. - name: define the 2nd handler
  22. debug: msg="define the 2nd handler"
  23. - name: define the 3nd handler
  24. debug: msg="define the 3nd handler"