如何在Ansible中通过scp -3p实现跨远程主机目录复制?
问题解决:通过Ansible使用scp -3p跨主机复制目录并匹配清单配置
一、单目标主机的正确实现
核心问题是直接使用主机名时,scp不会自动读取Ansible清单中的自定义端口、用户等配置,需手动拼接清单内的连接参数。
修改copy_webapp/tasks/main.yml中的任务,通过hostvars调用目标主机的清单变量:
- name: 复制Web应用目录到指定主机 ansible.builtin.command: > scp -3p -P {{ hostvars[desthost].ansible_port }} webapp{{ template }}.mydomain.com:{{ webapp_basedir }} {{ hostvars[desthost].ansible_user }}@{{ hostvars[desthost].ansible_host }}:{{ webapp_basedir }} delegate_to: localhost
关键说明:
hostvars[desthost]可获取清单中目标主机的所有配置变量,包括ansible_host(实际连接地址)、ansible_port、ansible_user- scp的端口参数为大写
-P,需与清单中的ansible_port对应 delegate_to: localhost指定任务在本地执行,适配scp -3的中转逻辑
执行命令保持不变:
ansible-playbook -i inventory/ playbook.yml --extra-vars "desthost=websrv1"
二、遍历组内主机批量复制
若需批量复制到指定组的所有主机,可利用Ansible内置的groups变量遍历组内主机:
修改任务为:
- name: 批量复制Web应用目录到组内所有主机 ansible.builtin.command: > scp -3p -P {{ hostvars[item].ansible_port }} webapp{{ template }}.mydomain.com:{{ webapp_basedir }} {{ hostvars[item].ansible_user }}@{{ hostvars[item].ansible_host }}:{{ webapp_basedir }} delegate_to: localhost loop: "{{ groups[destgroup] }}"
使用说明:
- 通过
--extra-vars传入目标组名,示例命令:
ansible-playbook -i inventory/ playbook.yml --extra-vars "destgroup=client1"
groups[destgroup]会返回指定组内的所有主机名列表,loop会逐个执行复制操作
补充优化建议
- 添加有效性校验:提前检查目标主机/组是否存在于清单,避免无效变量报错:
- name: 验证目标主机存在 ansible.builtin.assert: that: desthost in groups.all fail_msg: "目标主机{{ desthost }}不在主机清单中" when: desthost is defined - name: 验证目标组存在 ansible.builtin.assert: that: destgroup in groups fail_msg: "目标组{{ destgroup }}不在主机清单中" when: destgroup is defined
- 禁用命令警告:若Ansible提示scp命令的合规警告,可添加
warn: false参数关闭提示 - 错误捕获:通过
failed_when定义自定义失败条件,比如捕获权限不足、文件不存在等场景:
failed_when: "'Permission denied' in stdout or 'No such file or directory' in stdout"
内容的提问来源于stack exchange,提问作者Lucio Crusca
相关产品推荐
相关产品推荐

