2023年1月

了解 MySQL 如何存储和显示你的字符串变量,以便你能更好地控制你的数据。

字符串是你在 MySQL 中使用的最常见的数据类型之一。许多用户在他们的数据库中插入和读取字符串,而没有认真地了解过它们。本文旨在让你深入了解 MySQL 如何存储和显示你的字符串变量,以便你能更好地控制你的数据。

你可以把字符串分成两类:二进制和非二进制。你可能在大多数时候想到的是非二进制字符串。非二进制字符串有字符集和排序的不同。另一方面,二进制字符串存储诸如 MP3 文件或图像等东西。即使你在二进制字符串中存储了一个词,比如“歌曲”,它的存储方式也与非二进制字符串不同。

我将重点讨论非二进制字符串。MySQL 中的所有非二进制字符串都与字符集和排序相关。字符串的字符集控制哪些字符可以存储在字符串中,而它的排序方式控制当你显示字符串时如何排序。

字符集

要查看你系统中的字符集,请运行以下命令:

SHOW CHARACTER SET;

这个命令将输出四列数据,包括字符集:

  • 名称
  • 简要描述
  • 默认的排序方式
  • 字符集中每个字符的最大尺寸

MySQL 过去默认为 latin1 字符集,但自 8.0 版以来,默认为 utf8mb4。现在的默认排序方式是 utf8mb4_0900_ai_ciai 表示该排序对音调不敏感( á = a),而 ci 则指定它对大小写不敏感(a = A)。

不同的字符集将其字符存储在内存中不同大小的块中。例如,从上面的命令可以看出,存储在 utf8mb4 的字符被存储在 1 到 4 个字节大小的内存中。如果你想看看一个字符串是否包含多字节的字符,你可以使用 CHAR_LENGTH()LENGTH() 函数。CHAR_LENGTH() 显示一个字符串包含多少个字符,而 LENGTH() 显示一个字符串有多少个字节,根据字符集的不同,它可能与一个字符串的字符长度相同,也可能不相同。下面是一个例子:

SET @a = CONVERT('data' USING latin1);

SELECT LENGTH(@a), CHAR_LENGTH(@a);

+------------+-----------------+
| LENGTH(@a) | CHAR_LENGTH(@a) |
+------------+-----------------+
|     4      |       4         |
+------------+-----------------+

这个例子表明,latin1 字符集以单字节为单位存储字符。其他字符集,如 utf16,允许多字节的字符:

SET @b = CONVERT('data' USING utf16);

SELECT LENGTH(@b), CHAR_LENGTH(@b);

+------------+------------------+
| LENGTH(@b) | CHAR_LENGTH(@b)  |
+------------+------------------+
|       8    |        4         |
+------------+------------------+

排序

当你运行带有 ORDER BY 子句的 SQL 语句时,字符串排序方式将决定值的显示方式。你对排序方式的选择是由你选择的字符集决定的。当你运行上面的 SHOW CHARACTER SET 命令时,你看到了每个字符集的默认排序方式。你可以很容易地看到某个特定字符集的所有排序方式。例如,如果你想查看 utf8mb4 字符集允许哪些排序,请运行:

SHOW COLLATION LIKE 'utf8mb4%';

排序方式可以是不区分大小写的,也可以是区分大小写的,或者是二进制的。让我们建立一个简单的表,向其中插入一些值,然后用不同的排序方式查看数据,看看输出结果有什么不同:

CREATE TABLE sample (s CHAR(5));

INSERT INTO sample (s) VALUES 
 ('AAAAA'), ('ccccc'),  ('bbbbb'), ('BBBBB'), ('aaaaa'), ('CCCCC');

SELECT * FROM sample;

+-----------+
| s         |
+-----------+
| AAAAA     |
| ccccc     |
| bbbbb     |
| BBBBB     |
| aaaaa     |
| CCCCC     |
+-----------+

在不区分大小写的情况下,你的数据会按字母顺序返回,但不能保证大写的单词会排在小写的单词之前,如下图所示:

SELECT * FROM sample ORDER BY s COLLATE utf8mb4_turkish_ci;

+-----------+
| s         |
+-----------+
| AAAAA     |
| aaaaa     |
| bbbbb     |
| BBBBB     |
| ccccc     |
| CCCCC     |
+-----------+

另一方面,当 MySQL 运行大小写敏感的搜索时,每个字母的小写将排在大写之前:

SELECT * FROM sample ORDER BY s COLLATE utf8mb4_0900_as_cs;

+-----------+
| s         |
+-----------+
| aaaaa     |
| AAAAA     |
| bbbbb     |
| BBBBB     |
| ccccc     |
| CCCCC     |
+-----------+

