ansible-playbook的循环(Loops)
1.标准的Loops:也是最常用的一种循环
例:当需要安装10个软件包时,不用写10次任务,只需要写一次然后进行循环即可
#注:已经安装的软件系统即不在安装 [root@nfs-server playbook]# cat yum_list.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "需要安装的软件清单" yum: name={{ item }} state=present with_items: - lrzsz - vim - sysstat [root@nfs-server playbook]# ansible-playbook yum_list.yml PLAY [webservers] ************************************************************************************************************************************** TASK [需要安装的软件清单] *************************************************************************************************************************************** changed: [192.168.2.101] => (item=[u'lrzsz', u'vim', u'sysstat']) changed: [192.168.2.111] => (item=[u'lrzsz', u'vim', u'sysstat']) PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=1 unreachable=0 failed=0 192.168.2.111 : ok=1 changed=1 unreachable=0 failed=0
2.字典格式的循环:with_items
#写法一: [root@nfs-server playbook]# cat dict_list.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "字典格式的循环" debug: msg="name ---->{{ item.name }},age---->{{ item.age }}" with_items: - {name: "Liu Zhengwei",age: 28} - {name: "Jia Dongli",age: 25} #写法二: [root@nfs-server playbook]# cat dict_list.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "字典格式的循环" debug: msg="name ---->{{ item.name }},age---->{{ item.age }}" with_items: - name: "Liu Zhengwei" age: 28 - name: "Jia Dongli" age: 25 #注:以上两种写法效果是一样的 [root@nfs-server playbook]# ansible-playbook dict_list.yml PLAY [webservers] ************************************************************************************************************************************** TASK [字典格式的循环] ***************************************************************************************************************************************** ok: [192.168.2.101] => (item={u'age': 28, u'name': u'Liu Zhengwei'}) => { "item": { "age": 28, "name": "Liu Zhengwei" }, "msg": "name ---->Liu Zhengwei,age---->28" } ok: [192.168.2.101] => (item={u'age': 25, u'name': u'Jia Dongli'}) => { "item": { "age": 25, "name": "Jia Dongli" }, "msg": "name ---->Jia Dongli,age---->25" } ok: [192.168.2.111] => (item={u'age': 28, u'name': u'Liu Zhengwei'}) => { "item": { "age": 28, "name": "Liu Zhengwei" }, "msg": "name ---->Liu Zhengwei,age---->28" } ok: [192.168.2.111] => (item={u'age': 25, u'name': u'Jia Dongli'}) => { "item": { "age": 25, "name": "Jia Dongli" }, "msg": "name ---->Jia Dongli,age---->25" } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=0 unreachable=0 failed=0 192.168.2.111 : ok=1 changed=0 unreachable=0 failed=0
3.嵌套Loops(列表格式的循环,用于1对多或者多对多关系时)--> with_nested
[root@nfs-server playbook]# cat netsted_list.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "实现1对多关系的循环" debug: msg="name--->{{ item[0] }},value--->{{ item[1] }}" with_nested: - ['A'] - ['a','b','c' ] [root@nfs-server playbook]# ansible-playbook netsted_list.yml -l 192.168.2.101 PLAY [webservers] ************************************************************************************************************************************** TASK [实现1对多关系的循环] ************************************************************************************************************************************** ok: [192.168.2.101] => (item=[u'A', u'a']) => { "item": [ "A", "a" ], "msg": "name--->A,value--->a" } ok: [192.168.2.101] => (item=[u'A', u'b']) => { "item": [ "A", "b" ], "msg": "name--->A,value--->b" } ok: [192.168.2.101] => (item=[u'A', u'c']) => { "item": [ "A", "c" ], "msg": "name--->A,value--->c" } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=0 unreachable=0 failed=0
4.散列loops:with_dict(支持更丰富的数据结构)
注:with_dict的写法在新版本中进行了改变,必须要写成字典的形式,跟我下面写的格式一样
[root@nfs-server playbook]# cat with_dict.yml --- - hosts: webservers gather_facts: False remote_user: root vars: user: shencan: name: shencan shell: bash ruifengyun: name: ruifengyun shell: zsh tasks: - name: debug loops debug: "msg=name--->{{ item.key }} value--->{{ item.value.name }} shell--->{{ item.value.shell }}" with_dict: "{{ user }}" [root@nfs-server playbook]# ansible-playbook with_dict.yml -l 192.168.2.101 PLAY [webservers] ************************************************************************************************************************************** TASK [debug loops] ************************************************************************************************************************************* ok: [192.168.2.101] => (item={'key': u'ruifengyun', 'value': {u'shell': u'zsh', u'name': u'ruifengyun'}}) => { "item": { "key": "ruifengyun", "value": { "name": "ruifengyun", "shell": "zsh" } }, "msg": "name--->ruifengyun" } ok: [192.168.2.101] => (item={'key': u'shencan', 'value': {u'shell': u'bash', u'name': u'shencan'}}) => { "item": { "key": "shencan", "value": { "name": "shencan", "shell": "bash" } }, "msg": "name--->shencan" } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=0 unreachable=0 failed=0
5.文件匹配loops:with_fileglob
在工作中,我们经常遇到需要针对一个目录下指定格式的文件进行处理,这个时候直接引用with_fileglob循环去匹配我们需要处理的文件即可
[root@nfs-server playbook]# cat with_fileglob.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: debug loops debug: "msg=files-->{{ item }}" with_fileglob: - /var/log/nginx/*.gz [root@nfs-server playbook]# ansible-playbook with_fileglob.yml PLAY [webservers] ************************************************************************************************************************************** TASK [debug loops] ************************************************************************************************************************************* ok: [192.168.2.101] => (item=/var/log/nginx/host.access.log-20170816.gz) => { "item": "/var/log/nginx/host.access.log-20170816.gz", "msg": "files-->/var/log/nginx/host.access.log-20170816.gz" } ok: [192.168.2.101] => (item=/var/log/nginx/error.log-20170815.gz) => { "item": "/var/log/nginx/error.log-20170815.gz", "msg": "files-->/var/log/nginx/error.log-20170815.gz" } ok: [192.168.2.101] => (item=/var/log/nginx/error.log-20170823.gz) => { "item": "/var/log/nginx/error.log-20170823.gz", "msg": "files-->/var/log/nginx/error.log-20170823.gz" } ok: [192.168.2.111] => (item=/var/log/nginx/access.log-20170817.gz) => { "item": "/var/log/nginx/access.log-20170817.gz", "msg": "files-->/var/log/nginx/access.log-20170817.gz" } ok: [192.168.2.111] => (item=/var/log/nginx/error.log-20170825.gz) => { "item": "/var/log/nginx/error.log-20170825.gz", "msg": "files-->/var/log/nginx/error.log-20170825.gz" } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=0 unreachable=0 failed=0 192.168.2.111 : ok=1 changed=0 unreachable=0 failed=0
6.随机选择loops:with_random_choice(会从给定的值中随便选取一个显示)
[root@nfs-server playbook]# cat with_random_choice.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: debug loops debug: 'msg="name --> {{ item }}"' with_random_choice: - "Beijing" - "Shanghai" - "TianJin" [root@nfs-server playbook]# ansible-playbook with_random_choice.yml PLAY [webservers] ************************************************************************************************************************************** TASK [debug loops] ************************************************************************************************************************************* ok: [192.168.2.101] => (item=Beijing) => { "item": "Beijing", "msg": "name --> Beijing" } ok: [192.168.2.111] => (item=Shanghai) => { "item": "Shanghai", "msg": "name --> Shanghai" } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=1 changed=0 unreachable=0 failed=0 192.168.2.111 : ok=1 changed=0 unreachable=0 failed=0
7.条件判断loops
在某些情况下,我们需要检测某个task是否达到了预想的状态,如果没有达到,就需要退出整个剧本。
until:检测条件
retries:检测次数
delay:每次检测的间隔时长
[root@nfs-server playbook]# cat if_else.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "对task的执行结果进行判断" shell: cat /etc/fstab register: info until: info.stdout.startswith("sysfs") retries: 5 delay: 5 [root@nfs-server playbook]# ansible-playbook if_else.yml PLAY [webservers] ************************************************************************************************************************************** TASK [对task的执行结果进行判断] ********************************************************************************************************************************** FAILED - RETRYING: 对task的执行结果进行判断 (5 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (5 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (4 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (4 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (3 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (3 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (2 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (2 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (1 retries left). FAILED - RETRYING: 对task的执行结果进行判断 (1 retries left). fatal: [192.168.2.111]: FAILED! => {"attempts": 5, "changed": true, "cmd": "cat /etc/fstab", "delta": "0:00:00.003310", "end": "2017-09-04 01:09:18.651001", "failed": true, "rc": 0, "start": "2017-09-04 01:09:18.647691", "stderr": "", "stderr_lines": [], "stdout": "\n#\n# /etc/fstab\n# Created by anaconda on Sun Jun 26 03:08:48 2016\n#\n# Accessible filesystems, by reference, are maintained under '/dev/disk'\n# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info\n#\n/dev/mapper/vg_test2-lv_root / ext4 defaults 1 1\nUUID=8699d6c2-883b-41a0-8282-5be27641ee02 /boot ext4 defaults 1 2\n/dev/mapper/vg_test2-lv_swap swap swap defaults 0 0\ntmpfs /dev/shm tmpfs defaults 0 0\ndevpts /dev/pts devpts gid=5,mode=620 0 0\nsysfs /sys sysfs defaults 0 0\nproc /proc proc defaults 0 0\n/dev/cdrom /media/cdrom iso9660 defaults 0 0", "stdout_lines": ["", "#", "# /etc/fstab", "# Created by anaconda on Sun Jun 26 03:08:48 2016", "#", "# Accessible filesystems, by reference, are maintained under '/dev/disk'", "# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info", "#", "/dev/mapper/vg_test2-lv_root / ext4 defaults 1 1", "UUID=8699d6c2-883b-41a0-8282-5be27641ee02 /boot ext4 defaults 1 2", "/dev/mapper/vg_test2-lv_swap swap swap defaults 0 0", "tmpfs /dev/shm tmpfs defaults 0 0", "devpts /dev/pts devpts gid=5,mode=620 0 0", "sysfs /sys sysfs defaults 0 0", "proc /proc proc defaults 0 0", "/dev/cdrom /media/cdrom iso9660 defaults 0 0"]} fatal: [192.168.2.101]: FAILED! => {"attempts": 5, "changed": true, "cmd": "cat /etc/fstab", "delta": "0:00:00.002489", "end": "2017-09-04 01:11:02.560507", "failed": true, "rc": 0, "start": "2017-09-04 01:11:02.558018", "stderr": "", "stderr_lines": [], "stdout": "\n#\n# /etc/fstab\n# Created by anaconda on Sun Jun 26 03:11:47 2016\n#\n# Accessible filesystems, by reference, are maintained under '/dev/disk'\n# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info\n#\n/dev/mapper/vg_test3-lv_root / ext4 defaults 1 1\nUUID=e48217af-0ad9-45be-aa68-b0b1bbc88c97 /boot ext4 defaults 1 2\n/dev/mapper/vg_test3-lv_swap swap swap defaults 0 0\ntmpfs /dev/shm tmpfs defaults 0 0\ndevpts /dev/pts devpts gid=5,mode=620 0 0\nsysfs /sys sysfs defaults 0 0\nproc /proc proc defaults 0 0\n/dev/cdrom /media/cdrom iso9660 defaults 0 0", "stdout_lines": ["", "#", "# /etc/fstab", "# Created by anaconda on Sun Jun 26 03:11:47 2016", "#", "# Accessible filesystems, by reference, are maintained under '/dev/disk'", "# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info", "#", "/dev/mapper/vg_test3-lv_root / ext4 defaults 1 1", "UUID=e48217af-0ad9-45be-aa68-b0b1bbc88c97 /boot ext4 defaults 1 2", "/dev/mapper/vg_test3-lv_swap swap swap defaults 0 0", "tmpfs /dev/shm tmpfs defaults 0 0", "devpts /dev/pts devpts gid=5,mode=620 0 0", "sysfs /sys sysfs defaults 0 0", "proc /proc proc defaults 0 0", "/dev/cdrom /media/cdrom iso9660 defaults 0 0"]} to retry, use: --limit @/ansible/playbook/if_else.retry PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=0 changed=0 unreachable=0 failed=1 192.168.2.111 : ok=0 changed=0 unreachable=0 failed=1
8.register同时接收多个变量进行传递
#注:接收到的多个值可以用jinja的for循环方式显示每个值 [root@nfs-server playbook]# cat register_vars.yml --- - hosts: webservers remote_user: root gather_facts: False tasks: - name: "register接受多个值测试" shell: "{{ item }}" with_items: - hostname - uname register: ret - name: "显示接收到的值" debug: 'msg="{% for i in ret.results %} {{ i.stdout }} {% endfor%}"' [root@nfs-server playbook]# ansible-playbook register_vars.yml PLAY [webservers] ************************************************************************************************************************************** TASK [register接受多个值测试] ********************************************************************************************************************************* changed: [192.168.2.101] => (item=hostname) changed: [192.168.2.111] => (item=hostname) changed: [192.168.2.101] => (item=uname) changed: [192.168.2.111] => (item=uname) TASK [显示接收到的值] ***************************************************************************************************************************************** ok: [192.168.2.101] => { "msg": " lamp1 Linux " } ok: [192.168.2.111] => { "msg": " lamp2 Linux " } PLAY RECAP ********************************************************************************************************************************************* 192.168.2.101 : ok=2 changed=1 unreachable=0 failed=0 192.168.2.111 : ok=2 changed=1 unreachable=0 failed=0