一、handlers和notify结合使用触发条件

  handlers同tasks是属同级,相当于一个特殊任务列表,这些任务同前文说的tasks里的任务没有本质的不同,用于当关注的资源发生变化时,才会采取一定的操作。notify此action可用于在每一个play的最后被触发,这样可避免多次有改变发生时都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作,在notify中列出的操作称为handler,换句话说当所关注的资源发生变化时notify将调用handlers中定义的操作。其中notify所在任务就是被监控的任务资源变化的任务,notify可以调用多个handlers定义的操作,一个handlers里可以定义很多任务。

---
- hosts: websers
remote_user: root tasks:
- name: create apache group
group: name=apache gid=80 system=yes
- name: create apache user
user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html
- name: install httpd
yum: name=httpd
- name: copy config file
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd service - name: start httpd service
service: name=httpd state=started enabled=yes handlers:
- name: restart httpd service
service: name=httpd state=restarted

  说明:notify后指定的名称必须要和handlers里的任务名称相同,如不同handlers所定义的任务将不会执行,相当于没有notify调用handlers里的任务。

  在某些情况下,我们可能同时需要调用多个handlers,或者需要使用handlers其他handlers,ansible可以很简单的实现这些功能,如下所示

  1)调用多个handlers

---
- hosts: websers
remote_user: root tasks:
- name: create apache group
group: name=apache gid=80 system=yes
- name: create apache user
user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html
- name: install httpd
yum: name=httpd
- name: copy config file
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
notify:
- restart httpd service
- check httpd process - name: start httpd service
service: name=httpd state=started enabled=yes handlers:
- name: restart httpd service
service: name=httpd state=restarted
- name: check httpd process
shell: /usr/bin/killall -0 httpd &> /tmp/httpd.log

  说明:调用多个handlers我们需要在notify中写成列表的形式,同样我们被触发的任务名称需要同handlers里的被调用的任务名称完全相同

  2)handlers调用handlers

---
- hosts: websers
remote_user: root tasks:
- name: create apache group
group: name=apache gid=80 system=yes
- name: create apache user
user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html
- name: install httpd
yum: name=httpd
- name: copy config file
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd service - name: start httpd service
service: name=httpd state=started enabled=yes handlers:
- name: restart httpd service
service: name=httpd state=restarted
notify: check httpd process
- name: check httpd process
shell: /usr/bin/killall -0 httpd &> /tmp/httpd.log

  说明:handlers调用handlers,则直接在handlers中使用notify选项就可以。

在使用handlers我们需要注意一下几点:

  1)handlers只有在其所在任务被执行时才会被运行,handlers定义的任务它不会像task任务那样,自动会从上至下依次执行,它只会被notify所在的任务发生状态改变时才会触发handlers 的任务执行,如果一个任务中定义了notify调用handlers,但由于条件的判断等原因,该任务尚未执行,那么notify调用的handlers同样也不会执行。

  2)handlers只会在play的末尾运行一次;如果想要在一个playbook的中间运行handlers,则需要使用meta模块来实现,如:-mate: flush_handlers

  二、playbook中变量的使用

ansible中变量的命名规范同其他语言或系统中变量命名规则非常类似。变量名以英文大小写字母开头,中间可以包含下划线和数字,ansible变量的来源有很多,具体有以下几点:

  1)ansible setup模块,这个模块可以从远程主机上获取很多远程主机的基本信息,它所返回的所有变量都可以直接调用,有关setup说明请参考本人博客https://www.cnblogs.com/qiuhom-1874/p/11853512.html

  2)在/etc/ansible/hosts中定义,此文件是ansible执行名时默认加载的主机清单文件,在里面除了可定义我们要管理的主机外,我们还可以定义针对单个主机定义单独的变量,我们把针对单独某一台主机定义的变量叫做普通变量(也可叫做主机变量);还有一种变量它不是针对单独一个主机,它针对某一个组里的所有主机,我们把这种变量叫做公共组变量。主机清单中定义的变量优先级是普通变量高于公共变量。

    2.1)主机变量,可以在主机清单中定义主机时为其添加主机变量以便于在playbook中使用,如下所示