而按二进制排序方式将返回所有大写的值,然后再返回小写的值:

SELECT * FROM sample ORDER BY s COLLATE utf8mb4_0900_bin;

+-----------+
| s         |
+-----------+
| AAAAA     |
| ccccc     |
| bbbbb     |
| BBBBB     |
| aaaaa     |
| CCCCC     |
+-----------+

如果你想知道一个字符串使用哪种字符集和排序,你可以使用被恰当命名的 charsetcollation 函数。运行 MySQL 8.0 或更高版本的服务器将默认使用 utf8mb4 字符集和 utf8mb4_0900_ai_ci 排序:

SELECT charset('data');

+-------------------+
| charset('data')   |
+-------------------+
| utf8mb4           |
+-------------------+

SELECT collation('data');

+--------------------+
| collation('data')  |
+--------------------+
| utf8mb4_0900_ai_ci |
+--------------------+

你可以使用 SET NAMES 命令来改变所使用的字符集或排序方式。

要从 utf8mb4 字符集改为 utf16,运行这个命令:

SET NAMES 'utf16';

如果你想选择默认以外的排序方式,你可以在 SET NAMES 命令中添加一个 COLLATE 子句。

例如,假设你的数据库存储西班牙语的单词。MySQL 的默认排序(utf8mb4_0900_ai_ci)将 chll 视为两个不同的字符,并将它们排序。但在西班牙语中,chll 是单独的字母,所以如果你想让它们按正确的顺序排序(分别排在 cl 之后),你需要使用不同的排序。一个选择是使用 utf8mb4_spanish2_ci 排序方式:

SET NAMES 'utf8mb4' COLLATE 'utf8mb4_spanish2_ci';

储存字符串

MySQL 允许你为你的字符串值选择不同的数据类型。(甚至比其他流行的数据库,如 PostgreSQL 和 MongoDB 更多。)

下面是 MySQL 的二进制字符串数据类型的列表、它们的非二进制对应物,以及它们的最大长度:

  • binarychar(255)
  • varbinaryvarchar(65,535)
  • tinyblobtinytext(255)
  • blobtext(65,535)
  • mediumblobmediumtext(16,777,215)
  • longbloblongtext(4,294,967,295)

要记住的一件重要事情是,与被存储在可变长度的字段中的 varbinaryvarchartextblob 类型不同(也就是说,只使用需要的空间),MySQL 将二进制(binary)和字符(char)类型存储在固定长度的字段。因此,像 char(20)binary(20) 这样的值将总是占用 20 个字节,即使你在其中存储了少于 20 个字符。对于二进制类型,MySQL用 ASCII NUL 值(0x00)填充这些值,对于 字符类型,用空格填充。

在选择数据类型时要考虑的另一件事是,你是否希望在字符串后面的空格被保留或剥离。在显示数据时,MySQL 会从以字符数据类型存储的数据中剥离空格,但不会剥离 varchar 的空格。

CREATE TABLE sample2 (s1 CHAR(10), s2 VARCHAR(10));

INSERT INTO sample2 (s1, s2) VALUES ('cat       ', 'cat       ');

SELECT s1, s2, CHAR_LENGTH(s1), CHAR_LENGTH(s2) FROM sample2;

+---------+---------+-----------------------------------+
| s1      | s2      | CHAR_LENGTH(s1) | CHAR_LENGTH(s2) |
+---------+---------+-----------------------------------+
| cat     | cat     |        3        |       10        |
+---------+---------+-----------------------------------+

总结

字符串是数据库中最常用的数据类型之一,而 MySQL 仍然是当今最流行的数据库系统之一。我希望你能从这篇文章中学到一些新的东西,并能用你的新知识来提高你的数据库技能。


via: https://opensource.com/article/23/1/strings-mysql

作者:Hunter Coleman 选题:lkxed 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

MasterPlus 将被彻底改造并推出开源版本?听起来不错!

大多数游戏/外设软件套装要么是专有的,要么是没有对 Linux 的官方支持。

因此,我们必须不断寻找开源工具来配置我们的硬件以获得原生功能。

PiperOpenRGBSolaar 等在这些情况下都很有用。

但是,有时候,即使是这些也是不够的。

幸运的是,酷冷至尊(CoolerMaster) 已经决定发布其 MasterPlus 软件的开源版本,旨在为其散热器和第三方的散热器提供服务。

虽然这并不能保证它可以用在 Linux 系统上,但我们绝对可以期待它。

此举也应该鼓励雷蛇和罗技这样公司考虑制作精简过的开源工具。

让我们看看酷冷至尊打算怎么做。

MasterPlus 开源版本:我们目前所知的情况

