Gentoo Linux ppc64 手册:使用Gentoo

From Gentoo Wiki
Jump to:navigation Jump to:search
This page is a translated version of the page Handbook:PPC64/Full/Working and the translation is 100% complete.



欢迎使用 Portage

Portage 系统是 Gentoo 在软件管理方面最显著的创新之一。由于 Portage 的高度灵活性和数量庞大的特性,它时常被誉为 Linux 下最好的软件管理工具。

Portage 是用 PythonBash 两种语言编写的。因为它们都是脚本语言所以用户可以直接阅读它的代码。

大多数用户通过 emerge 使用 Portage。本章的内容不是复述 emerge 的 man page。要了解 emerge 的所有可用选项,请查阅 emerge 的 man page:

user $man emerge

Gentoo 软件仓库

Ebuilds

当 Gentoo 的文档介绍某个软件包的时候,这意味着 Gentoo 的用户们可以在 Gentoo 的软件仓库里找到它。ebuild 是一种包含了所有 Portage 维护软件(比如安装,搜索,查询等等)所需信息的文件,而 Gentoo 的软件仓库是它们的一个集合。这些 ebuild 文件默认储存在 /var/db/repos/gentoo

Portage 对于软件的行为都是基于本地的 ebuild。为了能收到新的软件包,安全更新等等,时常更新本地 ebuild 是一件很重要的事情。

更新 Gentoo 软件仓库

Gentoo 的软件仓库通常使用 rsync 进行同步,rsync 是一个快速的文件增量传输工具。要使用它很简单,Portage 的命令行前端 emerge 提供了一个调用 rsync 的方法:

root #emerge --sync

有时防火墙会干扰 rsync 与镜像的连接。这时,我们可以使用 emerge-webrsync 来自动下载和安装 Portage 树的快照版本:

root #emerge-webrsync

维护软件

搜索软件

有很多方法可以在 Gentoo 的软件仓库寻找软件。其中之一是使用 emerge 本身。在默认情况下 emerge --search 会返回所有符合搜索条件的包名。

举个例子,找出所有名字里含有 “pdf” 的包:

user $emerge --search pdf

如果要根据描述进行搜索,可以使用 --searchdesc (或 -S)选项:

user $emerge --searchdesc pdf

需要注意的是它会输出很多信息。不过由于都有很清楚的标识,我们就不再赘述它们的意思了:

代码 搜索命令的输出样例
*  net-print/cups-pdf
      Latest version available: 1.5.2
      Latest version installed: [Not Installed]
      Size of downloaded files: 15 kB
      Homepage:    http://cip.physik.uni-wuerzburg.de/~vrbehr/cups-pdf/
      Description: Provides a virtual printer for CUPS to produce PDF files.
      License:     GPL-2

安装软件

当你找到了软件包的名字,安装它只需要简单得使用 emerge。举个例子,如果要安装 gnumeric:

root #emerge --ask app-office/gnumeric

由于很多软件依赖其它的软件,在安装该软件的同时很可能还会安装它的一些以来。不要担心,Portage 可以很好地处理依赖关系。如果要知道 Portage 会安装什么软件,可以在命令中加入 --pretend 选项。举个例子:

root #emerge --pretend gnumeric

To do the same, but interactively choose whether or not to proceed with the installation, add the --ask flag:

root #emerge --ask gnumeric

在安装软件期间,Portage将从Internet下载必要的源代码(如果需要),并将其默认存储在 /var/cache/distfiles/中。 之后,它将解压缩,编译和安装包。 要让Portage仅下载源代码而不安装软件,请添加--fetchonly选项到emerge命令:

root #emerge --fetchonly gnumeric

查找已安装软件的文档

许多软件包中包含有自己的文档,有些时候,doc的USE标记决定了软件包中的自带文档是否会被安装。您可以通过 emerge -vp category/包,名命令来检查是否存在doc USE 标志:

root #emerge -vp media-libs/alsa-lib
These are the packages that would be merged, in order:
 
Calculating dependencies... done!
[ebuild   R    ] media-libs/alsa-lib-1.1.3::gentoo  USE="python -alisp -debug -doc" ABI_X86="(64) -32 (-x32)" PYTHON_TARGETS="python2_7" 0 KiB

最好的启用 doc USE 的方式是在 /etc/portage/package.use里对想要启用的包单独启用,这样你就能只获得你想要的软件文档。了解更多信息请阅读 USE flags chapter

当一个软件包安装结束后,它的文档通常会存放在/usr/share/doc/目录下的,以软件包名命名的子目录中:

user $ls -l /usr/share/doc/alsa-lib-1.1.3
total 16
-rw-r--r-- 1 root root 3098 Mar  9 15:36 asoundrc.txt.bz2
-rw-r--r-- 1 root root  672 Mar  9 15:36 ChangeLog.bz2
-rw-r--r-- 1 root root 1083 Mar  9 15:36 NOTES.bz2
-rw-r--r-- 1 root root  220 Mar  9 15:36 TODO.bz2

列出已安装文档文件的更可靠方法是使用 equery--filter 选项。 equery 用于查询Portage的数据库,并作为 app-portage/gentoolkit 包的一部分:

user $equery files --filter=doc alsa-lib
 * Searching for alsa-lib in media-libs ...
 * Contents of media-libs/alsa-lib-1.1.3:
/usr/share/doc/alsa-lib-1.1.3/ChangeLog.bz2
/usr/share/doc/alsa-lib-1.1.3/NOTES.bz2
/usr/share/doc/alsa-lib-1.1.3/TODO.bz2
/usr/share/doc/alsa-lib-1.1.3/asoundrc.txt.bz2

--filter 选项可与其他规则一起使用,以查看许多其他类型文件的安装位置。可以在 equery 的手册中查看其他功能: man 1 equery

移除软件

当您想把一个软件包从系统中安全地移除的时候,使用 emerge --deselect 命令。它将告诉 Portage 有一个软件包不需要了,并且有可以通过 --depclean 清理。

root #emerge --deselect gnumeric

当不需要一个软件包时,之前那些为了满足其依赖关系而被自动安装的软件包将会被保留在系统中。要使 Portage 找到现在可以删除的所有依赖项,可以使用 --depclean 功能。稍后我们将介绍这一点。

更新系统

要保持您的系统在最佳状态(更不用说安装那些最新的安全更新),您需要定期的更新您的系统。由于Portage只能检查本地已有文件,因此您首先应该更新您的Portage树。当您的Portage树更新后,您可以用 emerge --update @world命令来更新系统。在下一个例子里,我们还会使用 --ask 选项来控制Portage显示它要更新的软件包列表, 并让您决定是否继续更新。

Portage将搜索已安装的程序的新版本。 然而,它只会验证明确安装的应用程序(在 /var/lib/portage/world 列出的应用程序)的版本,却不会检查它们的依赖项。若要更新这些包的依赖项,请添加 --deep 选项:

root #emerge --update --deep @world

每当您改变了系统中任何的 USE 标记后,最好加入 --newuse 选项。这样 Portage 将会验证这个 USE 标记变动后,是否需要安装新的软件包或者将现有的软件包重新编译。

root #emerge --update --deep --newuse @world

元软件包

Gentoo中的一些软件包并没有包含任何实际的内容,而只是用来安装一系列软件包的集合。例如,kde-plasma/plasma-meta 包就是一个包含了一系列与Plasma相关的互相依赖的软件包的集合,您可以通过安装它来在系统中搭建起一个完整的KDE Plasma 桌面环境。

如果您试图从系统中移除一个这样的软件包的集合体,只是单纯地使用 emerge --deselect 命令并不能完成您的要求,原因在于这些包的依赖关系仍然保留在系统中。

不用担心,Portage也提供了移除孤立依赖的软件包的功能,但由于软件包间的依赖关系是动态的,您首先需要充分地更新您的整个系统,包括更改USE标记设定而导致的变化。在这之后您可以运行emerge --depclean来移除那些完全没有被其他包依赖的软件包。移除之后你需要重新编译那些曾经与刚刚移除的这些包动态连接过的应用程序,因为实际上这些程序不需要那些包。

所有这些可以用以下两个命令来实现:

root #emerge --update --deep --newuse @world
root #emerge --ask --depclean

