Ubuntu 已经 12 岁了！

現在Ubuntu很受西方學生歡迎，廣泛用於學生的桌面電腦和伺服器。<- 其實感覺都是小白在用，看到大神一般都是用Arch或者Gentoo的

至於企業嘛，RH腦殘粉表示，世界500強企業幾乎都用的是RHEL。

无语，ubuntu强项在桌面和云计算领域，用ubuntu就成了小白？<br />
非得花费大量的时间去安装编译一个系统，这才是低手才会做的事，即开即用，即时上手才是王道，安装编译一个桌面linux系统在我看来并不能说明有多屌。

我申請過一張CD，他們真給寄到國內，我的辦公室了，好像是2010年左右，那時候Adobe PDF Reader還官方支持Linux。不過後來有兩次，我的系統崩潰了，從此就鎖定Debian和openSUSE，不過後來，16.04LTS我又裝上玩了玩，回憶了一下從前的記憶～

哈哈 我以前一个学长存了一堆Ubuntu的cd

以前很喜欢“折腾”各种Linux，基本就是学习加好玩，现在只是希望打开系统就能直接去做要做的事了，而不是花一堆时间弄好配置然后在进入正题，我主要用来做开发，不是做运维，而且运维也更希望自动化会方便点。这一点上基本上一个正常的Linux发型版都允许你去写脚本做配置，arch能做rh能做，Ubuntu也能做，一样的吧。

这都是文物啊，谁要是能从 4.10 开始收集齐所有官方 CD 的话，我愿意出高价收过来~

先生请跟我们走一趟，我们怀疑你涉嫌刷版本号

不是我，是火狐狸和氪星人。。。

确实，总折腾都烦了。

2016 年 10 月 20 日，Ubuntu 12 岁了！从 2004 年的这一天，创始人 Mark Shuttleworth 发布了 Ubuntu 的第一个版本 Ubuntu 4.10 （Warty Warthog）开始，Ubuntu 已经发布了 25 个主要版本。

![](/data/attachment/album/201610/22/124739bh17fvpg2fv1d1fs.jpg)

可能有些人还记得当年 Ubuntu Linux 背后的 Canonical 公司所采用的一种赠送 Ubuntu 安装 CD 的方式。当时网络环境并不是很快，下载几百 M 的镜像，还得有个可以刻录 CD 的设备，这对于 Linux 和 Ubuntu 的推广形成了一定阻碍，因此，Canonical 率先采用了一种免费提供安装 CD 的方式。只要你申请，Canonical 就会从国外寄过来包装精美的 Ubuntu 安装 CD。这可能是很多人的第一个正版的软件 CD 呢。那些年， Canonical 到底送出去多少 CD，花了多少邮费，我们并没有一个具体的数据，不过显然不是一个小数目，这也多亏了[创始人 Mark Shuttleworth](/article-7523-1.html) 是一个亿万富翁，Canonical 得益于他的支持，并不像其它的开源组织那样资金捉襟见肘才能行此壮举。

![](/data/attachment/album/201610/22/125854r80c8e3yn88yegp8.jpg)

12 年过去了，已经有了 25 个发行版本、十几个特色分支的 Ubuntu 已经成为了现今最流行的 Linux 发行版之一，广泛用于桌面、服务器和云领域。虽然 Mark Shuttleworth [2011 年吹下的牛好像并没有实现](/article-6773-1.html)，但是他们认为，从某种意义上讲，[Ubuntu 的用户可能已经超过了 10亿](/article-6784-1.html)。

而就在前几天，Ubuntu 16.10 （Yakkety Yak）也发布了，下一个版本 Ubuntu 17.04 （Zesty Zapus）明年后，不知道会不会又会再次从字母“A”开始产品代号。

![](/data/attachment/album/201610/22/130540yee1a9dw7ezbfabh.png)

