# 4.4.使用 pkg 管理二进制包

[pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 提供了一个用于操作软件包的接口：注册、添加、删除和升级软件包。

对于只希望使用 FreeBSD 镜像站提供的预构建二进制包的站点，使用 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 管理软件包是足够的。

然而，对于从源代码构建软件的站点，需要一个单独的 [Ports 管理工具](https://docs.freebsd.org/en/books/handbook/ports/#ports-upgrading-tools)。

由于 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 只与二进制包一起使用，它不能替代这些工具。那些工具可以用来从二进制包和 Ports 安装软件，而 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 只安装二进制包。

## 4.4.1. 开始使用 pkg

所有受支持的 FreeBSD 版本现在都包含 `/usr/sbin/pkg`，即 [pkg(7)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=7\&format=html)。这是一个小的占位符，仅具有安装真实的 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 所需的最小功能。

> **注意**
>
> 引导过程需要网络连接才能成功。

运行 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 命令行：

```sh
# pkg
```

输出应类似于以下内容：

```sh
The package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]
```

[pkg(7)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=7\&format=html) 将拦截该命令，如果你确认这是你的意图，它将下载 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) tarball，从中安装 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html)，引导本地软件包数据库，然后继续执行你最初请求的命令。

较新的 [pkg(7)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=7\&format=html) 版本理解 `pkg -N` 作为测试，查看 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 是否已安装而不触发安装，反之，使用 pkg bootstrap\[-f] 安装 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html)（或强制重新安装）而不执行其他任何操作。

有关 pkg 使用信息，请参见 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 手册页，或运行 `pkg` 而不带附加参数。其他 pkg 配置选项在 [pkg.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=pkg.conf\&sektion=5\&format=html) 中有描述。

每个 pkg 命令参数都在特定的命令手册页中进行了记录。

例如，要查看 `pkg install` 的手册页，请运行以下命令：

```sh
# pkg help install
```

本节的其余部分演示了可以使用 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 执行的常见二进制软件包管理任务。每个演示的命令都有许多选项，可以自定义其使用方式。请参考命令的帮助或手册页以获取详细信息和更多示例。

## 4.4.2. 季度和最新 Ports 分支

`Quarterly` 分支为用户提供了更可预测和稳定的 Port 和软件包安装及升级体验。这主要通过只允许非功能性更新来实现。季度分支旨在接收安全修复（这些可能是版本更新，或是提交的回溯）、错误修复和 Port 合规性或框架更改。季度分支在每年的一月、四月、七月和十月的开始从 HEAD 分支切出。分支名称根据它们创建的年份（YYYY）和季度（Q1-4）命名。例如，2023 年一月创建的季度分支命名为 2023Q1。`Latest` 分支则为用户提供最新版本的软件包。

要将 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 从 Quarterly 切换到 Latest，请运行以下命令：

```sh
# mkdir -p /usr/local/etc/pkg/repos
# echo 'FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest" }' > /usr/local/etc/pkg/repos/FreeBSD.conf
```

然后运行以下命令以更新本地软件包仓库目录以获取 Latest 分支的内容：

```sh
# pkg update -f
```

## 4.4.3. 内核模块仓库

内核模块仓库能让用户安装可直接使用的内核模块，例如用于图形驱动和特定硬件的模块。从 FreeBSD 14.3 开始，FreeBSD 项目为每个支持的版本提供了预构建的内核模块。若要创建这样的仓库配置（如果尚不存在），请将以下内容添加到 **/usr/local/etc/pkg/repos/kmods.conf**：

```ini
FreeBSD-kmods: {
        url: "pkg+https://pkg.FreeBSD.org/${ABI}/KMODSFLAVOR",
        mirror_type: "srv",
        signature_type: "fingerprints",
        fingerprints: "/usr/share/keys/pkg",
        enabled: yes
}
```

`KMODSFLAVOR` 遵循如下模式：`kmods_PORTBRANCH_MINORRELEASE`。

例如：

Kmodsflavor