酷冷至尊 Masterplus 改版

酷冷至尊在最近的 CES 2023 活动中透露了他们计划发布新的 MasterPlus 开源版本。感谢来自 Boring Text Reviews 的 Albert 让我们注意到了这一点。

预期会有什么? 对 MasterPlus 软件进行了全面的重新设计,有一个 API 插件系统,允许非酷冷至尊散热器与之整合。

他们已经澄清,酷冷至尊的独有功能不能配合其他散热器一起工作。因此,诸如检测 AIO 散热器的泄漏或计算 PSU 的效率等,都不能对第三方产品进行跟踪。

相反,该应用程序将只支持读取基本的性能信息,如温度和风扇速度,并能够配置 ARGB 设备。

如果你问我,这总比没有好。 而且,如果你的系统碰巧使用了酷冷至尊的组件,这对你来说是一个令人兴奋的消息!

酷冷至尊还展示了 API 系统的潜在应用,让它与一个照片应用程序挂钩,用它来控制集成在电脑机箱侧面的辅助显示器。

此外,他们还介绍了其软件的全面云整合。但遗憾的是,这部分不会开源。

什么时候? 我们还没有 MasterPlus 开源的具体发布日期。

但是,如果让我猜,2023 年的某个时候是最好的选择。

? 即使该工具没有被确认可以在 Linux 上工作,对开源工具来说也是一个好的开始,不是吗?你怎么看?


via: https://news.itsfoss.com/coolermaster-open-source-software/

作者:Sourav Rudra 选题:lkxed 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是一篇快速而简单的指南,用 Oh My Zsh 和 Powerlevel10k 主题改造你的 Zsh 终端 Shell,使其在 Ubuntu 和其他 Linux 发行版中看起来很酷。

大多数 Linux 发行版中的默认 Shell 是 Bash。Bash 是一个可靠的和传统的工具。然而,它缺乏一些自定义功能,比如漂亮的颜色、光标支持等等。

你可以使用另一个 Shell,即 Zsh 来得到更多的设置调整,并帮助你扩展你的 Bash Shell 体验。

这个简单的指南解释了如何安装 Zsh、Oh My Zsh 并应用 Powerlevel10k 主题。

Oh My Zsh 和 Powerlevel10k 安装和配置指南

1、安装 Zsh 和改变 Shell

打开一个终端,使用以下适用于你的发行版的命令安装 Zsh。

Ubuntu、Debian、Linux Mint 和所有相关的发行版:

sudo apt install zsh

Fedora:

sudo dnf install zsh

Arch:

pacman -S zsh

安装完成后,找出 Zsh 的安装路径:

whereis zsh

然后使用当前用户的 Zsh 可执行路径改变 Shell。

chsh -s /usr/bin/zsh <用户名 >

改变当前用户的 Shell

关闭并再次打开终端。然后你应该看到 Zsh 的首次设置。选择选项 2。它将用一个默认的主题改变你的 Shell 提示符的外观,如下图所示:

Zsh 的首次设置

2、安装 Oh My Zsh

Oh My Zsh 是一套可以进一步定制 Zsh 的脚本。

首先,我们将从 GitHub 上下载 Oh My Zsh 脚本来安装它。如果你有 wgetgit 软件包,那就最好了。如果还没有安装,请使用以下命令 安装 wget & git:

sudo apt install wget
sudo apt install git

然后用下面的命令安装 Oh My Zsh:

sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

然后你应该看到 Oh My Zsh 及默认主题 Robbyrussell 应用到了你的终端。

安装 Oh My Zsh 和默认主题

Oh My Zsh 还附带了其他的主题,你可以 使用这篇指南 安装它们。然而,在本教程中,我将谈论一个特定的主题,即 Powerlevel10k。

3、为 Oh My Zsh 安装 Powerlevel10k 主题

打开终端,运行以下命令,从 GitHub 上克隆 Powerlevel10k 代码库,并将文件放到 Oh My Zsh 的配置文件夹中。

git clone https://github.com/romkatv/powerlevel10k.git $ZSH_CUSTOM/themes/powerlevel10k

用文本编辑器打开 ~/.zshrc 文件,将 ZSH_THEME 变量设为 "powerlevel10k/powerlevel10k"

cd ~
nano .zshrc

默认情况下,它应该是 Robbyrussell。删除 ”robbyrussell",添加下面的 "powerlevel10k/powerlevel10k"

更改后,你的 ~/.zshrc 文件应该是这样的:

ZSH_THEME="powerlevel10k/powerlevel10k”

保存并关闭该文件(CTRL+O、回车和 CTRL+X)。

改变 Oh My Zsh 主题为 Powerlevel10k

