RedHat9 | Ansible 编写循环和条件任务

环境版本说明

  • RedHat9 [Red Hat Enterprise Linux release 9.0]
  • Ansible [core 2.13.3]
  • Python [3.9.10]
  • jinja [3.1.2]

1. 利用循环迭代任务

  • 通过利用循环,管理员无需编写多个使用同一模块的任务。
  • Ansible支持使用loop关键字对一组项目迭代任务,通过配置循环以利用列表中各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

2. 简单循环

简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表为值。循环变量item保存每个迭代过程中使用的值。

查看当前清单文件

bash 复制代码
cat inventory

针对both组实现,关闭防火墙服务和时钟同步服务,playbook内容如下

yaml 复制代码
---
- name: play1
  hosts: both
  tasks:
  - name: stop firewalld.service and chronyd.service
    ansible.builtin.service:
      name: "{{ item }}"		# 固定格式,表示从loop中提取列表项
      state: stopped
    loop:
      - firewalld				# loop循环列表值
      - chronyd

3. 循环使用单个变量

将loop循环列表值修改为变量引用,在变量中定义要循环的列表值。

将循环列表值定义在vars字段中

yaml 复制代码
---
- name: play1
  hosts: both
  vars:				# 在变量中定义循环列表值
    servers:
    - firewalld
    - chronyd
  tasks:
  - name: stop firewalld.service and chronyd.service
    ansible.builtin.service:
      name: "{{ item }}"		# 固定格式,表示从loop中提取列表项
      state: stopped
    loop: "{{ services }}"

将循环列表值定义在文件中

bash 复制代码
# 新建vars.yml变量文件
services:
  - firewalld
  - chronyd

# 新建playbook
---
- name: play1
  hosts: both
  vars_files: vars.yml
  tasks:
  - name: stop firewalld.service and chronyd.service
    ansible.builtin.service:
      name: "{{ item }}"
      state: stopped
    loop: "{{ services }}"

4. 循环字典列表

将循环列表值定义在vars字段中

yaml 复制代码
---
- name: play1
  hosts: serverb
  vars:
    msg:
      - name: Mike
        age: 20
      - name: Jack
        age: 18
  tasks:
  - name: Print Msg
    ansible.builtin.debug:
      msg: Print {{ item.name }} and {{ item.age }}
    loop: "{{ msg }}"

将循环列表值定义在文件中

yaml 复制代码
# 创建变量文件
vim for4_vars.yml

msg:
  - name: Mike
    age: 20
  - name: Jack
	age: 18
	

# 新建playlook
---
- name: play1
  hosts: serverb
  vars_files: /home/student/ansible/for4_vars.yml
  tasks:
  - name: Print Msg
    ansible.builtin.debug:
      msg: Print {{ item.name }} and {{ item.age }}
    loop: "{{ msg }}"

5. 有条件的运行任务

  • Ansible可以使用 conditionals 在符合特定条件时运行任务或Play。例:可以使用条件在Ansible安装或配置某个服务之前,确定受管主机上的可用内存。
  • 条件语句可以帮助区分不同的受管主机,并根据所符合的条件来分配功能角色。
  • Playbook变量、注册的变量和Ansible事实都可以通过条件句来进行测试。
  • 可以比较字符串、数字数据和布尔值的运算符

when判断语句

  • when判断对象是模块,和模块在同一层次
  • when判断当前模块是否执行,而非判断它下级模块是否执行
  • when中引用变量、facts,不需要添加{``{}}
  • 用于测试条件中相等的==运算符不可与变量赋值=运算符混淆
  • 一个when语句可用于评估多个值,通过使用andor关键字组合,或使用括号分组条件

简单示例

bash 复制代码
---
- name: play1
  hosts: both
  tasks:
  - name: print msg
    ansible.builtin.debug:
      msg: Print Message
    when: inventory_hostname == 'serverc'		# 限定主机名为serverc

条件示例

表达式 作用
inventory_hostname == "serverc" 等于(值为字符串)
Mtu == 1500 等于(值为数字)
Mtu < 1500 小于
Mtu > 1500 大于
Mtu >= 1500 大于等于
Mtu <= 1500 小于等于
Mtu != 1500 不等于
Min_memory is defined 变量存在
Min_memory is undefined 变量不存在
Min_memory is not defined 变量不存在
inventory_hostname in group.both 第一个变量存在,且在第二个变量内,类似 Python中的 'Mike' in ['Mike','Jack']

多条件示例:or是或的关系,任意一个条件为真即可

yaml 复制代码
when: ansible_board_name= == "RHEL" and ansible_board_vendor == "Red Hat"

多条件实例:and是与的关系,全部条件都满足为真

yaml 复制代码
# 第一种方式
when: ansible_board_name= == "RHEL" and ansible_board_vendor == "Red Hat"

