Linux 文件系统详解

Summary: 这篇教程将帮你快速了解 Linux 文件系统。

超级棒的文章，已看完+收藏！！

漏了一个`

/dev 目录的条目中漏了一个 ’

这篇教程将帮你快速了解 Linux 文件系统。

# Linux 文件系统详解

>
> 这篇教程将帮你快速了解 Linux 文件系统。
>
>
>

早在 1996 年，在真正理解文件系统的结构之前，我就学会了如何在我崭新的 Linux 上安装软件。这是一个问题，但对程序来说不是大问题，因为即使我不知道实际的可执行文件在哪里，它们也会神奇地工作。问题在于文档。

你知道，那时候，Linux 不是像今天这样直观、用户友好的系统。你必须读很多东西。你必须知道你的 CRT 显示器的扫描频率以及拨号调制解调器的噪音来龙去脉，以及其他数以百计的事情。 我很快就意识到我需要花一些时间来掌握目录的组织方式以及 `/etc`（不是用于“其它”文件），`/usr`（不是用于“用户”文件）和 `/bin` （不是“垃圾桶”）的意思。

本教程将帮助你比我当时更快地了解这些。

### 结构

从终端窗口探索 Linux 文件系统是有道理的，这并不是因为作者是一个脾气暴躁的老人，并且对新孩子和他们漂亮的图形工具不以为然（尽管某些事实如此），而是因为终端，尽管只是文本界面，才是更好地显示 Linux 目录树结构的工具。

事实上，帮助你了解这一切的、应该首先安装的第一个工具的名为：`tree`。如果你正在使用 Ubuntu 或 Debian ，你可以：

```
sudo apt install tree

```

在 Red Hat 或 Fedora :

```
sudo dnf install tree

```

对于 SUSE/openSUSE 可以使用 `zypper`：

```
sudo zypper install tree

```

对于使用 Arch （Manjaro，Antergos，等等）使用：

```
sudo pacman -S tree

```

……等等。

一旦安装好，在终端窗口运行 `tree` 命令：

```
tree /

```

上述指令中的 `/` 指的是根目录。系统中的其他目录都是从根目录分支而出，当你运行 `tree` 命令，并且告诉它从根目录开始，那么你就可以看到整个目录树，系统中的所有目录及其子目录，还有它们的文件。

如果你已经使用你的系统有一段时间了，这可能需要一段时间，因为即使你自己还没有生成很多文件，Linux 系统及其应用程序总是在记录、缓存和存储各种临时文件。文件系统中的条目数量会快速增长。

不过，不要感到不知所措。 相反，试试这个：

```
tree -L 1 /

```

你应该看到如图 1 所示。

*tree*

上面的指令可以翻译为“只显示以 `/`（根目录） 开头的目录树的第一级”。 `-L` 选项告诉树你想看到多少层目录。

大多数 Linux 发行版都会向你显示与你在上图中看到的相同或非常类似的结构。 这意味着，即使你现在感到困惑，掌握这一点，你将掌握大部分（如果不是全部的话）全世界的 Linux 文件系统。

为了让你开始走上掌控之路，让我们看看每个目录的用途。 当我们查看每一个目录的时候，你可以使用 `ls` 来查看他们的内容。

### 目录

从上到下，你所看到的目录如下

#### /bin

`/bin` 目录是包含一些二进制文件的目录，即可以运行的一些应用程序。 你会在这个目录中找到上面提到的 `ls` 程序，以及用于新建和删除文件和目录、移动它们基本工具。还有其它一些程序，等等。文件系统树的其他部分有更多的 *bin* 目录，但我们将在一会儿讨论这些目录。

#### /boot

`/boot` 目录包含启动系统所需的文件。我必须要说吗？ 好吧，我会说：**不要动它**！ 如果你在这里弄乱了其中一个文件，你可能无法运行你的 Linux，修复被破坏的系统是非常痛苦的一件事。 另一方面，不要太担心无意中破坏系统：你必须拥有超级用户权限才能执行此操作。

#### /dev

`/dev` 目录包含设备文件。 其中许多是在启动时或甚至在运行时生成的。 例如，如果你将新的网络摄像头或 USB 随身碟连接到你的机器中，则会自动弹出一个新的设备条目。

#### /etc

`/etc` 的目录名称会让人变得非常的困惑。`/etc` 得名于最早的 Unix 系统们，它的字面意思是 “etcetera”（诸如此类） ，因为它是系统文件管理员不确定在哪里放置的文件的垃圾场。

现在，说 `/etc` 是“<ruby> 要配置的所有内容 <rt>  Everything To Configure </rt></ruby>”更为恰当，因为它包含大部分（如果不是全部的话）的系统配置文件。 例如，包含系统名称、用户及其密码、网络上计算机名称以及硬盘上分区的安装位置和时间的文件都在这里。 再说一遍，如果你是 Linux 的新手，最好是不要在这里接触太多，直到你对系统的工作有更好的理解。

#### /home

`/home` 是你可以找到用户个人目录的地方。在我的情况下，`/home` 下有两个目录：`/home/paul`，其中包含我所有的东西；另外一个目录是 `/home/guest` 目录，以防有客人需要使用我的电脑。

#### /lib

`/lib` 是库文件所在的地方。库是包含应用程序可以使用的代码文件。它们包含应用程序用于在桌面上绘制窗口、控制外围设备或将文件发送到硬盘的代码片段。

在文件系统周围散布着更多的 `lib` 目录，但是这个直接挂载在 `/` 的 `/lib` 目录是特殊的，除此之外，它包含了所有重要的内核模块。 内核模块是使你的显卡、声卡、WiFi、打印机等工作的驱动程序。

#### /media

在 `/media` 目录中，当你插入外部存储器试图访问它时，将自动挂载它。与此列表中的大多数其他项目不同，`/media` 并不追溯到 1970 年代，主要是因为当计算机正在运行而动态地插入和检测存储（U 盘、USB 硬盘、SD 卡、外部 SSD 等)，这是近些年才发生的事。

#### /mnt

然而，`/mnt` 目录是一些过去的残余。这是你手动挂载存储设备或分区的地方。现在不常用了。

#### /opt

`/opt` 目录通常是你编译软件（即，你从源代码构建，并不是从你的系统的软件库中安装软件）的地方。应用程序最终会出现在 `/opt/bin` 目录，库会在 `/opt/lib` 目录中出现。

稍微的题外话：应用程序和库的另一个地方是 `/usr/local`，在这里安装软件时，也会有 `/usr/local/bin` 和 `/usr/local/lib` 目录。开发人员如何配置文件来控制编译和安装过程，这就决定了软件安装到哪个地方。

#### /proc

`/proc`，就像 `/dev` 是一个虚拟目录。它包含有关你的计算机的信息，例如关于你的 CPU 和你的 Linux 系统正在运行的内核的信息。与 `/dev` 一样，文件和目录是在计算机启动或运行时生成的，因为你的系统正在运行且会发生变化。

#### /root

`/root` 是系统的超级用户（也称为“管理员”）的主目录。 它与其他用户的主目录是分开的，**因为你不应该动它**。 所以把自己的东西放在你自己的目录中，伙计们。

#### /run

`/run` 是另一个新出现的目录。系统进程出于自己不可告人的原因使用它来存储临时数据。这是另一个**不要动它**的文件夹。

#### /sbin

`/sbin` 与 `/bin` 类似，但它包含的应用程序只有超级用户（即首字母的 `s` ）才需要。你可以使用 `sudo` 命令使用这些应用程序，该命令暂时允许你在许多 Linux 发行版上拥有超级用户权限。`/sbin` 目录通常包含可以安装、删除和格式化各种东西的工具。你可以想象，如果你使用不当，这些指令中有一些是致命的，所以要小心处理。

#### /usr

`/usr` 目录是在 UNIX 早期用户的主目录所处的地方。然而，正如我们上面看到的，现在 `/home` 是用户保存他们的东西的地方。如今，`/usr` 包含了大量目录，而这些目录又包含了应用程序、库、文档、壁纸、图标和许多其他需要应用程序和服务共享的内容。

你还可以在 `/usr` 目录下找到 `bin`，`sbin`，`lib` 目录，它们与挂载到根目录下的那些有什么区别呢？现在的区别不是很大。在早期，`/bin` 目录（挂载在根目录下的）只会包含一些基本的命令，例如 `ls`、`mv` 和 `rm` ；这是一些在安装系统的时候就会预装的一些命令，用于维护系统的一个基本的命令。 而 `/usr/bin` 目录则包含了用户自己安装和用于工作的软件，例如文字处理器，浏览器和一些其他的软件。

但是许多现代的 Linux 发行版只是把所有的东西都放到 `/usr/bin` 中，并让 `/bin` 指向 `/usr/bin`，以防彻底删除它会破坏某些东西。因此，Debian、Ubuntu 和 Mint 仍然保持 `/bin` 和 `/usr/bin` （和 `/sbin` 和 `/usr/sbin` ）分离；其他的，比如 Arch 和它衍生版，只是有一个“真实”存储二进制程序的目录，`/usr/bin`，其余的任何 `bin` 目录是指向 `/usr/`bin` 的“假”目录。

#### /srv

`/srv` 目录包含服务器的数据。如果你正在 Linux 机器上运行 Web 服务器，你网站的 HTML文件将放到 `/srv/http`（或 `/srv/www`）。 如果你正在运行 FTP 服务器，则你的文件将放到 `/srv/ftp`。

#### /sys

`/sys` 是另一个类似 `/proc` 和 `/dev` 的虚拟目录，它还包含连接到计算机的设备的信息。

在某些情况下，你还可以操纵这些设备。 例如，我可以通过修改存储在 `/sys/devices/pci0000:00/0000:00:02.0/drm/card1/card1-eDP-1/intel_backlight/brightness` 中的值来更改笔记本电脑屏幕的亮度（在你的机器上你可能会有不同的文件）。但要做到这一点，你必须成为超级用户。原因是，与许多其它虚拟目录一样，在 `/sys` 中打乱内容和文件可能是危险的，你可能会破坏系统。直到你确信你知道你在做什么。否则不要动它。

#### /tmp

`/tmp` 包含临时文件，通常由正在运行的应用程序放置。文件和目录通常（并非总是）包含应用程序现在不需要但以后可能需要的数据。

你还可以使用 `/tmp` 来存储你自己的临时文件 —— `/tmp` 是少数挂载到根目录下而你可以在不成为超级用户的情况下与它进行实际交互的目录之一。

#### /var

`/var` 最初被如此命名是因为它的内容被认为是<ruby> 可变的 <rt>  variable </rt></ruby>，因为它经常变化。今天，它有点用词不当，因为还有许多其他目录也包含频繁更改的数据，特别是我们上面看到的虚拟目录。

不管怎样，`/var` 目录包含了放在 `/var/log` 子目录的日志文件之类。日志是记录系统中发生的事件的文件。如果内核中出现了什么问题，它将被记录到 `/var/log` 下的文件中；如果有人试图从外部侵入你的计算机，你的防火墙也将记录尝试。它还包含用于任务的假脱机程序。这些“任务”可以是你发送给共享打印机必须等待执行的任务，因为另一个用户正在打印一个长文档，或者是等待递交给系统上的用户的邮件。

