2017年4月

气人的软件 1

annoying-software 1

软件:

“你总是能够听取他人的意见,

现在是不是为自己切身考虑下呢?

不管怎样,您的操作已经完成。”

——这软件真气人!

气人的软件 2

annoying-software 2

软件:

真的忘记了吗?这已经是您本周第三次忘记密码了!

您是不是该考虑吃药了!

——你才该吃药呢!

气人的软件 3

annoying-software 3

自作聪明的软件,屡屡让人发疯!

气人的软件 4

annoying-software 4

我觉得现在都用 LCD 显示器有一个好处就是,你可以一拳打破而不用担心骨折(流血那种事情不在我们的考虑之中~)。

好气呀!


via:

作者:Daniel Stori 译者:GHLandy 校对:wxy 合成:GHLandy 点评:wxy

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

为牺牲性能追求生产率而呐喊

让我从关于 Python 中的 asyncio 这个标准库的讨论中休息一会,谈谈我最近正在思考的一些东西:Python 的速度。对不了解我的人说明一下,我是一个 Python 的粉丝,而且我在我能想到的所有地方都积极地使用 Python。人们对 Python 最大的抱怨之一就是它的速度比较慢,有些人甚至拒绝尝试使用 Python,因为它比其他语言速度慢。这里说说为什么我认为应该尝试使用 Python,尽管它是有点慢。

速度不再重要

过去的情形是,程序需要花费很长的时间来运行,CPU 比较贵,内存也很贵。程序的运行时间是一个很重要的指标。计算机非常的昂贵,计算机运行所需要的电也是相当贵的。对这些资源进行优化是因为一个永恒的商业法则:

优化你最贵的资源。

在过去,最贵的资源是计算机的运行时间。这就是导致计算机科学致力于研究不同算法的效率的原因。然而,这已经不再是正确的,因为现在硅芯片很便宜,确实很便宜。运行时间不再是你最贵的资源。公司最贵的资源现在是它的员工时间。或者换句话说,就是你。把事情做完比把它变快更加重要。实际上,这是相当的重要,我将把它再次放在这里,仿佛它是一个引文一样(给那些只是粗略浏览的人):

把事情做完比快速地做事更加重要。

你可能会说:“我的公司在意速度,我开发一个 web 应用程序,那么所有的响应时间必须少于 x 毫秒。”或者,“我们失去了客户,因为他们认为我们的 app 运行太慢了。”我并不是想说速度一点也不重要,我只是想说速度不再是最重要的东西;它不再是你最贵的资源。

速度是唯一重要的东西

当你在编程的背景下说 速度 时,你通常是说性能,也就是 CPU 周期。当你的 CEO 在编程的背景下说 速度 时,他指的是业务速度,最重要的指标是产品上市的时间。基本上,你的产品/web 程序是多么的快并不重要。它是用什么语言写的也不重要。甚至它需要花费多少钱也不重要。在一天结束时,让你的公司存活下来或者死去的唯一事物就是产品上市时间。我不只是说创业公司的想法 -- 你开始赚钱需要花费多久,更多的是“从想法到客户手中”的时间期限。企业能够存活下来的唯一方法就是比你的竞争对手更快地创新。如果在你的产品上市之前,你的竞争对手已经提前上市了,那么你想出了多少好的主意也将不再重要。你必须第一个上市,或者至少能跟上。一但你放慢了脚步,你就输了。

企业能够存活下来的唯一方法就是比你的竞争对手更快地创新。

一个微服务的案例

像 Amazon、Google 和 Netflix 这样的公司明白快速前进的重要性。他们创建了一个业务系统,可以使用这个系统迅速地前进和快速的创新。微服务是针对他们的问题的解决方案。这篇文章不谈你是否应该使用微服务,但是至少要理解为什么 Amazon 和 Google 认为他们应该使用微服务。

微服务本来就很慢。微服务的主要概念是用网络调用来打破边界。这意味着你正在把使用的函数调用(几个 cpu 周期)转变为一个网络调用。没有什么比这更影响性能了。和 CPU 相比较,网络调用真的很慢。但是这些大公司仍然选择使用微服务。我所知道的架构里面没有比微服务还要慢的了。微服务最大的弊端就是它的性能,但是最大的长处就是上市的时间。通过在较小的项目和代码库上建立团队,一个公司能够以更快的速度进行迭代和创新。这恰恰表明了,非常大的公司也很在意上市时间,而不仅仅只是只有创业公司。

CPU 不是你的瓶颈

如果你在写一个网络应用程序,如 web 服务器,很有可能的情况会是,CPU 时间并不是你的程序的瓶颈。当你的 web 服务器处理一个请求时,可能会进行几次网络调用,例如到数据库,或者像 Redis 这样的缓存服务器。虽然这些服务本身可能比较快速,但是对它们的网络调用却很慢。这里有一篇很好的关于特定操作的速度差异的博客文章。在这篇文章里,作者把 CPU 周期时间缩放到更容易理解的人类时间。如果一个单独的 CPU 周期等同于 1 秒,那么一个从 California 到 New York 的网络调用将相当于 4 年。那就说明了网络调用是多少的慢。按一些粗略估计,我们可以假设在同一数据中心内的普通网络调用大约需要 3 毫秒。这相当于我们“人类比例” 3 个月。现在假设你的程序是高 CPU 密集型,这需要 100000 个 CPU 周期来对单一调用进行响应。这相当于刚刚超过 1 天。现在让我们假设你使用的是一种要慢 5 倍的语言,这将需要大约 5 天。很好,将那与我们 3 个月的网络调用时间相比,4 天的差异就显得并不是很重要了。如果有人为了一个包裹不得不至少等待 3 个月,我不认为额外的 4 天对他们来说真的很重要。

上面所说的终极意思是,尽管 Python 速度慢,但是这并不重要。语言的速度(或者 CPU 时间)几乎从来不是问题。实际上谷歌曾经就这一概念做过一个研究,并且他们就此发表过一篇论文。那篇论文论述了设计高吞吐量的系统。在结论里,他们说到:

在高吞吐量的环境中使用解释性语言似乎是矛盾的,但是我们已经发现 CPU 时间几乎不是限制因素;语言的表达性是指,大多数程序是源程序,同时它们的大多数时间花费在 I/O 读写和本机的运行时代码上。而且,解释性语言无论是在语言层面的轻松实验还是在允许我们在很多机器上探索分布计算的方法都是很有帮助的,

