Salt 的 pkgutil 执行模块:基于 OpenCSW 管理 Solaris 软件包全指南
2026/9/23 14:03:20 网站建设 项目流程

Salt 的 pkgutil 执行模块:基于 OpenCSW 管理 Solaris 软件包全指南

【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt

导读

本文深入讲解 Salt 中面向 Solaris 操作系统的pkgutil执行模块(salt/modules/pkgutil.py)。该模块是 Salt 虚拟pkg模块在 Solaris + OpenCSW 场景下的具体实现,通过调用 OpenCSW 的pkgutil(1)与系统自带的pkginfo(1)完成软件包的刷新、查询、安装、升级与卸载。读完本文,你将掌握pkgutil模块的加载条件、全部函数与参数、底层命令映射关系、返回值结构,并能直接在 Salt 命令行与 SLS 状态文件中正确使用它管理 Solaris 上的软件包。

模块定位:pkg 虚拟模块的 Solaris Provider

Salt 的包管理入口是一个名为pkg虚拟模块:用户在命令行或状态文件中写pkg.installpkg.latest时,Salt 的加载器会根据目标系统的特性自动选择真正干活的执行模块。doc/ref/modules/all/salt.modules.pkg.rst 中明确列出,pkg虚拟模块由以下模块之一提供,其中:

:py:mod:`~salt.modules.pkgutil` Solaris-based OSes using OpenCSW's ``pkgutil(1)``

也就是说,当被管理的主机是基于 Solaris 且使用 OpenCSW 的软件仓库时,pkg.xxx系列命令实际由pkgutil模块承接。同属 Solaris 阵营的还有使用pkgadd(1M)solarispkg模块、使用 IPSpkg(1)solarisipspkg模块——三者分工不同,选择依据是目标主机采用的包工具。

加载条件与虚拟名

pkgutil模块定义了虚拟名__virtualname__ = "pkgutil",并通过__virtual__()决定是否加载(salt/modules/pkgutil.py):

def __virtual__(): """ Set the virtual pkg module if the os is Solaris """ if __grains__["os_family"] == "Solaris": return __virtualname__ return ( False, "The pkgutil execution module cannot be loaded: " "only available on Solaris systems.", )

关键点:

  • 判断依据是 grainos_family == "Solaris"与具体 Solaris 版本无关(Solaris 10、11 及 OpenSolaris 衍生系统均适用)。
  • 当不满足条件时返回(False, "错误说明"),模块不会加载,此时执行pkg.install会得到类似'pkg.install' is not available的错误。
  • 模块 docstring 特别提醒:如果 Salt 没有选择本模块而用了其他模块(或报出上述错误),可以参考 Salt 文档中的module-provider-override(模块提供者覆盖)机制,在 minion 配置中用providers强制指定pkgpkgutil提供。

底层命令依赖

该模块不自行实现包仓库逻辑,而是封装了 OpenCSW 环境下的两个外部命令:

命令用途模块内使用点
/opt/csw/bin/pkgutilOpenCSW 包管理工具,负责刷新仓库、查询可用/可升级包、安装与升级refresh_dbupgrade_availablelist_upgradesupgradelatest_versioninstallremove
/usr/bin/pkginfoSolaris 系统自带命令,用于枚举当前已安装的包list_pkgs

模块源码对每个函数都给出了对应的底层命令与参数(如pkgutil -Upkgutil -A --parsepkgutil -yupkgutil -yr),使用该模块前应确认目标主机已安装 OpenCSW 且/opt/csw/bin下存在pkgutil

仓库数据刷新:refresh_db

salt '*' pkgutil.refresh_db

refresh_db 执行/opt/csw/bin/pkgutil -U更新 OpenCSW 仓库数据库,返回布尔值表示是否成功:

def refresh_db(): salt.utils.pkg.clear_rtag(__opts__) return __salt__"cmd.retcode" == 0

两个实现细节值得注意:

  1. 通过cmd.retcode判断退出码是否为 0 来确定成功与否;
  2. 调用salt.utils.pkg.clear_rtag(__opts__)清除 Salt 内部的 rtag 标记文件。这是 Salt 包管理体系的通用机制:rtag 用于记录"最近一次刷新"的时间戳,避免在同一个 state 运行中多个 state 反复触发仓库刷新。手动调用refresh_db前清除 rtag,保证后续pkgstate 中refresh: True的语义仍然成立。在 tests/pytests/unit/modules/test_pkgutil.py 中,test_refresh_db同时 mock 了cmd.retcodeclear_rtag来验证这一行为。

