一个基本的FreeBSD安装包括足以使系统运行的内容,以及Unix系统传统上包含的一些额外位(extra bits)。您可以决定是否安装其他程序或源代码。虽然FreeBSD多年来一直在发展,但一个完整的基础安装大约需要1GB的磁盘空间,比Windows或商业Linux安装少得多。
这种稀疏性的优点是它只包括必要的系统组件。当你知道没有一个你从未听说过、也永远不会使用的共享库可以为你的问题负责时,调试会变得简单得多。缺点是你必须决定你需要什么功能,并选择提供这些功能的软件。FreeBSD通过ports和packages简化了附加软件的安装。
FreeBSD支持两种不同的方式来安装附加软件。一切都始于Ports Collection,但大多数用户更喜欢预配置的包。
FreeBSD有一个用于构建附加软件的系统,称为 Ports Collection ,或简称为 ports 。端口允许您从程序供应商的原始源代码开始,以您需要的方式构建软件,根据需要启用和禁用功能。对于有经验的用户来说,端口是快速和简单的,但需要一定的Unix专业知识,并且可能会吓到新用户。
packages 是构建ports的结果,使用port维护人员认为对最广泛的人群最有用的选项,并将它们捆绑在一起,使其易于安装。FreeBSD项目有一个完整的系统群,除了构建所有ports、捆绑它们并让用户下载和安装之外,什么都不做。软件包允许您快速安装、卸载和升级附加软件。
互联网建议永远存在
论坛和邮件列表档案包含许多跳过软件包直接前往ports的建议。这已不再是事实;出于技术原因和您自己的安心,软件包更可取。旧的包系统pkg_tools有严重的局限性。
忽略任何提及 pkg_add(8)
、pkg_delete(8)
和 pkg_create(8)
等工具的建议。它已经过时了。
FreeBSD高度灵活的打包系统被称为 package、pkg(8)
或简称为plain pkg。包信息存储在SQLite数据库中,这允许您对包数据执行任意查询。在开发过程中,pkg被称为 pkgNG 。这个名字已经消失多年了,但在一些旧文档和第三方软件中仍然存在。别让这个名字把你弄糊涂了。
我们将首先讨论使用 pkg(8)
管理系统,然后继续使用ports定制软件。
软件包是Ports Collection中的预编译软件,为特定版本的FreeBSD捆绑在一起。FreeBSD项目在公共存储库中提供了几组软件包,每隔几天更新一次。软件包是安装附加软件的最简单方法。任何对其分发没有法律限制的软件都可能以软件包的形式提供。
法律限制?软件可以有任何许可条款,包括一些非常奇怪的条款。某些软件的许可证禁止以源代码以外的任何形式分发。FreeBSD不能合法地打包它。其他软件只能以预编译的形式合法分发。FreeBSD通常会打包此类软件,将其作为预编译的二进制文件和FreeBSD特定的打包信息分发。
软件包构建在每个主要FreeBSD版本的最旧支持版本上。所有版本的FreeBSD 12的软件包都是基于最旧的受支持的FreeBSD 12版本构建的,FreeBSD 13的软件包是基于最古老的受支持版本的FreeBSD 13构建的,以此类推。这有助于减少、识别和包含ABI不兼容问题。
如果您需要构建自己的包存储库,请调查Ports Collection(见第16章)和附加包poudriere。
最终,包包含文件。这些文件可能是二进制程序、文档、配置文件或软件可能需要的任何其他文件。这些文件被认为是操作系统的一部分。不要手动编辑它们。
一个奇怪的情况是,包中包含示例配置文件。如果程序需要配置文件,则包中应包含示例。您需要编辑配置以满足您的需求——这就是配置文件的用途。
FreeBSD通过安装后缀为 .sample 的包配置文件来调和这一点。我们的web服务器配置文件看起来像 httpd.conf.sample 。
如果没有生产配置文件,包安装还会将示例文件复制到适当的位置。那个文件由你编辑。
如果升级包,pkg(8)
会将当前生产文件与旧示例文件进行比较。如果示例与生产版本相同,则升级将替换生产文件。如果文件有任何不同,pkg只会更新示例文件。您的工作是将任何所需的更改合并到生产配置中。请注意,包升级始终会替换示例配置,因此如果旧示例很重要,您需要注意保留它。
与旧的打包系统不同,pkg(8)
是一个包含大量子命令的单个程序。您将使用相同的程序来安装、卸载和调查软件包。对已安装包的所有更改都必须以root身份运行。以下是如何安装一个思维正常的系统管理员所需的重要程序:
xxxxxxxxxx
# pkg install emacs
你们中那些对高级文本处理器抱有非理性偏见的人可能想删除它:
xxxxxxxxxx
# pkg delete emacs
所有包操作都使用 pkg(8)
命令。
虽然 pkg(8)
手册页记录了基本pkg函数,但每个子命令都有自己的手册页,名为 pkg- 和子命令。示例包括 pkg-install(8)
和 pkg-delete(8)
。您还可以使用 pkg help
命令和子命令的名称来获取帮助,例如 pkg help install
。
FreeBSD没有安装pkg(8)。你需要安装它。作为一个包裹。不,等等,别尖叫——这比听起来好多了。
FreeBSD在 /usr/sbin/pkg ,pkg(7)
中附带了一个非常简单的包管理器。它几乎没有足够的大脑来找到FreeBSD当前的包管理器。它安装了新的包管理器,并将包管理的所有责任交给它。这使FreeBSD能够灵活地用包更新包管理器。
当您第一次尝试安装软件包时,pkg(8)
会提示您安装软件包管理器。我发现我需要在新服务器上安装dmidecode包,这样我就可以从制造商那里获得电源故障的RMA。(不用担心我是怎么找到dmidecode包的——就跟我走吧。)
xxxxxxxxxx
# pkg install dmidecode
FreeBSD运行 pkg(8)
,发现还没有安装包管理:
xxxxxxxxxx
he package management tool is not yet installed on your system.
Do you want to fetch and install it now? [y/N]: y
默认答案以大写字母显示。如果我按下 n
并按下ENTER键,pkg将终止。如果我按 y
和ENTER,FreeBSD会引导系统。
xxxxxxxxxx
➊ Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:12:amd64/quarterly, please wait...
➋ Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
➌ Installing pkg-1.10.0_2...
Extracting pkg-1.10.0_2: 100%
➍ Updating FreeBSD repository catalogue...
meta.txz : 100% 944 B 0.9kB/s 00:01
packagesite.txz : 100% 6 MiB 2.0MB/s 00:03
Processing entries: 100%
FreeBSD repository update completed. 26059 packages processed.
All repositories are up to date.
Updating database digests format: 100%
安装首先从FreeBSD镜像下载当前的pkg工具➊。然后检查下载文件➌上的数字签名。提取并安装这些工具➋。pkg然后下载并安装可用软件包的目录➍。
包装系统现已安装。为了解决问题,FreeBSD附带的stub pkg(8)
告诉新安装的打包系统安装您真正想要的程序。在这种情况下,我们的新 pkg(8)
会为您安装dmidecode。
您可以通过运行 pkg bootstrap
自行安装打包系统,而无需添加其他包,但说真的,没有人在命令行上这样做。当打包系统已经安装时,运行 pkg bootstrap
不会做任何事情,因此它对安装脚本很有用。
虽然每个pkg子命令都有其独特的功能,但一些命令选项几乎适用于所有这些子命令。
在默认配置中,pkg会在执行任何操作之前提示您进行确认。使用 -y
标志告诉pkg采取行动,而不提示您。
另一方面,也许你想让pkg向你展示如果你运行了一个命令,它会做什么,但实际上什么都不做。使用 -n
标志进行模拟运行。例如,使用 -n
的包安装将显示要安装的每个包的名称,包括依赖项。但是,系统不会安装这些软件包。试运行可以帮助您在维护窗口期间为更改做好准备。
许多pkg操作都会产生一堆输出。用 -q
减少输出量。
-a
标志通常将命令应用于所有已安装的软件包。
最后,pkg通常拒绝做无意义的事情或破坏系统的事情。-f
标志迫使pkg按照你说的去做。强制打包活动通常是一个坏主意,但并非总是如此。例如,您可能需要 -f
强制重新安装损坏的软件包。
pkg(8)
pkg(8)
程序设计得非常灵活。虽然每个子命令都有一大堆选项,但您可以使用配置文件 /usr/local/etc/pkg.conf 为大多数程序建立定制但一致的行为。
pkg.conf 文件包含注释掉的 pkg(8)
默认值。这是一个很好的地方,可以在你完全没有搞砸的情况下查看系统的行为。配置是用UCL编写的(见第2章)。变量可以设置为整数;字符串,例如文件路径;或布尔值,如 YES
或 NO
。YES
、ON
和 TRUE
是同义词,NO
、OFF
和 FALSE
也是同义词。所有这些都不区分大小写。
xxxxxxxxxx
#PKG_DBDIR = "/var/db/pkg";
#PKG_CACHEDIR = "/var/cache/pkg";
#PORTSDIR = "/usr/ports";
#INDEXDIR = "";
--snip--
FreeBSD在空的 pkg.conf 下运行良好。默认配置包含一大堆注释掉的条目和相当多的别名。您可以在继续操作时考虑这些示例设置。
大多数pkg操作都提供了一个yes/no对话框,将默认值显示为大写字母。出于保守考虑,pkg通常默认为 NO
。使用 DEFAULT_ALWAYS_YES
选项将默认值更改为 YES
。
您可以通过添加 -y
标志使pkg命令假设您对所有内容都回答YES
。如果你厌倦了键入 -y
,可以通过将 ASSUME_ALWAYS_YES
标志设置为 YES
,让pkg假设你总是回答yes。
由于我懒惰但并不鲁莽,我更喜欢这些 pkg.conf 设置:
xxxxxxxxxx
DEFAULT_ALWAYS_YES = true;
ASSUME_ALWAYS_YES = false;
如果安装软件包运行异常,您可能需要调试输出。设置 DEBUGLEVEL
可打开调试输出。此变量接受从0(无调试)到4(完全调试)的整数。
许多软件包在安装过程中都包含脚本。通过将 DEBUG_SCRIPTS
设置为 YES
来启用每个脚本的调试。
任何 pkg.conf 设置也可用作环境变量。环境变量覆盖配置文件中的任何内容。您可以安装一个调试包,如下所示:
xxxxxxxxxx
# env DEBUG_LEVEL=4 pkg upgrade
所有选项都记录在 pkg.conf(5)
中。不过,并非所有选项都有注释掉的条目。如果一个选项的示例不存在,但你想要它,请添加它。我们将在以下部分中研究其中的许多选项。
现在您已经安装了包管理器,可以安装包了。熟悉各种类Unix操作系统的系统管理员知道,不同的操作系统为同一软件的打包版本分配不同的名称。FreeBSD上Apache web服务器的包将与illumos上打包的Apache甚至不同的Linux发行版有完全不同的名称。在安装任何东西之前,你需要弄清楚它叫什么。
假设客户端想在Apache上运行WordPress。你的工作不是质疑客户在web服务器中的选择;你的工作是构建和支持web服务器。首先,使用 pkg search
命令查找Apache。您需要为pkg提供一个文本字符串,以便执行不区分大小写的搜索。
xxxxxxxxxx
# pkg search apache
apache-ant-1.9.7 Java- and XML-based build tool
apache-forrest-0.9 Tool for rapid development of small sites
apache-mode.el-2.0 Emacs major mode for editing Apache configuration files
--snip--
我故意举了一个恼人的例子;FreeBSD有50多个与Apache web服务器相关的包。幸运的是,每个搜索结果都列出了一行包描述。在找到实际的web服务器之前,很容易浏览结果。
xxxxxxxxxx
--snip--
apache22-2.2.31_1 Version 2.2.x of Apache web server with prefork MPM
apache22-event-mpm-2.2.31_1 Version 2.2.x of Apache web server with event MPM
apache22-itk-mpm-2.2.31_1 Version 2.2.x of Apache web server with itk MPM
apache22-peruser-mpm-2.2.31_1 Version 2.2.x of Apache web server with peruser MPM
apache22-worker-mpm-2.2.31_1 Version 2.2.x of Apache web server with worker MPM
apache24-2.4.25_1 Version 2.4.x of Apache web server
--snip--
Apache的六个不同版本。首先,看看包名。当一个软件有多个版本时,主版本号会集成到软件包名称中。Apache 2.2与Apache 2.4截然不同,因此这些包被命名为apache22和apache24 。实际版本号如下。我们的第一个Apache 2.2包实际上是针对Apache 2.2.31的。后面的_1是包版本号,这意味着这是一个更新的包。附带的软件没有改变,但软件包不知怎么地被改变了。软件包版本号出现冲突有两个原因。当源端口的更改对包产生重大影响时,版本号会增加。当所需共享库中的ABI更改要求重新编译包时,这也值得进行版本升级。
Apache 2.2有五个不同的包。熟悉Apache的人可能还记得,这个版本的Apache可以使用不同的多处理模块(Multi-Processing Modules —— MPM),但必须在编译时选择MPM。我幸福地忘记了我所知道的关于MPM的一切,所以与其大惊小怪,我会选择安装Apache 2.4软件包apache24。
一些搜索可以生成数百个结果。尝试搜索Perl,你会得到大约150个包。Perl模块都以字符串p5-开头;FreeBSD有5200多个Perl模块的软件包!使用命令行选项修剪或调整搜索结果。虽然 pkg-search(8)
列出了许多选项,但这里有一些最常见的选项。
-C
使搜索区分大小写。-e
标志搜索完全匹配的包。不过,您的搜索词必须包含软件包版本号。pkg-search(8)
中的 -L
、-S
和 -Q
标志。也许你不确定一个包裹是否是你真正想要的。您可以从第三方网站(如FreshPorts)查找该软件包的详细信息(https://www.freshports.org/),但这需要离开你的航站楼,我不能接受。使用 -R
标志检查包的存储库目录元数据。此元数据是每个包中内置的完整包清单的子集。
xxxxxxxxxx
# pkg search -R apache24
name: "apache24"
origin: "www/apache24"
version: "2.4.25_1"
comment: "Version 2.4.x of Apache web server"
maintainer: "apache@FreeBSD.org"
www: "http://httpd.apache.org/"
--snip--
包清单包括包名称、构建包的端口、软件版本、包存储库、依赖关系等字段。它很少被充分使用,也可能会发生变化,所以我们不会详细讨论它,但滚动浏览这些信息可以提供有关包内软件的更多详细信息。
这里的一个重要细节是 www 字段,它为网站提供了原始软件的来源。这是Apache web服务器,而不是使用该名称的分支或其他项目。
此原始清单的默认格式是YAML,即“YAML不是标记语言”。这是格式化配置文件的另一种语法,但它相当易于人类阅读。使用 --raw-format
标志选择替代格式。其他支持的格式包括json和json-compact。
xxxxxxxxxx
# pkg search -R --raw-format json-compact apache24
如果你想自动解析包信息,这就是你获取原始数据的方式。
使用pkg的 install
子命令和软件包的名称来安装软件包。您不需要提供完整的包名称。
xxxxxxxxxx
# pkg install apache24
首先,pkg会检查其包数据库的本地副本是否与包服务器上的副本相同。你要么会收到一条消息,比如“正在更新FreeBSD存储库目录”,要么会被告知“FreeBSD存储库是最新的”。
然后,系统会检查您选择的包所需的任何包。阅读依赖关系列表。您不希望在此主机上安装任何内容吗?该列表是否为您提供了不安装该软件包的理由?
xxxxxxxxxx
The following 8 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
apache24: 2.4.25_1
libxml2: 2.9.4
--snip--
Number of packages to be installed: 8
作为最后一个警告,pkg告诉您安装所需的磁盘空间和带宽。然后你会被提示改变主意。
xThe process will require 139 MiB more space.
33 MiB to be downloaded.
Proceed with this action? [y/N]:
输入 y
,pkg将从存储库中获取包并将其安装到您的系统中。
install
子命令假定您要么给出了包的完整名称,要么给出了没有包版本号的包的名称。您可以请求apache24包,pkg会发现当前包是apache24-2.4.25_1。您还可以使用构建包的port名称,如 pkg install www/apache24
。
在上一节中,我们的包搜索发现了五个不同的Apache 2.2包,每个包都是略有不同的变体。如果你让 pkg install
获取apache22软件包,它会安装名为apache22的版本以及一个软件包版本号。如果你想要一个变体,比如apache22-event-mpm,请在 install
命令中指定完整的包名。
某些软件包包含安装消息。这些信息可能是有用的说明、警告(warnings)、警告(caveats)或其他任何相关信息。如果包创建者觉得有一大块信息足够重要,可以花宝贵的时间写一条关于它的消息,那么你至少可以阅读它。你可以使用 script(1)
记录这些信息,或者运行 pkg info --pkg-message
和包名再次显示它。
FreeBSD通过互联网下载来安装软件包。您可能希望在一个位置下载软件包,以便在其他位置或其他时间安装。使用 pkg fetch
命令下载但不安装软件包。当与 -d
结合使用时,获取包是最有意义的,这使得 pkg fetch
能够获取所有依赖项以及指定的包。
xxxxxxxxxx
# pkg fetch -d apache24
您将看到正常的存储库更新消息,然后是pkg将下载什么的通知。
xxxxxxxxxx
New packages to be FETCHED:
apache24-2.4.25_1 (5 MiB: 14.25% of the 33 MiB to download)
libxml2-2.9.4 (821 KiB: 2.43% of the 33 MiB to download)
--snip--
验证pkg计划下载的内容是否符合您的期望,然后单击y继续。这些包被下载到包文件缓存中。
要安装下载的软件包,请正常运行 pkg install
。安装过程使用缓存的文件,而不是下载的文件。
阅读手册页的人可能会注意到 -a
标志,它会下载整个包存储库。不要用那个。-a
选项用于公共存储库镜像。镜像整个存储库的普通系统管理员会浪费带宽,降低每个人的系统速度。慷慨的人捐赠FreeBSD的包服务器带宽。别浪费了。你可能需要一大堆包。对于依赖关系,您可能需要数百甚至数千个包。你不需要成千上万的包裹。只下载你需要的东西。
任何访问互联网的工具都需要设置下载文件的最长时间。您可以使用两个 pkg.conf 设置自定义pkg的下载行为。
如果下载失败,pkg会再次尝试。FETCH_RETRY
选项控制pkg重试下载的次数。默认值为3,这意味着它尝试下载一次,最多重试三次。
在大多数现代互联网连接上,下载速度相当快。如果你的上行链路不够现代,你可能需要增加pkg在单次下载尝试上花费的时间。FETCH_TIMEOUT
设置控制pkg等待任何一个文件下载的时间。默认值为30,下载时间限制为30秒。如果你通过33.6调制解调器下载LibreOffice,你需要增加此设置,并考虑通过Pony Express在可移动驱动器上向你发送文件。
下载软件包并稍后安装的能力意味着 pkg(8)
将这些软件包保存在磁盘上的某个位置以供以后使用。包缓存 /var/cache/pkg 包含从互联网下载的原始包文件。虽然你可以管理FreeBSD主机数年而不会浪费缓存,但你应该知道以下几点。
随着升级、新软件包、删除的软件包以及系统管理的随机性,缓存目录可能会被填满。我的web服务器只有几个包,但不知怎么地,它已经积累了1.7GB的旧包文件。pkg clean
命令删除任何已被更新版本替换的缓存包,以及存储库中不再存在的任何包文件。您将获得一个将被删除的所有文件的列表,以及继续或退出的机会。
xxxxxxxxxx
# pkg clean
The following package files will be deleted:
/var/cache/pkg/php56-mbstring-5.6.26.txz
/var/cache/pkg/mod_php56-5.6.21-c80f5ce183.txz
--snip--
如果你从未在长时间运行的系统上清理过包缓存,那么这个列表会很长。在提示下,按 y
继续。
如果要删除所有缓存的包,请使用 -a
标志。
请记住,pkg clean
会删除包存储库中不再可用的包文件。如果您依赖于已从存储库中删除的包,请在粗心的清理将其永久删除之前,将该文件备份到缓存外。您还可以尝试 pkg-create(8)
从已安装的组件重建包。
如果要在每次安装或升级包后自动清理包缓存,请将 pkg.conf 选项 AUTOCLEAN
设置为 true
。我发现自动清理过于激进,因为有时升级包中的新错误会迫使我恢复到旧版本。我们将在本章末尾介绍升级包。
您可能希望包缓存位于文件系统的其他位置。使用 pkg.conf 选项 PKG_CACHEDIR
设置新的包缓存目录。
为什么要移动缓存目录?许多服务器场在多台机器上共享一个包缓存。您可以在运行相同FreeBSD主要版本和硬件架构的主机之间安全地共享包缓存。验证您的NFS配置是否使用锁定,并设置 pkg.conf 选项 NFS_WITH_PROPER_LOCKING
。
过了一段时间,你会忘记在系统上安装了哪些软件包。使用 pkg info
获取已安装软件的完整列表。
xxxxxxxxxx
# pkg info
gettext-runtime-0.19.8.1_1 GNU gettext runtime libraries and programs
indexinfo-0.2.6 Utility to regenerate the GNU info page index
--snip--
如果您想了解有关已安装软件包的更多信息,请使用 pkg info
和软件包名称。这将在人性化的报告中显示包清单和安装详细信息。
xxxxxxxxxx
# pkg info apache24
apache24-2.4.25_1
Name : apache24
Version : 2.4.25_1
Installed on : Tue Mar 14 16:56:14 2017 EDT
Origin : www/apache24
Architecture : freebsd:12:x86:64
--snip--
该软件包是什么时候安装的?此计算机上安装的软件包是否基于端口树构建,并启用了某些选项?许可证是什么?软件包中的每个程序都需要哪些共享库?使用 pkg info
和包名称回答所有这些问题以及更多问题。
pkg info
子命令还有许多其他功能。我们将在本章稍后看到其中的一些,例如锁定状态。pkg-info(8)
手册页提供了完整的详细信息。
回头看看示例 pkg info
输出。我故意在这个系统上安装了一些不同的程序,但我很确定我从来没有故意安装过任何关于GNU信息页或gettext的东西。
我安装了这些程序。我只是没有太注意它们是什么,因为我更关心的是安装需要它们的软件包。它们是依赖关系。
FreeBSD记录您是请求安装软件包还是将其作为依赖项带来。作为依赖项安装的包称为automatic (自动)包。您请求的包只是包,尽管它们有时被称为nonautomatic (非自动)包。
您可能想知道您请求安装哪些包,以及哪些包作为依赖项被拖动。这就是事情变得棘手的时候。
pkg工具无法覆盖系统管理员可能面临的所有可能的意外情况。获取某些信息的最简单方法是查询已安装的软件包数据库。虽然你可以使用原始SQLite,但这意味着你需要熟悉数据库的内部。大多数系统管理员没有这样的时间,尤其是当数据库可能随时更改时。FreeBSD通过 pkg query
子命令与之隔离。对包查询的完整调查将填满一章,但这里有一个快速概述。
远程查询
使用 pkg-query(8)
搜索已安装软件包的数据库。不过,如果存储库中可用的软件包数据库是最新的,则可以使用 pkg-rquery(8)
进行搜索。然而,可用包的数据库并不包含已安装包的所有元数据,因此并非所有模式都可用。
您可能想从包数据库中获取的任何内容都可以在 pkg query
中方便地表示出来。问题是,正如快速阅读 pkg query(8)
所示,任何人都可能不想从包数据库中提取的东西都在 pkg query
中。查询和命令结构是专门为在脚本中使用而设计的,但我们偶尔会交互式地使用它。
使用patterns(模式)运行查询。模式是一个具有指定含义的变量,由百分号和字母表示。例如,%n
包含包名称(name),%o
包含构建包的端口(port),%t
包含指示包安装时间的时间戳(timestamp)。
运行 pkg query
并给出模式会为每个已安装的包生成该值。由于 %n
代表包名称,因此您可以通过以下方式获取系统上所有内容的列表:
xxxxxxxxxx
# pkg query %n
apache24
apr
--snip--
我们没有得到 pkg info
显示的额外信息,但也许这就是你想要的。
您可以在单个查询中请求多个项目。%v
模式表示包版本(version),而 %c
表示注释(comment)。在这里,我用破折号分隔包名和版本,但在版本和注释之间放一个标签。使用shell选项卡字符 \t
意味着我必须引用 pkg query
参数。
xxxxxxxxxx
# pkg query "%n-%v\t%c"
apache24-2.4.25_1 Version 2.4.x of Apache web server
apr-1.5.2.1.5.4_2 Apache Portability Library
--snip--
你知道,这看起来很像 pkg info
的输出。当pkg命令查询或操作包数据库时,它使用这些完全相同的模式。您对打包系统的可见性与其他工具相同。
如果要获取特定包的模式,请将包名作为最后一个参数。在这里,我得到apache24包来自的port:
xxxxxxxxxx
# pkg query %o apache24
www/apache24
然而,在询问所有包裹和特定包裹之间,我们确实有一个中间地带。
这是最后一个漂亮的包查询功能。许多(不是全部,而是许多)模式都可以作为变量使用。命令可以评估这些变量,并根据结果采取行动。使用 -e
命令行选项使用逻辑运算符计算变量。逻辑运算符的完整列表出现在 pkg-query(8)
中。
评估分为“如果这是真的,就这样做”。测试在引号内。这里有一个例子:
xxxxxxxxxx
# pkg query -e '%a = 0' %n
此查询将遍历已安装软件包的整个列表。-e
表示我们正在为每个包计算一个变量。引号内的语句 %a=0
表示我们正在测试该包中 %a
的值。如果 %a
等于0 ,则查询计算结果为true,pkg query
打印出 %n
的内容。如果 %a
为除0之外的任何值,则语句为false,pkg query
继续执行下一个包而不做任何操作。
我们已经知道 %n
包含包名称。变量 %a
包含pkg关于软件包是否自动安装的记录。如果您请求了此特定包,则将其设置为0。如果一个包最初是作为依赖项安装的,则将其设置为1。所以:如果包不是依赖项,请打印名称。此查询打印非自动包。
xxxxxxxxxx
# pkg query -e '%a = 0' %n
apache24
dmidecode
pkg
youtube_dl
这里有几件事很突出。首先,我没有故意让pkg安装 pkg(8)
。我请求dmidecode,pkg自行引导。不过,pkg套件本身一直被认为是一个非自动软件包。
第二:谁在这个盒子上安装了youtube_dl?
要找出哪些包是作为依赖项安装的,请评估 %a
是否设置为1。
=还是==?
您将看到使用双等号的示例,就像 pkg query
是一种编程语言一样。我的例子使用了一个等号。当然,这两个等号和你应该使用的特殊条件之间有一些微妙的区别吗?
不!
你可以根据肌肉记忆的喜好使用单等号或双等号。
不过,实际上,我不会费心记住如何在所有主机上运行此查询。我需要一个简单的方法让 pkg(8)
为我记住它。
您可以在 pkg.conf 中为pkg子命令定义别名。这允许您创建别名来显示自动和非自动命令。我可以在我的shell中做类似的事情,但它不会显示为 pkg(8)
子命令,我很容易混淆。
在 pkg.conf 的底部,您会发现一个标记为 ALIAS
的部分。
xxxxxxxxxx
ALIAS : {
all-depends: query %dn-%dv,
annotations: info -A,
--snip--
}
别名是别名的单个单词,可以是冒号或等号,然后是要运行的pkg命令。如果运行 pkg all-depends
,pkg(8)
会在 pkg.conf 中查找并运行 pkg query %dn-%dv
。每个别名都以冒号结尾,表示别名列表在下一行继续。
默认配置中的许多别名代表了为我们这些老用户创建的pkg_add aeon的遗留问题。不过,现有的别名是查找示例查询和搜索的好地方。在别名中搜索会发现这个很好的条目:
xxxxxxxxxx
noauto = "query -e '%a == 0' '%n-%v'",
这个别名 noauto 运行一个 pkg query
命令来计算 %a
,如果包的名称和版本号为0,则打印出来。它打印未自动安装的软件包。我添加了一个非常相似的别名来打印自动包裹。
xxxxxxxxxx
auto = "query -e '%a == 1' '%n-%v'",
当您发现自己反复运行复杂的命令时,请添加别名。
我们都安装了软件,结果却厌恶地把它撕了出来。唯一的区别是,究竟是什么让我们反感。使用 pkg delete
子命令卸载软件包。它也可以作为 pkg remove
使用。那个无关的youtube_dl包?让我们把它从系统中删除。
xxxxxxxxxx
# pkg delete youtube_dl
Checking integrity... done (0 conflicting)
移除过程确保包没有发生任何可怕的事情,没有其他人需要它,并且它的移除不会造成包系统可以预测的可怕事情。
然后,您将获得要删除的包的列表以及它们将释放多少空间。最后是说不的最后机会。
xxxxxxxxxx
Proceed with deinstalling packages? [Y/n]: y
[1/1] Deinstalling youtube_dl-2017.02.11...
[1/1] Deleting files for youtube_dl-2017.02.11: 100%
该包已从您的系统中删除。
如果你删除了其他包所依赖的包,pkg也会删除依赖的包。
xxxxxxxxxx
# pkg delete trousers
--snip--
Installed packages to be REMOVED:
trousers-0.3.14_1
gnutls-3.5.9
emacs-nox11-25.1,3
--snip--
gnutls包需要trousers,emacs-nox11需要gnutls。卸载trousers会破坏这两者,所以pkg认为你显然也不希望它们出现在你的系统中。
如果你真的想删除其他包所依赖的包,请添加 -f
标志。
请非常仔细阅读 pkg delete
的警告!
在主机上安装不必要的软件会增加安全风险和系统管理员的工作量。在长时间运行的系统中,您并不总是知道要删除哪些软件。删除您选择安装的软件很容易,但该软件可能带来了您从未真正注意过的依赖关系。或者,新版本的软件包的依赖关系可能比上一版本少或不同。
我从测试系统中删除了youtube_dl包。这给我留下了我故意安装的其他软件包及其依赖关系。它还留下了youtube_dl所依赖的包,但其他什么都不需要。pkg autoremove
子命令标识作为依赖项安装但不再被任何其他包需要的包。它提出删除这些不再需要的内容。我强烈建议在删除不必要的依赖关系之前进行一次模拟运行,只是为了让你虚弱的人脑有机会看两次列表。
xxxxxxxxxx
# pkg autoremove
pkg运行数据库查询以识别不需要的依赖关系,并建议将其删除。
xxxxxxxxxx
Installed packages to be REMOVED:
python27-2.7.13_1
readline-6.3.8
rtmpdump-2.4.20151223
librtmp-2.4.20151223
--snip--
仔细研究这份清单。一个未打包的软件需要一个从其他地方带来的包,这并不罕见。如果没有youtube_dl,你可能不需要视频处理工具rtmpdump和librtmp,但很多软件都需要Python解释器。你真的想把它吹走吗?
如果你真的可以删除所有这些包,请回答 y
并继续。不过,如果其中一个依赖关系变得至关重要,请更改数据库以告知它。
想在 pkg(8)
之外更改包数据库吗?不要。你只会给自己带来痛苦,你寻求帮助的请求要么会遭到嘲笑,要么会被建议扔掉所有包裹重新开始。
不过,在某些情况下,pkg(8)
支持更改包数据库。这时你就可以使用 pkg set
了。 pkg-set(8)
子命令允许您在不损坏数据的情况下正确调整数据库中的一些合理值。最常见的是当你想让自动包装不再自动时。
pkg set
的 -A
标志允许您更改包的自动设置。将此标志设置为1表示该包作为依赖项自动安装,而0表示该包是用户特别请求的。
在上一节中,pkg autoremove
要删除的四个包的列表包括Python。我想保留Python——不仅是这次,而且将来任何时候我都可以执行自动删除。实现这一点的简单方法是将Python从自动更改为非自动。
xxxxxxxxxx
# pkg set -A 0 python27
Mark python27-2.7.13_1 as not automatically installed? [Y/n]: y
Python现在是一个非自动包。pkg autoremove
的结果现在看起来不同了。
xxxxxxxxxx
# pkg autoremove -n
--snip--
Installed packages to be REMOVED:
rtmpdump-2.4.20151223
librtmp-2.4.20151223
--snip--
只有两个包,而不是四个?显然Python需要readline。我很高兴pkg为我找到了答案,因为我懒得去记住它。
我们将根据需要对 pkg set
进行更多介绍。
有些软件就像地铁的电气化轨道。触摸它会导致痛苦或死亡。
我最喜欢的例子是远程文件同步程序 rsync(8)
。Rsync已经存在了几十年,其内部协议也随着时间的推移而发生了变化。许多嵌入式和传统系统都使用rsync,但它从未升级过。我花了很多痛苦的时间调试为什么当前的rsync无法与20世纪嵌入式电话开关控制器上的rsync通信。事实证明,rsync点版本放弃了对电话交换机支持的非常旧的协议的支持。升级手机交换机是不可能的,所以我需要主机上的rsync软件包才能永远升级。绝不。
这就是锁定包的地方。
锁定软件包时,pkg不会对其进行升级、降级、卸载或重新安装。它对软件包的依赖关系及其所依赖的程序应用相同的规则。负责获取锁定rsync软件包所需的电话交换机文件的主机。使用 pkg lock
锁定包。
xxxxxxxxxx
# pkg lock rsync
rsync-3.1.2_6: lock this package? [Y/n]: y
Locking rsync-3.1.2_6
这个包现在已经钉好了。
要显示系统上所有锁定的包,请使用 -l
标志。这只显示了您故意锁定的包,而不是被依赖项(dependents)或依赖项(dependencies)。
xxxxxxxxxx
# pkg lock -l
Currently locked packages:
rsync-3.1.2_6
使用 pkg unlock
命令解除锁。
xxxxxxxxxx
# pkg unlock rsync
rsync-3.1.2_6: unlock this package? [Y/n]: y
Unlocking rsync-3.1.2_6
要锁定或解锁系统上的所有包,请使用 -a
标志。您将收到每个包的确认提示,因此如果您真的想影响所有包,请添加 -y
标志。
xxxxxxxxxx
# pkg unlock -a
apache24-2.4.25_1: already unlocked
apr-1.5.2.1.5.4_2: already unlocked
--snip--
rsync-3.1.2_6: unlock this package? [Y/n]: y
Unlocking rsync-3.1.2_6
--snip--
包锁定并不能阻止具有root访问权限的人篡改包中包含的文件。
与此相关的是,第22章涵盖了使用监狱来容纳非常旧的软件。
由软件包安装的文件被视为系统文件,您不应该手动编辑它们。在编辑这些文件之前,您必须知道软件包附带了哪些文件。使用 pkg info l
和包名查看完整列表。(由于 pkg.conf 别名,它也可以作为 pkg list
使用。)
xxxxxxxxxx
# pkg info -l rsync
rsync-3.1.2_6:
/usr/local/bin/rsync
/usr/local/etc/rc.d/rsyncd
/usr/local/etc/rsync/rsyncd.conf.sample
--snip--
另一种可能性是,您想知道文件来自哪个包。使用 pkg white
命令。当我发现一个奇怪的图书馆并想知道它从哪里来时,我通常会使用这个。
xxxxxxxxxx
# pkg which libp11-kit.so
/usr/local/lib/libp11-kit.so was installed by package p11-kit-0.23.5
我现在的问题是,“什么是p11试剂盒?”但这是进步。
虽然你不应该更改包文件,但最终会有人这样做。您可以使用pkg来发现这些更改并撤消损坏。
pkg-check(8)
工具包括用于识别包损坏和包依赖关系的功能。开发人员还可以使用 pkg-check(8)
来检查从ports构建并分发给最终用户的捆绑包,但这是一个完全独立的问题。
使用 pkg check -s
和包名称验证包的文件是否未更改。当我锁定的rsync包停止从挑剔的远程服务器同步文件时,我验证的一件事是包的完整性。
xxxxxxxxxx
# pkg check -s rsync
Checking rsync: 0%
rsync-3.1.2_6: checksum mismatch for /usr/local/bin/rsync
Checking rsync: 100%
磁盘出现故障,或者有人篡改了我的 rsync(1)
二进制文件。由于这个系统使用了自我修复的ZFS,所以会有一场戏。
您可以卸载并重新安装该软件包,但这可能会触发更改,具体取决于哪些软件包需要您更新的软件包。此外,如前所述,这个特殊的包是特殊的。我不希望pkg将软件包升级到最新版本。相反,我想强制pkg从包缓存中重新安装当前的包。使用 -f
标志运行 pkg install
。在更新存储库数据库的同时,它会重新安装缓存的包。如果包裹已锁定,您必须先解锁。
xxxxxxxxxx
# pkg unlock -y rsync
Unlocking rsync-3.1.2_6
# pkg install -fy rsync
--snip--
[1/1] Reinstalling rsync-3.1.2_6...
[1/1] Extracting rsync-3.1.2_6: 100%
# pkg lock -y rsync
我珍贵的rsync恢复了。
通过运行 pkg check -saq
检查所有软件包的完整性。除非有什么变化,否则它不会产生任何输出,所以你可以通过cron来安排它(见第20章)。
如果有人真的尝试了,他们可以删除其他包所依赖的包。使用 pkg check
的 -d
标志来识别和修复缺失的依赖关系。
xxxxxxxxxx
# pkg check -d emacs-nox11
Checking emacs-nox11: 100%
emacs-nox11 has a missing dependency: gnutls
emacs-nox11 is missing a required shared library: ➊libgnutls.so.30
--snip--
>>> Try to fix the missing dependencies? [Y/n]: y
首先要注意的是,当 pkg check
识别出缺少的依赖关系时,它会尝试纠正它。在提示符处回答y以重新安装依赖关系。
请注意,此 pkg check
运行向我们显示了一个缺失的库libgnutls.so.30➊。依赖性检查实际上并没有搜索所有包中的所有文件。它知道这个库不见了,只是因为包含它的包不见了。如果手动删除库,依赖性检查将找不到它。您需要像以前一样检查包文件的完整性。
如果你想用 pkg check -d
检查所有包依赖关系,不要给它一个包名。您可以添加 -a
来显式检查所有包,但这不是必需的。如果添加 -q
标志,则此命令仅在发现问题时才产生输出。添加 -q
还告诉 pkg check
尝试解决它发现的任何依赖性问题,而无需用户干预。
这种组合意味着,虽然我可以将此检查作为计划作业运行,但我对主机重新安装缺失的依赖关系不太满意。在自动化依赖关系更正之前,请考虑一下您的系统在没有注意的情况下安装软件包。
pkg check
子命令还包括其他几个有用的选项,例如 -B
用于重建共享库依赖关系,-r
用于手动重新计算已安装包的校验和。阅读 pkg-check(8)
了解详细信息。
该软件包系统包括几个维护脚本,这些脚本旨在从 periodic(8)
开始运行。在 /etc/periodic.conf 中启用这些,如第20章所述。每个都会添加到每日、每周或安全状态电子邮件中。
要使用 pkg check -saq
进行日常维护检查包校验和替换损坏的包,请将 daily_status_security_pkg_checksum_enable
设置为 YES
。
要确定已安装的软件包是否存在FreeBSD软件包安全系统中发布的安全漏洞,如第19章所述,请将 daily_status_security_pkgaudit_enable
设置为 YES
。
如果您希望FreeBSD每天备份已安装的软件包和软件包数据库,请将 daily_backup_pkg_enable
设置为 YES
。
要收到已安装软件包更改的通知,请将 daily_status_pkg_changes_enable
设置为 YES
。
最后,您可以通过将 weekly_status _pkg_enable
设置为 YES
来每周检查过时的软件包。
FreeBSD的软件包系统设计用于连接到互联网的正常网络。这是一个残酷的笑话,因为没有网络是正常的。您可以调整pkg的行为以适应您的网络。
最常见的变化是需要代理服务器。pkg使用 fetch(3)
下载包文件,它通过环境变量进行任何特殊的网络配置。在 pkg.conf 的 PKG_ENV
部分设置环境变量。每个变量都需要变量名、冒号和值。在这里,我将 HTTP_PROXY
环境变量设置为我的网络代理:
xxxxxxxxxx
pkg_env : {
HTTP_PROXY: "http://proxy.mwl.io/"
}
有关代理环境设置的完整列表,请参阅 fetch(3)
。
一些网络为不同的网络堆栈提供单独的带宽。我使用过不止一个IPv6连接比IPv4更好的网络,或者相反。通过 pkg.conf 中的 IP_VERSION
设置,指示pkg使用一种或另一种网络协议。您可以将其设置为4、6,或让主机自动选择默认值0。
最后,pkg.conf NAMESERVER
设置允许您覆盖 /etc/resolv.conf 中给出的名称服务器。在此处输入IPv4或IPv6地址。您可以在此处使用主机名,但pkg将使用默认的系统名称服务器查找该主机名。
您可能希望使用FreeBSD项目提供的包以外的包。也许你构建了自己的包,如第16章所述。也许您可以访问一个实验包存储库。或者,你可能想切换你正在使用的官方软件包。
pkg支持包repositories(存储库)或repos,它们是包的命名集合。您可以添加、删除、启用和禁用存储库。
普通的存储库非常简单,但在极少数情况下,它们可能会变得非常复杂。我们不会深入到配置自己的存储库的边缘案例,但基础知识会让你走得很远。
在各自的文件中配置每个存储库。FreeBSD官方存储库位于 /etc/pkg 中。以UCL格式配置存储库(见第2章)。FreeBSD附带了启用FreeBSD的仓库。您可以在 /etc/pkg/FreeBSD.conf 中找到配置文件。
xxxxxxxxxx
FreeBSD: {
➊ url: "pkg+http://pkg.FreeBSD.org/${ABI}/quarterly",
➋ mirror_type: "srv",
➌ signature_type: "fingerprints",
➍ fingerprints: "/usr/share/keys/pkg",
➎ enabled: yes
}
这个名为 FreeBSD 的仓库支持FreeBSD仓库。当你决定建立自己的存储库时,给它一个有意义的名称。
mirror_type
条目➋告诉pkg此存储库是否托管在普通网站上。将 mirror_type
设置为 NONE
后,就可以告诉pkg使用fetch来获取使用标准网络方法的软件包,如HTTP、FTP,甚至文件路径。
数以百万计的机器运行FreeBSD,需要访问包存储库。单个web服务器无法跟上。通过将 mirror_type
设置为 srv
,您可以告诉pkg检查DNS中的SRV记录。SRV记录用于指导高可用性服务,如VoIP和Active Directory。
url
条目➊显示了可以找到此存储库的互联网站点。我相信你以前见过http URL,但这个pkg+http的东西呢?它将请求与用于引导pkg请求的SRV记录联系起来,如 mirror_type
所设置的。
包系统可以使用公钥或加密哈希指纹验证下载的包➌。不过,您需要告诉pkg在哪里可以找到密钥或哈希➍。
最后,您必须明确启用或禁用➎每个存储库。
您可以根据需要添加和删除存储库。由于 /etc/pkg 是为FreeBSD官方存储库保留的,因此您需要另一个目录。传统的位置是 /usr/local/etc/pkg/repos 。如果你想使用其他目录,你需要在 pkg.conf 中用 REPO_DIRS
选项设置一个位置。您将看到默认值的注释示例。
xxxxxxxxxx
#REPOS_DIR [
# "/etc/pkg/",
# "/usr/local/etc/pkg/repos/",
#]
默认情况下,本地存储库目录不存在,因此您需要创建它。
xxxxxxxxxx
# mkdir -p /usr/local/pkg/repos
将您自己的存储库配置放在该目录中。
FreeBSD按目录顺序搜索包,按 REPOS_DIR
中给出的顺序检查目录。这显然意味着默认的FreeBSD仓库不能被禁用或覆盖。这并不完全正确,但原因有点棘手。
您可以将存储库的配置拆分为多个文件。后面文件中的条目会覆盖前面文件中的条目的内容。
要了解其工作原理,请考虑名为 FreeBSD 的默认存储库。如果您在 /usr/local/etc/pkg/repos 中配置了所有自定义存储库,pkg会首先找到FreeBSD存储库。
但现在创建一个 /usr/local/etc/pkg/repos/FreeBSD.conf 文件。在那里定义FreeBSD仓库,但只包含一个配置语句。
xxxxxxxxxx
FreeBSD: { enabled: no }
pkg首先在 /etc/pkg/FreeBSD.conf 中找到名为FreeBSD的存储库。此配置定义了此存储库的默认值。稍后将找到第二个配置。第二种配置仅覆盖一个选项,但该选项会关闭存储库。
虽然对于不运行自己的存储库的人来说,禁用FreeBSD存储库是一个极端的情况,但我们有充分的理由对存储库进行细微的更改,我们将在下面看到。
FreeBSD的软件包是从Ports Collection构建的(见第16章)。Ports Collection试图将数以万计的不同软件套件引入FreeBSD。这些不同的程序都有自己的发布时间表,Ports Collection不断发展以跟上它们的步伐。正如你所想象的,Ports Collection有很多客户流失。我们大多数运行服务器的人都希望稳定。当大多数系统管理员考虑stability(稳定性)时,他们不会想到 churn (流失)这个词。
我们大多数人不需要服务器上的最新软件。大多数时候,如果我的数据库服务器落后一两个小版本,我也没问题;我只关心它是否继续工作。我当然不会仅仅因为MySQL、nginx或PHP有新的软件版本就升级我的服务器。这就是不断升级的疯狂之处。
然而,我确实希望获得安全性和稳定性的更新。数据库服务器稍微老一点并没有让我感到困扰。数据库服务器偶尔会失去理智,把我所有的数据都发送到比特桶,或者把所有的东西都提供给底特律的黑客团队,这让我非常困扰。
FreeBSD软件包系统的 quarterly branches (季度分支)试图在世界上不断变化的软件和系统管理员的安心之间找到一个中间地带。每年一月、四月、七月和十月,Ports工作人员都会将Ports Collection分成季度分支。季度分支机构只收到安全和稳定性更新,而主要的Ports Collection则愉快地提前收费。
FreeBSD项目为每个版本构建两组包。quarterly (季度)包是根据季度Ports Collection构建的。latest 的软件包是从最前沿的软件包构建而来的。
尽管客户流失,但你们中的一些人更喜欢最新的套餐。没关系。切换很简单。您只需要覆盖FreeBSD存储库中的一个条目。创建一个新的存储库文件 /usr/local/etc/pkg/rerepos/FreeBSD.conf ,就像上一节一样。不过,我们将覆盖包源代码,而不是禁用默认存储库。将“quarterly”和URL末尾更改为“latest”。
xxxxxxxxxx
FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest" }
欢迎加入我们!
强烈建议在更改存储库后运行 pkg update -f
,以强制pkg下载最新的存储库目录。
切换包集合并不一定意味着您需要重新安装所有内容。如果你的旧软件包正常工作,就使用它们。不过,如果出现奇怪的问题,请使用 pkg upgrade -fa
之类的命令重新安装所有软件包。即使是与其他软件包集合中版本相同的软件包也可能略有不同。
尽管我们可能希望情况并非如此,但你不能设置一个新系统并忽略它。要么是出现了稳定性漏洞,要么是某个聪明的混蛋发现了安全漏洞。(第19章讨论了审计包安全。)有时您必须升级第三方软件。使用FreeBSD的原始打包系统pkg_add,包升级可能会带来一定程度的心痛。使用 pkg(8)
,你仍然有心痛的风险,但这是来自软件的新版本,而不是打包系统本身。
在升级软件包之前,请备份您的系统。然后,使用 upgrade
子命令让 pkg(8)
升级所有软件包。我建议先用 -n
进行模拟运行。
xxxxxxxxxx
# pkg upgrade -n
--snip--
Checking for upgrades (2 candidates): 100%
Processing candidates (2 candidates): 100%
The following 1 package(s) will be affected (of 0 checked):
Installed packages to be UPGRADED:
ca_root_nss: 3.29.1 -> 3.29.3
Number of packages to be upgraded: 1
335 KiB to be downloaded.
仔细查看要升级的软件包列表。有大的跳跃吗?你需要查看任何发布说明吗?这可能会有多大的侵扰性?升级是否删除了您想要的任何软件包,如 X.org 或您的文本编辑器?你应该等到星期天凌晨3点,让你的孩子做这件事吗?研究升级并考虑每个软件包升级的风险可能不会减少你需要做的工作量,但会减少停机时间和人们对你大喊大叫的时间。
一旦你对即将发生的变化感到满意,就运行升级。
xxxxxxxxxx
# pkg upgrade -y
您将看到关于要升级的软件包的非常相似的消息,然后是下载和安装过程的通知。最后,pkg显示每个升级包的安装消息。
即使是世界上最灵活的包装系统也不会总是满足您的需求。FreeBSD通过Ports Collection使定制附加软件变得非常容易,我们接下来将介绍Ports Collection。