在Loongnix Server系统中使用module stream
0 环境
CPU :3A5000
操作系统 :Loongnix Server 8.4(衍生自:CentOS 8.4)
1 几个概念
1.1 模块流(module stream)
模块流的本质是一组通过modulemd文件(定义模块流规则的文件,可以类比为定义rpm规则的spec文件)定义的RPM包。
模块流通常代表一个应用程序、一个语言运行时或者一组工具的某个主要版本。例如:postgres:12
模块流:包含了PostgreSQL 12版本和PostgreSQL 12相关软件包。
1.2 模块(module)
具有相同名称的模块流的集合。例如:postgresql
模块由postgresql:10
和postgresql:12
模块流组成。
为了简化安装,模块通常定义一个或多个安装配置文件,代表一个特定的使用情况。例如,一个数据库模块中的服务器或客户端配置文件。
2 使用模块流
2.1 发现和安装模块流
2.2.1 列出软件包
在RedHat8.0版本之前的操作系统中,模块流的概念还没有引入,我们更常使用的是一个个独立的RPM包。当我们需要了解系统中或者仓库中是否存在某个RPM包时,我们可以使用dnf search NAME
、dnf list NAME
或者更复杂一点的dnf repoquery QUERY
命令来查询。
从RedHat8.0开始,操作系统中引入了模块流的概念。但是这对于查询RPM包并没有什么太多的影响。
2.2.2 列出模块
要查看系统中可用的模块,可以使用:
[loongson@bogon ~]$ dnf module list
上次元数据过期检查:0:00:07 前,执行于 2023年03月20日 星期一 23时00分36秒。
Loongnix server 8.4 - AppStream
Name Stream Profiles Summary
389-ds 1.4 [d] common [d] 389 Directory Server (base)
freeradius 3.0 [d] server [d] High-performance and highly configurable free RADIUS server
httpd 2.4 [d][e] common [d], devel, minimal Apache HTTP Server
javapackages-runtime 201801 [d][e] common [d] Basic runtime utilities to support Java applications
mariadb 10.3 [d] client, server [d] MariaDB Module
mariadb 10.4 everything [d] a very fast and robust SQL database server
maven 3.5 [d] common [d] Java project management and project comprehension tool
mercurial 4.8 [d] common [d] Mercurial -- a distributed SCM
nginx 1.14 [d] common [d] nginx webserver
......
提示:[d]默认,[e]已启用,[x]已禁用,[i]已安装
其中可以根据最后一行给出的解释信息,来查看对应流的状态。
2.2.3 安装软件包
可以通过运行 dnf install NAME
命令以通常的方式安装软件包。 任何传统的RPM包或来自已启用模块的模块化RPM包都可以通过这种方式安装。
来自其他模块流的包可以通过启用模块流,然后安装单个包,或者直接安装模块来使用。
2.2.4 启用模块
要启用一个模块流并使其软件包可供安装,请运行命令:
$ dnf module enable NAME:STREAM
例如:使能postgresql:12
模块流:
[loongson@bogon ~]$ sudo dnf module enable postgresql:12
[sudo] loongson 的密码:
上次元数据过期检查:1:35:22 前,执行于 2023年03月20日 星期一 21时32分10秒。
依赖关系解决。
=============================================================================================================================================================================
软件包 架构 版本 仓库 大小
=============================================================================================================================================================================
启用模块流:
postgresql 12
事务概要
=============================================================================================================================================================================
确定吗?[y/N]: y
完毕!
[loongson@bogon ~]$ dnf module list|grep postgresql
postgresql 9.6 client, server [d] PostgreSQL server and client module
postgresql 10 [d] client, server [d] PostgreSQL server and client module
postgresql 12 [e] client, server [d] PostgreSQL server and client module
postgresql 13 client, server [d] PostgreSQL server and client module
[loongson@bogon ~]$
可以看到postgresql:12
模块流后面状态加上了一个[e]
标志。
已经启用的模块流中的软件包,可以通过dnf install NAME
命令进行安装。
2.2.5 安装模块
要安装一个模块,请使用下列命令之一。不指定流或配置文件时,DNF会选择默认值。然而,并不是每个模块都有一个默认流或默认配置文件。在这种情况下,就需要明确指定流或配置文件 :
$ dnf module install NAME
$ dnf module install NAME:STREAM
$ dnf module install NAME/PROFILE
$ dnf module install NAME:STREAM/PROFILE
例如:安装postgresql
模块
[loongson@bogon ~]$ sudo dnf module install postgresql
[sudo] loongson 的密码:
上次元数据过期检查:1:42:24 前,执行于 2023年03月20日 星期一 21时32分10秒。
依赖关系解决。
=============================================================================================================================================================================
软件包 架构 版本 仓库 大小
=============================================================================================================================================================================
安装组/模块包:
postgresql-server loongarch64 12.7-1.0.1.module+lns8.4.0+10433+f0a9b894 appstream 5.2 M
安装依赖关系:
postgresql loongarch64 12.7-1.0.1.module+lns8.4.0+10433+f0a9b894 appstream 1.4 M
安装模块配置档案:
postgresql/server
事务概要
......
[loongson@bogon ~]$ dnf module list|grep postgresql
postgresql 9.6 client, server [d] PostgreSQL server and client module
postgresql 10 [d] client, server [d] PostgreSQL server and client module
postgresql 12 [e] client, server [d] [i] PostgreSQL server and client module
postgresql 13 client, server [d] PostgreSQL server and client module
[loongson@bogon ~]postgres --version
postgres (PostgreSQL) 12.7
2.2.6 切换模块流
注意:
1)switch-to 参数是推荐和首选的流切换方式。
2)切换流是一个有风险的操作,在软件包中可能并不总是被支持,特别是降级操作。
通过switch-to参数切换到一个与系统上安装的不同的流
$ dnf module switch-to NAME:STREAM
例如:从postgresql:12
切换到postgresql:13
:
[loongson@bogon ~]$ sudo dnf module switch-to postgresql:13
[sudo] loongson 的密码:
上次元数据过期检查:2:05:28 前,执行于 2023年03月20日 星期一 21时32分10秒。
依赖关系解决。
=====================================================================================================================
软件包 架构 版本 仓库 大小
=====================================================================================================================
升级:
postgresql loongarch64 13.3-1.0.1.module+lns8.4.0+10434+c6815fa0 appstream 1.5 M
postgresql-server loongarch64 13.3-1.0.1.module+lns8.4.0+10434+c6815fa0 appstream 5.2 M
切换模块流:
postgresql 12 -> 13
事务概要
=====================================================================================================================
升级 2 软件包
......
[loongson@bogon ~]$ dnf module list|grep postgresql
postgresql 9.6 client, server [d] PostgreSQL server and client module
postgresql 10 [d] client, server [d] PostgreSQL server and client module
postgresql 12 client, server [d] PostgreSQL server and client module
postgresql 13 [e] client, server [d] [i] PostgreSQL server and client module
[loongson@bogon ~]$
再例如:从从postgresql:13
切换到postgresql:10
:
[loongson@bogon ~]$ sudo dnf module switch-to postgresql:10
[sudo] loongson 的密码:
上次元数据过期检查:0:05:51 前,执行于 2023年03月21日 星期二 02时16分10秒。
依赖关系解决。
=====================================================================================================================
软件包 架构 版本 仓库 大小
=====================================================================================================================
降级:
postgresql loongarch64 10.17-1.0.1.module+lns8.4.0+10432+4026c932 appstream 1.4 M
postgresql-server loongarch64 10.17-1.0.1.module+lns8.4.0+10432+4026c932 appstream 4.7 M
切换模块流:
postgresql 13 -> 10
事务概要
......
[loongson@bogon ~]$ dnf module list|grep postgresql
postgresql 9.6 client, server [d] PostgreSQL server and client module
postgresql 10 [d][e] client, server [d] [i] PostgreSQL server and client module
postgresql 12 client, server [d] PostgreSQL server and client module
postgresql 13 client, server [d] PostgreSQL server and client module
毕竟postgresql
已经属于应用软件了,而且涉及到的软件包很少,所以无论从低版本到高版本还是从高版本到低版本切换,看起来都很顺利,如果是perl
、python
等涉及范围比较广的模块流,切换时可能会造成某些依赖不满足的问题。
例如:从系统中默认的perl:5.26
切换到perl:5.24
时,因为我的环境中已经安装了很多perl相关的软件,所以出现了如下问题:
[loongson@bogon ~]$ sudo dnf module switch-to perl:5.24
上次元数据过期检查:0:10:34 前,执行于 2023年03月21日 星期二 02时16分10秒。
错误:
问题 1: problem with installed package perl-DynaLoader-Functions-0.003-2.lns8.noarch
- package perl-DynaLoader-Functions-0.003-2.lns8.noarch requires perl(:MODULE_COMPAT_5.26.3), but none of the providers can be installed
- perl-libs-4:5.26.3-419.0.2.lns8.loongarch64 does not belong to a distupgrade repository
- package perl-libs-4:5.26.3-419.0.2.lns8.loongarch64 is filtered out by modular filtering
问题 2: problem with installed package perl-TermReadKey-2.37-7.lns8.loongarch64
- package perl-TermReadKey-2.37-7.lns8.loongarch64 requires libperl.so.5.26()(64bit), but none of the providers can be installed
- package perl-TermReadKey-2.37-7.lns8.loongarch64 requires perl(:MODULE_COMPAT_5.26.3)
......
这个问题的具体原因是:Loongnix Server 8.4系统中默认的perl版本为5.26,也就是其他使用perl语言实现的软件包,编译时都是基于perl:5.26版本的。perl:5.24
模块流中也只是包含了自洽的5.24版本的perl主包及其的一些运行时的依赖包。安装了perl:5.24
模块流的确是可以安装、使用perl:5.24
的功能,但是前提是系统中没有其他依赖于perl:5.26的包。
当然还可以通过加上--allowerasing
参数来允许删除依赖关系破裂的软件包,以达到切换流的结果,但是这个最好只在实验环境中使用,如下:
[huangyang@bogon ~]$ sudo dnf module switch-to perl:5.24 --allowerasing
上次元数据过期检查:2:04:51 前,执行于 2023年03月21日 星期二 12时35分13秒。
依赖关系解决。
=====================================================================================================================
软件包 架构 版本 仓库 大小
=====================================================================================================================
升级:
perl-Exporter noarch 5.72-1001.module+lns8.4.0+10501+7279654e appstream 33 k
......
移除依赖的软件包:
git loongarch64 2.27.0-1.lns8 @appstream 368 k
pacemaker-cli loongarch64 2.0.5-9.1.lns8 @appstream 1.0 M
pcs loongarch64 0.10.8-1.lns8 @local 22 M
perl-Error noarch 1:0.17025-2.lns8 @appstream 70 k
perl-Git noarch 2.27.0-1.lns8 @appstream 63 k
perl-TermReadKey loongarch64 2.37-7.lns8 @appstream 76 k
perl-TimeDate noarch 1:2.30-15.module+lns8.4.0+10530+61ba1e5e @appstream 94 k
rpkg noarch 2.10-1.lns8 @@commandline 156 k
rpkg-macros noarch 1.1-1.lns8 @epel 60 k
降级:
perl-Carp noarch 1.40-367.module+lns8.4.0+10501+7279654e appstream 28 k
perl-Data-Dumper loongarch64 2.161-5.module+lns8.4.0+10501+7279654e appstream 54 k
perl-Encode loongarch64 4:2.88-7.module+lns8.4.0+10501+7279654e appstream 1.4 M
......
切换模块流:
perl 5.26 -> 5.24
事务概要
=====================================================================================================================
安装 11 软件包
升级 13 软件包
移除 9 软件包
降级 32 软件包
......
switch-to
参数包含多个操作,需要执行这些操作才能安全地切换到另一个模块流。
在此示例中,我们展示了从postgresql:13
到postgresql:10
的手动切换,而无需运行switch-to
参数:
1)先卸载了系统中安装的postgresql包
[huangyang@bogon ~]$ sudo dnf module list|grep postgresql
postgresql 9.6 client, server [d] PostgreSQL server and client module
postgresql 10 [d] client, server [d] PostgreSQL server and client module
postgresql 12 client, server [d] PostgreSQL server and client module
postgresql 13 [e] client, server [d] [i] PostgreSQL server and client module
[huangyang@bogon ~]$ sudo dnf remove postgresql
依赖关系解决。
......
2)然后reset
postgresql
模块,重置之后,一切又回到了开始的模样。
[huangyang@bogon ~]$ sudo dnf module reset postgresql
上次元数据过期检查:2:10:04 前,执行于 2023年03月21日 星期二 12时35分13秒。
依赖关系解决。
=====================================================================================================================
软件包 架构 版本 仓库 大小
=====================================================================================================================
禁用模块配置档案:
postgresql/server
重置模块:
postgresq
......
3)使能postgresql:10
模块流
[huangyang@bogon ~]$ sudo dnf module enable postgresql:10
上次元数据过期检查:2:19:49 前,执行于 2023年03月21日 星期二 12时35分13秒。
依赖关系解决。
=============================================================================================================================================================================
软件包 架构 版本 仓库 大小
=============================================================================================================================================================================
启用模块流:
postgresql 10
事务概要
=============================================================================================================================================================================
确定吗?[y/N]: y
完毕!
4)安装postgresql:10
模块流
[huangyang@bogon ~]$ sudo dnf module install postgresql:10
上次元数据过期检查:2:20:31 前,执行于 2023年03月21日 星期二 12时35分13秒。
依赖关系解决。
=============================================================================================================================================================================
软件包 架构 版本 仓库 大小
=============================================================================================================================================================================
安装组/模块包:
postgresql-server loongarch64 10.17-1.0.1.module+lns8.4.0+10432+4026c932 appstream 4.7 M
安装依赖关系:
postgresql loongarch64 10.17-1.0.1.module+lns8.4.0+10432+4026c932
2.2.7 查看模块流信息
使用dnf module info NAME:STREAM
命令查看模块流信息
例如:
[huangyang@bogon ~]$ sudo dnf module info perl:5.24
上次元数据过期检查:2:22:37 前,执行于 2023年03月21日 星期二 12时35分13秒。
Name : perl
Stream : 5.24
Version : 8040020211122094452
Context : 3d27a66e
Architecture : loongarch64
Profiles : common [d], minimal
Default profiles : common
Repo : appstream
Summary : Practical Extraction and Report Language
Description : Perl is a high-level programming language with roots in C, sed, awk and shell scripting. Perl is good at handling processes and files, and is especially good at handling text. Perl's hallmarks are practicality and efficiency. While it is used to do a lot of different things, Perl's most common applications are system administration utilities and web programming.
Requires : platform:[lns8]
Artifacts : perl-4:5.24.4-404.0.1.module+lns8.4.0+10501+7279654e.loongarch64
: perl-4:5.24.4-404.0.1.module+lns8.4.0+10501+7279654e.src
: perl-Algorithm-Diff-0:1.1903-10.module+lns8.4.0+10501+7279654e.noarch
: perl-Algorithm-Diff-0:1.1903-10.module+lns8.4.0+10501+7279654e.src
: perl-Archive-Tar-0:2.30-2.module+lns8.4.0+10501+7279654e.noarch
: perl-Archive-Tar-0:2.30-2.module+lns8.4.0+10501+7279654e.src
......
基本上就是模块流编译完成后生成的modulemd文件内容。
2.2 更新系统
通过运行 dnf update
命令更新系统会导致所有包升级到其模块流提供的最新版本。
2.3 卸载模块
一般来说,要删除安装在系统上的模块,使用以下命令:
$ dnf module remove MODULE:STREAM/PROFILE
3 高级部分
有一种情况是先安装一个特定的软件包,然后再安装一个模块。例如:
$ dnf install ruby
$ dnf module install ruby:2.6/default
在这种情况下,运行dnf module remove
命令不会删除 ruby 包,因为 DNF 会记住该包已明确安装。
要使 ruby 包通过 dnf module remove 命令卸载,请运行以下命令:
$ dnf mark group ruby
$ dnf module remove ruby:2.6/default
这是因为 DNF 会记住一个软件包被安装的原因。一共有三个,从最强排序:
- usr
- group
- dependency
因为模块使用的group 比dnf install
命令使用的usr权限弱,所以在运行dnf module remove
命令后,包仍然留在系统上。 然而,将其“降级”为group,也会使dnf module
删除。
4 模块化过滤和冲突
本章内容翻译自:https://docs.fedoraproject.org/en-US/modularity/using-modules/#_modular_filtering_and_conflicts
关于冲突在上面已经略有提及,在此继续讨论。
当使用模块流时,会执行很多操作。 模块流包含替代的模块化 RPM 包,这些包可以与已经存在的非模块化 RPM 包同名,可能会出现很多冲突。 在接下来的几个示例中,我们将向您展示一些冲突。
4.1 切换模块流而不从旧模块流中删除 RPM 包
示例 1. 在不删除已安装内容的情况下切换模块流时破坏依赖关系
[root@5e7d134a8883 /]# dnf module install nodejs:14/common
Last metadata expiration check: 0:02:38 ago on Thu Mar 3 08:57:00 2022.
Dependencies resolved.
Problem 1: cannot install the best candidate for the job
- nothing provides /usr/bin/pwsh needed by nodejs-1:14.19.0-2.module_f35+13766+ad18d3e5.x86_64
Problem 2: package npm-1:6.14.16-1.14.19.0.2.module_f35+13766+ad18d3e5.x86_64 requires nodejs = 1:14.19.0-2.module_f35+13766+ad18d3e5, but none of the providers can be installed
- cannot install the best candidate for the job
- nothing provides /usr/bin/pwsh needed by nodejs-1:14.19.0-2.module_f35+13766+ad18d3e5.x86_64
===========================================================================================================================================================================
Package Architecture Version Repository Size
===========================================================================================================================================================================
Upgrading:
nodejs x86_64 1:14.17.2-2.module_f35+12348+fe4be0bd fedora-modular 93 k
nodejs-docs noarch 1:14.17.2-2.module_f35+12348+fe4be0bd fedora-modular 6.0 M
nodejs-full-i18n x86_64 1:14.17.2-2.module_f35+12348+fe4be0bd fedora-modular 7.8 M
nodejs-libs x86_64 1:14.17.2-2.module_f35+12348+fe4be0bd fedora-modular 13 M
Downgrading:
npm x86_64 1:6.14.13-1.14.17.2.2.module_f35+12348+fe4be0bd fedora-modular 3.3 M
Installing module profiles:
nodejs/common
Skipping packages with broken dependencies:
nodejs x86_64 1:14.19.0-2.module_f35+13766+ad18d3e5 updates-modular 199 k
npm x86_64 1:6.14.16-1.14.19.0.2.module_f35+13766+ad18d3e5 updates-modular 3.3 M
Transaction Summary
===========================================================================================================================================================================
Upgrade 4 Packages
Downgrade 1 Package
Skip 2 Packages
Total download size: 30 M
Is this ok [y/N]:
在这种情况下,我们在 Fedora 35 上启用并安装了nodejs:12
模块流。然后我们重置12
流并启用14
流。 之后我们要安装nodejs:14
模块流。
首先 DNF正在尝试升级或降级现有已安装的软件。 它不会在执行reset
参数期间删除现有软件。reset
只会禁用模块的已启用流。 模块流中 RPM 文件的 NEVRA 可以与安装的软件(新的或旧的)有不同的版本,也可以与同一模块的其他流有不同的版本。 来自不同模块流的 RPM 包之间的运行时依赖关系可能不同。
这个冲突是正确的,不是错误。 当你尝试使用 14 流中的 RPM 包更新 12 流中已安装的 RPM 包时。 来自同一模块的模块流是互斥的,一次只能启用和安装一个流。
如果你正在切换流并且不确定手动过程,请使用 switch-to
参数,因为这是推荐的方式。
4.2 从错误的模块流安装 RPM 包
示例 2. 请求从错误的模块流安装的 RPM 包
[root@bdaeaab947e6 /]# dnf module enable perl:5.30
Fedora 35 - x86_64 6.8 MB/s | 79 MB 00:11
Fedora 35 openh264 (From Cisco) - x86_64 3.1 kB/s | 2.5 kB 00:00
Fedora Modular 35 - x86_64 2.8 MB/s | 3.3 MB 00:01
Fedora 35 - x86_64 - Updates 7.3 MB/s | 27 MB 00:03
Fedora Modular 35 - x86_64 - Updates 2.3 MB/s | 2.8 MB 00:01
Dependencies resolved.
===========================================================================================================================================================================
Package Architecture Version Repository Size
===========================================================================================================================================================================
Enabling module streams:
perl 5.30
Transaction Summary
===========================================================================================================================================================================
Is this ok [y/N]: y
Complete!
[root@bdaeaab947e6 /]# dnf install perl-Tie-RefHash
Last metadata expiration check: 0:00:22 ago on Thu Mar 3 09:41:23 2022.
Error:
Problem: package perl-Tie-RefHash-1.40-478.fc35.noarch requires perl(:MODULE_COMPAT_5.34.0), but none of the providers can be installed
- conflicting requests
- package perl-libs-4:5.34.0-481.fc35.i686 is filtered out by modular filtering
- package perl-libs-4:5.34.0-481.fc35.x86_64 is filtered out by modular filtering
- package perl-libs-4:5.34.0-482.fc35.i686 is filtered out by modular filtering
- package perl-libs-4:5.34.0-482.fc35.x86_64 is filtered out by modular filtering
(try to add '--skip-broken' to skip uninstallable packages)
[root@bdaeaab947e6 /]#
该示例描述了当尝试安装不是已启用perl:5.30
模块流提供的RPM包时的情况。 我们首先启用perl:5.30
模块流。 之后我们尝试安装包perl-Tie-RefHash
。 DNF 包管理器试图告诉你无法安装perl-Tie-RefHash
,因为它不是由任何已启用的模块流提供的。 模块化过滤将自动过滤掉所有不是由已启用模块流提供的 RPM 包。
要解决这个冲突,你必须启用正确的模块流。在我们的例子中,它是perl:5.32
模块流。
4.3 安装一个RPM包而不启用提供该包的模块流。
例子3.在没有启用正确的模块流的情况下安装一个包,会出现安装冲突
[root@bdaeaab947e6 /]# dnf install perl-DBI
Last metadata expiration check: 3:13:30 ago on Thu Mar 3 09:41:23 2022.
Error:
Problem: package perl-DBI-1.643-10.fc35.x86_64 requires libperl.so.5.34()(64bit), but none of the providers can be installed
- conflicting requests
- package perl-libs-4:5.34.0-481.fc35.x86_64 is filtered out by modular filtering
- package perl-libs-4:5.34.0-482.fc35.x86_64 is filtered out by modular filtering
(try to add '--skip-broken' to skip uninstallable packages)
[root@bdaeaab947e6 /]# dnf module enable perl-DBI
Last metadata expiration check: 3:14:38 ago on Thu Mar 3 09:41:23 2022.
Dependencies resolved.
===========================================================================================================================================================================
Package Architecture Version Repository Size
===========================================================================================================================================================================
Enabling module streams:
perl-DBI 1.643
Transaction Summary
===========================================================================================================================================================================
Is this ok [y/N]: y
Complete!
[root@bdaeaab947e6 /]# dnf install perl-DBI
Last metadata expiration check: 3:14:46 ago on Thu Mar 3 09:41:23 2022.
Dependencies resolved.
===========================================================================================================================================================================
Package Architecture Version Repository Size
===========================================================================================================================================================================
Installing:
perl-DBI x86_64 1.643-7.module_f35+12493+425c54a8 fedora-modular 700 k
Transaction Summary
===========================================================================================================================================================================
Install 1 Package
Total download size: 700 k
Installed size: 1.9 M
Is this ok [y/N]:
在这个例子中,我们试图安装perl-DBI
包。在我们的系统中,我们之前已经启用并安装了perl:5.32
模块流。冲突告诉我们,我们正试图安装非模块化的perl-DBI
,它依赖于非模块化的perl,但由于模块化过滤,非模块化的perl包不可用。唯一可以进行依赖性解析的RPM包是来自5.32流的RPM包。
警告:非模块化的RPM包不能依赖模块化的内容。如果你的非模块化包需要一个模块化的依赖,请将你的内容模块化。
为了解决这个问题,我们需要启用perl-DBI:1.643
模块流。当启用perl-DBI:1.643
时,我们就满足了per 模块的模块化依赖性。非模块化的perl-DBI
RPM包现在被模块化过滤了,它在依赖关系解析和内容集创建中不被考虑。
5 参考内容
1)https://docs.fedoraproject.org/en-US/modularity/using-modules/
2)https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/installing_managing_and_removing_user-space_components/introduction-to-modules_using-appstream