重新启动你的终端,启动首次向导来设置 Powerlevel10k 主题。

4、Powerleve10k 的首次设置

安装后启动终端时,Powerlevel10k 会提示你各种问题以了解你的 Linux 发行版设置。所以,根据你的需要按下键,按照你的口味来定制你的终端。下面是一些问题的例子截图,可以给你一些启发。

Powerlevel10k - wizard1

Powerlevel10k - wizard2

最后,你可以保存文件,享受你的终端的新面貌。

应用 Powerlevel10k Zsh 主题设置后

如果你想再次重启配置向导,运行以下程序。你可以随心所欲地做,次数不限。

p10k configure

基本设置就这样结束了。如果你想了解更多,请继续阅读。

更多配置(高级用法)

5、安装 Dracula GNOME 终端主题

如果你使用的是带有原生终端应用的 GNOME 桌面,你可以试试令人惊叹的 Drakula 主题。要做到这一点,打开一个终端,运行下面的命令来下载该主题:

git clone https://github.com/dracula/gnome-terminalcd gnome-terminal

打开 GNOME “终端”应用,进入偏好设置。通过点击 “+” 添加一个新的配置文件,并命名为 “drakula”。然后进入颜色标签,取消勾选 “ 使用系统主题的颜色 use colors from system theme ” 选项。

为终端创建一个新的配置文件

回到终端,运行以下程序。当出现提示时,选择你刚才创建的配置文件名称,如上所述。

./install.sh

为 GNOME “终端”应用 Drakula 主题

一旦安装完成,回到偏好设置中,将 Drakula 配置文件标记为默认。

6、Zsh 的自动补完和语法高亮

你可能想试试由社区开发的两个可用于 Zsh 的插件。它们是 zsh-autosuggestions 和 zsh-syntax-highlighting。

打开终端,运行以下程序,下载 zsh-autosuggestions,并将其放在插件文件夹中:

git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions

同样地,为语法高亮插件运行以下程序:

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting

通过文本编辑器打开 ~/.zshrc文件(使用以下命令),并找到 plugins=(git) 一行。并将其替换为以下内容:

nano ~/.zshrc
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)

使用 CTRL+O、回车和 CTRL+X 保存并关闭该文件。

关闭并打开你的终端。现在,你应该可以使用自动建议和语法高亮了。

总结

这样就好了!你现在应该已经在你的系统上安装了 Oh My Zsh 和 Powerlevel10k 主题。你可以根据自己的需要,进一步定制 Powerlevel10k 主题的外观和行为。

干杯。


via: https://www.debugpoint.com/oh-my-zsh-powerlevel10k/

作者:Arindam 选题:lkxed 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

微软准备将 AI 聊天机器人添加到 Word 和电子邮件中

据报道,微软已经讨论在 Word、PowerPoint、Outlook 等应用程序中加入 OpenAI 的人工智能,以便客户能够使用简单的提示自动生成文本。这一举措可能会改变超过 10 亿人编写文档、演示文稿和电子邮件的方式。工程师们正在开发在客户数据上训练这些模型的方法,并保证这些数据不会泄露给其他客户或落入不良分子手中。

消息来源:The Information
老王点评:让我想一下,或许以后可以就写个提纲,Word 就可以替你补充大段看起来没什么问题的文字?这简直是灌水的福音。

艺术家担心 Adobe 追踪其设计过程来训练 AI

前两天我们 报道 过,Adobe 创意云服务的隐私条款让用户担心其创作被用来训练 Adobe 的生成性 AI。这一讨论在 Twitter 上吸引了数百万次浏览和数千次转发。但是除了对图像、音乐、视频等创作被利用的担心之外,艺术家们还担心 Photoshop 和其他 Adobe 产品追踪其应用的使用,以了解创作者是如何工作的。也就是说,窃取平面设计师在几十年的工作中形成的流程和行动。一个复杂、曲折的艺术过程变得有可能被自动化。

消息来源:Fast Company
老王点评:如果是真的,那么平面设计师或艺术家们也将很快被人工智能取代。我们说的 AI 的消息够多了,总感觉我们处在 AI 爆发前夜,或许明天一切你想得到、想不到的工作都会因 AI 而改变。

动态三重缓冲有望加入 GNOME 44

两年多来,Canonical 一直在为 GNOME 桌面的 Mutter 合成器研究动态三重缓冲。这种按需的三重缓冲可以极大地提高桌面性能,特别是在使用英特尔集成显卡和树莓派板卡的情况下。虽然三重缓冲的实现还没有被上游化,但从 Ubuntu 22.04 LTS 开始就把这些补丁作为他们发行的 Mutter 包的一部分,Debian 等发行版也一直携带该补丁。开发人员表示动态三重缓冲有望会被 GNOME 44 上游纳入。GNOME 44.0 稳定版将于 3 月 22 日发布。

