任务控制

编写循环和条件任务

利用循环迭代任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

简单循环

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

- name: test
  service:
    name: httpd
    state: started
    
- name: Devecot is running
  service:
    name: mariadb
    state: started

#计划循环
- name: test
  service: "{{ item }}"
    name: 
    state: started
  loop:
  - httpd
  - mariadb
  

可以通过一个变量提供loop所使用的列表。在以下示例中,变量services含有需要处于运行状态的服务的列表。

vars:
  services:
    - httpd
    - mariadb

tasks:
  - name: test
    service:
      name: "{{ item }}"
      state: started
    loop: "{{ services }}"

循环散列或字典列表

loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过item.name和item.groups变量来检索。

- name: test
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop:
    - name: mike
      groups: tom
    - name: jerry
      groups: root

将Register变量与Loop一起使用

register关键字也可以捕获循环任务的输出。以下代码片段显示了循环任务中register变量的结构:

[root@localhost ~]# vim test.yml
---
- name: test
  gather_facts: no
  hosts: 192.168.8.130
  tasks:
    - name: loop
      shell: "echo This is my item: {{ item }}"
      loop:
        - one
        - two
      register: echo_results    # 注册echo_results变量
      
    - name: results
      debug:
        var: echo_results       # echo_results变量的内容显示在屏幕上
        

有条件地运行任务

Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。

我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。
以下场景说明了在Ansible中使用条件的情况:

  • 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
  • Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理。
  • 可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)。
  • 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
  • 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改。

条件任务语法

when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。

可以测试的一个最简单条件是某一布尔变量是True还是False。以下示例中的when语句导致任务仅在run_my_task为True时运行:

---
- name: test
  hosts: 192.168.8.130
  vars:
    run_my_task: True
  tasks:
    - name: install httpd
      yum:
        name: httpd
      when: run_my_task

下表显示了在处理条件时可使用的一些运算:

操作示例
等于(值为字符串)ansible_machine == “x86_64”
等于(值为数字)max_memory == 512
小于min_memory < 128
大于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的求值为Truememory_available
布尔变量是False。0、False或no的求值为Falsenot memory_available
第一个变量的值存在,作为第二个变量的列表中的值ansible_distribution in supported_distros

测试多个条件

一个when语句可用于评估多个条件。使用and和or关键字组合条件,并使用括号分组条件。

如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是红帽企业linux或Fedora,则下述条件得到满足:

when: ansible_distribution == “Redhat” or ansible_distribution == “Fedora”

使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是红帽企业Linux7.5主机,并且安装的内核是指定版本,则将满足以下条件:

when: ansible_distribution_version == “7.5” and ansible_kernel == “3.10.0-327.el7.x86_64”

组合循环和有条件任务

循环和条件可以组合使用

yum模块将安装mariadb-server软件包,只要/上挂载的文件系统具有超过300MB的可用空间。ansible_mounts事实是一组字典,各自代表一个已挂载文件系统的相关事实。循环迭代列表中每一字典,只有找到了代表两个条件都为真的已挂载文件系统的字典时,条件语句才得到满足。

- name: test
  yum:
    name: mariadb
    state: latest
  loop: "{{ ansible_mounts }}"
  when: item.mount == "/" and item.size_available > 300000000

对某个任务结合使用when和loop时,将对每个项检查when语句。

---
- name: test
  hosts: 192.168.8.130
  tasks:
    - name: one
      command: /usr/bin/systemctl is-active postfix     # Postfix是否在运行?
      ignore_errors: yes    # 如果它不在运行并且命令失败,则不停止处理。
      register: result      # 将模块的结果信息保存在名为result的变量中
      
    - name: Restart Apache HTTPD based on Postfix status
      service:
        name: httpd
        state: restarted
      when: result.rc == 0      # 评估Postfix任务的输出。如果systemctl命令的退出代码为0,\
                                # 则Postfix激活并且此任务重启httpd服务

实施处理程序

Ansible处理程序

Ansible模块设计为具有幂等性。这表示,在正确编写的playbook中,playbook及其任务可以运行多次而不会改变受管主机,除非需要进行更改使受管主机进入所需的状态。

但在时候,在任务确实更改系统时,可能需要运行进一步的任务。例如,更改服务配置文件时可能要求重新加载该服务以便使其更改的配置生效。

