如何在Ansible中基于源路径自动循环复制文件到目标路径
问题描述
我的Ansible项目中,files/目录遵循以下规范(所有角色均按此结构存放文件):
files/{{ ansible_distribution }}/etc/modules-load.d/i915.conf files/{{ ansible_distribution }}/{{ host }}/etc/modules-load.d/i2c-dev.conf files/etc/modules-load.d/tcp-bbr.conf ...
源文件分为三类层级目录:
files/ files/{{ ansible_distribution }}/ files/{{ ansible_distribution }}/{{ host }}/
files/下的文件适用于所有受管目标主机files/{{ ansible_distribution }}/下的文件仅对应特定发行版的主机files/{{ ansible_distribution }}/{{ host }}/下的文件为单台主机专属
这些文件的目标路径对应系统根目录/,例如:
/etc/modules-load.d/i2c-dev.conf /etc/modules-load.d/i915.conf /etc/modules-load.d/tcp-bbr.conf
需求:不硬编码每个文件的源路径与目标路径,自动循环复制所有符合结构的源文件到对应目标路径(假设同一文件不会同时出现在主机专属目录与通用目录中)。
解决方案
方法一:使用find模块收集文件后批量复制
通过find模块在控制端收集所有层级的配置文件,再通过正则截取目标路径完成复制:
- name: 收集所有需要同步的配置文件 find: paths: - "{{ role_path }}/files" - "{{ role_path }}/files/{{ ansible_distribution }}" - "{{ role_path }}/files/{{ ansible_distribution }}/{{ inventory_hostname }}" recurse: yes file_type: file register: config_files delegate_to: localhost - name: 复制配置文件到目标主机对应路径 copy: src: "{{ item.path }}" dest: "/{{ item.path | regex_replace('^.*?files(/|$)(.*)$', '\\2') }}" owner: root group: root mode: '0644' loop: "{{ config_files.files }}"
关键说明:
delegate_to: localhost:在控制端执行文件查找,避免在目标主机上操作本地文件- 正则表达式
regex_replace:截取files/之后的路径部分,拼接成目标主机根路径下的对应位置 - 若不在角色中使用,将
role_path替换为playbook_dir + '/files'即可
方法二:使用with_filetree遍历文件树(Ansible 2.5+)
利用with_filetree递归遍历files/目录,直接处理所有文件:
- name: 遍历配置文件树并同步到目标主机 copy: src: "{{ item.src }}" dest: "/{{ item.path | regex_replace('^(files|files/.*?/)(.*)$', '\\2') }}" owner: root group: root mode: '0644' with_filetree: "{{ role_path }}/files" when: item.state == 'file'
关键说明:
with_filetree会自动递归遍历指定目录下的所有文件与目录when: item.state == 'file'确保只处理文件,跳过目录节点- 正则表达式自动剥离
files/及前面的层级前缀,生成目标路径
注意事项
- 题目已说明同一文件不会重复出现在不同层级目录,因此无需处理覆盖优先级;若需要支持覆盖(如主机专属文件覆盖通用文件),可调整
find模块的paths顺序(优先级高的目录放在前面),或在复制前增加文件存在性检查 - 可根据实际需求调整
copy模块的owner、group、mode等权限参数
内容的提问来源于stack exchange,提问作者David Shields
相关产品推荐
相关产品推荐

