ansible loop循环

 loop介绍

在 Ansible 中,loop(循环)用于 批量执行任务,避免重复编写相同的任务代码,适用于 文件管理、用户管理、软件安装等 场景。

1. 循环创建用户

- name: 创建多个用户
  ansible.builtin.user:
    name: "{{ item }}"
    state: present
  loop:
    - user1
    - user2
    - user3

关键点解析

1. user 模块

ansible.builtin.user 用于管理 Linux 用户。这里的 shell 参数用于指定用户的默认 Shell(如 /bin/bash/bin/zsh)。

2. vars 变量
vars:
  user_shells:
    user1: /bin/bash
    user2: /bin/zsh
    user3: /bin/sh

📌 这里定义了一个字典(dict),键(key)是用户名,值(value)是该用户的 Shell。

3. lookup('dict', user_shells)
loop: "{{ lookup('dict', user_shells) }}"

📌 lookup('dict', user_shells) 将字典转换为列表,生成的数据格式如下:

[
  { "key": "user1", "value": "/bin/bash" },
  { "key": "user2", "value": "/bin/zsh" },
  { "key": "user3", "value": "/bin/sh" }
]

然后,loop 遍历这个列表,每次迭代时:

  • item.key 代表 用户名(如 user1
  • item.value 代表 Shell(如 /bin/bash

2.loop 传递多个参数(字典列表)

复制代码
- name: 创建用户并设置 UID
  ansible.builtin.user:
    name: "{{ item.name }}"
    uid: "{{ item.uid }}"
    state: present
  loop:
    - { name: "user1", uid: "1010" }   # 如果是多个值,需要写成字典格式
    - { name: "user2", uid: "1020" }
    - { name: "user3", uid: "1030" }
复制代码

3. 循环创建目录

复制代码
- name: 创建多个目录
  ansible.builtin.file:
    path: "/data/{{ item }}"
    state: directory
    mode: '0755'
  loop:
    - app1
    - app2
    - app3
复制代码

4. 循环安装包

传统写法

复制代码
    - name: ubuntu install gcc openssl
      ansible.builtin.apt:
        name:
          - build-essential
          - libpcre3
          - libpcre3-dev
          - openssl
          - libssl-dev
          - zlib1g-dev zlib1g
        state: present
        update_cache: yes
      when: ansible_distribution == "Ubuntu"
复制代码

使用loop后

老写法,尽量用loop

- name: 安装多个软件包
  ansible.builtin.package:
    name: "{{ item }}"
    state: present
  with_items:
    - vim
    - git
    - curl
复制代码
- hosts: nginx
  remote_user: root
  # 收集远程主机信息
  gather_facts: yes
  #vars:
  #  nginx_version: "1.22.1"
  #  nginx_src_dir: "/tmp/nginx/"
  #  nginx_install_dir: "/usr/local/nginx"
  vars_files:
    - vars.yaml
  tasks:
    - name: install gcc openssl
      ansible.builtin.yum:
        name: "{{ item }}"
        state: present
        update_cache: yes
      loop:
          - openssl
          - openssl-devel- perl
          - perl-ExtUtils-Embed
      when: ansible_distribution == "CentOS"
    - name: ubuntu install gcc openssl
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
        update_cache: yes
      loop:
          - build-essential
          - libpcre3- libssl-dev
          - zlib1g-dev zlib1g
      when: ansible_distribution == "Ubuntu"
复制代码

loop + with_dict(字典迭代)

复制代码
- name: 配置多个用户的 Shell
  ansible.builtin.user:
    name: "{{ item.key }}"
    shell: "{{ item.value }}"
  loop: "{{ lookup('dict', user_shells) }}"
  vars:
    user_shells:
      user1: /bin/bash
      user2: /bin/zsh
      user3: /bin/sh
复制代码

作用

  • 读取 user_shells 变量,分别为 user1user2user3 设置不同 Shell。
  • lookup 是一个插件,用于从不同的来源(如文件、环境变量、字典等)获取数据
  • lookup('<插件名>', <参数>)

在 Ansible 中,lookup 是一个插件,用于从不同的来源(如文件、环境变量、字典等)获取数据

lookup('dict', dictionary_name) 作用:

  • 输入:字典
  • 输出:将字典转换成 key-value 对象的列表
  • 典型用途:配合 loop 进行批量任务执行

 lookup 介绍

 lookup 在 Ansible 中的更多用法

它的基本格式:

lookup('<插件名>', <参数>)

1. lookup('file', <文件路径>) 读取文件内容

🔹 作用:读取本地文件的内容并返回为字符串。

- name: 读取文件内容
  debug:
    msg: "{{ lookup('file', '/etc/hostname') }}"

结果

TASK [读取文件内容] *****************************************
ok: [localhost] => {
    "msg": "my-server-hostname"
}

适用场景:读取 SSH 密钥、证书、配置信息等。

 2. lookup('env', '<环境变量名>') 读取环境变量

🔹 作用:获取控制机(Ansible 运行的机器)上的环境变量。

- name: 获取 HOME 目录
  debug:
    msg: "{{ lookup('env', 'HOME') }}"

结果

TASK [获取 HOME 目录] *****************************************
ok: [localhost] => {
    "msg": "/root"
}

适用场景:在 Playbook 中使用系统环境变量,如 PATHHOMEJAVA_HOME

3. lookup('dict', <字典变量>) 遍历字典

🔹 作用:将字典转换成列表,适用于 loop 进行迭代。

复制代码
- name: 遍历字典
  debug:
    msg: "User {{ item.key }} uses {{ item.value }}"
  loop: "{{ lookup('dict', user_shells) }}"
  vars:
    user_shells:
      user1: /bin/bash
      user2: /bin/zsh
      user3: /bin/sh
复制代码
dict 介绍

dict 是 Ansible lookup 插件中的一种类型,专门用于将字典转换为可迭代的列表。

vars:
  user_shells:
    user1: /bin/bash
    user2: /bin/zsh
    user3: /bin/sh

例子 1:配合 user 模块批量配置用户

复制代码
- name: 配置多个用户的 Shell
  ansible.builtin.user:
    name: "{{ item.key }}"     # 用户名
    shell: "{{ item.value }}"  # 指定 Shell
  loop: "{{ lookup('dict', user_shells) }}"
  vars:
    user_shells:
      user1: /bin/bash
      user2: /bin/zsh
      user3: /bin/sh
复制代码

错误写法

- name: 遍历 user_shells
  loop: "{{ user_shells }}"

错误原因

  • user_shells 是一个字典,而 loop 需要列表才能遍历。
  • 直接传 user_shells 会导致 Ansible 报错。

正确写法

- name: 遍历字典
  loop: "{{ lookup('dict', user_shells) }}"

原因

  • lookup('dict', user_shells) 把字典转换成列表,可以被 loop 遍历。

4. lookup('password', <参数>) 生成随机密码

🔹 作用:生成一个随机密码,可用于创建用户、数据库密码等。

- name: 生成随机密码
  debug:
    msg: "{{ lookup('password', '/dev/null length=12 chars=ascii_letters,digits') }}"

结果

TASK [生成随机密码] *****************************************
ok: [localhost] => {
    "msg": "G5d7T3p9K2Lx"
}

5. lookup('url', '<远程 URL>') 获取网页内容

🔹 作用:从远程 URL 获取数据,如 API 响应、HTML 页面等。

- name: 获取远程 JSON 数据
  debug:
    msg: "{{ lookup('url', 'https://api.github.com/repos/ansible/ansible') }}"

结果

TASK [获取远程 JSON 数据] *****************************************
ok: [localhost] => {
    "msg": "{'id': 3638964, 'name': 'ansible', 'full_name': 'ansible/ansible', 'owner': {...}, ...}"
}

6. lookup('csvfile', '<文件路径>') 读取 CSV 文件

🔹 作用:解析 CSV 文件,提取数据。

- name: 读取 CSV 文件
  debug:
    msg: "{{ lookup('csvfile', '/tmp/users.csv delimiter=, col=1') }}"

结果

TASK [读取 CSV 文件] *****************************************
ok: [localhost] => {
    "msg": "user1"
}

7. lookup('ini', '<文件路径>') 读取 INI 配置文件

🔹 作用:解析 .ini 文件,提取特定的键值对。

示例 假设有一个 INI 文件 /etc/app.conf

[database]
user = admin
password = secret

使用 lookup 读取 user

- name: 获取数据库用户
  debug:
    msg: "{{ lookup('ini', '/etc/app.conf section=database key=user') }}"

结果

TASK [获取数据库用户] *****************************************
ok: [localhost] => {
    "msg": "admin"
}

 Ansible loop_control 详解

在 Ansible 的 loop 结构中,loop_control 允许你自定义循环行为,比如:

  • 控制变量名称(loop_var
  • 格式化输出(label
  • 限制循环深度(index_var
  • 访问当前迭代索引(index

1. loop_var 自定义循环变量

默认情况下,Ansible 会使用 item 作为循环变量。如果多个 loop 嵌套,会导致变量冲突,loop_var 允许你自定义变量名称。

复制代码
- name: 创建多个用户
  ansible.builtin.user:
    name: "{{ user.name }}"
    shell: "{{ user.shell }}"
  loop:
    - { name: "user1", shell: "/bin/bash" }
    - { name: "user2", shell: "/bin/zsh" }
  loop_control:
    loop_var: user
复制代码

2. index_var 获取循环索引

在循环中,index_var 可以获取当前迭代的索引(从 0 开始)。

复制代码
- name: 安装多个软件包
  ansible.builtin.package:
    name: "{{ item }}"
    state: present
  loop:
    - nginx
    - mysql
    - redis
  loop_control:
    index_var: idx
  debug:
    msg: "安装第 {{ idx + 1 }} 个软件包:{{ item }}"
复制代码

结果

TASK [安装多个软件包] *****************************************
ok: [localhost] => (item=nginx) =>
  msg: "安装第 1 个软件包:nginx"
ok: [localhost] => (item=mysql) =>
  msg: "安装第 2 个软件包:mysql"
ok: [localhost] => (item=redis) =>
  msg: "安装第 3 个软件包:redis"

3. label 自定义调试信息

label 允许你在 debug 输出中自定义更易读的消息

复制代码
- name: 添加用户
  ansible.builtin.user:
    name: "{{ user.name }}"
    shell: "{{ user.shell }}"
  loop:
    - { name: "alice", shell: "/bin/bash" }
    - { name: "bob", shell: "/bin/zsh" }
  loop_control:
    loop_var: user
    label: "用户: {{ user.name }} 使用 {{ user.shell }}"
复制代码

结果

TASK [添加用户] *****************************************
ok: [localhost] => (用户: alice 使用 /bin/bash)
ok: [localhost] => (用户: bob 使用 /bin/zsh)

4. extended 启用高级循环变量

如果 loop 迭代的是复杂数据(如字典),默认 debug 只会显示 item 的值,使用 extended: yes 可以显示 indexkeyvalue 等信息。

复制代码
- name: 遍历字典
  debug:
    msg: "{{ item }}"
  loop: "{{ lookup('dict', user_shells) }}"
  loop_control:
    extended: yes
  vars:
    user_shells:
      user1: /bin/bash
      user2: /bin/zsh
复制代码

结果

TASK [遍历字典] *****************************************
ok: [localhost] => (item={'key': 'user1', 'value': '/bin/bash', 'index': 0}) =>
  msg: "{'key': 'user1', 'value': '/bin/bash', 'index': 0}"
ok: [localhost] => (item={'key': 'user2', 'value': '/bin/zsh', 'index': 1}) =>
  msg: "{'key': 'user2', 'value': '/bin/zsh', 'index': 1}"

5.loop + pause(循环间隔执行)

复制代码
- name: 批量重启服务,并等待 5 秒
  ansible.builtin.service:
    name: "{{ item }}"
    state: restarted
  loop:
    - nginx
    - mysql
    - redis
  loop_control:
    pause: 5  # 每次执行后暂停 5
复制代码

作用:

  • 依次重启 nginxmysqlredis每次重启后等 5 秒

loop VS with_*

用法适用场景是否推荐
loop 通用方式(列表、字典、复杂数据) ✅ 推荐
with_items 单纯的列表 ❌ 旧写法,不推荐
with_dict 字典迭代 ✅ 仍可用,但 loop + lookup('dict') 更好
with_fileglob 读取目录下的所有文件 ✅ 仍可用
with_lines 运行命令并迭代结果 ✅ 仍可用
posted @   不会跳舞的胖子  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示