Ansible获取DNF最新更新列表时如何仅保留每个软件包的最新版本
Ansible获取DNF最新更新列表时如何仅保留每个软件包的最新版本
我来帮你搞定这个问题!你现在遇到的情况是,用dnf: list=updates返回的结果里包含了同一个软件包的多个更新版本(比如vlc有1和2两个release版本),而你只想要每个包的最新可用版本对吧?
先说说原代码的问题:原任务只是把packages.results里的所有条目都遍历拼接,没有做去重和版本筛选,所以才会出现同一个包的多个版本。
下面是修改后的解决方案,核心思路是按包名分组,然后对每组内的版本进行排序,取最新的那个:
tasks: - name: List Available Patches (Non-Kernel) dnf: list: updates update_cache: true register: packages - name: Filter to keep only the latest version per package set_fact: latest_packages: >- {%- set pkg_groups = packages.results | groupby('name') -%} {%- set latest_list = [] -%} {%- for pkg_name, pkg_entries in pkg_groups -%} # 先按版本号倒序,再按release倒序,确保取到最新的版本 {%- set sorted_entries = pkg_entries | sort(attribute='version', reverse=true) | sort(attribute='release', reverse=true) -%} {%- set latest_entry = sorted_entries[0] -%} {{ latest_list.append(latest_entry.name ~ '-' ~ latest_entry.version ~ '-' ~ latest_entry.release) }} {%- endfor -%} {{ latest_list }} - debug: msg: "{{ latest_packages }}"
代码解释:
- 分组:用
groupby('name')把所有更新包按软件包名称分组,这样同一个包的不同版本会被归到同一组里; - 排序:对每个分组内的包条目,先按
version倒序排序,再按release倒序排序——因为RPM包的版本优先级里,release号也是重要的判断依据(比如3.0.18-2.el7.3就比3.0.18-1.el7.3新); - 取最新版本:排序后的第一个条目就是该包的最新版本,把它的名称、版本、release拼接成字符串加入结果列表。
特殊情况处理:
如果你的系统里有版本号带字母的包(比如1.0.0a vs 1.0.0b),默认的字符串排序可能不准确,这时候可以用Ansible的version_compare过滤器来做更专业的版本比对,修改排序部分的代码:
{%- set sorted_entries = pkg_entries | sort(reverse=true, key=lambda x: x.version ~ '-' ~ x.release, cmp=lambda a,b: version_compare(a, b)) -%}
这样就能更精准地处理复杂版本号的排序了。
用这个方案处理你给出的示例数据,最终会得到如下结果:
[ "vlc-3.0.18-2.el7.3", "vlc-core-3.0.18-2.el7.3", "xdg-desktop-portal-1.8.0-3.el7", "xorg-x11-server-Xorg-1.20.14-6.el7.3" ]
完全符合你只保留每个包最新版本的需求!
备注:内容来源于stack exchange,提问作者rk3dnp
相关产品推荐
相关产品推荐