| FreeBSD 版本           | ports main       | 季度 ports            |
| -------------------- | ---------------- | ------------------- |
| FreeBSD 14.2-RELEASE | kmods\_latest\_2 | kmods\_quarterly\_2 |
| FreeBSD 14.3-RELEASE | kmods\_latest\_3 | kmods\_quarterly\_3 |
| FreeBSD 14.3-STABLE  | kmods\_latest    | kmods\_quarterly    |
| FreeBSD 15.0-CURRENT | kmods\_latest    |                     |

## 4.4.4. 配置 pkg

[pkg.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=pkg.conf\&sektion=5\&format=html) 是 [pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 工具使用的系统配置文件。该文件的默认位置是 `/usr/local/etc/pkg.conf`。

> **注意**
>
> FreeBSD 不需要 `pkg.conf` 文件。许多安装在没有 `pkg.conf` 或者空的 `pkg.conf`（除了注释行）时也能正常工作。

以 `#` 开头的行是注释行，会被忽略。

该文件采用 UCL 格式。有关 [libucl(3)](https://man.freebsd.org/cgi/man.cgi?query=libucl\&sektion=3\&format=html) 语法的更多信息，请访问 [官方 UCL 网站](https://github.com/vstakhov/libucl)。

以下类型的选项是被识别的 - 布尔选项、字符串选项和列表选项。

如果配置文件中指定以下值之一，则布尔选项被视为启用：YES、TRUE 和 ON。

## 4.4.5. 搜索软件包

要搜索软件包，可以使用 [pkg-search(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-search\&sektion=8\&format=html) 命令：

```sh
# pkg search nginx
```

输出应该类似于以下内容：

```sh
modsecurity3-nginx-1.0.3       Instruction detection and prevention engine / nginx Wrapper
nginx-1.22.1_2,3               Robust and small WWW server
nginx-devel-1.23.2_4           Robust and small WWW server
nginx-full-1.22.1_1,3          Robust and small WWW server (full package)
nginx-lite-1.22.1,3            Robust and small WWW server (lite package)
nginx-naxsi-1.22.1,3           Robust and small WWW server (plus NAXSI)
nginx-prometheus-exporter-0.10.0_7 Prometheus exporter for NGINX and NGINX Plus stats
nginx-ultimate-bad-bot-blocker-4.2020.03.2005_1 Nginx bad bot and other things blocker
nginx-vts-exporter-0.10.7_7    Server that scraps NGINX vts stats and export them via HTTP
p5-Nginx-ReadBody-0.07_1       Nginx embeded perl module to read and evaluate a request body
p5-Nginx-Simple-0.07_1         Perl 5 module for easy to use interface for Nginx Perl Module
p5-Test-Nginx-0.30             Testing modules for Nginx C module development
py39-certbot-nginx-2.0.0       NGINX plugin for Certbot
rubygem-passenger-nginx-6.0.15 Modules for running Ruby on Rails and Rack applications
```

## 4.4.6. 安装和获取软件包

要安装二进制软件包，可以使用 [pkg-install(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-install\&sektion=8\&format=html) 命令。此命令使用仓库数据来确定要安装的软件版本以及是否有任何未安装的依赖项。例如，要安装 curl：

```sh
# pkg install curl
```

输出应类似于以下内容：

```sh
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 9 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        ca_root_nss: 3.83
        curl: 7.86.0
        gettext-runtime: 0.21
        indexinfo: 0.3.1
        libidn2: 2.3.3
        libnghttp2: 1.48.0
        libpsl: 0.21.1_4
        libssh2: 1.10.0.3
        libunistring: 1.0

Number of packages to be installed: 9

The process will require 11 MiB more space.
3 MiB to be downloaded

Proceed with this action? [y/N]
```

新软件包和作为依赖项安装的任何额外软件包可以在已安装软件包列表中查看：

```sh
# pkg info
```

输出应类似于以下内容：

```sh
ca_root_nss-3.83               Root certificate bundle from the Mozilla Project
curl-7.86.0                    Command line tool and library for transferring data with URLs
gettext-runtime-0.21.1         GNU gettext runtime libraries and programs
indexinfo-0.3.1                Utility to regenerate the GNU info page index
libidn2-2.3.3                  Implementation of IDNA2008 internationalized domain names
libnghttp2-1.48.0              HTTP/2.0 C Library
libpsl-0.21.1_6                C library to handle the Public Suffix List
libssh2-1.10.0.3               Library implementing the SSH2 protocol
libunistring-1.0               Unicode string library
pkg-1.18.4                     Package manager
```

要获取软件包并稍后安装或在其他地方安装，可以使用 [pkg-fetch(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-fetch\&sektion=8\&format=html)。例如，要下载 `nginx-lite`：

```sh
# pkg fetch -d -o /usr/home/user/packages/ nginx-lite
```

* `-d`：用于获取所有依赖项
* `-o`：用于指定下载目录

输出应类似于以下内容：

```sh
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following packages will be fetched:

New packages to be FETCHED:
        nginx-lite: 1.22.1,3 (342 KiB: 22.20% of the 2 MiB to download)
        pcre: 8.45_3 (1 MiB: 77.80% of the 2 MiB to download)

Number of packages to be fetched: 2

The process will require 2 MiB more space.
2 MiB to be downloaded.

Proceed with fetching packages? [y/N]:
```

要安装下载的软件包，可以使用 [pkg-install(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-install\&sektion=8\&format=html)，如下所示：

```sh
# cd /usr/home/user/packages/
```

```sh
# pkg install nginx-lite-1.22.1,3.pkg
```

## 4.4.7. 获取已安装软件包的信息

可以通过运行 [pkg-info(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-info\&sektion=8\&format=html) 来查看系统上已安装的软件包信息。当不带任何选项运行时，它将列出所有已安装的软件包的版本，或者指定的软件包的版本。

例如，要查看安装的 pkg 版本，可以运行：

```sh
# pkg info pkg
```

输出应类似于以下内容：

```sh
pkg-1.19.0
Name           : pkg
Version        : 1.19.0
Installed on   : Sat Dec 17 11:05:28 2022 CET
Origin         : ports-mgmt/pkg
Architecture   : FreeBSD:13:amd64
Prefix         : /usr/local
Categories     : ports-mgmt
Licenses       : BSD2CLAUSE
Maintainer     : pkg@FreeBSD.org
WWW            : https://github.com/freebsd/pkg
Comment        : Package manager
Options        :
        DOCS           : on
Shared Libs provided:
        libpkg.so.4
Annotations    :
        FreeBSD_version: 1301000
        repo_type      : binary
        repository     : FreeBSD
Flat size      : 33.2MiB
Description    :
Package management tool

WWW: https://github.com/freebsd/pkg
```

## 4.4.8. 升级已安装的软件包

可以使用 [pkg-upgrade(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-upgrade\&sektion=8\&format=html) 升级已安装的软件包到最新版本：

```sh
# pkg upgrade
```

此命令将比较已安装版本与仓库目录中可用版本，并从仓库升级它们。

## 4.4.9. 审计已安装的软件包

第三方应用程序中经常发现软件漏洞。为了解决这个问题，pkg 包括了一个内建的审计机制。要检查系统上已安装软件是否存在已知漏洞，可以使用 [pkg-audit(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-audit\&sektion=8\&format=html)：

```sh
# pkg audit -F
```

输出应类似于以下内容：

```sh
Fetching vuln.xml.xz: 100%  976 KiB 499.5kB/s    00:02
chromium-108.0.5359.98 is vulnerable:
  chromium -- multiple vulnerabilities
  CVE: CVE-2022-4440
  CVE: CVE-2022-4439
  CVE: CVE-2022-4438
  CVE: CVE-2022-4437
  CVE: CVE-2022-4436
  WWW: https://vuxml.FreeBSD.org/freebsd/83eb9374-7b97-11ed-be8f-3065ec8fd3ec.html
```

## 4.4.10. 移除软件包

可以使用 [pkg-delete(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-delete\&sektion=8\&format=html) 移除不再需要的软件包。

例如：

```sh
# pkg delete curl
```

输出应类似于以下内容：

```sh
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 1 packages (of 0 packages in the universe):

Installed packages to be REMOVED:
        curl :7.86.0

Number of packages to be removed: 1

The operation will free 4 MiB.

Proceed with deinstallation packages? [y/N]: y
[1/1] Deinstalling curl-7.86.0...
[1/1] Deleting files for curl-7.86.0: 100%
```

## 4.4.11. 自动移除未使用的软件包

移除一个软件包可能会留下不再需要的依赖项。可以使用 [pkg-autoremove(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-autoremove\&sektion=8\&format=html) 自动检测并移除作为依赖项安装但不再需要的未使用软件包（叶子包）：

```sh
# pkg autoremove
```

输出应类似于以下内容：

```sh
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 1 packages:

Installed packages to be REMOVED:
        ca_root_nss-3.83

Number of packages to be removed: 1

The operation will free 723 KiB.

Proceed with deinstalling packages? [y/N]:
```

作为依赖项安装的软件包被称为 *自动* 包。非自动包，即作为独立包而不是作为另一个软件包的依赖项明确安装的软件包，可以通过以下命令列出：

```sh
# pkg prime-list
```

输出应类似于以下内容：

```sh
nginx
openvpn
sudo
```

`pkg prime-list` 是在 `/usr/local/etc/pkg.conf` 中声明的别名命令。还有许多其他命令可用于查询系统的软件包数据库。例如，可以使用命令 `pkg prime-origins` 获取上述列表的原始 Port 目录：

```sh
# pkg prime-origins
```

输出应类似于以下内容：

```sh
www/nginx
security/openvpn
security/sudo
```

此列表可用于使用构建工具如 [ports-mgmt/poudriere](https://cgit.freebsd.org/ports/tree/ports-mgmt/poudriere/) 或 [ports-mgmt/synth](https://cgit.freebsd.org/ports/tree/ports-mgmt/synth/) 重新构建系统上安装的所有软件包。

可以通过以下命令将已安装的软件包标记为自动包：

```sh
# pkg set -A 1 devel/cmake
```

待软件包成为叶子包并被标记为自动包，它就会被 `pkg autoremove` 选中。

可以通过以下命令将已安装的软件包标记为 *非* 自动包：

```sh
# pkg set -A 0 devel/cmake
```

## 4.4.12. 移除过时的软件包

默认情况下，pkg 会将二进制软件包存储在由 [pkg.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=pkg.conf\&sektion=5\&format=html) 中的 `PKG_CACHEDIR` 定义的缓存目录中。只保留最新安装的软件包的副本。旧版本的 pkg 会保留所有先前的软件包。要移除这些过时的二进制软件包，可以运行：

```sh
# pkg clean
```

可以通过运行以下命令清空整个缓存：

```sh
# pkg clean -a
```

## 4.4.13. 锁定和解锁软件包

[pkg-lock(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-lock\&sektion=8\&format=html) 用于锁定软件包，防止其被重新安装、修改或删除。使用 [pkg-unlock(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg-unlock\&sektion=8\&format=html) 可以解锁已锁定的软件包。这两种操作仅对当前已安装的软件包有效。因此，除非新安装的软件包需要更新已锁定的包，否则无法通过此机制阻止新软件包的安装。

例如，要锁定 `nginx-lite`：

```sh
# pkg lock nginx-lite
```

要解锁 `nginx-lite`：

```sh
# pkg unlock nginx-lite
```

## 4.4.14. 修改软件包元数据

FreeBSD Ports 中的软件包可能会发生重大版本号变化。为了解决这个问题，pkg 提供了一个内置命令来更新软件包的来源。这个功能在例如将 [lang/python3](https://cgit.freebsd.org/ports/tree/lang/python3/) 重命名为 [lang/python311](https://cgit.freebsd.org/ports/tree/lang/python311/) 时非常有用，这样 [lang/python3](https://cgit.freebsd.org/ports/tree/lang/python3/) 就可以代表版本 `3.11`。

要更改上述示例中的软件包来源，可以运行：

```sh
# pkg set -o lang/python3:lang/python311
```

另一个例子是将 [lang/ruby31](https://cgit.freebsd.org/ports/tree/lang/ruby31/) 更新为 [lang/ruby32](https://cgit.freebsd.org/ports/tree/lang/ruby32/)，可以运行：

```sh
# pkg set -o lang/ruby31:lang/ruby32
```

然后安装更新后的软件包：

```sh
# pkg install -Rf lang/ruby32
```