你的系统可能还有一些我们上面没有提到的目录。例如，在屏幕截图中，有一个 `/snap` 目录。这是因为这张截图是在 Ubuntu 系统上截取的。Ubuntu 最近将 [snap](https://www.ubuntu.com/desktop/snappy) 包作为一种分发软件的方式。`/snap` 目录包含所有文件和从 snaps 安装的软件。

### 更深入的研究

这里仅仅谈了根目录，但是许多子目录都指向它们自己的一组文件和子目录。图 2 给出了基本文件系统的总体概念（图片是在 Paul Gardner 的 CC BY-SA 许可下提供的），[Wikipedia 对每个目录的用途进行了总结](https://en.wikipedia.org/wiki/Unix_filesystem#Conventional_directory_layout)。

*图 2：标准 Unix 文件系统*

要自行探索文件系统，请使用 `cd` 命令：`cd`将带你到你所选择的目录（ `cd` 代表更改目录）。

如果你不知道你在哪儿，`pwd`会告诉你，你到底在哪里，（ `pwd` 代表打印工作目录 ），同时 `cd`命令在没有任何选项或者参数的时候，将会直接带你到你自己的主目录，这是一个安全舒适的地方。

最后，`cd ..`将会带你到上一层目录，会使你更加接近根目录，如果你在 `/usr/share/wallpapers` 目录，然后你执行 `cd ..` 命令，你将会跳转到 `/usr/share` 目录

要查看目录里有什么内容，使用 `ls` 或这简单的使用 `l` 列出你所在目录的内容。

当然，你总是可以使用 `tree` 来获得目录中内容的概述。在 `/usr/share` 上试试——里面有很多有趣的东西。

### 总结

尽管 Linux 发行版之间存在细微差别，但它们的文件系统的布局非常相似。 你可以这么说：一旦你了解一个，你就会都了解了。 了解文件系统的最好方法就是探索它。 因此，伴随 `tree` ，`ls` 和 `cd` 进入未知的领域吧。

你不会只是因为查看文件系统就破坏了文件系统，因此请从一个目录移动到另一个目录并进行浏览。 很快你就会发现 Linux 文件系统及其布局的确很有意义，并且你会直观地知道在哪里可以找到应用程序，文档和其他资源。

通过 Linux 基金会和 edX 免费的 “[Linux入门](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)” 课程了解更多有关 Linux 的信息。

---

via: <https://www.linux.com/blog/learn/intro-to-linux/2018/4/linux-filesystem-explained>

作者：[PAUL BROWN](https://www.linux.com/users/bro66) 选题：[lujun9972](https://github.com/lujun9972) 译者：[amwps290](https://github.com/amwps290) 校对：[wxy](https://github.com/wxy)

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


容器基础知识：你需要知道的术语

Summary: 让我们来探讨 Docker 容器世界中使用的一些基本术语吧。

让我们来探讨 Docker 容器世界中使用的一些基本术语吧。

# 容器基础知识：你需要知道的术语

<img src="content_image/album_201807_02_100402fcve3ll4fvzo9aev.jpg" alt="" title="">

[在前一篇文章中](/article-9468-1.html)，我们谈到了<ruby> 容器 <rt>  container </rt></ruby>是什么以及它是如何培育创新并助力企业快速发展的。在以后的文章中，我们将讨论如何使用容器。然而，在深入探讨这个话题之前，我们需要了解关于容器的一些术语和命令。掌握了这些术语，才不至于产生混淆。

让我们来探讨 [Docker](https://www.docker.com/) 容器世界中使用的一些基本术语吧。

<ruby> 容器 <rt>  Container </rt></ruby>：到底什么是容器呢？它是一个 Docker <ruby> 镜像 <rt>  image </rt></ruby>的运行实例。它包含一个 Docker 镜像、执行环境和说明。它与系统完全隔离，所以可以在系统上运行多个容器，并且完全无视对方的存在。你可以从同一镜像中复制出多个容器，并在需求较高时扩展服务，在需求低时对这些容器进行缩减。

Docker <ruby> 镜像 <rt>  Image </rt></ruby>：这与你下载的 Linux 发行版的镜像别无二致。它是一个安装包，包含了用于创建、部署和执行容器的一系列依赖关系和信息。你可以在几秒钟内创建任意数量的完全相同的容器。镜像是分层叠加的。一旦镜像被创建出来，是不能更改的。如果你想对容器进行更改，则只需创建一个新的镜像并从该镜像部署新的容器即可。

<ruby> 仓库 <rt>  Repository </rt></ruby>（repo）：Linux 的用户对于仓库这个术语一定不陌生吧。它是一个软件库，存储了可下载并安装在系统中的软件包。在 Docker 容器中，唯一的区别是它管理的是通过标签分类的 Docker 镜像。你可以找到同一个应用程序的不同版本或不同变体，他们都有适当的标记。

<ruby> 镜像管理服务 <rt>  Registry </rt></ruby>：可以将其想象成 GitHub。这是一个在线服务，管理并提供了对 Docker 镜像仓库的访问，例如默认的公共镜像仓库——DockerHub。供应商可以将他们的镜像库上传到 DockerHub 上，以便他们的客户下载和使用官方镜像。一些公司为他们的镜像提供自己的服务。镜像管理服务不必由第三方机构来运行和管理。组织机构可以使用预置的服务来管理内部范围的镜像库访问。

<ruby> 标签 <rt>  Tag </rt></ruby>：当你创建 Docker 镜像时，可以给它添加一个合适的标签，以便轻松识别不同的变体或版本。这与你在任何软件包中看到的并无区别。Docker 镜像在添加到镜像仓库时被标记。

现在你已经掌握了基本知识，下一个阶段是理解实际使用 Docker 容器时用到的术语。

**Dockerfile** ：这是一个文本文件，包含为了为构建 Docker 镜像需手动执行的命令。Docker 使用这些指令自动构建镜像。

<ruby> 构建 <rt>  Build </rt></ruby>：这是从 Dockerfile 创建成镜像的过程。

<ruby> 推送 <rt>  Push </rt></ruby>：一旦镜像创建完成，“push” 是将镜像发布到仓库的过程。该术语也是我们下一篇文章要学习的命令之一。

<ruby> 拉取 <rt>  Pull </rt></ruby>：用户可以通过 “pull” 过程从仓库检索该镜像。

<ruby> 编组 <rt>  Compose </rt></ruby>：复杂的应用程序会包含多个容器。docker-compose 是一个用于运行多容器应用程序的命令行工具。它允许你用单条命令运行一个多容器的应用程序，简化了多容器带来的问题。

### 总结

容器术语的范围很广泛，这里是经常遇到的一些基本术语。下一次当你看到这些术语时，你会确切地知道它们的含义。在下一篇文章中，我们将开始使用 Docker 容器。

---

via: <https://www.linux.com/blog/intro-to-linux/2017/12/container-basics-terms-you-need-know>

作者：[Swapnil Bhartiya](https://www.linux.com/users/arnieswap) 译者：[jessie-pang](https://github.com/jessie-pang) 校对：[wxy](https://github.com/wxy)

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


协同编辑器的历史性清单

Summary: 按时间顺序快速列出主要协同编辑器的演变。

按时间顺序快速列出主要协同编辑器的演变。

# 协同编辑器的历史性清单

按时间顺序快速列出主要协同编辑器的演变。

正如任何这样的清单一样，它必定会在一开始便提到被誉为“<ruby>   所有演示之母  <rt>  the mother of all demos </rt></ruby>”，在这个演示里<ruby>   道格·恩格尔巴特  <rt>  Doug Engelbart </rt></ruby>早在 1968 年就描述了几乎所有软件的详尽清单。这不仅包括协同编辑器，还包括图形、编程和数学编辑器。

一切都始于那个演示，只不过软件的实现跟不上硬件的发展罢了。

>
> 软件发展的速度比硬件提升的速度慢。——沃斯定律
>
>
>

闲话少说，这里是我找到的可圈可点的协同编辑器的清单。我说“可圈可点”的意思是它们具有可圈可点的特征或实现细节。

| 项目 | 日期 | 平台 | 说明 |
| --- | --- | --- | --- |
| [SubEthaEdit](https://www.codingmonkeys.de/subethaedit/) | 2003-2015？ | 仅 Mac | 我能找到的首个协同的、实时的、多光标的编辑器， [有个在 Emacs 上的逆向工程的尝试](https://www.emacswiki.org/emacs/SubEthaEmacs)却没有什么结果。 |
| [DocSynch](http://docsynch.sourceforge.net/) | 2004-2007 | ？ | 建立于 IRC 之上！ |
| [Gobby](https://gobby.github.io/) | 2005 至今 | C，多平台 | 首个开源、稳固可靠的实现。 仍然存在！众所周知 [libinfinoted](http://infinote.0x539.de/libinfinity/API/libinfinity/) 协议很难移植到其他编辑器中（例如： [Rudel](https://www.emacswiki.org/emacs/Rudel) 不能在 Emacs 上实现此协议）。 2017 年 1 月发行的 0.7 版本添加了也许可以改善这种状况的 Python 绑定。 值得注意的插件: 自动保存到磁盘。 |
| [Ethercalc](https://ethercalc.net/) | 2005 至今 | Web，JavaScript | 首个电子表格，随同 [Google Docs](https://en.wikipedia.org/wiki/Google_docs)。 |
| [moonedit](https://web.archive.org/web/20060423192346/http://www.moonedit.com:80/) | 2005-2008？ | ？ | 原网站已关闭。其他用户的光标可见并且会模仿击键的声音。 包括一个计算器和音乐定序器。 |
| [synchroedit](http://www.synchroedit.com/) | 2006-2007 | ？ | 首个 Web 应用。 |
| [Inkscape](http://wiki.inkscape.org/wiki/index.php/WhiteBoard) | 2007-2011 | C++ | 首个具备协同功能的图形编辑器，其背后的“whiteboard” 插件构建于 Jabber 之上，现已停摆。 |
| [Abiword](https://en.wikipedia.org/wiki/AbiWord) | 2008 至今 | C++ | 首个文字处理器。 |
| [Etherpad](http://etherpad.org/) | 2008 至今 | Web | 首款稳定的 Web 应用。 最初在 2008 年被开发时是一款大型 Java 应用，在 2009 年被谷歌收购并开源，然后在 2011 年被用 Node.JS 重写。使用广泛。 |
| [Wave](https://en.wikipedia.org/wiki/Apache_Wave) | 2009-2010 | Web， Java | 在大一统协议的尝试上失败。 |
| [CRDT](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) | 2011 | 特定平台 | 在不同电脑间可靠地复制一个文件的数据结构的标准。 |
| [Operational transform](http://operational-transformation.github.io/) | 2013 | 特定平台 | 与 CRDT 类似，然而确切地说，两者是不同的。 |
| [Floobits](https://floobits.com/) | 2013 至今 | ？ | 商业软件，但有对各种编辑器的开源插件。 |
| [LibreOffice Online](https://wiki.documentfoundation.org/Development/LibreOffice_Online) | 2015至今 | Web | 免费的 Google docs 替代品，现已集成到 [Nextcloud](https://nextcloud.com/collaboraonline/) |
| [HackMD](https://hackmd.io/) | 2015 至今 | ？ | 商业软件，[开源](https://github.com/hackmdio/hackmd)。灵感来自于（已被 Dropbox 收购的) hackpad。 |
| [Cryptpad](https://cryptpad.fr/) | 2016 至今 | Web ? | Xwiki 的副产品。服务器端的加密的、“零知识” 产品。 |
| [Prosemirror](https://prosemirror.net/) | 2016 至今 | Web， Node.JS | “试图架起消除 Markdown 文本编辑和传统的所见即所得编辑器之间隔阂的桥梁。”不是完全意义上的编辑器，而是一种可以用来构建编辑器的工具。 |
| [Qill](https://quilljs.com/) | 2013 至今 | Web， Node.JS | 富文本编辑器，同时也是 JavaScript 编辑器。不确定是否是协同式的。 |
| [Teletype](https://teletype.atom.io/) | 2017 至今 | WebRTC， Node.JS | 为 GitHub 的 [Atom 编辑器](https://atom.io) 引入了“门户”的思路 ，使得访客可以夸多个文档跟踪主人的操作。访问介绍服务器后使用实时通讯的点对点技术（P2P），基于 CRDT。 |
| [Tandem](http://typeintandem.com/) | 2018 至今 | Node.JS？ | Atom、 Vim、Neovim、 Sublime 等的插件。 使用中继来设置基于 CRDT 的 P2P 连接。多亏 Debian 开发者的参与，[可疑证书问题](https://github.com/typeintandem/tandem/issues/131)已被解决，这使它成为很有希望在未来被遵循的标准。 |

### 其他清单

* [Emacs 维基](https://www.emacswiki.org/emacs/CollaborativeEditing)
* [维基百科](https://en.wikipedia.org/wiki/Collaborative_real-time_editor)

---

via: <https://anarc.at/blog/2018-06-26-collaborative-editors-history/>

作者：[Anacr](https://anarc.at) 选题：[lujun9972](https://github.com/lujun9972) 译者：[ZenMoore](https://github.com/ZenMoore) 校对：[wxy](https://github.com/wxy)

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


在开源项目中做出你的第一个贡献

Summary: 这是许多事情的第一步

# 在开源项目中做出你的第一个贡献

>
> 这是许多事情的第一步
>
>
>

有一个普遍的误解，那就是对开源做出贡献是一件很难的事。你可能会想，“有时我甚至不能理解我自己的代码；那我怎么可能理解别人的？”

放轻松。直到去年，我都以为是这样。阅读和理解他人的代码，然后在他们的基础上写上你自己的代码，这是一件令人气馁的任务；但如果有合适的资源，这不像你想象的那么糟。

第一步要做的是选择一个项目。这个决定是可能是一个菜鸟转变成一个老练的开源贡献者的关键一步。

许多对开源感兴趣的业余程序员都被建议从 [Git](https://git-scm.com/) 入手，但这并不是最好的开始方式。Git 是由许多有着多年软件开发经验的超级极客维护的。它是寻找可以做贡献的开源项目的好地方，但对新手并不友好。大多数对 Git 做出贡献的开发者都有足够的经验，他们不需要参考各类资源或文档。在这篇文章里，我将提供一个对新手友好的特性的列表，并且给出一些建议，希望可以使你更轻松地对开源做出贡献。

### 理解产品

在开始贡献之前，你需要理解项目是怎么工作的。为了理解这一点，你需要自己来尝试。如果你发现这个产品很有趣并且有用，它就值得你来做贡献。

初学者常常选择参与贡献那些他们没有使用过的软件。他们会失望，并且最终放弃贡献。如果你没有用过这个软件，你不会理解它是怎么工作的。如果你不理解它是怎么工作的，你怎么能解决 bug 或添加新特性呢？

要记住：尝试它，才能改变它。

### 确认产品的状况

这个项目有多活跃？

如果你向一个暂停维护的项目提交一个<ruby> 拉取请求 <rt>  pull request </rt></ruby>，你的请求可能永远不会被讨论或合并。找找那些活跃的项目，这样你的代码可以得到即时的反馈，你的贡献也就不会被浪费。

这里介绍了怎么确认一个项目是否还是活跃的：

* **贡献者数量：** 一个增加的贡献者数量表明开发者社区乐于接受新的贡献者。
* **<ruby> 提交 <rt>  commit </rt></ruby>频率：** 查看最近的提交时间。如果是一周之内，甚至是一两个月内，这个项目应该是定期维护的。
* **维护者数量：** 维护者的数量越多，你越可能得到指导。
* **聊天室或 IRC 活跃度：** 一个繁忙的聊天室意味着你的问题可以更快得到回复。

### 新手资源

Coala 是一个开源项目的例子。它有自己的教程和文档，让你可以使用它（每一个类和方法）的 API。这个网站还设计了一个有吸引力的界面，让你有阅读的兴趣。

**文档：** 不管哪种水平的开发者都需要可靠的、被很好地维护的文档，来理解项目的细节。找找在 [GitHub](https://github.com/)（或者放在其它位置）或者类似于 [Read the Docs](https://readthedocs.org/) 之类的独立站点上提供了完善文档的项目，这样可以帮助你深入了解代码。

**教程：** 教程会给新手解释如何在项目里添加特性 （然而，你不是在每个项目中都能找到它）。例如，Coala 提供了 [小熊编写指南](http://api.coala.io/en/latest/Developers/Writing_Linter_Bears.html) （进行代码分析的<ruby> 代码格式化 <rt>  linting </rt></ruby>工具的 Python 包装器）。

**分类的<ruby> 讨论点 <rt>  issue </rt></ruby>：** 对刚刚想明白如何选择第一个项目的初学者来说，选择一个讨论点是一个更加困难的任务。标签被设为“难度/低”、“难度/新手”、“利于初学者”，以及“<ruby> 触手可及 <rt>  low-hanging fruit </rt></ruby>”都表明是对新手友好的。

### 其他因素

* **维护者对新的贡献者的态度：** 从我的经验来看，大部分开源贡献者都很乐于帮助他们项目里的新手。然而，当你问问题时，你也有可能遇到一些不太友好的人（甚至可能有点粗鲁）。不要因为这些人失去信心。他们只是因为在比他们经验更丰富的人那儿得不到发泄的机会而已。还有很多其他人愿意提供帮助。
* **审阅过程/机制：** 你的拉取请求将经历几遍你的同伴和有经验的开发者的查看和更改——这就是你学习软件开发最主要的方式。一个具有严格审阅过程的项目使您在编写生产级代码的过程中成长。
* **一个稳健的<ruby> 持续集成 <rt>  continuous integration </rt></ruby>管道：** 开源项目会向新手们介绍持续集成和部署服务。一个稳健的 CI 管道将帮助你学习阅读和理解 CI 日志。它也将带给你处理失败的测试用例和代码覆盖率问题的经验。
* **参加编程项目（例如 [Google Summer Of Code](https://en.wikipedia.org/wiki/Google_Summer_of_Code)）：** 参加组织证明了你乐于对一个项目的长期发展做贡献。他们也会给新手提供一个机会来获得现实世界中的开发经验，从而获得报酬。大多数参加这些项目的组织都欢迎新人加入。

### 7 对新手友好的组织

* [coala (Python)](https://github.com/coala/coala)
* [oppia (Python, Django)](https://github.com/oppia/oppia)
* [DuckDuckGo (Perl, JavaScript)](https://github.com/duckduckgo/)
* [OpenGenus (JavaScript)](https://github.com/OpenGenus/)
* [Kinto (Python, JavaScript)](https://github.com/kinto)
* [FOSSASIA (Python, JavaScript)](https://github.com/fossasia/)
* [Kubernetes (Go)](https://github.com/kubernetes)

### 关于作者

Palash Nigam - 我是一个印度计算机科学专业本科生，十分乐于参与开源软件的开发，我在 GitHub 上花费了大部分的时间。我现在的兴趣包括 web 后端开发，区块链，和 All things python。

---

via: <https://opensource.com/article/18/4/get-started-open-source-project>

作者：[Palash Nigam](https://opensource.com/users/palash25) 译者：[lonaparte](https://github.com/lonaparte) 校对：[wxy](https://github.com/wxy)

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


如何记录你在终端中执行的所有操作

# 如何记录你在终端中执行的所有操作

<img src="content_image/album_201807_03_111838fnoqyctynxwzxdx4.jpg" alt="" title="">

几天前，我们发布了一个解释如何[保存终端中的命令并按需使用](https://www.ostechnix.com/save-commands-terminal-use-demand/)的指南。对于那些不想记忆冗长的 Linux 命令的人来说，这非常有用。今天，在本指南中，我们将看到如何使用 `script` 命令记录你在终端中执行的所有操作。你可能已经在终端中运行了一个命令，或创建了一个目录，或者安装了一个程序。`script` 命令会保存你在终端中执行的任何操作。如果你想知道你几小时或几天前做了什么，那么你可以查看它们。我知道我知道，我们可以使用上/下箭头或 `history` 命令查看以前运行的命令。但是，你无法查看这些命令的输出。而 `script` 命令记录并显示完整的终端会话活动。

`script` 命令会在终端中创建你所做的所有事件的记录。无论你是安装程序，创建目录/文件还是删除文件夹，一切都会被记录下来，包括命令和相应的输出。这个命令对那些想要一份交互式会话拷贝作为作业证明的人有用。无论是学生还是导师，你都可以将所有在终端中执行的操作和所有输出复制一份。

### 在 Linux 中使用 script 命令记录终端中的所有内容

`script` 命令预先安装在大多数现代 Linux 操作系统上。所以，我们不用担心安装。

让我们继续看看如何实时使用它。

运行以下命令启动终端会话记录。

```
$ script -a my_terminal_activities

```

其中，`-a` 标志用于将输出追加到文件（记录）中，并保留以前的内容。上述命令会记录你在终端中执行的所有操作，并将输出追加到名为 `my_terminal_activities` 的文件中，并将其保存在当前工作目录中。

示例输出：

```
Script started, file is my_terminal_activities

```

现在，在终端中运行一些随机的 Linux 命令。

```
$ mkdir ostechnix
$ cd ostechnix/
$ touch hello_world.txt
$ cd ..
$ uname -r

```

运行所有命令后，使用以下命令结束 `script` 命令的会话：

```
$ exit

```

示例输出：

```
exit
Script done, file is my_terminal_activities

```

如你所见，终端活动已存储在名为 `my_terminal_activities` 的文件中，并将其保存在当前工作目录中。

要查看你的终端活动，只需在任何编辑器中打开此文件，或者使用 `cat` 命令直接显示它。

```
$ cat my_terminal_activities

```

示例输出：

```
Script started on Thu 09 Mar 2017 03:33:44 PM IST
[sk@sk]: ~>$ mkdir ostechnix
[sk@sk]: ~>$ cd ostechnix/
[sk@sk]: ~/ostechnix>$ touch hello_world.txt
[sk@sk]: ~/ostechnix>$ cd ..
[sk@sk]: ~>$ uname -r
4.9.11-1-ARCH
[sk@sk]: ~>$ exit
exit

Script done on Thu 09 Mar 2017 03:37:49 PM IST
```

正如你在上面的输出中看到的，`script` 命令记录了我所有的终端活动，包括 `script` 命令的开始和结束时间。真棒，不是吗？使用 `script` 命令的原因不仅仅是记录命令，还有命令的输出。简单地说，脚本命令将记录你在终端上执行的所有操作。

### 结论

就像我说的那样，脚本命令对于想要保留其终端活动记录的学生，教师和 Linux 用户非常有用。尽管有很多 CLI 和 GUI 可用来执行此操作，但 `script` 命令是记录终端会话活动的最简单快捷的方式。

就是这些。希望这有帮助。如果你发现本指南有用，请在你的社交，专业网络上分享，并支持我们。

干杯!

---

via: <https://www.ostechnix.com/record-everything-terminal/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[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/) 荣誉推出


不要再手动合并你的拉取请求（PR）

# 不要再手动合并你的拉取请求（PR）

如果有什么我讨厌的东西，那就是当我知道我可以自动化它们时，但我手动进行了操作。只有我有这种情况么？我觉得不是。

尽管如此，他们每天都有数千名使用 [GitHub](https://github.com) 的开发人员一遍又一遍地做同样的事情：他们点击这个按钮：

这没有任何意义。

不要误解我的意思。合并拉取请求是有意义的。只是每次点击这个该死的按钮是没有意义的。

这样做没有意义因为世界上的每个开发团队在合并拉取请求之前都有一个已知的先决条件列表。这些要求几乎总是相同的，而且这些要求也是如此：

* 是否通过测试？
* 文档是否更新了？
* 这是否遵循我们的代码风格指南？
* 是否有若干位开发人员对此进行审查？

随着此列表变长，合并过程变得更容易出错。 “糟糕，在没有足够的开发人员审查补丁时 John 就点了合并按钮。” 要发出警报么？

在我的团队中，我们就像外面的每一支队伍。我们知道我们将一些代码合并到我们仓库的标准是什么。这就是为什么我们建立一个持续集成系统，每次有人创建一个拉取请求时运行我们的测试。我们还要求代码在获得批准之前由团队的 2 名成员进行审查。

当这些条件全部设定好时，我希望代码被合并。

而不用点击一个按钮。

这正是启动 [Mergify](https://mergify.io) 的原因。

[Mergify](https://mergify.io) 是一个为你按下合并按钮的服务。你可以在仓库的 `.mergify.yml` 中定义规则，当规则满足时，Mergify 将合并该请求。

无需按任何按钮。

随机抽取一个请求，就像这样：

这来自一个小型项目，没有很多持续集成服务，只有 Travis。在这个拉取请求中，一切都是绿色的：其中一个所有者审查了代码，并且测试通过。因此，该代码应该被合并：但是它还在那里挂起这，等待某人有一天按下合并按钮。

使用 [Mergify](https://mergify.io) 后，你只需将 `.mergify.yml` 放在仓库的根目录即可：

```
rules:
  default:
    protection:
      required_status_checks:
        contexts:
          - continuous-integration/travis-ci
      required_pull_request_reviews:
        required_approving_review_count: 1

```

通过这样的配置，[Mergify](https://mergify.io) 可以实现所需的限制，即 Travis 通过，并且至少有一个项目成员审阅了代码。只要这些条件是肯定的，拉取请求就会自动合并。

我们将 [Mergify](https://mergify.io) 构建为 **一个对开源项目免费的服务**。[提供服务的引擎](https://github.com/mergifyio/mergify-engine)也是开源的。

现在去[尝试它](https://mergify.io)，不要让这些拉取请求再挂起哪怕一秒钟。合并它们！

如果你有任何问题，请随时在下面向我们提问或写下评论！并且敬请期待 - 因为 Mergify 还提供了其他一些我迫不及待想要介绍的功能！

---

via: <https://julien.danjou.info/stop-merging-your-pull-request-manually/>

作者：[Julien Danjou](https://julien.danjou.info/author/jd/) 选题：[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/) 荣誉推出


Intel 和 AMD 透露新的处理器设计

# Intel 和 AMD 透露新的处理器设计

>
> Whiskey Lake U 系列和 Amber Lake Y 系列的酷睿芯片将会在今年秋季开始出现在超过 70 款笔记本以及 2 合 1 机型中。
>
>
>

<img src="content_image/album_201807_04_094930tdxid7b0jpejb8j8.jpg" alt="" title="">

根据最近的台北国际电脑展 (Computex 2018) 以及最近其它的消息，处理器成为科技新闻圈中最前沿的话题。Intel 发布了一些公告涉及从新的酷睿处理器到延长电池续航的尖端技术。与此同时，AMD 亮相了第二代 32 核心的高端游戏处理器线程撕裂者（Threadripper）以及一些适合嵌入式的新型号锐龙 Ryzen 处理器。

以上是对 Intel 和 AMD 主要公布产品的快速浏览，针对那些对嵌入式 Linux 开发者最感兴趣的处理器。

### Intel 最新的第八代 CPU 家族

在四月份，Intel 已经宣布量产 10nm 制程的 Cannon Lake 系列酷睿处理器将会延期到 2019 年，这件事引起了人们对摩尔定律最终走上正轨的议论。然而，在 Intel 的 [Computex 展区](https://newsroom.intel.com/editorials/pc-personal-contribution-platform-pushing-boundaries-modern-computers-computex/) 中有着众多让人欣慰的消息。Intel 展示了两款节能的第八代 14nm 酷睿家族产品，同时也是 Intel 首款 5GHz 的设计。

Whiskey Lake U 系列和 Amber Lake Y 系列的酷睿芯片将会在今年秋季开始出现在超过 70 款笔记本以及 2 合 1 机型中。Intel 表示，这些芯片相较于第七代的 Kaby Lake 酷睿系列处理器会带来两倍的性能提升。新的产品家族将会相比于目前出现的搭载 [Coffee Lake](https://www.linux.com/news/elc-openiot/2018/3/hot-chips-face-mwc-and-embedded-world) 芯片的产品更加节能 。

Whiskey Lake 和 Amber Lake 两者将会配备 Intel 高性能千兆 WiFi (Intel 9560 AC)，该网卡同样出现在 [Gemini Lake](http://linuxgizmos.com/intel-launches-gemini-lake-socs-with-gigabit-wifi/) 架构的奔腾银牌和赛扬处理器，随之出现在 Apollo Lake 一代。千兆 WiFi 本质上就是 Intel 将 2×2 MU-MIMO 和 160MHz 信道技术与 802.11ac 结合。

Intel 的 Whiskey Lake 将作为第七代和第八代 Skylake U 系列处理器的继任者，它们现在已经流行于嵌入式设备。Intel 透漏了少量细节，但是 Whiskey Lake 想必将会提供同样的，相对较低的 15W TDP。这与 [Coffee Lake U 系列芯片](http://linuxgizmos.com/intel-coffee-lake-h-series-debuts-in-congatec-and-seco-modules) 也很像，它将会被用于四核以及 Kaby Lake 和 Skylake U 系列的双核芯片。

[PC World](https://www.pcworld.com/article/3278091/components-processors/intel-computex-news-a-28-core-chip-a-5ghz-8086-two-new-architectures-and-more.html) 报导称，Amber Lake Y 系列芯片主要目标定位是 2 合 1 机型。就像双核的 [Kaby Lake Y 系列](http://linuxgizmos.com/more-kaby-lake-chips-arrive-plus-four-nuc-mini-pcs/) 芯片，Amber Lake 将会支持 4.5W TDP。

为了庆祝 Intel 即将到来的 50 周年庆典， 同样也是作为世界上第一款 8086 处理器的 40 周年庆典，Intel 将启动一个限量版，带有一个时钟频率 4GHz 的第八代 [酷睿 i7-8086K](https://newsroom.intel.com/wp-content/uploads/sites/11/2018/06/intel-i7-8086k-launch-fact-sheet.pdf) CPU。 这款 64 位限量版产品将会是第一块拥有 5GHz, 单核睿频加速，并且是首款带有集成显卡的 6 核，12 线程处理器。Intel 将会于 6 月 7 日开始 [赠送](https://game.intel.com/8086sweepstakes/) 8086 块超频酷睿 i7-8086K 芯片。

Intel 也展示了计划于今年年底启动新的高端 Core X 系列拥有高核心和线程数。[AnandTech 预测](https://www.anandtech.com/show/12878/intel-discuss-whiskey-lake-amber-lake-and-cascade-lake) 可能会使用类似于 Xeon 的 Cascade Lake 架构。今年晚些时候，Intel 将会公布新的酷睿 S系列型号，AnandTech 预测它可能会是八核心的 Coffee Lake 芯片。

Intel 也表示第一款疾速傲腾 SSD —— 一个 M.2 接口产品被称作 [905P](https://www.intel.com/content/www/us/en/products/memory-storage/solid-state-drives/gaming-enthusiast-ssds/optane-905p-series.htm) —— 终于可用了。今年来迟的是 Intel XMM 800 系列调制解调器，它支持 Sprint 的 5G 蜂窝技术。Intel 表示 可用于 PC 的 5G 将会在 2019 年出现。

### Intel 承诺笔记本全天候的电池寿命

另一则消息，Intel 表示将会尽快启动一项 Intel 低功耗显示技术，它将会为笔记本设备提供一整天的电池续航。合作开发伙伴 Sharp 和 Innolux 正在使用这项技术在 2018 年晚期开始生产 1W 显示面板，这能节省 LCD 一半的电量消耗。

### AMD 继续翻身

在展会中，AMD 亮相了第二代拥有 32 核 64 线程的线程撕裂者（Threadripper） CPU。为了走在 Intel 尚未命名的 28 核怪兽之前，这款高端游戏处理器将会在第三季度推出。根据 [Engadget](https://www.engadget.com/2018/06/05/amd-threadripper-32-cores/) 的消息，新的线程撕裂者同样采用了被用在锐龙 Ryzen 芯片的 12nm Zen+ 架构。

[WCCFTech](https://wccftech.com/amd-demos-worlds-first-7nm-gpu/) 报导，AMD 也表示它选自 7nm Vega Instinct GPU（为拥有 32GB 昂贵的 HBM2 显存而不是 GDDR5X 或 GDDR6 的显卡而设计）。这款 Vega Instinct 将提供相比现今 14nm Vega GPU 高出 35% 的性能和两倍的功效效率。新的渲染能力将会帮助它同 Nvidia 启用 CUDA 技术的 GPU 在光线追踪中竞争。

一些新的 Ryzen 2000 系列处理器近期出现在一个 ASRock CPU 聊天室，它将拥有比主流的 Ryzen 芯片更低的功耗。[AnandTech](https://www.anandtech.com/show/12841/amd-preps-new-ryzen-2000series-cpus-45w-ryzen-7-2700e-ryzen-5-2600e) 详细介绍了，2.8GHz，8 核心，16 线程的 Ryzen 7 2700E 和 3.4GHz/3.9GHz，六核，12 线程 Ryzen 5 2600E 都将拥有 45W TDP。这比 12-54W TDP 的 [Ryzen Embedded V1000](https://www.linux.com/news/elc-openiot/2018/3/hot-chips-face-mwc-and-embedded-world) 处理器更高，但低于 65W 甚至更高的主流 Ryzen 芯片。新的 Ryzen-E 型号是针对 SFF (外形小巧，small form factor) 和无风扇系统。

在 [开源峰会 + 欧洲嵌入式 Linux 会议](https://events.linuxfoundation.org/events/elc-openiot-europe-2018/) 加入我们，关于 Linux，云，容器，AI，社区等 100 多场会议，爱丁堡，英国，2018 年 10 月 22-24 日。

---

via: <https://www.linux.com/blog/2018/6/intel-amd-and-arm-reveal-new-processor-designs>

作者：[Eric Brown](https://www.linux.com/users/ericstephenbrown) 选题：[lujun9972](https://github.com/lujun9972) 译者：[softpaopao](https://github.com/softpaopao) 校对：[wxy](https://github.com/wxy)

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


云计算的成本

Summary: 两个开发团队的一天

# 云计算的成本

>
> 两个开发团队的一天
>
>
>

几个月以前，我与一些人讨论过关于公共云服务成本与传统专用基础设施价格比较的话题。为给你提供一些见解，我们来跟踪一下一个企业中的两个开发团队  —  并比较他们构建类似服务的方式。

第一个团队将使用传统的专用基础设施来部署他们的应用，而第二个团队将使用 AWS 提供的公共云服务。

这两个团队被要求为一家全球化企业开发一个新的服务，该企业目前为全球数百万消费者提供服务。要开发的这项新服务需要满足以下基本需求：

1. 能够随时**扩展**以满足弹性需求
2. 具备应对数据中心故障的**弹性**
3. 确保数据**安全**以及数据受到保护
4. 为排错提供深入的**调试**功能
5. 项目必须能**迅速分发**
6. 服务构建和维护的**性价比**要高

就新服务来说，这看起来是非常标准的需求 — 从本质上看传统专用基础设备上没有什么东西可以超越公共云了。

#### 1 — 扩展以满足客户需求

当说到可扩展性时，这个新服务需要去满足客户变化无常的需求。我们构建的服务不可以拒绝任何请求，以防让公司遭受损失或者声誉受到影响。

**传统团队**

使用的是专用基础设施，架构体系的计算能力需要与峰值数据需求相匹配。对于负载变化无常的服务来说，大量昂贵的计算能力在低利用率时被浪费掉。

这是一种很浪费的方法  —  并且大量的资本支出会侵蚀掉你的利润。另外，这些未充分利用的庞大的服务器资源的维护也是一项很大的运营成本。这是一项你无法忽略的成本  —  我不得不再强调一下，为支持一个单一服务去维护一机柜的服务器是多么的浪费时间和金钱。

**云团队**

使用的是基于云的自动伸缩解决方案，应用会按需要进行自动扩展和收缩。也就是说你只需要支付你所消费的计算资源的费用。

一个架构良好的基于云的应用可以实现无缝地伸缩 —  并且还是自动进行的。开发团队只需要定义好自动伸缩的资源组即可，即当你的应用 CPU 利用率达到某个高位、或者每秒有多大请求数时启动多少实例，并且你可以根据你的意愿去定制这些规则。

#### 2 — 应对故障的弹性

当说到弹性时，将托管服务的基础设施放在同一个房间里并不是一个好的选择。如果你的应用托管在一个单一的数据中心  —  （不是如果）发生某些失败时（LCTT 译注：指坍塌、地震、洪灾等），你的所有的东西都被埋了。

**传统团队**

满足这种基本需求的标准解决方案是，为实现局部弹性建立至少两个服务器  —  在地理上冗余的数据中心之间实施秒级复制。

开发团队需要一个负载均衡解决方案，以便于在发生饱和或者故障等事件时将流量转向到另一个节点  —  并且还要确保镜像节点之间，整个栈是持续完全同步的。

**云团队**

在 AWS 全球 50 个地区中，他们都提供多个*可用区*。每个区域由多个容错数据中心组成  —  通过自动故障切换功能，AWS 可以将服务无缝地转移到该地区的其它区中。

在一个 `CloudFormation` 模板中定义你的*基础设施即代码*，确保你的基础设施在自动伸缩事件中跨区保持一致 — 而对于流量的流向管理，AWS 负载均衡服务仅需要做很少的配置即可。

#### 3 — 安全和数据保护

安全是一个组织中任何一个系统的基本要求。我想你肯定不想成为那些不幸遭遇安全问题的公司之一的。

**传统团队**

为保证运行他们服务的基础服务器安全，他们不得不持续投入成本。这意味着将需要投资一个团队，以监视和识别安全威胁，并用来自不同数据源的跨多个供应商解决方案打上补丁。

**云团队**

使用公共云并不能免除来自安全方面的责任。云团队仍然需要提高警惕，但是并不需要去担心为底层基础设施打补丁的问题。AWS 将积极地对付各种零日漏洞 — 最近的一次是 Spectre 和 Meltdown。

利用来自 AWS 的身份管理和加密安全服务，可以让云团队专注于他们的应用 —  而不是无差别的安全管理。使用 CloudTrail 对 API 到 AWS 服务的调用做全面审计，可以实现透明地监视。

#### 4 — 监视和日志

任何基础设施和部署为服务的应用都需要严密监视实时数据。团队应该有一个可以访问的仪表板，当超过指标阈值时仪表板会显示警报，并能够在排错时提供与事件相关的日志。

**传统团队**

对于传统基础设施，将不得不在跨不同供应商和“雪花状”的解决方案上配置监视和报告解决方案。配置这些“见鬼的”解决方案将花费你大量的时间和精力 —  并且能够正确地实现你的目的是相当困难的。

对于大多数部署在专用基础设施上的应用来说，为了搞清楚你的应用为什么崩溃，你可以通过搜索保存在你的服务器文件系统上的日志文件来找到答案。为此你的团队需要通过 SSH 进入服务器，导航到日志文件所在的目录，然后浪费大量的时间，通过 `grep` 在成百上千的日志文件中寻找。如果你在一个横跨 60 台服务器上部署的应用中这么做  —  我能负责任地告诉你，这是一个极差的解决方案。

**云团队**

利用原生的 AWS 服务，如 CloudWatch 和 CloudTrail，来做云应用程序的监视是非常容易。不需要很多的配置，开发团队就可以监视部署的服务上的各种指标  —  问题的排除过程也不再是个恶梦了。

对于传统的基础设施，团队需要构建自己的解决方案，配置他们的 REST API 或者服务去推送日志到一个聚合器。而得到这个“开箱即用”的解决方案将对生产力有极大的提升。

#### 5 — 加速开发进程

现在的商业环境中，快速上市的能力越来越重要。由于实施的延误所失去的机会成本，可能成为影响最终利润的一个主要因素。

**传统团队**

对于大多数组织，他们需要在新项目所需要的硬件采购、配置和部署上花费很长的时间 — 并且由于预测能力差，提前获得的额外的性能将造成大量的浪费。

而且还有可能的是，传统的开发团队在无数的“筒仓”中穿梭以及在移交创建的服务上花费数月的时间。项目的每一步都会在数据库、系统、安全、以及网络管理方面需要一个独立工作。

**云团队**

而云团队开发新特性时，拥有大量的随时可投入生产系统的服务套件供你使用。这是开发者的天堂。每个 AWS 服务一般都有非常好的文档并且可以通过你选择的语言以编程的方式去访问。

使用新的云架构，例如无服务器，开发团队可以在最小化冲突的前提下构建和部署一个可扩展的解决方案。比如，只需要几天时间就可以建立一个 [Imgur 的无服务器克隆](https://read.acloud.guru/building-an-imgur-clone-part-2-image-rekognition-and-a-dynamodb-backend-abc9af300123)，它具有图像识别的特性，内置一个产品级的监视/日志解决方案，并且它的弹性极好。

*如何建立一个 Imgur 的无服务器克隆*

如果必须要我亲自去设计弹性和可伸缩性，我可以向你保证，我会陷在这个项目的开发里 — 而且最终的产品将远不如目前的这个好。

从我实践的情况来看，使用无服务器架构的交付时间远小于在大多数公司中提供硬件所花费的时间。我只是简单地将一系列 AWS 服务与 Lambda 功能 — 以及 ta-da 耦合到一起而已！我只专注于开发解决方案，而无差别的可伸缩性和弹性是由 AWS 为我处理的。

#### 关于云计算成本的结论

就弹性而言，云计算团队的按需扩展是当之无愧的赢家 — 因为他们仅为需要的计算能力埋单。而不需要为维护和底层的物理基础设施打补丁付出相应的资源。

云计算也为开发团队提供一个可使用多个可用区的弹性架构、为每个服务构建的安全特性、持续的日志和监视工具、随用随付的服务、以及低成本的加速分发实践。

大多数情况下，云计算的成本要远低于为你的应用运行所需要的购买、支持、维护和设计的按需基础架构的成本 —  并且云计算的麻烦事更少。

通过利用云计算，我们可以更少的先期投入而使业务快速开展。整体而言，当你开发和部署业务服务时，云计算的经济性可以让你的工作更赞。

也有一些云计算比传统基础设施更昂贵的例子，一些情况是在周末忘记关闭运行的一些极其昂贵的测试机器。

[Dropbox 在决定推出自己的基础设施并减少对 AWS 服务的依赖之后，在两年的时间内节省近 7500 万美元的费用，Dropbox…——www.geekwire.com](https://www.geekwire.com/2018/dropbox-saved-almost-75-million-two-years-building-tech-infrastructure/)

即便如此，这样的案例仍然是非常少见的。更不用说当初 Dropbox 也是从 AWS 上开始它的业务的  —  并且当它的业务达到一个临界点时，才决定离开这个平台。即便到现在，他们也已经进入到云计算的领域了，并且还在 AWS 和 GCP 上保留了 40% 的基础设施。

将云服务与基于单一“成本”指标（LCTT 译注：此处的“成本”仅指物理基础设施的购置成本）的传统基础设施比较的想法是极其幼稚的  —  公然无视云为开发团队和你的业务带来的一些主要的优势。

在极少数的情况下，云服务比传统基础设施产生更多的绝对成本  —  但它在开发团队的生产力、速度和创新方面仍然贡献着更好的价值。

*客户才不在乎你的数据中心呢*

*我非常乐意倾听你在云中开发的真实成本相关的经验和反馈！请在下面的评论区、Twitter [@Elliot\_F](https://twitter.com/Elliot_F) 上、或者直接在 [LinkedIn](https://www.linkedin.com/in/elliotforbes/) 上联系我。*

---

via: <https://read.acloud.guru/the-true-cost-of-cloud-a-comparison-of-two-development-teams-edc77d3dc6dc>

作者：[Elliot Forbes](https://read.acloud.guru/@elliot_f?source=post_header_lockup) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


命令行中的世界杯

# 命令行中的世界杯

足球始终在我们身边。即使我们国家的队伍已经出局（LCTT 译注：显然这不是指我们国家，因为我们根本没有入局……），我还是想知道球赛比分。目前， 国际足联世界杯是世界上最大的足球锦标赛，2018 届是由俄罗斯主办的。每届世界杯都有一些足球强国未能取得参赛资格（LCTT 译注：我要吐槽么？）。意大利和荷兰就无缘本次世界杯。但是即使在未参加比赛的国家，追踪关注最新比分也成为了一种仪式。我希望能及时了解这个世界级的重大赛事最新比分的变化，而不用去搜索不同的网站。

如果你很喜欢命令行，那么有更好的方法用一个小型命令行程序追踪最新的世界杯比分和排名。让我们看一看最热门的可用的球赛趋势分析程序之一，它叫作 football-cli。

football-cli 不是一个开创性的应用程序。这几年，有许多命令行工具可以让你了解到最新的球赛比分和赛事排名。例如，我是 soccer-cli （Python 写的）和 App-football （Perl 写的）的重度用户。但我总是在寻找新的趋势分析应用，而 football-cli 在某些方面脱颖而出。

football-cli 是 JavaScript 开发的，由 Manraj Singh 编写，它是开源的软件。基于 MIT 许可证发布，用 npm（JavaScript 包管理器）安装十分简单。那么，让我们直接行动吧！

该应用程序提供了命令以获取过去及现在的赛事得分、查看联赛和球队之前和将要进行的赛事。它也会显示某一特定联赛的排名。有一条指令可以列出程序所支持的不同赛事。我们不妨从最后一个条指令开始。

在 shell 提示符下：

```
luke@ganges:~$ football lists

```

世界杯被列在最下方，我错过了昨天的比赛，所以为了了解比分，我在 shell 提示下输入：

```
luke@ganges:~$ football scores

```

现在，我想看看目前的世界杯小组排名。很简单：

```
luke@ganges:~$ football standings -l WC

```

下面是输出的一个片段：

你们当中眼尖的可能会注意到这里有一个错误。比如比利时看上去领先于 G 组，但这是不正确的，比利时和英格兰（截稿前）在得分上打平。在这种情况下，纪律好的队伍排名更高。英格兰收到两张黄牌，而比利时收到三张，因此，英格兰应当名列榜首。

假设我想知道利物浦 90 天前英超联赛的结果，那么:

```
luke@ganges:~$ football fixtures -l PL -d 90 -t "Liverpool"

```

我发现这个程序非常方便。它用一种清晰、整洁而有吸引力的方式显示分数和排名。当欧洲联赛再次开始时，它就更有用了。（事实上 2018-19 冠军联赛已经在进行中）！

这几个示例让大家对 football-cli 的实用性有了更深的体会。想要了解更多，请转至开发者的 [GitHub 页面](https://github.com/ManrajGrover/football-cli)。足球 ＋ 命令行 ＝ football-cli。

如同许多类似的工具一样，该软件从 football-data.org 获取相关数据。这项服务以机器可读的方式为所有欧洲主要联赛提供数据，包括比赛、球队、球员、结果等等。所有这些信息都是以 JOSN 形式通过一个易于使用的 RESTful API 提供的。

---

via: <https://www.linuxlinks.com/football-cli-world-cup-football-on-the-command-line/>

作者：[Luke Baker](https://www.linuxlinks.com/author/luke-baker/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[ZenMoore](https://github.com/ZenMoore) 校对：[wxy](https://github.com/wxy)

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


3 个 Python 命令行工具

Summary: 用 Click、Docopt 和 Fire 库写你自己的命令行应用。

用 Click、Docopt 和 Fire 库写你自己的命令行应用。

# 3 个 Python 命令行工具

>
> 用 Click、Docopt 和 Fire 库写你自己的命令行应用。
>
>
>

<img src="content_image/album_201807_04_221255bso5csppf0437x8r.jpg" alt="" title="">

有时对于某项工作来说一个命令行工具就足以胜任。命令行工具是一种从你的 shell 或者终端之类的地方交互或运行的程序。[Git](https://git-scm.com/) 和 [Curl](https://curl.haxx.se/) 就是两个你也许已经很熟悉的命令行工具。

当你有一小段代码需要在一行中执行多次或者经常性地被执行，命令行工具就会很有用。Django 开发者执行 `./manage.py runserver` 命令来启动他们的网络服务器；Docker 开发者执行 `docker-compose up` 来启动他们的容器。你想要写一个命令行工具的原因可能和你一开始想写代码的原因有很大不同。

对于这个月的 Python 专栏，我们有 3 个库想介绍给希望为自己编写命令行工具的 Python 使用者。

### Click

[Click](http://click.pocoo.org/5/) 是我们最爱的用来开发命令行工具的 Python 包。其：

* 有一个富含例子的出色文档
* 包含说明如何将命令行工具打包成一个更加易于执行的 Python 应用程序
* 自动生成实用的帮助文本
* 使你能够叠加使用可选和必要参数，甚至是 [多个命令](http://click.pocoo.org/5/commands/)
* 有一个 Django 版本（ [`django-click`](https://github.com/GaretJax/django-click) ）用来编写管理命令

Click 使用 `@click.command()` 去声明一个函数作为命令，同时可以指定必要和可选参数。

```
# hello.py
import click

@click.command()
@click.option('--name', default='', help='Your name')
def say_hello(name):
    click.echo("Hello {}!".format(name))

if __name__ == '__main__':
    say_hello()

```

`@click.option()` 修饰器声明了一个 [可选参数](http://click.pocoo.org/5/options/) ，而 `@click.argument()` 修饰器声明了一个 [必要参数](http://click.pocoo.org/5/arguments/)。你可以通过叠加修饰器来组合可选和必要参数。`echo()` 方法将结果打印到控制台。

```
$ python hello.py --name='Lacey'
Hello Lacey!

```

### Docopt

[Docopt](http://docopt.org/) 是一个命令行工具的解析器，类似于命令行工具的 Markdown。如果你喜欢流畅地编写应用文档，在本文推荐的库中 Docopt 有着最好的格式化帮助文本。它不是我们最爱的命令行工具开发包的原因是它的文档犹如把人扔进深渊，使你开始使用时会有一些小困难。然而，它仍是一个轻量级的、广受欢迎的库，特别是当一个漂亮的说明文档对你来说很重要的时候。

Docopt 对于如何格式化文章开头的 docstring 是很特别的。在工具名称后面的 docsring 中，顶部元素必须是 `Usage:` 并且需要列出你希望命令被调用的方式（比如：自身调用，使用参数等等）。`Usage:` 需要包含 `help` 和 `version` 参数。

docstring 中的第二个元素是 `Options:`，对于在 `Usages:` 中提及的可选项和参数，它应当提供更多的信息。你的 docstring 的内容变成了你帮助文本的内容。

```
"""HELLO CLI

Usage:
    hello.py
    hello.py <name>
    hello.py -h|--help
    hello.py -v|--version

Options:
    <name>  Optional name argument.
    -h --help  Show this screen.
    -v --version  Show version.
"""

from docopt import docopt

def say_hello(name):
    return("Hello {}!".format(name))

if __name__ == '__main__':
    arguments = docopt(__doc__, version='DEMO 1.0')
    if arguments['<name>']:
        print(say_hello(arguments['<name>']))
    else:
        print(arguments)

```

在最基本的层面，Docopt 被设计用来返回你的参数键值对。如果我不指定上述的 `name` 调用上面的命令，我会得到一个字典的返回值：

```
$ python hello.py
{'--help': False,
 '--version': False,
 '<name>': None}

```

这里可看到我没有输入 `help` 和 `version` 标记并且 `name` 参数是 `None`。

但是如果我带着一个 `name` 参数调用，`say_hello` 函数就会执行了。

```
$ python hello.py Jeff
Hello Jeff!

```

Docopt 允许同时指定必要和可选参数，且各自有着不同的语法约定。必要参数需要在 `ALLCAPS` 和 `<carets>` 中展示，而可选参数需要单双横杠显示，就像 `--like`。更多内容可以阅读 Docopt 有关 [patterns](https://github.com/docopt/docopt#usage-pattern-format) 的文档。

### Fire

[Fire](https://github.com/google/python-fire) 是谷歌的一个命令行工具开发库。尤其令人喜欢的是当你的命令需要更多复杂参数或者处理 Python 对象时，它会聪明地尝试解析你的参数类型。

Fire 的 [文档](https://github.com/google/python-fire/blob/master/docs/guide.md) 包括了海量的样例，但是我希望这些文档能被更好地组织。Fire 能够处理 [同一个文件中的多条命令](https://github.com/google/python-fire/blob/master/docs/guide.md#exposing-multiple-commands)、使用 [对象](https://github.com/google/python-fire/blob/master/docs/guide.md#version-3-firefireobject) 的方法作为命令和 [分组](https://github.com/google/python-fire/blob/master/docs/guide.md#grouping-commands) 命令。

它的弱点在于输出到控制台的文档。命令行中的 docstring 不会出现在帮助文本中，并且帮助文本也不一定标识出参数。

```
import fire

def say_hello(name=''):
    return 'Hello {}!'.format(name)

if __name__ == '__main__':
    fire.Fire()

```

参数是必要还是可选取决于你是否在函数或者方法定义中为其指定了一个默认值。要调用命令，你必须指定文件名和函数名，比较类似 Click 的语法：

```
$ python hello.py say_hello Rikki
Hello Rikki!

```

你还可以像标记一样传参，比如 `--name=Rikki`。

### 额外赠送：打包！

Click 包含了使用 `setuptools` [打包](http://click.pocoo.org/5/setuptools/) 命令行工具的使用说明（强烈推荐按照说明操作）。

要打包我们第一个例子中的命令行工具，将以下内容加到你的 `setup.py` 文件里：

```
from setuptools import setup

setup(
    name='hello',
    version='0.1',
    py_modules=['hello'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        hello=hello:say_hello
    ''',
)

```

任何你看见 `hello` 的地方，使用你自己的模块名称替换掉，但是要记得忽略 `.py` 后缀名。将 `say_hello` 替换成你的函数名称。

然后，执行 `pip install --editable` 来使你的命令在命令行中可用。

现在你可以调用你的命令，就像这样：

```
$ hello --name='Jeff'
Hello Jeff!

```

通过打包你的命令，你可以省掉在控制台键入 `python hello.py --name='Jeff'` 这种额外的步骤以减少键盘敲击。这些指令也很可能可在我们提到的其他库中使用。

---

via: <https://opensource.com/article/18/5/3-python-command-line-tools>

作者：[Jeff Triplett](https://opensource.com/users/laceynwilliams)，[Lacey Williams Hensche](https://opensource.com/users/laceynwilliams) 选题：[lujun9972](https://github.com/lujun9972) 译者：[hoppipolla-](https://github.com/hoppipolla-) 校对：[wxy](https://github.com/wxy)

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


红帽 6.28 媒体开放日手记

# 红帽 6.28 媒体开放日手记

在一个炎热的下午我代表 Linux 中国开源社区参加了 6 月 28 日的红帽媒体开放日。以下内容摘录自该活动，有删节。

本次参加红帽开放日的主要官方人员如题图，从左到右分别是：

* Fedora 社区工程师 Adam Samalik
* 红帽资深高级云技术官 Thomas Cameron
* ManageIQ 社区负责人 Carol Chen
* 社区活动经理 Jennifer Madriaga
* Fedora 社区负责人 Brian Exelbierd
* CoreOS 及 Prometheus 社区软件工程师 Max Leonard Inden

以下是问题摘录：

### 问题 1

记者：我想问各位社区成员一个问题，大家本身是社区的负责人或者工程师，同时又有红帽的背景，你们怎么把技术能量转换成价值贡献给社区，又怎么将社区开源的服务能力转化给红帽？

Thomas Cameron：这个问题非常好，其实对我们来说这并不是两边。我们想的首先是这个技术先提供给社区，然后社区进一步的开发完善，最后成为供企业可以使用的技术或者软件，开源是红帽的 DNA，对我们来说最重要的一件事是使这些软件取得成功，因此在我们的工作是就某个软件进行研究，或者推动在某个软件上增加什么新的功能的时候，或者要求红帽提供更多的资源。我们想的目的都是一样的，就是先把技术放进社区，然后在这个基础上进一步的开发创新，最终拿出来供企业使用。

### 问题 2

记者：比较一下十年前的开源社区跟今天的开源社区的用户差别，十年前的开源社区是极客在参与这个项目，现在再去社区里看一下，有一些用户级的，他可能遇到使用上的麻烦，可能到社区找一些答案，我们这个产品可能在场景应用当中遇到一些特殊的问题和麻烦，这个时候能不能向这些应用者，向被迫进入社区的人介绍一下咱们的沟通机制和反馈机制是怎么样的？另外一个我看到咱们这个众筹项目正在进行中，不同的项目的沟通机制是什么样的，能不能给用户一个介绍？

Brian Exelbierd：这个问题，涉及到沟通的机制，对任何一个项目来说沟通发生在多个不同的层次上，以 Fedora 社区为例，我们的这些核心贡献者、开发建造软件并且把它们提供出来的开发者，他们在 IRC 里进行沟通交流，但是大量的用户沟通的地点在自己感兴趣的场景或者内容不同发生在不同的地点，有些特别专注于游戏或者某个特定场景，他们都有论坛和交流地点，我们也会提醒我们的人要去不同的地点才能了解到更多用户的反馈意见。

下个问题也是令人兴奋的问题，因为 Fedora 的发布会涉及到很多不同的技术，从最开始社区发展起来的时候，我们就在不同的技术小组间建立了很强的反馈和交流机制，我们在进行测试的时候也会对所有的要素进行测试，比如我们会和 CentOS、OpenCI 这样的项目进行联系看看在哪些点上可以实现很好的集成，在哪些点上可能存在问题，这也是不同项目组之间进行沟通的方式。

Max Leonard Inden：我也想补充一个观点，我们每个项目的沟通方式都是不一样的，但是各个项目之间仍然存在着非常密切的沟通，而且我们大家的态度是一样的：所有的沟通都是受欢迎的，没有人会因为在不合适的地点问了问题而受到责难，我们会欢迎你充分的参与进来，提出问题，这是非常重要的一点。

红帽技术人员：再补充一点，关于您提到的现在的普通用户参与社区比十年前多多了，今天的科技更复杂，解决方案也更复杂，我们上游社区的项目同样更复杂，用户也在试图参与进来，第二，对于开发者而言，他使用的最主要的沟通方式是代码和编码，因为代码是他们的共同语言，虽然有人发布了代码，那么就有人从代码的角度看一看应该怎么对他检查，漏洞怎么进行修改，所以代码对于全世界的开发者来说都是同样的语言。

### 问题 3

记者：红帽愿意帮助我们设立站点下载 ISO 和文件么？当我在用一个红帽的帐户登录网站的时候，我去下载镜像，点按纽会发现有一个衔接，由于我们国家到美国的网速非常慢，整个镜像下载不下来，我们的工作没法进展，我们的解决方案是租一个美国的 VPS，从 VPS 再下载到本地还是会超时，第二个解决方案是再租一个香港 VPS，把这个从美国的拉到香港 VPS，再从香港拉到本地这个时候发现中间这一块又特别慢，想知道红帽有没有相对的解决方案？

Thomas Cameron：我非常理解您的这种沮丧的情绪，而且我们也感觉这样非常麻烦。但是特别坦率的说，这个问题的解决方案涉及到方方面面，它同时是法律问题，监管问题，涉及到条约等各种各样的问题，而我们在座的人没有一个人适合回答这样的问题，因为我们不是相关问题的专家，但是鉴于您有红帽的帐户，我建议您联系一个帐户经理，他会想办法帮您找解决方案，因为我们不想使您得到非常坏的体验，也不想麻烦您建立多个 VPS 的去解决，但是这个问题的最终解决还是需要律师法律团队和网络的工程团队，我们没办法回答，谢谢。

### 问题 4

记者：在 Fedora 社区有不同的区域划分，相互之间的差异化红帽是怎么解决的，在中国的本地化进程是怎样落地的，人员参与和贡献分别是多少？

Brian Exelbierd：我非得站起来回答您的第二个问题不可，因为要给您看一下我穿的体恤，这个体恤是 Fedora 本地化的主题，这是我们第 26 次发布 Fedora 版本的时候做的，主要目的是为了感谢全世界各地为 Fedora 本地化做出贡献的人们，因为确实有很多人都参与进来了，里面有一个泡泡写的是汉语。

我现在回答您问题的第一部分，您讲的非常对，我们 Fedora 是分区域的这个主要是有两个原因，首先是过去为了行政管理的便利做出的安排，因为这样分成不同的区域之后就可以更为容易的，相当于在本地做决定，而且资金的流动也更便利一些，随着全球化的发展，这个重要性降低了。还有第二个原因，您刚才提到差异化，差异性是无处不在的，我们希望在对话的时候，彼此的对话能在一个更适合的地方发生，因而在不同的国家和社区进行对话时所产生的决议有效，毕竟不同区域在文化上是有敏感性的。

回答您的第二个问题，您问到中国有多少贡献者，和他们在在这个社区中多活跃，对这样的问题，我们的回答永远是不够多，因为我们希望任何地方的贡献者都能够更多一些，希望他们更活跃的参与社区的活动。在中国我们也面临这样的挑战，因为中国的这些软件工程师或者相关可能的爱好者，他们本身的工作时间是非常长的，会加很长的班，通勤时间也非常长。这样他们就没有太多的精力投入开源社区的活动，此外中国社会不太重视让学生参与开源活动，大部分学生更专注于把考分弄的更高一点。我们在中国一直希望寻找对开源感兴趣的人，鼓励他们参与进来。不管你面临什么样的用户和场景，我们希望都是有人能够和你进行交流提供帮助的，所以我们非常鼓励大家的参与。

再补充一点，我们的开源社区是非常具有全球性的社区，因此绝不会在中国天然的有哪些情况就使得中国人为社区做贡献特别难，不会有这些情况，比如我本人经常在晚上九点和社区的成员进行交流，因为这个对大部分社区成员来说是最合适的时间。对不少中国人来讲，中国的时区和美国时区差异特别大，但是这一点不会阻止开源社区的交流。

### 问题 5

记者：我想问一个跟开源和闭源有关的问题，从软件开发的角度来讲，开源比闭源好，因为闭源一年更新的速度比较慢，而开源的广泛性和活跃性远远大于闭源，但是从商业角度来讲，开源还是不太成功的，以红帽为例，现在红帽每年的营收跟微软和闭源的软件厂商来讲远远不在一个级别上，从商业的角度讲，开源不那么成熟，作为开源社区的大拿来讲，吸引你们进入开源的热情是你们对技术的偏好，还是你们坚信开源技术未来在商业上有很大的潜质，什么支撑你们在开源领域里努力？

Thomas Cameron：在商业上我们已经比那些闭源的软件厂商要成功了。如果仔细的看一下红帽的财报跟他每年的增长，我们每年平均增长都在 20% 以上，所以从增速的角度来看，我们比所有的闭源软件开发公司做的都要好，所以从商业模式上已经证明了开源可以做的很好。关于为什么我个人会在开源中，这个回答非常简单，因为在这个世界上没有任何其他一个我所知道的行业能够让一个国家、或者一个村子里的人看到代码，并且利用手上的电脑开展相关的工作，没有任何一个其他的行业像开源社区一样把自己知道的一切都告诉别人，而在这个过程中我还拿到一份薪酬，当然我不能代表别人说话，我自己而言我觉得我是全世界最幸运的人，一方面我能够每天都在玩这些最酷的技术，同时还把我所知道的一切告诉任何感兴趣想学习的人，在这个过程中还能拿到工资。

给大家看一下大臂上的刺青，我觉得几乎没有那个闭源公司的员工会把自己公司的logo刻到自己的身上，但是我这样做了。大概五年前，闭源和开源软件公司之间的冲突还是非常显著的，但是今天我们可以看到所有的闭源软件公司都在采用开源的方法，他们也在发布大量的开源的代码，也就是说他们都看到了开源的模式，协作，为他人提供服务，以及做一切人人们生活变的更好的事情，这个模式是被大家认可的，这个时代是非常不可思议的，著名厂商包括IBM，微软，甲骨文等等，他们都在做开源的事情。

Jennifer Madriaga：我也补充一下，强调一下我们开源的核心是协作，在开源的社区里面，你会发现很多竞争对手同时也是合作的伙伴，我们和 IBM 是很好的伙伴，和微软是很好的伙伴，是 AWS、谷歌都是非常好的伙伴。重要的是没有他们的参与，没有我们的参与，这个行业就不可能取得这么大的成功。我经常到各个社区去，在这个过程中会和其他的组织进行交流，其中不少会被媒体描述为我们的竞争对手。我们也不仅仅和这些公司打交道，我们还和很多大学，非盈利机构进行沟通，这个社区是多样的，而且有大量的互动。开源社区伟大的一点是他特别促进创新，有这样的一个机构，CERN，欧洲原子能组织，他们的每一个软件都是开源的，他们在用 CoreOS、Fedora、Ceph 等，还有 NASA，也使用了大量的开源软件，其实他们是最早发明了 OpenStack，之后在社区得以进一步开发。行业的未来是开源，很多公司为什么用开源，因为他们知道只有用了开源才能保持自己的敏捷性，而且他们也知道自己是没有办法预测未来的，但是如果他们不与时俱进，那么这个公司可能将来就死路一条。

 Adam Samalik：假如你是一个喜欢编代码的人，或者公司让程序员编写代码，如果你在社区里发布过你的代码，并且让其他人为这个代码做出贡献，你立刻会意识到开源的重要性或者价值。拿 Kubernetes 举个例子，它最早是谷歌拿出来的，一开始非常简单，但是大家都看到它的前景，现在有好多公司在为 Kubernetes 做出贡献，Kubernetes 本身也变的更为庞大，而且是非常棒的，但是在开源社区会发生这些事情，你把代码拿出来不是损失了自己的代码，有更多人会对你帮助，会有更多的贡献。

Carol Chen：谈到关系，在去年我们与阿里巴巴建立了伙伴关系，我希望并且认为肯定有更多的中国本地的伙伴关系发展起来。其实看一看 LC3 大会就知道了，有那么多大大小小的本地公司他们都在做开源，而且非常愿意分享自己用开源的经验，所以我想在这方面我们可以真实的看到这个趋势。关于个人的动机，我非常喜欢技术，我喜欢和别人分享东西，我也喜欢给别人参与这些非常酷的项目的机会，我也希望生活能够过的好，而参与开源给了我这一切。

某男：我补充一句关于创新和开源的关系，我们的 CEO 发布了一本新书《开放式创新》，现在我们看到在当今世界上人们面临的问题越来越复杂，对于这些复杂的问题一个公司单独没有办法解决，我们需要很多公司很多人合作，所以开源的平台会是非常重要的，这么多人和企业都可以一起寻找解决方案，所以开源在将来肯定会非常重要的推动创新。

Brian Exelbierd：我要讲的故事跟他们都不一样，我不知道一开始加入开源社区的动机是不是像我的同事那么纯净。 我就记得当时在大学里的朋友来找我，他当时拿着最初的 Linux 的某个版本，我们当时用软盘的复制工具复制了 64 个软盘，当时是希望能用这个东西让我非常糟糕的电脑转的更快一点。

当时我这个同学就说，欧洲有这么一个人在干这个事情，你知道我们都是美国人，住在美国也不太关心，不知道他在欧洲哪儿，但是现在我住在欧洲，知道那些地方在哪儿。当时有一个特别自私的想法，就是想让我的电脑快一点，我也做出了我的第一个贡献，因为我想让这个程序运行得有点差别，想改一下。所以最初这个动机帮助我逐步进入开源社区，当时我还是一个大学生，所以写的代码不太好，当时有代码的审阅人员，他们会看代码给你各种建议帮助你改进，这样逐步的参与动机，自私程度降低了，而更多的希望我能够也做出点贡献，也给其他人提供一些帮助。我们最早的时候有 GRP 系统，厂商根本不问我们用的怎么样，但是在开源社区情况完全不一样，我们跟企业用户沟通，他们会直接说出这个软件存在什么问题，并且他会告诉你我们应该怎么改进。

Max Leonard Inden：我为什么我参加了开源社区，我的同事们讲的非常好，从我的角度来讲是开源让我能够到这儿，让我在大会上发言，并且公开谈论我自己感兴趣的东西，而且能听别人谈。

---

听了大家的提问和回答，本人有如下感受：

* 开源在中国需要更多的非程序员的贡献者，来在艺术、营销、文档三个方面做出更多的贡献。
* 文化始终是大于代码的（Culture is bigger than code）。
* 开源本身是跨越了国界、地域、文化，让我们把资源更高效的利用起来让人们的生活更美好（OpenSource making people's life better）。


lua 中神奇的表（table）

Summary: 最近在尝试配置 awesome WM，因此粗略地学习了一下 lua 。 在学习过程中，我完全被 table 在 lua 中的应用所镇住了。

# lua 中神奇的表（table）

<img src="content_image/album_201807_05_155958zjef7jp7jpdafy6m.jpg" alt="" title="">

最近在尝试配置 awesome WM，因此粗略地学习了一下 lua 。 在学习过程中，我完全被<ruby> 表 <rp>  （ </rp> <rt>  表 </rt> <rp>  ） </rp></ruby>在 lua 中的应用所镇住了。

表在 lua 中真的是无处不在：首先，它可以作为字典和数组来用；此外，它还可以被用于设置闭包环境、模块；甚至可以用来模拟对象和类。

### 字典

表最基础的作用就是当成字典来用。 它的键可以是除了 `nil` 之外的任何类型的值。

```
t={}
t[{}] = "table"                 -- key 可以是表
t[1] = "int"                    -- key 可以是整数
t[1.1] = "double"               -- key 可以是小数
t[function () end] = "function" -- key 可以是函数
t[true] = "Boolean"             -- key 可以是布尔值
t["abc"] = "String"             -- key 可以是字符串
t[io.stdout] = "userdata"       -- key 可以是userdata
t[coroutine.create(function () end)] = "Thread" -- key可以是thread

```

当把表当成字典来用时，可以使用 `pairs` 函数来进行遍历。

```
for k,v in pairs(t) do
  print(k,"->",v)
end

```

运行结果为：

```
1   ->  int
1.1 ->  double
thread: 0x220bb08   ->  Thread
table: 0x220b670    ->  table
abc ->  String
file (0x7f34a81ef5c0)   ->  userdata
function: 0x220b340 ->  function
true    ->  Boolean

```

从结果中你还可以发现，使用 `pairs` 进行遍历时的顺序是随机的，事实上相同的语句执行多次得到的结果是不一样的。

表 中的键最常见的两种类型就是整数型和字符串类型。 当键为字符串时，表 可以当成结构体来用。同时形如 `t["field"]` 这种形式的写法可以简写成 `t.field` 这种形式。

### 数组

当键为整数时，表 就可以当成数组来用。而且这个数组是一个 **索引从 1 开始** 、没有固定长度、可以根据需要自动增长的数组。

```
a = {}
for i=0,5 do                    -- 注意，这里故意写成了i从0开始
  a[i] = 0
end

```

当将表当成数组来用时，可以通过长度操作符 `#` 来获取数组的长度：

```
print(#a)

```

结果为：

```
5

```

你会发现， lua 认为数组 `a` 中只有 5 个元素，到底是哪 5 个元素呢？我们可以使用使用 `ipairs` 对数组进行遍历：

```
for i,v in ipairs(a) do
  print(i,v)
end

```

结果为：

```
1   0
2   0
3   0
4   0
5   0

```

从结果中你会发现 `a` 的 0 号索引并不认为是数组中的一个元素，从而也验证了 lua 中的数组是从 **1 开始索引的**。

另外，将表当成数组来用时，一定要注意索引不连贯的情况，这种情况下 `#` 计算长度时会变得很诡异。

```
a = {}
for i=1,5 do
  a[i] = 0
end
a[8] = 0                        -- 虽然索引不连贯，但长度是以最大索引为准
print(#a)
a[100] = 0                      -- 索引不连贯，而且长度不再以最大索引为准了
print(#a)

```

结果为：

```
8
8

```

而使用 `ipairs` 对数组进行遍历时，只会从 1 遍历到索引中断处。

```
for i,v in ipairs(a) do
  print(i,v)
end

```

结果为：

```
1   0
2   0
3   0
4   0
5   0

```

### 环境（命名空间）

lua 将所有的全局变量/局部变量保存在一个常规表中，这个表一般被称为全局或者某个函数（闭包）的环境。

为了方便，lua 在创建最初的全局环境时，使用全局变量 `_G` 来引用这个全局环境。因此，在未手工设置环境的情况下，可以使用 `-G[varname]` 来存取全局变量的值。

```
for k,v in pairs(_G) do
  print(k,"->",v)
end

```

```
rawequal    ->  function: 0x41c2a0
require ->  function: 0x1ea4e70
_VERSION    ->  Lua 5.3
debug   ->  table: 0x1ea8ad0
string  ->  table: 0x1ea74b0
xpcall  ->  function: 0x41c720
select  ->  function: 0x41bea0
package ->  table: 0x1ea4820
assert  ->  function: 0x41cc50
pcall   ->  function: 0x41cd10
next    ->  function: 0x41c450
tostring    ->  function: 0x41be70
_G  ->  table: 0x1ea2b80
coroutine   ->  table: 0x1ea4ee0
unpack  ->  function: 0x424fa0
loadstring  ->  function: 0x41ca00
setmetatable    ->  function: 0x41c7e0
rawlen  ->  function: 0x41c250
bit32   ->  table: 0x1ea8fc0
utf8    ->  table: 0x1ea8650
math    ->  table: 0x1ea7770
collectgarbage  ->  function: 0x41c650
rawset  ->  function: 0x41c1b0
os  ->  table: 0x1ea6840
pairs   ->  function: 0x41c950
arg ->  table: 0x1ea9450
table   ->  table: 0x1ea5130
tonumber    ->  function: 0x41bf40
io  ->  table: 0x1ea5430
loadfile    ->  function: 0x41cb10
error   ->  function: 0x41c5c0
load    ->  function: 0x41ca00
print   ->  function: 0x41c2e0
dofile  ->  function: 0x41cbd0
rawget  ->  function: 0x41c200
type    ->  function: 0x41be10
getmetatable    ->  function: 0x41cb80
module  ->  function: 0x1ea4e00
ipairs  ->  function: 0x41c970

```

从 lua 5.2 开始，可以通过修改 `_ENV` 这个值（**lua 5.1 中的 `setfenv` 从 5.2 开始被废除**）来设置某个函数的环境，从而让这个函数中的执行语句在一个新的环境中查找全局变量的值。

```
a=1                             -- 全局变量中a=1
local env={a=10,print=_G.print} -- 新环境中a=10,并且确保能访问到全局的print函数
function f1()
  local _ENV=env
  print("in f1:a=",a)
  a=a*10                        -- 修改的是新环境中的a值
end

f1()
print("globally:a=",a)
print("env.a=",env.a)

```

```
in f1:a=    10
globally:a= 1
env.a=  100

```

另外，新创建的闭包都继承了创建它的函数的环境。

### 模块

lua 中的模块也是通过返回一个表来供模块使用者来使用的。 这个表中包含的是模块中所导出的所有东西，包括函数和常量。

定义模块的一般模板为：

```
module(模块名, package.seeall)

```

其中 `module(模块名)` 的作用类似于：

```
local modname = 模块名
local M = {}                    -- M即为存放模块所有函数及常数的table
_G[modname] = M
package.loaded[modname] = M
setmetatable(M,{__index=_G})    -- package.seeall可以使全局环境_G对当前环境可见
local _ENV = M                  -- 设置当前的运行环境为 M，这样后续所有代码都不需要限定模块名了，所定义的所有函数自动变成M的成员
<函数定义以及常量定义>

return M                        -- module函数会帮你返回module table，而无需手工返回

```

### 对象

lua 中之所以可以把表当成对象来用是因为：

1. 函数在 lua 中是一类值，你可以直接存取表中的函数值。 这使得一个表既可以有自己的状态，也可以有自己的行为：

```
Account = {balance = 0}
function Account.withdraw(v)
  Account.balance = Account.balance - v
end

```
2. lua 支持闭包，这个特性可以用来模拟对象的私有成员变量：

```
function new_account(b)
  local balance = b
  return {withdraw = function (v) balance = balance -v end,
          get_balance = function () return balance end
  }
end

a1 = new_account(1000)
a1.withdraw(10)
print(a1.get_balance())

```

```
990

```

不过，上面第一种定义对象的方法有一个缺陷，那就是方法与 `Account` 这个名称绑定死了。 也就是说，这个对象的名称必须为 `Accout` 否则就会出错。

```
a = Account
Account = nil
a.withdraw(10)                  -- 会报错，因为Accout.balance不再存在

```

为了解决这个问题，我们可以给 `withdraw` 方法多一个参数用于指向对象本身。

```
Account = {balance=100}
function Account.withdraw(self,v)
  self.balance = self.balance - v
end
a = Account
Account = nil
a.withdraw(a,10)                  -- 没问题，这个时候 self 指向的是a，因此会去寻找 a.balance
print(a.balance)

```

```
90

```

不过由于第一个参数 `self` 几乎总是指向调用方法的对象本身，因此 lua 提供了一种语法糖形式 `object:method(...)` 用于隐藏 `self` 参数的定义及传递。这里冒号的作用有两个，其在定义函数时往函数中地一个参数的位置添加一个额外的隐藏参数 `sef`, 而在调用时传递一个额外的隐藏参数 `self` 到地一个参数位置。 即 `function object:method(v) end` 等价于 `function object.method(self,v) end`, `object:method(v)` 等价于 `object.method(object,v)`。

### 类

当涉及到类和继承时，就要用到元表和元方法了。事实上，对于 lua 来说，对象和类并不存在一个严格的划分。

当一个对象被另一个表的 `__index` 元方法所引用时，表就能引用该对象中所定义的方法，因此也就可以理解为对象变成了表的类。

类定义的一般模板为:

```
function 类名:new(o)
  o = o or {}
  setmetatable(o,{__index = self})
  return o
end

```

或者：

```
function 类名:new(o)
  o = o or {}
  setmetatable(o,self)
  self.__index = self
  return o
end

```

相比之下，第二种写法可以多省略一个表。

另外有一点我觉得有必要说明的就是 lua 中的元方法是在元表中定义的，而不是对象本身定义的，这一点跟其他面向对象的语言比较不同。


4 种用于构建嵌入式 Linux 系统的工具

# 4 种用于构建嵌入式 Linux 系统的工具

>
> 了解 Yocto、Buildroot、 OpenWRT，和改造过的桌面发行版以确定哪种方式最适合你的项目。
>
>
>

<img src="content_image/album_201807_06_095532wzz9flhboh6anfcw.jpg" alt="" title="">

Linux 被部署到比 Linus Torvalds 在他的宿舍里开发时所预期的更广泛的设备。令人震惊的支持了各种芯片，使得Linux 可以应用于大大小小的设备上：从 [IBM 的巨型机](https://en.wikipedia.org/wiki/Linux_on_z_Systems)到不如其连接的端口大的[微型设备](http://www.picotux.com/)，以及各种大小的设备。它被用于大型企业数据中心、互联网基础设施设备和个人的开发系统。它还为消费类电子产品、移动电话和许多物联网设备提供了动力。

在为桌面和企业级设备构建 Linux 软件时，开发者通常在他们的构建机器上使用桌面发行版，如 [Ubuntu](https://www.ubuntu.com/) 以便尽可能与被部署的机器相似。如 [VirtualBox](https://www.virtualbox.org/) 和 [Docker](https://www.docker.com/) 这样的工具使得开发、测试和生产环境更好的保持了一致。

### 什么是嵌入式系统？

维基百科将[嵌入式系统](https://en.wikipedia.org/wiki/Embedded_system)定义为：“在更大的机械或电气系统中具有专用功能的计算机系统，往往伴随着实时计算限制。”

我觉得可以很简单地说，嵌入式系统是大多数人不认为是计算机的计算机。它的主要作用是作为某种设备，而不被视为通用计算平台。

嵌入式系统编程的开发环境通常与测试和生产环境大不相同。它们可能会使用不同的芯片架构、软件堆栈甚至操作系统。开发工作流程对于嵌入式开发人员与桌面和 Web 开发人员来说是非常不同的。通常，其构建后的输出将包含目标设备的整个软件映像，包括内核、设备驱动程序、库和应用程序软件（有时也包括引导加载程序）。

在本文中，我将对构建嵌入式 Linux 系统的四种常用方式进行纵览。我将介绍一下每种产品的工作原理，并提供足够的信息来帮助读者确定使用哪种工具进行设计。我不会教你如何使用它们中的任何一个；一旦缩小了选择范围，就有大量深入的在线学习资源。没有任何选择适用于所有情况，我希望提供足够的细节来指导您的决定。

### Yocto

[Yocto](https://yoctoproject.org/) 项目 [定义](https://www.yoctoproject.org/about/)为“一个开源协作项目，提供模板、工具和方法，帮助您为嵌入式产品创建定制的基于 Linux 的系统，而不管硬件架构如何。”它是用于创建定制的 Linux 运行时映像的配方、配置值和依赖关系的集合，可根据您的特定需求进行定制。

完全公开：我在嵌入式 Linux 中的大部分工作都集中在 Yocto 项目上，而且我对这个系统的认识和偏见可能很明显。

Yocto 使用 [Openembedded](https://www.openembedded.org/) 作为其构建系统。从技术上讲，这两个是独立的项目；然而，在实践中，用户不需要了解区别，项目名称经常可以互换使用。

Yocto 项目的输出大致由三部分组成：

* **目标运行时二进制文件：**这些包括引导加载程序、内核、内核模块、根文件系统映像。以及将 Linux 部署到目标平台所需的任何其他辅助文件。
* **包流：**这是可以安装在目标上的软件包集合。您可以根据需要选择软件包格式（例如，deb、rpm、ipk）。其中一些可能预先安装在目标运行时二进制文件中，但可以构建用于安装到已部署系统的软件包。
* **目标 SDK：**这些是安装在目标平台上的软件的库和头文件的集合。应用程序开发人员在构建代码时使用它们，以确保它们与适当的库链接

#### 优点

Yocto 项目在行业中得到广泛应用，并得到许多有影响力的公司的支持。此外，它还拥有一个庞大且充满活力的开发人员[社区](https://www.yoctoproject.org/community/)和[生态系统](https://www.yoctoproject.org/ecosystem/participants/)。开源爱好者和企业赞助商的结合的方式有助于推动 Yocto 项目。

获得 Yocto 的支持有很多选择。如果您想自己动手，有书籍和其他培训材料。如果您想获得专业知识，有许多有 Yocto 经验的工程师。而且许多商业组织可以为您的设计提供基于 Yocto 的 Turnkey 产品或基于服务的实施和定制。

Yocto 项目很容易通过 [层](https://layers.openembedded.org/layerindex/branch/master/layers/) 进行扩展，层可以独立发布以添加额外的功能，或针对项目发布时尚不可用的平台，或用于保存系统特有定制功能。层可以添加到你的配置中，以添加未特别包含在市面上版本中的独特功能；例如，“[meta-browser](https://layers.openembedded.org/layerindex/branch/master/layer/meta-browser/)” 层包含 Web 浏览器的清单，可以轻松为您的系统进行构建。因为它们是独立维护的，所以层可以按不同的时间发布（根据层的开发速度），而不是跟着标准的 Yocto 版本发布。

Yocto 可以说是本文讨论的任何方式中最广泛的设备支持。由于许多半导体和电路板制造商的支持，Yocto 很可能能够支持您选择的任何目标平台。主版本 Yocto [分支](https://yoctoproject.org/downloads)仅支持少数几块主板（以便达成合理的测试和发布周期），但是，标准工作模式是使用外部主板支持层。

最后，Yocto 非常灵活和可定制。您的特定应用程序的自定义可以存储在一个层进行封装和隔离，通常将要素层特有的自定义项存储为层本身的一部分，这可以将相同的设置同时应用于多个系统配置。Yocto 还提供了一个定义良好的层优先和覆盖功能。这使您可以定义层应用和搜索元数据的顺序。它还使您可以覆盖具有更高优先级的层的设置；例如，现有清单的许多自定义功能都将保留。

#### 缺点

Yocto 项目最大的缺点是学习曲线陡峭。学习该系统并真正理解系统需要花费大量的时间和精力。 根据您的需求，这可能对您的应用程序不重要的技术和能力投入太大。 在这种情况下，与一家商业供应商合作可能是一个不错的选择。

Yocto 项目的开发时间和资源相当高。 需要构建的包（包括工具链，内核和所有目标运行时组件）的数量相当不少。 Yocto 开发人员的开发工作站往往是大型系统。 不建议使用小型笔记本电脑。 这可以通过使用许多提供商提供的基于云的构建服务器来缓解。 另外，Yocto 有一个内置的缓存机制，当它确定用于构建特定包的参数没有改变时，它允许它重新使用先前构建的组件。

#### 建议

为您的下一个嵌入式 Linux 设计使用 Yocto 项目是一个强有力的选择。 在这里介绍的选项中，无论您的目标用例如何，它都是最广泛适用的。 广泛的行业支持，积极的社区和广泛的平台支持使其成为必须设计师的不错选择。

### Buildroot

[Buildroot](https://buildroot.org/) 项目定义为“通过交叉编译生成嵌入式 Linux 系统的简单、高效且易于使用的工具。”它与 Yocto 项目具有许多相同的目标，但它注重简单性和简约性。一般来说，Buildroot 会禁用所有软件包的所有可选编译时设置（有一些值得注意的例外），从而生成尽可能小的系统。系统设计人员需要启用适用于给定设备的设置。

Buildroot 从源代码构建所有组件，但不支持按目标包管理。因此，它有时称为固件生成器，因为镜像在构建时大部分是固定的。应用程序可以更新目标文件系统，但是没有机制将新软件包安装到正在运行的系统中。

Buildroot 输出主要由三部分组成：

* 将 Linux 部署到目标平台所需的根文件系统映像和任何其他辅助文件
* 适用于目标硬件的内核，引导加载程序和内核模块
* 用于构建所有目标二进制文件的工具链。

#### 优点

Buildroot 对简单性的关注意味着，一般来说，它比 Yocto 更容易学习。核心构建系统用 Make 编写，并且足够短以便开发人员了解整个系统，同时可扩展到足以满足嵌入式 Linux 开发人员的需求。 Buildroot 核心通常只处理常见用例，但它可以通过脚本进行扩展。

Buildroot 系统使用普通的 Makefile 和 Kconfig 语言来进行配置。 Kconfig 由 Linux 内核社区开发，广泛用于开源项目，使得许多开发人员都熟悉它。

由于禁用所有可选的构建时设置的设计目标，Buildroot 通常会使用开箱即用的配置生成尽可能最小的镜像。一般来说，构建时间和构建主机资源的规模将比 Yocto 项目的规模更小。

#### 缺点

关注简单性和最小化启用的构建方式意味着您可能需要执行大量的自定义来为应用程序配置 Buildroot 构建。此外，所有配置选项都存储在单个文件中，这意味着如果您有多个硬件平台，则需要为每个平台进行每个定制更改。

对系统配置文件的任何更改都需要全部重新构建所有软件包。与 Yocto 相比，这个问题通过最小的镜像大小和构建时间得到了一定的解决，但在你调整配置时可能会导致构建时间过长。

中间软件包状态缓存默认情况下未启用，并且不像 Yocto 实施那么彻底。这意味着，虽然第一次构建可能比等效的 Yocto 构建短，但后续构建可能需要重建许多组件。

#### 建议

对于大多数应用程序，使用 Buildroot 进行下一个嵌入式 Linux 设计是一个不错的选择。如果您的设计需要多种硬件类型或其他差异，但由于同步多个配置的复杂性，您可能需要重新考虑，但对于由单一设置组成的系统，Buildroot 可能适合您。

### OpenWRT/LEDE

[OpenWRT](https://openwrt.org/) 项目开始为消费类路由器开发定制固件。您当地零售商提供的许多低成本路由器都可以运行 Linux 系统，但可能无法开箱即用。这些路由器的制造商可能无法提供频繁的更新来解决新的威胁，即使他们这样做，安装更新镜像的机制也很困难且容易出错。 OpenWRT 项目为许多已被其制造商放弃的设备生成更新的固件镜像，让这些设备焕发新生。

OpenWRT 项目的主要交付物是可用于大量商业设备的二进制镜像。它有网络可访问的软件包存储库，允许设备最终用户将新软件添加到他们的系统中。 OpenWRT 构建系统是一个通用构建系统，它允许开发人员创建自定义版本以满足他们自己的需求并添加新软件包，但其主要重点是目标二进制文件。

#### 优点

如果您正在为商业设备寻找替代固件，则 OpenWRT 应位于您的选项列表中。它的维护良好，可以保护您免受制造商固件无法解决的问题。您也可以添加额外的功能，使您的设备更有用。

如果您的嵌入式设计专注于网络，则 OpenWRT 是一个不错的选择。网络应用程序是 OpenWRT 的主要用例，您可能会发现许多可用的软件包。

#### 缺点

OpenWRT 对您的设计限制很多（与 Yocto 和 Buildroot 相比）。如果这些决定不符合您的设计目标，则可能需要进行大量的修改。

在部署的设备中允许基于软件包的更新是很难管理的。按照其定义，这会导致与您的 QA 团队测试的软件负载不同。此外，很难保证大多数软件包管理器的原子安装，以及错误的电源循环可能会使您的设备处于不可预知的状态。

#### 建议

OpenWRT 是爱好者项目或商用硬件再利用的不错选择。它也是网络应用程序的不错选择。如果您需要从默认设置进行大量定制，您可能更喜欢 Buildroot 或 Yocto。

### 桌面发行版

设计嵌入式 Linux 系统的一种常见方法是从桌面发行版开始，例如 [Debian](https://www.debian.org/) 或 [Red Hat](https://www.redhat.com/)，并删除不需要的组件，直到安装的镜像符合目标设备的占用空间。这是 [Raspberry Pi](https://www.raspberrypi.org/) 平台流行的 [Raspbian](https://www.raspbian.org/)发行版的方法。

#### 优点

这种方法的主要优点是熟悉。通常，嵌入式 Linux 开发人员也是桌面 Linux 用户，并且精通他们的选择发行版。在目标上使用类似的环境可能会让开发人员更快地入门。根据所选的分布，可以使用 apt 和 yum 等标准封装工具安装许多其他工具。

可以将显示器和键盘连接到目标设备，并直接在那里进行所有的开发。对于不熟悉嵌入式空间的开发人员来说，这可能是一个更为熟悉的环境，无需配置和使用棘手的跨开发平台设置。

大多数桌面发行版可用的软件包数量通常大于前面讨论的嵌入式特定的构建器可用软件包数量。由于较大的用户群和更广泛的用例，您可能能够找到您的应用程序所需的所有运行时包，这些包已经构建并可供使用。

#### 缺点

将目标平台作为您的主要开发环境可能会很慢。运行编译器工具是一项资源密集型操作，根据您构建的代码的多少，这可能会严重妨碍您的性能。

除了一些例外情况，桌面发行版的设计并不适合低资源系统，并且可能难以充分裁剪目标映像。同样，桌面环境中的预设工作流程对于大多数嵌入式设计来说都不理想。以这种方式获得可再现的环境很困难。手动添加和删除软件包很容易出错。这可以使用特定于发行版的工具进行脚本化，例如基于 Debian 系统的 [debootstrap](https://wiki.debian.org/Debootstrap)。为了进一步提高[可再现性](https://wiki.debian.org/Debootstrap)，您可以使用配置管理工具，如 [CFEngine](https://cfengine.com/)（我的雇主 [Mender.io](http://Mender.io) 完整披露了 这一工具）。但是，您仍然受发行版提供商的支配，他们将更新软件包以满足他们的需求，而不是您的需求。

#### 建议

对于您打算推向市场的产品，请谨慎使用此方法。这对于爱好者应用程序来说是一个很好的模型；但是，对于需要支持的产品，这种方法很可能会遇到麻烦。虽然您可能能够获得更快的起步，但从长远来看，您可能会花费您的时间和精力。

### 其他考虑

这个讨论集中在构建系统的功能上，但通常有非功能性需求可能会影响您的决定。如果您已经选择了片上系统（SoC）或电路板，则您的选择很可能由供应商决定。如果您的供应商为特定系统提供板级支持包（BSP），使用它通常会节省相当多的时间，但请研究 BSP 的质量以避免在开发周期后期发生问题。

如果您的预算允许，您可能需要考虑为目标操作系统使用商业供应商。有些公司会为这里讨论的许多选项提供经过验证和支持的配置，除非您拥有嵌入式 Linux 构建系统方面的专业知识，否则这是一个不错的选择，可以让您专注于核心能力。

作为替代，您可以考虑为您的开发人员进行商业培训。这可能比商业操作系统供应商便宜，并且可以让你更加自给自足。这是快速找到您选择的构建系统基础知识的学习曲线。

最后，您可能已经有一些开发人员拥有一个或多个系统的经验。如果你的工程师有倾向性，当你做出决定时，肯定值得考虑。

### 总结

构建嵌入式 Linux 系统有多种选择，每种都有优点和缺点。将这部分设计放在优先位置至关重要，因为在以后的过程中切换系统的成本非常高。除了这些选择之外，还有新的系统在开发中。希望这次讨论能够为评估新的系统（以及这里提到的系统）提供一些背景，并帮助您为下一个项目做出坚实的决定。

---

via: <https://opensource.com/article/18/6/embedded-linux-build-tools>

作者：[Drew Moseley](https://opensource.com/users/drewmoseley) 选题：[lujun9972](https://github.com/lujun9972) 译者：[LHRChina](https://github.com/LHRChina) 校对：[wxy](https://github.com/wxy)

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


Linux 上的五个开源益智游戏

Summary: 用这些有趣好玩的游戏来测试你的战略能力。

用这些有趣好玩的游戏来测试你的战略能力。

# Linux 上的五个开源益智游戏

>
> 用这些有趣好玩的游戏来测试你的战略能力。
>
>
>

游戏一直是 Linux 的弱点之一。由于 Steam、GOG 和其他将商业游戏引入多种操作系统的努力，这种情况近年来有所改变，但这些游戏通常不是开源的。当然，这些游戏可以在开源操作系统上玩，但对于纯粹开源主义者来说还不够好。

那么，一个只使用开源软件的人，能否找到那些经过足够打磨的游戏，在不损害其开源理念的前提下，提供一种可靠的游戏体验呢？当然可以。虽然开源游戏历来不太可能与一些借由大量预算开发的 AAA 商业游戏相匹敌，但在多种类型的开源游戏中，有很多都很有趣，可以从大多数主要 Linux 发行版的仓库中安装。即使某个特定的游戏没有被打包成特定的发行版本，通常也很容易从项目的网站上下载该游戏以便安装和游戏。

这篇文章着眼于益智游戏。我已经写过[街机风格游戏](https://opensource.com/article/18/1/arcade-games-linux)和[棋牌游戏](https://opensource.com/article/18/3/card-board-games-linux)。 在之后的文章中，我计划涉足赛车，角色扮演、战略和模拟经营游戏。

### Atomix

[Atomix](https://wiki.gnome.org/action/raw/Apps/Atomix) 是 1990 年在 Amiga、Commodore 64、MS-DOS 和其他平台发布的 [Atomix](https://en.wikipedia.org/w/index.php?title=Atomix_(video_game)) 益智游戏的开源克隆。Atomix 的目标是通过连接原子来构建原子分子。单个原子可以向上、向下、向左或向右移动，并一直朝这个方向移动，直到原子撞上一个障碍物——水平墙或另一个原子。这意味着需要进行规划，以确定在水平上构建分子的位置，以及移动单个部件的顺序。第一关是一个简单的水分子，它由两个氢原子和一个氧原子组成，但后来的关卡是更复杂的分子。

要安装 Atomix，请运行以下命令:

* 在 Fedora： `dnf install atomix`
* 在 Debian/Ubuntu： `apt install atomix`

### Fish Fillets - Next Generation

[Fish Fillets - Next Generation](http://fillets.sourceforge.net/index.php) 是游戏 Fish fillet 的 Linux 移植版本，它于 1998 年在 Windows 发布，源代码在 2004 年以 GPL 许可证发布。游戏中，两条鱼试图将物体移出道路来通过不同的关卡。这两条鱼有不同的属性，所以玩家需要为每个任务挑选合适的鱼。较大的鱼可以移动较重的物体，但它更大，这意味着它不适合较小的空隙。较小的鱼可以适应那些较小的间隙，但它不能移动较重的物体。如果一个物体从上面掉下来，两条鱼都会被压死，所以玩家在移动棋子时要小心。

要安装 Fish fillet——Next Generation，请运行以下命令:

* 在 Fedora：`dnf install fillets-ng`
* 在 Debian/Ubuntu： `apt install fillets-ng`

### Frozen Bubble

[Frozen Bubble](http://www.frozen-bubble.org/home/) 是一款街机风格的益智游戏，从屏幕底部向屏幕顶部的一堆泡泡射击。如果三个相同颜色的气泡连接在一起，它们就会被从屏幕上移除。任何连接在被移除的气泡下面但没有连接其他任何东西的气泡也会被移除。在拼图模式下，关卡的设计是固定的，玩家只需要在泡泡掉到屏幕底部的线以下前将泡泡从游戏区域中移除。该游戏街机模式和多人模式遵循相同的基本规则，但也有不同，这增加了多样性。Frozen Bubble 是一个标志性的开源游戏，所以如果你以前没有玩过它，玩玩看。

要安装 Frozen Bubble，请运行以下命令：

* 在 Fedora： `dnf install frozen-bubble`
* 在 Debian/Ubuntu： `apt install frozen-bubble`

### Hex-a-hop

[Hex-a-hop](http://hexahop.sourceforge.net/index.html) 是一款基于六角形瓦片的益智游戏，玩家需要将所有的绿色瓦片从水平面上移除。瓦片通过移动被移除。由于瓦片在移动后会消失，所以有必要规划出穿过水平面的最佳路径，以便在不被卡住的情况下移除所有的瓦片。但是，如果玩家使用的是次优路径，会有撤销功能。之后的关卡增加了额外的复杂性，包括需要跨越多次的瓦片和使玩家跳过一定数量的六角弹跳瓦片。

要安装 Hex-a-hop，请运行以下命令：

* 在 Fedora： `dnf install hex-a-hop`
* 在 Debian/Ubuntu： `apt install hex-a-hop`

### Pingus

[Pingus](https://pingus.seul.org/index.html) 是 [Lemmings](http://en.wikipedia.org/wiki/Lemmings) 的开源克隆。这不是一个精确的克隆，但游戏非常相似。小动物（Lemmings 里是旅鼠，Pingus 里是企鹅）通过关卡入口进入关卡，开始沿着直线行走。玩家需要使用特殊技能使小动物能够到达关卡的出口而不会被困住或者掉下悬崖。这些技能包括挖掘或建桥。如果有足够数量的小动物进入出口，这个关卡将成功完成，玩家可以进入下一个关卡。Pingus 为标准的 Lemmings 添加了一些额外的特性，包括一个世界地图和一些在原版游戏中没有的技能，但经典 Lemmings 游戏的粉丝们在这个开源版本中仍会感到自在。

要安装 Pingus，请运行以下命令：

* 在 Fedora： `dnf install pingus`
* 在 Debian/Ubuntu： `apt install pingus`

我漏掉你最喜欢的开源益智游戏了吗? 请在下面的评论中分享。

---

via: <https://opensource.com/article/18/6/puzzle-games-linux>

作者：[Joshua Allen Holm](https://opensource.com/users/holmja) 选题：[lujun9972](https://github.com/lujun9972) 译者：[ZenMoore](https://github.com/ZenMoore) 校对：[wxy](https://github.com/wxy)

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


使用 LSWC 在 Linux 中自动更改壁纸

Summary: 这是一个小脚本，可以在 Linux 桌面上定期自动更改壁纸。

这是一个小脚本，可以在 Linux 桌面上定期自动更改壁纸。

# 使用 LSWC 在 Linux 中自动更改壁纸

>
> 简介：这是一个小脚本，可以在 Linux 桌面上定期自动更改壁纸。
>
>
>

顾名思义，LittleSimpleWallpaperChanger （LSWC）是一个小脚本，可以定期地随机更改壁纸。

我知道在“外观”或“更改桌面背景”设置中有一个随机壁纸选项。但那是随机更改预置的壁纸而不是你添加的壁纸。

因此，在本文中，我们将看到如何使用 LittleSimpleWallpaperChanger 设置包含照片的随机桌面壁纸。

### Little Simple Wallpaper Changer (LSWC)

[LittleSimpleWallpaperChanger](https://github.com/LittleSimpleWallpaperChanger/lswc) （LSWC） 是一个非常轻量级的脚本，它在后台运行，从用户指定的文件夹中更改壁纸。壁纸以 1 至 5 分钟的随机间隔变化。该软件设置起来相当简单，设置完后，用户就可以不用再操心了。

#### 安装 LSWC

[点此链接下载 LSWC](https://github.com/LittleSimpleWallpaperChanger/lswc/raw/master/Lswc.zip)。压缩文件的大小约为 15KB。

* 进入下载位置。
* 右键单击下载的 .zip 文件，然后选择“在此处解压”。
* 打开解压后的文件夹，右键单击并选择“在终端中打开”。
* 在终端中复制粘贴命令 `bash ./README_and_install.sh` 并按回车键。
* 然后会弹出一个对话框，要求你选择包含壁纸的文件夹。单击它，然后选择你存放壁纸的文件夹。
* 就是这样。然后重启计算机。

#### 使用 LSWC

安装时，LSWC 会要求你选择包含壁纸的文件夹。因此，我建议你在安装 LSWC 之前创建一个文件夹并将你想要的壁纸全部移动到那。或者你可以使用图片文件夹中的“壁纸”文件夹。**所有壁纸都必须是 .jpg 格式。**

你可以添加更多壁纸或从所选文件夹中删除当前壁纸。要更改壁纸文件夹位置，你可以从以下文件中编辑壁纸的位置。

```
.config/lswc/homepath.conf

```

#### 删除 LSWC

打开终端并运行以下命令以停止 LSWC：

```
pkill lswc

```

在文件管理器中打开家目录，然后按 `Ctrl+H` 显示隐藏文件，接着删除以下文件：

* `.local` 中的 `scripts` 文件夹
* `.config` 中的 `lswc` 文件夹
* `.config/autostart` 中的 `lswc.desktop` 文件

这就完成了。创建自己的桌面背景幻灯片。LSWC 非常轻巧，易于使用。安装它然后忘记它。

LSWC 功能不是很丰富，但这是有意的。它做了它打算做的事情，那就是更换壁纸。如果你想要一个自动下载壁纸的工具试试 [WallpaperDownloader](https://itsfoss.com/wallpaperdownloader-linux/)。

请在下面的评论栏分享你对这个漂亮的小软件的想法。别忘了分享这篇文章。干杯。

---

via: <https://itsfoss.com/little-simple-wallpaper-changer/>

作者：[Aquil Roshan](https://itsfoss.com/author/aquil/) 选题：[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/) 荣誉推出


为什么 Python 开发人员应该使用 Pipenv

看官网也没看明白这玩意.

两个问题

1. Pipfile 和 Pipfile.lock 里面的 pip 源地址, pipenv install 的时候怎么才能让他自己替换成阿里的, 官网的 --pypi-mirror 还有 url 选项都不好使啊

2. 想弄一个一模一样的环境,  迁移的时候, 具体什么步骤, 两个文件移哪个, 实验了好多遍, 不得其法呀

恰巧最近在用, 有大神知道的么??

# 为什么 Python 开发人员应该使用 Pipenv

>
> 只用了一年， Pipenv 就变成了管理软件包依赖关系的 Python 官方推荐资源。
>
>
>

<img src="content_image/album_201807_07_142824cermze96p8tzaznb.jpg" alt="" title="">

Pipenv 是由 Kenneth Reitz 在一年多前创建的“面向开发者而生的 Python 开发工作流”，它已经成为管理软件包依赖关系的 [Python 官方推荐资源](https://packaging.python.org/tutorials/managing-dependencies/#managing-dependencies)。但是对于它解决了什么问题，以及它如何比使用 `pip` 和 `requirements.txt` 文件的标准工作流更有用处，这两点仍然存在困惑。在本月的 Python 专栏中，我们将填补这些空白。

### Python 包安装简史

为了理解 Pipenv 所解决的问题，看一看 Python 包管理如何发展十分有用的。

让我们回到第一个 Python 版本，这时我们有了 Python，但是没有干净的方法来安装软件包。

然后有了 [Easy Install](http://peak.telecommunity.com/DevCenter/EasyInstall)，这是一个可以相对容易地安装其他 Python 包的软件包，但它也带来了一个问题：卸载不需要的包并不容易。

[pip](https://packaging.python.org/tutorials/installing-packages/#use-pip-for-installing) 登场，绝大多数 Python 用户都熟悉它。`pip` 可以让我们安装和卸载包。我们可以指定版本，运行 `pip freeze > requirements.txt` 来输出一个已安装包列表到一个文本文件，还可以用相同的文本文件配合 `pip install -r requirements.txt` 来安装一个应用程序需要的所有包。

但是 `pip` 并没有包含将软件包彼此隔离的方法。我们可能会开发使用相同库的不同版本的应用程序，因此我们需要一种方法来实现这一点。随之而来的是[虚拟环境](https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments)，它使我们能够为我们开发的每个应用程序创建一个小型的、隔离的环境。我们已经看到了许多管理虚拟环境的工具：[virtualenv](https://virtualenv.pypa.io/en/stable/)、 [venv](https://docs.python.org/3/library/venv.html)、 [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/)、 [pyenv](https://github.com/pyenv/pyenv)、 [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)、 [pyenv-virtualenvwrapper](https://github.com/pyenv/pyenv-virtualenvwrapper) 等等。它们都可以很好地使用 `pip` 和 `requirements.txt` 文件。

### 新方法：Pipenv

Pipenv 旨在解决几个问题：

首先，需要 `pip` 库来安装包，外加一个用于创建虚拟环境的库，以及用于管理虚拟环境的库，再有与这些库相关的所有命令。这些都需要管理。Pipenv 附带包管理和虚拟环境支持，因此你可以使用一个工具来安装、卸载、跟踪和记录依赖性，并创建、使用和组织你的虚拟环境。当你使用它启动一个项目时，如果你还没有使用虚拟环境的话，Pipenv 将自动为该项目创建一个虚拟环境。

Pipenv 通过放弃 `requirements.txt` 规范转而将其移动到一个名为 [Pipfile](https://github.com/pypa/pipfile) 的新文档中来完成这种依赖管理。当你使用 Pipenv 安装一个库时，项目的 `Pipfile` 会自动更新安装细节，包括版本信息，还有可能的 Git 仓库位置、文件路径和其他信息。

其次，Pipenv 希望能更容易地管理复杂的相互依赖关系。你的应用程序可能依赖于某个特定版本的库，而那个库可能依赖于另一个特定版本的库，这些依赖关系如海龟般堆叠起来。当你的应用程序使用的两个库有冲突的依赖关系时，你的情况会变得很艰难。Pipenv 希望通过在一个名为 `Pipfile.lock` 的文件中跟踪应用程序相互依赖关系树来减轻这种痛苦。`Pipfile.lock` 还会验证生产中是否使用了正确版本的依赖关系。

另外，当多个开发人员在开发一个项目时，Pipenv 很方便。通过 `pip` 工作流，凯西可能会安装一个库，并花两天时间使用该库实现一个新功能。当凯西提交更改时，他可能会忘记运行 `pip freeze` 来更新 `requirements.txt` 文件。第二天，杰米拉取凯西的改变，测试就突然失败了。这样会花费好一会儿才能意识到问题是在 `requirements.txt` 文件中缺少相关库，而杰米尚未在虚拟环境中安装这些文件。

因为 Pipenv 会在安装时自动记录依赖性，如果杰米和凯西使用了 Pipenv，`Pipfile` 会自动更新并包含在凯西的提交中。这样杰米和凯西就可以节省时间并更快地运送他们的产品。

最后，将 Pipenv 推荐给在你项目上工作的其他人，因为它使用标准化的方式来安装项目依赖项和开发和测试的需求。使用 `pip` 工作流和 `requirements.txt` 文件意味着你可能只有一个 `requirements.txt` 文件，或针对不同环境的多个 `requirements.txt` 文件。例如，你的同事可能不清楚他们是否应该在他们的笔记本电脑上运行项目时是运行 `dev.txt` 还是 `local.txt`。当两个相似的 `requirements.txt` 文件彼此不同步时它也会造成混淆：`local.txt` 是否过时了，还是真的应该与 `dev.txt` 不同？多个 `requirements.txt` 文件需要更多的上下文和文档，以使其他人能够按照预期正确安装依赖关系。这个工作流程有可能会混淆同时并增加你的维护负担。

使用 Pipenv，它会生成 `Pipfile`，通过为你管理对不同环境的依赖关系，可以避免这些问题。该命令将安装主项目依赖项：

```
pipenv install

```

添加 `--dev` 标志将安装开发/测试的 `requirements.txt`：

```
pipenv install --dev

```

使用 Pipenv 还有其他好处：它具有更好的安全特性，以易于理解的格式绘制你的依赖关系，无缝处理 `.env` 文件，并且可以在一个文件中自动处理开发与生产环境的不同依赖关系。你可以在[文档](https://docs.pipenv.org/)中阅读更多内容。

### 使用 Pipenv

使用 Pipenv 的基础知识在官方 Python 包管理教程[管理应用程序依赖关系](https://packaging.python.org/tutorials/managing-dependencies/)部分中详细介绍。要安装 Pipenv，使用 `pip`：

```
pip install pipenv

```

要安装在项目中使用的包，请更改为项目的目录。然后安装一个包（我们将使用 Django 作为例子），运行：

```
pipenv install django

```

你会看到一些输出，表明 Pipenv 正在为你的项目创建一个 `Pipfile`。

如果你还没有使用虚拟环境，你还会看到 Pipenv 的一些输出，说明它正在为你创建一个虚拟环境。

然后，你将看到你在安装包时常看到的输出。

为了生成 `Pipfile.lock` 文件，运行：

```
pipenv lock

```

你也可以使用 Pipenv 运行 Python 脚本。运行名为 `hello.py` 的上层 Python 脚本：

```
pipenv run python hello.py

```

你将在控制台中看到预期结果。

启动一个 shell，运行：

```
pipenv shell

```

如果你想将当前使用 `requirements.txt` 文件的项目转换为使用 Pipenv，请安装 Pipenv 并运行：

```
pipenv install requirements.txt

```

这将创建一个 Pipfile 并安装指定的 `requirements.txt`。考虑一下升级你的项目！

### 了解更多

查看 Pipenv 文档，特别是 [Pipenv 的基本用法](https://docs.pipenv.org/basics/)，以帮助你进一步学习。Pipenv 的创建者 Kenneth Reitz 为 Pipenv 在最近的 PyTennessee 发表了一篇演讲：“[Python 依赖管理的未来](https://www.pytennessee.org/schedule/presentation/158/)”。这次演讲没有被记录下来，但他的[幻灯片](https://speakerdeck.com/kennethreitz/the-future-of-python-dependency-management)有助于理解 Pipenv 所做的以及解决的问题。

---

via: <https://opensource.com/article/18/2/why-python-devs-should-use-pipenv>

作者：[Lacey Williams Henschel](https://opensource.com/users/laceynwilliams), [Jeff Triplett](https://opensource.com/users/jefftriplett) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


JavaScript 路由器

# JavaScript 路由器

<img src="content_image/album_201807_07_144603n00b0ma2bmlmnx0l.jpg" alt="" title="">

构建单页面应用（SPA）有许多的框架/库，但是我希望它们能少一些。我有一个解决方案，我想共享给大家。

```
class Router {
    constructor() {
        this.routes = []
    }

    handle(pattern, handler) {
        this.routes.push({ pattern, handler })
    }

    exec(pathname) {
        for (const route of this.routes) {
            if (typeof route.pattern === 'string') {
                if (route.pattern === pathname) {
                    return route.handler()
                }
            } else if (route.pattern instanceof RegExp) {
                const result = pathname.match(route.pattern)
                if (result !== null) {
                    const params = result.slice(1).map(decodeURIComponent)
                    return route.handler(...params)
                }
            }
        }
    }
}
const router = new Router()

router.handle('/', homePage)
router.handle(/^\/users\/([^\/]+)$/, userPage)
router.handle(/^\//, notFoundPage)

function homePage() {
    return 'home page'
}

function userPage(username) {
    return `${username}'s page`
}

function notFoundPage() {
    return 'not found page'
}

console.log(router.exec('/')) // home page
console.log(router.exec('/users/john')) // john's page
console.log(router.exec('/foo')) // not found page

```

使用它你可以为一个 URL 模式添加处理程序。这个模式可能是一个简单的字符串或一个正则表达式。使用一个字符串将精确匹配它，但是如果使用一个正则表达式将允许你做一些更复杂的事情，比如，从用户页面上看到的 URL 中获取其中的一部分，或者匹配任何没有找到页面的 URL。

我将详细解释这个 `exec` 方法 … 正如我前面说的，URL 模式既有可能是一个字符串，也有可能是一个正则表达式，因此，我首先来检查它是否是一个字符串。如果模式与给定的路径名相同，它返回运行处理程序。如果是一个正则表达式，我们与给定的路径名进行匹配。如果匹配成功，它将获取的参数传递给处理程序，并返回运行这个处理程序。

### 工作示例

那个例子正好记录到了控制台。我们尝试将它整合到一个页面，看看它是什么样的。

```
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Router Demo</title>
 <link rel="shortcut icon" href="data:,">
 <script src="/main.js" type="module"></script>
</head>
<body>
 <header>
 <a href="/">Home</a>
 <a href="/users/john_doe">Profile</a>
 </header>
 <main></main>
</body>
</html>

```

这是 `index.html`。对于单页面应用程序来说，你必须在服务器侧做一个特别的工作，因为所有未知的路径都将返回这个 `index.html`。在开发时，我们使用了一个 npm 工具调用了 [serve](https://npm.im/serve)。这个工具去提供静态内容。使用标志 `-s`/`--single`，你可以提供单页面应用程序。

使用 [Node.js](https://nodejs.org/) 和安装的 npm（它与 Node 一起安装），运行：

```
npm i -g serve
serve -s

```

那个 HTML 文件将脚本 `main.js` 加载为一个模块。在我们渲染的相关页面中，它有一个简单的 `<header>` 和一个 `<main>` 元素。

在 `main.js` 文件中：

```
const main = document.querySelector('main')
const result = router.exec(location.pathname)
main.innerHTML = result

```

我们调用传递了当前路径名为参数的 `router.exec()`，然后将 `result` 设置为 `main` 元素的 HTML。

如果你访问 `localhost` 并运行它，你将看到它能够正常工作，但不是预期中的来自一个单页面应用程序。当你点击链接时，单页面应用程序将不会被刷新。

我们将在每个点击的链接的锚点上附加事件监听器，防止出现缺省行为，并做出正确的渲染。因为一个单页面应用程序是一个动态的东西，你预期要创建的锚点链接是动态的，因此要添加事件监听器，我使用的是一个叫 [事件委托](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) 的方法。

我给整个文档附加一个点击事件监听器，然后去检查在锚点上（或内部）是否有点击事件。

在 `Router` 类中，我有一个注册回调的方法，在我们每次点击一个链接或者一个 `popstate` 事件发生时，这个方法将被运行。每次你使用浏览器的返回或者前进按钮时，`popstate` 事件将被发送。

为了方便其见，我们给回调传递与 `router.exec(location.pathname)` 相同的参数。

```
class Router {
    // ...
    install(callback) {
        const execCallback = () => {
            callback(this.exec(location.pathname))
        }

        document.addEventListener('click', ev => {
            if (ev.defaultPrevented
                || ev.button !== 0
                || ev.ctrlKey
                || ev.shiftKey
                || ev.altKey
                || ev.metaKey) {
                return
            }

            const a = ev.target.closest('a')

            if (a === null
                || (a.target !== '' && a.target !== '_self')
                || a.hostname !== location.hostname) {
                return
            }

            ev.preventDefault()

            if (a.href !== location.href) {
                history.pushState(history.state, document.title, a.href)
                execCallback()
            }
        })

        addEventListener('popstate', execCallback)
        execCallback()
    }
}

```

对于链接的点击事件，除调用了回调之外，我们还使用 `history.pushState()` 去更新 URL。

我们将前面的 `main` 元素中的渲染移动到 `install` 回调中。

```
router.install(result => {
 main.innerHTML = result
})

```

#### DOM

你传递给路由器的这些处理程序并不需要返回一个字符串。如果你需要更多的东西，你可以返回实际的 DOM。如：

```
const homeTmpl = document.createElement('template')
homeTmpl.innerHTML = `
 <div class="container">
 <h1>Home Page</h1>
 </div>
`

function homePage() {
 const page = homeTmpl.content.cloneNode(true)
 // You can do `page.querySelector()` here...
 return page
}

```

现在，在 `install` 回调中，你可以去检查 `result` 是一个 `string` 还是一个 `Node`。

```
router.install(result => {
    if (typeof result === 'string') {
        main.innerHTML = result
    } else if (result instanceof Node) {
        main.innerHTML = ''
        main.appendChild(result)
    }
})

```

这些就是基本的功能。我希望将它共享出来，因为我将在下篇文章中使用到这个路由器。

我已经以一个 [npm 包](https://www.npmjs.com/package/@nicolasparada/router) 的形式将它发布了。

---

via: <https://nicolasparada.netlify.com/posts/js-router/>

作者：[Nicolás Parada](https://nicolasparada.netlify.com/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


Python 字节码介绍

# Python 字节码介绍

>
> 了解 Python 字节码是什么，Python 如何使用它来执行你的代码，以及知道它是如何帮到你的。
>
>
>

<img src="content_image/album_201807_08_072357fqngnbmjjqqbkkvk.jpg" alt="" title="">

如果你曾经编写过 Python，或者只是使用过 Python，你或许经常会看到 Python 源代码文件——它们的名字以 `.py` 结尾。你可能还看到过其它类型的文件，比如以 `.pyc` 结尾的文件，或许你可能听说过它们就是 Python 的 “<ruby> 字节码 <rt>  bytecode </rt></ruby>” 文件。（在 Python 3 上这些可能不容易看到 —— 因为它们与你的 `.py` 文件不在同一个目录下，它们在一个叫 `__pycache__` 的子目录中）或者你也听说过，这是节省时间的一种方法，它可以避免每次运行 Python 时去重新解析源代码。

但是，除了 “噢，原来这就是 Python 字节码” 之外，你还知道这些文件能做什么吗？以及 Python 是如何使用它们的？

如果你不知道，那你走运了！今天我将带你了解 Python 的字节码是什么，Python 如何使用它去运行你的代码，以及知道它是如何帮助你的。

### Python 如何工作

Python 经常被介绍为它是一个解释型语言 —— 其中一个原因是在程序运行时，你的源代码被转换成 CPU 的原生指令 —— 但这样的看法只是部分正确。Python 与大多数解释型语言一样，确实是将源代码编译为一组虚拟机指令，并且 Python 解释器是针对相应的虚拟机实现的。这种中间格式被称为 “字节码”。

因此，这些 `.pyc` 文件是 Python 悄悄留下的，是为了让它们运行的 “更快”，或者是针对你的源代码的 “优化” 版本；它们是你的程序在 Python 虚拟机上运行的字节码指令。

我们来看一个示例。这里是用 Python 写的经典程序 “Hello, World!”：

```
def hello()
    print("Hello, World!")

```

下面是转换后的字节码（转换为人类可读的格式）：

```
2           0 LOAD_GLOBAL              0 (print)
            2 LOAD_CONST               1 ('Hello, World!')
            4 CALL_FUNCTION            1

```

如果你输入那个 `hello()` 函数，然后使用 [CPython](https://github.com/python/cpython) 解释器去运行它，那么上述列出的内容就是 Python 所运行的。它看起来可能有点奇怪，因此，我们来深入了解一下它都做了些什么。

### Python 虚拟机内幕

CPython 使用一个基于栈的虚拟机。也就是说，它完全面向栈数据结构的（你可以 “推入” 一个东西到栈 “顶”，或者，从栈 “顶” 上 “弹出” 一个东西来）。

CPython 使用三种类型的栈：

1. <ruby> 调用栈 <rt>  call stack </rt></ruby>。这是运行 Python 程序的主要结构。它为每个当前活动的函数调用使用了一个东西 —— “<ruby> 帧 <rt>  frame </rt></ruby>”，栈底是程序的入口点。每个函数调用推送一个新的帧到调用栈，每当函数调用返回后，这个帧被销毁。
2. 在每个帧中，有一个<ruby> 计算栈 <rt>  evaluation stack </rt></ruby> （也称为<ruby> 数据栈 <rt>  data stack </rt></ruby>）。这个栈就是 Python 函数运行的地方，运行的 Python 代码大多数是由推入到这个栈中的东西组成的，操作它们，然后在返回后销毁它们。
3. 在每个帧中，还有一个<ruby> 块栈 <rt>  block stack </rt></ruby>。它被 Python 用于去跟踪某些类型的控制结构：循环、`try` / `except` 块、以及 `with` 块，全部推入到块栈中，当你退出这些控制结构时，块栈被销毁。这将帮助 Python 了解任意给定时刻哪个块是活动的，比如，一个 `continue` 或者 `break` 语句可能影响正确的块。

大多数 Python 字节码指令操作的是当前调用栈帧的计算栈，虽然，还有一些指令可以做其它的事情（比如跳转到指定指令，或者操作块栈）。

为了更好地理解，假设我们有一些调用函数的代码，比如这个：`my_function(my_variable, 2)`。Python 将转换为一系列字节码指令：

1. 一个 `LOAD_NAME` 指令去查找函数对象 `my_function`，然后将它推入到计算栈的顶部
2. 另一个 `LOAD_NAME` 指令去查找变量 `my_variable`，然后将它推入到计算栈的顶部
3. 一个 `LOAD_CONST` 指令去推入一个实整数值 `2` 到计算栈的顶部
4. 一个 `CALL_FUNCTION` 指令

这个 `CALL_FUNCTION` 指令将有 2 个参数，它表示那个 Python 需要从栈顶弹出两个位置参数；然后函数将在它上面进行调用，并且它也同时被弹出（对于函数涉及的关键字参数，它使用另一个不同的指令 —— `CALL_FUNCTION_KW`，但使用的操作原则类似，以及第三个指令 —— `CALL_FUNCTION_EX`，它适用于函数调用涉及到参数使用 `*` 或 `**` 操作符的情况）。一旦 Python 拥有了这些之后，它将在调用栈上分配一个新帧，填充到函数调用的本地变量上，然后，运行那个帧内的 `my_function` 字节码。运行完成后，这个帧将被调用栈销毁，而在最初的帧内，`my_function` 的返回值将被推入到计算栈的顶部。

### 访问和理解 Python 字节码

如果你想玩转字节码，那么，Python 标准库中的 `dis` 模块将对你有非常大的帮助；`dis` 模块为 Python 字节码提供了一个 “反汇编”，它可以让你更容易地得到一个人类可读的版本，以及查找各种字节码指令。[`dis` 模块的文档](https://docs.python.org/3/library/dis.html) 可以让你遍历它的内容，并且提供一个字节码指令能够做什么和有什么样的参数的完整清单。

例如，获取上面的 `hello()` 函数的列表，可以在一个 Python 解析器中输入如下内容，然后运行它：

```
import dis
dis.dis(hello)

```

函数 `dis.dis()` 将反汇编一个函数、方法、类、模块、编译过的 Python 代码对象、或者字符串包含的源代码，以及显示出一个人类可读的版本。`dis` 模块中另一个方便的功能是 `distb()`。你可以给它传递一个 Python 追溯对象，或者在发生预期外情况时调用它，然后它将在发生预期外情况时反汇编调用栈上最顶端的函数，并显示它的字节码，以及插入一个指向到引发意外情况的指令的指针。

它也可以用于查看 Python 为每个函数构建的编译后的代码对象，因为运行一个函数将会用到这些代码对象的属性。这里有一个查看 `hello()` 函数的示例：

```
>>> hello.__code__
<code object hello at 0x104e46930, file "<stdin>", line 1>
>>> hello.__code__.co_consts
(None, 'Hello, World!')
>>> hello.__code__.co_varnames
()
>>> hello.__code__.co_names
('print',)

```

代码对象在函数中可以以属性 `__code__` 来访问，并且携带了一些重要的属性：

* `co_consts` 是存在于函数体内的任意实数的元组
* `co_varnames` 是函数体内使用的包含任意本地变量名字的元组
* `co_names` 是在函数体内引用的任意非本地名字的元组

许多字节码指令 —— 尤其是那些推入到栈中的加载值，或者在变量和属性中的存储值 —— 在这些元组中的索引作为它们参数。

因此，现在我们能够理解 `hello()` 函数中所列出的字节码：

1. `LOAD_GLOBAL 0`：告诉 Python 通过 `co_names` （它是 `print` 函数）的索引 0 上的名字去查找它指向的全局对象，然后将它推入到计算栈
2. `LOAD_CONST 1`：带入 `co_consts` 在索引 1 上的字面值，并将它推入（索引 0 上的字面值是 `None`，它表示在 `co_consts` 中，因为 Python 函数调用有一个隐式的返回值 `None`，如果没有显式的返回表达式，就返回这个隐式的值 ）。
3. `CALL_FUNCTION 1`：告诉 Python 去调用一个函数；它需要从栈中弹出一个位置参数，然后，新的栈顶将被函数调用。

“原始的” 字节码 —— 是非人类可读格式的字节 —— 也可以在代码对象上作为 `co_code` 属性可用。如果你有兴趣尝试手工反汇编一个函数时，你可以从它们的十进制字节值中，使用列出 `dis.opname` 的方式去查看字节码指令的名字。

### 字节码的用处

现在，你已经了解的足够多了，你可能会想 “OK，我认为它很酷，但是知道这些有什么实际价值呢？”由于对它很好奇，我们去了解它，但是除了好奇之外，Python 字节码在几个方面还是非常有用的。

首先，理解 Python 的运行模型可以帮你更好地理解你的代码。人们都开玩笑说，C 是一种 “可移植汇编器”，你可以很好地猜测出一段 C 代码转换成什么样的机器指令。理解 Python 字节码之后，你在使用 Python 时也具备同样的能力 —— 如果你能预料到你的 Python 源代码将被转换成什么样的字节码，那么你可以知道如何更好地写和优化 Python 源代码。

第二，理解字节码可以帮你更好地回答有关 Python 的问题。比如，我经常看到一些 Python 新手困惑为什么某些结构比其它结构运行的更快（比如，为什么 `{}` 比 `dict()` 快）。知道如何去访问和阅读 Python 字节码将让你很容易回答这样的问题（尝试对比一下： `dis.dis("{}")` 与 `dis.dis("dict()")` 就会明白）。

最后，理解字节码和 Python 如何运行它，为 Python 程序员不经常使用的一种特定的编程方式提供了有用的视角：面向栈的编程。如果你以前从来没有使用过像 FORTH 或 Fator 这样的面向栈的编程语言，它们可能有些古老，但是，如果你不熟悉这种方法，学习有关 Python 字节码的知识，以及理解面向栈的编程模型是如何工作的，将有助你开拓你的编程视野。

### 延伸阅读

如果你想进一步了解有关 Python 字节码、Python 虚拟机、以及它们是如何工作的更多知识，我推荐如下的这些资源：

* [Python 虚拟机内幕](https://leanpub.com/insidethepythonvirtualmachine)，它是 Obi Ike-Nwosu 写的一本免费在线电子书，它深入 Python 解析器，解释了 Python 如何工作的细节。
* [一个用 Python 编写的 Python 解析器](http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html)，它是由 Allison Kaptur 写的一个教程，它是用 Python 构建的 Python 字节码解析器，并且它实现了运行 Python 字节码的全部构件。
* 最后，CPython 解析器是一个开源软件，你可以在 [GitHub](https://github.com/python/cpython) 上阅读它。它在文件 `Python/ceval.c` 中实现了字节码解析器。[这是 Python 3.6.4 发行版中那个文件的链接](https://github.com/python/cpython/blob/d48ecebad5ac78a1783e09b0d32c211d9754edf4/Python/ceval.c)；字节码指令是由第 1266 行开始的 `switch` 语句来处理的。

学习更多内容，参与到 James Bennett 的演讲，[有关字节的知识：理解 Python 字节码](https://us.pycon.org/2018/schedule/presentation/127/)，将在 [PyCon Cleveland 2018](https://us.pycon.org/2018/) 召开。

---

via: <https://opensource.com/article/18/4/introduction-python-bytecode>

作者：[James Bennett](https://opensource.com/users/ubernostrum) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


Sosreport：收集系统日志和诊断信息的工具

Summary: 它是一个从类 Unix 操作系统中收集系统配置详细信息和诊断信息的工具。

它是一个从类 Unix 操作系统中收集系统配置详细信息和诊断信息的工具。

# Sosreport：收集系统日志和诊断信息的工具

<img src="content_image/album_201807_08_093729btevwc3iyv23euvc.png" alt="" title="">

如果你是 RHEL 管理员，你可能肯定听说过 **Sosreport** ：一个可扩展、可移植的支持数据收集工具。它是一个从类 Unix 操作系统中收集系统配置详细信息和诊断信息的工具。当用户提出支持服务单时，他/她必须运行此工具并将由 Sosreport 工具生成的结果报告发送给 Red Hat 支持人员。然后，执行人员将根据报告进行初步分析，并尝试找出系统中的问题。不仅在 RHEL 系统上，你可以在任何类 Unix 操作系统上使用它来收集系统日志和其他调试信息。

### 安装 Sosreport

Sosreport 在 Red Hat 官方系统仓库中，因此你可以使用 Yum 或 DNF 包管理器安装它，如下所示。

```
$ sudo yum install sos

```

要么，

```
$ sudo dnf install sos

```

在 Debian、Ubuntu 和 Linux Mint 上运行：

```
$ sudo apt install sosreport

```

### 用法

安装后，运行以下命令以收集系统配置详细信息和其他诊断信息。

```
$ sudo sosreport

```

系统将要求你输入系统的一些详细信息，例如系统名称、案例 ID 等。相应地输入详细信息，然后按回车键生成报告。如果你不想更改任何内容并使用默认值，只需按回车键即可。

我的 CentOS 7 服务器的示例输出：

```
sosreport (version 3.5)

This command will collect diagnostic and configuration information from
this CentOS Linux system and installed applications.

An archive containing the collected information will be generated in
/var/tmp/sos.DiJXi7 and may be provided to a CentOS support
representative.

Any information provided to CentOS will be treated in accordance with
the published support policies at:

https://wiki.centos.org/

The generated archive may contain data considered sensitive and its
content should be reviewed by the originating organization before being
passed to any third party.

No changes will be made to system configuration.

Press ENTER to continue, or CTRL-C to quit.

Please enter your first initial and last name [server.ostechnix.local]:
Please enter the case id that you are generating this report for []:

Setting up archive ...
Setting up plugins ...
Running plugins. Please wait ...

Running 73/73: yum...
Creating compressed archive...

Your sosreport has been generated and saved in:
/var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz

The checksum is: 8f08f99a1702184ec13a497eff5ce334

Please send this file to your support representative.

```

如果你不希望系统提示你输入此类详细信息，请如下使用批处理模式。

```
$ sudo sosreport --batch

```

正如你在上面的输出中所看到的，生成了一个归档报告并保存在 `/var/tmp/sos.DiJXi7` 中。在 RHEL 6/CentOS 6 中，报告将在 `/tmp` 中生成。你现在可以将此报告发送给你的支持人员，以便他可以进行初步分析并找出问题所在。

你可能会担心或想知道报告中的内容。如果是这样，你可以通过运行以下命令来查看它：

```
$ sudo tar -tf /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz

```

要么，

```
$ sudo vim /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz

```

请注意，上述命令不会解压存档，而只显示存档中的文件和文件夹列表。如果要查看存档中文件的实际内容，请首先使用以下命令解压存档：

```
$ sudo tar -xf /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz

```

存档的所有内容都将解压当前工作目录中 `ssosreport-server.ostechnix.local-20180628171844/` 目录中。进入目录并使用 `cat` 命令或任何其他文本浏览器查看文件内容：

```
$ cd sosreport-server.ostechnix.local-20180628171844/

$ cat uptime
17:19:02 up 1:03, 2 users, load average: 0.50, 0.17, 0.10

```

有关 Sosreport 的更多详细信息，请参阅手册页。

```
$ man sosreport

```

就是这些了。希望这些有用。还有更多好东西。敬请关注！

干杯！

---

via: <https://www.ostechnix.com/sosreport-a-tool-to-collect-system-logs-and-diagnostic-information/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[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/) 荣誉推出


将你的树莓派打造成一个 Tor 中继节点

Summary: 在此教程中学习如何将你的旧树莓派打造成一个完美的 Tor 中继节点。

在此教程中学习如何将你的旧树莓派打造成一个完美的 Tor 中继节点。

# 将你的树莓派打造成一个 Tor 中继节点

>
> 在此教程中学习如何将你的旧树莓派打造成一个完美的 Tor 中继节点。
>
>
>

<img src="content_image/album_201807_08_095040irm37me7umm7721c.jpg" alt="" title="">

你是否和我一样，在第一代或者第二代树莓派发布时买了一个，玩了一段时间就把它搁置“吃灰”了。毕竟，除非你是机器人爱好者，否则一般不太可能去长时间使用一个处理器很慢的、并且内存只有 256 MB 的计算机。这并不是说你不能用它去做一件很酷的东西，但是在工作和其它任务之间，我还没有看到用一些旧的物件发挥新作用的机会。

然而，如果你想去好好利用它并且不想花费你太多的时间和资源的话，可以将你的旧树莓派打造成一个完美的 Tor 中继节点。

### Tor 中继节点是什么

在此之前你或许听说过 [Tor 项目](https://www.torproject.org/)，如果恰好你没有听说过，我简单给你介绍一下，“Tor” 是 “The Onion Router（洋葱路由器）” 的缩写，它是用来对付在线追踪和其它违反隐私行为的技术。

不论你在互联网上做什么事情，都会在你的 IP 包通过的设备上留下一些数字“脚印”：所有的交换机、路由器、负载均衡，以及目标网络记录的来自你的原始会话的 IP 地址，以及你访问的互联网资源（通常是它的主机名，[即使是在使用 HTTPS 时](https://en.wikipedia.org/wiki/Server_Name_Indication#Security_implications)）的 IP 地址。如过你是在家中上互联网，那么你的 IP 地址可以直接映射到你的家庭所在地。如果你使用了 VPN 服务（[你应该使用](https://www.linux.com/blog/2017/10/tips-secure-your-network-wake-krack)），那么你的 IP 地址映射到你的 VPN 提供商那里，而 VPN 提供商是可以映射到你的家庭所在地的。无论如何，有可能在某个地方的某个人正在根据你访问的网络和在网站上呆了多长时间来为你建立一个个人的在线资料。然后将这个资料进行出售，并与从其它服务上收集的资料进行聚合，然后利用广告网络进行赚钱。至少，这是乐观主义者对如何利用这些数据的一些看法 —— 我相信你还可以找到更多的更恶意地使用这些数据的例子。

Tor 项目尝试去提供一个解决这种问题的方案，使它们不可能（或者至少是更加困难）追踪到你的终端 IP 地址。Tor 是通过让你的连接在一个由匿名的入口节点、中继节点和出口节点组成的匿名中继链上反复跳转的方式来实现防止追踪的目的：

1. **入口节点** 只知道你的 IP 地址和中继节点的 IP 地址，但是不知道你最终要访问的目标 IP 地址
2. **中继节点** 只知道入口节点和出口节点的 IP 地址，以及既不是源也不是最终目标的 IP 地址
3. **出口节点** 仅知道中继节点和最终目标地址，它是在到达最终目标地址之前解密流量的节点

中继节点在这个交换过程中扮演一个关键的角色，因为它在源请求和目标地址之间创建了一个加密的障碍。甚至在意图偷窥你数据的对手控制了出口节点的情况下，在他们没有完全控制整个 Tor 中继链的情况下仍然无法知道请求源在哪里。

只要存在大量的中继节点，你的隐私被会得到保护 —— 这就是我为什么真诚地建议你，如果你的家庭宽带有空闲的时候去配置和运行一个中继节点。

#### 考虑去做 Tor 中继时要记住的一些事情

一个 Tor 中继节点仅发送和接收加密流量 —— 它从不访问任何其它站点或者在线资源，因此你不用担心有人会利用你的家庭 IP 地址去直接浏览一些令人担心的站点。话虽如此，但是如果你居住在一个提供<ruby> 匿名增强服务 <rt>  anonymity-enhancing services </rt></ruby>是违法行为的司法管辖区的话，那么你还是不要运营你的 Tor 中继节点了。你还需要去查看你的互联网服务提供商的服务条款是否允许你去运营一个 Tor 中继。

### 需要哪些东西

* 一个带完整外围附件的树莓派（任何型号/代次都行）
* 一张有 [Raspbian Stretch Lite](https://www.raspberrypi.org/downloads/raspbian/) 的 SD 卡
* 一根以太网线缆
* 一根用于供电的 micro-USB 线缆
* 一个键盘和带 HDMI 接口的显示器（在配置期间使用）

本指南假设你已经配置好了你的家庭网络连接的线缆或者 ADSL 路由器，它用于运行 NAT 转换（它几乎是必需的）。大多数型号的树莓派都有一个可用于为树莓派供电的 USB 端口，如果你只是使用路由器的 WiFi 功能，那么路由器应该有空闲的以太网口。但是在我们将树莓派设置为一个“配置完不管”的 Tor 中继之前，我们还需要一个键盘和显示器。

### 引导脚本

我改编了一个很流行的 Tor 中继节点引导脚本以适配树莓派上使用 —— 你可以在我的 GitHub 仓库 <https://github.com/mricon/tor-relay-bootstrap-rpi> 上找到它。你用它引导树莓派并使用缺省的用户 `pi` 登入之后，做如下的工作：

```
sudo apt-get install -y git
git clone https://github.com/mricon/tor-relay-bootstrap-rpi
cd tor-relay-bootstrap-rpi
sudo ./bootstrap.sh

```

这个脚本将做如下的工作：

1. 安装最新版本的操作系统更新以确保树莓派打了所有的补丁
2. 将系统配置为无人值守自动更新，以确保有可用更新时会自动接收并安装
3. 安装 Tor 软件
4. 告诉你的 NAT 路由器去转发所需要的端口（端口一般是 443 和 8080，因为这两个端口最不可能被互联网提供商过滤掉）上的数据包到你的中继节点

脚本运行完成后，你需要去配置 `torrc` 文件 —— 但是首先，你需要决定打算贡献给 Tor 流量多大带宽。首先，在 Google 中输入 “[Speed Test](https://www.google.com/search?q=speed+test)”，然后点击 “Run Speed Test” 按钮。你可以不用管 “Download speed” 的结果，因为你的 Tor 中继能处理的速度不会超过最大的上行带宽。

所以，将 “Mbps upload” 的数字除以 8，然后再乘以 1024，结果就是每秒多少 KB 的宽带速度。比如，如果你得到的上行带宽是 21.5 Mbps，那么这个数字应该是：

```
21.5 Mbps / 8 * 1024 = 2752 KBytes per second

```

你可以限制你的中继带宽为那个数字的一半，并允许突发带宽为那个数字的四分之三。确定好之后，使用喜欢的文本编辑器打开 `/etc/tor/torrc` 文件，调整好带宽设置。

```
RelayBandwidthRate 1300 KBytes
RelayBandwidthBurst 2400 KBytes

```

当然，如果你想更慷慨，你可以将那几个设置的数字调的更大，但是尽量不要设置为最大的出口带宽 —— 如果设置的太高，它会影响你的日常使用。

你打开那个文件之后，你应该去设置更多的东西。首先是昵称 —— 只是为了你自己保存记录，第二个是联系信息，只需要一个电子邮件地址。由于你的中继是运行在无人值守模式下的，你应该使用一个定期检查的电子邮件地址 —— 如果你的中继节点离线超过 48 个小时，你将收到 “Tor Weather” 服务的告警信息。

```
Nickname myrpirelay
ContactInfo you@example.com

```

保存文件并重引导系统去启动 Tor 中继。

### 测试它确认有 Tor 流量通过

如果你想去确认中继节点的功能，你可以运行 `arm` 工具：

```
sudo -u debian-tor arm

```

它需要一点时间才显示，尤其是在老板子上。它通常会给你显示一个表示入站和出站流量（或者是错误信息，它将有助于你去排错）的柱状图。

一旦你确信它运行正常，就可以将键盘和显示器拔掉了，然后将树莓派放到地下室，它就可以在那里悄悄地呆着并到处转发加密的比特了。恭喜你，你已经帮助去改善隐私和防范在线的恶意跟踪了！

通过来自 Linux 基金会和 edX 的免费课程 ["Linux 入门"](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)  来学习更多的 Linux 知识。

---

via: <https://www.linux.com/blog/intro-to-linux/2018/6/turn-your-raspberry-pi-tor-relay-node>

作者：[Konstantin Ryabitsev](https://www.linux.com/users/mricon) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


迁移到 Linux：使用 sudo

Summary: sudo 机制可以让你轻松以普通用户偶尔执行管理任务。让我们来学习一下。

sudo 机制可以让你轻松以普通用户偶尔执行管理任务。让我们来学习一下。

# 迁移到 Linux：使用 sudo

>
> sudo 机制可以让你轻松以普通用户偶尔执行管理任务。让我们来学习一下。
>
>
>

<img src="content_image/album_201807_09_180426anjij9nn8tjni7w7.jpg" alt="" title="">

本文是我们关于迁移到 Linux 的系列文章的第五篇。如果你错过了之前的那些，你可以在这里赶上：

* [第1部分 - 入门介绍](/article-9212-1.html)
* [第2部分 - 磁盘、文件和文件系统](/article-9213-1.html)
* [第3部分 - 图形操作环境](/article-9293-1.html)
* [第4部分 - 命令行](/article-9565-1.html)

你可能一直想了解 Linux。也许它在你的工作场所使用，如果你每天使用它，你的工作效率会更高。或者，也许你想在家里的某些计算机上安装 Linux。无论是什么原因，这一系列文章都是为了让过渡更容易。

与许多其他操作系统一样，Linux 支持多用户。它甚至支持多个用户同时登录。

用户帐户通常会被分配一个可以存储文件的家目录。通常这个家目录位于：

```
/home/<login name>

```

这样，每个用户都有存储自己的文档和其他文件的独立位置。

### 管理任务

在传统的 Linux 安装中，常规用户帐户无权在系统上执行管理任务。典型的安装 Linux 的系统会要求用户以管理员身份登录以执行某些任务，而不是为每个用户分配权限以执行各种任务。

Linux 上的管理员帐户称为 root。

### Sudo 解释

从历史上看，要执行管理任务，必须以 root 身份登录，执行任务，然后登出。这个过程有点乏味，所以很多人以 root 登录并且整天都以管理员身份工作。这种做法可能会导致灾难性的后果，例如，意外删除系统中的所有文件。当然，root 用户可以做任何事情，因此没有任何保护措施可以防止有人意外地执行影响很大的操作。

创建 `sudo` 工具是为了使你更容易以常规用户帐户登录，偶尔以 root 身份执行管理任务，而无需登录、执行任务然后登出。具体来说，`sudo` 允许你以不同的用户身份运行命令。如果你未指定特定用户，则假定你指的是 root 用户。

`sudo` 可以有复杂的设置，允许用户有权限使用 `sudo` 运行某些命令，而其他的不行。通常，安装的桌面系统会使创建的第一个帐户在 `sudo` 中有完全的权限，因此你作为主要用户可以完全管理 Linux 安装。

### 使用 Sudo

某些安装 Linux 的系统设置了 `sudo`，因此你仍需要知道 root 帐户的密码才能执行管理任务。其他人，设置 `sudo` 输入自己的密码。这里有不同的哲学。

当你尝试在图形环境中执行管理任务时，通常会打开一个要求输入密码的对话框。输入你自己的密码（例如，在 Ubuntu 上）或 root 帐户的密码（例如，Red Hat）。

当你尝试在命令行中执行管理任务时，它通常只会给你一个 “permission denied” 错误。然后你在前面用 `sudo` 重新运行命令。例如：

```
systemctl start vsftpd
Failed to start vsftpd.service: Access denied

sudo systemctl start vsftpd
[sudo] password for user1:

```

### 何时使用 Sudo

以 root 身份运行命令（在 `sudo` 或其他情况下）并不总是解决权限错误的最佳解决方案。虽然将以 root 身份运行会消除 “permission denied” 错误，但有时最好寻找根本原因而不是仅仅解决症状。有时文件拥有错误的所有者和权限。

当你在尝试一个需要 root 权限来执行操作的任务或者程序时使用 `sudo`。如果文件恰好由另一个用户（包括 root 用户）拥有，请不要使用 `sudo`。在第二种情况下，最好正确设置文件的权限。

通过 Linux 基金会和 edX 的免费[“Linux 介绍”](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)课程了解有关 Linux 的更多信息。

---

via: <https://www.linux.com/blog/learn/2018/3/migrating-linux-using-sudo>

作者：[John Bonesio](https://www.linux.com/users/johnbonesio) 选题：[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/) 荣誉推出


五个最热门的开源机器学习 JavaScript 框架

# 五个最热门的开源机器学习 JavaScript 框架

>
> 如果你是一位想要深入机器学习的 JavaScript 程序员或想成为一位使用 JavaScript 的机器学习专家，那么这些开源框架也许会吸引你。
>
>
>

<img src="content_image/album_201807_09_182213tquw1qihuyf5cnwq.jpg" alt="" title="">

开源工具的涌现使得开发者能够更加轻松地开发应用，这一点使机器学习领域本身获得了极大增长。（例如，AndreyBu，他来自德国，在机器学习领域拥有五年以上的经验，他一直在使用各种各样的开源框架来创造富有魅力的机器学习项目。）

虽然 Python 是绝大多数的机器学习框架所采用的语言，但是 JavaScript 也并没有被抛下。JavaScript 开发者可以在浏览器中使用各种框架来训练和部署机器学习模型。

下面是 JavaScript 中最热门五个机器学习框架

### 1、 TensorFlow.js

[TensorFlow.js](https://js.tensorflow.org/) 是一个开源库，它使你能在浏览器中完整地运行机器学习程序，它是 Deeplearn.js 的继承者，Deeplearn.js 不再更新了。TensorFlow.js 在 Deeplearn.js 功能的基础上进行了改善，使你能够充分利用浏览器，得到更加深入的机器学习经验。

通过这个开源库，你可以在浏览器中使用有各种功能的、直观的 API 来定义、训练和部署模型。除此之外，它自动提供 WebGL 和 Node.js 的支持。

如果您有了一个已经训练过的模型，你想要导入到浏览器中。TensorFlow.js 可以让你做到这一点，你也可以在不离开浏览器的情况下重新训练已有的模型。

### 2、 机器学习工具库

现在有很多在浏览器中提供广泛的机器学习功能的资源型开源工具，这个[机器学习工具库](https://github.com/mljs/ml)就是这些开源工具的集合。这个工具库为好几种机器学习算法提供支持，包括非监督式学习、监督式学习、数据处理、人工神经网络（ANN）、数学和回归。

如果你以前使用 Python，现在想找类似于 Scikit-learn 的，能在浏览器中使用 JavaScript 进行机器学习的工具，这套工具会满足你的要求。

### 3、 Keras.js

[Keras.js](https://transcranial.github.io/keras-js/#/) 是另外一个热门的开源框架，它使你能够在浏览器中运行机器学习模型，它使用 WebGL 来提供 GPU 模式的支持。如果你有使用 Node.js 的模型，你就只能在 GPU 模式下运行它。Keras.js 还为使用任意后端框架的模型训练提供支持，例如 Microsoft Cognitive Toolkit (CNTK) 。

一些 Keras 模型可以部署在客户端浏览器上，包括 Inception v3 (训练在 ImageNet 上)，50 层冗余网络(训练在 ImageNet 上)，和卷积变化自动编码器(训练在 MNIST 上)。

### 4、 Brain.js

机器学习里的概念非常重要，它可能会使刚开始进入这个领域的人们气馁，这个领域里的学术用语和专业词汇可能会使初学者感到崩溃，而解决以上问题的能力就是 [Brain.js](https://github.com/BrainJS/brain.js) 的优势所在。它是开源的，基于 JavaScript 的框架，简化了定义、训练和运行神经网络的流程。

如果你是一个 JavaScript 开发者，并且在机器学习领域是完全的新手，Brain.js 能减低你学习的难度曲线。它可以和 Node.js 一起使用，或者运行在客户端浏览器里来训练机器学习模型。Brain.js 支持部分类型的神经网络，包括前馈式网络、Ellman 网络，和门循环单元网络。

### 5、 STDLib

[STDLib](https://stdlib.io/) 是一个基于 JavaScript 和 Node.js 应用的开源库，如果您正在寻找一种在浏览器中运行，支持科学和数字化的基于 web 的机器学习应用，STDLib 能满足你的需要。

这个库能提供全面而先进的数学和统计学上的功能，来帮助你构建高性能的机器学习模型。你同样也可以使用它丰富的功能来构建应用程序和其他的库。除此之外，如果你想要一个数据可视化和探索性数据分析的框架 —— STDLib，你，值得拥有。

### 总结

如果你是一个 JavaScript 开发者，并且打算深入研究令人兴奋的机器学习世界，或者说，你是一个机器学习方面的专家，打算开始尝试使用 JavaScript ，那么上述的开源框架会激起您的兴趣。

你有知道其他的，提供在浏览器里运行机器学习功能的开源库吗？请在下面的评论区里告诉我们。

---

via: <https://opensource.com/article/18/5/machine-learning-javascript-frameworks>

作者：[Dr.Michael J.Garbade](https://opensource.com/users/drmjg) 选题：[lujun9972](https://github.com/lujun9972) 译者：[hopefully2333](https://github.com/hopefully2333) 校对：[wxy](https://github.com/wxy)

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


3 款 Linux 桌面的日记程序

Summary: 用轻量、灵活的数字日记工具来记录你的活动。

用轻量、灵活的数字日记工具来记录你的活动。

# 3 款 Linux 桌面的日记程序

>
> 用轻量、灵活的数字日记工具来记录你的活动。
>
>
>

保持记日记的习惯，即使是不定期地记，也可以带来很多好处。这不仅是治疗和宣泄，而且还可以很好地记录你所在的位置以及你去过的地方。它可以帮助你展示你在生活中的进步，并提醒你自己做对了什么，做错了什么。

无论你记日记的原因是什么，都有多种方法可以做到这一点。你可以使用传统的笔和纸，也可以使用基于 Web 的程序，或者你可以使用[简单的文本文件](https://plaintextproject.online/2017/07/19/journal.html)。

另一种选择是使用专门的日记程序。Linux 桌面有几种非常灵活且非常有用的日记工具。我们来看看其中的三个。

### RedNotebook

在这里描述的三个日记程序中，[RedNotebook](http://rednotebook.sourceforge.net) 是最灵活的。大部分灵活性来自其模板。这些模板可让你记录个人想法或会议记录、计划旅程或记录电话。你还可以编辑现有模板或创建自己的模板。

你可以使用与 Markdown 非常相似的标记语言来记录日记。你还可以在日记中添加标签，以便于查找。只需在程序的左窗格中单击或输入标记，右窗格中将显示相应日记的列表。

最重要的是，你可以将全部、部分或仅一个日记导出为纯文本、HTML、LaTeX 或 PDF。在执行此操作之前，你可以通过单击工具栏上的“预览”按钮了解日志在 PDF 或 HTML 中的显示情况。

总的来说，RedNotebook 是一款易于使用且灵活的程序。它需要习惯，但一旦你这样做，它是一个有用的工具。

### Lifeograph

[Lifeograph](http://lifeograph.sourceforge.net/wiki/Main_Page) 与 RedNotebook 有相似的外观和感觉。它没有那么多功能，但 Lifeograph 也够了。

该程序通过保持简单和整洁性来简化记日记这件事。你有一个很大的区域可以记录，你可以为日记添加一些基本格式。这包括通常的粗体和斜体，以及箭头和高亮显示。你可以在日记中添加标签，以便更好地组织和查找它们。

Lifeograph 有一个我觉得特别有用的功能。首先，你可以创建多个日记 - 例如，工作日记和个人日记。其次是密码保护你的日记的能力。虽然该网站声称 Lifeograph 使用“真正的加密”，但没有关于它的详细信息。尽管如此，设置密码仍然会阻止大多数窥探者。

### Almanah Diary

[Almanah Diary](https://wiki.gnome.org/Apps/Almanah_Diary) 是另一种非常简单的日记工具。但不要因为它缺乏功能就丢掉它。虽简单，但足够。

有多简单？它差不多只是一个包含了日记输入和日历的区域而已。你可以做更多的事情 —— 比如添加一些基本格式（粗体、斜体和下划线）并将文本转换为超链接。Almanah 还允许你加密日记。

虽然有一个可以将纯文本文件导入该程序的功能，但我无法使其正常工作。尽管如此，如果你喜欢一个简单，能够快速记日记的软件，那么 Almanah 日记值得一看。

### 命令行怎么样？

如果你不想用 GUI 则可以不必用。命令行是保存日记的绝佳选择。

我尝试过并且喜欢的是 [jrnl](http://maebert.github.com/jrnl/)。或者你可以使用[此方案](http://tamilinux.wordpress.com/2007/07/27/writing-short-notes-and-diaries-from-the-cli/)，它使用命令行别名格式化并将日记保存到文本文件中。

你有喜欢的日记程序吗？请留下评论，随意分享。

---

via: <https://opensource.com/article/18/6/linux-journaling-applications>

作者：[Scott Nesbitt](https://opensource.com/users/scottnesbitt) 选题：[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/) 荣誉推出


迁移到 Linux：安装软件

# 迁移到 Linux：安装软件

>
> 所有的 Linux 打包系统和工具都会让人迷惑，但是这篇面向初学者的教程可以帮助你搞明白。
>
>
>

如你所见，众所瞩目的 Linux 已经用在互联网，以及 Arduino、Beagle 和树莓派主板等设备上，或许你正在考虑是时候尝试一下 Linux 了。本系列将帮助你成功过渡到 Linux。如果你错过了本系列的早期文章，可以在这里找到它们：

* [第1部分 - 入门介绍](/article-9212-1.html)
* [第2部分 - 磁盘、文件和文件系统](/article-9213-1.html)
* [第3部分 - 图形操作环境](/article-9293-1.html)
* [第4部分 - 命令行](/article-9565-1.html)
* [第5部分 - 使用 sudo](/article-9819-1.html)

### 安装软件

要在你的计算机上获得新软件，通常的方法是从供应商处获得软件产品，然后运行一个安装程序。过去，软件产品会出现在像 CD-ROM 或 DVD 一样的物理媒介上，而现在我们经常从互联网上下载软件产品。

使用 Linux，安装软件就像在你的智能手机上安装一样。如同你的手机应用商店一样，在 Linux 上有个提供开源软件工具和程序的<ruby> 中央仓库 <rt>  central repository </rt></ruby>，几乎任何你想要的程序都会出现在可用软件包列表中以供你安装。

每个程序并不需要运行单独的安装程序，而是你可以使用 Linux 发行版附带的软件包管理工具。（这里说的 Linux 发行版就是你安装的 Linux，例如 Ubuntu、Fedora、Debian 等）每个发行版在互联网上都有它自己的集中存储库（称为仓库），它们存储了数千个预先构建好的应用程序。

你可能会注意到，在 Linux 上安装软件有几种例外情况。有时候，你仍然需要去供应商那里获取他们的软件，因为该程序不存在于你的发行版的中央仓库中。当软件不是开源和/或自由软件的时候，通常就是这种情况。

另外请记住，如果你想要安装一个不在发行版仓库中的程序时，事情就不是那么简单了，即使你正在安装自由及开源程序。这篇文章没有涉及到这些更复杂的情况，请遵循在线的指引。

有了所有的 Linux 包管理系统和工具，接下来干什么可能仍然令人困惑。本文应该有助于澄清一些事情。

### 包管理

目前在 Linux 发行版中有几个相互竞争的用于管理、安装和删除软件的包管理系统。每个发行版都选择使用了一个<ruby> 包管理工具 <rt>  package management tools </rt> <rt> </rt></ruby>。Red Hat、Fedora、CentOS、Scientific Linux、SUSE 等使用 Red Hat 包管理（RPM）。Debian、Ubuntu、Linux Mint 等等都使用 Debian 包管理系统，简称 DPKG。还有一些其它包管理系统，但 RPM 和 DPKG 是最常见的。

*图 1: Package installers*

无论你使用的软件包管理是什么，它们通常都是一组构建于另外一种工具之上的工具（图 1）。最底层是一个命令行工具，它可以让你做任何与安装软件相关的一切工作。你可以列出已安装的程序、删除程序、安装软件包文件等等。

这个底层工具并不总是最方便使用的，所以通常会有一个命令行工具，它可以使用单个命令在发行版的中央仓库中找到软件包，并下载和安装它以及任何依赖项。最后，通常会有一个<ruby> 图形应用程序 <rt>  graphical application </rt> <rt> </rt></ruby>，可以让你使用鼠标选择任何想要的内容，然后单击 “install” 按钮即可。

*图 2: PackageKit*

对于基于 Red Hat 的发行版，包括 Fedora、CentOS、Scientific Linux 等，它们的底层工具是 rpm，高级工具叫做 dnf（在旧系统上是 yum）。图形安装程序称为 PackageKit（图 2），它可能在系统管理菜单下显示名字为 “Add/Remove Software（添加/删除软件）”。

*图 3: Ubuntu Software*

对于基于 Debian 的发行版，包括 Debian、Ubuntu、Linux Mint、Elementary OS 等，它们的底层命令行工具是 dpkg，高级工具称为 apt。在 Ubuntu 上管理已安装软件的图形工具是 Ubuntu Software（图 3）。对于 Debian 和 Linux Mint，图形工具称为<ruby> 新立得 <rt>  Synaptic </rt></ruby>，它也可以安装在 Ubuntu 上。

你也可以在 Debian 相关发行版上安装一个基于文本的图形化工具 aptitude。它比 <ruby> 新立得 <rt>  synaptic </rt></ruby>更强大，并且即使你只能访问命令行也能工作。如果你想通过各种选项进行各种“骚”操作，你可以试试这个，但它使用起来比新立得更复杂。其它发行版也可能有自己独特的工具。

### 命令行工具

在 Linux 上安装软件的在线说明通常描述了在命令行中键入的命令。这些说明通常更容易理解，并且将命令复制粘贴到命令行窗口中，可以在不出错的情况下一步步进行。这与下面的说明相反：“打开这个菜单，选择这个程序，输入这个搜索模式，点击这个标签，选择这个程序，然后点击这个按钮”，这经常让你在各种操作中迷失。

有时你正在使用的 Linux 没有图形环境，因此熟悉从命令行安装软件包是件好事。表 1 和表 2 列出了基于 RPM 和 DPKG 系统的一下常见操作及其相关命令。

请注意 SUSE，它像 RedHat 和 Fedora 一样使用 RPM，却没有 dnf 或 yum。相反，它使用一个名为 zypper 的程序作为高级命令行工具。其他发行版也可能有不同的工具，例如 Arch Linux 上的 pacman 或 Gentoo 上的 emerge。有很多包管理工具，所以你可能需要查找哪个适用于你的发行版。

这些技巧应该能让你更好地了解如何在新的 Linux 中安装程序，以及更好地了解 Linux 中各种软件包管理方式如何相互关联。

通过 Linux 基金会和 edX 的免费 [“Linux 入门”](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)课程了解有关 Linux 的更多信息。

---

via: <https://www.linux.com/blog/learn/2018/3/migrating-linux-installing-software>

作者：[JOHN BONESIO](https://www.linux.com/users/johnbonesio) 译者：[MjSeven](https://github.com/MjSeven) 校对：[pityonline](https://github.com/pityonline), [wxy](https://github.com/wxy)

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


如何在 Arch Linux 中查找已安装的专有软件包？

Summary: 它将基于 Arch 系统中的所有安装包与 Parabola 的软件包 blacklist 和 aur-blacklist 进行比较，然后显示出你的斯托曼自由指数（“自由/总计”比分）。

# 如何在 Arch Linux 中查找已安装的专有软件包？

你是狂热的自由软件支持者吗？你目前在使用任何基于 Arch 的 Linux 发行版吗？我有一个小小的提示送给你！现在，你可以轻松地在 Arch Linux 及其变体（如 Antergos、Manjaro Linux 等）中找到已安装的专有软件包。你无需在已安装软件包的网站中参考其许可细节，也无需使用任何其它外部工具来查明软件包是自由的还是专有的。（LCTT 译注：其实下面还是借助了一个外部程序）

### 在 Arch Linux 中查找已安装的专有软件包

一位开发人员开发了一个名为 “[Absolutely Proprietary](https://github.com/vmavromatis/absolutely-proprietary)” 的实用程序，它是一种用于基于 Arch 发行版的专有软件包检测器。它将基于 Arch 系统中的所有安装包与 Parabola 的软件包 [blacklist](https://git.parabola.nu/blacklist.git/plain/blacklist.txt) 和 [aur-blacklist](https://git.parabola.nu/blacklist.git/plain/aur-blacklist.txt) 进行比较，然后显示出你的<ruby> 斯托曼自由指数 <rt>  Stallman Freedom Index </rt></ruby>（“自由/总计”比分）。此外，你可以将该列表保存到文件中，并与其他系统/用户共享或比较。

在安装之前，确保你安装了 Python 和 Git。

然后，`git clone` 仓库：

```
git clone https://github.com/vmavromatis/absolutely-proprietary.git

```

这条命令将会下载所有内容到你当前工作目录中的 `absolutely-proprietary` 目录。

进入此目录：

```
cd absolutely-proprietary

```

接着，使用以下命令查找已安装的专有软件：

```
python main.py

```

这条命令将会下载 `blacklist.txt`、`aur-blacklist.txt`，并将本地已安装的软件包与远程软件包进行比较并显示其指数。

以下是在我的 Arch Linux 桌面的示例输出：

```
Retrieving local packages (including AUR)...
Downloading https://git.parabola.nu/blacklist.git/plain/blacklist.txt
Downloading https://git.parabola.nu/blacklist.git/plain/aur-blacklist.txt
Comparing local packages to remote...
=============================================
47 ABSOLUTELY PROPRIETARY PACKAGES INSTALLED
=============================================

Your GNU/Linux is infected with 47 proprietary packages out of 1370 total installed.
Your Stallman Freedom Index is 96.57

+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| Name | Status | Libre Alternatives | Description |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| chromium-pepper-flash | nonfree | | proprietary Google Chrome EULA, missing sources |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| faac | nonfree | | [FIXME:description] is a GPL'ed package, but has non free code that can't be distributed und|
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| libunrar | nonfree | | part of nonfree unrar, Issue442 |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| opera | nonfree | | nonfree, nondistributable, built from binary installers, etc |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| shutter | nonfree | | need registered user to download (and access website) the source code and depends perl-net-d|
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| ttf-ms-fonts | nonfree | | |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| ttf-ubuntu-font-family | nonfree | | Ubuntu font license considered non-free by DFSG and Fedora |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| unace | nonfree | | license forbids making competing ACE archivers from unace |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| unrar | nonfree | unar | |
| | | fsf | |
| | | unrar | |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| virtualbox | nonfree | | contains BIOS which needs a nonfree compiler to build from source (OpenWatcom compiler), doe|
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+
| wordnet | nonfree | | |
+------------------------|---------|--------------------|---------------------------------------------------------------------------------------------+

Save list to file? (Y/n)

```

如你所见，我的系统中有 47 个专有软件包。就像我说的那样，我们可以将它保存到文件中稍后查看。为此，当提示你将列表保存在文件时，请按 `y`。然后按 `y` 接受默认值，或按 `n` 以你喜欢的格式和位置来保存它。

```
Save list to file? (Y/n) y
Save as markdown table? (Y/n) y
Save it to (/tmp/tmpkuky_082.md): y
The list is saved at /home/sk/absolutely-proprietary/y.md

You can review it from the command line
using the "less -S /home/sk/absolutely-proprietary/y.md"
or, if installed, the "most /home/sk/absolutely-proprietary/y.md" commands

```

你可能已经注意到，我只有 **nonfree** 包。它还会显示另外两种类型的软件包，例如 semifree、 uses-nonfree。

* **nonfree**：这个软件包是公然的非自由软件。
* **semifree**：这个软件包大部分是自由的，但包含一些非自由软件。
* **uses-nonfree**：这个软件包依赖、推荐或不恰当地与其他自由软件或服务集成。

该使用程序的另一个显著特点是它不仅显示了专有软件包，而且还显示这些包的替代品。

希望这有些帮助。我很快就会在这里提供另一份有用的指南。敬请关注！

干杯!

资源：

* [Absolutely Proprietary](https://github.com/vmavromatis/absolutely-proprietary)

---

via: <https://www.ostechnix.com/find-installed-proprietary-packages-arch-linux/>

作者：[SK](https://www.ostechnix.com/author/sk/) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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