处理程序是响应由其他任务触发的通知的任务。仅当任务在受管主机上更改了某些内容时,任务才通知其处理程序。每个处理程序具有全局唯一的名称,在playbook中任务块的末尾触发。如果没有任务通过名称通知处理程序,处理程序就不会运行。如果一个或多个任务通知处理程序,处理程序就会在play中的所有其他任务完成后运行一次。因为处理程序就是任务,所以可以在处理程序中使用他们将用于任何其他任务的模块。通常而言,处理程序被用于重新引导主机和重启服务。

处理程序可视为非活动任务,只有在使用notify语句显式调用时才会被触发。在下列代码片段中,只有配置文件更新并且通知了该任务,restart apache处理程序才会重启Apache服务器:

tasks:
  - name: copy     # 通知处理程序的任务
    template:
      src: /var/lib/templates/demo.example.conf.template
      dest: /etc/httpd/conf.d/demo.example.conf
    notify:         # notify语句指出该任务需要触发一个处理程序
      - restart apache     # 要运行的处理程序的名称

handlers:       # handlers关键字表示处理程序任务列表的开头
  - name: restart apache   # 被任务调用的处理程序的名称
    service:    # 用于该处理程序的模块
      name: httpd
      state: restarted

处理任务失败

管理play中的任务错误

Ansible评估任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible将立即在该主机上中止play的其余部分并且跳过所有后续任务

但有些时候,可能希望即使在任务失败时也继续执行play。例如,或许预期待定任务有可能会失败,并且希望通过有条件地运行某项其他任务来修复。

忽略任务失败

默认情况下,任务失败时play会中止。不过,可以通过忽略失败的任务来覆盖此行为。可以在任务中使用ignore_errors关键字来实现此目的。

当任务失败时,将ignore_errors设为yes,则任务将继续执行

[root@client Fact]# cat facts.yml 
---
- name: test
  hosts: 192.168.8.130
  tasks:
    - name: one      
      dnf:
        name: httpd1
        state: latest
      ignore_errors: yes

[root@client Fact]# ansible-playbook facts.yml 

PLAY [test] **********************************************************************************

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

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

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

任务失败后强制执行处理程序

通常而言,如果任务失败并且play在该主机上中止,则收到play中早前任务通知的处理程序将不会运行。如果在play中设置force_handlers: yes关键字,则即使play因为后续任务失败而中止也会调用被通知的处理程序。

---
- hosts: 192.168.8.130
  force_handlers: yes
  tasks:
    - name: test1
      command: /bin/true
      notify: restart the database
      
    - name: test2
      yum:
        name: notapkg
        state: latest
        
  handlers:
    - name: restart the database
      service:
        name: mariadb
        state: restarted

指定任务失败条件

可以在任务中使用failed_when关键字来指定表示任务已失败的条件。这通常与命令模块搭配使用,这些模块可能成功执行了某一命令,但命令的输出可能指示了失败。

可以运行输出错误消息的脚本,并使用该消息定义任务的失败状态。下列代码片段演示了如何在任务中使用failed_when关键字:

[root@client Fact]# cat facts.yml 
---
- name: test
  hosts: 192.168.8.130
  gather_facts: no
  tasks:
    - name: one      
      command: /root/test.sh
      register: result
      failed_when: "'already' in result.stderr"

Playbook部署LAMP(循环)

部署LAMP

主机IP
client192.168.8.129
node1192.168.8.130
[root@client test2]# tree
.
├── 1
├── lamp.yml
└── var2
    └── vars2_file.yml

编写playbook

[root@client test2]# cat lamp.yml 
---
- name: lamp
  hosts: 192.168.8.130
  vars_files:
    - var2/vars2_file.yml
  tasks:
    - name: create users
      user:
        name: "{{ item }}"
        state: present
      loop: "{{ user }}"

    - name: install httpd
      dnf:
        name: "{{ item }}"
        state: latest
      loop: "{{ name }}"

    - name: index.php
      copy:
        src: /root/index.php
        dest: /var/www/html

    - name: reloaded server
      service: 
        name: "{{ item }}"
        state: reloaded
        enabled: true
      loop: "{{ server }}"


#编写循环任务
[root@client test2]# cat var2/vars2_file.yml 	
user:
  - apache
  - mysql
  - php

name:
  - httpd
  - mariadb*
  - php

server:
  - httpd
  - mariadb
  - php-fpm 

编写php访问页面

[root@client ~]# cat index.php 
<?php
   phpinfo();
?>

访问测试页面
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值