notify 和 handlers,译为通知和处理程序。它们两者关系是notify通知调用hanlers其下的任务执行。
hanlders和tasks是同级,两者下面都定义了任务。但是handlers下的任务,在没有notify调用它下面任务的情况下,它是不会触发执行的。
那么如何去调用,我们可以在tasks下面的某个任务中去定义notify调用handlers下的任务。一般在一个任务的结尾,和模块同级。
可以说 notify 监控这个任务,如果任务是changed状态(即真正的进行实际操作,造成了实际的改变),那么notify会通知调用hanlers其下的某个任务执行。如果任务没有处在changed状态,即任务没造成实际改变,那么notify就不会去通知调用。
示例:
[root@m1 test]# vim notify.yml
- hosts: web1
tasks:
- name: configure nginx server
template:
src: /root/nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx server
handlers:
- name: restart nginx server
systemd:
name: nginx
state: restarted
需要注意的是默认情况下,在tasks下的所有task执行完毕后,才会执行各个handler,并不是执行完某个任务后,立即执行其对应的handler,如果你想要在执行完某些task以后立即执行对应的handler,则需要使用meta模块,示例如下:
[root@m1 test]# cat notify2.yml
- hosts: web1
tasks:
- name: test1
shell: 'echo "1"'
notify: touch test1
- name: test2
shell: 'echo "2"'
notify: touch test2
- meta: flush_handlers
- name: test3
shell: 'echo "3"'
notify: touch test3
handlers:
- name: touch test1
file:
name: /root/test1
state: touch
- name: touch test2
file:
name: /root/test2
state: touch
- name: touch test3
file:
name: /root/test3
state: touch
上例中,meta任务的参数值为flush_handlers,"meta: flush_handlers"表示立即执行之前的task所对应handler。我们来看下运行结果:
[root@m1 test]# ansible-playbook notify2.yml
PLAY [web1] *************************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [172.16.1.7]
TASK [test1] ************************************************************************************
changed: [172.16.1.7]
TASK [test2] ************************************************************************************
changed: [172.16.1.7]
RUNNING HANDLER [touch test1] *******************************************************************
changed: [172.16.1.7]
RUNNING HANDLER [touch test2] *******************************************************************
changed: [172.16.1.7]
TASK [test3] ************************************************************************************
changed: [172.16.1.7]
RUNNING HANDLER [touch test3] *******************************************************************
changed: [172.16.1.7]
PLAY RECAP **************************************************************************************
172.16.1.7 : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
假如我们想要在一个task中用一个notify调用多个handler。我们可能会想到定义多个handler使用相同的name,但是这样并不可行,因为当多个handler的name相同时,只有一个handler会被执行,即遇到第一个剩下同名的不会执行。所以,我们并不能用这种方式去实现。
想要用一个notify调用多个handler,则需要借助另一个关键字,它就是 listen ,我们可以把 listen 理解成组名,我们可以把多个handler分到这 listen定义的组中,使用notify去调用这个组即可。示例如下:
[root@m1 test]# cat notify2.yml
- hosts: web1
tasks:
- name: test1
shell: 'echo "1"'
notify: group
handlers:
- name: touch test1
listen: group
file:
name: /root/test1
state: touch
- name: touch test2
listen: group
file:
name: /root/test2
state: touch
运行结果如下:
[root@m1 test]# ansible-playbook notify2.yml
PLAY [web1] *************************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [172.16.1.7]
TASK [test1] ************************************************************************************
changed: [172.16.1.7]
RUNNING HANDLER [touch test1] *******************************************************************
changed: [172.16.1.7]
RUNNING HANDLER [touch test2] *******************************************************************
changed: [172.16.1.7]
PLAY RECAP **************************************************************************************
172.16.1.7 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
参考文章: http://www.zsythink.net/archives/2624