Ansible synchronize模块执行后未复制文件到远程主机故障排查
问题根因
synchronize模块是rsync的封装,参数行为和手敲rsync命令存在差异:当配置recursive: no时,若源路径为目录,模块默认不会遍历目录下的平级文件,仅会校验目录本身属性,因此执行后无文件同步、changed值为0,属于参数默认逻辑的预期表现,不是执行故障。- 配置
dirs: yes时,实际对应rsync的-d (--dirs)参数,逻辑为复制路径中遇到的目录项但不递归复制目录内的内容,因此会创建空的html子目录,和recursive: no的组合逻辑本身就会产生空目录,无法满足跳过所有子目录的需求。 rsync_opts报语法错误是参数转义问题:Ansible传递rsync_opts的列表参数时,不会经过shell的引号解析流程,写法"-f'- */'"会把嵌套的单引号作为参数内容的一部分传给rsync,导致rsync收到的过滤规则格式非法;而终端直接执行rsync命令时,shell会先解析掉外层嵌套的引号,rsync收到的是合法规则,因此可以正常运行。
解决方案
方案1:修正rsync_opts传参格式
去掉参数里多余的嵌套引号,同时注意源路径末尾加斜杠(表示复制目录下的内容,而非复制目录本身),参考配置如下:
- name: Sync only top-level non-directory files synchronize: src: /home/osboxes/ansible/roles/deploy/files/application/ dest: /opt/application/ recursive: no rsync_opts: - "-f- */" - "-f+ *" delegate_to: localhost
该配置会直接通过rsync过滤规则排除所有目录项,仅同步根路径下的普通文件,不会创建空的html子目录。
方案2:预查找文件后同步(逻辑更直观,无转义坑)
如果不想处理rsync的规则转义问题,可以先通过find模块筛选出源路径下所有非目录类型的文件,再逐个同步,完全规避目录复制逻辑,参考配置如下:
- name: Locate all non-directory files in source path find: paths: /home/osboxes/ansible/roles/deploy/files/application file_type: file delegate_to: localhost register: target_sync_files - name: Push files to target host synchronize: src: "{{ item.path }}" dest: /opt/application/ loop: "{{ target_sync_files.files }}" delegate_to: localhost
该方案逻辑完全可控,不会出现多余目录被复制的问题,适合对rsync规则不熟悉的场景。
内容的提问来源于stack exchange,提问作者Sallivan80
相关产品推荐
相关产品推荐