再次强调:

CPU 时间几乎不是限制因素。

如果 CPU 时间是一个问题怎么办?

你可能会说,“前面说的情况真是太好了,但是我们确实有过一些问题,这些问题中 CPU 成为了我们的瓶颈,并造成了我们的 web 应用的速度十分缓慢”,或者“在服务器上 X 语言比 Y 语言需要更少的硬件资源来运行。”这些都可能是对的。关于 web 服务器有这样的美妙的事情:你可以几乎无限地负载均衡它们。换句话说,可以在 web 服务器上投入更多的硬件。当然,Python 可能会比其他语言要求更好的硬件资源,比如 c 语言。只是把硬件投入在 CPU 问题上。相比于你的时间,硬件就显得非常的便宜了。如果你在一年内节省了两周的生产力时间,那将远远多于所增加的硬件开销的回报。

那么,Python 更快一些吗?

这一篇文章里面,我一直在谈论最重要的是开发时间。所以问题依然存在:当就开发时间而言,Python 要比其他语言更快吗?按常规惯例来看,我、google 还有其他几个人可以告诉你 Python 是多么的高效。它为你抽象出很多东西,帮助你关注那些你真正应该编写代码的地方,而不会被困在琐碎事情的杂草里,比如你是否应该使用一个向量或者一个数组。但你可能不喜欢只是听别人说的这些话,所以让我们来看一些更多的经验数据。

在大多数情况下,关于 python 是否是更高效语言的争论可以归结为脚本语言(或动态语言)与静态类型语言两者的争论。我认为人们普遍接受的是静态类型语言的生产力较低,但是,这有一篇优秀的论文解释了为什么不是这样。就 Python 而言,这里有一项研究,它调查了不同语言编写字符串处理的代码所需要花费的时间,供参考。

在上述研究中,Python 的效率比 Java 高出 2 倍。有一些其他研究也显示相似的东西。 Rosetta Code 对编程语言的差异进行了深入的研究。在论文中,他们把 python 与其他脚本语言/解释性语言相比较,得出结论:

Python 更简洁,即使与函数式语言相比较(平均要短 1.2 到 1.6 倍)

