编写循环
简单循环
- 简单循环对一组项目迭代任务
- loop关键字添加到任务中,将应对其迭代任务的项目列表取为值
- 循环变量item保存每个迭代过程中使用的值
请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态:
- name: Postfix is running
service:
name: postfix
state: started
- name: Devecot is running
service:
name: dovecot
state: started
这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行:
- name: Postfix and Devecot are running
service:
name: "{{ item }}"
state: started
loop:
- postfix
- dovecot
- 使用简单循环批量创建用户
//编写playbook
[root@192 playbook]# vim user.yml
---
- hosts: 192.168.218.128
vars_files:
- vars/user.yml
tasks:
- name: creat user
user:
name: "{{ item }}"
state: present
loop:
- tom1
- tom2
- tom3
- tom4
- tom4
- tom5
//执行
[root@192 playbook]# ansible-playbook user.yml
//检查
[root@localhost ~]# id tom1
uid=6003(tom1) gid=6003(tom1) groups=6003(tom1)
[root@localhost ~]# id tom2
uid=6004(tom2) gid=6004(tom2) groups=6004(tom2)
[root@localhost ~]# id tom3
uid=6005(tom3) gid=6005(tom3) groups=6005(tom3)
...
- 使用变量和循环,批量创建用户
//编写变量,创建tom1-tom8八个用户
[root@192 vars]# vim user.yml
user:
- tom1
- tom2
- tom3
- tom4
- tom5
- tom6
- tom7
- tom8
//编辑playbook
[root@192 playbook]# vim user.yml
---
- hosts: 192.168.218.128
vars_files:
- vars/user.yml
tasks:
- name: creat user
user:
name: "{{ item }}"
state: present
loop: "{{ user }}"
//执行playbook
[root@192 playbook]# ansible-playbook user.yml
//检查
[root@localhost ~]# id tom1
uid=6003(tom1) gid=6003(tom1) groups=6003(tom1)
[root@localhost ~]# id tom2
uid=6004(tom2) gid=6004(tom2) groups=6004(tom2)
循环散列或字典列表
//不使用变量
---
- hosts: 192.168.218.128
tasks:
- name: creat user
user:
name: "{{ item.name }}"
uid: "{{ item.uid}}"
state: absent
loop:
- name: tom1
uid: 2100
- name: tom2
uid: 2111
//使用变量
//编辑变量
[root@192 vars]# vim user.yml
user:
- name: tom1
uid: 2011
- name: tom2
uid: 2010
//编辑playbook
[root@192 playbook]# vim user.yml
---
- hosts: 192.168.218.12
vars_files:
- vars/user.yml
tasks:
- name: creat user
user:
name: "{{ item.name }}"
uid: "{{ item.uid}}"
state: absent
loop: "{{ user }}"
有条件地运行任务
在Ansible中使用条件的情况:
- 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较
- Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理
- 可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)
- 可以评估CPU的数量,来确定如何正确调节某一Web服务器
- 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改
条件任务语法
-
when语句用于有条件地运行任务
-
取要测试的条件为值
-
如果条件满足,则运行任务。如果条件不满足,则跳过任务
-
可以测试的一个最简单条件是某一布尔变量是True还是False
//使用条件语句安装服务
//编写playbook
[root@192 playbook]# vim test.yml
---
- hosts: 192.168.218.128
vars:
install: true //若设为false,下面的任务将不会执行
tasks:
- name: install service
yum:
name: vsftpd
state: present
when: install
//检查
[root@192 playbook]# ansible-playbook test.yml
[root@localhost ~]# rpm -qa |grep vsftpd
vsftpd-3.0.3-34.el8.x86_64 //变量为true时安装服务成功
- 以下示例测试service_name变量是否具有值。若有值,则将service_name的值用作要安装的软件包的名称。如果未定义service_name变量,则跳过任务且不显示错误。
//定义service_name测试
[root@192 playbook]# vim test.yml
---
- hosts: 192.168.218.128
vars:
service_name: vsftpd
tasks:
- name: install service
yum:
name: "{{ service_name }}" //引用变量
state: present
when: service_name is defined //service_name被定义,安装服务任务将执行
//查看
[root@192 playbook]# ansible-playbook test.yml
[root@localhost ~]# rpm -qa |grep vsftpd
vsftpd-3.0.3-34.el8.x86_64 //安装服务成功
//测试不定义service_name,执行看是否跳过
[root@192 playbook]# vim test.yml
---
- hosts: 192.168.218.128
vars: //变量下没有定义service_name
tasks:
- name: install service
yum:
name: "{{ service_name }}"
state: present
when: service_name is defined
//查看
[root@192 playbook]# ansible-playbook test.yml
PLAY [192.168.218.128] ********************************************************************
TASK [Gathering Facts] ********************************************************************
ok: [192.168.218.128]
TASK [install service] ********************************************************************
skipping: [192.168.218.128] //skipping代表跳过,没有安装服务,跳过了,但是没有报错
PLAY RECAP ********************************************************************************
192.168.218.128 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
[root@localhost ~]# rpm -qa |grep vsftpd
[root@localhost ~]#
//总结:要想执行条件任务,变量中中的值需要设置为true;如果在条件中使用是否被定义,变量中需要定义变量,否则将跳过,不执行任务
下表显示在处理条件中可使用的一些算法:
示例条件:
操作 | 示例 |
---|---|
等于(值为字符串) | ansible_machine == “x86_64” |
等于(值为数字) | max_memory == 512 |
小于 | min_memory < 128 |
大于 | min_memory > 256 |
min_memory > 256 | min_memory <= 256 |
大于等于 | min_memory >= 512 |
不等于 | min_memory != 512 |
变量存在 | min_memory is defined |
变量不存在 | min_memory is not defined |
布尔变量是True。1、True或yes的求值为True | memory_available |
布尔变量是False。0、False或no的求值为False | not memory_available |
第一个变量的值存在,作为第二个变量的列表中的值 | ansible_distribution in supported_distros |
举例演示:
//想要在CentOS系统上安装服务vsftpd,若没有则跳过,定义变量系统名称时严格区分大小写,CentOS和centos不一样
---
- hosts: 192.168.218.128
vars:
platform:
- redhat
- CentOS
tasks:
- name: install service
yum:
name: vsftpd
state: present
when: ansible_facts['distribution'] in platform
//检查
[root@192 playbook]# ansible-playbook test.yml
[root@localhost ~]# rpm -qa |grep vsftpd
vsftpd-3.0.3-34.el8.x86_64
//下面演示条件没有匹配到,跳过,不安装
[root@192 playbook]# vim test.yml
---
- hosts: 192.168.218.128
vars:
platform:
- redhat
- centOS //把CentOS改为centos
tasks:
- name: install service
yum:
name: vsftpd
state: present
when: ansible_facts['distribution'] in platform
//检查
[root@192 playbook]# ansible-playbook test.yml
PLAY [192.168.218.128] ********************************************************************
TASK [Gathering Facts] ********************************************************************
ok: [192.168.218.128]
TASK [install service] ********************************************************************
skipping: [192.168.218.128] //显示了跳过,没有执行安装任务
PLAY RECAP ********************************************************************************
192.168.218.128 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
//检查受管主机是否安装服务
[root@localhost ~]# rpm -qa |grep vsftpd
[root@localhost ~]#
测试多个条件
-
一个when语句可用于评估多个条件。使用and和or关键字组合条件,并使用括号分组条件。
-
如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是redhat或CentOS,则下述条件得到满足:
when: ansible_facts['distrbution'] =='redhat' or ansible_facts['distrbution'] =='CentOS'
- 使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是CentOS主机,并且安装的内核是指定版本8,则将满足以下条件:
when: ansible_facts['distribution'] == CentOS and ansible_facts['distribution']['version'] == 8
//若满足上述条件则执行任务,否则跳过
- when关键字还支持使用列表来描述条件列表。向when关键字提供列表时,将使用and运算组合所有条件。下面的示例演示了使用and运算符组合多个条件语句的另一方式:
when:
- ansible_facts['distribution'] == 'CentOS'
- ansible_facts['distribution']['version'] == '8'
//这种格式提高了可读性,而可读性是良好编写Ansible Playbook的关键目标
- 通过使用括号分组条件,可以表达更复杂的条件语句。例如,如果计算机上运行的是红帽企业Linux7或Fedora28,则下述条件语句得到满足。此示例使用大于字符,这样长条件就可以在playbook中分成多行,以便于阅读。
when: >
(ansible_facts['distribution'] == 'CentOS' and ansible_facts['distribution']['version'] == '8')
or
(ansible_facts['distribution'] == 'redhat' and ansible_facts['distribution']['version'] == '7')