ansible - 如何在 Ansible 中比较多个文件
问题描述
我正在尝试找到一种方法来将目录中的多个文件与另一个目录中的文件进行比较。例如 - 目录 /home/ansible/properties/ 中有 10 个文件,远程主机上的另一个目录(如 /opt/apps/properties/)中有类似的文件集。我想比较它们中的每一个,可能使用校验和,即使其中一个文件被更改,然后做一些任务 -
我的剧本下面可以比较一个文件,但是有没有办法比较所有文件或目录?
- name: Get checksum of my First file
stat:
path : "/home/ansible/properties/my.properties"
register: myfirstfile
- name: Current SHA1
set_fact:
1stFilechecksum: "{{ myfirstfile.stat.checksum }}"
- name: Get checksum of my Second File
stat:
path : "/opt/aaps/properties/my.properties"
register: mysecondfile
- name: Current SHA1
set_fact:
2ndFilechecksum: "{{ mysecondfile.stat.checksum }}"
- name: Comparing 2 files
debug:
msg: "Do Something....."
when: 1stFilechecksum != 2ndFilechecksum
解决方案
根据您的描述测试文件树
……或者至少我从中了解到的。
/tmp/test/a /tmp/test/b
├── file10.txt ├── file10.txt
├── file1.txt ├── file1.txt
├── file2.txt ├── file2.txt
├── file3.txt ├── file3.txt
├── file4.txt ├── file4.txt
├── file5.txt ├── file5.txt
├── file6.txt ├── file6.txt
├── file7.txt ├── file7.txt
├── file8.txt ├── file8.txt
├── file9.txt ├── file9.txt
└── toto.txt └── titi.txt
如您所见,所有文件都是通用的,除了每个目录中的文件。这些将被排除在比较之外。file2.txt
对于通用文件,除了内容相同外,其他文件都是不同file5.txt
的。
用于解决方案的碱基
- 我们在循环中搜索两个目录中的所有文件
find
。中的所有文件a
都在 中,results[0]
那些来自b
.results[1]
该get_checksum
选项收集我们需要的信息。 - 在下一个任务中:
- 我们循环在
a
. - 在每次迭代中,我们通过在替换 dir 路径后仅
b
选择selectattr
具有相同名称的列表元素来计算相应的文件。path
保留结果的第一个元素给出了我们的文件。如果结果为空(不是公共文件),我们默认为空对象 - when 子句检查文件是否存在(常见的我们跳过)以及它们是否不同(校验和不相等)
loop_control
用于自定义循环变量名称以提高可读性(即 item => file1)并将循环项的输出限制为可以理解的内容。
- 我们循环在
剧本
---
- name: compare files in two dirs
hosts: localhost
gather_facts: false
vars:
dir1: /tmp/test/a
dir2: /tmp/test/b
tasks:
- name: "Find all files in {{ dir1 }} and {{ dir2 }}"
find:
paths:
- "{{ item }}"
get_checksum: true
register: search_files
loop:
- "{{ dir1 }}"
- "{{ dir2 }}"
- name: "Compare checksums from {{ dir1 }} to {{ dir2 }}. do something if different"
vars:
file2: >-
{{
search_files.results[1].files |
selectattr('path', 'eq', file1.path | replace(dir1, dir2)) |
list |
first |
default({})
}}
debug:
msg: "Files differ. Do something"
loop: "{{ search_files.results[0].files }}"
loop_control:
loop_var: file1
label: "Comparing {{ file1.path }} to {{ file2.path | default('N/A') }}"
when:
- file2.path is defined
- file1.checksum != file2.checksum
结果
$ ansible-playbook test.yml
PLAY [compare files in two dirs] ***************************************************************************************************************
TASK [Find all files in /tmp/test/a and /tmp/test/b] *******************************************************************************************
ok: [localhost] => (item=/tmp/test/a)
ok: [localhost] => (item=/tmp/test/b)
TASK [Compare checksums from /tmp/test/a to /tmp/test/b. do something if different] ************************************************************
ok: [localhost] => (item=Comparing /tmp/test/a/file1.txt to /tmp/test/b/file1.txt) => {
"msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/file2.txt to /tmp/test/b/file2.txt)
ok: [localhost] => (item=Comparing /tmp/test/a/file3.txt to /tmp/test/b/file3.txt) => {
"msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file4.txt to /tmp/test/b/file4.txt) => {
"msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/file5.txt to /tmp/test/b/file5.txt)
ok: [localhost] => (item=Comparing /tmp/test/a/file6.txt to /tmp/test/b/file6.txt) => {
"msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file7.txt to /tmp/test/b/file7.txt) => {
"msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file8.txt to /tmp/test/b/file8.txt) => {
"msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file9.txt to /tmp/test/b/file9.txt) => {
"msg": "Files differ. Do something"
}
ok: [localhost] => (item=Comparing /tmp/test/a/file10.txt to /tmp/test/b/file10.txt) => {
"msg": "Files differ. Do something"
}
skipping: [localhost] => (item=Comparing /tmp/test/a/toto.txt to N/A)
PLAY RECAP *************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0