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

如何使用with_fileglob循环?复制通配符匹配文件并设置不同目标权限

解决Ansible中用通配符复制文件并设置不同权限的问题

嘿,我一看你这个Playbook就知道问题出在哪了——with_fileglob根本不支持你这种传入字典(带origin和mode)的用法!它的设计初衷就是单纯接收通配符路径,返回控制节点上匹配到的文件列表,没法同时携带额外参数比如权限,所以你这么写肯定会报错。

下面分两种常见场景给你解决方案:

场景1:文件在控制节点,要复制到远程节点并设置不同权限

这种情况我们可以用with_subelements配合lookup('fileglob')来实现,把每个通配符规则和对应的权限绑定,再遍历每个匹配到的文件:

- hosts: myhost
  gather_facts: no
  tasks:
    # 先确保目标目录存在,不然复制会失败
    - name: Create target directory
      file:
        path: /home/user1/tmps/
        state: directory
        owner: user1
        mode: '750'

    - name: Copy files with specific permissions
      copy:
        src: "{{ file_path }}"
        dest: /home/user1/tmps/
        owner: user1
        mode: "{{ item.0.mode }}"
      with_subelements:
        - # 定义规则组:权限 + 控制节点上的文件通配符
          - mode: '640'
            files: "{{ lookup('fileglob', '/tmp/hello*', wantlist=True) }}"
          - mode: '600'
            files: "{{ lookup('fileglob', '/tmp/hi*', wantlist=True) }}"
        - files

这里的关键点:

  • wantlist=True必须加,它让lookup返回列表格式的文件路径,哪怕只匹配到一个文件也不会变成字符串,避免遍历出错
  • with_subelements会帮我们把每个规则下的文件拆出来,item.0对应规则(包含mode),item.1对应单个文件路径

场景2:文件在远程节点,要复制到远程的另一个目录并设置不同权限

这种情况不能用fileglob(它只在控制节点查找文件),得先用find模块获取远程节点上的文件列表,再根据文件名匹配规则设置权限:

方案A:拆分任务(清晰直观)

- hosts: myhost
  gather_facts: no
  tasks:
    - name: Create target directory
      file:
        path: /home/user1/tmps/
        state: directory
        owner: user1
        mode: '750'

    # 获取远程节点上的hello*文件
    - name: Locate hello* files on remote
      find:
        paths: /tmp
        patterns: 'hello*'
      register: hello_files

    # 获取远程节点上的hi*文件
    - name: Locate hi* files on remote
      find:
        paths: /tmp
        patterns: 'hi*'
      register: hi_files

    # 复制hello*并设置640权限
    - name: Copy hello files with 640 permissions
      copy:
        src: "{{ item.path }}"
        dest: /home/user1/tmps/
        owner: user1
        mode: '640'
      loop: "{{ hello_files.files }}"

    # 复制hi*并设置600权限
    - name: Copy hi files with 600 permissions
      copy:
        src: "{{ item.path }}"
        dest: /home/user1/tmps/
        owner: user1
        mode: '600'
      loop: "{{ hi_files.files }}"

方案B:合并成单个任务(更简洁)

如果规则简单,也可以一次获取所有文件,用条件判断来分配权限:

- hosts: myhost
  gather_facts: no
  tasks:
    - name: Create target directory
      file:
        path: /home/user1/tmps/
        state: directory
        owner: user1
        mode: '750'

    - name: Get all target files on remote
      find:
        paths: /tmp
        patterns: ['hello*', 'hi*']
      register: all_files

    - name: Copy files with dynamic permissions
      copy:
        src: "{{ item.path }}"
        dest: /home/user1/tmps/
        owner: user1
        # 根据文件名匹配规则设置权限
        mode: "{{ '640' if item.path is match('/tmp/hello.*') else '600' }}"
      loop: "{{ all_files.files }}"

为什么你的原Playbook会报错?

再强调一下:with_fileglob的参数只能是字符串类型的通配符路径,它会直接把你传入的{ origin: '/tmp/hello*', mode: '640' }当成文件路径去查找,自然找不到对应的文件,所以抛出了异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:51:12