Playbook条件语句

  • 在有的时候play会依赖于变量,fact或者前一个任务的执行结果,或者基于上一个任务执行返回的结果而决定如何执行后续的任务,这个时候就需要用到条件判断
  • 应用场景
    • 某个任务要求运行的主机最少要有1G内存或者10G的磁盘
    • 捕获一个命令的输出,根据输出来触发不同的任务
    • 根据不同的操作系统来定义不同的任务
    • 根据目标主机的CPU来定义调优参数

1. when的基本使用

  • 在ansible中,使用的条件判断是when

1.1 when的基本示例

[ansible@master ansible]$ vim when-rhel.yaml
- name: install vim
hosts: test
tasks:
- name: install vim via yum
yum:
name: vim
state: present
when: ansible_os_family == "RedHat"
  • ansible_os_family 这个变量可以在setup收集的信息里面找到

    为什么需要用到判断呢?

    因为只有在红帽系的发行版中,包管理工具使用的是yum,而在debian的系列中,使用的apt,所以如果你管理的主机有红帽系的,也有debian系的,那么就需要写一个判断来让他们分开执行

[ansible@master ansible]$ ansible-playbook when-rhel.yaml
TASK [install vim via yum] *****************************************************
ok: [192.168.200.200]
ok: [192.168.200.210]
PLAY RECAP *********************************************************************
192.168.200.200 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.200.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

通过这个回显我们可以得知,任务他是要执行的,但是由于我们的系统上有vim,所以他没有发生改变,显示的是ok

那我们将ansible_os_family == "RedHat" 改为Debian看看呢

- name: install vim
hosts: test
tasks:
- name: install vim via yum
yum:
name: vim
state: present
when: ansible_os_family == "Debain"

执行剧本

[ansible@master ansible]$ ansible-playbook when-rhel.yaml 

PLAY [install vim] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.200]
ok: [192.168.200.210] TASK [install vim via yum] *****************************************************
skipping: [192.168.200.210]
skipping: [192.168.200.200] PLAY RECAP *********************************************************************
192.168.200.200 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
192.168.200.210 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

可以看到,他的状态是skipping,也就说跳过的意思,因为他没有跟条件语句匹配上,所以他不会执行

1.2比较运算符

在ansible中,支持以下比较运算符

  • ==:比较两个对象是否相等
  • !=:比较两个对象是否不相等
  • >:比较两个对象的大小
  • <
  • >=
  • <=

1.3 比较运算符示例

  • when: ansible_machine == "x86_64"
  • when: ansible_memtotal_mb >= 1024

1.4 逻辑运算符

  • and: 逻辑与,当两边都为真时为真
  • or:逻辑或,当有一边为真时为真
  • not:逻辑否,对表达式取反
  • ():可以将多个语句写到一个括号里面,括号内的表达式都是逻辑与的关系

1.5 逻辑运算符示例

  • when: ansible_distribution == "openEuler" or nsible_distribution == "RedHat"

    • 表示判断操作系统是openEuler或者RedHat任意一者都行
  • when: ansible_machine == "x86_64" and ansible_memtotal_mb > 1024
    • 表示架构必须是x86并且机器的内存得大于1024m才行

2. 条件判断与block

  • 假设现在的场景是这样的,操作系统刚装完,现在需要你对这些系统进行一些初始化的操作,比如安装一些必要的软件包,关闭防火墙,selinux,但是现在有一个问题,就是这些操作系统并不一定都是红帽,可能还有Debian,Debian上面的操作跟红帽的操作就又不一样了啊

  • 如果我们按照之前的思维,那么就是安装软件包的时候有一个判断语句,关闭selinux又是一个判断语句,这样下来我们就需要写很多一模一样的判断语句了,能不能只写一条,这条判断语句过了之后直接执行对应的一系列任务呢? 是可以的

2.1 block示例

[ansible@master ansible]$ vim block.yaml
- name: block
hosts: test
tasks:
- block:
- name: install software
yum:
name: vim
state: present
- name: disable Selinux
selinux:
policy: targeted
state: disabled
- name: disabled firewalld
systemd:
name: firewalld
state: stopped
enabled: no
when: ansible_os_family == "RedHat" - block:
- name: install software
apt:
name: vim
state: present
when: ansible_os_family == "Debian"

通过加上block之后,在block里面定义的任务就是一个整体了,那么条件判断也是针对这个block的,如果条件判断返回为真之后,那么这个block里面的所有任务都会被执行

  • 我们的第一个block就是来判断是否为红帽系的系统,如果是的话那么就会执行那3个任务
  • 如果我们使用的系统是Debian系列的话,那么就会执行第二个block了

2.2 rescue

block除了能和when一起使用之外,还可以和rescue一起使用,作用是能做错误处理

[ansible@master ansible]$ vim rescue.yaml
- name: rescue
hosts: test
tasks:
- block:
- name: test file exist
shell: "ls /aaa.txt"
rescue:
- name: print file is not exist
debug:
msg: 'file is not exist'

