You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure磁盘挂载自动化中Ansible include_tasks循环'item'未定义问题解决

问题描述

通过Terraform创建Azure虚拟机时,需自动挂载基于Jenkins用户输入创建的磁盘——每个磁盘对应传入的LUN编号,通过grep命令获取设备名(如sdc、sdd)。编写了my_tasks.yml实现磁盘分区、格式化、挂载及写入/etc/fstab的操作,计划在playbook.yml中循环调用该任务,但执行时报错。

相关代码

my_tasks.yml

---

- parted:
    device: "{{ volumename.stdout }}"
    number: 1
    state: present
- filesystem:
    fstype: xfs
    dev: "{{ volumename.stdout }}"
- mount:
    fstype: xfs
    opts: noatime
    src: "{{ volumename.stdout }}"
    path: "{{ item.mountpoint }}"
    state: mounted
- command: blkid -s UUID -o value {{ volumename.stdout }}
  register: volumename_disk

- blockinfile:
    path: /etc/fstab
    state: present
    block: |
      UUID={{ volumename_disk.stdout }}   {{ volumename.stdout }}      xfs defaults,noatime,nofail 0 0

playbook.yml

---
- hosts: "{{ host }}"
  become: true
  become_method: sudo
  become_user: root
  vars:
    mount: "{{ lookup('file', '/home/xyz/vars.txt') }}"
  tasks:
    - name: Generate the Lun_Name
      shell: "tree /dev/disk/azure/scsi1 | grep -i lun | awk '{print $2}'"
      register: lun

    - set_fact:
        lun_name: "{{ lun_name|default([]) + [ { 'name': lun.stdout } ] }}"

    - debug:
        msg: "LUN is: {{ lun_name }}"

    - name: Generate the Volume_Name
      shell: echo "$(ls -l /dev/disk/azure/scsi1 |grep  lun |egrep -o "([^\/]+$)")"
      register: volumename

    - set_fact:
        volumenames: "{{ volumenames|default([]) + [ { 'name': volumename.stdout } ] }}"

    - debug:
        msg: "VOLUMENAME is: {{ volumenames }}"

        #    - debug:
        #        msg: "the mountpoints are {{ mount }}"

    - set_fact:
        mountpoint: "{{ lookup('file', '/home/xyz/vars.txt').split(',')  }}"

    - debug:
        msg: "the mountpoints are {{ mountpoint }}"

        #     loop: "{{ mountpoint }}"
    - include_tasks:  my_tasks.yml
      loop: "{{ item.volumenames | list }} {{ item.mountpoint | list }}"
      loop_control:
        loop_var: "{{ item }}"

执行错误

fatal: [10.102.26.74]: FAILED! => {"msg": "'item' is undefined"}

单独循环mountpoint可正常运行,确认问题出在include_tasks的循环逻辑部分,需解决该问题并优化代码。


解决方法与优化建议

1. 修复循环逻辑错误

报错核心是item未定义:你在loop中错误引用了item.volumenames和item.mountpoint,但此时item尚未生成。正确做法是先将设备名与挂载点配对成统一的字典列表,再循环这个列表。

2. 修正playbook.yml关键部分

---
- hosts: "{{ host }}"
  become: true
  become_method: sudo
  become_user: root
  vars:
    mount_file_path: "/home/xyz/vars.txt"
  tasks:
    # 修正:直接获取所有LUN对应的设备名字符串列表
    - name: 获取磁盘设备名列表
      shell: "ls -l /dev/disk/azure/scsi1 | grep lun | egrep -o '[^/]+$'"
      register: volumename_result

    - set_fact:
        volumenames: "{{ volumename_result.stdout_lines }}"

    - debug:
        msg: "磁盘设备名: {{ volumenames }}"

    # 获取挂载点列表(去除空格)
    - set_fact:
        mountpoints: "{{ lookup('file', mount_file_path).split(',') | map('trim') | list }}"

    - debug:
        msg: "挂载点列表: {{ mountpoints }}"

    # 配对设备名与挂载点为字典列表(需确保两者长度一致)
    - set_fact:
        disk_mount_pairs: "{{ disk_mount_pairs|default([]) + [ {'device': volumenames[index], 'mountpoint': mountpoints[index]} ] }}"
      loop: "{{ range(0, volumenames|length) | list }}"
      loop_control:
        index_var: index

    - debug:
        msg: "磁盘-挂载点配对: {{ disk_mount_pairs }}"

    # 循环调用任务,传递配对后的变量
    - include_tasks: my_tasks.yml
      loop: "{{ disk_mount_pairs }}"
      loop_control:
        loop_var: disk_pair

3. 调整my_tasks.yml接收变量

原任务中的volumename.stdout和item.mountpoint需替换为循环传递的disk_pair变量,同时注意分区后设备名会追加1(如sdc变为sdc1):

---

- parted:
    device: "/dev/{{ disk_pair.device }}"
    number: 1
    state: present
- filesystem:
    fstype: xfs
    dev: "/dev/{{ disk_pair.device }}1"
- mount:
    fstype: xfs
    opts: noatime
    src: "/dev/{{ disk_pair.device }}1"
    path: "{{ disk_pair.mountpoint }}"
    state: mounted
- command: blkid -s UUID -o value "/dev/{{ disk_pair.device }}1"
  register: disk_uuid

- blockinfile:
    path: /etc/fstab
    state: present
    block: |
      UUID={{ disk_uuid.stdout }}   {{ disk_pair.mountpoint }}      xfs defaults,noatime,nofail 0 0

4. 额外优化点

  • 替换shell命令获取设备:改用azure_rm_disk_info模块从Azure API直接获取磁盘信息,比解析/dev目录更可靠
  • 增加长度校验:在配对前检查volumenames与mountpoints长度是否一致,避免不匹配
  • 幂等性优化:给parted和filesystem模块添加条件判断,如检查分区是否已存在、文件系统是否已格式化,避免重复执行
  • 错误处理:添加failed_when或rescue块,处理磁盘操作失败的场景

内容的提问来源于stack exchange,提问作者Sagar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:25:53