[websers]
192.168.0.128 http_port=80 maxRequestsPerChild=808
192.168.0.218 http_port=81 maxRequestsPerChild=909

    2.2)主机组变量,组变量是指定赋予给指定组内所有主机上的在playbook中可使用的变量,如下所示

[websers]
192.168.0.128 http_port=80
192.168.0.218 http_port=81
[websers:vars]
maxRequestsPerChild=909

  3)通过命令行指定变量(-e指定变量赋值,可以说多个但需要用引号引起或者一个变量用一个-e指定赋值),这种在命令行指定的优先级最高。如下所示

ansible-playbook -e 'package_name1=httpd package_name2=nginx' test_vars.yml

  4)在playbook中定义变量,最常见的定义变量的方法是使用vars代码块,如下所示

---
- hosts: websers
remote_user: root
vars:
- abc: xxx
- bcd: aaa

  5)在独立的变量yml文件中定义,在playbook中使用vars_files代码块引用其变量文件,如下所示

[root@test ~]#cat vars.yml
---
package_name1: vsftpd
package_name2: nginx
[root@test ~]#cat test_vars.yml
---
- hosts: websers
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install package1
yum: name={{ package_name1 }}
- name: install package2
yum: name={{ package_name2 }}
[root@test ~]#

  6)在role中定义,这个后续说到角色在做解释

  变量的调用方式:第一种在playbook中使用变量需要用“{{}}”将变量括起来,表示括号里的内容是一个变量,有时用“{{  variable_name }}"才生效;第二种是ansible-playbook -e 选项指定其变量,ansible-playbook -e "hosts=www user=xxxx" test.yml

  在主机清单中定义变量的方法虽然简单直观,但是当所需要定义的变量有很多时,并且被多台主机使用时,这种方法显得非常麻烦,事实上ansible的官方手册中也不建议我们把变量直接定义到hosts文件中;在执行ansible命令时,ansible会默认会从/etc/ansible/host_vars/和/etc/ansible/group_vars/两个目录下读取变量定义文件,如果/etc/ansible/下没有以上这两个目录,我们可以手动创建,并且可以在这两个目录下创建与hosts文件中的主机名或主机组同名的文件来定义变量。比如我们要给192.168.0.218 这个主机定义个变量文件,我们可以在/etc/ansible/host_vars/目录下创建一个192.168.0.218的空白文件,然后在文件中以ymal语法来定义所需变量即可。如下所示

[root@test ~]#tail -6 /etc/ansible/hosts
## db-[99:101]-node.example.com
[websers]
192.168.0.128
192.168.0.218
[appsers]
192.168.0.217
[root@test ~]#cat /etc/ansible/host_vars/192.168.0.218
---
file1: abc
file2: bcd
[root@test ~]#cat test.yml
---
- hosts: 192.168.0.218
remote_user: root tasks:
- name: touch file1
file: name={{ file1 }} state=touch
- name: toch file2
file: name={{ file2 }} state=touch
[root@test ~]#ansible-playbook test.yml PLAY [192.168.0.218] ************************************************************************************************ TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218] TASK [touch file1] **************************************************************************************************
changed: [192.168.0.218] TASK [toch file2] ***************************************************************************************************
changed: [192.168.0.218] PLAY RECAP **********************************************************************************************************
192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible 192.168.0.218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 12
-rw-r--r--. 1 root root 0 11月 17 16:49 abc
-rw-r--r--. 1 root root 0 11月 17 16:49 bcd
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root root 57 11月 13 19:15 test_cron_file [root@test ~]#

  说明:可看到我们定义在/etc/ansible/host_vars/下的主机变量文件中的变量生效了。

同理,我们要想针对某个组的主机定义一些变量,我们只需要在/etc/ansible/group_vars/目录下创建与主机清单中的主机组同名的文件即可。

  三、使用高阶变量

  对于普通变量,例如由ansible命令行设定的,hosts文件中定义的以及playbook中定义的和变量文件中定义的,这些变量都被称为普通变量或者叫简单变量,我们可以在playbook中直接用双大括号加变量名来读取变量内容;除此以外ansible还有数组变量或者叫做列表变量,如下所示:

