Linux 上最好的 9 个免费视频编辑软件（2018）

>
> 概要：这里介绍 Linux 上几个最好的视频编辑器，介绍它们的特性、利与弊，以及如何在你的 Linux 发行版上安装它们。
>
>
>

![Linux 上最好的视频编辑器](/data/attachment/album/201811/02/204345u32noteb8n128ook.png)

我们曾经在一篇短文中讨论过 [Linux 上最好的照片管理应用](https://itsfoss.com/linux-photo-management-software/)，[Linux 上最好的代码编辑器](https://itsfoss.com/best-modern-open-source-code-editors-for-linux/)。今天我们将讨论 **Linux 上最好的视频编辑软件**。

当谈到免费视频编辑软件，Windows Movie Maker 和 iMovie 是大部分人经常推荐的。

很不幸，上述两者在 GNU/Linux 上都不可用。但是不必担心，我们为你汇集了一个**最好的视频编辑器**清单。

### Linux 上最好的视频编辑器

接下来让我们一起看看这些最好的视频编辑软件。如果你觉得文章读起来太长，这里有一个快速摘要。

| 视频编辑器 | 主要用途 | 类型 |
| --- | --- | --- |
| Kdenlive | 通用视频编辑 | 自由开源 |
| OpenShot | 通用视频编辑 | 自由开源 |
| Shotcut | 通用视频编辑 | 自由开源 |
| Flowblade | 通用视频编辑 | 自由开源 |
| Lightworks | 专业级视频编辑 | 免费增值 |
| Blender | 专业级三维编辑 | 自由开源 |
| Cinelerra | 通用视频编辑 | 自由开源 |
| DaVinci | 专业级视频处理编辑 | 免费增值 |
| VidCutter | 简单视频拆分合并 | 自由开源 |

### 1、 Kdenlive

![Kdenlive - Ubuntu 上的免费视频编辑器](/data/attachment/album/201811/02/204346cz44445pg454e3f4.jpg)

[Kdenlive](https://kdenlive.org/) 是 [KDE](https://www.kde.org/) 上的一个自由且[开源](https://itsfoss.com/tag/open-source/)的视频编辑软件，支持双视频监控、多轨时间线、剪辑列表、自定义布局、基本效果，以及基本过渡效果。

它支持多种文件格式和多种摄像机、相机，包括低分辨率摄像机（Raw 和 AVI DV 编辑）、mpeg2、mpeg4 和 h264 AVCHD（小型相机和便携式摄像机）、高分辨率摄像机文件（包括 HDV 和 AVCHD 摄像机）、专业摄像机（包括 XDCAM-HD™ 流、IMX™ (D10) 流、DVCAM (D10)、DVCAM、DVCPRO™、DVCPRO50™ 流以及 DNxHD™ 流）。

如果你正寻找 Linux 上 iMovie 的替代品，Kdenlive 会是你最好的选择。

Kdenlive 特性：

* 多轨视频编辑
* 多种音视频格式支持
* 可配置的界面和快捷方式
* 使用文本或图像轻松创建切片
* 丰富的效果和过渡
* 音频和视频示波器可确保镜头绝对平衡
* 代理编辑
* 自动保存
* 广泛的硬件支持
* 关键帧效果

优点：

* 通用视频编辑器
* 对于那些熟悉视频编辑的人来说并不太复杂

缺点：

* 如果你想找的是极致简单的编辑软件，它可能还是令你有些困惑
* KDE 应用程序以臃肿而臭名昭著

#### 安装 Kdenlive

Kdenlive 适用于所有主要的 Linux 发行版。你只需在软件中心搜索即可。[Kdenlive 网站的下载部分](https://kdenlive.org/download/)提供了各种软件包。

命令行爱好者可以通过在 Debian 和基于 Ubuntu 的 Linux 发行版中运行以下命令从终端安装它：

```
sudo apt install kdenlive
```

### 2、 OpenShot

![Openshot - ubuntu 上的免费视频编辑器](/data/attachment/album/201811/02/204347tno7ojnq9z9qjq7f.jpg)

[OpenShot](http://www.openshot.org/) 是 Linux 上的另一个多用途视频编辑器。OpenShot 可以帮助你创建具有过渡和效果的视频。你还可以调整声音大小。当然，它支持大多数格式和编解码器。

你还可以将视频导出至 DVD，上传至 YouTube、Vimeo、Xbox 360 以及许多常见的视频格式。OpenShot 比 Kdenlive 要简单一些。因此，如果你需要界面简单的视频编辑器，OpenShot 是一个不错的选择。

它还有个简洁的[开始使用 Openshot](http://www.openshot.org/user-guide/) 文档。

OpenShot 特性：

* 跨平台，可在 Linux、macOS 和 Windows 上使用
* 支持多种视频，音频和图像格式
* 强大的基于曲线的关键帧动画
* 桌面集成与拖放支持
* 不受限制的音视频轨道或图层
* 可剪辑调整大小、缩放、修剪、捕捉、旋转和剪切
* 视频转换可实时预览
* 合成，图像层叠和水印
* 标题模板，标题创建，子标题
* 利用图像序列支持2D动画
* 3D 动画标题和效果
* 支持保存为 SVG 格式以及矢量标题和可信证
* 滚动动态图片
* 帧精度（逐步浏览每一帧视频）
* 剪辑的时间映射和速度更改
* 音频混合和编辑
* 数字视频效果，包括亮度，伽玛，色调，灰度，色度键等

优点：

* 用于一般视频编辑需求的通用视频编辑器
* 可在 Windows 和 macOS 以及 Linux 上使用

缺点：

* 软件用起来可能很简单，但如果你对视频编辑非常陌生，那么肯定需要一个曲折学习的过程
* 你可能仍然没有达到专业级电影制作编辑软件的水准

#### 安装 OpenShot

OpenShot 也可以在所有主流 Linux 发行版的软件仓库中使用。你只需在软件中心搜索即可。你也可以从[官方页面](http://www.openshot.org/download/)中获取它。

在 Debian 和基于 Ubuntu 的 Linux 发行版中，我最喜欢运行以下命令来安装它：

```
sudo apt install openshot
```

### 3、 Shotcut

![Shotcut Linux 视频编辑器](/data/attachment/album/201811/02/204349kbzimpje6u6je2wf.jpg)

[Shotcut](https://www.shotcut.org/) 是 Linux 上的另一个编辑器，可以和 Kdenlive 与 OpenShot 归为同一联盟。虽然它确实与上面讨论的其他两个软件有类似的功能，但 Shotcut 更先进的地方是支持 4K 视频。

支持许多音频、视频格式，过渡和效果是 Shotcut 的众多功能中的一部分。它也支持外部监视器。

这里有一系列视频教程让你[轻松上手 Shotcut](https://www.shotcut.org/tutorials/)。它也可在 Windows 和 macOS 上使用，因此你也可以在其他操作系统上学习。

Shotcut 特性：

* 跨平台，可在 Linux、macOS 和 Windows 上使用
* 支持各种视频，音频和图像格式
* 原生时间线编辑
* 混合并匹配项目中的分辨率和帧速率
* 音频滤波、混音和效果
* 视频转换和过滤
* 具有缩略图和波形的多轨时间轴
* 无限制撤消和重做播放列表编辑，包括历史记录视图
* 剪辑调整大小、缩放、修剪、捕捉、旋转和剪切
* 使用纹波选项修剪源剪辑播放器或时间轴
* 在额外系统显示/监视器上的外部监察
* 硬件支持

你可以在[这里](https://www.shotcut.org/features/)阅它的更多特性。

优点：

* 用于常见视频编辑需求的通用视频编辑器
* 支持 4K 视频
* 可在 Windows，macOS 以及 Linux 上使用

缺点：

* 功能太多降低了软件的易用性

#### 安装 Shotcut

Shotcut 以 [Snap](https://itsfoss.com/use-snap-packages-ubuntu-16-04/) 格式提供。你可以在 Ubuntu 软件中心找到它。对于其他发行版，你可以从此[下载页面](https://www.shotcut.org/download/)获取可执行文件来安装。

### 4、 Flowblade

![Flowblade ubuntu 上的视频编辑器](/data/attachment/album/201811/02/204350k71e99njyd7kkov1.jpg)

[Flowblade](http://jliljebl.github.io/flowblade/) 是 Linux 上的一个多轨非线性视频编辑器。与上面讨论的一样，这也是一个自由开源的软件。它具有时尚和现代化的用户界面。

用 Python 编写，它的设计初衷是快速且准确。Flowblade 专注于在 Linux 和其他自由平台上提供最佳体验。所以它没有在 Windows 和 OS X 上运行的版本。Linux 用户专享其实感觉也不错的。

你也可以查看这个不错的[文档](https://jliljebl.github.io/flowblade/webhelp/help.html)来帮助你使用它的所有功能。

Flowblade 特性：

* 轻量级应用
* 为简单的任务提供简单的界面，如拆分、合并、覆盖等
* 大量的音视频效果和过滤器
* 支持[代理编辑](https://jliljebl.github.io/flowblade/webhelp/proxy.html)
* 支持拖拽
* 支持多种视频、音频和图像格式
* 批量渲染
* 水印
* 视频转换和过滤器
* 具有缩略图和波形的多轨时间轴

你可以在 [Flowblade 特性](https://jliljebl.github.io/flowblade/features.html)里阅读关于它的更多信息。

优点：

* 轻量
* 适用于通用视频编辑

缺点：

* 不支持其他平台

#### 安装 Flowblade

Flowblade 应当在所有主流 Linux 发行版的软件仓库中都可以找到。你可以从软件中心安装它。也可以在[下载页面](https://jliljebl.github.io/flowblade/download.html)查看更多信息。

另外，你可以在 Ubuntu 和基于 Ubuntu 的系统中使用一下命令安装 Flowblade：

```
sudo apt install flowblade
```

### 5、 Lightworks

![Lightworks 运行在 ubuntu 16.04](/data/attachment/album/201811/02/204351udkc8guc82du78lw.jpg)

如果你在寻找一个具有更多特性的视频编辑器，这就是你想要的。[Lightworks](https://www.lwks.com/) 是一个跨平台的专业视频编辑器，可以在 Linux、Mac OS X 以及 Windows上使用。

它是一款屡获殊荣的专业[非线性编辑](https://en.wikipedia.org/wiki/Non-linear_editing_system)（NLE）软件，支持高达 4K 的分辨率以及 SD 和 HD 格式的视频。

Lightworks 可以在 Linux 上使用，然而它不开源。

Lightwokrs 有两个版本：

* Lightworks 免费版
* Lightworks 专业版

专业版有更多功能，比如支持更高的分辨率，支持 4K 和蓝光视频等。

这个[页面](https://www.lwks.com/index.php?option=com_lwks&view=download&Itemid=206&tab=4)有广泛的可用文档。你也可以参考 [Lightworks 视频向导页](https://www.lwks.com/videotutorials)的视频。

Lightworks 特性：

* 跨平台
* 简单直观的用户界面
* 简明的时间线编辑和修剪
* 实时可用的音频和视频FX
* 可用精彩的免版税音频和视频内容
* 适用于 4K 的 Lo-Res 代理工作流程
* 支持导出 YouTube/Vimeo，SD/HD视频，最高可达4K
* 支持拖拽
* 各种音频和视频效果和滤镜

优点：

* 专业，功能丰富的视频编辑器

缺点：

* 免费版有使用限制

#### 安装 Lightworks

Lightworks 为 Debian 和基于 Ubuntu 的 Linux 提供了 DEB 安装包，为基于 Fedora 的 Linux 发行版提供了RPM 安装包。你可以在[下载页面](https://www.lwks.com/index.php?option=com_lwks&view=download&Itemid=206&tab=1)找到安装包。

### 6、 Blender

![Blender 运行在 Ubuntu 16.04](/data/attachment/album/201811/02/204352a640yhq4a9l30aa4.jpg)

[Blender](https://www.blender.org/) 是一个专业的，工业级的开源跨平台视频编辑器。它在制作 3D 作品的工具当中较为流行。Blender 已被用于制作多部好莱坞电影，包括蜘蛛侠系列。

虽然最初设计用于制作 3D 模型，但它也具有多种格式视频的编辑功能。

Blender 特性：

* 实时预览、亮度波形、色度矢量显示和直方图显示
* 音频混合、同步、擦洗和波形可视化
* 最多32个轨道，用于添加视频、图像、音频、场景、面具和效果
* 速度控制、调整图层、过渡、关键帧、过滤器等

你可以在[这里](https://www.blender.org/features/)阅读更多相关特性。

优点：

* 跨平台
* 专业级视频编辑

缺点：

* 复杂
* 主要用于制作 3D 动画，不专门用于常规视频编辑

#### 安装 Blender

Blender 的最新版本可以从[下载页面](https://www.blender.org/download/)下载。

### 7、 Cinelerra

![Cinelerra Linux 上的视频编辑器](/data/attachment/album/201811/02/204354a274mr7aywcym7c4.jpg)

[Cinelerra](http://cinelerra.org/) 从 1998 年发布以来，已被下载超过 500 万次。它是 2003 年第一个在 64 位系统上提供非线性编辑的视频编辑器。当时它是 Linux 用户的首选视频编辑器，但随后一些开发人员丢弃了此项目，它也随之失去了光彩。

好消息是它正回到正轨并且良好地再次发展。

如果你想了解关于 Cinelerra 项目是如何开始的，这里有些[有趣的背景故事](http://cinelerra.org/our-story)。

Cinelerra 特性：

* 非线性编辑
* 支持 HD 视频
* 内置框架渲染器
* 各种视频效果
* 不受限制的图层数量
* 拆分窗格编辑

优点：

* 通用视频编辑器

缺点：

* 不适用于新手
* 没有可用的安装包

#### 安装 Cinelerra

你可以从 [SourceForge](https://sourceforge.net/projects/heroines/files/cinelerra-6-src.tar.xz/download) 下载源码。更多相关信息请看[下载页面](http://cinelerra.org/download)。

### 8、 DaVinci Resolve

![DaVinci Resolve 视频编辑器](/data/attachment/album/201811/02/204355t4vgiesbsgivjv4o.jpg)

如果你想要好莱坞级别的视频编辑器，那就用好莱坞正在使用的专业工具。来自 Blackmagic 公司的 [DaVinci Resolve](https://www.blackmagicdesign.com/products/davinciresolve/) 就是专业人士用于编辑电影和电视节目的专业工具。

DaVinci Resolve 不是常规的视频编辑器。它是一个成熟的编辑工具，在这一个应用程序中提供编辑，色彩校正和专业音频后期制作功能。

DaVinci Resolve 不开源。类似于 LightWorks，它也为 Linux 提供一个免费版本。专业版售价是 $300。

DaVinci Resolve 特性：

* 高性能播放引擎
* 支持所有类型的编辑类型，如覆盖、插入、波纹覆盖、替换、适合填充、末尾追加
* 高级修剪
* 音频叠加
* Multicam Editing 可实现实时编辑来自多个摄像机的镜头
* 过渡和过滤效果
* 速度效果
* 时间轴曲线编辑器
* VFX 的非线性编辑

优点：

* 跨平台
* 专业级视频编辑器

缺点：

* 不适用于通用视频编辑
* 不开源
* 免费版本中有些功能无法使用

#### 安装 DaVinci Resolve

你可以从[这个页面](https://www.blackmagicdesign.com/products/davinciresolve/)下载 DaVinci Resolve。你需要注册，哪怕仅仅下载免费版。

### 9、 VidCutter

![VidCutter Linux 上的视频编辑器](/data/attachment/album/201811/02/204356skf1ofwuakfuvata.jpg)

不像这篇文章讨论的其他视频编辑器，[VidCutter](https://itsfoss.com/vidcutter-video-editor-linux/) 非常简单。除了分割和合并视频之外，它没有其他太多功能。但有时你正好需要 VidCutter 提供的这些功能。

VidCutter 特性：

* 适用于Linux、Windows 和 MacOS 的跨平台应用程序
* 支持绝大多数常见视频格式，例如：AVI、MP4、MPEG 1/2、WMV、MP3、MOV、3GP、FLV 等等
* 界面简单
* 修剪和合并视频，仅此而已

优点：

* 跨平台
* 很适合做简单的视频分割和合并

缺点：

* 不适合用于通用视频编辑
* 经常崩溃

#### 安装 VidCutter

如果你使用的是基于 Ubuntu 的 Linux 发行版，你可以使用这个官方 PPA（LCTT 译注：PPA，个人软件包档案，PersonalPackageArchives）：

```
sudo add-apt-repository ppa:ozmartian/apps
sudo apt-get update
sudo apt-get install vidcutter
```

Arch Linux 用户可以轻松的使用 AUR 安装它。对于其他 Linux 发行版的用户，你可以从这个 [Github 页面](https://github.com/ozmartian/vidcutter/releases)上查找安装文件。

### 哪个是 Linux 上最好的视频编辑软件？

文章里提到的一些视频编辑器使用 [FFmpeg](https://www.ffmpeg.org/)。你也可以自己使用 FFmpeg。它只是一个命令行工具，所以我没有在上文的列表中提到，但一句也不提又不公平。

如果你需要一个视频编辑器来简单的剪切和拼接视频，请使用 VidCutter。

如果你需要的不止这些，**OpenShot** 或者 **Kdenlive** 是不错的选择。他们有规格标准的系统，适用于初学者。

如果你拥有一台高端计算机并且需要高级功能，可以使用 **Lightworks** 或者 **DaVinci Resolve**。如果你在寻找更高级的工具用于制作 3D 作品，你肯定会支持选择 **Blender**。

这就是在 Ubuntu、Linux Mint、Elementary，以及其它发行版等 **Linux 上最好的视频编辑软件**的全部内容。向我们分享你最喜欢的视频编辑器。

---

via: <https://itsfoss.com/best-video-editing-software-linux/>

作者：[itsfoss](https://itsfoss.com/author/itsfoss/) 译者：[fuowang](https://github.com/fuowang) 校对：[wxy](https://github.com/wxy)

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


Gifski：一个跨平台的高质量 GIF 编码器

Summary: 今天，我将向你展示如何从一段视频或者一些图片来制作高质量的 gif 动图。

今天，我将向你展示如何从一段视频或者一些图片来制作高质量的 gif 动图。

![](/data/attachment/album/201811/02/211831hq0ygxiu9k9y0zdo.png)

作为一名文字工作者，我需要在我的文章中添加图片。有时为了更容易讲清楚某个概念，我还会添加视频或者 gif 动图，相比于文字，通过视频或者 gif 格式的输出，读者可以更容易地理解我的指导。前些天，我已经写了篇文章来介绍针对 Linux 的功能丰富的强大截屏工具 [Flameshot](/article-10180-1.html)。今天，我将向你展示如何从一段视频或者一些图片来制作高质量的 gif 动图。这个工具就是 **Gifski**，一个跨平台、开源、基于 **Pngquant** 的高质量命令行 GIF 编码器。

对于那些好奇 pngquant 是什么的读者，简单来说 pngquant 是一个针对 PNG 图片的无损压缩命令行工具。相信我，pngquant 是我使用过的最好的 PNG 无损压缩工具。它可以将 PNG 图片最高压缩 **70%** 而不会损失图片的原有质量并保存了所有的阿尔法透明度。经过压缩的图片可以在所有的网络浏览器和系统中使用。而 Gifski 是基于 Pngquant 的，它使用 pngquant 的功能来创建高质量的 GIF 动图。Gifski 能够创建每帧包含上千种颜色的 GIF 动图。Gifski 也需要 **ffmpeg** 来将视频转换为 PNG 图片。

### 安装 Gifski

首先需要确保你安装了 FFMpeg 和 Pngquant。

FFmpeg 在大多数的 Linux 发行版的默认软件仓库中都可以获取到，所以你可以使用默认的包管理器来安装它。具体的安装过程，请参考下面链接中的指导。

* [在 Linux 中如何安装 FFmpeg](https://www.ostechnix.com/install-ffmpeg-linux/)

Pngquant 可以从 [AUR](https://aur.archlinux.org/packages/pngquant/) 中获取到。要在基于 Arch 的系统安装它，使用任意一个 AUR 帮助程序即可，例如下面示例中的 [Yay](https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/)：

```
$ yay -S pngquant
```

在基于 Debian 的系统中，运行：

```
$ sudo apt install pngquant
```

假如在你使用的发行版中没有 pngquant，你可以从源码编译并安装它。为此你还需要安装 `libpng-dev` 包。

```
$ git clone --recursive https://github.com/kornelski/pngquant.git
$ make
$ sudo make install
```

安装完上述依赖后，再安装 Gifski。假如你已经安装了 [Rust](https://www.ostechnix.com/install-rust-programming-language-in-linux/) 编程语言，你可以使用 **cargo** 来安装它：

```
$ cargo install gifski
```

另外，你还可以使用 [Linuxbrew](https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/) 包管理器来安装它：

```
$ brew install gifski
```

假如你不想安装 cargo 或 Linuxbrew，可以从它的 [发布页面](https://github.com/ImageOptim/gifski/releases) 下载最新的二进制程序，或者手动从源码编译并安装 gifski 。

### 使用 Gifski 来创建高质量的 GIF 动图

进入你保存 PNG 图片的目录，然后运行下面的命令来从这些图片创建 GIF 动图：

```
$ gifski -o file.gif *.png
```

上面的 `file.gif` 为最后输出的 gif 动图。

Gifski 还有其他的特性，例如：

* 创建特定大小的 GIF 动图
* 在每秒钟展示特定数目的动图
* 以特定的质量编码
* 更快速度的编码
* 以给定顺序来编码图片，而不是以排序的结果来编码

为了创建特定大小的 GIF 动图，例如宽为 800，高为 400，可以使用下面的命令：

```
$ gifski -o file.gif -W 800 -H 400 *.png
```

你可以设定 GIF 动图在每秒钟展示多少帧，默认值是 **20**。为此，可以运行下面的命令：

```
$ gifski -o file.gif --fps 1 *.png
```

在上面的例子中，我指定每秒钟展示 1 帧。

我们还能够以特定质量（1-100 范围内）来编码。显然，更低的质量将生成更小的文件，更高的质量将生成更大的 GIF 动图文件。

```
$ gifski -o file.gif --quality 50 *.png
```

当需要编码大量图片时，Gifski 将会花费更多时间。如果想要编码过程加快到通常速度的 3 倍左右，可以运行：

```
$ gifski -o file.gif --fast *.png
```

请注意上面的命令产生的 GIF 动图文件将减少 10% 的质量，并且文件大小也会更大。

如果想让图片以某个给定的顺序（而不是通过排序）精确地被编码，可以使用 `--nosort` 选项。

```
$ gifski -o file.gif --nosort *.png
```

假如你不想让 GIF 循环播放，只需要使用 `--once` 选项即可：

```
$ gifski -o file.gif --once *.png
```

### 从视频创建 GIF 动图

有时或许你想从一个视频创建 GIF 动图。这也是可以做到的，这时候 FFmpeg 便能提供帮助。首先像下面这样，将视频转换成一系列的 PNG 图片：

```
$ ffmpeg -i video.mp4 frame%04d.png
```

上面的命令将会从 `video.mp4` 这个视频文件创建名为 “frame0001.png”、“frame0002.png”、“frame0003.png” 等等形式的图片（其中的 `%04d` 代表帧数），然后将这些图片保存在当前的工作目录。

转换好图片后，只需要运行下面的命令便可以制作 GIF 动图了：

```
$ gifski -o file.gif *.png
```

想知晓更多的细节，请参考它的帮助部分：

```
$ gifski -h
```

[这是](https://gif.ski/jazz-chromecast-ultra.gif)使用 Gifski 创建的示例 GIF 动图文件。

正如你看到的那样，GIF 动图的质量看起来是非常好的。

好了，这就是全部内容了。希望这篇指南对你有所帮助。更多精彩内容即将呈现，请保持关注！

干杯吧！

---

```
via: https://www.ostechnix.com/gifski-a-cross-platform-high-quality-gif-encoder/
```

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

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


6 个用于写书的开源工具

Summary: 这些多能、免费的工具可以满足你撰写、编辑和生成你自己的书籍的全部需求。

这些多能、免费的工具可以满足你撰写、编辑和生成你自己的书籍的全部需求。

>
> 这些多能、免费的工具可以满足你撰写、编辑和生成你自己的书籍的全部需求。
>
>
>

![](/data/attachment/album/201811/02/214546jj828j99tt88d08d.png)

我在 1993 年首次使用并贡献了免费和开源软件，从那时起我一直是一名开源软件的开发人员和布道者。尽管我被记住的一个项目是 [FreeDOS 项目](http://www.freedos.org/)，这是一个 DOS 操作系统的开源实现，但我已经编写或者贡献了数十个开源软件项目。

我最近写了一本关于 FreeDOS 的书。《[使用 FreeDOS](http://www.freedos.org/ebook/)》是我庆祝 FreeDOS 出现 24 周年而撰写的。它是关于安装和使用 FreeDOS、关于我最喜欢的 DOS 程序，以及 DOS 命令行和 DOS 批处理编程的快速参考指南的集合。在一位出色的专业编辑的帮助下，我在过去的几个月里一直在编写这本书。

《使用 FreeDOS》 可在知识共享署名（cc-by）国际公共许可证下获得。你可以从 [FreeDOS 电子书](http://www.freedos.org/ebook/)网站免费下载 EPUB 和 PDF 版本。（我也计划为那些喜欢纸质的人提供印刷版本。）

这本书几乎完全是用开源软件制作的。我想分享一下对用来创建、编辑和生成《使用 FreeDOS》的工具的看法。

### Google 文档

[Google 文档](https://www.google.com/docs/about/)是我使用的唯一不是开源软件的工具。我将我的第一份草稿上传到 Google 文档，这样我就能与编辑器进行协作。我确信有开源协作工具，但 Google 文档能够让两个人同时编辑同一个文档、发表评论、编辑建议和更改跟踪 —— 更不用说它使用段落样式和能够下载完成的文档 —— 这使其成为编辑过程中有价值的一部分。

### LibreOffice

我开始使用的是 [LibreOffice](https://www.libreoffice.org/) 6.0，但我最终使用 LibreOffice 6.1 完成了这本书。我喜欢 LibreOffice 对样式的丰富支持。段落样式可以轻松地为标题、页眉、正文、示例代码和其他文本应用样式。字符样式允许我修改段落中文本的外观，例如内联示例代码或用不同的样式代表文件名。图形样式让我可以将某些样式应用于截图和其他图像。页面样式允许我轻松修改页面的布局和外观。

### GIMP

我的书包括很多 DOS 程序截图、网站截图和 FreeDOS 的 logo。我用 [GIMP](https://www.gimp.org/) 修改这本书的图像。通常，只是裁剪或调整图像大小，但在我准备本书的印刷版时，我使用 GIMP 创建了一些更适于打印布局的图像。

### Inkscape

大多数 FreeDOS 的 logo 和小鱼吉祥物都是 SVG 格式，我使用 [Inkscape](https://inkscape.org/) 来调整它们。在准备电子书的 PDF 版本时，我想在页面顶部放置一个简单的蓝色横幅，角落里有 FreeDOS 的 logo。实验后，我发现在 Inkscape 中创建一个我想要的横幅 SVG 图案更容易，然后我将其粘贴到页眉中。

### ImageMagick

虽然使用 GIMP 来完成这项工作也很好，但有时在一组图像上运行 [ImageMagick](https://www.imagemagick.org/) 命令会更快，例如转换为 PNG 格式或调整图像大小。

### Sigil

LibreOffice 可以直接导出到 EPUB 格式，但它不是个好的转换器。我没有尝试使用 LibreOffice 6.1 创建 EPUB，但在 LibreOffice 6.0 中没有包含我的图像。它还以奇怪的方式添加了样式。我使用 [Sigil](https://sigil-ebook.com/) 来调整 EPUB 并使一切看起来正常。Sigil 甚至还有预览功能，因此你可以看到 EPUB 的样子。

### QEMU

因为本书是关于安装和运行 FreeDOS 的，所以我需要实际运行 FreeDOS。你可以在任何 PC 模拟器中启动 FreeDOS，包括 VirtualBox、QEMU、GNOME Boxes、PCem 和 Bochs。但我喜欢 [QEMU](https://www.qemu.org/) 的简单性。QEMU 控制台允许你以 PPM 格式转储屏幕，这非常适合抓取截图来包含在书中。

当然，我不得不提到在 [Linux](https://www.kernel.org/) 上运行 [GNOME](https://www.gnome.org/)。我使用 Linux 的 [Fedora](https://getfedora.org/) 发行版。

---

via: <https://opensource.com/article/18/9/writing-book-open-source-tools>

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


10 个最值得关注的树莓派博客

Summary: 如果你正在计划你的下一个树莓派项目，那么这些博客或许有帮助。

如果你正在计划你的下一个树莓派项目，那么这些博客或许有帮助。

>
> 如果你正在计划你的下一个树莓派项目，那么这些博客或许有帮助。
>
>
>

![](/data/attachment/album/201811/02/231408nnq8es4n8c8cc3zy.png)

网上有很多很棒的树莓派爱好者网站、教程、代码仓库、YouTube 频道和其他资源。以下是我最喜欢的十大树莓派博客，排名不分先后。

### 1、Raspberry Pi Spy

树莓派粉丝 Matt Hawkins 从很早开始就在他的网站 [Raspberry Pi Spy](https://www.raspberrypi-spy.co.uk/) 上撰写了大量全面且信息丰富的教程。我从这个网站上直接学到了很多东西，而且 Matt 似乎也总是涵盖到众多主题的第一个人。在我学习使用树莓派的前三年里，多次在这个网站得到帮助。

值得庆幸的是，这个不断采用新技术的网站仍然很强大。我希望看到它继续存在下去，让新社区成员在需要时得到帮助。

### 2、Adafruit

[Adafruit](https://blog.adafruit.com/category/raspberry-pi/) 是硬件黑客中知名品牌之一。该公司制作和销售漂亮的硬件，并提供由员工、社区成员，甚至 Lady Ada 女士自己编写的优秀教程。

除了网上商店，Adafruit 还经营一个博客，这个博客充满了来自世界各地的精彩内容。在博客上可以查看树莓派的类别，特别是在工作日的最后一天，会在 Adafruit Towers 举办名为 [Friday is Pi Day](https://blog.adafruit.com/category/raspberry-pi/) 的活动。

### 3、Recantha 的 Raspberry Pi Pod

Mike Horne（Recantha）是英国一位重要的树莓派社区成员，负责 [CamJam 和 Potton Pi＆Pint](https://camjam.me/?page_id=753)（剑桥的两个树莓派社团）以及 [Pi Wars](https://piwars.org/) （一年一度的树莓派机器人竞赛）。他为其他人建立树莓派社团提供建议，并且总是有时间帮助初学者。Horne 和他的共同组织者 Tim Richardson 一起开发了 CamJam Edu Kit （一系列小巧且价格合理的套件，适合初学者使用 Python 学习物理计算）。

除此之外，他还运营着 [Pi Pod](https://www.recantha.co.uk/blog/)，这是一个包含了世界各地树莓派相关内容的博客。它可能是这个列表中更新最频繁的树莓派博客，所以这是一个把握树莓派社区动向的极好方式。

### 4. Raspberry Pi 官方博客

必须提一下[树莓派基金会](https://www.raspberrypi.org/blog/)的官方博客，这个博客涵盖了基金会的硬件、软件、教育、社区、慈善和青年编码俱乐部的一系列内容。博客上的大型主题是家庭数字化、教育授权，以及硬件版本和软件更新的官方新闻。

该博客自 [2011 年](https://www.raspberrypi.org/blog/first-post/) 运行至今，并提供了自那时以来所有 1800 多个帖子的 [存档](https://www.raspberrypi.org/blog/archive/) 。你也可以在 Twitter 上关注[@raspberrypi\_otd](https://twitter.com/raspberrypi_otd)，这是我用 [Python](https://github.com/bennuttall/rpi-otd-bot/blob/master/src/bot.py) 创建的机器人（教程在这里：[Opensource.com](https://opensource.com/article/17/8/raspberry-pi-twitter-bot)）。Twitter 机器人推送来自博客存档的过去几年同一天的树莓派帖子。

### 5、RasPi.tv

另一位开创性的树莓派社区成员是 Alex Eames，通过他的博客和 YouTube 频道 [RasPi.tv](https://rasp.tv/)，他很早就加入了树莓派社区。他的网站为很多创客项目提供高质量、精心制作的视频教程和书面指南。

Alex 的网站 [RasP.iO](https://rasp.io/) 制作了一系列树莓派附加板和配件，包括方便的 GPIO 端口引脚、电路板测量尺等等。他的博客也拓展到了 [Arduino](https://www.arduino.cc/)、[WEMO](http://community.wemo.com/) 以及其他小网站。

### 6、pyimagesearch

虽然不是严格的树莓派博客（名称中的“py”是“Python”，而不是“树莓派”），但该网站的 [树莓派栏目](https://www.pyimagesearch.com/category/raspberry-pi/) 有着大量内容。 Adrian Rosebrock 获得了计算机视觉和机器学习领域的博士学位，他的博客旨在分享他在学习和制作自己的计算机视觉项目时所学到的机器学习技巧。

如果你想使用树莓派的相机模块学习面部或物体识别，来这个网站就对了。Adrian 在图像识别领域的深度学习和人工智能知识和实际应用是首屈一指的，而且他编写了自己的项目，这样任何人都可以进行尝试。

### 7、Raspberry Pi Roundup

这个[博客](https://thepihut.com/blogs/raspberry-pi-roundup)由英国官方树莓派经销商之一 The Pi Hut 进行维护，会有每周的树莓派新闻。这是另一个很好的资源，可以紧跟树莓派社区的最新资讯，而且之前的文章也值得回顾。

### 8、Dave Akerman

[Dave Akerman](http://www.daveakerman.com/) 是研究高空热气球的一流专家，他分享使用树莓派以最低的成本进行热气球发射方面的知识和经验。他会在一张由热气球拍摄的平流层照片下面对本次发射进行评论，也会对个人发射树莓派热气球给出自己的建议。

查看 Dave 的[博客](http://www.daveakerman.com/)，了解精彩的临近空间摄影作品。

### 9、Pimoroni

[Pimoroni](https://blog.pimoroni.com/) 是一家世界知名的树莓派经销商，其总部位于英国谢菲尔德。这家经销商制作了著名的 [树莓派彩虹保护壳](https://shop.pimoroni.com/products/pibow-for-raspberry-pi-3-b-plus)，并推出了许多极好的定制附加板和配件。

Pimoroni 的博客布局与其硬件设计和品牌推广一样精美，博文内容非常适合创客和业余爱好者在家进行创作，并且可以在有趣的 YouTube 频道 [Bilge Tank](https://www.youtube.com/channel/UCuiDNTaTdPTGZZzHm0iriGQ) 上找到。

### 10、Stuff About Code

Martin O'Hanlon 以树莓派社区成员的身份转为了树莓派基金会的员工，他起初出于乐趣在树莓派上开发“我的世界”作弊器，最近作为内容编辑加入了树莓派基金会。幸运的是，马丁的新工作并没有阻止他更新[博客](https://www.stuffaboutcode.com/)并与世界分享有益的趣闻。

除了“我的世界”的很多内容，你还可以在 Python 库、[Blue Dot](https://bluedot.readthedocs.io/en/latest/#) 和 [guizero](https://lawsie.github.io/guizero/) 上找到 Martin O'Hanlon 的贡献，以及一些总结性的树莓派技巧。

---

via: <https://opensource.com/article/18/8/top-10-raspberry-pi-blogs-follow>

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

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


9 个提升开发者与设计师协作的方法

>
> 抛开成见，设计师和开发者的命运永远交织在一起。 以下是如何让每个人都在同一页面上。
>
>
>

![](/data/attachment/album/201811/03/231741r8atzzk0k1jtja8t.png)

在任何软件项目中，设计至关重要。设计师不像开发团队那样熟悉其内部工作，但迟早都要知道开发人员写代码的意图。

两边都有自己的成见。工程师经常认为设计师们古怪不理性，而设计师也认为工程师们死板要求高。在一天的工作快要结束时，情况会变得更加微妙。设计师和开发者们的命运永远交织在一起。

做到以下九件事，便可以改进他们之间的合作。

### 1. 首先，说实在的，打破壁垒

几乎每一个行业都有“<ruby> 迷墙 <rt>  wall of confusion </rt></ruby>”的因子。无论你干什么工作，拆除这堵墙的第一步就是要双方都认同它需要拆除。一旦所有的人都认为现有的流程效率低下，你就可以从其它想法中获得灵感，然后解决问题。

### 2. 学会共情

在开始干之前，先等一下。这是团队建设的重要的交汇点，也是建立共同认知的时机：我们都是成人，我们都有自己的优点与缺点，更重要的是，我们是一个团队。围绕工作流程与工作效率的讨论会经常发生，因此在开始之前，建立一个信任与协作的基础至关重要。

### 3. 认识差异

设计师和开发者从不同的角度攻克问题。对于相同的问题，设计师会追求更好的效果，而开发者会寻求更高的效率。这两种观点不必互相排斥。谈判和妥协的余地很大，并且在二者之间必然存在一个用户满意度最佳的中点。

### 4. 拥抱共性

这一切都是与工作流程相关的。<ruby> 持续集成 <rt>  Continuous Integration </rt></ruby>/<ruby> 持续交付 <rt>  Continuous Delivery </rt></ruby>，scrum，agile 等等，都基本上说了一件事：构思，迭代，考察，重复。迭代和重复是两种工作的相同点。因此，不再让开发周期紧跟设计周期，而是同时并行地运行它们，这样会更有意义。<ruby> 同步周期 <rt>  Syncing cycles </rt></ruby>允许团队在每个环节交流、协作、互相影响。

### 5. 管理期望

一切冲突的起因一言以蔽之：期望不符。因此，防止系统性分裂的简单办法就是通过确保团队成员在说之前先想、在做之前先说来管理期望。设定的期望往往会通过日常对话不断演变。强迫团队通过开会以达到其效果可能会适得其反。

### 6. 按需开会

只在工作开始和工作结束开一次会远远不够。但也不意味着每天或每周都要开会。定期开会也可能会适得其反。试着按需开会吧。即兴会议，即使是员工闲聊，也可能会发生很棒的事情。如果你的团队是分散式的或者甚至有一名远程员工，视频会议，文本聊天或者打电话都是开会的好方法。团队中的每人都有多种方式互相沟通，这一点非常重要。

### 7. 建立词库

设计师和开发者有时候对相似的想法有着不同的术语，就像把猫叫成喵。毕竟，比起术语的准确度和合适度来，大家统一说法才更重要。

### 8. 学会沟通

无论什么时候，团队中的每个人都有责任去维持一个有效的沟通。每个人都应该努力做到一字一板。

### 9. 不断改善

仅一名团队成员就能破坏整个进度。全力以赴。如果每个人都不关心产品或目标，继续项目或者做出改变的动机就会出现问题。

---

via: <https://opensource.com/article/18/5/9-ways-improve-collaboration-developers-designers>

作者：[Jason Brock](https://opensource.com/users/jkbrock), [Jason Porter](https://opensource.com/users/lightguardjp) 选题：[lujun9972](https://github.com/lujun9972) 译者：[LuuMing](https://github.com/LuuMing) 校对：[pityonline](https://github.com/pityonline)

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


如何分析并探索 Docker 容器镜像的内容

Summary: 我们将学会使用一个名为 Dive 的工具来分析和探索 Docker 镜像每层的内容。

![](/data/attachment/album/201811/03/234700k5dg5drb5eh35sns.png)

或许你已经了解到 Docker 容器镜像是一个轻量、独立、含有运行某个应用所需全部软件的可执行包，这也是为什么容器镜像会经常被开发者用于构建和分发应用。假如你很好奇一个 Docker 镜像里面包含了什么东西，那么这篇简要的指南或许会帮助到你。今天，我们将学会使用一个名为 **Dive** 的工具来分析和探索 Docker 镜像每层的内容。

通过分析 Docker 镜像，我们可以发现在各个层之间可能重复的文件并通过移除它们来减小 Docker 镜像的大小。Dive 工具不仅仅是一个 Docker 镜像分析工具，它还可以帮助我们来构建镜像。Dive 是一个用 Go 编程语言编写的自由开源工具。

### 安装 Dive

首先从该项目的 [发布页](https://github.com/wagoodman/dive/releases) 下载最新版本，然后像下面展示的那样根据你所使用的发行版来安装它。

假如你正在使用 **Debian** 或者 **Ubuntu**，那么可以运行下面的命令来下载并安装它。

```
$ wget https://github.com/wagoodman/dive/releases/download/v0.0.8/dive_0.0.8_linux_amd64.deb
```

```
$ sudo apt install ./dive_0.0.8_linux_amd64.deb
```

**在 RHEL 或 CentOS 系统中**

```
$ wget https://github.com/wagoodman/dive/releases/download/v0.0.8/dive_0.0.8_linux_amd64.rpm
```

```
$ sudo rpm -i dive_0.0.8_linux_amd64.rpm
```

Dive 也可以使用 [Linuxbrew](https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/) 包管理器来安装。

```
$ brew tap wagoodman/dive
```

```
$ brew install dive
```

至于其他的安装方法，请参考 [Dive 项目的 GitHub 网页](https://github.com/wagoodman/dive)。

### 分析并探索 Docker 镜像的内容

要分析一个 Docker 镜像，只需要运行加上 Docker 镜像 ID 的 `dive` 命令就可以了。你可以使用 `sudo docker images` 来得到 Docker 镜像的 ID。

```
$ sudo dive ea4c82dcd15a
```

上面命令中的 `ea4c82dcd15a` 是某个镜像的 ID。

然后 `dive` 命令将快速地分析给定 Docker 镜像的内容并将它在终端中展示出来。

![](/data/attachment/album/201811/03/234701nornboi7ue0o9l0e.png)

正如你在上面的截图中看到的那样，在终端的左边一栏列出了给定 Docker 镜像的各个层及其详细内容，浪费的空间大小等信息。右边一栏则给出了给定 Docker 镜像每一层的内容。你可以使用 `Ctrl+空格` 来在左右栏之间切换，使用 `UP`/`DOWN` 光标键来在目录树中进行浏览。

下面是 `dive` 的快捷键列表：

* `Ctrl+空格` —— 在左右栏之间切换
* `空格` —— 展开或收起目录树
* `Ctrl+A` —— 文件树视图：展示或隐藏增加的文件
* `Ctrl+R` —— 文件树视图：展示或隐藏被移除的文件
* `Ctrl+M` —— 文件树视图：展示或隐藏被修改的文件
* `Ctrl+U` —— 文件树视图：展示或隐藏未修改的文件
* `Ctrl+L` —— 层视图：展示当前层的变化
* `Ctrl+A` —— 层视图：展示总的变化
* `Ctrl+/` —— 筛选文件
* `Ctrl+C` —— 退出

在上面的例子中，我使用了 `sudo` 权限，这是因为我的 Docker 镜像存储在 `/var/lib/docker/` 目录中。假如你的镜像保存在你的家目录 （`$HOME`）或者在其他不属于 `root` 用户的目录，你就没有必要使用 `sudo` 命令。

你还可以使用下面的单个命令来构建一个 Docker 镜像并立刻分析该镜像：

```
$ dive build -t <some-tag>
```

Dive 工具仍处于 beta 阶段，所以可能会存在 bug。假如你遇到了 bug，请在该项目的 GitHub 主页上进行报告。

好了，这就是今天的全部内容。现在你知道如何使用 Dive 工具来探索和分析 Docker 容器镜像的内容以及利用它构建镜像。希望本文对你有所帮助。

更多精彩内容即将呈现，请保持关注！

干杯！

---

via: <https://www.ostechnix.com/how-to-analyze-and-explore-the-contents-of-docker-images/>

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

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


在 Linux 命令行中使用 tcpdump 抓包

Summary: tcpdump 是一款灵活、功能强大的抓包工具，能有效地帮助排查网络故障问题。

作者大大赞一个

介绍的十分详细，对我帮助很大，感谢！

感谢。

太赞了

有用。

感谢大佬

感谢，有用

感谢，有用

感谢

写的真好

写的真好

tcpdump 是一款灵活、功能强大的抓包工具，能有效地帮助排查网络故障问题。

>
> `tcpdump` 是一款灵活、功能强大的抓包工具，能有效地帮助排查网络故障问题。
>
>
>

![](/data/attachment/album/201811/04/002029aif53buzlzlrbei2.jpg)

以我作为管理员的经验，在网络连接中经常遇到十分难以排查的故障问题。对于这类情况，`tcpdump` 便能派上用场。

`tcpdump` 是一个命令行实用工具，允许你抓取和分析经过系统的流量数据包。它通常被用作于网络故障分析工具以及安全工具。

`tcpdump` 是一款强大的工具，支持多种选项和过滤规则，适用场景十分广泛。由于它是命令行工具，因此适用于在远程服务器或者没有图形界面的设备中收集数据包以便于事后分析。它可以在后台启动，也可以用 cron 等定时工具创建定时任务启用它。

本文中，我们将讨论 `tcpdump` 最常用的一些功能。

### 1、在 Linux 中安装 tcpdump

`tcpdump` 支持多种 Linux 发行版，所以你的系统中很有可能已经安装了它。用下面的命令检查一下是否已经安装了 `tcpdump`：

```
$ which tcpdump
/usr/sbin/tcpdump
```

如果还没有安装 `tcpdump`，你可以用软件包管理器安装它。 例如，在 CentOS 或者 Red Hat Enterprise 系统中，用如下命令安装 `tcpdump`：

```
$ sudo yum install -y tcpdump
```

`tcpdump` 依赖于 `libpcap`，该库文件用于捕获网络数据包。如果该库文件也没有安装，系统会根据依赖关系自动安装它。

现在你可以开始抓包了。

### 2、用 tcpdump 抓包

使用 `tcpdump` 抓包，需要管理员权限，因此下面的示例中绝大多数命令都是以 `sudo` 开头。

首先，先用 `tcpdump -D` 命令列出可以抓包的网络接口：

```
$ sudo tcpdump -D
1.eth0
2.virbr0
3.eth1
4.any (Pseudo-device that captures on all interfaces)
5.lo [Loopback]
```

如上所示，可以看到我的机器中所有可以抓包的网络接口。其中特殊接口 `any` 可用于抓取所有活动的网络接口的数据包。

我们就用如下命令先对 `any` 接口进行抓包：

```
$ sudo tcpdump -i any
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
09:56:18.293641 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3770820720:3770820916, ack 3503648727, win 309, options [nop,nop,TS val 76577898 ecr 510770929], length 196
09:56:18.293794 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 391, options [nop,nop,TS val 510771017 ecr 76577898], length 0
09:56:18.295058 IP rhel75.59883 > gateway.domain: 2486+ PTR? 1.64.168.192.in-addr.arpa. (43)
09:56:18.310225 IP gateway.domain > rhel75.59883: 2486 NXDomain* 0/1/0 (102)
09:56:18.312482 IP rhel75.49685 > gateway.domain: 34242+ PTR? 28.64.168.192.in-addr.arpa. (44)
09:56:18.322425 IP gateway.domain > rhel75.49685: 34242 NXDomain* 0/1/0 (103)
09:56:18.323164 IP rhel75.56631 > gateway.domain: 29904+ PTR? 1.122.168.192.in-addr.arpa. (44)
09:56:18.323342 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 196:584, ack 1, win 309, options [nop,nop,TS val 76577928 ecr 510771017], length 388
09:56:18.323563 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 584, win 411, options [nop,nop,TS val 510771047 ecr 76577928], length 0
09:56:18.335569 IP gateway.domain > rhel75.56631: 29904 NXDomain* 0/1/0 (103)
09:56:18.336429 IP rhel75.44007 > gateway.domain: 61677+ PTR? 98.122.168.192.in-addr.arpa. (45)
09:56:18.336655 IP gateway.domain > rhel75.44007: 61677* 1/0/0 PTR rhel75. (65)
09:56:18.337177 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 584:1644, ack 1, win 309, options [nop,nop,TS val 76577942 ecr 510771047], length 1060

---- SKIPPING LONG OUTPUT -----

09:56:19.342939 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 1752016, win 1444, options [nop,nop,TS val 510772067 ecr 76578948], length 0
^C
9003 packets captured
9010 packets received by filter
7 packets dropped by kernel
$
```

`tcpdump` 会持续抓包直到收到中断信号。你可以按 `Ctrl+C` 来停止抓包。正如上面示例所示，`tcpdump` 抓取了超过 9000 个数据包。在这个示例中，由于我是通过 `ssh` 连接到服务器，所以 `tcpdump` 也捕获了所有这类数据包。`-c` 选项可以用于限制 `tcpdump` 抓包的数量：

```
$ sudo tcpdump -i any -c 5
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
11:21:30.242740 IP rhel75.localdomain.ssh > 192.168.64.1.56322: Flags [P.], seq 3772575680:3772575876, ack 3503651743, win 309, options [nop,nop,TS val 81689848 ecr 515883153], length 196
11:21:30.242906 IP 192.168.64.1.56322 > rhel75.localdomain.ssh: Flags [.], ack 196, win 1443, options [nop,nop,TS val 515883235 ecr 81689848], length 0
11:21:30.244442 IP rhel75.43634 > gateway.domain: 57680+ PTR? 1.64.168.192.in-addr.arpa. (43)
11:21:30.244829 IP gateway.domain > rhel75.43634: 57680 NXDomain 0/0/0 (43)
11:21:30.247048 IP rhel75.33696 > gateway.domain: 37429+ PTR? 28.64.168.192.in-addr.arpa. (44)
5 packets captured
12 packets received by filter
0 packets dropped by kernel
$
```

如上所示，`tcpdump` 在抓取 5 个数据包后自动停止了抓包。这在有些场景中十分有用 —— 比如你只需要抓取少量的数据包用于分析。当我们需要使用过滤规则抓取特定的数据包（如下所示）时，`-c` 的作用就十分突出了。

在上面示例中，`tcpdump` 默认是将 IP 地址和端口号解析为对应的接口名以及服务协议名称。而通常在网络故障排查中，使用 IP 地址和端口号更便于分析问题；用 `-n` 选项显示 IP 地址，`-nn` 选项显示端口号：

```
$ sudo tcpdump -i any -c5 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
23:56:24.292206 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 166198580:166198776, ack 2414541257, win 309, options [nop,nop,TS val 615664 ecr 540031155], length 196
23:56:24.292357 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 196, win 1377, options [nop,nop,TS val 540031229 ecr 615664], length 0
23:56:24.292570 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 372
23:56:24.292655 IP 192.168.64.1.35110 > 192.168.64.28.22: Flags [.], ack 568, win 1400, options [nop,nop,TS val 540031229 ecr 615664], length 0
23:56:24.292752 IP 192.168.64.28.22 > 192.168.64.1.35110: Flags [P.], seq 568:908, ack 1, win 309, options [nop,nop,TS val 615664 ecr 540031229], length 340
5 packets captured
6 packets received by filter
0 packets dropped by kernel
```

如上所示，抓取的数据包中显示 IP 地址和端口号。这样还可以阻止 `tcpdump` 发出 DNS 查找，有助于在网络故障排查中减少数据流量。

现在你已经会抓包了，让我们来分析一下这些抓包输出的含义吧。

### 3、理解抓取的报文

`tcpdump` 能够抓取并解码多种协议类型的数据报文，如 TCP、UDP、ICMP 等等。虽然这里我们不可能介绍所有的数据报文类型，但可以分析下 TCP 类型的数据报文，来帮助你入门。更多有关 `tcpdump` 的详细介绍可以参考其 [帮助手册](http://www.tcpdump.org/manpages/tcpdump.1.html#lbAG)。`tcpdump` 抓取的 TCP 报文看起来如下：

```
08:41:13.729687 IP 192.168.64.28.22 > 192.168.64.1.41916: Flags [P.], seq 196:568, ack 1, win 309, options [nop,nop,TS val 117964079 ecr 816509256], length 372
```

具体的字段根据不同的报文类型会有不同，但上面这个例子是一般的格式形式。

第一个字段 `08:41:13.729687` 是该数据报文被抓取的系统本地时间戳。

然后，`IP` 是网络层协议类型，这里是 `IPv4`，如果是 `IPv6` 协议，该字段值是 `IP6`。

`192.168.64.28.22` 是源 ip 地址和端口号，紧跟其后的是目的 ip 地址和其端口号，这里是 `192.168.64.1.41916`。

在源 IP 和目的 IP 之后，可以看到是 TCP 报文标记段 `Flags [P.]`。该字段通常取值如下：

| 值 | 标志类型 | 描述 |
| --- | --- | --- |
| S | SYN | Connection Start |
| F | FIN | Connection Finish |
| P | PUSH | Data push |
| R | RST | Connection reset |
| . | ACK | Acknowledgment |

该字段也可以是这些值的组合，例如 `[S.]` 代表 `SYN-ACK` 数据包。

接下来是该数据包中数据的序列号。对于抓取的第一个数据包，该字段值是一个绝对数字，后续包使用相对数值，以便更容易查询跟踪。例如此处 `seq 196:568` 代表该数据包包含该数据流的第 196 到 568 字节。

接下来是 ack 值：`ack 1`。该数据包是数据发送方，ack 值为 1。在数据接收方，该字段代表数据流上的下一个预期字节数据，例如，该数据流中下一个数据包的 ack 值应该是 568。

接下来字段是接收窗口大小 `win 309`，它表示接收缓冲区中可用的字节数，后跟 TCP 选项如 MSS（最大段大小）或者窗口比例值。更详尽的 TCP 协议内容请参考 [Transmission Control Protocol(TCP) Parameters](https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml)。

最后，`length 372` 代表数据包有效载荷字节长度。这个长度和 seq 序列号中字节数值长度是不一样的。

现在让我们学习如何过滤数据报文以便更容易的分析定位问题。

### 4、过滤数据包

正如上面所提，`tcpdump` 可以抓取很多种类型的数据报文，其中很多可能和我们需要查找的问题并没有关系。举个例子，假设你正在定位一个与 web 服务器连接的网络问题，就不必关系 SSH 数据报文，因此在抓包结果中过滤掉 SSH 报文可能更便于你分析问题。

`tcpdump` 有很多参数选项可以设置数据包过滤规则，例如根据源 IP 以及目的 IP 地址，端口号，协议等等规则来过滤数据包。下面就介绍一些最常用的过滤方法。

#### 协议

在命令中指定协议便可以按照协议类型来筛选数据包。比方说用如下命令只要抓取 ICMP 报文：

```
$ sudo tcpdump -i any -c5 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
```

然后再打开一个终端，去 ping 另一台机器：

```
$ ping opensource.com
PING opensource.com (54.204.39.132) 56(84) bytes of data.
64 bytes from ec2-54-204-39-132.compute-1.amazonaws.com (54.204.39.132): icmp_seq=1 ttl=47 time=39.6 ms
```

回到运行 `tcpdump` 命令的终端中，可以看到它筛选出了 ICMP 报文。这里 `tcpdump` 并没有显示有关 `opensource.com` 的域名解析数据包：

```
09:34:20.136766 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 1, length 64
09:34:20.176402 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 1, length 64
09:34:21.140230 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 2, length 64
09:34:21.180020 IP ec2-54-204-39-132.compute-1.amazonaws.com > rhel75: ICMP echo reply, id 20361, seq 2, length 64
09:34:22.141777 IP rhel75 > ec2-54-204-39-132.compute-1.amazonaws.com: ICMP echo request, id 20361, seq 3, length 64
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

#### 主机

用 `host` 参数只抓取和特定主机相关的数据包：

```
$ sudo tcpdump -i any -c5 -nn host 54.204.39.132
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
09:54:20.042023 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [S], seq 1375157070, win 29200, options [mss 1460,sackOK,TS val 122350391 ecr 0,nop,wscale 7], length 0
09:54:20.088127 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [S.], seq 1935542841, ack 1375157071, win 28960, options [mss 1460,sackOK,TS val 522713542 ecr 122350391,nop,wscale 9], length 0
09:54:20.088204 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122350437 ecr 522713542], length 0
09:54:20.088734 IP 192.168.122.98.39326 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122350438 ecr 522713542], length 112: HTTP: GET / HTTP/1.1
09:54:20.129733 IP 54.204.39.132.80 > 192.168.122.98.39326: Flags [.], ack 113, win 57, options [nop,nop,TS val 522713552 ecr 122350438], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

如上所示，只抓取和显示与 `54.204.39.132` 有关的数据包。

#### 端口号

`tcpdump` 可以根据服务类型或者端口号来筛选数据包。例如，抓取和 HTTP 服务相关的数据包：

```
$ sudo tcpdump -i any -c5 -nn port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
09:58:28.790548 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [S], seq 1745665159, win 29200, options [mss 1460,sackOK,TS val 122599140 ecr 0,nop,wscale 7], length 0
09:58:28.834026 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [S.], seq 4063583040, ack 1745665160, win 28960, options [mss 1460,sackOK,TS val 522775728 ecr 122599140,nop,wscale 9], length 0
09:58:28.834093 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 122599183 ecr 522775728], length 0
09:58:28.834588 IP 192.168.122.98.39330 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 122599184 ecr 522775728], length 112: HTTP: GET / HTTP/1.1
09:58:28.878445 IP 54.204.39.132.80 > 192.168.122.98.39330: Flags [.], ack 113, win 57, options [nop,nop,TS val 522775739 ecr 122599184], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

#### IP 地址/主机名

同样，你也可以根据源 IP 地址或者目的 IP 地址或者主机名来筛选数据包。例如抓取源 IP 地址为 `192.168.122.98` 的数据包：

```
$ sudo tcpdump -i any -c5 -nn src 192.168.122.98
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10:02:15.220824 IP 192.168.122.98.39436 > 192.168.122.1.53: 59332+ A? opensource.com. (32)
10:02:15.220862 IP 192.168.122.98.39436 > 192.168.122.1.53: 20749+ AAAA? opensource.com. (32)
10:02:15.364062 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [S], seq 1108640533, win 29200, options [mss 1460,sackOK,TS val 122825713 ecr 0,nop,wscale 7], length 0
10:02:15.409229 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [.], ack 669337581, win 229, options [nop,nop,TS val 122825758 ecr 522832372], length 0
10:02:15.409667 IP 192.168.122.98.39334 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 122825759 ecr 522832372], length 112: HTTP: GET / HTTP/1.1
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

注意此处示例中抓取了来自源 IP 地址 `192.168.122.98` 的 53 端口以及 80 端口的数据包，它们的应答包没有显示出来因为那些包的源 IP 地址已经变了。

相对的，使用 `dst` 就是按目的 IP/主机名来筛选数据包。

```
$ sudo tcpdump -i any -c5 -nn dst 192.168.122.98
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10:05:03.572931 IP 192.168.122.1.53 > 192.168.122.98.47049: 2248 1/0/0 A 54.204.39.132 (48)
10:05:03.572944 IP 192.168.122.1.53 > 192.168.122.98.47049: 33770 0/0/0 (32)
10:05:03.621833 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [S.], seq 3474204576, ack 3256851264, win 28960, options [mss 1460,sackOK,TS val 522874425 ecr 122993922,nop,wscale 9], length 0
10:05:03.667767 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [.], ack 113, win 57, options [nop,nop,TS val 522874436 ecr 122993972], length 0
10:05:03.672221 IP 54.204.39.132.80 > 192.168.122.98.39338: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 522874437 ecr 122993972], length 642: HTTP: HTTP/1.1 302 Found
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

#### 多条件筛选

当然，可以使用多条件组合来筛选数据包，使用 `and` 以及 `or` 逻辑操作符来创建过滤规则。例如，筛选来自源 IP 地址 `192.168.122.98` 的 HTTP 数据包：

```
$ sudo tcpdump -i any -c5 -nn src 192.168.122.98 and port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10:08:00.472696 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [S], seq 2712685325, win 29200, options [mss 1460,sackOK,TS val 123170822 ecr 0,nop,wscale 7], length 0
10:08:00.516118 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 268723504, win 229, options [nop,nop,TS val 123170865 ecr 522918648], length 0
10:08:00.516583 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [P.], seq 0:112, ack 1, win 229, options [nop,nop,TS val 123170866 ecr 522918648], length 112: HTTP: GET / HTTP/1.1
10:08:00.567044 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 123170916 ecr 522918661], length 0
10:08:00.788153 IP 192.168.122.98.39342 > 54.204.39.132.80: Flags [F.], seq 112, ack 643, win 239, options [nop,nop,TS val 123171137 ecr 522918661], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

你也可以使用括号来创建更为复杂的过滤规则，但在 shell 中请用引号包含你的过滤规则以防止被识别为 shell 表达式：

```
$ sudo tcpdump -i any -c5 -nn "port 80 and (src 192.168.122.98 or src 54.204.39.132)"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10:10:37.602214 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [S], seq 871108679, win 29200, options [mss 1460,sackOK,TS val 123327951 ecr 0,nop,wscale 7], length 0
10:10:37.650651 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [S.], seq 854753193, ack 871108680, win 28960, options [mss 1460,sackOK,TS val 522957932 ecr 123327951,nop,wscale 9], length 0
10:10:37.650708 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 0
10:10:37.651097 IP 192.168.122.98.39346 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 123328000 ecr 522957932], length 112: HTTP: GET / HTTP/1.1
10:10:37.692900 IP 54.204.39.132.80 > 192.168.122.98.39346: Flags [.], ack 113, win 57, options [nop,nop,TS val 522957942 ecr 123328000], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel
```

该例子中我们只抓取了来自源 IP 为 `192.168.122.98` 或者 `54.204.39.132` 的 HTTP （端口号80）的数据包。使用该方法就很容易抓取到数据流中交互双方的数据包了。

### 5、检查数据包内容

在以上的示例中，我们只按数据包头部的信息来建立规则筛选数据包，例如源地址、目的地址、端口号等等。有时我们需要分析网络连接问题，可能需要分析数据包中的内容来判断什么内容需要被发送、什么内容需要被接收等。`tcpdump` 提供了两个选项可以查看数据包内容，`-X` 以十六进制打印出数据报文内容，`-A` 打印数据报文的 ASCII 值。

例如，HTTP 请求报文内容如下：

```
$ sudo tcpdump -i any -c10 -nn -A port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
13:02:14.871803 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [S], seq 2546602048, win 29200, options [mss 1460,sackOK,TS val 133625221 ecr 0,nop,wscale 7], length 0
E..<..@.@.....zb6.'....P...@......r............
............................
13:02:14.910734 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [S.], seq 1877348646, ack 2546602049, win 28960, options [mss 1460,sackOK,TS val 525532247 ecr 133625221,nop,wscale 9], length 0
E..<..@./..a6.'...zb.P..o..&...A..q a..........
.R.W.......     ................
13:02:14.910832 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 133625260 ecr 525532247], length 0
E..4..@.@.....zb6.'....P...Ao..'...........
.....R.W................
13:02:14.911808 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 133625261 ecr 525532247], length 112: HTTP: GET / HTTP/1.1
E.....@.@..1..zb6.'....P...Ao..'...........
.....R.WGET / HTTP/1.1
User-Agent: Wget/1.14 (linux-gnu)
Accept: */*
Host: opensource.com
Connection: Keep-Alive

................
13:02:14.951199 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [.], ack 113, win 57, options [nop,nop,TS val 525532257 ecr 133625261], length 0
E..4.F@./.."6.'...zb.P..o..'.......9.2.....
.R.a....................
13:02:14.955030 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 525532258 ecr 133625261], length 642: HTTP: HTTP/1.1 302 Found
E....G@./...6.'...zb.P..o..'.......9.......
.R.b....HTTP/1.1 302 Found
Server: nginx
Date: Sun, 23 Sep 2018 17:02:14 GMT
Content-Type: text/html; charset=iso-8859-1
Content-Length: 207
X-Content-Type-Options: nosniff
Location: https://opensource.com/
Cache-Control: max-age=1209600
Expires: Sun, 07 Oct 2018 17:02:14 GMT
X-Request-ID: v-6baa3acc-bf52-11e8-9195-22000ab8cf2d
X-Varnish: 632951979
Age: 0
Via: 1.1 varnish (Varnish/5.2)
X-Cache: MISS
Connection: keep-alive

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://opensource.com/">here</a>.</p>
</body></html>
................
13:02:14.955083 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 133625304 ecr 525532258], length 0
E..4..@.@.....zb6.'....P....o..............
.....R.b................
13:02:15.195524 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 133625545 ecr 525532258], length 0
E..4..@.@.....zb6.'....P....o..............
.....R.b................
13:02:15.236592 IP 54.204.39.132.80 > 192.168.122.98.39366: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 525532329 ecr 133625545], length 0
E..4.H@./.. 6.'...zb.P..o..........9.I.....
.R......................
13:02:15.236656 IP 192.168.122.98.39366 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 133625586 ecr 525532329], length 0
E..4..@.@.....zb6.'....P....o..............
.....R..................
10 packets captured
10 packets received by filter
0 packets dropped by kernel
```

这对定位一些普通 HTTP 调用 API 接口的问题很有用。当然如果是加密报文，这个输出也就没多大用了。

### 6、保存抓包数据

`tcpdump` 提供了保存抓包数据的功能以便后续分析数据包。例如，你可以夜里让它在那里抓包，然后早上起来再去分析它。同样当有很多数据包时，显示过快也不利于分析，将数据包保存下来，更有利于分析问题。

使用 `-w` 选项来保存数据包而不是在屏幕上显示出抓取的数据包：

```
$ sudo tcpdump -i any -c10 -nn -w webserver.pcap port 80
[sudo] password for ricardo:
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
10 packets captured
10 packets received by filter
0 packets dropped by kernel
```

该命令将抓取的数据包保存到文件 `webserver.pcap`。后缀名 `pcap` 表示文件是抓取的数据包格式。

正如示例中所示，保存数据包到文件中时屏幕上就没有任何有关数据报文的输出，其中 `-c10` 表示抓取到 10 个数据包后就停止抓包。如果想有一些反馈来提示确实抓取到了数据包，可以使用 `-v` 选项。

`tcpdump` 将数据包保存在二进制文件中，所以不能简单的用文本编辑器去打开它。使用 `-r` 选项参数来阅读该文件中的报文内容：

```
$ tcpdump -nn -r webserver.pcap
reading from file webserver.pcap, link-type LINUX_SLL (Linux cooked)
13:36:57.679494 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [S], seq 3709732619, win 29200, options [mss 1460,sackOK,TS val 135708029 ecr 0,nop,wscale 7], length 0
13:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 0
13:36:57.719005 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 0
13:36:57.719186 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [P.], seq 1:113, ack 1, win 229, options [nop,nop,TS val 135708068 ecr 526052949], length 112: HTTP: GET / HTTP/1.1
13:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 0
13:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found
13:36:57.760182 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 643, win 239, options [nop,nop,TS val 135708109 ecr 526052959], length 0
13:36:57.977602 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [F.], seq 113, ack 643, win 239, options [nop,nop,TS val 135708327 ecr 526052959], length 0
13:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 0
13:36:58.022132 IP 192.168.122.98.39378 > 54.204.39.132.80: Flags [.], ack 644, win 239, options [nop,nop,TS val 135708371 ecr 526053025], length 0
$
```

这里不需要管理员权限 `sudo` 了，因为此刻并不是在网络接口处抓包。

你还可以使用我们讨论过的任何过滤规则来过滤文件中的内容，就像使用实时数据一样。 例如，通过执行以下命令从源 IP 地址 `54.204.39.132` 检查文件中的数据包：

```
$ tcpdump -nn -r webserver.pcap src 54.204.39.132
reading from file webserver.pcap, link-type LINUX_SLL (Linux cooked)
13:36:57.718932 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [S.], seq 1999298316, ack 3709732620, win 28960, options [mss 1460,sackOK,TS val 526052949 ecr 135708029,nop,wscale 9], length 0
13:36:57.756979 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [.], ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 0
13:36:57.760122 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [P.], seq 1:643, ack 113, win 57, options [nop,nop,TS val 526052959 ecr 135708068], length 642: HTTP: HTTP/1.1 302 Found
13:36:58.022089 IP 54.204.39.132.80 > 192.168.122.98.39378: Flags [F.], seq 643, ack 114, win 57, options [nop,nop,TS val 526053025 ecr 135708327], length 0
```

### 下一步做什么？

以上的基本功能已经可以帮助你使用强大的 `tcpdump` 抓包工具了。更多的内容请参考 [tcpdump 网站](http://www.tcpdump.org/#) 以及它的 [帮助文件](http://www.tcpdump.org/manpages/tcpdump.1.html)。

`tcpdump` 命令行工具为分析网络流量数据包提供了强大的灵活性。如果需要使用图形工具来抓包请参考 [Wireshark](https://www.wireshark.org/)。

Wireshark 还可以用来读取 `tcpdump` 保存的 pcap 文件。你可以使用 `tcpdump` 命令行在没有 GUI 界面的远程机器上抓包然后在 Wireshark 中分析数据包。

---

via: <https://opensource.com/article/18/10/introduction-tcpdump>

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

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


让决策更透明的三步

Summary: 当您使用这种决策技巧时，可以使你作为一个开源领导人做出决策时更透明。

当您使用这种决策技巧时，可以使你作为一个开源领导人做出决策时更透明。

>
> 当您使用这种决策技巧时，可以使你作为一个开源领导人做出决策时更透明。
>
>
>

![](/data/attachment/album/201811/04/222853v2ws0jcqzxyi0cy9.png)

要让你的领导工作更加透明，其中一个最有效的方法就是将一个现有的流程开放给你的团队进行反馈，然后根据反馈去改变流程。下面这些练习能让透明度更加切实，并且它有助于让你在持续评估并调整你的工作的透明度时形成“肌肉记忆”。

我想说，你可以通过任何流程来完成这项工作 —— 即使有些流程看起来像是“禁区”流程，比如晋升或者调薪。但是如果第一次它对于初步实践来说太大了，那么你可能需要从一个不那么敏感的流程开始，比如旅行批准流程或者为你的团队寻找空缺候选人的系统。（举个例子，我在我们的招聘和晋升流程中使用了这种方式）

开放流程并使其更加透明可以建立你的信誉并增强团队成员对你的信任。它会使你以一种可能超乎你设想和舒适程度的方式“走在透明的路上”。以这种方式工作确实会产生额外的工作，尤其是在过程的开始阶段 —— 但是，最终这种方法对于让管理者（比如我）对团队成员更具责任，而且它会更加相容。

### 阶段一：选择一个流程

**第一步** 想想你的团队使用的一个普通的或常规的流程，但是这个流程通常不需要仔细检查。下面有一些例子：

* 招聘：如何创建职位描述、如何挑选面试团队、如何筛选候选人以及如何做出最终的招聘决定。
* 规划：你的团队或组织如何确定年度或季度目标。
* 升职：你如何选择并考虑升职候选人，并决定谁升职。
* 经理绩效评估：谁有机会就经理绩效提供反馈，以及他们是如何反馈。
* 旅游：旅游预算如何分配，以及你如何决定是否批准旅行（或提名某人是否旅行）。

上面的某个例子可能会引起你的共鸣，或者你可能会发现一些你觉得更合适的流程。也许你已经收到了关于某个特定流程的问题，又或者你发现自己屡次解释某个特定决策的逻辑依据。选择一些你能够控制或影响的东西 —— 一些你认为你的成员所关心的东西。

**第二步** 现在回答以下关于这个流程的问题：

* 该流程目前是否记录在一个所有成员都知道并可以访问的地方？如果没有，现在就开始创建文档（不必太详细；只需要解释这个流程的不同步骤以及它是如何工作的）。你可能会发现这个过程不够清晰或一致，无法记录到文档。在这种情况下，用你*认为*理想情况下所应该的方式去记录它。
* 完成流程的文档是否说明了在不同的点上是如何做出决定？例如，在旅行批准流程中，它是否解释了如何批准或拒绝请求。
* 流程的*输入信息*是什么？例如，在确定部门年度目标时，哪些数据用于关键绩效指标，查找或者采纳谁的反馈，谁有机会审查或“签字”。
* 这个过程会做出什么*假设*？例如，在升职决策中，你是否认为所有的晋升候选人都会在适当的时间被他们的经理提出。
* 流程的*输出物*是什么？例如，在评估经理的绩效时，评估的结果是否会与经理共享，该审查报告的任何方面是否会与经理的直接报告更广泛地共享（例如，改进的领域)？

回答上述问题时，避免作出判断。如果这个流程不能清楚地解释一个决定是如何做出的，那也可以接受。这些问题只是评估现状的一个机会。

接下来，修改流程的文档，直到你对它充分说明了流程并预测潜在的问题感到满意。

### 阶段二：收集反馈

下一个阶段涉及到与你的成员分享这个流程并要求反馈。分享说起来容易做起来难。

**第一步** 鼓励人们提供反馈。考虑一下实现此目的的各种机制：

* 把这个流程公布在人们可以在内部找到的地方，并提示他们可以在哪里发表评论或提供反馈。谷歌文档可以很好地评论特定的文本或直接提议文本中的更改。
* 通过电子邮件分享过程文档，邀请反馈。
* 提及流程文档，在团队会议或一对一的谈话时要求反馈。
* 给人们一个他们可以提供反馈的时间窗口，并在此窗口内定期发送提醒。

如果你得不到太多的反馈，不要认为沉默就等于认可。你可以试着直接询问人们，他们为什么没有反馈。是因为他们太忙了吗？这个过程对他们来说不像你想的那么重要吗？你清楚地表达了你的要求吗？

**第二步** 迭代。当你获得关于流程的反馈时，鼓励团队对流程进行修改和迭代。加入改进的想法和建议，并要求确认预期的反馈已经被应用。如果你不同意某个建议，那就接受讨论，问问自己为什么不同意，以及一种方法和另一种方法的优点是什么。

设置一个收集反馈和迭代的时间窗口有助于向前推进。一旦收集和审查了反馈，你应当讨论和应用它，并且发布最终的流程供团队审查。

### 阶段三：实现

实现一个流程通常是计划中最困难的阶段。但如果你在修改过程中考虑了反馈意见，人们应该已经预料到了，并且可能会更支持你。从上面迭代过程中获得的文档是一个很好的工具，可以让你对实现负责。

**第一步** 审查实施需求。许多可以从提高透明度中获益的流程只需要做一点不同的事情，但是你确实需要检查你是否需要其他支持（例如工具）。

**第二步** 设置实现的时间表。与成员一起回顾时间表，这样他们就知道会发生什么。如果新流程需要对其他流程进行更改，请确保为人们提供足够的时间去适应新方式，并提供沟通和提醒。

**第三步** 跟进。在使用该流程 3-6 个月后，与你的成员联系，看看进展如何。新流程是否更加透明、更有效、更可预测？你有什么经验教训可以用来进一步改进这个流程吗？

### 关于作者

Sam Knuth —— 我有幸在 Red Hat 领导客户内容服务团队；我们生成提供给我们的客户的所有文档。我们的目标是为客户提供他们在企业中使用开源技术取得成功所需要的洞察力。在 Twitter 上与我 [@samfw](https://twitter.com/samfw) 联系。

---

via: <https://opensource.com/open-organization/17/9/exercise-in-transparent-decisions>

作者：[Sam Knuth](https://opensource.com/users/samfw) 译者：[MarineFish](https://github.com/MarineFish) 校对：[wxy](https://github.com/wxy)

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


如何在 Linux 中查看已挂载的文件系统类型

Summary: 本指南将解释如何在类 Unix 的操作系统中查看已挂载的文件系统类型。

本指南将解释如何在类 Unix 的操作系统中查看已挂载的文件系统类型。

![](/data/attachment/album/201811/04/230047r833us3bzm5o88ii.png)

如你所知，Linux 支持非常多的文件系统，例如 ext4、ext3、ext2、sysfs、securityfs、FAT16、FAT32、NTFS 等等，当前被使用最多的文件系统是 ext4。你曾经疑惑过你的 Linux 系统使用的是什么类型的文件系统吗？没有疑惑过？不用担心！我们将帮助你。本指南将解释如何在类 Unix 的操作系统中查看已挂载的文件系统类型。

### 在 Linux 中查看已挂载的文件系统类型

有很多种方法可以在 Linux 中查看已挂载的文件系统类型，下面我将给出 8 种不同的方法。那现在就让我们开始吧！

#### 方法 1 – 使用 findmnt 命令

这是查出文件系统类型最常使用的方法。`findmnt` 命令将列出所有已挂载的文件系统或者搜索出某个文件系统。`findmnt` 命令能够在 `/etc/fstab`、`/etc/mtab` 或 `/proc/self/mountinfo` 这几个文件中进行搜索。

`findmnt` 预装在大多数的 Linux 发行版中，因为它是 `util-linux` 包的一部分。如果 `findmnt` 命令不可用，你可以安装这个软件包。例如，你可以使用下面的命令在基于 Debian 的系统中安装 `util-linux` 包：

```
$ sudo apt install util-linux
```

下面让我们继续看看如何使用 `findmnt` 来找出已挂载的文件系统。

假如你只敲 `findmnt` 命令而不带任何的参数或选项，它将像下面展示的那样以树状图形式列举出所有已挂载的文件系统。

```
$ findmnt
```

示例输出：

![](/data/attachment/album/201811/04/230049spu33uuuq3jiw8zw.png)

正如你看到的那样，`findmnt` 展示出了目标挂载点（`TARGET`）、源设备（`SOURCE`）、文件系统类型（`FSTYPE`）以及相关的挂载选项（`OPTIONS`），例如文件系统是否是可读可写或者只读的。以我的系统为例，我的根（`/`）文件系统的类型是 EXT4 。

假如你不想以树状图的形式来展示输出，可以使用 `-l` 选项来以简单平凡的形式来展示输出：

```
$ findmnt -l
```

![](/data/attachment/album/201811/04/230050o85h1chczpl18hh6.png)

你还可以使用 `-t` 选项来列举出特定类型的文件系统，例如下面展示的 `ext4` 文件系统类型：

```
$ findmnt -t ext4
TARGET  SOURCE    FSTYPE OPTIONS
/       /dev/sda2 ext4   rw,relatime,commit=360
└─/boot /dev/sda1 ext4   rw,relatime,commit=360,data=ordered
```

`findmnt` 还可以生成 `df` 类型的输出，使用命令

```
$ findmnt --df
```

或

```
$ findmnt -D
```

示例输出：

```
SOURCE     FSTYPE            SIZE    USED   AVAIL   USE% TARGET
dev        devtmpfs          3.9G       0    3.9G     0% /dev
run        tmpfs             3.9G    1.1M    3.9G     0% /run
/dev/sda2  ext4            456.3G  342.5G   90.6G    75% /
tmpfs      tmpfs             3.9G   32.2M    3.8G     1% /dev/shm
tmpfs      tmpfs             3.9G       0    3.9G     0% /sys/fs/cgroup
bpf        bpf                  0       0       0      - /sys/fs/bpf
tmpfs      tmpfs             3.9G    8.4M    3.9G     0% /tmp
/dev/loop0 squashfs         82.1M   82.1M       0   100% /var/lib/snapd/snap/core/4327
/dev/sda1  ext4             92.8M   55.7M   30.1M    60% /boot
tmpfs      tmpfs           788.8M     32K  788.8M     0% /run/user/1000
gvfsd-fuse fuse.gvfsd-fuse      0       0       0      - /run/user/1000/gvfs
```

你还可以展示某个特定设备或者挂载点的文件系统类型。

查看某个特定的设备：

```
$ findmnt /dev/sda1
TARGET SOURCE    FSTYPE OPTIONS
/boot  /dev/sda1 ext4   rw,relatime,commit=360,data=ordered
```

查看某个特定的挂载点：

```
$ findmnt /
TARGET SOURCE    FSTYPE OPTIONS
/      /dev/sda2 ext4   rw,relatime,commit=360
```

你甚至还可以查看某个特定标签的文件系统的类型：

```
$ findmnt LABEL=Storage
```

更多详情，请参考其 man 手册。

```
$ man findmnt
```

`findmnt` 命令已足够完成在 Linux 中查看已挂载文件系统类型的任务，这个命令就是为了这个特定任务而生的。然而，还存在其他方法来查看文件系统的类型，假如你感兴趣的话，请接着往下看。

#### 方法 2 – 使用 blkid 命令

`blkid` 命令被用来查找和打印块设备的属性。它也是 `util-linux` 包的一部分，所以你不必再安装它。

为了使用 `blkid` 命令来查看某个文件系统的类型，可以运行：

```
$ blkid /dev/sda1
```

#### 方法 3 – 使用 df 命令

在类 Unix 的操作系统中，`df` 命令被用来报告文件系统的磁盘空间使用情况。为了查看所有已挂载文件系统的类型，只需要运行：

```
$ df -T
```

示例输出：

![](/data/attachment/album/201811/04/230052o9saxi6mzhbhfbfm.png)

关于 `df` 命令的更多细节，可以参考下面的指南。

* [针对新手的 df 命令教程](https://www.ostechnix.com/the-df-command-tutorial-with-examples-for-beginners/)

同样也可以参考其 man 手册：

```
$ man df
```

#### 方法 4 – 使用 file 命令

`file` 命令可以判读出某个特定文件的类型，即便该文件没有文件后缀名也同样适用。

运行下面的命令来找出某个特定分区的文件系统类型：

```
$ sudo file -sL /dev/sda1
[sudo] password for sk:
/dev/sda1: Linux rev 1.0 ext4 filesystem data, UUID=83a1dbbf-1e15-4b45-94fe-134d3872af96 (needs journal recovery) (extents) (large files) (huge files)
```

查看其 man 手册可以知晓更多细节：

```
$ man file
```

#### 方法 5 – 使用 fsck 命令

`fsck` 命令被用来检查某个文件系统是否健全或者修复它。你可以像下面那样通过将分区名字作为 `fsck` 的参数来查看该分区的文件系统类型：

```
$ fsck -N /dev/sda1
fsck from util-linux 2.32
[/usr/bin/fsck.ext4 (1) -- /boot] fsck.ext4 /dev/sda1
```

如果想知道更多的内容，请查看其 man 手册：

```
$ man fsck
```

#### 方法 6 – 使用 fstab 命令

`fstab` 是一个包含文件系统静态信息的文件。这个文件通常包含了挂载点、文件系统类型和挂载选项等信息。

要查看某个文件系统的类型，只需要运行：

```
$ cat /etc/fstab
```

![](/data/attachment/album/201811/04/230053j9uccofxhdireod6.png)

更多详情，请查看其 man 手册：

```
$ man fstab
```

#### 方法 7 – 使用 lsblk 命令

`lsblk` 命令可以展示设备的信息。

要展示已挂载文件系统的信息，只需运行：

```
$ lsblk -f
NAME   FSTYPE   LABEL  UUID                                 MOUNTPOINT
loop0  squashfs                                             /var/lib/snapd/snap/core/4327
sda
├─sda1 ext4            83a1dbbf-1e15-4b45-94fe-134d3872af96 /boot
├─sda2 ext4            4d25ddb0-5b20-40b4-ae35-ef96376d6594 /
└─sda3 swap            1f8f5e2e-7c17-4f35-97e6-8bce7a4849cb [SWAP]
sr0
```

更多细节，可以参考它的 man 手册：

```
$ man lsblk
```

#### 方法 8 – 使用 mount 命令

`mount` 被用来在类 Unix 系统中挂载本地或远程的文件系统。

要使用 `mount` 命令查看文件系统的类型，可以像下面这样做：

```
$ mount | grep "^/dev"
/dev/sda2 on / type ext4 (rw,relatime,commit=360)
/dev/sda1 on /boot type ext4 (rw,relatime,commit=360,data=ordered)
```

更多详情，请参考其 man 手册的内容：

```
$ man mount
```

好了，上面便是今天的全部内容了。现在你知道了 8 种不同的 Linux 命令来查看已挂载的 Linux 文件系统的类型。假如你知道其他的命令来完成同样的任务，请在下面的评论部分让我们知晓，我将确认并相应地升级本教程。

更过精彩内容即将呈现，请保持关注！

---

via: <https://www.ostechnix.com/how-to-find-the-mounted-filesystem-type-in-linux/>

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

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


使用极简浏览器 Min 浏览网页

>
> 并非所有 web 浏览器都要做到无所不能，Min 就是一个极简主义风格的浏览器。
>
>
>

![](/data/attachment/album/201811/04/233116fjhpjllxlh7phje1.png)

现在还有开发新的 Web 浏览器的需要吗？即使现在浏览器领域已经成为了寡头市场，但仍然不断涌现出各种前所未有的浏览器产品。

[Min](https://minbrowser.github.io/min/) 就是其中一个。顾名思义，Min 是一个小的浏览器，也是一个极简主义的浏览器。但它麻雀虽小五脏俱全，而且还是一个开源的浏览器，它的 Apache 2.0 许可证引起了我的注意。

让我们来看看 Min 有什么值得关注的方面。

### 开始

Min 基于 [Electron](http://electron.atom.io/apps/) 框架开发，值得一提的是，[Atom 文本编辑器](https://opensource.com/article/17/5/atom-text-editor-packages-writers)也是基于这个框架开发的。它提供 Linux、MacOS 和 Windows 的[安装程序](https://github.com/minbrowser/min/releases/)，当然也可以[从 GitHub 获取它的源代码](https://github.com/minbrowser/min)自行编译安装。

我使用的 Linux 发行版是 Manjaro，但没有完全匹配这个发行版的安装程序。还好，我通过 Manjaro 的包管理器也能安装 Min。

安装完成后，在终端就可以直接启动 Min。

![](/data/attachment/album/201811/04/233120n3291rh9t21r1jh2.png)

Min 号称是更智能、更快速的浏览器。经过尝试以后，我觉得它比我在其它电脑上使用过的 Firefox 和 Chrome 浏览器启动得更快。

而使用 Min 浏览网页的过程则和 Firefox 或 Chrome 一样，只要再地址栏输入 URL，回车，就好了。

### Min 的功能

尽管 Min 不可能带有 Firefox 或 Chrome 等浏览器得所有功能，但它也有可取之处。

Min 和其它浏览器一样，支持页面选项卡。它还有一个称为 Tasks 的功能，可以对打开的选项卡进行分组。

[DuckDuckGo](http://duckduckgo.com) 是我最喜欢的搜索引擎，而 Min 的默认搜索引擎恰好就是它，这正合我意。当然，如果你喜欢另一个搜索引擎，也可以在 Min 的偏好设置中配置你喜欢的搜索引擎作为默认搜索引擎。

Min 没有使用类似 AdBlock 这样的插件来过滤你不想看到的内容，而是使用了一个名为 [EasyList](https://easylist.to/) 的内置的广告拦截器，你可以使用它来屏蔽脚本和图片。另外 Min 还带有一个内置的防跟踪软件。

类似 Firefox，Min 有一个名为叫做 Reading List 的阅读模式。只需点击地址栏中的对应图标，就可以去除页面中的大部分无关内容，让你专注于正在阅读的内容。网页在阅读列表中可以保留 30 天。

![](/data/attachment/album/201811/04/233128vn1n1v88tt4abt8k.png)

Min 还有一个专注模式，可以隐藏其它选项卡并阻止你打开新的选项卡。在专注模式下，如果一个 web 页面中进行工作，需要多点击好几次才能打开一个新页面。

Min 也有很多快捷键让你快速使用某个功能。你可以[在 GitHub 上](https://github.com/minbrowser/min/wiki)找到这些这些快捷键的参考文档，也可以在 Min 的偏好设置中进行更改。

我发现 Min 可以在 YouTube、Vimeo、Dailymotion 等视频网站上播放视频，还可以在音乐网站 7Digital 上播放音乐。但由于我没有账号，所以没法测试是否能在 Spotify 或 Last.fm 等这些网站上播放音乐。

![](/data/attachment/album/201811/04/233144sayymt7tbujt4tgo.png)

### Min 的弱点

Min 确实也有自己的缺点，例如它无法将网站添加为书签。替代方案要么是查看 Min 的搜索历史来找回你需要的链接，要么是使用一个第三方的书签服务。

最大的缺点是 Min 不支持插件。这对我来说不是一件坏事，因为浏览器启动速度和运行速度快的主要原因就在于此。当然也有一些人非常喜欢使用浏览器插件，Min 就不是他们的选择。

### 总结

Min 算是一个中规中矩的浏览器，它可以凭借轻量、快速的优点吸引很多极简主义的用户。但是对于追求多功能的用户来说，Min 就显得相当捉襟见肘了。

所以，如果你想摆脱当今多功能浏览器的束缚，我觉得可以试用一下 Min。

---

via: <https://opensource.com/article/18/10/min-web-browser>

作者：[Scott Nesbitt](https://opensource.com/users/scottnesbitt) 选题：[lujun9972](https://github.com/lujun9972) 译者：[HankChow](https://github.com/HankChow) 校对：[wxy](https://github.com/wxy)

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


推动 DevOps 变革的三个方面

>
> 推动大规模的组织变革是一个痛苦的过程。对于 DevOps 来说，尽管也有阵痛，但变革带来的价值则相当可观。
>
>
>

![](/data/attachment/album/201811/05/102242f22hd19lq6d93d06.png)

避免痛苦是一种强大的动力。一些研究表明，[植物也会通过遭受疼痛的过程](https://link.springer.com/article/10.1007%2Fs00442-014-2995-6)以采取措施来保护自己。我们人类有时也会刻意让自己受苦——在剧烈运动之后，身体可能会发生酸痛，但我们仍然坚持运动。那是因为当人认为整个过程利大于弊时，几乎可以忍受任何事情。

推动大规模的组织变革的过程确实是痛苦的。有人可能会因难以改变价值观和行为而感到痛苦，有人可能会因难以带领团队而感到痛苦，也有人可能会因难以开展工作而感到痛苦。但就 DevOps 而言，我可以说这些痛苦都是值得的。

我也曾经关注过一个团队耗费大量时间优化技术流程的过程，在这个过程中，团队逐渐将流程进行自动化改造，并最终获得了成功。

![Improvements after DevOps transformation](/data/attachment/album/201811/05/102242qcz2mgyy2hgzobsr.png "Improvements after DevOps transformation")

图片来源：Lee Eason. CC BY-SA 4.0

这张图表充分表明了变革的价值。一家公司在我主导实行了 DevOps 转型之后，60 多个团队每月提交了超过 900 个发布请求。这些工作量的原耗时高达每个月 350 人/天，而这么多的工作量对于任何公司来说都是不可忽视的。除此以外，他们每月的部署次数从 100 次增加到了 9000 次，高危 bug 减少了 24%，工程师们更轻松了，<ruby> 净推荐值 <rt>  Net Promoter Score </rt></ruby>（NPS）也提高了，而 NPS 提高反过来也让团队的 DevOps 转型更加顺利。正如 [Puppet 发布的 DevOps 报告](https://puppet.com/resources/whitepaper/state-of-devops-report)所预测的，用在技术流程改进上的投入可以在业务成果上明显地体现出来。

而 DevOps 主导者在推动变革时必须关注这三个方面：团队管理，团队文化和团队活力。

### 团队管理

最重要的是，改进对技术流程的投入可以转化为更好的业务成果。

组织架构越大，业务领导与一线员工之间的距离就会越大，当然发生误解的可能性也会越大。而且各种技术工具和实际应用都在以日新月异的速度变化，这就导致业务领导几乎不可能对 DevOps 或敏捷开发的转型方向有一个亲身的了解。

DevOps 主导者必须和管理层密切合作，在进行决策的时候给出相关的意见，以帮助他们做出正确的决策。

公司的管理层只是知道 DevOps 会对产品部署的方式进行改进，而并不了解其中的具体过程。假设你正在帮助一个软件开发团队实现自动化部署，当管理层得知某次部署失败时（这种情况是有的），就会想要了解这件事情的细节。如果管理层了解到进行部署的是软件团队而不是专门的发布管理团队，就可能会坚持使用传统的变更流程来保证业务的正常运作。你可能会失去团队的信任，团队也可能不愿意做出进一步的改变。

如果没有和管理层做好心理上的预期，一旦发生意外的生产事件，重建管理层的信任并得到他们的支持比事先对他们进行教育需要更长的时间。所以，最好事先和管理层在各方面协调好，这会让你在后续的工作中避免很多麻烦。

对于和管理层之间的协调，这里有两条建议：

* 一是**重视所有规章制度**。如果管理层对合同、安全等各方面有任何疑问，你都可以向法务或安全负责人咨询，这样做可以避免犯下后果严重的错误。
* 二是**将管理层重点关注的方面输出为量化指标**。举个例子，如果公司的目标是减少客户流失，而你调查得出计划外的服务宕机是造成客户流失的主要原因，那么就可以让团队对故障的<ruby> 平均排查时间 <rt>  Mean Time To Detection </rt></ruby>（MTTD）和<ruby> 平均解决时间 <rt>  Mean Time To Resolution </rt></ruby>（MTTR）实行重点优化。你可以使用这些关键指标来量化团队的工作成果，而管理层对此也可以有一个直观的了解。

### 团队文化

DevOps 是一种专注于持续改进代码、构建、部署和操作流程的文化，而团队文化代表了团队的价值观和行为。从本质上说，团队文化是要塑造团队成员的行为方式，而这并不是一件容易的事。

我推荐一本叫做《[披着狼皮的 CIO](https://www.gartner.com/en/publications/wolf-cio)》的书。另外，研究心理学、阅读《[Drive](https://en.wikipedia.org/wiki/Drive:_The_Surprising_Truth_About_What_Motivates_Us)》、观看 Daniel Pink 的 [TED 演讲](https://www.ted.com/talks/dan_pink_on_motivation?language=en#t-2094)、阅读《[千面英雄](https://www.ted.com/talks/dan_pink_on_motivation?language=en#t-2094)》、了解每个人的心路历程，以上这些都是你推动公司技术变革所应该尝试去做的事情。如果这些你都没兴趣，说明你不是那个推动公司变革的人。如果你想成为那个人，那就开始学习吧！

从本质上说，改变一个人真不是件容易的事。

理性的人大多都按照自己的价值观工作，然而团队通常没有让每个人都能达成共识的明确价值观。因此，你需要明确团队目前的价值观，包括价值观的形成过程和价值观的目标导向。但不能将这些价值观强加到团队成员身上，只需要让团队成员在现有条件下力所能及地做到最好就可以了。

同时需要向团队成员阐明，公司正在发生组织和团队目标的变化，团队的价值观也随之改变，最好也厘清整个过程中将会作出什么变化。例如，公司以往或许是由于资金有限，一直将节约成本的原则放在首位，在研发新产品的时候，基础架构团队不得不共享数据库集群或服务器，从而导致了服务之间的紧密耦合。然而随着时间的推移，这种做法会产生难以维护的混乱，即使是一个小小的变化也可能造成无法预料的后果。这就导致交付团队难以执行变更控制流程，进而令变更停滞不前。

如果这种状况持续几年，最终的结果将会是毫无创新、技术老旧、问题繁多以及产品品质低下，公司的发展到达了瓶颈，原本的价值观已经不再适用。所以，工作效率的优先级必须高于节约成本。如果一个选择能让团队运作更好，另一个选择只是短期来看成本便宜，那你应该选择前者。

你必须反复强调团队的价值观。每当团队取得了一定的工作进展（即使探索创新时出现一些小的失误），都应该对团队作出激励。在团队部署出现失败时，鼓励他们承担风险、吸取教训，同时指导团队如何改进他们的工作并表示支持。长此下来，团队成员就会对你产生信任，不再顾虑为切合团队的价值观而做出改变。

### 团队活力

你有没有在会议上听过类似这样的话？“在张三度假回来之前，我们无法对这件事情做出评估。他是唯一一个了解代码的人”，或者是“我们完成不了这项任务，它在网络上需要跨团队合作，而防火墙管理员刚好请病假了”，又或者是“张三最清楚这个系统，他说是怎么样，通常就是怎么样”。那么如果团队在处理工作时，谁才是主力？就是张三。而且也一直会是他。

我们一直都认为这就是软件开发的自带属性。但是如果我们不作出改变，这种循环就会一直持续下去。

熵的存在会让团队自发地变得混乱和缺乏活力，团队的成员和主导者的都有责任控制这个熵并保持团队的活力。DevOps、敏捷开发、上云、代码重构这些行为都会令熵加速增长，这是因为转型让团队需要学习更多新技能和专业知识以开展新工作。

我们来看一个产品团队重构历史代码的例子。像往常一样，他们在 AWS 上构建新的服务。而传统的系统则在数据中心部署，并由 IT 部门进行监控和备份。IT 部门会确保在基础架构的层面上满足应用的安全需求、进行灾难恢复测试、系统补丁、安装配置了入侵检测和防病毒代理，而且 IT 部门还保留了年度审计流程所需的变更控制记录。

产品团队经常会犯一个致命的错误，就是认为 IT 是消耗资源的部门，是需要突破的瓶颈。他们希望脱离已有的 IT 部门并使用公有云，但实际上是他们忽视了 IT 部门提供的关键服务。迁移到云上只是以不同的方式实现这些关键服务，因为 AWS 也是一个数据中心，团队即使使用 AWS 也需要完成 IT 运维任务。

实际上，产品团队在向云迁移的时候也必须学习如何使用这些 IT 服务。因此，当产品团队开始重构历史代码并部署到云上时，也需要学习大量的技能才能正常运作。这些技能不会无师自通，必须自行学习或者聘用相关的人员，团队的主导者也必须积极进行管理。

在带领团队时，我找不到任何适合我的工具，因此我建立了 [Tekita.io](https://tekata.io/) 这个项目。Tekata 免费而且容易使用。但相比起来，把注意力集中在人员和流程上更为重要，你需要不断学习，持续关注团队的短板，因为它们会影响团队的交付能力，而弥补这些短板往往需要学习大量的新知识，这就需要团队成员之间有一个很好的协作。因此 76％ 的年轻人都认为个人发展机会是公司文化[最重要的的一环](https://www.execu-search.com/%7E/media/Resources/pdf/2017_Hiring_Outlook_eBook)。

### 效果就是最好的证明

DevOps 转型会改变团队的工作方式和文化，这需要得到管理层的支持和理解。同时，工作方式的改变意味着新技术的引入，所以在管理上也必须谨慎。但转型的最终结果是团队变得更高效、成员变得更积极、产品变得更优质，客户也变得更满意。

免责声明：本文中的内容仅为 Lee Eason 的个人立场，不代表 Ipreo 或 IHS Markit。

---

via: <https://opensource.com/article/18/10/tales-devops-transformation>

作者：[Lee Eason](https://opensource.com/users/leeeason) 选题：[lujun9972](https://github.com/lujun9972) 译者：[HankChow](https://github.com/HankChow) 校对：[pityonline](https://github.com/pityonline)

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


在你开始使用 Kali Linux 之前必须知道的事情

无意中看到这篇文章，刚刚接触渗透，有一些东西想请教作者

无意中看到这篇文章，刚刚接触渗透，有一些东西想请教作者

无意中看到这篇文章，刚刚接触渗透，有一些东西想请教作者

无意中看到这篇文章，刚刚接触渗透，有一些东西想请教作者

虚拟机中学习可以吗，只是为了学习

虚拟机中学习可以吗，只是为了学习

虚拟机中学习可以吗，只是为了学习

虚拟机中学习可以吗，只是为了学习

可以使用docker 跑kali的i

废话

废话

废话

好话。

来自117.157.169.122的 QQ Browser 10.5|Windows 7 用户

好怕怕，吓死个人了......

hhh

kail 用的好，监狱进的早

你这不废话吗

kail用的好监狱少不了

我觉得kali不用这么神化吧，想用就用呗

不要过度神话，功过七三开

巧了

我就是想要用kali的渗透工具破解楼上的WiFi密码才安装的 live USB kali

这篇文章整的我不敢玩kali了

kali玩的好，牢饭吃到老

我的就是把kali装成了主操作系统

我赶紧关机了

我只是单纯的想弄来玩玩，学习一下网络破解

kali用得妙，狱警一直笑

已经吓得半死了。我只是想看看

来自山东济南的 Chrome Mobile 83.0|Android 10 用户

休想劝退我

我就装在虚拟机里玩玩

win11 来啦！

win11 来啦！

win11 来啦！

win11 来啦！

无所谓，我不做太出格的事情<br />
即使你捕捉到我到又怎么样，我只是个穷学生而已

<script>alert()</script>

<script> type="text/java script">console.log(Hi); </script>

<script>alert(“看看有漏洞没？")</script>

<script>alert(“看看有漏洞没？")</script>

<script>alert(“看看有漏洞没？")</script>

ok，我会出手

win 11

<script>alert(“看看有漏洞没？")</script>

![](/data/attachment/album/201811/05/143507x6i0sbd02ok0gteo.png)

Kali Linux 在渗透测试和白帽子方面是业界领先的 Linux 发行版。默认情况下，该发行版附带了大量入侵和渗透的工具和软件，并且在全世界都得到了广泛认可。即使在那些甚至可能不知道 Linux 是什么的 Windows 用户中也是如此。

由于后者的原因（LCTT 译注：Windows 用户），许多人都试图单独使用 Kali Linux，尽管他们甚至不了解 Linux 系统的基础知识。原因可能各不相同，有的为了玩乐，有的是为了取悦女友而伪装成黑客，有的仅仅是试图破解邻居的 WiFi 网络以免费上网。如果你打算使用 Kali Linux，记住，所有的这些都是不好的事情。

在计划使用 Kali Linux 之前，你应该了解一些提示。

### Kali Linux 不适合初学者

![](/data/attachment/album/201811/05/143454zhurywzc6vkclrh4.png)

*Kali Linux 默认 GNOME 桌面*

如果你是几个月前刚开始使用 Linux 的人，或者你认为自己的知识水平低于平均水平，那么 Kali Linux 就不适合你。如果你打算问“如何在 Kali 上安装 Steam？如何让我的打印机在 Kali 上工作？如何解决 Kali 上的 APT 源错误？”这些东西，那么 Kali Linux 并不适合你。

Kali Linux 主要面向想要运行渗透测试套件的专家或想要学习成为白帽子和数字取证的人。但即使你属于后者，普通的 Kali Linux 用户在日常使用时也会遇到很多麻烦。他还被要求以非常谨慎的方式使用工具和软件，而不仅仅是“让我们安装并运行一切”。每一个工具必须小心使用，你安装的每一个软件都必须仔细检查。

**建议阅读：** [Linux 系统的组件有什么?](https://fosspost.org/articles/what-are-the-components-of-a-linux-distribution)

普通 Linux 用户都无法自如地使用它。一个更好的方法是花几周时间学习 Linux 及其守护进程、服务、软件、发行版及其工作方式，然后观看几十个关于白帽子攻击的视频和课程，然后再尝试使用 Kali 来应用你学习到的东西。

### 它会让你被黑客攻击

![](/data/attachment/album/201811/05/143522d6kn8jik7o6bba6k.png)

*Kali Linux 入侵和测试工具*

在普通的 Linux 系统中，普通用户有一个账户，而 root 用户也有一个单独的账号。但在 Kali Linux 中并非如此。Kali Linux 默认使用 root 账户，不提供普通用户账户。这是因为 Kali 中几乎所有可用的安全工具都需要 root 权限，并且为了避免每分钟要求你输入 root 密码，所以这样设计。

当然，你可以简单地创建一个普通用户账户并开始使用它。但是，这种方式仍然不推荐，因为这不是 Kali Linux 系统设计的工作方式。使用普通用户在使用程序，打开端口，调试软件时，你会遇到很多问题，你会发现为什么这个东西不起作用，最终却发现它是一个奇怪的权限错误。另外每次在系统上做任何事情时，你会被每次运行工具都要求输入密码而烦恼。

现在，由于你被迫以 root 用户身份使用它，因此你在系统上运行的所有软件也将以 root 权限运行。如果你不知道自己在做什么，那么这很糟糕，因为如果 Firefox 中存在漏洞，并且你访问了一个受感染的网站，那么黑客能够在你的 PC 上获得全部 root 权限并入侵你。如果你使用的是普通用户账户，则会受到限制。此外，你安装和使用的某些工具可能会在你不知情的情况下打开端口并泄露信息，因此如果你不是非常小心，人们可能会以你尝试入侵他们的方式入侵你。

如果你曾经访问过与 Kali Linux 相关的 Facebook 群组，你会发现这些群组中几乎有四分之一的帖子是人们在寻求帮助，因为有人入侵了他们。

### 它可以让你入狱

Kali Linux 只是提供了软件。那么，如何使用它们完全是你自己的责任。

在世界上大多数发达国家，使用针对公共 WiFi 网络或其他设备的渗透测试工具很容易让你入狱。现在不要以为你使用了 Kali 就无法被跟踪，许多系统都配置了复杂的日志记录设备来简单地跟踪试图监听或入侵其网络的人，你可能无意间成为其中的一个，那么它会毁掉你的生活。

永远不要对不属于你的设备或网络使用 Kali Linux 系统，也不要明确允许对它们进行入侵。如果你说你不知道你在做什么，在法庭上它不会被当作借口来接受。

### 修改了的内核和软件

Kali [基于](https://www.kali.org/news/kali-linux-rolling-edition-2016-1/) Debian（“测试”分支，这意味着 Kali Linux 使用滚动发布模型），因此它使用了 Debian 的大部分软件体系结构，你会发现 Kali Linux 中的大部分软件跟 Debian 中的没什么区别。

但是，Kali 修改了一些包来加强安全性并修复了一些可能的漏洞。例如，Kali 使用的 Linux 内核被打了补丁，允许在各种设备上进行无线注入。这些补丁通常在普通内核中不可用。此外，Kali Linux 不依赖于 Debian 服务器和镜像，而是通过自己的服务器构建软件包。以下是最新版本中的默认软件源：

```
deb http://http.kali.org/kali kali-rolling main contrib non-free
deb-src http://http.kali.org/kali kali-rolling main contrib non-free
```

这就是为什么，对于某些特定的软件，当你在 Kali Linux 和 Fedora 中使用相同的程序时，你会发现不同的行为。你可以从 [git.kali.org](http://git.kali.org) 中查看 Kali Linux 软件的完整列表。你还可以在 Kali Linux（GNOME）上找到我们[自己生成的已安装包列表](https://paste.ubuntu.com/p/bctSVWwpVw/)。

更重要的是，Kali Linux 官方文档极力建议不要添加任何其他第三方软件仓库，因为 Kali Linux 是一个滚动发行版，并且依赖于 Debian 测试分支，由于依赖关系冲突和包钩子，所以你很可能只是添加一个新的仓库源就会破坏系统。

### 不要安装 Kali Linux

![](/data/attachment/album/201811/05/143536z7eq1q72k1t99b31.png)

*使用 Kali Linux 在 fosspost.org 上运行 wpscan*

我在极少数情况下使用 Kali Linux 来测试我部署的软件和服务器。但是，我永远不敢安装它并将其用作主系统。

如果你要将其用作主系统，那么你必须保留自己的个人文件、密码、数据以及系统上的所有内容。你还需要安装大量日常使用的软件，以解放你的生活。但正如我们上面提到的，使用 Kali Linux 是非常危险的，应该非常小心地进行，如果你被入侵了，你将丢失所有数据，并且可能会暴露给更多的人。如果你在做一些不合法的事情，你的个人信息也可用于跟踪你。如果你不小心使用这些工具，那么你甚至可能会毁掉自己的数据。

即使是专业的白帽子也不建议将其作为主系统安装，而是通过 USB 使用它来进行渗透测试工作，然后再回到普通的 Linux 发行版。

### 底线

正如你现在所看到的，使用 Kali 并不是一个轻松的决定。如果你打算成为一个白帽子，你需要使用 Kali 来学习，那么在学习了基础知识并花了几个月的时间使用普通 Linux 系统之后再来学习 Kali。但是小心你正在做的事情，以避免遇到麻烦。

如果你打算使用 Kali，或者你需要任何帮助，我很乐意在评论中听到你的想法。

---

via: <https://fosspost.org/articles/must-know-before-using-kali-linux>

作者：[M.Hanny Sabbagh](https://fosspost.org/author/mhsabbagh) 选题：[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/) 荣誉推出


如何禁用 Ubuntu 服务器中终端欢迎消息中的广告

哈哈, 今天登录了 确实有

如果你正在使用最新的 Ubuntu 服务器版本，你可能已经注意到欢迎消息中有一些与 Ubuntu 服务器平台无关的促销链接。你可能已经知道 **MOTD**，即 **M**essage **O**f **T**he **D**ay 的开头首字母，在 Linux 系统每次登录时都会显示欢迎信息。通常，欢迎消息包含操作系统版本，基本系统信息，官方文档链接以及有关最新安全更新等的链接。这些是我们每次通过 SSH 或本地登录时通常会看到的内容。但是，最近在终端欢迎消息中出现了一些其他链接。我已经几次注意到这些链接，但我并在意，也从未点击过。题图是我的 Ubuntu 18.04 LTS 服务器上显示的终端欢迎消息。

![](/data/attachment/album/201811/05/215049ct0ncp60oxnvtpo0.png)

正如你在上面截图中所看到的，欢迎消息中有一个 bit.ly 链接和 Ubuntu wiki 链接。有些人可能会惊讶并想知道这是什么。其实欢迎信息中的链接无需担心。它可能看起来像广告，但并不是商业广告。链接实际上指向到了 [Ubuntu 官方博客](https://blog.ubuntu.com/) 和 [Ubuntu wiki](https://wiki.ubuntu.com/)。正如我之前所说，其中的一个链接是不相关的，没有任何与 Ubuntu 服务器相关的细节，这就是为什么我开头称它们为广告。

虽然我们大多数人都不会访问 bit.ly 链接，但是有些人可能出于好奇去访问这些链接，结果失望地发现它只是指向一个外部链接。你可以使用任何 URL 去短网址服务，例如 unshorten.it，在访问真正链接之前，查看它会指向哪里。或者，你只需在 bit.ly 链接的末尾输入加号（`+`）即可查看它们的实际位置以及有关链接的一些统计信息。

![](/data/attachment/album/201811/05/215050l2p24gd4bqg6qd91.png)

### 什么是 MOTD 以及它是如何工作的？

2009 年，来自 Canonical 的 Dustin Kirkland 在 Ubuntu 中引入了 MOTD 的概念。它是一个灵活的框架，使管理员或发行包能够在 `/etc/update-motd.d/` 位置添加可执行脚本，目的是生成在登录时显示有益的、有趣的消息。它最初是为 Landscape（Canonical 的商业服务）实现的，但是其它发行版维护者发现它很有用，并且在他们自己的发行版中也采用了这个特性。

如果你在 Ubuntu 系统中查看 `/etc/update-motd.d/`，你会看到一组脚本。一个是打印通用的 “欢迎” 横幅。下一个打印 3 个链接，显示在哪里可以找到操作系统的帮助。另一个计算并显示本地系统包可以更新的数量。另一个脚本告诉你是否需要重新启动等等。

从 Ubuntu 17.04 起，开发人员添加了 `/etc/update-motd.d/50-motd-news`，这是一个脚本用来在欢迎消息中包含一些附加信息。这些附加信息是：

1. 重要的关键信息，例如 ShellShock、Heartbleed 等
2. 生命周期（EOL）消息，新功能可用性等
3. 在 Ubuntu 官方博客和其他有关 Ubuntu 的新闻中发布的一些有趣且有益的帖子

另一个特点是异步，启动后约 60 秒，systemd 计时器运行 `/etc/update-motd.d/50-motd-news –force` 脚本。它提供了 `/etc/default/motd-news` 脚本中定义的 3 个配置变量。默认值为：`ENABLED=1, URLS="https://motd.ubuntu.com", WAIT="5"`。

以下是 `/etc/default/motd-news` 文件的内容：

```
$ cat /etc/default/motd-news
# Enable/disable the dynamic MOTD news service
# This is a useful way to provide dynamic, informative
# information pertinent to the users and administrators
# of the local system
ENABLED=1

# Configure the source of dynamic MOTD news
# White space separated list of 0 to many news services
# For security reasons, these must be https
# and have a valid certificate
# Canonical runs a service at motd.ubuntu.com, and you
# can easily run one too
URLS="https://motd.ubuntu.com"

# Specify the time in seconds, you're willing to wait for
# dynamic MOTD news
# Note that news messages are fetched in the background by
# a systemd timer, so this should never block boot or login
WAIT=5
```

好事情是 MOTD 是完全可定制的，所以你可以彻底禁用它（`ENABLED=0`）、根据你的意愿更改或添加脚本、以秒为单位更改等待时间等等。

如果启用了 MOTD，那么 systemd 计时器作业将循环遍历每个 URL，将它们的内容缩减到每行 80 个字符、最多 10 行，并将它们连接到 `/var/cache/motd-news` 中的缓存文件。此 systemd 计时器作业将每隔 12 小时运行并更新 `/var/cache/motd-news`。用户登录后，`/var/cache/motd-news` 的内容会打印到屏幕上。这就是 MOTD 的工作原理。

此外，`/etc/update-motd.d/50-motd-news` 文件中包含自定义的用户代理字符串，以报告有关计算机的信息。如果你查看 `/etc/update-motd.d/50-motd-news` 文件，你会看到：

```
# Piece together the user agent
USER_AGENT="curl/$curl_ver $lsb $platform $cpu $uptime"
```

这意味着，MOTD 检索器将向 Canonical 报告你的操作系统版本、硬件平台、CPU 类型和正常运行时间。

到这里，希望你对 MOTD 有了一个基本的了解。

现在让我们回到主题，我不想要这个功能。我该如何禁用它？如果欢迎消息中的促销链接仍然困扰你，并且你想永久禁用它们，则可以通过以下方法快速禁用它。

### 在 Ubuntu 服务器中禁用终端欢迎消息中的广告

要禁用这些广告，编辑文件：

```
$ sudo vi /etc/default/motd-news
```

找到以下行并将其值设置为 `0`（零）。

```
[...]
ENABLED=0
[...]
```

保存并关闭文件。现在，重新启动系统，看看欢迎消息是否仍然显示来自 Ubuntu 博客的链接。

![](/data/attachment/album/201811/05/215051b8a4hh575sp1aa97.png)

看到没？现在没有来自 Ubuntu 博客和 Ubuntu wiki 的链接。

这就是全部内容了。希望这对你有所帮助。更多好东西要来了，敬请关注！

顺祝时祺！

---

via: <https://www.ostechnix.com/how-to-disable-ads-in-terminal-welcome-message-in-ubuntu-server/>

作者：[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/) 荣誉推出


在 Linux 上使用 Lutries 管理你的游戏

![](/data/attachment/album/201811/05/222141o9dggd9a9g3fhilg.jpg)

今天我们要讨论的是 **Lutris**，一个 Linux 上的开源游戏平台。你可以使用 Lutries 安装、移除、配置、启动和管理你的游戏。它可以在一个单一界面中帮你管理你的 Linux 游戏、Windows 游戏、仿真控制台游戏和浏览器游戏。它还包含社区编写的安装脚本，使得游戏的安装过程更加简单。

Lutries 自动安装（或者你可以单击点击安装）了超过 20 个模拟器，它提供了从七十年代到现在的大多数游戏系统。目前支持的游戏系统如下：

* Linux 原生
* Windows
* Steam (Linux 和 Windows)
* MS-DOS
* 街机
* Amiga 电脑
* Atari 8 和 16 位计算机和控制器
* 浏览器 (Flash 或者 HTML5 游戏)
* Commmodore 8 位计算机
* 基于 SCUMM 的游戏和其他点击式冒险游戏
* Magnavox Odyssey²、Videopac+
* Mattel Intellivision
* NEC PC-Engine Turbographx 16、Supergraphx、PC-FX
* Nintendo NES、SNES、Game Boy、Game Boy Advance、DS
* Game Cube 和 Wii
* Sega Master Sytem、Game Gear、Genesis、Dreamcast
* SNK Neo Geo、Neo Geo Pocket
* Sony PlayStation
* Sony PlayStation 2
* Sony PSP
* 像 Zork 这样的 Z-Machine 游戏
* 还有更多

### 安装 Lutris

就像 Steam 一样，Lutries 包含两部分：网站和客户端程序。从网站你可以浏览可用的游戏，添加最喜欢的游戏到个人库，以及使用安装链接安装他们。

首先，我们还是来安装客户端。它目前支持 Arch Linux、Debian、Fedroa、Gentoo、openSUSE 和 Ubuntu。

对于 **Arch Linux** 和它的衍生版本，像是 Antergos, Manjaro Linux，都可以在 [AUR](https://aur.archlinux.org/packages/lutris/) 中找到。因此，你可以使用 AUR 帮助程序安装它。

使用 [Pacaur](https://www.ostechnix.com/install-pacaur-arch-linux/)：

```
pacaur -S lutris
```

使用 [Packer](https://www.ostechnix.com/install-packer-arch-linux-2/)：

```
packer -S lutris
```

使用 [Yaourt](https://www.ostechnix.com/install-yaourt-arch-linux/)：

```
yaourt -S lutris
```

使用 [Yay](https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/)：

```
yay -S lutris
```

**Debian:**

在 **Debian 9.0** 上以 **root** 身份运行以下命令：

```
echo 'deb http://download.opensuse.org/repositories/home:/strycore/Debian_9.0/ /' > /etc/apt/sources.list.d/lutris.list
wget -nv https://download.opensuse.org/repositories/home:strycore/Debian_9.0/Release.key -O Release.key
apt-key add - < Release.key
apt-get update
apt-get install lutris
```

在 **Debian 8.0** 上以 **root** 身份运行以下命令：

```
echo 'deb http://download.opensuse.org/repositories/home:/strycore/Debian_8.0/ /' > /etc/apt/sources.list.d/lutris.list
wget -nv https://download.opensuse.org/repositories/home:strycore/Debian_8.0/Release.key -O Release.key
apt-key add - < Release.key
apt-get update
apt-get install lutris
```

在 **Fedora 27** 上以 **root** 身份运行以下命令：

```
dnf config-manager --add-repo https://download.opensuse.org/repositories/home:strycore/Fedora_27/home:strycore.repo
dnf install lutris
```

在 **Fedora 26** 上以 **root** 身份运行以下命令：

```
dnf config-manager --add-repo https://download.opensuse.org/repositories/home:strycore/Fedora_26/home:strycore.repo
dnf install lutris
```

在 **openSUSE Tumbleweed** 上以 **root** 身份运行以下命令：

```
zypper addrepo https://download.opensuse.org/repositories/home:strycore/openSUSE_Tumbleweed/home:strycore.repo
zypper refresh
zypper install lutris
```

在 **openSUSE Leap 42.3** 上以 **root** 身份运行以下命令：

```
zypper addrepo https://download.opensuse.org/repositories/home:strycore/openSUSE_Leap_42.3/home:strycore.repo
zypper refresh
zypper install lutris
```

**Ubuntu 17.10**：

```
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/strycore/xUbuntu_17.10/ /' > /etc/apt/sources.list.d/lutris.list"
wget -nv https://download.opensuse.org/repositories/home:strycore/xUbuntu_17.10/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update
sudo apt-get install lutris
```

**Ubuntu 17.04**：

```
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/strycore/xUbuntu_17.04/ /' > /etc/apt/sources.list.d/lutris.list"
wget -nv https://download.opensuse.org/repositories/home:strycore/xUbuntu_17.04/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update
sudo apt-get install lutris
```

**Ubuntu 16.10**：

```
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/strycore/xUbuntu_16.10/ /' > /etc/apt/sources.list.d/lutris.list"
wget -nv https://download.opensuse.org/repositories/home:strycore/xUbuntu_16.10/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update
sudo apt-get install lutris
```

**Ubuntu 16.04**：

```
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/strycore/xUbuntu_16.04/ /' > /etc/apt/sources.list.d/lutris.list"
wget -nv https://download.opensuse.org/repositories/home:strycore/xUbuntu_16.04/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update
sudo apt-get install lutris
```

对于其他平台，参考 [Lutris 下载链接](https://lutris.net/downloads/)。

### 使用 Lutris 管理你的游戏

安装完成后，从菜单或者应用启动器里打开 Lutries。首次启动时，Lutries 的默认界面像下面这样：

![](/data/attachment/album/201811/05/222143r8e50181l50cmosc.png)

#### 登录你的 Lutris.net 账号

为了能同步你个人库中的游戏，下一步你需要在客户端中登录你的 Lutris.net 账号。如果你没有，先 [注册一个新的账号](https://lutris.net/user/register/)。然后点击 “Connecting to your Lutirs.net account to sync your library” 连接到 Lutries 客户端。

输入你的账号信息然后点击 “Connect”。

![](/data/attachment/album/201811/05/222144gj0p5fpnwffmnywc.png)

现在你已经连接到你的 Lutries.net 账号了。

![](/data/attachment/album/201811/05/222146umaxibgbrhryxiqb.png)

#### 浏览游戏

点击工具栏里的浏览图标（游戏控制器图标）可以搜索任何游戏。它会自动定向到 Lutries 网站的游戏页。你可以以字母顺序查看所有可用的游戏。Lutries 现在已经有了很多游戏，而且还有更多的不断添加进来。

![](/data/attachment/album/201811/05/222149putrjrauaczricou.png)

任选一个游戏，添加到你的库中。

![](/data/attachment/album/201811/05/222151ps0j276uis77jrqz.png)

然后返回到你的 Lutries 客户端，点击 “Menu -> Lutris -> Synchronize library”。现在你可以在本地的 Lutries 客户端中看到所有在库中的游戏了。

![](/data/attachment/album/201811/05/222154eh7s97rc1tptn0zp.png)

如果你没有看到游戏，只需要重启一次。

#### 安装游戏

安装游戏，只需要点击游戏，然后点击 “Install” 按钮。例如，我想在我的系统安装 [2048](https://www.ostechnix.com/let-us-play-2048-game-terminal/)，就像你在底下的截图中看到的，它要求我选择一个版本去安装。因为它只有一个版本（例如，在线），它就会自动选择这个版本。点击 “Continue”。

![](/data/attachment/album/201811/05/222155j7sjaaeoj7mcjcss.png)

点击“Install”：

![](/data/attachment/album/201811/05/222157nosorgivk234r4k2.png)

安装完成之后，你可以启动新安装的游戏或是关闭这个窗口，继续从你的库中安装其他游戏。

#### 导入 Steam 库

你也可以导入你的 Steam 库。在你的头像处点击 “Sign in through Steam” 按钮。接下来你将被重定向到 Steam，输入你的账号信息。填写正确后，你的 Steam 账号将被连接到 Lutries 账号。请注意，为了同步库中的游戏，这里你的 Steam 账号将被公开。你可以在同步完成之后将其重新设为私密状态。

#### 手动添加游戏

Lutries 有手动添加游戏的选项。在工具栏中点击 “+” 号登录。

![](/data/attachment/album/201811/05/222158nj2bj0ifx6ikdkm9.png)

在下一个窗口，输入游戏名，在游戏信息栏选择一个运行器。运行器是指 Linux 上类似 wine、Steam 之类的程序，它们可以帮助你启动这个游戏。你可以从 “Menu -> Manage” 中安装运行器。

![](/data/attachment/album/201811/05/222200mz87hgheazmnk64m.png)

然后在下一栏中选择可执行文件或者 ISO。最后点击保存。有一个好消息是，你可以添加一个游戏的多个版本。

#### 移除游戏

移除任何已安装的游戏，只需在 Lutries 客户端的本地库中点击对应的游戏。选择 “Remove” 然后 “Apply”。

![](/data/attachment/album/201811/05/222202n22fvk8kqkci2t20.png)

Lutries 就像 Steam。只是从网站向你的库中添加游戏，并在客户端中为你安装它们。

各位，这就是今天所有的内容了。我们将会在今年发表更多好的和有用的文章。敬请关注！

干杯！

：）

---

via: <https://www.ostechnix.com/manage-games-using-lutris-linux/>

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

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


Caffeinated 6.828：实验 2：内存管理

Summary: 在本实验中，你将为你的操作系统写内存管理方面的代码。

在本实验中，你将为你的操作系统写内存管理方面的代码。

![](/data/attachment/album/201811/06/161724w1zol0zojs9te07o.jpg)

### 简介

在本实验中，你将为你的操作系统写内存管理方面的代码。内存管理由两部分组成。

第一部分是内核的物理内存分配器，内核通过它来分配内存，以及在不需要时释放所分配的内存。分配器以<ruby> 页 <rt>  page </rt></ruby>为单位分配内存，每个页的大小为 4096 字节。你的任务是去维护那个数据结构，它负责记录物理页的分配和释放，以及每个分配的页有多少进程共享它。本实验中你将要写出分配和释放内存页的全套代码。

第二个部分是虚拟内存的管理，它负责由内核和用户软件使用的虚拟内存地址到物理内存地址之间的映射。当使用内存时，x86 架构的硬件是由内存管理单元（MMU）负责执行映射操作来查阅一组页表。接下来你将要修改 JOS，以根据我们提供的特定指令去设置 MMU 的页表。

#### 预备知识

在本实验及后面的实验中，你将逐步构建你的内核。我们将会为你提供一些附加的资源。使用 Git 去获取这些资源、提交自[实验 1](/article-9740-1.html) 以来的改变（如有需要的话）、获取课程仓库的最新版本、以及在我们的实验 2 （`origin/lab2`）的基础上创建一个称为 `lab2` 的本地分支：

```
athena% cd ~/6.828/lab
athena% add git
athena% git pull
Already up-to-date.
athena% git checkout -b lab2 origin/lab2
Branch lab2 set up to track remote branch refs/remotes/origin/lab2.
Switched to a new branch "lab2"
athena%
```

上面的 `git checkout -b` 命令其实做了两件事情：首先它创建了一个本地分支 `lab2`，它跟踪给我们提供课程内容的远程分支 `origin/lab2` ，第二件事情是，它改变你的 `lab` 目录的内容以反映 `lab2` 分支上存储的文件的变化。Git 允许你在已存在的两个分支之间使用 `git checkout *branch-name*` 命令去切换，但是在你切换到另一个分支之前，你应该去提交那个分支上你做的任何有意义的变更。

现在，你需要将你在 `lab1` 分支中的改变合并到 `lab2` 分支中，命令如下：

```
athena% git merge lab1
Merge made by recursive.
 kern/kdebug.c  |   11 +++++++++--
 kern/monitor.c |   19 +++++++++++++++++++
 lib/printfmt.c |    7 +++----
 3 files changed, 31 insertions(+), 6 deletions(-)
athena%
```

在一些案例中，Git 或许并不知道如何将你的更改与新的实验任务合并（例如，你在第二个实验任务中变更了一些代码的修改）。在那种情况下，你使用 `git` 命令去合并，它会告诉你哪个文件发生了冲突，你必须首先去解决冲突（通过编辑冲突的文件），然后使用 `git commit -a` 去重新提交文件。

实验 2 包含如下的新源代码，后面你将逐个了解它们：

* `inc/memlayout.h`
* `kern/pmap.c`
* `kern/pmap.h`
* `kern/kclock.h`
* `kern/kclock.c`

`memlayout.h` 描述虚拟地址空间的布局，这个虚拟地址空间是通过修改 `pmap.c`、`memlayout.h` 和 `pmap.h` 所定义的 `PageInfo` 数据结构来实现的，这个数据结构用于跟踪物理内存页面是否被释放。`kclock.c` 和 `kclock.h` 维护 PC 上基于电池的时钟和 CMOS RAM 硬件，在此，BIOS 中记录了 PC 上安装的物理内存数量，以及其它的一些信息。在 `pmap.c` 中的代码需要去读取这个设备硬件，以算出在这个设备上安装了多少物理内存，但这部分代码已经为你完成了：你不需要知道 CMOS 硬件工作原理的细节。

特别需要注意的是 `memlayout.h` 和 `pmap.h`，因为本实验需要你去使用和理解的大部分内容都包含在这两个文件中。你或许还需要去看看 `inc/mmu.h` 这个文件，因为它也包含了本实验中用到的许多定义。

开始本实验之前，记得去添加 `exokernel` 以获取 QEMU 的 6.828 版本。

#### 实验过程

在你准备进行实验和写代码之前，先添加你的 `answers-lab2.txt` 文件到 Git 仓库，提交你的改变然后去运行 `make handin`。

```
athena% git add answers-lab2.txt
athena% git commit -am "my answer to lab2"
[lab2 a823de9] my answer to lab2 4 files changed, 87 insertions(+), 10 deletions(-)
athena% make handin
```

正如前面所说的，我们将使用一个评级程序来分级你的解决方案，你可以在 `lab` 目录下运行 `make grade`，使用评级程序来测试你的内核。为了完成你的实验，你可以改变任何你需要的内核源代码和头文件。但毫无疑问的是，你不能以任何形式去改变或破坏评级代码。

### 第 1 部分：物理页面管理

操作系统必须跟踪物理内存页是否使用的状态。JOS 以“页”为最小粒度来管理 PC 的物理内存，以便于它使用 MMU 去映射和保护每个已分配的内存片段。

现在，你将要写内存的物理页分配器的代码。它将使用 `struct PageInfo` 对象的链表来保持对物理页的状态跟踪，每个对象都对应到一个物理内存页。在你能够编写剩下的虚拟内存实现代码之前，你需要先编写物理内存页面分配器，因为你的页表管理代码将需要去分配物理内存来存储页表。

>
> **练习 1**
>
>
> 在文件 `kern/pmap.c` 中，你需要去实现以下函数的代码（或许要按给定的顺序来实现）。
>
>
> * `boot_alloc()`
> * `mem_init()`（只要能够调用 `check_page_free_list()` 即可）
> * `page_init()`
> * `page_alloc()`
> * `page_free()`
>
>
> `check_page_free_list()` 和 `check_page_alloc()` 可以测试你的物理内存页分配器。你将需要引导 JOS 然后去看一下 `check_page_alloc()` 是否报告成功即可。如果没有报告成功，修复你的代码直到成功为止。你可以添加你自己的 `assert()` 以帮助你去验证是否符合你的预期。
>
>
>

本实验以及所有的 6.828 实验中，将要求你做一些检测工作，以便于你搞清楚它们是否按你的预期来工作。这个任务不需要详细描述你添加到 JOS 中的代码的细节。查找 JOS 源代码中你需要去修改的那部分的注释；这些注释中经常包含有技术规范和提示信息。你也可能需要去查阅 JOS 和 Intel 的技术手册、以及你的 6.004 或 6.033 课程笔记的相关部分。

### 第 2 部分：虚拟内存

在你开始动手之前，需要先熟悉 x86 内存管理架构的保护模式：即分段和页面转换。

>
> **练习 2**
>
>
> 如果你对 x86 的保护模式还不熟悉，可以查看 [Intel 80386 参考手册](https://sipb.mit.edu/iap/6.828/readings/i386/toc.htm)的第 5 章和第 6 章。阅读这些章节（5.2 和 6.4）中关于页面转换和基于页面的保护。我们建议你也去了解关于段的章节；在虚拟内存和保护模式中，JOS 使用了分页、段转换、以及在 x86 上不能禁用的基于段的保护，因此你需要去理解这些基础知识。
>
>
>

#### 虚拟地址、线性地址和物理地址

在 x86 的专用术语中，一个<ruby> 虚拟地址 <rt>  virtual address </rt></ruby>是由一个段选择器和在段中的偏移量组成。一个<ruby> 线性地址 <rt>  linear address </rt></ruby>是在页面转换之前、段转换之后得到的一个地址。一个<ruby> 物理地址 <rt>  physical address </rt></ruby>是段和页面转换之后得到的最终地址，它最终将进入你的物理内存中的硬件总线。

![](/data/attachment/album/201811/06/161734ocu4ok5kicyzi5yi.jpg)

一个 C 指针是虚拟地址的“偏移量”部分。在 `boot/boot.S` 中我们安装了一个<ruby> 全局描述符表 <rt>  Global Descriptor Table </rt></ruby>（GDT），它通过设置所有的段基址为 0，并且限制为 `0xffffffff` 来有效地禁用段转换。因此“段选择器”并不会生效，而线性地址总是等于虚拟地址的偏移量。在实验 3 中，为了设置权限级别，我们将与段有更多的交互。但是对于内存转换，我们将在整个 JOS 实验中忽略段，只专注于页转换。

回顾[实验 1](/article-9740-1.html) 中的第 3 部分，我们安装了一个简单的页表，这样内核就可以在 `0xf0100000` 链接的地址上运行，尽管它实际上是加载在 `0x00100000` 处的 ROM BIOS 的物理内存上。这个页表仅映射了 4MB 的内存。在实验中，你将要为 JOS 去设置虚拟内存布局，我们将从虚拟地址 `0xf0000000` 处开始扩展它，以映射物理内存的前 256MB，并映射许多其它区域的虚拟内存。

>
> **练习 3**
>
>
> 虽然 GDB 能够通过虚拟地址访问 QEMU 的内存，它经常用于在配置虚拟内存期间检查物理内存。在实验工具指南中复习 QEMU 的[监视器命令](https://sipb.mit.edu/iap/6.828/labguide/#qemu)，尤其是 `xp` 命令，它可以让你去检查物理内存。要访问 QEMU 监视器，可以在终端中按 `Ctrl-a c`（相同的绑定返回到串行控制台）。
>
>
> 使用 QEMU 监视器的 `xp` 命令和 GDB 的 `x` 命令去检查相应的物理内存和虚拟内存，以确保你看到的是相同的数据。
>
>
> 我们的打过补丁的 QEMU 版本提供一个非常有用的 `info pg` 命令：它可以展示当前页表的一个具体描述，包括所有已映射的内存范围、权限、以及标志。原本的 QEMU 也提供一个 `info mem` 命令用于去展示一个概要信息，这个信息包含了已映射的虚拟内存范围和使用了什么权限。
>
>
>

在 CPU 上运行的代码，一旦处于保护模式（这是在 `boot/boot.S` 中所做的第一件事情）中，是没有办法去直接使用一个线性地址或物理地址的。所有的内存引用都被解释为虚拟地址，然后由 MMU 来转换，这意味着在 C 语言中的指针都是虚拟地址。

例如在物理内存分配器中，JOS 内存经常需要在不反向引用的情况下，去维护作为地址的一个很难懂的值或一个整数。有时它们是虚拟地址，而有时是物理地址。为便于在代码中证明，JOS 源文件中将它们区分为两种：类型 `uintptr_t` 表示一个难懂的虚拟地址，而类型 `physaddr_trepresents` 表示物理地址。这些类型其实不过是 32 位整数（`uint32_t`）的同义词，因此编译器不会阻止你将一个类型的数据指派为另一个类型！因为它们都是整数（而不是指针）类型，如果你想去反向引用它们，编译器将报错。

JOS 内核能够通过将它转换为指针类型的方式来反向引用一个 `uintptr_t` 类型。相反，内核不能反向引用一个物理地址，因为这是由 MMU 来转换所有的内存引用。如果你转换一个 `physaddr_t` 为一个指针类型，并反向引用它，你或许能够加载和存储最终结果地址（硬件将它解释为一个虚拟地址），但你并不会取得你想要的内存位置。

总结如下：

| C 类型 | 地址类型 |
| --- | --- |
| `T*` | 虚拟 |
| `uintptr_t` | 虚拟 |
| `physaddr_t` | 物理 |

>
> 问题：
>
>
> 1. 假设下面的 JOS 内核代码是正确的，那么变量 `x` 应该是什么类型？`uintptr_t` 还是 `physaddr_t` ？
>
>
> ![](/data/attachment/album/201811/06/161734c90qt09q5949mqz1.jpg)
>
>
>

JOS 内核有时需要去读取或修改它只知道其物理地址的内存。例如，添加一个映射到页表，可以要求分配物理内存去存储一个页目录，然后去初始化它们。然而，内核也和其它的软件一样，并不能跳过虚拟地址转换，内核并不能直接加载和存储物理地址。一个原因是 JOS 将重映射从虚拟地址 `0xf0000000` 处的物理地址 `0` 开始的所有的物理地址，以帮助内核去读取和写入它知道物理地址的内存。为转换一个物理地址为一个内核能够真正进行读写操作的虚拟地址，内核必须添加 `0xf0000000` 到物理地址以找到在重映射区域中相应的虚拟地址。你应该使用 `KADDR(pa)` 去做那个添加操作。

JOS 内核有时也需要能够通过给定的内核数据结构中存储的虚拟地址找到内存中的物理地址。内核全局变量和通过 `boot_alloc()` 分配的内存是在内核所加载的区域中，从 `0xf0000000` 处开始的这个所有物理内存映射的区域。因此，要转换这些区域中一个虚拟地址为物理地址时，内核能够只是简单地减去 `0xf0000000` 即可得到物理地址。你应该使用 `PADDR(va)` 去做那个减法操作。

#### 引用计数

在以后的实验中，你将会经常遇到多个虚拟地址（或多个环境下的地址空间中）同时映射到相同的物理页面上。你将在 `struct PageInfo` 数据结构中的 `pp_ref` 字段来记录一个每个物理页面的引用计数器。如果一个物理页面的这个计数器为 0，表示这个页面已经被释放，因为它不再被使用了。一般情况下，这个计数器应该等于所有页表中物理页面出现在 `UTOP` 之下的次数（`UTOP` 之上的映射大都是在引导时由内核设置的，并且它从不会被释放，因此不需要引用计数器）。我们也使用它去跟踪放到页目录页的指针数量，反过来就是，页目录到页表页的引用数量。

使用 `page_alloc` 时要注意。它返回的页面引用计数总是为 0，因此，一旦对返回页做了一些操作（比如将它插入到页表），`pp_ref` 就应该增加。有时这需要通过其它函数（比如，`page_instert`）来处理，而有时这个函数是直接调用 `page_alloc` 来做的。

#### 页表管理

现在，你将写一套管理页表的代码：去插入和删除线性地址到物理地址的映射表，并且在需要的时候去创建页表。

>
> **练习 4**
>
>
> 在文件 `kern/pmap.c` 中，你必须去实现下列函数的代码。
>
>
> * pgdir\_walk()
> * bootmapregion()
> * page\_lookup()
> * page\_remove()
> * page\_insert()
>
>
> `check_page()`，调用自 `mem_init()`，测试你的页表管理函数。在进行下一步流程之前你应该确保它成功运行。
>
>
>

### 第 3 部分：内核地址空间

JOS 分割处理器的 32 位线性地址空间为两部分：用户环境（进程），（我们将在实验 3 中开始加载和运行），它将控制其上的布局和低位部分的内容；而内核总是维护对高位部分的完全控制。分割线的定义是在 `inc/memlayout.h` 中通过符号 `ULIM` 来划分的，它为内核保留了大约 256MB 的虚拟地址空间。这就解释了为什么我们要在实验 1 中给内核这样的一个高位链接地址的原因：如是不这样做的话，内核的虚拟地址空间将没有足够的空间去同时映射到下面的用户空间中。

你可以在 `inc/memlayout.h` 中找到一个图表，它有助于你去理解 JOS 内存布局，这在本实验和后面的实验中都会用到。

#### 权限和故障隔离

由于内核和用户的内存都存在于它们各自环境的地址空间中，因此我们需要在 x86 的页表中使用权限位去允许用户代码只能访问用户所属地址空间的部分。否则，用户代码中的 bug 可能会覆写内核数据，导致系统崩溃或者发生各种莫名其妙的的故障；用户代码也可能会偷窥其它环境的私有数据。

对于 `ULIM` 以上部分的内存，用户环境没有任何权限，只有内核才可以读取和写入这部分内存。对于 `[UTOP,ULIM]` 地址范围，内核和用户都有相同的权限：它们可以读取但不能写入这个地址范围。这个地址范围是用于向用户环境暴露某些只读的内核数据结构。最后，低于 `UTOP` 的地址空间是为用户环境所使用的；用户环境将为访问这些内核设置权限。

#### 初始化内核地址空间

现在，你将去配置 `UTOP` 以上的地址空间：内核部分的地址空间。`inc/memlayout.h` 中展示了你将要使用的布局。我将使用函数去写相关的线性地址到物理地址的映射配置。

>
> **练习 5**
>
>
> 完成调用 `check_page()` 之后在 `mem_init()` 中缺失的代码。
>
>
>

现在，你的代码应该通过了 `check_kern_pgdir()` 和 `check_page_installed_pgdir()` 的检查。

>
> 问题：
>
>
>  1、在这个时刻，页目录中的条目（行）是什么？它们映射的址址是什么？以及它们映射到哪里了？换句话说就是，尽可能多地填写这个表：
>
>
>
>
> | 条目 | 虚拟地址基址 | 指向（逻辑上）： |
> | --- | --- | --- |
> | 1023 | ? | 物理内存顶部 4MB 的页表 |
> | 1022 | ? | ? |
> | . | ? | ? |
> | . | ? | ? |
> | . | ? | ? |
> | 2 | 0x00800000 | ? |
> | 1 | 0x00400000 | ? |
> | 0 | 0x00000000 | [参见下一问题] |
>
>
>  2、(来自课程 3) 我们将内核和用户环境放在相同的地址空间中。为什么用户程序不能去读取和写入内核的内存？有什么特殊机制保护内核内存？
>
>
>  3、这个操作系统能够支持的最大的物理内存数量是多少？为什么？
>
>
>  4、如果我们真的拥有最大数量的物理内存，有多少空间的开销用于管理内存？这个开销可以减少吗？
>
>
>  5、复习在 `kern/entry.S` 和 `kern/entrypgdir.c` 中的页表设置。一旦我们打开分页，EIP 仍是一个很小的数字（稍大于 1MB）。在什么情况下，我们转而去运行在 KERNBASE 之上的一个 EIP？当我们启用分页并开始在 KERNBASE 之上运行一个 EIP 时，是什么让我们能够一个很低的 EIP 上持续运行？为什么这种转变是必需的？
>
>
>

#### 地址空间布局的其它选择

在 JOS 中我们使用的地址空间布局并不是我们唯一的选择。一个操作系统可以在低位的线性地址上映射内核，而为用户进程保留线性地址的高位部分。然而，x86 内核一般并不采用这种方法，因为 x86 向后兼容模式之一（被称为“虚拟 8086 模式”）“不可改变地”在处理器使用线性地址空间的最下面部分，所以，如果内核被映射到这里是根本无法使用的。

虽然很困难，但是设计这样的内核是有这种可能的，即：不为处理器自身保留任何固定的线性地址或虚拟地址空间，而有效地允许用户级进程不受限制地使用整个 4GB 的虚拟地址空间 —— 同时还要在这些进程之间充分保护内核以及不同的进程之间相互受保护！

将内核的内存分配系统进行概括类推，以支持二次幂为单位的各种页大小，从 4KB 到一些你选择的合理的最大值。你务必要有一些方法，将较大的分配单位按需分割为一些较小的单位，以及在需要时，将多个较小的分配单位合并为一个较大的分配单位。想一想在这样的一个系统中可能会出现些什么样的问题。

这个实验做完了。确保你通过了所有的等级测试，并记得在 `answers-lab2.txt` 中写下你对上述问题的答案。提交你的改变（包括添加 `answers-lab2.txt` 文件），并在 `lab` 目录下输入 `make handin` 去提交你的实验。

---

via: <https://sipb.mit.edu/iap/6.828/lab/lab2/>

作者：[Mit](https://sipb.mit.edu/iap/6.828/lab/lab2/) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


对 C++ 的忧虑？C++ 创始人警告：关于 C++ 的某些未来计划十分危险

Summary: Bjarne Stroustrup 是 C++ 语言的创始人，他写了一封信，请那些关注编程语言进展的人去“想想瓦萨号！”

![](/data/attachment/album/201811/06/164654t32a8b1rzdnt38a3.jpg)

今年早些时候，我们对 Bjarne Stroustrup 进行了采访。他是 C++ 语言的创始人，摩根士丹利技术部门的董事总经理，美国哥伦比亚大学计算机科学的客座教授。他写了[一封信](http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0977r0.pdf)，请那些关注编程语言进展的人去“想想瓦萨号！”

这句话对于丹麦人来说，毫无疑问，很容易理解。而那些对于 17 世纪的斯堪的纳维亚历史了解不多的人，还需要详细说明一下。瓦萨号是一艘瑞典军舰，由国王 Gustavus Adolphus 定做。它是当时波罗的海国家中最强大的军舰，但在 1628 年 8 月 10 日首航没几分钟之后就沉没了。

![](/data/attachment/album/201811/06/164644atfrqo3hqf55wnyq.jpg)

巨大的瓦萨号有一个难以解决的设计缺陷：头重脚轻，以至于它被[一阵狂风刮翻了](https://www.vasamuseet.se/en/vasa-history/disaster)。通过援引这艘沉船的历史，Stroustrup 警示了 C++ 所面临的风险 —— 现在越来越多的特性被添加到了 C++ 中。

我们现在已经发现了好些能导致头重脚轻的特性。Stroustrup 在他的信中引用了 43 个提议。他认为那些参与 C++ 语言 ISO 标准演进的人（即所谓的 [WG21 小组](http://open-std.org/JTC1/SC22/WG21/)）正在努力推进语言发展，但成员们的努力方向却并不一致。

在他的信中，他写道：

>
> 分开来看，许多提议都很有道理。但将它们综合到一起，这些提议是很愚蠢的，将危害 C++ 的未来。
>
>
>

他明确表示，他用瓦萨号作为比喻并不是说他认为不断提升会带来毁灭。我们应该吸取瓦萨号的教训，构建一个坚实的基础，从错误中学习并对新版本做彻底的测试。

在瑞士<ruby> 拉普斯威尔 <rt>  Rapperswill </rt></ruby>召开 C++ 标准化委员会会议之后，本月早些时候，Stroustrup 接受了 *The Register* 的采访，回答了有关 C++ 语言下一步发展方向的几个问题。（最新版是去年刚发布的 C++17；下一个版本是 C++20，预计于 2020 年发布。）

*Register：*在您的信件《想想瓦萨号！》中，您写道：

>
> 在 C++11 开始的基础建设尚未完成，而 C++17 基本没有在使基础更加稳固、规范和完整方面做出改善。相反，却增加了重要接口的复杂度（原文为 surface complexity，直译“表面复杂度”），让人们需要学习的特性数量越来越多。C++ 可能在这种不成熟的提议的重压之下崩溃。我们不应该花费大量的时间为专家级用户们（比如我们自己）去创建越来越复杂的东西。~~（还要考虑普通用户的学习曲线，越复杂的东西越不易普及。）~~
>
>
>

**对新人来说，C++ 过难了吗？如果是这样，您认为怎样的特性让新人更易理解？**

*Stroustrup：*C++ 的有些东西对于新人来说确实很具有挑战性。

另一方面而言，C++ 中有些东西对于新人来说，比起 C 或上世纪九十年代的 C++ 更容易理解了。而难点是让大型社区专注于这些部分，并且帮助新手和非专业的 C++ 用户去规避那些对高级库实现提供支持的部分。

我建议使用 [C++ 核心准则](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)作为实现上述目标的一个辅助。

此外，我的“C++ 教程”也可以帮助人们在使用现代 C++ 时走上正确的方向，而不会迷失在自上世纪九十年代以来的复杂性中，或困惑于只有专家级用户才能理解的东西中。这本即将出版的第二版的“C++ 教程”涵盖了 C++17 和部分 C++20 的内容。

我和其他人给没有编程经验的大一新生教过 C++，只要你不去深入编程语言的每个晦涩难懂的角落，把注意力集中到 C++ 中最主流的部分，就可以在三个月内学会 C++。

“让简单的东西保持简单”是我长期追求的目标。比如 C++11 的 `range-for` 循环：

```
for (int& x : v) ++x; // increment each element of the container v
```

`v` 的位置可以是任何容器。在 C 和 C 风格的 C++ 中，它可能看起来是这样：

```
for (int i=0; i<MAX; i++) ++v[i]; // increment each element of the array v
```

一些人抱怨说添加了 `range-for` 循环让 C++ 变得更复杂了，很显然，他们是正确的，因为它添加了一个新特性。但它却让 C++ 用起来更简单，而且同时它还消除了使用传统 `for` 循环时会出现的一些常见错误。

另一个例子是 C++11 的<ruby> 标准线程库 <rt>  standard thread library </rt></ruby>。它比起使用 POSIX 或直接使用 Windows 的 C API 来说更简单，并且更不易出错。

*Register：***您如何看待 C++ 现在的状况？**

*Stroustrup：*C++11 中作出了许多重大改进，并且我们在 C++14 上全面完成了改进工作。C++17 添加了相当多的新特性，但是没有提供对新技术的很多支持。C++20 目前看上去可能会成为一个重大改进版。编译器的状况非常好，标准库实现得也很优秀，非常接近最新的标准。C++17 现在已经可以使用，对于工具的支持正在逐步推进。已经有了许多第三方的库和好些新工具。然而，不幸的是，这些东西不太好找到。

我在《想想瓦萨号！》一文中所表达的担忧与标准化过程有关，对新东西的过度热情与完美主义的组合推迟了重大改进。“追求完美往往事与愿违”。在六月份拉普斯威尔的会议上有 160 人参与；在这样一个数量庞大且多样化的人群中很难取得一致意见。专家们也本来就有只为自己设计语言的倾向，这让他们不会时常在设计时考虑整个社区的需求。

*Register：***C++ 是否有一个理想的状态，或者与之相反，您只是为了程序员们的期望而努力，随时适应并且努力满足程序员们的需要？**

*Stroustrup：*二者都有。我很乐意看到 C++ 支持彻底保证<ruby> 类型安全 <rt>  type-safe </rt></ruby>和<ruby> 资源安全 <rt>  resource-safe </rt></ruby>的编程方式。这不应该通过限制适用性或增加性能损耗来实现，而是应该通过改进的表达能力和更好的性能来实现。通过让程序员使用更好的（和更易用的）语言工具可以达到这个目标，我们可以做到的。

终极目标不会马上实现，也不会单靠语言设计来实现。为了实现这一目标，我们需要改进语言特性、提供更好的库和静态分析，并且设立提升编程效率的规则。C++ 核心准则是我为了提升 C++ 代码质量而实行的广泛而长期的计划的一部分。

*Register：***目前 C++ 是否面临着可以预见的风险？如果有，它是以什么形式出现的？（如，迭代过于缓慢，新兴低级语言，等等……据您的观点来看，似乎是提出的提议过多。）**

*Stroustrup：*就是这样。今年我们已经收到了 400 篇文章。当然了，它们并不都是新提议。许多提议都与规范语言和标准库这一必需而乏味的工作相关，但是量大到难以管理。你可以在 [WG21 网站](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/)上找到所有这些文章。

我写了《想想瓦萨号！》这封信作为一个呼吁，因为这种为了解决即刻需求（或者赶时髦）而不断增添语言特性，却对巩固语言基础（比如，改善<ruby> 静态类型系统 <rt>  static type system </rt></ruby>）不管不问的倾向让我感到震惊。增加的任何新东西，无论它多小都会产生成本，比如实现、学习、工具升级。重大的特性改变能够改变我们对编程的想法，而它们才是我们必须关注的东西。

委员会已经设立了一个“指导小组”，这个小组由在语言、标准库、实现、以及工程实践领域中拥有不错履历的人组成。我是其中的成员之一。我们负责为重点领域写[一些关于发展方向、设计理念和建议重点发展领域的东西](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0939r0.pdf)。

对于 C++20，我们建议去关注：

* 概念
* 模块（适度地模块化并带来编译时的显著改进）
* Ranges（包括一些无限序列的扩展）
* 标准库中的网络概念

在拉普斯威尔会议之后，这些都有了实现的机会，虽然模块和网络化都不是会议的重点讨论对象。我是一个乐观主义者，并且委员会的成员们都非常努力。

我并不担心其它语言或新语言会取代它。我喜欢编程语言。如果一门新的语言提供了独一无二的、非常有用的东西，那它就是我们的榜样，我们可以向它学习。当然，每门语言本身都有一些问题。C++ 的许多问题都与它广泛的应用领域、大量的使用人群和过度的热情有关。大多数语言的社区都会有这样的问题。

*Register：***关于 C++ 您是否重新考虑过任何架构方面的决策？**

*Stroustrup：*当我着手规划新版本时，我经常反思原来的决策和设计。关于这些，可以看我的《编程的历史》论文第 [1](http://www.stroustrup.com/hopl-almost-final.pdf)、[2](http://www.stroustrup.com/hopl2.pdf) 部分。

并没有让我觉得很后悔的重大决策。如果我必须重新做一次，我觉得和以前做的不会有太大的不同。

与以前一样，能够直接处理硬件加上零开销的抽象是设计的指导思想。使用<ruby> 构造函数 <rt>  constructor </rt></ruby>和<ruby> 析构函数 <rt>  destructor </rt></ruby>去处理资源是关键（<ruby> 资源获取即初始化 <rt>  Resource Acquisition Is Initialization </rt> <ruby>  ，RAII）；  <ruby>   标准模板库   <rt>    Standard Template Library   </rt>  </ruby>  （STL） 就是解释 C++ 库能够做什么的一个很好的例子。 </ruby></ruby>

*Register：***在 2011 年被采纳的每三年发布一个新版本的节奏是否仍然有效？我之所以这样问是因为 Java 已经决定更快地迭代。**

*Stroustrup：*我认为 C++20 将会按时发布（就像 C++14 和 C++17 那样），并且主流的编译器也会立即采用它。我也希望 C++20 基于 C++17 能有重大的改进。

对于其它语言如何管理它们的版本，我并不十分关心。C++ 是由一个遵循 ISO 规则的委员会来管理的，而不是由某个大公司或某种“<ruby> 终生的仁慈独裁者 <rt>  Beneficial Dictator Of Life </rt></ruby>（BDOL）”来管理。这一点不会改变。C++ 每三年发布一次的周期在 ISO 标准中是一个引人注目的创举。通常而言，周期应该是 5 或 10 年。

*Register：***在您的信中您写道：**

>
> 我们需要一个能够被“普通程序员”使用的，条理还算清楚的编程语言。他们主要关心的是，能否按时高质量地交付他们的应用程序。
>
>
>

改进语言能够解决这个问题吗？或者，我们还需要更容易获得的工具和教育支持？

*Stroustrup：*我尽力宣传我关于 C++ 的实质和使用方式的[理念](http://www.stroustrup.com/papers.html)，并且我鼓励其他人也和我采取相同的行动。

特别是，我鼓励讲师和作者们向 C++ 程序员们提出有用的建议，而不是去示范复杂的示例和技术来展示他们自己有多高明。我在 2017 年的 CppCon 大会上的演讲主题就是“学习和传授 C++”，并且也指出，我们需要更好的工具。

我在演讲中提到了构建技术支持和包管理器，这些历来都是 C++ 的弱项。标准化委员会现在有一个工具研究小组，或许不久的将来也会组建一个教育研究小组。

C++ 的社区以前是十分无组织性的，但是在过去的五年里，为了满足社区对新闻和技术支持的需要，出现了很多集会和博客。CppCon、isocpp.org、以及 Meeting++ 就是一些例子。

在一个庞大的委员会中做语言标准设计是很困难的。但是，对于所有的大型项目来说，委员会又是必不可少的。我很忧虑，但是关注它们并且面对问题是成功的必要条件。

*Register：***您如何看待 C++ 社区的流程？在沟通和决策方面你希望看到哪些变化？**

*Stroustrup：*C++ 并没有企业管理一般的“社区流程”；它所遵循的是 ISO 标准流程。我们不能对 ISO 的条例做大的改变。理想的情况是，我们设立一个小型的、全职的“秘书处”来做最终决策和方向管理，但这种理想情况是不会出现的。相反，我们有成百上千的人在线讨论，大约有 160 人在技术问题上进行投票，大约有 70 组织和 11 个国家的人在最终提议上正式投票。这样很混乱，但是有些时候它的确能发挥作用。

*Register：***在最后，您认为那些即将推出的 C++ 特性中，对 C++ 用户最有帮助的是哪些？**

*Stroustrup：*

* 那些能让编程显著变简单的概念。
* <ruby> 并行算法 <rt>  Parallel algorithms </rt></ruby> —— 如果要使用现代硬件的并发特性的话，这方法再简单不过了。
* <ruby> 协程 <rt>  Coroutines </rt></ruby>，如果委员会能够确定在 C++20 上推出。
* 改进了组织源代码方式的，并且大幅改善了编译时间的模块。我希望能有这样的模块，但是还没办法确定我们能不能在 C++20 上推出。
* 一个标准的网络库，但是还没办法确定我们能否在 C++20 上推出。

此外：

* Contracts（运行时检查的先决条件、后置条件、和断言）可能对许多人都非常重要。
* date 和 time-zone 支持库可能对许多人（行业）非常重要。

*Register：***您还有想对读者们说的话吗？**

*Stroustrup：*如果 C++ 标准化委员会能够专注于重大问题，去解决重大问题，那么 C++20 将会非常优秀。但是在 C++20 推出之前，我们还有 C++17；无论如何，它仍然远超许多人对 C++ 的旧印象。®

---

via: <https://www.theregister.co.uk/2018/06/18/bjarne_stroustrup_c_plus_plus/>

作者：[Thomas Claburn](http://www.theregister.co.uk/Author/3190) 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[thecyanbird](https://github.com/thecyanbird)、[Northurland](https://github.com/Northurland)、[pityonline](https://github.com/pityonline)

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


Python 数据科学入门

Summary: 不需要昂贵的工具即可领略数据科学的力量，从这些开源工具起步即可。

不需要昂贵的工具即可领略数据科学的力量，从这些开源工具起步即可。

>
> 不需要昂贵的工具即可领略数据科学的力量，从这些开源工具起步即可。
>
>
>

![](/data/attachment/album/201811/06/195017agc777rln78znrl2.jpg)

无论你是一个具有数学或计算机科学背景的资深数据科学爱好者，还是一个其它领域的专家，数据科学提供的可能性都在你力所能及的范围内，而且你不需要昂贵的，高度专业化的企业级软件。本文中讨论的开源工具就是你入门时所需的全部内容。

[Python](https://www.python.org/)，其机器学习和数据科学库（[pandas](https://pandas.pydata.org/)、 [Keras](https://keras.io/)、 [TensorFlow](https://www.tensorflow.org/)、 [scikit-learn](http://scikit-learn.org/stable/)、 [SciPy](https://www.scipy.org/)、 [NumPy](http://www.numpy.org/) 等），以及大量可视化库（[Matplotlib](https://matplotlib.org/)、[pyplot](https://matplotlib.org/api/pyplot_api.html)、 [Plotly](https://plot.ly/) 等）对于初学者和专家来说都是优秀的自由及开源软件工具。它们易于学习，很受欢迎且受到社区支持，并拥有为数据科学而开发的最新技术和算法。它们是你在开始学习时可以获得的最佳工具集之一。

许多 Python 库都是建立在彼此之上的（称为依赖项），其基础是 [NumPy](http://www.numpy.org/) 库。NumPy 专门为数据科学设计，经常被用于在其 ndarray 数据类型中存储数据集的相关部分。ndarray 是一种方便的数据类型，用于将关系表中的记录存储为 `cvs` 文件或其它任何格式，反之亦然。将 scikit 函数应用于多维数组时，它特别方便。SQL 非常适合查询数据库，但是对于执行复杂和资源密集型的数据科学操作，在 ndarray 中存储数据可以提高效率和速度（但请确保在处理大量数据集时有足够的 RAM）。当你使用 pandas 进行知识提取和分析时，pandas 中的 DataFrame 数据类型和 NumPy 中的 ndarray 之间的无缝转换分别为提取和计算密集型操作创建了一个强大的组合。

作为快速演示，让我们启动 Python shell 并在 pandas DataFrame 变量中加载来自巴尔的摩的犯罪统计数据的开放数据集，并查看加载的一部分 DataFrame：

```
>>>  import pandas as pd
>>>  crime_stats = pd.read_csv('BPD_Arrests.csv')
>>>  crime_stats.head()
```

![](/data/attachment/album/201811/06/195030toone53knfmxnp31.jpg)

我们现在可以在这个 pandas DataFrame 上执行大多数查询，就像我们可以在数据库中使用 SQL 一样。例如，要获取 `Description` 属性的所有唯一值，SQL 查询是：

```
$ SELECT unique(“Description”) from crime_stats;
```

利用 pandas DataFrame 编写相同的查询如下所示：

```
>>>  crime_stats['Description'].unique()
['COMMON   ASSAULT'   'LARCENY'   'ROBBERY   - STREET'   'AGG.   ASSAULT'
'LARCENY   FROM   AUTO'   'HOMICIDE'   'BURGLARY'   'AUTO   THEFT'
'ROBBERY   - RESIDENCE'   'ROBBERY   - COMMERCIAL'   'ROBBERY   - CARJACKING'
'ASSAULT   BY  THREAT'   'SHOOTING'   'RAPE'   'ARSON']
```

它返回的是一个 NumPy 数组（ndarray 类型）：

```
>>>  type(crime_stats['Description'].unique())
<class   'numpy.ndarray'>
```

接下来让我们将这些数据输入神经网络，看看它能多准确地预测使用的武器类型，给出的数据包括犯罪事件，犯罪类型以及发生的地点：

```
>>>  from   sklearn.neural_network   import   MLPClassifier
>>>  import   numpy   as np
>>>
>>>  prediction   =  crime_stats[[‘Weapon’]]
>>>  predictors   =  crime_stats['CrimeTime',   ‘CrimeCode’,   ‘Neighborhood’]
>>>
>>>  nn_model   =  MLPClassifier(solver='lbfgs',   alpha=1e-5,   hidden_layer_sizes=(5,
2),   random_state=1)
>>>
>>>predict_weapon   =  nn_model.fit(prediction,   predictors)
```

现在学习模型准备就绪，我们可以执行一些测试来确定其质量和可靠性。对于初学者，让我们输入一个训练集数据（用于训练模型的原始数据集的一部分，不包括在创建模型中）：

```
>>>  predict_weapon.predict(training_set_weapons)
array([4,   4,   4,   ..., 0,   4,   4])
```

如你所见，它返回一个列表，每个数字预测训练集中每个记录的武器。我们之所以看到的是数字而不是武器名称，是因为大多数分类算法都是用数字优化的。对于分类数据，有一些技术可以将属性转换为数字表示。在这种情况下，使用的技术是标签编码，使用 sklearn 预处理库中的 `LabelEncoder` 函数：`preprocessing.LabelEncoder()`。它能够对一个数据和其对应的数值表示来进行变换和逆变换。在这个例子中，我们可以使用 `LabelEncoder()` 的 `inverse_transform` 函数来查看武器 0 和 4 是什么:

```
>>>  preprocessing.LabelEncoder().inverse_transform(encoded_weapons)
array(['HANDS',   'FIREARM',   'HANDS',   ..., 'FIREARM',   'FIREARM',   'FIREARM']
```

这很有趣，但为了了解这个模型的准确程度，我们将几个分数计算为百分比：

```
>>>  nn_model.score(X,   y)
0.81999999999999995

```

这表明我们的神经网络模型准确度约为 82%。这个结果似乎令人印象深刻，但用于不同的犯罪数据集时，检查其有效性非常重要。还有其它测试来做这个，如相关性、混淆、矩阵等。尽管我们的模型有很高的准确率，但它对于一般犯罪数据集并不是非常有用，因为这个特定数据集具有不成比例的行数，其列出 `FIREARM` 作为使用的武器。除非重新训练，否则我们的分类器最有可能预测 `FIREARM`，即使输入数据集有不同的分布。

在对数据进行分类之前清洗数据并删除异常值和畸形数据非常重要。预处理越好，我们的见解准确性就越高。此外，为模型或分类器提供过多数据（通常超过 90%）以获得更高的准确度是一个坏主意，因为它看起来准确但由于[过度拟合](https://www.kdnuggets.com/2014/06/cardinal-sin-data-mining-data-science.html)而无效。

[Jupyter notebooks](http://jupyter.org/) 相对于命令行来说是一个很好的交互式替代品。虽然 CLI 对于大多数事情都很好，但是当你想要运行代码片段以生成可视化时，Jupyter 会很出色。它比终端更好地格式化数据。

[这篇文章](https://machinelearningmastery.com/best-machine-learning-resources-for-getting-started/) 列出了一些最好的机器学习免费资源，但是还有很多其它的指导和教程。根据你的兴趣和爱好，你还会发现许多开放数据集可供使用。作为起点，由 [Kaggle](https://www.kaggle.com/) 维护的数据集，以及在州政府网站上提供的数据集是极好的资源。

---

via: <https://opensource.com/article/18/3/getting-started-data-science>

作者：[Payal Singh](https://opensource.com/users/payalsingh) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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