ansible————task控制

一、loop循环

当某一个操作需要多次执行的时候,就需要用到循环

1、循环语句

安装多个安装包,启动多个应用

[root@control ansible_manage]# cat play_book/loop.yaml 
---
- name: loop exercise
  hosts: manage1
  vars_files:
    - var/loop_var.yaml
  tasks:
    - name: install pkg
      yum:
        name: "{{ item }}"
        state: latest
      loop: "{{ web_related_pkg }}"
      
    - name: start service
      service:
        name: "{{ item }}"
        enabled: true
        state: started
      loop:  "{{ web_related_service }}"

循环loop使"{{ item }}"位置的变量进行循环,loop位置的变量则使在变量文件中的变量

[root@control ansible_manage]# cat play_book/var/loop_var.yaml 
web_related_pkg:
  - httpd
  - firewalld
  - mariadb-server
  - vsftpd
web_related_service:
  - httpd
  - firewalld
  - vsftpd
  - mariadb

运行

[root@control ansible_manage]# ansible-playbook play_book/loop.yaml

2、loop循环和变量矩阵

user:   
  - name: jinna
    groups: nana
  - name: cui
    groups: nana

有"-"的为同一个级别

二、条件判断

使用场景

  • 基于可用内存,筛选主机

  • 基于命令输出,

  • 根据facts变量决定使用什么文件

  • 根据cpu的数量来调优web服务器

  • 比较register变量来决定是否一个服务状态要改变

when语句

写一个循环,当httpd没有安装的时候,就安装httpd

[root@control ansible_manage]# cat play_book/when.yaml 
---
- name: loop exercise
  hosts: manage1
  vars:
    my_service: httpd
  tasks:
## 当my_service没有被定义的时候执行
    - name: debug httpd
      debug:
        var: my_service
      when: my_service is not defined
## 当service没有被定义的时候执行
    - name: debug httpd 2
      debug:
        var: my_service
      when: service is not defined

根据表述可得知,第二个debug应该会被执行

[root@control ansible_manage]# ansible-playbook play_book/when.yaml

PLAY [loop exercise] ********************************************************************************************

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

TASK [debug httpd] **********************************************************************************************
skipping: [manage1]

TASK [debug httpd 2] **********************************************************************************************
ok: [manage1] => {
    "my_service": "httpd"
}

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

结果可用看到,第一个debug模块没有被执行

判断语句的判断

  • [变量] == [值]

  • [变量] < [值]

  • [变量] > [值]

  • [变量] <= [值]

  • [变量] >= [值]

  • [变量] != [值]

  • [变量] is defined:什么被定义

  • [变量] is not defined:什么没有被定义

  • true、yes、1:可用直接定义布尔值,执行

  • false、no、0:可用直接定义布尔值,不执行

  • [单变量] in [变量矩阵]:用在变量矩阵中,单变量在变量矩阵中的时候,执行

多重判断语句

and:两个条件都要满足

or:只需要满足一个

[root@control ansible_manage]# cat play_book/when2.yaml 
---
- name: loop exercise
  hosts: manage1
  vars:
    my_service: httpd
    my_service2: nana
  tasks:
## 当my_service没有被定义或者my_service被定义的时候执行
    - name: debug httpd
      debug:
        var: my_service
      when: my_service is not defined or my_service2 is defined
## 当service没有被定义和my_service2被定义的时候执行
    - name: debug httpd 2
      debug:
        var: my_service
      when: service is not defined and my_service2 is defined

 运行

[root@control ansible_manage]# ansible-playbook play_book/when2.yaml 

PLAY [loop exercise] ********************************************************************************************

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

TASK [debug httpd] **********************************************************************************************
ok: [manage1] => {
    "my_service": "httpd"
}

TASK [debug httpd 2] ********************************************************************************************
ok: [manage1] => {
    "my_service": "httpd"
}

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

可以看到两个debug模块都执行了

三、handlers

是一个特殊的处理器,作用是检测tasks的状态

当tasks出现changed状态的时候,可用做对应的操作

大量用于服务的重启

1、handlers控制服务的重启

当firewalld关闭的时候,重新启动firewalld