消息来源:Phoronix
老王点评:这对低性能显卡真是一件好事。相比 GNOME、KDE 的各种花哨改进,我更愿意看到它们在性能和稳定性等底层的进展。

这里是一个关于理解 Linux 中 who 命令的初学者指南,并带有几个例子。

这篇文章是 Linux 命令学习系列的一部分。

who 命令

Linux 中的 who 命令用于显示当前登录到系统中的用户的信息。它显示用户的登录名,用户登录的终端,用户登录的时间,以及远程主机名(如果有)。

语法

下面是 who 命令的基本语法:

who [OPTION]... [ FILE | ARG1 ARG2 ]

各种 who 命令和开关的例子

默认情况下,who 读取文件 /var/run/utmp,其中包含当前登录的用户的信息。如果没有指定选项,它会显示每个用户的登录名、终端和登录时间。

who

它给出了以下输出。你可以看到它显示了登录名是 debugpoint,终端 ID tty2 和登录的日期和时间。

debugpoint tty2 2023-01-01 11:22 (tty2)

who 命令 - 默认示例

然而,如果你在虚拟机中运行上述命令,你应该看到同样的情况,但终端 ID 将是 x11 服务器的显示名称,即 :0

❯ who
debugpoint :0 2023-01-01 23:36 (:0)

要显示当前用户的用户名和信息,使用下面的方法:

whoami

使用 -b 选项查看最后一次系统启动时间:

❯ who -b
system boot 2023-01-01 23:36

显示当前系统中登录的用户数:

❯ who -q
debugpoint
users=1

所有上述命令与 -H 选项配对时,你会有一个更好的含标题行的信息,如下所示:

who -H

NAME LINE TIME COMMENT
debugpoint tty2 2023-01-01 11:22 (tty2)

如果你想在 Linux 中显示与 who 命令有关的所有信息,请使用选项 -a

who -aH

NAME LINE TIME IDLE PID COMMENT EXIT
system boot 2023-01-01 11:19
run-level 5 2023-01-01 11:19
debugpoint + tty2 2023-01-01 11:22 13:26 2042 (tty2)

像往常一样,你可以使用下面的重定向将 who 命令的输出保存到任何文件:

who > user_details.txt

who 命令选项的例子总结

下面是一些 who 命令的例子和它们的解释:

下面是一些可以与 who 命令一起使用的选项:

  • -a: 显示每个用户的主机名、登录时间和进程
  • -b: 显示上次系统启动的时间
  • -d: 显示死进程(已终止但未从 utmp 文件中删除的进程)
  • -H: 显示标题行
  • -l: 显示长格式的登录进程
  • -m: 只显示在 ARG1 ARG2 指定的终端上登录的用户的名字和行。
  • -q: 显示已登录用户的数量
  • -u: 显示拥有未脱离进程的用户的信息
  • -w: 显示已经登录的用户信息,格式与 utmp 文件相同

总结

我希望这篇文章能够帮助你了解 who 命令及其基本原理。你也可以阅读 who 手册页来了解更多。如果你有任何问题,请告诉我。


via: https://www.debugpoint.com/who-command-linux/

作者:Arindam 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

引言

2022 年末,openEuler Summit 2022 上,中国 Linux 内核圈最有影响力的开发者之一——吴峰光博士做了名为《面向全场景操作系统的构建服务发布》的主题演讲,正式向开发者披露了 openEuler 统一构建服务 EulerMaker

Linux 中国开源社区就此采访了吴峰光博士,为读者挖掘到一些在峰会上亮相的 EulerMaker 背后的有趣细节。

? 吴峰光博士是著名的 Linux 内核贡献者、华为计算操作系统首席专家、openEuler 社区技术委员会委员。他在 Linux 内核领域上拥有卓越贡献,在 I/O 和内存管理、内核测试服务方面做出了重要的贡献。有关他的故事,可以参阅《新程序员》杂志的专访《吴峰光杀进 Linux 内核》。

openEuler 的全场景

2021 年 9 月,openEuler 宣布将支持全场景,在服务器、云计算之外,还支持编译计算和嵌入式场景,这就引来了很多人的关注,但也有一些怀疑的眼光。因为,服务器和嵌入式分处两端,中间有着巨大的鸿沟。

“30 年前,服务器 OS、嵌入式 OS,界限非常清晰,像是两个村,中间全是农田。但后来 IT 越来越深入千行百业,云、边缘、IoT 兴起,各种场景涌现,发生了交叠。所以我们认为这是一个新的历史机会,来做一个全场景 OS。”吴峰光说。

