如何在Ansible Playbook中对比两台主机输出?及相关报错排查
解决Ansible跨主机文件校验和对比的Playbook错误问题
问题分析
你遇到的报错信息如下:
ERROR! 'when' is not a valid attribute for a Play,错误出现在/root/two_file_stat.yml的第27行第3列,报错行如下:
- name: Block run only if file has no changes ^ here
这个错误的核心原因很明确:最后那个名为Block run only if file has no changes的任务没有被包含在任何一个Play的tasks列表里,它直接游离在两个独立的Play(分别针对remote_1和remote_2的Play)之外,而Ansible的Playbook语法要求所有任务必须隶属于某个Play,因此无法识别这种游离的任务结构。
除此之外,原Playbook还有一个隐藏的逻辑问题:在第二个Play中直接引用第一个Play注册的test_file_check_1变量是无效的——Ansible的变量默认是Play级别的,跨Play访问其他主机的变量需要通过hostvars这个特殊变量来获取。
修正后的Playbook写法
下面提供两种可行的修正方案,你可以根据自己的需求选择:
方案1:合并逻辑到单个Play,利用hostvars跨主机访问变量
这种方案更简洁,把两台主机的校验和获取与对比逻辑放在同一个Play中:
- hosts: remote_1,remote_2 tasks: - name: 获取目标文件的SHA256校验和 stat: path: /root/abc.txt checksum_algorithm: sha256 register: file_checksum_result - name: 打印当前主机的文件校验和(可选) debug: var: file_checksum_result.stat.checksum when: file_checksum_result.stat.exists - name: 仅在remote_2上执行校验和对比,不同则运行任务 command: /bin/true when: - inventory_hostname == 'remote_2' - hostvars['remote_1'].file_checksum_result.stat.exists - file_checksum_result.stat.exists - hostvars['remote_1'].file_checksum_result.stat.checksum != file_checksum_result.stat.checksum
方案2:分Play执行,通过hostvars跨Play引用变量
这种方案保留了你原有的分Play结构,只修正语法和变量访问问题:
- hosts: remote_1 tasks: - name: 获取remote_1上文件的SHA256校验和 stat: path: /root/abc.txt checksum_algorithm: sha256 register: test_file_check_1 - debug: var: test_file_check_1.stat.checksum when: test_file_check_1.stat.exists - hosts: remote_2 tasks: - name: 获取remote_2上文件的SHA256校验和 stat: path: /root/abc.txt checksum_algorithm: sha256 register: test_file_check_2 - debug: var: test_file_check_2.stat.checksum when: test_file_check_2.stat.exists - name: 对比两台主机的校验和,不同则执行任务 command: /bin/true when: - test_file_check_2.stat.exists - hostvars['remote_1'].test_file_check_1.stat.exists - hostvars['remote_1'].test_file_check_1.stat.checksum != test_file_check_2.stat.checksum
关键注意事项
- 任务归属规则:所有任务必须放在某个Play的
tasks字段下,绝对不能独立于Play存在,这是Ansible Playbook的基础语法要求。 - 跨主机变量访问:使用
hostvars['目标主机名']格式来获取其他主机上注册的变量,比如hostvars['remote_1'].test_file_check_1.stat.checksum就能拿到remote_1上文件的校验和。 - 文件存在性检查:在对比校验和之前,一定要先判断两台主机的目标文件是否存在,避免因为文件不存在导致变量未定义而触发额外报错。
内容的提问来源于stack exchange,提问作者Akash Talole
相关产品推荐
相关产品推荐

