diff --git a/published/20160518 Cleaning Up Your Linux Startup Process.md b/published/20160518 Cleaning Up Your Linux Startup Process.md
new file mode 100644
index 0000000000..b4f8c3d02d
--- /dev/null
+++ b/published/20160518 Cleaning Up Your Linux Startup Process.md
@@ -0,0 +1,145 @@
+Linux 系统开机启动项清理
+=======
+
+
+
+一般情况下,常规用途的 Linux 发行版在开机启动时拉起各种相关服务进程,包括许多你可能无需使用的服务,例如蓝牙、Avahi、 调制解调管理器、ppp-dns(LCTT 译注:此处作者笔误 ppp-dns 应该为 pppd-dns) 等服务进程,这些都是什么东西?用于哪里,有何功能?
+
+Systemd 提供了许多很好的工具用于查看系统启动情况,也可以控制在系统启动时运行什么。在这篇文章中,我将说明在 Systemd 类发行版中如何关闭一些令人讨厌的进程。
+
+### 查看开机启动项
+
+在过去,你能很容易通过查看 `/etc/init.d` 了解到哪些服务进程会在引导时启动。Systemd 以不同的方式展现,你可以使用如下命令罗列允许开机启动的服务进程。
+
+```
+$ systemctl list-unit-files --type=service | grep enabled
+accounts-daemon.service enabled
+anacron-resume.service enabled
+anacron.service enabled
+bluetooth.service enabled
+brltty.service enabled
+[...]
+```
+
+在此列表顶部,对我来说,蓝牙服务是冗余项,因为在该电脑上我不需要使用蓝牙功能,故无需运行此服务。下面的命令将停止该服务进程,并且使其开机不启动。
+
+```
+$ sudo systemctl stop bluetooth.service
+$ sudo systemctl disable bluetooth.service
+```
+
+你可以通过下面命令确定是否操作成功。
+
+```
+$ systemctl status bluetooth.service
+ bluetooth.service - Bluetooth service
+ Loaded: loaded (/lib/systemd/system/bluetooth.service; disabled; vendor preset: enabled)
+ Active: inactive (dead)
+ Docs: man:bluetoothd(8)
+```
+
+停用的服务进程仍然能够被另外一个服务进程启动。如果你真的想在任何情况下系统启动时都不启动该进程,无需卸载该它,只需要把它掩盖起来就可以阻止该进程在任何情况下开机启动。
+
+```
+$ sudo systemctl mask bluetooth.service
+ Created symlink from /etc/systemd/system/bluetooth.service to /dev/null.
+```
+
+一旦你对禁用该进程启动而没有出现负面作用感到满意,你也可以选择卸载该程序。
+
+通过执行命令可以获得如下服务列表:
+
+```
+$ systemctl list-unit-files --type=service
+UNIT FILE STATE
+accounts-daemon.service enabled
+acpid.service disabled
+alsa-restore.service static
+alsa-utils.service masked
+```
+
+你不能启用或禁用静态服务,因为静态服务被其他的进程所依赖,并不意味着它们自己运行。
+
+### 哪些服务能够禁止?
+
+如何知道你需要哪些服务,而哪些又是可以安全地禁用的呢?它总是依赖于你的个性化需求。
+
+这里举例了几个服务进程的作用。许多服务进程都是发行版特定的,所以你应该看看你的发行版文档(比如通过 google 或 StackOverflow)。
+
+- **accounts-daemon.service** 是一个潜在的安全风险。它是 AccountsService 的一部分,AccountsService 允许程序获得或操作用户账户信息。我不认为有好的理由能使我允许这样的后台操作,所以我选择掩盖该服务进程。
+- **avahi-daemon.service** 用于零配置网络发现,使电脑超容易发现网络中打印机或其他的主机,我总是禁用它,别漏掉它。
+- **brltty.service** 提供布莱叶盲文设备支持,例如布莱叶盲文显示器。
+- **debug-shell.service** 开放了一个巨大的安全漏洞(该服务提供了一个无密码的 root shell ,用于帮助 调试 systemd 问题),除非你正在使用该服务,否则永远不要启动服务。
+- **ModemManager.service** 该服务是一个被 dbus 激活的守护进程,用于提供移动宽频(2G/3G/4G)接口,如果你没有该接口,无论是内置接口,还是通过如蓝牙配对的电话,以及 USB 适配器,那么你也无需该服务。
+- **pppd-dns.service** 是一个计算机发展的遗物,如果你使用拨号接入互联网的话,保留它,否则你不需要它。
+- **rtkit-daemon.service** 听起来很可怕,听起来像是 rootkit。 但是你需要该服务,因为它是一个实时内核调度器。
+- **whoopsie.service** 是 Ubuntu 错误报告服务。它用于收集 Ubuntu 系统崩溃报告,并发送报告到 https://daisy.ubuntu.com 。 你可以放心地禁止其启动,或者永久的卸载它。
+- **wpa_supplicant.service** 仅在你使用 Wi-Fi 连接时需要。
+
+### 系统启动时发生了什么?
+
+Systemd 提供了一些命令帮助调试系统开机启动问题。该命令会重演你的系统启动的所有消息。
+
+```
+$ journalctl -b
+
+-- Logs begin at Mon 2016-05-09 06:18:11 PDT,
+end at Mon 2016-05-09 10:17:01 PDT. --
+May 16 06:18:11 studio systemd-journal[289]:
+Runtime journal (/run/log/journal/) is currently using 8.0M.
+Maximum allowed usage is set to 157.2M.
+Leaving at least 235.9M free (of currently available 1.5G of space).
+Enforced usage limit is thus 157.2M.
+[...]
+```
+
+通过命令 `journalctl -b -1` 可以复审前一次启动,`journalctl -b -2` 可以复审倒数第 2 次启动,以此类推。
+
+该命令会打印出大量的信息,你可能并不关注所有信息,只是关注其中问题相关部分。为此,系统提供了几个过滤器,用于帮助你锁定目标。让我们以进程号为 1 的进程为例,该进程是所有其它进程的父进程。
+
+```
+$ journalctl _PID=1
+
+May 08 06:18:17 studio systemd[1]: Starting LSB: Raise network interfaces....
+May 08 06:18:17 studio systemd[1]: Started LSB: Raise network interfaces..
+May 08 06:18:17 studio systemd[1]: Reached target System Initialization.
+May 08 06:18:17 studio systemd[1]: Started CUPS Scheduler.
+May 08 06:18:17 studio systemd[1]: Listening on D-Bus System Message Bus Socket
+May 08 06:18:17 studio systemd[1]: Listening on CUPS Scheduler.
+[...]
+```
+
+这些打印消息显示了什么被启动,或者是正在尝试启动。
+
+一个最有用的命令工具之一 `systemd-analyze blame`,用于帮助查看哪个服务进程启动耗时最长。
+
+```
+$ systemd-analyze blame
+ 8.708s gpu-manager.service
+ 8.002s NetworkManager-wait-online.service
+ 5.791s mysql.service
+ 2.975s dev-sda3.device
+ 1.810s alsa-restore.service
+ 1.806s systemd-logind.service
+ 1.803s irqbalance.service
+ 1.800s lm-sensors.service
+ 1.800s grub-common.service
+```
+
+这个特定的例子没有出现任何异常,但是如果存在系统启动瓶颈,则该命令将能发现它。
+
+你也能通过如下资源了解 Systemd 如何工作:
+
+- [理解和使用 Systemd](https://www.linux.com/learn/understanding-and-using-systemd)
+- [介绍 Systemd 运行级别和服务管理命令](https://www.linux.com/learn/intro-systemd-runlevels-and-service-management-commands)
+- [再次前行,另一个 Linux 初始化系统:Systemd 介绍](https://www.linux.com/learn/here-we-go-again-another-linux-init-intro-systemd)
+
+----
+
+via: https://www.linux.com/learn/cleaning-your-linux-startup-process
+
+作者:[David Both](https://www.linux.com/users/cschroder)
+译者:[penghuster](https://github.com/penghuster)
+校对:[wxy](https://github.com/wxy)
+
+本文由 LCTT 原创编译,Linux中国 荣誉推出
diff --git a/published/20160815 Here are all the Git commands I used last week and what they do.md b/published/20160815 Here are all the Git commands I used last week and what they do.md
new file mode 100644
index 0000000000..da5520275c
--- /dev/null
+++ b/published/20160815 Here are all the Git commands I used last week and what they do.md
@@ -0,0 +1,196 @@
+一周工作所用的日常 Git 命令
+============================================================
+
+
+
+像大多数新手一样,我一开始是在 StackOverflow 上搜索 Git 命令,然后把答案复制粘贴,并没有真正理解它们究竟做了什么。
+
+
+
+*Image credit: [XKCD][7]*
+
+我曾经想过:“如果有一个最常见的 Git 命令的列表,以及它们的功能是什么,这不是极好的吗?”
+
+多年之后,我编制了这样一个列表,并且给出了一些最佳实践,让新手们甚至中高级开发人员都能从中发现有用的东西。
+
+为了保持实用性,我将这个列表与我过去一周实际使用的 Git 命令进行了比较。
+
+几乎每个开发人员都在使用 Git,当然很可能是 GitHub。但大多数开发者大概有 99% 的时间只是使用这三个命令:
+
+```
+git add --all
+git commit -am ""
+git push origin master
+```
+
+如果你只是单枪匹马,或者参加一场黑客马拉松或开发一次性的应用时,它工作得很好,但是当稳定性和可维护性开始成为一个优先考虑的事情后,清理提交、坚持分支策略和提交信息的规范性就变得很重要。
+
+我将从常用命令的列表开始,使新手更容易了解 Git 能做什么,然后进入更高级的功能和最佳实践。
+
+### 经常使用的命令
+
+要想在仓库(repo)中初始化 Git,你只需输入以下命令即可。如果你没有初始化 Git,则不能在该仓库内运行任何其他的 Git 命令。
+
+```
+git init
+```
+
+如果你在使用 GitHub,而且正在将代码推送到在线存储的 GitHub 仓库中,那么你正在使用的就是远程(remote)仓库。该远程仓库的默认名称(也称为别名)为 `origin`。如果你已经从 Github 复制了一个项目,它就有了一个 `origin`。你可以使用命令 `git remote -v` 查看该 `origin`,该命令将列出远程仓库的 URL。
+
+如果你初始化了自己的 Git 仓库,并希望将其与 GitHub 仓库相关联,则必须在 GitHub 上创建一个,复制新仓库提供的 URL,并使用 `git remote add origin ` 命令,这里使用 GitHub 提供的 URL 替换 ``。这样,你就可以添加、提交和推送更改到你的远程仓库了。
+
+最后一条命令用在当你需要更改远程仓库时。如果你从其他人那里复制了一个仓库,并希望将远程仓库从原始所有者更改为你自己的 GitHub 帐户。除了改用 `set-url` 来更改远程仓库外,流程与 `git remote add origin` 相同。
+
+```
+git remote -v
+git remote add origin
+git remote set-url origin
+```
+
+复制仓库最常见的方式是使用 `git clone`,后跟仓库的 URL。
+
+请记住,远程仓库将连接到克隆仓库原属于的帐户。所以,如果你克隆了一个属于别人的仓库,你将无法推送到 GitHub,除非你使用上面的命令改变了 `origin`。
+
+```
+git clone
+```
+
+你很快就会发现自己正在使用分支。如果你还不理解什么是分支,有许多其他更深入的教程,你应该先阅读它们,再继续下面的操作。([这里是一个教程][8])
+
+命令 `git branch` 列出了本地机器上的所有分支。如果要创建一个新的分支,可以使用命令 `git branch `,其中 `` 表示分支的名字,比如说 `master`。
+
+`git checkout ` 命令可以切换到现有的分支。你也可以使用 `git checkout -b` 命令创建一个新的分支并立即切换到它。大多数人都使用此命令而不是单独的 `branch` 和 `checkout` 命令。
+
+```
+git branch
+git branch
+git checkout
+git checkout -b
+```
+
+如果你对一个分支进行了一系列的更改,假如说此分支名为 `develop`,如果想要将该分支合并回主分支(`master`)上,则使用 `git merge ` 命令。你需要先检出(`checkout`)主分支,然后运行 `git merge develop` 将 `develop` 合并到主分支中。
+
+```
+git merge
+```
+
+如果你正在与多个人进行协作,你会发现有时 GitHub 的仓库上已经更新了,但你的本地却没有做相应的更改。如果是这样,你可以使用 `git pull origin ` 命令从远程分支中拉取最新的更改。
+
+```
+git pull origin
+```
+
+如果您好奇地想看到哪些文件已被更改以及哪些内存正在被跟踪,可以使用 `git status` 命令。如果要查看每个文件的更改,可以使用 `git diff` 来查看每个文件中更改的行。
+
+```
+git status
+git diff --stat
+```
+
+### 高级命令和最佳实践
+
+很快你会到达一个阶段,这时你希望你的提交看起来整洁一致。你可能还需要调整你的提交记录,使得提交更容易理解或者能还原一个意外的有破坏性的更改。
+
+`git log` 命令可以输出提交的历史记录。你将使用它来查看提交的历史记录。
+
+你的提交会附带消息和一个哈希值,哈希值是一串包含数字和字母的随机序列。一个哈希值示例如下:`c3d882aa1aa4e3d5f18b3890132670fbeac912f7`。
+
+```
+git log
+```
+
+假设你推送了一些可能破坏了你应用程序的东西。你最好回退一个提交然后再提交一次正确的,而不是修复它和推送新的东西。
+
+如果你希望及时回退并从之前的提交中检出(`checkout`)你的应用程序,则可以使用该哈希作为分支名直接执行此操作。这将使你的应用程序与当前版本分离(因为你正在编辑历史记录的版本,而不是当前版本)。
+
+```
+git checkout c3d88eaa1aa4e4d5f
+```
+
+然后,如果你在那个历史分支中做了更改,并且想要再次推送,你必须使用强制推送。
+
+**注意**:强制推送是危险的,只有在绝对必要的时候才能执行它。它将覆盖你的应用程序的历史记录,你将失去之后版本的任何信息。
+
+```
+git push -f origin master
+```
+
+在其他时候,将所有内容保留在一个提交中是不现实的。也行你想在尝试有潜在风险的操作之前保存当前进度,或者也许你犯了一个错误,但希望在你的版本历史中避免尴尬地留着这个错误。对此,我们有 `git rebase`。
+
+假设你在本地历史记录上有 4 个提交(没有推送到 GitHub),你要回退这是个提交。你的提交记录看起来很乱很拖拉。这时你可以使用 `rebase` 将所有这些提交合并到一个简单的提交中。
+
+```
+git rebase -i HEAD~4
+```
+
+上面的命令会打开你计算机的默认编辑器(默认为 Vim,除非你将默认修改为其他的),提供了几个你准备如何修改你的提交的选项。它看起来就像下面的代码:
+
+```
+pick 130deo9 oldest commit message
+pick 4209fei second oldest commit message
+pick 4390gne third oldest commit message
+pick bmo0dne newest commit message
+```
+
+为了合并这些提交,我们需要将 `pick` 选项修改为 `fixup`(如代码下面的文档所示),以将该提交合并并丢弃该提交消息。请注意,在 Vim 中,你需要按下 `a` 或 `i` 才能编辑文本,要保存退出,你需要按下 `Esc` 键,然后按 `shift + z + z`。不要问我为什么,它就是这样。
+
+```
+pick 130deo9 oldest commit message
+fixup 4209fei second oldest commit message
+fixup 4390gne third oldest commit message
+fixup bmo0dne newest commit message
+```
+
+这将把你的所有提交合并到一个提交中,提交消息为 `oldest commit message`。
+
+下一步是重命名你的提交消息。这完全是一个建议的操作,但只要你一直遵循一致的模式,都可以做得很好。这里我建议使用 [Google 为 Angular.js 提供的提交指南][9]。
+
+为了更改提交消息,请使用 `amend` 标志。
+
+```
+git commit --amend
+```
+
+这也会打开 Vim,文本编辑和保存规则如上所示。为了给出一个良好的提交消息的例子,下面是遵循该指南中规则的提交消息:
+
+```
+feat: add stripe checkout button to payments page
+
+- add stripe checkout button
+- write tests for checkout
+```
+
+保持指南中列出的类型(type)的一个优点是它使编写更改日志更加容易。你还可以在页脚(footer)(再次,在指南中规定的)中包含信息来引用问题(issue)。
+
+**注意:**如果你正在协作一个项目,并将代码推送到了 GitHub,你应该避免重新引用(`rebase`)并压缩(`squash`)你的提交。如果你开始在人们的眼皮子底下更改版本历史,那么你可能会遇到难以追踪的错误,从而给每个人都带来麻烦。
+
+Git 有无数的命令,但这里介绍的命令可能是您最初几年编程所需要知道的所有。
+
+* * *
+
+Sam Corcos 是 [Sightline Maps][10] 的首席开发工程师和联合创始人,Sightline Maps 是最直观的 3D 打印地形图的平台,以及用于构建 Phoenix 和 React 的可扩展生产应用程序的中级高级教程网站 [LearnPhoenix.io][11]。使用优惠码:free_code_camp 取得 LearnPhoenix 的20美元。
+
+(题图:[GitHub Octodex][6])
+
+--------------------------------------------------------------------------------
+
+via: https://medium.freecodecamp.org/git-cheat-sheet-and-best-practices-c6ce5321f52
+
+作者:[Sam Corcos][a]
+译者:[firmianay](https://github.com/firmianay)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://medium.freecodecamp.org/@SamCorcos?source=post_header_lockup
+[1]:https://medium.freecodecamp.org/tagged/git?source=post
+[2]:https://medium.freecodecamp.org/tagged/github?source=post
+[3]:https://medium.freecodecamp.org/tagged/programming?source=post
+[4]:https://medium.freecodecamp.org/tagged/software-development?source=post
+[5]:https://medium.freecodecamp.org/tagged/web-development?source=post
+[6]:https://octodex.github.com/
+[7]:https://xkcd.com/1597/
+[8]:https://guides.github.com/introduction/flow/
+[9]:https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines
+[10]:http://sightlinemaps.com/
+[11]:http://learnphoenix.io/
diff --git a/translated/tech/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md b/published/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md
similarity index 64%
rename from translated/tech/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md
rename to published/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md
index d7b7627e49..dae5a6e6dc 100644
--- a/translated/tech/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md
+++ b/published/20170123 What I Dont Like About Error Handling in Go and How to Work Around It.md
@@ -1,18 +1,17 @@
我对 Go 的错误处理有哪些不满,以及我是如何处理的
======================
-写 Go 的人往往对它的错误处理模式有一定的看法。根据你对其他语言的经验,你可能习惯于不同的方法。这就是为什么我决定要写这篇文章,尽管有点固执己见,但我认为吸收我的经验在辩论中是有用的。 我想要解决的主要问题是,很难去强制良好的错误处理实践,错误没有堆栈追踪,并且错误处理本身太冗长。不过,我已经看到了一些潜在的解决方案或许能帮助解决一些问题。
+写 Go 的人往往对它的错误处理模式有一定的看法。按不同的语言经验,人们可能有不同的习惯处理方法。这就是为什么我决定要写这篇文章,尽管有点固执己见,但我认为听取我的经验是有用的。我想要讲的主要问题是,很难去强制执行良好的错误处理实践,错误经常没有堆栈追踪,并且错误处理本身太冗长。不过,我已经看到了一些潜在的解决方案,或许能帮助解决一些问题。
### 与其他语言的快速比较
-
-[在 Go 中,所有的错误是值][1]。因为这点,相当多的函数最后会返回一个 `error`, 看起来像这样:
+[在 Go 中,所有的错误都是值][1]。因为这点,相当多的函数最后会返回一个 `error`, 看起来像这样:
```
func (s *SomeStruct) Function() (string, error)
```
-由于这点,调用代码常规上会使用 `if` 语句来检查它们:
+因此这导致调用代码通常会使用 `if` 语句来检查它们:
```
bytes, err := someStruct.Function()
@@ -21,13 +20,13 @@ if err != nil {
}
```
-另外一种是在其他语言中如 Java、C#、Javascript、Objective C、Python 等使用的 `try-catch` 模式。如下你可以看到与先前的 Go 示例类似的 Java 代码,声明 `throws` 而不是返回 `error`:
+另外一种方法,是在其他语言中,如 Java、C#、Javascript、Objective C、Python 等使用的 `try-catch` 模式。如下你可以看到与先前的 Go 示例类似的 Java 代码,声明 `throws` 而不是返回 `error`:
```
public String function() throws Exception
```
- `try-catch` 而不是 `if err != nil`:
+它使用的是 `try-catch` 而不是 `if err != nil`:
```
try {
@@ -39,11 +38,11 @@ catch (Exception e) {
}
```
-当然,还有其他的不同。不如,`error` 不会使你的程序崩溃,然而 `Exception` 会。还有其他的一些,我希望在在本篇中专注在这些上。
+当然,还有其他的不同。例如,`error` 不会使你的程序崩溃,然而 `Exception` 会。还有其他的一些,在本篇中会专门提到这些。
### 实现集中式错误处理
-退一步,让我们看看为什么以及如何在一个集中的地方处理错误。
+退一步,让我们看看为什么要在一个集中的地方处理错误,以及如何做到。
大多数人或许会熟悉的一个例子是 web 服务 - 如果出现了一些未预料的的服务端错误,我们会生成一个 5xx 错误。在 Go 中,你或许会这么实现:
@@ -68,7 +67,7 @@ func viewCompanies(w http.ResponseWriter, r *http.Request) {
}
```
-这并不是一个好的解决方案,因为我们不得不重复在所有的处理函数中处理错误。为了能更好地维护,最好能在一处地方处理错误。幸运的是,[在 Go 的博客中,Andrew Gerrand 提供了一个替代方法][2]可以完美地实现。我们可以错见一个处理错误的类型:
+这并不是一个好的解决方案,因为我们不得不重复地在所有的处理函数中处理错误。为了能更好地维护,最好能在一处地方处理错误。幸运的是,[在 Go 语言的官方博客中,Andrew Gerrand 提供了一个替代方法][2],可以完美地实现。我们可以创建一个处理错误的 Type:
```
type appHandler func(http.ResponseWriter, *http.Request) error
@@ -89,11 +88,11 @@ func init() {
}
```
-接着我们需要做的是修改处理函数的签名来使它们返回 `errors`。这个方法很好,因为我们做到了 [dry][3] 原则,并且没有重复使用不必要的代码 - 现在我们可以在一处返回默认错误了。
+接着我们需要做的是修改处理函数的签名来使它们返回 `errors`。这个方法很好,因为我们做到了 [DRY][3] 原则,并且没有重复使用不必要的代码 - 现在我们可以在单独一个地方返回默认错误了。
### 错误上下文
-在先前的例子中,我们可能会收到许多潜在的错误,它们的任何一个都可能在调用堆栈的许多部分生成。这时候事情就变得棘手了。
+在先前的例子中,我们可能会收到许多潜在的错误,它们中的任何一个都可能在调用堆栈的许多环节中生成。这时候事情就变得棘手了。
为了演示这点,我们可以扩展我们的处理函数。它可能看上去像这样,因为模板执行并不是唯一一处会发生错误的地方:
@@ -109,9 +108,9 @@ func viewUsers(w http.ResponseWriter, r *http.Request) error {
调用链可能会相当深,在整个过程中,各种错误可能在不同的地方实例化。[Russ Cox][4]的这篇文章解释了如何避免遇到太多这类问题的最佳实践:
- 在 Go 中错误报告的部分约定是函数包含相关的上下文、包含正在尝试的操作(比如函数名和它的参数)
+> “在 Go 中错误报告的部分约定是函数包含相关的上下文,包括正在尝试的操作(比如函数名和它的参数)。”
-给出的例子是 OS 包中的一个调用:
+这个给出的例子是对 OS 包的一个调用:
```
err := os.Remove("/tmp/nonexist")
@@ -140,11 +139,11 @@ if err != nil {
}
```
-这意味着错误发生时它们没有交流。
+这意味着错误何时发生并没有被传递出来。
应该注意的是,所有这些错误都可以在 `Exception` 驱动的模型中发生 - 糟糕的错误信息、隐藏异常等。那么为什么我认为该模型更有用?
-如果我们在处理一个糟糕的异常消息,_我们仍然能够了解堆栈中发生了什么_。因为堆栈跟踪,这引发了一些我对 Go 不了解的部分 - 你知道 Go 的 `panic` 包含了堆栈追踪,但是 `error` 没有。我认为推论是 `panic` 可能会使你的程序崩溃,因此需要一个堆栈追踪,而处理错误并不会,因为它会假定你在它发生的地方做一些事。
+即便我们在处理一个糟糕的异常消息,_我们仍然能够了解它发生在调用堆栈中什么地方_。因为堆栈跟踪,这引发了一些我对 Go 不了解的部分 - 你知道 Go 的 `panic` 包含了堆栈追踪,但是 `error` 没有。我推测可能是 `panic` 会使你的程序崩溃,因此需要一个堆栈追踪,而处理错误并不会,因为它会假定你在它发生的地方做一些事。
所以让我们回到之前的例子 - 一个有糟糕错误信息的第三方库,它只是输出了调用链。你认为调试会更容易吗?
@@ -170,17 +169,17 @@ github.com/Org/app/core/vendor/github.com/rusenask/goproxy.FuncReqHandler.Handle
如果我们使用 Java 作为一个随意的例子,其中人们犯的一个最愚蠢的错误是不记录堆栈追踪:
```
-LOGGER.error(ex.getMessage()) // Doesn't log stack trace
-LOGGER.error(ex.getMessage(), ex) // Does log stack trace
+LOGGER.error(ex.getMessage()) // 不记录堆栈追踪
+LOGGER.error(ex.getMessage(), ex) // 记录堆栈追踪
```
-但是 Go 设计中似乎没有这个信息
+但是 Go 似乎在设计中就没有这个信息。
-在获取上下文信息方面 - Russ 还提到了社区正在讨论一些潜在的接口用于剥离上下文错误。了解更多这点或许会很有趣。
+在获取上下文信息方面 - Russ 还提到了社区正在讨论一些潜在的接口用于剥离上下文错误。关于这点,了解更多或许会很有趣。
### 堆栈追踪问题解决方案
-幸运的是,在做了一些查找后,我发现了这个出色的[ Go 错误][5]库来帮助解决这个问题,来给错误添加堆栈跟踪:
+幸运的是,在做了一些查找后,我发现了这个出色的 [Go 错误][5]库来帮助解决这个问题,来给错误添加堆栈跟踪:
```
if errors.Is(err, crashy.Crashed) {
@@ -188,7 +187,7 @@ if errors.Is(err, crashy.Crashed) {
}
```
-不过,我认为这个功能能成为语言的一等公民将是一个改进,这样你就不必对类型做一些修改了。此外,如果我们像先前的例子那样使用第三方库,那就可能不必使用 `crashy` - 我们仍有相同的问题。
+不过,我认为这个功能如果能成为语言的第一类公民将是一个改进,这样你就不必做一些类型修改了。此外,如果我们像先前的例子那样使用第三方库,它可能没有使用 `crashy` - 我们仍有相同的问题。
### 我们对错误应该做什么?
@@ -201,7 +200,7 @@ if err != nil {
}
```
-如果我们想要调用大量会返回错误的方法时会发生什么,在同一个地方处理它们么?看上去像这样:
+如果我们想要调用大量方法,它们会产生错误,然后在一个地方处理所有错误,这时会发生什么?看上去像这样:
```
err := doSomething()
@@ -222,7 +221,7 @@ func doSomething() error {
}
```
-这感觉有点冗余,然而在其他语言中你可以将多条语句作为一个整体处理。
+这感觉有点冗余,在其他语言中你可以将多条语句作为一个整体处理。
```
try {
@@ -245,9 +244,9 @@ public void doSomething() throws SomeErrorToPropogate {
}
```
-我个人认为这两个例子实现了一件事情,只有 `Exception` 模式更少冗余更加弹性。如果有什么,我发现 `if err!= nil` 感觉像样板。也许有一种方法可以清理?
+我个人认为这两个例子实现了一件事情,只是 `Exception` 模式更少冗余,更加弹性。如果有什么的话,我觉得 `if err!= nil` 感觉像样板。也许有一种方法可以清理?
-### 将多条语句像一个整体那样发生错误
+### 将失败的多条语句做为一个整体处理错误
首先,我做了更多的阅读,并[在 Rob Pike 写的 Go 博客中][7]发现了一个比较务实的解决方案。
@@ -280,7 +279,7 @@ if ew.err != nil {
}
```
-这也是一个很好的方案,但是我感觉缺少了点什么 - 因为我们不能重复使用这个模式。如果我们想要一个含有字符串参数的方法,我们就不得不改变函数签名。或者如果我们不想执行写会怎样?我们可以尝试使它更通用:
+这也是一个很好的方案,但是我感觉缺少了点什么 - 因为我们不能重复使用这个模式。如果我们想要一个含有字符串参数的方法,我们就不得不改变函数签名。或者如果我们不想执行写操作会怎样?我们可以尝试使它更通用:
```
type errWrapper struct {
@@ -317,11 +316,11 @@ if err != nil {
}
```
-这可以用,但是并没有帮助太大,因为它最后比标准的 `if err != nil` 检查带来了更多的冗余。我有兴趣听到有人能提供其他解决方案。或许语言本身需要一些方法来以不那么臃肿的方式的传递或者组合错误 - 但是感觉似乎是特意设计成不那么做。
+这可以用,但是并没有太大帮助,因为它最终比标准的 `if err != nil` 检查带来了更多的冗余。如果有人能提供其他解决方案,我会很有兴趣听。或许这个语言本身需要一些方法来以不那么臃肿的方式传递或者组合错误 - 但是感觉似乎是特意设计成不那么做。
### 总结
-看完这些之后,你可能会认为我反对在 Go 中使用 `error`。但事实并非如此,我只是描述了如何将它与 `try catch` 模型的经验进行比较。它是一个用于系统编程很好的语言,并且已经出现了一些优秀的工具。仅举几例有 [Kubernetes][8]、[Docker][9]、[Terraform][10]、[Hoverfly][11] 等。还有小型、高性能、本地二进制的优点。但是,`error` 难以适应。 我希望我的推论是有道理的,而且一些方案和解决方法可能会有帮助。
+看完这些之后,你可能会认为我在对 `error` 挑刺儿,由此推论我反对 Go。事实并非如此,我只是将它与我使用 `try catch` 模型的经验进行比较。它是一个用于系统编程很好的语言,并且已经出现了一些优秀的工具。仅举几例,有 [Kubernetes][8]、[Docker][9]、[Terraform][10]、[Hoverfly][11] 等。还有小型、高性能、本地二进制的优点。但是,`error` 难以适应。 我希望我的推论是有道理的,而且一些方案和解决方法可能会有帮助。
--------------------------------------------------------------------------------
@@ -336,7 +335,7 @@ via: https://opencredo.com/why-i-dont-like-error-handling-in-go
作者:[Andrew Morgan][a]
译者:[geekpi](https://github.com/geekpi)
-校对:[校对者ID](https://github.com/校对者ID)
+校对:[jasminepeng](https://github.com/jasminepeng)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/published/20170531 DNS Infrastructure at GitHub.md b/published/20170531 DNS Infrastructure at GitHub.md
new file mode 100644
index 0000000000..0abec33d5b
--- /dev/null
+++ b/published/20170531 DNS Infrastructure at GitHub.md
@@ -0,0 +1,79 @@
+GitHub 的 DNS 基础设施
+============================================================
+
+在 GitHub,我们最近从头改进了 DNS。这包括了我们[如何与外部 DNS 提供商交互][4]以及我们如何在内部向我们的主机提供记录。为此,我们必须设计和构建一个新的 DNS 基础设施,它可以随着 GitHub 的增长扩展并跨越多个数据中心。
+
+以前,GitHub 的 DNS 基础设施相当简单直接。它包括每台服务器上本地的、只具备转发功能的 DNS 缓存服务器,以及一对被所有这些主机使用的缓存服务器和权威服务器主机。这些主机在内部网络以及公共互联网上都可用。我们在缓存守护程序中配置了区域存根,以在本地进行查询,而不是在互联网上进行递归。我们还在我们的 DNS 提供商处设置了 NS 记录,它们将特定的内部域指向这对主机的公共 IP,以便我们网络外部的查询。
+
+这个配置使用了很多年,但它并非没有缺点。许多程序对于解析 DNS 查询非常敏感,我们遇到的任何性能或可用性问题在最好的情况下也会导致服务排队和性能降级,而最坏情况下客户会遭遇服务中断。配置和代码的更改可能会导致查询率发生大幅度的意外变化。因此超出这两台主机的扩展成为了一个问题。由于这些主机的网络配置,如果我们只是继续添加 IP 和主机的话存在一些本身的问题。在试图解决和补救这些问题的同时,由于缺乏测量指标和可见性,老旧的系统难以识别问题的原因。在许多情况下,我们使用 `tcpdump` 来识别有问题的流量和查询。另一个问题是在公共 DNS 服务器上运行,我们处于泄露内部网络信息的风险之下。因此,我们决定建立更好的东西,并开始确定我们对新系统的要求。
+
+我们着手设计一个新的 DNS 基础设施,以改善上述包括扩展和可见性在内的运维问题,并引入了一些额外的需求。我们希望通过外部 DNS 提供商继续运行我们的公共 DNS 域,因此我们构建的系统需要与供应商无关。此外,我们希望该系统能够服务于我们的内部和外部域,这意味着内部域仅在我们的内部网络上可用,除非另有特别配置,而外部域也不用离开我们的内部网络就可解析。我们希望新的 DNS 架构不但可以[基于部署的工作流进行更改][5],并可以通过我们的仓库和配置系统使用 API 自动更改 DNS 记录。新系统不能有任何外部依赖,太依赖于 DNS 功能将会陷入级联故障,这包括连接到其他数据中心和其中可能有的 DNS 服务。我们的旧系统将缓存服务器和权威服务器在同一台主机上混合使用。我们想转到具有独立角色的分层设计。最后,我们希望系统能够支持多数据中心环境,无论是 EC2 还是裸机。
+
+### 实现
+
+
+
+为了构建这个系统,我们确定了三类主机:缓存主机、边缘主机和权威主机。缓存主机作为递归解析器和 DNS “路由器” 缓存来自边缘层的响应。边缘层运行 DNS 权威守护程序,用于响应缓存层对 DNS 区域的请求,其被配置为来自权威层的区域传输。权威层作为隐藏的 DNS 主服务器,作为 DNS 数据的规范来源,为来自边缘主机的区域传输提供服务,并提供用于创建、修改或删除记录的 HTTP API。
+
+在我们的新配置中,缓存主机存在于每个数据中心中,这意味着应用主机不需要穿过数据中心边界来检索记录。缓存主机被配置为将区域映射到其地域内的边缘主机,以便将我们的内部区域路由到我们自己的主机。未明确配置的任何区域将通过互联网递归解析。
+
+边缘主机是地域性的主机,存在我们的网络边缘 PoP(存在点)内。我们的 PoP 有一个或多个依赖于它们进行外部连接的数据中心,没有 PoP 数据中心将无法访问互联网,互联网也无法访问它们。边缘主机对所有的权威主机执行区域传输,无论它们存在什么地域或位置,并将这些区域存在本地的磁盘上。
+
+我们的权威主机也是地域性的主机,只包含适用于其所在地域的区域。我们的仓库和配置系统决定一个区域存放在哪个地域性权威主机,并通过 HTTP API 服务来创建和删除记录。 OctoDNS 将区域映射到地域性权威主机,并使用相同的 API 创建静态记录,以及确保动态源处于同步状态。对于外部域 (如 github.com),我们有另外一个单独的权威主机,以允许我们可以在连接中断期间查询我们的外部域。所有记录都存储在 MySQL 中。
+
+### 可运维性
+
+
+
+迁移到更现代的 DNS 基础设施的巨大好处是可观察性。我们的旧 DNS 系统几乎没有指标,只有有限的日志。决定使用哪些 DNS 服务器的一个重要因素是它们所产生的指标的广度和深度。我们最终用 [Unbound][6] 作为缓存主机,[NSD][7] 作为边缘主机,[PowerDNS][8] 作为权威主机,所有这些都已在比 GitHub 大得多的 DNS 基础架构中得到了证实。
+
+当在我们的裸机数据中心运行时,缓存通过私有的[任播][9] IP 访问,从而使之可以到达最近的可用缓存主机。缓存主机已经以机架感知的方式部署,在它们之间提供了一定程度的平衡负载,并且与一些电源和网络故障模式相隔离。当缓存主机出现故障时,通常将用其进行 DNS 查询的服务器现在将自动路由到下一个最接近的缓存主机,以保持低延迟并提供对某些故障模式的容错。任播允许我们扩展单个 IP 地址后面的缓存数量,这与先前的配置不同,使得我们能够按 DNS 需求量运行尽可能多的缓存主机。
+
+无论地域或位置如何,边缘主机使用权威层进行区域传输。我们的区域并没有大到在每个地域保留所有区域的副本成为问题。(LCTT 译注:此处原文“Our zones are not large enough that keeping a copy of all of them in every region is a problem.”,根据上下文理解而翻译。)这意味着对于每个区域,即使某个地域处于脱机状态,或者上游服务提供商存在连接问题,所有缓存服务器都可以访问具备所有区域的本地副本的本地边缘服务器。这种变化在面对连接问题方面已被证明是相当有弹性的,并且在不久前本来会导致客户面临停止服务的故障期间帮助保持 GitHub 可用。
+
+那些区域传输包括了内部和外部域从它们相应的权威服务器进行的传输。正如你可能会猜想像 github.com 这样的区域是外部的,像 github.net 这样的区域通常是内部的。它们之间的区别仅在于我们使用的类型和存储在其中的数据。了解哪些区域是内部和外部的,为我们在配置中提供了一些灵活性。
+
+```
+$ dig +short github.com
+192.30.253.112
+192.30.253.113
+```
+
+公共区域被[同步][10]到外部 DNS 提供商,并且是 GitHub 用户每天使用的 DNS 记录。另外,公共区域在我们的网络中是完全可解析的,而不需要与我们的外部提供商进行通信。这意味着需要查询 `api.github.com` 的任何服务都可以这样做,而无需依赖外部网络连接。我们还使用了 Unbound 的 `stub-first` 配置选项,它给了我们第二次查询的机会,如果我们的内部 DNS 服务由于某些原因在外部查询失败,则可以进行第二次查找。
+
+```
+$ dig +short time.github.net
+10.127.6.10
+```
+
+大部分的 `github.net` 区域是完全私有的,无法从互联网访问,它只包含 [RFC 1918][11] 中规定的 IP 地址。每个地域和站点都划分了私有区域。每个地域和/或站点都具有适用于该位置的一组子区域,子区域用于管理网络、服务发现、特定的服务记录,并且还包括在我们仓库中的配置主机。私有区域还包括 PTR 反向查找区域。
+
+### 总结
+
+用一个新系统替换可以为数百万客户提供服务的旧系统并不容易。使用实用的、基于需求的方法来设计和实施我们的新 DNS 系统,才能打造出一个能够迅速有效地运行、并有望与 GitHub 一起成长的 DNS 基础设施。
+
+想帮助 GitHub SRE 团队解决有趣的问题吗?我们很乐意你加入我们。[在这申请][12]。
+
+--------------------------------------------------------------------------------
+
+via: https://githubengineering.com/dns-infrastructure-at-github/
+
+作者:[Joe Williams][a]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://github.com/joewilliams
+[1]:https://githubengineering.com/dns-infrastructure-at-github/
+[2]:https://github.com/joewilliams
+[3]:https://github.com/joewilliams
+[4]:https://githubengineering.com/enabling-split-authority-dns-with-octodns/
+[5]:https://githubengineering.com/enabling-split-authority-dns-with-octodns/
+[6]:https://unbound.net/
+[7]:https://www.nlnetlabs.nl/projects/nsd/
+[8]:https://powerdns.com/
+[9]:https://en.wikipedia.org/wiki/Anycast
+[10]:https://githubengineering.com/enabling-split-authority-dns-with-octodns/
+[11]:http://www.faqs.org/rfcs/rfc1918.html
+[12]:https://boards.greenhouse.io/github/jobs/669805#.WPVqJlPyvUI
diff --git a/published/20170718 Integrate Ubuntu to Samba4 AD DC with SSSD and Realm – Part 15.md b/published/20170718 Integrate Ubuntu to Samba4 AD DC with SSSD and Realm – Part 15.md
new file mode 100644
index 0000000000..cf322790a7
--- /dev/null
+++ b/published/20170718 Integrate Ubuntu to Samba4 AD DC with SSSD and Realm – Part 15.md
@@ -0,0 +1,384 @@
+Samba 系列(十五):用 SSSD 和 Realm 集成 Ubuntu 到 Samba4 AD DC
+============================================================
+
+本教程将告诉你如何将 Ubuntu 桌面版机器加入到带有 SSSD 和 Realm 服务的 Samba4 活动目录域中,以在活动目录中认证用户。
+
+### 要求:
+
+1. [在 Ubuntu 上用 Samba4 创建一个活动目录架构][1]
+
+### 第 1 步:初始配置
+
+1、 在把 Ubuntu 加入活动目录前确保主机名被正确设置了。使用 `hostnamectl` 命令设置机器名字或者手动编辑 `/etc/hostname` 文件。
+
+```
+$ sudo hostnamectl set-hostname your_machine_short_hostname
+$ cat /etc/hostname
+$ hostnamectl
+```
+
+2、 接下来,编辑机器网络接口设置并且添加合适的 IP 设置,并将正确的 DNS IP 服务器地址指向 Samba 活动目录域控制器,如下图所示。
+
+如果你已经配置了 DHCP 服务来为局域网机器自动分配包括合适的 AD DNS IP 地址的 IP 设置,那么你可以跳过这一步。
+
+[][2]
+
+*设置网络接口*
+
+上图中,`192.168.1.254` 和 `192.168.1.253` 代表 Samba4 域控制器的 IP 地址。
+
+3、 用 GUI(图形用户界面)或命令行重启网络服务来应用修改,并且对你的域名发起一系列 ping 请求来测试 DNS 解析如预期工作。 也用 `host` 命令来测试 DNS 解析。
+
+```
+$ sudo systemctl restart networking.service
+$ host your_domain.tld
+$ ping -c2 your_domain_name
+$ ping -c2 adc1
+$ ping -c2 adc2
+```
+
+4、 最后, 确保机器时间和 Samba4 AD 同步。安装 `ntpdate` 包并用下列指令和 AD 同步时间。
+
+```
+$ sudo apt-get install ntpdate
+$ sudo ntpdate your_domain_name
+```
+
+### 第 2 步:安装需要的包
+
+5、 这一步将安装将 Ubuntu 加入 Samba4 活动目录域控制器所必须的软件和依赖:Realmd 和 SSSD 服务。
+
+```
+$ sudo apt install adcli realmd krb5-user samba-common-bin samba-libs samba-dsdb-modules sssd sssd-tools libnss-sss libpam-sss packagekit policykit-1
+```
+
+6、 输入大写的默认 realm 名称,然后按下回车继续安装。
+
+[][3]
+
+*输入 Realm 名称*
+
+7、 接着,创建包含以下内容的 SSSD 配置文件。
+
+```
+$ sudo nano /etc/sssd/sssd.conf
+```
+
+加入下面的内容到 `sssd.conf` 文件。
+
+```
+[nss]
+filter_groups = root
+filter_users = root
+reconnection_retries = 3
+[pam]
+reconnection_retries = 3
+[sssd]
+domains = tecmint.lan
+config_file_version = 2
+services = nss, pam
+default_domain_suffix = TECMINT.LAN
+[domain/tecmint.lan]
+ad_domain = tecmint.lan
+krb5_realm = TECMINT.LAN
+realmd_tags = manages-system joined-with-samba
+cache_credentials = True
+id_provider = ad
+krb5_store_password_if_offline = True
+default_shell = /bin/bash
+ldap_id_mapping = True
+use_fully_qualified_names = True
+fallback_homedir = /home/%d/%u
+access_provider = ad
+auth_provider = ad
+chpass_provider = ad
+access_provider = ad
+ldap_schema = ad
+dyndns_update = true
+dyndsn_refresh_interval = 43200
+dyndns_update_ptr = true
+dyndns_ttl = 3600
+```
+
+确保你对应地替换了下列参数的域名:
+
+```
+domains = tecmint.lan
+default_domain_suffix = TECMINT.LAN
+[domain/tecmint.lan]
+ad_domain = tecmint.lan
+krb5_realm = TECMINT.LAN
+```
+
+8、 接着,用下列命令给 SSSD 配置文件适当的权限:
+
+```
+$ sudo chmod 700 /etc/sssd/sssd.conf
+```
+
+9、 现在,打开并编辑 Realmd 配置文件,输入下面这行:
+
+```
+$ sudo nano /etc/realmd.conf
+```
+
+`realmd.conf` 文件摘录:
+
+```
+[active-directory]
+os-name = Linux Ubuntu
+os-version = 17.04
+[service]
+automatic-install = yes
+[users]
+default-home = /home/%d/%u
+default-shell = /bin/bash
+[tecmint.lan]
+user-principal = yes
+fully-qualified-names = no
+```
+
+10、 最后需要修改的文件属于 Samba 守护进程。 打开 `/etc/samba/smb.conf` 文件编辑,然后在文件开头加入下面这块代码,在 `[global]` 之后的部分如下图所示。
+
+```
+workgroup = TECMINT
+client signing = yes
+client use spnego = yes
+kerberos method = secrets and keytab
+realm = TECMINT.LAN
+security = ads
+```
+
+[][4]
+
+*配置 Samba 服务器*
+
+确保你替换了域名值,特别是对应域名的 realm 值,并运行 `testparm` 命令检验设置文件是否包含错误。
+
+```
+$ sudo testparm
+```
+
+[][5]
+
+*测试 Samba 配置*
+
+11、 在做完所有必需的修改之后,用 AD 管理员帐号验证 Kerberos 认证并用下面的命令列出票据。
+
+```
+$ sudo kinit ad_admin_user@DOMAIN.TLD
+$ sudo klist
+```
+
+[][6]
+
+*检验 Kerberos 认证*
+
+### 第 3 步: 加入 Ubuntu 到 Samba4 Realm
+
+12、 键入下列命令将 Ubuntu 机器加入到 Samba4 活动目录。用有管理员权限的 AD DC 账户名字,以便绑定 realm 可以如预期般工作,并替换对应的域名值。
+
+```
+$ sudo realm discover -v DOMAIN.TLD
+$ sudo realm list
+$ sudo realm join TECMINT.LAN -U ad_admin_user -v
+$ sudo net ads join -k
+```
+
+[][7]
+
+*加入 Ubuntu 到 Samba4 Realm*
+
+[][8]
+
+*列出 Realm Domain 信息*
+
+[][9]
+
+*添加用户到 Realm Domain*
+
+[][10]
+
+*添加 Domain 到 Realm*
+
+13、 区域绑定好了之后,运行下面的命令确保所有域账户允许在这台机器上认证。
+
+```
+$ sudo realm permit -all
+```
+
+然后你可以使用下面举例的 `realm` 命令允许或者禁止域用户帐号或群组访问。
+
+```
+$ sudo realm deny -a
+$ realm permit --groups ‘domain.tld\Linux Admins’
+$ realm permit user@domain.lan
+$ realm permit DOMAIN\\User2
+```
+
+14、 从一个 [安装了 RSAT 工具的][11] Windows 机器上你可以打开 AD UC 并浏览“电脑”容器,并检验是否有一个使用你机器名的对象帐号已经创建。
+
+[][12]
+
+*确保域被加入 AD DC*
+
+### 第 4 步:配置 AD 账户认证
+
+15、 为了在 Ubuntu 机器上用域账户认证,你需要用 root 权限运行 `pam-auth-update` 命令并允许所有 PAM 配置文件,包括为每个域账户在第一次注册的时候自动创建家目录的选项。
+
+按 [空格] 键检验所有配置项并点击 ok 来应用配置。
+
+```
+$ sudo pam-auth-update
+```
+
+[][13]
+
+*PAM 配置*
+
+16、 在系统上手动编辑 `/etc/pam.d/common-account` 文件,下面这几行是为了给认证过的域用户自动创建家目录。
+
+```
+session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
+```
+
+17、 如果活动目录用户不能用 linux 命令行修改他们的密码,打开 `/etc/pam.d/common-password` 文件并在 `password` 行移除 `use_authtok` 语句,最后如下:
+
+```
+password [success=1 default=ignore] pam_winbind.so try_first_pass
+```
+
+18、 最后,用下面的命令重启并启用以应用 Realmd 和 SSSD 服务的修改:
+
+```
+$ sudo systemctl restart realmd sssd
+$ sudo systemctl enable realmd sssd
+```
+
+19、 为了测试 Ubuntu 机器是是否成功集成到 realm ,安装 winbind 包并运行 `wbinfo` 命令列出域账户和群组,如下所示。
+
+```
+$ sudo apt-get install winbind
+$ wbinfo -u
+$ wbinfo -g
+```
+
+[][14]
+
+*列出域账户*
+
+20、 同样,也可以针对特定的域用户或群组使用 `getent` 命令检验 Winbind nsswitch 模块。
+
+```
+$ sudo getent passwd your_domain_user
+$ sudo getent group ‘domain admins’
+```
+
+[][15]
+
+*检验 Winbind Nsswitch*
+
+21、 你也可以用 Linux `id` 命令获取 AD 账户的信息,命令如下:
+
+```
+$ id tecmint_user
+```
+
+[][16]
+
+*检验 AD 用户信息*
+
+22、 用 `su -` 后跟上域用户名参数来认证 Ubuntu 主机的一个 Samba4 AD 账户。运行 `id` 命令获取该 AD 账户的更多信息。
+
+```
+$ su - your_ad_user
+```
+
+[][17]
+
+*AD 用户认证*
+
+用 `pwd` 命令查看你的域用户当前工作目录,和用 `passwd` 命令修改密码。
+
+23、 在 Ubuntu 上使用有 root 权限的域账户,你需要用下面的命令添加 AD 用户名到 sudo 系统群组:
+
+```
+$ sudo usermod -aG sudo your_domain_user@domain.tld
+```
+
+用域账户登录 Ubuntu 并运行 `apt update` 命令来更新你的系统以检验 root 权限。
+
+24、 给一个域群组 root 权限,用 `visudo` 命令打开并编辑 `/etc/sudoers` 文件,并加入如下行:
+
+```
+%domain\ admins@tecmint.lan ALL=(ALL:ALL) ALL
+```
+
+25、 要在 Ubuntu 桌面使用域账户认证,通过编辑 `/usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf` 文件来修改 LightDM 显示管理器,增加以下两行并重启 lightdm 服务或重启机器应用修改。
+
+```
+greeter-show-manual-login=true
+greeter-hide-users=true
+```
+
+域账户用“你的域用户”或“你的域用户@你的域” 格式来登录 Ubuntu 桌面。
+
+26、 为使用 Samba AD 账户的简称格式,编辑 `/etc/sssd/sssd.conf` 文件,在 `[sssd]` 块加入如下几行命令。
+
+```
+full_name_format = %1$s
+```
+
+并重启 SSSD 守护进程应用改变。
+
+```
+$ sudo systemctl restart sssd
+```
+
+你会注意到 bash 提示符会变成了没有附加域名部分的 AD 用户名。
+
+27、 万一你因为 `sssd.conf` 里的 `enumerate=true` 参数设定而不能登录,你得用下面的命令清空 sssd 缓存数据:
+
+```
+$ rm /var/lib/sss/db/cache_tecmint.lan.ldb
+```
+
+这就是全部了!虽然这个教程主要集中于集成 Samba4 活动目录,同样的步骤也能被用于把使用 Realm 和 SSSD 服务的 Ubuntu 整合到微软 Windows 服务器活动目录。
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Matei Cezar - 我是一名网瘾少年,开源和基于 linux 系统软件的粉丝,有4年经验在 linux 发行版桌面、服务器和 bash 脚本。
+
+------------------
+
+via: https://www.tecmint.com/integrate-ubuntu-to-samba4-ad-dc-with-sssd-and-realm/
+
+作者:[Matei Cezar][a]
+译者:[XYenChi](https://github.com/XYenChi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.tecmint.com/author/cezarmatei/
+[1]:https://linux.cn/article-8065-1.html
+[2]:https://www.tecmint.com/wp-content/uploads/2017/07/Configure-Network-Interface.jpg
+[3]:https://www.tecmint.com/wp-content/uploads/2017/07/Set-realm-name.png
+[4]:https://www.tecmint.com/wp-content/uploads/2017/07/Configure-Samba-Server.jpg
+[5]:https://www.tecmint.com/wp-content/uploads/2017/07/Test-Samba-Configuration.jpg
+[6]:https://www.tecmint.com/wp-content/uploads/2017/07/Check-Kerberos-Authentication.jpg
+[7]:https://www.tecmint.com/wp-content/uploads/2017/07/Join-Ubuntu-to-Samba4-Realm.jpg
+[8]:https://www.tecmint.com/wp-content/uploads/2017/07/List-Realm-Domain-Info.jpg
+[9]:https://www.tecmint.com/wp-content/uploads/2017/07/Add-User-to-Realm-Domain.jpg
+[10]:https://www.tecmint.com/wp-content/uploads/2017/07/Add-Domain-to-Realm.jpg
+[11]:https://linux.cn/article-8097-1.html
+[12]:https://www.tecmint.com/wp-content/uploads/2017/07/Confirm-Domain-Added.jpg
+[13]:https://www.tecmint.com/wp-content/uploads/2017/07/PAM-Configuration.jpg
+[14]:https://www.tecmint.com/wp-content/uploads/2017/07/List-Domain-Accounts.jpg
+[15]:https://www.tecmint.com/wp-content/uploads/2017/07/check-Winbind-nsswitch.jpg
+[16]:https://www.tecmint.com/wp-content/uploads/2017/07/Check-AD-User-Info.jpg
+[17]:https://www.tecmint.com/wp-content/uploads/2017/07/AD-User-Authentication.jpg
+[18]:https://www.tecmint.com/author/cezarmatei/
+[19]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
+[20]:https://www.tecmint.com/free-linux-shell-scripting-books/
diff --git a/published/20170813 An Intro to Compilers.md b/published/20170813 An Intro to Compilers.md
new file mode 100644
index 0000000000..8d9e9a3f60
--- /dev/null
+++ b/published/20170813 An Intro to Compilers.md
@@ -0,0 +1,216 @@
+编译器简介: 在 Siri 前时代如何与计算机对话
+============================================================
+
+
+
+简单说来,一个编译器不过是一个可以翻译其他程序的程序。传统的编译器可以把源代码翻译成你的计算机能够理解的可执行机器代码。(一些编译器将源代码翻译成别的程序语言,这样的编译器称为源到源翻译器或转化器。)[LLVM][7] 是一个广泛使用的编译器项目,包含许多模块化的编译工具。
+
+传统的编译器设计包含三个部分:
+
+
+
+* 前端将源代码翻译为中间表示 (IR)* 。[clang][1] 是 LLVM 中用于 C 家族语言的前端工具。
+* 优化器分析 IR 然后将其转化为更高效的形式。[opt][2] 是 LLVM 的优化工具。
+* 后端通过将 IR 映射到目标硬件指令集从而生成机器代码。[llc][3] 是 LLVM 的后端工具。
+
+注:LLVM 的 IR 是一种和汇编类似的低级语言。然而,它抽离了特定硬件信息。
+
+### Hello, Compiler
+
+下面是一个打印 “Hello, Compiler!” 到标准输出的简单 C 程序。C 语法是人类可读的,但是计算机却不能理解,不知道该程序要干什么。我将通过三个编译阶段使该程序变成机器可执行的程序。
+
+```
+// compile_me.c
+// Wave to the compiler. The world can wait.
+
+#include
+
+int main() {
+ printf("Hello, Compiler!\n");
+ return 0;
+}
+```
+
+#### 前端
+
+正如我在上面所提到的,`clang` 是 LLVM 中用于 C 家族语言的前端工具。Clang 包含 C 预处理器、词法分析器、语法解析器、语义分析器和 IR 生成器。
+
+**C 预处理器**在将源程序翻译成 IR 前修改源程序。预处理器处理外部包含文件,比如上面的 `#include `。 它将会把这一行替换为 `stdio.h` C 标准库文件的完整内容,其中包含 `printf` 函数的声明。
+
+通过运行下面的命令来查看预处理步骤的输出:
+
+```
+clang -E compile_me.c -o preprocessed.i
+```
+
+**词法分析器**(或扫描器或分词器)将一串字符转化为一串单词。每一个单词或记号,被归并到五种语法类别之一:标点符号、关键字、标识符、文字或注释。
+
+compile_me.c 的分词过程:
+
+
+
+**语法分析器**确定源程序中的单词流是否组成了合法的句子。在分析记号流的语法后,它会输出一个抽象语法树(AST)。Clang 的 AST 中的节点表示声明、语句和类型。
+
+compile_me.c 的语法树:
+
+
+
+**语义分析器**会遍历抽象语法树,从而确定代码语句是否有正确意义。这个阶段会检查类型错误。如果 `compile_me.c` 的 main 函数返回 `"zero"`而不是 `0`, 那么语义分析器将会抛出一个错误,因为 `"zero"` 不是 `int` 类型。
+
+**IR 生成器**将抽象语法树翻译为 IR。
+
+对 compile_me.c 运行 clang 来生成 LLVM IR:
+
+```
+clang -S -emit-llvm -o llvm_ir.ll compile_me.c
+```
+
+在 `llvm_ir.ll` 中的 main 函数:
+
+```
+; llvm_ir.ll
+@.str = private unnamed_addr constant [18 x i8] c"Hello, Compiler!\0A\00", align 1
+
+define i32 @main() {
+ %1 = alloca i32, align 4 ; <- memory allocated on the stack
+ store i32 0, i32* %1, align 4
+ %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+```
+
+#### 优化程序
+
+优化程序的工作是基于其对程序的运行时行为的理解来提高代码效率。优化程序将 IR 作为输入,然后生成改进后的 IR 作为输出。LLVM 的优化工具 `opt` 将会通过标记 `-O2`(大写字母 `o`,数字 2)来优化处理器速度,通过标记 `Os`(大写字母 `o`,小写字母 `s`)来减少指令数目。
+
+看一看上面的前端工具生成的 LLVM IR 代码和运行下面的命令生成的结果之间的区别:
+
+```
+opt -O2 -S llvm_ir.ll -o optimized.ll
+```
+
+在 `optimized.ll` 中的 main 函数:
+
+```
+optimized.ll
+
+@str = private unnamed_addr constant [17 x i8] c"Hello, Compiler!\00"
+
+define i32 @main() {
+ %puts = tail call i32 @puts(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @str, i64 0, i64 0))
+ ret i32 0
+}
+
+declare i32 @puts(i8* nocapture readonly)
+```
+
+优化后的版本中, main 函数没有在栈中分配内存,因为它不使用任何内存。优化后的代码中调用 `puts` 函数而不是 `printf` 函数,因为程序中并没有使用 `printf` 函数的格式化功能。
+
+当然,优化程序不仅仅知道何时可以把 `printf` 函数用 `puts` 函数代替。优化程序也能展开循环并内联简单计算的结果。考虑下面的程序,它将两个整数相加并打印出结果。
+
+```
+// add.c
+#include
+
+int main() {
+ int a = 5, b = 10, c = a + b;
+ printf("%i + %i = %i\n", a, b, c);
+}
+```
+
+下面是未优化的 LLVM IR:
+
+```
+@.str = private unnamed_addr constant [14 x i8] c"%i + %i = %i\0A\00", align 1
+
+define i32 @main() {
+ %1 = alloca i32, align 4 ; <- allocate stack space for var a
+ %2 = alloca i32, align 4 ; <- allocate stack space for var b
+ %3 = alloca i32, align 4 ; <- allocate stack space for var c
+ store i32 5, i32* %1, align 4 ; <- store 5 at memory location %1
+ store i32 10, i32* %2, align 4 ; <- store 10 at memory location %2
+ %4 = load i32, i32* %1, align 4 ; <- load the value at memory address %1 into register %4
+ %5 = load i32, i32* %2, align 4 ; <- load the value at memory address %2 into register %5
+ %6 = add nsw i32 %4, %5 ; <- add the values in registers %4 and %5\. put the result in register %6
+ store i32 %6, i32* %3, align 4 ; <- put the value of register %6 into memory address %3
+ %7 = load i32, i32* %1, align 4 ; <- load the value at memory address %1 into register %7
+ %8 = load i32, i32* %2, align 4 ; <- load the value at memory address %2 into register %8
+ %9 = load i32, i32* %3, align 4 ; <- load the value at memory address %3 into register %9
+ %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i32 0, i32 0), i32 %7, i32 %8, i32 %9)
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+```
+
+下面是优化后的 LLVM IR:
+
+```
+@.str = private unnamed_addr constant [14 x i8] c"%i + %i = %i\0A\00", align 1
+
+define i32 @main() {
+ %1 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0), i32 5, i32 10, i32 15)
+ ret i32 0
+}
+
+declare i32 @printf(i8* nocapture readonly, ...)
+```
+
+优化后的 main 函数本质上是未优化版本的第 17 行和 18 行,伴有变量值内联。`opt` 计算加法,因为所有的变量都是常数。很酷吧,对不对?
+
+#### 后端
+
+LLVM 的后端工具是 `llc`。它分三个阶段将 LLVM IR 作为输入生成机器代码。
+
+* **指令选择**是将 IR 指令映射到目标机器的指令集。这个步骤使用虚拟寄存器的无限名字空间。
+* **寄存器分配**是将虚拟寄存器映射到目标体系结构的实际寄存器。我的 CPU 是 x86 结构,它只有 16 个寄存器。然而,编译器将会尽可能少的使用寄存器。
+* **指令安排**是重排操作,从而反映出目标机器的性能约束。
+
+运行下面这个命令将会产生一些机器代码:
+
+```
+llc -o compiled-assembly.s optimized.ll
+```
+
+```
+_main:
+ pushq %rbp
+ movq %rsp, %rbp
+ leaq L_str(%rip), %rdi
+ callq _puts
+ xorl %eax, %eax
+ popq %rbp
+ retq
+L_str:
+ .asciz "Hello, Compiler!"
+```
+
+这个程序是 x86 汇编语言,它是计算机所说的语言,并具有人类可读语法。某些人最后也许能理解我。
+
+* * *
+
+相关资源:
+
+1. [设计一个编译器][4]
+2. [开始探索 LLVM 核心库][5]
+
+--------------------------------------------------------------------------------
+
+via: https://nicoleorchard.com/blog/compilers
+
+作者:[Nicole Orchard][a]
+译者:[ucasFL](https://github.com/ucasFL)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://nicoleorchard.com/
+[1]:http://clang.llvm.org/
+[2]:http://llvm.org/docs/CommandGuide/opt.html
+[3]:http://llvm.org/docs/CommandGuide/llc.html
+[4]:https://www.amazon.com/Engineering-Compiler-Second-Keith-Cooper/dp/012088478X
+[5]:https://www.amazon.com/Getting-Started-LLVM-Core-Libraries/dp/1782166920
+[6]:https://twitter.com/norchard/status/864246049266958336
+[7]:http://llvm.org/
\ No newline at end of file
diff --git a/sources/tech/20170815 Getting Started with Headless Chrome.md b/published/20170815 Getting Started with Headless Chrome.md
similarity index 50%
rename from sources/tech/20170815 Getting Started with Headless Chrome.md
rename to published/20170815 Getting Started with Headless Chrome.md
index 6d4c9bc3cc..fc65331a10 100644
--- a/sources/tech/20170815 Getting Started with Headless Chrome.md
+++ b/published/20170815 Getting Started with Headless Chrome.md
@@ -1,20 +1,20 @@
-Getting Started with Headless Chrome
+Headless Chrome 入门
============================================================
-### TL;DR
+### 摘要
-[Headless Chrome][9] is shipping in Chrome 59\. It's a way to run the Chrome browser in a headless environment. Essentially, running Chrome without chrome! It brings **all modern web platform features** provided by Chromium and the Blink rendering engine to the command line.
+在 Chrome 59 中开始搭载 [Headless Chrome][9]。这是一种在无需显示的环境下运行 Chrome 浏览器的方式。从本质上来说,就是不用 chrome 浏览器来运行 Chrome 的功能!它将 Chromium 和 Blink 渲染引擎提供的所有现代 Web 平台的功能都带入了命令行。
-Why is that useful?
+它有什么用?
-A headless browser is a great tool for automated testing and server environments where you don't need a visible UI shell. For example, you may want to run some tests against a real web page, create a PDF of it, or just inspect how the browser renders an URL.
+无需显示的浏览器对于自动化测试和不需要可视化 UI 界面的服务器环境是一个很好的工具。例如,你可能需要对真实的网页运行一些测试,创建一个 PDF,或者只是检查浏览器如何呈现 URL。
-
+> **注意:** Mac 和 Linux 上的 Chrome 59 都可以运行无需显示模式。[对 Windows 的支持][2]将在 Chrome 60 中提供。要检查你使用的 Chrome 版本,请在浏览器中打开 `chrome://version`。
-### Starting Headless (CLI)
+### 开启无需显示模式(命令行界面)
-The easiest way to get started with headless mode is to open the Chrome binary from the command line. If you've got Chrome 59+ installed, start Chrome with the `--headless` flag:
+开启无需显示模式最简单的方法是从命令行打开 Chrome 二进制文件。如果你已经安装了 Chrome 59 以上的版本,请使用 `--headless` 标志启动 Chrome:
```
chrome \
@@ -24,11 +24,11 @@ chrome \
https://www.chromestatus.com # URL to open. Defaults to about:blank.
```
-
+> **注意:**目前你仍然需要使用 `--disable-gpu` 标志。但它最终会不需要的。
-`chrome` should point to your installation of Chrome. The exact location will vary from platform to platform. Since I'm on Mac, I created convenient aliases for each version of Chrome that I have installed.
+`chrome` 二进制文件应该指向你安装 Chrome 的位置。确切的位置会因平台差异而不同。当前我在 Mac 上操作,所以我为安装的每个版本的 Chrome 都创建了方便使用的别名。
-If you're on the stable channel of Chrome and cannot get the Beta, I recommend using `chrome-canary`:
+如果您使用 Chrome 的稳定版,并且无法获得测试版,我建议您使用 `chrome-canary` 版本:
```
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
@@ -36,31 +36,31 @@ alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Goo
alias chromium="/Applications/Chromium.app/Contents/MacOS/Chromium"
```
-Download Chrome Canary [here][10].
+在[这里][10]下载 Chrome Cannary。
-### Command line features
+### 命令行的功能
-In some cases, you may not need to [programmatically script][11] Headless Chrome. There are some [useful command line flags][12] to perform common tasks.
+在某些情况下,你可能不需要[以脚本编程的方式][11]操作 Headless Chrome。可以使用一些[有用的命令行标志][12]来执行常见的任务。
-### Printing the DOM
+#### 打印 DOM
-The `--dump-dom` flag prints `document.body.innerHTML` to stdout:
+`--dump-dom` 标志将打印 `document.body.innerHTML` 到标准输出:
```
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
```
-### Create a PDF
+#### 创建一个 PDF
-The `--print-to-pdf` flag creates a PDF of the page:
+`--print-to-pdf` 标志将页面转出为 PDF 文件:
```
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
```
-### Taking screenshots
+#### 截图
-To capture a screenshot of a page, use the `--screenshot` flag:
+要捕获页面的屏幕截图,请使用 `--screenshot` 标志:
```
chrome --headless --disable-gpu --screenshot https://www.chromestatus.com/
@@ -72,11 +72,11 @@ chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://www
chrome --headless --disable-gpu --screenshot --window-size=412,732 https://www.chromestatus.com/
```
-Running with `--screenshot` will produce a file named `screenshot.png` in the current working directory. If you're looking for full page screenshots, things are a tad more involved. There's a great blog post from David Schnurr that has you covered. Check out [Using headless Chrome as an automated screenshot tool ][13].
+使用 `--screenshot` 标志运行 Headless Chrome 将在当前工作目录中生成一个名为 `screenshot.png` 的文件。如果你正在寻求整个页面的截图,那么会涉及到很多事情。来自 David Schnurr 的一篇很棒的博文已经介绍了这一内容。请查看 [使用 headless Chrome 作为自动截屏工具][13]。
-### REPL mode (read-eval-print loop)
+#### REPL 模式 (read-eval-print loop)
-The `--repl` flag runs Headless in a mode where you can evaluate JS expressions in the browser, right from the command line:
+`--repl` 标志可以使 Headless Chrome 运行在一个你可以使用浏览器评估 JS 表达式的模式下。执行下面的命令:
```
$ chrome --headless --disable-gpu --repl https://www.chromestatus.com/
@@ -84,35 +84,35 @@ $ chrome --headless --disable-gpu --repl https://www.chromestatus.com/
>>> location.href
{"result":{"type":"string","value":"https://www.chromestatus.com/features"}}
>>> quit
-$
```
-### Debugging Chrome without a browser UI?
+### 在没有浏览器界面的情况下调试 Chrome
-When you run Chrome with `--remote-debugging-port=9222`, it starts an instance with the [DevTools protocol][14] enabled. The protocol is used to communicate with Chrome and drive the headless browser instance. It's also what tools like Sublime, VS Code, and Node use for remote debugging an application. #synergy
+当你使用 `--remote-debugging-port=9222` 运行 Chrome 时,它会启动一个支持 [DevTools 协议][14]的实例。该协议用于与 Chrome 进行通信,并且驱动 Headless Chrome 浏览器实例。它也是一个类似 Sublime、VS Code 和 Node 的工具,可用于应用程序的远程调试。#协同效应
-Since you don't have browser UI to see the page, navigate to `http://localhost:9222` in another browser to check that everything is working. You'll see a list of inspectable pages where you can click through and see what Headless is rendering:
+由于你没有浏览器用户界面可用来查看网页,请在另一个浏览器中输入 `http://localhost:9222`,以检查一切是否正常。你将会看到一个可检查的页面的列表,可以点击它们来查看 Headless Chrome 正在呈现的内容:

-DevTools remote debugging UI
-From here, you can use the familiar DevTools features to inspect, debug, and tweak the page as you normally would. If you're using Headless programmatically, this page is also a powerful debugging tool for seeing all the raw DevTools protocol commands going across the wire, communicating with the browser.
+*DevTools 远程调试界面*
-### Using programmatically (Node)
+从这里,你就可以像往常一样使用熟悉的 DevTools 来检查、调试和调整页面了。如果你以编程方式使用 Headless Chrome,这个页面也是一个功能强大的调试工具,用于查看所有通过网络与浏览器交互的原始 DevTools 协议命令。
-### The Puppeteer API
+### 使用编程模式 (Node)
-[Puppeteer][15] is a Node library developed by the Chrome team. It provides a high-level API to control headless (or full) Chrome. It's similar to other automated testing libraries like Phantom and NightmareJS, but it only works with the latest versions of Chrome.
+#### Puppeteer 库 API
-Among other things, Puppeteer can be used to easily take screenshots, create PDFs, navigate pages, and fetch information about those pages. I recommend the library if you want to quickly automate browser testing. It hides away the complexities of the DevTools protocol and takes care of redundant tasks like launching a debug instance of Chrome.
+[Puppeteer][15] 是一个由 Chrome 团队开发的 Node 库。它提供了一个高层次的 API 来控制无需显示版(或 完全版)的 Chrome。它与其他自动化测试库,如 Phantom 和 NightmareJS 相类似,但是只适用于最新版本的 Chrome。
-Install it:
+除此之外,Puppeteer 还可用于轻松截取屏幕截图,创建 PDF,页面间导航以及获取有关这些页面的信息。如果你想快速地自动化进行浏览器测试,我建议使用该库。它隐藏了 DevTools 协议的复杂性,并可以处理诸如启动 Chrome 调试实例等繁冗的任务。
+
+安装:
```
yarn add puppeteer
```
-**Example** - print the user agent
+**例子** - 打印用户代理:
```
const puppeteer = require('puppeteer');
@@ -124,7 +124,7 @@ const puppeteer = require('puppeteer');
})();
```
-**Example** - taking a screenshot of the page
+**例子** - 获取页面的屏幕截图:
```
const puppeteer = require('puppeteer');
@@ -140,19 +140,19 @@ browser.close();
})();
```
-Check out [Puppeteer's documentation][16] to learn more about the full API.
+查看 [Puppeteer 的文档][16],了解完整 API 的更多信息。
-### The CRI library
+#### CRI 库
-[chrome-remote-interface][17] is a lower-level library than Puppeteer's API. I recommend it if you want to be close to the metal and use the [DevTools protocol][18] directly.
+[chrome-remote-interface][17] 是一个比 Puppeteer API 更低层次的库。如果你想要更接近原始信息和更直接地使用 [DevTools 协议][18]的话,我推荐使用它。
-#### Launching Chrome
+**启动 Chrome**
-chrome-remote-interface doesn't launch Chrome for you, so you'll have to take care of that yourself.
+chrome-remote-interface 不会为你启动 Chrome,所以你要自己启动它。
-In the CLI section, we [started Chrome manually][19] using `--headless --remote-debugging-port=9222`. However, to fully automate tests, you'll probably want to spawn Chrome _from_ your application.
+在前面的 CLI 章节中,我们使用 `--headless --remote-debugging-port=9222` [手动启动了 Chrome][19]。但是,要想做到完全自动化测试,你可能希望从你的应用程序中启动 Chrome。
-One way is to use `child_process`:
+其中一种方法是使用 `child_process`:
```
const execFile = require('child_process').execFile;
@@ -168,19 +168,19 @@ launchHeadlessChrome('https://www.chromestatus.com', (err, stdout, stderr) => {
});
```
-But things get tricky if you want a portable solution that works across multiple platforms. Just look at that hard-coded path to Chrome :(
+但是如果你想要在多个平台上运行可移植的解决方案,事情会变得很棘手。请注意 Chrome 的硬编码路径:
-##### Using ChromeLauncher
+**使用 ChromeLauncher**
-[Lighthouse][20] is a marvelous tool for testing the quality of your web apps. A robust module for launching Chrome was developed within Lighthouse and is now extracted for standalone use. The [`chrome-launcher` NPM module][21] will find where Chrome is installed, set up a debug instance, launch the browser, and kill it when your program is done. Best part is that it works cross-platform thanks to Node!
+[Lighthouse][20] 是一个令人称奇的网络应用的质量测试工具。Lighthouse 内部开发了一个强大的用于启动 Chrome 的模块,现在已经被提取出来单独使用。[chrome-launcher NPM 模块][21] 可以找到 Chrome 的安装位置,设置调试实例,启动浏览器和在程序运行完之后将其杀死。它最好的一点是可以跨平台工作,感谢 Node!
-By default, **`chrome-launcher` will try to launch Chrome Canary** (if it's installed), but you can change that to manually select which Chrome to use. To use it, first install from npm:
+默认情况下,**chrome-launcher 会尝试启动 Chrome Canary**(如果已经安装),但是你也可以更改它,手动选择使用的 Chrome 版本。要想使用它,首先从 npm 安装:
```
yarn add chrome-launcher
```
-**Example** - using `chrome-launcher` to launch Headless
+**例子** - 使用 `chrome-launcher` 启动 Headless Chrome:
```
const chromeLauncher = require('chrome-launcher');
@@ -214,23 +214,21 @@ launchChrome().then(chrome => {
});
```
-Running this script doesn't do much, but you should see an instance of Chrome fire up in the task manager that loaded `about:blank`. Remember, there won't be any browser UI. We're headless.
+运行这个脚本没有做太多的事情,但你应该能在任务管理器中看到启动了一个 Chrome 的实例,它加载了页面 `about:blank`。记住,它不会有任何的浏览器界面,我们是无需显示的。
-To control the browser, we need the DevTools protocol!
+为了控制浏览器,我们需要 DevTools 协议!
-#### Retrieving information about the page
+#### 检索有关页面的信息
-
+> **警告:** DevTools 协议可以做一些有趣的事情,但是起初可能有点令人生畏。我建议先花点时间浏览 [DevTools 协议查看器][3]。然后,转到 `chrome-remote-interface` 的 API 文档,看看它是如何包装原始协议的。
-Let's install the library:
+我们来安装该库:
```
yarn add chrome-remote-interface
```
-##### Examples
-
-**Example** - print the user agent
+**例子** - 打印用户代理:
```
const CDP = require('chrome-remote-interface');
@@ -243,9 +241,9 @@ launchChrome().then(async chrome => {
});
```
-Results in something like: `HeadlessChrome/60.0.3082.0`
+结果是类似这样的东西:`HeadlessChrome/60.0.3082.0`。
-**Example** - check if the site has a [web app manifest][22]
+**例子** - 检查网站是否有 [Web 应用程序清单][22]:
```
const CDP = require('chrome-remote-interface');
@@ -282,7 +280,7 @@ Page.loadEventFired(async () => {
})();
```
-**Example** - extract the `` of the page using DOM APIs.
+**例子** - 使用 DOM API 提取页面的 ``:
```
const CDP = require('chrome-remote-interface');
@@ -316,21 +314,21 @@ Page.loadEventFired(async () => {
})();
```
-### Using Selenium, WebDriver, and ChromeDriver
+### 使用 Selenium、WebDriver 和 ChromeDriver
-Right now, Selenium opens a full instance of Chrome. In other words, it's an automated solution but not completely headless. However, Selenium can be configured to run headless Chrome with a little work. I recommend [Running Selenium with Headless Chrome][23] if you want the full instructions on how to set things up yourself, but I've dropped in some examples below to get you started.
+现在,Selenium 开启了 Chrome 的完整实例。换句话说,这是一个自动化的解决方案,但不是完全无需显示的。但是,Selenium 只需要进行小小的配置即可运行 Headless Chrome。如果你想要关于如何自己设置的完整说明,我建议你阅读“[使用 Headless Chrome 来运行 Selenium][23]”,不过你可以从下面的一些示例开始。
-#### Using ChromeDriver
+#### 使用 ChromeDriver
-[ChromeDriver][24] 2.3.0 supports Chrome 59 and later and works with headless Chrome. In some cases, you may need Chrome 60 to work around bugs. For example, there are known issues with taking screenshots in Chrome 59.
+[ChromeDriver][24] 2.3.0 支持 Chrome 59 及更新版本,可与 Headless Chrome 配合使用。在某些情况下,你可能需要等到 Chrome 60 以解决 bug。例如,Chrome 59 中屏幕截图已知存在问题。
-Install:
+安装:
```
yarn add selenium-webdriver chromedriver
```
-Example:
+例子:
```
const fs = require('fs');
@@ -368,17 +366,17 @@ driver.takeScreenshot().then(base64png => {
driver.quit();
```
-#### Using WebDriverIO
+#### 使用 WebDriverIO
-[WebDriverIO][25] is a higher level API on top of Selenium WebDriver.
+[WebDriverIO][25] 是一个在 Selenium WebDrive 上构建的更高层次的 API。
-Install:
+安装:
```
yarn add webdriverio chromedriver
```
-Example: filter CSS features on chromestatus.com
+例子:过滤 chromestatus.com 上的 CSS 功能:
```
const webdriverio = require('webdriverio');
@@ -435,71 +433,69 @@ browser.end();
})();
```
-### Further resources
+### 更多资源
-Here are some useful resources to get you started:
+以下是一些可以带你入门的有用资源:
-Docs
+文档
-* [DevTools Protocol Viewer][4] - API reference docs
+* [DevTools Protocol Viewer][4] - API 参考文档
-Tools
+工具
-* [chrome-remote-interface][5] - node module that wraps the DevTools protocol
+* [chrome-remote-interface][5] - 基于 DevTools 协议的 node 模块
+* [Lighthouse][6] - 测试 Web 应用程序质量的自动化工具;大量使用了协议
+* [chrome-launcher][7] - 用于启动 Chrome 的 node 模块,可以自动化
-* [Lighthouse][6] - automated tool for testing web app quality; makes heavy use of the protocol
+样例
-* [chrome-launcher][7] - node module for launching Chrome, ready for automation
+* "[The Headless Web][8]" - Paul Kinlan 发布的使用了 Headless 和 api.ai 的精彩博客
-Demos
+### 常见问题
-* "[The Headless Web][8]" - Paul Kinlan's great blog post on using Headless with api.ai.
+**我需要 `--disable-gpu` 标志吗?**
-### FAQ
+目前是需要的。`--disable-gpu` 标志在处理一些 bug 时是需要的。在未来版本的 Chrome 中就不需要了。查看 [https://crbug.com/546953#c152][26] 和 [https://crbug.com/695212][27] 获取更多信息。
-**Do I need the `--disable-gpu` flag?**
+**所以我仍然需要 Xvfb 吗?**
-Yes, for now. The `--disable-gpu` flag is a temporary requirement to work around a few bugs. You won't need this flag in future versions of Chrome. See [https://crbug.com/546953#c152][26] and [https://crbug.com/695212][27] for more information.
+不。Headless Chrome 不使用窗口,所以不需要像 Xvfb 这样的显示服务器。没有它你也可以愉快地运行你的自动化测试。
-**So I still need Xvfb?**
+什么是 Xvfb?Xvfb 是一个用于类 Unix 系统的运行于内存之内的显示服务器,可以让你运行图形应用程序(如 Chrome),而无需附加的物理显示器。许多人使用 Xvfb 运行早期版本的 Chrome 进行 “headless” 测试。
-No. Headless Chrome doesn't use a window so a display server like Xvfb is no longer needed. You can happily run your automated tests without it.
+**如何创建一个运行 Headless Chrome 的 Docker 容器?**
-What is Xvfb? Xvfb is an in-memory display server for Unix-like systems that enables you to run graphical applications (like Chrome) without an attached physical display. Many people use Xvfb to run earlier versions of Chrome to do "headless" testing.
+查看 [lighthouse-ci][28]。它有一个使用 Ubuntu 作为基础镜像的 [Dockerfile 示例][29],并且在 App Engine Flexible 容器中安装和运行了 Lighthouse。
-**How do I create a Docker container that runs Headless Chrome?**
+**我可以把它和 Selenium / WebDriver / ChromeDriver 一起使用吗?**
-Check out [lighthouse-ci][28]. It has an [example Dockerfile][29] that uses Ubuntu as a base image, and installs + runs Lighthouse in an App Engine Flexible container.
+是的。查看 [Using Selenium, WebDrive, or ChromeDriver][30]。
-**Can I use this with Selenium / WebDriver / ChromeDriver**?
+**它和 PhantomJS 有什么关系?**
-Yes. See [Using Selenium, WebDrive, or ChromeDriver][30].
+Headless Chrome 和 [PhantomJS][31] 是类似的工具。它们都可以用来在无需显示的环境中进行自动化测试。两者的主要不同在于 Phantom 使用了一个较老版本的 WebKit 作为它的渲染引擎,而 Headless Chrome 使用了最新版本的 Blink。
-**How is this related to PhantomJS?**
+目前,Phantom 提供了比 [DevTools protocol][32] 更高层次的 API。
-Headless Chrome is similar to tools like [PhantomJS][31]. Both can be used for automated testing in a headless environment. The main difference between the two is that Phantom uses an older version of WebKit as its rendering engine while Headless Chrome uses the latest version of Blink.
+**我在哪儿提交 bug?**
-At the moment, Phantom also provides a higher level API than the [DevTools protocol][32].
+对于 Headless Chrome 的 bug,请提交到 [crbug.com][33]。
-**Where do I report bugs?**
-
-For bugs against Headless Chrome, file them on [crbug.com][33].
-
-For bugs in the DevTools protocol, file them at [github.com/ChromeDevTools/devtools-protocol][34].
+对于 DevTools 协议的 bug,请提交到 [github.com/ChromeDevTools/devtools-protocol][34]。
--------------------------------------------------------------------------------
作者简介
-[Eric Bidelman][1]Engineer @ Google working on Lighthouse, Web Components, Chrome, and the web
+[Eric Bidelman][1] 谷歌工程师,Lighthouse 开发,Web 和 Web 组件开发,Chrome 开发
-----------------------------------
via: https://developers.google.com/web/updates/2017/04/headless-chrome
-作者:[Eric Bidelman ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
+作者:[Eric Bidelman][a]
+译者:[firmianay](https://github.com/firmianay)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/published/20170821 Getting started with ImageMagick.md b/published/20170821 Getting started with ImageMagick.md
new file mode 100644
index 0000000000..14d25f8eff
--- /dev/null
+++ b/published/20170821 Getting started with ImageMagick.md
@@ -0,0 +1,184 @@
+ImageMagick 入门:使用命令行来编辑图片
+============================================================
+
+> 了解使用此轻量级图像编辑器查看和修改图像的常见方法。
+
+
+
+
+在最近一篇关于[轻量级图像查看器][8]的文章中,作者 Scott Nesbitt 提到了 `display`,它是 [ImageMagick][9] 中的一个组件。ImageMagick 不仅仅是一个图像查看器,它还提供了大量的图像编辑工具和选项。本教程将详细介绍如何在 ImageMagick 中使用 `display` 命令和其他命令行工具。
+
+现在有许多优秀的图像编辑器可用,你可能会想知道为什么有人会选择一个非 GUI 的、基于命令行的程序,如 ImageMagick。一方面,它非常可靠。但更大的好处是,它允许你建立一个以特定的方式编辑大量图像的方式。
+
+这篇对于常见的 ImageMagick 命令的介绍应该让你入门。
+
+### display 命令
+
+让我们从 Scott 提到的命令开始:`display`。假设你有一个目录,其中有很多想要查看的图像。使用以下命令开始 `display`:
+
+```
+cd Pictures
+display *.JPG
+```
+
+这将按照字母数字顺序顺序加载你的 JPG 文件,每张放在一个简单的窗口中。左键单击图像可以打开一个简单的独立菜单(ImageMagick 中唯一的 GUI 功能)。
+
+
+
+你可以在 **display** 菜单中找到以下内容:
+
+* **File** 包含选项 Open、Next、Former、Select、Save、Print、Delete、New、Visual Directory 和 Quit。 _Select_ 来选择要显示的特定文件,_Visual Directory_ 显示当前工作目录中的所有文件(而不仅仅是图像)。如果要滚动显示所有选定的图像,你可以使用 _Next_ 和 _Former_,但使用键盘快捷键(下一张图像用空格键,上一张图像用退格)更容易。
+* **Edit** 提供 Undo、Redo、Cut、Copy 和 Paste,它们只是辅助命令进行更具体的编辑过程。 当你进行不同的编辑功能看看它们做什么时 _Undo_ 特别有用。
+* **View** 有 Half Size、Original Size、Double Size、Resize、Apply、Refresh 和 Restore。这些大多是不用说明的,除非你在应用其中之一后保存图像,否则图像文件不会更改。_Resize_ 会打开一个对话框,以像素为单位,带有或者不带尺寸限制,或者是百分比指定图片大小。我不知道 _Apply_ 会做什么。
+* **Transform** 显示 Crop、Chop、Flop、Flip、Rotate Right、Rotate Left、Rotate、Shear、Roll 和 Trim Edges。_Chop_ 使用点击拖动操作剪切图像的垂直或水平部分,将边缘粘贴在一起。了解这些功能如何工作的最佳方法是操作它们,而不是看看。
+* **Enhance** 提供 Hue、Saturation、Brightness、Gamma、Spiff、Dull、Contrast Stretch、Sigmoidal Contrast、Normalize、Equalize、Negate、Grayscale、Map 和 Quantize。这些是用于颜色和调整亮度和对比度的操作。
+* **效果** 有 Despeckle、Emboss、Reduce Noise、Add Noise、Sharpen、Blur、Threshold、Edge Detect、Spread、Shade、Raise 和 Segment。这些是相当标准的图像编辑效果。
+* **F/X** 选项有 Solarize、Sepia Tone、Swirl、Implode、Vignette、Wave、Oil Paint 和 Charcoal Draw,在图像编辑器中也是非常常见的效果。
+* **Image Edit** 包含 Annotate、Draw、Color、Matte、Composite、Add Border、Add Frame、Comment、Launch 和 Region of Interest。_Launch _ 将打开 GIMP 中的当前图像(至少在我的 Fedora 中是这样)。 _Region of Interest_ 允许你选择一个区域来应用编辑。按下 Esc 取消选择该区域。
+* **Miscellany** 提供 Image Info、Zoom Image、Show Preview、Show Histogram、Show Matte、Background、Slide Show 和 Preferences。 _Show Preview_ 似乎很有趣,但我努力让它工作。
+* **Help** 有 Overview、Browse Documentation 和 About Display。 _Overview_ 提供了大量关于 display 的基本信息,并且包含大量内置的键盘快捷键,用于各种命令和操作。在我的 Fedora 中,_Browse Documentation_ 没有作用。
+
+虽然 `display` 的 GUI 界面提供了一个称职的图像编辑器,但 ImageMagick 还提供了 89 个命令行选项,其中许多与上述菜单项相对应。例如,如果我显示的数码相片目录中的图像大于我的屏幕尺寸,我不用在显示后单独调整大小,我可以指定:
+
+```
+display -resize 50% *.JPG
+```
+
+上面菜单中的许多操作都可以通过在命令行中添加一个选项来完成。但是还有其他的选项在菜单中没有,包括 `-monochrome`,将图像转换为黑白(不是灰度),还有 `-colors`,你可以指定在图像中使用多少种颜色。例如,尝试这些:
+
+```
+display -resize 50% -monochrome *.JPG
+```
+
+```
+display -resize 50% -colors 8 *.JPG
+```
+
+这些操作会创建有趣的图像。试试增强颜色或进行其他编辑后减少颜色。记住,除非你保存并覆盖它们,否则原始文件保持不变。
+
+### convert 命令
+
+`convert` 命令有 237 个选项 - 是的, 237 个! - 它提供了你可以做的各种各样的事情(其中一些 `display` 也可以做)。我只会覆盖其中的几个,主要是图像操作。你可以用 `convert` 做的两件简单的事情是:
+
+```
+convert DSC_0001.JPG dsc0001.png
+```
+
+```
+convert *.bmp *.png
+```
+
+第一个命令将单个文件(DSC_0001)从 JPG 转换为 PNG 格式,而不更改原始文件。第二个将对目录中的所有 BMP 图像执行此操作。
+
+如果要查看 ImageMagick 可以使用的格式,请输入:
+
+```
+identify -list format
+```
+
+我们来看几个用 `convert` 命令来处理图像的有趣方法。以下是此命令的一般格式:
+
+```
+convert inputfilename [options] outputfilename
+```
+
+你有多个选项,它们按照从左到右排列的顺序完成。
+
+以下是几个简单的选项:
+
+```
+convert monochrome_source.jpg -monochrome monochrome_example.jpg
+```
+
+
+
+
+```
+convert DSC_0008.jpg -charcoal 1.2 charcoal_example.jpg
+```
+
+
+
+`-monochrome` 选项没有关联的设置,但 `-charcoal` 变量需要一个相关因子。根据我的经验,它需要一个小的数字(甚至小于 1)来实现类似于炭笔绘画的东西,否则你会得到很大的黑色斑点。即使如此,图像中的尖锐边缘也是非常明显的,与炭笔绘画不同。
+
+现在来看看这些:
+
+```
+convert DSC_0032.JPG -edge 3 edge_demo.jpg
+```
+
+```
+convert DSC_0032.JPG -colors 4 reduced4_demo.jpg
+```
+
+```
+convert DSC_0032.JPG -colors 4 -edge 3 reduced+edge_demo.jpg
+```
+
+
+
+原始图像位于左上方。在第一个命令中,我使用了一个 `-edge` 选项,设置为 3(见右上角的图像) - 对于我的喜好而言小于它的数字都太精细了。在第二个命令(左下角的图像)中,我们将颜色的数量减少到了 4 个,与原来没有什么不同。但是看看当我们在第三个命令中组合这两个时,会发生什么(右下角的图像)!也许这有点大胆,但谁能预期到从原始图像或任何一个选项变成这个结果?
+
+`-canny` 选项提供了另外一个惊喜。这是另一种边缘检测器,称为“多阶算法”。单独使用 `-canny` 可以产生基本黑色的图像和一些白线。我后面跟着一个 `-negate` 选项:
+
+```
+convert DSC_0049.jpg -canny 0x1 -negate canny_egret.jpg
+convert DSC_0023.jpg -canny 0x1 -negate canny_ship.jpg
+```
+
+
+
+这有点极简主义,但我认为它类似于一种笔墨绘画,与原始照片有相当显著的差异。它并不能用于所有图片。一般来说,它对有锐利线条的图像效果最好。不是焦点的元素可能会消失。注意白鹭图片中的背景沙滩没有显示,因为它是模糊的。同样注意下船舶图片,虽然大多数边缘显示得非常好,因为没有颜色,我们失去了图片的整体形象,所以也许这可以作为一些数字着色,甚至在印后着色的基础。
+
+### montage 命令
+
+最后,我想谈一下 `montage` (蒙太奇)命令。我已经在上面展示了这个例子,我将单个图像组合成复合图片。
+
+这是我如何生成炭笔的例子(请注意,它们都在一行):
+
+```
+montage -label %f DSC_0008.jpg charcoal_example.jpg -geometry +10+10
+ -resize 25% -shadow -title 'charcoal demo' charcoal_demo.jpg
+```
+
+`-label` 选项会在每个图像下方标记它的文件名(`%f`)。不用 `-geometry` 选项,所有的图像将是缩略图大小(120 像素宽),`+10+10` 负责边框大小。接下来,我调整了整个最终组合的大小(`-resize 25%`),并添加了一个阴影(没有设置,因此是默认值),最后为这次 montage 操作创建了一个标题(`-title`)。
+
+你可以将所有图像名称放在最后,最后一个图像的名称将是 `montage` 操作所保存的文件名。这可用于为命令及其所有选项创建别名,然后我可以简单地键入该别名、输入适当的文件名即可。我偶尔会这么做来减少 `montage` 操作需要输入的命令长度。
+
+在 `-canny` 的例子中,我对 4 张图像进行了蒙太奇操作。我添加了 `-tile` 选项,确切地说是 `-tile 2x`,它创建了有两列的蒙太奇。我可以指定一个 `matrix`、`-tile 2x2` 或 `-tile x2` 来产生相同的结果。
+
+ImageMagick 还有更多可以了解,所以我打算写更多关于它的文章,甚至可能使用 [Perl][10] 脚本运行 ImageMagick 命令。ImageMagick 具有丰富的[文档][11],尽管该网站在示例或者显示结果上还不足,我认为最好的学习方式是通过实验和更改各种设置和选项来学习。
+
+(题图: opensource.com)
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Greg Pittman - Greg 是肯塔基州路易斯维尔的一名退休的神经科医生,对计算机和程序设计有着长期的兴趣,从 1960 年代的 Fortran IV 开始。当 Linux 和开源软件相继出现时,他开始学习更多,并最终做出贡献。他是 Scribus 团队的成员。
+
+---------------------
+
+via: https://opensource.com/article/17/8/imagemagick
+
+作者:[Greg Pittman][a]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/greg-p
+[1]:https://opensource.com/file/367401
+[2]:https://opensource.com/file/367391
+[3]:https://opensource.com/file/367396
+[4]:https://opensource.com/file/367381
+[5]:https://opensource.com/file/367406
+[6]:https://opensource.com/article/17/8/imagemagick?rate=W2W3j4nu4L14gOClu1RhT7GOMDS31pUdyw-dsgFNqYI
+[7]:https://opensource.com/user/30666/feed
+[8]:https://opensource.com/article/17/7/4-lightweight-image-viewers-linux-desktop
+[9]:https://www.imagemagick.org/script/index.php
+[10]:https://opensource.com/sitewide-search?search_api_views_fulltext=perl
+[11]:https://imagemagick.org/script/index.php
+[12]:https://opensource.com/users/greg-p
+[13]:https://opensource.com/users/greg-p
+[14]:https://opensource.com/article/17/8/imagemagick#comments
diff --git a/published/20170823 Using Ansible for deploying serverless applications.md b/published/20170823 Using Ansible for deploying serverless applications.md
new file mode 100644
index 0000000000..2c435b3a45
--- /dev/null
+++ b/published/20170823 Using Ansible for deploying serverless applications.md
@@ -0,0 +1,116 @@
+使用 Ansible 部署无服务(serverless)应用
+============================================================
+
+> 无服务是托管服务发展方向的又一步,并且与 Ansible 的无代理体系结构相得益彰。
+
+
+
+[Ansible][8] 被设计为实际工作中的最简化的部署工具。这意味着它不是一个完整的编程语言。你需要编写定义任务的 YAML 模板,并列出任何需要自动完成的任务。
+
+大多数人认为 Ansible 是一种更强大的“处于 for 循环中的 SSH”,在简单的使用场景下这是真的。但其实 Ansible 是_任务_,而非 SSH。在很多情况下,我们通过 SSH 进行连接,但它也支持 Windows 机器上的 Windows 远程管理(WinRM),以及作为云服务的通用语言的 HTTPS API 之类的东西。
+
+在云中,Ansible 可以在两个独立的层面上操作:控制面和实例资源。控制面由所有_没有_运行在操作系统上的东西组成。包括设置网络、新建实例、供给更高级别的服务,如亚马逊的 S3 或 DynamoDB,以及保持云基础设施安全和服务客户所需的一切。
+
+实例上的工作是你已经知道 Ansible 可以做的:启动和停止服务、配置文件模版化、安装软件包以及通过 SSH 执行的所有与操作系统相关的操作。
+
+现在,什么是[无服务][9]呢?这要看你问谁,无服务要么是对公有云的无限延伸,或者是一个全新的范例,其中所有的东西都是 API 调用,以前从来没有这样做过。
+
+Ansible 采取第一种观点。在 “无服务” 是专门术语之前,用户不得不管理和配置 EC2 实例、虚拟私有云 (VPC) 网络以及其他所有内容。无服务是托管服务方向迈出的另一步,并且与 Ansible 的无代理体系结构相得益彰。
+
+在我们开始 [Lambda][10] 示例之前,让我们来看一个简单的配置 CloudFormation 栈任务:
+
+```
+- name: Build network
+ cloudformation:
+ stack_name: prod-vpc
+ state: present
+ template: base_vpc.yml
+```
+
+编写这样的任务只需要几分钟,但它是构建基础架构所涉及的最后的半手动步骤 - 点击 “Create Stack” - 这将 playbook 与其他放在一起。现在你的 VPC 只是在建立新区域时可以调用的另一项任务了。
+
+由于云提供商是你帐户中发生些什么的真相来源,因此 Ansible 有许多方法来取回并使用 ID、名称和其他参数来过滤和查询运行的实例或网络。以 `cloudformation_facts` 模块为例,我们可以从我们刚刚创建的模板中得到子网 ID、网络范围和其他数据。
+
+```
+- name: Pull all new resources back in as a variable
+ cloudformation_facts:
+ stack_name: prod-vpc
+ register: network_stack
+```
+
+对于无服务应用,除了 DynamoDB 表,S3 bucket 和其他任何其他功能之外,你肯定还需要一个 Lambda 函数的补充。幸运的是,通过使用 `lambda` 模块, Lambda 函数可以以上次任务的堆栈相同的方式创建:
+
+```
+- lambda:
+ name: sendReportMail
+ zip_file: "{{ deployment_package }}"
+ runtime: python3.6
+ handler: report.send
+ memory_size: 1024
+ role: "{{ iam_exec_role }}"
+ register: new_function
+```
+
+如果你有其他想用来交付无服务应用的工具,这也是可以的。开源的[无服务框架][11]有自己的 Ansible 模块,它也可以工作:
+
+```
+- serverless:
+ service_path: '{{ project_dir }}'
+ stage: dev
+ register: sls
+- name: Serverless uses CloudFormation under the hood, so you can easily pull info back into Ansible
+ cloudformation_facts:
+ stack_name: "{{ sls.service_name }}"
+ register: sls_facts
+```
+
+这不是你需要的全部,因为无服务项目也必须存在,你将在那里大量的定义你的函数和事件源。对于此例,我们将制作一个响应 HTTP 请求的函数。无服务框架使用 YAML 作为其配置语言(和 Ansible 一样),所以这应该看起来很熟悉。
+
+```
+# serverless.yml
+service: fakeservice
+
+provider:
+ name: aws
+ runtime: python3.6
+
+functions:
+ main:
+ handler: test_function.handler
+ events:
+ - http:
+ path: /
+ method: get
+```
+
+在 [AnsibleFest][12] 中,我将介绍这个例子和其他深入的部署策略,以最大限度地利用你已经拥有的 playbook 和基础设施,还有新的无服务实践。无论你是否能到,我希望这些例子可以让你开始使用 Ansible,无论你是否有任何服务要管理。
+
+_AnsibleFest 是一个单日会议,汇集了数百名 Ansible 用户、开发人员和行业合作伙伴。加入我们吧,这里有产品更新、鼓舞人心的交谈、技术深度潜水,动手演示和整天的网络。_
+
+(题图: opensource.com)
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/17/8/ansible-serverless-applications
+
+作者:[Ryan Scott Brown][a]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/ryansb
+[1]:https://www.ansible.com/how-ansible-works?intcmp=701f2000000h4RcAAI
+[2]:https://www.ansible.com/ebooks?intcmp=701f2000000h4RcAAI
+[3]:https://www.ansible.com/quick-start-video?intcmp=701f2000000h4RcAAI
+[4]:https://docs.ansible.com/ansible/latest/intro_installation.html?intcmp=701f2000000h4RcAAI
+[5]:https://opensource.com/article/17/8/ansible-serverless-applications?rate=zOgBPQUEmiTctfbajpu_TddaH-8b-ay3pFCK0b43vFw
+[6]:https://www.eventbrite.com/e/ansiblefest-san-francisco-2017-tickets-34008433139
+[7]:https://opensource.com/user/12043/feed
+[8]:https://www.ansible.com/
+[9]:https://en.wikipedia.org/wiki/Serverless_computing
+[10]:https://aws.amazon.com/lambda/
+[11]:https://serverless.com/
+[12]:https://www.ansible.com/ansiblefest?intcmp=701f2000000h4RcAAI
+[13]:https://opensource.com/users/ryansb
+[14]:https://opensource.com/users/ryansb
diff --git a/published/20170823 Using Kubernetes for Local Development — Minikube.md b/published/20170823 Using Kubernetes for Local Development — Minikube.md
new file mode 100644
index 0000000000..438e2df530
--- /dev/null
+++ b/published/20170823 Using Kubernetes for Local Development — Minikube.md
@@ -0,0 +1,273 @@
+Minikube:使用 Kubernetes 进行本地开发
+============================================================
+
+如果你的运维团队在使用 Docker 和 Kubernetes,那么建议开发上采用相同或相似的技术。这将减少不兼容性和可移植性问题的数量,并使每个人都会认识到应用程序容器是开发和运维团队的共同责任。
+
+
+
+这篇博客文章介绍了 Kubernetes 在开发模式中的用法,它的灵感来自于一个视频教程,你可以在“[无痛 Docker 教程][10]”中找到它。
+
+
+
+Minikube 是一个允许开发人员在本地使用和运行 Kubernetes 集群的工具,从而使开发人员的生活变得轻松。
+
+在这篇博客中,对于我测试的例子,我使用的是 Linux Mint 18,但其它 Linux 发行版在安装部分没有区别。
+
+```
+cat /etc/lsb-release
+```
+
+```
+DISTRIB_ID=LinuxMint
+DISTRIB_RELEASE=18.1
+DISTRIB_CODENAME=serena
+DISTRIB_DESCRIPTION=”Linux Mint 18.1 Serena”
+```
+
+
+
+### 先决条件
+
+为了与 Minkube 一起工作,我们应该安装 Kubectl 和 Minikube 和一些虚拟化驱动程序。
+
+* 对于 OS X,安装 [xhyve 驱动][2]、[VirtualBox][3] 或者 [VMware Fusion][4],然后再安装 Kubectl 和 Minkube。
+
+ ```
+ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
+
+ chmod +x ./kubectl
+
+ sudo mv ./kubectl /usr/local/bin/kubectl
+
+ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.21.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
+ ```
+
+* 对于 Windows,安装 [VirtualBox][6] 或者 [Hyper-V][7],然后再安装 Kubectl 和 Minkube。
+
+ ```
+ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.7.0/bin/windows/amd64/kubectl.exe
+ ```
+
+ 将二进制文件添加到你的 PATH 中(这篇[文章][11]解释了如何修改 PATH)
+
+ 下载 `minikube-windows-amd64.exe`,将其重命名为 `minikube.exe`,并将其添加到你的 PATH 中。[在这][12]可以找到最新版本。
+
+* 对于 Linux,安装 [VirtualBox][8] 或者 [KVM][9],然后再安装 Kubectl 和 Minkube。
+
+ ```
+ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
+
+ chmod +x ./kubectl
+
+ sudo mv ./kubectl /usr/local/bin/kubectl
+
+ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.21.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
+ ```
+
+### 使用 Minikube
+
+我们先从这个 Dockerfile 创建一个镜像:
+
+```
+FROM busybox
+ADD index.html /www/index.html
+EXPOSE 8000
+CMD httpd -p 8000 -h /www; tail -f /dev/null
+```
+
+添加你希望在 index.html 中看到的内容。
+
+构建镜像:
+
+```
+docker build -t eon01/hello-world-web-server .
+```
+
+我们来运行容器来测试它:
+
+```
+docker run -d --name webserver -p 8000:8000 eon01/hello-world-web-server
+```
+
+这是 `docker ps` 的输出:
+
+```
+docker ps
+
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+2ad8d688d812 eon01/hello-world-web-server "/bin/sh -c 'httpd..." 3 seconds ago Up 2 seconds 0.0.0.0:8000->8000/tcp webserver
+```
+
+让我们提交镜像并将其上传到公共 Docker Hub 中。你也可以使用自己的私有仓库:
+
+```
+docker commit webserver
+docker push eon01/hello-world-web-server
+```
+
+删除容器,因为我们将与 Minikube 一起使用它。
+
+```
+docker rm -f webserver
+```
+
+启动 Minikube:
+
+```
+minkube start
+```
+
+检查状态:
+
+```
+minikube status
+```
+
+我们运行一个单一节点:
+
+```
+kubectl get node
+```
+
+运行 webserver:
+
+```
+kubectl run webserver --image=eon01/hello-world-web-server --port=8000
+```
+
+webserver 应该会暴露它的端口:
+
+```
+kubectl expose deployment webserver --type=NodePort
+```
+
+为了得到服务 url 输入:
+
+```
+minikube service webserver --url
+```
+
+使用下面的命令得到 Web 页面的内容:
+
+```
+curl $(minikube service webserver --url)
+```
+
+显示运行中集群的摘要:
+
+```
+kubectl cluster-info
+```
+
+更多细节:
+
+```
+kubectl cluster-info dump
+```
+
+我们还可以使用以下方式列出 pod:
+
+```
+kubectl get pods
+```
+
+使用下面的方式访问面板:
+
+```
+minikube dashboard
+```
+
+如果你想访问 Web 程序的前端,输入:
+
+```
+kubectl proxy
+```
+
+如果我们要在容器内部执行一个命令,请使用以下命令获取 pod id:
+
+```
+kubetctl get pods
+```
+
+然后像这样使用:
+
+```
+kubectl exec webserver-2022867364-0v1p9 -it -- /bin/sh
+```
+
+最后完成了,请删除所有部署:
+
+```
+kubectl delete deployments --all
+```
+
+删除所有 pod:
+
+```
+kubectl delete pods --all
+```
+
+并且停止 Minikube。
+
+```
+minikube stop
+```
+
+我希望你享受这个介绍。
+
+### 更加深入
+
+如果你对本文感到共鸣,您可以在[无痛 Docker 教程][13]中找到更多有趣的内容。
+
+我们 [Eralabs][14] 将很乐意为你的 Docker 和云计算项目提供帮助,[联系我们][15],我们将很乐意听到你的项目。
+
+请订阅 [DevOpsLinks][16]:成千上万的 IT 专家和 DevOps 爱好者在线社区。
+
+你可能也有兴趣加入我们的新闻订阅 [Shipped][17],一个专注于容器,编排和无服务技术的新闻订阅。
+
+你可以在 [Twitter][18]、[Clarity][19] 或我的[网站][20]上找到我,你也可以看看我的书:[SaltStack For DevOps][21]。
+
+不要忘记加入我的最后一个项目 [DevOps 的职位][22]!
+
+如果你喜欢本文,请推荐它,并与你的关注者分享。
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Aymen El Amri - 云和软件架构师、企业家、作者、www.eralabs.io 的 CEO、www.devopslinks.com 的创始人,个人页面:www.aymenelamri.com
+
+-------------------
+
+
+via: https://medium.com/devopslinks/using-kubernetes-minikube-for-local-development-c37c6e56e3db
+
+作者:[Aymen El Amri][a]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://medium.com/@eon01
+[1]:http://painlessdocker.com/
+[2]:https://git.k8s.io/minikube/docs/drivers.md#xhyve-driver
+[3]:https://www.virtualbox.org/wiki/Downloads
+[4]:https://www.vmware.com/products/fusion
+[5]:https://storage.googleapis.com/kubernetes-release/release/stable.txt%29/bin/darwin/amd64/kubectl
+[6]:https://www.virtualbox.org/wiki/Downloads
+[7]:https://msdn.microsoft.com/en-us/virtualization/hyperv_on_windows/quick_start/walkthrough_install
+[8]:https://www.virtualbox.org/wiki/Downloads
+[9]:http://www.linux-kvm.org/
+[10]:http://painlessdocker.com/
+[11]:https://www.windows-commandline.com/set-path-command-line/
+[12]:https://github.com/kubernetes/minikube/releases
+[13]:http://painlessdocker.com/
+[14]:http://eralabs.io/
+[15]:http://eralabs.io/
+[16]:http://devopslinks.com/
+[17]:http://shipped.devopslinks.com/
+[18]:https://twitter.com/eon01
+[19]:https://clarity.fm/aymenelamri/
+[20]:http://aymenelamri.com/
+[21]:http://saltstackfordevops.com/
+[22]:http://jobsfordevops.com/
diff --git a/published/20170823 Why open source should be the first choice for cloud-native environments.md b/published/20170823 Why open source should be the first choice for cloud-native environments.md
new file mode 100644
index 0000000000..ed47aa5710
--- /dev/null
+++ b/published/20170823 Why open source should be the first choice for cloud-native environments.md
@@ -0,0 +1,110 @@
+为什么开源应该是云原生环境的首选
+============================================================
+
+> 基于 Linux 击败了专有软件一样的原因,开源应该成为云原生环境的首选。
+
+
+
+让我们回溯到上世纪 90 年代,当时专有软件大行其道,而开源才刚开始进入它自己的时代。是什么导致了这种转变?更重要的是,而今天我们转到云原生环境时,我们能从中学到什么?
+
+### 基础设施的历史经验
+
+我将以一个高度武断的、开源的视角开始,来看看基础设施过去 30 年的历史。在上世纪 90 年代,Linux 只是大多数组织视野中一个微不足道的小光点而已——如果他们听说过它的话。你早早购入股票的那些公司们很快就发现了 Linux 的好处,它主要是作为专有的 Unix 的廉价替代品,而部署服务器的标准方式是使用专有的 Unix,或者日渐增多的使用 Microsoft Windows NT。
+
+这种模式的专有本性为更专有的软件提供了一个肥沃的生态系统。软件被装在盒子里面放在商店出售。甚至开源软件也参与了这种装盒游戏;你可以在货架上买到 Linux,而不是用你的互联网连接免费下载。去商店和从你的软件供应商那里只是你得到软件的不同方式而已。
+
+
+
+*Ubuntu 包装盒出现在百思买的货架上*
+
+我认为,随着 LAMP 系列(Linux、Apache、MySQL 和 PHP / Perl / Python)的崛起,情况发生了变化。LAMP 系列非常成功。它是稳定的、可伸缩的和相对用户友好的。与此同时,我开始看到对专有解决方案的不满。一旦客户在 LAMP 系列中尝过了开源的甜头,他们就会改变他们对软件的期望,包括:
+
+* 不愿被供应商绑架,
+* 关注安全,
+* 希望自己来修复 bug ,以及
+* 孤立开发的软件意味着创新被扼杀。
+
+在技术方面,我们也看到了各种组织在如何使用软件上的巨大变化。忽然有一天,网站的宕机变成不可接受的了。这就对扩展性和自动化有了更多的依赖。特别是在过去的十年里,我们看到了基础设施从传统的“宠物”模式到“群牛”模式的转变,在这种模式中,服务器可以被换下和替换,而不是一直运行和被指定。公司使用大量的数据,更注重数据留存和数据到用户的处理和返回速度。
+
+开源和开源社区,以及来自大公司的日益增多的投入,为我们改变如何使用软件提供了基础。系统管理员的岗位要求开始 要求 Linux 技能和对开源技术和理念的熟悉。通过开源类似 Chef cookbooks 和 Puppet 模块这样东西,管理员可以分享他们的模式配置。我们不再单独配置和调优 MySQL;我们创建了一个掌控基础部分的系统,我们现在可以专注于更有趣的、可以给我们雇主带来更高价值的工程作业。
+
+开源现在无处不在,围绕它的模式也无处不在。曾经仇视这个想法的公司不仅通过协同项目与外界拥抱开源,而且进一步地,还发布了他们自己的开源软件项目并且围绕它们构建了社区。
+
+
+
+### 转向云端
+
+今天,我们生活在一个 DevOps 和云端的世界里。我们收获了开源运动带来的创新成果。在公司内部采用开源软件开发实践的情况下, Tim O'reilly 所称的 “[内部开源][11]” 有了明显增长。我们为云平台共享部署配置。像 Terraform 这样的工具甚至允许我们编写和分享我们如何部署特定的平台。
+
+但这些平台本身呢?
+
+> “大多数人想都不想就使用了云……许多用户将钱投入到根本不属于他们的基础设施中,而对放弃他们的数据和信息毫无顾虑。"
+> —Edward Snowden, OpenStack Summit, May 9, 2017
+
+现在是时候要更多地想想本能地转移或扩展到云上的事情了。
+
+就像 Snowden 强调的那样,现在我们正面临着对我们的用户和客户的数据的失控风险。抛开安全不谈,如果我们回顾一下我们转向开源的原因,个中原因还包括被厂商绑架的担忧、创新难以推动、甚至修复 bug 的考虑。
+
+在把你自己和/或你的公司锁定在一个专有平台之前,考虑以下问题:
+
+* 我使用的服务是遵循开放标准,还是被厂商绑架的?
+* 如果服务供应商破产或被竞争对手收购,什么是我可以依赖的?
+* 关于停机、安全等问题,供应商与其客户沟通中是否有一个明确而真诚的历史过往?
+* 供应商是否响应 bug 和特性请求,即使那是来自小客户?
+* 供应商是否会在我不知情的情况下使用我们的数据(或者更糟,即便我们的客户协议所不同意)?
+* 供应商是否有一个计划来处理长期的,不断上升的增长成本,特别是如果最初的成本很低呢?
+
+您可以通过这个问卷,讨论每个要点,而仍然决定使用专有的解决方案。这很好,很多公司一直都在这么做。然而,如果你像我一样,宁愿找到一个更开放的解决方案而仍然受益于云,你确实有的选择。
+
+### 基于私有云
+
+当您寻找私有云解决方案时,您的首选是开源,投资一个云提供商,其核心运行在开源软件上。 [OpenStack][12] 是行业领袖,在其 7 年的历史中,有 100 多个参与组织和成千上万的贡献者(包括我)。 OpenStack 项目已经证明,结合多个基于 OpenStack 云不仅是可行的,而且相对简单。云公司之间的 API 是相似的,所以您不必局限于特定的 OpenStack 供应商。作为一个开放源码项目,您仍然可以影响该基础设施的特性、bug 请求和发展方向。
+
+第二种选择是继续在基础层面上使用私有云,但在一个开源容器编排系统中。无论您选择 [DC/OS][13](基于[Apache Mesos][14]) 、[Kubernetes][15] 或 [Docker Swarm 模式][16] ,这些平台都允许您将私有云系统提供的虚拟机作为独立的 Linux 机器,并在此之上安装您的平台。您所需要的只是 Linux 而已,不会立即被锁定在特定云的工具或平台上。可以根据具体情况来决定是否使用特定的专属后端,但如果你这样做,就应该着眼于未来。
+
+有了这两种选择,你也可以选择完全离开云服务商。您可以部署自己的 OpenStack 云,或者将容器平台内部架构移动到您自己的数据中心。
+
+### 做一个登月计划
+
+最后,我想谈一谈开源项目基础设施。今年 3 月,在召开的 [南加州 Linux 展会][17] 上,多个开放源码项目的参与者讨论了为他们的项目运行开源基础设施。(更多的,请阅读我的 [关于该会议的总结][18])我认为这些项目正在做的这个工作是基础设施开源的最后一步。除了我们现在正在做的基本分享之外,我相信公司和组织们可以在不放弃与竞争对手相区分的“独门秘方”的情况下,进一步充分利用他们的基础设施开源。
+
+开源了他们的基础设施的开源项目,已经证明了允许多个公司和组织向他们的基础设施提交训练有素的 bug 报告,甚至是补丁和特定论文的价值。突然之间,你可以邀请兼职的贡献者。你的客户可以通过了解你的基础设施,“深入引擎盖子之下”,从而获得信心。
+
+想要更多的证据吗?访问 [开源基础设施][19] 的网站了解开源基础设施的项目(以及他们已经发布的大量基础设施)。
+
+可以在 8 月 26 日在费城举办的 FOSSCON 大会上 Elizabeth K. Joseph 的演讲“[基础架构开源][4]”上了解更多。
+
+(题图:[Jason Baker][6]. [CC BY-SA 4.0][7]. Source: [Cloud][8], [Globe][9]. Both [CC0][10].)
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/17/8/open-sourcing-infrastructure
+
+作者:[Elizabeth K. Joseph][a]
+译者:[wenzhiyi](https://github.com/wenzhiyi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/pleia2
+[1]:https://opensource.com/file/366596
+[2]:https://opensource.com/file/366591
+[3]:https://opensource.com/article/17/8/open-sourcing-infrastructure?rate=PdT-huv5y5HFZVMHOoRoo_qd95RG70y4DARqU5pzgkU
+[4]:https://fosscon.us/node/12637
+[5]:https://opensource.com/user/25923/feed
+[6]:https://opensource.com/users/jason-baker
+[7]:https://creativecommons.org/licenses/by-sa/4.0/
+[8]:https://pixabay.com/en/clouds-sky-cloud-dark-clouds-1473311/
+[9]:https://pixabay.com/en/globe-planet-earth-world-1015311/
+[10]:https://creativecommons.org/publicdomain/zero/1.0/
+[11]:https://opensource.com/life/16/11/create-internal-innersource-community
+[12]:https://www.openstack.org/
+[13]:https://dcos.io/
+[14]:http://mesos.apache.org/
+[15]:https://kubernetes.io/
+[16]:https://docs.docker.com/engine/swarm/
+[17]:https://www.socallinuxexpo.org/
+[18]:https://opensource.com/article/17/3/growth-open-source-project-infrastructures
+[19]:https://opensourceinfra.org/
+[20]:https://opensource.com/users/pleia2
+[21]:https://opensource.com/users/pleia2
diff --git a/published/20170825 Happy anniversary Linux A look back at where it all began.md b/published/20170825 Happy anniversary Linux A look back at where it all began.md
new file mode 100644
index 0000000000..037b7b7203
--- /dev/null
+++ b/published/20170825 Happy anniversary Linux A look back at where it all began.md
@@ -0,0 +1,153 @@
+Linux 1.0 之旅:回顾这一切的开始
+============================================================
+
+> 通过安装 SLS 1.05 展示了 Linux 内核在这 26 年间走过了多远。
+
+
+
+我第一次安装 Linux 是在 1993 年。那时我跑的是 MS-DOS,但我真的很喜欢学校机房电脑的 Unix 系统,就在那里度过了我大学本科时光。 当我听说了 Linux,一个 Unix 的免费版本,可以在我家的 386 电脑上运行的时候,我立刻就想要试试。我的第一个 Linux 发行版是 [Softlanding Linux System][27] (SLS) 1.03,带有 11 级补丁的 0.99 alpha 版本的 Linux 内核。它要求高达 2 MB 的内存,如果你想要编译项目需要 4 MB,运行 X windows 则需要 8 MB。
+
+我认为 Linux 相较于 MS-DOS 世界是一个巨大的进步。 尽管 Linux 缺乏运行在 MS-DOS 上的广泛的应用及游戏,但我发现 Linux 带给我的是巨大的灵活性。不像 MS-DOS ,现在我可以进行真正的多任务,同时运行不止一个程序。并且 Linux 提供了丰富的工具,包括一个 C 语言编译器,让我可以构建自己的项目。
+
+一年后,我升级到了 SLS 1.05,它支持全新的 Linux 内核 1.0。 更重要的,Linux 引入了内核模块。通过内核模块,你不再需要为支持新硬件而编译整个内核;取而代之,只需要从包含 Linux 内核之内的 63 个模块里加载一个就行。在 SLS 1.05 的发行自述文件中包含这些关于模块的注释:
+
+> 内核的模块化旨在正视减少并最终消除重新编译内核的要求,无论是变更、修改设备驱动或者为了动态访问不常用的驱动。也许更为重要的是,个别工作小组的工作不再影响到内核的正确开发。事实上,这让以二进制发布官方内核现在成为了可能。
+
+在 8 月 25 日,Linux 内核将迎来它的第 26 周年(LCTT 译注:已经过去了 =.= )。为了庆祝,我重新安装了 SLS 1.05 来提醒自己 Linux 1.0 内核是什么样子,去认识 Linux 自二十世纪 90 年代以来走了多远。和我一起踏上 Linux 的怀旧之旅吧!
+
+### 安装
+
+SLS 是第一个真正的 “发行版”,因为它包含一个安装程序。 尽管安装过程并不像现代发行版一样顺畅。 不能从 CD-ROM 启动安装,我需要从安装软盘启动我的系统,然后从 **login** 提示中运行安装程序。
+
+
+
+在 SLS 1.05 中引入的一个漂亮的功能是支持彩色的文本模式安装器。当我选择彩色模式时,安装器切换到一个带有黑色文字的亮蓝色背景,不再是我们祖祖辈辈们使用的原始的普通黑白文本。
+
+
+
+SLS 安装器是个简单的东西,文本从屏幕底部滚动而上,显示其做的工作。通过对一些简单的提示的响应,我能够创建一个 Linux 分区,挂载上 ext2 文件系统,并安装 Linux 。 安装包含了 X windows 和开发工具的 SLS 1.05,需要大约 85 MB 的磁盘空间。依照今天的标准这听起来可能不是很多,但在 Linux 1.0 出来的时候,120 MB 的硬件设备才是主流设备。
+
+
+
+
+
+### 系统级别
+
+当我第一次启动到 Linux 时,让我想起来了一些关于这个早期版本 Linux 系统的事情。首先,Linux 没有占据很多的空间。在启动系统之后运行一些程序来检查的时候,Linux 占用了不到 4 MB 的内存。在一个拥有 16MB 内存的系统中,这就意味着节省了很多内存用来运行程序。
+
+
+
+熟悉的 `/proc` 元文件系统在 Linux 1.0 就存在了,尽管对比我们今天在现代系统上看到的,它并不能提供许多信息。在 Linux 1.0, `/proc` 包含一些接口来探测类似 `meminfo` 和 `stat` 之类的基本系统状态。
+
+
+
+在这个系统上的 `/etc` 文件目录非常简单。值得一提的是,SLS 1.05 借用了来自 [BSD Unix][28] 的 **rc** 脚本来控制系统启动。 初始化是通过 **rc** 脚本进行的,由 `rc.local` 文件来定义本地系统的调整。后来,许多 Linux 发行版采用了来自 [Unix System V][29] 的很相似的 **init** 脚本,后来又是 [systemd][30] 初始化系统。
+
+
+
+### 你能做些什么
+
+随着我的系统的启动运行,接下来就可以使用了了。那么,在这样的早期 Linux 系统上你能做些什么?
+
+让我们从基本的文件管理开始。 每次在你登录的时候,SLS 会让你使用 Softlanding 菜单界面(MESH),这是一个文件管理程序,现代的用户们可能觉得它和 [Midnight Commander][31] 很相似。 而二十世纪 90 年代的用户们可能会拿 MESH 与更为接近的 [Norton Commander][32] 相比,这个可以说是在 MS-DOS 上最流行的第三方文件管理程序。
+
+")
+
+除了 MESH 之外,在 SLS 1.05 中还少量包含了一些全屏应用程序。你可以找到熟悉的用户工具,包括 Elm 邮件阅读器、GNU Emacs 可编程编辑器,以及古老的 Vim 编辑器。
+
+
+
+
+
+SLS 1.05 甚至包含了一个可以让你在终端玩的俄罗斯方块版本。
+
+
+
+在二十世纪 90 年代,多数住宅的网络接入是通过拨号连接的,所以 SLS 1.05 包含了 Minicom 调制解调器拨号程序。Minicom 提供一个与调制解调器的直接连接,并需要用户通过贺氏调制解调器的 **AT** 命令来完成一些像是拨号或挂电话这样的基础功能。Minicom 同样支持宏和其他简单功能来使连接你的本地调制解调器池更容易。
+
+
+
+但如果你想要写一篇文档时怎么办? SLS 1.05 的存在要比 LibreOffice 或者 OpenOffice 早很长时间。在二十世纪 90 年代,Linux 还没有这些应用。相反,如果你想要使用一个文字处理器,可能需要引导你的系统进入 MS-DOS,然后运行你喜欢的文字处理器程序,如 WordPerfect 或者共享软件 GalaxyWrite。
+
+但是所有的 Unix 系统都包含一套简单的文本格式化程序,叫做 nroff 和 troff。在 Linux 系统中,他们被合并成 GNU groff 包,而 SLS 1.05 包含了 groff 的一个版本。我在 SLS 1.05 上的一项测试就是用 nroff 生成一个简单的文本文档。
+
+
+
+
+
+### 运行 X windows
+
+获取安装 X windows 并不特别容易,如 SLS 安装文件承诺的那样:
+
+> 在你的 PC 上获取安装 X windows 可能会有一些发人深省的体验,主要是因为 PC 的显示卡类型太多。Linux X11 仅支持 VGA 类型的显示卡,但在许多类型的 VGA 中仅有个别的某些类型是完全支持的。SLS 存在两种 X windows 服务器。全彩的 XFree86,支持一些或所有 ET3000、ET400、PVGA1、GVGA、Trident、S3、8514、Accelerated cards、ATI plus 等。
+>
+> 另一个服务器 XF86_Mono,能够工作在几乎所有的 VGA 卡上,但只提供单色模式。因此,相比于彩色服务器,它会占用更少的内存并拥有更快的速度。当然就是看起来不怎么漂亮。
+>
+> X windows 的配置信息都堆放在目录 “/usr/X386/lib/X11/”。需要注意的是,“Xconfig” 文件为监视器和显示卡定义了时序。默认情况下,X windows 设置使用彩色服务器,如果彩色服务器出现问题,你可以切换到单色服务器 x386mono,因为它已经支持各种标准的 VGA。本质上,这只是将 /usr/X386/bin/X 链接到它。
+>
+> 只需要编辑 Xconfig 来设置鼠标驱动类型和时序,然后键入 “startx” 即可。
+
+这些听起来令人困惑,但它就是这样。手工配置 X windows 真的可以是一个发人深省的体验。幸好,SLS 1.05 包含了 syssetup 程序来帮你确定系统组件的种类,包括了 X windows 的显示设置。在一些提示过后,经过一些实验和调整,最终我成功启动了 X windows!
+
+
+
+但这是来自于 1994 年的 X windows,它仍然并没有桌面的概念。我可以从 FVWM (一个虚拟窗口管理器)或 TWM (选项卡式的窗口管理器)中选择。TWM 直观地设置提供一个功能简单的图形环境。
+
+
+
+### 关机
+
+我已经在我的 Linux 寻根之旅沉浸许久,是时候最终回到我的现代桌面上了。最初我跑 Linux 的是一台仅有 8MB 内存和 一个 120MB 硬盘驱动器的 32 位 386 电脑,而我现在的系统已经足够强大了。拥有双核 64 位 Intel Core i5 处理器,4 GB 内存和一个 128 GB 的固态硬盘,我可以在我的运行着 Linux 内核 4.11.11 的系统上做更多事情。那么,在我的 SLS 1.05 的实验结束之后,是时候离开了。
+
+
+
+再见,Linux 1.0。很高兴看到你的茁壮成长。
+
+(题图:图片来源:[litlnemo][25]。由 Opnesource.com 修改。[CC BY-SA 2.0.][26])
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/17/8/linux-anniversary
+
+作者:[Jim Hall][a]
+译者:[softpaopao](https://github.com/softpaopao)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/jim-hall
+[1]:https://opensource.com/resources/what-is-linux?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[2]:https://opensource.com/resources/what-are-linux-containers?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[3]:https://developers.redhat.com/promotions/linux-cheatsheet/?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[4]:https://developers.redhat.com/cheat-sheet/advanced-linux-commands-cheatsheet?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[5]:https://opensource.com/tags/linux?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[6]:https://opensource.com/file/365166
+[7]:https://opensource.com/file/365171
+[8]:https://opensource.com/file/365176
+[9]:https://opensource.com/file/365161
+[10]:https://opensource.com/file/365221
+[11]:https://opensource.com/file/365196
+[12]:https://opensource.com/file/365156
+[13]:https://opensource.com/file/365181
+[14]:https://opensource.com/file/365146
+[15]:https://opensource.com/file/365151
+[16]:https://opensource.com/file/365211
+[17]:https://opensource.com/file/365186
+[18]:https://opensource.com/file/365191
+[19]:https://opensource.com/file/365226
+[20]:https://opensource.com/file/365206
+[21]:https://opensource.com/file/365236
+[22]:https://opensource.com/file/365201
+[23]:https://opensource.com/article/17/8/linux-anniversary?rate=XujKSFS7GfDmxcV7Jf_HUK_MdrW15Po336fO3G8s1m0
+[24]:https://opensource.com/user/126046/feed
+[25]:https://www.flickr.com/photos/litlnemo/19777182/
+[26]:https://creativecommons.org/licenses/by-sa/2.0/
+[27]:https://en.wikipedia.org/wiki/Softlanding_Linux_System
+[28]:https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
+[29]:https://en.wikipedia.org/wiki/UNIX_System_V
+[30]:https://en.wikipedia.org/wiki/Systemd
+[31]:https://midnight-commander.org/
+[32]:https://en.wikipedia.org/wiki/Norton_Commander
+[33]:https://opensource.com/users/jim-hall
+[34]:https://opensource.com/users/jim-hall
+[35]:https://opensource.com/article/17/8/linux-anniversary#comments
diff --git a/published/20170901 An economically efficient model for open source software license compliance.md b/published/20170901 An economically efficient model for open source software license compliance.md
new file mode 100644
index 0000000000..abc27f2a84
--- /dev/null
+++ b/published/20170901 An economically efficient model for open source software license compliance.md
@@ -0,0 +1,61 @@
+一个开源软件许可证合规的经济高效模式
+============================================================
+
+> 使用开源的方式有利于你的盈亏底线以及开源生态系统。
+
+
+
+
+
+“合规性工业联合体” 是一个术语,它会唤起那些组织参与精心设计并且花费昂贵流程的以遵守开源许可条款的反乌托邦想象。由于“生活经常模仿艺术”,许多组织采用了这种做法,可惜的是它们剥夺了许多开源模型的好处。本文介绍了一种经济高效的开源软件许可证合规性方法。
+
+开源许可证通常对从第三方授权的代码分发者有三个要求:
+
+1. 提供开源许可证的副本
+2. 包括版权声明
+3. 对于 copyleft 许可证(如 GPL),将相应的源代码提供给接受者。
+
+_(与任何一般性声明一样,可能会有例外情况,因此始终建议审查许可条款,如有需要,请咨询律师的意见。)_
+
+因为源代码(以及任何相关的文件,例如:许可证、README)通常都包含所有这些信息,所以最简单的遵循方法就是随着二进制/可执行程序一起提供源代码。
+
+替代方案更加困难并且昂贵,因为在大多数情况下,你仍然需要提供开源许可证的副本并保留版权声明。提取这些信息来结合你的二进制/可执行版本并不简单。你需要流程、系统和人员来从源代码和相关文件中复制此信息,并将其插入到单独的文本文件或文档中。
+
+不要低估创建此文件的时间和费用。虽然有工具也许可以自动化部分流程,但这些工具通常需要人力资源(例如工程师、质量经理、发布经理)来准备代码来扫描并对结果进行评估(没有完美的工具,几乎总是需要审查)。你的组织资源有限,将其转移到此活动会增加机会成本。考虑到这笔费用,每个后续版本(主要或次要)的成本将需要进行新的分析和修订。
+
+也有因不选择发布不能被很好识别的源码而导致增加的其他成本。这些根源在于不向开源项目的原始作者和/或维护者发布源代码, 这一活动称为上游化。独自上游化一般不满足大多数开源许可证的要求,这就是为什么这篇文章主张与你的二进制/可执行文件一起发布源代码。然而,上游化和提供源代码以及二进制/可执行文件都能提供额外的经济效益。这是因为你的组织不再需要保留随着每次发布合并开源代码修改而产生的私有分支 - 由于你的内部代码库与社区项目不同,这将是越来越消耗和凌乱的工作。上游化还增强了开源生态系统,它会鼓励社区创新,从中你的组织或许也会得到收益。
+
+那么为什么大量的组织不会为其产品发布源代码来简化其合规性工作?在许多情况下,这是因为他们认为这可能会暴露他们竞争优势的信息。考虑到这些专有产品中的大量代码可能是开源代码的直接副本,以支持诸如 WiFi 或云服务这些当代产品的基础功能,这种信念可能是错误的。
+
+即使对这些开源作品进行了修改来适配其专有产品,这些更改也往往是微不足道的,并包含了很少的新的版权部分或可用来专利的内容。因此,任何组织都应该通过这种方式来查看其代码,因为它可能会发现其代码库中绝大部分是开源的,只有一小部分是真正专有的、与竞争对手区分开来的部分。那么为什么不分发和向上游提交这些没有差别的代码呢?
+
+考虑一下拒绝遵从工业联合体的思维方式, 以降低成本并大大简化合规性。使用开源的方式,并体验发布你的源代码的乐趣,以造福于你的盈亏底线和开源生态系统,从中你将继续收获更多的利益。
+
+------------------------
+
+作者简介
+
+Jeffrey Robert Kaufman - Jeffrey R. Kaufman 是全球领先的开源软件解决方案提供商红帽公司的开源知识产权律师。Jeffrey 还担任着 Thomas Jefferson 法学院的兼职教授。 在加入红帽前,Jeffrey 在高通担任专利法律顾问,为首席科学家办公室提供开源顾问。 Jeffrey 在 RFID、条形码、图像处理和打印技术方面拥有多项专利。[更多关于我][2]
+
+(题图: opensource.com)
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/17/9/economically-efficient-model
+
+作者:[Jeffrey Robert Kaufman][a]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/jkaufman
+[1]:https://opensource.com/article/17/9/economically-efficient-model?rate=0SO3DeFAxtgLdmZxE2ZZQyTRTTbu2OOlksFZSUXmjJk
+[2]:https://opensource.com/users/jkaufman
+[3]:https://opensource.com/user/74461/feed
+[4]:https://opensource.com/users/jkaufman
+[5]:https://opensource.com/users/jkaufman
+[6]:https://opensource.com/users/jkaufman
+[7]:https://opensource.com/tags/law
+[8]:https://opensource.com/tags/licensing
+[9]:https://opensource.com/participate
diff --git a/sources/talk/20170310 How to use pull requests to improve your code reviews.md b/sources/talk/20170310 How to use pull requests to improve your code reviews.md
deleted file mode 100644
index 4e84a4a2fd..0000000000
--- a/sources/talk/20170310 How to use pull requests to improve your code reviews.md
+++ /dev/null
@@ -1,95 +0,0 @@
-How to use pull requests to improve your code reviews
-============================================================
-
-Spend more time building and less time fixing with GitHub Pull Requests for proper code review.
-
- 
-
-
->Take a look Brent and Peter’s book, [ _Introducing GitHub_ ][5], for more on creating projects, starting pull requests, and getting an overview of your team’s software development process.
-
-
-If you don’t write code every day, you may not know some of the problems that software developers face on a daily basis:
-
-* Security vulnerabilities in the code
-* Code that causes your application to crash
-* Code that can be referred to as “technical debt” and needs to be re-written later
-* Code that has already been written somewhere that you didn’t know about
-
-
-Code review helps improve the software we write by allowing other people and/or tools to look it over for us. This review can happen with automated code analysis or test coverage tools — two important pieces of the software development process that can save hours of manual work — or peer review. Peer review is a process where developers review each other's work. When it comes to developing software, speed and urgency are two components that often result in some of the previously mentioned problems. If you don’t release soon enough, your competitor may come out with a new feature first. If you don’t release often enough, your users may doubt whether or not you still care about improvements to your application.
-
-### Weighing the time trade-off: code review vs. bug fixing
-
-If someone is able to bring together multiple types of code review in a way that has minimal friction, then the quality of that software written over time will be improved. It would be naive to think that the introduction of new tools or processes would not at first introduce some amount of delay in time. But what is more expensive: time to fix bugs in production, or improving the software before it makes it into production? Even if new tools introduce some lag time in which a new feature can be released and appreciated by customers, that lag time will shorten as the software developers improve their own skills and the software release cycles will increase back to previous levels while bugs should decrease.
-
-One of the keys for achieving this goal of proactively improving code quality with code review is using a platform that is flexible enough to allow software developers to quickly write code, plug in the tools they are familiar with, and do peer review of each others’ code. [GitHub][9] is a great example of such a platform. However, putting your code on GitHub doesn’t just magically make code review happen; you have to open a pull request to start down this journey.
-
-### Pull requests: a living discussion about code
-
-[Pull requests][10] are a tool on GitHub that allows software developers to discuss and propose changes to the main codebase of a project that later can be deployed for all users to see. They were created back in February of 2008 for the purpose of suggesting a change on to someone’s work before it would be accepted (merged) and later deployed to production for end-users to see that change.
-
-Pull requests started out as a loose way to offer your change to someone’s project, but they have evolved into:
-
-* A living discussion about the code you want merged
-* Added functionality of increasing the visibility of what changed
-* Integration of your favorite tools
-* Explicit pull request reviews that can be required as part of a protected branch workflow
-
-### Considering code: URLs are forever
-
-Looking at the first two bullet points above, pull requests foster an ongoing code discussion that makes code changes very visible, as well as making it easy to pick up where you left off on your review. For both new and experienced developers, being able to refer back to these previous discussions about why a feature was developed the way it was or being linked to another conversation about a related feature should be priceless. Context can be so important when coordinating features across multiple projects and keeping everyone in the loop as close as possible to the code is great too. If those features are still being developed, it’s important to be able to just see what’s changed since you last reviewed. After all, it’s far easier to [review a small change than a large one][11], but that’s not always possible with large features. So, it’s important to be able to pick up where you last reviewed and only view the changes since then.
-
-### Integrating tools: software developers are opinionated
-
-Considering the third point above, GitHub’s pull requests have a lot of functionality but developers will always have a preference on additional tools. Code quality is a whole realm of code review that involves the other component to code reviews that aren’t necessarily human. Detecting code that’s “inefficient” or slow, a potential security vulnerability, or just not up to company standards is a task best left to automated tools. Tools like [SonarQube][12] and [Code Climate][13]can analyse your code, while tools like [Codecov][14] and [Coveralls][15] can tell you if the new code you just wrote is not well tested. The wonder of these tools is that they can plug into GitHub and report their findings right back into the pull request! This means the conversation not only has people reviewing the code, but the tools are reporting there too. Everyone can stay in the loop of exactly how a feature is developing.
-
-Lastly, depending on the preference of your team, you can make the tools and the peer review required by leveraging the required status feature of the [protected branch workflow][16].
-
-Though you may just be getting started on your software development journey, a business stakeholder who wants to know how a project is doing, or a project manager who wants to ensure the timeliness and quality of a project, getting involved in the pull request by setting up an approval workflow and thinking about integration with additional tools to ensure quality is important at any level of software development.
-
-Whether it’s for your personal website, your company’s online store, or the latest combine to harvest this year’s corn with maximum yield, writing good software involves having good code review. Having good code review involves the right tools and platform. To learn more about GitHub and the software development process, take a look at the O’Reilly book, [ _Introducing GitHub_ ][17], where you can understand creating projects, starting pull requests, and getting an overview of your team's’ software development process.
-
---------------------------------------------------------------------------------
-
-作者简介:
-
-**Brent Beer**
-
-Brent Beer has used Git and GitHub for over 5 years through university classes, contributions to open source projects, and professionally as a web developer. While working as a trainer for GitHub, he also became a published author of “Introducing GitHub” for O’Reilly. He now works as a solutions engineer for GitHub in Amsterdam to help bring Git and GitHub to developers across the world.
-
-**Peter Bell**
-
-Peter Bell is the founder and CTO of Ronin Labs. Training is broken - we're fixing it through technology enhanced training! He is an experienced entrepreneur, technologist, agile coach and CTO specializing in EdTech projects. He wrote "Introducing GitHub" for O'Reilly, created the "Mastering GitHub" course for code school and "Git and GitHub LiveLessons" for Pearson. He has presented regularly at national and international conferences on ruby, nodejs, NoSQL (especially MongoDB and neo4j), cloud computing, software craftsmanship, java, groovy, j...
-
-
--------------
-
-
-via: https://www.oreilly.com/ideas/how-to-use-pull-requests-to-improve-your-code-reviews?imm_mid=0ee8ca&cmp=em-prog-na-na-newsltr_20170311
-
-作者:[Brent Beer][a],[Peter Bell][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.oreilly.com/people/acf937de-cdf4-4b0e-85bd-b559404c580e
-[b]:https://www.oreilly.com/people/2256f119-7ea0-440e-99e8-65281919e952
-[1]:https://pixabay.com/en/measure-measures-rule-metro-106354/
-[2]:http://conferences.oreilly.com/oscon/oscon-tx?intcmp=il-prog-confreg-update-ostx17_new_site_oscon_17_austin_right_rail_cta
-[3]:https://www.oreilly.com/people/acf937de-cdf4-4b0e-85bd-b559404c580e
-[4]:https://www.oreilly.com/people/2256f119-7ea0-440e-99e8-65281919e952
-[5]:https://www.safaribooksonline.com/library/view/introducing-github/9781491949801/?utm_source=newsite&utm_medium=content&utm_campaign=lgen&utm_content=how-to-use-pull-requests-to-improve-your-code-reviews
-[6]:http://conferences.oreilly.com/oscon/oscon-tx?intcmp=il-prog-confreg-update-ostx17_new_site_oscon_17_austin_right_rail_cta
-[7]:http://conferences.oreilly.com/oscon/oscon-tx?intcmp=il-prog-confreg-update-ostx17_new_site_oscon_17_austin_right_rail_cta
-[8]:https://www.oreilly.com/ideas/how-to-use-pull-requests-to-improve-your-code-reviews?imm_mid=0ee8ca&cmp=em-prog-na-na-newsltr_20170311
-[9]:https://github.com/about
-[10]:https://help.github.com/articles/about-pull-requests/
-[11]:https://blog.skyliner.io/ship-small-diffs-741308bec0d1
-[12]:https://github.com/integrations/sonarqube
-[13]:https://github.com/integrations/code-climate
-[14]:https://github.com/integrations/codecov
-[15]:https://github.com/integrations/coveralls
-[16]:https://help.github.com/articles/about-protected-branches/
-[17]:https://www.safaribooksonline.com/library/view/introducing-github/9781491949801/?utm_source=newsite&utm_medium=content&utm_campaign=lgen&utm_content=how-to-use-pull-requests-to-improve-your-code-reviews-lower
diff --git a/sources/tech/20160815 Here are all the Git commands I used last week and what they do.md b/sources/tech/20160815 Here are all the Git commands I used last week and what they do.md
deleted file mode 100644
index dd044d3c34..0000000000
--- a/sources/tech/20160815 Here are all the Git commands I used last week and what they do.md
+++ /dev/null
@@ -1,214 +0,0 @@
-translating by firmianay
-
-Here are all the Git commands I used last week, and what they do.
-============================================================
-
-Image credit: [GitHub Octodex][6]
-
-Like most newbies, I started out searching StackOverflow for Git commands, then copy-pasting answers, without really understanding what they did.
-
-
-
-Image credit: [XKCD][7]
-
-I remember thinking,“Wouldn’t it be nice if there were a list of the most common Git commands along with an explanation as to why they are useful?”
-
-Well, here I am years later to compile such a list, and lay out some best practices that even intermediate-advanced developers should find useful.
-
-To keep things practical, I’m basing this list off of the actual Git commands I used over the past week.
-
-Almost every developer uses Git, and most likely GitHub. But the average developer probably only uses these three commands 99% of the time:
-
-```
-git add --all
-git commit -am ""
-git push origin master
-```
-
-That’s all well and good when you’re working on a one-person team, a hackathon, or a throw-away app, but when stability and maintenance start to become a priority, cleaning up commits, sticking to a branching strategy, and writing coherent commit messages becomes important.
-
-I’ll start with the list of commonly used commands to make it easier for newbies to understand what is possible with Git, then move into the more advanced functionality and best practices.
-
-#### Regularly used commands
-
-To initialize Git in a repository (repo), you just need to type the following command. If you don’t initialize Git, you cannot run any other Git commands within that repo.
-
-```
-git init
-```
-
-If you’re using GitHub and you’re pushing code to a GitHub repo that’s stored online, you’re using a remote repo. The default name (also known as an alias) for that remote repo is origin. If you’ve copied a project from Github, it already has an origin. You can view that origin with the command git remote -v, which will list the URL of the remote repo.
-
-If you initialized your own Git repo and want to associate it with a GitHub repo, you’ll have to create one on GitHub, copy the URL provided, and use the command git remote add origin , with the URL provided by GitHub replacing “”. From there, you can add, commit, and push to your remote repo.
-
-The last one is used when you need to change the remote repository. Let’s say you copied a repo from someone else and want to change the remote repository from the original owner’s to your own GitHub account. Follow the same process as git remote add origin, except use set-url instead to change the remote repo.
-
-```
-git remote -v
-git remote add origin
-git remote set-url origin
-```
-
-The most common way to copy a repo is to use git clone, followed by the URL of the repo.
-
-Keep in mind that the remote repository will be linked to the account from which you cloned the repo. So if you cloned a repo that belongs to someone else, you will not be able to push to GitHub until you change the originusing the commands above.
-
-```
-git clone
-```
-
-You’ll quickly find yourself using branches. If you don’t understand what branches are, there are other tutorials that are much more in-depth, and you should read those before proceeding ([here’s one][8]).
-
-The command git branch lists all branches on your local machine. If you want to create a new branch, you can use git branch , with representing the name of the branch, such as “master”.
-
-The git checkout command switches to an existing branch. You can also use the git checkout -b command to create a new branch and immediately switch to it. Most people use this instead of separate branch and checkout commands.
-
-```
-git branch
-git branch
-git checkout
-git checkout -b
-```
-
-If you’ve made a bunch of changes to a branch, let’s call it “develop”, and you want to merge that branch back into your master branch, you use the git merge command. You’ll want to checkout the master branch, then run git merge develop to merge develop into the master branch.
-
-```
-git merge
-```
-
-If you’re working with multiple people, you’ll find yourself in a position where a repo was updated on GitHub, but you don’t have the changes locally. If that’s the case, you can use git pull origin to pull the most recent changes from that remote branch.
-
-```
-git pull origin
-```
-
-If you’re curious to see what files have been changed and what’s being tracked, you can use git status. If you want to see _how much_ each file has been changed, you can use git diff to see the number of lines changed in each file.
-
-```
-git status
-git diff --stat
-```
-
-### Advanced commands and best practices
-
-Soon you reach a point where you want your commits to look nice and stay consistent. You might also have to fiddle around with your commit history to make your commits easier to comprehend or to revert an accidental breaking change.
-
-The git log command lets you see the commit history. You’ll want to use this to see the history of your commits.
-
-Your commits will come with messages and a hash, which is random series of numbers and letters. An example hash might look like this: c3d882aa1aa4e3d5f18b3890132670fbeac912f7
-
-```
-git log
-```
-
-Let’s say you pushed something that broke your app. Rather than fix it and push something new, you’d rather just go back one commit and try again.
-
-If you want to go back in time and checkout your app from a previous commit, you can do this directly by using the hash as the branch name. This will detach your app from the current version (because you’re editing a historical record, rather than the current version).
-
-```
-git checkout c3d88eaa1aa4e4d5f
-```
-
-Then, if you make changes from that historical branch and you want to push again, you’d have to do a force push.
-
-Caution: Force pushing is dangerous and should only be done if you absolutely must. It will overwrite the history of your app and you will lose whatever came after.
-
-```
-git push -f origin master
-```
-
-Other times it’s just not practical to keep everything in one commit. Perhaps you want to save your progress before trying something potentially risky, or perhaps you made a mistake and want to spare yourself the embarrassment of having an error in your version history. For that, we have git rebase.
-
-Let’s say you have 4 commits in your local history (not pushed to GitHub) in which you’ve gone back and forth. Your commits look sloppy and indecisive. You can use rebase to combine all of those commits into a single, concise commit.
-
-```
-git rebase -i HEAD~4
-```
-
-The above command will open up your computer’s default editor (which is Vim unless you’ve set it to something else), with several options for how you can change your commits. It will look something like the code below:
-
-```
-pick 130deo9 oldest commit message
-pick 4209fei second oldest commit message
-pick 4390gne third oldest commit message
-pick bmo0dne newest commit message
-```
-
-In order to combine these, we need to change the “pick” option to “fixup” (as the documentation below the code says) to meld the commits and discard the commit messages. Note that in vim, you need to press “a” or “i” to be able to edit the text, and to save and exit, you need to type the escapekey followed by “shift + z + z”. Don’t ask me why, it just is.
-
-```
-pick 130deo9 oldest commit message
-fixup 4209fei second oldest commit message
-fixup 4390gne third oldest commit message
-fixup bmo0dne newest commit message
-```
-
-This will merge all of your commits into the commit with the message “oldest commit message”.
-
-The next step is to rename your commit message. This is entirely a matter of opinion, but so long as you follow a consistent pattern, anything you do is fine. I recommend using the [commit guidelines put out by Google for Angular.js][9].
-
-In order to change the commit message, use the amend flag.
-
-```
-git commit --amend
-```
-
-This will also open vim, and the text editing and saving rules are the same as above. To give an example of a good commit message, here’s one following the rules from the guideline:
-
-```
-feat: add stripe checkout button to payments page
-```
-
-```
-- add stripe checkout button
-- write tests for checkout
-```
-
-One advantage to keeping with the types listed in the guideline is that it makes writing change logs easier. You can also include information in the footer (again, specified in the guideline) that references issues.
-
-Note: you should avoid rebasing and squashing your commits if you are collaborating on a project, and have code pushed to GitHub. If you start changing version history under people’s noses, you could end up making everyone’s lives more difficult with bugs that are difficult to track.
-
-There are an almost endless number of possible commands with Git, but these commands are probably the only ones you’ll need to know for your first few years of programming.
-
-* * *
-
- _Sam Corcos is the lead developer and co-founder of _ [_Sightline Maps_][10] _, the most intuitive platform for 3D printing topographical maps, as well as _ [_LearnPhoenix.io_][11] _, an intermediate-advanced tutorial site for building scalable production apps with Phoenix and React. Get $20 off of LearnPhoenix with the coupon code: _ _free_code_camp_
-
-
-* [Git][1]
-
-* [Github][2]
-
-* [Programming][3]
-
-* [Software Development][4]
-
-* [Web Development][5]
-
-Show your support
-
-Clapping shows how much you appreciated Sam Corcos’s story.
-
-
---------------------------------------------------------------------------------
-
-via: https://medium.freecodecamp.org/git-cheat-sheet-and-best-practices-c6ce5321f52
-
-作者:[Sam Corcos][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://medium.freecodecamp.org/@SamCorcos?source=post_header_lockup
-[1]:https://medium.freecodecamp.org/tagged/git?source=post
-[2]:https://medium.freecodecamp.org/tagged/github?source=post
-[3]:https://medium.freecodecamp.org/tagged/programming?source=post
-[4]:https://medium.freecodecamp.org/tagged/software-development?source=post
-[5]:https://medium.freecodecamp.org/tagged/web-development?source=post
-[6]:https://octodex.github.com/
-[7]:https://xkcd.com/1597/
-[8]:https://guides.github.com/introduction/flow/
-[9]:https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines
-[10]:http://sightlinemaps.com/
-[11]:http://learnphoenix.io/
diff --git a/sources/tech/20161031 An introduction to Linux filesystems.md b/sources/tech/20161031 An introduction to Linux filesystems.md
new file mode 100644
index 0000000000..92aed3b557
--- /dev/null
+++ b/sources/tech/20161031 An introduction to Linux filesystems.md
@@ -0,0 +1,214 @@
+ucasFL translating
+
+An introduction to Linux filesystems
+============================================================
+
+
+Image credits : Original photo by Rikki Endsley. [CC BY-SA 4.0][9]
+
+This article is intended to be a very high-level discussion of Linux filesystem concepts. It is not intended to be a low-level description of how a particular filesystem type, such as EXT4, works, nor is it intended to be a tutorial of filesystem commands.
+
+More Linux resources
+
+* [What is Linux?][1]
+
+* [What are Linux containers?][2]
+
+* [Download Now: Linux commands cheat sheet][3]
+
+* [Advanced Linux commands cheat sheet][4]
+
+* [Our latest Linux articles][5]
+
+Every general-purpose computer needs to store data of various types on a hard disk drive (HDD) or some equivalent, such as a USB memory stick. There are a couple reasons for this. First, RAM loses its contents when the computer is switched off. There are non-volatile types of RAM that can maintain the data stored there after power is removed (such as flash RAM that is used in USB memory sticks and solid state drives), but flash RAM is much more expensive than standard, volatile RAM like DDR3 and other, similar types.
+
+The second reason that data needs to be stored on hard drives is that even standard RAM is still more expensive than disk space. Both RAM and disk costs have been dropping rapidly, but RAM still leads the way in terms of cost per byte. A quick calculation of the cost per byte, based on costs for 16GB of RAM vs. a 2TB hard drive, shows that the RAM is about 71 times more expensive per unit than the hard drive. A typical cost for RAM is around $0.0000000043743750 per byte today.
+
+For a quick historical note to put present RAM costs in perspective, in the very early days of computing, one type of memory was based on dots on a CRT screen. This was very expensive at about $1.00 _per bit_ !
+
+### Definitions
+
+You may hear people talk about filesystems in a number of different and confusing ways. The word itself can have multiple meanings, and you may have to discern the correct meaning from the context of a discussion or document.
+
+I will attempt to define the various meanings of the word "filesystem" based on how I have observed it being used in different circumstances. Note that while attempting to conform to standard "official" meanings, my intent is to define the term based on its various usages. These meanings will be explored in greater detail in the following sections of this article.
+
+1. The entire Linux directory structure starting at the top (/) root directory.
+
+2. A specific type of data storage format, such as EXT3, EXT4, BTRFS, XFS, and so on. Linux supports almost 100 types of filesystems, including some very old ones as well as some of the newest. Each of these filesystem types uses its own metadata structures to define how the data is stored and accessed.
+
+3. A partition or logical volume formatted with a specific type of filesystem that can be mounted on a specified mount point on a Linux filesystem.
+
+### Basic filesystem functions
+
+Disk storage is a necessity that brings with it some interesting and inescapable details. Obviously, a filesystem is designed to provide space for non-volatile storage of data; that is its ultimate function. However, there are many other important functions that flow from that requirement.
+
+All filesystems need to provide a namespace—that is, a naming and organizational methodology. This defines how a file can be named, specifically the length of a filename and the subset of characters that can be used for filenames out of the total set of characters available. It also defines the logical structure of the data on a disk, such as the use of directories for organizing files instead of just lumping them all together in a single, huge conglomeration of files.
+
+Once the namespace has been defined, a metadata structure is necessary to provide the logical foundation for that namespace. This includes the data structures required to support a hierarchical directory structure; structures to determine which blocks of space on the disk are used and which are available; structures that allow for maintaining the names of the files and directories; information about the files such as their size and times they were created, modified or last accessed; and the location or locations of the data belonging to the file on the disk. Other metadata is used to store high-level information about the subdivisions of the disk, such as logical volumes and partitions. This higher-level metadata and the structures it represents contain the information describing the filesystem stored on the drive or partition, but is separate from and independent of the filesystem metadata.
+
+Filesystems also require an Application Programming Interface (API) that provides access to system function calls which manipulate filesystem objects like files and directories. APIs provide for tasks such as creating, moving, and deleting files. It also provides algorithms that determine things like where a file is placed on a filesystem. Such algorithms may account for objectives such as speed or minimizing disk fragmentation.
+
+Modern filesystems also provide a security model, which is a scheme for defining access rights to files and directories. The Linux filesystem security model helps to ensure that users only have access to their own files and not those of others or the operating system itself.
+
+The final building block is the software required to implement all of these functions. Linux uses a two-part software implementation as a way to improve both system and programmer efficiency.
+
+
+
+
+Figure 1: The Linux two-part filesystem software implementation.
+
+The first part of this two-part implementation is the Linux virtual filesystem. This virtual filesystem provides a single set of commands for the kernel, and developers, to access all types of filesystems. The virtual filesystem software calls the specific device driver required to interface to the various types of filesystems. The filesystem-specific device drivers are the second part of the implementation. The device driver interprets the standard set of filesystem commands to ones specific to the type of filesystem on the partition or logical volume.
+
+### Directory structure
+
+As a usually very organized Virgo, I like things stored in smaller, organized groups rather than in one big bucket. The use of directories helps me to be able to store and then locate the files I want when I am looking for them. Directories are also known as folders because they can be thought of as folders in which files are kept in a sort of physical desktop analogy.
+
+In Linux and many other operating systems, directories can be structured in a tree-like hierarchy. The Linux directory structure is well defined and documented in the [Linux Filesystem Hierarchy Standard][10] (FHS). Referencing those directories when accessing them is accomplished by using the sequentially deeper directory names connected by forward slashes (/) such as /var/log and /var/spool/mail. These are called paths.
+
+The following table provides a very brief list of the standard, well-known, and defined top-level Linux directories and their purposes.
+
+| Directory | Description |
+| --- | --- |
+| / (root filesystem) | The root filesystem is the top-level directory of the filesystem. It must contain all of the files required to boot the Linux system before other filesystems are mounted. It must include all of the required executables and libraries required to boot the remaining filesystems. After the system is booted, all other filesystems are mounted on standard, well-defined mount points as subdirectories of the root filesystem. |
+| /bin | The /bin directory contains user executable files. |
+| /boot | Contains the static bootloader and kernel executable and configuration files required to boot a Linux computer. |
+| /dev | This directory contains the device files for every hardware device attached to the system. These are not device drivers, rather they are files that represent each device on the computer and facilitate access to those devices. |
+| /etc | Contains the local system configuration files for the host computer. |
+| /home | Home directory storage for user files. Each user has a subdirectory in /home. |
+| /lib | Contains shared library files that are required to boot the system. |
+| /media | A place to mount external removable media devices such as USB thumb drives that may be connected to the host. |
+| /mnt | A temporary mountpoint for regular filesystems (as in not removable media) that can be used while the administrator is repairing or working on a filesystem. |
+| /opt | Optional files such as vendor supplied application programs should be located here. |
+| /root | This is not the root (/) filesystem. It is the home directory for the root user. |
+| /sbin | System binary files. These are executables used for system administration. |
+| /tmp | Temporary directory. Used by the operating system and many programs to store temporary files. Users may also store files here temporarily. Note that files stored here may be deleted at any time without prior notice. |
+| /usr | These are shareable, read-only files, including executable binaries and libraries, man files, and other types of documentation. |
+| /var | Variable data files are stored here. This can include things like log files, MySQL, and other database files, web server data files, email inboxes, and much more. |
+
+
Table 1: The top level of the Linux filesystem hierarchy.