[root@control ansible_manage]# cat  play_book/handlers.yaml
---
- name: handlers exercise
  hosts: manage1
  tasks:
    - name: use systemd stop firewalld
      systemd:
        name: firewalld
        state: stopped
      notify:
        - restart firewalld

## 必须有在上方定义了notify,handlers才能生效
  handlers: 
## name的名字对应上方notify定义的名字
    - name: restart firewalld
      debug:
        msg: the firewalld is down, now open
    - name: restart firewalld
      service:
        name: firewalld
        state: restarted

开启manage1的防火墙

[root@manage1 ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; preset: enabled)
     Active: active (running) since Wed 2024-04-03 15:10:36 CST; 4s ago
       Docs: man:firewalld(1)
   Main PID: 109653 (firewalld)
      Tasks: 2 (limit: 10684)
     Memory: 25.1M
        CPU: 274ms
     CGroup: /system.slice/firewalld.service
             └─109653 /usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid

Apr 03 15:10:36 manage1 systemd[1]: Starting firewalld - dynamic firewall daemon...
Apr 03 15:10:36 manage1 systemd[1]: Started firewalld - dynamic firewall daemon.

运行ansible-playbook

[root@control ansible_manage]# ansible-playbook play_book/handlers.yaml 

PLAY [handlers exercise] ***************************************************************************************************

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

TASK [use systemd stop firewalld] ******************************************************************************************
changed: [manage1]

RUNNING HANDLER [restart firewalld] ****************************************************************************************
ok: [manage1] => {
    "msg": "the firewalld is down, now open"
}

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

当模块定义了notify,当状态发生改变的时候,就会启动handlers对firewalld进行重启

2、handlers强制执行

handlers只有在这个tasks执行完毕之后,才会执行,如果中间有错误,就无法执行

但是在前面定义一个force_handlers: yes,即使出现错误,也可以执行成功

[root@control ansible_manage]# cat play_book/handlers1.yaml 
---
- name: handlers exercise
  hosts: manage1
## force_handlers这参数可以定义即使下面的有错误,定义了notify的模块也会通知handlers,进行操作
  force_handlers: yes
  tasks:
    - name: use systemd stop firewalld
      command: /bin/true
      notify: restart the database

    - name: a tasj which fails because the package doesn't exist
      yum:
        name: nnnnnnnnn  ## 这个软件不存在,就会有报错
        state: latse

  handlers:
    - name: restart the database
      debug:
        msg: the firewalld is down, now open
    - name: restart the database
      service:
        name: firewalld
        state: restarted

 运行playbook四

[root@control ansible_manage]# ansible-playbook play_book/handlers1.yaml 

PLAY [handlers exercise] ***************************************************************************************************

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

TASK [use systemd stop firewalld] ******************************************************************************************
changed: [manage1]

