Loading

Ansible系列基础篇 1.7.2、PlayBook之循环

一、循环定义

 循环可迭代对象,重复处理每条信息。

 基础示例:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_items:
    - 1
    - 2
    - 3
    # 也可以 with_items: [1,2,3]

  

使用内置变量循环,示例如下:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_items: "{{groups.ungrouped}}"

  

复杂字段的循环,示例如下:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item.test1}}"
    with_items:
    - { test1: a, test2: b }
    - { test1: c, test2: d }

  

循环结果的存储与读取,通过register,把模块执行的结果存储到变量中,命令的结果,以列表形式存在returnvalue.results,示例如下:

---
- hosts: test70
  gather_facts: no
  tasks:
  - shell: "{{item}}"
    with_items:
    - "ls /opt"
    - "ls /home"
    register: returnvalue
  - debug:
      msg: "{{item.stdout}}"
    with_items: "{{returnvalue.results}}"

  

 

二、循环特殊关键字

2.1、with_list

当处理单层的简单列表时,with_list与with_items没有任何区别,只有在处理上例中的"嵌套列表"时,才会体现出区别,区别就是,with_items会将嵌套在内的小列表"拉平",拉平后循环处理所有元素,而with_list则不会"拉平"嵌套的列表,with_list只会循环的处理列表(最外层列表)中的每一项。

with_items的嵌套的列表(序列中的序列),示例如下:

# 结果为 1, 2, 3, a, b
# 每个循环的列表项,也展开
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_items:
    - [ 1, 2, 3 ]
    - [ a, b ]

  

使用with_list:

# 结果为 [1, 2, 3], [a, b]
# 外层列表循环,每个项的列表内容不循环
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_list:
    - [ 1, 2, 3 ]
    - [ a, b ]

  

2.2、with_flattened

该关键字与with_items效果完全相同

 

2.3、with_together

两列表一一对应聚合,示例如下:

# 结果为: [1, a], [2, b], [3, c]
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_together:
    - [ 1, 2, 3 ]
    - [ a, b, c ]

如果两列表长度不一致,一一对应时,无数据的,用null补齐。 

 

2.4、with_cartesian

 示例需求:需要在目标主机的测试目录中创建a、b、c三个目录,这三个目录都有相同的子目录,它们都有test1和test2两个子目录。

linux命令实现:mkdir -p {a,b,c}/{test1,test2}

ansible实现,用到关键字 with_cartesian ,实现交叉循环,和笛卡尔乘积一样,示例如下:

代码结果:[a, test1], [a, test2], [b, test1], [b, test2], [c, test1], [c, test2]

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "/testdir/testdir/{{ item.0 }}/{{ item.1 }}"
    with_cartesian:
    - [ a, b, c ]
    - [ test1, test2 ]

  

2.5、with_indexed_items

功能“:在循环处理列表时为列表中的每一项添加"数字索引","索引"从0开始。

代码结果: [0, test1], [1, test2], [2, test3]

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "index is : {{ item.0 }} , value is {{ item.1 }}"
    with_indexed_items:
    - test1
    - test2
    - test3

  

 多嵌套时,展开情况:

 实例一,结果:[0, test1], [1, test2], [2, test3], [3, test4], [4, test5]

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "index is : {{ item.0 }} , value is {{ item.1 }}"
    with_indexed_items:
    - [ test1, test2 ]
    - [ test3, test4, test5 ]

实例二,结果:[0, test1], [1, test2], [2, test3], [3, [test4, test5]]

当多加了一层嵌套以后,"with_indexed_items"并不能像"with_flattened"一样将嵌套的列表"完全拉平",第二层列表中的项如果仍然是一个列表,"with_indexed_items"则不会拉平这个列表,而是将其当做一个整体进行编号。

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_indexed_items:
    - [ test1, test2 ]
    - [ test3, [ test4, test5 ] ]

  

2.6、with_sequence

功能:按照数字递增\递减方式,进行循环。

实例结果:1, 2, 3, 4, 5

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_sequence: start=1 end=5 stride=1

  

下例中count=5表示数字序列默认从1开始,到5结束,默认步长为1,效果与上例相同。

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_sequence: count=5

  

下例执行结果:6, 4 ,2

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_sequence: start=6 end=2 stride=-2

  

