一、handlers的感念:
Handlers 是一个触发器,也可以理解成是一个特殊的 tasks,与tasks同级,因为他无法直接运行,handlers中的任务会被tasks中的任务进行“调用”,但是,被调用,并不意味着一定会执行,只有当tasks中的任务真正执行以后(真正的操作,发生了改变),handlers中被调用的任务才会执行,如果tasks中的任务并没有做出任何实际的操作,那么handlers即使被调用,也不会执行。
注意:
- 无论多少个tasks通知了相同的handlers,handlers仅会在所有tasks结束后运行一次,除非调用meta 模块,立即执行的意思
- 只有tasks发生改变了才会通知handlers,没有改变则不会触发handlers
- 不能使用handlers替代tasks,因为handlers是一个特殊的tasks。
示例:
---
- hosts: web
remote_user: root
tasks:
- name: installed httpd server
yum:
name: httpd
state: installed
- name: started httped
service:
name: httpd
state: started
- name: Modify the configuration
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: "Listen 80"
line: "Listen 8088"
backrefs: yes
backup: yes
notify:
restart httpd
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
1、先查下原来的端口
[root@k8s-node-2 tmp]# netstat -antlupe |grep httpd
tcp6 0 0 :::80 :::* LISTEN 0 785186 67884/httpd
2、我们先安装了httpd的服务,然后起了服务,再然后,修改了配置文件中httpd服务的端口为8088,并指定了使用notify关键字’调用’handlers中的任务,如果”Modify the configuration”真正的修改了配置文件(实际的操作),那么则执行”restart httpd”任务,如果”Modify the configuration”并没有进行任何实际的改动,则不执行”restart httpd” ,这就是handlers的作用。
3、执行完,在查看 端口已经更改,并进行了备份
[root@k8s-node-2 conf]# netstat -antlupe |grep httpd
tcp6 0 0 :::8088 :::* LISTEN 0 815321 75315/httpd
[root@k8s-node-2 conf]# ll
总用量 40
-rw-r--r-- 1 root root 11755 7月 25 16:31 httpd.conf
-rw-r--r-- 1 root root 11753 5月 30 21:49 httpd.conf.75221.2023-07-25@16:31:35~
二、handlers中的多任务实现
handlers是另一种任务列表,所以handlers中可以有多个任务,被tasks中不同的任务notify,示例如下
---
- hosts: web
remote_user: root
tasks:
- name: make testfile1
file:
path: /tmp/asd1
state: directory
notify: ht2
- name: make testfile2
file:
path: /tmp/asd2
state: directory
notify: ht1
handlers:
- name: ht1
file:
path: /tmp/ht1
state: touch
- name: ht2
file:
path: /tmp/ht2
state: touch
[root@k8s-master-1 handlers]# ansible-playbook test2.yaml
PLAY [web] **********************************************************************************
TASK [Gathering Facts] **********************************************************************
ok: [192.168.134.138]
TASK [make testfile1] ***********************************************************************
changed: [192.168.134.138]
TASK [make testfile2] ***********************************************************************
changed: [192.168.134.138]
RUNNING HANDLER [ht1] ***********************************************************************
changed: [192.168.134.138]
RUNNING HANDLER [ht2] *********
PLAY RECAP **********************************************************************
192.168.134.138 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
从输出信息可以看出,handler执行的顺序与handler在playbook中定义的顺序是相同的,与”handler被notify”的顺序无关。
[root@k8s-master-1 handlers]# ansible web -m shell -a 'ls -l /tmp/'
192.168.134.138 | CHANGED | rc=0 >>
drwxr-xr-x 2 root root 6 7月 25 16:53 asd1
drwxr-xr-x 2 root root 6 7月 25 16:53 asd2
-rw-r--r-- 1 root root 0 7月 25 16:53 ht1
-rw-r--r-- 1 root root 0 7月 25 16:53 ht2
三、meta模块
如上步骤,默认情况下,task执行完毕之后,才会执行各个handlers,并不是执行完某个task之后,立即执行handlers,如果想要在某个场景中,执行完task,就立即执行handlers,就需要使用meta模块,示例如下:
[root@k8s-master-1 handlers]# vim test2.yaml
---
- hosts: web
remote_user: root
tasks:
- name: make testfile1
file:
path: /tmp/asd1
state: directory
notify: ht1
- name: make testfile2
file:
path: /tmp/asd2
state: directory
notify: ht2
- meta: flush_handlers #强制执行
- name: make testfile3
file:
path: /tmp/asd3
state: directory
notify: ht3
handlers:
- name: ht1
file:
path: /tmp/ht1
state: touch
- name: ht2
file:
path: /tmp/ht2
state: touch
- name: ht3
file:
path: /tmp/ht3
state: touch
#可以看到 以下执行顺序是先创建了 testfile1 > testfile2 > ht1 > ht2 > testfile3 > ht3
[root@k8s-master-1 handlers]# ansible-playbook -C test2.yaml
PLAY [web] ****************************************************************
TASK [Gathering Facts] ****************************************************
ok: [192.168.134.138]
TASK [make testfile1] *****************************************************
changed: [192.168.134.138]
TASK [make testfile2] *****************************************************
changed: [192.168.134.138]
RUNNING HANDLER [ht1] **************************************************
ok: [192.168.134.138]
RUNNING HANDLER [ht2] *****************************************************
ok: [192.168.134.138]
TASK [make testfile3] ***************************************************
changed: [192.168.134.138]
RUNNING HANDLER [ht3] *****************************************************
ok: [192.168.134.138]
PLAY RECAP *****************************************************************
192.168.134.138 : ok=7 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
四、一个task中调用多个handlers
我们还可以在一个task中一次性notify多个handlers,怎样才能一次性notify多个handler呢?你可能会尝试将多个handler使用相同的name,但是这样并不可行,因为当多个handler的name相同时,只有一个handler会被执行,所以,我们并不能通过这种方式notify多个handler,如果想要一次notify多个handler,则需要借助另一个关键字,它就是’listen’,可以把listen理解成”组名”,我们可以把多个handler分成”组”,当我们需要一次性notify多个handler时,只要将多个handler分为”一组”,使用相同的”组名”即可,当notify对应的值为”组名”时,”组”内的所有handler都会被notify,这样说可能还是不容易理解,我们来看个小示例,示例如下:
---
- hosts: web
remote_user: root
tasks:
- name: task1
file:
path: /tmp/abc
state: touch
notify: handler group
handlers:
- name: handler1
listen: handler group
file:
path: /tmp/th1
state: touch
- name: handler2
listen: handler group
file:
path: /tmp/th2
state: touch
[root@k8s-master-1 handlers]# ansible-playbook test3.yaml
PLAY [web] *************************************************************************************************
TASK [Gathering Facts] *************************************************************************************
ok: [192.168.134.138]
TASK [task1] ************************************************************************************************
changed: [192.168.134.138]
RUNNING HANDLER [handler1] **********************************************************************************
changed: [192.168.134.138]
RUNNING HANDLER [handler2] ***********************************************************************************
changed: [192.168.134.138]
PLAY RECAP ***************************************************************************************************
192.168.134.138 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如上例所示,handler1与handler2的listen的值都是handler group,当task1中notify的值为handler group1时,handler1与handler2都会被notify。