FreeBSD pkg 命令概述
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
原文:
作者:重村法克
2025-02-09
由于 FreeBSD 中针对第三方工具引入的机制(Ports 和 Packages)的完善,二进制包的使用得到了发展。尤其是引入了 Flavors(版本)功能的好处尤为显著,尽管安装的内容是相同的,但由于依赖的包版本不同,组合的复杂性也随之增加。然而,只要为这些依赖包的所有版本提供相应的包,那么包管理就变得非常简单了。虽然我们希望所有的依赖包都能提供完整的包,但依然能够感受到二进制包带来的便利。
在这里,为了能够更好地利用二进制包,我总结了一些常用的命令。虽然详细的选项讲解会非常繁琐,但我只会列出常用的选项。此外,大多数命令在执行时都会询问是否继续。因此,几乎所有命令都可以使用 -y
选项来避免这一提示,我将在这里省略这一部分的详细描述。当你熟悉之后,可以自如使用。除此之外,我也没有列举太多实际操作的案例。如果你有任何疑问,欢迎告知,我会补充相关内容。
在这里,我会在命令名称(或子命令名称)后标注 [R]
和 [L]
,它们的含义如下:
[R]
:参考外部包/仓库中的信息。
[L]
:参考已安装的包或本地文件系统中的包。
[RL]
:根据环境的不同,既可以是 [R]
也可以是 [L]
。
这是用来收集包元数据的命令。首先需要收集元数据,其他命令的执行依赖于此。这与 yum check-update
很相似。
需要注意的是,这并不是一个每次都需要执行的命令,许多命令会在自动更新元数据后再执行,因此如果你不介意自动更新,便不需要手动执行该命令。以下子命令会基于最新的元数据执行:
pkg install
pkg upgrade
pkg version
pkg search
pkg fetch
pkg rquery
用于安装软件包。与后面提到的 pkg add
不同,pkg install
是通过关键词指定并从网络获取包来安装。
用于安装指定的包文件。与 pkg install
不同,pkg add
是明确指定包文件名并进行安装。
删除指定的软件包。
使用 -a
选项删除所有包,-f
选项强制执行删除,并且 -y
选项使得操作不进行任何询问。直观上,指定 -ay
就足够了,但是在因依赖关系无法删除某些包时,必须指定 -f
选项。如果你打算删除所有包,毫不犹豫地全部指定就好。
用于进行包的版本比较。由于其特殊性,使用时需要分解具体的用例来理解。
默认情况下,pkg version
会与 /usr/ports/INDEX-OS major version
这样的元数据文件进行比较。
如果该文件不存在,会参考每个 Ports 的源目录(相当于指定 -P
选项)。
如果该目录也不存在,则会参考远程仓库(相当于指定 -R
选项)。
前两种情况属于 [L]
范畴,而后者则属于 [R]
范畴。
通常使用 -L
选项进行已安装包的版本比较,使用 =
来显示没有匹配的包。通常情况下,只指定 =
就足够了,但也可以指定 >
、<
、?
、!
等其他符号,所有这些符号都需要加引号。
以下是每个符号的含义,但在使用 -L
选项时,表示的是“非该符号”的情况。若需要查找该符号的含义,则需要使用 -l
选项。
>
:当前安装的版本有较新的版本可用。
=
:当前安装的版本与发布的版本相同。
<
:当前安装的版本有较旧的版本可用,通常是元数据未更新或者进行新版本的测试安装时会出现。
?
:当前安装的包来源(origin)不存在,无法进行版本比较(可能已被删除或重命名)。
!
:当前安装的版本无法进行版本比较。
用于比较任意指定的版本号(实际上是字符串)。这个功能更多是用于测试不同版本号之间的关系,而不是特定包的功能。它与其他子命令有所不同,主要用于测试版本号的替换(例如,在替换 alpha 版、beta 版时),帮助用户确定哪个版本更大(更新),哪个版本更小(更旧)。
更新指定的包。如果没有特别指定,默认会检查所有包并尝试更新它们。
显示指定包的信息。如果没有指定包,则列出所有已安装包的概述。
与其他选项一起使用时,表示列出所有包的信息。
显示指定包的安装路径列表。
显示指定包的注意事项,可能包含安装提示或其他相关信息。
锁定指定包,防止其被更新。锁定的效果不仅限于防止包本身的更改,还包括以下功能:
阻止锁定包的重新安装、升级、降级和删除。
阻止依赖于锁定包的其他包的升级或降级,特别是当依赖关系指向另一个版本的锁定包时。
阻止锁定包依赖的其他包的删除、升级或降级。
即使间接共享依赖关系,也会被锁定。
解锁指定包。
使用正则表达式(大小写不敏感)搜索包名。通过 -e
选项可以进行严格的匹配,但这包括版本号,因此对于一般用户来说并不太友好。-g
选项支持类似于 shell glob(例如 ?
或 *
)的模糊搜索,但由于版本号的包含,实际上搜索时需要加上 *
。
显示指定的文件、目录等属于哪个包。使用 -o
选项可以显示该包的 origin。
报告已安装包与漏洞信息的匹配结果。由于需要从外部获取漏洞信息,这个功能偏向 [R]
,但如果没有急于更新信息的需求,就无需通过 -F
选项主动获取漏洞信息。通常,系统会有一个脚本每天自动获取漏洞信息。
检查指定包是否未被篡改且保持一致性。通常与 -a
选项一起使用。
检查指定包的依赖是否完好,是否未损坏。通常与 -a
选项一起使用。
删除孤立的包。所谓“孤立”的包是指因为依赖关系而安装,但由于某些包被删除或更新后不再被依赖,因此变得不再使用。
实际中,某些“孤立”的包可能仍在使用,但由于包的依赖信息无法反映这一点,因此在执行此操作时需要小心。例如,如果 bash
被作为某个包的依赖安装,但你仍在使用它,这种情况下就需要特别留意。可以通过显式安装 bash
或使用后续技巧避免此问题。
在 ports
系统中,通常是需要在构建过程中使用的包(如编译器等)会被标记为删除对象。
显示需要注意的包更新步骤(手动更新指示)。具体来说,会读取 /usr/ports/UPDATING
文件,并根据安装的(或指定的)包信息匹配并显示相关内容。该文件的内容是为人类阅读设计的,构造上有些启发式,但其严格性可能并不高。此外,需要确保该文件存在,系统不会自动下载该文件。
修改指定包的元数据(数据库)。通常是在根据 pkg updating
信息操作时才会用到这个命令,一般不需要主动使用。
通过为 -A
选项指定以下值,来修改指定包的元数据。此更改会影响 pkg autoremove
的行为结果。
0
:使指定的包不成为 pkg autoremove
的删除对象。
1
:使指定的包成为 pkg autoremove
的删除对象。
对这个选项感兴趣的人,可能也会关心 pkg autoremove
的工作原理。实际上,仅设置这个标志并不足以使包成为 pkg autoremove
的目标;还需要判断该包没有被其他包依赖等条件。
另外,通过 pkg install
或 pkg add
明确指定安装的包,在安装时会自动设置为此标志无效。这个标志只对因依赖关系被自动安装的包有效。
使用 -o 旧 origin:新 origin
的形式,将所有依赖旧 origin 的包的元数据中的 origin 信息修改为新值。
使用 -n 旧包名:新包名
的形式修改包名。不过,考虑到包名中通常不包含版本号,这个操作本身存在一些微妙的问题。
显示定义在 /usr/local/etc/pkg.conf
中的别名信息。
以指定的格式显示软件包的元信息。如果未指定包名,则会针对所有已安装的包进行查询。 可用于格式字符串中的占位符如下所示:
%n
:包名
%v
:包的版本
%o
:包的 origin
%p
:包的 prefix
%m
:包的维护者(电子邮件地址)
%c
:包的注释
%e
:包的描述
%w
:包的网址
%l
:包的许可证逻辑(无/单一/and/or)
%sb
或 %sh
:包的大小(字节单位或更适合人类阅读的单位)
%a
:包的自动安装标志
%Q
:包支持的架构候选项
%q
:包的架构(操作系统、版本、CPU 架构)
%k
:包的锁定标志
%M
:包的信息消息
%t
:包的安装时间戳
%R
:包的安装来源仓库
%X
:包的校验和
%?C
:表示某种条件 C
是否成立的布尔标志(d
/r
/C
/F
/O
/D
/L
/U
/G
/B
/b
/A
,各自说明略)
%#C
:满足某种条件 C
的项目数(与上同)
%dC
:该包依赖的其他包列表,通过 C
(具体为 n
/o
/v
)来选择输出 Name/Origin/Version
%rC
:依赖于该包的其他包列表,通过 C
(具体为 n
/o
/v
)来选择输出 Name/Origin/Version
%C
:包所属的分类列表
%FC
:包包含的文件列表,通过 C
(p
/s
)来选择 Path 或校验和 Sum
%D
:包包含的目录列表
%OC
:包的选项列表,通过 C
(k
/v
/d
/D
)来选择 key、value、默认值、描述
%L
:包的许可证列表
%U
:包使用的用户列表
%G
:包使用的用户组列表
%B
:包在程序中使用的共享库列表
%b
:包所提供的共享库列表
%AC
:包的注解标签列表,通过 C
(t
/v
)选择 tag 或 value
常见的用法之一是 %n-%v
,用于输出包名和版本的组合形式。
用于根据指定的查询条件筛选符合条件的软件包。以下是可用于右侧(不能用于左侧)条件表达式的字段:
%n
:包名(字符串型)
%o
:包的 origin(字符串型)
%p
:包的 prefix(字符串型)
%m
:包的维护者(邮箱,字符串型)
%c
:包的注释(字符串型)
%e
:包的描述(字符串型)
%w
:包的网址(字符串型)
%s
:包的大小(字节单位,数值型)
%a
:包的自动安装标志(数值型)
%q
:包的架构(操作系统、版本、CPU 架构,字符串型)
%k
:包的锁定标志(数值型)
%M
:包的信息消息(字符串型)
%t
:包的安装时间戳(数值型)
%i
:包的附加信息(字符串型)
%#C
:表示某类项目的数量(C
可为 d
/r
/C
/F
/O
/D
/L
/U
/G
/B
/b
/A
,说明略)
可使用的运算符如下:
||
:逻辑“或”,用于连接两个判断条件
&&
:逻辑“与”,用于连接两个判断条件
~
:用于匹配 glob 模式,例如 %var ~ 模式
,判断是否匹配
!~
:用于判断是否不匹配 glob 模式
>
/ >=
:用于数值比较,大于或大于等于
<
/ <=
:用于数值比较,小于或小于等于
=
/ ==
:判断是否等于(数字或字符串)
!=
:判断是否不等于(数字或字符串)
=~
:判断是否大小写不敏感地等于(数字或字符串)
!=~
:判断是否大小写不敏感地不等于(数字或字符串)
作用类似于 pkg query
,但用于远程元数据。不再赘述,请参见 pkg query
的说明。
用于为软件包添加、修改或删除“注释信息标签”的命令。
这些注释信息可通过 pkg info -A
查看。至于注释标签的具体含义与使用方式,此处不做特别说明。
用于直接访问管理软件包元数据的数据库(即 SQLite3)的命令。
基本上只能用来执行类似 pkg shell VACUUM
这样的操作。
如果你只是想利用查询功能,用 pkg query
就已经绰绰有余了,这个命令实用性很低。
以下命令是别名,用于筛选出“自动安装标志为 0”的软件包,即那些是用户显式安装的包:
pkg prime-list
[L]
pkg prime-origins
[L]
pkg noauto
[L]
显示所有“叶子”软件包,即在依赖树最下层的包。
若某个软件包出现在这里但不出现在 pkg noauto
中,则它是 pkg autoremove
的候选对象。
显示指定软件包所安装的文件路径列表。
以下是等价的命令别名,可以任选其一来执行操作。
甚至你可以用像 pkg vanish
(消失)这种中二感满满的词自定义别名,只要你愿意。
系统默认提供了一些比较中性的别名。
pkg remove
等价于 pkg delete
这些命令大多是供内部使用的,或是给其他工具调用使用(比如把别的包管理系统的软件包信息注册到 FreeBSD 的 pkg 系统中)。 一般用户不需要关心:
pkg stats
:显示统计信息
pkg clean
:清理包缓存
pkg config
:查看 /usr/local/etc/pkg.conf
中的设置(大小写不敏感)
pkg create
:创建软件包。虽然在 Ports 构建过程中常用,但很少单独使用
pkg fetch
:下载包。pkg install
实际上等价于 pkg fetch
加上 pkg add
pkg register
:将包注册进本地数据库。纯粹是内部用途
pkg repo
:生成包仓库目录,相关内容建议参考 pkg-repository(5)
手册
pkg shlib
:显示软件包所提供的共享库以及依赖这些库的其他包,主要用于安全审计
pkg ssh
:完全用于内部,不适合人类用户使用,省略
pkg triggers
:执行延迟触发器。这是什么时候谁延迟的?总之也是内部使用,省略
以 Python 3.11 为例,说明如何列出“依赖 Python 3.11 且是用户明确指定安装”的所有软件包。
首先可以使用 pkg info -r python311
(按包名指定)列出所有依赖 Python 3.11 的软件包。
也可以使用 pkg query '%ro' python311
以“原始名称”(origin)来列出。
此外,也可以直接使用如 lang/python311
这样的 origin 作为指定方式,而非包名。
接着,检查这些软件包的“自动安装标志”,只列出自动安装标志为 0 的,即明确安装的那些。 示例如下:
由于没有很干净的一条命令就能完成所有功能的写法,因此也可以借助 pkg shell
来做(不推荐,供参考)。
注意:此方法依赖底层数据库结构,未来可能失效。
A.Origin 是什么以后再说吧。有空我再写。
A.是的,pkg
命令本身就是一个包。
/usr/sbin/pkg
是什么?A.那是一个“引导器”,只负责安装真正的 pkg 包。
实际会执行的是 pkg 包里的 /usr/local/bin/pkg-static
。
A.FreeBSD 曾经因为旧的软件包系统吃了太多苦,所以才采用了现在这种结构。 以前 pkg 命令不升级,整个系统就什么都干不了(即使新版本系统已经发布了,还会强制用老功能)。
A.功能完全一样。pkg-static
主要在某些“极端情况”(如你要删掉 pkg 本身)时才需要。
一般正常使用用 pkg
就够了;pkg-static
只是为了某些内部处理时更安全。
pkg update
获取的仓库信息?A.我也很感兴趣,目前还在调查中。
pkg query
过滤总是不太顺利啊。比如说,想列出“最后安装的包”怎么办?A.这种时候可以用 pkg shell
来努力一下。虽说“让我们来写 SQL 吧!”这听起来有点夸张,但你说得没错,pkg query
并不支持排序或聚合。
另一种思路是,把 pkg query
的输出通过管道传给其它工具,比如 sort
、awk
、head
、tail
等组合使用。
A.常用的当然记得住。原以为我也就记了三五个而已,没想到写着写着就十几个浮现脑海。说明这些的确值得记。 虽然有些细节的语义可能模糊了,但那种情况就查下手册吧。 总之,平时不常用的,忘了也无妨。
顺便说一下,pkg query
和 pkg shell
以前我其实用得不多,这次因为研究查数据才顺手补上的。虽然 pkg shell
基本就是只查结果而已。
A.很遗憾,这是必须记下来的。
其他包管理器有时 update
和 upgrade
是同一个东西,但在 FreeBSD 上……很遗憾(信息在此中断了)。
A.这是非常古早(比 10.0-RELEASE 还早)的事情,完全可以无视。 它们只具备历史意义,现在的设置和运维里已经毫无价值。
关于版本比较的规则,你可以参阅 。
刚列完这些“大家应该都知道吧”的命令,立马陷入绝望:平时常用到底是指哪些……? 但如果不写这些,又感觉内容不完整,简直是地狱。 结果还在翻 man 手册时发现了个 bug(),orz。