[root@test ~]#cat vars.yml
---
packages_list:
- vsftpd
- nginx
[root@test ~]#

  列表定义完成后我们要使用其中的变量可以列表名加下标的方式去访问,有点类似shell脚本里的数组的使用,如下所示

[root@test ~]#cat test.yml
---
- hosts: 192.168.0.218
remote_user: root vars_files:
- vars.yml
tasks:
- name: touch file
file: name={{ packages_list[0] }} state=touch
- name: mkdir dir
file: name={{ packages_list[1] }} state=directory
[root@test ~]#

  说明:我们要使用列表中的第一个元素变量,我们可以写成vars_list[0],使用第二个变量则下标就是1,依此类推

[root@test ~]#ansible *218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 12
-rw-r--r--. 1 root root 0 11月 17 16:49 abc
-rw-r--r--. 1 root root 0 11月 17 16:49 bcd
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root root 57 11月 13 19:15 test_cron_file [root@test ~]#ansible-playbook test.yml PLAY [192.168.0.218] ************************************************************************************************ TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218] TASK [touch file] ***************************************************************************************************
changed: [192.168.0.218] TASK [mkdir dir] ****************************************************************************************************
changed: [192.168.0.218] PLAY RECAP **********************************************************************************************************
192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible *218 -m shell -a 'ls -l /root'
192.168.0.218 | SUCCESS | rc=0 >>
总用量 16
-rw-r--r--. 1 root root 0 11月 17 16:49 abc
-rw-r--r--. 1 root root 0 11月 17 16:49 bcd
drwxr-xr-x. 2 root root 4096 11月 17 17:23 nginx
drwxr-xr-x. 2 qiuhom root 4096 11月 11 19:18 scripts
drwxr-xr-x. 3 qiuhom root 4096 11月 11 19:28 test
-rw-r--r--. 1 root root 57 11月 13 19:15 test_cron_file
-rw-r--r--. 1 root root 0 11月 17 17:23 vsftpd [root@test ~]#

  说明:可看到我们创建的文件和目录在目标主机已经生成

上面的用法是典型的python列表的用法,在python中读取列表中的元素就是用下标的表示来读取相应的元素的值。接下我们将介绍另外一种更为复杂的变量,它类似python中的字典概念,但比字典的维度要高,更像是二维字典。ansible内置变量ansible_eth0就是这样一种,它用来保存远端主机上面eth0接口的信息,包括ip地址和子网掩码等。如下所示

