如何使用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
相关产品推荐
相关产品推荐

