《代码英雄》第三季（4）：深入 Perl 语言的世界

>
> 代码英雄讲述了开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。
>
>
>

>
> **什么是《代码英雄》**
>
>
> <ruby> 代码英雄 <rt>  Command Line Heroes </rt></ruby>是世界领先的企业开源软件解决方案供应商红帽（Red Hat）精心制作的原创音频播客，讲述开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。该音频博客邀请到了谷歌、NASA 等重量级企业的众多技术大牛共同讲述开源、操作系统、容器、DevOps、混合云等发展过程中的动人故事。
>
>
>

![](/data/attachment/album/202012/03/123749k2lozf7zrtprxfjo.png)

本文是《[代码英雄](https://www.redhat.com/en/command-line-heroes)》系列播客[《代码英雄》第三季（4）：深入 Perl 语言的世界](https://www.redhat.com/en/command-line-heroes/season-3/diving-for-perl)的[音频](https://cdn.simplecast.com/audio/a88fbe/a88fbe81-5614-4834-8a78-24c287debbe6/be4cc2b9-8548-476d-98d5-874a93439675/CLH_S3E4_The_Perl_Dive_vFINAL_tc.mp3)脚本。

>
> 导语：语言来了又走。只有少数几种语言具备了登峰造极的能力，而能留在那里的则更少。Perl 有过一次惊人的崛起，也有过一次平静的低迷，现在已经在编程世界中找到了自己的位置。
>
>
> Perl似乎注定要统治网络。Michael Stevenson 和 Mike Bursell 描述了 Perl 的设计如何使它成为早期 web 的理想选择。我们从 Conor Myhrvold 那里听到了它的座右铭：“<ruby> 实现它的方法不止一种 <rt>  There is more than one way to do it. </rt></ruby>”。Elizabeth Mattijsen 分享了，尽管 Perl 有优势，但漫长的开发周期如何减缓了 Perl 的发展。虽然它不再是最顶级的网络语言，但 John Siracusa 指出，Perl 作为一种小众工具仍然存在。
>
>
>

**00:00:02 - Saron Yitbarek**：

想象一下 Perl 语言的创建者 Larry Wall 在 1999 年的一次会议上站在麦克风前，留着他标志性的浓密胡子和梳理过的刘海，感觉相当好，因为他所发明的语言正在越来越受欢迎。

**00:00:19 - 配音演员**：

声音测试。

**00:00:19 - Saron Yitbarek**：

Perl 语言轻而易举地超越了 COBOL、Visual Basic，而 Python 呢? Python 仍然是一个不入流的竞争者，是Larry Wall 的几个玩笑素材。Wall 展示了 [dice.com](http://dice.com) 报告中的人群数据，在那时来看，Perl 语言的未来是非常、非常光明的。然而之后 Perl 的未来就不再如此了。20 年之后，[dice.com](http://dice.com) 在 2018 年夏天将 Perl 列为最可能灭绝的语言之一。短短 20 年之间发生了什么？

\*\*00:00:59 \*\*：

我是 Saron Yitbarek，这里是《代码英雄》，一档红帽公司的原创播客。这一季是关于我们编程语言的力量和前景的。在上一集我们追踪了搭上了互联网顺风车的 JavaScript 的疯狂崛起。

**00:01:19**：

并不是每一种语言都有一个不停地成长和成功的故事。大多数语言的出现，在当时非常特殊的生态系统中发挥了它们的作用，然后当我们的编程生活里需要其他类型的工具时它们就开始消退。

**00:01:37**：

本集我们将深入了解 Perl 世界。是什么造就了它早期的成功，为什么它的成功突然就被颠覆了？我们所处的环境，我们的基础设施，我们的硬件，各种因素都会决定哪些语言会繁荣，哪些会开始萎缩。这就是 Perl 语言的故事的魅力所在。

**00:02:08**：

我们知道 Perl 并没有统治世界，但是退回到上世纪 90 年代的时候，却看不到这一点。Tim Berners-Lee 在 1991 年发明了<ruby> 万维网 <rt>  World Wide Web </rt></ruby>（WWW），它迅速创造了一个全新的基于 Web 的开发领域。谁也说不准会是哪种编程语言在这个新领域取得成功。

**00:02:31 - Michael Stevenson**：

在 Web 出现的时候，所有人都等待着会有什么事情发生。那个时候整个世界都是令人兴奋的。

**00:02:39 - Saron Yitbarek**：

Michael Stevenson 是<ruby> 阿姆斯特丹大学 <rt>  University of Amsterdam </rt></ruby>媒体研究的副教授。他为我们描述了早期的 Web。人们见过 Usenet，也见过 ARPANET。他们看到了<ruby> 美国在线 <rt>  America Online </rt></ruby>，还有一些其它的东西。但是直到 Web 出现，互联网的全部发展潜力才真正得到体现。突然之间，你就可以通过鼠标和点击进入了这个巨大的互联世界。这是一个出乎意料的事情。

**00:03:09 - Michael Stevenson**：

你要是记得 1993 年，也就是 Web 开始崭露头角的那一年，也是《<ruby> 连线杂志 <rt>  Wired Magazine </rt></ruby>》开始出版的那年。在那之前类似《Mondo 2000》这类的杂志真的让电脑看起来像神秘知识的来源，让电脑看起来很酷。

**00:03:32**：

因此从这个意义上说，Web 也到达了一个相当特定的时期，人们已经准备好以这样的方式迎接技术的兴起。

**00:03:43 - Saron Yitbarek**：

故事在这个时候开始了：Larry Wall 在 1987 年创建了 Perl，4 年后万维网才开始兴起。Larry Wall 给世界带来的 Perl 最初只是一种通用的 Unix 脚本语言。当然，它确实很有用，但同时 Perl 还有一些秘密元素，这些元素使它成为即将到来的 Web 开发世界的理想语言。

**00:04:14 - Michael Stevenson**：

比较有名的是 Perl 是 Larry Wall 在参与的一个美国国家安全局（NSA）的秘密项目中发明的，基本上他所做的就是创建一个类似黑客版的新闻栏目，运行在 Usenet 上，因此 Perl 语言从一开始就是操作文本和将数据从一个地方移动到另一个地方，这完全符合 Web 的需求。而 Perl 作为一种易于使用的脚本语言，更加接近于自然语言。它可以用来快速开发东西，所有这些都让 Perl 成为了一个完美的契机，不仅适合专业用户，也适合新加入的业余爱好者。

**00:05:09 - Saron Yitbarek**：

很偶然的是，当 Web 出现时，Perl 已经为 Web 做好了准备。Larry Wall 不可能知道 Web 即将出现。但当它出现时正好相互吻合。但我认为还有一点很关键：Perl 是一种自由语言。Larry Wall 在<ruby> 自由软件基金会 <rt>  Free Software Foundation </rt></ruby>开发的 GPL（<ruby> 通用公共许可证 <rt>  General Public License </rt></ruby>）下发布了它。

**00:05:37**：

Larry Wall 让他的语言自由开源的决定，这完全符合刚刚开始出现的基于 Web 的新思维方式，同时 Perl 在其他方面也很有前瞻性。

**00:05:50 - Michael Stevenson**：

Perl 的开放性令人难以置信，在某种意义上，它总是愿意整合一些其他的东西，新的东西。这和 Larry Wall 的身份很相配。他是个很开放谦虚的人，总是仔细考虑别人的想法，并试着设身处地为别人着想。对我来说 Perl 作为一种语言，以及作为一个社区的性格，在很长一段时间里，真的很符合这一点。

**00:06:27 - Saron Yitbarek**：

同样 Perl 非常适合 Web 早期的、狂野的西部阶段，也就是黑客时代。实际上 Perl 的座右铭之一就是“<ruby> 实现它的方法不止一种 <rt>  There is more than one way to do it. </rt></ruby>”。

**00:06:39 - Michael Stevenson**：

在 Perl 的鼎盛时期和这个试验性的开放 Web 的鼎盛时期之间，存在着一种近乎浪漫的联系，在它变得如此被几个平台所控制之前。

**00:06:56 - Saron Yitbarek**：

记得上世纪 90 年代是互联网历史上的一段启蒙时期，那时人们还在争先恐后地想知道还有哪些是可能的。那时对编程的需求是巨大的，每个人都需要有一个网页，这意味着一群全新的开发人员，他们都对新的做事方法持开放态度。问题变成了“好吧，我们有了一个全新的领域，但用什么语言来完成这项工作呢？”

**00:07:26**：

Perl 虽然并不是这个问题的最终答案，但对于很多人来说 Perl 是他们首选的答案。

**00:07:34 - Michael Stevenson**：

我并不是说我更愿意看到加载速度超慢的网页、也没有谷歌搜索引擎的时代，但我确实认为那个时代有一些特别的东西，当时有一些人，在他们的宿舍里，创建了一个类似 slashdot 的东西。而现在随着 Web 已经变得如此主流、专业化和被集中在几个大公司中，我们确实怀念那个时代。对我来说，Perl 比其他任何早期的故事都更能象征这一点。

**00:08:15 - Saron Yitbarek**：

Michael Stevenson 是阿姆斯特丹大学媒体研究的副教授。

**00:08:24 - Saron Yitbarek**：

之后，随着 90 年代的到来，Perl 作为一种能适应早期互联网发展潜力的语言出现了，它是一个时代的语言。Larry Wall 和他所创造的 Perl 正好明白了 Web 的本质。

**00:08:40 - Mike Bursell**：

在网上你可以随意搜索，也可以随时创建网页，这是互联网的美丽新世界，你可以随时做这些事情。

**00:08:52 - Saron Yitbarek**：

这位是 Mike Bursell，红帽公司的首席安全架构师。Mike 是 90 年代中期发现和使用 Perl 的黑客之一。

**00:09:00 - Mike Bursell**：

对于 Web 来说，Perl 是许多人的起点。Java™ 语言还处于早期阶段，它在文本输入输出方面并不是很出色。如果你想进行查询和生成页面，Perl 是人们都在使用的工具。

**00:09:22**：

Perl 非常适合，因为它擅长获取文本，并使用文本做其他事情，而这正是 Web 所需要的。

**00:09:31 - Saron Yitbarek**：

顺便需要说一下的是，Larry Wall 有语言学背景，这就解释了为什么 Perl 有强大的文本解析能力。正如 Mike Bursell 提到的，这是一笔巨大的好处，因为在早期，Web 主要是一种基于文本的媒介，因为那时候人们没有足够的带宽来处理图像。

**00:09:51 - Mike Bursell**：

它很容易使用，也很容易复制。人们在分享方面非常开放，而且它的输出速度很快，这些都是好东西。

**00:10:02**：

哦，当然还有一点，就是你可以用管道使用它。所以，这是非常多的人所习惯的，而且非常容易测试，甚至离线测试，这都是非常有用的。

**00:10:13 - Saron Yitbarek**：

尤其对那些在 Web 的世界中重新规划自己生活的系统管理员来说非常有用。

**00:10:21 - Mike Bursell**：

Perl 是给系统管理员们的真正礼物。即使在那个年代，如果你做一些事情，你会得到很多日志。管理这些日志，分解它们，搜索它们，并能够以不同的方式显示它们，或获取任何其他大型文本语料库（主要就是日志），甚至可以对它们进行调试。除非你要在命令行里用管道方式传输 `orc`、`sed` 之类的东西，以及 `ed` 命令，那样的话你很快就会变得非常痛苦，而 Perl 正好适合让你去处理这些事情。

**00:10:55 - Saron Yitbarek**：

到上世纪 90 年代后期，Perl 5 已经聚集了一个强大的用户群体。像 Fortran 和 C 这样的旧语言依赖于庞大而昂贵的硬件，而 Perl 更有生命力，也更容易移植。在那样一个硬件成本急剧下降的世界里，Perl 的设计使得它得到了蓬勃发展，Perl 让所有的新程序员快速、轻松地工作。这是因为 Larry Wall 以牺牲 CPU 和内存的需求为代价，使 Perl 语法更人性化。所有这些元素组合在一起，使 Perl 成为一种很受新开发社区欢迎的语言。

**00:11:36 - Mike Bursell**：

在一个正在壮大的社区里，你可以去和他们聊聊社区里的事情，然后 PerlMonks 论坛出现了，那里是一个讨论的好地方，能在论坛里知道正在发生的事情。

**00:11:50 - Saron Yitbarek**：

这个社区确实拥有 Web 所能提供的最好的东西。他们发现了一个巨大的软件模块库，一个叫做 CPAN 的存储库，这些系统管理员都很喜欢它。它给 Perl 提供了更多的灵活性，许多人都可以部署由少数几个编程大师编写的代码。

**00:12:15 - Mike Bursell**：

它有很多库可以做你想做的任何事情，如果你找不到你想要的库，你可以去问一下，然后就会有好心人写出你想要的库。

**00:12:21 - Saron Yitbarek**：

Mike Bursell 是红帽公司的首席安全架构师。

**00:12:28 - Saron Yitbarek**：

正是由于 Perl 是免费的，它受到不断增长的模块库的支持，它是可移植的，而且它有一个蓬勃发展的社区。一切看起来都很好。Perl 可以在上世纪 90 年代 Web 开发新天地中发挥所有优势，但就在 90 年代即将结束的时候，互联网的发展前景又一次发生了变化，时代来了一个大的转变。

**00:12:57 - Alan Greenspan**：

但我们又能如何知道非理性繁荣何时已过度推高了资产价值，进而导致了意料之外的长期经济收缩?

**00:13:12 - Saron Yitbarek**：

“非理性繁荣”是时任美联储主席 Alan Greenspan 在 1996 年对<ruby> 美国企业协会 <rt>  American Enterprise Institute </rt></ruby>所说的话。他那句“非理性繁荣”是对 90 年代人人都经历过的网络泡沫的警告。所有早期使用 Perl 的 Web 开发人员都在那个泡沫中乘风破浪，但正如 Greenspan 预测的那样，泡沫在 2000 年破裂了。

**00:14:11 - Conor Myhrvold**:

大家好，我是 Conor Myhrvold 。在过去的五六年里我一直从事编程，现在在技术领域为 Uber 工作。

**00:14:20 - Saron Yitbarek**：

2000 年代初，当 Conor 还在高中的时候，Perl 仍然是一个非常重要的东西。但他越来越意识到一种与之竞争的语言，叫做 Python。

**00:14:31 - Conor Myhrvold**：

Python 所追求的是一种更结构化的语言，做很多不同的事情都有一种更显然的方式，它就是那样设计的。而 Perl 则喜欢做某件事有不止一种方法，但这让很多初学者感到困惑。

**00:14:49 - Saron Yitbarek**：

Perl 有这样一句座右铭“<ruby> 实现它的方法不止一种 <rt>  There is more than one way to do it. </rt></ruby>”。而 Python 的理念实际上是相反的，Python 为每个问题都提供了一个明显的解决方案，这意味着查看别人的 Python 代码很容易；而另一方面查看其他人的 Perl 代码可能会令人困惑。Perl 作为一个程序员的第三或第四种语言是有意义的，而正是因为它是一种脚本语言，而脚本是互联网连结的基础。

**00:15:23**：

但是 Python 是一种你可以真正深入研究的语言，即使你是一个新手。Perl 有一套特定的优势，比如在搜索文本和生物信息学上。但是 Python 就是这样一种简单通用的语言。Python 获得了越来越多的信任，成为人们首先想学的语言，这是一件大事。

**00:15:47 - Conor Myhrvold**：

越来越多的人开始上网，越来越多的人开始学习如何编程。尤其是相对于 Perl 而言，Python 受益于它本身相对容易学习，因为它更结构化。而这样结果是，在一个快速增长的世界里，如果你能得到更多增长的份额，那将最终意味着有更多的教程和更多的东西可供你使用。

**00:16:10 - Saron Yitbarek**：

在之前提到过的 CPAN，它是 Perl 用户可以使用的强大的中央存储库。这在 90 年代是一大亮点，但 CPAN 的价值也在变化。

**00:16:24 - Conor Myhrvold**：

这也不能真正帮助你学习一门语言，因为你是在“复制粘贴”，只是用最少的方式替换你需要的东西。从长远来看这是一个劣势，因为如果你让人们通过自己进行原始开发来学习如何使用一种编程语言，即使这需要花费更长的时间，他们也会觉得自己对它投入了更多，而且他们也了解在这中间发生了什么。

**00:16:48 - Saron Yitbarek**：

Python 没有像 CPAN 那样的集中式存储库，但是对于那些在新千年时代来到这里的开发人员来说，在一个互联网搜索功能如此强大的世界里，存储库并没有那么大的价值。

**00:17:05 - Saron Yitbarek**：

最终 Python 有了大量的教程，当然现在也有了像 GitHub 这样的平台。

**00:17:13 - Conor Myhrvold**：

最终发生的事情是 Perl 拥有的许多优势，是来自一个已经过时的时代的网络效应。

**00:17:24 - Saron Yitbarek**：

Conor Myhrvold 是 Uber 的一名工程师。

**00:17:30 - Saron Yitbarek**：

然而语言的兴衰很少是由外部力量单独决定的，而 Perl 的内部问题是，在它的发展过程中它似乎遇到了障碍。Python 正在以一种相当有序的方式发布新的迭代，而正如我们在本季度第一集中所了解到的，Perl 在 2000 年互联网泡沫破裂之时，Python 开始获得更多新开发人员的青睐。

**00:17:59 - Saron Yitbarek**：

每个人都期待着 Perl 6 的发布，人们都很兴奋。他们等啊，等啊，等啊……他们等了 14 年。

**00:18:15 - Elizabeth Mattijsen**：

人们提出了大约 300 多件 Perl 6 应该能够完成的事情，当然其中很多事情基本上都是相互排斥的。

**00:18:26 - Saron Yitbarek**：

这是 Elizabeth Mattijsen，她是 Perl 6 的核心开发人员。2000 年，Elizabeth 参加了在<ruby> 蒙特雷 <rt>  Monterey </rt></ruby>举办的 Perl 会议。那时开发者认为他们已经停滞不前了，所以 Perl 6 是必要的。Larry Wall 同意了，但是如果说 Perl 5 是他对 Perl 的重写，那么他希望 Perl 6 是由社区来对 Perl 进行重写。由于团队合作可能需要更长时间，甚至用了 14 年，对于那些开发者来说，这是一条漫长而艰难的道路。

**00:19:01 - Elizabeth Mattijsen**：

我们可以说当前实施的 Perl 6 项目实际上是实现它的第三次尝试。

**00:19:07 - Saron Yitbarek**：

按照 Elizabeth 的说法，在这 14 年里有过多次尝试。中间经历了漫长而痛苦的深度的尝试。开发者们心力交瘁；人们陷入了死胡同。到 2015 年圣诞节那天 Perl 6 终于问世时，世界上的许多地方已经开始了新的发展。而需要注意的是 Perl 6 并没有给予成为某种革命性的新事物，从而实现对 Python 的反击。Perl 6 是对原版进行了深思熟虑的重新设计。

**00:19:43 - Elizabeth Mattijsen**：

我认为 Larry Wall 在他的“<ruby> 洋葱状态 <rt>  State of the Onion </rt></ruby>”演讲中使用了一个很好的比喻。对他来说，Perl 5 就像《<ruby> 霍比特人 <rt>  The Hobbit </rt></ruby>》，而 Perl 6 就像《<ruby> 指环王 <rt>  Lord of the Rings </rt></ruby>》。如果你仔细看过《霍比特人》和《指环王》的故事，你会发现它们基本上是同一个故事。只是《霍比特人》比《指环王》小得多，情节漏洞也更多，没有《指环王》那么宏大的背景。我认为这很好地描述了 Perl 5 和 Perl 6 之间的区别。它基本上是同样的想法，同样的思路，同样的环境，只是对它的重新构想。

**00:20:26 - Saron Yitbarek**：

Elizabeth Mattijsen 是 Perl 6 的核心贡献者。

**00:20:32**：

如今，Perl 甚至可能不在前 20 种语言之列。在外部竞争和内部拖延之间，它还没有向大多数新开发人员证明自己。但这提出了一个大问题，我们真的应该根据一种语言的流行度来判断我们的编程语言吗？或者说我们应该根据其他方面来判断一种编程语言的价值？当昔日的超级巨星成为陪衬时，这到底意味着什么呢？

**00:21:06**：

在世纪之交时互联网泡沫破裂时，Perl 的统治地位开始衰退时，Larry Wall 发表了一个有趣的声明。他认为尽管 Perl 永远不会再成为世界上最流行的编程语言，但它可以成为较小类别中的领先者。Larry Wall 说那才是真正的目标。成为同类中最好的，而不是世界上最好的。正如他所说的，SUV 永远不会和赛车竞争。

**00:21:38 - Saron Yitbarek**：

我想深入研究这个想法，我想了解在细分类别中做到最好对编程语言的真正含义。

**00:21:48 - John Siracusa**：

我是 John Siracusa，我是一个程序员，也是一个播客主。

**00:21:53 - Saron Yitbarek**：

John 实际上共同主持了三个播客：《Accidental Tech Podcast》、《Reconcilable Differences》和《Robot or Not?》。我们刚刚聊到了 Perl 在当今世界的地位。

**00:22:06**：

Perl 在当今世界排名如何？它仍然是最好的计算机语言吗？

**00:22:10 - John Siracusa**：

Perl 6 具有其他语言没有的、其他语言应该具有的东西，我一直在等待其他语言偷学它。例如语法是将常见任务概念化的一种好方法，而在我看来，使用语法来解决解析问题比使用现有的工具更令人愉快、更干净、更好。

**00:22:31**：

在 Perl 中，对象系统的许多部分看起来很琐碎而无关紧要，但我完全期待其他语言最终会采用它，就像许多语言最终采纳了 Perl 5 中的许多思想一样。因此我认为 Perl 6 在许多方面都是最好的。遗憾的是，很少有人有机会使用它。

**00:22:52 - Saron Yitbarek**：

你认为 Perl 6 社区的发展需要做些什么？想让人们更多地参与到 Perl 6 中，需要做些什么？

**00:23:00 - John Siracusa**：

这有点像 Perl 6 的故事，就像它一直在寻找一个真正奇妙的实现一样。这是第二系统问题的一部分……<ruby> 第二系统综合症 <rt>  second-system syndrome </rt></ruby>，我想他们是这样称呼……

**00:23:11 - Saron Yitbarek**：

哦。

**00:23:12 - John Siracusa**：

Perl 6 的，人们希望修复世界上的所有问题。他们想要解决的问题之一是运行时环境。是什么在运行我们的代码？运行 Perl 5 和之前的 Perl 4 的东西是一个巨大的 C 程序，这是由具有独特编码风格的开发者编写的。还有大量的宏，它是一种相当难以理解的东西。

**00:23:33**：

Perl 6 的想法是让我们不要再那样做了，让我们不要制造大量的 C 代码。相反，让我们使用一个虚拟机，这在当时是一种时尚，有很多关于如何实现它的伟大想法。最终我们得到了几个中规中矩的虚拟机实现版本，有时这些还会相互竞争，但没有一个达到真正交付语言使用时需要的性能、稳定性和特性。

**00:24:01 - Saron Yitbarek**：

现如今 Perl 到底发生了什么？你对此有什么看法？

**00:24:06 - John Siracusa**：

Perl 5 绝对像是在走下坡路，因为与 Perl 5 同时代的所有其他语言都采纳了它的大部分最佳思想，并获得了更多的支持。也就是说，因为它在很长一段时间内都是王者，所以有很多 Perl 5 代码在运行一些大型的、重要的站点，人们需要维护和扩展这些代码。

**00:24:29**：

这需要很长时间才能消失。只要看看现今仍然存在的 COBOL，人们怎么还在雇佣人在 COBOL 上做维护吧？

**00:24:35 - Saron Yitbarek**：

嗯。是这样。

**00:24:36 - John Siracusa**：

你刚才问 Perl 是不是一门垂死的语言，我提到了 COBOL，这听起来并不乐观。Perl 6 本身会成为主流语言吗？看起来可能性不大。现在对其他语言有非常多的关注，如果 Perl 6 现在还没有得到开发者的关注，我不知道将会需要发生什么变化来让它流行起来。

**00:24:54 - Saron Yitbarek**：

如果你是这样想的，你对 Perl 有什么期望？你希望在 Perl 5 或 Perl 6 中看到什么，以及希望看到将来发生什么？

**00:25:04 - John Siracusa**：

我对 Perl 5 的希望是人们不要忽视它，因为尽管有其它更流行的语言，但今天许多公司仍然采用 Perl 5 做为解决问题的最佳方案。通常这些都是胶水类型语言的问题。如果你发现自己曾经编写过 shell 脚本，并且可能会说:“好吧，我不会用我的‘真正的编程语言’来做这件事。”不管是 Python，还是 Ruby，还是别的什么。但是 shell 脚本可以让我把一堆东西连接起来（胶水类型语言）。Perl 是完成这项工作的更好工具。编写正确的 Perl 脚本要比编写正确的 shell 脚本更容易。

**00:25:40 - Saron Yitbarek**：

我认为归根结底 Perl 可能不再是一个适合入门的语言，但对于经验更丰富的多语言开发人员来说，它是那个你永远不希望扔掉的工具箱中的小工具，而且特定的工具有时让你提升水平的工具。

**00:25:58 - John Siracusa**：

有时我为 Perl 6 感到难过和沮丧，认为它不会有任何进展，有时我想“好吧，这是个不错的小社区”。每个社区都不需要称霸世界，也不需要成为整个行业的主导语言。也许可以就这样一直走下去，就是，无限期地走下去。这就是开源，和编程语言的伟大之处。没人可以阻止你，你可以像以前一样继续开发 Perl 6。

**00:26:27 - Saron Yitbarek**：

John Siracusa 是一名程序员，也是三个科技播客的联合主持人。

**00:26:34**：

语言都是有生命周期的。当新的语言出现时它们能够精确地适应新的现实，像 Perl 这样的选择可能会占据更小的、更小众的领域，但这并不是一件坏事。我们的语言应该随着我们需求的变化而扩大或缩小它们的群体。在互联网开发的早期历史中，Perl 是一个至关重要的角色，它以各种方式与我们联系在一起，只要看一看它的历史就会发现它的存在。

**00:27:11**：

下次在《代码英雄》中，我们将讨论：是什么将一种语言变成了标准？以及在基于云的开发世界中，新的标准将如何出现？

**00:27:26**：

《代码英雄》是红帽的原创播客。如果你想深入了解 Perl 的故事，或者任何我们在第三季中探索的编程语言，请访问 [redhat.com/commandlineheroes](file:///Users/xingyuwang/develop/LCRH-wxy/translated/redhat.com/commandlineheroes) 。我们的网站里有许多精彩内容等你去探索。

**00:27:49**：

我是 Saron Yitbarek。下期之前，编码不止。

>
> **什么是 LCTT SIG 和 LCTT LCRH SIG**
>
>
> LCTT SIG 是 LCTT <ruby> 特别兴趣小组 <rt>  Special Interest Group </rt></ruby>，LCTT SIG 是针对特定领域、特定内容的翻译小组，翻译组成员将遵循 LCTT 流程和规范，参与翻译，并获得相应的奖励。LCRH SIG 是 LCTT 联合红帽（Red Hat）发起的 SIG，当前专注任务是《代码英雄》系列播客的脚本汉化，已有数十位贡献者加入。敬请每周三、周五期待经过我们精心翻译、校对和发布的译文。
>
>
> 欢迎[加入 LCRH SIG](/article-12436-1.html) 一同参与贡献，并领取红帽（Red Hat）和我们联合颁发的专属贡献者证书。
>
>
>

---

via: <https://www.redhat.com/en/command-line-heroes/season-3/diving-for-perl>

作者：[Red Hat](https://www.redhat.com/en/command-line-heroes) 选题：[bestony](https://github.com/bestony) 译者：[Mikedkmilk](https://github.com/Mikedkmilk) 校对：[Northurland](https://github.com/Northurland), [wxy](https://github.com/wxy)

本文由 [LCRH](https://github.com/LCTT/LCRH) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


十年 Linux 桌面生存指南

一大堆命令，很难想象这就是桌面生存指南，很难生存的

同感，这对命令行最适合自娱自乐，自己怎么玩都行，但是现在私有格式那么多，老板发给你个word就gg了

说白了学那些最适合大众的东西成本最低

我用从fedora8开始，从来都是用桌面的，很好用啊

我用linux大概也有十年了，各种版本都尝试过了，最终选择折中的版本-debian，最小化安装，i3wm桌面管理。<br />
兼容的软件最多。稳定性非常好

都到这种程度了,你觉得是老板给word就跪的人物吗？这配置,这台机一开就只干一件事——写代码.其他事务给其他机器做,只要开这台机就完全沉浸到代码世界里了.

word太好解决了,转PDF,转HTML,转XML,转MARKDOWN,转ODT,要高级排版LATEX转XML或PDF之类的再转成word,想要什么格式随你挑,实在挑剔？让小弟搞排版,排 版这破事让技术人员做也亏你老板想的出来.

![](/data/attachment/album/202012/03/223817smrej5qwsbqjb3vs.jpg)

从 2006 年开始转战 Linux 系统后，经过几年的实践，我的软件设置在过去十年内出人意料的固定。再过十年回顾一下，看看发生了什么，也许会非常有趣。在写这篇推文时，我迅速回顾了正在运行的内容：

![htop overview](/data/attachment/album/202012/03/223912v0gsgf43fsxs383f.png)

### 动机

我的软件介绍排序不分先后：

* 程序应该运行在本地系统中以便我可以控制它，这其中并不包括云解决方案。
* 程序应在终端中运行，以便于在任何地方连贯地使用它们，包括性能稍差的电脑或手机。
* 通过使用终端软件，可以实现自动聚焦键盘。只有在一些有意义的地方，我会更喜欢使用鼠标，因为在打字期间一直伸手去拿鼠标感觉像在浪费时间。有时候过了一个小时我才注意到甚至还没有插鼠标。
* 最好使用快速高效的软件，我不喜欢听到风扇的声音和感到房间在变热。我还可以继续长久地运行旧硬件，已经使用了 10 年的 Thinkpad x200s 还能很好地支持我所使用的软件。
* 组合。我不想手动执行每个步骤，而是在需要时自动执行更多操作，这时自然是支持 shell。

### 操作系统

十二年前移除 Windows 系统后，我在 Linux 系统上经历了一个艰难的开始，当时我手上只有 [Gentoo Linux](https://gentoo.org/) 系统的安装光盘和一本打印的说明书，要用它们来实现一个可运行的 Linux 系统。虽然花费了几天的时间去编译和修整，但最终还是觉得自己受益颇多。

自此我再也没有转回 Windows 系统，但在持续的编译压力导致风扇失灵后，我将我的电脑系统切换到 [Arch Linux](https://www.archlinux.org/)。之后我将其他的电脑和私人服务器也切换到了 Arch Linux。作为一个滚动发布发行版，你可以随时升级软件包，但 [Arch Linux News](https://www.archlinux.org/news/) 已经详细报道了其中最主要的漏洞。

不过，令人烦恼的是一旦你更新了旧的内核模组，Arch Linux 就会移除旧版的相关信息。我经常注意到一旦我试着插入一个 USB 闪存盘，内核就无法加载相关组件。相反，每次内核升级后都应该进行重启。有一些 [方法](https://www.reddit.com/r/archlinux/comments/4zrsc3/keep_your_system_fully_functional_after_a_kernel/) 可以解决这个问题，但我还没有实际地使用它们。

其他程序也会出现类似的情况，通常 Firefox 、 cron 或者 Samba 在升级后都需要重启，但恼人的是，它们没有警告你存在这种情况。我在工作中使用的 [SUSE](https://www.suse.com/) 很好地提醒了这种情况。

对于 [DDNet](https://ddnet.tw/) 产品服务器，相较于 Arch Linux ，我更倾向于 [Debian](https://www.debian.org/) 系统，这样在每次升级时出现故障的几率更低。我的防火墙和路由器使用了 [OpenBSD](https://www.openbsd.org/) ，它拥有干净系统、文档和强大的 [pf 防火墙](https://www.openbsd.org/faq/pf/)，而我现在不需要一个单独的路由器。

### 窗口管理器

从我开始使用 Gentoo 后，我很快注意到 KDE 的编译时间非常长，这让我没办法继续使用它。我四处寻找更简单的解决方案，最初使用了 [Openbox](http://openbox.org/wiki/Main_Page) 和 [Fluxbox](http://fluxbox.org/)。某次，为了能更多进行纯键盘操作，我开始尝试转入平铺窗口管理器，并在研究其初始版本的时候学习了 [dwm](https://dwm.suckless.org/) 和 [awesome](https://awesomewm.org/)。

最终，由于 [xmonad](https://xmonad.org/)的灵活性、可扩展性以及使用纯 [Haskell](https://www.haskell.org/)（一种出色的函数编程语言）编写和配置，最终选择了它。一个例子是，我在家中运行一个 40" 4K 的屏幕，但经常会将它分为四个虚拟屏幕，每个虚拟屏幕显示一个工作区，每个工作区自动排列在我的窗口上。当然， xmonad 有一个对应的 [模块](http://hackage.haskell.org/package/xmonad-contrib-0.15/docs/XMonad-Layout-LayoutScreens.html)。

[dzen](http://robm.github.io/dzen/) 和 [conky](https://github.com/brndnmtthws/conky) 对我来说是一个非常简单的状态栏。我的整体 conky 配置看起来是这样的：

```
out_to_console yes
update_interval 1
total_run_times 0

TEXT
${downspeed eth0} ${upspeed eth0} | $cpu% ${loadavg 1} ${loadavg 2} ${loadavg 3} $mem/$memmax | ${time %F %T}

```

输入命令直接通过管道输入 dzen2：

```
conky | dzen2 -fn '-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-*' -bg '#000000' -fg '#ffffff' -p -e '' -x 1000 -w 920 -xs 1 -ta r

```

对我而言，一项重要功能是在完成工作后使终端发出蜂鸣声。只需要简单地在 zsh 中的 `PR_TITLEBAR` 变量中添加一个 `\a` 字符就可以做到，只要工作完成就可以发出蜂鸣声。当然，我使用了命令：

```
echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf

```

将 `pcspkr` 内核模块列入黑名单来禁用实际的蜂鸣声。相反 urxvt 的 `URxvt.urgentOnBell: true` 设置会将声音变为尖锐。之后 xmonad 有一个 urgency 钩子来捕捉这类信号，并且我可以使用组合键自动聚焦到当前的发出紧急信号的窗口。在 dzen 中我可以看到一个漂亮且明亮的 `#ff0000` 紧急窗口。

在我笔记本上所得到的最终成品是：

![Laptop screenshot](/data/attachment/album/202012/03/223915yh19a7t4ta9z1zlx.png)

我听说前几年 [i3](https://i3wm.org/) 变得非常流行，但它要求更多的手动窗口对齐而不是自动对齐。

我意识到也有像 [tmux](https://github.com/tmux/tmux/wiki) 那样的终端多路复用器，但我仍想要一些图形化应用程序，因此最终我没有有效地使用它们。

### 终端连续性

为了使终端保持活跃状态，我使用了 [dtach](http://dtach.sourceforge.net/) ，它只是模拟屏幕分离功能。为了使计算机上的每个终端都可连接和断开，我编写了一个小的封装脚本。 这意味着，即使必须重新启动 X 服务器，我也可以使所有终端都运行良好，包括本地和远程终端。

### Shell & 编程

对于 shell，我使用 [zsh](http://www.zsh.org/) 而不是 [bash](https://www.gnu.org/software/bash/)，因为它有众多的功能。

作为终端模拟，我发现 [urxvt](http://software.schmorp.de/pkg/rxvt-unicode.html) 足够轻巧，支持 Unicode 编码和 256 色，具有出色的性能。另一个重要的功能是可以分别运行 urxvt 客户端和守护进程。因此，即使大量终端也几乎不占用任何内存（回滚缓冲区除外）。

对我而言，只有一种字体看起来绝对干净和完美： [Terminus](http://terminus-font.sourceforge.net/)。 由于它是位图字体，因此所有内容都是完美像素，渲染速度极快且 CPU 使用率低。为了能使用 `CTRL-WIN-[1-7]` 在每个终端按需切换字体，我的 `~/.Xdefaults` 包含:

```
URxvt.font: -xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*
dzen2.font: -xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*

URxvt.keysym.C-M-1: command:\033]50;-xos4-terminus-medium-r-normal-*-12-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-2: command:\033]50;-xos4-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-3: command:\033]50;-xos4-terminus-medium-r-normal-*-18-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-4: command:\033]50;-xos4-terminus-medium-r-normal-*-22-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-5: command:\033]50;-xos4-terminus-medium-r-normal-*-24-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-6: command:\033]50;-xos4-terminus-medium-r-normal-*-28-*-*-*-*-*-*-*\007
URxvt.keysym.C-M-7: command:\033]50;-xos4-terminus-medium-r-normal-*-32-*-*-*-*-*-*-*\007

URxvt.keysym.C-M-n: command:\033]10;#ffffff\007\033]11;#000000\007\033]12;#ffffff\007\033]706;#00ffff\007\033]707;#ffff00\007
URxvt.keysym.C-M-b: command:\033]10;#000000\007\033]11;#ffffff\007\033]12;#000000\007\033]706;#0000ff\007\033]707;#ff0000\007

```

对于编程和书写，我使用 [Vim](https://www.vim.org/) 语法高亮显示和 [ctags](http://ctags.sourceforge.net/) 进行索引，以及一些带有 `grep` 、`sed` 和其他用于搜索和操作的常用终端窗口。这可能不像 IDE 那样舒适，但可以实现更多的自动化。

Vim 的一个问题是你已经习惯了它的键映射，因此希望在任何地方都使用它们。

在 shell 功能不够强大时，[Python](https://www.python.org/) 和 [Nim](https://nim-lang.org/) 作为脚本语言也不错。

### 系统监控

[htop](https://hisham.hm/htop/) （查看当前站点的后台运行，是托管服务器的实时视图）非常适合快速了解软件的当前运行状态。 [lm\_sensors](http://lm-sensors.org/) 可以监控硬件温度、风扇和电压。 [powertop](https://01.org/powertop/) 是一款由 Intel 发布的优秀省电小工具。 [ncdu](https://dev.yorhel.nl/ncdu) 可以交互式分析磁盘使用情况。

[nmap](https://nmap.org/)、 iptraf-ng、 [tcpdump](https://www.tcpdump.org/) 和 [Wireshark](https://www.wireshark.org/) 都是分析网络问题的基本工具。

当然还有很多更优秀的工具。

### 邮件 & 同步

在我的家庭服务器上，我为自己所有的邮箱账号运行了 [fetchmail](http://www.fetchmail.info/) 守护进程。fetchmail 只是检索收到的邮件并调用 [procmail](http://www.procmail.org/)：

```
#!/bin/sh
for i in /home/deen/.fetchmail/*; do
 FETCHMAILHOME=$i /usr/bin/fetchmail -m 'procmail -d %T' -d 60
done

```

配置非常简单，然后等待服务器通知我们有新的邮件：

```
poll imap.1und1.de protocol imap timeout 120 user "dennis@felsin9.de" password "XXX" folders INBOX keep ssl idle

```

我的 `.procmailrc` 配置包含一些备份全部邮件的规则，并将邮件整理在对应的目录下面。例如，基于邮件列表名或者邮件标题：

```
MAILDIR=/home/deen/shared/Maildir
LOGFILE=$HOME/.procmaillog
LOGABSTRACT=no
VERBOSE=off
FORMAIL=/usr/bin/formail
NL="
"

:0wc
* ! ? test -d /media/mailarchive/`date +%Y`
| mkdir -p /media/mailarchive/`date +%Y`

# Make backups of all mail received in format YYYY/YYYY-MM
:0c
/media/mailarchive/`date +%Y`/`date +%Y-%m`

:0
* ^From: .*(.*@.*.kit.edu|.*@.*.uka.de|.*@.*.uni-karlsruhe.de)
$MAILDIR/.uni/

:0
* ^list-Id:.*lists.kit.edu
$MAILDIR/.uni-ml/

[...]

```

我使用 [msmtp](https://marlam.de/msmtp/) 来发送邮件，它也很好配置：

```
account default
host smtp.1und1.de
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
auth on
from dennis@felsin9.de
user dennis@felsin9.de
password XXX

[...]

```

但是到目前为止，邮件还在服务器上。 我的文档全部存储在一个目录中，我使用 [Unison](https://www.cis.upenn.edu/~bcpierce/unison/) 在所有计算机之间进行同步。Unison 可以视为双向交互式 [rsync](https://rsync.samba.org/)，我的邮件是这个文件目录下的一部分，因此它们最终存储在我的电脑上。

这也意味着，尽管邮件会立即到达我的邮箱，但我只是按需拿取，而不是邮件一到达时就立即收到通知。

从此我使用 [mutt](http://www.mutt.org/) 阅读邮件，使用侧边栏显示我的邮件目录。 `/etc/mailcap` 文件对于显示非纯文本邮件（ HTML, Word 或者 PDF）不可或缺：

```
text/html;w3m -I %{charset} -T text/html; copiousoutput
application/msword; antiword %s; copiousoutput
application/pdf; pdftotext -layout /dev/stdin -; copiousoutput

```

### 新闻 & 通讯

[Newsboat](https://newsboat.org/) 是一个非常棒的终端 RSS/Atom 阅读器。我在一个有约 150 个提要的 `tach` 会话服务器上运行它。也可以在本地选择提要，例如：

```
ignore-article "https://forum.ddnet.tw/feed.php" "title =~ \"Map Testing •\" or title =~ \"Old maps •\" or title =~ \"Map Bugs •\" or title =~ \"Archive •\" or title =~ \"Waiting for mapper •\" or title =~ \"Other mods •\" or title =~ \"Fixes •\""

```

我以同样的方式使用 [Irssi](https://irssi.org/) 进行 IRC 通讯。

### 日历

[remind](https://www.roaringpenguin.com/products/remind) 是一个可以从命令行获取的日历。通过编辑 `rem` 文件可以设置新的提醒：

```
# One time events
REM 2019-01-20 +90 Flight to China %b

# Recurring Holidays
REM 1 May +90 Holiday "Tag der Arbeit" %b
REM [trigger(easterdate(year(today()))-2)] +90 Holiday "Karfreitag" %b

# Time Change
REM Nov Sunday 1 --7 +90 Time Change (03:00 -> 02:00) %b
REM Apr Sunday 1 --7 +90 Time Change (02:00 -> 03:00) %b

# Birthdays
FSET birthday(x) "'s " + ord(year(trigdate())-x) + " birthday is %b"
REM 16 Apr +90 MSG Andreas[birthday(1994)]

# Sun
SET $LatDeg 49
SET $LatMin 19
SET $LatSec 49
SET $LongDeg -8
SET $LongMin -40
SET $LongSec -24

MSG Sun from [sunrise(trigdate())] to [sunset(trigdate())]
[...]

```

遗憾的是，目前 remind 中还没有中国农历的提醒功能，因此中国的节日不易计算。

我给提醒设置了两个名字：

```
rem -m -b1 -q -g

```

按时间顺序查看待办事项清单

```
rem -m -b1 -q -cuc12 -w$(($(tput cols)+1)) | sed -e "s/\f//g" | less

```

显示适应终端宽度的日历：

![remcal](/data/attachment/album/202012/03/223915bjyjlmaylvfmyyal.png)

### 字典

[rdictcc](https://github.com/tsdh/rdictcc) 是鲜为人知的字典工具，它可以使用 [dict.cc](https://www.dict.cc/) 很棒的词典并将他们转存在本地数据库中：

```
$ rdictcc rasch
====================[ A => B ]====================
rasch:
 - apace
 - brisk [speedy]
 - cursory
 - in a timely manner
 - quick
 - quickly
 - rapid
 - rapidly
 - sharpish [Br.] [coll.]
 - speedily
 - speedy
 - swift
 - swiftly
rasch [gehen]:
 - smartly [quickly]
Rasch {n} [Zittergras-Segge]:
 - Alpine grass [Carex brizoides]
 - quaking grass sedge [Carex brizoides]
Rasch {m} [regional] [Putzrasch]:
 - scouring pad
====================[ B => A ]====================
Rasch model:
 - Rasch-Modell {n}

```

### 记录和阅读

我有一个简单记录任务的备忘录，在 Vim 会话中基本上一直处于打开状态。我也使用备忘录作为工作中“已完成”工作的记录，这样就可以检查自己每天完成了哪些任务。

对于写文件、信件和演示文稿，我会使用 [LaTeX](https://www.latex-project.org/) 进行高级排版。德式的简单信件可以这样设置，例如：

```
\documentclass[paper = a4, fromalign = right]{scrlttr2}
\usepackage{german}
\usepackage{eurosym}
\usepackage[utf8]{inputenc}
\setlength{\parskip}{6pt}
\setlength{\parindent}{0pt}

\setkomavar{fromname}{Dennis Felsing}
\setkomavar{fromaddress}{Meine Str. 1\\69181 Leimen}
\setkomavar{subject}{Titel}

\setkomavar*{enclseparator}{Anlagen}

\makeatletter
\@setplength{refvpos}{89mm}
\makeatother

\begin{document}
\begin{letter} {Herr Soundso\\Deine Str. 2\\69121 Heidelberg}
\opening{Sehr geehrter Herr Soundso,}

Sie haben bei mir seit dem Bla Bla Bla.

Ich fordere Sie hiermit zu Bla Bla Bla auf.

\closing{Mit freundlichen Grüßen}

\end{letter}
\end{document}

```

在 [我的私人网站](http://felsin9.de/nnis/research/) 上可以找到更多的示例文档和演示文稿。

[Zathura](https://pwmt.org/projects/zathura/) 读取 PDF 文件速度很快，支持 Vim 类控件，还支持两种不同的 PDF 后端： Poppler 和 MuPDF。另一方面，在偶尔遇到 Zathura 无法打开的文件时，[Evince](https://wiki.gnome.org/Apps/Evince) 则显得更全能一些。

### 图片编辑

简便的选择是，[GIMP](https://www.gimp.org/) 和 [Inkscape](https://inkscape.org/) 分别用于照片编辑和交互式向量图形。

有时 [Imagemagick](https://imagemagick.org/Usage/) 已经足够好了，它可以从命令行直接使用，从而自动编辑图片。同样 [Graphviz](https://www.graphviz.org/) 和 [TikZ](https://sourceforge.net/projects/pgf/) 可以用来绘制曲线图和其他图表。

### Web 浏览器

对于 Web 浏览器，我一直在使用 [Firefox](https://www.mozilla.org/en-US/firefox/new/)。相较于 Chrome，它的可扩展性更好，资源使用率更低。

不幸的是，在 Firefox 完全改用 Chrome 风格的扩展之后， [Pentadactyl](https://github.com/5digits/dactyl) 扩展的开发就停止了，所以我的浏览器中再也没有令人满意的 Vim 类控件了。

### 媒体播放器

通过设置 `vo=gpu` 以及 `hwdec=vaapi`，具有硬件解码功能的 [mpv](https://mpv.io/) 在播放期间 CPU 的占用率保持在 5%。相较于默认的 PulseAudio，mpv 中的 `audio-channels=2` 似乎可以使我的立体扬声器/耳机获得更清晰的降级混频。一个很棒的小功能是用 `Shift-Q` 退出，而不是只用 `Q` 来保存回放位置。当你与母语是其他语言的人一起看视频时，你可以使用 `--secondary-sid=` 同时显示两种字幕，主字幕位于底部，次字幕位于屏幕顶部。

我的无线鼠标可以简单地通过一个小的配置文件（ `~/.config/mpv/input.conf` ）实现远程控制 mpv ：

```
MOUSE_BTN5 run "mixer" "pcm" "-2"
MOUSE_BTN6 run "mixer" "pcm" "+2"
MOUSE_BTN1 cycle sub-visibility
MOUSE_BTN7 add chapter -1
MOUSE_BTN8 add chapter 1

```

[youtube-dl](https://rg3.github.io/youtube-dl/) 非常适合观看在线托管的视频，使用 `-f bestvideo+bestaudio/best --all-subs --embed-subs` 命令可获得最高质量的视频。

作为音乐播放器， [MOC](http://moc.daper.net/) 不再活跃开发，但它仍是一个简易的播放器，可以播放各种可能的格式，包括最不常用的 Chiptune 格式。在 AUR 中有一个 [补丁](https://aur.archlinux.org/packages/moc-pulse/) 增加了 PulseAudio 支持。即使在 CPU 时钟频率降到 800 MHz， MOC 也只使用了单核 CPU 的 1-2% 。

![moc](/data/attachment/album/202012/03/223920maaylcaooljjca3e.png)

我的音乐收藏夹保存在我的家庭服务器上，因此我可以从任何地方访问它。它使用 [SSHFS](https://github.com/libfuse/sshfs) 挂载并自动安装在 `/etc/fstab/` 目录下：

```
root@server:/media/media /mnt/media fuse.sshfs noauto,x-systemd.automount,idmap=user,IdentityFile=/root/.ssh/id_rsa,allow_other,reconnect 0 0

```

### 跨平台构建

除了 Linux 本身，它对于构建任何主流操作系统的软件包都很优秀！ 一开始，我使用 [QEMU](https://www.qemu.org/) 与旧版 Debian、 Windows 以及 Mac OS X VM 一起构建这些平台。

现在我在旧版 Debian 发行版上转而使用 chroot （以获得最大的 Linux 兼容性），在 Windows 上使用 [MinGW](http://www.mingw.org/) 进行交叉编译，在 Mac OS X 上则使用 [OSXCross](https://github.com/tpoechtrager/osxcross)。

用于 [构建 DDNet](https://github.com/ddnet/ddnet-scripts/blob/master/ddnet-release.sh) 的脚本以及 [更新库构建的说明](https://github.com/ddnet/ddnet-scripts/blob/master/ddnet-lib-update.sh) 的脚本都基于这个。

### 备份

通常，我们都会忘记备份。即使这是最后一节，它也不应该成为事后诸葛。

十年前我写了 [rrb](https://github.com/def-/rrb/blob/master/rrb) （反向 rsync 备份）重新封装了 `rsync` ，因此我只需要将备份服务器的 root SSH 权限授予正在备份的计算机。令人惊讶地是，尽管我一直在使用 rrb ，但它在过去十年里没有任何改变。

备份文件直接存储在文件系统中。使用硬链接实现增量备份（`--link-dest`）。一个简单的 [配置](https://github.com/def-/rrb/blob/master/config.example) 定义了备份保存时间，默认为：

```
KEEP_RULES=( \
   7  7 \ # One backup a day for the last 7 days
  31  8 \ # 8 more backups for the last month
 365 11 \ # 11 more backups for the last year
1825  4 \ # 4 more backups for the last 5 years
)

```

因为我的一些计算机没有静态 IP / DNS 但仍想使用 rrb 备份，那我会使用反向安全隧道（作为 systemd 服务）：

```
[Unit]
Description=Reverse SSH Tunnel
After=network.target

[Service]
ExecStart=/usr/bin/ssh -N -R 27276:localhost:22 -o "ExitOnForwardFailure yes" server
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

```

现在，隧道运行备份时，服务器可以通过 `ssh -p 27276 localhost` 命令或者使用 `.ssh/config` 到达服务器端。

```
Host cr-remote
 HostName localhost
 Port 27276

```

在谈及 SSH 技巧时，有时由于某些中断的路由会很难访问到服务器。在那种情况下你可以借道其他服务器的 SSH 连接，以获得更好的路由。在这种情况下，你可能通过美国连接访问到我的中国服务器，而来自德国的不可靠连接可能需要几个周：

```
Host chn.ddnet.tw
 ProxyCommand ssh -q usa.ddnet.tw nc -q0 chn.ddnet.tw 22
 Port 22

```

### 结语

感谢阅读我工具的收藏。这其中我也许遗漏了许多日常中自然成习惯的步骤。让我们来看看我的软件设置在下一年里能多稳定吧。如果你有任何问题，随时联系我 [dennis@felsin9.de](mailto:dennis@felsin9.de) 。

在 [Hacker News](https://news.ycombinator.com/item?id=18979731) 下评论吧。

---

via: <https://hookrace.net/blog/linux-desktop-setup/>

作者：[Dennis Felsing](http://felsin9.de/nnis/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[chenmu-kk](https://github.com/chenmu-kk) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Rails 之旅第 1 天：一个令人困惑的 Rails 错误信息

这教程真水。

直接全局搜索user，就能找到所有user，然后点击开，花2秒就知道自己抄错了。

devise确实比较复杂，但可用性是极高的。

![](/data/attachment/album/202012/04/080957f0p4piqz52bypqb5.jpg)

今天，我开始了一个 Recurse Center 的班次学习！我认识了一些人，并开始了一个小小的有趣的 Rails 项目。我想我今天不会谈太多关于这个项目的实际内容，但这里有一些关于 Rails 一天的快速笔记。

### 一些关于开始的笔记

在建立 Rails 项目的过程中，我学到的主要是：

1. 它默认使用 sqlite，你必须告诉它使用 Postgres。
2. Rails 默认包含了大量的东西，你可以禁用。

我安装并 `rm -rf` Rails 大概 7 次后才满意，最后用了这个咒语：

```
rails new . -d postgresql --skip-sprockets --skip-javascript

```

主要是因为我想用 Postgres 而不是 sqlite，而且跳过 sprockets 和 javascript 似乎能让安装 Rails 的速度更快，而且我想如果我决定要它们的话，我可以在以后再安装。

### 官方的 Rails 指南真的很不错

我在创建我的 Rails 入门应用时主要参考了 2 个资源：

* DHH 在 2005 年的 Rails 原版演讲 <https://www.youtube.com/watch?v=Gzj723LkRJY>（这次我没有看，但上次我花了一天时间学习 Rails 时看了，我发现它很有启发和帮助）。
* 官方的 Rails 入门指南，似乎非常简短明了 <https://guides.rubyonrails.org/v5.0/getting_started.html>。

### 一个神秘的错误信息：`undefined method 'user'`

我喜欢 bug，所以今天我遇到了一个奇怪的 Rails 错误! 我有一些看起来像这样的代码：

```
@user = User.new(user_params)
@user.save

```

很简单吧？但当这段代码运行时，我得到了这个令人费解的错误信息：

```
undefined method `user' for #<User:0x00007fb6f4012ab8> Did you mean? super

```

我对这里发生的事情感到**超级**困惑，因为我没有调用一个叫做 `user` 的方法。我调用的是 `.save`。什么嘛？！我对此感到困惑和沮丧，大概呆了 20 分钟，最后我看了看我的 `User` 模型，发现了这段代码：

```
class User < ApplicationRecord
  has_secure_password

  validates :user, presence: true, uniqueness: true
end

```

`validates :user...` *应该*是一些 Rails 魔法，验证每个 `User` 都有一个 `username`，而且用户名必须是唯一的。但我犯了一个错，我写的是 `user` 而不是 `username`。我把这个问题解决了，然后一切都正常了！万岁。

我仍然不明白我应该如何调试这个问题：堆栈跟踪告诉我问题出在 `@user.save` 行，根本没有提到 `validates :user` 的事情。我觉得一定有办法调试这个问题，但我不知道是什么办法。

我学 Rails 的目的就是想看看 Rails 的魔力在实践中是如何发挥的，所以这是个很有意思的 bug，早早的就掉坑里了。

### 一个简单的用户管理系统

我决定在我的玩具应用中加入用户。我在网上搜索了一下，发现有一个非常流行的叫做 [devise](https://github.com/heartcombo/devise) 的工具可以处理用户。我发现它的 `README` 有点让人不知所措，而且我知道想要在我的玩具应用中建立一个非常简陋的用户管理系统，所以我遵循了这个名为《[Rails 5.2 中从零开始进行用户验证](https://medium.com/@wintermeyer/authentication-from-scratch-with-rails-5-2-92d8676f6836)》的指南，到目前为止，这个指南似乎还不错。Rails 似乎已经有了一大堆管理用户的内置东西，我真的很惊讶于这本指南的短小和我需要写的代码之少。

我在实现用户功能的时候了解到，Rails 有一个内置的神奇的会话管理系统（参见 [Rails 会话如何工作](https://www.justinweiss.com/articles/how-rails-sessions-work/)。默认情况下，所有的会话数据似乎都存储在用户电脑上的 cookie 中，不过我想如果 cookie 太大了，你也可以把会话数据存储在数据库中。

已经有了会话管理系统，有了 cookie 和用户，却不太清楚到底发生了什么，这肯定是有点奇怪的，但也是挺好玩的！我们会看看情况如何。我们将拭目以待。

### 明天：更多的 Rails!

也许明天我可以在实现我的有趣的 rails 应用的想法上取得一些进展!

---

via: <https://jvns.ca/blog/2020/11/09/day-1--a-little-rails-/>

作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


scanimage：从命令行扫描！

Summary: 我一直以为在 Linux 上使用打印机/扫描仪是一个噩梦，我真的很惊讶 scanimage 可以工作。

受本帖启发，写了一篇ChromeOS及内置Linux中使用扫描仪的指南。<br />
wildgun.net/2022/11/use_scanner_in_chromeos_and_linux/

不错不错~点个赞！

![](/data/attachment/album/202012/05/105822m30t6x66hz3hx6x3.jpg)

这又是一篇关于我很喜欢的一个命令行工具的文章。

昨晚，出于官僚原因，我需要扫描一些文档。我以前从来没有在 Linux 上使用过扫描仪，我担心会花上好几个小时才弄明白。我从使用 `gscan2pdf` 开始，但在用户界面上遇到了麻烦。我想同时扫描两面（我知道我们的扫描仪支持），但无法使它工作。

### 遇到 scanimage！

`scanimage` 是一个命令行工具，在 `sane-utils` Debian 软件包中。我想所有的 Linux 扫描工具都使用 `sane` （“scanner access now easy”） 库，所以我猜测它和其他扫描软件有类似的能力。在这里，我不需要 OCR，所以我不打算谈论 OCR。

### 用 scanimage -L 得到你的扫描仪的名字

`scanimage -L` 列出了你所有的扫描设备。

一开始我不能让它工作，我有点沮丧，但事实证明，我把扫描仪连接到了我的电脑上，但没有插上电源。

插上后，它马上就能工作了。显然我们的扫描仪叫 `fujitsu:ScanSnap S1500:2314`。万岁！

### 用 --help 列出你的扫描仪选项

显然每个扫描仪有不同的选项（有道理！），所以我运行这个命令来获取我的扫描仪的选项：

```
scanimage --help -d 'fujitsu:ScanSnap S1500:2314'

```

我发现我的扫描仪支持 `--source` 选项（我可以用它来启用双面扫描）和 `--resolution` 选项（我把它改为 150，以减少文件大小，使扫描更快）。

### scanimage 不支持输出 PDF 文件（但你可以写一个小脚本）

唯一的缺点是：我想要一个 PDF 格式的扫描文件，而 scanimage 似乎不支持 PDF 输出。

所以我写了这个 5 行的 shell 脚本在一个临时文件夹中扫描一堆 PNG 文件，并将结果保存到 PDF 中。

```
#!/bin/bash
set -e

DIR=`mktemp -d`
CUR=$PWD
cd $DIR
scanimage -b --format png  -d 'fujitsu:ScanSnap S1500:2314' --source 'ADF Front' --resolution 150
convert *.png $CUR/$1

```

我像这样运行脚本：`scan-single-sided output-file-to-save.pdf`

你可能需要为你的扫描仪设置不同的 `-d` 和 `-source`。

### 这真是太简单了!

我一直以为在 Linux 上使用打印机/扫描仪是一个噩梦，我真的很惊讶 `scanimage` 可以工作。我可以直接运行我的脚本 `scan-single-sided receipts.pdf`，它将扫描文档并将其保存到 `receipts.pdf`！

---

via: <https://jvns.ca/blog/2020/07/11/scanimage--scan-from-the-command-line/>

作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


每天用 Jupyter 写 5 分钟的日记

Summary: 用 Jupyter 和 Python 在你的日常写作背后实现一些自动化。

用 Jupyter 和 Python 在你的日常写作背后实现一些自动化。

>
> 用 Jupyter 和 Python 在你的日常写作背后实现一些自动化。
>
>
>

![](/data/attachment/album/202012/05/131314woxpksatp2toe7tz.jpg)

有些人会遵循传统，制定一年的计划。不过，一年的时间很长，所以我以季节性的主题或轨迹来规划。每个季度，我都会坐下来，看看即将到来的三个月的季节，并决定在这段时间里我将努力做什么。

对于我最新的主题，我决定要每天写一篇日记。我喜欢有明确的承诺，所以我承诺每天写 5 分钟。我也喜欢有可观察的承诺，哪怕只是对我而言，所以我把我的记录放在 Git 里。

我决定在写日记的过程中实现一些自动化，于是我使用了我最喜欢的自动化工具：[Jupyter](https://jupyter.org/)。Jupyter 有一个有趣的功能 [ipywidgets](https://ipywidgets.readthedocs.io/en/latest/)，这是一套用于 Jupyter Notebooks、JupyterLab 和 IPython 内核的交互式 HTML 组件。

如果你想跟着本文的代码走，请注意，让你的 JupyterLab 实例支持组件可能有点复杂，请按照[这些说明](https://ipywidgets.readthedocs.io/en/latest/user_install.html)来进行设置。

### 导入 ipywidgets 模块

首先，你需要导入一堆东西，比如 ipywidgets 和 [Twisted](https://twistedmatrix.com/trac/)。Twisted 模块可以用来创建一个异步时间计数器：

```
import twisted.internet.asyncioreactor
twisted.internet.asyncioreactor.install()
from twisted.internet import reactor, task
import ipywidgets, datetime, subprocess, functools, os

```

### 设置定时条目

用 Twisted 实现时间计数器是利用了 `task.LoopingCall`。然而，结束循环调用的唯一方法是用一个异常。倒计时时钟总会停止，所以你需要一个自定义的异常来指示“一切正常；计数器结束”：

```
class DoneError(Exception):
    pass

```

现在你已经写好了异常，你可以写定时器了。第一步是创建一个 `ipywidgets.Label` 的文本标签组件。循环使用 `divmod` 计算出分和秒，然后设置标签的文本值：

```
def time_out_counter(reactor):
    label = ipywidgets.Label("Time left: 5:00")
    current_seconds = datetime.timedelta(minutes=5).total_seconds()
    def decrement(count):
        nonlocal current_seconds
        current_seconds -= count
        time_left = datetime.timedelta(seconds=max(current_seconds, 0))
        minutes, left = divmod(time_left, minute)
        seconds = int(left.total_seconds())
        label.value = f"Time left: {minutes}:{seconds:02}"
        if current_seconds < 0:
            raise DoneError("finished")
    minute = datetime.timedelta(minutes=1)
    call = task.LoopingCall.withCount(decrement)
    call.reactor = reactor
    d = call.start(1)
    d.addErrback(lambda f: f.trap(DoneError))
    return d, label

```

### 从 Jupyter 组件中保存文本

下一步是写一些东西，将你输入的文字保存到一个文件中，并提交到 Git。另外，由于你要写 5 分钟的日记，你需要一个能给你提供写字区域的组件（滚动肯定是可以的，但一次能看到更多的文字就更好了）。

这就用到了组件 `Textarea`，这是一个你可以书写的文本字段，而 `Output` 则是用来给出反馈的。这一点很重要，因为 `git push` 可能会花点时间或失败，这取决于网络。如果备份失败，用反馈提醒用户很重要：

```
def editor(fname):
    textarea = ipywidgets.Textarea(continuous_update=False)
    textarea.rows = 20
    output = ipywidgets.Output()
    runner = functools.partial(subprocess.run, capture_output=True, text=True, check=True)
    def save(_ignored):
        with output:
            with open(fname, "w") as fpout:
                fpout.write(textarea.value)
            print("Sending...", end='')
            try:
                runner(["git", "add", fname])
                runner(["git", "commit", "-m", f"updated {fname}"])
                runner(["git", "push"])
            except subprocess.CalledProcessError as exc:
                print("Could not send")
                print(exc.stdout)
                print(exc.stderr)
            else:
                 print("Done")
    textarea.observe(save, names="value")
    return textarea, output, save

```

`continuous_update=False` 是为了避免每个字符都保存一遍并发送至 Git。相反，只要脱离输入焦点，它就会保存。这个函数也返回 `save` 函数，所以可以明确地调用它。

### 创建一个布局

最后，你可以使用 `ipywidgets.VBox` 把这些东西放在一起。这是一个包含一些组件并垂直显示的东西。还有一些其他的方法来排列组件，但这足够简单：

```
def journal():
    date = str(datetime.date.today())
    title = f"Log: Startdate {date}"
    filename = os.path.join(f"{date}.txt")
    d, clock = time_out_counter(reactor)
    textarea, output, save = editor(filename)
    box = ipywidgets.VBox([
        ipywidgets.Label(title),
        textarea,
        clock,
        output
    ])
    d.addCallback(save)
    return box

```

biu！你已经定义了一个写日记的函数了，所以是时候试试了。

```
journal()

```

![Jupyter journal](/data/attachment/album/202012/05/131427th1adajyyyeqhrny.png "Jupyter journal")

你现在可以写 5 分钟了！

---

via: <https://opensource.com/article/20/11/daily-journal-jupyter>

作者：[Moshe Zadka](https://opensource.com/users/moshez) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


下载 2020 年度 Linux 基金会年度报告

![](/data/attachment/album/202012/05/205526tp6unnun6p6t4opr.png)

2020 年对于 <ruby> Linux 基金会 <rt>  Linux Foundation </rt></ruby>（LF）和我们托管的社区来说，是充满挑战的一年。在这次大流行期间，我们都看到我们和世界各地许多同事、朋友和家人的日常生活完全改变了。在我们的社区中，有太多的人也为失去家人和朋友而悲痛。

看到 LF 的成员加入到对抗 COVID-19 的斗争中，令人振奋。我们在世界各地的成员为科研人员贡献了技术资源，为挣扎中的家庭和个人提供了援助，为国家和国际努力做出了贡献，有些人甚至一起在 [LF 公共卫生](https://www.lfph.io/) 下创建了开源项目，以帮助各国应对这场大流行病。

今年，我们的项目社区在继续发展，在许多开放技术领域、开放标准、开放数据和开放硬件方面都有新的举措。今年，我们迎接了 150 多个新社区加入 LF，包括 [FINOS 基金会](https://www.finos.org/)，它是开源金融服务项目的保护项目。

我们的 [活动团队](https://events.linuxfoundation.org/) 不得不进行了重大转型，在几周内，从面对面的活动转变为虚拟活动，参与者从不足 100 人到数万人不等。这些虚拟聚会帮助我们社区中的许多人在这个困难时期建立了联系。我们也学到了很多关于未来可能通过提供虚拟体验的<ruby> 混合亲身活动 <rt>  hybrid in-person events </rt></ruby>来提供更具包容性的体验。今年，我们很想念在我们的社区中见到的许多朋友，并期待着在安全的情况下再次见到你们。

我们的 [培训和认证](https://training.linuxfoundation.org/) 团队能够帮助 170 多万名报名参加我们免费培训课程的人。我要祝贺今年获得 LF 认证的 4 万多人。

《[LF 的 2020 年度工作报告](https://training.linuxfoundation.org/resources/2020-open-source-jobs-report/)》显示，尽管商业环境充满挑战，但经过培训和认证的开源专业人员仍有大有需求，并能轻松地展示其价值。

作为我们正在进行的多元化努力的一部分，在加入反对不平等的斗争中，我们的社区专注于该如何在项目中使用语言，并寻找导师来指导下一代的贡献者。我们的社区，如 Linux 内核团队和在北美 KubeCon 上发起的 <ruby>   包容性命名倡议  <rt>  Inclusive Naming Initiative </rt></ruby>，在加强我们的互动方式上取得了进展。

今年是我们<ruby> 联合发展基金会 <rt>  Joint Development Foundation </rt></ruby>（JDF）和<ruby> 开放标准社区 <rt>  open standards communities </rt></ruby>的突破性一年。我们迎来了六个建立开放标准的新项目。[JDF 还被批准为 ISO/IEC JTC 1 公开发布规范（PAS）提交者](https://www.linuxfoundation.org/blog/2020/05/joint-development-foundation-recognized-as-an-iso-iec-jtc-1-pas-submitter-and-submits-openchain-for-international-review/)。今年还标志着我们的第一个开放标准社区 OpenChain 通过 PAS 程序，被正式认可为国际标准。今天，Linux 基金会可以把我们的社区，从开源仓库带到一个公认的全球标准。

今年，我们生态系统中的许多人已经站出来帮助安全工作。一个新的社区 <ruby>   开源安全基金会  <rt>  Open Source Security Foundation </rt></ruby>（OpenSSF）启动了，以协调专注于提高开源软件安全性的努力。

当我们继续在美国与挑战作斗争时，[我们也重申 LF 是全球社区的一部分](https://www.linuxfoundation.org/blog/2020/08/open-source-collaboration-is-a-global-endeavor/)。

我们的成员必须得应对国际贸易政策变化的一年，并了解到开放源码在政治上的蓬勃发展。来自世界各地的我们的成员社区参与了<ruby> 开放合作 <rt>  open collaboration </rt></ruby>，因为它是开放、中立和透明的。这些参与者显然希望继续与全球同行合作，以应对大大小小的挑战。

在这困难的一年结束时，所有这些都让我们确信，开放合作是解决世界上最复杂挑战的模式。没有任何一个人、组织或政府能够单独创造出我们解决最紧迫问题所需的技术。我们代表整个 Linux 基金会团队，期待着帮助您和我们的社区应对接下来的任何挑战。

![](/data/attachment/album/202012/05/205324foky7mm8f8xon7hx.png)

Jim Zemlin，Linux 基金会执行总监

* [下载 Linux 基金会 2020 年度报告](http://linuxfoundation.org/2020-annual-report)

这篇文章首先发布于 [Linux 基金会](https://www.linuxfoundation.org/)。

---

via: <https://www.linux.com/news/download-the-2020-linux-foundation-annual-report/>

作者：[The Linux Foundation](https://www.linuxfoundation.org/blog/2020/12/download-the-2020-linux-foundation-annual-report/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Rails 之旅第 2 天：Rails 关联和拖动 div

![](/data/attachment/album/202012/05/212345zz8jajhaj0hh8h2f.jpg)

大家好！今天是我搭建这个玩具项目的第 2 天。下面再来记录一下关于 Rails 的一些有趣的事情吧！

### 目标：做一个冰箱诗歌论坛

我想做一种无聊的标准网站来学习 Rails，并且其他人可以与之互动，就像一个论坛一样! 但如果人们真的可以在网站上打字，那就会产生各种各样的问题（如果他们是垃圾邮件发送者怎么办？又或者只是言语刻薄？）。

我想到的第一个想法是，可以让人们与网站互动，但实际上却不能在网站上打字，那就是一个“冰箱诗歌论坛”，只给你一组固定的字，你就可以随意组合。

所以，这就是我们的计划！

我这个项目的目标是想知道我是否能用 Rails 来做其他的小型网络项目（而不是像我通常做的那样，使用一些更基本的东西，比如 Flask，或者放弃后端，用 Javascript 来写所有东西）。

### 怎么把字拖来拖去呢？jQuery 的可拖放 UI！

我想让大家能够把文字拖动起来，但我又不想写很多 Javascript。结果发现这超级简单 —— 有一个 jQuery 库可以做到，它叫做 `draggable`！一开始，拖动并不成功。

一开始拖动在手机上是不行的，但是有一个技巧可以让 jQuery UI 在手机上工作，叫做 [jQuery UI touch punch](https://github.com/furf/jquery-ui-touch-punch)。下面是它的样子（有兴趣看工作原理的可以查看源码，代码很少）。

>
> `banana` `forest` `cake` `is`
>
>
>

### 一个有趣的 Rails 功能：关联

我以前从来没有使用过关系型 ORM，对于 Rails，我很兴奋的一件事就是想看看使用 Active Record 是什么样子的！今天我了解了 Rails 的 ORM 功能之一：[关联](https://guides.rubyonrails.org/association_basics.html)。如果你像我一样对 ORM 完全不了解的话，那就来看看是怎么回事吧。

在我的论坛中，我有：

* 用户
* 话题（我本来想把它叫做“线索”，但显然这在 Rails 中是一个保留词，所以现在叫做“话题”）。
* 帖子

当显示一个帖子时，我需要显示创建该帖子的用户的用户名。所以我想我可能需要写一些代码来加载帖子，并为每个帖子加载用户，就像这样（在 Rails 中，`Post.where` 和 `User.find` 将会运行 SQL 语句，并将结果转化为 Ruby 对象）：

```
@posts = Post.where(topic_id: id)
@posts.each do |post|
    user = User.find(post.user_id)
    post.user = user
end

```

这还不够好，它要为每个帖子做一次单独的 SQL 查询！我知道有一个更好的方法，我发现它叫做[关联](https://guides.rubyonrails.org/association_basics.html)。这个链接是来自 <https://guides.rubyonrails.org> 的指南，到目前为止，它对我很有帮助。

基本上我需要做的就是：

1. 在 `User` 模型中添加一行 `has_many :post`。
2. 在 `Post` 模型中添加一行 `belongs_to :user`。
3. Rails 现在知道如何将这两个表连接起来，尽管我没有告诉它要连接到什么列上！我认为这是因为我按照它所期望的惯例命名了 `posts` 表中的 `user_id` 列。
4. 对 `User` 和 `Topic` 做完全相同的事情（一个主题也有很多帖子：`has_many :posts`）。

然后我加载每一个帖子和它的关联用户的代码就变成了只有一行! 就是这一行：

```
@posts = @topic.posts.order(created_at: :asc).preload(:user)

```

比起只有一行更重要的是，它不是单独做一个查询来获取每个帖子的用户，而是在 1 个查询中获取所有用户。显然，在 Rails 中，有一堆[不同的方法](https://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html)来做类似的事情（预加载、急切加载、联接和包含？），我还不知道这些都是什么，但也许我以后会知道的。

### 一个有趣的 Rails 功能：脚手架！

Rails 有一个叫 `rails` 的命令行工具，它可以生成很多代码。例如，我想添加一个 `Topic` 模型/控制器。我不用去想在哪里添加所有的代码，可以直接运行

```
rails generate scaffold Topic title:text

```

并生成了一堆代码，这样我已经有了基本的端点来创建/编辑/删除主题（`Topic`）。例如，这是我的[现在的主题控制器](https://github.com/jvns/refrigerator-forum/blob/776b3227cfd7004cb1efb00ec7e3f82a511cbdc4/app/controllers/topics_controller.rb#L13-L15)，其中大部分我没有写（我只写了高亮的 3 行）。我可能会删除很多内容，但是有一个起点，让我可以扩展我想要的部分，删除我不想要的部分，感觉还不错。

### 数据库迁移！

`rails` 工具还可以生成数据库迁移! 例如，我决定要删除帖子中的 `title` 字段。

下面是我要做的：

```
rails generate migration RemoveTitleFromPosts title:string
rails db:migrate

```

就是这样 —— 只要运行几个命令行咒语就可以了! 我运行了几个这样的迁移，因为我改变了对我的数据库模式的设想。它是相当直接的，到目前为止 —— 感觉很神奇。

当我试图在一列中的某些字段为空的地方添加一个“不为空”（`not null`）约束时，情况就变得有点有趣了 —— 迁移失败。但我可以修复违例的记录，并轻松地重新运行迁移。

### 今天就到这里吧！

明天，如果我有更多的进展，也许我会把它放在互联网上。

---

via: <https://jvns.ca/blog/2020/11/10/day-2--rails-associations---dragging-divs-around/>

作者：[Julia Evans](https://jvns.ca/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


使用 UEFI 双启动 Windows 和 Linux

一个小问题。如果打算使用Windows系统，而不是只做安装测试，20GB空间是远远不够的。20GB连平常安装系统安全更新都不够，不要说加装第三方软件。建议80G起步，最好能有100GB以上。

Win10 系统盘还是200G吧，100G都不够了的。建议256G的SSD单分区，128GSSD转移用户目录后勉强能用个3年。

虚拟机用得也可以的

>
> 这是一份在同一台机器上设置 Linux 和 Windows 双重启动的速成解释，使用统一可扩展固件接口（UEFI）。
>
>
>

![](/data/attachment/album/202012/06/101431eb02wvkk0nzkk5sw.jpg)

我将强调一些重要点，而不是一步一步地指导你来如何配置你的系统以实现双重启动。作为一个示例，我将提到我在几个月之前新买的笔记本计算机。我先是安装 [Ubuntu Linux](https://www.ubuntu.com) 到整个硬盘中，这就摧毁了预装的 [Windows 10](https://www.microsoft.com/en-us/windows) 环境。几个月后，我决定安装一个不同的 Linux 发行版 [Fedora Linux](https://getfedora.org)，也决定在双重启动配置中与它一起再次安装 Windows 10 。我将强调一些极其重要的实际情况。让我们开始吧！

### 固件

双重启动不仅仅是软件问题。或者说它算是软件的问题，因为它需要更改你的固件，以告诉你的机器如何开始启动程序。这里有一些和固件相关的重要事项要铭记于心。

#### UEFI vs BIOS

在尝试安装前，确保你的固件配置是最佳的。现在出售的大多数计算机有一个名为 <ruby>   统一可扩展固件接口  <rt>  Unified Extensible Firmware Interface </rt></ruby> （UEFI）的新类型固件，UEFI 差不多取代了另一个名为 <ruby>   基本输入输出系统  <rt>  Basic Input Output System </rt></ruby>（BIOS）的固件类型，（包括很多固件供应商在内的很多人）通常称 BIOS 为<ruby> 传统启动模式 <rt>  Legacy Boot </rt></ruby>。

我不需要 BIOS，所以我选择了 UEFI 模式。

#### 安全启动

另一个重要的设置是<ruby> 安全启动 <rt>  Secure Boot </rt></ruby>。这个功能将检测启动路径是否被篡改，并阻止未经批准的操作系统的启动。现在，我禁用这个选项来确保我能够安装 Fedora Linux 。依据 Fedora 项目维基“[功能/安全启动](https://fedoraproject.org/wiki/Features/SecureBoot)”部分的介绍可知：Fedora Linux 在安全启动选项启用的时候也可以工作。这对其它的 Linux 发行版来说可能有所不同 — 我打算今后重新研究这项设置。

简而言之，如果你发现在这项设置启用时你不能安装你的 Linux 操作系统，那么禁用安全启动并再次重新尝试安装。

### 对启动驱动器进行分区

如果你选择双重启动并且两个操作系统都在同一个驱动器上，那么你必须将它分成多个分区。即使你使用两个不同的驱动器进行双重启动，出于各种各样的原因，大多数 Linux 环境也最好分成几个基本的分区。这里有一些选项值得考虑。

#### GPT vs MBR

如果你决定手动分区你的启动驱动器，在动手前，我建议使用<ruby>   GUID 分区表  <rt>  GUID Partition Table </rt></ruby>（GPT），而不是使用旧的<ruby>   主启动记录  <rt>  Master Boot Record </rt></ruby>（MBR） 。这种更改的原因之一是：MBR 有两个特定的限制，而 GPT 却没有：

* MBR 可以最多拥有 15 个分区，而 GPT 可以最多拥有 128 个分区。
* MBR 最多仅支持 2 TB 磁盘，而 GPT 使用 64 位地址，这使得它最多支持 800 万 TB 的磁盘。

如果你最近购买过硬盘，那么你可能会知道现代的很多硬盘都超过了 2 TB 的限制。

#### EFI 系统分区

如果你正在进行一次全新的安装或使用一块新的驱动器，那么这里可能没有可以开始的分区。在这种情况下，操作系统安装程序将先创建一个分区，即<ruby>   EFI 系统分区  <rt>  EFI System Partition </rt></ruby>（ESP）。如果你选择使用一个诸如 [gdisk](https://sourceforge.net/projects/gptfdisk/) 之类的工具来手动分区你的驱动器，你将需要使用一些参数来创建这个分区。基于现有的 ESP ，我设置它为约 500 MB 的大小，并分配它为 `ef00`（ EFI 系统 ）分区类型。UEFI 规范要求格式化为 FAT32/msdos ，很可能是因为这种格式被大量的操作系统所支持。

![分区](/data/attachment/album/202012/06/181252q1adefue9wx0qbkw.png)

### 操作系统安装

在你完成先前的两个任务后，你就可以安装你的操作系统了。虽然我在这里关注的是 Windows 10 和 Fedora Linux ，当安装其它组合时的过程也是非常相似。

#### Windows 10

我开始 Windows 10 的安装，并创建了一个 20 GB 的 Windows 分区。因为我先前在我的笔记本计算机上安装了 Linux ，所以驱动器已经有了一个 ESP ，我选择保留它。我删除所有的现有 Linux 和交换分区来开始一次全新安装，然后开始我的 Windows 安装。Windows 安装程序自动创建另一个 16 MB 的小分区，称为 <ruby>   微软保留分区  <rt>  Microsoft Reserved Partition </rt></ruby>（MSR）。在这完成后，在 512 GB 启动驱动器上仍然有大约 400 GB 的未分配空间。

接下来，我继续完成了 Windows 10 安装过程。随后我重新启动到 Windows 来确保它是工作的，在操作系统第一次启动时，创建我的用户账号，设置 Wi-Fi ，并完成其它必须的任务。

#### Fedora Linux

接下来，我将心思转移到安装 Linux 。我开始了安装过程，当安装进行到磁盘配置的步骤时，我确保不会更改 Windows NTFS 和 MSR 分区。我也不会更改 ESP ，但是我设置它的挂载点为 `/boot/efi`。然后我创建常用的 ext4 格式分区， `/`（根分区）、`/boot` 和 `/home`。我创建的最后一个分区是 Linux 的交换分区（swap）。

像安装 Windows 一样，我继续完成了 Linux 安装，随后重新启动。令我高兴的是，在启动时<ruby>   大一统启动加载程序  <rt>  GRand Unified Boot Loader </rt></ruby>（GRUB）菜单提供选择 Windows 或 Linux 的选项，这意味着我不需要再做任何额外的配置。我选择 Linux 并完成了诸如创建我的用户账号等常规步骤。

### 总结

总体而言，这个过程是不难的，在过去的几年里，从 BIOS 过渡到 UEFI 有一些困难需要解决，加上诸如安全启动等功能的引入。我相信我们现在已经克服了这些障碍，可以可靠地设置多重启动系统。

我不再怀念 [Linux LOader](https://en.wikipedia.org/wiki/LILO_(boot_loader))（LILO）！

---

via: <https://opensource.com/article/19/5/dual-booting-windows-linux-uefi>

作者：[Alan Formy-Duval](https://opensource.com/users/alanfdoss/users/ckrzen) 选题：[lujun9972](https://github.com/lujun9972) 译者：[robsean](https://github.com/robsean) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 LibreOffice 中完全启用深色模式

![](/data/attachment/album/202012/07/083812n0zgss9qt175pm9z.jpg)

[LibreOffice](https://www.libreoffice.org) 是一款自由开源的跨平台办公生产力软件。如果你没有充分利用它，那么必须看下 [LibreOffice 小技巧](https://itsfoss.com/libreoffice-tips/)。

甚至在非编程人员中，深色主题也越来越受欢迎。它减轻了眼睛的压力，特别适合长时间使用屏幕。有人认为，这使文本看起来清晰明了，有助于提高生产率。

如今，某些 Linux 发行版例如 [Ubuntu 带有深色模式](https://itsfoss.com/dark-mode-ubuntu/)，使你的系统具有更暗的色彩。当你打开<ruby> 深色模式 <rt>  dark mode </rt></ruby>时，某些应用将自动切换到深色模式。

LibreOffice 也会这样，但你编辑的主区域除外：

![LibreOffice semi dark mode matching with the system theme](/data/attachment/album/202012/07/084009a9f904449z46dxz9.png)

你可以更改它。如果要让 LibreOffice 进入完全深色模式，只需更改一些设置。让我告诉你如何做。

### 如何在 LibreOffice 中完全启用深色模式

如前所述，你需要先启用系统范围的深色模式。这样可以确保窗口颜色（或标题栏）与应用内深色完全融合。

接下来，打开套件中的**任意** LibreOffice 应用，例如 **Writer**。然后从菜单中，依次点击 **Tools -> Options -> Application Colors**，然后选择 **Document background 和 Application background** 为 **Black** 或 **Automatic**（任意适合你的方式）。

![](/data/attachment/album/202012/07/083939y8cmmokapap6aoz2.png)

如果图标不是深色，那么可以从菜单（如下图所示）中更改它们，**Tools -> Options -> View** ，我在 MX Linux 上的个人选择是 Ubuntu 的 [Yaru](https://extensions.libreoffice.org/en/extensions/show/yaru-icon-theme) 图标样式（如果你使用的图标包为深色版本，请选择它） 。

![](/data/attachment/album/202012/07/083946olxmuigslmoujs3f.png)

当然，你也可以尝试其他 Linux 发行版的 [icon 主题](https://itsfoss.com/best-icon-themes-ubuntu-16-04/)。

最终结果应如下所示：

![](/data/attachment/album/202012/07/083949n7f5sa9zwcxlalil.png)

#### LibreOffice flatpak 软件包的其他技巧

如果你使用的是 LibreOffice 套件的 [Flatpak 软件包](https://itsfoss.com/what-is-flatpak/)，那么 LibreOffice 的标题区域（或菜单区域）可能看起来是白色的。在这种情况下，你可以尝试进入 **Tools -> Options -> Personalization**，然后选择 “**灰色主题**”，如下截图所示。

![](/data/attachment/album/202012/07/083952tcqqt1cnqqwc67bt.png)

它并不完全是黑色的，但应该可以使外观看起来更好。希望可以帮助你切换到深色主题的 LibreOffice 体验！

#### 总结

深色主题逐渐开始在我们的台式机中占主导地位，它具有现代品味并减少了眼睛疲劳，尤其是在弱光条件下。

LibreOffice 使你可以自由地将工作环境切换为深色主题或保留浅色主题元素。实际上，你将有大量的自定义选项来调整你喜欢的内容。你是否已在 LibreOffice 上切换为深色主题？你首选哪种颜色组合？在下面的评论中让我们知道！

---

via: <https://itsfoss.com/libreoffice-dark-mode/>

作者：[Dimitrios Savvopoulos](https://itsfoss.com/author/dimitrios/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


改变我使用 Git 工作方式的七个技巧

Summary: 这些有用的技巧将改变你使用这个流行的版本控制系统的工作方式。

这些有用的技巧将改变你使用这个流行的版本控制系统的工作方式。

>
> 这些有用的技巧将改变你使用这个流行的版本控制系统的工作方式。
>
>
>

![](/data/attachment/album/202012/07/092803d67fa7bttuuj98fb.jpg)

Git 是目前最常见的版本控制系统之一，无论是私有系统还是公开托管的网站，都在使用它进行各种开发工作。但无论我对 Git 的使用有多熟练，似乎总有一些功能还没有被发现，下面是改变我使用 Git 工作方式的七个技巧。

### 1、Git 中的自动更正

我们有时都会打错字，但如果启用了 Git 的自动更正功能，就可以让 Git 自动修正打错的子命令。

假设你想用 `git status` 检查状态，却不小心输入了 `git stats`。正常情况下，Git 会告诉你 `stats` 不是一条有效的命令：

```
$ git stats
git: ‘stats’ is not a git command. See ‘git --help’.

The most similar command is
status

```

为了避免类似的情况发生，请在 Git 配置中启用 Git 自动更正功能：

```
$ git config --global help.autocorrect 1

```

如果你希望这个命令只适用于你当前的版本库，请省略 `--global` 选项。

这条命令启用了自动更正功能。更深入的教程可以在 [Git Docs](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_code_help_autocorrect_code) 中找到，但尝试一下和上面一样的错误命令，就能很好地了解这个配置的作用：

```
$ git stats
git: ‘stats’ is not a git command. See ‘git --help’.
On branch master
Your branch is up to date with ‘origin/master’.

nothing to commit, working tree clean

```

Git 现在不会建议使用其他子命令，而是直接运行最上面的建议，在本例中是 `git status`。

### 2、计算你的提交量

你需要计算提交数量可能有很多原因。例如，许多开发者通过计算提交数量来判断何时该增加构建版本号，或者只是想了解项目的进展情况。

要计算提交数量其实很简单直接，下面是 Git 的命令：

```
$ git rev-list --count branch-name

```

在上面的命令中，`branch-name` 应该是当前版本库中有效的分支名称：

```
$ git rev-list –count master
32
$ git rev-list –count dev
34

```

### 3、优化你的仓库

你的代码仓库不仅对你有价值，对你的组织也有价值。你可以通过一些简单的做法来保持你的版本库的清洁和更新。其中一个最好的做法是 [使用 .gitignore 文件](/article-12524-1.html)。使用这个文件，就是告诉 Git 不要存储许多不需要的文件，比如二进制文件、临时文件等等。

为了进一步优化你的版本库，你可以使用 Git 的垃圾收集功能：

```
$ git gc --prune=now --aggressive

```

当你或你的团队大量使用 `pull` 或 `push` 命令时，这条命令就会起到帮助作用。

这个命令是一个内部工具，可以清理仓库中无法访问或 “孤儿” Git 对象。

### 4、备份未被跟踪的文件

大多数时候，删除所有未被跟踪的文件是安全的。不过很多时候，你不仅要删除，还要为你的未跟踪文件创建一个备份，以备以后需要。

通过 Git 和一些 Bash 命令管道，可以很容易地为你的未被跟踪的文件创建一个压缩包：

```
$ git ls-files --others --exclude-standard -z |\
xargs -0 tar rvf ~/backup-untracked.zip

```

上面的命令制作了一个名为 `backup-untracked.zip` 的存档（并排除了 `.gitignore` 中列出的文件）。

### 5、了解你的 .git 文件夹

每个版本库都有一个 `.git` 文件夹。它是一个特殊的隐藏文件夹。

```
$ ls -a
. … .git

```

Git 的工作主要依赖于两个部分：

1. 工作树（你当前签出的文件状态）。
2. 你的 Git 仓库的路径（即你的 `.git` 文件夹的位置，其中包含版本信息）。

这个文件夹存储了所有的引用和其他重要的细节，比如配置、仓库数据、HEAD 状态、日志等等。

如果你删除这个文件夹，你的源代码的当前状态不会被删除，但你的远程信息，如你的项目历史记录，会被删除。删除这个文件夹意味着你的项目（至少是本地副本）不再处于版本控制之下。这意味着你不能跟踪你的变化；你不能从远程拉取或推送。

一般来说，不需要在 `.git` 文件夹里做什么，也没有什么应该做的。它是由 Git 管理的，基本上被认为是个禁区。然而，这个目录里有一些有趣的工件，包括 HEAD 的当前状态。

```
$ cat .git/HEAD
ref: refs/heads/master

```

它还可能包含对你的存储库的描述：

```
$ cat .git/description

```

这是一个未命名的仓库，编辑这个 `description` 文件可以命名这个仓库。

Git 钩子文件夹（`hooks`）也在这里，里面有一些钩子示例文件。你可以阅读这些示例来了解通过 Git 钩子可以实现什么，你也可以 [阅读 Seth Kenlon 的 Git 钩子介绍](https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6)。

### 6、查看另一个分支的文件

有时你想查看另一个分支的文件的内容。用一个简单的 Git 命令就可以实现，而且不需要切换分支。

假设你有一个名为 [README.md](http://README.md) 的文件，它在 `main` 分支中，而你正在 `dev` 分支上工作。

使用下面的 Git 命令，你可以在终端上完成：

```
$ git show main:README.md

```

一旦你执行了这个命令，你就可以在你的终端上查看文件的内容。

### 7、在 Git 中搜索

只需一个简单的命令，你就可以像专业人士一样在 Git 中搜索。更棒的是，即使你不确定是在哪个提交或分支上做的修改，也可以在 Git 中搜索。

```
$ git rev-list --all | xargs git grep -F 'string'

```

例如，假设你想在你的版本库中搜索 `font-size: 52 px;` 这个字符串：

```
$ git rev-list –all | xargs git grep -F 'font-size: 52 px;'
F3022…9e12:HtmlTemplate/style.css: font-size: 52 px;
E9211…8244:RR.Web/Content/style/style.css: font-size: 52 px;

```

### 试试这些技巧

希望这些高级技巧对你有用，提高你的工作效率，为你节省很多时间。

你有喜欢的 [Git 小技巧](https://acompiler.com/git-tips/) 吗？在评论中分享吧。

---

via: <https://opensource.com/article/20/10/advanced-git-tips>

作者：[Rajeev Bera](https://opensource.com/users/acompiler) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


2020 年的 GitHub 年度报告，我看出了这些不一样的点

Summary: 作为一个开发者，我十分建议你下载一份官方的报告，细读其中的建议，让自己的开发更有效率；让自己的生活更加丰富多彩；让自己的代码，更少 Bug ！

![](/data/attachment/album/202012/07/095516lnxag1t96n9zfd8c.png)

距离 2020 年结束只剩下区区 24 天，我们即将结束魔幻的 2020 ，迎来新的一年，新的一年或好或坏，但终将到来。

### Github 年度报告的两点变化

在上周，Github 发布了 [2020 年度报告](https://octoverse.github.com/)，相信各位都有所耳闻。在对比了从 2016 年至 2020 年共计五年的报告后，我观察到了以下两点变化：

#### 1、从关注数据，到关注人

2020 年和往年的报告一个很不同的点在于，不再单纯的以数据讲话。这样的表现“很不程序员”，反倒是和我们所熟悉的另外一个科技巨头 —— 苹果很像。不再强调数据的绝对差值，更多关注技术对于人、事、物引发的变化。

在 2020 年的报告中，内容被分为了三个不同的部分：**寻找平衡、赋能社区、保护软件安全**。

![](/data/attachment/album/202012/07/095618o5z7o275tfb85ss8.jpg)

这三者则分别对应在今年发生在每一个 GitHub 开发者身上的事件：

* Covid-19 新冠肺炎迫使开发者居家办公，以及由此引发的生活和工作平衡的思考；
* GitHub 为开源项目提供新的功能 Discussions 允许开源项目建立社区，让<ruby> 议题 <rt>  issue </rt></ruby>可以更加专业；
* GitHub 为所有项目开启安全检查项目，提醒开发者为项目更新出现安全问题的依赖和软件代码。

除了一个标准的概览之外，GitHub 还为这三个不同的大事件准备了详细的报告，如果你感兴趣，可以[下载](https://octoverse.github.com/static/2020-reports.zip)来看。

#### 2、从只给数据，到还给建议

和往年的报告只关注数据不同，今年的 GitHub 2020 年度报告给出了不少的建议，指导开发者们的下一步行动。而这些建议，无论你是否可以遵循，都可以给你一些新的思考维度，可以让你获得更全的信息。

比如，在生产力篇的第 6 页，GitHub 给出了一些建议，来帮助开发者获得工作和生活的平衡，谋求更好的开发体验。

![](/data/attachment/album/202012/07/095650fgkgoza26xl6kdx8.jpg)

类似的建议也出现在了安全篇的第 6 页，GitHub 为开发者提供了一些有效的保护软件安全的介绍，帮助开发者防御安全问题。

![](/data/attachment/album/202012/07/095715oqbngc3poo4uj4p4.jpg)

报告中的其他地方也出现了类似的建议，帮助更多的开发者避开问题。

![](/data/attachment/album/202012/07/095745nkgflfw9yyfyny0x.jpg)

### 值得关注的数据

除了 2020 年度报告的结构和行文变化，报告中的一些数据也值得我们关注：

#### GitHub 不仅仅是开源的代名词，更是工作的代名词

在 2020 年度报告中，GitHub 首次给出了按周计算的活跃度信息，可以看到，GitHub 的活跃用户信息和工作日、节日等节点高度重合，明显表现出了工作日和休息日的区别。

![](/data/attachment/album/202012/07/095818wk11gk1ukhczklgq.jpg)

和我们曾经设想的，工作时做公司的事，下班的时候做开源不同。如今，GitHub 已经成为一种工作方式，我们会在工作的时候，因为工作需要而打开 GitHub，在休息的时候，因为个人兴趣而打开 GitHub。

**Github 如今已经成为了一种必备品，我们每天都在“面向 GitHub 编程”～**

#### 变大的总量，新加入的学生和占比减少的开发者们

GitHub 公布的 2020 年开发者总数为 5600 万开发者，而在 2019 年这一数字是 4000 万开发者，过去的一年里新增了 1600 万开发者，而纵观近几年数据，今年新增的数据是历年来新增用户最多的一年。

![](/data/attachment/album/202012/07/095849ah1fzasbosx0e7sg.jpg)

而总量变化的同时，开发者的比重在所有用户的所占比重在下降，从 2016 年的 60% 逐年递减至 2020 年的 54%，相反，我们可以看到，教育相关的学生用户、教师用户的比重在不断的攀升，到 2020 年，教育相关用户的比例已达 23%，几乎达到了 Github 用户比重的四分之一。

![](/Users/xingyuwang/Desktop/github2020/media/16072639196024/16072655897089.jpg)![](/data/attachment/album/202012/07/095910mtf1btp1e889jeta.jpg)

学生成为 GitHub 用户中的主力，在未来，我们将会看到更多基于 GitHub 的学习、教育的方式，GitHub 也将成为软件开发、计算机科学等相关领域的必修课。

#### 自动生成的安全更新和更快的软件安全更新

对于绝大多数的软件来说，对于第三方库和代码的依赖是不可避免的，特别是使用 JavaScript、Ruby 和 .Net 的开发者，对于第三方库的依赖都在 90% 以上；这些第三方依赖除了引入了更便捷完成代码逻辑以外，还带入了更多的安全问题。对于开发者来说，如何尽可能不受依赖影响，保障软件安全就成为了一个值得关注的问题。

![](/data/attachment/album/202012/07/095941fgpd7n7778j4759d.jpg)![](/Users/xingyuwang/Desktop/github2020/media/16072639196024/16072680807233.jpg)

GitHub 为开发者提供了无痛的自动生成安全更新<ruby> 拉取请求 <rt>  Pull Request </rt></ruby>（PR）功能，系统在后台自动检测依赖代码是否有相应的安全更新，并创建相应的拉取请求，为开发者提供了一键解决依赖库所引发的安全问题的功能。降低开发者维护软件的成本，将一部分可以自动化完成的工作，交由系统自动完成。根据 GitHub 的测算，在接入了该功能以后，**开源代码的安全更新速度相比于之前提升了 4.4 周时间，让软件的迭代更加的快捷。**

不过目前该功能仅支持六种不同的包管理器和编程语言，具体包括：Composer（PHP）、Maven（Java）、npm（Javascript）、NuGet（.Net）、PyPI（Python）、RubyGems（Ruby），其他语言暂时无法享受到来自 GitHub 提交的安全更新。

### 总结

今年的 Github 报告中的一些表现，和往年的报告有所不同，表现出的人性，让我们有了更加暖心的建议。作为一个开发者，我十分建议你[下载](https://octoverse.github.com/static/2020-reports.zip)一份官方的报告，细读其中的建议，让自己的开发更有效率；让自己的生活更加丰富多彩；让自己的代码，更少 Bug ！

![](/data/attachment/album/202012/07/100021ooyyfyi9oyyxozxw.png)


如何在 1 分钟内阻止 7000 台机器的僵尸网络

>
> 对 CrowdSec 的配置更改，在不到一分钟的时间内阻止了一个 7000 台机器的僵尸网络的攻击。
>
>
>

![](/data/attachment/album/202012/07/220444x6kaedeu6ko0e7uo.jpg)

2020 年，我们的生活和工作方式在短短几天内被彻底颠覆。随着 COVID-19 开始在全球范围内蔓延，我们将工作带回家，与同事、朋友和家人保持在线联系成为关键的必需品。这为黑客造成破坏打开了大门。例如，根据 Neustar 的数据，今年上半年全球的分布式拒绝服务（DDOS） 攻击[增长了 151%](https://www.businesswire.com/news/home/20200916005046/en/DDoS-Attacks-Increase-by-151-in-First-Half-Of-2020)。

[CrowdSec](https://crowdsec.net/) 是一个开源的安全引擎，它可以分析访问者的行为，并提供适应各种攻击的响应。它能解析来自各种来源的日志，并应用启发式方案来识别攻击性行为，并防范大多数攻击类别。并且，它与其它安装的 CrowdSec 系统共享该情报。每次 IP 地址被阻止时，它都会通知整个用户社区。这就创建了一个[实时、协作的 IP 信誉数据库](https://opensource.com/article/20/10/crowdsec)，利用人群的力量使互联网更加安全。

### CrowdSec 如何工作：案例研究

Sorf Networks 是一家总部位于土耳其的技术公司，为客户提供高配置的托管服务器和 DDoS 防护解决方案，它提供了一个 CrowdSec 工作的例子。Sorf 的一个客户每天都会遇到来自 1 万多台机器僵尸网络的 DDoS 攻击，并努力寻找一种能够满足技术要求的解决方案来及时处理这些攻击。

虽然客户采取了一般的预防措施来缓解这些攻击，比如引入 JavaScript（JS）<ruby> 挑战 <rt>  challenges </rt></ruby>、限速等，但这些措施在整个攻击面并不可行。一些 URL 需要被非常基本的软件使用，而这些软件不支持 JS 挑战。黑客就是黑客，这正是他们每天的目标：链条上最薄弱的环节。

Sorf Networks 首先使用 [Fail2ban](https://www.fail2ban.org)（这启发了 CrowdSec）为其客户建立了一个 DDoS 缓解策略。它在一定程度上帮助了客户，但它太慢了。它需要 50 分钟来处理日志和处理 7000 到 10000 台机器的 DDoS 攻击。这使得它在这种情况下没有效果。另外，因为它没有禁止 IP，日志会持续堆积，它需要每秒处理几千条日志，这是不可能的。

在使用租用的僵尸网络进行的 DDoS 测试中，一次攻击可以高达每秒 6700 个左右的请求，这些请求来自 8600 个独立 IP。这是对一台服务器流量的捕捉：

![Server traffic](/data/attachment/album/202012/07/220638f49an828ue2pp2q9.png "Server traffic")

虽然 CrowdSec 技术可以应对巨大的攻击，但其默认设置每秒只能处理约 1000 个端点。Sorf 需要一个量身定做的配置来处理单台机器上这么多的流量。

Sorf 的团队对 CrowdSec 的配置进行了修改，以显著提高其吞吐量来处理日志。首先，它去掉了高消耗且非关键的<ruby> 富集 <rt>  enrichment </rt></ruby>解析器，例如 [GeoIP 富集](https://hub.crowdsec.net/author/crowdsecurity/configurations/geoip-enrich)。它还将允许的 goroutine 的默认数量从一个增加到五个。之后，团队又用 8000 到 9000 台主机做了一次实测，平均每秒 6000 到 7000 个请求。这个方案是有代价的，因为 CrowdSec 在运行过程中吃掉了 600% 的 CPU，但其内存消耗却保持在 270MB 左右。

然而，结果却显示出明显的成功：

* 在一分钟内，CrowdSec 能够处理所有的日志
* 95% 的僵尸网络被禁止，攻击得到有效缓解
* 15 个域现在受到保护，不受 DDoS 攻击

根据 Sorf Networks 的总监 Cagdas Aydogdu 的说法，CrowdSec 的平台使团队“能够在令人难以置信的短时间内提供一个世界级的高效防御系统”。

---

本文改编自[如何用 CrowdSec 在 1 分钟内阻止 7000 台机器的僵尸网络](https://crowdsec.net/2020/10/21/how-to-stop-a-botnet-with-crowdsec/)，原载于 CrowdSec 网站。

---

via: <https://opensource.com/article/20/12/open-source-vs-ddos-attacks>

作者：[Philippe Humeau](https://opensource.com/users/philippe-humeau) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Fedora 中添加第三方存储库以访问大量附加软件

![](/data/attachment/album/202012/08/074323tkjpr2499rtjnjq0.jpg)

在你安装 Fedora 后。你可能会发现你想要安装和使用的一些软件在软件商店中找不到。出于一些原因，这些软件包不能出现在 Fedora 存储库中。

不用担心，我将告诉你如何为 Fedora 添加第三方存储库来使这些软件包可使用。

### 在 Fedora 中的第三方存储库是什么？

操作系统开发人员通常会决定哪些软件包可以在其存储库中使用，哪些软件包不可以在其存储库中使用。Fedora 也是如此。依据 [Fedora 文档](https://docs.fedoraproject.org/en-US/quick-docs/setup_rpmfusion/#third-party-repositories) ，第三方存储库包含有 “拥有更为宽松的许可政策，并提供 Fedora 因各种原因所排除软件包” 的软件包。

Fedora 强制执行下面的 [准则](https://fedoraproject.org/wiki/Forbidden_items) ，当它打包软件包时:

* 如果它是专有的，它就不能包含在 Fedora 中
* 如果它在法律上被限制，它就不能包含在 Fedora 中
* 如果它违反美国法律（特别是联邦政府或适用于州政府的法律），它就不能包含在 Fedora 中

因此，有一些可以由用户自行添加的存储库。这使得用户能够访问附加的软件包。

### 在 Fedora 中启用 RPM Fusion 存储库

[RPM Fusion](https://rpmfusion.org/RPM%20Fusion) 是 Fedora 的第三方应用程序的主要来源。RPM Fusion 是由三个项目（Dribble、Freshrpms 和 Livna）合并而成的。RPM Fusion 提供两种不同的软件存储库。

* free 存储库：包含开源软件。
* nonfree 存储库：包含没有开源协议的软件，但是它们的源文件代码却是可以自由使用的。

这里有两种方法来启动 RPM Fusion：从终端启用，或通过点击几个按钮来启用。我们将逐一查看。

#### 方法 1：命令行方法

这是启用 RPM Fusion 存储库的最简单的方法。只需要输入下面的命令即可启用两个存储库：

```
sudo dnf install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

```

会要求你输入密码、确认是否你想要安装这些存储库。在你确认后，安装过程将在几秒钟或几分钟内完成。

![通过命令行安装 RPM Fusion](/data/attachment/album/202012/08/074421at4wec4wzcijeet0.png)

#### 方法 2：图形用户界面方法

使用这个方法来启用 RPM Fusion 存储库，你需要访问 [RPM Fusion 网站](https://rpmfusion.org/Configuration) 。你将看到针对不同 Fedora 版本的两个存储库的链接。

RPM Fusion 建议先安装 free 存储库。因此，单击针对你 Fedora 版本的 free 存储库的链接。然后会打开一个窗口来询问你是否想安装该存储库。单击安装。

![通过图形用户界面安装 RPM Fusion](/data/attachment/album/202012/08/074452qli72bbl7byxbqyt.png)

在安装过程完成后，返回并使用相同的步骤安装 nonfree 存储库。

### 启用 Fedora 的第三方存储库

Fedora 最近开始提供它自己的 [第三方应用程序存储库](https://fedoraproject.org/wiki/Workstation/Third_Party_Software_Repositories) 。在这个存储库中 [可使用的应用程序的数量](https://fedoraproject.org/wiki/Workstation/Third_party_software_list) 是非常少的。你可以 [使用它来在 Fedora 上安装 Chrome 浏览器](https://itsfoss.com/install-google-chrome-fedora/) 。除 Chrome 外，它也包含 Adobe Brackets、Atom、Steam、Vivaldi、Opera 等应用程序。

就像 RPM Fusion 一样，你可以通过终端或图形用户界面的方法来启用这个存储库。

#### 方法 1：命令行方法

为启用 Fedora 的第三方存储库，输入下面的命令到你的终端中：

```
sudo dnf install fedora-workstation-repositories

```

当被提示时，确保输入你的密码并输入 `Y` 来确认安装。

#### 方法 2：图形用户界面方法

如果你不习惯使用终端，你可以使用图形用户界面方法。

首先，你需要打开 Gnome “软件”。接下来，你需要单击右上角的汉堡菜单，并从菜单中选择“软件存储库”。

![Gnome 软件的菜单](/data/attachment/album/202012/08/074432d0b5tb8uxkputtu5.png)

在软件存储库窗口中，你将在其顶部看到写着 “第三方存储库” 字样的部分。单击“安装”按钮。当你被提示时，输入你的密码。

![Fedora 第三方存储库安装](/data/attachment/album/202012/08/074436omnddprda8ncxlal.png)

随着这些附加存储库的启用，你可以安装软件到你的系统当中。你可以从软件中心管理器或使用 DNF 软件包管理器来轻松地安装它们。

如果你发现这篇文章很有趣，请花费一些时间来在社交媒体上分享它。

---

via: <https://itsfoss.com/fedora-third-party-repos/>

作者：[John Paul](https://itsfoss.com/author/john/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[robsean](https://github.com/robsean) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Python Web 框架 Django 中使用序列化器

>
> 序列化用于将数据转换为方便存储或传输的格式，然后将其重新构建以供使用。DRF 是最具有知名的序列化器。
>
>
>

![](/data/attachment/album/202012/08/220845q5tz7cfftze5oem5.jpg)

序列化是将数据转换为可以存储或传输的格式，然后对其进行重新构建的过程。在开发应用程序或将数据存储在数据库、内存或将其转换为文件时，一直会用到它。

我最近帮助 [Labcodes](http://www.labcodes.com.br) 的两名初级开发人员理解序列化器，我想也可以与诸位读者分享一下我的方法。

假设你正在编写一个电子商务网站，你有一个订单，该订单记录了某人在某个日期以某种价格购买了一个产品：

```
class Order:
    def __init__(self, product, customer, price, date):
        self.product = product
        self.customer = customer
        self.price = price
        self.date = date

```

现在，假设你想从一个键值数据库中存储和检索订单数据。幸运的是，它的接口可以接受和返回字典，因此你需要将对象转换成字典：

```
def serialize_order(order):
    return {
        'product': order.product,
        'customer': order.customer,
        'price': order.price,
        'date': order.date
    }

```

如果你想从数据库中获取一些数据，你可以获取字典数据并将其转换为订单对象（`Order`）：

```
def deserialize_order(order_data):
    return Order(
        product=order_data['product'],
        customer=order_data['customer'],
        price=order_data['price'],
        date=order_data['date'],
    )

```

这对于简单的数据非常直接了当，但是当你需要处理一些由复杂属性构成的复杂对象时，这种方法就无法很好地扩展。你还需要处理不同类型字段的验证，这需要手工完成大量工作。

此时框架的序列化可以很方便的派上用场。它们使你可以创建带有少量模板的序列化器，这将适用于复杂的情况。

[Django](https://www.djangoproject.com/) 提供了一个序列化模块，允许你将模型“转换”为其它格式：

```
from django.core import serializers

serializers.serialize('json', Order.objects.all())

```

它涵盖了 Web 应用程序最常用的种类，例如 JSON、YAML 和 XML。但是你也可以使用第三方序列化器或创建自己的序列化器。你只需要在 `settings.py` 文件中注册它：

```
# settings.py
SERIALIZATION_MODULES = {
    'my_format': appname.serializers.MyFormatSerializer,
}

```

要创建自己的 `MyFormatSerializer`，你需要实现 `.serialize()` 方法并接受一个查询集和其它选项作为参数：

```
class MyFormatSerializer:
    def serialize(self, queryset, **options):
        # serious serialization happening

```

现在，你可以将查询集序列化为新格式：

```
from django.core import serializers

serializers.serialize('my_format', Order.objects.all())

```

你可以使用选项参数来定义序列化程序的行为。例如，如果要定义在处理 `ForeignKeys` 时要使用嵌套序列化，或者只希望数据返回其主键，你可以传递一个 `flat=True` 参数作为选项，并在方法中处理：

```
class MyFormatSerializer:
    def serializer(self, queryset, **options):
        if options.get('flat', False):
            # don't recursively serialize relationships
        # recursively serialize relationships

```

使用 Django 序列化的一种方法是使用 `loaddata` 和 `dumpdata` 管理命令。

### DRF 序列化器

在 Django 社区中，[Django REST 框架](https://www.django-rest-framework.org/)（DRF）提供了最著名的序列化器。尽管你可以使用 Django 的序列化器来构建将在 API 中响应的 JSON，但 REST 框架中的序列化器提供了更出色的功能，可以帮助你处理并轻松验证复杂的数据。

在订单的例子中，你可以像这样创建一个序列化器：

```
from restframework import serializers

class OrderSerializer(serializers.Serializer):
    product = serializers.CharField(max_length=255)
    customer = serializers.CharField(max_lenght=255)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    date = serializers.DateField()

```

轻松序列化其数据：

```
order = Order('pen', 'renato', 10.50, date.today())
serializer = OrderSerializer(order)

serializer.data
# {'product': 'pen', 'customer': 'renato', 'price': '10.50', 'date': '2020-08-16'}

```

为了能够从数据返回实例，你需要实现两个方法：`create` 和 `update`：

```
from rest_framework import serializers

class OrderSerializer(serializers.Serializer):
    product = serializers.CharField(max_length=255)
    customer = serializers.CharField(max_length=255)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    date = serializers.DateField()

    def create(self, validated_data):
        # 执行订单创建
        return order

    def update(self, instance, validated_data):
       # 执行实例更新
       return instance

```

之后，你可以通过调用 `is_valid()` 来验证数据，并通过调用 `save()` 来创建或更新实例：

```
serializer = OrderSerializer(**data)
## 若要验证数据，在调用 save 之前必须执行
serializer.is_valid()
serializer.save()

```

### 模型序列化器

序列化数据时，通常需要从数据库（即你创建的模型）进行数据处理。`ModelSerializer` 与 `ModelForm` 一样，提供了一个 API，用于从模型创建序列化器。假设你有一个订单模型：

```
from django.db import models

class Order(models.Model):
    product = models.CharField(max_length=255)
    customer = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    date = models.DateField()

```

你可以像这样为它创建一个序列化器：

```
from rest_framework import serializers

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

```

Django 会自动在序列化器中包含所有模型字段，并创建 `create` 和 `udpate` 方法。

### 在基于类的视图（CBV）中使用序列化器

像 Django CBV 中的 `Forms` 一样，序列化器可以很好地与 DRF 集成。你可以设置 `serializer_class` 属性，方便序列化器用于视图：

```
from rest_framework import generics

class OrderListCreateAPIView(generics.ListCreateAPIView):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

```

你也可以定义 `get_serializer_class()` 方法：

```
from rest_framework import generics

class OrderListCreateAPIView(generics.ListCreateAPIView):
    queryset = Order.objects.all()

    def get_serializer_class(self):
        if is_free_order():
            return FreeOrderSerializer
        return OrderSerializer

```

在 CBV 中还有其它与序列化器交互的方法。例如，[get\_serializer()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer) 返回一个已经实例化的序列化器，[get\_serializer\_context()](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#get_serializer_context) 返回创建实例时传递给序列化器的参数。对于创建或更新数据的视图，有 `create` 和 `update`，它们使用 `is_valid` 方法验证数据，还有 [perform\_create](http://www.cdrf.co/3.9/rest_framework.generics/CreateAPIView.html#perform_create) 和 [perform\_update](http://www.cdrf.co/3.9/rest_framework.generics/RetrieveUpdateAPIView.html#perform_update) 调用序列化器的 `save` 方法。

### 了解更多

要了解更多资源，参考我朋友 André Ericson 的[经典 Django REST 框架](http://www.cdrf.co/)网站。它是一个[基于类的经典视图](https://ccbv.co.uk/)的 REST 框架版本，可让你深入查看组成 DRF 的类。当然，官方[文档](https://www.django-rest-framework.org/api-guide/serializers/#serializers)也是一个很棒的资源。

---

via: <https://opensource.com/article/20/11/django-rest-framework-serializers>

作者：[Renato Oliveira](https://opensource.com/users/renato-oliveira) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


尝试将 Jed 作为你的 Linux 终端文本编辑器

Summary: Jed 方便的下拉菜单，让新用户可以轻松地使用终端文本编辑器。

当我按下F10时，激活的不是jed的菜单，而是终端窗口的菜单。何解？

Jed 方便的下拉菜单，让新用户可以轻松地使用终端文本编辑器。

>
> Jed 方便的下拉菜单，让新用户可以轻松地使用终端文本编辑器。
>
>
>

![](/data/attachment/album/202012/09/085456f7fmt74eu6eekpmt.jpg)

你可能听说过 Emacs、Vim 和 Nano 这些典型的 Linux 文本编辑器，但 Linux 有大量的开源文本编辑器，我的目标是在 12 月份对其中的 31 个文本编辑器进行一次公平的测试。

在这篇文章中，我将介绍 [Jed](https://www.jedsoft.org/jed)，它是一个基于终端的编辑器，它的特点是有一个方便的下拉菜单，这让那些刚刚接触终端编辑器的用户，以及那些不喜欢记住每个功能的组合键的用户而言变得特别容易。

### 安装 Jed

在 Linux 上，你的发行版软件仓库可能会让 Jed 通过你的软件包管理器安装：

```
$ sudo dnf install jed

```

并不是所有发行版都是如此，但它是一个很容易从源码编译的应用。首先，下载 [S 语言](https://www.jedsoft.org/releases/slang/)（Jed 的编写语言）并安装（其中 `x.y.z` 请替换为对应的版本号）：

```
$ wget https://www.jedsoft.org/releases/slang/slang-x.y.z.tar.bz2
$ tar xvf slang*bz2
$ cd slang-x.y.z
$ ./configure ; make
$ sudo make install

```

安装好后，对 [Jed 源码](https://www.jedsoft.org/releases/jed)也同样操作（其中 `x.y.z` 请替换为对应的版本号）：

```
$ wget https://www.jedsoft.org/releases/jed/jed-x.y.z.tar.bz2
$ tar xvf jed*bz2
$ cd jed-x.y.z
$ ./configure ; make
$ sudo make install

```

### 启动 Jed

Jed 在终端中运行，所以要启动它，只需打开终端，输入 `jed`：

```
F10 key ==> File   Edit   Search   Buffers   Windows   System   Help

     This is a scratch buffer.  It is NOT saved when you exit.

     To access the menus, press F10 or ESC-m and the use the arrow
     keys to navigate.

     Latest version information is available on the web from
     <http://www.jedsoft.org/jed/>.  Other sources of JED
     information include the usenet newsgroups comp.editors and
     alt.lang.s-lang.  To subscribe to the jed-users mailing list, see
     <http://www.jedsoft.org/jed/mailinglists.html>.

     Copyright (C) 1994, 2000-2009  John E. Davis
     Email comments or suggestions to <jed@jedsoft.org>.

[ (Jed 0.99.19U) Emacs: *scratch*    ()  1/16   8:49am ]

```

### 如何使用 Jed

Jed 自动加载的说明很清晰且很有帮助。你可以按 `F10` 键或 `Esc` 键，然后按字母 `M` 进入顶部菜单。这将使你的光标进入 Jed 顶部的菜单栏，但它不会打开菜单。要打开菜单，请按键盘上的回车键。使用方向键来浏览每个菜单。

屏幕上的菜单不仅对初次使用的用户很有帮助，对有经验的用户来说，它还提供了很好的键盘快捷键提醒。例如，你大概能猜到如何保存正在处理的文件。进入 **File** 菜单，选择 **Save**。如果你想加快这个过程，你可以记住 `Ctrl+X`，然后 `Ctrl+S` 的组合键（是的，这是连续的两个组合键）。

### 探索 Jed 的功能

对于一个简单的编辑器来说，Jed 拥有一系列令人惊讶的实用功能。它有一个内置的多路复用器，允许你同时打开多个文件，但它会“叠”在另一个文件之上，所以你可以在它们之间切换。你可以分割你的 Jed 窗口，让多个文件同时出现在屏幕上，改变你的颜色主题，或者打开一个 shell。

对于任何有 Emacs 使用经验的人来说，Jed 的许多“没有宣传”的功能，例如用于导航和控制的组合键，都是一目了然的。然而，当一个组合键与你所期望的大相径庭时，就会有一个轻微的学习（或者说没有学习）曲线。例如，GNU Emacs 中的 `Alt+B` 可以将光标向后移动一个字，但在 Jed 中，默认情况下，它是 **Buffers** 菜单的快捷键。这让我措手不及，大约本文每句话都遇到一次。

![Jed](/data/attachment/album/202012/09/085555hw48f4momml7o7nl.png "Jed")

Jed 也有**模式**，允许你加载模块或插件来帮助你编写特定种类的文本。例如，我使用默认的 text 模式写了这篇文章，但当我在编写 [Lua](https://opensource.com/article/20/2/lua-cheat-sheet) 时，我能够切换到 lua 模式。这些模式提供语法高亮，并帮助匹配括号和其他分隔符。你可以在 `/usr/share/jed/lib` 中查看 Jed 捆绑了哪些模式，而且因为它们是用 S 语言编写的，你可以浏览代码，并可能学习一种新的语言。

### 尝试 Jed

Jed 是一个令人愉快且清新的 Linux 终端文本编辑器。它轻量级，易于使用，设计相对简单。作为 Vi 的替代方案，你可以在你的 `~/.bashrc` 文件中（如果你是 root 用户，在 root 用户的 `~/.bashrc` 文件中）将 Jed 设置为 `EDITOR` 和 `VISUAL` 变量。今天就试试 Jed 吧。

---

via: <https://opensource.com/article/20/12/jed>

作者：[Seth Kenlon](https://opensource.com/users/seth) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


CentOS 8 落幕，“免费”的 RHEL 没了

Summary: 12 月 8 日，CentOS 项目宣布，CentOS 8 将于 2021 年底结束，而 CentOS 7 将在其生命周期结束后停止维护。

这应该算是一个大新闻吧！！！

Debian的大胜利

资本的胜利，理想主义者又失去了一块阵地。

来自山东日照的 Chrome Mobile 86.0|Android 5.1 用户

可以考虑国产一个 centos 了

完了，快失业了

薪王烧了这么多年终于烧成余烬了，有请下一位传火人

背靠大公司的系统都有可能会有这种遭遇，好多服务器又要裸奔了orz。

对不起，我是debian/ubuntu系的

Ubuntu LTS 走起, 最不济也就退回Debian, 从Ubuntu回退到Debian显然比从yum系转过去容易得多. 更何况还有 Mint 这个小可爱.

OS软件化了，利好勤快的和有系统级开发能力的运维团队

银河麒麟请

Rocky Linux，我们还没有输

![](/data/attachment/album/202012/09/105429lxy4nalgmg40lxle.jpg)

12 月 8 日，CentOS 项目[宣布](https://lists.centos.org/pipermail/centos-announce/2020-December/048208.html)，CentOS 8 将于 2021 年底结束，而 CentOS 7 将在其生命周期结束后停止维护。

**换言之，“免费”的 RHEL 以后没有了。**

一直以来，CentOS 就是以“免费的 RHEL 版本”而深得开源社区和运维工程师们的喜爱。[RHEL](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux)（<ruby> 红帽企业 Linux <rp>  （ </rp> <rt>  Red Hat Enterprise Linux </rt> <rp>  ） </rp></ruby>）是红帽公司推出的企业版 Linux ，向以稳定、可靠和高性能著称。但是，RHEL 是红帽公司的商业产品，用户需[订阅](https://access.redhat.com/subscription-value/)红帽公司的商业支持服务才可以使用。而 CentOS 是基于红帽按照开源许可证发布的 RHEL 源代码，并去除了商标等商业信息后重构的版本。从产品特性和使用上来说，CentOS 和 RHEL 几无二致，当然，CentOS 的用户得不到红帽公司的商业支持。

除此以外，CentOS 的发行也比 RHEL 的发行晚得多。除了 CentOS 之外，还有一些也是基于 RHEL 衍生的 Linux 发行版，如 Oracle Linux。

**可以说，在中国有大量的 CentOS 用户和装机量，这和 CentOS 的免费不无关系。**

CentOS 项目本来是一个社区项目，但是后来红帽公司收购了 CentOS 之后，其地位就有些尴尬。红帽公司旗下有着三个主要的 Linux 发行版产品线：一个是 Fedora，作为先行实验版本，会在快速迭代的同时实验各种新的 Linux 功能和特性，稳定成熟后，这些特性会发布到 RHEL 上；另一个是红帽 Linux ，即 RHEL，它是红帽公司的主要 Linux 发行版，相对来说，在特性和新软件包的添加和更新方面更加保守；最后就是 CentOS，就是 RHEL 的自由开源构建版本，但是在 CentOS 被纳入红帽怀抱之后，其只是作为 RHEL 的一个“免费”版本发布，似乎在红帽公司内的定位也一直模糊。

而在去年，CentOS 团队[宣布](/article-11412-1.html)和红帽合作推出了一个新的滚动版 Linux：CentOS Stream。是的，你没看错，是滚动版。按照红帽的说法，这是一个“中游”的发行版，位于 Fedora 和 RHEL 之间。主要的目标是为了形成一个可循环的“彭罗斯三角”，以使社群对 CentOS 的改进可以流回到 RHEL 当中。

或许，从那一刻开始，就注定了 CentOS Linux 终将落幕吧。

在本次公告中，CentOS 项目宣布，“在接下来的一年里，我们将把重点从 CentOS Linux 转移到 CentOS Stream 上。CentOS Linux 8 作为 RHEL 8 的重构版，将在 2021 年底结束。”而尚在计划维护期的 CentOS 7 系列，也将在 2024 年维护期限到达之后停止维护。所以，还在使用 CentOS 作为生产服务环境的运维工程师们，要么考虑购买 RHEL 商业订阅；要么考虑自行根据 RHEL 源代码构建吧——或许也会有一群人重新接过这个重构的工作，发行新的 Linux 发行版吧。

目前使用 CentOS 的服务器，还可以继续在 RHEL 的[计划维护期](https://access.redhat.com/support/policy/updates/errata/#Life_Cycle_Dates)得到支持，见下表：

![Red Hat Enterprise Linux Life Cycle](/data/attachment/album/202012/09/101735ktipbl887wh7dhp7.png)

而 “CentOS Stream 将在该日期之后继续，作为 RHEL 的上游（开发）分支。”也就是说，以后，Fedora 依然是第一个上游，但是在 RHEL 发布新版本之后，CentOS Stream 会在它的基础上滚动更新，并将成熟的更新反哺到 RHEL 当中。

此外，CentOS Stream 也将成为 CentOS 特别兴趣小组（SIG）之间合作的核心，这可以让 CentOS 贡献者社区对 RHEL 的未来有很大的影响力。红帽认为，“将我们的全部投资转移到 CentOS Stream 是进一步推动 Linux 创新的最佳方式。”

当然，在 CentOS Linux 8 结束时，你可以考虑迁移到 CentOS Stream 8，它会像传统的 CentOS Linux 版本一样定期更新。但是，切记，这是一个作为 RHEL 中游的**滚动发行版**，并不太建议你在生产环境中使用。关于这个变化，你还可以参考这个 [FAQ](https://centos.org/distro-faq/)。

不过，像 Facebook 这样的有足够技术力量的大型 IT 公司，已经将其运行着的数百万台服务器迁移（或正在迁移）到一个他们从 CentOS Stream 衍生而出的操作系统上了。红帽也鼓励所有合作伙伴和开发人员不仅仅参与 CentOS Stream，而是开始建立自己的分支。

此外，除了 CentOS Stream 之外，红帽也提供了一系列平台来支持不同的需求：

* Fedora 项目：是 Fedora 操作系统的基础，用于那些希望贡献操作系统创新前沿的人。
* Red Hat Universal Base Image：是一个免费的、可再发行的、面向开发人员的镜像，用于创建容器化的、云原生企业应用。有了它，开发人员可以更轻松地在 RHEL 上和红帽的开放混合云产品组合（包括红帽 OpenShift）中创建经认证的应用。
* RHEL 开发者订阅：是一个免费的、自助支持的开发者订阅，它为应用的开发提供了一个开发/测试环境，在 RHEL 的稳定、更安全和高性能的基础上部署到生产中。

好了，你对这件事怎么看？


8 个让我更有效率的 Git 别名

Summary: 使用别名为你最常用或复杂的 Git 命令创建快捷方式。

使用别名为你最常用或复杂的 Git 命令创建快捷方式。

>
> 使用别名为你最常用或复杂的 Git 命令创建快捷方式。
>
>
>

![](/data/attachment/album/202012/09/202245q50ss5kncqc241sf.jpg)

这篇出色的文章《[改变我使用 Git 工作方式的七个技巧](/article-12894-1.html)》启发了我写下另一个对我在命令行上使用 Git 的经验有重大影响的 Git 特性：别名。

定义 Git 的别名来替代命令有两大好处。

* 它简化了有许多选项的长命令，使它们更短，更容易记住。
* 缩短了经常使用的命令，使你的工作更有效率。

### 如何定义和使用别名

要定义 Git 的别名，请使用 `git config` 命令，加上别名和要替换的命令。例如，要为 `git push` 创建别名 `p`：

```
$ git config --global alias.p 'push'

```

你可以通过将别名作为 `git` 的参数来使用别名，就像其他命令一样：

```
$ git p

```

要查看所有的别名，用 `git config` 列出你的配置：

```
$ git config --global -l
user.name=ricardo
user.email=ricardo@example.com
alias.p=push

```

你也可以用你喜欢的 shell 来定义别名，比如 Bash 或 Zsh。不过，用 Git 定义别名有几个功能是用 shell 无法实现的。首先，它允许你在不同的 shell 中使用别名，而无需额外配置。此外，它还集成了 Git 的自动更正功能，所以当你输入错误的命令时，Git 可以建议你正确的别名。最后，Git 还会将别名保存在用户配置文件中，你可以通过复制一个文件将别名转移到其他机器上。

无论使用哪种方法，定义别名都能改善你使用 Git 的整体体验。更多关于定义 Git 别名的信息，请看《[Git Book](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases)》。

### 8 个有用的 Git 别名

现在你知道如何创建和使用别名了，来看看一些有用的别名。

#### 1、Git 状态

Git 命令行用户经常使用 `status` 命令来查看已更改或未跟踪的文件。默认情况下，这个命令提供了很多行的冗长输出，你可能不想要或不需要。你可以使用一个别名来处理这两个组件。定义别名 `st` 来缩短命令，并使用选项 `-sb` 来输出一个不那么啰嗦的状态和分支信息。

```
$ git config --global alias.st 'status -sb'

```

如果你在一个干净的分支上使用这个别名，你的输出就像这样：

```
$  git st
## master

```

在一个带有已更改和未跟踪文件的分支上使用它，会产生这样的输出：

```
$ git st
## master
 M test2
?? test3

```

#### 2、Git 单行日志

创建一个别名，以单行方式显示你的提交，使输出更紧凑：

```
$ git config --global alias.ll 'log --oneline'

```

使用这个别名可以提供所有提交的简短列表：

```
$ git ll
33559c5 (HEAD -> master) Another commit
17646c1 test1

```

#### 3、Git 的最近一次提交

这将显示你最近一次提交的详细信息。这是扩展了《Git Book》中 [别名](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases) 一章的例子：

```
$ git config --global alias.last 'log -1 HEAD --stat'

```

用它来查看最后的提交：

```
$ git last
commit f3dddcbaabb928f84f45131ea5be88dcf0692783 (HEAD -> branch1)
Author: ricardo <ricardo@example.com>
Date:   Tue Nov 3 00:19:52 2020 +0000

    Commit to branch1

 test2 | 1 +
 test3 | 0
 2 files changed, 1 insertion(+)

```

#### 4、Git 提交

当你对 Git 仓库进行修改时，你会经常使用 `git commit`。使用 `cm` 别名使 `git commit -m` 命令更有效率：

```
$ git config --global alias.cm 'commit -m'

```

因为 Git 别名扩展了命令，所以你可以在执行过程中提供额外的参数：

```
$ git cm "A nice commit message"
[branch1 0baa729] A nice commit message
 1 file changed, 2 insertions(+)

```

#### 5、Git 远程仓库

`git remote -v` 命令列出了所有配置的远程仓库。用别名 `rv` 将其缩短：

```
$ git config --global alias.rv 'remote -v'

```

#### 6、Git 差异

`git diff` 命令可以显示不同提交的文件之间的差异，或者提交和工作树之间的差异。用 `d` 别名来简化它：

```
$ git config --global alias.d 'diff'

```

标准的 `git diff` 命令对小的改动很好用，但对于比较复杂的改动，外部工具如 `vimdiff` 就更有用。创建别名 `dv` 来使用 `vimdiff` 显示差异，并使用 `y` 参数跳过确认提示：

```
$ git config --global alias.dv 'difftool -t vimdiff -y'

```

使用这个别名来显示两个提交之间的 `file1` 差异：

```
$ git dv 33559c5 ca1494d file1

```

![vim-diff results](/data/attachment/album/202012/09/202318c1ddkud88sh2tklh.png "vim-diff results")

#### 7、Git 配置列表

`gl` 别名可以更方便地列出所有用户配置：

```
$ git config --global alias.gl 'config --global -l'

```

现在你可以看到所有定义的别名（和其他配置选项）：

```
$ git gl
user.name=ricardo
user.email=ricardo@example.com
alias.p=push
alias.st=status -sb
alias.ll=log --oneline
alias.last=log -1 HEAD --stat
alias.cm=commit -m
alias.rv=remote -v
alias.d=diff
alias.dv=difftool -t vimdiff -y
alias.gl=config --global -l
alias.se=!git rev-list --all | xargs git grep -F

```

#### 8、搜索提交

Git 别名允许你定义更复杂的别名，比如执行外部 shell 命令，可以在别名前加上 `!` 字符。你可以用它来执行自定义脚本或更复杂的命令，包括 shell 管道。

例如，定义 `se` 别名来搜索你的提交：

```
$ git config --global alias.se '!git rev-list --all | xargs git grep -F'

```

使用这个别名来搜索提交中的特定字符串：

```
$ git se test2
0baa729c1d683201d0500b0e2f9c408df8f9a366:file1:test2
ca1494dd06633f08519ec43b57e25c30b1c78b32:file1:test2

```

### 自动更正你的别名

使用 Git 别名的一个很酷的好处是它与自动更正功能的原生集成。如果你犯了错误，默认情况下，Git 会建议使用与你输入的命令相似的命令，包括别名。例如，如果你把 `status` 打成了 `ts`，而不是 `st`，Git 会推荐正确的别名：

```
$ git ts
git: 'ts' is not a git command. See 'git --help'.

The most similar command is
        st

```

如果你启用了自动更正功能，Git 会自动执行正确的命令：

```
$ git config --global help.autocorrect 20
$ git ts
WARNING: You called a Git command named 'ts', which does not exist.
Continuing in 2.0 seconds, assuming that you meant 'st'.
## branch1
?? test4

```

### 优化 Git 命令

Git 别名是一个很有用的功能，它可以优化常见的重复性命令的执行，从而提高你的效率。Git 允许你定义任意数量的别名，有些用户会定义很多别名。我更喜欢只为最常用的命令定义别名 —— 定义太多别名会让人难以记忆，而且可能需要查找才能使用。

更多关于别名的内容，包括其他有用的内容，请参见 [Git 维基的别名页面](https://git.wiki.kernel.org/index.php/Aliases)。

---

via: <https://opensource.com/article/20/11/git-aliases>

作者：[Ricardo Gerardi](https://opensource.com/users/rgerardi) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Zotero：一款帮助你收集和分享研究成果的开源应用

>
> Zotero 是一款令人印象深刻的自由开源的应用，它让你可以收集、组织、引用和共享研究成果。你还可以使用 Zotero 为你的文档即时创建参考文献和书目。
>
>
>

![](/data/attachment/album/202012/09/213010i6o78b6y5gifyjtf.jpg)

通常，你可以[使用 Linux 上任何一款笔记应用](https://itsfoss.com/note-taking-apps-linux/)来收集和分享你的想法。但是，在这里，我想分享一些专门为你量身定做的东西，来帮助你收集、整理和分享你的研究成果，即 [Zotero](https://www.zotero.org/)。

### Zotero：收集、整理和分享研究成果

![](/data/attachment/album/202012/09/214045rirz9m8v5mp5rpvm.png)

Zotero 是一个完全开源的项目，你可以在 [GitHub](https://github.com/zotero/zotero) 上找到它。它的目的是帮助你轻松地收集、整理、添加笔记和分享你的研究成果。

而且，这一切都不需要基于云端的服务，它是完全离线的。所以，你的研究成果是属于你的。当然，除非你出于协作目的想将其同步，为此你可能需要参考[该文档](https://www.zotero.org/support/)。

作为一个好的起点，你可以选择 [WebDAV 存储](https://en.wikipedia.org/wiki/WebDAV)，或者直接创建一个 Zotero 帐户来轻松同步和分享你的研究成果。

例如，我创建了一个名为 `ankush9` 的 Zotero 账户，你可以在 <https://www.zotero.org/ankush9> 找到我的研究合集（我添加到我的出版物中）。

![](/data/attachment/album/202012/09/214056b9o7ccom0camc2zz.jpg)

这使得它很容易分享你组织的研究成果，你可以选择将哪些部分共享到出版物中。

让我着重介绍一下 Zotero 的主要功能，来帮助你决定是否需要尝试一下。

### Zotero 的功能

![](/data/attachment/album/202012/09/214324cmdv2ylln2jdi00y.jpg)

* 能够使用浏览器插件从网页直接添加信息
* 为每份资料添加说明
* 支持添加标签
* 支持添加语音记录
* 添加视频作为附件
* 添加软件作为附件
* 将电子邮件作为附件
* 将播客作为附件
* 添加博客文章
* 添加一个文件链接
* 根据项目建立书目
* 离线快照存储（无需连接互联网即可访问保存的网页）
* 可以复制项目
* 整理库中的项目
* 提供了一个垃圾箱，可以删除你的项目，并在需要时轻松恢复。
* 支持同步
* 支持数据导出
* 可整合 LibreOffice 插件
* 使用你的 Zotero 个人资料链接轻松分享你的研究笔记。
* 跨平台支持

如果你只是想快速创建书目，你可以尝试他们的另一个工具，[ZoteroBib](https://zbib.org/)。

### 在 Linux 上安装 Zotero

![](/data/attachment/album/202012/09/214355as7ka9v3at13kviv.png)

它适用于 Windows、macOS 和 Linux。对于 Linux，如果你使用的是基于 Ubuntu 的发行版（或 Ubuntu 本身），你可以下载一个 deb 文件（由第三方维护）并安装它。

安装 [deb 文件](https://itsfoss.com/install-deb-files-ubuntu/)很简单，它在 Pop OS 20.04 上工作得很好。如果你使用的是其他 Linux 发行版，你可以[解压 tar 包](https://en.wikipedia.org/wiki/Tarball)并进行安装。

你可以按照[官方安装说明](https://www.zotero.org/support/installation)来找到合适的方法。

* [下载 Zotero](https://www.zotero.org/)

### 总结

它有大量的功能，你可以组织、分享、引用和收集资源，以供你进行搜索。由于支持音频、视频、文本和链接，它应该适合几乎所有的东西。

当然，我会将它推荐给有经验的用户，让它发挥最大的作用。而且，如果你之前使用过树状图（思维导图）笔记工具的人，你就知道要做什么了。

你觉得 Zotero 怎么样？如果它不适合你，你有更好的替代品建议么？请在下面的评论中告诉我你的想法。

---

via: <https://itsfoss.com/zotero/>

作者：[Ankush Das](https://itsfoss.com/author/ankush/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


《代码英雄》第三季（5）： 基础设施的影响

>
> 代码英雄讲述了开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。
>
>
>

>
> **什么是《代码英雄》**
>
>
> <ruby> 代码英雄 <rt>  Command Line Heroes </rt></ruby>是世界领先的企业开源软件解决方案供应商红帽（Red Hat）精心制作的原创音频播客，讲述开发人员、程序员、黑客、极客和开源反叛者如何彻底改变技术前景的真实史诗。该音频博客邀请到了谷歌、NASA 等重量级企业的众多技术大牛共同讲述开源、操作系统、容器、DevOps、混合云等发展过程中的动人故事。
>
>
>

![](/data/attachment/album/202012/11/094106a0cbrz2b1cz0c7c0.png)

本文是《[代码英雄](https://www.redhat.com/en/command-line-heroes)》系列播客[《代码英雄》第三季（5）：基础设施的影响](https://www.redhat.com/en/command-line-heroes/season-3/the-infrastructure-effect)的[音频](https://cdn.simplecast.com/audio/a88fbe/a88fbe81-5614-4834-8a78-24c287debbe6/0ea5a208-a01f-46f8-902c-27cf4ffd0e6a/CLH_S3_EP5_The_Infrastructure_Effect_vFINAL_tc.mp3)脚本。

>
> 导语：用在 IT 基础设施中的语言是没有有效期的。COBOL 已经存在了 60 年 —— 而且不会很快消失。我们为大型机维护了数十亿行经典代码。但我们也在用 Go 等语言为云构建新的基础设施。
>
>
> COBOL 是计算机的一次巨大飞跃，让各行各业变得更加高效。Chris Short 介绍了学习 COBOL 是如何被视为安全的长期投注的。60 年后的今天，还有数十亿行并不容易被替换掉的 COBOL 代码 —— 懂这门语言的专家也很少。Ritika Trikha 解释说，有些事情必须改变。要么更多的人必须学习 COBOL，要么依赖 COBOL 的行业必须更新他们的代码库。这两个选择都很困难。但未来并不是用 COBOL 编写的。今天的 IT 基础架构是在云端构建的，其中很多是用 Go 编写的。Carmen Hernández Andoh 分享了 Go 的设计者是如何想要设计一种更适合云计算的语言。Kelsey Hightower 指出，语言通常都是超专注于一种任务。但它们正变得越来越开放和灵活。
>
>
>

**00:00:00 - Saron Yitbarek**：

1904 年，纽约市地铁首次开始运营时，它被惊叹为现代的一个奇迹。但是……当今天的通勤者仍依赖一个多世纪前设计的基础设施时，会发生什么？列车挤满了人，而且常常晚点。纽约每年有 20 亿人次地铁出行，再也没有人为此感到惊叹了。我们还在依赖昨日的过时基础设施，我们必须找到新的好办法，让它发挥作用。

**00:00:44**：

过去，基础设施项目通常是些可见的大而具体的事物，例如地铁。而且由于这种物理可见性，它们损坏时也显而易见。高速公路开裂、电线杆倒下，我们很清楚这些东西何时需要维修。为了使我们的生活与老化的基础设施保持协调，大量的工作是必不可少的。

**00:01:12**：

但是事物并不总是那么一是一、二是二。如今，我们还拥有 IT 基础设施，在偏僻地区嗡嗡作响的服务器农场，跨越海洋的光纤电缆，还有软件基础设施。而像遗留的操作系统或没人敢替换的 shell 脚本，这些 IT 基础设施变得陈旧和破旧时，我们是无法看出的。但是，造就了今日发展的基础设施却正在老化，就像旧的地铁轨道一样。这可能会扰乱我们的现代生活。如今命令行英雄们正努力确保我们不会被过去束缚，因此出现了大量新的挑战。

**00:02:02**：

这是我们第三季进入编程语言世界探索的第 5 期。我们将研究两种编程语言，它们与最初设计的目标基础设施密切相关。COBOL 是一种大型机的原生语言，而 Go 是云计算的原生语言。它们都深受其起源的影响。理解这一点可能会让明天的开发者不至于像纽约人一样被塞进宾夕法尼亚州的车站。

**00:02:33**：

我是 Saron Yitbarek，这里是红帽的原创播客，《命令行英雄》的第三季。

>
> **00:02:43 - <ruby> 格蕾丝·赫柏 <rt>  Grace Hopper </rt></ruby>**：
>
>
> 我们面前有很多事情需要去做，但是我们首先需要大量相关的且易于访问的信息。我们才刚刚开始。
>
>
>

**00:02:53 - Saron Yitbarek**：

海军上将<ruby> 格蕾丝·赫柏 <rt>  Grace Hopper </rt> 在 20 世纪 40、50 年代率先开发了高级编程语言。而她之所以能够实现这种巨大的飞跃，是因为当时的基础设施，大型计算机。</ruby>

**00:03:08 - Chris Short**：

嗨，我叫 Chris Short。

**00:03:10 - Saron Yitbarek**：

Chris 是红帽的首席产品营销经理，而且他也是一位历史爱好者。

**00:03:17 - Chris Short**：

上世纪 40 年代的赫柏上将创造了 FLOW-MATIC，这在当时是革命性的，她被广泛认为是 COBOL 的祖母。因此，她能够坐在那里说：“嘿，只需将其放在大型机上”，或“嘿，只需将其存储在大型机上”即可。

**00:03:31 - Saron Yitbarek**：

这是一个重大的游戏规则改变。突然，你有了这种机器无关的语言，即 COBOL，它是大型机环境特有的。可能性开始逐步打开。

**00:03:42 - Chris Short**：

大型机和 COBOL 真正使得每个组织能够说，它们不再需要充满了带着铅笔、纸、计算器和滑尺的人的办公室，他们可能只需要半个办公室来安装大型机。然后，他们可以雇人用 COBOL 来编写一些应用程序来完成整个财务团队做的所有的数学、逻辑运算以及账目。因此，你需要的财务团队人数少了，仅仅是因为更多的输入可以被数字化，而不是全手动操作。

**00:04:17 - Saron Yitbarek**：

如果你是那些新来的 COBOL 程序员之一，你会觉得你有了一份终身的工作。因为你的工作所基于的基础设施 —— 所有那些大型机 —— 始终会在那里。

**00:04:30 - Chris Short**：

那时侯摩尔定律还未出现，所以你可以整整十年都在同一个大型机上工作，对吧？就像你不用去考虑下一个操作系统，或者下一个类型的容器编排器，又或者下一个出现 AI 之类的东西一样。你可能会整个职业生涯都在从事 COBOL。而且你知道自己的生活将会非常稳定。

**00:04:55 - Saron Yitbarek**：

但是，摩尔定律最终还是来了。新的基础设施也出现了。现如今，程序员不太可能去学习一种半个世纪前的旧语言。但实际上，那些老旧的大型机其实并没有消失。这意味着我们对 COBOL 开发人员的需求也没有消失。

**00:05:17 - Chris Short**：

寻找 COBOL 开发者变得越来越困难。最终会发生的事情是这些大型机可能已经存在了 50 年。这些仍然可以编写出色 COBOL 程序的开发人员将获得巨额收入，以帮助项目运行并完成大型机中的数据重组。而且，该技能肯定会绝迹，并且正在成为一个利润丰厚的职业领域，如果你……现在写 COBOL 绝对可以赚很多钱。

**00:05:49 - Saron Yitbarek**：

尤其是在制造业和金融业。你无法超越几十年前建立的所有基础设施。遗留代码遍及全球。忽略这些老旧的基础设施及其相关的语言，将是一个巨大的错误。

**00:06:08 - Chris Short**：

有两千亿行代码摆在那里，要重构这些代码真的很难。不，我不认为在有生之年我们会看到它消失，真的。

**00:06:21 - Saron Yitbarek**：

Chris Short 是红帽的首席产品营销经理。

**00:06:28**：

我想花一秒钟解释一下 Chris 的观点。你想想看，95% 的 ATM 交易中都有 COBOL 代码，那就是我们与这种语言的联系。但是，COBOL 程序员的平均年龄并不比该语言年轻多少。他们 45 岁，或许 55岁。新人们并不感兴趣这门语言。这就是为什么我想向你介绍一个人。

**00:06:56 - Ritika Trikha**：

嘿，我是 Ritika Trikha。

**00:06:59 - Saron Yitbarek**：

Ritika 是一名技术编辑，曾在 HackerRank 工作。她对 COBOL 的这个问题着迷：人们认为 COBOL 是后大型机时代无意义的残留品。

**00:07:12 - Ritika Trikha**：

如今的开发人员根本不会考虑 COBOL 了，见也没见过，想也没想过。

**00:07:17 - Saron Yitbarek**：

但这可能是灾难的根源。

**00:07:21 - Ritika Trikha**：

如今，仍然有大量的 COBOL 代码在驱动企业的业务。每年至少新增 15 亿行 COBOL 新代码。我认为当你看特定行业时，真的很有意思。就像美国国税局有 5000 万行代码。社会保障局有 6000 万行代码。 因此，这些单位和实体正在处理一些如今最敏感、重要的信息，如果我们不继续为这些大型机提供支持和维护，就会造成很大的破坏。

**00:08:04 - Saron Yitbarek**：

因此，如果我们无法摆脱旧的基础设施，又无法挥舞魔杖来重建整个大型机业务，我们该怎么办？编码人员有时候仅考虑未来，该如何接受过去？我们首先需要直面该问题。

**00:08:25 - Ritika Trikha**：

你知道，年轻一代将不得不重拾这些技能。或者，必须对这些大型机进行某种现代化改造。无论是哪种方式，这个问题都不会消失。这就是为什么 COBOL 还活着的原因。

**00:08:35 - Saron Yitbarek**：

这并不容易。 Ritika 认为我们已经忽略这个问题太长时间了。

**00:08:42 - Ritika Trikha**：

这非常昂贵、艰巨，并且替换数十亿行 COBOL 代码的风险也非常高。它是用于关键任务的代码，比如社会保障和金融信息。COBOL 是专门为此类大量交易而设计的。因此，它由格蕾丝·赫柏在 60 年代为商业交易而设计。自上世纪 60 年代以来，一直存在“如果没坏，为什么要修复它”的说法，现在我们处于这样一个关头，即延续了数十年的大量的高价值数据运行在 COBOL 上。

**00:09:22 - Saron Yitbarek**：

从某种意义上说， Ritika 在呼吁一种文化的转变。改变对 "进 "与 "退 "的态度。由于发展的世界慢慢有了越来越久的历史，我们会更加地接触到自己的历史。你无法摆脱老化的基础设施。这意味着你也不能忽略编程语言的历史。

**00:09:47 - Ritika Trikha**：

有些事情必须得做。当我在 HackerRank 时，我亲眼看到了多少银行和金融机构对 COBOL 开发人员的伤害，几乎是绝望的。这不是一个会被解决的问题，我认为要么必须有某种现代化的系统，要么我们继续培训人员并激励他们。我个人认为将会有 COBOL 再次出现的一天。真的，当所有拥有 COBOL 知识的开发人员退休，并且没有新一代的开发人员学 COBOL 时，将会发生什么？总得做点什么，对吧？所以，当从 COBOL 转向新的基于云的基础设施时，需要有更多的系统化和制度化的改变。

**00:10:37 - Saron Yitbarek**：

Ritika Trikha 是一名旧金山的技术作家。

**00:10:49 - Saron Yitbarek**：

那么 Ritika 提到的那些基于云的基础设施呢？我们今天建立的基础设施是否会将后代绑定到特定的语言，像我们仍绑定找 COBOL 上一样？<ruby> 亚马逊 Web 服务 <rt>  Amazon Web Services </rt></ruby>（AWS）可能是最大的单一云基础设施，于 2006 年推出。<ruby> Google 云平台 <rt>  Google Cloud Platform </rt></ruby>（GCP）于 2008 年问世，微软 Azure 于 2010 年问世。 Go 语言以并发为重点，定位于在新的云基础设施上蓬勃发展。这是这个时代的语言。

**00:11:26 - Carmen Andoh**：

嗨，我叫 Carmen Andoh， 我是谷歌 Go 团队的项目经理。

**00:11:34 - Saron Yitbarek**：

Carmen 对 Go 语言与今天的基础设施有怎样的联系有深入的理解。这要从 Go 的创作者和编程语言历史的紧密联系说起。

**00:11:47 - Carmen Andoh**：

Robert Pike、Robert Griesemer 和 Ken Thompson。这些名字算是从上世纪 60 年代就开始出现了。Ken Thompson 发明了 B 语言，然后他在夏天的假期继续发明 UNIX 操作系统。Rob Pike 发明了字符串编码 UTF-8，他还发明了 ASCII。他帮助 Ken Thompson 共同编写了 UNIX 编程环境。所以，这两个人是很多、很多年前的同事，他们一直在研究和发明用以前的编程语言编写的操作系统，这些语言包括 Ken Thompson 最终帮助 Dennis Ritchie 一起编写的 C 语言。

**00:12:28 - Saron Yitbarek**：

Pike、Griesemer 和 Thompson 在 Google 工作之后，他们发现了一个严重的问题。并没有出现大规模的并发。人们等待了几个小时编译出来。他们使用的是 C++，并且必须得编写所有这些回调和事件调度器。那是在 2009 年，我们的基础设施再次发生了变化。诸如 C++ 之类的语言越来越不适应这种新的现实。

**00:12:59 - Carmen Andoh**：

多核处理器、网络系统、大规模计算集群和 Web 编程模型等正在引入这些问题。而且，还有这个行业的增长，程序员数量在 2010 年就会达到成千上万。因此，直到那时，所有的编程语言都是在规避问题而不是在正面解决问题。

**00:13:24 - Saron Yitbarek**：

最终，将达到一个临界点，必须开始改变。

**00:13:30 - Carmen Andoh**：

嘿，我们讨厌 C++ ，我说：“好吧，让我们看看我们是否能发明些新的东西。”

**00:13:37 - Saron Yitbarek**：

这种新语言需要完美地适应我们最新的基础设施。

**00:13:43 - Carmen Andoh**：

2005 年云技术到来以后，你不再需要自己的计算机，在某种程度上在其他地方租用它，你就可以得到一个分布式系统。但是在分布式系统中，以及在云计算中，存在并发消息传递问题。你需要确保采用异步对你来说没有问题。Go 缺省就是异步的编程语言。基本上，这意味着你执行的每个操作（例如将所有这些不同的消息发送给系统中的另一个计算机）都无需等待另一个机器对你的响应即可完成。因此，它可以在任何给定时间处理多个消息。

**00:14:28 - Carmen Andoh**：

就是说，云计算是分布式的。因此 Go 的开发就是来满足这一确切需求。Go 早就成为进行这种分布式计算的标准方法之一。这就是为什么我认为它立即引起了开发人员的广泛关注。Go 绝对是云基础设施的语言，无论是其设计，还是所有云基础设施工具，以及在过去十年中如雨后春笋般出现的模块的生态。

**00:15:06 - Saron Yitbarek**：

很快，诸如 Kubernetes 之类的关键应用都用 Go 编写了。谷歌还创建了 Go Cloud，这是一个开源库和一系列工具，使得 Go 更具吸引力。很显然，它是新生态系统的语言。它是云的语言。而且，它的创造者们因开发生命力持久的语言而享有声誉，这绝对没有坏处。

**00:15:33 - Carmen Andoh**：

我认为业界的其他人会说：“嘿，我认为这不会很快消失。”这种语言的发明者恰巧也发明了语言有 50 、60 年了。

**00:15:47 - Saron Yitbarek**：

Carmen Andoh 是谷歌 Go 团队的项目经理。

**00:15:54**：

因此，我们有了一种新的语言 Go ，旨在提供云基础设施必需的并发性。听起来不错。Go 的设计师倾向于创造可以持续半个世纪的语言。这也很棒。但是我的问题是，从现在起，50 年后，当 Go 更像是 COBOL 时，这到底意味着什么？当世界上充满了只有老开发人员才能理解的旧版 Go 代码时，这又意味着什么？在当今的云基础设施老化的时候，我们是否会做好准备？我们是否从 COBOL 和大型机领域吸取了教训，可以帮助我们为 Go 和云设计更美好的未来？

**00:16:40**：

幸运的是，我找到了问所有这些问题的合适人选。这就是下面这位。

**00:16:51**：

我们如何使我们的语言能面向未来？我们知道他们与当今的基础设施息息相关。我们也知道，随着数十年的发展，新的基础设施必将取代旧的基础设施。那么，我们今天做些什么以确保将来能平滑演进？

**00:17:10 - Kelsey Hightower**：

我是 Kelsey Hightower ，我在谷歌，是一名开发人员推广大使，我致力于引入开放性技术并将它们应用于谷歌云上的产品。

**00:17:19 - Saron Yitbarek**：

Kelsey 花了大量时间思考编程的未来。我很好奇，是否有一天我们将陷于握有 Go 语言技能的是另一批老龄化的程序员的问题，就像我们现在缺少 COBOL 的引导一样。我们是否在为这个长远的未来做计划？因此，我和 Kelsey 坐下来进行讨论。

**00:17:42 - Kelsey Hightower**：

...等等。但是，如果你考虑到今天面临的一些新的挑战，如应对互联网，这种网络，你将面临许多用户，成千上万的并发用户，以及不同的机器和架构类型的组合。考虑到这些新的场景，因此你通常希望有一种新的语言来解决。例如， JavaScript 是用于 Web 的，你不会想改造 COBOL 以便可以用它来进行 Web 编程。最终，我们今天已经有了数百种相当完善的语言，而且它们都非常专注于他们的优势。

**00:18:15 - Saron Yitbarek**：

那么，在那种情况下，我们是否需要积极推动人们走向 COBOL ？如果我们正在为这些新问题开发新语言，并且它们是高度定制化的，而 COBOL 仍在坚持不谢幕，我们是否需要鼓励人们选择它，以便我们可以维护我们的旧代码？

**00:18:32 - Kelsey Hightower**：

好吧，我认为这将对企业是个挑战吧？所以，你已经在 COBOL 上投入了 10 到 20 年，没有人会主动想学习一些新的 COBOL。或者你不会像刚从大学毕业那么“我要加倍努力……”。

**00:18:45 - Saron Yitbarek**：

没错。

**00:18:46 - Kelsey Hightower**：

“...这种语言比我父母的年龄都大。” 因此，在那个领域，你必须问自己，继续使用 COBOL 的风险是什么？未来是否仍然有意义？我认为它仍然有益于某些类型的工作任务，但是我们必须问自己一个问题，是时候推进了吗？是时候进化一点了吗？因此，如果你仍然有数十亿行的 COBOL 代码，那么你将必须寻找所有剩余的 COBOL 人才，并将其招进来，但也许我们该开始考虑其他语言能从 COBOL 学习些什么，并将某些功能和库加入到其他语言中。

**00:19:26 - Saron Yitbarek**：

COBOL 终止以后的日子，将会是一个巨大的基础设施项目。用我对纽约地铁的比喻，就像是要替换每条地下隧道。因此，展望未来，我想知道我们是否可以预见到这些问题，甚至将来对自己也能有所帮助。

**00:19:48**：

如果我们将今天的云计算与大型机进行比较，我们是否会在最终到达同一条船上，有着这些旧代码库，使用着旧的但非常稳定的语言，而且我们也到了必须做出选择的时候，我们应该继续前进还是保持不变？

**00:20:05 - Kelsey Hightower**：

云有点不同的是它不是来自一个制造商，对吗？许多云提供商通常提供了一系列技术集合，你就可以选择编程语言、编程范式，无论你是要事件驱动还是基于 HTTP 的全 Web 服务。这意味着你可以选择编程的方式，然后只需专注于要解决的问题。因此，数据进进出出，但是你来选择处理数据的方式。

**00:20:36**：

大型机通常只有一个主界面，对吗？就像你编写一份任务一样，这就是你提交任务的方式，这就是你监控任务的方式，这就是结果。这本身就是一个限制。如果你考虑一些较新的大型机，它们也会支持些较新的技术，因此即使在大型机领域，你也会开始看到可用于运行任务的编程语言扩展。

**00:20:58**：

那么我们开始问自己，好吧，既然我有了新的选项，该什么时候离开这种特定的编程范式继续前进呢？我认为我们不会陷入困境。

**00:21:08 - Saron Yitbarek**：

正确。

**00:21:08 - Kelsey Hightower**：

我认为新的分布式机器很不错，可能起步成本更低，你不必购买整个大型机即可开工。但是我们仍然希望易用性和之前一样：给你我的工作，你为我运行它，完成后告诉我。

**00:21:24 - Saron Yitbarek**：

绝对是这样，你觉得发生的事情，或者说 COBOL 所发生的事情，会发生在今天的任何一种语言上吗？ 以 Go 语言做例子，你看到我们在努力地改进 Go 从而吸引人们在 30 年后还想用 Go ？

**00:21:38 - Kelsey Hightower**：

我认为所有语言都会遭受这种命运吧？如果你仔细想一下，其实 Python 已经存在很长时间了。我想差不多 20 年了，甚至更久。因此，我认为会 …… Python 重新流行起来了，它现在是机器学习的基础语言。

**00:21:53 - Saron Yitbarek**：

是的。

**00:21:54 - Kelsey Hightower**：

对于 Tensorflow 之类的库，如果我们仅用时间来衡量，我认为这可能不是看待它的正确方式。还应该有社区是否活跃？语言的适配意愿是否活跃？我认为 Python 做得确实非常出色……社区看到了使其他语言更易于使用的能力。例如，Tensorflow 底层有很多 C++ ，使用这种语言编程可能没有 Python 这样的用户友好性。你可以用 Python，并用它来生成人们正在使用的一些东西，例如 Tensorflow 。现在机器学习非常热门，人们将 Python 引入了这个新领域，那么你猜怎么着？ Python 仍然是活跃的，并且在未来的一段时间内都是活跃的。对于 Go 来说，这同样适用。如果 Go 能够继续保持活跃度，那么，它就像许多基础设施工具和许多云库的基层一样，它也将保持活跃。因此，我认为都是这些社区确保了它们将来占有一席之地，并且当未来出现时，确保那里仍有它们的位置。

**00:22:58 - Saron Yitbarek**：

是的。那么，我们如何让我们的语言面向未来呢？就是说，我们如何有意地设计一种语言，使其能持续存在，并在 20、30 年内都保持活跃呢？

**00:23:10 - Kelsey Hightower**：

使用语言的人，我认为这在开源世界中确实是独一无二的。现在，我们已经不再使用商业语言了，对吧，过去曾经来自微软的语言或太阳微系统的如 Java™ ，那时侯，每个人都依赖于供应商来尽心尽力来对语言能干什么以及对运行时环境进行新的改进。现在，我们看到的诸如 Go、Node.js、Ruby 之类的东西，所有这些都是社区支持的，并且社区专注于运行时环境和语言。这样任何人都可以添加新库，对吧？有一个新的 HTTP 规范，对，HTTP/2 几年前问世了，每个社区都有贡献者添加了那些特定的库，猜猜现在怎么样？所有现在这些语言，都兼容于大部分的未来网站。

**00:24:01**：

我认为现在是个人真正地拥有了更多的控制权，如果他们想让语言适用于新的用例，只需要自己贡献即可。因此，我们不再受限于一两家公司。如果公司倒闭，那么运行时环境可能会因此而消亡。我们不再有这个问题了。

**00:24:23 - Saron Yitbarek**：

我们之前在这个播客上已经说过了。未来是开放的。但是，令人着迷的是考虑怎样能做到再过几十年，过去也将是开放的。它们将继承能够变形和演进的基础设施和语言。

**00:24:39 - Kelsey Hightower**：

太棒了，感谢你的加入，我期待人们的工作，而且大型机仍然有意义。它们是经典技术，因此我们不称其为遗产。

**00:24:47 - Saron Yitbarek**：

哦，我喜欢，经典，非常好。

**00:24:51**：

Kelsey Hightower 是 Google 的开发者推广大使。

**00:24:57**：

我正在想象一个充满经典编程语言以及尚未诞生的新语言的未来。那是我为之兴奋的未来。

**00:25:07 - 演讲者**：

请离关着的门远一点。

**00:25:12 - Saron Yitbarek**：

要知道，2017 年 Andrew Cuomo 州长宣布纽约市地铁进入紧急状态。他的政府拨出 90 亿美元投资于老化的基础设施。这应该提醒我们，迟早我们得注意遗留的系统。你不仅需要继续前进，面向未来。你还背着历史包袱。

**00:25:37**：

在开发的世界中，我们倾向于偏向未来。我们认为我们的语言仅在它们流行时才有用。但是，随着信息基础架构的不断老化，开发的历史变得越来越真实。事实证明，过去根本没有过去。记住这一点是我们的工作。

**00:26:05**：

你可以前往 [redhat.com/commandlineheroes](http://redhat.com/commandlineheroes) ，以了解有关 COBOL 或 Go 或本季我们要介绍的其他语言的更多信息。那里有很多很棒的材料在等你。

**00:26:19 - Saron Yitbarek**：

下一集是关于 Bash 的。我们将探索 shell 脚本的起源以及自动化的关键。

**00:26:30 - Saron Yitbarek**：

《命令行英雄》是红帽的原创播客。我是 Saron Yitbarek 。下期之前，编码不止。

>
> **什么是 LCTT SIG 和 LCTT LCRH SIG**
>
>
> LCTT SIG 是 LCTT <ruby> 特别兴趣小组 <rt>  Special Interest Group </rt></ruby>，LCTT SIG 是针对特定领域、特定内容的翻译小组，翻译组成员将遵循 LCTT 流程和规范，参与翻译，并获得相应的奖励。LCRH SIG 是 LCTT 联合红帽（Red Hat）发起的 SIG，当前专注任务是《代码英雄》系列播客的脚本汉化，已有数十位贡献者加入。敬请每周三、周五期待经过我们精心翻译、校对和发布的译文。
>
>
> 欢迎[加入 LCRH SIG](/article-12436-1.html) 一同参与贡献，并领取红帽（Red Hat）和我们联合颁发的专属贡献者证书。
>
>
>

---

via: <https://www.redhat.com/en/command-line-heroes/season-3/the-infrastructure-effect>

作者：[Red Hat](https://www.redhat.com/en/command-line-heroes) 选题：[bestony](https://github.com/bestony) 译者：[messon007](https://github.com/messon007) 校对：[wxy](https://github.com/wxy)

本文由 [LCRH](https://github.com/LCTT/LCRH) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


跟踪多个 Git 远程仓库

Summary: 拥有一致的命名标准是保持本地和上游 Git 仓库保持一致的关键。

拥有一致的命名标准是保持本地和上游 Git 仓库保持一致的关键。

>
> 拥有一致的命名标准是保持本地和上游 Git 仓库保持一致的关键。
>
>
>

![](/data/attachment/album/202012/11/220828tjt9qlpmg1opvibq.jpg)

当本地 Git 仓库的命名与远程仓库不一致时，与远程仓库协作就会变得很混乱。

解决此问题的一个方法是标准化两个词的使用和含义：`origin` 指的是你个人的 `example.com/<USER>/*` 仓库，而 `upstream` 指的是你从 `origin` 仓库<ruby> 复刻 <rt>  fork </rt></ruby>出来的 `example.com` 仓库。换句话说，`upstream` 指的是公开提交工作的上游仓库，而 `origin` 指的是你对上游仓库的本地复刻，例如，你从这里生成<ruby> 拉取请求 <rt>  pull request </rt></ruby>（PR）。

以 [pbench](https://github.com/distributed-system-analysis/pbench) 仓库为例，下面是一个逐步建立新的本地克隆的方法，其中 `origin` 和 `upstream` 的定义是一致的。

1、在大多数 Git 托管服务上，当你想在上面工作时，必须对它进行复刻。当你运行自己的 Git 服务器时，这并不是必要的，但对于一个公开的代码库来说，这是一个在贡献者之间传输差异的简单方法。

创建一个 Git 仓库的复刻。在这个例子中，假设你的复刻位于 `example.com/<USER>/pbench`。

2、接下来，你必须获得一个统一资源标识符 （[URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)），以便通过 SSH 进行<ruby> 克隆 <rt>  cloning </rt></ruby>。在大多数 Git 托管服务上，比如 GitLab 或 GitHub，它在一个标有 “Clone” 或 “Clone over SSH” 的按钮或面板上，可以将克隆 URI 复制到剪贴板中。

3、在你的开发系统中，使用你复制的 URI 克隆仓库：

```
$ git clone git@example.com:<USER>/pbench.git

```

这将以默认名称 `origin` 来克隆 Git 仓库，作为你的 `pbench` 仓库复刻副本。

4、切换到刚才克隆的目录：

```
$ cd ~/pbench

```

5、下一步，获取源仓库的 SSH URI（你最初复刻的那个）。这可能和上面的方法一样。找到 “Clone” 按钮或面板，复制克隆地址。在软件开发中，这通常被称为“上游”，因为（理论上）这是大多数提交发生的地方，而你打算让这些提交流向下游的仓库。

6、将 URI 添加到你的本地仓库中。是的，将有*两个不同*的远程仓库分配给你的本地仓库副本：

```
$ git remote add upstream git@example.com:bigproject/pbench.git

```

7、现在你有两个命名远程仓库：`origin` 和 `upstream`。 你可以用 `remote` 子命令查看你的远程仓库：

```
$ git remote -v

```

现在，你的本地 `master` 分支正在跟踪 `origin` 的 `master`，这不一定是你想要的。你可能想跟踪这个分支的 `upstream` 版本，因为大多数开发都在上游进行。这个想法是，你要在从上游获得的内容的基础上添加更改。

8、将你的本地的 `master` 分支改成跟踪 `upstream/master`：

```
$ git fetch upstream
$ git branch --set-upstream-to=upstream/master master

```

你可以对任何你想要的分支这样做，而不仅仅是 `master`。例如，有些项目使用 `dev` 分支来处理所有不稳定的变化，而将 `master` 保留给已批准发布的代码。

9、一旦你设置了你的跟踪分支，一定要变基（`rebase`）你的 `master` 分支，使它与上游仓库的任何新变化保持一致：

```
$ git remote update
$ git checkout master
$ git rebase

```

这是一个保持 Git 仓库在不同复刻之间同步的好方法。如果你想自动完成这项工作，请阅读 Seth Kenlon 关于[使用 Ansible 托管 Git 仓库](https://opensource.com/article/19/11/how-host-github-gitlab-ansible)的文章。

---

via: <https://opensource.com/article/20/11/multiple-git-repositories>

作者：[Peter Portante](https://opensource.com/users/portante) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出