? 关于多场景的支持和融合,请参考我们之前对欧拉技术委员熊伟的采访:《操作系统专家解读 openEuler 22.09 最新技术特性》。

“要做全场景 OS,就引入了一个需求:原来的构建系统,如何转化为全场景统一构建系统?”

什么是 OS 构建系统?

OS 构建系统以 OS 源代码作为输入,以用户可安装使用的软件仓或OS镜像作为输出。

? 服务器领域的 OBS、嵌入式领域的 Bitbake,是各自领域的代表性构建系统,历史悠久。

为什么需要新的构建系统?

“openEuler 社区一开始是用 OBS 来构建的,”吴峰光介绍说,“OBS 最初由 SUSE 贡献开源,功能强大。但随着使用的深入,我们发现一些复杂的新需求很难在它上面改进,这就对 openEuler 的演进造成了困难。”

就一般的 OS 来说,OBS 构建可能够用;但是当一个操作系统要支持全场景,复杂度就大大增加,对构建系统提出了更严苛的要求。

吴峰光博士对 OBS、Bitbake 做了深入调研。他解释了这些老牌构建系统,为什么满足不了openEuler的需求:

“服务器领域的 OBS 主打能力是什么?几大主流的 Linux 发行版它都支持,比如可以给 Redhat 打包,也可以给 Debian 打包。兼容并包是它的核心设计目标,适应了 Linux 多样化的现状。但我们认为,多样化在早期对 Linux 发展有利,但长期而言,Linux 生态的碎片化是一个需要被解决的问题。”

“嵌入式领域的 Bitbake 采用了面向任务和过程的 DSL 描述语言,这使得它非常灵活强大,但自由度和复杂性过高,以学习曲线陡峭知名。现在流行的理念是如 YAML、JSON 等通用、声明式的配置语言,和函数式编程,以实现低门槛、易理解、可控可重复的构建过程。”

在吴峰光看来,在 30 年后的今天,构建系统有着新的时代目标

2022 年 3 月,openEuler 团队开始设计新的构建系统 EulerMaker。

EulerMaker 构建系统

OS 构建系统的核心流程是,用户给定一组软件包后,按照包依赖关系,对它们发起并行构建任务。“那么搭一个 Kubernetes 集群,上面叠加一个包构建调度模块,是不是就可以了呢?”

“这里的包依赖管理和调度,的确非常复杂:既有源包的依赖,又有二进制包的依赖,还有构建环境的依赖;既有构建依赖,又有运行依赖,还有传递依赖;成千上万的依赖关系,形成一个巨大的图,要考虑怎么破环,把它变成一个有向无环图(DAG),用于最大化并发调度。随着包构建的推进,新输出的 RPM 包需要成为之后 RPM 包构建的环境,还会提供新的依赖信息,动态更新这个 DAG 图。还要考虑各种包构建的失败情况,多用户并发任务之间的干扰,或者任意机器、模块随时崩溃重启后如何接力,避免单点故障,等等,这需要一整套精巧的架构设计。”

看到这样的难题,可能有工程师大牛们要摩拳擦掌,跃跃欲试了。但是在难题面前,吴峰光不慌不忙,踩了一脚刹车——

“我们先把发动机放一边,追根溯源,回到最初的那一个问题:用户到底需要一辆什么车?

做架构设计,首先要考虑用户场景,然后推导出功能,最后才能确定数据和流程。设计时全盘考虑了所有的用户需求,数据和流程在未来才会稳定,才不会变来变去。

“我们对用户需求的考虑,真的全面了吗?”

吴峰光继续展开分析:“在 Linux 发展的最初阶段,需求是简单的:只要功能实现了,跑一下 gcc / make 能构建出来,用户能用,构建系统的工作就完成了。那时侯 Linux 社区对测试不重视,也还没有 CI / CD 的概念,测试基本全靠用户踩坑。现在情况就不一样了,时代的要求在提高:开发者期望有质量把控,要做测试,要有一整套的构建测试 CI / CD,要覆盖一整个开发流程,一站式全部搞定,出来的 RPM 包已经是经过测试的、用户能放心用的。这已经被开发者认为是标配,是开发者的正常预期。”

所以,新的构建系统要集成测试流程。

那么,是不是直接集成现在流行的通用 CI / CD 测试工具就可以了呢?

“市面上的 CI / CD 通用测试服务,适合测试上层的应用;而操作系统需要测试的,既有上层软件,又有基础软件;既面向应用开发者,又面向内核开发者,还有软件厂商、硬件厂商、OS 厂商,他们都有独特的测试需求;既要做功能测试,还要做性能测试。这些不是市面上通用 CI / CD 能做的。”