格式化数据:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_sequence: start=2 end=6 stride=2 format="number is %0.2f"

  

2.7、with_random_choice

 功能:从列表的多个值中随机返回一个值。

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{item}}"
    with_random_choice:
    - 1
    - 2
    - 3
    - 4
    - 5

  

2.8、with_dict

---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars:
    users:
      alice: female
      bob: male
  tasks:
  - debug:
      msg: "{{item}}"
    with_dict: "{{users}}"

示例执行结果:

TASK [debug] *************************************
ok: [test70] => (item={'value': u'male', 'key': u'bob'}) => {
    "changed": false,
    "item": {
        "key": "bob",
        "value": "male"
    },
    "msg": {
        "key": "bob",
        "value": "male"
    }
}
ok: [test70] => (item={'value': u'female', 'key': u'alice'}) => {
    "changed": false,
    "item": {
        "key": "alice",
        "value": "female"
    },
    "msg": {
        "key": "alice",
        "value": "female"
    }
}

 

with_dict具体使用方式如下:

---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars:
    users:
      alice: female
      bob: male
  tasks:
  - debug:
      msg: "User name: {{item.key}} , User's gender: {{item.value}} "
    with_dict: "{{users}}"

  

2.9、with_subelements

 处理一个像上例中一样的复合结构的字典数据,在处理这个字典的同时,需要指定一个子元素,这个子元素的值必须是一个列表,之后,"with_subelements"会将子元素的列表中的每一项作为一个整体,将其他子元素作为一个整体,然后将两个整体组合成item。

---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars:
    users:
    - name: bob
      gender: male
      hobby:
        - Skateboard
        - VideoGame
    - name: alice
      gender: female
      hobby:
        - Music
  tasks:
  - debug:
      msg: "{{ item }}"
    with_subelements:
    - "{{users}}"
    - hobby

执行结果:

TASK [debug] ***********************************************************
ok: [test70] => (item=({u'gender': u'male', u'name': u'bob'}, u'Skateboard')) => {
    "changed": false,
    "item": [
        {
            "gender": "male",
            "name": "bob"
        },
        "Skateboard"
    ],
    "msg": [
        {
            "gender": "male",
            "name": "bob"
        },
        "Skateboard"
    ]
}
ok: [test70] => (item=({u'gender': u'male', u'name': u'bob'}, u'VideoGame')) => {
    "changed": false,
    "item": [
        {
            "gender": "male",
            "name": "bob"
        },
        "VideoGame"
    ],
    "msg": [
        {
            "gender": "male",
            "name": "bob"
        },
        "VideoGame"
    ]
}
ok: [test70] => (item=({u'gender': u'female', u'name': u'alice'}, u'Music')) => {
    "changed": false,
    "item": [
        {
            "gender": "female",
            "name": "alice"
        },
        "Music"
    ],
    "msg": [
        {
            "gender": "female",
            "name": "alice"
        },
        "Music"
    ]
}

 

---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars:
    users:
    - name: bob
      gender: male
      hobby:
        - Skateboard
        - VideoGame
    - name: alice
      gender: female
      hobby:
        - Music
  tasks:
  - debug:
      msg: "{{ item.0.name }} 's hobby is {{ item.1 }}"
    with_subelements:
    - "{{users}}"
    - hobby

执行结果:  

"msg": "bob 's hobby is Skateboard"
"msg": "bob 's hobby is VideoGame"
"msg": "alice 's hobby is Music"

 

2.10、with_file

功能:获取到这些文件的内容。

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_file:
    - /testdir/testdir/a.log
    - /opt/testfile

  

2.11、with_fileglob

功能:匹配文件名称。

  • 只会匹配指定目录中的文件,而不会匹配指定目录中的目录。
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_fileglob:
    - /testdir/*

  

# 这个列表中有两项,第一项表示匹配"/testdir"目录下的文件,第二项表示匹配"/opt"目录下,以"test"开头,以". 任意3个字符"结尾的文件,比如"testa.123"或者"testfile.yml"
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - debug:
      msg: "{{ item }}"
    with_fileglob:
    - /testdir/*
    - /opt/test*.???

  

 

posted @ 2020-12-26 19:16  wsongl  阅读(276)  评论(0编辑  收藏  举报