Ansible synchronize模块推送文件至远程MTA主机失败求助
在10.1.0.4主机上以play用户运行Ansible playbook,目标是将本地生成的Let's Encrypt证书同步至inventory中定义的MTA主机,但同步任务执行失败,报错显示rsync尝试创建不存在的路径/root/ssh://xxx/tmp,无论指定何种目标目录均失败。
Inventory配置
mta: hosts: 10.1.0.3: 10.1.0.2: vars: ansible_user: root ansible_ssh_private_key_file: ~/.ssh/play
同步任务配置
- name: Synchronization using rsync protocol on delegate host (push) ansible.posix.synchronize: src: "/home/play/tmp/" dest: "ssh://{{ mta_servers }}/tmp" loop: "{{ groups['mta'] }}" loop_control: loop_var: mta_servers run_once: true register: sync_files
报错信息
TASK [local : Synchronization using rsync protocol on delegate host ( push )] ********************************************************************************************************************************** failed: [10.1.0.4] (item=10.1.0.3) => {"ansible_loop_var": "mta_servers", "changed": false, "cmd": "/usr/bin/rsync --delay-updates -F --compress --archive --rsh='/usr/bin/ssh -S none -i /home/play/.ssh/pwned -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' /home/play/tmp/ root@10.1.0.4:ssh://10.1.0.3/tmp", "msg": "Warning: Permanently added '10.1.0.4' (ED25519) to the list of known hosts.\r\nrsync: [Receiver] mkdir \"/root/ssh://10.1.0.3/tmp\" failed: No such file or directory (2)\nrsync error: error in file IO (code 11) at main.c(783) [Receiver=3.2.3]\n", "mta_servers": "10.1.0.3", "rc": 11} failed: [10.1.0.4] (item=10.1.0.2) => {"ansible_loop_var": "mta_servers", "changed": false, "cmd": "/usr/bin/rsync --delay-updates -F --compress --archive --rsh='/usr/bin/ssh -S none -i /home/play/.ssh/pwned -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' /home/play/tmp/ root@10.1.0.4:ssh://10.1.0.2/tmp", "msg": "Warning: Permanently added '10.1.0.4' (ED25519) to the list of known hosts.\r\nrsync: [Receiver] mkdir \"/root/ssh://10.1.0.2/tmp\" failed: No such file or directory (2)\nrsync error: error in file IO (code 11) at main.c(783) [Receiver=3.2.3]\n", "mta_servers": "10.1.0.2", "rc": 11}
详细输出(-vvv)
failed: [10.1.0.4] (item=10.1.0.2) => { "ansible_loop_var": "mta_servers", "changed": false, "cmd": "/usr/bin/rsync --delay-updates -F --compress --archive --rsh='/usr/bin/ssh -S none -i /home/play/.ssh/pwned -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' --out-format='<<CHANGED>>%i %n%L' /home/play/tmp/ root@10.1.0.4:ssh://10.1.0.2/tmp", "invocation": { "module_args": { "_local_rsync_password": null, "_local_rsync_path": "rsync", "_substitute_controller": false, "archive": true, "checksum": false, "compress": true, "copy_links": false, "delay_updates": true, "delete": false, "dest": "root@10.1.0.4:ssh://10.1.0.2/tmp", "dest_port": null, "dirs": false, "existing_only": false, "group": null, "link_dest": null, "links": null, "mode": "push", "owner": null, "partial": false, "perms": null, "private_key": "/home/play/.ssh/pwned", "recursive": null, "rsync_opts": [], "rsync_path": null, "rsync_timeout": 0, "set_remote_user": true, "src": "/home/play/tmp/", "ssh_args": null, "ssh_connection_multiplexing": false, "times": null, "verify_host": false } }, "msg": "Warning: Permanently added '10.1.0.4' (ED25519) to the list of known hosts.\r\nrsync: [Receiver] mkdir \"/root/ssh://10.1.0.2/tmp\" failed: No such file or directory (2)\nrsync error: error in file IO (code 11) at main.c(783) [Receiver=3.2.3]\n", "mta_servers": "10.1.0.2", "rc": 11 }
Ansible版本信息
[play@ans ansible]$ ansible --version ansible [core 2.13.3] config file = /home/play/ansible/ansible.cfg configured module search path = ['/home/play/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3.9/site-packages/ansible ansible collection location = /home/play/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.9.14 (main, Jan 9 2023, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)] jinja version = 3.1.2 libyaml = True
系统环境:RHEL9
从报错的rsync命令可以看出,Ansible错误地把目标地址拼接成了root@10.1.0.4:ssh://10.1.0.2/tmp,这是因为使用synchronize模块时,dest参数格式错误,且run_once: true结合循环的方式不符合模块预期用法。
修复方法1:使用delegate_to循环目标主机
synchronize模块在push模式下,dest直接填写远程主机路径即可,模块会自动结合inventory中的用户和密钥信息构建命令。修改后的任务:
- name: Push certificates to MTA hosts ansible.posix.synchronize: src: "/home/play/tmp/" dest: "/tmp" delegate_to: "{{ item }}" loop: "{{ groups['mta'] }}"
- 移除
run_once: true,改用delegate_to循环每个MTA主机,模块会针对每个目标单独执行同步 dest直接写远程主机上的路径/tmp,模块自动使用inventory定义的ansible_user和密钥连接
修复方法2:保持run_once并正确构造dest参数
如果必须使用run_once,直接在dest中指定完整的远程主机地址(无需ssh://前缀):
- name: Synchronization using rsync protocol on delegate host (push) ansible.posix.synchronize: src: "/home/play/tmp/" dest: "root@{{ mta_servers }}:/tmp" loop: "{{ groups['mta'] }}" loop_control: loop_var: mta_servers run_once: true register: sync_files vars: ansible_ssh_private_key_file: ~/.ssh/play
直接指定root@{{ mta_servers }}:/tmp作为目标,确保模块不会错误拼接地址。
问题根源
原配置中dest使用ssh://{{ mta_servers }}/tmp格式,而synchronize模块默认会将当前执行主机(10.1.0.4)的用户信息附加到目标地址前,导致最终目标路径变成root@10.1.0.4:ssh://10.1.0.2/tmp。rsync会将ssh://10.1.0.2/tmp当作10.1.0.4主机上的本地路径,从而尝试创建不存在的/root/ssh://10.1.0.2/tmp目录。
内容的提问来源于stack exchange,提问作者cybernet2u