“所以,我们需要一套全栈系统,既能构建,又满足上述所有测试需求。”

早在 2020 年,吴峰光就综合分析上述需求,设计了 Compass-CI。Compass-CI 被设计为一个通用的任务执行系统,可以执行构建、功能测试、性能测试等各类任务。Compass-CI 也被设计为一个异构调度系统,可以调度物理机、虚拟机、容器等各种资源。

“Compass-CI 已经在 2020 年上线服务,在这个基础上补足构建相关的模块,就可以作为 EulerMaker 的后端,服务 openEuler 的构建。”

“当我们可以用一套系统,来服务好业界各方的需求,就会有硬件厂商问我们,能不能远程接入他们的硬件?然后,我们就需要支持工作机远程接入,分布式调度,数据共享,立足云端,连接各类线下机房,x86、ARM 等各类硬件,方便开发者之间、厂商之间、开发者与厂商之间的分布式协作。”

“资源有了,功能有了,开发者来了,也会有很多需求:我打包了,能不能看见进展?出问题了能不能复现当时的环境?能不能登录调试修复?能不能 DIY 验证?这些需求都需要一一满足大家。现在 EulerMaker 的可视化界面可以显示构建的进展,每个包会显示其依赖关系图以及其构建的进度,哪些包已经构建了,哪些包还没有构建,预计还有多少分钟,它前面还有哪几个依赖都一目了然。而且每个开发者都可以有专属队列,可以大大缩短等待时间。”

EulerMaker 怎么解决全场景

一个 OS 怎么支持全场景?

“首先这个 OS 要足够通用。但这还不够。”吴峰光继续说到:“一个通用的 OS,所带的软件往往要求大而全,把常见的功能都编进去。但很多场合有着不同的需求,比如启用一个不常用的功能,或者在嵌入式设备上,因为资源受限,需要把不必要的功能裁减掉。”

一个通用软件,往往会提供一组编译期的定制功能,方便不同场景的开发者和用户针对自己的需求,构建出不同功能组合的二进制程序。

“类似的,当我们说一个 OS 支持全场景,是只需维护一套 OS 源代码,通过源码级 + 镜像级定制,即可构建生成各类场景化的二进制 OS 发布。强大的定制能力,是赋能一套 OS 源码支持全场景的‘究极魔法’。”

吴峰光进一步介绍什么是定制能力:

“最简单的定制能力,体现在软件打包上,就是对用户提供定制选项。一般是把上游软件的可选功能做一个封装,让用户在做包构建的时候可以打开或者关闭。比如 RPM SPEC 文件中通过宏定义了 %{with xxx} 选项,用户就可以通过 rpmbuild --with xxx 来打开 xxx 选项对应的软件功能。”

“然而 SPEC 文件中往往只封装了少量选项,对于没有被 SPEC 维护者封装的上游软件功能,用户就只好自行修改 SPEC 文件来实现定制,这样就很杂乱了。”

“事实上 OS 的用户和场景多种多样,他们需要的定制项,往往远超包维护者所能提供。比如有人想升级版本号,有人想加个补丁,有人想加个编译选项,或者修改编译器。我们需要一种开放式的定制规范,即允许用户在不修改打包文件的情况下,实现对打包文件的定制,且允许定制任意字段,不限于包维护者事先提供的一个封闭选项集合。”

“这时候就会发现 SPEC 文件的定制能力不够用了。”

EulerMaker 怎么解决这个问题呢?

“我们引入了开发者们都很熟悉的 YAML 配置语言,用它来声明式的描述一个软件包。然后允许用户再定义一个 YAML 文件,来选择性覆盖或者修改 OS 软件包 YAML 文件里的任意字段。这样不但实现了开放式定制,而且用户定制选项都可以以 YAML 配置文件的形式,集中存储管理,或者代码化 Git 管理。”

不过,事情并没有这么简单。

“当用户可以非常方便的定制任意字段,随之而来一个风险:很多包字段之间有条件依赖和约束,用户一不小心,就容易在不知情的情况下,破坏一些关联约束。在过去,很多这种约束在 Git 日志里隐式维护的。比如开发者首先修改一个 SPEC 文件里的版本号,同时去掉一个只适用于老版本的补丁,完成对软件包的一次升级。当暴露在定制环境下,这就是一大脆弱性,会造成事实上难以自由定制。”

而 EulerMaker 的解决办法,是把该补丁适用的版本范围,用条件语句显式的写在软件包 YAML 里。“这样用户随便改版本号,都不会出错,其它关联字段会自适应的变化,从而实现定制自由。”