许可证

从 Portage 2.1.7 版本开始,可以根据其许可证接受或拒绝安装软件。portage 树中的所有包在其ebuild中包含一个 LICENSE 选项。 运行 emerge --search category/package 将显示软件包的许可证。

重要
ebuild 中 的 LICENSE 变量仅是为 Gentoo 开发人员和用户准备的一份指南。它既不是法律声明,也不保证其真实性。因此不要过度依赖它,您需要深入检查软件包的本身,以及您使用的所有文件。

If a discrepancies is found in the ebuild, please file a bug to suggest a change to the value(s) assigned to the ebuild's LICENSE variable.}}

默认情况下,Portage允许自由软件基金会开源计划或遵循自由软件定义明确批准的许可。

控制允许的许可证的变量称为ACCEPT_LICENSE,可以在/etc/portage/make.conf文件中设置。 在下一个示例中,将显示他的默认值:

文件 /etc/portage/make.conf默认 ACCEPT_LICENSE 设定
ACCEPT_LICENSE="-* @FREE"

使用此配置,可以安装具有自由软件或文档许可证的软件包。非自由软件将无法安装。

可以在ACCEPT_LICENSE中全局设置t ACCEPT_LICENSE,或者在/etc/portage/package.license 文进行配置。

举个例子,要允许www-client/google-chrome 包的google-chrome的授权协议, 把下面的内容添加到 /etc/portage/package.license:

文件 /etc/portage/package.license接受www-client/google-chrome 包的 google-chrome 的授权协议
www-client/google-chrome google-chrome

这允许安装www-client/google-chrome 程序包,但禁止安装www-plugins/chrome-binary-plugins 程序包,即使它具有相同的 授权协议。

Or to allow the often-needed sys-kernel/linux-firmware:

文件 /etc/portage/package.licenseAccepting the licenses for the linux-firmware package
# Accepting the license for linux-firmware
sys-kernel/linux-firmware linux-fw-redistributable
</div>

<div lang="en" dir="ltr" class="mw-content-ltr">
# Accepting any license that permits redistribution
sys-kernel/linux-firmware @BINARY-REDISTRIBUTABLE
重要
授权协议存储在 /var/db/repos/gentoo/licenses/ ,授权协议组在/var/db/repos/gentoo/profiles/license_groups 里面。CAPITAL字母中每行的第一个条目是许可证组的名称,之后的每个条目都是单独的许可证。

ACCEPT_LICENSE 变量中定义的许可证组前缀为@ 符号。一种可能的设置(以前的Portage默认设置),是允许除“最终用户许可协议(EULA)”以外所有的许可证,“最终用户许可协议(EULA)”中的许可证需要阅读并签署接受协议。要完成此操作,请接受所有许可证(使用*),然后删除EULA组中的许可证,如下所示:

文件 /etc/portage/make.conf接受除EULA外的所有许可证
ACCEPT_LICENSE="* -@EULA"

请注意,此设置也将接受非自由软件和文档。

当 Portage 报错的时候

术语

正如我们之前指出的那样,Portage是一个非常强大并支持许多特性的软件包管理工具,而这是其他类似工具所欠缺的。为了理解这一点,我们为您粗略地解释一些Portage的面貌。

在 Portage 中,系统中可以共存软件的不同版本。其他发行版倾向于直接在软件包名字中包含版本号(例如 gtk+2 和 gtk+3),但 Portage 使用一种称之为 SLOT 的技术。ebuild 为版本声明了一个确切的 SLOT。不同 SLOT 的 ebuild 可以共存于系统中。例如,上例中那个 gtk+ 包就拥有不同的 ebuild,分别是 SLOT="2" 和 SLOT="4"。

有一些不同的软件包提供了类似的功能。比如metalogd,sysklogd和syslog-ng都是系统日志记录工具。那些依赖于“系统日志记录工具”的程序并不能随便的依赖于其中之一,比如metalogd。因为其他的系统日志工具可能也是很好的选择。好在Portage允许使用虚拟包:每一个系统日志记录工具都可以提供virtual/logger包,因此应用程序们可以设定成仅仅依赖于virtual/syslog即可。

Portage树中的软件可以存在于不同的分支中。您的系统默认只会接受那些Gentoo认为稳定的软件包。绝大多数新提交的软件会被添加到测试分支里。这意味着在此软件被标示为稳定版前需要进行更多的测试。尽管您可以看到那些软件的ebuilds已经加入Portage数据库,在它们未被加入稳定分支前Portage将不会安装它们。

有些软件只能在某几个体系结构上使用。或者在其他体系结构中还不能运行,或者仍需要对其进行更多的测试,或者将软件提交到Portage树中的开发者还不能确定这个软件能否运行于其他体系结构。

每一个Gentoo安装都依附于一个确定的profile,此文件里除了其他信息外还包含了一个正常工作的系统需要的软件包的列表。

被阻止的软件包

代码 对于被阻止的软件包 Portage 的警告
[ebuild  N     ] x11-wm/i3-4.20.1  USE="-doc -test"
[blocks B      ] x11-wm/i3 ("x11-wm/i3" is soft blocking x11-wm/i3-gaps-4.20.1)

 * Error: The above package list contains packages which cannot be
 * installed at the same time on the same system.

  (x11-wm/i3-4.20.1:0/0::gentoo, ebuild scheduled for merge) pulled in by
    x11-wm/i3

  (x11-wm/i3-gaps-4.20.1-1:0/0::gentoo, installed) pulled in by
    x11-wm/i3-gaps required by @selected

ebuild 文件中包含了特定的字段,里面为 Portage 提供了此软件包各种依赖关系的信息。有两种可能的依赖关系:一种是编译依赖,在 DEPEND 变量中声明;另一种是运行时依赖,在 RDEPEND 变量中声明。如果在上述的两种依赖关系中,明确指明某个软件包或者虚拟包(译注:可能已安装和正要安装)与要安装的包不兼容,那么就会阻止软件包安装。

虽然Portage的最新版本足够聪明,可以在没有用户干预的情况下解决轻微的问题,但偶尔也需要手动解决此类问题。

为了使安装得以继续进行,您可以选择不安装这个软件包,或者先将发生冲突的包卸载。例如,在我们给出的这个例子中,您可以选择不安装postfix,或者先卸载ssmtp。

你也可能会遇到某些特定版本的包被屏蔽的情况,比如<media-video/mplayer-1.0_rc1-r2。在这种情况下,升级到一个更新的版本就能解决问题。

也有可能两个需要安装的包互相阻挡。这种少见的情况下,您应该明确自己为什么需要同时安装它们。绝大多数时候您只需要安装它们之中的一个就可以了。如果不是这样,请您到 Gentoo 的错误追踪系统 中提交 bug。

被屏蔽的软件包

代码 对于被屏蔽的软件包 Portage 的警告
!!! all ebuilds that could satisfy "bootsplash" have been masked.
代码 PPortage关于被屏蔽的包的警告——原因
!!! possible candidates are:
  
- gnome-base/gnome-2.8.0_pre1 (masked by: ~x86 keyword)
- lm-sensors/lm-sensors-2.8.7 (masked by: -sparc keyword)
- sys-libs/glibc-2.3.4.20040808 (masked by: -* keyword)
- dev-util/cvsd-1.0.2 (masked by: missing keyword)
- games-fps/unreal-tournament-451 (masked by: package.mask)
- sys-libs/glibc-2.3.2-r11 (masked by: profile)
- net-im/skype-2.1.0.81 (masked by: skype-eula license(s))

当您想安装一个对于您系统不可用的软件包。您会收到类似这样的屏蔽错误提示。您应该试着安装那些对于您系统可用的程序或者等待那些不可用的包被置为可用的。通常一个软件包被屏蔽的原因在于:

