如何通过Ansible实现文件与对应主机的逐一复制?
问题
需要将10个文件按一一对应关系复制到10台主机,例如1_file.txt复制到1_host,2_file.txt复制到2_host,以此类推。
尝试过两种方法均报错:
- 使用
zip过滤器的Playbook:
- name: Copy splitted files to instances copy: src: "{{ item.0 }}" dest: "{{ remote_ips_file }}" delegate_to: "{{ item.1 }}" loop: "{{ splitted_files.files | zip(instances) | list }}"
报错信息:
{"msg": "Unexpected failure during module execution.", "stdout": ""}
- 调用
zip()函数的写法:
- name: Copy files to hosts hosts: "{{ hosts }}" tasks: - name: Copy file to host copy: src: "{{ item.0 }}" dest: "/tmp/{{ item.1 }}" loop: "{{ zip(files, hosts) }}" vars: files: ['/path/to/file1', '/path/to/file2'] hosts: ['host1', 'host2']
报错信息:
zip is undefined
临时解决方法使用with_together,但无法并行执行:
- name: Copy splitted files to instances copy: src: "{{ item.0.path }}" dest: "{{ remote_ips_file }}" delegate_to: "{{ item.1 }}" with_together: - "{{ splitted_files.files }}" - "{{groups['all']}}"
错误原因
- 直接调用
zip()函数报错:Ansible的Jinja2模板环境中没有内置zip函数,必须通过管道过滤器的方式使用zip(即list1 | zip(list2))。 - 第一种
zip过滤器写法报错:splitted_files.files是文件对象列表(通常由find模块返回),每个元素是包含path等属性的字典,直接使用item.0会传递整个对象而非文件路径,导致模块执行失败。 with_together无法并行:这是旧版循环语法的特性,默认串行执行;而loop是Ansible推荐的新语法,支持并行执行(依赖forks配置)。
正确实现方式
以下两种方法均支持并行执行,且能保证文件与主机的一一对应:
方法1:修正zip过滤器的路径引用
- name: 按对应关系复制文件到主机 copy: src: "{{ item.0.path }}" # 取文件对象的path属性作为源路径 dest: "{{ remote_ips_file }}" delegate_to: "{{ item.1 }}" loop: "{{ splitted_files.files | zip(groups['all']) | list }}" # 若使用自定义主机列表,替换groups['all']为你的instances变量
说明:
- 确保
splitted_files.files和主机列表(如groups['all'])长度完全一致 - Ansible默认并行数由
forks参数控制(默认5,可在ansible.cfg中调整为10以匹配你的主机数量)
方法2:利用循环索引匹配
通过循环的索引值直接对应文件和主机,逻辑更直观:
- name: 按索引对应复制文件到主机 copy: src: "{{ splitted_files.files[ansible_loop.index0].path }}" dest: "{{ remote_ips_file }}" delegate_to: "{{ groups['all'][ansible_loop.index0] }}" loop: "{{ groups['all'] }}" loop_control: extended: yes # 开启扩展循环变量,才能使用ansible_loop.index0
说明:
ansible_loop.index0是从0开始的循环索引,确保第N个循环对应第N个文件和第N台主机- 同样需要保证文件列表与主机列表长度一致
关键注意事项
- 始终确保文件列表和主机列表的长度相同,否则会出现匹配错位或执行报错
- 若需要全并行执行,将
ansible.cfg中的forks值设置为等于或大于主机数量(如forks=10) - 使用
delegate_to时,控制节点需能SSH访问所有目标主机,且拥有文件复制的权限
内容的提问来源于stack exchange,提问作者Сергей Гусев
相关产品推荐
相关产品推荐

