在写 playbook 的时候发现了很多 task 都要重复引用某个相同的模块,如果按照传统的写法最少要写10次,这样会使得 playbook很臃肿。
Ansible提供了两个用于创建循环的关键字:loop和with_*,目前我们习惯于用loop替代with_*

1、---对迭代项的引用,固定变量名为"item";
2、---要在task中使用with_items或loop关键字给定要迭代的元素列表;

一、使用循环批量安装软件

方法一:这里把loop换成with_items效果一样

# vim /tmp/item.yaml
---
 - hosts: web1
   tasks:
   - name: install some package
     yum: 
       name: "{{ item }}" 
       state=present
     loop:
     - nginx
     - htop
     - keepalived

# ansible-playbook /tmp/item.yaml

方法二:采用变量的方式安装

# vim /tmp/item.yaml
---
 - hosts: web1
   tasks:
   - name: install some package
     yum: 
       name: "{{ item }}" 
       state: present
     loop: "{{ package }}"
     vars:
     - package:
        - nginx
        - htop
        - keepalived

# ansible-playbook /tmp/item.yaml

二、使用循环批量创建用户

方法一:使用loop循环

# vim /tmp/item.yaml
# vim /tmp/item.yaml
---
 - hosts: web1
   tasks:
   - name: add some groups
     group:
       name: "{{ item }}"
       state: present
     loop: [ g1 , g2 , g3 ]
   - name: add some users
     user:
       name: "{{ item.name }}"
       groups: "{{ item.group }}"
       uid: "{{ item.uid }}"
       state: present
     loop: 
       - { name: "user1" , groups: "g1" , uid: "2000" }
       - { name: "user2" , groups: "g2" , uid: "2001" }
       - { name: "user3" , groups: "g3" , uid: "2002" }

# ansible-playbook /tmp/item.yaml

方法二:引入外部yaml文件

# vim /tmp/item_var.yaml
---
   - users:
     - name: "user1"
       group: "g1"
     - name: "user2"
       group: "g2"
     - name: "user3"
       group: "g3"
   - group: [ g1 , g2 , g3 ]

# vim /tmp/item.yaml
---
 - hosts: web1
   vars_files:
   - /root/users.yaml
   tasks:
   - name: add some groups
     group:
       name: "{{ item }}"
       state: present
     loop: "{{ groups }}"
   
   - name: add some users
     user:
       name: "{{ item.name }}"
       groups: "{{ item.group }}"
       uid: "{{ item.uid }}"
       state: present
     loop: "{{ users }}"

# ansible-playbook /tmp/item.yaml

三、使用循环批量拷贝文件

# vim file_test.yaml
---
 - file_test:
     - src: /root/a.txt
       dest: /tmp/
       owner: root
       group: root
       mode: 0644
     - src: /root/b.txt
       dest: /tmp/
       owner: root
       group: root
       mode: 0644
     - src: /root/c.txt
       dest: /tmp/
       owner: root
       group: root
       mode: 0644

# vim /tmp/loopfile.yaml
---
 - hosts: web1
   vars_files:
   - /root/file_test.yaml
   tasks:
   - name: copy file
     template:
       src: "{{ item.src }}"
       dest: "{{ item.dest }}"
       owner: "{{ item.owner }}"
       group: "{{ item.group }}"
       mode: "{{ item.mode }}"
     loop: "{{ file_test }}"

#       - { src: "/root/a.txt" , dest: "/tmp/", owner: "root", group: "root", mode: "0644" }
#       - { src: "/root/b.txt" , dest: "/tmp/", owner: "root", group: "root", mode: "0644" }
#       - { src: "/root/c.txt" , dest: "/tmp/", owner: "root", group: "root", mode: "0644" }

# ansible-playbook /tmp/loopfile.yaml

四、嵌套循环with_nested

# vim /tmp/with_nested.yaml
---
- hosts: web1
  tasks:
  - name: mkdir 
    file:  
      path: "/testdir/{{item.0}}/{{item.1}}/{{item.2}}" 
      state: directory
    with_nested:
      - [ a, b, c ]
      - [ test1, test2 ]
      - [ a1, a2 ]

# ansible-playbook /tmp/with_nested.yaml

执行后的结果
# tree /testdir/
/testdir/
├── a
│   ├── test1
│   │   ├── a1
│   │   └── a2
│   └── test2
│       ├── a1
│       └── a2
├── b
│   ├── test1
│   │   ├── a1
│   │   └── a2
│   └── test2
│       ├── a1
│       └── a2
└── c
    ├── test1
    │   ├── a1
    │   └── a2
    └── test2
        ├── a1
        └── a2

五、对哈希表循环(key:value)

# vim /tmp/key_value.yaml
---
- hosts: web1
  vars:
  - users:
    - user1:
        name: tom
        age: 20
        telephone: 123-456-7890
    - user2:
        name: jerry
        age: 22
        telephone: 987-654-3210
  tasks:
    - name: print phone
      debug:
        msg: "User {{ item.key }} is {{ item.value.name }}  年龄: {{ item.value.age }}  联系方式: {{ item.value.telephone }}"
      with_dict: "{{ users }}"

# ansible-playbook /tmp/key_value.yaml

输出结果:
ok: [192.168.58.101] => (item={'key': 'user1', 'value': {'name': 'tom', 'telephone': '123-456-7890'}}) => {
    "msg": "User user1 is tom 123-456-7890"
}
ok: [192.168.58.101] => (item={'key': 'user2', 'value': {'name': 'jerry', 'telephone': '987-654-3210'}}) => {
    "msg": "User user2 is jerry 987-654-3210"

六、文件列表使用循环with_fileglob

# vim /tmp/with_fileglob.yaml

---
- hosts: web1
  tasks:
  - name: copy file *
    copy:
      src: "{{ item }}"
      dest: /tmp
      owner: root
      mode: 0600
    with_fileglob:
    - /tmp/copy/*
    - /root/index.html
#   - /tmp/copy/a.txt
#   - /tmp/copy/b.txt 

相当于批量化拷贝文件到被控端,使用loop也可以循环,但是不能指定/tmp/copy/*,只能一个个列出需要循环拷贝的文件

# ansible-playbook /tmp/with_fileglob.yaml