屏蔽原因 描述
~arch keyword 该软件没有经过充分的测试,不能进入稳定分支,请等待一段时间后尝试使用。
-arch keyword or -* keyword 该软件不能在目标机器的架构中工作。如果情况并非如此,请到提交 bug
missing keyword 该软件至今还没有在机器的架构中进行过测试。可以咨询相应架构移植小组是否能对它进行测试,或者自行测试并将结果报告到 Gentoo 的 Bugzilla 网站。查看 /etc/portage/package.accept_keywords接受单个软件包的关键字
package.mask 发现该软件包已损坏、不稳定或更严重的问题,被故意标识为“请勿使用”。
profile 该软件包不适用于当前 profile。安装该软件可能会破坏系统,或只是与当前使用的 profile 不兼容。
license 该软件包的许可证与 ACCEPT_LICENSE 不兼容。通过在 /etc/portage/make.conf/etc/portage/package.license 设置来允许其许可证或正确的许可证组。

必要的 USE 标记更改

代码 Portage 提示 USE 标志需要进行更改
The following USE changes are necessary to proceed:
#required by app-text/happypackage-2.0, required by happypackage (argument)
>=app-text/feelings-1.0.0 test

如果未使用--autounmask参数,则错误消息也可能显示如下:

代码 Portage 提示USE标志设置错误
emerge: there are no ebuilds built with USE flags to satisfy "app-text/feelings[test]".
!!! One of the following packages is required to complete your request:
- app-text/feelings-1.0.0 (Change USE: +test)
(dependency required by "app-text/happypackage-2.0" [ebuild])
(dependency required by "happypackage" [argument])

当请求安装包时,发生这种警告或错误,这不仅取决于另一个包,而且还要求该包使用特定的USE标志(或一组USE标志)构建。 在给定的示例中,包应用文本/感觉需要使用 USE="test"构建,但此系统上未设置此USE标志。

要解决这个问题, 到/etc/portage/make.conf编辑里面的USE标志, 或者去/etc/portage/package.use设置一个特殊的包.

缺失依赖

代码 Portage提示依赖性不满足
emerge: there are no ebuilds to satisfy ">=sys-devel/gcc-3.4.2-r4".
  
