Ansible循环与判断

发布于:2025-09-06 ⋅ 阅读:(21) ⋅ 点赞:(0)

Ansible循环与判断

一、Ansible循环

1.with_items迭代列表

当Linux中依次需要安装多个软件包时,可以使用with_items迭代功能进行实现。

 # 安装 httpd smaba smaba-client
 ---
 - name: install
   hosts: all
   tasks: 
     - name: install httpd smaba smaba-client
       yum: 
         name: "{{ item }}"
         state: present
       with_items: 
         - httpd
         - smaba
         - smaba-client
 # with_items可以使用loop代替

2.with_dict迭代字典

item.key对应是字典的键,item.value对应是字典的值

 ---
 - name: test
   hosts: all
   tasks: 
     - name: debug
       debug: 
         msg: "{{ item.key }} & {{ item.value }}"
       with_dict: 
         address: 1
         netmask: 2
         gateway: 3
 # 结果为
 address & 1
 netmask & 2
 gateway & 3

3.with_fileglob迭代文件

当拷贝多个文件到受控主机上时,可以使用。

 # 拷贝本机/tmp/中所有.sh结尾和.py结尾的文件到node1的/tmp/中
 ---
 - name: test
   hosts: node1
   tasks: 
     - name: cp file
       copy: 
         src: "{{ item }}"
         dest: /tmp/
       with_fileglob: 
         - /tmp/*.sh
         - /tmp/*.py

4.with_lines迭代行

with_lines可以将命令行的输出结果按行迭代。

 # 查找本机/home/student/ansible/中所有的/.yml结尾的文件,并将这些文件拷贝到主机node1的/tmp/中
 ---
 - name: test
   hosts: node1
   tasks: 
     - name: cp file
       copy: 
         src: "{{ item }}"
         dest: /tmp/
       with_lines: 
         - find /home/student/ansible/ -name "*.yml"

5.with_nested嵌套迭代

例如:a、b、c与1、2、3连接组合

 ---
 - name: test
   hosts: node1
   tasks: 
     - name: debug
       debug: 
         msg: "{{ item[0] }} & {{ item[1] }}"
       with_nested: 
         - [a,b,c]
         - [1,2,3]

6.with_sequence排序列

start:是从什么开始

stride:每隔多少

end:结束

 # 在主机node1中显示1、3、5、7、9
 ---
 - name: test
   hosts: node1
   tasks: 
     - name: debug
       debug: 
         var: item
       with_sequence: 
         start=1
         end=10
         stride=2

7.with_random_choice随机获得列表中的一个值

 ---
 - name: test
   hosts: node1
   tasks:
     - name: debug
       debug:
         msg: "{{item}}"
       with_random_choice:
         - 1
         - 2
         - a
         - b
         - c

8.过滤器

 # 字符相关过滤器
 upper # 将字符串转换成纯大写
 lower # 将字符串转换成纯小写
 trim # 将字符串的首尾空格去掉,可以去掉多个空格
 length # 求字符串的长度,与count等效
 capitalize # 将字符串首字母大写,之后的所有字母纯小写
 first # 返回字符串的第一个字符
 last # 返回字符串的最后一个字符 
 center(width=30) # 将字符串居中,并设置长度为30,长度不足,字符串两边用空格补全
 list # 将字符串转换成列表,每个字符作为一个元素
 shuffle # 洗牌,即将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
 ​
 # 数字操作有关的过滤器
 int # 将对应的值转换成int类型,如果无法转换,默认返回0
 float # 将对应的值转换成浮点型,如果无法转换,默认返回'0.0'
 abs # 获取对应数值的绝对值 
 round # 四舍五入
 round(5) # 取小数点后5位
 random # 随机返回一个随机数,random(start=5)从5开始
 random(step=3) # 返回一个随机数,这个随机数是3的倍数
 random(start=5,step=3) # 返回一个随机数,从5开始,步长为3,例如{{ 15 | random(start=5,step=3) }},返回的随机数只可能是5、8、11、14
 ​
 # 文件或目录类过滤器
 hash('sha1') # 使用sha1算法对字符串进行哈希
 hash('md5') # 使用md5算法对字符串进行哈希
 checksum # 获取到字符串的校验和,与md5哈希值一致
 password_hash('sha256') # 使用sha256算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
 password_hash('sha256','mysalt')  # 使用sha256算法对字符串进行哈希,并使用指定的字符串作为"盐"
 password_hash('sha512') # 使用sha512算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
 password_hash('sha512','ebzL.U5cjaHe55KK') # 使用sha512算法对字符串进行哈希,并使用指定的字符串作为"盐"
---
- name: test
  hosts: node1
  vars:
    testvar: "abc123ABC  666"
    testvar1: "     abc     "
  tasks:
    - name: debug1
      debug:
        msg: "{{ testvar | upper }}"

    - name: debug2
      debug:
        msg: "{{ testvar | lower }}"

    - name: debug3
      debug:
        msg: "{{ testvar1 | trim }}"

    - name: debug4
      debug: 
        msg: "{{ testvar1 | length }}"
    - name: debug5
      debug:
        msg: "{{ testvar | capitalize }}"

    - name: debug6
      debug:
        msg: "{{ testvar | first }}"

    - name: debug7
      debug:
        msg: "{{ testvar | last }}"

    - name: debug7
      debug:
        msg: "{{ testvar | shuffle }}"

    - name: debug8
      debug:
        msg: "{{ testvar | list }}"

二、Ansible判断

when关键字

判断运算符

== # 等于
!= # 不等
>
<
>=
<=
and
or
not
is
in

每次执行完一个任务,不管成功与失败,都会将执行的结果进行注册,可以使用这个注册的变量来when

判断变量

Defined # 判断变量是否已经定义,已定义则返回真
Undefined # 判断变量是否已经定义,未定义则返回真
None # 判断变量值是否为空,如果变量已经定义,但是变量值为空,则返回真

判断执行结果

Success/successed # 通过任务的返回信息判断执行状态,任务执行成功返回真
Failure/failed # 通过执行任务的返回信息判断执行状态,任务执行失败返回真
Change/changed # 通过任务的返回信息判断执行状态,任务返回状态为changed返回真
Skip/skipped # 通过任务的返回信息判断执行状态,当任务没有满足条件,而被跳过执行,则返回真

判断路径

# 判断均对ansible主机中的路径,与目标主机无关
file # 判断路径是否是一个文件
directory # 判断路径是否是一个目录
link # 判断路径是否是一个软连接
mount # 判断路径是否是一个挂载点
exists # 判断路径是否存在

判断字符串

# 该判断字符串中的字母大小写,字符串中的数字与其他字符不影响判断
upper # 判断包含字母的字符串中的字母是否为纯大写
lower # 判断包含字母的字符串中的字母是否为纯小写

其他判断

string # 判断对象是否是一个字符串
number # 判断对象是否是一个数字

block/rescue/always

如果block执行失败,则执行rescue,无论是block还是rescue执行失败还是成功,在最后都执行always

判断与错误处理

fail模块可用于中断剧本,但我们一般是不会无故中断,除非在满足条件的情况下可以中断,经常和when一起用

---
- name: test
  hosts: node1
  tasks: 
    - name: shell
      shell: 
        cmd: echo 'this is a string for testing--error'
      register: return_value
      
    - name: fail
      fail: 
        msg: Conditions established,Interrupt running playbook
      when: "'error' in return_value.stdout"
      
    - name: debug
      debug: 
        msg: I never execute,because the playbook has stopped

三、练习

练习1

创建一个名为/etc/ansible/lv.yml 的playbook,它将在所有受管节点上运行以执行下列任务:

创建符合以下要求的逻辑卷:

  • 逻辑卷创建在research卷组中

  • 逻辑卷名称为data

  • 逻辑卷大小为1500MiB

  • 使用ext4文件系统格式化逻辑卷

  • 如果无法创建请求的逻辑卷大小,应显示错误消息Could not create logical volume of that size,并且应改为使用大小 800MiB。

  • 如果卷组research 不存在 ,应显示错误消息Volume group does not exist。

  • 不要以任何方式挂载逻辑卷

前提:在node1、node2上添加一块硬盘,然后新建卷组

Node1的卷组大小为2G 卷组名为research

Node2的卷组大小为1G 卷组名为research

---
- name: test
  hosts: all
  tasks:
    - name: create lv
      block:
        - name: create lv 1500M
          lvol:
            vg: research
            lv: data
            size: 1500

      rescue:
        - name: output
          debug: 
            msg: Could not create logical volume of that size

        - name: create lv 800M
          lvol:
            vg: research
            lv: data
            size: 800
            
      always:
        - name: filesystem
          filesystem:
            dev: /dev/research/data
            fstype: ext4

      when: "'research' in ansible_lvm.vgs"

    - name: research not exists
      debug:
        msg: Volume group does not exist

      when: "'research' not in ansible_lvm.vgs"

练习2

http://ansible.example.com/materials/newhosts.j2 下载模板文件 完成该模板文件,用来生成新主机清单(主机的显示顺序没有要求),结构如下:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.122.10 node1.example.com node1
192.168.122.20 node2.example.com node2
192.168.122.30 node3.example.com node3
192.168.122.40 node4.example.com node4
192.168.122.50 node5.example.com node5

创建剧本/home/student/ansible/newhosts.yml,它将使用上述模板在 test01 主机组的主机上 生成文件/etc/newhosts。

1.ansible主机下载模板文件

# ansible主机下载模板文件
[student@master ansible]$ curl -O http://ansible.example.com/materials/newhosts.j2

2.修改newhosts.j2文件

vim newhosts.j2
# 在后面写
{% for i in groups.all %}
{{ hostvars[i].ansible_default_ipv4.address }} {{ hostvars[i].ansible_fqdn }} {{ hostvars[i].ansible_hostname }}
{% endfor %}

# groups.all为所有受控主机
# hostvars为主机变量

3.编写剧本/home/student/ansible/newhosts.yml

---
# 先获取所有主机的事实变量
- name: test
  hosts: all

- name: test1
  hosts: test01
  tasks:
    - name: aa
      template:
        src: /home/student/ansible/newhosts.j2
        dest: /etc/newhosts

4.验证

[student@master ansible]$ ansible test01 -m shell -a 'cat /etc/newhosts'

练习3

编写剧本修改远程文件内容 创建剧本 /home/student/ansible/newissue.yml,满足下列要求: 1)在所有清单主机上运行,替换/etc/issue 的内容 2)对于 test01 主机组中的主机,/etc/issue 文件内容为 test01 3)对于 test02 主机组中的主机,/etc/issue 文件内容为 test02 4)对于 web 主机组中的主机,/etc/issue 文件内容为 Webserver

---
- name: test
  hosts: all
  tasks:
    - name: copy
      copy:
        content: |
          {% if 'test01' in group_names %}
          test01
          {% elif 'test02' in group_names %}
          test02
          {% elif 'web' in group_names %}
          Webserver
          {% endif %}
        dest: /etc/issue

验证

[student@master ansible]$ ansible all -m shell -a 'cat /etc/issue'


网站公告

今日签到

点亮在社区的每一天
去签到