用以检查 Linux 内存使用的 5 个命令

>
> 对于 Linux 管理员来说，检查系统内存用量是一个重要的技能。Jack 给出了解决这个问题的五种不同方式。
>
>
>

![](/data/attachment/album/201808/09/014512zegx7k8fehphhecf.jpg)

Linux 操作系统包含大量工具，所有这些工具都可以帮助你管理系统。从简单的文件和目录工具到非常复杂的安全命令，在 Linux 中没有多少是你做不了的。而且，尽管普通桌面用户可能不需要在命令行熟悉这些工具，但对于 Linux 管理员来说，它们是必需的。为什么？首先，你在某些时候不得不使用没有 GUI 的 Linux 服务器。其次，命令行工具通常比 GUI 替代工具提供更多的功能和灵活性。

确定内存使用情况是你可能需要的技能，尤其是某个应用程序变得异常和占用系统内存时。当发生这种情况时，知道有多种工具可以帮助你进行故障排除十分方便的。或者，你可能需要收集有关 Linux 交换分区的信息，或者有关安装的内存的详细信息？对于这些也有相应的命令。让我们深入了解各种 Linux 命令行工具，以帮助你检查系统内存使用情况。这些工具并不是非常难以使用，在本文中，我将向你展示五种不同的方法来解决这个问题。

