有没有一种优雅的方法可以使用从服务器获取的 md5 文件在 ansible 中使用 md5 检查文件完整性?

Is there an elegant way to check file integrity with md5 in ansible using md5 files fetched from server?

我的服务器上有几个文件需要从 ansible playbook 下载,但由于连接很可能会中断,我想在下载后检查它们的完整性。

我正在考虑两种方法:

  1. 将这些文件的 md5 作为 vars 存储在 ansible 中
  2. 将这些文件的 md5 作为扩展名为 .md5 的文件存储在服务器上。这样的一对看起来像:file.extensionfile.extension.md5.

first 方法引入了在 ansible 中维护 md5 的开销。所以每次有人添加新文件时,他都需要确保在正确的位置添加了 md5。

但作为一个优势,有一个解决方案,使用 get_url 操作中的内置检查与 checksum=md5 结合使用。例如:

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

second 方法更优雅并且缩小了责任范围。当有人在服务器上添加新文件时,他将确保也添加 .md5,甚至不需要使用 ansible 剧本。

有没有办法使用 checksum 方法来匹配文件中的 md5?

优雅的解决方案将使用ansible本身提供的以下3个模块

  1. http://docs.ansible.com/ansible/stat_module.html

    使用stat模块提取md5值并注册到变量中

  2. http://docs.ansible.com/ansible/copy_module.html

    在使用复制模块从服务器复制文件时,将md5的return值注册到另一个变量

  3. http://docs.ansible.com/ansible/playbooks_conditionals.html

    使用这个条件模块比较上面的2个变量并打印结果文件是否被正确复制

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

下载 .md5 文件并将其读入 var:

- 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') }}"

此外,如果您从某种网络服务器中提取 sums/artifacts,您实际上可以直接从 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 文件,然后使用查找从中读取。

使用统计模块:

- stat:
    path: "path/to/your/file"
  register: your_file_info

- debug:
    var: your_file_info.stat.md5

另一种解决方案是使用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') }}"

https://pypi.org/project/checksumdir

的帮助下编写了一个ansible模块

可以找到模块here

示例:

- get_checksum: 
    path: path/to/directory
    checksum_type: sha1/md5/sha256/sha512
  register: checksum