在Ansible中,是否有一种优雅的方式可以使用从服务器获取的md5文件检查文件完整性?

13

我有几个需要从服务器下载的文件,需要在ansible playbook中进行下载,但由于连接容易中断,所以我希望在下载后检查它们的完整性。

我考虑了两种方法:

  1. 将这些文件的MD5存储为ansible变量。
  2. 将这些文件的MD5存储为文件,并将扩展名设置为.md5。这样一对文件看起来像:file.extensionfile.extension.md5

第一种方法需要在ansible中维护MD5的开销。每次有人添加新文件时,他都需要确保将MD5放在正确位置。

但是,这种方法的优点是可以使用get_url操作中内置的checksum=md5检查解决这个问题。例如:

action: get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf checksum=md5:66dffb5228a211e61d6d7ef4a86f5758

第二种方法更为优雅,且缩小了责任范围。当有人在服务器上添加一个新文件时,他会确保同时添加 .md5 文件,甚至不需要使用ansible playbooks。

是否有一种方式可以使用 checksum 方法来匹配文件的md5值?

5个回答

22

如果您希望采用在服务器上将校验和存储在文件中的方法,您可以使用get_url校验和参数来验证它。

下载.md5文件并将其读入变量中:

- set_fact:
    md5_value: "{{ lookup('file', '/etc/myfile.md5') }}"

然后当您下载文件时,请将md5_value的内容传递给get_url:

- get_url:
    url: http://example.com
    dest: /my/dest/file
    checksum: "md5:{{ md5_value }}"
    force: true

请注意,在dest中指定文件路径是非常重要的;如果将其设置为目录(并且在url中有文件名),行为将发生显着变化。

还要注意,您可能需要使用force: true。这将导致每次运行时都会下载一个新文件。只有在下载文件时才会触发校验和。如果文件已经存在于您的主机上,它将不会验证现有文件的总和,这可能是不可取的。

为避免每次下载文件,您可以执行stat以查看文件是否已经存在,查看其总和,并根据条件设置force参数。

- stat:
    path: /my/dest/file
  register: existing_file

- set_fact:
    force_new_download: "{{ existing_file.stat.md5 != md5_value }}"
  when: existing_file.stat.exists

- get_url:
    url: http://example.com
    dest: /my/dest/file
    checksum: "md5:{{ md5_value }}"
    force:  "{{ force_new_download | default ('false') }}"

另外,如果你从某种类型的Web服务器获取这些总和/文件,则实际上可以直接从URL中获取总和值,而无需将文件下载到主机。这里是一个使用Nexus服务器作为主机托管文件及其总和的示例:

- set_fact:
    md5_value: "{{ item }}"
  with_url: http://my_nexus_server.com:8081/nexus/service/local/artifact/maven/content?g=log4j&a=log4j&v=1.2.9&r=central&e=jar.md5

可以使用这种方法替代使用get_url下载md5文件,然后使用lookup从中读取内容。


这肯定不对。文件查找插件只能在本地主机上工作,无法查找远程文件。get_url将文件存储在远程目标位置。因此,整个概念实际上是错误的。 - Wang
请至少在您的get_url任务中添加delegate_to: 127.0.0.1 - Wang
在使用 stat 时,还需要设置 checksum_algorithm,这是在 ansible.builtin 的 2.0 版本中添加的。 - Iron Bishop
最新的get_url文档中写道:“如果校验和与目标校验和不相等,则删除目标文件。”因此,在没有其他人编写该文件的情况下,可以安全地使用它而无需force: true - Petr

3
使用stat模块:
- stat:
    path: "path/to/your/file"
  register: your_file_info

- debug:
    var: your_file_info.stat.md5

1
stat.md5属性在“stat”输出中已经不存在,现在仅包含stat.checksum属性,该属性是文件的sha1sum - Jeroen Vermeulen - MageHost

2
优雅的解决方案是使用Ansible自带的以下3个模块:
  1. 使用stat模块提取md5值并将其注册到变量中。
  2. 在使用复制模块复制文件时,将md5的返回值注册到另一个变量中。
  3. 使用条件模块比较上述2个变量,并输出结果以判断文件是否正确复制。
这些模块的文档链接如下:
  • http://docs.ansible.com/ansible/stat_module.html
  • http://docs.ansible.com/ansible/copy_module.html
  • http://docs.ansible.com/ansible/playbooks_conditionals.html

  • 1

    另一种解决方案是使用 url 查找(在 ansible-2.3.1.0 上测试通过):

    - name: Download
      get_url:
        url: "http://localhost/file"
        dest: "/tmp/file"
        checksum: "md5:{{ lookup('url', 'http://localhost/file.md5') }}"
    

    0

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接