已安装包清单:list_pkgs 与 version

list_pkgs

salt '*' pkg.list_pkgs salt '*' pkg.list_pkgs versions_as_list=True

list_pkgs 返回{'<package_name>': '<version>'}形式的字典。其数据来源是系统命令/usr/bin/pkginfo -x,源码中对此有精妙的解析逻辑(salt/modules/pkgutil.py):

# Package information returned two lines per package. On even-offset # lines, the package name is in the first column. On odd-offset lines, the # package version is in the second column. lines = __salt__"cmd.run".splitlines() for index, line in enumerate(lines): if index % 2 == 0: name = line.split()[0].strip() if index % 2 == 1: version_num = line.split()[1].strip() __salt__"pkg_resource.add_pkg"

也就是说,pkginfo -x每个包输出两行(偶数行包名、奇数行版本号),模块按行号奇偶配对解析。解析结果通过pkg_resource.add_pkg汇总、pkg_resource.sort_pkglist排序,并深拷贝写入__context__["pkg.list_pkgs"]缓存。

其他行为:

  • versions_as_list=True时,返回的每个包版本以列表形式呈现(兼容同版本多实例场景);
  • removed=True参数在当前实现中直接返回{}(源码注释注明 "removed not yet implemented or not applicable");
  • use_context参数控制是否优先读取上下文缓存,配合_list_pkgs_from_context(salt/modules/pkgutil.py)避免在同一进程内重复执行pkginfo命令——测试 test_list_pkgs_no_context 专门验证了use_context=False时不会调用上下文读取逻辑。

version

salt '*' pkgutil.version CSWpython

version 直接委托给pkg_resource.version,返回已安装包的版本字符串;未安装则返回空字符串。

版本查询:latest_version 与 upgrade_available

latest_version

salt '*' pkgutil.latest_version CSWpython salt '*' pkgutil.latest_version <package1> <package2> <package3> ...

latest_version 返回指定包当前可安装/可升级的最新版本:

  • 支持一次传入多个包名,返回{name: version}字典;只传一个包名时直接返回字符串;
  • 若包已是最新版本,对应返回空字符串;
  • refresh=True(默认)时先调用refresh_db()
  • 底层命令为/opt/csw/bin/pkgutil -a --parse <names>,并对每行输出做健壮性处理(ValueError时跳过);
  • 版本比较使用salt.utils.versions.compare(ver1=cver, oper="<", ver2=nver),仅当已装版本低于可用版本时才返回新版本,且比较前会去掉version_rev中的修订号(split(",")[0])。

模块同时提供了一个被标记为废弃的别名:

# available_version is being deprecated available_version = salt.utils.functools.alias_function( latest_version, "available_version" )

(salt/modules/pkgutil.py)。新代码应使用latest_version。也正因如此,API 文档salt.modules.pkgutil.rst通过:exclude-members: available_version排除了该成员的自动文档生成。

upgrade_available

salt '*' pkgutil.upgrade_available CSWpython

upgrade_available 是轻量级的"是否有升级"检查,执行pkgutil -c --parse --single <name>,取输出第三列(out.split()[2]):

  • 若为SAME或命令无输出,返回空字符串(无可升级);
  • 否则返回可用版本号。

单元测试 test_upgrade_available 覆盖了SAME、可升级、无输出三种分支。

升级管理:list_upgrades 与 upgrade

list_upgrades

salt '*' pkgutil.list_upgrades

list_upgrades 列出系统上所有可升级的包:

  • 默认refresh=True,先刷新仓库;
  • 执行/opt/csw/bin/pkgutil -A --parse,逐行按\t切分;
  • 跳过状态为SAME(已最新)与not installed(未安装)的行,其余记入upgrades[包名] = 版本
  • 返回形如{'<pkg>': '<version>'}的字典。

upgrade

salt '*' pkgutil.upgrade

upgrade 升级系统上全部软件包:

  1. 默认先refresh_db()
  2. 调用list_pkgs()记录升级前的包清单old
  3. 执行/opt/csw/bin/pkgutil -yu完成全量升级;
  4. 弹出__context__中的pkg.list_pkgs缓存,重新调用list_pkgs()得到new
  5. 通过salt.utils.data.compare_dicts(old, new)返回变更字典,结构为:
{'<package>': {'old': '<old-version>', 'new': '<new-version>'}}

注意第 4 步的"弹缓存再重查"是模块内所有变更类操作(upgradeinstallremove)的统一模式,确保返回值反映的是真实变更而非过期缓存。

安装:install