（[版本历史图](https://en.wikipedia.org/wiki/Ubuntu_version_history)来自维基百科）

Ubuntu 从最初的一个主要关注于 Debian 衍生版开始，目前已经将触手探入到服务器、云环境、物联网等各个领域，让我们期待 Ubuntu 取得更好的发展，与开源和自由同在！


Firefox 52 将正式支持 TLS 1.3

great!

Mozilla 宣布计划将在明年发布的 Firefox 52 中支持 TLS 1.3，TLS 1.3 是当前仍在开发中的 TLS 安全协议的最新版本。

之前，Mozilla 已经在六月中发布的 Firefox 49 的开发版本中添加了对 TLS 1.3 的支持，当然，由于该协议还在开发阶段，所以基本上还没有支持它的网站，因此该特性并未默认启用（需要通过 about:config 来启用）。

![](/data/attachment/album/201610/22/135127fynakyksxwtrfzrw.jpg)

在一篇[公告](https://groups.google.com/forum/#!topic/mozilla.dev.platform/sfeqeMkyxCI)中，Mozilla 首席工程师兼<ruby> 互联网架构委员会 <rp>  （ </rp> <rt>  Internet Architecture Board </rt> <rp>  ） </rp></ruby>（IAB）成员 Martin Thomson 说，Firefox 52 将是第一个为所有用户启用 TLS 1.3 支持的稳定版 Firefox 浏览器。

### TLS 1.3 协议得到了 Mozilla、Chrome、Edge 等主流浏览器的欢迎

TLS 协议是 HTTPS 网站工作的基础，它负责用户浏览器和 Web 服务器之间的建立加密通讯的安全操作。TLS 1.3 当前仍是 IETF 的草案，[这里](https://tools.ietf.org/html/draft-ietf-tls-tls13-16)可以查看该草案。

“TLS 1.3 移除了陈旧和不安全的加密基元，它采用现代化的分析技术使之更安全，更保密，它将保护更多的数据，也会比 TLS 1.2 更快，” Thomson 解释说，“TLS 1.3 提供了一个 0-RTT 模式，消除了握手往返的延迟。”

他还说，Mozilla 计划使用 TLS 1.3 规范的第 16 个草案，但是会随时更新使用最新的草案，直到部署最终版本。

此外，9 月份时，CloudFlare 宣布在他们的服务器上[添加了 TLS 1.3 的支持](https://blog.cloudflare.com/introducing-tls-1-3/)。而其他主流浏览器厂商，比如微软和谷歌也分别宣布在 Edge 和 Chrome Canary 中支持 TLS 1.3。


Ubuntu 提供实时补丁服务，更新内核不需要重启了

Summary: 通常，内核实时补丁用于大规模操作系统分发上，而现在， Canonical 将这个功能也提供给了它的每个用户，每人可以有三台机器使用免费的内核实时补丁服务。

收费都是从低到高的，从滴滴打车到这些假自由软件都一样的方法，无聊的货们

来自陕西西安的 Chrome Mobile 54.0|Android 6.0 用户

呵呵:-)<br />
C社已经无聊到这种程度了。

Canonical 的 Dustin Kirkland 发布消息称，Ubuntu 16.04 LTS 的用户可以启用新的实时更新内核服务了。

你可能还记得，一年半之前发布的 [Linux 4.0 内核](/article-5272-1.html)带来了一个新功能，允许用户不用重启就可以对内核进行更新或打补丁。该功能称之为<ruby> 内核实时补丁 <rp>  （ </rp> <rt>  kernel live patching </rt> <rp>  ） </rp></ruby>，但是直到现在，仍然没有 GNU/Linux 发行版为用户免费提供它。目前，只有类似 [SUSE 企业 Linux （SLES）](/article-7360-1.html)或红帽企业 Linux（RHEL）这样的商业服务提供了该功能。

![](/data/attachment/album/201610/22/145235x25117ocsv55kp5z.jpg)

“内核实时补丁可以让你不用重启就可以在运行环境中修复内核中的严重安全问题。这是确保机器在内核层面安全的最好办法，并且它不会中断服务时间，特别是用作容器宿主机时，一台机器运行着上千个不同的任务。” Canonical 的 Ubuntu 产品与战略部门的 Dustin Kirkland 说到。

通常，内核实时补丁用于大规模操作系统的分发上，而现在， Canonical 将这个功能也提供给了它的每个用户，每人可以有三台机器使用免费的内核实时补丁服务。

### 如何在 Ubuntu 上启用内核实时补丁服务

如果你想在你的 Ubuntu 上启用这个服务，首先你需要去 Canonical 的[实时补丁服务网站](https://ubuntu.com/livepatch)获取一个令牌，这是一串类似 md5 编码的字符串。然后使用如下命令安装 livepatch 的 Snap 软件包，并用你的令牌来启用该服务。

```
sudo snap install canonical-livepatch
sudo canonical-livepatch enable d3b07384d113edec49eaa6238ad5ff00
```

这样，你就启用了内核实时补丁服务。你可以通过如下命令来检查是否已经生效：

```
canonical-livepatch status
  kernel: 4.4.0-38.57-generic
  fully-patched: true
  version: "12.2"
```

这个服务可以免费用在你的最多三个机器上。一般来说，就个人使用也足够了，但是如果对于将 Ubuntu 或 Ubuntu server 用于企业环境的用户来说，三台就显然不够了，超过三台的部分，你可以购买一份[商业支持服务](http://ubuntu.com/advantage)，每个月 $12 起。

另外，需要注意的是，Canonical 的实时补丁服务仅支持 64 位的 Ubuntu 16.04，且运行长期支持版的 Linux 4.4 内核才行。

（高清题图来自：[klowner.com](http://klowner.com/wallery/christmas_tux_2013/download/christmastux2013.svg)）


在主要浏览器禁用后，SHA-1 使用量得到了下降

使用量的到下降？这标题感觉怪怪的》》》

在 Mozilla 宣布计划阶段性废弃 SHA-1 算法签名的证书一年后，SHA-1 的使用量得到了显著下降。据 Firefox 的数据看，使用量从去年的 50% 降至今年三月的 3.5%，而到这个月仅占到加密流量的 0.8%。

Mozilla [最近宣布](https://blog.mozilla.org/security/2016/10/18/phasing-out-sha-1-on-the-public-web/)，从 Firefox 51 开始，该浏览器将对 SHA-1 签名的证书显示“不可信的连接”错误信息。Firefox 51 将发布于 2017 年 1 月，Mozilla 最初计划于 2017 年初拉黑 SHA-1 证书。

![](/data/attachment/album/201610/23/111037m0ctivixhxevxee4.jpg)

### Mozilla 率先推动了 SHA-1 废弃

在去年秋天荷兰和法国的大学研究人员们发现可以[非常容易地破解 SHA-1 加密](http://news.softpedia.com/news/sha1-algorithm-could-become-useless-by-the-end-of-the-year-494097.shtml)后， Mozilla 率先推动了 SHA-1 废弃的活动。

在 Mozilla 制定了其阶段性[废弃 SHA-1 算法的时间表](http://news.softpedia.com/news/mozilla-outlines-plan-to-phase-out-sha-1-certificates-as-1-million-sites-still-employ-them-495011.shtml)之后，[谷歌](http://news.softpedia.com/news/after-microsoft-and-mozilla-google-also-hurries-to-block-sha-1-certificates-497942.shtml)和[微软](http://news.softpedia.com/news/microsoft-moves-to-deprecate-sha-1-certificates-in-edge-and-internet-explorer-503597.shtml)也跟着做了相同的决定，这些计划得到了 NIST 的支持。从 2016 年元旦开始，浏览器厂商们就禁用了之后新签发的 SHA-1 签名的 SSL/TLS 证书。

### SHA-1 废弃基本上完成了

即便是有一些[例外](http://news.softpedia.com/news/mozilla-gives-a-security-pass-to-the-people-it-shouldn-t-500986.shtml)，甚至还有一些[争议](http://news.softpedia.com/news/chinese-https-provider-wosign-fires-ceo-after-back-dating-certificate-fiasco-509140.shtml)，但是在多数情况下，CA 厂商们都遵从了此次 SHA-1 禁用行动，SHA-1 市场份额的降低表明了他们的工作成果。

如今，之前签发的使用 SHA-1 签名的旧证书仍然被标为可信，但是从 2017 年元旦开始，浏览器厂商们就会将这类证书标为不可信，无论其签发日期是何时。

Mozilla 的加密工程师 J.C. Jones 说，特殊情况下，比如在内部站点或其它封闭性网络内，如果 SHA-1 证书是由手动导入的根证书签发的，Firefox 不会显示该警告。

在 2015 年底，[Facebook 和 Cloudflare 提议](/article-6721-1.html)允许 CA 厂商们为那些不支持 SHA-2 和其它算法的老浏览器签发 SHA-1 证书，但是这个倡议基本上没得到响应，尽管这有一定的意义。


又一顶帽子：适用于初学者的 Fedora —— Chapeau Linux 24 已发布

Summary: 你可能已经知道 Fedora 是一种帽子。我认为因为 Fedora 是来自红帽的一个社区项目，所以他们命名它为另一种帽子。有趣的是，Chapeau 也是一种帽子，一种法国帽子。

又一个轮子

没有对比就没有伤害。轮子也有好用不好用。可惜桌面版大家都比不过win。

又一个轮子

然而我不喜欢GNOME

这个默认自带httpd，然后占用100%cpu   卸载后就没事了   有人遇到过么

最烦Gnome3，之前定制了半天把它定制成Gnome2，结果发现还没Mate好用，再见。

地沟油大法……红帽的试验品…

Fedora本身已经很易用了！

我倒是觉得现在的 GNOME shell 已经很好用了。

用过还不错

![](/data/attachment/album/201610/23/232518rlx62dfdlw9fjj9d.jpg)

[Chapeau](http://chapeaulinux.org/) 是专注于初学者的[一个基于 Fedora 的 Linux 发行版](https://itsfoss.com/best-fedora-linux-distributions/)。 Chapeau Linux 最近发布了新的 24 版本。

正如名字所暗示的，Chapeau 24 基于 Fedora 24。所以，你可以在 Chapeau 24 中发现大多数甚至全部的[Fedora 24 特性](https://itsfoss.com/fedora-24-released/)。

我在这儿增加一个细节。你可能已经知道 [Fedora 是一种帽子](https://en.wikipedia.org/wiki/Fedora)。我认为因为 [Fedora](https://getfedora.org/) 是来自[红帽](https://www.redhat.com/en)的一个社区项目，所以他们命名它为另一种帽子。有趣的是，[Chapeau 也是一种帽子](https://en.wikipedia.org/wiki/Chapeau)，一种法国帽子。现在，这些名字变得有意义了，不是吗？如果你对这样的细节性事实感兴趣，可以去了解一下其它 [Linux 发行版代号命名习惯](/article-7893-1.html)的背后的逻辑。

### CHAPEAU 24 特性

Chapeau 24 的特性几乎和 Fedora 24 提供的特性一样。它仍然运行在 GNOME 3.20 上，这是可以理解的，因为[GNOME 3.22](https://itsfoss.com/gnome-3-22-new-features/) 最近才刚发布。Chapeau 24 发行版一些主要的新亮点是：

* [Gnome](http://www.gnome.org/) 3.20 桌面环境
* LibreOffice 5
* [PlayOnLinux](http://www.playonlinux.com/) 和 [Wine](https://itsfoss.com/use-windows-applications-linux/)
* [Steam](https://itsfoss.com/install-steam-ubuntu-linux/)
* [VLC](http://www.videolan.org/)
* [Mozilla 火狐浏览器](https://www.mozilla.org/en-US/firefox/desktop)，带有 [Adobe Flash](http://www.adobe.com/products/flashplayer.html)
* [硬件帮助工具（hht）](http://chapeaulinux.org/hardware-helper-tool)（在 [Chapeau 23](https://itsfoss.com/chapeau-23-armstrong-released/) 中引入，这个工具能够帮助你找到硬件的驱动程序）
* 预配置了 [RPMFusion](http://rpmfusion.org/) 软件源
* 媒体解码和 DVD 回放支持
* Gnome Boxes
* KVM 虚拟化
* Dropbox 集成
* UI 改善
* 博通（Broadcom）无线芯片硬件
* 针对佳能打印机的 CUPS 后端
* Linux 4.7 内核

![](/data/attachment/album/201610/23/232715jw31r0hvfbs21yu3.jpg)![](/data/attachment/album/201610/23/232715lsj1gogsgolzpkme.jpg)

### 应该使用 CHAPEAU 24 吗？

这是一个很难回答的问题。看，在 Linux 的世界里，我们有超过 300 种活跃的 Linux 发行版。这些系统大量是针对桌面用户的。

这取决于个人更偏爱什么样的系统。你可以完整的安装 Fedora 24 和它所伴有的各种工具，然后你不需要再到其他地方寻找这些工具。但是你可能也知道 Fedora 对专有硬件支持非常“吝啬”。

总之， Chapeau 是一个很好的 Linux 版本，使用它能够不像使用 Fedora 那么“头疼”。如果你喜欢 GNOME，那么 Chapeau Linux 会是你的菜。

你可以从 SourceForge 下载 Chapeau 24：

* [下载 Chapeau 24](https://sourceforge.net/projects/chapeau/files/releases/Chapeau_24_x86-64.iso/download)

你已经尝试使用 Chapeau 24 了吗？你的使用体验是什么样的？

---

via: <https://itsfoss.com/chapeau-linux-24-released/>

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

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


白宫开源聊天机器人代码

Summary: “具体地说，我们开源了一个 Drupal 模块，只需要一些简单的步骤和样板化代码就可以搞定，” 白宫首席数码执行官 Jason Goldman 在他的博客的文章中这样写到，“这可以让 Drupal 8 开发者迅速推出 Facebook Messenger 机器人。”

争先部署那种可以响应用户请求的机器人的潮流也步入到了奥巴马总统的家——美国白宫。白宫在 10 月 14 号宣布开源其机器人代码，目的是为了使增加更加开放的合作与交流。

![](/data/attachment/album/201610/24/164257yuiegx5xtgext5qg.jpg)

“具体地说，我们开源了一个 Drupal 模块，只需要一些简单的步骤和样板化代码就可以搞定，” 白宫首席数码执行官 Jason Goldman 在他的博客的[文章](https://www.whitehouse.gov/blog/2016/10/13/removing-barriers-constituent-conversations)中这样写到，“这可以让 Drupal 8 开发者迅速推出 Facebook Messenger 机器人。”

白宫早在 2009 年就率先用开源的 Drupal 内容管理系统（CMS）[部署](http://www.internetnews.com/skerner/2009/10/white-house-goes-open-source-w.html)了它自己的网站。从那时起白宫就已经成为了 Drupal 的积极贡献者，并以许多不同的方式做着贡献，包括将用在其网站上的代码以开源方式发布。在白宫过去发布的那些项目中有完整的 Drupal 主题，被称作“fourtyfour”，目前用于 WhiteHouse.gov 网站。

现在，白宫新发布 Facebook Messenger 机器人的完整代码可以从 [GitHub](https://github.com/WhiteHouse/fb_messenger_bot) 上获取，包括完整的安装指导和项目蓝图。在蓝图中最大的项目（列在 ‘Enhancements and hopes’ 一节下面）是切实使项目更加独立，通过重构代码使项目模块化，从而让它在 Drupal 内容管理系统（CMS）之外也可以使用。

---

via: <http://www.internetnews.com/blog/skerner/white-house-open-sources-bot-code.html>

作者：Sean Michael Kerner 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

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


趣谈形形色色的 Linux 发行版的代号

Summary:
你是否对你喜爱的 Linux 发行版的最新发布版本的代号感到好奇？

比如说今年发布的 Linux Mint 18 的代号是 Sarah，而 Ubuntu 16.10 则叫做 Yakkety Yak，这样的名字还有很多很多。

“这个数字是说法的”少了一个 “有”字。

都挺好的，Ubuntu的是比喻自由的非洲大草原吗？Debian的命名者一定超喜欢玩具总动员吧。好不好记应该看人，对代号越熟悉/感兴趣就越容易记，反之亦然。话说Android作为Google的私生子采用的命名方式跟Ubuntu意外的相似啊。<br />
总之比Windows的7,8,10什么的舒服多了，win9,win11？怎么听怎么别扭~

Fedora有代号吗？

21 之前有~

谢谢~果然还是有笔误啊~

感觉代号完全没必要，比如说 xx 包支持到 ubuntu Utopic，这时候我就要上网查一些这到底是那个版本，有没有可能在我的mint上安装

我觉得还是只用版本号就好了，记那些代号对我这个“爱国者”来说难度太大~

Gentoo表示：別說代號了，連版本號都沒有，反正沒有什麼亂用

Gentoo：你在说什么？

蛮有意思

同感

Linux Mint表示女性名字……额……有点怪怪的

![](/data/attachment/album/201610/24/103044ml5713m41y4ie18l.jpg)

你是否对你喜爱的 Linux 发行版的最新发布版本的代号感到好奇？

比如说今年发布的 [Linux Mint 18](/article-7529-1.html) 的代号是 Sarah，而 Ubuntu 16.10 则叫做 [Yakkety Yak](/article-7862-1.html "Ubuntu 16.10 Yakkety Yak 正式发布")，这样的名字还有很多很多。

代号这个问题真不是一个大事，毕竟这些代号不能代表不同的发行版功能之间的不同。然而，对于一个好奇的 Linux 用户来说，你或许想知道每个发行版本代号背后的逻辑。不管怎么说，代号都是每个版本不可分割的一部分，而开发团队也为此付出了不少的努力，对吧？

下面我将会告诉你这些最流行的 Linux 发行版的代号背后的故事，请安坐，有趣的部分即将来到 :)

### Ubuntu 的版本号和代号

![](/data/attachment/album/201610/24/103105ossyfliilbzkuigb.jpg)

作为最流行的 Linux 发行版之一，[Ubuntu](http://www.ubuntu.com/) 有着一个稳定的开发周期，每年 4 月份和 10 月份各发布一个主要版本。

其所发布的年份和月份构成了 Ubuntu 发布版本的版本号。它的版本号格式是 XX.YY，其中 XX 是年份后两位，YY 是月份。比如说 Ubuntu 16.04 就是 2016 年 4 月份发布的版本，而 Ubuntu 16.10 则是该年 10 月份发布的。之所以 Ubuntu 没有像其它软件一样有 1.0 版本，也只是因为其第一个版本是[发布于 2004 年](https://lists.ubuntu.com/archives/ubuntu-announce/2004-October/000003.html)而已。

这么久以来，在过去的 11 年之中， 除了一次例外之外，Ubuntu 的所有版本都是 4 月份和 10 月份发布的。这唯一的一次例外是 Ubuntu 在 2006 年 4 月份的版本延迟了两个月，并因此其版本号叫做 Ubuntu 6.06，而不是 6.04。

另外，顺便提一句，每两年的 4 月份，都会推出一个长期支持版本（LTS），其支持期长达五年，而非 LTS 版本的支持期通常只有半年。

现在让我们看看 Ubuntu 的代号，你也许注意到了每个 Ubuntu 版本的代号都是两个相同首字母的单词，比如说， Ubuntu 14.04 叫做 Trusty Tahr，就是以两个“T”字母开头的。

Ubuntu 的代号一直遵循两个单词的规则，第一个是一个形容词，第二个则是一种濒危物种的名称（后来也包含一些传说生物，比如<ruby> 独角兽 <rp>  （ </rp> <rt>  Unicorn </rt> <rp>  ） </rp></ruby>、<ruby> 狼人 <rp>  （ </rp> <rt>  Werewolf </rt> <rp>  ） </rp></ruby>）。在前面的例子中，Trusty 是一个表示“忠实的”的形容词，而 [Tahr](https://en.wikipedia.org/wiki/Tahr) （塔尔羊）则是一种濒危的小物种动物。

另外一个有趣的事情是，这些字母的顺序是按字母表排列的（除了最开始时的两个），所以我们看到，Ubuntu 14.04 是 Trusty Tahr， Ubuntu 14.10 是 Utopic Unicorn， Ubuntu 15.04 是 Vivid Vervet ，明年即将发布的 Ubuntu 17.04 则是 Zesty Zapus 等等。至于再之后的版本，字母“Z”之后该用哪个，目前还没有得到 Canonical 官方的消息，我猜测或许是将没有用过的 A 和 C 用上，或许是从头开始循环，抑或是其它的可能也未尝可知。

如下是当前的 Ubuntu 的版本号和代号：

| 版本号 | 代号 | 发布日期 | 支持期 | 内核版本 |
| --- | --- | --- | --- | --- |
| 桌面版 | 服务器版 |
| 4.10 | Warty Warthog | 2004-10-20 | 2006-04-30 | 2.6.8 |
| 5.04 | Hoary Hedgehog | 2005-04-08 | 2006-10-31 | 2.6.10 |
| 5.10 | Breezy Badger | 2005-10-13 | 2007-04-13 | 2.6.12 |
| **6.06 LTS** | Dapper Drake | 2006-06-01 | 2009-07-14 | 2011-06-01 | 2.6.15 |
| 6.10 | Edgy Eft | 2006-10-26 | 2008-04-25 | 2.6.17 |
| 7.04 | Feisty Fawn | 2007-04-19 | 2008-10-19 | 2.6.20 |
| 7.10 | Gutsy Gibbon | 2007-10-18 | 2009-04-18 | 2.6.22 |
| **8.04 LTS** | Hardy Heron | 2008-04-24 | 2011-05-12 | 2013-05-09 | 2.6.24 |
| 8.10 | Intrepid Ibex | 2008-10-30 | 2010-04-30 | 2.6.27 |
| 9.04 | Jaunty Jackalope | 2009-04-23 | 2010-10-23 | 2.6.28 |
| 9.10 | Karmic Koala | 2009-10-29 | 2011-04-30 | 2.6.31 |
| **10.04 LTS** | Lucid Lynx | 2010-04-29 | 2013-05-09 | 2015-04-30 | 2.6.32 |
| 10.10 | Maverick Meerkat | 2010-10-10 | 2012-04-10 | 2.6.35 |
| 11.04 | Natty Narwhal | 2011-04-28 | 2012-10-28 | 2.6.38 |
| 11.10 | Oneiric Ocelot | 2011-10-13 | 2013-05-09 | 3.0.0 |
| **12.04 LTS** | Precise Pangolin | 2012-04-26 | 2017-04-26 | 3.2.0 |
| 12.10 | Quantal Quetzal | 2012-10-18 | 2014-05-16 | 3.5.0 |
| 13.04 | Raring Ringtail | 2013-04-25 | 2014-01-27 | 3.8.0 |
| 13.10 | Saucy Salamander | 2013-10-17 | 2014-07-17 | 3.11.0 |
| **14.04 LTS** | Trusty Tahr | 2014-04-17 | 2019-04 | 3.13.0 |
| 14.10 | Utopic Unicorn | 2014-10-23 | 2015-07-23 | 3.16.0 |
| 15.04 | Vivid Vervet | 2015-04-23 | 2016-02-04 | 3.19 |
| 15.10 | Wily Werewolf | 2015-10-22 | 2016-07-28 | 4.2 |
| **16.04 LTS** | Xenial Xerus | 2016-04-21 | 2021-04 | 4.4 |
| 16.10 | Yakkety Yak | 2016-10-13 | 2017-07 | 4.8 |
| 17.04 | Zesty Zapus | TBA | TBA | TBA |

 （表格来自[维基百科](https://en.wikipedia.org/wiki/Ubuntu_version_history)）

哈，Ubuntu 每次发布新版本都能扩充我们的英语词汇，也会让我们了解一种世界上需要关注的的濒危动物。

### Linux Mint 的版本号和代号

![](/data/attachment/album/201610/24/120455cnhsoahcaalzkhrc.jpeg)

作为 Ubuntu 的远亲，Linux Mint 也是一个 Debian 族系的流行发行版。现在让我们深挖一下 Linux Mint 的版本号和代号。

Linux Mint 是基于 Ubuntu 的，通常在 Ubuntu 发布后几个月内，Linux Mint 就会发布它基于 Ubuntu 衍生的版本。

但是不像 Ubuntu，Linut Mint 的版本号并没有遵循年和月的规则，只是简单的递增。所以 Linux Mint 15 之后就是 Linux Mint 16，Linux Mint 17 等等。这是主要版本，还会有维护的小版本，比如 Linux Mint 17.1、Linux Mint 17.2 等等。

这就是 Linux Mint 的版本号，现在让我们看看代号。每个 Linux Mint 版本，无论是主要版本还是维护版本，都有一个代号，而且和 Ubuntu 一样，都是按字母顺序递增的。

更有意思的一点是 Linux Mint 的代号都是女性名，而且以字母“a”结尾，而这些名字都来自于[亚伯拉罕诸教](https://zh.wikipedia.org/wiki/%E4%BA%9E%E4%BC%AF%E6%8B%89%E7%BD%95%E8%AB%B8%E6%95%99)。比如说 Linux Mint 17 的代号是 Qiana（国内戏称“钱啊”，其实发言应该是“奎阿纳”）。

主要版本会递增代号的首字母顺序，而通常维护版本会使用相同的首字母，不过在 Linux Mint 17.x 发生了变化，没有继续使用 Linux Mint 17 的“Q”，而是使用了“R”：Linux Mint 17.1 是 Rebecca, 17.2 是 Rafaela，17.3 是 Rosa。

如下是当前的 Linux Mint 的版本号和代号：

| 版本 | 代号 | 分支 | 上游 | 默认桌面环境 | 发布日期 | LTS | 支持期 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1.0 | Ada | Main | Kubuntu 6.06 | KDE | 2006-08-27 |  | 未知 |
| 2.0 | Barbara | Main | Ubuntu 6.10 | GNOME | 2006-11-13 |  | 2008-04 |
| 2.1 | Bea | Main | Ubuntu 6.10 | GNOME | 2006-12-20 |  | 2008-04 |
| 2.2 | Bianca | Main | Ubuntu 6.10 | GNOME | 2007-02-20 |  | 2008-04 |
| Light | Ubuntu 6.10 | GNOME | 2007-03-29 |
| KDE CE | Kubuntu 6.10 | KDE | 2007-04-20 |
| 3.0 | Cassandra | Main | Bianca 2.2 | GNOME | 2007-05-30 |  | 2008-10 |
| Light | Bianca 2.2 | GNOME | 2007-06-15 |
| KDE CE | Bianca 2.2 | KDE | 2007-08-14 |
| MiniKDE CE | Bianca 2.2 | KDE | 2007-08-14 |
| Xfce CE | Cassandra 3.0 | Xfce | 2007-08-07 |
| 3.1 | Celena | Main | Bianca 2.2 | GNOME | 2007-09-24 |  | 2008-10 |
| Light | Bianca 2.2 | GNOME | 2007-10-01 |
| 4.0 | Daryna | Main | Celena 3.1 | GNOME | 2007-10-15 |  | 2009-04 |
| Light | Celena 3.1 | GNOME | 2007-10-15 |
| KDE CE | Cassandra 3.0 | KDE | 2008-03-03 |
| 5 | **Elyssa** | Main | Daryna 4.0 | GNOME | 2008-06-08 | 是 | 2011-04 |
| Light | Daryna 4.0 | GNOME | 2008-06-08 |
| x64 | Ubuntu 8.04 | GNOME | 2008-10-18 |
| KDE CE | Daryna 4.0 | KDE | 2008-09-15 |
| Xfce CE | Daryna 4.0 | Xfce | 2008-09-08 |
| Fluxbox CE | Ubuntu 8.04 | Fluxbox | 2008-10-21 |
| 6 | Felicia | Main | Ubuntu 8.10 | GNOME | 2008-12-15 | 否 | 2010-04 |
| Universal (Light) | Ubuntu 8.10 | GNOME | 2008-12-15 |
| x64 | Ubuntu 8.10 | GNOME | 2009-02-06 |
| KDE CE | Elyssa 5 | KDE | 2009-04-08 |
| Xfce CE | Xubuntu 8.10 | Xfce | 2009-02-24 |
| Fluxbox CE | Xubuntu 8.10 | Fluxbox | 2009-04-07 |
| 7 | Gloria | Main | Ubuntu 9.04 | GNOME | 2009-05-26 | 否 | 2010-10 |
| Universal (Light) | Ubuntu 9.04 | GNOME | 2009-05-26 |
| x64 | Ubuntu 9.04 | GNOME | 2009-06-24 |
| KDE CE | Kubuntu 9.04 | KDE | 2009-08-03 |
| Xfce CE | Xubuntu 9.04 | Xfce | 2009-08-13 |
| 8 | Helena | Main | Ubuntu 9.10 | GNOME | 2009-11-28 | 否 | 2011-04 |
| Universal (Light) | Ubuntu 9.10 | GNOME | 2009-11-28 |
| Gnome x64 | Ubuntu 9.10 | GNOME | 2009-12-14 |
| KDE | Kubuntu 9.10 | KDE | 2010-02-06 |
| KDE x64 | Kubuntu 9.10 | KDE | 2010-02-12 |
| Fluxbox | Helena Main | Fluxbox | 2010-02-12 |
| Xfce | Xubuntu 9.10 | Xfce | 2010-03-31 |
| LXDE | Helena Main | LXDE | 2010-03-31 |
| 9 | Isadora | Main | Ubuntu 10.04 | GNOME | 2010-05-18 | 否 | 2013-04 |
| Gnome x64 | Ubuntu 10.04 | GNOME | 2010-05-18 |
| LXDE | Lubuntu 10.04 | LXDE | 2010-07-18 |
| KDE | Kubuntu 10.04 | KDE | 2010-07-27 |
| KDE x64 | Kubuntu 10.04 | KDE | 2010-07-27 |
| Xfce | Xubuntu 10.04 | Xfce | 2010-08-24 |
| Fluxbox | Lubuntu 10.04 | Fluxbox | 2010-09-06 |
| 10 | Julia | Main | Ubuntu 10.10 | GNOME | 2010-11-12 | 否 | 2012-04 |
| Gnome x64 | Ubuntu 10.10 | GNOME | 2010-11-12 |
| KDE | Kubuntu 10.10 | KDE | 2011-02-23 |
| KDE x64 | Kubuntu 10.10 | KDE | 2011-02-23 |
| LXDE | Lubuntu 10.10 | LXDE | 2011-03-11 |
| 11 | Katya | Main | Ubuntu 11.04 | GNOME | 2011-05-26 | 否 | 2012-10 |
| Gnome x64 | Ubuntu 11.04 | GNOME | 2011-05-26 |
| LXDE | Lubuntu 11.04 | LXDE | 2011-08-16 |
| 12 | Lisa | Main | Ubuntu 11.10 | GNOME 3 with MGSE,MATE | 2011-11-26 | 否 | 2013-04 |
| KDE | Kubuntu 11.10 | KDE | 2012-02-02 |
| LXDE | Lubuntu 11.10 | LXDE | 2012-03-09 |
| 13 | **Maya** | Main | Ubuntu 12.04 | Cinnamon, MATE | 2012-05-22 | 是 | 2017-04 |
| Xfce | Xubuntu 12.04 | Xfce | 2012-07-21 |
| KDE | Kubuntu 12.04 | KDE | 2012-07-23 |
| 14 | Nadia | Main | Ubuntu 12.10 | Cinnamon, MATE | 2012-11-20 | 否 | 2014-05 |
| Xfce | Xubuntu 12.10 | Xfce | 2012-12-21 |
| KDE | Kubuntu 12.10 | KDE | 2012-12-23 |
| 15 | Olivia | Main | Ubuntu 13.04 | Cinnamon, MATE | 2013-05-29 | 否 | 2014-01 |
| Xfce | Xfce | 2013-07-12 |
| KDE | KDE | 2013-07-21 |
| 16 | Petra | Main | Ubuntu 13.10 | Cinnamon, MATE | 2013-11-30 | 否 | 2014-07 |
| KDE | KDE | 2013-12-22 |
| Xfce | Xfce | 2013-12-22 |
| 17 | **Qiana** | Main | Ubuntu 14.04 | Cinnamon, MATE | 2014-05-31 | 是 | 2019-04 |
| KDE | KDE | 2014-06-23 |
| Xfce | Xfce | 2014-06-15 |
| 17.1 | **Rebecca** | Main | Cinnamon, MATE | 2014-11-29 |
| KDE | KDE | 2015-01-08 |
| Xfce | Xfce | 2015-01-11 |
| 17.2 | **Rafaela** | Main | Cinnamon, MATE | 2015-06-30 |
| KDE | KDE | 2015-07-23 |
| Xfce | Xfce | 2015-07-23 |
| 17.3 | **Rosa** | Main | Cinnamon, MATE | 2015-12-04 |
| KDE | KDE | 2016-01-09 |
| Xfce | Xfce | 2016-01-09 |
| 18 | **Sarah** | Main | Ubuntu 16.04 | Cinnamon, MATE | 2016-06-30 | 是 | 2021 |

不过，Sarah 是上述列表中唯一不以“a”结尾的代号，可能是因为没有合适的名称。

### elementary OS 的版本号和代号

![](/data/attachment/album/201610/24/141639iz2tovvudcvmcovo.jpg)

因为我们谈过了 Ubuntu 和 Linux Mint，让我们继续看看 Ubuntu 家族的另外一位： [elementary OS](https://elementary.io/) ，它也是基于 Ubuntu 的一个以优美著称的 Linux 发行版。

elementary OS 的版本号都是 0.X 这样递增的，第一个稳定版本是 0.1，然后是 0.2，现在的稳定版本是 0.3——不知道什么时候可以变成 1.0。

>
> 开源软件界之前一直有个传统就是使用极其微小的版本，比如 0.1，0.01 这样的，直到作者或开发团队觉得已经非常成熟了，才有可能变成 1.0 这样的看起来正式一些的版本号。当然，也有的软件从未进化到 1.0 就消亡了。不过虽然是这种看起来像是测试版本的版本号，却往往并不代表其质量和功能不可靠。而现在也有一些软件开始飙版本号，比如 Chrome、Firefox 之类的，我觉得用不了几年，或许我们就会见到 xx 100 这样的软件了。
>
>
>

而 elementary OS 的代号则是采用神话中神的名字，通常这些来自于罗马神话或北欧神话中。比如现在已有的三个版本的代号是 Jupiter（罗马神话中的神王）、 Luna （月神，不是“撸哪” ）、 Freya（北欧神话中的爱与美之女神，不过 0.3 之前的代号名是 ISIS ，后因避讳而改名），以及现在的 0.4 Loki（北欧神话中的火与恶之神）。

### Debian 的版本号和代号

![](/data/attachment/album/201610/24/131931a0d0let2lf2215s5.jpg)

让我们回到 Ubuntu 、Linux Mint 和 elementary OS 的父系看看。[Debian](https://www.debian.org/) 是 Ubuntu 及其族系派生的来源，它的代号命名非常有意思。事实上，Debian 这个发行版本身的名字就来源于其创始人 Ian 及其女朋友 Debra 的名词合写，虽然 Ian 已经去世，但是其名字却会随着 Debian 而长存。

Debian 的版本号是递增的，这并没什么特殊的，不过有趣的是所有的 Debian 发行版本的代号都来自于《[玩具总动员](https://zh.wikipedia.org/wiki/%E7%8E%A9%E5%85%B7%E6%80%BB%E5%8A%A8%E5%91%98)》这个动画片中的角色名。这就是你为什么看到 Debian 的代号是 [Jessie](https://en.wikipedia.org/wiki/Jessie_(Toy_Story)) 和 [Woody](https://en.wikipedia.org/wiki/Sheriff_Woody) 这样的原因。

如下是当前的 Debian 的版本号和代号：

| 版本 | 代号 | 发布日期 | Linux 内核 | 安全支持期 | 长期支持期 |
| --- | --- | --- | --- | --- | --- |
| 1.1 | Buzz | 1996-06-17 | 2.0 | N/A | 无 |
| 1.2 | Rex | 1996-12-12 | N/A | N/A |
| 1.3 | Bo | 1997-06-05 | 2.0.33 | N/A |
| 2.0 | Hamm | 1998-07-24 | 2.0.34 | N/A |
| 2.1 | Slink | 1999-03-09 | 2.0.34, 2.0.35, 2.0.36, 2.0.38 | 2000-10-30 |
| 2.2 | Potato | 2000-08-14 | 2.0.38, 2.2.19 | 2003-06-30 |
| 3.0 | Woody | 2002-07-19 | 2.2.20, 2.4.6 | 2006-03-30 |
| 3.1 | Sarge | 6 June 2005 | 2.4.27, 2.6.8 | 2008-03-31 |
| 4.0 | Etch | 8 April 2007 | 2.6.18 | 2010-02-15 |
| 5.0 | Lenny | 14 February 2009 | 2.6.26 | 2012-02-06 |
| 6.0 | Squeeze | 6 February 2011 | 2.6.32 | 2014-07-19 | 2016-02-29 |
| 7 | Wheezy | 4 May 2013 | 3.2 | 2016-04-26 | 2018-05 |
| 8 | Jessie | 25–26 April 2015 | 3.16 | 2018-05 | 2020-04 |
| 9 | Stretch | TBA | 4.10 | TBA | TBA |
| 10 | Buster | TBA | TBA | TBA | TBA |
| 11 | Bullseye | TBA | TBA | TBA | TBA |

我觉得动画片《玩具总动员》里面还有很多角色，所以我们不用担心不够用了。

### openSUSE 的版本号和代号

![](/data/attachment/album/201610/24/134316j619xtj2p11w2w6s.jpg)

[openSUSE](https://www.opensuse.org/) 的第一个版本 10.2 发布于 2006 年。

SUSE 家族的 Linux 发行版的版本号相当的任性，包括发行版的名字也换来换去。最初，该发行版的名字叫做 S.u.S.E Linux，这个名字从 1994 年用到了 1998 年，后来改成了 SuSE Linux（把名字中的“.”去掉了），然后到了 2003 年的时候变成了 SUSE Linux Enterprise。在 2005 年的时候，Novell 公司宣布将 SUSE 专业版系列变为开源项目，由于当时 SUSE 的版本是 9.X，所以第一个 SUSE Linux 的版本是以 10.0 开始的。到 2006 年底的时候，再次决定改名为 openSUSE，第一个版本是 10.2。接下来将近十年倒是没再改名称，直到 2015 年 openSUSE 已经发展到 13.2 时，又又又改名成 openSUSE Leap，版本号嘛，好吧，就是这么任性，直接变成了 42.1（当然[这个数字是有说法的](/article-6533-1.html)）。

SUSE 家族最初发布的 Linux 发行版是没有代号的，后来可能是受到了其它 Linux 发行版的启发，从 openSUSE 11.2 开始有了代号。由于 openSUSE 以绿色为代表色，所以它的代号也都是各种绿色色调。

如下是当前的 openSUSE 的版本号和代号：

| 名字 | 版本 | 代号 | 发布日期 | 生命周期 | 内核版本 |
| --- | --- | --- | --- | --- | --- |
| 标准 | Evergreen/ Major |
| SUSE Linux | 10.0 | N/A | 2005-10-06 | 2007-11-30 | N/A | 2.6.13 |
| 10.1 | N/A | 2006-05-11 | 2008-05-31 | N/A | 2.6.16 |
| openSUSE | 10.2 | N/A | 2006-12-07 | 2008-11-30 | N/A | 2.6.18 |
| 10.3 | N/A | 2007-10-04 | 2009-10-31 | N/A | 2.6.22 |
| 11.0 | N/A | 2008-06-19 | 2010-06-26 | N/A | 2.6.25 |
| 11.1 | N/A | 2008-12-18 | 2011-01-14 | 2012-04-13 | 2.6.27 |
| 11.2 | Emerald | 2009-11-12 | 2011-05-12 | 2013-11 | 2.6.31 |
| 11.3 | Teal | 2010-07-15 | 2012-01-16 | N/A | 2.6.34 |
| 11.4 | Celadon | 2011-03-10 | 2012-11-05 | 2015-07 | 2.6.37 |
| 12.1 | Asparagus | 2011-11-16 | 2013-05-15 | N/A | 3.1.0 |
| 12.2 | Mantis | 2012-09-05 | 2014-01-15 | N/A | 3.4.6 |
| 12.3 | Dartmouth | 2013-03-13 | 2015-01-01 | N/A | 3.7.10 |
| 13.1 | Bottle | 2013-11-19 | 2016-01 | 2016-11 | 3.11.6 |
| 13.2 | Harlequin | 2014-11-04 | Q1 2017 | N/A | 3.16.6 |
| openSUSE Leap | 42.1 | Malachite | 2015-11-04 | Q2 2017 | N/A | 4.1 |
| 42.2 | N/A | 2016-11-16 | Q2 2018 | N/A | 4.4 |

可能你都从来没听说过这么多的绿色色调，或许你会担心 openSUSE 会把绿色都用完，不过我觉得不用担心，毕竟连灰色都有 15 种之多，何况绿色呢？

### 你怎么看？

你喜欢哪个代号呢？你觉得是代号好记还是版本号好记呢？你认为需要代号吗？你又喜欢哪个发行版的代号命名方式呢？请在下面发表您的留言吧。


为何 Linux 之父 Linus Torvalds 在 ARM 会议上说他喜欢 x86

脱袜子真傲娇 233

言之有理！

我也喜欢x86，你看arm成什么卵样了

看看

所谓的企业级产品其实很扯淡，大概都是那种让你上了贼船就无法停下来的感觉，其实还是另一种形式的商业陷阱。还是觉得LINUS说的那句话有道理，大概意思就是一定要选择一个上下游都通用的平台和环境。这样才能愉快的玩耍

>
> **Torvalds 因为 x86 的基础架构和生态系统而对其宠爱有加**
>
>
>

![](/data/attachment/album/201610/24/215638cni4rh7onn27o4sn.jpg)

*Linus Torvalds 于 1999 年 8 月 10 日在加州圣何塞举行的 LinuxWorld 节目中给挤满礼堂的 Linux 发烧友们作演讲。*

——出自：James Niccolai

Linux 领袖 Linus Torvalds 是一个直率的人——他总是心口如一。比方说最近在 Linux 内核 4.8 的[事故](http://www.theregister.co.uk/2016/10/05/linus_torvalds_admits_buggy_crap_made_it_into_linux_48/)中，他没有文过饰非，而是承认了自己的过失。

不过他在上周的 Linaro Connect 会议上倒是[让人瞠目结舌](https://www.youtube.com/watch?v=fuAebQvFnRI)。当他被问到最喜欢的芯片架构的时候，他不假思索地说 x86，而不是 ARM。

或许是 x86 电脑悠久的历史让他得出这个答案。x86 没有多少碎片化的软件和硬件，它几乎仅仅是用来工作的。

Torvalds 说，人们总是痴迷于指令集和 CPU 核心，但事实是围绕架构的生态系统更为重要。

“重要的是围绕指令集的所有基础设施，而 x86 拥有大量的不同级别的基础设施”，Torvalds 说。“它在走一条与众不同的路。”

许多应用都是在英特尔或者 AMD 的 x86 机器上开发的。兼容性对于 x86 芯片和电脑来说是重要的，x86 平台有统一的硬件、开发模式以及其它的基础设施。

而 ARM 则迥然不同。从硬件供应商的角度来看，它引领着一个碎片化的市场，Torvalds 说。

“x86 的生态系统一向都秉承着兼容为先的理念，而 ARM 则不以为然，”Torvalds 在与 ARM 开发者进行的一场炉边闲谈时如是说。

ARM 主导了移动设备的市场，有大量的设备都是使用基于 Linux 内核的安卓操作系统的。但是 ARM 的生态系统太过于碎片化了，这导致了很多支持和设备的问题。

问题之一：由于硬件的配置不同，在所有移动设备上部署同一个版本的 Android 是不可能的。硬件制造商会调整 Android 系统以兼容他们设备的芯片组。不像 Windows 更新到 PC，一个 Android 更新无法推送到所有的移动设备。

英特尔尝试过将 x86 芯片放在智能手机上，但是现在已经放弃了。英特尔的其中一个目标就是推送可以在所有 x86 手机上下载并安装成功的[安卓更新](http://www.infoworld.com/article/2908072/android/google-and-intel-vow-to-speed-up-delivery-of-android-updates-to-devices.html)。

还有 ARM 服务器软件的开发问题。每个芯片组的架构、网络和 I/O 特性不同，必须编写软件才能利用这些特性。这大大减慢了服务器中采用 ARM 的速度。x86 不存在适配的问题，它将继续主导服务器市场。

“我对于 ARM 作为一个硬件平台而不是一个指令集感到非常失望，虽然我也有我的问题，”Torvalds 说。“作为一个硬件平台，它始终不太好对付。”

Torvalds 小时候在一台装配有 8 位的 6502 处理器的微机上编程，他很喜欢这种架构，因为它的指令是流式的，当时还没有其它硬件可以与之媲美。这种架构为芯片提供了更高的性能。

“我那时想升级的是一台 Acorn Archimedes，呃，ARM 就是因该公司而命名的，“Torvalds说，“那曾经是我梦寐以求的机器。”

[Archimedes](http://www.pcworld.com/article/3097427/hardware/how-arm-set-itself-up-for-a-32-billion-acquisition.html) 是第一台基于 Acorn 电脑公司的 ARM RISC 芯片的个人电脑。ARM 作为 Acorn 的一个分支而成立。（LCTT 译注：ARM 的缩写来自于 Acorn RISC Machine。——引自[维基百科](https://en.wikipedia.org/wiki/Acorn_Archimedes)。）

Torvalds 喜欢 Archimedes，因为它搭载了像 6502 一样的流式指令和 RAM 芯片以获得高性能。不尽人意的是，他找不到那台电脑。

他尝试过一台“古怪的英式电脑”，[Sinclair QL](http://oldcomputers.net/ql.html)，这是一台比 Acorn Archimedes 还要失败的机器，Torvalds 说。

“那时的芬兰不是宇宙的中心，”Torvalds 说。“在那之后我吸取教训了——再也没有去买没有基础设施（生态）的机器。”

---

via: <http://www.pcworld.com/article/3129300/linux/why-linux-pioneer-linus-torvalds-prefers-x86-over-arm.html>

作者：[Agam Shah](http://www.pcworld.com/author/Agam-Shah/) 译者：[OneNewLife](https://github.com/OneNewLife) 校对：[wxy](https://github.com/wxy)

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


8 个构建容器应用的最佳实践

![](/data/attachment/album/201610/25/092800e8u2dct6c9i6v9mw.jpg)

容器是未来在共有云和私有云进行应用开发的主要趋势，但是容器到底是什么，为什么它们成为了一种广受欢迎的部署机制，而且你需要怎样来修改你的应用来为容器化的环境优化它？

### 什么是容器？

容器技术的历史始于 2000 年的 SELinux 和 2005 年的 Solaris zones。今天，容器是由包括 SELinux、Linux 命名空间和控制组（cgroup）等几项内核特性构成，提供了用户进程、网络空间和文件系统空间的隔离。

### 为什么它们如此流行？

最近容器技术大规模的应用在很大程度上是由于旨在使容器更加易于使用的标准的发展，例如 Docker 镜像格式和分布模型，这个标准使用<ruby> 不可变镜像 <rp>  （ </rp> <rt>  immutable image </rt> <rp>  ） </rp></ruby>，这正是容器运行时环境的起点，不可变镜像可以保证开发团队发布的镜像就是经过测试的，和部署到生产环境中的镜像是同样的镜像。

容器所提供的轻量级隔离为一个应用组件提供了一个更好的抽象。在容器中运行的组件将不会干扰其它可能直接运行在虚拟机上的应用。它们可以避免对系统资源的争夺，而且除非它们共享一个持久卷，否则不会阻止对同一个文件的写请求。容器使得日志和指标采集的实践得以标准化，而且它们可以在物理机和虚拟机上支持更大的用户密度，所有的这些优点将导致更低的部署成本。

### 我们应该如何构建一个基于容器的应用呢？

将应用改为运行在容器中并不是什么很高的要求。主要的 Linux 发行版都有提供了基础镜像，任何可以在虚拟机上运行的程序都可以在上面运行。但是容器化应用的趋势是遵循如下最佳实践：

#### 1. 实例是一次性的

你的应用的任何实例都不需要小心地保持运行。如果你的一个运行了许多容器的系统崩溃了，你还能够转移到其它可用的系统去创建新的容器。

#### 2. 重试而不是崩溃

当你的应用的一个服务依赖于另一个服务的时候，在另一个服务不可用的时候它应该不会崩溃。例如，你的 API 服务正在启动而且监测到数据库不能连接。你应该设计它使得其不断重试连接，而不是运行失败和拒绝启动。当数据库连接断开的时候 API 可以返回 503 状态码，告诉客户端服务现在不可用。应用应该已经遵守了这个实践，但是如果你正在一个一次性实例的容器环境中工作，那么对这个实践的需要会更加明显。

#### 3. 持久性数据是特殊的

容器是基于共享镜像启动，它使用了写时复制（COW）文件系统。如果容器的进程选择写入文件，那么这些写的内容只有在直到容器存在时才存在。当容器被删除的时候，写时复制文件系统中的那一层会被删除。提供给容器一个挂载的文件系统目录，使之在容器存活之外也能持久保存，这需要另外的配置，而且会额外消耗物理存储。明确的抽象定义了什么存储是持久的，催生出了实例是一次性的观点。拥有一个抽象层也使得容器编制引擎可以处理挂载和卸载持久卷的复杂请求，以便这些持久卷可以用于容器。

#### 4. 使用 stdout 而不是日志文件

现在你或许会思考，如果持久的数据是特殊的，那么我用日志文件来做什么事情？容器运行时环境和编制引擎项目所采用的方法是进程应该[写入 stdout/stderr](https://docs.docker.com/engine/reference/commandline/logs/)，而且具有归档和维护[容器日志](http://kubernetes.io/docs/getting-started-guides/logging/)的基础设施。

#### 5. 敏感信息（以及其它配置信息）也是特殊的

你绝不应该将敏感信息例如密码、密钥和证书硬编码到你的镜像中。通常在你的应用与开发服务、测试服务，或者生产服务相交互时，这些敏感信息通常都是不同的。大多数开发者并没有访问生产环境的敏感信息的权限，所以如果敏感信息被打包到镜像中，那么必须创建一个新的镜像层来覆盖这个开发服务的敏感信息。基于这一点来看，你再也不能使用与你们开发团队所创建的和质量测试所测试的相同的镜像了，而且也失去了不可修改的镜像的好处。相反的，这些值应该被存储在环境变量中文件中，它们会在容器启动时导入。

#### 6. 不要假设服务的协同定位

在一个编排好的容器环境中，你会希望让编排器将你的容器发送到任何最适合的节点。最适合意味着很多事情：它应该基于那个节点现在拥有最多的空间、容器所需的服务质量、容器是否需要持久卷，等等。这可能意味这你的前端、API 和数据库容器最终都会放在不同的节点。尽管给每个节点强制分配一个 API 容器是可以做到的（参考 Kubernetes 的 [DaemonSets](http://kubernetes.io/docs/admin/daemons/)），但这种方式应该留给执行监控节点自身这类任务的容器。

#### 7. 冗余/高可用计划

即使你没有那么多负载需要高可用性的配置，你也不应该以单路方式编写服务，否则会阻止它运行多份拷贝。这将会允许你运用滚动式部署，使得将负载从一个节点移动到另外一个节点非常容易，或者将服务从一个版本更新到下一个版本而不需要下线。

#### 8. 实现就绪检查和灵活性检查

应用在响应请求之前会有一定的启动时间是一件很正常的事情，例如，一个 API 服务器需要填充内存数据缓存。容器编排引擎需要一种方法来检测你的容器是否准备好服务用户请求。为一个新的容器提供就绪检查可以允许我们进行滚动式部署，使得旧容器可以继续运行直到不再需要它，这可以防止服务宕机。类似的，一个存活检查也是一种容器编排引擎持续检查容器是否在健康可用状态的方法。决定容器健康或者说“存活”应该由容器应用的创建者说了算。一个不再存活的容器将会被结束，而且一个新的容器会被创建来替代它。

### 想查找更多资料？

我将会出席十月份的格雷丝霍普计算机女性峰会（Grace Hopper Celebration of Women in Computing），你可以在这里来看一下关于我的访谈：[应用的容器化：是什么，为什么，和如何实现](https://www.eiseverywhere.com/ehome/index.php?eventid=153076&tabid=351462&cid=1350690&sessionid=11443135&sessionchoice=1&)。今年不去 GHC 吗？那你可以在 [OpenShift](https://www.openshift.org/) 和 [Kubernetes](http://kubernetes.io/) 的项目站点来了解关于容器、编排和应用的相关内容。

---

via: <https://opensource.com/life/16/9/8-best-practices-building-containerized-applications>

作者：[Jessica Forrester](https://opensource.com/users/jwforres) 译者：[LinuxBars](https://github.com/LinuxBars) 校对：[wxy](https://github.com/wxy)

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


Mozilla 做出不再信任沃通 CA 的决定，沃通回应打一折

Summary: 从 Firefox 51 （预计将在 2017 年 1 月 23 日发布）起移除之前预置的 4 个沃通根证书

这条新闻的传播路径：

solidot--cnbeta---一些其他媒体---***---linuxcn。

自从360私有化，动作挺大啊，先是干掉了云盘，然后是整死了沃通，有把刷子。不过mozilla这么折腾没有用，360有倒填时间大法（举例：当前时间2016-10-26，但是他写成10月21日以前签的整数，mozilla就不会取消信任）。对付流氓，你还真没招儿。

错了，它可以倒填，但是它不能在 CT 上作假。

全部手动设置为不信任！

ca沃通是个流氓，大家都知道的

![](/data/attachment/album/201610/25/212540qyrfcajxc30pvlza.jpg)

Mozilla 对沃通（WoSign）的处罚终于落定。

前一段时间，Mozilla 就沃通 CA 违规的问题，于 8 月 24 日发起了针对沃通 CA 的调查，并发布了一个[问题列表](https://wiki.mozilla.org/CA:WoSign_Issues)。之后在 10 月 5 日， Mozilla、奇虎 360 、StartCom 和沃通在伦敦举行了闭门商谈，讨论下一步行动。

10 月 20 日，Mozilla 公布了对沃通 CA 的[最终处理意见](https://bugzilla.mozilla.org/show_bug.cgi?id=1311824)：

* 它不再信任在 10 月 21 日之后签发的沃通 CA 证书
* 从 Firefox 51 （[预计](https://wiki.mozilla.org/RapidRelease/Calendar)将在 2017 年 1 月 23 日发布）起，移除之前预置的 4 个沃通根证书：
	1. CN=CA 沃通根证书, OU=null, O=WoSign CA Limited, C=CN
	2. CN=Certification Authority of WoSign, OU=null, O=WoSign CA Limited, C=CN
	3. CN=Certification Authority of WoSign G2, OU=null, O=WoSign CA Limited, C=CN
	4. CN=CA WoSign ECC Root, OU=null, O=WoSign CA Limited, C=CN

但是从这 4 个根证书签发的所有代码签名证书、客户端证书、签名平台（WoSignDoc）均不受任何影响。10 月 21 日（包括 21 日）之前签发的所有 SSL 证书也都不受任何影响，都能正常被 Mozilla 的火狐浏览器信任。

预计 Mozilla 的这一决定也有可能被其它主流浏览器所接纳。

此外，Mozilla 提出了六点操作要求：

1. 提供实施整改计划列表，确保将来不会违例 Mozilla 的 CA 证书策略和 CA/Browser 论坛的基准要求。
2. 实施整改，并更新其 CP/CPS 来完整描述其改进过程。CP/CPS 必须明确申明禁止倒填超过一天前的证书。
3. 对所做的整改，提供来自 Mozilla 所认可的 WebTrust 鉴证机构的面向公众的认证。该审计可能需要作为年度 WebTrust CA 审计的一部分。
4. 提供审计认证，对全部业务进行审计，确认合规 CA/Browser 论坛的基准要求。该审计可能需要作为年度 WebTrust CA 审计的一部分。
5. 提供审计认证，对 CA 的签发基础设施可以顺利完成执行完整的安全审计。
6. 所有签发的证书 100% 嵌入证书透明度（CT）信息，嵌入的 SCT 至少有一条来自谷歌，一条来自谷歌之外。

2017 年 6 月 1 日后，在满足 Mozilla 提出的上述 6 点操作要求后，沃通 CA 可以重新走正常申请 Mozilla 根认证流程，重新申请新的根证书预置。

沃通对此[表示遗憾](http://www.wosign.com/News/announcement_about_Mozilla_Action_20161024.htm)， 并宣布：

> 1. 将更新数字证书商店Buy网站，从10月22日起，所有从沃通4个根证书下签发的所有收费SSL证书全部**一折**销售；免费SSL证书继续停止开放；
> 2. 将增加一个产品选项，用户可以选购从新的沃通（WoSign）中级根证书下签发的支持所有浏览器（包括火狐浏览器）的SSL证书，在过渡期**八折**优惠。此中级根证书将由全球信任的其他CA根证书签发，支持所有浏览器和所有新老终端设备。此项产品升级计划一个月内完成并为广大用户提供证书服务；
> 3. 将积极按照Mozilla提出的6点要求进行操作，争取在2017年6月1日之后，尽快完成新根证书在各个浏览器系统的预置工作；
> 4. 已经并继续对所有系统进行全面的安全审计并加固升级改造，同时完善各种内控管理制度，组建国际标准研究团队和内审团队，确保所有系统100%符合国际标准，所有业务操作严格按照国际标准要求操作，加强员工严格按照标准操作的执行力度，违者将受到严厉惩处。
>

（题图来自：[deviantart.net](http://img13.deviantart.net/ee6d/i/2015/132/b/f/iris___broken_bridge_by_laitma-d8t2uxi.png)）


通过 AWS 的 Lambda 和 API Gateway 走向 Serverless

Summary: serverless 是一个概念，它允许你提供代码或可执行程序给某个服务，由服务来为你执行它们，而你无需自己管理服务器。这就是所谓的执行即服务（execution-as-a-service），它带来了很多机会，同时也遇到了它独有的挑战。

近来，在计算领域出现了很多关于 serverless 的讨论。serverless 是一个概念，它允许你提供代码或可执行程序给某个服务，由服务来为你执行它们，而你无需自己管理服务器。这就是所谓的<ruby> 执行即服务 <rp>  （ </rp> <rt>  execution-as-a-service </rt> <rp>  ） </rp></ruby>，它带来了很多机会，同时也遇到了它独有的挑战。

### 简短回忆下计算领域的发展

早期，出现了……好吧，这有点复杂。很早的时候，出现了机械计算机，后来又有了埃尼阿克 ENIAC（Electronic Numerical Integrator And Computer，很早的电子计算机)，但是都没有规模生产。直到大型机出现后，计算领域才快速发展。

![](/data/attachment/album/201610/26/110123oyk1iy212ld4iyuu.jpg)

* 上世纪 50 年代 - 大型机
* 上世纪 60 年代 - 微型机
* 1994 - 机架服务器
* 2001 - 刀片服务器
* 本世纪初 - 虚拟服务器
* 2006 - 服务器云化
* 2013 - 容器化
* 2014 - serverless（计算资源服务化）

>
> 这些日期是大概的发布或者流行日期，无需和我争论时间的准确性。
>
>
>

计算领域的演进趋势是执行的功能单元越来越小。每一次演进通常都意味着运维负担的减小和运维灵活性的增加。

### 发展前景

喔，Serverless！但是，serverless 能给我们带来什么好处? 我们将面临什么挑战呢?

**未执行代码时无需付费。**我认为，这是个巨大的卖点。当无人访问你的站点或用你的 API 时，你无需付钱。没有持续支出的基础设施成本，仅仅支付你需要的部分。换句话说，这履行了云计算的承诺：“仅仅支付你真正用的资源”。

**无需维护服务器，也无需考虑服务器安全。**服务器的维护和安全将由你的服务提供商来处理（当然，你也可以架设自己的 serverless 主机，只是这似乎是在向错误的方向前进）。由于你的执行时间也是受限的，安全补丁也被简化了，因为完全不需要重启。这些都应该由你的服务提供商无缝地处理。

**无限的可扩展性。**这是又一个大的好处。假设你又开发了一个 Pokemon Go, 与其频繁地把站点下线维护升级，不如用 serverless 来不断地扩展。当然，这也是个双刃剑，大量的账单也会随之而来。如果你的业务的利润强依赖于站点上线率的话，serverless 确实能帮上忙。

**强制的微服务架构。**这也有两面性，一方面，微服务似乎是一种好的构建灵活可扩展的、容错的架构的方式。另一方面，如果你的业务没有按照这种方式设计，你将很难在已有的架构中引入 serverless。

### 但是现在你被限制在**他们的**平台上

**受限的环境。**你只能用服务提供商提供的环境，你想在 Rust 中用 serverless？你可能不会太幸运。

**受限的预装包。**你只有提供商预装的包。但是你或许能够提供你自己的包。

**受限的执行时间。**你的 Function 只可以运行这么长时间。如果你必须处理 1TB 的文件，你可能需要有一个解决办法或者用其他方案。

**强制的微服务架构。**参考上面的描述。

**受限的监视和诊断能力。**例如，你的代码**在**干什么? 在 serverless 中，基本不可能在调试器中设置断点和跟踪流程。你仍然可以像往常一样记录日志并发出统计度量，但是这带来的帮助很有限，无法定位在 serverless 环境中发生的难点问题。

### 竞争领域

自从 2014 年出现 AWS Lambda 以后，serverless 的提供商已经增加了一些。下面是一些主流的服务提供商:

* AWS Lambda - 起步最早的
* OpenWhisk - 在 IBM 的 Bluemix 云上可用
* Google Cloud Functions
* Azure Functions

这些平台都有它们的相对优势和劣势（例如，Azure 支持 C#，或者紧密集成在其他提供商的平台上）。这里面最大的玩家是 AWS。

### 通过 AWS 的 Lambda 和 API Gateway 构建你的第一个 API

我们来试一试 serverless。我们将用 AWS Lambda 和 API Gateway 来构建一个能返回 [Jimmy](http://blog.ryankelly.us/2016/07/11/jimmy.html) 所说的“Guru Meditations”的 API。

所有代码在 [GitHub](https://github.com/f0rk/meditations) 上可以找到。

API文档：

```
POST /
{
    "status": "success",
    "meditation": "did u mention banana cognac shower"
}

```

### 怎样组织工程文件

文件结构树:

```
.
├── LICENSE
├── README.md
├── server
│   ├── __init__.py
│   ├── meditate.py
│   └── swagger.json
├── setup.py
├── tests
│   └── test_server
│       └── test_meditate.py
└── tools
    ├── deploy.py
    ├── serve.py
    ├── serve.sh
    ├── setup.sh
    └── zip.sh

```

AWS 中的信息（想了解这里究竟在做什么的详细信息，可查看源码 `tools/deploy.py`）。

* **API。**实际构建的对象。它在 AWS 中表示为一个单独的对象。
* **执行角色。**在 AWS 中，每个 Function 作为一个单独的角色执行。在这里就是 meditations。
* **角色策略。**每个 Function 作为一个角色执行，每个角色需要权限来干活。我们的 Lambda Function 不干太多活，故我们只添加一些日志记录权限。
* **Lambda Function。**运行我们的代码的地方。
* **Swagger。** Swagger 是 API 的规范。API Gateway 支持解析 swagger 的定义来为 API 配置大部分资源。
* **部署。**API Gateway 提供部署的概念。我们只需要为我们的 API 用一个就行（例如，所有的都用生产或者 yolo等)，但是得知道它们是存在的，并且对于真正的产品级服务，你可能想用开发和暂存环境。
* **监控。**在我们的业务崩溃的情况下（或者因为使用产生大量账单时），我们想以云告警查看方式为这些错误和费用添加一些监控。注意你应该修改 `tools/deploy.py` 来正确地设置你的 email。

### 代码

Lambda Function 将从一个硬编码列表中随机选择一个并返回 guru meditations，非常简单：

```
import logging
import random

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def handler(event, context):

    logger.info(u"received request with id '{}'".format(context.aws_request_id))

    meditations = [
    "off to a regex/",
    "the count of machines abides",
    "you wouldn't fax a bat",
    "HAZARDOUS CHEMICALS + RKELLY",
    "your solution requires a blood eagle",
    "testing is broken because I'm lazy",
    "did u mention banana cognac shower",
    ]

    meditation = random.choice(meditations)

    return {
        "status": "success",
        "meditation": meditation,
    }

```

### deploy.py 脚本

这个脚本相当长，我没法贴在这里。它基本只是遍历上述“AWS 中的信息”下的项目，确保每项都存在。

### 我们来部署这个脚本

只需运行 `./tools/deploy.py`。

基本完成了。不过似乎在权限申请上有些问题，由于 API Gateway 没有权限去执行你的 Function，所以你的 Lambda Function 将不能执行，报错应该是“Execution failed due to configuration error: Invalid permissions on Lambda function”。我不知道怎么用 botocore 添加权限。你可以通过 AWS console 来解决这个问题，找到你的 API, 进到 `/POST` 端点，进到“integration request”，点击“Lambda Function”旁边的编辑图标，修改它，然后保存。此时将弹出一个窗口提示“You are about to give API Gateway permission to invoke your Lambda function”， 点击“OK”。

当你完成后，记录下 `./tools/deploy.py` 打印出的 URL，像下面这样调用它，然后查看你的新 API 的行为：

```
$ curl -X POST https://a1b2c3d4.execute-api.us-east-1.amazonaws.com/prod/
{"status": "success", "meditation": "the count of machines abides"}

```

### 本地运行

不幸的是，AWS Lambda 没有好的方法能在本地运行你的代码。在这个例子里，我们将用一个简单的 flask 服务器来在本地托管合适的端点，并调用 handler 函数。

```
from __future__ import absolute_import

from flask import Flask, jsonify

from server.meditate import handler

app = Flask(__name__)

@app.route("/", methods=["POST"])
def index():

    class FakeContext(object):
        aws_request_id = "XXX"

    return jsonify(**handler(None, FakeContext()))

app.run(host="0.0.0.0")

```

你可以在仓库中用 `./tools/serve.sh` 运行它，像这样调用：

```
$ curl -X POST http://localhost:5000/
{
    "meditation": "your solution requires a blood eagle",
    "status": "success"
}

```

### 测试

你总是应该测试你的代码。我们的测试方法是导入并运行我们的 handler 函数。这是最基本的 python 测试方法：

```
from __future__ import absolute_import

import unittest

from server.meditate import handler

class SubmitTestCase(unittest.TestCase):

    def test_submit(self):

        class FakeContext(object):

            aws_request_id = "XXX"

        response = handler(None, FakeContext())

        self.assertEquals(response["status"], "success")
        self.assertTrue("meditation" in response)

```

你可以在仓库里通过 nose2 运行这个测试代码。

### 更多前景

* **和 AWS 服务的无缝集成。**通过 boto，你可以完美地轻易连接到任何其他的 AWS 服务。你可以轻易地让你的执行角色用 IAM 访问这些服务。你可以从 S3 取文件或放文件到 S3，连接到 Dynamo DB，调用其他 Lambda Function，等等。
* **访问数据库。**你也可以轻易地访问远程数据库。在你的 Lambda handler 模块的最上面连接数据库，并在handler 函数中执行查询。你很可能必须从它的安装位置上传相关的包内容才能使它正常工作。可能你也需要静态编译某些库。
* **调用其他 webservices。**API Gateway 也是一种把 webservices 的输出从一个格式转换成另一个格式的方法。你可以充分利用这个特点通过不同的 webservices 来代理调用，或者当业务变更时提供后向兼容能力。

---

via: <http://blog.ryankelly.us/2016/08/07/going-serverless-with-aws-lambda-and-api-gateway.html>

作者：[Ryan Kelly](https://github.com/f0rk/blog.ryankelly.us/) 译者：[messon007](https://github.com/messon007) 校对：[wxy](https://github.com/wxy)

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


开发者的实用 Vim 插件（一）

括号补全插件很好用！

delimitMate跟auto-pairs比较有什么优点，谁给普及一下？

pathgone.vim应该不推荐了吧？选择vundle吧？

我用vimplug

不错,正在捣鼓vim

作为 Vi 的升级版，[Vim](http://www.vim.org/) 毫无争议是 Linux 中最受欢迎的命令行编辑器之一。除了是一个多功能编辑器外，世界各地的软件开发者将 Vim 当做 IDE（<ruby> 集成开发环境 <rp>  （ </rp> <rt>  Integrated Development Environment </rt> <rp>  ） </rp></ruby>）来使用。

![](/data/attachment/album/201610/26/115338kwz9oi5srhwhwqqo.jpg)

事实上，因为 Vim 可以通过插件来扩展其自身功能才使得它如此功能强大。不用说，肯定有那么几个 Vim 插件是旨在提高用户的编程体验的。

特别是对于刚刚使用 Vim 或者使用 Vim 做开发的的软件开发者来说，我们将在本教程中讨论一些非常有用的 Vim 插件，具体请看例示。

请注意：本教程中列举的所有例示、命令和说明都是在 Ubuntu 16.04 环境下进行测试的，并且，我们使用的 Vim 版本是 7.4。

### 插件安装设置

这是为新用户准备的，假设他们不知道如何安装 Vim 插件。所以，首先，就是给出一些完成安装设置的步骤。

* 在你的家目录下创建 `.vim` 目录，并在其中创建子目录 `autoload` 和 `bundle`。
* 然后，在 `autoload` 放置 [pathogen.vim](http://www.vim.org/scripts/script.php?script_id=2332) 文件，这个文件可以从[此处](https://raw.githubusercontent.com/tpope/vim-pathogen/master/autoload/pathogen.vim) 下载。
* 最后，在你的家目录创建 `.vimrc` 文件，并添加以下内容。

```
call pathogen#infect()

```

![Vim plugin installation](/data/attachment/album/201610/26/115348w626oy43h640z3cv.png)

至此，你已完成了 Vim 插件安装的准备工作。

注意：我们已经讨论了使用 Pathogen 管理 Vim 插件。当然还有其他的插件管理工具——欲了解，请访问[此处](http://vi.stackexchange.com/questions/388/what-is-the-difference-between-the-vim-plugin-managers)。

现在已经全部设置完毕，就让我们来讨论两个好用的 Vim 插件吧。

### Vim 标签侧边栏（Tagbar）插件

首先就是标签侧边栏（Tagbar）插件。该插件能够让你浏览源文件包含的标签，从而提供该源文件的结构简览。[其官网的插件说明](http://majutsushi.github.io/tagbar/)是这样说的：“它通过创建侧边栏，然后以一定顺序展示从当前文件以 ctags 提取的标签来完成这一功能。这意味着，比如，C++ 中的方法将展示在其自身所定义在的类里边。”

听起来很酷，不是吗？让我们来看看该怎么安装它。

标签侧边栏（Tagbar）的安装过程是相当容易的——你只需要运行下列命令：

```
cd ~/.vim/bundle/

git clone git://github.com/majutsushi/tagbar

```

安装完之后就可以使用了，你可以在 Vim 中打开一个 .cpp 文件来测试它：进入[命令模式](http://www.tldp.org/LDP/intro-linux/html/sect_06_02.html)，然后运行 `:TagbarOpen` 命令。以下是运行 `:TagbarOpen` 命令之后出现侧边栏（右侧） 的效果图。

[![Vim tagbar plugin](/data/attachment/album/201610/26/115349xkys5v2qmsmccqrx.png)](https://www.howtoforge.com/images/vim-editor-plugins-for-software-developers/big/vimplugins-tagbar-example.png)

使用 `:TagbarClose` 可以关闭侧边栏。值得一提的是，可以使用 `:TagbarOpen fj` 命令打开侧边栏来打开它的跳转（shift control）功能。也就是说，你可以很方便的浏览当前文件包含的标签——在对应的标签上按下 Enter 键，然后在左侧的源代码窗口跳转到对应的位置。

![](/data/attachment/album/201610/26/115351yr7x0uh1x10dlbab.png)

假如你想要反复地开关侧边栏，你可以使用 `:TagbarToggle` 命令，而不用交替的使用 `:TagbarOpen` 和 `:TagbarClose` 命令。

如果你觉得输入这些命令很费时间，你可以为 `:TagbarToggle` 命令创建快捷键。比如，添加以下内容到 `.vimrc` 文件中：

```
nmap <F8> :TagbarToggle<CR>

```

这样，你就可以用 F8 来切换标签侧边栏（Tagbar）了。

更进一步，有时候你可能会注意到某个标签前边有一个 `+`、`-` 或者 `#` 符号。比如，以下截图（取自该插件的官网）展示了一些前边有 `+` 号的标签。

![Toggle Tagbar window](/data/attachment/album/201610/26/115353t8x54siys8a84wyq.png)

这些符号基本是用来表明一个特定标签的可见性信息。特别是 `+` 表示该类是 public 的，而 `-` 表示一个 private 类。`#` 则是表示一个 protected 类。

以下是使用标签侧边栏（Tagbar）的一些注意事项：

* 该插件的官网早就有说明：“标签侧边栏（Tagbar）并非是管理标签（tags）文件而设计，它只是在内存中动态创建所需的标签，而非创建任何文件。标签（tags）文件的管理有其他插件提供支持。”
* 低于 7.0.167 版本的 Vim 和标签侧边栏（Tagbar）插件存在着一个兼容性问题。根据官网：“如果你受到此问题的影响，请使用代替版：[下载 zip 压缩包](https://github.com/majutsushi/tagbar/zipball/70fix)。这对应到 2.2 版本，但由于大量的依赖变更，它可能不会再升级。”
* 如果你在加载该插件时遇到这样的错误：未找到 ctags！（Tagbar: Exuberant ctags not found!）。你可以从 [此处](http://ctags.sourceforge.net/)下载并安装 ctags 来修复错误。
* 获取更多信息请访问 [这里](https://github.com/majutsushi/tagbar)。

### Vim 界定符自动补齐（delimitMate）插件

下一个要介绍的插件就是界定符自动补齐（delimitMate）。该插件在 Vim 插入模式下提供引号、圆括号和方括号等界定符自动补齐功能。

[该插件官网](https://github.com/Raimondi/delimitMate)说：“它同时也提供一些相关的特性让你在输入模式下变得更加便捷，比如语法纠错（在注释区或者其他的可配置区不会自动插入结束界定符）、回车和空格填充（默认关闭）等。”

安装步骤与之前介绍的相似：

```
cd ~/.vim/bundle/

git clone git://github.com/Raimondi/delimitMate.git

```

一旦你成功安装这个插件（即上述命令执行成功），你就不需要进行任何配置了——当 Vim 启动时会自动加载这个插件。

至此，在你使用 Vim 的任何时候，只要你输入一个双引号、单引号、单号、圆括号、方括号，它们都会自动补齐。

你可以自己配置界定符自动补齐（delimitMate）。比如，你可以添加需要自动补齐的符号列表，阻止自动加载该插件，对指定类型文件关闭该插件等。想了解如何配置这些（或者其他更多的配置），请阅读该插件的详细文档——运行 `:help delimitMate` 即可。

上述命令会将你的 Vim 窗口水平分割成两个，上边一个包含我们所说的文档。

![Vim deliMate Plugin](/data/attachment/album/201610/26/115354ctzt2onint75jti3.png)

### 结论

本文之中提到的两个插件，Tagbar 需要花费较多时间来适应——你应该会同样这个说法。但只要正确设置好它（这意味着你像是有了快捷键一样方便），就容易使用了。至于 delimitMate，不需要任何要求就可以上手。

本教程就是向你展示 Vim 如何高效能的想法。除了本文中提及的，仍然还有许多开发者可用的插件，我们将在下一个部分进行讨论。假如你正在使用一个关于开发的 Vim 插件，并希望广为人知，请在下方留下评论。

我们将在本教程的第二部分讲到 [语法高亮插件：Syntastic](https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-2-syntastic/)。

---

via: <https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers/>

作者：[Ansh](https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers/) 译者：[GHLandy](https://github.com/GHLandy) 校对：[wxy](https://github.com/wxy)

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


NitroShare：内网多操作系统间快捷文件共享工具

Summary: 网络的最重要用途之一就是实现文件共享的目的。现在，虽然有多种方式可以让在同一网络中的 Linux 和 Windows 以及 MacOS X 用户之间共享文件，但这篇文章，我们只打算介绍 NitroShare。这是一款跨平台、开源以及易于使用的应用软件，可以在本地网络（内网）中共享文件。

看看如何

能代替smb？

网站上不去啊~

android不支持啊？

网络的最重要用途之一就是实现文件共享的目的。现在，虽然有多种方式可以让在同一网络中的 Linux 和 Windows 以及 MacOS X 用户之间共享文件，但这篇文章，我们只打算介绍 NitroShare。这是一款跨平台、[开源](https://github.com/nitroshare/nitroshare-desktop)以及易于使用的应用软件，可以在本地网络（内网）中共享文件。

![](/data/attachment/album/201610/27/101514k2m7yve79jhmz997.jpg)

NitroShare 大大简化了本地网络的文件共享操作，一旦安装上，它就会与操作系统无缝集成。Ubuntu 系统中，从应用程序显示面板中可以简单的打开，在 Windows 系统中，在系统托盘中可以找到它。

此外，在装有 NitroShare 的机器上，它会自动检测在同一网段的其它安装了它的设备，用户只需选择好需要传输到的设备，就可以直接向其传输文件。

NitroShare 的特性如下：

* 跨平台，即可以运行于 Linux， Windows 和 MacOS X 系统
* 设置容易，无需配置
* 易于使用
* 支持在本地网络上自动发现运行着 Nitroshare 设备的能力
* 安全性上支持可选的 TLS (<ruby> 传输层安全协议 <rp>  （ </rp> <rt>  Transport Layer Security </rt> <rp>  ） </rp></ruby>) 编码传输方式
* 支持网络高速传输功能
* 支持文件和目录（Windows 上的文件夹）传输
* 支持对发送文件、连接设备等这些的桌面通知功能

最新版本的 NitroShare 是使用 Qt5 开发的，它做了一些重大的改进，例如：

* 用户界面焕然一新
* 简化设备发现过程
* 移除不同版本传输文件大小的限制
* 为了使用方便，已经去除配置向导

### Linux 系统中安装 Nitroshare

NitroShare 可运行于各种各样的现代 Linux 发行版和桌面环境。

#### Debian Sid 和 Ubuntu 16.04+

NitroShare 已经包含在 Debian 和 Ubuntu 的软件源仓库中，所以可以很容易的就安装上，使用如下命令：

```
$ sudo apt-get install nitroshare

```

但安装的版本可能已经过期了。要安装最新的版本的话，可按照如下的命令添加最新的 PPA。

```
$ sudo apt-add-repository ppa:george-edison55/nitroshare
$ sudo apt-get update
$ sudo apt-get install nitroshare

```

#### Fedora 24-23

最近，NitroShare 已经包含在 Fedora 源仓库中了，可以按如下命令安装：

```
$ sudo dnf install nitroshare

```

#### Arch Linux

在 Arch Linux 系统中，NitroShare 包在 AUR 上已经可用了，可以用如下命令来构建/安装：

```
# wget https://aur.archlinux.org/cgit/aur.git/snapshot/nitroshare.tar.gz
# tar xf nitroshare.tar.gz
# cd nitroshare
# makepkg -sri

```

### Linux 中使用 NitroShare

注意：如我前面所述，在本地网络中，您想要共享文件的其它机器设备都需要安装上 NitroShare 并运行起来。

在成功安装后，在系统 dash 面板里或系统菜单里搜索 NitroShare，然后启动。NitroShare 非常容易使用，你可从该应用或托盘图标上找到“发送文件”、“发送目录”、“查看传输”等选项。

![](/data/attachment/album/201610/27/101554l6ul0whvtu5aafih.png)

选择文件后，点击“打开”继续选择目标设备，如下图所示。如果在本地网络有设备正的运行 NitroShare 的话，选择相应的设备然后点击“确定”。

![](/data/attachment/album/201610/27/101558nael4o05ww01udb1.png)

![](/data/attachment/album/201610/27/101600ouu4e5ri4c0gzm44.png)

如果需要，在 NitroShare 的配置 -- 通用标签页里，您可以增加设备的名字，设置默认文件下载位置，在高级设置里您能设置端口、缓存、超时时间等等。

主页：<https://nitroshare.net/index.html>

这就是所要介绍的，如果您有关于 Nitroshare 的任何问题，可以在下面的评论区给我们分享。您也可以给我们提供一些建议，告诉一些可能我们不知道的很不错的跨平台文件共享应用程序。

---

via: <http://www.tecmint.com/nitroshare-share-files-between-linux-ubuntu-windows/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[runningwater](https://github.com/runningwater) 校对：[wxy](https://github.com/wxy)

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


解决 Linux 内核代码审查人员短缺问题

Summary: 操作系统安全是现在最重要的事情，而 Linux 则是一个主要被讨论的部分。首先要解决的问题之一就是：我们如何确定提交到上游的补丁已经进行了代码审核？

操作系统安全是[现在最重要的事情](http://www.infoworld.com/article/3124432/linux/is-the-linux-kernel-a-security-problem.html)，而 Linux 则是一个主要被讨论的部分。首先要解决的问题之一就是：我们如何确定提交到上游的补丁已经进行了代码审核？

Wolfram Sang 从 2008 年开始成为一名 Linux 内核开发者，他经常在各地召开的 Linux 峰会上发表讲话，比如在 [2016 年柏林 Linux 峰会](https://linuxconcontainerconeurope2016.sched.org/event/7oA4/kernel-development-i-still-think-we-have-a-scaling-problem-wolfram-sang-consultant)，他提出了如何提高内核开发实践的想法。

让我们来看看他的观点。

![](/data/attachment/album/201610/27/111637qgg4i0ygd3btztgt.png)

**在 2013 年的时候，你曾在爱丁堡（Edinburgh）提醒 ELCE 委员会，如果不作出改变，那么子系统的潜在问题和其他争议问题将会逐渐扩大。他们做出改变了吗？你所提及的那些事件发生了吗？**

是的，在某些程度上来说。当然了，Linux 内核是一个很多部分组成的项目，所以给以 Linux 各个子系统更多关注应该放在一个更重要的位置。然而，有太多的子系统“只是拼图中的一块”，所以通常来说，这些子系统的潜在问题还未被解决。

**你曾指出代码审核人数是一个大问题。为何你觉得 Linux 内核开发社区没有足够的代码审核人员呢？**

理由之一就是，大多数开发者实际上只是编写代码，而读代码并不多。这本是没有什么错，但却说明了并非每个人都是代码审核人员，所以我们真的应该鼓励每个人都进行代码审核。

我所看到另一件事就是，但我们要请人员加入我们的社区时，最重要的考核就是补丁贡献数量。我个人认为这是很正常的，并且在初期总贡献量少的时候是非常好的做法。但是随着越来越多的人员，特别是公司的加入，我们就碰到源码审核的问题。但是别误解了，有着数量可观的贡献是很棒的。但目前需要指出的是，参与社区有着更多内涵，比方说如何为下一步发展负责。有些部分在改善，但是还不够。

**你认为更多的代码审核人员培训或者审核激励措施是否会有帮助？**

我最主要的观点就是要指出，现今仍存在问题。是的，目前为止我们做到很好，但不意味着全都做的很好。我们也有类似扩张方面的问题。让人们了解事实，是希望能够让一些团体对此感兴趣并参与其中。尽管，我并不认为我们需要特殊的训练。我所熟悉的一些代码审核人员都非常棒或者很有天赋，只是这类人太少或者他们的空闲时间太少。

首先就是需要有这种内在动力，至于其它的，边做边学就非常好了。这又是我想要指出的优势之一：审核补丁能够使你成为更出色的代码开发者。

**依你之见，是否有那么一个受欢迎的大项目在扩张这方面做的很好，可以供我们借鉴？**

我还真不知道有这么一个项目，如果有的话随时借鉴。

我很专注于 Linux 内核，所以可能会存在一些偏见。然而在我看来，Linux 内核项目在规模大小、贡献数量和多样性方面真的很特别。所以当我想要找另一个项目来寻找灵感以便改善工作流是很正常的想法，目前我们的扩张问题真的比较特别。而且我发现，看看其他子系统在内核中做了什么是一个很有的方法。

**你曾说安全问题是我们每个人都该想到的事情，那用户应该做些什么来避免或者改善安全问题的危险？**

在今年（2016年）柏林 Linux 峰会我的谈话是针对开发层面的。安全隐患可能来自于没有正确审核的补丁中。我并不想要用户亲自解决这种问题，我更希望这些安全问题永远不会出现。当然这是不可能的，但这仍然是我处理问题所首选的方法。

**我很好奇这个庞大社区如何改善这些问题。是否有你希望用户定期以文件形式提交的某些类型的错误报告？需要定期检查的区域却因为某些原因没有注意到的？**

我们并不缺少错误报告。我所担心的是：由于代码审核人员的短缺造成补丁不完整，从而导致更多的错误报告。所以，到时候不仅需要处理大量的贡献，还需要处理更多错误或者进行版本回退。

**你是否还有什么事情希望我们读者知道，以了解你所在的努力？**

Linux 内核的特殊性，常常让我牢记着，在底层它就是代码而已。

---

via: <https://opensource.com/business/16/10/linux-kernel-review>

作者：[Deb Nicholson](https://opensource.com/users/eximious) 译者：[GHLandy](https://github.com/GHLandy) 校对：[wxy](https://github.com/wxy)

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


ORWL：能够删除被篡改数据的微型开源计算机

只想要一个折叠屏

![](/data/attachment/album/201610/27/121104vwsfh5x7lz9sfy5l.jpg)

在当今这个信息时代，安全是最重要的。恐怕没有人会希望自己的重要数据落入到坏人的手里。但是即便是无安全防护的硬件同样面临不少威胁，而大多数时候人们还只是对软件采取安全防护措施。ORWL 就是来改变这件事的。

![](/data/attachment/album/201610/27/121457lvmcpwjmcpqncjz5.jpg)

### [ORWL 是什么？](http://www.design-shift.com/orwl/)

ORWL 宣称是社区里“造得最安全的家用电脑”。 它是一台小型的飞碟形计算机，在设计上全面考虑了物理安全性。物理安全很重要，因为一旦有人获得了从物理上访问你的计算机的途径，那么就 Game Over 了，这是信息安全专业人员中的一个老生常谈。

![](/data/attachment/album/201610/27/121523fjjooyo6a1lha1jo.jpg)

ORWL 的基本规格包括英特尔 Skylake M3 处理器、USB-C 和微型 HDMI 接口、8GB 内存、120G 固态硬盘、蓝牙、Wifi 和 NFC 技术。目前它支持的操作系统有 Ubuntu 16.04、Qubes OS，以及 Windows 10 等，开箱即用。你只需要有一个显示器，键盘和鼠标就可以开始使用它了。

### ORWL 是开源的

ORWL 是**完全**开源的。这意味着，如果有人想设计一台自己的计算机或者对 ORWL 作出改进的话，原理图和设计文件、软件、固件、所有东西都是可以获取的。

![](/data/attachment/album/201610/27/121551kumk79m5yyf0x9xr.jpg)

### ORWL 是如何工作的？

ORWL 使用自加密固态硬盘（SSD）。一个安全微控制器集成到其主板上来产生和存储加密密匙。一旦核实了系统的完整性和已验证用户，它就使用密匙来解密固态硬盘（SSD）。无论对 ORWL 进行任何类型的篡改，密匙都会立即删除固态硬盘（SSD）上的无用数据

为了完成身份验证，ORWL 有一个使用和智能卡类似技术的密匙卡。它使用 NFC 技术来验证用户，同时使用蓝牙来检测用户是否在当前使用范围内。如果用户不在附近（不在使用范围内），ORWL 将会自动锁定。

![](/data/attachment/album/201610/27/121603cja07djjjaddlaaz.jpg)

整个 ORWL 系统被包裹在一个到处伴有压力开关的活动翻盖网格里。安全微控制器持续监控专用惯性测量部件，活动翻盖网格，内部温度和电源输入电压，以用于检测篡改。这将防止访问内部组件，比如试图破坏翻盖将会触发安全微控制器从而删除加密密匙。此外，出于安全考虑，动态随机存储器（DRAM）也焊有外壳。

这并不是全部安全防护措施，ORWL 还有更多详细的措施来确保设备绝对的物理安全性，包括冷启动防护，直接存储器访问（DMA）攻击防御等。

更多信息可以在 [ORWL 引导页](https://www.orwl.org/)找到。这儿是一个关于它如何工作的快速视频。

### ORWL 是信息安全的最终答案吗？

令人沮丧的是，ORWL 并不是信息安全的最终答案。ORWL 只能为计算机提供物理安全，尽管这很强大并且看起来<ruby> 极酷 <rp>  （ </rp> <rt>  totally ninja </rt> <rp>  ） </rp></ruby>，但是还有许多来自其他方面的攻击会损坏你的系统。然而，ORWL 确实从整体上提高了计算机的安全性。

你认为 ORWL 怎么样？通过评论让我们知道你的想法。

---

via: <https://itsfoss.com/orwl-physically-secure-computer/>

作者：[Munif Tanjim](https://itsfoss.com/author/munif/) 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

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


构建你的数据科学作品集：机器学习项目

Summary: 数据科学公司在决定雇佣时越来越关注你在数据科学方面的作品集。这其中的一个原因是，这样的作品集是判断某人的实际技能的最好的方法。好消息是构建这样的作品集完全要看你自己。只要你在这方面付出了努力，你一定可以取得让这些公司钦佩的作品集。

这篇文章翻译的真不容易，感谢组长……

很赞！！！

>
> 这是[这个系列](https://www.dataquest.io/blog/data-science-portfolio-project/)发布的第三篇关于如何构建数据<ruby> 科学作品集 <rp>  （ </rp> <rt>  Data Science Portfolio </rt> <rp>  ） </rp></ruby>的文章。如果你喜欢这个系列并且想继续关注，你可以在订阅页面的底部找到[链接](https://www.dataquest.io/blog/data-science-portfolio-machine-learning/#email-signup)。
>
>
>

数据科学公司在决定雇佣时越来越关注你在数据科学方面的<ruby> 作品集 <rp>  （ </rp> <rt>  Portfolio </rt> <rp>  ） </rp></ruby>。这其中的一个原因是，这样的作品集是判断某人的实际技能的最好的方法。好消息是构建这样的作品集完全要看你自己。只要你在这方面付出了努力，你一定可以取得让这些公司钦佩的作品集。

![](/data/attachment/album/201610/28/102139w8yn68zmpl7ipzn8.jpg)

构建高质量的作品集的第一步就是知道需要什么技能。公司想要在数据科学方面拥有的、他们希望你能够运用的主要技能有：

* 沟通能力
* 协作能力
* 技术能力
* 数据推理能力
* 动机和主动性

任何好的作品集都由多个项目表现出来，其中每个都能够表现出以上一到两点。这是本系列的第三篇，本系列我们主要讲包括如何打造面面俱到的数据科学作品集。在这一篇中，我们主要涵盖了如何构建组成你的作品集的第二个项目，以及如何创建一个端对端的机器学习项目。在最后，我们将拥有一个展示你的数据推理能力和技术能力的项目。如果你想看一下的话，[这里](https://github.com/dataquestio/loan-prediction)有一个完整的例子。

### 一个端到端的项目

作为一个数据科学家，有时候你会拿到一个数据集并被问如何[用它来讲故事](https://www.dataquest.io/blog/data-science-portfolio-project/)。在这个时候，沟通就是非常重要的，你需要用它来完成这个事情。像我们在前一篇文章中用过的，类似 Jupyter notebook 这样的工具，将对你非常有帮助。在这里你能找到一些可以用的报告或者总结文档。

不管怎样，有时候你会被要求创建一个具有操作价值的项目。具有操作价值的项目将直接影响到公司的日常业务，它会使用不止一次，经常是许多人使用。这个任务可能像这样 “创建一个算法来预测周转率”或者“创建一个模型来自动对我们的文章打标签”。在这种情况下，技术能力比讲故事更重要。你必须能够得到一个数据集，并且理解它，然后创建脚本处理该数据。这个脚本要运行的很快，占用系统资源很小。通常它可能要运行很多次，脚本的可使用性也很重要，并不仅仅是一个演示版。可使用性是指整合进操作流程，并且甚至是是面向用户的。

端对端项目的主要组成部分:

* 理解背景
* 浏览数据并找出细微差别
* 创建结构化项目，那样比较容易整合进操作流程
* 运行速度快、占用系统资源小的高性能代码
* 写好安装和使用文档以便其他人用

为了有效的创建这种类型的项目，我们可能需要处理多个文件。强烈推荐使用 [Atom](https://atom.io/) 这样的文本编辑器或者 [PyCharm](https://www.jetbrains.com/pycharm/) 这样的 IDE。这些工具允许你在文件间跳转，编辑不同类型的文件，例如 markdown 文件，Python 文件，和 csv 文件等等。结构化你的项目还利于版本控制，并上传一个类似 [Github](https://github.com/) 这样的协作开发工具上也很有用。

![](/data/attachment/album/201610/28/100707fwx12ctoj9lp654v.png)

*Github 上的这个项目*

在这一节中我们将使用 [Pandas](http://pandas.pydata.org/) 和 [scikit-learn](http://scikit-learn.org/) 这样的库，我们还将大量用到 Pandas [DataFrames](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)，它使得 python 读取和处理表格数据更加方便。

### 找到好的数据集

为一个端到端的作品集项目的找到好的数据集很难。在内存和性能的限制下，数据集需要尽量的大。它还需要是实际有用的。例如，[这个数据集](https://collegescorecard.ed.gov/data/)，它包含有美国院校的录取标准、毕业率以及毕业以后的收入，是个很好的可以讲故事的数据集。但是，不管你如何看待这个数据，很显然它不适合创建端到端的项目。比如，你能告诉人们他们去了这些大学以后的未来收入，但是这个快速检索却并不足够呈现出你的技术能力。你还能找出院校的招生标准和更高的收入相关，但是这更像是常理而不是你的技术结论。

这里还有内存和性能约束的问题，比如你有几千兆的数据，而且当你需要找到一些差异时，就需要对数据集一遍遍运行算法。

一个好的可操作的数据集可以让你构建一系列脚本来转换数据、动态地回答问题。一个很好的例子是股票价格数据集，当股市关闭时，就会给算法提供新的数据。这可以让你预测明天的股价，甚至预测收益。这不是讲故事，它带来的是真金白银。

一些找到数据集的好地方：

* [/r/datasets](https://reddit.com/r/datasets) – 有上百的有趣数据的 subreddit（Reddit 是国外一个社交新闻站点，subreddit 指该论坛下的各不同版块）。
* [Google Public Datasets](https://cloud.google.com/bigquery/public-data/#usa-names) – 通过 Google BigQuery 使用的公开数据集。
* [Awesome datasets](https://github.com/caesar0301/awesome-public-datasets) – 一个数据集列表，放在 Github 上。

当你查看这些数据集时，想一下人们想要在这些数据集中得到什么答案，哪怕这些问题只想过一次（“房价是如何与标准普尔 500 指数关联的?”），或者更进一步（“你能预测股市吗?”）。这里的关键是更进一步地找出问题，并且用相同的代码在不同输入（不同的数据）上运行多次。

对于本文的目标，我们来看一下 <ruby> 房利美 <rp>  （ </rp> <rt>  Fannie Mae </rt> <rp>  ） </rp></ruby>[贷款数据](http://www.fanniemae.com/portal/funding-the-market/data/loan-performance-data.html)。房利美是一家在美国的政府赞助的企业抵押贷款公司，它从其他银行购买按揭贷款，然后捆绑这些贷款为贷款证券来转卖它们。这使得贷款机构可以提供更多的抵押贷款，在市场上创造更多的流动性。这在理论上会带来更多的住房和更好的贷款期限。从借款人的角度来说，它们大体上差不多，话虽这样说。

房利美发布了两种类型的数据 – 它获得的贷款的数据，和贷款偿还情况的数据。在理想的情况下，有人向贷款人借钱，然后还款直到还清。不管怎样，有些人多次不还，从而丧失了抵押品赎回权。抵押品赎回权是指没钱还了被银行把房子给收走了。房利美会追踪谁没还钱，并且哪个贷款需要收回抵押的房屋（取消赎回权）。每个季度会发布此数据，发布的是滞后一年的数据。当前可用是 2015 年第一季度数据。

“贷款数据”是由房利美发布的贷款发放的数据，它包含借款人的信息、信用评分，和他们的家庭贷款信息。“执行数据”，贷款发放后的每一个季度公布，包含借贷人的还款信息和是否丧失抵押品赎回权的状态，一个“贷款数据”的“执行数据”可能有十几行。可以这样理解，“贷款数据”告诉你房利美所控制的贷款，“执行数据”包含该贷款一系列的状态更新。其中一个状态更新可以告诉我们一笔贷款在某个季度被取消赎回权了。

![](/data/attachment/album/201610/28/100856wgsknycgcksccpsc.jpg)

*一个没有及时还贷的房子就这样的被卖了*

### 选择一个角度

这里有几个我们可以去分析房利美数据集的方向。我们可以：

* 预测房屋的销售价格。
* 预测借款人还款历史。
* 在获得贷款时为每一笔贷款打分。

最重要的事情是坚持单一的角度。同时关注太多的事情很难做出效果。选择一个有着足够细节的角度也很重要。下面的角度就没有太多细节：

* 找出哪些银行将贷款出售给房利美的多数被取消赎回权。
* 计算贷款人的信用评分趋势。
* 找到哪些类型的家庭没有偿还贷款的能力。
* 找到贷款金额和抵押品价格之间的关系。

上面的想法非常有趣，如果我们关注于讲故事，那是一个不错的角度，但是不是很适合一个操作性项目。

在房利美数据集中，我们将仅使用申请贷款时有的那些信息来预测贷款是否将来会被取消赎回权。实际上, 我们将为每一笔贷款建立“分数”来告诉房利美买还是不买。这将给我们打下良好的基础，并将组成这个漂亮的作品集的一部分。

### 理解数据

我们来简单看一下原始数据文件。下面是 2012 年 1 季度前几行的贷款数据：

```
100000853384|R|OTHER|4.625|280000|360|02/2012|04/2012|31|31|1|23|801|N|C|SF|1|I|CA|945||FRM|
100003735682|R|SUNTRUST MORTGAGE INC.|3.99|466000|360|01/2012|03/2012|80|80|2|30|794|N|P|SF|1|P|MD|208||FRM|788
100006367485|C|PHH MORTGAGE CORPORATION|4|229000|360|02/2012|04/2012|67|67|2|36|802|N|R|SF|1|P|CA|959||FRM|794

```

下面是 2012 年 1 季度的前几行执行数据：

```
100000853384|03/01/2012|OTHER|4.625||0|360|359|03/2042|41860|0|N||||||||||||||||
100000853384|04/01/2012||4.625||1|359|358|03/2042|41860|0|N||||||||||||||||
100000853384|05/01/2012||4.625||2|358|357|03/2042|41860|0|N||||||||||||||||

```

在开始编码之前，花些时间真正理解数据是值得的。这对于操作性项目优为重要，因为我们没有交互式探索数据，将很难察觉到细微的差别，除非我们在前期发现他们。在这种情况下，第一个步骤是阅读房利美站点的资料：

* [概述](http://www.fanniemae.com/portal/funding-the-market/data/loan-performance-data.html)
* [有用的术语表](https://loanperformancedata.fanniemae.com/lppub-docs/lppub_glossary.pdf)
* [常见问答](https://loanperformancedata.fanniemae.com/lppub-docs/lppub_faq.pdf)
* [贷款和执行文件中的列](https://loanperformancedata.fanniemae.com/lppub-docs/lppub_file_layout.pdf)
* [贷款数据文件样本](https://loanperformancedata.fanniemae.com/lppub-docs/acquisition-sample-file.txt)
* [执行数据文件样本](https://loanperformancedata.fanniemae.com/lppub-docs/performance-sample-file.txt)

在看完这些文件后后，我们了解到一些能帮助我们的关键点：

* 从 2000 年到现在，每季度都有一个贷款和执行文件，因数据是滞后一年的，所以到目前为止最新数据是 2015 年的。
* 这些文件是文本格式的，采用管道符号`|`进行分割。
* 这些文件是没有表头的，但我们有个文件列明了各列的名称。
* 所有一起，文件包含 2200 万个贷款的数据。
* 由于执行数据的文件包含过去几年获得的贷款的信息，在早些年获得的贷款将有更多的执行数据（即在 2014 获得的贷款没有多少历史执行数据）。

这些小小的信息将会为我们节省很多时间，因为这样我们就知道如何构造我们的项目和利用这些数据了。

### 构造项目

在我们开始下载和探索数据之前，先想一想将如何构造项目是很重要的。当建立端到端项目时，我们的主要目标是：

* 创建一个可行解决方案
* 有一个快速运行且占用最小资源的解决方案
* 容易可扩展
* 写容易理解的代码
* 写尽量少的代码

为了实现这些目标，需要对我们的项目进行良好的构造。一个结构良好的项目遵循几个原则：

* 分离数据文件和代码文件
* 从原始数据中分离生成的数据。
* 有一个 `README.md` 文件帮助人们安装和使用该项目。
* 有一个 `requirements.txt` 文件列明项目运行所需的所有包。
* 有一个单独的 `settings.py` 文件列明其它文件中使用的所有的设置
	+ 例如，如果从多个 `Python` 脚本读取同一个文件，让它们全部 `import` 设置并从一个集中的地方获得文件名是有用的。
* 有一个 `.gitignore` 文件，防止大的或密码文件被提交。
* 分解任务中每一步可以单独执行的步骤到单独的文件中。
	+ 例如，我们将有一个文件用于读取数据，一个用于创建特征，一个用于做出预测。
* 保存中间结果，例如，一个脚本可以输出下一个脚本可读取的文件。
	+ 这使我们无需重新计算就可以在数据处理流程中进行更改。

我们的文件结构大体如下：

```
loan-prediction
├── data
├── processed
├── .gitignore
├── README.md
├── requirements.txt
├── settings.py

```

### 创建初始文件

首先，我们需要创建一个 `loan-prediction` 文件夹，在此文件夹下面，再创建一个 `data` 文件夹和一个 `processed` 文件夹。`data` 文件夹存放原始数据，`processed` 文件夹存放所有的中间计算结果。

其次，创建 `.gitignore` 文件，`.gitignore` 文件将保证某些文件被 git 忽略而不会被推送至 GitHub。关于这个文件的一个好的例子是由 OSX 在每一个文件夹都会创建的 `.DS_Store` 文件，`.gitignore` 文件一个很好的范本在[这里](https://github.com/github/gitignore/blob/master/Python.gitignore)。我们还想忽略数据文件，因为它们实在是太大了，同时房利美的条文禁止我们重新分发该数据文件，所以我们应该在我们的文件后面添加以下 2 行：

```
data
processed

```

[这里](https://github.com/dataquestio/loan-prediction/blob/master/.gitignore)是该项目的一个关于 .gitignore 文件的例子。

再次，我们需要创建 `README.md` 文件，它将帮助人们理解该项目。后缀 .md 表示这个文件采用 markdown 格式。Markdown 使你能够写纯文本文件，同时还可以添加你想要的神奇的格式。[这里](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)是关于 markdown 的导引。如果你上传一个叫 `README.md` 的文件至 Github，Github 会自动处理该 markdown，同时展示给浏览该项目的人。例子在[这里](https://github.com/dataquestio/loan-prediction)。

至此，我们仅需在 `README.md` 文件中添加简单的描述：

```
Loan Prediction
-----------------------

Predict whether or not loans acquired by Fannie Mae will go into foreclosure.  Fannie Mae acquires loans from other lenders as a way of inducing them to lend more.  Fannie Mae releases data on the loans it has acquired and their performance afterwards [here](http://www.fanniemae.com/portal/funding-the-market/data/loan-performance-data.html).

```

现在，我们可以创建 `requirements.txt` 文件了。这会帮助其它人可以很方便地安装我们的项目。我们还不知道我们将会具体用到哪些库，但是以下几个库是需要的：

```
pandas
matplotlib
scikit-learn
numpy
ipython
scipy

```

以上几个是在 python 数据分析任务中最常用到的库。可以认为我们将会用到大部分这些库。[这里](https://github.com/dataquestio/loan-prediction/blob/master/requirements.txt)是该项目 `requirements.txt` 文件的一个例子。

创建 `requirements.txt` 文件之后，你应该安装这些包了。我们将会使用 python3。如果你没有安装 python，你应该考虑使用 [Anaconda](https://www.continuum.io/downloads)，它是一个 python 安装程序，同时安装了上面列出的所有包。

最后，我们可以建立一个空白的 `settings.py` 文件，因为我们的项目还没有任何设置。

### 获取数据

一旦我们有了项目的基本架构，我们就可以去获得原始数据。

房利美对获取数据有一些限制，所以你需要去注册一个账户。在创建完账户之后，你可以找到[在这里](https://loanperformancedata.fanniemae.com/lppub/index.html)的下载页面，你可以按照你所需要的下载或多或少的贷款数据文件。文件格式是 zip，在解压后当然是非常大的。

为了达到我们这个文章的目的，我们将要下载从 2012 年 1 季度到 2015 年 1 季度的所有数据。接着我们需要解压所有的文件。解压过后，删掉原来的 .zip 格式的文件。最后，loan-prediction 文件夹看起来应该像下面的一样：

```
loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
├── .gitignore
├── README.md
├── requirements.txt
├── settings.py

```

在下载完数据后，你可以在 shell 命令行中使用 `head` 和 `tail` 命令去查看文件中的行数据，你看到任何的不需要的数据列了吗？在做这件事的同时查阅[列名称的 pdf 文件](https://loanperformancedata.fanniemae.com/lppub-docs/lppub_file_layout.pdf)可能有帮助。

### 读入数据

有两个问题让我们的数据难以现在就使用：

* 贷款数据和执行数据被分割在多个文件中
* 每个文件都缺少列名标题

在我们开始使用数据之前，我们需要首先明白我们要在哪里去存一个贷款数据的文件，同时到哪里去存储一个执行数据的文件。每个文件仅仅需要包括我们关注的那些数据列，同时拥有正确的列名标题。这里有一个小问题是执行数据非常大，因此我们需要尝试去修剪一些数据列。

第一步是向 `settings.py` 文件中增加一些变量，这个文件中同时也包括了我们原始数据的存放路径和处理出的数据存放路径。我们同时也将添加其他一些可能在接下来会用到的设置数据：

```
DATA_DIR = "data"
PROCESSED_DIR = "processed"
MINIMUM_TRACKING_QUARTERS = 4
TARGET = "foreclosure_status"
NON_PREDICTORS = [TARGET, "id"]
CV_FOLDS = 3

```

把路径设置在 `settings.py` 中使它们放在一个集中的地方，同时使其修改更加的容易。当在多个文件中用到相同的变量时，你想改变它的话，把他们放在一个地方比分散放在每一个文件时更加容易。[这里的](https://github.com/dataquestio/loan-prediction/blob/master/settings.py)是一个这个工程的示例 `settings.py` 文件

第二步是创建一个文件名为 `assemble.py`，它将所有的数据分为 2 个文件。当我们运行 `Python assemble.py`，我们在处理数据文件的目录会获得 2 个数据文件。

接下来我们开始写 `assemble.py` 文件中的代码。首先我们需要为每个文件定义相应的列名标题，因此我们需要查看[列名称的 pdf 文件](https://loanperformancedata.fanniemae.com/lppub-docs/lppub_file_layout.pdf)，同时创建在每一个贷款数据和执行数据的文件的数据列的列表：

```
HEADERS = {
    "Acquisition": [
        "id",
        "channel",
        "seller",
        "interest_rate",
        "balance",
        "loan_term",
        "origination_date",
        "first_payment_date",
        "ltv",
        "cltv",
        "borrower_count",
        "dti",
        "borrower_credit_score",
        "first_time_homebuyer",
        "loan_purpose",
        "property_type",
        "unit_count",
        "occupancy_status",
        "property_state",
        "zip",
        "insurance_percentage",
        "product_type",
        "co_borrower_credit_score"
    ],
    "Performance": [
        "id",
        "reporting_period",
        "servicer_name",
        "interest_rate",
        "balance",
        "loan_age",
        "months_to_maturity",
        "maturity_date",
        "msa",
        "delinquency_status",
        "modification_flag",
        "zero_balance_code",
        "zero_balance_date",
        "last_paid_installment_date",
        "foreclosure_date",
        "disposition_date",
        "foreclosure_costs",
        "property_repair_costs",
        "recovery_costs",
        "misc_costs",
        "tax_costs",
        "sale_proceeds",
        "credit_enhancement_proceeds",
        "repurchase_proceeds",
        "other_foreclosure_proceeds",
        "non_interest_bearing_balance",
        "principal_forgiveness_balance"
    ]
}

```

接下来一步是定义我们想要保留的数据列。因为我们要预测一个贷款是否会被撤回，我们可以丢弃执行数据中的许多列。我们将需要保留贷款数据中的所有数据列，因为我们需要尽量多的了解贷款发放时的信息（毕竟我们是在预测贷款发放时这笔贷款将来是否会被撤回）。丢弃数据列将会使我们节省下内存和硬盘空间，同时也会加速我们的代码。

```
SELECT = {
    "Acquisition": HEADERS["Acquisition"],
    "Performance": [
        "id",
        "foreclosure_date"
    ]
}

```

下一步，我们将编写一个函数来连接数据集。下面的代码将：

* 引用一些需要的库，包括 `settings`。
* 定义一个函数 `concatenate`，目的是：
	+ 获取到所有 `data` 目录中的文件名。
	+ 遍历每个文件。
		- 如果文件不是正确的格式 (不是以我们需要的格式作为开头)，我们将忽略它。
		- 通过使用 Pandas 的 [read\_csv](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html) 函数及正确的设置把文件读入一个 [DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)。
			* 设置分隔符为`｜`，以便所有的字段能被正确读出。
			* 数据没有标题行，因此设置 `header` 为 `None` 来进行标示。
			* 从 `HEADERS` 字典中设置正确的标题名称 – 这将会是我们的 DataFrame 中的数据列名称。
			* 仅选择我们加在 `SELECT` 中的 DataFrame 的列。
* 把所有的 DataFrame 共同连接在一起。
* 把已经连接好的 DataFrame 写回一个文件。

```
import os
import settings
import pandas as pd

def concatenate(prefix="Acquisition"):
    files = os.listdir(settings.DATA_DIR)
    full = []
    for f in files:
        if not f.startswith(prefix):
            continue

        data = pd.read_csv(os.path.join(settings.DATA_DIR, f), sep="|", header=None, names=HEADERS[prefix], index_col=False)
        data = data[SELECT[prefix]]
        full.append(data)

    full = pd.concat(full, axis=0)

    full.to_csv(os.path.join(settings.PROCESSED_DIR, "{}.txt".format(prefix)), sep="|", header=SELECT[prefix], index=False)

```

我们可以通过调用上面的函数，通过传递的参数 `Acquisition` 和 `Performance` 两次以将所有的贷款和执行文件连接在一起。下面的代码将：

* 仅在命令行中运行 `python assemble.py` 时执行。
* 将所有的数据连接在一起，并且产生 2 个文件：
	+ `processed/Acquisition.txt`
	+ `processed/Performance.txt`

```
if __name__ == "__main__":
    concatenate("Acquisition")
    concatenate("Performance")

```

我们现在拥有了一个漂亮的，划分过的 `assemble.py` 文件，它很容易执行，也容易建立。通过像这样把问题分解为一块一块的，我们构建工程就会变的容易许多。不用一个可以做所有工作的凌乱脚本，我们定义的数据将会在多个脚本间传递，同时使脚本间完全的彼此隔离。当你正在一个大的项目中工作时，这样做是一个好的想法，因为这样可以更加容易修改其中的某一部分而不会引起其他项目中不关联部分产生预料之外的结果。

一旦我们完成 `assemble.py` 脚本文件，我们可以运行 `python assemble.py` 命令。你可以[在这里](https://github.com/dataquestio/loan-prediction/blob/master/assemble.py)查看完整的 `assemble.py` 文件。

这将会在 `processed` 目录下产生 2 个文件：

```
loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
├── .gitignore
├── assemble.py
├── README.md
├── requirements.txt
├── settings.py

```

### 计算来自执行数据的值

接下来我们会计算来自 `processed/Performance.txt` 中的值。我们要做的就是推测这些资产是否被取消赎回权。如果能够计算出来，我们只要看一下关联到贷款的执行数据的参数 `foreclosure_date` 就可以了。如果这个参数的值是 `None`，那么这些资产肯定没有收回。为了避免我们的样例中只有少量的执行数据，我们会为每个贷款计算出执行数据文件中的行数。这样我们就能够从我们的训练数据中筛选出贷款数据，排除了一些执行数据。

下面是我认为贷款数据和执行数据的关系：

![](/data/attachment/album/201610/28/101352pqj44fnouqvo45nx.jpg)

在上面的表格中，贷款数据中的每一行数据都关联到执行数据中的多行数据。在执行数据中，在取消赎回权的时候 `foreclosure_date` 就会出现在该季度，而之前它是空的。一些贷款还没有被取消赎回权，所以与执行数据中的贷款数据有关的行在 `foreclosure_date` 列都是空格。

我们需要计算 `foreclosure_status` 的值，它的值是布尔类型，可以表示一个特殊的贷款数据 `id` 是否被取消赎回权过，还有一个参数 `performance_count` ，它记录了执行数据中每个贷款 `id` 出现的行数。

计算这些行数有多种不同的方法：

* 我们能够读取所有的执行数据，然后我们用 Pandas 的 [groupby](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html) 方法在 DataFrame 中计算出与每个贷款 `id` 有关的行的行数，然后就可以查看贷款 `id` 的 `foreclosure_date` 值是否为 `None` 。
	+ 这种方法的优点是从语法上来说容易执行。
	+ 它的缺点需要读取所有的 129236094 行数据，这样就会占用大量内存，并且运行起来极慢。
* 我们可以读取所有的执行数据，然后在贷款 DataFrame 上使用 [apply](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.apply.html) 去计算每个贷款 `id`　出现的次数。
	+ 这种方法的优点是容易理解。
	+ 缺点是需要读取所有的 129236094 行数据。这样会占用大量内存，并且运行起来极慢。
* 我们可以在迭代访问执行数据中的每一行数据，而且会建立一个单独的计数字典。
	+ 这种方法的优点是数据不需要被加载到内存中，所以运行起来会很快且不需要占用内存。
	+ 缺点是这样的话理解和执行上可能有点耗费时间，我们需要对每一行数据进行语法分析。

加载所有的数据会非常耗费内存，所以我们采用第三种方法。我们要做的就是迭代执行数据中的每一行数据，然后为每一个贷款 `id` 在字典中保留一个计数。在这个字典中，我们会计算出贷款 `id` 在执行数据中出现的次数，而且看看 `foreclosure_date` 是否是 `None` 。我们可以查看 `foreclosure_status` 和 `performance_count` 的值 。

我们会新建一个 `annotate.py` 文件，文件中的代码可以计算这些值。我们会使用下面的代码：

* 导入需要的库
* 定义一个函数 `count_performance_rows` 。
	+ 打开 `processed/Performance.txt` 文件。这不是在内存中读取文件而是打开了一个文件标识符，这个标识符可以用来以行为单位读取文件。
	+ 迭代文件的每一行数据。
	+ 使用分隔符`|`分开每行的不同数据。
	+ 检查 `loan_id` 是否在计数字典中。
		- 如果不存在，把它加进去。
	+ `loan_id` 的 `performance_count` 参数自增 1 次，因为我们这次迭代也包含其中。
	+ 如果 `date` 不是 `None ，我们就会知道贷款被取消赎回权了，然后为`foreclosure\_status` 设置合适的值。

```
import os
import settings
import pandas as pd

def count_performance_rows():
    counts = {}
    with open(os.path.join(settings.PROCESSED_DIR, "Performance.txt"), 'r') as f:
        for i, line in enumerate(f):
            if i == 0:
                # Skip header row
                continue
            loan_id, date = line.split("|")
            loan_id = int(loan_id)
            if loan_id not in counts:
                counts[loan_id] = {
                    "foreclosure_status": False,
                    "performance_count": 0
                }
            counts[loan_id]["performance_count"] += 1
            if len(date.strip()) > 0:
                counts[loan_id]["foreclosure_status"] = True
    return counts

```

### 获取值

只要我们创建了计数字典，我们就可以使用一个函数通过一个 `loan_id` 和一个 `key` 从字典中提取到需要的参数的值：

```
def get_performance_summary_value(loan_id, key, counts):
    value = counts.get(loan_id, {
        "foreclosure_status": False,
        "performance_count": 0
    })
    return value[key]

```

上面的函数会从 `counts` 字典中返回合适的值，我们也能够为贷款数据中的每一行赋一个 `foreclosure_status` 值和一个 `performance_count` 值。如果键不存在，字典的 [get](https://docs.python.org/3/library/stdtypes.html#dict.get) 方法会返回一个默认值，所以在字典中不存在键的时候我们就可以得到一个可知的默认值。

### 转换数据

我们已经在 `annotate.py` 中添加了一些功能，现在我们来看一看数据文件。我们需要将贷款到的数据转换到训练数据集来进行机器学习算法的训练。这涉及到以下几件事情:

* 转换所有列为数字。
* 填充缺失值。
* 为每一行分配 `performance_count` 和 `foreclosure_status`。
* 移除出现执行数据很少的行（`performance_count` 计数低）。

我们有几个列是文本类型的，看起来对于机器学习算法来说并不是很有用。然而，它们实际上是分类变量，其中有很多不同的类别代码，例如 `R`，`S` 等等. 我们可以把这些类别标签转换为数值：

![](/data/attachment/album/201610/28/101451p3xmfd34fyfq0xf5.jpg)

通过这种方法转换的列我们可以应用到机器学习算法中。

还有一些包含日期的列 (`first_payment_date` 和 `origination_date`）。我们可以将这些日期放到两个列中：

![](/data/attachment/album/201610/28/101502gn0icuiiziiug5ez.jpg)

在下面的代码中，我们将转换贷款数据。我们将定义一个函数如下：

* 在 `acquisition` 中创建 `foreclosure_status` 列，并从 `counts` 字典中得到值。
* 在 `acquisition` 中创建 `performance_count` 列，并从 `counts` 字典中得到值。
* 将下面的列从字符串转换为整数：
	+ `channel`
	+ `seller`
	+ `first_time_homebuyer`
	+ `loan_purpose`
	+ `property_type`
	+ `occupancy_status`
	+ `property_state`
	+ `product_type`
* 将 `first_payment_date` 和 `origination_date` 分别转换为两列：
	+ 通过斜杠分离列。
	+ 将第一部分分离成 `month` 列。
	+ 将第二部分分离成 `year` 列。
	+ 删除该列。
	+ 最后，我们得到 `first_payment_month`、`first_payment_year`、`rigination_month` 和 `origination_year`。
* 所有缺失值填充为 `-1`。

```
def annotate(acquisition, counts):
    acquisition["foreclosure_status"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "foreclosure_status", counts))
    acquisition["performance_count"] = acquisition["id"].apply(lambda x: get_performance_summary_value(x, "performance_count", counts))
    for column in [
        "channel",
        "seller",
        "first_time_homebuyer",
        "loan_purpose",
        "property_type",
        "occupancy_status",
        "property_state",
        "product_type"
    ]:
        acquisition[column] = acquisition[column].astype('category').cat.codes

    for start in ["first_payment", "origination"]:
        column = "{}_date".format(start)
        acquisition["{}_year".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(1))
        acquisition["{}_month".format(start)] = pd.to_numeric(acquisition[column].str.split('/').str.get(0))
        del acquisition[column]

    acquisition = acquisition.fillna(-1)
    acquisition = acquisition[acquisition["performance_count"] > settings.MINIMUM_TRACKING_QUARTERS]
    return acquisition

```

### 聚合到一起

我们差不多准备就绪了，我们只需要再在 `annotate.py` 添加一点点代码。在下面代码中，我们将：

* 定义一个函数来读取贷款的数据。
* 定义一个函数来写入处理过的数据到 `processed/train.csv`。
* 如果该文件在命令行以 `python annotate.py` 的方式运行：
	+ 读取贷款数据。
	+ 计算执行数据的计数，并将其赋予 `counts`。
	+ 转换 `acquisition` DataFrame。
	+ 将`acquisition` DataFrame 写入到 `train.csv`。

```
def read():
    acquisition = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "Acquisition.txt"), sep="|")
    return acquisition

def write(acquisition):
    acquisition.to_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"), index=False)

if __name__ == "__main__":
    acquisition = read()
    counts = count_performance_rows()
    acquisition = annotate(acquisition, counts)
    write(acquisition)

```

修改完成以后，确保运行 `python annotate.py` 来生成 `train.csv` 文件。 你可以在[这里](https://github.com/dataquestio/loan-prediction/blob/master/annotate.py)找到完整的 `annotate.py` 文件。

现在文件夹看起来应该像这样：

```
loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
│   ├── train.csv
├── .gitignore
├── annotate.py
├── assemble.py
├── README.md
├── requirements.txt
├── settings.py

```

### 找到误差标准

我们已经完成了训练数据表的生成，现在我们需要最后一步，生成预测。我们需要找到误差的标准，以及该如何评估我们的数据。在这种情况下，因为有很多的贷款没有被取消赎回权，所以根本不可能做到精确的计算。

我们需要读取训练数据，并且计算 `foreclosure_status` 列的计数，我们将得到如下信息：

```
import pandas as pd
import settings

train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"))
train["foreclosure_status"].value_counts()

```

```
False    4635982
True        1585
Name: foreclosure_status, dtype: int64

```

因为只有很少的贷款被取消赎回权，只需要检查正确预测的标签的百分比就意味着我们可以创建一个机器学习模型，来为每一行预测 `False`，并能取得很高的精确度。相反，我们想要使用一个度量来考虑分类的不平衡，确保我们可以准确预测。我们要避免太多的误报率（预测贷款被取消赎回权，但是实际没有），也要避免太多的漏报率（预测贷款没有别取消赎回权，但是实际被取消了）。对于这两个来说，漏报率对于房利美来说成本更高，因为他们买的贷款可能是他们无法收回投资的贷款。

所以我们将定义一个漏报率，就是模型预测没有取消赎回权但是实际上取消了，这个数除以总的取消赎回权数。这是“缺失的”实际取消赎回权百分比的模型。下面看这个图表：

![](/data/attachment/album/201610/28/101602npfaaa3rjh2fjfos.jpg)

通过上面的图表，有 1 个贷款预测不会取消赎回权，但是实际上取消了。如果我们将这个数除以实际取消赎回权的总数 2，我们将得到漏报率 50%。 我们将使用这个误差标准，因此我们可以评估一下模型的行为。

### 设置机器学习分类器

我们使用交叉验证预测。通过交叉验证法，我们将数据分为3组。按照下面的方法来做：

* 用组 1 和组 2 训练模型，然后用该模型来预测组 3
* 用组 1 和组 3 训练模型，然后用该模型来预测组 2
* 用组 2 和组 3 训练模型，然后用该模型来预测组 1

将它们分割到不同的组，这意味着我们永远不会用相同的数据来为其预测训练模型。这样就避免了过拟合。如果过拟合，我们将错误地拉低了漏报率，这使得我们难以改进算法或者应用到现实生活中。

[Scikit-learn](http://scikit-learn.org/) 有一个叫做 [cross*val*predict](http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.cross_val_predict.html) ，它可以帮助我们理解交叉算法.

我们还需要一种算法来帮我们预测。我们还需要一个分类器来做[二元分类](https://en.wikipedia.org/wiki/Binary_classification)。目标变量 `foreclosure_status` 只有两个值， `True` 和 `False`。

这里我们用 [逻辑回归算法](https://en.wikipedia.org/wiki/Logistic_regression)，因为它能很好的进行二元分类，并且运行很快，占用内存很小。我们来说一下它是如何工作的：不使用像随机森林一样多树结构，也不像支持向量机一样做复杂的转换，逻辑回归算法涉及更少的步骤和更少的矩阵。

我们可以使用 scikit-learn 实现的[逻辑回归分类器](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)算法。我们唯一需要注意的是每个类的权重。如果我们使用等权重的类，算法将会预测每行都为 `false`，因为它总是试图最小化误差。不管怎样，我们重视有多少贷款要被取消赎回权而不是有多少不能被取消。因此，我们给[逻辑回归](http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)类的 `class_weight` 关键字传递 `balanced` 参数，让算法可以为不同 counts 的每个类考虑不同的取消赎回权的权重。这将使我们的算法不会为每一行都预测 `false`，而是两个类的误差水平一致。

### 做出预测

既然完成了前期准备，我们可以开始准备做出预测了。我将创建一个名为 `predict.py` 的新文件，它会使用我们在最后一步创建的 `train.csv` 文件。下面的代码：

* 导入所需的库
* 创建一个名为 `cross_validate` 的函数：
	+ 使用正确的关键词参数创建逻辑回归分类器
	+ 创建用于训练模型的数据列的列表，移除 `id` 和 `foreclosure_status` 列
	+ 交叉验证 `train` DataFrame
	+ 返回预测结果

```
import os
import settings
import pandas as pd
from sklearn import cross_validation
from sklearn.linear_model import LogisticRegression
from sklearn import metrics

def cross_validate(train):
    clf = LogisticRegression(random_state=1, class_weight="balanced")

    predictors = train.columns.tolist()
    predictors = [p for p in predictors if p not in settings.NON_PREDICTORS]

    predictions = cross_validation.cross_val_predict(clf, train[predictors], train[settings.TARGET], cv=settings.CV_FOLDS)
    return predictions

```

### 预测误差

现在，我们仅仅需要写一些函数来计算误差。下面的代码：

* 创建函数 `compute_error`：
	+ 使用 scikit-learn 计算一个简单的精确分数（与实际 `foreclosure_status` 值匹配的预测百分比）
* 创建函数 `compute_false_negatives`：
	+ 为了方便，将目标和预测结果合并到一个 DataFrame
	+ 查找漏报率
		- 找到原本应被预测模型取消赎回权，但实际没有取消的贷款数目
		- 除以没被取消赎回权的贷款总数目

```
def compute_error(target, predictions):
    return metrics.accuracy_score(target, predictions)

def compute_false_negatives(target, predictions):
    df = pd.DataFrame({"target": target, "predictions": predictions})
    return df[(df["target"] == 1) & (df["predictions"] == 0)].shape[0] / (df[(df["target"] == 1)].shape[0] + 1)

def compute_false_positives(target, predictions):
    df = pd.DataFrame({"target": target, "predictions": predictions})
    return df[(df["target"] == 0) & (df["predictions"] == 1)].shape[0] / (df[(df["target"] == 0)].shape[0] + 1)

```

### 聚合到一起

现在，我们可以把函数都放在 `predict.py`。下面的代码：

* 读取数据集
* 计算交叉验证预测
* 计算上面的 3 个误差
* 打印误差

```
def read():
    train = pd.read_csv(os.path.join(settings.PROCESSED_DIR, "train.csv"))
    return train

if __name__ == "__main__":
    train = read()
    predictions = cross_validate(train)
    error = compute_error(train[settings.TARGET], predictions)
    fn = compute_false_negatives(train[settings.TARGET], predictions)
    fp = compute_false_positives(train[settings.TARGET], predictions)
    print("Accuracy Score: {}".format(error))
    print("False Negatives: {}".format(fn))
    print("False Positives: {}".format(fp))

```

一旦你添加完代码，你可以运行 `python predict.py` 来产生预测结果。运行结果向我们展示漏报率为 `.26`，这意味着我们没能预测 `26%` 的取消贷款。这是一个好的开始，但仍有很多改善的地方！

你可以在[这里](https://github.com/dataquestio/loan-prediction/blob/master/predict.py)找到完整的 `predict.py` 文件。

你的文件树现在看起来像下面这样：

```
loan-prediction
├── data
│   ├── Acquisition_2012Q1.txt
│   ├── Acquisition_2012Q2.txt
│   ├── Performance_2012Q1.txt
│   ├── Performance_2012Q2.txt
│   └── ...
├── processed
│   ├── Acquisition.txt
│   ├── Performance.txt
│   ├── train.csv
├── .gitignore
├── annotate.py
├── assemble.py
├── predict.py
├── README.md
├── requirements.txt
├── settings.py

```

### 撰写 README

既然我们完成了端到端的项目，那么我们可以撰写 `README.md` 文件了，这样其他人便可以知道我们做的事，以及如何复制它。一个项目典型的 `README.md` 应该包括这些部分：

* 一个高水准的项目概览，并介绍项目目的
* 任何必需的数据和材料的下载地址
* 安装命令
	+ 如何安装要求依赖
* 使用命令
	+ 如何运行项目
	+ 每一步之后会看到的结果
* 如何为这个项目作贡献
	+ 扩展项目的下一步计划

[这里](https://github.com/dataquestio/loan-prediction/blob/master/README.md) 是这个项目的一个 `README.md` 样例。

### 下一步

恭喜你完成了端到端的机器学习项目！你可以在[这里](https://github.com/dataquestio/loan-prediction)找到一个完整的示例项目。一旦你完成了项目，把它上传到 [Github](https://www.github.com/) 是一个不错的主意，这样其他人也可以看到你的文件夹的部分项目。

这里仍有一些留待探索数据的角度。总的来说，我们可以把它们分割为 3 类： 扩展这个项目并使它更加精确，发现其他可以预测的列，并探索数据。这是其中一些想法：

* 在 `annotate.py` 中生成更多的特性
* 切换 `predict.py` 中的算法
* 尝试使用比我们发表在这里的更多的房利美数据
* 添加对未来数据进行预测的方法。如果我们添加更多数据，我们所写的代码仍然可以起作用，这样我们可以添加更多过去和未来的数据。
* 尝试看看是否你能预测一个银行原本是否应该发放贷款（相对地，房利美是否应该获得贷款）
	+ 移除 `train` 中银行在发放贷款时间的不知道的任何列
		- 当房利美购买贷款时，一些列是已知的，但之前是不知道的
	+ 做出预测
* 探索是否你可以预测除了 `foreclosure_status` 的其他列
	+ 你可以预测在销售时资产值是多少？
* 探索探索执行数据更新之间的细微差别
	+ 你能否预测借款人会逾期还款多少次?
	+ 你能否标出的典型贷款周期?
* 将数据按州或邮政编码标出
	+ 你看到一些有趣的模式了吗?

如果你建立了任何有趣的东西,请在评论中让我们知道!

如果你喜欢这篇文章，或许你也会喜欢阅读“构建你的数据科学作品集”系列的其他文章：

* [用数据讲故事](https://www.dataquest.io/blog/data-science-portfolio-project/)
* [如何搭建一个数据科学博客](https://www.dataquest.io/blog/how-to-setup-a-data-science-blog/)
* [构建一个可以帮你找到工作的数据科学作品集的关键](https://www.dataquest.io/blog/build-a-data-science-portfolio/)
* [找到数据科学用的数据集的 17 个地方](https://www.dataquest.io/blog/free-datasets-for-projects)

---

via: <https://www.dataquest.io/blog/data-science-portfolio-machine-learning/>

作者：[Vik Paruchuri](https://www.dataquest.io/blog) 译者：[kokialoves](https://github.com/kokialoves), [zky001](https://github.com/zky001), [vim-kakali](https://github.com/vim-kakali), [cposture](https://github.com/cposture), [ideas4u](https://github.com/ideas4u) 校对：[wxy](https://github.com/wxy)

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


开发者的实用 Vim 插件（二）

这个插件确实不错，很及时的发现编写错误。只是在低配置的机器上，这个插件太重，影响vim的编辑速度。

顶上的图片很漂亮啊，从哪里弄的？

专业搜图小能手就是我——秘籍一：请善用搜索引擎。

非常不错的插件。~\(≧▽≦)/~

毫无疑问，Vim 是一个开箱即用并能够胜任编程任务的编辑器，但实际上是该编辑器中的插件帮你实现这些方便的功能。在 [开发者的实用 Vim 插件（一）](/article-7901-1.html)，我们已经讨论两个编程相关的 Vim 插件——标签侧边栏（Tagbar）和定界符自动补齐（delimitMate）。作为相同系列，我们在本文讨论另一个非常有用、专门为软件开发正定制的插件——语法高亮插件。

![](/data/attachment/album/201610/28/163904kpp139uefxxm1xbx.jpg)

请注意：本教程中列举的所有例示、命令和说明都是在 Ubuntu 16.04 环境下进行测试的，并且，我们使用的 Vim 版本是 7.4。

### 语法高亮（Syntastic）插件

假如你的软件开发工作涉及到 C/C++ 语言，毫无疑问的说，遇到编译错误也是你每天工作中的一部分。很多时候，编译错误是由源代码之中的语法不正确造成的，因为开发者在浏览源码的时候很少能够一眼就看出所有这些错误。

那么 Vim 中是否存在一种插件可以让你不经编译源码就可以显示出语法错误呢？当然是有这样一种插件的，其名字就是 Syntastic。

“Syntastic 是 Vim 用来检验语法的插件，通过外部语法校验器校验文件并将错误呈现给用户。该过程可以在需要时进行，或者在文件保存的时候自动进行。”该插件 [官方文档](https://github.com/scrooloose/syntastic) 如是说。“如果检测到语法错误就会提示用户，因为不用编译代码或者执行脚本就可以知道语法错误，用户也就乐享与此了。”

安装过程和第一部分提到的方法类似，你只需要运行下列命令即可：

```
cd ~/.vim/bundle/

git clone https://github.com/scrooloose/syntastic.git

```

一旦你成功安装这个插件（即上述命令执行成功），你就不需要进行任何配置了——当 Vim 启动时会自动加载这个插件。

现在，打开一个源码文件并用 `:w` Vim 命令保存即可使用这个插件了。等待片刻之后，如果在源码中有语法错误的好，就会高亮显示出来。比如，看看一下截图你就会明白该插件是如何高亮显示语法错误的：

![Vim Syntax error highlighting](/data/attachment/album/201610/28/163933wdt2t35qoq50l2r2.png)

在每行之前的 `>>` 表示该行中有语法错误。了解确切的错误或者想知道是什么东西错了，将光标移到该行——错误描述就会展示在 Vim 窗口的最底下。

![View Syntax errors in Vim](/data/attachment/album/201610/28/163934o9gu0urhpgulxfi0.png)

这样，不用进行编译你就能够修复大多数语法相关的错误。

再往下，如果你运行 `:Errors` 命令，就会展现当前源文件中所有语法相关错误的描述。比如，我运行 `:Errors` 命令就是下图的效果：

![Syntastic :Errors command](/data/attachment/album/201610/28/163934ci5vvn3vomh9nnzb.png)

请记住，`:Errors` 展现的语法错误是不会自动更新的，这意味着在你修复错误之后，你需要重新运行 `:Errors` 命令，编辑器底部的错误描述才会消除。

值得一提的是，还有 [许多配置选项](https://github.com/scrooloose/syntastic/blob/master/doc/syntastic.txt) 能够使得 Syntastic 插件使用起来更加友好。比如，你可以在你的 `.vimrc` 中添加下列内容，然后 `:Errors` 就可以在修复错误之后自动更新它的底部描述。

```
let g:syntastic_always_populate_loc_list = 1

```

添加以下内容，以确保在你打开文件时 Syntastic 插件自动高亮显示错误。

```
let g:syntastic_check_on_open = 1

```

类似的，你也可以在保存或打开文件时让光标跳转到检测到的第一个问题处，将下列行放到你的 `.vimrc` 文件之中：

```
let g:syntastic_auto_jump = 1

```

这个值也可以指定为其它两个值： 2 和 3，其官方文档的解释如下：

“如果设置为 2 的话，光标就会跳到检测到的第一个问题，当然，只有这个问题是一个错误的时候才跳转；设置为 3 的话，如果存在错误，则会跳到第一个错误。所有检测到的问题都会有警告，但光标不会跳转。”

以下信息可能对你有帮助：

“使用 `:SyntasticCheck` 来手动检测错误。使用 `:Errors` 打开错误位置列表并使用 `:lclose` 来关闭。使用 `:SyntasticReset` 可以清除掉错误列表，使用 `:SyntasticToggleMode` 来切换激活（在写到 buffer 时检测）和被动（即手动检测）检测错误。”

注意：Syntastic 并不局限于 C/C++ 所写的代码，它同时也支持很多的编程语言——点击 [此处](https://github.com/scrooloose/syntastic) 了解更多相关信息。

### 结论

毫无疑问的，Syntastic 是一个非常有用的 Vim 插件，因为在出现语法相关错误时候，它至少能够让免去频繁编译的麻烦，而且不用说，同时也节约了你不少的时间。

正如你所看到的一样，配置好几个主要选项之后，Syntastic 变得非常好用了。为了帮助你了解这些设置，官方文档中包含了一份“推荐设置”——跟着文档进行设置即可。加入你遇到一些错误、有些疑问或者问题，你也可以查询一下 FAQ。

---

via: <https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-2-syntastic/>

作者：[Ansh](https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-2-syntastic/) 译者：[GHLandy](https://github.com/GHLandy) 校对：[wxy](https://github.com/wxy)

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


7 个 Linux 新手容易犯的错误

这些都不算什么，最可怕的还是墨守陈规，不敢尝试linux。此情况下，说什么都是0。

错误0：买了个双显卡的笔记本

错误-1：啊！这是DOS！

错误-2：这评论一排windows10用户。

错误

最尴尬的是，这样的linux文章，发表评论的都是windows用户～～～

其实最难的是迈出第一步，我帮很多朋友安装的了双系统，其中不乏程序猿，最终的结果是10个能有一个坚持下来就不错，大多数的理由都是没有QQ，没有LOL，Linux成了摆设，Linux的优势大家都知道，但是我实在是很难说服他们继续使用，真是太尴尬了。。。

错误－3，我看到公司里一堆在虚拟机里装ubuntu的

如果是纯技术宅的话，Linux 是不二的选择。只是大多数人都有其它的需求，所以 Linux 可能不是很适合那些人。

也许这是公司的电脑呢 233

已经用纯linux两年了

只在虚拟机里跑，算不算伪爱？

玩游戏的时候才想进win...

想试一试双系统

Charmony [Internet Explorer 10.0|Windows 7]

伪爱

不要尝试了，双系统没意思

我觉得在虚拟机中过渡比较好  纯属猎奇使用linux桌面不会长久  长期使用linux桌面肯定要打造一个满足日常或工作 并且相对稳定高效的系统  这个过程会很折腾   在1个虚拟机尝试安装配置所需软件  并做好文档记录   然后在另1台虚拟机中把经过验证可用的软件安装上 平时就在这台虚拟机中使用  除了必要的安全更新  避免频繁升级系统  这个想法源于git  多个虚拟机好比feature、develop、release和master分支  过程有些繁琐  但是一个有效过渡到linux桌面的方法

![](/data/attachment/album/201610/30/131514eae5ql6xcfcvvlqy.jpg)

换操作系统对每个人来说都是一件大事——尤其是许多用户根本不清楚操作系统是什么。

然而，从 Windows 切换到 Linux 特别地困难。这两个操作系统有着不同的前提和优先级，以及不同的处理方式。结果导致 Linux 新手容易混淆，因为他们在 Windows 上面得到经验不再适用。

例如，这里有 7 个 Windows “难民”开始使用 Linux 的时候会犯的错误（没有先后顺序）：

### 7. 选择错误的 Linux 发行版

Linux 有几百个不同的版本，或者按他们的称呼叫做<ruby> 发行版 <rp>  （ </rp> <rt>  distribution </rt> <rp>  ） </rp></ruby>。其中许多是专门针对不同的版本或用户的。选择了错误的版本，你与 Linux 的第一次亲密体验将很快变成一个噩梦。

如果你是在朋友的帮助下切换的话，确认他们的建议是适合你，而不是他们。有大量的文章可以帮助到你，你只需要关注前 20 名左右的或者列在 [Distrowatch](http://distrowatch.com/) 的即可，就不太可能会搞错。

更好的做法是，在你安装某个发行版之前先试试它的 [Live DVD](https://en.wikipedia.org/wiki/Live_CD)。Live DVD 是在外设上运行发行版的，这样可以允许你在不对硬盘做任何改动的情况下对其进行测试。事实上，除非你知道怎么让硬盘在 Linux 下可访问，否则你是不会看到你的硬盘的。

### 6. 期待什么都是一样的

由于经验有限，许多 Windows 用户不知道新的操作系统意味着新的程序和新的处理方式。事实上你的 Windows 程序是无法在 Linux 上运行的，除非你用 [WINE](https://en.wikipedia.org/wiki/Wine_%28software%29) 或者 Windows 虚拟机。而且你还不能用 MS Office 或者 PhotoShop —— 你必须要学会使用 LibreOffice 和 Krita。经过这些年，这些应用可能会有和 Windows 上的应用类似的功能，但它们的功能可能具有不同的名称，并且会从不同的菜单或工具栏获得。

就连很多想当然的都不一样了。Windows 用户会特别容易因为他们有多个桌面环境可以选择而大吃一惊——至少有一个主要的和很多次要的桌面环境。

### 5. 安装软件的时候不知所措

在 Windows 上，新软件是作为一个完全独立的程序来安装的。通常它囊括了其它所需的依赖库。

有两种叫做 [Flatpak](http://flatpak.org/) 和 [Snap](http://snapcraft.io/) 的软件包服务目前正在 Linux 上引进类似的安装系统，但是它们对于移动设备和嵌入式设备来说太大了。更多情况下，Linux 依赖于包管理系统，它会根据已安装的包来判断软件的依赖包是否是必需的，从而提供其它所需的依赖包。

笔记本和工作站上的包管理本质上相当于手机或平板电脑上的 Google Play：它速度很快，并且不需要用于安装的物理介质。不仅如此，它还可以节省 20%-35% 的硬盘空间，因为依赖包不会重复安装。

### 4. 假想软件会自动更新好

Linux 用户认为控制权很重要。Linux 提供更新服务，不过默认需要用户手动运行。例如，大多数发行版会让你知道有可用的软件更新，但是你需要选择安装这些更新。

如果你选择更新的话，你甚至可以单独决定每一个更新。例如，你可能不想更新到新的内核，因为你安装了一些东西需要使用当前的内核。又或者你想要安装所有的安全性更新，但不想把发行版更新到一个新的版本。一切都由你来选择。

### 3. 忘记密码

许多 Windows 用户因为登录不方便而忘记密码。又或者为了方便起见，经常运行一个管理账户。

在 Linux 上这两种做法都不容易。许多发行版使用 [sudo](https://en.wikipedia.org/wiki/Sudo) 来避免以 root 登录，特别是那些基于 Ubuntu 的发行版，而其它发行版大多数是安装为禁止 root 运行图形界面。但是，如果你在 Linux 上成功绕开了这些限制，请注意你的大部分 Linux 安全性优势都会无效（其实在 Windows 上也不推荐这样做）。

对了，你是不是在安装程序上看到一个自动登录的选项？那是在不常用的情景下使用的，例如不包含隐私信息的虚拟机。

### 2. 担心没有碎片整理和杀毒软件

Linux 偶尔需要进行碎片整理，不过只有在恢复分区或者分区差不多满了的时候。并且由于固态硬盘越来越火，碎片整理正在变成过去时，尽管固态硬盘确实需要在任何操作系统上定期运行 [trim](https://en.wikipedia.org/wiki/Trim_%28computing%29)。

同样地，只有当你安装的 Linux 经常传输文件给 Windows 机器的时候，杀毒软件才是一个主要问题。很少有 Linux 病毒或恶意软件存在，并且日常使用非 root 用户、使用强密码、经常备份当前文件就已经足够阻止病毒了。

### 1. 认为自己没有软件可用

Windows 上的软件是收费的，大多数类别由一家公司独占——例如，办公套装 MS Office 以及图形和设计的 Adobe。这些条件鼓励用户坚持使用相同的应用程序，尽管它们错漏百出。

在 Linux 上，故事情节不一样了。只有少数高端程序是收费的，而且几乎每一类软件都有两三个替代品，所有这些可用的软件都可以在 10 分钟或者更短的时间内下载好。如果一个替代品不合你口味，你可以删掉它然后毫不费力就可以再装一个其它的。在 Linux 上，你几乎总会有选择。

### 过渡期

可能没有那么多建议可以让 Windows 用户充分准备好切换到 Linux。即使说新用户应该保持开放的心态也是没什么用的，因为他们的期望总是太高，以至于许多用户都没有意识到自己有如此高的期望。

Linux 新手可以做的最好的事情就是调整心态，并且花一点时间来适应它们。过渡期会需要一些功夫，不过，从长远来看，你的多次尝试终会得到回报。

---

via: <http://www.datamation.com/open-source/7-mistakes-new-linux-users-make.html>

作者：[Bruce Byfield](http://www.datamation.com/author/Bruce-Byfield-6030.html) 译者：[OneNewLife](https://github.com/OneNewLife) 校对：[wxy](https://github.com/wxy)

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


科学音频处理（三）：如何使用 Octave 的高级数学技术处理音频文件

Summary: 我们的数字音频处理技术第三部分涵盖了信号调制内容，将解释如何进行调幅（Amplitude Modulation）、颤音效果（Tremolo Effect）和频率变化（Frequency Variation）。

dsfs

我们的数字音频处理技术第三部分涵盖了信号调制内容，将解释如何进行<ruby> 调幅 <rp>  （ </rp> <rt>  Amplitude Modulation </rt> <rp>  ） </rp></ruby>、<ruby> 颤音效果 <rp>  （ </rp> <rt>  Tremolo Effect </rt> <rp>  ） </rp></ruby>和<ruby> 频率变化 <rp>  （ </rp> <rt>  Frequency Variation </rt> <rp>  ） </rp></ruby>。

![](/data/attachment/album/201610/30/135341z7x6diiio7orkdog.jpg)

### 调制

#### 调幅

正如它的名字暗示的那样， 影响正弦信号的振幅变化依据传递的信息而不断改变。正弦波因为承载着大量的信息被称作<ruby> 载波 <rp>  （ </rp> <rt>  carrier </rt> <rp>  ） </rp></ruby>。这种调制技术被用于许多的商业广播和市民信息传输波段（AM）。

#### 为何要使用调幅技术？

**调制发射**

假设信道是免费资源，有天线就可以发射和接收信号。这要求有效的电磁信号发射天线，它的大小和要被发射的信号的波长应该是同一数量级。很多信号，包括音频成分，通常在 100 赫兹或更低。对于这些信号，如果直接发射，我们就需要建立长达 300 公里的天线。如果通过信号调制将信息加载到 100MHz 的高频载波中，那么天线仅仅需要 1 米（横向长度）。

**集中调制与多通道**

假设多个信号占用一个通道，调制可以将不同的信号不同频域位置，以便接收者选择该特定信号。使用集中调制（“复用”）的应用有遥感探测数据、立体声调频收音机和长途电话等。

**克服设备限制的调制**

信号处理设备，比如过滤器、放大器，以及可以用它们简单组成的设备，它们的性能依赖于信号在频域中的境况以及高频率和低频信号的关系。调制可以用于传递信号到频域中的更容易满足设计需求的位置。调制也可以将“宽带信号“（高频和低频的比例很大的信号）转换成”窄带“信号。

**音频特效**

许多音频特效由于引人注目和处理信号的便捷性使用了调幅技术。我们可以说出很多，比如颤音、合唱、镶边等等。这种实用性就是我们关注它的原因。

### 颤音效果

颤音效果是调幅最简单的应用，为实现这样的效果，我们会用周期信号改变（乘）音频信号，使用正弦或其他。

```
>> tremolo='tremolo.ogg';
>> fs=44100;
>> t=0:1/fs:10;
>> wo=2*pi*440*t;
>> wa=2*pi*1.2*t;
>> audiowrite(tremolo, cos(wa).*cos(wo),fs);

```

![Tremolo](/data/attachment/album/201610/30/135359izvjvv5vxuoqv1vo.png)

这将创造一个正弦形状的信号，它的效果就像‘颤音’。

![Tremolo Shape](/data/attachment/album/201610/30/135402zgdkml8fg9alf8f0.png)

### 在真实音频文件中的颤音

现在我们将展示真实世界中的颤音效果。首先，我们使用之前记录过男性发声 ‘A’ 的音频文件。这个信号图就像下面这样：

```
>> [y,fs]=audioread('A.ogg');
>> plot(y);

```

![Vocal](/data/attachment/album/201610/30/135405t9h99c7qhnqcbon7.png)

现在我们将创建一个完整的正弦信号，使用如下的参数：

* 增幅 = 1
* 频率= 1.5Hz
* 相位 = 0

```
>> t=0:1/fs:4.99999999;
>> t=t(:);
>> w=2*pi*1.5*t;
>> q=cos(w);
>> plot(q);

```

注意： 当我们创建一组时间值时，默认情况下，它是以列的格式呈现，如, 1x220500 的值。为了乘以这样的值，必须将其变成行的形式（220500x1）。这就是 `t=t(:)` 命令的作用。

![Sinusodial](/data/attachment/album/201610/30/135406adpz3zei2e0dte18.png)

我们将创建第二份 ogg 音频格式的文件，它包含了如下的调制信号：

```
>> tremolo='tremolo.ogg';
>> audiowrite(tremolo, q.*y,fs);

```

![](/data/attachment/album/201610/30/135409pqw9w9nfn1rmkafn.png)

![Tremolo Signal](/data/attachment/album/201610/30/135412tgemjrmmjp78mkbo.png)

### 频率变化

我们可以改变频率实现一些有趣的音效，比如原音变形，电影音效，多人比赛。

#### 正弦频率调制的影响

这是正弦调制频率变化的演示代码，根据方程：

```
Y=Ac*Cos(wo*Cos(wo/k))

```

这里：

* Ac = 增幅
* wo = 基频
* k = 标量除数

```
>> fm='fm.ogg';
>> fs=44100;
>> t=0:1/fs:10;
>> w=2*pi*442*t;
>> audiowrite(fm, cos(cos(w/1500).*w), fs);
>> [y,fs]=audioread('fm.ogg');
>> figure (); plot (y);

```

信号图：

![](/data/attachment/album/201610/30/135418dp1pa696npwnle6z.png)

你可以使用几乎任何类型的周期函数频率调制。本例中，我们仅仅用了一个正弦函数。请大胆的改变函数频率，用复合函数，甚至改变函数的类型。

---

via: <https://www.howtoforge.com/tutorial/ubuntu-octave-audio-processing-part-3/>

作者：[David Duarte](https://www.howtoforge.com/tutorial/ubuntu-octave-audio-processing-part-3/) 译者：[theArcticOcean](https://github.com/theArcticOcean) 校对：[wxy](https://github.com/wxy)

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


Linux 桌面份额连续四个月超过 2%

Summary: 我们之前报道过，今年六月份时 Linux 桌面的市场份额首次突破了 2%，并于次月达到了历史最高点 2.33%。

不管怎么样,linux有增长就好

大快人心

我新电脑用的ubuntu,放弃了下片啊

win10是有史以来最糟糕的体验，不停的更新升级稳定性却一点都不在。希望Linux的应用能追赶的快点

呵呵

Ubuntu14.04 Server版配gnome3.9的桌面用户发来贺电

不管怎么样,linux有增长就好

一个台式机，一个笔记本加公司一台电脑，我一个人贡献个3个。

国内软件是硬伤，可以deepin做的比较好点，可是还是有些软件没有啊。比如ps，AUTOcad等特别专业的软件，几乎都必须有windows和mac

在公司为了和同事统一环境 ，用的windows, 回家用我的linux desktop

国内实用性软件还是太少呀

试试

太不容易了～ 虽然我在虚拟机跑！

看着好心酸的数据， 2%...

有我的贡献 哈哈

这是国际上的数据吧，国内的远低于这个值的，关键就是应用，你看看linux应用程序，哪个不是国外（国外开源项目）的？

good

哥一个人虚拟机跑了6个，物理硬盘装了双linux，不说了，信仰啊！

心酸...

我笔记本是双系统，xubuntu + Windows ，只有工作才会用windows

[据 Net Market Share 的数据](https://www.netmarketshare.com/report.aspx?qprid=11&qpaf=&qpcustom=Linux&qpcustomb=0)，全球的 Linux 桌面用户的份额已经连续四个月超过了 2% 。

![](/data/attachment/album/201610/30/191917wke674bb417nz4n4.jpg)

我们之前报道过，今年六月份时 Linux 桌面的市场份额[首次突破了 2%](/article-7538-1.html)，并于次月达到了历史最高点 2.33%。

那些将 Linux 作为主要桌面的用户们为这个份额做出了贡献。显然，从 这个图表的趋势来看，使用 Linux 作为桌面的用户越来越多了。

不过，不同的分析公司由于采样范围和分析方法的不同，其报告的数据、图表会有些不同，但是从总体的趋势来看，都是呈现向上增长的。

Net Market Share 的报告是基于全球 4 万个网站的访客得出的，4 万个网站也是一个比较大的数量了，当然，与整个互联网相比还是较小。

事实上，我们并不能真正摸清 Linux 具体的市场份额，因为有太多的发行版、内核版本和浏览器了，而且有些专门在隐私保护方面做了不少的工作，因此这部分我们的采集不到的。


Python 单元测试：assertTrue 是真值，assertFalse 是假值

Summary: ，我们将介绍单元测试的布尔断言方法 assertTrue 和 assertFalse 与身份断言 assertIs 之间的区别。

在这篇文章中，我们将介绍单元测试的布尔断言方法 `assertTrue` 和 `assertFalse` 与身份断言 `assertIs` 之间的区别。

![](/data/attachment/album/201610/30/215451lzjhnhy8qquumq8n.jpg)

### 定义

下面是目前[单元测试模块文档](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue)中关于 `assertTrue` 和 `assertFalse` 的说明，代码进行了高亮：

>
> `assertTrue(expr, msg=None)`
>
>
> `assertFalse(expr, msg=None)`
>
>
>
> >
> > 测试该*表达式*是真值（或假值）。
> >
> >
> > 注：这等价于
> >
> >
> > `bool(expr) is True`
> >
> >
> > 而不等价于
> >
> >
> > `expr is True`
> >
> >
> > （后一种情况请使用 `assertIs(expr, True)`）。
> >
> >
> >
>
>
>

[Mozilla 开发者网络中定义 `真值`](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) 如下：

>
> 在一个布尔值的上下文环境中能变成“真”的值
>
>
>

在 Python 中等价于：

```
bool(expr) is True

```

这个和 `assertTrue` 的测试目的完全匹配。

因此该文档中已经指出 `assertTrue` 返回真值，`assertFalse` 返回假值。这些断言方法从接受到的值构造出一个布尔值，然后判断它。同样文档中也建议我们根本不应该使用 `assertTrue` 和 `assertFalse`。

### 在实践中怎么理解？

我们使用一个非常简单的例子 - 一个名称为 `always_true` 的函数，它返回 `True`。我们为它写一些测试用例，然后改变代码，看看测试用例的表现。

作为开始，我们先写两个测试用例。一个是“宽松的”：使用 `assertTrue` 来测试真值。另外一个是“严格的”：使用文档中建议的 `assertIs` 函数。

```
import unittest
from func import always_true

class TestAlwaysTrue(unittest.TestCase):
    def test_assertTrue(self):
        """
        always_true returns a truthy value
        """
        result = always_true()

        self.assertTrue(result)

    def test_assertIs(self):
        """
        always_true returns True
        """
        result = always_true()

        self.assertIs(result, True)

```

下面是 `func.py` 中的非常简单的函数代码：

```
def always_true():
    """
    I'm always True.

    Returns:
        bool: True
    """
    return True

```

当你运行时，所有测试都通过了：

```
always_true returns True ... ok
always_true returns a truthy value ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.004s

OK

```

开心ing~

现在，某个人将 `always_true` 函数改变成下面这样：

```
def always_true():
    """
    I'm always True.

    Returns:
        bool: True
    """
    return 'True'

```

它现在是用返回字符串 `"True"` 来替代之前反馈的 `True` （布尔值）。（当然，那个“某人”并没有更新文档 - 后面我们会增加难度。）

这次结果并不如开心了：

```
always_true returns True ... FAIL
always_true returns a truthy value ... ok

======================================================================
FAIL: always_true returns True
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/assertttt/test.py", line 22, in test_is_true
    self.assertIs(result, True)
AssertionError: 'True' is not True

----------------------------------------------------------------------
Ran 2 tests in 0.004s

FAILED (failures=1)

```

只有一个测试用例失败了！这意味着 `assertTrue` 给了我们一个<ruby> 误判 <rp>  （ </rp> <rt>  false-positive </rt> <rp>  ） </rp></ruby>。在它不应该通过测试时，它通过了。很幸运的是我们第二个测试是使用 `assertIs` 来写的。

因此，跟手册上了解到的信息一样，为了保证 `always_true` 的功能和更严格测试的结果保持一致，应该使用 `assertIs` 而不是 `assertTrue`。

### 使用断言的辅助方法

使用 `assertIs` 来测试返回 `True` 和 `False` 来冗长了。因此，如果你有个项目需要经常检查是否是返回了 `True` 或者 `False`，那们你可以自己编写一些断言的辅助方法。

这好像并没有节省大量的代码，但是我个人觉得提高了代码的可读性。

```
def assertIsTrue(self, value):
    self.assertIs(value, True)

def assertIsFalse(self, value):
    self.assertIs(value, False)

```

### 总结

一般来说，我的建议是让测试越严格越好。如果你想测试 `True` 或者 `False`，听从[文档](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue)的建议，使用 `assertIs`。除非不得已，否则不要使用 `assertTrue` 和 `assertFalse`。

如果你面对的是一个可以返回多种类型的函数，例如，有时候返回布尔值，有时候返回整形，那么考虑重构它。这是代码的异味。在 Python 中，抛出一个异常比使用 `False` 表示错误更好。

此外，如果你确实想使用断言来判断函数的返回值是否是真，可能还存在第二个代码异味 - 代码是正确封装了吗？如果 `assertTrue` 和 `assertFalse` 是根据正确的 `if` 语句来执行，那么值得检查下你是否把所有你想要的东西都封装在合适的位置。也许这些 `if` 语句应该封装在测试的函数中。

测试开心！

---

via: <http://jamescooke.info/python-unittest-asserttrue-is-truthy-assertfalse-is-falsy.html>

作者：[James Cooke](http://jamescooke.info/pages/hello-my-name-is-james.html) 译者：[chunyang-wen](https://github.com/chunyang-wen) 校对：[wxy](https://github.com/wxy)

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


在维基激动人心的四年

Summary: 我对维基的爱从我第 10 次考试（像在美国的 10 年级学生的年级考试）之后看到的英文维基文章孟加拉解放战争开始

我居然看完了……

![](/data/attachment/album/201610/30/234329kt15dpfzaztpotz3.jpg)

我自认为自己是个奥迪亚的维基人。我通过写文章和纠正文章错误给很多维基项目贡献了<ruby> <a href="https://en.wikipedia.org/wiki/Odia_language">  奥迪亚 </a> <rp>  （ </rp> <rt>  Odia </rt> <rp>  ） </rp></ruby>知识（这是在印度的[奥里萨邦](https://en.wikipedia.org/wiki/Odisha)的主要语言），比如维基百科和维基文库，我也为用印地语和英语写的维基文章做贡献。

![](/data/attachment/album/201610/30/234329s6mi0muyzu2edtmy.jpg)

我对维基的爱从我第 10 次考试（像在美国的 10 年级学生的年级考试）之后看到的英文维基文章[孟加拉解放战争](https://en.wikipedia.org/wiki/Bangladesh_Liberation_War)开始。一不小心我打开了印度维基文章的链接，并且开始阅读它。在文章左边有用奥迪亚语写的东西，所以我点击了一下, 打开了一篇在奥迪亚维基上的 [ଭାରତ/Bhārat](https://or.wikipedia.org/s/d2) 文章。发现了用母语写的维基让我很激动！

![](/data/attachment/album/201610/30/234330b6ogygzt1ay1xbz1.png)

一个邀请读者参加 2014 年 4 月 1 日召开的第二届布巴内斯瓦尔研讨会的旗帜广告引起了我的好奇。我过去从来没有为维基做过贡献，只用它做过研究，我并不熟悉开源和社区贡献流程。再加上，当时我只有 15 岁。我注册了，在研讨会上有很多语言爱好者，他们全比我大。尽管我害怕，我父亲还是鼓励我去参与。他起了非常重要的作用—他不是一个维基媒体人，和我不一样，但是他的鼓励给了我改变奥迪亚维基的动力和参加社区活动的勇气。

我觉得关于奥迪亚语言和文学的知识很多需要改进，有很多错误的观念和知识缺口，所以，我帮助组织关于奥迪亚维基的活动和和研讨会，我完成了如下列表：

* 在奥迪亚维基发起 3 次主要的 edit-a-thons ：2015 年妇女节、2016年妇女节、abd [Nabakalebara edit-a-thon 2015](https://or.wikipedia.org/s/toq)
* 在全印度发起了征集[檀车节](https://commons.wikimedia.org/wiki/Commons:The_Rathyatra_Challenge)图片的比赛
* 在谷歌的两大事件（[谷歌I/O大会扩展](http://cis-india.org/openness/blog-old/odia-wikipedia-meets-google-developer-group)和谷歌开发节）中代表奥迪亚维基
* 在2015 [Perception](http://perception.cetb.in/events/odia-wikipedia-event/) 和第一次 [Open Access India](https://opencon2015kolkata.sched.org/speaker/sailesh.patnaik007) 会议

![](/data/attachment/album/201610/30/234330gkxp3tyzrrpmuy51.jpg)

我在维基项目当编辑直到去年（ 2015 年 1 月）为止，当我出席[孟加拉语维基百科的十周年会议](https://meta.wikimedia.org/wiki/Bengali_Wikipedia_10th_Anniversary_Celebration_Kolkata)和[毗瑟挐](https://www.facebook.com/vishnu.vardhan.50746?fref=ts)活动时，[互联网和社会中心](http://cis-india.org/)主任，邀请我参加[培训师培训计划](https://meta.wikimedia.org/wiki/CIS-A2K/Events/Train_the_Trainer_Program/2015)。我的开始超越奥迪亚维基，为[GLAM](https://en.wikipedia.org/wiki/Wikipedia:GLAM)的活动举办聚会和培训新的维基人。这些经验告诉我作为一个贡献者该如何为社区工作。

[Ravi](https://www.facebook.com/ravidreams?fref=ts)，在当时印度维基的总监，在我的旅程也发挥了重要作用。他非常相信我，让我参与到了 [Wiki Loves Food](https://commons.wikimedia.org/wiki/Commons:Wiki_Loves_Food)，维基共享中的公共摄影比赛，组织方是 [2016 印度维基会议](https://meta.wikimedia.org/wiki/WikiConference_India_2016)。在 2015 的 Loves Food 活动期间，我的团队在维基共享中加入了 10000+ 采用 CC BY-SA 协议的图片。Ravi 进一步坚定了我的信心，和我分享了很多关于维基媒体运动的信息，以及他自己在 [奥迪亚维基百科 13 周年](https://or.wikipedia.org/s/sml)的经历。

不到一年后，在 2015 年十二月，我成为了网络与社会中心的[获取知识计划](https://meta.wikimedia.org/wiki/CIS-A2K)的项目助理（ CIS-A2K 运动）。我自豪的时刻之一是在印度普里的研讨会，我们给奥迪亚维基媒体社区带来了 20 个新的维基人。现在，我在一个名为 [WikiTungi](https://or.wikipedia.org/s/xgx) 普里的非正式聚会上指导着维基人。我和这个小组一起工作，把奥迪亚 Wikiquotes 变成一个真实的计划项目。在奥迪亚维基我也致力于缩小性别差距。[八个女编辑](https://or.wikipedia.org/s/ysg)也正帮助组织聚会和研讨会，参加 [Women's History month edit-a-thon](https://or.wikipedia.org/s/ynj)。

在我四年短暂而令人激动的旅行之中，我也参与到 [维基百科的教育项目](https://outreach.wikimedia.org/wiki/Education)，[通讯团队](https://outreach.wikimedia.org/wiki/Talk:Education/News#Call_for_volunteers)，两个全球的 edit-a-thons： [Art and Feminsim](https://en.wikipedia.org/wiki/User_talk:Saileshpat#Barnstar_for_Art_.26_Feminism_Challenge) 和 [Menu Challenge](https://opensource.com/life/15/11/tasty-translations-the-open-source-way)。我期待着更多的到来！

我还要感谢 [Sameer](https://www.facebook.com/samirsharbaty?fref=ts) 和 [Anna](https://www.facebook.com/anna.koval.737?fref=ts)（都是之前维基百科教育计划的成员）。

---

via: <https://opensource.com/life/16/4/my-open-source-story-sailesh-patnaik>

作者：[Sailesh Patnaik](https://opensource.com/users/saileshpat) 译者：[hkurj](https://github.com/hkurj) 校对：[wxy](https://github.com/wxy)

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


如何在后台运行 Linux 命令并且将进程脱离终端

Summary:
当一个进程与终端关联在一起时，可能会出现两种问题：
- 你的控制终端充满了很多输出数据或者错误及诊断信息；
- 如果发生终端关闭的情况，进程连同它的子进程都将会终止。

记得以前在vps上使用nohup+aria2c下载bt种子，nohup还会把程序打印的内容保存到文本文件。如此一来，就可以通过本地浏览器直接查看输出了，很方便。

当然，如果你觉得该文本文件的内容太多，拖慢浏览器速度，可以写个php，只读取尾部50行这样的功能，如此一来，简直比迅雷离线下载还给力。

牛逼，还有这种操作

牛逼，还有这种操作

在本指南中，我们将会阐明一个在 [Linux 系统中进程管理](http://www.tecmint.com/monitor-linux-processes-and-set-process-limits-per-user/)的简单但是重要的概念，那就是如何从它的控制终端完全脱离一个进程。

当一个进程与终端关联在一起时，可能会出现两种问题：

1. 你的控制终端充满了很多输出数据或者错误及诊断信息
2. 如果发生终端关闭的情况，进程连同它的子进程都将会终止

为了解决上面两个问题，你需要从一个控制终端完全脱离一个进程。在我们实际上解决这个问题之前，让我们先简要的介绍一下，如何在后台运行一个进程。

![](/data/attachment/album/201611/01/081944jrc87qz7ryzfjfzc.jpg)

### 如何在后台开始一个 Linux 进程或者命令行

如果一个进程已经运行，例如下面的 [tar 命令行的例子](/article-7802-1.html)，简单的按下 `Ctrl+Z` 就可以停止它（LCTT 译注：这里说的“停止”，不是终止，而是“暂停”的意思），然后输入命令 `bg` 就可以继续以一个任务在后台运行了。

你可以通过输入 `jobs` 查看所有的后台任务。但是，标准输入（STDIN）、标准输出（STDOUT）和标准错误（STDERR）依旧掺杂到控制台中。

```
$ tar -czf home.tar.gz .
$ bg
$ jobs
```

![](/data/attachment/album/201611/01/082404gmdvzdfxdbnmnzls.png "在后台运行 Linux 命令")

*在后台运行 Linux 命令*

你也可以直接使用符号 `&` 在后台运行一个进程：

```
$ tar -czf home.tar.gz . &
$ jobs
```

![](/data/attachment/album/201611/01/082404zrr8jd48daxp5wkh.png "在后台开始一个 Linux 进程")

*在后台开始一个 Linux 进程*

看一下下面的这个例子，虽然 [tar 命令](/article-7802-1.html)是作为一个后台任务开始的，但是错误信息依旧发送到终端，这表示，进程依旧和控制终端关联在一起。

```
$ tar -czf home.tar.gz . &
$ jobs
```

![](/data/attachment/album/201611/01/082405gim90e9f0uu7z3aa.png "运行在后台的 Linux 进程信息")

*运行在后台的 Linux 进程信息*

### 退出控制台之后，保持 Linux 进程的运行

我们将使用 `disown` 命令，它在一个进程已经运行并且被放在后台之后使用，它的作用是从 shell 的活动任务列表中移走一个 shell 任务，因此，对于该任务，你将再也不能使用 `fg` 、 `bg` 命令了。

而且，当你关闭控制控制终端，这个任务将不会挂起（暂停）或者向任何一个子任务发送 SIGHUP 信号。

让我们看一下先下面的这个使用 bash 中内置命令 `disown` 的例子。

```
$ sudo rsync Templates/* /var/www/html/files/ &
$ jobs
$ disown  -h  %1
$ jobs
```

![](/data/attachment/album/201611/01/082405d9ifmh0s4fm5d99g.png "关闭终端之后，保持 Linux 进程运行")

*关闭终端之后，保持 Linux 进程运行*

你也可以使用 `nohup` 命令，这个命令也可以在用户退出 shell 之后保证进程在后台继续运行。

```
$ nohup tar -czf iso.tar.gz Templates/* &
$ jobs
```

![](/data/attachment/album/201611/01/082406s9b88jmjpd93fov8.png "关闭 shell 之后把 Linux 进程置于后台")

*关闭 shell 之后把 Linux 进程置于后台*

### 从控制终端脱离一个 Linux 进程

因此，为了彻底从控制终端脱离一个程序，对于图形用户界面 (GUI) 的程序例如 firefox 来说，使用下面的命令行格式会更有效：

```
$ firefox </dev/null &>/dev/null &
```

在 Linux 上，/dev/null 是一个特殊的文件设备，它会忽略所有的写在它上面的数据，上述命令，输入来源和输出发送目标都是 /dev/null。

作为结束陈述，运行一个连接到控制终端的进程，作为用户你将会在你的终端上看到这个进程数据的许多行的输出，也包含错误信息。同样，当你关闭一个控制终端，你的进程和子进程都将会终止。

重要的是，对于这个主题任何的问题或者观点，通过下面的评论联系我们。

---

via: <http://www.tecmint.com/run-linux-command-process-in-background-detach-process/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[yangmingming](https://github.com/yangmingming) 校对：[wxy](https://github.com/wxy)

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