[root@test ~]#cat test.yml
---
- hosts: 192.168.0.218
remote_user: root tasks:
- debug: var=ansible_eth0
[root@test ~]#ansible-playbook test.yml PLAY [192.168.0.218] ************************************************************************************************ TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218] TASK [debug] ********************************************************************************************************
ok: [192.168.0.218] => {
"ansible_eth0": {
"active": true,
"device": "eth0",
"features": {
"fcoe_mtu": "off [fixed]",
"generic_receive_offload": "on",
"generic_segmentation_offload": "on",
"highdma": "off [fixed]",
"large_receive_offload": "off [fixed]",
"loopback": "off [fixed]",
"netns_local": "off [fixed]",
"ntuple_filters": "off [fixed]",
"receive_hashing": "off [fixed]",
"rx_checksumming": "on",
"rx_vlan_filter": "on [fixed]",
"rx_vlan_offload": "on [fixed]",
"scatter_gather": "on",
"tcp_segmentation_offload": "on",
"tx_checksum_fcoe_crc": "off [fixed]",
"tx_checksum_ip_generic": "on",
"tx_checksum_ipv4": "off",
"tx_checksum_ipv6": "off",
"tx_checksum_sctp": "off [fixed]",
"tx_checksum_unneeded": "off",
"tx_checksumming": "on",
"tx_fcoe_segmentation": "off [fixed]",
"tx_gre_segmentation": "off [fixed]",
"tx_gso_robust": "off [fixed]",
"tx_lockless": "off [fixed]",
"tx_scatter_gather": "on",
"tx_scatter_gather_fraglist": "off [fixed]",
"tx_tcp6_segmentation": "off",
"tx_tcp_ecn_segmentation": "off",
"tx_tcp_segmentation": "on",
"tx_udp_tnl_segmentation": "off [fixed]",
"tx_vlan_offload": "on [fixed]",
"udp_fragmentation_offload": "off [fixed]",
"vlan_challenged": "off [fixed]"
},
"hw_timestamp_filters": [],
"ipv4": {
"address": "192.168.0.218",
"broadcast": "192.168.0.255",
"netmask": "255.255.255.0",
"network": "192.168.0.0"
},
"ipv6": [
{
"address": "fe80::20c:29ff:fee8:f67b",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "00:0c:29:e8:f6:7b",
"module": "e1000",
"mtu": 1500,
"pciid": "0000:02:01.0",
"promisc": false,
"speed": 1000,
"timestamping": [
"rx_software",
"software"
],
"type": "ether"
}
} PLAY RECAP **********************************************************************************************************
192.168.0.218 : ok=2 changed=0 unreachable=0 failed=0 [root@test ~]#

  说明:以上playbook就实现了对ansible_eth0这个变量进行调试并打印,可以看到ansible_eth0是一个相对比较复杂的变量,里面包含了字典,列表混合一起的一个大字典。

我们可以看到ansible_eht0里面包含了很多内容,我们要想读取其中的IPV4地址,我们可以采用“.”或者下标的方式去访问,如下所示

[root@test ~]#cat test.yml
---
- hosts: 192.168.0.218
remote_user: root tasks:
- name: print ipv4
shell: echo {{ ansible_eth0["ipv4"]["address"] }}
- name: print mac
shell: echo {{ ansible_eth0.macaddress }}
[root@test ~]#ansible-playbook test.yml -v
Using /etc/ansible/ansible.cfg as config file PLAY [192.168.0.218] ************************************************************************************************ TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.218] TASK [print ipv4] ***************************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "echo 192.168.0.218", "delta": "0:00:00.001680", "end": "2019-11-17 18:30:21.926368", "rc": 0, "start": "2019-11-17 18:30:21.924688", "stderr": "", "stderr_lines": [], "stdout": "192.168.0.218", "stdout_lines": ["192.168.0.218"]} TASK [print mac] ****************************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "echo 00:0c:29:e8:f6:7b", "delta": "0:00:00.001746", "end": "2019-11-17 18:30:22.650541", "rc": 0, "start": "2019-11-17 18:30:22.648795", "stderr": "", "stderr_lines": [], "stdout": "00:0c:29:e8:f6:7b", "stdout_lines": ["00:0c:29:e8:f6:7b"]} PLAY RECAP **********************************************************************************************************
192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#

  说明:由此可以看出ansible多级变量的调用,使用中括号和点号都是可以的