我将在 [Ubuntu 18.04 服务器平台](https://www.ubuntu.com/download/server)上进行演示，但是你应该在你选择的发行版中找到对应的所有命令。更妙的是，你不需要安装任何东西（因为大多数这些工具都包含 Linux 系统中）。

话虽如此，让我们开始工作吧。

### top

我想从最常用的工具开始。`top` 命令提供正在运行的系统的实时动态视图，它检查每个进程的内存使用情况。这非常重要，因为你可以轻松地看到同一命令的多个示例消耗不同的内存量。虽然你无法在没有显示器的服务器上看到这种情况，但是你已经注意到打开 Chrome 使你的系统速度变慢了。运行 `top` 命令以查看 Chrome 有多个进程在运行（每个选项卡一个 - 图 1）。

![top](/data/attachment/album/201808/09/014538b1jbuywsbyzzwjpa.jpg "top")

*图1：top 命令中出现多个 Chrome 进程。*

Chrome 并不是唯一显示多个进程的应用。你看到图 1 中的 Firefox 了吗？那是 Firefox 的主进程，而 Web Content 进程是其打开的选项卡。在输出的顶部，你将看到系统统计信息。在我的机器上（[System76 Leopard Extreme](https://system76.com/desktops/leopard)），我总共有 16GB 可用 RAM，其中只有超过 10GB 的 RAM 正在使用中。然后，你可以整理该列表，查看每个进程使用的内存百分比。

`top` 最好的地方之一就是发现可能已经失控的服务的进程 ID 号（PID）。有了这些 PID，你可以对有问题的任务进行故障排除（或 `kill`）。

如果你想让 `top` 显示更友好的内存信息，使用命令 `top -o ％MEM`，这会使 `top` 按进程所用内存对所有进程进行排序（图 2）。

![top](/data/attachment/album/201808/09/014539kv40k6g9cq66ddkc.jpg "top")

*图 2：在 top 命令中按使用内存对进程排序*

`top` 命令还为你提供有关使用了多少交换空间的实时更新。

### free

然而有时候，`top` 命令可能不能满足你的需求。你可能只需要查看系统的可用和已用内存。对此，Linux 还有 `free` 命令。`free` 命令显示：

* 可用和已使用的物理内存总量
* 系统中交换内存的总量
* 内核使用的缓冲区和缓存

在终端窗口中，输入 `free` 命令。它的输出不是实时的，相反，你将获得的是当前空闲和已用内存的即时快照（图 3）。

![free](/data/attachment/album/201808/09/014539wzj67qqyrn4k6d86.jpg "free")

*图 3 ：free 命令的输出简单明了。*

当然，你可以通过添加 `-m` 选项来让 `free` 显示得更友好一点，就像这样：`free -m`。这将显示内存的使用情况，以 MB 为单位（图 4）。

![free](/data/attachment/album/201808/09/014539x3exhjm33jwwizmq.jpg "free")

*图 4：free 命令以一种更易于阅读的形式输出。*

当然，如果你的系统是很新的，你将希望使用 `-g` 选项（以 GB 为单位），比如 `free -g`。

如果你需要知道内存总量，你可以添加 `-t` 选项，比如：`free -mt`。这将简单地计算每列中的内存总量（图 5）。

![total](/data/attachment/album/201808/09/014540uwm3bldd3ycdicx2.jpg "total")

*图 5：为你提供空闲的内存列。*

### vmstat

另一个非常方便的工具是 `vmstat`。这个特殊的命令是一个报告虚拟内存统计信息的小技巧。`vmstat` 命令将报告关于：

* 进程
* 内存
* 分页
* 阻塞 IO
* 中断
* 磁盘
* CPU

使用 `vmstat` 的最佳方法是使用 `-s` 选项，如 `vmstat -s`。这将在单列中报告统计信息（这比默认报告更容易阅读）。`vmstat` 命令将提供比你需要的更多的信息（图 6），但更多的总是更好的（在这种情况下）。

![vmstat](/data/attachment/album/201808/09/014540ibvpe83xoxwed85m.jpg "vmstat")

*图 6：使用 vmstat 命令来检查内存使用情况。*

### dmidecode

如果你想找到关于已安装的系统内存的详细信息，该怎么办？为此，你可以使用 `dmidecode` 命令。这个特殊的工具是 DMI 表解码器，它将系统的 DMI 表内容转储成人类可读的格式。如果你不清楚 DMI 表是什么，那么可以这样说，它可以用来描述系统的构成（以及系统的演变）。

要运行 `dmidecode` 命令，你需要 `sudo` 权限。因此输入命令 `sudo dmidecode -t 17`。该命令的输出（图 7）可能很长，因为它显示所有内存类型设备的信息。因此，如果你无法上下滚动，则可能需要将该命令的输出发送到一个文件中，比如：`sudo dmidecode -t 17> dmi_infoI`，或将其传递给 `less` 命令，如 `sudo dmidecode | less`。

![dmidecode](/data/attachment/album/201808/09/014541dur591hh2qqdwg6u.jpg "dmidecode")

*图 7：dmidecode 命令的输出。*

### /proc/meminfo

你可能会问自己：“这些命令从哪里获取这些信息？”在某些情况下，它们从 `/proc/meminfo` 文件中获取。猜到了吗？你可以使用命令 `less /proc/meminfo` 直接读取该文件。通过使用 `less` 命令，你可以在长长的输出中向上和向下滚动，以准确找到你需要的内容（图 8）。

![/proc/meminfo](/data/attachment/album/201808/09/014541w1m5puy0hmimrvzz.jpg "/proc/meminfo")

*图 8：less /proc/meminfo 命令的输出。*

关于 `/proc/meminfo` 你应该知道：这不是一个真实的文件。相反 `/proc/meminfo` 是一个虚拟文件，包含有关系统的实时动态信息。特别是，你需要检查以下值：

* 全部内存（`MemTotal`）
* 空闲内存（`MemFree`）
* 可用内存（`MemAvailable`）
* 缓冲区（`Buffers`）
* 文件缓存（`Cached`）
* 交换缓存（`SwapCached`）
* 全部交换区（`SwapTotal`）
* 空闲交换区（`SwapFree`）

如果你想使用 `/proc/meminfo`，你可以连接 egrep 命令使用它：`egrep --color'Mem | Cache | Swap'/proc/meminfo`。这将生成一个易于阅读的列表，其中包含 `Mem`、 `Cache` 和 `Swap` 等内容的条目将是彩色的（图 9）。

![/proc/meminfo](/data/attachment/album/201808/09/014541wbmp3p8hdo5nzzbh.jpg "/proc/meminfo")

*图 9：让 /proc/meminfo 更容易阅读。*

### 继续学习

你要做的第一件事就是阅读每个命令的手册页（例如 `man top`、`man free`、`man vmstat`、`man dmidecode`）。从命令的手册页开始，对于如何在 Linux 上使用一个工具，它总是一个很好的学习方法。

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

---

via: <https://www.linux.com/learn/5-commands-checking-memory-usage-linux>

作者：[Jack Wallen](https://www.linux.com/users/jlwallen) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


献给 Debian 和 Ubuntu 用户的一组实用程序

![](/data/attachment/album/201808/09/151322wp1y21wq1p9p1uk8.png)

你使用的是基于 Debian 的系统吗？如果是，太好了！我今天在这里给你带来了一个好消息。先向 “Debian-goodies” 打个招呼，这是一组基于 Debian 系统（比如：Ubuntu、Linux Mint）的有用工具。这些实用工具提供了一些额外的有用的命令，这些命令在基于 Debian 的系统中默认不可用。通过使用这些工具，用户可以找到哪些程序占用更多磁盘空间，更新系统后需要重新启动哪些服务，在一个软件包中搜索与模式匹配的文件，根据搜索字符串列出已安装的包等等。在这个简短的指南中，我们将讨论一些有用的 Debian 的好东西。

### Debian-goodies – 给 Debian 和 Ubuntu 用户的实用程序

debian-goodies 包可以在 Debian 和其衍生的 Ubuntu 以及其它 Ubuntu 变体（如 Linux Mint）的官方仓库中找到。要安装 debian-goodies，只需简单运行：

```
$ sudo apt-get install debian-goodies

```

debian-goodies 安装完成后，让我们继续看一看一些有用的实用程序。

#### 1、 checkrestart

让我从我最喜欢的 `checkrestart` 实用程序开始。安装某些安全更新时，某些正在运行的应用程序可能仍然会使用旧库。要彻底应用安全更新，你需要查找并重新启动所有这些更新。这就是 `checkrestart` 派上用场的地方。该实用程序将查找哪些进程仍在使用旧版本的库，然后，你可以重新启动服务。

在进行库更新后，要检查哪些守护进程应该被重新启动，运行：

```
$ sudo checkrestart
[sudo] password for sk:
Found 0 processes using old versions of upgraded files

```

由于我最近没有执行任何安全更新，因此没有显示任何内容。

请注意，`checkrestart` 实用程序确实运行良好。但是，有一个名为 `needrestart` 的类似的新工具可用于最新的 Debian 系统。`needrestart` 的灵感来自 `checkrestart` 实用程序，它完成了同样的工作。 `needrestart` 得到了积极维护，并支持容器（LXC、 Docker）等新技术。

以下是 `needrestart` 的特点：

* 支持（但不要求）systemd
* 二进制程序的黑名单（例如：用于图形显示的显示管理器）
* 尝试检测挂起的内核升级
* 尝试检测基于解释器的守护进程所需的重启（支持 Perl、Python、Ruby）
* 使用钩子完全集成到 apt/dpkg 中

它在默认仓库中也可以使用。所以，你可以使用如下命令安装它：

```
$ sudo apt-get install needrestart

```

现在，你可以使用以下命令检查更新系统后需要重新启动的守护程序列表：

```
$ sudo needrestart
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

Failed to check for processor microcode upgrades.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

```

好消息是 Needrestart 同样也适用于其它 Linux 发行版。例如，你可以从 Arch Linux 及其衍生版的 AUR 或者其它任何 AUR 帮助程序来安装，就像下面这样：

```
$ yaourt -S needrestart

```

在 Fedora：

```
$ sudo dnf install needrestart

```

#### 2、 check-enhancements

`check-enhancements` 实用程序用于查找那些用于增强已安装的包的软件包。此实用程序将列出增强其它包但不是必须运行它的包。你可以通过 `-ip` 或 `–installed-packages` 选项来查找增强单个包或所有已安装包的软件包。

例如，我将列出增强 gimp 包功能的包：

```
$ check-enhancements gimp
gimp => gimp-data: Installed: (none) Candidate: 2.8.22-1
gimp => gimp-gmic: Installed: (none) Candidate: 1.7.9+zart-4build3
gimp => gimp-gutenprint: Installed: (none) Candidate: 5.2.13-2
gimp => gimp-help-ca: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-de: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-el: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-en: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-es: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-fr: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-it: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-ja: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-ko: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-nl: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-nn: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-pt: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-ru: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-sl: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-help-sv: Installed: (none) Candidate: 2.8.2-0.1
gimp => gimp-plugin-registry: Installed: (none) Candidate: 7.20140602ubuntu3
gimp => xcftools: Installed: (none) Candidate: 1.0.7-6

```

要列出增强所有已安装包的，请运行：

```
$ check-enhancements -ip
autoconf => autoconf-archive: Installed: (none) Candidate: 20170928-2
btrfs-progs => snapper: Installed: (none) Candidate: 0.5.4-3
ca-certificates => ca-cacert: Installed: (none) Candidate: 2011.0523-2
cryptsetup => mandos-client: Installed: (none) Candidate: 1.7.19-1
dpkg => debsig-verify: Installed: (none) Candidate: 0.18
[...]

```

#### 3、 dgrep

顾名思义，`dgrep` 用于根据给定的正则表达式搜索制指定包的所有文件。例如，我将在 Vim 包中搜索包含正则表达式 “text” 的文件。

```
$ sudo dgrep "text" vim
Binary file /usr/bin/vim.tiny matches
/usr/share/doc/vim-tiny/copyright: that they must include this license text. You can also distribute
/usr/share/doc/vim-tiny/copyright: include this license text. You are also allowed to include executables
/usr/share/doc/vim-tiny/copyright: 1) This license text must be included unmodified.
/usr/share/doc/vim-tiny/copyright: text under a) applies to those changes.
/usr/share/doc/vim-tiny/copyright: context diff. You can choose what license to use for new code you
/usr/share/doc/vim-tiny/copyright: context diff will do. The e-mail address to be used is
/usr/share/doc/vim-tiny/copyright: On Debian systems, the complete text of the GPL version 2 license can be
[...]

```

`dgrep` 支持大多数 `grep` 的选项。参阅以下指南以了解 `grep` 命令。

* [献给初学者的 Grep 命令教程](https://www.ostechnix.com/the-grep-command-tutorial-with-examples-for-beginners/)

#### 4、 dglob

`dglob` 实用程序生成与给定模式匹配的包名称列表。例如，找到与字符串 “vim” 匹配的包列表。

```
$ sudo dglob vim
vim-tiny:amd64
vim:amd64
vim-common:all
vim-runtime:all

```

默认情况下，`dglob` 将仅显示已安装的软件包。如果要列出所有包（包括已安装的和未安装的），使用 `-a` 标志。

```
$ sudo dglob vim -a

```

#### 5、 debget

`debget` 实用程序将在 APT 的数据库中下载一个包的 .deb 文件。请注意，它只会下载给定的包，不包括依赖项。

```
$ debget nano
Get:1 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 nano amd64 2.9.3-2 [231 kB]
Fetched 231 kB in 2s (113 kB/s)

```

#### 6、 dpigs

这是此次集合中另一个有用的实用程序。`dpigs` 实用程序将查找并显示那些占用磁盘空间最多的已安装包。

```
$ dpigs
260644 linux-firmware
167195 linux-modules-extra-4.15.0-20-generic
75186 linux-headers-4.15.0-20
64217 linux-modules-4.15.0-20-generic
55620 snapd
31376 git
31070 libicu60
28420 vim-runtime
25971 gcc-7
24349 g++-7

```

如你所见，linux-firmware 包占用的磁盘空间最多。默认情况下，它将显示占用磁盘空间的 **前 10 个**包。如果要显示更多包，例如 20 个，运行以下命令：

```
$ dpigs -n 20

```

#### 7. debman

`debman` 实用程序允许你轻松查看二进制文件 .deb 中的手册页而不提取它。你甚至不需要安装 .deb 包。以下命令显示 nano 包的手册页。

```
$ debman -f nano_2.9.3-2_amd64.deb nano

```

如果你没有 .deb 软件包的本地副本，使用 `-p` 标志下载并查看包的手册页。

```
$ debman -p nano nano

```

**建议阅读：**

* [每个 Linux 用户都应该知道的 3 个 man 的替代品](https://www.ostechnix.com/3-good-alternatives-man-pages-every-linux-user-know/)

#### 8、 debmany

安装的 Debian 包不仅包含手册页，还包括其它文件，如确认、版权和自述文件等。`debmany` 实用程序允许你查看和读取那些文件。

```
$ debmany vim

```

![](/data/attachment/album/201808/09/151324vqdd6n6dbnb6jkdn.png)

使用方向键选择要查看的文件，然后按回车键查看所选文件。按 `q` 返回主菜单。

如果未安装指定的软件包，`debmany` 将从 APT 数据库下载并显示手册页。应安装 `dialog` 包来阅读手册页。

#### 9、 popbugs

如果你是开发人员，`popbugs` 实用程序将非常有用。它将根据你使用的包显示一个定制的发布关键 bug 列表（使用 popularity-contest 数据）。对于那些不关心的人，popularity-contest 包设置了一个 cron （定时）任务，它将定期匿名向 Debian 开发人员提交有关该系统上最常用的 Debian 软件包的统计信息。这些信息有助于 Debian 做出决定，例如哪些软件包应该放在第一张 CD 上。它还允许 Debian 改进未来的发行版本，以便为新用户自动安装最流行的软件包。

要生成严重 bug 列表并在默认 Web 浏览器中显示结果，运行：

```
$ popbugs

```

此外，你可以将结果保存在文件中，如下所示。

```
$ popbugs --output=bugs.txt

```

#### 10、 which-pkg-broke

此命令将显示给定包的所有依赖项以及安装每个依赖项的时间。通过使用此信息，你可以在升级系统或软件包之后轻松找到哪个包可能会在什么时间损坏了另一个包。

```
$ which-pkg-broke vim
Package <debconf-2.0> has no install time info
debconf Wed Apr 25 08:08:40 2018
gcc-8-base:amd64 Wed Apr 25 08:08:41 2018
libacl1:amd64 Wed Apr 25 08:08:41 2018
libattr1:amd64 Wed Apr 25 08:08:41 2018
dpkg Wed Apr 25 08:08:41 2018
libbz2-1.0:amd64 Wed Apr 25 08:08:41 2018
libc6:amd64 Wed Apr 25 08:08:42 2018
libgcc1:amd64 Wed Apr 25 08:08:42 2018
liblzma5:amd64 Wed Apr 25 08:08:42 2018
libdb5.3:amd64 Wed Apr 25 08:08:42 2018
[...]

```

#### 11、 dhomepage

`dhomepage` 实用程序将在默认 Web 浏览器中显示给定包的官方网站。例如，以下命令将打开 Vim 编辑器的主页。

```
$ dhomepage vim

```

这就是全部了。Debian-goodies 是你武器库中必备的工具。即使我们不经常使用所有这些实用程序，但它们值得学习，我相信它们有时会非常有用。

我希望这很有用。更多好东西要来了。敬请关注！

干杯!

---

via: <https://www.ostechnix.com/debian-goodies-a-set-of-useful-utilities-for-debian-and-ubuntu-users/>

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

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


Google 为树莓派 Zero W 发布了基于TensorFlow 的视觉识别套件

![](/data/attachment/album/201808/09/153345vg8bo3cl9aacc83f.jpg)

Google 发布了一个 45 美元的 “AIY Vision Kit”，它是运行在树莓派 Zero W 上的基于 TensorFlow 的视觉识别开发套件，它使用了一个带 Movidius 芯片的 “VisionBonnet” 板。

为加速该设备上的神经网络，Google 的 AIY 视频套件继承了早期树莓派上运行的 [AIY 项目](http://linuxgizmos.com/free-raspberry-pi-voice-kit-taps-google-assistant-sdk/) 的语音/AI 套件，这个型号的树莓派随五月份的 MagPi 杂志一起赠送。与语音套件和老的 Google 硬纸板 VR 查看器一样，这个新的 AIY 视觉套件也使用一个硬纸板包装。这个套件和 [Cloud Vision API](http://linuxgizmos.com/google-releases-cloud-vision-api-with-demo-for-pi-based-robot/) 是不一样的，它使用了一个在 2015 年演示过的基于树莓派的 GoPiGo 机器人，它完全在本地的处理能力上运行，而不需要使用一个云端连接。这个 AIY 视觉套件现在可以 45 美元的价格去预订，将在 12 月份发货。

[![](/data/attachment/album/201808/09/153413j76kyykr65t6l6yv.jpg)](http://linuxgizmos.com/files/google_aiyvisionkit.jpg) [![](/data/attachment/album/201808/09/153414q992onemd4o2xctz.jpg)](http://linuxgizmos.com/files/rpi_zerow.jpg)

*AIY 视觉套件，完整包装（左）和树莓派 Zero W*

这个套件的主要处理部分除了所需要的 [树莓派 Zero W](http://linuxgizmos.com/raspberry-pi-zero-w-adds-wifi-and-bluetooth-for-only-5-more/) 单片机之外 —— 一个基于 ARM11 的 1 GHz 的 Broadcom BCM2836 片上系统，另外的就是 Google 最新的 VisionBonnet RPi 附件板。这个 VisionBonnet pHAT 附件板使用了一个 Movidius MA2450，它是 [Movidius Myriad 2 VPU](https://www.movidius.com/solutions/vision-processing-unit) 版的处理器。在 VisionBonnet 上，处理器为神经网络运行了 Google 的开源机器学习库 [TensorFlow](https://www.tensorflow.org/)。因为这个芯片，使得视觉处理的速度最高达每秒 30 帧。

这个 AIY 视觉套件要求用户提供一个树莓派 Zero W、一个 [树莓派摄像机 v2](http://linuxgizmos.com/raspberry-pi-cameras-jump-to-8mp-keep-25-dollar-price/)、以及一个 16GB 的 micro SD 卡，它用来下载基于 Linux 的 OS 镜像。这个套件包含了 VisionBonnet、一个 RGB 街机风格的按钮、一个压电扬声器、一个广角镜头套件、以及一个包裹它们的硬纸板。还有一些就是线缆、支架、安装螺母，以及连接部件。

[![](/data/attachment/album/201808/09/153414xvxuukphyp2vdqbu.jpg)](http://linuxgizmos.com/files/google_aiyvisionkit_pieces.jpg) [![](/data/attachment/album/201808/09/153415a1lme7nvkd76e68k.jpg)](http://linuxgizmos.com/files/google_visionbonnet.jpg)

*AIY 视觉套件组件（左）和 VisonBonnet 附件板*

有三个可用的神经网络模型。一个是通用的模型，它可以识别常见的 1000 个东西，一个是面部检测模型，它可以对 “快乐程度” 进行评分，从 “悲伤” 到 “大笑”，还有一个模型可以用来辨别图像内容是狗、猫、还是人。这个 1000 个图片模型源自 Google 的开源 [MobileNets](https://research.googleblog.com/2017/06/mobilenets-open-source-models-for.html)，它是基于 TensorFlow 家族的计算机视觉模型，它设计用于资源受限的移动或者嵌入式设备。

MobileNet 模型是低延时、低功耗，和参数化的，以满足资源受限的不同使用情景。Google 说，这个模型可以用于构建分类、检测、嵌入、以及分隔。在本月的早些时候，Google 发布了一个开发者预览版，它是一个对 Android 和 iOS 移动设备友好的 [TensorFlow Lite](https://developers.googleblog.com/2017/11/announcing-tensorflow-lite.html) 库，它与 MobileNets 和 Android 神经网络 API 是兼容的。

[![](/data/attachment/album/201808/09/153416t5x00xp5xc56vpx0.jpg)](http://linuxgizmos.com/files/google_aiyvisionkit_assembly.jpg)

*AIY 视觉套件包装图*

除了提供这三个模型之外，AIY 视觉套件还提供了基本的 TensorFlow 代码和一个编译器，因此用户可以去开发自己的模型。另外，Python 开发者可以写一些新软件去定制 RGB 按钮颜色、压电元素声音、以及在 VisionBonnet 上的 4x GPIO 针脚，它可以添加另外的指示灯、按钮、或者伺服机构。Potential 模型包括识别食物、基于可视化输入来打开一个狗门、当你的汽车偏离车道时发出文本信息、或者根据识别到的人的面部表情来播放特定的音乐。

[![](/data/attachment/album/201808/09/153416kcf91eksyyu7ejfz.jpg)](http://linuxgizmos.com/files/movidius_myriad2vpu_block.jpg) [![](/data/attachment/album/201808/09/153417scltkwfkffk3skrk.jpg)](http://linuxgizmos.com/files/movidius_myriad2_reference_board.jpg)

*Myriad 2 VPU 结构图（左）和参考板*

Movidius Myriad 2 处理器在一个标称 1W 的功耗下提供每秒万亿次浮点运算的性能。在被 Intel 收购之前，这个芯片最早出现在 Tango 项目的参考平台上，并内置在 2016 年 5 月由 Movidius 首次亮相的、Ubuntu 驱动的 USB 的 [Fathom](http://linuxgizmos.com/usb-stick-brings-neural-computing-functions-to-devices/) 神经网络处理棒中。根据 Movidius 的说法，Myriad 2 目前已经在 “市场上数百万的设备上使用”。

**更多信息**

AIY 视觉套件可以在 Micro Center 上预订，价格为 $44.99，预计在（2017 年） 12 月初发货。更多信息请参考 AIY 视觉套件的 [公告](https://blog.google/topics/machine-learning/introducing-aiy-vision-kit-make-devices-see/)、[Google 博客](https://developers.googleblog.com/2017/11/introducing-aiy-vision-kit-add-computer.html)、以及 [Micro Center 购物页面](http://www.microcenter.com/site/content/Google_AIY.aspx?ekw=aiy&rd=1)。

---

via: <http://linuxgizmos.com/google-launches-tensorflow-based-vision-recognition-kit-for-rpi-zero-w/>

作者：[Eric Brown](http://linuxgizmos.com/google-launches-tensorflow-based-vision-recognition-kit-for-rpi-zero-w/) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


老树发新芽：微服务

![](/data/attachment/album/201808/11/005341qlofmbsl5z60jfoo.jpg)

如果我告诉你有这样一种软件架构，一个应用程序的组件通过基于网络的通讯协议为其它组件提供服务，我估计你可能会说它是 …

是的，它和你编程的年限有关。如果你从上世纪九十年代就开始了你的编程生涯，那么你肯定会说它是 <ruby>   面向服务的架构  <rt>  Service-Oriented Architecture </rt></ruby>（SOA）。但是，如果你是个年青人，并且在云上获得初步的经验，那么，你将会说：“哦，你说的是 <ruby>   微服务  <rt>  Microservices </rt></ruby>。”

你们都没错。如果想真正地了解它们的差别，你需要深入地研究这两种架构。

在 SOA 中，服务是一个功能，它是定义好的、自包含的、并且是不依赖上下文和其它服务的状态的功能。总共有两种服务。一种是消费者服务，它从另外类型的服务 —— 提供者服务 —— 中请求一个服务。一个 SOA 服务可以同时扮演这两种角色。

SOA 服务可以与其它服务交换数据。两个或多个服务也可以彼此之间相互协调。这些服务执行基本的任务，比如创建一个用户帐户、提供登录功能、或验证支付。

与其说 SOA 是模块化一个应用程序，还不如说它是把分布式的、独立维护和部署的组件，组合成一个应用程序。然后在服务器上运行这些组件。

早期版本的 SOA 使用面向对象的协议进行组件间通讯。例如，微软的 <ruby>   分布式组件对象模型  <rt>  Distributed Component Object Model </rt></ruby>（DCOM） 和使用 <ruby>   通用对象请求代理架构  <rt>  Common Object Request Broker Architecture </rt></ruby>（CORBA） 规范的 <ruby>   对象请求代理  <rt>  Object Request Broker </rt></ruby>（ORB）。

用于消息服务的最新的版本，有 <ruby>   Java 消息服务  <rt>  Java Message Service </rt></ruby>（JMS）或者 <ruby>   高级消息队列协议  <rt>  Advanced Message Queuing Protocol </rt></ruby>（AMQP）。这些服务通过<ruby> 企业服务总线 <rt>  Enterprise Service Bus </rt></ruby>（ESB） 进行连接。基于这些总线，来传递和接收可扩展标记语言（XML）格式的数据。

[微服务](http://microservices.io/) 是一个架构样式，其中的应用程序以松散耦合的服务或模块组成。它适用于开发大型的、复杂的应用程序的<ruby> 持续集成 <rt>  Continuous Integration </rt></ruby>/<ruby> 持续部署 <rt>  Continuous Deployment </rt></ruby>（CI/CD）模型。一个应用程序就是一堆模块的汇总。

每个微服务提供一个应用程序编程接口（API）端点。它们通过轻量级协议连接，比如，<ruby>   表述性状态转移  <rt>  REpresentational State Transfer </rt></ruby>（REST），或 [gRPC](https://grpc.io/)。数据倾向于使用 <ruby>   JavaScript 对象标记  <rt>  JavaScript Object Notation </rt></ruby>（JSON）或 [Protobuf](https://github.com/google/protobuf/) 来表示。

这两种架构都可以用于去替代以前老的整体式架构，整体式架构的应用程序被构建为单个的、自治的单元。例如，在一个客户机 —— 服务器模式中，一个典型的 Linux、Apache、MySQL、PHP/Python/Perl (LAMP) 服务器端应用程序将去处理 HTTP 请求、运行子程序、以及从底层的 MySQL 数据库中检索/更新数据。所有这些应用程序“绑”在一起提供服务。当你改变了任何一个东西，你都必须去构建和部署一个新版本。

使用 SOA，你可以只改变需要的几个组件，而不是整个应用程序。使用微服务，你可以做到一次只改变一个服务。使用微服务，你才能真正做到一个解耦架构。

微服务也比 SOA 更轻量级。不过 SOA 服务是部署到服务器和虚拟机上，而微服务是部署在容器中。协议也更轻量级。这使得微服务比 SOA 更灵活。因此，它更适合于要求敏捷性的电商网站。

说了这么多，到底意味着什么呢？微服务就是 SOA 在容器和云计算上的变种。

老式的 SOA 并没有离我们远去，而因为我们不断地将应用程序搬迁到容器中，所以微服务架构将越来越流行。

---

via: <https://blogs.dxc.technology/2018/05/08/everything-old-is-new-again-microservices/>

作者：[Cloudy Weather](https://blogs.dxc.technology/author/steven-vaughan-nichols/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


欧洲核子研究组织（CERN）是如何使用 Linux 和开源的

![CERN](/data/attachment/album/201808/11/073015p8ucw080sauuuu8c.jpg "CERN")

>
> 欧洲核子研究组织（简称 CERN）依靠开源技术处理大型强子对撞机生成的大量数据。ATLAS（超环面仪器，如图所示）是一种探测基本粒子的通用探测器。
>
>
>

[CERN](https://home.cern/) 无需过多介绍了吧。CERN 创建了<ruby> 万维网 <rt>  World Wide Web </rt></ruby>（WWW）和<ruby> 大型强子对撞机 <rt>  Large Hadron Collider </rt></ruby>（LHC），这是世界上最大的<ruby> 粒子加速器 <rt>  particle accelerator </rt></ruby>，就是通过它发现了 <ruby> <a href="https://home.cern/topics/higgs-boson">  希格斯玻色子 </a> <rt>  Higgs boson </rt></ruby>。负责该组织 IT 操作系统和基础架构的 Tim Bell 表示，他的团队的目标是“为全球 13000 名物理学家提供计算设施，以分析这些碰撞，了解宇宙的构成以及是如何运转的。”

CERN 正在进行硬核科学研究，尤其是大型强子对撞机，它在运行时 [生成大量数据](https://home.cern/about/computing)。“CERN 目前存储大约 200 PB 的数据，当加速器运行时，每月有超过 10 PB 的数据产生。这必然会给计算基础架构带来极大的挑战，包括存储大量数据，以及能够在合理的时间范围内处理数据，对于网络、存储技术和高效计算架构都是很大的压力。“Bell 说到。

![Tim Bell](/data/attachment/album/201808/11/073016iygy4e8eamdmam8m.png "Tim Bell")

*Tim Bell, CERN*

大型强子对撞机的运作规模和它产生的数据量带来了严峻的挑战，但 CERN 对这些问题并不陌生。CERN 成立于 1954 年，已经 60 余年了。“我们一直面临着难以解决的计算能力挑战，但我们一直在与开源社区合作解决这些问题。”Bell 说，“即使在 90 年代，当我们发明万维网时，我们也希望与人们共享，使其能够从 CERN 的研究中受益，开源是做这件事的再合适不过的工具了。”

### 使用 OpenStack 和 CentOS

时至今日，CERN 是 OpenStack 的深度用户，而 Bell 则是 OpenStack 基金会的董事会成员之一。不过 CERN 比 OpenStack 出现的要早，多年来，他们一直在使用各种开源技术通过 Linux 服务器提供服务。

“在过去的十年中，我们发现，与其自己解决问题，不如找到面临类似挑战的上游开源社区进行合作，然后我们一同为这些项目做出贡献，而不是一切都由自己来创造和维护。“Bell 说。

一个很好的例子是 Linux 本身。CERN 曾经是 Red Hat Enterprise Linux 的客户。其实，早在 2004 年，他们就与 Fermilab 合作一起建立了自己的 Linux 发行版，名为 [Scientific Linux](https://www.scientificlinux.org/)。最终他们意识到，因为没有修改内核，耗费时间建立自己的发行版是没有意义的，所以他们迁移到了 CentOS 上。由于 CentOS 是一个完全开源和社区驱使的项目，CERN 可以与该项目合作，并为 CentOS 的构建和分发做出贡献。

CERN 帮助 CentOS 提供基础架构，他们还组织了 CentOS DoJo 活动（LCTT 译者注：CentOS Dojo 是为期一日的活动，汇聚来自 CentOS 社群的人分享系统管理、最佳实践及新兴科技。），工程师可以汇聚在此共同改进 CentOS 的封装。

除了 OpenStack 和 CentOS 之外，CERN 还是其他开源项目的深度用户，包括用于配置管理的 Puppet、用于监控的 Grafana 和 InfluxDB，等等。

“我们与全球约 170 个实验室合作。因此，每当我们发现一个开源项目的改进之处，其他实验室便可以很容易地采纳使用。”Bell 说，“与此同时，我们也向其他项目学习。当像 eBay 和 Rackspace 这样大规模的装机量提高了解决方案的可扩展性时，我们也从中受益，也可以扩大规模。“

### 解决现实问题

2012 年左右，CERN 正在研究如何为大型强子对撞机扩展计算能力，但难点是人员而不是技术。CERN 雇用的员工人数是固定的。“我们必须找到一种方法来扩展计算能力，而不需要大量额外的人来管理。”Bell 说，“OpenStack 为我们提供了一个自动的 API 驱动和软件定义的基础架构。”OpenStack 还帮助 CERN 检查与服务交付相关的问题，然后使其自动化，而无需增加员工。

“我们目前在日内瓦和布达佩斯的两个数据中心运行大约 280000 个处理器核心和 7000 台服务器。我们正在使用软件定义的基础架构使一切自动化，这使我们能够在保持员工数量不变的同时继续添加更多的服务器。“Bell 说。

随着时间的推移，CERN 将面临更大的挑战。大型强子对撞机有一个到 2035 年的蓝图，包括一些重要的升级。“我们的加速器运转三到四年，然后会用 18 个月或两年的时间来升级基础架构。在这维护期间我们会做一些计算能力的规划。 ”Bell 说。CERN 还计划升级高亮度大型强子对撞机，会允许更高光度的光束。与目前的 CERN 的规模相比，升级意味着计算需求需增加约 60 倍。

“根据摩尔定律，我们可能只能满足需求的四分之一，因此我们必须找到相应的扩展计算能力和存储基础架构的方法，并找到自动化和解决方案，例如 OpenStack，将有助于此。”Bell 说。

“当我们开始使用大型强子对撞机并观察我们如何提供计算能力时，很明显我们无法将所有内容都放入 CERN 的数据中心，因此我们设计了一个分布式网格结构：位于中心的 CERN 和围绕着它的级联结构。”Bell 说，“全世界约有 12 个大型一级数据中心，然后是 150 所小型大学和实验室。他们从大型强子对撞机的数据中收集样本，以帮助物理学家理解和分析数据。”

这种结构意味着 CERN 正在进行国际合作，数百个国家正致力于分析这些数据。归结为一个基本原则，即开源不仅仅是共享代码，还包括人们之间的协作、知识共享，以实现个人、组织或公司无法单独实现的目标。这就是开源世界的希格斯玻色子。

---

via: <https://www.linux.com/blog/2018/5/how-cern-using-linux-open-source>

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

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


如何在 Linux 中使用 Fio 来测评硬盘性能

Summary: Fio（Flexible I/O Tester） 是一款由 Jens Axboe 开发的用于测评和压力/硬件验证的自由开源的软件。

![](/data/attachment/album/201808/11/111004tzk6ulvdvvvvvl86.jpg)

Fio（Flexible I/O Tester） 是一款由 Jens Axboe 开发的用于测评和压力/硬件验证的[自由开源](https://github.com/axboe/fio)的软件。

它支持 19 种不同类型的 I/O 引擎 (sync、mmap、libaio、posixaio、SG v3、splice、null、network、 syslet、guasi、solarisaio，以及更多)， I/O 优先级（针对较新的 Linux 内核），I/O 速度，fork 的任务或线程任务等等。它能够在块设备和文件上工作。

Fio 接受一种非常简单易于理解的文本格式的任务描述。软件默认包含了几个示例任务文件。 Fio 展示了所有类型的 I/O 性能信息，包括完整的 IO 延迟和百分比。

它被广泛的应用在非常多的地方，包括测评、QA，以及验证用途。它支持 Linux 、FreeBSD 、NetBSD、 OpenBSD、 OS X、 OpenSolaris、 AIX、 HP-UX、 Android 以及 Windows。

在这个教程，我们将使用 Ubuntu 16 ，你需要拥有这台电脑的 `sudo` 或 root 权限。我们将完整的进行安装和 Fio 的使用。

### 使用源码安装 Fio

我们要去克隆 GitHub 上的仓库。安装所需的依赖，然后我们将会从源码构建应用。首先，确保我们安装了 Git 。

```
sudo apt-get install git

```

CentOS 用户可以执行下述命令：

```
sudo yum install git

```

现在，我们切换到 `/opt` 目录，并从 Github 上克隆仓库：

```
cd /opt
git clone https://github.com/axboe/fio

```

你应该会看到下面这样的输出：

```
Cloning into 'fio'...
remote: Counting objects: 24819, done.
remote: Compressing objects: 100% (44/44), done.
remote: Total 24819 (delta 39), reused 62 (delta 32), pack-reused 24743
Receiving objects: 100% (24819/24819), 16.07 MiB | 0 bytes/s, done.
Resolving deltas: 100% (16251/16251), done.
Checking connectivity... done.

```

现在，我们通过在 `/opt` 目录下输入下方的命令切换到 Fio 的代码目录：

```
cd fio

```

最后，我们可以使用下面的命令来使用 `make` 从源码构建软件：

```
# ./configure
# make
# make install

```

### 在 Ubuntu 上安装 Fio

对于 Ubuntu 和 Debian 来说， Fio 已经在主仓库内。你可以很容易的使用类似 `yum` 和 `apt-get` 的标准包管理器来安装 Fio。

对于 Ubuntu 和 Debian ，你只需要简单的执行下述命令：

```
sudo apt-get install fio

```

对于 CentOS/Redhat 你只需要简单执行下述命令。

在 CentOS ，你可能在你能安装 Fio 前需要去安装 EPEL 仓库到你的系统中。你可以通过执行下述命令来安装它：

```
sudo yum install epel-release -y

```

你可以执行下述命令来安装 Fio：

```
sudo yum install fio -y

```

### 使用 Fio 进行磁盘性能测试

现在 Fio 已经安装到了你的系统中。现在是时候看一些如何使用 Fio 的例子了。我们将进行随机写、读和读写测试。

### 执行随机写测试

执行下面的命令来开始。这个命令将要同一时间执行两个进程，写入共计 4GB（ 4 个任务 x 512MB = 2GB） 文件：

```
sudo fio --name=randwrite --ioengine=libaio --iodepth=1 --rw=randwrite --bs=4k --direct=0 --size=512M --numjobs=2 --runtime=240 --group_reporting

```

```
...
fio-2.2.10
Starting 2 processes

randwrite: (groupid=0, jobs=2): err= 0: pid=7271: Sat Aug 5 13:28:44 2017
 write: io=1024.0MB, bw=2485.5MB/s, iops=636271, runt= 412msec
 slat (usec): min=1, max=268, avg= 1.79, stdev= 1.01
 clat (usec): min=0, max=13, avg= 0.20, stdev= 0.40
 lat (usec): min=1, max=268, avg= 2.03, stdev= 1.01
 clat percentiles (usec):
 | 1.00th=[ 0], 5.00th=[ 0], 10.00th=[ 0], 20.00th=[ 0],
 | 30.00th=[ 0], 40.00th=[ 0], 50.00th=[ 0], 60.00th=[ 0],
 | 70.00th=[ 0], 80.00th=[ 1], 90.00th=[ 1], 95.00th=[ 1],
 | 99.00th=[ 1], 99.50th=[ 1], 99.90th=[ 1], 99.95th=[ 1],
 | 99.99th=[ 1]
 lat (usec) : 2=99.99%, 4=0.01%, 10=0.01%, 20=0.01%
 cpu : usr=15.14%, sys=84.00%, ctx=8, majf=0, minf=26
 IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
 submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
 complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
 issued : total=r=0/w=262144/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
 latency : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
 WRITE: io=1024.0MB, aggrb=2485.5MB/s, minb=2485.5MB/s, maxb=2485.5MB/s, mint=412msec, maxt=412msec

Disk stats (read/write):
 sda: ios=0/0, merge=0/0, ticks=0/0, in_queue=0, util=0.00%

```

### 执行随机读测试

我们将要执行一个随机读测试，我们将会尝试读取一个随机的 2GB 文件。

```

sudo fio --name=randread --ioengine=libaio --iodepth=16 --rw=randread --bs=4k --direct=0 --size=512M --numjobs=4 --runtime=240 --group_reporting

```

你应该会看到下面这样的输出：

```
...
fio-2.2.10
Starting 4 processes
randread: Laying out IO file(s) (1 file(s) / 512MB)
randread: Laying out IO file(s) (1 file(s) / 512MB)
randread: Laying out IO file(s) (1 file(s) / 512MB)
randread: Laying out IO file(s) (1 file(s) / 512MB)
Jobs: 4 (f=4): [r(4)] [100.0% done] [71800KB/0KB/0KB /s] [17.1K/0/0 iops] [eta 00m:00s]
randread: (groupid=0, jobs=4): err= 0: pid=7586: Sat Aug 5 13:30:52 2017
 read : io=2048.0MB, bw=80719KB/s, iops=20179, runt= 25981msec
 slat (usec): min=72, max=10008, avg=195.79, stdev=94.72
 clat (usec): min=2, max=28811, avg=2971.96, stdev=760.33
 lat (usec): min=185, max=29080, avg=3167.96, stdev=798.91
 clat percentiles (usec):
 | 1.00th=[ 2192], 5.00th=[ 2448], 10.00th=[ 2576], 20.00th=[ 2736],
 | 30.00th=[ 2800], 40.00th=[ 2832], 50.00th=[ 2928], 60.00th=[ 3024],
 | 70.00th=[ 3120], 80.00th=[ 3184], 90.00th=[ 3248], 95.00th=[ 3312],
 | 99.00th=[ 3536], 99.50th=[ 6304], 99.90th=[15168], 99.95th=[18816],
 | 99.99th=[22912]
 bw (KB /s): min=17360, max=25144, per=25.05%, avg=20216.90, stdev=1605.65
 lat (usec) : 4=0.01%, 10=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
 lat (usec) : 1000=0.01%
 lat (msec) : 2=0.01%, 4=99.27%, 10=0.44%, 20=0.24%, 50=0.04%
 cpu : usr=1.35%, sys=5.18%, ctx=524309, majf=0, minf=98
 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=100.0%, 32=0.0%, >=64=0.0%
 submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
 complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0%
 issued : total=r=524288/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
 latency : target=0, window=0, percentile=100.00%, depth=16

Run status group 0 (all jobs):
 READ: io=2048.0MB, aggrb=80718KB/s, minb=80718KB/s, maxb=80718KB/s, mint=25981msec, maxt=25981msec

Disk stats (read/write):
 sda: ios=521587/871, merge=0/1142, ticks=96664/612, in_queue=97284, util=99.85%

```

最后，我们想要展示一个简单的随机读-写测试来看一看 Fio 返回的输出类型。

### 读写性能测试

下述命令将会测试 USB Pen 驱动器 (`/dev/sdc1`) 的随机读写性能：

```
sudo fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=random_read_write.fio --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75

```

下面的内容是我们从上面的命令得到的输出：

```
fio-2.2.10
Starting 1 process
Jobs: 1 (f=1): [m(1)] [100.0% done] [217.8MB/74452KB/0KB /s] [55.8K/18.7K/0 iops] [eta 00m:00s]
test: (groupid=0, jobs=1): err= 0: pid=8475: Sat Aug 5 13:36:04 2017
 read : io=3071.7MB, bw=219374KB/s, iops=54843, runt= 14338msec
 write: io=1024.4MB, bw=73156KB/s, iops=18289, runt= 14338msec
 cpu : usr=6.78%, sys=20.81%, ctx=1007218, majf=0, minf=9
 IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
 submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
 complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
 issued : total=r=786347/w=262229/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
 latency : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
 READ: io=3071.7MB, aggrb=219374KB/s, minb=219374KB/s, maxb=219374KB/s, mint=14338msec, maxt=14338msec
 WRITE: io=1024.4MB, aggrb=73156KB/s, minb=73156KB/s, maxb=73156KB/s, mint=14338msec, maxt=14338msec

Disk stats (read/write):
 sda: ios=774141/258944, merge=1463/899, ticks=748800/150316, in_queue=900720, util=99.35%

```

我们希望你能喜欢这个教程并且享受接下来的内容，Fio 是一个非常有用的工具，并且我们希望你能在你下一次 Debugging 活动中使用到它。如果你喜欢这个文章，欢迎留下评论和问题。

---

via: <https://wpmojo.com/how-to-use-fio-to-measure-disk-performance-in-linux/>

作者：[Alex Pearson](https://wpmojo.com/author/wpmojo/) 译者：[Bestony](https://github.com/bestony) 校对：[wxy](https://github.com/wxy)

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


比特币是一个邪教

Summary: 币之邪教（Cult of the Coin）有许多圣人，或许没有人比中本聪Satoshi Nakamoto更伟大，他是比特币创始者（们）的假名。

![](/data/attachment/album/201808/11/144815tqgsl6bjhfiwu66i.jpg)

经过这些年，比特币社区已经发生了非常大的变化；社区成员从闭着眼睛都能讲解 [梅克尔树](https://en.wikipedia.org/wiki/Merkle_tree) 的技术迷们，变成了被一夜爆富欲望驱使的投机者和由一些连什么是梅克尔树都不懂的人所领导的企图寻求 10 亿美元估值的区块链初创公司。随着时间的流逝，围绕比特币和其它加密货币形成了一股热潮，他们认为比特币和其它加密货币远比实际的更重要；他们相信常见的货币（法定货币）正在成为过去，而加密货币将从根本上改变世界经济。

每一年他们的队伍都在壮大，而他们对加密货币的看法也在变得更加宏伟，那怕是对该技术的[新奇的用法](https://hackernoon.com/how-crypto-kitties-disrupted-the-ethereum-network-845c22aa1e6e)而使它陷入了困境。虽然我坚信设计优良的加密货币可以使金钱的跨境流动更容易，并且在大规模通胀的领域提供一个更稳定的选择，但现实情况是，我们并没有做到这些。实际上，正是价值的巨大不稳定性才使得投机者赚钱。那些宣扬美元和欧元即将死去的人，已经完全抛弃了对现实世界客观公正的看法。

### 一点点背景 …

比特币发行那天，我读了它的白皮书 —— 它使用有趣的 [梅克尔树](https://en.wikipedia.org/wiki/Merkle_tree) 去创建一个公共账簿和一个非常合理的共识协议 —— 由于它新颖的特性引起了密码学领域中许多人的注意。在白皮书发布后的几年里，比特币变得非常有价值，并由此吸引了许多人将它视为是一种投资，和那些认为它将改变一切的忠实追随者（和发声者）。这篇文章将讨论的正是后者。

昨天（2018/6/20），有人在推特上发布了一个最近的比特币区块的哈希，下面成千上万的推文和其它讨论让我相信，比特币已经跨越界线进入了真正的邪教领域。

一切都源于 Mark Wilcox 的[这个推文](https://twitter.com/mwilcox/status/1009160832398262273?ref_src=twsrc%5Etfw)：

>
> [#00000000000000000021e800c1e8df51b22c1588e5a624bea17e9faa34b2dc4a](https://twitter.com/hashtag/00000000000000000021e800c1e8df51b22c1588e5a624bea17e9faa34b2dc4a?src=hash&ref_src=twsrc%5Etfw)
>
>
> — Mark Wilcox (@mwilcox) [June 19, 2018](https://twitter.com/mwilcox/status/1009160832398262273?ref_src=twsrc%5Etfw)
>
>
>

张贴的这个值是 [比特币 #528249 号区块](https://blockchain.info/block-height/528249) 的哈希值。前导零是挖矿过程的结果；挖掘一个区块就是把区块内容与一个<ruby> 现时数 <rt>  nonce </rt></ruby>（和其它数据）组合起来，然后做哈希运算，并且它至少有一定数量的前导零才能被验证为有效区块。如果它不是正确的数字，你可以更换现时数再试。重复这个过程直到哈希值的前导零数量是正确的数字之后，你就有了一个有效的区块。让人们感到很兴奋的部分是接下来的 `21e800`。

一些人说这是一个有意义的编号，挖掘出这个区块的人实际上的难度远远超出当前所看到的，不仅要调整前导零的数量，还要匹配接下来的 24 位 —— 它要求非常强大的计算能力。如果有人能够以蛮力去实现它，这将表明有些事情很严重，比如，在计算或密码学方面的重大突破。

你一定会有疑问，为什么 `21e800` 如此重要 —— 一个你问了肯定会后悔的问题。有人说它是参考了 [E8 理论](https://en.wikipedia.org/wiki/An_Exceptionally_Simple_Theory_of_Everything)（一个广受批评的提出标准场理论的论文），或是表示总共存在 2,100,000,000 枚比特币（`21 x 10^8` 就是 2,100,000,000）。还有其它说法，因为太疯狂了而没有办法写出来。另一个重要的事实是，在前导零后面有 21e8 的区块平均每年被挖掘出一次 —— 这些从来没有人认为是很重要的。

这就引出了有趣的地方：关于这是如何发生的[理论](https://medium.com/@coop__soup/00000000000000000021e800c1e8df51b22c1588e5a624bea17e9faa34b2dc4a-cd4b67d446be)。

* 一台量子计算机，它能以某种方式用不可思议的速度做哈希运算。尽管在量子计算机的理论中还没有迹象表明它能够做这件事。哈希是量子计算机认为安全的东西之一。
* 时间旅行。是的，真的有人这么说，有人从未来穿梭回到现在去挖掘这个区块。我认为这种说法太荒谬了，都懒得去解释它为什么是错误的。
* 中本聪回来了。尽管事实上他的私钥没有任何活动，一些人从理论上认为他回来了，他能做一些没人能做的事情。这些理论是无法解释他如何做到的。

>
> 因此，总的来说（按我的理解）中本聪，为了知道和计算他做的事情，根据现代科学，他可能是以下之一：
>
>
> A) 使用了一台量子计算机 B) 来自未来 C) 两者都是
>
>
> — Crypto Randy Marsh [REKT](@nondualrandy) [June 21, 2018](https://twitter.com/nondualrandy/status/1009609117768605696?ref_src=twsrc%5Etfw)
>
>
>

如果你觉得所有的这一切听起来像 <ruby> <a href="https://en.wikipedia.org/wiki/Numerology">  命理学 </a> <rt>  numerology </rt></ruby>，不止你一个人是这样想的。

所有围绕有特殊意义的区块哈希的讨论，也引发了对在某种程度上比较有趣的东西的讨论。比特币的创世区块，它是第一个比特币区块，有一个不寻常的属性：早期的比特币要求哈希值的前 32 <ruby> 位 <rt>  bit </rt></ruby>是零；而创始区块的前导零有 43 位。因为产生创世区块的代码从未发布过，不知道它是如何产生的，也不知道是用什么类型的硬件产生的。中本聪有学术背景，因此可能他有比那个时候大学中常见设备更强大的计算能力。从这一点上说，只是对古怪的创世区块的历史有点好奇，仅此而已。

### 关于哈希运算的简单题外话

这种喧嚣始于比特币区块的哈希运算；因此理解哈希是什么很重要，并且要理解一个非常重要的属性，哈希是单向加密函数，它能够基于给定的数据创建一个伪随机输出。

这意味着什么呢？基于本文讨论的目的，对于每个给定的输入你将得到一个随机的输出。随机数有时看起来很有趣，很简单，因为它是随机的结果，并且人类大脑可以很容易从任何东西中找到顺序。当你从随机数据中开始查看顺序时，你就会发现有趣的事情 —— 这些东西毫无意义，因为它们只是简单地随机数。当人们把重要的意义归属到随机数据上时，它将告诉你很多这些参与者观念相关的东西，而不是数据本身。

### 币之邪教

首先，我们来定义一组术语：

* <ruby> 邪教 <rt>  Cult </rt></ruby>：一个宗教崇拜和直接向一个特定的人或物虔诚的体系。
* <ruby> 宗教 <rt>  Religion </rt></ruby>：有人认为是至高无上的追求或兴趣。

<ruby> 币之邪教 <rt>  Cult of the Coin </rt></ruby>有许多圣人，或许没有人比<ruby> 中本聪 <rt>  Satoshi Nakamoto </rt></ruby>更伟大，他是比特币创始者（们）的假名。（对他的）狂热拥戴，要归因于他的能力和理解力远超过一般的研究人员，认为他的远见卓视无人能比，他影响了世界新经济的秩序。当将中本聪的神秘本质和未知的真实身份结合起来时，狂热的追随着们将中本聪视为一个真正值得尊敬的人物。

当然，除了追随其他圣人的追捧者之外，毫无疑问这些追捧者认为自己是正确的。任何对他们的圣人的批评都被认为也是对他们的批评。例如，那些追捧 EOS 的人，可能会视中本聪为一个开发了失败项目的黑客，而对 EOS 那怕是最轻微的批评，他们也会作出激烈的反应，之所以反应如此强烈，仅仅是因为攻击了他们心目中的神。那些追捧 IOTA 的人的反应也一样；还有更多这样的例子。

这些追随者在讨论问题时已经失去了理性和客观，他们的狂热遮盖了他们的视野。任何对这些项目和项目背后的人的讨论，如果不是溢美之词，必然以某种程序的刻薄言辞结束，对于一个技术的讨论那种做法是毫无道理的。

这很危险，原因很多：

* 开发者 & 研究者对缺陷视而不见。由于追捧者的大量赞美，这些参与开发的人对自己的能力的看法开始膨胀，并将一些批评看作是无端的攻击 —— 因为他们认为自己是不可能错的。
* 真正的问题是被攻击。技术问题不再被看作是需要去解决的问题和改进的机会，他们认为是来自那些想去破坏项目的人的攻击。
* 物以类聚，人以币分。追随者们通常会结盟到一起，而圣人仅有一个。承认其它项目的优越，意味着认同自己项目的缺陷或不足，而这是他们不愿意做的事情。
* 阻止真实的进步。进化是很残酷的，死亡是必然会有的，项目可能失败，也要承认这些失败的原因。如果忽视失败的教训，如果不允许那些应该去死亡的事情发生，进步就会停止。

许多围绕加密货币和相关区块链项目的讨论已经开始变得越来越”有毒“，善意的人想在不受攻击的情况下进行技术性讨论越来越不可能。随着对真正缺陷的讨论，那些在其它环境中注定要失败的缺陷，在没有做任何的事实分析的情况下即刻被判定为异端已经成为了惯例，善意的人参与其中的代价变得极其昂贵。至少有些人已经意识到极其严重的安全漏洞，由于高“毒性”的环境，他们选择保持沉默。

曾经被好奇、学习和改进的期望、创意可行性所驱动的东西，现在被盲目的贪婪、宗教般的狂热、自以为是和自我膨胀所驱动。

我对受这种狂热激励的项目的未来不抱太多的希望，而它持续地传播，可能会损害多年来在这个领域中真正的研究者。这些技术项目中，一些项目成功了，一些项目失败了 —— 这就是技术演进的方式。设计这些系统的人，就和你我一样都有缺点，同样这些项目也有缺陷。有些项目非常适合某些使用场景而不适合其它场景，有些项目不适合任何使用场景，没有一个项目适合所有使用场景。关于这些项目的讨论应该关注于技术方面，这样做是为了让这一研究领域得以发展；在这些项目中掺杂宗教般狂热必将损害所有人。

[注意：这种行为有许多例子可以引用，但是为了保护那些因批评项目而成为被攻击目标的人，我选择尽可能少的列出这种例子。我看到许多我很尊敬的人、许多我认为是朋友的人成为这种恶毒攻击的受害者 —— 我不想引起人们对这些攻击的注意和重新引起对他们的攻击。]

（题图：news.bitcoin.com）

---

关于作者：

我是一个资深应用安全顾问、研究员和具有超过 15 年的经验的软件开发者。我主要关注的是应用程序安全、安全通信和加密, 虽然我经常由于无聊而去研究新的领域。我通常会写了一些关于我的研究和安全、开发和软件设计，和我当前吸引了我注意力的爱好的文章。

---

via: <https://adamcaudill.com/2018/06/21/bitcoin-is-a-cult/>

作者：[Adam Caudill](https://adamcaudill.com/author/adam/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


CSRF（跨站请求伪造）简介

Summary: 设计 Web 程序时，安全性是一个主要问题。我不是在谈论 DDoS 保护、使用强密码或两步验证。我说的是对网络程序的最大威胁。它被称为CSRF, 是 Cross Site Request Forgery （跨站请求伪造）的缩写。

![](/data/attachment/album/201808/13/083832posuqdwbxf8hszdl.jpg)

设计 Web 程序时，安全性是一个主要问题。我不是在谈论 DDoS 保护、使用强密码或两步验证。我说的是对网络程序的最大威胁。它被称为 **CSRF**, 是 **Cross Site Request Forgery** （跨站请求伪造）的缩写。

### 什么是 CSRF？

[![csrf what is cross site forgery](/data/attachment/album/201808/13/083832wgqw4ku1t8pt7pku.jpg)](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/csrf-what-is-cross-site-forgery_orig.jpg)

首先，**CSRF** 是 Cross Site Request Forgery 的缩写。它通常发音为 “sea-surf”，也经常被称为 XSRF。CSRF 是一种攻击类型，在受害者不知情的情况下，在受害者登录的 Web 程序上执行各种操作。这些行为可以是任何事情，从简单地点赞或评论社交媒体帖子到向人们发送垃圾消息，甚至从受害者的银行账户转移资金。

### CSRF 如何工作？

**CSRF** 攻击尝试利用所有浏览器上的一个简单的常见漏洞。每次我们对网站进行身份验证或登录时，会话 cookie 都会存储在浏览器中。因此，每当我们向网站提出请求时，这些 cookie 就会自动发送到服务器，服务器通过匹配与服务器记录一起发送的 cookie 来识别我们。这样就知道是我们了。

[![cookies set by website chrome](/data/attachment/album/201808/13/083832q88w7bu44phknmsw.jpg)](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/cookies-set-by-website-chrome_orig.jpg)

这意味着我将在知情或不知情的情况下发出请求。由于 cookie 也被发送并且它们将匹配服务器上的记录，服务器认为我在发出该请求。  CSRF 攻击通常以链接的形式出现。我们可以在其他网站上点击它们或通过电子邮件接收它们。单击这些链接时，会向服务器发出不需要的请求。正如我之前所说，服务器认为我们发出了请求并对其进行了身份验证。

#### 一个真实世界的例子

为了把事情看得更深入，想象一下你已登录银行的网站。并在 **yourbank.com/transfer** 上填写表格。你将接收者的帐号填写为 1234，填入金额 5,000 并单击提交按钮。现在，我们将有一个 **yourbank.com/transfer/send?to=1234&amount=5000** 的请求。因此服务器将根据请求进行操作并转账。现在想象一下你在另一个网站上，然后点击一个链接，用黑客的帐号作为参数打开上面的 URL。这笔钱现在会转账给黑客，服务器认为你做了交易。即使你没有。

[![csrf hacking bank account](/data/attachment/album/201808/13/083832zrxck6kxchh66d5i.jpg)](http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/csrf-hacking-bank-account_orig.jpg)

#### CSRF 防护

CSRF 防护非常容易实现。它通常将一个称为 CSRF 令牌的令牌发送到网页。每次发出新请求时，都会发送并验证此令牌。因此，向服务器发出的恶意请求将通过 cookie 身份验证，但 CSRF 验证会失败。大多数 Web 框架为防止 CSRF 攻击提供了开箱即用的支持，而 CSRF 攻击现在并不像以前那样常见。

### 总结

CSRF 攻击在 10 年前是一件大事，但如今我们看不到太多。过去，Youtube、纽约时报和 Netflix 等知名网站都容易受到 CSRF 的攻击。然而，CSRF 攻击的普遍性和发生率最近有减少。尽管如此，CSRF 攻击仍然是一种威胁，重要的是，你要保护自己的网站或程序免受攻击。

---

via: <http://www.linuxandubuntu.com/home/understanding-csrf-cross-site-request-forgery>

作者：[linuxandubuntu](http://www.linuxandubuntu.com) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


如何在 Git 中重置、恢复，返回到以前的状态

Summary: 用简洁而优雅的 Git 命令撤销仓库中的改变。

用简洁而优雅的 Git 命令撤销仓库中的改变。

>
> 用简洁而优雅的 Git 命令撤销仓库中的改变。
>
>
>

![](/data/attachment/album/201808/13/092329hgipv16hvunpiqng.jpg)

使用 Git 工作时其中一个鲜为人知（和没有意识到）的方面就是，如何轻松地返回到你以前的位置 —— 也就是说，在仓库中如何很容易地去撤销那怕是重大的变更。在本文中，我们将带你了解如何去重置、恢复和完全回到以前的状态，做到这些只需要几个简单而优雅的 Git 命令。

### 重置

我们从 Git 的 `reset` 命令开始。确实，你应该能够认为它就是一个 “回滚” —— 它将你本地环境返回到之前的提交。这里的 “本地环境” 一词，我们指的是你的本地仓库、暂存区以及工作目录。

先看一下图 1。在这里我们有一个在 Git 中表示一系列提交的示意图。在 Git 中一个分支简单来说就是一个命名的、指向一个特定的提交的可移动指针。在这里，我们的 master 分支是指向链中最新提交的一个指针。

![Local Git environment with repository, staging area, and working directory](/data/attachment/album/201808/13/092340zeqpc29hoz66c7f2.png "Local Git environment with repository, staging area, and working directory")

*图 1：有仓库、暂存区、和工作目录的本地环境*

如果看一下我们的 master 分支是什么，可以看一下到目前为止我们产生的提交链。

```
$ git log --oneline
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line

```

如果我们想回滚到前一个提交会发生什么呢？很简单 —— 我们只需要移动分支指针即可。Git 提供了为我们做这个动作的 `reset` 命令。例如，如果我们重置 master 为当前提交回退两个提交的位置，我们可以使用如下之一的方法：

```
$ git reset 9ef9173

```

（使用一个绝对的提交 SHA1 值 `9ef9173`）

或：

```
$ git reset current~2

```

（在 “current” 标签之前，使用一个相对值 -2）

图 2 展示了操作的结果。在这之后，如果我们在当前分支（master）上运行一个 `git log` 命令，我们将看到只有一个提交。

```
$ git log --oneline

9ef9173 File with one line

```

![After reset](/data/attachment/album/201808/13/092345d5ljjolboajc9obn.png "After reset")

*图 2：在 `reset` 之后*

`git reset` 命令也包含使用一些选项，可以让你最终满意的提交内容去更新本地环境的其它部分。这些选项包括：`hard` 在仓库中去重置指向的提交，用提交的内容去填充工作目录，并重置暂存区；`soft` 仅重置仓库中的指针；而 `mixed`（默认值）将重置指针和暂存区。

这些选项在特定情况下非常有用，比如，`git reset --hard <commit sha1 | reference>` 这个命令将覆盖本地任何未提交的更改。实际上，它重置了（清除掉）暂存区，并用你重置的提交内容去覆盖了工作区中的内容。在你使用 `hard` 选项之前，一定要确保这是你真正地想要做的操作，因为这个命令会覆盖掉任何未提交的更改。

### 恢复

`git revert` 命令的实际结果类似于 `reset`，但它的方法不同。`reset` 命令（默认）是在链中向后移动分支的指针去“撤销”更改，`revert` 命令是在链中添加一个新的提交去“取消”更改。再次查看图 1 可以非常轻松地看到这种影响。如果我们在链中的每个提交中向文件添加一行，一种方法是使用 `reset` 使那个提交返回到仅有两行的那个版本，如：`git reset HEAD~1`。

另一个方法是添加一个新的提交去删除第三行，以使最终结束变成两行的版本 —— 实际效果也是取消了那个更改。使用一个 `git revert` 命令可以实现上述目的，比如：

```
$ git revert HEAD

```

因为它添加了一个新的提交，Git 将提示如下的提交信息：

```
Revert "File with three lines"

This reverts commit b764644bad524b804577684bf74e7bca3117f554.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#       modified:   file1.txt
#

```

图 3（在下面）展示了 `revert` 操作完成后的结果。

如果我们现在运行一个 `git log` 命令，我们将看到前面的提交之前的一个新提交。

```
$ git log --oneline
11b7712 Revert "File with three lines"
b764644 File with three lines
7c709f0 File with two lines
9ef9173 File with one line

```

这里是工作目录中这个文件当前的内容：

```
$ cat <filename>
Line 1
Line 2

```

![img](/data/attachment/album/201808/13/092413unln6dzhu1lzv9nu.png)

*图 3 `revert` 操作之后*

### 恢复或重置如何选择？

为什么要优先选择 `revert` 而不是 `reset` 操作？如果你已经将你的提交链推送到远程仓库（其它人可以已经拉取了你的代码并开始工作），一个 `revert` 操作是让他们去获得更改的非常友好的方式。这是因为 Git 工作流可以非常好地在分支的末端添加提交，但是当有人 `reset` 分支指针之后，一组提交将再也看不见了，这可能会是一个挑战。

当我们以这种方式使用 Git 工作时，我们的基本规则之一是：在你的本地仓库中使用这种方式去更改还没有推送的代码是可以的。如果提交已经推送到了远程仓库，并且可能其它人已经使用它来工作了，那么应该避免这些重写提交历史的更改。

总之，如果你想回滚、撤销或者重写其它人已经在使用的一个提交链的历史，当你的同事试图将他们的更改合并到他们拉取的原始链上时，他们可能需要做更多的工作。如果你必须对已经推送并被其他人正在使用的代码做更改，在你做更改之前必须要与他们沟通，让他们先合并他们的更改。然后在这个侵入操作没有需要合并的内容之后，他们再拉取最新的副本。

你可能注意到了，在我们做了 `reset` 操作之后，原始的提交链仍然在那个位置。我们移动了指针，然后 `reset` 代码回到前一个提交，但它并没有删除任何提交。换句话说就是，只要我们知道我们所指向的原始提交，我们能够通过简单的返回到分支的原始链的头部来“恢复”指针到前面的位置：

```
git reset <sha1 of commit>

```

当提交被替换之后，我们在 Git 中做的大量其它操作也会发生类似的事情。新提交被创建，有关的指针被移动到一个新的链，但是老的提交链仍然存在。

### 变基

现在我们来看一个分支变基。假设我们有两个分支：master 和 feature，提交链如下图 4 所示。master 的提交链是 `C4->C2->C1->C0` 和 feature 的提交链是 `C5->C3->C2->C1->C0`。

![Chain of commits for branches master and feature](/data/attachment/album/201808/13/092420b5yachh5yykpuacy.png "Chain of commits for branches master and feature")

*图 4：master 和 feature 分支的提交链*

如果我们在分支中看它的提交记录，它们看起来应该像下面的这样。（为了易于理解，`C` 表示提交信息）

```
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

```

我告诉人们在 Git 中，可以将 `rebase` 认为是 “将历史合并”。从本质上来说，Git 将一个分支中的每个不同提交尝试“重放”到另一个分支中。

因此，我们使用基本的 Git 命令，可以变基一个 feature 分支进入到 master 中，并将它拼入到 `C4` 中（比如，将它插入到 feature 的链中）。操作命令如下：

```
$ git checkout feature
$ git rebase master

First, rewinding head to replay your work on top of it...
Applying: C3
Applying: C5

```

完成以后，我们的提交链将变成如下图 5 的样子。

![Chain of commits after the rebase command](/data/attachment/album/201808/13/092427dm1ve2vrz95vv58c.png "Chain of commits after the rebase command")

*图 5：`rebase` 命令完成后的提交链*

接着，我们看一下提交历史，它应该变成如下的样子。

```
$ git log --oneline master
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

$ git log --oneline feature
c4533a5 C5
64f2047 C3
6a92e7a C4
259bf36 C2
f33ae68 C1
5043e79 C0

```

注意那个 `C3'` 和 `C5'`— 在 master 分支上已处于提交链的“顶部”，由于产生了更改而创建了新提交。但是也要注意的是，rebase 后“原始的” `C3` 和 `C5` 仍然在那里 — 只是再没有一个分支指向它们而已。

如果我们做了这个变基，然后确定这不是我们想要的结果，希望去撤销它，我们可以做下面示例所做的操作：

```
$ git reset 79768b8

```

由于这个简单的变更，现在我们的分支将重新指向到做 `rebase` 操作之前一模一样的位置 —— 完全等效于撤销操作（图 6）。

![After undoing rebase](/data/attachment/album/201808/13/092435xitucz90inn987k7.png "After undoing rebase")

*图 6：撤销 `rebase` 操作之后*

如果你想不起来之前一个操作指向的一个分支上提交了什么内容怎么办？幸运的是，Git 命令依然可以帮助你。用这种方式可以修改大多数操作的指针，Git 会记住你的原始提交。事实上，它是在 `.git` 仓库目录下，将它保存为一个特定的名为 `ORIG_HEAD` 的文件中。在它被修改之前，那个路径是一个包含了大多数最新引用的文件。如果我们 `cat` 这个文件，我们可以看到它的内容。

```
$ cat .git/ORIG_HEAD
79768b891f47ce06f13456a7e222536ee47ad2fe

```

我们可以使用 `reset` 命令，正如前面所述，它返回指向到原始的链。然后它的历史将是如下的这样：

```
$ git log --oneline feature
79768b8 C5
000f9ae C3
259bf36 C2
f33ae68 C1
5043e79 C0

```

在 reflog 中是获取这些信息的另外一个地方。reflog 是你本地仓库中相关切换或更改的详细描述清单。你可以使用 `git reflog` 命令去查看它的内容：

```
$ git reflog
79768b8 HEAD@{0}: reset: moving to 79768b
c4533a5 HEAD@{1}: rebase finished: returning to refs/heads/feature
c4533a5 HEAD@{2}: rebase: C5
64f2047 HEAD@{3}: rebase: C3
6a92e7a HEAD@{4}: rebase: checkout master
79768b8 HEAD@{5}: checkout: moving from feature to feature
79768b8 HEAD@{6}: commit: C5
000f9ae HEAD@{7}: checkout: moving from master to feature
6a92e7a HEAD@{8}: commit: C4
259bf36 HEAD@{9}: checkout: moving from feature to master
000f9ae HEAD@{10}: commit: C3
259bf36 HEAD@{11}: checkout: moving from master to feature
259bf36 HEAD@{12}: commit: C2
f33ae68 HEAD@{13}: commit: C1
5043e79 HEAD@{14}: commit (initial): C0

```

你可以使用日志中列出的、你看到的相关命名格式，去重置任何一个东西：

```
$ git reset HEAD@{1}

```

一旦你理解了当“修改”链的操作发生后，Git 是如何跟踪原始提交链的基本原理，那么在 Git 中做一些更改将不再是那么可怕的事。这就是强大的 Git 的核心能力之一：能够很快速、很容易地尝试任何事情，并且如果不成功就撤销它们。

---

via: <https://opensource.com/article/18/6/git-reset-revert-rebase-commands>

作者：[Brent Laster](https://opensource.com/users/bclaster) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


如何在 Linux 上使用 pbcopy 和 pbpaste 命令

Summary: pbcopy 命令将标准输入复制到剪贴板。然后，你可以在任何地方使用 pbpaste 命令粘贴剪贴板内容。

![](/data/attachment/album/201808/14/092631ugqj2klqnj8n2lp4.png)

由于 Linux 和 Mac OS X 是基于 \*Nix 的系统，因此许多命令可以在两个平台上运行。但是，某些命令可能在两个平台上都没有，比如 `pbcopy` 和 `pbpast`。这些命令仅在 Mac OS X 平台上可用。`pbcopy` 命令将标准输入复制到剪贴板。然后，你可以在任何地方使用 `pbpaste` 命令粘贴剪贴板内容。当然，上述命令可能有一些 Linux 替代品，例如 `xclip`。 `xclip` 与 `pbcopy` 完全相同。但是，从 Mac OS 切换到 Linux 的发行版的人将会找不到这两个命令，不过仍然想使用它们。别担心！这个简短的教程描述了如何在 Linux 上使用 `pbcopy` 和 `pbpaste` 命令。

### 安装 xclip / xsel

就像我已经说过的那样，Linux 中没有 `pbcopy` 和 `pbpaste` 命令。但是，我们可以通过 shell 别名使用 xclip 和/或 xsel 命令复制 `pbcopy` 和 `pbpaste` 命令的功能。xclip 和 xsel 包存在于大多数 Linux 发行版的默认存储库中。请注意，你无需安装这两个程序。只需安装上述任何一个程序即可。

要在 Arch Linux 及其衍生产版上安装它们，请运行：

```
$ sudo pacman xclip xsel

```

在 Fedora 上：

```
$ sudo dnf xclip xsel

```

在 Debian、Ubuntu、Linux Mint 上：

```
$ sudo apt install xclip xsel

```

安装后，你需要为 `pbcopy` 和 `pbpaste` 命令创建别名。为此，请编辑 `~/.bashrc`：

```
$ vi ~/.bashrc

```

如果要使用 xclip，请粘贴以下行：

```
alias pbcopy='xclip -selection clipboard'
alias pbpaste='xclip -selection clipboard -o'

```

如果要使用 xsel，请在 `~/.bashrc` 中粘贴以下行。

```
alias pbcopy='xsel --clipboard --input'
alias pbpaste='xsel --clipboard --output'

```

保存并关闭文件。

接下来，运行以下命令以更新 `~/.bashrc` 中的更改。

```
$ source ~/.bashrc

```

ZSH 用户将上述行粘贴到 `~/.zshrc` 中。

### 在 Linux 上使用 pbcopy 和 pbpaste 命令

让我们看一些例子。

`pbcopy` 命令将文本从 stdin 复制到剪贴板缓冲区。例如，看看下面的例子。

```
$ echo "Welcome To OSTechNix!" | pbcopy

```

上面的命令会将文本 “Welcome to OSTechNix” 复制到剪贴板中。你可以稍后访问此内容并使用如下所示的 `pbpaste` 命令将其粘贴到任何位置。

```
$ echo `pbpaste`
Welcome To OSTechNix!

```

![](/data/attachment/album/201808/14/092632tl5uau5sza5mm3as.png)

以下是一些其他例子。

我有一个名为 `file.txt` 的文件，其中包含以下内容。

```
$ cat file.txt
Welcome To OSTechNix!

```

你可以直接将文件内容复制到剪贴板中，如下所示。

```
$ pbcopy < file.txt

```

现在，只要你用其他文件的内容更新了剪切板，那么剪切板中的内容就可用了。

要从剪贴板检索内容，只需输入：

```
$ pbpaste
Welcome To OSTechNix!

```

你还可以使用管道字符将任何 Linux 命令的输出发送到剪贴板。看看下面的例子。

```
$ ps aux | pbcopy

```

现在，输入 `pbpaste` 命令以显示剪贴板中 `ps aux` 命令的输出。

```
$ pbpaste

```

![](/data/attachment/album/201808/14/092633obkgk1bvkekk15wg.png)

使用 `pbcopy` 和 `pbpaste` 命令可以做更多的事情。我希望你现在对这些命令有一个基本的想法。

就是这些了。还有更好的东西。敬请关注！

干杯!

---

via: <https://www.ostechnix.com/how-to-use-pbcopy-and-pbpaste-commands-on-linux/>

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

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


如何查看 Linux 中所有正在运行的服务

Summary: 有许多方法和工具可以查看 Linux 中所有正在运行的服务。

有许多方法和工具可以查看 Linux 中所有正在运行的服务。

![](/data/attachment/album/201808/14/100502f0es3ysz3e0ekeyi.jpg)

有许多方法和工具可以查看 Linux 中所有正在运行的服务。大多数管理员会在 System V（SysV）初始化系统中使用 `service service-name status` 或 `/etc/init.d/service-name status`，而在 systemd 初始化系统中使用 `systemctl status service-name`。

以上命令可以清楚地显示该服务是否在服务器上运行，这也是每个 Linux 管理员都该知道的非常简单和基础的命令。

如果你对系统环境并不熟悉，也不清楚系统在运行哪些服务，你会如何检查？

是的，我们的确有必要这样检查一下。这将有助于我们了解系统上运行了什么服务，以及哪些是必要的、哪些需要被禁用。

init（<ruby> 初始化 <rt>  initialization </rt></ruby>的简称）是在系统启动期间运行的第一个进程。`init` 是一个守护进程，它将持续运行直至关机。

大多数 Linux 发行版都使用如下的初始化系统之一：

* System V 是更老的初始化系统
* Upstart 是一个基于事件的传统的初始化系统的替代品
* systemd 是新的初始化系统，它已经被大多数最新的 Linux 发行版所采用

### 什么是 System V（SysV）

SysV（意即 System V） 初始化系统是早期传统的初始化系统和系统管理器。由于 sysVinit 系统上一些长期悬而未决的问题，大多数最新的发行版都适用于 systemd 系统。

### 什么是 Upstart 初始化系统

Upstart 是一个基于事件的 /sbin/init 的替代品，它控制在启动时的任务和服务的开始，在关机时停止它们，并在系统运行时监控它们。

它最初是为 Ubuntu 发行版开发的，但其是以适合所有 Linux 发行版的开发为目标的，以替换过时的 System-V 初始化系统。

### 什么是 systemd

systemd 是一个新的初始化系统以及系统管理器，它已成为大多数 Linux 发行版中非常流行且广泛适应的新的标准初始化系统。`systemctl` 是一个 systemd 管理工具，它可以帮助我们管理 systemd 系统。

### 方法一：如何在 System V（SysV）系统中查看运行的服务

以下命令可以帮助我们列出 System V（SysV） 系统中所有正在运行的服务。

如果服务很多，我建议使用文件查看命令，如 `less`、`more` 等，以便得到清晰的结果。

```
# service --status-all
或
# service --status-all | more
或
# service --status-all | less

```

```
abrt-ccpp hook is installed
abrtd (pid  2131) is running...
abrt-dump-oops is stopped
acpid (pid  1958) is running...
atd (pid  2164) is running...
auditd (pid  1731) is running...
Frequency scaling enabled using ondemand governor
crond (pid  2153) is running...
hald (pid  1967) is running...
htcacheclean is stopped
httpd is stopped
Table: filter
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     all      ::/0                 ::/0                state RELATED,ESTABLISHED
2    ACCEPT     icmpv6    ::/0                 ::/0
3    ACCEPT     all      ::/0                 ::/0
4    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:80
5    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:21
6    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:22
7    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:25
8    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:2082
9    ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:2086
10   ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:2083
11   ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:2087
12   ACCEPT     tcp      ::/0                 ::/0                state NEW tcp dpt:10000
13   REJECT     all      ::/0                 ::/0                reject-with icmp6-adm-prohibited

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination
1    REJECT     all      ::/0                 ::/0                reject-with icmp6-adm-prohibited

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

iptables: Firewall is not running.
irqbalance (pid 1826) is running...
Kdump is operational
lvmetad is stopped
mdmonitor is stopped
messagebus (pid  1929) is running...
 SUCCESS! MySQL running (24376)
rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
named is stopped
netconsole module not loaded
Usage: startup.sh { start | stop }
Configured devices:
lo eth0 eth1
Currently active devices:
lo eth0
ntpd is stopped
portreserve (pid  1749) is running...
master (pid  2107) is running...
Process accounting is disabled.
quota_nld is stopped
rdisc is stopped
rngd is stopped
rpcbind (pid  1840) is running...
rsyslogd (pid  1756) is running...
sandbox is stopped
saslauthd is stopped
smartd is stopped
openssh-daemon (pid  9859) is running...
svnserve is stopped
vsftpd (pid 4008) is running...
xinetd (pid  2031) is running...
zabbix_agentd (pid 2150 2149 2148 2147 2146 2140) is running...

```

执行以下命令，可以只查看正在运行的服务：

```
# service --status-all | grep running

```

```
crond (pid 535) is running...
httpd (pid 627) is running...
mysqld (pid 911) is running...
rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
rsyslogd (pid 449) is running...
saslauthd (pid 492) is running...
sendmail (pid 509) is running...
sm-client (pid 519) is running...
openssh-daemon (pid 478) is running...
xinetd (pid 485) is running...

```

运行以下命令以查看指定服务的状态：

```
# service --status-all | grep httpd
httpd (pid 627) is running...

```

或者，使用以下命令也可以查看指定服务的状态：

```
# service httpd status
httpd (pid 627) is running...

```

使用以下命令查看系统启动时哪些服务会被启用：

```
# chkconfig --list

```

```
crond           0:off   1:off   2:on    3:on    4:on    5:on    6:off
htcacheclean    0:off   1:off   2:off   3:off   4:off   5:off   6:off
httpd           0:off   1:off   2:off   3:on    4:off   5:off   6:off
ip6tables       0:off   1:off   2:on    3:off   4:on    5:on    6:off
iptables        0:off   1:off   2:on    3:on    4:on    5:on    6:off
modules_dep     0:off   1:off   2:on    3:on    4:on    5:on    6:off
mysqld          0:off   1:off   2:on    3:on    4:on    5:on    6:off
named           0:off   1:off   2:off   3:off   4:off   5:off   6:off
netconsole      0:off   1:off   2:off   3:off   4:off   5:off   6:off
netfs           0:off   1:off   2:off   3:off   4:on    5:on    6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off
nmb             0:off   1:off   2:off   3:off   4:off   5:off   6:off
nscd            0:off   1:off   2:off   3:off   4:off   5:off   6:off
portreserve     0:off   1:off   2:on    3:off   4:on    5:on    6:off
quota_nld       0:off   1:off   2:off   3:off   4:off   5:off   6:off
rdisc           0:off   1:off   2:off   3:off   4:off   5:off   6:off
restorecond     0:off   1:off   2:off   3:off   4:off   5:off   6:off
rpcbind         0:off   1:off   2:on    3:off   4:on    5:on    6:off
rsyslog         0:off   1:off   2:on    3:on    4:on    5:on    6:off
saslauthd       0:off   1:off   2:off   3:on    4:off   5:off   6:off
sendmail        0:off   1:off   2:on    3:on    4:on    5:on    6:off
smb             0:off   1:off   2:off   3:off   4:off   5:off   6:off
snmpd           0:off   1:off   2:off   3:off   4:off   5:off   6:off
snmptrapd       0:off   1:off   2:off   3:off   4:off   5:off   6:off
sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
udev-post       0:off   1:on    2:on    3:off   4:on    5:on    6:off
winbind         0:off   1:off   2:off   3:off   4:off   5:off   6:off
xinetd          0:off   1:off   2:off   3:on    4:on    5:on    6:off

xinetd based services:
        chargen-dgram:  off
        chargen-stream: off
        daytime-dgram:  off
        daytime-stream: off
        discard-dgram:  off
        discard-stream: off
        echo-dgram:     off
        echo-stream:    off
        finger:         off
        ntalk:          off
        rsync:          off
        talk:           off
        tcpmux-server:  off
        time-dgram:     off
        time-stream:    off

```

### 方法二：如何在 System V（SysV）系统中查看运行的服务

另外一种在 Linux 系统上列出运行的服务的方法是使用 initctl 命令：

```
# initctl list
rc stop/waiting
tty (/dev/tty3) start/running, process 1740
tty (/dev/tty2) start/running, process 1738
tty (/dev/tty1) start/running, process 1736
tty (/dev/tty6) start/running, process 1746
tty (/dev/tty5) start/running, process 1744
tty (/dev/tty4) start/running, process 1742
plymouth-shutdown stop/waiting
control-alt-delete stop/waiting
rcS-emergency stop/waiting
readahead-collector stop/waiting
kexec-disable stop/waiting
quit-plymouth stop/waiting
rcS stop/waiting
prefdm stop/waiting
init-system-dbus stop/waiting
ck-log-system-restart stop/waiting
readahead stop/waiting
ck-log-system-start stop/waiting
splash-manager stop/waiting
start-ttys stop/waiting
readahead-disable-services stop/waiting
ck-log-system-stop stop/waiting
rcS-sulogin stop/waiting
serial stop/waiting

```

### 方法三：如何在 systemd 系统中查看运行的服务

以下命令帮助我们列出 systemd 系统中所有服务：

```
# systemctl
  UNIT                                                                                LOAD   ACTIVE SUB       DESCRIPTION
  sys-devices-virtual-block-loop0.device                                                   loaded active plugged   /sys/devices/virtual/block/loop0
  sys-devices-virtual-block-loop1.device                                                   loaded active plugged   /sys/devices/virtual/block/loop1
  sys-devices-virtual-block-loop2.device                                                   loaded active plugged   /sys/devices/virtual/block/loop2
  sys-devices-virtual-block-loop3.device                                                   loaded active plugged   /sys/devices/virtual/block/loop3
  sys-devices-virtual-block-loop4.device                                                   loaded active plugged   /sys/devices/virtual/block/loop4
  sys-devices-virtual-misc-rfkill.device                                                   loaded active plugged   /sys/devices/virtual/misc/rfkill
  sys-devices-virtual-tty-ttyprintk.device                                                 loaded active plugged   /sys/devices/virtual/tty/ttyprintk
  sys-module-fuse.device                                                                   loaded active plugged   /sys/module/fuse
  sys-subsystem-net-devices-enp0s3.device                                                  loaded active plugged   82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter)
  -.mount                                                                                loaded active mounted   Root Mount
  dev-hugepages.mount                                                                      loaded active mounted   Huge Pages File System
  dev-mqueue.mount                                                                         loaded active mounted   POSIX Message Queue File System
  run-user-1000-gvfs.mount                                                                 loaded active mounted   /run/user/1000/gvfs
  run-user-1000.mount                                                                      loaded active mounted   /run/user/1000
  snap-core-3887.mount                                                                     loaded active mounted   Mount unit for core
  snap-core-4017.mount                                                                     loaded active mounted   Mount unit for core
  snap-core-4110.mount                                                                     loaded active mounted   Mount unit for core
  snap-gping-13.mount                                                                      loaded active mounted   Mount unit for gping
  snap-termius\x2dapp-8.mount                                                              loaded active mounted   Mount unit for termius-app
  sys-fs-fuse-connections.mount                                                            loaded active mounted   FUSE Control File System
  sys-kernel-debug.mount                                                                   loaded active mounted   Debug File System
  acpid.path                                                                               loaded active running   ACPI Events Check
  cups.path                                                                                loaded active running   CUPS Scheduler
  systemd-ask-password-plymouth.path                                                       loaded active waiting   Forward Password Requests to Plymouth Directory Watch
  systemd-ask-password-wall.path                                                           loaded active waiting   Forward Password Requests to Wall Directory Watch
  init.scope                                                                               loaded active running   System and Service Manager
  session-c2.scope                                                                         loaded active running   Session c2 of user magi
  accounts-daemon.service                                                                  loaded active running   Accounts Service
  acpid.service                                                                            loaded active running   ACPI event daemon
  anacron.service                                                                          loaded active running   Run anacron jobs
  apache2.service                                                                          loaded active running   The Apache HTTP Server
  apparmor.service                                                                         loaded active exited    AppArmor initialization
  apport.service                                                                           loaded active exited    LSB: automatic crash report generation
  aptik-battery-monitor.service                                                            loaded active running   LSB: start/stop the aptik battery monitor daemon
  atop.service                                                                             loaded active running   Atop advanced performance monitor
  atopacct.service                                                                         loaded active running   Atop process accounting daemon
  avahi-daemon.service                                                                     loaded active running   Avahi mDNS/DNS-SD Stack
  colord.service                                                                           loaded active running   Manage, Install and Generate Color Profiles
  console-setup.service                                                                    loaded active exited    Set console font and keymap
  cron.service                                                                             loaded active running   Regular background program processing daemon
  cups-browsed.service                                                                     loaded active running   Make remote CUPS printers available locally
  cups.service                                                                             loaded active running   CUPS Scheduler
  dbus.service                                                                             loaded active running   D-Bus System Message Bus
  postfix.service                                                                          loaded active exited    Postfix Mail Transport Agent

```

* `UNIT` 相应的 systemd 单元名称
* `LOAD` 相应的单元是否被加载到内存中
* `ACTIVE` 该单元是否处于活动状态
* `SUB` 该单元是否处于运行状态（LCTT 译注：是较于 ACTIVE 更加详细的状态描述，不同的单元类型有不同的状态。）
* `DESCRIPTION` 关于该单元的简短描述

以下选项可根据类型列出单元：

```
# systemctl list-units --type service
  UNIT                               LOAD   ACTIVE SUB     DESCRIPTION
  accounts-daemon.service            loaded active running Accounts Service
  acpid.service                      loaded active running ACPI event daemon
  anacron.service                    loaded active running Run anacron jobs
  apache2.service                    loaded active running The Apache HTTP Server
  apparmor.service                   loaded active exited  AppArmor initialization
  apport.service                     loaded active exited  LSB: automatic crash report generation
  aptik-battery-monitor.service      loaded active running LSB: start/stop the aptik battery monitor daemon
  atop.service                       loaded active running Atop advanced performance monitor
  atopacct.service                   loaded active running Atop process accounting daemon
  avahi-daemon.service               loaded active running Avahi mDNS/DNS-SD Stack
  colord.service                     loaded active running Manage, Install and Generate Color Profiles
  console-setup.service              loaded active exited  Set console font and keymap
  cron.service                       loaded active running Regular background program processing daemon
  cups-browsed.service               loaded active running Make remote CUPS printers available locally
  cups.service                       loaded active running CUPS Scheduler
  dbus.service                       loaded active running D-Bus System Message Bus
  fwupd.service                      loaded active running Firmware update daemon
  getty@tty1.service                 loaded active running Getty on tty1
  grub-common.service                loaded active exited  LSB: Record successful boot for GRUB
  irqbalance.service                 loaded active running LSB: daemon to balance interrupts for SMP systems
  keyboard-setup.service             loaded active exited  Set the console keyboard layout
  kmod-static-nodes.service          loaded active exited  Create list of required static device nodes for the current kernel

```

以下选项可帮助您根据状态列出单位，输出与前例类似但更直截了当：

```
# systemctl list-unit-files --type service

UNIT FILE                                  STATE
accounts-daemon.service                    enabled
acpid.service                              disabled
alsa-restore.service                       static
alsa-state.service                         static
alsa-utils.service                         masked
anacron-resume.service                     enabled
anacron.service                            enabled
apache-htcacheclean.service                disabled
apache-htcacheclean@.service               disabled
apache2.service                            enabled
apache2@.service                           disabled
apparmor.service                           enabled
apport-forward@.service                    static
apport.service                             generated
apt-daily-upgrade.service                  static
apt-daily.service                          static
aptik-battery-monitor.service              generated
atop.service                               enabled
atopacct.service                           enabled
autovt@.service                            enabled
avahi-daemon.service                       enabled
bluetooth.service                          enabled

```

运行以下命令以查看指定服务的状态：

```
# systemctl | grep apache2
  apache2.service                                                                          loaded active running   The Apache HTTP Server

```

或者，使用以下命令也可查看指定服务的状态：

```
# systemctl status apache2
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
  Drop-In: /lib/systemd/system/apache2.service.d
           └─apache2-systemd.conf
   Active: active (running) since Tue 2018-03-06 12:34:09 IST; 8min ago
  Process: 2786 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS)
 Main PID: 1171 (apache2)
    Tasks: 55 (limit: 4915)
   CGroup: /system.slice/apache2.service
           ├─1171 /usr/sbin/apache2 -k start
           ├─2790 /usr/sbin/apache2 -k start
           └─2791 /usr/sbin/apache2 -k start

Mar 06 12:34:08 magi-VirtualBox systemd[1]: Starting The Apache HTTP Server...
Mar 06 12:34:09 magi-VirtualBox apachectl[1089]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.0.2.15. Set the 'ServerName' directive globally to suppre
Mar 06 12:34:09 magi-VirtualBox systemd[1]: Started The Apache HTTP Server.
Mar 06 12:39:10 magi-VirtualBox systemd[1]: Reloading The Apache HTTP Server.
Mar 06 12:39:10 magi-VirtualBox apachectl[2786]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using fe80::7929:4ed1:279f:4d65. Set the 'ServerName' directive gl
Mar 06 12:39:10 magi-VirtualBox systemd[1]: Reloaded The Apache HTTP Server.

```

执行以下命令，只查看正在运行的服务：

```
# systemctl | grep running
  acpid.path                                                                               loaded active running   ACPI Events Check
  cups.path                                                                                loaded active running   CUPS Scheduler
  init.scope                                                                               loaded active running   System and Service Manager
  session-c2.scope                                                                         loaded active running   Session c2 of user magi
  accounts-daemon.service                                                                  loaded active running   Accounts Service
  acpid.service                                                                            loaded active running   ACPI event daemon
  apache2.service                                                                          loaded active running   The Apache HTTP Server
  aptik-battery-monitor.service                                                            loaded active running   LSB: start/stop the aptik battery monitor daemon
  atop.service                                                                             loaded active running   Atop advanced performance monitor
  atopacct.service                                                                         loaded active running   Atop process accounting daemon
  avahi-daemon.service                                                                     loaded active running   Avahi mDNS/DNS-SD Stack
  colord.service                                                                           loaded active running   Manage, Install and Generate Color Profiles
  cron.service                                                                             loaded active running   Regular background program processing daemon
  cups-browsed.service                                                                     loaded active running   Make remote CUPS printers available locally
  cups.service                                                                             loaded active running   CUPS Scheduler
  dbus.service                                                                             loaded active running   D-Bus System Message Bus
  fwupd.service                                                                            loaded active running   Firmware update daemon
  getty@tty1.service                                                                       loaded active running   Getty on tty1
  irqbalance.service                                                                       loaded active running   LSB: daemon to balance interrupts for SMP systems
  lightdm.service                                                                          loaded active running   Light Display Manager
  ModemManager.service                                                                     loaded active running   Modem Manager
  NetworkManager.service                                                                   loaded active running   Network Manager
  polkit.service                                                                           loaded active running   Authorization Manager

```

使用以下命令查看系统启动时会被启用的服务列表：

```
# systemctl list-unit-files | grep enabled
acpid.path                                 enabled
cups.path                                  enabled
accounts-daemon.service                    enabled
anacron-resume.service                     enabled
anacron.service                            enabled
apache2.service                            enabled
apparmor.service                           enabled
atop.service                               enabled
atopacct.service                           enabled
autovt@.service                            enabled
avahi-daemon.service                       enabled
bluetooth.service                          enabled
console-setup.service                      enabled
cron.service                               enabled
cups-browsed.service                       enabled
cups.service                               enabled
display-manager.service                    enabled
dns-clean.service                          enabled
friendly-recovery.service                  enabled
getty@.service                             enabled
gpu-manager.service                        enabled
keyboard-setup.service                     enabled
lightdm.service                            enabled
ModemManager.service                       enabled
network-manager.service                    enabled
networking.service                         enabled
NetworkManager-dispatcher.service          enabled
NetworkManager-wait-online.service         enabled
NetworkManager.service                     enabled

```

`systemd-cgtop` 按资源使用情况（任务、CPU、内存、输入和输出）列出控制组：

```
# systemd-cgtop

Control Group                                              Tasks   %CPU   Memory  Input/s Output/s
/                                                              -      -     1.5G        -        -
/init.scope                                                    1      -        -        -        -
/system.slice                                                153      -        -        -        -
/system.slice/ModemManager.service                             3      -        -        -        -
/system.slice/NetworkManager.service                           4      -        -        -        -
/system.slice/accounts-daemon.service                          3      -        -        -        -
/system.slice/acpid.service                                    1      -        -        -        -
/system.slice/apache2.service                                 55      -        -        -        -
/system.slice/aptik-battery-monitor.service                    1      -        -        -        -
/system.slice/atop.service                                     1      -        -        -        -
/system.slice/atopacct.service                                 1      -        -        -        -
/system.slice/avahi-daemon.service                             2      -        -        -        -
/system.slice/colord.service                                   3      -        -        -        -
/system.slice/cron.service                                     1      -        -        -        -
/system.slice/cups-browsed.service                             3      -        -        -        -
/system.slice/cups.service                                     2      -        -        -        -
/system.slice/dbus.service                                     6      -        -        -        -
/system.slice/fwupd.service                                    5      -        -        -        -
/system.slice/irqbalance.service                               1      -        -        -        -
/system.slice/lightdm.service                                  7      -        -        -        -
/system.slice/polkit.service                                   3      -        -        -        -
/system.slice/repowerd.service                                14      -        -        -        -
/system.slice/rsyslog.service                                  4      -        -        -        -
/system.slice/rtkit-daemon.service                             3      -        -        -        -
/system.slice/snapd.service                                    8      -        -        -        -
/system.slice/system-getty.slice                               1      -        -        -        -

```

同时，我们可以使用 `pstree` 命令（输出来自 SysVinit 系统）查看正在运行的服务：

```
# pstree
init-+-crond
     |-httpd---2*[httpd]
     |-kthreadd/99149---khelper/99149
     |-2*[mingetty]
     |-mysqld_safe---mysqld---9*[{mysqld}]
     |-rsyslogd---3*[{rsyslogd}]
     |-saslauthd---saslauthd
     |-2*[sendmail]
     |-sshd---sshd---bash---pstree
     |-udevd
     `-xinetd

```

我们还可以使用 `pstree` 命令（输出来自 systemd 系统）查看正在运行的服务：

```
# pstree
systemd─┬─ModemManager─┬─{gdbus}
        │              └─{gmain}
        ├─NetworkManager─┬─dhclient
        │                ├─{gdbus}
        │                └─{gmain}
        ├─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─acpid
        ├─agetty
        ├─anacron
        ├─apache2───2*[apache2───26*[{apache2}]]
        ├─aptd───{gmain}
        ├─aptik-battery-m
        ├─atop
        ├─atopacctd
        ├─avahi-daemon───avahi-daemon
        ├─colord─┬─{gdbus}
        │        └─{gmain}
        ├─cron
        ├─cups-browsed─┬─{gdbus}
        │              └─{gmain}
        ├─cupsd
        ├─dbus-daemon
        ├─fwupd─┬─{GUsbEventThread}
        │       ├─{fwupd}
        │       ├─{gdbus}
        │       └─{gmain}
        ├─gnome-keyring-d─┬─{gdbus}
        │                 ├─{gmain}
        │                 └─{timer}

```

### 方法四：如何使用 chkservice 在 systemd 系统中查看正在运行的服务

`chkservice` 是一个管理系统单元的终端工具，需要超级用户权限。

```
# chkservice

```

![](/data/attachment/album/201808/14/100535c5jj5j4tya55lygi.png)

要查看帮助页面，请按下 `?` ，它将显示管理 systemd 服务的可用选项。

![](/data/attachment/album/201808/14/100535tyyxunaggdtwpkwk.png)

---

via: <https://www.2daygeek.com/how-to-check-all-running-services-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/) 荣誉推出


面向系统管理员的 Bash 指南

Summary: 使 Bash 工作的更好的技巧。

使 Bash 工作的更好的技巧。

>
> 使 Bash 工作的更好的技巧。
>
>
>

![](/data/attachment/album/201808/15/123148pv494gv6qd26wrii.jpg)

每个行业都有一个该行业的大师们最常使用的工具。 对于许多系统管理员来说，这个工具就是他们的 [shell](http://www.catb.org/jargon/html/S/shell.html)。 在大多数 Linux 和其他类 Unix 系统上，默认的 shell 是 Bash。

Bash 是一个相当古老的程序——它起源于 20 世纪 80 年代后期——但它建立在更多更老的 shell 上，比如 C shell（csh），csh 至少是它 10 年前的前辈了。 因为 shell 的概念是那么古老，所以有大量的神秘知识等待着系统管理员去吸收领悟，使其生活更轻松。

我们来看看一些基础知识。

在某些时候，谁曾经无意中以 root 身份运行命令并导致某种问题？ *举手*

我很确定我们很多人一度都是那个人。 这很痛苦。 这里有一些非常简单的技巧可以防止你再次碰上这类问题。

### 使用别名

首先，为 `mv` 和 `rm` 等命令设置别名，指向 `mv -i` 和 `rm -i`。 这将确保在运行 `rm -f /boot` 时至少需要你确认。 在 Red Hat 企业版 Linux 中，如果你使用 root 帐户，则默认设置这些别名。

如果你还要为普通用户帐户设置这些别名，只需将这两行放入家目录下名为 `.bashrc` 的文件中（这些也适用于 `sudo` ）：

```
alias mv='mv -i'
alias rm='rm -i'

```

### 让你的 root 提示符脱颖而出

你可以采取的防止意外发生的另一项措施是确保你很清楚在使用 root 帐户。 在日常工作中，我通常会让 root 提示符从日常使用的提示符中脱颖而出。

如果将以下内容放入 root 的家目录中的 `.bashrc` 文件中，你将看到一个黑色背景上的红色的 root 提示符，清楚地表明你（或其他任何人）应该谨慎行事。

```
export PS1="\[$(tput bold)$(tput setab 0)$(tput setaf 1)\]\u@\h:\w # \[$(tput sgr0)\]"

```

实际上，你应该尽可能避免以 root 用户身份登录，而是通过 `sudo` 运行大多数系统管理命令，但这是另一回事。

使用了一些小技巧用于防止使用 root 帐户时的“不小心的副作用”之后，让我们看看 Bash 可以帮助你在日常工作中做的一些好事。

### 控制你的历史

你可能知道在 Bash 中你按向上的箭头时能看见和重新使用你之前所有（好吧，大多数）的命令。这是因为这些命令已经保存到了你家目录下的名为 `.bash_history` 的文件中。这个历史文件附带了一组有用的设置和命令。

首先，你可以通过键入 `history` 来查看整个最近的命令历史记录，或者你可以通过键入 `history 30` 将其限制为最近 30 个命令。不过这技巧太平淡无奇了（LCTT 译注： vanilla 原为香草，后引申没拓展的、标准、普通的，比如 vanilla C++ compiler 意为标准 C++ 编译器）。 你可以更好地控制 Bash 保存的内容以及保存方式。

例如，如果将以下内容添加到 `.bashrc`，那么任何以空格开头的命令都不会保存到历史记录列表中：

```
HISTCONTROL=ignorespace

```

如果你需要以明文形式将密码传递给一个命令，这就非常有用。 （是的，这太可怕了，但它仍然会发生。）

如果你不希望经常执行的命令充斥在历史记录中，请使用：

```
HISTCONTROL=ignorespace:erasedups

```

这样，每次使用一个命令时，都会从历史记录文件中删除之前出现的所有相同命令，并且只将最后一次调用保存到历史记录列表中。

我特别喜欢的历史记录设置是 `HISTTIMEFORMAT` 设置。 这将在历史记录文件中在所有的条目前面添加上时间戳。 例如，我使用：

```
HISTTIMEFORMAT="%F %T  "

```

当我输入 `history 5` 时，我得到了很好的完整信息，如下所示：

```
1009  2018-06-11 22:34:38  cat /etc/hosts
1010  2018-06-11 22:34:40  echo $foo
1011  2018-06-11 22:34:42  echo $bar
1012  2018-06-11 22:34:44  ssh myhost
1013  2018-06-11 22:34:55  vim .bashrc

```

这使我更容易浏览我的命令历史记录并找到我两天前用来建立到我家实验室的 SSH 连接（我一次又一次地忘记......）。

### Bash 最佳实践

我将在编写 Bash 脚本时最好的（或者至少是好的，我不要求无所不知）11 项实践列出来。

11、 Bash 脚本可能变得复杂，不过注释也很方便。 如果你在考虑是否要添加注释，那就添加一个注释。 如果你在周末之后回来并且不得不花时间搞清楚你上周五想要做什么，那你是忘了添加注释。

10、 用花括号括起所有变量名，比如 `${myvariable}`。 养成这个习惯可以使用 `${variable}_suffix` 这种用法了，还能提高整个脚本的一致性。

9、 计算表达式时不要使用反引号；请改用 `$()` 语法。 所以使用：

```
for  file in $(ls); do

```

而不使用：

```
for  file in `ls`; do

```

前一个方式是可嵌套的，更易于阅读的，还能让一般的系统管理员群体感到满意。 不要使用反引号。

8、 一致性是好的。 选择一种风格并在整个脚本中坚持下去。 显然，我喜欢人们选择 `$()` 语法而不是反引号，并将其变量包在花括号中。 我更喜欢人们使用两个或四个空格而不是制表符来缩进，但即使你选择了错误的方式，也要一贯地错下去。

7、 为 Bash 脚本使用适当的<ruby> <a href="/article-3664-1.html">  释伴 </a> <rt>  shebang </rt></ruby>（LCTT 译注：**Shebang**，也称为 **Hashbang** ，是一个由井号和叹号构成的字符序列 `#!` ，其出现在文本文件的第一行的前两个字符。 在文件中存在释伴的情况下，类 Unix 操作系统的程序载入器会分析释伴后的内容，将这些内容作为解释器指令，并调用该指令，并将载有释伴的文件路径作为该解释器的参数）。 因为我正在编写Bash脚本，只打算用 Bash 执行它们，所以我经常使用 `#!/usr/bin/bash` 作为我的释伴。 不要使用 `#!/bin/sh` 或 `#!/usr/bin/sh`。 你的脚本会被执行，但它会以兼容模式运行——可能会产生许多意外的副作用。 （当然，除非你想要兼容模式。）

6、 比较字符串时，在 `if` 语句中给变量加上引号是个好主意，因为如果你的变量是空的，Bash 会为这样的行抛出一个错误：

```
if [ ${myvar} == "foo" ]; then
  echo "bar"
fi

```

对于这样的行，将判定为 `false`：

```
if [ "${myvar}" == "foo" ]; then
  echo "bar"
fi

```

此外，如果你不确定变量的内容（例如，在解析用户输入时），请给变量加引号以防止解释某些特殊字符，并确保该变量被视为单个单词，即使它包含空格。

5、 我想这是一个品味问题，但我更喜欢使用双等号（ `==` ），即使是比较 Bash 中的字符串。 这是一致性的问题，尽管对于字符串比较，只有一个等号会起作用，我的思维立即变为“单个 `=` 是一个赋值运算符！”

4、 使用适当的退出代码。 确保如果你的脚本无法执行某些操作，则会向用户显示已写好的失败消息（最好提供解决问题的方法）并发送非零退出代码：

```
# we have failed
echo "Process has failed to complete, you need to manually restart the whatchamacallit"
exit 1

```

这样可以更容易地以编程方式从另一个脚本调用你的脚本并验证其成功完成。

3、 使用 Bash 的内置机制为变量提供合理的默认值，或者如果未定义你希望定义的变量，则抛出错误：

```
# this sets the value of $myvar to redhat, and prints 'redhat'
echo ${myvar:=redhat}

```

```
# this throws an error reading 'The variable myvar is undefined, dear reader' if $myvar is undefined
${myvar:?The variable myvar is undefined, dear reader}

```

2、 特别是如果你正在编写大型脚本，或者是如果你与其他人一起开发该大型脚本，请考虑在函数内部定义变量时使用 `local` 关键字。 `local` 关键字将创建一个局部变量，该变量只在该函数中可见。 这限制了变量冲突的可能性。

1、 每个系统管理员有时必须这样做：在控制台上调试一些东西，可能是数据中心的真实服务器，也可能是虚拟化平台的虚拟服务器。 如果你必须以这种方式调试脚本，你会感谢你自己记住了这个：不要让你的脚本中的行太长！

在许多系统上，控制台的默认宽度仍为 80 个字符。 如果你需要在控制台上调试脚本并且该脚本有很长的行，那么你将成为一个悲伤的熊猫。 此外，具有较短行的脚本—— 默认值仍为 80 个字符——在普通编辑器中也更容易阅读和理解！

我真的很喜欢 Bash。 我可以花几个小时写这篇文章或与其他爱好者交流优秀的技巧。 就希望你们能在评论中留下赞美。

---

via: <https://opensource.com/article/18/7/admin-guide-bash>

作者：[Maxim Burgerhout](https://opensource.com/users/wzzrd) 选题：[lujun9972](https://github.com/lujun9972) 译者：[Flowsnow](https://github.com/Flowsnow) 校对：[wxy](https://github.com/wxy)

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


Mu 入门：一个面向初学者的 Python 编辑器

Summary: 相识 Mu —— 一个可以使学生学习 Python 更轻松的开源编辑器。

相识 Mu —— 一个可以使学生学习 Python 更轻松的开源编辑器。

>
> 相识 Mu —— 一个可以使学生学习 Python 更轻松的开源编辑器。
>
>
>

![](/data/attachment/album/201808/15/124829nvjjnihejp6vhtv5.png)

Mu 是一个给初学者的 Python 编辑器，它旨在使学习体验更加愉快。它使学生能够在早期体验成功，这在你学习任何新知识的时候都很重要。

如果你曾试图教年轻人如何编程，你会立即把握到 [Mu](https://codewith.mu) 的重要性。大多数编程工具都是由开发人员为开发人员编写的，不管他们的年龄如何，它们并不适合初学者。然而，Mu 是由老师为学生写的。

### Mu 的起源

Mu 是 [Nicholas Tollervey](https://us.pycon.org/2018/speaker/profile/194/) 的心血结晶（我听过他 5 月份在 PyCon2018 上发言）。Nicholas 是一位受过古典音乐训练的音乐家，在担任音乐老师期间，他在职业生涯早期就开始对 Python 和开发感兴趣。他还写了 [Python in Education](https://www.oreilly.com/programming/free/python-in-education.csp)，这是一本可以从 O'Reilly 下载的免费书。

Nicholas 曾经寻找过一个更简单的 Python 编程界面。他想要一些没有其他编辑器（甚至是 Python 附带的 IDLE3 编辑器 ）复杂性的东西，所以他与 Raspberry Pi 基金会（赞助他的工作）的教育总监 [Carrie Ann Philbin](https://uk.linkedin.com/in/carrie-anne-philbin-a20649b7) 合作开发了 Mu 。

Mu 是一个用 Python 编写的开源程序（在 [GNU GPLv3](https://mu.readthedocs.io/en/latest/license.html) 许可证下）。它最初是为 [Micro:bit](http://microbit.org/) 迷你计算机开发的，但是其他老师的反馈和请求促使他将 Mu 重写为通用的 Python 编辑器。

### 受音乐启发

Nicholas 对 Mu 的启发来自于他教授音乐的方法。他想知道如果我们按照教授音乐的方式教授编程会如何，并立即看出了差别。与编程不同，我们没有音乐训练营，我们也不会书上学习如何演奏乐器，比如说如何演奏长笛。

Nicholas 说，Mu “旨在成为真实的东西”，因为没有人可以在 30 分钟内学习 Python。当他开发 Mu 时，他与老师一起工作，观察编程俱乐部，并观看中学生使用 Python。他发现少即多，保持简单可以改善成品的功能。Nicholas 说，Mu 只有大约 3,000 行代码。

### 使用 Mu

要尝试它，[下载](https://codewith.mu/en/download) Mu 并按照 [Linux、Windows 和 Mac OS](https://codewith.mu/en/howto/install_with_python)的简易安装说明进行操作。如果像我一样，你想[在 Raspberry Pi 上安装](https://codewith.mu/en/howto/install_raspberry_pi)，请在终端中输入以下内容：

```
$ sudo apt-get update
$ sudo apt-get install mu

```

从编程菜单启动 Mu。然后你就可以选择如何使用 Mu。

![](/data/attachment/album/201808/15/124843tby91r6ecbe67lhl.png)

我选择了Python 3，它启动了编写代码的环境。Python shell 直接在下面，它允许你查看代码执行。

![](/data/attachment/album/201808/15/124855ox2oo72695pvqp5o.png)

菜单使用和理解非常简单，这实现了 Mu 的目标 —— 让编写代码对初学者简单。

在 Mu 用户的网站上可找到[教程](https://codewith.mu/en/tutorials/)和其他资源。在网站上，你还可以看到一些帮助开发 Mu 的[志愿者](https://codewith.mu/en/thanks)的名字。如果你想成为其中之一并[为 Mu 的发展做出贡献](https://mu.readthedocs.io/en/latest/contributing.html)，我们非常欢迎您。

---

via: <https://opensource.com/article/18/8/getting-started-mu-python-editor-beginners>

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

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


使用 MQTT 在项目中实现数据收发

>
> 从开源数据到开源事件流，了解一下 MQTT 发布/订阅（pubsub）线路协议。
>
>
>

![](/data/attachment/album/201808/15/220809dc3h54p1v3q5cc0r.jpg)

去年 11 月我们购买了一辆电动汽车，同时也引发了有趣的思考：我们应该什么时候为电动汽车充电？对于电动汽车充电所用的电，我希望能够对应最小的二氧化碳排放，归结为一个特定的问题：对于任意给定时刻，每千瓦时对应的二氧化碳排放量是多少，一天中什么时间这个值最低？

### 寻找数据

我住在纽约州，大约 80% 的电力消耗可以自给自足，主要来自天然气、水坝（大部分来自于<ruby> 尼亚加拉 <rt>  Niagara </rt></ruby>大瀑布）、核能发电，少部分来自风力、太阳能和其它化石燃料发电。非盈利性组织 [<ruby> 纽约独立电网运营商 <rt>  New York Independent System Operator </rt></ruby>](http://www.nyiso.com/public/index.jsp) （NYISO）负责整个系统的运作，实现发电机组发电与用电之间的平衡，同时也是纽约路灯系统的监管部门。

尽管没有为公众提供公开 API，NYISO 还是尽责提供了[不少公开数据](http://www.nyiso.com/public/markets_operations/market_data/reports_info/index.jsp)供公众使用。每隔 5 分钟汇报全州各个发电机组消耗的燃料数据。数据以 CSV 文件的形式发布于公开的档案库中，全天更新。如果你了解不同燃料对发电瓦数的贡献比例，你可以比较准确的估计任意时刻的二氧化碳排放情况。

在构建收集处理公开数据的工具时，我们应该时刻避免过度使用这些资源。相比将这些数据打包并发送给所有人，我们有更好的方案。我们可以创建一个低开销的<ruby> 事件流 <rt>  event stream </rt></ruby>，人们可以订阅并第一时间得到消息。我们可以使用 [MQTT](http://mqtt.org/) 实现该方案。我的项目（[ny-power.org](http://ny-power.org/#)）目标是收录到 [Home Assistant](https://www.home-assistant.io) 项目中；后者是一个开源的<ruby> 家庭自动化 <rt>  home automation </rt></ruby>平台，拥有数十万用户。如果所有用户同时访问 CSV 文件服务器，估计 NYISO 不得不增加访问限制。

### MQTT 是什么？

MQTT 是一个<ruby> 发布订阅线路协议 <rt>  publish/subscription wire protocol </rt></ruby>，为小规模设备设计。发布订阅系统工作原理类似于消息总线。你将一条消息发布到一个<ruby> 主题 <rt>  topic </rt></ruby>上，那么所有订阅了该主题的客户端都可以获得该消息的一份拷贝。对于消息发送者而言，无需知道哪些人在订阅消息；你只需将消息发布到一系列主题，并订阅一些你感兴趣的主题。就像参加了一场聚会，你选取并加入感兴趣的对话。

MQTT 能够构建极为高效的应用。客户端订阅有限的几个主题，也只收到它们感兴趣的内容。不仅节省了处理时间，还降低了网络带宽使用。

作为一个开放标准，MQTT 有很多开源的客户端和服务端实现。对于你能想到的每种编程语言，都有对应的客户端库；甚至有嵌入到 Arduino 的库，可以构建传感器网络。服务端可供选择的也很多，我的选择是 Eclipse 项目提供的 [Mosquitto](https://mosquitto.org/) 服务端，这是因为它体积小、用 C 编写，可以承载数以万计的订阅者。

### 为何我喜爱 MQTT

在过去二十年间，我们为软件应用设计了可靠且准确的模型，用于解决服务遇到的问题。我还有其它邮件吗？当前的天气情况如何？我应该此刻购买这种产品吗？在绝大多数情况下，这种<ruby> 问答式 <rt>  ask/receive </rt></ruby>的模型工作良好；但对于一个数据爆炸的世界，我们需要其它的模型。MQTT 的发布订阅模型十分强大，可以将大量数据发送到系统中。客户可以订阅数据中的一小部分并在订阅数据发布的第一时间收到更新。

MQTT 还有一些有趣的特性，其中之一是<ruby> 遗嘱 <rt>  last-will-and-testament </rt></ruby>消息，可以用于区分两种不同的静默，一种是没有主题相关数据推送，另一种是你的数据接收器出现故障。MQTT 还包括<ruby> 保留消息 <rt>  retained message </rt></ruby>，当客户端初次连接时会提供相关主题的最后一条消息。这对那些更新缓慢的主题来说很有必要。

我在 Home Assistant 项目开发过程中，发现这种消息总线模型对<ruby> 异构系统 <rt>  heterogeneous systems </rt></ruby>尤为适合。如果你深入<ruby> 物联网 <rt>  Internet of Things </rt></ruby>领域，你会发现 MQTT 无处不在。

### 我们的第一个 MQTT 流

NYSO 公布的 CSV 文件中有一个是实时的燃料混合使用情况。每 5 分钟，NYSO 发布这 5 分钟内发电使用的燃料类型和相应的发电量（以兆瓦为单位）。

这个 CSV 文件看起来像这样：

| 时间戳 | 时区 | 燃料类型 | 兆瓦为单位的发电量 |
| --- | --- | --- | --- |
| 05/09/2018 00:05:00 | EDT | 混合燃料 | 1400 |
| 05/09/2018 00:05:00 | EDT | 天然气 | 2144 |
| 05/09/2018 00:05:00 | EDT | 核能 | 4114 |
| 05/09/2018 00:05:00 | EDT | 其它化石燃料 | 4 |
| 05/09/2018 00:05:00 | EDT | 其它可再生资源 | 226 |
| 05/09/2018 00:05:00 | EDT | 风力 | 1 |
| 05/09/2018 00:05:00 | EDT | 水力 | 3229 |
| 05/09/2018 00:10:00 | EDT | 混合燃料 | 1307 |
| 05/09/2018 00:10:00 | EDT | 天然气 | 2092 |
| 05/09/2018 00:10:00 | EDT | 核能 | 4115 |
| 05/09/2018 00:10:00 | EDT | 其它化石燃料 | 4 |
| 05/09/2018 00:10:00 | EDT | 其它可再生资源 | 224 |
| 05/09/2018 00:10:00 | EDT | 风力 | 40 |
| 05/09/2018 00:10:00 | EDT | 水力 | 3166 |

表中唯一令人不解就是燃料类别中的混合燃料。纽约的大多数天然气工厂也通过燃烧其它类型的化石燃料发电。在冬季寒潮到来之际，家庭供暖的优先级高于发电；但这种情况出现的次数不多，（在我们计算中）可以将混合燃料类型看作天然气类型。

CSV 文件全天更新。我编写了一个简单的数据泵，每隔 1 分钟检查是否有数据更新，并将新条目发布到 MQTT 服务器的一系列主题上，主题名称基本与 CSV 文件有一定的对应关系。数据内容被转换为 JSON 对象，方便各种编程语言处理。

```
ny-power/upstream/fuel-mix/Hydro {"units": "MW", "value": 3229, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Dual Fuel {"units": "MW", "value": 1400, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Natural Gas {"units": "MW", "value": 2144, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Other Fossil Fuels {"units": "MW", "value": 4, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Wind {"units": "MW", "value": 41, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Other Renewables {"units": "MW", "value": 226, "ts": "05/09/2018 00:05:00"}
ny-power/upstream/fuel-mix/Nuclear {"units": "MW", "value": 4114, "ts": "05/09/2018 00:05:00"}

```

这种直接的转换是种不错的尝试，可将公开数据转换为公开事件。我们后续会继续将数据转换为二氧化碳排放强度，但这些原始数据还可被其它应用使用，用于其它计算用途。

### MQTT 主题

主题和<ruby> 主题结构 <rt>  topic structure </rt></ruby>是 MQTT 的一个主要特色。与其它标准的企业级消息总线不同，MQTT 的主题无需事先注册。发送者可以凭空创建主题，唯一的限制是主题的长度，不超过 220 字符。其中 `/` 字符有特殊含义，用于创建主题的层次结构。我们即将看到，你可以订阅这些层次中的一些分片。

基于开箱即用的 Mosquitto，任何一个客户端都可以向任何主题发布消息。在原型设计过程中，这种方式十分便利；但一旦部署到生产环境，你需要增加<ruby> 访问控制列表 <rt>  access control list </rt></ruby>（ACL）只允许授权的应用发布消息。例如，任何人都能以只读的方式访问我的应用的主题层级，但只有那些具有特定<ruby> 凭证 <rt>  credentials </rt></ruby>的客户端可以发布内容。

主题中不包含<ruby> 自动样式 <rt>  automatic schema </rt></ruby>，也没有方法查找客户端可以发布的全部主题。因此，对于那些从 MQTT 总线消费数据的应用，你需要让其直接使用已知的主题和消息格式样式。

那么应该如何设计主题呢？最佳实践包括使用应用相关的根名称，例如在我的应用中使用 `ny-power`。接着，为提高订阅效率，构建足够深的层次结构。`upstream` 层次结构包含了直接从数据源获取的、不经处理的原始数据，而 `fuel-mix` 层次结构包含特定类型的数据；我们后续还可以增加其它的层次结构。

### 订阅主题

在 MQTT 中，订阅仅仅是简单的字符串匹配。为提高处理效率，只允许如下两种通配符：

* `#` 以递归方式匹配，直到字符串结束
* `+` 匹配下一个 `/` 之前的内容

为便于理解，下面给出几个例子：

```
ny-power/#  - 匹配 ny-power 应用发布的全部主题
ny-power/upstream/#  - 匹配全部原始数据的主题
ny-power/upstream/fuel-mix/+  - 匹配全部燃料类型的主题
ny-power/+/+/Hydro - 匹配全部两次层级之后为 Hydro 类型的主题（即使不位于 upstream 层次结构下）

```

类似 `ny-power/#` 的大范围订阅适用于<ruby> 低数据量 <rt>  low-volume </rt></ruby>的应用，应用从网络获取全部数据并处理。但对<ruby> 高数据量 <rt>  high-volume </rt></ruby>应用而言则是一个灾难，由于绝大多数消息并不会被使用，大部分的网络带宽被白白浪费了。

在大数据量情况下，为确保性能，应用需要使用恰当的主题筛选（如 `ny-power/+/+/Hydro`）尽量准确获取业务所需的数据。

### 增加我们自己的数据层次

接下来，应用中的一切都依赖于已有的 MQTT 流并构建新流。第一个额外的数据层用于计算发电对应的二氧化碳排放。

利用[<ruby> 美国能源情报署 <rt>  U.S. Energy Information Administration </rt></ruby>](https://www.eia.gov/) 给出的 2016 年纽约各类燃料发电及排放情况，我们可以给出各类燃料的[平均排放率](https://github.com/IBM/ny-power/blob/master/src/nypower/calc.py#L1-L60)，单位为克/兆瓦时。

上述结果被封装到一个专用的微服务中。该微服务订阅 `ny-power/upstream/fuel-mix/+`，即数据泵中燃料组成情况的原始数据，接着完成计算并将结果（单位为克/千瓦时）发布到新的主题层次结构上：

```
ny-power/computed/co2 {"units": "g / kWh", "value": 152.9486, "ts": "05/09/2018 00:05:00"}

```

接着，另一个服务会订阅该主题层次结构并将数据打包到 [InfluxDB](https://www.influxdata.com/) 进程中；同时，发布 24 小时内的时间序列数据到 `ny-power/archive/co2/24h` 主题，这样可以大大简化当前变化数据的绘制。

这种层次结构的主题模型效果不错，可以将上述程序之间的逻辑解耦合。在复杂系统中，各个组件可能使用不同的编程语言，但这并不重要，因为交换格式都是 MQTT 消息，即主题和 JSON 格式的消息内容。

### 从终端消费数据

为了更好的了解 MQTT 完成了什么工作，将其绑定到一个消息总线并查看消息流是个不错的方法。`mosquitto-clients` 包中的 `mosquitto_sub` 可以让我们轻松实现该目标。

安装程序后，你需要提供服务器名称以及你要订阅的主题。如果有需要，使用参数 `-v` 可以让你看到有新消息发布的那些主题；否则，你只能看到主题内的消息数据。

```
mosquitto_sub -h mqtt.ny-power.org -t ny-power/# -v

```

只要我编写或调试 MQTT 应用，我总会在一个终端中运行 `mosquitto_sub`。

### 从网页直接访问 MQTT

到目前为止，我们已经有提供公开事件流的应用，可以用微服务或命令行工具访问该应用。但考虑到互联网仍占据主导地位，因此让用户可以从浏览器直接获取事件流是很重要。

MQTT 的设计者已经考虑到了这一点。协议标准支持三种不同的传输协议：[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)、[UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) 和 [WebSockets](https://en.wikipedia.org/wiki/WebSocket)。主流浏览器都支持 WebSockets，可以维持持久连接，用于实时应用。

Eclipse 项目提供了 MQTT 的一个 JavaScript 实现，叫做 [Paho](https://www.eclipse.org/paho/)，可包含在你的应用中。工作模式为与服务器建立连接、建立一些订阅，然后根据接收到的消息进行响应。

```
// ny-power web console application

var client = new Paho.MQTT.Client(mqttHost, Number("80"), "client-" + Math.random());

// set callback handlers
client.onMessageArrived = onMessageArrived;

// connect the client
client.reconnect = true;
client.connect({onSuccess: onConnect});

// called when the client connects
function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
    console.log("onConnect");
    client.subscribe("ny-power/computed/co2");
    client.subscribe("ny-power/archive/co2/24h");
    client.subscribe("ny-power/upstream/fuel-mix/#");
}

// called when a message arrives
function onMessageArrived(message) {
    console.log("onMessageArrived:"+message.destinationName + message.payloadString);
    if (message.destinationName == "ny-power/computed/co2") {
        var data = JSON.parse(message.payloadString);
        $("#co2-per-kwh").html(Math.round(data.value));
        $("#co2-units").html(data.units);
        $("#co2-updated").html(data.ts);
    }

    if (message.destinationName.startsWith("ny-power/upstream/fuel-mix")) {
        fuel_mix_graph(message);
    }

    if (message.destinationName == "ny-power/archive/co2/24h") {
        var data = JSON.parse(message.payloadString);
        var plot = [
            {
                x: data.ts,
                y: data.values,
                type: 'scatter'
            }
        ];
        var layout = {
            yaxis: {
                title: "g CO2 / kWh",
            }
        };
        Plotly.newPlot('co2_graph', plot, layout);
    }

```

上述应用订阅了不少主题，因为我们将要呈现若干种不同类型的数据；其中 `ny-power/computed/co2` 主题为我们提供当前二氧化碳排放的参考值。一旦收到该主题的新消息，网站上的相应内容会被相应替换。

![NYISO 二氧化碳排放图](/data/attachment/album/201808/15/220846oejtdbotat1ar19n.png "NY ISO Grid CO2 Intensity")

*[ny-power.org](http://ny-power.org/#) 网站提供的 NYISO 二氧化碳排放图。*

`ny-power/archive/co2/24h` 主题提供了时间序列数据，用于为 [Plotly](https://plot.ly/) 线表提供数据。`ny-power/upstream/fuel-mix` 主题提供当前燃料组成情况，为漂亮的柱状图提供数据。

![NYISO 燃料组成情况](/data/attachment/album/201808/15/220850xgbq4bgb5ogqkg7k.png "Fuel mix on NYISO grid")

*[ny-power.org](http://ny-power.org/#) 网站提供的燃料组成情况。*

这是一个动态网站，数据不从服务器拉取，而是结合 MQTT 消息总线，监听对外开放的 WebSocket。就像数据泵和打包器程序那样，网站页面也是一个发布订阅客户端，只不过是在你的浏览器中执行，而不是在公有云的微服务上。

你可以在 <http://ny-power.org> 站点点看到动态变更，包括图像和可以看到消息到达的实时 MQTT 终端。

### 继续深入

ny-power.org 应用的完整内容开源在 [GitHub](https://github.com/IBM/ny-power) 中。你也可以查阅 [架构简介](https://developer.ibm.com/code/patterns/use-mqtt-stream-real-time-data/)，学习如何使用 [Helm](https://helm.sh/) 部署一系列 Kubernetes 微服务构建应用。另一个有趣的 MQTT 示例使用 MQTT 和 OpenWhisk 进行实时文本消息翻译，<ruby> 代码模式 <rt>  code pattern </rt></ruby>参考[链接](https://developer.ibm.com/code/patterns/deploy-serverless-multilingual-conference-room/)。

MQTT 被广泛应用于物联网领域，更多关于 MQTT 用途的例子可以在 [Home Assistant](https://www.home-assistant.io/) 项目中找到。

如果你希望深入了解协议内容，可以从 [mqtt.org](http://mqtt.org/) 获得该公开标准的全部细节。

想了解更多，可以参加 Sean Dague 在 [OSCON](https://conferences.oreilly.com/oscon/oscon-or) 上的演讲，主题为 [将 MQTT 加入到你的工具箱](https://conferences.oreilly.com/oscon/oscon-or/public/schedule/speaker/77317)，会议将于 7 月 16-19 日在奥尔良州波特兰举办。

---

via: <https://opensource.com/article/18/6/mqtt>

作者：[Sean Dague](https://opensource.com/users/sdague) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

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


使用 EduBlocks 轻松学习 Python 编程

>
> EduBlocks 提供了 Scratch 式的图形界面来编写 Python 3 代码。
>
>
>

![](/data/attachment/album/201808/15/222348bxwz02l8w40h5x4r.png)

如果你正在寻找一种方法将你的学生（或你自己）从使用 [Scratch](https://scratch.mit.edu/) 编程转移到学习 [Python](https://www.python.org/)，我建议你了解一下 [EduBlocks](https://edublocks.org/)。它为 Python 3 编程带来了熟悉的拖放式图形用户界面（GUI）。

从 Scratch 过渡到 Python 的一个障碍是缺少拖放式 GUI，而正是这种拖放式 GUI 使得 Scratch 成为 K-12 学校的首选程序。EduBlocks 的拖放版的 Python 3 改变了这种范式。它的目的是“帮助教师在较早的时候向儿童介绍基于文本的编程语言，如 Python。”

EduBlocks 的硬件要求非常适中 —— 一个树莓派和一条互联网连接 —— 应该可以在许多教室中使用。

EduBlocks 是由来自英国的 14 岁 Python 开发人员 Joshua Lowe 开发的。我看到 Joshua 在 2018 年 5 月的 [PyCon 2018](https://us.pycon.org/2018/about/) 上展示了他的项目。

### 入门

安装 EduBlocks 很容易。该网站提供了清晰的安装说明，你可以在项目的 [GitHub](https://github.com/AllAboutCode/EduBlocks) 仓库中找到详细的截图。

使用以下命令在 Raspberry Pi 命令行安装 EduBlocks：

```
curl -sSL get.edublocks.org | bash

```

### 在 EduBlocks 中编程

安装完成后，从桌面快捷方式或 Raspberry Pi 上的“编程”菜单启动 EduBlocks。

![](/data/attachment/album/201808/15/222120tmzg08g2cmvejacg.png)

启动程序后，你可以使用 EduBlocks 的拖放界面开始创建 Python 3 代码。它的菜单有清晰的标签。你可以通过单击 **Samples** 菜单按钮使用示例代码。你还可以通过单击 **Theme** 为你的编程界面选择不同的配色方案。使用 **Save** 菜单，你可以保存你的作品，然后 **Download** 你的 Python 代码。单击 **Run** 来执行并测试你的代码。

你可以通过单击最右侧的 **Blockly** 按钮来查看代码。它让你在 ”Blockly” 界面和普通的 Python 代码视图之间切换（正如你在任何其他 Python 编辑器中看到的那样）。

![](/data/attachment/album/201808/15/222128y7s1kes2vos70zn1.png)

EduBlocks 附带了一系列代码库，包括 [EduPython](https://edupython.tuxfamily.org/)、[Minecraft](https://minecraft.net/en-us/edition/pi/)、[Sonic Pi](https://sonic-pi.net/)、[GPIO Zero](https://gpiozero.readthedocs.io/en/stable/) 和 [Sense Hat](https://www.raspberrypi.org/products/sense-hat/)。

### 学习和支持

该项目维护了一个[学习门户网站](https://edublocks.org/learn.html)，其中包含教程和其他资源，可以轻松地 [hack](https://edublocks.org/resources/1.pdf) 树莓派版本的 Minecraft，编写 GPIOZero 和 Sonic Pi，并使用 Micro:bit 代码编辑器控制 LED。可以在 Twitter [@edu\_blocks](https://twitter.com/edu_blocks?lang=en) 和 [@all*about*code](https://twitter.com/all_about_code) 以及 [email](mailto:support@edublocks.org) 提供对 EduBlocks 的支持。

为了更深入的了解，你可以在 [GitHub](https://github.com/allaboutcode/edublocks) 上访问 EduBlocks 的源代码。该程序在 GNU Affero Public License v3.0 下[许可](https://github.com/AllAboutCode/EduBlocks/blob/tarball-install/LICENSE)。EduBlocks 的创建者（项目负责人 [Joshua Lowe](https://github.com/JoshuaLowe1002) 和开发人员 [Chris Dell](https://twitter.com/cjdell?lang=en) 和 [Les Pounder](https://twitter.com/biglesp?lang=en)）希望它成为一个社区项目，并邀请人们提出问题，提供反馈，以及提交 pull request 以向项目添加功能或修复。

---

via: <https://opensource.com/article/18/8/edublocks>

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

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