如此一来,定制能力是强大了,那么易用性又如何?

“一般用户要的不是一堆零件,而是套装。成千上万的定制项,小白用户眼花缭乱,不知道拿它们怎么办,他可能只知道我用的是 OrangePI,那有没有对应的一组定制项可以拿来就用的?”

针对这个问题,EulerMaker 的解决思路如下:

“这组定制项,要由这个专业领域的开发者或者厂商,在社区里提供,我们称之为一个定制层。每一种硬件、场景都可以有这样一个个的定制层。这样场景化 OS 的开发任务就简化为,菜单式选择所需的层,像搭积木一样组合,轻松完成 OS 的场景化分层定制。”

以上,就是 EulerMaker 解决全场景的整体思路。最后,吴峰光总结说:

“一个好用的全场景 OS,一定会是一种生态协作的组织形态。首先把各个场景的公共知识下沉到 BaseOS,统一描述,汇聚复杂枯燥的字段间条件依赖,方便在各个场景中复用。然后创建一个个薄薄的场景化定制层,简单描述各场景下“我要什么”的问题。BaseOS + 多样化场景层,成为 openEuler 社区共同维护和提供的公共组件,通过搭积木的方式,让开发者 DIY 菜单式定制,成就一个轻松愉悦的 OS 创造体验。”

为了让读者们对分层定制有一个直观的概念,吴峰光举了两个例子:

1、Redis 容器裁剪:

env.CC: /usr/bin/musl-gcc -static
env.CFLAGS: -I/usr/musl/include
env.LDFLAGS: -L/usr/musl/lib

buildRequires:
    - musl-gcc

subpackage.redis-server:
    meta.summary: redis-server
    files: %{_bindir}/%{name}-server

redis.yaml 示例

该示例使用十行 YAML,即可裁剪出 1MB 的 Redis 。

​以下视频演示了分层定制 Redis 的过程:

2、内核定制维护:

env.kconfig: CONFIG_BTRFS_FS=y
patchset.my-xxx-improve: xxx.patch

kernel.yaml 示例

该示例使用一个 YAML 文件,两行搞定 Linux 内核的定制维护。

“比如您在一家大公司的基础设施团队,需要在 openEuler 基础上定制 Linux 内核,改一下 kconfig,加一个补丁。在过去,您可能需要拷贝一份 kernel.spec,然后直接在上面修改。这意味着维护上百行的 SPEC 文件,且时不时要从上游回合新的改进,这一过程枯燥而繁琐。现在从 Fork 模式转为搭积木模式,只需维护好一个小小的 kernel.yaml 文件。然后每次拉新的 BaseOS 重新构建,都会自动拿到上游欧拉内核的最新错误修复。这样就很好的降低了开发维护成本,提高了安全性。是一种更加可持续的上下游协同演进方式。”

统一的包格式

在吴峰光的介绍中,我发现了一件令我很感兴趣的事情,就是 openEuler 在探索自己独有的软件包规范。

我们知道,openEuler 现在采用的是业界主流的软件包格式之一:RPM 。这种软件包格式不仅仅被 Redhat Linux 使用,也被 openSUSE、OpenMandriva、Oracle Linux、Tizen 等使用。

而在 openEuler 中,RPM 软件包不仅仅用在我们熟知的服务器、云计算领域,还应用在其它场景中,比如嵌入式。

为了一统软件包的定义,openEuler 采用了新的 YAML 配置语言进行包描述,并接管 RPM 的 SPEC 文件,成为新的开发者界面。吴峰光说,SPEC 文件中采用了大量复杂的宏定义,而 EulerMaker 将这些复杂性隐藏到YAML后面。换言之,openEuler 新的统一构建系统采用的 YAML 配置语言制定了一种更通用、更灵活的包定义。

这是不是代表着 openEuler 会逐渐发展自己的软件包格式?吴峰光表示,在保持兼容性的同时,openEuler 会走出一条自己的路。

别出心裁创建一种新的包格式容易,但是能在兼容既有架构的基础上,又能开拓新的特性,乃至于支持更广泛的场景,这应该很值得期待。

迈向开源开放

经过半年的努力,统一构建系统服务 EulerMaker 已经上线,已经在欧拉社区发挥作用,但是作为一个开源社区的产物,笔者更希望看到它能开源出来,惠及更广大的开源社区,也接受开源社区的批评和贡献。对此,吴峰光博士表示,一定是会开源的,但是目前还需要进一步打磨成熟。对于这样的回应,笔者很认可,毕竟吴峰光博士对开源社区的贡献一向以精益求精而著称。非常期待能早日见到一个强大而完善的统一构建系统开源出来。