使用 Ansible 在树莓派上构建一个基于 Linux 的高性能计算系统

Summary: 使用低成本的硬件和开源软件设计一个高性能计算集群。

使用低成本的硬件和开源软件设计一个高性能计算集群。

# 使用 Ansible 在树莓派上构建一个基于 Linux 的高性能计算系统

>
> 使用低成本的硬件和开源软件设计一个高性能计算集群。
>
>
>

在我的 [之前发表在 Opensource.com 上的文章中](https://opensource.com/article/17/11/openhpc)，我介绍了 [OpenHPC](https://openhpc.community/) 项目，它的目标是致力于加速高性能计算（HPC）的创新。这篇文章将更深入来介绍使用 OpenHPC 的特性来构建一个小型的 HPC 系统。将它称为 *HPC 系统* 可能有点“扯虎皮拉大旗”的意思，因此，更确切的说法应该是，它是一个基于 OpenHPC 项目发布的 [集群构建方法](https://openhpc.community/downloads/) 的系统。

这个集群由两台树莓派 3 系统作为计算节点，以及一台虚拟机作为主节点，结构示意如下：

我的主节点运行的是 x86\_64 架构的 CentOS 操作系统，而计算节点运行了 aarch64 的轻度修改版的 CentOS 操作系统。

下图是真实的设备工作照：

要把我的系统配置成像上图这样的 HPC 系统，我是按照 OpenHPC 的集群构建方法的 [CentOS 7.4/aarch64 + Warewulf + Slurm 安装指南](https://github.com/openhpc/ohpc/releases/download/v1.3.3.GA/Install_guide-CentOS7-Warewulf-SLURM-1.3.3-aarch64.pdf) （PDF）的一些步骤来做的。这个方法包括了使用 [Warewulf](https://en.wikipedia.org/wiki/Warewulf) 的配置说明；因为我的那三个系统是手动安装的，我跳过了 Warewulf 部分以及创建 [Ansible 剧本](http://people.redhat.com/areber/openhpc/ansible/) 的一些步骤。

在 [Ansible](https://www.ansible.com/) 剧本中设置完成我的集群之后，我就可以向资源管理器提交作业了。在我的这个案例中， [Slurm](https://slurm.schedmd.com/) 充当了资源管理器，它是集群中的一个实例，由它来决定我的作业什么时候在哪里运行。在集群上启动一个简单的作业的方式之一：

```
[ohpc@centos01 ~]$ srun hostname
calvin

```

如果需要更多的资源，我可以去告诉 Slurm，我希望在 8 个 CPU 上去运行我的命令：

```
[ohpc@centos01 ~]$ srun -n 8 hostname
hobbes
hobbes
hobbes
hobbes
calvin
calvin
calvin
calvin

```

在第一个示例中，Slurm 在一个单个的 CPU 上运行了指定的命令（`hostname`），而在第二个示例中，Slurm 在 8 个 CPU 上运行了那个命令。我的计算节点一个命名为 `calvin`，而另一个命名为 `hobbes`；在上面的命令输出部分可以看到它们的名字。每个计算节点都是由 4 个 CPU 核心的树莓派 3 构成的。

在我的集群中提交作业的另一种方法是使用命令 `sbatch`，它可以用于运行脚本，将输出写入到一个文件，而不是我的终端上。

```
[ohpc@centos01 ~]$ cat script1.sh
#!/bin/sh
date
hostname
sleep 10
date
[ohpc@centos01 ~]$ sbatch script1.sh
Submitted batch job 101

```

它将创建一个名为 `slurm-101.out` 的输出文件，这个输出文件包含下列的内容：

```
Mon 11 Dec 16:42:31 UTC 2017
calvin
Mon 11 Dec 16:42:41 UTC 2017

```

为示范资源管理器的基本功能，简单的串行命令行工具就行，但是，做各种工作去配置一个类似 HPC 系统就有点无聊了。

一个更有趣的应用是在这个集群的所有可用 CPU 上运行一个 [Open MPI](https://www.open-mpi.org/) 的并行作业。我使用了一个基于 [康威生命游戏](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) 的应用，它被用于一个名为“使用 Red Hat 企业版 Linux 跨多种架构运行康威生命游戏”的 [视频](https://www.youtube.com/watch?v=n8DvxMcOMXk)。除了以前基于 MPI 的 `Game of Life` 版本之外，在我的集群中现在运行的这个版本对每个涉及的主机的单元格颜色都是不同的。下面的脚本以图形输出的方式来交互式启动应用：

```
$ cat life.mpi
#!/bin/bash

module load gnu6 openmpi3

if [[ "$SLURM_PROCID" != "0" ]]; then
    exit
fi

mpirun ./mpi_life -a -p -b

```

我使用下面的命令来启动作业，它告诉 Slurm，为这个作业分配 8 个 CPU：

```
$ srun -n 8 --x11 life.mpi

```

为了演示，这个作业有一个图形界面，它展示了当前计算的结果：

红色单元格是由其中一个计算节点来计算的，而绿色单元格是由另外一个计算节点来计算的。我也可以让康威生命游戏程序为使用的每个 CPU 核心（这里的每个计算节点有四个核心）去生成不同的颜色，这样它的输出如下：

感谢 OpenHPC 提供的软件包和安装方法，因为它们让我可以去配置一个由两个计算节点和一个主节点的 HPC 式的系统。我可以在资源管理器上提交作业，然后使用 OpenHPC 提供的软件在我的树莓派的 CPU 上去启动 MPI 应用程序。

---

*想学习更多的关于使用 OpenHPC 去构建树莓派集群，请参与 Adrian Reber 在 [DevConf.cz 2018](https://devconfcz2018.sched.com/event/DJYi/openhpc-introduction) 的讨论，它于 1月 26-28 日在 Brno，Czech Republic 举行，以及在 [CentOS Dojo 2018](https://wiki.centos.org/Events/Dojo/Brussels2018) ，它于 2 月 2 日在 Brussels 举行。*

### 关于作者

Adrian Reber —— Adrian 是 Red Hat 的高级软件工程师，他早在 2010 年就开始了迁移处理过程到高性能计算环境，从那个时候起迁移了许多的处理过程，并因此获得了博士学位，然后加入了 Red Hat 公司并开始去迁移到容器。偶尔他仍然去迁移单个处理过程，并且它至今仍然对高性能计算非常感兴趣。[关于我的更多信息点这里](https://opensource.com/users/adrianreber)

---

via: <https://opensource.com/article/18/1/how-build-hpc-system-raspberry-pi-and-openhpc>

作者：[Adrian Reber](https://opensource.com/users/adrianreber) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


如何搭建“我的世界”服务器

推荐 Vultr  你的良心不会痛吗

有什么更好的吗推荐一下

有什么更好的吗推荐一下

有什么更好的吗推荐一下

有什么更好的吗推荐一下

哈哈哈

哈哈哈

这个技术分享真的很详细，太感谢了

centos怎么弄

弄好了服务器地址不知道啊

来自广西南宁的 Chrome Mobile 74.0|Android 6.0 用户

现在vultr都被墙了....

现在vultr都被墙了....

服务器的控制台怎么退出

vultr不好吧

但是好像还是要收费qwq

很好的教程

想问一下，这个服务器是无法安装插件的官服吗？我找不到plugins文件夹

想问一下，这个服务器是无法安装插件的官服吗？我找不到plugins文件夹

本人使用的是阿里的服务器，centos实测可用

stop

三丰云啊

为什么连接不上来？

为什么连接不上来？

为什么连接不上来？

看起来很详细

# 如何搭建“我的世界”服务器

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

我们将通过一个一步步的、新手友好的教程来向你展示如何搭建一个“我的世界（Minecraft）”服务器。这将会是一个长期的多人游戏服务器，你可以与来自世界各地的朋友们一起玩，而不用在同一个局域网下。

### 如何搭建一个“我的世界”服务器 - 快速指南

在你开始行动之前，要先了解一些事情：

#### 为什么你**不**应该使用专门的“我的世界”服务器提供商

既然你正在阅读这篇文章，你肯定对搭建自己的“我的世界”服务器感兴趣。不应该使用专门的“我的世界”服务器提供商的原因有很多，以下是其中一些：

* 它们通常很慢。这是因为你是在和很多用户一起共享资源。这有的时候会超负荷，他们中很多都会超售。
* 你并不能完全控制“我的世界”服务端或真正的服务器。你没法按照你的意愿进行自定义。
* 你是受限制的。这种主机套餐或多或少都会有限制。

当然，使用现成的提供商也是有优点的。最好的就是你不用做下面这些操作。但是那还有什么意思呢？!

#### 为什么不应该用你的个人电脑作为“我的世界”服务器

我们注意到很多教程都展示的是如何在你自己的电脑上搭建服务器。这样做有一些弊端，比如：

* 你的家庭网络不够安全，无法抵挡 DDoS 攻击。游戏服务器通常容易被 DDoS 攻击，而你的家庭网络设置通常不够安全，来抵挡它们。很可能连小型攻击都无法阻挡。
* 你得处理端口转发。如果你试着在家庭网络中搭建“我的世界”服务器的话，你肯定会偶然发现端口转发的问题，并且处理时可能会有问题。
* 你得保持你的电脑一直开着。你的电费将会突破天际，并且你会增加不必要的硬件负载。大部分服务器硬件都是企业级的，提升了稳定性和持久性，专门设计用来处理负载。
* 你的家庭网络速度不够快。家庭网络并不是设计用来负载多人联机游戏的。即使你想搭建一个小型服务器，你也需要一个更好的网络套餐。幸运的是，数据中心有多个高速的、企业级的互联网连接，来保证他们达到（或尽量达到）100%在线。
* 你的硬件很可能不够好。再说一次，服务器使用的都是企业级硬件，最新最快的处理器、固态硬盘，等等。你的个人电脑很可能不是的。
* 你的个人电脑很可能是 Windows/MacOS。尽管这有所争议，但我们相信 Linux 更适合搭建游戏服务器。不用担心，搭建“我的世界”服务器不需要完全了解 Linux（尽管推荐这样）。我们会向你展示你需要了解的。

我们的建议是不要使用个人电脑，即使从技术角度来说你能做到。买一个云服务器并不是很贵。下面我们会向你展示如何在云服务器上搭建“我的世界”服务端。小心地遵守以下步骤，就很简单。

### 搭建一个“我的世界”服务器 - 需求

这是一些需求，你在教程开始之前需要拥有并了解它们：

* 你需要一个 [Linux 云服务器](https://thishosting.rocks/cheap-cloud-hosting-providers-comparison/)。我们推荐 [Vultr](https://thishosting.rocks/go/vultr/)。这家价格便宜，服务质量高，客户支持很好，并且所有的服务器硬件都很高端。检查[“我的世界”服务器需求](https://minecraft.gamepedia.com/Server/Requirements/Dedicated)来选择你需要哪种类型的服务器（像内存和硬盘之类的资源）。我们推荐每月 20 美元的套餐。他们也支持按小时收费，所以如果你只是临时需要服务器和朋友们联机的话，你的花费会更少。注册时选择 Ubuntu 16.04 发行版。在注册时选择离你的朋友们最近的地域。这样的话你就需要保护并管理服务器。如果你不想这样的话，你可以选择[托管的服务器](https://thishosting.rocks/best-cheap-managed-vps/)，这样的话服务器提供商可能会给你搭建好一个“我的世界”服务器。
* 你需要一个 SSH 客户端来连接到你的 Linux 云服务器。新手通常建议使用 [PuTTy](https://www.chiark.greenend.org.uk/%7Esgtatham/putty/)，但我们也推荐使用 [MobaXTerm](https://mobaxterm.mobatek.net/)。也有很多 SSH 客户端，所以挑一个你喜欢的吧。
* 你需要设置你的服务器（至少做好基本的安全设置）。谷歌一下你会发现很多教程。你也可以按照 [Linode 的 安全指南](https://www.linode.com/docs/security/securing-your-server/)，然后在你的 [Vultr](https://thishosting.rocks/go/vultr/) 服务器上一步步操作。
* 下面我们将会处理软件依赖，比如 Java。

终于，到我们真正的教程了：

### 如何在 Ubuntu（Linux）上搭建一个“我的世界”服务器

这篇教程是为 [Vultr](https://thishosting.rocks/go/vultr/) 上的 Ubuntu 16.04 撰写并测试可行的。但是这对 Ubuntu 14.04， [Ubuntu 18.04](https://thishosting.rocks/ubuntu-18-04-new-features-release-date/)，以及其他基于 Ubuntu 的发行版、其他服务器提供商也是可行的。

我们使用默认的 Vanilla 服务端。你也可以使用像 CraftBukkit 或 Spigot 这样的服务端，来支持更多的自定义和插件。虽然如果你使用过多插件的话会影响服务端。这各有优缺点。不管怎么说，下面的教程使用默认的 Vanilla 服务端，来使事情变得简单和更新手友好。如果有兴趣的话我们可能会发表一篇 CraftBukkit 的教程。

#### 1. 登录到你的服务器

我们将使用 root 账户。如果你使用受限的账户的话，大部分命令都需要 `sudo`。做你没有权限的事情时会出现警告。

你可以通过 SSH 客户端来登录你的服务器。使用你的 IP 和端口（大部分都是 22）。

在你登录之后，确保你的[服务器安全](https://www.linode.com/docs/security/securing-your-server/)。

#### 2. 更新 Ubuntu

在你做任何事之前都要先更新你的 Ubuntu。你可以通过以下命令更新：

```
apt-get update && apt-get upgrade

```

在提示时敲击“回车键” 和/或 `y`。

#### 3. 安装必要的工具

在这篇教程中你需要一些工具和软件来编辑文本、长久保持服务端运行等。使用下面的命令安装：

```
apt-get install nano wget screen bash default-jdk ufw

```

其中一些可能已经安装好了。

#### 4. 下载“我的世界”服务端

首先，创建一个目录来保存你的“我的世界”服务端和其他文件：

```
mkdir /opt/minecraft

```

然后进入新目录：

```
cd /opt/minecraft

```

现在你可以下载“我的世界“服务端文件了。去往[下载页面](https://minecraft.net/en-us/download/server)获取下载链接。使用 `wget` 下载文件：

```
wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.1.12.2.jar

```

#### 5. 安装“我的世界”服务端

下载好了服务端的 .jar 文件之后，你就需要先运行一下，它会生成一些文件，包括一个 `eula.txt` 许可文件。第一次运行的时候，它会返回一个错误并退出。这是正常的。使用下面的命令运行它：

```
java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui

```

`-Xms2048M` 是你的服务端能使用的最小的内存，`-Xmx3472M` 是最大的内存。[调整](https://minecraft.gamepedia.com/Commands)基于你服务器的硬件资源。如果你在 [Vultr](https://thishosting.rocks/go/vultr/) 服务器上有 4GB 内存，并且不用服务器来干其他事情的话可以就这样留着不动。

在这条命令结束并返回一个错误之后，将会生成一个新的 `eula.txt` 文件。你需要同意那个文件里的协议。你可以通过下面这条命令将 `eula=true` 添加到文件中：

```
sed -i.orig 's/eula=false/eula=true/g' eula.txt

```

你现在可以通过和上面一样的命令来开启服务端并进入“我的世界”服务端控制台了：

```
java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui

```

确保你在 `/opt/minecraft` 目录，或者其他你安装你的 MC 服务端的目录下。

如果你只是测试或暂时需要的话，到这里就可以停了。如果你在登录服务器时有问题的话，你就需要[配置你的防火墙](https://thishosting.rocks/how-to-make-a-minecraft-server/#configure-minecraft-server)。

第一次成功启动服务端时会花费一点时间来生成。

我们将向你展示如何创建一个脚本来启动。

#### 6. 使用脚本启动“我的世界”服务端，让服务端长期运行并在启动时开启

方便起见，我们将创建一个自动启动服务端的 bash 脚本。

首先，使用 nano 创建一个 bash 脚本：

```
nano /opt/minecraft/startminecraft.sh

```

这将会打开一个新的（空白）文件。粘贴以下内容：

```
#!/bin/bash
cd /opt/minecraft/ && java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui

```

如果你不熟悉 nano 的话 - 你可以使用 `CTRL + X`，再敲击 `Y`，然后回车。这个脚本将进入你先前创建的“我的世界”服务端并运行 Java 命令来开启服务端。你需要执行下面的命令来使脚本可执行：

```
chmod +x startminecraft.sh

```

然后，你就可以通过下面的命令随时运行服务端了：

```
/opt/minecraft/startminecraft.sh

```

但是，如果/当你登出 SSH 会话的话，服务端就会关闭。要想让服务端不登录也持续运行的话，你可以使用 `screen` 会话。`screen` 会话会一直运行，直到实际的服务器被关闭或重启。

使用下面的命令开启一个 screen 会话：

```
screen -S minecraft

```

一旦你进入了 `screen` 会话（看起来就像是你新建了一个 SSH 会话），你就可以使用先前创建的 bash 脚本来启动服务端：

```
/opt/minecraft/startminecraft.sh

```

要退出 `screen` 会话的话，你应该按 `CTRL+A-D`。即使你离开 `screen` 会话（断开的），服务端也会继续运行。你现在可以安全的登出 Ubuntu 服务器了，你创建的“我的世界”服务端将会继续运行。

但是，如果 Ubuntu 服务器重启或关闭了的话，`screen` 会话将不再起作用。所以**为了让我们之前做的这些在启动时自动运行**，做下面这些：

打开 `/etc/rc.local` 文件：

```
nano /etc/rc.local

```

在 `exit 0` 语句前添加如下内容：

```
screen -dm -S minecraft /opt/minecraft/startminecraft.sh
exit 0

```

保存并关闭文件。

要访问“我的世界”服务端控制台，只需运行下面的命令来重新连接 `screen` 会话：

```
screen -r minecraft

```

现在就是这样。祝贺你，玩的开心！你现在可以连接到你的“我的世界”服务端或配置/修改它了。

### 配置你的 Ubuntu 服务器

你首先肯定要设置并确保你的 Ubuntu 服务器安全，如果你还没有这么做的话。按照[我们之前提及的指南](https://www.linode.com/docs/security/securing-your-server/)并谷歌一下来获取更多信息。你需要在服务器上配置的有这些：

#### 开启并配置防火墙

首先，如果防火墙还没有开启的话，你应该先开启先前安装的 UFW：

```
ufw enable

```

你应该开放默认的“我的世界”服务端端口：

```
ufw allow 25565/tcp

```

你应该根据你的使用情况开放或拒绝其他规则。如果你不用服务器负载网站的话，就应该拒绝 80 和 443 端口。谷歌一下 Ubuntu 的 UFW/防火墙指南，你会得到建议的。设置防火墙的时候小心一些，如果你屏蔽了 SSH 端口的话你会把自己锁在服务器外面。

由于这是默认端口，这个端口经常被扫描以及攻击。你可以通过屏蔽白名单之外的访问权限来阻挡攻击。

首先，你需要在你的 [server.properties](https://minecraft.gamepedia.com/Server.properties) 文件中开启白名单模式。要开启的话，打开文件：

```
nano /opt/minecraft/server.properties

```

并将 `white-list` 行改为 `true`：

```
white-list=true

```

保存并关闭文件。

然后重启你的服务器（重启你的服务器或重新运行启动脚本）：

```
/opt/minecraft/startminecraft.sh

```

访问“我的世界”服务端控制台：

```
screen -r minecraft

```

如果你想要某人进入你的服务端，你需要通过以下命令把他们添加到白名单：

```
whitelist add PlayerUsername

```

运行以下命令来将他们移出白名单：

```
whitelist remove PlayerUsername

```

使用 `CTRL+A-D` 来退出 `screen`（服务器控制台）。值得注意的是，这会拒绝除白名单以外的所有人连接到服务端。

### 如何搭建“我的世界”服务器 - 常见问题

我们将解答一些有关“我的世界”服务器和我们的指南的常见问题。

#### 我该如何重启“我的世界”服务器？

如果你按照我们的教程来的话，包括开启了服务端随系统启动，你可以直接重启你的 Ubuntu 服务器。如果没有设置岁系统启动的话，你可以通过重新运行启动脚本来重启“我的世界”服务端：

```
/opt/minecraft/startminecraft.sh

```

#### 我该如何配置我的“我的世界”服务端？

你可以使用 [server.properties](https://minecraft.gamepedia.com/Server.properties) 文件来配置你的服务端。查看“我的世界”维基来获取更多信息，你也可以什么都不动，它会工作的很好。

如果你想改变游戏模式、难度等诸如此类的东西，你可以使用服务端控制台。通过下面的命令访问服务端控制台：

```
screen -r minecraft

```

并执行[命令](https://minecraft.gamepedia.com/Commands)。像下面这些命令：

```
difficulty hard

```

```
gamemode survival @a

```

你可能需要重新启动服务端，这取决于你使用了什么命令。你可以使用很多命令，查看[维基](https://minecraft.gamepedia.com/Commands)来获取更多。

#### 我该如何升级我的“我的世界”服务端？

如果有新版本发布的话，你需要这样做：

进入“我的世界”目录：

```
cd /opt/minecraft

```

下载最新的版本，比如使用 wget 下载 1.12.3 版本：

```
wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12.3/minecraft_server.1.12.3.jar

```

接下来，运行并构建新服务端：

```
java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.3.jar nogui

```

最后，更新你的启动脚本：

```
nano /opt/minecraft/startminecraft.sh

```

更新版本号数字：

```
#!/bin/bash
cd /opt/minecraft/ && java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.3.jar nogui

```

现在你可以重启服务端了，一切都应该没有问题。

#### 为什么你们的教程这么长，而其他的只有 2 行那么长？！

我们想让这个教程对新手来说更友好，并且尽可能详细。我们还向你展示了如何让服务端长期运行并跟随系统启动，我们向你展示了如何配置你的服务端以及所有的东西。我是说，你当然可以用几行来启动“我的世界”服务器，但那样的话绝对很烂，从不仅一方面说。

#### 我不知道 Linux 或者这里说的什么东西，我该如何搭建一个“我的世界”服务器呢？

只要通篇阅读我们的文章，复制粘贴几个命令就行了。如果你真的不知道该如何做的话，[我们可以帮你](https://thishosting.rocks/support/)，或者直接找一个[托管的](https://thishosting.rocks/best-cheap-managed-vps/)服务器[提供商](https://thishosting.rocks/best-cheap-managed-vps/)，让他们帮你做这些。

#### 我该如何在服务端上安装 mod 和插件？

我们的文章意图作一篇入门指南，你应该查看[“我的世界维基”](https://minecraft.gamepedia.com/Minecraft_Wiki)，或者谷歌一下来获取更多信息。网上有很多教程。

---

via: <https://thishosting.rocks/how-to-make-a-minecraft-server/>

作者：[ThisHosting.Rocks](https://thishosting.rocks) 译者：[heart4lor](https://github.com/heart4lor) 校对：[wxy](https://github.com/wxy)

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


在你的网络中使用树莓派和 Pi-hole 拦截广告

Summary: 痛恨上网时看到广告？学习这篇教程来设置 Pi-hole。

痛恨上网时看到广告？学习这篇教程来设置 Pi-hole。

# 在你的网络中使用树莓派和 Pi-hole 拦截广告

>
> 痛恨上网时看到广告？学习这篇教程来设置 Pi-hole。
>
>
>

有一个闲置的树莓派？在浏览网页时讨厌广告？[Pi-hole](https://pi-hole.net/) 是一个拦截广告的开源软件项目，它可以将你的家庭网络上的所有广告路由到一个不存在的地方，从而实现在你的设备上拦截广告的目的。这么好的方法只需要花几钟的时间来设置，你就可以使用它了。

Pi-hole 拦截了超过 100,000 个提供广告的域名，它可以拦截任何设备（包括移动设备、平板电脑、以及个人电脑）上的广告，并且它是完整的拦截了广告，而不是仅将它们隐藏起来，这样做可以提升总体的网络性能（因为广告不需要下载）。你可以在一个 web 界面上、或者也可以使用一个 API 来监视性能和统计数据。

### 你需要：

* 树莓派 + SD 卡
* USB 电源线
* 以太网线

你不需要使用一个最新型号的树莓派 — 一个老款足够完成这项工作，只要它的内存不小于 512MB 就可以 — 因此一个一代树莓派 Model B（rev 2）就足够，一个 Model B+、或者二代的或者三代的树莓派都可以。你可以使用 Pi Zero，但需要一个 USB micro 以太网适配器。你可以使用一个带 WiFi 的 Pi Zero W 而不是以太网。但是，作为你的网络基础设施的一部分，我建议你使用一个性能良好、稳定的有线连接来代替 WiFi 连接。

### 准备 SD 卡

开始的第一步，你可能需要将 Raspbian Stretch Lite 安装到一个 SD 卡上。SD 卡至少需要 4GB 大小（完整的桌面版 Raspbian 镜像至少要 8GB，但是 Lite 版镜像更小更轻量化，足够完成这项工作）。如果你喜欢，也可以使用完整的 Raspbian 桌面版镜像，但是作为一个去运行简单应用程序的树莓派，你没必要做更多的事情。

使用你的个人电脑，从树莓派的网站上下载 Raspbian Stretch Lite 镜像。解压它并提取出里面的 `.img` 文件，然后将这个 `.img` 文件写入到你的 SD 卡。不论你的 SD 卡是否是空白的，这一步都不会有什么麻烦，因为在写入前它会清空上面的数据。

如果你使用的是 Linux，写入镜像文件更简单的办法是使用命令行工具 `dd`。或者，你也可以使用跨平台的软件 [Etcher](https://etcher.io/) （可以去参考 Les Pounder 写的指南 “[如何为树莓派准备 SD 卡](https://opensource.com/article/17/3/how-write-sd-cards-raspberry-pi)“）。

SD 卡准备完成之后，你可以将它插入到你的树莓派，连接上键盘、显示器和以太网，然后为树莓派接上电源。在初始化设置之后，这个树莓派就不需要键盘或显示器了。如果你有使用“<ruby> 无末端 <rt>  headless </rt></ruby>”树莓派工作的经验，你可以 [启用 SSH](https://www.raspberrypi.org/blog/a-security-update-for-raspbian-pixel/) 然后去设置它 [启用远程连接](https://www.raspberrypi.org/documentation/remote-access/ssh/README.md)。

### 安装 Pi-hole

在你的树莓派引导完成之后，用缺省用户名（`pi`）和密码（`raspberry`）登入。现在你就可以运行命令行了，可以去安装 Pi-hole 了。简单地输入下列命令并回车：

```
curl -sSL https://install.pi-hole.net | bash

```

这个命令下载了 Pi-hole 安装脚本然后去运行它。你可以在你的电脑浏览器中输入 `https://install.pi-hole.net` 来查看它的内容，你将会看到这个脚本做了些什么。它为你生成了一个**管理员密码**，并和其它安装信息一起显示在你的屏幕上。

就是这么简单，几分钟之后，你的树莓派将准备好为你拦截广告。

在你断开树莓派连接之前，你需要知道它的 IP 地址和你的路由器的 IP 地址。（如果你不知道），在你的终端中输入 `hostname -I` 来查看你的树莓派的 IP 地址，输入 `ip route | grep default` 来找到你的路由器的 IP 地址。你看到的将是像 `192.168.1.1` 这样的地址。

### 配置你的路由器

你的树莓派现在运行着一个 DNS 服务器，接下来你需要告诉你的路由器去使用 Pi-hole 作为它的 DNS 服务器而不是你的 ISP 提供给你的缺省 DNS。进入路由器的管理控制台 web 界面。这个界面一般是输入你的路由器的 IP 地址来进入的。

找到 LAN 设置下面的 DHCP/DNS 设置，然后将你的主 DNS 服务器的 IP 地址设置为你的 Pi-hole 的 IP 地址。设置完成之后，它应该你下图的样子：

关于这一步的更多信息，可以查看 [Pi-hole discourse](https://discourse.pi-hole.net/t/how-do-i-configure-my-devices-to-use-pi-hole-as-their-dns-server/245)。

你还需要确保你的 Pi-hole 始终保持相同的 IP 地址，因此，你需要去查看 DHCP 设置，将你的树莓派的 IP 地址条目添加到保留地址中。

### 外部测试

现在，在命令行下输入 `sudo halt` 关闭运行的树莓派，并断开它的电源。你可以拔掉显示器连接线和键盘，然后将你的树莓派放置到一个合适的固定的地方 — 或许应该将它放在你的路由器附近。确保连接着以太网线，然后重新连接电源以启动它。

在你的个人电脑上导航到一个网站（强烈建议访问 [Opensource.com](https://opensource.com/) 网站），或者用你的 WiFi 中的一个设备去检查你的因特网访问是否正常（如果不能正常访问，可能是你的 DNS 配置错误）。如果在浏览器中看到了预期的结果，说明它的工作正常。现在，你浏览网站时，应该再也看不到广告了！甚至在你的 app 中提供的广告也无法出现在你的移动设备中！祝你“冲浪”愉快！

如果你想去测试一下你的广告拦截的新功能，你可以去这个 [测试页面](https://pi-hole.net/pages-to-test-ad-blocking-performance/) 尝试浏览一些内置广告的网站。

现在你可以在你的电脑浏览器上输入 Pi-hole 的 IP 地址来访问它的 web 界面（比如，`http://192.168.1.4/admin` 或者 `http://pi.hole/admin` 也可能会工作）。你将看到 Pi-hole 管理面板和一些统计数据（在这时可能数字比较小）。在你输入（在安装时显示在屏幕上的）密码后，你将看到更漂亮的图形界面：

你也可以微调你的 Pi-hole 的设置，像域名的白名单和黑名单、永久和临时禁止、访问拦截统计信息等等。

个别情况下，你可能需要去升级你的 Pi-hole 安装。当软件需要更新时，这个 web 界面会出现一个更新提示。如果你启用了 SSH，你可以远程登入，否则，那你只能再次连接键盘和显示器。远程登入之后，输入 `pihole -up`命令来更新它。

如果你使用过 Pi-hole 或者其它的开源广告拦截器，请在下面的评论区把你的经验共享出来。

---

via: <https://opensource.com/article/18/2/block-ads-raspberry-pi>

作者：[Ben Nuttall](https://opensource.com/users/bennuttall) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


如何在 Web 服务器文档根目录上设置只读文件权限

Summary: 如何对我存放在 /var/www/html/ 目录中的所有文件设置只读权限？

如何对我存放在 /var/www/html/ 目录中的所有文件设置只读权限？

# 如何在 Web 服务器文档根目录上设置只读文件权限

**Q：如何对我存放在 `/var/www/html/` 目录中的所有文件设置只读权限？**

你可以使用 `chmod` 命令对 Linux/Unix/macOS/OS X/\*BSD 操作系统上的所有文件来设置只读权限。这篇文章介绍如何在 Linux/Unix 的 web 服务器（如 Nginx、 Lighttpd、 Apache 等）上来设置只读文件权限。

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

### 如何设置文件为只读模式

语法为:

```
### 仅针对文件 ###
chmod 0444 /var/www/html/*
chmod 0444 /var/www/html/*.php

```

### 如何设置目录为只读模式

语法为：

```
### 仅针对目录 ###
chmod 0444 /var/www/html/
chmod 0444 /path/to/your/dir/
# ***************************************************************************
# 假如 web 服务器的用户/用户组是 www-data，文件拥有者是 ftp-data 用户/用户组
# ***************************************************************************
# 设置目录所有文件为只读
chmod -R 0444 /var/www/html/
# 设置文件/目录拥有者为 ftp-data
chown -R ftp-data:ftp-data /var/www/html/
# 所有目录和子目录的权限为 0445 （这样 web 服务器的用户或用户组就可以读取我们的文件）
find /var/www/html/ -type d -print0 | xargs -0 -I {} chmod 0445 "{}"

```

找到所有 `/var/www/html` 下的所有文件（包括子目录），键入：

```
### 仅对文件有效 ###
find /var/www/html -type f -iname "*" -print0 | xargs -I {} -0 chmod 0444 {}

```

然而，你需要在 `/var/www/html` 目录及其子目录上设置只读和执行权限，如此才能让 web 服务器能够访问根目录，键入：

```
### 仅对目录有效 ###
find /var/www/html -type d -iname "*" -print0 | xargs -I {} -0 chmod 0544 {}

```

### 警惕写权限

请注意在 `/var/www/html/` 目录上的写权限会允许任何人删除文件或添加新文件。也就是说，你可能需要设置一个只读权限给 `/var/www/html/` 目录本身。

```
### web根目录只读 ###
chmod 0555 /var/www/html

```

在某些情况下，根据你的设置要求，你可以改变文件的属主和属组来设置严格的权限。

```
### 如果 /var/www/html 目录的拥有人是普通用户，你可以设置拥有人为：root:root 或 httpd:httpd (推荐) ###
chown -R root:root /var/www/html/

### 确保 apache 拥有 /var/www/html/ ###
chown -R apache:apache /var/www/html/

```

### 关于 NFS 导出目录

你可以在 `/etc/exports` 文件中指定哪个目录应该拥有[只读或者读写权限](https://www.cyberciti.biz//www.cyberciti.biz/faq/centos-fedora-rhel-nfs-v4-configuration/) 。这个文件定义各种各样的共享在 NFS 服务器和他们的权限。如：

```
# 对任何人只读权限
/var/www/html *(ro,sync)

# 对192.168.1.10(upload.example.com)客户端读写权限访问
/var/www/html 192.168.1.10(rw,sync)

```

### 关于用于 MS-Windows客户端的 Samba（CIFS）只读共享

要以只读共享 `sales`，更新 `smb.conf`，如下：

```
[sales]
comment = Sales Data
path = /export/cifs/sales
read only = Yes
guest ok = Yes

```

### 关于文件系统表（fstab）

你可以在 Unix/Linux 上的 `/etc/fstab` 文件中配置挂载某些文件为只读模式。

你需要有专用分区，不要设置其他系统分区为只读模式。

如下在 `/etc/fstab` 文件中设置 `/srv/html` 为只读模式。

```
/dev/sda6 /srv/html ext4 ro 1 1

```

你可以使用 `mount` 命令[重新挂载分区为只读模式](https://www.cyberciti.biz/faq/howto-freebsd-remount-partition/)（使用 root 用户）

```
# mount -o remount,ro /dev/sda6 /srv/html

```

或者

```
# mount -o remount,ro /srv/html

```

上面的命令会尝试重新挂载已挂载的文件系统到 `/srv/html`上。这是改变文件系统挂载标志的常用方法，特别是让只读文件改为可写的。这种方式不会改变设备或者挂载点。让文件变得再次可写,键入：

```
# mount -o remount,rw /dev/sda6 /srv/html

```

或

```
# mount -o remount,rw /srv/html

```

### Linux：chattr 命令

你可以在 Linux 文件系统上使用 `chattr` 命令[改变文件属性为只读](https://www.cyberciti.biz/tips/linux-password-trick.html)，如：

```
chattr +i /path/to/file.php
chattr +i /var/www/html/

# 查找任何在/var/www/html下的文件并设置为只读#
find /var/www/html -iname "*" -print0 | xargs -I {} -0 chattr +i {}

```

通过提供 `-i` 选项可删除只读属性：

```
chattr -i /path/to/file.php

```

FreeBSD、Mac OS X 和其他 BSD Unix 用户可使用[`chflags`命令](https://www.cyberciti.biz/tips/howto-write-protect-file-with-immutable-bit.html)：

```
### 设置只读 ##
chflags schg /path/to/file.php

### 删除只读 ##
chflags noschg /path/to/file.php

```

---

via: <https://www.cyberciti.biz/faq/howto-set-readonly-file-permission-in-linux-unix/>

作者：[Vivek Gite](https://www.cyberciti.biz) 译者：[yizhuoyan](https://github.com/yizhuoyan) 校对：[wxy](https://github.com/wxy)

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


可以运行在 Windows 10 中的最实用的 Linux 命令

# 可以运行在 Windows 10 中的最实用的 Linux 命令

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

在本系列早先的文章中，我们讨论了关于如何在 [Windows 10 上开启 WSL 之旅](https://www.linux.com/blog/learn/2018/2/how-get-started-using-wsl-windows-10) 的内容。作为本系列的最后一篇文章，我们准备探讨一些能在 Windows 10 上广泛使用的 Linux 命令。

话题深入之前，请先让我们明确本教程所适用的人群。本文适用于使用 Windows 10 系统，但是又想在 Azure、AWS 或是私有云平台上学习 Linux 的初级开发者。换句话说，就是为了帮助初次接触 Linux 系统的 Windows 10 用户。

您的工作任务决定了您所需要的命令，而我的需求可能和您的不一样。本文旨在帮助您在 Windwos 10 上舒服的使用 Linux。不过请牢记，WSL 并不提供硬件访问的功能，比如声卡、GPU，至少官方是这么描述的。但是这可能并不能阻止 Linux 用户的折腾精神。很多用户不仅完成了硬件访问，甚至已经在 Windows 10 上安装上了 Linux 桌面程序。但是本文并不会涉及这些内容，我们可能会讨论这些，但不是现在。

下面是我们需要着手的任务。

### 如何让您的 Linux 系统保持到最新的版本

因为 Linux 运行在了 Windows 系统中，所以您将被剥夺 Linux 系统所提供的所有安全特性。另外，如果不及时给 Linux 系统打补丁，你的 Windows 设备将被迫暴露在外界威胁中，所以还请保持您的 Linux 为最新版本。

WSL 官方支持 openSUSE/SUSE Linux Enterprise 和 Ubuntu。您也可以安装其他发行版，但是我只需要它们当中的二者之一就可以完成我的所有工作，毕竟，我只需要访问一些 Linux 基础程序。

**更新 openSUSE Leap：**

```
sudo zypper up

```

如果您想升级系统，您可以运行下面的命令：

```
sudo zypper dup

```

**更新 Ubuntu：**

```
sudo apt-get update
sudo apt-get dist-upgrade

```

这样你就安全了，由于 Linux 系统的更新是渐进式的，所以更新系统成为了我的日常。不像 Windows 10 的更新通常需要重启系统，而 Linux 不同，一般只有 KB 或是 MB 级的更新，无需重启。

### 管理文件目录

系统更新之后，我们来看看一些或普通或不太普通的任务。

系统更新之外的第二重要的任务是使用 Linux 管理本地和远程文件。我承认我更青睐图形界面程序，但是终端能提供更可靠、更有价值的服务。要不你使用资源管理器移动 1 TB 的文件试试？我通常使用 `rsync` 命令来移动大量文件。如果中断任务，`rsync` 可以在上次停止的位置继续工作。

虽然您可能更习惯使用 `cp` 或是 `mv` 命令复制、移动文件，但是我还是喜欢灵活的 `rsync` 命令，了解 `rsync` 对远程文件传输也有帮助。使用 `rsync` 大半为了完成下面三个任务：

**使用 rsync 复制整个目录：**

```
rsync -avzP /source-directory /destination directory

```

**使用 rsync 移动文件：**

```
rsync --remove-source-files -avzP /source-directory /destination-directory

```

在成功复制目标目录之后，此命令将删除源文件。

**使用 rsync 同步文件：**

我的文件可能在多处存储。但是，我只会在主要位置中增加或是删除。如果不使用专业的软件，同步文件可能会给用户带来挑战，而 `rsync` 刚好可以简化这个过程。这个命令可以让两个目录文件内容同步。不过要注意，这是一个单向同步，即从源位置同步到目标位置。

```
rsync --delete -avzP /source-directory /destination-directory

```

如果源目录中没有找到文件，上述命令将删除目标目录中的文件。换言之，它创建了源目录的一个镜像。

### 文件自动备份

保持文件备份是一项乏味的工作。为了保持我的设备的完全同步，我运行了一个 cron 作业在夜间保持我的所有目录同步。不过我会留一个外部驱动器，基本上每周我都会手动同步一次。由于可能删掉我不想删除的文件，所以我并没有使用 `--delete` 选项。我会根据情况手动决定是否使用这个选项。

**创建 cron 作业，打开 crontab：**

```
crontab -e

```

移动大文件时，我会选择在系统空闲的深夜执行该命令。此命令将在每天早上 1 点运行，您大概可以这样修改它：

```
# 0 1 * * * rsync -avzP /source-directory /destination-directory

```

这是使用 crontab 的定时作业的命令结构：

```
# m h dom mon dow command

```

在此，`m` = 分钟，`h` = 小时，`dom` = 本月的某天，`mon` = 月，`dow` = 本周的某天。

我们将在每天早上 1 点运行这条命令。您可以选择 `dow` 或是 `dom`（比如，每月 5 号）等。您可以在 [这里](http://www.adminschoice.com/crontab-quick-reference) 阅读更多相关内容。

### 管理远程服务器

在 Windows 系统上使用 WSL 的优势之一就是能方便管理云上的 Linux 服务器，WSL 能提供原生的 Linux 工具给您。首先，您需要使用 `ssh` 命令登录远程 Linux 服务器。

比如，我的服务器 ip 是 192.168.0.112；端口为 2018（不是默认的 22 端口）；Linux 用户名是 swapnil，密码是 “就不告诉你”。

```
ssh -p2018 swapnil@192.168.0.112

```

它会向您询问用户密码，然后您就可以登录到 Linux 服务器了。现在您可以在 Linux 服务器上执行任意您想执行的所有操作了。不需使用 PuTTY 程序了。

使用 `rsync` ，您可以很轻易的在本地机器和远程机器之间传输文件。源目录还是目标目录取决于您是上传文件到服务器，还是下载文件到本地目录，您可以使用 `username@IP-address-of-server:/path-of-directory` 来指定目录。

如果我想复制一些文本内容到服务器的 home 目录，命令如下：

```
rsync -avzP /source-directory-on-local-machine ‘ssh -p2018’ swapnil@192.168.0.112:/home/swapnil/Documents/

```

这将会复制这些文件到远程服务器中 `Documents` 目录。

### 总结

本教程主要是为了证明您可以在 Windows 10 系统上通过 WSL 完成 Linux 方面的很大一部分的任务。通常来说，它提高了生产效率。现在，Linux 的世界已经向 Windwos 10 系统张开怀抱了，尽情探索吧。如果您有任何疑问，或是想了解 WSL 涉及到的其他层面，欢迎在下方的评论区分享您的想法。

在 [Administering Linux on Azure (LFS205)](https://training.linuxfoundation.org/linux-courses/system-administration-training/administering-linux-on-azure) 课程中了解更多，可以在 [这里](http://bit.ly/2FpFtPg) 注册。

---

via: <https://www.linux.com/blog/learn/2018/3/most-useful-linux-commands-you-can-run-windows-10>

作者：[SAPNIL BHARTIYA](https://www.linux.com/users/arnieswap) 译者：[CYLeft](https://github.com/CYLeft) 校对：[wxy](https://github.com/wxy)

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


3 种扩展 Kubernetes 能力的方式

Summary: 你需要扩展 Kubernetes。有三种方法可以做到这一点，从最灵活（但也更困难）到最简单的依次是：使用 Kube 聚合器、使用 API 服务器构建器或创建自定义资源定义（CRD）。

# 3 种扩展 Kubernetes 能力的方式

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

Google 的工程总监 Chen Goldberg 在最近的奥斯汀 [KubeCon 和 CloudNativeCon](http://events17.linuxfoundation.org/events/kubecon-and-cloudnativecon-north-america)上说，Kubernetes 的扩展能力是它的秘密武器。

在建立帮助工程师提高工作效率的工具的竞赛中，Goldberg 谈到他曾经领导过一个开发这样一个平台的团队。尽管平台最初有用，但它无法扩展，并且修改也很困难。

幸运的是，Goldberg 说，Kubernetes 没有这些问题。首先，Kubernetes 是一个自我修复系统，因为它使用的控制器实现了“<ruby> 协调环 <rt>  Reconciliation Loop </rt></ruby>”。在协调环中，控制器观察系统的当前状态并将其与所需状态进行比较。一旦它确定了这两个状态之间的差异，它就会努力实现所需的状态。这使得 Kubernetes 非常适合动态环境。

### 3 种扩展 Kubernetes 的方式

Goldberg 然后解释说，要建立控制器，你需要资源，也就是说，你需要扩展 Kubernetes。有三种方法可以做到这一点，从最灵活（但也更困难）到最简单的依次是：使用 Kube 聚合器、使用 API 服务器构建器或创建<ruby> 自定义资源定义 <rt>  Custom Resource Definition </rt></ruby>（CRD）。

后者甚至可以使用极少的代码来扩展 Kubernetes 的功能。为了演示它是如何完成的，Goggle 软件工程师 Anthony Yeh 上台展示了为 Kubernetes 添加一个状态集。 （状态集对象用于管理有状态应用，即需要存储应用状态的程序，跟踪例如用户身份及其个人设置。）使用 *catset*，在一个 100 行 JavaScript 的文件中实现的 CRD，Yeh 展示了如何将状态集添加到 Kubernetes 部署中。之前的扩展不是 CRD，需要 24 个文件和 3000 多行代码。

为解决 CRD 可靠性问题，Goldberg 表示，Kubernetes 已经启动了一项认证计划，允许公司在 Kubernetes 社区注册和认证其扩展。在一个月内，已有 30 多家公司报名参加该计划。

Goldberg 继续解释 Kubernetes 的可扩展性如何成为今年 KubeCon 的热门话题，以及 Google 和 IBM 如何构建一个使用 CRD 管理和保护微服务的平台。或者一些开发人员如何将机器学习带入 Kubernetes，另外展示开放服务代理以及在混合设置上的服务消费。

Goldberg 总结说，可扩展性是种增能。而且，Kubernetes 的可扩展性使其成为开发者的通用平台，并且易于使用，这使得他们可以运行任何应用程序。

你可以在下面观看整个视频：

---

via: <https://www.linux.com/blog/event/kubecon/2018/2/3-ways-extend-power-kubernetes>

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

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


如何用 Python 解析 HTML

# 如何用 Python 解析 HTML

>
> 用一些简单的脚本，可以很容易地清理文档和其它大量的 HTML 文件。但是首先你需要解析它们。
>
>
>

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

作为 Scribus 文档团队的长期成员，我要随时了解最新的源代码更新，以便对文档进行更新和补充。 我最近在刚升级到 Fedora 27 系统的计算机上使用 Subversion 进行检出操作时，对于下载该文档所需要的时间我感到很惊讶，文档由 HTML 页面和相关图像组成。 我恐怕该项目的文档看起来比项目本身大得多，并且怀疑其中的一些内容是“僵尸”文档——不再使用的 HTML 文件以及 HTML 中无法访问到的图像。

我决定为自己创建一个项目来解决这个问题。 一种方法是搜索未使用的现有图像文件。 如果我可以扫描所有 HTML 文件中的图像引用，然后将该列表与实际图像文件进行比较，那么我可能会看到不匹配的文件。

这是一个典型的图像标签：

```
<img src="images/edit_shapes.png" ALT="Edit examples" ALIGN=left>

```

我对 `src=` 之后的第一组引号之间的部分很感兴趣。 在寻找了一些解决方案后，我找到一个名为 [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/) 的 Python 模块。 脚本的核心部分如下所示：

```
soup = BeautifulSoup(all_text, 'html.parser')
match = soup.findAll("img")
if len(match) > 0:
    for m in match:
        imagelist.append(str(m))

```

我们可以使用这个 `findAll` 方法来挖出图片标签。 这是一小部分输出：

```
<img src="images/pdf-form-ht3.png"/><img src="images/pdf-form-ht4.png"/><img src="images/pdf-form-ht5.png"/><img src="images/pdf-form-ht6.png"/><img align="middle" alt="GSview - Advanced Options Panel" src="images/gsadv1.png" title="GSview - Advanced Options Panel"/><img align="middle" alt="Scribus External Tools Preferences" src="images/gsadv2.png" title="Scribus External Tools Preferences"/>

```

到现在为止还挺好。我原以为下一步就可以搞定了，但是当我在脚本中尝试了一些字符串方法时，它返回了有关标记的错误而不是字符串的错误。 我将输出保存到一个文件中，并在 [KWrite](https://www.kde.org/applications/utilities/kwrite/) 中进行编辑。 KWrite 的一个好处是你可以使用正则表达式（regex）来做“查找和替换”操作，所以我可以用 `\n<img` 替换 `<img`，这样可以看得更清楚。 KWrite 的另一个好处是，如果你用正则表达式做了一个不明智的选择，你还可以撤消。

但我认为，肯定有比这更好的东西，所以我转而使用正则表达式，或者更具体地说 Python 的 `re` 模块。 这个新脚本的相关部分如下所示：

```
match = re.findall(r'src="(.*)/>', all_text)
if len(match)>0:
    for m in match:
        imagelist.append(m)

```

它的一小部分输出如下所示：

```
images/cmcanvas.png" title="Context Menu for the document canvas" alt="Context Menu for the document canvas" /></td></tr></table><br images/eps-imp1.png" title="EPS preview in a file dialog" alt="EPS preview in a file dialog" images/eps-imp5.png" title="Colors imported from an EPS file" alt="Colors imported from an EPS file" images/eps-imp4.png" title="EPS font substitution" alt="EPS font substitution" images/eps-imp2.png" title="EPS import progress" alt="EPS import progress" images/eps-imp3.png" title="Bitmap conversion failure" alt="Bitmap conversion failure"

```

乍一看，它看起来与上面的输出类似，并且附带有去除图像的标签部分的好处，但是有令人费解的是还夹杂着表格标签和其他内容。 我认为这涉及到这个正则表达式 `src="(.*)/>`，这被称为*贪婪*，意味着它不一定停止在遇到 `/>` 的第一个实例。我应该补充一点，我也尝试过 `src="(.*)"`，这真的没有什么更好的效果，我不是一个正则表达式专家（只是做了这个），找了各种方法来改进这一点但是并没什么用。

做了一系列的事情之后，甚至尝试了 Perl 的 `HTML::Parser` 模块，最终我试图将这与我为 Scribus 编写的一些脚本进行比较，这些脚本逐个字符的分析文本内容，然后采取一些行动。 为了最终目的，我终于想出了所有这些方法，并且完全不需要正则表达式或 HTML 解析器。 让我们回到展示的那个 `img` 标签的例子。

```
<img src="images/edit_shapes.png" ALT="Edit examples" ALIGN=left>

```

我决定回到 `src=` 这一块。 一种方法是等待 `s` 出现，然后看下一个字符是否是 `r`，下一个是 `c`，下一个是否 `=`。 如果是这样，那就匹配上了！ 那么两个双引号之间的内容就是我所需要的。 这种方法的问题在于需要连续识别上面这样的结构。 一种查看代表一行 HTML 文本的字符串的方法是：

```
for c in all_text:

```

但是这个逻辑太乱了，以至于不能持续匹配到前面的 `c`，还有之前的字符，更之前的字符，更更之前的字符。

最后，我决定专注于 `=` 并使用索引方法，以便我可以轻松地引用字符串中的任何先前或将来的字符。 这里是搜索部分：

```
    index = 3
    while index < linelength:
        if (all_text[index] == '='):
            if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and (all_text[index-1] == 'c'):
                imagefound(all_text, imagelist, index)
                index += 1
            else:
                index += 1
        else:
            index += 1

```

我用第四个字符开始搜索（索引从 0 开始），所以我在下面没有出现索引错误，并且实际上，在每一行的第四个字符之前不会有等号。 第一个测试是看字符串中是否出现了 `=`，如果没有，我们就会前进。 如果我们确实看到一个等号，那么我们会看前三个字符是否是 `s`、`r` 和 `c`。 如果全都匹配了，就调用函数 `imagefound`：

```
def imagefound(all_text, imagelist, index):
    end = 0
    index += 2
    newimage = ''
    while end == 0:
        if (all_text[index] != '"'):
            newimage = newimage + all_text[index]
            index += 1
        else:
            newimage = newimage + '\n'
            imagelist.append(newimage)
            end = 1
            return

```

我们给函数发送当前索引，它代表着 `=`。 我们知道下一个字符将会是 `"`，所以我们跳过两个字符，并开始向名为 `newimage` 的控制字符串添加字符，直到我们发现下一个 `"`，此时我们完成了一次匹配。 我们将字符串加一个换行符（`\n`）添加到列表 `imagelist` 中并返回（`return`），请记住，在剩余的这个 HTML 字符串中可能会有更多图片标签，所以我们马上回到搜索循环中。

以下是我们的输出现在的样子：

```
images/text-frame-link.png
images/text-frame-unlink.png
images/gimpoptions1.png
images/gimpoptions3.png
images/gimpoptions2.png
images/fontpref3.png
images/font-subst.png
images/fontpref2.png
images/fontpref1.png
images/dtp-studio.png

```

啊，干净多了，而这只花费几秒钟的时间。 我本可以将索引前移 7 步来剪切 `images/` 部分，但我更愿意把这个部分保存下来，以确保我没有剪切掉图像文件名的第一个字母，这很容易用 KWrite 编辑成功 —— 你甚至不需要正则表达式。 做完这些并保存文件后，下一步就是运行我编写的另一个脚本 `sortlist.py`：

```
#!/usr/bin/env python
# -*- coding: utf-8  -*-
# sortlist.py

import os

imagelist = []
for line in open('/tmp/imagelist_parse4.txt').xreadlines():
    imagelist.append(line)

imagelist.sort()

outfile = open('/tmp/imagelist_parse4_sorted.txt', 'w')
outfile.writelines(imagelist)
outfile.close()

```

这会读取文件内容，并存储为列表，对其排序，然后另存为另一个文件。 之后，我可以做到以下几点：

```
ls /home/gregp/development/Scribus15x/doc/en/images/*.png > '/tmp/actual_images.txt'

```

然后我需要在该文件上运行 `sortlist.py`，因为 `ls` 方法的排序与 Python 不同。 我原本可以在这些文件上运行比较脚本，但我更愿意以可视方式进行操作。 最后，我成功找到了 42 个图像，这些图像没有来自文档的 HTML 引用。

这是我的完整解析脚本：

```
#!/usr/bin/env python
# -*- coding: utf-8  -*-
# parseimg4.py

import os

def imagefound(all_text, imagelist, index):
    end = 0
    index += 2
    newimage = ''
    while end == 0:
        if (all_text[index] != '"'):
            newimage = newimage + all_text[index]
            index += 1
        else:
            newimage = newimage + '\n'
            imagelist.append(newimage)
            end = 1
            return

htmlnames = []
imagelist = []
tempstring = ''
filenames = os.listdir('/home/gregp/development/Scribus15x/doc/en/')
for name in filenames:
    if name.endswith('.html'):
        htmlnames.append(name)
#print htmlnames
for htmlfile in htmlnames:
    all_text = open('/home/gregp/development/Scribus15x/doc/en/' + htmlfile).read()
    linelength = len(all_text)
    index = 3
    while index < linelength:
        if (all_text[index] == '='):
            if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and
(all_text[index-1] == 'c'):
                imagefound(all_text, imagelist, index)
                index += 1
            else:
                index += 1
        else:
            index += 1

outfile = open('/tmp/imagelist_parse4.txt', 'w')
outfile.writelines(imagelist)
outfile.close()
imageno = len(imagelist)
print str(imageno) + " images were found and saved"

```

脚本名称为 `parseimg4.py`，这并不能真实反映我陆续编写的脚本数量（包括微调的和大改的以及丢弃并重新开始写的）。 请注意，我已经对这些目录和文件名进行了硬编码，但是很容易变得通用化，让用户输入这些信息。 同样，因为它们是工作脚本，所以我将输出发送到 `/tmp` 目录，所以一旦重新启动系统，它们就会消失。

这不是故事的结尾，因为下一个问题是：僵尸 HTML 文件怎么办？ 任何未使用的文件都可能会引用图像，不能被前面的方法所找出。 我们有一个 `menu.xml` 文件作为联机手册的目录，但我还需要考虑 TOC（LCTT 译注：TOC 是 table of contents 的缩写）中列出的某些文件可能引用了不在 TOC 中的文件，是的，我确实找到了一些这样的文件。

最后我可以说，这是一个比图像搜索更简单的任务，而且开发的过程对我有很大的帮助。

### 关于作者

Greg Pittman 是 Kentucky 州 Louisville 市的一名退休的神经学家，从二十世纪六十年代的 Fortran IV 语言开始长期以来对计算机和编程有着浓厚的兴趣。 当 Linux 和开源软件出现的时候，Greg 深受启发，去学习更多知识，并实现最终贡献的承诺。 他是 Scribus 团队的成员。[更多关于我](https://opensource.com/users/greg-p)

---

via: <https://opensource.com/article/18/1/parsing-html-python>

作者：[Greg Pittman](https://opensource.com/users/greg-p) 译者：[Flowsnow](https://github.com/Flowsnow) 校对：[wxy](https://github.com/wxy)

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


如何在 Linux 上安装应用程序

Summary: 学习在你的 Linux 计算机上摆弄那些软件。

学习在你的 Linux 计算机上摆弄那些软件。

# 如何在 Linux 上安装应用程序

>
> 学习在你的 Linux 计算机上摆弄那些软件。
>
>
>

如何在 Linux 上安装应用程序？因为有许多操作系统，这个问题不止有一个答案。应用程序可以可以来自许多来源 —— 几乎不可能数的清，并且每个开发团队都可以以他们认为最好的方式提供软件。知道如何安装你所得到的软件是成为操作系统高级用户的一部分。

### 仓库

十多年来，Linux 已经在使用软件库来分发软件。在这种情况下，“仓库”是一个托管可安装软件包的公共服务器。Linux 发行版提供了一条命令，以及该命令的图形界面，用于从服务器获取软件并将其安装到你的计算机。这是一个非常简单的概念，它已经成为所有主流手机操作系统的模式，最近，该模式也成为了两大闭源计算机操作系统的“应用商店”。

*不是应用程序商店*

从软件仓库安装是在 Linux 上安装应用程序的主要方法，它应该是你寻找想要安装的任何应用程序的首选地方。

从软件仓库安装，通常需要一个命令，如：

```
$ sudo dnf install inkscape

```

实际使用的命令取决于你所使用的 Linux 发行版。Fedora 使用 `dnf`，OpenSUSE 使用 `zypper`，Debian 和 Ubuntu 使用 `apt`，Slackware 使用 `sbopkg`，FreeBSD 使用 `pkg_add`，而基于 lllumos 的 Openlndiana 使用 `pkg`。无论你使用什么，该命令通常要搜索你想要安装应用程序的正确名称，因为有时候你认为的软件名称不是它官方或独有的名称：

```
$ sudo dnf search pyqt
PyQt.x86_64 : Python bindings for Qt3
PyQt4.x86_64 : Python bindings for Qt4
python-qt5.x86_64 : PyQt5 is Python bindings for Qt5

```

一旦你找到要安装的软件包的名称后，使用 `install` 子命令执行实际的下载和自动安装：

```
$ sudo dnf install python-qt5

```

有关从软件仓库安装的具体信息，请参阅你的 Linux 发行版的文档。

图形工具通常也是如此。搜索你认为你想要的，然后安装它。

与底层命令一样，图形安装程序的名称取决于你正在运行的 Linux 发行版。相关的应用程序通常使用“软件（software）”或“包（package）”等关键字进行标记，因此请在你的启动项或菜单中搜索这些词汇，然后你将找到所需的内容。 由于开源全由用户来选择，所以如果你不喜欢你的发行版提供的图形用户界面（GUI），那么你可以选择安装替代品。 你知道该如何做到这一点。

#### 额外仓库

你的 Linux 发行版为其打包的软件提供了标准仓库，通常也有额外的仓库。例如，[EPEL](https://fedoraproject.org/wiki/EPEL) 服务于 Red Hat Enterprise Linux 和 CentOS，[RPMFusion](http://rpmfusion.org) 服务于 Fedora，Ubuntu 有各种级别的支持以及个人包存档（PPA），[Packman](http://packman.links2linux.org/) 为 OpenSUSE 提供额外的软件以及 [SlackBuilds.org](http://slackbuilds.org) 为 Slackware 提供社区构建脚本。

默认情况下，你的 Linux 操作系统设置为只查看其官方仓库，因此如果你想使用其他软件集合，则必须自己添加额外库。你通常可以像安装软件包一样安装仓库。实际上，当你安装例如 [GNU Ring](https://ring.cx/en/download/gnu-linux) 视频聊天，[Vivaldi](http://vivaldi.com) web 浏览器，谷歌浏览器等许多软件时，你的实际安装是访问他们的私有仓库，从中将最新版本的应用程序安装到你的机器上。

*安装仓库*

你还可以通过编辑文本文件将仓库手动添加到你的软件包管理器的配置目录，或者运行命令来添加添加仓库。像往常一样，你使用的确切命令取决于 Linux 发行版本。例如，这是一个 `dnf` 命令，它将一个仓库添加到系统中：

```
$ sudo dnf config-manager --add-repo=http://example.com/pub/centos/7

```

### 不使用仓库来安装应用程序

仓库模型非常流行，因为它提供了用户（你）和开发人员之间的链接。重要更新发布之后，系统会提示你接受更新，并且你可以从一个集中位置接受所有更新。

然而，有时候一个软件包还没有放到仓库中时。这些安装包有几种形式。

#### Linux 包

有时候，开发人员会以通用的 Linux 打包格式分发软件，例如 RPM、DEB 或较新但非常流行的 FlatPak 或 Snap 格式。你不是访问仓库下载的，你只是得到了这个包。

例如，视频编辑器 [Lightworks](https://www.lwks.com/) 为 APT 用户提供了一个 `.deb` 文件，RPM 用户提供了 `.rpm` 文件。当你想要更新时，可以到网站下载最新的适合的文件。

这些一次性软件包可以使用从仓库进行安装时所用的一样的工具进行安装。如果双击下载的软件包，图形安装程序将启动并逐步完成安装过程。

或者，你可以从终端进行安装。这里的区别在于你从互联网下载的独立包文件不是来自仓库。这是一个“本地”安装，这意味着你的软件安装包不需要下载来安装。大多数软件包管理器都是透明处理的：

```
$ sudo dnf install ~/Downloads/lwks-14.0.0-amd64.rpm

```

在某些情况下，你需要采取额外的步骤才能使应用程序运行，因此请仔细阅读有关你正在安装软件的文档。

#### 通用安装脚本

一些开发人员以几种通用格式发布他们的包。常见的扩展名包括 `.run` 和 `.sh`。NVIDIA 显卡驱动程序、像 Nuke 和 Mari 这样的 Foundry visual FX 软件包以及来自 [GOG](http://gog.com) 的许多非 DRM 游戏都是用这种安装程序。（LCTT 译注：DRM 是数字版权管理。）

这种安装模式依赖于开发人员提供安装“向导”。一些安装程序是图形化的，而另一些只是在终端中运行。

有两种方式来运行这些类型的安装程序。

1、 你可以直接从终端运行安装程序：

```
$ sh ./game/gog_warsow_x.y.z.sh

```

2、 另外，你可以通过标记其为可执行文件来运行它。要标记为安装程序可执行文件，右键单击它的图标并选择其属性。

*给安装程序可执行权限。*

一旦你允许其运行，双击图标就可以安装了。

*GOG 安装程序*

对于其余的安装程序，只需要按照屏幕上的说明进行操作。

#### AppImage 便携式应用程序

AppImage 格式对于 Linux 相对来说比较新，尽管它的概念是基于 NeXT 和 Rox 的。这个想法很简单：运行应用程序所需的一切都应该放在一个目录中，然后该目录被视为一个“应用程序”。要运行该应用程序，只需双击该图标即可运行。不需要也要不应该把应用程序安装在传统意义的地方；它从你在硬盘上的任何地方运行都行。

尽管它可以作为独立应用运行，但 AppImage 通常提供一些系统集成。

*AppImage 系统集成*

如果你接受此条件，则将一个本地的 `.desktop` 文件安装到你的主目录。`.desktop` 文件是 Linux 桌面的应用程序菜单和 mimetype 系统使用的一个小配置文件。实质上，只是将桌面配置文件放置在主目录的应用程序列表中“安装”应用程序，而不实际安装它。你获得了安装某些东西的所有好处，以及能够在本地运行某些东西的好处，即“便携式应用程序”。

#### 应用程序目录

有时，开发人员只是编译一个应用程序，然后将结果发布到下载中，没有安装脚本，也没有打包。通常，这意味着你下载了一个 TAR 文件，然后 [解压缩](https://opensource.com/article/17/7/how-unzip-targz-file)，然后双击可执行文件（通常是你下载软件的名称）。

*下载 Twine*

当使用这种软件方式交付时，你可以将它放在你下载的地方，当你需要它时，你可以手动启动它，或者你可以自己进行快速但是麻烦的安装。这包括两个简单的步骤：

1. 将目录保存到一个标准位置，并在需要时手动启动它。
2. 将目录保存到一个标准位置，并创建一个 `.desktop` 文件，将其集成到你的系统中。

如果你只是为自己安装应用程序，那么传统上会在你的主目录中放个 `bin` （“<ruby> 二进制文件 <rt>  binary </rt></ruby>” 的简称）目录作为本地安装的应用程序和脚本的存储位置。如果你的系统上有其他用户需要访问这些应用程序，传统上将二进制文件放置在 `/opt` 中。最后，这取决于你存储应用程序的位置。

下载通常以带版本名称的目录进行，如 `twine_2.13` 或者 `pcgen-v6.07.04`。由于假设你将在某个时候更新应用程序，因此将版本号删除或创建目录的符号链接是个不错的主意。这样，即使你更新应用程序本身，为应用程序创建的启动程序也可以保持不变。

要创建一个 `.desktop` 启动文件，打开一个文本编辑器并创建一个名为 `twine.desktop` 的文件。[桌面条目规范](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) 由 [FreeDesktop.org](http://freedesktop.org) 定义。下面是一个简单的启动器，用于一个名为 Twine 的游戏开发 IDE，安装在系统范围的 `/opt` 目录中：

```
[Desktop Entry]
Encoding=UTF-8
Name=Twine
GenericName=Twine
Comment=Twine
Exec=/opt/twine/Twine
Icon=/usr/share/icons/oxygen/64x64/categories/applications-games.png
Terminal=false
Type=Application
Categories=Development;IDE;

```

棘手的一行是 `Exec` 行。它必须包含一个有效的命令来启动应用程序。通常，它只是你下载的东西的完整路径，但在某些情况下，它更复杂一些。例如，Java 应用程序可能需要作为 Java 自身的参数启动。

```
Exec=java -jar /path/to/foo.jar

```

有时，一个项目包含一个可以运行的包装脚本，这样你就不必找出正确的命令：

```
Exec=/opt/foo/foo-launcher.sh

```

在这个 Twine 例子中，没有与该下载的软件捆绑的图标，因此示例 `.desktop` 文件指定了 KDE 桌面附带的通用游戏图标。你可以使用类似的解决方法，但如果你更具艺术性，可以创建自己的图标，或者可以在 Internet 上搜索一个好的图标。只要 `Icon` 行指向一个有效的 PNG 或 SVG 文件，你的应用程序就会以该图标为代表。

示例脚本还将应用程序类别主要设置为 Development，因此在 KDE、GNOME 和大多数其他应用程序菜单中，Twine 出现在开发类别下。

为了让这个例子出现在应用程序菜单中，把 `twine.desktop` 文件放这到两个地方之一：

* 如果你将应用程序存储在你自己的家目录下，那么请将其放在 `~/.local/share/applications`。
* 如果你将应用程序存储在 `/opt` 目录或者其他系统范围的位置，并希望它出现在所有用户的应用程序菜单中，请将它放在 `/usr/share/applications` 目录中。

现在，该应用程序已安装，因为它需要与系统的其他部分集成。

### 从源代码编译

最后，还有真正的通用格式安装格式：源代码。从源代码编译应用程序是学习如何构建应用程序，如何与系统交互以及如何定制应用程序的好方法。尽管如此，它绝不是一个点击按钮式过程。它需要一个构建环境，通常需要安装依赖库和头文件，有时还要进行一些调试。

要了解更多关于从源代码编译的内容，请阅读[我这篇文章](https://opensource.com/article/17/10/open-source-cats)。

### 现在你明白了

有些人认为安装软件是一个神奇的过程，只有开发人员理解，或者他们认为它“激活”了应用程序，就好像二进制可执行文件在“安装”之前无效。学习许多不同的安装方法会告诉你安装实际上只是“将文件从一个地方复制到系统中适当位置”的简写。 没有什么神秘的。只要你去了解每次安装，不是期望应该如何发生，并且寻找开发者为安装过程设置了什么，那么通常很容易，即使它与你的习惯不同。

重要的是安装器要诚实于你。 如果你遇到未经你的同意尝试安装其他软件的安装程序（或者它可能会以混淆或误导的方式请求同意），或者尝试在没有明显原因的情况下对系统执行检查，则不要继续安装。

好的软件是灵活的、诚实的、开放的。 现在你知道如何在你的计算机上获得好软件了。

---

via: <https://opensource.com/article/18/1/how-install-apps-linux>

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

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


如何在 Linux / Unix 上使用 awk 打印文件名

Summary: 我想在 Linux / 类Unix 系统上使用 awk 打印文件名。 如何使用 awk 的 BEGIN 特殊模式打印文件名？

# 如何在 Linux / Unix 上使用 awk 打印文件名

Q：我想在 Linux / 类Unix 系统上使用 awk 打印文件名。 如何使用 awk 的 `BEGIN` 特殊模式打印文件名？ 我可以使用 gawk/awk 打印当前输入文件的名称吗？（LCTT 译注：读者最好能有一些 awk 的背景知识，否则阅读本文的时候会有一些困惑）

在 `FILENAME` 变量中存放着当前输入文件的名称。 您可以使用 `FILENAME` 显示或打印当前输入文件名，如果在命令行中未指定文件，则 `FILENAME` 的值为 `-` （标准输入）（LCTT 译注：多次按下回车键即可看到效果）。 但是，除非由 `getline` 设置，否则 `FILENAME` 在 `BEGIN` 特殊模式中未定义。

### 使用 awk 打印文件名

使用语法如下：

```
awk '{ print FILENAME }' fileNameHere
awk '{ print FILENAME }' /etc/hosts

```

因 awk 逐行读取文件，因此，你可能看到多个文件名，为了避免这个情况，你可以使用如下的命令：（LCTT 译注：`FNR` 表示当前记录数，只在文件中有效）

```
awk 'FNR == 1{ print FILENAME } ' /etc/passwd
awk 'FNR == 1{ print FILENAME } ' /etc/hosts

```

### 使用 awk 的 BEGIN 特殊规则打印文件名

使用下面的语法：（LCTT 译注：`ARGV[I]` 表示输入的第 i 个参数）

```
awk 'BEGIN{print ARGV[1]}' fileNameHere
awk 'BEGIN{print ARGV[1]}{ print "someting or do something on data" }END{}' fileNameHere
awk 'BEGIN{print ARGV[1]}' /etc/hosts

```

示例输出：

```
/etc/hosts

```

然而，`ARGV[1]` 并不是每一次都能奏效，例如：

```
ls -l /etc/hosts | awk 'BEGIN{print ARGV[1]} { print }'

```

你需要将它修改如下（假设 `ls -l` 只产生一行输出）：

```
ls -l /etc/hosts | awk '{ print "File: " $9 ", Owner:" $3 ", Group: " $4 }'

```

示例输出：

```
File: /etc/hosts, Owner:root, Group: root

```

### 处理由通配符指定的多个文件名

使用如下的示例语法：

```
awk '{ print FILENAME; nextfile } ' *.c
awk 'BEGIN{ print "Starting..."} { print FILENAME; nextfile }END{ print "....DONE"} ' *.conf

```

示例输出：

```
Starting...
blkid.conf
cryptconfig.conf
dhclient6.conf
dhclient.conf
dracut.conf
gai.conf
gnome_defaults.conf
host.conf
idmapd.conf
idnalias.conf
idn.conf
insserv.conf
iscsid.conf
krb5.conf
ld.so.conf
logrotate.conf
mke2fs.conf
mtools.conf
netscsid.conf
nfsmount.conf
nscd.conf
nsswitch.conf
openct.conf
opensc.conf
request-key.conf
resolv.conf
rsyncd.conf
sensors3.conf
slp.conf
smartd.conf
sysctl.conf
vconsole.conf
warnquota.conf
wodim.conf
xattr.conf
xinetd.conf
yp.conf
....DONE

```

`nextfile` 告诉 awk 停止处理当前的输入文件。 下一个输入记录读取来自下一个输入文件。 更多信息，请参见 awk/[gawk](https://www.gnu.org/software/gawk/manual/) 命令手册页：

```
man awk
man gawk

```

**关于作者**

作者是 nixCraft 的创立者，也是经验丰富的系统管理员和 Linux/Unix shell 脚本的培训师。 他曾与全球各行各业的客户合作，涉及 IT，教育，国防和空间研究以及非营利部门等多个行业。 您可以在 [Twitter](https://twitter.com/nixcraft)，[Facebook](https://facebook.com/nixcraft) 和 [Google+](https://plus.google.com/+CybercitiBiz)上关注他。 可以通过订阅我的 [RSS](https://www.cyberciti.biz/atom/atom.xml) 来获取更多的关于**系统管理，Linux/Unix ，和开源主题**的相关资料。

---

via: <https://www.cyberciti.biz/faq/how-to-print-filename-with-awk-on-linux-unix/>

作者：[Vivek Gite](https://www.cyberciti.biz/) 译者：[amwps290](https://github.com/amwps290) 校对：[wxy](https://github.com/wxy)

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


COPR 仓库中 4 个很酷的新软件

# COPR 仓库中 4 个很酷的新软件

COPR 是一个个人软件仓库[集合](https://copr.fedorainfracloud.org/)，它们不存在于 Fedora 中。有些软件不符合标准而不容易打包。或者它可能不符合其他的 Fedora 标准，尽管它是自由和开源的。COPR 可以在 Fedora 套件之外提供这些项目。COPR 中的软件不受 Fedora 基础设施的支持，或者是由项目自己签名的。但是，它是尝试新的或实验性软件的一种很好的方法。

这是 COPR 中一系列新的和有趣的项目。

### Elisa

[Elisa](https://community.kde.org/Elisa) 是一个极小的音乐播放器。它可以让你通过专辑、艺术家或曲目浏览音乐。它会自动检测你的 `~/Music` 目录中的所有可播放音乐，因此它根本不需要设置 - 它也不提供任何音乐。目前，Elisa 专注于做一个简单的音乐播放器，所以它不提供管理音乐收藏的工具。

#### 安装说明

仓库目前为 Fedora 26、27 和 Rawhide 提供 Elisa。要安装 Elisa，请使用以下命令：

```
sudo dnf copr enable eclipseo/elisa
sudo dnf install elisa

```

### 必应壁纸

[必应壁纸](http://bingwallpapers.lekgoara.com/)是一个简单的程序，它会下载当日的必应壁纸，并将其设置为桌面壁纸或锁屏图片。该程序可以在设定的时间间隔内轮转目录中的图片，并在一段时间后删除旧图片。

#### 安装说明

仓库目前为 Fedora 25、26、27 和 Rawhide 提供必应壁纸。要安装必应壁纸，请使用以下命令：

```
sudo dnf copr enable julekgwa/Bingwallpapers
sudo dnf install bingwallpapers

```

### Polybar

[Polybar](https://github.com/jaagr/polybar) 是一个创建状态栏的工具。它有很多自定义选项以及显示常用服务的信息的内置功能，例如 [bspwm](https://github.com/baskerville/bspwm)、[i3](https://i3wm.org/) 的系统托盘图标、窗口标题、工作区和桌面面板等。你也可以为你的状态栏配置你自己的模块。有关使用和配置的更多信息，请参考 [Polybar 的 wiki](https://github.com/jaagr/polybar/wiki)。

#### 安装说明

仓库目前为 Fedora 27 提供 Polybar。要安装 Polybar，请使用以下命令：

```
sudo dnf copr enable tomwishaupt/polybar
sudo dnf install polybar

```

### Netdata

[Netdata](http://my-netdata.io/) 是一个分布式监控系统。它可以运行在包括个人电脑、服务器、容器和物联网设备在内的所有系统上，从中实时收集指标。所有的信息都可以使用 netdata 的 web 面板访问。此外，Netdata 还提供预配置的警报和通知来检测性能问题，以及用于创建自己的警报的模板。

#### 安装说明

仓库目前提供 EPEL 7、Fedora 27 和 Rawhide 提供 netdata。要安装 netdata，请使用以下命令：

```
sudo dnf copr enable recteurlp/netdata
sudo dnf install netdata

```

---

via: <https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-january/>

作者：[Dominik Turecek](https://fedoramagazine.org) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


邮件传输代理（MTA）基础

# 邮件传输代理（MTA）基础

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

### 概述

本教程中，你将学习：

* 使用 `mail` 命令。
* 创建邮件别名。
* 配置电子邮件转发。
* 了解常见邮件传输代理（MTA），比如，postfix、sendmail、qmail、以及 exim。

### 控制邮件去向

Linux 系统上的电子邮件是使用 MTA 投递的。你的 MTA 投递邮件到你的系统上的其他用户，并且 MTA 彼此通讯跨越系统投递到全世界。

Sendmail 是最古老的 Linux MTA。它最初起源于 1979 年用于阿帕网（ARPANET）的 delivermail 程序。如今它有几个替代品，在本教程中，我也会介绍它们。

### 前提条件

为完成本系列教程的大部分内容，你需要具备 Linux 的基础知识，你需要拥有一个 Linux 系统来实践本教程中的命令。你应该熟悉 GNU 以及 UNIX 命令。有时候不同版本的程序的输出格式可能不同，因此，在你的系统中输出的结果可能与我在下面列出的稍有不同。

在本教程中，我使用的是 Ubuntu 14.04 LTS 和 sendmail 8.14.4 来做的演示。

### 邮件传输

邮件传输代理（比如 sendmail）在用户之间和系统之间投递邮件。大量的因特网邮件使用简单邮件传输协议（SMTP），但是本地邮件可能是通过文件或者套接字等其它可能的方式来传输的。邮件是一种存储和转发的操作，因此，在用户接收邮件或者接收系统和通讯联系可用之前，邮件一直是存储在某种文件或者数据库中。配置和确保 MTA 的安全是非常复杂的任务，它们中的大部分内容都已经超出了本教程的范围。

### mail 命令

如果你使用 SMTP 协议传输电子邮件，你或许知道你可以使用许多邮件客户端，包括 `mail`、`mutt`、`alpine`、`notmuch`、以及其它基于主机控制台或者图形界面的邮件客户端。`mail` 命令是最老的、可用于脚本中的、发送和接收以及管理收到的邮件的备用命令。

你可以使用 `mail` 命令交互式的向列表中的收件人发送信息，或者不使用参数去查看你收到的邮件。清单 1 展示了如何在你的系统上去发送信息到用户 steve 和 pat，同时抄送拷贝给用户 bob。当提示 `Cc:` 和 `subject:` 时，输入相应的抄送用户以及邮件主题，接着输入邮件正文，输入完成后按下 `Ctrl+D` （按下 `Ctrl` 键并保持再按下 `D` 之后全部松开）。

```
ian@attic4-u14:~$ mail steve,pat
Cc: bob
Subject: Test message 1
This is a test message

Ian

```

*清单 1. 使用 `mail` 交互式发送邮件*

如果一切顺利，你的邮件已经发出。如果在这里发生错误，你将看到错误信息。例如，如果你在接收者列表中输入一个无效的用户名，邮件将无法发送。注意在本示例中，所有的用户都在本地系统上存在，因此他们都是有效用户。

你也可以使用命令行以非交互式发送邮件。清单 2 展示了如何给用户 steve 和 pat 发送一封邮件。这种方式可以用在脚本中。在不同的软件包中 `mail` 命令的版本不同。对于抄送（`Cc:`）有些支持一个 `-c` 选项，但是我使用的这个版本不支持这个选项，因此，我仅将邮件发送到收件人。

```
ian@attic4-u14:~$ mail -t steve,pat -s "Test message 2" <<< "Another test.\n\nIan"

```

*清单 2. 使用 `mail` 命令非交互式发送邮件*

如果你使用没有选项的 `mail` 命令，你将看到一个如清单 3 中所展示的那样一个收到信息的列表。你将看到用户 steve 有我上面发送的两个信息，再加上我以前发送的一个信息和后来用户 bob 发送的信息。所有的邮件都用 'N' 标记为新邮件。

```
steve@attic4-u14:~$ mail
"/var/mail/steve": 4 messages 4 new
>N 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 N 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
 N 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?

```

*清单 3. 使用 `mail` 查看收到的邮件*

当前选中的信息使用一个 `>` 来标识，它是清单 3 中的第一封邮件。如果你按下回车键（`Enter`），将显示下一封未读邮件的第一页。按下空格楗将显示这个邮件的下一页。当你读完这个邮件并想返回到 `?` 提示符时，按下回车键再次查看下一封邮件，依次类推。在 `?` 提示符下，你可以输入 `h` 再次去查看邮件头。你看过的邮件前面将显示一个 `R` 状态，如清单 4 所示。

```
? h
 R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
?

```

*清单 4. 使用 `h` 去显示邮件头*

在这个图中，Steve 已经读了三个邮件，但是没有读来自 bob 的邮件。你可以通过数字来选择单个的信息，你也可以通过输入 `d` 删除你不想要的信息，或者输入 `3d` 去删除第三个信息。如果你输入 `q` 你将退出 `mail` 命令。已读的信息将被转移到你的家目录下的 `mbox` 文件中，而未读的信息仍然保留在你的收件箱中，默认在 `/var/mail/$(id -un)`。如清单 5 所示。

```
? h
 R 1 Ian Shields Tue Dec 12 21:03 16/704 test message
 R 2 Ian Shields Tue Dec 12 21:04 18/701 Test message 1
>R 3 Ian Shields Tue Dec 12 21:23 15/661 Test message 2
 N 4 Bob C Tue Dec 12 21:45 17/653 How about lunch tomorrow?
? q
Saved 3 messages in /home/steve/mbox
Held 1 message in /var/mail/steve
You have mail in /var/mail/steve

```

*清单 5. 使用 `q` 退出 `mail`*

如果你输入 `x` 而不是使用 `q` 去退出，你的邮箱在退出后将不保留你做的改变。因为这在 `/var` 文件系统中，你的系统管理员可能仅允许邮件在一个有限的时间范围内保留。要重新读取或者以其它方式再次处理保存在你的本地邮箱中的邮件，你可以使用 `-f` 选项去指定想要去读的文件。比如，`mail -f mbox`。

### 邮件别名

在前面的节中，看了如何在系统上给许多用户发送邮件。你可以使用一个全限定名字（比如 [ian@myexampledomain.com](mailto:ian@myexampledomain.com)）给其它系统上的用户发送邮件。

有时候你可能希望用户的所有邮件都可以发送到其它地方。比如，你有一个服务器群，你希望所有的 root 用户的邮件都发给中心的系统管理员。或者你可能希望去创建一个邮件列表，将邮件发送给一些人。为实现上述目标，你可以使用别名，别名允许你为一个给定的用户名定义一个或者多个目的地。这个目的地或者是其它用户的邮箱、文件、管道、或者是某个进一步处理的命令。你可以在 `/etc/mail/aliases` 或者 `/etc/aliases` 中创建别名来实现上述目的。根据你的系统的不同，你可以找到上述其中一个，符号链接到它们、或者其中之一。改变别名文件你需要有 root 权限。

别名的格式一般是：

```
name: addr_1, addr_2, addr_3, ...

```

这里 `name` 是一个要别名的本地用户名字（即别名），而 `addr_1`，`addr_2`，... 可以是一个或多个别名。别名可以是一个本地用户、一个本地文件名、另一个别名、一个命令、一个包含文件，或者一个外部地址。

因此，发送邮件时如何区分别名呢（addr-N）？

* 本地用户名是你机器上系统中的一个用户名字。从技术角度来说，它可以通过调用 `getpwnam` 命令找到它。
* 本地文件名是以 `/` 开始的完全路径和文件名。它必须是 `sendmail` 可写的。信息会追加到这个文件上。
* 命令是以一个管道符号开始的（`|`）。信息是通过标准输入的方式发送到命令的。
* 包含文件别名是以 `:include:` 和指定的路径和文件名开始的。在该文件中的别名被添加到该名字所代表的别名中。
* 外部地址是一个电子邮件地址，比如 [john@somewhere.com](mailto:john@somewhere.com)。

你可以在你的系统中找到一个示例文件，它是与你的 sendmail 包一起安装的，它的位置在 `/usr/share/sendmail/examples/db/aliases`。它包含一些给 `postmaster`、`MAILER-DAEMON`、`abuse` 和 `spam 的别名建议。在清单 6，我把我的 Ubuntu 14.04 LTS 系统上的一些示例文件，和人工修改的示例结合起来说明一些可能的情况。

```
ian@attic4-u14:~$ cat /etc/mail/aliases
# First include some default system aliases from
# /usr/share/sendmail/examples/db/aliases

#
# Mail aliases for sendmail
#
# You must run newaliases(1) after making changes to this file.
#

# Required aliases
postmaster: root
MAILER-DAEMON:  postmaster

# Common aliases
abuse:    postmaster
spam:   postmaster

# Other aliases

# Send steve's mail to bob and pat instead
steve: bob,pat

# Send pat's mail to a file in her home directory and also to her inbox.
# Finally send it to a command that will make another copy.
pat: /home/pat/accumulated-mail,
 \pat,
 |/home/pat/makemailcopy.sh

# Mailing list for system administrators
sysadmins: :include: /etc/aliases-sysadmins

```

*清单 6. 人工修改的 /etc/mail/aliases 示例*

注意那个 pat 既是一个别名也是一个系统中的用户。别名是以递归的方式展开的，因此，如果一个别名也是一个名字，那么它将被展开。Sendmail 并不会给同一个用户发送相同的邮件两遍，因此，如果你正好将 pat 作为 pat 的别名，那么 sendmail 在已经找到并处理完用户 pat 之后，将忽略别名 pat。为避免这种问题，你可以在别名前使用一个 `\` 做为前缀去指示它是一个不要进一步引起混淆的名字。在这种情况下，pat 的邮件除了文件和命令之外，其余的可能会被发送到他的正常的邮箱中。

在 `aliases` 文件中以 `#` 开始的行是注释，它会被忽略。以空白开始的行会以延续行来处理。

清单 7 展示了包含文件 `/etc/aliases-sysadmins`。

```
ian@attic4-u14:~$ cat /etc/aliases-sysadmins

# Mailing list for system administrators
bob,pat

```

*清单 7 包含文件 /etc/aliases-sysadmins*

### newaliases 命令

sendmail 使用的主要配置文件会被编译成数据库文件。邮件别名也是如此。你可以使用 `newaliases` 命令去编译你的 `/etc/mail/aliases` 和任何包含文件到 `/etc/mail/aliases.db` 中。注意，`newaliases` 命令等价于 `sendmail -bi`。清单 8 展示了一个示例。

```
ian@attic4-u14:~$ sudo newaliases
/etc/mail/aliases: 7 aliases, longest 62 bytes, 184 bytes total
ian@attic4-u14:~$ ls -l /etc/mail/aliases*
lrwxrwxrwx 1 root smmsp 10 Dec 8 15:48 /etc/mail/aliases -> ../aliases
-rw-r----- 1 smmta smmsp 12288 Dec 13 23:18 /etc/mail/aliases.db

```

*清单 8. 为邮件别名重建数据库*

### 使用别名的示例

清单 9 展示了一个简单的 shell 脚本，它在我的别名示例中以一个命令的方式来使用。

```
ian@attic4-u14:~$ cat ~pat/makemailcopy.sh
#!/bin/bash

# Note: Target file ~/mail-copy must be writeable by sendmail!
cat >> ~pat/mail-copy

```

*清单 9. makemailcopy.sh 脚本*

清单 10 展示了用于测试时更新的文件。

```
ian@attic4-u14:~$ date
Wed Dec 13 22:54:22 EST 2017
ian@attic4-u14:~$ mail -t sysadmins -s "sysadmin test 1" <<< "Testing mail"
ian@attic4-u14:~$ ls -lrt $(find /var/mail ~pat -type f -mmin -3 2>/dev/null )
-rw-rw---- 1 pat mail 2046 Dec 13 22:54 /home/pat/mail-copy
-rw------- 1 pat mail 13240 Dec 13 22:54 /var/mail/pat
-rw-rw---- 1 pat mail 9442 Dec 13 22:54 /home/pat/accumulated-mail
-rw-rw---- 1 bob mail 12522 Dec 13 22:54 /var/mail/bob

```

*清单 10. /etc/aliases-sysadmins 包含文件*

需要注意的几点：

* sendmail 使用的用户和组的名字是 mail。
* sendmail 在 `/var/mail` 保存用户邮件，它也是用户 mail 的家目录。用户 ian 的默认收件箱在 `/var/mail/ian` 中。
* 如果你希望 sendmail 在用户目录下写入文件，这个文件必须允许 sendmail 可写入。与其让任何人都可以写入，还不如定义一个组可写入，组名称为 mail。这需要系统管理员来帮你完成。

### 使用一个 `.forward` 文件去转发邮件

别名文件是由系统管理员来管理的。个人用户可以使用它们自己的家目录下的 `.forward` 文件去转发他们自己的邮件。你可以在你的 `.forward` 文件中放任何可以出现在别名文件的右侧的东西。这个文件的内容是明文的，不需要编译。当你收到邮件时，sendmail 将检查你的家目录中的 `.forward` 文件，然后就像处理别名一样处理它。

### 邮件队列和 mailq 命令

Linux 邮件使用存储-转发的处理模式。你已经看到的已接收邮件，在你读它之前一直保存在文件 `/var/mail` 中。你发出的邮件在接收服务器连接可用之前也会被保存。你可以使用 `mailq` 命令去查看邮件队列。清单 11 展示了一个发送给外部用户 ian@attic4-c6 的一个邮件示例，以及运行 `mailq` 命令的结果。在这个案例中，当前服务器没有连接到 attic4-c6，因此邮件在与对方服务器连接可用之前一直保存在队列中。

```
ian@attic4-u14:~$ mail -t ian@attic4-c6 -s "External mail" <<< "Testing external mail queues"
ian@attic4-u14:~$ mailq
MSP Queue status...
/var/spool/mqueue-client is empty
    Total requests: 0
MTA Queue status...
    /var/spool/mqueue (1 request)
-----Q-ID----- --Size-- -----Q-Time----- ------------Sender/Recipient-----------
vBE4mdE7025908* 29 Wed Dec 13 23:48 <ian@attic4-u14.hopto.org>
           <ian@attic4-c6.hopto.org>
    Total requests: 1

```

*清单 11. 使用 `mailq` 命令*

### 其它邮件传输代理

为解决使用 sendmail 时安全方面的问题，在上世纪九十年代开发了几个其它的邮件传输代理。Postfix 或许是最流行的一个，但是 qmail 和 exim 也大量使用。

Postfix 是 IBM 为代替 sendmail 而研发的。它更快、也易于管理、安全性更好一些。从外表看它非常像 sendmail，但是它的内部完全与 sendmail 不同。

Qmail 是一个安全、可靠、高效、简单的邮件传输代理，它由 Dan Bernstein 开发。但是，最近几年以来，它的核心包已经不再更新了。Qmail 和几个其它的包已经被吸收到 IndiMail 中了。

Exim 是另外一个 MTA，它由 University of Cambridge 开发。最初，它的名字是 `EXperimental Internet Mailer`。

所有的这些 MTA 都是为代替 sendmail 而设计的，因此，它们它们都兼容 sendmail 的一些格式。它们都能够处理别名和 `.forward` 文件。有些封装了一个 `sendmail` 命令作为一个到特定的 MTA 自有命令的前端。尽管一些选项可能会被静默忽略，但是大多数都允许使用常见的 sendmail 选项。`mailq` 命令是被直接支持的，或者使用一个类似功能的命令来代替。比如，你可以使用 `mailq` 或者 `exim -bp` 去显示 exim 邮件队列。当然，输出可以看到与 sendmail 的 `mailq` 命令的不同之外。

查看相关的主题，你可以找到更多的关于这些 MTA 的更多信息。

对 Linux 上的邮件传输代理的介绍到此结束。

---

via: <https://www.ibm.com/developerworks/library/l-lpic1-108-3/index.html>

作者：[Ian Shields](https://www.ibm.com) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


通过玩命令行游戏来测试你的 BASH 技能

# 通过玩命令行游戏来测试你的 BASH 技能

如果我们经常在实际场景中使用 Linux 命令，我们就会更有效的学习和记忆它们。除非你经常使用 Linux 命令，否则你可能会在一段时间内忘记它们。无论你是新手还是老手，总会有一些趣味的方法来测试你的 BASH 技能。在本教程中，我将解释如何通过玩命令行游戏来测试你的 BASH 技能。其实从技术上讲，这些并不是像 Super TuxKart、极品飞车或 CS 等真正的游戏。这些只是 Linux 命令培训课程的游戏化版本。你将需要根据游戏本身的某些指示来完成一个任务。

现在，我们来看看几款能帮助你实时学习和练习 Linux 命令的游戏。这些游戏不是消磨时间或者令人惊诧的，这些游戏将帮助你获得终端命令的真实体验。请继续阅读：

### 使用 “Wargames” 来测试 BASH 技能

这是一个在线游戏，所以你必须联网。这些游戏可以帮助你以充满乐趣的游戏形式学习和练习 Linux 命令。Wargames 是一个 shell 游戏的集合，每款游戏有很多关卡。只有通过解决先前的关卡才能访问下一个关卡。不要担心！每个游戏都提供了有关如何进入下一关的清晰简洁说明。

要玩 Wargames，请点击以下链接：[Wargames](http://overthewire.org/wargames/) 。

如你所见，左边列出了许多 shell 游戏。每个 shell 游戏都有自己的 SSH 端口。所以，你必须通过本地系统配置 SSH 连接到游戏，你可以在 Wargames 网站的左上角找到关于如何使用 SSH 连接到每个游戏的信息。

例如，让我们来玩 Bandit 游戏吧。为此，单击 Wargames 主页上的 Bandit 链接。在左上角，你会看到 Bandit 游戏的 SSH 信息。

正如你在上面的屏幕截图中看到的，有很多关卡。要进入每个关卡，请单机左侧列中的相应链接。此外，右侧还有适合初学者的说明。如果你对如何玩此游戏有任何疑问，请阅读它们。

现在，让我们点击它进入关卡 0。在下一个屏幕中，你将获得该关卡的 SSH 信息。

正如你在上面的屏幕截图中看到的，你需要配置 SSH 端口 2220 连接 `bandit.labs.overthewire.org`，用户名是 `bandit0`，密码是 `bandit0`。

让我们连接到 Bandit 游戏关卡 0。

```
$ ssh bandit0@bandit.labs.overthewire.org -p 2220

```

输入密码 `bandit0`。

示例输出将是：

登录后，输入 `ls` 命令查看内容或者进入关卡 1 页面，了解如何通过关卡 1 等等。建议的命令列表已在每个关卡提供。所以，你可以选择和使用任何合适的命令来解决每个关卡。

我必须承认，Wargames 是令人上瘾的，并且解决每个关卡是非常有趣的。 尽管有些关卡确实很具挑战性，你可能需要谷歌才能知道如何解决问题。 试一试，你会很喜欢它。

### 使用 “Terminus” 来测试 BASH 技能

这是另一个基于浏览器的在线 CLI 游戏，可用于改进或测试你的 Linux 命令技能。要玩这个游戏，请打开你的 web 浏览器并导航到以下 URL：[Play Terminus Game](http://web.mit.edu/mprat/Public/web/Terminus/Web/main.html)

一旦你进入游戏，你会看到有关如何玩游戏的说明。与 Wargames 不同，你不需要连接到它们的游戏服务器来玩游戏。Terminus 有一个内置的 CLI，你可以在其中找到有关如何使用它的说明。

你可以使用命令 `ls` 查看周围的环境，使用命令 `cd 位置` 移动到新的位置，返回使用命令 `cd ..`，与这个世界进行交互使用命令 `less 项目` 等等。要知道你当前的位置，只需输入 `pwd`。

### 使用 “clmystery” 来测试 BASH 技能

与上述游戏不同，你可以在本地玩这款游戏。你不需要连接任何远程系统，这是完全离线的游戏。

相信我，这家伙是一个有趣的游戏。按照给定的说明，你将扮演一个侦探角色来解决一个神秘案件。

首先，克隆仓库：

```
$ git clone https://github.com/veltman/clmystery.git

```

或者，从 [这里](https://github.com/veltman/clmystery/archive/master.zip) 将其作为 zip 文件下载。解压缩并切换到下载文件的地方。最后，通过阅读 `instructions` 文件来开启宝箱。

```
[sk@sk]: clmystery-master>$ ls
cheatsheet.md cheatsheet.pdf encoded hint1 hint2 hint3 hint4 hint5 hint6 hint7 hint8 instructions LICENSE.md mystery README.md solution

```

这里是玩这个游戏的说明：

终端城发生了一起谋杀案，TCPD 需要你的帮助。你需要帮助它们弄清楚是谁犯罪了。

为了查明是谁干的，你需要到 `mystery` 子目录并从那里开始工作。你可能需要查看犯罪现场的所有线索（ `crimescene` 文件）。现场的警官相当谨慎，所以他们在警官报告中写下了一切。幸运的是，警官以全部大写的 “CLUE” 一词把真正的线索标记了出来。

如果里遇到任何问题，请打开其中一个提示文件，例如 “hint1”，“hint2” 等。你可以使用下面的 `cat` 命令打开提示文件。

```
$ cat hint1
$ cat hint2

```

要检查你的答案或找出解决方案，请在 `clmystery` 目录中打开文件 `solution`。

```
$ cat solution

```

要了解如何使用命令行，请参阅 `cheatsheet.md` 或 `cheatsheet.pdf` （在命令行中，你可以输入 ‘nano cheatsheet.md’）。请勿使用文本编辑器查看除 `instructions`、`cheatsheet` 和 `hint` 以外的任何文件。

有关更多详细信息，请参阅 [clmystery GitHub](https://github.com/veltman/clmystery) 页面。

推荐阅读：

而这就是我现在所知道的。如果将来遇到任何问题，我会继续添加更多游戏。将此链接加入书签并不时访问。如果你知道其他类似的游戏，请在下面的评论部分告诉我，我将测试和更新本指南。

还有更多好东西，敬请关注！

干杯！

---

via: <https://www.ostechnix.com/test-your-bash-skills-by-playing-command-line-games/>

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

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


gdb 如何工作？

Summary: 最近，我使用 gdb 来查看我的 Ruby 程序，所以，我们将对一个 Ruby 程序运行 gdb 。

# gdb 如何工作？

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

大家好！今天，我开始进行我的 [ruby 堆栈跟踪项目](http://jvns.ca/blog/2016/06/12/a-weird-system-call-process-vm-readv/)，我发觉我现在了解了一些关于 `gdb` 内部如何工作的内容。

最近，我使用 `gdb` 来查看我的 Ruby 程序，所以，我们将对一个 Ruby 程序运行 `gdb` 。它实际上就是一个 Ruby 解释器。首先，我们需要打印出一个全局变量的地址：`ruby_current_thread`。

### 获取全局变量

下面展示了如何获取全局变量 `ruby_current_thread` 的地址：

```
$ sudo gdb -p 2983
(gdb) p & ruby_current_thread
$2 = (rb_thread_t **) 0x5598a9a8f7f0 <ruby_current_thread>

```

变量能够位于的地方有<ruby> 堆 <rt>  heap </rt></ruby>、<ruby> 栈 <rt>  stack </rt></ruby>或者程序的<ruby> 文本段 <rt>  text </rt></ruby>。全局变量是程序的一部分。某种程度上，你可以把它们想象成是在编译的时候分配的。因此，我们可以很容易的找出全局变量的地址。让我们来看看，`gdb` 是如何找出 `0x5598a9a87f0` 这个地址的。

我们可以通过查看位于 `/proc` 目录下一个叫做 `/proc/$pid/maps` 的文件，来找到这个变量所位于的大致区域。

```
$ sudo cat /proc/2983/maps | grep bin/ruby
5598a9605000-5598a9886000 r-xp 00000000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby
5598a9a86000-5598a9a8b000 r--p 00281000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby
5598a9a8b000-5598a9a8d000 rw-p 00286000 00:32 323508                     /home/bork/.rbenv/versions/2.1.6/bin/ruby

```

所以，我们看到，起始地址 `5598a9605000` 和 `0x5598a9a8f7f0` 很像，但并不一样。哪里不一样呢，我们把两个数相减，看看结果是多少：

```
(gdb) p/x 0x5598a9a8f7f0 - 0x5598a9605000
$4 = 0x48a7f0

```

你可能会问，这个数是什么？让我们使用 `nm` 来查看一下程序的符号表。

```
sudo nm /proc/2983/exe | grep ruby_current_thread
000000000048a7f0 b ruby_current_thread

```

我们看到了什么？能够看到 `0x48a7f0` 吗？是的，没错。所以，如果我们想找到程序中一个全局变量的地址，那么只需在符号表中查找变量的名字，然后再加上在 `/proc/whatever/maps` 中的起始地址，就得到了。

所以现在，我们知道 `gdb` 做了什么。但是，`gdb` 实际做的事情更多，让我们跳过直接转到…

### 解引用指针

```
(gdb) p ruby_current_thread
$1 = (rb_thread_t *) 0x5598ab3235b0

```

我们要做的下一件事就是解引用 `ruby_current_thread` 这一指针。我们想看一下它所指向的地址。为了完成这件事，`gdb` 会运行大量系统调用比如：

```
ptrace(PTRACE_PEEKTEXT, 2983, 0x5598a9a8f7f0, [0x5598ab3235b0]) = 0

```

你是否还记得 `0x5598a9a8f7f0` 这个地址？`gdb` 会问：“嘿，在这个地址中的实际内容是什么？”。`2983` 是我们运行 gdb 这个进程的 ID。gdb 使用 `ptrace` 这一系统调用来完成这一件事。

好极了！因此，我们可以解引用内存并找出内存地址中存储的内容。有一些有用的 `gdb` 命令，比如 `x/40w 变量` 和 `x/40b 变量` 分别会显示给定地址的 40 个字/字节。

### 描述结构

一个内存地址中的内容可能看起来像下面这样。可以看到很多字节！

```
(gdb) x/40b ruby_current_thread
0x5598ab3235b0: 16  -90 55  -85 -104    85  0   0
0x5598ab3235b8: 32  47  50  -85 -104    85  0   0
0x5598ab3235c0: 16  -64 -55 115 -97 127 0   0
0x5598ab3235c8: 0   0   2   0   0   0   0   0
0x5598ab3235d0: -96 -83 -39 115 -97 127 0   0

```

这很有用，但也不是非常有用！如果你是一个像我一样的人类并且想知道它代表什么，那么你需要更多内容，比如像这样：

```
(gdb) p *(ruby_current_thread)
$8 = {self = 94114195940880, vm = 0x5598ab322f20, stack = 0x7f9f73c9c010,
    stack_size = 131072, cfp = 0x7f9f73d9ada0, safe_level = 0,    raised_flag = 0,
    last_status = 8, state = 0, waiting_fd = -1, passed_block = 0x0,
    passed_bmethod_me = 0x0, passed_ci = 0x0,    top_self = 94114195612680,
    top_wrapper = 0, base_block = 0x0, root_lep = 0x0, root_svar = 8, thread_id =
    140322820187904,

```

太好了。现在就更加有用了。`gdb` 是如何知道这些所有域的，比如 `stack_size` ？是从 `DWARF` 得知的。`DWARF` 是存储额外程序调试数据的一种方式，从而像 `gdb` 这样的调试器能够工作的更好。它通常存储为二进制的一部分。如果我对我的 Ruby 二进制文件运行 `dwarfdump` 命令，那么我将会得到下面的输出：

（我已经重新编排使得它更容易理解）

```
DW_AT_name                  "rb_thread_struct"
DW_AT_byte_size             0x000003e8
DW_TAG_member
  DW_AT_name                  "self"
  DW_AT_type                  <0x00000579>
  DW_AT_data_member_location  DW_OP_plus_uconst 0
DW_TAG_member
  DW_AT_name                  "vm"
  DW_AT_type                  <0x0000270c>
  DW_AT_data_member_location  DW_OP_plus_uconst 8
DW_TAG_member
  DW_AT_name                  "stack"
  DW_AT_type                  <0x000006b3>
  DW_AT_data_member_location  DW_OP_plus_uconst 16
DW_TAG_member
  DW_AT_name                  "stack_size"
  DW_AT_type                  <0x00000031>
  DW_AT_data_member_location  DW_OP_plus_uconst 24
DW_TAG_member
  DW_AT_name                  "cfp"
  DW_AT_type                  <0x00002712>
  DW_AT_data_member_location  DW_OP_plus_uconst 32
DW_TAG_member
  DW_AT_name                  "safe_level"
  DW_AT_type                  <0x00000066>

```

所以，`ruby_current_thread` 的类型名为 `rb_thread_struct`，它的大小为 `0x3e8` （即 1000 字节），它有许多成员项，`stack_size` 是其中之一，在偏移为 `24` 的地方，它有类型 `31` 。`31` 是什么？不用担心，我们也可以在 DWARF 信息中查看。

```
< 1><0x00000031>    DW_TAG_typedef
                      DW_AT_name                  "size_t"
                      DW_AT_type                  <0x0000003c>
< 1><0x0000003c>    DW_TAG_base_type
                      DW_AT_byte_size             0x00000008
                      DW_AT_encoding              DW_ATE_unsigned
                      DW_AT_name                  "long unsigned int"

```

所以，`stack_size` 具有类型 `size_t`，即 `long unsigned int`，它是 8 字节的。这意味着我们可以查看该栈的大小。

如果我们有了 DWARF 调试数据，该如何分解：

1. 查看 `ruby_current_thread` 所指向的内存区域
2. 加上 `24` 字节来得到 `stack_size`
3. 读 8 字节（以小端的格式，因为是在 x86 上）
4. 得到答案！

在上面这个例子中是 `131072`（即 128 kb）。

对我来说，这使得调试信息的用途更加明显。如果我们不知道这些所有变量所表示的额外的元数据，那么我们无法知道存储在 `0x5598ab325b0` 这一地址的字节是什么。

这就是为什么你可以为你的程序单独安装程序的调试信息，因为 `gdb` 并不关心从何处获取这些额外的调试信息。

### DWARF 令人迷惑

我最近阅读了大量的 DWARF 知识。现在，我使用 libdwarf，使用体验不是很好，这个 API 令人迷惑，你将以一种奇怪的方式初始化所有东西，它真的很慢（需要花费 0.3 秒的时间来读取我的 Ruby 程序的所有调试信息，这真是可笑）。有人告诉我，来自 elfutils 的 libdw 要好一些。

同样，再提及一点，你可以查看 `DW_AT_data_member_location` 来查看结构成员的偏移。我在 Stack Overflow 上查找如何完成这件事，并且得到[这个答案](https://stackoverflow.com/questions/25047329/how-to-get-struct-member-offset-from-dwarf-info)。基本上，以下面这样一个检查开始：

```
dwarf_whatform(attrs[i], &form, &error);
    if (form == DW_FORM_data1 || form == DW_FORM_data2
        form == DW_FORM_data2 || form == DW_FORM_data4
        form == DW_FORM_data8 || form == DW_FORM_udata) {

```

继续往前。为什么会有 800 万种不同的 `DW_FORM_data` 需要检查？发生了什么？我没有头绪。

不管怎么说，我的印象是，DWARF 是一个庞大而复杂的标准（可能是人们用来生成 DWARF 的库稍微不兼容），但是我们有的就是这些，所以我们只能用它来工作。

我能够编写代码并查看 DWARF ，这就很酷了，并且我的代码实际上大多数能够工作。除了程序崩溃的时候。我就是这样工作的。

### 展开栈路径

在这篇文章的早期版本中，我说过，`gdb` 使用 libunwind 来展开栈路径，这样说并不总是对的。

有一位对 `gdb` 有深入研究的人发了大量邮件告诉我，为了能够做得比 libunwind 更好，他们花费了大量时间来尝试如何展开栈路径。这意味着，如果你在程序的一个奇怪的中间位置停下来了，你所能够获取的调试信息又很少，那么你可以对栈做一些奇怪的事情，`gdb` 会尝试找出你位于何处。

### gdb 能做的其他事

我在这儿所描述的一些事请（查看内存，理解 DWARF 所展示的结构）并不是 `gdb` 能够做的全部事情。阅读 Brendan Gregg 的[昔日 gdb 例子](http://www.brendangregg.com/blog/2016-08-09/gdb-example-ncurses.html)，我们可以知道，`gdb` 也能够完成下面这些事情：

* 反汇编
* 查看寄存器内容

在操作程序方面，它可以：

* 设置断点，单步运行程序
* 修改内存（这是一个危险行为）

了解 `gdb` 如何工作使得当我使用它的时候更加自信。我过去经常感到迷惑，因为 `gdb` 有点像 C，当你输入 `ruby_current_thread->cfp->iseq`，就好像是在写 C 代码。但是你并不是在写 C 代码。我很容易遇到 `gdb` 的限制，不知道为什么。

知道使用 DWARF 来找出结构内容给了我一个更好的心智模型和更加正确的期望！这真是极好的！

---

via: <https://jvns.ca/blog/2016/08/10/how-does-gdb-work/>

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

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


如何在 Debian Linux 上设置和配置网桥

Summary: 那么我该如何在 Debian Linux 9.x 服务器上的 /etc/network/interfaces 中设置桥接网络呢？

# 如何在 Debian Linux 上设置和配置网桥

Q：我是一个新 Debian Linux 用户，我想为 Debian Linux 上运行的虚拟化环境（KVM）设置网桥。那么我该如何在 Debian Linux 9.x 服务器上的 `/etc/network/interfaces` 中设置桥接网络呢？

如何你想为你的虚拟机分配 IP 地址并使其可从你的局域网访问，则需要设置网络桥接器。默认情况下，虚拟机使用 KVM 创建的专用网桥。但你需要手动设置接口，避免与网络管理员发生冲突。

### 怎样安装 brctl

输入以下 [apt-get 命令](https://www.cyberciti.biz/tips/linux-debian-package-management-cheat-sheet.html "See Linux/Unix apt-get command examples for more info")：

```
$ sudo apt install bridge-utils

```

### 怎样在 Debian Linux 上设置网桥

你需要编辑 `/etc/network/interface` 文件。不过，我建议在 `/etc/network/interface.d/` 目录下放置一个全新的配置。在 Debian Linux 配置网桥的过程如下：

#### 步骤 1 - 找出你的物理接口

使用 [ip 命令](https://www.cyberciti.biz/faq/linux-ip-command-examples-usage-syntax/ "See Linux/Unix ip command examples for more info")：

```
$ ip -f inet a s

```

示例输出如下：

```
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
 inet 192.168.2.23/24 brd 192.168.2.255 scope global eno1
 valid_lft forever preferred_lft forever

```

`eno1` 是我的物理网卡。

#### 步骤 2 - 更新 /etc/network/interface 文件

确保只有 `lo`（loopback 在 `/etc/network/interface` 中处于活动状态）。（LCTT 译注：loopback 指本地环回接口，也称为回送地址）删除与 `eno1` 相关的任何配置。这是我使用 [cat 命令](https://www.cyberciti.biz/faq/linux-unix-appleosx-bsd-cat-command-examples/ "See Linux/Unix cat command examples for more info") 打印的配置文件：

```
$ cat /etc/network/interface

```

```
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

```

#### 步骤 3 - 在 /etc/network/interfaces.d/br0 中配置网桥（br0）

使用文本编辑器创建一个文本文件，比如 `vi` 命令：

```
$ sudo vi /etc/network/interfaces.d/br0

```

在其中添加配置：

```
## static ip config file for br0 ##
auto br0
iface br0 inet static
    address 192.168.2.23
    broadcast 192.168.2.255
    netmask 255.255.255.0
    gateway 192.168.2.254
    # If the resolvconf package is installed, you should not edit
    # the resolv.conf configuration file manually. Set name server here
    #dns-nameservers 192.168.2.254
    # If you have muliple interfaces such as eth0 and eth1
    # bridge_ports eth0 eth1
    bridge_ports eno1
    bridge_stp off # disable Spanning Tree Protocol
    bridge_waitport 0 # no delay before a port becomes available
    bridge_fd 0 # no forwarding delay

```

如果你想使用 DHCP 来获得 IP 地址：

```
## DHCP ip config file for br0 ##
auto br0

# Bridge setup
 iface br0 inet dhcp
  bridge_ports eno1

```

[在 vi/vim 中保存并关闭文件](https://www.cyberciti.biz/faq/linux-unix-vim-save-and-quit-command/)。

#### 步骤 4 - 重新启动网络服务

在重新启动网络服务之前，请确保防火墙已关闭。防火墙可能会引用较老的接口，例如 `eno1`。一旦服务重新启动，你必须更新 `br0` 接口的防火墙规则。键入以下命令重新启动防火墙：

```
$ sudo systemctl restart network-manager

```

确认服务已经重新启动：

```
$ systemctl status network-manager

```

借助 [ip 命令](https://www.cyberciti.biz/faq/linux-ip-command-examples-usage-syntax/ "See Linux/Unix ip command examples for more info")寻找新的 `br0` 接口和路由表：

```
$ ip a s $ ip r $ ping -c 2 cyberciti.biz

```

示例输出：

你可以使用 brctl 命令查看网桥有关信息：

```
$ brctl show

```

显示当前网桥：

```
$ bridge link

```

### 关于作者

作者是 nixCraft 的创建者，也是经验丰富的系统管理员，DevOps 工程师以及 Linux 操作系统/ Unix shell 脚本的培训师。通过订阅 [RSS/XML 流](https://www.cyberciti.biz/atom/atom.xml) 或者 [每周邮件推送](https://www.cyberciti.biz/subscribe-to-weekly-linux-unix-newsletter-for-sysadmin/)获得关于 SysAdmin, Linux/Unix 和开源主题的最新教程。

---

via: <https://www.cyberciti.biz/faq/how-to-configuring-bridging-in-debian-linux/>

作者：[Vivek GIte](https://www.cyberciti.biz/) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


快捷教程：如何在命令行上编辑文件

# 快捷教程：如何在命令行上编辑文件

此次教程中，我们将向您展示三种命令行编辑文件的方式。本文一共覆盖了三种命令行编辑器，vi（或 vim）、nano 和 emacs。

### 在命令行上使用 Vi 或 Vim 编辑文件

您可以使用 `vi` 编辑文件。运行如下命令，打开文件：

```
vi /path/to/file

```

现在，您可以看见文件中的内容了（如果文件存在。请注意，如果此文件不存在，该命令会创建文件）。

`vi` 最重要的命令莫过于此：

键入 `i` 进入<ruby> 编辑 <rt>  Insert </rt></ruby>模式。如此，您可以编辑文本。

退出编辑模式请键入 `ESC`。

正处于光标之下的字符，使用 `x` 键删除（您千万不要在编辑模式这样做，如果您这样做了，将不会删除光标下的字符，而是会在光标下插入 `x` 字符）。因此，当您仅仅使用 `vi` 打开文本（LCTT 译注：此时默认进入指令模式），此时您可以使用 `x` 键立即删除字符。在编辑模式下，您需要键入 `ESC` 退出编辑模式。

如果您做了修改，想要保存文件，请键入 `:x`（同样，您不能在编辑模式执行此操作。请按 `ESC` 退出编辑模式，完成此操作）。

如果您并没有做修改，键入 `:q` 退出文本（您同样不能在编辑模式执行此操作）。

如果您做了修改，但却想不保存文本而之际退出，请键入 `:q!` （同样不能在编辑模式执行此作）。

请注意在上述所有操作中，您都可以使用方向键操控光标在文本中的位置。

以上所有都是 `vi` 编辑器的内容。请注意，`vim` 编辑器或多或少也会支持这些操作，如果您想深层次了解 `vim`，请看 [这里](https://www.howtoforge.com/vim-basics)。

### 使用 Nano 命令行编辑器编辑文件

接下来是 Nano 编辑器。您可以执行 `nano` 命令调用它：

```
nano

```

这里是 `nano` 的用户界面：

您同样可以使用它启动文件。

```
nano [filename]

```

例如：

```
nano test.txt

```

如您所见的用户界面，大致被分成四个部分。编辑器顶部显示编辑器版本、正在编辑的文件和编辑状态。然后是实际编辑区域，在这里，您能看见文件的内容。编辑器下方高亮区展示着重要的信息，最后两行显示能执行基础任务地快捷键，切实地帮助初学者。

这里是您前期应当了解的快捷键快表。

使用方向键浏览文本，退格键删除文本，`Ctrl+O` 保存文件修改。当您尝试保存时，`nano` 会征询您的确认（请参阅截图中主编辑器下方区域）：

注意，在这个阶段，您有一个选项，可以保存不同的系统格式。键入 `Alt+D` 选择 DOS 格式，`Atl+M` 选择 Mac 格式。

敲回车保存更改。

继续，文本剪切使用 `Ctrl+K`，文本复制使用 `Ctrl+U`。这些快捷键同样可以用来粘贴剪切单个单词，但您需要先选择好单词，通常，您可以通过键入 `Alt+A`（光标在第一个单词下） 然后使用方向键选择完整的单词。

现在来进行搜索操作。使用 `Ctrl+W` 可以执行一个简单的搜索，同时搜索和替换您可以使用 `Ctrl+\\`。

这些就是 `nano` 的一些基础功，它能给您带来一些不错的开始，如果您是初次使用 `nano` 编辑器。更多内容，请阅读我们的完整内容，点击 [这里](https://www.howtoforge.com/linux-nano-command/)。

### 使用 Emacs 命令行编辑器编辑文件

接下来登场的是 Emacs。如果系统未安装此软件，您可以使用下面的命令在您的系统中安装它：

```
sudo apt-get install emacs

```

和 `nano` 一致，您可以使用下面的方式在 `emacs` 中直接打开文件：

```
emacs -nw [filename]

```

注意：`-nw` 选项确保 `emacs` 在本窗口启动，而不是打开一个新窗口，默认情况下，它会打开一个新窗口。

一个实例：

```
emacs -nw test.txt

```

下面是编辑器的用户界面：

和 `nano` 一样，`emacs` 的界面同样被分割成了几个部分。第一部分是最上方的菜单区域，和您在图形界面下的应用程序一致。接下来是显示文本（您打开的文件文本）内容的主编辑区域。

编辑区域下方坐落着另一个高亮菜单条，显示了文件名，编辑模式（如截图内的 ‘Text’）和状态（`**` 为已修改，`-` 为未修改，`%%` 为只读）。最后是提供输入指令的区域，同时也能查看输出。

现在开始基础操作，当您做了修改、想要保存时，在 `Ctrl+x` 之后键入 `Ctrl+s`。最后，在面板最后一行会向您显示一些信息：‘Wrote ........’。这里有一个例子：

现在，如果您放弃修改并且退出时，在 `Ctrl+x` 之后键入`Ctrl+c`。编辑器将会立即询问，如下图：

输入 `n` 之后键入 `yes`，之后编辑器将会不保存而直接退出。

请注意，Emacs 中 `C` 代表 `Ctrl`，`M` 代表 `Alt`。比如，当你看见 `C-x`，这意味着按下 `Ctrl+x`。

至于其他基本编辑器操作，以删除为例，大多数人都会，使用 `Backspace`/`Delete` 键。然而，这里的一些删除快捷键能够提高用户体验。比如，使用 `Ctrl+k` 删除一整行，`Alt+d` 删除一个单词，`Alt+k` 删除一个整句。

在键入 `Ctrl+k` 之后键入 `u` 将撤销操作，输入 `Ctrl+g` 之后输入 `Ctrl+_` 恢复撤销的操作。使用 `Ctrl+s` 向前搜索，`Ctrl+r` 反向搜索。

继续，使用 `Alt+Shift+%` 执行替换操作。您将被询问要替换单词。回复并回车。之后编辑器将会询问您是否替换。例如，下方截图展示了 `emacs` 询问使用者关于单词 ‘This’ 的替换操作。

输入替换文本并回车。每一个替换操作 `emacs` 都会等待询问，下面是首次询问：

键入 `y` 之后，单词将会被替换。

这些就是几乎所有的基础操作，您在开始使用 `emacs` 时需要了解掌握的。对了，我们忘记讨论如何访问顶部菜单，其实这些可以通过使用 `F10` 访问它们。

按 `Esc` 键三次，退出这些菜单。

---

via: <https://www.howtoforge.com/faq/how-to-edit-files-on-the-command-line>

作者：[Falko Timme, Himanshu Arora](https://www.howtoforge.com) 译者：[CYLeft](https://github.com/CYLeft) 校对：[wxy](https://github.com/wxy)

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


发现 GPL 违规怎么办？多种法律救济可用

Summary: 最近一系列的法律案件为解决 GPL 违规问题提供了一些启示。

最近一系列的法律案件为解决 GPL 违规问题提供了一些启示。

# 发现 GPL 违规怎么办？多种法律救济可用

>
> 提要：最近一系列的法律案件为解决 GPL 违规问题提供了一些启示。
>
>
>

2017 年 4 月份，位于加州的一家美国联邦法院在 [Artifex Software, Inc. 诉 Hancom, Inc. 案](/article-8522-1.html)（2017 WL 1477373）中做出了一项[裁决](https://www.fsf.org/blogs/licensing/update-on-artifex-v-hancom-gnu-gpl-compliance-case-1)，为针对 GPL 违规的救济方式提供了新的视角。令人遗憾的是，这起案件由于对法院裁定 GPL 是合同的一些错误解释而重新引发了已持续数十年之久的 GPL 究竟是许可还是合同的[辩论](/article-8971-1.html)。在研究救济措施的新进展之前，值得我们去重新审视为什么这种争辩依然存在。

当您考虑针对 GPL 违规的救济措施时，您可能会想到针对版权侵权主张权利，这种法律原则似乎适用于强制执行 GPL，因为版权侵权最有力的救济措施之一就是<ruby> 禁令救济 <rp>  （ </rp> <rt>  injunctive relief </rt> <rp>  ） </rp></ruby>。对于 GPL 违规，这通常意味着防止侵权者分发违规软件。版权法还规定了实际和法定损害赔偿。相反，合同违约的救济措施相当有限，尽管也存在其他形式的救济，但通常只用于使一方完全避免造成损失。正如 Hancom 公司在其简易判决动议（虽然[被法院驳回](/article-8971-1.html)）中所指出的，对于 GPL 软件来说，可能很难进行损失计算。

关于为什么 GPL 应该被视为许可而不是合同，已经有很多想法提出。例如，自由软件基金会（FSF）[一直认为](https://www.gnu.org/philosophy/enforcing-gpl.en.html) [GPL 不是合同](https://www.gnu.org/philosophy/enforcing-gpl.en.html)。合同和开源许可证之间的这种区别可以在协议的性质中找到：合同是契约或承诺的交换，而开源许可证则给出了使用许可证的条件。在 Jacobsen 诉 Katzer 案（535 F.3d 1373）中，法院支持这种看法，认为<ruby> 艺术许可协议 <rp>  （ </rp> <rt>  Artistic License </rt> <rp>  ） </rp></ruby>列举了条件而非契约。有鉴于此，违反许可证将导致强有力救济措施的观点让许可/合同争辩陷入平息。

我们再来看 Artifex，该公司针对许可违规（根据上述分析）以及合同违约均提出了权利主张。有很多文章讨论了法院对 GPL 构成合同的分析，其中也包括 FSF [发表的文章](https://www.fsf.org/blogs/licensing/motion-to-dismiss-denied-in-recent-gnu-gpl-case)，所以本文不会详细讨论这个看法。总结其分析结果，法院认为创建合同的要素（要约、接受和对价）得到了充分的陈述，其中大部分聚焦在对 GPL 的接受上（如果 GPL 被视为合同）。法院试图寻找 GPL 之外的接受证据，在 Hancom 制作的 Ghostscript 在线描述资料以及该产品的双重许可性质中已经找到。因此，法院认定可能存在合同。

在这里，我们关注的是法院合同分析之外的两个问题。首先，注意上面使用的“可能”这个词的重要性。Artifex 的判令来自于一个驳回动议，只评估 Artifex 主张的合理性而非优劣。法院对此事没有进一步的法律分析。所以如果这一点已经被提起诉讼，它可能会或可能没有找到合法的合同。既然这一点在第二个动议中已经得到了承认，并且[各方私下达成了和解](https://www.artifex.com/news/artifex-and-hancom-reach-settlement-over-ghostscript-open-source-dispute/)，所以我们不知道这个争议会如何结束。

其次，尽管可能的合同权利主要很重要，但还有更有趣的第二个问题。在 Artifex 案之前，版权和合同的讨论也被搁置，其中一部分原因是由于<ruby> 优先适用 <rp>  （ </rp> <rt>  preemption </rt> <rp>  ） </rp></ruby>问题。当美国国会颁布<ruby> 版权法 <rp>  （ </rp> <rt>  Copyright Act </rt> <rp>  ） </rp></ruby>时，它取代了任何与其不一致的州法的权利主张，例如有的州法对等同权提供版权保护。如果州法的权利主张（例如违约）涉及与“（联邦）版权法本质上不同的权利”（引自 Artifex），则可以避免优先适用的问题。在确定是否存在优先适用问题时，法院会询问州法的权利主张是否有超出联邦版权法的“额外要素”。

在争论一个“额外要素”来证实其合同违约的权利主张时，Artifex 引用了 [Versata Software, Inc. 诉 Ameriprise Fin., Inc. 案](https://opensource.com/law/14/12/gplv2-court-decisions-versata)（2014 WL 950065）中版权法自身没有强加任何开源义务的主张。因此，任何“额外要素”（例如开源责任）都不在联邦版权法的范围之内，从而使得违反了州法中的合同权利主张变得可能。因此，Artifex 提出了这一概念以及与域外侵权有关的另一个概念（不在本文讨论范围），法院认定合同违约权利主张可以继续进行，同时允许进行合同法和版权法意义下的可能的救济，且不能对其中任意一个权利主张构成减损。

这一案件的最终效应仍有待观察，但结果是为针对 GPL 违规行为通过版权侵权和合同违约来实施多种救济措施铺平了道路。

---

作者简介：Chris Gillespie 就职于红帽公司（Redhat）。

译者简介：薛亮，集慧智佳知识产权咨询公司高级咨询师，擅长专利检索、专利分析、竞争对手跟踪、FTO 分析、开源软件知识产权风险分析，致力于为互联网企业、高科技公司提供知识产权咨询服务。


如何在 Linux 中查找最大的 10 个文件

Summary: 当系统的磁盘空间不足时，您可能会使用 df、du 或 ncdu 命令进行检查，但这些命令只会显示当前目录的文件，并不会显示整个系统范围的文件。

注意！！！ 千万不要在生产环境 find / 这么搜索，这会搜索磁盘的所有文件，且耗时很长，对负载较高的服务器执行也会有隐患。 正常的需求我们不会找整个服务器占用最大的文件，而是找某个项目下或者挂载点下占用磁盘最高的文件。

四串指令都是权限不够。。。

是 root 用户吗？

赞

# 如何在 Linux 中查找最大的 10 个文件

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

当系统的磁盘空间不足时，您可能会使用 `df`、`du` 或 `ncdu` 命令进行检查，但这些命令只会显示当前目录的文件，并不会显示整个系统范围的文件。

您得花费大量的时间才能用上述命令获取系统中最大的文件，因为要进入到每个目录重复运行上述命令。

这种方法比较麻烦，也并不恰当。

如果是这样，那么该如何在 Linux 中找到最大的 10 个文件呢？

我在谷歌上搜索了很久，却没发现类似的文章，我反而看到了很多关于列出当前目录中最大的 10 个文件的文章。所以，我希望这篇文章对那些有类似需求的人有所帮助。

本教程中，我们将教您如何使用以下四种方法在 Linux 系统中查找最大的前 10 个文件。

### 方法 1

在 Linux 中没有特定的命令可以直接执行此操作，因此我们需要将多个命令结合使用。

```
# find / -type f -print0 | xargs -0 du -h | sort -rh | head -n 10

1.4G    /swapfile
1.1G    /home/magi/ubuntu-17.04-desktop-amd64.iso
564M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqTFU0XzkzUlJUZzA
378M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqeldzUmhPeC03Zm8
377M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqRGd4V0VrOXM4YVU
100M    /usr/lib/x86_64-linux-gnu/libOxideQtCore.so.0
93M /usr/lib/firefox/libxul.so
84M /var/lib/snapd/snaps/core_3604.snap
84M /var/lib/snapd/snaps/core_3440.snap
84M /var/lib/snapd/snaps/core_3247.snap

```

详解：

* `find`：在目录结构中搜索文件的命令
* `/`：在整个系统（从根目录开始）中查找
* `-type`：指定文件类型
	+ `f`：普通文件
* `-print0`：在标准输出显示完整的文件名，其后跟一个空字符（null）
* `|`：控制操作符，将一条命令的输出传递给下一个命令以供进一步处理
* `xargs`：将标准输入转换成命令行参数的命令
* `-0`：以空字符（null）而不是空白字符（LCTT 译者注：即空格、制表符和换行）来分割记录
* `du -h`：以可读格式计算磁盘空间使用情况的命令
* `sort`：对文本文件进行排序的命令
* `-r`：反转结果
* `-h`：用可读格式打印输出
* `head`：输出文件开头部分的命令
* `n -10`：打印前 10 个文件

### 方法 2

这是查找 Linux 系统中最大的前 10 个文件的另一种方法。我们依然使用多个命令共同完成这个任务。

```
# find / -type f -exec du -Sh {} + | sort -rh | head -n 10

1.4G    /swapfile
1.1G    /home/magi/ubuntu-17.04-desktop-amd64.iso
564M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqTFU0XzkzUlJUZzA
378M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqeldzUmhPeC03Zm8
377M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqRGd4V0VrOXM4YVU
100M    /usr/lib/x86_64-linux-gnu/libOxideQtCore.so.0
93M /usr/lib/firefox/libxul.so
84M /var/lib/snapd/snaps/core_3604.snap
84M /var/lib/snapd/snaps/core_3440.snap
84M /var/lib/snapd/snaps/core_3247.snap

```

详解：

* `find`：在目录结构中搜索文件的命令
* `/`：在整个系统（从根目录开始）中查找
* `-type`：指定文件类型
	+ `f`：普通文件
* `-exec`：在所选文件上运行指定命令
* `du`：计算文件占用的磁盘空间的命令
* `-S`：不包含子目录的大小
* `-h`：以可读格式打印
* `{}`：递归地查找目录，统计每个文件占用的磁盘空间
* `|`：控制操作符，将一条命令的输出传递给下一个命令以供进一步处理
* `sort`：对文本文件进行按行排序的命令
* `-r`：反转结果
* `-h`：用可读格式打印输出
* `head`：输出文件开头部分的命令
* `n -10`：打印前 10 个文件

### 方法 3

这里介绍另一种在 Linux 系统中搜索最大的前 10 个文件的方法。

```
# find / -type f -print0 | xargs -0 du | sort -n | tail -10 | cut -f2 | xargs -I{} du -sh {}

84M /var/lib/snapd/snaps/core_3247.snap
84M /var/lib/snapd/snaps/core_3440.snap
84M /var/lib/snapd/snaps/core_3604.snap
93M /usr/lib/firefox/libxul.so
100M    /usr/lib/x86_64-linux-gnu/libOxideQtCore.so.0
377M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqRGd4V0VrOXM4YVU
378M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqeldzUmhPeC03Zm8
564M    /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqTFU0XzkzUlJUZzA
1.1G    /home/magi/ubuntu-17.04-desktop-amd64.iso
1.4G    /swapfile

```

详解：

* `find`：在目录结构中搜索文件的命令
* `/`：在整个系统（从根目录开始）中查找
* `-type`：指定文件类型
	+ `f`：普通文件
* `-print0`：输出完整的文件名，其后跟一个空字符（null）
* `|`：控制操作符，将一条命令的输出传递给下一个命令以供进一步处理
* `xargs`：将标准输入转换成命令行参数的命令
* `-0`：以空字符（null）而不是空白字符来分割记录
* `du`：计算文件占用的磁盘空间的命令
* `sort`：对文本文件进行按行排序的命令
* `-n`：根据数字大小进行比较
* `tail -10`：输出文件结尾部分的命令（最后 10 个文件）
* `cut`：从每行删除特定部分的命令
* `-f2`：只选择特定字段值
* `-I{}`：将初始参数中出现的每个替换字符串都替换为从标准输入读取的名称
* `-s`：仅显示每个参数的总和
* `-h`：用可读格式打印输出
* `{}`：递归地查找目录，统计每个文件占用的磁盘空间

### 方法 4

还有一种在 Linux 系统中查找最大的前 10 个文件的方法。

```
# find / -type f -ls | sort -k 7 -r -n | head -10 | column -t | awk '{print $7,$11}'

1494845440 /swapfile
1085984380 /home/magi/ubuntu-17.04-desktop-amd64.iso
591003648 /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqTFU0XzkzUlJUZzA
395770383 /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqeldzUmhPeC03Zm8
394891761 /home/magi/.gdfuse/magi/cache/0B5nso_FPaZFqRGd4V0VrOXM4YVU
103999072 /usr/lib/x86_64-linux-gnu/libOxideQtCore.so.0
97356256 /usr/lib/firefox/libxul.so
87896064 /var/lib/snapd/snaps/core_3604.snap
87793664 /var/lib/snapd/snaps/core_3440.snap
87089152 /var/lib/snapd/snaps/core_3247.snap

```

详解：

* `find`：在目录结构中搜索文件的命令
* `/`：在整个系统（从根目录开始）中查找
* `-type`：指定文件类型
	+ `f`：普通文件
* `-ls`：在标准输出中以 `ls -dils` 的格式列出当前文件
* `|`：控制操作符，将一条命令的输出传递给下一个命令以供进一步处理
* `sort`：对文本文件进行按行排序的命令
* `-k`：按指定列进行排序
* `-r`：反转结果
* `-n`：根据数字大小进行比较
* `head`：输出文件开头部分的命令
* `-10`：打印前 10 个文件
* `column`：将其输入格式化为多列的命令
* `-t`：确定输入包含的列数并创建一个表
* `awk`：模式扫描和处理语言
* `'{print $7,$11}'`：只打印指定的列

---

via: <https://www.2daygeek.com/how-to-find-search-check-print-top-10-largest-biggest-files-in-linux/>

作者：[Magesh Maruthamuthu](https://www.2daygeek.com/author/magesh/) 译者：[jessie-pang](https://github.com/jessie-pang) 校对：[wxy](https://github.com/wxy)

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


我是如何创造“开源”这个词的

Summary: Christine Peterson 最终公开讲述了二十年前那决定命运的一天。

Christine Peterson 最终公开讲述了二十年前那决定命运的一天。

# 我是如何创造“开源”这个词的

>
> Christine Peterson 最终公开讲述了二十年前那决定命运的一天。
>
>
>

2 月 3 日是术语“<ruby>   开源软件  <rt>  open source software </rt></ruby>”创立 20 周年的纪念日。由于开源软件渐受欢迎，并且为这个时代强有力的重要变革提供了动力，我们仔细反思了它的初生到崛起。

我是 “开源软件” 这个词的始作俑者，它是我在<ruby> 前瞻协会 <rt>  Foresight Institute </rt></ruby>担任执行董事时提出的。我不像其它人是个软件开发者，所以感谢 Linux 程序员 Todd Anderson 对这个术语的支持并将它提交小组讨论。

这是我对于它如何想到的，如何提出的，以及后续影响的记叙。当然，还有一些有关该术语的其它记叙，例如 Eric Raymond 和 Richard Stallman 写的，而我的，则写于 2006 年 1 月 2 日。

但直到今天，我才公诸于世。

---

推行术语“开源软件”是特别为了让新手和商业人士更加理解这个领域，对它的推广被认为对于更广泛的用户社区很有必要。早期的称呼“<ruby> 自由软件 <rt>  free software </rt></ruby>”不适用并非是因为含有政治意义，而是对于新手来说会误导关注于价格。所以需要一个关注于关键的源代码，而且不会让新用户混淆概念的术语。第一个在正确时间出现并且满足这些要求的术语被迅速接受了：<ruby> 开源 <rt>  open source </rt></ruby>。

这个术语很长一段时间被用在“情报”（即间谍活动）活动中，但据我所知，确实在 1998 年以前软件领域从未使用过该术语。下面这个就是讲述了术语“开源软件”如何流行起来，并且变成了一项产业和一场运动名称的故事。

### 计算机安全会议

在 1997 年的晚些时候，<ruby> 前瞻协会 <rt>  Foresight Institute </rt></ruby>开始举办周会讨论计算机安全问题。这个协会是一个非盈利性智库，它专注于纳米技术和人工智能，而二者的安全性及可靠性取决于软件安全。我们确定了自由软件是一个改进软件安全可靠性且具有发展前景的方法，并将寻找推动它的方式。 对自由软件的兴趣开始在编程社区外开始增长，而且越来越清晰，一个改变世界的机会正在来临。然而，该怎么做我们并不清楚，因为我们当时正在摸索中。

在这些会议中，由于“容易混淆”的因素，我们讨论了采用一个新术语的必要性。观点主要如下：对于那些新接触“自由软件”的人会把 “free” 当成了价格上的 “免费” 。老资格的成员们开始解释，通常像下面所说的：“我们指的是 ‘freedom’ 中的自由，而不是‘免费啤酒’的免费。”在这一点上，关于软件方面的讨论就会变成了关于酒精饮料价格的讨论。问题不在于解释不了它的含义 —— 问题在于重要概念的术语不应该使新手们感到困惑。所以需要一个更清晰的术语。自由软件一词并没有政治上的问题；问题在于这个术语不能对新人清晰表明其概念。

### 开放的网景

1998 年 2 月 2 日，Eric Raymond 访问网景公司，并与它一起计划采用自由软件风格的许可证发布其浏览器的源代码。我们那晚在前瞻协会位于<ruby> 罗斯阿尔托斯 <rt>  Los Altos </rt></ruby>的办公室开会，商讨并完善了我们的计划。除了 Eric 和我，积极参与者还有 Brian Behlendorf、Michael Tiemann、Todd Anderson、Mark S. Miller 和 Ka-Ping Yee。但在那次会议上，这一领域仍然被描述成“自由软件”，或者用 Brian 的话说， 叫“可获得源代码的” 软件。

在这个镇上，Eric 把前瞻协会作为行动的大本营。他访问行程期间，他接到了网景的法律和市场部门人员的电话。当他聊完后，我要求和他们（一男一女，可能是 Mitchell Baker）通电话，以便我告诉他们一个新的术语的必要性。他们原则上立即同意了，但我们在具体术语上并未达成一致。

在那周的会议中，我始终专注于起一个更好的名字并提出了 “开源软件”一词。 虽然不太理想，但我觉得足够好了。我找到至少四个人征求意见：Eric Drexler、Mark Miller 以及 Todd Anderson 都喜欢它，而一个从事市场公关的朋友觉得术语 “open” 被滥用了，并且觉得我们能找到一个更好。理论上他是对的，可我想不出更好的了，所以我想试着先推广它。事后想起来，我应该直接向 Eric Raymond 提议，但在那时我并不是很了解他，所以我采取了间接的策略。

Todd 强烈同意需要一个新的术语，并提供协助推广它。这很有帮助，因为作为一个非编程人员，我在自由软件社区的影响力很弱。我从事的纳米技术教育是一个加分项，但不足以让我在自由软件问题上非常得到重视。而作为一个 Linux 程序员，Todd 的话更容易被倾听。

### 关键性会议

那周稍晚时候，1998 年的 2 月 5 日，一伙人在 VA Research 进行头脑风暴商量对策。与会者除了 Eric Raymond、Todd 和我之外，还有 Larry Augustin、Sam Ockman，和 Jon Hall （“maddog”）通过电话参与。

会议的主要议题是推广策略，特别是要联系的公司。 我几乎没说什么，但是一直在寻找机会介绍提议的术语。我觉得我直接说“你们这些技术人员应当开始使用我的新术语了。”没有什么用。大多数与会者不认识我，而且据我所知，他们可能甚至不同意现在就迫切需要一个新术语。

幸运的是，Todd 一直留心着。他没有主张社区应该用哪个特定的术语，而是面对社区这些固执的人间接地做了一些事。他仅仅是在其它话题中使用了那个术语 —— 把它放进对话里看看会发生什么。我很紧张，期待得到回应，但是起初什么也没有。讨论继续进行原来的话题。似乎只有他和我注意了这个术语的使用。

不仅如此——模因演化（LCTT 译注：人类学术语）在起作用。几分钟后，另一个人使用了这个术语，显然没有注意到，而在继续进行话题讨论。Todd 和我用眼角互觑了一下：是的，我们都注意到发生了什么。我很激动——它或许有用！但我保持了安静：我在小组中仍然地位不高。可能有些人都奇怪为什么 Eric 会邀请我。

临近会议尾声，可能是 Todd 或 Eric，明确提出了[术语问题](https://wiki2.org/en/Alternative_terms_for_free_software)。Maddog 提及了一个早期的术语“可自由分发的”，和一个新的术语“合作开发的”。Eric 列出了“自由软件”、“开源软件”和“软件源”作为主要选项。Todd 提议使用“开源”，然后 Eric 支持了他。我没说太多，就让 Todd 和 Eric（轻松、非正式地）就“开源”这个名字达成了共识。显然对于大多数与会者，改名并不是在这讨论的最重要议题；那只是一个次要的相关议题。从我的会议记录中看只有大约 10% 的内容是术语的。

但是我很高兴。在那有许多社区的关键领导人，并且他们喜欢这新名字，或者至少没反对。这是一个好的信号。可能我帮不上什么忙； Eric Raymond 更适合宣传新的名称，而且他也这么做了。Bruce Perens 立即表示支持，帮助建立了 [Opensource.org](https://opensource.org/) 并在新术语的宣传中发挥了重要作用。

为了让这个名字获得认同，Tim O'Reilly 同意在代表社区的多个项目中积极使用它，这是很必要，甚至是非常值得的。并且在官方即将发布的 Netscape Navigator（网景浏览器）代码中也使用了此术语。 到二月底， O'Reilly & Associates 还有网景公司（Netscape） 已经开始使用新术语。

### 名字的宣传

在那之后的一段时间，这条术语由 Eric Raymond 向媒体推广，由 Tim O'Reilly 向商业推广，并由二人向编程社区推广，它似乎传播的相当快。

1998 年 4 月 17 日，Tim O'Reilly 召集了该领域的一些重要领袖的峰会，宣布为第一次 “[自由软件峰会](http://www.oreilly.com/pub/pr/636)” ，在 4 月14 日之后，它又被称作首届 “[开源峰会](http://www.oreilly.com/pub/pr/796)”。

这几个月对于开源来说是相当激动人心的。似乎每周都有一个新公司宣布加入计划。读 Slashdot（LCTT 译注：科技资讯网站）已经成了一个必需操作，甚至对于那些像我一样只能外围地参与者亦是如此。我坚信新术语能对快速传播到商业很有帮助，能被公众广泛使用。

尽管在谷歌搜索一下表明“开源”比“自由软件”出现的更多，但后者仍然有大量的使用，在和偏爱它的人们沟通的时候我们应该包容。

### 快乐的感觉

当 Eric Raymond 写的有关术语更改的[早期声明](https://ipfs.io/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Alternative_terms_for_free_software.html)被发布在了<ruby> 开源促进会 <rt>  Open Source Initiative </rt></ruby>的网站上时，我被列在 VA 头脑风暴会议的名单上，但并不是作为术语的创始人。这是我自己的失误，我没告诉 Eric 细节。我的想法就是让它过去吧，我呆在幕后就好，但是 Todd 不这样认为。他认为我总有一天会为被称作“开源软件”这个名词的创造者而高兴。他向 Eric 解释了这个情况，Eric 及时更新了网站。

想出这个短语只是一个小贡献，但是我很感激那些把它归功于我的人。每次我听到它（现在经常听到了），它都给我些许的感动。

说服社区的巨大功劳要归功于 Eric Raymond 和 Tim O'Reilly，是他们让这一切成为可能。感谢他们对我的归功，并感谢 Todd Anderson 所做的一切。以上内容并非完整的开源一词的历史，让我对很多没有提及的关键人士表示歉意。那些寻求更完整讲述的人应该参考本文和网上其他地方的链接。

### 关于作者

Christine Peterson 撰写、举办讲座，并向媒体介绍未来强大的技术，特别是在纳米技术，人工智能和长寿方面。她是纳米科技公益组织前瞻协会的共同创始人和前任主席。前瞻协会向公众、技术团体和政策制定者提供未来强大的技术的教育以及告诉它是如何引导他们的长期影响。她服务于[机器智能](http://intelligence.org/)咨询委员会……[更多关于 Christine Peterson](https://opensource.com/users/christine-peterson)

---

via: <https://opensource.com/article/18/2/coining-term-open-source-software>

作者：[Christine Peterson](https://opensource.com/users/christine-peterson) 译者：[fuzheng1998](https://github.com/fuzheng1998) 校对：[wxy](https://github.com/wxy)

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


命令行乐趣：嘲讽输错 Bash 命令的用户

Summary: 你可以通过配置 sudo 命令去嘲讽输入错误密码的用户。但是现在，当用户在 shell 输错命令时，就能嘲讽他了（滥用？）。

# 命令行乐趣：嘲讽输错 Bash 命令的用户

你可以通过配置 `sudo` 命令去嘲讽输入错误密码的用户。但是现在，当用户在 shell 输错命令时，就能嘲讽他了（滥用？）。

### 你好 bash-insulter

来自 Github 页面：

>
> 当用户键入错误命令，随机嘲讽。它使用了一个 bash4.x. 版本的全新内置错误处理函数，叫 `command_not_found_handle`。
>
>
>

### 安装

键入下列 git 命令克隆一个仓库：

```
git clone https://github.com/hkbakke/bash-insulter.git bash-insulter

```

示例输出：

```
Cloning into 'bash-insulter'...
remote: Counting objects: 52, done.
remote: Compressing objects: 100% (49/49), done.
remote: Total 52 (delta 12), reused 12 (delta 2), pack-reused 0
Unpacking objects: 100% (52/52), done.

```

用文本编辑器，比如说使用 `vi`，编辑你的 `~/.bashrc` 或者 `/etc/bash.bashrc` 文件：

```
$ vi ~/.bashrc

```

在其后追加这一行（具体了解请查看 [if..else..fi 声明](https://bash.cyberciti.biz/guide/If..else..fi) 和 [source 命令](https://bash.cyberciti.biz/guide/Source_command)）：

```
if [ -f $HOME/bash-insulter/src/bash.command-not-found ]; then
    source $HOME/bash-insulter/src/bash.command-not-found
fi

```

保存并关闭文件。重新登录，如果不想退出账号也可以手动运行它：

```
$ . $HOME/bash-insulter/src/bash.command-not-found

```

### 如何使用它？

尝试键入一些无效命令：

```
$ ifconfigs
$ dates

```

示例输出:

[](https://www.cyberciti.biz/media/new/cms/2017/11/bash-insulter-Insults-the-user-when-typing-wrong-command.jpg)

### 自定义

你需要编辑 `$HOME/bash-insulter/src/bash.command-not-found`：

```
$ vi $HOME/bash-insulter/src/bash.command-not-found

```

示例代码：

```
command_not_found_handle () {
    local INSULTS=(
        "Boooo!"
        "Don't you know anything?"
        "RTFM!"
        "Hahaha, n00b!"
        "Wow! That was impressively wrong!"
        "What are you doing??"
        "Pathetic"
        "...and this is the best you can do??"
        "The worst one today!"
        "n00b alert!"
        "Your application for reduced salary has been sent!"
        "lol"
        "u suk"
        "lol... plz"
        "plz uninstall"
        "And the Darwin Award goes to.... ${USER}!"
        "ERROR_INCOMPETENT_USER"
        "Incompetence is also competence"
        "Bad."
        "Fake it till you make it!"
        "What is this...? Amateur hour!?"
        "Come on! You can do it!"
        "Nice try."
        "What if... you type an actual command the next time!"
        "What if I told you... it is possible to type valid commands."
        "Y u no speak computer???"
        "This is not Windows"
        "Perhaps you should leave the command line alone..."
        "Please step away from the keyboard!"
        "error code: 1D10T"
        "ACHTUNG! ALLES TURISTEN UND NONTEKNISCHEN LOOKENPEEPERS! DAS KOMPUTERMASCHINE IST NICHT FÜR DER GEFINGERPOKEN UND MITTENGRABEN! ODERWISE IST EASY TO SCHNAPPEN DER SPRINGENWERK, BLOWENFUSEN UND POPPENCORKEN MIT SPITZENSPARKEN. IST NICHT FÜR GEWERKEN BEI DUMMKOPFEN. DER RUBBERNECKEN SIGHTSEEREN KEEPEN DAS COTTONPICKEN HÄNDER IN DAS POCKETS MUSS. ZO RELAXEN UND WATSCHEN DER BLINKENLICHTEN."
        "Pro tip: type a valid command!"
    )

    # 设置“随机”种子发生器
    RANDOM=$(date +%s%N)
    VALUE=$((${RANDOM}%2))

    if [[ ${VALUE} -lt 1 ]]; then
        printf "\n  $(tput bold)$(tput setaf 1)$(shuf -n 1 -e "${INSULTS[@]}")$(tput sgr0)\n\n"
    fi

    echo "-bash: $1: command not found"

    # 无效命令，常规返回已存在的代码
    return 127
}

```

### 赠品：sudo 嘲讽

编辑 `sudoers` 文件：

```
$ sudo visudo

```

追加下面这一行：

```
Defaults insults

```

或者像下面尾行增加一句嘲讽语：

```
Defaults !lecture,tty_tickets,!fqdn,insults

```

这是我的文件：

```
Defaults    env_reset
Defaults    mail_badpass
Defaults    secure_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
## If set, sudo will insult users when they enter an incorrect password. ##
Defaults    insults

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root ALL = (ALL:ALL) ALL

# Members of the admin group may gain root privileges
% admin ALL = (ALL) ALL

# Allow members of group sudo to execute any command
% sudo ALL = (ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

```

试一试：

```
$ sudo -k # 清除缓存，从头开始
$ sudo ls /root/
$ sudo -i

```

样例对话：

[](https://www.cyberciti.biz/media/new/cms/2017/11/sudo-insults.jpg)

### 赠品：你好 sl

[sl 或是 UNIX 经典捣蛋软件](https://www.cyberciti.biz/tips/displays-animations-when-accidentally-you-type-sl-instead-of-ls.html) 游戏。当你错误的把 `ls` 输入成 `sl`，将会有一辆蒸汽机车穿过你的屏幕。

```
$ sl

```

[](https://www.cyberciti.biz/tips/displays-animations-when-accidentally-you-type-sl-instead-of-ls.html)

---

via: <https://www.cyberciti.biz/howto/insult-linux-unix-bash-user-when-typing-wrong-command/>

作者：[Vivek Gite](https://www.cyberciti.biz) 译者：[CYLeft](https://github.com/CYLeft) 校对：[wxy](https://github.com/wxy)

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


你没听过的 10 个免费的 Linux 生产力应用程序

# 你没听过的 10 个免费的 Linux 生产力应用程序

高效率的应用程序确实可以让你工作变得更轻松。如果你是一位 Linux 用户，这 10 个不太知名的 Linux 桌面应用程序可以帮助到你。事实上，Linux 用户可能已经听说过这个列表上的所有应用，但对于那些只用过主流应用的人来说，应该是不知道这些应用的。

### 1. Tomboy/Gnote

[Tomboy](https://wiki.gnome.org/Apps/Tomboy) 是一个简单的便签应用。它不仅仅适用于 Linux，你也可以在 Unix、Windows 和 macOS 上获得它。Tomboy 很容易使用——你写一个便条，选择是否让它粘贴在你的桌面上，当你完成它时删除它。

### 2. MyNotex

如果你想要一个更多功能的便签，但是仍喜欢一个小而简单的应用程序，而不是一个巨大的套件，请看看 [MyNotex](https://sites.google.com/site/mynotex/)。除了简单的笔记和检索之外，它还带有一些不错的功能，例如格式化、键盘快捷键和附件等等。你也可以将其用作图片管理器。

### 3. Trojitá

尽管你可以没有桌面电子邮件客户端，但如果你想要一个的话，在几十个的桌面电子邮件客户端里，请尝试下 [Trojita](http://trojita.flaska.net/)。这有利于生产力，因为它是一个快速而轻量级的电子邮件客户端，但它提供了一个好的电子邮件客户端所必须具备的所有功能（以及更多）。

### 4. Kontact

个人信息管理器（PIM）是一款出色的生产力工具。我的个人喜好是 [Kontact](https://userbase.kde.org/Kontact)。尽管它已经有几年没有更新，但它仍然是一个非常有用的 PIM 工具，用于管理电子邮件、地址簿、日历、任务、新闻源等。Kontact 是一个 KDE 原生程序，但你也可以在其他桌面上使用它。

### 5. Osmo

[Osmo](http://clayo.org/osmo/) 是一款更先进的应用，包括日历、任务、联系人和便签功能。它还附带一些额外的功能，比如加密私有数据备份和地图上的地理位置，以及对便签、任务、联系人等的强大搜索功能。

### 6. Catfish

没有好的搜索工具就没有高生产力。[Catfish](http://www.twotoasts.de/index.php/catfish/) 是一个必须尝试的搜索工具。它是一个 GTK+ 工具，非常快速，轻量级。Catfish 会利用 Zeitgeist 的自动完成功能，你还可以按日期和类型过滤搜索结果。

### 7. KOrganizer

[KOrganizer](https://userbase.kde.org/KOrganizer) 是我上面提到的 Kontact 应用程序的日历和计划组件。如果你不需要完整的 PIM 应用程序，只需要日历和日程安排，则可以使用 KOrganizer。KOrganizer 提供快速的待办事项和快速事件条目，以及事件和待办事项的附件。

### 8. Evolution

如果你不是 KDE 应用程序的粉丝，但你仍然需要一个好的 PIM，那么试试 GNOME 的 [Evolution](https://help.gnome.org/users/evolution/3.22/intro-main-window.html.en)。Evolution 并不是一个你从没听过的少见的应用程序，但因为它有用，所以它出现在这个列表中。也许你已经听说过 Evolution 是一个电子邮件客户端，但它远不止于此——你可以用它来管理日历、邮件、地址簿和任务。

### 9. Freeplane

我不知道你们中的大多数是否每天都使用思维导图软件，但是如果你使用，请选择 [Freeplane](https://www.freeplane.org/wiki/index.php/Home)。这是一款免费的思维导图和知识管理软件，可用于商业或娱乐。你可以创建笔记，将其排列在云图或图表中，使用日历和提醒设置任务等。

### 10. Calligra Flow

最后，如果你需要流程图和图表工具，请尝试 [Calligra Flow](https://www.calligra.org/flow/)。你可以将其视为开放源代码的 [Microsoft Visio](https://www.maketecheasier.com/5-best-free-alternatives-to-microsoft-visio/) 替代品，但 Calligra Flow 不提供 Viso 提供的所有特性。不过，你可以使用它来创建网络图、组织结构图、流程图等等。

生产力工具不仅可以加快工作速度，还可以让你更有条理。我敢打赌，几乎没有人不使用某种形式的生产力工具。尝试这里列出的应用程序可以使你的工作效率更高，还能让你的生活至少轻松一些。

---

via: <https://www.maketecheasier.com/free-linux-productivity-apps-you-havent-heard-of/>

作者：[Ada Ivanova](https://www.maketecheasier.com/author/adaivanoff/) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


chkservice：在 Linux 终端管理 systemd 单元的工具

Summary: chkservice 是一个基于 ncurses 的在终端中管理 systemd 单元的工具。它提供了一个非常全面的 systemd 服务的视图，使得它们非常容易修改。

# chkservice：在 Linux 终端管理 systemd 单元的工具

systemd 意即<ruby> 系统守护进程 <rt>  system daemon </rt></ruby>，是一个新的初始化系统和系统管理工具，它现在非常流行，大部分的 Linux 发行版开始使用这种新的初始化系统。

`systemctl` 是一个 systemd 的工具，它可以帮助我们管理 systemd 守护进程。 它控制系统的启动程序和服务，使用并行化方式，为启动的服务激活套接字和 D-Bus，提供守护进程的按需启动，使用 Linux 控制组跟踪进程，维护挂载和自动挂载点。

此外，它还提供了日志守护进程、用于控制基本系统配置的功能，如主机名、日期、地区、维护已登录用户列表和运行容器和虚拟机、系统帐户、运行时目录和设置，以及管理简单网络配置、网络时间同步、日志转发和名称解析的守护进程。

### 什么是 chkservice

[chkservice](https://github.com/linuxenko/chkservice) 是一个基于 ncurses 的在终端中管理 systemd 单元的工具。它提供了一个非常全面的 systemd 服务的视图，使得它们非常容易修改。

只有拥有超级管理权限才能够改变 systemd 单元的状态和 sysv 系统启动脚本。

### 在 Linux 安装 chkservice

我们可以通过两种方式安装 `chkservice`，通过包安装或者手动安装。

对于 Debian/Ubuntu，使用 [APT-GET 命令](https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/) 或 [APT 命令](https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/) 安装 `chkservice`。

```
$ sudo add-apt-repository ppa:linuxenko/chkservice
$ sudo apt-get update
$ sudo apt-get install chkservice

```

对于 Arch Linux 系的系统，使用 [Yaourt 命令](https://www.2daygeek.com/install-yaourt-aur-helper-on-arch-linux/) 或 [Packer 命令](https://www.2daygeek.com/install-packer-aur-helper-on-arch-linux/) 从 AUR 库安装 `chkservice`。

```
$ yaourt -S chkservice
或
$ packer -S chkservice

```

对于 Fedora，使用 [DNF 命令](https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/) 安装 `chkservice`。

```
$ sudo dnf copr enable srakitnican/default
$ sudo dnf install chkservice

```

对于 Debian 系系统，使用 [DPKG 命令](https://www.2daygeek.com/dpkg-command-to-manage-packages-on-debian-ubuntu-linux-mint-systems/) 安装 `chkservice`。

```
$ wget https://github.com/linuxenko/chkservice/releases/download/0.1/chkservice_0.1.0-amd64.deb
$ sudo dpkg -i chkservice_0.1.0-amd64.deb

```

对于 RPM 系的系统，使用 [DNF 命令](https://www.2daygeek.com/rpm-command-examples/) 安装 `chkservice`。

```
$ sudo yum install https://github.com/linuxenko/chkservice/releases/download/0.1/chkservice_0.1.0-amd64.rpm

```

### 如何使用 chkservice

只需输入以下命令即可启动 `chkservice` 工具。 输出分为四部分。

* **第一部分：** 这一部分显示了守护进程的状态，比如可用的 `[X]` 或者不可用的 `[ ]` 或者静态的 `[s]` 或者被掩藏的 `-m-`
* **第二部分：** 这一部分显示守护进程的状态例如开始 `>` 或者停止 `=`
* **第三部分：** 这一部分显示单元的名称
* **第四部分：** 这一部分简短地显示了守护进程的一些信息

```
$ sudo chkservice

```

要查看帮助页面，按下 `?`。 这将向您显示管理 systemd 服务的可用选项。

选择要启用或禁用的守护进程，然后点击空格键。

选择你想开始或停止的守护进程，然后按下 `s`。

选择要重新启动的守护进程，然后按下 `r`，之后，您可以在顶部看到更新的提示。

按下 `q` 退出。

---

via: <https://www.2daygeek.com/chkservice-a-tool-for-managing-systemd-units-from-linux-terminal/>

作者：[Ramya Nuvvula](https://www.2daygeek.com/author/ramya/) 译者：[amwps290](https://github.com/amwps290) 校对：[wxy](https://github.com/wxy)

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


计算机系统进化论

Summary: 纵观现代计算机的历史，从与系统的交互方式方面，可以划分为数个进化阶段。

纵观现代计算机的历史，从与系统的交互方式方面，可以划分为数个进化阶段。

# 计算机系统进化论

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

纵观现代计算机的历史，从与系统的交互方式方面，可以划分为数个进化阶段。而我更倾向于将之归类为以下几个阶段：

1. 数字系统
2. 专用应用系统
3. 应用中心系统
4. 信息中心系统
5. 无应用系统

下面我们详细聊聊这几种分类。

### 数字系统

在我看来，[早期计算机](https://en.wikipedia.org/wiki/History_of_computing_hardware)，只被设计用来处理数字。它们能够加、减、乘、除。在它们中有一些能够运行像是微分和积分之类的更复杂的数学操作。

当然，如果你把字符映射成数字，它们也可以计算字符串。但这多少有点“数字的创造性使用”的意思，而不是直接处理各种信息。

### 专用应用系统

对于更高层级的问题，纯粹的数字系统是不够的。专用应用系统被开发用来处理单一任务。它们和数字系统十分相似，但是，它们拥有足够的复杂数字计算能力。这些系统能够完成十分明确的高层级任务，像调度问题的相关计算或者其他优化问题。

这类系统为单一目的而搭建，它们解决的是单一明确的问题。

### 应用中心系统

应用中心系统是第一个真正的通用系统。它们的主要使用风格很像专用应用系统，但是它们拥有以时间片模式（一个接一个）或以多任务模式（多应用同时）运行的多个应用程序。

上世纪 70 年代的 [早期的个人电脑](https://en.wikipedia.org/wiki/Xerox_Alto)是第一种受人们欢迎的应用中心系统。

如今的现在操作系统 —— Windows 、macOS 、大多数 GNU/Linux 桌面环境 —— 一直遵循相同的法则。

当然，应用中心系统还可以再细分为两种子类：

1. 紧密型应用中心系统
2. 松散型应用中心系统

紧密型应用中心系统像是 [Windows 3.1](https://en.wikipedia.org/wiki/Windows_3.1x) （拥有程序管理器和文件管理器）或者甚至 [Windows 95](https://en.wikipedia.org/wiki/Windows_95) 的最初版本都没有预定义的文件夹层次。用户启动文本处理程序（像  [WinWord](https://en.wikipedia.org/wiki/Microsoft_Word) ）并且把文件保存在 WinWord 的程序文件夹中。在使用表格处理程序的时候，又把文件保存在表格处理工具的程序文件夹中。诸如此类。用户几乎不创建自己的文件层次结构，可能由于此举的不方便、用户单方面的懒惰，或者他们认为根本没有必要。那时，每个用户拥有几十个至多几百个文件。

为了访问文件中的信息，用户常常先打开一个应用程序，然后通过程序中的“文件/打开”功能来获取处理过的数据文件。

在 Windows 平台的 [Windows 95](https://en.wikipedia.org/wiki/Windows_95) SP2 中，“[我的文档](https://en.wikipedia.org/wiki/My_Documents)”首次被使用。有了这样一个文件层次结构的样板，应用设计者开始把 “[我的文档](https://en.wikipedia.org/wiki/My_Documents)” 作为程序的默认的保存 / 打开目录，抛弃了原来将软件产品安装目录作为默认目录的做法。这样一来，用户渐渐适应了这种模式，并且开始自己维护文件夹层次。

松散型应用中心系统（通过文件管理器来提取文件）应运而生。在这种系统下，当打开一个文件的时候，操作系统会自动启动与之相关的应用程序。这是一次小而精妙的用法转变。这种应用中心系统的用法模式一直是个人电脑的主要用法模式。

然而，这种模式有很多的缺点。例如，为了防止数据提取出现问题，需要维护一个包含给定项目的所有相关文件的严格文件夹层次结构。不幸的是，人们并不总能这样做。更进一步说，[这种模式不能很好的扩展](http://karl-voit.at/tagstore/downloads/Voit2012b.pdf)。 桌面搜索引擎和高级数据组织工具（像 [tagstore](http://karl-voit.at/tagstore/)）可以起到一点改善作用。正如研究显示的那样，只有一少部分人正在使用那些高级文件提取工具。大多数的用户不使用替代提取工具或者辅助提取技术在文件系统中寻找文件。

### 信息中心系统

解决上述需要将所有文件都放到一个文件夹的问题的可行办法之一就是从应用中心系统转换到信息中心系统。

信息中心系统将项目的所有信息联合起来，放在一个地方，放在同一个应用程序里。因此，我们再也不需要计算项目预算时，打开表格处理程序；写工程报告时，打开文本处理程序；处理图片文件时，又打开另一个工具。

上个月的预算情况在客户会议笔记的右下方，客户会议笔记又在画板的右下方，而画板又在另一些要去完成的任务的右下方。在各个层之间没有文件或者应用程序来回切换的麻烦。

早期，IBM [OS/2](https://en.wikipedia.org/wiki/OS/2)、 Microsoft [OLE](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding) 和 [NeXT](https://en.wikipedia.org/wiki/NeXT) 都做过类似的尝试。但都由于种种原因没有取得重大成功。从 [Plan 9](https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs) 发展而来的 [ACme](https://en.wikipedia.org/wiki/Acme_%2528text_editor%2529) 是一个非常有趣的信息中心环境。它在一个应用程序中包含了[多种应用程序](https://en.wikipedia.org/wiki/List_of_Plan_9_applications)。但是即时是它移植到了 Windows 和 GNU/Linux，也从来没有成为一个引起关注的软件。

信息中心系统的现代形式是高级 [个人维基](https://en.wikipedia.org/wiki/Personal_wiki)（像 [TheBrain](https://en.wikipedia.org/wiki/TheBrain) 和 [Microsoft OneNote](https://en.wikipedia.org/wiki/Microsoft_OneNote)）。

我选择的个人工具是带 [Org 模式](../../../../tags/emacs) 扩展的 [GNU/Emacs](https://github.com/novoid/Memacs) 平台。在用电脑的时候，我几乎不能没有 Org 模式 。为了访问外部数据资源，我创建了一个可以将多种数据导入 Org 模式的插件 —— [Memacs](https://github.com/novoid/Memacs) 。我喜欢将表格数据计算放到日程任务的右下方，然后是行内图片，内部和外部链接，等等。它是一个真正的用户不用必须操心程序或者严格的层次文件系统文件夹的信息中心系统。同时，用简单的或高级的标签也可以进行多分类。一个命令可以派生多种视图。比如，一个视图有日历，待办事项。另一个视图是租借事宜列表。等等。它对 Org 模式的用户没有限制。只有你想不到，没有它做不到。

进化结束了吗？ 当然没有。

### 无应用系统

我能想到这样一类操作系统，我称之为无应用系统。在下一步的发展中，系统将不需要单一领域的应用程序，即使它们能和 Org 模式一样出色。计算机直接提供一个处理信息和使用功能的友好用户接口，而不通过文件和程序。甚至连传统的操作系统也不需要。

无应用系统也可能和 [人工智能](https://en.wikipedia.org/wiki/Artificial_intelligence) 联系起来。把它想象成 [2001 太空漫游](https://en.wikipedia.org/wiki/2001:_A_Space_Odyssey) 中的 [HAL 9000](https://en.wikipedia.org/wiki/HAL_9000) 和星际迷航中的 [LCARS](https://en.wikipedia.org/wiki/LCARS) 一类的东西就可以了。

从基于应用的、基于供应商的软件文化到无应用系统的转化让人很难相信。 或许，缓慢但却不断发展的开源环境，可以使一个由各种各样组织和人们贡献的真正无应用环境成型。

信息和提取、操作信息的功能，这是系统应该具有的，同时也是我们所需要的。其他的东西仅仅是为了使我们不至于分散注意力。

---

via: <http://karl-voit.at/2017/02/10/evolution-of-systems/>

作者：[Karl Voit](http://karl-voit.at) 译者：[lontow](https://github.com/lontow) 校对：[wxy](https://github.com/wxy)

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


为初学者准备的 ln 命令教程（5 个示例）

Summary: 当我们在命令行上工作时，您可能需要在文件之间创建链接。

当我们在命令行上工作时，您可能需要在文件之间创建链接。

# 为初学者准备的 ln 命令教程（5 个示例）

当我们在命令行上工作时，您可能需要在文件之间创建链接。这时，您可以可以借助一个专用命令，`ln`。本教程中，我们将通过一些简单易理解的例子来讨论此工具的基础知识。在此之前，值得一提的是，本教程所有例子都已在 Ubuntu 16.04 上测试通过。

### Linux ln 命令

正如你现在所了解的，`ln` 命令能够让您在文件之间创建链接。下面就是 `ln` 工具的语法（或者使用其他一些可行的语法）。

```
ln [OPTION]... [-T] TARGET LINK_NAME （第一种形式）
ln [OPTION]... TARGET （第二种形式）
ln [OPTION]... TARGET... DIRECTORY （第三种形式）
ln [OPTION]... -t DIRECTORY TARGET... （第四种形式）

```

下面是 `ln` 工具 man 文档描述的内容：

>
> 在第一种形式下，为目标位置（TARGET）创建一个叫 LINK\_NAME 的链接。在第二种形式下，为目标位置（TARGET）在当前目录下创建一个链接（LCTT 译注：创建的为同名链接）。在第三和第四种形式中，在 DIRECTORY 目录下为每一个目标位置（TARGET）创建链接。默认创建硬链接，符号链接需要 `--symbolic` 选项。默认创建的每一个创建的链接（新链接的名字）都不能已经存在。当创建硬链接时，目标位置（TARGET）文件必须存在；符号链接可以保存任意文本，如果之后解析，相对链接的解析与其父目录有关。
>
>
>

通过下面问答风格的例子，可能会给你更好的理解。但是在此之前，建议您先了解 [硬链接和软链接的区别](https://medium.com/meatandmachines/explaining-the-difference-between-hard-links-symbolic-links-using-bruce-lee-32828832e8d3).

### Q1. 如何使用 ln 命令创建硬链接？

这很简单，你只需要像下面使用 `ln` 命令：

```
ln [file] [hard-link-to-file]

```

例如：

```
ln test.txt test_hard_link.txt

```

[](https://www.howtoforge.com/images/command-tutorial/big/ln-hard-link.png)

如此，您便可以看见一个已经创建好的，名为 `test_hard_link.txt` 的硬链接。

### Q2. 如何使用 ln 命令创建软/符号链接？

使用 `-s` 命令行选项：

```
ln -s [file] [soft-link-to-file]

```

例如：

```
ln -s test.txt test_soft_link.txt

```

[](https://www.howtoforge.com/images/command-tutorial/big/ln-soft-link.png)

`test_soft_link.txt` 文件就是一个软/符号链接，以天蓝色文本 [标识](https://askubuntu.com/questions/17299/what-do-the-different-colors-mean-in-ls)。

### Q3. 如何使用 ln 命令删除既存的同名目标文件？

默认情况下，`ln` 不允许您在目标目录下创建已存在的链接。

[](https://www.howtoforge.com/images/command-tutorial/big/ln-file-exists.png)

然而，如果一定要这么做，您可以使用 `-f` 命令行选项覆盖此行为。

[](https://www.howtoforge.com/images/command-tutorial/big/ln-f-option.png)

提示：如果您想在此删除过程中有所交互，您可以使用 `-i` 选项。

### Q4. 如何使用 ln 命令创建现有文件的同名备份？

如果您不想 `ln` 删除同名的现有文件，您可以为这些文件创建备份。使用 `-b` 即可实现此效果，以这种方式创建的备份文件，会在其文件名结尾处包含一个波浪号（`~`）。

[](https://www.howtoforge.com/images/command-tutorial/big/ln-b-option.png)

### Q5. 如何在当前目录以外的其它目录创建链接？

使用 `-t` 选项指定一个文件目录（除了当前目录）。比如：

```
ls test* | xargs ln -s -t /home/himanshu/Desktop/

```

上述命令会为（当前目录下的）所有 `test*` 文件创建链接，并放到桌面目录下。

### 总结

当然，尤其对于新手来说，`ln` 并不是日常必备命令。但是，这是一个有用的命令，因为你永远不知道它什么时候能够节省你一天的时间。对于这个命令，我们已经讨论了一些实用的选项，如果你已经完成了这些，可以查询 [man 文档](https://linux.die.net/man/1/ln) 来了解更多详情。

---

via: <https://www.howtoforge.com/linux-ln-command/>

作者：[Himanshu Arora](https://www.howtoforge.com) 译者：[CYLeft](https://github.com/CYLeft) 校对：[Locez](https://github.com/locez)

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