普遍的趋势似乎是 Python 中的代码行总是更少。代码行听起来可能像一个可怕的指标,但是包括上面已经提到的两项研究在内的多项研究表明,每种语言中每行代码所需要花费的时间大约是一样的。因此,限制代码行数就可以提高生产效率。甚至 codinghorror(一名 C# 程序员)本人写了一篇关于 Python 是如何更有效率的文章

我认为说 Python 比其他的很多语言更加的有效率是公正的。这主要是由于 Python 有大量的自带以及第三方库。这里是一篇讨论 Python 和其他语言间的差异的简单的文章。如果你不知道为何 Python 是如此的小巧和高效,我邀请你借此机会学习一点 python,自己多实践。这儿是你的第一个程序:

import __hello__ 

但是如果速度真的重要呢?

上述论点的语气可能会让人觉得优化与速度一点也不重要。但事实是,很多时候运行时性能真的很重要。一个例子是,你有一个 web 应用程序,其中有一个特定的端点需要用很长的时间来响应。你知道这个程序需要多快,并且知道程序需要改进多少。

在我们的例子中,发生了两件事:

  1. 我们注意到有一个端点执行缓慢。
  2. 我们承认它是缓慢,因为我们有一个可以衡量是否足够快的标准,而它没达到那个标准。

我们不必在应用程序中微调优化所有内容,只需要让其中每一个都“足够快”。如果一个端点花费了几秒钟来响应,你的用户可能会注意到,但是,他们并不会注意到你将响应时间由 35 毫秒降低到 25 毫秒。“足够好”就是你需要做到的所有事情。免责声明: 我应该说有一些应用程序,如实时投标程序,确实需要细微优化,每一毫秒都相当重要。但那只是例外,而不是规则。

为了明白如何对端点进行优化,你的第一步将是配置代码,并尝试找出瓶颈在哪。毕竟:

任何除了瓶颈之外的改进都是错觉。 Any improvements made anywhere besides the bottleneck are an illusion. -- Gene Kim

如果你的优化没有触及到瓶颈,你只是浪费你的时间,并没有解决实际问题。在你优化瓶颈之前,你不会得到任何重要的改进。如果你在不知道瓶颈是什么前就尝试优化,那么你最终只会在部分代码中玩耍。在测量和确定瓶颈之前优化代码被称为“过早优化”。人们常提及 Donald Knuth 说的话,但他声称这句话实际上是他从别人那里听来的:

过早优化是万恶之源 Premature optimization is the root of all evil

在谈到维护代码库时,来自 Donald Knuth 的更完整的引文是:

在 97% 的时间里,我们应该忘记微不足道的效率:过早的优化是万恶之源。然而在关 键的 3%,我们不应该错过优化的机会。 —— Donald Knuth

换句话说,他所说的是,在大多数时间你应该忘记对你的代码进行优化。它几乎总是足够好。在不是足够好的情况下,我们通常只需要触及 3% 的代码路径。比如因为你使用了 if 语句而不是函数,你的端点快了几纳秒,但这并不会使你赢得任何奖项。

过早的优化包括调用某些更快的函数,或者甚至使用特定的数据结构,因为它通常更快。计算机科学认为,如果一个方法或者算法与另一个具有相同的渐近增长(或称为 Big-O),那么它们是等价的,即使在实践中要慢两倍。计算机是如此之快,算法随着数据/使用增加而造成的计算增长远远超过实际速度本身。换句话说,如果你有两个 O(log n) 的函数,但是一个要慢两倍,这实际上并不重要。随着数据规模的增大,它们都以同样的速度“慢下来”。这就是过早优化是万恶之源的原因;它浪费了我们的时间,几乎从来没有真正有助于我们的性能改进。

就 Big-O 而言,你可以认为对你的程序而言,所有的语言都是 O(n),其中 n 是代码或者指令的行数。对于同样的指令,它们以同样的速率增长。对于渐进增长,一种语言的速度快慢并不重要,所有语言都是相同的。在这个逻辑下,你可以说,为你的应用程序选择一种语言仅仅是因为它的“快速”是过早优化的最终形式。你选择某些预期快速的东西,却没有测量,也不理解瓶颈将在哪里。

为您的应用选择语言只是因为它的“快速”,是过早优化的最终形式。

优化 Python

我最喜欢 Python 的一点是,它可以让你一次优化一点点代码。假设你有一个 Python 的方法,你发现它是你的瓶颈。你对它优化过几次,可能遵循这里那里的一些指导,现在,你很肯定 Python 本身就是你的瓶颈。Python 有调用 C 代码的能力,这意味着,你可以用 C 重写这个方法来减少性能问题。你可以一次重写一个这样的方法。这个过程允许你用任何可以编译为 C 兼容汇编程序的语言,编写良好优化后的瓶颈方法。这让你能够在大多数时间使用 Python 编写,只在必要的时候都才用较低级的语言来写代码。

有一种叫做 Cython 的编程语言,它是 Python 的超集。它几乎是 Python 和 C 的合并,是一种渐进类型的语言。任何 Python 代码都是有效的 Cython 代码,Cython 代码可以编译成 C 代码。使用 Cython,你可以编写一个模块或者一个方法,并逐渐进步到越来越多的 C 类型和性能。你可以将 C 类型和 Python 的鸭子类型混在一起。使用 Cython,你可以获得混合后的完美组合,只在瓶颈处进行优化,同时在其他所有地方不失去 Python 的美丽。

星战前夜的一幅截图:这是用 Python 编写的 space MMO 游戏。

当您最终遇到 Python 的性能问题阻碍时,你不需要把你的整个代码库用另一种不同的语言来编写。你只需要用 Cython 重写几个函数,几乎就能得到你所需要的性能。这就是星战前夜采取的策略。这是一个大型多玩家的电脑游戏,在整个架构中使用 Python 和 Cython。它们通过优化 C/Cython 中的瓶颈来实现游戏级别的性能。如果这个策略对他们有用,那么它应该对任何人都有帮助。或者,还有其他方法来优化你的 Python。例如,PyPy 是一个 Python 的 JIT 实现,它通过使用 PyPy 替掉 CPython(这是 Python 的默认实现),为长时间运行的应用程序提供重要的运行时改进(如 web 服务器)。

让我们回顾一下要点:

  • 优化你最贵的资源。那就是你,而不是计算机。
  • 选择一种语言/框架/架构来帮助你快速开发(比如 Python)。不要仅仅因为某些技术的快而选择它们。
  • 当你遇到性能问题时,请找到瓶颈所在。
  • 你的瓶颈很可能不是 CPU 或者 Python 本身。
  • 如果 Python 成为你的瓶颈(你已经优化过你的算法),那么可以转向热门的 Cython 或者 C。
  • 尽情享受可以快速做完事情的乐趣。

我希望你喜欢阅读这篇文章,就像我喜欢写这篇文章一样。如果你想说谢谢,请为我点下赞。另外,如果某个时候你想和我讨论 Python,你可以在 twitter 上艾特我(@nhumrich),或者你可以在 Python slack channel 找到我。


作者简介:

Nick Humrich -- 坚持采用持续交付的方法,并为之写了很多工具。同是还是一名 Python 黑客与技术狂热者,目前是一名 DevOps 工程师。

(题图:Pixabay,CC0)

via: https://medium.com/hacker-daily/yes-python-is-slow-and-i-dont-care-13763980b5a1

作者:Nick Humrich 译者:zhousiyu325 校对:jasminepeng

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

GoTTY 是一个简单的基于 Go 语言的命令行工具,它可以将你的终端(TTY)作为 web 程序共享。它会将命令行工具转换为 web 程序。

它使用 Chrome OS 的终端仿真器(hterm)来在 Web 浏览器上执行基于 JavaScript 的终端。重要的是,GoTTY 运行了一个 Web 套接字服务器,它基本上是将 TTY 的输出传输给客户端,并从客户端接收输入(即允许客户端的输入),并将其转发给 TTY。

它的架构(hterm + web socket 的想法)灵感来自 Wetty 项目,它使终端能够通过 HTTP 和 HTTPS 使用。

先决条件

你需要在 Linux 中安装 GoLang (Go 编程语言) 环境来运行 GoTTY。

如何在 Linux 中安装 GoTTY

如果你已经有一个可以工作的 Go 语言环境,运行下面的 go get 命令来安装它:

# go get github.com/yudai/gotty

上面的命令会在你的 GOBIN 环境变量中安装 GOTTY 的二进制,尝试检查下是否如此:

# $GOPATH/bin/

Check GOBIN Environment

检查 GOBIN 环境

如何在 Linux 中使用 GoTTY

要运行它,你可以使用 GOBIN 环境变量并用命令补全:

# $GOBIN/gotty

另外,要不带完整命令路径运行 GoTTY 或其他 Go 程序,使用 export 命令将 GOBIN 变量添加到 ~/.profile 文件中的 PATH 环境变量中。

export PATH="$PATH:$GOBIN"

保存文件并关闭。接着运行 source 来使更改生效:

# source ~/.profile

运行 GoTTY 命令的常规语法是:

Usage: gotty [options] <Linux command here> [<arguments...>]

现在用 GoTTY 运行任意命令,如 df 来从 Web 浏览器中查看系统分区空间及使用率。

# gotty df -h

GoTTY 默认会在 8080 启动一个 Web 服务器。在浏览器中打开 URL:http://127.0.0.1:8080/,你会看到运行的命令仿佛运行在终端中一样:

Gotty Linux Disk Usage

Gotty 查看 Linux 磁盘使用率

如何在 Linux 中自定义 GoTTY

你可以在 ~/.gotty 配置文件中修改默认选项以及终端,如果该文件存在,它会在每次启动时加载这个文件。

这是由 getty 命令读取的主要自定义文件,因此,按如下方式创建:

# touch ~/.gotty

并为配置选项设置你自己的有效值(在此处查找所有配置选项)以自定义 GoTTY,例如:

// Listen at port 9000 by default
port = "9000"
// Enable TSL/SSL by default
enable_tls = true
// hterm preferences
// Smaller font and a little bit bluer background color
preferences {
font_size = 5,
background_color = "rgb(16, 16, 32)"
}

你可以使用命令行中的 --html 选项设置你自己的 index.html 文件:

# gotty --index /path/to/index.html uptime

如何在 GoTTY 中使用安全功能

由于 GoTTY 默认不提供可靠的安全保障,你需要手动使用下面说明的某些安全功能。

允许客户端在终端中运行命令

请注意,默认情况下,GoTTY 不允许客户端输入到TTY中,它只支持窗口缩放。

但是,你可以使用 -w--permit-write 选项来允许客户端写入 TTY,但是并不推荐这么做因为会有安全威胁。

以下命令会使用 vi 命令行编辑器在 Web 浏览器中打开文件 fossmint.txt 进行编辑:

# gotty -w vi fossmint.txt

以下是从 Web 浏览器看到的 vi 界面(像平常一样使用 vi 命令):

Gotty Web Vi Editor

Gotty Web Vi 编辑器

使用基本(用户名和密码)验证运行 GoTTY

尝试激活基本身份验证机制,这样客户端将需要输入指定的用户名和密码才能连接到 GoTTY 服务器。

以下命令使用 -c 选项限制客户端访问,以向用户询问指定的凭据(用户名:test 密码:@67890):

# gotty -w -p "9000" -c "test@67890" glances

Gotty with Basic Authentication

使用基本验证运行 GoTTY

Gotty 生成随机 URL

限制访问服务器的另一种方法是使用 -r 选项。GoTTY 会生成一个随机 URL,这样只有知道该 URL 的用户才可以访问该服务器。

还可以使用 -title-format "GoTTY – {{ .Command }} ({{ .Hostname }})" 选项来定义浏览器标题。glances 用于显示系统监控统计信息:

# gotty -r --title-format "GoTTY - {{ .Command }} ({{ .Hostname }})" glances

以下是从浏览器中看到的上面的命令的结果:

Gotty Random URL for Glances Linux Monitoring

使用 Gotty 随机 URL 用于 Glances 系统监控

带有 SSL/TLS 使用 GoTTY

因为默认情况下服务器和客户端之间的所有连接都不加密,当你通过 GoTTY 发送秘密信息(如用户凭据或任何其他信息)时,你需要使用 -t--tls 选项才能在会话中启用 TLS/SSL:

默认情况下,GoTTY 会读取证书文件 ~/.gotty.crt 和密钥文件 ~/.gotty.key,因此,首先使用下面的 openssl 命令创建一个自签名的证书以及密钥( 回答问题以生成证书和密钥文件):

# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ~/.gotty.key -out ~/.gotty.crt

按如下所示,通过启用 SSL/TLS,以安全方式使用 GoTTY:

# gotty -tr --title-format "GoTTY - {{ .Command }} ({{ .Hostname }})" glances

与多个客户端分享你的终端

你可以使用终端复用程序来与多个客户端共享一个进程,以下命令会启动一个名为 gotty 的新 tmux 会话来运行 glances(确保你安装了 tmux):

# gotty tmux new -A -s gotty glances 

要读取不同的配置文件,像下面那样使用 –config "/path/to/file" 选项:

# gotty -tr --config "~/gotty_new_config" --title-format "GoTTY - {{ .Command }} ({{ .Hostname }})" glances

要显示 GoTTY 版本,运行命令:

# gotty -v 

访问 GoTTY GitHub 仓库以查找更多使用示例:https://github.com/yudai/gotty

就这样了!你有尝试过了吗?如何知道 GoTTY 的?通过下面的反馈栏与我们分享你的想法。


作者简介:

Aaron Kili 是 Linux 和 F.O.S.S 爱好者,即将成为 Linux SysAdmin 和网络开发人员,目前是 TecMint 的内容创作者,他喜欢在电脑上工作,并坚信分享知识。


via: http://www.tecmint.com/gotty-share-linux-terminal-in-web-browser/

作者:Aaron Kili 译者:geekpi 校对:wxy

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

Software Testing

这幅漫画吐槽了目前的软件开发的乱象:

软件开发的不规范,在开发者自己的电脑上运行正常,在质量检测团队测试时就出现了 Warning,在项目经理测试时已经发生了蓝屏,当用户测试时,发生了“核爆”。

这里讽刺了两件事:

1、开发者开发时,不注重软件质量,无法保证软件在不同环境下的一致性。当然,锅不能完全开发者来背。同时,也是 Docker 这样的产品的用武之地。

2、当质量监测团队出现了 Warning ,项目管理出现了蓝屏的情况下, 问题一级级放大,等到交付给了用户,导致在用户那里出现了“核爆”这样的巨大危害。


via: https://turnoff.us/geek/software-test/

作者:Daniel Stori 译者&点评:Bestony 校对&合成:GHLandy

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

背景

开源目前已经成为全球IT 界和互联网界一致推崇的文化和战略,而阿里巴巴作为国际顶级的互联网企业之一,在开源方面也一直秉持坚定而热忱的态度,积极地将其一些成熟或发展中的产品和技术以开源、开放的态度回馈到社区。

据目前已知的数据,阿里巴巴(以下简称阿里)已经贡献了上百款软件项目,其中去年到现在就开源了三十个左右的项目,得到了开源界和业界积极关注和参与,其中不乏重量级的开源项目。

不过,对于阿里的开源举措,业界也有一些不同的声音,比如有人认为阿里的开源项目虎头蛇尾,往往开源后就置之不理,活跃度走低,缺乏进一步的维护;也有人认为阿里的开源项目实际并没有得到社区的广泛参与和认可,更多还是阿里自身的员工在进行维护,社区并没有对这些项目提供有力的贡献,也没有衍生出重要的分支项目。

为了对中国企业在开源方面的情况进行深入的了解,从而对开源和企业之间的关系做一些定性、定量的分析,那么,让我们来具体分析一下阿里高调开源几年以来的开源项目的发展情况。

说明:我们本次的分析仅以阿里在 GitHub 上的开源项目的公开数据为基础,并不涉及到阿里在其它开源社区和代码托管网站的情况。

首先,我们在 GitHub 上找到阿里的开源团队,其在 GitHub 以团队形式出现的有几个,这里我们主要分析 https://github.com/alibaba和https://github.com/ant-design 两个团队的情况。

在上述的 alibaba团队中,我们可以发现,其名下的 代码库 repository 截止至本文写作时多达 133 个。但是有些项目仅仅是对上游项目的 复刻 fork ,并无或甚少进行修改提交,也有一些项目无实际意义,因此经过筛选后,我们得到了大约110 个项目。

而在 alibaba 团队中正式公开登记的成员(员工和前员工)有101 个,有不少参与贡献的成员没有公开登记,但是我们在做数据分析时,将邮件后缀域是 alibaba-inc.com、alipay.com、taobao.com、aliyun.com 的贡献者也归类为阿里员工。

阿里团队在 GitHub 旗下的项目数量和登记成员数在国内互联网公司来说,已经不算少了,虽然据统计,阿里团队所获得的 星标 star 数全球排名第12位,国内排到了第一,但是和国际上的一些开源领袖公司相比,还有较大距离。(注:如果累计 ant-design 团队项目的星标数,由于该团队旗下的开源项目包括了去年的一个重点项目 ant-design,其排名应该可以更高一些。)

在本文中,我们将从这些开源项目的各个维度的数据来进行分析,主要关注于以下两个方面:

  • 项目的活跃程度
  • 社区的参与程度

在分析之前,我们需要先了解哪些数据对我们来说是重要的,以及其背后反映的意义。

GitHub 上的开源项目指标

在 GitHub 上开源的项目有那些指标呢?可以反映出什么信息?

我们认为可以从以下几个指标进行分析:

1、项目的 提交 commit 数量、 分支 branch 数量、 发布 release 数量。

这代表了项目代码的活跃程度,其中提交数量是主要指标,而分支数量和发布数量虽然也可以侧面反映出代码的活跃程度,但是更多是不同的相关项目管理方式导致的。

2、项目的 拉取请求 pull request (PR)数量、 贡献者 contributor 数量、 问题 issue 数量。

这代表了项目参与者的参与程度,其中拉取请求数量是主要指标,而贡献者数量和问题数量与之正相关,可以反映出贡献者分布密度和项目反馈速度。

3、项目的 复刻 fork 数量、 星标 star 数量、 关注 watch 数量。

这代表了项目的受关注程度,其中复刻数量是主要指标,因为复刻一个项目往往代表了社区更多的参与意愿,并进而通过提交拉取请求、问题等进行参与,这也是社区生态发展不同的下游衍生版本的必由之路。而星标数量和关注数量,现在由于逐渐蔓延的 GitHub 营销潮流,其水分比较大,可以作为辅助指标参考。

4、项目的持续时长和最后更新时间。

项目的持续时长是从项目建立开始到最后更新时间之间的时长,这代表了项目的生存时间。如果最后更新时间是很久以前,则代表该项目已经陷入消亡中。

项目的提交数量

阿里开源的项目很多,但如同大多数企业组织一样,各个项目的活跃程度大相径庭。有的活跃项目得到了来自社区上万的 星标 star 、数千的 复刻 fork 乃至上千的 拉取请求 pull request ,项目本身也拥有数万的 提交 commit 乃至几十个 分支 branch ;而有的项目则数据寥寥,基本上陷入沉寂,其中有一半数量的项目最后提交于一年前,甚至还有 5 个项目的最后更新于 5 年前——基本上可以判定已经停止维护。

在统计时,我们发现一种情况,复刻或衍生的上游项目,会将上游的提交数量、分支数量等数据继承下来,因此在针对阿里对该项目的贡献和发展方面进行分析时,应该将这部分数据减去。这样的话,在阿里团队名下列出的一些知名项目,如复刻自 CocoaPods/Specs 的 Specs 项目拥有 14 万之多的提交数,但是阿里本身并没有对其复刻的版本进行任何提交;又比如阿里的重点项目 AliSQL 是基于 MySQL 官方版本的一个衍生版,因此其近 10万的提交数中绝大部分是 来自MySQL 发展多年来积累下的提交数量,本身阿里在将其衍生为 AliSQL 之后,只有 52 个提交数;同样 AliSQLBackup 的 10 万多个提交数也是来自于上游项目,阿里几乎没有做过更新提交,并且也停止维护两年了;因此,这些项目在统计时,我们会从阿里复刻或衍生该项目时开始计数提交数量。

当然,我们知道,仅仅以提交数来评估一个项目的活跃度是片面的,比如说,上述的 AliSQL 虽然只有 52 个提交,但是其由于开发模式和审慎态度的缘故,往往一次提交的代码量比较多,其中某次提交行数高达 5 万多行,而对上游 MariaDB 的贡献虽然只有三次提交,但是已经占到了总代码量的 1%。鉴于此,我们会不仅仅从提交数,还从复刻数、问题数等多个方面来综合进行观察。

下表是阿里旗下开源的提交数前十的项目:

项目创建天数提交数员工提交数社区提交数日均提交数
ant-design730天85672494597311.60
weex398天5779804497514.52
druid1987天4056106729892.04
fastjson1987天188383410490.95
LuaViewSDK461天1195118962.59
rax180天10017682335.56
tengine1848天9076112960.49
dubbo1758天414370440.24
freeline252天3772271501.50
anyproxy975天369352170.38

我们可从上表中看到,阿里旗下开源的项目提交数最多的是 ant-design 项目,这是蚂蚁金服旗下推出的一种 UI 设计语言,在开源两年来,得到了快速的发展。我们可以看到,其提交数约计比第二名高过 1/3,其中社区提交数是成员提交数的两倍,并且日均提交数也达到了很高的水平。

第二名是 weex 项目,这是一个用于构建跨平台移动应用 UI 的框架,前些时间刚刚捐献给 Apache 基金会孵化管理。项目开源于 2016 年底,目前已有近 6 千提交,其中社区提交数量是阿里员工的提交数的 6 倍!而且,日均提交数竟然达到了 14.52 个,其发展速度还要超过了第一名 ant-design。这代表了社区强烈的参与意愿,并且该项目得到了社区的广泛应用。

第三名是 druid 项目,这是一个是“为监控而生的数据库连接池”,自称“是 Java 语言中最好的数据库连接池”。采用 Java 开发,也是阿里重点发展的项目之一,2011 年底开源发布,目前已经有 4 千余个提交,代码迭代很快。而且,非阿里员工的提交数量是阿里员工的提交数量的三倍左右

应该说,这些排名较高的项目的活跃度都不错,其中只有一个项目是更新于半年前的,其它的项目都在近期有不同程度的更新维护。

从上面的项目的提交来源看,提交数最高前三名来自社区的提交要超过了阿里员工的提交,甚至远远超过,这说明这三个项目得到了社区的普遍支持,我们在后面分析复刻情况时也可以看到,这两个项目的复刻数都很高。而之后排名的项目,却呈现了另外一种趋势,即来自阿里员工的提交数要超过或远超来自社区的提交数,相应的表示出这些项目在社区的受欢迎程度要差一些。

从整体的这些项目来看,各个项目的提交数明显呈长尾样分布:

项目提交数分布

而且,我们可以看到,从提交数排名第 8 位的项目开始,提交数呈断崖式下降,但是整体的以正态分布呈现:

项目提交数分布(去除前 7 名)

从上述分布上来看,阿里旗下的开源项目的发展情况正常,既有活跃项目,也有消亡项目。

我们判断,阿里对其开源项目的管理处于自由生长状况,并没有从统一管理的层面来督导、辅导各个开源项目的发展,也没有对陷入消亡的项目进行进一步处置和收尾,也就是说,一些烂尾的项目并没有进行妥善处置。

为了验证这个结论,我们来看一下阿里旗下开源的项目的最近更新时间。

项目的最近更新时间

抛开一些项目内的无关紧要的更新(如修订一些 README,pom.xml 等),我们发现这 133 个项目当中有 60 个项目更新于一年前,其中更新于 4 年前及以上的有 30 个。可见有不少遗留项目缺乏处置。

当然,根据上图也可以反映出近年来阿里的开源项目整体的发展趋势要超过过去几年。

项目的拉取请求数和问题数

GitHub 开创性的使用了 拉取请求 pull request (经常简称为 PR)的方式来为开源项目提供社区协作支持。无论是项目成员还是外部合作者,以及偶尔的关注该项目的贡献者,都可以通过发起拉取请求来给某个项目提交补丁,项目维护人员可以对该拉取请求进行审核,如果审核通过,就会“拉取”该合并请求到项目中,从而将贡献者提交的代码融合到项目代码之中。

作为社区贡献者,对一个项目发起贡献的主要方式就是给该项目发起拉取请求。虽然也有不少项目要求几乎所有成员都必须以拉取请求的方式来提交其代码,而不允许直接提交到仓库中,但是通常而言,一个项目的拉取请求数可以从侧面反映出一个项目的社区(外部)参与程度。

而对一个项目作出贡献的方式不仅仅是贡献代码,还有对项目中发现的问题、缺失功能所提交的报告也是一种重要的方式,这些信息在 GitHub 中统一被称之为 问题 issue

每个拉取请求和问题,都会被项目维护者进行审核,并进行处置。比如对于拉取请求,可以接受、可以拒绝;对于问题,可以回复、也可以忽略/关闭。

一般来说,活跃的项目其拉取请求数量和问题数量也会越大,但是我们这里不去做这些数量的排名,我们感兴趣的是,这些拉取请求和问题中,开放和关闭的比例情况。

如下表,我们列出了拉取请求未接纳比例最高的前十名(这里略去了拉取请求数低于10的项目)。

项目开放 PR 关闭 PR PR PR 开放比
LuaViewSDK831172.73%
DataX15163148.39%
dubbo577112844.53%
RocketMQ18325036.00%
nginx-http-concat6121833.33%
jstorm17537024.29%
anyproxy9303923.08%
atlas4172119.05%
otter111128.33%
nginx-tfs113147.14%

我们可以看到,这些项目中拉取请求未接纳的比例最高的有的高达 70% 以上,当然,另外一方面,我们也看到了这些项目的拉取请求数都不高。这可以反映出该项目的社区参与积极性不高。

但是几个提交数比较高的项目,除个别情况外,其拉取请求未接纳的比例都很低:

项目PR 开放比提交数
ant-design0.10%8467
weex1.03%5779
druid0.50%4056
fastjson0.00%1883
LuaViewSDK72.73%1195
rax3.82%1001
tengine6.83%907
dubbo44.53%414
freeline0.00%377
anyproxy23.08%369
terraform-provider0.00%355

这说明这些项目的活跃不是没有道理的。

究竟是由于社区参与积极性不高导致的未接纳比例高,还是反之,我们认为或许是彼此互相影响导致的。

再让我们来看看问题数。

项目全部问题开放问题关闭问题问题开放比
oceanbase12120100.00%
mirrors4645197.83%
ons1211191.67%
simpleimage1513286.67%
LVS2521484.00%
tfs2319482.61%
taokeeper3123874.19%
nginx-http-concat44291565.91%
dubbo42327315064.54%
AndFix34121912264.22%
DataX1831137061.75%

我们可以看到,有些项目,居然所有的问题都没有处置,比如 oceanbase,甚至连被寄予厚望的 dubbo 和 DataX 也有相当比例的问题没有解决——难怪有人对阿里开源项目烂尾颇有微词。

那么我们同样来看看几个活跃项目的问题解决比例:

项目全部问题问题开放比提交数
ant-design58601.69%8467
weex297712.83%5779
druid167225.90%4056
fastjson113723.13%1883
LuaViewSDK7625.00%1195
rax2186.88%1001
tengine88417.99%907
dubbo42364.54%414
freeline7583.30%377
anyproxy16137.27%369

我们可以看到,这些活跃项目的问题解决比例还是比较高的。

项目的复刻数

下面我们来看看这些项目的复刻数。前面我们说过,开源项目的复刻数代表了(外部)社区参与该项目的积极性。因为复刻一个项目的意图可能有以下几种:

  • 保留(冻结)该项目当前的代码以做将来之用,以避免该项目出于种种原因被删除、关闭。
  • 要对该项目提交补丁(拉取请求),需要复刻一份,完成修改后发起拉取请求。
  • 意图衍生该项目,通常是为了发展不同的方向。
  • 只是为了方便找到该项目?可能更习惯这种方式,而不是加以星标、关注等方式来标记该项目。

无论是哪种情况,我们可以看到,复刻这种行为基本上可以代表复刻者对该项目的积极参与意愿。

以下是阿里开源的项目中复刻数最高十个项目:

项目创建天数复刻数日均复刻数PR 全部问题
dubbo1763天79464.51128423
fastjson1992天30611.541711137
druid1992天29461.488011672
ant-design730天26593.6314135860
RocketMQ894天21082.3650479
weex402天19184.7713602977
tengine1853天15320.83571884
jstorm1322天15311.1670485
AndFix580天13262.297341
canal1555天11680.7542291

从上面我们可以看到,复刻数最高的项目是一个名为 dubbo 的分布式、高性能的 RPC 框架,是阿里巴巴 SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。Dubbo 的复刻数远高于第二名的 fastjson,但是其相应的拉取请求数和问题数却不相称的低——这代表了什么?社区或业界觉得这个项目有价值,但是鲜于应用场景,也缺乏参与回馈的能力(或动力?)。

而第二名,fastjson 却显著的问题数比较高,这表明社区在大量使用该项目,因此产生(发现)的问题或需求也比较多。但是其拉取请求数却没有与问题数相应的提高,侧面说明了该项目本身参与开发的难度较高。

第三名 druid,是一个 java 的数据库连接池,其问题数和拉取请求数都很高,我们认为它的活跃度和社区参与程度都很健康。

第四到六名 ant-design 、RocketMQ 、 weex 都是阿里重点发展的项目,并且后两者都捐赠给了 apache 基金会孵化管理,而且 weex 的发展更是后来居上,就拉取请求和问题数来说,weex 的发展更健康一些。

那么,结论呢?可以大致的看出,复刻数较高的项目其日均复刻数也存在较大的波动,说明其发展速度不一,但是复刻数可以作为一个项目是否健康发展的指标之一,但是该指标应和拉取请求数和问题数综合来看。

项目的星标数和关注数

对 GitHub 上的开源项目的观察久已有之,但是人们一般习惯于按项目的星标数来进行排名。不过,现在随着 GitHub 的日益流行,星标这种成本低廉简单操作已经逐渐失去了作为排名依据的意义,以至于一些 markdown 项目(也称为 awesome 项目)虽然并无代码,仅仅一篇以 markdown 格式提交的资源大全,也往往取得了不错的星标数。我们认为,对于开源项目,尤其是特指代码方面的开源项目时,其星标数并不应该与那些 markdown 项目进行横向比较。当然,同样作为开源代码项目,星标数还是有一定的参考价值的。

我们来看看阿里旗下开源项目的星标数前十的项目:

项目创建天数星标数关注数日均星标数
weex402天13864199234.49
ant-design730天1274568017.45
fastjson1992天86749454.35
dubbo1763天815917654.63
druid1992天601411253.02
tengine1853天53847782.91
AndFix580天51674388.91
atlas48天406829184.75
RocketMQ894天36527274.09
freeline257天351119513.66
dexposed657天34753925.29

啊哦,不出意外,这些项目基本上还是和复刻数排名比较相近。Weex 在该项排名中又取得了第一。令我们比较感兴趣的是,排名稍后的几个项目的开源时间并不算长。让我们来以日均星标数排名看看,这回我们多取几名:

项目创建天数星标数关注数日均星标数
atlas48天406829184.75
vlayout49天325012066.33
UltraViewPager19天9032347.53
weex402天13864199234.49
Tangram-iOS19天4552623.95
Tangram-Android19天4013021.11
LazyScrollView46天8423018.30
ant-design730天1274568017.45
rax185天275511914.89
freeline257天351119513.66
ARouter124天15516012.51
AndFix580天51674388.91
BeeHive259天1908987.37
AliSQL264天18773757.11
dexposed657天34753925.29
dubbo1763天815917654.63
fastjson1992天86749454.35
RocketMQ894天36527274.09
LuaViewSDK466天18211833.91
HandyJSON209天810413.88

发现什么没有?日均星标数的前几名,或者说大多数都是相当年轻的开源项目,其星标增长速度要让几个已经开源了几年的项目瞠目其后。我们判断,这说明阿里现在在开源方面已经处于高调宣传模式,对于新开源的项目,都有一波持续和明确的传播意图。但是我们认为,作为一家商业企业,这也代表了阿里已经将开源作为一个主流战略、也是其企业文化和品牌形象推广的重要方面,那么是不是代表着阿里以后的开源项目的支持力度和维护热情会更高、更持久呢?

总结

以上,我们通过对阿里旗下开源的多个项目的各个指标进行了横向和纵向的比较,从中也观察到了一些有趣的现象。但是这些数据并不能完全的反映出一个一致的结论,只是,从整体来看我们认为,阿里巴巴旗下的开源项目,正在以更快、更主动的方式在发展,至于说是否还会出现之前的那种开源之后被抛弃的情况,下定论还为时尚早。这或许要看阿里的开源委员会是否能够制定更宏观的发展战略而定。

不过,无论如何,我们欣喜的看到,阿里在践行开源理念、积极主动的拥抱、回馈开源方面,取得了瞩目的成就。我们也期待国内的更多互联网企业、IT 企业可以在开源方面有更多的实际行动,让中国这个世界上除了美国之外第二大的互联网大国在开源方面也取得相应的成就。

了解 Fedora 第一个官方支持树莓派的版本

 title=

2016 年 10 月,Fedora 25 Beta 发布了,随之而来的还有对 树莓派 2 和 3 的初步支持。Fedora 25 的最终“通用”版在一个月后发布,从那时起,我一直在树莓派上尝试不同的 Fedora spins。

这篇文章不仅是一篇 树莓派 Raspberry Pi 3 上的 Fedora 25 的点评,还集合了技巧、截图以及我对 Fedora 第一个官方支持 Pi 的这个版本的一些个人看法。

在我开始之前,需要说一下的是,为写这篇文章所做的所有工作都是在我的运行 Fedora 25 的个人笔记本电脑上完成的。我使用一张 microSD 插到 SD 适配器中,复制和编辑所有的 Fedora 镜像到 32GB 的 microSD 卡中,然后用它在一台三星电视上启动了树莓派 3。 因为 Fedora 25 尚不支持内置 Wi-Fi,所以树莓派 3 使用了以太网线缆进行网络连接。最后,我使用了 Logitech K410 无线键盘和触摸板进行输入。

如果你没有条件使用以太网线连接在你的树莓派上玩 Fedora 25,我曾经用过一个 Edimax Wi-Fi USB 适配器,它也可以在 Fedora 25 上工作,但在本文中,我只使用了以太网连接。

在树莓派上安装 Fedora 25 之前

阅读 Fedora 项目 wiki 上的树莓派支持文档。你可以从 wiki 下载 Fedora 25 安装所需的镜像,那里还列出了所有支持和不支持的内容。

此外,请注意,这是初始支持版本,还有许多新的工作和支持将随着 Fedora 26 的发布而出现,所以请随时报告 bug,并通过 Bugzilla、Fedora 的 ARM 邮件列表、或者 Freenode IRC 频道#fedora-arm,分享你在树莓派上使用 Fedora 25 的体验反馈。

安装

我下载并安装了五个不同的 Fedora 25 spin:GNOME(默认工作站)、KDE、Minimal、LXDE 和 Xfce。在多数情况下,它们都有一致和易于遵循的步骤,以确保我的树莓派 3 上启动正常。有的 spin 有已知 bug 的正在解决之中,而有的按照 Fedora wik 遵循标准操作程序即可。

 title=

树莓派 3 上的 Fedora 25 workstation、 GNOME 版本

安装步骤

1、 在你的笔记本上,从支持文档页面的链接下载一个树莓派的 Fedora 25 镜像。

2、 在笔记本上,使用 fedora-arm-installer 或下述命令行将镜像复制到 microSD:

xzcat Fedora-Workstation-armhfp-25-1.3-sda.raw.xz | dd bs=4M status=progress of=/dev/mmcblk0

注意:/dev/mmclk0 是我的 microSD 插到 SD 适配器后,在我的笔记本电脑上挂载的设备名。虽然我在笔记本上使用 Fedora,可以使用 fedora-arm-installer,但我还是喜欢命令行。

3、 复制完镜像后,先不要启动你的系统。我知道你很想这么做,但你仍然需要进行几个调整。

4、 为了使镜像文件尽可能小以便下载,镜像上的根文件系统是很小的,因此你必须增加根文件系统的大小。如果你不这么做,你仍然可以启动你的派,但如果你一旦运行 dnf update 来升级你的系统,它就会填满文件系统,导致糟糕的事情发生,所以趁着 microSD 还在你的笔记本上进行分区:

growpart /dev/mmcblk0 4
resize2fs /dev/mmcblk0p4

注意:在 Fedora 中,growpart 命令由 cloud-utils-growpart.noarch 这个 RPM 提供的。

5、文件系统更新后,您需要将 vc4 模块列入黑名单。更多有关此 bug 的信息在此。

我建议在启动树莓派之前这样做,因为不同的 spin 有不同表现方式。例如,(至少对我来说)在没有黑名单 vc4 的情况下,GNOME 在我启动后首先出现,但在系统更新后,它不再出现。 KDE spin 则在第一次启动时根本不会出现 KDE。因此我们可能需要在我们的第一次启动之前将 vc4 加入黑名单,直到这个错误以后解决了。

黑名单应该出现在两个不同的地方。首先,在你的 microSD 根分区上,在 etc/modprode.d/ 下创建一个 vc4.conf,内容是:blacklist vc4。第二,在你的 microSD 启动分区,添加 rd.driver.blacklist=vc4extlinux/extlinux.conf 文件的末尾。

6、 现在,你可以启动你的树莓派了。

启动

你要有耐心,特别是对于 GNOME 和 KDE 发行版来说。在 SSD(固态驱动器)几乎即时启动的时代,你很容易就对派的启动速度感到不耐烦,特别是第一次启动时。在第一次启动 Window Manager 之前,会先弹出一个初始配置页面,可以配置 root 密码、常规用户、时区和网络。配置完毕后,你就应该能够 SSH 到你的树莓派上,方便地调试显示问题了。

系统更新

在树莓派上运行 Fedora 25 后,你最终(或立即)会想要更新系统。

首先,进行内核升级时,先熟悉你的 /boot/extlinux/extlinux.conf 文件。如果升级内核,下次启动时,除非手动选择正确的内核,否则很可能会启动进入救援( Rescue )模式。避免这种情况发生最好的方法是,在你的 extlinux.conf 中将定义 Rescue 镜像的那五行移动到文件的底部,这样最新的内核将在下次自动启动。你可以直接在派上或通过在笔记本挂载来编辑 /boot/extlinux/extlinux.conf

label Fedora 25 Rescue fdcb76d0032447209f782a184f35eebc (4.9.9-200.fc25.armv7hl)
            kernel /vmlinuz-0-rescue-fdcb76d0032447209f782a184f35eebc
            append ro root=UUID=c19816a7-cbb8-4cbb-8608-7fec6d4994d0 rd.driver.blacklist=vc4
            fdtdir /dtb-4.9.9-200.fc25.armv7hl/
            initrd /initramfs-0-rescue-fdcb76d0032447209f782a184f35eebc.img

第二点,如果无论什么原因,如果你的显示器在升级后再次变暗,并且你确定已经将 vc4 加入黑名单,请运行 lsmod | grep vc4。你可以先启动到多用户模式而不是图形模式,并从命令行中运行 startx。 请阅读 /etc/inittab 中的内容,了解如何切换 target 的说明。

 title=

树莓派 3 上的 Fedora 25 workstation、 KDE 版本

Fedora Spin

在我尝试过的所有 Fedora Spin 中,唯一有问题的是 XFCE spin,我相信这是由于这个已知的 bug 导致的。

按照我在这里分享的步骤操作,GNOME、KDE、LXDE 和 minimal 都运行得很好。考虑到 KDE 和 GNOME 会占用更多资源,我会推荐想要在树莓派上使用 Fedora 25 的人使用 LXDE 和 Minimal。如果你是一位系统管理员,想要一台廉价的 SELinux 支持的服务器来满足你的安全考虑,而且只是想要使用树莓派作为你的服务器,开放 22 端口以及 vi 可用,那就用 Minimal 版本。对于开发人员或刚开始学习 Linux 的人来说,LXDE 可能是更好的方式,因为它可以快速方便地访问所有基于 GUI 的工具,如浏览器、IDE 和你可能需要的客户端。

 title=

树莓派 3 上的 Fedora 25 workstation、LXDE。

看到越来越多的 Linux 发行版在基于 ARM 的树莓派上可用,那真是太棒了。对于其第一个支持的版本,Fedora 团队为日常 Linux 用户提供了更好的体验。我很期待 Fedora 26 的改进和 bug 修复。

(题图: opensource.com)


作者简介:

Anderson Silva - Anderson 于 1996 年开始使用 Linux。更精确地说是 Red Hat Linux。 2007 年,他作为 IT 部门的发布工程师时加入红帽,他的职业梦想成为了现实。此后,他在红帽担任过多个不同角色,从发布工程师到系统管理员、高级经理和信息系统工程师。他是一名 RHCE 和 RHCA 以及一名活跃的 Fedora 包维护者。


via: https://opensource.com/article/17/3/how-install-fedora-on-raspberry-pi

作者:Anderson Silva 译者:geekpi 校对:jasminepeng

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