# 第二种方式
when: 
  - ansible_board_name= == "RHEL"
  - ansible_board_vendor == "Red Hat"

与或嵌套语句书写

yaml 复制代码
when: >
  ( ansible_board_name= == "RHEL" and
    ansible_board_vendor == "Red Hat" )
  or
  ( ansible_board_name= == "RHEL" and
    ansible_board_vendor == "CentOS")

6. 综合练习1

案例需求

  • 创建一个名为 inventory 的主机清单
  • 创建主机组 dev,包含serverb
  • 创建主机组 prod,包含serverc、serverd
  • 创建一个名为 /home/student/ansible/packages.yml 的palybook
  • 将 php 和 mariadb 软件包安装到 dev、test、prod 主机组中
  • RPM Development Tools 软件包组 安装到 dev 主机组中的主机上
  • dev 主机组中的主机上的所有软件包更新为最新版本

[Step1]:创建主机清单

bash 复制代码
vim inventory

# 写入下列内容
[dev]
serverb

[prod]
serverc
serverd

[Step2]:验证条件语句:通过查看group_names魔法变量可以看到主机所在的驱主机组

bash 复制代码
ansible serverb -m debug -a var=group_names

[Step3]:编写playlook

bash 复制代码
vim package.yml

# 写入下列内容
---
- name: play1
  hosts: dev,prod
  tasks:
  - name: Install php and mariadb
    ansible.builtin.yum:
      name: "{{ item }}"		# 递归提取loop字段中的值
      state: latest
    loop:
      - php
      - mariadb

  - name: Install the 'RPM Development tools' package group
    ansible.builtin.yum:				# 安装软件包组
      name: "@RPM Development Tools"
      state: present
    when: inventory_hostname in groups.dev	# 当主机存在dev组中才执行

  - name: Upgrade all packages		# 更新所有的软件包
    ansible.builtin.yum:
      name: '*'
      state: latest
    when: inventory_hostname in groups.dev	# 当主机存在dev组中才执行

[Step4]:校验playlook语法

bash 复制代码
ansible-navigator run package.yml -m stdout --syntax-check

[Step4]:运行playlook

bash 复制代码
ansible-navigator run package.yml -m stdout

7. 综合练习2

修改文件内容

  • 按照下方所述,创建一个名为 /home/greg/ansible/issue.yml的 playbook

  • 该 playbook 将在所有清单主机上运行,主机清单引用综合练习1清单

  • 该 playbook 会将 /etc/issue 的内容替换为下方所示的一行文本:

  • 在 dev 主机组中的主机上,这行文本显示 为:Development

  • 在 prod 主机组中的主机上,这行文本显示 : Production

[Step1]:分别在三台主机上创建/etc/issue文件

bash 复制代码
ssh root@serverb "echo 111 > /etc/issue"
ssh root@serverc "echo 111 > /etc/issue"
ssh root@serverd "echo 111 > /etc/issue"

[Step2]:编写playbook

yaml 复制代码
vim issue.yml

# 写入下列内容
---
- name: play1
  hosts: all
  tasks:

  - name: Copy Text for dev
    ansible.builtin.copy:
      content: "Development"
      dest: /etc/issue.yml
    when: inventory_hostname in groups.dev


  - name: Copy Text for prod
    ansible.builtin.copy:
      content: "Production"
      dest: /etc/issue.yml
    when: inventory_hostname in groups.prod

[Step4]:校验playlook语法

bash 复制代码
ansible-navigator run issue.yml -m stdout --syntax-check

[Step5]:运行playbook

bash 复制代码
ansible-navigator run issue.yml -m stdout

[Step6]:验证:查看所有主机的文件内容

bash 复制代码
ssh root@serverb "cat /etc/issue.yml"
ssh root@serverc "cat /etc/issue.yml"
ssh root@serverd "cat /etc/issue.yml"
相关推荐
秦jh_5 分钟前
【Linux】多线程(概念,控制)
linux·运维·前端
keep__go1 小时前
Linux 批量配置互信
linux·运维·服务器·数据库·shell
矛取矛求2 小时前
Linux中给普通账户一次性提权
linux·运维·服务器
Fanstay9852 小时前
在Linux中使用Nginx和Docker进行项目部署
linux·nginx·docker
大熊程序猿2 小时前
ubuntu 安装kafka-eagle
linux·ubuntu·kafka
daizikui4 小时前
Linux文件目录命令
linux·运维·服务器
NikitaC4 小时前
ldconfig 和 LD_LIBRARY_PATH 区别
linux·c++
清源妙木真菌4 小时前
Linux:进程概念
linux
许嵩664 小时前
IC 脚本之VIM 记录
linux·编辑器·vim