六、ansible的条件判断

目录

一、when控制语句

 二、ansible中的条件判断和tests

1、条件判断和tests

2、判断变量的tests

3、判断执行结果的一些tests

4、判断是否是数字

5、判断是否是字符串

三、ansible中的条件判断与block

1、block 关键字

2、block 错误处理功能:

3、always 关键字

四、ansible中的条件判断 与错误处理fail模块 failed_when changed_when关键字

1、failed_when关键字

2、changed_when关键字


一、when控制语句

when 判断在用于控制在满足when所指定的条件的情况下 才执行相应的动作。

在when关键字中引用变量时,变量名不需要加"{{ }}",我们可以使用when关键字为任务指定条件,条件成立,则执行任务,条件不成立,则不执行任务。

比如:比如: Centos 与 Ubuntu 都需要安装 Apache ,而 Centos 系统软件包为httpd ,而 Ubuntu 系统软件包为httpd2 ,那么此时就需要判断主机系统,然后为不同的主机系统安装不同的软件包。

示例1:

为所有主机安装Apache软件,若系统为CentOS :安装httpd,若系统为Ubuntu :安装httpd2。


ansible_distribution 变量可以获取主机的发行版本
[root@k8s-master-1 variables]# ansible web -m setup -a 'filter=ansible_distribution'
192.168.134.138 | SUCCESS => {
    "ansible_facts": {
            "ansible_distribution": "CentOS", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
playbook 如下,因为我的系统是centos 的系统,所以在安装时候,会直接跳过
[root@k8s-master-1 test]# vim when.yaml
---
- hosts: web
  remote_user: root

  tasks:

  - name: test when
    yum:
      name: httpd2
      state: installed
    when: ansible_distribution=="Ubuntu"   <==判断版本语句,此处变量不需要{{ }}引用。
     # when也可以使用and与or方式进行多项匹配。
[root@k8s-master-1 test]# ansible-playbook when.yaml 

PLAY [web] **************************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.134.138]

TASK [test when] ****************************************************************
skipping: [192.168.134.138]

PLAY RECAP *********************************************************************
192.168.134.138            : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

示例2:

---
- hosts: web
  remote_user: root

  tasks:
  - name: test when
    debug:
      msg: "{{ item }}"
    with_items:
    - 1
    - 2
    - 3
    when: item >= 2 // 输出item的值大于等于2
[root@k8s-master-1 test]# ansible-playbook -C when.yaml
skipping: [192.168.134.138] => (item=1) 
ok: [192.168.134.138] => (item=2) => {
    "msg": 2
}
ok: [192.168.134.138] => (item=3) => {
    "msg": 3
}

示例3:

判断kubelet.service 服务是否正常运行,运行就停止,不运行不作处理

[root@k8s-master-1 test]# vim when.yaml
---
- hosts: web
  remote_user: root

  tasks:
  - name: Check Nginx Status
    shell: systemctl status kubelet.service
    register: check_k8s
  - name: Print check_k8s
    debug:
      var:
        "check_k8s"     <==#通过debug的var输出该变量的所有内容
  - name:
    service:
      name: kubelet.service
      state: stopped
    when: check_k8s.rc == 0    <==.rc是check_nginx变量中的执行结果,见下面的执行过程
[root@k8s-master-1 test]# ansible-playbook when.yaml 

PLAY [web] *******************************
TASK [Gathering Facts] *****************
ok: [192.168.134.138]

TASK [Check Nginx Status] *****************
changed: [192.168.134.138]

TASK [Print check_k8s] *********************
ok: [192.168.134.138] => {
    "check_k8s": {
        "changed": true, 
        "cmd": "systemctl status kubelet.service", 
        "delta": "0:00:00.006566", 
        "end": "2023-07-24 16:30:11.969695", 
        "failed": false, 
        "rc": 0,   <==.rc是check_nginx变量中的执行结果状态,0表示执行正常
        "start": "2023-07-24 16:30:11.963129", 
        "stderr": "", 
        "stderr_lines": [], 
       
        "stdout_lines": [
            "● kubelet.service - Kubernetes Kubelet", 
            "   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)", 
            "   Active: active (running) since 一 2023-07-24 16:27:35 CST; 2min 36s ago", 
            " Main PID: 40292 (kubelet)", 
            "   Memory: 48.5M", 
            "   CGroup: /system.slice/kubelet.service",             
        ]
    }
}

TASK [service] ********************
changed: [192.168.134.138]

PLAY RECAP ************************
192.168.134.138            : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

运算符

比较运算符

含义

>

大于

>=

大于等于

<

小于

<=

小于等于

==

等于

!=

不等于

逻辑运算符

含义

and

逻辑与,当左边与右边同时为真,则返回真

or

逻辑或,当左边或右边有一个为真时,返回真

not

取反,

()

组合

示例4:

运算符和ignore_errors关键字

---
- hosts: web
  remote_user: root

  tasks:
  - name: task1
    shell: "df -h"
    register: returnmsg
    ignore_errors: true   //设置为true,如果task1 报错,也不影响其他任务执行
  - name: task2
    debug:
      msg: "{{returnmsg.stdout_lines}}"
    when: returnmsg.rc == 0
  - name: task3
    debug:
      msg: "Command execution failed"
    when: returnmsg.rc != 0
[root@k8s-master-1 test]# ansible-playbook when.yaml
ok: [192.168.134.138] => {
    "msg": [
        "文件系统                 容量  已用  可用 已用% 挂载点", 
        "/dev/mapper/centos-root   36G  8.3G   27G   24% /", 
        "devtmpfs                 1.9G     0  1.9G    0% /dev", 
        "tmpfs                    1.9G     0  1.9G    0% /dev/shm", 
        "tmpfs                    1.9G   18M  1.9G    1% /run", 
        "tmpfs                    1.9G     0  1.9G    0% /sys/fs/cgroup", 
        "/dev/sda1               1014M  179M  836M   18% /boot", 
        "tmpfs                    378M   12K  378M    1% /run/user/42", 
        "tmpfs                    378M     0  378M    0% /run/user/0", 
    ]
}

TASK [task3] *******************************************************************
skipping: [192.168.134.138]

PLAY RECAP *********************************************************************
192.168.134.138         : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

 二、ansible中的条件判断和tests

1、条件判断和tests

        tests会将判断后的布尔值返回,如果条件成立,则返回true,如果条件不成立,tests会返回false,我们通常会在条件判断时使用到tests

示例:

---
- hosts: web
  remote_user: root

  vars:
    testpath: /tmp
  tasks:
  - name: test
    debug:
      msg: "file exist"
    when: testpath is exists
"is exists"中的"exists"就是tests的一种,判断ansible主机中的对应路径是否存在(注意:是ansible控制主机中的路径,与目标主机没有关系),当对应的路径存在于ansible控制节点时,"is exists"为真。
"is not exists"表示对应路径不存在时返回真。
上边我们学了 逻辑运算符,也可以使用 not testpath is exists   :表示取反,不存在则返回真

2、判断变量的tests

  • defined:判断变量是否已经定义,已经定义返回真
  • undefind:判断变量是否已经定义,没定义就返回真
  • none:判断变量值是否为空,如果变量已经定义,但变量值为空,则返回真

示例:

---
- hosts: web
  remote_user: root

  vars:
    test1: vl
    test2:
  tasks:
  - debug:
      msg: "test1 is defined"
    when: test1 is defined
  - debug:
      msg: "test1 is undefind"
    when: test2 is undefined
[root@k8s-master-1 condition]# ansible-playbook pd2.yaml
TASK [debug] *****************************************************************
ok: [192.168.134.138] => {
    "msg": "test1 is defined"
}

TASK [debug] ****************************************************************
ok: [192.168.134.138] => {
    "msg": "test1 is undefind"
}

3、判断执行结果的一些tests

  • success或者succeeded:通过任务的返回信息判断任务的执行状态,任务执行成功则返回真
  • failure 或 failed:通过任务的返回信息判断任务的执行状态,任务执行失败则返回真
  • change 或 changed:通过任务的返回信息判断任务的执行状态,任务执行状态为changed则返回真
  • skip 或 skipped:通过任务的返回信息判断任务的执行状态,当任务没有满足条件,而被跳过执行时,则返回真

4、判断是否是数字

  • number:判断对象是否是一个数字,是数字则返回真

5、判断是否是字符串

  • string:判断对象是否是一个字符串,是字符串则返回真

三、ansible中的条件判断与block

        when 关键字表示:当条件成立时,我们只能执行一个任务,如果我们想要在条件成立的情况下,执行多个任务,那该怎么解决呢?

1、block 关键字

---
- hosts: web
  remote_user: root
  tasks:
  - name: test
    debug:
      msg: "test 1 2 3 "
  - name: test block
    block:
    - debug:
        msg: "test2"
    - debug:
        msg: "test3"
    when: 2 > 1
[root@k8s-master-1 condition]# ansible-playbook  pd3.yaml
TASK [test] *******************************************************************
ok: [192.168.134.138] => {
    "msg": "test 1 2 3 "
}

TASK [debug] *******************************************************************
ok: [192.168.134.138] => {
    "msg": "test2"
}

TASK [debug] ********************************************************************
ok: [192.168.134.138] => {
    "msg": "test3"
}
上例中一共包含三个任务,第一个任务使用debug模块输出了 "task1 1 2 3 "这句话,在第一个任务之后,我们定义了一个block,这个block中包含两个任务,两个debug任务分别输出各自的信息,上例的when关键字与block关键字对齐,表示when关键字的条件是针对block的,当when对应的条件成立,则执行block中的两个任务。

2、block 错误处理功能:

        "错误处理"功能就是当某任务出错时,执行指定的其他任务,打个比方,我们想要在A任务执行失败时执行B任务,如果A任务执行成功,则无需执行B任务,实现这个功能,就能够使用block,当然,我们还有一些别的方法,也可以实现类似的功能,比如前文中提到的jinja2的tests,有个一名为failed的test,借助failed也可以实现类似的功能,

示例

---
- hosts: web
  remote_user: root
  tasks:
  - shell: 'ls /ooo'
    register: return_value
    ignore_errors: true
  - debug:
      msg: "i caught an error"
    when: return_value is failed
如上示例,web主机中,没有000 目录,所以是报错不执行的,但是把报错写进了变量return_value 中,然后使用 is failed 进行判断,如果条件成立,代表shell出错,就执行debug任务
2、使用block示例:
---
- hosts: web
  remote_user: root
  tasks:
  - name: test block
    block:
    - shell: 'ls /ooo'
    rescue:
    - debug:
        msg: "i caught an error"
[root@k8s-master-1 condition]# ansible-playbook -C pd4.yaml
ok: [192.168.134.138] => {
    "msg": "i caught an error"
}
如上所示:定义了一个block,web主机中,没有000 目录,所以是报错不执行的,除了block关键字,还有另外一个关键字rescue,rescue关键字与block关键字对齐,rescue的字面意思为"救援",表示当block中的任务执行失败时,会执行rescue中的任务进行补救。当block中的任务出错时,会执行rescue中的任务,当block中的任务顺利执行时,则不会执行rescue中的任务:
---
- hosts: web
  remote_user: root
  tasks:
  - name: test block
    block:
    - shell: 'ls /tmp'
      register: return_value
    - debug:
        msg: "{{ return_value.stdout_lines }}"
    rescue:
    - debug:
        msg: "i caught an error"
[root@k8s-master-1 condition]# ansible-playbook pd4.yaml
ok: [192.168.134.138] => {
    "msg": [
        "a.log", 
        "ansible_command_payload_HmpFJ4", 
        "asd.yaml", 
        "asd.yaml.31523.2023-07-25@10:27:55~", 
        "systemd-private-64d62f5f121349008dac5639e0d3cd34-colord.service-SA1hiU", 
        "systemd-private-64d62f5f121349008dac5639e0d3cd34-cups.service-1xLJWH", 
        "systemd-private-64d62f5f121349008dac5639e0d3cd34-rtkit-daemon.service-47dWX8", 
        "systemd-private-64d62f5f121349008dac5639e0d3cd34-vgauthd.service-H9RsHM", 
        "systemd-private-64d62f5f121349008dac5639e0d3cd34-vmtoolsd.service-b3zMCq", 
        "tracker-extract-files.1000"
    ]
}
这个示例是正常的 就输出/tmp 下的目录,rescue 任务 会跳过不执行。

3、always 关键字

always 关键字:意思就是无论block中的任务失败还是成功  always任务 都会执行
示例:
---
- hosts: web
  remote_user: root
  tasks:
  - name: test block
    block:
    - shell: 'ls /000'
      register: return_value
    - debug:
        msg: "{{ return_value.stdout_lines }}"
    rescue:
    - debug:
        msg: "i caught an error"
    always:
    - debug:
        msg: "asddsaasddsa"
[root@k8s-master-1 condition]# ansible-playbook pd4.yaml
TASK [shell] ********************************
fatal: [192.168.134.138]: FAILED! => {"changed": true, "cmd": "ls /000", "delta": "0:00:00.005273", "end": "2023-08-03 10:40:36.440712", "msg": "non-zero return code", "rc": 2, "start": "2023-08-03 10:40:36.435439", "stderr": "ls: 无法访问/000: 没有那个文件或目录", "stderr_lines": ["ls: 无法访问/000: 没有那个文件或目录"], "stdout": "", "stdout_lines": []}

TASK [debug] *************************************
ok: [192.168.134.138] => {
    "msg": "i caught an error"
}

TASK [debug] ***********************************
ok: [192.168.134.138] => {
    "msg": "asddsaasddsa"
}

四、ansible中的条件判断 与错误处理fail模块 failed_when changed_when关键字

1、failed_when关键字

作用:当对应的条件成立时,将对应的任务执行的状态设置为失败。

示例:

[root@k8s-master-1 condition]# vim failed_when.yaml
---
- hosts: web
  remote_user: root

  tasks:
  - debug:
      msg: "I execute normally"

  - shell: "echo 'This is a string for testing error'"
    register: return_value
    failed_when: ' "error" in return_value.stdout'

  - debug:
      msg: "I never execute,Because the playbook has stopped"
上例中,一共有三个任务,第一个任务通过debug模块输出 “I execute normally”,第二个任务调用shell模块,echo了'This is a string for testing error'这句话,并且将返回值注册到了'return_value'变量中,'failed_when'关键字与shell关键字对齐,表示其对应的条件是针对shell模块的,'failed_when'对应的条件是"error” in return_value.stdout",表示"error"字符串如果存在于shell模块执行后的标准输出中,则条件成立,当条件成立后,shell模块的执行状态将会被设置为失败,由于shell模块的执行状态被设置为失败,所以playbook会终止运行,于是,最后的debug模块并不会被执行.

'failed_when'虽然会将任务的执行状态设置为失败,但是并不代表任务真的失败了,就以上例来说,上例的shell模块的确是完全正常的执行了,只不过在执行之后,'failed_when'对应的条件成立了,'failed_when'将shell模块的执行状态设置为失败而已,所以,'failed_when'并不会影响shell模块的执行过程,只会在条件成立时影响shell模块最终的执行状态,以便停止playbook的运行。

2、changed_when关键字

作用:在条件成立时,将对应任务的执行状态设置为changed

示例:

正常情况下:
[root@k8s-master-1 condition]# vim changed_when.yaml
---
- hosts: web
  remote_user: root
  tasks:
  - debug:
      msg: "test message"
    changed_when: 2 > 1
[root@k8s-master-1 condition]# ansible-playbook changed_when.yaml
ok: [192.168.134.138] => {
    "msg": "test message"
}
状态是“ok”
2、使用changed_when 关键字
[root@k8s-master-1 condition]# ansible-playbook changed_when.yaml
changed: [192.168.134.138] => {
    "msg": "test message"
}
前文中总结过handlers的用法,我们知道,只有任务作出了实际的操作时(执行后状态为changed),才会真正的执行对应的handlers,而在某些时候,如果想要通过任务执行后的返回值将任务的最终执行状态判定为changed,则可以使用'changed_when'关键字,以便条件成立时,可以执行对应的handlers。
其实,'changed_when'除了能够在条件成立时将任务的执行状态设置为"changed",还能让对应的任务永远不能是changed状态
当将'changed_when'直接设置为 false 时,对应任务的状态将不会被设置为'changed',如果任务原本的执行状态为'changed',最终则会被设置为'ok'.
  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁华依在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值