Ansible自动化运维之Playbook循环迭代

在ansible中,可以通过迭代机制完成重复性操作,将需要迭代的内容定义为item变量,并通过with_items语句指明迭代的元素列表即可。

0x01 with_items

with_items是playbooks中最基本也是最常用的循环语句,使用with_items迭代循环的变量可以是个单纯的列表,也可以是一个较为复杂的数据结果,如字典类型。

# 普通列表
- hosts: webservice
  remote_user: root
  tasks:
    - name: "Install_Packages"
      yum: name={{ item }} state=latest
      with_items:
        - nginx
        - php

# 数据字典
- hosts: webservice
  remote_user: root
  tasks:
    - name: create_users
      user: name={{ item.name }} groups={{ item.groups }} state=present
      with_items:
        - { name: 'demouser1' , groups : 'demogroup1' }
        - { name: 'demouser2' , groups : 'demogroup2' } 

0x02 with_nested

with_nested支持多组列表循环。

- hosts: webservice
  remote_user: root
  tasks:
    - name: mysql_privilegs
      mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=Password123
      with_nested:
        - [ 'lzl', 'lrx' ]
        - [ 'nextcloud', 'wordpress', 'dedecms' ]

0x03 with_dict

with_dict可以遍历更复杂的数据结构。

# 变量内容
users:
  lzl:
    name: Liu Zhilin
    gender: Male
    age: 40
  lly:
    name: Liu Liya
    gender: Famale
    age: 18

# playbook.yml
- hosts: webservice
  remote_user: root
  tasks:
  - name: echo_user_info
    debug:
      msg="用户 {{ item.key }} 的信息:\n {{ item.value.name }} ({{ item.value.gender}} {{item.value.age}})"
    with_dict: "{{ users }}"

0x04 with_fileglob

with_fileglob遍历目录或文件。

- hosts: webservice
  tasks:
    # 核验目标主机上的目录
    - file: dest=/demodir state=directory

    # 遍历目录并将文件复制到目标主机
    - copy: src={{ item }} dest=/demodir/ owner=root mode=755
      with_fileglob:
        - /data/scripts/*

0x05 with_together

with_together遍历数据并进行集合。

- hosts: webservers
  remote_user: root
  vars:
    strings: [ 'a','b','c']
    numbers: [ 1,2,3 ]
  tasks:
    - debug: msg="{{ item.0 }} and {{ item.1 }}"
      with_together:
         - "{{ strings }}"
         - "{{ numbers }}"

0x06 with_subelements

with_subelements遍历子元素。

# 变量内容
users:
  - name: liuzl
    authorized:
      - /home/liuzl/id_rsa_1.pub
      - /home/liuzl/id_rsa_2.pub
    mysql:
        password: mysql-password
        hosts:
          - "%"
          - "127.0.0.1"
          - "::1"
          - "localhost"
        privs:
          - "*.*:SELECT"
          - "demo_db_1.*:ALL"
  - name: liurx
    authorized:
      - /home/liurx/id_rsa.pub
    mysql:
        password: other-mysql-password
        hosts:
          - "demo_db_1"
        privs:
          - "*.*:SELECT"
          - "demo_db_2.*:ALL"

# playbook.yml
- hosts: webservice
  remote_user: root
  tasks:
    - user: name={{ item.name }} state=present generate_ssh_key=yes
      with_items: "`users`"
    - authorized_key: "user={{ item.0.name }} key='{{ lookup('file', item.1) }}'"
      with_subelements:
        - users
        - authorized

# 遍历嵌套的子列表
- hosts: webservice
  remote_user: root
  tasks:
    - name: mysql_config_privilegs
      mysql_user: name={{ item.0.user }} password={{ item.0.mysql.password }} host={{ item.1 }} priv={{ item.0.mysql.privs | join('/') }}
      with_subelements:
        - users
        - mysql.hosts

0x07 with_sequence

with_sequence用于生成一个自增的整数序列,可以指定起始值和结束值,或者指定增长步长,参数形式key=value,format指定输出格式,数字可以是十进制、八进制,十六进制。

- hosts: webservice
  remote_user: root
  tasks:
    # 准备用户组
    - group: name=group1 state=present

    # 创建用户
    - user: name={{ item }} state=present groups=group1
      with_sequence: start=0 end=32 format=demouser%02x

    # 创建目录
    - file: dest=/data/{{ item }} state=directory
      with_sequence: start=4 end=16 stride=2

    # 创建用户组
    - group: name=group{{ item }} state=present
      with_sequence: count=4

0x08 with_random_choice

with_random_choice从列表中随机取一个值。

- hosts: webservice
  remote_user: root
  tasks:
    - debug: msg={{ item }}
      with_random_choice:
        - "我的选择是1"
        - "我的选择是2"
        - "我的选择是3"
        - "我的选择是4"

0x09 util循环

重复执行指定动作,当输出内容中包含指定信息的时候停止执行,retries为重试次数,默认值为3次,delay为延时,默认值为5秒。

- hosts: webservice
  remote_user: root
  tasks:
    - action: shell /usr/bin/netstat -tlnp
      register: result
      until: result.stdout.find("443") != -1
      retries: 3
      delay: 30

0x10 循环注册变量

# 变量内容
{
    "changed": true,
    "msg": "完成任务",
    "results": [
        {
            "changed": true,
            "cmd": "echo \"demo1\" ",
            "delta": "0:00:00.003110",
            "end": "2021-08-04 10:00:05.187153",
            "invocation": {
                "module_args": "echo \"demo1\"",
                "module_name": "shell"
            },
            "item": "demo1",
            "rc": 0,
            "start": "2021-08-04 10:00:05.184043",
            "stderr": "",
            "stdout": "demo1"
        },
        {
            "changed": true,
            "cmd": "echo \"demo2\" ",
            "delta": "0:00:00.002920",
            "end": "2021-08-04 10:00:05.245502",
            "invocation": {
                "module_args": "echo \"demo2\"",
                "module_name": "shell"
            },
            "item": "demo2",
            "rc": 0,
            "start": "2021-08-04 10:00:05.242582",
            "stderr": "",
            "stdout": "demo2"
        }
    ]
}

# playbook.yml
- hosts: webservers
  remote_user: root
  tasks:
   - shell: echo "{{ item }}"
     with_items:
      - demo1
      - demo2
     register: echo
   - debug:
     msg="{{ echo }}"
   - name: return_code_not_zero
     fail: msg="命令 {{ item.cmd }} 执行结果返回0"
     when: item.rc != 0
     with_items: "{{ echo.results }}"

原创文章禁止转载:技术学堂 » Ansible自动化运维之Playbook循环迭代

精彩评论

8+6=

感谢您的支持与鼓励

支付宝扫一扫打赏

微信扫一扫打赏