TASK [a tasj which fails because the package doesn't exist] ****************************************************************
fatal: [manage1]: FAILED! => {"changed": false, "msg": "value of state must be one of: absent, installed, latest, present, removed, got: latse"}

RUNNING HANDLER [restart the database] *************************************************************************************
ok: [manage1] => {
    "msg": "the firewalld is down, now open"
}

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

四、ansible的错误控制

在ansible playbook中会写一些预期错误的操作

比如:备份,当空间不够的时候,会报错,就会导致备份不成功

1、忽略task的错误:ignore_errors

使用ignore_errors就能忽略这个错误

写一个yaml文件,使用yum模块安装两个服务,其中第一个服务是随便写的,没有这个服务,第二个服务是httpd

正常情况下,第一个安装包安装失败,就会停止playbook,但是使用ignore_errors可以忽略第一个错误,安装第二个软件包

[root@control ansible_manage]# cat play_book/ignore_erors.yaml 
---
- name: ignore_errors play
  hosts: manage1
  tasks:
    - name: install pkg
      yum:
        name: nananananan
        state: present
      ignore_errors: yes
    - name: install httpd
      yum:
        name: httpd
        state: present

运行playbook

[root@control ansible_manage]# ansible-playbook play_book/ignore_erors.yaml 

PLAY [ignore_errors play] **************************************************************************************************

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

TASK [install pkg] *********************************************************************************************************
fatal: [manage1]: FAILED! => {"changed": false, "failures": ["No package nananananan available."], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
...ignoring

TASK [install httpd] *******************************************************************************************************
ok: [manage1]

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

2、标记tasks状态:failed_when

failed_when一般用在ansible和脚本的结合

ansible和脚本结合可以使用shell模块

ansible执行脚本,每一次的直接结果都是changeed(只有在个别情况下才会报错,比如,没有调用权限,脚本不存在等),无法判断脚本是否运行成功

控制failed状态

可以使用register变量和failed_when结合进行对tasks状态的控制

可以通过标准输出来控制脚本运行的状态

1、简单写一个脚本,并赋予权限

[root@manage1 ~]# cat install_web.sh 
#!/bin/bash
## install web

yum -y install httpd &>> /dev/null
{
        if [ "$?" == 0 ]
        then
                state=success
        else
                state=fail
        fi
}
echo success
# start httpd
systemctl start httpd &>> /dev/null
systemctl enable httpd  &>> /dev/null
[root@manage1 ~]# chmod +x install_web.sh 

当执行脚本的时候,如果执行成功,返回的结果是success,失败返回的结果就是fail

2、写一个安装web的playbook

[root@control ansible_manage]# cat play_book/install_web.yaml 
---
- name: ignore_errors play
  hosts: manage1
  tasks:
    - name: install pkg
      shell: /root/install_web.sh
      register: command_result
      failed_when: " 'success' not in command_result.stdout "

    - name: debug command_result
      debug:
        var: command_result

使用register变量,如果在变量command_result.stdout中出现success,则表示脚本运行成功

failed_when: " 'success' not in command_result.stdout "是指,如果字段success不在变量command_result.stdout中,就不会报错

3、运行

[root@control ansible_manage]# ansible-playbook play_book/install_web.yaml 

PLAY [ignore_errors play] **************************************************************************************************

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

TASK [install pkg] *********************************************************************************************************
changed: [manage1]

TASK [debug command_result] ************************************************************************************************
ok: [manage1] => {
    "command_result": {
        "changed": true,
        "cmd": "/root/install_web.sh",
        "delta": "0:00:01.139397",
        "end": "2024-04-03 17:49:18.804363",
        "failed": false,
        "failed_when_result": false,
        "msg": "",
        "rc": 0,
        "start": "2024-04-03 17:49:17.664966",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "success",
        "stdout_lines": [
            "success"
        ]
    }
}

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

task状态是changes状态,表示脚本执行成功

从debug模块可以看出,register变量中有command_result.stdout中有seccess字段

控制task的changed状态

只要使用了command模块,就会出现changed的状态

可以使用changed_when: false可以强制改变changed模块,为ok

changed_when: true将状态改变为changed

1、写一个command模块的playbook

[root@control ansible_manage]# cat play_book/change_changed.yaml 
---
- name: ignore_errors play
  hosts: manage1
  tasks:
    - name: command
      command: echo "I love you"
      changed_when: false

2、执行

[root@control ansible_manage]# ansible-playbook play_book/change_changed.yaml 

PLAY [ignore_errors play] **************************************************************************************************

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

TASK [command] *************************************************************************************************************
ok: [manage1]

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

可以看到状态不是changed,而是ok

如果把changed_when: false去掉,则就是changed的状态

root@control ansible_manage]# ansible-playbook play_book/change_changed.yaml 

PLAY [ignore_errors play] **************************************************************************************************

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

TASK [command] *************************************************************************************************************
changed: [manage1]

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

五、block、rescue、always

block、rescue、always都可以定义一组task

  • block:定义一组task

  • rescue:当block块内的task执行失败的时候执行

  • always:无论上面两个执行成功还是失败,都执行

[root@control ansible_manage]# cat play_book/change_changed.yaml
---
- name: ignore_errors play
  hosts: manage1
  tasks:
    - name: use command
      block:
        - name: command echo
          command: echo "sdasdddd"
        - name: 
          command: echo "csdd sdsdd a"
      rescue:
        - name: command
          command: echo "hahahahahha"
        - name: command
          command: echo "aaaaaaaaa"
      always:
        - name: command
          command: echo "aaaaaaaaaa"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值