如何用Ansible的get_url模块幂等性下载并更新二进制文件?
问题
我想用Ansible的get_url模块幂等性地下载二进制文件,编写的Playbook如下:
- name: calculate hash for existing file stat: path: /usr/bin/yq checksum_algorithm: sha256 register: resultStat - name: (re)download file become: true get_url: url: https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64 #url: https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 dest: /usr/bin/yq checksum: "{{ '' if not resultStat.stat.exists else 'sha256:' + resultStat.stat.checksum }}" #force: true owner: root group: root mode: '0755'
首次运行及重复运行时均正常,具备幂等性。但将下载链接切换为指向latest版本的链接后,期望旧文件被删除并下载新版本。根据Ansible官方文档描述:
若传递checksum参数且目标位置存在文件,会计算目标文件的校验和;若与传入的checksum一致则跳过下载(除非force为true);若不一致则删除目标文件。
实际测试中,添加force: true时旧文件会被删除,但随后报错“The checksum for /usr/bin/yq did not match ...”;不添加force: true时,文件完全不会更新。请问该如何解决此问题?
解决方案
问题核心在于:使用latest版本链接时,你传递的checksum是本地旧文件的哈希值,而下载的新版本文件哈希必然和旧文件不一致,导致校验失败。要实现自动更新到latest版本并保持幂等性,需获取最新版本对应的官方校验值,再用该值进行下载校验。
方法1:动态获取最新版本的校验和(推荐)
修改Playbook,先从GitHub官方接口获取yq最新版本的sha256校验值,再传递给get_url模块:
- name: Get latest yq release info uri: url: https://api.github.com/repos/mikefarah/yq/releases/latest return_content: true register: yq_latest_release - name: Extract yq_linux_amd64 sha256 checksum set_fact: yq_checksum: "{{ yq_latest_release.json.body | regex_search('yq_linux_amd64.sha256: (\\w+)', '\\1') | first }}" - name: Download or update yq to latest version become: true get_url: url: https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 dest: /usr/bin/yq checksum: "sha256:{{ yq_checksum }}" owner: root group: root mode: '0755'
逻辑说明:
- 通过GitHub API获取最新release的详情,其中包含各平台文件的校验和
- 提取对应架构文件的sha256值
- 用官方校验值执行下载,只有当本地文件与最新版本校验值不一致时,才会重新下载,完全符合幂等性要求
方法2:跳过本地校验,依赖HTTP标识(不推荐)
如果不想动态获取校验和,可以设置force: true并移除checksum参数,让get_url依赖HTTP的ETag或文件大小判断是否更新:
- name: (re)download latest yq become: true get_url: url: https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 dest: /usr/bin/yq force: true owner: root group: root mode: '0755'
这种方法可靠性较低,因为ETag或文件大小可能不会随版本更新而变化,导致无法正确触发更新。
原方法失效原因
- 不加
force: true时:get_url发现本地文件哈希与你传递的旧哈希一致,直接跳过下载,不会检查远程文件是否更新 - 加
force: true时:虽然会删除旧文件并下载新文件,但下载完成后会用旧文件的哈希校验新文件,自然不匹配而报错
内容的提问来源于stack exchange,提问作者lonix
相关产品推荐
相关产品推荐