我们的文件 /aaa.txt是不存在的,所以他执行这个任务会报错,但是正常情况下,举报报错就会停止执行了,后面的任务也就不会有输出了,rescue就是来做错误处理的,如果这里面有错误的话,他不会影响剧本执行,反而还会触发resue字段里的任务

[ansible@master ansible]$ ansible-playbook rescue.yaml 

PLAY [rescue] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.200.200]
ok: [192.168.200.210] TASK [test file exist] *********************************************************
fatal: [192.168.200.210]: FAILED! => {"changed": true, "cmd": "ls /aaa.txt", "delta": "0:00:00.002396", "end": "2024-06-21 10:20:25.001243", "msg": "non-zero return code", "rc": 2, "start": "2024-06-21 10:20:24.998847", "stderr": "ls: cannot access '/aaa.txt': No such file or directory", "stderr_lines": ["ls: cannot access '/aaa.txt': No such file or directory"], "stdout": "", "stdout_lines": []}
fatal: [192.168.200.200]: FAILED! => {"changed": true, "cmd": "ls /aaa.txt", "delta": "0:00:01.003922", "end": "2024-06-21 10:20:25.992768", "msg": "non-zero return code", "rc": 2, "start": "2024-06-21 10:20:24.988846", "stderr": "ls: cannot access '/aaa.txt': No such file or directory", "stderr_lines": ["ls: cannot access '/aaa.txt': No such file or directory"], "stdout": "", "stdout_lines": []} TASK [print file is not exist] *************************************************
ok: [192.168.200.210] => {
"msg": "file is not exist"
}
ok: [192.168.200.200] => {
"msg": "file is not exist"
} PLAY RECAP *********************************************************************
192.168.200.200 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
192.168.200.210 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0

我们可以看到,执行命令报错了,但是任务剧本没有被打断,后面还输出了file is not exist

那我们来将文件改为存在的,看看rescue还会执行吗

[ansible@master ansible]$ vim rescue.yaml
- name: rescue
hosts: test
tasks:
- block:
- name: test file exist
shell: "ls /etc/passwd"
rescue:
- name: print file is not exist
debug:
msg: 'file is not exist'

执行这个剧本

[ansible@master ansible]$ ansible-playbook rescue.yaml
[ansible@master ansible]$ ansible-playbook rescue.yaml PLAY [rescue] ****************************************************************** TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]
ok: [192.168.200.200] TASK [test file exist] *********************************************************
changed: [192.168.200.200]
changed: [192.168.200.210] PLAY RECAP *********************************************************************
192.168.200.200 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.200.210 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

我们可以看到,这个任务执行成功了,他没有输出rescue里面定义的任务

也就是说,只有block里面的任务出错的时候rescue才会接管任务,平时是不会执行的

2.3 always

当block执行失败,rescue才会执行;而无论block失败还是成功,always里面的任务都将会执行

- name: always
hosts: test
tasks:
- block:
- name: success
debug:
msg: "this is success task"
- name: faild
debug:
msg: "{{ aaa }}"
rescue:
- name: print faile
debug:
msg: "Task failure"
always:
- name: print always
debug:
msg: "This task is always performed"

这个剧本定义了一个成功的任务,一个失败的任务,当有任务失败的时候会触发rescue,当所以任务执行完之后会执行always

[ansible@master ansible]$ ansible-playbook always.yaml
[ansible@master ansible]$ ansible-playbook always.yaml PLAY [always] ****************************************************************** TASK [Gathering Facts] *********************************************************
ok: [192.168.200.210]
ok: [192.168.200.200] TASK [success] *****************************************************************
ok: [192.168.200.210] => {
"msg": "this is success task"
}
ok: [192.168.200.200] => {
"msg": "this is success task"
} TASK [faild] *******************************************************************
fatal: [192.168.200.210]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'aaa' is undefined\n\nThe error appears to be in '/home/ansible/ansible/always.yaml': line 8, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n msg: \"this is success task\"\n - name: faild\n ^ here\n"}
fatal: [192.168.200.200]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'aaa' is undefined\n\nThe error appears to be in '/home/ansible/ansible/always.yaml': line 8, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n msg: \"this is success task\"\n - name: faild\n ^ here\n"} TASK [print faile] *************************************************************
ok: [192.168.200.210] => {
"msg": "Task failure"
}
ok: [192.168.200.200] => {
"msg": "Task failure"
} TASK [print always] ************************************************************
ok: [192.168.200.210] => {
"msg": "This task is always performed"
}
ok: [192.168.200.200] => {
"msg": "This task is always performed"
}

