仅本页所有页面
由 GitBook 提供支持
无法为135页生成 PDF,生成在100页时停止。
使用50页进行扩展。
1 / 100

翻译文章存档

Loading...

Loading...

Loading...

Loading...

2025 年

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

2024 年 11 月

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

2024 年 7 月

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

2023 年 12 月

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

2023 年 9 月

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

2023 年 9 月以前

Loading...

Loading...

Loading...

Loading...

Loading...

FreeBSD 网络文章集锦

警告

本项目目前翻译错漏百出,不适合用于生产。但译者已经尽力修正。

本项目目前处于低维护状态,主要维护者因精力所限仅处理 PR。欢迎社区通过 PR 贡献力量。

年份仅代表翻译时间,不代表真实的文章发表时间。但是一般来说,不会不符合所在年份,也是可用的。

Robert Clausecker EuroBSDcon 2025 旅行报告

  • 原文:EuroBSDcon 2025 Trip Report – Robert Clausecker

  • 发布日期:2025 年 11 月 12 日

  • 作者:Robert Clausecker

今年的 EuroBSDcon 在克罗地亚萨格勒布大学电气工程与计算学院举办。这是我第二次参加 EuroBSDcon,此前我曾在 2024 年的都柏林 EuroBSDcon 上就我在 [SIMD 增强 libc 字符串函数] 的工作作过报告,我对今年的会议非常期待。我非常感谢 FreeBSD 基金会对我前往会议的旅程资助,否则对我来说很难负担得起。

我与 Jan Bramkamp 一起旅行,然后共享了一个房间,他在会议上做了一场关于基于 ZFS 的 jail 配置的精彩演讲。我们居住在德国柏林,因此利用机会乘坐德国高铁到慕尼黑,然后通过卧铺列车前往萨格勒布。这让我们能够精力充沛地到达会场,并有机会欣赏斯洛文尼亚乡村的美景。在会议期间,我们还与 Getz Mikalsen 和 Benni Stürz 会面,他们通过去年参加谷歌编程之夏项目而加入 FreeBSD 项目,还有另一位来自柏林的感兴趣的学生。

今年的 EuroBSDcon 首次延长至五天。前两天用于 FreeBSD 开发者峰会(Dev Summit),随后是 Eurobhyvecon,同时进行的还有教程。第四天和第五天举办了 EuroBSDcon 正式会议,提供了三条平行轨道的丰富演讲内容。

在 FreeBSD 开发者峰会的第一天,我最感兴趣的是关于 pkgbase 项目的进展(计划在 FreeBSD 15 中用正式打包系统取代我们自制的 freebsd-update(8))以及 CHERI 工作的上游合并情况。我也花了很多时间在走廊轨道上,与许多参加会议的其他项目成员交流。一场意外吸引我注意的演讲是 Alfonso Siciliano 关于 FreeBSD 可访问性的讲解,这个话题平时很少听到。

第二天让我对核心团队的运作以及成员们面临的各种问题有了一些有趣的了解,同时也对 libzfs 有一些认识。第三天比较轻松;我没有参加 Eurobhyvecon,后来加入了其他开发者前往距离不远的 Nikola Tesla 技术博物馆的小旅行。

第四天和第五天的演讲都非常密集,有时很难选择参加哪一条轨道。在同事 Jan Bramkamp 关于基于 ZFS 的 FreeBSD jail 配置的演讲之后,我在 Harald Eilertsen 关于将 OpenJDK 移植到 FreeBSD 的演讲中学到了许多困难;作为 ports 的常规贡献者,处理此类问题对我尤为重要。接下来的演讲介绍了用于并行构建工具(如 make(1))的轻量级作业服务器协议,为以工具无关的方式解决此类问题提供了新思路。在 pkgbase 的演讲之后,Björn Zeeb 详细讲解了在 FreeBSD 上使 WLAN 驱动正常工作的进展——这是提升笔记本支持的重要问题。虽然我的笔记本 Qualcomm QCNFA765 网卡目前仍不受支持,但显然已经取得了重要进展,完全支持只是个时间问题。当天的演讲以 Moin Rahman 关于 FreeBSD ports 的讲解结束,我们在社交活动中继续了讨论。

在最后一天,我遗憾地错过了主题演讲,但参加了 Kirk McKusick 关于 UNIX 守护进程历史的报告(去年我错过了第一版)。午餐后,我在 Charlie Li 的 MIDI 演讲和 John Baldwin 的链接器演讲之间艰难选择,最终参加了后者。随后还有关于去中心化互联网服务的演讲,以及一场关于 Type-C 内部工作机制的非常有启发性的讲解。在闭幕前,我还参加了关于如何使用 FreeBSD 改善 UNIX 教学的讲座。这对我尤其有意义,因为我们在柏林自由大学每年都会开设关于 UNIX 系统管理的课程,涵盖 FreeBSD、AIX 和 Solaris,并一直在寻找改进教材的方法。

除了会议议程之外,我也非常感激能有机会与许多其他 FreeBSD 开发者交流,讨论各种问题和项目想法。我希望明年在比利时布鲁塞尔举办的会议能够和今年一样精彩!

再次衷心感谢 FreeBSD 基金会资助此次旅程。

目录

TalkDev:探索开源的未来

  • 原文链接:

  • 译者:Canvis-Me & ChatGPT

2023 年 10 月 27 日

基金会执行董事 Deb Goodkin 与 上就 FreeBSD 的现状进行了深入探讨,消除了人们对开源软件的常见误解,讨论了 FreeBSD 在日益重要的安全领域中所扮演的角色,并展望了开源生态系统的未来。

https://freebsdfoundation.org/news-and-events/latest-news/talkdev-exploring-the-future-of-open-source/
Tejdeep Desai 在 TalkDev

Leah Budzicka EuroBSDcon 2025 旅行报告

  • 原文:2025 EuroBSDCon Trip Report – Leah Budzicka

  • 发布时间:2025 年 11 月 12 日

  • 作者:Leah Budzicka

作为计算机科学三年级学生,同时也是我所在大学操作系统学生俱乐部 The :wheel Group 的 BOFH(Bastard Operator From Hell, 地狱来的混蛋操作员),我一直关注着 BSD,但始终未曾真正腾出时间去深入探索。

有一天,在浏览 Fediverse 动态时,我看到了 FreeBSD 基金会在 Mastodon 上发布的旅行资助截止日期公告。出于一时兴起,我提交了申请——想着这是一个学习的好机会,也可以把新的见解带回学生俱乐部。你可以想象,当我得知申请被批准时,我多么惊讶!

我提前一天到达了萨格勒布,在老城区闲逛。由于旅馆就在附近,傍晚时分我还顺便去了会场看了一眼。

虽然第一天是为 FreeBSD 开发者峰会(Developer Summit)预留的,我还是希望能帮忙组织工作,顺便提前认识一些参会者。虽然并不需要额外帮助,但我问是否可以旁听——令我高兴的是,我得到了 Ed Maste 的邀请,顺利参加了会议。

开幕环节由 Benedict Reuschling 主持,包括一个生动的破冰活动,参会者根据不同标准排列,比如参加过多少次会议,或者从多远的地方来到萨格勒布。这是一个很有趣的方式,让人立即与他人建立联系。之后,我与 Benedict 交流,他表示有兴趣来我的大学做客座讲座。

技术环节同样引人入胜。Greg Wallace 的《FreeBSD 企业工作组的经验分享》揭示了企业采用 FreeBSD 的困境,而 Brooks Davis 关于 CHERI 安全架构的演讲尤其令人着迷。Ed Maste 关于基金会项目的更新让我了解了 Grimoire 和 Sylve,而 Sven Ruediger 与 Lukas Engelhardt 关于 pkgbase 的演讲则解释了 FreeBSD 新的升级机制如何取代传统的 freebsd-update(8)。

当晚,我与一群开发者在当地餐厅共进晚餐,享受美食的同时,也就 FreeBSD 和开源开发进行了愉快的交流。

第二天和第三天,我参加了 Kirk McKusick 关于 FreeBSD 内核的传奇工作坊。作为 BSD 的主要作者之一,Kirk 不仅分享了深厚的技术知识,还讲述了生动有趣的故事,使课程易于理解。我对 FreeBSD 的内核结构、进程管理、安全子系统、虚拟内存实现、I/O 与设备接口、文件系统以及网络栈有了更清晰的理解。

每天晚上,我都与更多开发者见面,交流有关学生俱乐部可能开展的讲座和工作坊的想法。

接下来的主会议正式开幕。Jan Bramkamp 关于基于 ZFS 的快速 FreeBSD Jail 配置的演讲展示了利用巧妙的 ZFS 数据集技术实现亚秒级 jail 部署——这是我最期待的环节。我还非常喜欢 Hans-Jörg Höxer 关于 OpenBSD 的机密计算演讲,探讨了 AMD 的 SEV/SEV-ES 虚拟化扩展,以及 Roller Angel 关于 Ansible/Salt 自动化的课程,这为我提供了多个项目思路。

在晚间社交活动中,我甚至为 Gentoo Linux 打包了 Benjamin Stürz 的 fuse-ufs 驱动,并与 Kirk 和 Eric 进行了另一次愉快的交流。

最后一天以 Kirk McKusick 的《BSD 守护进程的历史》演讲开场,讲述了吉祥物演变的有趣轶事。随后 Patrick M. Hausen 分享了在 Hetzner 服务器上部署 FreeBSD 的经验,这与我的兴趣非常契合。最令人鼓舞的是 Jake Freeland 关于 Capsicum 的演讲,这促使我决定将本科毕业论文聚焦于 FreeBSD。

我要对 FreeBSD 基金会表示最深切的感谢,感谢他们资助我前往萨格勒布参加 EuroBSDCon。这次经历远远超出了我的预期——既富有教育意义,又充满启发性,更感受到社区的真诚温暖。

这是我的第一次 BSD 会议,但绝不会是最后一次。

展望将来,我计划通过 The :wheel Group 在我的大学开展 FreeBSD 讲座和工作坊,将其融入自己的工作流程,并在学习和未来职业生涯中持续为 FreeBSD 做贡献。

此致 敬礼,

Leah Budzicka

FreeBSD 已实现可重复构建及无 root 权限构建

  • FreeBSD now builds reproducibly and without root privilege

  • 2025 年 10 月 27 日

FreeBSD 基金会很高兴地宣布,FreeBSD 现已完成无需 root 权限即可进行构建的工作。我们已经为所有源代码的发布构建实现了无 root 基础设施支持,彻底消除了在 FreeBSD 发布流水线中使用 root 权限的需求。此项工作是 由 Sovereign Tech Agency(主权技术基金)委托的项目 的一部分。

上述更改目前已在 FreeBSD 开发分支中实现,并将在可能的情况下合并到 FreeBSD 15.0 的发布(RELEASE)分支中。

现在,在构建 FreeBSD 发布产物时,无需 root 权限即可创建设备文件、设置正确的文件所有权及挂载文件系统。这一改进提升了安全性,并简化了自动化构建过程。

现在,每份 FreeBSD 发布产物都能在无 root 权限的情况下完成构建:

  • 适用于 U 盘与 CD/DVD 安装介质的双模式 ISO 镜像

  • 适用于可引导 U 盘的 Memstick 镜像

  • 适用于虚拟机部署的 VM 镜像

  • 适用于 AWS、Azure 等云平台的云磁盘镜像

消除了构建流水线中对 root 权限的依赖,减少了攻击面和权限提升的风险。这使得构建环境更加安全与灵活,无论是官方基础设施还是社区贡献者都能从中受益。

可重复构建

与无 root 工作并行,FreeBSD 还引入了多项改进以提升构建的可重现性——确保相同的源代码输入始终能生成逐字节完全一致的二进制输出。这些更改覆盖了操作系统本身、发布工具链以及完整的构建过程。

主要改进包括:

  • 消除或标准化时间戳

  • 文件列表、包元数据等内容的稳定排序

  • 一致的构建环境,包括调试路径与区域设置

  • 在诸如文件系统镜像创建工具 mkimg(1) 等构建工具中实现可重现产物支持

可重复构建增强了整个软件供应链的完整性与透明度。它能够实现可验证的信任、改进调试与审计流程、简化持续集成,并有助于长期可维护性。

现在,FreeBSD 可以在无特权容器或受限环境中运行持续集成系统与自动化构建基础设施。在本地系统上,贡献者们也能够无需提升权限即可完整构建 FreeBSD RELEASE 版本。

FreeBSD 现已能够在无需 root 权限的情况下安全、可重现地完成构建。它更快、更安全、更透明——让任何人、在任何地方,都能以信任的方式构建 FreeBSD。

2025 年
  • FrankenPad T25 上的 FreeBSD 14.3

  • FreeBSD Jail 容器中的 Minecraft 服务器

  • FreeBSD 开发计划

  • ZFS 启动环境中的其他 FreeBSD 版本

2024 年 11 月

  • 苹果的开源基石:macOS 和 iOS 背后的 BSD 传统

  • 在动荡的开源世界中保持稳定:FreeBSD 的持久稳定性

  • 为什么你应该使用 FreeBSD

  • FreeBSD 13.4: 新特性及其发展历程

2024 年 7 月

  • BSD 老将:Michael J. Karels 逝世,享年 68 岁

  • 讣告——Michael "Mike" John Karels

  • 配置自己的 VPN——基于 OpenBSD、Wireguard、IPv6 和广告拦截

  • 如何在 FreeBSD 中指定 CPU 类型

2023 年 12 月

  • FreeBSD 新手?来参与社区吧

  • 介绍来 FreeBSD 的学生

  • EuroBSDCon 2023 旅行报告——Bojan Novković

  • 什么是开发播客?FreeBSD 项目的演变

2023 年 9 月

  • 认识 2023 年参与 FreeBSD 谷歌编程之夏项目的学生:Soobin Rho

  • 认识 2023 年参与 FreeBSD 谷歌编程之夏项目的学生:Aymeric Wibo

  • FreeBSD 企业工作组首次会议总结

  • 认识 2023 年 FreeBSD 谷歌编程之夏的学生:Sudhanshu Mohan Kashyap

2023 年 9 月以前

  • 在 FreeBSD 的 jail 中安装 NextCloud

  • 参与宣传:2023 年 5 月的 FreeBSD 开发者峰会和 BSDCan

  • 恭喜 FreeBSD 迎来 30 周年!为什么开源项目 FreeBSD 能够持续存在

  • 庆祝 FreeBSD 成立 30 周年:许可证

2000-2023

  • BSDCan 2023 旅行报告:Andrew Fengler

  • BSDCan 2023 旅行报告:Jake Freeland

  • AsiaBSDCon 2023 旅行报告:Chih-Hsin Chang

  • FreeBSD 基金会欢迎新成员加入

FreeBSD 网络文章集锦
目录
FreeBSD 特色开发项目(滚动更新)
zfs 速查手册

zfs 速查手册

  • 原文链接:OpenZFS Cheat Sheet

  • 作者:Benedict Reuschling ([email protected])

  • 原发布时间:2025 年 3 月

存储池配置

单个磁盘 无冗余,挂载为 /mypool,无需在 /etc/fstab 中添加条目。

条带(RAID-0) 无冗余,任意一块磁盘损坏都会导致数据全部丢失。性能高,可用容量为所有磁盘总和。

镜像(RAID-1) 可承受一块磁盘损坏,VDEV 在 zpool status 输出中显示为 mirror-0,可并行读取所有磁盘,写入速度较慢,总容量低于 RAID-0。

单奇偶校验(RAID-Z1) 至少需要 3 块磁盘,可承受 1 块磁盘损坏,奇偶校验信息分布在所有磁盘上,读写速度较快,性能相当,容量约为 66%。在 zpool status 输出中显示为 raidz1-0 VDEV。

双奇偶校验(RAID-Z2) 每个 VDEV 可承受 2 块磁盘损坏,比 RAID-Z1 慢,至少需要 4 块磁盘,可用容量约为 50%。

RAID10 至少需要 4 块磁盘,每个 VDEV 可承受 1 块磁盘损坏,读速快,写速为单个磁盘的一半,容量为 50%。是冗余性、容量和性能的良好折中方案。

三奇偶校验(RAID-Z3) 比 RAID-Z2 稍慢,每个 VDEV 可承受 3 块磁盘损坏,至少需要 5 块磁盘,可用容量约为 40%。

显示存储池状态

显示存储池状态【包括磁盘配置、错误信息、适用的更新、上次 scrub 时间(若有)】

显示存储池容量、已用空间和可用空间

显示存储池 I/O 统计信息

选项:

  • -v 显示各个设备

  • -w 显示 I/O 延迟

  • -r 显示请求大小直方图

显示存储池的管理命令历史

选项:

  • -l 详细格式

  • -i 仅显示事务组等事件

获取存储池属性及其值,并可使用 zpool set 修改默认值

特殊 VDEV

二级 ARC(L2ARC)

当数据不再适合存储在 ZFS 主内存缓存(ARC:自适应替换缓存)时,L2ARC 充当快速读取缓存。读取请求将由 L2ARC 处理,需使用高速存储设备(如闪存)才能获得显著效果。使用 cache 关键字将设备添加到存储池。

ZFS 意图日志(ZFS intent log, ZIL)

将同步写入转换为异步写入(不影响读取),使应用程序能更快确认数据已写入,类似于数据库事务日志。当写入完成并存储到底层存储介质后,ZIL 将被清除。ZIL 需要快速存储设备,但无需大容量。使用关键字 log 将设备添加到存储池。

备用盘(Spare)

备用盘在替换故障磁盘之前不会参与 I/O 操作,可以由手动操作或外部故障管理软件触发替换。使用关键字 spare 添加备用盘。


存储池扩展

将单磁盘存储池转换为 RAID1

为单磁盘存储池设备 /dev/nda0 添加镜像磁盘 /dev/nda1:

替换故障磁盘

将存储池中的故障磁盘 /dev/nda2 替换为设备 /dev/nda3:


存储池导入/导出

导出存储池

完成 I/O 操作后,从文件系统层次结构中卸载存储池。可在其他系统上导入以恢复存储池状态。

导入存储池

将存储池导入当前系统。

  • 扫描 ZFS 存储池标识

  • 通过 ID 或名称导入存储池

  • 重命名存储池

  • 在不同路径下挂载已导入的存储池(防止覆盖现有存储池)


ZFS 数据集

数据集位于存储池之上,并占用其空间。访问方式如下:mypool/data。每个存储池创建时,都会默认生成一个与其同名的顶级数据集。例如,执行以下命令:

将创建一个名为 test 的存储池和数据集,顶级数据集将挂载为 /test,并可包含子数据集。

创建数据集

创建一个名为 ds 的新数据集,大部分属性继承自父数据集:

创建多个数据集:


显示数据集信息

列出已用空间、可用空间和挂载点

按 ZFS 路径显示数据集

列出数据集及其子数据集

限制显示数据集的层级深度

仅显示数据集名称

移除输出头部

修改显示顺序

按列排序

倒序排列

显示存储池可用空间

列出每个数据集及其子数据集的可用空间和已用空间,包括快照和任何预留空间:

推荐:使用该命令代替 df -h。


重命名数据集

重命名数据集或在存储池层次结构内移动数据集,类似于 Unix mv 命令:


销毁数据集

模拟销毁(不会执行实际删除):

输出:

执行销毁并显示结果:

输出:

递归销毁数据集及其子数据集:


属性管理

数据集通过继承父数据集的大部分属性来提高灵活性。子数据集可根据需要覆盖这些属性。仅可更改 SOURCE 列中的默认属性,存储池的属性规则相同。

显示属性

多种方式可以查看存储池和数据集的属性:

  • 查看存储池的属性

  • 查看数据集的属性

  • 查看单个属性(容量)

  • 查看多个属性(容量与健康状态)

修改属性

  • 禁用访问时间更新(可提高性能):

  • 更改挂载点:

自定义属性

可为数据集定义自定义属性(key=value),数据集会继承这些属性,但可更改其值。

  • 创建自定义属性:

  • 列出自定义属性:

  • 重置属性值(继承父级值):

  • 删除自定义属性(递归删除):


数据完整性检查(Scrub)

ZFS 在数据存储时会计算并存储校验和,覆盖整个数据集层次结构。I/O 错误、驱动故障、内存损坏、损坏的电缆等因素可能导致校验和不匹配。

如果存储池具有足够的冗余(如镜像或 RAID-Z),ZFS 可以检测到这些错误并自动修复(自我修复)。

建议 每月运行一次 Scrub,重新计算校验和。如果发现数据损坏,ZFS 会从冗余 VDEV 获取正确的数据并修正错误。

启动 Scrub:

查看 Scrub 进度和错误信息:

ZFS 无需 fsck,因为 ZFS 自带数据完整性检查机制。

卷(Volumes)

ZFS 卷使用连续的存储池空间,并可通过 iSCSI 在网络上导出。当使用非 ZFS 文件系统格式化卷时,该文件系统仍可自动利用 ZFS 的底层功能。


创建卷

创建一个 10GB 的 ZFS 卷:


创建稀疏卷(Sparse Volume)

稀疏卷是 超分配 的卷,不会立即占用预留空间,而是随着数据的增长逐步填充。

创建一个 1PB(1 PB)稀疏卷:

配额(Quota)

每个数据集默认可以使用整个存储池的空间。配额用于限制数据集的最大存储量。ZFS 严格 执行配额限制,任何超出配额的写入都会被阻止。


定义配额

ZFS 默认无配额。可使用 zfs set 命令为特定数据集设置配额:

该配额适用于该数据集及其子数据集(包括未来创建的子数据集)。这些数据集 共享 配额总量。

如果仅想限制 父数据集本身,不影响子数据集,则使用 refquota:

用户和组配额

  • 限制特定用户的存储空间:

  • 限制某个用户组的存储空间:


显示配额信息

  • 查询数据集的配额:

  • 查询 refquota:

  • 查询用户配额:

  • 查询组配额:


移除配额

将数据集的配额取消(refquota 也同样适用):


预留空间(Reservation)

预留(Reservation)确保存储池中一定量的空间始终可用,不受其他数据集占用。这减少了存储池的可用空间,但可以防止单个数据集占满整个池,有助于容量规划。

定义预留空间

使用 reservation 属性设置数据集的预留空间:

预留空间 会被子数据集继承。如果只想对该数据集本身生效,而不影响子数据集,则使用 refreservation:

显示预留空间

  • 查看数据集的预留空间:

  • 查看 USEDREFRESERV 列中的预留空间:

移除预留空间

将 reservation 或 refreservation 设为 none:


快照(Snapshots)

快照提供了一种 快速保存数据集只读状态 的方法,可用于恢复数据集到特定时间点的状态。无需回滚整个快照,也可以单独恢复其中的文件。

ZFS 通过 .zfs 目录提供只读访问,可从快照中读取文件。


创建快照

  • 创建快照:

  • 简写命令:

  • 递归创建快照(包含所有子数据集):


显示快照

  • 列出所有快照:

  • 列出数据集及其所有子数据集的快照:


显示自上次快照以来的写入数据量

  • written 属性显示自上次快照以来写入的数据量。

  • 配合 used 和 referenced 属性可以直观查看存储池空间使用情况:


比较快照

使用 zfs diff 比较当前数据集与某个快照之间的更改:

输出说明:

符号
说明

对比 两个快照 之间的更改:

快照回滚(Snapshot Rollback)

回滚操作会 丢弃当前数据集的状态,恢复到指定快照的状态。所有在该快照之后创建的数据 都会被删除。

如果要回滚到更早的快照,必须先使用选项 -r 删除所有中间快照:


挂载快照(Snapshot Mounting)

可将快照 以只读方式 挂载到文件系统:


删除快照(Snapshot Deletion)

模拟删除(Dry Run)

建议先执行 模拟删除(选项 -n)查看即将删除的内容,配合 -v 显示详细信息:

如果确认无误,去掉 -n 选项执行删除:

递归删除快照

删除指定快照及其所有子快照:

删除快照范围(Delete Range)

假设快照列表如下:

  • 删除快照 @b 至 @d(含 @d):

  • 删除 @b 及其后所有快照:


快照保护(ZFS Holds)

ZFS 能为快照创建 保护标记(tag),被标记的快照不能删除。可以对一个快照添加 多个 保护标记,只有 所有标记都被移除 后,快照才可以删除。

创建快照保护(Hold)

递归列出快照的所有 Holds

解除快照保护(Release Hold)


克隆(Clones)

克隆是 可写的快照副本,创建的克隆数据集 包含原快照的所有数据。

创建克隆

克隆数据集的 origin 属性指向其 来源快照:

解除克隆对原快照的依赖(Promote Clone)

ZFS 不允许删除 有依赖克隆的快照。要删除原快照,必须 先提升克隆为独立数据集(promote):

此时:

  • origin 属性消失

  • 该快照成为克隆的新基础

  • 原快照可安全删除

删除克隆(Clone Removal)

可像删除普通数据集一样删除克隆:

加密(Encryption)

ZFS 支持数据集加密,每个数据集可以有独立的密钥。一些元数据仍然保持未加密状态,以便执行 scrub 等操作。

创建加密数据集(Create Encrypted Dataset)

设置数据集的加密密码:

查看加密状态(Load Status)

获取密钥状态:

加载密钥(Load Key)

解锁数据集:


权限委派(Delegation)

ZFS 允许将 ZFS 命令的权限 委派给非 root 用户。

授权用户(Delegate Permission to User)

授予用户 joe 对 atime 属性的修改权限:

查看现有权限(Display Delegations)

撤销用户权限(Remove Delegation)

移除 joe 的 compression 权限:

授权给用户组(Delegate Permission to Group)

授予 mygroup 组 atime 属性权限:

允许用户委派权限(Delegate Permission to Delegate)

授予 jill 允许其他用户管理数据集权限的权限:

创建权限集合(Create a Set of Permissions)

创建权限集合 @myset,包含 mount、snapshot、rollback 和 destroy 权限:

应用权限集合(Use Permission Set for Delegations)

将 @myset 赋予用户 jill:


快照发送与接收(Sending and Receiving Snapshots)

ZFS 能以字节流的方式 本地和通过网络传输快照,可用于备份。

将快照写入文件(Write Snapshot to a File)

要恢复快照,可使用 zfs receive,并通过 -v 选项显示详细信息:

从快照创建数据集(Create Dataset from Snapshot)

显示传输详细信息:

不使用中间文件进行复制(Replication Without Intermediary File)

直接通过管道传输快照数据:

通过 SSH 复制(Replication via SSH)

使用 SSH 传输快照到另一台主机的 ZFS 池:


权限管理(Send and Receive Permissions)

发送权限(Send Permissions)

允许 sender 用户发送数据集:

接收权限(Receive Permissions)

接收方 receiver 需要额外的权限:

新型 ZFS 启动环境工具

  • New ZFS Boot Environments Tool

  • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

  • 2018/08/24

注意

注:15.0-RELEASE 中仅存在命令 bectl。

大约一个月前,我有幸在 上做了关于 ZFS 启动环境 的演讲。在演讲的最后,我提到了在 FreeBSD 上管理 ZFS 启动环境 的工具发展历史。

Pawel Jakub Dawidek——他也参加了 PBUG #3 会议——建议我应该尝试将 beadm 纳入 FreeBSD 基本系统。我也从很多 beadm 用户那里听到过这个想法,他们反复询问为什么 FreeBSD 基本系统没有内置 beadm。因此,在 PBUG #3 结束后,我正是做了这件事。我创建了新的 PR————令我(惊喜地)发现,他们将新工具 bectl 内置到了 FreeBSD 基本系统!现在,我们的 ZFS 启动环境 工具家族中新增了一员——工具 bectl。

当然,我仍会维护和更新工具 beadm,它仍可通过 FreeBSD Ports 中的 获取。因为该工具是用 POSIX /bin/sh 编写的,所以调试快速且易于修改。简单来说(TLDR):bectl 是用 C 语言实现的 beadm,它已引入到了 FreeBSD 基本系统,这意味着它将成为 FreeBSD 12.0-RELEASE 的一部分。目前 bectl 已经可以在 12.0-ALPHA2 镜像中使用。

对比

新的 bectl 工具还处于非常早期的阶段,目前(尚未)能完全替代工具 beadm。下面是 bectl 和 beadm 工具使用信息的简单对比。

……以及新的 bectl 工具。

例如,bectl 目前无法重命名正在使用/已挂载的启动环境,而 beadm 可以。

可以通过命令 zfs rename -u ... 重命名挂载到 / 的 ZFS 数据集(这正是 beadm 在底层所做的操作),作为 bectl 工具的替代方案。

随后它会像平常一样以新名字显示在 bectl 下,如下所示:

bectl 相较于 beadm 的一个很棒的新功能是可以在指定的启动环境中动态创建 FreeBSD Jail。

下面展示 bectl 创建 FreeBSD Jail 的实际操作。

如果你从 beadm 迁移到 bectl,你也需要更加小心,因为 bectl 不会让你进行确认 :🙂:

例如,beadm 工具会在销毁指定的启动环境前询问你是否确认。而 bectl 工具则会直接删除,不会在屏幕上出现任何提示。

bectl 缺少的功能之一是 Ansible 插件支持。beadm 支持 Ansible 插件,因此如果你希望使用该配置管理工具,那么使用 bectl 时就需要退回到 原生 Ansible 模块 :🙂:

好消息是 beadm 和 bectl 可以在同一台主机上共存,所以你不必二选一。你仍然可以用 beadm 工具处理日常任务(或用于 Ansible 模块),而用 bectl 来处理 jail/unjail 等选项。

我认为随着时间推移,bectl 会增加所需功能,而将这样的工具纳入 FreeBSD 基本系统无疑是个受欢迎的补充。

更新 1

文章被收录在 集中。

感谢分享!

更新 2

最后,我有时间在更新的 FreeBSD-12.0-ALPHA6 版本中再次测试新的 bectl 命令,看是否有改进。

现在在无参数调用时,bectl 不会显示缺少命令的提示。

可以使用 bectl 命令重命名当前正在使用的启动环境。

我注意到的最后一点是,bectl jail 命令在退出后不会保持 Jail 处于启用/运行状态,虽然只是外观上的变化,但很重要。

最后,最简单的迁移路径是创建一个简单别名:

… 或针对 (T)CSH shell:

FreeBSD 爱好者团结起来支持新兴项目 zVault——社区分支继 TrueNAS CORE 之后继续发展

  • 原文:FreeBSD fans rally round zVault upstart

  • 作者:iconLiam Proven

  • 2025 年 5 月 12 日

TrueNAS 依然活跃健康,但 iXsystems 已将重点转向基于 Linux 的 SCALE 版本。对于仍然坚持使用 CORE 的 FreeBSD 忠实用户来说,新的竞争者正在崛起:zVault。

zVault 项目 是一款基于 FreeBSD 13.3 的全自由开源操作系统,专为网络附加存储(NAS)服务器设计。该项目刚刚发布了 第二个预览版本,解决了首个预览版本中存在的一些知识产权问题。目前这仍是预览版本,我们绝对不建议将任何重要数据存储在上面,但这是一个令人鼓舞的信号。

正如我们 的,iXsystems 已将其基于 FreeBSD 的 NAS 操作系统 TrueNAS CORE 转入维护模式。其继任产品是 ,该版本以 Debian Linux 作为底层操作系统,而非 FreeBSD。公司强调,“没有人会因为转向 Debian 而被‘遗弃’”,这是它对 The Register 旗下 Blocks & Files 网站的说法。事实上,借助 ZFS 的 ——完整且可启动的操作系统快照——甚至可以在原地将 FreeBSD 版本迁移到新的 Linux 版本。

但如果你不想在存储服务器上运行 Docker 容器,或者不想将存储集成到 Kubernetes 集群中,那么好消息来了:zVault 已经接手了 TrueNAS CORE 的最终 FreeBSD 版本。

zVault 在二月底发布了 ,但 iXsystems 的 Kris Moore 针对此版本 ,声称其中包含了 iXsystems 的知识产权,随后 zVault 项目撤回了该 ISO 镜像。现在,zVault 团队正在努力剥离 iXsystems 的残留部分,移除所有剩余的专有文件,力求打造纯自由开源版本。

FreeBSD 博主 Vermaden 发布了更新,表达了一些 FreeBSD 社区成员对 iXsystems 此举的看法,标题为“”。这篇更新是对他们去年发布的文章“”的补充。文章中附带了一张截图,显示第一个版本中有超过 50 个文件涉及了 TrueNAS 企业许可协议的内容,。

zVault 项目主页上的 相对简单。第一步:发布一个可用版本;第二步:发布稳定版本;第三步是更新到 13.5 版本;第四步则是在此基础上切换到当前的 FreeBSD 14。

与此同时,还有 ,它基于早期的 FreeNAS 版本继续开发,早于 iXsystems 的介入,没有后者投入的现代化改进。它的部署比 TrueNAS CORE 要复杂些,网页界面也明显不如 TrueNAS CORE 精致,但它依然存在,能用,并且持续获得更新。 ®

主权科技基金将投资 68.64 万欧元用于 FreeBSD 基础设施现代化

原文地址:Sovereign Tech Fund to Invest €686,400 in FreeBSD Infrastructure Modernization

2024 年 8 月 26 日

投资将加速零信任构建、软件物料清单(SBOM)、安全工具和开发者体验的提升

2024 年 8 月 26 日,科罗拉多州博尔德市 致力于推动开源 FreeBSD 操作系统发展及支持社区的 FreeBSD 基金会宣布,德国主权科技基金(Sovereign Tech Fund,STF)已同意向 FreeBSD 项目投资 68.64 万欧元,以推动改进基础设施、安全性、合规性及开发者体验。

由 FreeBSD 基金会组织和管理的这一工作将于 2024 年 8 月开始,并持续到 2025 年,主要涉及以下五个关键项目:

  • 零信任构建:改进工具和流程

  • 自动化 CI/CD:优化软件交付与操作

  • 偿还技术债务:实施工具和流程以减轻技术债务

  • 安全控制:现代化、加固安全工件,如 FreeBSD Ports 和软件包,助力合规性

  • 改进 SBOM:优化和实施 FreeBSD 软件物料清单(SBOM)的新工具和流程

开发者是每个开源项目的核心。主权科技基金对 FreeBSD 基础设施的投资将确保开发者的一流体验,同时维护和扩展 FreeBSD 以其闻名的安全性和数字主权。

德国主权科技基金委托的工作与美国国家网络总监办公室(ONCD)于 2024 年 8 月 9 日发布的 密切相关。该报告整合了 2023 年有关加强开源软件生态系统安全的关键优先事项的反馈意见。通过增强安全控制和 SBOM 工具,FreeBSD 基金会帮助确保 FreeBSD 在改进漏洞披露机制和软件安全基础方面处于前沿。

“主权科技基金很高兴赞助 FreeBSD 项目,”德国主权科技基金联合创始人 Fiona Krakenbürger 表示。“这一针对关键数字基础设施的投资将加速 FreeBSD 的现代化,提升安全性并改善开发者体验。FreeBSD 的广泛应用意味着这些改进将在全球公共部门、研究领域以及商业用户中产生深远影响。我们很高兴为其持续现代化做出贡献,以更好地服务于公共利益和 FreeBSD 社区。”

“我们非常感谢主权科技基金的这笔重要投资,这将进一步提升 FreeBSD 开发者和用户的安全性及基础设施。”FreeBSD 基金会执行董事 Deb Goodkin 表示,“在过去的 30 年中,FreeBSD 项目始终处于开源安全性、兼容性和可靠性的前沿。各国政府越来越认识到开源项目如 FreeBSD 在共享数字基础设施中发挥的重要作用。这项主权科技基金委托的工作将为面临新法规的商业用户,以及公共部门、学术界和个人用户,提供必要的透明度、可审计性和信任。”


关于主权科技基金(STF)

主权科技基金()支持开放数字基础设施的开发、改进和维护,以服务公共利益。其目标是可持续地加强开源生态系统,关注安全性、兼容性、技术多样性以及代码背后的人。主权科技基金由德国联邦经济事务和气候行动部(BMWK)资助,并由德国联邦颠覆性创新署(SPRIND)主办和赞助。


如何参与:

FreeBSD 基金会承诺保持透明和协作的沟通。将通过已建立的公共渠道发布全部公告和更新。如有问题或者希望参与潜在的咨询委员会,为主权科技基金资助的工作提供反馈和指导,请联系 [email protected]。


关于 FreeBSD 基金会

FreeBSD 基金会是一家 501(c)(3) 非营利组织,致力于支持 FreeBSD 项目和社区。基金会接受个人和企业的捐赠,用于开发功能、雇佣软件工程师、改进构建和测试基础设施、通过线上和线下活动宣传 FreeBSD,以及提供培训和教育材料。基金会还代表 FreeBSD 项目处理法律事务,是合同、许可和其他法律安排的公认实体,完全依赖捐赠支持。了解更多信息,请访问 。

认识 2023 年参与 FreeBSD 谷歌编程之夏项目的学生:Soobin Rho

  • 原链接:Meet the 2023 FreeBSD Google Summer Of Code Students: Soobin Rho

  • 发布日期:2023-8-24

  • 译者:ykla & ChatGPT

自从 2005 年谷歌编程之夏项目创立以来,FreeBSD 项目很自豪地参与其中。随着 2023 年季节即将结束,基金会请几位我们的学生分享更多关于他们自己以及他们与该项目合作经验的信息。

问:请简单介绍一下你自己,以及你在教育旅程中的进展。

我是 Soobin Rho,这是我在南达科他州的奥古斯塔纳大学的第三个学年,预计于 2025 年毕业。我主修哲学、数学和计算机科学。

我出生于韩国,在迪拜长大,几年前来到美国上大学。我的目标是白天在一家有使命感的优秀公司工作,然后在空闲时间做我真正关心的事情,比如为环境和可持续性开展开源项目。

问:你以前有参与过谷歌编程之夏项目吗?

没有,2023 谷歌编程之夏是我第一次参与。我是在 Hacker News 上第一次听说谷歌编程之夏的。其中一条评论提到 FreeBSD 是参与的开源项目之一。所以,我就申请了。我从 FreeBSD 维基的谷歌编程之夏项目创意列表中选择了我的项目。

问:你为什么想与 FreeBSD 合作?

我尝试过很多操作系统(虽然我不会逐一列举)也尝试过很多桌面环境。然而最终,至少目前来说,我决定我最喜欢的编码环境是没有桌面环境,只有终端的 FreeBSD 加上 vim 和 tmux。

当然,每当我需要使用图形界面时,我会不时地回到其他操作系统。尽管如此,它就是感觉对了。我所有的开发工作都是通过 FreeBSD 进行的。加入 2023 谷歌编程之夏是我第一次为 FreeBSD 做贡献,但我也打算继续作为贡献者,并继续维护 mfsBSD 集成。

问:请简要介绍一下你的谷歌编程之夏项目。

说到 mfsBSD,这是由 Matuska 于 2007 年创建的,mfs 代表内存文件系统。基本上,一旦你在系统中安装了 mfsBSD 并引导到它,整个操作系统现在都在内存文件系统下运行。这意味着你现在可以做很多事情,比如恢复操作和系统诊断。特别是,我对 mfsBSD 的最喜欢用途之一是用于我的一台只有一块硬盘的笔记本电脑。我可以在硬盘中引导 mfsBSD,然后在我安装了 mfsBSD 的特定的硬盘上安装 FreeBSD。由于 mfsBSD 中的每个文件都被移动并加载到内存文件系统中,甚至可以删除原始磁盘,并使用 mfsBSD 中的 bsdinstall 完全覆盖为全新的 FreeBSD 实例。

我的项目将 mfsBSD 集成到 FreeBSD 发布工具集中,这样 mfsBSD 镜像(.img 用于光盘,.iso 用于光盘)现在将在 FreeBSD 主页上提供。【注 1】

问:到目前为止,你从这个经验中学到了什么?

在接手这个项目之前,我对 MAKE(1) 一无所知。阅读 /usr/src/Makefile 和 /usr/src/release/Makefile 对我帮助很大。此外,阅读 /usr/src/release/Makefile.vm 非常有价值,事实上,我很多的代码都是基于这些 make 文件的。

问:与 FreeBSD 项目合作的经历如何?

有趣而令人兴奋!每周与我的导师 Joseph Mingrone 和 Juraj Lutter 进行会议很有趣。看到我的代码生成了我自己可以使用的 mfsBSD 镜像,以及为所有需要的其他人生成的镜像,这让我感到兴奋。

FreeBSD 在 OCI 运行时规范 v1.3 中获得正式支持

  • 原文:FreeBSD Officially Supported in OCI Runtime Specification v1.3

  • 发布日期:2025 年 11 月 4 日

FreeBSD 已被纳入 Open Container Initiative(OCI)运行时规范 的 1.3 版本中,成为官方支持的平台。该版本于 2025 年 11 月 4 日发布。这一里程碑标志着 FreeBSD 的重大成就,体现了社区志愿者多年来为将云原生容器技术引入该平台所做的不懈努力。

FreeBSD 的重大进步

FreeBSD 纳入了 OCI 运行时规范,是个分水岭式的时刻,使 FreeBSD 成为现代云原生工作负载的一级平台。官方的 OCI 支持意味着 FreeBSD 用户现在可以放心地利用完整的容器工具和编排平台生态系统,因为他们使用的是标准化、厂商无关的规范。对于已经在生产环境中运行 FreeBSD 的组织来说,这为采用符合行业标准的容器化应用部署策略打开了大门,使 FreeBSD 成为云基础设施、边缘计算和企业部署的更具吸引力的选择。

基于 FreeBSD 虚拟化传统的扩展

新增的云原生容器支持,进一步强化了 FreeBSD 已经非常成熟的虚拟化能力,尤其是强大的 FreeBSD jail 技术——它已成为 FreeBSD 二十多年来的基石。实际上,FreeBSD 上的 OCI 容器是通过 jail 作为底层隔离机制实现的,将 jail 的安全性和资源管理优势与符合 OCI 标准的容器可移植性和生态系统优势结合在一起。这种技术结合为 FreeBSD 用户带来了两全其美的体验:既有 jail 所具备的轻量、安全隔离,又拥有容器在现代软件开发中广泛普及的标准化工具链和镜像格式。

凝聚多年努力的社区成果

这一成就凝聚了由志愿者 Doug Rabson 领导的长期开发工作,并得到了来自 OCI 社区、FreeBSD 项目以及 FreeBSD 基金会众多贡献者的支持与合作。实现官方 OCI 支持的历程包括以下几个关键里程碑:

  • 2021 年:Samuel Karp 发布了 runj,这是 FreeBSD 的首个 OCI 运行时,并支持 containerd,证明了在该平台上运行 OCI 容器的可行性。

  • 2022 年:Doug Rabson 为 Buildah 和 Podman 添加了 FreeBSD 支持,这两个关键的容器管理工具的改进要求对 FreeBSD 内核进行重要修改,以满足 OCI 运行时规范的要求,为今天的正式认可奠定了基础。

  • 2024 年:Dave Cottlehuber 领导将 FreeBSD 官方 OCI 镜像纳入的工作,首次出现在 FreeBSD 14.2 中,可在 Docker Hub 和 GitHub Container Registry 上获取这些镜像。

  • 2025 年:Doug Rabson 领导将 FreeBSD 作为平台添加到 OCI 运行时规范中的工作,该支持在 v1.3 版本中正式提供。

FreeBSD 基金会借此机会感谢 Samuel Karp 与 Doug Rabson 在推动此项计划中所付出的不懈努力,同时向所有为使 FreeBSD 成为完全受支持的 OCI 平台而作出贡献的人员致以诚挚谢意。

展望将来

随着官方 OCI 运行时规范支持的确立,FreeBSD 比以往任何时候都更有能力满足现代基础设施与应用开发的需求。我们期待看到社区如何利用这一能力,在 FreeBSD 上构建创新解决方案。

确保最新动态:

认识 2023 年夏季滑铁卢大学合作学生:Naman Sood

  • 原文链接:Meet The Summer 2023 University of Waterloo Co-Op Student: Naman Sood

  • 发布日期:2023.9.7

  • 译者:ykla & ChatGPT

FreeBSD 基金会继续与滑铁卢大学合作项目成功合作。自 2017 年以来,我们已经招募了 15 名实习生,其中一些人已经回来做过多次实习。我们还有两名实习生成为了正式的贡献者,许多人继续为项目做出贡献。今年夏季合作学生生是 Naman Sood,我们坐下来与他聊了聊,了解他以及他选择为 FreeBSD 工作的原因。

姓名: Naman Sood

问:请简要介绍一下自己以及你的教育经历。

我来自印度,2019 年来到加拿大就读滑铁卢大学,主修计算机科学。目前我已经读到了第四年的一半,计划于 2024 年春季毕业。

问:你已经参加了多少次合作实习?

FreeBSD 是我第五次的合作实习。

问:为什么你想要在 FreeBSD 基金会工作?

我一直喜欢编写与计算机硬件的内部机制有关且为其他程序提供良好接口的底层代码。FreeBSD 基金会为我提供了一个特殊的机会,可以实际参与到全世界的人们使用的实际系统的开发中,而这种工作正是我所热衷的。此外,在开源生态系统中工作的经历对我来说是一个难得的学习机会,使我更加自如地为我每天使用的软件做出贡献。

问:你希望从这个实习中学到什么?

我最想从这个实习中获得的经验是在一个真正的、可用于生产的操作系统内核上进行一些“hack”活动的经验。我所在大学的操作系统课程非常出色,但更多地是对整体概念的引导。它没有涉及到我认为使在底层级别工作变得有趣的许多复杂细节,而 FreeBSD 则为我提供了在这种环境下工作的实践和经验。

问:你目前在做什么工作?

我目前正在尝试将 FreeBSD 的 VPS 子系统()从 FreeBSD 10 移植到 14,具体来说,我正在考虑将 TCP 检查点和跨进程故障转移进行移植。例如,如果你有一个多进程的 Web 服务器,其中一个进程崩溃,它可以将其 TCP 连接移交给另一个进程。从客户端的角度来看,即使面对此故障,也可以继续正常运行。

问:到目前为止,你对 FreeBSD 的经验如何?

非常好!在这个大型的、由志愿者推动的开源软件项目中,自然会出现技术和社交方面的挑战。但这些挑战正是我来这里应对的,我在我的工作中得到了非常有益和愉快的经验。

Realtek RTL8188CUS – USB 802.11n 无线网卡评测

  • 原文:

  • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

  • 发布时间:2020/11/18

在新款笔记本上使用 FreeBSD 时,有时你会发现自带的 WiFi 芯片不受支持……或者在 RELEASE 版本中尚未支持,而支持仅存在于你不想使用的开发版本 CURRENT 中。

这时,芯片 Realtek RTL8188CUS 就派上用场了。

使用 ZFS 启动环境更新 FreeBSD

  • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

  • 发布时间:2021/02/23

我以强烈支持 ZFS 启动环境 而闻名……而这并非没有理由。我已经多次说明了支持的原因,但大多数(或全部)内容在这里被浓缩了————在我关于此的演示中。即将发布的 FreeBSD 13.0-RELEASE 看起来非常有希望。在许多测试中,它的速度几乎是 12.2-RELEASE 的两倍。哎呀!

详细测试可以在 网站上查看。由于我已经安装了 12.2-RELEASE,我想测试 13.0-BETA*,看看对我来说重要的功能——比如正常工作的挂起/恢复——在新版本中是否如宣传般正常工作。这正是使用

从 PlayStation 到路由器,你很可能一直在使用 FreeBSD 而不自知

  • 原文:

  • 作者:iconLiam Proven

  • 2025 年 4 月 28 日

先有操作系统,后建基金会——那么基金会到底在做什么?

采访过 许多开源自由软件项目由非营利基金会支持。FreeBSD 基金会就是其中一个例子,FreeBSD 基金会由 Meta 软件工程师 Justin T Gibbs 创立。他在接受 The Register 采访时谈到了 FreeBSD 的版权理念、基金会的职能以及其重要性。

认识 2023 年 FreeBSD 谷歌编程之夏的学生:Sudhanshu Mohan Kashyap

  • 原文地址:

  • 发布日期:2023-8-29

  • 译者:ykla & ChatGPT

自 2005 年以来,FreeBSD 项目一直以参与谷歌编程之夏计划为傲。随着 2023 季接近尾声,基金会要求我们的一些 GSoC 学生分享更多关于自己以及他们与项目合作的经验。

2023 年全球开放大会报告

  • 原文链接:

  • 作者:Drew Gurkowski

  • 译者:Canvis-Me & ChatGPT

2023 年 11 月 14 日

在上个月,我前往北卡罗来纳州的罗利参加了 2023 年的 All Things Open 大会。虽然基金会过去曾在展台设有工作人员,但这是我第一次亲自参加这个会议。我在会议前一天飞到了罗利,并在设置基金会展台之前有时间参观了这个城市。我结束了这一天,尝试了我的第一顿北卡罗来纳烤肉,真是让人满意!

认识 2023 年参与 FreeBSD 谷歌编程之夏项目的学生:Aymeric Wibo

  • 原文链接:

  • 发布日期:2023-8-29

  • 译者:ykla & ChatGPT

自从 2005 年谷歌编程之夏项目创立以来,FreeBSD 项目很自豪地参与其中。随着 2023 年季节即将结束,基金会请几位我们的谷歌编程之夏学生分享更多关于他们自己以及他们与该项目合作经验的信息。

为什么选择 FreeBSD?Metify 展示迁移到 FreeBSD 如何对两个新产品进行增强

  • 原文链接:

  • 译者:Canvis-Me & ChatGPT

2023 年 11 月 2 日

FreeBSD 厂商峰会始终是一个绝佳的机会,让人更深入地了解公司是如何以及为何使用 FreeBSD。Metify,这家背后是屡获殊荣的 Mojo 平台的公司,将在今年的峰会上展示两款创新产品,为大家提供这样的机会。

Metify Mojo 是一个虚拟设备,可以从所有地方被发现、配置和维护服务器。Metify 的首席技术官 Ian Evans 将讨论 FreeBSD 在创建 Mojo 中的关键角色。

什么是开发播客?FreeBSD 项目的演变

  • 原文链接:

  • 译者:Canvis-Me & ChatGPT

基金会执行董事 Deb Goodkin 在 中和《SD Times》的主编 David Rubinstein 一起谈论了 FreeBSD 的 30 周年纪念,以及这些年它是如何成长和变化的。

ZFS 启动环境详解
使用 ZFS 启动环境更新 FreeBSD
Realtek RTL8188CUS – USB 802.11n 无线网卡评测
为什么是 FreeBSD?
使用 Pacemaker 与 Corosync 构建 FreeBSD 集群
在 FreeBSD 上以 lsblk(8) 风格列出块设备
新型 ZFS 启动环境工具
FreeBSD 企业级 1 PB 存储
在 FreeBSD 容器上运行 RabbitMQ 集群
修复 FreeBSD 上的依赖
不为人知的 pkg(8) 功能
服务之力:FreeBSD 电源管理
我的 FreeBSD 故事
在 FreeBSD 上部署 Syncthing
FreeBSD 上的高可用 DHCP 服务器
Leah Budzicka EuroBSDcon 2025 旅行报告
Robert Clausecker EuroBSDcon 2025 旅行报告
FreeBSD 在 OCI 运行时规范 v1.3 中获得正式支持
FreeBSD OCI 容器简介
为什么你应该将所有东西从 Linux 迁移到 BSD
选择 FreeBSD 而非 GNU/Linux 的技术性原因
GPL 之殇
FreeBSD 已实现可重复构建及无 root 权限构建
利用 FreeBSD Capsicum 框架实现程序沙箱化
简单而轻松的 FreeBSD Jail
Chuck Tuffli 的 BSDCan 2025 旅行报告
Mark Johnston 的 BSDCan 2025 旅行报告
FreeBSD Periodic 系统简介
如何安装和配置 Galene 视频会议服务器
FreeBSD 基金会欢迎董事会新成员:John Baldwin
FreeBSD 与 HiFi 音频设置:比特完美、均衡器、实时处理
FreeBSD 开发者正在决定是否为 FreeBSD 15 的 WiFi 采取稳定版策略
伯克利 Unix 二十年——从 AT&T 掌控到自由分发
BSD 在 Unix 发展中的角色
FreeBSD 爱好者团结起来支持新兴项目 zVault——社区分支继 TrueNAS CORE 之后继续发展
从 PlayStation 到路由器,你很可能一直在使用 FreeBSD 而不自知
FreeBSD 并没有死,别听信那些夸张的说法
FreeBSD 上的 ZFS 日志压缩
为 FreeBSD 发声:FOSDEM 2025 参会报告
谁在使用 FreeBSD(基金会官方版本)
如何将基于 Electron 的应用程序移植到 FreeBSD
FreeBSD:原始操作系统发行版的火炬传承者
浏览 FreeBSD 新的季度和两年一次发布计划
FreeBSD 日专访 BSD 守护神 Beastie
Quantum Leap Research 和 FreeBSD 基金会将投资 75 万美元以改善笔记本电脑支持和用户体验
主权科技基金将投资 68.64 万欧元用于 FreeBSD 基础设施现代化
使用 BIOS 引导和 UEFI 引导的 GPT 分区的区别和制作方法
通过替换 ZFS 镜像池中的磁盘来扩容
通过将 ZFS 池构建为镜像结构,消除异常数据的影响
ZFS 池破坏实验
FreeBSD ports 开发技术研究
FreeBSD pkg 命令概述
portsnap 被淘汰了,本应由 git 代替,但结果我发现自己用的是 got
ccache 在构建 FreeBSD 的 buildworld 时的效率
关于对 FreeBSD 发布计划和生命周期的修订
EuroBSDCon 2023 旅行报告——Mark Johnston
TalkDev:探索开源的未来
为什么选择 FreeBSD?Metify 展示迁移到 FreeBSD 如何对两个新产品进行增强
FreeBSD 基金会宣布通过 SSDF 认证
2023 年全球开放大会报告
FreeBSD v14:恪守类 Unix 操作系统传统,提升安全性与性能
认识 2023 年夏季滑铁卢大学合作学生:Naman Sood
FreeBSD 基金会 2023 年暑期实习生:Jake Freeland
第二次企业工作组会议回顾
OpenBSD 与 FreeBSD:有何不同,哪个更好?
聚集在开放领域工作的公益和慈善基金会
在 Linode 上安装 pfSense
在 FreeBSD 的 jail 中安装 NextCloud
将 FreeBSD 上的 Ansible 主机和客户机都安装在 Jail 中
FreeBSD 简介 | BSD.pw 研讨会
如何在 FreeBSD 上安装 Python
升级到 FreeBSD 13.2 的十大理由
采访 FreeBSD 基金会执行董事 Deb Goodkin
我们使用开源的 FreeBSD 作为企业操作系统的 5 个原因
关于 BSD 与 Linux 的典型讨论
OpenBSD 太棒了
systemd 背后的真正动机
systemd 在任何地方都不安全
如何在 FreeBSD 上设置一个简单且实际工作的 WireGuard 服务器
FreeBSD 与研究社区
在 OpenBSD 和 FreeBSD 之间选择的区别
FreeBSD 是一个令人惊叹的操作系统
留意日期:2023 年 11 月的自由软件组织厂商峰会
JENNY 日常使用的系统:FreeBSD 13.2
FreeBSD Ports 中的 OPTIONS 功能介绍——使用 OPTIONS_SET/OPTIONS_UNSET/NO_DIALOG 进行操作和实践
FreeBSD Bhyve 上的 PCI 直通
2023 年 FreebBSD 谷歌编程之夏学生介绍:Raghav Sharma
2023 年 7 月软件开发项目进展报道
用于研究的 FreeBSD:CHERI/Morello
在 FreeBSD Jail 中使用 OpenRC 启动并运行 Devuan GNU+Linux 系统
第 20 届南加州 Linux 博览会(SCaLE)会议报告
FOSDEM 2023 会议报告
EuroBSDCon 2022 旅行报告:Patrick McEvoy
EuroBSDCon 2022 旅行报告:Muhammad Moinur Rahman
遇见 2022 年 FreeBSD 谷歌编程之夏学生:Bojan Novković
遇见 2022 年 FreeBSD 谷歌编程之夏学生:Koichi Imai
BSDTW 2017 旅行报告:杨光远
去年三月报道
TrueNAS SCALE
启动环境
第一个预览版本
提出了问题
TrueNAS CORE 已死——zVault 万岁
TrueNAS CORE 与 TrueNAS SCALE
截图链接
路线图
XigmaNAS
总结报告
https://www.sovereigntechfund.de
freebsdfoundation.org
https://wiki.freebsd.org/SummerOfCode2023Projects/IntegrateMfsBSDIntoTheReleaseBuildingTools
加入 FreeBSD jail 邮件列表,获取云原生容器相关更新
加入工作组,为 FreeBSD 云原生容器技术的开发作出贡献
http://www.7he.at/freebsd/vps/
问:让我们从 FreeBSD 的历史说起,它起源于哪里,以及与早期 BSD 发行版的关系。

答: FreeBSD 的起源可以追溯到加州大学伯克利分校的计算机系统研究小组(CSRG),伯克利软件发行版(BSD)正是在 1970 年代作为该校的一个协作项目开发的,推动了开源运动的形成。到了 1990 年代初,BSD 遭遇了法律挑战,Linus Torvalds 后来也提到这正是他创建 Linux 的关键原因之一。那个时期,386BSD 出现,旨在将 BSD 引入 Intel 80386 处理器。FreeBSD 于 1993 年 6 月 19 日正式成立,作为 386BSD 的演进,重点关注性能、稳定性以及开放开发模式。

在早期,FreeBSD 不仅因其技术卓越而获得认可,还因为其独特的吉祥物——Beastie,BSD 小恶魔——而闻名,该形象经过皮克斯著名动画师 John Lasseter 的参与进行了精心完善。

从伯克利的起源到今天,FreeBSD 始终致力于打造所有人都能使用和学习的软件。正如 FreeBSD 最早的开发者之一 Marshall Kirk McKusick 博士所说:“FreeBSD 是‘复制中心(Copy-Center)’,而不是‘著佐权(Copy-Left)’——你可以去复制中心,根据自己的需要制作任意数量的副本,目的随意。”这种理念在 30 多年后依然成立。

FreeBSD 与类似的开源项目不同之处,还在于它能够在没有核心人物领导的情况下坚持和创新。根据设计,其治理结构不断演进,既引入新视角,又保持项目本身的稳定和稳步发展。这个项目让我这样的年轻大学生能够立刻参与贡献,学习对职业生涯至关重要的技能,最终加入核心团队,协助管理项目。我于 2000 年 3 月创立了 FreeBSD 基金会,因为我想确保 FreeBSD 的长期发展,使其能够为未来一代提供同样的机会。基金会提供财务和法律支持,推动基础设施改进,并支持 FreeBSD 的推广和开发。

问:自那以后,FreeBSD 最大的成功是什么?

答: FreeBSD 最大的成功之一是其作为“催化剂”的角色,为无数产品和创新提供了稳定且高性能的基础。得益于其宽松的 BSD 许可证,公司和开发者能够在 FreeBSD 之上进行开发,而无需受限于严格的义务,这使得它被广泛应用于从 PlayStation 游戏机到网络基础设施和云服务等各个领域。FreeBSD 的影响力不仅限于直接采用——它还为存储、安全和网络领域的技术进步提供了技术支撑。

安全是创新的关键领域,其中包括 Jail 功能,这种轻量级操作系统级虚拟化技术早于 Linux 容器成为主流,以及 Capsicum,这是一个细粒度的基于能力的安全框架,用于现代应用的沙箱保护。此外,英国剑桥大学的研究人员在 FreeBSD 上开发了 CHERI(能力硬件增强 RISC 指令集),它通过硬件支持的内存安全防止处理器级别的漏洞。

自然,围绕 FreeBSD 的关注大多集中在其技术创新上,而 FreeBSD 基金会则默默保障着使这些创新成为可能的稳定性和持续性。除了资助引人注目的项目,比如笔记本上的现代 WiFi 支持,基金会还负责关键但不显眼的工作:维护基础设施,管理安全披露,保护商标权,防范法律和监管风险。这些努力确保 FreeBSD 始终是安全且高质量的平台。当遇到时间紧迫或复杂的挑战——如安全审计或紧急漏洞修复——超出志愿者能力范围时,基金会会介入提供支持。正是这背后的工作,使得 FreeBSD 在全球开发者和组织中保持稳定可靠。

问:FreeBSD 现在的影响力如何?

答: FreeBSD 依然具有重大影响力,既作为一款完整的操作系统存在,也通过其广泛使用的组件发挥作用。其成功基于三大支柱:宽松的许可证、自我更新的项目结构,以及高度可靠且技术先进的软件。正因为如此,FreeBSD 被嵌入到无数技术中——驱动手机、游戏机、处理全球大部分互联网流量的路由器,以及工业控制系统。很可能你正在使用 FreeBSD 却未曾察觉。

例如,奈飞依赖 FreeBSD 来优化流媒体性能,向数百万用户传输高质量视频且延迟极低——单台服务器的速度可达 800 Gbps。除了娱乐领域,FreeBSD 的稳定性和先进的网络功能使其成为关键基础设施的首选。数据管理全球领导者 NetApp 以 FreeBSD 作为其 ONTAP 软件的基础,该软件支持多个行业——他们特别强调了与阿斯顿·马丁一级方程式车队的合作案例。此外,另一家基于 FreeBSD 静悄悄发展的市值数十亿美元的公司是倍福自动化。仔细查看其网站,可以看到他们如何将平台从老旧的 Windows CE 迁移到 FreeBSD。倍福高级产品经理 Heiko Wilke 表示:“从安全角度来看,一款持续活跃开发的现代操作系统是不可或缺的。”这些案例凸显了 FreeBSD 作为关键任务和高性能应用基础的多样性。

这仅是部分例子。FreeBSD 基金会不断发现该操作系统新的应用场景,并致力于将企业与开发者社区连接起来,推动更多创新。FreeBSD 支撑着许多当今技术的发展,因为它提供了一个强大且灵活的平台——正如最初在计算机系统研究小组创建的 BSD 一样。

问:FreeBSD 的程序开发社区是否出现了老龄化?如果没有,是如何避免这个问题的?

答: 尽管有一批经验丰富的核心开发者,FreeBSD 依然不断吸引新的年轻贡献者。作为一款完整的操作系统——包括内核和用户空间——它是学习操作系统工作原理的绝佳工具。通过 FreeBSD 基金会与滑铁卢大学的实习合作、开发用于教授操作系统基础的教育材料,以及 FreeBSD 项目 20 年来参与谷歌编程之夏,我们积极吸纳新贡献者。

主权技术机构(Sovereign Tech Agency)专注于投资开放数字基础设施以打造未来基础,最近委托 基金会推动基础设施、安全、合规和开发者体验的改进,重点简化用户首次为项目贡献代码的过程。

最后,FreeBSD 的项目结构使新贡献者能轻松找到自己的定位并产生影响。尽管业界普遍认为系统编程问题已被解决,但仍有重要且令人兴奋的工作待完成。FreeBSD 提供了理想的创新环境。通过平衡经验与新视角,FreeBSD 和 FreeBSD 基金会确保开发者社区保持活力并持续进化。®

From PlayStation to routers, you've probably been using FreeBSD without knowing it
问:请简要介绍一下自己以及你的教育之旅的进展。

我叫 Sudhanshu Mohan Kashyap,我去年刚刚获得了在皮拉尼比尔拉科学技术学院果阿校区的电气与电子专业的学士学位。目前,我在摩根大通担任初级分析员(SE1)。我热爱 Linux 和 FreeBSD,并且把很多空闲时间都用来玩 VPS 服务器。我对像 FreeBSD 这样的开源项目做贡献感到兴奋,也希望进一步提升我的技能。

问:你以前参与过谷歌编程之夏项目吗?

没有,这是我第一次参加谷歌编程之夏项目。

问:为什么想要与 FreeBSD 合作?

我是通过一个亲近的朋友,他曾经通过贡献 FreeBSD 的 ports 来初次接触到 FreeBSD 的。我对创建网站和服务器管理产生了浓厚的兴趣,通过托管 Minetest 服务器,我积累了相当多的知识。由于我的电气与电子背景以及基础设施工程方面的经验,我认为 FreeBSD 是一个很好的平台,可以结合我的技能并为一项著名的开源项目做出贡献。

问:请简要介绍一下你的谷歌编程之夏项目。

我的项目提案是为 FreeBSD 的引导加载程序创建一个 CI 测试工具。目前的脚本 full-test.sh 在所有支持的体系结构和组合上缺乏全面的测试。我计划用 Lua 重新编写此脚本,以便测试多个体系结构组合并生成关于损坏的组合和预期功能的报告。如果时间允许,我将把该脚本与现有的构建基础设施(如 Jenkins 或 Github Actions)集成,以提供全面的测试结果。

问:迄今为止,你从这次经历中学到了什么?

在 Warner Losh 的指导下,通过这次经历,我获得了宝贵的技术技能,包括部署服务器、Lua 编程和模块化脚本编写。我学会了在协作编码环境中进行详细项目规划的重要性,有效沟通的重要性,以及系统测试的重要性。在 Warner 的指导下,我成功配置了服务器,解决了设计问题,并通过深入测试提高了代码质量。这个过程不仅扩展了我的技术专长,还提高了我的问题解决能力和注重细节的能力,使我成为了一名更加熟练和适应性强的软件开发人员。

问:与 FreeBSD 项目合作的经验如何?

与 FreeBSD 项目合作是一次启发性的经验。来自 Warner Losh 等导师的反馈和指导对于完善我的项目提案非常重要。这个项目与我的兴趣和技能很好地契合,我很高兴能为这样一个著名的开源社区做出贡献。

Meet the 2023 FreeBSD Google Summer of Code Students: Sudhanshu Mohan Kashyap
问:请简单介绍一下你自己,以及你在教育旅程中的进展。

嗨!我叫 Aymeric Wibo,目前正在比利时鲁汶天主教大学攻读计算机科学学士学位。

问:你以前有参与过谷歌编程之夏项目吗?

没有!这是第一次。

问:你为什么想与 FreeBSD 合作?

我已经将 FreeBSD 作为我的主要操作系统使用了 2 年多,之前我已经提交过一些补丁,因此我认为下一步自然的进展就是为 FreeBSD 做一些更有实质性的工作,特别是在今年的 FOSDEM 上简要会见了项目的一些成员之后。

问:请简要介绍一下你的谷歌编程之夏项目。

我的项目是使 FreeBSD 支持 BATMAN mesh 网络。BATMAN 是由 Freifunk 开发的一种路由协议,用于基于网络中立原则构建城市规模的开放 Wi-Fi 网络。

具体来说,这包括将 Linux 中的 batman-adv 内核模块移植到 FreeBSD(作为 batman_adv)。这利用了 LinuxKPI,这是一个将 Linux 调用转换为 FreeBSD 代码的内核接口,以及 FreeBSD 中的新 Netlink 支持。

问:你从这次经验中学到了什么?

学到了很多!

更具体地说,我对 Linux 和 FreeBSD 网络堆栈的内部了解更多,现在更加熟悉浏览它们各自的源代码并跟踪与网络相关的问题。我还学会了如何使用 FreeBSD 提供的出色内核调试工具(kgdb,dtrace,以及最重要的 printf ;))。

总体而言,在短时间内作为开发者取得了很大的进步,并获得了很多可迁移的经验!

问:与 FreeBSD 项目合作的经历如何?

非常棒!在开源项目上工作总是一种乐趣。FreeBSD 社区的人们反应迅速,乐于助人,我非常感激有一位导师(嗨,mmokhi@!)在我遇到困难时指导我。

我期待未来继续在 FreeBSD 上工作!

Meet the 2023 FreeBSD Google Summer of CodeStudents: Aymeric Wibo
https://freebsdfoundation.org/news-and-events/latest-news/what-the-dev-podcast-the-evolution-of-the-freebsd-project/
What the Dev Podcast

Mark Johnston 的 BSDCan 2025 旅行报告

  • 原文:BSDCan 2025 Trip Report – Mark Johnston

  • 2025 年 7 月 11 日

  • 作者:Mark Johnston

FreeBSD 基金会赞助我前往渥太华参加 BSDCan 2025 会议及 FreeBSD 开发者峰会。如往常一样,开发者峰会在 6 月 11 日和 12 日举行,为期两天,随后在 13 日和 14 日举办正式会议。按照惯例,我从多伦多乘火车前往渥太华参加 BSDCan,这次带来了我的 ARM Morello 台式机,以便在 Brooks Davis 关于 CHERI 的演讲中使用,并演示将其支持回溯到 FreeBSD。Ed Maste 善意地帮我运送了设备,这让我的行程轻松许多;回程时,我不得不将其放在超大行李箱中随火车携带。我以前从未尝试过这样运输台式机,当我回家后发现它仍然可以正常启动时,我感到相当安心。

开发者峰会的第一天主要以演讲为主,中间安排了充足的休息时间,方便大家交流或进行一些副项目开发。会议期间,我通常会在休息时间和晚上在 90U 的黑客休息室处理一个到两个小项目,这次是针对内核调试的 GDB 脚本,灵感来自与我们尊敬的 pf 维护者 Kristof 的讨论。撰写本文时,我还未完成会议期间想要完成的工作,但很快会完成。

第一天早上的主要亮点是例行的核心小组动态,会中 FreeBSD 核心小组的成员汇报了各类议题。特别引起我注意的是关于在 FreeBSD 项目中使用基于 LLM(大型语言模型)的编程工具的草案政策。简单总结,该政策禁止将 LLM 生成的代码纳入项目,但允许在开发过程中以其他方式使用 LLM,例如帮助审查补丁、撰写提交信息或其他非显式许可的内容。该政策旨在避免将来源不明的代码“污染”FreeBSD 项目,众所周知,许多 LLM 模型训练数据中包含与 BSD 许可不兼容的代码,目前法律上尚缺乏明确先例表明将其输出纳入项目是绝对安全的。

表面上看,这似乎是合理的政策:它试图在保持项目许可完整性(对重要的 *BSD 用户吸引力很大)与使用新工具辅助开发之间取得平衡。尽管近期 LLM 编程的热度略显夸张,我确实发现它们在某些工作类型中很有用[*]。在随后的讨论中,我对会议室中普遍持消极态度感到有些失望。然而,核心小组的做法公平公正,也与其他大型开源项目保持一致,我对未来几年开发者的动态很感兴趣。我的个人观点是——撇开许可问题——我们应鼓励资深开发者在愿意的情况下尽可能利用 LLM。长期从事 OSS 的开发者已经习惯于审查和修改非自己编写的代码,我认为这种怀疑精神足以对低质量 LLM 输出进行把关。

午餐后,Verisign 的 Rick Miller 发表了关于在核心互联网 DNS 基础设施中使用 FreeBSD 的深度防御策略的演讲。他讲解了操作系统多样性在提升安全性方面的作用,以及为什么 FreeBSD 是其中一个理想候选操作系统。作为此策略的一部分,Verisign 在其基础设施中同时使用 Linux 和 FreeBSD,并在不同操作系统上使用不同的应用框架,以进一步降低对单一技术栈的依赖。具体来说,虽然 Verisign 的应用在 Linux 上使用 DPDK,在 FreeBSD 上可以使用 Netmap 框架实现类似的底层网络硬件访问。Rick 还介绍了 Linux 与 FreeBSD 各自存在的内核安全漏洞,但我认为大多数 CVE 级别的内核漏洞高度依赖操作系统,尤其是内存安全漏洞。Verisign 对此策略的全面投入令人印象深刻,我希望未来能看到更多类似案例。

在 Rick 的演讲之后,我和其他 FreeBSD srcmgr(源代码管理)团队成员做了类似早晨核心小组动态的报告,介绍了源代码管理团队的工作及正在解决的问题。特别值得注意的是,我们呼吁潜水者(lurkers)加入团队并参与会议,即便不是正式成员,也能参与源代码管理的讨论及 bug/PR 分拣工作。我们收到了许多感兴趣的开发者反馈,现在几周后,源代码管理的双周会议参与人数从通常的四人增加到九人。

开发者峰会第二天,我参加了 Brooks Davis 有关 CHERI 的演讲,以及将其支持回溯到 FreeBSD 的动机。整个演讲使用我从多伦多带来的 ARM Morello 系统;KDE 桌面堆栈直到用于渲染幻灯片的 PDF 查看器都运行在纯 capability 模式下,所有 C 指针都用 CHERI 能力表示。在此模式下,许多内存安全漏洞会导致应用以确定性崩溃关闭,而非暴露给利用。Brooks 介绍了几个正在进行的商业 CHERI 硬件项目,通常基于 RISC-V,并讲解了从 CheriBSD 上游到 FreeBSD 的路径。CheriBSD 含有一些大规模改动,其中部分无法上游;混合模式下,内核作为典型 aarch64 二进制运行,同时支持纯 capability 用户空间应用。这些补丁较为 hack,需要对内核操作的所有用户空间指针进行显式标注。演讲中,Brooks 还展示了若干 CHERI 特性,尤其是 CheriBSD 的基于库的隔离(c18n)。

在主会议期间,我参加了不少精彩演讲,个人亮点包括:

  • ELF Nightmares, GOTs, PLTs and Relocations Oh My – John Baldwin 展示了 ELF 二进制执行过程中静态和运行时链接器使用的数据结构,涉及 PLT 函数调用间接跳转等复杂概念,并提供了出色的可视化演示,有助于理解。

  • ABI Stability in FreeBSD – ShengYi Hung 介绍了新工具 ctfdiff,可比较两个文件的 CTF(Compact C Type Format)数据,检测类型定义和函数签名差异,辅助判断内核变更是否影响出树内核模块的二进制接口。演讲后,围绕如何使用该工具展开了热烈讨论,我提出了比较内核模块与目标内核 CTF 类型图的方法,以减少误报。

  • Improvements to FreeBSD KASAN – Zhuo Ying Jiang Li 分析了 FreeBSD KASAN 实现的若干不足,并提出解决方案。KASAN 利用编译器插装和小型运行时组件检测内核内存安全漏洞。她指出两个主要问题:一是 UMA slab 中对象间未插入填充,二是已释放对象未隔离,这会降低 KASAN 检测 use-after-free(UAF,释放后重用漏洞)的能力。她提出通过修改 UMA 解决这些问题,并讨论了利用现有 UMA 特性进行优化的策略。我期待这些补丁尽快被上游采纳。

非常感谢 FreeBSD 基金会赞助我的此次行程。

[*] 不管怎样,此报告均未借助大型语言模型辅助撰写。

讣告——Michael "Mike" John Karels

点击此处 可以观看弥撒的录制视频。

  • 原文位于 https://www.gearty-delmore.com/obituaries/michael-mike-karels(网上扫墓)

Michael "Mike" John Karels(1956 年 8 月 2 日 - 2024 年 6 月 2 日),享年 67 岁,来自伊甸草原。

Michael 于加拿大渥太华因突发心脏病猝然离世。仅余他挚爱的妻子 Theresa“Teri”(娘家姓 Spartz)仍在人世间;女儿 Sarah 及其男友 Ivan Munkres、姐妹 Colleen (Stuart) Lind、Mary Beth (Brad) Schleif 和 Katherine Karels、兄弟 Eugene (Ann) Karels 以及许多家人和朋友,包括他的父母 Patricia 和 Charles Karels 都在他之前去世了。

Michael 毕业于圣母大学(即诺特丹大学),取得微生物学学士学位,并在加州大学伯克利分校完成了研究生学业。在攻读博士学位期间,他接触到了计算机,使他的兴趣发生转向。他最终成为了一名软件工程师,并在 BSD UNIX 历史上扮演了重要角色,这是现代计算史上一个重要的里程碑。通过在伯克利大学的工作,他为早期互联网的实现做出了贡献,为现代网络奠定了基础。他是《4.4 BSD 操作系统的设计与实现》的作者之一,这是该领域的重要著作。”

在完成伯克利的学业后,他曾在多个组织担任高级首席工程师,包括风河公司、安全计算公司、迈克菲、英特尔和 Forcepoint。2021 年他退休了,并将时间和才能倾注于为 FreeBSD(一款免费操作系统)做志愿工作。尽管他在相关领域取得了成功并占据重要地位,但 Michael 被人描述为是一个非常谦逊、有耐心和善良的人,并且乐于与他人分享知识。”

除了在工作上取得的成功,Michael 还是他的家庭中的关键一员,他是个乐于奉献,能支撑的儿子、兄弟、丈夫及父亲。从小,他就承担着额外的责任,在许多方面带领、帮助和指导家庭成员,但他总是以善良、坚持和智慧来面对这些。

Michael 也是一位热情的环保主义者。他对自然的热爱始于早年与家人的野营之旅,其中在冰川国家公园独自过夜的经历成为他成长中的深层记忆。这份热情随着时间的推移而增长,成年后的他成为了许多环保组织的积极支持者,致力于对抗气候变化,并在当地参与清除植物入侵物种的工作。他和妻子最后一次同游国家公园是在 2023 年秋,他们观光了大峡谷和锡安国家公园。

多年来,他的爱好各异,比如音乐和摄影。他的音乐品味多样,从杰思罗·塔尔乐队到贝多芬再到戴夫·布鲁贝克。他对摄影的兴趣始于高中时期,他在其童年卧室里搭建了自己的暗室,并随之进入了现代摄影和数码单反相机时代。在圣母大学就读期间,他担任了校园广播电台的站长,白天播放古典音乐,晚上拍摄巡演的摇滚乐队。

Michael 原本期盼着在退休后的余生中进行编程、改善家居环境,并见证女儿从医学院毕业并成家。他的离世使家人和朋友乃至整个科技界都倍感遗憾。

6 月 18 日(周二)上午 11:00 在 Pax Christi 天主教社区举行基督葬礼,地址:Eden Prairie,12100 Pioneer Trail。

Michael 将安眠在 Pleasant Hill 公墓。

6 月 17 日(星期一)下午 5:00 至 8:00 在 Gearty-Delmore Park 殡仪馆(地址:St. Louis Park,3960 Wooddale Avenue South)举行追思会,其中包括下午 6:30 的回忆时光(弥撒前一小时在教堂举行)。

祭奠活动请优先考虑捐赠至 Free BSD 基金会;3980 Broadway Street; STE #103-107; Boulder, CO 80304 或捐款至环境保护基金会(EDF)。

-l 显示等待时间统计
  • -q 显示队列统计

  • 以只读模式导入存储池

  • 尝试恢复最近销毁的存储池

  • 删除 @b 及之前的所有快照:

    +

    新增文件

    -

    删除文件

    M

    修改文件

    R

    重命名文件(应用于目录时表示元数据更改)

    它被用于许多设备和产品,但我们关心的是它的小型 USB WiFi 版本,非常小巧。

    Realtek 公司甚至在 2011 年因其 802.11b/g/n 2.4GHz 1T1R WLAN 单芯片控制器(RTL8188CE/RTL8188CUS) 获得了 台湾绿能经典奖 2011,当时该芯片刚推出。

    由于仅配备 1×1 天线并支持 802.11n,它的性能并不强——最高 150Mbps,仅单天线。

    它体积也非常小,几乎不会从笔记本上突出来。

    在连接时,它还会发出微弱的灯光。

    FreeBSD

    下面展示它在 FreeBSD 上的使用情况。本文以 12.2-RELEASE 为例,但三年前在 11.1-RELEASE 上也是同样适用。

    我的 ThinkPad W520 笔记本已经配备了 Intel 6300 WiFi 卡,3×3 天线,802.11n 标准,由 iwn(4) 驱动。

    现在我们将连接到 Realtek RTL8188CUS 芯片,并查看 dmesg(8) 命令的输出。

    ……以及来自 usbconfig(8) 命令的更多信息。

    它现在被列为 rtwn0,因为在 FreeBSD 上由 rtwn(4) 驱动。

    现在让我们用这个 Realtek 芯片连接无线网络。我将创建 wlan1 设备,因为 wlan0 已经被另一张 Intel 6300 卡占用。

    此时我们的网络二层(LAYER 2)应该已经连接,wpa_supplicant(8) 应在后台运行,wlan1 接口应显示 associated 状态。

    现在使用 dhclient(8) 命令为网络添加三层(LAYER 3)并获取 IP 地址。

    我们刚刚获得了 IP 地址 10.0.0.9。

    最后一步是配置 DNS,然后使用命令 ping(8) 测试连接。

    可用。

    FreeBSD 性能测试

    接下来,我使用 thunar(1) 文件管理器,通过 NFS 大文件传输测试了这块简单的单天线 Realtek 芯片的性能。

    结果不算太差,但也算不上优秀。

    从直接连接到 WiFi 路由器的局域网服务器复制文件到我的笔记本,速度约为 2.9 MB/s。我当时距离路由器 5 米。

    从笔记本通过 WiFi 向直接连接到 WiFi 路由器的局域网服务器复制文件,速度约为 2.6 MB/s。仍然距离路由器约 5 米。

    分别为 23.2 Mbps 和 20.8 Mbps。远低于单天线 802.11n 理论传输速度 150 Mbps……这很可能是 FreeBSD 无线栈的问题。

    我认为这对于上网浏览已经足够,但通过 NFS 使用本地局域网资源可能会很痛苦。

    相比之下,我的 Intel 6300 WiFi 卡在笔记本到路由器到服务器的复制速度为 5.5 MB/s,在服务器到路由器到笔记本的传输速度为 10.5 MB/s,分别为 44 Mbps 和 84 Mbps,而理论最大值为 450 Mbps。Intel 6300 和我的路由器均为 3×3 天线。

    希望这些数字能接近 30 MB/s……

    树莓派

    Realtek RTL8188CUS 芯片的另一个优点是它在树莓派等小型设备上表现良好。我个人在 树莓派 2B 上测试过,效果非常出色。

    价格

    这款芯片的价格也非常诱人。基于它的产品随处可见。在 EBAY、全球速卖通 上都有出售,许多情况下价格低至 $2.50。

    有时运费甚至比产品本身还贵 :🙂:

    尽情享用。

    更新 1 – 中世纪状态

    Reddit 用户 Yaazkal 提醒我,FreeBSD 上的 rtwn(4) 驱动仍不支持 802.11n 协议。

    它仍停留在 802.11g 的“中世纪”传输水平。

    更新 2 – 意外好处

    虽然我很少使用或安装 Windows 系统,但我发现了 Realtek RTL8188CUS USB WiFi 适配器的新用途……例如在 Windows 10 全新安装后,原有 WiFi 卡可能“无法使用”,因为没有可用驱动。

    这时,这个小巧的设备就非常有用——只需插入,运行 Windows 更新 获取所需的驱动和更新,无需查找设备 ID 或从 USB 驱动手动安装。

    Realtek RTL8188CUS – USB 802.11n WiFi Review
    ZFS Boot Environments
    可以完美实现的任务。

    在下面的示例中,我们将创建一个全新的 ZFS 启动环境,克隆我们当前的 12.2-RELEASE 系统,并在该 BE 中升级到 13.0-BETA3 版本……这样重启时只需一次,而不像典型的 freebsd-update(8) 升级流程需要三次重启。

    我假设你已经安装了带 ZFS 的 FreeBSD 12.2-RELEASE(FreeBSD 默认 ZFS 安装),并且系统以 UEFI 或 UEFI+BIOS 模式安装。以下是所需的步骤。

    我在这个过程中使用的是我的 sysutils/beadm,但你也可以使用 FreeBSD 基础系统自带的 bectl(8)。

    我们还需要更新新的 FreeBSD loader(8) —— 通过这种方式可以更新 —— 感谢 @JeffSipek 的指点。

    在我的系统中,FreeBSD 安装在 ada1 设备上。

    有小概率你无法挂载 efi 分区。即使使用 fsck(8) 也无法解决此问题。

    一些用户遇到的典型错误如下:

    如果你遇到这个问题,首先将当前的 efi 分区备份,例如备份到 /BACKUP.ada1p1 文件。

    现在我们将从零开始创建全新的 efi 分区。

    现在你应该已经有了新的“可用” efi 分区。

    最后一步是 reboot(8) 进入新的 13.0-BETA3 系统。

    如果你发现新的引导加载程序无法加载你的新 FreeBSD,也可以选择将 /boot/boot1.efi 而不是 /boot/loader.efi 复制到 /mnt/efi/boot/bootx64.efi。

    请记住,如果你从 geli(8) 加密系统启动,那么 /boot/loader.efi 是必需的,如果使用 /boot/boot1.efi 文件将无法启动。

    完成。

    现在你应该能看到全新的 FreeBSD loader(8):🙂

    你现在可以享受最新的 FreeBSD 13.0-BETA3 安装。

    同样的步骤将适用于即将发布的 FreeBSD 13.0-RC*(RC1/RC2/RC3)版本的更新,最终希望在 2021 年 3 月发布 FreeBSD 13.0-RELEASE。

    更新 1 – 如果一切顺利

    你现在拥有最先进的 FreeBSD 系统,运行速度应该比 12.2-RELEASE 更快,同时你仍保留旧的 12.2-RELEASE Boot Environment,如果在 13.0 版本中遇到问题,可以回退。

    在我的系统中,它看起来是这样的:

    Space 列有点容易误导,因为它会计算例如快照占用的空间。要获取每个 Boot Environment 占用的精确信息,请使用 -D 选项。这样你可以分别查看每个 Boot Environment 的空间信息。

    我会暂时保留 12.2-RELEASE Boot Environment —— 可能在 13.0-RELEASE 发布后一个月左右删除它,但如果你测试过所有需求,并且发现 13.0 能像 12.2-RELEASE 一样或更好地满足需求,那么你可以使用下面的命令删除旧的 Boot Environment。

    更新 2 – 如果出现问题

    一般来说,如果新 BE 名为 ‘13’ 无法启动(或在启动时挂起),只需选择你在升级前使用的旧 Boot Environment —— 也就是包含 12.2-RELEASE 的那个。

    这样你就可以回到升级前可正常工作的系统。

    如果这也失败了(或者引导加载程序损坏),那么下载 FreeBSD-13.0-BETA3-amd64-memstick.img 镜像,并用 dd(8) 命令写入 U 盘。

    现在你有了 FreeBSD 13.0-BETA3 的 U 盘,可以从它启动并修复你的安装。启动后选择 LiveCD,在 login: 提示符下输入 root 并按 [ENTER] 留空密码。

    接下来可以执行的操作取决于具体损坏情况,我无法预估每种可能的错误和修复方案。如果在升级过程中遇到任何问题,请通过你方便的方式联系我,我们会一起解决。

    更新 3 – 使用新版本 beadm(8) 更快升级

    今天(2022/05/06)我发布了新版本 beadm(8) 1.3.5,带来了新的 chroot(8) 功能。它已经提交到 FreeBSD Ports 树的 263805 PR 中,所以预计很快就能获取到软件包。

    你也可以直接这样更新 beadm(8):

    现在讲更快的升级流程 —— 以下说明根据你使用的 shell 而定。

    • ZSH / CSH

    • SH / BASH / FISH / KSH

    祝升级顺利 :🙂:

    Upgrade FreeBSD with ZFS Boot Environments
    https://is.gd/BECTL
    phoronix.com

    会议的第一天早早开始,基金会的合作与研究总监 Greg Wallace 带着一台由 Ampere 捐赠的 Ampere 2U 服务器亲自到场。不幸的是,我们在安装过程中遇到了问题,但即便如此,这台服务器还是吸引了许多与会者,讨论 Ampere 上的 FreeBSD 是一个很好的话题。

    image

    FreeBSD 展台最终吸引了相当多的参与者,我很兴奋能够与来自北卡罗来纳地区的 FreeBSD 社区成员以及许多当地渴望了解该项目的学生们见面。我在类似 ATO 这样的大会上最喜欢的部分是它们培养了一个非常多元化的开源社区。这使我们有机会与经验丰富的 FreeBSD 用户互动,他们乐于分享与 FreeBSD 历史相关的故事,以及寻求首次安装 FreeBSD 的新开发人员和用户。我们分发了大量的 FreeBSD 周边产品,我终于能够亲自见到一些我之前只在虚拟空间中互动过的社区成员的真实面孔。

    第二天,我有更多的时间参观其他展台。由于有超过 4300 名注册参与者,会议场面热烈,所有人都聚集在一起庆祝和倡导开源。虽然没有专门的 BSD 行动方针,Greg Wallace 参与了开源倡议组织的开源与公共政策小组讨论,你可以在这里观看。这次讨论引发了一些关于更大范围的开源软件社区如何合作以影响公共政策的精彩对话。当我们拆卸我们的展台时,和与会者的一次即兴对话涉及到 BSD 许可证的好处和开源的未来,并持续到了会议结束后。

    我非常享受我的第一次 All Things Open,很高兴有机会与 FreeBSD 用户和更广泛的开源社区讨论有关 FreeBSD 的话题。我期待着 All Things Open 2024!

    https://freebsdfoundation.org/blog/all-things-open-2023-conference-report/
    Metify 提供两个产品:
    • Mojo Edge 数据中心配置——平台 - 这是一个综合解决方案,旨在在数据中心和边缘发现、配置和配置裸机服务器和存储。该解决方案注重保持用户体验简洁,避免与供应商绑定。该工具与 Metify 的 Photon ISP 平台配合使用,无缝管理分布在不同位置的裸机资产。该平台完全依赖于 BSD 和 bhyve,在 Oracle Cloud Infrastructure (OCI) 成熟后,平台将立即过渡到 BSD 本机。

    • Photon ISP 平台——作为对无线 ISP 服务的补充层,确保了不间断的 4G/5G 和 Starlink 故障切换。基于强大的 FreeBSD 13.2 构建,它完全取代了 Starlink 的路由器功能。这一创新将过渡到目前为我们的弗吉尼亚州布鲁蒙特客户提供服务的 Photon WISP 平台。

    “FreeBSD 是 Metify 堆栈的基石,帮助我们推动 Mojo 的创新。我们从 Linux 切换到 FreeBSD,是因为其许可的灵活性和无与伦比的性能能力,使我们能够一次性配置数千个数据中心节点。此外,它显着简化了我们的软件架构,同时提高了系统的稳定性,”Metify 的 CTO Ian Evans 评论道。

    在 FreeBSD 厂商峰会上,Evans 将讨论:

    • 从 Linux 过渡到 FreeBSD:Metify 从 Linux 过渡到 FreeBSD 以及从 KVM 到 Bhyve 的方式和原因。他将讨论 Metify 如何将 Bhyve 整合到其系统中。

    • 用 FreeBSD 简化的价值:通过 FreeBSD,Metify 简化了其软件堆栈并提高了可靠性。它将讨论如何构建零触及的 FreeBSD 安装流程,并使用 Ansible 自动化其堆栈。

    • 灵活性和创新:Metify 将讨论 FreeBSD 许可结构如何在未来允许更大的灵活性(特别是与 Linux 相比)。它还将讨论 Metify 如何使用 FreeBSD 开发设备,用于通过 4G 和 5G 网络进行远程设置,以及基于 FreeBSD 的边缘设备,通过 4G 和 5G 网络实现远程裸机配置。

    • 增强的安全性:Metify 还将分享如何将 FreeBSD 用作 Mojo 的安全网关。这将包括围绕 pf、ipfw、dummynet 和 NTOPNG 的流量监控的讨论。

    你可以在峰会上 亲自 听到 Ian 的演讲,也可以通过 直播 在线观看。

    https://freebsdfoundation.org/blog/why-freebsd-metify-to-showcase-how-moving-to-freebsd-enhanced-two-new-products/
    Ian Evans, CTO, Metify
    PBUG
    Bug 230323 – Idea/Feature Request – include beadm in the base
    sysutils/beadm
    New ZFS Boot Environments Tool
    BSD Now 262 – OpenBSD Surfacing
    zfs-boot-environments-history.png

    FreeBSD Periodic 系统简介

    • 原文:An Introduction to FreeBSD’s Periodic System

    • 2025 年 7 月 8 日

    • 作者:Benedict Reuschling

    FreeBSD 的 periodic 实用程序是一款内置系统,用于以 shell 脚本的形式安排和运行定期(每日、每周、每月)维护任务。它们包括系统健康检查、安全审计和清理任务。借助 periodic 的模块化结构,也可以把自定义任务集成到现有框架中。

    本文将介绍如何使用系统提供的 periodic 脚本,以及如何集成我们自己的脚本。

    periodic 脚本的位置

    以下目录包含计划通过 periodic 系统运行的脚本:

    • /etc/periodic/daily、/etc/periodic/weekly、/etc/periodic/monthly:应在特定周期运行的脚本(例如每周一次)。

    • /etc/periodic/security:与安全相关的检查,例如已启用的防火墙或登录失败情况。

    • /usr/local/etc/periodic/daily、/usr/local/etc/periodic/weekly

    调度本身通过 /etc/crontab 中的以下三行实现:

    要配置 periodic 系统本身以及应运行的脚本,FreeBSD 提供了单独的配置文件 /etc/periodic.conf。默认情况下,该文件为空或不存在。/etc/defaults/ 目录提供了一个带有详细注释的示例文件。更多信息可参考手册页 。

    例如,要激活每日备份 /etc/passwd 和 /etc/group 文件(位于 /etc/periodic/200.backup-passwd 脚本中),在 /etc/periodic.conf 添加如下行:

    不需要提供前缀数字(示例中为 200)。该数字用于在同一类别(这里为 daily)中有多个脚本时控制运行顺序。在配置文件中逐行列出所有需要运行的脚本。

    当这些脚本执行时,产生的输出会发送到系统管理员账号(root)。若要将输出重定向到 /var/log 中的文件,可分别为 daily、weekly 和 monthly 脚本添加以下行:

    文件名可以任意选择,只要不与已有日志文件重名即可。使用这种方法,这些日志文件在过分膨胀时会被轮替。/etc/newsyslog.conf 中的配置会处理上述三个文件的轮替。

    添加自定义 periodic 脚本

    下面的自定义脚本用于检查系统中所有 ZFS 池的容量是否达到 80%。如果达到阈值,会输出当前容量和对应的池名称:

    接下来使用提升权限将脚本设为可执行:

    在全局配置文件 /etc/periodic.conf 中激活该脚本,并将阈值降低到 75%:

    如果没有 zfs_pool_usage_threshold 这行,脚本会使用默认值 80%。daily_show_success 用于在日志文件中查看脚本输出。如果在测试中将其设为 NO,你将看不到日志输出,而手动执行脚本则正常。

    要测试脚本,以 root 权限运行:

    该命令会遍历每个 daily 脚本以确定哪些需要运行。完成后,你会在 /var/log/daily.log 文件末尾看到新的输出行。

    示例输出:

    编写自定义脚本的建议:

    • 确保脚本运行时间不过长

    • 使用正确的退出码(成功为 0,失败为非零)

    • 减少输出内容,仅保留必要信息,避免日志过快增长

    • 脚本以非交互方式运行,不要等待用户输入或执行需要交互的命令

    总结

    掌握这些技巧后,你可以向系统添加各种有用的任务。查看上文列出的目录,了解已有功能,避免重复造轮子。此外,安装 Ports 时可查看 /usr/local/etc/periodic 是否提供了 periodic 脚本,它们有特定用途,能很好地融入你的定期任务计划中。

    为 FreeBSD 发声:FOSDEM 2025 参会报告

    • 原文:Advocating for FreeBSD: A FOSDEM 2025 Trip Report

    • 作者:Tom Jones

    • 2025 年 4 月 8 日

    在过去十年里,我一直在从事开源软件开发并参加各种会议,但直到上个周末,我还从未像这次那样被问到这么多有关 FreeBSD 的问题。

    2025 年 2 月的第一个周末,我从北海彼岸飞跃而过,第三次造访布鲁塞尔,以一种全新的方式体验了 FOSDEM。

    FOSDEM 可以说是全球规模最大的开源会议。每年 1 月底的一个周末,布鲁塞尔自由大学校园对外开放,约有近一万名开发者、用户、推广者和好奇者齐聚大学校园。

    为了让这么多人尽兴,FOSDEM 2025 安排了 78 条不同的议程轨道,主议程使用了一个可以容纳 3000 人的巨大讲堂,此外还有许多 Devroom(开发者房间),为较小的社区提供了分享最新想法和进展的平台。今年,BSD Devroom 重新回归,共安排了 8 场讲座,涵盖了所有主流 BSD 项目的贡献。

    除了我抽空去 做了一场名为“Writing About FreeBSD”(撰写 FreeBSD 相关内容)的演讲,其余时间我没有去参加其他 1000 场讲座,而是整整一个周末都在 FreeBSD 展台值班。

    除了 Devroom 里的讲座和议程外,FOSDEM 还为一些精选的开源项目提供了展台空间。这让各个项目可以进行宣传,成为用户与开发者交流的接触点,也为项目推广新版本、展示优势,甚至分发贴纸提供了平台。

    在 FOSDEM 2025,我同意协助组织 FreeBSD 项目的展台。在数位项目成员的协助下,我们几乎不间断地向与会者介绍使用 FreeBSD 的理由。我们送出了我带去的 750 张官方贴纸,以及一位社区成员带来的几千张贴纸。

    我们迎来了许多 FreeBSD 的新老用户,他们对我们表示赞赏,我们也有机会向许多不太了解或完全不了解这个项目的人“推销”FreeBSD。

    Rodrigo(rodrigo@,他也协助组织 BSD Devroom)带来了更多贴纸,其中包括

    FreeBSD 项目早期的经典 logo(在“Orb”标志出现之前的版本),以及 Paduka Jorat 打印的 jail 速查表(这些很快就被一扫而空),还有一些马克杯。Rodrigo 打印了一批马克杯,上面印有 Michael W. Lucas 所著《TLS Mastery》中的插画——BSD 小恶魔以《呐喊》的姿态现身。他的妻子起初怀疑这些杯子会滞销,但到周六正式开始前,10 个杯子已经全部售罄。

    除了向所有靠近我们桌子的人发贴纸,我们也回答了许多问题。这些问题种类繁多,非常有启发性。我们回答完“什么是 FreeBSD”后,接下来的一连串问题就让我们意识到,有许多方面我们可以在现场活动和线上平台上做得更好。

    以下是一些典型问题:

    • FreeBSD 支持什么桌面环境?

    • FreeBSD 可以做什么?

    • 我能拿个贴纸吗?

    • 谁在用 FreeBSD?

    我觉得“FreeBSD 能运行什么”和“我能用 FreeBSD 做什么”这类问题非常有趣。这说明我们正被与一些更具专业定位的 Linux 发行版进行比较。在这样的背景下,我们作为一个通用操作系统确实显得很特别。

    在我被问到的问题中确实存在某种共性。作为操作系统开发领域的一员,我们往往会误以为大家都知道我们知道的事情(而实际上我每天都在为自己知识的边界感到敬畏)。能向别人解释我们不仅拥有完整的操作系统,而且几乎可以运行你能想到的所有软件,而且运行得很好,这是非常有意义的。虽然我们有时会被忽略,但在大多数使用场景中,我认为我们不只是具备竞争力。

    FOSDEM 2025 对我来说是一次极好的经历。见到新老朋友令人耳目一新。我也首次有机会见到 FreeBSD 基金会的其他工程师,整个周末都在谈论 FreeBSD 有多棒。

    来自社区的提问以及大家对贴纸(和马克杯!)的热情给了我很多启发,让我思考今后我们可以如何更好地呈现这个项目。人与人之间的互动无疑是向新用户传达项目价值的最佳方式,但演示也是极具吸引力的开场手段,有助于开启对话。

    我希望明年还能再次参加 FOSDEM。如果我真的去了,届时一定会为所有来 FreeBSD 展台的朋友们准备一些真正特别的东西,无论是体验,还是可以带回家的纪念品。

    FreeBSD 上的 ZFS 日志压缩

    • 原文:ZFS Log Compression on FreeBSD

    • 2025-4-16

    系统日志是关于系统运行时发生事件的重要信息来源。FreeBSD 默认的日志系统是 syslog,它会根据主题将日志写入 /var/log/ 下的不同文件。最常见的事件和那些不属于任何其他类别的事件,会被写入 /var/log/messages。

    日志轮转

    随着时间推移,日志会不断增长,并由守护进程 newsyslog 进行轮转。在轮转时,newsyslog 会创建新的日志文件,同时重命名旧的日志文件,同时对其进行压缩以节省空间。默认的命名规则是根据文件的时间添加(或增加)一个数字。例如,当前的日志文件会被加上扩展名 .1,而旧的 .1 文件会被重命名为 .2。超出 .7 的日志文件会作为最老的日志被删除。两个配置文件控制了日志的大小、日志总数以及其他轮转规则和日志行为:/etc/newsyslog.conf 和 syslog.conf。

    ZFS 数据压缩

    OpenZFS 提供了一些强大而高效的压缩算法,能实时压缩数据集中的数据。每当系统写入日志文件时,ZFS 会在主内存中对其进行压缩,然后再写入底层存储。当再次读取文件时,ZFS 会自动解压所请求的数据,并以未压缩形式呈现给应用程序。这种方式在压缩率和便捷性上都具有巨大优势,因为文件系统会自动完成所有压缩步骤。而传统的 syslog 压缩方式仍是通过对文件进行压缩和解压来实现。当访问旧日志文件时,用户需要先使用类似 bzcat 的程序进行解压。而 ZFS 往往能提供更高的压缩率,因此也非常适合接管 syslog 的压缩任务。

    配置 newsyslog

    在基于 ZFS 的根系统中,/var/log 位于一个单独的数据集上。使用以下命令查看当前使用的压缩算法:

    我们在此使用 FreeBSD 安装器默认的存储池名称(zroot)。如果运行 zpool list -Ho name 返回了不同的名称,请根据实际情况修改命令。如果输出为 off,请将其设置为 手册页中列出的某种压缩算法。较好的开始是 lz4 或 zstd:

    请注意,ZFS 只会压缩新的数据,不会影响数据集中已存在的旧文件。接下来我们将对 newsyslog 配置做些修改,以禁用其自身的压缩。FreeBSD 在 中对 /etc/newsyslog.conf 文件各字段做了详细说明。配置文件最后一列(标志位)包含了在轮转日志时要应用的压缩算法。既然我们要让 ZFS 负责压缩,请删除每个相关日志条目的此列中的标志 J。修改完成后保存并退出 newsyslog.conf。

    修改 syslog 的轮转命名方案

    这一步不是必须的,但可以更方便地识别某个被轮转日志的时间点。前面提到,旧日志文件会被加上从 .1 到 .7 的扩展名。在查找某个特定日期的旧日志时,可能需要逐个打开这些文件,十分麻烦。如果直接将轮转日期加入文件名会不会更方便?例如,messages.20240914T210000 表示该 messages 文件最后一次轮转发生在 2024 年 9 月 14 日 21:00:00。当然能配置成这种格式,可参考 newsyslog 的 -t 参数说明。

    我们可以通过编辑 /etc/crontab,将这种命名方式应用于每个日志文件。找到如下带注释的行:

    修改为如下内容:

    保存并退出。

    应用更改

    为了让这些更改生效,重启守护进程 newsyslog 和 syslog:

    ZFS 现在将处理 /var/log 中的未压缩日志文件。日志轮转依然进行,但旧日志不再由 newsyslog 进行压缩。要检查 ZFS 压缩带来的空间节省效果,可运行以下命令:

    下面是某个几周前进行了此更改的系统输出结果:

    这意味着日志文件大小仅为原始未压缩大小的 1/40。ZFS 还提供了关于未压缩前大小的属性信息:

    对于如此小的改动,获得如此多的空间节省是十分可观的。新的日志文件在今后轮转时也将采用新的命名方案。若想进一步了解 FreeBSD 中的日志系统,可阅读 手册章节。

    虽然这些更改很少而且简单,我们还为你编写了一个 Ansible playbook 来实现自动化 😊 。

    Chuck Tuffli 的 BSDCan 2025 旅行报告

    • 原文:BSDCan 2025 Trip Report – Chuck Tuffli

    • 2025 年 7 月 11 日

    • 作者:Chuck Tuffli

    FreeBSD 基金会善意地赞助了我前往渥太华参加 BSDCan 2025 大会和 FreeBSD 开发者峰会的行程。此次活动为期四天,前两天为开发者峰会,后两天为大会,地点依旧是在渥太华大学。

    我及时抵达渥太华参加了 Father and Sons(译者注:一家酒吧)的 Goat BoF(译者注:非正式聚会)。除了能与 Groff the BSD(译者注:一头山羊)亲密接触外,这也是一次难得的机会,与一年一次才能见面的老朋友叙旧,并结识一些新朋友。长途旅行结束后,我回到 U90 的房间,为开发者峰会第一天的活动休息调整。

    开发者峰会的第一天以 FreeBSD 基金会的演讲开场,内容涵盖社区调查、透明度工作以及软件开发项目,特别是他们在改善笔记本电脑支持方面的工作。看到团队在让 FreeBSD 更适合作为日常操作系统方面投入如此专注的努力,令人振奋。

    随后,核心团队进行了汇报,强调了若干长期工作,包括审查章程以应对近期挑战、重新设想 DocEng(文档工程)团队的角色,以及制定技术路线图。该路线图将服务于多重目的,例如指导新贡献者回答“我能帮什么?”的问题,并协调社区与 FreeBSD 基金会等组织的工作。

    项目的 AI 政策引发了与会者和核心团队之间的广泛争议。拟议的政策禁止使用 AI 或 LLM 生成的材料(Phabricator 审查 D50650 供好奇者参考)(译者注:即 ),以防潜在的开源许可证违规。讨论达成的共识是不应全面禁止 AI,例如,应允许用 AI 校对提交信息,Ports 中也可以包含 AI 工具。

    午餐后,srcmg(源代码管理)团队介绍了他们的使命:减少新开发者的障碍,并提高所有开发者的生产力。他们详述了当前活动,如自动 MFC 提交、漏洞处理会议,以及一个宏愿,即整合项目工具(Phabricator、Bugzilla 和 GitHub)。

    当天还包括两场行业演讲:Verisign 介绍了操作系统多样性要求如何促使他们在基础设施中部署 FreeBSD,而 NVIDIA 则讨论了向 FreeBSD 的 mlx5 驱动添加 IPSec 卸载。

    开发者峰会第二天,由 Alpha-Omega Project 做了关于软件供应链安全的演讲。该项目自 2021 年起由 Microsoft、Google 和 Amazon 资助,旨在改善开源软件安全性。演讲提供了许多关于改善安全工作中有效与无效做法的深刻见解。

    不同于典型的“have, need, want”环节以生成下一版 FreeBSD 所需功能,这次会议集中讨论了 15.0 版本的收尾事项。15.0 的主要变化是将操作系统分发为一套庞大的软件包(即“pkg-base”),而非传统的几个大型分发文件。这一变更备受期待,但讨论显示仍有不少细节需要落实。其他议题包括升级基本系统中的 OpenSSL 版本至新的 LTS 版本,以及部分 32 位架构的弃用。

    本届开发者峰会新增了交替对话环节,形式为两名开发者互相对话讨论任意主题,每五分钟由另一名开发者替换其中一人。此环节趣味十足,希望明年还能举办。

    在晚间的黑客沙龙中,我有机会回顾几年前未完成的项目。我曾指导一名谷歌编程之夏学生尝试向内核添加 SquashFS 驱动。尽管学生完成了很棒的工作,但未能提交代码。FreeBSD 开发者 Kyle Evans 认为该工作有潜力,他花时间将代码接近可提交状态。我将 Kyle 的修改 rebase 到当前 FreeBSD 内核,编写了 kyua 的集成测试,并与 Alex Ziaee 合作为驱动添加了手册页。

    本届 BSDCan 大会的讲座丰富多样,日程安排多次迫使我在同一时段的两个讲座中做选择。其中几场给我留下深刻印象的包括:

    • Stefano Marinelli 的“Why (and how) we’re migrating Linux servers to the BSDs”(我们为何,以及如何将 Linux 服务器迁移到 BSD),讲述了他为客户使用开源软件解决问题的经历。BSD 的稳定性和可靠性,加上务实的“解决问题”思路,使客户的疑问从“还有 Linux 以外的选择?”转变为“更多 jail,请”。演讲充满热情与感染力,让我重燃了 FreeBSD 的动力。

    • Hans-Jörg Höxer 讨论了 OpenBSD 对 AMD 硬件支持的“Confidential Computing”(机密计算),目标是在不受信任环境下保护虚拟机中的敏感数据。演讲回顾了 AMD Secure Encrypted Virtualization(SEV,AMD 安全加密虚拟化)的先前工作,并介绍了 SEV-ES 的新进展。我对将这些工作移植到 FreeBSD 的 vmm 和 bhyve 感到兴奋。

    • Xe Iaso 的 lightning talk“I fight bots in my free time”(我在闲时对抗机器人),介绍了他们开发的 Anubis 软件——一款网页 AI 防火墙工具。聆听开发者为解决自身问题而快速发现他人也面临同样困扰的故事,令人着迷。

    在大会的“走廊交流”中,我与另一位 FreeBSD 开发者 Allan Jude 交流了将 bhyve 与 NVMe-oF 存储阵列连接的想法。正是这种偶遇交流理念并可能孕育新项目,使得参加会议非常有价值。

    大会闭幕环节包括由 Dan Langille 主持的慈善拍卖,为 Ottawa Mission(译者注:一家加拿大渥太华的社会服务组织)筹款。亮点包括:

    • 一名与会者以 110 美元竞拍回自己的外套

    • Dan 拍卖一个 Trader Joe’s 的纸袋(译者注:即精美的购物袋),但需划掉附带收据上的信用卡信息

    感谢 FreeBSD 基金会赞助我参加本次大会。

    FreeBSD 开发者正在决定是否为 FreeBSD 15 的 WiFi 采取稳定版策略

    • 原文:FreeBSD Developers Deciding What To Do For WiFi With FreeBSD 15: Stable Or Unstable

    • 作者:Michael Larabel

    • 2025 年 6 月 5 日

    FreeBSD 的开发者近几个月来一直在大力改进其无线/WiFi 驱动的支持,这是他们更普遍地提升 FreeBSD 对笔记本电脑支持计划的一部分。虽然在支持更现代的 WiFi 技术以及启用新款 WiFi 芯片组方面已有不少进展,但整体工作尚未完成,这也让 FreeBSD 15 面临着一个棘手的抉择。FreeBSD 15 计划在今年晚些时候发布,开发者很可能会将其无线支持声明为“不稳定”,以便为后续可能引入的不兼容性变更留出空间。

    由于 FreeBSD 15.0-RELEASE 将于 2025 年晚些时候发布,而 WiFi 驱动相关的开发工作尚未完全完成,当前的关键问题是,是否应将这些最新的无线驱动工作标记为“稳定”。如果按照 FreeBSD 的 ABI 稳定性政策,一旦标记为稳定,今后就不得对用户空间造成破坏性变更。因此,开发者正在考虑采用“不稳定”的方式发布 FreeBSD 15,以便在后续的 FreeBSD 15.x 小版本中可以按需引入无线相关的破坏性变更。

    当前工作的重点是围绕 FreeBSD 的 KPI(内核编程接口)兼容层,特别是用于在无线驱动方面借助 Linux 的驱动代码,以及处理无线驱动相关的 KBI(二进制内核接口)问题。

    Bjoern Zeeb 昨日在 中对这一情况作了解释:

    “FreeBSD 的 WiFi 开发工作已经重新获得动力。随着 FreeBSD 15 即将在今年年底前发布,我们面临着一个决策。

    为了继续推进 WiFi 的开发,接下来的变更必然会破坏 net80211 的驱动层接口和用户空间接口。按照 FreeBSD 的标准,这类变更将无法合并到诸如 stable/15 这样的 stable 分支中。

    这意味着所有后续开发必须留在 FreeBSD 16-CURRENT(即那时的 main 分支)中,所有重大的新功能将不得不等到 2027 年 12 月的 FreeBSD 16.0 才能随之发布。

    经过一些讨论,我们认为这种做法不可行,因此我们决定在 FreeBSD 15 中将无线相关的 KPI 和 KBI 声明为不稳定。

    这样我们可以将 main 分支中的变更合并到 stable/15,从而包含进未来的小版本发布(例如 15.1、15.2 等),随着代码的成熟逐步推进。不过,这也意味着在 FreeBSD 15 的整个生命周期中,我们可能会引入破坏性变更,影响系统内外驱动、用户空间与内核接口、以及具体芯片支持。我们将针对每个破坏性变更逐一应对。

    在最终敲定这个决定之前,我们希望社区能够反馈意见。如果你有任何担忧或反对,请现在就提出。”

    这种做法至少可以让 FreeBSD 的无线驱动支持在 FreeBSD 15 系列中得以持续改进和活跃发展,而不必等到两年后的 FreeBSD 16 才能让使用笔记本电脑和其他 WiFi 设备的用户获得更好的体验。

    BSD 老将:Michael J. Karels 逝世,享年 68 岁

    • 原文地址:https://www.heise.de/news/BSD-Urgestein-Michael-J-Karels-mit-68-Jahren-gestorben-9751528.html

    • 作者:Michael Plura

    • 发布时间:2024 年 6 月 7 日上午 10:07

    他在 BSD-Unix 开源项目中发挥了重要作用,BSD 许可证正是由他一手创建,他一直致力于 FreeBSD 的发展。让我们一起追忆永远离开我们的 Michael J. Karels 先生。

    (图片:FreeBSD 基金会)

    Michael J. Karels 曾在加利福尼亚大学伯克利分校(University of California, Berkeley)攻读分子生物学学位,那是他首次接触到伯克利软件发行版计划(Berkeley Software Distribution,BSD)。他所在的实验室涉足了两个领域:研究细菌基因的遗传学,他曾说那里的高科技设备是由牙签和培养皿构成的。另一个领域是分析细菌基因的子部分,该部分提供了某种特定酶的建模说明。实验室有许多专业设备,其中就包含了一台用于数据收集和数据分析的 PDP 11/40。

    Unix V6/V7: 从 0 开始

    这台机器上运行着第六版 Unix(V6 Unix),附带了一些来自 2.8BSD、2.9BSD 的增强功能。PDP11/40 引起了他的兴趣,为了科学评估,他编写了个 Fortran 程序。在系统发生错误后,一位员工将 V6 Unix 替换为第 7 版 Unix(V7)——他就是于 2022 年 3 月去世的 Bill Jolitz。Bill 和他的妻子在 386BSD 的开发中发挥了重要作用。Unix V7 并不能完美运行在 PDP11/40 上,技术仪器的设备也无法正常驱动。在对计算机几乎一无所知的情况下,Michael J. Karels 开始研究这个问题,并在 Bill Jolitz 的帮助下适配了 V7 Unix 的软件和驱动。

    计算机系统研究小组(CSRG)

    1974 年,加州大学伯克利分校的 Bob Fabry 教授从 AT&T 获得了 UNIX 源代码许可证。他与同事开始修改 UNIX,并将修改成果以伯克利软件发行版(BSD)的名义进行销售。1980 年 4 月,为了满足 ARPAnet(美国国防部高级研究计划局)的特殊需求,Fabry 与 DARPA 签订合同,以继续开发 UNIX。在此资助下,Fabry 成立了计算机系统研究小组(CSRG)。

    Michael J. Karels 也早早加入了 CSRG,成为负责 BSD TCP 堆栈开发的一员。BSD4.2 中并没有版权声明,但许多美国公司在略微修改后却加入了自己的版权信息,Karels 对此感到不满。因此,他与律师合作,创造了如今在每个源代码文件中都存在的版权声明,该声明随 4.3BSD 分发。随着时间的推移,FreeBSD、NetBSD、OpenBSD、DragonFly BSD 和 Sun Solaris 等系统因此而诞生。

    转职为 BSDi 的首席系统架构师

    1992 年 2 月,Karels 转职到 BSDi(伯克利软件设计公司),参与 BSD/OS 的开发。BSD/OS 曾是多年唯一在英特尔平台上提供的商业化类 BSD Unix 操作系统。BSDi 的所有软件资产于 2001 年 4 月被凤河收购,Karels 随后成为风河的首席技术专家,负责 BSD/OS 平台。

    2003 年,Karels 转职成为 Secure Computing Corporation 的高级首席工程师,该公司以 BSD/OS 作为 SecureOS 的基石。在这,他主要开发的产品是 Sidewinder 防火墙,后来被称为 McAfee Firewall Enterprise(即臭名昭著的迈克菲防火墙企业版)。由于 BSD/OS 的开发逐渐停滞,Karels 提议将 SecureOS 从 BSD/OS 迁移到 FreeBSD。多年来,该项目中的许多重要成果都回馈给了 FreeBSD。Karels 在 2017 年被正式任命为 FreeBSD 的提交者。退休后,他继续在业余时间为 FreeBSD 做贡献。

    奖项、书籍和演讲

    1993 年,USENIX 协会为加利福尼亚大学伯克利分校计算机系统研究小组授予终身成就奖,以表彰包括 Karels 在内的 180 位人士,他们为 CSRG 发布 4.4BSD-Lite 做出了贡献。

    Michael J. Karels 与 Marshall Kirk McKusick 合著了多本关于《4.3BSD UNIX 操作系统设计与实现》的书籍。去年五月,Karels 在渥太华举行的 FreeBSD 开发者峰会 2023 上谈到了他在 BSD 生态系统内的职业生涯。

    FreeBSD 新手?来参与社区吧

    • 原文链接:https://freebsdfoundation.org/blog/new-to-freebsd-heres-where-to-connect-with-the-community/

    • 译者:Canvis-Me & ChatGPT

    2023 年 10 月 4 日

    image

    FreeBSD 项目始终对新用户和贡献者充满期待!参与其中的最简单方式是通过社区本身:邮件列表、社交媒体和本地聚会。这里充满了热衷于帮助新用户的 FreeBSD 用户、开发者和爱好者。它们是讨论 FreeBSD、认识社区成员以及询问有关操作系统的问题的绝佳场所。

    想要回馈社区吗?新的贡献者可以帮助校对现有文档、提供全新的详细文档、推荐错误修复,并将新软件移植到 FreeBSD。无论你的专业知识如何,都有一个适合每个人的地方!

    通过 建立联系!

    • 是与更广泛的 FreeBSD 社区建立联系的绝佳起点,同时可能找到在使用 FreeBSD 时遇到的任何问题的答案。

    • 包含大量关于使用 FreeBSD Current 的讨论。

    在社交媒体上找到 FreeBSD 社区!

    • 加入 。

    • 在 上参与讨论。

    • 在 上提问并讨论。

    • 加入 。

    找到本地用户组和活动!

    • 查找你最近的 。

    • 在你所在地区查找即将举行的 。

    介绍来 FreeBSD 的学生

    • 原文链接:https://freebsdfoundation.org/blog/introducing-students-to-freebsd/

    • 作者:Deb Goodkin

    • 译者:Canvis-Me & ChatGPT

    2023 年 10 月 4 日

    基金会在 2023-2024 年的目标之一是提高 FreeBSD 的使用率和知名度。这是一个相当广泛而宏伟的目标,因此我们将其分解为一些我们计划针对的关键市场/受众群体。我们确定的一个群体是大学生。在他们教育生涯的早期介绍 FreeBSD 将有助于为他们在系统编程方面的工作做准备,并为未来的许多机会提供有市场价值的技能。此外,通过有更多人为 FreeBSD 做贡献,项目也会受益。

    以下是我们正在制定的 FreeBSD 大学计划的简要概述,尽管它目前还在规划阶段。然而,我们有一位最近的实习生愿意与我们合作,并在本学期在他的大学介绍 FreeBSD。

    首先,我们将确定 2-3 所大学,与其合作开发这个试点项目。我们已经确定了两所我们正在合作开展项目的大学,同时也在关注其他可能性。

    项目的一些目标包括:

    • 在几所大学内培养 FreeBSD 大使,以促进 FreeBSD 的意识和采用。

    • 将 FreeBSD 纳入操作系统课程,确保学生了解这个可行的选择。

    • 制定教育/培训材料,帮助学生学习如何使用 FreeBSD 并过渡为开发人员和贡献者。

    • 改进新手接触 FreeBSD 的流程。这将包括入门文档、系统管理员和开发人员培训视频、改进桌面体验以及简化在裸机系统上的安装。

    我们很高兴开始推动这个计划,并将随时向大家通报最新进展。如果你有兴趣在你的大学介绍 FreeBSD,请通过 与我联系,并告诉我你希望在该计划的初始阶段参与的方式。

    我的 FreeBSD 故事

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2018/09

    由于 邀请我为他的 Tell Your BSD Story(讲述你的 BSD 故事) 页面撰写一篇文章,我实在无法拒绝。该页面原本位于 ,但很遗憾,Roman 后来放弃了 bsdjobs.com 这个域名。我本想尽量简短,但看来还是不够直白 :🙂:

    最近也被添加到了页面

    如何安装和配置 Galene 视频会议服务器

    • 原文:

    • 2025 年 7 月 7 日

    • 作者:Benedict Reuschling

    EuroBSDCon 2023 旅行报告——Mark Johnston

    • 原文链接:

    • 作者:Mark Johnston

    • 译者:Canvis-Me & ChatGPT

    2023 年 10 月 24 日

    FreeBSD 基金会慷慨地资助了我前往葡萄牙科英布拉参加 EuroBSDCon 2023 的行程。与往常一样,会议包括为期两天的 FreeBSD 开发者峰会,然后是为期两天的正式会议。会议在科英布拉大学的几幢建筑中举行,这本身就值得一游:大学建筑壮丽宏伟,坐落在山上,可以俯瞰整个城市。每天早上爬上山有点辛苦,但非常值得。

    FreeBSD 并没有死,别听信那些夸张的说法

    • 原文:

    • 2025-5-20

    我来到基金会已经大约三个月了。在这段时间里,我和一些正在使用 FreeBSD 的企业、以及一些有意愿使用 FreeBSD 的企业进行过几次交谈。在不止一次的场合中,有个说法让我不禁挑眉——因为这既不是我所见,也不是我所感受到的。那句话是:“FreeBSD 不是快死了吗?”

    等等!什么?你怎么会这么想?

    在我仔细拆解这个问题的过程中,我得出了一个惊人的结论,以及一个显而易见的事实。在我们一起踏上这段旅程之前,我先简明地回答这个问题:不,FreeBSD 没有死,甚至连濒死都谈不上。 我为什么如此肯定?请往下看……

    谷歌搜索正在往你脑子里灌输观念

    FreeBSD v14:恪守类 Unix 操作系统传统,提升安全性与性能

    • 原文链接:

    • 作者:Sean Michael Kerner

    • 时间:2023 年 11 月 22 日 7:04

    恭喜 FreeBSD 迎来 30 周年!为什么开源项目 FreeBSD 能够持续存在

    • 原文链接:

    • 作者:Deb Goodkin

    • 译者:ykla 使用 deepl【】部分为 ykla 注释

    在庆祝成功的 FreeBSD 的三十年里,我们可以归功于开源自由、强大的文化、共享的领导模式、现代的开发实践和不断演进的稳健代码。

    FreeBSD 的 30 岁生日为我们提供了一个机会,回顾并探究为什么这个开源操作系统不仅能够长久存在,而且在许多组织和应用场景中蓬勃发展。虽然开源项目诞生的背景各不相同,但 FreeBSD 从一开始就有着独特的发展模式。该项目所采取的路径与其长寿有着密切关系,这也解释了为什么 30 年之后,你会发现 FreeBSD 的代码帮助驱动着从 Netflix 上的内容到 PlayStation 上的游戏等各种应用。

    FreeBSD 基金会宣布通过 SSDF 认证

    • 原文链接:

    • 作者:Boulder, CO & San Jose, CA

    • 译者:Canvis-Me & ChatGPT

    2023 年 11 月 3 日

    新报告帮助 FreeBSD 商业用户遵守美国政府安全软件开发报告要求。

    Quantum Leap Research 和 FreeBSD 基金会将投资 75 万美元以改善笔记本电脑支持和用户体验

    原文地址:

    2024 年 9 月 24 日

    (2024 年 9 月 20 日,科罗拉多州博尔德市)FreeBSD 基金会宣布与 Quantum Leap Research(量子跃迁研究)建立战略合作伙伴关系,共同投资总额达 75 万美元,用于增强对 FreeBSD 在笔记本电脑和通用平台的支持。Quantum Leap Research 是一家专注于为国家安全威胁提供解决方案的公司,承诺捐赠 25 万美元,而 FreeBSD 基金会将投资 50 万美元。

    整个计划的预算估计为 100 万美元,基金会欢迎其他组织提供资金支持,以填补资金缺口 25 万美元。

    该计划将专注于笔记本电脑和通用计算的关键可用性功能,包括现代 WiFi、完整音频支持、现代化的待机和恢复功能、改进显卡性能、蓝牙以及其他已确定的功能。

    “FreeBSD 是一款高性能、安全的操作系统,可支持 Dell ThinOS 等笔记本电脑以及多种流行桌面设备。我们最近的 FreeBSD 社区调查显示,43% 的受访者将 FreeBSD 用作日常使用的系统。Quantum Leap Research 和 FreeBSD 基金会的投资将明显丰富 FreeBSD 平台的支持范围,使其成为那些重视稳定性、安全性、简洁性和性能的用户的绝佳选择。”——FreeBSD 基金会高级技术总监 Ed Maste 表示。

    FreeBSD 基金会执行董事 Deb Goodkin 补充道:“这一举措是 FreeBSD 的重大进步,尤其是对于依赖笔记本电脑完成日常计算任务的用户而言。通过增加硬件支持和改进可用性功能,我们正在使 FreeBSD 对更宽泛的受众更加友好。此项投资不仅强化了 FreeBSD 生态系统,也符合我们推广 FreeBSD 作为稳健、安全和多功能操作系统的使命。”

    增强 FreeBSD 在笔记本电脑上的支持和可访问性将有助于实现基金会的战略目标,即加速开发者和企业的采用。确保 FreeBSD 在多种个人计算设备上“开箱即用”表现良好,不仅会吸引开发者使用、测试和为 FreeBSD 项目做出贡献,还将扩大企业的应用范围。

    “Quantum Leap Research 认为,FreeBSD 是新一代安全计算计划的绝佳基础,得益于其在安全性和稳定性方面的悠久历史。”Quantum Leap Research 总裁 Jim Miller 表示。Quantum Leap 计划在现代笔记本电脑上运行 FreeBSD,作为一种类似虚拟机管理程序的解决方案,利用 Bhyve 来虚拟化其他操作系统,如 Linux 和 Windows。

    庆祝 FreeBSD 成立 30 周年:许可证

    • 译者:ykla

    今天的主题:许可证

    在决定新项目要使用什么许可证时,有许多许可证可供选择。今天,我们将专注于 Berkeley(伯克利)软件发行(BSD)许可证的 2 条款变体,也被称为 FreeBSD 许可证。对于许多人来说,商业友好的 FreeBSD 许可证提供了他们所寻求的灵活性。为什么呢?首先让我们看一下许可证本身。

    FreeBSD 许可证

    参考译文:

    换句话说,FreeBSD 许可证不要求派生源代码使用与原始代码相同的许可证条款。这意味着 FreeBSD 可以作为其他项目和专有软件的组件使用,而无需共享派生代码。相比之下,Linux 是根据 GNU 通用公共许可证(GPL)许可的。GPL 也被称为“共享协议”,是相互的,意味着 GPL 项目的派生代码也必须以相同的许可证条款提供。

    FreeBSD 及其组件可以用于构建专有软件,没有任何限制。从法律角度来看,这也对开发者具有吸引力。你可以随心所欲地使用(他的)代码。

    浏览 FreeBSD 新的季度和两年一次发布计划

    • 原文链接:

    • 发布时间:2024 年 7 月 16 日

    FreeBSD 用户,准备好迎接更流畅、更可预测的系统管理体验吧!我们很高兴地宣布 。这些更新将改善你的整体体验,增强系统安全性,并简化维护工作。

    EuroBSDCon 2023 旅行报告——Bojan Novković

    • 原文链接:

    • 作者:Bojan Novković

    • 译者:Canvis-Me & ChatGPT

    2023 年 10 月 20 日

    今年,我有幸获得了 FreeBSD 基金会的差旅津贴,参加了在葡萄牙科英布拉举行的 EuroBSDcon。

    zpool import -o readonly mypool
    zpool import -D mypool
    zpool create mypool disk1
    zpool create mystripe disk1 disk2
    zpool create mymirror mirror disk1 disk2
    zpool create paritypool raidz disk1 disk2 disk3
    zpool create myraidz2 raidz2 disk1 disk2 disk3 disk4
    zpool create myr10 mirror disk1 disk2 mirror disk3 disk4
    zpool create myz3 raidz3 disk1 disk2 disk3 disk4 disk5
    zpool status
    zpool list
    zpool iostat
    zpool history
    zpool get
    zpool add mypool cache /dev/nda0
    zpool add mypool log /dev/nda1
    zpool add mypool spare /dev/nda2
    zpool attach mypool mirror /dev/nda0 /dev/nda1
    zpool replace mypool /dev/nda2 /dev/nda3
    zpool export mypool
    zpool import
    zpool import mypool
    zpool import oldname newname
    zpool import -R /media mypool
    zpool create test disk1
    zfs create mypool/ds
    zfs create -p mypool/home/fred
    zfs list
    zfs list mypool/ds
    zfs list -r mypool/ds
    zfs list -d 1 mypool/home
    zfs list -o name mypool/home
    zfs list -Ho name mypool/home
    zfs list -o used,avail,refer,name
    zfs list -rs refer mypool/home
    zfs list -rS refer mypool/home
    zfs list -o space
    zfs rename mypool/home/fred mypool/home/eva
    zfs destroy -nv mypool/old
    would destroy mypool/old
    zfs destroy -v mypool/old
    will destroy mypool/old
    zfs destroy -r mypool/testdata
    zpool get all mypool
    zfs get all mypool/dataset
    zpool get capacity mypool
    zpool get capacity,health mypool
    zfs set atime=off mypool
    zfs set mountpoint=/media mypool/ds
    zfs set warranty:expires=2048/04/20 mypool
    zfs get warranty:expires mypool
    zfs inherit warranty:expires mypool
    zfs inherit -r warranty:expires mypool
    zpool scrub mypool
    zpool status
    zfs create -V 10G mypool/vol1
    zfs create -V 1P -s mypool/sparse1PBvol
    zfs set quota=10G mypool/dataset
    zfs set refquota=10G mypool/dataset
    zfs set userquota@fred=10G mypool/home/fred
    zfs set groupquota@projectX=100G mypool/projectX
    zfs get quota mypool/dataset
    zfs get refquota mypool/home/fred
    zfs userspace mypool/home/fred
    zfs groupspace mypool/projectX
    zfs set quota=none mypool/home/fred
    zfs set reservation=100G mypool/home
    zfs set refreservation=10G mypool/home/eve
    zfs get reservation mypool/home/eve
    zfs list -o space
    zfs set reservation=none mypool/home/eve
    zfs snapshot mypool/ds@mysnapshot
    zfs snap mypool/ds@mysnapshot
    zfs snap -r mypool/ds@mysnapshot
    zfs list -t snap mypool/ds
    zfs list -rt snap mypool/ds
    zfs list -rt all -o name,used,refer,written mypool
    zfs diff mypool/ds@backup
    zfs diff mypool/ds@backup1 mypool/ds@backup2
    zfs rollback mypool/ds@backup2
    zfs rollback -r mypool/ds@backup1
    mount -t zfs mypool/ds@backup /mnt/backup
    zfs destroy -vn mypool/ds@backup
    zfs destroy -v mypool/ds@backup
    zfs destroy -rv mypool/ds@backup
    mypool@a  
    mypool@b  
    mypool@c  
    mypool@d  
    mypool@e  
    zfs destroy -v mypool@b%d
    zfs destroy -v mypool@b%
    zfs hold keepme mypool/home@important
    zfs holds -r mypool/home@important
    zfs release keepme mypool/home@important
    zfs clone mypool/ds@backup mypool/myclone
    zfs get origin mypool/myclone
    zfs promote mypool/myclone
    zfs destroy mypool/myclone
    zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt mypool/secret
    zfs get keystatus mypool/secret
    zfs load-key mypool/secret
    zfs allow -u joe atime mypool/dataset
    zfs allow mypool/dataset
    zfs unallow -u joe compression mypool/dataset
    zfs allow -g mygroup atime mypool/dataset
    zfs allow -u jill allow mypool/dataset
    zfs allow -s @myset mount,snapshot,rollback,destroy mypool/dataset
    zfs allow -u jill @myset mypool/dataset
    zfs send mypool/ds@backup > dsbackup
    zfs send -v mypool/ds@backup > target
    zfs recv mypool/backup < dsbackup
    zfs recv -v mypool/backup < dsbackup
    zfs send mypool/ds@backup | zfs recv mypool/new
    zfs send poolA/ds@backup | ssh host zfs recv poolB/new
    zfs allow -u sender send,snapshot mypool/source
    zfs allow -u receiver compression,mountpoint,mount,create,receive mypool/destination
    zfs destroy -v mypool@%b
    # sysctl net.wlan.devices
    net.wlan.devices: iwn0
    # dmesg
    (...)
    ugen2.3:  at usbus2
    rtwn0 on uhub4
    rtwn0:  on usbus2
    rtwn0: MAC/BB RTL8188CUS, RF 6052 1T1R
    # usbconfig
    (...)
    ugen2.3:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (500mA)
    
    # usbconfig -d 2.3 show_ifdrv
    ugen2.3:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (500mA)
    ugen2.3.0: rtwn0:
    # sysctl net.wlan.devices
    net.wlan.devices: rtwn0 iwn0
    # ifconfig wlan1 create wlandev rtwn0
    
    # ifconfig wlan1
    wlan1: flags=8802<broadcast,simplex,multicast> metric 0 mtu 1500
            ether 00:1d:43:21:2d:1c
            groups: wlan
            ssid "" channel 1 (2412 MHz 11b)
            regdomain FCC country US authmode OPEN privacy OFF txpower 30 bmiss 7
            scanvalid 60 wme bintval 0
            parent interface: rtwn0
            media: IEEE 802.11 Wireless Ethernet autoselect (autoselect)
            status: no carrier
            nd6 options=21<performnud,auto_linklocal>
    
    # wpa_passphrase WIFINETWORK PASSWORD >> /etc/wpa_supplicant.conf
    
    # wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf
    Successfully initialized wpa_supplicant
    wlan1: Trying to associate with d8:07:b8:b8:f4:81 (SSID='wireless' freq=2442 MHz)
    wlan1: Associated with d8:07:b6:b8:f4:81
    wlan1: WPA: Key negotiation completed with d8:07:b6:b8:f4:81 [PTK=CCMP GTK=CCMP]
    wlan1: CTRL-EVENT-CONNECTED - Connection to d8:07:b6:b8:f4:81 completed [id=40 id_str=]
    ^Z // 在这里按 [CTRL]+[Z] 键
    zsh: suspended  wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf
    
    # bg
    [1]  + continued  wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf
    
    #
    # ps ax | grep wpa_supplicant
    48693  4  S        0:00.43 wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf
    50687  4  S+       0:00.00 grep --color wpa_supplicant
    
    # ifconfig wlan1
    wlan1: flags=8843<up,broadcast,running,simplex,multicast> metric 0 mtu 1500
            ether 00:1d:43:21:2d:1c
            groups: wlan
            ssid wireless channel 7 (2442 MHz 11g ht/20) bssid d8:07:b6:b8:f4:81
            regdomain FCC country US authmode WPA2/802.11i privacy ON
            deftxkey UNDEF AES-CCM 2:128-bit txpower 30 bmiss 7 scanvalid 60
            protmode CTS ht20 ampdulimit 64k ampdudensity 4 shortgi -stbc -ldpc
            -uapsd wme roaming MANUAL
            parent interface: rtwn0
            media: IEEE 802.11 Wireless Ethernet MCS mode 11ng
            status: associated
            nd6 options=29<performnud,ifdisabled,auto_linklocal>
    # dhclient wlan1
    DHCPDISCOVER on wlan1 to 255.255.255.255 port 67 interval 3
    DHCPOFFER from 10.0.0.1
    DHCPREQUEST on wlan1 to 255.255.255.255 port 67
    DHCPACK from 10.0.0.1
    bound to 10.0.0.9 -- renewal in 3600 seconds.
    # echo nameserver 1.1.1.1 > /etc/resolv.conf
    
    # ping -c 3 freebsd.org
    PING freebsd.org (96.47.72.84): 56 data bytes
    64 bytes from 96.47.72.84: icmp_seq=0 ttl=50 time=119.870 ms
    64 bytes from 96.47.72.84: icmp_seq=1 ttl=50 time=119.371 ms
    64 bytes from 96.47.72.84: icmp_seq=2 ttl=50 time=119.128 ms
    
    --- freebsd.org ping statistics ---
    3 packets transmitted, 3 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 119.128/119.456/119.870/0.309 ms
    服务器  ==局域网==>  路由器  ==WiFi==>  笔记本  @  2.9 MB/s
    笔记本  ==WiFi==>  路由器  ==局域网==>  服务器  @  2.6 MB/s
    (host) # beadm create 13                        # 创建新的 '13' ZFS Boot Environment
           Created successfully
    (host) # beadm mount 13 /var/tmp/BE-13          # 将新的 '13' BE 挂载到某个目录
           Mounted successfully on '/var/tmp/BE-13'
    (host) # chroot /var/tmp/BE-13                  # 切换到该目录的 chroot(8) 环境
      (BE) # mount -t devfs devfs /dev              # 在该 BE 中挂载 devfs(8)
      (BE) # rm -rf /var/db/freebsd-update          # 删除任何旧补丁
      (BE) # mkdir /var/db/freebsd-update           # 为补丁创建新的目录
      (BE) # freebsd-update upgrade -r 13.0-BETA3   # 获取升级所需的补丁
      (BE) # freebsd-update install                 # 安装内核及内核模块
      (BE) # freebsd-update install                 # 安装用户空间程序/二进制文件/库
      (BE) # pkg upgrade                            # 使用 pkg(8) 升级所有软件包
      (BE) # freebsd-update install                 # 移除旧的库和文件
      (BE) # exit                                   # 退出 chroot(8) 环境
    (host) # umount -f /var/tmp/BE-13/dev           # 卸载该 BE 中的 devfs(8)
    (host) # beadm activate 13                      # 激活新的 '13' BE
           Activated successfully
    (host) # gpart show -p ada1 | grep efi                # 查找 UEFI msdosfs(5) 分区
                   40     409600  ada1p1  efi  (200M)     # <-- 就是这一项
    (host) # mount_msdosfs /dev/ada1p1 /mnt               # 将其挂载到 /mnt 下
    (host) # find /mnt                                    # 显示其内容
           /mnt
           /mnt/efi
           /mnt/efi/boot
           /mnt/efi/boot/bootx64.efi                      # 更新 bootx64.efi 文件
    (host) # cp /boot/boot1.efi /mnt/efi/boot/bootx64.efi # 从 /boot/boot1.efi 文件复制
    (host) # umount -f /mnt                               # 卸载 /mnt 文件系统
    (host) # mount_msdosfs /dev/ada1p1 /mnt # 尝试挂载 EFI 分区时出错
           mount_msdosfs: /dev/ada1p1: Invalid argument
    
    (host) # fsck_msdosfs -y /dev/ada1p1    # 尝试对该分区执行 fsck(8) 时出错
           ** /dev/ada1p1
           Invalid signature in boot block: 0b6a
    (host) # dd < /dev/ada1p1 > /BACKUP.ada1p1 bs=1m
    (host) # newfs_msdos -F 32 -c 1 /dev/ada0p1            # 创建新的 FAT32 分区
    (host) # mount_msdosfs /dev/ada0p1 /mnt                # 挂载到 /mnt 下
    (host) # mkdir -p /mnt/efi/boot                        # 创建所需目录
    (host) # cp /boot/loader.efi /mnt/efi/boot/bootx64.efi # 从 /boot/loader.efi 复制文件
    (host) # umount -f /mnt                                # 卸载 /mnt 文件系统
    (host) # reboot
    (host) # beadm list
           BE   Active Mountpoint Space Created
           12.2 -      -           6.5G 2021-02-12 10:15
           13   NR     /          18.8G 2021-02-13 11:32
    (host) # beadm list -D
           BE   Active Mountpoint  Space Created
           12.2 -      -            9.8G 2021-02-12 10:15
           13   NR     /            9.6G 2021-02-13 11:32
    (host) # beadm destroy 12.2
    # dd if=FreeBSD-13.0-BETA3-amd64-memstick.img of=/dev/da0 bs=1M status=progress
    # fetch -o /usr/local/sbin/beadm https://raw.githubusercontent.com/vermaden/beadm
    # beadm create 13.1-RC6
    # beadm chroot 13.1-RC6
    BE # zsh || csh
    BE # yes | freebsd-update upgrade -r 13.1-RC6
    BE # 重复执行 3 次 freebsd-update install
    BE # exit
    # beadm activate 13.1-RC6
    # reboot
    # beadm create 13.1-RC6
    # beadm chroot 13.1-RC6
    BE # sh || bash || fish || ksh
    BE # yes | freebsd-update upgrade -r 13.1-RC6
    BE # seq 3 | xargs -I- freebsd-update install
    BE # exit
    # beadm activate 13.1-RC6
    # reboot
    root@fbsd12:~ # beadm
    usage:
      beadm activate 
      beadm create [-e nonActiveBe | -e beName@snapshot] 
      beadm create 
      beadm destroy [-F] 
      beadm list [-a] [-s] [-D] [-H]
      beadm rename  
      beadm mount  [mountpoint]
      beadm { umount | unmount } [-f] 
      beadm version
    root@fbsd12:~ # bectl
    missing command
    usage:  bectl ( -h | -? | subcommand [args...] )
            bectl activate [-t] beName
            bectl create [-e nonActiveBe | -e beName@snapshot] beName
            bectl create beName@snapshot
            bectl destroy [-F] beName | beName@snapshot⟩
            bectl export sourceBe
            bectl import targetBe
            bectl jail [ -o key=value | -u key ]... bootenv
            bectl list [-a] [-D] [-H] [-s]
            bectl mount beName [mountpoint]
            bectl rename origBeName newBeName
            bectl { ujail | unjail } ⟨jailID | jailName | bootenv)
            bectl { umount | unmount } [-f] beName
    root@fbsd12:~ # bectl rename safe new
    boot environment is already mounted
    failed to rename bootenv safe to new
    root@fbsd12:~ # bectl list
    BE      Active Mountpoint Space Created
    safe    NR     /          188K  2018-08-18 02:32
    default -      -          427M  2018-08-18 02:26
    
    root@fbsd12:~ # zfs list | grep safe
    zroot/ROOT/safe      108K  6.85G   427M  /
    
    root@fbsd12:~ # zfs rename -u zroot/ROOT/safe zroot/ROOT/new
    root@fbsd12:~ # bectl list
    BE      Active Mountpoint Space Created
    new     NR     /          188K  2018-08-18 02:32
    default -      -          427M  2018-08-18 02:26
    root@fbsd12:~ # bectl list
    BE      Active Mountpoint Space Created
    new     NR     /          188K  2018-08-18 02:32
    default -      -          427M  2018-08-18 02:26
    
    root@fbsd12:~ # bectl jail default
    # pwd
    /
    # ls /
    .cshrc          bin             entropy         libexec         net             root            usr
    .profile        boot            etc             media           proc            sbin            var
    COPYRIGHT       dev             lib             mnt             rescue          tmp             zroot
    # exit
    root@fbsd12:~ # jls
       JID  IP Address      Hostname                      Path
         1                  default                       /tmp/be_mount.OnRc
    
    root@fbsd12:~ # mount | grep default
    zroot/ROOT/default on /tmp/be_mount.OnRc (zfs, local, noatime, nfsv4acls)
    
    root@fbsd12:~ # bectl unjail default
    
    root@fbsd12:~ # jls
       JID  IP Address      Hostname                      Path
    root@fbsd12:~ # bectl list
    BE      Active Mountpoint Space Created
    new     NR     /          188K  2018-08-18 02:32
    default -      -          427M  2018-08-18 02:26
    
    root@fbsd12:~ # beadm destroy safe
    Are you sure you want to destroy 'safe'?
    This action cannot be undone (y/[n]): n
    
    root@fbsd12:~ # bectl destroy safe
    
    root@fbsd12:~ # bectl list
    BE      Active Mountpoint Space Created
    new     NR     /          188K  2018-08-18 02:32
    # alias beadm=bectl
    # alias beadm bectl
    https://reviews.freebsd.org/D50650
    FreeBSD 邮件列表

    为学生与潜在雇主互动创造途径,以深入了解雇主在招募大学生时寻找的技能。

  • 将该计划的可用性扩展到其他大学。

  • [email protected]

    由于技术问题,开发者峰会的第一天开始得有些晚,但这提供了与其他与会者聊天和了解的好机会。我与 Ruslan Bukin(br@)聊了一些关于他计划将一些软件移植到 Morello 的计划,Morello 是 ARM 的 CHERI 的硬件实现。我还与 Bojan Novković 交谈,他是我今年谷歌编程之夏的学生,谈论了他一直在努力实现的一些补丁。他在谷歌编程之夏结束后继续为 FreeBSD 做贡献。我终于见到了 Olivier Certner,他最近开始为内核贡献高质量的补丁和代码审查。

    技术问题得到解决之后,一些演讲按计划进行。几位 FreeBSD 基金会的工作人员介绍了基金会活动的最新进展;看到众多正在进行中的实习项目的反馈很不错。在此之后,Justin Gibbs 进行了一场题为“如果你不害怕,你会做什么?”的演讲,讲述了 FreeBSD 开发者社区的技术成就和“第一次”的历史。一个统一的主题是,项目需要近乎鲁莽的雄心壮志,以及勇于尝试的意愿,而不必过多担心失败的可能性。演讲中强调了很多这样的例子,CHERI 和最初将 ZFS 移植到 FreeBSD 的例子就是其中几个。然后,Justin 邀请我们设想如果不必考虑失败,我们会做什么,人们分享了各种想法。

    我们中的一些人一起在学生餐厅用午餐并聊了起来。午餐后,来自基金会的 Greg Wallace 提出了 SWOT 分析的想法,该分析对组织的优势、劣势、机会和威胁进行概述,以提供未来工作规划的客观背景。房间分成小组,每个小组都对 FreeBSD 进行了自己的 SWOT 分析。下午,我终于见到了 Christos Margiolis(christos@),他最近完成了基金会的实习,也是我在 2022 年的谷歌编程之夏学生。尽管我们在几个项目上一直一起工作,但这是我们首次面对面会面,所以见到他真是太好了。我们和其他一些人聊了很多有关 FreeBSD 的话题。在这一天的最后,Jordan Hubbard 进行了一场演讲,诉说了他的职业生涯,并提出了他认为大型语言模型和其他机器学习创新将如何在短期内改变软件领域的观点。

    开发者峰会的第二天以几场技术演讲开始。首先,Ruslan Bukin 介绍了他最近在 CPU 跟踪方面的一些工作,该工作使得可以使用 ARM CoreSight 和 Intel PT 等技术。这些设施允许 CPU 实时记录其操作,以相对较小的开销对 CPU 的行为进行细粒度跟踪。Ruslan 的实现,HWT,目前针对 ARM 但已设计为可扩展。Ruslan 还进行了一些有趣的演示,其中他使用启用跟踪的小命令行实用程序(例如 uname(1))。这展示了 HWT 的符号解析能力。HWT 在精神上与 Christos 最近由基金会赞助的有关 DTrace 的工作相似,该工作使得可以跟踪单个 CPU 指令,但具有完全不同的权衡。

    然后,Bojan 介绍了他为谷歌编程之夏开始的一些工作,具体是一个用于内核性能基准测试的框架。这是因为要总结他所开发的主要功能(一个执行在线内存碎片整理的内核子系统)的性能改进和影响是一项挑战。特别地,这样的系统必然会有一些性能开销,因为它消耗 CPU 资源,但它(希望)通过为系统的其余部分提供更连续的物理内存而带来一些好处,这可以改善某些工作负载的性能。因此,确定该功能的净效果是一项棘手的任务,因此需要进行基准测试。

    接下来的一天的日程相对较轻松,所以我花了一些时间来开发一个个人项目,目的是让运行 FreeBSD 回归测试套件变得更容易,并与其他一些 FreeBSD 开发人员讨论了我们的开发工具中的各种差距和不一致。

    随后的几天举办了 EuroBSDCon。我参加了相当多的演讲,一些亮点包括:

    • Hiroki Sato 针对他在 FreeBSD 的 USB 堆栈上的补丁进行演讲,以启用 USB 调试功能。这是一种存在于一些 USB 控制器中的硬件特性,允许在 USB 上创建通信通道。这样就能为任何带有兼容 USB 控制器的设备提供调试控制台。这对于调试与笔记本电脑的挂起/恢复相关的问题应该非常有用,否则缺乏可用于调试的带外通道。这项工作需要一些特殊的硬件,特别是 USB 交叉线;幸运的是,Hiroki 在演讲后带来了几个,大家可以买。我不得不迅速行动,最后抢到了一个。

    • Christos Margiolis 关于 kinst 的演讲,这是他在谷歌编程之夏 2022 和他在 2023 年基金会实习期间开发的新 DTrace provider 程序。我以前已经与他在这方面合作过,因此对技术背景已经很熟悉,但看到他向更广泛的观众展示它还是很不错的。kinst 是一种相当底层的技术,需要一些 CPU 内部知识才能理解。Christos 在向多样化的观众解释它时做得非常出色。演讲后有许多有趣的问题和讨论,我也参与其中。

    • Michael Chiu 对 xc 的工作进行了介绍,这是一个针对 FreeBSD 的新的容器运行时。这是一项非常令人印象深刻的工作,提供了几个围绕管理 FreeBSD jail 的便利功能。演讲包括相当多的演示,例如使用 xc 在 FreeBSD 上的 Linux jail 中启动 MariaDB。我受到演讲的启发,尝试使用 xc 来运行一些我自己的工作负载;特别是,它似乎将成为在 FreeBSD 上运行最小设置的自动化测试的一种相当有用的方式。我一直在开发一个 xc 配置,可以用在 FreeBSD 上运行 syzkaller。总体而言,我对 Michael 的工作感到非常激动。

    我还与 Warner Losh 进行了一些交流,了解他启用通过 LinuxBoot 引导 FreeBSD 的一些工作。LinuxBoot 通过将传统的引导固件替换为一个负责初始化硬件然后引导主 Linux 内核的最小 Linux 内核,简化了某些平台上的引导过程。以这种方式引导 FreeBSD 涉及实现一个称为 kexec(2) 的二进制接口;这个工作是 Warner 演讲的主题。最近,我一直在进行一个在精神上类似的项目,有相当多的技术重叠,所以听到他的工作很有帮助,当我们要将各自的项目提交到 FreeBSD 时,我们可以一起努力。

    我想感谢 FreeBSD 基金会对我行程的赞助;我进行了很多非常富有成效的交流,并了解了 FreeBSD 社区中其他人正在从事的工作。

    https://freebsdfoundation.org/blog/eurobsdcon-2023-trip-report-mark-johnston/

    BSD(前 FreeBSD)

    FreeBSD 最初于 1993 年发布,它扎根于 Berkeley 软件发行版(BSD,即伯克利发行版套件)的代码基础上,该发行版自上世纪 70 年代以来一直在开发中。先驱性的 BSD 项目引入了套接字网络接口、TCP/IP 的首个实现、包括 VFS、FFS 和 NFS 在内的文件系统、mmap 内存模型等。尽管 BSD 不是开源的,但其受许可的代码仍然得到了许多学术界和工业界用户的贡献。

    大部分的 BSD 代码在 4.4BSD-Lite 发行版中以开源软件的形式提供,为 FreeBSD 提供了基础。其技术的基础性质自那时起就成为其成功的重要因素之一。

    集体领导模式

    为了管理领导继任并避免与许多其他开源项目普遍采用的单一领导结构相关的风险,FreeBSD 项目的创始人成立了 FreeBSD 核心团队(FreeBSD Core Team),这是一个负责项目方向和控制提交者特权的领导小组。尽管在最初由创始人自己分配这些领导者,但在 2000 年,核心团队的九个席位变为由选举产生。使提交者能够为 FreeBSD 的领导层投票并让自己晋升为领导角色,使该项目保持了特别的强大性和能够不断演进的能力。

    现代远程开发

    FreeBSD 从一开始就利用源代码控制、错误报告和其他工具来支持远程开发。在一个时代,开源项目发行版通常由个人维护,个人负责添加所有代码贡献时,FreeBSD 的策略的新颖优势已经成为定义现代实践的标志。这种超越标准限制的加速开发的自由意味着迅速整合代码,包括从 NetBSD 和 OpenBSD 获取的有价值的功能。

    对硬件的审慎选择

    FreeBSD 项目从一开始就决定选择推荐的硬件并提供细致、有针对性的支持。因此,当涉及可靠性和性能指标时,FreeBSD 一直处于领先地位。这种区别是为什么它成为从拨号时代到现代 Web 服务器提供商都持久受欢迎的选择的原因。

    出色的沟通、文档、支持和文化

    由于 FreeBSD 支持远程开发和全球贡献,该项目在开发邮件列表方面特别注重策略,以保持工作和设计讨论的组织和高效。因此,FreeBSD 迅速实现了思考周到的沟通管理,通过监控和调节保持讨论的文明(是的,文明!)和专注,同时不限制言论自由,并为来自不同文化背景的开发者提供服务。

    FreeBSD 在软件文档方面也取得了出色的成绩。从一开始就专注于招募文档贡献者,并要求开发者参与确保文档的准确和完整。为了实现这个目标,FreeBSD 专门引入了一个与代码提交者拥有相同特权的文档提交者小组。该项目还支持多语言文档框架,使得 FreeBSD 的知识更加易于全球各地的开发者获取。

    在开源领域,文化与技术同样重要,FreeBSD 拥有一个友好和包容的文化,给予所有提交者相同的投票权利(以及在社区中平等的发声权)。蓬勃发展的 FreeBSD 基金会是业界最早成立的之一,提供了一系列深度的项目支持服务。

    宝贵的 Ports

    FreeBSD 的最初版本包含了许多贡献的实用工具和库,而现在这些已经发展成为庞大的 FreeBSD Ports。这个 Ports 在 FreeBSD 之上提供了对先进开源技术的强大且得到良好支持的访问。再次证明,FreeBSD 是一个早期的领导者。多年来,FreeBSD 的软件包管理工具 pkg 一直在不断改进。Poudriere 是一个 FreeBSD 软件包创建和测试工具,它利用了 FreeBSD 的一个重要优势—— jail,允许开发者可复现地测试 port 更改并可靠地构建我们的 30000 多个 port。最后,所有的 port 都以二进制形式提供【除了一些有分发限制的软件,比如 jdk】,使用户可以通过使用 pkg 命令更轻松地安装应用程序。

    最后但同样重要的是开源许可证

    也许对于 FreeBSD 成功的 30 年来说,最重要的贡献者是它的开源 BSD 许可证。BSD 许可证不要求组织将源代码更改与他人共享,而 Linux 则要求如此。那些必须将代表专有知识产权的代码置于产品中的公司需要这种许可自由,例如那些在设备和嵌入式操作系统市场中的公司。这种开源自由,加上强大的领导力、强大的文化和不断演进的稳健代码,是为什么 FreeBSD 现在庆祝着 30 周年生日的原因。

    展望未来的 30 年

    FreeBSD 的 30 周年纪念提醒我们,持久的成功不是偶然发生的。回顾我们的社区在这一时期面对的巨大技术变化和挑战的方式,也可以为我们提供对如何确保在未来几十年庆祝类似里程碑的洞察。通过提供最佳平台,快速尝试和开发新技术,同时提供可靠的商业化基础和广泛采用,我们预计 FreeBSD 将继续蓬勃发展。我们邀请并鼓励你成为未来 30 年的一部分。


    作者 Deb Goodkin 是 FreeBSD 基金会的执行主任,该基金会支持开源的 FreeBSD 操作系统。Deb 自 2005 年 8 月起就加入了该基金会。她在市场营销、销售和数据存储设备的开发方面有超过 20 年的工作经验。她在圣塔克拉拉大学获得了电子工程硕士学位(MSEE),并在加利福尼亚大学圣地亚哥分校获得了计算机工程学士学位(BSCE)。

    Happy 30th, FreeBSD! Why the FreeBSD open source project has endured

    FreeBSD 基金会,是一家致力于推动开源 FreeBSD 操作系统并支持其社区的公共慈善机构,今天宣布推出一项新服务,以帮助使用 National Institutes of Standards and Technology(NIST,美国国家标准及技术研究所)安全软件开发框架(SSDF)的 FreeBSD 商业用户。

    SSDF 将于 2023 年第四季度部分生效,并在 2024 年彻底生效,它是基于 BSA、OWASP 和 SAFECode 等组织的已建立的安全软件开发文档的一套软件开发实践。SSDF 旨在减少美国政府使用的软件解决方案中的软件漏洞。

    一旦生效,OMB 和 CISA 要求所有向美国政府颁发软件许可证的组织自我证明其自身软件及其使用的所有开源组件均符合 SSDF。

    “FreeBSD 社区从其创立以来一直是安全、分布式开源软件开发的先驱。随着世界各地的政府认识到开源的普及性,认识到开源对创新的重要性,以及对设计和默认安全性的需求,FreeBSD 基金会自豪地向我们的商业合作伙伴提供 SSDF 认证,”——FreeBSD 基金会技术高级总监 Ed Maste 表示。

    鉴于美国政府广泛使用 FreeBSD 为无数解决方案提供支持,这项新的基金会服务旨在使供应商和云提供商能够轻松证明他们使用的 FreeBSD 软件的安全开发实践。

    为确保各种规模的商业用户的访问权,FreeBSD SSDF 认证报告对所有 FreeBSD 基金会合作伙伴开放,无论捐赠级别是银牌、金牌还是白金。要了解更多信息,请联系 [email protected]。

    “我们在 NIST 很高兴看到 SSDF 被证明是有用的,并被诸如 FreeBSD 基金会之类的组织采用,因为它试图通过为开源社区开发与安全软件开发实践相对应的认证映射来支持《改善国家网络安全行政命令(EO 14028)》。”——国家标准与技术研究所信息技术实验室计算机安全部的计算机科学家 Murugiah Souppaya 表示。

    “NetApp 自豪地利用 FreeBSD 提供高性能产品,始终满足我们客户对可靠性、安全性和可支持性的期望,包括众多美国军方和文职政府机构,”——NetApp 的 ONTAP 工程高级总监 Matt Hambrick 表示。“在向我们的政府客户报告 NetApp 的安全软件开发流程和程序时,FreeBSD 基金会的 SSDF 认证报告对这些工作是一项有价值且受欢迎的支持。”

    “FreeBSD 是 Metify 技术堆栈的关键部分,我们使用它提供裸机服务器和无线 ISP 解决方案。FreeBSD 的可靠性、安全性、可支持性以及开放而创新的社区对我们来说是关键优势,”——Metify 联合创始人兼首席执行官 Mike Wagner 表示。“作为一家初创公司,FreeBSD 基金会的 SSDF 认证报告对我们的联邦政府增长战略是一个受欢迎的帮助和重要的推动因素。”

    关于 FreeBSD 基金会

    FreeBSD 基金会是一家 501(c)(3) 非营利组织,致力于支持 FreeBSD 项目和社区。接受个人和企业的捐赠,基金会利用资金开发功能,雇用软件工程师,改进构建和测试基础设施,通过线上和线下活动倡导 FreeBSD,并提供培训和教育材料。在法律事务方面代表 FreeBSD 项目,基金会是合同、许可和其他法律安排的承认实体,完全由捐赠支持。了解更多信息,请访问 freebsdfoundation.org。

    https://freebsdfoundation.org/news-and-events/latest-news/freebsd-foundation-announces-ssdf-attestation/

    关于 Quantum Leap Research

    Quantum Leap Research, LLC 为美国政府开发符合未来需求的技术,专注于解决国防部和美国情报界面临的一些最复杂的问题。更多信息请访问 http://www.ql-research.com。


    关于 FreeBSD 基金会

    FreeBSD 基金会是一家 501(c)(3) 非营利组织,致力于支持 FreeBSD 项目及其社区。基金会接受来自个人和企业的捐赠,用于开发新功能、雇佣软件工程师、改进构建和测试基础设施、通过线下和在线活动宣传 FreeBSD,以及提供培训和教育材料。基金会还代表 FreeBSD 项目处理法律事务,是合同、许可和其他法律安排的公认实体,完全依赖捐赠支持。了解更多信息,请访问 freebsdfoundation.org。

    Quantum Leap Research and FreeBSD Foundation to Invest $750,000 to Improve Laptop Support and Usability

    我于 9 月 13 日抵达科英布拉,并在第二天参加了 FreeBSD 开发者峰会。峰会的第一天日程安排得很紧凑。在参加开幕会议并了解 FreeBSD 基金会团队的最新消息后,我与 Mark Johnston 会面,审查并提交了今年谷歌编程之夏项目中剩下的一些补丁。在附近的学生餐厅短暂用过午餐后,我参加了 Sergio 关于新的 FreeBSD.org 网站设计的演讲。

    随后,Greg Wallace 介绍了 SWOT 分析的概念,并组织了一个互动环节。我们分成小组,集思广益,讨论了项目的优势、劣势等方面。这一天的最后一个环节是 Jordan Hubbard 关于 FreeBSD 项目早期历史的演讲,其中融入了他与该项目的个人历史。不幸的是,我的演讲被推迟到了第二天,因此在最后一场演讲后,我与 Li-Wen Hsu 讨论了我打算在 FreeBSD 的 CI 循环中用于性能回归测试的工作。

    开发者峰会的第二天以一场关于我正在进行的旨在测试内核补丁的性能基准框架的演讲开始。这个想法得到了很好的响应,与其他开发人员的讨论也很有见地。之后,我参加了 Ruslan 关于 hwt 的演讲,这是一个用于 FreeBSD 的硬件性能跟踪框架。演讲后,我与 Ruslan 碰面,讨论了向 hwt 添加 Intel 性能跟踪支持的步骤。这标志着闪电演讲的结束,午餐休息后,我与 Christos Margiolis 结对进行了一个一直持续到下午的黑客会话。

    接下来的一天以 Paula Alexandra Silva 的主题演讲开始。在主题演讲后,我参加了 Walter Belgers 的演讲,听取了关于 BSD 早期历史的各种故事和轶事。接下来是 Otto Moerbeek 关于 OpenBSD 的 malloc 的演讲。能够参加由安全堆内存分配器的先驱提供的讲座是一种荣幸,演讲充满了关于堆分配器在运行时防止对普通 C 内存管理错误的恶意滥用的机制的细节和见解。在会场外拍摄了全家福照片并短暂休息用午餐后,我参加了 Hiroki Sato 关于 USB 调试能力的演讲。演讲很棒,我对有一种新的调试实时机器的方式感到兴奋,因为在现代硬件上使用串口已经不再可能。演讲后,我与 Christos 进行了短暂的黑客会话。然后,我参加了 Toshaan 关于在 POWER 架构上运行 FreeBSD 的演讲。这一天在附近的场地结束了一场很棒的社交活动。

    第二天以 Phillip Bueller 关于 EuroBSDcon 历史的精彩演讲开始。之后,我参加了 Eirik Øverby 的演讲,了解了 Modirum 的最新探索。接下来是 Christos 关于 kinst 的演讲,这是一个允许跟踪任意指令的新 DTrace provider 程序。他说了他的方法的一般架构和一些常见用例,并在与观众进行有趣而深入的技术讨论时引发了兴趣。在此之后,我参加了 Kirk 关于 gunion 的演讲。演讲非常有趣,它提供了对 GEOM 的良好概述以及 gunion 的几个有用的应用程序。我参加的下一个环节是 Yan Ka Chiu 关于他正在进行的 OCI 兼容 FreeBSD 容器运行时的演讲。演讲中充满了展示该运行时功能的出色短片。

    我非常感谢 FreeBSD 基金会让我能够参加这次会议。这是一次极好的经历,让我能够与 FreeBSD 社区的其他成员建立联系,并讨论未来的工作。

    https://freebsdfoundation.org/blog/eurobsdcon-2023-trip-report-bojan-novkovic/
    :第三方脚本,通常来自 Ports 或包,也按时间运行。例如,轮转 nginx 日志文件或备份 pkg 文件。
  • /usr/local/etc/periodic/security:来自第三方的安全检查脚本,例如运行 pkg audit 的脚本。

  • 添加错误处理以捕获异常情况并提示,不要让脚本静默失败
  • 通过手动调用和 periodic 调用分别测试脚本

  • periodic.conf(5)
    zfsprops
    newsyslog.conf(5)
    《系统日志配置》
    点击这里查看
    此外,FreeBSD 许可证已被自由软件基金会验证为与 GPL 兼容,也经过了开放源代码促进会【注 1】的审查,被确认为开源许可证。这意味着 FreeBSD 仍然是作为开发产品的参考平台的绝佳选择。FreeBSD 的代码具有最广泛的适用性。你可以从 FreeBSD 入手,然后在任何地方发布。

    像 Nextflix 和他们开发的 Open Connect Appliances【Open Connect Appliance 软件内置了一个 FreeBSD 操作系统和 NGINX 服务器,许可证是 BSD】。像这样的公司,最初就是因为宽松的许可证才吸引了 Open Connect 工程师使用 FreeBSD【注 2】。

    其他公司,例如 Beckhoff 之所以选择 FreeBSD 和宽松的许可证,部分原因是因为 GPL【注 3】不能满足要求。

    简而言之,BSD 许可证,尤其是 FreeBSD 许可证,在构建产品和服务时提供了灵活性和安心感。

    1.-BSD 许可证维基百科页面-https://en.wikipedia.org/wiki/BSD_licenses

    2.-FreeBSD 案例研究:Netflix-https://freebsdfoundation.org/blog/freebsd-case-study-netflix/

    3.-2020 年 FreeBSD 供应商峰会:Beckhoff-https://youtu.be/8LUdZseNrpE


    原文地址:https://freebsdfoundation.org/blog/celebrating-30-years-of-freebsd-licensing/

    Copyright <YEAR> <COPYRIGHT HOLDER>
    
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
    
    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    
    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”
    1       3       *       *       *       root    periodic daily
    15      4       *       *       6       root    periodic weekly
    30      5       1       *       *       root    periodic monthly
    daily_backup_passwd_enable="YES"
    daily_output=/var/log/daily.log
    weekly_output=/var/log/weekly.log
    monthly_output=/var/log/monthly.log
    #!/bin/sh
    
    if [ -r /etc/defaults/periodic.conf ]
    then
      . /etc/defaults/periodic.conf
      source_periodic_confs
    fi
    
    : ${zfs_pool_usage_enable:="YES"}
    : ${zfs_pool_usage_threshold:=80}
    
    [ "$zfs_pool_usage_enable" = "YES" ] || exit 0
    
    echo ""
    echo "Checking ZFS pool usage (threshold: ${zfs_pool_usage_threshold}%)..."
    
    zpool list -H -o name,capacity | while read -r pool usage; do
        percent=${usage%%%}  # 移除 '%' 符号
        if [ "${percent}" -ge "${zfs_pool_usage_threshold}" ]; then
            echo "WARNING: ZFS pool '${pool}' is ${percent}% full!"
        else
            echo "OK: ZFS pool '${pool}' is below capacity threshold (${percent}%)."
        fi
    done
    
    exit 0
    chmod +x /etc/periodic/daily/405.zfs_pool_usage
    daily_show_success="YES"
    zfs_pool_usage_enable="YES"
    zfs_pool_usage_threshold="75"
    periodic daily
    Checking ZFS pool usage (threshold: 75%)...
    OK: ZFS pool 'data' is below capacity threshold (6%).
    OK: ZFS pool 'zroot' is below capacity threshold (27%).
    zfs get compression zroot/var/log
    zfs set compression=zstd zroot/var/log
    # Rotate log files every hour, if necessary.
    0       *       *       *       *       root    newsyslog
    # Rotate log files every hour, if necessary.
    0       *       *       *       *       root    newsyslog -t DEFAULT
    service newsyslog restart
    service syslogd restart
    zfs get refcompressratio zroot/var/log
    NAME           PROPERTY          VALUE     SOURCE
    zroot/var/log  refcompressratio  40.60x    -
    zfs get used,logicalreferenced zroot/var/log
    NAME           PROPERTY           VALUE   SOURCE
    zroot/var/log  used               2.28M   -
    zroot/var/log  logicalreferenced  91.0M   -
    FreeBSD 许可证
    
    版权所有(年份)(版权所有者)
    
    在包括但不限于修改的源代码和二进制形式的重新分发和使用是允许的,前提是满足以下条件:
    
    1. 源代码的再分发必须保留上述版权声明、条件列表和以下免责声明。
    
    2. 二进制形式的再分发必须在文档和/或其他提供的材料中复制上述版权声明、条件列表和以下免责声明。
    
    本软件按原样提供,版权所有者和贡献者对于任何直接、间接、偶然、特殊、示例或后果性损害(包括但不限于替代商品或服务的获取、使用数据或利润损失、业务中断)不负任何责任,无论是在合同、严格责任或侵权行为(包括疏忽或其他)的任何理论下,即使事先已被告知可能发生此类损害。
    为什么选择 FreeBSD 而不是某个 Linux 发行版?
  • 你能说服我朋友用 FreeBSD 吗?

  • FreeBSD 能跑容器吗?

  • BSD Devroom
    。

    我记得的第一批设备/电脑/游戏机(不是同时拥有的)是 Atari 2600 和 Pegasus 游戏机,后者是 Nintendo NES 的硬件克隆版。

    那时我甚至不知道它是 Atari 2600,我只称它为 Video Computer System …… 当时我也完全不懂英语。花了大约二十年,我才偶然发现这个 Video Computer System 实际上是 Atari 2600 :🙂:

    这台设备只用来玩电子游戏。

    后来我拥有了 AMIGA 600 电脑(或者说是父母为我买的),这次它不仅可以玩游戏,还能干其他事。AMIGA 对我影响最大,因为这是我第一次学习 Amiga Workbench 操作系统的书籍,并在 Amiga Shell 终端学习命令。我特别喜欢桌面上 Ram Disk 图标/目录的概念,它能让我透明地将任何东西放入系统内存。如今的桌面系统中仍然没有这个概念,我仍然记得看到 Amiga Deathbed Vigil 电影时的那份落寞。

    1998 年底,我拥有了第一台 PC,当然预装了 Windows,它既是游戏机,也是日常工具。有一次我深入研究 Windows 注册表(它的概念和实现让我感到厌恶)以及由 CMD.EXE 提供的有限命令行界面。我记得,这台机器的核心并不是 CPU 和主板,而是图形加速器——传奇的 3Dfx Voodoo 显卡。这个公司(3Dfx)的态度和理念,也像 AMIGA 一样,对我影响深远。

    因此,我现在的笔记本外观也是这种风格 :🙂:

    有些游戏甚至以支持 3Dfx Glide 驱动为唯一特点发行特别版,比如 Need for Speed II: Special Edition(极品飞车 II:特殊版)。

    从 AMIGA 迁移到 PC 后,它再也没有“感觉对了”。游戏很酷,但 Windows 系统烂完了。随着时间推移,不同版本的 Windows 和硬件改进不断出现。当时 Windows XP 已经很沉重,更别提硬件要求更高的 Windows 2000。至于大家对 Windows ME 的所有抱怨,我并不完全理解。它的崩溃频率与 Windows 98 或 Windows 98 Second Edition 相当,也许只是我的硬件不同 :🙂:

    那段时间,我没有保存任何“自己的”截图,因为在用 Partition Magic 移动/调整分区以从较空的 C: 盘获取更多空间时,我整个 40 GB(当时很大)数据盘都丢了。那天,我深刻领悟到:“有些人会备份数据,有些人将会备份数据”。自那以后,我再也没有丢过数据,因为我拥有多份备份,但就像 Netheril 帝国(《龙与地下城》中已毁灭的古老帝国)的覆灭一样,丢失的数据永远消失了。

    我一直在尝试各种替代方案,这也促使我在 2003 年尝试 Linux。在阅读了各种发行版的理念后,我决定用 Slackware Linux 跑 KDE 3。当时我的朋友使用 Aurox Linux(波兰少数几个 Linux 发行版之一),并建议我也这样做——特别是在解决潜在问题时,因为他已经熟悉这个系统,而且他最近刚放弃了 Windows。但 Slackware 听起来更合适,所以我选择了这条路径。一开始,我在用 Windows XP 和 Slackware Linux 双系统,因为我在 Windows 世界里一切都运作正常,而在 Linux 世界里常常感到无助,所以如果需要玩游戏或解决 Linux 问题,我就会重启回 Windows。我还记得当时对双剪贴板(PRIMARY 和 SECONDARY)的概念感到非常陌生。我很惊讶,为什么 Linux 这个“更优秀”的系统(至少宣传如此)需要一个系统托盘程序来管理剪贴板。在 Windows 上很直观,[CTRL]+[C] 复制,[CTRL]+[V] 粘贴就完成了,但在 Linux(现在我知道这是 X11 的特性)中,有两个剪贴板,需要由 KDE 3 的这个小托盘程序同步。我也难以接受,如果关闭了进行复制操作的应用程序,最后一次 [CTRL]+[C] 的内容就会“丢失”。我在 Slackware 上稍微安定了一段时间,但不久就不适应了。我真的不喜欢手动管理软件包依赖,而且 KDE 3 非常丑陋,尽管尝试了各种可能的方案,我仍无法将它调成好看的界面。

    在使用 Slackware 半年以后,我再次查看 Linux 发行版,并决定尝试 Gentoo Linux。我完全赞同下面的形象,它形象地展示了首次安装 Gentoo Linux 的体验 :🙂:

    当然,我选择了最硬核的版本——自建 Stage 1(编译器和工具链),当时这是个坏主意,因为在缓慢的单核机器上编译几乎耗时无穷……但经过若干小时,我终于安装好了 Gentoo。接下来我必须决定使用哪个桌面环境。当时我读到很多关于 Fluxbox 的好评,所以我尝试了它。这是一次非常奇特的体验(从零在 GUI 中创建一切),但也很愉快。这让我回想起 AMIGA 的时光……但 Linux 经常让事情变得复杂。越深入 Gentoo Linux,我越发现很多 Gentoo 特性都是基于 FreeBSD 的解决方案。Gentoo Portage 就是 FreeBSD Ports 的仿制品。而那个“中央”的 ·/etc/rc.conf· 系统配置文件概念也是从 FreeBSD 借鉴而来。所以我开始收集关于 FreeBSD 的信息。那个时候的 FreeBSD 网站或 FreeBSD Ports 网站(至今)显得有些过时,但这并没有让我气馁。

    大约在 2005 年,我在电脑上安装了 FreeBSD 5.4。起步维艰,就像之前使用 Gentoo 时一样,但同样像 Gentoo,FreeBSD 项目提供了大量优秀的文档。Gentoo 的文档主要集中在各种 Gentoo Wiki 网站上,而 FreeBSD 项目提供了“官方”文档,如 手册 和 FAQ。我还记得在现已不存在的 BSDForums.org 网站上提的第一个问题——例如其中一个最早的问题是如何在普通终端中滚动输出。现在我知道需要按 Scroll Lock 键,但对我来说那完全是新鲜事物。

    BSDForums.org 当年的样子。

    这是我从那个时期获得的最早截图,Gentoo 的安装界面看起来非常相似。

    为什么选择 FreeBSD 而不是 OpenBSD 或 NetBSD?可能是因为 Gentoo 的许多概念都是基于 FreeBSD 的解决方案,这也引导我选择了 FreeBSD 而非其他 BSD 操作系统。目前我仍在使用 FreeBSD,但我一直关注 OpenBSD、HardenedBSD 和 DragonFly BSD 的解决方案及改进。

    由于从 Linux 迁移到 FreeBSD 的路径非常简单——/home 下的所有配置文件都可以直接复制——迁移过程非常快速且容易。我再次使用了在 Gentoo 上的 Fluxbox 配置。现在在 FreeBSD 上,它甚至更让我回想起 AMIGA 的那些日子。一切都是经过深思熟虑的,每个功能都有其位置和意义。文档完备,而 FreeBSD 社区 更是无与伦比。

    我甚至决定升级硬件,尝试一些更“特别”的配置。我入手了服务器主板 Gigabyte-GA-7DPXDW ,搭载了双 CPU 插槽——而由于 Athlon XP(桌面)处理器可以很容易地改装为 Athlon MP(服务器)处理器,我也获得了第二颗 CPU,以及 1 GB ECC 内存。

    这套双 CPU 配置在当时不常见,但对我来说非常适合。我从 nvidia 的闭源驱动换成了开源的 nv 驱动,因为 nvidia 驱动会每隔几天就打断我的系统运行时间 :🙂:

    我在这台桌面机器上累计达到了 30 天的正常运行时间,对于没有应急 UPS 的系统来说还不错 :🙂:

    这是我最后一次在 FreeBSD 上(至少在我的机器上)使用 ECC 内存,当时 FreeBSD 上还没有 ZFS:🙂: 光阴荏苒,我开始感受到对更快硬件的需求。同时,我也对 Intel 显卡产生了兴趣,于是换上了新主板和当时最快的 Intel X3000 GMA 显卡——虽然听起来很愚蠢——使用 Asus P5B-V……这是个烂的主意,因为 FreeBSD 的图形栈尚不支持这款 Intel 显卡。最初我使用软件 VESA 驱动,但问题不在于驱动性能(我当时还有四核 Intel Q6600 CPU),而是在屏幕分辨率上。当时我有 1280 x 1024 的显示器,但只能使用 1024 x 768,体验极差。我决定暂时尝试其他方案,等待 FreeBSD 对 Intel X3000 的支持到来。我需要尽快解决,因为当时我还需要撰写我的 硕士论文。

    那是 2007 年中期。我想尝试 Linux 发行版光谱的另一端——Ubuntu。我不能再更“桌面化”了 :🙂: 它当然顺利安装了 GNOME 2 桌面环境,但不幸的是 pulseaudio 已经存在。当时我喜欢长时间开机(不花电费),有几件事让我非常烦恼。例如前面提到的 pulseaudio——使用一两天后声音就会冻结(即使我没有播放音乐或视频),且一直保持冻结状态。可以重启 pulseaudio 或重新加载 ALSA 模块,但状态仍然保持 SUSFU(Situation Unchanged Still Fucked Up, 情况没有改变还是一团糟),必须重启才行。由于我要写 硕士论文,没时间重装其他系统,因为 pulseaudio 在其他 Linux 发行版上可能同样会出问题,而 FreeBSD 还不支持 Intel X3000 GMA。总体来说 GNOME 2 体验还行,但我非常怀念所有自定义设置、快捷键以及自定义行为。我在 Ubuntu 上忍受了两个月,直到完成了我的关于 操作系统虚拟化 的 硕士论文(PDF 为波兰语,可用翻译工具阅读) :🙂:

    那时的 Ubuntu 长这样。

    我也曾短暂遨游过 Mac 世界,当时有机会使用了一年的 MacBook Pro 和 Mac OS X Leopard。这让我真正感受了 Mac 的生态系统和硬件(以及理念),因此不会像很多反苹果的人那样重复陈词滥调。但在工作中切回 FreeBSD 系统后,感觉更自然。我在 Mac 上大量使用 Terminal.app,但 FreeBSD 的 xterm(1) 更符合我的习惯。

    有趣的是,多年来我设计了 Mac 风格的 Fluxbox 主题,直到真正使用 Mac 时,我仍然喜欢 Leopard 时代的 Mac OS X 外观。

    我还曾尝试过 Solaris(后来是 OpenSolaris)。必须承认,当时 Solaris 的所谓 Java Desktop 基于 GNOME 2,外观确实很棒,仅次于 Mac OS X。

    我非常喜欢 Solaris 的概念和解决方案,例如 Zones、ZFS、Crossbow、Comstar 或 IPS(当时 FreeBSD 还没有 PNGng)。但桌面软件始终是问题所在。虽然我在 FreeBSD Ports 中几乎找到了和 Linux 一样多的应用,但在 Solaris 世界中总是缺少一些应用。

    这段 Solaris 体验也影响了我的灵感,所以我的 Fluxbox 主题也改成了 Solaris 风格 :🙂:

    在 Ubuntu 体验失败之后,我换了另一块主板,因为 FreeBSD 当时仍不支持 Intel GMA X3000,再次回到 FreeBSD 世界。摆脱 pulseaudio 的困扰后,我终于松了口气。同时,我看到很多关于 Openbox 的好评,决定尝试它来代替 Fluxbox。刚开始编辑 XML 配置文件时感觉很奇怪,但熟悉后将 rc.xml 和 menu.xml 文件整理好就不成问题了。从那以后,我在不同机器上使用 FreeBSD,包括物理服务器、虚拟机和笔记本。我学到,在 FreeBSD 生态中,硬件支持是最重要的因素。

    我至今仍在使用 Openbox 和 FreeBSD,我的桌面如今如下所示:

    经过 15 年使用各种 Windows、UNIX(macOS/AIX/HP-UX/Solaris/OpenSolaris/Illumos/FreeBSD/OpenBSD/NetBSD)及类 UNIX(Linux)系统,我始终得出结论:FreeBSD 是“出错最少”的系统。而且每次发布更新,它表现得越来越好。某一天我会详细写为什么 FreeBSD 是如此出色的操作系统……如果我还没写的话 :🙂:

    更新 1

    正如 Roman Zolotarev 所做,他将我的故事添加到他的 Tell Your BSD Story 页面。该页面原本在 https://www.bsdjobs.com/people/,但 Roman 后来似乎放弃了 bsdjobs.com 域名。

    感谢 Roman!

    你可以查看 Slawomir Wojciech Wojtczak (vermaden) 的 FreeBSD 页面。

    My FreeBSD Story
    Roman Zolotarev
    https://www.bsdjobs.com/people/hi.html
    cybersynapse.ro
    一点背景

    来自 其官网:

    Galene(或 Galène)是一款视频会议服务器(“SFU”),易于部署,对服务器资源需求非常适中。它最初设计用于讲座、会议和学生辅导,但后来发现同样适用于传统会议。Galene 已在两所主要大学(巴黎大学和索邦大学)投入生产,用于讲座、实验课、研讨会和员工会议。

    要求

    • 较新的 FreeBSD 系统(本文写作时为版本 14.3)

    • 可以不用 ZFS,但强烈建议使用

    FreeBSD 基础设置

    首先,确保你已经安装了最新的 FreeBSD 系统更新。以 root 身份运行以下命令(由 # 表示):

    接着,将 pkg 仓库更新为 latest 分支。编辑 /etc/pkg/Freebsd.conf,把字符串 quarterly 改成 latest。然后运行以下命令更新 pkg 数据库:

    安装 Galene

    在从包安装 Galene 之前,我们可以在 /var/db/galene 下添加几个 ZFS 数据集来保存视频会议数据。这一步是可选的,Galene 在 UFS2 上同样能正常工作。这里使用 ZFS 是因为它提供了额外的特性,在生产环境中可能会很有用。

    假设我们的池叫做 videostar。我们在 /var/db 下为 Galene 创建数据集。

    为 Galene 创建 ZFS 数据集

    通过这些命令,我们在 galene 子目录下创建了一个独立数据集,并在其下创建了三个数据集:recordings、data 和 groups。我们稍后将填充这些内容。

    包安装

    FreeBSD 的软件包非常易用,并包含了预构建好的 Galene 包。我们接下来安装它:

    安装过程中,/var/db/galene 下的目录会被创建。由于我们提前用 ZFS 数据集创建了它们,管理起来就更灵活了。例如,我们可以为 recordings 数据集设置配额。对于长时间的视频会议,录制文件会变得非常大。设置配额能防止 Galene 占满池中剩余的磁盘空间。

    Galene 配置文件

    在首次启动 Galene 前,我们需要定义有哪些 group(群组)。这些群组就是视频会议房间,允许多个用户加入同一个房间,或在不同房间举行会议而互不干扰。同时,也需要定义用户的权限和密码。

    一个在 /var/db/galene/groups 下的基础示例文件如下:

    这里我们定义了一个名为 bob 的用户、一个密码以及房间中的操作员权限。房间本身叫做 videostar。

    添加有效的 SSL 证书

    虽然我们没有将其加入 Ansible playbook,但添加一份来自 letsencrypt.org 的有效 SSL 证书相对简单。简要步骤如下:

    Galene 启动配置

    Galene 包在安装二进制文件的同时也安装了启动脚本,位于 /usr/local/etc/rc.d。要让 Galene 随系统启动,在 /etc/rc.conf 中加入以下内容:

    之后启动服务:

    检查服务是否在运行:

    若显示 Galene 正在运行并附带进程 ID(PID),说明启动成功。如果没有,请重新检查上面的步骤,并查看 /var/log/messages 获取更多提示。

    测试 Galene

    我们可以在 sockstat -l(监听套接字列表)的输出中找到正在运行的 Galene 进程 PID:

    在同一行里,可以看到 Galene 默认监听的端口 8443。假设我们的主机名是 videostar.example,在浏览器地址栏中输入:

    此时会打开一个网页,询问你要加入哪个 group。输入 videostar(我们在配置文件中定义的那个),点击 Join 按钮。在下一页输入用户名和密码,选择允许使用的设备(摄像头、麦克风),然后点击 Connect 按钮。如果一切顺利,你就进入了拥有完整权限的视频会议房间。之后只需在 videostar.json 文件中添加更多用户并重启 galene 进程,就能把这个网址分享给他人。祝贺你,视频会议愉快!

    How To Install and Configure the Galene Video Meeting Server
    我们从一些数字说起,或者至少,从谷歌的视角看一些数字。开始输入一个搜索词时,谷歌的自动补全建议就会浮现出一幅图景。你看第七个建议是什么?所以说,谷歌已经开始在你脑海中植入想法了。然而如果我们深入挖掘……

    这条线正在上升

    ……很清楚地可以看到,这是稳定的上升趋势。我知道你在想什么:“统计数字不过是乐观的真相!”确实,通过谷歌趋势几乎可以构造出任何故事。我之所以选择这个时间范围,是因为当我查看更广的时间线时,谷歌提示他们更改了算法,意味着结果并不完全可比。在上一次算法更改之后,这大概是我能找到的最合适的时间段了。

    当然,单独看这一张图表意义不大,那我们来做个对比……

    完全平坦的一张图

    在相同时间段内,“Linux”的搜索量显示出的是平稳趋势。虽然绝对数字可能大不一样,但趋势很明显:Linux 是一条平线,而 FreeBSD 呈缓慢上升趋势。

    究竟发生了什么?

    我有一个假设,能解释为什么人们 认为 FreeBSD 正在衰亡,以及引言中提到的那个令人吃惊的结论。

    最近,万能的 YouTube 算法给我推送了一段关于 Cal Newport 的简短访谈。我读过他的一本书,也听过其他访谈,所以自然引起了我的兴趣。在这段视频中,他谈到了他所谓的“伪生产力”——基本上是用工厂式的生产力标准来衡量办公室或知识工作。这导致了大量无意义的忙碌,人们试图看起来很忙碌,却没有做真正有意义的工作。我认为 FreeBSD 的问题正好是这种情况的相反方向。因为它不被频繁提及,人们就认为它在衰亡。这是一个典型的 可得性启发 的例子。

    那么一个显而易见的问题是,为什么人们不怎么谈论 FreeBSD 呢?

    令人吃惊的结论

    可得性启发是一种迷人的心理捷径。它解释了为什么一些产品名称会变成动词和家喻户晓的词汇。比如“谷歌”(搜索)、“Hoover”(吸尘器)、“Zoom”(视频会议)。这些词达到了某个临界点,人们不再需要多想,直接“谷歌”或者“zoom”。

    如今,构建互联网服务时很少会考虑底层系统。随着容器和云平台的普及,开发已经远离了硬件层面。操作系统不再是人们关注的焦点,因此大家默认使用熟悉的东西,而当他们想到操作系统时,通常是 Linux。

    然而 FreeBSD 就在那里,默默支撑着互联网的大量服务,一点声响也没有。使用它的公司呢?他们也不怎么宣传。为什么?因为他们没必要。让我恍然大悟的是,FreeBSD 既是我们所有人的礼物,同时也是它自己的阿喀琉斯之踵,那就是它的 许可证。

    不同于 GPL 许可证要求你必须共享衍生作品,BSD 许可证并没有这种要求。你可以拿 FreeBSD 代码,进行开发,然后完全不用回馈任何东西。这使得 FreeBSD 成为构建产品的绝佳基础——但同时也意味着公司几乎没有理由去贡献回馈。

    来聊聊吧

    由于厂商相信 FreeBSD 正在衰亡这一错误观念,FreeBSD 的硬件支持有时比 Linux 更加棘手。但我们只需看看最近在 Wi-Fi 支持 方面取得的惊人成果,就能明白采用 Linux 驱动 是一项切实可行的解决方案。

    因此,我们想向使用 FreeBSD 的公司发出呼吁。请跟我们分享你们的使用场景。如果你们在硬件支持方面遇到困难,也请告诉我们。哪怕你们的法务团队不希望公开谈论这些使用情况,我们仍然 希望听到你们的声音。这些对话可以只在我们之间进行 😀,但至少我们能够了解 FreeBSD 的使用案例和存在的问题。我们,FreeBSD 基金会,可以成为工业界与软件和硬件厂商之间的纽带。

    与此同时,请 持续关注本博客 和 我们的 YouTube 频道。我们即将推出一些精彩内容,介绍基于 FreeBSD 构建的解决方案,并展示适合日常使用的现代笔记本电脑。

    The Report of My Death Was an Exaggeration
    别相信搜索引擎!
    译者:Canvis-Me & ChatGPT

    image

    Linux 并不是唯一的开源操作系统(OS)。还有许多类 Unix 的开源 BSD 操作系统,其中就包括仍在积极开发中的 FreeBSD。

    FreeBSD 项目于 1993 年首次发布,是最早的开源操作系统项目之一,也是加州大学伯克利分校最初的开源 BSD 工作的直接继承者。本周,FreeBSD 14 正式发布,这是自 2021 年以来该开源操作系统的第一个主版本号更新。这个在 14 分支上的首个稳定版本为这个开源操作系统带来了重要的更新和新功能。

    “FreeBSD 14 代表了一些新功能和对各个子系统的大量更新,以提高性能、稳定性和安全性,”FreeBSD 基金会技术高级总监 Ed Maste 与 SDxCentral 说道。

    在 FreeBSD 14 中,ZFS 文件系统获得了大幅提升

    FreeBSD 14 的新特性之一是将 ZFS 文件系统更新为 OpenZFS 2.2 版本。

    ZFS 起源于 Oracle(之前是 Sun Microsystems)的 Solaris UNIX 操作系统,长期以来一直承诺支持庞大的存储容量。Maste 指出,OpenZFS 2.2 包括诸如块克隆之类的增强功能,为需要大量复制的工作负载提供了巨大的性能提升。除了对 OpenZFS 本身的改进,还添加和更新了新的工具,以提高 ZFS 在 FreeBSD 中的集成度。

    此外,还进行了更新,使 ZFS 在虚拟化环境中运行得更好,FreeBSD 还将 ZFS 支持添加到 makefs 镜像创建工具中。

    “这使得 FreeBSD 发布工程团队可以开始为云提供商构建基于 ZFS 的根镜像,”Maste 说道。

    FreeBSD 14 增强了安全性和可扩展性

    新版本还包括了许多安全改进。

    Maste 指出,FreeBSD 的 Capsicum 沙盒框架已应用于基本系统中的其他工具。还更新了基本系统中的关键安全工具,包括将 OpenSSL 升级到 3.0.12,将 OpenSSH 升级到版本 9.5p1。

    性能和可扩展性也在提高,同时增强了对硬件的支持。

    “还有一些支持当代硬件的变化,例如将支持的 CPU 数量增加到 1024,”Maste 说。

    他补充说,还有一大堆可用性和“外观和完成”改进,如缩短引导时间,解决与某些 UEFI(统一可扩展固件接口)固件实现不兼容性,改进 NVMe 设备错误处理等等。

    为什么 FreeBSD 仍然重要——尤其是对于网络而言

    尽管 Linux 作为开源操作系统可能在许多企业中更广为人知,但 FreeBSD 也绝对不陌生,尤其是在网络系统方面。

    “网络仍然是 FreeBSD 的强项,包括 Juniper 在内的许多公司都依赖于 FreeBSD 的网络功能,并贡献代码来改进 FreeBSD 的网络功能,”Maste 说。 “其他在网络安全和性能前沿的公司,如 Netflix,Nvidia Mellanox Metify,Netgate,Chelsio 和 Nginx(F5),也使用并为 FreeBSD 做出贡献。”

    Juniper 的 Junos 网络操作系统基于 FreeBSD。Maste 指出,商业友好的 BSD 开源许可证使其对于那些希望在其 OS 与专有软件组合成产品的过程中没有任何负担的公司而言,变得很有吸引力。

    “因此,我们看到很多 FreeBSD 作为专门用途的安全、网络和工业控制设备的基础;SaaS 解决方案;以及平台,”他说。

    Maste 还指出,FreeBSD 支持几个领先的支付处理网络,包括 DeepStack(现为加利福尼亚银行的一部分),Modirum 等。企业级存储是 FreeBSD 受欢迎的另一个市场,有助于支持 Avere Systems(现为 Microsoft 的一部分),EMC Isilon 和 NetApp 的解决方案。

    展望未来,Maste 表示,FreeBSD 核心团队正在开始规划过程,以确定社区的发展重点。FreeBSD 基金会是一个独立的实体,但这些重点将有助于指导基金会的软件开发工作。

    “基金会未来一两年的一个重点是改善 FreeBSD 的终端用户开箱即用的体验,”Maste 说。 “如果你是一个想要了解或探索系统编程的人,我们希望 FreeBSD 能够(为你)提供一个出色的起点。”

    https://www.sdxcentral.com/articles/analysis/freebsd-keeps-unix-like-os-alive-boosts-security-and-performance-with-v14/2023/11/
    主要变化
    • 可预测且更频繁的发布计划: 预计每季度都会发布一个新的点(.)版本。这意味着更新更频繁,改进持续不断。

    • 缩短的支持周期: 从 FreeBSD 15.x 开始,STABLE 分支将会在 .0 版本发布后有四年支持,而不是以前的五年。

    为什么 FreeBSD 项目会改变发布和支持周期?

    这些调整基于对我们发布流程的全面审查。目标是提高效率、改善用户体验,并更好地与 FreeBSD 社区不断变化的需求对接。我们计划通过以下方式实现这一目标:

    • 简化发布流程: 更集中的发布流程意味着更新和 bug 修复的交付更快,从而加速问题解决并提供更稳定的系统。

    • 定期更新: 更频繁的发布确保你可以获得最新的功能、性能提升和安全补丁。

    • 改进的规划: 可预测的发布计划帮助你更有效地规划系统升级和维护。

    • 平衡的支持: 缩短至四年的支持周期在维护稳定性与应对新兴安全威胁之间提供了实际的平衡。

    新发布计划: 为了帮助你更好地规划系统管理,以下是新发布计划的详细内容:

    • 季度次要版本发布: 新的次要版本将在大约 每三个月发布一次。 (注意:尽管每三个月会发布一次次要版本,但所有特定的主要版本每六到九个月才会有新的次要版本发布。)

    • 每两年发布一次主要版本: 主要的 .0 版本将 每两年发布一次,带来重要的更新和新特性。

    示例:

    • 2024 年: 3 月:13.3 (13.x 有五年支持周期,2026 年 4 月结束,13.5 是最后一个版本)

      • 6 月:14.1 (14.x 有五年支持周期,2028 年 11 月结束,14.6 是最后一个版本)

      • 9 月:13.4

      • 12 月:14.2

    • 2025 年: 3 月:13.5

      • 6 月:14.3

      • 12 月:15.0(15.x 有四年支持周期,2029 年 12 月结束,15.6 是最后一个版本)

    • 2026 年: 3 月:14.4

      • 6 月:15.1

      • 9 月:14.5

      • 12 月:15.2

    新的 FreeBSD 发布计划和支持周期标志着朝着提供更安全、更稳定、更易管理的系统迈出了重要一步。我们致力于提供最佳的 FreeBSD 使用体验,而这些变化正是我们承诺的体现。

    欲了解更多信息并保持更新,请访问 FreeBSD 项目 网站或 订阅邮件列表。

    Navigating FreeBSD’s New Quarterly and Biennial Release Schedule
    FreeBSD 发布计划和支持周期的变化
    FreeBSD 邮件列表
    FreeBSD-Questions 邮件列表
    FreeBSD-Current 邮件列表
    FreeBSD Discord
    IRC 频道
    官方 FreeBSD 论坛
    FreeBSD subreddit
    FreeBSD 用户组
    FreeBSD/Unix 活动

    简单而轻松的 FreeBSD Jail

    • 原文:FreeBSD Jails are Simple and Easy

    • 2025 年 8 月 25 日

    • 作者:FreeBSD 基金会

    在 FreeBSD 上运行常见服务很简单。但有时你想在同一个操作系统实例上运行多个服务,并且让每个服务都彼此安全地“隔离”。如果不提供互联网连接,web 服务就没多大意义,但这同时也可能带来了安全漏洞。很显然,我们不希望这样。如果某个服务有可能因为安全漏洞而被攻破,那么尽可能减少系统的暴露会更好,不是吗?

    这就是 jail 的用武之地。Jail 是容器化的轻量化答案,早在 Docker 变得流行之前,很久以前 它就已存在。

    设置 Jail

    同科技行业中的所有事情一样,至少有一只手的方法能实现相同的结果。在 FreeBSD 上有许多工具可以用来创建和管理 jail,但我更倾向于 保持简单,所以选择使用默认安装系统中自带的工具。

    手册中有 ,我基本遵循它,仅做了一些细微的调整。

    我从 中创建的基础虚拟机开始,因为接下来的设置使用 ZFS。

    这就是我设置 jail 的过程。如果你有五分钟,我们一起来看看。

    配置宿主机

    启用 jail:

    然后创建一些基本的 zfs 文件系统:

    手册中有其他挂载方式,你也可以选择使用。我更喜欢稍微简单一些的“base”和模板文件系统,然后通过快照来生成新的 jail。我们稍后会用到。

    创建模板 jail

    下载 FreeBSD 用户态文件用作我们的模板:

    解压文件,修补模板,然后创建快照:

    现在我们有了“模板”jail,可以用来创建新的 jail。我不会运行这个 jail,而且通常会在模板里添加常用包,这样每个后续克隆都会包含它们。把你喜欢的工具都放进去 🙂 值得注意的是:如果你打算用 Ansible 来管理 jail 中的包,你也需要在里面安装 pkg。之前为了保持简单,我没有这么做,而是直接在宿主机上用命令 pkg -j JAILNAME install BLAH 来安装。我想这算是个哲学问题——你是把 jail 看作是扩展的 chroot,还是微型的虚拟机?

    差不多快完成了。我们需要 /etc/jail.conf ——我选择使用统一的“全局”文件,其中的选项适用于所有 jail,然后在 /etc/jail.conf.d/ 中为每个 jail 单独创建配置文件:

    /etc/jail.conf 模板:

    创建新的 jail

    每当我需要新的 jail 时,只需 zfs 克隆模板,在 /etc/jail.conf.d/ 中创建一个配置文件,并在 /etc/rc.conf 的 jail_list 中添加新 jail 名称。我写了个简单的 shell 脚本来实现这一点:

    扩展 Jail

    这只是有关关于如何快速启动 jail 的简单介绍。手册文档里有更多细节,包括如何 (比如限制内存和 CPU)。如果你想进一步扩展,运行更多的 jail,你可能需要看看手册中列出的一些工具,或者参考 。

    正如我们博客文章中常做的那样,我们把本文用到的一些资源放在了 ,并制作了视频:

    FreeBSD OCI 容器简介

    • 原文 An introduction to OCI Containers on FreeBSD

    • 发布日期:2025 年 10 月 31 日

    《在 FreeBSD 上运行 Linux 容器!》https://www.youtube.com/watch?v=HV-wUUzRCMo

    我想你在过去十年里大概没有与世隔绝,所以我就不解释什么是 容器 了。不过我会提到什么是开放容器倡议(Open Container Initiative,简称 OCI),因为 FreeBSD 刚刚成为了它的一部分。引用 他们自己网站 上的话:

    “开放容器倡议(OCI)是一款轻量级、开放治理结构,其明确目的是围绕容器格式和运行时创建开放的行业标准。”

    很好。为了在这个框架内工作,我们需要一款工具。登场的是 Podman:

    “Podman 是一款功能齐全的容器引擎,是一款简单的无守护进程工具。Podman 提供了与 Docker CLI 可比的命令行,使从其他容器引擎的迁移变得容易,并可管理 pod、容器和镜像。”

    规则已经设定。让我们看看 Podman 所谓的“简单”,是否真的名副其实。

    安装与设置

    我这里从全新的 FreeBSD 15.0-BETA3 安装开始,但我也在 CURRENT、STABLE、14.3-RELEASE 上进行了测试,结果完全一致。让我们安装所需包:

    Podman 默认会把容器存储在 /var/db/containers,所以你可能想为它创建专用的 ZFS 文件系统:

    如果我们希望访问运行在容器中的任何服务,就需要使用 pf 防火墙。podman 有个示例配置文件,让事情变得简单:

    别忘了在启用并启动 pf 服务之前,更新复制文件中的接口变量。 当然,如果你已经在运行 pf,并且已经有配置文件,请不要直接覆盖。只需从示例文件中取出相关部分,添加到现有配置中即可。

    如果我们想使用任何基于 Linux 的容器,还需要启用 Linux 服务:

    准备就绪。我们来试试 FreeBSD 容器(这里我们是普通用户,所以需要使用权限提升,因为目前 podman 需要 root——我个人偏好使用 doas;它小巧而简单):

    非常简单!我们再测试一个 Linux 容器:

    同样非常简单。

    你可以在 和 上找到 FreeBSD OCI 镜像。不过我们可以想象,许多人更希望使用 Linux 镜像。

    测试一些有用的东西

    我很早前就听说过 Caddy,当时是在与一家基于 FreeBSD 的公司讨论大型多人在线游戏服务时(那是另一个有趣的故事,以后再说)。简单了解后我发现,它可能是一个在容器中安全地提供网站服务的极其简单的方法。于是我用 Hugo 生成的静态网站进行了测试——仅仅是提供 public 文件夹。

    哇,太简单了!

    我能得到什么?

    除了让现有的 FreeBSD 用户能使用容器之外,Podman 还将把一大批新用户带到 FreeBSD 世界。我们已经看到,越来越多的新用户访问 和 ,希望在 FreeBSD 以简洁和可靠著称的基础上构建他们的数字世界。ZFS 万岁 💪

    因此,我决定尝试一个有点奇特的挑战。很多年前,我在 Docker Hub 上发布过一个容器:以 CentOS 为基础的 Python Pandas。那我能否在我崭新的 OCI FreeBSD 服务器上运行它?

    可以!太棒了!这意味着可以将旧的工作负载迁移到新平台上。

    快速又简单

    就是这样。在 FreeBSD 上启动并运行容器既简单又快捷。同时,它也非常容易使用旧的容器——为将底层平台迁移到一个精心设计、坚如磐石的操作系统提供了路径。

    FreeBSD 手册很快将更新,加入 OCI 容器的正式文档,但与此同时,你可以查看核心成员 Dave Cottlehuber 的。

    我们会定期发布新的技术主题文章和视频,因此请务必订阅 ,并在你喜欢的 RSS 阅读器中关注。如果你希望通过电子邮件接收更新,也可以订阅。

    我们也希望这个内容系列是互动的——你希望我们讨论什么?有哪些 FreeBSD 问题可以帮你解决?请,告诉我们你的想法。

    聚集在开放领域工作的公益和慈善基金会

    • 译者:ykla/chatgpt

    • 旧金山 - 2023 年 7 月 12 日

    FreeBSD 基金会加入了 OSI 的开放政策联盟

    本基金会很高兴地宣布我们参与了开放政策联盟(Open Policy Alliance,简称 OPA),这是开放源代码倡议(Open Source Initiative,简称 OSI)的一个新项目。根据 OSI 的说法,“OPA 是一个旨在建立并支持一个由公益和慈善基金会中代表不足的声音组成的联盟。”

    开放源代码倡议(Open Source Initiative,简称 OSI)的公共政策团队已经推出了开放政策联盟(Open Policy Alliance,简称 OPA)计划,旨在建立并支持一个由公益和慈善基金会中代表不足的声音组成的联盟。OPA 是针对开源软件社区以及与之相关的开放内容、研究、人工智能和数据等领域中,对公共对话和利益相关方参与日益增长的需求而创建的。

    开源生态系统的资深人士 Deborah Bryant 将领导这个计划,她是 OSI 美国政策总监。Bryant 表示:“尽管开源活动是一项全球性、无国界的活动,但公共政策是在本地制定的。OPA 将专注于在美国进行教育工作,同时与全球志同道合的组织进行交流和信息共享。OPA 旨在赋予这些声音权力,使其能够积极参与教育和影响与开源软件、内容、研究和教育相关的美国公共政策决策。”

    由于全球范围内软件行业和相关开放领域的新法规出现,创建这样一个计划的需求如今更加紧迫。网络安全、人工智能的社会影响、数据和隐私是全球立法者关注的重要问题。与此同时,COVID-19 疫情推动了协作开发达到了前所未有的水平,并将开源软件、开放研究、开放内容和数据从边缘带到了主流舞台。在推进这些重要公共政策的同时,又不损害生态系统,需要理解开源生态系统的运作方式。确保那些历史上未被代表的利益相关方参与到这些讨论中变得非常重要。

    OPA 将专注于向公共政策制定者进行开源教育,以便在制定和审议新的政策概念时能够获得信息支持。缺乏对开放协作实践方式的了解会导致意想不到的后果。OPA 将解决这个问题,同时还将解决历史上少数群体贡献不足的问题。OPA 社区的兴趣领域将与 Digitable Public Goods Alliance 相互补充,后者是联合国儿童基金会(UNICEF){今年早些时候加入的](https://blog.opensource.org/osi-joins-digital-public-goods-alliance/) 一个多利益相关方倡议,旨在加速低收入和中等收入国家实现可持续发展目标。

    开放政策联盟创始组织的引述

    “开源已经改变了我们构建软件的方式,也改变了世界与技术互动的方式,带来了更好的结果,”Python 软件基金会的执行主任 Deb Nicholson 表示。“现在比以往任何时候都更需要决策者听取社区驱动的开源项目的意见,了解政策变化对开发者、用户和合作未来的影响。我们很高兴看到开放源代码倡议将慈善基金会聚集在一起,帮助提供这方面的专业知识。”

    “随着软件领域的监管环境不断演变,开源正面临危险,”开放基础设施基金会的总经理 Thierry Carrez 说道。“有谁比开源倡议更适合汇集和放大社区开源组织的声音,让每个人都能参与其中的讨论呢?作为开放基础设施基金会的附属组织,我们自豪地加入了 OPA,并加强了我们在这个及时倡议中的合作,因为这与我们在欧洲和亚洲的中心正在进行的工作相互补充。”

    “Open@RIT 很荣幸被邀请作为创始组织加入 OPA。在过去的 15 年里,我们开始教授学生和教职员工成为自由和开放源代码的贡献者,并将他们的学术和研究成果以开放的方式发布,”主任 Stephen Jacobs 表示。“在此期间,我们的大部分工作都集中在与 UNICEF、纽约州政府以及项目社区(如 P5JS 和 Csound)等组织合作,支持人道主义和公民项目。由于这些类型的社区的实践多样性,很难代表性地表达出它们的共同需求,特别是在基础设施和支持方面,以推动技术的发展并保持其稳定性。OPA 旨在填补这一需求。我们与 Deb Bryant 合作了十多年,很高兴听到她将把她对非营利和营利世界的广泛而深入的开源理解带给该组织。”

    “作为数字开放的倡导者,OpenForum Europe 认识到开放政策联盟为数字政策制定提供了更多声音和想法的平台的机会,”执行主任 Astor Nummelin Carlberg 表示。“我们愿意与全球志同道合的组织分享我们的知识并进行合作。这一努力不仅凸显了开源在我们互联的世界中的重要性,而且强调了明智和包容的政策制定的必要性。”

    “FreeBSD 基金会很高兴参与 OPA,并感谢 OSI 采取这一举措。开源已经无处不在,一家代码扫描公司发现 96% 的代码库都包含开源代码,”执行主任 Deb Goodkin 表示。“这意味着保护和维护开源对于确保我们的数字基础设施的安全性是必要的。然而,开源并不是统一的。很多开源项目是由企业支持的,但也有很多项目,比如 FreeBSD,是由社区驱动的。政策制定者了解这些模型的差异至关重要,以确保政策能够产生期望的结果。”

    鼓励对开源软件、内容、研究和教育感兴趣的公益和慈善基金会加入 OPA。通过共同努力,联盟成员将增强其集体影响力,为开源创造一个更具包容性和公平性的未来。开放政策联盟的创始组织包括以下非营利组织:

    • Apereo Foundation

    • FreeBSD Foundation

    • open@RIT

    • OpenInfra Foundation

    OSI 执行主任 Stefano Maffulli 将于 7 月 15 日在俄勒冈州波特兰举办的 上讨论全球政策环境以及 OPA 在其中的作用。有关 OPA 的更多信息,请访问 。

    原文地址:

    参与宣传:2023 年 5 月的 FreeBSD 开发者峰会和 BSDCan

    • 作者:Anne Dickison

    • 译者:ykla/chagpt

    2023 年 5 月的 FreeBSD 开发者峰会 和 BSDCan 标志着许多 FreeBSD 社区成员(包括我自己)重返线下活动。能够再次亲眼见到每个人是一次非常美妙的经历。线下活动,特别是像开发者峰会这样的活动,是 FreeBSD 社区不可或缺的一部分。面对面交流,讨论面临的问题,以及新版本的进展,这些都对推动项目的发展至关重要。从宣传的角度来看,这个活动是与使用 FreeBSD 的公司交流的机会,了解他们的使用情况,以及发现其中的问题和不足之处。这是更多了解人们选择 FreeBSD 的原因的机会,也是招募其他人帮助我们传播消息的机会。今年的 5 月份开发者峰会更加令人兴奋,因为我们能够庆祝 FreeBSD 的 30 周年。稍后会详细谈到这个。

    作为组织委员会的一员,自 1 月份以来,基金会团队成员一直在开会,为我们两年来的首次线下会议做准备。在整理众多活动筹划细节时,当我抵达会场并看到摆放着 T 恤和 FreeBSD 杂志的盒子时,我感到非常欣慰。如果没有 BSDCan 的 Dan Langille 提供的宝贵帮助,组织委员会就会遗漏一些重要事情。与 BSDCan 共同举办使得开发者峰会的举办变得更加可控。

    组织委员会成员和出色的主持人 John Baldwin 首先介绍了当天的日程安排,并向我们的赞助商表示感谢。 以金牌赞助商的身份与 FreeBSD 基金会一起参与,让 Colin Percival 继续设计开发者峰会 T 恤的背面,这是他长期以来的工作。iX Systems 和 以铜牌赞助商的身份赞助了峰会。当 FreeBSD 生态系统内的公司能够支持面向开发者的活动时,我们总是非常感激。

    活动开始时,FreeBSD 基金会进行了一次更新报告。尽管演讲不是我的强项,但我很高兴能与我的同事们一起分享我们在宣传方面今年到目前为止的工作情况。

    接下来的一天包括 FreeBSD 核心团队的更新报告,由 Mark Johnston 主持的代码阅读指导环节(根据参与者之后的讨论来看,非常受欢迎),以及专注于谷歌代码之夏和外部工具链的小组工作会议。

    在下一个休息时间,我们庆祝了 FreeBSD 项目的 30 周年,还有一个带有时间线的蛋糕!能够邀请到 FreeBSD 的原创成员 Kirk McKusick 和 Mike Karels 参与我们的庆祝活动是非常棒的。

    第一天以继续进行的“FreeBSD by the Fire”系列活动结束。Mike Karels 上台与大家分享了 FreeBSD 早期的故事并回答问题。

    接下来,基金会在大学宿舍楼下的“黑客休息室”举办了一个披萨派对。返回线下方式的最大好处之一就是可以与他人并肩坐在一起解决问题和学习新知识。黑客休息室还为基金会团队成员提供了另一个机会,可以与开发人员和企业代表坐下来了解他们的需求,以及我们可能需要填补的空白。

    开发者峰会的第二天以基金会向 Colin Percival 颁发奖项开始,以表彰他在组织 13.2 RELEASE 发布方面的努力。在 FreeBSD 发布工程师 Glen Barber 不在时,Colin 挺身而出,成功地保持了项目的进展。他的努力没有被忽视。

    随后,John 主持了一场关于 14.0 RELEASE 的总结会议,与大家共同确保新版本在今年秋季如期发布。因为创新从未停止,John 随后又组织了一场关于 15.0 RELEASE 计划的会议。峰会以工作小组会议结束,重点关注基金会的技术路线图、文档和工作流程/ GitHub PR。所有会议的幻灯片可以在 2023 年 5 月 FreeBSD 开发者峰会 上找到。感谢 Alan Jude 和 ScaleEngine、Patrick McEvoy 和 Andrew Fengler 的支持,会议还进行了实时直播,视频可以在 FreeBSD Project 的 上找到。

    BSDCan 的开始也意味着基金会的展台开放。我的同事 Drew Gurkowski、Deb Goodkin 和我早早就到了那里进行准备。在 BSDCan 的展台是我最喜欢的地方之一。这使得 Drew 和我有机会与社区交流,了解人们如何使用 FreeBSD,并找到推广项目的其他途径。今年的展台特别令人兴奋,因为我们能够展示新的 30 周年纪念品、时间线海报和 的印刷版。

    BSDCan 的最后一天,Drew 和我还邀请了一些人进行采访,作为我们庆祝 的一部分。Drew 就人们使用 FreeBSD 的原因和方式提出了很好的问题,甚至请教了 Kirk McKusick 关于 30 年后的 FreeBSD 的看法。你也可以在该项目的 上找到这些采访。

    从宣传的角度来看,FreeBSD 开发者峰会和 BSDCan 对基金会的营销工作至关重要。我们有机会向从事这项工作的人们学习。社区的意见帮助我们明确 FreeBSD 使用的好处,并帮助我们制定新的活动策略,评估在整体宣传规划中的工作情况。对于基金会团队来说,这是一个非常繁忙而充实的一周,我们不希望有其他的方式。感谢所有来访展台、参与采访、在峰会上发表演讲的人们,使我们在渥太华度过了一个成功的一周。我期待明年再见。


    原文地址:

    FreeBSD 基金会欢迎董事会新成员:John Baldwin

    • 原文:FreeBSD Foundation Welcomes New Board Member: John Baldwin

    • 2025 年 6 月 27 日

    长期参加 FreeBSD 社区的成员 John Baldwin 于 2025 年 6 月 10 日的年度会议上当选为 FreeBSD 基金会董事会成员。我们与 John 进行了交流,了解他与 FreeBSD 的渊源,以及他在任期内最期待完成的事情。

    请介绍一下你自己,以及你是如何参与到 FreeBSD 的?

    我初次接触 FreeBSD 是在大学本科期间(我想大概是大一的时候),当时安装了 FreeBSD 2.1.7。真正认真使用 FreeBSD 是在第二年,用 FreeBSD 2.2.2 在宿舍里搭建了一个 NAT/PPP 路由器。第三年,我开始为 FreeBSD 的文档项目做贡献,并于 1999 年 8 月获得了提交权限。大学毕业后的第一份工作,我选择了在 BSDi 全职从事 FreeBSD 开发,在那里我开始参与 SMPng 项目。

    除了代码贡献,我还曾在核心小组(7 届)、发布工程团队以及新成立的源代码管理(srcmgr)团队中任职。自 FreeBSD 期刊创刊以来,我一直担任编辑委员会成员,并担任了主席多年。我还帮助组织了多次开发者和厂商峰会(包括在 2001 年波士顿 USENIX ATC 上首次提出“devsummit”,开发峰会)。

    你为什么热衷于在 FreeBSD 基金会董事会任职?

    过去我认为自己在“项目”方面的不同角色比在基金会董事会中更能发挥作用(而且我也不想只是为了“收集所有的头衔”而担任董事)。然而,在我最后一次核心小组任期之后,以及发生的一些事件之后,我认为我现在可以通过为董事会带来开发者社区的脉动,并反驳外界关于基金会与项目其他领域之间存在脱节的说法来提供帮助。

    基金会的工作中,什么让你感到兴奋?

    我亲眼见证了基金会对项目的支持,例如在新泽西州 Bridgewater 数据中心进行机器的机架安装和清点;与多位工作人员一起组织峰会(非常有帮助!);在期刊编辑委员会任职等。基金会长期以来一直是项目的支持者。

    你希望通过新的领导角色为组织和社区带来什么?

    上面部分已经回答,主要是强化开发者社区和基金会之间的联系。我也有一些与非营利组织相关的有限经验,既包括作为“大额”(姑且这么说)捐赠人,也包括在几个教会董事会中任职(其中包括一次为购置建筑物而进行的筹款活动)。

    你认为你的背景和经验如何补充现有的董事会?

    我认为我在当前董事会中能够发挥的主要作用,是作为一个被视为仍然活跃于开发者社区日常活动的个体。

    在动荡的开源世界中保持稳定:FreeBSD 的持久稳定性

    • 原文链接:

    • 作者:Jason Perlow

    • 原文发布时间:2024 年 9 月 17 日

    在不断发展的开源软件世界中,稳定性和可预测性往往是稀缺资源。最近,红帽企业版 Linux(RHEL)生态系统的变化,包括限制访问源代码,激起了社区的反应,并导致了开放企业 Linux 协会(OpenELA)的成立。

    在这场动荡之中,自 1993 年以降, 始终作为一致性和可靠性的典范脱颖而出。本文将探讨 FreeBSD 的稳定开发模型与即将变化的发布计划,如何与 Linux 社区面临的挑战形成鲜明对比。

    FreeBSD:原始操作系统发行版的火炬传承者

    • 原文链接:

    • 发布时间:2024 年 4 月 25 日

    FreeBSD 是一款开创性的开源操作系统,它延续了伯克利软件发行版(Berkeley Software Distribution,BSD)的传统,该传统最初由加州大学伯克利分校计算机系统研究小组(CSRG)于 1970 和 1980 年代开创。

    尽管“发行版(distribution)”这个术语现在普遍与 Linux 相关联,但它的起源可以追溯到 BSD 的创新方法。与模块化且碎片化的 Linux 发行版不同,FreeBSD 采用整体的方法进行系统开发,提供包含内核、用户空间、工具、库和文档的完整软件包。这一原始概念为向终端用户交付完整的开源操作系统设定了标准。

    在比较开源软件时,FreeBSD 和 Linux 有明显的差异。Linux 有数百个发行版,以满足特定的需求、偏好和理念。另一方面,FreeBSD 的独特之处在于它是一个单一、完整且完全可定制的操作系统。这种独特性不仅体现在发行版的数量上,还体现在 FreeBSD 的整体开发模式和哲学基础上。

    FreeBSD 企业工作组首次会议总结

    • 原地址:

    • 发布日期:2023-8-24

    • 译者:ykla & ChatGPT

    这个工作组的成立始于长期使用 FreeBSD 的用户 Michael Osipov,他花时间向基金会提供了关于他在使用 FreeBSD 时遇到的阻碍的详细笔记。

    接下来的步骤是评估兴趣——我在

    # freebsd-update fetch install
    # pkg update
    # zfs create -p videostar/var/db/galene/data
    # zfs create videostar/var/db/galene/groups
    # zfs create videostar/var/db/galene/recordings
    # pkg install galene
    {
        "users":
        {
            "bob":
            {
                "password": "secret",
                "permissions": "op"
            }
        }
    }
    pkg install py311-certbot
    certbot certonly -d YOURHOSTSFQDN --standalone
    cp /usr/local/etc/letsencrypt/live/meet.fortasse.cloud/fullchain.pem /var/db/galene/data/cert.pem
    cp /usr/local/etc/letsencrypt/live/meet.fortasse.cloud/privkey.pem /var/db/galene/data/key.pem
    chown galene:galene /var/db/galene/data/*
    service galene restart
    # service galene enable
    # service galene start
    # service galene status
    # sockstat -l|grep galene
    https://videostar.example:8443

    Plone Foundation

  • Python Software Foundation

  • Associazione LibreItalia

  • The Document Foundation

  • Eclipse Foundation

  • KDE Foundation

  • OpenForum Europe

  • Open Source Hong Kong

  • OpenStreetMap Foundation

  • FOSSY 2023 会议
    其网页
    https://blog.opensource.org/convening-public-benefit-and-charitable-foundations-working-in-open-domains/
    https://freebsdfoundation.org/news-and-events/latest-news/freebsd-foundation-joins-osis-open-policy-alliance/
    Tarsnap
    TruNas
    Linux Professional Institute
    WIKI
    YouTube 频道
    特刊
    FreeBSD 日
    YouTube 频道
    https://freebsdfoundation.org/blog/advocating-at-events-may-2023-freebsd-dev-summit-and-bsdcan/
    FreeBSD:稳定与创新的传承

    FreeBSD 是一款开创性的开源操作系统,继承了由加州大学伯克利分校计算机系统研究小组(CSRG)在 1970 和 1980 年代开创的原始伯克利软件分发(BSD)遗产。同模块化和碎片化的 Linux 发行版不同,FreeBSD 采取整体方法进行系统开发,提供了包含内核、用户空间、实用程序、库和文档的统一软件包。这一原始概念为向最终用户交付完整的开源操作系统设定了标准。

    RHEL 和 CentOS 现状简述

    红帽企业版 Linux(RHEL)长期以来一直是企业级 Linux 部署的基石。2023 年 6 月,红帽决定限制访问 RHEL 的源代码,这一决定显著影响了下游项目,如流行的免费开源 RHEL 克隆项目 CentOS。根据他们对 GPLv2 和 GPLv3 的解读,红帽通过按要求提供源代码履行了义务,但并不一定以易读和可复现的格式提供。作为回应,开放企业 Linux 协会(OpenELA) 成立,旨在提供开放和免费的企业 Linux 源代码。OpenELA 已经自动化其流程,使得每次 RHEL 新版本发布后的几天内,新版企业 Linux 源代码便能提供,确保其他发行版可以继续基于当前的 RHEL 代码构建。

    开源操作系统开发的集中化与去中心化方法

    在比较开源软件时,FreeBSD 和 Linux 有着显著的不同。Linux 提供数百个适应特定需求、偏好和哲学的发行版。这种去中心化方法允许高度定制和专业化,但也可能引发碎片化和不一致性。而 FreeBSD 则独树一帜,它是一款单一的、完整的且完全可定制的操作系统。其集中化的开发模型确保了统一的软件包,能提供系统一致性和可靠性,并促进了更统一、稳定的环境。

    去中心化方法(如 Linux 发行版)与集中化方法(如 FreeBSD)并没有固有的优劣之分。每种方法都有其优劣。然而,最近的 RHEL/CentOS 代码可用性事件突显了当供应商仅按照其对版权和 GPL 的解释履行义务时,可能对社区利益产生的影响,与从社区最佳利益出发的做法之间的对比。

    FreeBSD 的开发方式

    FreeBSD 项目的组织稳定性是其关键区别之一,自 1993 年以来持续开发着。FreeBSD 是许多企业设备(如 Juniper 的交换机和 NetApp 的 NAS 单元)、消费电子、网络与安全解决方案以及像 Netflix 的 OpenConnect CDN 这样的高流量内容分发系统的基石。这一长期稳定的组织和社区为 FreeBSD 的开发工作提供了可靠性和持续的创新。

    受到原始 伯克利软件分发 启发,FreeBSD 的开发方法采用了集中式模型,这与 Linux 的高度分布式开发生态系统有着很大的不同。与第三方 Linux 发行版将内核与许多外部项目的软件结合不同,FreeBSD 所有系统组件和文档均由单一项目框架内的团队进行开发。这一方法确保了系统的一致性和安全性,突显了 FreeBSD 对统一操作系统的坚持。

    对 BSD 许可证的深厚承诺

    FreeBSD 的核心理念是坚守 BSD 许可证,这反映了项目在自由与开放创新方面的基本原则。这一宽松的许可证几乎不限制软件的使用、修改和分发。FreeBSD 力求减少 GPL 许可证组件的使用,展示了其致力于保持尽可能开放和自由的基础系统,促进创新和协作的环境。

    BSD 2-Clause 许可证 推动着 FreeBSD 的开发和采用。尽管它对使用 BSD 许可证代码的开发者要求较少(并且较为简洁,仅 200 余字,而 GPLv2 长达近 3000 字),FreeBSD 项目由于其领导和结构方式,仍显得更加利他。与像红帽这样的公司不同,红帽虽有贡献于开源项目,但它是以商业利益为驱动,FreeBSD 则来自于其自身的源头,作为一款统一体开发内核和操作系统。这一集中式开发方法确保了所有组件的紧密集成,带来更大的一致性和可靠性。

    FreeBSD 基金会与 FreeBSD 项目的角色

    FreeBSD 基金会 是一家非营利性 501(c)(3) 组织,旨在支持 FreeBSD 项目。该项目的目标是开发一款 BSD 许可证下的开源操作系统。由于项目的组织方式以及它们各自的目的,未来的代码可用性不成问题,项目对开源的承诺也无可置疑。FreeBSD 基金会提供资金和支持,以确保 FreeBSD 继续作为顶级开源操作系统存在。该组织结构强化了 FreeBSD 对开源原则的承诺,确保其持续开发和可访问性。

    安全的构建环境

    FreeBSD 的 持续集成构建环境 以安全为基础原则进行设计。通过隔离构建环境、最小化外部依赖、严格验证源代码并确保一致的构建过程,FreeBSD 有效地减少了与更复杂和控制较少的构建环境相关的风险。这些设计原则共同提升了系统的完整性和安全性,确保了安全和受控的构建过程,减少了漏洞。

    FreeBSD 的新季度和双年度发布计划

    为了提升用户体验、改善系统安全性并简化维护,FreeBSD 更新了其 发布计划。用户现在可以期望每个季度发布一个新的次要版本,每两年发布一次主要的 .0 版本。从 FreeBSD 15.x 开始,稳定分支将支持四年,较之前的五年有所缩短。这一新计划确保了持续的更新流动,实现在维持稳定性的同时应对新出现的安全威胁的实际平衡。

    上游贡献的广泛影响

    FreeBSD 的开发模型秉承了伯克利 BSD 的协作精神。社区的 上游贡献 对整个系统产生了重要影响,从内核到实用程序和文档。这种集中式的开发意味着单一贡献就能改善整个系统的性能、安全性和可用性,产生连锁反应,每一次提升都对项目的整体健康和发展做出贡献。

    未来方向与如何参与

    展望未来,FreeBSD 将继续适应和发展。转向双年度发布周期以及引入四年支持期限是确保项目继续与时俱进、响应用户需求的重要步骤。这些变化,加上 FreeBSD 已经建立的稳定性,使其在开源生态系统中继续成功发展的前景广阔。

    对于有兴趣参与 FreeBSD 的新成员,有很多方式可以参与。无论是担任导师、推广 FreeBSD,还是参与论坛和邮件列表,你的努力都会推动项目的创新和发展。今天就支持 FreeBSD 项目,加入其充满活力的社区,帮助构建这个长期发展的开源生态系统。你可以通过 改进文档、处理 错误报告、提交代码 和 参与讨论 来帮助提升 FreeBSD。每份贡献,无论大小,都会帮助 FreeBSD 成为一款更稳定、安全和高效的开源操作系统。

    结论

    FreeBSD 在开源世界经历重大变化与挑战的时期,依然屹立不倒,成为稳定性和可靠性的灯塔。其集中化的开发模型、宽松的许可证以及对一致性发布的承诺,提供了引人注目的替代方案,展现了与其他项目中动荡局面相对立的优势。随着 FreeBSD 开启加速发布计划,它继续展示着稳定且可预测的开源操作系统的持久价值。


    Jason 是一位拥有超过 25 年开源经验的作家和内容制作人,专注于分布式系统和企业架构等技术话题。曾担任 Linux 基金会的编辑总监,目前是 FreeBSD 基金会的高级撰稿人,亦为 ZDNet 的高级特约撰稿人。他的作品遍布于各大平台,涉及人工智能、云计算、网络安全和 Linux 等领域。

    Steady in a shifting Open Source world: FreeBSD’s enduring stability
    FreeBSD
    对 BSD 许可证的深厚承诺

    FreeBSD 哲学的核心是坚定不移地高扬 BSD 许可证,这体现了 FreeBSD 项目在自由和开放创新方面的基础原则。FreeBSD 遵循与伯克利原始 BSD 相同的精神,几乎所有组件,包括用来构建 FreeBSD 的 C 编译器堆栈,都优先采用 BSD 许可证。

    这一许可模式因其宽松性而闻名,几乎没有限制地允许软件的使用、修改和分发。减少 GPL 许可证组件的努力 强调了 FreeBSD 致力于保持一个尽可能开放和自由的基本系统,促进创新和合作的环境。

    FreeBSD:坚持统一的开发模式

    原始的伯克利软件发行版启发了 FreeBSD 的开发方法,并采用了集中的开发模式,这与 Linux 的高度分散的开发生态系统有很大不同。

    与第三方 Linux 发行版(如 Debian、Ubuntu、Fedora 等)不同,后者将由 Linux 内核项目(由 Linux 基金会管理的项目)开发的内核与来自许多外部项目的软件结合,FreeBSD 在一个单一的项目框架内开发所有系统组件和文档。这种方法确保了无与伦比的系统一致性和安全性,凸显了 FreeBSD 对统一操作系统的承诺。

    FreeBSD 的方法根植于原始伯克利软件发行版的原则,强调一个全面且统一的操作系统。与此相反,Linux 是一个通用内核基石,众多独立实体在其上构建了不同的发行版。因此,Linux 发行版在行为、功能和用户体验上有显著差异。

    FreeBSD 的方法在所有系统组件之间创建了一个集成关系,允许轻松顺利的更新和改进、向后兼容性,以及对生产环境的保证,等等。与 Linux 的模块化方法不同,FreeBSD 的方法简化了安全审计并提高了性能。开发者可以全面了解整个系统的架构,而不是孤立的部分。所有系统组件都一起开发,然后由其发布工程团队 打包 进行每个版本的发布。这种方法确保了更新的系统性一致性,缓解了 Linux 环境中常见的依赖冲突问题。

    安全的构建环境

    FreeBSD 的一个关键特点是,其基本系统(核心)的构建环境是以安全为基础原则设计的。通过隔离、最小化、一致性和可验证的构建过程,FreeBSD 有效地减少了与更复杂、控制较少的构建环境相关的风险,确保了系统的完整性和安全性。

    FreeBSD 构建系统的架构设计遵循多个原则,这些原则共同增强了其安全性:

    • 隔离与控制: FreeBSD 的构建环境被设计为隔离且自包含,最大限度地减少了外部干扰的机会。这种设置确保了构建过程受到外部威胁的保护,并减少了恶意代码注入的可能性。通过保持构建环境的独立性和隔离性,FreeBSD 减少了与外部系统交互相关的风险。

    • 最小化外部依赖: FreeBSD 旨在最小化构建系统中的外部依赖。此方法减少了系统暴露于第三方工具和库的漏洞,从而限制了攻击面。专注于使用内部工具和资源构建基本系统有助于保持一个受控且安全的构建过程。

    • 源代码验证: 在 FreeBSD 的核心环境构建过程中,源代码的完整性是一个优先考虑的问题。在编译并集成到系统之前,所有的代码都将经过严格检查。这个验证过程对于发现未经授权的更改或潜在的恶意代码至关重要,确保只有经过验证和信任的代码才会用于构建。

    • 一致的构建环境: 构建环境的一致性是 FreeBSD 方法的另一个关键方面。稳定且可预测的构建环境有助于尽早发现任何异常和不规则情况,这些情况可能表明存在安全问题。这种一致性有助于维护一个安全且受控的构建过程,减少引入漏洞的可能性。

    • 特权分离和最小特权: FreeBSD 的构建系统遵循特权分离和最小特权的原则,意味着构建环境中的每个进程和用户只有最必要的访问权限。这种方法通过防止受损的进程访问系统中无关的部分,限制了安全漏洞的潜在影响。

    • 可审计和可重现的构建: 确保构建是可审计和可重现的,是 FreeBSD 构建系统安全性的一个重要方面。可重现的构建意味着相同的源代码始终生成相同的二进制输出,这有助于验证和审计过程。这种透明性有助于检测未经授权或恶意的修改,从而保护构建过程的安全性。

    上游贡献对 FreeBSD 的广泛影响

    FreeBSD 的开发模式受到伯克利 BSD 精神的推动,强调协作。社区的上游贡献对整个系统产生了重大影响,从内核到工具和文档,最终形成了一个统一的方法,每一次增强都能造福整个生态系统。与 Linux 生态系统不同,Linux 中的改进通常局限于特定的发行版或组件,而 FreeBSD 的集中式开发意味着一次贡献可以提升系统的整体性能、安全性和可用性。

    这种方法产生了涟漪效应,每一个增强都为项目的整体健康和发展作出贡献,反映了 FreeBSD 对保持一个统一且强大的操作系统的深刻承诺。FreeBSD 包容性的社区和透明的流程放大了每一次贡献的价值,利用集体智慧进行系统性改进。

    相比之下,Linux 发行版的模块化特性可能导致个别贡献的影响碎片化。这突显了 FreeBSD 在促进统一、全面的开发生态系统方面的独特方法,展示了其对凝聚力和系统性进步的承诺。每一个上游贡献都是 FreeBSD 持续发展的组成部分。

    结论

    FreeBSD 的开发历史见证着它对开源原则的执着追求和伯克利 BSD 的传统。FreeBSD 与其他软件发行版的区别在于其统一的开发模式、对 BSD 许可证的支持以及关注那些能够惠及整个系统的贡献。FreeBSD 对质量、稳定性和完整性的承诺使其成为开源生态系统中的重要角色,也证明了全面方法在软件开发中的持久价值。

    FreeBSD 对这一具有凝聚力的“发行版”的承诺反映了其在操作系统开发上更深层次的哲学立场。FreeBSD 将稳定性和可靠性放在首位,使其有别于 Linux 发行版杂乱无章的局面,保持了其伯克利起源时所提出的统一而有凝聚力的愿景。

    FreeBSD: The torchbearer of the original operating system distribution
    关于 jail 的优秀文档
    我们最近 YouTube 视频
    管理资源限制
    社区的 Ansible 剧本
    我们的 GitHub 仓库
    https://www.youtube.com/embed/vVpd34bWCJA
    sysrc jail_enable="YES" && sysrc jail_parallel_start="YES"
    zfs create -o mountpoint=/jails zroot/jails
    zfs create zroot/jails/media
    zfs create zroot/jails/_base
    fetch https://download.freebsd.org/ftp/releases/$(uname -m)/$(freebsd-version)/base.txz -o /jails/media/$(freebsd-version)-base.txz
    tar -xf /jails/media/$(freebsd-version)-base.txz -C /jails/_base/ --unlink
    cp /etc/resolv.conf /jails/_base/etc/resolv.conf
    cp /etc/localtime /jails/_base/etc/localtime
    freebsd-update -b /jails/_base/ fetch install
    pkg -c /jails/_base install -y pkg python zsh
    zfs snapshot zroot/jails/_base@$(freebsd-version)-$(date +%d-%b-%y)
    # https://man.freebsd.org/jail.conf
    # https://man.freebsd.org/jail
    #
    ip4 = inherit;
    ip6 = inherit;
    
    # 默认应用于所有 jail
    exec.start = "/bin/sh /etc/rc";
    exec.stop = "/bin/sh /etc/rc.shutdown jail";
    exec.clean;
    
    # 文件系统
    mount.devfs;
    devfs_ruleset=4;
    enforce_statfs=1;
    securelevel=2;
    #allow.mount.zfs;
    #allow.mount;
    
    # 禁用所有花哨的东西
    allow.mount.nodevfs;
    allow.mount.nofdescfs;
    allow.mount.nolinprocfs;
    allow.mount.nonullfs;
    allow.mount.noprocfs;
    allow.mount.notmpfs;
    allow.nochflags;
    
    # 但这些总是有用的
    allow.raw_sockets;
    allow.reserved_ports;
    allow.sysvipc=1;
    
    # 杂项
    allow.nomlock;
    allow.noquotas;
    allow.noread_msgbuf;
    allow.noset_hostname;
    allow.nosocket_af;
    allow.nosysvipc;
    sysvmsg=disable;
    sysvsem=disable;
    children.max=0;
    .include "/etc/jail.conf.d/*.conf";
    #!/bin/sh
    #
    set -eo pipefail
    
    SNAP=${2:-$(zfs list -t snapshot -H -o name | grep "jails/_base" | cut -f3 -d/)}
    
    if [ -z $1 ]; then
        echo "pass new jail name"
        exit 1
    else
        new=$1
    fi
    
    zfs clone zroot/jails/${SNAP} zroot/jails/${new}
    
    test -d /etc/jail.conf.d || mkdir -p /etc/jail.conf.d
    cat > /etc/jail.conf.d/${new}.conf <<EOF
    ${new} {
        host.hostname = "${new}.jail";
        path = "/jails/${new}";
    }
    EOF
    
    sysrc jail_list+=${new}
    和 Discord 上发布了招募兴趣的信息,反应非常好。有 40 人举手加入了工作组。以下是这 40 人按角色划分的情况。
    image

    着手进行业务

    幸运的是,有 13 人,包括我在内,参加了 8 月 16 日举行的企业工作组的第一次会议。以下是会议回顾。

    在整理日常事务后,包括提醒遵守 FreeBSD 行为准则,我们批准了工作组章程,并继续讨论了现有的差距。

    image
    image

    在此过程中,我们就以下几个领域展开了愉快的讨论:

    科学计算

    讨论的第一个重点涉及相近但我认为稍有不同的科学计算用例。这是很好的时机,因为就在那周早些时候,我与长期使用 FreeBSD 的用户和社区成员进行通话,他正在努力改进 FreeBSD 在这个领域的应用。通话结束后,我将所有人联系在了一起,我的基金会同事 Joe Mingrone 还加入了在这个领域工作的一些 Port 维护者。如果你有兴趣在这个领域提供帮助,请让我知道,我会将你与合适的人联系起来。

    Samba

    下一个讨论涉及加强对 Samba 的支持。Allan Jude 提到 Klara 正在开发一个特殊的 Samba 模块,以便在上游使用,从而使其能够利用新的块引用树 ZFS 功能。要在 Samba CI 系统中获得更通用的 FreeBSD 上游支持,我们需要在 Samba 中引入 FreeBSD 的工作人员。下一步是从社区中寻找愿意在 FreeBSD 支持上游方面工作的志愿者。如果你可以提供帮助,请与我联系。

    云原生

    一位与会者评论说,在所有议题中,在他们看来云原生是最重要的,可能比其他所有议题加在一起还要重要。Allan 向大家介绍了一个名为 XC 的新项目:https://github.com/michael-yuji/xc 其他人询问了这与 runj 有什么关系。开放容器倡议社区正在为 FreeBSD 提供支持,一些企业工作组的参与者表示有兴趣提供帮助。谢谢大家!

    高端人工智能/高性能计算 Nvidia GPU 驱动

    一名在数据中心服务器制造商工作的参与者询问了 FreeBSD 中用于人工智能和高性能计算应用(例如 Nvidia h100/a100)的 Nvidia GPU 驱动的情况。

    添加到差距清单

    人们提出了以下要添加到差距清单的项目:

    • eBPF

    • 零信任 FreeBSD 构建

    • 可重复的 FreeBSD 构建

    • FreeBSD 的软件供应链和组成清单(SBOM)

    关于配置管理的问题

    一名与会者问了 SALT、Puppet 和 Ansible 对 FreeBSD 的支持情况。

    这三者在生产中都被使用,并且运行良好——Ansible 和 SALT 似乎更受欢迎。以下是一些资源:

    • SALT

      • 在 FreeBSD 上安装:https://docs.saltproject.io/salt/install-guide/en/latest/topics/install-by-operating-system/freebsd.html

      • 使用 SALT:https://papers.freebsd.org/2019/bsdcan/hendryxparker-masters_and_minions_or_the_dream_of_bsd_automation/

    • Ansible

      • 在 BSD 主机上使用 Ansible:

      • 快速入门指南:

      • 使用 Ansible Playbooks 自动部署 FreeBSD 上的各种服务

    • Puppet

    你可以在此处查看会议的录像:FreeBSD 基金会企业工作组会议 #1

    如果你对此感兴趣,并且希望提供帮助,请填写此 Google 表单,帮助使 FreeBSD 成为一个更好的通用企业操作系统。

    Recap of first meeting of the FreeBSD Enterprise Working Group
    LinkedIn
    GitHub
    Docker Hub
    YouTube 频道
    Subreddit
    工作文档
    YouTube 频道
    此订阅源
    我们的通讯
    联系我们

    ZFS 启动环境详解

    • ZFS Boot Environments Explained

    • 发布时间:2025/11/25

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    这篇文章不会尝试给出 ZFS 的通用解释——我们只会专注于 ZFS 启动环境。关于它们存在许多误解和误会——有些人不知道 ZFS 启动环境里面有什么、ZFS 启动环境里面没有什么——但更糟的是——有些人完全不懂。

    我假设读者确实了解什么是 ZFS 文件系统的概念和特性 —— 比如 ZFS 池或 ZFS 数据集之类的东西对读者来说是已知的……并且读者能够解释 ZFS 和 LVM 之间的区别。

    ZFS 启动环境里有什么

    这是首先经常被误解的主题……大概是因为没有理解 canmount=off 这个 ZFS 属性 —— 你可以在 man 中获得更多相关内容。

    如果该属性被设置为 off,则文件系统无法被挂载,并且会被 zfs mount -a 忽略。将该属性设置为 off 类似于将 mountpoint 属性设置为 none,但数据集仍然具有正常的 mountpoint 属性,该属性可以被继承。将此属性设置为 off 允许数据集仅作为继承属性的机制使用。设置 canmount=off 的一个例子是创建两个具有相同挂载点的数据集,这样两个数据集的子数据集会显示在同一目录中,但可能具有不同的继承特性。

    当设置为 noauto 时,数据集只能显式地挂载和卸载。数据集在创建或导入时不会自动挂载,也不会被 zfs mount -a 命令挂载,或被 zfs unmount -a 命令卸载。

    这是我以前关于 “ZFS 启动环境” 的演讲中的幻灯片 —— 可以在链接 获得 —— 那是在 2018 NLUUG 会议上做的……颜色并不是随便选的……它们是特地准备成那样,以致敬 NLUUG 会议举办的国家 —— 荷兰。

    对 /var 和 /usr 使用 canmount=off 背后的想法是这样的:

    /var 和 /usr 这些 ZFS 数据集的内容确实位于 ZFS 启动环境中 —— 位于安装程序创建的 zroot/ROOT/default 这个 ZFS 启动环境中 —— 而其余像下面这些这样的内容:

    这些内容 被排除在这个 ZFS 启动环境之外。

    因此,在默认情况下,一切都包含在 ZFS 启动环境中 —— 如果你想从 /usr 或 /var 中排除某些部分 —— 你就为这些需要排除的路径添加相应的 ZFS 数据集。

    下面是你在 安装程序中选择 Auto(ZFS) 选项后,FreeBSD 默认的 ZFS 布局。

    关键点在于,zroot/usr 和 zroot/var 这两个 ZFS 数据集都具有 canmount=off 这个 ZFS 属性。这意味着 /usr 文件系统 并不存放在 zroot/usr 这个 ZFS 数据集中……它是存放在 zroot/ROOT/default 这个 ZFS 启动环境里的。

    你可以用传统的 命令进行验证如下。

    如你所见,/usr 和 /var 都只是 zroot/ROOT/default 这个 ZFS 数据集中的目录。数据并 不 保存在 zroot/usr 或 zroot/var 这些 ZFS 数据集中……再次强调,这是因为它们具有 canmount=off 这个 ZFS 属性。

    现在,这个 FreeBSD 默认设置的主要理念 / 概念是:所有内容都保存在 zroot/ROOT/default 这个 ZFS 数据集中,而所有其他 ZFS 数据集都是从它中 排除(exclude) 出去的。比如 zroot/var/audit 具有 canmount=on 这个 ZFS 属性……其他所有的也都是完全相同的情况。

    说实话,为了让事情变得傻瓜式地简单,我会把 zroot/usr 和 zroot/var 这两个 ZFS 数据集换成一个能准确说明用途的名称 —— zroot/exclude,因为在它下面的所有 ZFS 数据集,本质上都是被排除在 ZFS 启动环境 之外的。

    现在更容易理解了吗?我希望是的……即使在上面进行了所有这些重命名,ZFS 的挂载点也 没有任何变化,因为 mountpoint 是个独立的 ZFS 属性——所以即使我们对 ZFS 数据集的命名逻辑进行了重新组织,只要没有从上层继承,这个 ZFS mountpoint 属性在逻辑重组后依然保持不变。

    之前使用 df(1) 的测试结果与之前完全相同。

    /usr 和 /var 的数据都保存在 default ZFS 启动环境内。

    我们甚至可以移除 /usr 和 /var 的挂载点,这样会更加清晰。

    够清楚了吗?

    新建 ZFS 启动环境时会发生什么

    另一个经常被误解的谜题……或者说没有被清楚理解的部分。

    通常,ZFS 启动环境 是由某个时间点创建的 ZFS 快照 克隆出来的可写 ZFS clone。

    让我用我最喜欢的 Enterprise Architect ASCII Edition 软件来可视化一下。

    关于上面的 ASCII 图,beadm(8) 命令的输出将显示类似的信息。

    现在……有趣的部分来了——你可以创建任意数量的额外 ZFS 启动环境,或者使用 ZFS 的 send|recv 功能。

    下面是这种设置的示例。

    ……并且你可以从每一个这些 ZFS dataset 创建额外的 ZFS 启动环境。

    在系统之间传输 ZFS 启动环境

    ……而且这些系统可以是 任意 系统。你可以在笔记本之间传输 ZFS 启动环境,或者从笔记本传到服务器……甚至从 Bhyve VM 传到服务器……随你喜欢。

    下面你将看到一些示例,展示如何将现有的 ZFS 启动环境通过网络从一个 FreeBSD UNIX 系统复制到另一个系统。

    这里的 mbuffer(1) 并非关键——它只是通过确保随时有数据可发送来加快传输过程。

    上面演示的是将我在 ThinkPad W520 上的 14.3 ZFS 启动环境发送到 ThinkPad T14 系统——这也是为什么我想在另一端将其命名为 14.3.w520,以确保我记得它的来源。

    你也可以像我在文章 中描述的那样,从零创建新的 ZFS 启动环境。

    总结

    我希望现在 ZFS 启动环境 的主要原理更加清晰了。

    ……如果还有不明白的地方,欢迎提出你的疑问。

    配置自己的 VPN——基于 OpenBSD、Wireguard、IPv6 和广告拦截

    原文链接:https://it-notes.dragas.net/2023/04/03/make-your-own-vpn-wireguard-ipv6-and-ad-blocking-included/

    VPN 是连接到自己的服务器和设备的基本工具。许多人出于各种原因使用商业 VPN,从不信任其提供商(尤其在连接到公共热点时)到希望使用不同 IP 地址(也许是其他国家的)在互联网上“活跃”。

    无论出于何种原因,解决方案都不会匮乏。我一直在设置管理 VPN,以允许服务器、客户端使用安全通道进行通信。最近,我在所有设备上(包括桌面/服务器和移动设备)启用了 IPv6 连接,我需要快速创建一个节点,集中一些网络并允许它们在 IPv6 网络上出站。我使用并将要描述的工具是:

    • VPS——在这种情况下,我使用了基本的 Hetzner Cloud VPS,但所有提供 IPv6 连接的提供商都可以:如果你需要 IPv6 的话。

    • OpenBSD——一款干净、稳定且安全的操作系统。

    • Wireguard——轻量级、安全,同时也不会“唠叨”,因此对移动设备电池也很友好。在没有流量时,它不会传输/接收任何内容。被所有主要的桌面和服务器操作系统以及 Android 和 iOS 设备广泛支持。

    • Unbound——可以直接向根域名服务器发出 DNS 查询,而非转发器。还允许插入阻止列表,类似于 Pi-Hole 的结果(即广告拦截)。

    • 列表——立即阻断与黑名单用户之间的连接。

    第一步是激活 VPS 并安装 OpenBSD。在 Hetzner 云控制台上,没有有预置的 OpenBSD 镜像,只有 Linux 发行版可选。别怕,只需选择其中一个 Linux 并创建 VPS。创建完成后,OpenBSD ISO 镜像将出现在“ISO 映像”中。只需插入虚拟光驱,重启 VPS,OpenBSD 安装程序就会出现在控制台中。

    我就不细说了,操作简单明了。唯一的注意事项(对于 Hetzner Cloud VPS)是使用“自动配置”进行 IPv4 设置,但暂时别配置 IPv6。稍后再配置。

    使用 syspatch 命令安装所有 OpenBSD 更新并重新启动,内核将被重新链接。

    在 OpenBSD 上,Wireguard 完全集成到了基本系统中,无需安装外部软件包。这是一个重大优势,因为随着时间的推移,所有与 Wireguard 相关的支持将由主要的 OpenBSD 开发团队直接管理。

    第一步是在 VPS 上配置 IPv6。在 Hetzner 下,不幸的是,他们只提供 /64 的地址,因此需要对分配的网络进行分段。在这个例子中,它将被划分为 /72 子网络 - 可以使用 来查找有效的子类。

    文件 /etc/hostname.vio0 应该看起来如下:

    简而言之,保留 Hetzner 分配的基地址,但将子网掩码改为/72 - 从而可以使用其他网络。

    它将重新配置网络接口并允许 IPv6 开始工作。要测试它:

    若一切配置正确,可执行 ping 命令且 google.com 将回复。

    现在需要为 IPv4 和 IPv6 启用转发。在文件 /etc/sysctl.conf 中输入以下内容:

    要应用这些更改,你可以重新启动或直接输入:

    配置 Wireguard,需要进行一些步骤。首先,需要创建私钥:

    会出现类似以下内容:

    YUkS6cNTyPbXmtVf/23ppVW3gX2hZIBzlHtXNFRp80w=

    现在创建一个名为 /etc/hostname.wg0 的新文件:

    正在创建一个新的 Wireguard 接口,名为 wg0。它将拥有 IPv4 地址“172.14.0.1”,Wireguard 将监听端口 51820,并使用稍后创建的私钥。它还将在供应商提供的子类别之一上拥有 IPv6 地址。

    保存并激活该接口:

    如果所有内容都正确输入,它应该会启用接口。现在:

    将返回类似这样的内容:

    记录下 wgpubkey——它将用于配置客户端。

    就防火墙而言,OpenBSD 带有基本的 pf 配置。在我的设置中,我倾向于阻断不需要的内容,并允许可能有用的内容。但是,我喜欢把“坏人”挡在门外,所以我使用黑名单。pf 允许在运行时向表中插入和移除元素,因此防火墙可以相应地进行配置。

    要下载并应用 Spamhaus 列表,我使用在互联网上找到的一个简单而有效的脚本。

    所以在/usr/local/sbin/spamhaus.sh 中创建脚本:

    使其可执行并运行:

    配置 pf 的方法很多。一个相当简单的例子可能是这样的:

    这是一个非常简单的配置:它阻止了来自 Spamhaus 下载列表中的所有内容,允许 Wireguard 网络到公共接口的 NAT,允许 IPv6 中的 icmp 流量(这对网络正常运行至关重要),同时阻止了针对 Wireguard IPv6 LAN 的传入流量(请记住,IP 地址将是公共的且可直接到达,因此我们不希望默认情况下公开我们的设备)。允许 Wireguard 接口上的所有流量通过。然后将阻止所有流量并指定异常,即允许 ssh 和 Wireguard 连接(当然)。还将授权允许流量从公共网络接口流出。

    重新加载 pf 配置:

    倘若一切正常,防火墙应该已加载新的参数。

    现在是配置 Unbound 来实现 DNS 查询缓存和相关广告拦截的时候了。一段时间前,我找到了一个脚本,稍作调整后使用。我记不清楚原始作者是谁了,所以我只在这里贴出来脚本。

    创建一个脚本来更新 /usr/local/sbin/unbound-adhosts.sh 中的 unbound 广告拦截。

    类似地,使脚本可执行并运行它:

    现在,可以修改位于 /var/unbound/etc/unbound.conf 的 Unbound 配置文件如下:

    在启动 unbound 之前,必须给予适当的权限:

    现在可以启用并启动 unbound。由于需要加载(长)阻止列表,这将需要几秒钟:

    如果一切都正确,unbound 将能够响应来自各自 LAN 的请求,位于 172.14.0.1 和 2a01:4f8:cafe:cafe:100::1 上。

    现在可以配置 Wireguard 客户端了。每种实现都有其自己的过程(Android、iOS、MikroTik、Linux 等),但基本上只需在服务器和客户端上创建正确的配置即可。例如,在 OpenBSD 服务器上输入“ifconfig wg0”命令可查看服务器的公钥,应将其插入到客户端上将创建的“peer”配置中;而客户端的公钥则将在服务器上这样使用:

    重新打开文件 /etc/hostname.wg0 添加:

    重新加载配置:

    在客户端上,通过在本地 IP 地址中插入“172.14.0.2/32, 2a01:4f8: cafe: cafe: 100:: 2/128”(在主机名为 wg0 的对等配置中输入的)创建一个新配置。将 DNS 服务器地址设置为“172.14.0.1”及/或其对应的 IPv6 地址(在本例中为 2a01:4f8: cafe: cafe: 100:: 1 - 你的将会不同)。在对等端,插入服务器的数据,包括其公钥、IP 地址:port(在示例中,port 是 51820),以及允许的地址(设置“0.0.0.0/0, :: 0/0”意味着“所有连接将通过 Wireguard 发送” - 所有流量将通过 VPN 传输,无论是 IPv4 还是 IPv6)。

    也可以将 VPN 仅用作广告拦截器,只通过其路由 DNS 流量。要实现此结果,只需配置客户端,使得唯一允许的地址是刚配置的 unbound 的地址(在本示例中,172.14.0.1 或 2a01:4f8: cafe: cafe: 100:: 1) - DNS 解析将通过 VPN 进行,但浏览将继续通过主提供商运行。

    如果你希望垃圾邮件和广告屏蔽列表能够自动更新,创建/etc/daily.local 文件并添加以下行:

    所有这些都可以通过简单安装 OpenBSD 来实现,无需安装任何额外的软件包。这既有助于更新管理,也有助于安全性。

    关于对 FreeBSD 发布计划和生命周期的修订

    • 邮件原文地址:https://lists.freebsd.org/archives/freebsd-announce/2024-July/000143.html

    亲爱的 FreeBSD 社区,

    我们正在对发布工程流程进行两项修改:

    1. 从 FreeBSD 15.x 开始,FreeBSD STABLE 分支生命周期将从首个 .0 release 发布后的 5 年缩短至 4 年。

    2. 将建立一个可预测的发布计划,在大多数情况下,每个季度都会从在生命周期内的 STABLE 分支新发布一个小版本的 release。

    背景介绍:

    我从 2023 年 11 月担任发布工程主管以来,一直在审查发布流程和时间表。我得出了以下结论:

    1. 通过改善发布工程团队与 FreeBSD 开发者之间的沟通,我们可以简化发布流程,通常只需进行 3 个 BETA 版本及 1 个 RC 版本,以前往往需要 3-4 个 BETA 版本及 3-6 个 RC 版本。

    2. 更加频繁的 release 将进一步改善发布流程,因为如果距离下一个小版本的 release 还有一年或更长时间,就不会有那么大的压力去增加“最后一个功能”。

    3. 虽然我们不能为具体发布时间打包票——因为我们始终会为重大 Bug 暂停发布,但我们可以确定发布周期开始的时间,这足以提供对长期规划有用的预计。

    4. 发布工程团队有能力每 3 个月发布一个 release,只有在 .0 release 时才会花费更长时间。

    综上,FreeBSD 核心团队已经批准如下:从 FreeBSD 15 开始,将 STABLE 分支的生命周期从 5 年削减至 4 年(每个 .0 release 的生命周期仍为“下个小版本 release 发布日起 + 3 个月”,虽说现在更加可预测了),我已经为即将到来的 release 制定了一个时间表:

    release
    发布时间
    EoL

    * 13.5 的生命周期为自 13.0 发布之日起的 5 年。14.6 的生命周期为自 14.0 发布之日起的 5 年。

    我将其称为“季度”计划,因为大多数季度都会发布新的 release,而且对于小版本 release 来说,整个发布流程都在该季度内完成:代码冻结从季度首月中旬开始;在次月初创建 release 分支并进行 BETA 构建;最终在季度末月初完成 release。

    因此:

    • 新功能和驱动更新应在一月/四月/七月/十月中旬完成,以便包含于相关 release。

    • 我们需要人员在二月/五月/八月/十一月对 BETA 版本进行测试。

    • 即使时间表略有延误,release 版本也应在三月/六月/九月/十二月底前完成。

    我们希望这个更具可预测性的发布时间表能够让 FreeBSD 用户更轻松地规划和管理他们的升级周期,同时平衡 release 版本中新功能的可用性和项目维护支持的众多 release。

    此致,

    Colin Percival

    FreeBSD 发布工程主管 & EC2 平台维护者

    Tarsnap 创始人 | | 专为高度安全需求者设计的在线备份服务

    FreeBSD ports 开发技术研究

    • 原文:FreeBSD ports を 作 る 際 の 調査 ノウハウ

    • 作者:重村法克

    • 2024-01-07

    介绍

    在创建 Ports 时,参考模板和手册进行操作时,可能会遇到一些无法按照常规模式处理的情况,或者需要处理一些特殊行为的情况。这时,我们可能会对如何追踪这些情况、如何正确插入操作产生困惑。

    例如,当从 Ports 安装时(make install),通常会按以下顺序执行:

    此外,通过在各个目标前加上 pre- 或 post- 前缀(例如 pre-fetch 或 post-patch),可以在执行某个目标之前或之后插入自定义操作。更进一步,通过指定 do- 前缀(覆盖默认行为),也可以控制 Ports 的默认行为。关于这些顺序和控制,详细内容如下:

    在某些情况下,可能需要禁用某个目标(例如 NO_BUILD、NO_INSTALL、NO_TEST,分别使 make build、make install、make test 失效),或显式启用某个目标(例如 HAS_CONFIGURE、GNU_CONFIGURE,使 make configure 生效)。这些设置在不同的 Ports 中有不同的处理方式。

    实际上,在更多的细节处,还会有各种各样的钩子。要完全列出这些钩子非常困难,因此可以记录一些调试和调查的关键点。

    目标阶段

    如前所述,常见的目标包括:

    • all

    • fetch

    • extract

    • patch

    除此之外,还应了解一些其他目标:

    • config / showconfig / rmconfig

    • package / repackage

    • test

    在 Ports 构建过程中,执行的一系列目标由 _TARGETS_STAGES 变量定义。这个变量在 bsd.port.mk 中定义,并不打算被覆盖。在适当的 Ports 目录中运行 make -V_TARGETS_STAGES,可以看到类似 SANITY PKG FETCH EXTRACT PATCH CONFIGURE BUILD INSTALL TEST PACKAGE STAGE 的内容。

    基于上述变量的内容,每个阶段都会通过 _阶段名_SEQ 变量详细设置顺序,依赖关系则通过 _阶段名_DEP 进行定义。特别是以 _SEQ 结尾的变量,定义了“优先级:目标”,即使后来添加的目标也会按照顺序执行。

    例如,在 Go 语言应用程序中,特有的 Go 获取操作 go mod download 会在以下阶段执行:

    如果需要在极其特殊的时机插入操作,则需要按照这个流程来进行插入。

    使用 make 命令进行调试

    在 Ports 中,为了实现各种简化的表达,表面上看起来可能更加简单。然而,结果是实现变得极为复杂。尽管你可能大致理解了先前提到的目标阶段,但实际发生了什么,为什么会失败,进行调查是非常困难的。这时,make 命令的调试选项(-dX,其中 X 是针对特定功能的选项)就派上了用场。

    特别是 -dl 选项,它会显示包括 bsd.port.mk 等文件中的 @ 隐藏的命令执行过程。

    或者使用 make -de。这个选项仅显示执行失败的命令。如果在构建过程中出现失败,并且你想知道具体是哪条命令执行失败,可以先使用 make -de 查看失败的命令,再通过 make -dl 查看整体流程,这样有助于更容易地掌握问题。

    此外,make -dx 选项会使得调用的 shell 命令带上 -x 选项,从而使得在 shell 脚本中执行的内容被显示出来。由于是每次调用时显示,因此与 make -dl 的区别可能不太明显。

    常见问题与解答

    Q. 为什么这篇文章写得有点杂乱?

    A. 这都是 Maven 或 Gradle 的错!它们像 Go 语言一样频繁地进行预获取(prefetch),这点我可以勉强接受。但问题是,它们没有很好地进行缓存,所以我查了很久,最后不得不想办法解决这个问题。

    Q. 那么你最终解决了吗?

    A. 继续关注网站上的更新吧!

    参考文献

    为什么你应该使用 FreeBSD

    • 原地址:

    • 作者:FreeBSD 基金会

    • 原文发布时间:2024 年 8 月 28 日

    是一款稳定可靠的开源操作系统,历史悠久,已成为一些全球关键基础设施的支撑平台。FreeBSD 以其稳定性、安全性和卓越性能著称,服务于广泛的用户群体,从寻求大规模部署可靠基础的经验丰富的系统管理员,到重视良好文档和社区驱动环境的开源新手。

    BSD 在 Unix 发展中的角色

    • 发表于 1993 年 8 月,澳大利亚霍巴特

    • 澳大利亚计算机协会塔斯马尼亚 Unix 特别兴趣小组

    • 作者:Michael G. Brown

    • 电子邮件:

    如何将基于 Electron 的应用程序移植到 FreeBSD

    • 原文链接:

    • 作者:Hiroki Tagato

    • 2020 年 3 月 3 日

    • 作者复刻的 GitHub 地址:

    FreeBSD 基金会 2023 年暑期实习生:Jake Freeland

    • 原标题:

    • 最后发布于 2023 年 9 月 8 日

    • 译者:ykla & ChatGPT

    向学生们介绍 FreeBSD 仍然是 FreeBSD 基金会的重要任务。今年,除了参与谷歌编程之夏和滑铁卢大学合作计划外,基金会还聘请了 Jake Freeland,一位之前的谷歌编程之夏学生,来进行暑期实习。我们坐下来与 Jake 了解了他以及他一直在为支持 FreeBSD 所做的工作。

    # pkg install -y podman-suite
    # zfs create -o mountpoint=/var/db/containers zroot/containers
    # cp /usr/local/etc/containers/pf.conf.sample /etc/pf.conf
    # sysctl net.pf.filter_local=1
    # service pf enable
    # service pf start
    # service linux enable
    # service linux start
    $ doas podman run ghcr.io/freebsd/freebsd-runtime:14.3 freebsd-version
    14.3-RELEASE
    $ doas podman run --rm --os=linux docker.io/alpine cat /etc/os-release | head -1
    NAME="Alpine Linux"
    $ doas podman run --os=linux -p 80:80 -v $PWD/website:/usr/share/caddy -v caddy_data:/data docker.io/caddy
    doas podman run -it --os=linux docker.io/phips/pandas:v3 /bin/bash

    从开发角度上来看,每两年发布一个 .0 release 的确是可行的(如果考虑到像无法合并到主干的新功能等因素),但安全团队和 ports 团队只能同时管理不大于两个的 STABLE 分支;故,4 年的生命期限比 5 年更为可行。

    13.5

    2025 年 3 月

    2026 年 4 月*

    14.3

    2025 年 6 月

    2026 年 6 月

    15.0

    2025 年 12 月

    2026 年 9 月

    14.4

    2026 年 3 月

    2026 年 12 月

    15.1

    2026 年 6 月

    2027 年 3 月

    14.5

    2026 年 9 月

    2027 年 6 月

    15.2

    2026 年 12 月

    2027 年 9 月

    14.6

    2027 年 3 月

    2028 年 11 月*

    15.3

    2027 年 6 月

    2028 年 6 月

    16.0

    2027 年 12 月

    2028 年 9 月

    15.4

    2028 年 3 月

    2028 年 12 月

    16.1

    2028 年 6 月

    2029 年 3 月

    15.5

    2028 年 9 月

    2029 年 6 月

    16.2

    2028 年 12 月

    2029 年 9 月

    15.6

    2029 年 3 月

    2029 年 12 月

    16.3

    2029 年 6 月

    2030 年 6 月

    17.0

    2029 年 12 月

    2030 年 9 月

    13.3

    2024 年 3 月

    2024 年 12 月

    14.1

    2024 年 6 月

    2025 年 3 月

    13.4

    2024 年 9 月

    2025 年 6 月

    14.2

    2024 年 12 月

    2025 年 9 月

    www.tarsnap.com
    治理与社区

    FreeBSD 受益于一种协作开发模式,这与其他某些由单一独裁式人物主导的操作系统不同。这种模式促进了平衡的决策过程,确保操作系统的发展方向能够反映其多样化用户群体的需求。一支由选举产生的,经验丰富的开发团队负责该项目,提供了长期的稳定性和清晰的发展路线图。

    此外,FreeBSD 拥有庞大而友好的社区,以乐于助人和响应迅速而闻名。新用户可以利用广泛且组织良好的文档资源,这些资源涵盖了从安装到高级配置的各个方面。FreeBSD 手册 是一本全面的指南,而在线论坛、邮件列表和用户制作的内容提供了额外的故障排除和学习途径。强大的社区感促进了合作,确保用户有一个可靠的支持网络来解答他们的问题并应对各种挑战。

    宽松的许可证

    FreeBSD 采用的宽松许可证——BSD 许可证,与 Linux 使用的更为严格的 GNU 通用公共许可协议(GPL)截然不同。BSD 许可赋予了用户极大的自由,可自由使用 FreeBSD:哪怕用于商业应用,亦无需支付许可费和版税。此外,用户可以自由修改源代码以满足他们的特定需求,如果选择分发修改后的软件,他们亦无需公开这些更改。这种灵活性使 FreeBSD 成为企业和开发人员的理想选择,尤其是在需要可定制且具有成本效益的基础平台时。公司可以利用 FreeBSD 的稳定性和性能来支撑其基础设施,而不受 GPL 的约束;开发人员则可以自由修改代码,创建定制化的解决方案,而不必担心许可的限制。

    卓越性能

    FreeBSD 在网络密集型环境中表现优异,提供了高效的网络性能和出色的 CPU 利用率的结合。这使其成为需要最大网络吞吐量和响应性的应用程序和部署的理想选择。

    经 FreeBSD 优化的 TCP/IP 堆栈是其强大性能的核心。其简化的设计提供了低延迟和卓越的响应时间,特别是在网络流量和输入/输出(I/O)操作方面。这转化为实际应用中的优势,如更快的数据传输、更流畅的流媒体播放和更灵敏的 Web 应用程序。

    进一步提升性能的是 FreeBSD 的轻量级和可扩展的基本系统。与一些体积较大的操作系统不同,FreeBSD 仅包含核心功能所需的基本组件。这种精简的方法带来了几项优势:

    • 启动时间更快: 由于需要初始化的组件较少,FreeBSD 启动速度很快,特别适合需要高可用性和快速恢复的环境。

    • 缩减攻击面: FreeBSD 通过最小化安装的组件数量,缩小了潜在攻击者的攻击面。这减少了系统遭受攻击和恶意软件的风险。

    • 易于定制: 用户可以根据特定需求轻松添加/删除组件。这使得 FreeBSD 可以针对不同的使用场景进行定制,从最简化的服务器安装到具有更广泛应用的功能齐全的桌面环境。

    • 高效的硬件利用率: 精简的基本系统确保了硬件资源的有效利用。这意味着在现代和旧版硬件上都能获得更好的整体性能,使 FreeBSD 成为更多部署场景下的多功能选择。

    Z 文件系统 (ZFS)

    ZFS 是一款大容量、容错的文件系统,为 FreeBSD 带来了多个性能优势。ZFS 的一些关键特点包括:

    • 池化存储:通过将多个磁盘合并为一个存储池,简化了存储管理。

    • 数据完整性:通过端到端的校验和确保数据完整性,能够检测并修正静默数据损坏。

    • 快照与克隆:支持快速高效的文件系统快照和克隆,用于备份和复制目的。

    • 可扩展性:能够有效扩展以支持大量数据和存储设备,适用于企业环境。

    bhyve 虚拟化

    bhyve 是 FreeBSD 原生的虚拟化程序,为用户提供了一种强大而高效的虚拟化解决方案。bhyve 的主要特点包括:

    • 轻量级与灵活性:设计轻量且高度灵活,适用于多种虚拟化需求。

    • 虚拟机支持多种操作系统:虚拟机可以运行多种操作系统,包括 FreeBSD、Linux 和 Windows。

    • 高效的资源利用:优化资源使用,确保虚拟机以最低的开销高效运行。

    • 与 FreeBSD 的集成:与 FreeBSD 基础系统无缝集成,提供一致的虚拟化体验。

    海量的软件包 Port

    通过 Port 软件包,FreeBSD 为用户提供了海量的软件应用。Ports 由 FreeBSD 项目自己维护着,有 30,000 款余应用,涉及包括 Web 服务器、数据库、桌面环境和开发工具等多个类别。

    pkg 包管理器 简化了从 Ports 安装软件 的流程。与其他系统中可能出现的复杂且易错的依赖管理不同,pkg 会自动处理所有依赖关系,确保用户能够快速高效地安装所需软件,无需担心依赖冲突和错误。

    安全性与稳定性

    安全性是 FreeBSD 哲学的核心原则之一。开发者在设计和开发过程中优先考虑安全性,以最小化攻击面并实施强大的访问控制。以下几个关键特性有助于 FreeBSD 强大的安全性:

    • 最小特权:服务以最小权限运行,限制了安全漏洞发生时可能带来的损害。这种隔离方法限制了被攻破服务对系统其他部分的影响。

    • 单一代码库开发:FreeBSD 项目将整个核心操作系统开发在单一的代码库中。这种集中式方法简化了安全维护,减少了必须监控和修补的外部组件数量。

    • 关注代码质量:FreeBSD 开发者在开发过程中高度重视代码质量和安全最佳实践。这种主动的方法有助于在漏洞被利用之前识别并缓解潜在的安全问题。

    除了核心安全措施外,FreeBSD 还提供了一些独特的功能,进一步增强了系统安全性:

    • Jail:Jail 提供了一种强大的机制,可以在操作系统内创建隔离的虚拟环境。这些环境作为独立的服务器运行,具有有限的资源和文件系统访问权限。隔离性有助于防止安全漏洞蔓延到系统的其他部分或危及主机操作系统本身。Jail 为需要强隔离的场景提供了传统全虚拟化的轻量级替代方案。

    • Capsicum:Capsicum 为开发者提供了一个有价值的安全框架,允许他们创建在受限沙箱环境中运行的应用程序。Capsicum 强制执行安全策略,限制应用程序的功能,从而大大减少了代码中漏洞可能带来的影响。

    • CheriBSD:CheriBSD 是 FreeBSD 的扩展,提供了先进的内存保护功能。通过实施硬件辅助的内存保护机制,CheriBSD 使得攻击者更难以利用系统漏洞。这种增强的保护级别对于安全关键的应用程序尤为重要。

    FreeBSD 采用严格且安全的构建过程,以确保操作系统的完整性和可信度。这个多方面的方法包含了几个关键原则:

    • 隔离与封闭:构建环境与外部网络及其他潜在干扰源隔离。这有助于防止在构建过程中注入恶意代码,并确保系统的完整性。

    • 最小外部依赖:构建过程主要依赖内部工具和资源,减少了通过第三方软件引入的漏洞风险。

    • 源代码验证:所有进入构建过程的代码都经过严格验证,以确保其真实性和完整性。这有助于识别并防止未经授权的修改或恶意代码的加入。

    • 一致性与可重现性:构建环境设计为稳定和可预测的。能检测到任何异常或不规则性,从而识别潜在的安全问题。可重现的构建过程还确保源代码始终生成相同的二进制输出,便于验证和审计。

    稳定性与进步的完美结合:可预测的升级

    FreeBSD 在稳定性与进步之间达到了完美的平衡。新特性会谨慎地集成到版本中,并经过严格的测试,确保在生产环境中的完美运行。这种对稳定性的承诺使 FreeBSD 成为开发和部署关键系统的可信选择。

    最小惊讶原则(POLA)是这一方法的指导思想。POLA 确保系统升级和变更不会破坏现有的功能或工作流程。在 FreeBSD 中,这一原则的应用方式如下:

    • 一致的用户体验:升级旨在保持熟悉的用户体验。用户可以期待最小的工作流程中断,避免由于不可预见的变化而浪费时间进行适应。

    • 可预测的系统行为:系统组件和工具遵循既定的约定,始终如一。这种可预测性使得用户更容易理解系统的行为,并有效地与系统进行互动。

    • 清晰的沟通:FreeBSD 开发者重视清晰透明的沟通。详细的发布说明和文档会通知用户即将发生的变更及其潜在影响。这种透明度使得用户能够做好升级准备,并进行必要的调整。

    • 以用户为中心的设计:FreeBSD 的开发过程积极寻求用户反馈,确保变更与用户的期望一致。这种关注最小化了在升级过程中用户遇到的不必要的复杂性和惊讶。

    FreeBSD 的升级过程简单且无痛,即使是重大版本升级也是如此。系统设计上确保升级过程流畅,最小化停机时间和复杂性。以下是 FreeBSD 升级过程中非常友好的几个特点:

    • 可预测且一致:升级旨在可预测且一致,确保系统功能在整个过程中保持不变。

    • 最小的停机时间:升级过程优化了最小的停机时间,非常适合那些需要持续运行的生产环境。

    • 简单执行:通常升级仅需执行几个命令即可完成。丰富的文档和用户指南可以在整个过程中为用户提供帮助。

    • 向后兼容性:FreeBSD 优先考虑向后兼容性。现有的应用程序和配置在升级后依然可以正常运行,减少了系统管理员的中断和重复工作。

    • 严格测试:每个版本都会经过广泛的测试,确保在问题进入用户环境之前就被发现和解决。

    • 快照与回滚:通过 ZFS,用户可以在升级前创建系统快照。如果在升级过程中出现不可预见的问题,可以轻松回滚到之前的状态。

    • 安全更新集成:升级机制无缝集成了定期的安全补丁和更新。这确保了系统在引入最新功能和改进的同时,也能防御最新的安全威胁。

    总结

    FreeBSD 提供了性能、安全性、稳定性、灵活性和支持性社区的完美结合。其宽松的许可使其成为各类企业和开发者的成本效益高的选择。无论你是寻求大规模部署可靠基础的经验丰富的系统管理员,还是寻求强大、安全操作系统的开源新手,FreeBSD 都值得考虑。凭借其对安全、稳定性和对用户社区的强烈承诺,FreeBSD 成为其他操作系统的可行替代方案,并继续为全球关键基础设施提供动力。

    为 FreeBSD 项目做贡献

    无论是通过指导、推广 FreeBSD,还是参与论坛和邮件列表,你的努力都推动着 FreeBSD 项目的创新与发展。今天就加入我们的充满活力的社区,通过帮助建设这个长期发展且不断壮大的开源生态系统来支持 FreeBSD 项目!通过 改进文档、处理 错误报告、提交代码 和 参与讨论,来提升 FreeBSD。每份贡献,不论大小,都有助于使 FreeBSD 变得更加稳定、安全和高效。

    关于 FreeBSD 基金会

    FreeBSD 基金会是一家 501(c)(3) 非营利组织,致力于支持 FreeBSD 项目和社区。接受个人和企业捐赠,基金会将资金用于开发新特性、雇佣软件工程师、改善构建和测试基础设施、通过线上和线下活动推广 FreeBSD,并提供培训和教育材料。作为 FreeBSD 项目的法律事务代表,基金会是合同、许可和其他法律安排的公认实体,完全依赖捐赠资金支持。了解更多信息,请访问 freebsdfoundation.org。

    Why You Should Use FreeBSD
    FreeBSD

    所属机构:塔斯马尼亚州政府总理与内阁部

  • 澳大利亚塔斯马尼亚

  • 摘要

    伯克利软件发行版(BSD)在 Unix 操作系统的发展过程中具有深远的影响。本文回顾了伯克利所做工作的若干成果、在 System V 第四版发布背景下伯克利 Unix 所处的位置,以及在“无版权负担”的 Unix 发布之后 BSD 的未来。

    历史

    最初,Unix 被创造了。这让许多人感到非常高兴,并被广泛认为是个正确的决定。

    ——节选自道格拉斯·亚当斯的《宇宙尽头的餐厅》(轻微改动)

    Unix 诞生于 1969 年,美国新泽西州默里山的贝尔电话实验室。当时,Multics 系统的开发者之一 Ken Thompson 决定创建一个良好的编程环境。Unix 最初是在一台闲置的 DEC PDP-7 上开发的,很快就引起了人们的兴趣,Dennis Ritchie 随后加入了 Thompson 的工作,并将操作系统移植到了更新的 DEC PDP-11 上。

    为了顺利过渡到 PDP-11,这次移植重写了操作系统的大部分代码,使用的是 Ritchie 的新语言——C 语言。向 C 语言的迁移被认为是使这个新操作系统取得成功的关键步骤之一。

    当时的惯例是为特定处理器架构专门开发操作系统,并且为了最大限度发挥硬件性能,往往要用汇编语言编写大量代码。而 C 语言的不同之处在于,它作为高级语言,不仅足够强大,能够实现高级数据结构和逻辑抽象,又足够底层,可以直接访问硬件资源。而且它本身足够简单,编译器也容易移植到新架构上。Unix 的 C 实现只保留了约 3% 的汇编代码,其余都用 C 实现,并提供了对应的桩函数(stub routines)。

    Unix 在贝尔实验室以“研究版本”(Research Edition)的形式持续开发,到 1976 年中期,已经发展到第六版。此时 AT&T 开始以极低成本向研究机构提供操作系统源代码。这一举措使这些机构可以自由修改 Unix 内核,添加新功能或调整已有功能。

    1978 年,AT&T 发布了第七版 Unix,并将其移植到了 DEC VAX 系统上,这个版本被称为 32V。这是贝尔实验室发布的最后一批研究版本。从这时起,Unix 分裂为三条主要的发展路线。

    随着第七版的发布,研究组将分发工作移交给 AT&T 新成立的 Unix 支持小组(Unix Support Group),后者逐渐演变为今天的 Unix System Laboratories(USL,Unix 系统实验室),即当前 Unix 操作系统的所有者。同时,第七版发布后,加州大学伯克利分校也开始正式投入 Unix 的开发。伯克利在第六版 Unix 上早已有部分工作成果,这些成果后来被整合进 1978 年底发布的 3BSD 中。

    第三条 Unix 的发展路线则仍然留在贝尔实验室,继续推动 Research Unix 的演化。从那以后,Unix 的主要版本发布主要来自 USL(及其前身)与伯克利两方。自 System III 起,USL 也将部分来自伯克利的改进整合进其主流产品中,最终在 System V Release 4 中达到顶峰 —— 该版本旨在将 BSD 与 USL 的 Unix 融合为一个统一的标准操作系统。

    伯克利软件发行版(BSD)

    “从托尔斯泰到奇妙仙子,从伯克利走到卡梅尔。”

    ——Paul Simon《Cloudy》中的歌词

    1978 至 1979 年间,加州大学伯克利分校开始了对 Unix 操作系统的研究。全球许多高校研究人员都利用了 AT&T 的慷慨政策 —— 几乎零成本即可获得 Unix 源代码(早期的源码许可证费用约为 100 美元)。

    伯克利的最初成果是为 PDP-11 平台开发的 1BSD 与 2BSD。由于 PDP-11 的内存极为有限,早期的工作受到限制,但内核中做出了一些小规模的效率改进,并加入了一些新程序,其中包括 Bill Joy 编写的、后来广为流传的可视化文本编辑器 vi(出现在 2BSD 中)。

    早期伯克利的开发工作以技术推动为主,研究者需要开发运行在大内存系统上的软件,例如伯克利的 LISP 实现。第七版 Unix 移植至 VAX(即 32V)为伯克利研究者提供了理想的平台 —— VAX 提供了比 PDP-11 更强大的虚拟内存系统,而后者则采用受限的分段结构。

    1978 年,Bill Joy 与 Ozalp Babaoglu 启动了 3BSD 的开发,目标是在传统进程换出机制(process swapping)之外,引入虚拟内存、页替换和按需分页机制。直到 1984 年发布的 SVR2 中,这些特性才出现在 USL 的商业产品中。

    3BSD 的成功引起了美国国防高级研究计划署(DARPA)的注意,后者资助伯克利继续开发,以期为军方承包商提供一套先进的、标准化的 Unix 系统。DARPA 的项目由一个学术界与工业界联合组成的委员会监督,因此诞生了一套在研究与实际需求之间取得平衡的 Unix 实现。借助 DARPA 的资助,伯克利相继推出多个 4BSD 版本 —— 主版本号为偶数的(如 4.0、4.2、4.4)表示功能重大更新,而奇数版(如 4.1、4.3)则主要是修复与性能优化版本。

    4.0BSD 于 1979 年末发布,主要目标是重新设计并实现虚拟内存系统、标准终端与屏幕处理机制、以及支持大量设备驱动程序。其中的屏幕处理机制看似不重要,但在 DARPA 资助背景下却极其关键 —— 承包商面向多样化用户环境开发软件,只有伯克利提供的 termcap(5) 屏幕处理系统可以避免高昂的现场定制成本。

    如前所述,BSD 在虚拟内存的引入方面领先 USL 约五年。虽然 SVR2 最终实现的 VM 系统并非源自伯克利,但其功能也包含了共享内存与信号量。USL 还从伯克利的 termcap 得到启发,设计了功能类似但不兼容的 terminfo 包。

    1980 年底发布的 4.1BSD 虽以维护性更新为主,却引入了作业控制(job control)、运行时自动配置系统(autoconfiguration)以及支持更长符号名的目标文件符号表。自动配置功能最终成为 SVR4 中可动态加载设备驱动的雏形。

    伯克利的自动配置机制为内核中配置的每个设备调用探测函数(probe routine),若检测结果确认设备存在,内核就会配置设备、分配所需缓冲区、建立中断向量等;反之,则不分配系统资源。这使得同一个内核可运行于多种硬件平台,大大减少了对硬件架构的具体了解需求。

    4.2BSD 于 1984 年 2 月发布,引入了可靠信号处理、网络支持、进程间通信机制,以及伯克利快速文件系统(Fast File System,FFS)。该版本的网络实现成为 DARPA Internet 网络架构的参考模型,伯克利实现的 TCP/IP 协议栈至今仍是互联网通信的核心标准。

    快速文件系统不仅极大提升了基于磁盘的文件操作性能,还支持长文件名、最大 2GB 文件大小、多个用户组成员资格等功能。4.2BSD 的信号机制后来成为 IEEE 1003.1 POSIX 标准的参考实现。多个组成员与 BSD 信号处理机制也被 POSIX 委员会采纳。4.2BSD 引入的 socket 模型也成为进程通信与网络通信的事实标准,广泛流传至今。包括 Sun Microsystems 的 SunOS(直至 4.1.3 版本)在内的许多商业 Unix 系统都是基于 4.2BSD。

    4.3BSD 于 1987 年发布,主要是为了解决 4.2BSD 中的问题。此后,4.3BSD 成为伯克利的标准发行版,并衍生出三个小版本:4.3BSD-Tahoe、4.3BSD-Reno 与 4.3BSD-Net/2。最初的 4.3 版本修复了许多问题,尤其是网络部分 —— 4.2BSD 发布时许多网络标准尚未确定,开发者做出了一些后来的实践证明并不成立的假设。

    后续版本加入了对 Computer Console Inc. 处理器的支持,以及其他一些小修复。Reno 版本则对文件系统布局做出重大改动,这些变动使得 BSD 与 SVR4 的顶层目录结构几乎一致。Net/2 版本则重新实现了 Sun Microsystems 的网络文件系统(NFS)并加入对 OSI 网络的支持。

    System V 第四版(SVR4)

    System V Release 4(SVR4)由 USL 于 1989 年发布,是 USL 与 Sun Microsystems 联合开发的成果。SVR4 的发布意在终结长期以来 USL 支持者与 BSD 拥趸之间的“宗教战争”。在 SVR4 发布之前,大多数主流 Unix 厂商都以 BSD 或 System V 之一为基础构建自家产品。这两大系统之间的差异显著,以致于源于其中一方的软件往往无法在另一方系统上直接编译,需作一定修改。

    SVR4 的总体策略似乎是为用户提供环境选择。如果用户偏好伯克利风格,只需将 /usr/ucb 放在路径中 /usr/bin 之前,系统行为就会类似传统 BSD。反之,偏好 System V 风格的用户可以将 /usr/bin 放在 /usr/ucb 前,以获得他们熟悉的 System V 环境。

    SVR4 与 BSD 的最大区别主要体现在系统管理员的体验上。大多数 BSD 管理任务只需编辑文本文件并向守护进程发送信号;而 System V 的传统则要求使用某种管理 shell 或者在 shell 中输入繁复的多参数命令。对普通用户而言,从 BSD 转向 SVR4 不会有太大变化,但系统管理员将面临显著差异。

    如今,大多数 Unix 厂商已承诺支持 SVR4。许多人认为 BSD 系的 Unix 不再有未来。从某种意义上讲,这是事实 —— 想要在商业 Unix 世界中竞争的厂商必须支持 SVR4。然而,对普通用户而言,SVR4 仍是一项昂贵的选择:一份无限用户数的 SVR4 许可证价格不少于 2,000 美元,加上支持和升级费用,其软件成本可能超过运行它的硬件。SVR4 通常被视为面向商业的、正规化的操作系统,而 BSD 传统上则面向学术用户与“黑客”。

    对于运行商业软件(如数据库服务器)并要求高可用性的组织而言,SVR4 是必然选择。然而,组织中还有许多任务并不需要如此昂贵的系统 —— 例如传统由 BSD 系统处理的邮件服务、新闻服务,或低成本的 X 终端系统等场景。BSD 的救星,可能正是自由 Unix 的兴起。

    自由的 Unix

    1991 年 12 月和 1992 年 2 月,Unix 世界发生了可能具有革命性影响的两件大事:两个完全自由可再分发的 Unix 系统相继发布。

    第一个是 Linux,由芬兰赫尔辛基大学学生 Linus Torvalds 从零开始开发。最初只是模仿 System V Release 2 的简单任务切换器,Linux 很快发展成一款支持网络和 X Window 的完整操作系统。

    第二个来自 William Jolitz,他宣布将 4.3BSD-Net/2 移植到 Intel 386 平台,提供完整无版权限制的源代码。Jolitz 曾为伯克利开发并贡献了 BSD 的 386 实现,并被包含进 Net/2。然而,Net/2 中仍含有一些 USL 的专有代码,因此不能完整再分发,除非拥有 USL 的源代码许可证。Jolitz 的做法是:取出 Net/2 中无版权负担的部分,再加入足够组件,构建出一个独立操作系统 —— 并免费提供。

    发布后的反响热烈。虽然首个版本(386BSD 0.0)极不稳定,但不久后便推出了改进版 386BSD 0.1。该软件易于获取,源代码开放,很快吸引了大量用户社群开始改进。386BSD 基于 BSD Net/2,内建网络支持、快速文件系统(FFS)和 NFS,绝大多数公开软件都能轻松移植 —— X Window 几乎在发布初期就已可用。

    386BSD 发布后,出现了多个分支项目,各自目标不同:

    • William Jolitz 继续开发 386BSD 0.2,作为研究性版本,计划引入动态共享库、可动态加载设备驱动等功能;

    • FreeBSD 项目则以打造稳定产品为目标,整合最新编译器与应用程序,通过网络和光盘提供易于安装的发行版;

    • NetBSD 项目则定位在研究与稳定之间,致力于协作开发,并通过网络提供频繁快照更新。

    除了这些专注 Intel 平台的项目外,还有多个团队致力于向其他平台移植,如 Motorola 68000、SPARC 以及 HP-900 系列机器。

    结语

    伯克利大学的计算机系统研究小组(CSRG)已宣布,4.4BSD 将是该校最后一次发行 BSD。其主要原因之一是缺乏企业资助 —— 绝大多数 Unix 厂商如今已拥有自家完善的研发团队。

    随着 Unix 厂商全面转向商业化,System V Release 4 已成为 1990 年代的标准 Unix 实现。未来,大型厂商不太可能再回头支持 BSD。然而,像 Sun Microsystems 这类长期支持 BSD 的公司,在推动用户迁移至 SVR4 时仍面临一定阻力。事实上,Sun 当前的 BSD 系统(4.1.3)比其 SVR4 系统更稳定,因此 Sun 很可能在一段时间内仍继续支持其 BSD 系列。

    但由于 BSD 的自由再分发实现仍在持续发展,伯克利的传统仍将在 Unix 社区中延续。源代码可得的操作系统保证了操作系统设计的学生能够继续学习与改进 BSD。这样一个功能完备、自由且由社区支持的系统,在普通硬件上运行良好,几乎可以确保 BSD Unix 在非关键任务场景中 —— 如邮件与新闻服务、低成本 X 支持、打印服务等 —— 将继续发挥重要作用。可以肯定地说,我们还没有听到 Berkeley Software Distributions 的最后消息。

    [email protected]
    姓名: Jake Freeland

    问:请简要介绍一下你自己以及你的教育经经历。

    我自记事起就对计算机硬件感兴趣。这一特点自然而然地将我引向了操作系统,这是最接近硬件的软件。我现在是明尼苏达大学双城分校的学生,计划于 2023 年 12 月取得计算机科学学士学位。

    问:你做过多少个实习?

    我曾在 2022 年代表谷歌编程之夏计划与 FreeBSD 基金会合作过一次。

    问:为什么你想要为 FreeBSD 基金会工作?

    当我开始寻找实习机会时,FreeBSD 就立刻出现在我的脑海中。我之前有作为系统管理员的经验,而 FreeBSD 是我最喜欢的操作系统之一。我知道他们的社区非常专业,我认为为该项目做贡献将是迈向内核开发的绝佳途径。

    问:你希望从这个实习中学到什么?

    我的 FreeBSD 经验教会了我如何处理大型代码库。我对遍历他们的 src 源码感到自如,也习惯将我的代码更改格式化为可审查的提交/补丁。与 Capsicum 安全沙盒一起工作也教会了我以安全为重进行思考。我觉得我已经积累了足够的直觉来检测和审计可能存在重大安全问题的代码。

    问:你目前正在做什么?

    我开始时的实习任务是扩展 FreeBSD 的 ktrace 工具中的能力违规跟踪功能。通过我的更改,开发人员可以在程序不在能力模式下时跟踪和收集详细的能力违规诊断信息。

    接下来,我将 FreeBSD 的系统日志实用程序 syslogd 隔离到了一个 Capsicum 安全沙盒中。syslogd 守护程序以 root 权限运行,因此是安全攻击的高风险目标。将 syslogd 放入沙盒环境中应该可以在出现 syslogd 安全漏洞的情况下防止有害影响。通过这一经验,我创建了一个关于使用 Capsicum 沙盒化程序的操作指南:https://cdaemon.com/posts/capsicum。

    问:到目前为止,你在 FreeBSD 的体验如何?

    我很享受与 FreeBSD 基金会一起工作(的过程),并计划继续为该项目做出贡献。我很高兴看到基金会认识到她需要更多年轻的开发者;我将与他们合作推出一个新的项目,以向大学生介绍 FreeBSD。

    Meet FreeBSD Foundation 2023 Summer Intern: Jake Freeland
    计算器
  • configure

  • build

  • install

  • clean

  • deinstall / reinstall

  • makesum / makepatch

  • Ports 的 Makefile 模板
    Mk/bsd.port.mk
    make(1)
    FreeBSD port 日语开发者手册
    FreeBSD Port 开发者手册
    Electron 是一款流行的框架,可用于使用 HTML、CSS 和 JavaScript 等 Web 技术开发桌面应用程序。基于 Electron 构建的应用程序有很多(无论开源还是闭源),可以在以下网站找到一些例子:
    • Electron Apps

    • Awesome Electron

    在 Wanted Ports 列表中待了一段时间后,Electron 于 2019 年 5 月正式进入 FreeBSD 的 Ports,目前支持两个主要版本(4 和 6)。自那以后,两款基于 Electron 的应用程序——Visual Studio Code 和 Atom(恰好都是代码编辑器)——已进入 Ports。

    如果你查看这些 ports,会发现它们包含冗长的 Makefile 和大量的补丁文件。因此,你可能会认为移植基于 Electron 的应用程序是件繁琐的工作。然而,事实并非如此。这两个编辑器属于特例,移植基于 Electron 的应用程序通常比你想象的要简单。

    借助一些 辅助 Makefile(仍在开发中),你可以通过编写不到 100 行的 Makefile 和一些配套文件来创建一个 port。

    在这篇文章中,我将介绍如何使用这些 .mk 文件来移植基于 Electron 的应用程序。我选择了一个简单但仍然实用的应用程序 YouTube Music Desktop 作为示例。

    准备工作

    在开始移植之前,我们需要进行一些准备工作。首先,我们需要获取关于该应用程序的信息,例如:

    • 该应用程序所依赖的 Electron 版本,

    • 构建该应用程序所需的 Node 版本,

    • 构建该应用程序所需的 Node 包管理器。

    应用程序的源代码归档文件中的 README 文档/ package.json 文件通常会提供这些信息。让我们下载该归档文件并查看内容。

    • Electron 版本 —— Electron 通常被指定为应用程序项目的开发依赖项。在 package.json 文件的 devDependencies 部分,我们找到如下行:"electron": "^7.1.11",,因此所需的 Electron 版本为 7。

    • Node 版本 —— 该归档文件中没有找到关于 Node 版本的具体描述。因此,我们假设可以使用所有受支持的 Node 版本。在本例中,我们选择 12 版本。(注意:这只是因为我个人喜欢使用最新的 LTS(长期支持)版本,其他受支持的版本应该也可以正常运行。)

    • 包管理器 —— 应用程序项目通常使用一个文件来锁定所有依赖项(Node 模块)的版本,以确保项目的可复现性。如果存在 package-lock.json 文件,则表示使用的是“NPM”包管理器;而 yarn.lock 文件表示使用的是“Yarn”。在本例中,该归档文件包含了这两个文件,这可能意味着可以使用任意一款包管理器。这里我们选择 NPM 作为包管理器(纯粹是个人决定 :-)。

    总结

    我们将使用以下版本:

    • Electron: 7

    • Node: 12

    • 包管理器:NPM

    还需要进行一步准备工作。如上所述,port 将使用那些仍在开发中的 .mk 文件提供的功能。因此,我们需要获取这些文件并将它们复制到 ports 目录中。

    现在,我们已准备好开始创建 port。

    移植

    注意

    可在 我复刻版 Ports 仓库 中找到完整的 port。如果你想快速查看它的样子,可以前往该链接。

    初始化 port

    首先,初始化 port,例如执行以下命令。(注意:这里使用了 ports-mgmt/porttools。)

    放置 package.json 和锁定文件

    将应用程序源代码归档文件中的 package.json 和 package-lock.json 复制到 port 的 files/packagejsons 目录中。

    为什么需要这样做?

    我认为移植基于 Electron 的应用程序最麻烦的部分是准备分发文件。官方 port 需要能够使用 Poudriere 进行构建,这意味着必须预先下载所有分发文件(包括应用程序依赖的所有 Node 模块),并使用校验和文件 (distinfo) 验证其完整性。

    使用 NPM 的项目会在 package.json 和 package-lock.json 中指定所有模块依赖项。辅助 .mk 文件利用这些文件来“预获取”应用程序所需的所有 Node 模块,并将它们打包成一个归档文件,以便进行校验和验证。

    因此,你无需手动处理 Node 模块的分发文件。Ports 基础设施会在执行 make makesum 时自动处理这些 Node 模块的命名、获取和校验。

    编写 Makefile

    现在,让我们来编写 Makefile。我只会介绍与 Electron 相关的部分。完整的 Makefile 请参考 我的复刻版仓库。

    我们需要指定三个重要的变量:USES、USE_NODE 和 USE_ELECTRON。首先来看 USES 和 USE_NODE。通过定义这两个变量,指定的 Electron 版本、Node 版本以及包管理器会被自动添加到必要的依赖项中。

    接下来的 USE_ELECTRON 变量涉及提供的核心功能,因此我会详细解释这些特性。

    • prefetch —— 如果在 ${DISTDIR} 目录中找不到分发文件,则在 fetch 阶段会使用预存的 package.json 和 package-lock.json 下载应用程序所依赖的所有 Node 模块。下载的 Node 模块会被打包成一个自动命名的 tar 文件,作为 DISTFILES 之一。

      • PREFETCH_TIMESTAMP —— 如果使用 prefetch 功能,则必须定义此变量。该变量是时间戳,会赋值给 tar 归档中的所有目录、文件和链接,以确保归档文件的可复现性。你可以使用命令 date '+%s' 获取一个合适的值。

    • extract —— 在 extract 阶段,将预获取的 Node 模块安装到 port 的工作源码目录中。

    • prebuild —— 在 build 阶段,会针对指定版本的 Node 重新编译本机 Node 模块,使其能够被 Node 执行,以便构建应用程序。此外,该功能还会在应用程序打包之前,针对指定版本的 Electron 重新编译本机 Node 模块。

    简单来说,这三个特性将 npm install 过程拆分为三个阶段,使其适用于 port 构建流程。

    最后一个特性与应用程序的打包有关,它会生成可分发的应用程序形式。根据 官方文档,常见的打包工具包括:

    • electron-forge

    • electron-builder

    • electron-packager

    当前,该特性支持 electron-builder 和 electron-packager(分别对应 build:builder 和 build:packager)。

    打包工具通常被指定为开发依赖项。查看 package.json 文件的 devDependencies 部分,我们可以找到如下行:

    这表明该应用程序依赖于 electron-builder。

    我们已经快要完成了,但还有最后一件事要做。安装阶段的准备工作是最繁琐的部分。你需要从零开始编写安装目标,主要涉及以下几个步骤:

    • 为应用程序创建一个包装脚本;

    • 为应用程序创建 .desktop 入口文件;

    • 生成应用程序图标(除非源代码归档中已经包含了图标);

    • 在 Makefile 中编写 do-install 目标。

    包装脚本的模板可能如下所示:

    在 do-install 目标中,手动安装创建的包装脚本、.desktop 文件和图标。此外,不要忘记将打包工具生成的应用程序资源目录复制到 ${DATADIR}。

    构建

    最后,我们已经准备好构建这个 port 了。

    此外,我们仍然需要 pkg-descr 和 pkg-plist 文件来打包该应用程序。不过,由于这些工作与 Electron 无关,这部分就留给你自行完成了。

    How to port an Electron-based application to FreeBSD
    https://github.com/tagattie/FreeBSD-Electron
    inet autoconf
    inet6 2a01:4f8:cafe:cafe::1 72 
    !route add -net ::/0 fe80::1%vio0
    sh /etc/netstart vio0
    ping6 google.com
    net.inet.ip.forwarding=1
    net.inet6.ip6.forwarding=1
    sysctl net.inet.ip.forwarding=1
    sysctl net.inet6.ip6.forwarding=1
    openssl rand -base64 32
    172.14.0.1/24 wgport 51820 wgkey YUkS6cNTyPbXmtVf/23ppVW3gX2hZIBzlHtXNFRp80w=
    inet6 2a01:4f8:cafe:cafe:100::1 72
    sh /etc/netstart wg0
    ifconfig wg0
    wg0: flags=80c3<UP,BROADCAST,RUNNING,NOARP,MULTICAST> mtu 1420
    	index 5 priority 0 llprio 3
    	wgport 51820
    	wgpubkey xxxxxxxxxxxxxxx=
    	groups: wg
    	inet 172.14.0.1 netmask 0xffffff00 broadcast 172.14.0.255
    	inet6 2a01:4f8:cafe:cafe:100::1 prefixlen 72
    #!/bin/sh
    #
    
    # this is normally run once per day via /etc/daily.local.
    #
    
    echo updating Spamhaus DROP lists:
    (
      { ftp -o - https://www.spamhaus.org/drop/drop.txt && \
        ftp -o - https://www.spamhaus.org/drop/dropv6.txt ; \
      } 2>/dev/null | sed "s/;/#/" > /var/db/drop.txt
    )
    pfctl -t spamhaus -T replace -f /var/db/drop.txt
    chmod a+rx /usr/local/sbin/spamhaus.sh
    /usr/local/sbin/spamhaus.sh
    pfctl -f /etc/pf.conf
    chmod a+rx /usr/local/sbin/unbound-adhosts.sh
    /usr/local/sbin/unbound-adhosts.sh
    chown -R nobody:nobody /var/unbound
    rcctl enable unbound
    rcctl start unbound
    172.14.0.1/24 wgport 51820 wgkey YUkS6cNTyPbXmtVf/23ppVW3gX2hZIBzlHtXNFRp80w=
    inet6 2a01:4f8:cafe:cafe:100::1 72
    wgpeer *client's public key* wgaip 172.14.0.2/32 wgaip 2a01:4f8:cafe:cafe:100::2/128
    sh /etc/netstart wg0
    #!/bin/ksh
    
    /usr/local/sbin/unbound-adhosts.sh
    /usr/local/sbin/spamhaus.sh
    make fetch
    make extract
    make patch
    make build
    make install
    make fetch
     +- make pre-fetch
     +- make do-fetch
     +- make post-fetch
    make extract
     +- make pre-extract
     +- make do-extract
     +- make post-extract
    make patch
     +- make pre-patch
     +- make do-patch
     +- make post-patch
    make configure
     +- make pre-configure
     +- make do-configure
     +- make post-configure
    make build
     +- make pre-build
     +- make do-build
     +- make post-fetch
    make install
     +- make pre-install
     +- make do-install
     +- make post-install
    make -V_FETCH_SEQ
    make -V_FETCH_REAL_SEQ
    make -dl
    fetch https://github.com/ytmdesktop/ytmdesktop/archive/v1.8.2.tar.gz
    tar -xzf v1.8.2.tar.gz
    less ytmdesktop-1.8.2/package.json
    git clone https://github.com/tagattie/FreeBSD-Electron.git
    cp FreeBSD-Electron/Mk/Uses/*.mk ${PORTSDIR}/Mk/Uses
    cd ${PORTSDIR}
    port create multimedia/ytmdesktop
    cd multimedia/ytmdesktop
    mkdir -p files/packagejsons
    cp /path/to/archive/ytmdesktop-1.8.2/package*.json files/packagejsons
    USES=           electron:7 node:12,build
    USE_NODE=       npm
    USE_ELECTRON=   prefetch extract prebuild build:builder
    PREFETCH_TIMESTAMP=     1582793516
    "electron-builder": "^21.2.0"
    #! /bin/sh
    
    export NODE_ENV=production
    export ELECTRON_IS_DEV=0
    
    electron%%ELECTRON_VER_MAJOR%% %%DATADIR%%/resources/app.asar $@
    do-install:
            # 将包装脚本、.desktop 入口文件和图标安装到适当位置
            # (此处省略部分代码)
            # 安装应用程序数据目录到 ${DATADIR}
            ${MKDIR} ${STAGEDIR}${DATADIR}
            cd ${WRKSRC}/dist/linux-unpacked && \
                    ${COPYTREE_SHARE} resources ${STAGEDIR}${DATADIR}
    make makesum # 生成 distinfo
    make build
    该属性不可继承。——整理者加
    zfsprops(7)
    https://is.gd/BECTL
    bsdinstall(8)
    df(1)
    Other FreeBSD Version in ZFS Boot Environment
    https://docs.ansible.com/ansible/latest/os_guide/intro_bsd.html
    https://blog.andreev.it/2021/02/ansible-quick-start-guide-for-freebsd-centos-and-ubuntu/
    https://wiki.freebsd.org/Puppet/GettingStarted/

    ZFS 启动环境中的其他 FreeBSD 版本

    • 发布时间:2021/10/19

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    FreeBSD 12.3-PRERELEASE 的首批快照终于 了。这意味着我们能在一个新的 ZFS 启动环境中尝试它们,而无需打扰当前运行的 13.0-RELEASE 系统。我们无法像平常那样从当前 ZFS 启动环境创建新的启动环境并将其升级到新版本,因为 12.3 的主版本比 13.0 还要旧(译注:旧版 FreeBSD 不识别新版的 ZFS)。

    在 FreeBSD 发布流程中,这有点悖论:当 12.3-RELEASE 发布时,它可能包含一些比今年早些时候发布的 13.0-RELEASE 更新的提交和功能。当然,并非所有提交到 HEAD 的内容都会自动进入 12-STABLE 或 13-STABLE,但大多数都会。只有最大的变更会被限制在 14.0-RELEASE,当然,这大概会在 2022 年中期其发布流程进行时出现。

    FreeBSD 上的高可用 DHCP 服务器

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2018/08

    今天我想分享在 FreeBSD 系统上搭建高可用 DHCP 服务器的方法,但在其他 UNIX 和类 UNIX 系统上也应该一样简单。我将在这里使用最显而易见的选择——Internet Systems Consortium 的实现——ISC DHCP server——它也可以在 FreeBSD Ports 和软件包中获得。

    zroot/tmp
    zroot/usr/home
    zroot/usr/ports
    zroot/usr/src
    zroot/var/audit
    zroot/var/crash
    zroot/var/log
    zroot/var/mail
    zroot/var/tmp
    root@freebsd:~ # zfs set mountpoint=none zroot
    
    root@freebsd:~ # zfs list
    NAME                 USED  AVAIL  REFER  MOUNTPOINT
    zroot                385M  18.5G    96K  none
    zroot/ROOT           383M  18.5G    96K  none
    zroot/ROOT/default   383M  18.5G   383M  /
    zroot/home            96K  18.5G    96K  /home
    zroot/tmp             96K  18.5G    96K  /tmp
    zroot/usr            288K  18.5G    96K  /usr
    zroot/usr/ports       96K  18.5G    96K  /usr/ports
    zroot/usr/src         96K  18.5G    96K  /usr/src
    zroot/var            600K  18.5G    96K  /var
    zroot/var/audit       96K  18.5G    96K  /var/audit
    zroot/var/crash       96K  18.5G    96K  /var/crash
    zroot/var/log        120K  18.5G   120K  /var/log
    zroot/var/mail        96K  18.5G    96K  /var/mail
    zroot/var/tmp         96K  18.5G    96K  /var/tmp
    
    root@freebsd:~ # zfs get canmount
    NAME                PROPERTY  VALUE     SOURCE
    zroot               canmount  on        default
    zroot/ROOT          canmount  on        default
    zroot/ROOT/default  canmount  noauto    local
    zroot/home          canmount  on        default
    zroot/tmp           canmount  on        default
    zroot/usr           canmount  off       local
    zroot/usr/ports     canmount  on        default
    zroot/usr/src       canmount  on        default
    zroot/var           canmount  off       local
    zroot/var/audit     canmount  on        default
    zroot/var/crash     canmount  on        default
    zroot/var/log       canmount  on        default
    zroot/var/mail      canmount  on        default
    zroot/var/tmp       canmount  on        default
    root@freebsd:~ # df -g /usr
    Filesystem         1G-blocks Used Avail Capacity  Mounted on
    zroot/ROOT/default        18    0    18     2%    /
    
    root@freebsd:~ # df -g /var
    Filesystem         1G-blocks Used Avail Capacity  Mounted on
    zroot/ROOT/default        18    0    18     2%    /
    root@freebsd:~ # zfs list
    NAME                 USED  AVAIL  REFER  MOUNTPOINT
    zroot                385M  18.5G    96K  none
    zroot/ROOT           383M  18.5G    96K  none
    zroot/ROOT/default   383M  18.5G   383M  /
    zroot/home            96K  18.5G    96K  /home
    zroot/tmp             96K  18.5G    96K  /tmp
    zroot/usr            288K  18.5G    96K  /usr
    zroot/usr/ports       96K  18.5G    96K  /usr/ports
    zroot/usr/src         96K  18.5G    96K  /usr/src
    zroot/var            600K  18.5G    96K  /var
    zroot/var/audit       96K  18.5G    96K  /var/audit
    zroot/var/crash       96K  18.5G    96K  /var/crash
    zroot/var/log        120K  18.5G   120K  /var/log	
    zroot/var/mail        96K  18.5G    96K  /var/mail
    zroot/var/tmp         96K  18.5G    96K  /var/tmp
    
    root@freebsd:~ # zfs create -o canmount=off -o mountpoint=none zroot/exclude
    
    root@freebsd:~ # zfs rename -u zroot/usr  zroot/exclude/usr
    root@freebsd:~ # zfs rename -u zroot/var  zroot/exclude/var
    root@freebsd:~ # zfs rename -u zroot/home zroot/exclude/home
    root@freebsd:~ # zfs rename -u zroot/tmp  zroot/exclude/tmp
    
    root@freebsd:~ # zfs list
    NAME                      USED  AVAIL  REFER  MOUNTPOINT
    zroot                     385M  18.5G    96K  none
    zroot/ROOT                383M  18.5G    96K  none
    zroot/ROOT/default        383M  18.5G   383M  /
    zroot/exclude            1.16M  18.5G    96K  none
    zroot/exclude/home         96K  18.5G    96K  /home
    zroot/exclude/tmp          96K  18.5G    96K  /tmp
    zroot/exclude/usr         288K  18.5G    96K  /usr
    zroot/exclude/usr/ports    96K  18.5G    96K  /usr/ports
    zroot/exclude/usr/src      96K  18.5G    96K  /usr/src
    zroot/exclude/var         612K  18.5G    96K  /var
    zroot/exclude/var/audit    96K  18.5G    96K  /var/audit
    zroot/exclude/var/crash    96K  18.5G    96K  /var/crash
    zroot/exclude/var/log     132K  18.5G   132K  /var/log
    zroot/exclude/var/mail     96K  18.5G    96K  /var/mail
    zroot/exclude/var/tmp      96K  18.5G    96K  /var/tmp
    root@freebsd:~ # df -g /usr
    Filesystem         1G-blocks Used Avail Capacity  Mounted on
    zroot/ROOT/default        18    0    18     2%    /
    
    root@freebsd:~ # df -g /var
    Filesystem         1G-blocks Used Avail Capacity  Mounted on
    zroot/ROOT/default        18    0    18     2%    /
    root@freebsd:~ # zfs set -u mountpoint=/var/tmp   zroot/exclude/var/tmp
    root@freebsd:~ # zfs set -u mountpoint=/var/mail  zroot/exclude/var/mail
    root@freebsd:~ # zfs set -u mountpoint=/var/log   zroot/exclude/var/log
    root@freebsd:~ # zfs set -u mountpoint=/var/crash zroot/exclude/var/crash
    root@freebsd:~ # zfs set -u mountpoint=/var/audit zroot/exclude/var/audit
    root@freebsd:~ # zfs set -u mountpoint=none       zroot/exclude/var
    
    root@freebsd:~ # zfs set -u mountpoint=/usr/src   zroot/exclude/usr/src
    root@freebsd:~ # zfs set -u mountpoint=/usr/ports zroot/exclude/usr/ports
    root@freebsd:~ # zfs set -u mountpoint=none       zroot/exclude/usr
    
    root@freebsd:~ # zfs list
    NAME                      USED  AVAIL  REFER  MOUNTPOINT
    zroot                     385M  18.5G    96K  none
    zroot/ROOT                383M  18.5G    96K  none
    zroot/ROOT/default        383M  18.5G   383M  /
    zroot/exclude            1.16M  18.5G    96K  none
    zroot/exclude/home         96K  18.5G    96K  /home
    zroot/exclude/tmp          96K  18.5G    96K  /tmp
    zroot/exclude/usr         288K  18.5G    96K  none
    zroot/exclude/usr/ports    96K  18.5G    96K  /usr/ports
    zroot/exclude/usr/src      96K  18.5G    96K  /usr/src
    zroot/exclude/var         612K  18.5G    96K  none
    zroot/exclude/var/audit    96K  18.5G    96K  /var/audit
    zroot/exclude/var/crash    96K  18.5G    96K  /var/crash
    zroot/exclude/var/log     132K  18.5G   132K  /var/log
    zroot/exclude/var/mail     96K  18.5G    96K  /var/mail
    zroot/exclude/var/tmp      96K  18.5G    96K  /var/tmp
    
    root@freebsd:~ # df -g
    Filesystem              1G-blocks Used Avail Capacity  Mounted on
    /dev/gpt/efiboot0               0    0     0     0%    /boot/efi
    devfs                           0    0     0     0%    /dev
    zroot/ROOT/default             18    0    18     2%    /
    zroot/exclude/tmp              18    0    18     0%    /tmp
    zroot/exclude/home             18    0    18     0%    /home
    zroot/exclude/var/log          18    0    18     0%    /var/log
    zroot/exclude/var/tmp          18    0    18     0%    /var/tmp
    zroot/exclude/var/mail         18    0    18     0%    /var/mail
    zroot/exclude/var/crash        18    0    18     0%    /var/crash
    zroot/exclude/var/audit        18    0    18     0%    /var/audit
    zroot/exclude/usr/src          18    0    18     0%    /usr/src
    zroot/exclude/usr/ports        18    0    18     0%    /usr/ports
                                     |
                        ZFS DATASET  |   ZFS MOUNTPOINT => WHY
                                     |
              +-------------------+  |
              | ZFS 'zroot' pool  |  |  /sys            => # zfs set mountpoint=/sys sys
              |     (dataset)     |  |  canmount:on     => # zfs set canmount=on     sys
              +---------+---------+  |
                        |            |
                +-------+-------+    |
                |     ROOT      |    |  (none)          => # zfs set mountpoint=none sys/ROOT
                |   (dataset)   |    |  canmount:on     => # zfs set canmount=on     sys/ROOT
                +-------+-------+    |
                        |            |
                  +-----+-----+      |
                  |  default  |      |  /               => # zfs set mountpoint=/    sys/ROOT/${DATASET}
                  | (dataset) |      |  canmount:noauto => # zfs set canmount=noauto sys/ROOT/${DATASET}
               +--+-----------+      |
               |                     |
               +- @2025-11-11@10:10  |  point-in-time   => # zfs snapshot            sys/ROOT/${DATASET}@2025-11-11@10:10
                  | (snapshot)       |  (read only)        # beadm create            sys/ROOT/${DATASET}@2025-11-11@10:10
                  |                  |
                  +- safe            |  clone           => # zfs clone               sys/ROOT/${DATASET}@2025-11-11@10:10 sys/ROOT/safe
                  | (clone)          |  (writable)         # beadm create -e default@2025-11-11@10:10 safe
                  |                  |
                  +- test            |  clone           => # zfs clone               sys/ROOT/${DATASET}@2025-11-11@10:10 sys/ROOT/test
                    (clone)          |  (writable)         # beadm create -e default@2025-11-11@10:10 test
                                     |
    root@freebsd:~ # beadm list
    BE                  Active Mountpoint  Space Created
    default             NR     /           24.0G 2025-10-08 01:42
    safe                -      -            1.3G 2025-06-10 09:47
    test                -      -            6.4G 2025-08-22 23:02
    
    root@freebsd:~ # zfs list -r -t all zroot/ROOT
    NAME                                                 USED  AVAIL  REFER  MOUNTPOINT
    zroot/ROOT                                          29.8G   154G    96K  none
    zroot/ROOT/default                                   748K   154G  19.5G  /
    zroot/ROOT/default@2025-11-11@10:10                 16.1G      -  24.2G  -
    zroot/ROOT/safe                                        8K   154G  20.5G  /
    zroot/ROOT/test                                      810M   154G  20.9G  /
    
    root@freebsd:~ # beadm list -a
    BE/Dataset/Snapshot                Active Mountpoint  Space Created
    
    default
      zroot/ROOT/default               NR     /           24.0G 2025-10-08 01:42
    
    safe
      zroot/ROOT/safe                  -      -          748.0K 2025-06-10 09:47
        default@2025-11-11@10:10       -      -            1.3G 2025-10-08 01:42
    
    test
      zroot/ROOT/test                  -      -          810.0M 2025-08-22 23:02
        default@2025-11-11@10:10        -      -            5.6G 2025-08-22 23:02
    
    
    root@freebsd:~ # zfs get origin zroot/ROOT/default
    NAME                PROPERTY  VALUE   SOURCE
    zroot/ROOT/default  origin    -       -
    
    root@freebsd:~ # zfs get origin zroot/ROOT/safe
    NAME             PROPERTY  VALUE                                SOURCE
    zroot/ROOT/safe  origin    zroot/ROOT/default@2025-11-11@10:10  -
    
    root@freebsd:~ # zfs get origin zroot/ROOT/test
    NAME             PROPERTY  VALUE                                SOURCE
    zroot/ROOT/test  origin    zroot/ROOT/default@2025-11-11@10:10  -
    
    root@freebsd:~ # zpool get bootfs
    NAME   PROPERTY  VALUE                SOURCE
    zdata  bootfs    -                    default
    zroot  bootfs    zroot/ROOT/default   local
                                            |
                           ZFS DATASET      |       MOUNTPOINT => WHY
                                            |
             +-----------------------+      |
             |    ZFS 'zroot' pool   |      |  /sys            => # zfs set mountpoint=/sys sys
             |     (ZFS dataset)     |      |  canmount:on     => # zfs set canmount=on     sys
             +-----------+-----------+      |
                         |                  |
               +---------+---------+        |
               |       ROOT        |        |  (none)          => # zfs set mountpoint=none sys/ROOT
               |   (ZFS dataset)   |        |  canmount:on     => # zfs set canmount=on     sys/ROOT
               +---------+---------+        |
                         |                  |
          +--------------+----------+       |
          |              |          |       |
     +----+----+ +-------+---+ +----+----+  |
     | default | |  15.0-RC1 | |  12.2   |  |  /               => # zfs set mountpoint=/    sys/ROOT/${DATASET}
     |(dataset)| | (dataset) | |(dataset)|  |  canmount:noauto => # zfs set canmount=noauto sys/ROOT/${DATASET}
     +---------+ +-----------+ +---------+  |
                                            |
    root@freebsd:~ # beadm export 14.3 | mbuffer | ssh 10.26 doas beadm import 14.3.w520
    summary: 30.3 GiByte in 34min 04.8sec - average of 15.2 MiB/s

    关于 FreeBSD 上的 ZFS 文件系统,有一点需要注意。人们常常将“真正的” ZFS 启动环境与它的替代品混淆,比如 Btrfs 快照或 Ubuntu 使用 zsysctl(8) 命令管理的快照。不幸的是,它们只是快照,并非完整的可写克隆(或完整独立的 ZFS 数据集)。它们可以冻结系统状态,从而在更新软件包后能够恢复到工作配置,但你无法像创建另一个独立的 ZFS 启动环境那样,安装其他独立版本的系统作为新的 ZFS 数据集。

    创建新的 ZFS 数据集

    安装 FreeBSD 12.3-PRERELEASE

    安装与主机相同的 Packages

    使用 pkg prime-list,我们可以获取当前运行系统上手动安装的所有 pkg(8) 软件包。你也可以省略此步骤,或者只安装你需要的软件包,而不是全部安装。

    如我们所见,在 FreeBSD 13.0-RELEASE 系统中安装的一些软件包,目前在 FreeBSD 12.3-PRERELEASE 系统的 pkg(8) “latest” 分支中不可用。这种情况有时会发生,例如某些软件包构建失败——但你可以假设这些软件包在一周左右会重新可用,因为 pkg(8) 软件包会在 “latest” 分支中进行重建。

    接下来我们将移除缺失的软件包,并重命名一些在 FreeBSD 12.x 版本中名称可能不同的软件包。

    一个小时左右后,我们的软件包已经安装完成。

    复制配置文件

    现在你可以重启到一个干净且未配置的 FreeBSD 系统,但你也可以从当前正在使用的安装中复制配置文件。以下是我复制的文件。

    首先是来自基本系统 /etc 和 /boot 目录的文件。

    接下来是已安装包在 /usr/local/etc 目录下的配置文件。

    添加用户并设置密码

    现在你应该添加常规用户,并为该用户和 root 账户设置密码。

    重启进入新的 ZFS 启动环境

    现在你可以退出该 ZFS 启动环境的 chroot(8),然后重启。在 FreeBSD loader(8) 菜单中选择 12.3 启动环境。

    测试新系统

    12.3-PRERELEASE 系统对我来说启动正常。我能够登录并像平常一样使用系统。需要注意的一点是 ZFS 池。我有另一个启用了 zstd 压缩的新 ZFS 池,但我无法导入该 ZFS 池,因为 FreeBSD 12.3-PRERELEASE 使用的不是 OpenZFS 2.0,而是 FreeBSD 内部的旧版本 ZFS。

    请记住这一点……但你也可以从 FreeBSD Ports 安装更新的 OpenZFS,这正是我们接下来要做的。

    接下来我们需要修改 /boot/loader.conf 文件。

    重启并再次尝试后,我成功导入了那个更新的 ZFS 池。

    希望你会觉得这篇指南有用。

    欢迎随时提出你的建议。

    更新 1 – 安装更新版本时的注意事项

    本指南撰写时,我尝试在之前使用 FreeBSD 13.0 的系统上安装 FreeBSD 12.3,因此无需更新 bootcode。我刚在同一台 13.0 系统上尝试安装 13.1,这时需要执行以下两个步骤来更新 bootcode。

    UEFI

    对于 UEFI 分区,你需要从 13.1 安装中复制 /boot/loader.efi 文件,即 /var/tmp/13.1 目录。使用的命令如下。

    BIOS

    对于以传统 BIOS 模式启动的系统,你需要使用以下 gpart(8) 命令。

    由于 FreeBSD 通常安装为 BIOS+UEFI 启动模式兼容,因此这两个步骤都需要执行。

    Other FreeBSD Version in ZFS Boot Environment
    可用
    host # beadm list
    BE             Active Mountpoint  Space Created
    13.0.w520      NR     /           12.8G 2021-09-14 17:27
    13.0.w520.safe -      -            1.2G 2021-10-18 10:01
    
    host # zfs list -r zroot/ROOT
    NAME                        USED  AVAIL     REFER  MOUNTPOINT
    zroot/ROOT                 12.8G  96.8G       88K  none
    zroot/ROOT/13.0.w520       12.8G  96.8G     11.6G  /
    zroot/ROOT/13.0.w520.safe     8K  96.8G     11.1G  /
    
    host # zfs create -o mountpoint=/ -o canmount=off zroot/ROOT/12.3
    
    host # beadm list
    BE             Active Mountpoint  Space Created
    13.0.w520      NR     /           12.8G 2021-09-14 17:27
    13.0.w520.safe -      -            1.2G 2021-10-18 10:01
    12.3           -      -           96.0K 2021-10-18 13:14
    host # beadm mount 12.3 /var/tmp/12.3
    Mounted successfully on '/var/tmp/12.3'
    
    host # beadm list
    BE             Active Mountpoint     Space Created
    13.0.w520      NR     /              12.8G 2021-09-14 17:27
    13.0.w520.safe -      -               1.2G 2021-10-18 10:01
    12.3           -      /var/tmp/12.3  96.0K 2021-10-18 13:14
    
    host # curl -o - https://download.freebsd.org/ftp/snapshots/amd64/12.3-PRERELEASE/base.txz \
             | tar --unlink -xpf - -C /var/tmp/12.3
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  173M  100  173M    0     0  1889k      0  0:01:33  0:01:33 --:--:-- 2228k
    
    host # exa -1 /var/tmp/12.3
    bin
    boot
    dev
    etc
    lib
    libexec
    media
    mnt
    net
    proc
    rescue
    root
    sbin
    tmp
    usr
    var
    COPYRIGHT
    sys
    
    host # curl -o - https://download.freebsd.org/ftp/snapshots/amd64/12.3-PRERELEASE/kernel.txz \
             | tar --unlink -xpf - -C /var/tmp/12.3
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 43.3M  100 43.3M    0     0  1733k      0  0:00:25  0:00:25 --:--:-- 1663k
    
    host # exa -lh /var/tmp/12.3/boot/kernel/kernel
    Permissions Size User Date Modified    Name
    .r-xr-xr-x   37M root 2021-10-14 06:31 /var/tmp/12.3/boot/kernel/kernel
    
    host # curl -o - https://download.freebsd.org/ftp/snapshots/amd64/12.3-PRERELEASE/lib32.txz \
             | tar --unlink -xpf - -C /var/tmp/12.3
    
    host # exa -ld /var/tmp/12.3/usr/lib32
    drwxr-xr-x - root 2021-10-18 13:45 /var/tmp/12.3/usr/lib32
    host # pkg prime-list > /var/tmp/12.3/pkg.prime-list
    
    host # chroot /var/tmp/12.3 /bin/sh
    
    (BE) # export PS1="BE # "
    
    BE # mount -t devfs devfs /dev
    
    BE # sed -i '' s/quarterly/latest/g /etc/pkg/FreeBSD.conf
    
    BE # pkg install -y $( cat pkg.prime-list )
    Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:12:amd64/latest, please wait...
    Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
    Installing pkg-1.17.2...
    Extracting pkg-1.17.2: 100%
    Updating FreeBSD repository catalogue...
    Fetching meta.conf: 100%    163 B   0.2kB/s    00:01
    Fetching packagesite.pkg: 100%    6 MiB   1.3MB/s    00:05
    Processing entries: 100%
    FreeBSD repository update completed. 31294 packages processed.
    All repositories are up to date.
    Updating database digests format: 100%
    pkg: No packages available to install matching 'chromium' have been found in the repositories
    pkg: No packages available to install matching 'drm-fbsd13-kmod' have been found in the repositories
    pkg: No packages available to install matching 'geany-gtk2' have been found in the repositories
    pkg: No packages available to install matching 'ramspeed' have been found in the repositories
    pkg: No packages available to install matching 'vim-console' have been found in the repositories
    BE # sed -i '' \
             -e s/drm-fbsd13-kmod/drm-kmod/g \
             -e s/geany-gtk2/geany/g \
             -e s/vim-console/vim-tiny/g \
             pkg.prime-list
    
    BE # pkg install -y $( cat pkg.prime-list | grep -v -e chromium -e ramspeed )
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 1072 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            (...)
    
    Number of packages to be installed: 1072
    
    The process will require 11 GiB more space.
    2 GiB to be downloaded.
    (...)
    
    BE # rm pkg.prime-list
    BE # pkg stats
    Local package database:
            Installed packages: 1073
            Disk space occupied: 11 GiB
    
    Remote package database(s):
            Number of repositories: 1
            Packages available: 31294
            Unique packages: 31294
            Total size of packages: 96 GiB
    host # for I in /boot/loader.conf        \
                    /etc/ttys                \
                    /etc/rc.conf             \
                    /etc/rc.local            \
                    /etc/sysctl.conf         \
                    /etc/hosts               \
                    /etc/ethers              \
                    /etc/fstab               \
                    /etc/jail.conf           \
                    /etc/make.conf           \
                    /etc/src.conf            \
                    /etc/devfs.rules         \
                    /etc/exports             \
                    /etc/resolv.conf         \
                    /etc/localtime           \
                    /etc/pf.conf             \
                    /etc/resolv.conf         \
                    /etc/profile             \
                    /etc/csh.cshrc           \
                    /etc/wpa_supplicant.conf \
                    /etc/freebsd-update.conf \
                    /etc/motd.template       \
                    /etc/motd                \
                    /var/cron/tabs/*
           do
             cp "${I}" /var/tmp/12.3/"${I}"
             echo "${I}"
           done
    /boot/loader.conf       
    /etc/ttys               
    /etc/rc.conf            
    /etc/rc.local           
    /etc/sysctl.conf        
    /etc/hosts              
    /etc/ethers             
    /etc/fstab              
    /etc/jail.conf          
    /etc/make.conf          
    /etc/src.conf           
    /etc/devfs.rules           
    /etc/localtime          
    /etc/pf.conf            
    /etc/resolv.conf        
    /etc/profile            
    /etc/csh.cshrc          
    /etc/wpa_supplicant.conf
    /etc/freebsd-update.conf
    /etc/motd.template      
    /etc/motd               
    /var/cron/tabs/vermaden
    /var/cron/tabs/root
    host # for I in /usr/local/etc/X11/xdm/Xresources \
                    /usr/local/etc/X11/xdm/Xsetup_0   \
                    /usr/local/etc/X11/xorg.conf.d/*  \
                    /usr/local/etc/devd/*             \
                    /usr/local/etc/automount.conf     \
                    /usr/local/etc/sudoers            \
                    /usr/local/etc/doas.conf          \
                    /usr/local/etc/zshrc              \
                    /usr/local/etc/smb4.conf          \
                    /usr/local/etc/automount.conf     \
                    /usr/local/etc/fscd.conf          \
                    /usr/local/etc/cups/*             \
                    /usr/local/etc/cups/ssl/*         \
                    /usr/local/etc/cups/ppd/*
           do
             cp "${I}" /var/tmp/12.3/"${I}"
             echo "${I}"
           done
    /usr/local/etc/X11/xdm/Xresources
    /usr/local/etc/X11/xdm/Xsetup_0
    /usr/local/etc/X11/xorg.conf.d/card.conf
    /usr/local/etc/X11/xorg.conf.d/flags.conf
    /usr/local/etc/X11/xorg.conf.d/keyboard.conf
    /usr/local/etc/X11/xorg.conf.d/touchpad.conf
    /usr/local/etc/devd/audio_source.conf
    /usr/local/etc/devd/automount_devd.conf
    /usr/local/etc/devd/cups.conf
    /usr/local/etc/devd/cups.conf.sample
    /usr/local/etc/devd/webcamd.conf
    /usr/local/etc/automount.conf
    /usr/local/etc/sudoers
    /usr/local/etc/doas.conf
    /usr/local/etc/zshrc
    /usr/local/etc/smb4.conf
    /usr/local/etc/automount.conf
    /usr/local/etc/fscd.conf
    /usr/local/etc/cups/classes.conf
    /usr/local/etc/cups/command.types
    /usr/local/etc/cups/cups-browsed.conf
    /usr/local/etc/cups/cups-browsed.conf.sample
    /usr/local/etc/cups/cups-files.conf
    /usr/local/etc/cups/cups-files.conf.sample
    /usr/local/etc/cups/cupsd.conf
    /usr/local/etc/cups/cupsd.conf.sample
    /usr/local/etc/cups/ppd
    /usr/local/etc/cups/printers.conf
    /usr/local/etc/cups/printers.conf.O
    /usr/local/etc/cups/snmp.conf
    /usr/local/etc/cups/snmp.conf.sample
    /usr/local/etc/cups/ssl
    /usr/local/etc/cups/ppd/HP-M251nw.ppd
    /usr/local/etc/cups/ppd/Samsung-ML-1915.ppd
    BE # pw useradd vermaden -u 1000 -d /home/vermaden -G wheel,operator,video,network,webcamd,vboxusers
    
    BE # passwd root
    
    BE # passwd vermaden
    BE # exit
    
    host # umount /var/tmp/12.3/dev
    
    host # beadm unmount 12.3
    Unmounted successfully
    
    host # beadm list -D
    BE             Active Mountpoint  Space Created
    13.0.w520      NR     /           11.3G 2021-09-14 17:27
    13.0.w520.safe -      -           11.1G 2021-10-18 10:01
    12.3        -      -            9.5G 2021-10-18 13:14
    
    host # shutdown -r now
    # zpool import data
    This pool uses the following feature(s) not supported by this system:
            org.freebsd:zstd_compress (zstd compression algorithm support.)
            com.delphix:log_spacemap (Log metaslab changes on a single spacemap and flush them periodically.)
            org.zfsonlinux:project_quota (space/object accounting based on project ID.)
            org.zfsonlinux:userobj_accounting (User/Group object accounting.)
    cannot import 'data': unsupported version or feature
    # pkg install -y openzfs openzfs-kmod
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 2 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            openzfs: 2021090800
            openzfs-kmod: 2021090800
    
    Number of packages to be installed: 2
    
    The process will require 22 MiB more space.
    4 MiB to be downloaded.
    [1/2] Fetching openzfs-2021090800.pkg: 100%    3 MiB 975.3kB/s    00:03
    [2/2] Fetching openzfs-kmod-2021090800.pkg: 100%    1 MiB 591.2kB/s    00:02
    Checking integrity... done (0 conflicting)
    [1/2] Installing openzfs-kmod-2021090800...
    [1/2] Extracting openzfs-kmod-2021090800: 100%
    pkg: Cannot open /dev/null:No such file or directory
    [2/2] Installing openzfs-2021090800...
    [2/2] Extracting openzfs-2021090800: 100%
    =====
    Message from openzfs-kmod-2021090800:
    
    --
    Amend /boot/loader.conf as follows to use this module:
    
    - change zfs_load="YES" to NO
    - change opensolaris_load="YES" to NO
    - add openzfs_load="YES"
    - (for ARM64) add cryptodev_load="YES"
    =====
    Message from openzfs-2021090800:
    
    --
    Ensure that any zfs-related commands, such as zpool, zfs, as used in scripts
    and in your terminal sessions, use the correct path of /usr/local/sbin/ and
    not the /sbin/ commands provided by the FreeBSD base system.
    
    Consider setting this in your shell profile defaults!
    host # beadm mount 12.3 /var/tmp/12.3
    Mounted successfully on '/var/tmp/12.3'
    
    host # chroot /var/tmp/12.3
    
    BE # cp /boot/loader.conf /boot/loader.conf.ZFS
    
    BE # vi /boot/loader.conf
    
    BE # diff -u /boot/loader.conf.ZFS /boot/loader.conf
    --- /boot/loader.conf.ZFS       2021-10-19 10:57:04.180732000 +0000
    +++ /boot/loader.conf   2021-10-19 10:57:23.992145000 +0000
    @@ -12,7 +12,8 @@
    
     # 启动模块
       geom_eli_load=YES
    -  zfs_load=YES
    +  zfs_load=NO
    +  openzfs_load=YES
    
     # 为磁盘禁用 /dev/diskid/*
       kern.geom.label.disk_ident.enable=0
    
    BE # shutdown -r now
    host # gpart show -p ada1
    =>       40  250069600    ada1  GPT  (119G)
             40     409600  ada1p1  efi  (200M)          <== UEFI BOOT PARTITION
         409640       1024  ada1p2  freebsd-boot  (512K) <== BIOS BOOT PARTITION
         410664        984          - free -  (492K)
         411648    2097152  ada1p3  freebsd-swap  (1.0G)
        2508800  247560192  ada1p4  freebsd-zfs  (118G)
      250068992        648          - free -  (324K)
    
    host # mount_msdosfs /dev/ada1p1 /mnt
    
    host # cp /var/tmp/13.1/boot/loader.efi /mnt/efi/boot/bootx64.efi
    host # cd /var/tmp/13.1/boot
    host # pwd
    /var/tmp/13.1/boot
    host # gpart bootcode -b ./pmbr -p ./gptzfsboot -i 2 ada1
    partcode written to ada1p2
    bootcode written to ada1
    因为一些时间的推进,ISC 正在开发一款新的 DHCP 服务器——Kea——他们打算最终在大多数服务器实现中用它替代 ISC DHCP。他们也建议新的实现者考虑使用 Kea 而不是 ISC DHCP,仅在 Kea 无法满足需求时才实现 ISC DHCP。例如,Kea 当前不包含客户端和中继。也许我以后会对这篇文章进行更新或者单独再写一篇文章。

    同时 Kea 在一个月前刚拥有了高可用模式,因此如果我更早写这篇文章,那么这样的设置在 Kea 上将不可行。这也显示了 Kea 实现是多么年轻,所以目前我会坚持使用 ISC DHCP server,并在后续“观察”Kea 的发展。

    架构

    下面是我们的 ISC DHCP 设置的 POOR MAN’S ASCII 架构图 图。

    每个 DHCP 服务器节点的设置都非常简单。它的 FreeBSD 11.2-RELEASE 安装在 4 GB 的 GPT 分区上,/ 文件系统是 UFS,如下所示只使用了 666 MB。

    对于少量客户端来说 128 MB 的内存已经足够。仍然有 32 MB 的空闲内存,以及 32 MB 的 Inactive 和 Buffered 内存可以被交换出去。更不用说每个 getty 进程大约占用 2 MB 内存,而你只需要其中 1 个,而不是 8 个。换言之,即使只有 64 MB 的内存,你也能跑起来。

    DHCP 节点 DHCPs1 和 DHCPs2 的 /etc/rc.conf 文件是相同的(除了主机名和地址不同)。

    ``sh root@DHCPs1:/ # cat /etc/rc.conf hostname=DHCPs1 ifconfig_em0="inet 10.0.10.251/24 up" sshd_enable=YES sendmail_enable=NONE clear_tmp_enable=YES syslogd_flags="-ss" dumpdev=NO

    现在让我们安装软件包 isc-dhcp44-server。

    现在更新 pkg(8) 仓库数据,并在 DHCPs2 节点上安装 isc-dhcp44-server。

    配置使用单一网络段 10.0.10.0/24,为客户端分配最后一段在 10-250 的地址。参数 split 128 会将负载在 DHCP 服务器节点之间平均分配。由于这只是示例,我们将使用 1.1.1.1 和 9.9.9.9 作为 DNS 服务器,以及 domain.com 作为域名。需要说明的是,仅在 primary 节点(在我们的例子中为 DHCPs1)上设置参数 split 128。正如 man dhcpd.conf 页面所建议的,我们将 “为两个服务器使用相同的主配置文件,并有一个单独的文件包含对等声明以及主文件。”,这样做 “有助于避免配置不一致。”

    ……secondary 节点

    /usr/local/etc/dhcpd.conf.SHARED 文件在两个节点上是相同的。

    现在让我们在两个节点上启动 DHCP 服务器。

    ……在 secondary 节点上也是一样。

    现在,由于高可用 DHCP 服务器的两个节点都已启动,让我们在 DHCP 客户端——在我们的示例中为 DHCPc——上尝试获取 DHCP 租约。

    我们可以看到 DHCP 客户端 DHCPc 获得了 10.0.10.131 的地址。

    当然,我们可以在 /usr/local/etc/dhcpd.conf.SHARED 配置文件中使用 host 选项为它设置固定地址,如下所示。

    所需的“额外配置”如下。

    需要在两个节点的 /usr/local/etc/dhcpd.conf.SHARED 配置文件中都添加,新的共享配置文件如下所示。

    现在将 /usr/local/etc/dhcpd.conf.SHARED 文件复制到第二个节点。

    让我们再次尝试从同一 DHCP 客户端获取地址。

    现在将 /usr/local/etc/dhcpd.conf.SHARED 文件复制到第二个节点。

    让我们再次尝试从同一 DHCP 客户端获取地址。

    现在我们已经获得了固定地址 10.0.10.9。

    你现在可以在 /etc/rc.conf 文件中尝试修改以下值:

    • dhcpd_flags

    • dhcpd_ifaces

    • dhcpd_withumask

    • dhcpd_chuser_enable

    • dhcpd_withuser

    • dhcpd_withgroup

    • dhcpd_chroot_enable

    • dhcpd_devfs_enable

    • dhcpd_rootdir

    • dhcpd_includedirnclude

    ……以及 man dhcpd.conf 页面上所有其他可能的选项 🙂

    Highly Available DHCP Server on FreeBSD
    ISC

    OpenBSD 与 FreeBSD:有何不同,哪个更好?

    ——是否对选择下一个项目中使用 OpenBSD 还是 FreeBSD 感到困惑?我们将比较这两种流行的基于 BSD 的操作系统。

    • 原文链接:OpenBSD vs. FreeBSD: What Is the Difference, Which Is Best?

    • 作者:DAVID DELONY

    • 发布时间:2023.9.22

    • 译者:ykla & ChatGPT

    主要要点

    OpenBSD 和 FreeBSD 在安装过程上有所不同,OpenBSD 假定用户具备更多的计算机经验,(安装)界面较为简约,而 FreeBSD 则具有更为精致的安装程序。

    OpenBSD 专注于安全性,并以其对代码正确性的承诺而闻名。另一方面,FreeBSD 被定位为通用系统,有着支持点对点互联网基础设施的历史。

    FreeBSD 拥有更好的文档,包括一本写得很好的手册,既可以作为专家的参考,也可以作为初学者的入门指南。而 OpenBSD 的文档更面向专家,并在视觉上根植于上世纪 90 年代。

    和 都是原始的服务器专用的伯克利软件发行版(BSD)的后继者,该发行版在 20 世纪 70 年代末至 90 年代由加州大学伯克利分校(UC Berkeley)开发。

    作为流行的开源项目,它们有着忠实的用户群,被视为 Linux 的替代选择。它们有哪些不同之处,哪一个可能更适合你呢?

    安装过程:OpenBSD 与 FreeBSD

    OpenBSD 和 FreeBSD 都有安装程序,可让你在计算机上分区并安装这些系统,安装过程类似于 Linux 发行版。然而,安装这两个操作系统的体验是非常不同的。

    OpenBSD 假定用户具备丰富的计算机经验,其(安装)界面相对简约。你需要从其网站下载安装镜像,就像在下载 Linux 时一样,然后将其 中,并启动计算机。

    当你的计算机启动时,你会看到一个控制台界面。与主要的 Linux 发行版不同,OpenBSD 没有图形化的安装程序和 live CD。你需要从终端运行安装程序,并回答有关键盘类型和区域的问题。

    如果你犯了错误,你唯一能做的就是按下 Ctrl + C,然后重新开始。这个安装程序类似于专注于专家用户的发行版——如 Arch 或 Gentoo。

    之后,你将选择要包含在系统中的“文件集”。开发人员建议初次使用者使用默认设置。然后,你将配置 root 密码以及其他用户。接下来,关键时刻来临,你将启动新的操作系统。

    FreeBSD 的安装程序类似,但(安装)界面更为精致。不过,它仍然是基于文本的。如果你在上世纪 90 年代曾在 MS-DOS 系统上安装过游戏,那么 FreeBSD 的安装程序会让你感到熟悉。

    它还会引导你完成 FreeBSD 机器的设置,如格式化分区(FreeBSD 称之为 "slices")、选择软件、设置互联网连接以及设置用户和时区。

    尽管它看起来更友好,但 FreeBSD 的安装程序也假定用户熟悉类 Unix 操作系统,就像 OpenBSD 一样。

    与 OpenBSD 相比,FreeBSD 在具有更直观的安装程序方面具有优势,如果你以前安装过操作系统,你可以在没有手册的情况下完成安装。

    用途和应用领域

    OpenBSD 和 FreeBSD 都源自 386BSD 项目,该项目旨在将 BSD 源代码移植到 Intel 80386 处理器上,但它们面向两个不同的市场。

    OpenBSD 由 Theo De Raadt 创建,此前他与其他 NetBSD 开发者发生了多次分歧。NetBSD 本身是 386BSD 的另一个分支。

    OpenBSD 以其对安全性的关注而闻名。截至 2023 年 9 月,该项目的官方网站声称在默认安装中已经在很长一段时间内只发现了两个远程漏洞。

    在上世纪 90 年代的互联网繁荣时期,OpenBSD 最初因在小型 ISP 中使用二手零件从头开始构建路由器和网关而广受欢迎。随着互联网服务的集中化和专业化,专用硬件变得更加普遍,但 OpenBSD 通过强调代码正确性来保持对安全性的关注。

    OpenBSD 对技术质量的承诺很可能是其组件被移植到其他系统(如 OpenSSH 和 tmux)并在 OpenBSD 生态系统之外广泛流行的原因。甚至在 Windows 10 和 11 上,都默认安装了 OpenSSH。

    另一方面,尽管开发者侧重于服务器用途,FreeBSD 被定位为通用系统。

    与 OpenBSD 一样,在上世纪 90 年代的互联网繁荣时期,FreeBSD 是驱动互联网基础设施的流行操作系统。当时,雅虎以广泛依赖 FreeBSD 而闻名,Netflix 的 Open Connect 内容交付网络处理了许多用户的连续观看会话。

    文档质量

    OpenBSD 和 FreeBSD 都维护有关其系统的文档。

    OpenBSD 的文档与其余系统一样,简洁而面向专家。从视觉上看,该项目的网站根植于上世纪 90 年代,尽管 OpenBSD 通常会有富有幽默感的发布主题。

    除了 man 页之外,OpenBSD 还维护着 ,实际上也可以作为手册使用。这些内容涵盖了一些细节,如安装和系统安全性。

    FreeBSD 的文档方式更加精致。FreeBSD 有写得很好的 man 页,但该系统最出色的特点可能是“”(手册)。它提供了足够详尽的信息,可作为专家用户的参考,同时也解释了足够基本的概念,适合那些对类 Unix 系统经验不太丰富的用户作为入门材料。

    在文档质量方面,FreeBSD 胜过 OpenBSD。

    防火墙实现

    OpenBSD 和 FreeBSD 都强调安全性,它们提供了防火墙作为提高安全性的一种方式。

    忠实于 OpenBSD 对安全性的强调,该项目开发了自己的防火墙程序,即 Packet Filter(PF)。与其他组件一样,PF 已经广泛移植到其他系统中。PF 是 macOS 的一部分,而 macOS 的一部分又是基于 FreeBSD 的。

    与 OpenBSD 一样,FreeBSD 也将 PF 作为主要的防火墙程序之一,但还提供了 IPFW 和 IPFILTER。FreeBSD 手册为 PF 提供了最多的空间,但警告说它们的移植版本与 OpenBSD 的有显著差异。

    在两个系统上配置防火墙以使其充当临时路由器需要一些时间和专业知识。对于那些决心构建 DIY 路由器的人来说,OpenBSD 因其对安全性的极端关注而具有优势。

    桌面环境

    尽管 OpenBSD 和 NetBSD 主要是面向服务器开发的,但也可以将它们用作桌面系统。

    OpenBSD 可以安装 X 服务器和基本的 FVWM 窗口管理器环境【译者注:这里表述有点问题,OpenBSD 的文件集是有 X 的,不需要也不能通过包管理器安装】。从视觉上看,与其他内容一样,它也带有上世纪 90 年代的风格。你可以通过软件包管理器安装其他桌面环境。

    FreeBSD 提供了许多与 Linux 发行版相同的窗口管理器和桌面环境。

    在这两个系统上安装图形用户界面(GUI)需要一些较为复杂的步骤,类似于在 Arch 或 Gentoo 上安装 GUI。在这方面,FreeBSD 可能是赢家,因为你可以安装像 TrueOS【译者注:2020 年该系统就已经停止开发了】或 MidnightBSD 这样的完整桌面系统,它们已经默认包含了桌面环境。

    硬件支持:OpenBSD 与 FreeBSD

    如果你觉得在 Linux 上 令人沮丧,那么在 ,你的选择会更有限,因为至少在桌面领域,它们比 Linux 更为小众。

    与 Linux 一样,最大的挑战在于显卡和 Wi-Fi。

    OpenBSD 支持 AMD 和 Intel 芯片组,但不支持 Radeon,因为该公司未向开发者提供任何技术信息。然而,有许多 Wi-Fi 驱动程序可用。

    FreeBSD 支持主要的显卡芯片制造商以及 Wi-Fi。

    与许多现代 Linux 发行版一样,X 在这两个系统上运行时需要很少或根本不需要配置。由于它们主要面向服务器,它们默认在控制台模式下运行。连接到 Wi-Fi 也较为复杂,但有线连接通常可以直接使用。

    FreeBSD 和 OpenBSD 中的包管理器

    OpenBSD 和 FreeBSD 都提供了软件包管理,以简化软件安装,类似于现代的 Linux 发行版。在这两个系统中,你可以从源代码编译 "ports",但也可以选择快速安装二进制软件包。后一种方法在这两个系统中越来越常见。

    OpenBSD 使用 pkg_add 和 pkg_info 程序来安装和搜索软件包。

    FreeBSD 的软件包命令称为 "pkg",并且所有操作都在一个程序中执行。后一种方法似乎更加简单。

    哪个更安全?OpenBSD 还是 FreeBSD

    OpenBSD 和 FreeBSD 都强调它们对安全性的承诺。FreeBSD 是一个更通用的系统,但显然可以看出,OpenBSD 在编码和系统设计方面非常专注。那些真正关心安全性的人可能会选择后者。

    知名度

    尽管仅仅因为流行度而选择操作系统不应该是唯一的考虑因素,但它将影响到寻找软件和支持的能力。虽然 OpenBSD 在开源社区中以其对安全性的忠诚以及在发布主题方面的俏皮一面而声名远扬,但 FreeBSD 似乎得到了更广泛的支持。

    很难准确衡量这两个系统在实际中有多广泛的使用,但截至 2023 年 9 月,根据对其网页的点击量,FreeBSD 在 上的排名高于 OpenBSD。

    现在,你可以根据工作的性质选择适合的 BSD

    在 OpenBSD 和 FreeBSD 之间做出决策可能令人生畏,但决策很可能取决于你希望系统有多么安全。如果你需要一个安全、坚不可摧的操作系统,最好选择 OpenBSD。如果需要一个更通用的 BSD 系统,可以选择 FreeBSD 或 NetBSD。

    FreeBSD Jail 容器中的 Minecraft 服务器

    • 原文:Minecraft Server in FreeBSD Jails Container

    • 发布时间:2025/04/05

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    今天——应我儿子的要求——我们来讲讲如何在 FreeBSD Jail 容器中运行 Minecraft 服务器。

    这有点像 Linux 上的 Docker/Podman,但安全性更高。

    准备工作

    首先我们将在 /jail 路径下创建环境,并获取所需的 FreeBSD 基本系统 版本。

    今天我们将使用 FreeBSD 14.2-RELEASE 版本。

    接下来我们将创建专用的 Minecraft FreeBSD Jail,并为其填充独立的 基本系统 内容。

    我们还会复制 /var/run/dmesg.boot,因为 Minecraft 服务器需要使用它。

    创建

    现在我们将设置基础 FreeBSD Jail 配置。

    这些配置将作为所有其他 Jail 的默认值,除非我们重新定义它们。

    现在配置我们的 Minecraft Jail。

    我们将使用局域网接口 em0 和 IP 地址 10.0.0.210。

    下面你还会看到宿主机上的规则集 /etc/devfs.rules。

    现在我们可以启动我们的 Jail 了。

    你也可以使用我提供的工具 。

    为了让 Minecraft Jail 在启动时自动运行,需要在 host 系统的 /etc/rc.conf 文件中添加如下内容:

    配置 FreeBSD Jail

    现在我们进入 Minecraft Jail。

    使用 jmore minecraft c 相当于执行了知名的命令:

    示例:

    接下来进行一些基本配置,例如设置 DNS 或将 pkg(8) FreeBSD 包管理器切换到 latest 分支:

    现在安装其他所需的包,因为 Minecraft 服务器需要通过 FreeBSD Ports 构建:

    由于需要通过 FreeBSD Ports 构建 Minecraft 服务器,并且许可需要手动接受(或忽略)(译注:并不需要),因此接下来使用 gitup 工具获取 FreeBSD Ports 树。

    在 make config 阶段选择选项 DAEMON 。

    构建

    接下来我们将构建 Minecraft 服务器。

    Minecraft 服务器配置

    按照 pkg-message 中的建议,我们将在 /etc/fstab 文件中添加额外的虚拟文件系统。

    同时,我们还要确保这些文件系统在 Jail 启动时通过 /etc/rc.local 文件被挂载。

    我们不会修改 Minecraft Jail 的主 /etc/rc.conf 配置文件来添加所需的 Minecraft 服务器选项。

    同时,我们将“接受”EULA,并在 /usr/local/etc/minecraft-server/server.properties 文件中创建基本的 Minecraft 服务器配置。

    你也可以在 /usr/local/etc/minecraft-server/java-args.txt 文件中配置额外的 Java 参数。如果默认值对你的情况太小,请自行增大。

    启动

    现在是时候启动已安装并配置好的 Minecraft 服务器了。

    看起来服务器运行正常——但如果不正常,可以使用以下命令进行调试。

    连接 Minecraft 客户端

    首先 – 确保你的客户端版本与 Minecraft 服务器版本一致 – 我这里是 1.21.4。

    我的情况是,Minecraft 客户端是在某台随机的 Windows 电脑上启动的,如下所示。

    点击 多人游戏 按钮。

    然后点击 添加服务器 按钮 – 我们将添加基于 FreeBSD 的 Minecraft 服务器。

    输入你喜欢的 Minecraft 服务器名称和 IP 地址。

    稍等片刻,我们的基于 FreeBSD 的 Minecraft 服务器将出现在列表中。

    现在点击 加入服务器 按钮加入服务器。

    我们会看到 正在连接服务器… 的提示。

    ……片刻之后,我们就成功加入了 Minecraft 服务器。

    用户

    由于我不是 Minecraft 专家,我花了一些时间才找到在该服务器上定义“管理员”的方法。

    幸运的是,我有一个可行的解决方案 🙂:

    当我在这里写关于我自己的 jmore(8) 工具时 ,我最初把它叫作 jless(8),但有人提醒我这个名字已经被一个处理 JSON 的工具占用了。我们稍后会用到它 🙂。

    当有人连接到我们的服务器时,他的 名字 和 uuid 会被添加到 /usr/local/etc/minecraft-server/usercache.json 文件中,如下所示。

    用 bat(1) 命令显示颜色后看起来效果更好。

    现在 – 要让这些用户成为“管理员”,我们需要将他们添加到 /usr/local/etc/minecraft-server/ops.json 文件中,并且重启 Minecraft 服务器才能生效。

    权限等级 4 是记录中最高的权限等级。

    现在我儿子拥有了他需要使用的所有命令,例如 /gamemode 或 /time 🙂。

    总结

    欢迎随意分享你对个人 Minecraft 服务器其他所需配置的想法。

    更新 1 – FreeBSD Jail 与 Linux Podman

    我没想到第一句话会成为评论的焦点,因此在这里补充一些细节。我们来讨论一下 FreeBSD Jails 和 Linux Podman 容器在安全性上的差异。

    隔离性: 对于无 root Podman 来说,如果启用了 SELinux/AppArmor,它的隔离性似乎与 Jail 在同一水平。但如果没有 SELinux/AppArmor,Jail 提供了更好的隔离性。当你在 Podman 中启用 SELinux/AppArmor 并再添加 MAC 框架(如 mac_sebsd / mac_jail / mac_bsdextended / mac_portacl)时,Jail 的隔离性更高。

    内核系统调用暴露面: 即使是无 root Podman,除非通过 seccomp(SELinux)限制,否则仍有“完全”的系统调用访问权限。Jail 对系统调用的使用有限制,不需要额外工具就能实现;在 FreeBSD 上结合 MAC 框架还可以进一步缩小系统调用的可用范围。

    防火墙: 你无法在无 root Podman 容器内运行防火墙。而在 VNET Jail 中,你可以运行完整的网络栈和任何防火墙(如 PF 或 IPFW),独立于宿主机运行,这意味着安全性更高。

    总结: FreeBSD Jail 通常在默认情况下比 Podman 容器更安全,如果花时间添加额外的安全层,其安全性会更高。

    市场存在时间也是一个重要因素。

    Jail 自 1999/2000 年引入以来已经投入生产环境,已有 25 年历史,久经考验。Docker 从 2014 年开始流行,时间短约 10 年,但我们要比较的是 Jail 与 Podman。Podman 的无 root 支持首次出现在 2019 年晚期(1.6 版本),因此在市场上的时间不足 6 年。

    这意味着 Jail 是所有方案中最经受考验的。

    portsnap 被淘汰了,本应由 git 代替,但结果我发现自己用的是 got

    • 原文:追放 された portsnap、変 わりに git が 入 ってくはずだったのに、気 がつけば got がいる

    • 作者:重村法克

    • 2023-12-02

    前言

    本文介绍了 ,这是源自 OpenBSD 项目的 替代工具。 这是一种所谓的 git 命令的替代品,但如果你对 git 命令的使用以及其许可证完全没有疑问的话,那就 使用这个工具。由于开发者的立场,这个工具的使用场景也具有独特性。

    据称 Got 旨在实现对 Git 的裸数据仓库的兼容 [1]。它在针对裸数据仓库的操作方面具有兼容性。相对地,在所谓的工作区(包括索引)层面上则不兼容。在工作流程中需要根据命令加以区分使用。

    虽然开篇是以通用视角进行介绍的,但说实话,是因为最近 FreeBSD 中移除了 portsnap 命令,所以大家看到了一些提示说“请改用 Git”[2]。本文正是面向那些觉得“为了替代 portsnap 而引入 Git 实在有点……”的人所写的内容。

    由于 Got 以实现 OpenBSD 开发工作流为目标进行开发,因此其代码量极少,依赖项也几乎没有。可以毫不夸张地称其为“轻量紧凑”。不过至于运行是否轻快……这一点暂且不予置评。 此外,由于它要求用户接受其独特的使用体验,因此如果你打算“用得很 Git”,那还是不建议使用 Got。

    后续的使用案例将以替代 portsnap 为目标进行说明。

    试着安装一下

    这部分和安装 git 没什么不同。由于没有依赖项,因此不会安装其他包。

    测试中使用的 Got 版本为 0.93。如果版本升级,文中内容可能会不适用。

    首先试试 clone

    got clone 和 git clone 的区别如下:

    • 仅支持克隆裸数据仓库(相当于 git clone --bare)

    • 无法指定 origin(可能因为裸仓库下 origin 没意义?)

    • 可以指定分支,默认好像是单分支模式

    • 不支持 shallow clone(浅克隆)

    克隆示例

    对应的 got 命令如下。首先需要一个目录用于放置裸仓库。 另外这个操作会非常慢(),如果条件允许,还是建议使用 git 命令来完成。

    支持的协议(スキーマ)

    • git://

    • git+ssh://(或者 ssh://)

    不支持的协议(スキーマ)

    • git+http://(或者 http://)※ 错误(因为政策原因,未来不打算支持)

    • https:// ※ 尚未实现的错误(TODO)

    • ftp:// ※ 什么?(不确定是否被识别)

    克隆时间的测量

    使用 git clone 时的输出信息

    使用 got clone 时的输出信息

    git clone 和 got clone 的执行时间对比

    • 执行环境约为 5 分 37 秒 与 14 分 1 秒之间的差异,差距为 2.5 倍。

    • 另外,Git 的 CPU 使用率较高,处理效率偏向 CPU 绑定(通过多线程处理实现)。

    • 相反,Got 的系统使用率较高,瓶颈主要集中在 I/O 绑定上。

    克隆时的选项指定对容量的影响

    命令
    单分支模式*
    多分支模式*
    • 单分支:git clone --single-branch 或 got clone

    • 多分支:git clone 或 got clone -a

    这里确认了不同选项指定时的容量差异。git 和 got 之间的差异较大,但为何会产生这种差异尚不明确,可能是某种开销造成的。

    工作树更新

    上面执行的命令,相当于 got 命令如下:

    这个是典型的使用方式。关于开发流程中需要的使用方法,请参考 等参考资料。

    附加的 tog 命令

    tog 是一款基于 ncurses 的日志查看器。它显示一行日志,当按下回车键时,会显示详细日志和修正内容,这是个非常方便的工具。它相当于 Git 的第三方工具 tig。

    信息展示

    Got 中用于管理仓库和工作树的命令不同。具体来说,分别是 gotadmin 和 got。

    不过,安全使用的子命令大概只有 info。根据仓库或工作树的状态,显示不同的信息。

    如果在通过 git clone --bare 克隆的目录内运行 gotadmin info,会看到 remote 行显示了更多的信息。

    查看仓库下的文件时,发现 config 文件中的 remote "origin" 配置被 got.conf 中的 remote "origin" 配置所替代。如果创建了 got.conf 文件,remote 行便会显示出来。

    另外,在工作树上执行 gotadmin info 时,会显示仓库的状态。而执行 got info 则会显示工作树相关的信息。

    常见问题及其解答

    问:https 协议不能使用吗?

    答:可能是因为没有依赖 curl。如果实现普通的 HTTP 通信,可能会遇到无法并行处理的问题……这是我个人的推测。而使用 ssh:// 则更加稳妥,因为很多系统中已经安装了 ssh 命令【需要引用来源】。

    问:got update、got merge、got rebase、got integrate 有什么区别?

    答:尚未研究。估计与 Git 中的用法相同。

    问:got clone ... /usr/ports/.git,不是就能创建与 git clone 完全相同的情况吗?

    答:经过验证,got clone 可以成功执行,但 got checkout 会失败。

    问:/usr/ports/.git 是怎么回事?

    答:实际上这是一个裸仓库的目录!在 git clone 后,运行 gotadmin info,结果非常令人吃惊……

    问:运行 git status 后看到惊人的结果

    答:关于 .gitignore 文件的处理,有一个 bug 这是设计上的特性。本来 .gitignore 文件中指定的目录和文件是不应显示的。根据略微的研究,它并不是完全没有处理 .gitignore 文件。所以这是 一个 bug 设计上的特性。

    问:有没有别名功能?

    答:没有。这个功能确实很需要,真希望有人能实现它。

    问:既然能这么做,为什么不把它加入到基本系统中?

    答:在彻底使用并报告其效果之前,不能肯定它的质量是否足够达到基本系统的要求。至少在我使用的范围内,它似乎还没有达到那个质量标准。

    参考文献


    1. より

    使用 BIOS 引导和 UEFI 引导的 GPT 分区的区别和制作方法

    • 原文:BIOS ブートと UEFI ブートで GPT パーティションの 違 いと 作 り 方

    • 作者:重村法克

    • 2020-11-11

    在当前的 FreeBSD 中,不论磁盘大小,几乎都建议使用 GPT(GUID 分区表)来进行分区配置。然而,在传统的 BIOS 启动和 UEFI 启动的情况下,分区配置会有所不同 [1]。以下将介绍两者的区别,并提供可用的启动分区配置示例。

    前提条件

    在这里,我们假设操作的是 SATA 磁盘,设备名称表示为 /dev/ada0。如果是 SAS/USB 磁盘,设备名为 dan,NVMe 磁盘为 nvdn,eMMC 磁盘为 mmcsdn(其中 n 是大于等于 0 的整数)。

    通用操作

    由于使用的是 GPT 分区,在所有操作步骤中,都必须执行以下命令 [2]:

    为了简化讨论,假设我们分配了以下分区:

    设备名
    分区类型
    用途

    在本讨论中,ada0p2 和 ada0p3 使用相同的通用步骤。即执行以下命令,虽然这些命令在当前场景中可能并不立即有用 [4][5] [6]:

    在 BIOS 启动情况下

    • 我们为启动分区定义了 freebsd-boot 类型。如果不是 freebsd-boot,引导加载器将无法发现该分区。

    • 起始位置(-b)指定为从第 40 扇区(LBA 40)开始。

      • GPT 分区表头大小为 34 扇区,但在支持 4KiB 扇区的磁盘上,起始位置可能会被四舍五入为 8 的倍数。

      • 近期版本中,GPT 分区表头的大小已经增加为 40 扇区(具体从哪个版本开始的尚未确认)。

    以上步骤完成后,引导加载器安装完毕了。引导加载器会查找 FreeBSD 分区 [9][10],然后将控制权交给 /boot/loader 或 /boot/zfsloader。

    在 UEFI 启动情况下

    • 我们为启动分区定义了 efi 类型。如果不是 efi,UEFI 将无法发现该分区。

    • 起始位置(-b)指定为从第 40 扇区(LBA 40)开始。

      • GPT 分区表头的大小为 34 扇区 [7],但在支持 4KiB 扇区的磁盘上,起始位置可能会被四舍五入为 8 的倍数。

      • 近期版本中,GPT 分区表头的大小已调整为 40 扇区(具体从哪个版本开始尚未确认)。

    完成上述步骤后,启动加载器将安装完毕。启动加载器会查找 FreeBSD 分区,并继续启动过程。

    常见问题与解答

    问:为什么与 上的步骤不同?

    答:没问题,完全没问题。时代已经跟上了。

    问:通过各种资料查看,似乎有很多方法来写入 /boot/boot1.efifat 分区,该采用哪种方式才正确?

    答:没问题,任何方法都可以。但我不推荐任何方法。

    /boot/boot1.efifat 实际上是分区镜像本身。极端地说,可以认为是 dd if=/dev/ada0p1 of=/boot/boot1.efifat 的结果。实际构建时也会做类似的操作。

    因此,无论是使用 dd(8) 还是 gpart(8) 写入都没问题,但显然,gpart(8) 是更聪明的选择。

    不过,最好避免使用 /boot/boot1.efifat。正如前面提到的,扩展到 200MiB 后,这个分区只能访问 800KiB 的空间。

    尽管分配了 200MiB 的空间,但 EFI 应用程序无法在这 200MiB 中运行。

    新安装不会有问题,但更新时,使用这种方式可能会不必要地删除一些内容。

    问:在操作系统更新时,是否需要更新启动分区?

    答:并非每次都需要,但有时需要,具体情况如下:

    1. 从 UFS 启动 时,由于 UFS 的格式稳定性,启动加载器代码通常不会发生变化,所以几乎不会出现问题。即使没有更新启动分区,通常也不会发现问题,除非从 UFS1 升级到 UFS2。

    2. 从 ZFS 启动 时,由于 ZFS 格式的不稳定性,启动加载器代码会发生变化。因此,必须定期维护启动分区,否则可能无法启动。有关这一点,/usr/src/UPDATING 中的 ZFS notes 提到:“如果更新启动的 ZFS 池的版本,请确保更新启动加载器。”

    因此,除了更新步骤外,更新启动加载器的步骤也应纳入操作流程。

    对于 freebsd-boot 分区,可以通过 gpart bootcode -p 命令覆盖,但对于 EFI 分区,需要先挂载,再通过 cp 命令进行覆盖()。

    问:如果分区号不是 1,那么是否可以随意设置?

    答:不行,最好不要这样做。

    由于 MBR 存在 2TiB 的限制,如果使用超过 2TiB 的空间,BIOS 可能无法找到启动加载器(freebsd-boot)。

    另外,如果分区号和分区顺序不一致,管理起来会很麻烦。

    问:我们使用的是 GPT 分区,为什么还要管 MBR?

    答:遗憾的是,GPT 是 MBR 的上位兼容,所以不能完全忽略它。

    对于 UEFI 启动,GPT 被视为 GPT,不用担心 MBR 的问题。

    然而对于 BIOS 启动,GPT 会表现得像 MBR,因此需要在前 2TiB 内有启动加载器(freebsd-boot)。不过,是否使用分区号 1 并不重要。

    问:我不确定系统是 UEFI 启动还是 BIOS 启动,怎么确定?

    答:很简单!在安装 CD 上启动为 LiveCD 后,执行命令 sysctl machdep.bootmethod。如果是 UEFI 启动,显示的是 UEFI;如果是 BIOS 启动,则显示的是 BIOS。

    【附录】启动加载器更新

    BIOS 启动情况下

    UEFI 启动的情况

    首先,在 /etc/fstab 中添加以下设置。

    接着,创建 /boot/efi 目录。

    首次可以手动执行挂载。当然,也可以重启后无需特别关注。

    之后的更新操作如下:

    参考文献


    1. 在 BIOS 中,通常使用“MBR(主引导记录)引导”,但是由于 2 TiB 限制的严格性以及几乎没有多重引导需求,因此已经统一采用了 GPT 引导(?)

    2. 执行此命令没有过多或不足之处。从兼容性的角度来看,根本没有修改默认值的余地。

    3. 虽然有时可能希望将 freebsd-ufs 改为 freebsd-zfs,但在本次讨论中暂且省略这一点。

    4. 实际上,需要使用 -s 尺寸 选项来指定大小。如果没有指定,意味着使用剩余的所有空间。也就是说,如果直接执行,将无法为交换空间分配空间。

    ccache 在构建 FreeBSD 的 buildworld 时的效率

    • 原文:

    • 作者:重村法克

    • 2022-11-16

    第二次企业工作组会议回顾

    • 原文:

    • 发布日期:2023.9.18

    • 译者:ykla & ChatGPT

    ZFS 池破坏实验

    • 原文:

    • 作者:みんみん

    • 最后更新于 2022-12-08

    +-------------+              +-------------+
      | {primary}   |              | {secondary} |
      | DHCPs1      | ==== HA ==== | DHCPs2      |
      | 10.0.10.251 |              | 10.0.10.252 |
      +-------------+              +-------------+
                     \            /
      +------------------------------------------+
      | ADDRESS POOL  10.0.10.x/24  ADDRESS POOL |
      +------------------------------------------+
                  \                  /
                   +----------------+
                   | {DHCP CLIENTS} |
                   +----------------+
    root@DHCPs1:/ # uname -v
    FreeBSD 11.2-RELEASE #0 r335510: Fri Jun 22 04:32:14 UTC 2018     [email protected]:/usr/obj/usr/src/sys/GENERIC 
    
    root@DHCPs1:/ # gpart show
    =>     40  8388528  ada0  GPT  (4.0G)
           40     1024     1  freebsd-boot  (512K)
         1064  8386560     2  freebsd-ufs  (4.0G)
      8387624      944        - free -  (472K)
    
    root@DHCPs1:/ # du -smc * | sort -n
    0       sys
    1       COPYRIGHT
    1       dev
    1       entropy
    1       libexec
    1       media
    1       mnt
    1       net
    1       proc
    1       root
    1       tmp
    2       bin
    4       etc
    7       sbin
    8       var
    10      rescue
    12      lib
    128     boot
    499     usr
    666     total
    root@DHCPs1:~ # top -b -o res
    last pid: 15205;  load averages:  0.13,  0.25,  0.29  up 0+07:39:11    20:03:48
    16 processes:  2 running, 14 sleeping
    
    Mem: 1688K Active, 30M Inact, 26M Wired, 3800K Buf, 32M Free
    Swap:
    
    
      PID USERNAME    THR PRI NICE   SIZE    RES STATE    TIME    WCPU COMMAND
    38897 dhcpd         1  20    0 16424K 10724K select   0:00   0.00% dhcpd
    30199 root          1  20    0 13160K  8036K RUN      0:00   0.00% sshd
    15106 root          1  28    0 12848K  7136K select   0:00   0.00% sshd
    53100 root          1  20    0  9180K  5040K select   0:02   0.00% devd
    31079 root          1  20    0  7412K  3640K pause    0:00   0.00% csh
    15205 root          1  20    0  7916K  3060K RUN      0:00   0.00% top
    15960 root          1  20    0  6464K  2480K nanslp   0:00   0.00% cron
    69084 root          1  20    0  6412K  2364K select   0:01   0.00% syslogd
    28412 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    28188 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    28504 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    28972 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    29736 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    29080 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    30106 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    29392 root          1  52    0  6408K  2124K ttyin    0:00   0.00% getty
    
    `/etc/sysctl.conf` 和 `/boot/loader.conf` 文件不需要修改。
    
    现在你需要安装 ISC DHCP 服务器,由于当前版本是 4.4.x,软件包名相应为 `isc-dhcp44-server`,我们使用命令 `pkg(8)` 来安装。
    
    ```sh
    root@DHCPs1:/ # pkg update -f -y
    The package management tool is not yet installed on your system.
    Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:11:amd64//quarterly, please wait...
    Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
    [nextcloud] Installing pkg-1.10.5...
    [nextcloud] Extracting pkg-1.10.5: 100%
    Updating FreeBSD repository catalogue...
    pkg: Repository FreeBSD load error: access repo file(/var/db/pkg/repo-FreeBSD.sqlite) failed: No such file or directory
    [nextcloud] Fetching meta.txz: 100%    944 B   0.9kB/s    00:01
    [nextcloud] Fetching packagesite.txz: 100%    6 MiB 530.8kB/s    00:12
    Processing entries: 100%
    FreeBSD repository update completed. 31134 packages processed.
    All repositories are up to date.
    root@DHCPs1:/ # echo ?
    0
    root@DHCPs1:/ #
    root@DHCPs1:/ # pkg install isc-dhcp44-server
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    Checking integrity... done (0 conflicting)
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            isc-dhcp44-server: 4.4.1_3 [FreeBSD]
    
    Number of packages to be installed: 1
    
    The process will require 6 MiB more space.
    
    Proceed with this action? [y/N]: y
    [1/1] Installing isc-dhcp44-server-4.4.1_3...
    ===> Creating groups.
    Creating group 'dhcpd' with gid '136'.
    ===> Creating users
    Creating user 'dhcpd' with uid '136'.
    [1/1] Extracting isc-dhcp44-server-4.4.1_3: 100%
    Message from isc-dhcp44-server-4.4.1_3:
    
    ****  To setup dhcpd, please edit /usr/local/etc/dhcpd.conf.
    
    ****  This port installs the dhcp daemon, but doesn't invoke dhcpd by default.
          If you want to invoke dhcpd at startup, add these lines to /etc/rc.conf:
    
                dhcpd_enable="YES"                          # dhcpd enabled?
                dhcpd_flags="-q"                            # command option(s)
                dhcpd_conf="/usr/local/etc/dhcpd.conf"      # configuration file
                dhcpd_ifaces=""                             # ethernet interface(s)
                dhcpd_withumask="022"                       # file creation mask
    
    ****  If compiled with paranoia support (the default), the following rc.conf
          options are also supported:
    
                dhcpd_chuser_enable="YES"           # runs w/o privileges?
                dhcpd_withuser="dhcpd"              # user name to run as
                dhcpd_withgroup="dhcpd"             # group name to run as
                dhcpd_chroot_enable="YES"           # runs chrooted?
                dhcpd_devfs_enable="YES"            # use devfs if available?
                dhcpd_rootdir="/var/db/dhcpd"       # directory to run in
                dhcpd_includedir=""       # directory with config-
                                                      files to include
    
    ****  WARNING: never edit the chrooted or jailed dhcpd.conf file but
          /usr/local/etc/dhcpd.conf instead which is always copied where
          needed upon startup.
    root@DHCPs1:/ # cat /usr/local/etc/dhcpd.conf
    # CORE
    failover peer "ha-dhcp" {
      primary;
      address 10.0.10.251;
      port 678;
      peer address 10.0.10.252;
      peer port 678;
      max-response-delay 60;
      max-unacked-updates 10;
      mclt 3600;
      split 128;
      load balance max seconds 3;
    }
    
    include "/usr/local/etc/dhcpd.conf.SHARED";
    root@DHCPs1:/ # cat /usr/local/etc/dhcpd.conf.SHARED
    # CLIENTS
    subnet 10.0.10.0 netmask 255.255.255.0 {
      default-lease-time         604800;
      max-lease-time             604800;
      option routers             10.0.10.254;
      option broadcast-address   10.0.10.255;
      option subnet-mask         255.255.255.0;
      option domain-search       "domain.com";
      option domain-name-servers 1.1.1.1,9.9.9.9;
    
      pool {
        failover peer "ha-dhcp";
        range 10.0.10.10 10.0.10.250;
      }
    }
    root@DHCPs2:~ # cat /usr/local/etc/dhcpd.conf
    # CORE
    failover peer "ha-dhcp" {
      secondary;
      address 10.0.10.252;
      port 678;
      peer address 10.0.10.251;
      peer port 678;
      max-response-delay 60;
      max-unacked-updates 10;
      mclt 3600;
      load balance max seconds 3;
    }
    
    include "/usr/local/etc/dhcpd.conf.SHARED";
    root@DHCPs2:/ # cat /usr/local/etc/dhcpd.conf.SHARED
    # CLIENTS
    subnet 10.0.10.0 netmask 255.255.255.0 {
      default-lease-time         604800;
      max-lease-time             604800;
      option routers             10.0.10.254;
      option broadcast-address   10.0.10.255;
      option subnet-mask         255.255.255.0;
      option domain-search       "domain.com";
      option domain-name-servers 1.1.1.1,9.9.9.9;
    
      pool {
        failover peer "ha-dhcp";
        range 10.0.10.10 10.0.10.250;
      }
    }
    root@DHCPs1:~ # sysrc dhcpd_enable=YES
    dhcpd_enable:  -> YES
    root@DHCPs1:~ # service isc-dhcpd start
    Starting dhcpd.
    Internet Systems Consortium DHCP Server 4.4.1
    Copyright 2004-2018 Internet Systems Consortium.
    All rights reserved.
    For info, please visit https://www.isc.org/software/dhcp/
    Config file: /usr/local/etc/dhcpd.conf
    Database file: /var/db/dhcpd/dhcpd.leases
    PID file: /var/run/dhcpd/dhcpd.pid
    Wrote 122 leases to leases file.
    Listening on BPF/em0/08:00:27:3c:ab:c8/10.0.10.0/24
    Sending on   BPF/em0/08:00:27:3c:ab:c8/10.0.10.0/24
    Sending on   Socket/fallback/fallback-net
    failover peer ha-dhcp: I move from normal to startup
    root@DHCPs2:~ # sysrc dhcpd_enable=YES
    dhcpd_enable:  -> YES
    root@DHCPs2:~ # service isc-dhcpd onestart
    Starting dhcpd.
    Internet Systems Consortium DHCP Server 4.4.1
    Copyright 2004-2018 Internet Systems Consortium.
    All rights reserved.
    For info, please visit https://www.isc.org/software/dhcp/
    Config file: /usr/local/etc/dhcpd.conf
    Database file: /var/db/dhcpd/dhcpd.leases
    PID file: /var/run/dhcpd/dhcpd.pid
    Wrote 122 leases to leases file.
    Listening on BPF/em0/08:00:27:de:9b:3d/10.0.10.0/24
    Sending on   BPF/em0/08:00:27:de:9b:3d/10.0.10.0/24
    Sending on   Socket/fallback/fallback-net
    failover peer ha-dhcp: I move from communications-interrupted to startup
    root@DHCPc:~ # dhclient em0
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPACK from 10.0.10.251
    bound to 10.0.10.131 -- renewal in 302119 seconds.
    root@DHCPc:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=9b
            ether 08:00:27:d9:45:96
            hwaddr 08:00:27:d9:45:96
            inet 10.0.10.131 netmask 0xffffff00 broadcast 10.0.10.255
            nd6 options=29
            media: Ethernet autoselect (1000baseT )
            status: active
    group
      {
        host DHCPc {
          hardware ethernet 08:00:27:d9:45:96;
          fixed-address 10.0.10.9;
        }
      }
    root@DHCPs1:~ # cat /usr/local/etc/dhcpd.conf.SHARED
    # CLIENTS
    subnet 10.0.10.0 netmask 255.255.255.0 {
      default-lease-time         604800;
      max-lease-time             604800;
      option routers             10.0.10.254;
      option broadcast-address   10.0.10.255;
      option subnet-mask         255.255.255.0;
      option domain-search       "domain.com";
      option domain-name-servers 1.1.1.1,9.9.9.9;
    
      group
      {
        host DHCPc {
          hardware ethernet 08:00:27:d9:45:96;
          fixed-address 10.0.10.9;
        }
      }
    
      pool {
        failover peer "ha-dhcp";
        range 10.0.10.10 10.0.10.250;
      }
    }
    root@DHCPs1:~ # cat /usr/local/etc/dhcpd.conf.SHARED
    # CLIENTS
    subnet 10.0.10.0 netmask 255.255.255.0 {
      default-lease-time         604800;
      max-lease-time             604800;
      option routers             10.0.10.254;
      option broadcast-address   10.0.10.255;
      option subnet-mask         255.255.255.0;
      option domain-search       "domain.com";
      option domain-name-servers 1.1.1.1,9.9.9.9;
    
      group
      {
        host DHCPc {
          hardware ethernet 08:00:27:d9:45:96;
          fixed-address 10.0.10.9;
        }
      }
    
      pool {
        failover peer "ha-dhcp";
        range 10.0.10.10 10.0.10.250;
      }
    }
    root@DHCPc:~ # pkill dhclient
    root@DHCPc:~ # service netif restart
    root@DHCPc:~ # dhclient em0
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPACK from 10.0.10.252
    bound to 10.0.10.131 -- renewal in 1665 seconds.
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPNAK from 10.0.10.252
    DHCPDISCOVER on em0 to 255.255.255.255 port 67 interval 3
    DHCPOFFER from 10.0.10.251
    DHCPOFFER from 10.0.10.252
    DHCPOFFER already seen.
    DHCPREQUEST on em0 to 255.255.255.255 port 67
    DHCPACK from 10.0.10.252
    bound to 10.0.10.9 -- renewal in 302400 seconds.
    root@DHCPc:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
    options=9b
    ether 08:00:27:d9:45:96
    hwaddr 08:00:27:d9:45:96
    inet 10.0.10.9 netmask 0xffffff00 broadcast 10.0.10.255
    nd6 options=29
    media: Ethernet autoselect (1000baseT )
    status: active
    image

    有镜像模式(无法向克隆的仓库提交)

  • 支持的协议(schema)较少 ※后述

  • 总之就是很慢(不会多线程进行 Resolving deltas) 后述

  • ftps:// ※ 什么?(不确定是否被识别)

    FOSDEM 2023 での 発表資料
  • EuroBSDcon 2019 での 発表資料

  • FreeBSD の 入手方法(Git の 利用)

  • got

    1,306,944KB

    1,326,872KB

    git

    1,322,480KB

    1,350,344KB

    Got
    Git
    完全没有必要
    后述
    命令对照表
    git
    got
    got、cvs、svn、git との 比較
    よくある 質問 とその 答 え
    Game of Trees Goals
    Ports Collection のインストール
    引言

    ZFS 文件系统本身就内置了校验和机制,在读取数据时会实时检查校验和与数据的完整性,确保数据没有损坏。

    执行命令 zpool scrub 后,会读取所有已写入的数据部分并与校验和进行一致性检查。如果在 scrub 过程中发现了错误,在具有冗余结构(如镜像或 RAID-Z 等)的情况下,错误会被自动修复。

    在这里,我们将实验性地修改 ZFS 管理范围外的数据,故意制造校验和不一致的情况,以引发数据错误。

    本实验在 FreeBSD 上进行,但如果是在 Ubuntu 等 Linux 系统上的 ZFS,虽然分区创建和磁盘设备名称可能会有所不同,但 ZFS 操作的命令是相同的。

    为实验磁盘创建分区

    首先,创建实验用的 ZFS 池。我们将在 USB 磁盘 da1 上进行实验。

    准备一块带 GPT 标签的磁盘。

    创建一个 4GB 的分区。

    检查创建的分区。

    创建 ZFS 池

    通常情况下,为了节省磁盘空间,当创建 ZFS 池时会使用 -O compression=lz4 等选项启用压缩功能,但本次实验为了写入零数据而没有启用压缩选项。因为启用压缩后,数据压缩会导致数据大小无法被实际写入。

    检查创建的 ZFS 池。

    写入虚拟数据

    Scrub 只会检查已经写入的数据部分的完整性。为了破坏已写入的数据,我们将首先创建一个内容为零的文件。

    进入 ZFS 池内的目录。

    使用 dd 命令从 /dev/zero 读取虚拟数据(即零数据)并填充整个池。

    可以看到,池已被填满。此处我们显式使用 -b 选项以便查看块数。

    故意破坏数据以制造不一致

    池已填满后,我们将故意制造 ZFS 校验和错误。由于通过 ZFS 进行的修改无法破坏数据,我们将从 ZFS 管理外部向磁盘写入垃圾数据。

    首先导出池。

    接着在相关分区的适当位置写入一个块的垃圾数据。

    检查是否损坏

    导入池并尝试读取之前创建的文件

    如上所示,发生了错误。池的状态如下,乍一看似乎没有错误。

    尝试执行 scrub。

    等待 scrub 完成后,使用 status 进行确认。

    可以看到,CKSUM 发生了错误。实际损坏的文件可以通过选项 -v 进行确认。

    重新读取 /ztest/dummy 时,错误依旧存在。

    修复损坏部分并确认

    接下来,通过重新写 0 来恢复损坏的部分。

    这应该已经将数据恢复到原状态,再次尝试读取。

    如上所示,读取成功且没有错误。虽然 zpool status 中的错误信息依然存在,但 CKSUM 的错误计数已经变为 0。

    重新执行 scrub

    scrub 完成后,检查池的状态。

    如上所示,错误已消失。

    ZFS プールを 壊 してみた
    $ pkg install got
    $ git clone https://git.freebsd.org/ports.git /usr/ports
    $ got clone -am ssh://[email protected]/ports.git /home/ports.git
    $ got checkout /home/ports.git /usr/ports
    $ git clone --bare --single-branch ssh://[email protected]/ports.git
    Cloning into bare repository 'ports.git'...
    remote: Enumerating objects: 5942473, done.
    remote: Counting objects: 100% (171767/171767), done.
    remote: Compressing objects: 100% (16358/16358), done.
    remote: Total 5942473 (delta 167421), reused 155423 (delta 155409), pack-reused 5770706
    Receiving objects: 100% (5942473/5942473), 1.12 GiB | 11.01 MiB/s, done.
    Resolving deltas: 100% (3577978/3577978), done.
    $ got clone ssh://[email protected]/ports.git
    Connecting to ssh://[email protected]/ports.git
    server: Enumerating objects: 5963414, done.
    server: Counting objects: 100% (133228/133228), done.
    server: Compressing objects: 100% (13237/13237), done.
    server: Total 5963414 (delta 129757), reused 119991 (delta 119991), pack-reused 5830186
    1157M fetched; indexing 100%; resolving deltas 100%
    Fetched 0d39a9d41ecbf5cd111bcc9ae9f2cfcf7e30a616.pack
    Created cloned repository 'ports.git'
    git clone --bare --single-branch ssh://[email protected]/ports.git
    511.72s user 40.21s system 163% cpu 5:36.76 total
    
    got clone ssh://[email protected]/ports.git
    660.88s user 75.82s system 87% cpu 14:00.91 total
    $ cd /usr/ports && git pull
    $ cd /usr/ports && got fetch && got update
    $ gotadmin info -r /home/ports.git
    repository: /home/ports.git
    remote "origin": ssh://[email protected]/ports.git
    pack files: 4
    packed objects: 5963321
    packed total size: 1318M
    loose objects: 0
    $ cd /usr/ports
    $ gotadmin info
    repository: /home/ports.git
    remote "origin": ssh://[email protected]/ports.git
    pack files: 4
    packed objects: 5963321
    packed total size: 1318M
    loose objects: 0
    $ got info
    work tree: /usr/ports
    work tree base commit: 388fa384c1dab4774d4db755ec1089b57e6f9a97
    work tree path prefix: /
    work tree branch reference: refs/heads/main
    work tree UUID: 0c2bbcf5-8a1d-11ee-8d56-9ca3ba01eed8
    repository: /home/ports.git
    $ got clone -m ssh://[email protected]/ports.git /usr/ports/.git
    Connecting to ssh://[email protected]/ports.git
       :
    Created mirrored repository '/usr/ports/.git'
    $ got checkout /usr/ports/.git /usr/ports/
    got: work tree and repository paths may not overlap: /usr/ports/.git: bad path
    $ gpart create -s gpt da1
    $ gpart add -t freebsd-zfs -a 4k -s 4g -l ttt da1
    $ gpart show da1
    =>       40  312581728  da1  GPT  (149G)
             40    8388608    1  freebsd-zfs  (4.0G)
        8388648  304193120       - free -  (145G)
    
    $ gpart show -l da1
    =>       40  312581728  da1  GPT  (149G)
             40    8388608    1  ttt  (4.0G)
        8388648  304193120       - free -  (145G)
    $ zpool create -O atime=off ztest gpt/ttt
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     0
    
    errors: No known data errors
    $ cd /ztest
    $ dd if=/dev/zero of=dummy bs=4m
    dd: dummy: No space left on device
    928+0 records in
    927+1 records out
    3891134464 bytes transferred in 157.300331 secs (24736976 bytes/sec)
    $
    $ df -b /ztest
    Filesystem 512-blocks    Used Avail Capacity  Mounted on
    ztest         7601024 7601024     0   100%    /ztest
    $ zpool export ztest
    $ dd if=/dev/random of=/dev/gpt/ttt count=1 oseek=4000000
    1+0 records in
    1+0 records out
    512 bytes transferred in 0.382043 secs (1340 bytes/sec)
    $
    $ zpool import ztest
    $ cat /ztest/dummy > /dev/null
    cat: /ztest/dummy: Input/output error
    $
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ zpool scrub ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
      scan: scrub in progress since Mon Aug 29 18:17:33 2022
            3.62G scanned at 412M/s, 550M issued at 61.1M/s, 3.62G total
            0B repaired, 14.81% done, 00:00:51 to go
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     0
    
    errors: No known data errors
    $ 
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    status: One or more devices has experienced an error resulting in data
            corruption.  Applications may be affected.
    action: Restore the file in question if possible.  Otherwise restore the
            entire pool from backup.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A
      scan: scrub repaired 0B in 00:01:05 with 1 errors on Mon Aug 29 18:18:32 2022
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     2
    
    errors: 1 data errors, use '-v' for a list
    $
    $ zpool status -v ztest
      pool: ztest
     state: ONLINE
    status: One or more devices has experienced an error resulting in data
            corruption.  Applications may be affected.
    action: Restore the file in question if possible.  Otherwise restore the
            entire pool from backup.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A
      scan: scrub repaired 0B in 00:01:05 with 1 errors on Mon Aug 29 18:18:32 2022
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     2
    
    errors: Permanent errors have been detected in the following files:
    
            /ztest/dummy
    $
    $ cat /ztest/dummy > /dev/null
    cat: /ztest/dummy: Input/output error
    $
    $ zpool export ztest
    $ dd if=/dev/zero of=/dev/gpt/ttt count=1 oseek=4000000
    1+0 records in
    1+0 records out
    512 bytes transferred in 0.382715 secs (1338 bytes/sec)
    $
    $ zpool import ztest
    $ cat /ztest/dummy > /dev/null
    $
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    status: One or more devices has experienced an error resulting in data
            corruption.  Applications may be affected.
    action: Restore the file in question if possible.  Otherwise restore the
            entire pool from backup.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-8A
      scan: scrub repaired 0B in 00:01:05 with 1 errors on Mon Aug 29 18:18:32 2022
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     0
    
    errors: 1 data errors, use '-v' for a list
    $
    $ zpool scrub ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
      scan: scrub repaired 0B in 00:01:05 with 0 errors on Mon Aug 29 18:34:27 2022
    config:
    
            NAME        STATE     READ WRITE CKSUM
            ztest       ONLINE       0     0     0
              gpt/ttt   ONLINE       0     0     0
    
    errors: No known data errors
    $

    分区大小(-s)推荐为 984 扇区。

    • 这样可以确保下一分区(freebsd-ufs)从 512KiB 边界开始 [8]。

    • 由于引导加载器的限制,分区大小不得小于 545KiB,所以下面的大小为 492KiB。

    • 因此,调整分区大小没有必要,也没有更多的空间来增大它。

    分区大小(-s)建议设置为 409560 扇区。

    • 这个设置确保下一个分区(freebsd-ufs)从 200MiB 边界开始。

    • 该分区的实际大小略小于 200MiB(少 40 扇区,即 20KB),但可以忽略不计。

    • 目前,11.2-R 的启动分区(/boot/boot1.efifat)的大小为 800KiB。

    • 在 10.4-R 或 11.1-R 版本中,推荐为该分区分配 200MiB,以考虑与其他操作系统(如 macOS)的兼容性。如果仅启动 FreeBSD,800KiB 的大小应无问题。

    • 在 的讨论中指出,为了支持固件更新工具等 EFI 应用程序,800KiB 的分区大小可能过小。

    FreeBSD 11.1 版本说明
  • bsdinstall: 增加 EFI 分区大小至 200MB

  • GPT 和 MBR 的区别是什么?

  • 通过命令行创建 FreeBSD 启动分区等

  • FreeBSD/UEFI 相关信息

  • 执行顺序需要注意。如果按此顺序执行,将无法分配启动分区(分区号会错位)。

  • 可以使用 -i 分区号 或 -b 起始位置 -i 分区号 选项来进行控制,但作为基本说明,建议不使用这些选项。

  • LBA 0 到 LBA 33 是 GPT 头区域。

  • 在现代各种介质(例如 4 KiB 扇区的 HDD 或 NAND 闪存等)中,边界 的最小公倍数(如果有 512 KiB 则适用于任何介质)是一个相当合理的数字(应该如此)。

  • gptboot 会查找 freebsd-ufs 分区中的 /boot/loader,gptzfsboot 会查找 freebsd-zfs 分区中的 /boot/zfsloader。

  • 由于“/boot/(zfs)loader”绑定到存储该文件的分区的文件系统,因此在引导时会解释为 UFS,而根文件系统使用 ZFS 的混合环境会解释为“UFS”。

  • 会查找 freebsd-ufs 或 freebsd-zfs 分区,但其优先级和控制方式较难解释,因此请参考 参考文献。虽然并不复杂,但因为需要对文件系统级别进行调整,所以需要进一步深入了解。

  • ada0p1

    freebsd-boot 或 efi

    启动分区

    ada0p2

    freebsd-ufs [3]

    FreeBSD 分区

    ada0p3

    freebsd-swap

    交换分区

    Bootable UEFI memory stick or Hard Disk
    后续说明
    gpart(8) 的手册
    FreeBSD 的启动过程
    UEFI - FreeBSD Wiki
    FreeBSD 10.4 版本说明
    开始

    虽然现在谈论 ccache 可能有些晚,但它作为加速构建过程的工具非常有名。通过调查,我们发现现有的很多信息已经过时。最近 FreeBSD 中的配置方法已经有所变化,但并没有找到相关的更新信息。因此,本篇将重点介绍这一变化,并分析其效果。

    ※与以前的设置方法相比,现在的控制变得非常简便。

    测试环境

    • FreeBSD 13.0-RELEASE-p5

    • FreeBSD 12.2-RELEASE-p11

    这次不讨论 ccache 的安装过程(没有特别的步骤)。为了进行磁盘使用量调查,我们提前执行了以下命令,确保不会出现缓存无法生效的情况。结论是,默认的 5GB 使用量在 FreeBSD 的构建过程中是完全没有问题的。

    扩展缓存容量(5GB → 32GB)

    值得注意的是,“字节”的 SI 前缀基本上是以 $10^3$ 为单位的。如果想使用 $2^{10}$ 作为单位,需要明确使用 103103 作为基本单位。如果要使用 $2^{10}$ 的方式表示容量,应该使用 32Gi(尽管显示仍不可更改)。另外,如果只是输入数字而不指定单位,默认会被解释为 G。

    配置(/etc/src.conf)

    /etc/src.conf

    如果只是使用 ccache 来进行 buildworld 构建,那么只需要设置上面的配置即可。无需再手动设置环境变量 CC="ccache cc"(这一点非常重要!)。

    对于 buildworld 或 buildkernel 构建中需要开启或关闭的组件,可以参考 src.conf(5) 文档,我自己目前还没有确认遗漏的部分(因为选项实在太多了…)。

    执行 make buildworld

    我们从没有缓存的状态开始执行 make buildworld。为了分析缓存命中率等信息,构建完成后,我运行了 ccache -s 来获取统计信息。

    第一次执行结果

    如下所示,几乎所有文件都进行了编译。由于 ccache 的开销,首次编译的时间比正常编译时间稍长。此外,虽然发生了一些重新编译,但比例极小,不到 0.2%,可以忽略不计。

    第一次执行结果(从无缓存状态开始构建)

    此外,实际的缓存使用量并未反映出来,这一点导致了一些不准确的结果。稍后将详细说明这一点。

    第二次执行结果

    在收集上述数据后,我再次执行了 buildworld。如下所示,结果显示了 100% 的缓存命中率,最终得出了「50.09%」的结果。

    第二次执行结果(从缓存状态中进行构建)

    清空统计信息后的第三次执行结果

    执行了 ccache -z 清空统计信息后,再次进行了 buildworld。如下所示,结果显示了 100% 的缓存命中率。这次没有进行任何编译,因此 buildworld 执行时间大大缩短。

    清空统计信息后的第三次执行结果(从缓存状态中进行构建)

    执行清理操作

    关于缓存大小未能即时反映的问题,我执行了 ccache -c 清理操作,成功将统计数据更新至最新状态。

    清理后正常化的统计信息

    如你所见,即便是 5GB 的缓存,也能勉强满足需求。

    基准测试

    buildkernel 示例

    从 karl 收到以下环境下的 make buildkernel 测量结果,并将其整理成表格。

    • CPU: AMD Ryzen9 3900(3.10GHz/4.30GHz)

    • 内存:32GB

    • 存储:WesternDigital SN550(NVMe 连接)· ZFS 操作

    • 构建目标:FreeBSD 14-CURRENT

    构建步骤
    无 CCache 时间
    有 CCache 时间

    make buildkernel

    1406 秒

    837 秒

    make -j4 buildkernel

    366 秒

    -

    make -j8 buildkernel

    200 秒

    -

    make -j12 buildkernel

    155 秒

    82 秒

    需要注意的是,CPU 资源未被完全消耗。

    buildworld 示例

    • CPU:Intel Pentium N4200(1.10GHz/2.50GHz·Apollo Lake·Goldmont 架构)

    • 内存:16GB

    • 存储:Transcend MTS400S(SATA 连接)· ZFS 操作

    • 构建目标:12.2-RELEASE-p11

    构建步骤※
    构建时间

    无 CCache

    22317 秒

    有 CCache(一轮)

    25603 秒

    有 CCache(二轮)

    3841 秒

    有 CCache(三轮)

    3854 秒

    ※均指定了 make -j5 buildworld

    总结

    • 无论构建并行度(-j 选项的设置)高低如何,100% 缓存命中时都会带来几倍级别的时间缩短效果(几分钟内完成构建)。

    • 对于 buildkernel 这种几乎全由 C 语言构成的构建,效果约为两倍;而对于包含 LLVM 这类重型构建的 buildworld,效果可达到六倍左右。

    • 引入 ccache 后的初始开销为 14%,但作为二次及后续构建效果的代价,这一开销可以忽略。

    • 在开发等场景下,经常需要稍微修改并重新构建的情况,ccache 的效果非常显著。

    • 本次测试还表明,在纯粹的重新构建场景下,100% 不会重新编译。这一点在执行 make clean 后,即使对象文件被删除,也得到了验证。

    • 近年来,FreeBSD 的开发环境(如 LLVM)的构建时间显著增加,而 ccache 在缩短构建时间(无论是时间上还是内存上)方面效果极为显著。

    • 然而,初次编译时所需的内存仍然是个问题,因此在内存较小的环境下进行构建仍然是一个挑战。

    ccache 的代表性命令与选项

    由于 ccache 本身较为简洁,因此相关的文档较少,下面简单总结了一些常用命令与选项。

    命令
    含义
    备注

    ccache -M n

    设置缓存容量(如果未指定,默认为 G)

    指定最大缓存容量※

    ccache -s

    显示统计信息

    ccache -z

    清除统计信息

    ccache -c

    清理缓存目录

    清理操作不会删除已缓存的数据

    ※n 可以指定的后缀包括:“k”,“M”,“G”,“T”,“Ki”,“Mi”,“Gi”,“Ti”。

    常见问题及解答

    问:能不能在 /etc/make.conf 中设置?

    答:/etc/make.conf 会被必定读取,因此实质上与在 /etc/src.conf 中设置相同。不过,若在 FreeBSD 的构建以外的其他地方使用该设置,行为无法保证。如果不介意这些差异,可以在 /etc/make.conf 中设置。为了与其他构建区分,建议将设置放在 /etc/src.conf 中。

    ccache で FreeBSD を buildworld した 場合 の 効率 について
    会议日期: 2023 年 9 月 4 日当周
  • 会议录像链接: Meeting Recording

  • TL; DR 以下表格总结了优先项目的状态。蓝色行似乎是我们可以立即采取行动的项目:

    项目
    明白下一步怎么做
    项目负责人
    用户/测试者
    开发者

    云原生 / OCI 运行时

    是

    Greg W

    是

    是

    AD / DNS

    是

    Michael O

    是

    否

    鉴于这个工作组在“Zero Trust Builds”和“Ports Automation”项目上可能取得的进展有限,我们建议将它们放到一旁,而不是将更好的证书机构支持纳入范围,因为社区似乎可以采取明确的下一步行动。

    我们回顾了功能和基础设施优先级和难度调查的结果,并开始制定下一步计划,以解决最高优先级的问题。

    以下是工作组为通用企业调查用例的功能和基础设施需求优先级的排名:

    image
    image

    然后,我们逐个讨论了每个类别中的前三个问题以及如何继续。

    Cloud Native / OCI runtime

    这被认为是最重要的缺失部分,差距很大。令人高兴的是,已经有正在进行的工作。

    以下是我所了解到的现有项目:

    项目
    说明
    链接

    Planternetes

    将 K8s v1.28.0 移植到 illumos,并为 FreeBSD 和 OpenBSD 编译了二进制文件。

    runj

    一个新的实验性、概念验证的 OCI 兼容运行时,用于 FreeBSD jail。

    ocijail

    实验性、概念验证的 OCI 兼容运行时,用于 jail。

    Podman port to FreeBSD

    在 FreeBSD 上使用 Podman 来管理 Pod、容器和容器镜像。

    接下来的步骤

    • 我们同意完成一个非常轻量级的 PRD(产品需求文档),以便我们就最终目标达成一致。

      • 需要志愿者。

    • 开发测试和文档协议,并根据 PRD 评估上述列出的方法。

      • 需要 3 名志愿者或更多。

    • 确定哪种方法最适合要求,然后确定如何将其推向生产就绪状态。

      • 需要 2 名志愿者。

    • 我已经创建了一个 Wrike 项目,包括上述三项任务,并将邀请志愿者加入。

    AD / DNS 集成

    正在寻找志愿者协助。下一步是进行电话会议,了解现有状态和所需工作。

    NVIDIA GPU / CUDA

    这个问题引发了一些很好的讨论。在 FreeBSD 中需要支持这些芯片和驱动程序,以用于高性能计算和人工智能工作负载。这些市场的许多用户喜欢 FreeBSD,因为它具有安全性、稳定性和性能,但需要更多的 NVIDIA 本机支持。讨论的一个使用模型是在私有数据上训练模型,然后在 FreeBSD 上托管,以获得诸如 ZFS、安全性等功能的好处。保护数据模型至关重要,并且在 FreeBSD 上托管是实现这一目标的好方法。

    我提供了两个链接,以提供特性请求给 Nvidia:

    • Will CUDA work with FreeBSD?

    • UDA and /(nv_(un|)register|os_(un|)lock)_user_pages/

    如果社区可以持续请求对 FreeBSD 的支持,希望能够得到 NVIDIA 的一些帮助。

    工作组中的其他两名成员表示愿意提供帮助。感谢他们!

    • Zoran,来自 Supermicro,可以测试并提供错误以帮助支持驱动程序开发。

    • Jason 可以在 Azure 上提供帮助。

    • 我将有机会在下周与 NVIDIA 的一些人交谈,并将提出这个讨论并报告回应。

    Samba

    在上周早些时候,我们与一位有着与 Samba 团队合作经验的开发者进行了交谈。他们将通过电子邮件联系 Samba 团队,并提供帮助将补丁(回馈给)上游。

    Samba 团队和其他项目要求的一个事项是使用 FreeBSD 进行 GitHub Actions,以帮助自动化工作。FreeBSD 基金会将联系 GitHub 和 Microsoft 的人,尝试将这个功能引入。

    我已经创建了一个 Wrike 项目,包括上述三项任务,并将邀请志愿者加入。

    bhyve/VM/Jail 的 Definitive manager

    现在有 5-6 个 VM 管理器,大部分相同。

    工作组似乎同意最好的下一步是组织一个电话会议或某种讨论,与各种工具的维护者讨论是否可以通过整合来提高效率。

    通过这个过程,希望有一个默认的配置。

    正在寻找志愿者协助。

    企业 CA(推进的原因是似乎需要的工作量较小,而“Zero Trust Builds”和“Ports Automation”目前对工作组无效)

    与 AD/DNS 类似,这里的下一步是进行快速电话会议——查看目前的情况,还需要做什么,需要有人可以提交补丁。

    Greg 将采取行动,与 Joe/Ed/其他人一起确定谁是最适合提供帮助的人。

    这是第二次企业工作组会议的回顾摘要,详细信息可在会议录像中找到。

    Recap of Second Enterprise Working Group Meeting
    jmore(8)
    New jmore(8) FreeBSD Jails List/Manage Tool
    OpenBSD
    FreeBSD
    提取到存储设备
    "FAQ" 部分
    Handbook
    开源和专有硬件驱动程序的支持
    基于 BSD 的操作系统上
    distrowatch.com
    image
    image
    image
    image
    image
    image
    image
    image

    苹果的开源基石:macOS 和 iOS 背后的 BSD 传统

    • 原文地址:Apple’s Open Source Roots: The BSD Heritage Behind macOS and iOS

    • 原作者:Jason Perlow

    • 原文发布时间:2024 年 7 月 8 日凌晨 5:00

    认识到 BSD 在苹果成功中的重要性,有助于我们更好地理解开源贡献在塑造我们日常使用的技术中之价值。

    想一想:苹果时尚且易用的设备,如强大的 MacBook 和无处不在的 iPhone,它们的可靠性和性能,在很大程度上得益于开源操作系统。那么,苹果究竟使用的是哪款开源操作系统呢?尽管常有人说,苹果的 macOS、iOS、iPadOS、watchOS、visionOS 和 tvOS 直接源自 FreeBSD,但其实这是一种误解。

    这些操作系统的真正基石在于苹果较早期的操作系统技术与 NeXTSTEP 的结合,而 NeXTSTEP 本身是 Mach 和 BSD 的混合体——早于 FreeBSD。尽管多年来,FreeBSD 的一些用户空间元素被整合进上述操作系统,但苹果的内核(XNU)并不直接来源于 FreeBSD。然而,它们确实共享一脉共同的 BSD 传统。

    理解 BSD 各版本

    要了解苹果操作系统的发展,理解不同版本的 BSD(伯克利软件发行版)及其影响至关重要:

    伯克利的原始 BSD

    BSD 起源于 1970 年代末的加州大学伯克利分校。作为对 AT&T 原始 UNIX 操作系统的增强,BSD 引入了许多成为现代操作系统标准的创新。第一个版本 1BSD 发布于 1977 年,随后是 1978 年的 2BSD。重要版本包括 4.1BSD(1981 年)和 4.2BSD(1983 年),它们引入了快速文件系统(FFS)、TCP/IP 网络和套接字 API,这些基础要素至今仍在使用。

    FreeBSD

    FreeBSD 是从原始 BSD 衍生而来的,以其出色的性能、先进的网络功能和广泛的硬件支持而著称。它源自 1993 年的 386BSD 项目,至今广泛应用于服务器、桌面和嵌入式系统。FreeBSD 强大的性能和可靠性使其成为高可用性应用和互联网基础设施的首选。

    NetBSD

    NetBSD 以其在多种硬件平台上的可移植性而闻名。其座右铭“Of course it runs NetBSD”(它当然可以运行 NetBSD)体现了它在各种硬件架构上运行的能力,从服务器和桌面到嵌入式设备和大型机。自 1993 年成立以来,NetBSD 一直是 BSD 系列中可移植性和简洁设计的典范。

    OpenBSD

    OpenBSD 是于 1995 年,从 NetBSD 复刻出来的,重点关注安全性、正确性和代码简洁性。它以严格的安全实践而闻名,并且是许多安全技术的先驱,如 OpenSSH、PF(包过滤器)和安全内存管理技术。OpenBSD 对安全性的承诺使其成为那些安全至关重要的应用程序的首选。

    其他衍生 BSD

    出现了几款衍生的 BSD,每款变种都有其独特的重点和增强功能。例如,DragonFly BSD 注重性能和可扩展性,而 Darwin 则是苹果 macOS 和 iOS 的内核。

    Darwin 和 XNU:苹果操作系统的内核

    macOS 的核心是 XNU 内核,这是一款混合内核,结合了 Mach 微内核、BSD 组件和 I/O Kit(设备驱动的面向对象 API)。这种集成确保了 macOS 受益于 BSD 类 Unix 的强大稳定性,同时利用了 Mach 微内核的灵活性。

    Darwin 是苹果操作系统(macOS、iOS、watchOS、tvOS 和 iPadOS)的开源基石,它包括了 XNU 内核、各种 BSD 组件和其他开源项目。Darwin 的起源可以追溯到 NeXT,这是一家由史蒂夫·乔布斯在 1985 年创办的公司,他离开苹果后创办了这家公司。NeXT 开发了 NeXTSTEP,这是一种基于 Mach 微内核和 BSD 的操作系统。它发展成为 OpenStep,并最终在史蒂夫·乔布斯回归苹果时演变成 Darwin,带回了 NeXT 的技术。

    2000 年,苹果发布了 Mac OS X 的一些核心组件(现在的 macOS)作为开源项目,采用 Apple 公共源代码许可证(APSL),允许更广泛的社区受益并为其开发做出贡献。这些组件包括 launchd、Grand Central Dispatch 和 Core Foundation,其中一些后来在更宽松的 Apache 许可证下重新授权,以促进更广泛的应用。然而,高级组件如 Cocoa 和 Carbon 框架仍然是专有的,以保持苹果的竞争优势。GPL 和 BSD 许可的组件未重新授权,保持了其原有的 。

    详细时间线

    • 1969 年:AT&T 贝尔实验室开发了 UNIX 操作系统。

    • 1977 年:加州大学伯克利分校发布了 BSD 的首个版本(1BSD),作为对 AT&T 原始 UNIX 操作系统的增强。

    • 1978 年:2BSD 发布,继续在 1BSD 的基础上进行改进和工具开发。

    • 1980 年:3BSD 发布,加入了更先进的特性和改进。

    BSD 组件在 macOS 中的演变与整合

    苹果的 macOS 是一款混合化的操作系统,集成了来自不同 BSD 变种的各种组件,形成了一个强大且多功能的平台。macOS 的内核是 XNU,它是一款混合内核,结合了来自 Mach、NeXTSTEP 和 OpenStep 的元素,并且加入了来自 BSD 的其他组件。这一基础架构利用了每个系统的优势,提供了一款可靠且高性能的操作系统。

    网络栈:macOS 的网络栈源自 FreeBSD 和其他 BSD 变种,集成了它们可靠和高效的网络功能。早期的网络元素,如 TCP/IP 栈,受 FreeBSD 设计的影响,因其性能和可靠性而闻名。包括最初为 FreeBSD 开发的 kqueue 事件通知接口,也增强了 macOS 处理 I/O 事件的能力。苹果的实现结合了来自 BSD 和 FreeBSD 的代码,但也包含了像网络内核扩展(NKE)、面向对象的设备驱动系统(IOKit)以及磁盘仲裁层等独特机制。这些组件与传统 BSD 实现有所不同。

    虚拟文件系统:macOS 的虚拟文件系统组件来自 FreeBSD 和其他 BSD 系统,确保了稳定和安全的文件管理系统。

    内存管理:macOS 的内存管理系统主要来源于 Mach,并受 NetBSD 的影响,特别是在共享/合并缓冲区缓存方面。

    进程模型:macOS 的进程模型基于 Mach,使用 Mach 系统线程作为进程子系统的基础层。

    Mach IPC 和安全性:Mach IPC 广泛应用于 macOS 和 iOS 的内核及用户空间,引入了进一步的差异。例如,Mach Security Trailers 是受信任的 IPC 的基础部分。应用程序沙箱中使用的强制访问控制(MAC)机制也与 *BSD 系统中的机制大相径庭。

    随着时间的推移发生的分歧:由于 FreeBSD 不愿意整合 UNIX03 兼容性更改,导致了分歧,尽管有一些混合的努力,像 libc 和 libm 这样的库还是出现了复刻。此外,像 NeXTBSD 项目这样的倡议,旨在将像 launchd、Mach IPC 和 Grand Central Dispatch 等苹果的技术带到 FreeBSD,但这些努力未能得到普遍支持。结果,代码库继续出现分歧,尤其是在苹果推进定制芯片支持和优化时,进一步拉大了它们之间的差距。

    已知的集成和贡献:macOS 在很大程度上受益于 FreeBSD,尤其是在网络概念上。尽管 macOS 并未完全采用 FreeBSD 的网络栈,但它集成了几款 FreeBSD 衍生的组件,经过调整以满足其独特的需求。macOS 中的早期网络元素,如 TCP/IP 栈,受 FreeBSD 设计的影响,以其性能和可靠性而著称。此外,像最初为 FreeBSD 开发的 kqueue 事件通知接口也被集成到 macOS 中,增强了它处理 I/O 事件的能力。

    对苹果产品的影响

    苹果对 BSD 代码的采用遍及其整个产品线。macOS 驱动着 Mac 台式机和笔记本,iOS 运行在 iPhone 上,iPadOS 运行在 iPad 上,watchOS 运行在 Apple Watch 上,visionOS 运行在 AR/VR 设备上,tvOS 运行在 Apple TV 上。每款操作系统都包含了 BSD 组件,突显了 BSD 在苹果生态系统中的广泛影响。

    BSD 的稳健性、安全性和性能特点在塑造苹果操作系统的稳定性和效率方面发挥了重要作用。集成 BSD 衍生的网络概念和组件,使得 macOS 能够提供高性能的网络功能,使其成为消费者和企业应用的可靠选择。BSD 的先进内存管理和进程调度也对 macOS 的响应能力和多任务处理能力作出了贡献。

    通过将 BSD 的强大特性与其专有技术相结合,苹果创造了一系列稳定、高效、创新且功能强大的操作系统。这种共生关系凸显了开源贡献在苹果软件生态系统持续演变中的重要性。

    苹果对开源的贡献与利用

    苹果公司在高度依赖 BSD 的同时,也积极参与着开源社区。公司通过其 和 发布了多项 Darwin OS 组件,包括 XNU 内核、各种用户空间工具和库。这些贡献确保了开源社区能够从苹果的创新和改进中受益。

    苹果会定期更新其开源项目,发布 Darwin OS 组件的新版本。这些更新通常与新的 macOS 和 iOS 版本发布同步,体现了苹果对开源社区的持续承诺。通过共享其改进和增强功能,苹果推动了 ,为开发者和用户带来益处。

    Darwin OS 的现状

    Darwin OS 是苹果操作系统的开源核心,目前已不再作为完整的、可安装的系统发布。苹果将 Darwin 的各个组件分开发布,例如 XNU 内核仓库在 GitHub 上,用户空间工具则发布在苹果的开源网站上。这种分散的发布策略使得从苹果的官方渠道组装完整的 Darwin OS 变得困难。

    通过 OpenDarwin 项目,苹果曾使这些组件能够单独安装并作为独立系统存在。然而,由于开发的兴趣有限和分歧逐渐加大,OpenDarwin 于 2006 年停止发布。苹果当时的目标值得称赞,但随着复刻过多,最终无法维持该项目,导致了当前的碎片化分发方式。

    尽管从苹果处获得完整的 Darwin OS 存在挑战,开源社区仍尝试将这些组件整合为可安装的操作系统,取得了一定的成功。像 (以及之前的 OpenDarwin)这样的社区驱动项目,旨在通过整合苹果发布的各种开源组件,提供可用的 Darwin OS 版本。这些项目展现了开源开发的合作精神,并证明了 Darwin OS 作为独立操作系统的潜力。

    苹果与 BSD 的现有关系

    苹果与 BSD 代码的关系仍然相当神秘。尽管苹果在开源方面作出了重大贡献,但该公司在操作系统中 BSD 代码的具体使用程度仍然较为模糊。这种封闭的开发过程使得很难准确指出 macOS、iOS 及其他苹果系统中有多少部分仍依赖于 BSD 基石。 的宽松性允许苹果使用并修改代码,而无需公开其使用方式和位置,这与 的“传染性”要求有所不同,后者要求修改后的代码必须共享。

    苹果的开源软件策略随着时间的推移发生了变化。公司将焦点从 CoreOS 的开源组件转向了其他领域,如编程语言和编译器技术。苹果投入大量时间和精力开发项目如 、 编译器和 运行时。这些项目代表了苹果对开源社区的主要贡献,并展示了苹果与 BSD 之间的技术转移,尤其是在编译工具链方面。

    此外,随着苹果对原始 BSD 组件的大量修改,传统 BSD 代码与现代改编之间的界限变得模糊。苹果在不断修改和扩展这些组件后,已经很难区分哪些部分是直接继承自 BSD 的,哪些是苹果的创新。这种不透明性限制了我们对 BSD 在苹果产品中全貌的理解,也突出了 BSD 的宽松许可证与 GPL 的传染性要求之间的差异。

    有证据表明,苹果仍在其操作系统中使用着当前的 BSD 组件。最近, 由 Klara 公司提交,该公司代表多个客户(如 NetApp)向 FreeBSD 项目提交代码,这表明 FreeBSD 代码的持续集成和使用,证明了尽管苹果的开发过程封闭,BSD 代码(尤其是 FreeBSD)仍然是其操作系统的重要组成部分。

    市场影响与采用

    苹果在其产品中使用 BSD 对消费电子行业和创意内容行业产生了重大影响。BSD 的稳健性、安全性和性能使得苹果设备对消费者和专业人士极具吸引力。电影、音乐制作、图形设计等创意领域的行业尤其青睐苹果产品,因为它们可靠且功能强大。

    BSD 的先进内存管理、进程调度和高性能网络能力确保了苹果的桌面和笔记本电脑为高要求的应用提供所需的性能。这使得 macOS 成为视频编辑、音乐制作和图形设计的优秀选择,在这些领域,稳定性和性能至关重要。

    其他行业利用 BSD

    虽然苹果集成 BSD 对其成功起到了关键作用,但 BSD 的特性也使其成为其他各行各业供应商的首选。例如,NetApp、Netflix、Juniper(均为 FreeBSD 用户)等公司,利用 BSD 的先进功能应用于不同的领域:

    • 安全性: BSD 强大的网络功能和安全措施使其在安全通信和数据保护领域尤为适用。

    • 互联网流量管理: BSD 可靠的 TCP/IP 栈确保了高数据量的有效处理,使其在互联网流量管理中大有作为。

    • 嵌入式系统: BSD 的先进内存管理和进程调度提高了嵌入式系统的效率和可靠性。

    • 存储解决方案: NetApp 等公司利用 BSD 提供强大而高效的存储解决方案。

    通过认识到 BSD 的广泛应用,我们可以更好地理解 BSD 对苹果产品以及广泛行业的影响,彰显了这一开源操作系统的多样性和稳健性。

    产品数量与市场覆盖

    苹果发布了多款运行 macOS、iOS、iPadOS、watchOS、tvOS 和 visionOS 的产品。因此,全球许多设备中都包含 BSD 代码。这些设备的出货量和运行数量,包括嵌入式设备、桌面/笔记本电脑,甚至苹果公司数据中心内的服务器计算机,可能与运行 Linux 的设备和系统数量相当,甚至更多。这强有力地证明了 BSD 在苹果生态系统中的广泛采用与影响。

    苹果的设备遍布各行各业,满足不同消费者群体的需求。这种广泛的市场覆盖展示了 BSD 对苹果操作系统成功和可靠性的贡献。来自 BSD 的无缝用户体验、强大性能和安全性使得苹果产品成为全球数百万用户的首选。

    展望

    苹果在开发其操作系统(包括 macOS、iOS、iPadOS、watchOS、visionOS 和 tvOS)时,极度依赖 BSD 代码。通过集成 BSD 组件,苹果为创新、稳定性和性能奠定了坚实的基础。尽管苹果系统中 BSD 代码的具体使用程度不透明,但显然,BSD 在苹果产品的设计和功能中起到了重要作用。

    展望未来,苹果可能会继续利用 BSD 的优势,并为开源社区作出贡献。BSD 和苹果操作系统的不断演进,暗示了开源合作在技术进步中的重要性。认识到 BSD 在苹果成功中的重要性,有助于我们更好地理解开源贡献在塑造我们日常使用技术中之价值。

    参考文献与进一步阅读:


    Jason Perlow 是一位技术专家,拥有二十余年的经验,曾在财富 500 强公司中整合大型异构多供应商计算环境。他曾担任 Linux 基金会的前编辑总监。目前,他在佛罗里达州科勒尔斯普林斯经营着自己的技术媒体咨询公司——Argonaut Media Communications LLC。

    FreeBSD 日专访 BSD 守护神 Beastie

    • 原文链接:FreeBSD Day Interview with Beastie, the BSD Daemon

    • 发布日期:2024 年 6 月 21 日

    Kim McMahon: 嗨,Beastie,谢谢你今天加入我们一起庆祝 FreeBSD 周!很荣幸有你在这里。

    Beastie: 嘿,Kim!(兴奋地打响指)非常激动能来这。FreeBSD 周?更像是 FreeBSD 派对周,对吧?

    Kim McMahon: 告诉我们你是怎么成为 BSD 吉祥物 Beastie 的吧。

    Beastie(若有所思地摸着下巴): 啊,BSD 守护神的历史是由两位传奇人物共同谱写的传奇!初章始于 1976 年,当时一位才华横溢的漫画艺术家 Phil Foglio 为传奇的 USENIX 会议创作了一群 调皮的小红色守护神角色,他们正爬在 PDP-11 计算机的卡通形象上,象征着那些让系统保持运行的背景进程——Unix 世界中的“守护神”。那群小家伙一度非常受欢迎,印在 T 恤上!

    Kim McMahon: 真有趣!然后是你出现了,Beastie?

    Beastie(微笑): 在 1984 年,约翰·拉塞特(John Lasseter),当时在卢卡斯电影公司工作,后来成为动画界的杰出人物,为一本 Unix 手册的封面画了 BSD 守护神的灰度图。这位约翰·拉塞特就是后来写作并导演了《玩具总动员》、《虫虫危机》、《玩具总动员 2》、《汽车总动员》以及《赛车总动员 2》等著名迪士尼/皮克斯电影的那位!

    Kim McMahon: 哇,真是太酷了!

    Beastie: 还有更酷的呢!几年后,1988 年,约翰设计了我们今天看到的 ,还配上了我 trusty(三叉戟)。这个设计出现在 先生的一本书中,他是 BSD 世界中的一位大人物。剩下的,正如人们常说的,是历史!所以,Foglio 的那群顽皮角色铺平了道路,而约翰的设计则巩固了 BSD 守护神的形象,成为我们今天所熟知并喜爱的样子。

    Kim McMahon: 作为 BSD 吉祥物,你在 FreeBSD 社区中最重要的角色是什么?

    Beastie: 想象一下:我是终极啦啦队员,但还带点小恶作剧。想象我用以太网线当拨片,疯狂弹着空气吉他,一边大喊“FreeBSD!FreeBSD!耶!”特别是在调试怪问题的通宵工作中,我的任务是保持大家的士气高涨。至于领导力?我通过时尚守护神的艺术来树立榜样。代码审查?我把这交给那些巫师们,但我提供精神支持,或许还会用我的三叉戟给大家一个击掌。嘿,谁都需要一个啦啦队员,哪怕是硬核程序员!

    Kim McMahon: FreeBSD 以其稳定性和安全性著称。你在充满技术混乱的环境中保持这种禅定般的心态的秘诀是什么?

    Beastie: 平衡,亲爱的 Kim,平衡。在经历了一整天的代码提交后,我会在服务器房间的温暖光辉下放松,喝上一点“守护神饮品”——它就像是为压力大的守护神们调制的神奇饮品。但这还不是全部!定期进行三叉戟旋转练习出奇地有疗效(而且是绝佳的臂力锻炼)。瑜伽?没错!倒立式守护神或威严的三叉戟姿势,随你选。有时候,我甚至会在听着服务器风扇的轻柔嗡嗡声时冥想。最重要的是在数据流中找到宁静。当别人因服务器崩溃而焦虑时,我会深呼吸,调整一下我的角,提醒自己:一切都会好起来的,只要有 FreeBSD 的稳定性和一点点守护神的禅意。

    Kim McMahon: Beastie,你已经在这里待了很长时间了。你是怎么跟上所有最新的技术进展的?你是不是有什么秘密的技术实验室隐藏在某个地方?

    Beastie: (低声)要是有就好了!想象一下,有闪烁的灯光、成堆的服务器,还有一个机器人助手帮我拿虚拟现实头盔。唉,我这守护神可没有秘密实验室。但我的秘密武器是社区参与和古老的好奇心的完美结合。我参加所有的 FreeBSD 大会——无论是线上还是线下(那些赠品包真是太棒了!)。你会惊讶于从走廊的对话和与杰出开发者的深夜编码会议中学到什么。此外,我像饿疯的妖精看食谱一样吞噬提交日志。真是太有趣了!当我不在现场时,我就呆在 IRC 频道里,那里才是魔法发生的地方。没有什么比极客讨论更能保持头脑敏锐、角尖闪亮的了。嘿,谁能抗拒技术博客、播客和偶尔的 Twitter 讨论呢?作为 FreeBSD 家庭的一员,保持最新的动态简直是轻而易举。

    Kim McMahon: Beastie 的典型一天是怎样的?是编码、开会,还是策划世界统治?

    Beastie: (狡猾地笑)什么都有一点!我的早晨开始于一杯热腾腾的守护神饮品,然后进入代码世界。修补漏洞和修复内核崩溃是我醒来的方式。谁还需要咖啡,当你有激动人心的编码挑战时?到了上午中期,我已经全身心投入编码会议,头脑风暴新的功能,让 FreeBSD 变得更棒。午餐是一只手吃的,保持双手在键盘上飞舞。没错,双手并用的编码真是存在的!

    Kim McMahon(挑眉):有意思……

    Beastie: 下午就是开会和社区助威的时候!无论是与开发者一起头脑风暴,在 IRC 频道虚拟地给大家击掌,还是策划下一场史诗般的 FreeBSD 大会,我都在保持社区的联系,让大家充满创意。还有,不要忘了偶尔跳一段自发的舞蹈,伴随服务器风扇混音。得保持精力充沛啊。随着一天的结束,我会回顾自己的成就,为明天制定策略。晚上的时间是……好吧,稍微计划一下世界统治。开玩笑的(大部分时候)!这是我释放创意的时候,画出雄心勃勃的项目想法,或者为 FreeBSD 想象下一个大创新。重要的是保持工作与乐趣的平衡——这是快乐守护神生活的秘诀!

    Kim McMahon: FreeBSD 以其多功能性和可靠性著称。如果你要用三个形容词来描述 FreeBSD,那会是什么?为什么?

    Beastie: 轻松搞定!强大、灵活和社区驱动。让我给你详细讲讲:

    • 强大: FreeBSD 就是操作系统中的赫拉克勒斯。它能应付你扔给它的所有东西,从运行庞大的服务器到为火星上的小机器人提供动力。它是举山打海怪的软体版,且总能保持冷静。难怪它是关键任务的首选。

    • 灵活: FreeBSD 是操作系统界的瑞士军刀。你可以将它部署在任何设备上,从桌面电脑、超级计算机到那些酷炫的联网冰箱。需要一个稳定的服务器?搞定。正在构建一个用于震撼科学计算的集群?轻松搞定。FreeBSD 是终极的多任务能手,准备迎接任何挑战。

    • 社区驱动: 这才是魔法发生的地方。FreeBSD 社区是一群充满热情的人,做成了一切。把它想象成一个大家庭,一起编程、一起调试,偶尔还争论一下最好的文本编辑器(vi 万岁!)。这种同仁之情和共同的目标使得 FreeBSD 与众不同。如果没有这个不可思议的社区,FreeBSD 就不会成为今天这个强大的存在。

    Kim McMahon: 你在技术世界中见证了许多变化。你认为在技术进化中最令你惊讶和有趣的事情是什么?

    Beastie: 哦,天哪,我都不知道从哪里开始。有些瞬间真是让人瞠目结舌。但如果要我选一个,那就是互联网连接的烤面包机的崛起。说真的,谁知道我们竟然能在做早餐的时候调试内核代码?简直像是生活在科幻电影里!想象一下:你在等吐司出来,突然手机响了,收到一条提示,说你的烤面包机需要更新固件。或者更酷的是,你可以黑进你的烤面包机,调整设置,每次都做出完美的金黄吐司。简直让人瞠目结舌,而且有点好笑。

    Kim McMahon: FreeBSD 被用于许多环境,从服务器到嵌入式系统。如果你可以选择成为一切类型的 FreeBSD 部署,你会选择哪个?为什么?

    Beastie: 绝对是高性能服务器!处理海量数据,保持一切安全,支持无数用户,简直是守护神的激动人心的生活!想象一下,成为一个大型公司网站的支柱,每天处理数百万访客。或者为一项可能改变世界的前沿科学实验提供动力。这才是像我这样的守护神渴望的行动!

    Kim McMahon: 我得问一个重要问题:你怎么看 BSD 许可证?你觉得这就像是把家里的银器送出去吗?

    Beastie: BSD 许可证?更像是为每个人分发魔法三叉戟,就像奥普拉那样!“你拿一个三叉戟!你也拿一个!”当然,任何人都可以拿到并用它做任何他们想做的事,但看到他们创造出一些不可思议的东西总是令人鼓舞。想象一个每个人都能访问这些强大工具的世界,他们可以定制和改进它们来解决独特的挑战。就像一个巨大的百乐餐,每个人都带着自己最好的菜肴。你可能会分享你奶奶的秘密布朗尼食谱,但作为交换,你能品尝到一种你从未想过的融合塔克饼。再说,看着那些布朗尼大受欢迎,简直让人倍感满足!BSD 许可证的核心就是分享知识和促进创新。当有人拿着我们的代码创造出一些非凡的东西时,就像看到我们的魔法三叉戟以全新的、激动人心的方式复活。而最棒的部分?没有附加条件。你可以自由使用、修改它,并将它变成你自己的。所以,这或许不是什么“赠送家族银器”的事,而更像是赋能一个由守护神、开发者和梦想家组成的大军,共同创造魔法。谁不喜欢世界上多一点魔法呢?

    Kim McMahon: 说到竞争。能分享一些关于与其他吉祥物的友好竞争或有趣轶事吗?比如 Linux 的 Tux(译者注:Linux 那只企鹅)、微软 Windows 的 Clippy(译者注:Office 那只回形针:大眼夹),甚至……苹果的?

    Beastie: Tux 和我就像失散多年的兄弟!我们经常一起虚拟地喝杯提神饮品,开玩笑说用户的怪癖。Tux 爱吹嘘 Linux 无处不在,从手机到太空飞船。我点点头提醒他,FreeBSD 也在一些酷炫的地方运行,比如 。这一切都是开玩笑的。

    Kim McMahon(笑):听起来很友好。

    Beastie: 说到 Clippy……那个角色真是个传奇。有一天,他突然跳出来,提供帮我管理一个系统守护进程。“看起来你在试着控制一个守护进程。需要一个有用的回形针吗?”Clippy,别搞笑了,但我们都笑了。他现在已经退休了,不过偶尔会出现在吉祥物重聚会上,带着他那古怪的回形针魅力。

    Kim McMahon: 那么苹果的 Craig Federighi(译者注:克雷格·费德里吉,苹果软件工程高级副总裁)呢?那位男人、传说中的人物……

    Beastie: (低声)Craig Federighi……依然是个谜。那家公司的一切都笼罩在神秘之中。他是一个真实的人,还是某种高级人工智能?他的头发永远完美,他的演讲也无懈可击。一定有什么不为人知的秘密吧?我们在技术活动中交换过一些寒暄,但我半信半疑,觉得他随时会像电子游戏角色一样出现故障。真是很可疑!适当的竞争让事情变得更有趣,即使是面对一个潜在的全息影像。最终,受益的还是用户们,借着我们的友好竞争和,嗯,偶尔的小插曲。

    Kim McMahon: 你最喜欢 FreeBSD 的哪个功能,觉得更多人应该了解?你有个人最喜欢的命令和工具吗?

    Beastie: Jails,绝对是!想象一下在一台系统上拥有多个隔离的环境,每个环境都有自己的空间、进程和网络。它就像一个虚拟的瑞士军刀!你可以测试软件、运行不同的应用,甚至安全地托管多个服务,而它们之间互不干扰。对系统管理员和安全专家来说简直是完美的选择。这就像拥有一支自己的宇宙飞船舰队,每艘飞船都在自己的安全航道上。

    Kim McMahon: 宇宙飞船?真有意思。

    Beastie: (咧嘴笑)至于命令,zfs 是我的魔法技巧。它在处理存储时简直令人震惊。我们说的是海量数据、轻松的快照、压缩和克隆,所有这些都可以通过简单的命令完成。需要回滚到之前的版本?没问题。想要创建几乎即时的数据副本?简直轻松。zfs 让你感觉自己像一个掌控数据的巫师。而且,它绝对是技术聚会中的话题杀手。“你还在使用那些老式的文件系统吗?让我来给你展示一下 zfs 的奇妙之处!”

    Kim McMahon: 你之前提到 vi 是你最喜欢的文本编辑器。为什么是它呢?

    Beastie: (戏剧性地叹气)啊,vi。这是一种爱恨交织的关系。它强大、简洁,而且能轻松完成任务,毫不繁琐。而且,当一个新人第一次尝试……(悄悄地凑近)……退出 vi 时,那种表情简直值千金!满脸困惑和沮丧。这就是 vi 的魅力之一,对吧?它教会你耐心,也让你意识到记住退出序列的重要性。虽然我得承认,有时候我会幻想,如果能有个吉祥物介入,举办一个用户友好的文本编辑器工作坊,可能会更好一点。也许可以加点小猫咪和彩虹……开玩笑的(大部分是)。但说真的,伙计们,使用所有能让你高效编码的工具都没有问题。Emacs、nano,甚至那些花哨的图形化编辑器——只要你能完成工作,那才是最重要的。

    Kim McMahon: Beastie,你最喜欢的 shell 是什么?你为什么特别偏爱它?

    Beastie: (用三叉戟摸着下巴)啊,shell!你得承认,它比“命令提示符”听起来酷多了。虽然“守护进程调度器”也有点意思,不是吗?

    Kim McMahon: (笑)也许吧。

    Beastie: 好了,关于这些 shell。FreeBSD 有各种各样的选择,每一种都有自己独特的风味。sh(1) 是经典的,无花哨的工作马。就像一条可靠的工装裤——完成工作,虽然可能无法赢得时尚比赛。

    Kim McMahon: 工装裤?

    Beastie: 没错!然后是 tcsh(1),我那老朋友。它舒适、熟悉,允许你根据自己的喜好进行定制——就像一顶佩戴多年的棒球帽。但说实话,有时候穿上和脱下它有点慢。

    Kim McMahon: (微笑)

    Beastie: 现在 bash(1) ——那可是 shell 世界里的派对动物。自动补全、华丽的颜色,所有的配套功能。就像穿着晚礼服进服务器房——时尚,但可能有点不太实用。

    Kim McMahon: 哇,我从没想到命令行 shell 会有这么多的变化!

    Beastie: 每个守护神都有自己的 shell 个性。至于我?我戴许多顶帽子——或者说,戴许多 shell?我做 root 任务时用 sh(1) ——得高效嘛,你懂的。但当我休息时,玩点有趣的东西,tcsh(1) 就是我舒适的首选 shell。嘿,谁不喜欢偶尔用一下 bash(1),给一天增添些亮点呢?一个真正的守护神是个适应力强的高手,能根据情况选择最合适的 shell!

    Kim McMahon: Beastie,你最喜欢的编程语言是什么?为什么偏爱它们?

    Beastie: (思考着用三叉戟轻点)选出最喜欢的?这可不容易。就像让一个守护神在披萨和塔可之间选一样!根本无法选错,不是吗?但我可以稍微弯一下规则,分享我的最爱。

    Kim McMahon: 我在听!

    Beastie: 首先是 C。啊,C,编程语言中的 OG(老大哥)。它是 FreeBSD 本身的基石,是把一切联系起来的螺丝和螺母。用 C 编程就像挥舞着一把魔法凿子,编写直接与硬件交互的代码。感觉就像是在和机器本身对话,mano a maquina!(译者注:西班牙语,手与机器对抗)而且,把代码的每一丝效率都挤出来是一种特别的满足感。就像调校赛车引擎——每一行代码都至关重要!

    Kim McMahon: 听起来真是挺紧张的!

    Beastie: (咧嘴笑)紧张,但值得!接着是 Python,完全是另一种类型的存在。它就像一把超能瑞士军刀。需要写个脚本?Python 扛得住。撘网站?Python 就是你最好的朋友。数据科学项目?Python 准备好帮你计算那些数字了!而且,Python 社区是技术界最友好的群体。就像和一群支持你的啦啦队员一起编程,他们总是在那里帮助你。

    Kim McMahon: 编程的啦啦队员,嗯?

    Beastie: 没错!然后是 shell 脚本。让我告诉你,当你需要快速自动化某些操作时,shell 脚本 是最好的选择。它就像用命令建造一台鲁布·戈德堡机械——效率链条的反应!把几行代码连起来,看着任务自己完成。无需花里胡哨工具,纯粹的命令行魔法。它诠释了“聪明地工作,而不是辛苦地工作”,每个守护神都喜欢这样!

    Kim McMahon: 听起来真有趣!

    Beastie: (眨眼)绝对的!这些只是我最喜欢的一部分,顺便说一下,Perl 是文本处理的高手,就像一个数字世界的忍者。Go 关注的是速度和性能,非常适合现代服务器应用。谁能忘记 JavaScript 呢?虽然它不是我首选的语言,但在 web 开发世界里到处都能看到它。真是个能变色的编程 chameleon(变色龙)!

    Kim McMahon: 所以,你是个 polyglot(多语言)程序员?

    Beastie: (摆出肌肉)一个全能的守护神必须具备适应力!每种语言都有它的优势、特点和独特的个性。关键是知道什么时候使用哪种工具。再说了,一点变化总能让编程世界更有趣。

    Kim McMahon(调侃地): 好吧,Beastie,我有一个有趣的问题。iPhone 还是 Android?

    Beastie(俏皮地扬起一只眉毛): (稍作思考,三叉戟敲在桌子上)这个问题难倒我了,Kim!作为一个守护神,我得保持平台无关性,你懂的?你得能够在任何系统上玩得转,无论是 FreeBSD 服务器、顶级工作站,甚至是一个跑 Linux 的小烤面包机。 (眨眼)

    Kim McMahon(大笑): 我不推荐用烤面包机,Beastie。但我明白你的意思。

    Beastie: 没错!不过,嘿,如果我得选择一个个人偏好,譬如说,外出时玩弄一下,嗯……让我说,某些移动设备的引擎盖下或许会露出一些熟悉的 BSD 根源。 (挑眉)当然,我可没说什么具体的!但一个强大、可靠的 Unix 基础,真的可以走得很远,wink wink。

    Kim McMahon(眼中闪烁着光芒,向前靠近): 好吧,Beastie,最后一个问题,快结束了。作为一个“太空生物”(差不多吧),我得问:星际迷航还是星球大战?

    Beastie(仰头大笑): Kim,Kim,Kim!你不能让一个守护神在如此辉煌的极客霸权之战之间做选择!这么做有啥乐趣?再说了,一个真正的跨维度旅行者像我,应该在某个时刻都曾经进入过这两个宇宙。(有分量地敲了敲三叉戟)就说,我见过一些真正史诗级的服务器大战,那些战斗足以让死星和博格望尘莫及。 (眨眼)

    Kim McMahon: Beastie,真是太好玩了!最后有什么话要对 FreeBSD 社区和我们的读者说吗?

    Beastie: (举起三叉戟敬礼)对于 FreeBSD 社区:继续你们的努力!你们的热情、奉献和编程能力让 FreeBSD 变得如此伟大。继续创新,继续分享,继续保持 FreeBSD 的精神活力!至于我们的读者——无论你是资深开发者,还是对开源软件充满好奇的人,我都鼓励你去探索 FreeBSD。它是一个强大、灵活、欢迎的社区。所以,赶快深入了解,动手试试,甚至学点新技能。毕竟,世界上需要更多像你这样的守护神、开发者和梦想家!而且记住,如果你看到一个带三叉戟、毛茸茸的吉祥物在服务器房间里徘徊,别害怕,打个招呼吧!说不定我还会分享一个酿造守护神 brew(译者注:酿造 xx)的最佳秘诀呢。

    Kim McMahon: Beastie,非常感谢你今天加入我们!真是太开心了。

    Beastie: 这是我的荣幸,Kim!如果你能原谅,我得去和一些企鹅开个视频会议,讨论如何维护跨物种吉祥物关系。下次见! (用力一响指,随即在一阵代码烟雾中消失)

    修复 FreeBSD 上的依赖

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2019/03

    不知道你怎么样,但我经常更新我的包……而且数量多达一千多个。

    ……不过这没什么,大多数都是我使用软件的依赖包。

    例如,我需要 Openbox 和 X11,但为了使用它们,我需要 300 多个库和协议依赖,这很正常,这就是它的工作方式……不过有时升级之后,一两个应用程序会因为缺失依赖而无法启动。我会说这种情况大约每二十到三十次更新发生一次(1/20 – 1/30),非常罕见,而且即便发生,也很容易解决。我在 Linux 系统上也遇到过很多次,所以这不仅仅是 FreeBSD 的问题,这就是开源桌面/笔记本生态的运作方式 🙂。

    gpart create -s GPT ada0
    gpart add -t freebsd-ufs  ada0
    gpart add -t freebsd-swap ada0
    gpart add -t freebsd-boot -b 40 -s 984  ada0
    gpart bootcode -b /boot/pmbr -p /boot/gptboot    -i 1 ada0
            或者
    gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
    gpart add -t efi -b 40 -s 409560 ada0
    newfs_msdos -F 32 -c 1 -L EFISYS /dev/ada0p1
    mount -t msdosfs /dev/ada0p1 /mnt
    mkdir -p /mnt/EFI/BOOT
    cp /boot/loader.efi /mnt/EFI/BOOT/BOOTX64.efi
    umount /mnt
            或者
    gpart bootcode -p /boot/boot1.efifat -i 1 ada0
    gpart bootcode -p /boot/gptboot    -i 1 ada0
            或
    gpart bootcode -p /boot/gptzfsboot -i 1 ada0
    # Device    Mountpoint FStype  Options Dump Pass #
    /dev/ada0p1 /boot/efi  msdosfs rw      0    0
    mkdir -p /boot/efi
    mount /boot/efi
    cp /boot/loader.efi /boot/efi/EFI/BOOT/BOOTX64.efi
    ccache -M 32G
    WITH_CCACHE_BUILD= yes
    cache directory                     /root/.ccache
    primary config                      /root/.ccache/ccache.conf
    secondary config      (readonly)    /usr/local/etc/ccache.conf
    cache hit (direct)                     5
    cache hit (preprocessed)              77
    cache miss                         46123
    cache hit rate                      0.18 %
    called for link                      116
    ccache internal error                  1
    unsupported code directive             3
    no input file                          1
    cleanups performed                     0
    files in cache                    137311
    cache size                           2.7 MB
    max cache size                      32.0 GB
    cache directory                     /root/.ccache
    primary config                      /root/.ccache/ccache.conf
    secondary config      (readonly)    /usr/local/etc/ccache.conf
    cache hit (direct)                 45050
    cache hit (preprocessed)            1237
    cache miss                         46123
    cache hit rate                     50.09 %
    called for link                      232
    ccache internal error                  2
    unsupported code directive             6
    no input file                          2
    cleanups performed                     0
    files in cache                    137454
    cache size                           2.7 MB
    max cache size                      32.0 GB
    cache directory                     /root/.ccache
    primary config                      /root/.ccache/ccache.conf
    secondary config      (readonly)    /usr/local/etc/ccache.conf
    cache hit (direct)                 45186
    cache hit (preprocessed)            1019
    cache miss                             0
    cache hit rate                    100.00 %
    called for link                      116
    ccache internal error                  1
    unsupported code directive             3
    no input file                          1
    cleanups performed                     0
    files in cache                    137578
    cache size                           2.7 MB
    max cache size                      32.0 GB
    cache directory                     /root/.ccache
    primary config                      /root/.ccache/ccache.conf
    secondary config      (readonly)    /usr/local/etc/ccache.conf
    cache hit (direct)                 45186
    cache hit (preprocessed)            1019
    cache miss                             0
    cache hit rate                    100.00 %
    called for link                      116
    ccache internal error                  1
    unsupported code directive             3
    no input file                          1
    cleanups performed                     0
    files in cache                    137578
    cache size                           4.5 GB
    max cache size                      32.0 GB
    host # mkdir -p /jail/minecraft /jail/BASE
    
    host # VER=$( freebsd-version | awk -F '-' '{print $1 "-" $2}' )
    
    host # fetch -o /jail/BASE/${VER}-base.txz https://download.freebsd.org/releases/amd64/14.2-RELEASE/base.txz
    host # tar -C /jail/minecraft --unlink -xvf /jail/BASE/14.2-RELEASE-base.txz
    
    host # cp /var/run/dmesg.boot /jail/minecraft/var/run/
    host # cat /etc/jail.conf
    exec.start      = "/bin/sh /etc/rc";
    exec.stop       = "/bin/sh /etc/rc.shutdown";
    exec.consolelog = "/var/log/jail_console_${name}.log";
    exec.clean;
    mount.devfs;
    host # cat /etc/jail.conf.d/minecraft.conf
      minecraft {
      # 全局
        exec.start = "/bin/sh /etc/rc";
        exec.stop  = "/bin/sh /etc/rc.shutdown";
        exec.consolelog = "/var/log/jail_console_${name}.log";
        exec.clean;
        mount.devfs;
        host.hostname = ${name};
        path = /jail/${name};
    
      # 自定义
        ip4.addr = 10.0.0.210;
        interface = em0;
        allow.raw_sockets;
        allow.sysvipc;
        devfs_ruleset=210;
        allow.mount;
        enforce_statfs=1;
        allow.mount.devfs;
        allow.mount.procfs;
        allow.mount.fdescfs;
      }
    host # grep -A 4 minecraft /etc/devfs.rules
    [minecraft=210]
    add include $devfsrules_jail
    add path 'fd*' unhide
    host # service jail onestart minecraft
    Starting jails: minecraft.
    
    host # jls
       JID  IP Address      Hostname                      Path
         1  10.0.0.210      minecraft                     /jail/minecraft
    host # jmore
    JAIL       JID  TYPE  VER     DIR              IFACE   IP(s)
    ----       ---  ----  ---     ---              -----   -----
    classic    -    std   13.2-R  /jail/classic    em0     10.0.0.199
    ctld-two   -    vnet  13.2-R  /jail/ctld-two   ${if}b  -
    ctld       -    vnet  13.2-R  /jail/ctld       ${if}b  -
    fbsdjail   -    std   13.1-R  /jail/fbsdjail   wlan0   10.0.0.43
    iscsi      -    vnet  13.2-R  /jail/iscsi      ${if}b  -
    minecraft  1    std   14.2-R  /jail/minecraft  em0     10.0.0.210
    minio      -    std   14.0-R  /jail/minio      em0     10.0.0.133
    nfsd       -    vnet  14.1-R  /jail/nfsd       ${if}b  -
    other      -    std   14.1-R  /jail/other      em0     10.0.0.199
    sambajail  -    vnet  14.1-R  /jail/sambajail  ${if}b  -
    unfs3      -    vnet  14.1-R  /jail/unfs3      ${if}b  -
    host # grep jail /etc/rc.conf
    jail_enable=YES
    jail_devfs_enable=YES
    jail_list="minecraft"
    env PS1='minecraft # ' jexec minecraft /bin/sh
    host # jmore minecraft c
    minecraft #
    minecraft # echo nameserver 1.1.1.1 > /etc/resolv.conf
    minecraft # mkdir -p /usr/local/etc/pkg/repos
    minecraft # sed -e 's|quarterly|latest|g' /etc/pkg/FreeBSD.conf > /usr/local/etc/pkg/repos/FreeBSD.conf
    minecraft # pkg search -o minecraft
    games/minecraft-client         Client for the block building game
    minecraft # pkg install gitup bsddialog ccache portconfig openjdk21 tmux jless
    minecraft # gitup ports
    (...)
    #
    # Please review the following file(s) for important changes.
    #       /usr/ports/UPDATING
    #       /usr/ports/mail/dspam/files/UPDATING
    #
    # Done.
    
    minecraft # cd /usr/ports/games/minecraft-server
    
    minecraft # make config
    
     +------------|minecraft-server-1.21.4|--------------+
     | 'F1' for Ports Collection help.                   |  
     | +---------- RUN [select at least one] ----------+ |
     | | new (*) DAEMON     Run as a service           | |
     | | new ( ) STANDALONE Run the .jar file directly | |
     | +-----------------------------------------------+ |
     |                [  OK  ]     [Cancel]              |
     +---------------------------------------------------+
    minecraft # echo DISABLE_LICENSES=yes >> /etc/make.conf
    
    minecraft # env BATCH=yes make build install clean
    (...)
    When you first run minecraft-server, it will populate the file
    /usr/local/etc/minecraft-server/eula.txt
    
    It is required to read the EULA, and then set eula=true
    
    - Configuration files can be found in /usr/local/etc/minecraft-server/
    - Log and debug output files can be found in /var/log/minecraft-server/
    - World files can be found in /var/db/minecraft-server/
    
    Without daemon option:
    - To run the server, run /usr/local/bin/minecraft-server
    - To edit java's parameters, edit /usr/local/etc/minecraft-server/java-args.txt
    - To run with a specific version of Java, set environment variable JAVA_VERSION,
      for example:
        export JAVA_VERSION=22
        /usr/local/bin/minecraft-server
      or:
        JAVA_VERSION=22 /usr/local/bin/minecraft-server
    
    With daemon option:
    - The service has been installed with the name 'minecraft'
    - To adjust maximum memory usage (-Xmx), use minecraft_memx= in /etc/rc.conf
    - To adjust initial memory usage (-Xms), use minecraft_mems= in /etc/rc.conf
    - To add other java parameters, use minecraft_args= in /etc/rc.conf
    - To run with a specific version of Java, use minecraft_java_version= in /etc/rc.conf
    - To see the interactive console, type service minecraft console
    
    ===>  Cleaning for minecraft-server-1.21.4
    minecraft # cat << FSTAB >> /etc/fstab
            fdesc   /dev/fd         fdescfs         rw      0       0
            proc    /proc           procfs          rw      0       0
    FSTAB
    
    minecraft # echo 'mount -a' >> /etc/rc.local
    
    minecraft # mount -a
    
    minecraft # mount
    zroot/jail on / (zfs, local, noatime, nfsv4acls)
    devfs on /dev (devfs)
    fdescfs on /dev/fd (fdescfs)
    procfs on /proc (procfs, local)
    devfs on /dev (devfs)
    minecraft # cat << RC >> /etc/rc.conf
    minecraft_enable=YES
    minecraft_mems=1024M
    minecraft_memx=1024M
    RC
    
    minecraft # echo eula=true > /usr/local/etc/minecraft-server/eula.txt
    
    minecraft # cat << MINECRAFT > /usr/local/etc/minecraft-server/server.properties
    enable-jmx-monitoring=false
    rcon.port=25575
    level-seed=
    gamemode=survival
    enable-command-block=false
    enable-query=false
    generator-settings={}
    enforce-secure-profile=true
    level-name=world
    motd=FreeBSD Minecraft Server
    query.port=25565
    pvp=true
    generate-structures=true
    max-chained-neighbor-updates=1000000
    difficulty=easy
    network-compression-threshold=256
    max-tick-time=60000
    require-resource-pack=false
    use-native-transport=true
    max-players=20
    online-mode=false
    enable-status=true
    allow-flight=false
    initial-disabled-packs=
    broadcast-rcon-to-ops=true
    view-distance=10
    server-ip=
    resource-pack-prompt=
    allow-nether=true
    server-port=25565
    enable-rcon=false
    sync-chunk-writes=true
    resource-pack-id=
    op-permission-level=4
    prevent-proxy-connections=false
    hide-online-players=false
    resource-pack=
    entity-broadcast-range-percentage=100
    simulation-distance=10
    rcon.password=
    player-idle-timeout=0
    force-gamemode=false
    rate-limit=0
    hardcore=false
    white-list=false
    broadcast-console-to-ops=true
    spawn-npcs=true
    spawn-animals=true
    log-ips=true
    function-permission-level=2
    initial-enabled-packs=vanilla
    level-type=minecraft\:normal
    text-filtering-config=
    spawn-monsters=true
    enforce-whitelist=false
    spawn-protection=16
    resource-pack-sha1=
    max-world-size=29999984
    MINECRAFT
    minecraft # service minecraft start
    Starting minecraft.
    
    minecraft # service minecraft status
    minecraft is running.
    
    minecraft # sockstat -l4
    USER     COMMAND    PID   FD  PROTO  LOCAL ADDRESS         FOREIGN ADDRESS      
    mcserver java       33227 103 tcp4   10.0.0.210:25565      *:*
    root     syslogd     7809 5   udp4   10.0.0.210:514        *:*
    minecraft # su mcserver -c '/usr/local/bin/java -Xmx1024M -Xms1024M -jar /usr/local/minecraft-server/server.jar nogui'
    host # cat /jail/minecraft/usr/local/etc/minecraft-server/usercache.json | tr ',' '\n'
    [{"name":"antuan"
    "uuid":"0d61326c-dfd1-3fa8-ba9d-249d402fb700"
    "expiresOn":"2025-05-05 14:04:15 +0000"}
    {"name":"antek"
    "uuid":"4b520bac-4b31-3c41-8f9b-2781763e5c88"
    "expiresOn":"2025-05-05 09:16:08 +0000"}]
    
    host # jless /jail/minecraft/usr/local/etc/minecraft-server/usercache.json | cat
    [
      {
        "name": "antuan",
        "uuid": "0d61326c-dfd1-3fa8-ba9d-249d402fb700",
        "expiresOn": "2025-05-05 14:04:15 +0000"
      },
      {
        "name": "antek",
        "uuid": "4b520bac-4b31-3c41-8f9b-2781763e5c88",
        "expiresOn": "2025-05-05 09:16:08 +0000"
      }
    ]
    host # jless /jail/minecraft/usr/local/etc/minecraft-server/ops.json | cat
    [
      {
        "uuid": "4b520bac-4b31-3c41-8f9b-2781763e5c88",
        "name": "antek",
        "level": 4,
        "bypassesPlayerLimit": false
    
      },
      {
        "uuid": "0d61326c-dfd1-3fa8-ba9d-249d402fb700",
        "name": "antuan",
        "level": 4,
        "bypassesPlayerLimit": false
      }
    ]

    make -j16 buildkernel

    136 秒

    -

    make -j20 buildkernel

    123 秒

    -

    make -j24 buildkernel

    115 秒

    55 秒

    ccache -C

    删除缓存

    bsdinstall: 增加 EFI 分区大小至 200MB
    标志性红色角状 Beastie
    Marshall Kirk McKusick
    奈飞服务器在播放他最喜欢的节目

    1983 年:4.2BSD 发布,包含了像快速文件系统(FFS)和 TCP/IP 网络这样的重大创新,这些成了未来操作系统的基础元素。

  • 1985 年:史蒂夫·乔布斯在离开苹果后创办了 NeXT 公司。

  • 1989 年:NeXTSTEP 发布,它基于 Mach 微内核和 BSD,结合了先进的功能和面向对象设计。

  • 1993 年:FreeBSD 和 NetBSD 从 386BSD 衍生出来,分别专注于性能、安全性和可移植性。

  • 1995 年:OpenBSD 从 NetBSD 复刻出来,强调安全性和代码正确性。

  • 1996 年:苹果收购 NeXT,带回了 NeXTSTEP 技术,为 Mac OS X 奠定基础。

  • 2000 年:苹果发布了基于 Darwin OS 的 Mac OS X 第一版。这个操作系统结合了 Mach 微内核和来自 BSD 的组件,成为苹果现代操作系统的核心。

  • 2006 年:OpenDarwin 停止发布,标志着苹果不再提供可独立安装的 Darwin OS 版本。

  • 组件

    来源

    XNU 内核

    Mach/NeXTStep/OpenStep

    网络栈

    FreeBSD/BSD,以及额外的 NIKE 和 IOKIT

    虚拟文件系统

    FreeBSD/BSD

    用户空间工具

    FreeBSD/BSD

    内存管理

    Mach/NetBSD

    进程模型

    Mach IPC、Mach Security Trailers 和强制访问控制(MAC)机制

    图片来源
    开源许可证
    开源网站
    GitHub
    开源软件开发
    PureDarwin
    BSD 许可证
    GPLv2
    Swift
    clang
    LLVM
    2024 年 6 月的提交
    Apple Open Source
    Apple GitHub
    FreeBSD Project
    PureDarwin Project

    今天的受害者是 Chromium。我平时一般使用 Firefox,但有时当某个页面在 Firefox 上表现异常时,我会用 Chromium 验证这个行为。我也把 Chromium 用作本地 .htm/.html/*.chm 文件的文件打开器(或者说文件浏览器)。但这次它无法启动,于是我去命令行检查出了什么问题。

    ……缺失的依赖是库 libx264.so.155。

    鲁莽的符号链接

    这种方法被认为是危险的,或者说是一种快速且粗糙的修复方式——它本身也可能引入其他问题——但在很多情况下,它可以暂时解决问题。

    ……而这正是它的作用——一个临时修复,直到 ffmpeg 包完成重建——这比执行 pkg upgrade 命令需要更长时间,但当我现在需要 Chromium 时,就是“现在”,而不是等 ffmpeg 包重建完成之后再说。这个问题的根源在于 FreeBSD 项目缺乏提供 lame 包的勇气。OpenBSD 的开发者没有这个问题,但 FreeBSD 的开发者有。因此,要在 ffmpeg 中支持 MP3,你必须先手动编译 lame 包,然后在 ffmpeg 中选择该选项,再将其重新构建为包……而且每次执行 pkg upgrade 命令都要重复这一过程……至少可以说这是非常麻烦的。

    这就是我使用 pkg-recompile.sh 脚本的原因——为了避免每次更新包(大约每周两次)都手动重复上述操作。如果可以称之为“工作流程”,它大致是这样的:

    那我们来验证一下,看看 Chromium 是否还有其他缺失的依赖。

    所以 /usr/local/bin/chrome 只是一个包装脚本,让我们看看它的内容。

    所以我们的真正二进制文件是 /usr/local/share/chromium/chrome,接下来用 ldd(8) 检查它。

    依赖很多,我们直接用 grep(1) 筛选,示例如下。

    只缺失了一个依赖——libx264.so.155。那我们就来修复它。

    这里有一个稍新的版本 libx264.so.157,所以我们用它创建一个符号链接,命名为缺失的 libx264.so.155。

    现在应该能正常启动 Chromium 了。

    没有出现任何 not found 的结果。

    那我们就用 chrome 命令启动 Chromium。

    一如既往,一切正常 🙂。

    可以通过下面这张简单的截图直观地看到整个过程。

    vermaden_2019-03-21_15-47-40.png

    使用 /etc/libmap.conf 文件

    与其创建符号链接——这种方法会全局生效——你也可以为二进制文件 /usr/local/share/chromium/chrome 单独创建一个合适的 libmap.conf 配置文件。

    下面是仅针对 Chromium 浏览器的修复方法。

    ……与之等效、可全局生效的解决方案是使用符号链接,如下所示。

    这种方法也更方便迁移或批量应用这些修改,而不需要复制符号链接。

    修复 pkg(8) 数据库中的破损依赖

    我在 Less Known pkg(8) Features 一文中已经写过,但为了选项的完整性,这里值得再提一次。

    曾经有一次,缺失的依赖——涉及易受攻击的 www/libxul19 包——折磨了我一段时间。

    我甚至已经绝望到想用 portmaster 重新编译所有东西。

    我一开始使用了 portmaster --check-depends 命令,但在提示是否修复时选择了‘n’,因为那会不必要地降级很多包。

    那我们来看 pkg(8) 显示的已安装包情况。

    问题在于我们安装的是 www/libxul 而不是 www/libxul19,这也是为什么 portmaster(以及其他工具)会报错。

    在引入 pkg(8) 之前,只需对整个 /var/db/pkg 目录及其“文件数据库”使用 grep -r 就很容易查到,但现在情况复杂得多,因为包数据库已经存储在 SQLite 数据库中。

    使用 pkg shell 命令可以连接到该数据库。让我们看看能找到些什么。

    所以现在我们知道,“deps”表可能就是我们要找的 ;)。

    由于 pkg shell 在 SQLite“浏览”方面相当有限,我将直接使用 sqlite3 命令。所谓有限,是指你不能直接输入 pkg shell "select * from deps;" 查询,而是需要先启动 pkg shell,然后才能输入查询语句。

    第二列是 name,所以我们可以尝试用它来查询。

    现在我们已经定位到这个“有问题”的依赖条目,让我们稍微修改它,使其与实际已安装的包状态一致。

    当然,你也可以使用“官方”方式,通过 pkg shell 命令来操作。

    现在 portmaster 已经不再抱怨缺失依赖,一切正常。

    完美!问题解决了 😉

    ……但 pkg(8) 本身已经提供了工具来处理这个问题 🙂

    它叫做 pkg set,在 man pkg-set 中最有用的两个选项是:

    在我们的例子中,可以使用以下命令:pkg set -o www/libxul19:www/libxul

    不过不确定它是否会以同样的方式解决问题,因为我同时还更新了数据库中的版本信息。

    使用 bsdadminscripts2 包中的 pkg_libchk

    还有另一种方法可以修复或检查此类问题——那就是使用 bsdadminscripts2 包中的 pkg_libchk。请注意,这里有两个名称中带有 bsdadminscripts 的冲突包,需要区分清楚。

    ……只要你安装了 bsdadminscripts2,就无法再安装 bsdadminscripts,因为它们存在冲突。我之前已经安装了 bsdadminscripts2,但想在系统中添加 bsdadminscripts。

    下面是 Port/包 /usr/ports/ports-mgmt/bsdadminscripts2 的描述。

    这个包正好有四个工具。

    如果不带任何参数调用,它会检查系统中安装的所有包。

    ……所以如果只想对 Chromium 进行检查,需要指定 chromium 包,命令如下:

    pkg_libchk 可以根据哪个包提供了哪些文件来获取缺失的依赖,或者生成需要重建的包列表。

    使用 Provides 数据库

    你也可以使用 pkg(8) 的“provides”数据库。

    想了解如何为 pkg(8) 命令设置“provides”数据库,请查阅文章 Less Known pkg(8) Features。

    更新 1 – 重新整理整篇文章

    古罗马哲学家塞涅卡曾说过——“在教别人的同时,我们也在学习。”——这句话非常正确——尤其是对本文而言。在我将文章发布到各处后,大家提醒我,仅仅创建符号链接并不是最好的方法。对此我接受指正,并增加了额外章节和方法,介绍如何在 FreeBSD(或 Linux/Illumos)系统上修复破损依赖。

    Fix Broken Dependency on FreeBSD

    NVIDIA GPU

    是

    Greg W

    是

    否

    Samba

    是

    Greg W

    是

    是

    Definitive manager bhyve/VM/Jail

    是

    ?

    是

    否

    Zero Trust Build

    是

    FreeBSD 基金会

    是

    否

    Ports Automation

    否

    FreeBSD 基金会

    是

    否

    Enterprise CA

    是

    Greg W

    是

    是

    FreeBSD containers on macOS

    Podman 支持在流行的客户端操作系统(macOS、Windows)上运行 Linux 容器,以便人们可以在这些系统上工作并部署到云中。它通过生成一个 Linux 虚拟机并从外部连接到它来实现这一点。该项目旨在为 FreeBSD 服务器带来与 Linux 服务器用户相同的 podman 桌面/笔记本体验。

    链接

    XC

    用于 FreeBSD 的正在进行中的容器引擎,可运行 Linux 和 FreeBSD 容器。它可以支持 OCI 兼容的镜像注册表,如 DockerHub 或 Azure 容器注册表,用于镜像分发。

    链接

    在 Kubelet 上加入基本的 FreeBSD 支持

    用于在 FreeBSD 上启动 kubelet 并与 CRI 运行时(在我这里是 containerd+runj)通信以运行(目前是)FreeBSD 容器的第一个基础构件。

    链接

    链接
    链接
    链接
    链接

    在 FreeBSD 上以 lsblk(8) 风格列出块设备

    • List Block Devices on FreeBSD lsblk(8) Style

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2019/09/27

    当我需要在 Linux 系统上工作时,我通常会怀念很多 FreeBSD 上很棒的工具,比如仅举几例:

    • sockstat

    • gstat

    • top -b -o res

    • top -m io -o total

    • usbconfig

    • rcorder

    • beadm/bectl

    • idprio/rtprio

    ……但有时候——虽然很少——Linux 上也有一些非常有用的工具,而 FreeBSD 上则没有。例子就是 lsblk(8),它专注于一件事,而且做得相当好——列出块设备及其内容。它也有一些问题,比如在完全应用 ZFS 池使用的磁盘上,它会显示两个分区,而不是直接显示 ZFS 的信息——但我们都知道,在某些圈子里,CDDL 许可的 ZFS 在那个 GPL 世界里是多么地“不受待见”。

    来自 Linux 系统的 lsblk(8) 示例输出:

    而 FreeBSD 在这方面提供了什么?可以使用命令 camcontrol(8) 和 geom(8)。你也可以使用 gpart(8) 命令来列出分区。下面是我在单磁盘笔记本上运行这些命令的输出。

    它们以可接受的方式提供了所需信息,但仅适用于磁盘数量较少的系统。如果你想显示所有系统驱动器内容的汇总呢?这时 lsblk.sh 就派上用场了。虽然 lsblk(8) 拥有许多有趣的功能,如 --perms/--scsi/--inverse 模式,我这里重点提供的只是最基本的功能——列出系统块设备及其内容。由于我在编写 shell 脚本方面有长期且愉快的经验,例如 或 ,我认为编写 lsblk.sh 是一个不错的主意。我实际上在 2016 年就在这个主题 的 FreeBSD Forums 上‘开源’或说分享了这个项目/想法,但由于时间有限,这个“副项目”的开发进度非常缓慢。我最终重新回到它,完成了它。

    lsblk.sh 是一个总体上小巧且简单的 shell 脚本,代码行数不到四百行。

    下面是我在单硬盘笔记本上运行 lsblk.sh 命令的示例输出。

    同样的输出在图形窗口中显示。

    下面是来自一台拥有两块系统固态硬盘(da0/da1)和两块机械数据盘(da2/da3)的服务器的 lsblk.sh 输出示例。

    下面是我在其他系统上测试 lsblk.sh 时的其他示例。

    虽然 lsblk.sh 并不是地球上最快的脚本(因为需要进行大量解析),但它能够很好地完成工作。如果你想在系统中安装它,只需输入以下命令:

    如果有时间,我可以考虑在 lsblk.sh 脚本中添加哪些其他原创的 Linux lsblk(8) 子命令/选项/参数呢?:🙂:

    此致敬礼。

    更新 1 – 添加 USAGE/HELP 信息

    刚刚添加了一些用法信息,可以通过以下任意参数显示:

    • h

    • -h

    • --h

    • help

    依我看,为这么一个简单的工具写 man 页面是没有必要的。我想等 lsblk.sh 工具在功能和选项上扩展到可与 Linux lsblk(8) 相媲美时,再创建专门的 man 页面。下面是它的显示效果。

    此致敬礼。

    更新 2 – 代码重组与重写 75%

    ……至少这是 git(1) 在 commit 信息中告诉我的内容。

    经过几个高效小时的工作,lsblk.sh 的新版本现已发布。

    它的源代码行数类似,但现在缩小了四分之一……同时功能更多、准确性更高。这是 “少即是多” 的绝佳例子。

    一些没有简单解决方案的问题如下所述。

    其中之一是 FAT 文件系统的“双重”标签。我们既有 /dev/gpt/efiboot0 标签,也有 FAT 标签 EFISYS。必须在两者中做出选择。由于并非所有 FAT 文件系统都有标签,我选择了 GPT 标签。

    我也无法覆盖 FUSE 挂载。当你挂载——例如——/dev/da0 设备为 NTFS(使用 ntfs-3g)或 exFAT(使用 mount.exfat)时,mount(8) 输出没有明显区别。

    当我通过守护进程(如 sysutils/automount)挂载此类文件系统时,我会在 /var/run/automount.state 文件中记录设备挂载到的目录。然后,当我收到 /dev/da0 设备的 detach 事件时,我就知道该卸载哪个挂载点……但当只有 /dev/fuse 设备时,这是不可能的。

    ……或者,也许你知道有什么方法可以从 /dev/fuse(或 FUSE 一般)中提取设备挂载位置的信息吗?

    下面展示更新后的效果。

    这里是各种非 ZFS 文件系统的挂载情况:

    ……现在 lsblk.sh 显示它们的方式如下。

    我为此使用了一些基于文件的内存设备。现在,默认情况下 lsblk.sh 也会显示内存磁盘的内容。

    下面是在 xterm(1) 终端中的显示效果。

    此致敬礼。

    更新 3 – 添加 geli(8) 支持

    我认为添加 geli(8) 支持可能会很有用。最新的 lsblk.sh 版本现在避免了 MOUNT 和 LABEL 检测的代码重复(已移入单一统一函数)。同时添加了更多注释以提高代码可读性,并进行了一些小修复……而且脚本再次变得更小 :🙂:

    此次更新大约修改了 40%(根据 git commit 显示:191 行新增,196 行删除)。

    还忘了提到,现在得益于智能优化(比如避免重复操作,并将 grep(1) | awk(1) 管道聚合为单个 awk(1) 查询),lsblk.sh 的运行速度比最初版本快了三倍 :🙂:

    下面是添加 geli(8) 支持后的新输出。

    此致敬礼。

    更新 4 – 添加 fuse(8) 支持

    如我在 更新 2 中所述,跟踪 fuse(8) 下的挂载设备及其挂载位置非常困难,因为挂载完成后,所有挂载的设备都会神奇地变成 /dev/fuse。

    经过一些研究,我发现这个信息(在 FreeBSD 下通过 fuse(8) 接口实际挂载的设备位置)可以在挂载 procfs 文件系统于 /proc 后获取。你只需要查看所有 ntfs-3g 进程的 cmdline 条目。虽然不完美,但至少可以获取到这些信息。

    这是用于检测 fuse(8) 挂载点的代码原型。

    ……我刚刚意识到,我找到了获取该信息的新方法(更好),无需挂载 /proc 文件系统——你只需要显示 ntfs-3g 进程及其命令行参数,例如如下方式:

    因此,在我考虑到这最初仅针对 NTFS(ntfs-3g(8) 进程)后,我也添加了 exFAT 支持,通过搜索 mount.exfat 的 PID。现在 fuse(8) 挂载点检测可以同时支持 NTFS 和 exFAT 文件系统……而且支持该功能的代码甚至更简洁。

    我还修改了 MAJOR 和 MINOR 号的显示方式——从 HEX 改为 DEC,就像 Linux 一样。FreeBSD Base System 的 ls(1) 会以 HEX 显示,例如你会得到 0x2af 值:

    但使用 FreeBSD Ports 中的 GNU 等价工具 gls(1)(来自 sysutils/coreutils 包),则以 DEC 值显示 MAJOR 和 MINOR。gls(1) 只是 Linux 世界的 ls(1),由于 FreeBSD 的 Base System 已有 ls(1),开发者在名称前加了 ‘g’(代表 GNU)来区分。

    使用 stat(1) 工具也可以更方便/快速获取:

    最新的 lsblk.sh 如下所示:

    这也是我还没有将 lsblk.sh 添加到 FreeBSD Ports 的原因——几天内就发布了几版带有重要新功能的版本 :🙂:

    此致敬礼。

    更新 5 – 再次重写 69%

    在进一步研究 gpart(8) 后,我发现使用参数 -p 是个重大改变。使用 -p 参数后,它会直接显示带有分区名的输出,不再需要自己寻找 PREFIX 并“创建”分区名。

    默认 gpart(8) 输出:

    使用参数 -p 的输出:

    这一发现导致 lsblk.sh 进行了相当大幅重写。git commit 估计此次重写达 69%:

    最新 lsblk.sh 的特性如下:

    • 修复了之前的 BUG。

    • 可以检测 exFAT 标签。

    • 运行速度提升 20%。

    • SLOC 减少 10%。

    代码差异如下:

    最新 lsblk.sh 看起来仍然如以前,但我现在用 ‘-’ 替代了以前的 ‘’ 标记:

    更新 6 – 新的更新与修复版本

    lsblk.sh 已更新至 3.4 版本——并已在 FreeBSD Ports 树中更新,在 sysutils/lsblk Port 中可用。

    该版本的 变更日志 如下:

    • 在磁盘列表中添加 sysctl -n kern.disks。

    • 在 __gpart_present 函数中重置 LABEL。

    • 修复 gpart(8) 的 [bootme] 和 [bootonce] 标志行为。

    • 禁用 GPTID

    请注意,lsblk.sh 使用 diskinfo(8),为了正常工作,你需要属于 operator 组。你可以这样将自己添加到该组:

    ……或者通过编辑 /etc/group 文件。

    示例输出如下:

    更新 7 – 更多修复

    lsblk.sh 已更新至 3.5 版本——并已在 FreeBSD Ports 树中更新,在 sysutils/lsblk Port 中可用。

    该版本的 变更日志 如下:

    • 列出磁盘时移除输出中的控制序列和颜色。

    • diskinfo(8) 仅用于 md(4) 磁盘,因为 geom(4) 不支持它们。

    • 添加新注释并重新整理部分旧注释。

    • 为 SIZE 收集和显示增加额外检查。

    仅 md(4) 磁盘的大小需要属于 operator 组。所有其他磁盘大小现在通过 geom(8) 命令收集。

    更新 8 – 优化标签

    现在 3.9 版本的 lsblk(8) 比以往更好。

    该版本的 变更日志 如下:

    • 改进 glabel(8) 标签搜索。

    • 改进 gpart(8) 输出标签处理。

    • 将冗长的 Microsoft 分区名称替换为合理名称。

    • 改进 exFAT 处理。

    已提交 PR ,因此在 Ports 中更新前请稍作等待。

    通过将 ZFS 池构建为镜像结构,消除异常数据的影响

    通过将 ZFS 池构建为镜像结构,消除异常数据的影响

    • 原文:

    • 作者:みんみん

    通过替换 ZFS 镜像池中的磁盘来扩容

    • 原文链接:

    • 作者:みんみん

    • 上次更新于 2023 年 07 月 16 日

    % pkg info | wc -l
        1051
    % chrome
    Shared object "libx264.so.155" not found, required by "libavcodec.so.58"
    # pkg upgrade
    # pkg-recompile.sh build
    % which chrome
    /usr/local/bin/chrome
    
    % ldd /usr/local/bin/chrome
    ldd: /usr/local/bin/chrome: not a dynamic executable
    % cat /usr/local/bin/chrome
    #!/bin/sh
    
    SYSCTL=kern.ipc.shm_allow_removed
    if [ "`/sbin/sysctl -n $SYSCTL`" = 0 ] ; then
            cat << EOMSG
    For correct operation, shared memory support has to be enabled
    in Chromium by performing the following command as root :
    
    sysctl $SYSCTL=1
    
    To preserve this setting across reboots, append the following
    to /etc/sysctl.conf :
    
    $SYSCTL=1
    EOMSG
            exit 1
    fi
    ulimit -c 0
    exec /usr/local/share/chromium/chrome ${1+"$@"}
    % ldd /usr/local/share/chromium/chrome
    /usr/local/share/chromium/chrome:
            libthr.so.3 => /lib/libthr.so.3 (0x809b78000)
            libX11.so.6 => /usr/local/lib/libX11.so.6 (0x809da0000)
            libX11-xcb.so.1 => /usr/local/lib/libX11-xcb.so.1 (0x80a0df000)
            libxcb.so.1 => /usr/local/lib/libxcb.so.1 (0x80a2e0000)
            libXcomposite.so.1 => /usr/local/lib/libXcomposite.so.1 (0x80a506000)
            libXcursor.so.1 => /usr/local/lib/libXcursor.so.1 (0x80a708000)
            libXdamage.so.1 => /usr/local/lib/libXdamage.so.1 (0x80a913000)
            libXext.so.6 => /usr/local/lib/libXext.so.6 (0x80ab15000)
            libXfixes.so.3 => /usr/local/lib/libXfixes.so.3 (0x80ad26000)
            libXi.so.6 => /usr/local/lib/libXi.so.6 (0x80af2b000)
            libXrender.so.1 => /usr/local/lib/libXrender.so.1 (0x80b139000)
            libXtst.so.6 => /usr/local/lib/libXtst.so.6 (0x80b342000)
            libgmodule-2.0.so.0 => /usr/local/lib/libgmodule-2.0.so.0 (0x80b547000)
            libglib-2.0.so.0 => /usr/local/lib/libglib-2.0.so.0 (0x80b74a000)
            libgobject-2.0.so.0 => /usr/local/lib/libgobject-2.0.so.0 (0x80ba61000)
            libgthread-2.0.so.0 => /usr/local/lib/libgthread-2.0.so.0 (0x80bcab000)
            libintl.so.8 => /usr/local/lib/libintl.so.8 (0x80beac000)
            libnss3.so => /usr/local/lib/nss/libnss3.so (0x80c0b7000)
            libsmime3.so => /usr/local/lib/nss/libsmime3.so (0x80c3e3000)
            libnssutil3.so => /usr/local/lib/nss/libnssutil3.so (0x80c60d000)
            libplds4.so => /usr/local/lib/libplds4.so (0x80c83d000)
            libplc4.so => /usr/local/lib/libplc4.so (0x80ca40000)
            libnspr4.so => /usr/local/lib/libnspr4.so (0x80cc44000)
            libdl.so.1 => /usr/lib/libdl.so.1 (0x80ce83000)
            libcups.so.2 => /usr/local/lib/libcups.so.2 (0x80d084000)
            libxml2.so.2 => /usr/local/lib/libxml2.so.2 (0x80d315000)
            libfontconfig.so.1 => /usr/local/lib/libfontconfig.so.1 (0x80d6a8000)
            libdbus-1.so.3 => /usr/local/lib/libdbus-1.so.3 (0x80d8ef000)
            libexecinfo.so.1 => /usr/lib/libexecinfo.so.1 (0x80db40000)
            libkvm.so.7 => /lib/libkvm.so.7 (0x80dd43000)
            libutil.so.9 => /lib/libutil.so.9 (0x80df51000)
            libXss.so.1 => /usr/local/lib/libXss.so.1 (0x80e165000)
            libwebpdemux.so.2 => /usr/local/lib/libwebpdemux.so.2 (0x80e367000)
            libwebpmux.so.3 => /usr/local/lib/libwebpmux.so.3 (0x80e56b000)
            libwebp.so.7 => /usr/local/lib/libwebp.so.7 (0x80e775000)
            libfreetype.so.6 => /usr/local/lib/libfreetype.so.6 (0x80ea05000)
            libjpeg.so.8 => /usr/local/lib/libjpeg.so.8 (0x80ecbb000)
            libexpat.so.1 => /usr/local/lib/libexpat.so.1 (0x80ef4e000)
            libharfbuzz.so.0 => /usr/local/lib/libharfbuzz.so.0 (0x80f179000)
            libdrm.so.2 => /usr/local/lib/libdrm.so.2 (0x80f458000)
            libXrandr.so.2 => /usr/local/lib/libXrandr.so.2 (0x80f66b000)
            libgio-2.0.so.0 => /usr/local/lib/libgio-2.0.so.0 (0x80f875000)
            libavcodec.so.58 => /usr/local/lib/libavcodec.so.58 (0x80fe00000)
            libavformat.so.58 => /usr/local/lib/libavformat.so.58 (0x811800000)
            libavutil.so.56 => /usr/local/lib/libavutil.so.56 (0x811c52000)
            libopenh264.so.4 => /usr/local/lib/libopenh264.so.4 (0x811eca000)
            libasound.so.2 => /usr/local/lib/libasound.so.2 (0x8121da000)
            libsnappy.so.1 => /usr/local/lib/libsnappy.so.1 (0x8124de000)
            libopus.so.0 => /usr/local/lib/libopus.so.0 (0x8126e6000)
            libpangocairo-1.0.so.0 => /usr/local/lib/libpangocairo-1.0.so.0 (0x812956000)
            libpango-1.0.so.0 => /usr/local/lib/libpango-1.0.so.0 (0x812b63000)
            libcairo.so.2 => /usr/local/lib/libcairo.so.2 (0x812db1000)
            libGL.so.1 => /usr/local/lib/libGL.so.1 (0x8130d8000)
            libpci.so.3 => /usr/local/lib/libpci.so.3 (0x813366000)
            libatk-1.0.so.0 => /usr/local/lib/libatk-1.0.so.0 (0x813571000)
            libatk-bridge-2.0.so.0 => /usr/local/lib/libatk-bridge-2.0.so.0 (0x81379c000)
            libatspi.so.0 => /usr/local/lib/libatspi.so.0 (0x8139cc000)
            libFLAC.so.8 => /usr/local/lib/libFLAC.so.8 (0x813bfd000)
            libgtk-3.so.0 => /usr/local/lib/libgtk-3.so.0 (0x814000000)
            libgdk-3.so.0 => /usr/local/lib/libgdk-3.so.0 (0x8148b9000)
            libcairo-gobject.so.2 => /usr/local/lib/libcairo-gobject.so.2 (0x814bb0000)
            libgdk_pixbuf-2.0.so.0 => /usr/local/lib/libgdk_pixbuf-2.0.so.0 (0x814db8000)
            libxslt.so.1 => /usr/local/lib/libxslt.so.1 (0x814fdb000)
            libz.so.6 => /lib/libz.so.6 (0x815218000)
            liblzma.so.5 => /usr/lib/liblzma.so.5 (0x815430000)
            libm.so.5 => /lib/libm.so.5 (0x815659000)
            librt.so.1 => /usr/lib/librt.so.1 (0x815886000)
            libc++.so.1 => /usr/lib/libc++.so.1 (0x815a8c000)
            libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x815d5a000)
            libc.so.7 => /lib/libc.so.7 (0x800823000)
            libXau.so.6 => /usr/local/lib/libXau.so.6 (0x815f79000)
            libXdmcp.so.6 => /usr/local/lib/libXdmcp.so.6 (0x81617c000)
            libiconv.so.2 => /usr/local/lib/libiconv.so.2 (0x816381000)
            libpcre.so.1 => /usr/local/lib/libpcre.so.1 (0x81667c000)
            libffi.so.6 => /usr/local/lib/libffi.so.6 (0x81691a000)
            libgnutls.so.30 => /usr/local/lib/libgnutls.so.30 (0x816b21000)
            libavahi-common.so.3 => /usr/local/lib/libavahi-common.so.3 (0x816ed4000)
            libavahi-client.so.3 => /usr/local/lib/libavahi-client.so.3 (0x8170e0000)
            libcrypt.so.5 => /lib/libcrypt.so.5 (0x8172ef000)
            libelf.so.2 => /lib/libelf.so.2 (0x81750e000)
            libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x817725000)
            libbz2.so.4 => /usr/lib/libbz2.so.4 (0x817934000)
            libgraphite2.so.3 => /usr/local/lib/libgraphite2.so.3 (0x817b48000)
            libswresample.so.3 => /usr/local/lib/libswresample.so.3 (0x817d71000)
            libvpx.so.6 => /usr/local/lib/libvpx.so.6 (0x818000000)
            libdav1d.so.1 => /usr/local/lib/libdav1d.so.1 (0x818411000)
            libmp3lame.so.0 => /usr/local/lib/libmp3lame.so.0 (0x818732000)
            libtheoraenc.so.1 => /usr/local/lib/libtheoraenc.so.1 (0x8189b3000)
            libtheoradec.so.1 => /usr/local/lib/libtheoradec.so.1 (0x818be2000)
            libvorbis.so.0 => /usr/local/lib/libvorbis.so.0 (0x818df3000)
            libvorbisenc.so.2 => /usr/local/lib/libvorbisenc.so.2 (0x819024000)
            libx264.so.155 => not found (0)
            libx265.so.170 => /usr/local/lib/libx265.so.170 (0x819400000)
            libxvidcore.so.4 => /usr/local/lib/libxvidcore.so.4 (0x819b4b000)
            libva.so.2 => /usr/local/lib/libva.so.2 (0x819e70000)
            libgmp.so.10 => /usr/local/lib/libgmp.so.10 (0x81a096000)
            libva-drm.so.2 => /usr/local/lib/libva-drm.so.2 (0x81a316000)
            libva-x11.so.2 => /usr/local/lib/libva-x11.so.2 (0x81a518000)
            libvdpau.so.1 => /usr/local/lib/libvdpau.so.1 (0x81a71d000)
            libpangoft2-1.0.so.0 => /usr/local/lib/libpangoft2-1.0.so.0 (0x81a920000)
            libfribidi.so.0 => /usr/local/lib/libfribidi.so.0 (0x81ab36000)
            libpixman-1.so.0 => /usr/local/lib/libpixman-1.so.0 (0x81ad4c000)
            libEGL.so.1 => /usr/local/lib/libEGL.so.1 (0x81b016000)
            libpng16.so.16 => /usr/local/lib/libpng16.so.16 (0x81b24e000)
            libxcb-shm.so.0 => /usr/local/lib/libxcb-shm.so.0 (0x81b489000)
            libxcb-render.so.0 => /usr/local/lib/libxcb-render.so.0 (0x81b68b000)
            libxcb-dri3.so.0 => /usr/local/lib/libxcb-dri3.so.0 (0x81b898000)
            libxcb-xfixes.so.0 => /usr/local/lib/libxcb-xfixes.so.0 (0x81ba9b000)
            libxcb-present.so.0 => /usr/local/lib/libxcb-present.so.0 (0x81bca2000)
            libxcb-sync.so.1 => /usr/local/lib/libxcb-sync.so.1 (0x81bea4000)
            libxshmfence.so.1 => /usr/local/lib/libxshmfence.so.1 (0x81c0aa000)
            libglapi.so.0 => /usr/local/lib/libglapi.so.0 (0x81c2ab000)
            libxcb-glx.so.0 => /usr/local/lib/libxcb-glx.so.0 (0x81c505000)
            libxcb-dri2.so.0 => /usr/local/lib/libxcb-dri2.so.0 (0x81c71e000)
            libXxf86vm.so.1 => /usr/local/lib/libXxf86vm.so.1 (0x81c922000)
            libogg.so.0 => /usr/local/lib/libogg.so.0 (0x81cb26000)
            libXinerama.so.1 => /usr/local/lib/libXinerama.so.1 (0x81cd2c000)
            libxkbcommon.so.0 => /usr/local/lib/libxkbcommon.so.0 (0x81cf2e000)
            libwayland-cursor.so.0 => /usr/local/lib/libwayland-cursor.so.0 (0x81d16b000)
            libwayland-egl.so.1 => /usr/local/lib/libwayland-egl.so.1 (0x81d372000)
            libwayland-client.so.0 => /usr/local/lib/libwayland-client.so.0 (0x81d573000)
            libepoxy.so.0 => /usr/local/lib/libepoxy.so.0 (0x81d782000)
            libp11-kit.so.0 => /usr/local/lib/libp11-kit.so.0 (0x81da91000)
            libtasn1.so.6 => /usr/local/lib/libtasn1.so.6 (0x81ddb2000)
            libnettle.so.6 => /usr/local/lib/libnettle.so.6 (0x81dfc7000)
            libhogweed.so.4 => /usr/local/lib/libhogweed.so.4 (0x81e1ff000)
            libidn2.so.0 => /usr/local/lib/libidn2.so.0 (0x81e435000)
            libunistring.so.2 => /usr/local/lib/libunistring.so.2 (0x81e653000)
            libgbm.so.1 => /usr/local/lib/libgbm.so.1 (0x81ea07000)
            libwayland-server.so.0 => /usr/local/lib/libwayland-server.so.0 (0x81ec15000)
            libepoll-shim.so.0 => /usr/local/lib/libepoll-shim.so.0 (0x81ee28000)
    % ldd /usr/local/share/chromium/chrome | grep found
            libx264.so.155 => not found (0)
    % cd /usr/local/lib
    % ls -l libx264.so*
    lrwxr-xr-x  1 root  wheel       14 2019.03.19 02:11 libx264.so -> libx264.so.157
    -rwxr-xr-x  1 root  wheel  2090944 2019.03.19 02:11 libx264.so.157
    # pwd
    /usr/local/lib
    # ln -s libx264.so libx264.so.155
    # ls -l libx264.so*
    lrwxr-xr-x  1 root  wheel       14 2019.03.19 02:11 libx264.so -> libx264.so.157
    lrwxr-xr-x  1 root  wheel       10 2019.03.21 15:26 libx264.so.155 -> libx264.so
    -rwxr-xr-x  1 root  wheel  2090944 2019.03.19 02:11 libx264.so.157
    % ldd /usr/local/share/chromium/chrome | grep found
    %
    % chrome
    # cat /etc/libmap.conf
    
    [/usr/local/share/chromium/chrome]
    libx264.so.155 libx264.so
    # cat /etc/libmap.conf
    
    libx264.so.155 libx264.so
    # portmaster --check-depends
    (...)
    Checking dependencies: evince
    graphics/evince has a missing dependency: www/libxul19
    (...)
    
    >>> Missing package dependencies were detected.
    >>> Found 1 issue(s) in total with your package database.
    
    The following packages will be installed:
    
            Downgrading perl: 5.14.2_3 -> 5.14.2_2
            Downgrading glib: 2.34.3 -> 2.28.8_5
            Downgrading gio-fam-backend: 2.34.3 -> 2.28.8_1
            Downgrading libffi: 3.0.12 -> 3.0.11
            Downgrading gobject-introspection: 1.34.2 -> 0.10.8_3
            Downgrading atk: 2.6.0 -> 2.0.1
            Downgrading gdk-pixbuf2: 2.26.5 -> 2.23.5_3
            Downgrading pango: 1.30.1 -> 1.28.4_1
            Downgrading gtk-update-icon-cache: 2.24.17 -> 2.24.6_1
            Downgrading dbus: 1.6.8 -> 1.4.14_4
            Downgrading gtk: 2.24.17 -> 2.24.6_2
            Downgrading dbus-glib: 0.100.1 -> 0.94
            Installing libxul: 1.9.2.28_1
    
    The installation will require 66 MB more space
    
    38 MB to be downloaded
    
    >>> Try to fix the missing dependencies [y/N]: n
    >>> Summary of actions performed:
    
    www/libxul19 dependency failed to be fixed
    
    >>> There are still missing dependencies.
    >>> You are advised to try fixing them manually.
    
    >>> Also make sure to check 'pkg updating' for known issues.
    # pkg info | grep libxul
    libxul-10.0.12                 Mozilla runtime package that can be used to bootstrap XUL+XPCOM apps
    
    # pkg info -qoa | grep libxul
    www/libxul
    # pkg shell
    SQLite version 3.7.13 2012-06-11 02:05:22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> .databases
    seq  name             file
    ---  ---------------  ----------------------------------------------------------
    0    main             /var/db/pkg/local.sqlite
    sqlite> .tables
    categories       licenses         pkg_directories  scripts
    deps             mtree            pkg_groups       shlibs
    directories      options          pkg_licenses     users
    files            packages         pkg_shlibs
    groups           pkg_categories   pkg_users
    sqlite> .header on
    sqlite> .mode column
    sqlite> pragma table_info(deps);
    cid         name        type        notnull     dflt_value  pk
    ----------  ----------  ----------  ----------  ----------  ----------
    0           origin      TEXT        1                       1
    1           name        TEXT        1                       0
    2           version     TEXT        1                       0
    3           package_id  INTEGER     0                       1
    sqlite> .quit
    # sqlite3 -column /var/db/pkg/local.sqlite "select * from deps;" | grep libxul
    www/libxul19   libxul      1.9.2.28_1  104
    sqlite3 -header -column /var/db/pkg/local.sqlite "select * from deps where name='libxul';"
    origin        name        version     package_id
    ------------  ----------  ----------  ----------
    www/libxul19  libxul      1.9.2.28_1  104
    # sqlite3 /var/db/pkg/local.sqlite "update deps set origin='www/libxul' where name='libxul';"
    # sqlite3 /var/db/pkg/local.sqlite "update deps set version='10.0.12' where name='libxul';"
    # pkg shell
    SQLite version 3.7.13 2012-06-11 02:05:22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> update deps set origin='www/libxul' where name='libxul';
    sqlite> update deps set version='10.0.12' where name='libxul';
    sqlite> .header on
    sqlite> .mode column
    sqlite> select * from deps where name='libxul';
    origin      name        version     package_id
    ----------  ----------  ----------  ----------
    www/libxul  libxul      10.0.12     104
    sqlite> .quit
    # portmaster --check-depends
    (...)
    Checking dependencies: zenity
    Checking dependencies: zip
    Checking dependencies: zsh
    #
      -n oldname:newname, --change-name oldname:newname
           Change the package name of a given dependency from oldname to newname.
           将指定依赖项的包名从 `oldname` 修改为 `newname`。
    
    (...)
    
      -o oldorigin:neworigin, --change-origin oldorigin:neworigin
           Change the port origin of a given dependency from oldorigin to neworigin.
           This corresponds to the port directory that the package originated from.
           Typically, this is only needed for upgrading a library or package that
           has MOVED or when the default version of a major port dependency changes.
           (DEPRECATED) Usually this will be explained in /usr/ports/UPDATING.
           Also see pkg-updating(8) and EXAMPLES.
           将指定依赖项的 Port 来源从 oldorigin 修改为 neworigin。
           这对应于该包最初来源的 Port 目录。通常,仅在升级已被 MOVED 的库或包,或者主要 Port 依赖的默认版本发生变化时才需要使用此功能。(已弃用)通常相关说明会在 /usr/ports/UPDATING 中给出。
           另请参见 pkg-updating(8) 和示例。
    # pkg search bsdadmin
    bsdadminscripts-6.1.1_8        Collection of administration scripts
    bsdadminscripts2-0.2.1         BSD Administration Scripts 2
    # pkg install bsdadminscripts
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    Checking integrity... done (1 conflicting)
      - bsdadminscripts-6.1.1_8 conflicts with bsdadminscripts2-0.2.1 on /usr/local/sbin/distviper
    Checking integrity... done (0 conflicting)
    The following 2 package(s) will be affected (of 0 checked):
    
    Installed packages to be REMOVED:
            bsdadminscripts2-0.2.1
    
    New packages to be INSTALLED:
            bsdadminscripts: 6.1.1_8
    
    Number of packages to be removed: 1
    Number of packages to be installed: 1
    
    Proceed with this action? [y/N]: n
    # cat /usr/ports/ports-mgmt/bsdadminscripts2/pkg-descr
    This is a collection of scripts around the use of ports and packages.
    
    It allows you to: 
    - check library dependencies without producing false positives (pkg_libchk)
    - lets you manage the autoremove flag for leaf packages (pkg_trim)
    - remove obsolete or damaged distfiles (distviper)
    - manage build flags (buildflags.conf)
    - auto-create pkg-plist files taking port options into account (makeplist)
    
    WWW: https://github.com/lonkamikaze/bsda2
    % pkg info -l bsdadminscripts2 | grep bin
            /usr/local/sbin/distviper
            /usr/local/sbin/makeplist
            /usr/local/sbin/pkg_libchk
            /usr/local/sbin/pkg_trim
    # pkg_libchk
    Jobs done:   35 of 1057
    bhyve-firmware-1.0_1
    bash-5.0.3
    beadm-1.2.9_1
    pkg_libchk chromium
    % pkg provides lib/libx264.so
    Name    : libx264-0.157.2945
    Desc    : H.264/MPEG-4 AVC Video Encoding (Library)
    Repo    : FreeBSD
    Filename: /usr/local/lib/libx264.so.155
              /usr/local/lib/libx264.so
    引言

    自家服务器的硬盘使用量已经快超过 80%[1],同时硬盘也已经使用了 10 多年。出于安全考虑,决定更换硬盘。因此,我购买了新的硬盘并进行了更换。本文记录了实际更换硬盘的过程。

    值得一提的是,笔者的服务器操作系统是 FreeBSD,但如果是在 Linux 上使用 ZFS,相关操作也是类似的(笔者也在 Linux 上使用 ZFS)。

    服务器存储结构

    目标服务器的操作系统为 FreeBSD,存储结构如下:用于系统的固态硬盘(256GB)1 块,用于数据存储的硬盘(2TB)2 块,所有硬盘均使用 ZFS 进行配置。这两块硬盘通过 ZFS 配置为镜像(mirror)方式,意味着即使有两块硬盘,容量仅相当于一块硬盘的容量。此次操作将把这两块 2TB 的硬盘分别更换为 6TB 的硬盘。

    更换前的检查

    在实际进行更换操作之前,我们先检查当前的状态。通过执行 zpool list 命令,查看硬盘的使用情况,输出如下:

    zroot 是系统用的 SSD,而 zvol0 是这次更换的硬盘,ZFS 镜像结构的使用量为 82%。

    可以通过 zpool list -v 或 zpool status 命令查看更详细的配置:

    从中可以看到,ndisk1 和 ndisk2 是组成镜像的硬盘分区。三块存储设备分别为 ada0(SSD)、ada1(硬盘)和 ada2(硬盘)。硬盘的分区信息如下:

    从中可以看出,ada1 和 ada2 均使用 GPT 分区,ada1 的 ZFS 用分区被命名为 ndisk1,ada2 的则为 ndisk2。

    镜像结构下的硬盘更换步骤

    对于 ZFS 或其他 RAID 1 镜像(Mirror)结构的硬盘,更换两块硬盘的步骤大致有两种方法:

    • 使用新的硬盘构建镜像,然后从现有镜像中复制数据,复制完成后再更换硬盘。或者先更换硬盘,再从原硬盘复制数据。

    • 更换其中一块硬盘,利用镜像功能同步数据,完成后再更换另一块硬盘并重新同步数据。

    如果采用第一种方法,数据复制仅需进行一次,但需要同时连接 3 或 4 台硬盘,这可能会受到 SATA 接口数量等限制。虽然硬盘可以通过 USB 连接,但如果使用 USB 2.0 接口,传输速度较慢,复制时间较长,因此建议使用 USB 3.0 接口。

    笔者选择了第二种方法,即逐个更换硬盘。这样,即便在数据同步期间(虽然会有性能下降),服务器仍然可以正常使用,这是一大优势。

    更换硬盘与数据同步

    ZFS 镜像中硬盘更换时的注意事项

    在更换 ZFS 镜像中的硬盘时,有一点非常重要:切勿在更换前执行 ZFS 池的操作,如 zpool detach zvol0 gpt/ndisk2 等。因为如果使用 zpool detach 将 ndisk2 从池中分离,ndisk2 上的数据会被视为已删除。若在数据同步过程中,ndisk1 读取出现错误,就无法使用新硬盘来重新同步数据了 [2]。如果只是切断电源并拆下 ndisk2,ndisk2 上的数据仍然会与 ndisk1 相同,因此万一出现问题时,可以使用 ndisk2 来进行恢复。

    更换第一块硬盘

    首先更换第一块硬盘,即拆下包含 ndisk2 分区的硬盘。关机并切断电源后,取下旧硬盘并连接新硬盘,然后重新开机。

    启动后,检查 zvol0 的状态:

    此时,虽然硬盘是镜像配置,但由于一侧的 gpt/ndisk2 缺失,状态变为 DEGRADED(降级)。在 zpool status 的输出中,config: 部分显示 gpt/ndisk2 不再出现,而是用一个 ID(12897545936258916783)代替,并且行尾标记为 "was /dev/gpt/ndisk2"。这个 ID 后续将会用到。

    创建交换分区

    为了准备更换用的硬盘,我们首先需要对其进行 GPT 初始化,并为 ZFS 创建一个分区。

    首先,我们使用 GPT 初始化硬盘:

    接下来,我们为 ZFS 创建一个分区。为了便于区分,我们将新分区命名为 sdisk1。

    同步第一台硬盘的数据

    新分区创建完成后,接下来用 sdisk1 替换旧的 ndisk2。我们使用 zpool replace 命令来完成此操作。

    通常,zpool replace 命令的第一个参数是要替换的设备,而第二个参数是新的设备。在本例中,由于硬盘已经被移除,所以原来的设备已经不存在了,因此我们需要指定 zpool status zvol0 中显示的 ID。

    此时,ndisk1 的镜像同步将在 sdisk1 上开始。

    同步过程将在后台进行,并且正如之前提到的,在此期间,服务器可以正常使用。由于数据量大约为 1.5TB,所需的同步时间会比较长。不过,ZFS 可以通过 zpool status 来查看同步的进度,这样我们就能得到一个结束时间的大致估算。

    在 zpool status 中,你会看到 One or more devices is currently being resilvered [3],这表明正在进行 resilver 操作(即同步)。在 action 部分,系统会指示你等待 resilver 操作完成。同时,scan 部分显示了处理的进度和预计完成时间,但在同步开始时,通常会看到 no estimated completion time,这意味着系统无法立即估算预计时间。

    稍等片刻,预计时间会逐渐显示,但根据经验,这个估算并不总是准确的。

    例如,刚开始时,你可能会看到类似下面的输出:

    过了一段时间,预计完成时间可能会变为:

    一小时后,你可能会看到预估的时间减少到 6 小时左右,但最终同步的实际时间可能比预估的要长。最终,第一台硬盘的同步总共花费了大约 15 小时半。

    以下是第一台硬盘同步完成时,检查 zpool list 和 zpool status 的结果:

    HEALTH 和 STATE 都显示为 ONLINE,且没有出现任何错误,可以确认第一台硬盘的同步已经顺利完成。

    第二台硬盘的同步

    第二台硬盘的更换和同步步骤与第一台完全相同,因此这里只展示相关命令的执行和结果。

    更换第二台硬盘并启动后。

    准备用于镜像的分区

    第二台同步开始

    第二台的同步大约用了 14 个小时。

    容量的扩展

    硬盘交换和数据同步顺利完成,但仍有一些工作需要完成。因为目前仅仅是更换了硬盘,并没有启用 2TB → 6TB 的容量扩展。

    重新检查 zvol0 的容量时,发现 SIZE 仍为 1.81T,与更换前相同。然而,EXPANDSZ 显示为 3.62T,这意味着还可以扩展 3.62TB 的空间。

    这个容量扩展是通过设置 ZFS 池的 autoexpand 属性来实现的。首先,检查当前 autoexpand 的值,发现默认值为 off。

    将 autoexpand 设置为 on。

    但是,仅将 autoexpand 设置为 on 并不会改变容量。

    要扩展容量,需要在设置了 autoexpand=on 之后,执行 zpool online -e。

    忘记指定设备名导致了错误 😅,但实际上,使用 zpool online 时必须指定设备名,而当使用 -e 选项时,应该指定池内某个设备名才可以执行。

    重新指定设备名并执行后,容量成功扩展到 5.45TB [4]。

    这次是硬盘更换后才修改 autoexpand 属性,如果在更换前就设置,容量会在第二台硬盘同步完成时自动扩展。同时,autoexpand 不仅适用于镜像,还可以在 RAIDZ 等结构中使用。

    2023-07-16 补充:通过 zpool online -e 扩展时,其实不需要设置 autoexpand 属性。autoexpand 属性是为了自动扩展容量而设计的。

    交换完成后

    由于新硬盘的传输速度提高,因此整体性能得到了提升。尽管 CPU 已经使用了 10 多年,但由于主要用途是文件服务器,仍然可以继续使用一段时间。


    1. 在 ZFS 中,由于采用了 Copy on Write 数据更新机制,当空闲空间不足时,性能通常会比其他文件系统低得多(在硬盘上尤为明显)。因此,将容量使用到极限并不明智。关于多少空间使用会导致性能下降,这取决于工作集,因此无法简单地确定。但即使是其他文件系统认为影响不大的空闲空间,在 ZFS 中也可能导致性能下降。

    2. 即使是卸载(detach)了 ndisk2,也可以通过 zpool import -D 来恢复数据,但我并没有试过。

    3. 我是在使用 ZFS 后才知道“resilver”这个词,原本它是指磨光银饰品,在 ZFS 中则表示 RAID 恢复中。

    4. 硬盘的 TB 是按十进制容量表示的,因此 6TB 是 6,000,000,000,000 字节,而二进制的 1TB 为 1,099,511,627,776 字节,所以实际容量为 5.45TB。

    ZFS ミラープールのディスク 交換 による 容量増設
    $ zpool list
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
    zroot   228G  16.8G   211G        -         -    12%     7%  1.00x  ONLINE  -
    zvol0  1.81T  1.49T   333G        -         -     5%    82%  1.00x  ONLINE  -
    $
    $ zpool list -v zvol0
    NAME             SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  
    zvol0           1.81T  1.49T   333G        -         -     5%    82%  1.00x    ONLINE  -
      mirror-0      1.81T  1.49T   333G        -         -     5%  82.1%      -    ONLINE
        gpt/ndisk2      -      -      -        -         -      -      -      -    ONLINE
        gpt/ndisk1      -      -      -        -         -      -      -      -    ONLINE
    $
    $ zpool status zvol0
      pool: zvol0
     state: ONLINE
      scan: scrub repaired 0B in 05:36:58 with 0 errors on Tue Jan 17 08:40:57 2023
    config:
    
            NAME            STATE     READ WRITE CKSUM
            zvol0           ONLINE       0     0     0
              mirror-0      ONLINE       0     0     0
                gpt/ndisk2  ONLINE       0     0     0
                gpt/ndisk1  ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ gpart show ada1 ada2
    =>        40  3907029088  ada1  GPT  (1.8T)
              40  3907029088     1  freebsd-zfs  (1.8T)
    
    =>        40  3907029088  ada2  GPT  (1.8T)
              40  3907029088     1  freebsd-zfs  (1.8T)
    
    $ gpart show -l ada1 ada2
    =>        40  3907029088  ada1  GPT  (1.8T)
              40  3907029088     1  ndisk1  (1.8T)
    
    =>        40  3907029088  ada2  GPT  (1.8T)
              40  3907029088     1  ndisk2  (1.8T)
    
    $
    $ zpool list
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    zroot   228G  16.8G   211G        -         -    12%     7%  1.00x    ONLINE  -
    zvol0  1.81T  1.49T   333G        -         -     5%    82%  1.00x  DEGRADED  -
    $
    $ zpool status zvol0
      pool: zvol0
     state: DEGRADED
    status: One or more devices could not be opened.  Sufficient replicas exist for
            the pool to continue functioning in a degraded state.
    action: Attach the missing device and online it using 'zpool online'.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
      scan: scrub repaired 0B in 05:36:58 with 0 errors on Tue Jan 17 08:40:57 2023
    config:
    
            NAME                      STATE     READ WRITE CKSUM
            zvol0                     DEGRADED     0     0     0
              mirror-0                DEGRADED     0     0     0
                12897545936258916783  UNAVAIL      0     0     0  was /dev/gpt/ndisk2
                gpt/ndisk1            ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ gpart show ada1
    gpart: No such geom: ada1.
    $ gpart create -s gpt ada1
    ada1 created
    $ gpart show ada1
    =>         40  11721045088  ada1  GPT  (5.5T)
               40  11721045088        - free -  (5.5T)
    
    $
    $ gpart add -t freebsd-zfs -a 4k -l sdisk1 ada1
    ada1p1 added
    $ gpart show ada1
    =>         40  11721045088  ada1  GPT  (5.5T)
               40  11721045088     1  freebsd-zfs  (5.5T)
    
    $ gpart show -l ada1
    =>         40  11721045088  ada1  GPT  (5.5T)
               40  11721045088     1  sdisk1  (5.5T)
    
    $
    $ zpool replace zvol0 12897545936258916783 gpt/sdisk1
    $
    $ zpool status zvol0
      pool: zvol0
     state: DEGRADED
    status: One or more devices is currently being resilvered.  The pool will
            continue to function, possibly in a degraded state.
    action: Wait for the resilver to complete.
      scan: resilver in progress since Sat Jan 28 14:25:44 2023
            12.8G scanned at 596M/s, 600K issued at 27.3K/s, 1.49T total
            0B resilvered, 0.00% done, no estimated completion time
    config:
    
            NAME                        STATE     READ WRITE CKSUM
            zvol0                       DEGRADED     0     0     0
              mirror-0                  DEGRADED     0     0     0
                replacing-0             DEGRADED     0     0     0
                  12897545936258916783  UNAVAIL      0     0     0  was /dev/gpt/ndisk2
                  gpt/sdisk1            ONLINE       0     0     0
                gpt/ndisk1              ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ zpool status zvol0
    ===== <省略> =====
      scan: resilver in progress since Sat Jan 28 14:25:44 2023
            265G scanned at 664M/s, 6.51G issued at 16.3M/s, 1.49T total
            6.51G resilvered, 0.43% done, 1 days 02:27:43 to go
    ===== <省略> =====
    $
    $ zpool status zvol0
    ===== <省略> =====
      scan: resilver in progress since Sat Jan 28 14:25:44 2023
            289G scanned at 488M/s, 18.6G issued at 31.4M/s, 1.49T total
            18.6G resilvered, 1.22% done, 13:38:30 to go
    ===== <省略> =====
    $
    $ zpool list -v zvol0
    NAME             SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    zvol0           1.81T  1.49T   333G        -         -     5%    82%  1.00x    ONLINE  -
      mirror-0      1.81T  1.49T   333G        -         -     5%  82.1%      -    ONLINE
        gpt/sdisk1      -      -      -        -         -      -      -      -    ONLINE
        gpt/ndisk1      -      -      -        -         -      -      -      -    ONLINE
    $
    $ zpool status zvol0
      pool: zvol0
     state: ONLINE
      scan: resilvered 1.49T in 15:34:45 with 0 errors on Sun Jan 29 06:00:29 2023
    config:
    
            NAME            STATE     READ WRITE CKSUM
            zvol0           ONLINE       0     0     0
              mirror-0      ONLINE       0     0     0
                gpt/sdisk1  ONLINE       0     0     0
                gpt/ndisk1  ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ zpool status zvol0
      pool: zvol0
     state: DEGRADED
    status: One or more devices could not be opened.  Sufficient replicas exist for
            the pool to continue functioning in a degraded state.
    action: Attach the missing device and online it using 'zpool online'.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
      scan: resilvered 1.49T in 15:34:45 with 0 errors on Sun Jan 29 06:00:29 2023
    config:
    
            NAME                      STATE     READ WRITE CKSUM
            zvol0                     DEGRADED     0     0     0
              mirror-0                DEGRADED     0     0     0
                gpt/sdisk1            ONLINE       0     0     0
                13953654332474917058  UNAVAIL      0     0     0  was /dev/gpt/ndisk1
    
    errors: No known data errors
    $
    # gpart create -s gpt ada2
    ada2 created
    # gpart show ada2
    =>         40  11721045088  ada2  GPT  (5.5T)
               40  11721045088        - free -  (5.5T)
    
    # gpart add -t freebsd-zfs -a 4k -l sdisk2 ada2
    ada2p1 added
    # gpart show ada2
    =>         40  11721045088  ada2  GPT  (5.5T)
               40  11721045088     1  freebsd-zfs  (5.5T)
    
    # gpart show -l ada2
    =>         40  11721045088  ada2  GPT  (5.5T)
               40  11721045088     1  sdisk2  (5.5T)
    
    #
    
    $ zpool replace zvol0 13953654332474917058 gpt/sdisk2
    $ zpool status zvol0
      pool: zvol0
     state: DEGRADED
    status: One or more devices is currently being resilvered.  The pool will
            continue to function, possibly in a degraded state.
    action: Wait for the resilver to complete.
      scan: resilver in progress since Sun Jan 29 13:38:15 2023
            12.8G scanned at 692M/s, 492K issued at 25.9K/s, 1.49T total
            0B resilvered, 0.00% done, no estimated completion time
    config:
    
            NAME                        STATE     READ WRITE CKSUM
            zvol0                       DEGRADED     0     0     0
              mirror-0                  DEGRADED     0     0     0
                gpt/sdisk1              ONLINE       0     0     0
                replacing-1             DEGRADED     0     0     0
                  13953654332474917058  UNAVAIL      0     0     0  was /dev/gpt/ndisk1
                  gpt/sdisk2            ONLINE       0     0     0
    
    errors: No known data errors
    $ zpool status zvol0
      pool: zvol0
     state: ONLINE
      scan: resilvered 1.49T in 14:11:00 with 0 errors on Mon Jan 30 03:49:15 2023
    config:
    
            NAME            STATE     READ WRITE CKSUM
            zvol0           ONLINE       0     0     0
              mirror-0      ONLINE       0     0     0
                gpt/sdisk1  ONLINE       0     0     0
                gpt/sdisk2  ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ zpool list zvol0
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    zvol0  1.81T  1.49T   333G        -     3.62T     5%    82%  1.00x    ONLINE  -
    $
    $ zpool get autoexpand zvol0
    NAME   PROPERTY    VALUE   SOURCE
    zvol0  autoexpand  off     default
    $
    $ zpool set autoexpand=on zvol0
    $ zpool get autoexpand zvol0
    NAME   PROPERTY    VALUE   SOURCE
    zvol0  autoexpand  on      local
    $
    $ zpool list zvol0
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    zvol0  1.81T  1.49T   333G        -     3.62T     5%    82%  1.00x    ONLINE  -
    $
    $ zpool online -e zvol0
    missing device name
    usage:
            online [-e] <pool> <device> ...
    $
    $ zpool online -e zvol0 gpt/sdisk1
    $ zpool list zvol0
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    zvol0  5.45T  1.49T  3.97T        -         -     1%    27%  1.00x    ONLINE  -
    $

    -help

  • --help

  • 代码量减少 15%。
  • 正确处理整个设备上的 bsdlabel(8)。

  • 正确处理整个设备上的 exFAT。

  • 显示标签。
  • 添加 -d|–disks 选项,仅列出整个磁盘。

  • 当整个设备没有分区时,正确显示 exFAT 文件系统标签。

  • 修复 NTFS-3G 挂载点显示。

  • 检查 automount(8) 的 /var/run/automount.state 以处理 fusefs(5) 文件系统。

  • 改进 md(4) 磁盘大小处理。

  • 移除标签中的冗余空格。

  • 为 -d 选项添加 TOTAL SYSTEM STORAGE。

  • 移除主设备检查循环中的子 shell。

  • sysutils/beadm
    sysutils/automount
    lsblk(8) Command for FreeBSD
    283268

    上次更新于 2022-12-26

    开始之前

    在上一篇文章 试着破坏了 ZFS 池 中,我们确认了 ZFS 能够正确地检测出磁盘上的非法数据。

    能够检测出非法数据这一点,比起那些无法检测到非法数据而可能在读取时引发错误行为的文件系统,要好得多。但既然能检测到非法数据,自然而然就会想到:那是否可以将其恢复呢?

    在 ZFS 中,如果构建了具备冗余性的池,即使存在非法数据,也可以获取到正确的数据。具体来说,可以使用镜像(mirror)、RAID-Z 或 RAID-Z2 等池结构。

    本文将基于与 试着破坏了 ZFS 池 相同的实验,在镜像结构的 ZFS 池上进行测试。

    2022 年 12 月 26 日补充了执行 scrub 后的磁盘状态

    准备 ZFS 镜像池

    为了实验,准备了 2 台通过 USB 连接的 HDD,并在每台硬盘上创建了 4GB 的分区,用于构建镜像结构的 ZFS 池。

    这两块 HDD 分别是 /dev/da1 和 /dev/da2,使用 GPT 创建分区表,并在每块硬盘上创建了带有 tt1 和 tt2 标签的分区。

    至此,镜像所需的两个 HDD 各自的分区已创建完成。

    接下来,将这两个分区组合成一个 ZFS 镜像池。当然和 上次的实验 一样,不启用 ZFS 压缩。

    如下所示,镜像结构的 ZFS 池已创建完成。

    写入伪数据

    那么就像上次实验一样,使用 dd 命令用零数据填满文件系统。

    破坏写入的数据

    接着像上次一样,强行写入垃圾数据,使其在 ZFS 中触发错误。由于是为了验证镜像冗余性和 ZFS 的修复功能,因此只向 da1 这一侧写入垃圾数据。

    通常,从构成镜像的磁盘中读取数据时,为了分散负载和提升性能,会交替访问两个磁盘。ZFS 的镜像结构也有类似行为。因此,如果像上次一样仅破坏一个区块,读取时可能会正好绕过被破坏的区块,访问正常的磁盘。因此,这次将写入几十 MB 的数据,以制造更大范围的错误。刚好内核有将近 30MB,就用它来破坏数据。

    读取被破坏的数据部分

    为了确认是否发生错误,仅使用 da1 这一侧进行导入。因为是 USB 接口的 HDD,把 da2 实体移除是最简单的方法。

    如上所示,无法访问 da2 侧的 gpt/tt2。就这样将 ztest 导入。

    虽然只有一侧的驱动器,但 /ztest/dummy 确实存在。那么现在尝试实际读取它的内容。为了确认数据内容,这里使用 hd 命令进行读取。

    无法读取文件,发生了错误。

    镜像结构下的读取

    现在重新恢复镜像结构,再次进行同样的操作。

    此时,重新连接之前拔下的 da2 侧 USB 硬盘。

    可以看到,gpt/tt2 一侧的状态已经是 ONLINE。那么就将 ztest 导入。

    成功地导入了 ztest。接下来就像之前一样,尝试读取 /ztest/dummy 文件。

    正如所见,文件已被正常读取,并且可以确认其内容全部为 0。

    接着确认一下 ztest 的状态,可以看到一切正常,没有问题。

    通过 scrub 检查磁盘一致性

    ZFS 理论上应该存在无法读取的损坏块,因此执行了 scrub 操作来进行一致性检查。

    经过一段时间后,确认 scrub 完成后的状态如下:

    从该结果可以看出,gpt/tt1(da1 一侧)发生了 130 次校验和错误。但由于镜像(mirror)结构,从健康的 gpt/tt2 一侧获取了正确的数据,并在 scrub 过程中修复了损坏的数据。

    重新读取数据

    为了排除操作系统磁盘缓存的影响,先将池导出再重新导入,并重新进行读取操作:

    如上所示,尽管存在发生错误的磁盘,但由于镜像结构的作用,依然成功读取到了正确的数据。

    已经成功导出,因此现在物理上移除 da2 一侧,只使用 da1 一侧进行导入并尝试读取数据。

    成功读取了损坏侧 da1 上的所有数据,完全没有问题。也就是说,通过 scrub 操作,数据被写回并得到了修复。而且实际在导入之后通过 status 确认,CKSUM 的值也确实是 0(可惜没来得及截图……)。

    接下来,再次为已经导出的 ztest 连接上 da2,并尝试导入。

    如上所示,错误已经被清除。

    总结

    通过本次实验可以确认,在 ZFS 中将磁盘配置为镜像或 RAID-Z 结构,可以避免部分数据错误的影响。同时也验证了,对于可以修复的数据,执行 scrub 后能够恢复为原来的状态。

    不仅仅是 ZFS,其他的卷管理器或 RAID 系统,如果正确配置了镜像或 RAID,也同样能够避免部分数据错误。而是否能够实现自动修复,则取决于各个系统的具体实现。

    ZFS プールをミラーで 構成 することで、不正 データの 影響 を 無 くす

    GPL 之殇

    • 原地址:https://unixsheikh.com/articles/the-problems-with-the-gpl.html

    • 最后发布日期:2023-10-28

    GNU 公共许可证(GPL)的诞生,正是为了与标准的专有许可证对抗。下面我们来看看 GPL 存在的一些问题。

    什么是 GPL

    GNU 通用公共许可证(GPL)是一系列软件许可证,用来“保证”最终用户拥有运行、研究、分发和修改软件的四项自由。

    GPL 的主要目的,是禁止将基于 GPL 授权的软件纳入专有软件中。

    一切对 GPL 授权软件所做的修改,都必须回馈给 GPL 社区;一切使用和链接了 GPL 源代码的应用程序,也必须遵循 GPL 授权。

    GPL 相当复杂:

    • 你不能出售 GPL 授权的软件,但你可以对软件的分发、支持或文档收取任意费用。

    • 如果一款程序在编译时需要使用 GPL 授权的源代码,那么该程序也必须遵循 GPL。静态链接到 GPL 库的程序必须采用 GPL 授权。

    由于 Linux 内核是基于 GPL 授权的,一切静态链接到 Linux 内核的代码也必须采用 GPL 授权。可以通过动态链接可加载内核模块来避免这一限制。这样公司就能分发二进制驱动程序,但缺点是它们仅适用于特定版本的 Linux 内核。

    由于 GPL 的复杂性,其合法性在世界许多地区实际上被忽视了。

    专有公司造成的损害

    某些公司会改进开源软件,但从不共享这些改进;另一些公司则只是“利用”代码而不作任何修改,却可能从中赚取数百万美元。然而,这些行为并未真正损害自由软件。自由软件并不是为了赚钱而存在的,因此从这个意义上说,并没有什么损失。

    真正受到损害的是整个社会。损害来自那些大型企业及其专有操作系统——它们不仅侵犯用户的自由(例如查看和修改源代码的自由、真正拥有应用程序的自由等),还侵犯了用户隐私,并限制使用权。此外,它们往往会添加恶意软件和间谍软件等。

    无论是否存在 GPL 或其他自由软件许可证,贪婪始终在那。无论使用何种软件许可证,损害都会发生,而这一问题需要在政治层面上加以解决,而非软件开发领域。

    同样值得指出的是,GPL 违规行为是个普遍存在的问题。世界各地都有把 GPL 软件当作“公共领域”对待的现象,在许多情况下,许可证几乎没能产生实际影响。这也是 项目诞生的原因。

    真正自由许可证的“灵魂”在于鼓励合作、帮助他人,从而也帮助那些由人组成、为了谋生而共同工作的公司。必须认识到,贪婪在实际上对任何人都没有好处,分享与互助要比让少数人的口袋越来越鼓更有意义。

    当然,邪恶的人总是存在,有些人永远不会改变。但事实是,仅仅使用 GPL 并不能防止任何损害,我们真正需要做的,是教育人们,让他们能够做出更好的选择。

    伪善

    众所周知, 和 为推广自由软件做了大量工作。在 FSF 网站上,我们可以看到关于“自由软件”的:

    “自由软件”尊重用户的自由,并且尊重整个社区。粗略来讲,一个软件如果是自由软件,这意味着用户可以自由地运行,拷贝,分发,学习,修改并改进该软件。因此,“自由软件”是关乎自由的问题,与价格无关。要理解这个概念,你要按照 Free Software 中的“Free”是指“自由言论(free speech)”中的自由,而非“免费午餐(free lunch)”的免费这一意项。为避免歧义,在使用英文时,我们也会借用法语或西班牙语的“Libre Software”来指自由软件,这样可以明确表示我们说的不是免费。

    我们支持软件用户的自由,因为我们坚信这是每个用户应得的。有了这些自由,软件用户,无论是个人还是集体,都可以掌控所运行的软件,并决定这些程序如何为自己服务。如果一个软件令用户失去了这种控制权,我们则称它为“非自由”的,或“专有”的程序。

    然而,GNU 项目和 FSF 同时又大力推崇并广泛使用 。根据上述定义,GPL 本身在某种意义上正是“非自由”的,因为它限制了用户对软件的使用方式。这里并不是在讨论哲学上的自由问题,也不是在讨论“真正的自由意味着没有限制”之类的抽象概念,而是指出:在实际执行层面上,GPL 违背了它最初要实现的目标。

    GPL 所设下的各种限制,从实质上讲就是“不自由”。这并非哲学意义上的“非自由”,而是实践层面的。正因为这些限制,许多采用宽松许可证的开源项目无法被整合进 Linux。

    这与一种形成鲜明对比。例如,上写道:

    我们希望提供让任何人都可以用于任何目的的源代码,不设任何限制。我们致力于让软件健壮、安全,并建议公司根据需要使用我们提供的任何内容。

    关于“Linux 偷我们代码”的那回事

    下面是一封 ( 项目的创始人)在 2007 年 8 月。当时,一群 Linux 开发者试图修改双重授权的 ath5k 驱动的许可证。

    GPL 偏离了初衷

    当人们使用 GPL 时,他们大多是为了防止某些公司拿走他们的软件、进行改进或修改,然后将其作为专有产品出售。但他们真正想要达成的是什么呢?是为了与专有软件竞争吗?还是为了阻止别人谋生?如果是这样,他们算在做“自由软件”吗?

    引用 Richard Stallman 的话:

    使用自由软件意味着做出政治和伦理选择,主张学习的权利,并将我们所学分享给他人。自由软件已成为学习型社会的基础,我们以一种他人可以在其上继续建设和享受的方式分享知识。

    目前,许多人使用的专有软件剥夺了用户这些自由和利益。如果我们复制软件并给朋友,如果我们尝试弄清楚程序如何工作,如果我们在自家多台电脑上安装同一份软件,我们可能会被罚款或监禁。这就是专有软件许可证条款中隐藏的内容。

    这是一种高度复杂且存在若干矛盾的解释。

    我认为应当做到:

    • 不使用妨碍你将其拷贝给朋友的专有软件。

    • 不使用监视你或限制你硬件使用的专有软件。

    • 教育大众使用真正的自由软件,但不要伪善——不要一边反对限制自由的许可证,一边又限制真正的软件自由。

    GPL 鼓励“劫持”和政治操纵

    GPL 的另一个问题是,当公司无法完全控制代码的共享方式时,它们要么不使用该软件,要么通过政治操纵或直接收购项目,努力“劫持”项目以满足自身利益。

    在 1990 年代初,向 Linux 上引入专有应用的压力非常大。这类应用通常需要链接系统库。压力之大,导致出现了 GPL 的一个修改版本——LGPL(“Library”,后来称为“Lesser”)。“Lesser GPL”能让专有代码链接到 。通过动态链接 LGPL 授权的库,你无需公开源代码;但如果静态链接(嵌入应用中),通常在嵌入式系统中如需这么做,那么应用必须公开源代码,不能保持专有。

    这些限制不仅损害了使用更开放许可证的项目(如 ),还会让公司处于困难境地。为了避免发布源代码,公司可能会通过雇佣上游开发者来影响项目,从而在上游实施有利于公司的修改。一旦这种政治操纵开始,往往会对自由软件社区产生负面影响。

    ,以及将其整合到主要 Linux 发行版的努力,就是政治操纵的一个典型案例。这次操纵源于红帽(IBM)的商业利益,尤其是在嵌入式设备市场。比如,他们在 systemd-resolved 网络应用中硬编码了谷歌、Cloudflare 和 Quad9 的 DNS 服务器,使其无需在 /etc 中进行任何设置即可运行。红帽当前的重点之一是逐步淘汰 /etc/passwd 等文件,以便更容易移除 /etc 其他内容,这也是 systemd-homed 的目标所在。这也解释了为什么 systemd 不再只是一个 init 系统,而成为一个庞大且相互依赖的构建模块集合,用于构建“操作系统”。红帽需要这些重大变更,使其成为主流 Linux 发行版的一体化部分,从而让第三方软件能在此环境中运行,而无需为现有环境绕过大量问题,这既耗时又困难。

    曾经,Linux 内核和发行版主要由社区驱动,但一些大公司的企业利益已经显著改变了这一格局。一些贡献确实对社区有益,但众多政治操纵对社区并无益处。目前 Linux(作为操作系统,而非仅内核)正在经历重大变革,其影响远超内核和 GNU 工具本身。

    在宽松许可证下,公司能自由行动,很少会出现“劫持”上游项目的情况。即从宽松许可证中获益的公司通常会将代码贡献回项目,因为将贡献纳入源代码对他们有利,同时可以保持“公司特定”修改的私密性。

    ,最初由苹果在 2005 年启动,采用宽松许可证发布。相比之下, 使用 GPL 第三版,要求分发 GCC 扩展或修改版本的开发者必须公开源代码,而 LLVM(Clang 的后端)采用类似 BSD 的许可证,不受此限制。因此苹果选择从零开发新的编译器前端,以支持 C、Objective-C 和 C++。Clang 项目于 2007 年开源,现在对 LLVM 和 Clang 进行改进的贡献者包括多项自由软件项目(如所有 BSD 项目)以及主要公司,如微软、谷歌、ARM、索尼、英特尔和 AMD。

    由于 GCC 源代码庞大且复杂,公司往往开发不愿共享的专有扩展,因此 GCC 正逐渐被放弃,未能从重大改进中受益;与此同时,一个真正自由的替代方案正在慢慢取代它。

    那为什么公司使用 Linux 而不是 BSD?

    首先,他们确实在使用 BSD,而且有些公司也在为 BSD 做贡献。

    其次,Linux 只是一个内核,而不同的 BSD 系统是完整的操作系统。

    1990 年,AT&T 因 BSD 相关的许可证问题起诉加州大学伯克利分校(UCB),这场诉讼后来被称为 。UCB 发现 AT&T 在其产品中未经承认或支付费用地使用了 BSD 的多项改进,由此引发了一场以 AT&T 与 UCB 为主的漫长诉讼。在此期间,一些 UCB 程序员开始重写与 BSD 相关的 AT&T 代码,这个项目最终产生了 BSD 4.4-lite 系统,并成为后续各 BSD 操作系统的基石。

    1993 年 3 月,法院驳回了 AT&T 的大部分诉讼请求,但法律纠纷仍持续,当时加州大学提出反诉。直到 1994 年初,由于 Novell 已收购 Unix 权利,这些法律纠纷才通过和解完全解决。

    这场法律风波给 BSD 操作系统的推广造成了阻碍,让人们对 BSD 的法律前景产生怀疑。因此,Linux 内核不仅获得了发展空间,还积累了庞大的用户群。

    结语

    我想大家都能认同,为了生计而开发软件、养家糊口没有错。我们不喜欢的是,当人和公司因此变得贪婪时的情况。

    1969 年,美国司法部指控 IBM 通过将自由软件捆绑在 IBM 硬件中,破坏了其他企业。结果是 IBM 将软件从硬件中分离出来,使软件成为独立于硬件的产品。1968 年,一家公司名为 Informatics 推出了首个商业软件应用,并确立了“软件产品”的概念及高额回报率。Informatics 开发了永久许可证(perpetual license),这一模式现已成为计算机行业的标准,其中软件所有权从不转移给客户。

    问题的核心——就是贪婪!

    认为你购买了某样东西却依然不拥有它,这种想法本身就违反理性。它矛盾到常人无法接受,只有在最高层级存在腐败,才可能接受这种荒谬并通过法律强制执行。这也是为什么所谓的软件盗版永远无法根除,并且有人说:

    如果购买不是拥有,那么盗版就不是偷窃!

    我们可以说,GPL 是基于人性自私且邪恶、不会主动回馈除非被迫的假设而制定的,但它并没有真正解决问题,也没有带来帮助。我们真正需要的是:一种基于人性本善、很多人会因原则和善意回馈的许可证。然后,我们要教育大众、树立好榜样、避免并抵制贪婪。我坚信,使用比 GPL 更宽松的许可证,效果会更好。

    最后补充一点,我理解 GPL 的历史背景及其制定原因,并对此深表尊重。我并不认为 GPL 是邪恶的,只是我认为它并未实现最初设定的目标,反而可能带来更多损害。我也不认为通过强制非自由可以鼓励自由与分享——这是双重标准。

    我们必须记住,公司由人组成,这些人主要是为了生计而努力,我们面对的只是人,而不是软件本身。

    我认为,我们可以把贪婪的公司放在一边,把 Richard Stallman 及极端反企业组织放在另一边。这两个极端,都无法真正带来任何实质性的好处。

    进一步阅读

    伯克利 Unix 二十年——从 AT&T 掌控到自由分发

    • 作者:Marshall Kirk McKusick

    • 注:本文属于《开源软件文集》中的一节。中国电力出版社,ISBN: 9787508301983

    早期历史

    Ken Thompson 和 Dennis Ritchie 于 1973 年 11 月在普渡大学操作系统原理研讨会上首次发表了 Unix 论文。加州大学伯克利分校的 Bob Fabry 教授出席并立即对获取系统副本以在伯克利实验产生兴趣。

    $ lsblk
    NAME                         MAJ:MIN RM   SIZE RO TYPE   MOUNTPOINT
    sr0                           11:0    1  1024M  0 rom
    sda                            8:0    0 931.5G  0 disk
    |-sda1                         8:1    0   500M  0 part   /boot
    `-sda2                         8:2    0   931G  0 part
      |-vg_local-lv_root (dm-0)  253:0    0    50G  0 lvm    /
      |-vg_local-lv_swap (dm-1)  253:1    0  17.7G  0 lvm    [SWAP]
      `-vg_local-lv_home (dm-2)  253:2    0   1.8T  0 lvm    /home
    sdc                            8:32   0 232.9G  0 disk
    `-sdc1                         8:33   0 232.9G  0 part
      `-md1                        9:1    0 232.9G  0 raid10 /data
    sdd                            8:48   0 232.9G  0 disk
    `-sdd1                         8:49   0 232.9G  0 part
      `-md1                        9:1    0 232.9G  0 raid10 /data
    # camcontrol devlist
    <Samsung SSD 860 EVO mSATA 1TB RVT41B6Q>  at scbus1 target 0 lun 0 (ada0,pass0)
    
    % geom disk list
    Geom name: ada0
    Providers:
    1. Name: ada0
       Mediasize: 1000204886016 (932G)
       Sectorsize: 512
       Mode: r1w1e2
       descr: Samsung SSD 860 EVO mSATA 1TB
       lunid: 5002538e402b4ddd
       ident: S41PNB0K303632D
       rotationrate: 0
       fwsectors: 63
       fwheads: 1
    
    # gpart show
    =>        40  1953525088  ada0  GPT  (932G)
              40      409600     1  efi  (200M)
          409640        1024     2  freebsd-boot  (512K)
          410664         984        - free -  (492K)
          411648  1953112064     3  freebsd-zfs  (931G)
      1953523712        1416        - free -  (708K)
    % lsblk.sh
    DEVICE         MAJ:MIN  SIZE TYPE                      LABEL MOUNT
    ada0             0:5b  932G GPT                           - -
      ada0p1         0:64  200M efi                    efiboot0 <UNMOUNTED>
      ada0p2         0:65  512K freebsd-boot           gptboot0 -
      <FREE>         -:-   492K -                             - -
      ada0p3         0:66  931G freebsd-zfs                zfs0 <ZFS>
      <FREE>         -:-   708K -                             - -
    # lsblk.sh
    DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
    da0              0:be  224G GPT                           - -
      da0p1          0:15a 200M efi                    efiboot0 <UNMOUNTED>
      da0p2          0:15b 512K freebsd-boot           gptboot0 -
      <FREE>         -:-   492K -                             - -
      da0p3          0:15c 2.0G freebsd-swap              swap0 <UNMOUNTED>
      da0p4          0:15d 221G freebsd-zfs                zfs0 <ZFS>
      <FREE>         -:-   580K -                             - -
    da1              0:bf  224G GPT                           - -
      da1p1          0:16a 200M efi                    efiboot1 <UNMOUNTED>
      da1p2          0:16b 512K freebsd-boot           gptboot1 -
      <FREE>         -:-   492K -                             - -
      da1p3          0:16c 2.0G freebsd-swap              swap1 <UNMOUNTED>
      da1p4          0:16d 221G freebsd-zfs                zfs1 <ZFS>
      <FREE>         -:-   580K -                             - -
    da2              0:c0   11T GPT                           - -
      da2p1          0:16e  11T freebsd-zfs                   - <ZFS>
      <FREE>         -:-   1.0G -                             - -
    da3              0:c1   11T GPT                           - -
      da3p1          0:16f  11T freebsd-zfs                   - <ZFS>
      <FREE>         -:-   1.0G -                             - -
    # fetch -o /usr/local/bin/lsblk https://raw.githubusercontent.com/vermaden/scripts/master/lsblk.sh
    # chmod +x /usr/local/bin/lsblk
    # hash -r || rehash
    # lsblk
    # lsblk.sh --help
    usage:
    
      BASIC USAGE INFORMATION
      =======================
      # lsblk.sh [DISK]
    
    example(s):
    
      LIST ALL BLOCK DEVICES IN SYSTEM
      --------------------------------
      # lsblk.sh
      DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
      ada0             0:5b  932G GPT                           - -
        ada0p1         0:64  200M efi                    efiboot0 <UNMOUNTED>
        ada0p2         0:65  512K freebsd-boot           gptboot0 -
        <FREE>         -:-   492K -                             - -
        ada0p3         0:66  931G freebsd-zfs                zfs0 <ZFS>
    
      LIST ONLY da1 BLOCK DEVICE
      --------------------------
      # lsblk.sh da1
      DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
      da1              0:80  2.0G MBR                           - -
        da1s1          0:80  2.0G freebsd                       - -
          da1s1a       0:81  1.0G freebsd-ufs                root /
          da1s1b       0:82  1.0G freebsd-swap               swap SWAP
    
    hint(s):
    
      DISPLAY ALL DISKS IN SYSTEM
      ---------------------------
      # sysctl kern.disks
      kern.disks: ada0 da0 da1
    % git commit (...)
    [master 12fd4aa] Rework entire flow. Split code into functions. Add many useful comments. In other words its 2.0 version.
     1 file changed, 494 insertions(+), 505 deletions(-)
     rewrite lsblk.sh (75%)
    % wc scripts/lsblk.sh.OLD
         491    2201   19721 scripts/lsblk.sh.OLD
    
    % wc scripts/lsblk.sh
         494    1871   15472 scripts/lsblk.sh
    % glabel status | grep ada0p1
      gpt/efiboot0     N/A  ada0p1
    msdosfs/EFISYS     N/A  ada0p1
    % mount -t fusefs
    /dev/fuse on /mnt/ntfs (fusefs)
    /dev/fuse on /mnt/exfat (fusefs)
    % mount -t nozfs
    devfs on /dev (devfs, local, multilabel)
    linprocfs on /compat/linux/proc (linprocfs, local)
    tmpfs on /compat/linux/dev/shm (tmpfs, local)
    /dev/label/ASD on /mnt/tmp (msdosfs, local)
    /dev/fuse on /mnt/ntfs (fusefs)
    /dev/md0s1f on /mnt/ufs.other (ufs, local)
    /dev/gpt/OTHER on /mnt/fat.other (msdosfs, local)
    /dev/md0s1a on /mnt/ufs (ufs, local)
    % lsblk.sh
    DEVICE         MAJ:MIN SIZE TYPE                      LABEL MOUNT
    ada0             0:56  932G GPT                           - -
      ada0p1         0:64  200M efi                gpt/efiboot0 -
      ada0p2         0:65  512K freebsd-boot       gpt/gptboot0 -
      <FREE>         -:-   492K -                             - -
      ada0p3         0:66  931G freebsd-zfs                   - <ZFS>
      <FREE>         -:-   708K -                             - -
    md0              0:28f 1.0G MBR                           - -
      md0s1          0:294 512M freebsd                       - -
        md0s1a       0:29a 100M freebsd-ufs                root /mnt/ufs
        md0s1b       0:29b  32M freebsd-swap         label/swap SWAP
        md0s1e       0:29c  64M freebsd-ufs                   - -
        md0s1f       0:29d 316M freebsd-ufs                   - /mnt/ufs.other
      md0s2          0:296 256M ntfs                          - -
      md0s3          0:297 256M fat32               msdosfs/ONE -
    md1              0:2a4 1.0G msdosfs                   LARGE 
    md2              0:298 2.0G GPT                           - -
      md2p1          0:29f 2.0G ms-basic-data         gpt/OTHER /mnt/fat.other
    % mdconfig.sh -l
    md0     vnode    1024M  /home/vermaden/FILE     
    md2     vnode    2048M  /home/vermaden/FILE.GPT 
    md1     vnode    1024M  /home/vermaden/FILER
    % wc lsblk.sh.1.0
         491    2201   19721 lsblk.sh.1.0
    
    % wc lsblk.sh.2.0
         493    1861   15415 lsblk.sh.2.0
    
    % wc lsblk.sh
         488    1820   15332 lsblk.sh
    # git commit (...)
    [master ec9985a] Add geli(8) support. Avoid code duplication and move MOUNT/LABEL detection into function. More comments. Minor fixes.
     1 file changed, 191 insertions(+), 196 deletions(-)
    # mount -t procfs proc /proc
    
    # ps ax | grep ntfs-3g
    45995  -  Is      0:00.00 ntfs-3g /dev/md1s2 /mnt/ntfs
    59607  -  Is      0:00.00 ntfs-3g /dev/md3 /mnt/ntfs.another
    83323  -  Is      0:00.00 ntfs-3g /dev/md3 /mnt/ntfs.another
    
    # pgrep ntfs-3g
    59607
    83323
    45995
    
    % pgrep ntfs-3g | while read I; do cat /proc/$I/cmdline; echo; done
    ntfs-3g/dev/md3/mnt/ntfs.another
    ntfs-3g/dev/md3/mnt/ntfs.another
    ntfs-3g/dev/md1s2/mnt/ntfs
        if [ -e /proc/0/status ]
        then
          FUSE_MOUNTS=$(
            while read PID
            do
              cat /proc/${PID}/cmdline
              echo
            done << ________EOF
              $( pgrep ntfs-3g )
    ________EOF
    )
          FUSE_MOUNTS=$( echo "${FUSE_MOUNTS}" | sort -u )
          FUSE_MOUNTS=$( echo "${FUSE_MOUNTS}" | sed 's|ntfs-3g||g' )
          FUSE_CHECKS=$( echo "${FUSE_MOUNTS}" | grep /dev/${TARGET}/ )
          if [ "${FUSE_CHECKS}" != "" ]
          then
            MOUNT=$( echo "${FUSE_CHECKS}" | sed "s|/dev/${TARGET}||g" )
          fi
        fi
      fi
    % ps -p $( pgrep ntfs-3g | tr '\n' ',' | sed '$s/.$//' ) -o command | sed 1d
    ntfs-3g /dev/md1s2 /mnt/ntfs
    ntfs-3g /dev/md3 /mnt/ntfs.another
    ntfs-3g /dev/md3 /mnt/ntfs.another
      # 尝试从进程中获取 fuse(8) 挂载点
      if [ "${MOUNT_FOUND}" != "1" ]
      then
        FUSE_PIDS=$( pgrep mount.exfat ntfs-3g | tr '\n' ',' | sed '$s/.$//' )
        FUSE_MOUNTS=$( ps -p "${FUSE_PIDS}" -o command | sed 1d | sort -u )
        MOUNT=$( echo "${FUSE_MOUNTS}" |  grep "/dev/${TARGET} " | awk '{print $3}' )
      fi
    % ls -l /dev/md4
    crw-rw----  1 root  operator  0x2af 2019.09.29 05:18 /dev/md4
    % gls -l /dev/md4
    crw-rw---- 1 root 2, 175 2019-09-29 05:18 /dev/md4
    MAJ=$( stat -f "%Hr" /dev/${DEV} )
    MIN=$( stat -f "%Lr" /dev/${DEV} )
    # gpart show md0
    =>     63  2097089  md0  MBR  (1.0G)
           63  1048576    1  freebsd  (512M)
      1048639   524288    2  ntfs  (256M)
      1572927   524225    3  fat32  (256M)
    # gpart show -p md0
    =>     63  2097089    md0  MBR  (1.0G)
           63  1048576  md0s1  freebsd  (512M)
      1048639   524288  md0s2  ntfs  (256M)
      1572927   524225  md0s3  fat32  (256M)
    # git commit (...)
    (...)
     1 file changed, 487 insertions(+), 501 deletions(-)
     rewrite lsblk.sh (69%)
    # wc lsblk.sh
         487    1791   13705 lsblk.sh
    
    # wc lsblk.sh.OLD
         544    1931   16170 lsblk.sh.OLD
    # pw groupmod operator -m yourself
    $ gpart create -s gpt da1
    da1 created
    $ gpart create -s gpt da2
    da2 created
    $ gpart add -t freebsd-zfs -a 4k -s 4g -l tt1 da1
    da1p1 added
    $ gpart add -t freebsd-zfs -a 4k -s 4g -l tt2 da2
    da2p1 added
    $
    $ gpart show da1
    =>       40  488397088  da1  GPT  (233G)
             40    8388608    1  freebsd-zfs  (4.0G)
        8388648  480008480       - free -  (229G)
    
    $ gpart show da2
    =>       40  312581728  da2  GPT  (149G)
             40    8388608    1  freebsd-zfs  (4.0G)
        8388648  304193120       - free -  (145G)
    
    $ gpart show -l da1
    =>       40  488397088  da1  GPT  (233G)
             40    8388608    1  tt1  (4.0G)
        8388648  480008480       - free -  (229G)
    
    $ gpart show -l da2
    =>       40  312581728  da2  GPT  (149G)
             40    8388608    1  tt2  (4.0G)
        8388648  304193120       - free -  (145G)
    
    $
    $ zpool create -O atime=off ztest mirror gpt/tt1 gpt/tt2
    $
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    config:
    
    	NAME	     STATE     READ WRITE CKSUM
    	ztest	     ONLINE	  0	0     0
    	  mirror-0   ONLINE	  0	0     0
    	    gpt/tt1  ONLINE	  0	0     0
    	    gpt/tt2  ONLINE	  0	0     0
    
    errors: No known data errors
    
    $ zpool list -v ztest
    NAME          SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
    ztest        3.75G  3.62G   128M        -         -    72%    96%  1.00x    ONLINE  -
      mirror-0   3.75G  3.62G   128M        -         -    72%  96.7%      -    ONLINE
        gpt/tt1      -      -      -        -         -      -      -      -    ONLINE
        gpt/tt2      -      -      -        -         -      -      -      -    ONLINE
    
    $ zfs list ztest
    NAME	USED  AVAIL	REFER  MOUNTPOINT
    ztest	420K  3.62G	  96K  /ztest
    
    $ df /ztest/
    Filesystem 512-blocks Used   Avail Capacity  Mounted on
    ztest         7601576  192 7601384     0%    /ztest
    $ dd if=/dev/zero of=/ztest/dummy bs=1m
    dd: /ztest/dummy: No space left on device
    3711+0 records in
    3710+1 records out
    3891134464 bytes transferred in 151.249101 secs (25726662 bytes/sec)
    
    $ df -h /ztest/
    Filesystem    Size    Used   Avail Capacity  Mounted on
    ztest         3.6G    3.6G      0B   100%    /ztest
    
    $ zfs list -o space ztest
    NAME   AVAIL   USED  USEDSNAP  USEDDS  USEDREFRESERV  USEDCHILD
    ztest     0B  3.63G        0B   3.62G             0B       672K
    
    $ ls -l /ztest/dummy
    -rw-r--r--  1 root  wheel  3891134464 Dec 22 17:43 /ztest/dummy
    $ zpool export ztest
    $ ls -l /boot/kernel/kernel
    -r-xr-xr-x  2 root  wheel  29343392 Nov  4 10:27 /boot/kernel/kernel
    $ dd if=/boot/kernel/kernel of=/dev/gpt/tt1 oseek=1000000
    dd: /dev/gpt/tt1: Invalid argument
    57311+1 records in
    57311+0 records out
    29343232 bytes transferred in 21.647581 secs (1355497 bytes/sec)
    $
    $ zpool import
       pool: ztest
         id: 6304409293823647838
      state: DEGRADED
    status: One or more devices are missing from the system.
     action: The pool can be imported despite missing or damaged devices.  The
            fault tolerance of the pool may be compromised if imported.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
     config:
    
            ztest        DEGRADED
              mirror-0   DEGRADED
                gpt/tt1  ONLINE
                gpt/tt2  UNAVAIL  cannot open
    $ zpool import ztest
    $ zpool status ztest
      pool: ztest
     state: DEGRADED
    status: One or more devices could not be opened.  Sufficient replicas exist for
            the pool to continue functioning in a degraded state.
    action: Attach the missing device and online it using 'zpool online'.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
    config:
    
            NAME                      STATE     READ WRITE CKSUM
            ztest                     DEGRADED     0     0     0
              mirror-0                DEGRADED     0     0     0
                gpt/tt1               ONLINE       0     0     0
                13953643250226400519  UNAVAIL      0     0     0  was /dev/gpt/tt2
    
    errors: No known data errors
    
    $ df /ztest
    Filesystem 512-blocks    Used Avail Capacity  Mounted on
    ztest         7601264 7601024   240   100%    /ztest
    $ ls /ztest
    dummy
    $ hd /ztest/dummy
    00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    hd: /ztest/dummy: Input/output error
    9e1a0000
    $
    $ zpool export ztest
    $ zpool import
       pool: ztest
         id: 6304409293823647838
      state: ONLINE
     action: The pool can be imported using its name or numeric identifier.
     config:
    
            ztest        ONLINE
              mirror-0   ONLINE
                gpt/tt1  ONLINE
                gpt/tt2  ONLINE
    $ zpool import ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0     0
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ hd /ztest/dummy
    00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    e7ee0000
    $
    $ zpool status ztest
      pool: ztest
     state: ONLINE
      scan: resilvered 432K in 00:00:01 with 0 errors on Fri Dec 23 11:14:23 2022
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0     0
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $
    $ zpool scrub ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
      scan: scrub in progress since Fri Dec 23 11:18:02 2022
            3.62G scanned at 530M/s, 378M issued at 54.0M/s, 3.62G total
            0B repaired, 10.18% done, 00:01:01 to go
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0     0
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    status: One or more devices has experienced an unrecoverable error.  An
            attempt was made to correct the error.  Applications are unaffected.
    action: Determine if the device needs to be replaced, and clear the errors
            using 'zpool clear' or replace the device with 'zpool replace'.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
      scan: scrub repaired 15.8M in 00:01:06 with 0 errors on Fri Dec 23 11:19:08 2022
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0   130
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $ zpool export ztest
    $ zpool import ztest
    $ hd /ztest/dummy
    00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    e7ee0000
    $
    $ zpool create -O atime=off ztest mirror gpt/tt1 gpt/tt2
    $ dd if=/dev/zero of=/ztest/dummy bs=1m
    dd: /ztest/dummy: No space left on device
    3711+0 records in
    3710+1 records out
    3891134464 bytes transferred in 153.170356 secs (25403966 bytes/sec)
    $ zpool export ztest
    $ dd if=/boot/kernel/kernel of=/dev/gpt/tt1 oseek=1000000
    dd: /dev/gpt/tt1: Invalid argument
    57311+1 records in
    57311+0 records out
    29343232 bytes transferred in 21.643263 secs (1355767 bytes/sec)
    $ zpool import ztest
    $ zpool scrub ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
    status: One or more devices has experienced an unrecoverable error.  An
            attempt was made to correct the error.  Applications are unaffected.
    action: Determine if the device needs to be replaced, and clear the errors
            using 'zpool clear' or replace the device with 'zpool replace'.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-9P
      scan: scrub repaired 27.9M in 00:01:06 with 0 errors on Mon Dec 26 10:55:49 2022
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0   227
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $ zpool export ztest
    $ zpool import
       pool: ztest
         id: 11275383091719095959
      state: DEGRADED
    status: One or more devices are missing from the system.
     action: The pool can be imported despite missing or damaged devices.  The
            fault tolerance of the pool may be compromised if imported.
       see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-2Q
     config:
    
            ztest        DEGRADED
              mirror-0   DEGRADED
                gpt/tt1  ONLINE
                gpt/tt2  UNAVAIL  cannot open
    $ zpool import ztest
    $ hd /ztest/dummy
    00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    *
    e7ee0000
    $ zpool export ztest
    $ zpool import ztest
    $ zpool status ztest
      pool: ztest
     state: ONLINE
      scan: scrub repaired 27.9M in 00:01:06 with 0 errors on Mon Dec 26 10:55:49 2022
    config:
    
            NAME         STATE     READ WRITE CKSUM
            ztest        ONLINE       0     0     0
              mirror-0   ONLINE       0     0     0
                gpt/tt1  ONLINE       0     0     0
                gpt/tt2  ONLINE       0     0     0
    
    errors: No known data errors
    $

    当时伯克利只有大型批处理主机,首要任务是购买一台适合运行当时 Unix 第 4 版的 PDP-11/45。伯克利的计算机科学系、数学系和统计系联合购买了该机器。1974 年 1 月,Unix 第 4 版磁带交付,研究生 Keith Standiford 完成安装。

    Ken Thompson 没有亲自参与安装,但因多次系统崩溃进行了远程调试。他通过 300 波特的声耦合调制解调器远程协助解决问题,发现多起崩溃因磁盘控制器无法正确执行重叠寻道操作。

    Thompson 的远程调试开启了伯克利与贝尔实验室的合作,贝尔实验室研究者积极分享成果,促进伯克利软件快速迭代。

    尽管 Unix 运行稳定,但计算机科学、数学和统计系在系统使用时间上存在矛盾,最终达成轮班使用协议,Unix 和 DEC 的 RSTS 系统交替运行。操作系统课程学生更喜欢在 Unix 上完成项目。

    教授 Eugene Wong 和 Michael Stonebraker 的 INGRES 数据库项目最早从批处理环境转向 Unix 交互环境。1974 年春,他们购买了运行 Unix 第 5 版的 11/40。1974 年秋首次发布 INGRES,成为计算机科学系首个对外发布软件的项目。

    即使 INGRES 离开 11/45,学生仍面临机时不足。Stonebraker 和 Fabry 教授于 1974 年 6 月开始为计算机科学系争取两台教学用 11/45,1975 年资金到位时 DEC 发布了更优的 11/70。用买两台 11/45 的钱购买了一台 11/70,1975 年秋到货。

    Ken Thompson 在 1975 年秋作为访问教授回到伯克利,和 Jeff Schriebman、Bob Kridle 一起在 11/70 上运行 Unix 第 6 版。

    1975 年秋,两位研究生 Bill Joy 和 Chuck Haley 对新系统产生兴趣,扩展了 Ken Thompson 早期开发的 Pascal 系统,因其优秀的错误恢复和快速编译执行,成为学生首选。

    Model 33 电传打字机被 ADM-3 屏幕终端替代后,Joy 和 Haley 基于从 George Coulouris 教授处获得的 em 编辑器,开发了行模式编辑器 ex。

    Ken Thompson 于 1976 年夏末离开后,Joy 和 Haley 在 Schriebman 监督下开始探索 Unix 内核,安装了贝尔实验室提供的“50 个变更”补丁,并提出多项内核性能改进建议。

    早期发行版

    与此同时,Pascal 编译器中的错误恢复工作引起了大家的关注,纷纷请求获得系统副本。1977 年初,Bill Joy 组建了“伯克利软件发行版”(Berkeley Software Distribution,简称 BSD)。首次发行包含了 Pascal 系统,以及 Pascal 源代码中一个不起眼的子目录里的编辑器 ex。在接下来的一年中,Joy 作为发行负责人,免费发送了大约三十份系统副本。

    随着带有屏幕可寻址光标的 ADM-3a 终端的到来,Joy 终于能编写出 vi,将基于屏幕的编辑带到了伯克利。他很快遇到一个难题:由于经费紧张,学校的老设备无法一次性全部替换。为了避免为多种终端编写不同的优化更新代码,他决定通过一个小型解释器来统一屏幕管理。该解释器根据终端特性描述驱动,这项工作最终发展成了 termcap。

    到了 1978 年中,软件发行显然需要更新。Pascal 系统因用户反馈变得更稳健,并分成两个阶段以便能在 PDP-11/34 上运行。更新后的版本被称为“第二版伯克利软件发行版”,简称 2BSD。除了改进的 Pascal 系统,还包含了适用于多种终端的 vi 和 termcap。同样由 Bill Joy 一人负责组装发行版、接听用户电话并将反馈融入系统。接下来一年中,寄出了近七十五份磁带。虽然 Joy 随后转向其他项目,2BSD 发行版仍持续扩展。其最终版本 2.11BSD 是一套完整系统,至今仍在世界各地数百台 PDP-11 上运行。

    VAX Unix

    1978 年初,Richard Fateman 教授开始寻找一台更大地址空间的机器,以继续他在 Macsyma 项目上的工作(最初在 PDP-10 上启动)。新发布的 VAX-11/780 满足要求且在预算内。Fateman 和其他十三位教师联合申请了 NSF 资金,并结合部门经费购买了这台 VAX。

    最初,VAX 运行 DEC 的 VMS 操作系统,但部门已习惯 Unix 环境并希望继续使用。VAX 到达后不久,Fateman 获得了 Bell Labs 的 John Reiser 和 Tom London 提供的 Unix 32/V 移植版。

    虽然 32/V 在 VAX 上提供了第 7 版 Unix 环境,但未利用 VAX 硬件的虚拟内存功能。它仍是基于交换的系统,Macsyma 团队因此受限于物理内存大小(初始为 1MB),限制了进程地址空间。

    为解决这一问题,Fateman 找到系统系教授 Domenico Ferrari,探讨让其团队为 Unix 编写虚拟内存系统的可能性。Ferrari 的学生 Ozalp Babaoglu 开始研究如何在无引用位的 VAX 上实现工作集分页系统。

    Babaoglu 接近第一个版本时,向 Bill Joy 求助了解 Unix 内核细节。Joy 被其方法吸引,加入集成代码和调试工作。

    不幸的是,伯克利只有一台 VAX 供系统开发和生产使用。圣诞节期间,用户轮流登录 32/V 和“虚拟 VAX/Unix”,系统常常突然中断,随后出现 32/V 登录提示。1979 年 1 月,大多数 Bug 被修复,32/V 被淘汰。

    Joy 预见 32 位 VAX 会取代 16 位 PDP-11,开始将 2BSD 软件移植到 VAX。Peter Kessler 和我负责移植 Pascal,Joy 移植编辑器 ex、vi、C shell 及其他 2BSD 程序。1979 年底,完整发行版成型,包含虚拟内核、标准 32/V 工具和 2BSD 增补。1979 年 12 月,Joy 发送了近百份首个伯克利 VAX 发行版 3BSD。

    贝尔实验室的最后一个发行是 32/V,此后 AT&T 的 Unix 发行(起初是 System III,后来是 System V)由另一家专注于稳定商用版本的团队管理。随着 Unix 商业化,贝尔实验室研究人员无法继续作为 Unix 研究的集散地。研究社区持续修改 Unix,迫切需要一家能发布研究版的组织。凭借早期参与 Unix 和发布相关工具的经验,伯克利迅速承担了贝尔实验室原先的角色。

    美国国防高级研究计划局(DARPA)的支持

    与此同时,美国国防高级研究计划局(DARPA)的策划部门正在进行一场讨论,这场讨论对伯克利的工作产生了重大影响。DARPA 早期的一项成功是建立了一个覆盖全国的计算机网络,将其所有主要研究中心连接起来。当时,他们发现许多研究中心的计算机即将服役期满,必须更换。更换的最大成本在于将研究软件移植到新机器上。此外,由于硬件和操作系统的多样性,许多站点无法共享软件。

    由于各研究组的计算需求差异巨大,且依赖单一硬件供应商并不理想,选择单一供应商不可行。于是,DARPA 的策划者们决定在操作系统层面统一。经过多次讨论,Unix 因其经验证的可移植性被选为标准。

    1979 年秋,Bob Fabry 针对 DARPA 采用 Unix 的意向,提出一项建议,建议伯克利为 DARPA 社区开发增强版 3BSD。Fabry 在一次 DARPA 图像处理和 VLSI 承包商会议上携带此提案,会议还有 ARPAnet 开发者 Bolt、Beranek 和 Newman 的代表参加。虽然有人对伯克利能否产出可用系统存疑,但 1979 年 12 月发布的 3BSD 几乎消除了所有疑虑。

    借助 3BSD 发布带来的良好声誉,Bob Fabry 于 1980 年 4 月获得 DARPA 一份为期 18 个月的合同,用于添加 DARPA 承包商所需功能。在此合同支持下,Fabry 成立了名为计算机系统研究小组(Computer Systems Research Group,简称 CSRG)的组织。他立即聘请 Laura Tong 负责项目管理。Fabry 开始寻找项目负责人管理软件开发。他原以为刚通过博士资格考试的 Bill Joy 会优先完成学业而拒绝此职,但 Joy 另有打算。三月初的某晚,Joy 致电 Fabry 表示有意接手 Unix 的进一步开发。Fabry 虽感意外,但很快同意了。

    项目迅速启动。Tong 建立了一款比 Joy 之前发行更能处理大量订单的分发系统。Fabry 协调 AT&T 的 Bob Guffy 与加州大学律师,正式以各方都接受的条款发布 Unix。Joy 集成了 Jim Kulp 的作业控制,增加了自动重启、1K 块文件系统以及对最新 VAX 机器 VAX-11/750 的支持。1980 年 10 月,包含 Pascal 编译器、Franz Lisp 系统和增强邮件处理系统的 4BSD 发行版问世。其九个月内发出近 150 份,授权按机构而非机器计数,约覆盖 500 台机器。

    随着伯克利 Unix 的广泛分发和知名度提升,批评者开始出现。斯坦福研究院的 David Kashtan 撰文对比了 VMS 和伯克利 Unix 在 VAX 上的基准测试,结果显示 Unix 性能存在严重问题。Joy 暂时搁置个人计划,系统性优化内核。数周内,他写出了反驳文章,证明 Kashtan 的基准测试经调优后,Unix 性能可媲美 VMS。

    Joy 没有继续发布 4BSD,而是在调优系统基础上,加入 Robert Elz 的自动配置代码,于 1981 年 6 月发布 4.1BSD。在两年时间里发出约 400 份。原本计划称为 5BSD,但 AT&T 反对,担心其商用 Unix 版本 System V 与 5BSD 名称引起混淆。为解决该问题,伯克利同意未来发行版继续使用 4BSD 编号,仅递增次版本号。

    4.2BSD

    随着 4.1BSD 的发布,关于性能的激烈争论逐渐平息。DARPA 对首个合同成果非常满意,遂向伯克利授予一份新的两年合同,资金几乎是原合同的五倍。资金中一半投入 Unix 项目,其余分配给计算机科学系的其他研究人员。合同要求对系统进行重大改进,以便 DARPA 研究社区更好地开展工作。

    基于 DARPA 社区的需求,确定了目标并开始定义系统修改内容。特别是,新系统预计包含更快的文件系统,使吞吐率达到当时磁盘技术的速度,支持多千兆字节地址空间的进程,提供灵活的进程间通信设施以便研究人员开展分布式系统研究,并集成网络支持,使运行新系统的机器能够轻松加入 ARPAnet。

    为协助定义新系统,伯克利的 DARPA 合同监督员 Duane Adams 组建了一个名为“指导委员会”的团队,指导设计工作,确保满足研究社区需求。该委员会从 1981 年 4 月到 1983 年 6 月每年召开两次会议,成员包括加州大学伯克利分校的 Bob Fabry、Bill Joy 和 Sam Leffler;Bolt, Beranek 和 Newman 的 Alan Nemeth 和 Rob Gurwitz;贝尔实验室的 Dennis Ritchie;斯坦福大学的 Keith Lantz;卡内基梅隆大学的 Rick Rashid;麻省理工学院的 Bert Halstead;信息科学研究所的 Dan Lynch;DARPA 的 Duane Adams 和 Bob Baker;以及加州大学洛杉矶分校的 Jerry Popek。自 1984 年起,该会议被扩大规模的工作坊取代,参与人数大增。

    1981 年 7 月,一份建议新系统所应包含功能的初稿发给指导委员会及伯克利外部人员,引发长时间讨论。1981 年夏,我加入了 CSRG,承担新文件系统的实现。夏季,Joy 主要实现进程间通信设施的原型。1981 年秋,Sam Leffler 作为全职成员加入 CSRG,与 Bill Joy 一同工作。

    当 Rob Gurwitz 向伯克利发布 TCP/IP 协议早期实现后,Joy 将其集成入系统并调优性能。在此过程中,Joy 和 Leffler 意识到新系统必须支持除 DARPA 标准网络协议外的更多协议。因此,他们重新设计了软件的内部结构,完善接口,使多个网络协议能同时使用。

    内部结构重组完成,TCP/IP 协议与进程间通信原型集成后,开发出几个简单应用程序为本地用户提供远程资源访问,包括 rcp、rsh、rlogin 和 rwho。这些程序原为临时工具,最终将被更合理的设施取代(因此使用“r”前缀)。该系统称为 4.1a,于 1982 年 4 月首次发布供本地使用,虽不打算广泛分发,但因各地急于等待 4.2 发布,盗版系统大量流传。

    4.1a 系统在完成前已显过时,但用户反馈提供了宝贵信息,用于制定名为《4.2BSD 系统手册》的修订提案。该文档于 1982 年 2 月发布,简洁描述了 4.2BSD 将实现的用户接口。

    与 4.1a 开发并行,我完成了新文件系统的实现,并于 1982 年 6 月将其完全集成入 4.1a 内核。新系统命名为 4.1b,仅运行于伯克利少数开发机器。Joy 认为系统将面临重大变更,且 4.1b 需对所有机器文件系统进行完整备份与恢复才能从 4.1a 转换,故避免本地分发。文件系统稳定后,Leffler 开始添加新文件系统相关系统调用,Joy 则着手修订进程间通信设施。

    1982 年春末,Joy 宣布加盟 Sun Microsystems。夏季,他在 Sun 与伯克利之间分配时间,主要完善进程间通信设施和重组 Unix 内核源代码以隔离机器相关依赖。Joy 离开后,Leffler 接手完成项目。鉴于既定期限及承诺 1983 年春向 DARPA 发布,团队评估剩余工作并设定优先级。虚拟内存增强和进程间通信设计的最复杂部分被降为低优先级(后被搁置)。随着实现时间超过一年、Unix 社区期望升高,决定发布中间版本以缓解等待压力。该版本命名为 4.1c,于 1983 年 4 月发布,许多厂商利用此版本准备将 4.2 移植到自家硬件。Pauline Schwartz 自 4.1c 起负责发行工作。

    1983 年 6 月,Bob Fabry 将 CSRG 管理权移交给 Domenico Ferrari 和 Susan Graham 教授,开始休假,摆脱此前四年高强度工作节奏。Leffler 继续完善系统,实施新的信号设施,增强网络支持,重做独立 I/O 系统简化安装流程,整合 Robert Elz 的磁盘配额功能,更新所有文档,并跟踪 4.1c 版本的缺陷。1983 年 8 月,系统作为 4.2BSD 发布。

    Leffler 完成 4.2 后前往 Lucasfilm,继任者为 Mike Karels。Karels 曾参与 2.9BSD PDP-11 软件分发,经验丰富,适合新职位。1984 年 12 月我博士毕业,随后全职加入 CSRG 与 Karels 共事。

    4.2BSD 的流行程度令人印象深刻;十八个月内发行超过 1000 份许可。4.2BSD 发行量超过之前所有伯克利软件发行总和。多数 Unix 厂商更愿意发布 4.2BSD 而非 AT&T 商业版 System V,原因是 System V 缺乏网络功能和伯克利快速文件系统。BSD 版本的 Unix 在商用领域占据主导仅数年,随后逐步回归其根源。随着网络功能和其他 4.2BSD 改进被整合进 System V,厂商们通常转回 System V。但后来 BSD 的发展依然持续被纳入 System V。

    4.3BSD

    与 4.1BSD 发布时一样,4.3BSD 也很快遭到批评。大多数抱怨是系统运行过慢。问题并不意外,主要是因为新功能尚未调优,许多内核数据结构不适合它们的新用途。Karels 和我在项目上的第一年都花在调优和完善系统上。

    经过两年的调试和改进网络代码,我们在 1985 年 6 月的 Usenix 会议上宣布预计将在当年夏天晚些时候发布 4.3BSD。然而,BBN 公司的人打断了我们的发布计划。他们指出我们从未将他们网络代码的最终版本更新到 4.2BSD 中,实际上我们还在使用多年前他们交给我们的经过大量修改的最初原型。他们向 DARPA 投诉称,伯克利负责实现接口,BBN 负责实现协议,因此伯克利应该用 BBN 实现替换 4.3BSD 中的 TCP/IP 代码。

    Mike Karels 获得了 BBN 代码并评估了自最初原型移交伯克利以来的工作。他决定最佳方案是将 BBN 代码中的好点子融入伯克利代码库,但不完全替换伯克利代码库。保留伯克利代码库的原因是它经过 4.2BSD 广泛分发,得到了大量测试和改进。作为妥协,他提出在 4.3BSD 中同时包含两套实现,允许用户在内核中选择使用哪一套。

    DARPA 审查了 Mike Karels 的决定后认为,发布两套代码库会导致不必要的互操作性问题,应仅发布一个实现。为决定使用哪套代码库,DARPA 将两者交给弹道研究实验室的 Mike Muuse,他被伯克利和 BBN 视为独立第三方。经过一个月评估,报告称伯克利代码效率更高,但 BBN 代码对拥塞处理更好。决定性的因素是伯克利代码在所有测试中表现无误,而 BBN 代码在部分压力测试下会崩溃。DARPA 最终决定 4.3BSD 保留伯克利代码库。

    精心打磨的 4.3BSD 系统最终于 1986 年 6 月发布。正如预期,它消除了许多性能上的抱怨,就像 4.1BSD 消除了对 4BSD 的抱怨一样。尽管多数厂商已开始转回 System V,但 4.3BSD 的许多部分,尤其是网络子系统,依然被纳入他们的系统。

    1986 年 10 月,Keith Bostic 加入 CSRG。他被雇佣的条件之一是允许完成之前工作的收尾,即将 4.3BSD 移植到 PDP-11。尽管 Karels 和我都认为一个在 VAX 上编译需 250 KB 的系统不可能装入 PDP-11 的 64 KB 地址空间,但同意 Bostic 继续尝试。令我们惊讶的是,他成功完成了移植,利用了 PDP-11 上复杂的覆盖技术和辅助处理器状态。最终发布了由 Casey Leedom 和 Bostic 完成的 2.11BSD 版本,该版本截至 1998 年仍在少数 PDP-11 机器上使用。

    与此同时,VAX 架构逐渐走向生命周期末期,开始考虑在其他机器上运行 BSD。一款当时颇有前景的新架构来自 Computer Consoles, Incorporated,名为 Power 6/32。不幸的是,该架构因公司战略转向而中止。然而,他们向 CSRG 提供了几台机器,使我们得以完成由 Bill Joy 启动的将 BSD 内核拆分为机器相关与无关部分的工作。该成果以 4.3BSD-Tahoe 形式于 1988 年 6 月发布。Tahoe 名称源自 Computer Consoles, Incorporated 给 Power 6/32 机器使用的开发代号。尽管 Power 6/32 的支持寿命较短,但这次内核拆分工作对 BSD 移植到众多其他架构极为宝贵。

    Networking, Release 1

    直到 4.3BSD-Tahoe 发布之前,所有 BSD 的使用者都必须先获得 AT&T 的源代码许可。这是因为伯克利从未以仅二进制形式发布 BSD 系统;发行版始终包含系统每个部分的完整源代码。Unix 系统,尤其是 BSD 系统的历史表明,向用户开放源代码具有巨大力量。用户不仅被动使用系统,还积极修复漏洞、提升性能和功能,甚至添加全新特性。

    随着 AT&T 源代码许可费用的不断增加,想要基于 BSD 代码为 PC 市场构建独立的 TCP/IP 网络产品的厂商发现按二进制收费成本过高。因此,他们请求伯克利将网络代码和工具拆分出来,并以不需 AT&T 源代码许可的授权条款提供。TCP/IP 网络代码显然不存在于 32/V 系统中,完全是由伯克利及其贡献者开发的。伯克利于 1989 年 6 月发布了 BSD 起源的网络代码及支持工具,称为 Networking Release 1,这是伯克利首次发布的自由再分发代码。

    授权条款十分宽松。被授权者可以修改或不修改代码,以源代码或二进制形式发布,无需向伯克利报告或支付版权费。唯一要求是保留源文件中的版权声明,并且在产品文档中注明产品包含加州大学及其贡献者的代码。虽然伯克利收取了 1000 美元的磁带费用,但任何人都可以自由从已获得许可的任何人那里复制代码。实际上,发布不久后,多个大型站点就通过匿名 ftp 提供下载。鉴于代码如此容易获取,CSRG 对数百个组织购买副本以支持进一步开发表示满意。

    4.3BSD-Reno

    与此同时,基础系统的开发持续进行。其接口最早在 4.2BSD 架构文档中描述的虚拟内存系统终于实现。CSRG 一贯倾向于整合现有代码,而非从头开发。因此,我们没有设计新的虚拟内存系统,而是寻找现有替代方案。首选是 Sun Microsystems 的 SunOS 中的虚拟内存系统。尽管曾讨论过 Sun 向伯克利贡献该代码,但最终未果。于是我们选用了第二方案,即整合卡内基梅隆大学开发的 MACH 操作系统的虚拟内存系统。犹他大学的 Mike Hibler 将 MACH 的核心技术与 4.2BSD 架构手册描述的用户接口(SunOS 也使用此接口)合并。

    当时系统的另一个重要新增是兼容 Sun 的网络文件系统(NFS)。同样,CSRG 避免自行编写 NFS 代码,而是采用加拿大圭尔夫大学 Rick Macklem 的实现。

    虽然 4.4BSD 的完整功能尚未准备好发布,CSRG 决定做一次中间版本发布,以获得对这两个重大新增功能的更多反馈和经验。这个有授权的中间版本称为 4.3BSD-Reno,于 1990 年初发布。此版本以内华达州赌城雷诺命名,含蓄提醒使用者此中间版本存在一定风险。

    Networking, Release 2

    在 CSRG 每周小组会议中,Keith Bostic 提出了免费再分发网络发布版的流行度问题,并询问是否有可能推出一个包含更多 BSD 代码的扩展版本。Mike Karels 和我告诉 Bostic,发布系统的大部分代码是一项庞大工程,但我们同意如果他能解决重写数百个工具和庞大 C 库的问题,我们愿意接手内核部分。私下里,Karels 和我都觉得这话题也许就此结束。

    然而,Bostic 毫不气馁,开创了基于网络的大规模协作开发模式。他号召大家根据已发布的工具描述,从零开始重写 Unix 工具。参与者唯一的报酬是他们的名字会被列在伯克利贡献者名单中,与所重写工具的名字并列。起初贡献缓慢,大多是些简单工具。但随着完成工具清单的增长,Bostic 在诸如 Usenix 等公共场合持续呼吁贡献,贡献速度加快。不久,工具清单突破一百个,18 个月内几乎所有重要工具和库都被重写完成。

    Bostic 怀着自豪感拿着清单来到 Mike Karels 和我办公室,问我们内核进展如何。我们心知任务艰巨,随后数月里,Karels、Bostic 和我逐文件审查整个发行版,剔除所有源自 32/V 版本的代码。最终发现仅剩 6 个内核文件受污染,且无法轻易重写。我们曾考虑重写这 6 个文件以发布完整系统,但最终决定先发布现有成果。发布前,我们向大学管理层高层申请许可,经过内部长时间争论及对专有代码识别方法的核实后,获得了发布许可。

    起初我们想为第二个免费再分发版本起一个全新名字,但鉴于大学律师起草和审批新许可协议会浪费资源且延迟发布,决定沿用 Networking Release 1 的许可协议,仅做修订。因此,第二个大幅扩展的免费再分发版本于 1991 年 6 月开始发行。授权条款和费用与第一次网络发布相同,数百个人和组织支付 1000 美元费用从伯克利获取发行版。

    从 Networking Release 2 到一个功能完整的系统进展迅速。发行六个月内,Bill Jolitz 编写了那 6 个缺失文件的替代品,迅速发布了基于 386 架构 PC 的完整编译和可启动系统,称为 386/BSD。Jolitz 几乎完全通过网络发布 386/BSD,他将其放在匿名 FTP 上,任何人均可免费下载,数周内获得大量追随者。

    不幸的是,Jolitz 因需全职工作,无法投入足够时间维护不断涌入的修复和改进。386/BSD 发布数月后,一群热衷用户成立了 NetBSD 组织,共同维护和改进系统。NetBSD 发行版以网络分发为主,强调支持尽可能多的平台,并延续 CSRG 的研究式开发模式。直至 1998 年,NetBSD 仍仅通过网络分发,无实体介质。该组织主要面向技术深度用户。更多信息可见 *http://www.netbsd.org*。

    FreeBSD 团队在 NetBSD 组建数月后成立,专注于 PC 架构,目标用户群较大且技术门槛较低,类似 Linux 的路线。他们开发了复杂的安装脚本,并通过低成本 CD-ROM 发行系统。安装便捷性结合在网络和 Comdex 等大型展会的广泛宣传,使其用户快速增长。目前 FreeBSD 拥有所有基于 Release 2 衍生系统中最大的装机基数。

    FreeBSD 还借助 Linux 流行热潮,添加了 Linux 模拟模式,使 Linux 二进制文件能在 FreeBSD 上运行。此功能让用户既能使用日益丰富的 Linux 应用,又能享受 FreeBSD 系统的稳定、可靠和高性能。FreeBSD 团队最近建立了 FreeBSD Mall(*http://www.freebsdmall.com*),汇聚社区的咨询服务、衍生产品、书籍和新闻通讯。

    1990 年代中期,OpenBSD 从 NetBSD 分离出来,专注提升系统安全性,市场策略则是提高易用性和广泛普及。他们开始销售 CD-ROM,借鉴了 FreeBSD 的简易安装理念。更多信息可见 http://www.openbsd.org

    诉讼案

    除了那些围绕 Networking Release 2 发行版组建的自由再分发组织外,还有一家公司,Berkeley Software Design, Incorporated(BSDI),成立以开发和发行商业支持版本的代码。(更多关于 BSDI 的信息可见 http://www.bsdi.com 和其他组织一样,他们从 Bill Jolitz 为其 386/BSD 发行版编写的六个缺失文件开始。BSDI 于 1992 年 1 月开始出售包含源码和二进制文件的系统,售价为 995 美元。他们开始投放广告,宣传其价格比 System V 源码加二进制系统低 99%。有兴趣的人被告知拨打电话 1-800-ITS-Unix。

    BSDI 开展销售活动不久后,Unix System Laboratories(USL,Unix 系统实验室;AT&T 的主要子公司,负责开发和销售 Unix)寄来一封信,要求他们停止将产品宣传为 Unix,尤其是停止使用误导性的电话号码。尽管 BSDI 立即取消了该电话号并修改广告声明该产品非 Unix,但 USL 仍不满意,并提起诉讼,要求禁止 BSDI 销售其产品。诉讼称 BSDI 产品含有 USL 的专有代码和商业机密。USL 寻求禁令,阻止 BSDI 销售,声称如果发行继续,将导致其商业机密不可弥补的损失。

    在禁令的初步听证会上,BSDI 辩称他们仅使用了加州大学免费分发的源码加上六个额外文件,愿意讨论六个文件的内容,但不认为自己应对加州大学发布的文件负责。法官支持 BSDI 的观点,告知 USL 必须仅针对这六个文件重述诉状,否则将驳回。意识到仅凭六个文件难以立案,USL 决定对 BSDI 和加州大学共同提起诉讼,并请求禁止加州大学继续发放 Networking Release 2 及禁止 BSDI 产品发售。

    距离禁令听证仅几周,双方紧锣密鼓准备。CSRG 全体成员及几乎所有 BSDI 员工均被传讯作证。律师们来回交换诉状、反诉状及回应。Keith Bostic 和我个人撰写了数百页材料,纳入各类诉状中。

    1992 年 12 月,新泽西联邦地区法官 Dickinson R. Debevoise 审理禁令请求。通常法官会立即裁决,但他决定先行评议。六周后的某个周五,他发布了 40 页意见书,驳回禁令请求,撤销除了两项投诉外的全部诉状。剩余两项投诉聚焦于近期版权和商业机密流失的可能性。他建议该案应先在州法院审理,再转至联邦法院。

    加州大学接受暗示,于次周一迅速向加州州法院提起反诉,地点的选择确立了后续州法院诉讼的管辖权。宪法法律要求所有州诉讼必须在单一州进行,防止财力雄厚的诉讼方在全美五十州重复起诉对手导致拖垮对方。结果是,如果 USL 要在州法院对大学采取行动,只能在加州,而非其新泽西本州。

    大学的诉讼称 USL 未能履行与大学签订的许可协议中关于 BSD 代码在 System V 中使用应给予适当归属的义务。若此指控成立,大学请求 USL 重新印制所有文档,加注适当归属,通知所有许可用户此疏忽,并在《华尔街日报》和《财富》等主要刊物刊登整版广告,告知商界此疏忽。

    州法院诉讼提起不久,AT&T 将 USL 出售给了 Novell。Novell CEO Ray Noorda 公开表示更愿意在市场竞争而非法庭竞争。1993 年夏季,和解谈判开始。双方立场僵硬,谈判缓慢。在 Noorda 的推动下,多数难题被克服,1994 年 1 月达成和解。结果是,从组成 Networking Release 2 的 18000 个文件中移除三份文件,并对其他文件做了若干细微修改。此外,大学同意在约 70 个文件中增加 USL 版权声明,但这些文件继续自由再分发。

    4.4BSD

    新发布的版本被命名为 4.4BSD-Lite,于 1994 年 6 月发布,其许可条款与之前的 Networking 发行版完全相同。具体来说,该条款允许源码和二进制形式的自由再分发,但必须保证加州大学版权完好无损,并且当他人使用代码时必须给予加州大学适当的署名。与此同时,完整系统作为 4.4BSD-Encumbered 同步发布,该版本仍要求接收方持有 USL 源代码许可。

    诉讼和解还规定 USL 不得对任何以 4.4BSD-Lite 为基础开发系统的组织提起诉讼。因此,当时所有发行 BSD 系统的组织——BSDI、NetBSD 和 FreeBSD——都必须以 4.4BSD-Lite 的源码为基础重新开始代码开发,并在其基础上合并自己的增强和改进。虽然这种重新整合导致各 BSD 系统开发短期内有所延迟,但这也是因祸得福,因为它强制所有分散的组织与自 Networking Release 2 发布后 CSRG 三年间的开发成果重新同步。

    4.4BSD-Lite,第二版

    来自 4.4BSD-Encumbered 和 4.4BSD-Lite 发行版的收入被用来资助一个兼职团队,负责整合漏洞修复和功能增强。该工作持续了两年,直到漏洞报告和功能增强的数量逐渐减少。最终的一批改动于 1995 年 6 月以 4.4BSD-Lite,第二版形式发布。这些改动大多数最终也被合并进其他 BSD 系统的源码库。

    4.4BSD-Lite 第二版发布后,CSRG 宣告解散。在近二十年领导 BSD 项目的历程后,我们觉得是时候让拥有新思想和无限热情的其他人接手了。虽然集中管理系统开发似乎最理想,但多个组织承担不同任务的方式确保了多种方法得以尝试。由于系统以源码形式发布,最佳方案能被其他组织轻松采纳。如果某个组织表现特别出色,最终可能成为主导的系统。

    如今,开源软件运动获得了越来越多关注和尊重。虽然 Linux 系统最为知名,但其捆绑的大约一半实用工具来自 BSD 发行版。Linux 发行版也高度依赖由自由软件基金会编写的编译器、调试器及其他开发工具。总体来看,CSRG、自由软件基金会和 Linux 内核开发者共同打造了开源软件运动的基础平台。我为能参与开源软件运动的开创感到自豪,并期待这一天的到来——开源成为用户和企业开发与购买软件的首选方式。

    真正的男子不会攻击稻草人(整个讨论串都很相关,尤其是 Theo de Raadt 对 Richard Stallman 的回应,例如 这个、这个、这个 和 这个)

  • MIT 许可证的神秘历史

  • GPL 违规案例

  • gpl-violations.org
    GNU 项目
    自由软件基金会 (FSF)
    如下定义
    GPL
    宽松许可证
    OpenBSD 官方目标页面
    Theo de Raadt
    OpenBSD
    写下的邮件
    GNU C 库(glibc)
    BSD 许可证
    systemd 背后的真实动机
    Clang
    GCC
    Unix 战争
    自由与开源软件的历史
    为什么你应该为开源项目使用 BSD 风格许可证
    自由/开源软件(FLOSS)许可证幻灯片
    按类别分类的开源许可证
    我在最近的争议中停止了公开发表声明,因为 Eben Moglen 开始在幕后努力“改进”Linux 人在许可证方面的错误,并要求我给他调停,以便他的团队可以工作。老实说,我对这种情况感到非常困扰,因为即使像 Alan Cox 这样的人也在给其他 Linux 开发人员提出违法建议。而且,不同社区之间的互动可能存在更大的潜在风险。
    
    记录一下,我是正确的,Linux 开发人员不能以任何那些 diff 中提出的方式修改许可证,或者在那次对话中(<http://lkml.org/lkml/2007/8/28/157>)。
    
    修改许可证是非法的,除非你是所有者或作者,因为它是一份法律文件。如果有多个所有者或作者,他们必须全都同意。收到双重许可证的人可以以任何一种方式使用该文件……但是,如果他们分发该文件(修改或未修改!),他们必须将其与现有许可证一起分发,因为我们所有人使用的许可证中都有声明,称许可证不得删除。
    
    可能看起来许可证允许以任何一种许可证来“分发”它,但这种对许可证的解释是错误的——依然非法地拆分、切割或修改他人的法律文件,且不能被另一个许可证替换,因为它不能被删除。因此,双重许可证的文件在每次分发时始终保持双重许可证。
    
    现在,我已经够善意,给了 Eben 和他的团队几天时间在 Linux 社区内部进行沟通,以说服他们所提出和讨论的东西在法律层面上是错误的。我认为 Eben 也同意我的看法,在伦理和社区层面上,这引起了严重的担忧(某种程度上,Linux 开发人员需要有一种共同的伦理与 *BSD 开发人员合作)。而且撰写应用程序的更大开源社区也可能面临类似问题。
    
    到目前为止,Eben 还选择不发表公开声明,但由于时间正在消磨人们的记忆,我现在发表一个(声明)。而且,我觉得很多 Linux 的“重新许可”舆论攻击我非常不公平,所以我不会等 Eben 公开发表关于这个问题的声明。
    
    在 <http://lkml.org/lkml/2007/8/29/183> 中,Alan Cox 成功地总结了 Jiri Slaby 和 Luis Rodriguez 试图通过修改未经所有作者同意的双许可证文件所提出的内容。Alan 问:“所以问题是什么?”嗯,Alan,我必须警告你——你的帖子正在建议人们违法。
    
    我将尝试简单地描述,基于我所学到的知识,如何处理这样的许可证:
    
    - 如果你收到双许可证的代码,你不能删除你不喜欢的许可证然后再分发它。它必须保留,因为你不能编辑他人的许可证——这是一份由三部分组成的法律文件(例如:版权声明、BSD 许可证,后跟 GPL)。
    - 如果你收到 ISC 或 BSD 许可证的代码,你不能删除许可证。原理相同,因为声明是如此。这是法律。真的。
    - 如果你向代码添加了“大量的原创内容”,这些内容本身在版权保护范围内,你可以选择在现有许可证上方放置一个不同且独立(必须不冲突……)的许可证。
      (警告:随着许可证组合意义的变得不那么明确——这也涉及道德陷阱)。
    - 如果你希望每个人保持友好,你应该还代码。
    
    这意味着(在某种伦理或友好的层面上),你可能不想在 BSD 或 ISC 文件的顶部放置 GPL,因为这将告诉编写 BSD 或 ISC 文件的人:
    
    “感谢你写的东西,但这是单行道,你给我们代码,我们拿走,我们不给你任何东西。滚开。”
    
    无论哪种情况,我认为在 BSD 世界中我们得到了一堂有价值的课——有很多很多喜欢 GPL 的人会尝试找到任何办法来不给予回馈和分享(我将提及一个名字:Luis Rodriguez 一直狂热地推动我们使用双许可证,我觉得他应该对这个特定问题负责)。许多同样的人多年来一直在说 BSD 代码可以被窃取,这就是为什么人们应该将代码 GPL 化。
    
    好吧,他们真正教给我们的教训是,他们认为 GPL 是他们从我们这里拿走东西的最好工具!
    
    GPL 的拥护者说,我们将面临的巨大问题是公司将拿走我们的 BSD 代码,对其进行修改,然后不给予回馈。不,我们面临
    
    的真正问题是,人们将 GPL 包装在我们的代码周围,并以与这些所谓的公司相同的方式锁定我们。就像 Linux 社区一样,我们有许多公司一直在不断地给我们回馈代码。但是一旦代码被 GPL 化,我们就无法将其拿回。
    
    这具有讽刺意味。
    
    我希望 GPL 社区中的一些人能好好考虑一下。你的许可证可能对你有利,但你可能会失去所需的朋友。GPL 用户有机会“发展社区”,保持共享伦理活跃。
    
    如果 Linux 开发人员在我们辛勤工作的代码周围加上 GPL,那肯定不会被视为社区发展。
    
    感谢你考虑这个问题。
    
    [我请求确保有个副本发到 Linux 内核邮件列表上]

    在 FreeBSD 上部署 Syncthing

    • Syncthing on FreeBSD

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2018/08

    本文将向你说明怎样在 FreeBSD 系统上配置 Syncthing。

    syncthing-logo.png

    警告

    请记住,Syncthing 配置文件实际上是 XML 文件。

    就我个人的大部分备份需求,我一般使用 rsync(1),但在像手机或平板这样的有限设备上 rsync 实在很麻烦。因此,对于从这些设备自动导入照片和其他文件,我更倾向于使用 Syncthing 工具。

    如果你还没听说过,我引用 Syncthing 官网 的话:“Syncthing 替代了专有的同步和云服务,提供开源、可靠和去中心化的方案。你的数据完全属于你自己,你有权选择数据存储位置、是否与第三方共享以及在互联网上的传输方式。” ……以及 的描述:“Syncthing 是一款免费、开源的点对点文件同步应用,适用于 Windows、Mac、Linux、Android、Solaris、Darwin 和 BSD。它可以在局域网设备间同步文件,或通过互联网在远程设备间同步。数据安全和数据保护是软件设计的一部分。”

    有人可能会问,它与 Nextcloud 有何不同。其实,Nextcloud 提供了几乎完整的云服务堆栈以及定制应用,而 Syncthing 仅是设备间的同步工具,仅此而已。

    最初,我像设置 一样,打算在 FreeBSD Jail 中完成全部设置。问题是,我尝试了几个小时后发现 Syncthing 无法在 FreeBSD Jail 虚拟环境中正常工作。管理界面可以访问并正常工作,但 Android 手机上的 Syncthing 无法与 FreeBSD Jail 中的 Syncthing 实例连接和同步。当然,我可以从手机连接到 Syncthing 管理界面,但仍无法使用 Syncthing 协议进行任何备份。了解了这个不足后,你有三种选择:

    • 在 FreeBSD 主机上像其他服务一样设置 Syncthing。

    • 使用 FreeBSD Bhyve 虚拟化运行 Syncthing 实例。

    • 使用 VirtualBox 软件包/Port 运行 Syncthing 实例。

    我选择了第一种方案。Bhyve 和 VirtualBox 实际上也是类似,但需要额外处理虚拟化层。我将以基于 Android 的手机作为 Syncthing 客户端示例,但你也可以在计算机之间同步数据。

    还有一点,Syncthing 没有服务器端和客户端的区分。所有 Syncthing 实例/安装都是一样的,你只需添加或移除设备及目录来进行同步。我上文中使用“客户端”一词,只是为了说明我将自动化从手机向 FreeBSD 服务器上运行的 Syncthing 实例复制文件,仅此而已。

    主机

    以下是在 FreeBSD 主机上我所做的一些基本步骤,包括别名数据库、时区、DNS 以及 FreeBSD 基本设置,这些都在其 /etc/rc.conf 关键文件中配置。

    ……以及主要的 FreeBSD 配置文件。

    安装

    首先,为了获取最新的软件包,我们将从 pkg(8) 分支 quarterly 分支切换到 latest。

    现在我们将引导安装 pkg(8),然后将其数据库更新到最新可用版本。

    ……然后从 pkg(8) 软件包中安装 Syncthing。

    Syncthing 软件包为我们创建了用户和用户组 syncthing。

    看看 Syncthing 的体积有多小,这些都是软件包 net/syncthing 安装的所有文件。

    配置

    如上所示,我们已经在 /etc/rc.conf 文件中添加了 syncthing_enable=YES。

    此外,你还可以从 Syncthing 的 rc(8) 启动脚本中查看其他启动选项。

    Syncthing 需要日志文件 /var/log/syncthing.log。让我们创建该文件,并为其设置正确的所有者和权限。

    由于我们将使用该日志文件,还需要管理日志轮转,我们将使用 FreeBSD 内置的守护进程 newsyslog(8) 来实现。

    让我们尝试初次启动 Syncthing。

    看来 rc(8) 启动 Syncthing 并不会自动创建 PID 文件,那么我们现在手动创建它。

    现在让我们再次尝试启动 Syncthing。

    好多了。让我们看看它使用了哪些端口。

    ……并查看它的日志文件。

    这里有几条关于默认 /Sync 目录的 WARNING 警告信息。让我们来修复它们。

    在第一次启动 Syncthing 时,rc(8) 启动脚本创建了目录及其配置文件 /usr/local/etc/syncthing。

    现在让我们回过头来修复 /Sync 目录的 WARNING 警告。

    现在让我们为 Syncthing 实例创建专用目录,并在 /usr/local/etc/syncthing/config.xml 配置文件中进行设置。

    我们还将禁用 Relay 和 Global Announce Server,但保持启用 Local Announce Server。

    在重启 Syncthing 之前,让我们清空 /var/log/syncthing.log 文件,以清除不再需要的信息。

    让我们看看现在日志中记录了哪些内容。

    我们可以看到管理界面监听的是 HTTP 而非 HTTPS,因为 tls 选项被设置为 false。我们还需要将管理界面的地址从本地主机 (127.0.0.1) 切换到我们的 IP 地址 (10.0.0.100)。

    现在让我们验证所做的更改。

    日志现在已经“干净”了,我们可以继续在浏览器中访问 管理界面,进行 Syncthing 的剩余配置。浏览器当然会提示我们 HTTPS 证书不受信任。

    Syncthing 会询问我们是否同意共享统计数据。你可自行选择。

    Syncthing 仪表盘会显示一个大红色警告,提示远程管理允许在没有密码的情况下访问。我们稍后会修复它,点击警告中的 Settings 按钮。

    保持第一个 General 标签页不修改。

    在 GUI 标签页中,我们为 Syncthing 管理界面创建用户 admin,密码为 SYNCTHINGPASSWORD。这里可以使用更合理的密码 🙂。

    我没有修改 Connections 标签页中的设置。点击 Save 继续。

    除了设置用户及其密码,我没有更改或设置其他选项。

    现在 Syncthing 已无错误。系统会提示你输入刚设置的用户和密码。接着我们将删除 Default Folder,因为不需要它。点击其 Edit 按钮。

    然后点击底部的 Remove 按钮。

    ……并点击 Yes 确认。

    “空白”的 Syncthing 仪表盘。

    接下来,我们将在 Android 手机上下载、安装并配置 Syncthing。根据你的喜好,可使用 F-Droid 仓库、Google Play 仓库,或直接从任意来源 APK 文件安装。安装后的 Syncthing 应用如下图,约 50 MB。

    启动应用,你会看到 Syncthing 的 Welcome 欢迎界面。

    根据 Android 版本,手机可能会要求你授权 Syncthing 各种权限,选择同意。

    与之前一样,Syncthing 会询问你是否同意共享统计数据。我同样留给你选择。

    Syncthing 现在需要重启,点击 RESTART NOW 继续。

    默认情况下,Camera 目录已预配置为 /storage/emulated/0/DCIM,用于存放手机拍摄的照片和截图。我将使用它。点击 Syncthing 按钮。

    选择 Web GUI 选项。

    你将看到 Android 手机上 Syncthing 的管理界面,向下滚动,在 Remote Devices 区域添加 FreeBSD 上的 blackbox.local Syncthing 实例。

    在 Remote Devices 区域点击 Add Remote Device 按钮。

    记住之前我们启用的 Local Announce 服务吗?此时它派上用场。FreeBSD 上的 Syncthing 实例 ID 会自动在网络中显示。

    点击显示的 ID,并输入 blackbox.local 主机名。

    除了输入(点击)ID 和主机名,我没有设置其他选项。点击 Save。

    blackbox.local 现在已添加到 Remote Devices 列表中。

    以下是 Camera 目录属性。记得选择 blackbox.local 作为允许的主机(小黄滑块)。

    ……以及 blackbox.local 设备属性。

    现在返回 FreeBSD 上的 Syncthing 管理界面,你会被提示将 Android 手机上的 Syncthing(在我这里是 SM-A320FL)添加到设备列表。点击绿色 Add Device 按钮。

    无需添加其他选项,直接点击 Save。

    Android 手机 SM-A320FL 设备现在在 Remote Devices 区域可见。

    系统会提示 SM-A320FL 设备想要共享 Camera 目录,点击绿色 Add 按钮。

    输入 SM-A320FL 作为文件夹标签,/syncthing/SM-A320FL 作为 FreeBSD Syncthing 实例上的目录名。确保在底部 Share With Devices 区域选择了 SM-A320FL。

    现在 SM-A320FL 设备及其 SM-A320FL 文件夹已配置完成。你将首先看到 Out of Sync 状态。同步将开始,其进度可在手机和 FreeBSD Syncthing 管理界面中观察。

    SM-A320FL 文件夹状态切换为 Syncing,显示同步进度。

    在 Android 手机上也会看到类似状态。

    一段时间后,SM-A320FL 文件夹状态显示 Up to Date,表示 Camera 目录中的所有文件已同步到 FreeBSD Syncthing 实例。

    在 FreeBSD Syncthing 实例上,来自 Android 手机的已创建/同步目录如下所示。

    现在,你的 Camera 文件已经同步完成,可作为备份使用。

    FreeBSD 实例上的完整 Syncthing 配置文件可在此获取:。下载后,将文件从 .xml.key 重命名为**.xml**(WordPress 限制所致)。

    更新 1

    文章曾在 节目中提及。

    感谢分享!

    FrankenPad T25 上的 FreeBSD 14.3

    • FreeBSD 14.3 on FrankenPad T25

    • 发布时间:2025/06/26

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    在我看过的许多电影中,我也很喜欢 No Country for Old Men(老无所依)(2007)——它与我对电脑/笔记本的偏好以及当时市场上可获得的设备产生了共鸣……以及现在可用的设备。我甚至还分享过我颇为消极的 笔记本悼文。不久前,我还在使用 ThinkPad W520,那是 2011 年的笔记本——已有 14 年历史——但它运行 FreeBSD 完全没问题……不过当我因工作离开家时,一个新的机会出现了。

    联想当时只生产了大约 5000 台 ThinkPad (T25) 25 周年纪念版 笔记本——所有机器配置相同——搭载了一颗“性能较弱”的 Intel 双核 CPU。我至今仍然遗憾,当时在我所在的波兰中部城市的本地商店里,一台全新的售价约 $1100,我没能买到,但过去无法改变。

    总体来说,ThinkPad T25 本质上是 ThinkPad T470,只是更换了若干部件——比如掌托和键盘。

    在随意查看 EBAY 上 ThinkPad T25 的购买方案时,我找到了 FrankenPad T25 ——价格大约 $1200,再加上税费和运送到波兰的费用。我购买了它,并顺利收到了,没有任何意外。经过一番测试后,它运行良好——一切正常——只是我花了大约半年时间才真正从 ThinkPad W520 迁移过去。

    对于不了解 FrankenPad 的人,我来解释一下——它是由各种 ThinkPad 型号混合改装而成的——有时需要 3D 打印部件,有时需要修改 BIOS,有时甚至需要焊接等。过去,你可以自己制作,也可以订购——例如这里:。

    FrankenPad 最重要的部分当然是经典的 7 排键盘——其余的都只是附加组件。

    白色虚线显示了尺寸差异。

    独一无二

    每次听到或看到 The One and Only(唯一) 这个词,我脑海中都会浮现 反恐精英 1.x 的 玩家——看起来 HeatoN(本名 Emil Christensen)最近被收入了 反恐精英 的 ——值得称赞!……我真的很喜欢二十年前我们玩的那些 反恐精英 1.x 局域网派对……可惜那些都已经结束了,每个人都太忙,再也无法像以前那样聚会……不过,当我的一个朋友创建了一个名为 CS:GO 的 WhatsApp 群组,在线聚会玩游戏时,多少恢复了一点乐趣……我们见面过一次,半年过去了。

    回到 FrankenPad——世界上可能至少有几台这样的机器——我的具有以下特征:

    – 它本质上是搭载四核 Intel CPU 和 32 GB 内存的 ThinkPad T480 笔记本。 – 它拥有 ThinkPad (T25) 25 周年纪念版 的掌托/触控板和经典键盘。 – 它还配备了来自 ThinkPad T490 的低功耗 FullHD(1920×1080)屏幕。

    因此可以说,我的 FrankenPad T25 是 ThinkPad T480/T25/T490 的混合体。

    从缺点来看——它仍然搭载 Nvidia MX150,我已在 BIOS 中将其关闭。

    你可以看到屏幕边框上仍有 T480 标识,而掌托和键盘来自 T25 型号。

    …… 至于最不重要的消息——上面的截图展示了我大部分文章的写作方式 🙂。

    我非常喜欢浏览器 Epiphany 的功能——每次保存文件时它都会刷新页面,所以我可以像有“实时”预览一样工作。

    另外——上盖仍然来自 ThinkPad T480(黑白色),而掌托来自 ThinkPad T25(彩色)。

    ThinkPad W520 的遗产

    迁移后会怀念它吗?有些东西会。比如 ThinkPad W520 左侧有三个 USB-A 接口,而 FrankenPad T25 右侧只有两个 USB-A 接口(我需要使用 90 度角 USB 转接头和延长线,以免干扰鼠标板)。

    FrankenPad T25 左侧还有两个 USB-C 接口……但一个被电源适配器占用,另一个在 FreeBSD 下无法直接使用,除非我接上一个廉价的 USB 集线器 🙂。

    我在这里买了一个小型 USB 集线器 – – 在 AliExpress 上。

    键盘方面——ThinkPad T25 的键盘略微柔软/细腻——打字手感更柔和——很好用——并不是说我不喜欢 ThinkPad W520 的键盘,只是我更喜欢 ThinkPad T25。

    其他优点是——我终于可以使用任何 65W Type-C 线来为它充电——包括我的 ZMI QB826G 210W 25000mAh 移动电源 – ——在这里有介绍。

    硬件

    我拿到它后做的第一件事之一就是看看内部硬件。

    内部大致就是普通 ThinkPad T480 的配置。

    ……但在拆卸底盖时,我把背部的一些塑料部件弄坏了。

    这是剩下的零件。这种情况在我过去拆装 ThinkPad W520 / X220 / T520 / T420s 时从未发生过。

    我还订购了一条 SATA 数据线——大约 $3——为了能够连接我的 Samsung 870 QVO 8TB SATA 2.5 SSD……

    但后来我以便宜的价格买到了 Corsair MP600 PRO LPX 8TB M.2 NVMe SSD,所以最终选择了 NVMe 固态硬盘。

    WiFi

    我最初在 FrankenPad T25 上安装的是 FreeBSD 14.2-RELEASE ——但 WiFi 完全无法使用。

    它原装安装的是 Intel AX210 网卡。

    感谢 Michal Sapka 在他的文章 中提供的解决方案,我购买了 Intel AC 9260 网卡,并将其安装到我的 FrankenPad 笔记本中。

    上图显示了安装好的 Intel AC 9260 WiFi 网卡。

    现在 —— 无论是 FreeBSD 14.2-RELEASE 还是 FreeBSD 14.3-RELEASE 都能顺利连接 WiFi 网络。

    指点杆

    有些人喜欢 ThinkPad 笔记本,因为它们配备 指点杆,但我不是其中之一——至少可以说它非常慢且不够精准。

    不过我对此并不反感——虽然它对我不适用,但我相信有很多人依赖它——所以就留给他们吧。

    FreeBSD 系统配置

    我非常喜欢 FreeBSD UNIX 的一点是(更多内容见 – ),它几乎可以仅通过三个文件完成完整配置。这套配置已经包含了我在 文章中描述的所有电源管理设置。

    像往常一样,我以比较标准的方式安装了 FreeBSD,启用了 GELI 加密,并使用 ZFS 作为文件系统。如果有疑问,安装过程可参考文章 。

    主要的 FreeBSD 配置文件如下:

    • /etc/rc.conf – 系统服务配置

    • /etc/sysctl.conf – 运行时参数

    • /boot/loader.conf – 启动可配置参数

    我还会包括以下文件,因为它们对配置也至关重要:

    • /etc/devfs.rules – 设备配置

    • /etc/fstab – 文件系统配置

    • /etc/ttys – 终端初始化配置

    • /etc/wpa_supplicant.conf – WiFi 配置

    首先是主要的 /etc/rc.conf 配置文件。

    接下来是运行时参数文件 /etc/sysctl.conf 。

    接下来是启动参数 /boot/loader.conf 文件。

    如上所示——我已禁用了 hwpstate_intel(4) 驱动,因为在保持系统响应性的同时,我无法找到性能、功耗与电池续航的最佳平衡。

    现在来看前面提到的 /etc/devfs.rules 文件。

    文件系统及 SWAP 配置。

    终端配置位于 /etc/ttys 文件中。重要部分是 ttyv4 条目,它需要与 /etc/rc.conf 文件中的 xdm_tty=ttyv4 值相对应。

    无线网络配置——作为不同网络类型的示例。如你所见,我没有在 /etc/rc.conf 文件中包含任何网络信息——这是因为我使用自己的 network.sh 方案来连接各种有线和无线网络——详细描述见 。

    automount(8) 配置。

    doas(1) 配置文件。

    我所属的用户组。

    我也不依赖“默认”的风扇转速,而是根据 CPU 温度使用 脚本自行设置风扇速度。

    性能差异

    为了测试 FrankenPad T25 的性能提升,我使用 unixbench(1) 测量 CPU 相关任务,并使用 blogbench(1) 测试磁盘读写性能。

    图例说明如下:

    • ub1 – unixbench(1) 单线程(1 CPU 线程)得分

    • ub8 – unixbench(1) 多线程(8 CPU 线程)得分

    • bbR – blogbench(1) 读取性能

    • bbW – blogbench(1)

    测试结果:

    ub1
    ub8
    bbR
    bbW

    如你所见,基于 T480 的 FrankenPad T25 在计算和 I/O 相关任务上大约比 ThinkPad W520 快 2.0 倍……老实说,这在日常工作中是明显感觉得到的。

    电池续航

    虽然 FrankenPad T25(或为了清晰起见称为改装的 T480)配备了两块电池,但它们都能支持约 3 到 4 小时的工作——如下所示,使用我创建的 FreeBSD 电池相关脚本测试。

    使用的脚本:

    测试结果如下。

    就像最初从 Chernobyl 核反应堆测得的每小时 3.6 兰氏剂量一样——不算好,也不算糟。

    桌面环境

    Openbox

    至于我使用的“桌面环境”,是我自定义的 Openbox 设置,配合 Tint2 和 Dzen2 等工具——用于最基础的环境。下图截图来自 FreeBSD 11.1,但今天看起来完全一样。

    我在整个 系列文章中详细描述了该设置。

    XFCE

    我也尝试过 XFCE——我特别喜欢配合 Global Menu appmenu 插件的使用方式。你可以参考这篇 的实用指南。

    配件

    对于 ThinkPad W520 笔记本,有一些非常实用的配件。我将在下文中说明它们。

    更小的电源适配器

    ThinkPad W520 需要大块电源砖——官方 ThinkPad 170W 电源 或 ThinkPad 135W 电源(最初随 ThinkPad W510 销售)。而对于 ThinkPad T480 或我的 FrankenPad T25,使用文章 中 Small Powerful USB-C Chargers 部分所述的 140W 电源更加方便。

    鼠标搭档

    在参考了多款鼠标(详见文章 )后,我最终选择了 罗技 Triathlon M720 鼠标。我将 联想 USB 接收器 插入侧边 USB 接口。使用 USB 接收器时可以使用该鼠标,你也可以通过蓝牙连接到其他电脑。这款鼠标有一个专用按钮,可在三台不同电脑间切换。可惜它们之间的复制粘贴功能无法使用 🙂。

    总结

    在使用 ThinkPad W520 这么长时间后,没有任何设备是完美的——但 FrankenPad T25 是我能迁移到的最“无痛”选择——老实说,使用几个月后,我终于再次有了家的感觉。唯一让我担心的事情是——如果 F25 出了问题怎么办?

    在大部分时间使用 ThinkPad W520 时,我都有备用设备……而这次我没有任何“备份”。

    为了对潜在问题保持一定准备,我仍然保留了 ThinkPad T14 GEN1,并且还将 ThinkPad T520 添加到我的“设备库”中……不过不是普通型号——而是搭载 4C/8T CPU 的型号。在我考虑 ThinkPad W520 最重要的部分时,发现是 4C/8T CPU 和 1920×1080 FullHD 屏幕……当然还有传奇的 7 排 ThinkPad 键盘——因此我又入手了一台 ThinkPad T520 作为备用笔记本,带 4C/8T CPU,价格约 $70——至少在波兰当时能买到。

    我计划在下个月左右出售我这两台 ThinkPad W520……虽然充满了许多回忆……

    如何在 FreeBSD 中指定 CPU 类型

    • FreeBSD での CPUTYPE の 指定方法

    • 作者:重村法克

    • 发布于 2021 年 03 月 11 日,最后更新于 2021 年 03 月 18 日

    引言

    在研究如何指定 CPUTYPE 的方法时 [1],我突然想起自己从没看过相关的日文文档……于是下定决心,打算留下这份研究笔记。

    这个指定方式基本上是不断追加的,因此我打算针对每个操作系统版本,调查 bsd.cpu.mk [1] 的差异。为了便于参考,这里也列出我已经研究过的版本。另外,区分大小写。

    如果你正在使用最新的 CPU,而表中没有列出该型号,请指定最接近的一代 CPUTYPE。因为大多数 CPU 都继承了旧架构的功能 [2],所以应该不会生成报错信息。

    那么,CPUTYPE 是什么呢?它是在 /etc/make.conf 中使用的变量,用于指定你当前所使用的 CPU,这样在编译时就可以生成针对该 CPU 优化的代码。对于使用软件包系统管理的人来说,这个设置基本没有关系 [3]。

    注意事项

    • 这里列出的内容,并不保证可以针对旧的 CPU 架构进行编译。

    • 特别是在编译器从 GCC 4 迁移到 LLVM 的过程中,可能出现原本还能用的 CPUTYPE 无法使用的情况。

    • 本文从 10.0-RELEASE 开始进行调查,更旧的版本将不予调查。

    • 其他架构方面怎么办呢……因为存在各种复杂关系和前后顺序问题 [4],所以不太容易说明。

    CPUTYPE(amd64 环境及 i386 环境)

    ※已调查版本:13.0、12.2、12.1、12.0、11.4、11.3、11.2、11.1、11.0、10.4、10.3、10.2、10.1、10.0

    • 尽量将较新的项目排在前面

    • 想要区分 amd64/i386 通用的 CPU 与仅支持 i386 的 CPU

    • 像“Opteron 支持 SSE3 的时候是哪代?”、“Blue Lightning 啊 Cyrix 啊 NexGen 啊,这些满满的回忆都去哪了!”……等等。

    导入版本
    CPUTYPE(别名)
    CPU 代号(架构名称)
    备注
    1. /usr/share/mk/bsd.cpu.mk

    2. 有些架构会偶尔回归到原点。

    3. 因为它们会根据包构建系统中指定的 CPUTYPE 进行编译。

    4. 向上兼容和向下兼容的关系。

    FreeBSD 13.4: 新特性及其发展历程

    • 原文地址:FreeBSD 13.4: What’s new, and how did we get here?

    • 作者:FreeBSD 基金会

    • 原文发布时间:2024 年 10 月 4 日

    简介

    长期以来,要寻求现代企业级开源操作系统,FreeBSD 始终是首选。FreeBSD 宽松的许可证、卓越的安全性、出色的性能和坚如磐石的稳定性使其成为各类企业和组织的不二选择。

    在基础设施、硬件兼容性和安全性方面有了重大改进,进一步证明了 FreeBSD 在业内的价值。此版本在 13.x 系列先前版本的坚实基础上进行了扩展,并与 2023 年 11 月推出的 的开发时间表相一致。

    FreeBSD 13.x 概览

    创新的基础

    FreeBSD 13.0-RELEASE 有重大改进,设定了新的系统稳健性和性能标准。包括工具链的战略性调整,全面过渡到 LLVM/Clang,使其作为默认编译器,这简化了开发过程并增强了系统稳定性。此外,作为一种现代 VPN 协议,WireGuard 显著增强了 FreeBSD 的网络安全,为 IPSec 和 OpenVPN 提供了一种更简单、快速的替代方案。

    随着 13.x 系列的推进,每个版本都在用户空间和内核中引入了重要的增强功能,解决了重大的安全漏洞,并确保系统在面对不断演变的威胁时依然岿然如山。13.x 系列扩展了硬件支持和网络功能,进一步巩固了 FreeBSD 项目对适应性和前瞻性的承诺,满足了从服务器管理员到桌面用户的普遍需求。

    FreeBSD 13.x 中的主要增强功能

    网络改进

    普通网络改进

    • mbuf 类型增强: 引入了一种新类型的 mbuf,能够将多个未映射的物理页面作为一个缓冲区来表示。这一增强由 Netflix 赞助,提升了 sendfile 操作的性能,突显了 FreeBSD 对网络性能的重视。

    • 安全内存回收(SMR): 将 SMR 集成到内核中,改进了多线程环境中的内存管理,优化了系统整体性能。

    增强传输层安全(TLS)

    • 基于内核的 TLS: 实现了基于内核的 TLS 数据帧和加密功能,支持 TCP 套接字上的 TLS 1.0 到 1.3 版本。包括通过内核加密驱动程序进行 AES-CBC 和 AES-GCM 密码套件的发送卸载,以及 TLS 1.2 中的 AES-GCM 接收卸载。这些增强功能由 Netflix 和 Chelsio Communications 赞助,进一步强化了 FreeBSD 在安全和高效数据传输方面的承诺。

    比例速率降低(PRR)

    • TCP 改进: 在 TCP 中启用了 PRR 功能,以增强在突发丢包和 ACK 削减场景下的丢包恢复性能。此功能改进了丢包恢复表现,并防止了超时重传(RTO)阻塞,提供了更强大的网络体验。

    路由栈重构

    • 重写的路由栈: 引入了一种基于“下一个跳点”(nexthop)的新路由栈,持有所有必要的状态信息,能高效地将数据包路由到目的地。这使得路由操作更加高效和可扩展。

    • 增强的多路径路由支持: 重新设计的多路径路由支持,支持 64 宽的多路径路由和 O(1) 查找时间,在多路径路由场景中显著提高了可扩展性和性能。

    • 自定义路由查找算法: 支持自定义路由查找算法,将控制平面和数据平面操作解耦,从而在负载下实现更快速的查找和更好的收敛时间。

    服务质量(QoS)与拥塞控制

    • QoS 增强: 现在,工具 ping 能使用 IP DSCP 和以太网 PCP 设置网络服务质量(QoS),方便进行更精细的流量管理和优先级排序。 (在 FreeBSD 13.3 中引入)

    • 拥塞控制算法改进: cc_cubic TCP 拥塞控制算法已更新,与 RFC 8312 中的标准更加一致,优化了 TCP 拥塞控制行为。 (在 FreeBSD 13.3 中引入)

    流控制传输协议(SCTP)与高级网络功能

    • SCTP 作为可加载内核模块: SCTP 支持已迁移到新的内核模块 sctp.ko,使其变为可选功能,不再默认编译进 GENERIC 内核,从而提供了更灵活的部署场景。

    • 堆叠 VLAN(802.1ad)支持: 引入对堆叠 VLAN 的支持,增强了在复杂网络环境中 VLAN 配置的灵活性和可扩展性。

    • 高级网络功能: 对 TCP/IP 栈的增强,如为改善 SACK 丢包恢复引入 PRR,展示了 FreeBSD 在保持网络性能和可靠性竞争力方面的承诺。

    存储与虚拟化改进

    存储增强

    • ctld 中的网络 QoS: 工具 ctld 现在支持使用差分服务代码点和以太网优先级代码点(Ethernet PCP)设置网络 QoS,进一步提升了 FreeBSD 在高性能存储解决方案中的表现。 (在 FreeBSD 13.3 中引入)

    • 更新的 NFS 支持: NFS 客户端和服务器已更新,以支持 NFSv4.2,包括扩展属性,展示了 FreeBSD 在兼容性和功能丰富性方面的持续承诺。

    • 基于 TLS 的安全 NFS: FreeBSD 支持通过 TLS 配置 NFS,专注于提供安全存储解决方案。

    虚拟化增强

    • Bhyve 中增强的虚拟机支持: 内核模块 vmm 现在支持的虚拟 CPU 可大于 16 个,使得虚拟机能够更有效地使用主机的 CPU 资源。此外,Bhyve 还引入了对 virtio-input 设备仿真的支持,通过支持将键盘和鼠标输入事件注入到虚拟机中,改善了与虚拟化环境的交互。

    用户空间与内核增强

    用户空间改进

    • 进程管理增强: 用户现在能直接从 ~/.login_conf 设置进程优先级和 umask 值,更精细地控制进程管理和文件权限。 (在 FreeBSD 13.3 中引入)

    • 报告与配置增强: 对定期输出的流线化和对 head、tail 等工具的更新,确保了参数 -q(安静模式)和 -v(详细模式)的一致性,同时采用 SI 后缀表示数值参数,提升了系统可用性和配置灵活性。 (在 FreeBSD 13.3 中引入)

    内核增强

    • 安全性改进: 实现了针对 64 位可执行文件的地址空间布局随机化(ASLR),通过随机化内存地址空间提高安全性,可有效缓解某些类型的攻击。此外,还针对特定英特尔 CPU 的硬件页面失效问题提供了变通解决方案,强调了 FreeBSD 对安全性的重视。 (在 FreeBSD 13.3 中引入)

    • 调试增强: 新的配置参数 SPLIT_KERNEL_DEBUG 能分别处理内核和模块的调试数据,优化了调试流程,而不影响系统性能。

    加密框架与驱动程序更新

    • libmd 提升加密多样性: 增加了对 SHA-512/224 的支持,这是一种截断版的 SHA-512 哈希函数,提供了紧凑而安全的哈希替代方案。 (在 FreeBSD 13.3 中引入)

    • 全面改进的加密框架: 内核中的加密框架经过了大幅度改进,增强了对现代加密算法的支持,并简化了设备驱动程序和框架消费者的接口。废弃的算法已被移除,以提升安全性。

    • 驱动程序支持增强: 将 aesni 驱动程序添加到 GENERIC 内核中,支持 AMD64 和 i386 架构,通过硬件加速的加密功能提升软件加密和安全性。

    硬件支持改进

    • 以太网控制器支持: 引入了驱动程序 igc,支持 Intel I225 以太网控制器,支持各种速度及高级功能,如校验和卸载和多队列操作。

    • 驱动程序更新: 驱动程序 ice 已添加固件日志记录和初步的数据中心桥接(DCB)支持,进一步提升了 FreeBSD 在管理和优化网络接口方面的能力。 (在 FreeBSD 13.3 中引入)

    • 处理器支持: 完善对英特尔 Alder Lake(12 代)CPU 的支持,并整合进 hwpmc 框架,以充分利用 CPU 的新特性。

    13.x 中已弃用功能和删除的支持

    在 FreeBSD 13.x 系列中,多个功能和支持被弃用/移除,反映了 FreeBSD 项目面向未来的理念,致力于采用现代技术和标准。

    用户空间与内核更改

    • 工具链现代化: 过时的 binutils 2.17 和 GCC 4.2.1 已被移除,标志着所有受支持的架构全面过渡到了 LLVM/Clang 工具链。这一变化强调了 FreeBSD 在提升系统稳定性和开发灵活性方面,致力于利用现代工具链的承诺。

    • 许可证与软件更新: GPL 许可证版本的 dtc 被 BSD 许可证版本取代。此外,BSD 版本的 grep 取代了 GNU 版本。工具 bc 和 dc 被 Gavin D. Howard 开发的版本所替代,这些版本不依赖外部的大数库,并提供了 GNU bc 的扩展功能。 (在 FreeBSD 13.3 中引入)

    网络驱动弃用

    • 过时的网络驱动: 一些不再使用的过时网络驱动被移除,以简化对较新和更常用硬件的支持。这使得可以更加专注于提升对现代网络接口的支持。

    虚拟化弃用

    • Bhyve 精细化改进: FreeBSD 对其本地虚拟化管理程序 Bhyve 进行了精细化改进,移除了已弃用的设备模型,并支持更新的功能,如 VirtIO-9p 文件系统共享和虚拟机快照。

    面向未来的更改

    • CPU 类型更改: i386 架构的默认 CPUTYPE 从 486 变更为 686,要求使用 686 类 CPU。这与行业标准一致,i686 已成为基准。 (在 FreeBSD 13.3 中引入)

    FreeBSD 13.4-RELEASE 亮点

    FreeBSD 13.4-RELEASE 是 13-STABLE 分支的最新版本。它包含了错误修复、安全补丁和更新的驱动程序,以增强用户体验和系统稳定性。

    从先前版本升级

    从早期版本升级的用户将发现升级过程非常顺利,升级过程有详细的文档支持。建议在进行安装前,先查阅发布说明中的勘误表,以了解任何最新的紧急问题。

    安全性与 Errata

    安全公告

    该版本解决了若干个重要的安全漏洞:

    勘误表

    重要修复包括:

    用户空间应用程序更改

    • 性能改进: libcapsicum 已改进,缓存了更多的时区信息,减少了对 tzset(3) 的调用,提升了性能。

    • 贡献软件更新:

      • SQLite3: 升级到版本 3.46.0。

    设备和驱动程序

    • 驱动程序更新:

      • irdma 和 ice: 这两个驱动已更新,以提高性能和稳定性。

      • u3g 支持: 增加了对设备 SIM7600G 的支持,扩展了移动网络的硬件兼容性。

      • 无线驱动程序: 对原生和基于 LinuxKPI 的无线驱动进行了多个稳定性修复,提升了 FreeBSD 的无线网络性能(由 FreeBSD 基金会赞助)。

    网络更新

    • SCTP 改进: 增加了对环回接口上 SCTP 校验和卸载的支持,同时对 SCTP 堆栈进行了性能提升和 bug 修复。

    硬件支持

    • 处理器支持: 为 AMD Ryzen 7“Phoenix”处理器增加了对驱动程序 amdsmn 和 amdtemp 的支持,可以通过 sysctl 获取温度读取值。

    文档更新

    • 手册页: 删除了对旧工具 disklabel 的引用,改为使用 gpart。后续的 FreeBSD 版本将完全移除该工具,推广现代的磁盘管理方法。

    Ports 和软件包基础设施

    • 软件包变更:

      • 现代化的 DVD 软件包集: 反映了当前的软件包装趋势。

      • 已移除的 Port:

        • archivers/unzip

    关于未来版本和开发战略

    随着 FreeBSD 的不断发展,项目的开发战略和未来版本的路线图反映了其致力于拥抱现代计算架构的同时,确保广泛的兼容性和支持。FreeBSD 15.0 将是这一旅程的一个重要节点,多个关键决策将塑造操作系统的发展方向:

    • 逐步淘汰 32 位平台支持: FreeBSD 15.0 预计不再支持 32 位平台,除 armv7 外,这标志着战略的转变,重点将转向 64 位计算。armv6、i386 和 powerpc 平台将被废弃,并计划移除,尽管 64 位系统仍将保留运行旧版 32 位二进制文件的能力。

    • armv7 架构状态: 预计 armv7 架构将在 FreeBSD 15.0 和 stable/15 分支中作为二级架构提供支持。然而,预计 armv7 支持可能会在 FreeBSD 16.0 中被取消,关于 armv7 支持的状态将在 15.0 版本发布时提供更新。

    • 继续支持 32 位二进制文件和应用程序: 尽管有向 64 位平台转型的趋势,FreeBSD 将继续支持在 64 位平台上执行 32 位二进制文件,至少在 stable/15 和 stable/16 分支中以参数 COMPAT_FREEBSD32 提供支持。此外,stable/15 分支将继续支持编译单个 32 位应用程序,确保与广泛的软件兼容性。

    结论

    FreeBSD 13.x 系列展示了该项目在持续改进、安全性和现代化方面的承诺。FreeBSD 一直在增强系统的健壮性、安全性和硬件兼容性,跟上并有时超越其他操作系统的技术进步。FreeBSD 13.4-RELEASE 是 FreeBSD 不断适应用户需求的坚定体现,巩固了其作为开源操作系统之一的领先地位。

    参考资料

    对于那些有兴趣深入了解 FreeBSD 13.x 系列详细演变的用户,官方的 FreeBSD 文档和发行说明提供了对每个版本的进展和改进的全面见解。

    • 官方发行说明:

    • 其他资源:

    比如其他架构有些已经移除(如 IA64、SPARC64),也有新增(如 AARCH64、RISC-V)等各种变化。

    11.3 / 12.1

    icelake-server

    Intel Ice Lake-SP

    11.3 / 12.1

    icelake-client

    Intel Ice Lake

    11.2 / 12.1

    cannonlake

    Intel Cannon Lake

    11.3 / 12.1

    skylake-avx512(skx)

    Intel Skylake

    11.2

    skylake-avx512

    Intel Skylake

    11.0

    skylake

    Intel Skylake

    11.0

    broadwell

    Intel Broadwell

    11.0

    haswell(core-avx2)

    Intel Haswell

    11.0

    ivybridge(core-avx-i)

    Intel IvyBridge

    11.0

    sandybridge(corei7-avx)

    Intel SandyBridge

    10.0

    core-avx-i

    Intel IvyBridge

    10.0

    corei7-avx

    Intel SandyBridge

    13.0

    znver2

    AMD Zen2

    11.2

    znver1

    AMD Zen

    11.0

    bdver4

    AMD Excavator

    10.1

    bdver3

    AMD Steamroller

    10.0

    bdver2

    AMD Piledriver

    10.0

    bdver1

    AMD Bulldozer

    13.0

    btver2

    AMD Jaguar

    10.0

    btver1

    AMD Bobcat

    11.3 / 12.1

    tremont

    Intel Tremont

    11.3 / 12.1

    goldmont-plus

    Intel Goldmont+

    11.2

    goldmont

    Intel Goldmont

    11.0

    silvermont(slm)

    Intel Silvermont

    10.1

    slm

    Intel Silvermont

    11.0

    bonnell(atom)

    Intel Bonnell

    10.0

    atom

    Intel Bonnell

    11.2 / 12.1

    knm

    Intel Knights Mill

    11.0

    knl

    Intel Knights Landing

    10.0

    penryn

    Intel Penryn

    10.0

    core2

    Intel Core2

    10.0

    westmere

    Intel Westmere

    10.0

    nehalem(corei7)

    Intel Nehalem

    10.0

    yonah

    Intel Yonah

    10.0

    prescott(core)

    Intel Prescott

    10.0

    nocona(prescott)

    Intel Nocona

    在 amd64 环境中,prescott 被视为 nocona

    10.0

    pentium4(p4)

    Intel Pentium 4

    10.0

    pentium4m(p4m)

    Intel Pentium 4M

    10.0

    pentium3(p3)

    Intel Pentium 3

    10.0

    pentium3m(p3m)

    Intel Pentium 3M

    10.0

    pentium-m(p-m)

    Intel Pentium M

    10.0

    pentium2(p2)

    Intel Pentium 2

    10.0

    pentiumpro(i686)

    Intel Pentium Pro

    FreeBSD 13/i386 的最低要求

    10.0

    pentium-mmx(i586/mmx)

    Intel Pentium MMX

    10.0

    pentium(i586)

    Intel Pentium

    10.0

    i486

    Intel i80486

    10.0

    i386

    Intel i80386

    10.0

    opteron-sse3

    AMD Opteron

    10.0

    athlon64-sse3

    AMD Athlon64

    10.0

    k8-sse3

    AMD K8

    10.0

    opteron

    AMD Opteron

    10.0

    amdfam10(barcelona)

    AMD K10

    10.0

    athlon64

    AMD Athlon64

    10.0

    athlon-fx

    AMD Athlon FX

    10.0

    athlon-mp

    AMD Athlon MP

    10.0

    athlon-xp

    AMD Athlon XP

    10.0

    athlon-4

    AMD Athlon 4

    10.0

    x86-64

    AMD Opteron

    FreeBSD/amd64 的最低要求

    10.0

    k8

    AMD K8

    11.0

    athlon(k7)

    AMD Athlon

    10.0

    athlon

    AMD Athlon

    10.0

    athlon-tbird

    AMD Athlon Thunderbird

    10.0

    k7

    AMD K7

    10.0

    k6

    AMD K6

    10.0

    k6-2

    AMD K6-2

    10.0

    k6-3

    AMD K6-3

    10.0

    geode

    NSC Geode

    10.0

    k5

    AMD K5

    与 pentium 处理类似(不确定是否为别名)

    10.0

    crusoe

    Transmeta Crusoe

    10.0

    c7

    VIA C7

    与 c3-m 处理类似

    10.0

    c3-2

    VIA C3-2

    10.0

    c3

    VIA C3

    10.0

    winchip2

    Centaur WinChip 2

    10.0

    winchip2-c6

    Centaur WinChip C6

    13.0

    tigerlake

    Intel Tiger Lake

    13.0

    cooperlake

    Intel Cooper Lake

    13.0

    cascadelake

    Intel Cascade Lake

    迁移到 OpenZFS: ZFS 作为 FreeBSD 存储能力的基石,现在是 OpenZFS 2.1.14,确保了 FreeBSD 享受该强大文件系统的最新发展成果。

    增强的认证: libtacplus 库现在符合 POSIX shell 语法规则,提高了 TACACS+ 认证的安全性和可配置性。 (在 FreeBSD 13.3 中引入)

    弃用的工具: 像自动挂载守护进程 ctm 和 amd 等工具已被移除,现代替代工具如 autofs 已取代其功能。 (在 FreeBSD 13.3 中引入)

    2024 年 8 月 7 日

    NFS 客户端接受包含路径分隔符的文件名

    FreeBSD-SA-24:08.openssh

    2024 年 8 月 7 日

    OpenSSH 预认证异步信号安全问题

    FreeBSD-SA-24:09.libnv

    2024 年 9 月 4 日

    libnv 中的多个漏洞

    FreeBSD-SA-24:10.bhyve

    2024 年 9 月 4 日

    bhyve(8) 通过 TPM 设备传递特权来宾逃逸

    FreeBSD-SA-24:11.ctl

    2024 年 9 月 4 日

    ctl(4) CAM 目标层中的多个问题

    FreeBSD-SA-24:12.bhyve

    2024 年 9 月 4 日

    bhyve(8) 通过 USB 控制器特权来宾逃逸

    FreeBSD-SA-24:13.openssl

    2024 年 9 月 4 日

    OpenSSL 中 X.509 名称检查的可能 DoS 漏洞

    FreeBSD-SA-24:14.umtx

    2024 年 9 月 4 日

    umtx 内核 panic 或使用后释放问题

    2024 年 4 月 24 日

    与 ZFS 相关的内核线程导致高 CPU 使用

    FreeBSD-EN-24:10.zfs

    2024 年 6 月 19 日

    ZFS 中的内核内存泄漏

    FreeBSD-EN-24:11.ldns

    2024 年 6 月 19 日

    ldns 使用在 resolv.conf 中注释掉的名称服务器

    FreeBSD-EN-24:12.killpg

    2024 年 6 月 19 日

    killpg 中的锁顺序反转导致活锁

    FreeBSD-EN-24:13.libc++

    2024 年 6 月 19 日

    向堆分配的 std:: string 删除传递了错误的大小

    FreeBSD-EN-24:14.ifconfig

    2024 年 8 月 7 日

    ifconfig 中的网络掩码分配错误

    FreeBSD-EN-24:15.calendar

    2024 年 9 月 4 日

    cron(8) / periodic(8) 会话登录问题

    OpenSSH:
    升级到版本 9.7p1。此次发布重点修复了 bug,并将 DSA 签名算法支持设为编译时参数,计划在今年稍晚禁用该算法,并在 2025 年完全移除支持。
  • LLVM/Clang: 升级到版本 18.1.5。

  • bc: 升级到版本 6.7.6。

  • atf: 升级到 0.22 快照 55c21b2c。

  • libarchive: 升级到版本 3.7.4。

  • capsicum-test: 升级到快照 eab7a83b。

  • (现在已包含在基本系统中)。
  • emulators/linux_base-c7(没有其他 Linux 软件包时不再有用)。

  • ports-mgmt/portmaster(不推荐使用,推荐使用 pkg 和二进制包)。

  • x11-drivers/xf86-video-vmware(在当前版本的 xorg-server 中不再有用)。

  • 已替换的 Port:

    • devel/git 被 devel/git@lite 替换,后者足以满足大多数需求。

  • 新增的 Port:

    • sysutils/seatd 和 x11-wm/sway 用于 Wayland 支持。

  • Ports 和软件包基础设施: 从 FreeBSD 15.0 开始,后续版本将不再支持为已废弃的 32 位平台从 Ports 构建软件包。这一决定反映了行业趋势,即逐步淘汰 32 位架构,并将开发精力集中在更广泛使用的 64 位平台上。

  • 32 位支持的生命周期结束(EOL): stable/14 分支将继续支持 32 位内核和用户空间,以及 Ports 系统对 32 位系统的支持,直到 FreeBSD 14.0 发布五年后达到生命周期结束(EOL)。这一时间表为依赖 32 位平台的用户和开发者提供了过渡期,便于迁移到支持的架构。

  • 社区反馈和未来决策: FreeBSD 项目重视社区反馈,承诺在形塑废弃平台的支持策略方面做出努力。社区的需求和贡献将对是否在 FreeBSD 15.0 或更高版本中扩展某些平台的支持产生影响。

  • FreeBSD 手册

    公告

    日期

    主题

    FreeBSD-SA-24:03.unbound

    2024 年 3 月 28 日

    Unbound 中的多个漏洞

    FreeBSD-SA-24:04.openssh

    2024 年 7 月 1 日

    OpenSSH 预认证远程代码执行

    FreeBSD-SA-24:05.pf

    2024 年 8 月 7 日

    pf 在状态表中错误匹配不同的 ICMPv6 状态

    FreeBSD-SA-24:06.ktrace

    2024 年 8 月 7 日

    ktrace(2) 在执行 setuid 二进制文件时未能解除附着

    Errata

    日期

    主题

    FreeBSD-EN-24:05.tty

    2024 年 3 月 28 日

    TTY 内核 panic

    FreeBSD-EN-24:06.wireguard

    2024 年 3 月 28 日

    WireGuard 中 if_wg(4) 的屏障不足

    FreeBSD-EN-24:07.clang

    2024 年 3 月 28 日

    启用某些优化时 Clang 崩溃

    FreeBSD-EN-24:08.kerberos

    2024 年 3 月 28 日

    使用弱加密时 Kerberos 崩溃

    FreeBSD 13.4-RELEASE
    FreeBSD 14 分支
    FreeBSD 13.4-RELEASE 发行说明
    FreeBSD 13.3-RELEASE 发行说明

    FreeBSD-SA-24:07.nfsclient

    FreeBSD-EN-24:09.zfs

    image
    image

    /usr/local/etc/automount.conf – automount(8) 配置

  • /usr/local/etc/doas.conf – doas(1) 配置

  • 用户组成员信息。

  • 写入性能
  • diff – F25 相对于 W520 提升的速度

  • 2.0x

    1.7x

    2.0x

    1.6x

    W520

    510

    1435

    346k

    1443

    F25

    1014

    2447

    548k

    2986

    https://xyte.ch/mods/t25-frankenpad/
    HeatoN
    Hall of Fame
    https://aliexpress.com/item/1005007244139650.html
    Tiny UPS for Tiny NAS Reloaded
    FreeBSD: Fixing ThinkPad X1 WiFi
    Quare FreeBSD?
    The Power to Serve – FreeBSD Power Management
    FreeBSD Desktop – Part 2.1 – Install FreeBSD 12
    FreeBSD Network Management with network.sh Script
    acpi-thinkpad-fan.sh
    battery-time.sh
    battery-capacity.sh
    battery-info.sh
    FreeBSD Desktop
    XFCE Cupertino Way
    More Undervalued Hardware Companions
    UNIX Mouse Shootout

    diff

    https://syncthing.net/
    维基百科
    FreeBSD 上的 Nextcloud
    https://10.0.0.100:8384
    汉堡菜单
    /usr/local/etc/syncthing/config.xml
    FreeBSD 上的 Syncthing
    BSD Now 262 – OpenBSD Surfacing
    syncthing-01.png
    syncthing-02.png
    syncthing-03
    syncthing-04.png
    syncthing-05.png
    syncthing-06.png
    syncthing-07.png
    syncthing-08.png
    syncthing-09.png
    syncthing-10.png
    syncthing-11
    syncthing-12
    syncthing-13
    syncthing-14
    syncthing-15
    syncthing-19
    syncthing-20
    syncthing-21
    syncthing-22
    syncthing-23
    syncthing-24
    syncthing-25
    syncthing-26
    syncthing-27
    syncthing-28.png
    syncthing-29.png
    syncthing-30.png
    syncthing-31.png
    syncthing-32.png
    syncthing-33.png
    syncthing-34.png
    syncthing-36
    syncthing-35

    在 FreeBSD 容器上运行 RabbitMQ 集群

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2019/06

    我真的很喜欢那种小而简单、专注做好一件事并且做得非常好的专用解决方案——也许是因为我太喜欢 UNIX 了。这种理念的好例子是 Minio 对象存储,它实现了 S3 协议,支持分布式集群、纠删码,并内置了 Web 界面,还有许多其他特性——我曾在一文中介绍过。

    RabbitMQ 是又一个这样的例子——它大概是目前最流行的 AMQP 协议实现之一——同样带有小巧、精致的 Web 界面。但它和 Minio 的区别在于“力量”。Minio 的 Web 界面非常基础、面向用户,大多数管理和配置任务都需要通过 CLI 完成。Minio 的 Web 界面主要提供创建/删除 buckets、上传/下载文件等功能。而 RabbitMQ 的 Web 界面则非常强大,一旦启用,你几乎不再需要命令行了,所有事情都可以通过 Web 界面完成。

    FreeBSD 特色开发项目(滚动更新)

    警告

    正在校对,请谨慎参考。

    本节是对 FreeBSD 基金会赞助的项目进行的说明。

    本节是对 的翻译。

    FreeBSD 基金会赞助和社区贡献的 FreeBSD 特色项目

    FreeBSD 基金会以资金和资源赞助 FreeBSD 操作系统的开发活动,重点是提升 FreeBSD 的安全性、性能和可用性。我们与社区携手合作,共同努力,确保 FreeBSD 的恒久生命力。

    基金会参与的开发项目由多种因素决定,包括与核心团队讨论需要填补的开发空白、该开发工作对改进项目的总体影响,以及基金会可提供的资金。以下是这些项目。

    如想参与,请访问 。

    FreeBSD pkg 命令概述

    • 原文:

    • 作者:重村法克

    • 2025-02-09

    F25 % cat /etc/rc.conf
    # 静默 # ------------------------------------------------------------------
      rc_startmsgs=NO
      rc_info=NO
    
    # 网络 # ------------------------------------------------------------------
      hostname=f25.local
      background_dhclient=YES
      extra_netfs_types=NFS
      defaultroute_delay=3
      defaultroute_carrier_delay=3
      wlans_iwm0=wlan0                              # // network.sh
      create_args_wlan0="country PL regdomain FCC4" # // network.sh
    # ifconfig_wlan0="WPA SYNCDHCP powersave"       # // network.sh
      gateway_enable="YES"
      harvest_mask=351
      rtsol_flags="-i"
      rtsold_flags="-a -i"
    
    # 模块/通用/基本 # ------------------------------------------------------
      kld_list="${kld_list} /boot/modules/i915kms.ko"
      kld_list="${kld_list} fusefs coretemp sem cpuctl ichsmb cuse linux linux64"
      kld_list="${kld_list} urndis"
    
    # 模块/BHYVE/VIRTUALBOX # -------------------------------------------------
      vboxnet_enable=NO
      vm_enable=YES
      vm_dir="zfs:zroot/vm"
      vm_list="poudriere"
      vm_delay="3"
      pf_enable=YES
      dnsmasq_enable=NO
    
    # 电源 # --------------------------------------------------------------------
      performance_cx_lowest=C1
      economy_cx_lowest=Cmax
      powerd_enable=YES
      powerd_flags="-n adaptive -a hiadaptive -b adaptive -m 800 -M 1400"
      powerdxx_enable=NO
      powerdxx_flags="-n adaptive -a hiadaptive -b adaptive -m 800 -M 1400"
    
    # 守护进程 | yes # ------------------------------------------------------------
      zfs_enable=YES
      xdm_enable=YES
      xdm_tty=ttyv4
      nfs_client_enable=YES
      devd_flags="-n"
      moused_enable=YES
      syslogd_flags='-s -s'
      sshd_enable=YES
      local_unbound_enable=NO
      webcamd_DEV=$( usbconfig | grep -i camera | awk -F ':' '{print $1}' )
      webcamd_enable=YES
      webcamd_0_flags="-d ${webcamd_DEV}"
      ubuntu_enable=YES
      rctl_enable=YES
      dbus_enable=YES
      cupsd_enable=YES
    
    # 守护进程/temp | yes # -------------------------------------------------------
      samba_server_enable=NO
      nmbd_enable=NO
      smbd_enable=NO
    
    # 守护进程 | no # -------------------------------------------------------------
      linux_enable=NO
      openssh_enable=NO
      openssh_flags='-4 -p 23'
      sendmail_enable=NO
      sendmail_submit_enable=YES
      sendmail_outbound_enable=NO
      sendmail_msp_queue_enable=NO
    
    # 文件系统 # -----------------------------------------------------------------------
      fsck_y_enable=YES
      clear_tmp_enable=NO
      clear_tmp_X=YES
      growfs_enable=YES
    
    # 其他 # --------------------------------------------------------------------
      keyrate=fast
      keymap=pl.kbd
      virecover_enable=NO
      update_motd=NO
      devfs_system_ruleset=desktop
      hostid_enable=YES
      entropy_file=NO
      savecore_enable=NO
      dumpdev=AUTO
    
    # NFSD # ---------------------------------------------------------------------
      sshd_enable=YES
      nfs_server_enable=YES
      nfsv4_server_only=YES
      nfs_server_flags="-t"
    
    # JAIL # ---------------------------------------------------------------------
      jail_enable=YES
      jail_devfs_enable=YES
      jail_list="minecraft"
    F25 % cat /etc/sysctl.conf
    # HARVEST MASK FOR random(4)
    kern.random.harvest.mask=33119
    
    # 安全
    security.bsd.see_jail_proc=0
    security.bsd.unprivileged_proc_debug=0
    
    # 安全性/禁用 Intel CPU MDS 缓解措施
    hw.mds_disable=0
    machdep.mitigations.mds.disable=0
    
    # 安全/随机 PID
    kern.randompid=1
    
    # 令人烦恼的事项
    vfs.usermount=1
    kern.coredump=0
    hw.syscons.bell=0
    kern.vt.enable_bell=0
    
    # ZFS 磁盘块大小对齐为 4k
    vfs.zfs.min_auto_ashift=12
    
    # ZFS 删除错误导致的 TRIM 问题 (def:64)
    vfs.zfs.vdev.trim_max_active=1
    
    # ZFS ARC 调优
    vfs.zfs.arc.min=134217728
    vfs.zfs.arc.max=536870912
    
    # 禁用 ZFS 严格的 ZVOL 配额执行 (def:1)
    vfs.zfs.zvol_enforce_quotas=0
    
    # Jail/允许在 Jail 中升级
    security.jail.chflags_allowed=1
    
    # JAILS/允许 RAW SOCKETS
    security.jail.allow_raw_sockets=1
    
    # JAILS/允许 fdescfs(5)
    security.jail.mount_fdescfs_allowed=1
    security.jail.param.allow.mount.fdescfs=1
    
    # 桌面/交互性
    kern.sched.preempt_thresh=224
    
    # 桌面量子用于时间共享线程,以 stathz 时钟滴答为单位 (def:12) NomadBSD
    kern.sched.slice=3
    
    # 桌面/Iridium/Chromium
    kern.ipc.shm_allow_removed=1
    
    # 采样率转换器质量 (0=low .. 4=high) (def:1) NomadBSD
    hw.snd.feeder_rate_quality=3
    
    # 性能/所有共享内存段将映射到不可分页内存
    kern.ipc.shm_use_phys=1
    
    # VIRTUALBOX aio(4) 设置
    vfs.aio.max_buf_aio=8192
    vfs.aio.max_aio_queue_per_proc=65536
    vfs.aio.max_aio_per_proc=8192
    vfs.aio.max_aio_queue=65536
    
    # 允许普通用户使用 idprio(8)
    security.bsd.unprivileged_idprio=1
    
    # 网络/不向已关闭端口的报文发送 RST
    net.inet.tcp.blackhole=2
    
    # 网络/对拒绝的连接不发送“端口不可达”响应
    net.inet.udp.blackhole=1
    
    # 网络/限制 SYN/ACK 重传次数(默认:3)
    
    net.inet.tcp.syncache.rexmtlimit=0
    
    # 网络/如果 syncache 溢出则使用 TCP SYN Cookies(默认:1)
    
    net.inet.tcp.syncookies=0
    
    # 网络/分配随机的 ip_id 值(默认:0)
    
    net.inet.ip.random_id=1
    
    # 网络/启用发送 IP 重定向(默认:1)
    
    net.inet.ip.redirect=0
    
    # 网络/忽略 ICMP 重定向(默认:0)
    
    net.inet.icmp.drop_redirect=1
    
    # 网络/丢弃 SYN+FIN 设置的 TCP 数据包(默认:0)
    
    net.inet.tcp.drop_synfin=1
    
    # 网络/更快回收 FIN_WAIT_2 状态的关闭连接(默认:0)
    
    net.inet.tcp.fast_finwait2_recycle=1
    
    # 网络/某些 ICMP 不可达消息可能会在 SYN_SENT 状态中中断连接(默认:1)
    
    net.inet.tcp.icmp_may_rst=0
    
    # 网络/初始发送/接收套接字缓冲区大小
    
    net.inet.tcp.sendspace=65536
    net.inet.tcp.recvspace=65536
    
    # BHYVE
    
    net.link.tap.up_on_open=1
    net.link.tap.user_open=1
    
    # 参考: [https://lists.freebsd.org/archives/freebsd-stable/2023-November/001726.html](https://lists.freebsd.org/archives/freebsd-stable/2023-November/001726.html)
    
    vfs.zfs.dmu_offset_next_sync=0
    
    # 声卡音量
    
    hw.snd.vpc_0db=35
    
    # 默认音频输出设备
    
    hw.snd.default_unit=0
    
    # 提高软件时钟精度(默认:5) 2025/02/05
    
    kern.timecounter.alloweddeviation=0
    
    # 禁用 ZFS Deadman —— 有助于 ZFS 在会进入睡眠的 USB 驱动器上运行
    
    vfs.zfs.deadman.enabled=0
    
    
    # 最大监听套接字待处理连接队列大小(默认: 128)
    
    kern.ipc.soacceptqueue=1024
    
    # 最大监听套接字待处理连接队列大小(兼容模式)(默认: 128)
    
    kern.ipc.somaxconn=1024
    
    # 在慢启动期间 TCP 最大 CWND 增量限制为该段数(默认: 2)
    
    net.inet.tcp.abc_l_var=16
    
    # 启用 TCP Fast Open 服务器功能(默认: 0)
    
    net.inet.tcp.fastopen.server_enable=1
    
    # FIN-WAIT2 超时(默认: 60000)
    
    net.inet.tcp.finwait2_timeout=8000
    
    # 防止共享内存被换出到磁盘
    
    kern.ipc.shm_use_phys=1
    
    # 在挂起时不切换虚拟控制台
    # 有时切换到不同 VT 会破坏硬件加速
    # 参考: [https://github.com/freebsd/drm-kmod/issues/175](https://github.com/freebsd/drm-kmod/issues/175)
    
    kern.vt.suspendswitch=0
    F25 % cat /boot/loader.conf
    # CONSOLE 通用
    autoboot_delay=2       # 使用 '-1' 表示不等待 | 使用 'NO' 表示无限等待
    boot_mute=YES          # 类似 LOADER 中的 '-m' 参数 —— 静音控制台并显示 FreeBSD 标志
    loader_logo=none       # 可选标志选项: fbsdbw beastiebw beastie none
    loader_menu_frame="none"
    screen.font="6x12"
    
    # CONSOLE 分辨率
    kern.vt.fb.default.mode="1920x1080"
    efi_max_resolution="1920x1080"
    vbe_max_resolution="1920x1080"
    
    # WINE 修复
    machdep.max_ldt_segment=2048
    
    # 启动模块
    aesni_load=YES
    geom_eli_load=YES
    cryptodev_load=YES
    zfs_load=YES
    
    # 启用帧缓冲压缩以节能
    
    compat.linuxkpi.i915_enable_fbc=1
    
    # 启动时跳过不必要的模式设置
    
    compat.linuxkpi.i915_fastboot=1
    
    # 启用节能显示 C 状态
    
    compat.linuxkpi.i915_enable_dc=2
    
    # 尽可能禁用显示电源井
    
    # compat.linuxkpi.i915_disable_power_well=1
    
    # 启用 Synaptics 支持
    
    hw.psm.synaptics_support=1
    
    # 禁用 /dev/diskid/* 和 /dev/gptid/* 磁盘条目
    
    kern.geom.label.disk_ident.enable=0
    kern.geom.label.gptid.enable=0
    
    # 增加 ZFS 事务超时时间以节省电池
    
    vfs.zfs.txg.timeout=10
    
    # RACCT/RCTL 资源限制
    
    kern.racct.enable=1
    # ZFS 调优
    
    vfs.zfs.prefetch_disable=1
    
    # 电源管理:关闭没有驱动程序的设备
    
    hw.pci.do_power_nodriver=3
    
    # 电源管理 / 为每个核心单独优化 ISS 时钟
    
    # machdep.hwpstate_pkg_ctrl=0
    
    # 电源管理:每个使用的 AHCI 通道(ahcich 0-7)
    
    hint.ahcich.0.pm_level=5
    hint.ahcich.1.pm_level=5
    hint.ahcich.2.pm_level=5
    hint.ahcich.3.pm_level=5
    hint.ahcich.4.pm_level=5
    hint.ahcich.5.pm_level=5
    hint.ahcich.6.pm_level=5
    hint.ahcich.7.pm_level=5
    
    # GELI 线程数
    
    kern.geom.eli.threads=4
    
    # 最大发送队列大小
    
    net.link.ifqmaxlen=2048
    
    # 禁用 USB 数据包过滤
    
    hw.usb.no_pf=1
    
    # 启动和关闭时不等待 USB 设备枚举
    
    hw.usb.no_boot_wait=0
    hw.usb.no_shutdown_wait=1
    
    # 禁用 hwpstate_intel(4) 驱动
    
    hint.hwpstate_intel.0.disabled=1
    F25 % cat /etc/devfs.rules
    [desktop=10]
    add path 'acd*'      mode 0660 group operator
    add path 'cd*'       mode 0660 group operator
    add path 'da*'       mode 0660 group operator
    add path 'pass*'     mode 0660 group operator
    add path 'xpt*'      mode 0660 group operator
    add path 'fd*'       mode 0660 group operator
    add path 'md*'       mode 0660 group operator
    add path 'uscanner*' mode 0660 group operator
    add path 'lpt*'      mode 0660 group cups
    add path 'ulpt*'     mode 0660 group cups
    add path 'unlpt*'    mode 0660 group cups
    add path 'ugen*'     mode 0660 group operator
    add path 'usb/*'     mode 0660 group operator
    add path 'video*'    mode 0660 group operator
    add path 'cuse*'     mode 0660 group operator
    F25 % cat /etc/fstab
    # SWAP
      /dev/gpt/swap0  none  swap  sw  0 0
    
    # /tmp @ RAM
      tmpfs  /tmp  tmpfs  rw,size=1g,mode=1777  0 0
    
    # FreeBSD PSEUDO
      procfs  /proc  procfs  rw  0 0
    
    # Ubuntu Linux PSEUDO
      linprocfs  /compat/ubuntu/proc     linprocfs  rw,failok,late                    0 0
      linsysfs   /compat/ubuntu/sys      linsysfs   rw,failok,late                    0 0
      devfs      /compat/ubuntu/dev      devfs      rw,failok,late                    0 0
      fdescfs    /compat/ubuntu/dev/fd   fdescfs    rw,failok,late,linrdlnk           0 0
      tmpfs      /compat/ubuntu/dev/shm  tmpfs      rw,failok,late,size=1g,mode=1777  0 0
      /home      /compat/ubuntu/home     nullfs     rw,failok,late                    0 0
      /tmp       /compat/ubuntu/tmp      nullfs     rw,failok,late                    0 0
    F25 % grep '^[^#]' /etc/ttys
    console	none				unknown	off insecure
    ttyv0	"/usr/libexec/getty Pc"		xterm	onifexists secure
    ttyv1	"/usr/libexec/getty Pc"		xterm	onifexists secure
    ttyv2	"/usr/libexec/getty Pc"		xterm	onifexists secure
    ttyv3	"/usr/libexec/getty Pc"		xterm	onifexists secure
    ttyu0	"/usr/libexec/getty 3wire"	vt100	onifconsole secure
    ttyu1	"/usr/libexec/getty 3wire"	vt100	onifconsole secure
    ttyu2	"/usr/libexec/getty 3wire"	vt100	onifconsole secure
    ttyu3	"/usr/libexec/getty 3wire"	vt100	onifconsole secure
    dcons	"/usr/libexec/getty std.115200"	vt100	off secure
    xc0	"/usr/libexec/getty Pc"		xterm	onifconsole secure
    rcons	"/usr/libexec/getty std.115200"	vt100	onifconsole secure
    F25 # cat /etc/wpa_supplicant.conf
    # 通用
    eapol_version=2
    ap_scan=1
    fast_reauth=1
    
    # 开放网络
    network={
      key_mgmt=NONE
      priority=0
    }
    
    # 隐藏 SSID 的 WIFI
    network={
      scan_ssid=1
      ssid="hidden-network"
      psk="12341234"
      priority=0
    }
    
    # 命名开放网络
    network={
      ssid="Free_Internet"
      key_mgmt=NONE
      priority=0
    }
    
    # 普通 WPA/WPA2 加密网络
    network={
      ssid="SECURED"
      psk="12345678"
    }
    F25 % cat /usr/local/etc/automount.conf
      USERUMOUNT=YES
      USER=vermaden
      FM='caja --no-desktop'
      NICENAMES=YES
    F25 # cat /usr/local/etc/doas.conf
    # 核心
      permit nopass keepenv root     as root
      permit nopass keepenv vermaden as root
    
    # network.sh 脚本
      # pw groupmod network -m YOURUSERNAME
      # cat /usr/local/etc/doas.conf
      permit nopass :network as root cmd /etc/rc.d/netif args onerestart
      permit nopass :network as root cmd /usr/sbin/service args squid onerestart
      permit nopass :network as root cmd dhclient
      permit nopass :network as root cmd ifconfig
      permit nopass :network as root cmd killall args -9 dhclient
      permit nopass :network as root cmd killall args -9 ppp
      permit nopass :network as root cmd killall args -9 wpa_supplicant
      permit nopass :network as root cmd ppp
      permit nopass :network as root cmd route
      permit nopass :network as root cmd tee args -a /etc/resolv.conf
      permit nopass :network as root cmd tee args /etc/resolv.conf
      permit nopass :network as root cmd umount
      permit nopass :network as root cmd wpa_supplicant
    F25 % id vermaden | tr ' ' '\n' | tr ',' '\n'
    uid=1000(vermaden)
    gid=1000(vermaden)
    groups=1000(vermaden)
    0(wheel)
    5(operator)
    44(video)
    47(realtime)
    48(idletime)
    69(network)
    145(webcamd)
    920(vboxusers)
    F25 % battery-time.sh
    time: 3:30
    bat0: 92%
    bat1: 98%
    
    F25 % battery-capacity.sh 0
    Battery '0' model '01AV420' has efficiency: 96%
    
    F25 % battery-capacity.sh 1
    Battery '1' model '01AV425' has efficiency: 92%
    
    F25 % battery-info.sh 0
             Design capacity: 23940 mWh
          Last full capacity: 23070 mWh
                  Technology: secondary (rechargeable)
    Battery Swappable Capability: Non-swappable
              Design voltage: 11400 mV
             Capacity (warn): 1153 mWh
              Capacity (low): 200 mWh
                 Cycle Count: 37
        Measurement Accuracy: 95%
        Max Average Interval: 1000 ms
        Min Average Interval: 500 ms
        Low/warn granularity: -1 mWh
       Warn/full granularity: -1 mWh
                Model number: 01AV420
               Serial number: 1020
                        Type: LiP
                    OEM info: LGC
                       State: high
          Remaining capacity: 100%
              Remaining time: unknown
                Present rate: 0 mW
             Present voltage: 12713 mV
    
    F25 % battery-info.sh 1
             Design capacity: 23990 mWh
          Last full capacity: 22220 mWh
                  Technology: secondary (rechargeable)
              Design voltage: 10800 mV
             Capacity (warn): 1111 mWh
              Capacity (low): 200 mWh
                 Cycle Count: 10
        Measurement Accuracy: 95%
        Max Average Interval: 1000 ms
        Min Average Interval: 500 ms
        Low/warn granularity: -1 mWh
       Warn/full granularity: -1 mWh
                Model number: 01AV425
               Serial number: 9001
                        Type: LION
                    OEM info: SANYO
                       State: high
          Remaining capacity: 98%
              Remaining time: unknown
                Present rate: 0 mW
             Present voltage: 12676 mV
    # newaliases -v
    /etc/mail/aliases: 29 aliases, longest 10 bytes, 297 bytes total
    
    # ln -s /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
    
    # date
    Fri Aug 17 22:05:18 CEST 2018
    
    # echo nameserver 1.1.1.1 > /etc/resolv.conf
    
    # ping -c 3 freebsd.org
    PING freebsd.org (96.47.72.84): 56 data bytes
    64 bytes from 96.47.72.84: icmp_seq=0 ttl=51 time=117.918 ms
    64 bytes from 96.47.72.84: icmp_seq=1 ttl=51 time=115.169 ms
    64 bytes from 96.47.72.84: icmp_seq=2 ttl=51 time=115.392 ms
    
    --- freebsd.org ping statistics ---
    3 packets transmitted, 3 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 115.169/116.160/117.918/1.247 ms
    # cat /etc/rc.conf
    # 网络
      hostname=blackbox.local
      ifconfig_re0="inet 10.0.0.100/24 up"
      defaultrouter="10.0.0.1"
    
    # 守护进程 | 启用
      zfs_enable=YES
      sshd_enable=YES
      ntpd_enable=YES
      syncthing_enable=YES
      syslogd_flags="-s -s"
    
    # 守护进程 | 禁用
      sendmail_enable=NONE
      sendmail_submit_enable=NO
      sendmail_outbound_enable=NO
      sendmail_msp_queue_enable=NO
    
    # 其他
      dumpdev=NO
      update_motd=NO
      virecover_enable=NO
      clear_tmp_enable=YES
    # grep url: /etc/pkg/FreeBSD.conf
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/quarterly",
    
    # sed -i '' s/quarterly/latest/g /etc/pkg/FreeBSD.conf
    
    # grep url: /etc/pkg/FreeBSD.conf
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
    # env ASSUME_ALWAYS_YES=yes pkg update -f
    Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:11:amd64/latest, please wait...
    Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
    [syncthing.local] Installing pkg-1.10.5_1...
    [syncthing.local] Extracting pkg-1.10.5_1: 100%
    Updating FreeBSD repository catalogue...
    pkg: Repository FreeBSD load error: access repo file(/var/db/pkg/repo-FreeBSD.sqlite) failed: No such file or directory
    [syncthing.local] Fetching meta.txz: 100%    944 B   0.9kB/s    00:01    
    [syncthing.local] Fetching packagesite.txz: 100%    6 MiB 352.7kB/s    00:19    
    Processing entries: 100%
    FreeBSD repository update completed. 32388 packages processed.
    All repositories are up to date.
    # pkg install -y syncthing 
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            syncthing: 0.14.48
    
    Number of packages to be installed: 1
    
    The process will require 88 MiB more space.
    15 MiB to be downloaded.
    [1/1] Fetching syncthing-0.14.48.txz: 100%   15 MiB 525.3kB/s    00:29    
    Checking integrity... done (0 conflicting)
    [1/1] Installing syncthing-0.14.48...
    ===> Creating groups.
    Creating group 'syncthing' with gid '983'.
    ===> Creating users
    Creating user 'syncthing' with uid '983'.
    [1/1] Extracting syncthing-0.14.48: 100%
    Message from syncthing-0.14.48:
    
    WARNING: This version is not backwards compatible with 0.13.x, 0.12.x, 0.11.x
    nor 0.10.x releases!
    
    For more information, please read:
    
    https://forum.syncthing.net/t/syncthing-v0-14-0/7806
    https://github.com/syncthing/syncthing/releases/tag/v0.13.0
    https://forum.syncthing.net/t/syncthing-v0-11-0-release-notes/2426
    https://forum.syncthing.net/t/syncthing-syncthing-v0-12-0-beryllium-bedbug/6026
    # id syncthing
    uid=983(syncthing) gid=983(syncthing) groups=983(syncthing)
    # pkg info -l syncthing
    syncthing-0.14.48:
            /usr/local/bin/stbench
            /usr/local/bin/stcli
            /usr/local/bin/stcompdirs
            /usr/local/bin/stdisco
            /usr/local/bin/stdiscosrv
            /usr/local/bin/stevents
            /usr/local/bin/stfileinfo
            /usr/local/bin/stfinddevice
            /usr/local/bin/stgenfiles
            /usr/local/bin/stindex
            /usr/local/bin/strelaypoolsrv
            /usr/local/bin/strelaysrv
            /usr/local/bin/stsigtool
            /usr/local/bin/sttestutil
            /usr/local/bin/stvanity
            /usr/local/bin/stwatchfile
            /usr/local/bin/syncthing
            /usr/local/etc/rc.d/syncthing
            /usr/local/etc/rc.d/syncthing-discosrv
            /usr/local/etc/rc.d/syncthing-relaypoolsrv
            /usr/local/etc/rc.d/syncthing-relaysrv
            /usr/local/share/doc/syncthing/AUTHORS
            /usr/local/share/doc/syncthing/LICENSE
            /usr/local/share/doc/syncthing/README.md
    # /usr/local/etc/rc.d/syncthing rcvar
    # syncthing
    #
    syncthing_enable="NO"
    #   (default: "")
    
    # grep syncthing_enable /etc/rc.conf
      syncthing_enable=YES
    # less -N /usr/local/etc/rc.d/syncthing
    (...)
          9 # Add the following lines to /etc/rc.conf.local or /etc/rc.conf
         10 # to enable this service:
         11 #
         12 # syncthing_enable (bool):      Set to NO by default.
         13 #                               Set it to YES to enable syncthing.
         14 # syncthing_home (path):        Directory where syncthing configuration
         15 #                               data is stored.
         16 #                               Default: /usr/local/etc/syncthing
         17 # syncthing_log_file (path):    Syncthing log file
         18 #                               Default: /var/log/syncthing.log
         19 # syncthing_user (user):        Set user to run syncthing.
         20 #                               Default is "syncthing".
         21 # syncthing_group (group):      Set group to run syncthing.
         22 #                               Default is "syncthing".
    (...)
    # ls /var/log/syncthing.log
    ls: /var/log/syncthing.log: No such file or directory
    
    # :> /var/log/syncthing.log
    
    # chown syncthing:syncthing /var/log/syncthing.log
    
    # ls -l /var/log/syncthing.log
    -rwxr-xr-x  1 syncthing  syncthing  0 2018.08.19 01:06 /var/log/syncthing.log
    # cat > /etc/newsyslog.conf.d/syncthing.conf << __EOF
    # logfilename              [owner:group]     mode  count  size  when  flags [/pid_file]
    /var/log/syncthing.log  syncthing:syncthing  640   7      100   *     JC
    __EOF
    
    # cat /etc/newsyslog.conf.d/syncthing.conf
    # logfilename              [owner:group]     mode  count  size  when  flags [/pid_file]
    /var/log/syncthing.log  syncthing:syncthing  640   7      100   *     JC
    
    # newsyslog -v | grep syncthing
    Processing /etc/newsyslog.conf.d/syncthing
    /var/log/syncthing.log : size (Kb): 0 [100] --> skipping
    # service syncthing start
    Starting syncthing.
    daemon: pidfile ``/var/run/syncthing.pid'': Permission denied
    /usr/local/etc/rc.d/syncthing: WARNING: failed to start syncthing
     
    # :> /var/run/syncthing.pid
    
    # chown syncthing:syncthing /var/run/syncthing.pid
    
    # ls -l /var/run/syncthing.pid
    -rwxr-xr-x  1 syncthing  syncthing  0 2018.08.19 01:08 /var/run/syncthing.pid
    # service syncthing start
    Starting syncthing.
    # sockstat -l -4 | grep syncthing
    syncthing syncthing 27499 9  tcp46  *:22000               *:*
    syncthing syncthing 27499 10 udp4   *:18876               *:*
    syncthing syncthing 27499 13 udp4   *:21027               *:*
    syncthing syncthing 27499 20 tcp4   127.0.0.1:8384        *:*
    # cat /var/log/syncthing.log
    [start] 01:08:40 INFO: Generating ECDSA key and certificate for syncthing...
    [MPN4S] 01:08:40 INFO: syncthing v0.14.48 "Dysprosium Dragonfly" (go1.10.3 freebsd-amd64) root@111amd64-default-job-12 2018-08-08 09:19:19 UTC [noupgrade]
    [MPN4S] 01:08:40 INFO: My ID: MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO
    [MPN4S] 01:08:41 INFO: Single thread SHA256 performance is 131 MB/s using minio/sha256-simd (89 MB/s using crypto/sha256).
    [MPN4S] 01:08:41 INFO: Default folder created and/or linked to new config
    [MPN4S] 01:08:41 INFO: Default config saved. Edit /usr/local/etc/syncthing/config.xml to taste or use the GUI
    [MPN4S] 01:08:42 INFO: Hashing performance is 112.85 MB/s
    [MPN4S] 01:08:42 INFO: Updating database schema version from 0 to 2...
    [MPN4S] 01:08:42 INFO: Updated symlink type for 0 index entries and added 0 invalid files to global list
    [MPN4S] 01:08:42 INFO: Finished updating database schema version from 0 to 2
    [MPN4S] 01:08:42 INFO: No stored folder metadata for "default": recalculating
    [MPN4S] 01:08:42 WARNING: Creating directory for "Default Folder" (default): mkdir /Sync/: permission denied
    [MPN4S] 01:08:42 WARNING: Creating folder marker: folder path missing
    [MPN4S] 01:08:42 INFO: Ready to synchronize "Default Folder" (default) (readwrite)
    [MPN4S] 01:08:42 INFO: Overall send rate is unlimited, receive rate is unlimited
    [MPN4S] 01:08:42 INFO: Rate limits do not apply to LAN connections
    [MPN4S] 01:08:42 INFO: Using discovery server https://discovery-v4.syncthing.net/v2/?nolookup&id=LYXKCHX-VI3NYZR-ALCJBHF-WMZYSPK-QG6QJA3-MPFYMSO-U56GTUK-NA2MIAW
    [MPN4S] 01:08:42 INFO: Using discovery server https://discovery-v6.syncthing.net/v2/?nolookup&id=LYXKCHX-VI3NYZR-ALCJBHF-WMZYSPK-QG6QJA3-MPFYMSO-U56GTUK-NA2MIAW
    [MPN4S] 01:08:42 INFO: Using discovery server https://discovery.syncthing.net/v2/?noannounce&id=LYXKCHX-VI3NYZR-ALCJBHF-WMZYSPK-QG6QJA3-MPFYMSO-U56GTUK-NA2MIAW
    [MPN4S] 01:08:42 INFO: TCP listener ([::]:22000) starting
    [MPN4S] 01:08:42 INFO: Relay listener (dynamic+https://relays.syncthing.net/endpoint) starting
    [MPN4S] 01:08:42 WARNING: Error on folder "Default Folder" (default): folder path missing
    [MPN4S] 01:08:42 INFO: Failed initial scan of readwrite folder "Default Folder" (default)
    [MPN4S] 01:08:42 INFO: Device MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO is "blackbox.local" at [dynamic]
    [MPN4S] 01:08:42 INFO: Loading HTTPS certificate: open /usr/local/etc/syncthing/https-cert.pem: no such file or directory
    [MPN4S] 01:08:42 INFO: Creating new HTTPS certificate
    [MPN4S] 01:08:42 INFO: GUI and API listening on 127.0.0.1:8384
    [MPN4S] 01:08:42 INFO: Access the GUI via the following URL: http://127.0.0.1:8384/
    [MPN4S] 01:08:55 INFO: Joined relay relay://11.12.13.14:443
    [MPN4S] 01:09:02 INFO: Detected 1 NAT service
    # service syncthing stop
    Stopping syncthing.
    Waiting for PIDS: 27498.
    # find /usr/local/etc/syncthing
    /usr/local/etc/syncthing
    /usr/local/etc/syncthing/https-cert.pem
    /usr/local/etc/syncthing/https-key.pem
    /usr/local/etc/syncthing/cert.pem
    /usr/local/etc/syncthing/key.pem
    /usr/local/etc/syncthing/config.xml
    /usr/local/etc/syncthing/index-v0.14.0.db
    /usr/local/etc/syncthing/index-v0.14.0.db/MANIFEST-000000
    /usr/local/etc/syncthing/index-v0.14.0.db/LOCK
    /usr/local/etc/syncthing/index-v0.14.0.db/000001.log
    /usr/local/etc/syncthing/index-v0.14.0.db/LOG
    /usr/local/etc/syncthing/index-v0.14.0.db/CURRENT
    # grep '/Sync' /usr/local/etc/syncthing/config.xml
        <folder id="default" label="Default Folder" path="//Sync" type="readwrite" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
    
    # ls /Sync
    ls: /Sync: No such file or directory
    # mkdir /syncthing
    
    # chown syncthing:syncthing /syncthing
    
    # chmod 750 /syncthing
    
    # vi /usr/local/etc/syncthing/config.xml
    
    # grep '/syncthing' /usr/local/etc/syncthing/config.xml
        <folder id="default" label="Default Folder" path="/syncthing" type="readwrite" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="10" ignorePerms="false" autoNormalize="true">
    # grep -i relay /usr/local/etc/syncthing/config.xml
            <relaysEnabled>true</relaysEnabled>
            <relayReconnectIntervalM>10</relayReconnectIntervalM>
    
    # vi /usr/local/etc/syncthing/config.xml
    
    # grep -i relay /usr/local/etc/syncthing/config.xml
            <relaysEnabled>false</relaysEnabled>
            <relayReconnectIntervalM>10</relayReconnectIntervalM>
    
    # grep globalAnnounce /usr/local/etc/syncthing/config.xml
            <globalAnnounceServer>default</globalAnnounceServer>
            <globalAnnounceEnabled>true</globalAnnounceEnabled>
    
    # vi /usr/local/etc/syncthing/config.xml
    
    # grep globalAnnounce /usr/local/etc/syncthing/config.xml
            <globalAnnounceServer>default</globalAnnounceServer>
            <globalAnnounceEnabled>false</globalAnnounceEnabled>
    # service syncthing stop
    Stopping syncthing.
    
    # :> /var/log/syncthing.log
    
    # service syncthing start
    Starting syncthing.
    # cat /var/log/syncthing.log
    [MPN4S] 01:13:38 INFO: syncthing v0.14.48 "Dysprosium Dragonfly" (go1.10.3 freebsd-amd64) root@111amd64-default-job-12 2018-08-08 09:19:19 UTC [noupgrade]
    [MPN4S] 01:13:38 INFO: My ID: MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO
    [MPN4S] 01:13:39 INFO: Single thread SHA256 performance is 131 MB/s using minio/sha256-simd (89 MB/s using crypto/sha256).
    [MPN4S] 01:13:40 INFO: Hashing performance is 112.97 MB/s
    [MPN4S] 01:13:40 INFO: Ready to synchronize "Default Folder" (default) (readwrite)
    [MPN4S] 01:13:40 INFO: Overall send rate is unlimited, receive rate is unlimited
    [MPN4S] 01:13:40 INFO: Rate limits do not apply to LAN connections
    [MPN4S] 01:13:40 INFO: Device MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO is "blackbox.local" at [dynamic]
    [MPN4S] 01:13:40 INFO: TCP listener ([::]:22000) starting
    [MPN4S] 01:13:40 INFO: Completed initial scan of readwrite folder "Default Folder" (default)
    [MPN4S] 01:13:40 INFO: GUI and API listening on 127.0.0.1:8384
    [MPN4S] 01:13:40 INFO: Access the GUI via the following URL: http://127.0.0.1:8384/
    # grep -B 1 -A 3 127.0.0.1 /usr/local/etc/syncthing/config.xml
        <gui enabled="true" tls="false" debugging="false">
            <address>127.0.0.1:8384</address>
            <apikey>2jU5aR4zTJLGdEuSLLmdRGgfCgJaUpUv</apikey>
            <theme>default</theme>
        </gui>
    
    # vi /usr/local/etc/syncthing/config.xml
    
    # grep -B 1 -A 3 10.0.0.100 /usr/local/etc/syncthing/config.xml
        <gui enabled="true" tls="true" debugging="false">
            <address>10.0.0.100:8384</address>
            <apikey>2jU5aR4zTJLGdEuSLLmdRGgfCgJaUpUv</apikey>
            <theme>default</theme>
        </gui>
    # service syncthing stop
    Stopping syncthing.
    
    # :> /var/log/syncthing.log
    
    # service syncthing start
    Starting syncthing.
    
    # cat /var/log/syncthing.log
    [MPN4S] 01:16:20 INFO: syncthing v0.14.48 "Dysprosium Dragonfly" (go1.10.3 freebsd-amd64) root@111amd64-default-job-12 2018-08-08 09:19:19 UTC [noupgrade]
    [MPN4S] 01:16:20 INFO: My ID: MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO
    [MPN4S] 01:16:21 INFO: Single thread SHA256 performance is 131 MB/s using minio/sha256-simd (89 MB/s using crypto/sha256).
    [MPN4S] 01:16:22 INFO: Hashing performance is 113.07 MB/s
    [MPN4S] 01:16:22 INFO: Ready to synchronize "Default Folder" (default) (readwrite)
    [MPN4S] 01:16:22 INFO: Overall send rate is unlimited, receive rate is unlimited
    [MPN4S] 01:16:22 INFO: Rate limits do not apply to LAN connections
    [MPN4S] 01:16:22 INFO: TCP listener ([::]:22000) starting
    [MPN4S] 01:16:22 INFO: Completed initial scan of readwrite folder "Default Folder" (default)
    [MPN4S] 01:16:22 INFO: Device MPN4S65-UQWC5SP-3LR2XDB-T5JNYET-VQEQC3X-DSAUI27-BQQKZQE-BWQ3NAO is "blackbox.local" at [dynamic]
    [MPN4S] 01:16:22 INFO: GUI and API listening on 10.0.0.100:8384
    [MPN4S] 01:16:22 INFO: Access the GUI via the following URL: https://10.0.0.100:8384/
    [MPN4S] 01:16:42 INFO: Detected 1 NAT service
    # find /syncthing -type d
    /syncthing
    /syncthing/SM-A320FL
    /syncthing/SM-A320FL/Camera
    /syncthing/SM-A320FL/Camera/.AutoPortrait
    /syncthing/SM-A320FL/Screenshots
    /syncthing/SM-A320FL/.thumbnails
    /syncthing/SM-A320FL/.stfolder
    rabbitmq-logo.png

    和 ActiveMQ、Apache Kafka 等其它消息系统相比,根据 Google Trends 的趋势来看,RabbitMQ 非常流行。

    rabbitmq-trends.jpg

    今天我想向你展示在 FreeBSD 容器上构建一个带有镜像队列的高度冗余 RabbitMQ 集群的消息系统。

    在 FreeBSD 提供的所有虚拟化方式中(VirtualBox / Bhyve / QEMU / Jail / Docker),我选择了最轻量的 FreeBSD 容器 —— Jail :🙂:

    图例依旧保持不变。

    在 host 系统上以 root 用户执行的命令:

    在 host 系统上以 普通用户 执行的命令:

    在 rabbitX Jail 中执行的命令:

    Jail 配置

    首先我们将创建用于本次部署的基础 Jail。host 系统与这些 Jail 容器 都使用 FreeBSD 11.2-RELEASE 系统。

    我们现在已经有了 2 个空的、干净的 Jail。

    接下来要把这些 Jail 的配置加入 /etc/jail.conf 文件中。

    因为我使用的是笔记本作为 Jail 的宿主机,所以 Jails 将会绑定无线网卡 wlan0,并使用 192.168.43.10X 这些地址。同时我也添加了 10.0.0.10X 这组地址,主要是为了撰写本文时操作更方便。

    这就是配置完成后的 /etc/jail.conf 文件的样子。

    现在我们可以启动这些 Jail 了。

    Jail 已正常运行。

    现在是时候给 Jail 添加 DNS 服务器,以便它们能够访问互联网。

    现在我们将把软件包源从 'quarterly' 切换到 'latest'。

    安装 RabbitMQ 安装

    现在我们可以安装包 RabbitMQ 了。

    让我们验证包 RabbitMQ 是否安装成功。

    配置 RabbitMQ

    接下来我们将在 Jail 中配置 /etc/hosts 文件。

    ……再简单验证。

    由于我们已经安装了包 RabbitMQ,现在需要启用并启动它。

    如我们所见,需要在每个 Jail 的 /etc/rc.conf 文件中设置 rabbitmq_enable=YES。

    现在我们可以在 Jail 中启动 RabbitMQ 了。

    现在我们有四个 RabbitMQ 实例已经启动并运行。

    默认启用的插件列表:无。

    RabbitMQ 插件

    现在是时候启用 Web 界面插件了。

    现在我们已经在每个 RabbitMQ FreeBSD Jail 中启用了 Web 界面插件。

    大写的 ‘E’ 表示这是我们主动启用的插件,而小写的 ‘e’ 表示该插件仅作为其他我们请求启用的插件的依赖而被启用。

    现在——为了创建集群——我们需要这些 RabbitMQ 实例共享相同的 ERLANG cookie。在 FreeBSD 系统上,ERLANG cookie 位于 /var/db/rabbitmq/.erlang.cookie。

    我们需要先停止 RabbitMQ,以便更改 ERLANG cookie。

    接下来在每个 FreeBSD Jail 上设置相同的 ERLANG cookie。

    ……现在我们需要再次启动它们。

    快速验证一下。

    RabbitMQ 管理用户

    现在我们将在 RabbitMQ 实例中创建管理用户 admin。

    我们现在应该可以登录 http://192.168.43.101:15672/(或者 http://10.0.0.101:15672/)的 RabbitMQ 管理页面了。

    01-rabbitmq-login.png

    登录后,将显示给你实用的 RabbitMQ 仪表板。

    02-rabbitmq-dashboard.png

    RabbitMQ 集群设置

    接下来我们将创建 RabbitMQ 集群。

    首先,我们需要停止 RabbitMQ 的“应用程序”,以便加入集群。

    现在我们已经形成了两节点的 RabbitMQ 集群。接下来我们将其重命名为 cluster。

    下面是在 Web 界面中查看我们集群的样子。

    08-rabbitmq-cluster.png

    RabbitMQ 高可用策略

    要在 RabbitMQ 中实现 高可用(镜像)队列,需要创建 Policy(策略)。我们将声明 Policy ha,它匹配名称以 ha- 前缀开头的队列,从而将这些队列配置为在集群中的两个节点上镜像。

    创建该 Policy 的命令如下:

    ……或者,你也可以使用 Web 界面来创建该策略。

    无论使用哪种方法,最终都会得到所需的 Policy ha,如下所示。

    03-rabbitmq-policy.png

    发送消息到队列

    现在我们已经有了两节点的 RabbitMQ 集群,并且为名称以 ha- 前缀开头的队列启用了高可用功能。接下来我们将测试 RabbitMQ 设置,使用 send.go 脚本创建并发送消息到队列——正如你可能猜到的,这个脚本是用 Go 语言编写的。我们需要在 host 系统上安装 Go 语言。

    安装 Go 语言

    这是 send.go 脚本——我们将使用它向 ha-default 队列发送 10 条消息。它基于教程 RabbitMQ Hello World。

    接下来我们将运行它。

    我们缺少 Go 语言的包 amqp。

    需要从页面 https://github.com/streadway/amqp 下载。我们将通过下载整个 ZIP 包的方式获取它。

    我们还需要确保 PATH 和 GOPATH 配置正确。为此,需要将它们写入你的交互式 shell 配置文件中。

    现在我们可以继续向队列发送消息了。

    ha-default 队列已创建并发送了 10 条消息。

    04-rabbitmq-queue

    现在我们需要从队列中“接收”这些消息,这时 receive.go 脚本就派上用场了。它同样基于教程 RabbitMQ Hello World 。

    这是运行后的输出。该程序会一直运行,直到你使用 CTRL-C 快捷键手动结束它。

    如果你仔细查看源码,你可能已经注意到,我是在 rabbit1 节点(10.0.0.101)“发送”消息,而在 rabbit2 节点(10.0.0.102)“接收”这些消息的。

    简单基准测试

    接下来我们将进行简单的基准测试:保持 receive.go 脚本运行,同时修改 send.go 脚本的 for 循环,发送 100000 条消息。

    ……现在开始发送消息。

    这个简单基准测试的结果如下。

    05-rabbitmq-benchmark.png

    在两个 FreeBSD Jails 内,这个 RabbitMQ 集群实例大约可以处理每秒 4000-5000 条消息。

    高可用性测试

    现在我们将测试 RabbitMQ 集群的高可用性。

    目前 ha-default 队列在 rabbit1 节点上。接下来我们将停止 rabbit1 Jail,观察 RabbitMQ Web 界面的反应。

    我们的 ha-default 队列在几秒钟内切换到了 rabbit2 节点 —— 高可用功能按预期工作。

    06-rabbitmq-ha-node-fail.png

    接下来启动 rabbit1 Jail,以恢复冗余。

    07-rabbitmq-ha-node-back.png

    ha-default 队列恢复了冗余,显示 +1 标记,但仍然位于 rabbit2 节点。

    ……最后一点小庆祝——这是我博客的第 50 篇文章(不包含 Valuable News 系列) :🙂:

    更新 1 – 本月 RabbitMQ 动态

    文章 RabbitMQ Cluster on FreeBSD Containers 被收录在 This Month in RabbitMQ – July 2019 中。

    感谢提及!

    更新 2 – 降低 RabbitMQ CPU 使用率

    如 Felix Ehlers 在 Twitter 所报告,设置变量 RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS="+sbwt none" ,可以降低 RabbitMQ 的 CPU 使用率。

    RabbitMQ Cluster on FreeBSD Containers
    《Distributed Object Storage with Minio on FreeBSD》
    改进笔记本睡眠管理

    正在进行

    作为更大规模的 笔记本改进项目 的一部分,我们正在开发对更新的 S0ix 睡眠/休眠状态的支持。许多现代笔记本采用的是 S0ix 状态,而非较早的 S3 标准。在 S0ix 状态下,操作系统需要确定哪些设备需要进入睡眠状态,才能关闭 CPU;只有当所有条件满足后,固件才会自动关闭 CPU。

    你可以在 此处关注项目进展。

    将 MIT Kerberos 引入 FreeBSD

    正在进行

    实现更常用的 MIT Kerberos,以提升与其他操作系统的互操作性。

    改进 bhyve 虚拟机监视器对 libvirt 的支持

    正在进行

    改进虚拟化 API(libvirt),使其具备管理 bhyve 虚拟机完整生命周期的能力,包括创建、启动、关机和销毁。该项目还将增强 libvirt 对 bhyve 虚拟机基础网络配置的支持。

    在 FreeBSD 上管理 bhyve 虚拟机监视器的图形用户界面(GUI)

    正在进行

    该项目将为 FreeBSD 开发一款类似 Proxmox 的图形界面,专为管理 bhyve 和 jail 而设计。系统将采用 Golang 进行后端开发,并使用 Svelte 构建现代、响应式的前端界面。

    项目的目标是提供直观而强大的图形用户界面,以简化虚拟化和容器化操作。现代化的 GUI 将使 FreeBSD 对系统管理员更为友好,并增强其在虚拟化领域的竞争力。

    你可以在 此处关注项目进展。

    FreeBSD 用户空间开发

    正在进行

    FreeBSD 向来被认为是一款稳定性极高、安全可靠的服务器操作系统。毋庸置疑,FreeBSD 也完全可以作为桌面操作系统使用。FreeBSD 项目早已意识到桌面应用的需求,因此发起了用户空间开发计划,以提升用户体验。这一计划也与提升 FreeBSD 在现代笔记本电脑上表现的更大规模赞助工作相契合。

    改进 FreeBSD 上的 OpenJDK

    正在进行

    本项目的主要目标是改善 OpenJDK 在 FreeBSD/amd64 和 FreeBSD/arm64 平台上的支持。为此,我们将与 FreeBSD 及 OpenJDK 社区密切合作,共同识别并解决问题和缺失的功能。在可能的情况下,相关工作将提交至上游,并且我们的一个重要目标是让 OpenJDK 的 JCK 测试套件在 FreeBSD 上全部通过。

    此外,该项目还着力于在 FreeBSD 平台上打造强大的 Java 生态系统。我们将通过加入 FreeBSD 企业工作组、通过邮件列表和博客定期发布更新,以及广泛征集想法和测试反馈,与社区保持积极互动。同时,项目还包括为 FreeBSD 上的 OpenJDK 搭建并维护持续集成系统。

    OCI 容器支持

    正在进行

    基于 Jail/Bhyve 实现 OCI 容器,支持 Podman 和 Buildah

    联系人: Doug Rabson [email protected]

    开放容器计划 (OCI) 为云原生容器格式和运行时制定了开放的行业标准,来确保平台的一致性。OCI 工作组 正在为 FreeBSD 制定这些标准,利用 jail 进行实现,并有可能通过 FreeBSD 的 bhyve 虚拟化管理程序支持轻量级虚拟机——可在 FreeBSD 主机上的容器中运行 FreeBSD 以外的其他操作系统。

    FreeBSD 项目成员 Doug Rabson 开发了 ocijail,这是一种兼容 OCI 的 FreeBSD jail 运行时实验工具。该工具旨在与容器管理系统(如 Podman 和 Buildah)集成,提供完善的容器管理体验。

    在 OCI 容器中运行应用程序的优势:

    • 标准化: 确保不同环境间的兼容性和互操作性,简化开发和部署过程。

    • 可移植性: 封装应用程序及其依赖项,使其能够在任何支持 OCI 的环境中一致运行。

    • 高效性: 轻量且高效,具备快速启动时间和最佳资源利用率,减少了与传统虚拟机相比的开销。

    • 隔离性: 提供类似虚拟机的强隔离功能,但开销较小,适合微服务和现代架构。它确保应用程序独立安全运行,避免冲突,增强了系统稳定性。

    Doug Rabson 的 GitHub 仓库 有与 Podman 和 Buildah 集成的初始代码。你还可以观看 Doug Rabson 在 Open Source Summit Seattle 前的 Container Plumbing Day 活动上关于实现 ocijail 的演讲 这里。

    Doug 还撰写了一篇 文章,讨论了预构建的 FreeBSD OCI 容器镜像的实现功能。FreeBSD 项目设想将使用现有的容器镜像基础设施(例如 Docker Hub 和 GitHub 容器注册表)进行管理,或者通过 FreeBSD 自有基础设施托管镜像注册表。

    更多信息请访问:ocijail (GitHub)

    UnionFS 稳定性与增强

    正在进行

    UnionFS 项目旨在使其稳定、增强其在 FreeBSD 上的实用性,重点包括:支持对只读文件系统的表面修改,支持多个共享相同基础的 jail 并简化升级,以及通过分层的预打包镜像促进容器场景的实现

    联系人: Olivier Certner [email protected]

    由 Olivier Certner 领导的 FreeBSD 上的 UnionFS 项目专注于增强和稳定 UnionFS 的功能,特别是涉及分层文件系统、jail、容器和存储优化的场景。Jason Harmening 多年来一直致力于 UnionFS 的开发,持续解决诸如 vnode 锁、whiteout 管理和其他系统性问题等关键问题。该项目涉及大量代码重写,并进行了精心的协调,以确保变更的合理性和与项目目标的一致性。重要的审查包括 D44288、D44601、D44788 和 D45398。

    项目的主要贡献:

    1. UnionFS 功能:

      • 表面修改: 允许对只读文件系统(例如 CDROM、NFS)进行更改,而不修改原始文件。适用于创建临时/永久的私人副本。

      • Jail: 支持多个 jail 共享基础文件系统,简化更新,提高存储效率。

      • 容器: 支持具有可修改顶层的预打包容器镜像,类似于 Docker。

      • 存储优化: 将 HDD 支持的文件系统堆叠在 SSD 支持的文件系统上,优化存储使用,同时利用二者的优势。

    2. 协调与开发:

      • Olivier Certner 与 Jason Harmening 协作,继续开发和稳定 UnionFS。Certner 的方法是尽量减少变更的范围,同时确保变更与重写 UnionFS 大部分代码的总体目标相一致。

    3. 审查贡献:

      • : 实现了 VOP_UNP_*,并移除了对 VSOCK vnode 的特殊处理。

      • : 解决了对 vnode 私有数据的非法访问问题,并提出了强制卸载的测试方案。

      • : 修复了 unionfs_rename 中的多个锁定问题,确保变更最小化以保证稳定性。

    4. 咨询:

      • Whiteout 处理 (): 与 Kirk McKusick 和 Jason Harmening 合作,解决了在 tmpfs 中 rename/rmdir 操作期间 whiteout 条目的问题,涉及 UnionFS 导出的元数据。

    此项目是一项全方位的努力,旨在确保 UnionFS 可靠、高效。适用于 FreeBSD 的现代用例,包括 jail、容器和复杂的存储配置。

    OpenZFS 分级速率限制

    正在进行

    该项目旨在通过引入类似配额可配置的分级速率限制,控制读/写操作次数和读/写带宽,从而提升系统性能和资源管理

    联系人: Pawel Dawidek [email protected]

    FreeBSD 的 OpenZFS 分级速率限制项目旨在通过引入分级速率限制大幅提升 OpenZFS 文件系统的功能。这些速率限制可像配额一样进行配置,用于控制读/写操作次数和读/写带宽,从而提高系统性能,优化资源管理。

    OpenZFS 尤为适合大规模和高要求的应用程序,如虚拟化和容器化(使用 jail 框架),这些应用程序需要对资源消耗进行精确控制。该项目将实现限制读/写/总操作次数以及读/写/总带宽的功能。限制将在 ZPL(ZFS POSIX 层)强制执行,确保下层数据集不会超过其父数据集上配置的限制。

    主要功能:

    • 分级强制执行: 限制将在 ZPL 层强制执行,确保下层数据集不会超过其父数据集上配置的限制。

    • 六个新属性:

      • ratelimit bw read: 限制每秒读取的字节数。

      • ratelimit bw write: 限制每秒写入的字节数。

      • ratelimit bw total: 限制每秒可以读取或写入的总字节数。

      • ratelimit op read: 限制每秒的读操作次数(数据或元数据读取)。

      • ratelimit op write: 限制每秒的写操作次数(数据或元数据写入)。

      • ratelimit op total: 限制每秒读或写操作(数据或元数据)的总次数。

    这些增强功能旨在提供对资源消耗的精确控制,使 OpenZFS 更加适用于高需求环境。通过实施分级速率限制,该项目确保了资源管理的高效和有效性,提升了 FreeBSD 操作系统的整体稳健性和可靠性。

    更多信息: OpenZFS 分级速率限制 (GitHub)

    AMD IOMMU

    正在进行

    开发完整的 FreeBSD AMD IOMMU(输入输出内存管理单元)驱动的项目

    联系人: Konstantin Belousov [email protected]

    由 Advanced Micro Devices(AMD)与 FreeBSD 基金会共同发起的新项目,旨在开发完整的 FreeBSD AMD IOMMU(输入输出内存管理单元)驱动程序。此项目的目标是使 FreeBSD 完全支持超过 256 核的系统,并集成高级功能,如 CPU 映射和 bhyve 虚拟化支持。

    开发 AMD IOMMU 驱动对于提升 FreeBSD 管理高核数系统的能力至关重要,有助于优化性能并确保强大的资源管理。该驱动将促进硬件资源的高效分配,改善 FreeBSD 在高需求环境中的整体功能性和可扩展性。

    更多信息: Konstantin Belousov 的代码提交 (GitHub)

    FreeBSD 图形化安装程序

    正在进行

    开发 FreeBSD 图形化安装界面的项目

    联系人: Pierre Pronchery [email protected]

    对于首次尝试新操作系统的用户来说,他们面临的第一个挑战是安装过程,安装过程也是他们对系统的原初印象来源。如今,大多数操作系统安装程序都搭载了图形界面,如 RedHat Enterprise Linux、Ubuntu 和 Debian GNU/Linux 等流行系统中所见。这种图形化方式在 UNIX 系统(包括 FreeBSD)中也变得越来越普遍。无论用户的技术水平如何,安装过程对于公众对该平台的看法至关重要。

    有多个项目已将 FreeBSD 转化为面向桌面的系统,其中 GhostBSD 就是个重要的例子,它提供了图形化安装程序。然而,GhostBSD 的安装程序依赖于由 Python 编写的 Gtk+ 界面,如果将其整合到 FreeBSD 常规的镜像生成过程中,可能会大幅增加安装介质的体积。此外,这一方法还需要在 Ports 中引入、维护新的项目。

    为了解决这个问题,提出了一个 BSD 许可证下 man: Xdialog [1] 的替代方案,并借鉴了现有的 man: bsdinstall [8] 和 man: bsdconfig [8] 工具的知识。这个新工具名为 man: gbsddialog [1],将提供图形化安装功能,同时与当前的安装程序基础设施共享资源。与 2006 年发布的,过时的 Xdialog 不同,gbsddialog 提供了一个现代化、高效的替代方案,确保占用最小的空间并保持 FreeBSD 的精简镜像生成流程。

    在 FreeBSD 14.0 版本发布后,完成了概念验证原型。FreeBSD 基金会随后用两个月的时间完成了一个可用的实现。该项目最终在 2024 年 AsiaBSDCon 大会的 WIP(半成品)环节中展示了功能齐全的图形化安装程序,标志着 FreeBSD 安装过程在用户友好性和视觉吸引力方面的重大进展。

    更多信息: 图形安装程序 (GitHub)

    FreeBSD 对 RISC-V 64 位的支持

    正在进行

    为 64 位 RISC-V 架构提供支持的项目

    联系人: Mitchell Horne

    联系人: Ruslan Bukin

    联系人: Jari Sihvola

    FreeBSD/RISC-V 项目旨在为 RISC-V 指令集架构 提供 FreeBSD 的支持。

    更多信息: RISC-V 支持 (FreeBSD.org)

    FreeBSD 的视觉辅助子系统

    正在进行

    为盲人、低视力和色盲用户提供子系统的项目

    联系人: Joe Mingrone

    该项目是为盲人、低视力和色盲用户提供“视觉辅助子系统”的开端。新功能将包括盲文刷新显示框架、虚拟终端控制台的通信通道、语音合成器、高对比度 TUI 工具和一本文档化 FreeBSD 上可用辅助技术的辅助技术书籍。

    项目交付物包括:

    • 修改基础系统中的 TUI 工具,以提供高对比度选项,可能处理 GUI 终端模拟器和环境变量 vt(4) 的“NO COLOR”。更新手册描述新功能。

    • 新选项可以通过启动对话框菜单选择“安装”和“高对比度安装”来以高对比度运行 bsdinstall(8)。

    • 为 vt(4) 和语音合成器提供新通信方法。手册将更新以描述新功能。

    • 盲文设备框架,可能作为 https://brltty.app 的 Port,具有其盲文刷新显示“驱动程序”。如果时间允许,还包括其语音能力功能。

    • 新工具实现 bsdinstall(8) 对话框,作为适合屏幕阅读器的简单文本界面。

    • 新的“语音安装”选项通过新的 CLI 工具运行 bsdinstall(8)。该功能将作为概念验证提供(会议和社交网络的视频和演示),因为语音合成器和 BRLTTY 在类似 GPL 的许可下发布。

    • 在文档库中新增“可访问性”书籍,以描述新的视觉辅助子系统和 Ports 中的工具。

    改进音频

    正在进行 中

    加强 FreeBSD 的音频堆栈,以改善对现代音频硬件和软件应用程序的支持

    联系人: Christos Margiolis [email protected]

    尽管以其高质量著称,但 FreeBSD 的音频堆栈一直处于欠缺维护的状态。一个新项目旨在全面增强该堆栈,解决框架、实用程序和内核驱动程序的 bug,以改善整体功能。

    近期开发中已经取得了几项重大改进。FreeBSD 14.1-RELEASE 和 14-STABLE 现已支持异步音频设备分离,提供了更灵活的音频设备管理。过时的“snd_clone”框架已被 DEVFS_CDEVPRIV(9) 取代,该框架也随 FreeBSD 14.1-RELEASE 和 14-STABLE 一同发布,使设备管理框架现代化。

    音频系统进行了多次崩溃和 bug 修复,并且在笔记本电脑上,对 man: snd_hda [4] 的支持得到了改善,确保了更稳定可靠的音频性能。OSS API 的增强改善了 SNDCTL_AUDIOINFO 和 SNDCTL_ENGINEINFO IOCTL 的实现,从而提高了兼容性和功能。

    新实现包括启动 man: audio [3],一个 OSS 音频和 MIDI 库,以及接管 man: virtual_oss [8] 的维护:这两者都为扩展 FreeBSD 音频堆栈的功能作出了贡献。

    展望未来,该项目计划开发新的 man: audio [8] 工具和蓝牙管理工具,进一步改善用户体验。还计划对 man: mixer [3] 和 man: mixer [8] 进行增强。此外,项目将改进文档和测试套件,以确保全面的测试和用户指导。还在进行一项实验尝试,以自动化 man: snd_hda [4] 引脚补丁,如果成功,将显著简化音频配置。

    这些努力旨在全面提升 FreeBSD 的音频能力,确保更好的用户支持和功能,并巩固 FreeBSD 在高质量音频性能方面的声誉。

    更多信息: 音频堆栈改进 (GitHub)

    完善 CI

    正在进行

    改进持续集成 (CI) 基础设施,以确保更可靠和高效的软件开发和测试过程

    联系人: Li-Wen Hsu: [email protected]

    在 2024 年第一季度,我们与项目贡献者和开发人员合作,解决他们的测试需求。同时,我们与外部项目和公司合作,通过在 FreeBSD 上进行更多测试来增强他们的产品。

    在 2024 年第一季度,FreeBSD 项目增强了其持续集成 (CI) 基础设施。由 Christos Margiolis 领导的团队与贡献者和外部项目合作,以满足测试需求并改善在 FreeBSD 上的产品测试。

    关键成就包括使用来自退役机器的零件升级测试虚拟机的磁盘和内存,将 stable/13 任务的构建环境更新为 13.3-RELEASE,并将主分支上的 i386 构建过渡为使用 amd64 的交叉构建。

    正在进行 的努力包括合并关键审查,向 CI 集群添加新硬件,以及设计预提交 CI 系统和拉取/合并请求系统。团队还在致力于利用 CI 集群构建发布工件,简化 CI/测试环境设置,以及重新设计硬件测试实验室。

    未来计划包括收集 CI 任务和想法,为虚拟机客机测试设置公共网络访问,实现裸金属硬件测试套件,添加针对 -CURRENT 的 DRM Port 构建测试,以及运行 ztest 测试。团队的目标是改善 FreeBSD 在 CI 流水线中的支持,并与托管的 CI 提供商合作。

    更多信息: 持续集成 (GitHub)

    将 FreeBSD 作为 cloud-init 一级平台

    正在进行

    增强对 cloud-init 的支持,使 FreeBSD 成为 Tier I 平台,改善 FreeBSD 在云环境中的集成和可用性

    联系人: Mina Galić [email protected]

    Cloud-init 现已成为在云中设置服务器的标准。在过去一年半的时间里,FreeBSD 在支持 cloud-init 方面取得了显著进展。今年的重点是同 cloud-init 开发者和 FreeBSD 基金会密切合作,增强 FreeBSD,使 cloud-init 团队能够直接测试未来对 FreeBSD 代码路径的更改。

    为此,FreeBSD 必须在 LXD(和 Incus)的控制下运行,并由 lxd-agent(或 incus-agent)管理。最近,已经取得了一些可见的改进。一个小型测试框架在 sh 中开发,正在逐步迁移到 OpenTofu/Terraform。该框架安装测试了 cloud-init-devel 和 cloud-init 的最新版本。为支持这一点,创建了专用的公共代码库,包含 FreeBSD 13 和 14 在 amd64 和 aarch64 上的 cloud-init-devel 和 cloud-init 的最新版本。

    此外,Linux vsock 测试框架也已移植到 FreeBSD。基于 HyperV Socket 驱动程序创建了 VirtIO Socket 驱动程序的驱动程序框架,导致 HyperV 套接字的多个改进。这些改进已部分接受,但仍需更多工作。

    最新的 cloud-init 24.1 系列经过测试并发布,修复了长期存在的错误,例如将 /run/cloud-init 移动到 BSD 上的 /var/run/cloud-init,并纠正了 user_groups 的参数 homedir。此次发布还包括社区贡献的 OpenBSD 代码路径的多个修复。

    展望未来,这项工作涉及几个关键任务。完成 FreeBSD VirtIO Socket 驱动程序和修复 Go 的运行时以支持 FreeBSD 上的 VirtIO 是首要任务。将 lxd-agent 的依赖项及 lxd-agent 本身移植到 FreeBSD 也至关重要。这些努力将与对 BSD 上 cloud-init 的进一步改进和在不同云提供商上的额外测试交替进行。

    更多信息: Cloud-Init (GitHub)

    FreeBSD 上的 OpenStack

    正在进行

    FreeBSD 上的 OpenStack 项目旨在将 OpenStack 云基础设施与 FreeBSD 操作系统无缝集成,利用 FreeBSD 的独特功能,同时保持与 OpenStack 标准的兼容性

    联系人: Chih-Hsin Chang [email protected],Li-Wen Hsu [email protected]

    第一季度:

    在 2024 年第一季度,该项目取得了重大进展。提交了 BSDCan 2024 的提案,团队参加了 AsiaBSDCon 2024,分享了移植经验并收集了有价值的反馈,这帮助完善了项目的方向。第一阶段的任务进行了审查,进行了必要的调整,并将第二和第三阶段的计划与长期目标进行了对齐。一项关键技术成就是验证了 bhyve 串口控制台通过 TCP 的功能。还制作了个演示视频,展示了项目的进展和特性。

    第二季度:

    第二季度继续取得进展。团队在 BSDCan 2024 上介绍了“朝着强大的基于 FreeBSD 的云:移植 OpenStack 组件”,这增加了项目的可见性,并吸引了潜在贡献者的兴趣。概念验证(POC)站点从单节点设置扩展到三节点设置,涉及详细的环境设置和网络规划。还启动了将基础迁移到 FreeBSD 15.0-CURRENT 的工作,以保持与最新 FreeBSD 发展的对齐。

    此外,手动安装步骤和代码补丁开始转换为 FreeBSD Port,简化安装过程。一个重要的里程碑是启动了对 FreeBSD 实例和 OpenStack Ironic 服务主机进行裸机配置的工作。

    后续计划:

    展望下一个季度,重点将放在完善这些进展并进一步增强项目的稳健性和易用性。具体计划包括将 OpenStack 组件从 Xena 版本升级到更近期的版本,因为 Xena 正接近生命周期的尽头。欢迎社区的建议和贡献,以帮助实现这些目标。

    更多信息: OpenStack (GitHub)

    WiFi 更新 – Intel 驱动程序和 802.11ac

    正在进行

    此更新支持了当前一代 Intel WiFi 设备和 802.11ac 标准,来改善无线连接性

    联系人: Björn Zeeb [email protected]

    在 2023 年 11 月,FreeBSD 基金会启动了一项重大举措,来改善 iwlwifi 驱动程序,该驱动程序对支持 FreeBSD 上的 Intel Wi-Fi 芯片至关重要。这个项目由 FreeBSD 开发者 Cheng Cui 领导,并与 Björn Zeeb 合作,旨在通过多个关键里程碑增强 FreeBSD 的无线功能。

    项目的主要目标之一是解决影响 iwlwifi 驱动程序的多个关键问题报告(PR)。在 PR 271979、273985、274382 和 275710 中记录的问题通过系统化和创新的调试技术成功解决。例如,使用铝箔包裹的纸板隔离信号是一种新颖的方法,证明在识别和修复这些问题上效果显著。

    该项目还专注于提高系统稳定性。审查和实施补丁显著改善了 FreeBSD 版本 13.3-RELEASE 和即将发布的 14.1 的稳定性。项目强调启用硬件支持的加密功能,这涉及创建 PR 277095 和 277100,以应对复杂的调试场景。

    改善对 802.11n 标准的支持是另一个重点领域。该项目通过利用深厚的领域专业知识并采用 Linux 中的 Driver API 跟踪等新调试技术,解决了 PR 276083。这一增强对于推动项目目标和改善 FreeBSD 的无线性能至关重要。

    此外,该项目在确保 FreeBSD 13.3 成功发布方面发挥了重要作用。通过重现用户报告的问题并测试后续修复,项目为操作系统的整体可靠性和性能做出了贡献。

    增强 iwlwifi 驱动程序的努力改善了 FreeBSD 对 Intel Wi-Fi 的支持。该项目确保了用户更好的无线性能和稳定性。持续的工作将继续提升 FreeBSD 的网络功能,使其成为更强大、更可靠的操作系统。

    更多信息: Wi-Fi 增强(FreeBSD 基金会)


    以下为 已完成 部分


    改进 Bhyve

    对 FreeBSD 虚拟机监视器的各种改进

    联系人: Chris Moerz

    I/O 性能测量

    最近,Bhyve 生产用户之间的讨论强调了正式 I/O 性能分析的必要性。作为回应,团队开始使用一组 shell 脚本和 benchmarks/fio 包测试不同的配置。重点评估不同的存储后端、内存设置、CPU 固定选项以及支持存储和虚拟磁盘的块大小。团队还比较了不同 CPU 制造商以及客户和主机环境的性能。

    虚拟机工具

    FreeBSD 基金会的企业工作组认为需要类似于 jail 的 Bhyve 工具。这促成了“vmstated”的开发,这是一款使用基本 FreeBSD 工具构建的守护进程和管理实用程序。Vmstated 通过 UCL 配置,提供灵活的虚拟机管理,具有类似于 jail 的命令集和状态转换钩子等功能。该工具已在 ports 中作为 sysutils/vmstated 提供,并在 GitHub 上持续更新。欢迎贡献和反馈。

    文档更新

    对 FreeBSD 手册和 Porter 手册进行了几次更新,重点关注虚拟化、Bhyve 配置和管理 Bhyve 客户。正在进行 Bhyve 手册页结构的更新审查,并计划进一步改进内容。欢迎对此次更新提出反馈。

    为 arm64 客户创建的扁平设备树

    Mark Johnston 和 Andrew Turner 合作创建了构建 arm64 bhyve 客户的扁平设备树(FDT)的基本例程。FDT 描述了不同的硬件组件,例如 CPU、内存、UART、PCIe 控制器、中断控制器和平台定时器,客户操作系统应当了解这些组件。

    更多信息: Bhyve 更新(GitHub)

    在 Azure 和 Hyper-V 上的 FreeBSD

    自动化 Azure Marketplace 中 FreeBSD 镜像的构建过程

    联系人:

    • Microsoft FreeBSD 集成服务团队:[email protected]

    • FreeBSD Azure 发布工程团队:[email protected]

    • Wei Hu: [email protected]

    • Souradeep Chakrabarti: [email protected]

    • Li-Wen Hsu: [email protected]

    在第一季度,团队成功解决了所有阻塞问题,并在 Azure Marketplace 上发布了 FreeBSD 13.3-RELEASE,使其可以在云环境中供用户使用。

    进行中的工作

    团队目前专注于几个关键任务:

    • 自动化镜像构建和发布过程: 正在进行 的努力旨在自动化镜像构建和发布过程,以将这些改进合并到 FreeBSD 的 src/release/ 仓库中。

    • 构建和发布快照构建: 快照构建正在开发和发布到 Azure 社区画廊,为用户提供最新的开发和更新。

    移植 .NET (dotnet)

    将“dotnet”原生移植到 FreeBSD,初始版本为 8,后续版本的移植 正在进行

    联系人: Gleb Popov [email protected]

    在 FreeBSD 上对 .NET 的支持(dotnet)使开发者能够选择自己喜欢的平台而不受限制。这种兼容性使他们能够利用 FreeBSD 独特的优势,同时保持与 .NET 一致的开发环境。

    新的 .NET 原生移植目前可用于 amd64 架构(对 aarch64 的支持 正在进行 中),将 .NET 运行时版本 8 带入 FreeBSD。这确保了完全兼容,同时利用了 FreeBSD 的性能和安全特性,使开发者能够充分利用 FreeBSD 的功能。

    将 .NET 移植到 FreeBSD 是一个协作努力,涉及主要社区贡献者。Gleb Popov([email protected])维护 .NET 移植,thefrank、Naram Qashat([email protected])和 Szczepan Ćwikliński(sec)也做出了重要贡献。团队与 dotnet 上游项目积极合作,包括在 GitHub 上提交 PR。他们的共同努力对实现 .NET 在 FreeBSD 上的运行至关重要。

    更多信息: dotnet (GitHub)

    FreeBSD 集群现代化

    加强 FreeBSD 项目基础设施、提升其能力,并为用户提供更好的服务的倡议

    联系人: Joseph Mingrone [email protected] 和 Philip Paeps [email protected]

    FreeBSD 基金会投资 10 余万美元,在芝加哥部署了一套服务器集群。此项投资旨在完善 FreeBSD 项目的基础设施、提升其能力,并为用户提供更好的服务。为了支持这一扩展,基金会与 NYI 合作,后者慷慨地在其芝加哥设施中提供了四个机架。

    新的集群配置旨在优化 FreeBSD 项目的运营效率,包括:

    • 两台路由器: 用于引导网络流量。

    • 五个软件包构建器: 旨在加速软件包发布过程。

    • 三台通用服务器: 这些服务器将提升 FreeBSD 项目面向公众和开发者的服务(如 Bugzilla、Git、Phabricator、Wiki 等)的可用性和性能。

    • 两个软件包镜像站: 一个托管在芝加哥的新集群,另一个托管在加州的 ISC。这些是 FreeBSD 项目日益扩大的 pkg.FreeBSD.org 和 download.FreeBSD.org 服务器网络的一部分,战略性地分布在全球,可提供更快的软件包下载速度。

    • 两台 CI 服务器: 以提高自动化代码测试的速度和效率。

    • 一台管理堡垒服务器: 这是管理集群的安全入口点,运行集群管理团队(clusteradm)工具、集群 DNS、监控以及其他管理系统所需的服务。

    这一硬件配置预计将显著提升 FreeBSD 项目的处理能力和服务响应速度。

    FreeBSD clusteradm 团队在新集群的集成阶段发挥了关键作用。

    • 硬件兼容性和固件调试: 为确保服务器固件与 FreeBSD 兼容,需要克服初期面临的多个障碍。集群依赖于能够网络启动机器,并要求可靠的带外管理。

    • 网络配置和自动化: 服务器能够可靠启动后,进行了网络配置,包括集群内部 DNS、数据包过滤规则和与互联网的 BGP 会话。

    • 自动化和系统配置: 团队的自动化工具大大简化了服务器的安装和配置。在使用临时 FreeBSD 安装克服了一些启动问题后,服务器被网络启动到集群安装镜像中,并使用标准集群构建进行安装。

    • 监控和管理集成: 团队在管理服务器上安装和配置了监控代理,将新站点集成到项目的中央监控系统中。这使得集群的管理和故障排除更加高效,确保了稳定性和性能。

    • 最终系统安装和网络服务设置: 团队通过使用工具自动化重新安装管理服务器,设置路由和防火墙配置,并在光纤上行链路上启用 BGP 会话,完成了集成工作。这一设置确保了新集群的运行,并优化了性能和安全性。

    Olivier Certner 的杂项更新

    已完成

    FreeBSD 源代码树各部分的杂项更新

    联系人: Olivier Certner [email protected]

    在 2024 年第二季度,长期承包商 Olivier Certner 在系统的多个不同部分积极工作:

    • rtprio(2):将每个运行队列的队列数量从 64 升级到 256。

    • Vnode 回收/ZFS ARC 回收: 审查了 bug #275594 的修复,与上游沟通以获取和测试回移,并发出了一份 EN 并作为 13.3-RELEASE-p2 应用,同时开始了长期工作以改进 vnode 回收机制,并确保 ZFS 传递正确的信息。

    • ULE 调度器: 更新为在单个运行队列上工作,而不是为满足 POSIX 合规性而使用 3 个运行队列,以处理 SCHED_FIFO/SCHED_RR 优先级级别的数量。

      • 杂项:* 进行了多达 26 项评审、软件包更新,并调查了 DRM 问题。

    • 在 FreeBSD Journal 发布了 。

    FreeBSD 14 CIS 基准(互联网安全中心)

    已完成

    这是个全面的安全加固指南,旨在帮助安全高效地配置 FreeBSD 系统。

    联系人: Moin Rahman [email protected]

    此新 CIS 基准涵盖了关键领域,包括:

    • 用户和组管理: 采用最佳实践指南安全地管理用户账户和组。

    • 服务配置: 关于安全配置基本服务的建议。

    • 文件系统和权限: 管理文件系统安全和权限的最佳实践。

    • 网络配置: 提供保护网络设置以防止未经授权访问和攻击的安全建议。

    • 审计和日志记录: 设置强大日志和审计的说明,以监控系统活动。

    该基准是系统管理员、安全审计员以及必须遵守行业标准和法规的组织的重要资源。我们欢迎 FreeBSD 社区提供反馈,为这些指南的不断完善做出贡献。安全工作在协作中最为有效,我们期待看到社区如何利用和扩展这一新资源。

    我们对 FreeBSD 社区在此基准中的重要贡献表示衷心感谢。特别感谢基准撰写者 Moin Rahman、编辑 Carole Fennelly、评审 Jason Kafer 和 Rick Miller、项目经理 Joe Mingrone,以及 CIS 的 Justin Brown 和 Eric Pinnell。同时,我们也感谢 Verisign 对创建 CIS FreeBSD 14 基准部分费用的资助,以及对 FreeBSD 基金会的慷慨捐赠者 给予的支持。

    更多信息: FreeBSD 14 基准(FreeBSD 基金会)

    在 FreeBSD 上的 VPP

    将矢量数据包处理(VPP)框架移植到 FreeBSD,来增强网络性能能力

    联系人: Tom Jones [email protected]

    FreeBSD 上的矢量数据包处理(VPP)项目旨在将 VPP 这一开源的高性能用户空间网络栈移植到 FreeBSD。VPP 通过矢量化操作和并行处理优化数据包处理,非常适合软件定义网络(SDN)和网络功能虚拟化(NFV)应用。该工作启动于 2023 年 11 月,由专注于网络性能的 FreeBSD 开发者 Tom Jones 在 FreeBSD 基金会的合同下领导。

    关键里程碑包括修复 VPP 在 FreeBSD 上的构建,确保其能够编译和运行,验证并添加基本功能,以及开发全面的测试和回归套件以维护可靠性和稳定性。性能基准测试帮助识别和解决潜在瓶颈,并提出改进和优化建议。

    文档工作专注于 FreeBSD 特定的 API 和用法,为开发者和用户提供清晰的指导。创建 VPP 的 FreeBSD 移植成功简化了安装和部署,使用户更易于使用。

    VPP 的 FreeBSD 移植取得了成功,正在进行 的工作旨在进一步增强其能力。不断进行改进和优化,以确保 FreeBSD 的网络性能保持强大和高效,巩固其在高速网络应用中的适用性。

    更多信息: Vector Packet Processor (GitHub)

    网络夏季实习

    已完成

    Naman Sood 是 FreeBSD 基金会的夏季实习生,一直在从事与网络相关的任务。Naman 在开始实习时提交了对 FreeBSD 中一个防火墙(pf)的改进。如,他们完成了 Luiz Amaral 开展的工作,以使 pfsync(pf 的状态表同步接口)流量通过 IPv6 进行传输。他们还提交了对 pf 完全圆锥 NAT 实现 RFC 4787 REQs 1 和 3 的工作。完全圆锥 NAT 意味着来自内部 IP/端口的所有请求都映射到相同的外部 IP/端口,这使得某些设备(如 Nintendo Switch)能够在 FreeBSD 上运行 pf 的情况下正常工作。Naman 还承担了一些杂项任务,例如探索从 Klaus P. Ohrhallinger 开展的 FreeBSD 项目 VPS 中提取 TCP 检查点和故障转移的工作,以及提交 pw(8) 和 du(1) 的 bug 修复。

    文档和测试实习

    已完成

    2023 年 7 月,Yan-Hao Wang 开始在基金会进行夏季实习,承担各种任务。以下是一些计划的工作内容:

    • 构建一款在线手册页面编辑器

    • 更新 FreeBSD 的 jenkins-tinderbox

    • 为 /bin、/sbin、/usr/bin 和 /usr/sbin 中的用户空间工具添加测试用例

    • 研究开发 FreeBSD 手册页面和文档的“专家系统”

    • 修复 libxo 问题,并编写相关测试

    • 调查 RPI4 和 IPV6 待办事项的开发路线图

    FreeBSD 手册页面和文档的“专家系统”将是一个尽力而为的概念验证任务,包括将 FreeBSD 文档(如手册页面和手册)导入到向量数据库中,以便像 ChatGPT 这样的语言模型可以“阅读”它们,从而在查询与 FreeBSD 相关的问题时能提供更好的答案。

    解决 OpenSSL 3 / LLVM 16 Port 问题

    已完成

    随着 FreeBSD 主分支中 OpenSSL 更新到版本 3,许多 Port 构建错误必须在 FreeBSD 14.0 发布之前解决。与 OpenSSL 3 和 LLVM 15 的大多数关键问题已经得到修复,但在使用 LLVM 16 时,约有 800 个额外的 Port 无法构建,导致在完整的 Ports 构建中跳过了 2800 个依赖 Port。穆罕默德·莫伊努尔(Moin)·拉赫曼将完成所有与 OpenSSL 3 和 LLVM 16 更新相关 Port 问题的耗时且繁琐的修复工作。

    SIMD 增强的 libc

    完成

    现代计算机架构提供了 SIMD(单指令多数据)指令集扩展,以便一次处理多个数据。SIMD 技术常用于视频编解码、图形渲染和科学计算等数值应用中,同时也有助于基本的数据处理任务,例如 libc 函数实现的任务。虽然其他 libc 实现已经提供了标准 libc 函数的 SIMD 增强版本,但 FreeBSD 的 libc 大体上并没有。罗伯特·克劳塞克(Robert Clausecker)发起的这个项目旨在提供相关 libc 库函数的 SIMD 增强版本,从而提高与之链接的软件性能。由于这些 libc 函数被大多数可用的 FreeBSD 软件使用,因此这些增强预计会为广泛的程序带来广泛的好处。该项目的主要关注点是 amd64,目标是基于 x86_64 psAB 定义的架构级别生成 SIMD 优化的实现。

    如果例程受益于较高架构级别可用的附加指令,计划实现多种例程的多个实现。这通常意味着一个基线或 x86-64-v2 的例程,以及每个 x86-64-v3 和 x86-64-v4 的一个例程。计划建立基准测试套件,以确定这些例程对 libc 性能的影响。在未来的工作中,这些例程可以适应 i386,或移植到其他架构,包括 arm64(ASIMD,SVE)和 ppc64/ppc64le,前提是有足够的兴趣。

    技术细节

    计划将优化的例程实现为汇编,以确保工具链独立性。对于动态链接的可执行文件,计划使用 ifunc 机制在运行时选择每个例程的最佳实现。如果可能,将查询一个环境变量,以允许用户选择不同的架构级别或完全禁用 SIMD 增强。对于静态链接的可执行文件或直接调用函数时(例如,通过隐藏别名从 libc 内部调用),计划提供调度跳板。在第一次调用跳板时,调用解析为一个调度函数,该函数确定使用哪个实现。调度函数将调度目标写入由跳板使用的函数指针中,然后尾调用选定的例程。在下一次迭代中,直接调用正确的函数。这两种机制都将以线程安全和异步信号安全的方式实现。最佳实现通常是使用 CPU 支持的最高架构级别的实现。然而,硬件约束,例如热许可和 AVX-SSE 转换惩罚,可能使某些处理器上的架构级别 v3 和 v4 变得不具吸引力。实现可能会在读取时超出字符串的末尾,但确保不会跨越页面边界。这样的溢出在未设置段限制时是无害的,但可能会让分析工具如 valgrind 感到困惑。这在处理以 NUL 结尾的字符串时尤其需要快速性能。

    文档

    SIMD 增强函数的存在将在新的手册页 simd(7) 中记录。该页面将向用户解释 libc 如何选择使用哪个实现以及如何配置这种行为。其他手册页,如 environ(7)、string(3) 和 bstring(3),将根据需要增强交叉引用和附加信息。内部文档将解释调度和函数选择机制。由于不计划将这些机制提供给用户代码,因此不会生成最终用户文档。根据需要,可能会生成关于基准测试和测试设置的附加文档。最终报告将描述所使用的技术,并给出最终性能改进。

    Capsicum 实习

    已完成

    从 2023 年 6 月 1 日到 9 月 1 日,Jake Freeland 将在基金会实习,致力于 Capsicum,这是 FreeBSD 的沙箱框架。Capsicum 的设计目的是限制应用程序和库的能力。Capsicum 模型简单且安全,但围绕该框架的进展和发展在近年来逐渐减缓。Capsicum 的核心思想直观易懂;一旦进入能力模式,资源获取和外部通信就会受到严格限制。围绕这一原则设计程序相对容易,但当现有的未设计为沙箱的应用程序需要在此环境中运行时,问题便接踵而来。确定哪些操作会导致 Capsicum 违规是困难的,而预先打开尚未请求/命名的资源是不可能的。此外,开发人员在开始实现 Capsicum 功能之前需要对程序有充分的了解。这些原因解释了为何 Capsicum 化的工作逐渐减缓。

    这次实习将涉及多个项目,这些项目的整体目标是振兴 Capsicum。主要目标是增强和简化希望将现有程序 Capsicum 化的开发人员的体验。Capsicum 最大的敌人是其陡峭的学习曲线。重构程序支持能力模式通常要求开发人员了解导致 Capsicum 违规的原因,并知道如何重构给定程序以避免违规。有时,这一过程相对简单,但较大的程序往往需要按需资源,而弄清楚如何满足这些需求可能会很困难。扩展可供开发人员使用的工具数量,以便方便地将程序 Capsicum 化,将显著平缓上述学习曲线。如果 Capsicum 化变得简单,更多的开发人员将会采用它。

    项目

    1. 跟踪 Capsicum 违规

    在撰写本文时,修改程序以支持 Capsicum 需要开发人员手动解析他们的代码并找到 Capsicum 违规。如果有一个工具可以在运行时跟踪应用程序并确定违规发生的位置,那将是很方便的。这一功能可以在 ktrace(1) 中添加一个选项标志。其前提是钩住通常会返回 ENOCAP 的位置,记录该位置,然后正常继续执行。David Chisnall 提出的差异修订 https://reviews.freebsd.org/D33248 也可以用来通过信号通知记录违规。

    2. Capsicum 化 syslogd(8)

    syslogd 守护进程负责读取并记录消息到系统控制台、日志文件和其他机器。记录是任何操作系统不可或缺且常常敏感的职责,因此 syslogd 理应使用 Capsicum 进行沙箱化。通过 ktrace(1) 跟踪 Capsicum 违规,将重新设计 syslogd 以在能力模式下运行。syslog.conf 配置文件负责为 syslogd 提供设施和程序进行监视,以及对应的日志文件位置。这一约定使我们能够解析 syslog.conf,并确定 syslogd 正常运行所需的资源。通过在执行开始时解析 syslog.conf 进行沙箱化并不可行。如果在任何时间接收到 SIGHUP 信号,syslogd 将重新处理其配置,并可能需要新的资源。为了绕过这个问题,syslogd 应该被分为两个并发进程:一个处理日志,另一个监听 SIGHUP,读取配置文件,并在必要时将能力传递给另一个进程。

    3. Capsicum 化 NFS 守护进程

    NFS 套件由许多守护进程组成,包括 nfsd(8)、mountd(8)、rpcbind(8)、rpc.statd(8)、rpc.lockd(8) 和 rpc.tlsservd(8)。该项目的重点将放在 Capsicum 化 rpcbind 上。rpcbind 守护进程负责将 RPC 程序号转换为标准通用 DARPA 地址。这个程序非常适合 Capsicum 化,因为它通常由 root 运行,因此是一个有价值的攻击目标。快速浏览 usr.sbin/rpcbind/rpcbind.c: 152 显示 rpcbind 限制自身至少使用 128 个资源,这表明它可能会按需请求打开任意文件。这是 Capsicum 化的一个明显障碍,因为我们无法在能力模式下打开任意文件。我们可能需要使用类似 libcasper(3) 的机制(或其他类似机制),在需要时将能力传递给 rpcbind。记录下这些命名资产的请求:rpc 锁文件、日志文件、网络配置文件、用于线程唤醒的管道、rpcbind 套接字。毫无疑问,还有更多。可能还会完成对其他 NFS 守护进程的 Capsicum 化。

    4. Capsicum 化 ggatec(8) 和 ggated(8)

    GEOM Gate 网络设施提供对存储设备的远程访问,并建立在 FreeBSD 的 GEOM 框架之上。与 NFS 类似,设备导出可以在导出文件 /etc/gg.exports 中管理。ggate 工具是 Capsicum 化的主要候选,因为它们以 root 身份运行,处理网络请求,并曾在 CVE-2021-29630 中遭受远程代码执行。ggatec 客户端工具用于创建 ggate 设备并与 ggated 通信。由于远程主机和设备路径在命令行参数中指定,因此 Capsicum 化 ggatec 应该相对简单。在进入能力模式之前,简单的文件和套接字预打开应该足够。ggated 工具查看 /etc/gg.exports 或指定的替代导出文件,并为 ggatec 服务 GEOM Gate 请求。所有所需资源似乎都在命令行参数和导出文件中指定,因此在进入能力模式之前预打开这些资源应该足够。

    5. Capsicum 化 tftpd(8)

    tftpd 服务器实现了互联网微型文件传输协议(RFC 1350),允许远程读取 tftpd 参数中指定的文件。由于所需资源提前指定,因此 tftpd 的 Capsicum 化应该涉及简单的目录预打开。

    6. Capsicum 化 ntpd(8)

    与 syslogd(8) 和 rpcbind(8) 不同,ntpd 的代码库似乎分为大约一百个大文件。根据手册页面,这些文件都有名称,且很容易进行预打开:配置文件、漂移文件、网络接口设备、密钥文件、日志文件、pid 文件和统计文件。假设不需要任意文件,Capsicum 化过程应该相对温和。

    7. Capsicum 化 libarchive(3)

    libarchive 库专注于压缩和解压缩多种流行的归档格式。已注意到 iconv(3) 的共享库获取正在引发 Capsicum 违规。一个临时解决方案是在 unzip(1) 中预打开这些 iconv(3) 文件,但这实际上应该发生在 libarchive 中。libarchive Capsicum 化的目标是在能力模式下引入与归档无关的创建和提取。这可能通过添加 Capsicum 特定的接口来实现,作为标准 API 的补充。如果这可行,下一步将是对 tar(1) 进行 Capsicum 化。由于大多数 tar 文件提取到当前目录,因此 Capsicum 化过程应包括打开当前目录文件描述符,并将所有文件系统资源获取调用更改为其 at() 派生函数。例如:open() 将更改为 openat()。

    8. 完成 SIGCAP 违规信号实现

    David Chisnall 提出的差异修订 https://reviews.freebsd.org/D33248 提议在 Capsicum 违规时可选地发送 SIGCAP 信号。不幸的是,该审查尚未完成,几个月来没有更新。完成此审查并添加 SIGCAP 信号可以使使用违规信号来触发 Capsicum 违规的程序的调试变得更加容易。我们可以使用 SIGCAP 告诉代码退回到替代路径,而不是等待可能被调试器拦截的 SIGTRAP。此外,拥有一个明确的 Capsicum 违规信号将允许 Capsicum 违规跟踪工具记录 Capsicum 特定的失败。例如,当 kern.trap enotcap = 1 被设置时,任何 Capsicum 违规将提示 SIGTRAP 及程序终止。并不透明的是,这个程序是否因为违规而终止,还是因为不相关的 SIGTRAP 信号而终止。将 kern.trap enotcap 更改为发送 SIGCAP 将消除这种混淆。这个 SIGCAP 信号还可以为前述的 ktrace(1) 引入一种跟踪 Capsicum 违规的替代方法。ktrace(1) 程序可以拦截并记录 SIGCAP 调用,并使用适当的信号处理程序将原始程序送回执行。

    无线实习

    已完成

    En-Wei Wu 是 2022 年谷歌编程之夏的贡献者,他于 2023 年初开始在 FreeBSD 基金会实习,专注于 FreeBSD 的无线驱动程序和工具。工作分为三个部分。

    wtap(4) 是由 Monthadar Al Jaberi 和 Adrian Chadd 于 2012 年推出的 net80211(4) Wi-Fi 模拟器。En-Wei 将通过添加对 802.11b 以外的更多 802.11 物理层的支持来扩展 wtap。对 wtap 的其他工作还将包括添加对 WPA/WPA2/WPA3 的支持,以便可以测试 wpa supplicant(8) 和 hostapd(8)。

    将为 hostapd(8) 添加对 WPA2 预认证的支持。WPA2 是作为 IEEE 802.11i 规范的一部分定义的认证协议。该协议现在通常用于将无线站点认证到接入点。该协议的一部分是能够与一个或多个接入点预认证站点,以便快速漫游。FreeBSD 在用于构建 WPA 启用接入点的 hostapd 程序中缺乏对该协议这一方面的支持。此任务将移植现有的 Linux 代码,以支持 hostapd 中的预认证。这主要涉及重写一些用户模式的多播代码并测试结果。对托管在 FreeBSD 之外的第三方源的修改应在适用时上游到相应的项目中。

    802.11 驱动程序的工作将完成。ath10k 驱动程序将通过完成 Adrian Chadd 开始的工作进行移植。同时,将为 Bjoern Zeeb 提供帮助,开发和测试 Realtek 驱动程序,如 rtw88 和 rtw89。

    改进 kinst DTrace 提供程序

    已完成

    DTrace 是一个框架,赋予管理员和内核开发人员实时观察内核行为的能力。DTrace 具有称为“提供程序”的内核模块,这些模块通过“探针”在内核中执行特定的插桩。

    kinst 是一个新的底层 DTrace 提供程序,由 Christos Margiolis 和 Mark Johnston 为 FreeBSD 操作系统共同编写。它允许用户跟踪任意指令,并且自 FreeBSD 14.0 起成为基础系统的一部分。

    kinst 探针的形式为 `kinst::<function>:<instruction>`,其中 `<function>` 是要跟踪的内核函数,`<instruction>` 是相对于函数开头的指令偏移量,可以从该函数的反汇编中获得。

    该项目的主要目标是实现内联函数跟踪(这是一个备受期待的 DTrace 功能),并将 kinst 移植到 riscv 和 arm64。对于内联跟踪,kinst 将利用 DWARF 调试标准,以便检测内联调用并为每个调用创建探针。未来,这一功能可以用于解决 FBT 的一些不足之处,例如尾调用优化问题(DTrace 手册第 20.4 章)以及缺乏内联跟踪能力。

    该项目的交付成果包括:

    – 扩展 kinst,以利用 FreeBSD 的 dwarf(3) 标准跟踪内联调用。 – 添加一个新的 dtrace(1) 标志,当 libdtrace 应用语法转换时(如果有),可以转储 D 脚本。这对调试 libdtrace 本身以及新的内联跟踪功能非常有用。 – 将 kinst 移植到 riscv 和 arm64。

    使用日志化软更新的文件系统快照

    已完成

    UFS/FFS 文件系统有快照能力。由于快照功能是在软更新编写之后添加的,因此它们与软更新完全集成。然而,当在 2010 年添加日志化软更新时,它们从未与快照集成。因此,在运行日志化软更新的文件系统上无法使用快照。

    当 FreeBSD 添加对 ZFS 的支持时,快照的重要性降低了。ZFS 可以快速且轻松地进行快照。然而,仍然存在两个实例,其中 UFS 快照仍然很重要。首先,它们能对实时文件系统进行可靠的转储,从而避免可能数小时的停机时间。其次,它们可在后台运行 fsck。与 ZFS 中需要进行清理的情况类似,fsck 需要定期运行,以发现未检测到的磁盘故障。快照能在实时文件系统上运行 fsck,而不需要安排停机时间。

    经过与开发者社区的磋商,FreeBSD 基金会的工作人员一致认为这样的基础设施工作能产生积极影响。因此,基金会开始赞助 Marshall Kirk McKusick 实施所需的更改,以允许使用日志化软更新的 UFS/FFS 文件系统进行快照。此项工作需要对 UFS/FFS 软更新和快照内核代码以及 fsck_ffs 实用程序进行广泛的更改。

    该项目预计将在 2023 年中期完成,工作分为两个里程碑。在里程碑 1 后,当运行日志化软更新时,将启用快照,并且它们将可用于对实时文件系统进行后台转储。里程碑 2 涉及扩展 fsck_ffs,使其能够在运行日志化软更新的文件系统上使用快照进行后台检查。每个里程碑在代码通过审查过程并已提交到主树时被视为完成。

    WireGuard 审查、更新与集成

    已完成

    WireGuard 是一种安全的隧道协议,具有用户空间和内核实现。在初期的修复程序发布后,FreeBSD 内核的 WireGuard 代码库更加完整和稳定。现在为每个提交设置了自动 CI,对 wireguard-freebsd 支持的版本进行编译并运行小规模的冒烟测试。

    基金会正在资助 John Baldwin 对 WireGuard 进行更新,主要是通过更新上游 WireGuard 驱动程序中的数据路径加密,使用内核中的 OpenCrypto 框架来处理数据路径。通过 WireGuard 隧道发送的数据包使用 Chacha20-Poly1305 AEAD 加密算法进行加密。与 TLS 和 IPsec 不同,WireGuard 使用 8 字节的随机数(nonce),而不是与该算法配合使用的 12 字节随机数。

    截至目前,大部分工作集中在更新 OCF,以更好地支持给定加密算法的多随机数(nonce)和标签/MAC 长度。John 之前已开始着手支持所有 AES-CCM NIST KAT 向量的工作,其中许多使用非默认的随机数和标签长度。该方法经过改进,更好地适应现有 OCF 模型,其中随机数和 MAC 长度是会话的属性(类似于密钥长度)。之前的一个分支将随机数长度设为单独操作的属性。这主要涉及扩展 /dev/crypto 接口,以允许为会话设置这些参数。现有的 OCF 测试在用户空间中运行,并使用 /dev/crypto 接口,包括 cryptocheck 实用程序和 NIST KAT 向量测试。

    在这些框架更改的基础上,John 扩展了 OCF 中现有的 Chacha20-Poly1305 加密算法,以支持 8 字节和 12 字节的随机数,包括在加速的 ossl(4) 驱动程序中。针对上游 WireGuard FreeBSD 驱动程序的补丁,已验证与标准 WireGuard 驱动程序的互操作性。

    LLDB 改进第三部分 – 内核调试支持

    已完成

    FreeBSD 的基础系统有 LLDB,它是 LLVM 家族的调试器。与 GNU GDB 调试器相比,FreeBSD 的 LLDB 目前存在一些限制,尚未完全取代 GDB。这个多阶段项目旨在为 FreeBSD 提供现代化的调试器,使 LLDB 更接近于一款功能齐全的 GDB 替代品。

    第一部分 和 第二部分 的 LLDB 改进项目描述了 FreeBSD 上 LLDB 的用户空间改进。第三部分专注于内核调试的改进。

    FreeBSD 上的 LLDB 调试器仍然缺乏能替代的 kgdb(1),kgdb 是一个包装了修改版 GDB 的调试器,依赖 libkvm 接口来调试死后和实时的 BSD 内核内存。LLDB 在 FreeBSD 内核调试中的一个主要限制是缺乏与 GDB 的远程协议兼容性。这种不兼容意味着 LLDB 前端与现有的 gdb-server 实现不兼容,尤其是与 qemu 使用的实现不兼容。第三部分的一个主要目标是解决这些不兼容,使得在内核调试中不再需要安装 GDB,并让 FreeBSD 开发人员使用 LLDB 满足他们所有的调试需求。

    GDB 和 LLDB 都支持通过 TCP/IP 进行远程调试。然而,GDB 还支持一种通过串口的 gdb-remote 协议变体。由于这种方法对于在不依赖内核 TCP/IP 堆栈的情况下进行远程内核调试非常有用,因此将会在 LLDB 中添加支持。

    libkvm 是 FreeBSD 基础系统的一部分,提供了一种统一的接口,用于访问内核虚拟内存映像,并支持实时内核和内核核心转储。为了促进在非 FreeBSD 平台上调试内核核心转储,libkvm 需要支持这些平台。第三部分的另一个目标是提供一个可移植的 libkvm 变体,将原始 FreeBSD 源代码与可移植的构建系统集成,类似于其他 *-portable 包(如 openssh-portable)。希望 libkvm-portable 能够支持在所有由 LLDB 支持的平台上,在 LLDB 中处理 FreeBSD 内核核心转储,包括不同的操作系统和不同的架构。FreeBSD 上的实时内核调试支持将会添加,从 amd64 开始,然后在时间允许的情况下扩展到其他平台(如 arm64 和 i386)。

    LLDB 改进第二部分 – 额外的 CPU 支持、跟踪 Fork 操作和 SaveCore 功能

    已完成

    FreeBSD 的基础系统有 LLDB,它是 LLVM 家族的调试器。与 GNU GDB 调试器相比,FreeBSD 的 LLDB 目前存在一些限制,尚未完全取代 GDB。这个多阶段项目旨在为 FreeBSD 提供现代化的调试器,使 LLDB 更接近于一款功能齐全的 GDB 替代品。

    LLDB 改进项目的第一部分 描述了用现代方法替换 FreeBSD x86_64 上过时的 LLDB 插件模型,该方法在单独的 lldb-server 进程下执行目标进程。传统的单体目标支持仍然在非 x86 目标上使用。该项目的第二部分涉及将一些非 x86 CPU 架构切换到新的远程进程插件框架,并完全移除旧的本地调试进程插件。待移植完成,将重点重新执行所有 ARM64 上的 LLDB 测试,并在时间允许的情况下解决任何错误,将非平凡的问题标记为已知故障。

    第二部分的其他里程碑包括:

    1. 支持跟踪 Fork 和 vfork 操作,以便与 GNU GDB 相媲美地调试子进程。

    2. 添加 follow-spawn 以增强进程跟踪支持(如果时间允许)。

    3. SaveCore 功能,允许用户按需创建核心转储文件。

    4. 在 FreeBSD 手册中记录改进后的 LLDB 支持。

    LLDB 改进第一部分 – 改进基础设施

    已完成

    FreeBSD 的基础系统有 LLDB,它是 LLVM 家族的调试器。与 GNU GDB 调试器相比,FreeBSD 的 LLDB 目前存在一些限制,尚未完全取代 GDB。这个多阶段项目旨在为 FreeBSD 提供现代化的调试器,使 LLDB 更接近于一款功能齐全的 GDB 替代品。

    FreeBSD 的 LLDB 使用的传统单体目标支持在同一进程空间中执行调试器的前端和后端,并依赖于一个过时的插件模型,技术债务日益增加。其他受支持目标上使用的现代 LLDB 插件方法是在单独的 lldb-server 进程下执行目标进程。这提高了可靠性,并简化了 LLDB 自身的进程/线程模型。此外,远程和本地调试都采用相同的方法。该项目的第一部分涉及为 FreeBSD x86_64 开发基本的远程进程插件,并将该工作上游提交到 LLVM。迁移到新进程模型完成后,将对 LLDB 的测试套件进行审查,并在时间允许的情况下进行必要的修复。此项工作预计在 2020 年完成。

    针对 Linuxulator 兼容性的改进

    已完成

    基金会此前资助了改善 Linux ABI 层(“Linuxulator”)的项目,重点是基础设施和诊断工具。这些早期项目为进一步的工作奠定了良好的基础,并修复了许多问题,但对用户的实际影响并不一定明确。

    基金会已向 Edward Tomasz Napierała 授予开发资助,旨在调查在 Linuxulator 下运行一系列流行的客户端和服务器相关的 Linux 应用程序,并修复/记录发现的问题。

    感兴趣的服务器软件应用程序将来自 Docker Hub 中的流行镜像。将识别出一些客户端应用程序,从基本的“冒烟测试”案例(如 xterm)到大型应用程序(如 Firefox、Chrome、VLC 等)。

    该项目于 2021 年第一季度完成。

    更新 DRM 图形驱动

    已完成

    FreeBSD 当前的直接渲染管理器(DRM)图形驱动程序在源代码树之外进行维护。这部分是由于许可问题,因为它们依赖于 GPL 下的一些 Linux 代码(尽管驱动程序本身是双重 BSD + GPL 许可)。这些驱动程序也越来越过时。

    该项目将更新 DRM 驱动程序至较新版本的 Linux,最初目标是长期支持(LTS)内核版本 5.4,并在可能的情况下实现 BSD 许可的内核兼容性适配层。待完成,将继续更新到更新的 Linux 内核版本。

    这项工作将使我们在图形驱动程序的开发和支持方面处于更好的位置,包括为非 x86 平台的图形支持后续工作提供便利。

    ZStd 集成到 OpenZFS

    已完成

    ZFS 是一个结合了文件系统和逻辑卷管理器的设计,旨在防止数据损坏并支持高存储容量。OpenZFS 提供了一种透明的压缩功能,能够在存储数据之前对其进行压缩,并在将数据返回给应用程序之前进行解压缩。这种压缩不仅节省空间,而且借助高性能的压缩算法,可以通过减少数据总量来降低读写延迟。

    OpenZFS 提供了两种主要的压缩参数,分别是 LZ4(高速,低节省)和 gzip(低速,高节省)。如今,预期的压缩比大约在 1.1 到 2.0 倍之间。

    将 ZStd 压缩算法集成到 OpenZFS 中,这是一种中速且高节省的压缩算法,将在对性能影响最小的情况下提供额外的空间节省。使用 ZStd 预期的压缩比范围在 1.1 到 3.6 倍之间。

    该项目将与其他 OpenZFS 开发者合作,更新和增强 Allan Jude 的原始原型实现,以准备将其合并到正式的 OpenZFS 中。工作还将包括额外的测试、向后兼容性改进、文档和性能分析。

    提升 if_bridge 性能

    已完成

    当前的 if_bridge 实现严重依赖于单个 BRIDGE_LOCK 互斥锁。因此,其性能限制在每秒略高于 100 万个数据包,无论系统中有多少核心。这意味着,对于小数据包,它几乎可以饱和 1Gbps 的链路,但也仅此而已。对于完整的(1500 字节)数据包,它可以饱和 10Gbps 的链路,但无法满足 40Gbps 或更高速度的链路。系统在等待获取桥接锁的过程中花费了绝大多数时间。

    总体思路是用两个读多写锁替换单个互斥锁,一个保护整体桥接,另一个保护转发表。绝大多数数据包只需要读取锁,从而允许多个核心同时通过桥接传输数据包。

    该项目 正在进行 中,目标完成日期为 2020 年春初。

    可扩展性和性能提升

    已完成

    CPU 的核心和线程数量每年都在不断增加,而在这些新 CPU 上运行 FreeBSD 往往会显示出新的可扩展性瓶颈。该项目将使用一些激励性的用例,例如“poudriere -j 128”软件包构建和“will-it-scale”。

    在此过程中可能会发现并解决可扩展性诊断工具(如 LOCK_PROFILING)中的不足。该项目预计将带来可共享锁、VFS 名称缓存锁、进程管理的改进,以及多个内核子系统的性能提升。

    改进 Linuxulator 诊断

    已完成

    FreeBSD 长期以来提供了一个 Linux 系统调用兼容层,之前能够执行大多数 Linux 二进制文件(在某些情况下速度甚至超过 Linux)。不幸的是,它最近没有得到太多开发,已逐渐落后,无法执行大多数现代 Linux 二进制文件。

    该项目将为调试运行现代 Linux 二进制文件时遇到的失败提供坚实的基础,并在二进制和源代码级别改善 Linux 兼容性。同时,它还将清理现有的 Linuxulator 实现,使其更容易和更快速地移植最初为 Linux 编写并主要在 Linux 下维护的软件。

    FUSE 用户空间文件系统更新

    已完成

    FreeBSD 的 fuse(4) 驱动程序存在错误且过时。它基本上无法用于任何网络文件系统,如 CephFS、MooseFS 或 Tahoe-LAFS。该项目将修复所有已知的 fuse 错误,更新内核 API,并添加新的测试套件。

    FUSE(用户空间中的文件系统)能让 FreeBSD 系统挂载由用户空间守护进程提供服务的文件系统,大多数 FUSE 守护进程很容易移植到 FreeBSD。截至本文撰写时,Ports 中包含 41 个 FUSE 文件系统。其中最受欢迎的是 fuse-ntfs,这是使用 FreeBSD 访问微软 NTFS 格式媒体的唯一方法。

    Fuse(4) 可以使用,但存在错误且不完整。在该项目开始时,错误跟踪器中有 26 个未解决的错误,其中一些已出现多年。最严重的是与缓存相关的错误,这可能导致任何 FUSE 网络文件系统中的数据损坏(在 Ports 中的 11 个,以及一些重要的非 Port 文件系统,如 CephFS 和 MooseFS)。

    Fuse(4) 的内核 API(内核与文件系统守护进程之间的通信协议)大约滞后于标准 11 年。这意味着我们无法支持与缓存失效、ioctl(2)、poll(2)、chflags(2)、文件锁定、utimes(2)、posix_fallocate(2) 和 ACL 相关的一些功能。我们还缺少一些性能增强功能,如 readdirplus、异步直接 I/O、回写缓存、SEEK_HOLE 和异步读取。

    该项目将修复所有已知的 fuse 错误,更新内核 API,并添加新的测试套件。

    预计于 2019 年夏季完成。

    集成 SDIO

    已完成

    该项目旨在集成对 SDIO 的支持,为支持 SDIO 连接的 WiFi 模块(如树莓派等设备)迈出第一步。

    树莓派 3 和 Zero W,以及 3A+ 和 3B+ 都基于博通的 FullMAC WiFi 设备集成了 WLAN。这些设备通过 SDIO WiFi 连接。目前,FreeBSD 既不支持 FullMAC WLAN 驱动程序,也没有其他 SDIO WiFi 连接。

    基于 Ilya Bakulin 的 MMCCAM SDIO 堆栈工作,该项目将帮助整合进一步的工作,并在必要时进行测试和增强,提供 SDIO WiFi 通信基础设施。

    USB 大容量存储目标

    已完成

    该项目提供了一个 USB 大容量存储目标,使得运行在嵌入式设备上的 FreeBSD 能够作为 USB 闪存驱动器出现,为用户提供了必要的文档和驱动程序,以便充分利用嵌入式目标。这在教学和产品环境中是非常宝贵的,成为出色的“开箱即用”体验的一部分。

    许多嵌入式板,例如 Beaglebone Black,提供 USB 目标或 USB On-the-Go (OTG) 接口。这允许嵌入式目标充当 USB 设备,并向 USB 主机(可能运行 FreeBSD、Linux、Mac OS、Windows、Android 或其他操作系统)呈现一个/多个接口(USB 设备类)。USB 设备类包括音频输入或输出(例如耳机)、大容量存储(USB 闪存驱动器)、人机接口设备(键盘、鼠标)、通信(以太网适配器)等。

    现代化博通 Wi-Fi

    已完成

    该基金会资助了 Landon Fuller 的工作,以现代化 FreeBSD 对博通 Wi-Fi 适配器的支持,为 FreeBSD 上全面的博通 Wi-Fi 支持奠定基础,包括启用从博通的 ISC 许可的 Linux 驱动程序中采用额外的 softmac PHY 和 fullmac 设备支持。

    此前,FreeBSD 对博通 Wi-Fi 适配器的支持由 bwn(4) 和 siba(4) 驱动程序提供,其中 siba(4) 负责调解 bwn(4) 访问通过片上 SSB 互连可访问的硬件核心。该项目将当前的 bwn(4) 驱动程序移植到 bhnd(4)——这是为了替换不再支持的 siba(4) 驱动程序而编写的,且被 FreeBSD/MIPS 博通移植使用——提供了一个统一的接口,支持 SSB 和 BCMA 互连,兼容 Wi-Fi 适配器和 Wi-Fi SoC。

    该项目于 2018 年 2 月完成,并将随 FreeBSD 12.0 发布。

    开箱即用的无头模式

    已完成

    该基金会资助了 Edward Napiarala 的工作,以提供 USB 供电功能(USB On The Go,USB OTG)的无头操作支持。虽然 FreeBSD 具备 OTG 支持,但默认情况下未启用/未配置,且往往无法正常工作。这使得在嵌入式设备(如树莓派 Zero)上使用 FreeBSD 变得繁琐。

    该项目旨在添加开箱即用的 USB OTG 支持,使 FreeBSD 对于缺乏设备来设置无头操作的新手以及寻求更友好的替代品的公司来说,更具吸引力。

    该项目的成功完成意味着用户仅需下载镜像,将其复制到 SD 卡上,通过 MicroUSB 电缆把开发板接入笔记本电脑,然后…就完成了:控制台和网络将作为虚拟 USB 设备出现,随时可以使用。这将大幅降低新用户在嵌入式设备上使用 FreeBSD 的门槛,使我们与 Linux 处于同一水平。

    ZFS 的“RAID-Z 扩展”功能开发

    已完成

    Zettabyte 文件系统(ZFS)是一种组合文件系统和逻辑卷管理器,旨在防止数据损坏并支持高存储容量。

    该基金会资助 Matthew Ahrens 开发“RAID-Z 扩展”功能。这将允许向现有的 RAID-Z 组添加额外的磁盘,例如将一个 4 宽的 RAID-Z1 组扩展为一个 5 宽的 RAID-Z1 组。

    这将通过“重新排列”所有现有数据来实现,将数据重新写入新的磁盘排列中,在逻辑 RAID-Z 组的末尾(因此在每个物理磁盘的末尾)留出一个新的连续空闲空间。重新排列的数据仍将保持原有的逻辑条带宽度,即数据与校验的比例将保持不变,而新写入的数据将使用新的逻辑条带宽度,具有改进的数据与校验比。重新排列的过程将在在线进行的同时,其他 zfs 和 zpool 操作也可以进行。

    该项目 已完成。

    将 'blacklistd' 守护进程移植到 FreeBSD

    已完成

    该项目提供了一个轻量级的守护进程,可以实时通知各种守护进程的“恶意行为”尝试。该守护进程将攻击的数据存储在一个持久化数据库中,并可以更新数据包过滤器,以阻止来自攻击者网络地址的访问。

    该项目于 2016 年 6 月完成,并在此之后进行了额外改进,并随 FreeBSD 11.0 发布。

    在 FreeBSD 中集成 VIMAGE 支持

    已完成

    该项目旨在完善 VIMAGE 网络栈代码,使其准备好投入生产。首先将更新以前在 Perforce 仓库中审查过的工作,逐步测试补丁,向社区展示,并将其纳入 FreeBSD SVN 基系统仓库的头部/分支。重点关注的两个主要领域是 (i) 网络栈的拆卸和排序,以及 (ii) 在拆卸过程中填补最后剩余的内存泄漏。

    该项目于 2016 年中完成。VIMAGE 是 FreeBSD 11 的一部分。在 2017 年 10 月,为了准备 FreeBSD 12.0,VIMAGE 默认启用。

    增强网络栈虚拟化项目

    已完成

    FreeBSD 开发者:Bjoern Zeeb

    虚拟化的网络栈将显著增强 FreeBSD 的 jail 功能,使 jail 可以拥有自己完整且本地管理的网络栈,包括防火墙、路由和 IPsec 配置。基金会将资助 FreeBSD 网络开发者 Bjoern Zeeb 来增强现有原型,目前正在合并到 FreeBSD 8.x,并提供代码审查。

    该项目于 2011 年完成。

    FreeBSD 的多路径 TCP

    已完成

    多路径操作的 TCP 扩展(MPTCP)允许一个多宿主主机在单个 TCP 会话中利用多个网络接口/路径。该协议目前正在 IETF 中标准化,参考文献为 RFC 6824。

    基金会资助了一个专注于 FreeBSD 多路径 TCP 的硕士研究奖学金。从现有实现出发,网络栈的设计将被完善,并增加其他功能,目标是在 2015 年中期发布一个功能性实现。还计划在 2014 年和 2015 年初进行几次增量发布。

    该项目的目标是设计和实现一个 FreeBSD MPTCP 栈,以促进进一步的 MPTCP 研究活动。关键在于实现一个可扩展的设计,以简化拥塞控制、调度和路径管理方案的实验。

    之前已经发布了一个 实验内核补丁。正在对 HEAD 分支进行持续开发。

    目前 正在进行 的功能包括扩展单路径模块 CC 代码以与 MPTCP 连接一起使用,以及添加一个模块化的数据包调度框架。此过程的一部分涉及重构现有 MPTCP 会话管理代码的大部分,以及创建新的多路径特定协议挂钩,这些步骤减少了 MPTCP 代码与现有 TCP 代码之间的耦合。

    基金会很高兴能够支持使用 FreeBSD 的大学研究,并通过这样的赞助为项目的增强作出贡献。

    移植 FreeBSD ARMv8 64 位 ARM

    已完成

    开发者:Andrew Turner 和 Semihalf sp.j.

    官方称为 AArch64 的 64 位 ARM 架构也被称为 ARMv8 和 arm64。与广泛采用 32 位 ARM 的嵌入式和移动市场相比,预计 64 位 ARM 架构将在传统服务器市场中实现应用。

    FreeBSD 基金会与 ARM、Cavium、Semihalf sp.j. 和 Andrew Turner 合作,将 FreeBSD 移植到 arm64。Cavium 直接向基金会提供支持,为开发社区提供工程专业知识和硬件。Cavium 的 ThunderX 平台与 FreeBSD 作为服务器操作系统的优势非常契合,支持在单个封装中最多 48 个核心。ThunderX 将是该项目的初始参考目标,但后续还会移植到其他 arm64 平台。

    该项目的总体目标是使 FreeBSD/arm64 达到一级地位,包括发布媒体和预构建的软件包集。有关 arm64 移植的更多信息,请访问 FreeBSD wiki,正在进行 中的源代码树可通过 FreeBSD 基金会的 GitHub 账号 获得。

    集成 Newcons 控制台驱动

    已完成

    FreeBSD 开发者:Aleksandr Rybalko、Ed Maste

    Newcons 项目交付了一个更新的 FreeBSD 控制台驱动,增加了对 Unicode 的支持,并改善了对图形模式的支持。这提高了与 X11 和内核模式设置 (KMS) 图形驱动的互操作性。

    该项目已集成,并在 FreeBSD 10.1 中进行了初始发布。对新控制台基础设施的其他改进仍在进行中。

    改进硬件性能计数器支持

    已完成

    FreeBSD 开发者:Joseph Koshy

    在谷歌的慷慨资助下,FreeBSD 基金会与 Joseph Koshy 合作,旨在改善 FreeBSD 中的硬件性能计数器支持。该项目的目标是在 hwpmc 驱动中添加调用图支持。通过调用图支持,开发人员可以更清晰地可视化性能问题,了解确切的代码路径,而不仅仅是某个特定函数,因为该函数可能仅通过一条路径显示出问题,而其他路径却没有问题。除了对软件的改进外,谷歌还提供了资金用于购买两台现代 CPU 机器,用于开发和测试。这些新机器被放置在由加拿大安大略省的 Sentex Corp 托管的网络性能集群中。

    以下是更详细的新增功能列表:

    • hwpmc 驱动现在支持调用链捕获,适用于内核和用户进程。

    • 对于 i386 和 amd64 架构的内核(hwpmc 可用的架构),机器相关和无关的部分进行了增强,以支持 hwpmc(4) 调用图支持所需的额外功能。

    • libpmc(3) 库已增强,以处理内核模块收集的新信息。

    • pmcstat(8) 工具使用捕获的调用链数据生成两种类型的报告:(a) 传统的 gprof(1) 调用图和 (b) 调用链摘要,为收集到的数据提供两种不同的“视图”。

    • 驱动程序 hwpmc(4)、命令行工具 pmcstat(8) 和接口库 pmc(3) 的手册页现在反映了可用的新功能。

    该项目于 2007 年完成。

    确保安全地移除挂载文件系统的磁盘设备

    已完成

    FreeBSD 开发者:Edward Tomasz Napierala

    该项目旨在使 FreeBSD 能够适应活动磁盘设备的移除,例如用户物理上拔掉已挂载文件系统的 USB 闪存设备。目前,在这种情况下,系统可能会出现崩溃。该工作涉及在内核的关键部分添加适当的引用计数,并修改文件系统以正确处理“设备丢失”错误。

    该项目于 2009 年完成。

    对 FreeBSD TCP 堆栈的改进

    已完成

    FreeBSD 开发者:Lawrence Stewart 和 斯威本科技大学 的高级互联网架构中心(CAIA)

    该三部分项目将包括实现适当字节计数(ABC)RFC3465 支持、将 CAIA 的 TCP 研究统计信息(SIFTR)TCP 分析工具适配并合并到 FreeBSD 中,以及对 TCP 重新组装队列进行改进。

    该项目于 2009 年 7 月完成。

    无线网状网络支持

    已完成

    FreeBSD 开发者:Rui Paulo

    Rui Paulo 将为 FreeBSD 实现即将推出的 IEEE 802.11s 无线网状网络标准。预计无线网状网络将变得普遍,因为路由器和网络设备将部署它们,从而允许动态构建和扩展无线网络。对该标准的支持将使 FreeBSD 用户能够利用这一新技术。

    扁平设备树项目

    已完成

    FreeBSD 开发者:Rafal Jaworowski

    Rafal Jaworowski 和 Semihalf 获得了一笔资助,以为 FreeBSD 提供对扁平设备树(FDT)技术的支持。该项目允许以平台中立和可移植的方式描述计算机系统的硬件资源及其依赖关系。

    这一功能的主要消费者是嵌入式系统,其硬件资源分配无法探测或自我发现。FDT 的概念源自 Open Firmware IEEE 1275 设备树的概念(常规 Open Firmware 实现的一部分),并且在其他部署中作为 Power.org 嵌入式平台参考规范(ePAPR)的基础。

    你可以在 http://wiki.freebsd.org/FlattenedDeviceTree 上了解更多关于该项目的信息。

    该项目于 2010 年完成。

    高可用存储项目

    FreeBSD 开发者:Pawel Jakub Dawidek

    Pawel Jakub Dawidek 获得了一笔资助,以实施存储复制软件,使用户能够使用 FreeBSD 操作系统进行高可用配置,其中数据必须在集群节点之间共享。该项目部分由 OMCnet Internet Service GmbH 和 TransIP BV 资助。

    该软件可通过 TCP/IP 网络对任何存储介质(GEOM 提供者,使用 FreeBSD 术语)进行同步块级复制,并实现快速故障恢复。HAST 将利用 GEOM 基础设施提供存储,这意味着它将与文件系统和应用程序无关,并可以与任何现有的 GEOM 类结合使用。在主节点发生故障的情况下,集群将能够切换到从节点,检查并挂载 UFS 文件系统/导入 ZFS 池,并继续工作而不会丢失任何数据。

    该项目于 2010 年完成。

    网络栈虚拟化项目

    已完成

    FreeBSD 开发者:Marko Zec

    网络栈虚拟化项目旨在扩展 FreeBSD 内核,以维护多个独立的网络状态实例。这将允许系统上不同 jail 之间实现完全的网络独立性,包括为每个 jail 提供自己的防火墙、虚拟网络接口、流量限制、路由表和 IPSEC 配置。

    该原型与 FreeBSD -CURRENT 保持同步,目前已经足够稳定以进行测试。它虚拟化了基本的 INET 和 INET6 内核结构和子系统,包括 IPFW 和 PF 防火墙等。下一步是对 IPSEC 代码进行完全虚拟化,并完善和记录管理 API。短期目标是为 FreeBSD 7.0-RELEASE 提供生产级内核支持的虚拟化网络(作为可插拔内核替换),同时继续与 -CURRENT 保持代码同步,以便将来可能合并。

    该项目于 2008 年完成。

    基于 FreeBSD Jail 的虚拟化项目

    已完成

    FreeBSD 开发者:Bjoern Zeeb

    Bjoern A. Zeeb 获得了一项资助,以改善 FreeBSD 的基于 jail 的虚拟化基础设施,并继续开发虚拟网络栈。他的雇主 CK Software GmbH 也在以工时形式匹配基金会的资助。

    在过去的十年中,FreeBSD 以其基于 jail 的虚拟化而闻名。随着虚拟网络栈的引入,FreeBSD 的操作系统级虚拟化达到了一个新的高度。

    该项目包括对两年的导入工作和开发进行清理,更重要的是,带来了网络栈拆解的基础设施。干净地关闭 FreeBSD 中的网络栈将是虚拟化领域面临的主要挑战,以使新特性达到 9.x 版本生命周期的生产就绪质量。

    此外,该项目还包括虚拟网络栈框架的通用化,将公共代码分离出来。这将提供一个基础设施,并将最小化开销地简化进一步子系统(如 SYSV/Posix IPC)的虚拟化。所有进一步虚拟化的子系统将立即受益于共享的调试设施,这是新技术早期采用者的一个重要特性。

    “改进的基于 jail 的虚拟化支持将继续保持轻量且易于管理,这将是未来几年的一大杀手级特性,”FreeBSD 开发者 Bjoern A. Zeeb 说。他还补充道:“这将使人们能够对他们的 FreeBSD 服务器进行分区,无需大量硬件就能运行模拟,或者在托管环境中相对轻松高效地提供数千个虚拟实例。虽然这符合绿色计算的趋势,但它也增强了 FreeBSD 的虚拟化组合,支持 Xen 或其他更重量级的虚拟机监控器,可以根据需要与 jail 混合使用。”

    该项目的资助持续至 2010 年 7 月。

    DTrace 用户空间项目

    已完成

    FreeBSD 开发者:Rui Paulo

    Rui Paulo 获得了一项资助,在 FreeBSD 中添加 DTrace 用户空间支持。

    DTrace 是一款通用且轻量的跟踪框架,能让管理员、开发者和用户调查系统故障/性能瓶颈的原因。自 FreeBSD 8.0 起,FreeBSD 操作系统就支持内核专用的 DTrace,但缺少用户空间支持。具备用户空间支持的 DTrace 允许检查用户空间软件及其与内核的关联,从而提供更清晰的后台运行情况。

    该项目将首先集中于添加 libproc 支持,包括符号与地址的映射、地址与符号的映射、断点设置以及 rtld 与 DTrace 的交互。接下来将重点关注 DTrace 进程控制,导入 pid 提供者并将其适配到 FreeBSD,同时移植用户空间静态定义探测提供者 (usdt)。最后将引入 plockstat 提供者。

    “通过拥有用户空间 DTrace 支持,公司可以使其产品在 FreeBSD 上表现得更好,因为他们现在可以访问这个出色的工具,”FreeBSD 开发者 Rui Paulo 说。他还表示:“当我们将用户空间支持与内核侧的 DTrace 支持结合时,我们还可以使 FreeBSD 成为更好的操作系统,因为我们可以更容易地调查性能瓶颈。”

    该项目于 2010 年 9 月完成。

    移植 DAHDI FreeBSD 驱动程序

    已完成

    FreeBSD 开发者:Max Khon

    Max Khon 获得了一项资助,以完成 DAHDI FreeBSD 驱动程序的移植。

    DAHDI/FreeBSD 项目的目的是使 FreeBSD 能够作为软件 PBX 解决方案的基础系统。

    DAHDI(Digium/Asterisk 硬件设备接口)是一个开源设备驱动程序框架和一套用于 E1/T1、ISDN 数字卡和 FXO/FXS 模拟卡的硬件驱动程序(http://www.asterisk.org/dahdi/)。Asterisk 是最流行的开源软件 PBX 解决方案之一(http://www.asterisk.org/)。

    该项目包括将 DAHDI 框架和 E1/T1、FXO/FXS 模拟卡以及 ISDN 数字卡的硬件驱动程序移植到 FreeBSD。这还包括 TDMoE 支持、软件和硬件回声消除(Octasic, VPMADT032)以及硬件转码支持(TC400B)。该工作在官方的 DAHDI SVN 仓库中进行,并与 Digium 的 DAHDI 团队密切合作。

    目前,大部分 DAHDI 组件已被移植,包括 DAHDI 框架本身、硬件驱动程序、TDMoE 驱动程序、软件和硬件回声消除(Octasic, VPMADT032)以及硬件转码(TC400B)。该项目托管在 官方 DAHDI SVN 仓库 中。

    FreeBSD ports 中的 misc/dahdi 现在包含 DAHDI/FreeBSD 的最新组件以及由于许可和版权限制而不在 DAHDI/FreeBSD SVN 中提供的一些内容。这些内容包括 OSLEC 回声消除器和实验性的 zaphfc 驱动程序。

    该项目于 2010 年 9 月完成。

    资源容器项目

    已完成

    FreeBSD 开发者:Edward Tomasz Napierala

    Edward Tomasz Napierala 获得了一项资助,以实现资源容器和简单的每个 jail 资源限制机制。

    与 Solaris 区域(zones)不同,当前的 FreeBSD Jail 实现并不提供每个 jail 的资源限制。因此,用户通常被迫用其他虚拟化机制替代 jail。该项目的目标是创建一个统一的框架来控制资源使用,并利用该框架实现每个 jail 的资源限制。未来,同一框架可能会用于实现更复杂的资源控制,例如层次资源限制,或实现类似于 AIX WLM 的机制。它还可以用于提供精确的资源使用计量,以便于管理或计费。

    “基金会决定资助这个项目真是太好了,”Edward 表示。“这将使基于 jail 的虚拟化在许多场景中成为更好的选择,例如对于虚拟专用服务器提供商。”

    该项目于 2011 年初完成。

    BSNMP 改进项目

    已完成

    FreeBSD 开发者:Shteryana Shopova

    FreeBSD 基金会很高兴宣布 Shteryana Shopova 获得了一项资助,用于改进 BSNMP。

    该项目包括对现有 FreeBSD SNMP 框架的几项增强功能,其中包括符合 SNMPv3 的用户身份验证、数据包加密和基于视图的访问控制。此外,该项目还包括一个新模块,该模块将允许对 FreeBSD 无线网络栈进行完整的 SNMP 管理和监控。项目完成后,FreeBSD 将成为构建基于开源的嵌入式无线设备的首选操作系统,这得益于其先进的无线网络栈能力,以及由 bsnmpd(1) 提供的轻量级、安全且完整的管理解决方案。使用 bsnmpd(1) 进行监控的现有 FreeBSD 安装也将从新增的安全功能和更细粒度的 SNMP 数据访问控制中受益。

    “SNMP 是网络监控的事实标准,”FreeBSD 开发者 Shteryana Shopova 说道。她还补充道:“SNMP 无处不在——用于网络服务器、交换机、路由器、防火墙、工作站、IP 电话、打印机、不间断电源设备和各种嵌入式设备。很高兴有机会为 bsnmpd(1) 增加一些 FreeBSD 社区请求的功能。”

    该项目于 2010 年 12 月完成。

    FreeBSD 和 PC-BSD 中的 IPv6 支持

    已完成

    FreeBSD 开发者:Bjoern Zeeb

    FreeBSD 基金会很高兴地宣布,已授予 Bjoern Zeeb 资助,来提高 FreeBSD 和 PC-BSD 中 IPv6 支持的成熟度。该项目由 iXsystems 联合赞助。

    FreeBSD 基于 KAME 的 IPv6 参考实现最早出现在 FreeBSD 4.0 中,并广泛应用于各种基于 FreeBSD 的商业产品中。到目前为止,IPv6 是默认 FreeBSD 内核中可选配置的功能,但配置 IPv6 时通常也意味着同时配置 IPv4。由于许多“IPv6 准备好”的应用程序依赖双栈行为,破损的 IPv6 应用程序往往被忽视。为不带 IPv4 的内核添加 IPv6 支持,将使 FreeBSD 和 PC-BSD 成为开源和专有 IPv6 兼容应用软件的理想测试和开发平台。

    “减少代码库对传统 IP 的依赖将有助于我们识别需要改进的操作系统和应用组件,以便在 IPv6 环境中良好运行。该项目将有助于确保 FreeBSD 作为全球互联网的组成部分继续在 IPv6 未来中占据重要地位:从根域名服务器、存储设备、路由器、防火墙、电视、桌面和移动系统,到全球一些最繁忙的网站,”Zeeb 先生说道。FreeBSD 基金会董事会成员兼 FreeBSD 核心团队成员 Robert Watson 将该项目描述为 FreeBSD 未来的关键,“Bjoern 的工作不仅会提高我们 IPv6 实现的成熟度,还将推动数百万部署的 FreeBSD 和其衍生系统上应用程序的改进。”该项目还将提高 FreeBSD IPv6 栈的质量和性能。

    Bjoern Zeeb 是一位总部位于德国的顾问,自 2004 年起成为 FreeBSD 的活跃提交者。他目前也是 FreeBSD 安全和发布工程团队的成员,最近因其在 FreeBSD 中的 IPv6 工作荣获 Itojun 服务奖。

    该项目于 2011 年 6 月完成。

    为 Intel 驱动程序实现 GEM、KMS 和 DRI 支持

    已完成

    FreeBSD 开发者:Konstantin Belousov

    FreeBSD 基金会很高兴地宣布,Konstantin Belousov 已获得资助,为 Intel 驱动程序实现 GEM、KMS 和 DRI 支持。该项目由 iXsystems 共同赞助。

    该项目的目标是实现 GEM、移植 KMS 并为 Intel 图形驱动编写新的 DRI 驱动程序,包括最新的 Sandy Bridge 集成图形单元。此工作将使最新的 Intel 开源驱动程序在 FreeBSD 上运行,从而扩大 FreeBSD 适用于桌面系统的硬件范围。

    “基金会资助的项目将允许我花更多的时间在这项有趣的工作上,并希望解决 FreeBSD 桌面系统持续使用的一个重大问题,”Konstantin 表示。

    iXsystems 公司首席技术官 Matt Olander 说:“为 GEM/KMS 提供支持将使 FreeBSD 和 PC-BSD 能在未来具有集成 3D 加速图形功能的高级架构上运行增强的原生图形支持。FreeBSD 长期以来在服务器市场占据主导地位,这是让 FreeBSD 成为笔记本、台式机和服务器完整平台的又一步。我们很高兴参与该项目。”

    Konstantin 是一位软件开发者,居住在乌克兰基辅。他在 2006 年获得了 src 提交权限,自那时起,他将大部分空闲时间花在操作系统上,修复错误并实现他认为有趣的功能。他目前还担任项目的发布工程师和核心团队成员。

    该项目于 2011 年 8 月完成。

    五种新的 TCP 拥塞控制算法

    已完成

    FreeBSD 开发者:斯威本科技大学

    FreeBSD 基金会很高兴地宣布,斯威本科技大学高级互联网架构中心已获得资助,在 FreeBSD 中实现五种新的 TCP 拥塞控制算法。

    正确运行的拥塞控制(CC)对互联网和 IP 网络的高效运行至关重要。拥塞控制动态地在流的吞吐量与对网络的推测影响之间取得平衡,必要时降低吞吐量以保护网络。

    目前,FreeBSD 操作系统的 TCP 协议栈采用了事实上的标准——基于丢包的 NewReno 拥塞控制算法,但该算法在处理现代数据网络的诸多方面(如高丢包率或大带宽/延迟路径)时存在已知问题。研究界和工业界都在持续进行大量工作,解决与拥塞控制相关的问题,特别是在广泛部署和使用的 TCP 协议上。

    斯威本科技大学与 FreeBSD 的 TCP 协议栈和拥塞控制实现的持续研究工作已逐步成熟。该项目旨在完善我们的原型并将其集成到 FreeBSD 中。

    该项目于 2011 年 3 月完成。

    前馈时钟同步算法

    已完成

    FreeBSD 开发者:墨尔本大学

    FreeBSD 基金会很高兴地宣布,墨尔本大学的 Julien Ridoux 和 Darryl Veitch 获得了资助,来实现前馈时钟同步算法的支持。

    网络时间协议(NTP)被广泛用于通过网络进行同步,而 ntpd 守护进程是当前参考的同步算法。FreeBSD 的系统时钟目前是以 ntpd 为基础设计的,这导致了内核与同步守护进程之间的强耦合反馈。

    RADclock 是基于前馈原理的另一类同步算法的一个示例。该项目将为前馈算法提供核心支持,使得可以开发和测试 ntpd 的替代方案。其核心动机在于这些方法在提供高度稳健和精确的同步方面具有巨大的潜力。

    此外,虚拟化是时间保持系统即将面临的主要挑战之一。目前的反馈同步模型过于复杂,并引入了自身的动态,这种方法不适合虚拟化的要求。基于前馈的同步提供了一种更简洁、更简单的方法,能够在虚拟机实时迁移时提供精确的时间保持。

    该项目于 2011 年 9 月完成。

    实现 xlocale API

    已完成

    FreeBSD 开发者:David Chisnall

    C 标准库(libc)是 UNIX 系统中最重要的部分之一,因为大多数程序通过用 C 语言编写的接口与内核交互。在类似的 libc 实现之间移植代码是非常容易的,如果某个功能在 libc 中得到支持,高级语言可以便使用它,而无需重新实现。

    随着时间的推移,C 语言逐渐演变以适应现代多核系统,但仍然存在一些问题区域,其中之一就是本地化支持。C 语言最初并不支持本地化。FreeBSD 的 libc 和 Darwin 的 libc(Mac OS X 使用的库)相似,这使得从 OS X 移植代码到 FreeBSD 比移植到 Linux 容易得多。OS X 使用的 libc 支持一组扩展的本地化函数(xlocale),允许在每个线程的基础上设置本地化。

    此外,LLVM 项目中的 libc++ 最初是在 Darwin 上开发的,因此它使用 xlocale 来支持大部分 C++ 的本地化功能。缺乏这种支持是将 libc++ 移植到 FreeBSD 的主要障碍。

    只要 FreeBSD libc 支持 xlocale,我们就可以将 libc++ 移植到 FreeBSD,从而为我们提供一个 MIT 许可的 C++11 标准库实现。结合 Clang 和 libcxxrt,这意味着 FreeBSD 中的整个 C++ 栈将不再包含任何 GNU 代码。此时,链接器将成为实现完全无 GPL 的 FreeBSD 10 唯一明显的障碍。

    该项目于 2011 年 9 月完成。

    分析 FreeBSD 的 IPv6 栈性能

    已完成

    FreeBSD 开发者:Bjoern Zeeb

    FreeBSD 基金会很高兴宣布已向 Bjoern Zeeb 提供资助,用来分析 FreeBSD 的 IPv6 栈性能。该项目由 iXsystems 共同赞助。

    在去年,Bjoern 改进了 FreeBSD 的 IPv6 支持,使得构建不包含 IPv4 支持的 FreeBSD 系统成为可能。该项目将基于这一工作,专注于内核,分析 FreeBSD 的 IPv6 栈性能。不同用户在对比 FreeBSD 上的 IPv4 和 IPv6 性能时,发现了 IPv6 存在性能较弱的情况。尽管不同版本之间的数据有所不同,但原因大多未知。

    该项目将首先通过基准测试对 IPv6 和 IPv4 进行详细的性能分析,获取最新的数据,帮助更好地理解当前的状况。接下来将继续确定性能差异的原因,并在可能的情况下直接解决这些问题,或为未来的工作确定改进方向。初步的基准测试数据将使我们能够通过重新运行测量来评估变更,并量化改进效果。

    “随着全球开始部署 IPv6,流量模式从 IPv4 向 IPv6 转移,不仅需要关注正确性和稳定性,功能一致性和性能也至关重要,”开发者 Bjoern Zeeb 说道。“使性能数据与 IPv4 看齐将确保用户在使用 IPv6 时不会消耗更多的资源。”

    实现守护进程 auditdistd

    已完成

    FreeBSD 开发者:Paweł Jakub Dawidek

    FreeBSD 的审计功能提供了针对安全相关事件的细粒度、可配置的日志记录。记录安全事件日志的一个关键目的是在系统遭到入侵时进行事后分析。目前,内核可以将审计记录直接写入文件或通过 /dev/auditpipe 设备进行读取。由于审计日志由内核本地存储,一旦系统被入侵,攻击者就可以访问这些日志,从而有可能清除其活动痕迹。

    auditdistd 项目的目标是通过 TCP/IP 网络在本地 auditdistd 守护进程和远程 auditdistd 守护进程之间安全且可靠地分发审计记录。如果源系统遭到入侵,可以通过远程系统收集的数据分析攻击者的活动,因为此时只有远程系统的审计日志是可信的。

    该项目于 2012 年 2 月完成。

    Growfs 已挂载的文件系统

    已完成

    FreeBSD 开发者:Edward Tomasz Napierała

    该项目实现了在读写挂载状态下扩展 UFS 和 ZFS 文件系统的功能。此功能涉及对文件系统、GEOM 基础设施以及驱动程序的修改。

    从系统管理员的角度来看,这使得可以用 gpart(8) 扩展分区,然后使用 growfs(8) 调整其包含的文件系统大小,而无需先卸载文件系统。这对于扩展根文件系统特别有用,特别是,对于虚拟机而言尤为重要。

    该项目于 2012 年 11 月完成。

    文档项目基础设施增强

    已完成

    FreeBSD 开发者:Gabor Kovesdan

    FreeBSD 文档项目长期依赖过时的工具来生成 FreeBSD 手册和其他文档。该项目将文档集升级到 DocBook 5.0,并提供了改进的渲染流程。

    该项目于 2013 年 7 月完成。

    支持 ARMv7 的超级页(SuperPage)

    已完成

    FreeBSD 开发者:Zbigniew Bodek,Semihalf

    ARM 架构正在扩展到高端服务器计算市场,支持该平台的复杂特性是 FreeBSD 在这些新领域取得成功的关键。该项目为大型内存工作负载增加了超级页支持,以提升性能。

    此项工作专门针对 ARMv7 架构,同时保持了与 ARMv6 的兼容性。该项目由 FreeBSD 基金会和 Semihalf 共同资助。

    该项目于 2013 年 9 月完成,并随 FreeBSD 10.0 发布。

    原生 iSCSI 内核栈

    已完成

    FreeBSD 开发者:Edward Tomasz Napierala

    该项目提供了原生的内核级 iSCSI 栈(包括目标和发起者),以支持日益流行的块存储协议。虽然已有多个支持 FreeBSD 的 iSCSI 实现,但 FreeBSD 项目缺乏高性能且可靠的内核级目标。iSCSI 栈首次出现在 FreeBSD 10.0 中。后续版本将进一步优化并支持硬件卸载。

    该项目于 2014 年初完成,并随 FreeBSD 11.0 发布。

    Capsicum 集成

    已完成

    FreeBSD 开发者:Paweł Jakub Dawidek

    该项目继续将 Capsicum 和 Casper 守护进程集成到 FreeBSD 中。新结构的能力权利增加了可能的能力权利数量,约为 1000,既支持了未来的开发,又保持了 API/ABI 兼容性。该项目还将 Casper、libcapsicum 和 libcasper 合并到 FreeBSD 中。

    该项目于 2014 年初完成,并随 FreeBSD 11.0 一道发布。

    基于 Autofs 的自动挂载程序

    已完成

    FreeBSD 开发者:Edward Tomasz Napierała

    amd(8) 自动挂载程序的局限性是一个许多 FreeBSD 用户频繁反映的问题。新款自动挂载程序项目旨在解决这些问题。

    该自动挂载程序是对大多数其他 Unix 系统中此类功能的独立实现,使用通过 autofs 文件系统实现的内核支持。自动挂载程序支持标准的 Sun 映射格式,并与轻量级目录访问协议(LDAP)服务集成。

    FreeBSD 基金会与企业和大学用户合作,在现有的基于 LDAP 的环境中测试新的自动挂载程序,其中包括一些具有数千个映射条目的环境。

    该项目于 2014 年 9 月完成,并在 FreeBSD 10.1 和 11.0 中发布。

    UEFI 引导集成

    已完成

    开发者:Ed Maste

    统一可扩展固件接口(UEFI)为 x86 计算机提供了引导和运行时服务,取代了传统的 BIOS。本项目旨在适配 FreeBSD 的加载程序和内核引导过程,兼容当今服务器、台式机和笔记本电脑上常见的 UEFI 固件。

    该项目建立在 Benno Rice 的赞助项目基础上,旨在改进 UEFI 引导程序,并于 2013 年提供了一个可行性证明。

    此项目于 2014 年完成,并随 FreeBSD 10.1 和 11.0 发布。

    为 OpenCrypto 添加 AES 模式

    已完成

    开发者:John-Mark Gurney

    本项目为 FreeBSD 的 OpenCrypto 加密框架添加了现代 AES 模式,以供 IPsec 和其他使用者使用。该项目由 FreeBSD 基金会和 Netgate 联合赞助,Netgate 是一家领先的 BSD 基础防火墙和网络设备供应商。

    该项目增加了新的加密模式,同时从 OpenBSD 引入了基础设施更新,可为 FreeBSD 用户提供前所未有的高性能加密通信支持。新增模式包括 AES-CTR 和 AES-GCM,并可使用 Intel 的 AES-NI 指令实现硬件加速。

    该项目的工作于 2014 年 12 月提交到 FreeBSD,并随 FreeBSD 11.0 发布。

    Projects
    FreeBSD 项目页面
    介绍

    由于 FreeBSD 中针对第三方工具引入的机制(Ports 和 Packages)的完善,二进制包的使用得到了发展。尤其是引入了 Flavors(版本)功能的好处尤为显著,尽管安装的内容是相同的,但由于依赖的包版本不同,组合的复杂性也随之增加。然而,只要为这些依赖包的所有版本提供相应的包,那么包管理就变得非常简单了。虽然我们希望所有的依赖包都能提供完整的包,但依然能够感受到二进制包带来的便利。

    在这里,为了能够更好地利用二进制包,我总结了一些常用的命令。虽然详细的选项讲解会非常繁琐,但我只会列出常用的选项。此外,大多数命令在执行时都会询问是否继续。因此,几乎所有命令都可以使用 -y 选项来避免这一提示,我将在这里省略这一部分的详细描述。当你熟悉之后,可以自如使用。除此之外,我也没有列举太多实际操作的案例。如果你有任何疑问,欢迎告知,我会补充相关内容。

    常用的 pkg 命令

    在这里,我会在命令名称(或子命令名称)后标注 [R] 和 [L],它们的含义如下:

    • [R]:参考外部包/仓库中的信息。

    • [L]:参考已安装的包或本地文件系统中的包。

    • [RL]:根据环境的不同,既可以是 [R] 也可以是 [L]。

    pkg update [R]

    这是用来收集包元数据的命令。首先需要收集元数据,其他命令的执行依赖于此。这与 yum check-update 很相似。 需要注意的是,这并不是一个每次都需要执行的命令,许多命令会在自动更新元数据后再执行,因此如果你不介意自动更新,便不需要手动执行该命令。以下子命令会基于最新的元数据执行:

    • pkg install

    • pkg upgrade

    • pkg version

    • pkg search

    • pkg fetch

    • pkg rquery

    pkg install [R]

    用于安装软件包。与后面提到的 pkg add 不同,pkg install 是通过关键词指定并从网络获取包来安装。

    pkg add [L]

    用于安装指定的包文件。与 pkg install 不同,pkg add 是明确指定包文件名并进行安装。

    pkg delete [L]

    删除指定的软件包。

    pkg delete -ayf

    使用 -a 选项删除所有包,-f 选项强制执行删除,并且 -y 选项使得操作不进行任何询问。直观上,指定 -ay 就足够了,但是在因依赖关系无法删除某些包时,必须指定 -f 选项。如果你打算删除所有包,毫不犹豫地全部指定就好。

    pkg version [RL]

    用于进行包的版本比较。由于其特殊性,使用时需要分解具体的用例来理解。

    • 默认情况下,pkg version 会与 /usr/ports/INDEX-OS major version 这样的元数据文件进行比较。

    • 如果该文件不存在,会参考每个 Ports 的源目录(相当于指定 -P 选项)。

    • 如果该目录也不存在,则会参考远程仓库(相当于指定 -R 选项)。

    前两种情况属于 [L] 范畴,而后者则属于 [R] 范畴。

    pkg version -L =

    通常使用 -L 选项进行已安装包的版本比较,使用 = 来显示没有匹配的包。通常情况下,只指定 = 就足够了,但也可以指定 >、<、?、! 等其他符号,所有这些符号都需要加引号。

    以下是每个符号的含义,但在使用 -L 选项时,表示的是“非该符号”的情况。若需要查找该符号的含义,则需要使用 -l 选项。

    • >:当前安装的版本有较新的版本可用。

    • =:当前安装的版本与发布的版本相同。

    • <:当前安装的版本有较旧的版本可用,通常是元数据未更新或者进行新版本的测试安装时会出现。

    • ?:当前安装的包来源(origin)不存在,无法进行版本比较(可能已被删除或重命名)。

    • !:当前安装的版本无法进行版本比较。

    pkg version -t

    用于比较任意指定的版本号(实际上是字符串)。这个功能更多是用于测试不同版本号之间的关系,而不是特定包的功能。它与其他子命令有所不同,主要用于测试版本号的替换(例如,在替换 alpha 版、beta 版时),帮助用户确定哪个版本更大(更新),哪个版本更小(更旧)。

    关于版本比较的规则,你可以参阅 FreeBSD Porter's Handbook - 5.2.2. Versions, DISTVERSION or PORTVERSION。

    pkg upgrade [R]

    更新指定的包。如果没有特别指定,默认会检查所有包并尝试更新它们。

    pkg info [L]

    显示指定包的信息。如果没有指定包,则列出所有已安装包的概述。

    pkg info -a

    与其他选项一起使用时,表示列出所有包的信息。

    pkg info -l

    显示指定包的安装路径列表。

    pkg info -D

    显示指定包的注意事项,可能包含安装提示或其他相关信息。

    pkg lock [L]

    锁定指定包,防止其被更新。锁定的效果不仅限于防止包本身的更改,还包括以下功能:

    • 阻止锁定包的重新安装、升级、降级和删除。

    • 阻止依赖于锁定包的其他包的升级或降级,特别是当依赖关系指向另一个版本的锁定包时。

    • 阻止锁定包依赖的其他包的删除、升级或降级。

    • 即使间接共享依赖关系,也会被锁定。

    pkg unlock [L]

    解锁指定包。

    pkg search [R]

    使用正则表达式(大小写不敏感)搜索包名。通过 -e 选项可以进行严格的匹配,但这包括版本号,因此对于一般用户来说并不太友好。-g 选项支持类似于 shell glob(例如 ? 或 *)的模糊搜索,但由于版本号的包含,实际上搜索时需要加上 *。

    pkg which [L]

    显示指定的文件、目录等属于哪个包。使用 -o 选项可以显示该包的 origin。

    不常用但值得了解的 pkg 命令

    pkg audit [RL]

    报告已安装包与漏洞信息的匹配结果。由于需要从外部获取漏洞信息,这个功能偏向 [R],但如果没有急于更新信息的需求,就无需通过 -F 选项主动获取漏洞信息。通常,系统会有一个脚本每天自动获取漏洞信息。

    pkg check -s [L]

    检查指定包是否未被篡改且保持一致性。通常与 -a 选项一起使用。

    pkg check -d [L]

    检查指定包的依赖是否完好,是否未损坏。通常与 -a 选项一起使用。

    pkg autoremove [L]

    删除孤立的包。所谓“孤立”的包是指因为依赖关系而安装,但由于某些包被删除或更新后不再被依赖,因此变得不再使用。

    实际中,某些“孤立”的包可能仍在使用,但由于包的依赖信息无法反映这一点,因此在执行此操作时需要小心。例如,如果 bash 被作为某个包的依赖安装,但你仍在使用它,这种情况下就需要特别留意。可以通过显式安装 bash 或使用后续技巧避免此问题。

    在 ports 系统中,通常是需要在构建过程中使用的包(如编译器等)会被标记为删除对象。

    pkg updating [L]

    显示需要注意的包更新步骤(手动更新指示)。具体来说,会读取 /usr/ports/UPDATING 文件,并根据安装的(或指定的)包信息匹配并显示相关内容。该文件的内容是为人类阅读设计的,构造上有些启发式,但其严格性可能并不高。此外,需要确保该文件存在,系统不会自动下载该文件。

    pkg set [L]

    修改指定包的元数据(数据库)。通常是在根据 pkg updating 信息操作时才会用到这个命令,一般不需要主动使用。

    pkg set -A

    通过为 -A 选项指定以下值,来修改指定包的元数据。此更改会影响 pkg autoremove 的行为结果。

    • 0:使指定的包不成为 pkg autoremove 的删除对象。

    • 1:使指定的包成为 pkg autoremove 的删除对象。

    对这个选项感兴趣的人,可能也会关心 pkg autoremove 的工作原理。实际上,仅设置这个标志并不足以使包成为 pkg autoremove 的目标;还需要判断该包没有被其他包依赖等条件。

    另外,通过 pkg install 或 pkg add 明确指定安装的包,在安装时会自动设置为此标志无效。这个标志只对因依赖关系被自动安装的包有效。

    pkg set -o

    使用 -o 旧 origin:新 origin 的形式,将所有依赖旧 origin 的包的元数据中的 origin 信息修改为新值。

    pkg set -n

    使用 -n 旧包名:新包名 的形式修改包名。不过,考虑到包名中通常不包含版本号,这个操作本身存在一些微妙的问题。

    太小众了其实可以不用知道的 pkg 命令

    pkg alias [L]

    显示定义在 /usr/local/etc/pkg.conf 中的别名信息。

    pkg query [L]

    以指定的格式显示软件包的元信息。如果未指定包名,则会针对所有已安装的包进行查询。 可用于格式字符串中的占位符如下所示:

    • %n:包名

    • %v:包的版本

    • %o:包的 origin

    • %p:包的 prefix

    • %m:包的维护者(电子邮件地址)

    • %c:包的注释

    • %e:包的描述

    • %w:包的网址

    • %l:包的许可证逻辑(无 / 单一 /and/or)

    • %sb 或 %sh:包的大小(字节单位或更适合人类阅读的单位)

    • %a:包的自动安装标志

    • %Q:包支持的架构候选项

    • %q:包的架构(操作系统、版本、CPU 架构)

    • %k:包的锁定标志

    • %M:包的信息消息

    • %t:包的安装时间戳

    • %R:包的安装来源仓库

    • %X:包的校验和

    • %?C:表示某种条件 C 是否成立的布尔标志(d/r/C/F/O/D/L/U/G/B/b

    • %#C:满足某种条件 C 的项目数(与上同)

    • %dC:该包依赖的其他包列表,通过 C(具体为 n/o/v)来选择输出 Name/Origin/Version

    • %rC:依赖于该包的其他包列表,通过 C(具体为 n/o/v)来选择输出 Name/Origin/Version

    • %C:包所属的分类列表

    • %FC:包包含的文件列表,通过 C(p/s)来选择 Path 或校验和 Sum

    • %D:包包含的目录列表

    • %OC:包的选项列表,通过 C(k/v/d/D)来选择 key、value、默认值、描述

    • %L:包的许可证列表

    • %U:包使用的用户列表

    • %G:包使用的用户组列表

    • %B:包在程序中使用的共享库列表

    • %b:包所提供的共享库列表

    • %AC:包的注解标签列表,通过 C(t/v)选择 tag 或 value

    常见的用法之一是 %n-%v,用于输出包名和版本的组合形式。

    pkg query -e

    用于根据指定的查询条件筛选符合条件的软件包。以下是可用于右侧(不能用于左侧)条件表达式的字段:

    • %n:包名(字符串型)

    • %o:包的 origin(字符串型)

    • %p:包的 prefix(字符串型)

    • %m:包的维护者(邮箱,字符串型)

    • %c:包的注释(字符串型)

    • %e:包的描述(字符串型)

    • %w:包的网址(字符串型)

    • %s:包的大小(字节单位,数值型)

    • %a:包的自动安装标志(数值型)

    • %q:包的架构(操作系统、版本、CPU 架构,字符串型)

    • %k:包的锁定标志(数值型)

    • %M:包的信息消息(字符串型)

    • %t:包的安装时间戳(数值型)

    • %i:包的附加信息(字符串型)

    • %#C:表示某类项目的数量(C 可为 d/r/C/F/O/D/L/U/G/B/b

    可使用的运算符如下:

    • ||:逻辑“或”,用于连接两个判断条件

    • &&:逻辑“与”,用于连接两个判断条件

    • ~:用于匹配 glob 模式,例如 %var ~ 模式,判断是否匹配

    • !~:用于判断是否不匹配 glob 模式

    • > / >=:用于数值比较,大于或大于等于

    • < / <=:用于数值比较,小于或小于等于

    • = / ==:判断是否等于(数字或字符串)

    • !=:判断是否不等于(数字或字符串)

    • =~:判断是否大小写不敏感地等于(数字或字符串)

    • !=~:判断是否大小写不敏感地不等于(数字或字符串)

    pkg rquery [R]

    作用类似于 pkg query,但用于远程元数据。不再赘述,请参见 pkg query 的说明。

    pkg annotate [L]

    用于为软件包添加、修改或删除“注释信息标签”的命令。 这些注释信息可通过 pkg info -A 查看。至于注释标签的具体含义与使用方式,此处不做特别说明。

    pkg shell [L]

    用于直接访问管理软件包元数据的数据库(即 SQLite3)的命令。 基本上只能用来执行类似 pkg shell VACUUM 这样的操作。 如果你只是想利用查询功能,用 pkg query 就已经绰绰有余了,这个命令实用性很低。

    便利的别名命令

    与自动安装标志相关

    以下命令是别名,用于筛选出“自动安装标志为 0”的软件包,即那些是用户显式安装的包:

    • pkg prime-list [L]

    • pkg prime-origins [L]

    • pkg noauto [L]

    pkg leaf [L]

    显示所有“叶子”软件包,即在依赖树最下层的包。 若某个软件包出现在这里但不出现在 pkg noauto 中,则它是 pkg autoremove 的候选对象。

    pkg list [L]

    显示指定软件包所安装的文件路径列表。

    语法糖

    以下是等价的命令别名,可以任选其一来执行操作。 甚至你可以用像 pkg vanish(消失)这种中二感满满的词自定义别名,只要你愿意。 系统默认提供了一些比较中性的别名。

    • pkg remove 等价于 pkg delete

    不需要在意的 pkg 命令们

    这些命令大多是供内部使用的,或是给其他工具调用使用(比如把别的包管理系统的软件包信息注册到 FreeBSD 的 pkg 系统中)。 一般用户不需要关心:

    • pkg stats:显示统计信息

    • pkg clean:清理包缓存

    • pkg config:查看 /usr/local/etc/pkg.conf 中的设置(大小写不敏感)

    • pkg create:创建软件包。虽然在 Ports 构建过程中常用,但很少单独使用

    • pkg fetch:下载包。pkg install 实际上等价于 pkg fetch 加上 pkg add

    • pkg register:将包注册进本地数据库。纯粹是内部用途

    • pkg repo:生成包仓库目录,相关内容建议参考 pkg-repository(5) 手册

    • pkg shlib:显示软件包所提供的共享库以及依赖这些库的其他包,主要用于安全审计

    • pkg ssh:完全用于内部,不适合人类用户使用,省略

    • pkg triggers:执行延迟触发器。这是什么时候谁延迟的?总之也是内部使用,省略

    查询(pkg-query)

    想查出依赖于某个包,且是“显式安装”的所有软件包

    以 Python 3.11 为例,说明如何列出“依赖 Python 3.11 且是用户明确指定安装”的所有软件包。

    首先可以使用 pkg info -r python311(按包名指定)列出所有依赖 Python 3.11 的软件包。 也可以使用 pkg query '%ro' python311 以“原始名称”(origin)来列出。 此外,也可以直接使用如 lang/python311 这样的 origin 作为指定方式,而非包名。

    接着,检查这些软件包的“自动安装标志”,只列出自动安装标志为 0 的,即明确安装的那些。 示例如下:

    由于没有很干净的一条命令就能完成所有功能的写法,因此也可以借助 pkg shell 来做(不推荐,供参考)。 注意:此方法依赖底层数据库结构,未来可能失效。

    常见问题及解答

    Q. 什么是 origin?

    A.Origin 是什么以后再说吧。有空我再写。

    Q.pkg 命令本身是一个软件包吗?

    A. 是的,pkg 命令本身就是一个包。

    Q. 那 /usr/sbin/pkg 是什么?

    A. 那是一个“引导器”,只负责安装真正的 pkg 包。 实际会执行的是 pkg 包里的 /usr/local/bin/pkg-static。

    Q. 那它不属于基本系统吗?

    A.FreeBSD 曾经因为旧的软件包系统吃了太多苦,所以才采用了现在这种结构。 以前 pkg 命令不升级,整个系统就什么都干不了(即使新版本系统已经发布了,还会强制用老功能)。

    Q.pkg 命令和 pkg-static 命令有什么区别?

    A. 功能完全一样。pkg-static 主要在某些“极端情况”(如你要删掉 pkg 本身)时才需要。 一般正常使用用 pkg 就够了;pkg-static 只是为了某些内部处理时更安全。

    Q. 如何删除通过 pkg update 获取的仓库信息?

    A. 我也很感兴趣,目前还在调查中。

    Q. 用 pkg query 过滤总是不太顺利啊。比如说,想列出“最后安装的包”怎么办?

    A. 这种时候可以用 pkg shell 来努力一下。虽说“让我们来写 SQL 吧!”这听起来有点夸张,但你说得没错,pkg query 并不支持排序或聚合。 另一种思路是,把 pkg query 的输出通过管道传给其它工具,比如 sort、awk、head、tail 等组合使用。

    Q. 你真的全都记得住?

    A. 常用的当然记得住。原以为我也就记了三五个而已,没想到写着写着就十几个浮现脑海。说明这些的确值得记。 虽然有些细节的语义可能模糊了,但那种情况就查下手册吧。 总之,平时不常用的,忘了也无妨。

    顺便说一下,pkg query 和 pkg shell 以前我其实用得不多,这次因为研究查数据才顺手补上的。虽然 pkg shell 基本就是只查结果而已。

    Q.pkg update / upgrade / updating 总是傻傻分不清楚

    A. 很遗憾,这是必须记下来的。 其他包管理器有时 update 和 upgrade 是同一个东西,但在 FreeBSD 上……很遗憾(信息在此中断了)。

    Q.WITH_PKGNG 和 pkg2ng 是什么?

    A. 这是非常古早(比 10.0-RELEASE 还早)的事情,完全可以无视。 它们只具备历史意义,现在的设置和运维里已经毫无价值。


    小吐槽

    刚列完这些“大家应该都知道吧”的命令,立马陷入绝望:平时常用到底是指哪些……? 但如果不写这些,又感觉内容不完整,简直是地狱。 结果还在翻 man 手册时发现了个 bug(pkg-query(8): duplicate %#b),orz。

    参考文献

    • FreeBSD pkg

    • pkg(8)

    • pkg update(8)

    • pkg install(8)

    FreeBSD pkg コマンド 概要

    利用 FreeBSD Capsicum 框架实现程序沙箱化

    • 原文:Sandbox Your Program Using FreeBSD's Capsicum

    • 作者:Jake Freeland

    • 发布日期:2023 年 9 月 1 日

    当今时代,数据泄露的平均成本高达四百余万美元,令人惊讶的是,只有 51% 的公司计划增加安全投资^1^。这一数字很可能归因于实施健全安全解决方案所需的高昂成本。

    许多安全框架都非常复杂。Capsicum 的独特之处在于其简洁性。开发者能相对容易地将 Capsicum 集成到程序中,从而在保护应用的同时降低高昂的实施成本。

    本文展示了 Capsicum 的功能,并撰写了将该框架集成到新旧程序中的完整指南。

    Capsicum

    Capsicum 是款轻量级的安全框架,提供了用于限制程序能力的原语。更具体地说,Capsicum 能让开发者将其程序隔离到安全沙箱中。该框架基于最小特权原则设计,程序仅能访问其运行所需的资源。

    能力沙箱

    在支持 Capsicum 的系统上,程序能使用 cap_enter(2) 进入沙箱:

    注意

    为简洁起见,本文档中的代码片段省略了错误处理。实际使用时,应在适当位置加入错误处理。

    不用链接额外的库;对 Capsicum 的支持已内置于标准 C 库(libc)。

    Capsicum 能让开发者通过能力模式将程序沙箱化。在程序调用 cap_enter(2) 进入能力模式后,程序将无法自行获取新的资源。例如,使用 open(2) 打开文件会触发能力违规,造成函数调用失败,并将 errno 设置为 ECAPMODE(译者注:特定错误码):这在能力模式下不被允许。

    一种对程序进行 Capsicum 化的方法是在进入能力模式之前就打开好全部资源。程序事先拥有的资源能在沙箱中继续使用。

    若程序需要访问某子目录域中数量未知的资源,则可以使用 openat(2)、mkdirat(2)、bindat(2) 等 *at() 系统调用。这些函数需要额外的描述符参数,用作相对引用点来打开新资源。

    在这个例子中,dirfd 是在进入能力模式之前获取的。若程序进入能力模式,dirfd 就能作为相对参考点访问 home/jfree/foo。无法访问相对引用所提供子目录域之外的资源。

    该 openat(2) 调用会失败,因为 ../beastie 路径指向的目录不在 dirfd 提供的目录层级之内。

    进程间通信同样受到限制。进入能力模式的进程无法向其他进程发送信号,命名共享内存对象亦被禁止。某些系统接口完全不可用,如 reboot(2) 和 kldload(2)。不过,这些限制都有相应的解决方法。

    沙箱化的分区

    预先打开资源对那些资源需求可预测的程序非常有效,但有些程序需要按需访问资源。在这种情况下,开发者可选择仅对程序的特定部分进行沙箱化。

    如果无法在沙箱中运行完整的程序,那么可以将其隔离分区(compartmentalization)。隔离分区的做法是把一款程序拆分成多个分区,每个分区承担自身的基本任务。通过隔离分区架构,开发者可以将受信任的代码保留在沙箱之外,而将不安全或危险的代码隔离到沙箱中的分区。如果危险代码中发现了安全漏洞,将被隔离。

    Capsicum 为程序的特定部分提供了直观的沙箱接口。程序能在任意时刻派生一个新的子进程,并在能力模式下执行危险代码。诸如管道和套接字这样的进程间通信原语可用于数据交换,而不会触发能力违规。

    父进程可在沙箱之外运行,而子进程在隔离环境中执行危险代码。若程序已经实现了隔离分区,开发者可以从沙箱化每个分区开始。大多数分区可能需要针对能力模式进行一些重构,但开发者可以自行选择哪些部分需要沙箱化。若正确实施,相较于对整个程序进行沙箱化,这种方式工作量更少,但安全性有大幅提升。

    使用 libcasper(3) 请求资源

    有些程序在设计时并未考虑隔离分区。开发者可以重新架构这些软件,但这通常需要大量时间和资源。幸运的是,库 libcasper(3) 为那些隔离分区无效的复杂程序提供了帮助。开发者可以利用 libcasper(3) 提供的接口在能力沙箱中获取新资源。

    使用 Casper 服务

    在程序进入能力模式之前,可以与某 casper 服务建立通信通道。Casper 服务是运行在能力沙箱之外的进程,与调用进程并行运行。建立的通信通道可用于向 casper 服务请求新资源。

    注意

    必须在进入能力模式之前就打开 libcasper(3) 通道,否则 casper 进程会继承父进程的沙箱。

    库 cap_net(3) 利用 libcasper(3) 提供了支持能力模式的 libc 网络函数,否则这些函数会因 ECAPMODE 而失败。通过 libcasper(3) 接口的函数通常以 cap_ 前缀命名,以表明它们能在能力模式下成功执行。类似于 cap_net(3) 的其他 casper 服务库也存在,并提供以 cap_ 为前缀的 libc 函数。可在 libcasper(3) 手册页中找到完整列表。

    如果程序支持在没有 libcasper(3) 的情况下构建,开发者依然可以使用 cap_ 函数,而无需用 #ifdef WITH_CASPER 包装。大多数 casper 服务将其 cap_ 函数定义为宏,当 WITH_CASPER 未定义时会替换为非 cap_ 的形式。

    创建 Casper 服务

    Casper 服务库很好地隐藏了接口 libcasper(3),使程序开发者无需直接与其交互。但有时程序需要访问现有 casper 服务库未提供的资源,这种情况下开发者可以自行创建 libcasper(3) 服务。

    所有 libcasper(3) 服务都基于 CREATE_SERVICE(3) 宏:

    所有参数都很重要,其中 command_func 函数指针尤为值得关注,因为它是服务的主例程。当通过 cap_service_open(3) 打开服务时,服务会等待命令。待接收到命令,就会传递给 command_func 的 cmd 参数。

    大多数 command_func 会将传入的 cmd 字符串与一组字面量比较,若匹配则调用对应函数。Casper 服务运行在能力沙箱之外,因此在 command_func 内调用的所有函数都会以环境权限(ambient authority)执行,这意味着它们可以随意获取新资源。

    可以使用函数在程序和 casper 服务之间 cap_xfer_nvlist(3) 交换资源。命令字符串和相关资源必须先封装进 nvlist(9),再传输给服务。Nvlist 可存储数字、字符串、二进制、描述符以及其他 nvlists。每个资源都必须配有一个标识名,用于检索。

    cap_xfer_nvlist(3) 函数会将 nvl nvlist 发送到与 chan 绑定的 casper 服务。待 nvlist 到达 casper 服务,命令字符串会被提取并传入服务的 command_func。

    回顾 net_command() 中的片段:

    cap_bind() 发送了 "bind" 命令字符串,因此该 strcmp() 条件成立并调用 net_bind()。

    当 bind(2) 成功时,套接字必须被传回能力沙箱。nvlist_move_descriptor(9) 函数会将套接字描述符移入 nvlout nvlist,并接管该描述符的所有权。

    回顾 cap_bind() 中的片段:

    cap_xfer_nvlist(9) 的返回值是 nvlout nvlist,它持有已绑定的套接字描述符。可以通过 nvlist_get_descriptor(nvl, "sockfd") 从返回的 nvlist 中获取该描述符。

    限制 Casper 服务

    Casper 服务提供的接口通常过于宽泛。在使用 cap_net(3) 时,你可能仅需要服务提供的部分函数。大多数服务库会定义自己的限制机制,使开发者可以禁用程序不需要的函数。

    每个服务库都提供不同的限制机制。由于使用模式过多,建议开发者查阅各服务库的手册以获取详细信息和示例。

    为 Casper 服务创建限制

    开发者可以在 CREATE_SERVICE(3) 中指定 limit_func 函数指针以限制服务接口。当程序调用 cap_limit_set(3) 时,提供的 limits 会被重定向到 casper 服务的 limit_func 中,并相应应用。该机制的灵活性允许服务对其接口进行精细限制。

    大多数服务库会为 cap_limit_set(3) 提供包装函数,并使用自定义的 _limit_t 类型。该类型由服务库定义,用于跟踪服务特定的限制。

    随着限制的细化,实现可能很快变得复杂。像 cap_net(3) 这样的服务提供了对接口的广泛控制,因此其限制函数需要处理所有边界情况。快速查看 cap_net(3) 的限制函数可以发现,为不同的“限制模式”实现了单独的验证函数,以确保限制被正确应用和执行。

    限制函数依赖于其所限制的服务,因此没有统一的编写模式。想要为 casper 服务创建限制的开发者应参考 FreeBSD 源码中 lib/libcasper/services 的系统服务库示例。

    回顾:Casper 服务的组成部分

    casper 服务由以下四个主要部分组成:

    • 以 cap_ 为前缀的函数,通过 cap_xfer_nvlist(3) 向 casper 服务发送命令;

    • 在沙箱外执行命令相关代码并返回新资源的 command_func;

    • 限制服务用途的 limit_func;

    虽然在技术上可以创建返回任意命名资源的 casper 服务,但这会破坏将程序隔离到沙箱的目的。设计良好的 casper 服务接口应当有限且受约束,避免被利用。

    检测违规

    当程序进入能力模式时,它是否遵循沙箱规则并不总是显而易见。尝试打开受限资源的函数会触发能力违规,并返回 errno = ECAPMODE。即便有适当的错误检查,排查违规也可能耗时。好在 ktrace(2) 内核跟踪工具能帮助发现违规。

    通常,程序必须进入能力模式才会报告违规,但 ktrace(2) 能在程序 未进入 能力模式前记录违规。这意味着开发者能在不修改程序的情况下运行违规跟踪,查看违规发生的位置。由于程序未真正进入能力模式,它依然会获取资源并正常执行。

    在程序开头添加以下两行即可启用违规跟踪:

    这段代码创建了 ktrace(2) 的输出文件,并指定 KTRFAC_CAPFAIL 跟踪点以记录能力失败。

    注意

    ktrace(2) 手册页对系统调用的使用有详细说明。启用其他跟踪点(如 KTRFAC_NAMEI 记录文件名查找)有助于定位文件系统违规的来源。

    下面的 cap_violate 例程试图触发 ktrace(2) 可捕获的所有违规。无需理解其具体做了什么,只需知道它能触发违规就可以了。

    若进程被跟踪,跟踪数据会一直记录,直到进程退出或清除跟踪点。此时可以使用 kdump(2) 将 ktrace(2) 的转储转换为可读格式。

    cap_violate 程序中的每次违规都会在 kdump(1) 输出中生成一条 CAP 记录。开发者可利用这些输出定位并替换触发违规的代码。

    大多数实际程序应尽量避免违规,而不是像 cap_violate 那样触发它们。下面的 kdump(1) 输出展示了在启用 KTRFAC_CAPFAIL 与 KTRFAC_NAMEI 跟踪点后,使用 unzip(1) 解压归档文件(未进行 Capsicum 化)时的结果。

    这类输出更接近开发者在自己程序中会看到的情况。unzip(2) 正在重建 zip 文件中的目录结构。所有 open(2)、fstat(2) 和 mkdir(2) 调用都被 libc 隐式转换为带 AT_FDCWD 的 *at() 变体。由于 AT_FDCWD 在能力模式下不可用,因此触发违规。这类问题可通过在进入能力模式前打开一个当前目录描述符(等价于 AT_FDCWD),并将其传递给 openat(2)、fstatat(2) 和 mkdirat(2) 来规避。

    注意

    在能力模式下违规总会返回错误,但在跟踪过程中不会被当作错误,因此程序行为可能不同。

    违规跟踪是开发者工具箱中的一项实用工具。只需几秒钟即可用 ktrace(2) 运行程序,其结果几乎总能作为使用 Capsicum 沙箱化程序的良好开始。

    能力 (Capabilities)

    尽管名称相似,能力模式 (capability mode) 和能力 (capabilities) 是不同的内核原语。

    • 能力模式是 Capsicum 实现的安全沙箱。

    • 能力是拥有权限的文件描述符。

    如果用户想要对某项能力描述符执行 read(2),则该描述符必须拥有 CAP_READ 权限。如果用户想要对某个套接字能力描述符执行 bind(2),则该描述符必须拥有 CAP_BIND 权限。几乎所有描述符操作都有细粒度的权限;完整列表见手册页 rights(4)。

    当使用 open(2)、socket(2) 等创建文件描述符时,它会被赋予完整的能力集。可以使用 cap_rights_limit(2) 函数限制描述符的能力。

    能力的设计原则是最小化权限。只要描述符的权限被限制,它就不应执行超出权限的操作。描述符的权限始终可以被限制,但不能被提升。

    在对程序进行沙箱化过于严格的情况下,开发者可以选择限制能力描述符。能力提供了对允许操作的精细控制,但使用这种保护的程序易受到人为疏忽的影响。如果开发者忘记限制某项能力,就可能引入恶意代码滥用的风险。

    想要最大化安全性的开发者可以在能力模式下结合使用能力。能力提供了能力模式本身不具备的细粒度功能。例如,仅允许描述符进行 read(2) 操作,这是能力可以做到的,但能力模式不能。

    使用 Capsicum 提升安全性

    和 的设计初衷都是为了让程序更安全。能力模式通过将程序与系统其余部分隔离提供了确定的安全性。能力则提供了一种更灵活但不如前者严格的方式来限制程序权限。只要正确集成其中任意一种原语,开发者就能确信,他们的程序比在引入 Capsicum 前更加安全。

    参考资料

    1. . IBM Corporation. 2023-07-24. Retrieved 2023-08-31.

    相关资料

    DSCF2555.JPG
    host # command
    host % command
    rabbitX # command
    host # mkdir -p /jail/BASE
    host # fetch -o /jail/BASE/11.2-RELEASE.base.txz http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/12.1-RELEASE/base.txz
    host # for I in 1 2; do echo ${I}; mkdir -p /jail/rabbit${I}; tar --unlink -xpJf /jail/BASE/11.2-RELEASE.base.txz -C /jail/rabbit${I}; done
    1
    2
    host #
    host # for I in 1 2
    do
      cat >> /etc/jail.conf << __EOF
    rabbit${I} {
      host.hostname = rabbit${I}.local;
      ip4.addr += 192.168.43.10${I};
      ip4.addr += 10.0.0.10${I};
      interface = wlan0;
      path = /jail/rabbit${I};
      exec.start = "/bin/sh /etc/rc";
      exec.stop = "/bin/sh /etc/rc.shutdown";
      exec.clean;
      mount.devfs;
      allow.raw_sockets;
    }
    
    __EOF
    done
    host #
    host # cat /etc/jail.conf
    rabbit1 {
      host.hostname = rabbit1.local;
      ip4.addr += 192.168.43.101;
      ip4.addr += 10.0.0.101;
      interface = wlan0;
      path = /jail/rabbit1;
      exec.start = "/bin/sh /etc/rc";
      exec.stop = "/bin/sh /etc/rc.shutdown";
      exec.clean;
      mount.devfs;
      allow.raw_sockets;
    }
    
    rabbit2 {
      host.hostname = rabbit2.local;
      ip4.addr += 192.168.43.102;
      ip4.addr += 10.0.0.102;
      interface = wlan0;
      path = /jail/rabbit2;
      exec.start = "/bin/sh /etc/rc";
      exec.stop = "/bin/sh /etc/rc.shutdown";
      exec.clean;
      mount.devfs;
      allow.raw_sockets;
    }
    host # for I in 1 2; do service jail onestart rabbit${I}; done
    Starting jails: rabbit1.
    Starting jails: rabbit2.
    # jls
       JID  IP Address      Hostname                      Path
         1  192.168.43.101  rabbit1.local                 /jail/rabbit1
         2  192.168.43.102  rabbit2.local                 /jail/rabbit2
    host # for I in 1 2; do cat /jail/rabbit${I}/etc/resolv.conf; done
    nameserver 1.1.1.1
    nameserver 1.1.1.1
    host # for I in 1 2; do sed -i '' s/quarterly/latest/g /jail/rabbit${I}/etc/pkg/FreeBSD.conf; done
    
    host # for I in 1 2; do grep latest /jail/rabbit${I}/etc/pkg/FreeBSD.conf; done
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
    host # for I in 1 2; do jexec rabbit${I} env ASSUME_ALWAYS_YES=yes pkg install -y rabbitmq; echo; done
    Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:11:amd64/latest, please wait...
    Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done
    [rabbit1.local] Installing pkg-1.10.5_5...
    [rabbit1.local] Extracting pkg-1.10.5_5: 100%
    Updating FreeBSD repository catalogue...
    pkg: Repository FreeBSD load error: access repo file(/var/db/pkg/repo-FreeBSD.sqlite) failed: No such file or directory
    [rabbit1.local] Fetching meta.txz: 100%    944 B   0.9kB/s    00:01    
    [rabbit1.local] Fetching packagesite.txz: 100%    6 MiB 745.4kB/s    00:09    
    Processing entries: 100%
    FreeBSD repository update completed. 32114 packages processed.
    All repositories are up to date.
    Updating database digests format: 100%
    The following 2 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            rabbitmq: 3.7.15
            erlang-runtime19: 21.3.8.2
    
    Number of packages to be installed: 2
    
    The process will require 104 MiB more space.
    41 MiB to be downloaded.
    [rabbit1.local] [1/2] Fetching rabbitmq-3.7.15.txz: 100%    9 MiB 762.2kB/s    00:12    
    [rabbit1.local] [2/2] Fetching erlang-runtime19-21.3.8.2.txz: 100%   33 MiB 978.8kB/s    00:35    
    Checking integrity... done (0 conflicting)
    [rabbit1.local] [1/2] Installing erlang-runtime19-21.3.8.2...
    [rabbit1.local] [1/2] Extracting erlang-runtime19-21.3.8.2: 100%
    [rabbit1.local] [2/2] Installing rabbitmq-3.7.15...
    ===> Creating groups.
    Creating group 'rabbitmq' with gid '135'.
    ===> Creating users
    Creating user 'rabbitmq' with uid '135'.
    [rabbit1.local] [2/2] Extracting rabbitmq-3.7.15: 100%
    Message from erlang-runtime19-21.3.8.2:
    
    ===========================================================================
    
    To use this runtime port for development or testing, just prepend
    its binary path ("/usr/local/lib/erlang19/bin") to your PATH variable.
    
    ===========================================================================
    
    (...)
    
    // 对于另一个 rabbit2 Jail,同样执行相同的操作。 //
    host # for I in 1 2; do jexec rabbit${I} which rabbitmqctl; done
    /usr/local/sbin/rabbitmqctl
    /usr/local/sbin/rabbitmqctl
    host # for I in 1 2; do cat >> /jail/rabbit${I}/etc/hosts << __EOF
    192.168.43.101 rabbit1
    192.168.43.102 rabbit2
    
    __EOF
    done
    host # cat /jail/rabbit?/etc/hosts | grep 192.168.43 | sort -n | uniq -c
    2 192.168.43.101 rabbit1
    2 192.168.43.102 rabbit2
    host # jexec rabbit1 /usr/local/etc/rc.d/rabbitmq rcvar
    # rabbitmq
    #
    rabbitmq_enable="NO"
    #   (default: "")
    host # for I in 1 2; do jexec rabbit${I} sysrc rabbitmq_enable=YES; done
    rabbitmq_enable:  -> YES
    rabbitmq_enable:  -> YES
    host # for I in 1 2; do jexec rabbit${I} service rabbitmq start; done
    Starting rabbitmq.
    Starting rabbitmq.
    rabbit1 # rabbitmq-plugins list
     Configured: E = explicitly enabled; e = implicitly enabled
     | Status: * = running on rabbit@rabbit1
     |/
    [  ] rabbitmq_amqp1_0                  3.7.15
    [  ] rabbitmq_auth_backend_cache       3.7.15
    [  ] rabbitmq_auth_backend_http        3.7.15
    [  ] rabbitmq_auth_backend_ldap        3.7.15
    [  ] rabbitmq_auth_mechanism_ssl       3.7.15
    [  ] rabbitmq_consistent_hash_exchange 3.7.15
    [  ] rabbitmq_event_exchange           3.7.15
    [  ] rabbitmq_federation               3.7.15
    [  ] rabbitmq_federation_management    3.7.15
    [  ] rabbitmq_jms_topic_exchange       3.7.15
    [  ] rabbitmq_management               3.7.15
    [  ] rabbitmq_management_agent         3.7.15
    [  ] rabbitmq_mqtt                     3.7.15
    [  ] rabbitmq_peer_discovery_aws       3.7.15
    [  ] rabbitmq_peer_discovery_common    3.7.15
    [  ] rabbitmq_peer_discovery_consul    3.7.15
    [  ] rabbitmq_peer_discovery_etcd      3.7.15
    [  ] rabbitmq_peer_discovery_k8s       3.7.15
    [  ] rabbitmq_random_exchange          3.7.15
    [  ] rabbitmq_recent_history_exchange  3.7.15
    [  ] rabbitmq_sharding                 3.7.15
    [  ] rabbitmq_shovel                   3.7.15
    [  ] rabbitmq_shovel_management        3.7.15
    [  ] rabbitmq_stomp                    3.7.15
    [  ] rabbitmq_top                      3.7.15
    [  ] rabbitmq_tracing                  3.7.15
    [  ] rabbitmq_trust_store              3.7.15
    [  ] rabbitmq_web_dispatch             3.7.15
    [  ] rabbitmq_web_mqtt                 3.7.15
    [  ] rabbitmq_web_mqtt_examples        3.7.15
    [  ] rabbitmq_web_stomp                3.7.15
    [  ] rabbitmq_web_stomp_examples       3.7.15
    host # for I in 1 2; do jexec rabbit${I} rabbitmq-plugins enable rabbitmq_management; done
    The following plugins have been configured:
      rabbitmq_management
      rabbitmq_management_agent
      rabbitmq_web_dispatch
    Applying plugin configuration to rabbit@rabbit1...
    The following plugins have been enabled:
      rabbitmq_management
      rabbitmq_management_agent
      rabbitmq_web_dispatch
    
    started 3 plugins.
    
    (...)
    
    // 对于另一个 rabbit2 Jail,同样启用 Web 界面插件。 //
    rabbit1 # rabbitmq-plugins list
     Configured: E = explicitly enabled; e = implicitly enabled
     | Status: * = running on rabbit@rabbit1
     |/
    [  ] rabbitmq_amqp1_0                  3.7.15
    [  ] rabbitmq_auth_backend_cache       3.7.15
    [  ] rabbitmq_auth_backend_http        3.7.15
    [  ] rabbitmq_auth_backend_ldap        3.7.15
    [  ] rabbitmq_auth_mechanism_ssl       3.7.15
    [  ] rabbitmq_consistent_hash_exchange 3.7.15
    [  ] rabbitmq_event_exchange           3.7.15
    [  ] rabbitmq_federation               3.7.15
    [  ] rabbitmq_federation_management    3.7.15
    [  ] rabbitmq_jms_topic_exchange       3.7.15
    [E*] rabbitmq_management               3.7.15
    [e*] rabbitmq_management_agent         3.7.15
    [  ] rabbitmq_mqtt                     3.7.15
    [  ] rabbitmq_peer_discovery_aws       3.7.15
    [  ] rabbitmq_peer_discovery_common    3.7.15
    [  ] rabbitmq_peer_discovery_consul    3.7.15
    [  ] rabbitmq_peer_discovery_etcd      3.7.15
    [  ] rabbitmq_peer_discovery_k8s       3.7.15
    [  ] rabbitmq_random_exchange          3.7.15
    [  ] rabbitmq_recent_history_exchange  3.7.15
    [  ] rabbitmq_sharding                 3.7.15
    [  ] rabbitmq_shovel                   3.7.15
    [  ] rabbitmq_shovel_management        3.7.15
    [  ] rabbitmq_stomp                    3.7.15
    [  ] rabbitmq_top                      3.7.15
    [  ] rabbitmq_tracing                  3.7.15
    [  ] rabbitmq_trust_store              3.7.15
    [e*] rabbitmq_web_dispatch             3.7.15
    [  ] rabbitmq_web_mqtt                 3.7.15
    [  ] rabbitmq_web_mqtt_examples        3.7.15
    [  ] rabbitmq_web_stomp                3.7.15
    [  ] rabbitmq_web_stomp_examples       3.7.15
    rabbot1 # cat /var/db/rabbitmq/.erlang.cookie; echo
    NOEVQNXJDNLAJOSVWNIW
    rabbot1 #
    host # for I in 1 2; do jexec rabbit${I} service rabbitmq stop; done
    Stopping rabbitmq.
    Waiting for PIDS: 88684.
    Stopping rabbitmq.
    Waiting for PIDS: 20976.
    host # for I in 1 2; do cat > /jail/rabbit${I}/var/db/rabbitmq/.erlang.cookie << __EOF
    RABBITMQFREEBSDJAILS
    __EOF
    done
    host # for I in 1 2; do jexec rabbit${I} service rabbitmq start; done
    Starting rabbitmq.
    Starting rabbitmq.
    host # for I in 1 2; do jexec rabbit${I} cat /var/db/rabbitmq/.erlang.cookie; done
    RABBITMQFREEBSDJAILS
    RABBITMQFREEBSDJAILS
    host # for I in 1 2; do jexec rabbit${I} rabbitmqctl add_user admin ADMINPASSWORD; done
    Adding user "admin" ...
    Adding user "admin" ...
    
    host # for I in 1 2; do jexec rabbit${I} rabbitmqctl set_user_tags admin administrator; done
    Setting tags for user "admin" to [administrator] ...
    Setting tags for user "admin" to [administrator] ...
    
    host # for I in 1 2; do jexec rabbit${I} rabbitmqctl set_permissions -p / admin ".*" ".*" ".*" ; done
    Setting permissions for user "admin" in vhost "/" ...
    Setting permissions for user "admin" in vhost "/" ...
    rabbit1 # rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1]}]},
     {running_nodes,[rabbit@rabbit1]},
     {cluster_name,},
     {partitions,[]},
     {alarms,[{rabbit@rabbit1,[]}]}]
    
    rabbit2 # hostname
    rabbit2.local
    
    rabbit2 # rabbitmqctl join_cluster rabbit@rabbit1
    Error: this command requires the 'rabbit' app to be stopped on the target node. Stop it with 'rabbitmqctl stop_app'.
    Arguments given:
            join_cluster rabbit@rabbit1
    
    Usage
    
    rabbitmqctl [--node ] [--longnames] [--quiet] join_cluster [--disc|--ram]
    rabbit2 # rabbitmqctl stop_app
    Stopping rabbit application on node rabbit@rabbit2 ...
    
    rabbit2 # rabbitmqctl join_cluster rabbit@rabbit1
    Clustering node rabbit@rabbit2 with rabbit@rabbit1
    
    rabbit2 # rabbitmqctl start_app
    Starting node rabbit@rabbit2 ...
     completed with 5 plugins.
    
    rabbit2 # rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit2 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]},
     {cluster_name,},
     {partitions,[]},
     {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]}]}]
    
    rabbit1 # rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]},
     {cluster_name,},
     {partitions,[]},
     {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]
    rabbit1 # rabbitmqctl set_cluster_name rabbit@cluster
    Setting cluster name to rabbit@cluster ...
    
    rabbit1 # rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]},
     {cluster_name,},
     {partitions,[]},
     {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]
    rabbit1 # rabbitmqctl set_policy ha "^ha-\.*" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
    Setting policy "ha-mirror" for pattern "^ha-\." to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0" for vhost "/" ...
    host # pkg install go
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            go: 1.12.5,1
    
    Number of packages to be installed: 1
    
    The process will require 262 MiB more space.
    75 MiB to be downloaded.
    
    Proceed with this action? [y/N]: y
    (...)
    
    host % go version
    go version go1.12.5 freebsd/amd64
    host % cat send.go
    package main
    
    import (
      "log"
      "amqp"
    )
    
    func FAIL_ON_ERROR(err error, msg string) {
      if err != nil {
        log.Fatalf("%s: %s", msg, err)
      }
    }
    
    func main() {
      conn, err := amqp.Dial("amqp://admin:[email protected]:5672/")
      FAIL_ON_ERROR(err, "ER: failed to connect to RabbitMQ")
      defer conn.Close()
    
      ch, err := conn.Channel()
      FAIL_ON_ERROR(err, "ER: failed to open channel")
      defer ch.Close()
    
      q, err := ch.QueueDeclare(
        "ha-default", // 队列名称
        false,        // 是否持久化
        false,        // 未使用时是否删除
        false,        // 是否排他
        false,        // 是否不等待
        nil,          // 参数
      )
      FAIL_ON_ERROR(err, "ER: failed to declare queue")
    
      body := "Hello World!"
    
      for i := 1; i <= 10; i++ {
        err = ch.Publish(
          "",     // exchange 交换
          q.Name, // routing key 路由键
          false,  // mandatory 强制
          false,  // immediate 立即
          amqp.Publishing{
            ContentType: "text/plain",
            Body:        []byte(body),
          })
        log.Printf("IN: sent message '%s' (%d)", body, i)
        FAIL_ON_ERROR(err, "ER: failed to publish message")
      }
    
    }
    host % go run send.go
    send.go:5:3: cannot find package "amqp" in any of:
            /usr/local/go/src/amqp (from $GOROOT)
            /home/vermaden/.gopkg/src/amqp (from $GOPATH)
    host % mkdir -p ~/.gopkg/src
    host % cd !$
    host % pwd
    /home/vermaden/.gopkg/src
    host % fetch https://github.com/streadway/amqp/archive/master.zip
    host % unzip master.zip 
    Archive:  /home/vermaden/.gopkg/src/master.zip
       creating: amqp-master/
     extracting: amqp-master/.gitignore
     extracting: amqp-master/.travis.yml
     (...)
     extracting: amqp-master/uri.go
     extracting: amqp-master/uri_test.go
     extracting: amqp-master/write.go
    host % rm master.zip
    host % mv amqp-master amqp
    host % cd amqp
    host % pwd
    /home/vermaden/.gopkg/src/amqp
    host % exa
    _examples          confirms.go         delivery_test.go        LICENSE            spec091.go
    spec               confirms_test.go    doc.go                  pre-commit         tls_test.go
    allocator.go       connection.go       example_client_test.go  read.go            types.go
    allocator_test.go  connection_test.go  examples_test.go        read_test.go       uri.go
    auth.go            consumers.go        fuzz.go                 README.md          uri_test.go
    certs.sh           consumers_test.go   gen.sh                  reconnect_test.go  write.go
    channel.go         CONTRIBUTING.md     go.mod                  return.go          
    client_test.go     delivery.go         integration_test.go     shared_test.go     
    # GO SHELL SETUP
    mkdir -p ~/.gopkg
    export GOPATH=~/.gopkg
    export PATH="${PATH}:~/.gopkg"
    host % go run send.go
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (1)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (2)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (3)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (4)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (5)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (6)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (7)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (8)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (9)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (10)
    %
    host % cat receive.go
    package main
    
    import (
      "log"
      "amqp"
    )
    
    func FAIL_ON_ERROR(err error, msg string) {
      if err != nil {
        log.Fatalf("%s: %s", msg, err)
      }
    }
    
    func main() {
      conn, err := amqp.Dial("amqp://admin:[email protected]:5672/")
      FAIL_ON_ERROR(err, "ER: failed to connect to RabbitMQ")
      defer conn.Close()
    
      ch, err := conn.Channel()
      FAIL_ON_ERROR(err, "ER: failed to open channel")
      defer ch.Close()
    
      q, err := ch.QueueDeclare(
        "ha-default", // 队列名称
        false,        // 是否持久化
        false,        // 未使用时是否删除
        false,        // 是否排他
        false,        // 是否不等待
        nil,          // 参数
      )
      FAIL_ON_ERROR(err, "ER: failed to declare queue")
    
      msgs, err := ch.Consume(
        q.Name, // 队列
        "",     // 消费者
        true,   // 自动确认
        false,  // 是否排他
        false,  // no-local
        false,  // 是否不等待
        nil,    // 参数
      )
      FAIL_ON_ERROR(err, "ER: failed to register consumer")
    
      forever := make(chan bool)
    
      go func() {
        for d := range msgs {
          log.Printf("IN: received message: %s", d.Body)
        }
      }()
    
      log.Printf("IN: waiting for messages")
      log.Printf("IN: to exit press CTRL+C")
      <-forever
    }
    host % go run receive.go
    2019/06/05 13:54:34 IN: waiting for messages
    2019/06/05 13:54:34 IN: to exit press CTRL+C
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    2019/06/05 13:54:34 IN: received message: Hello World!
    ^C
    %
    host % go run receive.go
    2019/06/05 13:52:34 IN: waiting for messages
    2019/06/05 13:52:34 IN: to exit press CTRL+C
    host % go run send.go
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (1)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (2)
    2019/06/05 13:53:59 IN: sent message 'Hello World!' (3)
    (...)
    2019/06/05 13:56:26 IN: sent message 'Hello World!' (99998)
    2019/06/05 13:56:26 IN: sent message 'Hello World!' (99999)
    2019/06/05 13:56:26 IN: sent message 'Hello World!' (100000)
    %
    host # jls
       JID  IP Address      Hostname                      Path
         1  192.168.43.101  rabbit1.local                 /jail/rabbit1
         2  192.168.43.102  rabbit2.local                 /jail/rabbit2
    
    host # killall -9 -j 1
    
    host # umount /jail/rabbit1/dev
    host # service jail onestart rabbit1
    Starting jails: rabbit1.
    host #
    pkg query -e "%a = 0" "%n" $(pkg info -r python311)
      或者
    pkg query -e "%a = 0" "%n" $(pkg query '%ro' python311)
    pkg shell -cmd "SELECT p.name FROM deps AS d INNER JOIN packages AS p ON package_id = p.id WHERE d.origin = 'lang/python311' AND p.automatic = 0" < /dev/null

    • D45398:* 重新设计了锁方案,使其仅锁定一个 vnode,经过多轮审查后,最终提交于 7 月 13 日。

    D44288
    D44601
    D44788
    D45987
    EuroBSDCon 2023 大会报告
    /
    A
    ,各自说明略)
    /
    A
    ,说明略)
    pkg add(8)
    pkg delete(8)
    pkg version(8)
    pkg upgrade(8)
    pkg info(8)
    pkg lock(8)
    pkg unlock(8)
    pkg-search(8)
    pkg-which(8)
    pkg-audit(8)
    pkg-check(8)
    pkg-autoremove(8)
    pkg-updating(8)
    pkg-set(8)
    pkg-alias(8)
    pkg-query(8)
    pkg-rquery(8)
    pkg-anotate(8)
    pkg-shell(8)
    pkg-stats(8)
    pkg-clean(8)
    pkg-config(8)
    pkg-create(8)
    pkg-fetch(8)
    pkg-register(8)
    pkg-repo(8)
    pkg-shlib(8)
    pkg-ssh(8)
    pkg-triggers(8)
    pkg-repository(5)
    FreeBSD Ports Flavors
    FreeBSD Porter's Handbook - 7. Flavors
    FreeBSD Porter's Handbook - 5.2.2. Versions, DISTVERSION or PORTVERSION
    FreeBSD Porter's Handbook - 13. pkg-* files
    FreeBSD pkg コマンドチート
    【FreeBSD】pkg で 普段使 うサブコマンド 達
    pkg
    FreeBSD – パッケージソフトのインストールと 削除、アップデートのやり 方
    パッケージコマンド 早見表
    アプリケーションをインストールする (前編): packages
    FreeBSD 13.0 RELEASE - ports・pkg - pkg
    DSCF2553.JPG

    将服务拼接在一起的 CREATE_SERVICE(3) 宏。

    能力模式
    能力
    "Cost of a Data Breach Report 2023"
    https://www.cl.cam.ac.uk/research/security/capsicum/
    https://www.usenix.org/legacy/events/sec10/tech/full_papers/Watson.pdf
    https://wiki.freebsd.org/Capsicum
    #include <sys/capsicum.h>
    #include <stdio.h>
    
    int
    main(void)
    {
        /* 进入 Capsicum 的能力模式。 */
        cap_enter();
        printf("能力模式下的 Hello world\n");
        return (0);
    }
    int dirfd;
    
    dirfd = open("/home/jfree", O_RDONLY | O_DIRECTORY);
    cap_enter();
    
    /* 打开 "/home/jfree/foo"。 */
    if (openat(dirfd, "foo", O_RDONLY) < 0)
        printf("这不会发生\n");
    int dirfd;
    
    dirfd = open("/home/jfree", O_RDONLY | O_DIRECTORY);
    cap_enter();
    
    /* 打开 "/home/beastie"。 */
    if (openat(dirfd, "../beastie", O_RDONLY) < 0)
        printf("这将会发生\n");
    pid_t pid;
    int pipefd[2], result;
    
    pipe(pipefd);
    /*
     * 创建一个子进程并将其隔离在能力沙箱中,
     * 在其中执行危险代码。
     */
    pid = fork();
    if (pid == 0) {
        close(pipefd[0]);
        cap_enter();
        result = dangerous_function();
        write(pipefd[1], &result, sizeof(result));
        exit(0);
    }
    close(pipefd[1]);
    /* 从沙箱子进程获取结果。 */
    result = read(pipefd[0], &result, sizeof(result));
    printf("Result: %d\n", result);
    /* 在父进程中继续正常执行。 */
    cap_channel_t *cap_casper, *cap_net;
    struct addrinfo *res;
    int s;
    
    /* 获取访问 libcasper(3) 服务的能力。 */
    cap_casper = cap_init();
    
    /*
     * 使用 cap_casper 能力与 "system.net" casper 服务
     * 建立通信通道。
     */
    cap_net = cap_service_open(cap_casper, "system.net");
    
    /*
     * 不再需要打开更多 casper 服务。
     * 关闭 cap_casper 能力。
     */
    cap_close(cap_casper);
    
    /*
     * 使用 cap_net(3) 库提供的 getaddrinfo() 变体。
     */
    cap_getaddrinfo(cap_net, "freebsd.org", "80", NULL, &res);
    
    s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    
    /*
     * 使用 cap_net(3) 库提供的 connect() 变体。
     */
    cap_connect(cap_net, s, res->ai_addr, res->ai_addrlen);
    CREATE_SERVICE(name, limit_func, command_func, flags);
    /*
     * cap_net(3) casper 服务库使用的命令函数。
     */
    static int
    net_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
        nvlist_t *nvlout)
    {
        if (strcmp(cmd, "bind") == 0)
            return (net_bind(limits, nvlin, nvlout));
        else if (strcmp(cmd, "connect") == 0)
            return (net_connect(limits, nvlin, nvlout));
        else if (strcmp(cmd, "gethostbyname") == 0)
            return (net_gethostbyname(limits, nvlin, nvlout));
        else if (strcmp(cmd, "gethostbyaddr") == 0)
            return (net_gethostbyaddr(limits, nvlin, nvlout));
        else if (strcmp(cmd, "getnameinfo") == 0)
            return (net_getnameinfo(limits, nvlin, nvlout));
        else if (strcmp(cmd, "getaddrinfo") == 0)
            return (net_getaddrinfo(limits, nvlin, nvlout));
    
        return (EINVAL);
    }
    
    CREATE_SERVICE("system.net", net_limit, net_command, 0);
    /*
     * 向与 @chan 绑定的 casper 服务发送 "bind" 命令。
     */
    static int
    cap_bind(cap_channel_t *chan, int sockfd, const struct sockaddr *addr,
        socklen_t addrlen)
    {
        nvlist_t *nvl = nvlist_create(0);
        int error;
    
        nvlist_add_string(nvl, "cmd", "bind");
        nvlist_add_descriptor(nvl, "sockfd", sockfd);
        nvlist_add_binary(nvl, "addr", addr, addrlen);
    
        nvl = cap_xfer_nvlist(chan, nvl);
        if (nvl == NULL)
            return (-1);
    
        error = nvlist_get_number(nvl, "error");
        if (error != 0) {
            nvlist_destroy(nvl);
            errno = error;
            return (-1);
        }
    
        error = dup2(sockfd, nvlist_get_descriptor(nvl, "sockfd"));
        nvlist_destroy(nvl);
    
        return (error == -1 ? -1 : 0);
    }
    if (strcmp(cmd, "bind") == 0)
            return (net_bind(limits, nvlin, nvlout));
    /*
     * net_bind() 函数的简化版。
     * 负责从 @nvlin 提取参数,调用 bind(2),
     * 并将返回值加入 @nvlout。
     */
    static int
    net_bind(const nvlist_t *limits __unused, nvlist_t *nvlin, nvlist_t *nvlout)
    {
        int sockfd;
        const void *addr;
        size_t len;
    
        addr = nvlist_get_binary(nvlin, "addr", &len);
        sockfd = nvlist_take_descriptor(nvlin, "sockfd");
        if (bind(sockfd, saddr, len) < 0) {
            int serrno = errno;
            close(sockfd);
            return (serrno);
        }
        nvlist_move_descriptor(nvlout, "sockfd", sockfd);
    
        return (0);
    }
    nvl = cap_xfer_nvlist(chan, nvl);
        if (nvl == NULL)
            err(1, "Failed transfer bind() nvlist");
    /*
     * 使用 cap_net(3) 的限制机制,仅允许解析 freebsd.org
     * 在 80 端口上的地址。
     *
     * 假设 cap_net(3) 服务已经被打开并在 @cap_net 上监听。
     */
    cap_net_limit_t *limit;
    int familylimit;
    
    /* 仅允许名称解析 (cap_getaddrinfo(3))。 */
    limit = cap_net_limit_init(cap_net, CAPNET_NAME2ADDR);
    
    /* 将名称解析限制为 "freebsd.org" 的 80 端口。 */
    cap_net_limit_name2addr(limit, "freebsd.org", "80");
    
    /* 将名称解析限制为 IPv4 地址。 */
    familylimit = AF_INET;
    cap_net_limit_name2addr_family(limit, &familylimit, 1);
    
    /* 将限制应用到 cap_net。 */
    cap_net_limit(limit);
    /*
     * cap_net(3) 中 net_limit() 函数的片段。
     * 为清晰起见,部分代码被省略。
     * 上下文见 "lib/libcasper/services/cap_net/cap_net.c"。
     */
    while ((name = nvlist_next(newlimits, NULL, &cookie)) != NULL) {
            /* ... */
            if (strcmp(name, LIMIT_NV_BIND) == 0) {
                    hasbind = true;
                    if (!verify_bind_newlimts(oldlimits,
                        cnvlist_get_nvlist(cookie))) {
                            return (ENOTCAPABLE);
                    }
            } else if (strcmp(name, LIMIT_NV_CONNECT) == 0) {
                    hasconnect = true;
                    if (!verify_connect_newlimits(oldlimits,
                        cnvlist_get_nvlist(cookie))) {
                            return (ENOTCAPABLE);
                    }
            } else if (strcmp(name, LIMIT_NV_ADDR2NAME) == 0) {
                    hasaddr2name = true;
                    if (!verify_addr2name_newlimits(oldlimits,
                        cnvlist_get_nvlist(cookie))) {
                            return (ENOTCAPABLE);
                    }
            } else if (strcmp(name, LIMIT_NV_NAME2ADDR) == 0) {
                    hasname2addr = true;
                    if (!verify_name2addr_newlimits(oldlimits,
                        cnvlist_get_nvlist(cookie))) {
                            return (ENOTCAPABLE);
                    }
            }
    }
    open("ktrace.out", O_RDONLY | O_CREAT | O_TRUNC);
    ktrace("ktrace.out", KTROP_SET, KTRFAC_CAPFAIL, getpid());
    open("ktrace.out", O_RDONLY | O_CREAT | O_TRUNC);
    ktrace("ktrace.out", KTROP_SET, KTRFAC_CAPFAIL, getpid());
    
    cap_rights_init(&rights, CAP_READ);
    caph_rights_limit(STDERR_FILENO, &rights);
    write(STDERR_FILENO, &val, sizeof(val));
    
    cap_rights_set(&rights, CAP_WRITE);
    caph_rights_limit(STDERR_FILENO, &rights);
    
    kinf.kf_structsize = sizeof(struct kinfo_file);
    fcntl(STDIN_FILENO, F_KINFO, &kinf);
    
    socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    
    addr.sin_family = AF_INET;
    addr.sin_port = htons(5000);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP),
        (const struct sockaddr *)&addr, sizeof(addr));
    sendto(fd, NULL, 0, 0, (const struct sockaddr *)&addr, sizeof(addr));
    
    kill(getppid(), SIGCONT);
    
    openat(AT_FDCWD, "/", O_RDONLY);
    
    CPU_SET(0, &cpuset_mask);
    cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, getppid(),
        sizeof(cpuset_mask), &cpuset_mask);
    # ./cap_violate
    # kdump
      1915 cap_violate CAP   operation requires CAP_WRITE, descriptor holds CAP_READ
      1915 cap_violate CAP   attempt to increase capabilities from CAP_READ to CAP_READ,CAP_WRITE
      1915 cap_violate CAP   system call not allowed: fcntl, cmd: F_KINFO
      1915 cap_violate CAP   socket: protocol not allowed: IPPROTO_ICMP
      1915 cap_violate CAP   system call not allowed: bind
      1915 cap_violate CAP   sendto: restricted address lookup: struct sockaddr { AF_INET, 0.0.0.0:5000 }
      1915 cap_violate CAP   kill: signal delivery not allowed: SIGCONT
      1915 cap_violate CAP   openat: restricted VFS lookup: AT_FDCWD
      1915 cap_violate CAP   cpuset_setaffinity: restricted cpuset operation
    # unzip foo.zip
    # kdump
      1926 unzip    NAMI  "foo.zip"
      1926 unzip    CAP   openat: restricted VFS lookup: AT_FDCWD
      1926 unzip    CAP   system call not allowed: open
      1926 unzip    NAMI  "/etc/localtime"
      1926 unzip    NAMI  "bar"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    CAP   system call not allowed: mkdir
      1926 unzip    NAMI  "bar"
      1926 unzip    NAMI  "bar"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    NAMI  "bar/bar.txt"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    NAMI  "bar/bar.txt"
      1926 unzip    CAP   openat: restricted VFS lookup: AT_FDCWD
      1926 unzip    NAMI  "baz"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    CAP   system call not allowed: mkdir
      1926 unzip    NAMI  "baz"
      1926 unzip    NAMI  "baz"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    NAMI  "baz/baz.txt"
      1926 unzip    CAP   fstatat: restricted VFS lookup: AT_FDCWD
      1926 unzip    NAMI  "baz/baz.txt"
      1926 unzip    CAP   openat: restricted VFS lookup: AT_FDCWD
    /*
     * 将文件描述符限制为只读。
     */
    cap_rights_t rights;
    int fd;
    char buf[1] = 'x';
    
    fd = open("/home/jfree/foo", O_RDWR);
    
    cap_rights_init(&rights, CAP_READ);
    cap_rights_limit(fd, &rights);
    
    if (read(fd, buf, sizeof(buf)) < 0)
        printf("这不会发生,因为我们有 CAP_READ\n");
    
    if (write(fd, buf, sizeof(buf)) < 0)
        printf("这将会发生,因为我们缺少 CAP_WRITE\n");
    /*
     * 试图扩展描述符的权限。
     */
    cap_rights_t rights;
    int fd;
    
    fd = open("/home/jfree/foo", O_RDWR);
    
    cap_rights_init(&rights, CAP_READ);
    cap_rights_limit(fd, &rights);
    
    cap_rights_set(&rights, CAP_WRITE);
    if (cap_rights_limit(fd, &rights) < 0)
        printf("应用权限失败;权限永远不能被提升\n");

    使用 Pacemaker 与 Corosync 构建 FreeBSD 集群

    • 原文:

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2020/09/03

    我一直很想找到适合 FreeBSD 系统的“正统”集群软件。最近我有机会在 Linux 系统上运行几个基于 Pacemaker/Corosync 的集群。我开始思考如何在 FreeBSD 上实现类似的高可用性解决方案,当我发现 Pacemaker 和 Corosync 工具在 FreeBSD Ports 和包中分别可以通过 net/pacemaker2 和 net/corosync2 获得时,我真的非常震惊。

    在本文中,我将检查 Pacemaker 和 Corosync 集群在 FreeBSD 上的运行情况。

    FreeBSD 开发计划

    翻译同步至

    FreeBSD 的生命周期为每个大版本 4 年,小版本是发布新的小版本版后 +3 个月。

    FreeBSD 15 开发计划

    FreeBSD 15.0 计划

    FreeBSD 与 HiFi 音频设置:比特完美、均衡器、实时处理

    • 原文:

    • 作者:Marcin Szewczyk-Wilgan

    译者注:

    • HiFi:High-Fidelity,高保真音效

    为什么你应该将所有东西从 Linux 迁移到 BSD

    • 原文: 和 。

    • 最后更新时间:2023-10-30

    作为操作系统,GNU/Linux 已经变得相当混乱,这主要是因为项目的碎片化、内核中的臃肿代码,但更重要的原因是企业利益的操控。的确存在一些技术上的理由,使得从 GNU/Linux 迁移到 BSD 在某些情况下是合理的,但本文并非为了讨论这些问题,它更像是对 Linux 现状的“分析”,更确切地说,是一篇带有强烈个人观点的评论文章。

    pacemaker

    集群,有很多定义。我最喜欢的定义是:集群是即使失去其中一个节点仍保持冗余的系统(仍然是集群)。这意味着根据这个定义,集群的最少节点数是 3 个。两节点集群存在较大问题,因为它们最容易出现脑裂问题。这就是为什么在两节点集群中,通常会添加额外的设备或系统,以确保不会发生脑裂。例如,可以添加第三个节点,不提供任何资源或服务,仅作为“见证者”角色。另一种方式是添加共享磁盘资源,其作用相同,通常是使用 SCSI-3 持久保留机制的原始卷。

    搭建实验室

    一如既往,整个实验将基于 VirtualBox,并由 3 台主机组成。为了不创建 3 个相同的 FreeBSD 安装,我直接使用了由 FreeBSD 项目提供的 12.1-RELEASE 虚拟机镜像:

    • https://download.freebsd.org/ftp/releases/VM-IMAGES/12.1-RELEASE/

    有多种格式可选 – qcow2/raw/vhd/vmdk – 因为我将使用 VirtualBox,所以选择了格式 VMDK 。

    下面是 GlusterFS 集群的主机列表:

    • 10.0.10.111 node1

    • 10.0.10.112 node2

    • 10.0.10.113 node3

    每个 VirtualBox 的 FreeBSD 虚拟机均为默认配置(如 VirtualBox 向导所建议),内存为 512 MB,网络模式为 NAT Network(NAT 网络),如下图所示。

    machine

    下面是 VirtualBox 上 NAT Network(NAT 网络) 的配置。

    nat-network-01
    nat-network-02

    在尝试连接 FreeBSD 主机之前,需要在每台虚拟机内进行最简网络配置。每台 FreeBSD 主机将具有如下示例的最简 /etc/rc.conf 文件(以 node1 为例)。

    为了搭建实验环境,我们需要允许 root 登录这些 FreeBSD 主机,在 /etc/ssh/sshd_config 文件中设置 PermitRootLogin yes。更改以后,还需要重启 sshd(8) 服务。

    通过使用带有 端口转发 的 NAT Network(NAT 网络),FreeBSD 主机可以通过本地主机端口访问。例如,可以通过端口 2211 访问 node1,可以通过端口 2212 访问 node2,依此类推。如下 sockstat 工具输出所示。

    nat-network-03-sockstat
    nat-network-04-ssh

    要从 VirtualBox 主机系统连接到这样的虚拟机,需要使用如下命令:

    软件包

    现在我们已经可以通过 ssh(1) 连接,需要安装所需的软件包。为了让我们的虚拟机能够解析 DNS 查询,还需要做最后一件事。同时,我们将切换 pkg(8) 软件包到 “quarterly” 分支。

    请记得在 node2 和 node3 系统上重复执行上述两条命令。

    现在我们将安装软件包 Pacemaker 和 Corosync。

    下面是 pacemaker2 和 corosync2 的一些需要我们处理的信息。

    我们需要修改 kern.ipc.maxsockbuf 参数。那就开始修改吧。

    我们来查看这些软件包都包含了哪些可执行文件。

    初始化集群

    现在我们将初始化 FreeBSD 集群。

    首先需要确保各节点的名称可以通过 DNS 解析。

    现在我们将生成 Corosync 密钥。

    现在是 Corosync 配置文件的部分。当然,软件包维护者已经提供了一些示例。

    我们将使用第二个示例作为配置的基础。

    现在我们需要将 Corosync 密钥和配置文件分发到集群中的各个节点。

    可以使用一些专门为此创建的简单工具,例如 net/csync2 集群同步工具,但传统的 net/rsync 也同样可用。

    现在我们来检查它们是否一致。

    一致。

    现在我们可以在 /etc/rc.conf 文件中添加 corosync_enable=YES 和 pacemaker_enable=YES。

    那就启动这些服务吧。

    在 node2 和 node3 系统上也执行同样操作。

    由于 Pacemaker 还未运行,因此操作会失败。

    现在我们将启动它。

    需要给它一些启动时间,因为如果你立即执行 crm status 命令,会看到如下所示的 0 nodes configured 消息。

    ……但过一会儿,所有节点都会被检测到,一切按预期正常工作。

    Pacemaker 运行正常。

    我们可以查看 Corosync 如何识别其成员。

    ……或者查看 quorum 信息。

    Corosync 日志文件中充满了以下信息。

    配置如下。

    由于我们不会配置 STONITH 机制,因此将其禁用。

    禁用 STONITH 后的新配置。

    STONITH 配置超出了本文的范围,但正确配置的 STONITH 如下所示。

    stonith

    第一个服务

    现在我们将配置第一个高可用服务——经典示例——一个浮动 IP 地址 :🙂:

    让我们看看它的运行情况。

    看起来不错——我们来检查一下集群状态。

    糟糕。Linux 思维模式。系统中预期存在 ip(8) 命令。但这是 FreeBSD,像所有 UNIX 系统一样,它提供的是 ifconfig(8) 命令。

    我们必须另想办法。目前我们先删除这个无用的 IP 服务。

    删除后的状态。

    自定义资源

    让我们查看默认 Pacemaker 安装提供了哪些资源。

    资源不多……我们将尝试将 Dummy 服务修改为在 FreeBSD 上的 IP 切换器。

    由于 WordPress 博客系统的限制,我不得不将这个 ifconfig 资源以图片形式发布……但别担心,文本版本也可在这里下载——ifconfig.odt。

    此外,第一个版本的效果并不理想……

    但在为其添加 755 权限并进行了若干(上百次)修改后,它终于可以使用了。

    看起来可以使用。

    这是 ifconfig 资源。目前它相当有限,而且 IP 地址是硬编码的。

    让我们尝试向 FreeBSD 集群添加新的 IP 资源。

    测试

    已添加。

    我们来看现在 status 命令显示的情况。

    糟糕,我忘了将这个新的 ifconfig 资源复制到其他节点。现在来修复它。

    现在我们先停止、删除,然后重新添加这个重要的资源。

    祈祷顺利吧。

    看起来运行正常。

    让我们验证它是否确实在应该的节点上启动。

    看起来确实在工作。

    现在我们尝试将它移动到集群中的另一台节点。

    已成功切换到 node3 系统。

    现在我们将 关闭 node3 系统,以检查这个 IP 是否真的具备高可用性。

    看起来故障切换进行得很顺利。

    crm 命令还会对其输出的不同部分进行高亮显示。

    failover

    很高兴知道 Pacemaker 和 Corosync 集群在 FreeBSD 上运行良好。

    虽然需要一些工作来编写必要的资源文件,但只要有时间和决心,完全可以将 FreeBSD 打造成非常强大的高可用集群。

    FreeBSD Cluster with Pacemaker and Corosync
    ✔️ 已完成

    已提交到源代码存储库的项目。

    项目
    负责人
    已提交 / 审查 / 补丁

    arm64 分支目标识别(BTI)

    andrew

    arm64 bhyve

    andrew

    在 bhyve 中的单步 AMD CPU

    jhb Bojan

    、

    借助 CTF 美化 DDB 的输出

    markj Bojan

    ✈️ 已实现

    未来 2 年内 / 在下次发布之前已经存在且可以传递至上游的项目(也许需要努力使其达到可回馈上游的状态)

    项目
    负责人
    提交 / 审查 / 补丁

    在 mv(1) 中实现 copy_file_range()

    pjd

    更好的 copy_file_range() 回滚机制/封装器

    pjd

    amd64/arm64 急救内核

    markj / Klara

    草稿在

    iovec 封装器

    brooks

    🚧 正在进行

    项目
    负责人
    状态

    重写 certctl

    des

    DRM 回归基本系统

    manu

    完成 90%

    devd 事件磁盘错误额外信息

    imp

    75%

    对默认 TCP 堆栈模块化

    jtl

    完成代码;需要 UX 支持、使用户更容易使用

    💸 需要做的

    未来两年内支持产品和服务所需的东西

    项目
    负责人
    投入 / 审查 / 补丁 / 状态

    新的 ELF 内核转储格式

    jhb markj

    pkg 组

    allanjude

    为无工具链的 Poudriere 提供支持 jail

    allanjude

    外部工具链支持

    brooks

    🥺 想要 🙏

    这些东西有当然最好、没有也行。

    东西
    拥有者
    提交 / 审核 / 补丁 / 状态

    清理 make -s

    jhb

    清理警告信息并使其保持在控制之下 🔥

    TPM 支持(GELI、ZFS)

    allanjude tsoome

    --

    ZFS 加密启动支持

    tsoome allanjude

    仅支持 UEFI

    取代 smbfs(v2 及更高版本)

    emaste jhixson

    --

    🗑️ 准备删除 🪓

    我们可能希望废弃的项目。可能需要进一步讨论以达成共识。

    项目
    负责人
    提交 / 审核 / 补丁

    Firewire 🔥(火线)

    imp

    宁愿晚一些而不是早一点(我们是否应该在更早的时候去除磁盘支持、因为有一个被 GIANT 锁定的 CAM 驱动程序)(我们是否迁移到 16?是的)

    i386 内核

    imp

    时间?

    powerpc、powerpcspe 内核

    imp

    PS3 🎮

    imp

    沒人使用了(我们需要移植 PS5!)

    图例

    符号
    含义

    ??

    状态待定

    !!

    需要新的负责人

    Updates prior to BSDCan 2025
    FreeBSD 15.0 Planning
    bit-perfect:比特完美,指进入 DAC 解码器的数字信号为原始数据。
  • filters:滤镜,指可以对原始音频进行处理以产生特殊效果(如添加回声)

  • 完整指南:将 FreeBSD 配置为发烧友音频服务器 —— 设置系统及音频子系统参数、实时操作、比特完美信号处理,以及启用和调节系统图形均衡器(equalizer)和使用 FFmpeg 滤镜实现高质量音频均衡的最佳方法。Linux 用户也能从中获得有用信息,尤其是在配置和个性化 MPD 播放器及滤镜方面。

    出于对音乐的热爱,我对数字音频处理解决方案有着 20 多年的业余兴趣。我曾使用 Linux 及其底层工具作为外部数模转换器(以下简称 DAC)的解码器、播放器和传输工具。直到我开始认真关注 FreeBSD。

    作为 HiFi 发烧友音频系统一部分的 FreeBSD

    在我看来,使 FreeBSD 优于 Linux 的,正是它那精确追踪音频设备参数、系统内核参数以及对其进行修改的能力。当然,我们这里讨论的仅限于操作系统层面对音频的处理(即在 FreeBSD 中由 OSS/sound(4) 驱动完成,Linux 中由 ALSA 完成),并以一种方式配置系统,使得音频数据只在听音设备的硬件层面以 比特完美 模式处理,也就是说:在传输到外部 DAC 设备或声卡的过程中,不进行重采样、路由或声道混合。因此,我自然省略了诸如 Jack 服务器、PulseAudio 或 RedHat 旗下令人头疼的 PipeWire 这类额外音频层的使用和配置。当然,软件信号解码器的问题仍存在,后文会详细论述。

    使用 FreeBSD 的另一个优势是,它对实时操作系统(RTOS)和实时程序的支持更好。虽然“更好”并不意味着完美,但在这方面 Linux 远远落后。直到 2024 年,实时 Linux(PREEMPT_RT)才正式成为内核及其主线软件的一部分。

    什么是实时系统以及它在音频处理中的重要性

    实时操作系统(RTOS)是一类专门设计用来以高精度和高可靠性处理时间敏感任务的操作系统。与通用操作系统不同,实时系统旨在在最严格、最短的时间内响应事件并处理数据。

    RTOS 的关键特征是其可预测的运行,这意味着关键任务能够保证在规定的时间内完成。人们常误以为实时系统运行更快,实际上并非如此,实时系统关注的是可靠性和可预测性。 正是这些特性使得 RTOS 广泛应用于时间至关重要的领域,比如工业自动化系统、航天设备、医疗器械,当然也包括音频处理领域。

    以实时系统模式运行音频服务器和播放器,能够让我们对处理质量有更强的掌控感和信心。因此,如果我们希望构建一款不妥协的发烧友音频系统,FreeBSD 将是个极佳的选择。在我们的方案中,所指的是作为传输端或立体声播放器的系统,而非专业录音室应用——后者涉及混音声道或与 MIDI 接口交互,使用 RTOS 的目的则有所不同。

    FreeBSD 与 Linux 的音质比较

    我进行了大量的听音测试,结果显示,在比特完美模式下配置的 FreeBSD 和 Linux 系统在音频设备性能方面表现相同。然而,FreeBSD 的优势在于它能够精确控制操作系统层面硬件处理流程中的所有参数,并且可以对其进行调整,这赋予了我们几乎极致的掌控和了解能力。

    Linux 的音频处理系统 ALSA 大多自动调整所有参数,因此启用接口(或协议)hw:0,0 的比特完美模式是否真如我们所期望的那样,仍值得商榷。而在 FreeBSD 中,不仅有直观的 sound(4) 驱动中的 dev.pcm.%d.bitperfect 参数,更有其它配置选项和完全透明的操作,提供了更多调控自由度。

    FreeBSD 与 Linux 的音频硬件支持

    不过必须指出,FreeBSD 和 Linux 之间有一个非常重要的区别。在 Linux 中,哪怕是在比特完美模式(hw:0,0)下,几乎所有内置声卡或 USB DAC 也都能正常工作;但 FreeBSD 并非如此。启用参数 dev.pcm.%d.bitperfect=1 有时会引发问题。例如,设备支持的 PCM 格式描述符无法被正确识别(尤其是针对 XMOS 通信芯片),强制设置该参数,包括使用 dev.pcm.%d.play.vchanformat=s16le:2.0,都无法达到预期效果。我测试过的 Presonus Audiobox iOne 系列设备就是如此。此时需要关闭比特完美模式,系统会自动启用对所有数据源以 48 kHz 的固定重采样。但在 Linux 下,这些设备运行正常。

    此外,还应提及一个长期存在的问题,特别是针对使用 USB DAC 的硬件配置——播放过程中偶尔出现的干扰声和点击声,大约每十几分钟出现一次。虽然这没有固定规律——某些硬件规格完全正常,而某些则问题频出。此问题值得另写文章详细探讨,尽管尝试了不同的延迟参数、缓冲区调整、PCM 设备调试和各个组件间的干扰分析,至今仍未找到解决方案。

    幸运的是,在大多数情况下,FreeBSD 中仍能按预期配置音频设备。简单来说,大部分参数系统默认已作出合理选择。

    FreeBSD 与音频子系统配置

    接下来介绍 FreeBSD 及其音频子系统的参数配置。本文所述设置基于最新版本 FreeBSD 14.2,自 2024 年以降,经过数年停滞后,FreeBSD 的音频栈迎来了许多新特性。按 FreeBSD 基金会的说法,相关工作仍在持续推进。

    音频服务器和播放器由 MPD(音乐播放器守护进程,Linux 中命名为 mpd,FreeBSD 中为 musicpd(1))承担。MPD 服务器的接口工具包括 ncmpcpp(1) 和 mpc(FreeBSD 中为 musicpc(1))。

    听音系统规格:

    • 电脑:HP t540 瘦客户机,AMD Ryzen,4GB DDR4 内存,16GB SSD

    • 存储:Seagate Expansion 2TB USB SSD

    • DAC:Cambridge Audio DacMagic Plus(新电容线路:松下 FM,ELNA 音频专用;Tomanek 电源),Presonus AudioBox iOne

    • USB 线缆:WireWorld ULTRAVIOLET 8

    • 耳机放大器:Forum608 IV 双单声道(A 类)

    • RCA 连接线:Audioquest Goldengate 0.6 米

    • 耳机:Beyerdynamic 990 Pro 250 欧姆,990 Edition 600 欧姆

    最常听的专辑:

    • Iron Maiden – Fear Of The Dark(铁娘子乐队 - 恐惧黑暗)

    • McIntosh Audiophile Test Reference 发烧友测试参考

    • Alan Parsons Project – Stereotomy(亚伦派森实验乐团-Stereotomy)

    • The WHO – Quadrophenia(谁人乐队 - 四重人格)

    • Depeche Mode – Violator(赶时髦乐队-Violator)

    • HD Audiophile Speaker Set-Up 高清发烧音箱设置(192-24)

    • TOOL – Lateralus(工具乐队-Lateralus)

    FreeBSD 配置文件

    FreeBSD 系统配置的主要且最重要的部分基于三个配置文件:/boot/loader.conf、/etc/sysctl.conf、/etc/rc.conf。以下是在比特完美音频和实时操作系统(RTOS)角色下系统运行相关的配置项。

    /boot/loader.conf

    ① 添加模块 sysctlinfo(4),该模块负责与各个内核 sysctl 状态和 MIB 树组件进行扩展的进程通信。此模块非必需,但部分应用程序(例如 mixertui(8))会使用该接口。

    ② 模块 mac_priority(4) 用于建立权限调度规则,使得特权用户可以让工具 rtprio(1) 以实时优先级运行进程。

    ③该参数负责启用 dev.pcm.5 设备的图形均衡器(equalizer)(上述规格中指的是 USB DAC 设备)。在比特完美配置中我们省略此项,具体内容详见后文 FreeBSD 中的图形均衡器 一节。

    /etc/sysctl.conf

    ①这是个非常重要的参数,它表示提高用于同步进程唤醒的软件时钟的精度,从而最小化处理器因进入和退出空闲状态而执行相对高开销操作的次数。

    如果想更深入了解进程唤醒延迟及系统时钟频率对该延迟的影响,推荐阅读 Paul Herman 的文章,文中除了测试结果,还提供了基准测试源码。

    为了直观展示参数 kern.timecounter.alloweddeviation 对延迟的影响,下面是我在系统上的测试结果:

    ② 驱动参数 snd_uaudio(4) 适用于 USB 音频设备(系统在检测到兼容设备时会加载该模块)。该参数定义了处理过程中以毫秒为单位报告的数据时间范围。时间越短,数据延迟越低,但建议根据实际情况进行参数调试和试验。

    ③ 数据传输延迟,除非软件(例如播放器)因某些原因将此值修改为更合适的数值。

    ④ 虚拟播放/录音通道数。我们只关注单一音源的播放,因此禁用虚拟通道。此外,启用比特完美模式也需要设置此选项为禁用。

    ⑤ 启用比特完美模式并禁用虚拟通道后,系统会绕过数字信号处理(DSP)、频率变换/重采样、均衡器等处理。纯净的 PCM 数据流将直接传输到音频终端设备。

    ⑥ 在上述硬件规格中,音频设备为 USB DAC,系统中显示为 dev.pcm.5 —— 我们将其设置为默认设备。

    ⑦ 音频驱动的相对音量级别参数,默认值为 45。这在比特完美模式下影响微乎其微,但在系统图形均衡器(equalizer)配置中则较为重要;在配置和比特完美模式下影响可忽略不计。

    ⑧与上述参数类似,此为相对音量级别参数,但针对系统图形均衡器的操作(默认 +0.0dB),在比特完美模式下影响可忽略不计。关于参数 dev.pcm.%d.eq_preamp 和 hw.snd.vpc_0db 的详细含义,请参见 FreeBSD 中的图形均衡器 一节。

    /etc/rc.conf

    ①在我们的配置中,使用 Music Player Daemon(MPD,音乐播放器守护进程)服务器作为播放器——在系统启动时以普通模式启动它。在其余配置中,我们以实时优先级启动 musicpd(1)。

    FreeBSD 命令:帮助检查驱动程序、内核参数(sysctl)及音频子系统状态

    通过以下命令,可以列出已加载的内核模块,确认我们添加的组件是否存在:

    执行结果应类似如下:

    以下命令将显示计算机上安装的音频设备:

    系统检测到的音频设备示例如下:

    内核参数 hw.snd.verbose 默认值为 0。将其设置为更高的值,可通过 ioctl 接口获得更多详细信息:

    接下来的命令会显示音频设备的更多详细信息(列表中仅显示感兴趣的设备):

    特定 USB 设备的通信接口状态可通过命令 usbconfig(8) 调用(此处物理地址 ugen0.3 对应系统中的 dev.pcm.5):

    以下是该 USB 设备的详细接口数据:

    连接 sound(4) 驱动与音频设备 PCM 驱动的 sysctl 接口参数:

    结果应类似如下:

    所选音频设备的状态及驱动数据:

    以下输出确认了多项信息,其中包括比特完美模式已明确启用(该模式的正确参数为:dev.pcm.%d.bitperfect=1、dev.pcm.%d.play.vchans=0),且当前处理的数据频率为 44098 MHz:

    在 FreeBSD 中以实时模式运行 MPD 音乐播放器

    在 FreeBSD 与音频子系统配置 一节中,我们已准备好系统以实时系统模式运行,即加载了模块 mac_priority(4),并通过调整参数 kern.timecounter.alloweddeviation 将进程延迟降至最低。通过命令 rtprio(1),可在系统实时调度器中启动服务器和 MPD。但在此之前,需先关闭系统启动时自动启动的服务 musicpd(1):

    在 FreeBSD 中,最高实时优先级为 0。优先级编号从 0 到 RTP_PRIO_MAX(通常为 31),数值越低优先级越高。

    要验证 MPD 服务器是否以实时且正确的优先级运行,可使用命令 ps 查看进程列表,并筛选出 musicpd(1) 进程:

    ps 命令的输出应类似如下:

    另一种通过命令 top(1) 检查 musicpd(1) 是否正确以实时模式启动的方法:

    FreeBSD 中用于调试和排查 USB 音频设备的其他命令

    FreeBSD 中的图形均衡器

    FreeBSD 系统的声音驱动(sound(4))中实现了一款简单的软件图形均衡器(equalizer),支持实时调节低音和高音。内核默认编译时,均衡器调节频率为 62 Hz 和 16 kHz,也可以通过编译内核时指定其他参数进行更改。要启用均衡器,需要在文件 /boot/loader.conf 中设置参数 hint.pcm.%d.eq(启用后需重启系统):

    启用 hint.pcm.%d.eq 后,混音器应用中会出现额外的低音和高音调节控件。我们可以使用图形界面应用 mixertui(1) 或系统命令 mixer(1) 来设置这些参数,例如:

    系统会返回设置的数值及其状态:

    开启并使用图形均衡器参数显然会对音频信号产生干扰。因此,当均衡器开启时,音频驱动会自动关闭比特完美模式:

    结果:

    音频均衡有可能引入一定的失真或音质劣化风险,尤其是在过度使用时。为防止这种情况,FreeBSD 声音驱动提供了两个参数:hw.snd.vpc_0db 和 dev.pcm.%d.eq_preamp(官方文档尚未详细描述)。这两个参数分别设置声卡驱动和均衡器的相对“零”音量级别,通常能为均衡计算留出更大的余量以避免失真:

    • hw.snd.vpc_0db —— 默认启用,值为 45。增大该参数(即降低音量级别)会为经过均衡校正后的频率处理提供更大的动态范围。

    • dev.pcm.%d.eq_preamp —— 默认值为 0,范围为 -9 dB 至 +9 dB。例如,设置为 -5 表示先将整个音频流整体衰减 5 dB(相对于最大增益),后续的放大均基于该点(0 dB)进行。这样听感音量会降低,但如上所述,可以更好地补偿因均衡放大某些频率产生的失真。

    这两个参数建议交替使用,通常配置到文件 /etc/sysctl.conf,也可以在运行时直接设置。

    示例:

    高品质均衡器——FFmpeg 滤镜

    在发烧友圈里,是否使用音频均衡器一直存在着不同的看法。一方面,纯粹主义者主张尽可能自然、不做任何修改地还原声音;另一方面,实用主义者建议使用图形均衡器,根据个人喜好、房间声学条件或音响设备的缺陷进行调节。

    也可以折中,即适度使用均衡器,寻找自然音质与个性化调音之间的平衡点。合适的图形均衡器能在不引入明显失真的情况下提升听感质量。

    FFmpeg 项目中的 libavfilter 库提供了极佳的高级滤镜。我们可以在 MPD 播放器中轻松使用它们,FFmpeg 同时承担信号解码角色。FreeBSD ports 仓库中的 MPD 已内置了 libavfilter 库,而 Debian 12 需要从 backports 仓库更新 MPD 以支持该功能。

    当然,使用均衡器时无法实现完全的比特完美模式,但在我们的配置中,比特完美信号传递到 FFmpeg 解码器,并通过 libavfilter 送达 DAC 设备或声卡。这种图形均衡器在音质上远胜于 FreeBSD sound(4) 驱动实现的系统均衡器和 Linux 中的 alsaequal 插件。

    在 FreeBSD 和 Linux 上启用 FFmpeg 滤镜前,也应先关闭系统均衡器。

    使用 FFmpeg 滤镜配置 MPD

    利用 FFmpeg 及其 libavfilter 库作为 MPD 播放器的图形均衡器,我们主要关注以下滤镜:bass、treble 和 anequalizer。这样不仅能在 FreeBSD 实现高品质的软件均衡器,也能在 Linux 中同样使用。此外,FFmpeg 滤镜还适合基于 MPD 的流媒体系统。

    启用滤镜时,需要在 MPD 配置文件 musicpd.conf 中添加一个新的 filter {} 区块,用于定义滤镜(或多个滤镜),并在 audio_output {} 区块中添加滤镜。同时确保 mixer_type 和 replay_gain_handler 参数设置正确,适合比特完美模式。系统配置方面保持之前 配置 FreeBSD 与音频子系统 中描述的方案。

    FFmpeg —— bass 与 treble 滤镜示例

    示例组合了 bass 和 treble 滤镜:

    滤镜说明:

    • bass —— 在 62 Hz 频率处以 120 Hz 带宽提升 10 个点,使用 64 位数据的浮点精度运算;

    • treble —— 在 16 kHz 频率处以 8 kHz 带宽提升 3 个点,使用 64 位数据的浮点精度运算。

    这两个滤镜中非常重要的参数是 n,它负责对信号进行归一化。简单来说,n 会实时自动降低信号振幅(音量),从而扩展计算范围,避免失真和杂音的产生。

    基于上述滤波器的频率响应可视化:

    FFmpeg – 滤镜 anequalizer

    FFmpeg 库中还有一个值得注意的滤镜,即 anequalizer。它是一个多通道参数均衡器,基于模拟的切比雪夫(Chebyshev)和巴特沃斯(Butterworth)滤波器(由于通带信号失真较小,建议用于音频应用)。anequalizer 滤镜的系数可以根据中心频率、峰值增益、带宽和带宽增益来计算。

    上述通过 anequalizer 构建的用于 MPD 的 bass 和 treble 滤波器的特性定义如下:

    正如你所见,使用滤镜 anequalizer,我们几乎可以构建任意图形均衡器的特性。但有一个注意点——它缺少对处理后信号进行归一化的选项,无法消除滤波处理带来的失真。而这种失真在 g 参数增益值为 3 时就能听出来。音频驱动的参数,比如 hw.snd.vpc_0db,在这里不起作用,因为信号振幅仅在滤波之后才被驱动程序降低。唯一的解决办法是使用 MPD 中的软件音量混合器。设置为 40% 时,即使 g=10,也不会听到失真,虽然这并不是获得理想音质的最佳方式。

    我们通过设置 MPD 的 mixer_type 参数来启用软件音量混合器,配置如下:

    设计 anequalizer 滤镜的特性

    可以通过 Intona fima 的 DSP 编辑器 设计和可视化 anequalizer 滤镜特性波形及其参数。

    下面这个滤镜定义的等效表达:

    在 DSP 应用中对应为:

    定义中给出的 w 参数所对应的 q 参数(Q 因子)由以下关系确定:

    我建议你设计一个符合自己喜好的图形均衡器。

    总结

    本文涵盖了如何配置 FreeBSD 系统及其音频子系统以获得最佳音质,讨论了进程架构的多个方面,包括 FreeBSD 系统的实时调度器、比特完美信号模式,以及如何启用系统均衡器并正确配置以提升音频处理质量。最后,我展示了如何在 MPD 播放器中使用 FFmpeg 滤镜实现高质量的图形均衡器(这部分内容也推荐给 Linux 用户)。音频轨道的最终阶段及其产生的音质,更多地取决于硬件规格:声卡、DAC、耳机、功放、音箱等。所以可以说,真正的音频冒险才刚刚重新开始 😉


    作者简介:我的名字是 Marcin Szewczyk-Wilgan,我是一名全栈设计师。专业从事排版、出版设计和视觉传播。作为认证的 UX 设计师,我还基于 WordPress 和 Woocommerce 创建可用性高、排名靠前的网站和网店。此外,我管理着 Linux 和 FreeBSD 系统,提供主机托管、存储和安全服务。联系邮箱:[email protected]。

    FreeBSD and hi-fi audio setup: bit-perfect, equalizer, real-time
    引言

    过去,我总是倾向于根据技术优劣来选择操作系统和工具。然而,在当今微软、苹果、谷歌等公司频繁侵犯用户隐私并开展有争议活动的背景下,我认为仅凭技术考虑已不足以作为决策依据。

    像 Microsoft Windows 10、Apple MacOS 和谷歌的安卓 这样的专有操作系统因其不当行为而臭名昭著。

    长期以来,我一直支持着开源替代方案,如 GNU/Linux 和 BSD。我不仅相信这些开源方案在许多技术层面上更优,而且始终反对 传统的 BSD 与 Linux 之争。我认为不同的开源项目应当互帮互助、合作共赢,终端用户的讨论应当基于技术而非个人偏好。

    在可能的情况下,我曾私下或专业地建议他人将其操作系统迁移至开源替代方案。当人们接受我的建议时,我会协助他们将工作站上的 Microsoft Windows 迁移到 BSD 或 Linux,同样在服务器端亦是如此。这一尝试非常成功,我从未遇到过不满意的个人和公司。

    然而,GNU/Linux 世界的情况正在发生变化。越来越多的企业试图控制 Linux 作为操作系统的发展方向。由于 GNU/Linux 的结构和组织特点,它不幸地容易受到了这些影响。尽管它仍然是开源的,并且远没有专有系统的问题严重,但在内核和 systemd 中,部分“可选择关闭”的功能已被缓慢引入。

    你仍然可以选择关闭这些功能,但作为开源爱好者和隐私关注者,也许更好的做法是迁移到一款不必担心“偷偷植入软件”和企业利益的系统,而是由社区驱动的系统(Linux 早期就是如此)。

    作为系统管理员,我不希望每次升级系统时都担心会被“惊喜”,也不希望每次使用系统时都必须记住要关闭哪些间谍软件功能。

    某些 Linux 发行版不仅因为隐私问题,也因为技术问题,选择使用 非 systemd 的 init 方案。但随着内核开发的现状,以及越来越多第三方应用对 systemd 的依赖(即便不必要),问题正在蔓延到操作系统的其他部分,我认为这是一场日益艰难的斗争。

    从社区和安全的角度来看,我认为 GNU/Linux 的未来并不乐观。作为可能的替代方案,我建议尽可能将系统迁移到更加理性、稳定的选择,例如某种 BSD 衍生版。

    Linux 是碎片化的

    1983 年,Richard Stallman 在 Usenet 上宣布打算开始编写 GNU 项目。到 1987 年 6 月,该项目已经积累并开发了自由开源的软件,包括汇编器、几乎完成的可移植优化 C 编译器(GCC)、编辑器(GNU Emacs),以及各种 Unix 工具,如 ls、grep、awk、make 和 ld。

    1991 年,Linus Torvalds 在 GNU 项目之外开发了 Linux 内核,并于 1992 年 12 月根据 GNU 通用公共许可证第 2 版发布。结合 GNU 项目已经开发的操作系统工具,这就形成了 GNU/Linux 操作系统,更广为人知的名字是“Linux”。

    随后,Linux 发行版开始出现。不同的项目将 Linux 内核、GNU 工具和库、额外的第三方软件、文档、X Window 系统、窗口管理器和桌面环境拼凑到各自的发行版中。不同发行版关注的目标各不相同,有些侧重桌面,有些主要面向服务器,还有一些尝试提供多用途操作系统。

    过去,这些不同的组件和项目都是由开源爱好者和社区开发的,编程和开源的热情是推动力。

    如今情况已不同。可以参考我另一篇文章 systemd 背后的真正动机。

    Linus Torvalds 多次明确表示,他并不关心“Linux 世界”发生了什么,他唯一关心的是内核开发。在 2020 年 1 月 6 日,Torvalds 在 realworldtech.com 的“Moderated Discussions”论坛上回答了用户的问题,同时发表了令人震惊的评论,这与一年前的内核维护争议有关,而该争议对 ZFS on Linux 项目产生了重大影响。

    在回答用户的实际问题之后,Torvalds 对 ZFS 文件系统发表了一些极为错误且有害的言论。他说:

    它(ZFS)一直更多的是噱头,而不是真正的东西。

    通过这句话,Linus Torvalds 就把全球最强大、最流行的文件系统之一超过十五年的开发成果,简化为“噱头”。

    ZFS 被称为“文件系统的最终之选”。它是一款结合了文件系统和逻辑卷管理器的系统,最初由 Sun Microsystems 设计。ZFS 是稳定、快速、安全、面向未来的文件系统。它可扩展,且包含广泛的数据损坏保护,支持大容量存储,最大文件尺寸可达 16 EB(艾字节),最大存储容量可达 256 PQZB(千万亿泽字节),且对文件系统(数据集)或文件数量无限制,支持高效数据压缩、快照和写时复制克隆、持续完整性检查和自动修复、RAID-Z、本地 NFSv4 ACL,并且可以非常精确地配置。

    ZFS 的两个主要实现——Oracle 版本和 OpenZFS 项目版本——非常相似,使 ZFS 在类 UNIX 系统中得到广泛应用。

    如维基百科文章所述,OpenZFS 旨在汇集使用 ZFS 文件系统并致力于改进它的个人和公司,推动 ZFS 以开源方式更广泛使用和开发的 umbrella 项目。OpenZFS 汇集了来自 Illumos、Linux、FreeBSD 和 macOS 平台的开发者,以及众多公司。该项目的高级目标包括提升开源 ZFS 实现的质量、实用性和可用性意识,建议就改进开源 ZFS 衍生版的持续努力进行公开沟通,并确保所有 ZFS 发行版的可靠性、功能性和性能一致。

    OpenZFS on Linux,即该项目在 Linux 平台的部分,目前有 345 名活跃贡献者,提交逾 5,600 次,几乎每天都有新的提交。

    世界上一些最大的 CDN 和数据存储服务都在 FreeBSD 或 Linux 上运行 ZFS。

    在另外的情况下,Linus Torvalds 在 TFiR: open source and Emerging Tech YouTube 频道 关于桌面 Linux 的采访中又发表了一条惊人言论,称 Linux 仍未准备好用于桌面,也许 Chrome OS 才是解决方案。

    这些以及 Linus Torvalds 的许多其他言论表明,作为一款操作系统,Linux 缺乏明确方向和清晰管理,因为内核开发与 Linux 世界的其他部分隔离进行。

    Linus Torvalds 通常也对企业利益的快速影响非常开放,他对安全性的看法也令人担忧。

    2009 年,Linus Torvalds 承认内核开发已经失控:

    我们越来越庞大和臃肿。是的,这是个问题……呃,我很想说我们有计划……我是说,有时有点遗憾,我们肯定不是我十五年前设想的精简、高效内核……内核庞大且臃肿,我们的指令缓存占用令人担忧。我是说,这毫无疑问。每当我们添加新功能,情况只会更坏。

    在 2014 年的 LinuxCon 上,他表示,他认为内核臃肿问题已经好些,因为现代 PC 要快得多!

    在过去二十年里,我们一直在让内核膨胀,但硬件增长得更快。

    这种态度非常有问题。

    当软件臃肿时,它不仅变得更不安全、更容易出错,而且运行速度也会大幅下降。认为问题会因为硬件更快而消失是一种不成熟的态度。在当今时代,我们需要优化软件以减少功耗,节约能源并限制污染。

    在 2007 年的一次“为什么我退出”采访中,内核开发者 Con Kolivas 表示:

    如果内核开发和 Linux 有一个最大的问题,那就是开发过程完全与普通用户脱节。你知道的,就是那些占 Linux 用户基数 99.9% 的用户。与内核开发者沟通的方式就是 Linux 内核邮件列表。委婉地说,Linux 内核邮件列表(lkml)几乎是最令人害怕的沟通论坛。大多数人完全不敢发邮件到列表,怕因为经验不足、提交不当的 Bug、显得愚蠢或其他原因而被批评……我认为大多数内核开发者根本不了解用户空间的问题有多严重。

    事实上,Linux 作为操作系统,是由来自完全不同项目的各类应用程序拼凑而成的。如果你对此一无所知,可以看看如何构建 Linux From Scratch。

    另一篇很好地展示了这些问题的文章是 Linux maintains bugs: The real reason ifconfig on Linux is deprecated,也可作为 PDF 阅读。

    所有这些都与 BSD 衍生版截然不同,即 FreeBSD、OpenBSD、NetBSD 和 DragonFly BSD,因为每一个项目都是完全独立的——可以说是“内部开发”。内核、标准 C 库、用户空间工具等都是操作系统基本系统的一部分,而不是从一堆外部来源拼凑而来。

    在 2005 年的一次采访中,OpenBSD 创始人 Theo de Raadt 作出如下评论:

    我相信大家现在都知道,Linux 只是内核,而 OpenBSD 是完整的 Unix 系统:包括内核、设备驱动、库、用户空间、开发环境、文档,以及所有你继续开发所需的工具。也就是说,仅仅从功能完整性来看,它的处理方式完全不同于 Linux 发行版,完全不同。

    当我们发现系统必须进行更改(无论是安全性还是其他原因)时,我们可以将这样的更改从用户空间通过库一直推到内核,从而强制执行更改。我们可以根据需要修改接口。我们可以快速行动。有时更改甚至会破坏之前的可执行文件;但如果需要,我们可以选择做出这样的决定。

    这赋予了我们极大的灵活性,使我们能够快速前进。如果某些设计有误,并且修复依赖的不仅仅是内核,我们可以通过修改正确位置的所有必要部分来解决问题。我们不需要在错误的位置使用 hack 来解决问题。

    Linux 正受到企业利益的强烈影响

    Linux 发行版是由不同群体开发的工具集合,这些群体的利益和优先事项往往存在冲突。由于 GNU/Linux 操作系统的这种碎片化结构,整个项目在商业利益的推动下正迅速失控。

    即便是最优秀的 GNU/Linux 发行版,如 Debian GNU/Linux 和 Arch Linux,它们仍主要由开源社区驱动,也无法完全规避这一问题,因为它们不仅依赖高度碎片化的工具,而且部分开发者已被一些大型商业公司雇佣。

    在我撰写的文章 The real motivation behind systemd 中,我曾写到,开发 systemd 的主要原因是 Red Hat 在嵌入式设备上的财务利益,主要涉及美国军方和汽车工业。最初,systemd 是作为一个新的 init 系统发布的,但它逐渐发展成 Poettering 所描述的“为 Linux 操作系统提供基础构建模块的软件套件”。

    在一次对红帽 CEO Jim Whitehurst 的 采访 中,他表示:

    我们与全球最大的嵌入式供应商合作,尤其是在电信和汽车行业,这些行业最关注稳定性和可靠性。他们很容易适应 systemd。

    我对 systemd 的“init”部分没有异议,但 systemd 已不再只是 init 系统,其主要问题在于其持续开发受到企业财务利益驱动,而非开源社区的利益。因此,我认为,像 Debian 和 Arch Linux 这样的主要 Linux 发行版采纳 systemd 是个很大的错误。由于 systemd 的复杂性,它们几乎陷入了“供应商锁定”。

    这纯属推测,但我也必须承认,我怀疑 systemd 可能是向 Linux 操作系统引入安全漏洞的平台。这些漏洞表面上看起来像普通的“编程错误”,但其中一些与 OpenSSL Heartbleed 漏洞 非常相似。而在开源软件中,利用“编程错误”来制造 后门和其他问题 是众所周知的策略。systemd 自 2015 年以来就有 大量公开且已确认的漏洞 仍未修复,但 systemd 开发者并没有修复这些漏洞,而是不断向 systemd 添加更多功能。

    另一家对 Linux 世界影响深远的公司是谷歌。谷歌开发了安卓和 Chrome OS,这两个都是基于 Linux 内核的操作系统。Chrome OS 来源于 Chromium OS,并使用 Google Chrome 浏览器作为主要用户界面。

    Chrome OS 被视为微软的竞争对手,不仅直接与 Microsoft Windows 竞争,还间接影响微软的文字处理和电子表格应用,后者依赖于 Chrome OS 的云计算。这也是 Chrome OS 的核心问题之一:它高度依赖谷歌的云基础设施。

    谷歌已成为最具争议的 公司之一。谷歌本质上是家广告公司,以操控搜索结果和极端用户跟踪能力闻名,这主要归因于“现代”网站开发者无知地在其网站中添加 Google Analytics。

    在 2019 年 8 月的一个 YouTube 视频(由 Linus Tech Tips 发布)中,Linus Sebastian 展示了互联网跟踪是如何运作的,以及它如何影响你在搜索商品时所得到的价格。

    请注意,该视频最初由 Private Internet Access 赞助,而该公司后来被 Kape Technologies 收购,该公司以通过其软件传播恶意软件和行为不端闻名。不要使用 Private Internet Access!

    Cloudflare 是另一家影响开发各领域的美国网络基础设施公司。该公司提供的服务实际上位于网站访问者与 Cloudflare 用户的托管服务提供商之间,充当网站的反向代理。因此,Cloudflare 已成为互联网的重大毒瘤之一。

    systemd 开发者已将 Cloudflare、Quad9 和谷歌集成到 systemd-resolved 的核心中,现在必须手动禁用(opt-out)。

    随着 Red Hat(IBM)通过 systemd 的影响力不断扩大,他们已经成功地将大多数主要 Linux 发行版引导到了与许多 Linux 系统管理员和用户期望背道而驰的方向。

    BSD 才是理想选择

    伯克利软件发行版(BSD)最初是基于 Research Unix 的操作系统,由加州大学伯克利分校的计算机系统研究小组(CSRG)开发和发布。今天,BSD 通常指它的后代系统,如 FreeBSD、OpenBSD、NetBSD 和 DragonFly BSD。这些项目是真正的操作系统,而不仅仅是内核,它们也不是“发行版”。

    Linux 发行版,例如 Debian 和 Arch Linux,需要将所有必需的软件整合在一起,才能构建出完整的 Linux 操作系统。它们需要 Linux 内核、GNU 工具和库、init 系统,以及一定数量的第三方应用程序,才能形成可用的操作系统。

    相比之下,BSD 系统既是内核,也是完整的操作系统。例如,FreeBSD 同时分发 FreeBSD 内核和 FreeBSD 操作系统,并作为一个单一项目进行维护。

    BSD 不属于任何个人或公司。它由全球技术高超且投入的社区贡献者创建和发布。

    企业也会使用和贡献 BSD。公司可以开发自己的 BSD 版本,例如索尼电脑娱乐公司为 PlayStation 3、PlayStation 4 和 PlayStation Vita 游戏主机所做的版本。但因为 BSD 是完整的操作系统,并且每个 BSD 项目都由开源爱好者和社区维护和开发,而非像 Red Hat 这样的公司,所以 BSD 项目是真正独立的。

    这种 BSD 组织方式的一个结果是,你不会在操作系统中看到疯狂的 opt-out“间谍软件”设置。

    相反,由于 BSD 项目由关心操作系统设计、安全性和隐私的技术娴熟、充满热情的人开发和推动,你会发现即使是通过包管理器安装的第三方软件,也会被修补以移除这些问题,例如 OpenBSD 在 Firefox 中禁用 DNS over HTTPS。

    另一大好处是,BSD 项目周围的社区成员通常经验丰富、乐于助人,并且大多非常友善。

    不同的 Linux 发行版,如 Debian 和 Arch Linux,甚至早期的 Red Hat Linux,都是非常优秀的项目。当项目由热情而非利润驱动时,质量往往更高。然而,当项目不再由热情驱动,而是由利润驱动时,其质量往往会下降。这很自然,因为利润驱动与热情驱动的动机截然不同。

    微软 Windows 在桌面端的成功,并不是因为人们认为 Windows 是一个优秀的操作系统,没有任何理智且经验丰富的系统管理员或 IT 支持人员会相信这一点,而是因为微软实施了极具攻击性的市场营销策略。

    虽然 BSD 项目确实会从公司获得代码和偶尔的资金支持,但它们的推动力是热情,而非利润。这主要意味着决策经过深思熟虑,不会为了利润而在隐私或安全上妥协,这与现今的 Linux 形成鲜明对比。

    许可问题

    GPL 许可对开发者要求更严格,它是一种 开源反模式,因为它强制要求发布所有修改过的源代码,并阻止其他开源项目被整合。例如,GPLv2 妨碍了在 Linux 上集成 DTrace 和 ZFS。

    另一方面,BSD 开发者没有这种限制。制造商在开发新设备时可以选择 BSD 作为操作系统,而不是 Linux,这能让他们在需要时保留代码修改,不必公开。

    GPL 许可听起来似乎更好,因为为什么我们要让公司简单地“窃取”我们的开源代码并制作专有产品,而不回馈任何东西呢?但事情并没有那么简单。

    更多信息请参见我的文章 GPL 的一些问题。

    是时候全面迁移到 BSD 了

    大约在 1998 年,我开始将家里、公司和客户的每台服务器与桌面操作系统从 Microsoft Windows 迁移到 Linux,最初是 Red Hat Linux,后来是 Debian。我这样做是因为我在微软 Windows 服务器和工作站支持上工作了大约十年,发现 Linux 更安全、更稳定、开源,并且在调试和控制上往往更容易。

    随后在 1999 年末 我发现了 FreeBSD,并最终开始在服务器和工作站上部署 FreeBSD 和 OpenBSD。

    那时候,Linux 通常对硬件的支持比 BSD 更好,因此我通常使用 Linux 多于 BSD。硬件昂贵,购买硬件时并不总能基于你想运行的操作系统来选择。这与今天不同,现在 BSD 系统一般对现代硬件有很好的支持。

    我仍然喜欢 Linux,但我不想再担心 Lennart Poettering(现为微软员工)接下来会搞出什么垃圾。我也不想担心内核中的各种臃肿功能,例如内核 强制 DRM 适配。我基本上不想再担心接下来会出现什么问题。一切都应该是默认合理的选项和决策,而不是 opt-out!

    最后,BSD 系统不仅仅是不用担心这些问题,它们本身就是非常优秀的操作系统!

    可以看看我其他一些关于 BSD 的文章和教程:

    • FreeBSD 是一款了不起的操作系统

    • 选择 FreeBSD 而非 GNU/Linux 的技术原因

    • OpenBSD 很棒

    • 如何设置 FreeBSD 并打造美化桌面 - 第 1 部分 - 基础设置

    其他相关链接

    • FreeBSD 提交者 Allan Jude 讨论 FreeBSD 的优势以及他在维护数百万服务器中所扮演的角色(自 2016 年与 Allan Jude 的访谈以来,FreeBSD 已经有了显著发展)

    • 为什么选择 FreeBSD?

    • FreeBSD 不是 Linux 发行版(YouTube)

    • The FreeBSD Journal

    在我发布了这篇文章的第一部分后,它被发布到了 Hacker News、Reddit 和 Lobsters 上,有一位叫“harryruhr”的人在他的博客上发表了回应,标题为 “是否应该从 Linux 迁移到 BSD?这取决于情况。”。在这篇回应中,harryruhr 提出了几个我认为需要澄清的错误论点。

    分裂问题

    针对我提出的“Linux 是分裂的”观点,harryruhr 写道:

    是的,它确实是。但如今 BSD 也同样存在分裂问题。三个“传统”BSD——FreeBSD、NetBSD 和 OpenBSD——在技术和目标上差异很大。还有一些“新”的 BSD 分支,如 Dragonfly、MidnightBSD、HardenedBSD 等。Distrowatch.com 列出了 18 款不同的 BSD“发行版”。作者高度赞扬的 ZFS 文件系统仅在 FreeBSD 及其近亲上可用,并且基于“ZFS on Linux”。它在 NetBSD 或 OpenBSD 上不可用。

    这完全不正确。FreeBSD 是最早将 ZFS 从 Sun Microsystems 移植过来的独立操作系统之一。ZFS on Linux 出现得更晚,然后演变为 OpenZFS,如今已经成为所有 FOSS ZFS 开发者的重要协作项目。来自 Linux、FreeBSD、NetBSD、Illumos 等平台的开发者现在都在为该项目贡献代码。

    Linux 是分裂的,因为内核、GNU 工具、库以及其他所有部分都是完全独立的项目。这些项目之间实际上没有任何联系,但你同时又无法拥有完整的 Linux 操作系统而不以某种形式将这些不同的项目“拼凑”在一起,这正是各个 Linux 发行版所做的工作。

    GNU 项目自 1990 年起就一直在开发自己的内核 GNU Hurd,最初计划替代 Unix 内核。Linux 内核只是为了快速得到一个可用的操作系统而采用的便利方式,因为 Hurd 内核尚未完成。

    BSD 完全不存在分裂问题,它们各自都是完整的操作系统和独立项目,都有内核、基础工具等。它们是目标不同的独立项目,虽然共享 BSD 内核的家族树,并偶尔共享部分代码,但除此之外彼此独立。如果 FreeBSD 或 NetBSD 停止开发,OpenBSD 完全不会受到影响,反之亦然。

    Dragonfly BSD 也是如此。Matthew Dillon 曾是 1994 到 2003 年间的 FreeBSD 开发者,他在 2003 年分叉 FreeBSD,因为他认为 FreeBSD 采用的线程和对称多处理技术会导致性能和维护问题。由于其他 FreeBSD 开发者不同意,他创建了 DragonflyBSD。但 DragonflyBSD 如今也是一个完全独立的操作系统和项目。

    所有这些不同的 BSD 项目仍然是完整且独立的操作系统。它们并不是由不同项目的独立组件拼凑而成的。

    至于 MidnightBSD、HardenedBSD 以及类似项目,它们也与分裂无关。这些项目大多基于 FreeBSD,利用 FreeBSD 构建不同的应用程序,或对内核进行补丁修改等。这与分裂没有关系。

    如果 BSD 项目像 GNU/Linux 那样分裂,那么 BSD 内核就应该由一个独立项目开发,基础工具则由另一个独立项目开发,只有把这些独立且分裂的部分“粘合”在一起,系统才能工作。

    这就是 GNU/Linux 操作系统的分裂特性与 BSD 操作系统之间的根本区别。

    关于被劫持的问题

    针对我提出的“Linux 被劫持了”这一观点,harryruhr 写道:

    作者说,大型“有争议”的公司在影响 Linux 的发展。这可能是真的,但 FreeBSD 的情况真的更好吗?

    FreeBSD 社区在每一个可能的场合都会自豪地说,Netflix 使用 FreeBSD 来提供他们的内容。此外,Netflix 还是 FreeBSD 内核最大的商业贡献者之一。但在 FreeBSD 桌面上,仍然无法在本地播放 Netflix。如果这一点,以及他们传播 DRM 内容,还不能让 Netflix 成为最有争议的公司之一,那我就不知道“有争议”是什么意思了。当然,基于 FreeBSD 的商业和专有产品还有几十个,它们剥夺了用户使用自由软件的利益。

    确实,Netflix 是 FreeBSD 最大的商业贡献者之一,但这与 Linux 世界中的“劫持”没有任何关系。Netflix 所做的所有 FreeBSD 改进都会回馈给项目。他们做的所有性能增强都已贡献回 FreeBSD,这对 FreeBSD 极有益。

    但 Netflix 并没有试图影响 FreeBSD 项目,也没有试图“劫持”FreeBSD。他们也没有开始开发一个新的 init 系统,然后再后来声称它实际上并不是 init 系统,而是一个“永远未完成、永远不完整、但用于跟踪技术进展”的东西,不断地膨胀和扩展。

    Netflix 的一名员工 drewg123 在 Hacker News 上提供了如下相关信息:

    在 Netflix,我所在的较大工作组中,至少有七名 FreeBSD 提交者,还有一名核心团队成员(我肯定还忘记了一些人,对此抱歉!)。我们还聘用了许多其他提交者和核心团队成员(按特定合同)。

    与雅虎不同,我们需要对 Netflix 的商业目标负责,即在提高流媒体用户体验的同时,维持或降低内容传输成本。这些目标通常与 FreeBSD 的目标高度一致,我们做出了大量贡献(async sendfile、kTLS、未映射的 mbufs、epoch 稳定、NUMA 工作、RACK TCP、BBR TCP、TCP pacing,以及很多我忘记的工作)。

    关于 Netflix 提供的服务及其所谓只能用专有应用播放的 DRM 内容,以及其他基于 FreeBSD 的专有项目,这些都对 FreeBSD 没有影响,也与“劫持”完全无关。这些项目都没有影响 FreeBSD。

    所以,可以肯定地说,FreeBSD 的情况要好得多。

    关于“理性人在哪里”的问题

    针对我提出的“BSD 是理想选择”(我原本标题为“BSD 是理性人所在之地”,因为 Linux 世界中 systemd 的广泛采用)的观点,harryruhr 写道:

    作者说:“BSD 项目维护整个操作系统,而不仅仅是内核。”确实,BSD 不只是内核,还有用户空间程序。但 BSD 操作系统自带多少“用户空间”程序完全由 BSD 开发者决定。通常只提供最基本的工具。其余的必须通过 Ports 和包来使用,这与在 Linux 发行版中使用包没有什么不同。例如 FreeBSD 的基本系统甚至没有 Xorg,你必须通过“pkg install xorg”从软件包安装。在很多情况下,原本集成系统的一部分会从基本系统中移除,变成单个包。

    我觉得这个说法有些诱导性。

    不能把 FreeBSD 需要从第三方项目安装 Xorg 的事实,与 GNU/Linux 操作系统的碎片化现实相比较,这两者毫无关系。

    我的文章关注的是 GNU/Linux 操作系统的碎片化特点,与不同 BSD 操作系统相比,而不是基本安装中包含多少第三方应用程序。

    harryruhr 接着写道:

    最“完整”的系统确实是 OpenBSD,它不仅自带 X(Xenocara),还有自己的 MTA(OpenSMTPd)和网页服务器(OpenBSD httpd),这可以使 OpenBSD 基本系统成为基本任务服务器的良好选择。当然,除了 xterm、xcalc 和三种窗口管理器(twm、fvwm、cwm)之外,几乎没有“图形化”程序。如果你想要网页浏览器或功能齐全的邮件程序,就必须从包安装。

    OpenBSD 中的 X、OpenSMTPd、httpd 以及其他应用程序,与操作系统本身没有关系。是否将这些集成到基本系统中,并不影响 OpenBSD 即使没有这些部分仍然是一个完整操作系统的事实。

    这些应用程序并不会使 OpenBSD 比 FreeBSD“更完整”。它们只是让 OpenBSD 的基础安装中自带更多应用程序而已。

    OpenBSD 项目之所以将更多应用程序集成到基础安装中,是因为 OpenBSD 非常重视安全。开发者希望将这些应用程序与基础安装集成,以控制它们的开发方式和运行方式。因此这些应用程序成为 OpenBSD 的集成部分。

    FreeBSD 或 NetBSD 也可以在基础安装中提供大量应用程序,但对于这些项目来说,这样做没有意义。

    事实是,这些应用程序并不影响操作系统的完整性。另一方面,如果没有内核,或者没有“用户空间”工具,那么就什么都没有了。这就是 GNU/Linux 的现实!

    关于许可的问题

    harryruhr 接着写道:

    关于“BSD 还是 GPL”的讨论与这些许可证本身一样古老。支持或反对都有合理的论点。就我个人而言,只要是自由软件,我并不在意。认为 GPL 会导致软件被利润驱动而非出于善意的论点,并不令人信服。

    我认为,真正关心“自由软件”的人,也就是关心开源软件可以自由分发和开发的人,应当更深入地思考这个问题。三十多年的实践经验显示,当利润驱动的公司依赖 GPL 授权的软件时,如果它们无法掌控软件,就很容易使用各种操控手段。

    而使用 BSD 许可证,公司不必通过政治手段或操纵来影响软件开发,它可以直接拿到软件,按自己的意愿使用。

    关于迁移的问题

    最后,harryruhr 针对使用 BSD 而非 Linux 的理由写道:

    但除了仅使用自由软件的理由外,这些理由应该仅仅是技术性的。过时的论点,比如“BSD 是完整系统而 Linux 仅是内核”或者“Linux 受利润驱动而 BSD 受善意驱动”,实际上已经不再成立。

    通常,我完全同意“选择特定操作系统的理由应该仅限于技术原因”这一观点。然而,现实已经不再如此,我提出的论点并非过时,相反,非常切中当前问题。

    请参考我的文章:以政治理由批评技术是否合理?

    微软 Windows 10 可能是某些特定应用或硬件的唯一可用操作系统,但这并不意味着你应该为了使用它而在重大隐私问题上作出如此妥协,并用所谓技术理由为此辩解。存在“过度垃圾”的问题。

    随着最近 Linux 内核被强制加入 DRM,再加上 Linus Torvalds 多次脱离现实的表态,以及他对 Linux 世界许多重要问题的完全忽视——他显然并不关心企业如何影响内核开发——Linux 内核的未来看起来并不乐观,无论是从隐私角度还是安全角度来看。

    除非你每次 Linux 内核发布时都愿意通过打补丁来解决问题,否则你需要一个可行的替代方案。一个内核开发者对项目方向有清晰认知的替代方案——一个不会妥协隐私、安全或其他重要问题的方向。

    当然,任何项目中总会存在分歧,但 FreeBSD 开发者之间的分歧,与那些为了利润而试图或多或少“劫持”项目的公司完全不同。

    Why you should migrate everything from Linux to BSD
    Why you should migrate everything from Linux to BSD - part 2

    选择 FreeBSD 而非 GNU/Linux 的技术性原因

    • 原文:https://unixsheikh.com/articles/technical-reasons-to-choose-freebsd-over-linux.html

    • 最后更新日期:2023-10-27

    在我的主工作站和所有服务器上都将 FreeBSD 作为日常使用的操作系统,自 1999 年起我就一直在使用 FreeBSD,因为我认为它是“一款了不起的操作系统”。在本文中,我将讨论选择 FreeBSD 而非 GNU/Linux 发行版的若干技术原因。

    完整的操作系统

    在 FreeBSD 上,你会立刻注意到,你面对的是“完整的操作系统”。所有不同的组件都是统一开发的。这意味着,如果一款组件的变动会影响整个系统,开发者可以更容易地在实施变更前考虑整体情况,并进一步规划和开发受影响的组件。BSD 内核、init 系统、用户空间工具、Ports 和包管理器,所有这些都是由项目成员开发并集成到一款系统中。例如,FreeBSD 上的 命令(参见 ZFS ARC Stats 部分)就整合了 ZFS (自适应替换缓存)的信息。

    内核和基本系统与第三方应用完全分离。基本系统配置放在 /etc,而所有第三方配置放在 /usr/local/etc。你可以配置和调优的一切内容,都在 man 手册中有详细记录。

    你拥有从 rc 工具(由 调用以控制自动启动过程的命令脚本)、、 内核管理工具,到所有不同的 等功能,这一切都被很好地整合和文档记载。

    因为 FreeBSD 是完整的操作系统,而不是像 Linux 发行版那样“拼凑”而成,一切设计得井井有条,基于多年的经验,并且当系统发生变化时,这些变化对整个社区都是有利的,同时参考了大量真实的使用案例和行业问题反馈。

    作为对比,我最喜欢的 Linux 发行版之一 Debian GNU/Linux 有其特定的 。Debian 方式代表了一套特定的配置管理工具和补丁,使第三方软件符合 Debian 的设置方式。虽然在某种程度上这可以统一 Debian 中的操作方法,但它不幸地破坏了上游配置,这可能会带来很大困扰。尤其是在某些功能无法正常工作,或者上游文档与 Debian 的实际设置不匹配时,这种问题尤其突出。另一个问题是,一些第三方软件,甚至 Debian 的核心组件,如 systemd,无法完全按照“Debian 方式”来处理。结果就是操作系统中有些部分运行“Debian 方式”,而有些部分则不是。Debian GNU/Linux 已经整合了 systemd,但同时默认网络部分仍是 Debian 特有的。有时你必须禁用并移除 Debian 特有的配置,才能让 systemd 的功能正常工作。这一切都源于由许多不同项目的不匹配组件拼凑而成的系统。

    另一方面,我同样喜欢的 Linux 发行版 Arch Linux 希望第三方软件保持上游状态,除非绝对必要,否则不做修改。这很好,因为上游文档与软件保持一致。然而,这虽然有助于改善整体系统管理,但事实仍然是 Linux 内核、用户空间工具以及其他所有组件都是由不同实体开发的。完全不同项目之间的冲突,例如 Linux 内核与 systemd 开发者之间的冲突,可能会导致操作系统无法正常运行。而 FreeBSD 不会出现这种问题,因为它是完整的操作系统。

    我从不喜欢的 Ubuntu Linux 发行版则更糟。由于它基于“Debian unstable”,运行了大量 Debian 工具和配置,但同时又有“Ubuntu 方式”,在 Debian 基础上做了修改。除此之外,还在其上增加了一层 GUI,也就是所谓的用户改进工具层,有时会导致 Ubuntu 出现难以理解的崩溃问题。

    文档

    有些人认为文档不是使用某项技术的技术理由之一,但文档应被视为其所述技术的组成部分。粗劣的文档、过时的文档以及缺失的文档都应被视为一种 Bug。

    FreeBSD 的文档随系统一同分发,因此你不必去网上搜索。基本系统的 man 手册质量极高,专为 FreeBSD 编写,你大多数所需的信息都可以在系统中直接找到。

    FreeBSD 还有 ,覆盖了从安装到日常使用的各个方面。安装时也可以将手册本地安装。手册偶尔会有一些过时的章节,因为它是众多个人持续工作的成果,但总体来说,手册是定期更新且编写良好的。

    安全

    通常被攻破的不是操作系统本身,而是运行在操作系统上的程序。在某些情况下,被攻破的程序可能与操作系统交互,从而影响操作系统的安全。保障操作系统安全意味着你要确保计算机资源仅被授权人员用于授权用途。

    FreeBSD 默认配置是为了性能优化,而不像 OpenBSD 那样默认安全,但 FreeBSD 提供了许多工具和选项,帮助你保护系统免受攻击者侵害。

    在本文中无法提供 FreeBSD 安全选项和可用功能的详尽列表,因为安全主题本身足以写成一本书。

    不过,我可以提及几项关键内容。

    安全性安装时选项

    在安装 FreeBSD 时,安装程序提供了一组可启用或禁用的选项:

    • 隐藏其他用户 ID(UID)的进程

    • 隐藏其他组 ID(GID)的进程

    • 隐藏 jail 内的进程

    • 隐藏消息缓冲区

    FreeBSD 其他大部分内核级安全设置都可通过 sysctl security.bsd 访问,而且每隔几个月还会增加新的选项。你可以运行命令 sysctl -d security.bsd 来显示你当前 FreeBSD 安装中可用的选项。

    漏洞统计

    下面是 FreeBSD 与 Linux 的漏洞统计列表。FreeBSD 漏洞数量通常较少,这并不一定意味着 FreeBSD 比 Linux 更安全(尽管我认为它确实更安全),也可能是因为 Linux 的用户和开发者更多、关注度更高。然而,大多数 Linux 发行版的攻击面通常比 FreeBSD 要大得多。

    有关具体漏洞的详细信息,可以访问 CVE Details 网站查看 和 的数据。

    稳定性

    FreeBSD 拥有出色的工程与版本管理实践。FreeBSD 从创意产生到公开发布经历多个步骤:

    1. 当有人提出新想法并进行开发时,首先会经过同行技术审查。

    2. 然后进入“current”分支进行集成测试,根据复杂性或潜在影响,进入“stable”分支的迁移窗口会做相应调整。

    3. 接着进入“stable”分支,供更广泛的用户群测试,这通常也是 Beta 测试阶段,并有更广泛的社区参与。

    4. 最后进入“release candidate”(RC)测试,通常会经历三轮测试,之后才成为正式“release”版本。

    会发布软件补丁以修复漏洞和缺陷。

    这些步骤使 FreeBSD 成为非常可靠且稳健的操作系统。

    Ports 数据集

    是工程学上的一项惊人成就。NetBSD 的 和 OpenBSD 的 都起源于 FreeBSD 的 Ports 系统。

    虽然 FreeBSD 也提供二进制包(就像 Debian Linux、Arch Linux 一样),由 包管理器处理,但 FreeBSD 还可以从源码编译软件,并能让用户在编译时进行个性化配置。Arch Linux 的 实际上在很大程度上受 FreeBSD Ports 系统启发。然而,在 FreeBSD Ports 系统中,你可以在 make 过程中选择最相关的编译选项,而在 Arch Linux 上,你通常需要手动编辑和修改包维护者提供的 脚本(基本上默认设置是必须接受的)。

    FreeBSD Ports 数据集使用 来自动化软件的编译、安装和卸载过程,通过 make 命令实现。组成单个 port 的文件包含了自动下载、解压、打补丁、配置、编译和安装应用所需的所有信息,在执行如 make install 或 make install clean 之类的初始命令后,几乎无需用户干预。如果该 port 依赖其他应用或库,它们会在安装前自动处理。

    大多数 port 配置了一套默认选项,这些选项被认为适合大多数用户。然而,Ports 系统的重大优势在于,你可以在安装前通过 make config 命令更改这些配置选项。该命令会弹出一个基于文本的界面,能让用户选择所需选项。

    截至本文发布时,Ports 数据集中可用的 port 已 30,000 余款。

    滚动更新的第三方包

    关于第三方包,你可以选择两个不同的分支:一个叫“quarterly”,另一个叫“latest”。

    Quarterly 是从版本系统的 HEAD 分支在每年季度初(1 月、4 月、7 月和 10 月)截取的 Ports 分支的名称,也是由这些分支生成的二进制包集的名称。

    Quarterly 分支为用户提供了更可预测、更稳定的 port 和包的安装与升级体验。这主要是通过只允许上游的非功能性更新来实现的。Quarterly 分支旨在接收安全修复,但也可能包含版本更新,或者回移的提交、错误修复以及 Ports 兼容性或框架更改——这取决于上游的操作。

    然而,如果你选择“latest”分支,FreeBSD 在第三方包方面将成为滚动更新发行(rolling release),类似于 Arch Linux,从而获得最前沿的软件。

    Poudriere

    Poudriere 是一个用于创建和测试 FreeBSD 包的工具。它利用 系统来搭建隔离的编译环境。这些 jail 可用于为任何版本的 FreeBSD 构建二进制包。待包构建完成,它们的布局与官方镜像完全一致。这些包可被 FreeBSD 的 pkg 二进制包管理工具使用。

    使用 Poudriere,你可以轻松地构建并设置自己的二进制包仓库,其中的包完全按照你的规格和需求进行构建。

    Poudriere 可以处理整个 ports 树的批量构建、ports 树的特定子集,或者包括依赖的单个 port。它会自动构建包、生成构建日志文件、提供签名的 pkg 仓库,并支持在向 FreeBSD bug 跟踪系统提交补丁前测试 port 构建,还可以使用不同选项测试不同构建。Poudriere 在干净的 jail 环境中执行构建,可以使用 zfs 特定功能。这意味着不会污染宿主环境,不会留下文件,也不会意外删除或更改现有配置文件。

    Poudriere 设置和使用都非常直接,因为它没有依赖,并且可以在任何受支持的 FreeBSD 版本上运行。

    ZFS

    与 Linux 不同, 文件系统在 FreeBSD 上是一等公民。这不仅意味着可以将根文件系统安装在 ZFS 上,并且安装程序开箱即支持这一功能,还意味着许多基本系统工具已经紧密集成并支持 ZFS。在 FreeBSD 上运行 ZFS 与在 Linux 上运行 ZFS 非常不同。在 FreeBSD 上,你可以获得更多专门用于调查 ZFS 性能问题或其他相关问题的工具。

    ZFS 的一些重要特性包括:

    • 为长期数据存储而设计,可无限扩展的数据存储规模,保证零数据丢失,并具有高度可配置性。

    • 对所有数据和元数据进行分层校验,确保整个存储系统在使用时可以被验证,确认数据正确存储,或在数据损坏时进行修复。校验和存储在块的父块中,而非存储在块本身中。这与许多文件系统形成对比,后者的校验和(如果存在)与数据存储在一起,如果数据丢失或损坏,校验和也可能丢失或不正确。

    • 可以存储用户指定数量的数据或元数据副本,或选择性的数据类型,以提高从重要文件和结构的数据损坏中恢复的能力。

    • 在某些情况下,如果出现错误或不一致,可自动回滚文件系统和数据的最近更改。

    当然,在 Linux 上使用 ZFS 也能获得这些功能。然而,有一个很大的区别:没有任何 Linux 发行版能接近 FreeBSD 对 ZFS 的集成水平。

    启动环境

    由于与 ZFS 的紧密集成,FreeBSD 还支持启动环境(Boot Environments)。通过启动环境,你可以安装多个核心操作系统版本,并选择启动哪个。因此,启动环境就是工作系统的可启动克隆或快照。借助启动环境,你可以执行“无忧升级”或系统更改,无需担心破坏系统,因为你随时可以回滚并舍弃修改。

    这也意味着你可以在新的 ZFS 启动环境中更新 FreeBSD 系统,而无需接触正在运行的系统。你还可以在 FreeBSD Jail 内进行升级并测试结果,甚至可以将 ZFS 启动环境复制或迁移到另一台机器上。

    FreeBSD 提供了 工具,使管理启动环境变得简单。

    BSD init

    FreeBSD 使用传统的 BSD 风格 。在 BSD 风格 init 中,没有运行级别(run-levels),/etc/inittab 文件也不存在。相反,启动由 脚本控制。

    /etc/rc.d/ 中的脚本用于基本系统自带的应用程序,如 cron、sshd、syslog 等。/usr/local/etc/rc.d/ 中的脚本用于用户安装的第三方应用程序,如 NGINX 或 Postfix。

    如前所述,由于 FreeBSD 是作为完整操作系统开发的,用户安装的第三方应用程序不属于基本系统。第三方应用程序通过包或 ports 安装。为了与基本系统保持分离,用户安装的应用程序会安装在 /usr/local/ 下。因此,用户安装的可执行文件位于 /usr/local/bin/,而配置文件位于 /usr/local/etc/。

    在 BSD init 系统中,启用服务的方法是向 /etc/rc.conf 添加服务条目。默认设置位于 /etc/defaults/rc.conf,而 /etc/rc.conf 中的设置会覆盖默认值。

    例如,以下条目在 /etc/rc.conf 中启用 sshd:

    你可以手动添加该条目,也可以运行:

    这将自动编辑 /etc/rc.conf 并添加该条目。

    你也可以手动启动服务,方法是:

    如果某个服务尚未启用,但你仍然想启动它,可以通过命令行使用以下命令启动:

    你能在 上阅读更多关于 init 系统的内容。

    Jail

    FreeBSD 的 系统是另一项了不起的工程成就。

    Jails 于 2000 年 3 月 14 日在 FreeBSD 4.0 版本中引入。

    FreeBSD jail 是一种 ,它能让你在多个独立的迷你系统(称为 jail)中安装基于 FreeBSD 的系统。运行在 jail 中的系统共享相同的内核和系统资源,因此开销非常小。

    FreeBSD jail 的需求来源于一个小型共享环境托管提供商(R&D Associates, Inc. 的所有者 Derrick T. Woolworth)希望在其自身服务和客户服务之间建立清晰的分离,主要是为了安全性和便于管理。解决方案由 开发,它不是通过增加新的精细配置选项层,而是将系统(包括文件和资源)进行隔离,使只有正确的人才能访问正确的隔间。

    通过 FreeBSD jail,可以创建各种虚拟机,每个虚拟机都有自己安装的工具集和配置。这提供了一种安全的方式来测试软件。例如,可以在不同的 jail 中运行不同版本或尝试不同配置的 Web 服务器包。由于 jail 的范围有限,即使 jail 内的超级用户配置错误或操作失误,也不会危及系统的其他部分的完整性。因为 jail 外部的内容没有被修改,所以可以通过删除 jail 中的目录树副本来丢弃更改。

    然而,FreeBSD jail 并不实现真正的虚拟化;它无法让虚拟机运行与基本系统不同版本的内核。

    FreeBSD jail 是提高服务器安全性的有效方式,因为它通过隔离 jail 环境与系统其他部分(其他 jail 和基本系统)来实现安全隔离。

    Bastille

    是一款开源系统,用于在 FreeBSD 上自动化部署和管理容器化应用程序。

    Bastille 使用 FreeBSD jail 作为容器平台,并添加了模板自动化功能,以创建类似 Docker 的容器化软件集合。

    模板负责安装、配置、启用和启动软件,提供了一种自动化构建容器化堆栈的方法。

    Capsicum

    Capsicum 是由 开发的沙箱框架,由谷歌、FreeBSD 基金会和美国国防高级研究计划局提供资助支持。

    Capsicum 扩展了 POSIX API,提供了多个新的操作系统原语,以在类 UNIX 系统上支持对象能力安全:

    • Capabilities —— 精细化的文件描述符,带有细粒度权限

    • Capability mode —— 进程沙箱,拒绝访问全局命名空间

    • Process descriptors —— 面向能力的进程 ID 替代

    • Anonymous shared memory objects —— 对 POSIX 共享内存 API 的扩展,支持与文件描述符(能力)关联的匿名交换对象

    FreeBSD 上的 Capsicum 由 Robert Watson 和 Jonathan Anderson 开发,自 FreeBSD 10.0 起即开箱可用。FreeBSD 实现的 Capsicum 是参考实现,不仅作为 Capsicum API 和语义的参考,还为移植到其他平台的 ports(例如 Linux 和 DragonFlyBSD 的 Capsicum)提供了起点源码。

    更多关于 FreeBSD 上 Capsicum 的信息,请参见:

    • (PDF)

    • (YouTube)

    DTrace

    是一款全面的动态追踪框架,移植自 Solaris。DTrace 提供了强大的基础设施,使管理员、开发人员和服务人员能够简明地回答关于操作系统和用户程序行为的任意问题。

    DTrace 可以提供运行系统的全局概览,例如活跃进程使用的内存、CPU 时间、文件系统和网络资源。DTrace 还可以提供细粒度信息,例如某个函数调用时的参数日志,或者访问特定文件的进程列表。

    更多 DTrace 使用信息请参见 和 。

    bhyve

    是 FreeBSD 原生的虚拟机管理程序(hypervisor),用于在虚拟机中运行客户操作系统。可以通过命令行参数指定虚拟 CPU 数量、客户机内存大小以及 I/O 连接等参数。

    bhyve 支持多种客户操作系统的虚拟化,包括 FreeBSD 9 及以上版本、OpenBSD、NetBSD、Linux、illumos、DragonFly、Windows Vista 及更高版本,以及 Windows Server 2008 及更高版本。目前的开发工作旨在扩大对 x86-64 架构下其他操作系统的支持。

    bhyve hypervisor 自 FreeBSD 10.0-RELEASE 起成为基本系统的一部分。

    bhyve 需要处理器支持英特尔扩展页表(EPT)或 AMD 快速虚拟化索引(RVI)或嵌套页表(NPT)。托管 Linux 客户机或具有多个 vCPU 的 FreeBSD 客户机需要支持 VMX 无限制模式(UG)。较新的处理器,尤其是英特尔酷睿 i3/i5/i7 和英特尔至强 E3/E5/E7 系列,支持这些功能。UG 支持从 Intel 的 Westmere 微架构开始引入。

    防火墙

    FreeBSD 强调自由选择,因此基本系统内置了三种不同的防火墙:PF、IPFW 和 IPFILTER(也称为 IPF)。

    自 FreeBSD 5.3 起,OpenBSD 的 PF 防火墙的移植版本已作为基本系统的集成部分分发。PF 是款功能完整的防火墙,支持可选的 ALTQ(Alternate Queuing)以实现服务质量(QoS)。PF 的过滤语法类似于 IPF,但经过一些修改以提高清晰度。网络地址转换(NAT)和服务质量(QoS)已集成到 PF 中,其中 QoS 通过导入 ALTQ 排队软件并与 PF 配置关联实现。PF 还扩展了诸如 pfsync 和 CARP(用于故障切换和冗余)、authpf(会话认证)以及 ftp-proxy(简化复杂的 FTP 防火墙设置)等功能。此外,PF 支持对称多处理(SMP)和状态跟踪选项(STO)。

    PF 的日志功能也是其创新特性之一。PF 的日志可在 pf.conf 中按规则进行配置,由 PF 提供日志,再通过伪网络接口 pflog 传送,这是从内核模式获取数据给用户级程序的唯一方式。可以使用标准工具如 tcpdump 监控日志。

    IPFW 是为 FreeBSD 编写的状态防火墙,支持 IPv4 和 IPv6。它由多个组件构成:内核防火墙规则处理器及其集成的包计数功能、日志功能、NAT、 流量整形器、转发功能、桥接功能以及 ipstealth 功能。

    FreeBSD 在 /etc/rc.firewall 中提供了示例规则集,为常见场景定义了几种防火墙类型,以帮助新手生成合适的规则集。IPFW 提供强大的语法,高级用户可以利用它构建满足特定环境安全需求的自定义规则集。

    IPF 是款跨平台开源防火墙,已移植到了多个操作系统,如 FreeBSD、NetBSD、OpenBSD 和 Solaris。IPF 是内核防火墙和 NAT 机制,可由用户空间程序进行控制和监控。防火墙规则可以使用 ipf 设置或删除,NAT 规则可以使用 ipnat 设置或删除,IPF 内核部分的运行时统计可以通过 ipfstat 打印,ipmon 可将 IPF 的操作记录到系统日志文件中。

    IPF 最初使用“最后匹配规则生效”的规则处理逻辑,并且仅使用无状态规则。此后,IPF 增强了选项 quick 和 keep state。

    调优

    FreeBSD 拥有五百多个系统变量,可通过 工具读取和设置。这些系统变量可用于对正在运行的 FreeBSD 系统进行修改,包括 TCP/IP 栈和虚拟内存系统的许多高级选项,对于经验丰富的系统管理员来说,可以显著提升性能。

    GEOM

    FreeBSD 的 是 FreeBSD 操作系统的主要存储框架。它提供了访问存储层的标准化方式。GEOM 采用模块化设计,能让 GEOM 模块连接到框架。例如,geom_mirror 模块为系统提供 RAID1 或镜像功能。已有许多模块可用,并且各种 FreeBSD 开发者始终在积极开发新的模块。

    由于 GEOM 的模块化设计,模块可以堆叠形成 GEOM 层的链。例如,在 geom_mirror 模块之上可以添加加密模块,如 geom_eli,从而提供镜像且加密的卷。每个模块都有消费者和提供者。提供者是 GEOM 模块的来源,通常是物理硬盘,有时也可以是虚拟化的磁盘,如内存盘。GEOM 模块本身提供一个输出设备,其他 GEOM 模块(称为消费者)可以使用该提供者来创建相互连接的模块链。

    Linux 二进制兼容层

    FreeBSD 提供对 Linux 的二进制兼容层。这能让用户在 FreeBSD 系统上安装和运行许多 Linux 二进制文件,而无需先修改这些二进制文件。在某些特定情况下,Linux 二进制文件在 FreeBSD 上的性能甚至可能优于在 Linux 上的表现。

    并非所有 Linux 特定的操作系统功能都在 FreeBSD 上受支持。例如,如果 Linux 二进制文件过度使用 i386 特定调用(如启用虚拟 8086 模式),则无法在 FreeBSD 上运行。

    安全事件审计

    FreeBSD 支持安全事件审计。事件审计可以对各种与安全相关的系统事件(包括登录、配置更改以及文件和网络访问)进行可靠、细粒度且可配置的日志记录。这些日志记录对于实时系统监控、入侵检测和事后分析非常有价值。FreeBSD 实现了 Sun 发布的基本安全模块(BSM)应用编程接口(API)和文件格式,并且能够与 Solaris 和 Mac OS X 的审计实现互操作。

    结语

    本文并不是关于使用 FreeBSD 而非 GNU/Linux 的技术原因的详尽列表。还有许多其他原因我没有涉及。然而,这些是我认为最突出的几个特性。

    我在第一台 PC 上运行过 Microsoft ,后来又使用了 Microsoft Windows 3.0。从那时起直到 Microsoft Windows XP,我在微软操作系统上做了很多 PC 和服务器相关的工作,但我非常讨厌这些系统。它们非常耗时,因为微软的操作系统既不安全、不稳定,又相当糟糕。

    大约在 1997 年,我的一位朋友建议我尝试 Linux,我照做了。我运行的第一个 Linux 发行版是 。通过我那台旧调制解调器下载它花了一个多星期,期间电话线几乎全天都在占用 :)

    在运行 Red Hat Linux 并测试了其他 Linux 发行版几年后,我最终选择了 Debian,主要是因为它当时出色的包管理器 以及其稳定性(稳定分支只接收安全和错误修复)。Debian 成为我最喜欢的 Linux 发行版,无论是个人还是工作站和服务器上,我都在使用它。

    1998 年,,从 1999 年左右开始,我个人和工作上都开始使用 FreeBSD,涵盖工作站和服务器。从那时起,我尝试了许多其他操作系统,如今我还使用 、、、 和 。

    我按不同任务使用不同操作系统,并且在特定场景下偏好某些系统。

    目前,我在桌面工作站和多台服务器上都以 FreeBSD 作为主要操作系统,除非你有非常特定的需求必须使用 Linux,否则你会发现 FreeBSD 更加贴近真正的 UNIX。如果你需要 ZFS,那么你绝对应该使用 FreeBSD。

    无论如何,下次如果你计划尝鲜操作系统,不妨尝试 。它也有优秀的社区,许多人乐于助人且友好。

    root@node1:~ # cat /etc/rc.conf
    hostname=node1
    ifconfig_em0="inet 10.0.10.111/24 up"
    defaultrouter=10.0.10.1
    sshd_enable=YES
    root@node1:~ # grep PermitRootLogin /etc/ssh/sshd_config
    PermitRootLogin yes
    
    root@node1:~ # service sshd restart
    vboxhost % ssh -l root localhost -p 2211
    root@node1:~ # echo 'nameserver 1.1.1.1' > /etc/resolv.conf
    root@node1:~ # sed -i '' s/quarterly/latest/g /etc/pkg/FreeBSD.conf
    root@node1:~ # pkg install pacemaker2 corosync2 crmsh
    
    root@node2:~ # pkg install pacemaker2 corosync2 crmsh
    
    root@node3:~ # pkg install pacemaker2 corosync2 crmsh
    Message from pacemaker2-2.0.4:
    
    --
    For correct operation, maximum socket buffer size must be tuned
    by performing the following command as root :
    
    # sysctl kern.ipc.maxsockbuf=18874368
    
    To preserve this setting across reboots, append the following
    to /etc/sysctl.conf :
    
    kern.ipc.maxsockbuf=18874368
    
    ======================================================================
    
    Message from corosync2-2.4.5_1:
    
    --
    For correct operation, maximum socket buffer size must be tuned
    by performing the following command as root :
    
    # sysctl kern.ipc.maxsockbuf=18874368
    
    To preserve this setting across reboots, append the following
    to /etc/sysctl.conf :
    
    kern.ipc.maxsockbuf=18874368
    root@node1:~ # echo 'kern.ipc.maxsockbuf=18874368' >> /etc/sysctl.conf
    root@node1:~ # service sysctl restart
    
    root@node2:~ # echo 'kern.ipc.maxsockbuf=18874368' >> /etc/sysctl.conf
    root@node2:~ # service sysctl restart
    
    root@node3:~ # echo 'kern.ipc.maxsockbuf=18874368' >> /etc/sysctl.conf
    root@node3:~ # service sysctl restart
    root@node1:~ # pkg info -l pacemaker2 | grep bin
            /usr/local/sbin/attrd_updater
            /usr/local/sbin/cibadmin
            /usr/local/sbin/crm_attribute
            /usr/local/sbin/crm_diff
            /usr/local/sbin/crm_error
            /usr/local/sbin/crm_failcount
            /usr/local/sbin/crm_master
            /usr/local/sbin/crm_mon
            /usr/local/sbin/crm_node
            /usr/local/sbin/crm_report
            /usr/local/sbin/crm_resource
            /usr/local/sbin/crm_rule
            /usr/local/sbin/crm_shadow
            /usr/local/sbin/crm_simulate
            /usr/local/sbin/crm_standby
            /usr/local/sbin/crm_ticket
            /usr/local/sbin/crm_verify
            /usr/local/sbin/crmadmin
            /usr/local/sbin/fence_legacy
            /usr/local/sbin/iso8601
            /usr/local/sbin/pacemaker-remoted
            /usr/local/sbin/pacemaker_remoted
            /usr/local/sbin/pacemakerd
            /usr/local/sbin/stonith_admin
    
    root@node1:~ # pkg info -l corosync2 | grep bin
            /usr/local/bin/corosync-blackbox
            /usr/local/sbin/corosync
            /usr/local/sbin/corosync-cfgtool
            /usr/local/sbin/corosync-cmapctl
            /usr/local/sbin/corosync-cpgtool
            /usr/local/sbin/corosync-keygen
            /usr/local/sbin/corosync-notifyd
            /usr/local/sbin/corosync-quorumtool
    
    root@node1:~ # pkg info -l crmsh | grep bin
            /usr/local/bin/crm
    root@node1:~ # tail -3 /etc/hosts
    
    10.0.10.111 node1
    10.0.10.112 node2
    10.0.10.113 node3
    
    root@node2:~ # tail -3 /etc/hosts
    
    10.0.10.111 node1
    10.0.10.112 node2
    10.0.10.113 node3
    
    root@node3:~ # tail -3 /etc/hosts
    
    10.0.10.111 node1
    10.0.10.112 node2
    10.0.10.113 node3
    root@node1:~ # corosync-keygen
    Corosync Cluster Engine Authentication key generator.
    Gathering 1024 bits for key from /dev/random.
    Press keys on your keyboard to generate entropy.
    Writing corosync key to /usr/local/etc/corosync/authkey.
    
    root@node1:~ # echo $?
    0
    
    root@node1:~ # ls -l /usr/local/etc/corosync/authkey
    -r--------  1 root  wheel  128 Sep  2 20:37 /usr/local/etc/corosync/authkey
    root@node1:~ # pkg info -l corosync2 | grep example
            /usr/local/etc/corosync/corosync.conf.example
            /usr/local/etc/corosync/corosync.conf.example.udpu
    root@node1:~ # cp /usr/local/etc/corosync/corosync.conf.example.udpu /usr/local/etc/corosync/corosync.conf
    
    root@node1:~ # vi /usr/local/etc/corosync/corosync.conf
                   /* LOTS OF EDITS HERE */
    
    root@node1:~ # cat /usr/local/etc/corosync/corosync.conf
    
    totem {
      version: 2
      crypto_cipher: aes256
      crypto_hash: sha256
      transport: udpu
    
      interface {
        ringnumber: 0
        bindnetaddr: 10.0.10.0
        mcastport: 5405
        ttl: 1
      }
    }
    
    logging {
      fileline: off
      to_logfile: yes
      to_syslog: no
      logfile: /var/log/cluster/corosync.log
      debug: off
      timestamp: on
    
      logger_subsys {
        subsys: QUORUM
        debug: off
      }
    }
    
    nodelist {
    
      node {
        ring0_addr: 10.0.10.111
        nodeid: 1
      }
    
      node {
        ring0_addr: 10.0.10.112
        nodeid: 2
      }
    
      node {
        ring0_addr: 10.0.10.113
        nodeid: 3
      }
    
    }
    
    quorum {
      provider: corosync_votequorum
      expected_votes: 2
    }
    root@node1:~ # pkg install -y rsync
    
    root@node1:~ # rsync -av /usr/local/etc/corosync/ node2:/usr/local/etc/corosync/
    The authenticity of host 'node2 (10.0.10.112)' can't be established.
    ECDSA key fingerprint is SHA256:/ZDmln7GKi6n0kbad73TIrajPjGfQqJJX+ReSf3NMvc.
    No matching host key fingerprint found in DNS.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'node2' (ECDSA) to the list of known hosts.
    Password for root@node2:
    sending incremental file list
    ./
    authkey
    corosync.conf
    service.d/
    uidgid.d/
    
    sent 1,100 bytes  received 69 bytes  259.78 bytes/sec
    total size is 4,398  speedup is 3.76
    
    root@node1:~ # rsync -av /usr/local/etc/corosync/ node3:/usr/local/etc/corosync/
    The authenticity of host 'node2 (10.0.10.112)' can't be established.
    ECDSA key fingerprint is SHA256:/ZDmln7GKi6n0kbad73TIrajPjGfQqJJX+ReSf3NMvc.
    No matching host key fingerprint found in DNS.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added 'node3' (ECDSA) to the list of known hosts.
    Password for root@node3:
    sending incremental file list
    ./
    authkey
    corosync.conf
    service.d/
    uidgid.d/
    
    sent 1,100 bytes  received 69 bytes  259.78 bytes/sec
    total size is 4,398  speedup is 3.76
    root@node1:~ # cksum /usr/local/etc/corosync/{authkey,corosync.conf}
    2277171666 128 /usr/local/etc/corosync/authkey
    1728717329 622 /usr/local/etc/corosync/corosync.conf
    
    root@node2:~ # cksum /usr/local/etc/corosync/{authkey,corosync.conf}
    2277171666 128 /usr/local/etc/corosync/authkey
    1728717329 622 /usr/local/etc/corosync/corosync.conf
    
    root@node3:~ # cksum /usr/local/etc/corosync/{authkey,corosync.conf}
    2277171666 128 /usr/local/etc/corosync/authkey
    1728717329 622 /usr/local/etc/corosync/corosync.conf
    root@node1:~ # sysrc corosync_enable=YES
    corosync_enable:  -> YES
    
    root@node1:~ # sysrc pacemaker_enable=YES
    pacemaker_enable:  -> YES
    
    root@node2:~ # sysrc corosync_enable=YES
    corosync_enable:  -> YES
    
    root@node2:~ # sysrc pacemaker_enable=YES
    pacemaker_enable:  -> YES
    
    root@node3:~ # sysrc corosync_enable=YES
    corosync_enable:  -> YES
    
    root@node3:~ # sysrc pacemaker_enable=YES
    pacemaker_enable:  -> YES
    root@node1:~ # service corosync start
    Starting corosync.
    Sep 02 20:55:35 notice  [MAIN  ] Corosync Cluster Engine ('2.4.5'): started and ready to provide service.
    Sep 02 20:55:35 info    [MAIN  ] Corosync built-in features:
    Sep 02 20:55:35 warning [MAIN  ] interface section bindnetaddr is used together with nodelist. Nodelist one is going to be used.
    Sep 02 20:55:35 warning [MAIN  ] Please migrate config file to nodelist.
    
    root@node1:~ # ps aux | grep corosync
    root  1695   0.0  7.9 38340 38516  -  S    20:55    0:00.40 /usr/local/sbin/corosync
    root  1699   0.0  0.1   524   336  0  R+   20:57    0:00.00 grep corosync
    root@node1:~ # crm status
    Could not connect to the CIB: Socket is not connected
    crm_mon: Error: cluster is not available on this node
    ERROR: status: crm_mon (rc=102):
    root@node1:~ # service pacemaker start
    Starting pacemaker.
    
    root@node2:~ # service pacemaker start
    Starting pacemaker.
    
    root@node3:~ # service pacemaker start
    Starting pacemaker.
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: unknown
      * Current DC: NONE
      * Last updated: Wed Sep  2 20:58:51 2020
      * Last change:  
      * 0 nodes configured
      * 0 resource instances configured
    
    
    Full List of Resources:
      * No resources
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 21:02:49 2020
      * Last change:  Wed Sep  2 20:59:00 2020 by hacluster via crmd on node2
      * 3 nodes configured
      * 0 resource instances configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * No resources
    root@node1:~ # ps aux | grep pacemaker
    root      1716   0.0  0.5 10844   2396  -  Is   20:58     0:00.00 daemon: /usr/local/sbin/pacemakerd[1717] (daemon)
    root      1717   0.0  5.2 49264  25284  -  S    20:58     0:00.27 /usr/local/sbin/pacemakerd
    hacluster 1718   0.0  6.1 48736  29708  -  Ss   20:58     0:00.75 /usr/local/libexec/pacemaker/pacemaker-based
    root      1719   0.0  4.5 40628  21984  -  Ss   20:58     0:00.28 /usr/local/libexec/pacemaker/pacemaker-fenced
    root      1720   0.0  2.8 25204  13688  -  Ss   20:58     0:00.20 /usr/local/libexec/pacemaker/pacemaker-execd
    hacluster 1721   0.0  3.9 38148  19100  -  Ss   20:58     0:00.25 /usr/local/libexec/pacemaker/pacemaker-attrd
    hacluster 1722   0.0  2.9 25460  13864  -  Ss   20:58     0:00.17 /usr/local/libexec/pacemaker/pacemaker-schedulerd
    hacluster 1723   0.0  5.4 49304  26300  -  Ss   20:58     0:00.41 /usr/local/libexec/pacemaker/pacemaker-controld
    root      1889   0.0  0.6 11348   2728  0  S+   21:56     0:00.00 grep pacemaker
    root@node1:~ # corosync-cmapctl | grep members
    runtime.totem.pg.mrp.srp.members.1.config_version (u64) = 0
    runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(10.0.10.111) 
    runtime.totem.pg.mrp.srp.members.1.join_count (u32) = 1
    runtime.totem.pg.mrp.srp.members.1.status (str) = joined
    runtime.totem.pg.mrp.srp.members.2.config_version (u64) = 0
    runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(10.0.10.112) 
    runtime.totem.pg.mrp.srp.members.2.join_count (u32) = 1
    runtime.totem.pg.mrp.srp.members.2.status (str) = joined
    runtime.totem.pg.mrp.srp.members.3.config_version (u64) = 0
    runtime.totem.pg.mrp.srp.members.3.ip (str) = r(0) ip(10.0.10.113) 
    runtime.totem.pg.mrp.srp.members.3.join_count (u32) = 1
    runtime.totem.pg.mrp.srp.members.3.status (str) = joined
    root@node1:~ # corosync-quorumtool
    Quorum information
    ------------------
    Date:             Wed Sep  2 21:00:38 2020
    Quorum provider:  corosync_votequorum
    Nodes:            3
    Node ID:          1
    Ring ID:          1/12
    Quorate:          Yes
    
    Votequorum information
    ----------------------
    Expected votes:   3
    Highest expected: 3
    Total votes:      3
    Quorum:           2  
    Flags:            Quorate 
    
    Membership information
    ----------------------
        Nodeid      Votes Name
             1          1 10.0.10.111 (local)
             2          1 10.0.10.112
             3          1 10.0.10.113
    root@node1:~ # cat /var/log/cluster/corosync.log
    Sep 02 20:55:35 [1694] node1 corosync notice  [MAIN  ] Corosync Cluster Engine ('2.4.5'): started and ready to provide service.
    Sep 02 20:55:35 [1694] node1 corosync info    [MAIN  ] Corosync built-in features:
    Sep 02 20:55:35 [1694] node1 corosync warning [MAIN  ] interface section bindnetaddr is used together with nodelist. Nodelist one is going to be used.
    Sep 02 20:55:35 [1694] node1 corosync warning [MAIN  ] Please migrate config file to nodelist.
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] Initializing transport (UDP/IP Unicast).
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] Initializing transmit/receive security (NSS) crypto: aes256 hash: sha256
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] The network interface [10.0.10.111] is now up.
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync configuration map access [0]
    Sep 02 20:55:35 [1694] node1 corosync info    [QB    ] server name: cmap
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync configuration service [1]
    Sep 02 20:55:35 [1694] node1 corosync info    [QB    ] server name: cfg
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync cluster closed process group service v1.01 [2]
    Sep 02 20:55:35 [1694] node1 corosync info    [QB    ] server name: cpg
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync profile loading service [4]
    Sep 02 20:55:35 [1694] node1 corosync notice  [QUORUM] Using quorum provider corosync_votequorum
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync vote quorum service v1.0 [5]
    Sep 02 20:55:35 [1694] node1 corosync info    [QB    ] server name: votequorum
    Sep 02 20:55:35 [1694] node1 corosync notice  [SERV  ] Service engine loaded: corosync cluster quorum service v0.1 [3]
    Sep 02 20:55:35 [1694] node1 corosync info    [QB    ] server name: quorum
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] adding new UDPU member {10.0.10.111}
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] adding new UDPU member {10.0.10.112}
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] adding new UDPU member {10.0.10.113}
    Sep 02 20:55:35 [1694] node1 corosync notice  [TOTEM ] A new membership (10.0.10.111:4) was formed. Members joined: 1
    Sep 02 20:55:35 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:55:35 [1694] node1 corosync notice  [QUORUM] Members[1]: 1
    Sep 02 20:55:35 [1694] node1 corosync notice  [MAIN  ] Completed service synchronization, ready to provide service.
    Sep 02 20:58:14 [1694] node1 corosync notice  [TOTEM ] A new membership (10.0.10.111:8) was formed. Members joined: 2
    Sep 02 20:58:14 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:58:14 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:58:14 [1694] node1 corosync notice  [QUORUM] This node is within the primary component and will provide service.
    Sep 02 20:58:14 [1694] node1 corosync notice  [QUORUM] Members[2]: 1 2
    Sep 02 20:58:14 [1694] node1 corosync notice  [MAIN  ] Completed service synchronization, ready to provide service.
    Sep 02 20:58:19 [1694] node1 corosync notice  [TOTEM ] A new membership (10.0.10.111:12) was formed. Members joined: 3
    Sep 02 20:58:19 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:58:19 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:58:19 [1694] node1 corosync warning [CPG   ] downlist left_list: 0 received
    Sep 02 20:58:19 [1694] node1 corosync notice  [QUORUM] Members[3]: 1 2 3
    Sep 02 20:58:19 [1694] node1 corosync notice  [MAIN  ] Completed service synchronization, ready to provide service.
    root@node1:~ # crm configure show
    node 1: node1
    node 2: node2
    node 3: node3
    property cib-bootstrap-options: \
            have-watchdog=false \
            dc-version=2.0.4-2deceaa3ae \
            cluster-infrastructure=corosync
    root@node1:~ # crm configure property stonith-enabled=false
    root@node1:~ # crm configure show
    node 1: node1
    node 2: node2
    node 3: node3
    property cib-bootstrap-options: \
            have-watchdog=false \
            dc-version=2.0.4-2deceaa3ae \
            cluster-infrastructure=corosync \
            stonith-enabled=false
    root@node1:~ # crm configure primitive IP ocf:heartbeat:IPaddr2 params ip=10.0.10.200 cidr_netmask="24" op monitor interval="30s"
    root@node1:~ # crm configure show
    node 1: node1
    node 2: node2
    node 3: node3
    primitive IP IPaddr2 \
            params ip=10.0.10.200 cidr_netmask=24 \
            op monitor interval=30s
    property cib-bootstrap-options: \
            have-watchdog=false \
            dc-version=2.0.4-2deceaa3ae \
            cluster-infrastructure=corosync \
            stonith-enabled=false
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:03:35 2020
      * Last change:  Wed Sep  2 22:02:53 2020 by root via cibadmin on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * IP  (ocf::heartbeat:IPaddr2):        Stopped
    
    Failed Resource Actions:
      * IP_monitor_0 on node3 'not installed' (5): call=5, status='complete', exitreason='Setup problem: couldn't find command: ip', last-rc-change='2020-09-02 22:02:53Z', queued=0ms, exec=132ms
      * IP_monitor_0 on node2 'not installed' (5): call=5, status='complete', exitreason='Setup problem: couldn't find command: ip', last-rc-change='2020-09-02 22:02:54Z', queued=0ms, exec=120ms
      * IP_monitor_0 on node1 'not installed' (5): call=5, status='complete', exitreason='Setup problem: couldn't find command: ip', last-rc-change='2020-09-02 22:02:53Z', queued=0ms, exec=110ms
    root@node1:~ # crm configure delete IP
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:04:34 2020
      * Last change:  Wed Sep  2 22:04:31 2020 by root via cibadmin on node1
      * 3 nodes configured
      * 0 resource instances configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * No resources
    root@node1:~ # ls -l /usr/local/lib/ocf/resource.d/pacemaker
    total 144
    -r-xr-xr-x  1 root  wheel   7484 Aug 29 01:22 ClusterMon
    -r-xr-xr-x  1 root  wheel   9432 Aug 29 01:22 Dummy
    -r-xr-xr-x  1 root  wheel   5256 Aug 29 01:22 HealthCPU
    -r-xr-xr-x  1 root  wheel   5342 Aug 29 01:22 HealthIOWait
    -r-xr-xr-x  1 root  wheel   9450 Aug 29 01:22 HealthSMART
    -r-xr-xr-x  1 root  wheel   6186 Aug 29 01:22 Stateful
    -r-xr-xr-x  1 root  wheel  11370 Aug 29 01:22 SysInfo
    -r-xr-xr-x  1 root  wheel   5856 Aug 29 01:22 SystemHealth
    -r-xr-xr-x  1 root  wheel   7382 Aug 29 01:22 attribute
    -r-xr-xr-x  1 root  wheel   7854 Aug 29 01:22 controld
    -r-xr-xr-x  1 root  wheel  16134 Aug 29 01:22 ifspeed
    -r-xr-xr-x  1 root  wheel  11040 Aug 29 01:22 o2cb
    -r-xr-xr-x  1 root  wheel  11696 Aug 29 01:22 ping
    -r-xr-xr-x  1 root  wheel   6356 Aug 29 01:22 pingd
    -r-xr-xr-x  1 root  wheel   3702 Aug 29 01:22 remote
    root@node1:~ # cp /usr/local/lib/ocf/resource.d/pacemaker/Dummy /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
    
    root@node1:~ # vi /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
                   /* 输入量真大啊…… */
    root@node1:~ # setenv OCF_ROOT /usr/local/lib/ocf
    root@node1:~ # ocf-tester -n resourcename /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
    Beginning tests for /usr/local/lib/ocf/resource.d/pacemaker/ifconfig...
    * rc=3: Your agent has too restrictive permissions: should be 755
    -:1: parser error : Start tag expected, '<' not found
    usage: /usr/local/lib/ocf/resource.d/pacemaker/ifconfig {start|stop|monitor}
    ^
    * rc=1: Your agent produces meta-data which does not conform to ra-api-1.dtd
    * rc=3: Your agent does not support the meta-data action
    * rc=3: Your agent does not support the validate-all action
    * rc=0: Monitoring a stopped resource should return 7
    * rc=0: The initial probe for a stopped resource should return 7 or 5 even if all binaries are missing
    * Your agent does not support the notify action (optional)
    * Your agent does not support the demote action (optional)
    * Your agent does not support the promote action (optional)
    * Your agent does not support master/slave (optional)
    * rc=0: Monitoring a stopped resource should return 7
    * rc=0: Monitoring a stopped resource should return 7
    * rc=0: Monitoring a stopped resource should return 7
    * Your agent does not support the reload action (optional)
    Tests failed: /usr/local/lib/ocf/resource.d/pacemaker/ifconfig failed 9 tests
    root@node1:~ # vi /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
                 /* LOTS OF NERVOUS TYPING */
    root@node1:~ # chmod 755 /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
    root@node1:~ # setenv OCF_ROOT /usr/local/lib/ocf
    root@node1:~ # ocf-tester -n resourcename /usr/local/lib/ocf/resource.d/pacemaker/ifconfig
    Beginning tests for /usr/local/lib/ocf/resource.d/pacemaker/ifconfig...
    * Your agent does not support the notify action (optional)
    * Your agent does not support the demote action (optional)
    * Your agent does not support the promote action (optional)
    * Your agent does not support master/slave (optional)
    * Your agent does not support the reload action (optional)
    /usr/local/lib/ocf/resource.d/pacemaker/ifconfig passed all tests
    root@node1:~ # crm configure primitive IP ocf:pacemaker:ifconfig op monitor interval="30"
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:44:52 2020
      * Last change:  Wed Sep  2 22:44:44 2020 by root via cibadmin on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * IP  (ocf::pacemaker:ifconfig):       Started node1
    
    Failed Resource Actions:
      * IP_monitor_0 on node3 'not installed' (5): call=24, status='Not installed', exitreason='', last-rc-change='2020-09-02 22:42:52Z', queued=0ms, exec=5ms
      * IP_monitor_0 on node2 'not installed' (5): call=24, status='Not installed', exitreason='', last-rc-change='2020-09-02 22:42:53Z', queued=0ms, exec=2ms
    root@node1:~ # rsync -av /usr/local/lib/ocf/resource.d/pacemaker/ node2:/usr/local/lib/ocf/resource.d/pacemaker/
    Password for root@node2:
    sending incremental file list
    ./
    ifconfig
    
    sent 3,798 bytes  received 38 bytes  1,534.40 bytes/sec
    total size is 128,003  speedup is 33.37
    
    root@node1:~ # rsync -av /usr/local/lib/ocf/resource.d/pacemaker/ node3:/usr/local/lib/ocf/resource.d/pacemaker/
    Password for root@node3:
    sending incremental file list
    ./
    ifconfig
    
    sent 3,798 bytes  received 38 bytes  1,534.40 bytes/sec
    total size is 128,003  speedup is 33.37
    root@node1:~ # crm resource stop IP
    root@node1:~ # crm configure delete IP
    root@node1:~ # crm configure primitive IP ocf:pacemaker:ifconfig op monitor interval="30"
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:45:46 2020
      * Last change:  Wed Sep  2 22:45:43 2020 by root via cibadmin on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * IP  (ocf::pacemaker:ifconfig):       Started node1
    root@node1:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=81009b
            ether 08:00:27:2a:78:60
            inet 10.0.10.111 netmask 0xffffff00 broadcast 10.0.10.255
            inet 10.0.10.200 netmask 0xffffff00 broadcast 10.0.10.255
            media: Ethernet autoselect (1000baseT )
            status: active
            nd6 options=29
    
    root@node2:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=81009b
            ether 08:00:27:80:50:05
            inet 10.0.10.112 netmask 0xffffff00 broadcast 10.0.10.255
            media: Ethernet autoselect (1000baseT )
            status: active
            nd6 options=29
    
    root@node3:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=81009b
            ether 08:00:27:74:5e:b9
            inet 10.0.10.113 netmask 0xffffff00 broadcast 10.0.10.255
            media: Ethernet autoselect (1000baseT )
            status: active
            nd6 options=29
    root@node1:~ # crm resource move IP node3
    INFO: Move constraint created for IP to node3
    
    root@node1:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:47:31 2020
      * Last change:  Wed Sep  2 22:47:28 2020 by root via crm_resource on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * IP  (ocf::pacemaker:ifconfig):       Started node3
    root@node3:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=81009b
            ether 08:00:27:74:5e:b9
            inet 10.0.10.113 netmask 0xffffff00 broadcast 10.0.10.255
            inet 10.0.10.200 netmask 0xffffff00 broadcast 10.0.10.255
            media: Ethernet autoselect (1000baseT )
            status: active
            nd6 options=29
    
    root@node1:~ # ifconfig em0
    em0: flags=8843 metric 0 mtu 1500
            options=81009b
            ether 08:00:27:2a:78:60
            inet 10.0.10.111 netmask 0xffffff00 broadcast 10.0.10.255
            media: Ethernet autoselect (1000baseT )
            status: active
            nd6 options=29
    root@node2:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:49:57 2020
      * Last change:  Wed Sep  2 22:47:29 2020 by root via crm_resource on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 node3 ]
    
    Full List of Resources:
      * IP  (ocf::pacemaker:ifconfig):       Started node3
    
    root@node3:~ # poweroff
    
    root@node2:~ # crm status
    Cluster Summary:
      * Stack: corosync
      * Current DC: node2 (version 2.0.4-2deceaa3ae) - partition with quorum
      * Last updated: Wed Sep  2 22:50:16 2020
      * Last change:  Wed Sep  2 22:47:29 2020 by root via crm_resource on node1
      * 3 nodes configured
      * 1 resource instance configured
    
    Node List:
      * Online: [ node1 node2 ]
      * OFFLINE: [ node3 ]
    
    Full List of Resources:
      * IP  (ocf::pacemaker:ifconfig):       Started node1
    sysctlinfo_load="YES" ①
    mac_priority_load="YES" ②
    #hint.pcm.5.eq=1 ③
    kern.timecounter.alloweddeviation=0 ①
    hw.usb.uaudio.buffer_ms=2 ②
    hw.snd.latency=0 ③
    dev.pcm.5.play.vchans=0 ④
    dev.pcm.5.bitperfect=1 ⑤
    hw.snd.default_unit=5 ⑥
    #hw.snd.vpc_0db=80 ⑦
    #dev.pcm.5.eq_preamp=-5 ⑧
    # ./wakeup_latency
    0.007341
    0.014410
    0.037370
    0.037336
    0.037375
    0.037345
    0.037356
    ...
    # sysctl kern.timecounter.alloweddeviation=0
    kern.timecounter.alloweddeviation: 5 -> 0
    
    # ./wakeup_latency
    0.000061
    0.000095
    0.000077
    0.000093
    0.000096
    0.000090
    0.000062
    ...
    musicpd_enable="YES" ①
    # kldstat
    Id Refs Address                Size Name
     1   43 0xffffffff80200000  1f3c6c0 kernel
     2    1 0xffffffff8213d000     3368 sysctlbyname_improved.ko
     3    1 0xffffffff82142000     77d8 cryptodev.ko
     4    1 0xffffffff8214a000     5b18 sysctlinfo.ko
     5    1 0xffffffff82150000     3c48 mac_priority.ko
     6    1 0xffffffff82154000   5da658 zfs.ko
     7    1 0xffffffff83020000     3390 acpi_wmi.ko
     8    1 0xffffffff83024000     4250 ichsmb.ko
     9    1 0xffffffff83029000     2178 smbus.ko
    10    1 0xffffffff8302c000     e5b0 snd_uaudio.ko
    11    1 0xffffffff8303b000     2a68 mac_ntpd.ko
    12    1 0xffffffff8303e000     3560 fdescfs.ko
    13    1 0xffffffff83042000    1aec0 ext2fs.ko
    # cat /dev/sndstat
    Installed devices:
    pcm0: <Realtek ALC233 (Analog 2.0+HP/2.0)> (play/rec)
    pcm1: <Realtek ALC233 (Analog)> (play/rec)
    pcm2: <Intel Braswell (HDMI/DP 8ch)> (play)
    pcm3: <Intel Braswell (HDMI/DP 8ch)> (play)
    pcm4: <Intel Braswell (HDMI/DP 8ch)> (play)
    pcm5: <Cambridge Audio Cambridge Audio USB Audio 2.0> (play) default
    No devices installed from userspace.
    # sysctl hw.snd.verbose=4
    # cat /dev/sndstat
    ...
    pcm5:  on uaudio0 (1p:0v/0r:0v) default
            snddev flags=0x3e7<SIMPLEX,AUTOVCHAN,SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,BITPERFECT,VPC>
            [dsp5.play.0]: spd 44100, fmt 0x00201000, flags 0x2000012c, 0x00000001, pid 1059 (musicpd)
                    interrupts 45405, underruns 0, feed 45404, ready 8192
                    [b:5648/2824/2|bs:8192/2048/4]
                    channel flags=0x2000012c<RUNNING,TRIGGERED,SLEEPING,BUSY,BITPERFECT>
                    {userland} -> feeder_root(0x00201000) -> {hardware}
    ...
    # usbconfig -d ugen0.3 dump_device_desc
    ugen0.3:  at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (2mA)
    
      bLength = 0x0012
      bDescriptorType = 0x0001
      bcdUSB = 0x0200
      bDeviceClass = 0x00ef  <Miscellaneous device>
      bDeviceSubClass = 0x0002
      bDeviceProtocol = 0x0001
      bMaxPacketSize0 = 0x0040
      idVendor = 0x22e8
      idProduct = 0xdac2
      bcdDevice = 0x0326
      iManufacturer = 0x0001  <Cambridge Audio >
      iProduct = 0x0002  <Cambridge Audio USB Audio 2.0>
      iSerialNumber = 0x0003  <0000>
      bNumConfigurations = 0x0002
    # sysctl hw.snd
    hw.snd.maxautovchans: 16
    hw.snd.default_unit: 5
    hw.snd.default_auto: 0
    hw.snd.verbose: 0
    hw.snd.vpc_mixer_bypass: 0
    0hw.snd.feeder_rate_quality: 1
    hw.snd.feeder_rate_round: 25
    hw.snd.feeder_rate_max: 2016000
    hw.snd.feeder_rate_min: 1
    hw.snd.feeder_rate_polyphase_max: 183040
    hw.snd.feeder_rate_presets: 100:8:0.85 100:36:0.92 100:164:0.97
    hw.snd.feeder_eq_exact_rate: 0
    hw.snd.feeder_eq_presets: PEQ:16000,0.2500,62,0.2500:-9,9,1.0:44100,48000,88200,96000,176400,192000
    hw.snd.basename_clone: 1
    hw.snd.compat_linux_mmap: 0
    hw.snd.syncdelay: -1
    hw.snd.usefrags: 0
    hw.snd.vpc_reset: 0
    hw.snd.vpc_0db: 45
    hw.snd.vpc_autoreset: 1
    hw.snd.timeout: 5
    hw.snd.latency_profile: 1
    hw.snd.latency: 0
    hw.snd.report_soft_matrix: 1
    hw.snd.report_soft_formats: 1
    # sysctl dev.pcm.5
    dev.pcm.5.feedback_rate: 44098
    dev.pcm.5.mode: 3
    dev.pcm.5.bitperfect: 1
    dev.pcm.5.buffersize: 0
    dev.pcm.5.play.vchans: 0
    dev.pcm.5.hwvol_mixer: vol
    dev.pcm.5.hwvol_step: 5
    dev.pcm.5.%iommu:
    dev.pcm.5.%parent: uaudio0
    dev.pcm.5.%pnpinfo:
    dev.pcm.5.%location:
    dev.pcm.5.%driver: pcm
    dev.pcm.5.%desc: Cambridge Audio Cambridge Audio USB Audio 2.0
    # service musicpd stop
    # rtprio 0 musicpd /usr/local/etc/musicpd.conf
    # ps -o rtprio -axl | grep [m]usicpd
    real:0 137 1146 1 0 -52 0 415080 214420 select I<s - 0:06.55 musicpd /usr/local/etc/musicpd.conf
    # top -p `pgrep -d "," musicpd`
    last pid:  1162;  load averages:  0.03,  0.07,  0.04              up 0+12:05:50  21:38:34
    50 processes:  2 running, 46 sleeping, 2 waiting
    CPU: 50.0% user,  0.0% nice, 50.0% system,  0.0% interrupt,  0.0% idle
    Mem: 497M Active, 64M Inact, 998M Wired, 49M Buf, 2267M Free
    ARC: 85M Total, 27M MFU, 55M MRU, 514K Header, 1935K Other
         66M Compressed, 153M Uncompressed, 2.32:1 Ratio
    Swap: 2048M Total, 2048M Free
    
      PID USERNAME    THR PRI NICE   SIZE    RES STATE    C   TIME    WCPU COMMAND
     1146 mpd           8 -52   r0   605M   227M select   0   0:12   0.00% musicpd
    # sysctl hw.usb.debug=1
    # tail -f /var/log/messages
    ...
    Jan 21 21:55:44 freebsd kernel: usbd_pipe_enter: enter
    Jan 21 21:55:44 freebsd kernel: usbd_transfer_done: err=USB_ERR_NORMAL_COMPLETION
    Jan 21 21:55:44 freebsd kernel: usbd_callback_wrapper_sub: xfer=0xfffffe007c950278 endpoint=0xfffff800038ad968 sts=0 alen=2816, slen=2816, afrm=64, nfrm=64
    Jan 21 21:55:44 freebsd kernel: usbd_pipe_start: start
    Jan 21 21:55:44 freebsd kernel: usbd_transfer_submit: xfer=0xfffffe007c950278, endpoint=0xfffff800038ad968, nframes=64, dir=write
    Jan 21 21:55:44 freebsd kernel: usb_dump_endpoint: endpoint=0xfffff800038ad968 edesc=0xfffff800056d6491 isoc_next=11268 toggle_next=0 bEndpointAddress=0x01
    Jan 21 21:55:44 freebsd kernel: usb_dump_queue: endpoint=0xfffff800038ad968 xfer:
    Jan 21 21:55:44 freebsd kernel: usbd_pipe_enter: enter
    Jan 21 21:55:44 freebsd kernel: usbd_transfer_done: err=USB_ERR_NORMAL_COMPLETION
    Jan 21 21:55:44 freebsd kernel: usbd_callback_wrapper_sub: xfer=0xfffffe007c950148 endpoint=0xfffff800038ad968 sts=0 alen=2824, slen=2824, afrm=64, nfrm=64
    Jan 21 21:55:44 freebsd kernel: usbd_pipe_start: start
    Jan 21 21:55:44 freebsd kernel: usbd_transfer_submit: xfer=0xfffffe007c950148, endpoint=0xfffff800038ad968, nframes=64, dir=write
    Jan 21 21:55:44 freebsd kernel: usb_dump_endpoint: endpoint=0xfffff800038ad968 edesc=0xfffff800056d6491 isoc_next=11332 toggle_next=0 bEndpointAddress=0x01
    Jan 21 21:55:44 freebsd kernel: usb_dump_queue: endpoint=0xfffff800038ad968 xfer:
    ...
    # sysctl hw.usb.uaudio.debug=1
    # tail -f /var/log/messages
    ...
    Jan 21 21:53:43 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:43 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    Jan 21 21:53:44 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:44 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    Jan 21 21:53:45 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:45 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    Jan 21 21:53:46 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:46 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    Jan 21 21:53:47 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:47 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    Jan 21 21:53:48 freebsd kernel: uaudio_chan_play_sync_callback: Value = 0x00058330
    Jan 21 21:53:48 freebsd kernel: uaudio_chan_play_sync_callback: Comparing 44099 Hz :: 44100 Hz
    ...
    #/boot/loader.conf
    ...
    hint.pcm.5.eq=1
    mixer -f /dev/mixer5 vol=0.75 pcm=0.75 bass=0.82 treble=0.76
    vol.volume: 0.75:0.75 -> 0.75:0.75
    pcm.volume: 0.75:0.75 -> 0.75:0.75
    bass.volume: 0.82:0.82 -> 0.82:0.82
    treble.volume: 0.76:0.76 -> 0.76:0.76
    pcm5:mixer:  on uaudio0 (play)
        vol       = 0.75:0.75     pbk
        bass      = 0.82:0.82     pbk
        treble    = 0.76:0.76     pbk
        pcm       = 0.75:0.75     pbk
    # sysctl dev.pcm.5 | grep bitperfect
    dev.pcm.5.bitperfect: 0
    # sysctl hw.snd.vpc_0db=80
    hw.snd.vpc_0db: 45 -> 80
    # sysctl dev.pcm.5.eq_preamp=-5
    dev.pcm.5.eq_preamp: +0.0dB -> -5.0dB
    filter {
      plugin "ffmpeg"
      name "equalizer"
      graph "bass=f=62:t=h:w=120:g=10:n=1:r=f64, treble=f=16000:t=h:width=8000:g=2:n=1:r=f64"
    }
    
    audio_output {
      type "oss"
      name "OSS"
      mixer_type "hardware"
      replay_gain_handler "none"
      filters "equalizer"
    }
    filter {
        plugin "ffmpeg"
        name "equalizer"
        graph "anequalizer=c0 f=62 w=120 g=10 t=0|c1 f=62 w=120 g=10 t=0|c0 f=16000 w=8000 g=2 t=0|c1 f=16000 w=8000 g=2 t=0"
    }
    mixer_type "software"
    graph "anequalizer=c0 f=62 w=120 g=10 t=0|c1 f=62 w=120 g=10 t=0|c0 f=16000 w=8000 g=2 t=0|c1 f=16000 w=8000 g=2 t=0"
    peq 62Hz q0.51 10dB
    peq 16kHz q2 3dB
    如何设置 FreeBSD 并打造美化桌面 - 第 2 部分 - Xfce
    如何设置 FreeBSD 并打造美化桌面 - 第 3 部分 - i3
    OpenBSD 路由器指南
    The OpenBSD Journal
    BSD 家族树
    EuroBSDcon YouTube 播放列表

    跨架构的 kldxref

    jhb

    0299afdff145

    在 install(1) 中实现 copy_file_range(2)

    mmatuska

    5a50d52f112a

    NVMe-oF/TCP

    jhb

    a8089ea5aee5

    基于单文件的 nullfs

    dfr

    521fbb722c3(不支持套接字)

    移植 9p 文件系统

    dfr

    e97ad33a89a7

    改进 NVMe Reset / Recovery

    imp

    aa41354349c1

    移除 OpenSSL FIPS

    gtetlow

    86dd740dd73a

    arm64 SVE(可伸缩性向量扩展)支持

    andrew

    332c426328db

    AMD IOMMU 驱动

    kib

    0f5116d7efe3

    实现 SO_SPLICE

    Klara / markj

    a1da7dc1cdad

    riscv64 bhyve 支持

    br

    d3916eace506 7ab1a32cd43c

    使用 Lua 生成系统调用表的更新(makesyscalls.lua 的库化)

    brooks

    9ded074e875c

    gve(4) 的 arm64 支持、GCE 的 arm64 实例需要

    delphij, kibab (由 lwhsu 推进)

    54dfc97b0bd9

    移除 ACPI 安全定时器

    cperciva

    00d061855deb

    移除对交换内核栈的支持

    markj

    6aa98f78cc6e

    移除 armv6 支持

    imp/manu

    7818c2d37c2c

    移除 publicwkey(5)

    manu

    9dcb984251b3

    内联 IPSEC 加速

    kib

    ef2a572bf6bd

    移除 gvinum

    jhb / emaste

    f87bb5967670 e51036fbf3f8

    bhyve 虚拟机中的硬件监控功能

    jhb Bojan

    使用 DTrace 工具进行内联函数的跟踪

    markj Christos

    谷歌编程之夏——squashfs

    chuck

    改进多核笔记本电脑上的 Powerd

    cperciva

    (与 gallatin@ 讨论)

    CHERI 各式先决条件(ABI 位)

    brooks

    cade8f6c118f

    在 ZFS 中的分层速率限制

    pjd

    ZFS PR 16205

    简单的库 ABI 检查器

    brooks

    原型在 D44271

    图形化安装程序

    khorben

    D44279 D44670 D44671 D44672 D44673 D44674 D45000

    bhyve 直接使用 Linux 引导器

    robn

    (请参阅 freebsd 虚拟化)

    bsdinstall 对 pkgbase 的支持

    emaste manu?

    基本系统中的 mfsBSD

    dch, mm, soobinrho?

    D41704 D41705 D41706

    更新 blocklistd

    jlduran?

    上游更改允许更多 blocklisting,部分工作已在 PR104 中完成

    真正有效的 UnionFS (overlayfs)

    olce

    开始(在计划中)

    符合标准、实际的调度优先级

    olce

    75%

    无头 bhyve

    markj

    进行中

    amd64 的 kboot 支持

    imp

    2024 年夏末 80%

    flua 和引导加载程序的更新至 Lua 5.4.7

    imp

    将在几周后发布,看起来“无聊”。

    整合我谷歌编程之夏学生代码中的加载器命令行编辑功能

    imp

    已有变基后的分支,需要帮助。

    S0ix 低功耗空闲

    obiwac, jhb

    原生 inotify(2)

    markj

    D50315 许多 Ports 需要此功能

    将 pkgbase 集成到发布及相关流程

    re, so

    希望每个包都有单独的 Makefile

    Pre-commit CI(源代码与文档)

    lwhsu, imp, bofh

    make ci 工作中,需与其他流程集成

    Universal Flash Storage(UFS)驱动

    loos

    某些嵌入式部署需要,但未来将更通用。即将支持 Intel 平台,也对 LinuxBoot 有用

    改进 make ci 以方便提交者

    imp、bofh

    改进 make ci 以对诸如登录 github 拉取请求等事项有益

    imp

    预提交 CI ports

    lwhsu 将与 bapt 和 decke 审查

    bofh 似乎有一些 PoC

    DTrace 的 -C(大写字母)参数再次生效

    antranigv、markj

    PR 尚未提交、只需运行 dtrace -c 就可查看所含文件

    优化 bsd-user 对发布过程的支持

    imp, dfr, cperciva

    解决 32 位在 64 位上的问题,更新非常旧的 Port qemu-bsd-user-static。完成 STA 工作后,对发布工程不再相关。

    优化 bsd-user binfmt 等以适应 jail

    cperciva, imp

    Colin 希望为这些设置提供每个 jail 的配置。 完成 STA 工作后,对发布工程不再相关。

    bsd bsd-user + poudriere 支持 RISCV

    imp、mhorne、jrtc27

    软件包构建完全损坏、但基本功能正常、需要修复以便我们可以再次使用 riscv 软件包

    使用 GitHub runner 拉取请求

    imp

    针对 cirrus-ci 漏洞中的解决方案之一

    使用 GitHub Action 改善外部贡献者的体验

    imp

    这里需要帮助

    15.0 应该使用哪个版本的 OpenSSL

    gtetlow

    通过在现行环境中运行更新的版本以获取调试时间。

    PCIe 活动状态电源管理 (ASPM)

    jhb

    某些系统上正确实现 PCIe 原生热插拔所必需

    PCIe 下行端口控制 (DPC)

    jhb

    雷电(Thunderbolt)所需,取代 PCIe 原生热插拔

    virtio-fs

    ??? asomers

    imp 表示有个补丁

    精简安装程序(使单个盘上的安装有更优的默认设置、一直按回车键就能完成)

    emaste brd

    增补每个文件 file 以支持套接字/命名管道

    dfr

    更多容器支持(OCI)

    dfr

    需要志愿者。软件 Containerd 需要维护者。官方镜像/仓库

    精简内核

    imp

    进行中

    使引导加载程序支持 devmatch

    imp manu

    PCI 和 USB

    重写 config(8) (使用 lua?)

    imp kevans

    合并 devmatch 和 devd(库)

    imp

    Meena 想帮助这个

    调度程序和 VFS 的相关文档

    mhorne、olce

    在大小核心上进行调度(P、E)

    olce

    我认为其他人感兴趣

    完成内核文档(手册第 9 节)审核

    mhorne

    简化过于复杂的解决方案

    jhb imp

    vt(4) 更好的 i18n 支持(CJK 字体、unicode 字体显示(即表情符号)、输入法)

    fanchung

    在 21 年谷歌编程之夏中有一个 IME 概念验证

    以 root 运行 tarfs

    imp

    overlayfs(用于 tarfs)

    Klara / allanjude

    内核中对 Rust 的支持

    brooks

    在用户空间支持 Rust

    brooks

    为 ZFS 提供 Netlink(zfsd/zed)

    allanjude

    以 netlink 取代 devd 套接字

    bapt

    具有内核部分

    登录配置的 UCL 化

    meena

    allanjude 拥有初始补丁:D25365

    为其余网络工具添加 libxo

    meena

    如有问题请在提议的页面上 ping phil@

    分层动态登录类

    ngor、meena

    删除 MAC“label”的限制

    allanjude des

    使用 OSD?建立在 bapt 的 mac_do 使用的每个 jail 机制上

    用于 jail 的 PID 命名空间

    pjd dfr allanjude

    你想要哪些其他命名空间?

    将 dhcpcd 引入基本系统

    初始(日期)版本在这里:D22012

    通过 netlink 访问 jail vnet

    dfr

    在计算哈希值的同时能够在内存中操作文件。

    sjg (想参加)

    为 mac_veriexec

    更新 flua、添加更多标准组件、更多“常见”组件及 FreeBSD 系统调用。

    启动加载程序也使用 Lua、因此在这里需要小心些。

    priv(1)

    pjd

    降低进程权限的能力

    rctl

    DFR、PJD?

    当前 RCTL 对于资源限制 jail 的工作效果不佳

    powerpc64、powerpc64le(整个 powerpc 架构)

    https://bugs.freebsd.org/271826 FreeBSD 在 PowerMac G5 上速度极慢……

    SoC 评估审查

    imp/manu/mhorne

    ftpd

    allanjude

    移除 DES

    des?

    sendmail 📮

    bapt?

    移除引导中的 Forth 语言 🔪

    imp/stevek

    如果使用 EFI 启动安装程序但请求了 BIOS 安装,则发出警告

    NIS 服务器组件

    des?

    还在使用、请添加到 ports (chuck)

    publicwkey(5)

    manu

    D30683 D30682

    targ(4) CAM 目标驱动程序

    imp

    fingerd

    ??

    Meena 想要做此事

    3dfx(4) & *_isa

    jhb

    syscons(4)(至少不再推荐使用)

    emaste / manu

    以太网驱动程序(100mbps、冷门的 1/10 gbps)

    brooks

    CAM 驱动程序(pms(4)、hpt*、siis、mvs 等)

    imp

    freebsd-update

    cperciva

    待 pkgbase 就绪

    32 位平台(仅内核、仍保留 compat32)

    jhb

    移除 arm*soft (支持构建完整的软系统、这是在我移除了 libsoft hack 构建和 ld.so 支持之后剩下的全部内容)

    imp

    支持 SMP amd64 内核 !

    markj

    达成共识? +1 +1

    d09a64e15d8f
    47e073941f4e
    e3b4fe645e50
    ca96a942cafb
    c21bc6f3c242
    D45243
    D45243
    D47358
    D42320

    禁用进程调试

  • 随机化进程 ID

  • 禁用 syslogd 网络功能

  • 禁用 Sendmail

  • 安全控制台

  • 不可执行的栈和栈保护

  • 自动(通常是静默)修复检测到的数据不一致和写入失败,对于所有可重建的数据错误。数据可以通过以下方式重建:每个块的父块中存储的错误检测和纠正校验和;磁盘上的数据多副本(包括校验和);记录在 SLOG(ZIL)上的写入意图,用于未发生的写入(如断电);来自 RAID/RAIDZ 磁盘和卷的奇偶校验数据;来自镜像磁盘和卷的数据副本。

  • 原生支持标准 RAID 级别及 ZFS 特有 RAID 布局(RAIDZ)。RAIDZ 级别仅在必要的磁盘上条带化数据以提高效率(许多 RAID 系统会无差别地在所有设备上条带化),并且校验和可将不一致或损坏的数据重建限制在有缺陷的块上。

  • 原生支持分层存储和缓存设备,这通常是卷相关的任务。由于 ZFS 还理解文件系统,它可以利用与文件相关的知识来优化分层存储管理,而单独的设备无法做到。

  • 原生支持快照和备份/复制,通过整合卷和文件处理实现高效操作。相关工具在低级别提供,使用时需外部脚本和软件。

  • 原生支持数据压缩和去重,尽管去重主要在内存中进行且占用内存较多。

  • 高效重建 RAID 阵列——RAID 控制器通常需要重建整个磁盘,但 ZFS 可结合磁盘和文件知识,仅重建实际丢失或损坏的数据,大大加快重建速度。

  • 不受 RAID 硬件更换影响,而这会影响许多其他系统。在许多系统中,如果独立 RAID 硬件(如 RAID 卡)故障,或数据迁移到其他 RAID 系统,文件系统将缺少原 RAID 硬件上的信息,这些信息对于管理 RAID 阵列至关重要。ZFS 自行管理 RAID,因此 ZFS 池可以迁移到其他硬件,或者操作系统可以重新安装,RAIDZ 结构和数据仍会被 ZFS 识别并立即可用。

  • 能够识别本应存在于缓存但最近被丢弃的数据,从而让 ZFS 根据后续使用重新评估缓存策略,实现非常高的缓存命中率(ZFS 缓存命中率通常大于 80%)。

  • 可使用替代缓存策略处理可能导致数据处理延迟的数据。例如,可以将可能减慢存储系统的同步写入转换为异步写入,通过写入快速独立的缓存设备(称为 SLOG,有时也称为 ZIL – ZFS Intent Log)。

  • 高度可调——许多内部参数可配置以实现最佳功能。

  • 可用于高可用性集群和计算,尽管并非专门为此设计。

  • rtld-elf-cap —— 修改过的 ELF 运行时链接器,用于构建沙箱化应用

  • libcapsicum —— 创建和使用能力及沙箱化组件的库

  • libuserangel —— 沙箱化应用或组件与用户天使(如 Power Boxes)交互的库

  • chromium-capsicum —— Google Chromium 浏览器的一个版本,使用能力模式和能力机制,为高风险网页渲染提供有效沙箱保护

  • top
    ARC
    init
    命令脚本
    sysctl
    系统配置
    Debian 方式
    FreeBSD 手册
    FreeBSD
    Linux
    FreeBSD Ports 数据集
    pkgsrc(包源)
    Ports 数据集
    pkg
    Build System
    PKGBUILD
    Makefiles
    FreeBSD jail
    ZFS
    bectl
    init
    rc
    Wikipedia
    Jail
    操作系统级虚拟化
    Poul-Henning Kamp
    Bastille
    剑桥大学计算机实验室
    FreeBSD 上的 Capsicum
    Capsicum:UNIX 上的实用能力
    Capsicum 与 Casper:解决安全问题的童话
    Capsicum 技术
    DTrace
    DTrace 单行命令教程
    DTrace 示例
    bhyve
    dummynet
    sysctl
    GEOM
    MS-DOS
    Red Hat Linux
    apt-get
    我发现了 FreeBSD
    OpenBSD
    Arch Linux
    Artix Linux
    Void Linux
    Alpine Linux
    FreeBSD
    # sysctl -d security.bsd
    security.bsd: BSD security policy
    security.bsd.stack_guard_page: Specifies the number of guard pages for a stack that grows
    security.bsd.unprivileged_get_quota: Unprivileged processes may retrieve quotas for other uids and gids
    security.bsd.hardlink_check_gid: Unprivileged processes cannot create hard links to files owned by other groups
    security.bsd.hardlink_check_uid: Unprivileged processes cannot create hard links to files owned by other users
    security.bsd.unprivileged_idprio: Allow non-root users to set an idle priority
    security.bsd.unprivileged_proc_debug: Unprivileged processes may use process debugging facilities
    security.bsd.conservative_signals: Unprivileged processes prevented from sending certain signals to processes whose credentials have changed
    security.bsd.see_jail_proc: Unprivileged processes may see subjects/objects with different jail ids
    security.bsd.see_other_gids: Unprivileged processes may see subjects/objects with different real gid
    security.bsd.see_other_uids: Unprivileged processes may see subjects/objects with different real uid
    security.bsd.unprivileged_read_msgbuf: Unprivileged processes may read the kernel message buffer
    security.bsd.unprivileged_mlock: Allow non-root users to call mlock(2)
    security.bsd.suser_enabled: processes with uid 0 have privilege
    security.bsd.map_at_zero: Permit processes to map an object at virtual address 0.
    +---------+---------+-------+
    | 年份    | FreeBSD | Linux |
    +---------|---------|-------|
    | 1999    | 18      | 19    |
    | 2000    | 27      | 5     |
    | 2001    | 36      | 22    |
    | 2002    | 31      | 15    |
    | 2003    | 14      | 19    |
    | 2004    | 15      | 51    |
    | 2005    | 17      | 133   |
    | 2006    | 27      | 90    |
    | 2007    | 9       | 62    |
    | 2008    | 15      | 71    |
    | 2009    | 11      | 102   |
    | 2010    | 8       | 123   |
    | 2011    | 10      | 83    |
    | 2012    | 10      | 115   |
    | 2013    | 13      | 189   |
    | 2014    | 18      | 130   |
    | 2015    | 6       | 86    |
    | 2016    | 6       | 217   |
    | 2017    | 23      | 454   |
    | 2018    | 29      | 177   |
    | 2019    | 18      | 170   |
    | 2020    | 31      | 126   |
    | 2021    | 25      | 158   |
    | 2022    | 1       | 73    |
    |---------|---------|-------|
    | 总计    | 430     | 2780  |
    +---------+---------+-------+
    sshd_enable="YES"
    # service sshd enable
    # service sshd start
    # service sshd onestart

    谁在使用 FreeBSD(基金会官方版本)

    本页面是对 FreeBSD End User Stories 的翻译。

    参与 FreeBSD

    无论你是担任导师、推广 FreeBSD,还是参与论坛和邮件列表,你的努力都推动着 FreeBSD 项目的创新与发展。通过加入我们活力四射的社区,帮助大家构建长期发展的开源生态系统,就在现在支持下 FreeBSD 项目吧!通过 改善文档、处理 错误报告 提交代码 和 参与讨论 来增强 FreeBSD。每份贡献,无论大小,都将有助于把 FreeBSD 发展成为一款更加稳定、安全和高效的开源操作系统。

    FreeBSD 终端用户故事

    从企业到个人,从关键任务服务器到笔记本电脑。了解用户如何利用 FreeBSD 强大的功能来实现安全性、性能和可扩展性。

    受益于 FreeBSD 的组织

    E-Card:使用 FreeBSD 扩展在线游戏和博彩

    E-Card 位于保加利亚索非亚,是一家领先的在线游戏和博彩提供商。自 2000 年成立以来,E-Card 采用 FreeBSD 为其基础设施提供支持,确保其多样化的游戏和博彩服务具有强大的性能、可扩展性和可靠性。E-Card 主要运营着两个业务领域:为其他网站制作和托管消费者游戏,以及运营自己的在线赌场和博彩平台。他们的旗舰平台每天为数千名客户提供游戏和体育博彩服务。

    性能与可扩展性

    FreeBSD 的 ZFS 文件系统提供了数据完整性、压缩和高效的数据处理能力,可响应 E-Card 的大规模数据操作。在高峰时段,E-Card 的服务器可以容纳数千名在线玩家。其基础设施每秒可实现约 100,000 次查询和 20,000 次交易,确保用户流畅体验和即时响应。该公司使用聚合的 10G 网络接口和 Arista 交换机,确保高网络吞吐量和可靠性。

    “自 2000 年以降,FreeBSD 始终是我们基础设施的支柱。它的稳定性、性能和简单的管理使我们能够扩展业务,满足在线游戏行业的严格要求。”——E-Card 首席技术官 Rumen Palov

    根据保加利亚博彩行业的监管要求,像 E-Card 这样的大型服务器必须留存大量数据,最长须达 5 年,因此需要像 ZFS 这样强大高效的存储解决方案。

    E-Card 对社区的贡献

    E-Card 遇到并报告了多个错误,为满足其特定需求而为 FreeBSD 和 ZFS 定制了补丁。它是 FreeBSD 社区的活跃成员,并表示有兴趣撰写文章,分享他们的技术经验和见解。该公司的参与有助于完善 FreeBSD 生态系统,帮助其他希望采用 FreeBSD 技术的企业。

    E-Card 成功采用 FreeBSD 的案例证明了该操作系统在处理高需求的大规模在线游戏和博彩应用中的能力。FreeBSD 的稳定性、性能和社区支持使其成为在线游戏行业运营企业的理想选择。

    Antithesis:利用 FreeBSD 和 Bhyve 开创确定性虚拟机监控程序

    Antithesis 正在攻克软件工程中最棘手的问题之一:改造软件测试和调试,使其更高效、更可靠。他们的解决方案是:基于一款构建于 FreeBSD 和其原生虚拟机监控程序 Bhyve 之上的确定性虚拟机监控程序。让我们研究一下 Antithesis 所应对的具体挑战、选择 FreeBSD 和 Bhyve 的原因,以及这一开创性技术的远大前景。

    挑战

    在软件工程中,错误的可复现性是一项重大挑战。许多错误极难以捕捉,在特定条件下常常不一致地出现,难以复制。这种不一致性阻碍了调试工作,导致开发周期延长和成本增加。传统的调试工具,例如记录重放机制(如 dtrace 等),面临着存储需求、操作系统依赖和可扩展性限制——尤其是在分布式系统中。

    Antithesis 识别出需要一项强大的解决方案,以提供一致和可复现的测试环境,使开发人员能够全面探索、诊断和修复错误。这一需求促成了他们的确定性虚拟机监控程序项目的诞生。

    Antithesis 选择 FreeBSD:Antithesis 需要一款稳定、灵活、能自由使用的操作系统来开发其确定性虚拟机监控程序。由于清晰的架构设计和完善的功能集,FreeBSD 完美匹配这些需求,为 Antithesis 创新和定制其虚拟机监控程序提供了必要的支持。

    FreeBSD 宽松的许可模式对 Antithesis 有利,使其能够在不受更严格许可证限制的情况下构建专有解决方案。

    宽松许可证是一种软件许可证,授予接收者广泛的修改、使用和分发软件的权利,通常限制较少。这些许可证通常允许将软件用于专有/闭源项目,无需要求这些项目发布其源代码。宽松许可证与强制性许可证形成对比,后者对软件的分发和修改施加了更为严格的要求。

    技术优势: FreeBSD 以其干净且结构良好的代码库而闻名。这种简洁性和清晰性使其成为确定性虚拟机监控程序的理想基石,因为它需要进行大量的修改和扩展。

    成熟与简洁: Bhyve 是 FreeBSD 原生的虚拟机监控程序,相较于 Xen 和 KVM 等其他虚拟机监控程序,提供了一个成熟且相对简单的代码库。其良好分层和干净的架构为 Antithesis 所需的大量修改提供了坚实的基点。

    定制化: Antithesis 需要大幅简化和修改 Bhyve 以实现确定性。通过关注核心确定性行为并逐步构建功能,他们创建了一款可确保多个运行之间状态和行为一致的虚拟机监控程序。

    在 FreeBSD 和 Bhyve 上实现 Determinator

    Antithesis ,即“Determinator”,可提供一个受控和可复现的测试环境。Determinator 在一个由虚拟机监控程序管理的单一虚拟机内运行着多个容器。该设置确保整个系统状态一致且可复现,从而能深入探索和调试错误。Determinator 的功能包括:

    确定化的可复现性: 确保每次软件测试运行产生相同的结果,甚至包括虚拟机内部状态的精确序列。

    状态空间探索: 使全面探索不同执行路径成为可能,以识别潜在错误和问题。

    时间旅行调试: 允许开发人员在执行历史中前后移动,以准确定位错误的发生时刻和原因。

    快照能力: 其实现的一项关键特性是高级快照功能,能让整个虚拟机状态瞬间保存和恢复。这一能力对于创建可复现的测试环境和进行软件行为的详细分析至关重要。

    可扩展性: 尽管运行在单个核心上,确定性虚拟机监控程序可通过运行多个虚拟机(每个虚拟机探索程序状态的不同部分)支持普遍的并行性。

    未来方向

    Antithesis 计划继续增强其确定性虚拟机监控程序并扩展其功能。他们的计划包括:

    开源和社区参与: 尽管当前聚焦于产品开发,Antithesis 也有兴趣对部分工作开源,回馈社区促进合作。

    新的测试场景: Antithesis 将为 API 测试、用户界面测试、金融交易系统测试和计算机游戏测试增加未来场景。

    更广泛的平台支持: 扩展对更多操作系统和硬件配置的支持,使虚拟机监控程序更加多功能和广泛适用。

    与 CI/CD 管道集成: 将确定性虚拟机监控程序纳入持续集成和交付管道,以自动化测试并确保高质量发布。

    结论

    Antithesis 创新性地利用 FreeBSD 和 Bhyve 创建了一款确定性虚拟机监控程序,这是一款解决软件开发中关键问题的工具:错误的可复现性。通过确保一致和可控的测试环境,它显著提升了软件调试和测试的效率与可靠性。通过持续致力于创新和社区参与,Antithesis 在软件工程领域的贡献前景广阔。

    Cloudnium 采用 FreeBSD 提供先进的托管解决方案

    Cloudnium 由 Earl Adams 在德克萨斯州沃斯堡创立,是一家专注于高密度机柜和人工智能及云计算托管解决方案的前沿服务提供商。Cloudnium 利用 FreeBSD 的稳定性、安全性和性能,满足客户不断变化的需求。

    Earl Adams 在 IT 行业有着丰富的历史,曾拥有多家公司和数据中心。Cloudnium 是他最新的创业项目,提供定制化解决方案,满足那些像 AWS 和 Azure 等主要提供商无法轻易满足的特定和高强度计算需求的客户。Cloudnium 的服务包括机房托管、专用服务器以及为开发公司提供的后台支持。

    挑战

    Cloudnium 面临着高密度托管提供商所特有的多项挑战。确保其高密度服务器的持续稳定运行至关重要,因为任何停机时间都可能对客户的运营造成重大影响。鉴于客户工作负载的性质,保护敏感数据的强大安全协议也至关重要。此外,Cloudnium 还需要为其服务所需的高能耗提供具有竞争力的定价。可扩展性也是一个主要关注点,因为他们必须管理有效支持人工智能和云计算客户的基础设施。

    解决方案:FreeBSD

    Cloudnium 选择 FreeBSD 作为其核心操作系统,应对这些挑战。FreeBSD 因其强大的性能和可靠性而闻名;在配置完成后,仅需最少的干预即可确保平稳持续的运行。FreeBSD 的高级安全特性为保护客户数据提供了坚实的基础。FreeBSD 的高效网络堆栈和对高性能应用程序的支持,使其成为 Cloudnium 需求的理想选择。此外,FreeBSD 的灵活性使 Cloudnium 能够根据具体要求定制操作系统,进一步提高了整体性能。

    实施

    Cloudnium 已将 FreeBSD 集成到其运营的多个关键领域。他们在 FreeBSD 上运行核心服务和支持基础设施,确保稳定安全的基础。此外,Cloudnium 将在沃斯堡的互联网交换中心大量部署 FreeBSD,突显了 FreeBSD 系统的可靠性和性能。

    采用 FreeBSD 为 Cloudnium 带来了众多好处。FreeBSD 的稳定性降低了停机时间和维护需求,为客户提供了更可靠的服务。加固的安全措施保护了 Cloudnium 及其客户免受潜在威胁,确保数据的完整性和安全性。FreeBSD 提供的高效资源利用导致显著的成本节省,使其服务更具竞争力。此外,其托管环境的高性能和可靠性提升了客户满意度。

    未来计划

    Cloudnium 计划在多个方面增加对 FreeBSD 的使用。他们正在开发基于 FreeBSD 的数据中心管理系统(DCM),增强其基础设施管理能力。此外,他们希望与 FreeBSD 社区更加紧密地合作,改善整体支持和工具,进一步增强系统能力。Cloudnium 还致力于通过建立免费的实验室和技术女性教育项目来支持技术领域的多样性。

    Cloudnium 战略性地利用 FreeBSD,使其在提供高密度和专业计算需求的先进托管解决方案方面处于领先地位。FreeBSD 的稳定性、安全性和性能使 Cloudnium 能够有效满足客户需求,同时为未来的增长和创新做好了准备。

    Metify 案例研究

    通过从 Linux 切换到 FreeBSD 提升网络管理:Metify 的方法

    Metify 在网络管理和基础设施优化领域脱颖而出,成为了创新的力量。该公司利用 FreeBSD 的能力推动其突破性的软解决方案。Metify 已将 FreeBSD 确立为其技术栈的基石,从而不再严格依赖 Linux。

    这一战略选择源于 FreeBSD 在网络环境中的无与伦比的性能和稳定性,这些特性在现代网络的快节奏环境中至关重要。Metify 的旗舰网络管理软件 Mojo 和多功能网络设备 Photon 展现了该公司利用 FreeBSD 能力提供先进解决方案的决心。

    切换的过程

    Metify 的首席技术官 Ian Evans 最近解释了 FreeBSD 相较于其他操作系统的独特优势。他强调了 FreeBSD 与 ZFS 文件系统的紧密集成,确保了数据完整性和高效存储管理,简化了整体系统架构。

    此外,他还强调了 FreeBSD 内核设计的优雅,创造了一个精简和可定制的环境,能够针对性能进行微调,这与 Linux 发行版中常见的复杂性形成鲜明对比。Ian 还指出,FreeBSD 文档的完整性在软件领域中较为罕见,强调了 FreeBSD 社区的活力与热情。

    “总体来说,FreeBSD 在文档方面做得非常出色。你总能找到参考资料,社区似乎更活跃、更健全。如果我们需要联系,同某人交流,我们发现这种支持更强,深度也更明显。”——Ian Evans, Metify 首席技术官

    Metify 对 FreeBSD 的决心不仅仅是使用它。他们正在通过在 Mojo 中集成精心设计的自动化安装流程,努力实现大规模部署 FreeBSD。Metify 的目标是使 FreeBSD 的使用更易于访问和用户友好——类似于 Linux。通过简化部署和配置过程,Metify 促进了 FreeBSD 在企业网络中的更广泛采用,利用其在性能和可靠性方面的内在优势。

    回馈社区

    Metify 的路线图列出了雄心勃勃的目标,包括进一步将 FreeBSD 整合到其生态系统中。该公司计划向上游贡献,增强对容器运行时的集成。通过促进 FreeBSD 的使用,鼓励开源社区的合作,Metify 不仅推动了产品的创新,还为网络技术的更广泛的发展做出了贡献。值得注意的是,BSD 许可证为 Metify 提供了灵活性,让他们可以立即实施 FreeBSD,且在适当时机回馈社区。

    “FreeBSD 许可证在使用方面提供了更大的灵活性。我们正处于一个阶段,待我们的产品达到一定水平,我们计划进行更多的上游贡献。这种对代码使用和集成到我们的软件栈的灵活性至关重要。” -Ian Evans, Metify 首席技术官

    Metify 战略性地将 FreeBSD 作为其网络管理解决方案的基础,代表了一个重要的关注点。通过利用 FreeBSD 的高性能网络能力和固有的可靠性,Metify 准备重新定义网络管理的卓越标准,为效率、可扩展性和创新设定新的基准。

    RG Nets 案例研究

    RG Nets 如何利用 FreeBSD 构建高性能边缘网络的未来

    RG Nets, Inc. 于 2007 年由 Simon Lok 博士创立,已成为设计和部署软件定义网络网关技术的领先者。该公司专注于为各种环境提供高性能、可扩展、安全的网络解决方案,涵盖从小型企业到大规模服务提供商的广泛需求。

    RG Nets 的 rXg 交钥匙网关设备是一种强大的解决方案,能够将多种网络功能整合到一个设备中。该设备可以从统一控制台轻松管理,这对于需要在多个远程位置管理和监控网络访问的大型组织尤其有用。这些功能对运营商、酒店、大型住宅物业以及大型公共场所(LPV)如体育场、交通枢纽和拥挤城市热点区域尤其有帮助。

    RG Nets:利用 FreeBSD 应对现代网络挑战

    如今,RG Nets 利用 FreeBSD 强大的能力,为复杂的边缘网络挑战提供了创新和有效的解决方案。该公司拥有坚实的基础,开发出满足小型企业和大型服务提供商多样化需求的先进网络解决方案。

    RG Nets 使用 FreeBSD 的稳健和模块化架构,创造出满足现代网络在性能、安全性和可扩展性方面具体需求的定制解决方案。通过利用 FreeBSD 的灵活性,RG Nets 可以根据客户的规格优化网络功能,在不受商业网络解决方案限制和费用的情况下,显著提高性能。

    应用的先进领域

    软件定义网络 (SDN): RG Nets 专注于使用 FreeBSD 进行软件定义网络 (SDN),这项技术通过将控制平面与数据平面分离,从而实现高效的网络管理和操作。通过利用 FreeBSD 独特的能力作为覆盖集线器并管理基础的控制平面,RG Nets 成为理想的 SDN 前端,具备高性能和能力。RG Nets 在 FreeBSD 上的 SDN 解决方案提供无与伦比的灵活性和控制,支持自动网络管理、高效资源分配和适应性网络基础设施。

    网络安全: 在当今的网络环境中,确保网络基础设施的安全至关重要,因为网络威胁不断演变。RG Nets 利用 FreeBSD 自带的安全环境来开发综合安全解决方案。这些解决方案包括先进的防火墙技术、微分段、入侵检测系统和安全网络网关,确保数据完整性,防止数据泄露。

    高可用性和灾难恢复: FreeBSD 的稳定性和可靠性使其成为需要高可用性和强大灾难恢复能力解决方案的理想选择。RG Nets 实施基于 FreeBSD 的系统,可确保持续运行和最小停机时间,这对各行各业的关键任务应用至关重要。

    网络功能虚拟化和应用虚拟化: RG Nets 可以利用 FreeBSD 的关键特性集 bhyve 虚拟机监控器和 jail 容器,为最具挑战性的行业应用和现代运营商网络构建高度竞争的开源网络解决方案。

    成本效益创新: RG Nets 致力于降低客户网络基础设施的成本。通过使用 FreeBSD,该公司避免了专有软件相关的高许可费用,并将这些节约回馈给客户。这种方法不仅使先进的网络更易于访问,还促进了更具竞争力的市场。

    社区贡献和未来技术:推动 RG Nets 的创新

    该公司在其基于 FreeBSD 的网络边缘解决方案中处于技术集成的前沿,特别是在应用容器化和网络虚拟化方面。这种集成提高了可扩展性和效率,使 RG Nets 能够提供强大而灵活的解决方案,以满足未来数字通信需求,包括 5G 网络和物联网生态系统。

    Simon Lok 博士和 RG Nets 积极参与 FreeBSD 社区,展示了他们在推动网络技术边界方面的努力。这种参与确保了 RG Nets 在创新前沿的地位,为 FreeBSD 生态系统的发展做出了重大贡献。

    在过去,RG Nets 为 FreeBSD 集成的包过滤防火墙 pf、网络数据包调度器 altq 以及针对特定配置的英特尔网络接口卡性能提升做出了贡献。

    RG Nets 当前贡献的一个明显例子是其对 Vector Packet Processor (VPP) 移植和数据平面开发工具包 (DPDK) 向 FreeBSD 的赞助。这些项目代表了网络数据处理的重大进展:

    • Vector Packet Processor (VPP): VPP 最初由思科开发,具有高度可扩展性,能够以极高的速度进行数据包处理。 到 使操作系统能够更高效地处理大规模数据流,从而降低延迟并提高对高要求网络应用的吞吐量。

    • 数据平面开发工具包 (DPDK): DPDK 是一套库和驱动程序,旨在加速各种 CPU 架构上的数据包处理工作负载。通过对 DPDK 的移植,RG Nets 促进了 FreeBSD 上网络应用的性能提升,使数据包处理更快更可靠。

    FreeBSD 对电信和网络行业的未来影响

    RG Nets 将 VPP 和 DPDK 集成到 FreeBSD 中,在电信和网络领域取得了显著进展。这些技术使电信公司能够更高效地管理更高的数据负载,这对处理来自视频流、云计算和物联网设备的增加流量至关重要。

    随着 VPP 的集成,该公司基于 FreeBSD 的网关将显著提升性能,尤其是在边缘网络部署中,这对于处理来自移动设备的 5G 和 Wi-Fi 流量至关重要,尤其是在大型公共场所和人口稠密的城市区域等挑战性环境中。VPP 使这些网关在减少 CPU 使用的同时实现更高性能,从而减少对计算能力的需求。这种效率对于管理像体育场这样在活动期间发生数千个同时连接的地方的 5G 网络的高数据吞吐量和低延迟需求尤为重要。

    此外,RG Nets 的系统提供了更佳的性能,减少了对重大硬件投资的需求。这使得能够使用可根据用户需求增长的可扩展解决方案,而无需增加成本。这种可扩展性对于希望有效扩展基础设施的电信提供商极为重要,可同时推出新服务。在将来,它还为使用具有非常高网络吞吐量的低功耗解决方案(如基于 Arm 和 RISC-V 的解决方案与 VPP 和集成数据处理单元(DPU))提供了可能性。

    RG Nets 与 FreeBSD 社区的未来

    RG Nets 对 FreeBSD 的发展做出了重要贡献,使服务提供商能够提供新颖和创新的服务,满足消费者和企业不断变化的需求。这些服务包括增强的宽带服务、更强大的安全功能以及下一代移动服务,这对提供高质量、可靠且先进的网络服务至关重要。

    RG Nets 参与 FreeBSD 的发展,在塑造电信未来方面至关重要。它还强调了开源解决方案在促进创新和推动行业标准方面的重要性。通过不断创新和利用开源技术,RG Nets 在电信行业中保持关键地位,为采用和开发尖端网络技术做出了贡献。

    FreeBSD 案例研究:Sheridan Computers

    十年不变的服务——FreeBSD 和 Asterisk 的故事

    引言

    十年前,电信的前景截然不同。基于云的解决方案刚刚开始悄然承诺无限的可扩展性和灵活性。然而,在这些初露端倪的云朵中,我们的一位客户决定将他们的电话需求牢牢固定在地面上,采用一种本地部署的 VoIP 解决方案。这个方案是 FreeBSD 与 的和谐结合,不仅经受住了时间的考验,还蓬勃发展,为耐用性、成本效益和技术韧性提供了深刻的见解。

    设置

    在 2014 年这个辉煌的年份,我们与客户一起踏上了旅程,安装了一种本地部署的 VoIP 解决方案。以其强大和安全性著称的 FreeBSD 成为了被选中的操作系统,而 VoIP 解决方案的明星 Asterisk 则成为了中心舞台。这个动态组合旨在支持大约 30 位用户。

    这个设置的魅力何在?它是以 12 个月的维护方案出售的。但转折在于——在一年后,客户觉得没有必要续费,因为系统表现出色。

    十年的沉默

    将近十年来,这个设置就像一个安静而强大的角色,效率高、可靠且完全不引人注目。然后,突然间,一封关于硬盘故障的电子邮件警报闪现。得益于安装了多块硬盘,并采用 RAID 配置,这次小故障不过是个小插曲。系统在继续毫不间断地勤奋工作。

    在接到客户的电话后,我们迅速更换了硬盘。然而,这一事件突显了一个令人印象深刻的事实——这个十年的系统依然表现优异。

    升级

    考虑到系统正在运行的是 FreeBSD 9.3,算是“享受退休生活”,是时候进行升级了。我们将系统更新到 FreeBSD 13.3,并将 Asterisk 更新到当前版本。这一转变就像给系统喝了一口青春之泉——它焕然一新。

    财务分析

    让我们来谈谈数字。如果我们的客户选择了基于云的解决方案,设想每位用户每月支付 15 英镑,那么十年的费用……好吧,简单来说,这会让他们的会计大吃一惊。而他们在本地解决方案上的初始投资,加上通话费用(和一次硬盘更换),描绘出了一幕更可接受的财务画面。

    无声的英雄

    这个故事不仅仅关乎节省成本。它证明了 FreeBSD 和 Asterisk 的可靠性。从十年前的操作系统无缝升级到当前版本,在科技界是极为少见的。这充分体现了 FreeBSD 在前瞻性设计和兼容性方面的考虑。

    结论

    回顾过去十年,这个案例研究不仅关乎技术。这关乎在适当的时机做出正确的选择。这关乎像 FreeBSD 和 Asterisk 这样的无形英雄,它们使企业能够有效沟通,而不需占据风头。

    至于我们的客户?也许在十年后我们会再听到他们的消息,可能是为了更换另一个硬盘。但在那之前,我们可以安然入眠,因为我们提供的解决方案不仅满足了现在,也为将来做好了准备。

    在一个不断追逐下一个重大事物的世界里,有时候,真正的价值在于那些已经存在的东西——坚定、可靠且始终有效。祝愿未来的十年服务如初,干杯!

    – 作者:

    倍福案例研究

    倍福通过从 Windows CE 切换到 FreeBSD 实现更小的占用空间

    Beckhoff Automation(倍福自动化)是工业自动化领域的先锋,以其创新的解决方案和尖端技术而闻名。倍福成立于 1980 年,利用经过验证的基于 PC 的控制技术实施开放的自动化系统。他们的产品组合包括工业 PC、I/O 和现场总线组件、驱动技术、自动化软件、无控制柜自动化和机器视觉硬件。倍福不断扩展自动化的边界,推出了基于 PC 的控制系统、EtherCAT 现场总线技术和 TwinCAT 自动化软件。这些产品使全球各行业能够在其流程中实现更高的效率、灵活性和精确度。倍福对开放标准和模块化架构的投入促进了无缝集成和可扩展性,使得在制造、汽车、能源等各个领域为多种应用提供量身定制的解决方案。

    变革的需求

    在过去的 25 年里,倍福一直将 Windows 作为其工业 PC 产品的唯一操作系统。因此,Windows CE 成为了所有 Beckhoff 小型自动化设备的基础。在 2015 年,倍福的客户发现他们的 Windows 设备遭遇了勒索软件攻击。随着 Windows CE 即将结束支持,倍福开始寻找其他操作系统。

    倍福需要一款经过验证且可靠的操作系统,能够支持其产品线的全系列硬件,从 ARM 到 Intel Xeon。由于更倾向于开放标准,倍福首先打算使用 Linux 作为 Windows CE 的替代方案,但由于 GNU 通用公共许可证会给倍福的客户带来额外的法律问题,并迫使倍福共享其专有的实时 TwinCAT(该软件在内核模式下运行),因此感到受挫。因此,倍福决定寻找一款具有宽松许可证的开源操作系统,以便能够调整内核以支持 TwinCAT 实时功能,而无需贡献 TwinCAT 的源代码。

    宽松许可证是一种软件许可证,授予接收者广泛的权利,可以修改、使用和分发软件,通常限制较少。这些许可证通常允许软件在专有/闭源项目中使用,而无需要求这些项目发布其源代码。宽松许可证与“反向版权”许可证形成对比,后者对软件的分发和修改施加了更严格的要求。

    识别并构建解决方案

    倍福转向 FreeBSD,因为其在工业领域的验证和可靠声誉以及宽松的许可结构,这使得倍福能够将 TwinCAT 添加到内核中。FreeBSD 拥有一个健康活跃的开发者社区,该社区推动了超过 30 年的创新,并持续进行。此外,FreeBSD 支持着一些全球最知名的品牌,如 NetApp、Netflix、Netgate、Juniper 等。

    借助 FreeBSD 的宽松许可结构,倍福将其专有的 TwinCAT 实时功能与 FreeBSD 结合,创建了 TwinCAT/BSD,这是一款基于软件包的操作系统,成为了 Windows 的替代方案。

    TwinCAT/BSD 支持所有 TwinCAT 3 运行时功能,为倍福提供了一种低成本和小占用的解决方案,适合倍福的最小设备。倍福的高级产品经理 Heiko Wilke 指出,在使用 Windows 时,仅安装的 Windows,倍福的设备就使用了 1.5GB 的内存。而相比之下,倍福的最小设备仅有 2GB 的 RAM。

    由于 FreeBSD 可不包含不需要的进程,倍福能够将内存使用减少到约 200MB,Heiko Wilke 表示,这为其操作系统上额外的程序留出了更多空间。此外,倍福还将 TwinCAT/BSD 作为基于软件包的系统进行部署,以便于更新,允许删除更多不必要的程序。由于其基于软件包的方法,Beckhoff 的 TwinCAT/BSD 占用空间约为标准 FreeBSD 安装的二分之一。

    开始使用 FreeBSD

    倍福给所有希望实施 FreeBSD 的组织的忠告是,尽早且频繁地咨询 FreeBSD 基金会。FreeBSD 基金会不仅可以帮助解决技术和实施问题,还可以帮助建立网络,联系社区成员。如果你的组织考虑开始使用 FreeBSD,请通过他们网站的 页面向 FreeBSD 基金会发送电子邮件,或 以便今天就开始。

    TwinCAT®、TwinCAT/BSD® 和 EtherCAT® 是 Beckhoff Automation GmbH 的注册商标。

    NetApp 案例研究

    FreeBSD 为 NetApp 的 ONTAP 数据管理系统提供灵活性和性能

    NetApp 是一家智能数据基础设施公司,为企业客户提供统一数据存储、集成数据服务和云计算运营解决方案。作为技术领导者,NetApp 以其业界领先的产品帮助企业在内部部署和混合云环境中管理数据和应用程序。FreeBSD 是 NetApp 成功故事中不可或缺的一部分,也是其产品的固定组件。FreeBSD 是 NetApp 成功故事中不可或缺的一部分,也是其产品的稳定组件。

    历史的进程……

    NetApp 与伯克利软件发行版(BSD)有着悠久的历史。在 2004 年,NetApp 的领导层决定将 NetApp ONTAP(其所有产品系列的数据管理软件)基于更注重性能的系统——FreeBSD。做出这一决定的一个重要因素是 BSD 许可证模型,从 2004 年的 6.0 版本到今天的 14.0 版本,FreeBSD 始终是 NetApp 中一项稳定和最新的组成部分。

    NetApp 需要的许可证模型:能在其新的数据管理系统中整合其专有技术,而不必担心潜在的软件许可证问题。NetApp 考虑了其他 BSD 分行版本,但最终选择了 FreeBSD,因为它在性能和安全性之间取得了良好的平衡。NetApp 与 FreeBSD 的成功经验使他们在多年来不断增加其使用,最近还改变了 ONTAP 中 FreeBSD 的实现。

    由于 FreeBSD 在实施中的灵活性和行业领先的稳定性,它在 NetApp ONTAP 中一直是一个可靠的组件。在过去,NetApp 使用的是较旧版本的 FreeBSD,但现在它更接近 CURRENT 发行版本(在 FreeBSD 社区中称为“”)。

    在不同组织和多种应用中,FreeBSD 有多种实现方式。有些组织可能像 NetApp 那样选择跟踪接近 head 版本,或者像 Netflix 那样选择跟踪 head 版本,而有些组织则决定保持在几个版本之前。FreeBSD 为组织提供了稳定性、灵活性和升级的便利,使他们可以选择最适合其特定用例的实施风格,无论是滞后几个版本还是跟踪 FreeBSD 的最新发行版本。

    NetApp 与 FreeBSD 社区

    FreeBSD 项目由一组核心的 FreeBSD 提交者管理,还有许多具有直接 Git 访问权限的贡献者,能够访问 FreeBSD 的主代码库。 负责推动项目的运营。FreeBSD 核心团队由 FreeBSD 项目内的活跃开发人员选举产生。这种开放和民主的治理政策以及社区专注的政策使 NetApp 对 FreeBSD 的未来感到更为安心,从而帮助他们更自信地跟踪 FreeBSD 的最新发行版本。

    FreeBSD 充满活力和支持的开发者和用户社区也是解决问题和学习的极佳资源。实际上,NetApp 得到了另一家商业 FreeBSD 用户的个人指导,这激励他们更靠近于 FreeBSD 的最新版本。NetApp 还参加了 FreeBSD 会议和活动,如 BSDCan 和 Vendor Summit,这些活动为 NetApp 开发人员与 FreeBSD 社区交流提供了极好的机会。

    NetApp 以多种方式为 FreeBSD 做出贡献,包括定期主办 FreeBSD 基金会活动、进行常规的错误修复和增强以及向 FreeBSD 基金会提供财政支持。值得注意的是,NetApp 有一个有趣的上游策略。NetApp 与 合作,获得商业支持并通过 Klara 进行上游开发。NetApp 还拥有一个全面的持续集成测试套件,在其代码库上每日运行,包括 FreeBSD。当测试遇到 FreeBSD 问题时,NetApp 会通过 Klara 报告,并由 Klara 进行上游更改。NetApp 的工程师过去还曾向 FreeBSD 上游提交新技术,如 ,这是个 BSD 许可证的虚拟机管理程序。近年来,NetApp 为上游提交了近 300 项更改。

    开始使用 FreeBSD

    NetApp 建议其他希望寻找高性能操作系统的组织考虑 FreeBSD,原因在于其宽松的软件许可证、充满活力和支持的社区,以及对可扩展性、稳定性和安全性的强烈关注。

    在实施方面,NetApp 提供了一些建议:

    • 从小开始,并随着对 FreeBSD 的深入使用逐渐积累经验。

    • 定期升级 FreeBSD,尽量保持接近最新版本。

    • 理解 FreeBSD 哲学和愿景。

    • 选择 FreeBSD 支持的合适硬件平台。

    案例研究:在 FreeBSD 上维护全球最快的内容分发网络

    Netflix 是一家全球娱乐公司,其流媒体服务彻底改变了人们消费电视节目和电影的方式。Netflix 总部位于加利福尼亚州洛斯加托斯,已发展成为全球领先的流媒体平台之一,在 190 多个国家拥有数百万用户。Netflix 以其广泛的电影、电视剧和纪录片目录而闻名,包括备受好评的原创作品,通过投资创新内容和技术,Netflix 继续塑造着娱乐行业。

    互联网上最快、流量最高的网络,全部运行 FreeBSD

    Gleb Smirnoff 是一位熟练的软件工程师和经验丰富的 FreeBSD 提交者,他在 Netflix 工作,负责管理用于 Open Connect 的定制和性能优化的 FreeBSD 基础固件,这是该公司的内容分发网络(CDN)。

    在他 2023 年 11 月在 FreeBSD 供应商峰会上的演讲中,Smirnoff 强调了 Netflix 运营的庞大规模。

    “我们是互联网上最大的流量来源之一——每秒发送数太比特,所有服务器和设备均运行着 FreeBSD。”

    正如 Smirnoff 所指出的,Netflix 的 Open Connect 最初是在标准的 FreeBSD 平台上运行,随后逐渐进行了性能改进。2012 年,一项基于 vanilla FreeBSD 9.0-RELEASE 和 nginx 的 CDN 概念验证项目启动,该项目部署在搭载单个 10 Gbit/s 接口的服务器上。

    随着时间的推移,显而易见,要实现快速增长,需要超越操作系统当前能力的限制。Netflix 的内容分发网络(CDN)的预期规模如此之大,以至于值得在 FreeBSD 的持续开源开发上投资。

    Netflix 意识到,在全球范围内部署 CDN 时,即使是性能提升一个百分点也能节省数十万美元。Netflix 定制的 FreeBSD 版本实现了更深的集成和更精确的内核级优化,从而带来了显著的性能提升。

    在 Netflix 上跟踪 FreeBSD-CURRENT

    Netflix 在平衡自定义修改与保持与 FreeBSD 项目核心代码库一致性间进行了谨慎的管理。这确保了他们的自定义增强功能在不触发与 FreeBSD 原始源代码不再可持续性偏离的情况下,提升系统能力。这种微妙的平衡使 Netflix 能够利用 FreeBSD 的优势,同时创造出满足其特定高性能需求的定制解决方案。

    另一位 Open Connect 团队成员 Drew Gallatin 在 2023 年 11 月的 OpenFest 保加利亚会议上详细介绍了 Netflix 如何对 FreeBSD 进行定制。

    拥有超过 25 年为 FreeBSD 贡献的经验,Gallatin 分享了他在优化 FreeBSD 以服务于 Netflix 的 Open Connect 中的经历和挑战,并强调了跟踪 FreeBSD-CURRENT 背后的战略决策过程:

    “我们觉得我们以往所做的是愚蠢的,因为我们应该做的是跟踪 FreeBSD-CURRENT。这听起来疯狂,因为这是大家推送所有内容的地方,但对我们来说,这实际上是世界上最好的选择。”

    在他的演讲中,他还分享了有关“神奇的神秘合并”的轶事,说明了运行 CURRENT 分支的重要性。Gallatin 反映了 Netflix 在维护系统性能和稳定性方面的主动做法:

    “当我们运行 FreeBSD-CURRENT 时,我们能够非常快速地捕捉到问题。如果有某些回归,我们会立刻发现。在某人提交某个东西与我们发现它有问题之间,不会存在两到三年的延迟。”

    Gallatin 还进一步阐述了子树集成的好处,强调了 Netflix 与 FreeBSD-CURRENT 战略性一致性所带来的简化开发和维护流程:

    “我们的树几乎与上游 FreeBSD 树完全相同……这大大减少了我们通过保持自己的补丁而积累的技术债务。”

    FreeBSD 的战略集成与性能优化

    Netflix 精心管理内部 FreeBSD 实现与更广泛的 FreeBSD 社区之间的代码流。严格的测试框架、持续集成和单元测试构成了 Netflix 的开发策略基础。定期合并包括上游更改,并特别关注在正式纳入 FreeBSD 之前集成性能提升补丁。每次合并都会进行 A/B 测试,以保持/提升系统性能和稳定性。

    Netflix 的 FreeBSD 实现的演变涉及对内核的精细调整,以缓解性能瓶颈并处理不断增加的数据流量,这包括 RACK(Recent ACKnowledgment),这是一个由 Randall Stewart 开发的 TCP 栈,旨在改善数据传输的性能和可靠性。Netflix 对 FreeBSD 的其他显著增强包括异步 sendfile 操作,便于非阻塞数据传输,以及先进的 VM 页缓存技术,提升数据处理效率和网络吞吐量。

    Netflix CDN 团队还与 FreeBSD 社区合作,以增强使用内核 TLS(KTLS)进行数据传输的安全性和效率。

    KTLS

    KTLS 是一种将 TLS(传输层安全性)处理从用户应用程序转移到操作系统内核的技术。通过在内核中加密数据,提高了使用 sendfile(9) 的文件和网络服务器的性能,避免了将数据复制进出用户空间进行加密。KTLS 对于需要安全数据传输的高吞吐量应用(如网络服务器)非常有帮助。它实现了高效的数据处理,并使 Netflix 能够在其 CDN 服务器上实现 400 Gb/s 的吞吐量。Gallatin 解释说:

    “我们拥有世界上第一台 100 千兆每秒的生产 CDN 服务器……这要归功于内核 TLS。”

    “内核 TLS 是什么?我们将批量加密处理移到了内核中(从 nginx),以保留 sendfile 流水线。”

    “通过 sendfile 和内核 TLS,我们可以消除许多内存带宽瓶颈,现在许多事情变得更可行。通过考虑带宽和 CPU 利用率,我们在 FreeBSD 上大约可以达到 375 Gb/s,CPU 使用率约为 53%。”

    在 FreeBSD 中,内核 TLS 是一个大型项目,通过社区的合作经历了显著的发展。在 Netflix 工作期间,Scott Long 首次提出将 TLS 集成到内核中。他与 Randall Stewart 共同开发了基础的软件 TLS 传输机制。Drew Gallatin 对该项目贡献巨大,引入了外部页面 mbufs 和 M_NOTREADY mbufs,这对在内核中处理加密数据至关重要。他还开发了一个可插拔接口,以支持各种软件 TLS 后端。

    后来的 KTLS 版本对系统进行了显著增强。例如,对于 FreeBSD 13,增加了通过网络接口卡(NIC)卸载进行传输层安全性(TLS)的功能。Drew Gallatin 首次与 Chelsio 合作实现了这一功能,Chelsio 与 Netflix 共同赞助了该项目,针对 Chelsio T6 适配器。随后, 扩展了这一功能,支持 Mellanox ConnectX-6 Dx 适配器,从而支持更广泛的硬件加速。

    这一持续的发展得到了 Netflix、Chelsio 和 Mellanox 的支持,突显了增强 FreeBSD 网络安全和性能能力的强大社区驱动努力。

    回馈社区

    Netflix 在管理其 FreeBSD 实施 Open Connect 的策略反映了对更广泛 FreeBSD 社区的深切决心。Smirnoff 强调了与 FreeBSD 开发紧密跟踪的重要性:

    “减少操作系统与 FreeBSD 之间的差异至关重要,这意味着你需要将更改提交到上游。”

    他还阐述了这一策略的实际好处,解释说:

    “跟踪 FreeBSD-CURRENT…让我们能够与上游开发人员合作,并快速将更改纳入 FreeBSD。”

    这种方法最小化了技术债务,促进了最新功能和改进的快速整合,使 Netflix 始终处于流媒体技术创新的前沿。

    经验教训与最佳实践

    成功管理大型 FreeBSD 实施(如 Netflix 的案例)提供了关于社区参与和开源协作重要性的宝贵经验教训。

    • 及早与社区互动,积极参与项目对于充分发挥 FreeBSD 的潜力至关重要。这些实践确保系统的任何调整都能与更广泛生态系统中的持续发展保持良好平衡。

    • 随着时间的推移,通过优先考虑社区参与、定期测试和战略性上游贡献,精炼管理组织 FreeBSD 实施的策略可以带来显著的好处。

    • 采用新的 FreeBSD 功能并进行彻底的测试,以便在开发早期识别潜在的系统退化是至关重要的。这种主动的方法有助于厘清组织的定制分支与主要 FreeBSD 项目之间的差异,确保改进提升系统能力而不引发不可持续性的偏离。

    • 建立一个明确的流程来集成外部代码和管理内部更改是关键。为代码审查、集成和测试设定清晰的规范对于维护系统的完整性和性能至关重要。

    通过采用这些实践,组织可以有效管理其基于 FreeBSD 的系统,确保它们满足特定的操作需求,同时保持在技术进步的前沿。

    未来方向

    Netflix 致力于利用 FreeBSD 的灵活性和性能能力,并将继续与社区合作,专注于增长和创新。Netflix 在行业内树立了成功维护定制 FreeBSD 实施的先例,依靠战略远见、严格测试和积极的社区参与。

    “除了技术优势外,FreeBSD 还拥有出色的开发者、供应商和用户生态系统,他们开放地分享专业知识、人才和技术改进。Netflix 接纳了这个社区,并致力于回馈其错误修复和增强功能,从而完成了社区协作的循环。”

    ——David Fullagar

    内容交付架构总监

    用户也喜欢 FreeBSD

    我们询问了用户对 FreeBSD 的喜爱之处。我们没想到会得到如此热切的回应!

    Tara Stella

    Tara 拥有多台笔记本电脑,其中一多半运行着 FreeBSD,秉持 KISS 原则:“保持简单和安全。”

    Robin Heywood

    Robin 在两台系统上运行着 FreeBSD,作为文件服务器和网关。为什么?因为它“非常稳定”,而且是开源的!

    Daniel Arves

    Daniel 在他的笔记本电脑上运行着 FreeBSD,他把脚踩在桌子上。他想要一款可定制且简单的系统。

    我们的粉丝

    在 20 余年的时间里,FreeBSD 积累了相当多的粉丝!看看他们怎么说!

    “NetApp 自豪地将 FreeBSD 作为我们 ONTAP 存储操作系统的核心组件。借助 FreeBSD,我们能够提供高性能的产品,满足客户对可靠性、安全性和可支持性的期望。”

    Matt Hambrick

    ONTAP 工程部主任

    “Netflix 选择 FreeBSD 9,因为它是一款高性能、低维护且可靠的操作系统,得到了主流硬件厂商的支持。FreeBSD 提供了一种简单而强大的解决方案,能够通过多个 10Gbit 光纤链接同时服务数万条视频流。”

    David Fullagar

    内容交付架构总监

    “Modirum 为全球的银行、商户、支付服务提供商和卡公司提供了软件和托管服务。我们在所有托管服务中使用 FreeBSD,从路由器和防火墙到应用服务器和数据库。”

    Eirik Øverby

    首席运营官

    “Mellanox Technologies 一直是 FreeBSD 社区的长期开发者和贡献者,将 Mellanox 的前沿 RDMA 以及其他先进的卸载技术集成到了通用的 FreeBSD 操作系统中。”

    Yaron Gepstein

    软件副总裁

    “对于我们来说,继续支持 FreeBSD 是个毋庸置疑的选择。NeoSmart 每年都很自豪地赞助 FreeBSD。在被问及我们推荐的快速、经过实战考验且可靠的平台时,都毫不犹豫地推荐 FreeBSD。”

    Mahmoud Al-Qudsi

    创始人

    “FreeBSD 出色的安全性和更新、网络性能以及卓越的输入/输出和内存管理,使得运行 SimPRO 的大型、高流量和关键任务应用变得更加轻松。该操作系统承担了大部分繁重的工作,这意味着我的工程师可以专注于产品的发展,而非服务器的维护。”

    Jonathan Eastgate

    首席技术官

    “MSI/FUNTORO 利用 FreeBSD 提供高性能的按需音视频流服务,服务对象包括公交车、火车、体育场和酒店。选择 FreeBSD 是因为它的稳定性和可靠性、升级和维护的便利性、安全更新的可靠性,以及软件包的整体出色质量。”

    Scott Chen

    常务董事

    “cleverbridge 在我们的开发、测试和生产环境中使用 FreeBSD。FreeBSD 为我们提供了独特的安全特性、可靠性、行业领先的技术和卓越的性能。从我们的 Web 服务器、邮件服务器到存储服务器,FreeBSD 促进了我们的全球电子商务解决方案。”

    Paul Herman

    IT 主管 – 技术

    “如果没有 FreeBSD 社区及其成员和赞助者的贡献,Netgate 的 pfSense 项目就无法像今天这样蓬勃发展。”

    Jim Thompson

    首席技术官

    “Hobnob 选择 FreeBSD,因为它是唯一真正支撑我们使命的操作系统:为我们的客户提供快速可靠的网络服务。”

    Aron Hall

    首席执行官

    “自从切换到 FreeBSD 以来,我们很高兴看到它达到了我们的预期。FreeBSD 开发社区的努力工作使互联网变得更安全、更可靠。Verisign 自豪地参与 FreeBSD 开发社区,并拥有为 FreeBSD 回馈工作的员工。”

    Glen Wiley

    首席工程师

    “Stormshield 利用 FreeBSD 提供高性能的统一威胁管理 (UTM) 和下一代防火墙技术。我们通过技术贡献和赞助不断支持 FreeBSD;作为一家公司,我们完全致力于这个伟大社区的持续成功。”

    Fabien Thomas

    首席创新官

    “我们的许多大型客户选择了 FreeBSD,基于我们提供的高质量支持和对 FreeBSD 的投入,我们发现选择 FreeBSD 的客户往往会选择 Chelsio。Chelsio 团队很高兴能够与社区共同贡献、学习和成长。”

    Mehdi Mohtashemi

    工程副总裁

    “FreeBSD 是 NGINX 项目的主要开发平台。我们的主要开发平台是 FreeBSD。我们继续将 FreeBSD 作为 NGINX 和 NGINX Plus 开发与测试的参考平台。我们非常欣赏它的成熟性、稳定性和出色的性能。”

    Maxim Konovalov

    工程副总裁兼联合创始人

    “ScaleEngine 的小型开发和系统管理团队管理着分布在 11 个国家的 38 个数据中心中的 100 多台服务器。能够在如此小的团队中实现这种规模,仅仅依靠于 FreeBSD 提供的丰富文档、可观察性、监控和自动化工具。

    Allan Jude

    运营副总裁

    “FreeBSD 在我们的旗舰产品——远程业务加速器中扮演着重要角色。尽管 Acceleration Systems 的大多数团队成员都有 Linux 的背景,但我们选择 FreeBSD 是因为它的轻量级特点、丰富的 Port 以及在这个极其稳定的操作系统上支持的运营级应用程序。”

    Jack McKinney

    工程副总裁

    “在 Hyper-V 上成功运行 FreeBSD 的动力几乎完全基于许多主要设备(网络、存储、安全等)将 FreeBSD 作为其基础操作系统来构建产品。确保这些基于 FreeBSD 的虚拟设备在 Hyper-V 上顺利运行,并最终在 Azure 上运行,是 微软 具有战略意义的一项重要投资。”

    Jason M. Anderson

    首席项目经理

    “当 Xinuos 寻求一款成熟且稳定的操作系统,以现代功能集作为其现有客户的替代方案时,FreeBSD 显然是最明智的选择。我们的经销商尤为欣赏 BSD 许可证所提供的自由,这为创建定制解决方案堆栈提供了业内最佳的灵活性。”

    Sean Synder

    总裁兼首席运营官

    “我们需要最稳定、高效、受支持且文档完善的网络栈,可以随心所欲地进行修改。正是 FreeBSD 为 XipLink 提供了这一切。它使我们第一次实现空间通信协议标准变得更加容易,因为其内核代码的友好 BSD 许可证模型以及可用的丰富文档。”

    Karim Fodil-Lemelin

    工程副总裁

    “我们大多数本地和远程承包商在过渡到 FreeBSD 的语法和更新其开发 Jail 的程序时没有遇到任何问题,他们在一个拥有完全控制权的“真实” UNIX 环境中工作,正如我们的客户一样。这种灵活性,加上项目对稳定性、安全性和可扩展性的持续努力,使 FreeBSD 成为 Tera Bear 大多数 Web 开发项目的正确选择。”

    Jon Lybrook

    Tera Bear Consulting 创始人

    “在 WhatsApp,我们利用 FreeBSD 和 Erlang 来提供行业领先的正常运行时间。能够在普通硬件上实现线性扩展,使 WhatsApp 能够保持低廉的服务成本。如今,我们在一台 FreeBSD 服务器上运行的并发 TCP 连接数量通常在 200 到 300 万之间。”

    Jan Koum

    首席执行官,高级社交媒体经理

    “我们坚信,对 FreeBSD 有利就是对我们的客户有利,而对我们的客户有利就是对 iXsystems 有利。BSD 许可证使我们能够自由使用和贡献代码,也使我们的客户和 FreeBSD 的用户能够这样做。FreeBSD 得益于多年的开放共享与协作,从而发展成为一款稳定、成熟、高性能的操作系统。”

    Josh Paetzel

    信息技术总监

    “FreeBSD 在塑造许多当今互联网技术方面发挥了重要作用,这些技术惠及全球所有互联网用户。随着互联网的发展,FreeBSD 作为一种灵活的工具,不断适应变化的环境。在这个过程中,FreeBSD 始终是稳定性、秩序和管理互联网最宝贵资源之一——Free BSD 操作系统的典范。”

    Marty Puranik

    Atlantic.Net 创始人兼首席执行官

    “FreeBSD 发布系统为 Juniper 提供了功能的路线图和代码的稳定基础,同时其实用的许可协议使 Juniper 能够开发知识产权,以推动高性能网络的发展。Juniper 拥有许多活跃的 FreeBSD 开发人员,他们不断为 FreeBSD 项目做出贡献,以进一步推动其作为领先操作系统的发展。”

    Naren Prabhu

    基础技术部副总裁

    “Pair Networks 一直以来依赖 FreeBSD 作为提供世界级网络托管服务的重要工具。FreeBSD 的可靠性和稳定性使我们能够为客户提供超过 99.9% 的服务器正常运行时间。我们的客户依赖 FreeBSD 的 proven security 来确保他们的网站正常运行和数据安全。作为一款开源系统,FreeBSD 在出现安全威胁时易于更新新保护措施。FreeBSD 的稳定性和健壮性使我们能够轻松兑现这一承诺。”

    Kevin Martin

    首席执行官

    “NYI 是一家数据中心提供商,使用 FreeBSD 作为其所有内部和面向客户的解决方案,包括托管和专用服务器、云计算以及托管服务。我们最初选择的技术包括与专有硬件相绑定的商业 Unix 系统。然而,FreeBSD 的成本和可移植性是我们在公司初期更换平台的重要因素。”

    Phillip Koblence

    运营副总裁

    “使用 Experts Exchange 对我们的网站、几种不同版本的 Linux 和 UNIX(包括 FreeBSD)进行了大量的性能测试。FreeBSD 在页面加载时间指标和 Lucene 搜索索引性能测试中超越了所有其他测试的操作系统。自那时起,我们已将我们的开发、测试和生产服务器迁移到 FreeBSD。我们还使用 FreeBSD Jail 来托管我们的开发测试服务器,并且我们已经在本地办公室数据中心和我们的托管数据中心架构中依赖 FreeBSD。”

    Andrew Alsup

    网站总监

    “我们的立场提供了关于 FreeBSD 在纽约大都会地区使用的多角度视野,从首次探索 FreeBSD 的终端用户到依赖 FreeBSD 的企业基础设施。虽然 NYC*BUG 树立了标志并保持了稳定的 *BSD 存在,我们受益于对 FreeBSD 作为稳定、理智的操作系统日益增长的兴趣和依赖。”

    NYC*BUG(New York City BSD User Group,纽约 BSD 用户组)管理小组

    image
    image
    image
    image
    ~4WTCG370H5}1%QEL 750 U
    考虑与提供 FreeBSD 商业支持的公司(如 Klara)签约。
  • 将专有定制限制在关键业务知识产权上,其余的尽量向上游开放。

  • 开发了一款确定性虚拟机监控程序
    将 VPP 移植
    FreeBSD
    Asterisk
    Sheridan Computers
    联系我们
    下载 FreeBSD
    跟踪 head
    FreeBSD 核心团队
    Klara Systems
    bhvye
    Hans Petter Selasky
    image

    不为人知的 pkg(8) 功能

    • 原文:Less Known pkg(8) Features

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2019/01

    我多次被要求撰写一篇关于 pkg(8) 的文章——这是 FreeBSD 现代软件包管理器,有时也称为 PKGng。

    在本篇文章中,我将尝试介绍一些不太为人所知的 pkg(8) 功能。

    大约在 8 年前——当时 pkg(8) 还未问世——我写过一篇帖子:。后来该文章甚至刊载于 BSD Magazine 2012/01 期(Issue 30)。

    回到 2011 年,软件包更新比现在稍微复杂一些。那时,你不得不使用 FreeBSD 的 STABLE 分支,因为 RELEASE 分支的软件包几乎不更新——类似于当前 OpenBSD 的情况。FreeBSD STABLE 分支上的软件包每两周构建一次,当时已经足够使用。

    当然,你也可以使用 portmaster 从 FreeBSD Ports 编译所有软件包,但这会浪费大量时间。当时 pkg_add/pkg_delete/pkg_info 是 FreeBSD 上的主要软件包工具,而 bsdadminscripts 包中的 pkg_upgrade 脚本在升级过程中非常有用。它会从 STABLE 分支的 FTP 服务器获取最新的软件包并更新已安装的软件包。要检查软件包的安全问题,则需要另一款第三方工具 portaudit。

    现在,我们有了功能完善的 pkg(8),能使用 pkg upgrade 来更新安装的软件包。得益于 pkg audit,已不再需要第三方工具 portaudit 了。我们甚至还有 pkg autoremove 来自动移除不再需要的依赖。

    我会尽量不重复已经非常优秀的 中 章节中已有的信息。

    较旧的 FreeBSD 版本

    在 FreeBSD 10 之前,如果要使用新的 pkg(8) 工具,非旧的 pkg_* 工具,则需要在 /etc/make.conf 文件中加入 WITH_PKGNG=yes。

    目前受支持的 FreeBSD RELEASE 版本只有最近发布的 12.0 以及更加稳定和完善的 11.2,因此无需在 /etc/make.conf 文件中加入某些内容来使用 pkg(8) 框架。

    数据库

    pkg(8) 数据库(实际上是 SQLite 数据库)保存在目录 /var/db/pkg。

    下面是 pkg(8) 引导过程之后目录 /var/db/pkg。

    最重要的文件是 /var/db/pkg/local.sqlite,因为它是已安装包及其文件的数据库。在输入 pkg shell 后,你实际上可以通过 SQLite 解释器连接到这个 SQLite 数据库。

    若由于某种原因你发现 pkg(8) 工具无法工作或已经损坏,你可以使用 sqlite3 包中的 sqlite3 命令连接到它。不要使用软件包 sqlite,因为它是 SQLite 的 2.x 版本,而这与 pkg(8) 使用的 3.x 版本不向前兼容。

    锁定/解锁

    使用 pkg(8),现在可以用 pkg lock 命令锁定指定的包。这意味着 pkg upgrade、pkg delete(甚至 pkg autoremove)操作都不会影响它们。你可以使用选项 -l 列出已锁定的包,如下所示。

    如你所见,无法 pkg delete 已锁定的包 exfat-utils。你必须先用 pkg unlock 命令将其解锁。你可以交互式地进行,也可以使用选项 -y 非交互式完成,如下所示。

    为什么要锁定某些软件包?

    根据我的经验,以下是需要锁定特定软件包的潜在原因:

    • 你将 Ports 和软件包结合使用。

    • 某个 Port 并不存在对应的软件包。

    • 官方软件包的默认编译选项与你自己的不同。

    • 你确实想使用旧版本的软件包。

    实际上,我使用 lock/unlock 机制,是因为上述所有情况对我都成立。

    我会同时使用 Ports 和软件包(在 FreeBSD 世界中这通常不被推荐),因为我使用的一些软件由于授权问题无法提供为软件包。例如所有和 Microsoft exFAT 文件系统相关的东西(exfat-utils/fusefs-exfat)以及 MP3(lame)。更令我惊讶的是,OpenBSD 多年来一直提供 lame 软件包,而 FreeBSD 团队仍然害怕专利问题。

    我还需要构建自定义版本的 ffmpeg 软件包——只是为了加入 lame 支持,但仍然是自定义的。最后一个我保持锁定的是 Conky。它在 1.9 版本时很好用,但开发者在 1.10 版本(现在甚至已有 1.11)把它彻底搞坏了。比如,你无法在桌面上右键点击得到 Openbox 菜单——换句话说,Conky 不再把鼠标事件传递给负责桌面的 Window Manager。

    于是我使用了 Ports 的另一个工具 portdowngrade,把 1.9 版本的文件提取到 Ports,然后编译出 1.9 的 conky 软件包并永久锁定。

    你可能已经知道,我更喜欢使用 dzen2 来显示界面信息,但我仍然会在需要时用 conky 做“FreeBSD Dashboard”,然后按下 [Scroll Lock] 键临时启用它。

    提供项

    如果你同时也是 RHEL/Fedora(或一般 yum/rpm)的用户,你可能会在 FreeBSD 的 pkg(8) 包管理器中怀念“provides”这个功能。为什么它如此有用?因为有了“provides”数据库,你可以直接通过指定软件包中某个二进制或文件的确切名称来安装软件包。例如你可以输入 yum install /sbin/ifconfig 来安装 net-tools 包,因为“provides”数据库中含有该信息。

    如果我告诉你使用 pkg(8) 也能实现类似的功能呢?

    插件能让你直接使用 pkg(8) 查询哪个软件包提供了某个特定的文件。

    它甚至已经作为软件包 pkg-provides 提供。下面我将展示如何安装配置。首先安装软件包 pkg-provides。

    然后配置文件 /usr/local/etc/pkg.conf。

    现在你就有了新命令 pkg provides,如下所示。

    你可以使用选项 -u 来更新 ‘provides’ 数据库。

    pkg provides 插件示例用法

    虽然例如无法通过输入 pkg install /compat/linux/usr/bin/pldd 命令来安装包 linux_base-c7,但可以检查哪个包包含该文件。

    下次你执行命令 pkg upgrade 时,也会看到 provides 数据库的刷新。

    pkg provides 数据库在目录 /var/db/pkg 中会占用相当量的空间。

    如果你使用像 LZ4 这样的 ZFS 压缩,那么它占用的空间就不会太大,如下所示。

    ……但是如果你使用 UFS,那么这个将近 600 MB 的数据库可能会让你有点吃惊 :🙂:

    Which

    虽然 pkg provides 可以提供尚未安装的软件包中文件的相关信息,pkg which 命令则是经典 UNIX which 命令在 pkg(8) 中的对应。它显示某个文件属于哪个软件包(或者根本不属于任何软件包)。

    双管齐下,乐趣加倍

    有时同时使用两个 which 命令会更快地得到所需的答案。

    periodic 定期任务

    有时你可能会看到如下情况。

    …但是你并没有启动任何其他 pkg(8) 实例,这到底是怎么回事呢?我们来看一下 ps(1) 的输出。

    FreeBSD 的 periodic 脚本正在执行它们的工作。

    要查看具体是哪些脚本,可以查看这里。

    如果你认为这些活动中某些是不必要的,可以在 /etc/periodic.conf 文件中使用这些值将它们禁用。

    例如,如果你想禁用 /usr/local/etc/periodic/daily/490.status-pkg-changes 的执行,你需要在 /etc/periodic.conf 文件中添加 daily_status_pkgng_changes_enable=no。

    接下来再检查一次 ps(1) 输出。

    periodic 任务已经完成。你现在可以像平常一样安装你的包了。

    统计信息

    虽然 pkg stats 命令可以提供已安装包的一些统计信息,但它对于查找哪个包占用空间最多并不是很有用。

    还有 pkg size 命令,它只会显示包占用的空间,但不会显示包名……没多大用处。

    此外,pkg size 的手册页并不存在。

    你可以使用 pkg info -as 命令,但它不仅不会对输出进行任何排序,还会以 KiB/MiB/GiB 等不同单位显示空间使用情况,这并不方便……幸运的是,sort 命令的选项 -h 能帮上忙。

    使用以下别名可以按空间使用量对包进行排序。我将输出限制为最大 20 个包,但你可以根据需要修改。

    缩写

    pkg(8) 工具同样支持缩写参数。例如,你不必输入完整的 pkg autoremove,只需输入 pkg autor 即可执行该命令。

    下面是简短名称示例。

    元数据

    许多 pkg(8) 的问题都是由旧的元数据数据库引起的。如果你遇到任何 pkg(8) 问题,首先应如下面所示强制刷新其数据库。

    为了记录——在这个过程中,“provides” 数据库也会被刷新。

    修复损坏的依赖

    曾经有段时间,缺失的软件包 www/libxul19 依赖问题折磨了我一阵子。

    我甚至绝望地准备用 portmaster 重新编译所有东西。

    我从命令 portmaster --check-depends 开始,但在系统询问是否修复时选择了“n”,因为这会不必要地降级大量软件包。

    让我们看看 pkg(8) 显示我们已经安装了哪些软件包。

    问题在于我们安装了 www/libxul 而不是 www/libxul19,这就是为什么 portmaster(不仅仅是它)会报错的原因。

    在 pkg(8) 被引入之前,只需使用 grep -r 搜索整个 /var/db/pkg 目录及其“文件数据库”就很容易,但现在情况复杂得多,因为软件包数据库保存在 SQLite 数据库中。使用 pkg shell 命令,你可以连接到该数据库。让我们看看能找到什么。

    所以现在我们知道,“deps” 表可能就是我们要找的 ;)。

    由于 pkg shell 在浏览 SQLite 时功能相当有限,我将直接使用命令 sqlite3。所谓有限是指,你不能直接输入 pkg shell "select * from deps;" 这样的查询,而是需要先启动 pkg shell,然后才能输入查询语句。

    第二列是 name,所以我们可以尝试使用它。

    现在我们已经找到了“有问题”的依赖条目,可以稍微修改它,使其与实际已安装的包状态一致。

    当然,你也可以使用“官方”方法,通过 pkg shell 命令来操作。

    现在 portmaster 感到满意,不会再命令依赖缺失了。

    太棒了!问题解决了 :😉:

    ……但 pkg(8) 已经自带一个工具可以做到这一点 :🙂:

    它叫 pkg set,在 man pkg-set 中最有用的两个选项是。

    在我们的例子中,我们会使用 pkg set -o www/libxul19:www/libxul 命令。

    不确定它是否能以同样方式解决问题,因为我在数据库中也更新了版本。

    更新(UPDATING)

    如果在执行 pkg upgrade 命令时遇到任何问题,那么你也应该查看最新版本的 /usr/ports/UPDATING 文件——例如可以在使用 portsnap fetch update 命令更新 Ports 后获取。

    该文件描述了 Ports 中的重要变更(以及由于包是由 Ports 构建而来的,因此也涵盖了包的变更)。

    pkg(8) 框架也提供了相应工具,即 pkg updating 命令。具体细节可查看 man pkg-updating 页面。最常见的用法是使用参数 -d 并指定日期,如下所示。

    你也可以在 在线查看 UPDATING 文件。

    使用 ZFS 启动环境进行稳健升级

    为了绝对确保无论 pkg upgrade 命令出现何种问题,你的系统都能正常工作,可以使用 ZFS 启动环境。我不久前曾在 和 介绍过其功能。仍可在链接 下载最新的 PDF 演示文稿。

    使用 beadm 命令的操作流程如下。

    现在,即使出现任何问题,你依然拥有名为 safepoint 的完整可用系统启动环境。

    只需重启并选择该环境(在 FreeBSD loader 中选择),你就能恢复到正常工作的系统,就像使用时间机器回到过去一样。

    查询

    你也可以使用命令 pkg query 来查找所需的信息。

    例如,要“模拟” pkg info -r pkg-name 参数(显示依赖 pkg-name 的软件包列表),可以使用如下方式的 pkg query 命令。

    如果你想知道每个包的初次安装时间,可以使用下面这个方法。

    你也可以显示那些不会被命令 pkg autoremove 移除的包,因为它们是你直接安装的。

    罗塞塔石碑

    页面也提供了一些表格,但信息不完整。

    因此我复制了表格并补充了缺失的数据。

    下面是旧 pkg_* 工具与当前 pkg(8) 框架的对照表(更新版):

    如果你知道其他有用的 pkg(8) 命令,也可以告诉我 🙂

    pkg_info -W /path/to/my/file

    pkg which /path/to/my/file

    安装本地包

    pkg_add ./localpkg.tbz

    pkg add ./localpkg.txz

    安装远程包

    pkg_add -r mypackage

    pkg install mypackage pkg install category/name pkg install pkgname-pkgversion

    搜索远程包

    ls /usr/ports/*

    grep mypackage

    搜索远程包的详细信息

    make search name=mypackage make search key=mypackage

    pkg search -f mypackage pkg search -f category/name pkg search -f pkgname-pkgversion

    已安装包的反向依赖

    pkg_info -R pkgname-pkgversion

    pkg info -r mypackage pkg info -r category/name pkg info -r pkgname-pkgversion

    已安装包的依赖

    pkg_info -r pkgname-pkgversion

    pkg info -d mypackage pkg info -d category/name pkg info -d pkgname-pkgversion

    删除作为依赖安装的未使用包

    N/A

    pkg autoremove

    二进制升级已安装包

    pkg_upgrade (FreeBSD Ports)

    pkg upgrade

    创建远程仓库

    N/A

    pkg repo /directory/with/packages

    操作 jail 中的包

    N/A

    pkg -j

    操作 chroot 中的包

    pkg_add -C

    pkg -c

    使用正则表达式获取已安装包信息

    pkg_info -x

    pkg info -x

    使用扩展正则表达式获取已安装包信息

    pkg_info -X

    pkg info -X

    使用通配符获取已安装包信息

    pkg_info

    pkg info -g

    检查已知漏洞

    portaudit (FreeBSD Ports)

    pkg audit

    过期包

    pkg_version -l <

    pkg version -l <

    过期包(安装信息详细)

    pkg_version -Il <

    pkg version -Il <

    与远程仓库对比的过期包

    N/A

    pkg upgrade -n

    已安装包统计信息

    N/A

    pkg stat

    检查缺失依赖(并修复)

    N/A

    pkg check -d

    包来源

    pkg_info -o

    pkg info -o

    功能

    旧 pkg_* 工具

    新 pkg(8) 工具

    列出已安装的包

    pkg_info

    pkg info

    获取包的基本信息

    pkg_info pkgname-pkgversion

    pkg info pkgname pkg info category/name pkg info pkgname-pkgversion

    获取包的详细信息

    N/A

    pkg info -f pkgname pkg info -f category/name pkg info -f pkgname-pkgversion

    列出已安装包中的所有文件

    pkg_info -L pkgname-pkgversion

    pkg info -l pkgname pkg info -l category/name pkg info -l pkgname-pkgversion

    HOWTO: Keeping FreeBSD’s Base System and Packages Up-to-Date
    FreeBSD Handbook
    4.4. 使用 pkg 管理二进制软件包
    pkg-provides
    https://www.freshports.org/UPDATING
    波兰 PBUG
    荷兰 NLUUG
    https://is.gd/BECTL
    FreeBSD Wiki
    bsd-magazine-2012-01
    vermaden_2019-01-16_21-32-07.png

    查找哪个包提供某个文件

    服务之力:FreeBSD 电源管理

    • 原文:The Power to Serve – FreeBSD Power Management

    • 2018/11

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    这是 FreeBSD 操作系统的格言 —— “The Power to Serve(服务之力)” —— 也非常契合本文的主题。十年前(是的,光阴荏苒)我甚至还制作了一张带有这个格言的壁纸 —— 仍可在 DeviatArt 页面上获取。

    是时候写一篇关于 FreeBSD 电源管理特性的文章了。它也适用于 FreeBSD 桌面 系列,但不限于此。流行的观点似乎是 FreeBSD 如此偏向服务器,以至于没有任何电源管理机制。事实完全不是这样。虽然在桌面上不那么重要(但仍能减少你的电费)或服务器上不那么关键,但在笔记本电脑上正确配置电源管理是非常必要的,这样它们会拥有更长的电池寿命,并运行得更安静。

    我写这篇文章,是因为 FreeBSD 手册 在 章节中并未涉及全部这些信息。FreeBSD on Laptops 文章的 部分来自 FreeBSD 10.1-RELEASE 的远古时代。FreeBSD Wiki 页面上也有一些信息,但部分已过时。

    FreeBSD 在电源管理领域有许多机制:

    • 关闭没有附加驱动的设备

    • 调整 CPU 频率和功耗

    • 支持 CPU 睡眠状态(C1 / C1E / C2 / C3 / …)

    • 启用/禁用大多数 CPU 可用的睿频

    关于 FreeBSD 系统中不同设置文件的一句话说明:

    • /etc/rc.conf —— 无需重启,只需重新加载守护进程

    • /etc/sysctl.conf —— 无需重启 —— 可在运行时设置

    • /boot/loader.conf —— 这些设置 需要重启

    信息

    让我们先从如何获取所需信息开始,例如当前 CPU 速度、已使用的 C 状态、USB 设备当前的电源管理模式、电池容量和剩余时间等。

    电池

    要获取电池信息,你可以使用工具 acpiconf(8)。以下是 acpiconf(8) 在我的主电池(ThinkPad T420s 笔记本)接通电源源时的输出。

    ……在接入电源适配器后:

    现在,当从笔记本电脑上拔掉电源时,Remaining time: 字段会显示该单块电池的剩余时间估计,这里显示为 2:31(两小时三十一分钟)。

    下面是我的第二块电池的 acpiconf(8) 输出(位于 ThinkPad T420s 的 ultrabay,替代了 DVD 驱动器)。

    ……在接入电源适配器后:

    在拔掉电源的情况下,它会将第二块电池的 Remaining time: 显示为 1:36。

    因此,总电池续航时间估计为 4:07。同样的时间,以分钟表示(247),会显示在名为 sysctl(8) 值 hw.acpi.battery.time 中,如下所示。

    你还可以通过 sysctl(8) hw.acpi.battery,获取更“完整”的电池信息。

    如果连接了电源,hw.acpi.battery.time 将显示为 -1。

    电池损耗

    随着时间的推移,电池会失去其“设计”容量。经过一到两年,这类电池的实际效率可能只剩下原来的 70% 或更低。

    检查这些信息所需的全部数据,都可以通过 acpiconf(8) 命令中的 Design capacity: 和 Last full capacity: 获取。我写了个 battery-capacity.sh 脚本,可以告诉你当前电池的效率。下面是该脚本运行时的效果示例。

    下面是 battery-capacity.sh 脚本。

    CPU

    要获取当前 CPU 的信息,你需要使用 dev.cpu,或者使用 dev.cpu.0 来获取第一个物理 CPU 核心的信息。

    如果你使用 kldload(8) 命令加载内核模块 coretemp(4),就能获得额外的温度信息。

    下面是加载内核模块 coretemp(4) 后,相同的 sysctl(8) dev.cpu.0 输出。

    让我说下最有用的值。

    CPU 核心温度。

    dev.cpu.0.temperature: 49.0C

    CPU 支持的 C 状态(此 CPU 支持 C1 和 C2)。

    dev.cpu.0.cx_supported: C1/1/1 C2/3/104

    CPU C -states 使用统计(仅使用了 C1 状态)。

    dev.cpu.0.cx_usage_counters: 16549 0 dev.cpu.0.cx_usage: 100.00% 0.00% last 1489us

    CPU 启用的最最深的 C 状态。

    dev.cpu.0.cx_lowest: C1

    CPU 支持的频率级别及其功耗(‘/’后面的数字表示功耗)。例如 2500/35000 可理解为 2.5 GHz 频率,功耗 35 W,而 2501 表示 Turbo 模式。最低频率为 800 MHz,功耗约 9 W。

    dev.cpu.0.freq_levels: 2501/35000 2500/35000 2200/29755 2000/26426 1800/23233 1600/20164 1400/17226 1200/14408 1000/11713 800/9140

    CPU 当前频率(使用守护进程 powerd(8) 或 powerdxx(8) 时会变化)。

    dev.cpu.0.freq: 800

    hw.acpi.thermal.tz0.temperature 也会显示当前热区温度。

    要检查你有多少颗 CPU 核心,可以使用以下命令。

    如果我的说明不够直观,你还能用 sysctl(8) 命令的参数 -d,如下所示。

    lscpu(1)

    还有个第三方工具 lscpu(8),可以显示你的 CPU 特性和型号。你需要从软件包中安装它。

    要使 lscpu(8) 正常工作,需要加载内核模块 cpuctl(4)。

    下面是我的双核 CPU 使用 lscpu(8) 的显示效果。

    dmesg(8)

    此外,dmesg(8) 命令(或长时间运行后查看 /var/run/dmesg.boot 文件)也可以显示你的 CPU 型号和特性信息。

    CPU 调频

    对于 CPU 调频功能,你可以使用 FreeBSD 基本系统提供的守护进程 powerd(8) ,或者使用来自 FreeBSD Ports 或软件包的 powerdxx(8)。守护进程 powerdxx(8) 旨在更好地调频多核系统,在系统负载适中时不会将所有核心都调到高状态,但有些人可能更喜欢那种方法,以便在执行所有操作时都拥有全部性能,而在闲置时节省功耗。因此,powerd(8) 并不比 powerdxx(8) 更好,反之亦然。它们只是不同的实现,为你的需求提供了更多选择。

    无论选择何者,都必须在文件 /etc/rc.conf 中进行配置。

    powerd(8)

    以下是守护进程 powerd(8) 的选项。

    -n 选项用于未知状态——当 powerd(8) 无法确定当前是使用电源还是电池供电时使用。-a 用于电源,-b 用于电池供电。adaptive 设置较“温和”,更有利于延长电池续航时间。hiadaptive 设置更激进,适合在电源供电时使用。-m 选项设置最低 CPU 频率,-M 设置最大 CPU 频率,单位均为 MHz。更多细节请参见 powerd(8) 手册页。

    powerdxx(8)

    首先,你需要安装它。

    然后,它的选项与守护进程 powerd(8) 的选项完全相同。

    请查看上文 powerdxx(8) 部分获取标志/参数说明。

    十年前,FreeBSD 上的 CPU 调频不像现在这么“简单”,你可以看看我 2008 年的老文章 。

    C 状态

    可以在 /etc/rc.conf 文件中用以下选项配置 C 状态。

    • performance_cx_lowest

    • economy_cx_lowest

    economy_cx_lowest 参数用于电池供电时,performance_cx_lowest 参数用于电源供电时。两者都通过 rc(8) 子系统使用的 /etc/rc.d/power_profile 脚本进行设置。该脚本会设置 hw.acpi.cpu.cx_lowest 参数,从而控制所有 dev.cpu.*.cx_lowest 的值。当你连接或断开电源时,也可以在 /var/log/messages 文件中跟踪这些变化。

    通常我只是使用这些值。

    上述设置对于大多数系统来说通常已经足够。要检查你的 CPU 支持哪些 C 状态,请看看 dev.cpu.0.cx_supported 的值。

    我的 CPU 仅支持 C1 和 C2,但你的 CPU 可能支持更多。我记得曾经使用一台老旧的 Core 2 Duo 笔记本时,从 C1(运行)状态返回到 C2(休眠)状态会有相当“明显”的延迟,因此需要如下设置。此时不使用参数 performance_cx_lowest 和 economy_cx_lowest。你可以将第一个核心设置为 C1,其他所有核心设置为 C2。这样即使在电池供电时,你的系统也能完全响应,而其他核心则可以休眠以节省能源。

    例如,如果你有 4 个核心,并且最深支持的 C 状态为 C3,那么你可以将如下内容添加到 /etc/sysctl.conf 文件中。

    CPU 睿频

    启用睿频模式有两种方式。一种是通过设置守护进程 powerd(8) 或 powerdxx(8),将最大频率设置高于 CPU 标称速度。例如,如果你的 CPU 描述为双核 2.3 GHz,则可以使用参数 -M 将最大速度设置为 4000(即 4 GHz)。如果你不使用 CPU 调频守护进程,则可以使用参数 dev.cpu.0.freq,将其设置为 dev.cpu.0.freq_levels 中的最高(第一个)值。

    下面是我系统上支持的 CPU 频率级别。

    最高值(左侧)为 2501/35000,因此我需要将 dev.cpu.0.freq 参数设置为该值以启用睿频模式。你只需要使用“频率”部分的值,因为如果连同功耗描述一起设置,会导致失败。

    如下所示为正确的使用方法。

    USB 设备

    要列出已连接的 USB 设备,请使用工具 usbconfig(8) 。

    你会看到 pwr 参数(即 power,电源的缩写)显示当前电源设置,可以为:

    • ON

    • OFF

    • SAVE

    要为 ugen1.1 设备设置新的 USB 电源选项,也可以使用 usbconfig(8) 工具,并使用参数 power_save,方法如下。

    FreeBSD 的 USB 电源管理没有专用的配置文件,因此我们将设置放入通用的 /etc/rc.local 文件中,该文件在 rc(8) 子系统管理的启动过程结束时运行。下面是添加的内容,唯一的例外是我的无线鼠标“Lenovo USB Receiver 联想 USB 接收器”。

    对于鼠标和触控设备,不保存电源是个好主意,因为每次使用时都需要等待约一秒钟,这会很烦人。我使用一个 for 循环为除无线 USB 鼠标(识别为“Lenovo USB Receiver”设备)之外的所有 USB 设备设置节能模式。

    SATA/AHCI 电源管理

    FreeBSD 通过 acpich(4) 驱动提供 AHCI 通道电源管理。这些电源管理设置可以在启动时通过 /boot/loader.conf 文件中的 hint.ahcich.*.pm_level 参数进行配置。我为多达 8 个通道进行了配置,尽管我实际上只有三个通道。

    这是因为对不存在的设备进行设置是无害的,不会显示任何错误信息,而且你也不必为不同系统使用不同设置,从而节省时间。下面是 ahci(4) 手册页中关于 hint.ahcich.*.pm_level 的说明。

    可能的电源管理选项如下:

    • 0 – 禁用接口电源管理(默认)

    • 1 – 允许设备主动发起 PM 状态改变,主机被动

    • 2 – 每次端口空闲时,主机发起 PARTIAL PM 状态转换

    • 3 – 每次端口空闲时,主机发起 SLUMBER PM 状态转换

    下面是我在 /boot/loader.conf 文件中的设置。

    无驱动的设备

    FreeBSD 提供了对未附加驱动的设备不供电的节能选项。该选项称为 hw.pci.do_power_nodriver,可以在 /boot/loader.conf 文件中设置。下面是 pci(4) 手册页中的说明。

    它可以设置为以下值之一:

    • 0 – 所有设备保持完全供电(默认)。

    • 1 – 类似于‘2’,但存储控制器仍保持供电。

    • 2 – 关闭大多数设备电源(显示器/内存/外设不关闭)。

    • 3 – 关闭所有没有驱动程序的 PCI 设备电源。

    下面是我在 /boot/loader.conf 文件中的设置。

    pciconf(8) 工具可以显示系统中的设备以及附加到它们的驱动程序。如果设备没有附加驱动,你会看到 *none@**,例如下面的 none0@。你还可以查看大多数驱动的手册页,例如 em(4) 查看 em0 设备,或 xhci(4) 查看 xhci0 设备。

    你也可以使用参数 -v 获取更详细的信息。

    Nvidia Optimus

    如果由于某种原因你的 BIOS/UEFI 固件无法禁用 Nvidia 独显,你可以使用此脚本将其禁用,从而避免消耗系统电源。该操作需要内核模块 acpi_call(4),该模块由软件包 acpi_call 提供。

    你可以在 /etc/rc.local 文件中,将其添加到 USB 节能选项之后,使用如下条目。

    它会将有效的 ACPI 调用存储在 /root/.gpu_method 文件中,并在每次启动时执行。

    挂起与恢复

    挂起/恢复机制的最大敌人是硬件 BIOS/UEFI 固件中的错误。例如,有时禁用蓝牙会有所帮助——这是 ThinkPad T420s 中的一个方案。要检查系统支持哪些挂起模式,请查看 sysctl(8) 中的 hw.acpi.supported_sleep_state。

    要进入 ACPI S3 睡眠状态(挂起),你可以使用 acpiconf(8) 工具或 zzz(8) 工具。

    ……或者使用 acpiconf(8) 工具。

    这与手册页 zzz(8) 中的说明完全相同。

    你还可以设置 sysctl(8) 值,使每次关闭笔记本盖时系统进入睡眠状态。为此,将 hw.acpi.lid_switch_state=S3 添加到 /etc/sysctl.conf 文件中。无论是通过命令还是关闭盖子让硬件进入睡眠状态,打开盖子后笔记本都会恢复。当然,如果在执行 zzz(8) 命令后没有关闭盖子,你需要关闭并重新打开盖子,或按下电源按钮以恢复。当然,你也可以对桌面或甚至备份服务器执行挂起/恢复操作,这并不仅限于笔记本。

    此外,不同厂商的 ACPI 子系统还有专用内核模块,如下:

    • /boot/kernel/acpi_asus_wmi.ko

    • /boot/kernel/acpi_asus.ko

    • /boot/kernel/acpi_dock.ko

    • /boot/kernel/acpi_fujitsu.ko

    例如,如果你使用的是 IBM/联想 ThinkPad,则需使用内核模块 acpi_ibm.ko。

    加载所需模块后,你会得到新的 sysctl(8) 值供使用,例如与风扇速度、键盘背光或屏幕亮度相关的值。下面是在加载 acpi_ibm(4) 内核模块后,sysctl(8) 中新增的 dev.acpi_ibm 部分。

    这里是一些更有趣的项的说明。

    控制麦克风静音按钮上的 LED 灯。

    dev.acpi_ibm.0.mic_led

    选择是否管理 CPU 风扇(0)或使用厂商默认设置(1)。

    dev.acpi_ibm.0.fan

    如果启用 CPU 风扇,设置其转速。

    dev.acpi_ibm.0.fan_level

    显示 CPU 风扇转速(单位 RPM)。

    dev.acpi_ibm.0.fan_speed

    启用/禁用 WiFi(前提是在 BIOS 中启用)。

    dev.acpi_ibm.0.wlan

    启用/禁用蓝牙(前提是在 BIOS 中启用)。

    dev.acpi_ibm.0.bluetooth

    启用/禁用 ThinkLight。

    dev.acpi_ibm.0.thinklight

    静音/取消静音扬声器。

    dev.acpi_ibm.0.mute

    扬声器音量。

    dev.acpi_ibm.0.volume

    屏幕亮度。

    dev.acpi_ibm.0.lcd_brightness

    在大多数情况下,你可能无需直接使用这些参数,因为通常会使用厂商定义的键盘快捷键(可能需要 Fn 键)或厂商特定的专用按键。但有时你可能希望创建或使用自己的设置,或者需要自定义快捷键,或者想根据 CPU 温度以不同于厂商预设的方式控制风扇转速。这时,这些专用的 ACPI 内核模块就非常有用。

    例如,我最近觉得我的 CPU 风扇声音似乎有些大,所以创建了基于 cron(8) 的自定义 acpi-thinkpad-fan.sh 脚本,在 CPU 温度足够低时使用较低或更安静的风扇转速。简单来说,它的工作逻辑是:CPU 温度低于 50°C 时关闭风扇,温度在 50°C 到 60°C 之间时设置为级别‘1’,温度超过 60°C 时设置为级别‘3’。

    ……下面是它在 crontab(5) 中的条目:

    网卡

    如果驱动支持节能功能,ifconfig(8) 也要相应选项,称为 powersave,用法如下:

    我在自己的 network.sh 网络管理脚本中使用了它,脚本在文章 中有详细介绍。

    厂商工具

    FreeBSD 上也有一些厂商提供的工具,例如 powermon(8)。请注意,它需要内核模块 cpuctl(4) 才能工作。

    DTrace

    动态追踪框架(像 ZFS 一样由 Solaris/Illumos 引入 FreeBSD)在延长电池使用时间方面也可能是款有用的工具。

    首先安装软件包 dtrace-toolkit:

    系统停止节能或唤醒 CPU,通常是因为有任务需要执行。你大多数情况下会使用 ps(1) 或 top(1) 来查看运行情况,但这些工具无法显示具体启动了哪些命令或命令的执行频率。这时 DTrace 就派上用场了。

    我们将使用软件包 dtrace-toolkit 中的 /usr/share/dtrace/toolkit/execsnoop 脚本。它会打印系统中执行的每一个命令及其所有参数。当没有命令执行时,它将保持静默,请注意。

    下面是我在更新 dzen2 工具栏时的示例输出。

    屏幕顶部的信息更新会启动许多进程。这就是为什么我只每 5 分钟刷新一次 dzen2 信息,如果我想获得当前时刻的精确信息和系统状态,我只需点击 dzen2 工具栏,它就会执行所有这些命令并刷新自己。

    通过这种方式使用 DTrace,你可以知道是否有不必要的进程消耗了宝贵的电池时间。你可以在我的文章 中找到相关 dzen2 配置。

    其他

    ZFS

    默认情况下,ZFS 每 5 秒提交一次事务组,这对于 vfs.zfs.txg.timeout 参数是一个良好的默认设置。如果需要,你可以稍微增加该值,例如设为 10。我之所以提到这个参数,是因为很多指南出于性能原因建议将其设置为 1,但请记住,将其设置为 1 会阻止你的磁盘(和 CPU)进入休眠,从而消耗更多电池寿命。

    如果你想调整 vfs.zfs.txg.timeout 值,可以在 /boot/loader.conf 文件中设置。

    应用程序

    延长电池使用时间时,所使用的应用程序也至关重要。例如,Thunar 比 Caja 或 Nautilus 占用更少的 CPU 时间。Geany 文本编辑器比 Scite 或 Gedit 占用更少的 CPU 资源和内存,即便是 GVim 也会占用更多资源。更不用说基于自定义 Openbox/Fluxbox/${YOUR_FAVORITE_WM} 的窗口管理器设置,其 CPU 占用远低于整个 Gnome 或 Mate 环境。

    硬件

    有时可以通过硬件本身获得更多电池时间。例如,当你为笔记本购买新的固态硬盘时,可以选择速度不是最快但最节能的型号。你可能感受不到性能差异,但会明显获得更长的电池使用时间。

    大多数内存模块的电压为 1.5V,但你的笔记本可能支持 LPDDR 模块(1.35V),从而延长电池续航。此外,每根内存条大约消耗 0.5–1.0W 功率,因此使用单根 8 GB 内存条比使用两根 4 GB 内存条能拥有更多电池时间。当然这也有性能上的缺点,因为单条内存无法使用双通道技术,会限制内存速度。一些笔记本甚至有四条内存槽(例如 ThinkPad W520),因此为了更长的电池寿命,可以选择使用两根 8 GB 内存条而不是四根 4 GB 内存条,而不会损失性能。

    有时你可以将 DVD 光驱替换为内部辅助电池。例如 Dell Latitude D630、ThinkPad T420s 或 ThinkPad T500/W500。有些厂商提供整块贴合笔记本底部的扩展电池,例如 ThinkPad X220、T420/T520/W520 或第一代 ThinkPad X1 笔记本的扩展电池。

    希望这些信息能帮助你在 FreeBSD 上延长一些电池使用时间(或至少节省一些电量) :🙂:

    更新 1 – 显卡节能

    如果你安装了 graphics/drm-kmod 包,你可能使用的是最新的内核模块 i915kms.ko 。

    要为 Intel 核显设置最大化电源管理,请将以下内容添加到 /boot/loader.conf 文件中:

    过去使用的旧设置如下,但现在已不再使用:

    更新 2 – AMD CPU 温度

    对于 Intel CPU 使用 coretemp(4) 内核模块,而 amdtemp(4) 内核模块可提供 AMD CPU 的额外温度信息。

    更新 3 – Suspend/Resume 提示

    Suspend/resume 子系统最大的敌人是 BIOS/UEFI 固件中的 BUG。有时禁用 Bluetooth 有助于解决问题——例如 Lenovo ThinkPad T420s 的做法。在 Lenovo ThinkPad X240 上,需要禁用 TPM(Trusted Platform Module)。

    更新 4 – Intel Speed Shift

    我在较老的 2011 年 ThinkPad W520 上运行 FreeBSD,因此这个选项对我来说仍然是个谜——但对于运行更新系统的用户可能会有帮助。

    随着 Intel Skylake(第六代)CPU 的引入,FreeBSD 能够利用 Intel Speed Shift 技术。你可以在 手册页中了解更多信息。要启用该功能,请在 /boot/loader.conf 文件中添加以下行:

    然后在 /etc/sysctl.conf 文件中,你需要为每个 CPU 线程(而非核心)都添加一行,使用你期望的设置:

    这里的 N 代表线程编号。对于双核四线程 CPU,你将有 4 行这样的设置;对于八核 CPU,你将有 8 行。

    Y 的取值含义如下:

    • 0 – 最大性能

    • 50 – 平衡(默认)

    • 100 – 最大节能

    若希望获得最大化节能,可以为所有线程使用 100,如下所示:

    当然,你也可以为单个线程使用全性能,将一个线程设置为平衡,其余线程节能,如下所示:

    … 当你接入电源而非使用电池时,你可能希望全部线程都使用无限制性能,将所有值设为 0。

    以下是具体设置示例。

    理想情况下,当使用电源时,你会使用 performance(性能)设置,而在使用电池时则运行 power save(节能)模式。你可以通过下面这个简单脚本实现,并让它在 cron(8) 守护进程中运行。

    … 下面是 crontab(5) 的条目。我这里假设你已经具备所需的 doas(1) 权限。如果你使用 sudo(8),请相应修改脚本。

    遗憾的是,我目前没有搭载 Intel Speed Shift CPU 的笔记本,所以不确定为前两个线程分别设置 0 和 50 是否最佳。也许将所有线程都设为 100 以节省更多电力会更好。当我将来拥有这样的笔记本时,会再做更新 🙂

    # find /var/db/pkg
    /var/db/pkg
    /var/db/pkg/FreeBSD.meta
    /var/db/pkg/vuln.xml
    /var/db/pkg/local.sqlite
    /var/db/pkg/repo-FreeBSD.sqlite
    # pkg shell
    -- Loading resources from /home/vermaden/.sqliterc
    SQLite version 3.15.2 2016-11-28 19:13:37
    Enter ".help" for usage hints.
    > .q
    #
    # file /var/db/pkg/*
    /var/db/pkg/FreeBSD.meta:        ASCII text
    /var/db/pkg/local.sqlite:        SQLite 3.x database, user version 34, last written using SQLite version 3015002
    /var/db/pkg/repo-FreeBSD.sqlite: SQLite 3.x database, user version 2014, last written using SQLite version 3015002
    /var/db/pkg/vuln.xml:            XML 1.0 document, UTF-8 Unicode text, with very long lines
    
    # sqlite3 /var/db/pkg/local.sqlite
    -- Loading resources from /home/vermaden/.sqliterc
    SQLite version 3.26.0 2018-12-01 12:34:55
    Enter ".help" for usage hints.
    > .q
    #
    # pkg lock -l
    Currently locked packages:
    conky-1.9.0_6
    exfat-utils-1.2.8
    ffmpeg-4.1_1,1
    fusefs-exfat-1.2.8
    lame-3.100_2
    
    # pkg delete exfat-utils
    Checking integrity... done (0 conflicting)
    The following package(s) are locked and may not be removed:
    
            exfat-utils
    
    1 packages requested for removal: 1 locked, 0 missing
    # 
    # pkg unlock exfat-utils
    exfat-utils-1.2.8: unlock this package? [y/N]: y
    Unlocking exfat-utils-1.2.8
    
    # pkg lock -y exfat-utils
    Locking exfat-utils-1.2.8
    # pkg search provides
    pkg-provides-0.5.0             Pkg plugin for querying which package provides a particular file
    
    # pkg install pkg-provides
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            pkg-provides: 0.5.0 [FreeBSD]
    
    Number of packages to be installed: 1
    
    10 KiB to be downloaded.
    
    Proceed with this action? [y/N]: y
    [1/1] Fetching pkg-provides-0.5.0.txz: 100%   10 KiB   9.8kB/s    00:01    
    Checking integrity... done (0 conflicting)
    [1/1] Installing pkg-provides-0.5.0...
    [1/1] Extracting pkg-provides-0.5.0: 100%
    Message from pkg-provides-0.5.0:
    
    ======================= pkg plugin activation ========================
      In order to use the pkg-provides plugin you need to enable plugins in pkg.
      To do this, uncomment the following lines in /usr/local/etc/pkg.conf file
      and add pkg-provides to the supported plugin list
    
      PKG_PLUGINS_DIR = "/usr/local/lib/pkg/";
      PKG_ENABLE_PLUGINS = true;
      PLUGINS [ provides ];
    
      After that run `pkg plugins' to see the plugins handled by pkg`.
    
      To update the provides database run `pkg provides -u`
    
      ====================================================================
    # cat << __EOF__ >> /usr/local/etc/pkg.conf
    PKG_PLUGINS_DIR = "/usr/local/lib/pkg/";
    PKG_ENABLE_PLUGINS = true;
    PLUGINS [ provides ];
    __EOF__
    # pkg provides
    usage: pkg provides [-uf] pattern
    
    A plugin for querying which package provides a particular file
    
    # pkg provides bin/pldd
    Provides database not found, please update first.
    # pkg provides -u
    Fetching provides database: 100%   29 MiB 700.9kB/s    00:43    
    Extracting database....success
    # pkg provides bin/pldd
    Name    : ptools2-0.5
    Desc    : Toolset based on Solaris ptools functionality
    Repo    : FreeBSD
    Filename: /usr/local/bin/pldd
    
    Name    : linux_base-c7-7.4.1708_6
    Desc    : Base set of packages needed in Linux mode (Linux CentOS 7.4.1708)
    Repo    : FreeBSD
    Filename: /compat/linux/usr/bin/pldd
    
    # pkg install /compat/linux/usr/bin/pldd
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    pkg: No packages available to install matching '/compat/linux/usr/bin/pldd' have been found in the repositories
    # pkg upgrade
    Updating FreeBSD repository catalogue...
    Fetching meta.txz: 100%    944 B   0.9kB/s    00:01    
    Fetching packagesite.txz: 100%    6 MiB 376.5kB/s    00:18    
    Processing entries: 100%
    Fetching provides database: 100%   29 MiB 386.3kB/s    01:18    
    Extracting database....success
    FreeBSD repository update completed. 32542 packages processed.
    All repositories are up to date.
    Checking integrity... done (0 conflicting)
    (...)
    # file /var/db/pkg/* /var/db/pkg/*/* | sort -n
    /var/db/pkg/FreeBSD.meta: ASCII text
    /var/db/pkg/local.sqlite: SQLite 3.x database, user version 34, last written using SQLite version 3015002
    /var/db/pkg/provides: directory
    /var/db/pkg/provides/provides.db: ASCII text
    /var/db/pkg/repo-FreeBSD.sqlite: SQLite 3.x database, user version 2014, last written using SQLite version 3015002
    /var/db/pkg/vuln.xml: XML 1.0 document, UTF-8 Unicode text, with very long lines
    # du -csm /var/db/pkg/*
    1       /var/db/pkg/FreeBSD.meta
    32      /var/db/pkg/local.sqlite
    72      /var/db/pkg/provides
    33      /var/db/pkg/repo-FreeBSD.sqlite
    2       /var/db/pkg/vuln.xml
    138     total
    # du -csmA /var/db/pkg/*
    1       /var/db/pkg/FreeBSD.meta
    68      /var/db/pkg/local.sqlite
    571     /var/db/pkg/provides
    52      /var/db/pkg/repo-FreeBSD.sqlite
    6       /var/db/pkg/vuln.xml
    694     total
    # pkg which /boot/modules/drm.ko
    /boot/modules/drm.ko was installed by package drm-fbsd11.2-kmod-4.11g20181210
    
    # pkg which /boot/kernel/drm.ko
    /boot/kernel/drm.ko was not found in the database
    # which firefox
    /usr/local/bin/firefox
    
    # pkg which `which firefox`
    /usr/local/bin/firefox was installed by package firefox-64.0.2,1
    # pkg install parallel
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    pkg: Cannot get an advisory lock on a database, it is locked by another process
    # ps ax | grep pkg
     8540  -  S        0:00.00 /bin/sh - /usr/local/etc/periodic/daily/411.pkg-backup
     8551  -  S        0:00.00 /usr/local/sbin/pkg shell .dump
     8555  -  D        0:01.08 /usr/local/sbin/pkg shell .dump
    # find /etc/periodic /usr/local/etc/periodic -name \*pkg\*
    /usr/local/etc/periodic/daily/490.status-pkg-changes
    /usr/local/etc/periodic/daily/411.pkg-backup
    /usr/local/etc/periodic/security/460.pkg-checksum
    /usr/local/etc/periodic/security/410.pkg-audit
    /usr/local/etc/periodic/weekly/400.status-pkg
    # find /etc/periodic /usr/local/etc/periodic -name \*pkg\* | xargs grep -m 1 -E -o "[a-z_]+_enable" 
    /usr/local/etc/periodic/daily/490.status-pkg-changes:daily_status_pkgng_changes_enable
    /usr/local/etc/periodic/daily/411.pkg-backup:daily_backup_pkgng_enable
    /usr/local/etc/periodic/security/460.pkg-checksum:security_status_pkgchecksum_enable
    /usr/local/etc/periodic/security/410.pkg-audit:security_status_pkgaudit_enable
    /usr/local/etc/periodic/weekly/400.status-pkg:weekly_status_pkgng_enable
    # ps ax | grep pkg
     8574  0  S+       0:00.00 grep --color pkg
    # pkg install parallel
    Updating FreeBSD repository catalogue...
    FreeBSD repository is up to date.
    All repositories are up to date.
    The following 1 package(s) will be affected (of 0 checked):
    
    New packages to be INSTALLED:
            parallel: 20171222
    
    Number of packages to be installed: 1
    
    The process will require 3 MiB more space.
    1 MiB to be downloaded.
    
    Proceed with this action? [y/N]: n
    #
    # pkg stats
    Local package database:
            Installed packages: 1081
            Disk space occupied: 9 GiB
    
    Remote package database(s):
            Number of repositories: 1
            Packages available: 32518
            Unique packages: 32518
            Total size of packages: 78 GiB
    # pkg size | head
    10.5MiB
    2.06MiB
    27.4MiB
    2.59MiB
    5.17MiB
    515KiB
    23.2MiB
    609KiB
    587KiB
    127KiB
    # man pkg-size
    No manual entry for pkg-size
    # alias pkg-size='pkg info -as | sort -k 2 -h | tail -20 | column -t'
    # which pkg-size
    pkg-size: aliased to pkg info -as | sort -k 2 -h | tail -20 | column -t
    # pkg-size
    python27-2.7.15          68.2MiB
    gtk3-3.22.30_4           68.8MiB
    opencollada-1.6.68_1     75.8MiB
    py27-ansible-2.7.5       88.6MiB
    argyllcms-1.9.2_4        92.4MiB
    webkit2-gtk3-2.22.5      92.9MiB
    gimp-app-2.10.8_1,1      95.4MiB
    python36-3.6.8           104MiB
    samba47-4.7.12           145MiB
    openjdk8-8.192.26_3      162MiB
    boost-libs-1.69.0        163MiB
    thunderbird-60.4.0_1     167MiB
    firefox-64.0.2,1         174MiB
    binutils-2.30_7,1        195MiB
    linux_base-c6-6.10       197MiB
    gcc6-6.5.0_3             241MiB
    chromium-71.0.3578.98_2  251MiB
    libreoffice-6.0.7_4      353MiB
    virtualbox-ose-5.2.22_2  375MiB
    llvm60-6.0.1_5           818MiB
    # pkg autor
    # pkg upg
    # pkg inf
    # pkg update -f
    Updating FreeBSD repository catalogue...
    Fetching meta.txz: 100%    944 B   0.9kB/s    00:01    
    Fetching packagesite.txz: 100%    6 MiB 352.9kB/s    00:19    
    Processing entries: 100%
    Fetching provides database: 100%   28 MiB 658.3kB/s    00:44    
    Extracting database....success
    FreeBSD repository update completed. 31778 packages processed.
    All repositories are up to date.
    # portmaster --check-depends
    (...)
    Checking dependencies: evince
    graphics/evince has a missing dependency: www/libxul19
    (...)
    
    >>> Missing package dependencies were detected.
    >>> Found 1 issue(s) in total with your package database.
    
    The following packages will be installed:
    
            Downgrading perl: 5.14.2_3 -> 5.14.2_2
            Downgrading glib: 2.34.3 -> 2.28.8_5
            Downgrading gio-fam-backend: 2.34.3 -> 2.28.8_1
            Downgrading libffi: 3.0.12 -> 3.0.11
            Downgrading gobject-introspection: 1.34.2 -> 0.10.8_3
            Downgrading atk: 2.6.0 -> 2.0.1
            Downgrading gdk-pixbuf2: 2.26.5 -> 2.23.5_3
            Downgrading pango: 1.30.1 -> 1.28.4_1
            Downgrading gtk-update-icon-cache: 2.24.17 -> 2.24.6_1
            Downgrading dbus: 1.6.8 -> 1.4.14_4
            Downgrading gtk: 2.24.17 -> 2.24.6_2
            Downgrading dbus-glib: 0.100.1 -> 0.94
            Installing libxul: 1.9.2.28_1
    
    The installation will require 66 MB more space
    
    38 MB to be downloaded
    
    >>> Try to fix the missing dependencies [y/N]: n
    >>> Summary of actions performed:
    
    www/libxul19 dependency failed to be fixed
    
    >>> There are still missing dependencies.
    >>> You are advised to try fixing them manually.
    
    >>> Also make sure to check 'pkg updating' for known issues.
    # pkg info | grep libxul
    libxul-10.0.12                 Mozilla runtime package that can be used to bootstrap XUL+XPCOM apps
    
    # pkg info -qoa | grep libxul
    www/libxul
    # pkg shell
    SQLite version 3.7.13 2012-06-11 02:05:22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> .databases
    seq  name             file
    ---  ---------------  ----------------------------------------------------------
    0    main             /var/db/pkg/local.sqlite
    sqlite> .tables
    categories       licenses         pkg_directories  scripts
    deps             mtree            pkg_groups       shlibs
    directories      options          pkg_licenses     users
    files            packages         pkg_shlibs
    groups           pkg_categories   pkg_users
    sqlite> .header on
    sqlite> .mode column
    sqlite> pragma table_info(deps);
    cid         name        type        notnull     dflt_value  pk
    ----------  ----------  ----------  ----------  ----------  ----------
    0           origin      TEXT        1                       1
    1           name        TEXT        1                       0
    2           version     TEXT        1                       0
    3           package_id  INTEGER     0                       1
    sqlite> .quit
    # sqlite3 -column /var/db/pkg/local.sqlite "select * from deps;" | grep libxul
    www/libxul19   libxul      1.9.2.28_1  104
    sqlite3 -header -column /var/db/pkg/local.sqlite "select * from deps where name='libxul';"
    origin        name        version     package_id
    ------------  ----------  ----------  ----------
    www/libxul19  libxul      1.9.2.28_1  104
    # sqlite3 /var/db/pkg/local.sqlite "update deps set origin='www/libxul' where name='libxul';"
    # sqlite3 /var/db/pkg/local.sqlite "update deps set version='10.0.12' where name='libxul';"
    # pkg shell
    SQLite version 3.7.13 2012-06-11 02:05:22
    Enter ".help" for instructions
    Enter SQL statements terminated with a ";"
    sqlite> update deps set origin='www/libxul' where name='libxul';
    sqlite> update deps set version='10.0.12' where name='libxul';
    sqlite> .header on
    sqlite> .mode column
    sqlite> select * from deps where name='libxul';
    origin      name        version     package_id
    ----------  ----------  ----------  ----------
    www/libxul  libxul      10.0.12     104
    sqlite> .quit
    # portmaster --check-depends
    (...)
    Checking dependencies: zenity
    Checking dependencies: zip
    Checking dependencies: zsh
    #
      -n oldname:newname, --change-name oldname:newname
           Change the package name of a given dependency from oldname to newname.
           将指定依赖项的包名从 `oldname` 修改为 `newname`。
    
    (...)
    
      -o oldorigin:neworigin, --change-origin oldorigin:neworigin
           Change the port origin of a given dependency from oldorigin to neworigin.
           This corresponds to the port directory that the package originated from.
           Typically, this is only needed for upgrading a library or package that
           has MOVED or when the default version of a major port dependency changes.
           (DEPRECATED) Usually this will be explained in /usr/ports/UPDATING.
           Also see pkg-updating(8) and EXAMPLES.
           将指定依赖项的 Port 来源从 oldorigin 修改为 neworigin。
           这对应于该包最初来源的 Port 目录。通常,仅在升级已被 MOVED 的库或包,或者主要 Port 依赖的默认版本发生变化时才需要使用此功能。(已弃用)通常相关说明会在 /usr/ports/UPDATING 中给出。
           另请参见 pkg-updating(8) 和示例。
    # less /usr/ports/UPDATING
    
    (...)
    20180518:
      AFFECTS: users of sysutils/ansible*
      AUTHOR: [email protected]
    
      Ansible ports are now flavored. Package names for Ansible changed
      to include python version. Poudriere and package users don't need
      to do anything.
    
      To rename an installed package to match the new naming scheme,
      for example, for ansible24, run:
    
       # pkg set -n ansible24:py27-ansible24
    
    (...)
    
    20180214:
      AFFECTS: users of lang/ruby23
      AUTHOR: [email protected]
    
      The default ruby version has been updated from 2.3 to 2.4.
    
      If you compile your own ports you may keep 2.3 as the default version by
      adding the following lines to your /etc/make.conf file:
    
      #
      # Keep ruby 2.3 as default version
      #
      DEFAULT_VERSIONS+=ruby=2.3
    
      If you wish to update to the new default version, you need to first stop any
      software that uses ruby. Then, you will need to follow these steps, depending
      upon how you manage your system.
    
      If you use pkgng, simply upgrade:
      # pkg upgrade
    
      If you use portmaster, install new ruby, then rebuild all ports that depend
      on ruby:
      # portmaster -o lang/ruby24 lang/ruby23
      # portmaster -R -r ruby-2.4
    
      If you use portupgrade, install new ruby, then rebuild all ports that depend
      on ruby:
    
      # pkg delete -f ruby portupgrade
      # make -C /usr/ports/ports-mgmt/portupgrade install clean
      # pkg set -o lang/ruby23:lang/ruby24
      # portupgrade -x ruby-2.4.\* -fr lang/ruby24
    
    (...)
    # pkg updating -d 20190101
    20190103:
      AFFECTS: users of multimedia/vlc*
      AUTHOR: [email protected]
    
      The multimedia/vlc port has been upgraded to 3.0.5, the latest upstream
      release. Subsequently, multimedia/vlc-qt4 and multimedia/vlc3 have been
      retired and removed from the ports tree. Users who previously used
      multimedia/vlc3 might want to switch to multimedia/vlc with the following
      commands:
    
      # pkg install multimedia/vlc
        or
      # portmaster -o multimedia/vlc multimedia/vlc3
        or
      # portupgrade -o multimedia/vlc multimedia/vlc3
    # beadm create safepoint
    Created successfully
    
    # beadm list
    BE           Active Mountpoint  Space Created
    11.2-RELEASE NR     /            5.7G 2018-12-01 13:09
    safepoint    -      -          316.0K 2019-01-16 23:03
    
    # pkg upgrade
    # pkg info -r sqlite3
    sqlite3-3.26.0:
            colord-gtk-0.1.26
            py27-sqlite3-2.7.15_7
            freeciv-2.5.10
            colord-1.3.5
            libsoup-2.62.3
            libsoup-gnome-2.62.3
            subversion-1.11.0_1
            nss-3.41_1
            webkit-gtk2-2.4.11_19
            filezilla-3.36.0_1
            epiphany-3.28.5_1
            darktable-2.4.4_3
            aria2-1.34.0_1
            webkit2-gtk3-2.22.5
            qt5-webkit-5.212.0.a2_17
            qt5-sqldrivers-sqlite3-5.12.0
            hugin-2018.0.0_6
            pidgin-2.13.0
            thunderbird-60.4.0_1
            midori-0.7.0
            firefox-64.0.2,1
    
    # pkg query -e '%n = sqlite3' %ro
    graphics/colord-gtk
    databases/py-sqlite3
    games/freeciv
    graphics/colord
    devel/libsoup
    devel/libsoup-gnome
    devel/subversion
    security/nss
    www/webkit-gtk2
    ftp/filezilla
    www/epiphany
    graphics/darktable
    www/aria2
    www/webkit2-gtk3
    www/qt5-webkit
    databases/qt5-sqldrivers-sqlite3
    graphics/hugin
    net-im/pidgin
    mail/thunderbird
    www/midori
    www/firefox
    # pkg query "%t %n-%v" \
        | sort -n \
        | while read timestamp pkgname
          do
            echo "$(date -r $timestamp) $pkgname"
          done | ( head; echo; tail )
    Fri Jul  7 14:17:29 CEST 2017 libpciaccess-0.13.5
    Fri Jul  7 14:17:35 CEST 2017 libedit-3.1.20170329_2,1
    Fri Jul  7 14:18:09 CEST 2017 font-util-1.3.1
    Fri Jul  7 14:18:10 CEST 2017 xcb-util-0.4.0_2,1
    Fri Jul  7 15:26:56 CEST 2017 xcb-util-renderutil-0.3.9_1
    Fri Jul  7 15:26:57 CEST 2017 dejavu-2.37
    Fri Jul  7 15:27:00 CEST 2017 font-misc-meltho-1.0.3_3
    Fri Jul  7 15:27:02 CEST 2017 font-misc-ethiopic-1.0.3_3
    Fri Jul  7 15:27:06 CEST 2017 font-bh-ttf-1.0.3_3
    Fri Jul  7 15:27:08 CEST 2017 tpm-emulator-0.7.4_2
    
    Sun Jan 13 20:48:01 CET 2019 firefox-64.0.2,1
    Sun Jan 13 20:48:01 CET 2019 htop-2.2.0_1
    Wed Jan 16 23:08:21 CET 2019 vlc-3.0.6,4
    Wed Jan 16 23:08:21 CET 2019 xdg-utils-1.1.3
    Wed Jan 16 23:08:25 CET 2019 phonon-qt4-4.10.2
    Wed Jan 16 23:08:25 CET 2019 physfs-3.0.1
    Wed Jan 16 23:08:25 CET 2019 py27-pyasn1-0.4.5
    Wed Jan 16 23:08:26 CET 2019 chromium-71.0.3578.98_2
    Wed Jan 16 23:08:26 CET 2019 moreutils-0.63
    Wed Jan 16 23:08:26 CET 2019 p5-URI-1.76
    # pkg query -e "%a != 1" "%n" | tail
    xmp
    xorg
    xprintidle
    xterm
    xxkb
    youtube_dl
    zenity
    zfs-stats
    zip
    zsh
    每个 USB 设备的电源管理方案
  • SATA / AHCI 通道/控制器电源管理

  • 挂起/恢复支持(包括用笔记本盖子执行)

  • 支持厂商专有工具帮助测量电源管理

  • 工具与 ACPI 支持风扇速度控制

  • 工具与 ACPI 支持屏幕亮度设置

  • 电池容量状态与运行时间估计

  • 网络接口的节能方案

  • 支持 AMD PowerNow!

  • 支持 Intel (Enhanced) SpeedStep

  • 支持 Intel Speed Shift

  • 支持 AMD Turbo Core

  • 支持 Intel 睿频

  • 4 – 端口空闲 1 毫秒后,驱动发起 PARTIAL PM 状态转换

  • 5 – 端口空闲 125 毫秒后,驱动发起 SLUMBER PM 状态转换

  • /boot/kernel/acpi_hp.ko

  • /boot/kernel/acpi_ibm.ko

  • /boot/kernel/acpi_panasonic.ko

  • /boot/kernel/acpi_sony.ko

  • /boot/kernel/acpi_toshiba.ko

  • /boot/kernel/acpi_video.ko

  • /boot/kernel/acpi_wmi.ko

  • 11.13. Power and Resource Management
    4. Power Management
    HOWTO: FreeBSD CPU Scaling and Power Saving
    FreeBSD Network Management with network.sh
    FreeBSD Desktop – Part 13 – Configuration – Dzen2
    hwpstate_intel(4)

    为什么是 FreeBSD?

    • 原文:Quare FreeBSD?

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2020/09/07

    我本来真的想把这篇文章写得不那么长……但我彻底失败了。但我至少尽力把它组织得井井有条,这样读者在略读之后可以回过头来复习,因为它并不是一堂速成课。我本想将它命名为 Why FreeBSD?,但当你在自己喜欢的 搜索引擎 duck.com中输入这个标题时,会出现很多类似的文章。我希望它有个独特且与众不同的名字,于是我使用了拉丁语中的“为什么”——quare。

    FreeBSD 能为你提供哪些在其他操作系统无法提供的东西?在我使用过的所有操作系统中,我发现 FreeBSD 的缺点最少。这篇文章并不是为了说服你使用和尝试 FreeBSD——这需要你自己去体验。本文将展示 FreeBSD 的价值所在,以及为何它是其他操作系统的更好替代方案,并且 FreeBSD 绝对没有走向大败局。

    基本系统

    当你安装 Linux 系统时,它只是一些 RPM 或 DEB 软件包的集合。例如,如果你安装 CentOS 7.8 的 Minimal 版本,最终会安装几百个 RPM 软件包。经过一周乃至一个月,其中许多软件包会收到更新,有时会导致这个 CentOS 系统无法使用,甚至无法启动(例如最近的 GRUB Boothole 问题)。而 FreeBSD 提供了 基本系统 的概念。这意味着当你安装 FreeBSD 时,你安装的是完整的最小系统。没有需要单独更新的软件包或子系统。只是完整的 基本系统。这意味着 /boot /bin /sbin /usr /etc /lib /libexec /rescue 目录不受其他软件包影响。当你决定安装软件包(或使用 FreeBSD Ports 构建它们)时,它们都会安装在路径 /usr/local 下。这意味着配置文件位于 /usr/local/etc,可执行文件位于 /usr/local/bin 和 /usr/local/sbin,库文件位于 /usr/local/lib 和 /usr/local/libexec,依此类推。FreeBSD 基本系统 的内核模块与内核一起存放在目录 /boot/kernel。为了保持整洁,由软件包提供的所有内核模块都会放在 /boot/modules 目录中。所有内容都有其位置并且互不干扰。

    这就是 基本系统 二进制文件(位于 /bin /sbin /usr/bin /usr/sbin 目录)与由 pkg(8) 维护的第三方软件包(位于 /usr/local/bin 和 /usr/local/sbin 目录)之间的分离。我们都知道 bin(普通用户)与 sbin(root)二进制文件的区别,但在 FreeBSD 中还有另一种与 UFS 相关的分离。当 FreeBSD 世界中只有 UFS 文件系统时,/bin 和 /sbin 二进制文件在根文件系统(/)挂载后、/usr 文件系统挂载前即可使用——这是个历史性的(在 UFS 配置中仍然有用)区分,可追溯到早期 UNIX 时代。在 ZFS 配置中,这不再重要,因为所有文件都在 ZFS 池中。

    下面是 基本系统 的 / 目录示意图,以及可选的第三方应用程序目录 /usr/local。

    FreeBSD 基本系统 的分离还有另一个好处——如果某个软件包产生“伟大”的想法,去安装新的 cc 编译器并覆盖默认系统编译器,或者以某种方式添加库和头文件,使得系统恢复工作变得非常困难,你也不必担心。如果某个随机的 FreeBSD 软件包将 libc.so 添加到 /usr/local/lib 目录,你仍然可以正常运行程序,因为 FreeBSD 系统二进制文件是链接到 /usr/lib 下的内容。这也是 UNIX 系统(包括 FreeBSD)中存在 PATH 变量的原因,用于设置首先搜索哪些目录的二进制文件。在 FreeBSD 中,默认设置是先搜索 基本系统 的二进制文件目录,然后再搜索第三方软件包目录。

    你可以使用命令 freebsd-update(8) 在 RELEASE 系统下单独更新(或不更新)基本系统,或者在 STABLE/CURRENT 系统下通过 make buildworld 和 make installworld 命令重新编译更新。而软件包可以通过 pkg(8) 工具更新,或者在 /usr/ports 目录下使用 portmaster 从 FreeBSD Ports 树构建更新。这意味着软件包的更新不会影响你的 FreeBSD 基本系统。例如,当你搞砸了已编译的 ports 和软件包(我在 FreeBSD 初期就这样做过),如果你想重新开始,你只需要删除 /usr/local、/boot/modules 和 /var/db/pkg 目录。就这样,你就回到了 基本系统,可以重新开始。这在 Linux 系统中是无法做到的。即使是很多概念基于 FreeBSD 的 Gentoo,也没有 基本系统 的特性。

    基本系统 还有个额外的优点。由于它与软件包分离,没有人阻止你在 2012 年的 FreeBSD 9.0 上运行最新的 Firefox 80 或 LibreOffice 7.0。而你却无法在 2012 年的 Ubuntu 上安装最新的 Firefox……

    有人可能担心,这样独立于安装软件包的 基本系统 会占用更多空间,但事实完全相反。Fresh 安装的 FreeBSD 12.1 系统占用不到 1 GB 磁盘空间,运行 sshd(8) 时使用不到 75 MB 内存。相比之下,Fresh 安装的 CentOS 7.8(选择 Minimal 集)占用 1.1 GB 磁盘空间,运行 sshd(8) 时使用超过 100 MB 内存。这样的 CentOS 系统非常精简,实际使用还需要安装更多软件包,而 FreeBSD 依靠 基本系统 本身就更强大且功能丰富,例如自带最新版本的 LLVM/CLANG 编译器套件。

    从 FreeBSD 15.0 开始,可以使用 PKGBASE 特性安装 FreeBSD,而不是传统的发行版集合——这允许 pkg(8) 命令管理 FreeBSD 基本系统 的软件包集。这与 Linux 系统不同,因为在 Linux 上所有内容都在一个平面仓库中。而 FreeBSD 使用 PKGBASE 仍然保留软件包集、核心软件包,并为 基本系统 提供独立仓库。如果 FreeBSD 与 Linux 相同,所有软件包——包括 基本系统 和第三方软件包——都在一个仓库中,没有 PKGBASE 软件包集,也没有 基本系统 核心软件包。而你仍然可以将 FreeBSD 基本系统 软件包与第三方软件包分开升级,只需向 pkg(8) 命令指定 -r REPOSITORY 参数即可。

    关于 基本系统 主题的更多资料:

    ZFS 启动环境

    我已经多次谈到过这一点,可能次数还不够,因为 Linux 世界仍然忽视这一“福音”。拥有 ZFS 启动环境 是一个彻底改变游戏规则的特性,一旦你发觉它的强大,你就再也不想使用不支持 ZFS 的系统。其核心思想是,你能在系统运行的任意时刻创建快照,如果出现问题,可重启回到该时刻(或快照)。这是升级或系统变更的完美解决方案。FreeBSD 系统本身已经很好地“防护”了更新软件包后可能产生的问题,但 ZFS 启动环境 将这种保护提升到了一个全新的水平。

    就像电影 中的情节一样,借助 ZFS 启动环境,你将拥有无限次机会来把事情处理好。即使 基本系统 的更新和变更,也受其保护。你甚至可以使用 zfs send 和 zfs recv 命令将该 启动环境 传输到其他系统,或者在多个系统间分发它。你可以基于它创建 Jails 容器……或者在新的 启动环境 中安装 FreeBSD 新版本并重启进入,同时保留旧的“生产”系统不受影响。

    关于 ZFS 启动环境 的更多资料:

    救援

    当你把系统搞得一团糟,甚至 基本系统 概念或 ZFS 启动环境 功能都无法阻止你破坏 FreeBSD 安装时,还有一个更高级别的救援手段——rescue 救援 子系统。

    你可以使用大约 150 个静态链接的二进制文件来执行 FreeBSD 安装的救援任务。你可能会想,这么多二进制文件是不是占用了大量空间……事实完全相反。它实际上是一个静态二进制文件,通过硬链接实现,并且只占用 11 MB 的磁盘空间。

    救援 子系统甚至包含一些二进制文件,例如用于 ZFS 启动环境 管理的 bectl(8),以及用于 ZFS 文件系统的 zfs(8) 和 zpool(8) 命令。以下是这些二进制文件的完整列表。

    关于 rescue 救援 主题的更多资料:

    音频

    许多人可能不会期望 FreeBSD 在音频方面表现突出,但它在这方面已经表现卓越,并且这种优势不是最近才有,而是持续了数十年。记得 Linux 摒弃了旧的 OSS 子系统(单声道)并提出“伟大”的 ALSA 思路吗?我记得,因为那时我用 Linux。用“灾难”来形容当时的 Linux 音频栈都算礼貌……后来 PulseAudio 出现,整个 Linux 音频系统变得更烂。当时,由于只有 OSS 单通道而 ALSA 有许多通道,这意味着只有一个使用 OSS 后端的应用程序(例如 WINE)可以输出声音。如果另一个应用想用 OSS 发声,而 WINE 已经占用了唯一 OSS 通道,就会没有声音。而当时 ALSA 的实现非常糟糕,以至于 KDE 或 GNOME 各自创建了用户空间的声音守护进程来混合音频,这些守护进程之间又不兼容。这意味着如果你同时使用 KDE 和 GNOME 应用,可能 GNOME 应用有声音,而 KDE 应用没有,反之亦然。那真是 Linux 上的音频地狱。

    回到 FreeBSD 音频,FreeBSD 提供了什么?惊人的 256 个 OSS 通道在内核中实时混音,实现低延迟。所有音频功能开箱即用——至今依然如此。你可以让 WINE 或 KDE/GNOME 的声音后端绑定到它们的 OSS 通道,同时 ALSA 应用也能正常使用声音设备。即使你插入一个 5.1 环绕音响系统,FreeBSD 也能开箱即用,应用程序能够立即使用。FreeBSD 的音频优势至今依然存在,而 Linux 中 PulseAudio 在用户空间混音虽然能用,但相比内核中的低延迟 FreeBSD 混音,会有较大延迟。

    同事 提到,FreeBSD 也是唯一拥有 virtual_oss 的操作系统,它能在用户空间进行混音/重采样/压缩,并能把蓝牙耳机和 USB 麦克风表示为单一声卡。

    关于 音频 的更多资料:

    Jail

    FreeBSD Jail 是最早的 实现之一,可追溯到 1999 年。即便是 Solaris 的 Zones/Containers,也要到 2004 年才问世,比 Jail 晚了五年。

    在 Linux 引入 Docker 之后,操作系统级虚拟化 这一术语逐渐被 容器(Containers)取代,现在 FreeBSD Jail 与 Solaris Zones/Containers 被称为初代容器。但这种命名上的变化并没有降低 FreeBSD Jail 的强大功能。它们使用起来也非常简单。你只需要一个目录——例如 /jail/nextcloud——将所需版本的 FreeBSD 基本系统 解压到该目录,例如从 12.1-RELEASE 获取 ,并在 /etc/jail.conf 文件中创建 Jail 配置,如下所示。

    现在你可以立即启动你的 Jail。

    瞧!你的 FreeBSD Jail 已经跑起来了。

    当然,如果需要,你可以在 Jail 中使用精简版的 FreeBSD 基本系统。ZFS 文件系统在这里也非常有用,因为使用 zfs clone 时,只有你的“基础” Jail 会占用空间,而从它创建的 Jails 只会记录你的修改。借助 FreeBSD 的另一个子系统——Linux 二进制兼容层,你还可以创建 Linux Jail,例如运行 Devuan 或 Ubuntu Jail。

    FreeBSD Jail 也非常轻量。在单台 4 GB 内存的 FreeBSD 系统上,你可以启动并使用约 1000 个 FreeBSD Jail。

    与纯 Docker 相比,它们也更容易调试和排错——更别提 Kubernetes,需要整支高技能团队来维护。

    可以仅通过 基本系统 工具管理 FreeBSD Jail,如 jls(8)/jexec(8),当然你也可以选择许多第三方 Jail 管理框架。在所有可用选项中,我会推荐 ,因为其现代化的方法和大量可用模板覆盖各种使用场景。

    如果你想了解 Jail 的所有功能,可以参考文章 。

    更多关于 Jail 的资料:

    Bhyve

    FreeBSD——和 Linux 或其他受人尊敬的操作系统一样——自带其自研的虚拟化 hypervisor。在 FreeBSD 世界中,这个原生解决方案被称为 Bhyve(拼写为 bee hive)。

    在功能方面,它类似于 KVM/XEN/VMware/VirtualBox。

    它唯一缺少的是 Live Migration 热迁移 功能。这个功能正在开发中,因为 Save/Resume 功能正在测试中,很快将被合并。

    除此之外——它的性能与前述竞争产品不相上下或相似。归根结底——它们都使用相同的 AMD/Intel CPU 功能,这些功能支持 x86 平台的虚拟化。

    如果你想全面了解 Bhyve hypervisor 的全部特性——可以查看 文章。

    另外,如果 Bhyve 不适合你的需求,FreeBSD 也支持 XEN(作为 dom0)和 VirtualBox hypervisor。

    更多关于 Bhyve 的信息:

    FreeBSD Ports 基础设施

    这又是一个例子,说明为什么 FreeBSD 如此出色。当你安装某个版本的 Ubuntu 或 CentOS 时,很可能得到的不是最新版本的包,而是该发行版发布时比较新的版本。这一点在 CentOS 世界(以及其上游企业源系统 Red Hat)中尤其明显——在 .0(点零)版本发布时,包几乎都是最新的,但当该版本的 .8 或 .9 版本可用时,包已经严重过时。更不用提像 Firefox 这样每个月都有新版本发布的情况了……

    正如我之前在说明 FreeBSD 基础系统 时所说,FreeBSD Ports(以及通过 pkg(8) 命令可用的由其构建的包)是独立的。这意味着来自 FreeBSD Ports 的第三方软件几乎总是最新的(或非常接近最新)。你甚至可以在 网站上查看详细信息。下面是本文撰写时 统计的“快照”。在线表格非常长,这里仅复制了与本文相关的系统部分。

    FreeBSD Ports 的另一个优势是,它提供了极其庞大的软件量——本文撰写时已有 40354 个 port,并且数量仍在增加。可直接安装的包数量略少,32000 余个可用包。

    我曾在 2009 年短暂迁移到 OpenSolaris,在我的 Dell Latitude D630 笔记本上,因为我非常喜欢 Solaris 的所有功能(包括当时 FreeBSD 上尚不可用的 ZFS 和 ZFS Boot Environments),OpenSolaris 基于 GNOME 的桌面也相当不错,即使在 Nautilus 文件管理器中提供 ZFS 快照的 Time Slider 功能。当时我成功连接了 WiFi,声音正常,总体而言笔记本上的一切都得到支持并正常运行……但软件很少。当然,“大”项目如 GIMP 或 OpenOffice 在默认 pkg(8) 仓库中可用,但其他不多。当时 OpenSolaris 的可用包不到 4000 个,而 FreeBSD 的包大约有 25000 个,如果我没记错的话。

    你也可以通过网页轻松浏览可用的 FreeBSD Ports(及其选项),使用 页面。

    FreeBSD Ports 的数量是一方面,功能则是另一方面。无论你使用哪种 Linux 发行版,总会遇到某些软件在编译和发布时没有加上你急需的标志。如果在 FreeBSD 上遇到类似情况,“痛苦”只会持续片刻,因为你可以非常轻松地使用所需选项重新编译该软件,并用自己的版本替换掉“默认”包。例如,FreeBSD 项目因为现有的 MP3 专利而不敢提供 Lame 包(译注:在 2020 年该限制及下述限制),所以 multimedia/ffmpeg 包默认是没有 MP3 支持的(使用 --disable-libmp3lame 标志)。这就是为什么我有自己的 audio/lame 和 multimedia/ffmpeg 包,都是按照我的 configure 选项构建的,而且实现非常简单。你只需进入 /usr/ports/multimedia/ffmpeg 目录,输入 make config,在 ncurses 对话框中选择 [x] LAME。你选择的选项会保存到普通文件 /var/db/ports/multimedia_ffmpeg/options。如果删除该文件(或输入 make rmconfig),这些自定义选项将重置为默认值。然后输入 make build deinstall install clean,你的 port 就会以新选项构建并安装为包,无需其他操作。你甚至可以使用 pkg(8) 的 pkg lock -y ffmpeg 命令锁定该包,防止之后被窜改,但更好的做法是每次执行 pkg upgrade 时重新构建此类包,以应对库版本升级和变化。虽然使用这些命令创建脚本实现自动化非常容易快捷,你也可以使用 FreeBSD Ports 基础设施的其他部分——比如 Poudriere(或 Synth)——在下一部分会详细介绍。

    你也不必每个 port 都这样配置(对于大量 port 来说会很麻烦),可以只在 /etc/make.conf 文件中全局指定所需的 (OPTIONS_SET) 或不需要的 (OPTIONS_UNSET) 参数。你还可以指定软件的默认版本,例如使用 Apache 2.2 而不是 2.4,使用 PHP 7.0 而不是 7.2。所有默认版本信息可以在 /usr/ports/Mk/bsd.default-versions.mk 文件中找到。只要设置好这些选项,你可以使用 portmaster(8) 工具从 FreeBSD Ports 构建/重建或更新包。类似 Gentoo Linux 的 USE 标志,但这才是原版。Gentoo 的大部分思想都是从 FreeBSD 系统及其 Ports 基础设施中借鉴的。

    Poudriere 是一款构建框架,它使用 FreeBSD Ports 和 FreeBSD Jails 以干净、可复现的方式构建所需包。你可以为 pkg(8) 命令创建全新的二进制包仓库。我提到 Synth,是因为 Poudriere 通常用于生成整个包仓库,而 Synth 通常仅用于重建几个不符合你需求的包。

    关于 FreeBSD Ports,有一点常被新手误解。Ports 和通过 pkg(8) 工具获取并安装的包有什么区别?很简单:软件包只是预构建并安装的 port,仅此而已。当你使用 pkg(8) 命令安装二进制包时,你使用的是某个人(在 FreeBSD 的情况下就是 FreeBSD 项目)在某个时间点从 FreeBSD Ports 构建的包。虽然 FreeBSD 努力保持构建包尽可能更新,但 FreeBSD Ports 的本质是总比构建好的包更新。这就是为什么你可以自己使用 FreeBSD Ports 构建并安装所需包的新版本。考虑安全漏洞时,这种使用方式尤其有意义。当某些本地执行的命令(如 file(1))存在安全漏洞时,可能不必急于更新,因为漏洞对你可能无害;但当 Firefox 的新版本修复了重要安全漏洞时,最好尽快从 FreeBSD Ports 更新,因为等待两天构建包(与其他包一起)可能太长。

    更多关于 FreeBSD Ports 的信息:

    从源码更新/构建

    虽然 FreeBSD Ports 基础设施是为第三方软件设计的,FreeBSD 基本系统(或其部分)也可以轻松方便地从源码构建。FreeBSD 内核配置也非常小巧且简单。相比之下,Linux 内核配置包含数千个选项——例如在默认 CentOS 8.2 安装中有 4432 个选项,而 FreeBSD 的 GENERIC 配置的选项数量约只有前者的二十分之一——只有 260 个选项。但这还未触及主题的核心。你可以从最小化的 FreeBSD 内核配置开始,其仅指定 75 个选项。

    ……而且这不仅仅是选项数量更少的问题。你能说说重建 CentOS 或 Ubuntu(例如去掉蓝牙支持)需要多少步骤(以及哪些步骤是必须的)吗?

    相反,在 FreeBSD 上操作非常简单(且快速)。虽然 /etc/make.conf 文件用于启用/禁用 Ports 选项,但 /etc/src.conf 文件用于在从源码构建 FreeBSD 基本系统 时启用/禁用选项。要构建不含 Bluetooth 支持的 FreeBSD,只需在 /etc/src.conf 文件中添加 WITHOUT_BLUETOOTH=yes,然后输入以下命令进行构建:

    瞧!现在你拥有了不含蓝牙支持的 FreeBSD……而且如果任何步骤失败,或者由于你的经验/专业知识不足导致 FreeBSD 系统无法启动或损坏,你可以使用 /rescue 中的工具尝试修复(或至少找出问题所在);如果你不想处理这些问题,只需在 FreeBSD loader(8) 中选择 safe ZFS Boot Environment,即可启动到你开始构建修改版 FreeBSD 之前的系统。是的,这里你几乎“刀枪不入”。在拥有 294 个 WITHOUT_X 选项和 125 个 WITH_X 选项的情况下,你真的可以将 FreeBSD 基本系统 调整到完全符合你的需求。

    通过源码更新 FreeBSD 的一大缺点是,你无法使用 freebsd-update 工具……但这并不妨碍你创建自己的 FreeBSD 更新服务器,这样你就可以通过使用 CURRENT 或 STABLE 系统(而不是 RELEASE)添加更新来使用 freebsd-update。这一过程在官方 FreeBSD 文档的 文章中有详细描述。

    更多关于 FreeBSD 源码更新/构建 的信息:

    存储

    存储是 FreeBSD 真正出彩的部分之一。很多人因为 FreeBSD 对 ZFS 文件系统的良好集成而喜爱它,这确实不假。FreeBSD 中的 ZFS 一直是一级公民。最近,OpenZFS 2.0 也已从 FreeBSD 与 Linux 的联合上游仓库集成。越来越多的 FreeBSD 功能和解决方案正在利用 ZFS 的特性。

    大多数喜欢 FreeBSD 集成 ZFS 的人并不了解 FreeBSD 的 GEOM 模块化磁盘转换框架,它提供了各种存储相关功能和工具,例如软件 RAID0/RAID1/RAID10/RAID3/RAID5 配置,或使用 GELI/GDBE 对底层设备进行透明加密(类似 Linux 上的 LUKS)。它还能为任何文件系统提供透明的文件系统日志功能(GJOURNAL,甚至适用于 FAT32 或 exFAT),或通过 GEOM GATE 设备将块设备导出到网络上(类似块设备的 NFS)。

    FreeBSD 还拥有自己的 FUSE 实现,使所有基于 FUSE 的文件系统能够在 FreeBSD 上原生工作。虽然很多 Linux 用户了解 DRBD,但很少有人知道 FreeBSD 自带类似 DRBD 的解决方案 HAST——其功能完全相同。尽管 ZFS 功能丰富,FreeBSD 仍然维护并开发快速且内存占用小的 UFS 文件系统,该文件系统今天根据使用场景可使用 Soft Updates (SU) 或 Journaled Soft Updates (SUJ)。例如,在 UFS 文件系统上使用 Journaled Soft Updates (SUJ) 管理 10 TB 数据,fsck(8) 检查大约只需 1 分钟。这些存储解决方案仅依赖 FreeBSD 基本系统 即可实现。FreeBSD Ports 提供更多功能,包括分布式文件系统解决方案,如 CEPH、LeoFS、LizardFS 或兼容 Amazon S3 的 Minio 存储。

    更多关于 存储 的信息:

    Init 系统

    FreeBSD 提供了非常简单但功能强大的 init 系统。它在 /etc/rc.conf 文件中有系统级配置,你可以通过条目 service_enable=YES 和 service_enable=NO 启用/禁用所需服务。你甚至不需要打开 vi(1) 来手动添加,只需输入 sysrc service_enable=YES,条目就会被添加到 /etc/rc.conf 文件中。系统还提供了默认值和默认启用的服务,你可以在 /etc/defaults/rc.conf 文件中找到它们,以及大量注释。每个 FreeBSD 服务文件都有 PROVIDE/REQUIRE 条目,用于自动确定服务启动顺序。可以并行运行的服务会同时启动以节省时间。例如,没有网络启动 sshd(8) 守护进程是毫无意义的。要启动或停止服务,只需输入 service sshd start 或 service sshd stop 命令。但当某个服务未在 /etc/rc.conf 文件中启用时,需要使用 onestart 和 onestop。基本系统 的分离在这里仍然保持:FreeBSD 基本系统 服务位于 /etc/rc.d 目录,而来自 ports/packages 的第三方应用位于 /usr/local 前缀下,即 /usr/local/etc/rc.d 目录。

    使用 systemd(1) 时,你无法预测服务启动顺序,每次可能都不同,完全没有确定性。而在 FreeBSD 上,你可以精确知道哪些服务会启动,因为它们总是根据 PROVIDE/REQUIRE 条目以相同顺序排列。FreeBSD 还提供了工具 rcorder(8),可用于查看所有服务、基本系统 服务或第三方服务的精确启动顺序。同时,service -r 命令可以显示启动时的实际顺序。

    在 FreeBSD 中添加新服务也非常简单,因为新服务的模板非常小巧且易于理解。

    如果你觉得还不够简单,FreeBSD 官方有一篇关于如何编写服务的文章——。

    更多关于 Init 系统 的信息:

    Linux 二进制兼容层

    虽然 Linux 不能成为 FreeBSD,但 FreeBSD 可以运行 Linux——而且这并非低速模拟,而是通过对 Linux 系统调用的实现来完成的。过去企业常使用 FreeBSD 的 Linux 二进制兼容层 来运行仅适用于 Linux 的应用(当时 FreeBSD 上不可用),因为这样比在 Linux 上原生运行更快——,这是官方 FreeBSD 新闻稿,介绍 FreeBSD 曾用于为经典影片 生成视觉特效。

    如今,LINUX_COMPAT 同样原生高效,能运行 Linux 应用——甚至可以在 X11 下硬件加速运行 Linux 游戏。可以将其理解为针对 Linux 应用的 WINE,它位于 /compat/linux 目录下。它甚至实现了 Linux 的 /proc 虚拟文件系统,可挂载在 /compat/linux/proc,但并非强制要求。对于任何没有源码、仅能在 Linux 上运行的软件,Linux 二进制兼容层 都能派上用场。例如 项目。在了解 Redshift 之前,我曾使用 LINUX_COMPAT 运行 f.lux Linux 二进制版本,在 FreeBSD 屏幕上抑制蓝光。Linux 二进制兼容层 子系统还可以用于运行基于 Linux 的 FreeBSD Jails,例如 Devuan。

    更多关于 Linux 二进制兼容层 的信息:

    简洁性

    FreeBSD 很简单,但并不粗糙或难以驾驭。例如,和 Linux 一样,FreeBSD 系统也支持虚拟文件系统 /proc,但在 FreeBSD 上它是可选的,默认不启用,而 Linux 则离不开它。然而,Linux 在强制使用 /proc 的同时,还拥有另一个位于 /sys 的虚拟文件系统……但为什么 Linux 需要两个目的类似的虚拟文件系统?为什么不能把所有内容都放在已经存在的 /proc 下呢?这对我的理智来说简直是个谜。

    而 /sys 并不是这场混乱的终点,它仅仅是开始。

    那么这些呢?

    • securityfs

    • devpts

    • cgroup

    • pstore

    看看 FreeBSD 在默认 ZFS 安装后的 mount(8) 输出,就能体会不同的简洁设计。

    几个 ZFS 数据集,以及一个用于 /dev 目录的虚拟 devfs 文件系统。如果安装在 UFS 上,则类似,只是会挂载几个 UFS 分区来替代 ZFS 数据集。

    再看看 CentOS 8.2 的安装情况——只有一个物理根(/)XFS 文件系统。

    天哪。那里甚至很难找到任何真正的文件系统……幸运的是,我们可以请求仅显示 XFS 文件系统。

    现在我们来谈谈网络。假设你想在一台物理服务器上建立标准企业级网络配置,将两个网卡聚合成一个高可用接口 bond0(在 FreeBSD 上为 lagg0),然后在该 VLAN 上配置 VLAN 标签和 IP 地址。CentOS 7.x/8.x 的安装程序(Anaconda)在面对这种情况时会让你应接不暇。

    说明一下——我选择了“STATIC”(静态)IPv4 地址,但安装程序却让这些接口同时使用 DHCP 和那个 STATIC 地址。这可能是一个 bug,不过我们直接说重点。

    经过手动使用 vi(1) 修正(花费大约一小时)后,它应该是这样的。

    更好了……但仍然占用大量空间,需要多个文件来完成这个相对简单的配置。更不用说其复杂度高、容易出错的特点。而在 FreeBSD 上,同样的配置只需在单个 /etc/rc.conf 文件中写 7 行即可,如下所示。

    但这还不是所有的复杂之处。过去,你可以使用简单的 service network restart 命令重启 RHEL/CentOS/Rocky/... 的网络配置……现在不行了。你需要输入两个命令:先 nmcli networking off,再 nmcli networking on。为了确保第二条命令能够执行,并且在执行前不会丢失网络连接,你必须在 screen(1) 或 tmux(1) 终端复用器中一个接一个地输入它们。简直方便得不得了 🙂。

    启动过程呢?FreeBSD 可以直接从 ZFS 根分区启动,只需一个小的 512 KB 不可挂载分区。无需单独的 /boot 设备。而 Linux 总是需要单独的 /boot 分区,并且里面充满了 GRUB 模块。不管是 ZFS 还是 LVM,这都是必须的。这也是为什么在 Linux 上实现 ZFS Boot Environments 非常复杂——即使你在 Linux 系统上使用 ZFS 根分区,仍然存在未受保护的 /boot 文件系统,无法用 ZFS 快照,只能用传统方式保护,这几乎摧毁了 ZFS Boot Environments 的理念。

    FreeBSD 真的是一个简单且设计周到的操作系统,同时也是被严重低估的系统。

    改革而非革命

    有多少 Linux 工具或子系统被废弃或被新工具取代?为什么没有为 ifconfig(8) 增补新选项,而是引入了全新的 ip(8) 命令?同样,netstat(8) 被 ss(8) 替代,arp(8)/iwconfig/route(8) 等也如此。整个 init 系统呢?Linux 世界已经被 systemd(1) 占领,无论你喜欢与否。即便像 Ubuntu 这样拥有成熟 init 系统(Upstart)的发行版,也完全转向 systemd(1)。如今,未采纳 systemd 的发行版非常少,被视为小众。

    而在 FreeBSD 世界中,仅在无法通过其他方式实现新功能时才会进行重大变更。这是 FreeBSD 最不希望发生的情况。FreeBSD 的发展注重稳定性和向后兼容性。用户空间工具会随着新选项逐步更新,而不是反复重写。更不用说,将一个工具换成另一个工具会带来多少新的 bug。

    更多关于 改革而非革命 的信息:

    文档

    拥有一款几乎能做任何事情的系统,但不知道如何操作,这样的系统几乎没用(或者至少使用起来非常麻烦)。FreeBSD 提供了无与伦比的文档,这些文档都是持续维护和更新的。除了其传奇的 和 ,FreeBSD 项目还提供官方 ,涵盖各种 FreeBSD 主题。 也非常详细,并包含大量示例。还有 页面,用于记录正在进行的文档和与 FreeBSD 开发相关的想法。如果你在使用 FreeBSD 时遇到问题或有疑问,也可以访问官方 和老派的 。

    以上仅是官方项目的知识来源,此外还有大量 FreeBSD 书籍。你也可以参考我专门的 文章,深入了解可用的 FreeBSD 书籍。以下是最佳且最新的书籍:

    • Absolute FreeBSD – Complete Guide to FreeBSD – 第三版(2019)

    • Beginning Modern Unix(2018)

    • Book of PF – 第三版(2015)

    • Design and Implementation of FreeBSD 11 Operating System(FreeBSD 操作系统设计与实现) – 第二版(2015)

    还有两本专门面向 BSD 和 FreeBSD 系统的杂志,均免费,涵盖大量 FreeBSD 有趣话题:

    拥有如此丰富的知识和支持,要在 FreeBSD 系统上实现所需功能几乎没有难度。

    社区

    最后但同样重要,我认为社区甚至比优秀的文档更重要(FreeBSD 的文档非常棒)。使用 FreeBSD 的人通常是有意识选择的,并且往往在 FreeBSD 领域以及其他 UNIX 系统相关领域都有经验。他们往往经历了从 Linux 系统开始使用的漫长过程,最终选择 FreeBSD,或者在日常仍然从事 Linux 管理工作,但在休息时使用更合理、理智的 FreeBSD 解决方案。我总是觉得 FreeBSD 社区非常乐于助人且友好,尤其对新人非常耐心。即便你试图在不公或有争议的讨论中“逼迫” FreeBSD 用户“争辩”,他们也会以尊严和技术论据回应,而不是对你大喊大叫。

    FreeBSD 项目甚至专门为 Linux 新手(有时被称为 systemd(1) 难民)制作了若干文章和 Handbook 章节:

    结语

    我尽力避免将其写成对 Linux 的抱怨,但有些人可能会有这种感觉——如果是这样,请记住,这并非我的本意。FreeBSD 和 Linux 以及任何其他操作系统一样,都有其优缺点。希望我向你展示了 FreeBSD 中最有趣的部分。将来我可能会在这里无预警地增加新章节 🙂。

    外部讨论

    来自“外部”来源的讨论和评论可在以下链接查看:

    % acpiconf -i 0
    Design capacity:        44000 mWh
    Last full capacity:     37930 mWh
    Technology:             secondary (rechargeable)
    Design voltage:         11100 mV
    Capacity (warn):        1896 mWh
    Capacity (low):         200 mWh
    Low/warn granularity:   1 mWh
    Warn/full granularity:  1 mWh
    Model number:           45N1037
    Serial number:          28608
    Type:                   LION
    OEM info:               SANYO
    State:                  high
    Remaining capacity:     100%
    Remaining time:         unknown
    Present rate:           0 mW
    Present voltage:        12495 mV
    % acpiconf -i 0
    Design capacity:        44000 mWh
    Last full capacity:     37930 mWh
    Technology:             secondary (rechargeable)
    Design voltage:         11100 mV
    Capacity (warn):        1896 mWh
    Capacity (low):         200 mWh
    Low/warn granularity:   1 mWh
    Warn/full granularity:  1 mWh
    Model number:           45N1037
    Serial number:          28608
    Type:                   LION
    OEM info:               SANYO
    State:                  high
    Remaining capacity:     100%
    Remaining time:         2:31
    Present rate:           0 mW
    Present voltage:        12492 mV
    % acpiconf -i 1
    Design capacity:        31320 mWh
    Last full capacity:     24510 mWh
    Technology:             secondary (rechargeable)
    Design voltage:         10800 mV
    Capacity (warn):        1225 mWh
    Capacity (low):         200 mWh
    Low/warn granularity:   1 mWh
    Warn/full granularity:  1 mWh
    Model number:           45N1041
    Serial number:            260
    Type:                   LiP
    OEM info:               SONY
    State:                  high
    Remaining capacity:     100%
    Remaining time:         unknown
    Present rate:           0 mW
    Present voltage:        12082 mV
    % acpiconf -i 1
    Design capacity:        31320 mWh
    Last full capacity:     24510 mWh
    Technology:             secondary (rechargeable)
    Design voltage:         10800 mV
    Capacity (warn):        1225 mWh
    Capacity (low):         200 mWh
    Low/warn granularity:   1 mWh
    Warn/full granularity:  1 mWh
    Model number:           45N1041
    Serial number:            260
    Type:                   LiP
    OEM info:               SONY
    State:                  discharging
    Remaining capacity:     98%
    Remaining time:         1:36
    Present rate:           14986 mW
    Present voltage:        11810 mV
    % sysctl hw.acpi.battery.time
    hw.acpi.battery.time: 247
    % sysctl hw.acpi.battery
    hw.acpi.battery.info_expire: 5
    hw.acpi.battery.units: 2
    hw.acpi.battery.state: 1
    hw.acpi.battery.time: 247
    hw.acpi.battery.life: 99
    % sysctl hw.acpi.battery
    hw.acpi.battery.info_expire: 5
    hw.acpi.battery.units: 2
    hw.acpi.battery.state: 0
    hw.acpi.battery.time: -1
    hw.acpi.battery.life: 100
    % battery-capacity.sh 0
    Battery '0' model '45N1037' has efficiency: 86%
    
    % battery-capacity.sh 1
    Battery '1' model '45N1041' has efficiency: 78%
    #! /bin/sh
    
    if [ ${#} -ne 1 ]
    then
      echo "usage: ${0##*/} BATTERY"
      exit
    fi
    
    if acpiconf -i ${1} 1> /dev/null 2> /dev/null
    then
      DATA=$( acpiconf -i ${1} )
      MAX=$( echo "${DATA}" | grep '^Design\ capacity:'     | awk -F ':' '{print $2}' | tr -c -d '0-9' )
      NOW=$( echo "${DATA}" | grep '^Last\ full\ capacity:' | awk -F ':' '{print $2}' | tr -c -d '0-9' )
      MOD=$( echo "${DATA}" | grep '^Model\ number:'        | awk -F ':' '{print $2}' | awk '{print $1}' )
      echo -n "Battery '${1}' model '${MOD}' has efficiency: "
      printf '%1.0f%%\n' $( bc -l -e "scale = 2; ${NOW} / ${MAX} * 100" -e quit )
    else
      echo "NOPE: Battery '${1}' does not exists on this system."
      echo "INFO: Most systems has only '0' or '1' batteries."
      exit 1
    fi
    % sysctl dev.cpu.0
    dev.cpu.0.cx_method: C1/hlt C2/io
    dev.cpu.0.cx_usage_counters: 412905 0
    dev.cpu.0.cx_usage: 100.00% 0.00% last 290us
    dev.cpu.0.cx_lowest: C1
    dev.cpu.0.cx_supported: C1/1/1 C2/3/104
    dev.cpu.0.freq_levels: 2501/35000 2500/35000 2200/29755 2000/26426 1800/23233 1600/20164 1400/17226 1200/14408 1000/11713 800/9140
    dev.cpu.0.freq: 800
    dev.cpu.0.%parent: acpi0
    dev.cpu.0.%pnpinfo: _HID=none _UID=0
    dev.cpu.0.%location: handle=\_PR_.CPU0
    dev.cpu.0.%driver: cpu
    dev.cpu.0.%desc: ACPI CPU
    % sysctl dev.cpu.0
    dev.cpu.0.temperature: 49.0C
    dev.cpu.0.coretemp.throttle_log: 0
    dev.cpu.0.coretemp.tjmax: 100.0C
    dev.cpu.0.coretemp.resolution: 1
    dev.cpu.0.coretemp.delta: 51
    dev.cpu.0.cx_method: C1/hlt C2/io
    dev.cpu.0.cx_usage_counters: 16549 0
    dev.cpu.0.cx_usage: 100.00% 0.00% last 1489us
    dev.cpu.0.cx_lowest: C1
    dev.cpu.0.cx_supported: C1/1/1 C2/3/104
    dev.cpu.0.freq_levels: 2501/35000 2500/35000 2200/29755 2000/26426 1800/23233 1600/20164 1400/17226 1200/14408 1000/11713 800/9140
    dev.cpu.0.freq: 800
    dev.cpu.0.%parent: acpi0
    dev.cpu.0.%pnpinfo: _HID=none _UID=0
    dev.cpu.0.%location: handle=\_PR_.CPU0
    dev.cpu.0.%driver: cpu
    dev.cpu.0.%desc: ACPI CPU
    % sysctl hw.acpi.thermal.tz0.temperature
    hw.acpi.thermal.tz0.temperature: 49.1C
    % grep FreeBSD/SMP /var/run/dmesg.boot
    FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs
    FreeBSD/SMP: 1 package(s) x 2 core(s)
    
    % sysctl kern.smp.cpus
    kern.smp.cpus: 2
    % sysctl -d dev.cpu.0.freq
    dev.cpu.0.freq: Current CPU frequency
    # pkg install lscpu
    # kldload cpuctl
    # lscpu
    Architecture:            amd64
    Byte Order:              Little Endian
    Total CPU(s):            2
    Thread(s) per core:      2
    Core(s) per socket:      2
    Socket(s):               0
    Vendor:                  GenuineIntel
    CPU family:              6
    Model:                   42
    Model name:              Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz
    Stepping:                7
    L1d cache:               32K
    L1i cache:               32K
    L2 cache:                256K
    L3 cache:                3M
    Flags:                   fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 cflsh ds acpi mmx fxsr sse sse2 ss htt tm pbe sse3 pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline aes xsave osxsave avx syscall nx rdtscp lm lahf_lm
    % grep CPU /var/run/dmesg.boot
    CPU: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz (2491.97-MHz K8-class CPU)
    FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs
    cpu0:  on acpi0
    coretemp0:  on cpu0
    powerd_enable=YES
    powerd_flags="-n adaptive -a hiadaptive -b adaptive -m 800 -M 1600"
    # pkg install powerdxx
    powerdxx_enable=YES
    powerdxx_flags="-n adaptive -a hiadaptive -b adaptive -m 800 -M 1600"
    % tail -f /var/log/messages
    Nov 28 13:14:42 t420s power_profile[48231]: changed to 'economy'
    Nov 28 13:14:46 t420s power_profile[56835]: changed to 'performance'
    performance_cx_lowest=C1
    economy_cx_lowest=Cmax
    % sysctl dev.cpu.0.cx_supported
    dev.cpu.0.cx_supported: C1/1/1 C2/3/104
    % grep cx_lowest /etc/sysctl.conf
    dev.cpu.0.cx_lowest=C1
    dev.cpu.1.cx_lowest=C3
    dev.cpu.2.cx_lowest=C3
    dev.cpu.3.cx_lowest=C3
    % sysctl dev.cpu.0.freq_levels 
    dev.cpu.0.freq_levels: 2501/35000 2500/35000 2200/29755 2000/26426 1800/23233 1600/20164 1400/17226 1200/14408 1000/11713 800/9140
    # sysctl dev.cpu.0.freq=2501/35000
    sysctl: invalid integer '2501/35000'
    # sysctl dev.cpu.0.freq=2501
    dev.cpu.0.freq: 800 -> 2501
    % usbconfig
    ugen1.1:  at usbus1, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
    ugen2.1:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen0.1:  at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen2.2:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen0.2:  at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    ugen0.3:  at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
    ugen2.3:  at usbus2, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
    # usbconfig -u 1 -a 1 power_save
    % grep -A 10 POWER /etc/rc.local
    # POWER SAVE USB DEVICES
    usbconfig \
      | grep -v 'Lenovo USB Receiver' \
      | grep -v 'Unifying Receiver Logitech' \
      | awk '{print $1}' \
      | sed 's|ugen||'g \
      | tr -d : \
      | awk -F '.' '{print $1 " " $2 }' \
      | while read U A
        do
          usbconfig -u ${U} -a ${A} power_save 2> /dev/null
        done
    % grep ahcich /var/run/dmesg.boot
    ahcich0:  at channel 0 on ahci0
    ahcich1:  at channel 1 on ahci0
    ahcich4:  at channel 4 on ahci0
    ada0 at ahcich0 bus 0 scbus0 target 0 lun 0
      hint.ahcich.X.pm_level
    
        controls SATA interface Power Management for the specified channel,
        allowing some power to be saved at the cost of additional command latency.
    
        Some controllers, such as ICH8, do not implement modes 2 and 3 with NCQ
        used. Because of artificial entering latency, performance degradation in
        modes 4 and 5 is much smaller then in modes 2 and 3.
    
    控制指定通道的 SATA 接口电源管理,可以在牺牲额外命令延迟的情况下节省一些电量。
    一些控制器(例如 ICH8)在用 NCQ 时不支持模式 2 和 3。
    由于人工进入延迟,模式 4 和 5 的性能下降远小于模式 2 和 3。
    
    # AHCI POWER MANAGEMENT FOR EVERY USED CHANNEL (ahcich 0-7)
      hint.ahcich.0.pm_level=5
      hint.ahcich.1.pm_level=5
      hint.ahcich.2.pm_level=5
      hint.ahcich.3.pm_level=5
      hint.ahcich.4.pm_level=5
      hint.ahcich.5.pm_level=5
      hint.ahcich.6.pm_level=5
      hint.ahcich.7.pm_level=5
      hw.pci.do_power_nodriver (Defaults to 0)
    
        Place devices into a low power state (D3) when
        a suitable device driver is not found.
    
    当未找到合适的设备驱动时,将设备置于低功耗状态(D3)。
    # POWER OFF DEVICES WITHOUT ATTACHED DRIVER
      hw.pci.do_power_nodriver=3
    % pciconf -l
    hostb0@pci0:0:0:0:      class=0x060000 card=0x21d217aa chip=0x01048086 rev=0x09 hdr=0x00
    vgapci0@pci0:0:2:0:     class=0x030000 card=0x21d217aa chip=0x01268086 rev=0x09 hdr=0x00
    none0@pci0:0:22:0:      class=0x078000 card=0x21d217aa chip=0x1c3a8086 rev=0x04 hdr=0x00
    em0@pci0:0:25:0:        class=0x020000 card=0x21ce17aa chip=0x15028086 rev=0x04 hdr=0x00
    ehci0@pci0:0:26:0:      class=0x0c0320 card=0x21d217aa chip=0x1c2d8086 rev=0x04 hdr=0x00
    hdac0@pci0:0:27:0:      class=0x040300 card=0x21d217aa chip=0x1c208086 rev=0x04 hdr=0x00
    pcib1@pci0:0:28:0:      class=0x060400 card=0x21d217aa chip=0x1c108086 rev=0xb4 hdr=0x01
    pcib2@pci0:0:28:1:      class=0x060400 card=0x21d217aa chip=0x1c128086 rev=0xb4 hdr=0x01
    pcib3@pci0:0:28:3:      class=0x060400 card=0x21d217aa chip=0x1c168086 rev=0xb4 hdr=0x01
    pcib4@pci0:0:28:4:      class=0x060400 card=0x21d217aa chip=0x1c188086 rev=0xb4 hdr=0x01
    ehci1@pci0:0:29:0:      class=0x0c0320 card=0x21d217aa chip=0x1c268086 rev=0x04 hdr=0x00
    isab0@pci0:0:31:0:      class=0x060100 card=0x21d217aa chip=0x1c4f8086 rev=0x04 hdr=0x00
    ahci0@pci0:0:31:2:      class=0x010601 card=0x21d217aa chip=0x1c038086 rev=0x04 hdr=0x00
    ichsmb0@pci0:0:31:3:    class=0x0c0500 card=0x21d217aa chip=0x1c228086 rev=0x04 hdr=0x00
    iwn0@pci0:3:0:0:        class=0x028000 card=0x11118086 chip=0x42388086 rev=0x3e hdr=0x00
    sdhci_pci0@pci0:5:0:0:  class=0x088000 card=0x21d217aa chip=0xe8221180 rev=0x07 hdr=0x00
    xhci0@pci0:13:0:0:      class=0x0c0330 card=0x01941033 chip=0x01941033 rev=0x04 hdr=0x00
    % pciconf -l -v
    (...)
    xhci0@pci0:13:0:0:      class=0x0c0330 card=0x01941033 chip=0x01941033 rev=0x04 hdr=0x00
        vendor     = 'NEC Corporation'
        device     = 'uPD720200 USB 3.0 Host Controller'
        class      = serial bus
        subclass   = USB
    # mkdir /root/bin
    # cd /root/bin
    # fetch https://people.freebsd.org/~xmj/turn_off_gpu.sh
    # pkg install acpi_call
    # kldload acpi_call
    # chmod +x /root/bin/turn_off_gpu.sh
    # /root/bin/turn_off_gpu.sh
    # DISABLE NVIDIA CARD
      /root/bin/turn_off_gpu.sh
    % sysctl hw.acpi.supported_sleep_state
    hw.acpi.supported_sleep_state: S3 S4 S5
    # zzz
    # acpiconf -s 3
    # kldload acpi_ibm
    % sysctl dev.acpi_ibm
    dev.acpi_ibm.0.handlerevents: NONE
    dev.acpi_ibm.0.mic_led: 0
    dev.acpi_ibm.0.fan: 0
    dev.acpi_ibm.0.fan_level: 0
    dev.acpi_ibm.0.fan_speed: 0
    dev.acpi_ibm.0.wlan: 1
    dev.acpi_ibm.0.bluetooth: 0
    dev.acpi_ibm.0.thinklight: 0
    dev.acpi_ibm.0.mute: 0
    dev.acpi_ibm.0.volume: 0
    dev.acpi_ibm.0.lcd_brightness: 0
    dev.acpi_ibm.0.hotkey: 1425
    dev.acpi_ibm.0.eventmask: 134217727
    dev.acpi_ibm.0.events: 1
    dev.acpi_ibm.0.availmask: 134217727
    dev.acpi_ibm.0.initialmask: 2060
    dev.acpi_ibm.0.%parent: acpi0
    dev.acpi_ibm.0.%pnpinfo: _HID=LEN0068 _UID=0
    dev.acpi_ibm.0.%location: handle=\_SB_.PCI0.LPC_.EC__.HKEY
    dev.acpi_ibm.0.%driver: acpi_ibm
    dev.acpi_ibm.0.%desc: IBM ThinkPad ACPI Extras
    dev.acpi_ibm.%parent:
    #! /bin/sh
    
    if ! kldstat | grep -q acpi_ibm.ko
    then
      doas kldload acpi_ibm
    fi
    
    doas sysctl dev.acpi_ibm.0.fan=0 1> /dev/null 
    
    TEMP=$( sysctl -n hw.acpi.thermal.tz0.temperature | awk -F'.' '{print $1}' )
    
    if [ ${TEMP} -lt 50 ]
    then
      doas sysctl dev.acpi_ibm.0.fan_level=0 1> /dev/null
      exit 0
    fi
    
    if [ ${TEMP} -lt 60 ]
    then
      doas sysctl dev.acpi_ibm.0.fan_level=1 1> /dev/null
      exit 0
    fi
    
    if [ ${TEMP} -ge 60 ]
    then
      doas sysctl dev.acpi_ibm.0.fan_level=3 1> /dev/null
      exit 0
    fi
    % crontab -l
    # ACPI/IBM/FAN
    * * * * * ~/scripts/acpi-thinkpad-fan.sh
    # ifconfig wlan0 powersave
    # pkg install powermon
    # kldload cpuctl
    # powermon
                      Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz
                          (Arch: Sandy Bridge, Limit: 44W)
    
    
    
       5.11W [=======>                                                           ]
    
    
    
     Package:           Uncore:             x86 Cores:          GPU:
     Current: 5.11W     Current: 3.17W      Current: 1.73W      Current: 0.21W
     Total: 98.33J      Total: 60.86J       Total: 33.49J       Total: 3.98J
    # pkg install dtrace-toolkit
    # /usr/local/share/dtrace-toolkit/execsnoop 
      UID    PID   PPID ARGS
     1000  97748  97509 /usr/local/bin/zsh -c ~/scripts/dzen2-update.sh > ~/.dzen2-fifo
     1000  97748      1 /bin/sh /home/vermaden/scripts/dzen2-update.sh
     1000  99157  97748 sysctl -n kern.smp.cpus
     1000    311  97748 ps ax -o %cpu,rss,command -c
     1000   3118   1521 awk -v SMP=200 /\ idle$/ {printf("%.1f%%",SMP-$1)}
     1000   4462  97748 date +%Y/%m/%d/%a/%H:%M
     1000   4801  97748 sysctl -n dev.cpu.0.freq
     1000   6009  97748 sysctl -n hw.acpi.thermal.tz0.temperature
     1000   6728  97748 sysctl -n vm.stats.vm.v_inactive_count
     1000   7043  97748 sysctl -n vm.stats.vm.v_free_count
     1000   7482  97748 sysctl -n vm.stats.vm.v_cache_count
     1000  10363   8568 bc -l
     1000  10863  10363 dc -x
     1000  13143   7773 grep --color -q ^\.
     1000  13798  97748 /bin/sh /home/vermaden/scripts/__conky_if_ip.sh
     1000  15089  14235 ifconfig -u
     1000  16439  14235 grep -v 127.0.0.1
     1000  17738  14235 grep -c inet 
     1000  19069  18612 ifconfig -l -u
     1000  19927  18612 sed s/lo0//g
     1000  20772  13798 ifconfig wlan0
     1000  23388  21410 grep ssid
     1000  24588  13798 grep -q "
     1000  25965  25282 awk /ssid/ {print $2}
     1000  27917  27217 awk /inet / {print $2}
     1000  29941  97748 /bin/sh /home/vermaden/scripts/__conky_if_gw.sh
     1000  32808  31412 route -n -4 -v get default
     1000  34012  31412 awk END{print $2}
     1000  34895  97748 /bin/sh /home/vermaden/scripts/__conky_if_dns.sh
     1000  36118  34895 awk /^nameserver/ {print $2; exit} /etc/resolv.conf
     1000  37628  97748 /bin/sh /home/vermaden/scripts/__conky_if_ping.sh dzen2
     1000  38829  37628 ping -c 1 -s 0 -t 1 -q 9.9.9.9
     1000  42079  41566 mixer -s vol
     1000  42177  41566 awk -F : {printf("%s",$2)}
     1000  44434  43254 zfs list -H -d 0 -o name,avail
     1000  45866  43254 awk {printf("%s/%s ",$1,$2)}
     1000  47004  97748 /bin/sh /home/vermaden/scripts/__conky_battery_separate.sh dzen2
     1000  48282  47004 sysctl -n hw.acpi.battery.units
     1000  49494  47004 sysctl -n hw.acpi.battery.life
     1000  49948  47004 sysctl -n hw.acpi.acline
     1000  52073  51441 acpiconf -i 0
     1000  53055  51441 awk /^State:/ {print $2}
     1000  53981  53186 acpiconf -i 0
     1000  55354  53186 awk /^Remaining capacity:/ {print $3}
     1000  55968  55631 acpiconf -i 1
     1000  57187  55631 awk /^State:/ {print $2}
     1000  58405  57471 acpiconf -i 1
     1000  59201  57471 awk /^Remaining capacity:/ {print $3}
     1000  60961  59252 bsdgrep -v -E (COMMAND|idle)$
     1000  63534  59252 head -3
     1000  62194  59252 sort -r -n
     1000  64629  59252 awk {printf("%s/%d%%/%.1fGB ",$3,$1,$2/1024/1024)}
     1000  64634  93198 tail -1 /home/vermaden/.dzen2-fifo
    # 使用 graphics/drm-kmod 包的 INTEL DRM(新)
    # 启动时跳过不必要的模式设置
      compat.linuxkpi.fastboot=1
    # 使用信号量进行环间同步
      compat.linuxkpi.semaphores=1
    # 启用渲染 C 状态 6 节能
      compat.linuxkpi.enable_rc6=7
    # 启用显示 C 状态节能
      compat.linuxkpi.enable_dc=2
    # 启用帧缓冲压缩以节能
      compat.linuxkpi.enable_fbc=1
    # 使用 graphics/drm-kmod 包的 INTEL DRM(旧)
      drm.i915.enable_rc6=7
      drm.i915.semaphores=1
      drm.i915.intel_iommu_enabled=1
    machdep.hwpstate_pkg_ctrl=0
    dev.hwpstate_intel.N.epp=Y
    dev.hwpstate_intel.0.epp=100
    dev.hwpstate_intel.1.epp=100
    dev.hwpstate_intel.2.epp=100
    dev.hwpstate_intel.3.epp=100
    dev.hwpstate_intel.4.epp=100
    dev.hwpstate_intel.5.epp=100
    dev.hwpstate_intel.6.epp=100
    dev.hwpstate_intel.7.epp=100
    dev.hwpstate_intel.0.epp=0
    dev.hwpstate_intel.1.epp=50
    dev.hwpstate_intel.2.epp=100
    dev.hwpstate_intel.3.epp=100
    dev.hwpstate_intel.4.epp=100
    dev.hwpstate_intel.5.epp=100
    dev.hwpstate_intel.6.epp=100
    dev.hwpstate_intel.7.epp=100
    dev.hwpstate_intel.0.epp=0
    dev.hwpstate_intel.1.epp=0
    dev.hwpstate_intel.2.epp=0
    dev.hwpstate_intel.3.epp=0
    dev.hwpstate_intel.4.epp=0
    dev.hwpstate_intel.5.epp=0
    dev.hwpstate_intel.6.epp=0
    dev.hwpstate_intel.7.epp=0
    #! /bin/sh
    
    case $( sysctl -n hw.acpi.acline ) in
    
      (0) # BATTERY
        doas sysctl dev.hwpstate_intel.0.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.1.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.2.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.3.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.4.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.5.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.6.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.7.epp=100 1> /dev/null 2> /dev/null
        ;;
    
      (1) # AC
        doas sysctl dev.hwpstate_intel.0.epp=0   1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.1.epp=50  1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.2.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.3.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.4.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.5.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.6.epp=100 1> /dev/null 2> /dev/null
        doas sysctl dev.hwpstate_intel.7.epp=100 1> /dev/null 2> /dev/null
        ;;
    
    esac
    % crontab -l
    # INTEL/SPEED/SHIFT
      * * * * * ~/scripts/acpi-intel-speed-shift.sh
    https://man.freebsd.org/portmaster
    https://man.freebsd.org/beadm
  • https://man.freebsd.org/bectl

  • https://wiki.freebsd.org/Sound
    https://man.freebsd.org/jls
  • https://man.freebsd.org/jexec

  • https://bastillebsd.org

  • https://web.archive.org/web/20170126214625/http://ivoras.sharanet.org/blog/tree/2009-10-20.the-night-of-1000-jails.html

  • https://forums.freebsd.org/threads/setting-up-a-debian-linux-jail-on-freebsd.68434/

  • https://freshports.org/
  • https://repology.org/repositories/statistics/newest

  • https://man.freebsd.org/src.conf
    https://freebsd.org/handbook/filesystems.html
  • https://man.freebsd.org/geom

  • https://man.freebsd.org/geli

  • https://man.freebsd.org/fusefs

  • https://man.freebsd.org/newfs

  • https://man.freebsd.org/hast.conf

  • https://man.freebsd.org/rc.local

    bpf

  • configfs

  • selinuxfs

  • systemd-1

  • mqueue

  • debugfs

  • hugetlbfs

  • FreeBSD Device Drivers(2012)

  • FreeBSD Mastery – ZFS(2015)

  • FreeBSD Mastery – Advanced ZFS(2016)

  • FreeBSD Mastery – Storage Essentials(2014)

  • FreeBSD Mastery – Specialty Filesystems(2015)

  • FreeBSD Mastery – Jails(2019)

  • https://www.over-yonder.net/~fullermd/rants/bsd4linux/03
    https://freebsd.org/handbook/dirstructure.html
    https://man.freebsd.org/hier
    https://man.freebsd.org/freebsd-version
    土拨鼠之日 (1993)
    https://is.gd/BECTL
    UFS 启动环境
    ARM 平台的 UFS 启动环境
    使用 ZFS 启动环境升级 FreeBSD
    https://man.freebsd.org/rescue
    https://docs.hetzner.com/robot/dedicated-server/operating-systems/freebsd-rescue-system/
    http://wiki.euserv.com/index.php/Manual_FreeBSD_Rescue_System/en
    meka
    https://freebsd.org/doc/en/books/arch-handbook/oss.html
    https://freebsd.org/handbook/sound-setup.html
    https://man.freebsd.org/sound
    https://papers.freebsd.org/2019/fosdem/mekic-audio_studio/
    操作系统级虚拟化
    base.txz
    BastilleBSD
    FreeBSD Jail 容器
    https://vermaden.wordpress.com/2023/06/28/freebsd-jails-containers/
    https://freebsd.org/handbook/jails.html
    https://man.freebsd.org/jail
    https://man.freebsd.org/jail.conf
    FreeBSD Bhyve Virtualization
    https://vermaden.wordpress.com/2023/08/18/freebsd-bhyve-virtualization/
    https://freebsd.org/handbook/virtualization-host-bhyve.html
    https://wiki.freebsd.org/bhyve
    https://man.freebsd.org/bhyve/8
    repology.org
    repology.org
    https://freshports.org/
    已经移除
    https://freebsd.org/handbook/ports-using.html
    https://freebsd.org/handbook/ports-poudriere.html
    https://man.freebsd.org/ports
    https://man.freebsd.org/build
    Build Your Own FreeBSD Update Server
    https://freebsd.org//handbook/kernelconfig.html
    https://freebsd.org/handbook/makeworld.html
    https://freebsd.org/doc/en/articles/freebsd-update-server/
    https://man.freebsd.org/build
    https://is.gd/bsdstg
    https://freebsd.org/handbook/disks.html
    https://freebsd.org/handbook/geom.html
    https://freebsd.org/handbook/zfs.html
    Practical rc.d Scripting in BSD
    https://freebsd.org/handbook/configtuning-rcd.html
    https://freebsd.org/doc/en/articles/rc-scripting/
    https://man.freebsd.org/rc
    https://man.freebsd.org/rc.conf
    FreeBSD 曾用于生成惊艳的特效
    黑客帝国 (1999)
    f.lux
    https://freebsd.org/handbook/linuxemu.html
    https://freebsd.org/handbook/linuxemu-lbc-install.html
    https://freebsd.org/doc/en/articles/linux-emulation/
    https://duck.com/?q=deprecated+linux+commands
    https://duck.com/?q=deprecated+linux+subsystems+-windows
    FreeBSD 手册
    FreeBSD FAQ
    FreeBSD 文章
    手册页
    FreeBSD Wiki
    FreeBSD 论坛
    邮件列表
    FreeBSD 书籍
    BSD Magazine
    FreeBSD 期刊
    For People New to Both FreeBSD and UNIX®
    FreeBSD Quickstart Guide for Linux® Users
    Explaining BSD
    Lobsters
    Hacker News
    Reddit
    groundhog
    rescue
    audio
    containers
    bhyve-logo
    packages
    repology
    ports-later
    code
    openzfs
    storage
    matrix
    evolution
    documentation

    在 FreeBSD 的 jail 中安装 NextCloud

    • 原文链接:https://github.com/possnfiffer/bsd-pw/blob/gh-pages/docs/Install_Nextcloud_on_FreeBSD_in_Jail.md

    • 作者:Roller Angel

    • 译者:飞鱼

    • 校对整理:ykla

    在我的实验室里,我的 OPNSense 防火墙同时也是我的 DHCP 服务器,默认网关设置为 172.16.28.1,而且它还充当我的 DNS

    在主机上运行:

    添加内容:

    运行以下命令:

    添加内容:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    使用 Poudriere 构建我们想要的 postgres

    在主机上运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    当 jail 启动后,用 nullfs 将 Poudriere 软件包仓库挂载到 jail 内

    运行以下命令:

    这个 fstab 的东西不起作用......以后会研究的,现在运行 fstab 之后的 mount -t 命令。

    添加以下内容:

    使用 mount 命令来代替 fstab(这是一个手动命令,不会自动运行)。

    运行以下命令:

    在 jail 中创建一个 pkg 仓库:

    禁止 FreeBSD 中 pkg 包管理器的系统级源

    将 enabled 选项改成 no:

    创建一个替换 FreeBSD.conf 的源配置文件:

    添加以下配置:

    用新的源来重新安装所有的包:

    运行以下命令:

    升级 Poudriere

    在主机上运行以下命令:

    从 jail 更新

    设置 PostgreSQL

    我确定我开启了 poudriere options 参数,并在 nextcloud 上启用了 memcached 支持,稍后我将把它添加到 make.conf 文件中

    在 jail 中运行以下命令:

    将以下设置添加到文件的末尾:

    运行以下命令:

    : 更新配置:

    运行以下命令:

    在 IPv4 部分添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    Nginx

    在 jail 中运行以下命令:

    输入 server.key 的密码短语:

    使用你的最佳判断来填写密码提示后的提示信息。

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    运行以下命令:

    添加以下配置:

    再次升级 rc.conf 文件:

    更新这些行,使其看起来像:

    Memcached

    在 jail 中运行以下命令:

    在主机上用火狐浏览器打开网址 https://172.16.28.2

    在 jail 上运行以下命令:

    将以下配置添加到文件的末尾:

    FreeBSD # ls -lh /rescue | head -5
    total 1118446
    -r-xr-xr-x  146 root  wheel    11M 2020.02.19 21:10 [
    -r-xr-xr-x  146 root  wheel    11M 2020.02.19 21:10 bectl
    -r-xr-xr-x  146 root  wheel    11M 2020.02.19 21:10 bsdlabel
    -r-xr-xr-x  146 root  wheel    11M 2020.02.19 21:10 bunzip2
    FreeBSD # ls /rescue
    [           dd               fsck_ffs      init       mdmfs          ping      rtsol        unlink
    bectl       devfs            fsck_msdosfs  ipf        mkdir          ping6     savecore     unlzma
    bsdlabel    df               fsck_ufs      iscsictl   mknod          pkill     sed          unxz
    bunzip2     dhclient         fsdb          iscsid     more           poweroff  setfacl      unzstd
    bzcat       dhclient-script  fsirand       kenv       mount          ps        sh           vi
    bzip2       disklabel        gbde          kill       mount_cd9660   pwd       shutdown     whoami
    camcontrol  dmesg            geom          kldconfig  mount_msdosfs  rcorder   sleep        xz
    cat         dump             getfacl       kldload    mount_nfs      rdump     spppcontrol  xzcat
    ccdconfig   dumpfs           glabel        kldstat    mount_nullfs   realpath  stty         zcat
    chflags     dumpon           gpart         kldunload  mount_udf      reboot    swapon       zdb
    chgrp       echo             groups        ldconfig   mount_unionfs  red       sync         zfs
    chio        ed               gunzip        less       mt             rescue    sysctl       zpool
    chmod       ex               gzcat         link       mv             restore   tail         zstd
    chown       expr             gzip          ln         nc             rm        tar          zstdcat
    chroot      fastboot         halt          ls         newfs          rmdir     tcsh         zstdmt
    clri        fasthalt         head          lzcat      newfs_msdos    route     tee          
    cp          fdisk            hostname      lzma       nextboot       routed    test         
    csh         fsck             id            md5        nos-tun        rrestore  tunefs       
    date        fsck_4.2bsd      ifconfig      mdconfig   pgrep          rtquery   umount
    FreeBSD # mkdir -p /jail/nextcloud
    FreeBSD # fetch -o - http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/12.1-RELEASE/base.txz | tar --unlink -xpJf - -C /jail/nextcloud
    FreeBSD # cat /etc/jail.conf
    nextcloud {
      host.hostname = nextcloud.local;
      ip4.addr = 10.0.0.100;
      path = /jail/nextcloud;
    }
    FreeBSD # service jail onestart nextcloud
    Starting jails: nextcloud.
    FreeBSD # jls
       JID  IP Address      Hostname                      Path
         1  10.0.0.100      nextcloud.local               /jail/nextcloud
    Linux # grep -c '^CONFIG' /boot/config-$( uname -r )
    4432
    
    FreeBSD # grep -c -E '^(device|options)' /usr/src/sys/amd64/conf/GENERIC
    260
    
    FreeBSD # grep -c -E '^(device|options)' /usr/src/sys/amd64/conf/MINIMAL
    75
    FreeBSD # beadm create safe
    FreeBSD # cd /usr/src
    FreeBSD # make buildworld kernel
    FreeBSD # reboot
    FreeBSD # cd /usr/src
    FreeBSD # etcupdate -p      # // 以前是: mergemaster -p
    FreeBSD # make installworld
    FreeBSD # etcupdate -B      # // 以前是: mergemaster -iU
    FreeBSD # reboot
    FreeBSD # zgrep -c WITHOUT_ /usr/share/man/man5/src.conf.5.gz
    294
    
    FreeBSD # zgrep -c WITH_ /usr/share/man/man5/src.conf.5.gz
    125
    FreeBSD # rcorder /etc/rc.d/* | head
    /etc/rc.d/growfs
    /etc/rc.d/sysctl
    /etc/rc.d/hostid
    /etc/rc.d/zvol
    /etc/rc.d/dumpon
    /etc/rc.d/ddb
    /etc/rc.d/geli
    /etc/rc.d/gbde
    /etc/rc.d/ccd
    /etc/rc.d/swap
    
    FreeBSD # rcorder /usr/local/etc/rc.d/* | tail
    /usr/local/etc/rc.d/hald
    /usr/local/etc/rc.d/git_daemon
    /usr/local/etc/rc.d/fscd
    /usr/local/etc/rc.d/cupsd
    /usr/local/etc/rc.d/cups_browsed
    /usr/local/etc/rc.d/clamav-clamd
    /usr/local/etc/rc.d/clamav-milter
    /usr/local/etc/rc.d/clamav-freshclam
    /usr/local/etc/rc.d/avahi-dnsconfd
    /usr/local/etc/rc.d/aria2
    
    FreeBSD # rcorder /etc/rc.d/* /usr/local/etc/rc.d/* 2> | grep -C 3 sshd
    /etc/rc.d/ubthidhci
    /etc/rc.d/syscons
    /etc/rc.d/swaplate
    /etc/rc.d/sshd
    /etc/rc.d/cron
    /etc/rc.d/jail
    /etc/rc.d/localpkg
    #!/bin/sh
    
    . /etc/rc.subr
    
    name=dummy
    rcvar=dummy_enable
    
    start_cmd="${name}_start"
    stop_cmd=":"
    
    load_rc_config $name
    : ${dummy_enable:=no}
    : ${dummy_msg="Nothing started."}
    
    dummy_start()
    {
    	echo "$dummy_msg"
    }
    
    run_rc_command "$1"
    FreeBSD # mount
    zroot/ROOT/12.1 on / (zfs, local, noatime, nfsv4acls)
    devfs on /dev (devfs, local, multilabel)
    zroot/tmp on /tmp (zfs, local, noatime, nosuid, nfsv4acls)
    zroot/var/mail on /var/mail (zfs, local, nfsv4acls)
    zroot/usr/home on /usr/home (zfs, local, noatime, nfsv4acls)
    zroot/var/crash on /var/crash (zfs, local, noatime, noexec, nosuid, nfsv4acls)
    zroot/var/log on /var/log (zfs, local, noatime, noexec, nosuid, nfsv4acls)
    zroot/var/audit on /var/audit (zfs, local, noatime, noexec, nosuid, nfsv4acls)
    zroot/var/tmp on /var/tmp (zfs, local, noatime, nosuid, nfsv4acls)
    zroot/usr/src on /usr/src (zfs, local, noatime, nfsv4acls)
    zroot/usr/ports on /usr/ports (zfs, local, noatime, nosuid, nfsv4acls)
    [root@centos8 ~]# mount
    sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
    proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
    devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=919388k,nr_inodes=229847,mode=755)
    securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
    tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,seclabel)
    devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,seclabel,gid=5,mode=620,ptmxmode=000)
    tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,mode=755)
    tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,mode=755)
    cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
    pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime,seclabel)
    bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
    cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
    cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
    cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
    cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
    cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_cls,net_prio)
    cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpu,cpuacct)
    cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
    cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
    cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,rdma)
    cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
    cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
    configfs on /sys/kernel/config type configfs (rw,relatime)
    /dev/sda1 on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
    selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)
    systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=34,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=17309)
    mqueue on /dev/mqueue type mqueue (rw,relatime,seclabel)
    debugfs on /sys/kernel/debug type debugfs (rw,relatime,seclabel)
    hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel,pagesize=2M)
    tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=187088k,mode=700)
    
    [root@centos8 ~]# mount | awk '{print $5}' | sort -u
    autofs
    bpf
    cgroup
    configfs
    debugfs
    devpts
    devtmpfs
    hugetlbfs
    mqueue
    proc
    pstore
    securityfs
    selinuxfs
    sysfs
    tmpfs
    xfs
    [root@centos7 ~]# mount -t xfs
    /dev/sda1 on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)
    [root@centos7 ~]# ls -1 /etc/sysconfig/network-scripts/ifcfg-*
    ifcfg-Bond_connection_1
    ifcfg-eno49
    ifcfg-eno49-1
    ifcfg-eno50
    ifcfg-eno50-1
    ifcfg-VLAN_connection_1
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-Bond_connection_1
    DEVICE=bond0
    BONDING_OPTS="miimon=1 updelay=0 downdelay=0 mode=active-backup"
    TYPE=Bond
    BONDING_MASTER=yes
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=dhcp
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_PRIVACY=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME="Bond connection 1"
    UUID=ca85417f-8852-43bf-96ee-5bd3f0f83648
    ONBOOT=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno49
    TYPE=Ethernet
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=dhcp
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME=eno49
    UUID=2f60f50b-38ad-492a-b90a-ba736acf6792
    DEVICE=eno49
    ONBOOT=no
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno49-1
    HWADDR=xx:xx:xx:xx:xx:xx
    TYPE=Ethernet
    NAME=eno49
    UUID=342b8494-126d-4f3a-b749-694c8c922aa1
    DEVICE=eno49
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno50
    TYPE=Ethernet
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=dhcp
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME=eno50
    UUID=4fd36e24-1c6d-4a65-a316-7a14e9a92965
    DEVICE=eno50
    ONBOOT=no
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno50-1
    HWADDR=xx:xx:xx:xx:xx:xx
    TYPE=Ethernet
    NAME=eno50
    UUID=a429b697-73c2-404d-9379-472cb3c35e06
    DEVICE=eno50
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-VLAN_connection_1
    VLAN=yes
    TYPE=Vlan
    PHYSDEV=ca85417f-8852-43bf-96ee-5bd3f0f83648
    VLAN_ID=601
    REORDER_HDR=yes
    GVRP=no
    MVRP=no
    PROXY_METHOD=none
    BROWSER_ONLY=no
    BOOTPROTO=none
    IPADDR=10.20.30.40
    PREFIX=24
    GATEWAY=10.20.30.1
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6INIT=yes
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    IPV6_PRIVACY=no
    IPV6_ADDR_GEN_MODE=stable-privacy
    NAME="VLAN connection 1"
    UUID=90f7a9bb-1443-4adf-a3eb-86a03b23ecfb
    ONBOOT=yes
    [root@centos7 ~]# cat /etc/sysconfig/network
    GATEWAY=10.20.30.1
    NOZEROCONF=yes
    
    [root@centos7 ~]# ls -1 /etc/sysconfig/network-scripts/ifcfg-*
    ifcfg-bond0
    ifcfg-bond0.601
    ifcfg-eno49
    ifcfg-eno50
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-bond0
    DEVICE=bond0
    BONDING_OPTS="miimon=1 updelay=0 downdelay=0 mode=active-backup"
    TYPE=Bond
    BONDING_MASTER=yes
    BOOTPROTO=none
    IPV4_FAILURE_FATAL=no
    IPV6INIT=no
    ONBOOT=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-bond0.601
    VLAN=yes
    TYPE=Vlan
    VLAN_ID=601
    DEVICE=bond0.601
    REORDER_HDR=yes
    GVRP=no
    MVRP=no
    BOOTPROTO=none
    IPADDR=10.20.30.40
    PREFIX=24
    IPV4_FAILURE_FATAL=no
    IPV6INIT=no
    ONBOOT=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno49
    BOOTPROTO=none
    IPV4_FAILURE_FATAL=no
    IPV6INIT=no
    TYPE=Ethernet
    NAME=eno49
    DEVICE=eno49
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    
    [root@centos7 ~]# cat /etc/sysconfig/network-scripts/ifcfg-eno50
    BOOTPROTO=none
    IPV4_FAILURE_FATAL=no
    IPV6INIT=no
    TYPE=Ethernet
    NAME=eno50
    DEVICE=eno50
    ONBOOT=yes
    MASTER=bond0
    SLAVE=yes
    FreeBSD # cat /etc/rc.conf
    ifconfig_fxp0="up"
    ifconfig_fxp1="up"
    cloned_interfaces="lagg0"
    ifconfig_lagg0="laggproto failover laggport fxp0 laggport fxp1"
    vlans_lagg0="601"
    ifconfig_lagg0_601="inet 10.20.30.40/24"
    defaultrouter="10.20.30.1"
    vi /etc/sysctl.conf
    # Allow jail raw sockets
    security.jail.allow_raw_sockets=1
    
    # Allow upgrades in jail
    security.jail.chflags_allowed=1
    sysctl security.jail.allow_raw_sockets=1
    sysctl security.jail.chflags_allowed=1
    vi /boot/loader.conf
    # RACCT/RCTL Resource limits
    kern.racct.enable=1
    zfs create -o mountpoint=/jail zroot/jail
    zfs create -o mountpoint=/jail/nextcloud zroot/jail/nextcloud
    zfs create -o mountpoint=/jail/nextcloud/var/db/postgres/data -o recordsize=8k zroot/jail/nextcloud/pgsql
    zfs get -r recordsize zroot/jail
    fetch -o - http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/12.0-RELEASE/base.txz | tar --unlink -xpJf - -C /jail/nextcloud
    ls /jail/nextcloud
    vi /etc/jail.conf
    nextcloud {
      host.hostname = nextcloud.lab.bsd.pw;
      ip4.addr = 172.16.28.2;
      interface = em0;
      path = /jail/nextcloud;
      exec.start = "/bin/sh /etc/rc";
      exec.stop = "/bin/sh /etc/rc.shutdown";
      exec.clean;
      mount.devfs;
      allow.raw_sockets;
      sysvsem = new;
      sysvshm = new;
      sysvmsg = new;
    }
    sysrc jail_enable=YES
    sysrc jail_nextcloud_mount_enable=YES
    vi /etc/hosts
    172.16.28.2 nextcloud.lab.bsd.pw nextcloud
    service jail restart nextcloud
    jexec 1 tcsh
    vi /etc/hosts
    172.16.28.2 nextcloud.lab.bsd.pw nextcloud
    jexec 1 tcsh
    newaliases -v
    cp /usr/share/zoneinfo/America/Denver /etc/localtime
    vi /etc/rc.conf
    # DAEMONS | yes
    syslogd_flags="-s -s"
    sshd_enable=YES
    # php_fpm_enable=YES
    # postgresql_enable=YES
    # postgresql_class=postgres
    # postgresql_data=/var/db/postgres/data
    # memcached_enable=YES
    # memcached_flags="-l 172.16.28.2"
    # nginx_enable=YES
    
    # DAEMONS | no
    sendmail_enable=NONE
    sendmail_submit_enable=NO
    sendmail_outbound_enable=NO
    sendmail_msp_queue_enable=NO
    
    # OTHER
    clear_tmp_enable=YES
    clear_tmp_X=YES
    extra_netfs_types=NFS
    dumpdev=NO
    update_motd=NO
    keyrate=fast
    vi /etc/cron.d/sendmail-clean-clientmqueue
    # CLEAN SENDMAIL
    0 * * * * root /bin/rm -r -f /var/spool/clientmqueue/*
    exit
    service jail restart nextcloud
    jls
    jexec nextcloud tcsh
    sockstat -l4
    vi /etc/resolv.conf
    nameserver 172.16.28.1
    ping -c 3 bsd.pw
    exit
    pkg install -y poudriere
    vi nextcloudpkglist
    www/nextcloud
    www/nginx
    databases/memcached
    security/sudo
    databases/postgresql10-server
    www/php72-opcache
    devel/php72-intl
    mail/cclient
    mail/php72-imap
    math/php72-gmp
    ftp/php72-ftp
    vi /usr/local/etc/poudriere.d/amd64-12-0-make.conf
    DEFAULT_VERSIONS += php=7.2
    DEFAULT_VERSIONS += pgsql=10
    OPTIONS_UNSET += MYSQL
    OPTIONS_SET += PGSQL
    poudriere bulk -j amd64-12-0 -p head -f nextcloudpkglist
    service jail start nextcloud
    jexec nextcloud tcsh
    mkdir /mnt/amd64-12-0-head
    exit
    vi /etc/fstab.nextcloud
    /usr/local/poudriere/data/packages/amd64-12-0-head    /mnt/amd64-12-0-head    nullfs    rw    0    0
    mount -t nullfs /usr/local/poudriere/data/packages/amd64-12-0-head /jail/nextcloud/mnt/amd64-12-0-head
    service jail restart nextcloud
    jexec nextcloud tcsh
    mkdir -p /usr/local/etc/pkg/repos
    vi /etc/pkg/FreeBSD.conf
    FreeBSD: {
        enabled: no
    }
    vi /usr/local/etc/pkg/repos/amd64-12-0.conf
    amd64-12-0: {
        url: “file:///mnt/amd64-12-0-head”,
        enabled: yes,
    }
    pkg upgrade -fy
    pkg install -y www/nextcloud www/nginx databases/memcached security/sudo databases/postgresql10-server www/php72-opcache devel/php72-intl mail/cclient mail/php72-imap math/php72-gmp ftp/php72-ftp
    vi /usr/local/etc/poudriere.conf
    CHECK_CHANGED_OPTIONS=verbose
    CHECK_CHANGED_DEPS=yes
    poudriere jail -j amd64-12-0 -u
    poudriere ports -p head -u
    poudriere bulk -j amd64-12-0 -p head -f nextcloudpkglist
    jexec nextcloud tcsh
    pkg update && pkg upgrade -y
    vi /etc/login.conf
    postgres:\
            :lang=en_US.UTF-8:\
            :setenv=LC_COLLATE=C:\
            :tc=default:
    cap_mkdb /etc/login.conf
    exit
    service jail restart nextcloud
    jexec nextcloud tcsh
    chown postgres:postgres /var/db/postgres/data
    vi /etc/rc.conf
    # DAEMONS | yes
    syslogd_flags="-s -s"
    sshd_enable=YES
    # php_fpm_enable=YES
    postgresql_enable=YES
    postgresql_class=postgres
    postgresql_data=/var/db/postgres/data
    # memcached_enable=YES
    # memcached_flags="-l 172.16.28.2"
    # nginx_enable=YES
    
    # DAEMONS | no
    sendmail_enable=NONE
    sendmail_submit_enable=NO
    sendmail_outbound_enable=NO
    sendmail_msp_queue_enable=NO
    
    # OTHER
    clear_tmp_enable=YES
    clear_tmp_X=YES
    extra_netfs_types=NFS
    dumpdev=NO
    update_motd=NO
    keyrate=fast
    /usr/local/etc/rc.d/postgresql initdb
    /usr/local/etc/rc.d/postgresql start
    sockstat -l4
    vi /var/db/postgres/data/pg_hba.conf
    # IPv4 local connections:
    host    all             all             172.16.28.2/32          trust
    /usr/local/etc/rc.d/postgresql restart
    psql -h nextcloud.lab.bsd.pw -U postgres
    CREATE USER nextcloud WITH PASSWORD 'something_random_from_bitwarden_or_other_password_manager';
    CREATE DATABASE nextcloud TEMPLATE template0 ENCODING 'UNICODE';
    ALTER DATABASE nextcloud OWNER TO nextcloud;
    \q
    vi /var/db/postgres/data/vacumm.sh
    /usr/local/bin/reindexdb -a 1> /dev/null 2> /dev/null
    /usr/local/bin/reindexdb -s 1> /dev/null 2> /dev/null
    chmod +x /var/db/postgres/data/vacumm.sh
    chown postgres:postgres /var/db/postgres/data/vacumm.sh
    su - postgres -c 'crontab -e'
    0 0 * * * /var/db/postgres/data/vacuum.sh
    su - postgres -c 'crontab -l'
    mkdir -p /usr/local/etc/nginx/ssl
    cd /usr/local/etc/nginx/ssl
    openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout nginx.key -out nginx.crt
    something_random_from_bitwarden_or_other_password_manager
    chmod 400 nginx.key
    ls -l
    chown -R www:www /var/log/nginx
    vi /usr/local/etc/nginx/nginx.conf
    user                 www;
    worker_processes     4;
    worker_rlimit_nofile 51200;
    error_log            /var/log/nginx/error.log;
    
    events {
      worker_connections 1024;
    }
    
    http {
      include           mime.types;
      default_type      application/octet-stream;
      log_format        main  '$remote_addr - $remote_user [$time_local] "$request" ';
      access_log        /var/log/nginx/access.log main;
      sendfile          on;
      keepalive_timeout 65;
    
      upstream php-handler {
        server unix:/var/run/php-fpm.sock;
      }
    
      server {
        # ENFORCE HTTPS
        listen      80;
        server_name nextcloud.lab.bsd.pw;
        return      301 https://$server_name$request_uri;
      }
    
      server {
        listen              443 ssl http2;
        server_name         nextcloud.lab.bsd.pw;
        ssl_certificate     /usr/local/etc/nginx/ssl/nginx.crt;
        ssl_certificate_key /usr/local/etc/nginx/ssl/nginx.key;
    
        # HEADERS SECURITY RELATED
        add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    
        # HEADERS
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
    
        # PATH TO THE ROOT OF YOUR INSTALLATION
        root /usr/local/www/nextcloud/;
    
        location = /robots.txt {
          allow all;
          log_not_found off;
          access_log off;
        }
    
        location = /.well-known/carddav {
          return 301 $scheme://$host/remote.php/dav;
        }
    
        location = /.well-known/caldav {
          return 301 $scheme://$host/remote.php/dav;
        }
    
        # BUFFERS TIMEOUTS UPLOAD SIZES
        client_max_body_size    16400M;
        client_body_buffer_size 1048576k;
        send_timeout            3000;
    
        # ENABLE GZIP BUT DO NOT REMOVE ETag HEADERS
        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
    
        location / {
          rewrite ^ /index.php$uri;
        }
    
        location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
          deny all;
        }
    
        location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
          deny all;
        }
    
        location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
          fastcgi_split_path_info ^(.+\.php)(/.*)$;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
          fastcgi_param HTTPS on;
          fastcgi_param modHeadersAvailable true;
          fastcgi_param front_controller_active true;
          fastcgi_pass php-handler;
          fastcgi_intercept_errors on;
          fastcgi_request_buffering off;
          fastcgi_keep_conn       off;
          fastcgi_buffers         16 256K;
          fastcgi_buffer_size     256k;
          fastcgi_busy_buffers_size 256k;
          fastcgi_temp_file_write_size 256k;
          fastcgi_send_timeout    3000s;
          fastcgi_read_timeout    3000s;
          fastcgi_connect_timeout 3000s;
        }
    
        location ~ ^/(?:updater|ocs-provider)(?:$|/) {
          try_files $uri/ =404;
          index index.php;
        }
    
        # ADDING THE CACHE CONTROL HEADER FOR JS AND CSS FILES
        # MAKE SURE IT IS BELOW PHP BLOCK
        location ~ \.(?:css|js|woff|svg|gif)$ {
          try_files $uri /index.php$uri$is_args$args;
          add_header Cache-Control "public, max-age=15778463";
          # HEADERS SECURITY RELATED
          # IT IS INTENDED TO HAVE THOSE DUPLICATED TO ONES ABOVE
          add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
          # HEADERS
          add_header X-Content-Type-Options nosniff;
          add_header X-XSS-Protection "1; mode=block";
          add_header X-Robots-Tag none;
          add_header X-Download-Options noopen;
          add_header X-Permitted-Cross-Domain-Policies none;
          # OPTIONAL: DONT LOG ACCESS TO ASSETS
          access_log off;
        }
    
        location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
          try_files $uri /index.php$uri$is_args$args;
          # OPTIONAL: DONT LOG ACCESS TO OTHER ASSETS
          access_log off;
        }
      }
    }
    vi /usr/local/etc/php/ext-20-pgsql.ini
    [PostgresSQL]
    pgsql.allow_persistent = On
    pgsql.auto_reset_persistent = Off
    pgsql.max_persistent = -1
    pgsql.max_links = -1
    pgsql.ignore_notice = 0
    pgsql.log_notice = 0
    vi /usr/local/etc/php/ext-30-pdo_pgsql.ini
    [PostgresSQL]
    pgsql.allow_persistent = On
    pgsql.auto_reset_persistent = Off
    pgsql.max_persistent = -1
    pgsql.max_links = -1
    pgsql.ignore_notice = 0
    pgsql.log_notice = 0
    touch /var/log/php-fpm.log
    chown www:www /var/log/php-fpm.log
    rm /usr/local/etc/php-fpm.d/www.conf
    vi /usr/local/etc/php-fpm.d/www.conf
    [www]
    user = www
    group = www
    listen = /var/run/php-fpm.sock
    listen.backlog = -1
    listen.owner = www
    listen.group = www
    listen.mode=0660
    pm = static
    pm.max_children = 4
    pm.start_servers = 2
    pm.min_spare_servers = 2
    pm.max_spare_servers = 4
    pm.process_idle_timeout = 1000s;
    pm.max_requests = 500
    request_terminate_timeout = 0
    rlimit_files = 51200
    env[HOSTNAME] = $HOSTNAME
    env[PATH] = /usr/local/bin:/usr/bin:/bin
    env[TMP] = /tmp
    env[TMPDIR] = /tmp
    env[TEMP] = /tmp
    vi /usr/local/etc/php.ini
    [PHP]
    max_input_time=3600
    engine = On
    short_open_tag = On
    precision = 14
    output_buffering = OFF
    zlib.output_compression = Off
    implicit_flush = Off
    unserialize_callback_func =
    serialize_precision = 17
    disable_functions =
    disable_classes =
    zend.enable_gc = On
    expose_php = On
    max_execution_time = 3600
    max_input_time = 30000
    memory_limit = 1024M
    error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
    display_errors = Off
    display_startup_errors = Off
    log_errors = On
    log_errors_max_len = 1024
    ignore_repeated_errors = Off
    ignore_repeated_source = Off
    report_memleaks = On
    track_errors = Off
    html_errors = On
    error_log = /var/log/php.log
    variables_order = "GPCS"
    request_order = "GP"
    register_argc_argv = Off
    auto_globals_jit = On
    post_max_size = 16400M
    auto_prepend_file =
    auto_append_file =
    default_mimetype = "text/html"
    default_charset = "UTF-8"
    doc_root =
    user_dir =
    enable_dl = Off
    file_uploads = On
    upload_max_filesize = 16400M
    max_file_uploads = 64
    allow_url_fopen = On
    allow_url_include = Off
    default_socket_timeout = 300
    [CLI Server]
    cli_server.color = On
    [Date]
    date.timezone = America/Denver
    [filter]
    [iconv]
    [intl]
    [sqlite3]
    [Pcre]
    [Pdo]
    [Pdo_mysql]
    pdo_mysql.cache_size = 2000
    pdo_mysql.default_socket=
    [Phar]
    [mail function]
    SMTP = localhost
    smtp_port = 25
    mail.add_x_header = On
    [SQL]
    sql.safe_mode = Off
    [ODBC]
    odbc.allow_persistent = On
    odbc.check_persistent = On
    odbc.max_persistent = -1
    odbc.max_links = -1
    odbc.defaultlrl = 4096
    odbc.defaultbinmode = 1
    [Interbase]
    ibase.allow_persistent = 1
    ibase.max_persistent = -1
    ibase.max_links = -1
    ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
    ibase.dateformat = "%Y-%m-%d"
    ibase.timeformat = "%H:%M:%S"
    [MySQLi]
    mysqli.max_persistent = -1
    mysqli.allow_persistent = On
    mysqli.max_links = -1
    mysqli.cache_size = 2000
    mysqli.default_port = 3306
    mysqli.default_socket =
    mysqli.default_host =
    mysqli.default_user =
    mysqli.default_pw =
    mysqli.reconnect = Off
    [mysqlnd]
    mysqlnd.collect_statistics = On
    mysqlnd.collect_memory_statistics = Off
    [OCI8]
    [PostgreSQL]
    pgsql.allow_persistent = On
    pgsql.auto_reset_persistent = Off
    pgsql.max_persistent = -1
    pgsql.max_links = -1
    pgsql.ignore_notice = 0
    pgsql.log_notice = 0
    [bcmath]
    bcmath.scale = 0
    [browscap]
    [Session]
    session.save_handler = files
    session.save_path = "/tmp"
    session.use_strict_mode = 0
    session.use_cookies = 1
    session.use_only_cookies = 1
    session.name = PHPSESSID
    session.auto_start = 0
    session.cookie_lifetime = 0
    session.cookie_path = /
    session.cookie_domain =
    session.cookie_httponly =
    session.serialize_handler = php
    session.gc_probability = 1
    session.gc_divisor = 1000
    session.gc_maxlifetime = 1440
    session.referer_check =
    session.cache_limiter = nocache
    session.cache_expire = 180
    session.use_trans_sid = 0
    session.hash_function = 0
    session.hash_bits_per_character = 5
    url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
    [Assertion]
    zend.assertions = -1
    [COM]
    [mbstring]
    [gd]
    [exif]
    [Tidy]
    tidy.clean_output = Off
    [soap]
    soap.wsdl_cache_enabled=1
    soap.wsdl_cache_dir="/tmp"
    soap.wsdl_cache_ttl=86400
    soap.wsdl_cache_limit = 5
    [sysvshm]
    [ldap]
    ldap.max_links = -1
    [mcrypt]
    [dba]
    [opcache]
    opcache.enable=1
    opcache.enable_cli=1
    opcache.interned_strings_buffer=8
    opcache.max_accelerated_files=10000
    opcache.memory_consumption=128
    opcache.save_comments=1
    opcache.revalidate_freq=1
    [curl]
    [openssl]
    vi /etc/rc.conf
    # DAEMONS | yes
    syslogd_flags="-s -s"
    sshd_enable=YES
    postgresql_enable=YES
    postgresql_class=postgres
    postgresql_data=/var/db/postgres/data
    php_fpm_enable=YES 
    memcached_enable=YES
    memcached_flags="-l 172.16.28.2"
    nginx_enable=YES
    
    # DAEMONS | no
    sendmail_enable=NONE
    sendmail_submit_enable=NO
    sendmail_outbound_enable=NO
    sendmail_msp_queue_enable=NO
    
    # OTHER
    clear_tmp_enable=YES
    clear_tmp_X=YES
    extra_netfs_types=NFS
    dumpdev=NO
    update_motd=NO
    keyrate=fast
    /usr/local/etc/rc.d/memcached start
    /usr/local/etc/rc.d/php-fpm start
    /usr/local/etc/rc.d/postgresql status
    /usr/local/etc/rc.d/nginx start
    sockstat -l4
    ls -l /var/run/php-fpm.sock
    mkdir -p /var/db/nextcloud/data
    chown -R www:www /var/db/nextcloud
    chown -R www:www /usr/local/www/nextcloud
    vi /etc/newsyslog.conf
    /var/db/nextcloud/data/nextcloud.log    www:www 640     7       *       @T00    JC
    /var/log/php-fpm.log                    www:www 640     7       *       @T00    JC
    /var/log/nginx/error.log                www:www 640     7       *       @T00    JC
    /var/log/nginx/access.log               www:www 640     7       *       @T00    JC
    image
    image

    FreeBSD 企业级 1 PB 存储

    • FreeBSD Enterprise 1 PB Storage

    • 作者:𝚟𝚎𝚛𝚖𝚊𝚍𝚎𝚗

    • 2019/06

    今天 FreeBSD 操作系统迎来了 26 周岁生日。6 月 19 日是 国际 FreeBSD 日。所以今天我准备了一些特别的内容 🙂。如何在真实硬件上使用 FreeBSD 构建企业级存储解决方案?这正是 FreeBSD 发挥其所有存储特性(包括 ZFS)优势的地方。

    今天我将展示我如何基于 FreeBSD 系统构建所谓的企业级存储,同时提供逾 1 PB(拍字节)的原始存储容量。

    我曾基于 FreeBSD 构建过各种存储相关系统:

    这个项目有所不同。一台 4U 服务器最多能提供多少存储空间?事实证明,非常多!绝对大于 1 PB(1024 TB)的原始存储空间。

    硬件

    这些是 4U 服务器,带有 90-100 个 3.5 寸硬盘位,可以安装 1260-1400 TB 数据(使用 14 TB 硬盘)。此类系统示例有:

    • (100 个硬盘位)

    • (90 个硬盘位)

    我会选择第一款 —— 简称 TYAN FA100。

    虽然之前的 GlusterFS 和 Minio 集群是在虚拟硬件(甚至 FreeBSD Jail 容器)上搭建的,但这个项目使用了真实物理硬件。

    该系统的规格如下:

    整套系统价格约为 $65,000(含硬盘)。外观如下:

    你需要长达 1200 mm 的机架机柜来放置这台巨兽 :🙂:

    管理界面

    所谓的 Lights Out 管理界面非常优秀。界面简洁、组织良好、响应迅速。可以创建多个独立用户账户,也可以连接外部用户服务,如 LDAP/AD/RADIUS。

    登录后,简洁的 Dashboard 在欢迎我们。

    可以获取各种 传感器 信息,包括系统组件温度。

    还可以查看 系统库存 信息,了解已安装硬件。

    有独立的 设置 菜单,用于各种配置选项。

    虽然是 2019 年,但只需 HTML5 的 远程控制(远程控制台),无需任何第三方插件如 Java/Silverlight/Flash 等,非常方便,也运行良好。

    当然可以远程开关机或循环重启主机。

    维护 菜单用于 BIOS 更新。

    BIOS/UEFI

    进入 BIOS/UEFI 后,可以选择从哪些硬盘启动。截图中显示为两块固态系统盘。

    BIOS/UEFI 界面显示两个 Enclosures,实际上是两块 Broadcom SAS3008 控制器。一些硬盘连接到第一个 SAS 控制器,其余连接到第二个,他们称之为 Enclosures 而非控制器,原因不明。

    FreeBSD 系统

    我选择了最新的 FreeBSD 12.0-RELEASE 来进行安装。安装过程多“默认”,系统盘使用两块 SSD 做 ZFS 镜像,没有特别配置。

    该安装当然支持 功能,可实现安全升级和系统变更。

    硬盘准备

    在所有 90 块 12 TB 硬盘的可能方案中,我选择使用 RAID60 —— 当然这是 ZFS 的等效方案。每个 RAID6(raidz2)组使用 12 块硬盘,总共会有 7 个这样的组 —— 这样 ZFS 池将使用 84 块硬盘,剩下 6 块作为备用(SPARE)硬盘 —— 对我来说非常合适。硬盘分布大致如下。

    下面是 FreeBSD 系统通过命令 camcontrol(8) 看到的这些硬盘情况。按连接的 SAS 控制器 —— scbus(4) 排序。

    有人可能会问,当硬盘出现故障时如何识别是哪一块……这时 FreeBSD 的 <sesutil(8)> 命令就非常有用了。

    第一条 sesutil(8) 命令关闭机箱中所有硬盘的位置指示灯。第二条命令则点亮了 da64 硬盘的识别灯。

    我还会确保不会使用每块硬盘的全部容量。这个想法看似无意义,但设想以下情况:五块 12 TB 硬盘在三年后同时损坏,你无法获得相同型号的硬盘,只能用其他 12 TB 硬盘替代,甚至可能来自不同厂商。

    单块 12 TB 硬盘共有 23437770752 个 512 字节的扇区,总原始容量为 12000138625024 字节。

    现在假设这些来自其他厂商的 12 TB 硬盘每块比原来的少 4 字节 —— ZFS 将不允许使用它们,因为容量不足。

    因此我会将每块硬盘的容量设置为 11175 GB,大约比其总容量 11176 GB 少 1 GB。

    下面是可以对所有 90 块硬盘执行此操作的命令。

    配置 ZFS 池

    接下来,我们需要创建 ZFS 池,这可能是我执行过的最长的 zpool 命令了 :🙂:

    由于东芝 12 TB 硬盘使用 4k 扇区,我们需要将 vfs.zfs.min_auto_ashift 设置为 12 来强制使用该扇区大小。

    ZFS 设置

    由于该存储的主要用途是存放文件,我将使用 recordsize 的最大值之一 —— 1 MB —— 以获得更好的压缩比。

    …但它也将作为 iSCSI 目标使用,在 iSCSI 中我们会使用原生的 4k 块,因此 iSCSI 设置为 4096 字节。

    另外说明一下参数 redundant_metadata ,因为它不是很直观。引用 zfs(8) 手册中的说明。

    从上面的文字可以看出,它主要在单设备池中有用,因为当我们基于 RAIDZ2(RAID6 等价)提供冗余时,就不需要保留额外的元数据副本。

    这样做能提升写入性能。

    为了记录——iSCSI 的 ZFS zvol 是通过如下命令创建的——作为稀疏文件,也称为 薄配置(Thin Provisioning) 模式。

    由于我们有备用(SPARE)磁盘,我们还需要通过在 /etc/rc.conf 文件中添加 zfsd_enable=YES 来启用 zfsd(8) 守护进程。

    我们还需要为池启用 autoreplace 属性,因为默认情况下它是 off。

    其他 ZFS 设置位于 /boot/loader.conf 文件中。由于该系统有 128 GB 内存,我们将允许 ZFS 使用其中的 50% 到 75% 作为 ARC。

    配置网络

    这正是我非常喜欢 FreeBSD 的地方。要设置 LACP 链路聚合,你只需在 /etc/rc.conf 文件中写 5 行。在 RHEL 上,你可能需要多个文件,每个文件还要写很多行。

    Intel X710 DA-2 10GE 网卡在 FreeBSD 下由 ixl(4) 驱动完美支持。

    配置 Cisco Nexus

    这是启用 LACP 聚合所需的 Cisco Nexus 配置。

    首先是端口设置。

    … 现在进行聚合配置。

    … 在第二台 Cisco Nexus NEXUS-2 交换机上也进行相同/类似配置。

    FreeBSD 配置

    这些是在 FreeBSD 系统上最重要的三个配置文件。

    现在我将发布我在这台存储系统上使用的所有设置。

    /etc/rc.conf 文件。

    /boot/loader.conf 文件。

    /etc/sysctl.conf 文件

    目的

    为什么要构建这种设备?因为它比购买“品牌”设备便宜得多。以 Dell EMC Data Domain 为例——而且不是“普通”的 Data Domain,而是几乎最高端的型号——至少是 Data Domain DD9300。它的价格至少要高十倍……容量更小,而且占用机架空间不是 4U,而是接近 14U,需要三个 DS60 扩展器。

    但你实际上可以让这个 FreeBSD 企业存储 的行为类似于 Dell EMC Data Domain……或者比如他们的 Dell EMC Elastic Cloud Storage。

    Dell EMC CloudBoost 可以部署在你的 VMware 环境中,以提供 DDBoost 去重功能。然后你还需要 OpenStack Swift,因为它是支持的后端设备之一。

    FreeBSD 上的 OpenStack Swift 包大约落后现实 4-5 年(版本 2.2.2)(译注:目前版本已经更新了),所以这里你需要使用 Bhyve。

    在这台 FreeBSD 企业存储 上可以创建 Bhyve 虚拟机,例如安装 CentOS 7.6 系统,然后在其中设置 Swift,这样完全可行。利用 20 个物理核心和 128 GB 内存,你几乎感觉不到虚拟机的存在。

    这样,你可以使用 Dell EMC Networker,而存储成本却降低到了原来的十分之一还多。

    以前我也写过关于 的文章,这种 FreeBSD 企业存储对它也非常有利。我实际上也将这个基于 FreeBSD 的存储用作 IBM Spectrum Protect (TSM) 容器池目录的空间。通过 iSCSI 导出效果非常好。

    你还可以将这个 FreeBSD 企业存储 与其他存储设备进行比较,比如 iXsystems TrueNAS 或 EXAGRID。

    性能

    你肯定想知道这个 FreeBSD 企业存储 的性能水平 :🙂:

    我会分享我收集到的所有性能数据。

    网络性能

    首先是网络性能。

    我使用 iperf3 作为基准测试工具。

    我在 FreeBSD 端启动服务器:

    然后在 Windows Server 2016 机器上启动客户端:

    这是在 MTU 1500 下的结果——不使用 Jumbo 帧 :😦:

    不幸的是,这套系统只有一个物理 10GE 接口,但我也做了其他测试。使用两台单 10GE 接口的服务器,可以很好地饱和 FreeBSD 端的双 10GE LACP。

    我还将 NFS 和 iSCSI 导出到 RHEL 系统。单个 10GE 接口下网络性能约为 500-600 MB/s。在 LACP 聚合下可以达到 1000-1200 MB/s。

    磁盘子系统性能

    现在是磁盘子系统。

    先用一些简单的测试,使用 FreeBSD 自带工具 diskinfo(8)。

    现在我们已经知道单块磁盘的速度了。

    接下来,让我们在 ZFS zvol 设备上重复同样的测试。

    接近 3 GB/s —— 不错。

    接下来进行更传统的测试 —— 不朽的 dd(8) 命令。

    这是在 compression=off 设置下进行的测试。

    单进程运行。

    四个并发进程运行。

    八个并发进程运行。

    总结这些数据。

    所以磁盘子系统在顺序写入时能够达到约 3.5 GB/s 的持续速度。这意味着如果想要完全饱和网络,需要再添加两个 10GE 接口。

    磁盘的压力测试仅达到约 55%,这可以通过 FreeBSD 的另一个实用工具 gstat(8) 命令看到。

    接下来进行更“智能”的测试——blogbench 测试。

    首先禁用压缩进行测试。

    接下来设置压缩为 LZ4 进行第二轮测试。

    压缩效果不大,但确实有一定帮助。

    为了对比,我们将在系统 ZFS 池上运行相同的测试——两个 Intel SSD DC S3500 240 GB 镜像驱动,其性能如下:

    Intel SSD DC S3500 240 GB 驱动特性:

    • 顺序读取(最大)500 MB/s

    • 顺序写入(最大)260 MB/s

    • 随机读取(100% 范围)75000 IOPS

    • 随机写入(100% 范围)7500 IOPS

    现在进行 randomio 测试。这是一个多线程磁盘 I/O 微基准测试。

    使用方法如下:

    使用 4k 块 进行的 随机 I/O 测试。

    … 使用 512 字节扇区 进行测试。

    两个 随机 I/O 测试都是在启用 LZ4 压缩的情况下运行的。

    接下来是 bonnie++ 基准测试。同样是在启用 LZ4 压缩的情况下运行的。

    最后但同样重要的是 fio 基准测试。同样启用了 LZ4 压缩。

    不知道你怎么看,我对性能是非常满意的 :🙂:

    FreeNAS

    最初我确实想在这些服务器上使用 FreeNAS,甚至还安装了 FreeNAS。它运行得不错,但…… FreeNAS 的安全部分并不是最佳。

    这是 pkg audit 命令的输出,非常吓人。

    我甚至试图了解为什么 FreeNAS 在其最新版本中会包含如此过时且不安全的包————这是我在他们论坛上发起的讨论贴。

    不幸的是,这反映了他们的政策,可以总结为“只要能用,就不要动/更改版本”——至少我得出了这个印象。

    因为这些安全漏洞,我无法推荐使用 FreeNAS,于是我转向了原生的 FreeBSD 系统。

    另一个有趣的情况是,在我安装 FreeBSD 后,我想导入 FreeNAS 创建的 ZFS pool。这是我执行 zpool import 命令后的结果。

    看起来 FreeNAS 对 ZFS 的处理方式略有不同,他们为每个 RAIDZ2 目标创建了单独的 pool,并配置了专用的备用盘。有趣……

    更新 1 – BSD Now 305

    文章出现在 节目中。

    感谢提及!

    更新 2 – 数据中心实景照片

    有些读者希望看到这台“怪兽”的实景照片。下面是数据中心拍摄的几张图片。

    机箱正面及布线。

    机箱正面另一角度。

    机箱背面及布线。

    带硬盘的顶部视角。

    顶部另一视角。

    硬盘位特写。

    固态硬盘与机械硬盘。

    FreeBSD 上基于 Minio 的分布式对象存储
    FreeBSD 上的 GlusterFS 集群,结合 Ansible 和 GNU Parallel
    静音无风扇 FreeBSD 服务器 —— 冗余备份
    TYAN Thunder SX FA100
    Supermicro SuperStorage 6048R-E1CR90L
    ZFS Boot Environments
    IBM Spectrum Protect (TSM)
    FreeNAS 11.2-U3 Vulnerabilities
    FreeBSD Enterprise 1 PB Storage
    BSD Now 305 – Changing Face of Unix
    logo-tyan.png
    tyan-fa100-small.jpg
    n01.png
    n02.png
    n03
    n04.png
    n05.png
    n06.png
    n07.png
    n08.png
    n09.png
    nas01.png
    nas05.png
    logo-freebsd.jpg
    intel-x710-da-2.jpg
    emc-cloudboost-swift-cover.png
    emc-cloudboost-swift-support.png
    n10.png
    tyan-real-01.jpg
    tyan-real-09.jpg
    tyan-real-02.jpg
    tyan-real-03
    tyan-real-07.jpg
    tyan-real-08.jpg
    tyan-real-06.jpg
    2 x 10 核 Intel Xeon Silver 4114 CPU @ 2.20GHz
    4 x 32 GB DDR4 内存(总计 128 GB)
    2 x Intel SSD DC S3500 240 GB(系统盘)
    90 x Toshiba HDD MN07ACA12TE 12 TB(数据盘)
    2 x Broadcom SAS3008 控制器
    2 x Intel X710 DA-2 10GE 网卡
    2 x 电源
    # zpool list zroot
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
    zroot   220G  3.75G   216G        -         -     0%     1%  1.00x  ONLINE  -
    
    # zpool status zroot
      pool: zroot
     state: ONLINE
      scan: none requested
    config:
    
            NAME        STATE     READ WRITE CKSUM
            zroot       ONLINE       0     0     0
              mirror-0  ONLINE       0     0     0
                da91p4  ONLINE       0     0     0
                da11p4  ONLINE       0     0     0
    
    errors: No known data errors
    
    # df -g
    Filesystem              1G-blocks Used  Avail Capacity  Mounted on
    zroot/ROOT/default            211    2    209     1%    /
    devfs                           0    0      0   100%    /dev
    zroot/tmp                     209    0    209     0%    /tmp
    zroot/usr/home                209    0    209     0%    /usr/home
    zroot/usr/ports               210    0    209     0%    /usr/ports
    zroot/usr/src                 210    0    209     0%    /usr/src
    zroot/var/audit               209    0    209     0%    /var/audit
    zroot/var/crash               209    0    209     0%    /var/crash
    zroot/var/log                 209    0    209     0%    /var/log
    zroot/var/mail                209    0    209     0%    /var/mail
    zroot/var/tmp                 209    0    209     0%    /var/tmp
    
    # beadm list
    BE      Active Mountpoint  Space Created
    default NR     /            2.4G 2019-05-24 13:24
    DISKS  CONTENT
       12  raidz2-0
       12  raidz2-1
       12  raidz2-2
       12  raidz2-3
       12  raidz2-4
       12  raidz2-5
       12  raidz2-6
        6  spares
       90  TOTAL
    # camcontrol devlist | sort -k 6
    (AHCI SGPIO Enclosure 1.00 0001)   at scbus2 target 0 lun 0 (pass0,ses0)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 50 lun 0 (pass1,da0)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 52 lun 0 (pass2,da1)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 54 lun 0 (pass3,da2)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 56 lun 0 (pass5,da4)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 57 lun 0 (pass6,da5)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 59 lun 0 (pass7,da6)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 60 lun 0 (pass8,da7)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 66 lun 0 (pass9,da8)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 67 lun 0 (pass10,da9)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 74 lun 0 (pass11,da10)
    (ATA INTEL SSDSC2KB24 0100)        at scbus3 target 75 lun 0 (pass12,da11)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 76 lun 0 (pass13,da12)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 82 lun 0 (pass14,da13)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 83 lun 0 (pass15,da14)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 85 lun 0 (pass16,da15)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 87 lun 0 (pass17,da16)
    (Tyan B7118 0500)                  at scbus3 target 88 lun 0 (pass18,ses1)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 89 lun 0 (pass19,da17)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 90 lun 0 (pass20,da18)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 91 lun 0 (pass21,da19)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 92 lun 0 (pass22,da20)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 93 lun 0 (pass23,da21)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 94 lun 0 (pass24,da22)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 95 lun 0 (pass25,da23)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 96 lun 0 (pass26,da24)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 97 lun 0 (pass27,da25)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 98 lun 0 (pass28,da26)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 99 lun 0 (pass29,da27)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 100 lun 0 (pass30,da28)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 101 lun 0 (pass31,da29)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 102 lun 0 (pass32,da30)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 103 lun 0 (pass33,da31)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 104 lun 0 (pass34,da32)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 105 lun 0 (pass35,da33)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 106 lun 0 (pass36,da34)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 107 lun 0 (pass37,da35)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 108 lun 0 (pass38,da36)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 109 lun 0 (pass39,da37)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus3 target 110 lun 0 (pass40,da38)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 48 lun 0 (pass41,da39)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 49 lun 0 (pass42,da40)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 51 lun 0 (pass43,da41)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 53 lun 0 (pass44,da42)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 55 lun 0 (da43,pass45)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 59 lun 0 (pass46,da44)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 64 lun 0 (pass47,da45)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 67 lun 0 (pass48,da46)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 68 lun 0 (pass49,da47)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 69 lun 0 (pass50,da48)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 73 lun 0 (pass51,da49)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 76 lun 0 (pass52,da50)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 77 lun 0 (pass53,da51)
    (Tyan B7118 0500)                  at scbus4 target 80 lun 0 (pass54,ses2)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 81 lun 0 (pass55,da52)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 82 lun 0 (pass56,da53)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 83 lun 0 (pass57,da54)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 84 lun 0 (pass58,da55)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 85 lun 0 (pass59,da56)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 86 lun 0 (pass60,da57)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 87 lun 0 (pass61,da58)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 88 lun 0 (pass62,da59)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 89 lun 0 (da63,pass66)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 90 lun 0 (pass64,da61)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 91 lun 0 (pass65,da62)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 92 lun 0 (da60,pass63)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 94 lun 0 (pass67,da64)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 97 lun 0 (pass68,da65)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 98 lun 0 (pass69,da66)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 99 lun 0 (pass70,da67)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 100 lun 0 (pass71,da68)
    (Tyan B7118 0500)                  at scbus4 target 101 lun 0 (pass72,ses3)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 102 lun 0 (pass73,da69)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 103 lun 0 (pass74,da70)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 104 lun 0 (pass75,da71)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 105 lun 0 (pass76,da72)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 106 lun 0 (pass77,da73)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 107 lun 0 (pass78,da74)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 108 lun 0 (pass79,da75)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 109 lun 0 (pass80,da76)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 110 lun 0 (pass81,da77)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 111 lun 0 (pass82,da78)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 112 lun 0 (pass83,da79)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 113 lun 0 (pass84,da80)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 114 lun 0 (pass85,da81)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 115 lun 0 (pass86,da82)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 116 lun 0 (pass87,da83)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 117 lun 0 (pass88,da84)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 118 lun 0 (pass89,da85)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 119 lun 0 (pass90,da86)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 120 lun 0 (pass91,da87)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 121 lun 0 (pass92,da88)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 122 lun 0 (pass93,da89)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 123 lun 0 (pass94,da90)
    (ATA INTEL SSDSC2KB24 0100)        at scbus4 target 124 lun 0 (pass95,da91)
    (ATA TOSHIBA MG07ACA1 0101)        at scbus4 target 125 lun 0 (da3,pass4)
    # sesutil locate all off
    # sesutil locate da64 on
    # grep da64 /var/run/dmesg.boot
    da64 at mpr1 bus 0 scbus4 target 93 lun 0
    da64:  Fixed Direct Access SPC-4 SCSI device
    da64: Serial Number 98G0A1EQF95G
    da64: 1200.000MB/s transfers
    da64: Command Queueing enabled
    da64: 11444224MB (23437770752 512 byte sectors)
    # expr 23437770752 \* 512
    12000138625024
    # camcontrol devlist \
        | grep TOSHIBA \
        | awk '{print $NF}' \
        | awk -F ',' '{print $2}' \
        | tr -d ')' \
        | while read DISK
          do
            gpart destroy -F                   ${DISK} 1> /dev/null 2> /dev/null
            gpart create -s GPT                ${DISK}
            gpart add -t freebsd-zfs -s 11175G ${DISK}
          done
    
    # gpart show da64
    =>         40  23437770672  da64  GPT  (11T)
               40  23435673600     1  freebsd-zfs  (11T)
      23435673640      2097072        - free -  (1.0G)
    # sysctl vfs.zfs.min_auto_ashift=12
    vfs.zfs.min_auto_ashift: 12 -> 12
    
    # zpool create nas02 \
        raidz2  da0p1  da1p1  da2p1  da3p1  da4p1  da5p1  da6p1  da7p1  da8p1  da9p1 da10p1 da12p1 \
        raidz2 da13p1 da14p1 da15p1 da16p1 da17p1 da18p1 da19p1 da20p1 da21p1 da22p1 da23p1 da24p1 \
        raidz2 da25p1 da26p1 da27p1 da28p1 da29p1 da30p1 da31p1 da32p1 da33p1 da34p1 da35p1 da36p1 \
        raidz2 da37p1 da38p1 da39p1 da40p1 da41p1 da42p1 da43p1 da44p1 da45p1 da46p1 da47p1 da48p1 \
        raidz2 da49p1 da50p1 da51p1 da52p1 da53p1 da54p1 da55p1 da56p1 da57p1 da58p1 da59p1 da60p1 \
        raidz2 da61p1 da62p1 da63p1 da64p1 da65p1 da66p1 da67p1 da68p1 da69p1 da70p1 da71p1 da72p1 \
        raidz2 da73p1 da74p1 da75p1 da76p1 da77p1 da78p1 da79p1 da80p1 da81p1 da82p1 da83p1 da84p1 \
        spare  da85p1 da86p1 da87p1 da88p1 da89p1 da90p1
    
    # zpool status
      pool: nas02
     state: ONLINE
      scan: scrub repaired 0 in 0 days 00:00:05 with 0 errors on Fri May 31 10:26:29 2019
    config:
    
            NAME        STATE     READ WRITE CKSUM
            nas02       ONLINE       0     0     0
              raidz2-0  ONLINE       0     0     0
                da0p1   ONLINE       0     0     0
                da1p1   ONLINE       0     0     0
                da2p1   ONLINE       0     0     0
                da3p1   ONLINE       0     0     0
                da4p1   ONLINE       0     0     0
                da5p1   ONLINE       0     0     0
                da6p1   ONLINE       0     0     0
                da7p1   ONLINE       0     0     0
                da8p1   ONLINE       0     0     0
                da9p1   ONLINE       0     0     0
                da10p1  ONLINE       0     0     0
                da12p1  ONLINE       0     0     0
              raidz2-1  ONLINE       0     0     0
                da13p1  ONLINE       0     0     0
                da14p1  ONLINE       0     0     0
                da15p1  ONLINE       0     0     0
                da16p1  ONLINE       0     0     0
                da17p1  ONLINE       0     0     0
                da18p1  ONLINE       0     0     0
                da19p1  ONLINE       0     0     0
                da20p1  ONLINE       0     0     0
                da21p1  ONLINE       0     0     0
                da22p1  ONLINE       0     0     0
                da23p1  ONLINE       0     0     0
                da24p1  ONLINE       0     0     0
              raidz2-2  ONLINE       0     0     0
                da25p1  ONLINE       0     0     0
                da26p1  ONLINE       0     0     0
                da27p1  ONLINE       0     0     0
                da28p1  ONLINE       0     0     0
                da29p1  ONLINE       0     0     0
                da30p1  ONLINE       0     0     0
                da31p1  ONLINE       0     0     0
                da32p1  ONLINE       0     0     0
                da33p1  ONLINE       0     0     0
                da34p1  ONLINE       0     0     0
                da35p1  ONLINE       0     0     0
                da36p1  ONLINE       0     0     0
              raidz2-3  ONLINE       0     0     0
                da37p1  ONLINE       0     0     0
                da38p1  ONLINE       0     0     0
                da39p1  ONLINE       0     0     0
                da40p1  ONLINE       0     0     0
                da41p1  ONLINE       0     0     0
                da42p1  ONLINE       0     0     0
                da43p1  ONLINE       0     0     0
                da44p1  ONLINE       0     0     0
                da45p1  ONLINE       0     0     0
                da46p1  ONLINE       0     0     0
                da47p1  ONLINE       0     0     0
                da48p1  ONLINE       0     0     0
              raidz2-4  ONLINE       0     0     0
                da49p1  ONLINE       0     0     0
                da50p1  ONLINE       0     0     0
                da51p1  ONLINE       0     0     0
                da52p1  ONLINE       0     0     0
                da53p1  ONLINE       0     0     0
                da54p1  ONLINE       0     0     0
                da55p1  ONLINE       0     0     0
                da56p1  ONLINE       0     0     0
                da57p1  ONLINE       0     0     0
                da58p1  ONLINE       0     0     0
                da59p1  ONLINE       0     0     0
                da60p1  ONLINE       0     0     0
              raidz2-5  ONLINE       0     0     0
                da61p1  ONLINE       0     0     0
                da62p1  ONLINE       0     0     0
                da63p1  ONLINE       0     0     0
                da64p1  ONLINE       0     0     0
                da65p1  ONLINE       0     0     0
                da66p1  ONLINE       0     0     0
                da67p1  ONLINE       0     0     0
                da68p1  ONLINE       0     0     0
                da69p1  ONLINE       0     0     0
                da70p1  ONLINE       0     0     0
                da71p1  ONLINE       0     0     0
                da72p1  ONLINE       0     0     0
              raidz2-6  ONLINE       0     0     0
                da73p1  ONLINE       0     0     0
                da74p1  ONLINE       0     0     0
                da75p1  ONLINE       0     0     0
                da76p1  ONLINE       0     0     0
                da77p1  ONLINE       0     0     0
                da78p1  ONLINE       0     0     0
                da79p1  ONLINE       0     0     0
                da80p1  ONLINE       0     0     0
                da81p1  ONLINE       0     0     0
                da82p1  ONLINE       0     0     0
                da83p1  ONLINE       0     0     0
                da84p1  ONLINE       0     0     0
            spares
              da85p1    AVAIL
              da86p1    AVAIL
              da87p1    AVAIL
              da88p1    AVAIL
              da89p1    AVAIL
              da90p1    AVAIL
    
    errors: No known data errors
    
    # zpool list nas02
    NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
    nas02   915T  1.42M   915T        -         -     0%     0%  1.00x  ONLINE  -
    
    # zfs list nas02
    NAME    USED  AVAIL  REFER  MOUNTPOINT
    nas02    88K   675T   201K  none
    # zfs set compression=lz4         nas02
    # zfs set atime=off               nas02
    # zfs set mountpoint=none         nas02
    # zfs set recordsize=1m           nas02
    # zfs set redundant_metadata=most nas02
    # zfs create                      nas02/nfs
    # zfs create                      nas02/smb
    # zfs create                      nas02/iscsi
    # zfs set recordsize=4k           nas02/iscsi
    # man zfs
    (...)
    redundant_metadata=all | most
      Controls what types of metadata are stored redundantly.  ZFS stores
      an extra copy of metadata, so that if a single block is corrupted,
      the amount of user data lost is limited.  This extra copy is in
      addition to any redundancy provided at the pool level (e.g. by
      mirroring or RAID-Z), and is in addition to an extra copy specified
      by the copies property (up to a total of 3 copies).  For example if
      the pool is mirrored, copies=2, and redundant_metadata=most, then ZFS
      stores 6 copies of most metadata, and 4 copies of data and some
      metadata.
    
      When set to all, ZFS stores an extra copy of all metadata.  If a
      single on-disk block is corrupt, at worst a single block of user data
      (which is recordsize bytes long can be lost.)
    
      When set to most, ZFS stores an extra copy of most types of metadata.
      This can improve performance of random writes, because less metadata
      must be written.  In practice, at worst about 100 blocks (of
      recordsize bytes each) of user data can be lost if a single on-disk
      block is corrupt.  The exact behavior of which metadata blocks are
      stored redundantly may change in future releases.
    
      The default value is all.
    
    控制存储哪些类型的元数据为冗余。
    ZFS 会存储额外的元数据副本,以便当单个块损坏时,用户数据的丢失量有限。
    这个额外副本是在池级别提供的冗余(例如镜像或 RAID-Z)之外的,并且是在 **copies** 属性指定的额外副本之外(最多可达三份)。
    例如,如果池是镜像,copies=2,且 redundant_metadata=most,那么 ZFS 会为大部分元数据存储 6 份副本,为数据和部分元数据存储 4 份副本。
    
    当设置为 **all** 时,ZFS 会为所有元数据存储额外副本。
    如果单个磁盘块损坏,最坏情况下只会丢失一块用户数据(大小为 recordsize 字节)。
    
    当设置为 **most** 时,ZFS 会为大部分类型的元数据存储额外副本。
    这可以提升随机写入性能,因为需要写入的元数据更少。
    实际上,如果单个磁盘块损坏,最坏情况下可能丢失大约 100 块用户数据(每块大小为 recordsize 字节)。
    具体哪些元数据块会被冗余存储,未来版本可能会有所变化。
    
    默认值为 **all**。
    
    (...)
    # zfs create -s -V 16T nas02/iscsi/test
    # zpool get autoreplace nas02
    NAME   PROPERTY     VALUE    SOURCE
    nas02  autoreplace  off      default
    
    # zpool set autoreplace=on nas02
    
    # zpool get autoreplace nas02
    NAME   PROPERTY     VALUE    SOURCE
    nas02  autoreplace  on       local
    # grep vfs.zfs /boot/loader.conf
      vfs.zfs.prefetch_disable=1
      vfs.zfs.cache_flush_disable=1
      vfs.zfs.vdev.cache.size=16M
      vfs.zfs.arc_min=64G
      vfs.zfs.arc_max=96G
      vfs.zfs.deadman_enabled=0
    # head -5 /etc/rc.conf
      defaultrouter="10.20.30.254"
      ifconfig_ixl0="up"
      ifconfig_ixl1="up"
      cloned_interfaces="lagg0"
      ifconfig_lagg0="laggproto lacp laggport ixl0 laggport ixl1 10.20.30.2/24 up"
    
    # ifconfig lagg0
    lagg0: flags=8843 metric 0 mtu 1500
            options=e507bb
            ether a0:42:3f:a0:42:3f
            inet 10.20.30.2 netmask 0xffffff00 broadcast 10.20.30.255
            laggproto lacp lagghash l2,l3,l4
            laggport: ixl0 flags=1c
            laggport: ixl1 flags=1c
            groups: lagg
            media: Ethernet autoselect
            status: active
            nd6 options=29
    NEXUS-1  Eth1/32  NAS02_IXL0  connected 3  full  a-10G  SFP-H10GB-A
    NEXUS-2  Eth1/32  NAS02_IXL1  connected 3  full  a-10G  SFP-H10GB-A
    interface Ethernet1/32
      description NAS02_IXL1
      switchport
      switchport access vlan 3
      mtu 9216
      channel-group 128 mode active
      no shutdown
    !
    interface port-channel128
      description NAS02
      switchport
      switchport access vlan 3
      mtu 9216
      vpc 128
    # cat /etc/rc.conf
    # 网络
      hostname="nas02.local"
      defaultrouter="10.20.30.254"
      ifconfig_ixl0="up"
      ifconfig_ixl1="up"
      cloned_interfaces="lagg0"
      ifconfig_lagg0="laggproto lacp laggport ixl0 laggport ixl1 10.20.30.2/24 up"
    
    # 内核模块
      kld_list="${kld_list} aesni"
    
    # 守护进程 | 启用
      zfs_enable=YES
      zfsd_enable=YES
      sshd_enable=YES
      ctld_enable=YES
      powerd_enable=YES
    
    # 守护进程 | NFS 服务
      nfs_server_enable=YES
      nfs_client_enable=YES
      rpc_lockd_enable=YES
      rpc_statd_enable=YES
      rpcbind_enable=YES
      mountd_enable=YES
      mountd_flags="-r"
    
    # 其他
      dumpdev=NO
    # cat /boot/loader.conf
    # 启动参数
      autoboot_delay=3
      kern.geom.label.disk_ident.enable=0
      kern.geom.label.gptid.enable=0
    
    # 禁用英特尔超线程
      machdep.hyperthreading_allowed=0
    
    # 在内核加载前更新英特尔处理器微码
      cpu_microcode_load=YES
      cpu_microcode_name=/boot/firmware/intel-ucode.bin
    
    # 模块
      zfs_load=YES
      aio_load=YES
    
    # RACCT/RCTL 资源限制
      kern.racct.enable=1
    
    # 启动时禁用内存测试
      hw.memtest.tests=0
    
    # 管道 KVA 限制 | 320 MB
      kern.ipc.maxpipekva=335544320
    
    # IPC
      kern.ipc.shmseg=1024
      kern.ipc.shmmni=1024
      kern.ipc.shmseg=1024
      kern.ipc.semmns=512
      kern.ipc.semmnu=256
      kern.ipc.semume=256
      kern.ipc.semopm=256
      kern.ipc.semmsl=512
    
    # 大页映射
      vm.pmap.pg_ps_enabled=1
    
    # ZFS 调优
      vfs.zfs.prefetch_disable=1
      vfs.zfs.cache_flush_disable=1
      vfs.zfs.vdev.cache.size=16M
      vfs.zfs.arc_min=64G
      vfs.zfs.arc_max=96G
    
    # ZFS 禁用对过期 I/O 的 panic
      vfs.zfs.deadman_enabled=0
    
    # NEWCONS 挂起
      kern.vt.suspendswitch=0
    # cat /etc/sysctl.conf
    # ZFS 对齐大小
      vfs.zfs.min_auto_ashift=12
    
    # 安全
      security.bsd.stack_guard_page=1
    
    # 安全性:Intel MDS(微架构数据采样)缓解措施
      hw.mds_disable=3
    
    # 禁用恼人的功能
      kern.coredump=0
      hw.syscons.bell=0
    
    # IPC
      kern.ipc.shmmax=4294967296
      kern.ipc.shmall=2097152
      kern.ipc.somaxconn=4096
      kern.ipc.maxsockbuf=5242880
      kern.ipc.shm_allow_removed=1
    
    # 网络
      kern.ipc.maxsockbuf=16777216
      kern.ipc.soacceptqueue=1024
      net.inet.tcp.recvbuf_max=8388608
      net.inet.tcp.sendbuf_max=8388608
      net.inet.tcp.mssdflt=1460
      net.inet.tcp.minmss=1300
      net.inet.tcp.syncache.rexmtlimit=0
      net.inet.tcp.syncookies=0
      net.inet.tcp.tso=0
      net.inet.ip.process_options=0
      net.inet.ip.random_id=1
      net.inet.ip.redirect=0
      net.inet.icmp.drop_redirect=1
      net.inet.tcp.always_keepalive=0
      net.inet.tcp.drop_synfin=1
      net.inet.tcp.fast_finwait2_recycle=1
      net.inet.tcp.icmp_may_rst=0
      net.inet.tcp.msl=8192
      net.inet.tcp.path_mtu_discovery=0
      net.inet.udp.blackhole=1
      net.inet.tcp.blackhole=2
      net.inet.tcp.hostcache.expire=7200
      net.inet.tcp.delacktime=20
    # pkg search swift
    (...)
    py27-swift-2.2.2_1             Highly available, distributed, eventually consistent object/blob store
    (...)
    # iperf3 -s
    C:\iperf-3.1.3-win64>iperf3.exe -c nas02 -P 8
    (...)
    [SUM]   0.00-10.00  sec  10.8 GBytes  9.26 Gbits/sec                  receiver
    (..)
    # diskinfo -ctv /dev/da12
    /dev/da12
            512             # sectorsize
            12000138625024  # mediasize in bytes (11T)
            23437770752     # mediasize in sectors
            4096            # stripesize
            0               # stripeoffset
            1458933         # Cylinders according to firmware.
            255             # Heads according to firmware.
            63              # Sectors according to firmware.
            ATA TOSHIBA MG07ACA1    # Disk descr.
            98H0A11KF95G    # Disk ident.
            id1,enc@n500e081010445dbd/type@0/slot@c/elmdesc@ArrayDevice11   # Physical path
            No              # TRIM/UNMAP support
            7200            # Rotation rate in RPM
            Not_Zoned       # Zone Mode
    
    I/O command overhead:
            time to read 10MB block      0.067031 sec       =    0.003 msec/sector
            time to read 20480 sectors   2.619989 sec       =    0.128 msec/sector
            calculated command overhead                     =    0.125 msec/sector
    
    Seek times:
            Full stroke:      250 iter in   5.665880 sec =   22.664 msec
            Half stroke:      250 iter in   4.263047 sec =   17.052 msec
            Quarter stroke:   500 iter in   6.867914 sec =   13.736 msec
            Short forward:    400 iter in   3.057913 sec =    7.645 msec
            Short backward:   400 iter in   1.979287 sec =    4.948 msec
            Seq outer:       2048 iter in   0.169472 sec =    0.083 msec
            Seq inner:       2048 iter in   0.469630 sec =    0.229 msec
    
    Transfer rates:
            outside:       102400 kbytes in   0.478251 sec =   214114 kbytes/sec
            middle:        102400 kbytes in   0.605701 sec =   169060 kbytes/sec
            inside:        102400 kbytes in   1.303909 sec =    78533 kbytes/sec
    # diskinfo -ctv /dev/zvol/nas02/iscsi/test
    /dev/zvol/nas02/iscsi/test
            512             # sectorsize
            17592186044416  # mediasize in bytes (16T)
            34359738368     # mediasize in sectors
            65536           # stripesize
            0               # stripeoffset
            Yes             # TRIM/UNMAP support
            Unknown         # Rotation rate in RPM
    
    I/O command overhead:
            time to read 10MB block      0.004512 sec       =    0.000 msec/sector
            time to read 20480 sectors   0.196824 sec       =    0.010 msec/sector
            calculated command overhead                     =    0.009 msec/sector
    
    Seek times:
            Full stroke:      250 iter in   0.006151 sec =    0.025 msec
            Half stroke:      250 iter in   0.008228 sec =    0.033 msec
            Quarter stroke:   500 iter in   0.014062 sec =    0.028 msec
            Short forward:    400 iter in   0.010564 sec =    0.026 msec
            Short backward:   400 iter in   0.011725 sec =    0.029 msec
            Seq outer:       2048 iter in   0.028198 sec =    0.014 msec
            Seq inner:       2048 iter in   0.028416 sec =    0.014 msec
    
    Transfer rates:
            outside:       102400 kbytes in   0.036938 sec =  2772213 kbytes/sec
            middle:        102400 kbytes in   0.043076 sec =  2377194 kbytes/sec
            inside:        102400 kbytes in   0.034260 sec =  2988908 kbytes/sec
    # dd if=/dev/zero of=FILE bs=128m status=progress
    26172456960 bytes (26 GB, 24 GiB) transferred 16.074s, 1628 MB/s
    202+0 records in
    201+0 records out
    26977763328 bytes transferred in 16.660884 secs (1619227644 bytes/sec)
    # dd if=/dev/zero of=FILE${X} bs=128m status=progress
    80933289984 bytes (81 GB, 75 GiB) transferred 98.081s, 825 MB/s
    608+0 records in
    608+0 records out
    81604378624 bytes transferred in 98.990579 secs (824365101 bytes/sec)
    # dd if=/dev/zero of=FILE${X} bs=128m status=progress
    174214610944 bytes (174 GB, 162 GiB) transferred 385.042s, 452 MB/s
    1302+0 records in
    1301+0 records out
    174617264128 bytes transferred in 385.379296 secs (453104943 bytes/sec)
    1 STREAM(s) ~ 1600 MB/s ~ 1.5 GB/s
    4 STREAM(s) ~ 3300 MB/s ~ 3.2 GB/s
    8 STREAM(s) ~ 3600 MB/s ~ 3.5 GB/s
    # time blogbench -d .
    Frequency = 10 secs
    Scratch dir = [.]
    Spawning 3 writers...
    Spawning 1 rewriters...
    Spawning 5 commenters...
    Spawning 100 readers...
    Benchmarking for 30 iterations.
    The test will run during 5 minutes.
    (...)
    Final score for writes:          6476
    Final score for reads :        660436
    
    blogbench -d .  280.58s user 4974.41s system 1748% cpu 5:00.54 total
    # time blogbench -d .
    Frequency = 10 secs
    Scratch dir = [.]
    Spawning 3 writers...
    Spawning 1 rewriters...
    Spawning 5 commenters...
    Spawning 100 readers...
    Benchmarking for 30 iterations.
    The test will run during 5 minutes.
    (...)
    Final score for writes:          7087
    Final score for reads :        733932
    
    blogbench -d .  299.08s user 5415.04s system 1900% cpu 5:00.68 total
    # time blogbench -d .
    Frequency = 10 secs
    Scratch dir = [.]
    Spawning 3 writers...
    Spawning 1 rewriters...
    Spawning 5 commenters...
    Spawning 100 readers...
    Benchmarking for 30 iterations.
    The test will run during 5 minutes.
    (...)
    Final score for writes:          6109
    Final score for reads :        654099
    
    blogbench -d .  278.73s user 5058.75s system 1777% cpu 5:00.30 total
    usage: randomio filename nr_threads write_fraction_of_io fsync_fraction_of_writes io_size nr_seconds_between_samples
    
    filename                    Filename or device to read/write.
    write_fraction_of_io        What fraction of I/O should be writes - for example 0.25 for 25% write.
    fsync_fraction_of_writes    What fraction of writes should be fsync'd.
    io_size                     How many bytes to read/write (multiple of 512 bytes).
    nr_seconds_between_samples  How many seconds to average samples over.
    # zfs create -s -V 1T nas02/iscsi/test
    # randomio /dev/zvol/nas02/iscsi/test 8 0.25 1 4096 10
      total |  read:         latency (ms)       |  write:        latency (ms)
       iops |   iops   min    avg    max   sdev |   iops   min    avg    max   sdev
    --------+-----------------------------------+----------------------------------
    54137.7 |40648.4   0.0    0.1  575.8    2.2 |13489.4   0.0    0.3  405.8    2.6
    66248.4 |49641.5   0.0    0.1   19.6    0.3 |16606.9   0.0    0.2   26.4    0.7
    66411.0 |49817.2   0.0    0.1   19.7    0.3 |16593.8   0.0    0.2   20.3    0.7
    64158.9 |48142.8   0.0    0.1  254.7    0.7 |16016.1   0.0    0.2  130.4    1.0
    48454.1 |36390.8   0.0    0.1  542.8    2.7 |12063.3   0.0    0.3  507.5    3.2
    66796.1 |50067.4   0.0    0.1   24.1    0.3 |16728.7   0.0    0.2   23.4    0.7
    58512.2 |43851.7   0.0    0.1  576.5    1.7 |14660.5   0.0    0.2  307.2    1.7
    63195.8 |47341.8   0.0    0.1  261.6    0.9 |15854.1   0.0    0.2  361.1    1.9
    67086.0 |50335.6   0.0    0.1   20.4    0.3 |16750.4   0.0    0.2   25.1    0.8
    67429.8 |50549.6   0.0    0.1   21.8    0.3 |16880.3   0.0    0.2   20.6    0.7
    ^C
    # zfs create -s -V 1T nas02/iscsi/test
    # randomio /dev/zvol/nas02/iscsi/TEST 8 0.25 1 512 10
      total |  read:         latency (ms)       |  write:        latency (ms)
       iops |   iops   min    avg    max   sdev |   iops   min    avg    max   sdev
    --------+-----------------------------------+----------------------------------
    58218.9 |43712.0   0.0    0.1  501.5    2.1 |14506.9   0.0    0.2  272.5    1.6
    66325.3 |49703.8   0.0    0.1  352.0    0.9 |16621.4   0.0    0.2  352.0    1.5
    68130.5 |51100.8   0.0    0.1   24.6    0.3 |17029.7   0.0    0.2   24.4    0.7
    68465.3 |51352.3   0.0    0.1   19.9    0.3 |17112.9   0.0    0.2   23.8    0.7
    54903.5 |41249.1   0.0    0.1  399.3    1.9 |13654.4   0.0    0.3  335.8    2.2
    61259.8 |45898.7   0.0    0.1  574.6    1.7 |15361.0   0.0    0.2  371.5    1.7
    68483.3 |51313.1   0.0    0.1   22.9    0.3 |17170.3   0.0    0.2   26.1    0.7
    56713.7 |42524.7   0.0    0.1  373.5    1.8 |14189.1   0.0    0.2  438.5    2.7
    68861.4 |51657.0   0.0    0.1   21.0    0.3 |17204.3   0.0    0.2   21.7    0.7
    68602.0 |51438.4   0.0    0.1   19.5    0.3 |17163.7   0.0    0.2   23.7    0.7
    ^C
    # bonnie++ -d . -u root
    Using uid:0, gid:0.
    Writing a byte at a time...done
    Writing intelligently...done
    Rewriting...done
    Reading a byte at a time...done
    Reading intelligently...done
    start 'em...done...done...done...done...done...
    Create files in sequential order...done.
    Stat files in sequential order...done.
    Delete files in sequential order...done.
    Create files in random order...done.
    Stat files in random order...done.
    Delete files in random order...done.
    Version  1.97       ------Sequential Output------ --Sequential Input- --Random-
    Concurrency   1     -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
    Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
    nas02.local 261368M   139  99 775132  99 589190  99   383  99 1638929  99 12930 2046
    Latency             60266us    7030us    7059us   21553us    3844us    5710us
    Version  1.97       ------Sequential Create------ --------Random Create--------
    nas02.local         -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
                  files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                     16 +++++ +++ +++++ +++ 12680  44 +++++ +++ +++++ +++ 30049  99
    Latency              2619us      43us     714ms    2748us      28us      58us
    # fio --randrepeat=1 --direct=1 --gtod_reduce=1 --name=test --filename=random_read_write.fio --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75
    test: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=64
    fio-3.13
    Starting 1 process
    Jobs: 1 (f=1): [m(1)][98.0%][r=38.0MiB/s,w=12.2MiB/s][r=9735,w=3128 IOPS][eta 00m:05s]
    test: (groupid=0, jobs=1): err= 0: pid=35368: Tue Jun 18 15:14:44 2019
      read: IOPS=3157, BW=12.3MiB/s (12.9MB/s)(3070MiB/248872msec)
       bw (  KiB/s): min= 9404, max=57732, per=98.72%, avg=12469.84, stdev=3082.99, samples=497
       iops        : min= 2351, max=14433, avg=3117.15, stdev=770.74, samples=497
      write: IOPS=1055, BW=4222KiB/s (4323kB/s)(1026MiB/248872msec)
       bw (  KiB/s): min= 3179, max=18914, per=98.71%, avg=4166.60, stdev=999.23, samples=497
       iops        : min=  794, max= 4728, avg=1041.25, stdev=249.76, samples=497
      cpu          : usr=1.11%, sys=88.64%, ctx=677981, majf=0, minf=0
      IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
         submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         issued rwts: total=785920,262656,0,0 short=0,0,0,0 dropped=0,0,0,0
         latency   : target=0, window=0, percentile=100.00%, depth=64
    
    Run status group 0 (all jobs):
       READ: bw=12.3MiB/s (12.9MB/s), 12.3MiB/s-12.3MiB/s (12.9MB/s-12.9MB/s), io=3070MiB (3219MB), run=248872-248872msec
      WRITE: bw=4222KiB/s (4323kB/s), 4222KiB/s-4222KiB/s (4323kB/s-4323kB/s), io=1026MiB (1076MB), run=248872-248872msec
    root@freenas[~]# pkg audit -F
    Fetching vuln.xml.bz2: 100%  785 KiB 804.3kB/s    00:01
    python27-2.7.15 is vulnerable:
    Python -- NULL pointer dereference vulnerability
    CVE: CVE-2019-5010
    WWW: https://vuxml.FreeBSD.org/freebsd/d74371d2-4fee-11e9-a5cd-1df8a848de3d.html
    
    curl-7.62.0 is vulnerable:
    curl -- multiple vulnerabilities
    CVE: CVE-2019-3823
    CVE: CVE-2019-3822
    CVE: CVE-2018-16890
    WWW: https://vuxml.FreeBSD.org/freebsd/714b033a-2b09-11e9-8bc3-610fd6e6cd05.html
    
    libgcrypt-1.8.2 is vulnerable:
    libgcrypt -- side-channel attack vulnerability
    CVE: CVE-2018-0495
    WWW: https://vuxml.FreeBSD.org/freebsd/9b5162de-6f39-11e8-818e-e8e0b747a45a.html
    
    python36-3.6.5_1 is vulnerable:
    Python -- NULL pointer dereference vulnerability
    CVE: CVE-2019-5010
    WWW: https://vuxml.FreeBSD.org/freebsd/d74371d2-4fee-11e9-a5cd-1df8a848de3d.html
    
    pango-1.42.0 is vulnerable:
    pango -- remote DoS vulnerability
    CVE: CVE-2018-15120
    WWW: https://vuxml.FreeBSD.org/freebsd/5a757a31-f98e-4bd4-8a85-f1c0f3409769.html
    
    py36-requests-2.18.4 is vulnerable:
    www/py-requests -- Information disclosure vulnerability
    WWW: https://vuxml.FreeBSD.org/freebsd/50ad9a9a-1e28-11e9-98d7-0050562a4d7b.html
    
    libnghttp2-1.31.0 is vulnerable:
    nghttp2 -- Denial of service due to NULL pointer dereference
    CVE: CVE-2018-1000168
    WWW: https://vuxml.FreeBSD.org/freebsd/1fccb25e-8451-438c-a2b9-6a021e4d7a31.html
    
    gnupg-2.2.6 is vulnerable:
    gnupg -- unsanitized output (CVE-2018-12020)
    CVE: CVE-2017-7526
    CVE: CVE-2018-12020
    WWW: https://vuxml.FreeBSD.org/freebsd/7da0417f-6b24-11e8-84cc-002590acae31.html
    
    py36-cryptography-2.1.4 is vulnerable:
    py-cryptography -- tag forgery vulnerability
    CVE: CVE-2018-10903
    WWW: https://vuxml.FreeBSD.org/freebsd/9e2d0dcf-9926-11e8-a92d-0050562a4d7b.html
    
    perl5-5.26.1 is vulnerable:
    perl -- multiple vulnerabilities
    CVE: CVE-2018-6913
    CVE: CVE-2018-6798
    CVE: CVE-2018-6797
    WWW: https://vuxml.FreeBSD.org/freebsd/41c96ffd-29a6-4dcc-9a88-65f5038fa6eb.html
    
    libssh2-1.8.0,3 is vulnerable:
    libssh2 -- multiple issues
    CVE: CVE-2019-3862
    CVE: CVE-2019-3861
    CVE: CVE-2019-3860
    CVE: CVE-2019-3858
    WWW: https://vuxml.FreeBSD.org/freebsd/6e58e1e9-2636-413e-9f84-4c0e21143628.html
    
    git-lite-2.17.0 is vulnerable:
    Git -- Fix memory out-of-bounds and remote code execution vulnerabilities (CVE-2018-11233 and CVE-2018-11235)
    CVE: CVE-2018-11235
    CVE: CVE-2018-11233
    WWW: https://vuxml.FreeBSD.org/freebsd/c7a135f4-66a4-11e8-9e63-3085a9a47796.html
    
    gnutls-3.5.18 is vulnerable:
    GnuTLS -- double free, invalid pointer access
    CVE: CVE-2019-3836
    CVE: CVE-2019-3829
    WWW: https://vuxml.FreeBSD.org/freebsd/fb30db8f-62af-11e9-b0de-001cc0382b2f.html
    
    13 problem(s) in the installed packages found.
    
    root@freenas[~]# uname -a
    FreeBSD freenas.local 11.2-STABLE FreeBSD 11.2-STABLE #0 r325575+95cc58ca2a0(HEAD): Mon May  6 19:08:58 EDT 2019     [email protected]:/freenas-releng/freenas/_BE/objs/freenas-releng/freenas/_BE/os/sys/FreeNAS.amd64  amd64
    
    root@freenas[~]# freebsd-version -uk
    11.2-STABLE
    11.2-STABLE
    
    root@freenas[~]# sockstat -l4
    USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
    root     uwsgi-3.6  4006  3  tcp4   127.0.0.1:9042        *:*
    root     uwsgi-3.6  3188  3  tcp4   127.0.0.1:9042        *:*
    nobody   mdnsd      3144  4  udp4   *:31417               *:*
    nobody   mdnsd      3144  6  udp4   *:5353                *:*
    www      nginx      3132  6  tcp4   *:443                 *:*
    www      nginx      3132  8  tcp4   *:80                  *:*
    root     nginx      3131  6  tcp4   *:443                 *:*
    root     nginx      3131  8  tcp4   *:80                  *:*
    root     ntpd       2823  21 udp4   *:123                 *:*
    root     ntpd       2823  22 udp4   10.49.13.99:123       *:*
    root     ntpd       2823  25 udp4   127.0.0.1:123         *:*
    root     sshd       2743  5  tcp4   *:22                  *:*
    root     syslog-ng  2341  19 udp4   *:1031                *:*
    nobody   mdnsd      2134  3  udp4   *:39020               *:*
    nobody   mdnsd      2134  5  udp4   *:5353                *:*
    root     python3.6  236   22 tcp4   *:6000                *:*
    # zpool import
       pool: nas02_gr06
         id: 1275660523517109367
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr06  ONLINE
              raidz2-0  ONLINE
                da58p2  ONLINE
                da59p2  ONLINE
                da60p2  ONLINE
                da61p2  ONLINE
                da62p2  ONLINE
                da63p2  ONLINE
                da64p2  ONLINE
                da26p2  ONLINE
                da65p2  ONLINE
                da23p2  ONLINE
                da29p2  ONLINE
                da66p2  ONLINE
                da67p2  ONLINE
                da68p2  ONLINE
            spares
              da69p2
    
       pool: nas02_gr05
         id: 5642709896812665361
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr05  ONLINE
              raidz2-0  ONLINE
                da20p2  ONLINE
                da30p2  ONLINE
                da34p2  ONLINE
                da50p2  ONLINE
                da28p2  ONLINE
                da38p2  ONLINE
                da51p2  ONLINE
                da52p2  ONLINE
                da27p2  ONLINE
                da32p2  ONLINE
                da53p2  ONLINE
                da54p2  ONLINE
                da55p2  ONLINE
                da56p2  ONLINE
            spares
              da57p2
    
       pool: nas02_gr04
         id: 2460983830075205166
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr04  ONLINE
              raidz2-0  ONLINE
                da44p2  ONLINE
                da37p2  ONLINE
                da18p2  ONLINE
                da36p2  ONLINE
                da45p2  ONLINE
                da19p2  ONLINE
                da22p2  ONLINE
                da33p2  ONLINE
                da35p2  ONLINE
                da21p2  ONLINE
                da31p2  ONLINE
                da47p2  ONLINE
                da48p2  ONLINE
                da49p2  ONLINE
            spares
              da46p2
    
       pool: nas02_gr03
         id: 4878868173820164207
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr03  ONLINE
              raidz2-0  ONLINE
                da81p2  ONLINE
                da71p2  ONLINE
                da14p2  ONLINE
                da15p2  ONLINE
                da80p2  ONLINE
                da16p2  ONLINE
                da88p2  ONLINE
                da17p2  ONLINE
                da40p2  ONLINE
                da41p2  ONLINE
                da25p2  ONLINE
                da42p2  ONLINE
                da24p2  ONLINE
                da43p2  ONLINE
            spares
              da39p2
    
       pool: nas02_gr02
         id: 3299037437134217744
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr02  ONLINE
              raidz2-0  ONLINE
                da84p2  ONLINE
                da76p2  ONLINE
                da85p2  ONLINE
                da8p2   ONLINE
                da9p2   ONLINE
                da78p2  ONLINE
                da73p2  ONLINE
                da74p2  ONLINE
                da70p2  ONLINE
                da77p2  ONLINE
                da11p2  ONLINE
                da13p2  ONLINE
                da79p2  ONLINE
                da89p2  ONLINE
            spares
              da90p2
    
       pool: nas02_gr01
         id: 1132383125952900182
      state: ONLINE
     status: The pool was last accessed by another system.
     action: The pool can be imported using its name or numeric identifier and
            the '-f' flag.
       see: http://illumos.org/msg/ZFS-8000-EY
     config:
    
            nas02_gr01  ONLINE
              raidz2-0  ONLINE
                da91p2  ONLINE
                da75p2  ONLINE
                da0p2   ONLINE
                da82p2  ONLINE
                da1p2   ONLINE
                da83p2  ONLINE
                da2p2   ONLINE
                da3p2   ONLINE
                da4p2   ONLINE
                da5p2   ONLINE
                da86p2  ONLINE
                da6p2   ONLINE
                da7p2   ONLINE
                da72p2  ONLINE
            spares
              da87p2