在 Linux 命令行中使用 ls 列出文件的技巧

Summary: 学习一些 Linux ls 命令最有用的变化。

学习一些 Linux ls 命令最有用的变化。

>
> 学习一些 Linux `ls` 命令最有用的变化。
>
>
>

![](/data/attachment/album/201810/22/082802j7mkmqx444q44n67.png)

我在 Linux 中最先学到的命令之一就是 `ls`。了解系统中文件所在目录中的内容非常重要。能够查看和修改不仅仅是一些文件还有所有文件也很重要。

我的第一个 Linux 备忘录是[单页 Linux 手册](http://hackerspace.cs.rutgers.edu/library/General/One_Page_Linux_Manual.pdf)，它于 1999 年发布，成了我的首选参考资料。当我开始探索 Linux 时，我把它贴在桌子上并经常参考它。它在第一页第一列的底部介绍了 `ls -l` 列出文件的命令。

之后，我将学习这个最基本命令的其它迭代。通过 `ls` 命令，我开始了解 Linux 文件权限的复杂性，以及哪些是我的文件，哪些需要 root 或者 sudo 权限来修改。随着时间的推移，我习惯了使用命令行，虽然我仍然使用 `ls -l` 来查找目录中的文件，但我经常使用 `ls -al`，这样我就可以看到可能需要更改的隐藏文件，比如那些配置文件。

根据 Eric Fischer 在 [Linux 文档项目](http://www.tldp.org/LDP/LG/issue48/fischer.html)中关于 `ls` 命令的文章，该命令的起源可以追溯到 1961 年 MIT 的<ruby> 相容分时系统 <rt>  Compatible Time-Sharing System </rt></ruby>（CTSS）上的 `listf` 命令。当 CTSS 被 [Multics](https://en.wikipedia.org/wiki/Multics) 代替时，命令变为 `list`，并有像 `list -all` 的开关。根据[维基百科](https://en.wikipedia.org/wiki/Ls)，`ls` 出现在 AT&T Unix 的原始版本中。我们今天在 Linux 系统上使用的 `ls` 命令来自 [GNU Core Utilities](http://www.gnu.org/s/coreutils/)。

大多数时候，我只使用几个迭代的命令。我通常用 `ls` 或 `ls -al` 查看目录内容，但是你还应该熟悉许多其它选项。

`ls -l` 提供了一个简单的目录列表：

![](/data/attachment/album/201810/22/082805mn77ffncfrf7d16n.png)

在我的 Fedora 28 系统的手册页中，我发现 `ls` 还有许多其它选项，所有这些选项都提供了有关 Linux 文件系统的有趣且有用的信息。通过在命令提示符下输入 `man ls`，我们可以开始探索其它一些选项：

![](/data/attachment/album/201810/22/082805faz49uk88rigik38.png)

要按文件大小对目录进行排序，请使用 `ls -lS`：

![](/data/attachment/album/201810/22/082805e323fgnynmg2q2q3.png)

要以相反的顺序列出内容，请使用 `ls -lr`：

![](/data/attachment/album/201810/22/082806sy1y6kpyr8w8168f.png)

要按列列出内容，请使用 `ls -c`：

![](/data/attachment/album/201810/22/082806noxnab5xnc5nncwx.png)

`ls -al` 提供了同一目录中所有文件的列表：

![](/data/attachment/album/201810/22/082806dd608hdpeheudw11.png)

以下是我认为有用且有趣的一些其它选项：

* 仅列出目录中的 .txt 文件：`ls *.txt`
* 按文件大小列出：`ls -s`
* 按时间和日期排序：`ls -t`
* 按扩展名排序：`ls -X`
* 按文件大小排序：`ls -S`
* 带有文件大小的长格式：`ls -ls`

要生成指定格式的目录列表并将其定向到文件供以后查看，请输入 `ls -al > mydirectorylist`。最后，我找到的一个更奇特的命令是 `ls -R`，它提供了计算机上所有目录及其内容的递归列表。

有关 `ls` 命令的所有迭代的完整列表，请参阅 [GNU Core Utilities](https://www.gnu.org/software/coreutils/manual/html_node/ls-invocation.html#ls-invocation)。

---

via: <https://opensource.com/article/18/10/ls-command>

作者：[Don Watkins](https://opensource.com/users/don-watkins) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[pityonline](https://github.com/pityonline)

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


PyTorch 1.0 预览版发布：Facebook 最新 AI 开源框架

Facebook 在人工智能项目中广泛使用自己的开源 AI 框架 PyTorch，最近，他们已经发布了 PyTorch 1.0 的预览版本。

如果你尚不了解，[PyTorch](https://pytorch.org/) 是一个基于 Python 的科学计算库。

PyTorch 利用 [GPU 超强的运算能力](https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units) 来实现复杂的 [张量](https://en.wikipedia.org/wiki/Tensor) 计算 和 [深度神经网络](https://www.techopedia.com/definition/32902/deep-neural-network)。 因此， 它被世界各地的研究人员和开发人员广泛使用。

这一新的可以投入使用的 [预览版](https://code.fb.com/ai-research/facebook-accelerates-ai-development-with-new-partners-and-production-capabilities-for-pytorch-1-0) 已于 2018 年 10 月 2 日周二在旧金山 [The Midway](https://www.themidwaysf.com/) 举办的 [PyTorch 开发人员大会](https://pytorch.fbreg.com/) 宣布。

### PyTorch 1.0 候选版本的亮点

![PyTorhc is Python based open source AI framework from Facebook](/data/attachment/album/201810/22/084432rtvtitfvt8teo5v0.jpg)

候选版本中的一些主要新功能包括：

#### 1、 JIT

JIT 是一个编译工具集，使研究和生产更加接近。 它包含一个基于 Python 语言的叫做 Torch Script 的脚本语言，也有能使现有代码与它自己兼容的方法。

#### 2、 全新的 torch.distributed 库: “C10D”

“C10D” 能够在不同的后端上启用异步操作， 并在较慢的网络上提高性能。

#### 3、 C++ 前端 (实验性功能)

虽然它被特别提到是一个不稳定的 API （估计是在预发行版中）， 这是一个 PyTorch 后端的纯 C++ 接口， 遵循 API 和建立的 Python 前端的体系结构，以实现高性能、低延迟的研究和开发直接安装在硬件上的 C++ 应用程序。

想要了解更多，可以在 GitHub 上查看完整的 [更新说明](https://github.com/pytorch/pytorch/releases/tag/v1.0rc0)。

第一个 PyTorch 1.0 的稳定版本将在夏季发布。（LCTT 译注：此信息可能有误）

### 在 Linux 上安装 PyTorch

为了安装 PyTorch v1.0rc0， 开发人员建议使用 [conda](https://conda.io/)， 同时也可以按照[本地安装页面](https://pytorch.org/get-started/locally/)所示，使用其他方法可以安装，所有必要的细节详见文档。

#### 前提

* Linux
* Pip
* Python
* [CUDA](https://www.pugetsystems.com/labs/hpc/How-to-install-CUDA-9-2-on-Ubuntu-18-04-1184/) (对于使用 Nvidia GPU 的用户)

我们已经知道[如何安装和使用 Pip](https://itsfoss.com/install-pip-ubuntu/)，那就让我们来了解如何使用 Pip 安装 PyTorch。

请注意，PyTorch 具有 GPU 和仅限 CPU 的不同安装包。你应该安装一个适合你硬件的安装包。

#### 安装 PyTorch 的旧版本和稳定版

如果你想在 GPU 机器上安装稳定版（0.4 版本），使用：

```
pip install torch torchvision
```

使用以下两个命令，来安装仅用于 CPU 的稳定版：

```
pip install http://download.pytorch.org/whl/cpu/torch-0.4.1-cp27-cp27mu-linux_x86_64.whl
pip install torchvision
```

#### 安装 PyTorch 1.0 候选版本

使用如下命令安装 PyTorch 1.0 RC GPU 版本：

```
pip install torch_nightly -f https://download.pytorch.org/whl/nightly/cu92/torch_nightly.html
```

如果没有GPU，并且更喜欢使用 仅限 CPU 版本，使用如下命令：

```
pip install torch_nightly -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html
```

#### 验证 PyTorch 安装

使用如下简单的命令，启动终端上的 python 控制台：

```
python
```

现在，按行输入下面的示例代码以验证您的安装：

```
from __future__ import print_function
import torch
x = torch.rand(5, 3)
print(x)
```

你应该得到如下输出：

```
tensor([[0.3380, 0.3845, 0.3217],
 [0.8337, 0.9050, 0.2650],
 [0.2979, 0.7141, 0.9069],
 [0.1449, 0.1132, 0.1375],
 [0.4675, 0.3947, 0.1426]])
```

若要检查是否可以使用 PyTorch 的 GPU 功能， 可以使用以下示例代码:

```
import torch
torch.cuda.is_available()
```

输出结果应该是：

```
True
```

支持 PyTorch 的 AMD GPU 仍在开发中， 因此, 尚未按[报告](https://github.com/pytorch/pytorch/issues/10657#issuecomment-415067478)提供完整的测试覆盖，如果您有 AMD GPU ，请在[这里](https://rocm.github.io/install.html#installing-from-amd-rocm-repositories)提出建议。

现在让我们来看看一些广泛使用 PyTorch 的研究项目：

### 基于 PyTorch 的持续研究项目

* [Detectron](https://github.com/facebookresearch/Detectron): Facebook AI 研究院的软件系统, 可以智能地进行对象检测和分类。它之前是基于 Caffe2 的。今年早些时候，Caffe2 和 PyTorch [合力](https://caffe2.ai/blog/2018/05/02/Caffe2_PyTorch_1_0.html)创建了一个研究 + 生产的 PyTorch 1.0
* [Unsupervised Sentiment Discovery](https://github.com/NVIDIA/sentiment-discovery): 广泛应用于社交媒体的一些算法
* [vid2vid](https://github.com/NVIDIA/vid2vid): 逼真的视频到视频的转换
* [DeepRecommender](https://github.com/NVIDIA/DeepRecommender/) 我们在过去的[网飞的 AI 文章](https://itsfoss.com/netflix-open-source-ai/)中介绍了这些系统是如何工作的

领先的 GPU 制造商英伟达在[更新](https://news.developer.nvidia.com/pytorch-1-0-accelerated-on-nvidia-gpus/)这方面最近的发展，你也可以阅读正在进行的合作的研究。

### 我们应该如何应对这种 PyTorch 的能力？

想到 Facebook 在社交媒体算法中应用如此令人惊叹的创新项目， 我们是否应该感激这一切或是感到惊恐？这几乎是[天网](https://en.wikipedia.org/wiki/Skynet_(Terminator))! 这一新改进的发布的 PyTorch 肯定会推动事情进一步向前! 在下方评论，随时与我们分享您的想法!

---

via: <https://itsfoss.com/pytorch-open-source-ai-framework/>

作者：[Avimanyu Bandyopadhyay](https://itsfoss.com/author/avimanyu/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[distant1219](https://github.com/distant1219) 校对：[wxy](https://github.com/wxy)

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


Grank：如何评估一个 Github 项目的活跃度

Summary: 本文为 Grank（Github Rank）的简介及相关思路的介绍。

本文为 Grank（Github Rank）的简介及相关思路的介绍。

>
> 本文为 Grank（Github Rank）的简介及相关思路的介绍。
>
>
>

![](/data/attachment/album/201810/22/145255spb0n4hhcwycz8ic.jpg)

在深圳刚刚结束的 CosCon 2018 大会上发布了《[中国开源调查报告](/article-10135-1.html)》，[Grank](/article-10135-1.html) 作为其中[数据篇](/article-10138-1.html)的部分数据提供者，构建了一个 Github 项目活跃度、社区化的模型，并以 Python 实现。

项目地址： <https://github.com/lctt/grank/>

### Grank 模型

我们认为，一个健康的开源项目应该体现为以下两个方面：

* 项目的活跃度趋势
* 项目的社区化（去中心化）程度

而这两个方面分别有多个因素组成：

### 活跃度和活跃度趋势

项目的活跃度，我们定义为项目的提交数、 拉取请求数和贡献者数（其它数据，如代码行数、文件数、issue 数、 fork 数、star 数，要么是权重相对低得多，要么是代表意义不够确定，此处忽略不计入模型）。

但是，对于不同的项目，其横向比较其活跃度，或有不同的活跃度形态，或不具备可比性。很难说一个项目比另外一个项目的提交数高，而拉取请求（PR）数低代表的确切含义。因此我们不认为对不同项目的这些数据进行绝对值的比较有太多的科学意义。

所以，我们认为一个项目本身的活跃度变化的趋势和幅度，会更有项目间比较的意义。

如果以三维空间来描述一个项目的活跃度，以提交数、拉取请求数、贡献者数为三维，可以确定在某个时间点某个项目的坐标，那么计算一段时间内，该坐标点的移动轨迹和速率，可以真实的反映该项目的活跃度趋势。

![](/data/attachment/album/201810/22/144516gvn63viz4jyoovti.jpg)

考虑到按周工作的作息时间的普遍影响，我们以一个工作周作为一个时间采样点，然后计算连续的几周内该坐标的移动速率。这反映了该项目的发展速度。

### 社区化程度

开源诞生于社区，繁荣于社区，根植于社区，虽然现在大型组织、商业公司也纷纷投身于开源生态，但是我们认为，开源项目的生命力仍然在于社区。我们并不否认机构、商业公司对开源的巨大贡献和影响力，但是如果一个开源项目变成了一家或几家大企业的私人游戏，其必然失去开源项目的生命力，它或许会在商业上取得成功，但是那个成功不是开源项目的成功模式。

因此，我们认为需要有一个评估开源项目的社区化（去中心化）程度的指标。项目（尤其是软件项目）的一个重要属性是开发人员的社区化身份，因此，我们以实际向项目贡献了代码的人员的社区化离散程度来评估项目的社区化程度。

每个参与项目开发的人员均有其身份属性，这个身份可能是企业雇佣身份，也可能是社区志愿者身份。我们通过对项目的提交中的提交者数据进行收集，然后根据开发人员的身份信息、邮件后缀等依优先级来判断其所属身份。然后对这些信息进行聚类，以一个离散评估模型来评估该数据集的离散程度。

虽然项目越中心化，其发展风险越高，但是，并不是社区化程度越高的项目就越健康，过于离散的项目也容易出现项目分裂、迭代缓慢等问题。这显然是存在一个适当的区域。

### Grank 的结果长什么样子？

**多项目活跃度：**

![](/data/attachment/album/201810/22/145056pesjitevzdy2ydgi.jpg)

**多项目社区化：**

![](/data/attachment/album/201810/22/145056lhb2oooxz0locccm.jpg)

**单项目社区化及活跃度：**

![](/data/attachment/album/201810/22/145056aljgaulm2so6z1jc.jpg)

### 使用方法

1. 使用 pip 安装项目 `pip install grank`
2. 获取 Github 的 [Personal Access Token](https://github.com/settings/tokens)
3. 使用 `grank login` 设置 Token
4. 使用 `grank config` 设置社区化企业关键词
5. 使用 `grank analy <owner> [<repository>]` 来分析特定用户 /组织和项目，比如 `grank analy lctt grank`,分析结果可以在执行命令目录的 result 目录中找到。
6. 使用命令行模式操作，如 `grank --token=XXXX --start=2018-01-01 --stop=2018-05-21 --askrule=0 --rule=inc analy <owner> <repository>` 其中 token 必须指定，其他可以使用缺省设置

### Grank 是如何实现的？

Grank 使用 Github 的 GraphQL 来完成数据抓取的工作，抓取项目的所有提交和拉取请求来进行分析，并使用 Pandas、numpy、pandas 进行数据的分析，最终得出结果。

此外，Grank 目前为命令行工具，采用了 Click 来编写命令行的支持。

### Grank 能够为你带来什么？

1. 评估自己的项目情况
2. 学习 Python 项目编写
3. 了解 Click 的使用
4. 了解 pytest 的使用。

项目地址：<https://github.com/LCTT/Grank>

Pypi 地址：<https://pypi.org/project/Grank/>


如何在 Arch Linux（UEFI）上安装 GRUB

![](/data/attachment/album/201810/22/221532acfzid5orlqi446r.jpg)

前段时间，我写了一篇在安装 Windows 后在 Arch Linux 上[如何重新安装 Grub](http://fasterland.net/reinstall-grub-arch-linux.html)的教程。

几周前，我不得不在我的笔记本上从头开始重新安装 Arch Linux，同时我发现安装 Grub 并不像我想的那么简单。

出于这个原因，由于在新安装 Arch Linux 时在 UEFI bios 中安装 Grub 并不容易，所以我要写这篇教程。

### 定位 EFI 分区

在 Arch Linux 上安装 Grub 的第一件重要事情是定位 EFI 分区。让我们运行以下命令以找到此分区：

```
# fdisk -l
```

我们需要检查标记为 EFI System 的分区，我这里是 `/dev/sda2`。

之后，我们需要在例如 `/boot/efi` 上挂载这个分区：

```
# mkdir /boot/efi
# mount /dev/sdb2 /boot/efi
```

另一件重要的事情是将此分区添加到 `/etc/fstab` 中。

#### 安装 Grub

现在我们可以在我们的系统中安装 Grub：

```
# grub-mkconfig -o /boot/grub/grub.cfg
# grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB
```

#### 自动将 Windows 添加到 Grub 菜单中

为了自动将 Windows 条目添加到 Grub 菜单，我们需要安装 os-prober：

```
# pacman -Sy os-prober
```

要添加它，让我们运行以下命令：

```
# os-prober
# grub-mkconfig -o /boot/grub/grub.cfg
# grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB
```

你可以在[这里](https://wiki.archlinux.org/index.php/GRUB)找到更多关于在 Arch Linux 上 Grub 的信息。

---

via: <http://fasterland.net/how-to-install-grub-on-arch-linux-uefi.html>

作者：[Francesco Mondello](http://fasterland.net/) 选题：[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/) 荣誉推出


系统管理员需知的 16 个 iptables 使用技巧

Summary: iptables 是一款控制系统进出流量的强大配置工具。

iptables 是一款控制系统进出流量的强大配置工具。

>
> iptables 是一款控制系统进出流量的强大配置工具。
>
>
>

![](/data/attachment/album/201810/22/224826corrbcmnpruin488.jpg)

现代 Linux 内核带有一个叫 [Netfilter](https://en.wikipedia.org/wiki/Netfilter) 的数据包过滤框架。Netfilter 提供了允许、丢弃以及修改等操作来控制进出系统的流量数据包。基于 Netfilter 框架的用户层命令行工具 `iptables` 提供了强大的防火墙配置功能，允许你添加规则来构建防火墙策略。[iptables](https://en.wikipedia.org/wiki/Iptables) 丰富复杂的功能以及其巴洛克式命令语法可能让人难以驾驭。我们就来探讨一下其中的一些功能，提供一些系统管理员解决某些问题需要的使用技巧。

### 避免封锁自己

应用场景：假设你将对公司服务器上的防火墙规则进行修改，你需要避免封锁你自己以及其他同事的情况（这将会带来一定时间和金钱的损失，也许一旦发生马上就有部门打电话找你了）

#### 技巧 #1: 开始之前先备份一下 iptables 配置文件。

用如下命令备份配置文件：

```
/sbin/iptables-save > /root/iptables-works
```

#### 技巧 #2: 更妥当的做法，给文件加上时间戳。

用如下命令加时间戳：

```
/sbin/iptables-save > /root/iptables-works-`date +%F`
```

然后你就可以生成如下名字的文件：

```
/root/iptables-works-2018-09-11
```

这样万一使得系统不工作了，你也可以很快的利用备份文件恢复原状：

```
/sbin/iptables-restore < /root/iptables-works-2018-09-11
```

#### 技巧 #3: 每次创建 iptables 配置文件副本时，都创建一个指向最新的文件的链接。

```
ln –s /root/iptables-works-`date +%F` /root/iptables-works-latest
```

#### 技巧 #4: 将特定规则放在策略顶部，底部放置通用规则。

避免在策略顶部使用如下的一些通用规则：

```
iptables -A INPUT -p tcp --dport 22 -j DROP
```

你在规则中指定的条件越多，封锁自己的可能性就越小。不要使用上面非常通用的规则，而是使用如下的规则：

```
iptables -A INPUT -p tcp --dport 22 –s 10.0.0.0/8 –d 192.168.100.101 -j DROP
```

此规则表示在 `INPUT` 链尾追加一条新规则，将源地址为 `10.0.0.0/8`、 目的地址是 `192.168.100.101`、目的端口号是 `22` （`--dport 22` ） 的 TCP（`-p tcp` ）数据包通通丢弃掉。

还有很多方法可以设置更具体的规则。例如，使用 `-i eth0` 将会限制这条规则作用于 `eth0` 网卡，对 `eth1` 网卡则不生效。

#### 技巧 #5: 在策略规则顶部将你的 IP 列入白名单。

这是一个有效地避免封锁自己的设置：

```
iptables -I INPUT -s <your IP> -j ACCEPT
```

你需要将该规则添加到策略首位置。`-I` 表示则策略首部插入规则，`-A` 表示在策略尾部追加规则。

#### 技巧 #6: 理解现有策略中的所有规则。

不犯错就已经成功了一半。如果你了解 iptables 策略背后的工作原理，使用起来更为得心应手。如果有必要，可以绘制流程图来理清数据包的走向。还要记住：策略的预期效果和实际效果可能完全是两回事。

### 设置防火墙策略

应用场景：你希望给工作站配置具有限制性策略的防火墙。

#### 技巧 #1: 设置默认规则为丢弃

```
# Set a default policy of DROP
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
```

#### 技巧 #2: 将用户完成工作所需的最少量服务设置为允许

该策略需要允许工作站能通过 DHCP（`-p udp --dport 67:68 -sport 67:68`）来获取 IP 地址、子网掩码以及其他一些信息。对于远程操作，需要允许 SSH 服务（`-dport 22`），邮件服务（`--dport 25`），DNS 服务（`--dport 53`），ping 功能（`-p icmp`），NTP 服务（`--dport 123 --sport 123`）以及 HTTP 服务（`-dport 80`）和 HTTPS 服务（`--dport 443`）。

```
# Set a default policy of DROP
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]

# Accept any related or established connections
-I INPUT  1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-I OUTPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow all traffic on the loopback interface
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

# Allow outbound DHCP request
-A OUTPUT –o eth0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT

# Allow inbound SSH
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW  -j ACCEPT

# Allow outbound email
-A OUTPUT -i eth0 -p tcp -m tcp --dport 25 -m state --state NEW  -j ACCEPT

# Outbound DNS lookups
-A OUTPUT -o eth0 -p udp -m udp --dport 53 -j ACCEPT

# Outbound PING requests
-A OUTPUT –o eth0 -p icmp -j ACCEPT

# Outbound Network Time Protocol (NTP) requests
-A OUTPUT –o eth0 -p udp --dport 123 --sport 123 -j ACCEPT

# Outbound HTTP
-A OUTPUT -o eth0 -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
-A OUTPUT -o eth0 -p tcp -m tcp --dport 443 -m state --state NEW -j ACCEPT

COMMIT
```

### 限制 IP 地址范围

应用场景：贵公司的 CEO 认为员工在 Facebook 上花费过多的时间，需要采取一些限制措施。CEO 命令下达给 CIO，CIO 命令 CISO，最终任务由你来执行。你决定阻止一切到 Facebook 的访问连接。首先你使用 `host` 或者 `whois` 命令来获取 Facebook 的 IP 地址。

```
host -t a www.facebook.com
www.facebook.com is an alias for star.c10r.facebook.com.
star.c10r.facebook.com has address 31.13.65.17
whois 31.13.65.17 | grep inetnum
inetnum:        31.13.64.0 - 31.13.127.255
```

然后使用 [CIDR 到 IPv4 转换](http://www.ipaddressguide.com/cidr) 页面来将其转换为 CIDR 表示法。然后你得到 `31.13.64.0/18` 的地址。输入以下命令来阻止对 Facebook 的访问：

```
iptables -A OUTPUT -p tcp -i eth0 –o eth1 –d 31.13.64.0/18 -j DROP
```

### 按时间规定做限制 - 场景1

应用场景：公司员工强烈反对限制一切对 Facebook 的访问，这导致了 CEO 放宽了要求（考虑到员工的反对以及他的助理提醒说她负责更新他的 Facebook 页面）。然后 CEO 决定允许在午餐时间访问 Facebook（中午 12 点到下午 1 点之间）。假设默认规则是丢弃，使用 iptables 的时间功能便可以实现。

```
iptables –A OUTPUT -p tcp -m multiport --dport http,https -i eth0 -o eth1 -m time --timestart 12:00 –timestop 13:00 –d 31.13.64.0/18 -j ACCEPT
```

该命令中指定在中午12点（`--timestart 12:00`）到下午 1 点（`--timestop 13:00`）之间允许（`-j ACCEPT`）到 Facebook.com （`-d [31.13.64.0/18][5]`）的 http 以及 https （`-m multiport --dport http,https`）的访问。

### 按时间规定做限制 - 场景2

应用场景：在计划系统维护期间，你需要设置凌晨 2 点到 3 点之间拒绝所有的 TCP 和 UDP 访问，这样维护任务就不会受到干扰。使用两个 iptables 规则可实现：

```
iptables -A INPUT -p tcp -m time --timestart 02:00 --timestop 03:00 -j DROP
iptables -A INPUT -p udp -m time --timestart 02:00 --timestop 03:00 -j DROP
```

该规则禁止（`-j DROP`）在凌晨2点（`--timestart 02:00`）到凌晨3点（`--timestop 03:00`）之间的 TCP 和 UDP （`-p tcp and -p udp`）的数据进入（`-A INPUT`）访问。

### 限制连接数量

应用场景：你的 web 服务器有可能受到来自世界各地的 DoS 攻击，为了避免这些攻击，你可以限制单个 IP 地址到你的 web 服务器创建连接的数量：

```
iptables –A INPUT –p tcp –syn -m multiport -–dport http,https –m connlimit -–connlimit-above 20 –j REJECT -–reject-with-tcp-reset
```

分析一下上面的命令。如果单个主机在一分钟之内新建立（`-p tcp -syn`）超过 20 个（`-connlimit-above 20`）到你的 web 服务器（`--dport http,https`）的连接，服务器将拒绝（`-j REJECT`）建立新的连接，然后通知对方新建连接被拒绝（`--reject-with-tcp-reset`）。

### 监控 iptables 规则

应用场景：由于数据包会遍历链中的规则，iptables 遵循 “首次匹配获胜” 的原则，因此经常匹配的规则应该靠近策略的顶部，而不太频繁匹配的规则应该接近底部。 你怎么知道哪些规则使用最多或最少，可以在顶部或底部附近监控？

#### 技巧 #1: 查看规则被访问了多少次

使用命令：

```
iptables -L -v -n –line-numbers
```

用 `-L` 选项列出链中的所有规则。因为没有指定具体哪条链，所有链规则都会被输出，使用 `-v` 选项显示详细信息，`-n` 选项则显示数字格式的数据包和字节计数器，每个规则开头的数值表示该规则在链中的位置。

根据数据包和字节计数的结果，你可以将访问频率最高的规则放到顶部，将访问频率最低的规则放到底部。

#### 技巧 #2: 删除不必要的规则

哪条规则从来没有被访问过？这些可以被清除掉。用如下命令查看：

```
iptables -nvL | grep -v "0     0"
```

注意：两个数字 0 之间不是 Tab 键，而是 **5** 个空格。

#### 技巧 #3: 监控正在发生什么

可能你也想像使用 `top` 命令一样来实时监控 iptables 的情况。使用如下命令来动态监视 iptables 中的活动，并仅显示正在遍历的规则：

```
watch --interval=5 'iptables -nvL | grep -v "0     0"'
```

`watch` 命令通过参数 `iptables -nvL | grep -v “0 0“` 每隔 5 秒输出 iptables 的动态。这条命令允许你查看数据包和字节计数的变化。

### 输出日志

应用场景：经理觉得你这个防火墙员工的工作质量杠杠的，但如果能有网络流量活动日志最好了。有时候这比写一份有关工作的报告更有效。

使用工具 [FWLogwatch](http://fwlogwatch.inside-security.de/) 基于 iptables 防火墙记录来生成日志报告。FWLogwatch 工具支持很多形式的报告并且也提供了很多分析功能。它生成的日志以及月报告使得管理员可以节省大量时间并且还更好地管理网络，甚至减少未被注意的潜在攻击。

这里是一个 FWLogwatch 生成的报告示例：

![](/data/attachment/album/201810/22/224854xwwfw1ct31w6u411.png)

### 不要满足于允许和丢弃规则

本文中已经涵盖了 iptables 的很多方面，从避免封锁自己、配置 iptables 防火墙以及监控 iptables 中的活动等等方面介绍了 iptables。你可以从这里开始探索 iptables 甚至获取更多的使用技巧。

---

via: <https://opensource.com/article/18/10/iptables-tips-and-tricks>

作者：[Gary Smith](https://opensource.com/users/greptile) 选题：[lujun9972](https://github.com/lujun9972) 译者：[jrg](https://github.com/jrglinux) 校对：[wxy](https://github.com/wxy)

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


5 个很酷的平铺窗口管理器

![](/data/attachment/album/201810/23/221336pyy3mdxbyebcbcj3.jpg)

Linux 桌面生态中有多种窗口管理器（WM）。有些是作为桌面环境的一部分开发的。有的则被用作独立程序。平铺窗口管理器就是这种情况，它提供了一个更轻量级的自定义环境。本文介绍了五种这样的平铺窗口管理器供你试用。

### i3

[i3](https://i3wm.org/) 是最受欢迎的平铺窗口管理器之一。与大多数其他此类 WM 一样，i3 专注于低资源消耗和用户可定制性。

您可以参考 [Magazine 上的这篇文章](https://fedoramagazine.org/getting-started-i3-window-manager/)了解 i3 安装细节以及如何配置它。

### sway

[sway](https://swaywm.org/) 是一个平铺 Wayland 合成器。它有与现有 i3 配置兼容的优点，因此你可以使用它来替换 i3 并使用 Wayland 作为显示协议。

您可以使用 `dnf` 从 Fedora 仓库安装 sway：

```
$ sudo dnf install sway
```

如果你想从 i3 迁移到 sway，这里有一个[迁移指南](https://github.com/swaywm/sway/wiki/i3-Migration-Guide)。

### Qtile

[Qtile](http://www.qtile.org/) 是另一个平铺管理器，也恰好是用 Python 编写的。默认情况下，你在位于 `~/.config/qtile/config.py` 下的 Python 脚本中配置 Qtile。当此脚本不存在时，Qtile 会使用默认[配置](https://github.com/qtile/qtile/blob/develop/libqtile/resources/default_config.py)。

Qtile 使用 Python 的一个好处是你可以编写脚本来控制 WM。例如，以下脚本打印屏幕详细信息：

```
> from libqtile.command import Client
> c = Client()
> print(c.screen.info)
{'index': 0, 'width': 1920, 'height': 1006, 'x': 0, 'y': 0}
```

要在 Fedora 上安装 Qlite，请使用以下命令：

```
$ sudo dnf install qtile
```

### dwm

[dwm](https://dwm.suckless.org/) 窗口管理器更侧重于轻量级。该项目的一个目标是保持 dwm 最小。例如，整个代码库从未超过 2000 行代码。另一方面，dwm 不容易定制和配置。实际上，改变 dwm 默认配置的唯一方法是[编辑源代码并重新编译程序](https://dwm.suckless.org/customisation/)。

如果你想尝试默认配置，你可以使用 `dnf` 在 Fedora 中安装 dwm：

```
$ sudo dnf install dwm
```

对于那些想要改变 dwm 配置的人，Fedora 中有一个 dwm-user 包。该软件包使用用户主目录中 `~/.dwm/config.h` 的配置自动重新编译 dwm。

### awesome

[awesome](https://awesomewm.org/) 最初是作为 dwm 的一个分支开发，使用外部配置文件提供 WM 的配置。配置通过 Lua 脚本完成，这些脚本允许你编写脚本以自动执行任务或创建 widget。

你可以使用这个命令在 Fedora 上安装 awesome：

```
$ sudo dnf install awesome
```

---

via: <https://fedoramagazine.org/5-cool-tiling-window-managers/>

作者：[Clément Verna](https://fedoramagazine.org) 选题：[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/) 荣誉推出


2018 年最好的 Linux 发行版

Summary: Jack Wallen 分享他挑选的 2018 年最好的 Linux 发行版。

![Linux distros 2018](/data/attachment/album/201810/24/094318h906e0tyipii0z2e.jpg "Linux distros 2018")

>
> Jack Wallen 分享他挑选的 2018 年最好的 Linux 发行版。
>
>
>

这是新的一年，Linux 仍有无限可能。而且许多 Linux 发行版在 2017 年都带来了许多重大的改变，我相信在 2018 年它在服务器和桌面上将会带来更加稳定的系统和市场份额的增长。

对于那些期待迁移到开源平台（或是那些想要切换到）的人对于即将到来的一年，什么是最好的选择？如果你去 [Distrowatch](https://distrowatch.com/) 找一下，你可能会因为众多的发行版而感到头晕，其中一些的排名在上升，而还有一些则恰恰相反。

因此，哪个 Linux 发行版将在 2018 年得到偏爱？我有我的看法。事实上，我现在就要和你们分享它。

跟我做的 [去年清单](https://www.linux.com/news/learn/sysadmin/best-linux-distributions-2017) 相似，我将会打破那张清单，使任务更加轻松。普通的 Linux 用户，至少包含以下几个类别：系统管理员，轻量级发行版，桌面，为物联网和服务器发行的版本。

根据这些，让我们开始 2018 年最好的 Linux 发行版清单吧。

### 对系统管理员最好的发行版

[Debian](https://www.debian.org/) 不常出现在“最好的”列表中。但它应该出现，为什么呢？如果了解到 Ubuntu 是基于 Debian 构建的（其实有很多的发行版都基于 Debian），你就很容易理解为什么这个发行版应该在许多“最好”清单中。但为什么是对管理员最好的呢？我想这是由于两个非常重要的原因：

* 容易使用
* 非常稳定

因为 Debain 使用 dpkg 和 apt 包管理，它使得使用该环境非常简单。而且因为 Debian 提供了最稳定的 Linux 平台之一，它为许多事物提供了理想的环境：桌面、服务器、测试、开发。虽然 Debian 可能不包括去年本分类的优胜者 [Parrot Linux](https://www.parrotsec.org/) 所带有的大量应用程序，但添加完成任务所需的任何或全部必要的应用程序都非常容易。而且因为 Debian 可以根据你的选择安装不同的桌面（Cinnamon、GNOME、KDE、LXDE、Mate 或者 Xfce），肯定可以满足你对桌面的需求。

![debian](/data/attachment/album/201810/24/094318nhnrsahh8kr5rwz3.jpg "debian")

*图 1：在 Debian 9.3 上运行的 GNOME 桌面。*

同时，Debain 在 Distrowatch 上名列第二。下载、安装，然后让它为你的工作而服务吧。Debain 尽管不那么华丽，但是对于管理员的工作来说十分有用。

### 最轻量级的发行版

轻量级的发行版有其特殊的用途：给予一些老旧或是性能低下的机器以新生。但是这不意味着这些特别的发行版仅仅只为了老旧的硬件机器而生。如果你想要的是运行速度，你可能会想知道在你的现代机器上这类发行版的运行速度能有多快。

在 2018 年上榜的最轻量级的发行版是 [Lubuntu](http://lubuntu.me/)。尽管在这个类别里还有很多选择，而且尽管 Lubuntu 的资源占用与 Puppy Linux 一样小，但得益于它是 Ubuntu 家庭的一员，其易用性为它加了分。但是不要担心，Lubuntu 对于硬件的要求并不高：

* CPU：奔腾 4 或者奔腾 M 或者 AMD K8 以上
* 对于本地应用，512 MB 的内存就可以了，对于网络使用（Youtube、Google+、Google Drive、Facebook），建议 1 GB 以上。

Lubuntu 使用的是 LXDE 桌面（图 2），这意味着新接触 Linux 的用户在使用这个发行版时不会有任何问题。这份简短清单中包含的应用（例如：Abiword、Gnumeric 和 Firefox）都是非常轻量的，且对用户友好的。

![Lubuntu](/data/attachment/album/201810/24/094318fw09t9k8z4qiviw4.jpg "Lubuntu")

*图 2：LXDE桌面。*

Lubuntu 能让十年以上的电脑如获新生。

### 最好的桌面发行版

[Elementary OS](https://elementary.io/) 连续两年都是我清单中最好的桌面发行版。对于许多人，[Linux Mint](https://linuxmint.com/) （也是一个非常棒的分支）都是桌面发行版的领袖。但是，于我来说，它在易用性和稳定性上很难打败 Elementary OS。例如，我确信是 [Ubuntu](https://www.ubuntu.com/) 17.10 的发布让我迁移回了 Canonical 的发行版。迁移到新的使用 GNOME 桌面的 Ubuntu 不久之后，我发现我缺少了 Elementary OS 外观、可用性和感觉（图 3）。在使用 Ubuntu 两周以后，我又换回了 Elementary OS。

![Elementary OS](/data/attachment/album/201810/24/094319mldzzsunuwuef4es.jpg "Elementary OS")

*图 3：Pantheon 桌面是一件像艺术品一样的桌面。*

使用 Elementary OS 的任何一个人都会觉得宾至如归。Pantheon 桌面是将操作顺滑和用户友好结合的最完美的桌面。每次更新，它都会变得更好。

尽管 Elementary OS 在 Distrowatch 页面访问量中排名第六，但我预计到 2018 年末，它将至少上升至第三名。Elementary 开发人员非常关注用户的需求。他们倾听并且改进，这个发行版目前的状态是如此之好，似乎他们一切都可以做的更好。 如果您需要一个具有出色可靠性和易用性的桌面，Elementary OS 就是你的发行版。

### 能够证明自己的最好的发行版

很长一段时间内，[Gentoo](https://www.gentoo.org/) 都稳坐“展现你技能”的发行版的首座。但是，我认为现在 Gentoo 是时候让出“证明自己”的宝座给 [Linux From Scratch（LFS）](http://www.linuxfromscratch.org/)。你可能认为这不公平，因为 LFS 实际上不是一个发行版，而是一个帮助用户创建自己的 Linux 发行版的项目。但是，有什么能比你自己创建一个自己的发行版更能证明自己所学的 Linux 知识的呢？在 LFS 项目中，你可以从头开始构建自定义的 Linux 系统，而且是从源代码开始。 所以，如果你真的想证明些什么，请下载 [Linux From Scratch Book](http://www.linuxfromscratch.org/lfs/download.html) 并开始构建。

### 对于物联网最好的发行版

[Ubuntu Core](https://www.ubuntu.com/core) 已经是第二年赢得了该项的冠军。Ubuntu Core 是 Ubuntu 的一个小型的、事务型版本，专为嵌入式和物联网设备而构建。使 Ubuntu Core 如此完美支持物联网的原因在于它将重点放在 snap 包上 —— 这种通用包可以安装到一个平台上而不会干扰其基本系统。这些 snap 包包含它们运行所需的所有内容（包括依赖项），因此不必担心安装它会破坏操作系统（或任何其他已安装的软件）。 此外，snap 包非常容易升级，并运行在隔离的沙箱中，这使它们成为物联网的理想解决方案。

Ubuntu Core 内置的另一个安全领域是登录机制。Ubuntu Core 使用Ubuntu One ssh密钥，这样登录系统的唯一方法是通过上传的 ssh 密钥到 [Ubuntu One帐户](https://login.ubuntu.com/)（图 4）。这为你的物联网设备提供了更高的安全性。

![ Ubuntu Core](/data/attachment/album/201810/24/094319hxazlrmml04rfjn0.jpg " Ubuntu Core")

*图 4：Ubuntu Core屏幕指示通过Ubuntu One用户启用远程访问。*

### 最好的服务器发行版

这里有点意见不统一。主要原因是支持。如果你需要商业支持，乍一看，你最好的选择可能是 [Red Hat Enterprise Linux](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux)。红帽年复一年地证明了自己不仅是全球最强大的企业服务器平台之一，而且是单一最赚钱的开源业务（年收入超过 20 亿美元）。

但是，Red Hat 并不是唯一的服务器发行版。 实际上，Red Hat 甚至并不能垄断企业服务器计算的各个方面。如果你关注亚马逊 Elastic Compute Cloud 上的云统计数据，Ubuntu 就会打败红帽企业 Linux。根据[云市场](http://thecloudmarket.com/stats#/by_platform_definition)的报告，EC2 统计数据显示 RHEL 的部署率低于 10 万，而 Ubuntu 的部署量超过 20 万。

最终的结果是，Ubuntu 几乎已经成为云计算的领导者。如果你将它与 Ubuntu 对容器的易用性和可管理性结合起来，就会发现 Ubuntu Server 是服务器类别的明显赢家。而且，如果你需要商业支持，Canonical 将为你提供 [Ubuntu Advantage](https://buy.ubuntu.com/?_ga=2.177313893.113132429.1514825043-1939188204.1510782993)。

对使用 Ubuntu Server 的一个警告是它默认为纯文本界面（图 5）。如果需要，你可以安装 GUI，但使用 Ubuntu Server 命令行非常简单（每个 Linux 管理员都应该知道）。

![Ubuntu server](/data/attachment/album/201810/24/094320fzju0bfm7jfbwpre.jpg "Ubuntu server")

*图 5：Ubuntu 服务器登录，通知更新。*

### 你怎么看

正如我之前所说，这些选择都非常主观，但如果你正在寻找一个好的开始，那就试试这些发行版。每一个都可以用于非常特定的目的，并且比大多数做得更好。虽然你可能不同意我的个别选择，但你可能会同意 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/1/best-linux-distributions-2018>

作者：[JACK WALLEN](https://www.linux.com/users/jlwallen) 译者：[dianbanjiu](https://github.com/dianbanjiu) 校对：[wxy](https://github.com/wxy)

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


写作是如何帮助技能拓展和事业成长的

Summary: 了解为什么写作可以帮助学习新技能和事业成长

了解为什么写作可以帮助学习新技能和事业成长

>
> 了解为什么写作可以帮助学习新技能和事业成长
>
>
>

![](/data/attachment/album/201810/24/103058ektgkc8oc690gov3.jpg)

在最近的[温哥华开源峰会](https://events.linuxfoundation.org/events/open-source-summit-north-america-2018/)上，我参加了一个小组讨论，叫做“写作是如何改变你的职业生涯的（即使你不是个作家）”。主持人是 Opensource.com 的社区经理兼编辑 Rikki Endsley，成员有开源策略顾问 VM (Vicky) Brasseur，The New Stack 的创始人兼主编 Alex Williams，还有 The Scale Factory 的顾问 Dawn Foster。

Rikki 在她的[这篇文章](https://opensource.com/article/18/2/career-changing-magic-writing)中总结了一些令人愉快的，并且能以意想不到的方式改善你职业生涯的写作方法，我在峰会上的发言是受她这篇文章的启发。透露一下，我认识 Rikki 很久了，我们在同一家公司共事了很多年，一起带过孩子，到现在还是很亲密的朋友。

### 写作和学习

正如 Rikki 对这个小组讨论的描述，“即使你自认为不是一个‘作家’，你也应该考虑写一下对开源的贡献，还有你的项目或者社区”。写作是一种很好的方式，来分享自己的知识并让别人参与到你的工作中来，当然它对个人也有好处。写作能帮助你结识新人，学习新技能，还能改善你的沟通。

我发现写作能让我搞清楚自己对某个主题有哪些不懂的地方。写作的过程会让知识体系的空白很突出，这激励了我通过进一步的研究、阅读和提问来填补这些空白。

Rikki 说：“写那些你不知道的东西会更加困难也更加耗时，但是也更有成就感，更有益于你的事业。我发现写我不知道的东西有助于自己学习，因为得研究透彻才能给读者解释清楚。”

把你刚学到的东西写出来对其他也在学习这些知识的人是很有价值的。[Julia Evans](https://jvns.ca/) 经常在她的博客里写有关学习新技能的文章。她能把主题分解成一个个小的部分，这种方法对读者很友好，容易上手。Evans 在自己的博客中带领读者了解她的学习过程，指出在这个过程中哪些是对她有用的，哪些是没用的，基本消除了读者的学习障碍，为新手清扫了道路。

### 更明确的沟通

写作有助于思维训练和准确表达，尤其是面向国际受众写作（或演讲）时。例如，在[这篇文章中](https://www.linux.com/blog/event/open-source-summit-eu/2017/12/technical-writing-international-audience)，Isabel Drost-Fromm 为那些母语不是英语的演讲者提供了几个技巧来消除歧义。不管是在会议上还是在自己团队内发言，写作还能帮你在演示幻灯片之前理清思路。

Rikki 说：“写文章的过程有助于我组织整理自己的发言和演示稿，也是一个给参会者提供笔记的好方式，还可以分享给没有参加活动的更多国际观众。”

如果你有兴趣，我鼓励你去写作。我强烈建议你参考这里提到的文章，开始思考你要写的内容。不幸的是，我们在开源峰会上的讨论没有记录下来，但我希望将来能再做一次讨论，分享更多的想法。

---

via: <https://www.linux.com/blog/2018/9/how-writing-can-help-you-learn-new-skills-and-grow-your-career>

作者：[Amber Ankerholz](https://www.linux.com/users/aankerholz) 选题：[lujun9972](https://github.com/lujun9972) 译者：[belitex](https://github.com/belitex) 校对：[pityonline](https://github.com/pityonline)

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


你从不知道的 11 个 KDE 应用

Summary: 你今天需要哪种有趣或奇特的应用？

你今天需要哪种有趣或奇特的应用？

>
> 你今天需要哪种有趣或奇特的应用？
>
>
>

![](/data/attachment/album/201810/24/151946u9pvudwvzpdoluoo.png)

Linux 桌面环境 KDE 于今年 10 月 14 日庆祝诞生 22 周年。KDE 社区用户创建了海量应用（并没有很多，但[也有不少](https://www.kde.org/applications/)），它们很多都提供有趣和奇特的服务。我们仔细看了该列表，并挑选出了你可能想了解的 11 个应用。

### 11 个你从没了解的 KDE 应用

1. [KTeaTime](https://www.kde.org/applications/games/kteatime/) 是一个泡茶计时器。选择你正在饮用的茶的类型 —— 绿茶、红茶、凉茶等 —— 当可以取出茶包来饮用时，计时器将会响。
2. [KTux](https://userbase.kde.org/KTux) 就是一个屏保程序……是么？Tux 用它的绿色飞船在外太空飞行。
3. [Blinken](https://www.kde.org/applications/education/blinken) 是一款基于 Simon Says 的记忆游戏，这是一个 1978 年发布的电子游戏。玩家们在记住长度增加的序列时会有挑战。
4. [Tellico](http://tellico-project.org/) 是一个收集管理器，用于组织你最喜欢的爱好。也许你还在收集棒球卡。也许你是红酒俱乐部的一员。也许你是一个严肃的书虫。也许三个都是！
5. [KRecipes](https://www.kde.org/applications/utilities/krecipes/) **不是** 简单的食谱管理器。它还有很多其他功能！购物清单、营养素分析、高级搜索、菜谱评级、导入/导出各种格式等。
6. [KHangMan](https://edu.kde.org/khangman/) 基于经典游戏 Hangman，你可以按逐个字母猜测单词。这个游戏有多种语言版本，这可以用来改善你学习另一种语言。它有四个分类，其中一个是“动物”，非常适合孩子。
7. [KLettres](https://edu.kde.org/klettres/) 是另一款可以帮助你学习新语言的应用。它教授字母表并挑战用户阅读和发音音节。
8. [KDiamond](https://games.kde.org/game.php?game=kdiamond) 类似于宝石迷阵或其他单人益智游戏，其中游戏的目标是搭建一定数量的相同类型的宝石或物体的行。这里是钻石。
9. [KolourPaint](https://www.kde.org/applications/graphics/kolourpaint/) 是一个非常简单的图像编辑工具，也可以用于创建简单的矢量图形。
10. [Kiriki](https://www.kde.org/applications/games/kiriki/) 是一款类似于 Yahtzee 的 2-6 名玩家的骰子游戏。
11. [RSIBreak](https://userbase.kde.org/RSIBreak) 居然没有以 K 开头！？它以“RSI”开头代表“<ruby> 重复性劳损 <rt>  Repetitive Strain Injury </rt></ruby>” ，这会在日复一日长时间使用鼠标和键盘后发生。这个应用会提醒你休息，并可以个性化定制，以满足你的需求。

---

via: <https://opensource.com/article/18/10/kde-applications>

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


CPU 电源管理器：Linux 系统中 CPU 主频的控制和管理

Summary: 有一款名为 CPU Power Manager 的 GNOME 扩展插件，可以很容易的就设置和管理你的 CPU 主频。

![](/data/attachment/album/201810/24/230729oc9hwc7zo9zoactw.jpg)

你使用笔记本的话，可能知道 Linux 系统的电源管理做的很不好。虽然有 **TLP**、[**Laptop Mode Tools** 和 **powertop**](https://www.ostechnix.com/improve-laptop-battery-performance-linux/) 这些工具来辅助减少电量消耗，但跟 Windows 和 Mac OS 系统比较起来，电池的整个使用周期还是不尽如意。此外，还有一种降低功耗的办法就是限制 CPU 的频率。这是可行的，然而却需要编写很复杂的终端命令来设置，所以使用起来不太方便。幸好，有一款名为 **CPU Power Manager** 的 GNOME 扩展插件，可以很容易的就设置和管理你的 CPU 主频。GNOME 桌面系统中，CPU Power Manager 使用名为 **intel\_pstate** 的频率调整驱动程序（几乎所有的 Intel CPU 都支持）来控制和管理 CPU 主频。

使用这个扩展插件的另一个原因是可以减少系统的发热量，因为很多系统在正常使用中的发热量总让人不舒服，限制 CPU 的主频就可以减低发热量。它还可以减少 CPU 和其他组件的磨损。

### 安装 CPU Power Manager

首先，进入[扩展插件主页面](https://extensions.gnome.org/extension/945/cpu-power-manager/)，安装此扩展插件。

安装好插件后，在 GNOME 顶部栏的右侧会出现一个 CPU 图标。点击图标，会出现安装此扩展一个选项提示，如下示：

![](/data/attachment/album/201810/24/230730jjowoo7ezo30pjjt.png)

点击“尝试安装”按纽，会弹出输入密码确认框。插件需要 root 权限来添加 policykit 规则，进而控制 CPU 主频。下面是弹出的提示框样子：

![](/data/attachment/album/201810/24/230731fv1gvh866etzeqff.png)

输入密码，点击“认证”按纽，完成安装。最后在 `/usr/share/polkit-1/actions` 目录下添加了一个名为 `mko.cpupower.setcpufreq.policy` 的 policykit 文件。

都安装完成后，如果点击右上脚的 CPU 图标，会出现如下所示：

![](/data/attachment/album/201810/24/230732hz00jpjuk60087qs.png)

### 功能特性

* **查看 CPU 主频：** 显然，你可以通过这个提示窗口看到 CPU 的当前运行频率。
* **设置最大、最小主频：** 使用此扩展，你可以根据列出的最大、最小频率百分比进度条来分别设置其频率限制。一旦设置，CPU 将会严格按照此设置范围运行。
* **开/关 Turbo Boost：** 这是我最喜欢的功能特性。大多数 Intel CPU 都有 “Turbo Boost” 特性，为了提高额外性能，其中的一个内核为自动进行超频。此功能虽然可以使系统获得更高的性能，但也大大增加功耗。所以，如果不做 CPU 密集运行的话，为节约电能，最好关闭 Turbo Boost 功能。事实上，在我电脑上，我大部分时间是把 Turbo Boost 关闭的。
* **生成配置文件：** 可以生成最大和最小频率的配置文件，就可以很轻松打开/关闭，而不是每次手工调整设置。

### 偏好设置

你也可以通过偏好设置窗口来自定义扩展插件显示形式：

![](/data/attachment/album/201810/24/230733i4vvp7vdfkd34zkm.png)

如你所见，你可以设置是否显示 CPU 主频，也可以设置是否以 **Ghz** 来代替 **Mhz** 显示。

你也可以编辑和创建/删除配置文件：

![](/data/attachment/album/201810/24/230734nb77uow4cwm4wonh.png)

可以为每个配置文件分别设置最大、最小主频及开/关 Turbo boost。

### 结论

正如我在开始时所说的，Linux 系统的电源管理并不是最好的，许多人总是希望他们的 Linux 笔记本电脑电池能多用几分钟。如果你也是其中一员，就试试此扩展插件吧。为了省电，虽然这是非常规的做法，但有效果。我确实喜欢这个插件，到现在已经使用了好几个月了。

你对此插件有何看法呢？请把你的观点留在下面的评论区吧。

祝贺!

---

via: <https://www.ostechnix.com/cpu-power-manager-control-and-manage-cpu-frequency-in-linux/>

作者：[EDITOR](https://www.ostechnix.com/author/editor/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[runningwater](https://github.com/runningwater) 校对：[wxy](https://github.com/wxy)

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


万维网的创建者正在创建一个新的去中心化网络

>
> 万维网（WWW）的创建者 Tim Berners-Lee 公布了他计划创建一个新的去中心化网络，该网络中的数据将由用户控制。
>
>
>

[Tim Berners-Lee](https://en.wikipedia.org/wiki/Tim_Berners-Lee) 以创建万维网而闻名，万维网就是你现在所知的互联网。二十多年之后，Tim 致力于将互联网从企业巨头的掌控中解放出来，并通过<ruby> 去中心化网络 <rt>  Decentralized Web </rt></ruby>将权力交回给人们。

Berners-Lee 对互联网“强权”们处理用户数据的方式感到不满。所以他[开始致力于他自己的开源项目](https://medium.com/@timberners_lee/one-small-step-for-the-web-87f92217d085) Solid “来将在网络上的权力归还给人们”。

>
> Solid 改变了当前用户必须将个人数据交给数字巨头以换取可感知价值的模型。正如我们都已发现的那样，这不符合我们的最佳利益。Solid 是我们如何驱动网络进化以恢复平衡 —— 以一种革命性的方式，让我们每个人完全地控制数据，无论数据是否是个人数据。
>
>
>

![Tim Berners-Lee is creating a decentralized web with open source project Solid](/data/attachment/album/201810/24/233504e8jyvyv3jq3dk0dd.jpg)

基本上，[Solid](https://solid.inrupt.com/) 是一个使用现有网络构建的平台，在这里你可以创建自己的 “pod” (个人数据存储)。你决定这个 “pod” 将被托管在哪里，谁将访问哪些数据元素以及数据将如何通过这个 pod 分享。

Berners-Lee 相信 Solid “将以一种全新的方式，授权个人、开发者和企业来构思、构建和寻找创新、可信和有益的应用和服务。”

开发人员需要将 Solid 集成进他们的应用程序和网站中。 Solid 仍在早期阶段，所以目前没有相关的应用程序。但是项目网站宣称“第一批 Solid 应用程序正在开发当中”。

Berners-Lee 已经创立一家名为 [Inrupt](https://www.inrupt.com/) 的初创公司，并已从麻省理工学院休学术假来全职工作在 Solid，来将其”从少部分人的愿景带到多数人的现实“。

如果你对 Solid 感兴趣，可以[学习如何开发应用程序](https://solid.inrupt.com/docs/getting-started)或者以自己的方式[给项目做贡献](https://solid.inrupt.com/community)。当然，建立和推动 Solid 的广泛采用将需要大量的努力，所以每一点的贡献都将有助于去中心化网络的成功。

你认为[去中心化网络](https://tech.co/decentralized-internet-guide-2018-02)会成为现实吗？你是如何看待去中心化网络，特别是 Solid 项目的？

---

via: <https://itsfoss.com/solid-decentralized-web/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[ypingcn](https://github.com/ypingcn) 校对：[wxy](https://github.com/wxy)

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


6 个托管 git 仓库的地方

>
> GitHub 被收购导致一些用户去寻找这个流行的代码仓库的替代品。这里有一些你可以考虑一下。
>
>
>

![](/data/attachment/album/201810/25/143554rszbl3h7iahqcm73.jpg)

也许你是少数一些没有注意到的人之一，就在之前，[微软收购了 GitHub](https://www.theverge.com/2018/6/4/17422788/microsoft-github-acquisition-official-deal)。两家公司达成了共识。微软在近些年已经变成了开源的有力支持者，而 GitHub 从成立起，就已经成为了大量的开源项目的实际代码库。

然而，最近发生的这次收购可能会带给你一些苦恼。毕竟公司的收购让你意识到了你的开源代码放在了一个商业平台上。可能你现在还没准备好迁移到其他的平台上去，但是至少这可以给你提供一些可选项。让我们找找网上现在都有哪些可用的平台。

### 选择之一： GitHub

严格来说，这是一个合格的选项。[GitHub](https://github.com/) 历史上没有什么失信的地方，而且微软后来也一直笑对开源。把你的项目继续放在 GitHub 上，保持观望没有什么不可以。它现在依然是最大的软件开发的网络社区，同时还有许多对于问题追踪、代码审查、持续集成、通用的代码管理等很有用的工具。而且它还是基于 Git 的，这是每个人都喜欢的开源版本控制系统。你的代码还是你的代码。如果没有出现什么问题，那保持原状是没错的。

### 选择之二： GitLab

[GitLab](https://gitlab.com) 是考虑替代代码库平台时的主要竞争者。它是完全开源的。你可以像在 GitHub 一样把你的代码托管在 GitLab，但你也可以选择在你自己的服务器上自行托管自己的 GitLab 实例，并完全控制谁可以访问那里的所有内容以及如何访问和管理。GitLab 与 GitHub 功能几乎相同，有些人甚至可能会说它的持续集成和测试工具更优越。尽管 GitLab 上的开发者社区肯定比 GitHub 上的开发者社区要小，但这并没有什么。你可能会在那里的人群中找到更多志同道合的开发者。

### 选择之三： Bitbucket

[Bitbucket](https://bitbucket.org) 已经存在很多年了。在某些方面，它可以作为 GitHub 未来的一面镜子。Bitbucket 八年前被一家大公司（Atlassian）收购，并且已经经历了一些变化。它仍然是一个像 GitHub 这样的商业平台，但它远不是一个创业公司，而且从组织上说它的基础相当稳定。Bitbucket 具有 GitHub 和 GitLab 上的大部分功能，以及它自己的一些新功能，如对 [Mercurial](https://www.mercurial-scm.org/wiki/Repository) 仓库的原生支持。

### 选择之四： SourceForge

[SourceForge](https://sourceforge.net) 是开源代码库的鼻祖。如果你曾经有一个开源项目，Sourceforge 就是那个托管你的代码并向其他人分享你的发布版本的地方。它迁移到 Git 版本控制用了一段时间，它有一些商业收购和再次收购的历史，以及一些对某些开源项目糟糕的捆绑决策。也就是说，SourceForge 从那时起似乎已经恢复，该网站仍然是一个有着不少开源项目的地方。然而，很多人仍然感到有点受伤，而且有些人并不是很支持它的平台货币化的各种尝试，所以一定要睁大眼睛。

### 选择之五： 自己管理

如果你想自己掌握自己项目的命运（除了你自己没人可以指责你），那么一切都由自己来做可能对你来说是最佳的选择。无论对于大项目还是小项目，都是好的选择。Git 是开源的，所以自己托管也很容易。如果你想要问题追踪和代码审查功能，你可以运行一个 GitLab 或者 [Phabricator](https://phacility.com/phabricator/) 的实例。对于持续集成，你可以设置自己的 [Jenkins](https://jenkins.io) 自动化服务实例。是的，你需要对自己的基础架构开销和相关的安全要求负责。但是，这个设置过程并不是很困难。所以如果你不想自己的代码被其他人的平台所吞没，这就是一种很好的方法。

### 选择之六：以上全部

以下是所有这些的美妙之处：尽管这些平台上有一些专有的选项，但它们仍然建立在坚实的开源技术之上。而且不仅仅是开源，而是明确设计为分布在大型网络（如互联网）上的多个节点上。你不需要只使用一个。你可以使用一对……或者全部。使用 GitLab 将你自己的设施作为保证的基础，并在 GitHub 和 Bitbucket 上安装克隆存储库，以进行问题跟踪和持续集成。将你的主代码库保留在 GitHub 上，但是出于你自己的考虑，可以在 GitLab 上安装“备份”克隆。

关键在于你可以选择。我们能有这么多选择，都是得益于那些非常有用而强大的项目之上的开源许可证。未来一片光明。

当然，在这个列表中我肯定忽略了一些开源平台。方便的话请补充给我们。你是否使用了多个平台？哪个是你最喜欢的？你都可以在这里说出来！

---

via: <https://opensource.com/article/18/8/github-alternatives>

作者：[Jason van Gumster](https://opensource.com/users/mairin) 选题：[lujun9972](https://github.com/lujun9972) 译者：[dianbanjiu](https://github.com/dianbanjiu) 校对：[wxy](https://github.com/wxy)

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


如何使用 Apache Web 服务器配置多个站点

Summary: 如何在流行而强大的 Apache Web 服务器上托管两个或多个站点。

如何在流行而强大的 Apache Web 服务器上托管两个或多个站点。

>
> 如何在流行而强大的 Apache Web 服务器上托管两个或多个站点。
>
>
>

![](/data/attachment/album/201810/25/153824lkmrkizcwr47w9oc.jpg)

在我的[上一篇文章](/article-9506-1.html)中，我解释了如何为单个站点配置 Apache Web 服务器，事实证明这很容易。在这篇文章中，我将向你展示如何使用单个 Apache 实例来服务多个站点。

注意：我写这篇文章的环境是 Fedora 27 虚拟机，配置了 Apache 2.4.29。如果你用另一个发行版或不同的 Fedora 版本，那么你使用的命令以及配置文件的位置和内容可能会有所不同。

正如我之前的文章中提到的，Apache 的所有配置文件都位于 `/etc/httpd/conf` 和 `/etc/httpd/conf.d`。默认情况下，站点的数据位于 `/var/www` 中。对于多个站点，你需要提供多个位置，每个位置对应托管的站点。

### 基于名称的虚拟主机

使用基于名称的虚拟主机，你可以为多个站点使用一个 IP 地址。现代 Web 服务器，包括 Apache，使用指定 URL 的 `hostname` 部分来确定哪个虚拟 Web 主机响应页面请求。这仅仅需要比一个站点更多的配置。

即使你只从单个站点开始，我也建议你将其设置为虚拟主机，这样可以在以后更轻松地添加更多站点。在本文中，我将从上一篇文章中我们停止的地方开始，因此你需要设置原来的站点，即基于名称的虚拟站点。

### 准备原来的站点

在设置第二个站点之前，你需要为现有网站提供基于名称的虚拟主机。如果你现在没有站点，[请返回并立即创建一个](/article-9506-1.html)。

一旦你有了站点，将以下内容添加到 `/etc/httpd/conf/httpd.conf` 配置文件的底部（添加此内容是你需要对 `httpd.conf` 文件进行的唯一更改）：

```
<VirtualHost 127.0.0.1:80>
    DocumentRoot /var/www/html
    ServerName www.site1.org
</VirtualHost>
```

这将是第一个虚拟主机配置节，它应该保持为第一个，以使其成为默认定义。这意味着通过 IP 地址或解析为此 IP 地址但没有特定命名主机配置节的其它名称对服务器的 HTTP 访问将定向到此虚拟主机。所有其它虚拟主机配置节都应跟在此节之后。

你还需要使用 `/etc/hosts` 中的条目设置你的网站以提供名称解析。上次，我们只使用了 `localhost` 的 IP 地址。通常，这可以使用你使用的任何名称服务来完成，例如 Google 或 Godaddy。对于你的测试网站，通过在 `/etc/hosts` 中的 `localhost` 行添加一个新名称来完成此操作。添加两个网站的条目，方便你以后不需再次编辑此文件。结果如下：

```
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 www.site1.org www.site2.org
```

让我们将 `/var/www/html/index.html` 文件改变得更加明显一点。它应该看起来像这样（带有一些额外的文本来识别这是站点 1）：

```
<h1>Hello World</h1>

Web site 1.
```

重新启动 HTTPD 服务器，已启用对 `httpd` 配置的更改。然后，你可以从命令行使用 Lynx 文本模式查看网站。

```
[root@testvm1 ~]# systemctl restart httpd
[root@testvm1 ~]# lynx www.site1.org

                                              Hello World
  Web site 1.
<snip>
Commands: Use arrow keys to move, '?' for help, 'q' to quit, '<-' to go back.
Arrow keys: Up and Down to move.  Right to follow a link; Left to go back.
H)elp O)ptions P)rint G)o M)ain screen Q)uit /=search [delete]=history list
```

你可以看到原始网站的修改内容，没有明显的错误，先按下 `Q` 键，然后按 `Y` 退出 Lynx Web 浏览器。

### 配置第二个站点

现在你已经准备好建立第二个网站。使用以下命令创建新的网站目录结构：

```
[root@testvm1 html]# mkdir -p /var/www/html2
```

注意，第二个站点只是第二个 `html` 目录，与第一个站点位于同一 `/var/www` 目录下。

现在创建一个新的索引文件 `/var/www/html2/index.html`，其中包含以下内容（此索引文件稍有不同，以区别于原来的网站）：

```
<h1>Hello World -- Again</h1>

Web site 2.
```

在 `httpd.conf` 中为第二个站点创建一个新的配置节，并将其放在上一个虚拟主机配置节下面（这两个应该看起来非常相似）。此节告诉 Web 服务器在哪里可以找到第二个站点的 HTML 文件。

```
<VirtualHost 127.0.0.1:80>
    DocumentRoot /var/www/html2
    ServerName www.site2.org
</VirtualHost>
```

重启 HTTPD，并使用 Lynx 来查看结果。

```
[root@testvm1 httpd]# systemctl restart httpd
[root@testvm1 httpd]# lynx www.site2.org

                                    Hello World -- Again

   Web site 2.

<snip>
Commands: Use arrow keys to move, '?' for help, 'q' to quit, '<-' to go back.
Arrow keys: Up and Down to move.  Right to follow a link; Left to go back.
H)elp O)ptions P)rint G)o M)ain screen Q)uit /=search [delete]=history list

```

在这里，我压缩了输出结果以适应这个空间。页面的差异表明这是第二个站点。要同时显示两个站点，请打开另一个终端会话并使用 Lynx Web 浏览器查看另一个站点。

### 其他考虑

这个简单的例子展示了如何使用 Apache HTTPD 服务器的单个实例来服务于两个站点。当考虑其他因素时，配置虚拟主机会变得有点复杂。

例如，你可能希望为这些网站中的一个或全部使用一些 CGI 脚本。为此，你可能为 CGI 程序在 `/var/www` 目录下创建一些目录：`/var/www/cgi-bin` 和 `/var/www/cgi-bin2`，以与 HTML 目录命名一致。然后，你需要将配置指令添加到虚拟主机节，以指定 CGI 脚本的目录位置。每个站点可以有下载文件的目录。这还需要相应虚拟主机节中的条目。

[Apache 网站](https://httpd.apache.org/docs/2.4/)描述了管理多个站点的其他方法，以及从性能调优到安全性的配置选项。

Apache 是一个强大的 Web 服务器，可以用来管理从简单到高度复杂的网站。尽管其总体市场份额在缩小，但它仍然是互联网上最常用的 HTTPD 服务器。

---

via: <https://opensource.com/article/18/3/configuring-multiple-web-sites-apache>

作者：[David Both](https://opensource.com/users/dboth) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


用 GNOME Boxes 下载一个操作系统镜像

![](/data/attachment/album/201810/25/164805hworcwv1opopf1fo.jpg)

Boxes 是 GNOME 上的虚拟机应用。最近 Boxes 添加了一个新的特性，使得它在运行不同的 Linux 发行版时更加容易。你现在可以在 Boxes 中自动安装那些发行版以及像 FreeBSD 和 FreeDOS 这样的操作系统，甚至还包括红帽企业 Linux。红帽开发者计划包括了一个[红帽企业版 Linux 的免费订阅](https://developers.redhat.com/blog/2016/03/31/no-cost-rhel-developer-subscription-now-available/)。 使用[红帽开发者](http://developers.redhat.com)帐户，Boxes 可以自动设置一个名为 Developer Suite 订阅的 RHEL 虚拟机。 下面是它的工作原理。

### 红帽企业版 Linux

要创建一个红帽企业版 Linux 的虚拟机，启动 Boxes，点击“新建”。从源选择列表中选择“下载一个镜像”。在顶部，点击“红帽企业版 Linux”。这将会打开网址为 [developers.redhat.com](http://developers.redhat.com) 的一个 Web 表单。使用已有的红帽开发者账号登录，或是新建一个。

![](/data/attachment/album/201810/25/164806ax9crr1tk2209tx9.png)

如果这是一个新帐号，Boxes 在继续之前需要一些额外的信息。这一步需要在账户中开启开发者订阅。还要确保 [接受条款和条件](https://www.redhat.com/wapps/tnc/termsack?event%5B%5D=signIn)，这样可以在之后的注册中节省一步。

![](/data/attachment/album/201810/25/164807e0jqboi4m85bge5s.png)

点击“提交”，然后就会开始下载安装磁盘镜像。下载需要的时间取决于你的网络状况。在这期间你可以去喝杯茶或者咖啡歇息一下。

![](/data/attachment/album/201810/25/164807qmbqbvt4cbkdsv44.png)

等介质下载完成（一般位于 `~/Downloads` ），Boxes 会有一个“快速安装”的显示。填入账号和密码然后点击“继续”，当你确认了虚拟机的信息之后点击“创建”。“快速安装”会自动完成接下来的整个安装！（现在你可以去享受你的第二杯茶或者咖啡了）

![](/data/attachment/album/201810/25/164808qzo585s13yo7f95e.png)

![](/data/attachment/album/201810/25/164809jn5nznnpak13z44i.png)

![](/data/attachment/album/201810/25/164811iwttk4kqks9a9aka.png)

等到安装结束，虚拟机会直接重启并登录到桌面。在虚拟机里，在应用菜单的“系统工具”一栏启动“红帽订阅管理”。这一步需要输入 root 密码。

![](/data/attachment/album/201810/25/164812ue79hs9qcww9zefr.png)

单击“注册”按钮，然后按照注册助手中的步骤操作。 出现提示时，使用你的红帽开发者帐户登录。

![](/data/attachment/album/201810/25/164813gzp4ptnju5hc48nx.png)

![](/data/attachment/album/201810/25/164814zozskb8zb40qaa0q.png)

现在你可以通过任何一种更新方法，像是 `yum` 或是 GNOME Software 进行下载和更新了。

![](/data/attachment/album/201810/25/164817mi7mybuulmm9cczi.png)

### FreeDOS 或是其他

Boxes 可以安装很多操作系统，而不仅仅只是红帽企业版。 作为 KVM 和 qemu 的前端，Boxes 支持各种操作系统。使用 [libosinfo](https://libosinfo.org)，Boxes 可以自动下载（在某些情况下安装）相当多不同操作系统。

![](/data/attachment/album/201810/25/164818r098azdx8zix91d8.png)

要从列表中安装一个操作系统，只需选择并完成创建一个新的虚拟机。一些操作系统，比如 FreeDOS，并不支持快速安装。这些操作系统需要虚拟机从安装介质中引导。之后你可以手动安装。

![](/data/attachment/album/201810/25/164818jxe9d2ann7xkbaes.png)

![](/data/attachment/album/201810/25/164819oyb2dbsmsgyktbmt.png)

### Boxes 上流行的操作系统

这里仅仅是一些目前在它上面比较受欢迎的选择。

![](/data/attachment/album/201810/25/164820wp35nffma66fana3.png)

![](/data/attachment/album/201810/25/164821kio71h7uncolu1c1.png)

![](/data/attachment/album/201810/25/164823u77q77qceuwuzrai.png)

![](/data/attachment/album/201810/25/164824hfvefv33f857fefh.png)

![](/data/attachment/album/201810/25/164826zd1d05poj4vlhcdd.png)

![](/data/attachment/album/201810/25/164827pww8wy97wwysm28m.png)

Fedora 会定期更新它的操作系统信息数据库（osinfo-db）。确保你会经常检查是否有新的操作系统选项。

---

via: <https://fedoramagazine.org/download-os-gnome-boxes/>

作者：[Link Dupont](https://fedoramagazine.org/author/linkdupont/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[dianbanjiu](https://github.com/dianbanjiu) 校对：[wxy](https://github.com/wxy)

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


使用 Podman 以非 root 用户身份运行 Linux 容器

![](/data/attachment/album/201810/26/082845qyjxxcmccjjm6cn0.jpg)

Linux 容器是由 Linux 内核所提供的具有特定隔离功能的进程 —— 包括文件系统、进程和网络的隔离。容器有助于实现可移植性 —— 应用可以在容器镜像中与其依赖项一起分发，并可在几乎任何有容器运行时环境的 Linux 系统上运行。

虽然容器技术存在了很长时间，但 Linux 容器是由 Docker 而得到了广泛推广。 “Docker” 这个词可以指几个不同的东西，包括容器技术和工具，周围的社区，或者 Docker Inc. 公司。但是，在本文中，我将用来指管理 Linux 容器的技术和工具。

### 什么是 Docker

[Docker](https://docs.docker.com/) 是一个以 root 身份在你的系统上运行的守护程序，它利用 Linux 内核的功能来管理正在运行的容器。除了运行容器之外，它还可以轻松管理容器镜像 —— 与容器注册库交互、存储映像、管理容器版本等。它基本上支持运行单个容器所需的所有操作。

但即使 Docker 是管理 Linux 容器的一个非常方便的工具，它也有两个缺点：它是一个需要在你的系统上运行的守护进程，并且需要以 root 权限运行，这可能有一定的安全隐患。然而，Podman 在解决这两个问题。

### Podman 介绍

[Podman](https://podman.io/) 是一个容器运行时环境，提供与 Docker 非常相似的功能。正如已经提示的那样，它不需要在你的系统上运行任何守护进程，并且它也可以在没有 root 权限的情况下运行。让我们看看使用 Podman 运行 Linux 容器的一些示例。

#### 使用 Podman 运行容器

其中一个最简单的例子可能是运行 Fedora 容器，在命令行中打印 “Hello world!”：

```
$ podman run --rm -it fedora:28 echo "Hello world!"
```

使用通用 Dockerfile 构建镜像的方式与 Docker 相同：

```
$ cat Dockerfile
FROM fedora:28
RUN dnf -y install cowsay

$ podman build . -t hello-world
... output omitted ...

$ podman run --rm -it hello-world cowsay "Hello!"
```

为了构建容器，Podman 在后台调用另一个名为 Buildah 的工具。你可以阅读最近一篇[关于使用 Buildah 构建容器镜像的文章](https://fedoramagazine.org/daemon-less-container-management-buildah/) —— 它不仅仅是使用典型的 Dockerfile。

除了构建和运行容器外，Podman 还可以与容器托管进行交互。要登录容器注册库，例如广泛使用的 Docker Hub，请运行：

```
$ podman login docker.io
```

为了推送我刚刚构建的镜像，我只需打上标记来代表特定的容器注册库，然后直接推送它。

```
$ podman -t hello-world docker.io/asamalik/hello-world
$ podman push docker.io/asamalik/hello-world
```

顺便说一下，你是否注意到我如何以非 root 用户身份运行所有内容？此外，我的系统上没有运行又大又重的守护进程！

#### 安装 Podman

Podman 默认在 [Silverblue](https://silverblue.fedoraproject.org/) 上提供 —— 一个基于容器的工作流的新一代 Linux 工作站。要在任何 Fedora 版本上安装它，只需运行：

```
$ sudo dnf install podman
```

---

via: <https://fedoramagazine.org/running-containers-with-podman/>

作者：[Adam Šamalík](https://fedoramagazine.org/author/asamalik/) 选题：[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 用户应该试一试 Rust

>
> 在 Linux 系统上安装 Rust 编程语言可能是你近年来所做的最有价值的事情之一。
>
>
>

![](/data/attachment/album/201810/26/090805l94nk97sz87e1yld.jpg)

Rust 是一种相当年轻和现代的编程语言，具有许多使其非常灵活而及其安全的功能。数据显示它正在变得非常受欢迎，连续三年（[2016](https://insights.stackoverflow.com/survey/2016#technology-most-loved-dreaded-and-wanted)、[2017](https://insights.stackoverflow.com/survey/2017#technology-most-loved-dreaded-and-wanted-languages) 和 [2018](https://insights.stackoverflow.com/survey/2018#technology-most-loved-dreaded-and-wanted-languages)）在 Stack Overflow 开发者调查中获得“最受喜爱的编程语言”的第一名。

Rust 也是开源语言的一种，它具有一系列特殊的功能，使得它可以适应许多不同的编程项目。 它最初源于 2006 年 Mozilla 员工的个人项目，几年后（2009 年）被 Mozilla 选为特别项目，然后在 2010 年宣布供公众使用。

Rust 程序运行速度极快，可防止段错误，并能保证线程安全。这些属性使该语言极大地吸引了专注于应用程序安全性的开发人员。Rust 也是一种非常易读的语言，可用于从简单程序到非常大而复杂的项目。

Rust 优点：

* 内存安全 —— Rust 不会受到悬空指针、缓冲区溢出或其他与内存相关的错误的影响。它提供内存安全，无回收垃圾。
* 通用 —— Rust 是适用于任何类型编程的语言
* 快速 —— Rust 在性能上与 C / C++ 相当，但具有更好的安全功能。
* 高效 —— Rust 是为了便于并发编程而构建的。
* 面向项目 —— Rust 具有内置的依赖关系和构建管理系统 Cargo。
* 得到很好的支持 —— Rust 有一个令人印象深刻的[支持社区](https://www.rust-lang.org/en-US/community.html)。

Rust 还强制执行 RAII（<ruby> 资源获取初始化 <rt>  Resource Acquisition Is Initialization </rt></ruby>）。这意味着当一个对象超出范围时，将调用其析构函数并释放其资源，从而提供防止资源泄漏的屏蔽。它提供了功能抽象和一个很棒的[类型系统](https://doc.rust-lang.org/reference/type-system.html)，并具有速度和数学健全性。

简而言之，Rust 是一种令人印象深刻的系统编程语言，具有其它大多数语言所缺乏的功能，使其成为 C、C++ 和 Objective-C 等多年来一直被使用的语言的有力竞争者。

### 安装 Rust

安装 Rust 是一个相当简单的过程。

```
$ curl https://sh.rustup.rs -sSf | sh
```

安装 Rust 后，使用 `rustc --version` 或 `which` 命令显示版本信息。

```
$ which rustc
rustc 1.27.2 (58cc626de 2018-07-18)
$ rustc --version
rustc 1.27.2 (58cc626de 2018-07-18)
```

### Rust 入门

Rust 即使是最简单的代码也与你之前使用过的语言输入的完全不同。

```
$ cat hello.rs
fn main() {
    // Print a greeting
    println!("Hello, world!");
}
```

在这些行中，我们正在设置一个函数（`main`），添加一个描述该函数的注释，并使用 `println` 语句来创建输出。您可以使用下面显示的命令编译然后运行程序。

```
$ rustc hello.rs
$ ./hello
Hello, world!
```

另外，你也可以创建一个“项目”（通常仅用于比这个更复杂的程序！）来保持代码的有序性。

```
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
```

请注意，即使是简单的程序，一旦编译，就会变成相当大的可执行文件。

```
$ ./hello
Hello, world!
$ ls -l hello*
-rwxrwxr-x 1 shs shs 5486784 Sep 23 19:02 hello     <== executable
-rw-rw-r-- 1 shs shs 68 Sep 23 15:25 hello.rs
```

当然，这只是一个开始且传统的“Hello, world!” 程序。 Rust 语言具有一系列可帮助你快速进入高级编程技能的功能。

### 学习 Rust

![](/data/attachment/album/201810/26/091030w78m17u8jodruj0j.png)

*No Starch Press*

Steve Klabnik 和 Carol Nichols 的《[Rust 编程语言](https://nostarch.com/Rust)》 （2018）一书提供了学习 Rust 的最佳方法之一。 这本书由核心开发团队的两名成员撰写，可从 [No Starch Press](https://nostarch.com/Rust) 出版社获得纸制书或者从 [rust-lang.org](https://doc.rust-lang.org/book/2018-edition/index.html) 获得电子书。它已经成为 Rust 开发者社区中的参考书。

在所涉及的众多主题中，你将了解这些高级主题：

* 所有权和 borrowing
* 安全保障
* 测试和错误处理
* 智能指针和多线程
* 高级模式匹配
* 使用 Cargo（内置包管理器）
* 使用 Rust 的高级编译器

#### 目录

* 前言（Nicholas Matsakis 和 Aaron Turon 编写）
* 致谢
* 介绍
* 第 1 章：新手入门
* 第 2 章：猜谜游戏
* 第 3 章：通用编程概念
* 第 4 章：了解所有权
* 第 5 章：结构
* 第 6 章：枚举和模式匹配
* 第 7 章：模块
* 第 8 章：常见集合
* 第 9 章：错误处理
* 第 10 章：通用类型、特征和生命周期
* 第 11 章：测试
* 第 12 章：输入/输出项目
* 第 13 章：迭代器和闭包
* 第 14 章：关于货物和 Crates.io 的更多信息
* 第 15 章：智能指针
* 第 16 章：并发
* 第 17 章：Rust 是面向对象的吗？
* 第 18 章：模式
* 第 19 章：关于生命周期的更多信息
* 第 20 章：高级类型系统功能
* 附录 A：关键字
* 附录 B：运算符和符号
* 附录 C：可衍生的特征
* 附录 D：宏
* 索引

《[Rust 编程语言](https://nostarch.com/Rust)》 将你从基本安装和语言语法带到复杂的主题，例如模块、错误处理、crates（与其他语言中的 “library” 或“package”同义），模块（允许你将你的代码分配到 crate 本身），生命周期等。

可能最重要的是，本书可以让您从基本的编程技巧转向构建和编译复杂、安全且非常有用的程序。

### 结束

如果你已经准备好用一种非常值得花时间和精力学习并且越来越受欢迎的语言进行一些严肃的编程，那么 Rust 是一个不错的选择！

加入 [Facebook](https://www.facebook.com/NetworkWorld/) 和 [LinkedIn](https://www.linkedin.com/company/network-world) 上的 Network World 社区，评论最重要的话题。

---

via: <https://www.networkworld.com/article/3308162/linux/why-you-should-try-rust.html>

作者：[Sandra Henry-Stocker](https://www.networkworld.com/author/Sandra-Henry_Stocker/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[way-ww](https://github.com/way-ww) 校对：[wxy](https://github.com/wxy)

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


使用 Lakka Linux 将你的旧 PC 变成复古游戏主机

>
> 如果你有一台吃灰的旧计算机，你可以用 Lakka Linux 将它变成像 PlayStation 那样的复古游戏主机。
>
>
>

你可能已经了解[专门用于复活旧计算机的 Linux 发行版](https://itsfoss.com/lightweight-linux-beginners/)。但是你知道有个 Linux 发行版专门是为了将旧电脑变成复古游戏主机创建的么？

![Lakka is a Linux distribution specially for retrogaming](/data/attachment/album/201810/26/095819b5enoa7zo8hwwhw7.jpg)

认识下 [Lakka](http://www.lakka.tv/)，它是一个轻量级 Linux 发行版，可以将旧的或低端的计算机（如 Raspberry Pi）变成一个完整的复古游戏主机，

当我说复古游戏主机时，我对主机部分很认真。如果你曾经使用过 Xbox 和 PlayStation，你就会知道典型的主机界面是什么样的。

Lakka 提供类似的界面和类似的体验。我稍后会谈到“体验”。先看一下界面。

![](/data/attachment/album/201810/26/095625eagrgrffrug44vfw.gif)

*Lakka 复古游戏界面*

### Lakka：为复古游戏而生的 Linux 发行版

Lakka 是 [RetroArch](https://www.retroarch.com/) 和 [Libretro](https://www.libretro.com/) 生态系统的官方 Linux 发行版。

RetroArch 是复古游戏模拟器和游戏引擎的前端。你在上面的视频中看到的界面只是 RetroArch。如果你是只想玩复古游戏，只需在当前的 Linux 发行版中安装 RetroArch 即可。

Lakka 提供了带有 Libretro 核心的 RetroArch。因此，你会获得一个预先配置完的操作系统，你可以安装或插入 live USB 并开始玩游戏。

Lakka 是轻量级的，你可以将它安装在大多数老系统或单板计算机上，如 Raspberry Pi 上。

它支持大量的模拟器。你只需要在系统上下载 ROM，Lakka 将从这些 ROM 运行游戏。你可以在[这里](http://www.lakka.tv/powerful/)找到支持的模拟器和硬件列表。

它通过其顺滑的图形界面让你能够在许多计算机和主机上运行经典游戏。设置也是统一的，因此可以一劳永逸地完成配置。

让我总结一下 Lakka 的主要特点：

* RetroArch 中与 PlayStation 类似的界面
* 支持许多复古游戏模拟器
* 支持最多 5 名玩家在同一系统上玩游戏
* 存档允许你随时保存游戏中的进度
* 你可以使用各种图形过滤器改善旧游戏的外表
* 你可以通过网络加入多人游戏
* 开箱即用支持 XBOX360、Dualshock 3 和 8bitdo 等多种游戏手柄
* 连接到 [RetroAchievements](https://retroachievements.org/) 获取奖杯和徽章

### 获取 Lakka

在你继续安装 Lakka 之前，你应该了解它仍在开发中，因此会有一些 bug。

请记住，Lakka 仅支持 MBR 分区。因此，如果在安装时没有读到你的硬盘，这可能是一个原因。

[项目的 FAQ 部分](http://www.lakka.tv/doc/FAQ/)回答了常见的疑问，所以如有任何其他的问题，请参考它。

* [获取 Lakka](http://www.lakka.tv/disclaimer/)

你喜欢复古游戏吗？你使用什么模拟器？你以前用过 Lakka 吗？在评论区与我们分享你的观点。

---

via: <https://itsfoss.com/lakka-retrogaming-linux/>

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

[9]; <http://www.lakka.tv/disclaimer/>


使用 Argbash 来改进你的 Bash 脚本

![](/data/attachment/album/201810/27/092854nrvazffgzfnqaxfw.png)

你编写或维护过有意义的 bash 脚本吗？如果回答是，那么你可能希望它们以标准且健壮的方式接收命令行参数。Fedora 最近得到了[一个很好的附加组件](https://argbash.readthedocs.io/)，它可以帮助你生成更好的脚本。不用担心，它不会花费你很多时间或精力。

### 为什么需要 Argbash?

Bash 是一种解释性的命令行语言，没有标准库。因此，如果你编写 bash 脚本并希望命令行界面符合 [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html) 和 [GNU CLI](https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html) 标准，那么你一般只有两种选择：

1. 直接编写为脚本量身定制的参数解析功能（可使用内置的 `getopts`）。
2. 使用外部 bash 模块。

第一个选项看起来非常愚蠢，因为正确实现接口并非易事。但是，从 [Stack Overflow](https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash) 到 [Bash Hackers](http://wiki.bash-hackers.org/howto/getopts_tutorial) wiki 的各种站点上，它却被认为是最佳选择。

第二个选项看起来更聪明，但使用模块有它自己的问题。最大的问题是你必须将其代码与脚本捆绑在一起。这可能意味着：

* 要么，你将库作为单独的文件分发
* 或者，在脚本的开头包含库代码

有两个文件而不是一个是愚蠢的；但采用一个文件的话，会让一堆上千行的复杂代码污染了你的脚本。

这是 Argbash [项目诞生](https://argbash.readthedocs.io/)的主要原因。Argbash 是一个代码生成器，它为你的脚本生成一个量身定制的解析库。与其他 bash 模块的通用代码不同，它生成你的脚本所需的最少代码。此外，如果你不需要 100% 符合那些 CLI 标准的话，你可以生成更简单的代码。

### 示例

#### 分析

假设你要实现一个脚本，它可以在终端窗口中[绘制条形图](http://wiki.bash-hackers.org/snipplets/print_horizontal_line)，你可以通过重复一个字符选定的次数来做到这一点。这意味着你需要从命令行获取以下信息：

* 哪个字符是组成该行的元素。如果未指定，使用破折号 `-`。 在命令行上，这是个单值定位参数 `character`，其默认值为 `-`。（LCTT 译注：定位参数是指确定位置的参数，此处 `character` 需是命令行的第一个参数）
* 直线的长度。如果未指定，会选择 `80`。 这是一个单值可选参数 `length`，默认值为 `80`。
* Verbose 模式（用于调试）。 这是一个布尔型参数 `verbose`，默认情况下关闭。

由于脚本的主体非常简单，因此本文主要关注从命令行获取用户的输入到合适的脚本变量。Argbash 生成的代码会将参数解析结果保存到 shell 变量 `_arg_character`、`_arg_length` 和 `_arg_verbose` 当中。

#### 执行

接下来，你还需要 `argbash-init` 和 `argbash` bash 脚本，它们是 argbash 包的一部分。因此，运行以下命令：

```
sudo dnf install argbash
```

然后，使用 `argbash-init` 来为 `argbash` 生成模板，它会生成可执行脚本。你需要三个参数：一个名为 `character` 的定位参数，一个可选的 `length` 参数以及一个可选的布尔 `verbose`。将这些传递给 `argbash-init`，然后将输出传递给 `argbash` : `argbash-init --pos character --opt length --opt-bool verbose script-template.sh
argbash script-template.sh -o script
./script`

看到帮助信息了吗？看起来该脚本不知道字符参数的默认选项。因此，看一下 [Argbash API](http://argbash.readthedocs.io/en/stable/guide.html#argbash-api)，然后通过编辑脚本的模板部分来解决问题：

```
# ...
# ARG_OPTIONAL_SINGLE([length],[l],[Length of the line],[80])
# ARG_OPTIONAL_BOOLEAN([verbose],[V],[Debug mode])
# ARG_POSITIONAL_SINGLE([character],[The element of the line],[-])
# ARG_HELP([The line drawer])
# ...
```

Argbash 非常智能，它试图让每个生成的脚本都成为自己的模板，这意味着你不需要存储源模版以供进一步使用，你也不要丢掉生成的 bash 脚本。现在，尝试重新生成如你所预期的下一个线条绘图脚本：

```
argbash script -o script
./script
```

如你所见，一切正常。剩下要做的唯一事情就是完成线条绘图功能。

### 结论

你可能会发现包含解析代码的部分很长，但考虑到它允许你以 `./script.sh x -Vl50` 的方式调用，并且能像 `./script -V -l 50 x` 一样工作。确实需要一些代码才能做到这一点。

但是，通过调用 `argbash-init` 并将参数 `-mode` 设置为 `minimal`，你可以平衡生成的代码复杂度和解析能力，而转向更简单的代码。这个选项将脚本的大小减少了大约 20 行，这相当于生成的解析代码大小减少了大约 25%。另一方面，`full` 模式使脚本更加智能。

如果你想要检查生成的代码，请给 `argbash` 提供参数 `-commented`，它会将注释放入解析代码中，从而揭示各个部分背后的意图。与其他参数解析库相比较，如 [shflags](https://raw.githubusercontent.com/Anvil/bash-argsparse/master/argsparse.sh), [argsparse](https://raw.githubusercontent.com/Anvil/bash-argsparse/master/argsparse.sh) 或 [bash-modules/arguments](https://raw.githubusercontent.com/vlisivka/bash-modules/master/main/bash-modules/src/bash-modules/arguments.sh)，你将看到 Argbash 强大的简单性。如果出现了严重的错误，你需要快速修复解析功能中的一个故障，Argbash 也允许你这样做。

由于你很有可能是 Fedora 用户，因此你可以享受从官方仓库安装命令行 Argbash 的便利。不过，也有一个[在线解析代码生成器](https://argbash.io/generate)服务可以使用。此外，如果你在服务器上使用 Docker 工作，你可以试试 [Argbash Docker 镜像](https://hub.docker.com/r/matejak/argbash/)。

这样你可以让你的脚本具有令用户满意的命令行界面。Argbash 随时为你提供帮助，你只需付出很少的努力。

---

via: <https://fedoramagazine.org/improve-bash-scripts-argbash/>

作者：[Matěj Týč](https://fedoramagazine.org/author/bubla/) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


一窥你安装的 Linux 软件包

>
> 这些最有用的命令可以让你了解安装在你的 Debian 类的 Linux 系统上的包的情况。
>
>
>

![](/data/attachment/album/201810/27/095619ks5en1rsgvguoojs.jpg)

你有没有想过你的 Linux 系统上安装了几千个软件包？ 是的，我说的是“千”。 即使是相当一般的 Linux 系统也可能安装了上千个软件包。 有很多方法可以获得这些包到底是什么包的详细信息。

首先，要在基于 Debian 的发行版（如 Ubuntu）上快速得到已安装的软件包数量，请使用 `apt list --installed`， 如下：

```
$ apt list --installed | wc -l
2067
```

这个数字实际上多了一个，因为输出中包含了 “Listing …” 作为它的第一行。 这个命令会更准确：

```
$ apt list --installed | grep -v "^Listing" | wc -l
2066
```

要获得所有这些包的详细信息，请按以下方式浏览列表：

```
$ apt list --installed | more
Listing...
a11y-profile-manager-indicator/xenial,now 0.1.10-0ubuntu3 amd64 [installed]
account-plugin-aim/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
account-plugin-facebook/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
account-plugin-flickr/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
account-plugin-google/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
account-plugin-jabber/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
account-plugin-salut/xenial,now 3.12.11-0ubuntu3 amd64 [installed]

```

这需要观察很多细节 —— 特别是让你的眼睛在所有 2000 多个文件中徘徊。 它包含包名称、版本等，以及更多但并不是以最易于我们人类解析的显示信息。 `dpkg-query` 使得描述更容易理解，但这些描述会塞满你的命令窗口，除非窗口非常宽。 因此，为了让此篇文章更容易阅读，下面的数据显示已经分成了左右两侧。

左侧：

```
$ dpkg-query -l | more
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                                 Version
+++-==============================================-=================================-
ii  a11y-profile-manager-indicator                 0.1.10-0ubuntu3
ii  account-plugin-aim                             3.12.11-0ubuntu3
ii  account-plugin-facebook                        0.12+16.04.20160126-0ubuntu1
ii  account-plugin-flickr                          0.12+16.04.20160126-0ubuntu1
ii  account-plugin-google                          0.12+16.04.20160126-0ubuntu1
ii  account-plugin-jabber                          3.12.11-0ubuntu3
ii  account-plugin-salut                           3.12.11-0ubuntu3
ii  account-plugin-twitter                         0.12+16.04.20160126-0ubuntu1
rc  account-plugin-windows-live                    0.11+14.04.20140409.1-0ubuntu2
```

右侧：

```
Architecture Description
============-=====================================================================
amd64        Accessibility Profile Manager - Unity desktop indicator
amd64        Messaging account plugin for AIM
all          GNOME Control Center account plugin for single signon - facebook
all          GNOME Control Center account plugin for single signon - flickr
all          GNOME Control Center account plugin for single signon
amd64        Messaging account plugin for Jabber/XMPP
amd64        Messaging account plugin for Local XMPP (Salut)
all          GNOME Control Center account plugin for single signon - twitter
all          GNOME Control Center account plugin for single signon - windows live
```

每行开头的 `ii` 和 `rc` 名称（见上文“左侧”）是包状态指示符。 第一个字母表示包的预期状态：

* `u` – 未知
* `i` – 安装
* `r` – 移除/反安装
* `p` – 清除（也包括配置文件）
* `h` – 保留

第二个代表包的当前状态：

* `n` – 未安装
* `i` – 已安装
* `c` – 配置文件（只安装了配置文件）
* `U` – 未打包
* `F` – 半配置（出于某些原因配置失败）
* `h` – 半安装（出于某些原因配置失败）
* `W` – 等待触发（该包等待另外一个包的触发器）
* `t` – 待定触发（该包被触发）

在通常的双字符字段末尾添加的 `R` 表示需要重新安装。 你可能永远不会碰到这些。

快速查看整体包状态的一种简单方法是计算在不同状态中包含的包的数量：

```
$ dpkg-query -l | tail -n +6 | awk '{print $1}' | sort | uniq -c
 2066 ii
 134 rc
```

我从上面的 `dpkg-query` 输出中排除了前五行，因为这些是标题行，会混淆输出。

这两行基本上告诉我们，在这个系统上，应该安装了 2066 个软件包，而 134 个其他的软件包已被删除，但留下了配置文件。 你始终可以使用以下命令删除程序包的剩余配置文件：

```
$ sudo dpkg --purge xfont-mathml
```

请注意，如果程序包二进制文件和配置文件都已经安装了，则上面的命令将两者都删除。

---

via: <https://www.networkworld.com/article/3242808/linux/peeking-into-your-linux-packages.html>

作者：[Sandra Henry-Stocker](https://www.networkworld.com/author/Sandra-Henry_Stocker/) 译者：[Flowsnow](https://github.com/Flowsnow) 校对：[wxy](https://github.com/wxy)

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


为什么 Python 这么慢？

Python 现在越来越火，已经迅速扩张到包括 DevOps、数据科学、Web 开发、信息安全等各个领域当中。

然而，相比起 Python 扩张的速度，Python 代码的运行速度就显得有点逊色了。

![](/data/attachment/album/201810/27/114058v8793uq037m9007f.jpg)

>
> 在代码运行速度方面，Java、C、C++、C# 和 Python 要如何进行比较呢？并没有一个放之四海而皆准的标准，因为具体结果很大程度上取决于运行的程序类型，而<ruby> 语言基准测试 <rt>  Computer Language Benchmarks Games </rt></ruby>可以作为[衡量的一个方面](http://algs4.cs.princeton.edu/faq/)。
>
>
>

根据我这些年来进行语言基准测试的经验来看，Python 比很多语言运行起来都要慢。无论是使用 [JIT](https://en.wikipedia.org/wiki/Just-in-time_compilation) 编译器的 C＃、Java，还是使用 [AOT](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) 编译器的 C、C++，又或者是 JavaScript 这些解释型语言，Python 都[比它们运行得慢](https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/python.html)。

注意：对于文中的 “Python” ，一般指 CPython 这个官方的实现。当然我也会在本文中提到其它语言的 Python 实现。

>
> 我要回答的是这个问题：对于一个类似的程序，Python 要比其它语言慢 2 到 10 倍不等，这其中的原因是什么？又有没有改善的方法呢？
>
>
>

主流的说法有这些：

* “是<ruby> 全局解释器锁 <rt>  Global Interpreter Lock </rt></ruby>（GIL）的原因”
* “是因为 Python 是解释型语言而不是编译型语言”
* “是因为 Python 是一种动态类型的语言”

哪一个才是是影响 Python 运行效率的主要原因呢？

### 是全局解释器锁的原因吗？

现在很多计算机都配备了具有多个核的 CPU ，有时甚至还会有多个处理器。为了更充分利用它们的处理能力，操作系统定义了一个称为线程的低级结构。某一个进程（例如 Chrome 浏览器）可以建立多个线程，在系统内执行不同的操作。在这种情况下，CPU 密集型进程就可以跨核心分担负载了，这样的做法可以大大提高应用程序的运行效率。

例如在我写这篇文章时，我的 Chrome 浏览器打开了 44 个线程。需要提及的是，基于 POSIX 的操作系统（例如 Mac OS、Linux）和 Windows 操作系统的线程结构、API 都是不同的，因此操作系统还负责对各个线程的调度。

如果你还没有写过多线程执行的代码，你就需要了解一下线程锁的概念了。多线程进程比单线程进程更为复杂，是因为需要使用线程锁来确保同一个内存地址中的数据不会被多个线程同时访问或更改。

CPython 解释器在创建变量时，首先会分配内存，然后对该变量的引用进行计数，这称为<ruby> 引用计数 <rt>  reference counting </rt></ruby>。如果变量的引用数变为 0，这个变量就会从内存中释放掉。这就是在 for 循环代码块内创建临时变量不会增加内存消耗的原因。

而当多个线程内共享一个变量时，CPython 锁定引用计数的关键就在于使用了 GIL，它会谨慎地控制线程的执行情况，无论同时存在多少个线程，解释器每次只允许一个线程进行操作。

#### 这会对 Python 程序的性能有什么影响？

如果你的程序只有单线程、单进程，代码的速度和性能不会受到全局解释器锁的影响。

但如果你通过在单进程中使用多线程实现并发，并且是 IO 密集型（例如网络 IO 或磁盘 IO）的线程，GIL 竞争的效果就很明显了。

![](/data/attachment/album/201810/27/114158pjel0jq0p808p4b8.png)

*由 David Beazley 提供的 GIL 竞争情况图<http://dabeaz.blogspot.com/2010/01/python-gil-visualized.html>*

对于一个 web 应用（例如 Django），同时还使用了 WSGI，那么对这个 web 应用的每一个请求都运行一个**单独**的 Python 解释器，而且每个请求只有一个锁。同时因为 Python 解释器的启动比较慢，某些 WSGI 实现还具有“守护进程模式”，[可以使 Python 进程一直就绪](https://www.slideshare.net/GrahamDumpleton/secrets-of-a-wsgi-master)。

#### 其它的 Python 解释器表现如何？

[PyPy 也是一种带有 GIL 的解释器](http://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil-why)，但通常比 CPython 要快 3 倍以上。

[Jython 则是一种没有 GIL 的解释器](http://www.jython.org/jythonbook/en/1.0/Concurrency.html#no-global-interpreter-lock)，这是因为 Jython 中的 Python 线程使用 Java 线程来实现，并且由 JVM 内存管理系统来进行管理。

#### JavaScript 在这方面又是怎样做的呢？

所有的 Javascript 引擎使用的都是 [mark-and-sweep 垃圾收集算法](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)，而 GIL 使用的则是 CPython 的内存管理算法。

JavaScript 没有 GIL，而且它是单线程的，也不需要用到 GIL， JavaScript 的事件循环和 Promise/Callback 模式实现了以异步编程的方式代替并发。在 Python 当中也有一个类似的 asyncio 事件循环。

### 是因为 Python 是解释型语言吗？

我经常会听到这个说法，但是这过于粗陋地简化了 Python 所实际做的工作了。其实当终端上执行 `python myscript.py` 之后，CPython 会对代码进行一系列的读取、语法分析、解析、编译、解释和执行的操作。

如果你对这一系列过程感兴趣，也可以阅读一下我之前的文章：[在 6 分钟内修改 Python 语言](https://hackernoon.com/modifying-the-python-language-in-7-minutes-b94b0a99ce14) 。

`.pyc` 文件的创建是这个过程的重点。在代码编译阶段，Python 3 会将字节码序列写入 `__pycache__/` 下的文件中，而 Python 2 则会将字节码序列写入当前目录的 `.pyc` 文件中。对于你编写的脚本、导入的所有代码以及第三方模块都是如此。

因此，绝大多数情况下（除非你的代码是一次性的……），Python 都会解释字节码并本地执行。与 Java、C#.NET 相比：

>
> Java 代码会被编译为“中间语言”，由 Java 虚拟机读取字节码，并将其即时编译为机器码。.NET CIL 也是如此，.NET CLR（Common-Language-Runtime）将字节码即时编译为机器码。
>
>
>

既然 Python 像 Java 和 C# 那样都使用虚拟机或某种字节码，为什么 Python 在基准测试中仍然比 Java 和 C# 慢得多呢？首要原因是，.NET 和 Java 都是 JIT 编译的。

<ruby> 即时 <rt>  Just-in-time </rt></ruby>（JIT）编译需要一种中间语言，以便将代码拆分为多个块（或多个帧）。而<ruby> 提前 <rt>  ahead of time </rt></ruby>（AOT）编译器则需要确保 CPU 在任何交互发生之前理解每一行代码。

JIT 本身不会使执行速度加快，因为它执行的仍然是同样的字节码序列。但是 JIT 会允许在运行时进行优化。一个优秀的 JIT 优化器会分析出程序的哪些部分会被多次执行，这就是程序中的“热点”，然后优化器会将这些代码替换为更有效率的版本以实现优化。

这就意味着如果你的程序是多次重复相同的操作时，有可能会被优化器优化得更快。而且，Java 和 C# 是强类型语言，因此优化器对代码的判断可以更为准确。

PyPy 使用了明显快于 CPython 的 JIT。更详细的结果可以在这篇性能基准测试文章中看到：[哪一个 Python 版本最快?](https://hackernoon.com/which-is-the-fastest-version-of-python-2ae7c61a6b2b)。

#### 那为什么 CPython 不使用 JIT 呢？

JIT 也不是完美的，它的一个显著缺点就在于启动时间。 CPython 的启动时间已经相对比较慢，而 PyPy 比 CPython 启动还要慢 2 到 3 倍。Java 虚拟机启动速度也是出了名的慢。.NET CLR 则通过在系统启动时启动来优化体验，而 CLR 的开发者也是在 CLR 上开发该操作系统。

因此如果你有个长时间运行的单一 Python 进程，JIT 就比较有意义了，因为代码里有“热点”可以优化。

不过，CPython 是个通用的实现。设想如果使用 Python 开发命令行程序，但每次调用 CLI 时都必须等待 JIT 缓慢启动，这种体验就相当不好了。

CPython 试图用于各种使用情况。有可能实现[将 JIT 插入到 CPython 中](https://www.slideshare.net/AnthonyShaw5/pyjion-a-jit-extension-system-for-cpython)，但这个改进工作的进度基本处于停滞不前的状态。

>
> 如果你想充分发挥 JIT 的优势，请使用 PyPy。
>
>
>

### 是因为 Python 是一种动态类型的语言吗？

在 C、C++、Java、C#、Go 这些静态类型语言中，必须在声明变量时指定变量的类型。而在动态类型语言中，虽然也有类型的概念，但变量的类型是可改变的。

```
a = 1
a = "foo"
```

在上面这个示例里，Python 将变量 `a` 一开始存储整数类型变量的内存空间释放了，并创建了一个新的存储字符串类型的内存空间，并且和原来的变量同名。

静态类型语言这样的设计并不是为了为难你，而是为了方便 CPU 运行而这样设计的。因为最终都需要将所有操作都对应为简单的二进制操作，因此必须将对象、类型这些高级的数据结构转换为低级数据结构。

Python 也实现了这样的转换，但用户看不到这些转换，也不需要关心这些转换。

不用必须声明类型并不是为了使 Python 运行慢，Python 的设计是让用户可以让各种东西变得动态：可以在运行时更改对象上的方法，也可以在运行时动态添加底层系统调用到值的声明上，几乎可以做到任何事。

但也正是这种设计使得 Python 的优化异常的难。

为了证明我的观点，我使用了一个 Mac OS 上的系统调用跟踪工具 DTrace。CPython 发布版本中没有内置 DTrace，因此必须重新对 CPython 进行编译。以下以 Python 3.6.6 为例：

```
wget https://github.com/python/cpython/archive/v3.6.6.zip
unzip v3.6.6.zip
cd v3.6.6
./configure --with-dtrace
make
```

这样 `python.exe` 将使用 DTrace 追踪所有代码。[Paul Ross 也作过关于 DTrace 的闪电演讲](https://github.com/paulross/dtrace-py#the-lightning-talk)。你可以下载 Python 的 DTrace 启动文件来查看函数调用、执行时间、CPU 时间、系统调用，以及各种其它的内容。

```
sudo dtrace -s toolkit/<tracer>.d -c ‘../cpython/python.exe script.py’
```

`py_callflow` 追踪器[显示](https://cdn-images-1.medium.com/max/1600/1*Lz4UdUi4EwknJ0IcpSJ52g.gif)了程序里调用的所有函数。

那么，Python 的动态类型会让它变慢吗？

* 类型比较和类型转换消耗的资源是比较多的，每次读取、写入或引用变量时都会检查变量的类型
* Python 的动态程度让它难以被优化，因此很多 Python 的替代品能够如此快都是为了提升速度而在灵活性方面作出了妥协
* 而 [Cython](http://cython.org/) 结合了 C 的静态类型和 Python 来优化已知类型的代码，它[可以将](http://notes-on-cython.readthedocs.io/en/latest/std_dev.html)性能提升 **84 倍**。

### 总结

>
> 由于 Python 是一种动态、多功能的语言，因此运行起来会相对缓慢。对于不同的实际需求，可以使用各种不同的优化或替代方案。
>
>
>

例如可以使用异步，引入分析工具或使用多种解释器来优化 Python 程序。

对于不要求启动时间且代码可以充分利用 JIT 的程序，可以考虑使用 PyPy。

而对于看重性能并且静态类型变量较多的程序，不妨使用 [Cython](http://cython.org/)。

#### 延伸阅读

Jake VDP 的优秀文章（略微过时） <https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/>

Dave Beazley 关于 GIL 的演讲 <http://www.dabeaz.com/python/GIL.pdf>

JIT 编译器的那些事 <https://hacks.mozilla.org/2017/02/a-crash-course-in-just-in-time-jit-compilers/>

---

via: <https://hackernoon.com/why-is-python-so-slow-e5074b6fe55b>

作者：[Anthony Shaw](https://hackernoon.com/@anthonypjshaw?source=post_header_lockup) 选题：[oska874](https://github.com/oska874) 译者：[HankChow](https://github.com/HankChow) 校对：[wxy](https://github.com/wxy)

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


坚实的 React 基础：初学者指南

![](/data/attachment/album/201810/28/104728nzehe82q5h9b8fqj.png)

在过去的几个月里，我一直在使用 React 和 React-Native。我已经发布了两个作为产品的应用， [Kiven Aa](https://kivenaa.com/)（React）和 [Pollen Chat](https://play.google.com/store/apps/details?id=com.pollenchat.android)（React Native）。当我开始学习 React 时，我找了一些不仅仅是教我如何用 React 写应用的东西（一个博客，一个视频，一个课程，等等），我也想让它帮我做好面试准备。

我发现的大部分资料都集中在某一单一方面上。所以，这篇文章针对的是那些希望理论与实践完美结合的观众。我会告诉你一些理论，以便你了解幕后发生的事情，然后我会向你展示如何编写一些 React.js 代码。

如果你更喜欢视频形式，我在 [YouTube][<https://youtu.be/WJ6PgzI16I4>] 上传了整个课程，请去看看。

让我们开始……

>
> React.js 是一个用于构建用户界面的 JavaScript 库
>
>
>

你可以构建各种单页应用程序。例如，你希望在用户界面上实时显示变化的聊天软件和电子商务门户。

### 一切都是组件

React 应用由组件组成，数量繁多且互相嵌套。你或许会问：”可什么是组件呢？“

组件是可重用的代码段，它定义了某些功能在 UI 上的外观和行为。 比如，按钮就是一个组件。

让我们看看下面的计算器，当你尝试计算 2 + 2 = 4 -1 = 3（简单的数学题）时，你会在 Google 上看到这个计算器。

![](/data/attachment/album/201810/28/104744a002jj0m8gwkxw2m.png)

*红色标记表示组件*

如上图所示，这个计算器有很多区域，比如展示窗口和数字键盘。所有这些都可以是许多单独的组件或一个巨大的组件。这取决于在 React 中分解和抽象出事物的程度。你为所有这些组件分别编写代码，然后合并这些组件到一个容器中，而这个容器又是一个 React 组件。这样你就可以创建可重用的组件，最终的应用将是一组协同工作的单独组件。

以下是一个你践行了以上原则并可以用 React 编写计算器的方法。

```
<Calculator>
  <DisplayWindow />
  <NumPad>
    <Key number={1}/>
    <Key number={2}/>
    .
    .
    .
    <Key number={9}/>
  </NumPad>
</Calculator>
```

没错！它看起来像HTML代码，然而并不是。我们将在后面的部分中详细探讨它。

### 设置我们的 Playground

这篇教程专注于 React 的基础部分。它没有偏向 Web 或 React Native（开发移动应用）。所以，我们会用一个在线编辑器，这样可以在学习 React 能做什么之前避免 web 或 native 的具体配置。

我已经为读者在 [codepen.io](https://codepen.io/raynesax/pen/MrNmBM) 设置好了开发环境。只需点开[该链接](https://codepen.io/raynesax/pen/MrNmBM)并且阅读 HTML 和 JavaScript 中的所有注释。

### 控制组件

我们已经了解到 React 应用是各种组件的集合，结构为嵌套树。因此，我们需要某种机制来将数据从一个组件传递到另一个组件。

#### 进入 “props”

我们可以使用 `props` 对象将任意数据传递给我们的组件。 React 中的每个组件都会获取 `props` 对象。在学习如何使用 `props` 之前，让我们学习函数式组件。

#### a) 函数式组件

在 React 中，一个函数式组件通过 `props` 对象使用你传递给它的任意数据。它返回一个对象，该对象描述了 React 应渲染的 UI。函数式组件也称为无状态组件。

让我们编写第一个函数式组件。

```
function Hello(props) {
  return <div>{props.name}</div>
}
```

就这么简单。我们只是将 `props` 作为参数传递给了一个普通的 JavaScript 函数并且有返回值。嗯？返回了什么？那个 `<div>{props.name}</div>`。它是 JSX（JavaScript Extended）。我们将在后面的部分中详细了解它。

上面这个函数将在浏览器中渲染出以下 HTML。

```
<!-- If the "props" object is: {name: 'rajat'} -->
<div>
  rajat
</div>
```

>
> 阅读以下有关 JSX 的部分，这一部分解释了如何从我们的 JSX 代码中得到这段 HTML 。
>
>
>

如何在 React 应用中使用这个函数式组件？ 很高兴你问了！ 它就像下面这么简单。

```
<Hello name='rajat' age={26}/>
```

属性 `name` 在上面的代码中变成了 `Hello` 组件里的 `props.name` ，属性 `age` 变成了 `props.age` 。

>
> 记住！ 你可以将一个 React 组件嵌套在其他 React 组件中。
>
>
>

让我们在 codepen playground 使用 `Hello` 组件。用我们的 `Hello` 组件替换 `ReactDOM.render()` 中的 `div`，并在底部窗口中查看更改。

```
function Hello(props) {
  return <div>{props.name}</div>
}

ReactDOM.render(<Hello name="rajat"/>, document.getElementById('root'));
```

>
> 但是如果你的组件有一些内部状态怎么办？例如，像下面的计数器组件一样，它有一个内部计数变量，它在 `+` 和 `-` 键按下时发生变化。
>
>
>

![](/data/attachment/album/201810/28/104630blf1tp07171zt1h4.gif)

*具有内部状态的 React 组件*

#### b) 基于类的组件

基于类的组件有一个额外属性 `state` ，你可以用它存放组件的私有数据。我们可以用 `class` 表示法重写我们的 `Hello` 。由于这些组件具有状态，因此这些组件也称为有状态组件。

```
class Counter extends React.Component {
  // this method should be present in your component
  render() {
    return (
      <div>
        {this.props.name}
      </div>
    );
  }
}
```

我们继承了 React 库的 `React.Component` 类以在 React 中创建基于类的组件。在[这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)了解更多有关 JavaScript 类的东西。

`render()` 方法必须存在于你的类中，因为 React 会查找此方法，用以了解它应在屏幕上渲染的 UI。为了使用这种内部状态，我们首先要在组件

要使用这种内部状态，我们首先必须按以下方式初始化组件类的构造函数中的状态对象。

```
class Counter extends React.Component {
  constructor() {
    super();

    // define the internal state of the component
    this.state = {name: 'rajat'}
  }

  render() {
    return (
      <div>
        {this.state.name}
      </div>
    );
  }
}

// Usage:
// In your react app: <Counter />
```

类似地，可以使用 `this.props` 对象在我们基于类的组件内访问 `props`。

要设置 `state`，请使用 `React.Component` 的 `setState()`。 在本教程的最后一部分中，我们将看到一个这样的例子。

>
> 提示：永远不要在 `render()` 函数中调用 `setState()`，因为 `setState` 会导致组件重新渲染，这将导致无限循环。
>
>
>

![](/data/attachment/album/201810/28/104806ilinyzkkd5v88n4m.png)

*基于类的组件具有可选属性 “state”。*

除了 `state` 以外，基于类的组件有一些声明周期方法比如 `componentWillMount()`。你可以利用这些去做初始化 `state`这样的事， 可是那将超出这篇文章的范畴。

### JSX

JSX 是 JavaScript Extended 的缩写，它是一种编写 React 组件的方法。使用 JSX，你可以在类 XML 标签中获得 JavaScript 的全部力量。

你把 JavaScript 表达式放在 `{}` 里。下面是一些有效的 JSX 例子。

```
 <button disabled={true}>Press me!</button>
 <button disabled={true}>Press me {3+1} times!</button>;
 <div className='container'><Hello /></div>
```

它的工作方式是你编写 JSX 来描述你的 UI 应该是什么样子。像 Babel 这样的转码器将这些代码转换为一堆 `React.createElement()` 调用。然后，React 库使用这些 `React.createElement()` 调用来构造 DOM 元素的树状结构。对于 React 的网页视图或 React Native 的 Native 视图，它将保存在内存中。

React 接着会计算它如何在展示给用户的 UI 的内存中有效地模仿这个树。此过程称为 [reconciliation](https://reactjs.org/docs/reconciliation.html)。完成计算后，React 会对屏幕上的真正 UI 进行更改。

![](/data/attachment/album/201810/28/104817g6jgbjnwagfnze0r.png)

*React 如何将你的 JSX 转化为描述应用 UI 的树。*

你可以使用 [Babel 的在线 REPL](https://babeljs.io/repl) 查看当你写一些 JSX 的时候，React 的真正输出。

![](/data/attachment/album/201810/28/104830m4184mdrdh48888t.png)

*使用Babel REPL 转换 JSX 为普通 JavaScript*

>
> 由于 JSX 只是 `React.createElement()` 调用的语法糖，因此可以在没有 JSX 的情况下使用 React。
>
>
>

现在我们了解了所有的概念，所以我们已经准备好编写我们之前看到之前的 GIF 图中的计数器组件。

代码如下，我希望你已经知道了如何在我们的 playground 上渲染它。

```
class Counter extends React.Component {
  constructor(props) {
    super(props);

    this.state = {count: this.props.start || 0}

    // the following bindings are necessary to make `this` work in the callback
    this.inc = this.inc.bind(this);
    this.dec = this.dec.bind(this);
  }

  inc() {
    this.setState({
      count: this.state.count + 1
    });
  }

  dec() {
    this.setState({
      count: this.state.count - 1
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.inc}>+</button>
        <button onClick={this.dec}>-</button>
        <div>{this.state.count}</div>
      </div>
    );
  }
}
```

以下是关于上述代码的一些重点。

1. JSX 使用 `驼峰命名` ，所以 `button` 的 属性是 `onClick`，不是我们在HTML中用的 `onclick`。
2. 绑定 `this` 是必要的，以便在回调时工作。 请参阅上面代码中的第8行和第9行。

最终的交互式代码位于[此处](https://codepen.io/raynesax/pen/QaROqK)。

有了这个，我们已经到了 React 速成课程的结束。我希望我已经阐明了 React 如何工作，以及如何使用 React 来构建更大的应用程序，使用更小和可重用的组件。

---

via: <https://medium.freecodecamp.org/rock-solid-react-js-foundations-a-beginners-guide-c45c93f5a923>

作者：[Rajat Saxena](https://medium.freecodecamp.org/@rajat1saxena) 译者：[GraveAccent](https://github.com/GraveAccent) 校对：[wxy](https://github.com/wxy)

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


面向系统管理员的容器手册

Summary: 你所需了解的容器如何工作的知识。

你所需了解的容器如何工作的知识。

>
> 你所需了解的容器如何工作的知识。
>
>
>

![](/data/attachment/album/201810/28/111518jruxxoukh0txu447.jpg)

现在人们严重过度使用了“容器”这个术语。另外，对不同的人来说，它可能会有不同的含义，这取决于上下文。

传统的 Linux 容器只是系统上普通的进程。一组进程与另外一组进程是相互隔离的，实现方法包括：资源限制（控制组 [cgoups]）、Linux 安全限制（文件权限，基于 Capability 的安全模块、SELinux、AppArmor、seccomp 等）还有名字空间（进程 ID、网络、挂载等）。

如果你启动一台现代 Linux 操作系统，使用 `cat /proc/PID/cgroup` 命令就可以看到该进程是属于一个控制组的。还可以从 `/proc/PID/status` 文件中查看进程的 Capability 信息，从 `/proc/self/attr/current` 文件中查看进程的 SELinux 标签信息，从 `/proc/PID/ns` 目录下的文件查看进程所属的名字空间。因此，如果把容器定义为带有资源限制、Linux 安全限制和名字空间的进程，那么按照这个定义，Linux 操作系统上的每一个进程都在一个容器里。因此我们常说 [Linux 就是容器，容器就是 Linux](https://www.redhat.com/en/blog/containers-are-linux)。而**容器运行时**是这样一种工具，它调整上述资源限制、安全限制和名字空间，并启动容器。

Docker 引入了**容器镜像**的概念，镜像是一个普通的 TAR 包文件，包含了：

* **rootfs（容器的根文件系统）**：一个目录，看起来像是操作系统的普通根目录（`/`），例如，一个包含 `/usr`, `/var`, `/home` 等的目录。
* **JSON 文件（容器的配置）**：定义了如何运行 rootfs；例如，当容器启动的时候要在 rootfs 里运行什么命令（`CMD`）或者入口（`ENTRYPOINT`），给容器定义什么样的环境变量（`ENV`），容器的工作目录（`WORKDIR`）是哪个，以及其他一些设置。

Docker 把 rootfs 和 JSON 配置文件打包成**基础镜像**。你可以在这个基础之上，给 rootfs 安装更多东西，创建新的 JSON 配置文件，然后把相对于原始镜像的不同内容打包到新的镜像。这种方法创建出来的是**分层的镜像**。

<ruby>   开放容器计划  <rt>  Open Container Initiative </rt></ruby>（OCI）标准组织最终把容器镜像的格式标准化了，也就是 <ruby>   镜像规范  <rt>  OCI Image Specification </rt></ruby>（OCI）。

用来创建容器镜像的工具被称为**容器镜像构建器**。有时候容器引擎做这件事情，不过可以用一些独立的工具来构建容器镜像。

Docker 把这些容器镜像（**tar 包**）托管到 web 服务中，并开发了一种协议来支持从 web 拉取镜像，这个 web 服务就叫<ruby> 容器仓库 <rt>  container registry </rt></ruby>。

**容器引擎**是能从镜像仓库拉取镜像并装载到**容器存储**上的程序。容器引擎还能启动**容器运行时**（见下图）。

![](/data/attachment/album/201810/28/111529awgwuyf1wii6zff5.png)

容器存储一般是<ruby> 写入时复制 <rt>  copy-on-write </rt></ruby>（COW）的分层文件系统。从容器仓库拉取一个镜像时，其中的 rootfs 首先被解压到磁盘。如果这个镜像是多层的，那么每一层都会被下载到 COW 文件系统的不同分层。 COW 文件系统保证了镜像的每一层独立存储，这最大化了多个分层镜像之间的文件共享程度。容器引擎通常支持多种容器存储类型，包括 `overlay`、`devicemapper`、`btrfs`、`aufs` 和 `zfs`。

容器引擎将容器镜像下载到容器存储中之后，需要创建一份**容器运行时配置**，这份配置是用户/调用者的输入和镜像配置的合并。例如，容器的调用者可能会调整安全设置，添加额外的环境变量或者挂载一些卷到容器中。

容器运行时配置的格式，和解压出来的 rootfs 也都被开放容器计划 OCI 标准组织做了标准化，称为 [OCI 运行时规范](https://github.com/opencontainers/runtime-spec)。

最终，容器引擎启动了一个**容器运行时**来读取运行时配置，修改 Linux 控制组、安全限制和名字空间，并执行容器命令来创建容器的 **PID 1** 进程。至此，容器引擎已经可以把容器的标准输入/标准输出转给调用方，并控制容器了（例如，`stop`、`start`、`attach`）。

值得一提的是，现在出现了很多新的容器运行时，它们使用 Linux 的不同特性来隔离容器。可以使用 KVM 技术来隔离容器（想想迷你虚拟机），或者使用其他虚拟机监视器策略（例如拦截所有从容器内的进程发起的系统调用）。既然我们有了标准的运行时规范，这些工具都能被相同的容器引擎来启动。即使在 Windows 系统下，也可以使用 OCI 运行时规范来启动 Windows 容器。

容器编排器是一个更高层次的概念。它是在多个不同的节点上协调容器执行的工具。容器编排工具通过和容器引擎的通信来管理容器。编排器控制容器引擎做容器的启动和容器间的网络连接，它能够监控容器，在负载变高的时候进行容器扩容。

---

via: <https://opensource.com/article/18/8/sysadmins-guide-containers>

作者：[Daniel J Walsh](https://opensource.com/users/rhatdan) 选题：[lujun9972](https://github.com/lujun9972) 译者：[belitex](https://github.com/belitex) 校对：[wxy](https://github.com/wxy)

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


如何构建 RPM 包

Summary: 节省跨多个主机安装文件和脚本的时间和精力。

节省跨多个主机安装文件和脚本的时间和精力。

>
> 节省跨多个主机安装文件和脚本的时间和精力。
>
>
>

![](/data/attachment/album/201810/28/125431qw2n6p643hww4wzy.jpg)

自20多年前我开始使用 Linux 以来，我已经使用过基于 rpm 的软件包管理器在 Red Hat 和 Fedora Linux 系统上安装软件。我使用过 `rpm` 程序本身，还有 `yum` 和 `dnf` ，用于在我的 Linux 主机上安装和更新软件包，`dnf` 是 `yum` 的一个近亲。 `yum` 和 `dnf` 工具是 `rpm` 实用程序的包装器，它提供了其他功能，例如查找和安装包依赖项的功能。

多年来，我创建了许多 Bash 脚本，其中一些脚本具有单独的配置文件，我希望在大多数新计算机和虚拟机上安装这些脚本。这也能解决安装所有这些软件包需要花费大量时间的难题，因此我决定通过创建一个 rpm 软件包来自动执行该过程，我可以将其复制到目标主机并将所有这些文件安装在适当的位置。虽然 `rpm` 工具以前用于构建 rpm 包，但该功能已被删除，并且创建了一个新工具来构建新的 rpm。

当我开始这个项目时，我发现很少有关于创建 rpm 包的信息，但我找到了一本书，名为《Maximum RPM》，这本书才帮我弄明白了。这本书现在已经过时了，我发现的绝大多数信息都是如此。它也已经绝版，用过的副本也需要花费数百美元。[Maximum RPM](http://ftp.rpm.org/max-rpm/) 的在线版本是免费提供的，并保持最新。该 [RPM 网站](http://rpm.org/index.html)还有其他网站的链接，这些网站上有很多关于 rpm 的文档。其他的信息往往是简短的，显然都是假设你已经对该过程有了很多了解。

此外，我发现的每个文档都假定代码需要在开发环境中从源代码编译。我不是开发人员。我是一个系统管理员，我们系统管理员有不同的需求，因为我们不需要或者我们不应该为了管理任务而去编译代码；我们应该使用 shell 脚本。所以我们没有源代码，因为它需要被编译成二进制可执行文件。我们拥有的源代码也应该是可执行的。

在大多数情况下，此项目应作为非 root 用户执行。 rpm 包永远不应该由 root 用户构建，而只能由非特权普通用户构建。我将指出哪些部分应该以 root 身份执行，哪些部分应由非 root，非特权用户执行。

### 准备

首先，打开一个终端会话，然后 `su` 到 root 用户。 请务必使用 `-` 选项以确保启用完整的 root 环境。 我不认为系统管理员应该使用 `sudo` 来执行任何管理任务。 在我的个人博客文章中可以找出为什么：[真正的系统管理员不要使用 sudo](http://www.both.org/?p=960)。

```
[student@testvm1 ~]$ su -
Password:
[root@testvm1 ~]#
```

创建可用于此项目的普通用户 student，并为该用户设置密码。

```
[root@testvm1 ~]# useradd -c "Student User" student
[root@testvm1 ~]# passwd student
Changing password for user student.
New password: <Enter the password>
Retype new password: <Enter the password>
passwd: all authentication tokens updated successfully.
[root@testvm1 ~]#
```

构建 rpm 包需要 `rpm-build` 包，该包可能尚未安装。 现在以 root 身份安装它。 请注意，此命令还将安装多个依赖项。 数量可能会有所不同，具体取决于主机上已安装的软件包； 它在我的测试虚拟机上总共安装了 17 个软件包，这是非常小的。

```
dnf install -y rpm-build
```

除非另有明确指示，否则本项目的剩余部分应以普通用户用户 student 来执行。 打开另一个终端会话并使用 `su` 切换到该用户以执行其余步骤。 使用以下命令从 GitHub 下载我准备好的开发目录结构 utils.tar 这个<ruby> tar 包 <rt>  tarball </rt></ruby>（LCTT 译注：tarball 是以 tar 命令来打包和压缩的文件的统称）：

```
wget https://github.com/opensourceway/how-to-rpm/raw/master/utils.tar
```

此 tar 包包含将由最终 `rpm` 程序安装的所有文件和 Bash 脚本。 还有一个完整的 spec 文件，你可以使用它来构建 rpm。 我们将详细介绍 spec 文件的每个部分。

作为普通学生 student，使用你的家目录作为当前工作目录（`pwd`），解压缩 tar 包。

```
[student@testvm1 ~]$ cd ; tar -xvf utils.tar
```

使用 `tree` 命令验证 `~/development` 的目录结构和包含的文件，如下所示：

```
[student@testvm1 ~]$ tree development/
development/
├── license
│   ├── Copyright.and.GPL.Notice.txt
│   └── GPL_LICENSE.txt
├── scripts
│   ├── create_motd
│   ├── die
│   ├── mymotd
│   └── sysdata
└── spec
    └── utils.spec

3 directories, 7 files
[student@testvm1 ~]$
```

`mymotd` 脚本创建一个发送到标准输出的“当日消息”数据流。 `create_motd` 脚本运行 `mymotd` 脚本并将输出重定向到 `/etc/motd` 文件。 此文件用于向使用 SSH 远程登录的用户显示每日消息。

`die` 脚本是我自己的脚本，它将 `kill` 命令包装在一些代码中，这些代码可以找到与指定字符串匹配的运行程序并将其终止。 它使用 `kill -9` 来确保 `kill` 命令一定会执行。

`sysdata` 脚本可以显示有关计算机硬件，还有已安装的 Linux 版本，所有已安装的软件包以及硬盘驱动器元数据等数万行数据。 我用它来记录某个时间点的主机状态。 我以后可以用它作为参考。 我曾经这样做是为了维护我为客户安装的主机记录。

你可能需要将这些文件和目录的所有权更改为 `student:student` 。 如有必要，使用以下命令执行此操作：

```
chown -R student:student development
```

此文件树中的大多数文件和目录将通过你在此项目期间创建的 rpm 包安装在 Fedora 系统上。

### 创建构建目录结构

`rpmbuild` 命令需要非常特定的目录结构。 你必须自己创建此目录结构，因为没有提供自动方式。 在家目录中创建以下目录结构：

```
~ ─ rpmbuild
    ├── RPMS
    │   └── noarch
    ├── SOURCES
    ├── SPECS
    └── SRPMS
```

我们不会创建 `rpmbuild/RPMS/X86_64` 目录，因为它是特定于体系结构编译的 64 位二进制文件。 我们有 shell 脚本，不是特定于体系结构的。 实际上，我们也不会使用 `SRPMS` 目录，它将包含编译器的源文件。

### 检查 spec 文件

每个 spec 文件都有许多部分，其中一些部分可能会被忽视或省略，取决于 rpm 构建的具体情况。 这个特定的 spec 文件不是工作所需的最小文件的示例，但它是一个包含不需要编译的文件的中等复杂 spec 文件的很好例子。 如果需要编译，它将在 `%build` 部分中执行，该部分在此 spec 文件中省略掉了，因为它不是必需的。

#### 前言

这是 spec 文件中唯一没有标签的部分。 它包含运行命令 `rpm -qi [Package Name]` 时看到的大部分信息。 每个数据都是一行，由标签和标签值的文本数据组成。

```
###############################################################################
# Spec file for utils
################################################################################
# Configured to be built by user student or other non-root user
################################################################################
#
Summary: Utility scripts for testing RPM creation
Name: utils
Version: 1.0.0
Release: 1
License: GPL
URL: http://www.both.org
Group: System
Packager: David Both
Requires: bash
Requires: screen
Requires: mc
Requires: dmidecode
BuildRoot: ~/rpmbuild/

# Build with the following syntax:
# rpmbuild --target noarch -bb utils.spec
```

`rpmbuild` 程序会忽略注释行。我总是喜欢在本节中添加注释，其中包含创建包所需的 `rpmbuild` 命令的确切语法。

`Summary` 标签是包的简短描述。

`Name`、`Version` 和 `Release` 标签用于创建 rpm 文件的名称，如 `utils-1.00-1.rpm`。通过增加发行版号码和版本号，你可以创建 rpm 包去更新旧版本的。

`License` 标签定义了发布包的许可证。我总是使用 GPL 的一个变体。指定许可证对于澄清包中包含的软件是开源的这一事实非常重要。这也是我将 `License` 和 `GPL` 语句包含在将要安装的文件中的原因。

`URL` 通常是项目或项目所有者的网页。在这种情况下，它是我的个人网页。

`Group` 标签很有趣，通常用于 GUI 应用程序。 `Group` 标签的值决定了应用程序菜单中的哪一组图标将包含此包中可执行文件的图标。与 `Icon` 标签（我们此处未使用）一起使用时，`Group` 标签允许在应用程序菜单结构中添加用于启动程序的图标和所需信息。

`Packager` 标签用于指定负责维护和创建包的人员或组织。

`Requires` 语句定义此 rpm 包的依赖项。每个都是包名。如果其中一个指定的软件包不存在，DNF 安装实用程序将尝试在 `/etc/yum.repos.d` 中定义的某个已定义的存储库中找到它，如果存在则安装它。如果 DNF 找不到一个或多个所需的包，它将抛出一个错误，指出哪些包丢失并终止。

`BuildRoot` 行指定顶级目录，`rpmbuild` 工具将在其中找到 spec 文件，并在构建包时在其中创建临时目录。完成的包将存储在我们之前指定的 `noarch` 子目录中。

注释显示了构建此程序包的命令语法，包括定义了目标体系结构的 `–target noarch` 选项。因为这些是 Bash 脚本，所以它们与特定的 CPU 架构无关。如果省略此选项，则构建将选用正在执行构建的 CPU 的体系结构。

`rpmbuild` 程序可以针对许多不同的体系结构，并且使用 `--target` 选项允许我们在不同的体系结构主机上构建特定体系结构的包，其具有与执行构建的体系结构不同的体系结构。所以我可以在 x86\_64 主机上构建一个用于 i686 架构的软件包，反之亦然。

如果你有自己的网站，请将打包者的名称更改为你自己的网站。

#### 描述部分（`%description`）

spec 文件的 `%description` 部分包含 rpm 包的描述。 它可以很短，也可以包含许多信息。 我们的 `%description` 部分相当简洁。

```
%description
A collection of utility scripts for testing RPM creation.
```

#### 准备部分（`%prep`）

`%prep` 部分是在构建过程中执行的第一个脚本。 在安装程序包期间不会执行此脚本。

这个脚本只是一个 Bash shell 脚本。 它准备构建目录，根据需要创建用于构建的目录，并将相应的文件复制到各自的目录中。 这将包括作为构建的一部分的完整编译所需的源代码。

`$RPM_BUILD_ROOT` 目录表示已安装系统的根目录。 在 `$RPM_BUILD_ROOT` 目录中创建的目录是真实文件系统中的绝对路径，例如 `/user/local/share/utils`、`/usr/local/bin` 等。

对于我们的包，我们没有预编译源，因为我们的所有程序都是 Bash 脚本。 因此，我们只需将这些脚本和其他文件复制到已安装系统的目录中。

```
%prep
################################################################################
# Create the build tree and copy the files from the development directories    #
# into the build tree.                                                         #
################################################################################
echo "BUILDROOT = $RPM_BUILD_ROOT"
mkdir -p $RPM_BUILD_ROOT/usr/local/bin/
mkdir -p $RPM_BUILD_ROOT/usr/local/share/utils

cp /home/student/development/utils/scripts/* $RPM_BUILD_ROOT/usr/local/bin
cp /home/student/development/utils/license/* $RPM_BUILD_ROOT/usr/local/share/utils
cp /home/student/development/utils/spec/* $RPM_BUILD_ROOT/usr/local/share/utils

exit
```

请注意，本节末尾的 `exit` 语句是必需的。

#### 文件部分（`%files`）

spec 文件的 `%files` 这一部分定义了要安装的文件及其在目录树中的位置。 它还指定了要安装的每个文件的文件属性（`%attr`）以及所有者和组所有者。 文件权限和所有权是可选的，但我建议明确设置它们以消除这些属性在安装时不正确或不明确的任何可能性。 如果目录尚不存在，则会在安装期间根据需要创建目录。

```
%files
%attr(0744, root, root) /usr/local/bin/*
%attr(0644, root, root) /usr/local/share/utils/*
```

#### 安装前（`%pre`）

在我们的实验室项目的 spec 文件中，此部分为空。 这应该放置那些需要 rpm 中的文件安装前执行的脚本。

#### 安装后（`%post`）

spec 文件的这一部分是另一个 Bash 脚本。 这个在文件安装后运行。 此部分几乎可以是你需要或想要的任何内容，包括创建文件、运行系统命令以及重新启动服务以在进行配置更改后重新初始化它们。 我们的 rpm 包的 `%post` 脚本执行其中一些任务。

```
%post
################################################################################
# Set up MOTD scripts                                                          #
################################################################################
cd /etc
# Save the old MOTD if it exists
if [ -e motd ]
then
   cp motd motd.orig
fi
# If not there already, Add link to create_motd to cron.daily
cd /etc/cron.daily
if [ ! -e create_motd ]
then
   ln -s /usr/local/bin/create_motd
fi
# create the MOTD for the first time
/usr/local/bin/mymotd > /etc/motd
```

此脚本中包含的注释应明确其用途。

#### 卸载后（`%postun`）

此部分包含将在卸载 rpm 软件包后运行的脚本。 使用 `rpm` 或 `dnf` 删除包会删除文件部分中列出的所有文件，但它不会删除安装后部分创建的文件或链接，因此我们需要在本节中处理。

此脚本通常由清理任务组成，只是清除以前由 `rpm` 安装的文件，但 rpm 本身无法完成清除。 对于我们的包，它包括删除 `%post` 脚本创建的链接并恢复 motd 文件的已保存原件。

```
%postun
# remove installed files and links
rm /etc/cron.daily/create_motd

# Restore the original MOTD if it was backed up
if [ -e /etc/motd.orig ]
then
   mv -f /etc/motd.orig /etc/motd
fi
```

#### 清理（`%clean`）

这个 Bash 脚本在 rpm 构建过程之后开始清理。 下面 `%clean` 部分中的两行删除了 `rpm-build` 命令创建的构建目录。 在许多情况下，可能还需要额外的清理。

```
%clean
rm -rf $RPM_BUILD_ROOT/usr/local/bin
rm -rf $RPM_BUILD_ROOT/usr/local/share/utils
```

#### 变更日志（`%changelog`）

此可选的文本部分包含 rpm 及其包含的文件的变更列表。最新的变更记录在本部分顶部。

```
%changelog
* Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>
  - The original package includes several useful scripts. it is
    primarily intended to be used to illustrate the process of
    building an RPM.
```

使用你自己的姓名和电子邮件地址替换标题行中的数据。

### 构建 rpm

spec 文件必须位于 `rpmbuild` 目录树的 `SPECS` 目录中。 我发现最简单的方法是创建一个指向该目录中实际 spec 文件的链接，以便可以在开发目录中对其进行编辑，而无需将其复制到 `SPECS` 目录。 将 `SPECS` 目录设为当前工作目录，然后创建链接。

```
cd ~/rpmbuild/SPECS/
ln -s ~/development/spec/utils.spec
```

运行以下命令以构建 rpm。 如果没有错误发生，只需要花一点时间来创建 rpm。

```
rpmbuild --target noarch -bb utils.spec
```

检查 `~/rpmbuild/RPMS/noarch` 目录以验证新的 rpm 是否存在。

```
[student@testvm1 ~]$ cd rpmbuild/RPMS/noarch/
[student@testvm1 noarch]$ ll
total 24
-rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm
[student@testvm1 noarch]$
```

### 测试 rpm

以 root 用户身份安装 rpm 以验证它是否正确安装并且文件是否安装在正确的目录中。 rpm 的确切名称将取决于你在前言部分中标签的值，但如果你使用了示例中的值，则 rpm 名称将如下面的示例命令所示：

```
[root@testvm1 ~]# cd /home/student/rpmbuild/RPMS/noarch/
[root@testvm1 noarch]# ll
total 24
-rw-rw-r--. 1 student student 24364 Aug 30 10:00 utils-1.0.0-1.noarch.rpm
[root@testvm1 noarch]# rpm -ivh utils-1.0.0-1.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:utils-1.0.0-1                    ################################# [100%]
```

检查 `/usr/local/bin` 以确保新文件存在。 你还应验证是否已创建 `/etc/cron.daily` 中的 `create_motd` 链接。

使用 `rpm -q --changelog utils` 命令查看更改日志。 使用 `rpm -ql utils` 命令（在 `ql` 中为小写 `L` ）查看程序包安装的文件。

```
[root@testvm1 noarch]# rpm -q --changelog utils
* Wed Aug 29 2018 Your Name <Youremail@yourdomain.com>
- The original package includes several useful scripts. it is
    primarily intended to be used to illustrate the process of
    building an RPM.

[root@testvm1 noarch]# rpm -ql utils
/usr/local/bin/create_motd
/usr/local/bin/die
/usr/local/bin/mymotd
/usr/local/bin/sysdata
/usr/local/share/utils/Copyright.and.GPL.Notice.txt
/usr/local/share/utils/GPL_LICENSE.txt
/usr/local/share/utils/utils.spec
[root@testvm1 noarch]#
```

删除包。

```
rpm -e utils
```

### 试验

现在，你将更改 spec 文件以要求一个不存在的包。 这将模拟无法满足的依赖关系。 在现有依赖行下立即添加以下行：

```
Requires: badrequire
```

构建包并尝试安装它。 显示什么消息？

我们使用 `rpm` 命令来安装和删除 `utils` 包。 尝试使用 `yum` 或 `dnf` 安装软件包。 你必须与程序包位于同一目录中，或指定程序包的完整路径才能使其正常工作。

### 总结

在这篇对创建 rpm 包的基础知识的概览中，我们没有涉及很多标签和很多部分。 下面列出的资源可以提供更多信息。 构建 rpm 包并不困难；你只需要正确的信息。 我希望这对你有所帮助——我花了几个月的时间来自己解决问题。

我们没有涵盖源代码构建，但如果你是开发人员，那么从这一点开始应该是一个简单的步骤。

创建 rpm 包是另一种成为懒惰系统管理员的好方法，可以节省时间和精力。 它提供了一种简单的方法来分发和安装那些我们作为系统管理员需要在许多主机上安装的脚本和其他文件。

### 资料

* Edward C. Baily，《Maximum RPM》，Sams 出版于 2000 年，ISBN 0-672-31105-4
* Edward C. Baily，《[Maximum RPM](http://ftp.rpm.org/max-rpm/)》，更新在线版本
* [RPM 文档](http://rpm.org/documentation.html)：此网页列出了 rpm 的大多数可用在线文档。 它包括许多其他网站的链接和有关 rpm 的信息。

---

via: <https://opensource.com/article/18/9/how-build-rpm-packages>

作者：[David Both](https://opensource.com/users/dboth) 选题：[lujun9972](https://github.com/lujun9972) 译者：[Flowsnow](https://github.com/Flowsnow) 校对：[wxy](https://github.com/wxy)

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


24 个必备的 Linux 应用程序

![](/data/attachment/album/201810/28/190052elhoxx7rzl2lxr7r.png)

>
> 提要：Linux 上必备的应用程序是什么呢？这个答案具有主观性并取决于你使用 Linux 桌面的目的是什么。但确实存在一些必备的并且大部分 Linux 用户都会安装的应用程序。接下来我们会列举出那些在所有 Linux 发行版上你都会安装的最优秀的 Linux 应用程序。
>
>
>

在 Linux 的世界中，所有东西都由你选择。你要选择一个发行版？你能找到一大把。你想要找到一个称心的音乐播放器？同样会有许多选择。

但它们并非全部遵循相同的设计理念 —— 其中一些可能追求极致轻量化而另一些会提供数不清的特性。因此想要找到正中需求的应用程序会成为相当令人头疼的繁重任务。那就让我们来缓解你的头疼吧。

### 对于 Linux 用户来说最优秀的自由软件

接下来我将罗列一系列在不同应用场景下我偏爱的必备 Linux 自由软件。当然此处我并非在说它们是最好的，但确实是在特定类别下我尝试的一系列软件中最喜欢的。也同样欢迎你在评论区介绍你最喜欢的应用程序。

同时我们也制作了关于此次应用清单的[视频](https://youtu.be/awawJnkUbWs)。在 YouTube 上订阅我们的频道获取更多的 Linux 视频。

### 网页浏览器

![网页浏览器](/data/attachment/album/201810/28/190103u62l9o9iy4ssae4o.jpg)

*网页浏览器*

#### Google Chrome

[Google Chrome](https://www.google.com/chrome/browser) 是一个强大并且功能完善的浏览器解决方案，它拥有完美的同步功能以及丰富的扩展。如果你喜欢 Google 的生态系统那么 Google Chrome 毫无疑问会是你的菜。如果你想要更加开源的解决方案，你可以尝试 [Chromium](https://www.chromium.org/Home)，它是 Google Chrome 的上游项目。

#### Firefox

如果你不是 Google Chrome 的粉丝，你可以尝试 [Firefox](https://www.mozilla.org/en-US/firefox)。它一直以来都是一个非常稳定并且健壮的网页浏览器。

#### Vivaldi

当然，如果你想要尝试点不同的新东西，你可以尝试 [Vivaldi](https://vivaldi.com)。Vivaldi 是一个完全重新设计的网页浏览器，它由 Opera 浏览器项目的前成员基于 Chromium 项目而创建。Vivaldi 轻量并且可定制，虽然它还非常年轻并且在某些特性上仍不完善，但它仍能让你眼前一亮并且优雅地工作。

* [推荐阅读：[回顾] Otter 浏览器为 Opera 爱好者带来了希望](https://itsfoss.com/otter-browser-review/)

### 下载管理器

![下载管理器](/data/attachment/album/201810/28/190103k822261und322v23.jpg)

*下载管理器*

#### uGet

[uGet](http://ugetdm.com/) 是我遇到过最棒的下载管理器，它是开源的并且能满足你对于一款下载管理器的一切期许。uGet 提供一系列便于管理下载的高级设置。你能够管理下载队列并且断点续传，针对大文件使用多连接下载，根据不同列表将文件下载至不同路径，等等。

#### XDM

Xtreme 下载管理器（[XDM](http://xdman.sourceforge.net/)）是一个 Java 开发的强大并且开源的下载工具。它拥有下载管理器的所有基本特性，包括视频抓取、智能计划任务以及浏览器集成。

* [推荐阅读：Linux 下最好的 4 个下载管理器](https://itsfoss.com/4-best-download-managers-for-linux/)

### BitTorrent 客户端

![BitTorrent 客户端](/data/attachment/album/201810/28/190105c2272y2vy11ae2eu.jpg)

*BitTorrent 客户端*

#### Deluge

[Deluge](http://deluge-torrent.org/) 是一个拥有漂亮用户界面的开源 BitTorrent 客户端。如果你习惯在 Windows 上使用 uTorrent，那么 Deluge 的界面会让你倍感亲切。它拥有丰富的设置项和针对不同任务的插件支持。

#### Transmission

[Transmission](https://transmissionbt.com/) 力求精简，它是用户界面最精简的 BitTorrent 客户端之一。Transmission 是许多 Linux 发行版的预装软件。

* [推荐阅读：Ubuntu Linux 上前 5 名的 Torrent 客户端](https://itsfoss.com/best-torrent-ubuntu/)

### 云存储

![云存储](/data/attachment/album/201810/28/190106a8x83xl0vqc5r5w3.jpg)

*云存储*

#### Dropbox

[Dropbox](https://www.dropbox.com) 是目前最流行的云存储服务之一，它为新用户提供了 2GB 的免费存储空间，以及一个健壮并且易于使用的 Linux 客户端。

#### MEGA

[MEGA](https://mega.nz/) 提供了 50GB 的免费存储，但这还并不是它最大的优点，MEGA 还为你的文件提供了端到端的加密支持。MEGA 提供一个名为 MEGAsync 的可靠的 Linux 客户端。

* [推荐阅读：2017 年 Linux 上最优秀的免费云服务](https://itsfoss.com/cloud-services-linux/)

### 通讯工具

![通讯工具](/data/attachment/album/201810/28/190107h50ygkcn58dc8cnc.jpg)

*通讯工具*

#### Pidgin

[Pidgin](https://www.pidgin.im/) 是一款开源的即时通讯工具，它支持许多聊天平台，包括 Google Talk、Yahoo 甚至 IRC。Pidgin 可通过第三方插件进行扩展，能提供许多附加功能。

你也可以使用 [Franz](https://itsfoss.com/franz-messaging-app/) 或 [Rambox](http://rambox.pro/) 来在一个应用中使用多个通讯服务。

#### Skype

我们都知道 [Skype](https://www.skype.com) 是最流行的视频聊天平台之一，它[发布了全新的 Linux 桌面客户端](https://itsfoss.com/skpe-alpha-linux/)。

* [推荐阅读：2017 年 Linux 平台上最优秀的 6 款消息应用](https://itsfoss.com/best-messaging-apps-linux/)

### 办公套件

![办公套件](/data/attachment/album/201810/28/190110ls9xmxaxpdi33zko.jpg)

*办公套件*

#### LibreOffice

[LibreOffice](https://www.libreoffice.org) 是 Linux 平台上开发最为活跃的开源办公套件，主要包括 Writer、Calc、Impress、Draw、Math、Base 六个主要模块，并且每个模块都提供广泛的文件格式支持。同时 LibreOffice 也支持第三方的扩展，以上优势使它成为许多 Linux 发行版的默认办公套件。

#### WPS Office

如果你想要尝试除 LibreOffice 以外的办公套件，[WPS Office](https://www.wps.com) 值得一试。WPS Office 套件包括了写作、演示和数据表格支持。

* [推荐阅读：Linux 平台 6 款最优秀的 Microsoft Office 替代品](https://itsfoss.com/best-free-open-source-alternatives-microsoft-office/)

### 音乐播放器

![音乐播放器](/data/attachment/album/201810/28/190111eborr7otfarizb13.jpg)

*音乐播放器*

#### Lollypop

[Lollypop](http://gnumdk.github.io/lollypop-web/) 是一款相对较新的开源音乐播放器，拥有漂亮又不失简洁的用户界面。它提供优秀的音乐管理、歌曲推荐、在线广播和派对模式支持。虽然它是一款不具有太多特性的简洁音乐播放器，但仍值得我们去尝试。

#### Rhythmbox

[Rhythmbox](https://wiki.gnome.org/Apps/Rhythmbox) 是一款主要为 GNOME 桌面环境开发的音乐播放器，当然它也可以在其他桌面环境运行。它能完成所有作为一款音乐播放器的基础功能，包括 CD 抓取和烧制、乱序播放，等等。它也提供了 iPod 支持。

#### cmus

如果你想要最轻量，并且喜欢命令行的话，[cmus](https://cmus.github.io/) 适合你。个人来讲，我是它的粉丝用户。cmus 是一款面向类 Unix 平台的小巧、快速并且强大的命令音乐播放器。它包含所有基础的音乐播放器特性，并且你能够通过扩展和脚本来增强它的功能。

* [推荐阅读：如何在 Ubuntu 14.04 和 Linux Mint 17 上安装 Tomahawk 播放器](https://itsfoss.com/install-tomahawk-ubuntu-1404-linux-mint-17/)

（LCTT 译注：好了好了，大家不要提醒我了，我这次补充上深受国内 Linux 和开源爱好者喜爱的[网易云音乐](https://music.163.com/#/download)。:D ）

### 视频播放器

![视频播放器](/data/attachment/album/201810/28/190113z38u0zusr7x7vhgw.jpg)

*视频播放器*

#### VLC

[VLC](http://www.videolan.org) 是一款简洁、快速、轻量并且非常强大的开源媒体播放器，它能够直接播放几乎所有格式的媒体文件，同时也能够播放在线的流媒体。它也能够安装一些时髦的扩展来完成不同的任务，比如直接在播放器内下载字幕。

#### Kodi

[Kodi](https://kodi.tv) 是一款成熟并且开源的媒体中心，在它的用户群中非常受欢迎。它能够处理来自本地或者网络媒体存储的视频、音乐、图片、播客甚至游戏，更强大的是你还能用它来录制电视节目。Kodi 可由附加组件和皮肤进行定制。

* [推荐阅读:Linux 平台上的 4 款格式工厂替代品](https://itsfoss.com/format-factory-alternative-linux/)

### 照片编辑器

![照片编辑器](/data/attachment/album/201810/28/190114de0e7cw6pn1t3tzp.jpg)

*照片编辑器*

#### GIMP

[GIMP](https://www.gimp.org/) 是 Linux 平台上 Photoshop 的替代品，它是一款开源、全功能并且专业的照片编辑软件。它打包了各式各样的工具用来编辑图片，更强大的是，它包含丰富的自定义设置以及第三方插件来增强体验。

#### Krita

[Krita](https://krita.org/en/) 主要是作为一款绘图工具，但也可以作为照片编辑软件。它是开源的并且打包了非常多复杂的高级工具。

* [推荐阅读:Linux 平台最好的照片应用](https://itsfoss.com/image-applications-ubuntu-linux/)

### 文字编辑器

每个 Linux 发行版都拥有自己的文字编缉器解决方案，当然大体上它们都非常简洁并且没有太多功能。但是也有一些文字编辑器具有更强大的功能。

![文字编辑器](/data/attachment/album/201810/28/190115lao29x657m625bm5.jpg)

*文字编辑器*

#### Atom

[Atom](https://atom.io/) 是由 GitHub 开发的一款现代高度可配置的文字编辑器，它是完全开源的并且能够提供所有你能想到的文字编辑器功能。你可以开箱即用，也可以将其配置成你想要的样子。并且你可以从它的社区安装大量的扩展和主题。

#### Sublime Text

[Sublime Text](http://www.sublimetext.com/) 是最受欢迎的文字编辑器之一，虽然它并不是免费的，但你可以无限地试用该款软件。Sublime Text 是一款特性丰富并且高度模块化的软件，当然它也提供插件和主题支持。

* [推荐阅读：Linux 平台最优秀的 4 款现代开源代码编辑器](https://itsfoss.com/best-modern-open-source-code-editors-for-linux/)

（LCTT 译注：当然，我知道你们也忘记不了 [VSCode](https://code.visualstudio.com/download)。）

### 启动器

![启动器](/data/attachment/album/201810/28/190116r08gt3usjgwgxyj4.jpg)

*启动器*

#### Albert

[Albert](https://github.com/ManuelSchneid3r/albert) 是一款快速、可扩展、可定制的生产力工具，受 Alfred（Mac 平台上一个非常好的生产力工具）启发并且仍处于开发阶段，它的目标是“使所有触手可及”。它能够与你的 Linux 发行版非常好的集成，帮助你提高生产力。

#### Synapse

[Synapse](https://launchpad.net/synapse-project) 已经有些年头了，它是一个能够搜索和运行程序的简单启动器。它也同时能够加速一些工作流，譬如音乐控制、文件搜索、路径切换、书签、运行命令，等等。

正如 Abhishek 所考虑的，我们将根据读者的（也就是你的）反馈更新最佳 Linux 应用程序清单。那么，你最爱的 Linux 应用程序是什么呢？分享给我们或者为这个清单增加新的软件分类吧。

---

via: <https://itsfoss.com/essential-linux-applications/>

作者：[Munif Tanjim](https://itsfoss.com/author/munif/) 译者：[cycoe](https://github.com/cycoe) 校对：[wxy](https://github.com/wxy)

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


设计更快的网页（一）：图片压缩

Summary: 这个系列的文章介绍了如何使用 Fedora 提供的工具来给网页“瘦身”。

这个系列的文章介绍了如何使用 Fedora 提供的工具来给网页“瘦身”。

![](/data/attachment/album/201810/28/213800xzz7e7txh75t5hhl.jpg)

很多 Web 开发者都希望做出加载速度很快的网页。在移动设备浏览占比越来越大的背景下，使用响应式设计使得网站在小屏幕下看起来更漂亮只是其中一个方面。Browser Calories 可以展示网页的加载时间 —— 这不单单关系到用户，还会影响到通过加载速度来进行评级的搜索引擎。这个系列的文章介绍了如何使用 Fedora 提供的工具来给网页“瘦身”。

### 准备工作

在你开始缩减网页之前，你需要明确核心问题所在。为此，你可以使用 [Browserdiet](https://browserdiet.com/calories/). 这是一个浏览器插件，适用于 Firefox、Opera、 Chrome 和其它浏览器。它会对打开的网页进行性能分析，这样你就可以知道应该从哪里入手来缩减网页。

然后，你需要一些用来处理的页面。下面的例子是针对 [getferoda.org](http://getfedora.org) 的测试截图。一开始，它看起来非常简单，也符合响应式设计。

![Browser Diet - getfedora.org 的评分](/data/attachment/album/201810/28/213800fjped7j9c1p3ej15.jpg)

然而，BroserDiet 的网页分析表明，这个网页需要加载 1.8MB 的文件。所以，我们现在有活干了！

### Web 优化

网页中包含 281 KB 的 JavaScript 文件、203 KB 的 CSS 文件，还有 1.2 MB 的图片。我们先从最严重的问题 —— 图片开始入手。为了解决问题，你需要的工具集有 GIMP、ImageMagick 和 optipng. 你可以使用如下命令轻松安装它们：

```
sudo dnf install gimp imagemagick optipng
```

比如，我们先拿到这个 6.4 KB 的[文件](https://getfedora.org/static/images/cinnamon.png)：

![](/data/attachment/album/201810/28/213803dhjhjmcej0ccxcbc.png)

首先，使用 `file` 命令来获取这张图片的一些基本信息：

```
$ file cinnamon.png
cinnamon.png: PNG image data, 60 x 60, 8-bit/color RGBA, non-interlaced
```

这张只由白色和灰色构成的图片使用 8 位 / RGBA 模式来存储。这种方式并没有那么高效。

使用 GIMP，你可以为这张图片设置一个更合适的颜色模式。在 GIMP 中打开 `cinnamon.png`。然后，在“图片 > 模式”菜单中将其设置为“灰度模式”。将这张图片以 PNG 格式导出。导出时使用压缩因子 9，导出对话框中的其它配置均使用默认选项。

```
$ file cinnamon.png
cinnamon.png: PNG image data, 60 x 60, 8-bit gray+alpha, non-interlaced
```

输出显示，现在这个文件现在处于 8 位 / 灰阶 + aplha 模式。文件大小从 6.4 KB 缩小到了 2.8 KB. 这已经是原来大小的 43.75% 了。但是，我们能做的还有很多！

你可以使用 ImageMagick 工具来查看这张图片的更多信息。

```
$ identify cinnamon2.png
cinnamon.png PNG 60x60 60x60+0+0 8-bit Grayscale Gray 2831B 0.000u 0:00.000
```

它告诉你，这个文件的大小为 2831 字节。我们回到 GIMP，重新导出文件。在导出对话框中，取消存储时间戳和 alpha 通道色值，来让文件更小一点。现在文件输出显示：

```
$ identify cinnamon.png
cinnamon.png PNG 60x60 60x60+0+0 8-bit Grayscale Gray 2798B 0.000u 0:00.000
```

下面，用 `optipng` 来无损优化你的 PNG 图片。具有相似功能的工具有很多，包括 `advdef`（这是 advancecomp 的一部分），`pngquant` 和 `pngcrush`。

对你的文件运行 `optipng`。 注意，这个操作会覆盖你的原文件：

```
$ optipng -o7 cinnamon.png
** Processing: cinnamon.png
60x60 pixels, 2x8 bits/pixel, grayscale+alpha
Reducing image to 8 bits/pixel, grayscale
Input IDAT size = 2720 bytes
Input file size = 2812 bytes

Trying:
 zc = 9 zm = 8 zs = 0 f = 0 IDAT size = 1922
 zc = 9 zm = 8 zs = 1 f = 0 IDAT size = 1920

Selecting parameters:
 zc = 9 zm = 8 zs = 1 f = 0 IDAT size = 1920

Output IDAT size = 1920 bytes (800 bytes decrease)
Output file size = 2012 bytes (800 bytes = 28.45% decrease)
```

`-o7` 选项处理起来最慢，但最终效果最好。于是你又将文件缩小了 800 字节，现在它只有 2012 字节了。

要压缩文件夹下的所有 PNG，可以使用这个命令：

```
$ optipng -o7 -dir=<directory> *.png
```

`-dir` 选项用来指定输出文件夹。如果不加这个选项，`optipng` 会覆盖原文件。

### 选择正确的文件格式

当涉及到在互联网中使用的图片时，你可以选择：

* [JPG 或 JPEG](https://en.wikipedia.org/wiki/JPEG)
* [GIF](https://en.wikipedia.org/wiki/GIF)
* [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics)
* [aPNG](https://en.wikipedia.org/wiki/APNG)
* [JPG-LS](https://en.wikipedia.org/wiki/JPEG_2000)
* [JPG 2000 或 JP2](https://en.wikipedia.org/wiki/JPEG_2000)
* [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics)

JPG-LS 和 JPG 2000 没有得到广泛使用。只有一部分数码相机支持这些格式，所以我们可以忽略它们。aPNG 是动态的 PNG 格式，也没有广泛使用。

可以通过更改压缩率或者使用其它文件格式来节省下更多字节。我们无法在 GIMP 中应用第一种方法，因为现在的图片已经使用了最高的压缩率了。因为我们的图片中不再包含 [aplha 通道](https://www.webopedia.com/TERM/A/alpha_channel.html)，你可以使用 JPG 类型来替代 PNG。 现在，使用默认值：90% 质量 —— 你可以将它减小至 85%，但这样会导致可见的叠影。这样又省下一些字节：

```
$ identify cinnamon.jpg
cinnamon.jpg JPEG 60x60 60x60+0+0 8-bit sRGB 2676B 0.000u 0:00.000
```

只将这张图转成正确的色域，并使用 JPG 作为文件格式，就可以将它从 23 KB 缩小到 12.3 KB，减少了近 50%.

#### PNG vs JPG: 质量和压缩率

那么，剩下的文件我们要怎么办呢？除了 Fedora “风味”图标和四个特性图标之外，此方法适用于所有其他图片。我们能够处理的图片都有一个白色的背景。

PNG 和 JPG 的一个主要区别在于，JPG 没有 alpha 通道。所以，它没有透明度选项。如果你使用 JPG 并为它添加白色背景，你可以将文件从 40.7 KB 缩小至 28.3 KB.

现在又有了四个可以处理的图片：背景图。对于灰色背景，你可以再次使用灰阶模式。对更大的图片，我们就可以节省下更多的空间。它从 216.2 KB 缩小到了 51 KB —— 基本上只有原图的 25% 了。整体下来，你把这些图片从 481.1 KB 缩小到了 191.5 KB —— 只有一开始的 39.8%.

#### 质量 vs 大小

PNG 和 JPG 的另外一个区别在于质量。PNG 是一种无损压缩光栅图形格式。但是 JPG 虽然使用压缩来缩小体积，可是这会影响到质量。不过，这并不意味着你不应该使用 JPG，只是你需要在文件大小和质量中找到一个平衡。

### 成就

这就是第一部分的结尾了。在使用上述技术后，得到的结果如下：

![](/data/attachment/album/201810/28/213804glanjnppfhchy0at.jpg)

你将一开始 1.2 MB 的图片体积缩小到了 488.9 KB. 只需通过 `optipng` 进行优化，就可以达到之前体积的三分之一。这可能使得页面更快地加载。不过，要是使用蜗牛到超音速来对比，这个速度还没到达赛车的速度呢！

最后，你可以在 [Google Insights](https://developers.google.com/speed/pagespeed/insights/?url=getfedora.org&tab=mobile) 中查看结果，例如：

![](/data/attachment/album/201810/28/213804cd8asadmrzub1k2b.png)

在移动端部分，这个页面的得分提升了 10 分，但它依然处于“中等”水平。对于桌面端，结果看起来完全不同，从 62/100 分提升至了 91/100 分，等级也达到了“好”的水平。如我们之前所说的，这个测试并不意味着我们的工作就做完了。通过参考这些分数可以让你朝着正确的方向前进。请记住，你正在为用户体验来进行优化，而不是搜索引擎。

---

via: <https://fedoramagazine.org/design-faster-web-pages-part-1-image-compression/>

作者：[Sirko Kemter](https://fedoramagazine.org/author/gnokii/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[StdioA](https://github.com/StdioA) 校对：[wxy](https://github.com/wxy)

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