salt '*' pkg.install <package_name> salt '*' pkg.install SMClgcc346

install 使用pkgutil工具安装软件包,参数如下:

参数说明
name要安装的包名
refresh是否先刷新仓库,默认False
version指定安装版本(与pkgs二选一使用)
pkgs批量安装列表,必须是 Python 列表,可混入{"name": "version"}形式的版本约束;传入时name会被忽略

批量安装示例:

salt '*' pkg.install pkgs='["foo", "bar"]' salt '*' pkg.install pkgs='["foo", {"bar": "1.2.3"}]'

执行流程(源码级):

  1. refresh=True时先refresh_db()
  2. 调用pkg_resource.parse_targets(name, pkgs, **kwargs)解析安装目标,MinionError会被包装为CommandExecutionError抛出;解析为空则直接返回{}
  3. pkgsNone且指定了version且只有单个目标,则把版本并入目标({name: version});
  4. 对每个目标拼接目标串:无版本时直接是包名,有版本时格式为pkgname-version
  5. 执行/opt/csw/bin/pkgutil -yu <targets...>
  6. 弹缓存、重新list_pkgs()compare_dicts(old, new)返回变更。

源码注释中 "Ignore 'sources' argument" 表明sources等多余参数会被parse_targets忽略。

卸载:remove 与 purge

salt '*' pkg.remove <package name> salt '*' pkg.remove <package1>,<package2>,<package3> salt '*' pkg.remove pkgs='["foo", "bar"]'

remove 卸载包及其不再被其他包使用的依赖:

  • name为要删除的包名;pkgs为批量删除列表,传入时name被忽略(pkgs选项自版本 0.16.0 起可用);
  • list_pkgs()得到old,只对当前确实已安装的目标(x in old)执行/opt/csw/bin/pkgutil -yr <targets...>;没有已安装目标时直接返回{}
  • 同样走"弹缓存→重查→compare_dicts"流程返回变更字典。

purge 与remove完全相同——Solaris 的pkgutil不区分卸载与清除,因此purge只是remove的别名式转发(return remove(name=name, pkgs=pkgs)),二者参数与返回结构一致。

与 Salt pkg 状态模块的联动

pkgutil模块不只用于命令行,它还作为底层支撑服务于pkg状态模块(salt/states/pkg.py)。状态模块在运行时通过__salt__["pkg.latest_version"](如 salt/states/pkg.py、salt/states/pkg.py)与__salt__["pkg.list_upgrades"](如 salt/states/pkg.py)与执行模块协作——这些调用在 Solaris 主机上即落到pkgutillatest_version/list_upgrades

因此,在 SLS 状态文件中可以这样声明式地管理 OpenCSW 包:

install_opencsw_python: pkg.installed: - name: CSWpython upgrade_all: pkg.uptodate: - refresh: True

pkg.uptodate会在目标主机上调用pkg.list_upgrades后执行升级,与命令行salt '*' pkgutil.upgrade语义一致。

注意事项与边界

  1. 平台限制pkgutil模块仅在os_family == Solaris的主机上加载,且依赖 OpenCSW 提供的/opt/csw/bin/pkgutil;若使用 Solaris 原生pkgadd或 IPS,则应分别选择solarispkg/solarisipspkg模块。
  2. 返回格式:所有变更类函数统一返回{'<pkg>': {'old': ..., 'new': ...}},便于状态模块做变更判断。
  3. 缓存一致性:模块通过__context__["pkg.list_pkgs"]缓存已装包清单以提升性能,所有修改类操作都会主动弹出该缓存,保证查询结果始终准确。
  4. purge语义purgeremove等价,不要期望它会额外删除配置文件。
  5. 废弃别名available_version已被标记为废弃,应统一使用latest_version
  6. 版本比较latest_version会剔除修订号再做大小比较,避免因1.0,REV=2016之类的修订后缀影响结果。

参考实现与测试

  • 模块实现:salt/modules/pkgutil.py
  • 单元测试(覆盖全部函数):tests/pytests/unit/modules/test_pkgutil.py
  • 虚拟模块pkg的 provider 说明:doc/ref/modules/all/salt.modules.pkg.rst
  • 状态层联动:salt/states/pkg.py
  • API 文档源文件:doc/ref/modules/all/salt.modules.pkgutil.rst

对每个函数(refresh_dbupgrade_availablelist_upgradesupgradelist_pkgsversionlatest_versioninstallremovepurge),单元测试中都有一一对应的测试用例,可作为理解边界行为与返回值约定的最直接参考。

【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询