Ansible之playbook拓展的更多相关文章

  1. Ansible进阶--playbook的使用

    一.什么是playbooksplaybooks是ansible的脚本.如同shell脚本一样,它是控制远程主机的一系列命令的集合,通过YAML语言编写.执行一些简单的任务,我们可以使用ad-hoc命令 ...

  2. ansible基础-playbook剧本的使用

    ansible基础-playbook剧本的使用 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.YAML概述 1>.YAML的诞生 YAML是一个可读性高,用来表达数据序 ...

  3. Ansible之playbook的使用总结 - 运维笔记

    之前详细介绍了Ansible的安装, 配置, 以及Ansible常用模块的使用. 下面对Ansible的playbook用法做一小结. 为什么引入playbook?一般运维人员完成一个任务, 比如安装 ...

  4. ansible学习-playbook的YAML语法

    [一篇非常好的ansible参考博文] 初识Ansible http://liumissyou.blog.51cto.com/4828343/1616462 --------------------- ...

  5. 自动化运维工具——ansible剧本playbook(三)

    一.Playbook--Ansible剧本 playbook是由一个或多个 "play"组成的列表 play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的ta ...

  6. Ansible基于playbook批量修改主机名实战

    Ansible基于playbook批量修改主机名 安装Ansible,相信这里也不用多说,大家都知道 说一下环境:这里的主机名是修改之后的,我先把其他两台的主机名改为别的 192.168.30.21 ...

  7. 利用ansible书写playbook在华为云上批量配置管理工具自动化安装ceph集群

    首先在华为云上购买搭建ceph集群所需云主机: 然后购买ceph所需存储磁盘 将购买的磁盘挂载到用来搭建ceph的云主机上 在跳板机上安装ansible 查看ansible版本,检验ansible是否 ...

  8. 利用ansible书写playbook搭建HAProxy+Keepalived+PXC负载均衡和高可用的PXC环境续

    ansible.playbook.haproxy.keepalived.PXC haproxy+keepalived双主模式调度pxc集群 HAProxy介绍 反向代理服务器,支持双机热备支持虚拟主机 ...

  9. Ansible 和 Playbook 暂存

    Ansible  和  Playbook 暂存 , 也是一个批量管理工具 自动化的批量管理工具 主机清单  HOST Inventory 模块插件  Playbooks 查看ansible的目录结构 ...

随机推荐

  1. Java中ArrayList和LinkedList的性能分析

    ArrayList和LinkedList是Java集合框架中经常使用的类.如果你只知道从基本性能比较ArrayList和LinkedList,那么请仔细阅读这篇文章. ArrayList应该在需要更多 ...

  2. vue中百度地图API的调用

    1.使用百度地图api需要使用jsonp,来获取百度api的返回,因为vue不自带jsonp所以需要下载 安装jsonp npm i vue-jsonp -S 引入jsop import Vue fr ...

  3. 2.RF中scalar,list和dict变量的定义和取值

    $:定义scalar变量:@定义list变量:&定义dict变量: $还用来取值,包含scalar, list和dict变量,如下example所示 1.定义scalar变量:set vari ...

  4. Qt5教程: (6) 菜单栏、工具栏、状态栏及核心控件

    1. 新建QMainWindow工程 取消生成.ui文件 2. 菜单栏 在mainwindow.cpp中添加头文件 和 #include <QMenuBar> #include <Q ...

  5. mvc请求管道(一)

    一.前言 在平常做后台开发的时候,经常会说到请求管道,很多开发者都知道这个,也能说几句,可能没法详细的去介绍,今天就来详细的说一下这个. 二.到达IIS之前 请看下面这个流程图.从用户打开浏览器到请求 ...

  6. 你不知道的Canvas(一)

    Canvas基础 一.Canvas是什么 Canvas是一个可以使用脚本(通常为JavaScript来绘制图形的HTML) 元素.例如,它可以用于绘制图表.制作图片构图或者制作简单的动画,主要用来绘制 ...

  7. java学习2-数据类型和运算符

    1.数据类型分类 java是强类型语言:a.所有的变量必须先声明后使用 b.指定类型的变量只能接受类型与之匹配的值 java语言支持的类型分为两类:基本类型和引用类型. 基本类型:包括boolean类 ...

  8. C# 求Π Π/4=1-1/3+1/5-1/7+......+1/(2*n-3)-1/(2*n-1); (n=2000)

    double a = 0.0;//最终Π的结果 double类型 int n; for (n = 1; n <= 2000; n++) { if (n % 2 == 1) { a += 1.0 ...

  9. 聊聊缓存淘汰算法-LRU 实现原理

    前言 我们常用缓存提升数据查询速度,由于缓存容量有限,当缓存容量到达上限,就需要删除部分数据挪出空间,这样新数据才可以添加进来.缓存数据不能随机删除,一般情况下我们需要根据某种算法删除缓存数据.常用淘 ...

  10. 搭建 webpack + react 框架爬坑之路

    由于工程实践需要搭一个 webpack + react 框架,本人刚开始学,就照b站上的react黑马视频做,爬过无数个坑...希望读者能引以为戒.我的是macos系统 https://www.bil ...