Playbook条件语句的更多相关文章

  1. Ansible14:Playbook条件语句

    目录 简介 when关键字 1. when基本使用 2. 比较运算符 3. 逻辑运算符 条件判断与tests 判断变量 判断执行结果 判断路径 判断字符串 判断整除 其他tests 条件判断与bloc ...

  2. Ansible的条件语句

    此篇主要讲述的ansible的condition,主要是用条件进行一些判断,此篇为官方文档的翻译,没有进行相关的测试,后续会写入相关的测试. Ansible的条件语句 1.    前言 在有的时候pl ...

  3. Ansible9:条件语句【转】

    在有的时候play的结果依赖于变量.fact或者是前一个任务的执行结果,从而需要使用到条件语句. 一.when    有的时候在特定的主机需要跳过特定的步骤,例如在安装包的时候,需要指定主机的操作系统 ...

  4. ansible之条件语句when

    注册变量: 变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用.例如: - hosts: webservers tasks: - shell: /usr/bin/foo ...

  5. ansible 之条件语句 when

    注册变量: 变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用.例如: - hosts: webservers tasks: - shell: /usr/bin/foo ...

  6. 011.Ansible条件语句

    一 简介 在有的时候play的结果依赖于变量.fact或者是前一个任务的执行结果,或者有的时候,我们会基于上一个task执行返回的结果而决定如何执行后续的task.这个时候就需要用到条件判断. 条件语 ...

  7. Python —条件语句

    条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空(null ...

  8. php简写表达式,&& or || 缩写条件语句

    有时候学的多了, 好多小细节 都忘了 ,比如 简单的表达式, 三元表达式   ?:; $aa or $bb 表达式 等等! 写一些简单的表达式,备忘! php用&&和||缩写条件语句 ...

  9. java中的条件语句(if、if...else、多重if、嵌套if)

    Java条件语句之 if 生活中,我们经常需要先做判断,然后才决定是否要做某件事情.例如,如果考试成绩大于 90 分,则奖励一个 IPHONE 5S .对于这种"需要先判断条件,条件满足后才 ...

  10. javascript语句——条件语句、循环语句和跳转语句

    × 目录 [1]条件语句 [2]循环语句 [3]跳转语句 前面的话 默认情况下,javascript解释器依照语句的编写顺序依次执行.而javascript中的很多语句可以改变语句的默认执行顺序.本文 ...

随机推荐

  1. [Trading] 专业交易: 专业交易员和散户交易员的不同, 什么是专业交易员

    专业交易员可能用的是公司的钱或者自己的钱 有基本工资支持,散户用的是自己的钱 没有人提供工资来做交易. 目标不同,专业交易员的目的是增长投资账户和获得奖金,散户大部分是为了提取盈利收入而无法增长投资账 ...

  2. 记 dotnet 8.0.4 修复的 WPF 的触摸模块安全问题

    本文记录 dotnet 8.0.4 版本修复的 WPF 的触摸模块安全问题,此问题影响所有的 .NET 版本,修复方法是更新 SDK 和运行时 宣布安全漏洞地址: https://github.com ...

  3. IIncrementalGenerator 获取项目默认命名空间

    本文将告诉大家如何在分析器里面获取到项目的默认命名空间 在 Roslyn 分析器里面读取项目的默认命名空间,可以通过读取项目的属性配置实现.通过 IIncrementalGenerator 增量 So ...

  4. WPF 已知问题 Popup 吃掉 PreviewMouseDown 事件

    在 WPF 中,使用 Popup 也许会看到 PreviewMouseDown 事件被吃掉 因为 PreviewMouseDown 是 RoutingStrategy.Direct 路由事件,不能在多 ...

  5. C# dotnet 的锁 SemaphoreSlim 和队列

    本文主要是试验在顺序进入等待 SemaphoreSlim 的任务是否会按照顺序经过锁执行 我在一个有趣的WPF程序里面,需要限制任务同时执行的线程数量,不然用户就会说用我的程序会让电脑卡渣.而我的任务 ...

  6. 数据可视化之matplotlib模块

    一.简介 Matplotlib是一个强大的Python绘图和数据可视化的工具包.数据可视化也是我们数据分析的最重要的工作之一,可以帮助我们完成很多操作,例如:找出异常值.必要的一些数据转换等.完成数据 ...

  7. dockerfile构建镜像常用命令

    一.什么是dockerfile Dockerfile是一个包含用于组合映像的命令的文本文档.可以使用在命令行中调用任何命令. Docker通过读取Dockerfile中的指令自动生成映像. docke ...

  8. C语言的指针不能与数组之前的内存进行比较

    标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但是不允许与指向数组第一个元素之前的那个内存位置的指针进行比较. 案例一 #define DATAMAX 5 int ...

  9. 移动端、微信小程序兼容性问题汇总(持续更新……

    1. safari浏览器字体不能自动随网页缩放调整大小 -webkit-text-size-adjust:100% 2. 点击<button><input>有灰色透明背景 -w ...

  10. Dijkstra迪杰斯特拉求最短路和最短路的条数和各个点权值的最大值

    作为一个城市的紧急救援队队长,你会得到一张你所在国家的特殊地图. 该地图显示了由一些道路连接的几个分散的城市. 地图上标出了每个城市的救援队伍数量以及任意两个城市之间每条道路的长度. 当其他城市接到紧 ...