!!! Problem with ebuild sys-devel/gcc-3.4.2-r2
!!! Possibly a DEPEND/*DEPEND problem.

这表示您正尝试安装的应用程序依赖于您的系统不可用的另外一些软件包。请到bugzilla查看是否有此问题的记录,如果没有查找到相关信息的话请提交一个报告。除非您的系统混用了不同分支,否则这类问题不应该发生,若发生了那就是一个bug。

ebuild 名称不明确

代码 对于不明确的 ebuild 名称 Portage 的警告
[ Results for search key : listen ]
[ Applications found : 2 ]
  
*  dev-tinyos/listen [ Masked ]
      Latest version available: 1.1.15
      Latest version installed: [ Not Installed ]
      Size of files: 10,032 kB
      Homepage:      http://www.tinyos.net/
      Description:   Raw listen for TinyOS
      License:       BSD
  
*  media-sound/listen [ Masked ]
      Latest version available: 0.6.3
      Latest version installed: [ Not Installed ]
      Size of files: 859 kB
      Homepage:      http://www.listen-project.org
      Description:   A Music player and management for GNOME
      License:       GPL-2
  
!!! The short ebuild name "listen" is ambiguous. Please specify
!!! one of the above fully-qualified ebuild names instead.

您要安装的应用程序对应有多个同名的包。您需要同时指定类别的名称。Portage会列出所有可供选择的名称匹配的包。

循环依赖

代码 Portage关于循环依赖问题的警告
!!! Error: circular dependencies: 
  
ebuild / net-print/cups-1.1.15-r2 depends on ebuild / app-text/ghostscript-7.05.3-r1
ebuild / app-text/ghostscript-7.05.3-r1 depends on ebuild / net-print/cups-1.1.15-r2

两个(或多个)您想安装的包由于循环依赖而不能安装。这很可能源于Portage树中的bug。请等一段时间后重新sync再尝试安装。您也可以去 Bugzilla 看看是否已经有此问题的报告,或者提交一个关于它的报告。

下载失败

代码 对于下载失败 Portage 的警告
!!! Fetch failed for sys-libs/ncurses-5.4-r5, continuing...
(...)
!!! Some fetch errors were encountered.  Please see above for details.

当Portage下载指定软件的源代码失败时,它会尝试继续安装其它(若适用)的应用程序。源代码下载失败可能源于镜像服务器没有正确同步,也可能因为ebuild文件给出了错误的下载地址。那些保存源代码的服务器也可能因为某些原因宕机。

一小时后重试一次,看看问题是否仍然存在。

系统 Profile 保护

代码 对于 profile 中保护的包 Portage 的警告
!!! Trying to unmerge package(s) in system profile. 'sys-apps/portage'
!!! This could be damaging to your system.

您要求移除系统核心软件包中的一个。它是您的profile中所列出的必需的软件,因此不能从系统中移除。

Digest验证失败

代码 Digest验证失败
>>> checking ebuild checksums
!!! Digest verification failed:

这是Portage树中出现了错误的迹象,通常是由于将ebuild提交到Gentoo ebuild存储库时出错造成的。

当digest校验失败的时候,请不要尝试自己去为此软件包重新产生digest。使用ebuild foo manifest 并不能修复问题,反而很可能会使问题变得更糟。

取而代之的应该是等待一至两个小时以便让软件仓库安定下来。一般来说错误很有可能马上就会被注意到,但是修复程序可能需要一点时间来逐步扫描rsync镜像。当您等待的时候,到Bugzilla或者#gentoo (webchat) (IRC)看看是否已经有人报告了这个问题。如果没有,那就为那个损坏的ebuild提交一个bug报告吧。

修复错误后,重新同步Gentoo ebuild仓库以获取修复的digest。

重要
值得注意的是:不要每天多次同步Gentoo ebuild repository 仓库。正如(当您运行emerge --sync时)Gentoo官方网络礼节策略所指出的那样,那些短时间内过于频繁进行多次sync的用户将会被更新服务器软封禁一段时间,一再不遵守这一政策的滥用者可能会被硬封禁。除非绝对必要,否则通常最好等待24小时再进行同步,因为这样您不会使Gentoo的rsync镜像服务器过载而影响其他用户的正常使用。





什么是 USE 标记

USE 标记的指导思想

安装 Gentoo 时,用户需要依据你工作的环境做出选择。服务器跟工作站的组织结构不同,游戏机跟3D工作站也会不一样。

不单只是选择你想要安装的包时如此,选择某一个包需要的特性时同样如此。如果你不需要OpenGL,为什么还要花费时间安装OpenGL并在其他包中加入对OpenGL的支持?如果你不用KDE,而且软件包没有KDE也能完美运行,为什么还要在编译这些包的时候加入KDE支持?

为了帮用户判断什么需要安装或激活,什么不需要;我们希望用户能用简单的方式设定他们自己的环境。这能促使用户判断他真正需要的东西,并让Portage做出有用的决定的过程变得简单。

USE 标记的定义

我们来具体看看 USE 标记。每一个标记都是代表对某特定概念的支持和依赖关系信息的关键字。如果你设定了某个 USE 标记,Portage会明白他们需要支持所选关键字。当然这同时也改变了这个包的依赖关系信息。

让我们看一个特殊示例:关键字 kde 。如果你的 USE 变量里面没有这个关键字,所有具有可选KDE支持的包在编译时都 不会 编译KDE支持。所有具有可选KDE依赖关系的包在安装时都 不会 (做为一个依赖关系而)安装KDE库。如果你设定了kde关键字,这些包在安装时都 编译KDE支持,而且KDE库也 (作为一个依赖关系而)被安装。

When the kde flag is set to enabled, then those packages will be compiled with KDE support, and the KDE libraries will be installed as dependency.

通过正确定义 USE 标记,系统会根据系统管理员的需求进行专门定制。

使用 USE 标记

声明永久 USE 标记

所有 USE 标记都声明在 USE 变量里面。为了让用户能方便地查找和选择 USE 标记,我们提供了一份默认的 USE 设定。这些设定是我们觉得 Gentoo 用户通常都要用到的 USE 标记的集合。这个默认设置在make.defaults 文件中声明,这是已选择的 profile 的一部分。

你的系统使用的profile是符号链接 /etc/portage/make.profile 所指向的目录。每个profile叠加于某个更大的profile之上,最终的结果是这些profile的并集。初始profile是base profile( /var/db/repos/gentoo/profiles/base)。

要查看当前正在使用的USE标记(完整的),请使用 emerge --info

root #emerge --info | grep ^USE
USE="a52 aac acpi alsa branding cairo cdr dbus dts ..."

这个变量已经包括了非常多的关键字。不要通过修改make.defaults 文件里的 USE 变量来满足你的需要:在升级Portage的时候,这个文件将会被覆盖。

要改变这个默认设置,你需要在 USE 变量里添加或移去关键字。这是通过在/etc/portage/make.conf里定义USE全局变量来实现的。在这个变量里,添加你需要的额外的USE标记,或者移去你不需要的USE标记。后者可通过在标记前面加个负号 (-).前缀来实现。

例如,要移除对 KDE 和 QT 的支持,并添加对 LDAP 的支持,可以在/etc/portage/make.conf里声明USE如下:

文件 /etc/portage/make.conf在 make.conf 更新 USE
USE="-kde -qt5 ldap"

使用 USE 标记为单个包声明 USE 标记

如果你不是想为整个系统声明 USE 标记,而是想要为一个(或者几个)程序声明USE标记,你需要编辑/etc/portage/package.use文件。package.use 通常是一个文件,不过它也可以是一个充满子文件的目录;请看下面的提示和 man 5 portage 以获得更多如何使用这个约定的信息。下面的例子假设 package.use 是一个文件。

比如说,如果你不想全局的启用 Blu-ray 支持,你只想把它应用到 VLC 包,你可以这样做:

文件 /etc/portage/package.useEnabling Blu-ray support for VLC
media-video/vlc bluray
提示
如果 package.use 是一个已经存在的“目录”(而不是一个单文件),只需简单地在 package.use/ 目录下创建文件,就可以修改软件包的本地USE标记。虽然任何文件命名规范都行,但是更明智的做法是统一命名方案。

有一种规范是简单地使用包名作为子文件的标题。比如说,可以用如下方式为 media-video/vlc 软件包设置 bluray USE 标记。

root #echo "media-video/vlc bluray" >> /etc/portage/package.use/vlc

你当然也可以直接为某一个程序禁用 USE 标记。比如说,禁用PHP的bzip2支持(但通过make.conf中的 USE 标记为其他包提供支持):

文件 /etc/portage/package.use禁用 PHP 对 bzip2 的支持
dev-lang/php -bzip2

声明临时 USE 标记

有时,你只想暂时改变一个USE设置。你可以仅仅把USE 变量声明成一个环境变量,而不必两次修改/etc/portage/make.conf 。但是要记住,当重新 emerge 或者更新这个程序时(不管是单独更新还是随系统更新),你的修改会被重置。

下面的例子我们将在安装 SeaMonkey 的时候临时从 USE 变量中移去pulseaudio 值。

root #USE="-pulseaudio" emerge www-client/seamonkey

优先级

当然,在什么设置优先于USE设置有一定的优先级。 USE设置的优先级,按优先级排序(第一优先级最低):

  1. make.defaults 里面的USE默认设定
  2. 用户在/etc/portage/make.conf里面的USE默认设定
  3. 用户在 /etc/portage/package.use里面的USE默认设定
  4. 用户作为环境变量的USE设定

运行 emerge --info可以看到Portage识别的最终的USE设定。它会列出Portage使用的所有相关变量(包括 USE 变量)。

root #emerge --info

在整个系统上应用新的 USE 标记

如果你已经修改了你的 USE 标记,而且你想用新的 USE 标记更新你的系统,可以使用emerge--newuse选项:

root #emerge --update --deep --newuse @world

然后运行Portage的depclean来移除已经安装到你的"旧"系统里但是在新 USE 标记中被废除的条件依赖关系。

重要
请反复检查“已废止(obsoleted)”软件包列表,确保不会移除所需要的软件包。下面这个例子里,--pretend (-p) 选项可以使 depclean 只列出这些软件包而不移除他们:
root #emerge -p --depclean

depclean 完成之后,emerge 会针对可能是已经删除的软件包提供的共享对象动态链接的应用程序提示重新构建。此操作完成前,为了防止破坏应用程序,Portage 将会保存必要的库。它存储着需要在 preserved-rebuild 设置的重建内容。若要重建必要的包,请运行:

root #emerge @preserved-rebuild

这些都完成之后,你的系统就已经应用上了新的 USE 标记的设定。

软件包特有的 USE 标记

查看可用 USE 标记

让我们以 seamonkey 来作例子,看看它接收什么 USE 标记。我们可以以--pretend--verbose为选项执行 emerge来查看:

root #emerge --pretend --verbose www-client/seamonkey
These are the packages that would be merged, in order:
 
Calculating dependencies... done!
[ebuild  N     ] www-client/seamonkey-2.48_beta1::gentoo  USE="calendar chatzilla crypt dbus gmp-autoupdate ipc jemalloc pulseaudio roaming skia startup-notification -custom-cflags -custom-optimization -debug -gtk3 -jack -minimal (-neon) (-selinux) (-system-cairo) -system-harfbuzz -system-icu -system-jpeg -system-libevent -system-libvpx -system-sqlite {-test} -wifi" L10N="-ca -cs -de -en-GB -es-AR -es-ES -fi -fr -gl -hu -it -ja -lt -nb -nl -pl -pt-PT -ru -sk -sv -tr -uk -zh-CN -zh-TW" 216,860 KiB
 
Total: 1 package (1 new), Size of downloads: 216,860 KiB

emerge 并不是做这件事的唯一工具。事实上,我们有一个专门的包信息工具叫equery,它属于app-portage/gentoolkit

root #emerge --ask app-portage/gentoolkit

现在带 uses 参数执行 equery 来查看指定包的 USE 标记。例如 app-portage/portage-utils 软件包:

user $equery --nocolor uses =app-portage/portage-utils-0.93.3
[ Legend : U - final flag setting for installation]
[        : I - package is installed with flag     ]
[ Colors : set, unset                             ]
 * Found these USE flags for app-portage/portage-utils-0.93.3:
 U I
 + + nls       : Add Native Language Support (using gettext - GNU locale utilities)
 + + openmp    : Build support for the OpenMP (support parallel computing), requires >=sys-devel/gcc-4.2 built with USE="openmp"
 + + qmanifest : Build qmanifest applet, this adds additional dependencies for GPG, OpenSSL and BLAKE2B hashing
 + + qtegrity  : Build qtegrity applet, this adds additional dependencies for OpenSSL
 - - static    : !!do not set this during bootstrap!! Causes binaries to be statically linked instead of dynamically

满足 REQUIRED_USE

一些 ebuild 需要或禁止 USE 标记的某些组合才能正常工作。这通过放置在 REQUIRED_USE ,用一组条件来表示。此条件确保所有功能和依赖性都已完成,并且构建将成功并按预期执行。 如果任何一个不符合,emerge 会提醒你,并要求你解决这个问题。

示例 描述
REQUIRED_USE="foo? ( bar )" 如果设定 foo,则必须设定 bar
REQUIRED_USE="foo? ( !bar )" 如果设定 foo,则不得设定 bar
REQUIRED_USE="foo? ( || ( bar baz ) )" 如果设定 foo,则必须在 barbaz 中设定一个。
REQUIRED_USE="^^ ( foo bar baz )" 必须在 foobarbaz 中设定一个。
REQUIRED_USE="|| ( foo bar baz )" 至少在 foobarbaz 中设定一个。
REQUIRED_USE="?? ( foo bar baz )" 可以在 foobarbaz 中设定一个或者都不设定。




Portage特性

Portage有几个附加的特性,它们能够令您的Gentoo之旅更加愉快。这些特性中的大多数依赖于某些能够提高性能、可靠性、安全性等的软件工具。

为了打开或者关闭某一Portage特性您需要编辑 /etc/portage/make.conf中的 FEATURES变量,这个变量包含不同的特性关键字,用空格分开。在一些情况下您可能还需要额外的安装被这个特性所依赖的工具。

并不是所有Portage所支持的特性都在这里列出。完整的概述,请查阅make.conf手册页:make.conf

user $man make.conf

查看 FEATURES 的默认设置,运行emerge --info并且查找FEATURES变量或者用grep 显示它:

user $emerge --info | grep ^FEATURES=

分布式编译

使用distcc

distcc 是一个分布式编译程序,可以把编译任务分配给同一网络中的不同机器,这些机器的配置不必完全相同。distcc客户端发送所有必须的信息给所有可利用的distcc服务器(运行distccd的机器)。这样它们每一个都能为客户端编译一部分源码。所获得的效果就是更短的编译时间。

您可以在Gentoo Distcc文档里找到更多的关于Distcc的信息(包括如何让它在Gentoo上工作)。

安装 distcc

Distcc使用一个图形化监视器来监视您的机器发送出去的编译工作。请把 USE=gnomeUSE=gtk放进您的USE设置中。

root #emerge --ask sys-devel/distcc

激活Portage的distcc支持

distcc 添加到/etc/portage/make.conf.中的 FEATURES </ var>变量中。 接下来,编辑MAKEOPTS变量,并增加系统允许的并行构建的数量。 一个已知的方法是填写 -jN 其中N 是运行distccd(包括当前主机)的CPU数量+1(或者核心数+1),但这只是一个建议。

现在运行 distcc-config并输入已有的DistCC服务器。作为一个简单例子,我们假设已有的DistCC服务器是192.168.1.102(当前主机)、192.168.1.103和192.168.1.104(两个远端服务器):

root #distcc-config --set-hosts "192.168.1.102 192.168.1.103 192.168.1.104"

当然,也不要忘了运行distccd系统服务:

root #rc-update add distccd default
root #/etc/init.d/distccd start

缓冲编译结果

关于ccache

ccache是一个快速编译器缓存。 无论何时编译应用程序,它都将缓存中间结果,以便每当重新编译相同的程序时,编译时间大大减少。 第一次运行ccache时,它会比正常编译慢得多。 但是后续的重新编译应该更快。 ccache只有在相同的应用程序将被重新编译多次(或相同应用程序的升级频繁发生)时才有用; 因此它通常只对软件开发人员有用。

如果您对ccache的工作机制有兴趣,请访问homepage主页.

警告
已知ccache会导致大量的编译失败。 有时ccache会保留旧代码对象或损坏的文件,这可能导致无法破损的源码。 如果发生这种情况(例如"File not recognized: File truncated"出现在构建日志中),请尝试重新编译ccache导致错误的应用程序 (FEATURES="-ccache"/etc/portage/make.conf)

安装 ccache

要安装ccache,只需要:

root #emerge --ask dev-util/ccache

激活Portage ccache 支持

打开 /etc/portage/make.conf并添加ccache到FEATURES变量。然后添加一个新的变量ccache并设置它为ccache:

文件 /etc/portage/make.conf开启 Portage ccache 支持
FEATURES="ccache"
CCACHE_SIZE="2G"

要检查ccache是否运行,只需让它提供给您它的统计数据。因为Portage使用一个不同的ccache主目录,您需要设定CCACHE_DIR变量:

root #CCACHE_DIR="/var/tmp/ccache" ccache -s

/var/tmp/ccache/是Portage的默认ccache主目录;为了修改这个设置,您可以设定/etc/portage/make.conf中的CCACHE_DIR参数。

不过,如果您运行 ccache ,它使用的默认目录是${HOME}/.ccache/。这就是为什么当您查询(Portage)ccache统计数据的时候您需要设定 CCACHE_DIR参数的原因。

非Portage编译中使用ccache

如果您需要在非Portage编译中使用ccache,添加 /usr/lib/ccache/bin/到您 PATH参数里靠前的位置(在/usr/bin之前)。这一点可以通过编辑在您用户主目录中的~/.bash_profile文件来实现。使用~/.bash_profile是定义 PATH参数的一个方式

文件 ~/.bash_profile设置 ccache 路径 PATH
PATH="/usr/lib/ccache/bin:${PATH}"

二进制包支持

创建预编译包

Portage 也支持安装预编译软件包。尽管 Gentoo 本身并不提供预编译包,但 Portage 依然能够处理预编译包。

如果某个包已经被安装在您的系统上,您可以用 quickpkg 来创建预编译包。也可以用带有 --buildpkg--buildpkgonly 选项的 emerge 命令。

如果您希望 Portage 为您所安装的每一个软件包创建预编译软件包,那么请在 FEATURES 中添加 buildpkg 变量。

预编译包的更多扩展支持可以用 catalyst 得到。关于catalyst的更多信息请参阅 Catalyst FAQ

安装预编译包

尽管Gentoo并不提供,但是您可以自己建立一个“中心仓库”来存放预编译包。如果您希望使用这个仓库,您需要设定PORTAGE_BINHOST参数使Portage能够知道它。例如,如果预编译包在 ftp://buildhost/gentoo 上:

文件 /etc/portage/make.conf添加 PORTAGE_BINHOST
PORTAGE_BINHOST="ftp://buildhost/gentoo"

当您需要安装预编译包的时候,在emerge命令后的 --getbinpkg选项旁加入 --usepkg 选项。前者让emerge命令从预定的服务器上下载预编译包,后者让emerge首先试图安装预编译包,如果预编译包不存在,那么才下载并编译源码。

例如:用预编译包安装gnumeric

root #emerge --usepkg --getbinpkg gnumeric

关于emerge的预编译包的更多信息请参阅emerge手册页:

user $man emerge

将预构建的软件包分发给他人

如果预构建的软件要分发给其他人,请确保这样做是被允许的。 检查上游软件包的分发要求。 例如,对于在GNU GPL协议下发布的软件,源代码必须与二进制文件一起提供。

如果构建的二进制程序不可分发,则Ebuild可以在其RESTRICT 变量中定义 bindist限制。 有时,此限制取决于一个或多个USE标志。

默认情况下,Portage将不会屏蔽任何包,因为有限制。 这可以通过在/etc/portage/make.conf中设置ACCEPT_RESTRICT变量来全局更改。 例如,要掩盖具有bindist 限制的软件包,请将以下行添加到make.conf

文件 /etc/portage/make.conf只接受预编译包
ACCEPT_RESTRICT="* -bindist"

还可以通过将ACCEPT_RESTRICT选项用于emerge命令,来覆盖--accept-restrict 变量。 例如, --accept-restrict=-bindist将临时屏蔽带有bindist 限制的包。

还可以考虑在分发包时设置ACCEPT_LICENSE变量。 请参阅 授权许可

重要
每个 用户完全有责任遵守软件许可条款和每个用户国家的法律。 ebuilds(RESTRICTLICENSE)定义的元数据变量可以为禁止预编译文件分发提供指导。但是Portage的输出或Gentoo开发人员的回答 不是 法律声明,不应该依赖他们。 谨慎遵守您的当地的法律。

下载文件

并行下载

Portage 通常是以root 用户运行的, FEATURES="userfetch"可以让Portage在下载源码包的时候弃用 root 权限,并以 portage:portage 的用户/组权限运行。这是一个小小的安全性的提高方法。

如果在 FEATURES 设置了 userfetch,请确保在 root 权限下,使用 chown 命令更改在 /var/db/repos/gentoo 下所有文件的所有者:

root #chown --recursive --verbose portage:portage /var/db/repos/gentoo

验证源文件

要重新验证完整性并(可能)重新下载当前所有安装的软件包以前删除或损坏的 distfiles,请运行:

root #emerge --ask --fetchonly --emptytree @world




Runlevels

Booting the system

当你启动系统时,会发现有很多的文字信息输出。如果注意观察的话,会发现每次启动时这些文字信息都是相同的。所有这些动作的顺序我们称之为启动顺序,而且它们基本上是被静态定义的。

首先,你的引导程序会把你在引导程序配置文件中定义的内核镜像加载到内存中,之后它就告诉CPU可以运行内核了。当内核被加载且运行后,内核会初始化所有内核专有的结构体和任务,并开启init进程。

This process then makes sure that all filesystems (defined in /etc/fstab) are mounted and ready to be used. Then it executes several scripts located in /etc/init.d/, which will start the services needed in order to have a successfully booted system.

Finally, when all scripts are executed, init activates the terminals (in most cases just the virtual consoles which are hidden beneath Alt+F1, Alt+F2, etc.) attaching a special process called agetty to it. This process will then make sure users are able to log on through these terminals by running login.

Initscripts

Now init doesn't just execute the scripts in /etc/init.d/ randomly. Even more, it doesn't run all scripts in /etc/init.d/, only the scripts it is told to execute. It decides which scripts to execute by looking into /etc/runlevels/.

First, init runs all scripts from /etc/init.d/ that have symbolic links inside /etc/runlevels/boot/. Usually, it will start the scripts in alphabetical order, but some scripts have dependency information in them, telling the system that another script must be run before they can be started.

When all /etc/runlevels/boot/ referenced scripts are executed, init continues with running the scripts that have a symbolic link to them in /etc/runlevels/default/. Again, it will use the alphabetical order to decide what script to run first, unless a script has dependency information in it, in which case the order is changed to provide a valid start-up sequence. The latter is also the reason why commands used during the installation of Gentoo Linux used default, as in rc-update add sshd default.

How init works

Of course init doesn't decide all that by itself. It needs a configuration file that specifies what actions need to be taken. This configuration file is /etc/inittab.

Remember the boot sequence that was just described - init's first action is to mount all file systems. This is defined in the following line from /etc/inittab:

文件 /etc/inittabInitialization command
si::sysinit:/sbin/openrc sysinit

This line tells init that it must run /sbin/openrc sysinit to initialize the system. The /sbin/openrc script takes care of the initialization, so one might say that init doesn't do much - it delegates the task of initializing the system to another process.

Second, init executed all scripts that had symbolic links in /etc/runlevels/boot/. This is defined in the following line:

文件 /etc/inittabBoot command invocation
rc::bootwait:/sbin/openrc boot

Again the OpenRC script performs the necessary tasks. Note that the option given to OpenRC (boot) is the same as the sub-directory of /etc/runlevels/ that is used.

Now init checks its configuration file to see what runlevel it should run. To decide this, it reads the following line from /etc/inittab:

文件 /etc/inittabDefault runlevel selection
id:3:initdefault:

In this case (which the majority of Gentoo users will use), the runlevel id is 3. Using this information, init checks what it must run to start runlevel 3:

文件 /etc/inittabRunlevel definitions
l0:0:wait:/sbin/openrc shutdown
l1:S1:wait:/sbin/openrc single
l2:2:wait:/sbin/openrc nonetwork
l3:3:wait:/sbin/openrc default
l4:4:wait:/sbin/openrc default
l5:5:wait:/sbin/openrc default
l6:6:wait:/sbin/openrc reboot

The line that defines level 3, again, uses the openrc script to start the services (now with argument default). Again note that the argument of openrc is the same as the subdirectory from /etc/runlevels/.

When OpenRC has finished, init decides what virtual consoles it should activate and what commands need to be run at each console:

文件 /etc/inittabTerminal definitions
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
c2:12345:respawn:/sbin/agetty 38400 tty2 linux
c3:12345:respawn:/sbin/agetty 38400 tty3 linux
c4:12345:respawn:/sbin/agetty 38400 tty4 linux
c5:12345:respawn:/sbin/agetty 38400 tty5 linux
c6:12345:respawn:/sbin/agetty 38400 tty6 linux

Available runlevels

In a previous section, we saw that init uses a numbering scheme to decide what runlevel it should activate. A runlevel is a state in which the system is running and contains a collection of scripts (runlevel scripts or initscripts) that must be executed when entering or leaving a runlevel.

In Gentoo, there are seven runlevels defined: three internal runlevels, and four user-defined runlevels. The internal runlevels are called sysinit, shutdown and reboot and do exactly what their names imply: initialize the system, powering off the system, and rebooting the system.

The user-defined runlevels are those with an accompanying /etc/runlevels/ subdirectory: boot, default, nonetwork and single. The boot runlevel starts all system-necessary services which all other runlevels use. The remaining three runlevels differ in what services they start: default is used for day-to-day operations, nonetwork is used in case no network connectivity is required, and single is used when the system needs to be fixed.

Working with initscripts

The scripts that the openrc process starts are called init scripts. Each script in /etc/init.d/ can be executed with the arguments start, stop, restart, zap, status, ineed, iuse, iwant, needsme, usesme, or wantsme.

To start, stop, or restart a service (and all depending services), the start, stop, and restart arguments should be used:

root #rc-service postfix start
附注
Only the services that need the given service are stopped or restarted. The other depending services (those that use the service but don't need it) are left untouched.

To stop a service, but not the services that depend on it, use the --nodeps option together with the stop argument:

root #rc-service --nodeps postfix stop

To see what status a service has (started, stopped, ...) use the status argument:

root #rc-service postfix status

If the status information shows that the service is running, but in reality it is not, then reset the status information to "stopped" with the zap argument:

root #rc-service postfix zap

To also ask what dependencies the service has, use iwant, iuse or ineed. With ineed it is possible to see the services that are really necessary for the correct functioning of the service. iwant or iuse, on the other hand, shows the services that can be used by the service, but are not necessary for the correct functioning.

root #rc-service postfix ineed

Similarly, it is possible to ask what services require the service (needsme) or can use it (usesme or wantsme):

root #rc-service postfix needsme

Updating runlevels

rc-update

Gentoo's init system uses a dependency-tree to decide what service needs to be started first. As this is a tedious task that we wouldn't want our users to have to do manually, we have created tools that ease the administration of the runlevels and init scripts.

With rc-update it is possible to add and remove init scripts to a runlevel. The rc-update tool will then automatically ask the depscan.sh script to rebuild the dependency tree.

Adding and removing services

In earlier instructions, init scripts have already been added to the "default" runlevel. What "default" means has been explained earlier in this document. Next to the runlevel, the rc-update script requires a second argument that defines the action: add, del, or show.

To add or remove an init script, just give rc-update the add or del argument, followed by the init script and the runlevel. For instance:

root #rc-update del postfix default

The rc-update -v show command will show all the available init scripts and list at which runlevels they will execute:

root #rc-update -v show

It is also possible to run rc-update show (without -v) to just view enabled init scripts and their runlevels.

Configuring services

Why additional configuration is needed

Init scripts can be quite complex. It is therefore not really desirable to have the users edit the init script directly, as it would make it more error-prone. It is however important to be able to configure such a service. For instance, users might want to give more options to the service itself.

A second reason to have this configuration outside the init script is to be able to update the init scripts without the fear that the user's configuration changes will be undone.

conf.d directory

Gentoo provides an easy way to configure such a service: every init script that can be configured has a file in /etc/conf.d/. For instance, the apache2 initscript (called /etc/init.d/apache2) has a configuration file called /etc/conf.d/apache2, which can contain the options to give to the Apache 2 server when it is started:

文件 /etc/conf.d/apache2Example options for apache2 init script
APACHE2_OPTS="-D PHP5"

Such a configuration file contains only variables (just like /etc/portage/make.conf does), making it very easy to configure services. It also allows us to provide more information about the variables (as comments).

Writing initscripts

Another useful resource is OpenRC's service script guide.

Is it necessary?

No, writing an init script is usually not necessary as Gentoo provides ready-to-use init scripts for all provided services. However, some users might have installed a service without using Portage, in which case they will most likely have to create an init script.

Do not use the init script provided by the service if it isn't explicitly written for Gentoo: Gentoo's init scripts are not compatible with the init scripts used by other distributions! That is, unless the other distribution is using OpenRC!

Layout

The basic layout of an init script is shown below.

代码 Example initscript layout (traditional)
#!/sbin/openrc-run
  
depend() {
#  (Dependency information)
}
  
start() {
#  (Commands necessary to start the service)
}
  
stop() {
#  (Commands necessary to stop the service)
}
代码 Example initscript layout (updated)
#!/sbin/openrc-run
command=/usr/bin/foo
command_args="${foo_args} --bar"
pidfile=/var/run/foo.pid
name="FooBar Daemon"
 
description="FooBar is a daemon that drinks"
extra_started_commands="drink"
description_drink="Opens mouth and reflexively swallows"
 
depend() {
#  (Dependency information)
}
 
start_pre() {
#  (Commands necessary to prepare to start the service)
    # Ensure that our dirs are correct
    checkpath --directory --owner foo:foo --mode 0775 \
        /var/run/foo /var/cache/foo
}
  
stop_post() {
#  (Commands necessary to clean up after the service)
    # Clean any spills
    rm -rf /var/cache/foo/*
}
 
drink() {
    ebegin "Starting to drink"
    ${command} --drink beer
    eend $? "Failed to drink any beer :("
}

Every init script requires the start() function or command variable to be defined. All other sections are optional.

Dependencies

There are three dependency-alike settings that can be defined which influence the start-up or sequencing of init scripts: want, use and need. Next to these, there are also two order-influencing methods called before and after. These last two are no dependencies per se - they do not make the original init script fail if the selected one isn't scheduled to start (or fails to start).

  • The use settings informs the init system that this script uses functionality offered by the selected script, but does not directly depend on it. A good example would be use logger or use dns. If those services are available, they will be put in good use, but if the system does not have a logger or DNS server the services will still work. If the services exist, then they are started before the script that uses them.
  • The want setting is similar to use with one exception. use only considers services which were added to an init level. want will try to start any available service even if not added to an init level.
  • The need setting is a hard dependency. It means that the script that is needing another script will not start before the other script is launched successfully. Also, if that other script is restarted, then this one will be restarted as well.
  • When using before, then the given script is launched before the selected one if the selected one is part of the init level. So an init script xdm that defines before alsasound will start before the alsasound script, but only if alsasound is scheduled to start as well in the same init level. If alsasound is not scheduled to start too, then this particular setting has no effect and xdm will be started when the init system deems it most appropriate.
  • Similarly, after informs the init system that the given script should be launched after the selected one if the selected one is part of the init level. If not, then the setting has no effect and the script will be launched by the init system when it deems it most appropriate.

It should be clear from the above that need is the only "true" dependency setting as it affects if the script will be started or not. All the others are merely pointers towards the init system to clarify in which order scripts can be (or should be) launched.

Now, look at many of Gentoo's available init scripts and notice that some have dependencies on things that are no init scripts. These "things" we call virtuals.

A virtual dependency is a dependency that a service provides, but that is not provided solely by that service. An init script can depend on a system logger, but there are many system loggers available (metalogd, syslog-ng, sysklogd, ...). As the script cannot need every single one of them (no sensible system has all these system loggers installed and running) we made sure that all these services provide a virtual dependency.

For instance, take a look at the postfix dependency information:

文件 /etc/init.d/postfixDependency information of the postfix service
depend() {
  need net
  use logger dns
  provide mta
}

As can be seen, the postfix service:

  • Requires the (virtual) net dependency (which is provided by, for instance, /etc/init.d/net.eth0).
  • Uses the (virtual) logger dependency (which is provided by, for instance, /etc/init.d/syslog-ng).
  • Uses the (virtual) dns dependency (which is provided by, for instance, /etc/init.d/named).
  • Provides the (virtual) mta dependency (which is common for all mail servers).

Controlling the order

As described in the previous section, it is possible to tell the init system what order it should use for starting (or stopping) scripts. This ordering is handled both through the dependency settings use and need, but also through the order settings before and after. As we have described these earlier already, let's take a look at the portmap service as an example of such init script.

文件 /etc/init.d/portmapDependency information of the portmap service
depend() {
  need net
  before inetd
  before xinetd
}

It is possible to use the "*" glob to catch all services in the same runlevel, although this isn't advisable.

代码 Using the * glob
depend() {
  before *
}

If the service must write to local disks, it should need localmount. If it places anything in /var/run/ such as a PID file, then it should start after bootmisc:

代码 Dependency setting with needing localmount and after bootmisc
depend() {
  need localmount
  after bootmisc
}

Standard functions

Next to the depend() functionality, it is also necessary to define the start() function. This one contains all the commands necessary to initialize the service. It is advisable to use the ebegin and eend functions to inform the user about what is happening:

代码 Example start() function
start() {
  if [ "${RC_CMD}" = "restart" ];
  then
    # Do something in case a restart requires more than stop, start
  fi
  
  ebegin "Starting my_service"
  start-stop-daemon --start --exec /path/to/my_service \
    --pidfile /path/to/my_pidfile
  eend $?
}

Both --exec and --pidfile should be used in start and stop functions. If the service does not create a pidfile, then use --make-pidfile if possible, though it is recommended to test this to be sure. Otherwise, don't use pidfiles. It is also possible to add --quiet to the start-stop-daemon options, but this is not recommended unless the service is extremely verbose. Using --quiet may hinder debugging if the service fails to start.

Another notable setting used in the above example is to check the contents of the RC_CMD variable. Unlike the previous init script system, the newer OpenRC system does not support script-specific restart functionality. Instead, the script needs to check the contents of the RC_CMD variable to see if a function (be it start() or stop()) is called as part of a restart or not.

附注
Make sure that --exec actually calls a service and not just a shell script that launches services and exits - that's what the init script is supposed to do.

For more examples of the start() function, please read the source code of the available init scripts in the /etc/init.d/ directory.

Another function that can (but does not have to) be defined is stop(). The init system is intelligent enough to fill in this function by itself if start-stop-daemon is used.

代码 Example stop() function
stop() {
  ebegin "Stopping my_service"
  start-stop-daemon --stop --exec /path/to/my_service \
    --pidfile /path/to/my_pidfile
  eend $?
}

If the service runs some other script (for example, Bash, Python, or Perl), and this script later changes names (for example, foo.py to foo), then it is necessary to add --name to start-stop-daemon. This must specify the name that the script will be changed to. In this example, a service starts foo.py, which changes names to foo:

代码 Example definition for a service that starts the foo script
start() {
  ebegin "Starting my_script"
  start-stop-daemon --start --exec /path/to/my_script \
    --pidfile /path/to/my_pidfile --name foo
  eend $?
}

start-stop-daemon has an excellent man page available if more information is needed:

user $man start-stop-daemon

Gentoo's init script syntax is based on the POSIX Shell so people are free to use sh-compatible constructs inside their init scripts. Keep other constructs, like bash-specific ones, out of the init scripts to ensure that the scripts remain functional regardless of the change Gentoo might do on its init system.

Adding custom options

If the initscript needs to support more options than the ones we have already encountered, then add the option to one of the following variables, and create a function with the same name as the option. For instance, to support an option called restartdelay:

  • extra_commands - Command is available with the service in any state
  • extra_started_commands - Command is available when the service is started
  • extra_stopped_commands - Command is available when the service is stopped


代码 Example definition of restartdelay method
extra_started_commands="restartdelay"
  
restartdelay() {
  stop
  sleep 3    # Wait 3 seconds before starting again
  start
}
重要
The restart() function cannot be overridden in OpenRC!

Service configuration variables

In order to support configuration files in /etc/conf.d/, no specifics need to be implemented: when the init script is executed, the following files are automatically sourced (i.e. the variables are available to use):

  • /etc/conf.d/YOUR_INIT_SCRIPT
  • /etc/conf.d/basic
  • /etc/rc.conf

Also, if the init script provides a virtual dependency (such as net), the file associated with that dependency (such as /etc/conf.d/net) will be sourced too.

Changing runlevel behavior

Who might benefit

Many laptop users know the situation: at home they need to start net.eth0, but they don't want to start net.eth0 while on the road (as there is no network available). With Gentoo the runlevel behavior can be altered at will.

For instance, a second "default" runlevel can be created which can be booted that has other init scripts assigned to it. At boot time, the user can then select what default runlevel to use.

Using softlevel

First of all, create the runlevel directory for the second "default" runlevel. As an example we create the offline runlevel:

root #mkdir /etc/runlevels/offline

Add the necessary init scripts to the newly created runlevel. For instance, to have an exact copy of the current default runlevel but without net.eth0:

root #cd /etc/runlevels/default
root #for service in *; do rc-update add $service offline; done
root #rc-update del net.eth0 offline
root #rc-update show offline
(Partial sample Output)
               acpid | offline
          domainname | offline
               local | offline
            net.eth0 |

Even though net.eth0 has been removed from the offline runlevel, udev might want to attempt to start any devices it detects and launch the appropriate services, a functionality that is called hotplugging. By default, Gentoo does not enable hotplugging.

To enable hotplugging, but only for a selected set of scripts, use the rc_hotplug variable in /etc/rc.conf:

文件 /etc/rc.confEnable hotplugging of the WLAN interface
rc_hotplug="net.wlan !net.*"
附注
For more information on device initiated services, please see the comments inside /etc/rc.conf.

Edit the bootloader configuration and add a new entry for the offline runlevel. In that entry, add softlevel=offline as a boot parameter.

Using bootlevel

Using bootlevel is completely analogous to softlevel. The only difference here is that a second "boot" runlevel is defined instead of a second "default" runlevel.





环境变量

简介

环境变量是一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。通过使用环境变量,你可以很容易的修改一个牵涉到一个或多个应用程序的配置信息。

重要的例子

下表展示了一些Linux系统使用的变量并说明了它们的用处。在表格后面将列举一些变量例值。

Variable Description
PATH 这个变量包含了一系列由冒号分隔开的目录,系统就从这些目录里寻找可执行文件。如果你输入的可执行文件(例如 ls, rc-update或者 emerge)不在这些目录中,系统就无法执行它(除非你输入这个命令的完整路径,如/bin/ls)。
ROOTPATH 这个变量的功能和 PATH相同,但它只罗列出超级用户(root)键入命令时所需检查的目录。
LDPATH 这个变量包含了一系列用冒号隔开的目录,动态链接器将在这些目录里查找库文件。
MANPATH 这个变量包含了一系列用冒号隔开的目录,命令 man 会在这些目录里搜索man页面。
INFODIR 这个变量包含了一系列用冒号隔开的目录,命令 info 将在这些目录里搜索info页面。
PAGER 这个变量包含了浏览文件内容的程序的路径,比如(less 或者 more)
EDITOR 这个变量包含了修改文件内容的程序(文件编辑器)的路径(比如 nanovi).
KDEDIRS 这个变量包含了一系列用冒号隔开的目录,里面放的是KDE相关的资料。
CONFIG_PROTECT 这个变量包含了一系列用空格隔开的目录,它们在软件包更新的时候会被Portage保护起来。
CONFIG_PROTECT_MASK 这个变量包含了一系列用空格隔开的目录,它们在软件包更新的时候不会被Portage保护起来。

下面你可以找到所有这些变量定义的范例:

代码 定义范例
PATH="/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/games/bin"
ROOTPATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
LDPATH="/lib:/usr/lib:/usr/local/lib:/usr/lib/gcc-lib/i686-pc-linux-gnu/3.2.3"
MANPATH="/usr/share/man:/usr/local/share/man"
INFODIR="/usr/share/info:/usr/local/share/info"
PAGER="/usr/bin/less"
EDITOR="/usr/bin/vim"
KDEDIRS="/usr"
CONFIG_PROTECT="/usr/X11R6/lib/X11/xkb /opt/tomcat/conf \
                /usr/kde/3.1/share/config /usr/share/texmf/tex/generic/config/ \
                /usr/share/texmf/tex/platex/config/ /usr/share/config"
CONFIG_PROTECT_MASK="/etc/gconf"

全局变量的定义

env.d目录

Gentoo采用了/etc/env.d/目录来集中定义全局变量。在这个目录里,你会发现很多类似 50baselayoutgcc/config-x86_64-pc-linux-gnu 等等这样的文件,它们包含了文件名中提到的应用程序需要的变量。

举个例子,当你安装 gcc时,ebuild 会创建一个名为 gcc/config-x86_64-pc-linux-gnu 的文件,里面包含了如下一些变量:

文件 /etc/env.d/gcc/config-x86_64-pc-linux-gnuGCC 13 默认启用的环境变量
GCC_PATH="/usr/x86_64-pc-linux-gnu/gcc-bin/13"
LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/13:/usr/lib/gcc/x86_64-pc-linux-gnu/13/32"
MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/13/man"
INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/13/info"
STDCXX_INCDIR="g++-v13"
CTARGET="x86_64-pc-linux-gnu"
GCC_SPECS=""
MULTIOSDIRS="../lib64:../lib"

其他的发行版会让你到/etc/profile或者其他地方修改和添加这些变量的定义。而Gentoo为用户(还有为Portage)提供了更加便捷的方式来维护和管理环境变量,以后你不再需要把精力放在那些众多的包含环境变量的文件身上了。

比如,当你更新完gcc 的时候, /etc/env.d/05gcc也会被同时更新,而不需要你手工来完成。

这不仅对Portage有益,作为用户,你也是受益者。有时候你需要设置某个系统范围的环境变量。我们拿http_proxy变量来做例子,为了避免http_proxy 搞乱,你只要新建一个文件/etc/env.d/99local然后添加你的定义:

文件 /etc/env.d/99local设置一个全局变量
http_proxy="proxy.server.com:8080"

通过使用同一个文件来定义你所有的变量,你对如何定义自己的变量有了个大概的了解。

env-update

/etc/env.d/ 中的好几个文件都定义了PATH变量。这并没有错:当你运行env-update的时候,它会在更新环境变量之前把这些定义都追加到PATH里,因此对于软件包(或者用户)来说将会很容易地设置他们自己的环境变量,而不影响到现有变量的值。

env-update 脚本会根据 /etc/env.d/ 里文件的字母顺序来附加变量的值。这些文件名必须要以两位数字开头。

代码 env-update所用的更新顺序
00basic        99kde-env       99local
     +-------------+----------------+-------------+
PATH="/bin:/usr/bin:/usr/kde/3.2/bin:/usr/local/bin"

变量并不总是被串联起来,只有下列变量才会被串联: ADA_INCLUDE_PATH, ADA_OBJECTS_PATH, CLASSPATH, KDEDIRS, PATH, LDPATH, MANPATH, INFODIR, INFOPATH, ROOTPATH, CONFIG_PROTECT, CONFIG_PROTECT_MASK, PRELINK_PATH, PRELINK_PATH_MASK, PKG_CONFIG_PATH,和PYTHONPATH。对于( /etc/env.d/) 里的文件中按照字母顺序排列后)其他所有变量,最新定义的值才会被使用到。

可以通过将变量名添加到 COLON_SEPARATED or SPACE_SEPARATED (也在 /etc/env.d/ 文件)。

当你运行 env-update的时候,它会在文件/etc/profile.env 里(会被/etc/profile使用)创建所有的环境变量。它也会从变量 LDPATH 中获取信息用来建立/etc/ld.so.conf。这些完成以后,它将运行 ldconfig来重建动态链接器需要的文件/etc/ld.so.cache

如果你想在运行env-update后立即看到效果,执行下面的命令来更新你的环境。自己安装过Gentoo的用户可能已经记住了这个安装指南中提到过的命令:

root #env-update && source /etc/profile
附注
上面的命令只会更新你当前终端里的环境变量、新控制台以及它们的子程序。因此,假如你正在X11里工作,你要么在每一个你打开的终端里输入source /etc/profile ,要么重新启动X,这样所有新的终端才能引用到新的变量。如果你使用了登录管理器,登陆成root然后输入 /etc/init.d/xdm 。如果不是这样,你需要注销然后重新登录回X这样才能产生使用新变量值的子程序。
重要
你在定义其他变量时不能使用shell变量。这意味着这样的定义 FOO="$BAR"(此处$BAR 是另外一个变量)是不允许的。

本地变量的定义

特定用户

你并不是一直都想定义全局变量。比如你想把/home/my_user/bin和当前目录(你当前所在的目录)添加到PATH 变量中,但又不想让其他用户的PATH变量中也有这个。如果你想定义一个本地变量,可以使用 ~/.bashrc 或者~/.bash_profile:

文件 ~/.bashrc在~/.bashrc中扩展PATH做为本地使用
# A colon followed by no directory is treated as the current working directory
PATH="${PATH}:/home/my_user/bin:"

当你重新登录的时候,你的PATH变量将被更新。

特定会话

有时候甚至需要更加严格的定义。你可能要使用一个你临时创建的目录里面的程序,而又不想输入它的路径或者为此短时间内内修改 ~/.bashrc

在这种情况下,你只需要在当前会话中使用export来定义 PATH 变量。只要你不注销,PATH变量将保持这个临时的设置。

root #export PATH="${PATH}:/home/my_user/tmp/usr/bin"



Warning: Display title "Gentoo Linux ppc64 手册:使用Gentoo" overrides earlier display title "手册:PPC64/全部/使用Gentoo".