Merge pull request #8 from LCTT/master

2016-10-3
This commit is contained in:
Chao-zhi Liu 2016-10-03 08:46:59 +08:00 committed by GitHub
commit 0f6cdd9558
90 changed files with 4012 additions and 3465 deletions

View File

@ -0,0 +1,59 @@
什么是 Copyleft
=============
如果你在开源项目中花费了很多时间的话,你可能会看到使用的术语 “copyleft”GNU 官方网站上的释义:[中文][1][英文][2])。虽然这个术语使用比较普遍,但是很多人却不理解它。软件许可是一个至少不亚于文件编辑器和打包格式的激烈辩论的主题。专家们对 copyleft 的理解可能会充斥在好多书中,但是这篇文章可以作为你理解 copyleft 启蒙之路的起点。
### 什么是 copyright
在我们可以理解 copyleft 之前,我们必须先介绍一下 copyright 的概念。copyleft 并不是一个脱离于 copyright 的法律框架copyleft 存在于 copyright 规则中。那么,什么是 copyright
它的准确定义随着司法权的不同而不同但是其本质就是作品的作者对于作品的复制copying因此这个术语称之为 “copyright”copy right、表现等有一定的垄断性。在美国其宪法明确地阐述了美国国会的任务就是制定版权法律来“促进科学和实用艺术的进步”。
不同于以往,版权会立刻附加到作品上——而且不需要注册。默认情况下,所有的权力都是保留的。也就是说,没有经过作者的允许,没有人可以重新出版、表现或者修改作品。这种“允许”就是一种许可,可能还会附加有一定的条件。
如果希望得到对于 copyright 更彻底的介绍Coursera 上的[教育工作者和图书管理员的著作权](https://www.coursera.org/learn/copyright-for-education)是一个非常优秀的课程。
### 什么是 copyleft
先不要着急,在我们讨论 copyleft 是什么之前还有一步。首先让我们解释一下开源open source意味着什么。所有的开源许可协议按照[开源倡议的定义Open Source Inititative's definition](https://opensource.org/osd)(规定),除其他形式外,必须以源码的形式发放。获得开源软件的任何人都有权利查看并修改源码。
copyleft 许可和所谓的 “自由permissive” 许可不同的地方在于,其衍生的作品中,也需要相同的 copyleft 许可。我倾向于通过这种方式来区分两者不同: 自由permissive许可向直接下游的开发者提供了最大的自由包括能够在闭源项目中使用开源代码的权力而 copyleft 许可则向最终用户提供最大的自由。
GNU 项目为 copyleft 提供了这个简单的定义([中文][3][英文][4]):“规则就是当重新分发该程序时,你不可以添加限制来否认其他人对于[自由软件]的自由。the rule that when redistributing the program, you cannot add restrictions to deny other people the central freedoms [of free software].)”这可以被认为权威的定义,因为 [GNU 通用许可证GNU General Public LicenseGPL](https://www.gnu.org/licenses/gpl.html)的各种版本的依然是最广泛使用的 copyleft 许可。
### 软件中的 copyleft
GPL 家族是最出名的 copyleft 许可,但是它们并不是唯一的。[Mozilla 公共许可协议Mozilla Public LicenseMPL](https://www.mozilla.org/en-US/MPL/)和[Eclipse 公共许可协议( Eclipse Public LicenseEPL](https://www.eclipse.org/legal/epl-v10.html)也很出名。很多[其它的 copyleft 许可](https://tldrlegal.com/licenses/tags/Copyleft) 也有较少的采用。
就像之前章节介绍的那样,一个 copyleft 许可意味着下游的项目不可以在软件的使用上添加额外的限制。这最好用一个例子来说明。如果我写了一个名为 MyCoolProgram 的程序,并且使用 copyleft 许可来发布,你将有使用和修改它的自由。你可以发布你修改后的版本,但是你必须让你的用户拥有我给你的同样的自由。(但)如果我使用 “自由permissive” 许可,你将可以将它自由地合并到一个不提供源码的闭源软件中。
对于我的 MyCoolProgram 程序,和你必须能做什么同样重要的是你必须不能做什么。你不必用和我完全一样的许可协议,只要它们相互兼容就行(但一般的为了简单起见,下游的项目也使用相同的许可)。你不必向我贡献出你的修改,但是你这么做的话,通常被认为一个很好的形式,尤其是这些修改是 bug 修复的话。
### 非软件中的 copyleft
虽然copyleft 的概念起始于软件世界,但是它也存在于之外的世界。“做你想做的,只要你保留其他人也有做同样的事的权力”的概念是应用于文字创作、视觉艺术等方面的知识共享署名许可([中文][5][英文][6]的一个显著的特点CC BY-SA 4.0 是贡献于 Opensource.com 默认的许可,也是很多开源网站,包括 [Linux.cn][7] 在内所采用的内容许可协议)。[GNU 自由文档许可证](https://www.gnu.org/licenses/fdl.html)是另一个非软件协议中 copyleft 的例子。在非软件中使用软件协议通常不被建议。
### 我是否需要选择一种 copyleft 许可?
关于项目应该使用哪一种许可可以用已经有了成篇累牍的文章在阐述。我的建议是首先将许可列表缩小以满足你的哲学信条和项目目标。GitHub 的 [choosealicense.com](http://choosealicense.com/) 是一种查找满足你的需求的许可协议的好方法。[tl;drLegal](https://tldrlegal.com/)使用平实的语言来解释了许多常见和不常见的软件许可。而且也要考虑你的项目所在的生态系统,围绕一种特定语言和技术的项目经常使用相同或者相似的许可。如果你希望你的项目可以运行的更出色,你可能需要确保你选择的许可是兼容的。
关于更多 copyleft 的信息,请查看 [copyleft 指南](https://copyleft.org/)。
--------------------------------------------------------------------------------
via: https://opensource.com/resources/what-is-copyleft
作者:[Ben Cotton][a]
译者:[yangmingming](https://github.com/yangmingming)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/bcotton
[1]: https://www.gnu.org/licenses/copyleft.zh-cn.html
[2]: https://www.gnu.org/licenses/copyleft.en.html
[3]: https://www.gnu.org/philosophy/free-sw.zh-cn.html
[4]: https://www.gnu.org/philosophy/free-sw.en.html
[5]: https://creativecommons.org/licenses/by-sa/4.0/deed.zh
[6]: https://creativecommons.org/licenses/by-sa/4.0/
[7]: https://linux.cn/

View File

@ -0,0 +1,66 @@
零配置部署 React
========================
你想使用 [React][1] 来构建应用吗?“[入门][2]”是很容易的,可是接下来呢?
React 是一个构建用户界面的库而它只是组成一个应用的一部分。应用还有其他的部分——风格、路由器、npm 模块、ES6 代码、捆绑和更多——这就是为什么使用它们的开发者不断流失的原因。这被称为 [JavaScript 疲劳][3]。尽管存在这种复杂性,但是使用 React 的用户依旧继续增长。
社区应对这一挑战的方法是共享[模版文件][4]。这些模版文件展示出开发者们架构选择的多样性。官方的“开始入门”似乎离一个实际可用的应用程序相去甚远。
### 新的,零配置体验
受开发者来自 [Ember.js][5] 和 [Elm][6] 的经验启发Facebook 的人们想要提供一个简单、直接的方式。他们发明了一个[新的开发 React 应用的方法][10] `create-react-app`。在初始的公开版发布的三个星期以来,它已经受到了极大的社区关注(超过 8000 个 GitHub 粉丝)和支持(许多的拉取请求)。
`create-react-app` 是不同于许多过去使用模板和开发启动工具包的尝试。它的目标是零配置的[惯例-优于-配置][7],使开发者关注于他们的应用的不同之处。
零配置一个强大的附带影响是这个工具可以在后台逐步成型。零配置奠定了工具生态系统的基础,创造的自动化和喜悦的开发远远超越 React 本身。
### 将零配置部署到 Heroku 上
多亏了 create-react-app 中打下的零配置基础,零配置的目标看起来快要达到了。因为这些新的应用都使用一个公共的、默认的架构,构建的过程可以被自动化,同时可以使用智能的默认项来配置。因此,[我们创造这个社区构建包来体验在 Heroku 零配置的过程][8]。
#### 在两分钟内创造和发布 React 应用
你可以免费在 Heroku 上开始构建 React 应用。
```
npm install -g create-react-app
create-react-app my-app
cd my-app
git init
heroku create -b https://github.com/mars/create-react-app-buildpack.git
git add .
git commit -m "react-create-app on Heroku"
git push heroku master
heroku open
```
[使用构建包文档][9]亲自试试吧。
### 从零配置出发
create-react-app 非常的新(目前版本是 0.2),同时因为它的目标是简洁的开发者体验,更多高级的使用情景并不支持(或者肯定不会支持)。例如,它不支持服务端渲染或者自定义捆绑。
为了支持更好的控制create-react-app 包括了 npm run eject 命令。Eject 将所有的工具(配置文件和 package.json 依赖库)解压到应用所在的路径,因此你可以按照你心中的想法定做。一旦被弹出,你做的改变或许有必要选择一个特定的用 Node.js 或静态的构建包来布署。总是通过一个分支/拉取请求来使类似的工程改变生效因此这些改变可以轻易撤销。Heroku 的预览应用对测试发布的改变是完美的。
我们将会追踪 create-react-app 的进度,当它们可用时,同时适配构建包来支持更多的高级使用情况。发布万岁!
--------------------------------------------------------------------------------
via: https://blog.heroku.com/deploying-react-with-zero-configuration
作者:[Mars Hall][a]
译者:[zky001](https://github.com/zky001)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://blog.heroku.com/deploying-react-with-zero-configuration
[1]: https://facebook.github.io/react/
[2]: https://facebook.github.io/react/docs/getting-started.html
[3]: https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4
[4]: https://github.com/search?q=react+boilerplate
[5]: http://emberjs.com/
[6]: http://elm-lang.org/
[7]: http://rubyonrails.org/doctrine/#convention-over-configuration
[8]: https://github.com/mars/create-react-app-buildpack
[9]: https://github.com/mars/create-react-app-buildpack#usage
[10]: https://github.com/facebookincubator/create-react-app

View File

@ -0,0 +1,59 @@
Linux 发行版们应该禁用 IPv4 映射的 IPv6 地址吗?
=============================================
从各方面来看,互联网向 IPv6 的过渡是件很缓慢的事情。不过在最近几年,可能是由于 IPv4 地址资源的枯竭IPv6 的使用处于[上升态势][1]。相应的,开发者也有兴趣确保软件能在 IPv4 和 IPv6 下工作。但是,正如近期 OpenBSD 邮件列表的讨论所关注的,一个使得向 IPv6 转换更加轻松的机制设计同时也可能导致网络更不安全——并且 Linux 发行版们的默认配置可能并不安全。
### 地址映射
IPv6 在很多方面看起来可能很像 IPv4但它是一个不同地址空间的不同的协议。服务器程序想要接受使用二者之中任意一个协议的连接必须给两个不同的地址族分别打开一个套接字——IPv4 的 `AF_INET` 和 IPv6 的 `AF_INET6`。特别是一个程序希望在主机的使用两种地址协议的任意接口都接受连接的话,需要创建一个绑定到全零通配符地址(`0.0.0.0`)的 `AF_INET` 套接字和一个绑定到 IPv6 等效地址(写作 `::`)的 `AF_INET6` 套接字。它必须在两个套接字上都监听连接——或者有人会这么认为。
多年前,在 [RFC 3493][2]IETF 指定了一个机制,程序可以使用一个单独的 IPv6 套接字工作在两个协议之上。有了一个启用这个行为的套接字,程序只需要绑定到 `::` 来在所有接口上接受使用这两个协议连接。当创建了一个 IPv4 连接到该绑定端口,源地址会像 [RFC 2373][3] 中描述的那样映射到 IPv6。所以举个例子一个使用了这个模式的程序会将一个 `192.168.1.1` 的传入连接看作来自 `::ffff:192.168.1.1`(这个混合的写法就是这种地址通常的写法)。程序也能通过相同的映射方法打开一个到 IPv4 地址的连接。
RFC 要求这个行为要默认实现所以大多数系统这么做了。不过也有些例外OpenBSD 就是其中之一;在那里,希望在两种协议下工作的程序能做的只能是创建两个独立的套接字。但一个在 Linux 中打开两个套接字的程序会遇到麻烦IPv4 和 IPv6 套接字都会尝试绑定到 IPv4 地址,所以不论是哪个后者都会失败。换句话说,一个绑定到 `::` 指定端口的套接字的程序会同时绑定到 IPv6 `::` 和 IPv4 `0.0.0.0` 地址的那个端口上。如果程序之后尝试绑定一个 IPv4 套接字到 `0.0.0.0` 的相同端口上时,这个操作会失败,因为这个端口已经被绑定了。
当然有个办法可以解决这个问题;程序可以调用 `setsockopt()` 来打开 `IPV6_V6ONLY` 选项。一个打开两个套接字并且设置了 `IPV6_V6ONLY` 的程序应该可以在所有的系统间移植。
读者们可能对不是每个程序都能正确处理这一问题没那么震惊。事实证明这些程序的其中之一是网络时间协议Network Time Protocol的 [OpenNTPD][4] 实现。Brent Cook 最近给上游 OpenNTPD 源码[提交了一个小补丁][5],添加了必要的 `setsockopt()` 调用,它也被提交到了 OpenBSD 中了。不过那个补丁看起来不大可能被接受,最可能是因为 OpenBSD 式的理由LCTT 译注如前文提到的OpenBSD 并不受这个问题的影响)。
### 安全担忧
正如上文所提到OpenBSD 根本不支持 IPv4 映射的 IPv6 套接字。即使一个程序试着通过将 `IPV6_V6ONLY` 选项设置为 0 显式地启用地址映射,它的作者会感到沮丧,因为这个设置在 OpenBSD 系统中无效。这个决定背后的原因是这个映射带来了一些安全担忧。攻击打开的接口的攻击类型有很多种,但它们最后都会回到规定的两个途径到达相同的端口,每个端口都有它自己的控制规则。
任何给定的服务器系统可能都设置了防火墙规则,描述端口的允许访问权限。也许还会有适当的机制,比如 TCP wrappers 或一个基于 BPF 的过滤器,或一个网络上的路由器可以做连接状态协议过滤。结果可能是导致防火墙保护和潜在的所有类型的混乱连接之间的缺口导致同一 IPv4 地址可以通过两个不同的协议到达。如果地址映射是在网络边界完成的,情况甚至会变得更加复杂;参看[这个 2003 年的 RFC 草案][6],它描述了如果映射地址在主机之间传播,一些随之而来的其它攻击场景。
改变系统和软件正确地处理 IPv4 映射的 IPv6 地址当然可以实现。但那增加了系统的整体复杂度,并且可以确定这个改动没有实际地完整实现到它应该实现的范围内。如同 Theo de Raadt [说的][7]
> **有时候人们将一个糟糕的想法放进了 RFC。之后他们发现这个想法是不可能的就将它丢回垃圾箱了。结果就是概念变得如此复杂每个人都得在管理和编码方面是个全职专家。**
我们也根本不清楚这些全职专家有多少在实际配置使用 IPv4 映射的 IPv6 地址的系统和网络。
有人可能会说,尽管 IPv4 映射的 IPv6 地址造成了安全危险,更改一下程序让它在实现了地址映射的系统上关闭地址映射应该没什么危害。但 Theo [认为][8]不应该这么做,有两个理由。第一个是有许多破旧的程序,它们永远不会被修复。而实际的原因是给发行版们施加压力去默认关闭地址映射。正如他说的:“**最终有人会理解这个危害是系统性的并更改系统默认行为使之secure by default**。”
### Linux 上的地址映射
在 Linux 系统,地址映射由一个叫做 `net.ipv6.bindv6only` 的 sysctl 开关控制;它默认设置为 0启用地址映射。管理员或发行版们可以通过将它设置为 1 来关闭地址映射但在部署这样一个系统到生产环境之前最好确认软件都能正常工作。一个快速调查显示没有哪个主要发行版改变这个默认值Debian 在 2009 年的 “squeeze” 中[改变了这个默认值][9],但这个改动破坏了足够多的软件包(比如[任何包含 Java 的程序][10][在经过了几次的 Debian 式的讨论之后][11],它恢复到了原来的设置。看上去不少程序依赖于默认启用地址映射。
OpenBSD 有以“secure by default”的名义打破其核心系统之外的东西的传统而 Linux 发行版们则更倾向于难以作出这样的改变。所以那些一般不愿意收到他们用户的不满的发行版们,不太可能很快对 bindv6only 的默认设置作出改变。好消息是这个功能作为默认已经很多年了,但很难找到被利用的例子。但是,正如我们都知道的,谁都无法保证这样的利用不可能发生。
--------------------------------------------------------------------------------
via: https://lwn.net/Articles/688462/
作者:[Jonathan Corbet][a]
译者:[alim0x](https://github.com/alim0x)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://lwn.net/
[1]: https://www.google.com/intl/en/ipv6/statistics.html
[2]: https://tools.ietf.org/html/rfc3493#section-3.7
[3]: https://tools.ietf.org/html/rfc2373#page-10
[4]: https://github.com/openntpd-portable/
[5]: https://lwn.net/Articles/688464/
[6]: https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
[7]: https://lwn.net/Articles/688465/
[8]: https://lwn.net/Articles/688466/
[9]: https://lists.debian.org/debian-devel/2009/10/msg00541.html
[10]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=560056
[11]: https://lists.debian.org/debian-devel/2010/04/msg00099.html

View File

@ -0,0 +1,76 @@
Instagram 基于 Python 语言的 Web Service 效率提升之道
===============================================
Instagram 目前部署了世界上最大规模的 Django Web 框架(该框架完全使用 Python 编写)。我们最初选用 Python 是因为它久负盛名的简洁性与实用性这非常符合我们的哲学思想——“先做简单的事情”。但简洁性也会带来效率方面的折衷。Instagram 的规模在过去两年中已经翻番,并且最近已突破 5 亿用户,所以急需最大程度地提升 web 服务效率以便我们的平台能够继续顺利地扩大。在过去的一年我们已经将效率计划efficiency program提上日程并在过去的六个月我们已经能够做到无需向我们的 Django 层Django tiers添加新的容量来维持我们的用户增长。我们将在本文分享一些由我们构建的工具以及如何使用它们来优化我们的日常部署流程。
### 为何需要提升效率?
Instagram正如所有的软件受限于像服务器和数据中心能源这样的物理限制。鉴于这些限制在我们的效率计划中有两个我们希望实现的主要目标
1. Instagram 应当能够利用持续代码发布正常地提供通信服务,防止因为自然灾害、区域性网络问题等造成某一个数据中心区丢失。
2. Instagram 应当能够自由地滚动发布新产品和新功能,不必因容量而受阻。
想要实现这些目标我们意识到我们需要持续不断地监控我们的系统并与回归regressions进行战斗。
### 定义效率
Web services 的瓶颈通常在于每台服务器上可用的 CPU 时间。在这种环境下,效率就意味着利用相同的 CPU 资源完成更多的任务也就是说每秒处理更多的用户请求requests per second, RPS。当我们寻找优化方法时我们面临的第一个最大的挑战就是尝试量化我们当前的效率。到目前为止我们一直在使用“每次请求的平均 CPU 时间”来评估效率,但使用这种指标也有其固有限制:
1. **设备多样性**。使用 CPU 时间来测量 CPU 资源并非理想方案,因为它同时受到 CPU 型号与 CPU 负载的影响。
2. **请求影响数据**。测量每次请求的 CPU 资源并非理想方案因为在使用每次请求测量per-request measurement方案时添加或移除轻量级或重量级的请求也会影响到效率指标。
相对于 CPU 时间来说CPU 指令是一种更好的指标,因为对于相同的请求,它会报告相同的数字,不管 CPU 型号和 CPU 负载情况如何。我们选择使用了一种叫做“每个活动用户per active user”的指标而不是将我们所有的数据关联到每个用户请求上。我们最终采用“每个活动用户在高峰期间的 CPU 指令CPU instruction per active user during peak minute”来测量效率。我们建立好新的度量标准后下一步就是通过对 Django 的分析来更多的了解一下我们的回归。
### Django web services 分析
通过分析我们的 Django web services我们希望回答两个主要问题
1. CPU 回归会发生吗?
2. 是什么导致了 CPU 回归发生以及我们该怎样修复它?
想要回答第一个问题,我们需要追踪”每个活动用户的 CPU 指令CPU-instruction-per-active-user“指标。如果该指标增加我们就知道已经发生了一次 CPU 回归。
我们为此构建的工具叫做 Dynostats。Dynostats 利用 Django 中间件以一定的速率采样用户请求,记录关键的效率以及性能指标,例如 CPU 总指令数、端到端请求时延、花费在访问内存缓存memcache和数据库服务的时间等。另一方面每个请求都有很多可用于聚合的元数据metadata例如端点名称、HTTP 请求返回码、服务该请求的服务器名称以及请求中最新提交的哈希值hash。对于单个请求记录来说有两个方面非常强大因为我们可以在不同的维度上进行切割那将帮助我们减少任何导致 CPU 回归的原因。例如,我们可以根据它们的端点名称聚合所有请求,正如下面的时间序列图所示,从图中可以清晰地看出在特定端点上是否发生了回归。
![](https://d262ilb51hltx0.cloudfront.net/max/800/1*3iouYiAchYBwzF-v0bALMw.png)
CPU 指令对测量效率很重要——当然它们也很难获得。Python 并没有支持直接访问 CPU 硬件计数器CPU 硬件计数器是指可编程 CPU 寄存器,用于测量性能指标,例如 CPU 指令的公共库。另一方面Linux 内核提供了 `perf_event_open` 系统调用。通过 Python `ctypes` 桥接技术能够让我们调用标准 C 库的系统调用函数 `syscall`,它也为我们提供了兼容 C 的数据类型,从而可以编程硬件计数器并从它们读取数据。
使用 Dynostats我们已经可以找出 CPU 回归,并探究 CPU 回归发生的原因,例如哪个端点受到的影响最多,谁提交了真正会导致 CPU 回归的变更等。然而,当开发者收到他们的变更已经导致一次 CPU 回归发生的通知时,他们通常难以找出问题所在。如果问题很明显,那么回归可能就不会一开始就被提交!
这就是为何我们需要一个 Python 分析器,(一旦 Dynostats 发现了它)从而使开发者能够使用它找出回归发生的根本原因。不同于白手起家,我们决定对一个现成的 Python 分析器 cProfile 做适当的修改。cProfile 模块通常会提供一个统计集合来描述程序不同的部分执行时间和执行频率。我们将 cProfile 的定时器timer替换成了一个从硬件计数器读取的 CPU 指令计数器,以此取代对时间的测量。我们在采样请求后产生数据并把数据发送到数据流水线。我们也会发送一些我们在 Dynostats 所拥有的类似元数据,例如服务器名称、集群、区域、端点名称等。
在数据流水线的另一边我们创建了一个消费数据的尾随者tailer。尾随者的主要功能是解析 cProfile 的统计数据并创建能够表示 Python 函数级别的 CPU 指令的实体。如此,我们能够通过 Python 函数来聚合 CPU 指令,从而更加方便地找出是什么函数导致了 CPU 回归。
### 监控与警报机制
在 Instagram我们[每天部署 30-50 次后端服务][1]。这些部署中的任何一个都能发生 CPU 回归的问题。因为每次发生通常都包含至少一个差异diff所以找出任何回归是很容易的。我们的效率监控机制包括在每次发布前后都会在 Dynostats 中扫描 CPU 指令,并且当变更超出某个阈值时发出警告。对于长期会发生 CPU 回归的情况,我们也有一个探测器为负载最繁重的端点提供日常和每周的变更扫描。
部署新的变更并非触发一次 CPU 回归的唯一情况。在许多情况下新的功能和新的代码路径都由全局环境变量global environment variablesGEV控制。 在一个计划好的时间表上,给一部分用户发布新功能是很常见事情。我们在 Dynostats 和 cProfile 统计数据中为每个请求添加了这个信息作为额外的元数据字段。按这些字段将请求分组可以找出由全局环境变量GEV改变导致的可能的 CPU 回归问题。这让我们能够在它们对性能造成影响前就捕获到 CPU 回归。
### 接下来是什么?
Dynostats 和我们定制的 cProfile以及我们建立的支持它们的监控和警报机制能够有效地找出大多数导致 CPU 回归的元凶。这些进展已经帮助我们恢复了超过 50% 的不必要的 CPU 回归,否则我们就根本不会知道。
我们仍然还有一些可以提升的方面,并很容易将它们地加入到 Instagram 的日常部署流程中:
1. CPU 指令指标应该要比其它指标如 CPU 时间更加稳定但我们仍然观察了让我们头疼的差异。保持“信噪比signal:noise ratio”合理地低是非常重要的这样开发者们就可以集中于真实的回归上。这可以通过引入置信区间confidence intervals的概念来提升并在信噪比过高时发出警报。针对不同的端点变化的阈值也可以设置为不同值。
2. 通过更改 GEV 来探测 CPU 回归的一个限制就是我们要在 Dynostats 中手动启用这些比较的日志输出。当 GEV 的数量逐渐增加,开发了越来越多的功能,这就不便于扩展了。相反,我们能够利用一个自动化框架来调度这些比较的日志输出,并对所有的 GEV 进行遍历,然后当检查到回归时就发出警告。
3. cProfile 需要一些增强以便更好地处理封装函数以及它们的子函数。
鉴于我们在为 Instagram 的 web service 构建效率框架中所投入的工作,所以我们对于将来使用 Python 继续扩展我们的服务很有信心。我们也开始向 Python 语言本身投入更多,并且开始探索从 Python 2 转移 Python 3 之道。我们将会继续探索并做更多的实验以继续提升基础设施与开发者效率,我们期待着很快能够分享更多的经验。
本文作者 Min Ni 是 Instagram 的软件工程师。
--------------------------------------------------------------------------------
via: https://engineering.instagram.com/web-service-efficiency-at-instagram-with-python-4976d078e366#.tiakuoi4p
作者:[Min Ni][a]
译者:[ChrisLeeGit](https://github.com/chrisleegit)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://engineering.instagram.com/@InstagramEng?source=post_header_lockup
[1]: https://engineering.instagram.com/continuous-deployment-at-instagram-1e18548f01d1#.p5adp7kcz

View File

@ -0,0 +1,239 @@
科学音频处理(二):如何使用 Octave 对音频文件进行基本数学信号处理
=========
在[前一篇的指导教程][1]中,我们看到了读、写以及重放音频文件的简单步骤,我们甚至看到如何从一个周期函数比如余弦函数合成一个音频文件。在这篇指导教程中,我们将会看到如何对信号进行叠加和倍乘(调整),并应用一些基本的数学函数看看它们对原始信号的影响。
### 信号叠加
两个信号 S1t和 S2t相加形成一个新的信号 R(t),这个信号在任何瞬间的值等于构成它的两个信号在那个时刻的值之和。就像下面这样:
```
R(t) = S1(t) + S2(t)
```
我们将用 Octave 重新产生两个信号的和并通过图表看达到的效果。首先,我们生成两个不同频率的信号,看一看它们的叠加信号是什么样的。
#### 第一步产生两个不同频率的信号oog 文件)
```
>> sig1='cos440.ogg'; %creating the audio file @440 Hz
>> sig2='cos880.ogg'; %creating the audio file @880 Hz
>> fs=44100; %generating the parameters values (Period, sampling frequency and angular frequency)
>> t=0:1/fs:0.02;
>> w1=2*pi*440*t;
>> w2=2*pi*880*t;
>> audiowrite(sig1,cos(w1),fs); %writing the function cos(w) on the files created
>> audiowrite(sig2,cos(w2),fs);
```
然后我们绘制出两个信号的图像。
**信号 1 的图像440 赫兹)**
```
>> [y1, fs] = audioread(sig1);
>> plot(y1)
```
[![信号 1 的图像](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsignal1.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsignal1.png)
**信号 2 的图像880 赫兹)**
```
>> [y2, fs] = audioread(sig2);
>> plot(y2)
```
[![信号 2 的图像](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsignal2.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsignal2.png)
#### 第二步:把两个信号叠加
现在我们展示一下前面步骤中产生的两个信号的和。
```
>> sumres=y1+y2;
>> plot(sumres)
```
叠加信号的图像
[![和信号的图像](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsum.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsum.png)
**Octaver 中的效果**
在 Octaver 中,这个效果产生的声音是独特的,因为它可以仿真音乐家弹奏的低八度或者高八度音符(取决于内部程序设计),仿真音符和原始音符成对,也就是两个音符发出相同的声音。
#### 第三步:把两个真实的信号相加(比如两首音乐歌曲)
为了实现这个目的我们使用格列高利圣咏Gregorian Chants中的两首歌曲声音采样
**圣母颂曲Avemaria Track**
首先,我们看一下圣母颂曲并绘出它的图像:
```
>> [y1,fs]=audioread('avemaria_.ogg');
>> plot(y1)
```
[![圣母歌曲](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/avemaria.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/avemaria.png)
**赞美诗曲Hymnus Track**
现在我们看一下赞美诗曲并绘出它的图像。
```
>> [y2,fs]=audioread('hymnus.ogg');
>> plot(y2)
```
[![赞美诗曲](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/hymnus.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/hymnus.png)
**圣母颂曲 + 赞美诗曲**
```
>> y='avehymnus.ogg';
>> audiowrite(y, y1+y2, fs);
>> [y, fs]=audioread('avehymnus.ogg');
>> plot(y)
```
[![圣母歌曲 + 赞美诗曲](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/avehymnus.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/avehymnus.png)
结果,从音频的角度来看,两个声音信号混合在了一起。
### 两个信号的乘积
对于求两个信号的乘积,我们可以使用类似求和的方法。我们使用之前生成的相同文件。
```
R(t) = S1(t) * S2(t)
```
```
>> sig1='cos440.ogg'; %creating the audio file @440 Hz
>> sig2='cos880.ogg'; %creating the audio file @880 Hz
>> product='prod.ogg'; %creating the audio file for product
>> fs=44100; %generating the parameters values (Period, sampling frequency and angular frequency)
>> t=0:1/fs:0.02;
>> w1=2*pi*440*t;
>> w2=2*pi*880*t;
>> audiowrite(sig1, cos(w1), fs); %writing the function cos(w) on the files created
>> audiowrite(sig2, cos(w2), fs);>> [y1,fs]=audioread(sig1);>> [y2,fs]=audioread(sig2);
>> audiowrite(product, y1.*y2, fs); %performing the product
>> [yprod,fs]=audioread(product);
>> plot(yprod); %plotting the product
```
注意:我们必须使用操作符 .*’,因为在参数文件中,这个乘积是值与值相乘。更多信息,请参考 Octave 矩阵操作产品手册。
#### 乘积生成信号的图像
[![乘积信号的图像](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotprod.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotprod.png)
#### 两个基本频率相差很大的信号相乘后的图表效果(调制原理)
**第一步:**
生成两个频率为 220 赫兹的声音信号。
```
>> fs=44100;
>> t=0:1/fs:0.03;
>> w=2*pi*220*t;
>> y1=cos(w);
>> plot(y1);
```
[![载波](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/carrier.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/carrier.png)
**第二步:**
生成一个 22000 赫兹的高频调制信号。
```
>> y2=cos(100*w);
>> plot(y2);
```
[![调制中](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/modulating.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/modulating.png)
**第三步:**
把两个信号相乘并绘出图像。
```
>> plot(y1.*y2);
```
[![调制后的信号](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/modulated.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/modulated.png)
### 一个信号和一个标量相乘
一个函数和一个标量相乘的效果等于更改它的值域,在某些情况下,更改的是相标志。给定一个标量 K ,一个函数 F(t) 和这个标量相乘定义为:
```
R(t) = K*F(t)
```
```
>> [y,fs]=audioread('cos440.ogg'); %creating the work files
>> res1='coslow.ogg';
>> res2='coshigh.ogg';>> res3='cosinverted.ogg';
>> K1=0.2; %values of the scalars
>> K2=0.5;>> K3=-1;
>> audiowrite(res1, K1*y, fs); %product function-scalar
>> audiowrite(res2, K2*y, fs);
>> audiowrite(res3, K3*y, fs);
```
**原始信号的图像**
```
>> plot(y)
```
[![](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/originalsignal.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/originalsignal.png)
**信号振幅减为原始信号振幅的 0.2 倍后的图像**
```
>> plot(res1)
```
[![低余弦](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/coslow.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/coslow.png)
**信号振幅减为原始振幅的 0.5 倍后的图像**
```
>> plot(res2)
```
[![高余弦](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/coshigh.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/coshigh.png)
**倒相后的信号图像**
```
>> plot(res3)
```
[![倒相余弦](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/cosinverted.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/cosinverted.png)
### 结论
基本数学运算比如代数和、乘,以及函数与常量相乘是更多高级运算比如谱分析、振幅调制,角调制等的支柱和基础。在下一个教程中,我们来看一看如何进行这样的运算以及它们对声音文件产生的效果。
--------------------------------------------------------------------------------
via: https://www.howtoforge.com/tutorial/octave-audio-signal-processing-ubuntu/
作者:[David Duarte][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.howtoforge.com/tutorial/octave-audio-signal-processing-ubuntu/
[1]: https://linux.cn/article-7755-1.html

View File

@ -0,0 +1,135 @@
你必须了解的基础的 Linux 网络命令
==================================================
![](https://itsfoss.com/wp-content/uploads/2016/06/Basic-Networking-Commands-Linux.jpg)
> 摘要:有抱负的 Linux 系统管理员和 Linux 狂热者必须知道的、最重要的、而且基础的 Linux 网络命令合集。
在 Its FOSS 我们并非每天都谈论 Linux 的“命令行方面”。基本上,我更专注于 Linux 的桌面端。但你们读者中的一些人在内部调查(仅面向 It's FOSS newsletter 订阅者)中指出,你们也想学些命令行技巧。速查表也受大部分读者所喜欢和支持。
为此,我编辑了一个 Linux 中基础网络命令的列表。它并不是一个教你如何使用这些命令的教程,而是一个命令合集和他们的简短解释。所以,如果你已经使用过这些命令,你可以用它来快速记住命令。
你可以把这个网页添加为书签以便快速查阅,或输出一个 PDF 版本以便离线使用。
当我还是通信系统工程专业的学生的时候我就有这个 Linux 网络命令的列表了。它帮助我在计算机网络课程获得了高分。希望它也能以同样的方式帮助你。
### Linux 基础网络命令列表
我在计算机网络课程上使用 FreeBSD不过这些 UNIX 命令应该也能在 Linux 上同样工作。
#### 连通性
- `ping <host>`:发送 ICMP echo 消息(一个包)到主机。这可能会不停地发送直到你按下 `Control-C`。Ping 的通意味着一个包从你的机器通过 ICMP 发送出去,并在 IP 层回显。Ping 告诉你另一个主机是否在运行。
- `telnet <host> [port]`:与主机在指定的端口通信。默认的 telnet 端口是 23。按 Control-] 以退出 telnet。其它一些常用的端口是
- 7 —— echo 端口
- 25 —— SMTP用于发送邮件
- 79 —— Finger (LCTT 译注:[维基百科 - Finger protocal](https://en.wikipedia.org/wiki/Finger_protocol),不过举例 Finger 恐怕不合时宜,倒不如试试 80提供该网络下其它用户的信息。
#### ARP
ARP 用于将 IP 地址转换为以太网地址。root 用户可以添加和删除 ARP 记录。当 ARP 记录被污染或者错误时删除它们会有用。root 显式添加的 ARP 记录是永久的 —— 代理设置的也是。ARP 表保存在内核中动态地被操作。ARP 记录会被缓存,通常在 20 分钟后失效并被删除。
- `arp -a`:打印 ARP 表。
- `arp -s <ip_address> <mac_address> [pub]`:添加一条记录到表中。
- `arp -a -d`:删除 ARP 表中的所有记录。
#### 路由
- `netstat -r`:打印路由表。路由表保存在内核中,用于 IP 层把包路由到非本地网络。
- `route add`route 命令用于向路由表添加静态(手动指定而非动态)路由路径。所有从该 PC 到那个 IP/子网的流量都会经由指定的网关 IP。它也可以用来设置一个默认路由。例如在 IP/子网处使用 0.0.0.0,就可以发送所有包到特定的网关。
- `routed`:控制动态路由的 BSD 守护程序。开机时启动。它运行 RIP 路由协议。只有 root 用户可用。没有 root 权限你不能运行它。
- `gated`gated 是另一个使用 RIP 协议的路由守护进程。它同时支持 OSPF、EGP 和 RIP 协议。只有 root 用户可用。
- `traceroute`:用于跟踪 IP 包的路由。它每次发送包时都把跳数加 1从而使得从源地址到目的地之间的所有网关都会返回消息。
- `netstat -rnf inet`:显示 IPv4 的路由表。
- `sysctl net.inet.ip.forwarding=1`:启用包转发(把主机变为路由器)。
- `route add|delete [-net|-host] <destination> <gateway>`:(如 `route add 192.168.20.0/24 192.168.30.4`)添加一条路由。
- `route flush`:删除所有路由。
- `route add -net 0.0.0.0 192.168.10.2`:添加一条默认路由。
- `routed -Pripv2 -Pno_rdisc -d [-s|-q]`:运行 routed 守护进程,使用 RIPv2 协议,不启用 ICMP 自动发现,在前台运行,供给模式或安静模式。
- `route add 224.0.0.0/4 127.0.0.1`为本地地址定义多播路由。LCTT 译注:原文存疑)
- `rtquery -n <host>`LCTT 译注:增加了 host 参数):查询指定主机上的 RIP 守护进程(手动更新路由表)。
#### 其它
- `nslookup`:向 DNS 服务器查询,将 IP 转为名称,或反之。例如,`nslookup facebook.com` 会给出 facebook.com 的 IP。
- `ftp <host> [port]`LCTT 译注:原文中 water 应是笔误):传输文件到指定主机。通常可以使用 登录名 "anonymous" , 密码 "guest" 来登录。
- `rlogin -l <host>`LCTT 译注:添加了 host 参数):使用类似 telnet 的虚拟终端登录到主机。
#### 重要文件
- `/etc/hosts`:域名到 IP 地址的映射。
- `/etc/networks`:网络名称到 IP 地址的映射。
- `/etc/protocols`:协议名称到协议编号的映射。
- `/etc/services`TCP/UDP 服务名称到端口号的映射。
#### 工具和网络性能分析
- `ifconfig <interface> <address> [up]`:启动接口。
- `ifconfig <interface> [down|delete]`:停止接口。
- `ethereal &`:在后台打开 `ethereal` 而非前台。
- `tcpdump -i -vvv`:抓取和分析包的工具。
- `netstat -w [seconds] -I [interface]`:显示网络设置和统计信息。
- `udpmt -p [port] -s [bytes] target_host`:发送 UDP 流量。
- `udptarget -p [port]`:接收 UDP 流量。
- `tcpmt -p [port] -s [bytes] target_host`:发送 TCP 流量。
- `tcptarget -p [port]`:接收 TCP 流量。
#### 交换机
- `ifconfig sl0 srcIP dstIP`:配置一个串行接口(在此前先执行 `slattach -l /dev/ttyd0`,此后执行 `sysctl net.inet.ip.forwarding=1`
- `telnet 192.168.0.254`:从子网中的一台主机访问交换机。
- `sh ru``show running-configuration`:查看当前配置。
- `configure terminal`:进入配置模式。
- `exit`退出当前模式。LCTT 译注:原文存疑)
#### VLAN
- `vlan n`:创建一个 ID 为 n 的 VLAN。
- `no vlan N`:删除 ID 为 n 的 VLAN。
- `untagged Y`:添加端口 Y 到 VLAN n。
- `ifconfig vlan0 create`:创建 vlan0 接口。
- `ifconfig vlan0 vlan_ID vlandev em0`:把 em0 加入到 vlan0 接口LCTT 译注:原文存疑),并设置标记为 ID。
- `ifconfig vlan0 [up]`:启用虚拟接口。
- `tagged Y`:为当前 VLAN 的端口 Y 添加标记帧支持。
#### UDP/TCP
- `socklab udp`:使用 UDP 协议运行 `socklab`
- `sock`:创建一个 UDP 套接字,等效于输入 `sock udp``bind`
- `sendto <Socket ID> <hostname> <port #>`:发送数据包。
- `recvfrom <Socket ID> <byte #>`:从套接字接收数据。
- `socklab tcp`:使用 TCP 协议运行 `socklab`
- `passive`:创建一个被动模式的套接字,等效于 `socklab``sock tcp``bind``listen`。
- `accept`:接受进来的连接(可以在发起进来的连接之前或之后执行)。
- `connect <hostname> <port #>`:等效于 `socklab``sock tcp``bind``connect`。
- `close`:关闭连接。
- `read <byte #>`:从套接字中读取 n 字节。
- `write`:(例如,`write ciao`、`write #10`)向套接字写入 "ciao" 或 10 个字节。
#### NAT/防火墙
- `rm /etc/resolv.conf`:禁止地址解析,保证你的过滤和防火墙规则正确工作。
- `ipnat -f file_name`:将过滤规则写入文件。
- `ipnat -l`:显示活动的规则列表。
- `ipnat -C -F`:重新初始化规则表。
- `map em0 192.168.1.0/24 -> 195.221.227.57/32 em0`:将 IP 地址映射到接口。
- `map em0 192.168.1.0/24 -> 195.221.227.57/32 portmap tcp/udp 20000:50000`:带端口号的映射。
- `ipf -f file_name`:将过滤规则写入文件。
- `ipf -F -a`:重置规则表。
- `ipfstat -I`:当与 -s 选项合用时列出活动的状态条目LCTT 译注:原文存疑)。
希望这份基础的 Linux 网络命令合集对你有用。欢迎各种问题和建议。
--------------------------------------------------------------------------------
via: https://itsfoss.com/basic-linux-networking-commands
作者:[Abhishek Prakash][a]
译者:[bianjp](https://github.com/bianjp)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[1]: https://drive.google.com/open?id=0By49_3Av9sT1cDdaZnh4cHB4aEk

View File

@ -0,0 +1,219 @@
Git 系列(六):如何搭建你自己的 Git 服务器
====================
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/bus-big-data.png?itok=sOQHDuID)
现在我们将要学习如何搭建 git 服务器,如何编写自定义的 Git 钩子来在特定的事件触发相应的动作(例如通知),或者是发布你的代码到一个站点。
直到现在,我们主要讨论的还是以一个使用者的身份与 Git 进行交互。这篇文章中我将讨论 Git 的管理,并且设计一个灵活的 Git 框架。你可能会觉得这听起来是 “高阶 Git 技术” 或者 “只有狂热粉才能阅读”的一句委婉的说法,但是事实是这里面的每个任务都不需要很深的知识或者其他特殊的训练,就能基本理解 Git 的工作原理,有可能需要一丁点关于 Linux 的知识。
### 共享 Git 服务器
创建你自己的共享 Git 服务器意外地简单,而且在很多情况下,遇到的这点麻烦是完全值得的。不仅仅是因为它保证你有权限查看自己的代码,它还可以通过扩展为 Git 的使用敞开了一扇大门,例如个人 Git 钩子、无限制的数据存储、和持续集成与分发CI & CD
如果你知道如何使用 Git 和 SSH那么你已经知道怎么创建一个 Git 服务器了。Git 的设计方式,就是让你在创建或者 clone 一个仓库的时候,就完成了一半服务器的搭建。然后允许用 SSH 访问仓库,而且任何有权限访问的人都可以使用你的仓库作为 clone 的新仓库的基础。
但是这是一个小的点对点环境ad-hoc。按照一些方案你可以创建一些带有同样的功能的设计优良的 Git 服务器,同时有更好的拓展性。
首要之事:确认你的用户们,现在的用户以及之后的用户都要考虑。如果你是唯一的用户那么没有任何改动的必要。但是如果你试图邀请其他的代码贡献者使用,那么你应该允许一个专门的分享系统用户给你的开发者们。
假定你有一个可用的服务器如果没有这不成问题Git 会帮忙解决CentOS 的 [树莓派 3][3] 是个不错的开始),然后第一步就是只允许使用 SSH 密钥认证的 SSH 登录。这比使用密码登录安全得多,因为这可以免于暴力破解,也可以通过直接删除用户密钥而禁用用户。
一旦你启用了 SSH 密钥认证,创建 `gituser` 用户。这是给你的所有授权的用户们的公共用户:
```
$ su -c 'adduser gituser'
```
然后切换到刚创建的 `gituser` 用户,创建一个 `~/.ssh` 的框架,并设置好合适的权限。这很重要,如果权限设置得太开放会使自己所保护的 SSH 没有意义。
```
$ su - gituser
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys
```
`authorized_keys` 文件里包含所有你的开发者们的 SSH 公钥,你开放权限允许他们可以在你的 Git 项目上工作。他们必须创建他们自己的 SSH 密钥对然后把他们的公钥给你。复制公钥到 gituser 用户下的 `authorized_keys` 文件中。例如,为一个叫 Bob 的开发者,执行以下命令:
```
$ cat ~/path/to/id_rsa.bob.pub >> /home/gituser/.ssh/authorized_keys
```
只要开发者 Bob 有私钥并且把相对应的公钥给你Bob 就可以用 `gituser` 用户访问服务器。
但是,你并不是想让你的开发者们能使用服务器,即使只是以 `gituser` 的身份访问。你只是想给他们访问 Git 仓库的权限。因为这个特殊的原因Git 提供了一个限制的 shell准确的说是 `git-shell`。以 root 身份执行以下命令,把 `git-shell` 添加到你的系统中,然后设置成 `gituser` 用户的默认 shell。
```
# grep git-shell /etc/shells || su -c "echo `which git-shell` >> /etc/shells"
# su -c 'usermod -s git-shell gituser'
```
现在 `gituser` 用户只能使用 SSH 来 push 或者 pull Git 仓库,并且无法使用任何一个可以登录的 shell。你应该把你自己添加到和 `gituser` 一样的组中,在我们的样例服务器中这个组的名字也是 `gituser`
举个例子:
```
# usermod -a -G gituser seth
```
仅剩下的一步就是创建一个 Git 仓库。因为没有人能在服务器上直接与 Git 交互(也就是说,你之后不能 SSH 到服务器然后直接操作这个仓库),所以创建一个空的仓库 。如果你想使用这个放在服务器上的仓库来完成工作,你可以从它的所在处 `clone` 下来,然后在你的 home 目录下进行工作。
严格地讲你不是必须创建这个空的仓库它和一个正常的仓库一样工作。但是一个空的仓库没有工作分支working tree (也就是说,使用 `checkout` 并没有任何分支显示)。这很重要,因为不允许远程使用者们 `push` 到一个有效的分支上(如果你正在 `dev` 分支工作然后突然有人把一些变更 `push` 到你的工作分支,你会有怎么样的感受?)。因为一个空的仓库可以没有有效的分支,所以这不会成为一个问题。
你可以把这个仓库放到任何你想放的地方,只要你想要放开权限给用户和用户组,让他们可以在仓库下工作。千万不要保存目录到比如说一个用户的 home 目录下,因为那里有严格的权限限制。保存到一个常规的共享地址,例如 `/opt` 或者 `/usr/local/share`
以 root 身份创建一个空的仓库:
```
# git init --bare /opt/jupiter.git
# chown -R gituser:gituser /opt/jupiter.git
# chmod -R 770 /opt/jupiter.git
```
现在任何一个用户,只要他被认证为 `gituser` 或者在 `gituser` 组中,就可以从 jupiter.git 库中读取或者写入。在本地机器尝试以下操作:
```
$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
Cloning into 'jupiter.clone'...
Warning: you appear to have cloned an empty repository.
```
谨记:开发者们**一定**要把他们的 SSH 公钥加入到 `gituser` 用户下的 `authorized_keys` 文件里,或者说,如果他们有服务器上的用户(如果你给了他们用户),那么他们的用户必须属于 `gituser` 用户组。
### Git 钩子
运行你自己的 Git 服务器最赞的一件事之一就是可以使用 Git 钩子。Git 托管服务有时提供一个钩子类的接口,但是他们并不会给你真正的 Git 钩子来让你访问文件系统。Git 钩子是一个脚本,它将在一个 Git 过程的某些点运行;钩子可以运行在当一个仓库即将接收一个 commit 时、或者接受一个 commit 之后,或者即将接收一次 push 时,或者一次 push 之后等等。
这是一个简单的系统:任何放在 `.git/hooks` 目录下的脚本、使用标准的命名体系,就可按设计好的时间运行。一个脚本是否应该被运行取决于它的名字; `pre-push` 脚本在 `push` 之前运行,`post-receive` 脚本在接受 `commit` 之后运行等等。这或多或少的可以从名字上看出来。
脚本可以用任何语言写;如果在你的系统上有可以执行的脚本语言,例如输出 hello world ,那么你就可以这个语言来写 Git 钩子脚本。Git 默认带了一些例子,但是并不有启用。
想要动手试一个?这很简单。如果你没有现成的 Git 仓库,首先创建一个 Git 仓库:
```
$ mkdir jupiter
$ cd jupiter
$ git init .
```
然后写一个 “hello world” 的 Git 钩子。因为我为了支持老旧系统而使用 tsch所以我仍然用它作为我的脚本语言你可以自由的使用自己喜欢的语言BashPythonRubyPerlRustSwiftGo
```
$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" >> ~/jupiter/.git/hooks/post-commit
$ chmod +x ~/jupiter/.git/hooks/post-commit
```
现在测试它的输出:
```
$ echo "hello world" > foo.txt
$ git add foo.txt
$ git commit -m 'first commit'
! POST-COMMIT SCRIPT TRIGGERED
[master (root-commit) c8678e0] first commit
1 file changed, 1 insertion(+)
create mode 100644 foo.txt
```
现在你已经实现了:你的第一个有功能的 Git 钩子。
### 有名的 push-to-web 钩子
Git 钩子最流行的用法就是自动 `push` 更改的代码到一个正在使用中的产品级 Web 服务器目录下。这是摆脱 FTP 的很好的方式,对于正在使用的产品保留完整的版本控制,整合并自动化内容的发布。
如果操作正确网站发布工作会像以前一样很好的完成而且在某种程度上很精准。Git 真的好棒。我不知道谁最初想到这个主意,但是我是从 Emacs 和 Git 方面的专家IBM 的 Bill von Hagen 那里第一次听到它的。他的文章包含关于这个过程的权威介绍:[Git 改变了分布式网页开发的游戏规则][1]。
### Git 变量
每一个 Git 钩子都有一系列不同的变量对应触发钩子的不同 Git 行为。你需不需要这些变量,主要取决于你写的程序。如果你只是需要一个当某人 push 代码时候的通用邮件通知,那么你就不需要什么特殊的东西,甚至也不需要编写额外的脚本,因为已经有现成的适合你的样例脚本。如果你想在邮件里查看 commit 信息和 commit 的作者,那么你的脚本就会变得相对麻烦些。
Git 钩子并不是被用户直接执行所以要弄清楚如何收集可能会混淆的重要信息。事实上Git 钩子脚本类似于其他的脚本,像 BASH、Python、C++ 等等一样从标准输入读取参数。不同的是,我们不会给它提供这个输入,所以,你在使用的时候,需要知道可能的输入参数。
在写 Git 钩子之前,看一下 Git 在你的项目目录下 `.git/hooks` 目录中提供的一些例子。举个例子,在这个 `pre-push.sample` 文件里,注释部分说明了如下内容:
```
# $1 -- 即将 push 的远程仓库的名字
# $2 -- 即将 push 的远程仓库的 URL
# 如果 push 的时候,并没有一个命名的远程仓库,那么这两个参数将会一样。
#
# 提交的信息将以下列形式按行发送给标准输入
# <local ref> <local sha1> <remote ref> <remote sha1>
```
并不是所有的例子都是这么清晰,而且关于钩子获取变量的文档依旧缺乏(除非你去读 Git 的源码)。但是,如果你有疑问,你可以从线上[其他用户的尝试中][2]学习,或者你只是写一些基本的脚本,比如 `echo $1, $2, $3` 等等。
### 分支检测示例
我发现,对于生产环境来说有一个共同的需求,就是需要一个只有在特定分支被修改之后,才会触发事件的钩子。以下就是如何跟踪分支的示例。
首先Git 钩子本身是不受版本控制的。 Git 并不会跟踪它自己的钩子,因为对于钩子来说,它是 Git 的一部分而不是你仓库的一部分。所以Git 钩子可以监控你的 Git 服务器上的一个空仓库的 commit 记录和 push 记录,而不是你本地仓库的一部分。
我们来写一个 `post-receive`(也就是说,在 `commit` 被接受之后触发)钩子。第一步就是需要确定分支名:
```
#!/bin/tcsh
foreach arg ( $< )
set argv = ( $arg )
set refname = $1
end
```
这个 for 循环用来读入第一个参数 `$1` ,然后循环用第二个参数 `$2` 去覆盖它,然后用第三个参数 `$3` 再这样。在 Bash 中有一个更好的方法,使用 `read` 命令,并且把值放入数组里。但是,这里是 tcsh并且变量的顺序可以预测的所以这个方法也是可行的。
当我们有了 commit 记录的 `refname`,我们就能使用 Git 去找到这个分支的供人看的名字:
```
set branch = `git rev-parse --symbolic --abbrev-ref $refname`
echo $branch #DEBUG
```
然后把这个分支名和我们想要触发的事件的分支名关键字进行比较:
```
if ( "$branch" == "master" ) then
echo "Branch detected: master"
git \
--work-tree=/path/to/where/you/want/to/copy/stuff/to \
checkout -f $branch || echo "master fail"
else if ( "$branch" == "dev" ) then
echo "Branch detected: dev"
Git \
--work-tree=/path/to/where/you/want/to/copy/stuff/to \
checkout -f $branch || echo "dev fail"
else
echo "Your push was successful."
echo "Private branch detected. No action triggered."
endif
```
给这个脚本分配可执行权限:
```
$ chmod +x ~/jupiter/.git/hooks/post-receive
```
现在,当一个用户提交到服务器的 master 分支,那些代码就会被复制到一个生产环境的目录,提交到 dev 分支则会被复制到另外的地方,其他分支将不会触发这些操作。
同时,创造一个 `pre-commit` 脚本也很简单。比如,判断一个用户是否在他们不该 `push` 的分支上 `push` 代码,或者对 commit 信息进行解析等等。
Git 钩子也可以变得复杂,而且它们因为 Git 的工作流的抽象层次不同而变得难以理解,但是它们确实是一个强大的系统,让你能够在你的 Git 基础设施上针对所有的行为进行对应的操作。如果你是一个 Git 重度用户,或者一个全职 Git 管理员,那么 Git 钩子是值得学习的,只有当你熟悉这个过程,你才能真正掌握它。
在我们这个系列下一篇也是最后一篇文章中,我们将会学习如何使用 Git 来管理非文本的二进制数据,比如音频和图片。
--------------------------------------------------------------------------------
via: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
作者:[Seth Kenlon][a]
译者:[maywanting](https://github.com/maywanting)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[1]: http://www.ibm.com/developerworks/library/wa-git/
[2]: https://www.analysisandsolutions.com/code/git-hooks-summary-cheat-sheet.htm
[3]: https://wiki.centos.org/SpecialInterestGroup/AltArch/Arm32/RaspberryPi3

View File

@ -0,0 +1,212 @@
漫游 HTTP/2
===================
自从我写了上一篇博文之后,就再也找不到空闲时间写文章了。今天我终于可以抽出时间写一些关于 HTTP 的东西。
我认为每一个 web 开发者都应该对这个支撑了整个 Web 世界的 HTTP 协议有所了解,这样才能帮助你更好的完成开发任务。
在这篇文章中,我将讨论什么是 HTTP它是怎么产生的它的地位以及我们应该怎么使用它。
### HTTP 是什么
首先我们要明白 HTTP 是什么。HTTP 是一个基于 `TCP/IP` 的应用层通信协议它是客户端和服务端在互联网互相通讯的标准。它定义了内容是如何通过互联网进行请求和传输的。HTTP 是在应用层中抽象出的一个标准,使得主机(客户端和服务端)之间的通信得以通过 `TCP/IP` 来进行请求和响应。TCP 默认使用的端口是 `80`,当然也可以使用其它端口,比如 HTTPS 使用的就是 `443` 端口。
### `HTTP/0.9` - 单行协议 (1991)
HTTP 最早的规范可以追溯到 1991 年,那时候的版本是 `HTTP/0.9`,该版本极其简单,只有一个叫做 `GET` 的 请求方式。如果客户端要访问服务端上的一个页面,只需要如下非常简单的请求:
```
GET /index.html
```
服务端的响应类似如下:
```
(response body)
(connection closed)
```
就这么简单,服务端捕获到请求后立马返回 HTML 并且关闭连接,在这之中:
- 没有头信息headers
- 仅支持 `GET` 这一种请求方法
- 必须返回 HTML
如同你所看到的,当时的 HTTP 协议只是一块基础的垫脚石。
### HTTP/1.0 - 1996
在 1996 年,新版本的 HTTP 对比之前的版本有了极大的改进,同时也被命名为 `HTTP/1.0`
`HTTP/0.9` 只能返回 HTML 不同的是,`HTTP/1.0` 支持处理多种返回的格式,比如图片、视频、文本或者其他格式的文件。它还增加了更多的请求方法(如 `POST``HEAD`请求和响应的格式也相应做了改变两者都增加了头信息引入了状态码来定义返回的特征引入了字符集支持支持多段类型multi-part、用户验证信息、缓存、内容编码格式等等。
一个简单的 HTTP/1.0 请求大概是这样的:
```
GET / HTTP/1.0
Host: kamranahmed.info
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
```
正如你所看到的,在请求中附带了客户端中的一些个人信息、响应类型要求等内容。这些是在 `HTTP/0.9` 无法实现的,因为那时候没有头信息。
一个对上述请求的响应例子如下所示:
```
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
(response body)
(connection closed)
```
`HTTP/1.0` HTTP 后面跟的是版本号)早期开始,在状态码 `200` 之后就附带一个原因短语(你可以用来描述状态码)。
在这个较新一点的版本中,请求和响应的头信息仍然必须是 `ASCII` 编码但是响应的内容可以是任意类型如图片、视频、HTML、文本或其他类型服务器可以返回任意内容给客户端。所以这之后`HTTP` 中的“超文本Hyper Text”成了名不副实。 `HMTP` (超媒体传输协议 - Hypermedia transfer protocol可能会更有意义但是我猜我们还是会一直沿用这个名字。
`HTTP/1.0` 的一个主要缺点就是它不能在一个连接内拥有多个请求。这意味着,当客户端需要从服务器获取东西时,必须建立一个新的 TCP 连接,并且处理完单个请求后连接即被关闭。需要下一个东西时,你必须重新建立一个新的连接。这样的坏处在哪呢?假设你要访问一个有 `10` 张图片,`5` 个样式表stylesheet`5` 个 JavaScript 的总计 `20` 个文件才能完整展示的一个页面。由于一个连接在处理完成一次请求后即被关闭,所以将有 `20` 个单独的连接,每一个文件都将通过各自对应的连接单独处理。当连接数量变得庞大的时候就会面临严重的性能问题,因为 `TCP` 启动需要经过三次握手,才能缓慢开始。
#### 三次握手
三次握手是一个简单的模型,所有的 `TCP` 连接在传输应用数据之前都需要在三次握手中传输一系列数据包。
- `SYN` - 客户端选取一个随机数,我们称为 `x`,然后发送给服务器。
- `SYN ACK` - 服务器响应对应请求的 `ACK` 包中,包含了一个由服务器随机产生的数字,我们称为 `y`,并且把客户端发送的 `x+1`,一并返回给客户端。
- `ACK` - 客户端在从服务器接受到 `y` 之后把 `y` 加上 `1` 作为一个 `ACK` 包返回给服务器。
一旦三次握手完成后,客户端和服务器之间就可以开始交换数据。值得注意的是,当客户端发出最后一个 `ACK` 数据包后,就可以立刻向服务器发送应用数据包,而服务器则需要等到收到这个 `ACK` 数据包后才能接受应用数据包。
![](http://i.imgur.com/uERG2G2.png)
> 请注意,上图有点小问题,客户端发回的最后一个 ACK 包仅包含 `y+1`,上图应该是 `ACK:y+1` 而不是 `ACK:x+1,y+1`
然而,某些 HTTP/1.0 的实现试图通过新引入一个称为 `Connection: keep-alive` 的头信息来克服这一问题,这个头信息意味着告诉服务器“嘿,服务器,请不要关闭此连接,我还要用它”。但是,这并没有得到广泛的支持,问题依然存在。
除了无连接之外HTTP 还是一个无状态的协议,即服务器不维护有关客户端的信息。因此每个请求必须给服务器必要的信息才能完成请求,每个请求都与之前的旧的请求无关。所以,这增加了推波助澜的作用,客户端除了需要新建大量连接之外,在每次连接中还需要发送许多重复的数据,这导致了带宽的大量浪费。
### `HTTP/1.1` - 1999
`HTTP/1.0` 经过仅仅 3 年,下一个版本,即 `HTTP/1.1` 就在 1999 年发布了,改进了它的前身很多问题,主要的改进包括:
- **增加了许多 HTTP 请求方法**,包括 `PUT`、`PATCH`、`HEAD`、`OPTIONS`、`DELETE`。
- **主机标识符** `Host``HTTP/1.0` 并不是必须的,而在 `HTTP/1.1` 是必须的。
- 如上所述的**持久连接**。在 `HTTP/1.0` 中每个连接只有一个请求并在该请求结束后被立即关闭,这导致了性能问题和增加了延迟。 `HTTP/1.1` 引入了持久连接,即连接在默认情况下是不关闭并保持开放的,这允许多个连续的请求使用这个连接。要关闭该连接只需要在头信息加入 `Connection: close`,客户通常在最后一个请求里发送这个头信息就能安全地关闭连接。
- 新版本还引入了“**管线化pipelining**”的支持,客户端可以不用等待服务器返回响应,就能在同一个连接内发送多个请求给服务器,而服务器必须以接收到的请求相同的序列发送响应。但是你可能会问了,客户端如何知道哪里是第一个响应下载完成而下一个响应内容开始的地方呢?要解决这个问题,头信息必须有 `Content-Length`,客户可以使用它来确定哪些响应结束之后可以开始等待下一个响应。
- 值得注意的是,为了从持久连接或管线化中受益, 头部信息必须包含 `Content-Length`,因为这会使客户端知道什么时候完成了传输,然后它可以发送下一个请求(持久连接中,以正常的依次顺序发送请求)或开始等待下一个响应(启用管线化时)。
- 但是,使用这种方法仍然有一个问题。那就是,如果数据是动态的,服务器无法提前知道内容长度呢?那么在这种情况下,你就不能使用这种方法中获益了吗?为了解决这个问题,`HTTP/1.1` 引进了分块编码。在这种情况下,服务器可能会忽略 `Content-Length` 来支持分块编码(更常见一些)。但是,如果它们都不可用,那么连接必须在请求结束时关闭。
- 在动态内容的情况下**分块传输**,当服务器在传输开始但无法得到 `Content-Length` 时,它可能会开始按块发送内容(一块接一块),并在传输时为每一个小块添加 `Content-Length`。当发送完所有的数据块后,即整个传输已经完成后,它发送一个空的小块,比如设置 `Content-Length` 为 0 ,以便客户端知道传输已完成。为了通知客户端块传输的信息,服务器在头信息中包含了 `Transfer-Encoding: chunked`
- 不像 HTTP/1.0 中只有 Basic 身份验证方式,`HTTP/1.1` 包括摘要验证方式digest authentication和代理验证方式proxy authentication
- 缓存。
- 范围请求Byte Ranges
- 字符集。
- 内容协商Content Negotiation
- 客户端 cookies。
- 支持压缩。
- 新的状态码。
- 等等。
我不打算在这里讨论所有 `HTTP/1.1` 的特性,因为你可以围绕这个话题找到很多关于这些的讨论。我建议你阅读 [`HTTP/1.0` 和 `HTTP/1.1` 版本之间的主要差异][5],希望了解更多可以读[原始的 RFC][6]。
`HTTP/1.1` 在 1999 年推出,到现在已经是多年前的标准。虽然,它比前一代改善了很多,但是网络日新月异,它已经垂垂老矣。相比之前,加载网页更是一个资源密集型任务,打开一个简单的网页已经需要建立超过 30 个连接。你或许会说,`HTTP/1.1` 具有持久连接,为什么还有这么多连接呢?其原因是,在任何时刻 `HTTP/1.1` 只能有一个未完成的连接。 `HTTP/1.1` 试图通过引入管线来解决这个问题,但它并没有完全地解决。因为一旦管线遇到了缓慢的请求或庞大的请求,后面的请求便被阻塞住,它们必须等待上一个请求完成。为了克服 `HTTP/1.1` 的这些缺点,开发人员开始实现一些解决方法,例如使用 spritesheets、在 CSS 中编码图像、单个巨型 CSS / JavaScript 文件、[域名切分][7]等。
### SPDY - 2009
谷歌走在业界前列,为了使网络速度更快,提高网络安全,同时减少网页的等待时间,他们开始实验替代的协议。在 2009 年,他们宣布了 `SPDY`
> `SPDY` 是谷歌的商标,而不是一个缩写。
显而易见的是,如果我们继续增加带宽,网络性能开始的时候能够得到提升,但是到了某个阶段后带来的性能提升就很有限了。但是如果把这些优化放在等待时间上,比如减少等待时间,将会有持续的性能提升。这就是 `SPDY` 优化之前的协议的核心思想,减少等待时间来提升网络性能。
> 对于那些不知道其中区别的人,等待时间就是延迟,即数据从源到达目的地需要多长时间(单位为毫秒),而带宽是每秒钟数据的传输量(比特每秒)。
`SPDY` 的特点包括:复用、压缩、优先级、安全性等。我不打算展开 `SPDY` 的细节。在下一章节,当我们将介绍 `HTTP/2`,这些都会被提到,因为 `HTTP/2` 大多特性是从 `SPDY` 受启发的。
`SPDY` 没有试图取代 HTTP它是处于应用层的 HTTP 之上的一个传输层,它只是在请求被发送之前做了一些修改。它开始成为事实标准,大多数浏览器都开始支持了。
2015年谷歌不想有两个相互竞争的标准所以他们决定将其合并到 HTTP 协议,这样就导致了 `HTTP/2` 的出现和 `SPDY` 的废弃。
### `HTTP/2` - 2015
现在想必你明白了为什么我们需要另一个版本的 HTTP 协议了。 `HTTP/2` 是专为了低延迟地内容传输而设计。主要特点和与 `HTTP/1.1` 的差异包括:
- 使用二进制替代明文
- 多路传输 - 多个异步 HTTP 请求可以使用单一连接
- 报头使用 HPACK 压缩
- 服务器推送 - 单个请求多个响应
- 请求优先级
- 安全性
![](http://i.imgur.com/S85j8gg.png)
#### 1. 二进制协议
`HTTP/2` 通过使其成为一个二进制协议以解决 HTTP/1.x 中存在的延迟问题。作为一个二进制协议,它更容易解析,但可读性却不如 `HTTP/1.x`。帧frames和流stream的概念组成了 `HTTP/2` 的主要部分。
**帧和流**
现在 HTTP 消息是由一个或多个帧组成的。`HEADERS` 帧承载了元数据meta data`DATA` 帧则承载了内容。还有其他类型的帧(`HEADERS`、`DATA`、`RST_STREAM`、`SETTINGS`、`PRIORITY` 等等),这些你可以通过[HTTP/2 规范][3]来了解。
每个 `HTTP/2` 请求和响应都被赋予一个唯一的流 ID并切分成帧。帧就是一小片二进制数据。帧的集合称为流每个帧都有个标识了其所属流的流 ID所以在同一个流下的每个帧具有共同的报头。值得注意的是除了流 ID 是唯一的之外,​由客户端发起的请求使用了奇数作为流 ID从来自服务器的响应使用了偶数作为流 ID。
除了 `HEADERS` 帧和 `DATA` 帧,另一个值得一提的帧是 `RST_STREAM`。这是一个特殊的帧类型,用来中止流,即客户可以发送此帧让服务器知道,我不再需要这个流了。在 `HTTP/1.1` 中让服务器停止给客户端发送响应的唯一方法是关闭连接,这样造成了延迟增加,因为之后要发送请求时,就要必须打开一个新的请求。而在 `HTTP/2` ,客户端可以使用 `RST_STREAM` 来停止接收特定的数据流,而连接仍然打开着,可以被其他请求使用。
#### 2. 多路传输
因为 `HTTP/2` 是一个二进制协议,而且如上所述它使用帧和流来传输请求与响应,一旦建立了 TCP 连接,相同连接内的所有流都可以同过这个 TCP 连接异步发送,而不用另外打开连接。反过来说,服务器也可以使用同样的异步方式返回响应,也就是说这些响应可以是无序的,客户端使用分配的流 ID 来识别数据包所属的流。这也解决了 HTTP/1.x 中请求管道被阻塞的问题,即客户端不必等待占用时间的请求而其他请求仍然可以被处理。
#### 3. HPACK 请求头部压缩
RFC 花了一篇文档的篇幅来介绍针对发送的头信息的优化,它的本质是当我们在同一客户端上不断地访问服务器时,许多冗余数据在头部中被反复发送,有时候仅仅是 cookies 就能增加头信息的大小,这会占用许多宽带和增加传输延迟。为了解决这个问题,`HTTP/2` 引入了头信息压缩。
![](http://i.imgur.com/3IPWXvR.png)
不像请求和响应那样,头信息中的信息不会以 `gzip` 或者 `compress` 等格式压缩。而是采用一种不同的机制来压缩头信息客户端和服务器同时维护一张头信息表储存了使用了哈夫曼编码进行编码后的头信息的值并且后续请求中若出现同样的字段则忽略重复值例如用户代理user agent只发送存在两边信息表中它的引用即可。
我们说的头信息,它们同 HTTP/1.1 中一样,并在此基础上增加了一些伪头信息,如 `:scheme``:host` 和 `:path`
#### 4. 服务器推送
服务器推送是 `HTTP/2` 的另一个巨大的特点。对于服务器来说,当它知道客户端需要一定的资源后,它可以把数据推送到客户端,即使客户端没有请求它。例如,假设一个浏览器在加载一个网页时,它解析了整个页面,发现有一些内容必须要从服务端获取,然后发送相应的请求到服务器以获取这些内容。
服务器推送减少了传输这些数据需要来回请求的次数。它是如何做到的呢?服务器通过发送一个名字为 `PUSH_PROMISE` 特殊的帧通知到客户端“嘿,我准备要发送这个资源给你了,不要再问我要了。”这个 `PUSH_PROMISE` 帧与要产生推送的流联系在一起,并包含了要推送的流 ID也就是说这个流将会被服务器推送到客户端上。
#### 5. 请求优先级
当流被打开的时候,客户端可以在 `HEADERS` 帧中包含优先级信息来为流指定优先级。在任何时候,客户端都可以发送 `PRIORITY` 帧来改变流的优先级。
如果没有任何优先级信息,服务器将异步地无序地处理这些请求。如果流分配了优先级,服务器将基于这个优先级来决定需要分配多少资源来处理这个请求。
#### 6. 安全性
在是否强制使用 `TLS` 来增加安全性的问题上产生了大范围的讨论,讨论的结果是不强制使用。然而大多数厂商只有在使用 `TLS` 时才能使用 `HTTP/2`。所以 `HTTP/2` 虽然规范上不要求加密,但是加密已经约定俗成了。这样,在 `TLS` 之上实现 `HTTP/2` 就有了一些强制要求,比如,`TLS` 的最低版本为 `1.2`,必须达到某种级别的最低限度的密钥大小,需要布署 ephemeral 密钥等等。
到现在 `HTTP/2` 已经[完全超越了 SPDY][4]并且还在不断成长HTTP/2 有很多关系性能的提升,我们应该开始布署它了。
如果你想更深入的了解细节,请访问[该规范的链接][1]和[ HTTP/2 性能提升演示的链接][2]。请在留言板写下你的疑问或者评论,最后如果你发现有错误,请同样留言指出。
这就是全部了,我们之后再见~
--------------------------------------------------------------------------------
via: http://kamranahmed.info/blog/2016/08/13/http-in-depth/
作者:[Kamran Ahmed][a]
译者:[NearTan](https://github.com/NearTan)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://github.com/kamranahmedse
[1]: https://http2.github.io/http2-spec
[2]: http://www.http2demo.io/
[3]: https://http2.github.io/http2-spec/#FrameTypes
[4]: http://caniuse.com/#search=http2
[5]: http://www.ra.ethz.ch/cdstore/www8/data/2136/pdf/pd1.pdf
[6]: https://tools.ietf.org/html/rfc2616
[7]: https://www.maxcdn.com/one/visual-glossary/domain-sharding-2/

View File

@ -0,0 +1,217 @@
理解 Linux 下 Shell 命令的不同分类及它们的用法
====================
当你打算真正操纵好你的 Linux 系统,没有什么能比命令行界面更让你做到这一点。为了成为一个 Linux 高手,你必须能够理解 [Shell 命令的不同类型][1],并且会在终端下正确的使用它们。
在 Linux 下,命令有几种类型,对于一个 Linux 新手来说,知道不同命令的意思才能够高效和准确的使用它们。因此,在这篇文章里,我们将会遍及各种不同分类的 Linux Shell 命令。
需要注意一件非常重要的事:命令行界面和 Shell 是不同的,命令行界面只是为你提供一个访问 Shell 的方式。而 Shell ,它是可编程的,这使得它可以通过命令与内核进行交流。
下面列出了 Linux 下命令的不同种类:
### 1. 程序可执行文件(文件系统 中的命令)
当你执行一条命令的时候Linux 通过从左到右搜索存储在 `$PATH` 环境变量中的目录来找到这条命令的可执行文件。
你可以像下面这样查看存储在 `$PATH` 中的目录:
```
$ echo $PATH
/home/aaronkilik/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
```
在上面的命令中,目录 `/home/aaronkilik/bin` 将会被首先搜索,紧跟着是 `/usr/local/sbin`,然后一直接着下去。在搜索过程中,搜索顺序是至关重要的。
比如在 `/usr/bin` 目录里的文件系统中的命令:
```
$ ll /bin/
```
样本输出:
```
total 16284
drwxr-xr-x 2 root root 4096 Jul 31 16:30 ./
drwxr-xr-x 23 root root 4096 Jul 31 16:29 ../
-rwxr-xr-x 1 root root 6456 Apr 14 18:53 archdetect*
-rwxr-xr-x 1 root root 1037440 May 17 16:15 bash*
-rwxr-xr-x 1 root root 520992 Jan 20 2016 btrfs*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-calc-size*
lrwxrwxrwx 1 root root 5 Jul 31 16:19 btrfsck -> btrfs*
-rwxr-xr-x 1 root root 278376 Jan 20 2016 btrfs-convert*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-debug-tree*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-find-root*
-rwxr-xr-x 1 root root 270136 Jan 20 2016 btrfs-image*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-map-logical*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-select-super*
-rwxr-xr-x 1 root root 253816 Jan 20 2016 btrfs-show-super*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfstune*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-zero-log*
-rwxr-xr-x 1 root root 31288 May 20 2015 bunzip2*
-rwxr-xr-x 1 root root 1964536 Aug 19 2015 busybox*
-rwxr-xr-x 1 root root 31288 May 20 2015 bzcat*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzcmp -> bzdiff*
-rwxr-xr-x 1 root root 2140 May 20 2015 bzdiff*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzegrep -> bzgrep*
-rwxr-xr-x 1 root root 4877 May 20 2015 bzexe*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzfgrep -> bzgrep*
-rwxr-xr-x 1 root root 3642 May 20 2015 bzgrep*
```
### 2. Linux 别名
这些是用户定义的命令,它们是通过 shell 内置命令 `alias` 创建的,其中包含其它一些带有选项和参数的 shell 命令。这个意图主要是使用新颖、简短的名字来替代冗长的命令。
创建一个别名的语法像下面这样:
```
$ alias newcommand='command -options'
```
通过下面的命令,可以列举系统中的所有别名:
```
$ alias -p
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
```
要在 Linux 中创建一个新的别名,仔细阅读下面的例子。
```
$ alias update='sudo apt update'
$ alias upgrade='sudo apt dist-upgrade'
$ alias -p | grep 'up'
```
![](http://www.tecmint.com/wp-content/uploads/2016/08/Create-Aliase-in-Linux.png)
然而,上面这些我们创建的别名只能暂时的工作,当经过下一次系统启动后它们不再工作。你可以像下面展示的这样在 '.bashrc' 文件中设置永久别名。
![](http://www.tecmint.com/wp-content/uploads/2016/08/Set-Linux-Aliases-Permanent.png)
添加以后,运行下面的命令来激活:
```
$ source ~/.bashrc
```
### 3. Linux Shell 保留字
在 shell 程序设计中,`if`、`then`、`fi`、`for`、`while`、`case`、`esac`、`else`、`until` 以及其他更多的字都是 shell 保留字。正如描述所暗示的,它们在 shell 中有特殊的含义。
你可以通过使用下面展示的 `type` 命令来列出所有的 shell 关键字:
```
$ type if then fi for while case esac else until
if is a shell keyword
then is a shell keyword
fi is a shell keyword
for is a shell keyword
while is a shell keyword
case is a shell keyword
esac is a shell keyword
else is a shell keyword
until is a shell keyword
```
### 4. Linux shell 函数
一个 shell 函数是一组在当前 shell 内一起执行的命令。函数有利于在 shell 脚本中实现特殊任务。在 shell 脚本中写 shell 函数的传统形式是下面这样:
```
function_name() {
command1
command2
......
}
```
或者像这样:
```
function function_name {
command1
command2
......
}
```
让我们看一看如何在一个名为 shell_functions.sh 的脚本中写 shell 函数。
```
#!/bin/bash
#write a shell function to update and upgrade installed packages
upgrade_system(){
sudo apt update;
sudo apt dist-upgrade;
}
#execute function
upgrade_system
```
取代通过命令行执行两条命令:`sudo apt update` 和 `sudo apt dist-upgrade`,我们在脚本内写了一个像执行一条单一命令一样来执行两条命令的 shell 函数 upgrade_system。
保存文件,然后使脚本可执行。最后像下面这样运行 shell 函数:
```
$ chmod +x shell_functions.sh
$ ./shell_functions.sh
```
![](http://www.tecmint.com/wp-content/uploads/2016/08/Linux-Shell-Functions-Script.png)
### 5. Linux Shell 内置命令
这些是在 shell 中内置的 Linux 命令,所以你无法在文件系统中找到它们。这些命令包括 `pwd`、`cd`、`bg`、`alias`、`history`、`type`、`source`、`read`、`exit` 等。
你可以通过下面展示的 `type` 命令来列出或检查 Linux 内置命令:
```
$ type pwd
pwd is a shell builtin
$ type cd
cd is a shell builtin
$ type bg
bg is a shell builtin
$ type alias
alias is a shell builtin
$ type history
history is a shell builtin
```
学习一些 Linux 内置命令用法:
- [Linux 下 15 个 pwd 命令例子][2]
- [Linux 下 15 个 cd 命令例子][3]
- [了解 Linux 下 history 命令的威力][4]
### 结论
作为一个 Linux 用户,知道你所运行的命令类型是很重要的。我相信,通过上面明确、简单并且易于理解的解释,包括一些相关的说明,你可能对 “[Linux 命令的不同种类][1]”有了很好的理解。
你也可以在下面的评论区提任何问题或补充意见,从而和我们取得联系。
--------------------------------------------------------------------------------
via: http://www.tecmint.com/understanding-different-linux-shell-commands-usage/
作者:[Aaron Kili][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.tecmint.com/author/aaronkili/
[1]: http://www.tecmint.com/different-types-of-linux-shells/
[2]: http://www.tecmint.com/pwd-command-examples/
[3]: http://www.tecmint.com/cd-command-in-linux/
[4]: http://www.tecmint.com/history-command-examples/
[5]: http://www.tecmint.com/category/linux-commands/

View File

@ -0,0 +1,265 @@
Ohm用两百行 JavaScript 创造你自己的编程语言
==========
![](https://www.pubnub.com/wp-content/uploads/2016/08/ohm-banner.jpg)
解析器是一种超级有用的软件库。从概念上简单的说,它们的实现很有挑战性,并且在计算机科学中经常被认为是黑魔法。在这个系列的博文中,我会向你们展示为什么你不需要成为哈利波特就能够精通解析器这种魔法。但是为了以防万一带上你的魔杖吧!
我们将探索一种叫做 Ohm 的新的开源库,它使得搭建解析器很简单并且易于重用。在这个系列里,我们使用 Ohm 去识别数字,构建一个计算器等等。在这个系列的最后你将已经用不到 200 行的代码发明了一种完整的编程语言。这个强大的工具将让你能够做到一些你可能过去认为不可能的事情。
###为什么解析器很困难?
解析器非常有用。在很多时候你可能需要一个解析器。或许有一种你需要处理的新的文件格式,但还没有人为它写了一个库;又或许你发现了一种古老格式的文件,但是已有的解析器不能在你的平台上构建。我已经看到这样的事发生无数次。 Code 在或者不在, Data 就在那里,不增不减。
从根本上来说,解析器很简单:只是把一个数据结构转化成另一个。所以你会不会觉得你要是邓布利多校长就好了?
解析器历来是出奇地难写,所面临的挑战是绝大多数现有的工具都很老,并且需要一定的晦涩难懂的计算机科学知识。如果你在大学里上过编译器课程,那么课本里也许还有从上世纪七十年传下来的技术。幸运的是,解析器技术从那时候起已经提高了很多。
典型的,解析器是通过使用一种叫作[形式语法formal grammar][1]的特殊语法来定义你想要解析的东西来创造的,然后你需要把它放入像 [Bison][2] 和 [Yacc][3] 的工具中,这些工具能够产生一堆 C 代码,这些代码你需要修改或者链接到你实际写入的编程语言中。另外的选择是用你更喜欢的语言亲自动手写一个解析器,这很慢且很容易出错,在你能够真正使用它之前还有许多额外的工作。
想像一下是否你关于你想要解析的东西的语法描述也是解析器如果你能够只是直接运行这些语法然后仅在你需要的地方增加一些挂钩hook那就是 Ohm 所可以做到的事。
### Ohm 简介
[Ohm][4]是一种新的解析系统。它类似于你可能已经在课本里面看到过的语法,但是它更强大,使用起来更简单。通过 Ohm, 你能够使用一种灵活的语法在一个 .ohm 文件中来写你自己的格式定义,然后使用你的宿主语言把语义加入到里面。在这篇博文里,我们将用 JavaScript 作为宿主语言。
Ohm 建立于一个为创造更简单、更灵活的解析器的多年研究基础之上。VPRI 的 [STEPS program (pdf)][5] 使用 Ohm 的前身 [Ometa][6] 为许多特殊的任务创造了专门的语言(比如一个有 400 行代码的平行制图描绘器)。
Ohm 有许多有趣的特点和符号,但是相比于全部解释它们,我认为我们只需要深入其中并构建一些东西就行了。
###解析整数
让我们来解析一些数字。这看起来会很简单,只需在一个文本串中寻找毗邻的数字,但是让我们尝试去处理所有形式的数字:整数和浮点数、十六进制数和八进制数、科学计数、负数。解析数字很简单,正确解析却很难。
亲自构建这个代码将会很困难,会有很多问题,会伴随有许多特殊的情况,比如有时会相互矛盾。正则表达式或许可以做的这一点,但是它会非常丑陋而难以维护。让我们用 Ohm 来试试。
用 Ohm 构建的解析器涉及三个部分语法grammar、语义semantics和测试tests。我通常挑选问题的一部分为它写测试然后构建足够的语法和语义来使测试通过。然后我再挑选问题的另一部分增加更多的测试、更新语法和语义从而确保所有的测试能够继续通过。即使我们有了新的强大的工具写解析器从概念上来说依旧很复杂。测试是用一种合理的方式来构建解析器的唯一方法。现在让我们开始工作。
我们将从整数开始。一个整数由一系列相互毗邻的数字组成。让我们把下面的内容放入一个叫做 grammar.ohm 的文件中:
```
CoolNums {
// just a basic integer
Number = digit+
}
```
这创造了一条匹配一个或多个数字(`digit`)叫作 `Number` 的单一规则。`` 意味着一个或更多,就在正则表达式中一样。当有一个或更多的数字时,这个规则将会匹配它们,如果没有数字或者有一些不是数字的东西将不会匹配。“数字(`digit`)”的定义是从 0 到 9 其中的一个字符。`digit` 也是像 `Number` 一样的规则,但是它是 Ohm 的其中一条构建规则因此我们不需要去定义它。如果我们想的话可以推翻它,但在这时候这没有任何意义,毕竟我们不打算去发明一种新的数。
现在,我们可以读入这个语法并用 Ohm 库来运行它。
把它放入 test1.js
```
var ohm = require('ohm-js');
var fs = require('fs');
var assert = require('assert');
var grammar = ohm.grammar(fs.readFileSync('src/blog_numbers/syntax1.ohm').toString());
```
`Ohm.grammar` 调用将读入该文件并解析成一个语法对象。现在我们可以增加一些语义。把下面内容增加到你的 JavaScript 文件中:
```
var sem = grammar.createSemantics().addOperation('toJS', {
Number: function(a) {
return parseInt(this.sourceString,10);
}
});
```
这通过 `toJS` 操作创造了一个叫作 `sem` 的语法集。这些语义本质上是一些对应到语法中每个规则的函数。每个函数当与之相匹配的语法规则被解析时将会被调用。上面的 `Number` 函数将会在语法中的 `Number` 规则被解析时被调用。语法grammar定义了在语言中这些代码是什么语义semantics定义了当这些代码被解析时应该做什么。
语义函数能够做我们想做的任何事,比如打印出故障信息、创建对象,或者在任何子节点上递归调用 `toJS`。此时我们仅仅想把匹配的文本转换成真正的 JavaScript 整数。
所有的语义函数有一个内含的 `this` 对象,带有一些有用的属性。其 `source` 属性代表了输入文本中和这个节点相匹配的部分。`this.sourceString` 是一个匹配输入的串,调用内置在 JavaScript 中的 `parseInt` 函数会把这个串转换成一个数。传给 `parseInt``10` 这个参数告诉 JavaScript 我们输入的是一个以 `10` 为基底10 进制)的数。如果少了这个参数, JavaScript 也会假定以 10 为基底,但是我们把它包含在里面因为后面我们将支持以 16 为基底的数,所以使之明确比较好。
既然我们有一些语法,让我们来实际解析一些东西看一看我们的解析器是否能够工作。如何知道我们的解析器可以工作?通过测试,许多许多的测试,每一个可能的边缘情况都需要一个测试。
使用标准的断言 `assert` API以下这个测试函数能够匹配一些输入并运用我们的语义把它转换成一个数然后把这个数和我们期望的输入进行比较。
```
function test(input, answer) {
var match = grammar.match(input);
if(match.failed()) return console.log("input failed to match " + input + match.message);
var result = sem(match).toJS();
assert.deepEqual(result,answer);
console.log('success = ', result, answer);
}
```
就是如此。现在我们能够为各种不同的数写一堆测试。如果匹配失败我们的脚本将会抛出一个例外。否则就打印成功信息。让我们尝试一下,把下面这些内容加入到脚本中:
```
test("123",123);
test("999",999);
test("abc",999);
```
然后用 `node test1.js` 运行脚本。
你的输出应该是这样:
```
success = 123 123
success = 999 999
input failed to match abcLine 1, col 1:
> 1 | abc
^
Expected a digit
```
真酷。正如预期的那样前两个成功了第三个失败了。更好的是Ohm 自动给了我们一个很棒的错误信息指出匹配失败。
###浮点数
我们的解析器工作了,但是它做的工作不是很有趣。让我们把它扩展成既能解析整数又能解析浮点数。改变 grammar.ohm 文件使它看起来像下面这样:
```
CoolNums {
// just a basic integer
Number = float | int
int = digit+
float = digit+ "." digit+
}
```
这把 `Number` 规则改变成指向一个浮点数(`float`)或者一个整数(`int`)。这个 `|` 代表着“或”。我们把这个读成“一个 `Number` 由一个浮点数或者一个整数构成。”然后整数(`int`)定义成 `digit+`,浮点数(`float`)定义成 `digit+` 后面跟着一个句号然后再跟着另一个 `digit+`。这意味着在句号前和句号后都至少要有一个数字。如果一个数中没有一个句号那么它就不是一个浮点数,因此就是一个整数。
现在,让我们再次看一下我们的语义功能。由于我们现在有了新的规则所以我们需要新的功能函数:一个作为整数的,一个作为浮点数的。
```
var sem = grammar.createSemantics().addOperation('toJS', {
Number: function(a) {
return a.toJS();
},
int: function(a) {
console.log("doing int", this.sourceString);
return parseInt(this.sourceString,10);
},
float: function(a,b,c) {
console.log("doing float", this.sourceString);
return parseFloat(this.sourceString);
}
});
```
这里有两件事情需要注意。首先,整数(`int`)、浮点数(`float`)和数(`Number`)都有相匹配的语法规则和函数。然而,针对 `Number` 的功能不再有任何意义。它接收子节点 `a` 然后返回该子节点的 `toJS` 结果。换句话说,`Number` 规则简单的返回相匹配的子规则。由于这是在 Ohm 中任何规则的默认行为,因此实际上我们不用去考虑 `Number` 的作用Ohm 会替我们做好这件事。
其次,整数(`int`)有一个参数 `a`,然而浮点数有三个:`a`、`b` 和 `c`。这是由于规则的实参数量arity决定的。[实参数量arity][7] 意味着一个规则里面有多少参数。如果我们回过头去看语法,浮点数(`float`)的规则是:
```
float = digit+ "." digit+
```
浮点数规则通过三个部分来定义:第一个 `digit+`、`.`、以及第二个 `digit+`。这三个部分都会作为参数传递给浮点数的功能函数。因此浮点数必须有三个参数,否则 Ohm 库会给出一个错误。在这种情况下我们不用在意参数,因为我们仅仅直接攫取了输入串,但是我们仍然需要参数列在那里来避免编译器错误。后面我们将实际使用其中一些参数。
现在我们可以为新的浮点数支持添加更多的测试。
```
test("123",123);
test("999",999);
//test("abc",999);
test('123.456',123.456);
test('0.123',0.123);
test('.123',0.123);
```
注意最后一个测试将会失败。一个浮点数必须以一个数开始,即使它就是个 0`.123` 不是有效的,实际上真正的 JavaScript 语言也有相同的规则。
###十六进制数
现在我们已经有了整数和浮点数,但是还有一些其它的数的语法最好可以支持:十六进制数和科学计数。十六进制数是以 16 为基底的整数。十六进制数的数字能从 0 到 9 和从 A 到 F。十六进制数经常用在计算机科学中当用二进制数据工作时你可以仅仅使用两个数字表示 0 到 255 的数。
在绝大多数源自 C 的编程语言(包括 JavaScript十六进制数通过在前面加上 `0x` 来向编译器表明后面跟的是一个十六进制数。为了让我们的解析器支持十六进制数,我们只需要添加另一条规则。
```
Number = hex | float | int
int = digit+
float = digit+ "." digit+
hex = "0x" hexDigit+
hexDigit := "0".."9" | "a".."f" | "A".."F"
```
我实际上已经增加了两条规则。十六进制数(`hex`)表明它是一个 `0x` 后面一个或多个十六进制数字(`hexDigits`)的串。一个十六进制数字(`hexDigit`)是从 0 到 9或从 a 到 f或 A 到 F包括大写和小写的情况的一个字符。我也修改了 `Number` 规则来识别十六进制数作为另外一种可能的情况。现在我们只需要另一条针对十六进制数的功能规则。
```
hex: function(a,b) {
return parseInt(this.sourceString,16);
}
```
注意到,在这种情况下,我们把 `16` 作为基底传递给 `parseInt`,因为我们希望 JavaScript 知道这是一个十六进制数。
我略过了一些很重要需要注意的事。`hexDigit` 的规则像下面这样:
```
hexDigit := "0".."9" | "a".."f" | "A".."F"
```
注意我使用的是 `:=` 而不是 `=`。在 Ohm 中,`:=` 是当你需要推翻一条规则的时候使用。这表明 Ohm 已经有了一条针对 `hexDigit` 的默认规则,就像 `digit`、`space` 等一堆其他的东西。如果我使用了 `=`, Ohm 将会报告一个错误。这是一个检查,从而避免我无意识的推翻一个规则。由于新的 `hexDigit` 规则和 Ohm 的构建规则一样,所以我们可以把它注释掉,然后让 Ohm 自己来实现它。我留下这个规则只是因为这样我们可以看到它实际上是如何进行的。
现在,我们可以添加更多的测试然后看到十六进制数真的能工作:
```
test('0x456',0x456);
test('0xFF',255);
```
###科学计数
最后,让我们来支持科学计数。科学计数是针对非常大或非常小的数的,比如 `1.8×10^3`。在大多数编程语言中科学计数法表示的数会写成这样1.8e3 表示 18000或者 1.8e-3 表示 .018。让我们增加另外一对规则来支持这个指数表示:
```
float = digit+ "." digit+ exp?
exp = "e" "-"? digit+
```
上面在浮点数规则末尾增加了一个指数(`exp`)规则和一个 `?`。`?` 表示没有或有一个,所以指数(`exp`)是可选的,但是不能超过一个。增加指数(`exp`)规则也改变了浮点数规则的实参数量,所以我们需要为浮点数功能增加另一个参数,即使我们不使用它。
```
float: function(a,b,c,d) {
console.log("doing float", this.sourceString);
return parseFloat(this.sourceString);
},
```
现在我们的测试可以通过了:
```
test('4.8e10',4.8e10);
test('4.8e-10',4.8e-10);
```
###结论
Ohm 是构建解析器的一个很棒的工具因为它易于上手并且你可以递增的增加规则。Ohm 也还有其他我今天没有写到的很棒的特点,比如调试观察仪和子类化。
到目前为止,我们已经使用 Ohm 来把字符串翻译成 JavaScript 数,并且 Ohm 经常用于把一种表示方式转化成另外一种。然而Ohm 还有更多的用途。通过放入不同的语义功能集,你可以使用 Ohm 来真正处理和计算东西。一个单独的语法可以被许多不同的语义使用,这是 Ohm 的魔法之一。
在这个系列的下一篇文章中,我将向你们展示如何像真正的计算机一样计算像 `(4.85 + 5 * (238 - 68)/2)` 这样的数学表达式,不仅仅是解析数。
额外的挑战:你能够扩展语法来支持八进制数吗?这些以 8 为基底的数能够只用 0 到 7 这几个数字来表示,前面加上一个数字 0 或者字母 `o`。看看针对下面这些测试情况是够正确。下次我将给出答案。
```
test('0o77',7*8+7);
test('0o23',0o23);
```
--------------------------------------------------------------------------------
via: https://www.pubnub.com/blog/2016-08-30-javascript-parser-ohm-makes-creating-a-programming-language-easy/
作者:[Josh Marinacci][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.pubnub.com/blog/author/josh/
[1]: https://en.wikipedia.org/wiki/Formal_grammar
[2]: https://en.wikipedia.org/wiki/GNU_bison
[3]: https://en.wikipedia.org/wiki/Yacc
[4]: https://github.com/cdglabs/ohm
[5]: http://www.vpri.org/pdf/tr2012001_steps.pdf
[6]: http://tinlizzie.org/ometa/
[7]: https://en.wikipedia.org/wiki/Arity

View File

@ -0,0 +1,80 @@
AWS 和 GCP 的 Spark 技术哪家强?
==============
> Tianhui Michael Li 和Ariel Mndange-Pfupfu将在今年10月10、12和14号组织一个在线经验分享课程[Spark 分布式计算入门][4]。该课程的内容包括创建端到端的运行应用程序和精通 Spark 关键工具。
毋庸置疑,云计算将会在未来数据科学领域扮演至关重要的角色。弹性,可扩展性和按需分配的计算能力作为云计算的重要资源,直接导致云服务提供商集体火拼。其中最大的两股势力正是[亚马逊网络服务AWS)][1] 和[谷歌云平台GCP)][2]。
本文依据构建时间和运营成本对 AWS 和 GCP 的 Spark 工作负载作一个简短比较。实验由我们的学生在数据孵化器The Data Incubator进行[数据孵化器The Data Incubator][3]是一个大数据培训组织,专门为公司招聘顶尖数据科学家并为公司职员培训最新的大数据科学技能。尽管 Spark 效率惊人,分布式工作负载的时间和成本亦然可以大到不能忽略不计。因此我们一直努力寻求更高效的技术,以便我们的学生能够学习到最好和最快的工具。
### 提交 Spark 任务到云
[Spark][5] 是一个类 MapReduce 但是比 MapReduce 更灵活、更抽象的并行计算框架。Spark 提供 Python 和 Java 编程接口,但它更愿意用户使用原生的 Scala 语言进行应用程序开发。Scala 可以把应用程序和依赖文件打包在一个 JAR 文件从而使 Spark 任务提交变得简单。
通常情况下Sprark 结合 HDFS 应用于分布式数据存储,而与 YARN 协同工作则应用于集群管理;这种堪称完美的配合使得 Spark 非常适用于 AWS 的弹性 MapReduce EMR集群和 GCP 的 Dataproc 集群。这两种集群都已有 HDFS 和 YARN 预配置,不需要额外进行配置。
### 配置云服务
通过命令行比通过网页界面管理数据、集群和任务具有更高的可扩展性。对 AWS 而言,这意味着客户需要安装 [CLI][6]。客户必须获得证书并为每个 EC2 实例创建[独立的密钥对][7]。除此之外,客户还需要为 EMR 用户和 EMR 本身创建角色(基本权限),主要是准入许可规则,从而使 EMR 用户获得足够多的权限(通常在 CLI 运行 `aws emr create-default-roles` 就可以)。
相比而言GCP 的处理流程更加直接。如果客户选择安装 [Google Cloud SDK][8] 并且使用其 Google 账号登录,那么客户即刻可以使用 GCP 的几乎所有功能而无需其他任何配置。唯一需要提醒的是不要忘记通过 API 管理器启用计算引擎、Dataproc 和云存储 JSON 的 API。
当你安装你的喜好设置好之后,有趣的事情就发生了!比如可以通过`aws s3 cp`或者`gsutil cp`命令拷贝客户的数据到云端。再比如客户可以创建自己的输入、输出或者任何其他需要的 bucket如此运行一个应用就像创建一个集群或者提交 JAR 文件一样简单。请确定日志存放的地方,毕竟在云环境下跟踪问题或者调试 bug 有点诡异。
### 一分钱一分货
谈及成本Google 的服务在以下几个方面更有优势。首先购买计算能力的原始成本更低。4 个 vCPU 和 15G RAM 的 Google 计算引擎服务GCE每小时只需 0.20 美元,如果运行 Dataproc每小时也只需区区 0.24 美元。相比之下同等的云配置AWS EMR 则需要每小时 0.336 美元。
其次计费方式。AWS 按小时计费,即使客户只使用 15 分钟也要付足 1 小时的费用。GCP 按分钟计费,最低计费 10 分钟。在诸多用户案例中,资费方式的不同直接导致成本的巨大差异。
两种云服务都有其他多种定价机制。客户可以使用 AWS 的 Sport Instance 或 GCP 的 Preemptible Instance 来竞价它们的空闲云计算能力。这些服务比专有的、按需服务便宜,缺点是不能保证随时有可用的云资源提供服务。在 GCP 上,如果客户长时间(每月的 25% 至 100%)使用服务,可以获取更多折扣。在 AWS 上预付费或者一次购买大批量服务可以节省不少费用。底线是,如果你是一个超级用户,并且使用云计算已经成为一种常态,那么最好深入研究云计算,自己算计好成本。
最后,新手在 GCP 上体验云服务的费用较低。新手只需 300 美元信用担保,就可以免费试用 60 天 GCP 提供的全部云服务。AWS 只免费提供特定服务的特定试用层级,如果运行 Spark 任务,需要付费。这意味着初次体验 SparkGCP 具有更多选择,也少了精打细算和讨价还价的烦恼。
### 性能比拼
我们通过实验检测一个典型 Spark 工作负载的性能与开销。实验分别选择 AWS 的 m3.xlarg 和 GCP 的 n1-standard-4它们都是由一个 Master 和 5 个核心实例组成的集群。除了规格略有差别,虚拟核心和费用都相同。实际上它们在 Spark 任务的执行时间上也表现的惊人相似。
测试 Spark 任务包括对数据的解析、过滤、合并和聚合,这些数据来自公开的[堆栈交换数据转储Stack Exchange Data Dump][9]。通过运行相同的 JAR我们首先对大约 50M 的数据子集进行[交叉验证][10],然后将验证扩大到大约 9.5G 的数据集。
![](https://d3ansictanv2wj.cloudfront.net/1400_img_1_AWS_GCP-25ed6069029112a8439d89999796be18.jpg)
>Figure 1. Credit: Michael Li and Ariel M'ndange-Pfupfu.
![](https://d3ansictanv2wj.cloudfront.net/1400_img_2_AWS_GCP-448714718896b21e32f8b47d4657fc8c.jpg)
>Figure 2. Credit: Michael Li and Ariel M'ndange-Pfupfu.
结果表明,短任务在 GCP 上具有明显的成本优势,这是因为 GCP 以分钟计费,并最终扣除了 10 分钟的费用,而 AWS 则收取了 1 小时的费用。但是即使长任务因为计费方式占优GPS 仍然具有相当优势。同样值得注意的是存储成本并不包括在此次比较当中。
###结论
AWS 是云计算的先驱,这甚至体现在 API 中。AWS 拥有巨大的生态系统但其许可模型已略显陈旧配置管理也有些晦涩难解。相比之下Google 是云计算领域的新星并且将云计算服务打造得更加圆润自如。但是 GCP 缺少一些便捷的功能,比如通过简单方法自动结束集群和详细的任务计费信息分解。另外,其 Python 编程接口也不像 [AWS 的 Boto][11] 那么全面。
如果你初次使用云计算GCP 因其简单易用,别具魅力。即使你已在使用 AWS你也许会发现迁移到 GCP 可能更划算,尽管真正从 AWS 迁移到 GCP 的代价可能得不偿失。
当然现在对两种云服务作一个全面的总结还非常困难因为它们都不是单一的实体而是由多个实体整合而成的完整生态系统并且各有利弊。真正的赢家是用户。一个例证就是在数据孵化器The Data Incubator我们的博士数据科学研究员在学习分布式负载的过程中真正体会到成本的下降。虽然我们的[大数据企业培训客户][12]可能对价格不那么敏感,他们更在意能够更快速地处理企业数据,同时保持价格不增加。数据科学家现在可以享受大量的可选服务,这些都是从竞争激烈的云计算市场得到的实惠。
--------------------------------------------------------------------------------
via: https://www.oreilly.com/ideas/spark-comparison-aws-vs-gcp
作者:[Michael Li][a][Ariel M'Ndange-Pfupfu][b]
译者:[firstadream](https://github.com/firstadream)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.oreilly.com/people/76a5b-michael-li
[b]: https://www.oreilly.com/people/Ariel-Mndange-Pfupfu
[1]: https://aws.amazon.com/
[2]: https://cloud.google.com/
[3]: https://www.thedataincubator.com/training.html?utm_source=OReilly&utm_medium=blog&utm_campaign=AWSvsGCP
[4]: http://www.oreilly.com/live-training/distributed-computing-with-spark.html?intcmp=il-data-olreg-lp-oltrain_20160828_new_site_spark_comparison_aws_gcp_post_top_note_training_link
[5]: http://spark.apache.org/
[6]: http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html
[7]: http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/EMR_SetUp_KeyPair.html
[8]: https://cloud.google.com/sdk/#Quick_Start
[9]: https://archive.org/details/stackexchange
[10]: http://stats.stackexchange.com/
[11]: https://github.com/boto/boto3
[12]: https://www.thedataincubator.com/training.html?utm_source=OReilly&utm_medium=blog&utm_campaign=AWSvsGCP

View File

@ -0,0 +1,333 @@
17 个 tar 命令实用示例
=====
TarTape ARchive磁带归档的缩写LCTT 译注:最初设计用于将文件打包到磁带上,现在我们大都使用它来实现备份某个分区或者某些重要的目录)是类 Unix 系统中使用最广泛的命令,用于归档多个文件或目录到单个归档文件中,并且归档文件可以进一步使用 gzip 或者 bzip2 等技术进行压缩。换言之tar 命令也可以用于备份:先是归档多个文件和目录到一个单独的 tar 文件或归档文件,然后在需要之时将 tar 文件中的文件和目录释放出来。
本文将介绍 tar 的 17 个实用示例。
tar 命令语法如下:
```
# tar <选项> <文件>
```
下面列举 tar 命令中一些常用的选项:
> --delete : 从归档文件 (而非磁带) 中删除
> -r, --append : 将文件追加到归档文件中
> -t, --list : 列出归档文件中包含的内容
> --test-label : 测试归档文件卷标并退出
> -u, --update : 将已更新的文件追加到归档文件中
> -x, --extract, --get : 释放归档文件中文件及目录
> -C, --directory=DIR : 执行归档动作前变更工作目录到 DIR
> -f, --file=ARCHIVE : 指定 (将要创建或已存在的) 归档文件名
> -j, --bip2 : 对归档文件使用 bzip2 压缩
> -J, --xz : 对归档文件使用 xz 压缩
> -p, --preserve-permissions : 保留原文件的访问权限
> -v, --verbose : 显示命令整个执行过程
> -z, gzip : 对归档文件使用 gzip 压缩
注 : 在 tar 命令选项中的连接符 `-` 是可选的LCTT 译注:不用 `-` 也没事。这在 GNU 软件里面很罕见,大概是由于 tar 命令更多受到古老的 UNIX 风格影响)。
### 示例 1创建一个 tar 归档文件
现在来创建一个 tar 文件,将 /etc/ 目录和 /root/anaconda-ks.cfg 文件打包进去。
```
[root@linuxtechi ~]# tar -cvf myarchive.tar /etc /root/anaconda-ks.cfg
```
以上命令会在当前目录创建一个名为 "myarchive" 的 tar 文件,内含 /etc/ 目录和 /root/anaconda-ks.cfg 文件。
其中,`-c` 选项表示要创建 tar 文件,`-v` 选项用于输出 tar 的详细过程到屏幕上,`-f` 选项则是指定归档文件名称。
```
[root@linuxtechi ~]# ls -l myarchive.tar
-rw-r--r--. 1 root root 22947840 Sep 7 00:24 myarchive.tar
[root@linuxtechi ~]#
```
### 示例 2列出归档文件中的内容
在 tar 命令中使用 `t` 选项可以不用释放其中的文件就可以快速列出文件中包含的内容。
```
[root@linuxtechi ~]# tar -tvf myarchive.tar
```
列出 tar 文件中的指定的文件和目录。下列命令尝试查看 anaconda-ks.cfg 文件是否存在于 tar 文件中。
```
[root@linuxtechi ~]# tar -tvf myarchive.tar root/anaconda-ks.cfg
-rw------- root/root 953 2016-08-24 01:33 root/anaconda-ks.cfg
[root@linuxtechi ~]#
```
### 示例 3追加文件到归档tar文件中
`-r` 选项用于向已有的 tar 文件中追加文件。下面来将 /etc/fstab 添加到 data.tar 中。
```
[root@linuxtechi ~]# tar -rvf data.tar /etc/fstab
```
注:在压缩过的 tar 文件中无法进行追加文件操作。
### 示例 4从 tar 文件中释放文件以及目录
`-x` 选项用于释放出 tar 文件中的文件和目录。下面来释放上边创建的 tar 文件中的内容。
```
[root@linuxtechi ~]# tar -xvf myarchive.tar
```
这个命令会在当前目录中释放出 myarchive.tar 文件中的内容。
### 示例 5释放 tar 文件到指定目录
假如你想要释放 tar 文件中的内容到指定的文件夹或者目录,使用 `-C` 选项后边加上指定的文件的路径。
```
[root@linuxtechi ~]# tar -xvf myarchive.tar -C /tmp/
```
### 示例 6释放 tar 文件中的指定文件或目录
假设你只要释放 tar 文件中的 anaconda-ks.cfg 到 /tmp 目录。
语法如下:
```
# tar xvf {tar-file } {file-to-be-extracted } -C {path-where-to-extract}
[root@linuxtechi tmp]# tar -xvf /root/myarchive.tar root/anaconda-ks.cfg -C /tmp/
root/anaconda-ks.cfg
[root@linuxtechi tmp]# ls -l /tmp/root/anaconda-ks.cfg
-rw-------. 1 root root 953 Aug 24 01:33 /tmp/root/anaconda-ks.cfg
[root@linuxtechi tmp]#
```
### 示例 7创建并压缩归档文件.tar.gz 或 .tgz
假设我们需要打包 /etc 和 /opt 文件夹,并用 gzip 工具将其压缩。可以在 tar 命令中使用 `-z` 选项来实现。这种 tar 文件的扩展名可以是 .tar.gz 或者 .tgz。
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tar.gz /etc/ /opt/
```
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tgz /etc/ /opt/
```
### 示例 8创建并压缩归档文件.tar.bz2 或 .tbz2
假设我们需要打包 /etc 和 /opt 文件夹,并使用 bzip2 压缩。可以在 tar 命令中使用 `-j` 选项来实现。这种 tar 文件的扩展名可以是 .tar.bz2 或者 .tbz。
```
[root@linuxtechi ~]# tar -jcpvf myarchive.tar.bz2 /etc/ /opt/
```
```
[root@linuxtechi ~]# tar -jcpvf myarchive.tbz2 /etc/ /opt/
```
### 示例 9排除指定文件或类型后创建 tar 文件
创建 tar 文件时在 tar 命令中使用 `exclude` 选项来排除指定文件或者类型。假设在创建压缩的 tar 文件时要排除 .html 文件。
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tgz /etc/ /opt/ --exclude=*.html
```
### 示例 10列出 .tar.gz 或 .tgz 文件中的内容
使用 `-t` 选项可以查看 .tar.gz 或 .tgz 文件中内容。如下:
```
[root@linuxtechi ~]# tar -tvf myarchive.tgz | more
.............................................
drwxr-xr-x root/root 0 2016-09-07 08:41 etc/
-rw-r--r-- root/root 541 2016-08-24 01:23 etc/fstab
-rw------- root/root 0 2016-08-24 01:23 etc/crypttab
lrwxrwxrwx root/root 0 2016-08-24 01:23 etc/mtab -> /proc/self/mounts
-rw-r--r-- root/root 149 2016-09-07 08:41 etc/resolv.conf
drwxr-xr-x root/root 0 2016-09-06 03:55 etc/pki/
drwxr-xr-x root/root 0 2016-09-06 03:15 etc/pki/rpm-gpg/
-rw-r--r-- root/root 1690 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
-rw-r--r-- root/root 1004 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-7
-rw-r--r-- root/root 1690 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Testing-7
-rw-r--r-- root/root 3140 2015-09-15 06:53 etc/pki/rpm-gpg/RPM-GPG-KEY-foreman
..........................................................
```
### 示例 11列出 .tar.bz2 或 .tbz2 文件中的内容
使用 `-t` 选项可以查看 .tar.bz2 或 .tbz2 文件中内容。如下:
```
[root@linuxtechi ~]# tar -tvf myarchive.tbz2 | more
........................................................
rwxr-xr-x root/root 0 2016-08-24 01:25 etc/pki/java/
lrwxrwxrwx root/root 0 2016-08-24 01:25 etc/pki/java/cacerts -> /etc/pki/ca-trust/extracted/java/cacerts
drwxr-xr-x root/root 0 2016-09-06 02:54 etc/pki/nssdb/
-rw-r--r-- root/root 65536 2010-01-12 15:09 etc/pki/nssdb/cert8.db
-rw-r--r-- root/root 9216 2016-09-06 02:54 etc/pki/nssdb/cert9.db
-rw-r--r-- root/root 16384 2010-01-12 16:21 etc/pki/nssdb/key3.db
-rw-r--r-- root/root 11264 2016-09-06 02:54 etc/pki/nssdb/key4.db
-rw-r--r-- root/root 451 2015-10-21 09:42 etc/pki/nssdb/pkcs11.txt
-rw-r--r-- root/root 16384 2010-01-12 15:45 etc/pki/nssdb/secmod.db
drwxr-xr-x root/root 0 2016-08-24 01:26 etc/pki/CA/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/certs/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/crl/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/newcerts/
drwx------ root/root 0 2015-06-29 08:48 etc/pki/CA/private/
drwx------ root/root 0 2015-11-20 06:34 etc/pki/rsyslog/
drwxr-xr-x root/root 0 2016-09-06 03:44 etc/pki/pulp/
..............................................................
```
### 示例 12解压 .tar.gz 或 .tgz 文件
使用 `-x``-z` 选项来解压 .tar.gz 或 .tgz 文件。如下:
```
[root@linuxtechi ~]# tar -zxpvf myarchive.tgz -C /tmp/
```
以上命令将 tar 文件解压到 /tmp 目录。
注:现今的 tar 命令会在执行解压动作前自动检查文件的压缩类型,这意味着我们在使用 tar 命令是可以不用指定文件的压缩类型。如下:
```
[root@linuxtechi ~]# tar -xpvf myarchive.tgz -C /tmp/
```
### 示例 13解压 .tar.bz2 或 .tbz2 文件
使用 `-j``-x` 选项来解压 .tar.bz2 或 .tbz2 文件。如下:
```
[root@linuxtechi ~]# tar -jxpvf myarchive.tbz2 -C /tmp/
```
```
[root@linuxtechi ~]# tar xpvf myarchive.tbz2 -C /tmp/
```
### 示例 14使用 tar 命令进行定时备份
总有一些实时场景需要我们对指定的文件和目录进行打包,已达到日常备份的目的。假设需要每天备份整个 /opt 目录,可以创建一个带 tar 命令的 cron 任务来完成。如下:
```
[root@linuxtechi ~]# tar -zcvf optbackup-$(date +%Y-%m-%d).tgz /opt/
```
为以上命令创建一个 cron 任务即可。
### 示例 15使用 -T 及 -X 创建压缩归档文件
想像这样一个场景:把想要归档和压缩的文件及目录记录到到一个文件,然后把这个文件当做 tar 命令的传入参数来完成归档任务;而有时候则是需要排除上面提到的这个文件里面记录的特定路径后进行归档和压缩。
在 tar 命令中使用 `-T` 选项来指定该输入文件,使用 `-X` 选项来指定包含要排除的文件列表。
假设要归档 /etc、/opt、/home 目录,并排除 /etc/sysconfig/kdump 和 /etc/sysconfig/foreman 文件,可以创建 /root/tar-include 和 /root/tar-exclude 然后分别输入以下内容:
```
[root@linuxtechi ~]# cat /root/tar-include
/etc
/opt
/home
[root@linuxtechi ~]#
[root@linuxtechi ~]# cat /root/tar-exclude
/etc/sysconfig/kdump
/etc/sysconfig/foreman
[root@linuxtechi ~]#
```
运行以下命令来创建一个压缩归档文件。
```
[root@linuxtechi ~]# tar zcpvf mybackup-$(date +%Y-%m-%d).tgz -T /root/tar-include -X /root/tar-exclude
```
### 示例 16查看 .tar、.tgz 和 .tbz2 文件的大小
使用如下命令来查看 (压缩) tar 文件的体积。
```
[root@linuxtechi ~]# tar -czf - data.tar | wc -c
427
[root@linuxtechi ~]# tar -czf - mybackup-2016-09-09.tgz | wc -c
37956009
[root@linuxtechi ~]# tar -czf - myarchive.tbz2 | wc -c
30835317
[root@linuxtechi ~]#
```
### 示例 17分割体积庞大的 tar 文件为多份小文件
类 Unix 系统中使用 split 命令来将大体积文件分割成小体积文件。大体积的 tar 当然也可以使用这个命令来进行分割。
假设需要将 "mybackup-2016-09-09.tgz" 分割成每份 6 MB 的小文件。
```
Syntax : split -b <Size-in-MB> <tar-file-name>.<extension> “prefix-name”
```
```
[root@linuxtechi ~]# split -b 6M mybackup-2016-09-09.tgz mybackup-parts
```
以上命令会在当前目录分割 mybackup-2016-09-09.tgz 文件成为多个 6 MB 的小文件,文件名为 mybackup-partsaa ~ mybackup-partsag。如果在要在分割文件后以数字而非字母来区分可以在以上的 split 命令使用 `-d` 选项。
```
[root@linuxtechi ~]# ls -l mybackup-parts*
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsaa
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsab
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsac
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsad
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsae
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsaf
-rw-r--r--. 1 root root 637219 Sep 10 03:05 mybackup-partsag
[root@linuxtechi ~]#
```
然后通过网络将这些分割文件转移到其他服务器,就可以合并成为一个单独的 tar 文件了,如下:
```
[root@linuxtechi ~]# cat mybackup-partsa* > mybackup-2016-09-09.tgz
[root@linuxtechi ~]#
```
文毕,希望你喜欢 tar 命令的这几个不同的示例。随时评论并分享你的心得。
--------------------------------------------------------------------------------
via: http://www.linuxtechi.com/17-tar-command-examples-in-linux/
作者:[Pradeep Kumar][a]
译者:[GHLandy](https://github.com/GHLandy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.linuxtechi.com/author/pradeep/

View File

@ -0,0 +1,58 @@
5 个值得了解的 Linux 服务器发行版
=========
> 你在 Distrowatch.com 上看到列出的将近 300 个 Linux 发行版本中,几乎任何一个发行版都可以被用来作为服务器系统。下面是一些相对于其他发行版而言比较突出的一些发行版。
![](http://windowsitpro.com/site-files/windowsitpro.com/files/imagecache/large_img/uploads/2016/09/cloudservers.jpg)
你在 Distrowatch.com 上看到列出的将近 300 个 Linux 发行版本中,几乎任何一个发行版都可以被用来作为服务器系统,在 Linux 发展的早期,给用户提供的一直是“全能”发行版,例如 Slackware、Debian 和 Gentoo 可以为家庭和企业作为服务器完成繁重的工作。那或许对业余爱好者是不错的,但是它对于专业人员来说也有好多不必要的地方。
首先,这里有一些发行版可以作为文件和应用服务器,给工作站提供常见外围设备的共享,提供网页服务和其它我们希望服务器做的任何工作,不管是在云端、在数据中心或者在服务器机架上,除此之外没有别的用途。
下面是 5 个最常用的 Linux 发行版的简单总结,而且每一个发行版都可以满足小型企业的需求。
### Red Hat Enterprise LinuxRHEL
这或许是最有名的 Linux 服务器发行版了。RHEL 以它在高要求的至关重要的任务上坚如磐石的稳定性而出名,例如运行着纽约证券交易系统。红帽也提供了业内最佳的服务支持。
那么红帽 Linux 的缺点都有什么呢? 尽管红帽以提供首屈一指的客户服务和支持而出名,但是它的支持订阅费用并不便宜。有人可能会指出,这的确物有所值。确实有便宜的 RHEL 第三方服务,但是你或许应该在这么做之前做一些研究。
### CentOS
任何喜欢 RHEL但是又不想给红帽付费来获得支持的人都应该了解一下 CentOS它基本上是红帽企业版 Linux 的一个分支。尽管这个项目 2004 年左右才开始,但它在 2014 年得到了红帽的官方支持,而它现在雇佣可这个项目的大多数开发者,这意味着安全补丁和漏洞修复提交到红帽不久后就会在 CentOS 上可用。
如果你想要部署 CentOS你将需要有 Linux 技能的员工,因为没有了技术支持,你基本上只能靠自己。有一个好消息是 CentOS 社区提供了十分丰富的资源例如邮件列表、Web 论坛和聊天室,所以对那些寻找帮助的人来说,社区帮助还是有的。
### Ubuntu Server
当许多年前 Canonical 宣布它将要推出一个服务器版本的 Ubuntu 的时候你可能会听到过嘲笑者的声音。然而嘲笑很快变成了惊奇Ubuntu Server 迅速地站稳了脚跟。部分原因是因为其来自 Debian 派生的基因Debian 长久以来就是一个备受喜爱的 Linux 服务器发行版Ubuntu 通过提供一般人可以支付的起的技术支持费用、优秀的硬件支持、开发工具和很多亮点填补了这个市场空隙。
那么 Ubuntu Server 有多么受欢迎呢?最近的数据表明它正在成为在 OpenStack 和 Amazon Elastic Compute Cloud 上[部署最多的操作系统][1]。在那里 Ubuntu Server 超过了位居第二的 Amazon Linux 的 Amazon Machine Image 一大截,而且让第三位 Windows 处于尘封的地位。另外一个调查显示 Ubuntu Server 是[使用最多的 Linux web 服务器][2]。
### SUSE Linux Enterprise ServerSLES
这个源自德国的发行版在欧洲有很大的用户群,而且在本世纪初由 Novell 公司引起的 PR 问题出现之前它一直都是大西洋这边的排名第一服务器发行版。在那段漫长的时期之后SUSE 在美国获得了发展,而且它的使用或许加速了惠普企业公司将它作为[ Linux 首选合作伙伴][3]。
SLES 稳定而且易于维护,这正是很久以来对于一个好的 Linux 发行版所期待的东西。付费的 7*24 小时快速响应技术支持可以供你选择,使得这发行版很适合关键任务的部署。
### ClearOS
基于 RHEL之所以这里要包括 [ClearOS][4] 是因为它对于每个人来说都足够简单,甚至是没有专业知识的人都可以去配置它。它定位于服务中小型企业,它也可以被家庭用户用来作为娱乐服务器,为了简单易用我们可以基于 Web 界面进行管理,它是以“构建你的 IT 基础设施应该像在智能手机上下载 app 一样简单”为前提来定制的。
最新的 7.2 发行版本,包括了一些可能并不“轻量级”的功能,例如对微软 Hyper-V 技术的 VM 支持,支持 XFS 和 BTRFS 文件系统,也支持 LVM 和 IPv6。这些新特性在免费版本或者在并不算贵的带着各种支持选项的专业版中都是可用的。
--------------------------------------------------------------------------------
via: http://windowsitpro.com/industry/five-linux-server-distros-worth-checking-out
作者:[Christine Hall][a]
译者:[LinuxBars](https://github.com/LinuxBars)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://windowsitpro.com/industry/five-linux-server-distros-worth-checking-out
[1]: http://www.zdnet.com/article/ubuntu-linux-continues-to-dominate-openstack-and-other-clouds/
[2]: https://w3techs.com/technologies/details/os-linux/all/all
[3]: http://windowsitpro.com/industry/suse-now-hpes-preferred-partner-micro-focus-pact
[4]: https://www.clearos.com/

View File

@ -0,0 +1,58 @@
在 WordPress 下如何通过 Markdown 来提高工作效率
=================
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/09/markdown-wordpress-featured-2.jpg)
Markdown 是一种简单的标记语言,旨在帮助你花费更小的代价来格式化纯文本文档。在 WordPress 下你可以使用 HTML 或者可视化编辑器来格式化你的文档,但是使用 markdown 可以让格式化文档变得更加容易而且你随时可以导出成很多种格式包括但不限于HTML。
WordPress 没有原生的 markdown 的支持,但是,如果你希望的话,在你的网站上有多种插件可以添加这种功能。
在这个教程中,我将会演示如何使用流行的 WP-Markdown 插件为 WordPress 网站添加 markdown 支持。
### 安装
导航到 “Plugins -> Add New”然后在提供的搜索框中输入 “[wp-markdown][1]” 就可以直接安装。插件应该会出现在列表中的第一个。单击 “Install Now” 进行安装。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/markdown-wordpress-install-plugin-1.png)
### 配置
当你已经安装了这个插件并且激活它之后,导航到 “Settings -> Writing” 并向下滚动,直到 markdown 选项。
你可以启用文章、页面和评论中对于 markdown 的支持。如果你刚刚开始学习 markdown 语法的话,那么你也可以在文章编辑器或者评论的地方启用一个帮助栏,这可以使你更方便一些。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/09/markdown-wordpress-configuration.png)
如果在你的博客文章中包括代码片段的话,那么启用 “Prettify syntax highlighter” 将会让你的代码片段自动语法高亮。
一旦对于你的选择感觉满意的话,那么就单击 “Save Changes” 来保存你的设置吧。
### 使用 Markdown 来写你的文章
当你在自己网站中启用了 markdown 的支持,你就可以立马开始使用了。
通过 “Posts -> Add New” 创建一篇新的文章。你将会注意到默认的可视化及纯文本编辑器已经被 markdown 编辑器所替代。
如果你在配置选项中没有启用 markdown 的帮助栏,你将不会看到 markdown 格式化后的实时预览。然而,只要你的语法是正确的,当你保存或者发布文章的时候,你的 markdown 就会转换成正确的 HTML。
然而,如果你是 markdown 的初学者的话,实时预览这一特征对你会很重要,只需要简单的回到刚才的设置中启用帮助栏选项,你就可以在你的文章底部看到一块漂亮的实时预览区域。另外,你也可以在顶部看到很多按钮,它们将帮助你在文章中快速的插入 markdown 格式。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/markdown-wordpress-create-post.png)
### 结语
正如你所看到的那样,在 WordPress 网站上添加 markdown 支持确实容易,你将只需要花费几分钟的时间就可以了。如果对于 markdown 你全然不知的话,或许你也可以查看我们的 [markdown 备忘录][2],它将对于 markdown 语法提供一个全面的参考。
--------------------------------------------------------------------------------
via: https://www.maketecheasier.com/use-markdown-in-wordpress/
作者:[Ayo Isaiah][a]
译者:[yangmingming](https://github.com/yangmingming)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.maketecheasier.com/author/ayoisaiah/
[1]: https://wordpress.org/plugins/wp-markdown/
[2]: https://www.maketecheasier.com/productive-with-markdown-cheatsheet/

View File

@ -0,0 +1,54 @@
TaskwarriorLinux 下一个很棒的命令行 TODO 工具
==============
Taskwarrior 是 Ubuntu/Linux 下一个简单而直接的基于命令行的 TODO 工具。这个开源软件是我曾用过的最简单的[基于命令行的工具][4]之一。Taskwarrior 可以帮助你更好地组织你自己,而不用安装笨重的新工具——这有时丧失了 TODO 工具的目的。
![](https://2.bp.blogspot.com/-pQnRlOUNIxk/V9cuc3ytsBI/AAAAAAAAKHs/yYxyiAk4PwMIE0HTxlrm6arWOAPcBRRywCLcB/s1600/taskwarrior-todo-app.png)
### Taskwarrior一个基于简单的基于命令行帮助完成任务的TODO工具
Taskwarrior是一个开源、跨平台、基于命令行的 TODO 工具,它帮你在终端中管理你的 to-do 列表。这个工具让你可以轻松地添加任务、展示列表、移除任务。而且,在你的默认仓库中就有,不用安装新的 PPA。在 Ubuntu 16.04 LTS 或者相似的发行版中。在终端中按照如下步骤安装 Taskwarrior。
```
sudo apt-get install task
```
简单的用如下:
```
$ task add Read a book
Created task 1.
$ task add priority:H Pay the bills
Created task 2.
```
我使用上面截图中的同样一个例子。是的你可以设置优先级H、L 或者 M。并且你可以使用task或者task next命令来查看你最新创建的 to-do 列表。比如:
```
$ task next
ID Age P Description Urg
-- --- - -------------------------------- ----
2 10s H Pay the bills 6
1 20s Read a book 0
```
完成之后,你可以使用 task 1 done 或者 task 2 done 来清除列表。[可以在这里][1]找到更加全面的命令和使用案例。同样Taskwarrior 是跨平台的,这意味着不管怎样,你都可以找到一个[满足你需求][2]的版本。如果你需要的话,这里甚至有[一个安卓版][3]。祝您用得开心!
--------------------------------------------------------------------------------
via: http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html
作者:[Manuel Jose][a]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+techdrivein+%28Tech+Drive-in%29
[1]: https://taskwarrior.org/docs/
[2]: https://taskwarrior.org/download/
[3]: https://taskwarrior.org/news/news.20160225.html
[4]: http://www.techdrivein.com/search/label/Terminal

View File

@ -1,93 +1,77 @@
如何用四个简单的步骤加速 LibreOffice
====
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-featured-2.jpg)
对于许多许多开源软件的粉丝和支持者来说LibreOffice 是 Microsoft Office 最好的替代品,在过去的一些发行版中可以看到它明显有了巨大的改进。然而,开始启动依然有许多经验需要掌握。有一些方法可以缩短 LibreOffice 的启动时间并改善它的所有性能。
对于许多许多开源软件的粉丝和支持者来说LibreOffice 是 Microsoft Office 最好的替代品,在最近的一些发布版本中可以看到它明显有了巨大的改进。然而,初始启动的体验仍然距离期望有所距离。有一些方法可以缩短 LibreOffice 的启动时间并改善它的整体性能。
在下面的段落里,我将会展示一些实用性的步骤,你可以通过它们来改善 LibreOffice 的加载时间和响应能力。
### 1. 增加每个对象和图像缓存的存储空间
### 1. 增加每个对象和图像缓存的内存占用
这将可以通过分配更多的内存资源给图像缓存和对象来加快程序的加载时间。
1. 启动 LibreOffice Writer (或者 Calc)
2. 点击菜单栏上的 “工具 -> 选择” 或者按键盘上的快捷键“Alt + F12.”
3. 点击 LibreOffice 下面的“内存”然后增加“LibreOffice使用”到128MB
4. 同样的增加“每个对象的内存”到20MB。
1. 启动 LibreOffice Writer (或者 Calc)。
2. 点击菜单栏上的 “工具 -> 选项” 或者按键盘上的快捷键“Alt + F12”。
3. 点击 LibreOffice 下面的“内存”然后增加“用于 LibreOffice” 到 128MB。
4. 同样的增加“每个对象的内存占用”到 20MB。
5. 点击确定来保存你的修改。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-step-1.png)
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-step-1.png)
注意:你可以根据自己机器的性能把数值设置得比建议值的高一些或低一些。最好通过亲自体验来看看什么值能够让机器达到最佳性能。
### 2.启用 LibreOffice 的快速启动
### 2.启用 LibreOffice 的快速启动QuickStarter
如果你的机器上有足够大的 RAM随机存取存储器,比如 4GB 或者更大,你可以启用“系统托盘快速启动”,从而让内存中的部分 LibreOffice 在打开新文件时能够快速反应。
如果你的机器上有足够大的内存,比如 4GB 或者更大,你可以启用“系统托盘快速启动”,从而让 LibreOffice 的一部分保持在内存中,在打开新文件时能够快速反应。
在启用这个选择以后,你会清楚的看到在打开新文件时它的性能有了很大的提高。
1.通过点击“工具 -> 选择”来打开选择对话框
2. 在 “LibreOffice” 下面的侧边栏选择“内存。”
3. 勾选“系统托盘快速启动”复选框。
1. 通过点击“工具 -> 选项”来打开选项对话框。
2. 在 “LibreOffice” 下面的侧边栏选择“内存”。
3. 勾选“启用系统托盘快速启动器”复选框。
4. 点击“确定”来保存修改。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-2.png)
一旦这个选项启用以后,你将会在你的系统托盘看到 LibreOffice 图标,以及可以打开任何类型的文件的选项。
一旦这个选项启用以后,你将会在你的系统托盘看到 LibreOffice 图标,可以选择来打开任何类型的文件。
### 3. 禁用 Java 运行环境
### 3. 关闭 Java 运行环境
另一个加快 LibreOffice 加载时间和响应能力的简单方法是关闭 Java。
1. 同时按下“Alt + F12”打开选择对话框
2. 在侧边栏里选择“Libreoffice”, 然后选择“高级”。
另一个加快 LibreOffice 加载时间和响应能力的简单方法是禁用 Java。
1. 同时按下“Alt + F12”打开选项对话框。
2. 在侧边栏里选择“Libreoffice”然后选择“高级”。
3. 取消勾选“使用 Java 运行环境”选项。
4. 点击“确定”来关闭对话框。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-3.png)
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-3.png)
如果你只使用 Writer 和 Calc那么关闭 Java 不会影响你正常使用,但如果你需要使用 LibreOffice Base 和一些其他的特性,那么你可能需要重新启用它。在那种情况,将会弹出一个框询问你是否希望再次打开它。
### 4. 减少使用撤销步骤
默认情况下LibreOffice 允许你最多撤销一个文件的 100 个改变。绝大多数用户不需要靠近那儿任何地方(使用撤销操作),所以多次使用撤销步骤是对内存资源的巨大浪费。
默认情况下LibreOffice 允许你撤销一个文件的多达 100 个改变。绝大多数用户不需要这么多,所以在内存中保留这么多撤销步骤是对资源的巨大浪费。
我建议减少撤销步骤到 20 次以下来为其他东西释放内存,但是这部分可以自由选择来满足你的需求。
1. 通过点击 “工具 -> 选择”来打开选择对话框。
我建议减少撤销步骤到 20 次以下来为其他东西释放内存,但是这个部分需要根据你自己的需求来确定。
1. 通过点击 “工具 -> 选项”来打开选项对话框。
2. 在 “LibreOffice” 下面的侧边栏,选择“内存”。
3. 在“撤销”下面把步骤数目改成最适合你的值。
4. 点击“确定”来保存修改。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/speed-up-libreoffice-5.png)
如果你这些技巧为加速你的 LibreOffice 套件的加载时间提供了帮助,请在评论里告诉我们。同样,请分享你知道的任何其他技巧来给其他人带来帮助。
假如你这些技巧为加速你的 LibreOffice 套件的加载时间提供了帮助,请在评论里告诉我们。同样,请分享你知道的任何其他技巧来给其他人带来帮助。
--------------------------------------------------------------------------------
via: https://www.maketecheasier.com/speed-up-libreoffice/?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+maketecheasier
via: https://www.maketecheasier.com/speed-up-libreoffice/
作者:[Ayo Isaiah][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -3,7 +3,7 @@
![](http://tr2.cbsistatic.com/hub/i/2016/09/14/2e91089b-7ebd-4579-bf8f-74c34d1a94ce/e7e9c8dd481d8e068f2934c644788928/openofficedeathhero.jpg)
先说下 OpenOffice。可能你已经无数次地看到说 Apache OpenOffice 即将终止。上一个稳定版本是 4.1.2 (发布于 2015 年 10 月),而最近的一个严重安全漏洞用了一个月才打上补丁。编码人员的缺乏使得开发爬行前进。然后,可能是最糟糕的消息了:这个项目建议用户切换到 [MS Office](https://products.office.com/)(或 [LibreOffice](https://www.libreoffice.org/download/))。
先说下 OpenOffice。可能你已经无数次地看到说 Apache OpenOffice 即将结束。上一个稳定版本是 4.1.2 (发布于 2015 年 10 月),而最近的一个严重安全漏洞用了一个月才打上补丁。编码人员的缺乏使得开发爬行前进一般。然后,可能是最糟糕的消息了:这个项目建议用户切换到 [MS Office](https://products.office.com/)(或 [LibreOffice](https://www.libreoffice.org/download/))。
丧钟为谁而鸣丧钟为你而鸣OpenOffice。
@ -15,15 +15,15 @@ OpenOffice 的终止对开源和用户来说都将是件好事。
### 一个分支统治所有
当 LibreOffice 从 OpenOffice 分支出来后,我们看到了另一个实例分支不只在原始基础上进行改进而且大幅超越了它。LibreOffice 一举成功。所有之前预装 OpenOffice 的 Linux 发行版都迁移到了这个新项目。LibreOffice 从起跑线突然冲出,并迅速迈出了一大步。更新以极快的速度发布,改善内容丰富而重要。
当 LibreOffice 从 OpenOffice 分支出来后,我们看到了另一个情况分支不只在原始基础上进行改进而且大幅超越了它。LibreOffice 一举成功。所有之前预装 OpenOffice 的 Linux 发行版都迁移到了这个新项目。LibreOffice 从起跑线突然冲出,并迅速迈出了一大步。更新以极快的速度发布,改善内容丰富而重要。
不久后OpenOffice 就被开源社区排在了后面。当 2011 年 Oracle 决定终止这个项目并把代码捐赠给 Apache 项目时,这种情况自然更加恶化了。从此 OpenOffice 艰难前进,然后把我们带到了现在这种局面。一个生机勃勃的 LibreOffice 和一个艰难的、缓慢的 OpenOffice。
不久后OpenOffice 就被开源社区丢在了脑后。当 2011 年 Oracle 决定终止这个项目并把代码捐赠给 Apache 项目时,这种情况自然更加恶化了。从此 OpenOffice 艰难前进,然后把我们就看到了现在这种局面:一个生机勃勃的 LibreOffice 和一个艰难的、缓慢的 OpenOffice。
但我认为在这个相当昏暗的隧道末尾有一丝曙光。
### 合并他们
这听起来可能很疯狂,但我认为是时候合并 LibreOffice 和 OpenOffice 了。是的,我知道很可能有政治问题和自尊意识,但我认为合并成一个会更好。合并的好处很多。我一时能想到的是:
这听起来可能很疯狂,但我认为是时候把 LibreOffice 和 OpenOffice 合二为一了。是的,我知道很可能有政治考虑和自尊意识,但我认为合并成一个会更好。合并的好处很多。我首先能想到的是:
- 把 MS Office 过滤器整合起来OpenOffice 在更好地导入某些 MS Office 文件上功能很强(而众所周知 LibreOffice 正在改进,但时好时坏)
- LibreOffice 有更多开发者:尽管 OpenOffice 的开发者数量不多,但也无疑会增加到合并后的项目。
@ -32,21 +32,19 @@ OpenOffice 的终止对开源和用户来说都将是件好事。
### 宝贵机遇
OpenOffice 的终止实际上会成为整个开源办公套件行业的一个宝贵机遇。为什么?我想表明有些东西我认为已经需要很久了。如果 OpenOffice 和 LibreOffice 集中他们的力量,比较他们的代码并合并,他们之后就可以做一些更必要的改工作,不仅是整体的内部工作,也包括界面。
OpenOffice 的终止实际上会成为整个开源办公套件行业的一个宝贵机遇。为什么?我想表明有些东西我认为已经需要很久了。如果 OpenOffice 和 LibreOffice 集中他们的力量,比较他们的代码并合并,他们之后就可以做一些更必要的改工作,不仅是整体的内部工作,也包括界面。
我们得面对现实LibreOffice 和(相关的) OpenOffice 的用户界面都是过时的。当我安装 LibreOffice 5.2.1.2 时,工具栏绝对是个灾难(见图 A
### Figure A
我们得面对现实LibreOffice 和(相关的) OpenOffice 的用户界面都是过时的。当我安装 LibreOffice 5.2.1.2 时,工具栏绝对是个灾难(见下图)。
![](http://tr2.cbsistatic.com/hub/i/2016/09/14/cc5250df-48cd-40e3-a083-34250511ffab/c5ac8eb1e2cb12224690a6a3525999f0/openofficea.jpg)
#### LibreOffice 默认工具栏显示
*LibreOffice 默认工具栏显示*
尽管我支持和关心并且日常使用LibreOffice但事实已经再清楚不过了界面需要完全重写。我们正在使用的是 90 年代末/ 2000 年初的复古界面,它必须得改变了。当新用户第一次打开 LibreOffice 时他们会被淹没在大量按钮、图标和工具栏中。Ubuntu Unity 的平视显示Head up Display简称 HUD帮助解决了这个问题但那并不适用于其它桌面和发行版。当然有经验的用户知道在哪里找什么甚至定制工具栏以满足特殊的需要但对新用户或普通用户那种界面是个噩梦。现在是做出改变的一个好时机。引入 OpenOffice 最后残留的开发者并让他们加入到改善界面的战斗中。借助于整合 OpenOffice 额外的导入过滤器和现代化的界面LibreOffice 终能在家庭和办公桌面上都引起一些轰动。
### 这会真的发生吗?
这需要发生。将会吗?我不知道。但即使掌权者决定用户界面并不需要重组(这会是个失误),合并 OpenOffice 仍是前进的一大步。合并两者将带来开发的更专注,更好的推广,公众更少的困惑。
这需要发生。但是会发生吗?我不知道。但即使掌权者决定用户界面并不需要重组(这会是个失误),合并 OpenOffice 仍是前进的一大步。合并两者将带来开发的更专注,更好的推广,公众更少的困惑。
我知道这可能看起来有悖于开源的核心精神,但合并 LibreOffice 和 OpenOffice 将能联合两者的力量,而且可能会摆脱弱点。
@ -56,9 +54,9 @@ OpenOffice 的终止实际上会成为整个开源办公套件行业的一个宝
via: http://www.techrepublic.com/article/its-time-to-make-libreoffice-and-openoffice-one-again/
作者:[Jack Wallen ][a]
作者:[Jack Wallen][a]
译者:[bianjp](https://github.com/bianjp)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,364 @@
在 Ubuntu 16.04 上安装和使用服务器监控报警系统 Shinken
=====
Shinken 是一个用 Python 实现的开源的主机和网络监控框架,并与 Nagios like 兼容,它可以运行在所有支持 Python 程序的操作系统上,比如说 Linux、Unix 和 WindowsShinken 是 Jean Gabes 为了验证一个新的 Nagios 架构思路而编写,但是这个想法被 Nagios 的作者拒绝后成为了一个独立的网络系统监视软件,并保持了与 Nagios 的兼容。
在这篇教程中,我将会描述如何从源代码编译安装 Shinken 和向监视系统中添加一台 Linux 主机。我将会以 Ubuntu 16.04 Xenial Xerus 操作系统来作为 Shinken 服务器和所监控的主机。
### 第一步 安装 Shinken 服务器
Shinken 是一个 Python 框架,我们可以通过 `pip` 安装或者从源码来安装它,在这一步中,我们将用源代码编译安装 Shinken。
在我们开始安装 Shinken 之前还需要完成几个步骤。
安装一些新的 Python 软件包并创建一个名为 `shinken` 的系统用户:
```
sudo apt-get install python-setuptools python-pip python-pycurl
useradd -m -s /bin/bash shinken
```
从 GitHub 仓库下载 Shinken 源代码:
```
git clone https://github.com/naparuba/shinken.git
cd shinken/
```
然后用以下命令安装 Shinken
```
git checkout 2.4.3
python setup.py install
```
然后,为了得到更好的效果,我们还需要从 Ubuntu 软件库中安装 `python-cherrypy3` 软件包:
```
sudo apt-get install python-cherrypy3
```
到这里Shinken 已经成功安装,接下来我们将 Shinken 添加到系统启动项并且启动它:
```
update-rc.d shinken defaults
systemctl start shinken
```
### 第二步 安装 Shinken Webui2
Webui2 是 Shinken 的 Web 界面(在 shinken.io 可以找到)。最简单的安装 Shinken webui2 的方法是使用shinken CLI 命令(必须作为 `shinken` 用户执行)。
切换到 shinken 用户:
```
su - shinken
```
初始化 shiken 配置文件,下面的命令将会创建一个新的配置文件 `.shinken.ini`
```
shinken --init
```
接下来用 shinken CLI 命令来安装 `webui2`
```
shinken install webui2
```
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/6.png)
至此 webui2 已经安装好,但是我们还需要安装 MongoDB 和用 `pip` 来安装另一个 Python 软件包。在 root 下运行如下命令:
```
sudo apt-get install mongodb
pip install pymongo>=3.0.3 requests arrow bottle==0.12.8
```
接下来,切换到 shinken 目录下并且通过编辑 `broker-master.cfg` 文件来添加这个新的 webui2 模块:
```
cd /etc/shinken/brokers/
vim broker-master.cfg
```
在第 40 行添加一个模块选项:
```
modules webui2
```
保存文件并且退出编辑器。
现在进入 `contacts` 目录下编辑 `admin.cfg` 来进行管理配置。
```
cd /etc/shinken/contacts/
vim admin.cfg
```
按照如下修改:
```
contact_name admin # Username 'admin'
password yourpass # Pass 'mypass'
```
保存和退出。
### 第三步 安装 Nagios 插件和 Shinken 软件包
在这一步中,我们将安装 Nagios 插件和一些 Perl 模块。然后从 shinken.io 安装其他的软件包来实现监视。
安装 Nagios 插件和安装 Perl 模块所需要的 `cpanminus`
```
sudo apt-get install nagios-plugins* cpanminus
```
`cpanm` 命令来安装 Perl 模块。
```
cpanm Net::SNMP
cpanm Time::HiRes
cpanm DBI
```
现在我们创建一个 `utils.pm` 文件的链接到 shinken 的目录,并且为 `Log_File_Health` 创建了一个新的日志目录 。
```
chmod u+s /usr/lib/nagios/plugins/check_icmp
ln -s /usr/lib/nagios/plugins/utils.pm /var/lib/shinken/libexec/
mkdir -p /var/log/rhosts/
touch /var/log/rhosts/remote-hosts.log
```
然后,从 shinken.io 安装 shinken 软件包 `ssh``linux-snmp` 来监视 SSH 和 SNMP
```
su - shinken
shinken install ssh
shinken install linux-snmp
```
### 第四步 添加一个 Linux 主机 host-one
我们将添加一个新的将被监控的 Linux 主机IP 地址为 192.168.1.121,主机名为 host-one 的 Ubuntu 16.04。
连接到 host-one 主机:
```
ssh host1@192.168.1.121
```
从 Ubuntu 软件库中安装 snmp 和snmpd 软件包:
```
sudo apt-get install snmp snmpd
```
然后,用 `vim` 编辑 `snmpd.conf` 配置文件:
```
vim /etc/snmp/snmpd.conf
```
注释掉第 15 行并取消注释第 17 行:
```
#agentAddress udp:127.0.0.1:161
agentAddress udp:161,udp6:[::1]:161
```
注释掉第 51 和 53 行,然后加一行新的配置,如下:
```
#rocommunity mypass default -V systemonly
#rocommunity6 mypass default -V systemonly
rocommunity mypass
```
保存并退出。
现在用 `systemctl` 命令来启动 `snmpd` 服务:
```
systemctl start snmpd
```
在 shinken 服务器上通过在 `hosts` 文件夹下创建新的文件来定义一个新的主机:
```
cd /etc/shinken/hosts/
vim host-one.cfg
```
粘贴如下配置信息:
```
define host{
use generic-host,linux-snmp,ssh
contact_groups admins
host_name host-one
address 192.168.1.121
_SNMPCOMMUNITY mypass # SNMP Pass Config on snmpd.conf
}
```
保存并退出。
在 shinken 服务器上编辑 SNMP 配置文件。
```
vim /etc/shinken/resource.d/snmp.cfg
```
`public` 改为 `mypass` -必须和你在客户端 `snmpd` 配置文件中使用的密码相同:
```
$SNMPCOMMUNITYREAD$=mypass
```
保存并退出。
现在将服务端和客户端都重启:
```
reboot
```
现在 Linux 主机已经被成功地添加到 shinken 服务器中了。
### 第五步 访问 Shinken Webui2
在端口 7677 访问 Shinken webui2 (将 URL 中的 IP 替换成你自己的 IP 地址):
```
http://192.168.1.120:7767
```
用管理员用户和密码登录(你在 admin.cfg 文件中设置的)
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/1.png)
Webui2 中的 Shinken 面板:
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/2.png)
我们的两个服务器正在被 Shinken 监控:
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/3.png)
列出所有被 linux-snmp 监控的服务:
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/4.png)
所有主机和服务的状态信息:
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/5.png)
### 第6步 Shinken 的常见问题
#### NTP 服务器相关的问题
当你得到如下的 NTP 错误提示
```
TimeSync - CRITICAL ( NTP CRITICAL: No response from the NTP server)
TimeSync - CRITICAL ( NTP CRITICAL: Offset unknown )
```
为了解决这个问题,在所有 Linux 主机上安装 ntp。
```
sudo apt-get install ntp ntpdate
```
编辑 ntp 配置文件:
```
vim /etc/ntp.conf
```
注释掉所有 pools 并替换为:
```
#pool 0.ubuntu.pool.ntp.org iburst
#pool 1.ubuntu.pool.ntp.org iburst
#pool 2.ubuntu.pool.ntp.org iburst
#pool 3.ubuntu.pool.ntp.org iburst
pool 0.id.pool.ntp.org
pool 1.asia.pool.ntp.org
pool 0.asia.pool.ntp.org
```
然后,在新的一行添加如下限制规则:
```
# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict 192.168.1.120 #shinken server IP address
restrict ::1
NOTE: 192.168.1.120 is the Shinken server IP address.
```
保存并退出。
启动 ntp 并且检查 Shinken 面板。
```
ntpd
```
#### check_netint.pl Not Found 问题
从 github 仓库下载源代码到 shinken 的库目录下:
```
cd /var/lib/shinken/libexec/
wget https://raw.githubusercontent.com/Sysnove/shinken-plugins/master/check_netint.pl
chmod +x check_netint.pl
chown shinken:shinken check_netint.pl
```
#### 网络占用的问题
这是错误信息:
```
ERROR : Unknown interface eth\d+
```
检查你的网络接口并且编辑 `linux-snmp` 模版。
在我的 Ununtu 服务器,网卡是 “enp0s8”而不是 eth0所以我遇到了这个错误。
`vim` 编辑 `linux-snmp` 模版:
```
vim /etc/shinken/packs/linux-snmp/templates.cfg
```
在第 24 行添加网络接口信息:
```
_NET_IFACES eth\d+|em\d+|enp0s8
```
保存并退出。
--------------------------------------------------------------------------------
via: https://www.howtoforge.com/tutorial/server-monitoring-with-shinken-on-ubuntu-16-04/
作者:[Muhammad Arul][a]
译者:[LinuxBars](https://github.com/LinuxBars)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.howtoforge.com/tutorial/server-monitoring-with-shinken-on-ubuntu-16-04/
Save and exit.

View File

@ -0,0 +1,90 @@
你该选择 openSUSE 的五大理由
===============
[![Reasons why you should use OpenSUSE](https://itsfoss.com/wp-content/uploads/2016/09/why-opensuse-is-best.jpg)](https://itsfoss.com/wp-content/uploads/2016/09/why-opensuse-is-best.jpg)
多数的的桌面 Linux 用户都会选择三种发行版本Debian/Ubuntu、Fedora 或者 Arch Linux。但是今天我将给出你需要使用 openSUSE 的五大理由。
相比其他的 Linux 发行版,我总能在 [openSUSE](https://www.opensuse.org/) 上看到一些令人耳目一新的东西。我说不太好,但它总是如此的闪亮和个性鲜明。这绿色的大蜥蜴是看起来如此的令人惊叹!但这并不是 openSUSE **即便不是最好也是要比其它发行版更好**的原因!
请别误解我。我在各种场合用过许多不同的 Linux 发行版,同时也很敬佩在这些发行版背后默默工作的开发者,是他们让计算变成一件快乐的事情。但是 openSUSE 一直让人感觉,嗯,令人崇敬——你是不是也这样觉得?
### openSUSE 比其他 Linux 发行版要好的五大理由
你是不是认为我在说 openSUSE 是最好的 Linux 发行版?不,我并不是要表达这个意思。其实没有任何一个 Linux 发行版是最好的。它真的可以满足你寻找 “灵魂伴侣” 的需求。
但在这里我准备给大家说说openSUSE 比其他发行版做得要好的五件事。如下:
#### #1 社区规则
openSUSE 是一个典型的社区驱动型项目。我经常看到很多用户在升级后抱怨开发人员改变了他们喜欢的发行版。但在 openSUSE 不是这样openSUSE 是纯社区驱动的项目,并且任何时候都朝着用户所希望的方向发展。
#### #2 系统的健壮性
另外一个是操作系统的集成程度。我可以在同一个 openSUSE 系统上安装所有的[最好的 Linux 桌面环境](https://itsfoss.com/best-linux-desktop-environments/),而在 Ubuntu 上则因为系统的稳定性坚决不允许用户这样做。而这恰好体现了一个系统的健壮程度。因此对于那些喜欢自己动手完成每一件事的用户openSUSE 还是很诱人的。
#### #3 易于安装软件
在 Linux 的世界里有很多非常好用的包管理工具。从 Debian 的 apt-get 到 [Fedora](https://itsfoss.com/fedora-24-review/) 的 DNF它们无不吸引着用户而且在这些发行版成为流行版本的过程中扮演着重要角色。
openSUSE 同样有一个将软件传递到桌面的好方法。[software.opensuse.org](https://software.opensuse.org/421/en) 是一个 Web 界面,你可以用它从仓库中获取安装软件。你所需要做的就是打开这个链接 (当然,是在 openSUSE 系统上),在搜索框中输入你想要的软件,点击“直接安装”即可。就是这么简单,不是吗?
听起来就像是在使用 Google 商店一样,是吗?
#### #4 YAST
毫不夸张的说,[YaST](https://en.opensuse.org/Portal:YaST) (LCTT 译注: YaST 是 openSUSE 和 SUSE Linux 企业版的安装和配置工具) 绝对是世界上有史以来**操作系统**上最好的控制中心。并且毫无疑问地,你可以使用它来操控系统上的一切:网络、软件升级以及所有的基础设置等。无论是 openSUSE 的个人版或是 SUSE Linux 企业版,你都能在 YaST 的强力支撑下,轻松的完成安装。总之,一个工具,方便而无所不能。
#### #5 开箱即用的极致体验
SUSE 的团队是 Linux 内核中最大的贡献者团体之一。他们辛勤的努力也意味着,他们有足够的经验来应付不同的硬件条件。
有着良好的硬件支持,一定会有很棒的开箱即用的体验。
#### #6 他们做了一些搞笑视频
等等,不是说好了是五个理由吗?怎么多了一个!
但因为 [Abhishek](https://itsfoss.com/author/abhishek/) 逼着我加进来,因为他们做的 Linux 的搞笑视频才使 openSUSE 成为了最好的发行版。
开了个玩笑,不过还是看看 [Uptime Funk](https://www.youtube.com/watch?v=zbABy9ul11I),你将会知道[为什么 SUSE 是最酷的 Linux ](https://itsfoss.com/suse-coolest-linux-enterprise/)。
### LEAP 还是 TUMBLEWEED该用哪一个
如果你现在想要使用 openSUSE 了,让我来告诉你,这两个 openSUSE 版本LEAP 和 TUMBLEWEED。哪一个更合适你一点。
![Choice](https://itsfoss.com/wp-content/uploads/2016/09/Untitled-design-2.jpg)
尽管两者都提供了相似的体验和相似的环境,但还是需要你自行决定安装那个版本到你硬盘上。
#### OPENSUSE : LEAP
[openSUSE Leap](https://en.opensuse.org/Portal:Leap) 是一个普通的大众版本,基本上每八个月更新一次。目前最新的版本是 openSUSE 42.1。它所有的软件都是稳定版,给用户提供最顺畅的体验。
对于家庭用户、办公和商业用户,是再合适不过的了。它合适那些想要一个稳定系统,而不必事事亲为,可以让他们安心工作的用户。只要进行正确的设置之后,你就不必担心其他事情,然后专心投入工作就好。同时,我也强烈建议图书馆和学校使用 Leap。
#### OPENSUSE: TUMBLEWEED
[Tumbleweed version of openSUSE](https://en.opensuse.org/Portal:Tumbleweed) 是滚动式更新的版本。它定期更新系统中所使用的软件集的最新版本。对于想要使用最新软件以及想向 openSUSE 做出贡献的开发者和高级用户来说,这个版本绝对值得一试。
需要指出的是Tumbleweed 并不是 Leap 的 beta 和 测试版本 。它是最新锐的 Linux 稳定发行版。
Tumbleweed 给了你最快的更新,但是仅在开发者确定某个包的稳定性之后才行。
### 说说你的想法?
请在下方评论说出你对 openSUSE 的想法。如果你已经在考虑使用 openSUSE你更想用 Leap 和 Tumbleweed 哪一个版本呢?
来,让我们开干!
--------------------------------------------------------------------------------
via: https://itsfoss.com/why-use-opensuse/
作者:[Aquil Roshan][a]
译者:[GHLandy](https://github.com/GHLandy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/aquil/

View File

@ -0,0 +1,140 @@
15 个开源的顶级人工智能工具
=========
人工智能artificial intelligence, AI是科技研究中最热门的方向之一。像 IBM、谷歌、微软、Facebook 和亚马逊等公司都在研发上投入大量的资金、或者收购那些在机器学习、神经网络、自然语言和图像处理等领域取得了进展的初创公司。考虑到人们对此感兴趣的程度,我们将不会惊讶于斯坦福的专家在[人工智能报告][1]中得出的结论:“越来越强大的人工智能应用,可能会对我们的社会和经济产生深远的积极影响,这将出现在从现在到 2030 年的时间段里。”
在最近的一篇[文章][2]中,我们概述了 45 个十分有趣或有前途的人工智能项目。在本文中,我们将聚焦于开源的人工智能工具,详细的了解下最著名的 15 个开源人工智能项目。
![](http://www.datamation.com/imagesvr_ce/5668/00AI.jpg)
*开源人工智能*
以下这些开源人工智能应用都处于人工智能研究的最前沿。
### 1. Caffe
![](http://www.datamation.com/imagesvr_ce/8922/01Caffe.JPG)
它是由[贾扬清][3]在加州大学伯克利分校的读博时创造的,[Caffe][4] 是一个基于表达体系结构和可扩展代码的深度学习框架。使它声名鹊起的是它的速度,这让它受到研究人员和企业用户的欢迎。根据其网站所言,它可以在一天之内只用一个 NVIDIA K40 GPU 处理 6000 万多个图像。它是由伯克利视野和学习中心BVLC管理的并且由 NVIDIA 和亚马逊等公司资助来支持它的发展。
### 2. CNTK
![](http://www.datamation.com/imagesvr_ce/1232/02CNTK.JPG)
它是计算网络工具包Computational Network Toolkit的缩写[CNTK][5] 是一个微软的开源人工智能工具。不论是在单个 CPU、单个 GPU、多个 GPU 或是拥有多个 GPU 的多台机器上它都有优异的表现。微软主要用它做语音识别的研究,但是它在机器翻译、图像识别、图像字幕、文本处理、语言理解和语言建模方面都有着良好的应用。
### 3. Deeplearning4j
![](http://www.datamation.com/imagesvr_ce/2901/03Deeplearning4j.JPG)
[Deeplearning4j][6] 是一个 java 虚拟机JVM的开源深度学习库。它运行在分布式环境并且集成在 Hadoop 和 Apache Spark 中。这使它可以配置深度神经网络,并且它与 Java、Scala 和 其他 JVM 语言兼容。
这个项目是由一个叫做 Skymind 的商业公司管理的,它为这个项目提供支持、培训和一个企业的发行版。
### 4. DMTK
![](http://www.datamation.com/imagesvr_ce/7269/04DMLT.JPG)
[DMTK][7] 是分布式机器学习工具Distributed Machine Learning Toolkit的缩写和 CNTK 一样是微软的开源人工智能工具。作为设计用于大数据的应用程序它的目标是更快的训练人工智能系统。它包括三个主要组件DMTK 框架、LightLDA 主题模型算法和分布式(多义)字嵌入算法。为了证明它的速度,微软声称在一个八集群的机器上,它能够“用 100 万个主题和 1000 万个单词的词汇表(总共 10 万亿参数)训练一个主题模型,在一个文档中收集 1000 亿个符号,”。这一成绩是别的工具无法比拟的。
### 5. H20
![](http://www.datamation.com/imagesvr_ce/2890/05H2O.JPG)
相比起科研,[H2O][8] 更注重将 AI 服务于企业用户,因此 H2O 有着大量的公司客户比如第一资本金融公司、思科、Nielsen Catalina、PayPal 和泛美都是它的用户。它声称任何人都可以利用机器学习和预测分析的力量来解决业务难题。它可以用于预测建模、风险和欺诈分析、保险分析、广告技术、医疗保健和客户情报。
它有两种开源版本:标准版 H2O 和 Sparking Water 版,它被集成在 Apache Spark 中。也有付费的企业用户支持。
### 6. Mahout
![](http://www.datamation.com/imagesvr_ce/1127/06Mahout.JPG)
它是 Apache 基金会项目,[Mahout][9] 是一个开源机器学习框架。根据它的网站所言,它有着三个主要的特性:一个构建可扩展算法的编程环境、像 Spark 和 H2O 一样的预制算法工具和一个叫 Samsara 的矢量数学实验环境。使用 Mahout 的公司有 Adobe、埃森哲咨询公司、Foursquare、英特尔、领英、Twitter、雅虎和其他许多公司。其网站列了出第三方的专业支持。
### 7. MLlib
![](http://www.datamation.com/imagesvr_ce/4038/07MLlib.JPG)
由于其速度Apache Spark 成为一个最流行的大数据处理工具。[MLlib][10] 是 Spark 的可扩展机器学习库。它集成了 Hadoop 并可以与 NumPy 和 R 进行交互操作。它包括了许多机器学习算法如分类、回归、决策树、推荐、集群、主题建模、功能转换、模型评价、ML 管道架构、ML 持久、生存分析、频繁项集和序列模式挖掘、分布式线性代数和统计。
### 8. NuPIC
![](http://www.datamation.com/imagesvr_ce/839/08NuPIC.JPG)
由 [Numenta][11] 公司管理的 [NuPIC][12] 是一个基于分层暂时记忆Hierarchical Temporal Memory, HTM理论的开源人工智能项目。从本质上讲HTM 试图创建一个计算机系统来模仿人类大脑皮层。他们的目标是创造一个 “在许多认知任务上接近或者超越人类认知能力” 的机器。
除了开源许可Numenta 还提供 NuPic 的商业许可协议,并且它还提供技术专利的许可证。
### 9. OpenNN
![](http://www.datamation.com/imagesvr_ce/99/09OpenNN.JPG)
作为一个为开发者和科研人员设计的具有高级理解力的人工智能,[OpenNN][13] 是一个实现神经网络算法的 c++ 编程库。它的关键特性包括深度的架构和快速的性能。其网站上可以查到丰富的文档包括一个解释了神经网络的基本知识的入门教程。OpenNN 的付费支持由一家从事预测分析的西班牙公司 [Artelnics][14] 提供。
### 10. OpenCyc
![](http://www.datamation.com/imagesvr_ce/4168/10OpenCyc.JPG)
由 Cycorp 公司开发的 [OpenCyc][15] 提供了对 Cyc 知识库的访问和常识推理引擎。它拥有超过 239,000 个条目,大约 2,093,000 个三元组和大约 69,000 owl这是一种类似于链接到外部语义库的命名空间。它在富领域模型、语义数据集成、文本理解、特殊领域的专家系统和游戏 AI 中有着良好的应用。该公司还提供另外两个版本的 Cyc一个免费的用于科研但是不开源和一个提供给企业的但是需要付费。
### 11. Oryx 2
![](http://www.datamation.com/imagesvr_ce/9761/11Oryx2.JPG)
构建在 Apache Spark 和 Kafka 之上的 [Oryx 2][16] 是一个专门针对大规模机器学习的应用程序开发框架。它采用一个独特的三层 λ 架构。开发者可以使用 Orys 2 创建新的应用程序,另外它还拥有一些预先构建的应用程序可以用于常见的大数据任务比如协同过滤、分类、回归和聚类。大数据工具供应商 Cloudera 创造了最初的 Oryx 1 项目并且一直积极参与持续发展。
### 12. PredictionIO
![](http://www.datamation.com/imagesvr_ce/7423/12.%20PredictionIO.JPG)
今年的二月Salesforce 收购了 [PredictionIO][17],接着在七月,它将该平台和商标贡献给 Apache 基金会Apache 基金会将其列为孵育计划。所以当 Salesforce 利用 PredictionIO 技术来提升它的机器学习能力时,成效将会同步出现在开源版本中。它可以帮助用户创建带有机器学习功能的预测引擎,这可用于部署能够实时动态查询的 Web 服务。
### 13. SystemML
![](http://www.datamation.com/imagesvr_ce/6886/13SystemML.JPG)
最初由 IBM 开发, [SystemML][18] 现在是一个 Apache 大数据项目。它提供了一个高度可伸缩的平台,可以实现高等数学运算,并且它的算法用 R 或一种类似 python 的语法写成。企业已经在使用它来跟踪汽车维修客户服务、规划机场交通和连接社会媒体数据与银行客户。它可以在 Spark 或 Hadoop 上运行。
### 14. TensorFlow
![](http://www.datamation.com/imagesvr_ce/5742/14TensorFlow.JPG)
[TensorFlow][19] 是一个谷歌的开源人工智能工具。它提供了一个使用数据流图进行数值计算的库。它可以运行在多种不同的有着单或多 CPU 和 GPU 的系统,甚至可以在移动设备上运行。它拥有深厚的灵活性、真正的可移植性、自动微分功能,并且支持 Python 和 c++。它的网站拥有十分详细的教程列表来帮助开发者和研究人员沉浸于使用或扩展他的功能。
### 15. Torch
![](http://www.datamation.com/imagesvr_ce/9018/15Torch.JPG)
[Torch][20] 将自己描述为:“一个优先使用 GPU 的拥有机器学习算法广泛支持的科学计算框架”,它的特点是灵活性和速度。此外,它可以很容易的通过软件包用于机器学习、计算机视觉、信号处理、并行处理、图像、视频、音频和网络等方面。它依赖一个叫做 LuaJIT 的脚本语言,而 LuaJIT 是基于 Lua 的。
--------------------------------------------------------------------------------
via: http://www.datamation.com/open-source/slideshows/15-top-open-source-artificial-intelligence-tools.html
作者:[Cynthia Harvey][a]
译者:[Chao-zhi](https://github.com/Chao-zhi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.datamation.com/author/Cynthia-Harvey-6460.html
[1]: https://ai100.stanford.edu/sites/default/files/ai_100_report_0906fnlc_single.pdf
[2]: http://www.datamation.com/applications/artificial-intelligence-software-45-ai-projects-to-watch-1.html
[3]: http://daggerfs.com/
[4]: http://caffe.berkeleyvision.org/
[5]: https://www.cntk.ai/
[6]: http://deeplearning4j.org/
[7]: http://www.dmtk.io/
[8]: http://www.h2o.ai/
[9]: http://mahout.apache.org/
[10]: https://spark.apache.org/mllib/
[11]: http://numenta.com/
[12]: http://numenta.org/
[13]: http://www.opennn.net/
[14]: https://www.artelnics.com/
[15]: http://www.cyc.com/platform/opencyc/
[16]: http://oryx.io/
[17]: https://prediction.io/
[18]: http://systemml.apache.org/
[19]: https://www.tensorflow.org/
[20]: http://torch.ch/

View File

@ -1,17 +1,19 @@
如何使用 Awk 语言写脚本 - Part 13
awk 系列:如何使用 awk 语言编写脚本
====
从 Awk 系列开始直到第 12 部分,我们都是在命令行或者脚本文件写一些简短的 Awk 命令和程序。
![](http://www.tecmint.com/wp-content/uploads/2016/08/Write-Shell-Scripts-in-Awk.png)
然而 Awk 和 Shell 一样也是一个解释语言。通过从开始到现在的一系列的学习,你现在能写可以执行的 Awk 脚本了
从 awk 系列开始直到[第 12 部分][1],我们都是在命令行或者脚本文件里写一些简短的 awk 命令和程序
和写 shell 脚本差不多Awk 脚本以下面这一行开头:
然而 awk 和 shell 一样也是一个解释型语言。通过从开始到现在的一系列的学习,你现在能写可以执行的 awk 脚本了。
和写 shell 脚本差不多awk 脚本以下面这一行开头:
```
#! /path/to/awk/utility -f
```
例如在我的系统上,Awk 工具安装在 /user/bin/awk 目录,所以我的 Awk 脚本以如下内容作为开头:
例如在我的系统上,awk 工具安装在 /user/bin/awk 目录,所以我的 awk 脚本以如下内容作为开头:
```
#! /usr/bin/awk -f
@ -19,13 +21,11 @@
上面一行的解释如下:
```
#! 称为 Shebang指明使用那个解释器来执行脚本中的命令
/usr/bin/awk –解释器
-f 解释器选项,用来指定读取的程序文件
```
- `#!` ,称为[释伴Shebang][2],指明使用那个解释器来执行脚本中的命令
- `/usr/bin/awk` ,即解释器
- `-f` ,解释器选项,用来指定读取的程序文件
说是这么说,现在从下面的简单例子开始,让我们深入研究一些可执行的 Awk 脚本。使用你最喜欢的编辑器创建一个新文件,像下面这样:
说是这么说,现在从下面的简单例子开始,让我们深入研究一些可执行的 awk 脚本。使用你最喜欢的编辑器创建一个新文件,像下面这样:
```
$ vi script.awk
@ -35,7 +35,7 @@ $ vi script.awk
```
#!/usr/bin/awk -f
BEGIN { printf "%s\n","Writing my first Awk executable script!" }
BEGIN { printf "%s\n","Writing my first awk executable script!" }
```
保存文件后退出,然后执行下面命令,使得脚本可执行:
@ -53,10 +53,10 @@ $ ./script.awk
输出样例:
```
Writing my first Awk executable script!
Writing my first awk executable script!
```
一个严格的程序员一定会问:“注释呢?”。是的,你可以在 Awk 脚本中包含注释。在代码中写注释是一种良好的编程习惯。
一个严格的程序员一定会问:“注释呢?”。是的,你可以在 awk 脚本中包含注释。在代码中写注释是一种良好的编程习惯。
它有利于其它程序员阅读你的代码,理解程序文件或者脚本中每一部分的功能。
@ -64,20 +64,20 @@ Writing my first Awk executable script!
```
#!/usr/bin/awk -f
#This is how to write a comment in Awk
#using the BEGIN special pattern to print a sentence
BEGIN { printf "%s\n","Writing my first Awk executable script!" }
# 这是如何在 awk 中写注释的示例
# 使用特殊模式 BEGIN 来输出一句话
BEGIN { printf "%s\n","Writing my first awk executable script!" }
```
接下来我们看一个读文件的例子。我们想从帐号文件 /etc/passwd 中查找一个叫 aaronkilik 的用户,然后像下面这样打印用户名,用户的 ID用户的 GID (译者注:组 ID)
接下来我们看一个读文件的例子。我们想从帐号文件 /etc/passwd 中查找一个叫 aaronkilik 的用户,然后像下面这样打印用户名、用户的 ID、用户的 GID LCTT译注组 ID
下面是我们脚本文件的内容,文件名为 second.awk。
```
#! /usr/bin/awk -f
#use BEGIN sepecial character to set FS built-in variable
# 使用 BEGIN 指定字符来设定 FS 内置变量
BEGIN { FS=":" }
#search for username: aaronkilik and print account details
# 搜索用户名 aaronkilik 并输出账号细节
/aaronkilik/ { print "Username :",$1,"User ID :",$3,"User GID :",$4 }
```
@ -88,13 +88,13 @@ $ chmod +x second.awk
$ ./second.awk /etc/passwd
```
输出样例
输出样例
```
Username : aaronkilik User ID : 1000 User GID : 1000
```
在下面最后一个例子中,我们将使用 do while 语句来打印数字 0-10
在下面最后一个例子中,我们将使用 `do while` 语句来打印数字 0-10
下面是我们脚本文件的内容,文件名为 do.awk。
@ -138,22 +138,24 @@ $ ./do.awk
### 总结
我们已经到达这个精彩的 Awk 系列的最后,我希望你从整个 13 部分中学到了很多知识,把这些当作你 Awk 编程语言的入门指导。
我们已经到达这个精彩的 awk 系列的最后,我希望你从整个 13 个章节中学到了很多知识,把这些当作你 awk 编程语言的入门指导。
我一开始就提到过,Awk 是一个完整的文本处理语言,所以你可以学习很多 Awk 编程语言的其它方面,例如环境变量,数组,函数(内置的或者用户自定义的),等等。
我一开始就提到过,awk 是一个完整的文本处理语言,所以你可以学习很多 awk 编程语言的其它方面,例如环境变量、数组、函数(内置的或者用户自定义的),等等。
Awk 编程还有其它内容需要学习和掌握,所以在文末我提供了一些重要的在线资源的链接,你可以利用他们拓展你的 Awk 编程技能。但这不是必须的,你也可以阅读一些关于 Awk 的书籍。
awk 编程还有其它内容需要学习和掌握,所以在文末我提供了一些重要的在线资源的链接,你可以利用他们拓展你的 awk 编程技能。但这不是必须的,你也可以阅读一些关于 awk 的书籍。
如果你任何想要分享的想法或者问题,在下面留言。记得保持关注 Tecmint,会有更多的精彩内容。
如果你任何想要分享的想法或者问题,在下面留言。记得保持关注我们,会有更多的精彩内容。
--------------------------------------------------------------------------------
via: http://www.tecmint.com/write-shell-scripts-in-awk-programming/
作者:[Aaron Kili |][a]
作者:[Aaron Kili][a]
译者:[chunyang-wen](https://github.com/chunyang-wen)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.tecmint.com/author/aaronkili/
[1]: https://linux.cn/article-7723-1.html
[2]: https://linux.cn/article-3664-1.html

View File

@ -1,7 +1,7 @@
如何使用 Awk 中的流控制语句 - part12
awk 系列:如何在 awk 中使用流控制语句
====
回顾从 Awk 系列最开始到现在我们所讲的所有关于 Awk 的例子,你会发现不同例子中的所有命令都是顺序执行的,也就是一个接一个的执行。但是在某些场景下,我们可能希望根据一些条件来执行一些文本过滤,这个时候流控制语句就派上用场了。
回顾从 Awk 系列,从最开始到现在我们所讲的所有关于 Awk 的例子,你会发现不同例子中的所有命令都是顺序执行的,也就是一个接一个的执行。但是在某些场景下,我们可能希望根据一些条件来执行一些[文本过滤操作][1],这个时候流控制语句就派上用场了。
![](http://www.tecmint.com/wp-content/uploads/2016/08/Use-Flow-Control-Statements-in-Awk.png)
@ -17,7 +17,7 @@ Awk 包含很多的流控制语句,包括:
- nextfile 语句
- exit 语句
但是在这个系列中我们将详细解释if-elseforwhiledo-while 语句。关于如何使用 next 语句,如果你们记得的话,我们已经在 Awk 系列的第6部分介绍过了。
但是在这个系列中,我们将详细解释:`if-else``for``while``do-while` 语句。关于如何使用 `next` 语句,如果你们记得的话,我们已经在 [Awk 系列的第6部分][2]介绍过了。
### 1. if-else 语句
@ -36,7 +36,7 @@ actions2
当 condition1 满足时,意味着它的值是 true此时会执行 actions1if 语句退出否则译注condition1 为 false执行 actions2。
if 语句可以扩展成如下的 if-else_if-else
if 语句可以扩展成如下的 `if-else_if-else`
```
if (condition1){
@ -52,7 +52,7 @@ actions3
上面例子中,如果 condition1 为 true执行 actions1if 语句退出;否则对 condition2 求值,如果值为 true那么执行 actions2if 语句退出。然而如果 condition2 是 false那么会执行 actions3 退出 if语句。
下面是一个使用 if 语句的例子,我们有一个存储用户和他们年龄列表的文件users.txt。
下面是一个使用 if 语句的例子,我们有一个存储用户和他们年龄列表的文件 users.txt。
我们想要打印用户的名字以及他们的年龄是大于 25 还是小于 25。
@ -85,7 +85,7 @@ $ chmod +x test.sh
$ ./test.sh
```
输出样例
输出样例
```
User Sarah L is more than 25 years old
@ -96,7 +96,7 @@ User Kili Seth is more than 25 years old
### 2. for 语句
如果你想循环执行一些 Awk 命令,那么 for 语句十分合适,它的语法如下:
如果你想循环执行一些 Awk 命令,那么 `for` 语句十分合适,它的语法如下:
这里只是简单的定义一个计数器来控制循环的执行。首先你要初始化那个计数器 counter然后根据某个条件判断是否执行如果该条件为 true 则执行,最后增加计数器。当计数器不满足条件时则终止循环。
@ -106,7 +106,7 @@ actions
}
```
下面的 Awk 命令利用打印数字 0-10 来说明 for 语句是怎么工作的。
下面的 Awk 命令利用打印数字 0-10 来说明 `for` 语句是怎么工作的。
```
$ awk 'BEGIN{ for(counter=0;counter<=10;counter++){ print counter} }'
@ -130,7 +130,7 @@ $ awk 'BEGIN{ for(counter=0;counter<=10;counter++){ print counter} }'
### 3. while 语句
传统的 while 语句语法如下:
传统的 `while` 语句语法如下:
```
while ( condition ) {
@ -138,7 +138,7 @@ actions
}
```
上面的 condition 是 Awk 表达式actions 是当 condition 为 true 时执行的 Awk命令。
上面的 condition 是 Awk 表达式actions 是当 condition 为 true 时执行的 Awk 命令。
下面是仍然用打印数字 0-10 来解释 while 语句的用法:
@ -159,8 +159,7 @@ $ chmod +x test.sh
$ ./test.sh
```
输出样例
Sample Output
输出样例:
```
0
@ -178,7 +177,7 @@ Sample Output
### 4. do-while 语句
这个是上面的 while 语句语法的一个变化,其语法如下:
这个是上面的 `while` 语句语法的一个变化,其语法如下:
```
do {
@ -187,7 +186,7 @@ actions
while (condition)
```
二者的区别是,在 do-while 中Awk 的命令在条件求值前先执行。我们使用 while 语句中同样的例子来解释 do-while 的使用,将 test.sh 脚本中的 Awk 命令做如下更改:
二者的区别是,在 `do-while`Awk 的命令在条件求值前先执行。我们使用 `while` 语句中同样的例子来解释 `do-while` 的使用,将 test.sh 脚本中的 Awk 命令做如下更改:
```
#!/bin/bash
@ -238,10 +237,11 @@ via: http://www.tecmint.com/use-flow-control-statements-with-awk-command/
作者:[Aaron Kili][a]
译者:[chunyang-wen](https://github.com/chunyang-wen)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.tecmint.com/author/aaronkili/
[1]: http://www.tecmint.com/use-linux-awk-command-to-filter-text-string-in-files/
[2]: http://www.tecmint.com/use-next-command-with-awk-in-linux/

View File

@ -1,3 +1,10 @@
Translating by WangYueScream
============================================================================
Should Smartphones Do Away with the Headphone Jack? Here Are Our Thoughts
====

View File

@ -1,3 +1,5 @@
willcoderwang 正在翻译
What the rise of permissive open source licenses means
====

View File

@ -1,236 +0,0 @@
translating by ucasFL
# Scientific Audio Processing, Part II - How to make basic Mathematical Signal Processing in Audio files using Ubuntu with Octave 4.0
In the [previous tutorial](https://www.howtoforge.com/tutorial/how-to-read-and-write-audio-files-with-octave-4-in-ubuntu/), we saw the simple steps to read, write and playback audio files. We even saw how we can synthesize an audio file from a periodic function such as the cosine function. In this tutorial, we will see how we can do additions to signals, multiplying signals (modulation), and applying some basic mathematical functions to see their effect on the original signal.
### Adding Signals
The sum of two signals S1(t) and S2(t) results in a signal R(t) whose value at any instant of time is the sum of the added signal values at that moment. Just like this:
```
R(t) = S1(t) + S2(t)
```
We will recreate the sum of two signals in Octave and see the effect graphically. First, we will generate two signals of different frequencies to see the signal resulting from the sum.
#### Step 1: Creating two signals of different frequencies (ogg files)
```
>> sig1='cos440.ogg'; %creating the audio file @440 Hz
>> sig2='cos880.ogg'; %creating the audio file @880 Hz
>> fs=44100; %generating the parameters values (Period, sampling frequency and angular frequency)
>> t=0:1/fs:0.02;
>> w1=2*pi*440*t;
>> w2=2*pi*880*t;
>> audiowrite(sig1,cos(w1),fs); %writing the function cos(w) on the files created
>> audiowrite(sig2,cos(w2),fs);
```
Here we will plot both signals.
Plot of Signal 1 (440 Hz)
```
>> [y1, fs] = audioread(sig1);
>> plot(y1)
```
[![Plot of signal 1](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsignal1.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsignal1.png)
Plot of Signal 2 (880 Hz)
```
>> [y2, fs] = audioread(sig2);
>> plot(y2)
```
[![Plot of signal 2](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsignal2.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsignal2.png)
#### Step 2: Adding two signals
Now we perform the sum of the two signals created in the previous step.
```
>> sumres=y1+y2;
>> plot(sumres)
```
Plot of Resulting Signal
[![Plot Signal sum.](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotsum.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotsum.png)
The Octaver Effect
In the Octaver, the sound provided by this effect is characteristic because it emulates the note being played by the musician, either in a lower or higher octave (according as it has been programmed), coupled with sound the original note, ie two notes appear identically sounding.
#### Step 3: Adding two real signals (example with two musical tracks)
For this purpose, we will use two tracks of Gregorian Chants (voice sampling).
Avemaria Track
First, will read and plot an Avemaria track:
```
>> [y1,fs]=audioread('avemaria_.ogg');
>> plot(y1)
```
[![Avemaria track](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/avemaria.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/avemaria.png)
Hymnus Track
Now, will read and plot an hymnus track
```
>> [y2,fs]=audioread('hymnus.ogg');
>> plot(y2)
```
[![Hymnus track](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/hymnus.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/hymnus.png)
Avemaria + Hymnus Track
```
>> y='avehymnus.ogg';
>> audiowrite(y, y1+y2, fs);
>> [y, fs]=audioread('avehymnus.ogg');
>> plot(y)
```
[![Avearia + hymnus track](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/avehymnus.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/avehymnus.png)The result, from the point of view of audio, is that both tracks will sound mixed.
### Product of two Signals
To multiply two signals, we have to use an analogous way to the sum. Let´s use the same files created previously.
```
R(t) = S1(t) * S2(t)
```
```
>> sig1='cos440.ogg'; %creating the audio file @440 Hz
>> sig2='cos880.ogg'; %creating the audio file @880 Hz
>> product='prod.ogg'; %creating the audio file for product
>> fs=44100; %generating the parameters values (Period, sampling frequency and angular frequency)
>> t=0:1/fs:0.02;
>> w1=2*pi*440*t;
>> w2=2*pi*880*t;
>> audiowrite(sig1, cos(w1), fs); %writing the function cos(w) on the files created
>> audiowrite(sig2, cos(w2), fs);>> [y1,fs]=audioread(sig1);>> [y2,fs]=audioread(sig2);
>> audiowrite(product, y1.*y2, fs); %performing the product
>> [yprod,fs]=audioread(product);
>> plot(yprod); %plotting the product
```
Note: we have to use the operand '.*' because this product is made, value to value, on the argument files. For more information, please refer to the manual of product operations with matrices of Octave.
#### Plot of Resulting Product Signal
[![Plotted product](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/plotprod.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/plotprod.png)
#### Graphical effect of multiplying two signals with a big fundamental frequency difference (Principles of Modulation)
##### Step 1:
Create an audio frequency signal with a 220Hz frequency.
```
>> fs=44100;
>> t=0:1/fs:0.03;
>> w=2*pi*220*t;
>> y1=cos(w);
>> plot(y1);
```
[![Carrier](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/carrier.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/carrier.png)
##### Step 2:
Create a higher frequency modulating signal of 22000 Hz.
```
>> y2=cos(100*w);
>> plot(y2);
```
[![Modulating](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/modulating.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/modulating.png)
##### Step 3:
Multiplying and plotting the two signals.
```
>> plot(y1.*y2);
```
[![Modulated signal](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/modulated.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/modulated.png)
### Multiplying a signal by a scalar
The effect of multiplying a function by a scalar is equivalent to modify their scope and, in some cases, the sign of the phase. Given a scalar K, the product of a function F(t) by the scalar is defined as:
```
R(t) = K*F(t)
```
```
>> [y,fs]=audioread('cos440.ogg'); %creating the work files
>> res1='coslow.ogg';
>> res2='coshigh.ogg';>> res3='cosinverted.ogg';
>> K1=0.2; %values of the scalars
>> K2=0.5;>> K3=-1;
>> audiowrite(res1, K1*y, fs); %product function-scalar
>> audiowrite(res2, K2*y, fs);
>> audiowrite(res3, K3*y, fs);
```
#### Plot of the Original Signal
```
>> plot(y)
```
[![](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/originalsignal.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/originalsignal.png)
Plot of a Signal reduced in amplitude by 0.2
```
>> plot(res1)
```
[![Cosine low](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/coslow.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/coslow.png)
Plot of a Signal reduced in amplitude by 0.5
```
>> plot(res2)
```
[![Cosine high](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/coshigh.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/coshigh.png)
Plot of a Signal with inverted phase
```
>> plot(res3)
```
[![Cosine inverted](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/cosinverted.png)](https://www.howtoforge.com/images/octave-audio-signal-processing-ubuntu/big/cosinverted.png)
### Conclusion
The basic mathematical operations, such as algebraic sum, product, and product of a function by a scalar are the backbone of more advanced operations among which are, spectrum analysis, modulation in amplitude, angular modulation, etc. In the next tutorial, we will see how to make such operations and their effects on audio signals.
--------------------------------------------------------------------------------
via: https://www.howtoforge.com/tutorial/octave-audio-signal-processing-ubuntu/
作者:[David Duarte][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.howtoforge.com/tutorial/octave-audio-signal-processing-ubuntu/

View File

@ -0,0 +1,139 @@
translating by theArcticOcean.
Part III - How to apply Advanced Mathematical Processing Effects on Audio files with Octave 4.0 on Ubuntu
=====
The third part of our Digital Audio processing tutorial series covers the signal Modulation, we explain how to apply Amplitude Modulation, Tremolo Effect, and Frequency Variation.
### Modulation
#### Amplitude Modulation
As its name implies, this effect varies the amplitude of a sinusoid according to the message to be transmitted. A sine wave is called a carrier because it carries the information. This type of modulation is used in some commercial broadcasting and transmission citizen bands (AM).
#### Why use the Amplitude Modulation?
**Modulation Radiation.**
If the communication channel is a free space, then antennas are required to radiate and receive the signal. It requires an efficient electromagnetic radiation antenna whose dimensions are of the same order of magnitude as the wavelength of the signal being radiated. Many signals, including audio components, have often 100 Hz or less. For these signals, it would be necessary to build antennas about 300 km in length if the signal were to be radiated directly. If signal modulation is used to print the message on a high-frequency carrier, let's say 100 MHz, then the antenna needs to have a length of over a meter (transverse length) only.
**Concentration modulation or multi-channeling.**
If more than one signal uses a single channel, modulation can be used for transferring different signals to different spectral positions allowing the receiver to select the desired signal. Applications that use concentration ("multiplexing") include telemetry data, stereo FM radio and long-distance telephony.
**Modulation to Overcome Limitations on equipment.**
The performance of signal processing devices such as filters and amplifiers, and the ease with which these devices can be constructed, depends on the situation of the signal in the frequency domain and the relationship between the higher frequency and low signal. Modulation can be used to transfer the signal to a position in the frequency domain where design requirements are met easier. The modulation can also be used to convert a "broadband signal" (a signal for which the ratio between the highest and lowest frequency is large) into a sign of "narrow band".
**Audio Effects**
Many audio effects use amplitude modulation due to the striking and ease with which it can handle such signals. We can name a few such as tremolo, chorus, flanger, etc. This utility is where we focus in this tutorial series.
### Tremolo effect
The tremolo effect is one of the simplest applications of amplitude modulation, to achieve this effect, we have to vary (multiply) the audio signal by a periodic signal, either sinusoidal or otherwise.
```
>> tremolo='tremolo.ogg';
>> fs=44100;
>> t=0:1/fs:10;
>> wo=2*pi*440*t;
>> wa=2*pi*1.2*t;
>> audiowrite(tremolo, cos(wa).*cos(wo),fs);
```
[![Tremolo](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/tremolo.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/tremolo.png)
This will generate a sinusoid-shaped signal which effect is like a 'tremolo'.
[![Tremolo Shape](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/tremoloshape.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/tremoloshape.png)
### Tremolo on real Audio Files
Now we will show the tremolo effect in the real world, First, we use a file previously recorded by a male voice saying 'A'. The plot for this signal is the following:
```
>> [y,fs]=audioread('A.ogg');
>> plot(y);
```
[![Vocal](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/avocalmale.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/avocalmale.png)
Now we have to create an enveloping sinusoidal signal with the following parameters:
```
Amplitude = 1
Frequency= 1.5Hz
Phase = 0
```
```
>> t=0:1/fs:4.99999999;
>> t=t(:);
>> w=2*pi*1.5*t;
>> q=cos(w);
>> plot(q);
```
Note: when we create an array of values of the time, by default, this is created in the form of columns, ie, 1x220500 values. To multiply this set of values must transpose it in rows (220500x1). This is the t=t(:) command
[![Sinusodial](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/sinusoidal.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/sinusoidal.png)
We will create a second ogg file which contains the resulting modulated signal:
```
>> tremolo='tremolo.ogg';
>> audiowrite(tremolo, q.*y,fs);
```
[![](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/tremsignal1.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/tremsignal1.png)[![Tremolo Signal](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/tremolsignal1.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/tremolsignal1.png)
### Frequency Variation
We can vary the frequency to obtain quite interesting musical effects such as distortion, sound effects for movies and games among others.
#### Effect of sinusoidal frequency modulation
This is the code where the sinusoidal modulation frequency is shown, according to equation:
```
Y=Ac*Cos(wo*Cos(wo/k))
```
Where:
```
Ac = Amplitude
wo = fundamental frequency
k = scalar divisor
```
```
>> fm='fm.ogg';
>> fs=44100;
>> t=0:1/fs:10;
>> w=2*pi*442*t;
>> audiowrite(fm, cos(cos(w/1500).*w), fs);
>> [y,fs]=audioread('fm.ogg');
>> figure (); plot (y);
```
The plot of the signal is:
[![](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/fmod.png)](https://www.howtoforge.com/images/ubuntu-octave-audio-processing-part-3/big/fmod.png)
You can use almost any type of periodic function as the frequency modulator. For this example, we only used a sine function here. Please feel free to experiment with changing the frequencies of the functions, mixing with other functions or change, even, the type of function.
--------------------------------------------------------------------------------
via: https://www.howtoforge.com/tutorial/ubuntu-octave-audio-processing-part-3/
作者:[David Duarte][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.howtoforge.com/tutorial/ubuntu-octave-audio-processing-part-3/

View File

@ -1,11 +1,16 @@
Translating by wikiios
Building a data science portfolio: Machine learning project
构建一个数据科学投资:机器学习项目
===========================================================
>This is the third in a series of posts on how to build a Data Science Portfolio. If you like this and want to know when the next post in the series is released, you can [subscribe at the bottom of the page][1].
>这是如何构建一个数据科学投资系列文章的第三弹。如果你喜欢本文并且想知道本系列下一篇文章发布的时间,你可以订阅本文底[邮箱][1]。
Data science companies are increasingly looking at portfolios when making hiring decisions. One of the reasons for this is that a portfolio is the best way to judge someones real-world skills. The good news for you is that a portfolio is entirely within your control. If you put some work in, you can make a great portfolio that companies are impressed by.
数据科学公司越来越多地研究投资并同时作出雇佣决定。原因之一就是一个投资是评判某人真实能力最好的方式。对你来说好消息是一个投资是完全在你掌控之中。如果你花些心思在其中,你就可以做出一个令公司印象深刻的投资。
The first step in making a high-quality portfolio is to know what skills to demonstrate. The primary skills that companies want in data scientists, and thus the primary skills they want a portfolio to demonstrate, are:
做出高质量投资的第一步是了解应该展示哪些技能,
- Ability to communicate
- Ability to collaborate with others

View File

@ -1,54 +0,0 @@
What is copyleft?
=============
If you've spent much time in open source projects, you have probably seen the term "copyleft" used. While the term is quite commonly used, many people don't understand it. Software licensing is the subject of at least as much heated debate as text editors or packaging formats. An expert understanding of copyleft would fill many books, but this article can be a starting point on your road to copyleft enlightenment.
## What is copyright?
Before we can understand copyleft, we must first introduce the concept of copyright. Copyleft is not a separate legal framework from copyright; copyleft exists within the rules of copyright. So what is copyright?
The exact definition varies based on jurisdiction, but the essence is this: the author of a work has a limited monopoly on the copying (hence the term "copyright"), performance, etc. of the work. In the United States, the Constitution explicitly tasks Congress for creating copyright laws in order to "promote the Progress of Science and useful Arts."
Unlike in the past, copyright attaches to a work immediately -- no registration is required. By default, all rights are reserved. That means no one can republish, perform, or modify a work without permission from the author. This permission is a "license" and may come with certain conditions attached.
For a more thorough introduction to copyright, Coursera's [Copyright for Educators & Librarians](https://www.coursera.org/learn/copyright-for-education) is an excellent resource.
## What is copyleft?
Bear with me, but there's one more step to take before we discuss what copyleft is. First, let's examine what open source means. All open source licenses, by the[Open Source Inititative's definition](https://opensource.org/osd) must, among other things, allow distribution in source form. Anyone who receives open source software has the right to inspect and modify the code.
Where copyleft licenses differ from so-called "permissive" licenses is that copyleft licenses require these same rights to be included in any derivative works. I prefer to think of the distinction in this way: permissive licenses provide the maximum freedom to the immediate downstream developers (including the ability to use the open source code in a closed source project), whereas copyleft licenses provide the maximum freedom through to the end users.
The GNU Project gives this [simple definition](https://www.gnu.org/philosophy/free-sw.en.html) of copyleft: "the rule that when redistributing the program, you cannot add restrictions to deny other people the central freedoms [of free software]." This can be considered the canonical definition, since the [GNU General Public License](https://www.gnu.org/licenses/gpl.html) (GPL) in its various versions remains the most widely-used copyleft license.
## Copyleft in software
While the GPL family are the most popular copyleft licenses, they are by no means the only ones. The [Mozilla Public License](https://www.mozilla.org/en-US/MPL/) and the [Eclipse Public License](https://www.eclipse.org/legal/epl-v10.html) are also very popular. Many [other copyleft licenses](https://tldrlegal.com/licenses/tags/Copyleft) exist with smaller adoption footprints.
As explained in the previous section, a copyleft license means downstream projects cannot add additional restrictions on the use of the software. This is best illustrated with an example. If I wrote MyCoolProgram and distributed it under a copyleft license, you would have the freedom to use and modify it. You could distribute versions with your changes, but you'd have to give your users the same freedoms I gave you. If I had licensed it under a permissive license, you'd be free to incorporate it into a closed software project that you do not provide the source to.
But just as important as what you must do with MyCoolProgram is what you don't have to do. You don't have to use the exact same license I did, so long as the terms are compatible (generally downstream projects use the same license for simplicity's sake). You don't have to contribute your changes back to me, but it's generally considered good form, especially when the changes are bug fixes.
## Copyleft in non-software
Although the notion of copyleft began in the software world, it exists outside as well. The notion of "do what you want, so long as you preserve the right for others to do the same" is the distinguishing characteristic of the [Creative Commons Attribution-ShareAlike](http://creativecommons.org/licenses/by-sa/4.0/) license used for written work, visual art, etc. (CC BY-SA 4.0 is the default license for contributions to Opensource.com.) The [GNU Free Documentation License ](https://www.gnu.org/licenses/fdl.html)is another example of a copyleft non-software license. The use of software licenses for non-software work is generally discouraged.
## Should I choose a copyleft license?
Pages and pages could be (and have been!) written about what type of license should be used for a project. My advice is to first narrow the list of licenses to ones that match your philosophy and your goals for the project. GitHub's[choosealicense.com](http://choosealicense.com/) is a good way to find a license that fits your needs. [tl;drLegal](https://tldrlegal.com/)has plain-language explanations of many common and uncommon software licenses. Also consider the ecosystem that your project lives in. Projects around a specific language or technology will often use the same or similar licenses. If you want your project to be able to play nicely, you may need to make sure the license you choose is compatible.
For more information about copyleft licensing, check out the [Copyleft Guide](https://copyleft.org/)project.
--------------------------------------------------------------------------------
via: http://linoxide.com/firewall/pfsense-setup-basic-configuration/
作者:[Ben Cotton][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/bcotton

View File

@ -1,215 +0,0 @@
NearTan 认领
Journey to HTTP/2
===================
It has been quite some time since I last wrote through my blog and the reason is not being able to find enough time to put into it. I finally got some time today and thought to put some of it writing about HTTP.
HTTP is the protocol that every web developer should know as it powers the whole web and knowing it is definitely going to help you develop better applications.
In this article, I am going to be discussing what HTTP is, how it came to be, where it is today and how did we get here.
### What is HTTP?
First things first, what is HTTP? HTTP is the TCP/IP based application layer communication protocol which standardizes how the client and server communicate with each other. It defines how the content is requested and transmitted across the internet. By application layer protocol, I mean its just an abstraction layer that standardizes how the hosts (clients and servers) communicate and itself it depends upon TCP/IP to get request and response between the client and server. By default TCP port 80 is used but other ports can be used as well. HTTPS, however, uses port 443.
#### HTTP/0.9 - The One Liner (1991)
The first documented version of HTTP was HTTP/0.9 which was put forward in 1991. It was the simplest protocol ever; having a single method called GET. If a client had to access some webpage on the server, it would have made the simple request like below
```
GET /index.html
```
And the response from server would have looked as follows
```
(response body)
(connection closed)
```
That is, the server would get the request, reply with the HTML in response and as soon as the content has been transferred, the connection will be closed. There were
- No headers
- GET was the only allowed method
- Response had to be HTML
As you can see, the protocol really had nothing more than being a stepping stone for what was to come.
#### HTTP/1.0 - 1996
In 1996, the next version of HTTP i.e. HTTP/1.0 evolved that vastly improved over the original version.
Unlike HTTP/0.9 which was only designed for HTML response, HTTP/1.0 could now deal with other response formats i.e. images, video files, plain text or any other content type as well. It added more methods (i.e. POST and HEAD), request/response formats got changed, HTTP headers got added to both the request and responses, status codes were added to identify the response, character set support was introduced, multi-part types, authorization, caching, content encoding and more was included.
Here is how a sample HTTP/1.0 request and response might have looked like:
```
GET / HTTP/1.0
Host: kamranahmed.info
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
```
As you can see, alongside the request, client has also sent its personal information, required response type etc. While in HTTP/0.9 client could never send such information because there were no headers.
Example response to the request above may have looked like below
```
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
(response body)
(connection closed)
```
In the very beginning of the response there is HTTP/1.0 (HTTP followed by the version number), then there is the status code 200 followed by the reason phrase (or description of the status code, if you will).
In this newer version, request and response headers were still kept as ASCII encoded, but the response body could have been of any type i.e. image, video, HTML, plain text or any other content type. So, now that server could send any content type to the client; not so long after the introduction, the term “Hyper Text” in HTTP became misnomer. HMTP or Hypermedia transfer protocol might have made more sense but, I guess, we are stuck with the name for life.
One of the major drawbacks of HTTP/1.0 were you couldnt have multiple requests per connection. That is, whenever a client will need something from the server, it will have to open a new TCP connection and after that single request has been fulfilled, connection will be closed. And for any next requirement, it will have to be on a new connection. Why is it bad? Well, lets assume that you visit a webpage having 10 images, 5 stylesheets and 5 javascript files, totalling to 20 items that needs to fetched when request to that webpage is made. Since the server closes the connection as soon as the request has been fulfilled, there will be a series of 20 separate connections where each of the items will be served one by one on their separate connections. This large number of connections results in a serious performance hit as requiring a new TCP connection imposes a significant performance penalty because of three-way handshake followed by slow-start.
### Three-way Handshake
Three-way handshake in its simples form is that all the TCP connections begin with a three-way handshake in which the client and the server share a series of packets before starting to share the application data.
- SYN - Client picks up a random number, lets say x, and sends it to the server.
- SYN ACK - Server acknowledges the request by sending an ACK packet back to the client which is made up of a random number, lets say y picked up by server and the number x+1 where x is the number that was sent by the client
- ACK - Client increments the number y received from the server and sends an ACK packet back with the number x+1
Once the three-way handshake is completed, the data sharing between the client and server may begin. It should be noted that the client may start sending the application data as soon as it dispatches the last ACK packet but the server will still have to wait for the ACK packet to be recieved in order to fulfill the request.
![](http://i.imgur.com/uERG2G2.png)
However, some implementations of HTTP/1.0 tried to overcome this issue by introducing a new header called Connection: keep-alive which was meant to tell the server “Hey server, do not close this connection, I need it again”. But still, it wasnt that widely supported and the problem still persisted.
Apart from being connectionless, HTTP also is a stateless protocol i.e. server doesnt maintain the information about the client and so each of the requests has to have the information necessary for the server to fulfill the request on its own without any association with any old requests. And so this adds fuel to the fire i.e. apart from the large number of connections that the client has to open, it also has to send some redundant data on the wire causing increased bandwidth usage.
#### HTTP/1.1 - 1999
After merely 3 years of HTTP/1.0, the next version i.e. HTTP/1.1 was released in 1999; which made alot of improvements over its predecessor. The major improvements over HTTP/1.0 included
- New HTTP methods were added, which introduced PUT, PATCH, HEAD, OPTIONS, DELETE
- Hostname Identification In HTTP/1.0 Host header wasnt required but HTTP/1.1 made it required.
- Persistent Connections As discussed above, in HTTP/1.0 there was only one request per connection and the connection was closed as soon as the request was fulfilled which resulted in accute performance hit and latency problems. HTTP/1.1 introduced the persistent connections i.e. connections werent closed by default and were kept open which allowed multiple sequential requests. To close the connections, the header Connection: close had to be available on the request. Clients usually send this header in the last request to safely close the connection.
- Pipelining It also introduced the support for pipelining, where the client could send multiple requests to the server without waiting for the response from server on the same connection and server had to send the response in the same sequence in which requests were received. But how does the client know that this is the point where first response download completes and the content for next response starts, you may ask! Well, to solve this, there must be Content-Length header present which clients can use to identify where the response ends and it can start waiting for the next response.
>It should be noted that in order to benefit from persistent connections or pipelining, Content-Length header must be available on the response, because this would let the client know when the transmission completes and it can send the next request (in normal sequential way of sending requests) or start waiting for the the next response (when pipelining is enabled).
>But there was still an issue with this approach. And that is, what if the data is dynamic and server cannot find the content length before hand? Well in that case, you really cant benefit from persistent connections, could you?! In order to solve this HTTP/1.1 introduced chunked encoding. In such cases server may omit content-Length in favor of chunked encoding (more to it in a moment). However, if none of them are available, then the connection must be closed at the end of request.
- Chunked Transfers In case of dynamic content, when the server cannot really find out the Content-Length when the transmission starts, it may start sending the content in pieces (chunk by chunk) and add the Content-Length for each chunk when it is sent. And when all of the chunks are sent i.e. whole transmission has completed, it sends an empty chunk i.e. the one with Content-Length set to zero in order to identify the client that transmission has completed. In order to notify the client about the chunked transfer, server includes the header Transfer-Encoding: chunked
- Unlike HTTP/1.0 which had Basic authentication only, HTTP/1.1 included digest and proxy authentication
- Caching
- Byte Ranges
- Character sets
- Language negotiation
- Client cookies
- Enhanced compression support
- New status codes
- ..and more
I am not going to dwell about all the HTTP/1.1 features in this post as it is a topic in itself and you can already find a lot about it. The one such document that I would recommend you to read is Key differences between HTTP/1.0 and HTTP/1.1 and here is the link to original RFC for the overachievers.
HTTP/1.1 was introduced in 1999 and it had been a standard for many years. Although, it improved alot over its predecessor; with the web changing everyday, it started to show its age. Loading a web page these days is more resource-intensive than it ever was. A simple webpage these days has to open more than 30 connections. Well HTTP/1.1 has persistent connections, then why so many connections? you say! The reason is, in HTTP/1.1 it can only have one outstanding connection at any moment of time. HTTP/1.1 tried to fix this by introducing pipelining but it didnt completely address the issue because of the head-of-line blocking where a slow or heavy request may block the requests behind and once a request gets stuck in a pipeline, it will have to wait for the next requests to be fulfilled. To overcome these shortcomings of HTTP/1.1, the developers started implementing the workarounds, for example use of spritesheets, encoded images in CSS, single humungous CSS/Javascript files, domain sharding etc.
#### SPDY - 2009
Google went ahead and started experimenting with alternative protocols to make the web faster and improving web security while reducing the latency of web pages. In 2009, they announced SPDY.
>SPDY is a trademark of Google and isnt an acronym.
It was seen that if we keep increasing the bandwidth, the network performance increases in the beginning but a point comes when there is not much of a performance gain. But if you do the same with latency i.e. if we keep dropping the latency, there is a constant performance gain. This was the core idea for performance gain behind SPDY, decrease the latency to increase the network performance.
>For those who dont know the difference, latency is the delay i.e. how long it takes for data to travel between the source and destination (measured in milliseconds) and bandwidth is the amount of data transfered per second (bits per second).
The features of SPDY included, multiplexing, compression, prioritization, security etc. I am not going to get into the details of SPDY, as you will get the idea when we get into the nitty gritty of HTTP/2 in the next section as I said HTTP/2 is mostly inspired from SPDY.
SPDY didnt really try to replace HTTP; it was a translation layer over HTTP which existed at the application layer and modified the request before sending it over to the wire. It started to become a defacto standards and majority of browsers started implementing it.
In 2015, at Google, they didnt want to have two competing standards and so they decided to merge it into HTTP while giving birth to HTTP/2 and deprecating SPDY.
#### HTTP/2 - 2015
By now, you must be convinced that why we needed another revision of the HTTP protocol. HTTP/2 was designed for low latency transport of content. The key features or differences from the old version of HTTP/1.1 include
- Binary instead of Textual
- Multiplexing - Multiple asynchronous HTTP requests over a single connection
- Header compression using HPACK
- Server Push - Multiple responses for single request
- Request Prioritization
- Security
![](http://i.imgur.com/S85j8gg.png)
##### 1. Binary Protocol
HTTP/2 tends to address the issue of increased latency that existed in HTTP/1.x by making it a binary protocol. Being a binary protocol, it easier to parse but unlike HTTP/1.x it is no longer readable by the human eye. The major building blocks of HTTP/2 are Frames and Streams
**Frames and Streams**
HTTP messages are now composed of one or more frames. There is a HEADERS frame for the meta data and DATA frame for the payload and there exist several other types of frames (HEADERS, DATA, RST_STREAM, SETTINGS, PRIORITY etc) that you can check through the HTTP/2 specs.
Every HTTP/2 request and response is given a unique stream ID and it is divided into frames. Frames are nothing but binary pieces of data. A collection of frames is called a Stream. Each frame has a stream id that identifies the stream to which it belongs and each frame has a common header. Also, apart from stream ID being unique, it is worth mentioning that, any request initiated by client uses odd numbers and the response from server has even numbers stream IDs.
Apart from the HEADERS and DATA, another frame type that I think worth mentioning here is RST_STREAM which is a special frame type that is used to abort some stream i.e. client may send this frame to let the server know that I dont need this stream anymore. In HTTP/1.1 the only way to make the server stop sending the response to client was closing the connection which resulted in increased latency because a new connection had to be opened for any consecutive requests. While in HTTP/2, client can use RST_STREAM and stop receiving a specific stream while the connection will still be open and the other streams will still be in play.
##### 2. Multiplexing
Since HTTP/2 is now a binary protocol and as I said above that it uses frames and streams for requests and responses, once a TCP connection is opened, all the streams are sent asynchronously through the same connection without opening any additional connections. And in turn, the server responds in the same asynchronous way i.e. the response has no order and the client uses the assigned stream id to identify the stream to which a specific packet belongs. This also solves the head-of-line blocking issue that existed in HTTP/1.x i.e. the client will not have to wait for the request that is taking time and other requests will still be getting processed.
##### 3. HPACK Header Compression
It was part of a separate RFC which was specifically aimed at optimizing the sent headers. The essence of it is that when we are constantly accessing the server from a same client there is alot of redundant data that we are sending in the headers over and over, and sometimes there might be cookies increasing the headers size which results in bandwidth usage and increased latency. To overcome this, HTTP/2 introduced header compression.
![](http://i.imgur.com/3IPWXvR.png)
Unlike request and response, headers are not compressed in gzip or compress etc formats but there is a different mechanism in place for header compression which is literal values are encoded using Huffman code and a headers table is maintained by the client and server and both the client and server omit any repetitive headers (e.g. user agent etc) in the subsequent requests and reference them using the headers table maintained by both.
While we are talking headers, let me add here that the headers are still the same as in HTTP/1.1, except for the addition of some pseudo headers i.e. :method, :scheme, :host and :path
##### 4. Server Push
Server push is another tremendous feature of HTTP/2 where the server, knowing that the client is going to ask for a certain resource, can push it to the client without even client asking for it. For example, lets say a browser loads a web page, it parses the whole page to find out the remote content that it has to load from the server and then sends consequent requests to the server to get that content.
Server push allows the server to decrease the roundtrips by pushing the data that it knows that client is going to demand. How it is done is, server sends a special frame called PUSH_PROMISE notifying the client that, “Hey, I am about to send this resource to you! Do not ask me for it.” The PUSH_PROMISE frame is associated with the stream that caused the push to happen and it contains the promised stream ID i.e. the stream on which the server will send the resource to be pushed.
##### 5. Request Prioritization
A client can assign a priority to a stream by including the prioritization information in the HEADERS frame by which a stream is opened. At any other time, client can send a PRIORITY frame to change the priority of a stream.
Without any priority information, server processes the requests asynchronously i.e. without any order. If there is priority assigned to a stream, then based on this prioritization information, server decides how much of the resources need to be given to process which request.
##### 6. Security
There was extensive discussion on whether security (through TLS) should be made mandatory for HTTP/2 or not. In the end, it was decided not to make it mandatory. However, most vendors stated that they will only support HTTP/2 when it is used over TLS. So, although HTTP/2 doesnt require encryption by specs but it has kind of become mandatory by default anyway. With that out of the way, HTTP/2 when implemented over TLS does impose some requirementsi.e. TLS version 1.2 or higher must be used, there must be a certain level of minimum keysizes, ephemeral keys are required etc.
HTTP/2 is here and it has already surpassed SPDY in adaption which is gradually increasing. HTTP/2 has alot to offer in terms of performance gain and it is about time we should start using it.
For anyone interested in further details here is the [link to specs][1] and a [link demonstrating the performance benefits of][2] HTTP/2. For any questions or comments, use the comments section below. Also, while reading, if you find any blatant lies; do point them out.
And that about wraps it up. Until next time! stay tuned.
--------------------------------------------------------------------------------
via: http://kamranahmed.info/blog/2016/08/13/http-in-depth/?utm_source=webopsweekly&utm_medium=email
作者:[Kamran Ahmed][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://github.com/kamranahmedse
[1]: https://http2.github.io/http2-spec
[2]: http://www.http2demo.io/

View File

@ -1,3 +1,5 @@
Translating by Yinr
The cost of small modules
====

View File

@ -1,70 +0,0 @@
翻译中byzky001
Deploying React with Zero Configuration
========================
So you want to build an app with [React][1]? "[Getting started][2]" is easy… and then what?
React is a library for building user interfaces, which comprise only one part of an app. Deciding on all the other parts — styles, routers, npm modules, ES6 code, bundling and more — and then figuring out how to use them is a drain on developers. This has become known as [javascript fatigue][3]. Despite this complexity, usage of React continues to grow.
The community answers this challenge by sharing boilerplates. These [boilerplates][4] reveal the profusion of architectural choices developers must make. That official "Getting Started" seems so far away from the reality of an operational app.
### New, Zero-configuration Experience
Inspired by the cohesive developer experience provided by [Ember.js][5] and [Elm][6], the folks at Facebook wanted to provide an easy, opinionated way forward. They created a new way to develop React apps, `create-react-app`. In the three weeks since initial public release, it has received tremendous community awareness (over 8,000 GitHub stargazers) and support (dozens of pull requests).
`create-react-app` is different than many past attempts with boilerplates and starter kits. It targets zero configuration [[convention-over-configuration]][7], focusing the developer on what is interesting and different about their application.
A powerful side-effect of zero configuration is that the tools can now evolve in the background. Zero configuration lays the foundation for the tools ecosystem to create automation and delight developers far beyond React itself.
### Zero-configuration Deploy to Heroku
Thanks to the zero-config foundation of create-react-app, the idea of zero-config deployment seemed within reach. Since these new apps all share a common, implicit architecture, the build process can be automated and then served with intelligent defaults. So, [we created this community buildpack to experiment with no-configuration deployment to Heroku][8].
#### Create and Deploy a React App in Two Minutes
You can get started building React apps for free on Heroku.
```
npm install -g create-react-app
create-react-app my-app
cd my-app
git init
heroku create -b https://github.com/mars/create-react-app-buildpack.git
git add .
git commit -m "react-create-app on Heroku"
git push heroku master
heroku open
```
Try it yourself [using the buildpack docs][9].
### Growing Up from Zero Config
create-react-app is very new (currently version 0.2) and since its target is a crystal-clear developer experience, more advanced use cases are not supported (or may never be supported). For example, it does not provide server-side rendering or customized bundles.
To support greater control, create-react-app includes the command npm run eject. Eject unpacks all the tooling (config files and package.json dependencies) into the app's directory, so you can customize to your heart's content. Once ejected, changes you make may necessitate switching to a custom deployment with Node.js and/or static buildpacks. Always perform such project changes through a branch / pull request, so they can be easily undone. Heroku's Review Apps are perfect for testing changes to the deployment.
We'll be tracking progress on create-react-app and adapting the buildpack to support more advanced use cases as they become available. Happy deploying!
--------------------------------------------------------------------------------
via: https://blog.heroku.com/deploying-react-with-zero-configuration?c=7013A000000NnBFQA0&utm_campaign=Display%20-%20Endemic%20-Cooper%20-Node%20-%20Blog%20-%20Zero-Configuration&utm_medium=display&utm_source=cooperpress&utm_content=blog&utm_term=node
作者:[Mars Hall][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://blog.heroku.com/deploying-react-with-zero-configuration?c=7013A000000NnBFQA0&utm_campaign=Display%20-%20Endemic%20-Cooper%20-Node%20-%20Blog%20-%20Zero-Configuration&utm_medium=display&utm_source=cooperpress&utm_content=blog&utm_term=node
[1]: https://facebook.github.io/react/
[2]: https://facebook.github.io/react/docs/getting-started.html
[3]: https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4
[4]: https://github.com/search?q=react+boilerplate
[5]: http://emberjs.com/
[6]: http://elm-lang.org/
[7]: http://rubyonrails.org/doctrine/#convention-over-configuration
[8]: https://github.com/mars/create-react-app-buildpack
[9]: https://github.com/mars/create-react-app-buildpack#usage

View File

@ -1,220 +0,0 @@
translating by ucasFL
Understanding Different Classifications of Shell Commands and Their Usage in Linux
====
When it comes to gaining absolute control over your Linux system, then nothing comes close to the command line interface (CLI). In order to become a Linux power user, one must understand the [different types of shell commands][1] and the appropriate ways of using them from the terminal.
In Linux, there are several types of commands, and for a new Linux user, knowing the meaning of different commands enables for efficient and precise usage. Therefore, in this article, we shall walk through the various classifications of shell commands in Linux.
One important thing to note is that the command line interface is different from the shell, it only provides a means for you to access the shell. The shell, which is also programmable then makes it possible to communicate with the kernel using commands.
Different classifications of Linux commands fall under the following classifications:
### 1. Program Executables (File System Commands)
When you run a command, Linux searches through the directories stored in the $PATH environmental variable from left to right for the executable of that specific command.
You can view the directories in the $PATH as follows:
```
$ echo $PATH
/home/aaronkilik/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
```
In the above order, the directory /home/aaronkilik/bin will be searched first followed by /usr/local/sbin and so on, the order is significant in the search process.
Examples of file system commands in /usr/bin directory:
```
$ ll /bin/
```
Sample Output
```
total 16284
drwxr-xr-x 2 root root 4096 Jul 31 16:30 ./
drwxr-xr-x 23 root root 4096 Jul 31 16:29 ../
-rwxr-xr-x 1 root root 6456 Apr 14 18:53 archdetect*
-rwxr-xr-x 1 root root 1037440 May 17 16:15 bash*
-rwxr-xr-x 1 root root 520992 Jan 20 2016 btrfs*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-calc-size*
lrwxrwxrwx 1 root root 5 Jul 31 16:19 btrfsck -> btrfs*
-rwxr-xr-x 1 root root 278376 Jan 20 2016 btrfs-convert*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-debug-tree*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-find-root*
-rwxr-xr-x 1 root root 270136 Jan 20 2016 btrfs-image*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfs-map-logical*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-select-super*
-rwxr-xr-x 1 root root 253816 Jan 20 2016 btrfs-show-super*
-rwxr-xr-x 1 root root 249464 Jan 20 2016 btrfstune*
-rwxr-xr-x 1 root root 245368 Jan 20 2016 btrfs-zero-log*
-rwxr-xr-x 1 root root 31288 May 20 2015 bunzip2*
-rwxr-xr-x 1 root root 1964536 Aug 19 2015 busybox*
-rwxr-xr-x 1 root root 31288 May 20 2015 bzcat*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzcmp -> bzdiff*
-rwxr-xr-x 1 root root 2140 May 20 2015 bzdiff*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzegrep -> bzgrep*
-rwxr-xr-x 1 root root 4877 May 20 2015 bzexe*
lrwxrwxrwx 1 root root 6 Jul 31 16:19 bzfgrep -> bzgrep*
-rwxr-xr-x 1 root root 3642 May 20 2015 bzgrep*
```
### 2. Linux Aliases
These are user defined commands, they are created using the alias shell built-in command, and contain other shell commands with some options and arguments. The ideas is to basically use new and short names for lengthy commands.
The syntax for creating an alias is as follows:
```
$ alias newcommand='command -options'
```
To list all aliases on your system, issue the command below:
```
$ alias -p
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
```
To create a new alias in Linux, go through some below examples.
```
$ alias update='sudo apt update'
$ alias upgrade='sudo apt dist-upgrade'
$ alias -p | grep 'up'
```
![](http://www.tecmint.com/wp-content/uploads/2016/08/Create-Aliase-in-Linux.png)
However, the aliases we have created above only work temporarily, when the system is restarted, they will not work after the next boot. You can set permanent aliases in your `.bashrc` file as shown below.
![](http://www.tecmint.com/wp-content/uploads/2016/08/Set-Linux-Aliases-Permanent.png)
After adding them, run the command below to active.
```
$ source ~/.bashrc
```
### 3. Linux Shell Reserved Words
In shell programming, words such as if, then, fi, for, while, case, esac, else, until and many others are shell reserved words. As the description implies, they have specialized meaning to the shell.
You can list out all Linux shell keywords using type command as shown:
```
$ type if then fi for while case esac else until
if is a shell keyword
then is a shell keyword
fi is a shell keyword
for is a shell keyword
while is a shell keyword
case is a shell keyword
esac is a shell keyword
else is a shell keyword
until is a shell keyword
```
Suggested Read: 10 Useful Linux Chaining Operators with Practical Examples
### 4. Linux Shell Functions
A shell function is a group of commands that are executed collectively within the current shell. Functions help to carry out a specific task in a shell script. The conventional form of writing shell functions in a script is:
```
function_name() {
command1
command2
…….
}
```
Alternatively,
```
function function_name {
command1
command2
…….
}
```
Lets take a look at how to write shell functions in a script named shell_functions.sh.
```
#!/bin/bash
#write a shell function to update and upgrade installed packages
upgrade_system(){
sudo apt update;
sudo apt dist-upgrade;
}
#execute function
upgrade_system
```
Instead of executing the two commands: sudo apt update and sudo apt dist-upgrade from the command line, we have written a simple shell function to execute the two commands as a single command, upgrade_system within a script.
Save the file and thereafter, make the script executable. Finally run it as below:
```
$ chmod +x shell_functions.sh
$ ./shell_functions.sh
```
![](http://www.tecmint.com/wp-content/uploads/2016/08/Linux-Shell-Functions-Script.png)
### 5. Linux Shell Built-in Commands
These are Linux commands that built into the shell, thus you cannot find them within the file system. They include pwd, cd, bg, alias, history, type, source, read, exit and many others.
You can list or check Linux built-in commands using type command as shown:
```
$ type pwd
pwd is a shell builtin
$ type cd
cd is a shell builtin
$ type bg
bg is a shell builtin
$ type alias
alias is a shell builtin
$ type history
history is a shell builtin
```
Learn about some Linux built-in Commands usage:
- [15 pwd Command Examples in Linux][2]
- [15 cd Command Examples in Linux][3]
- [Learn The Power of Linux history Command][4]
### Conclusion
As a Linux user, it is always important to know the type of command you are running. I believe, with the precise and simple-to-understand explanation above including a few relevant illustrations, you probably have a good understanding of the [various categories of Linux commands][5].
You can as well get in tough through the comment section below for any questions or supplementary ideas that you would like to offer us.
--------------------------------------------------------------------------------
via: http://linoxide.com/firewall/pfsense-setup-basic-configuration/
作者:[Aaron Kili ][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.tecmint.com/author/aaronkili/
[1]: http://www.tecmint.com/different-types-of-linux-shells/
[2]: http://www.tecmint.com/pwd-command-examples/
[3]: http://www.tecmint.com/cd-command-in-linux/
[4]: http://www.tecmint.com/history-command-examples/
[5]: http://www.tecmint.com/category/linux-commands/

View File

@ -1,3 +1,4 @@
翻译中 by-zky001
Apache Spark @Scale: A 60 TB+ production use case
===========
@ -113,7 +114,7 @@ While this post details our most challenging use case for Spark, a growing numbe
via: https://code.facebook.com/posts/1671373793181703/apache-spark-scale-a-60-tb-production-use-case/?utm_source=dbweekly&utm_medium=email
作者:[Sital Kedia][a] [王硕杰][b] [Avery Ching][c]
译者:[译者ID](https://github.com/译者ID)
译者:[zky001](https://github.com/zky001)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,436 +0,0 @@
HOSTING .NET CORE ON LINUX WITH DOCKER - A NOOB'S GUIDE
=====
This post builds on my previous [introduction to .NET Core][1]. First I upgrade that RESTful API from .NET Core RC1 to .NET Core 1.0, then I add support for Docker and describe how to host it on Linux in a production environment.
![](http://blog.scottlogic.com/nsoper/assets/noob.png)
Im completely new to Docker and Im far from a Linux expert, so these are very much the thoughts of a noob.
### INSTALLATION
Follow the instructions on https://www.microsoft.com/net/core to install .NET Core on your development machine. This will include the dotnet command line tool and the latest Visual Studio tooling for Windows.
### SOURCE CODE
You can jump straight to the finished source code on GitHub.
### CONVERTING TO .NET CORE 1.0
Naturally, my first port of call when thinking about how to upgrade the API from RC1 to 1.0 was to Google it with Bing. There are two pretty comprehensive guides that I followed:
- [Migrating from DNX to .NET Core CLI][2]
- [Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0][3]
I advise reading through both of these very carefully when migrating your code because I tried to skim read the second one without reading the first one and got very confused and frustrated!
I wont describe the changes in detail because you can look at the commit on GitHub. Here is a summary of what I changed:
- Updated version numbers on global.json and project.json
- Removed obsolete sections from project.json
- Using the more lightweight ControllerBase rather than Controller because I dont need methods related to MVC views (this was an optional change)
- Removed the Http prefix from helper methods e.g. HttpNotFound -> NotFound
- LogVerbose -> LogTrace
- Namespace changes: Microsoft.AspNetCore.*
- Using SetBasePath in Startup (appsettings.json wont be found without this)
- Running via WebHostBuilder rather than WebApplication.Run
- Removed Serilog (at the time of writing it does not support .NET Core 1.0)
The only real headache here is the need to remove Serilog. I could have implemented my own file logger, but I just deleted file logging because I didnt want to focus on it for this exercise.
Unfortunately, there will be plenty of third party developers that will be playing catch up with support for .NET Core 1.0 but I have sympathy for them because they are often working in their spare time without anything close to the resources available to Microsoft. I recommend reading Travis Illigs [.NET Core 1.0 is Released, but Where is Autofac][4]? for a third party developers point of view on this!
Having made these changes I was able to dotnet restore, dotnet build and dotnet run from the project.json directory and see the API working as before.
### RUNNING WITH DOCKER
At the time of writing, Docker only really works on Linux. There is beta support for Docker on Windows and OS X but they both rely on virtualisation so Ive chosen to run Ubuntu 14.04 as a VirtualBox. Follow these instructions if you havent already got Docker installed.
Ive been doing a bit of reading about Docker recently but Ive never tried to actually do anything with it until now. Ill assume the reader has no Docker knowledge so Ill explain all parts of the commands that Im using.
#### HELLO DOCKER
Having installed Docker on my Ubuntu machine, my next move was to follow the instructions at https://www.microsoft.com/net/core#docker to see how to get started with .NET Core and Docker.
First start a container with .NET Core installed:
```
docker run -it microsoft/dotnet:latest
```
The -it option means interactive so having executed this command you will be inside the container and free to run any bash commands you like.
Then we can run five commands to get Microsofts Hello World .NET Core console application running inside Docker!
1. mkdir hwapp
2. cd hwapp
3. dotnet new
4. dotnet restore
5. dotnet run
You can exit to leave the container, then docker ps -a to show that you have created a container which has exited. You should really now tidy up that container using docker rm <container_name>.
#### MOUNTING THE SOURCE
My next move was to use the same microsoft/dotnet image as above but to mount the source for my application as a data volume.
First check out the repository at the relevant commit:
1. git clone https://github.com/niksoper/aspnet5-books.git
2. cd aspnet5-books/src/MvcLibrary
3. git checkout dotnet-core-1.0
Now start a container running .NET Core 1.0 with the source located at /books. Note that youll need to change the /path/to/repo part to match your machine:
```
docker run -it \
-v /path/to/repo/aspnet5-books/src/MvcLibrary:/books \
microsoft/dotnet:latest
```
Now you can run the application inside the container!
```
cd /books
dotnet restore
dotnet run
```
Thats great as a proof of concept but we dont really want to have to worry about mounting the source code into a container like this whenever we want to start the application.
#### ADDING A DOCKERFILE
The next step I took was to introduce a Dockerfile, which will allow the application to be started easily inside its own container.
My Dockerfile lives in the src/MvcLibrary directory alongside project.json and looks like this:
```
FROM microsoft/dotnet:latest
# Create directory for the app source code
RUN mkdir -p /usr/src/books
WORKDIR /usr/src/books
# Copy the source and restore dependencies
COPY . /usr/src/books
RUN dotnet restore
# Expose the port and start the app
EXPOSE 5000
CMD [ "dotnet", "run" ]
```
Strictly, the `RUN mkdir -p /usr/src/books` command is not needed because COPY will create any missing directories automatically.
Docker images are built in layers. We start from the image containing .NET Core and add another layer which builds the application from source then runs the application.
Having added the Dockerfile, I then ran the following commands to build the image and start a container using that image (make sure you are in the same directory as the Dockerfile and you should really use your own username):
1. docker build -t niksoper/netcore-books .
2. docker run -it niksoper/netcore-books
You should see that the application started listening just as before, except this time we dont need to bother mounting the source code because its already contained in the docker image.
#### EXPOSING AND PUBLISHING A PORT
This API isnt going to be very useful unless we can communicate with it from outside the container. Docker has the concept of exposing and publishing ports, which are two very different things.
From the official Docker documentation:
>The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime. EXPOSE does not make the ports of the container accessible to the host. To do that, you must use either the -p flag to publish a range of ports or the -P flag to publish all of the exposed ports.
EXPOSE only adds metadata to the image so you can think of it as documentation for the consumers of the image. Technically, I could have left out the EXPOSE 5000 line completely because I know the port that the API is listening on but leaving it in is helpful and certainly recommended.
At this stage I want to access the API directly from the host so I need to use -p to publish the port - this allows a request to port 5000 on the host be forwarded to port 5000 in the container regardless of whether the port has previously been exposed via the Dockerfile:
```
docker run -d -p 5000:5000 niksoper/netcore-books
```
Using -d tells docker to run the container in detached mode so we wont see its output but it will still be running and listening on port 5000 - prove this to yourself with docker ps.
So then I prepared to celebrate by making a request from the host to the container:
```
curl http://localhost:5000/api/books
```
It didnt work.
Making the same curl request repeatedly, I see one of two errors - either curl: (56) Recv failure: Connection reset by peer or curl: (52) Empty reply from server.
I went back to the docker run documentation and double checked I was using the -p option correctly as well as EXPOSE in the Dockerfile. I couldnt see the problem and became a bit sad…
After pulling myself together, I decided to consult one of my local DevOps heroes - Dave Wybourn (also mentioned in this post on Docker Swarm). His team had run into this exact problem and the issue was the way that I had (not) configured Kestrel - the new lightweight, cross platform web server used for .NET Core.
By default, Kestrel will listen on http://localhost:5000. The problem here is that localhost is a loopback interface.
From Wikipedia:
>In computer networking, localhost is a hostname that means this computer. It is used to access the network services that are running on the host via its loopback network interface. Using the loopback interface bypasses any local network interface hardware.
This is a problem when running inside a container because localhost can only be reached from within that container. The solution was to update the Main method in Startup.cs to configure the URLs that Kestrel will listen on:
```
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls("http://*:5000") // listen on port 5000 on all network interfaces
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
```
With this extra configuration in place, I could then rebuild image and run the application in a container which will accept requests from the host:
1. docker build -t niksoper/netcore-books .
2. docker run -d -p 5000:5000 niksoper/netcore-books
3. curl -i http://localhost:5000/api/books
I now get the following response:
```
HTTP/1.1 200 OK
Date: Tue, 30 Aug 2016 15:25:43 GMT
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]
```
### KESTREL IN PRODUCTION
Microsofts words:
>Kestrel is great for serving dynamic content from ASP.NET, however the web serving parts arent as feature rich as full-featured servers like IIS, Apache or Nginx. A reverse proxy-server can allow you to offload work like serving static content, caching requests, compressing requests, and SSL termination from the HTTP server.
So I need to set up Nginx on my Linux machine to act as my reverse proxy. Microsoft spell out how to do this in Publish to a Linux Production Environment. Ill summarise the instructions here:
1. Use dotnet publish to produce a self contained package for the application
2. Copy the published application to the server
3. Install and configure Nginx (as a reverse proxy server)
4. Install and configure supervisor (for keeping the Kestrel server running)
5. Enable and configure AppArmor (for limiting the resources available to an application)
6. Configure the server firewall
7. Secure Nginx (involves building from source and configuring SSL)
Its beyond the scope of this post to cover all of that, so Im only going to concentrate on configuring Nginx as a reverse proxy - and naturally, Im going to use Docker to do it.
### RUN NGINX IN ANOTHER CONTAINER
My aim is to run Nginx in a second Docker container and configure it as a reverse proxy to my application container.
Ive used the official Nginx image from Docker Hub. First I tried it out like this:
```
docker run -d -p 8080:80 --name web nginx
```
This starts a container running Nginx and maps port 8080 on the host to port 80 in the container. Hitting http://localhost:8080 in the browser now shows the default Nginx landing page.
Now weve proved how easy it is to get Nginx running, we can kill the container.
```
docker rm -f web
```
### CONFIGURING NGINX AS A REVERSE PROXY
Nginx can be configured as a reverse proxy by editing the config file at /etc/nginx/conf.d/default.conf like this:
```
server {
listen 80;
location / {
proxy_pass http://localhost:6666;
}
}
```
The config above will cause Nginx to proxy all requests from the root to http://localhost:6666. Remember localhost here refers to the container running Nginx. We can use our own config file inside the Nginx container using a volume:
```
docker run -d -p 8080:80 \
-v /path/to/my.conf:/etc/nginx/conf.d/default.conf \
nginx
```
Note: this maps a single file from the host to the container, rather than an entire directory.
### COMMUNICATING BETWEEN CONTAINERS
Docker allows inter-container communication using shared virtual networks. By default, all containers started by the Docker daemon will have access to a virtual network called bridge. This allows containers to be referenced from other containers on the same network via IP address and port.
You can discover the IP address of a running container by inspecting it. Ill start a container from the niksoper/netcore-books image that I created earlier, and inspect it:
1. docker run -d -p 5000:5000 --name books niksoper/netcore-books
2. docker inspect books
![](http://blog.scottlogic.com/nsoper/assets/docker-inspect-ip.PNG)
We can see this container has "IPAddress": "172.17.0.3".
So now if I create the following Nginx config file, then start an Nginx container using that file, then it will proxy requests to my API:
```
server {
listen 80;
location / {
proxy_pass http://172.17.0.3:5000;
}
}
```
Now I can start an Nginx container using that config (note Im mapping port 8080 on the host to port 80 on the Nginx container):
```
docker run -d -p 8080:80 \
-v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf \
nginx
```
A request to http://localhost:8080 will now be proxied to my application. Note the Server header in the following curl response:
![](http://blog.scottlogic.com/nsoper/assets/nginx-proxy-response.PNG)
### DOCKER COMPOSE
At this point I was fairly pleased with my progress but I thought there must be a better way of configuring Nginx without needing to know the exact IP address of the application container. Another of the local Scott Logic DevOps heroes - Jason Ebbin - stepped up at this point and suggested Docker Compose.
As a high level description - Docker Compose makes it very easy to start up a collection of interconnected containers using a declarative syntax. I wont go into the details of how Docker Compose works because you can read about it in this previous post.
Ill start with the docker-compose.yml file that Im using:
```
version: '2'
services:
books-service:
container_name: books-api
build: .
reverse-proxy:
container_name: reverse-proxy
image: nginx
ports:
- "9090:8080"
volumes:
- ./proxy.conf:/etc/nginx/conf.d/default.conf
```
This is version 2 syntax, so youll need to have at least version 1.6 of Docker Compose in order for this to work.
This file tells Docker to create two services - one for the application and another for the Nginx reverse proxy.
### BOOKS-SERVICE
This builds a container called books-api from the Dockerfile in the same directory as this docker-compose.yml. Note that this container does not need to publish any ports because it only needs to be accessed from the reverse-proxy container rather than the host operating system.
### REVERSE-PROXY
This starts a container called reverse-proxy based on the nginx image with a proxy.conf file mounted as the config from the current directory. It maps port 9090 on the host to port 8080 in the container which allows us to access the container from the host at http://localhost:9090.
The proxy.conf file looks like this:
```
server {
listen 8080;
location / {
proxy_pass http://books-service:5000;
}
}
```
The key point here is that we can now refer to books-service by name so we dont need to know the IP address of the books-api container!
Now we can start the two containers with a working reverse proxy (-d means detached so we dont see the output from the containers):
```
docker compose up -d
```
Prove the containers were created:
```
docker ps
```
And finally confirm that we can hit the API via the reverse proxy:
```
curl -i http://localhost:9090/api/books
```
### WHATS GOING ON?
Docker Compose makes this happen by creating a new virtual network called mvclibrary_default which is used by both books-api and reverse-proxy containers (the name is based on the parent directory of the docker-compose.yml file).
Prove the network exists with docker network ls:
![](http://blog.scottlogic.com/nsoper/assets/docker-network-ls.PNG)
You can see the details of the new network using docker network inspect mvclibrary_default:
![](http://blog.scottlogic.com/nsoper/assets/network-inspect.PNG)
Note that Docker has assigned "Subnet": "172.18.0.0/16" to the network. The /16 part is CIDR notation and a full explanation is way beyond the scope of this post but CIDR just refers to a range of IP addresses. Running docker network inspect bridge shows "Subnet": "172.17.0.0/16" so the two networks do not overlap.
Now docker inspect books-api to confirm the application container is using this network:
![](http://blog.scottlogic.com/nsoper/assets/docker-inspect-books-api.PNG)
Notice the two "Aliases" for the container are the container identifier (3c42db680459) and the service name given in docker-compose.yml (books-service). Were using the books-service alias to reference the application container in the custom Nginx configuration file. This could have been done manually with docker network create but I like Docker Compose because it wraps up container creation and interdependencies cleanly and succinctly.
### CONCLUSION
So now I can get the application running on Linux with Nginx in a few easy steps, without making any lasting changes to the host operating system:
```
git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout blog-docker
docker-compose up -d
curl -i http://localhost:9090/api/books
```
I know what I have described in this post is not a truly production ready setup because Ive not spoken about any of the following, but most of these topics could take an entire post on their own:
- Security concerns like firewalls or SSL configuration
- How to ensure the application keeps running
- How to be selective about what to include in a Docker image (I dumped everything in via the Dockerfile)
- Databases - how to manage them in containers
This has been a very interesting learning experience for me because for a while now I have been curious to explore the new cross platform support that comes with ASP.NET Core, and the opportunity to explore a little bit of the DevOps world using Docker Compose for a “Configuration as Code” approach has been both enjoyable and educational.
If youre at all curious about Docker then I encourage you to get stuck in by trying it out - especially if this puts you out of your comfort zone. Who knows, you might enjoy it?
--------------------------------------------------------------------------------
via: http://blog.scottlogic.com/2016/09/05/hosting-netcore-on-linux-with-docker.html?utm_source=webopsweekly&utm_medium=email
作者:[Nick Soper][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://blog.scottlogic.com/nsoper
[1]: http://blog.scottlogic.com/2016/01/20/restful-api-with-aspnet50.html
[2]: https://docs.microsoft.com/en-us/dotnet/articles/core/migrating-from-dnx
[3]: https://docs.asp.net/en/latest/migration/rc1-to-rtm.html
[4]: http://www.paraesthesia.com/archive/2016/06/29/netcore-rtm-where-is-autofac/

View File

@ -1,3 +1,4 @@
LinuxBars 翻译中
8 best practices for building containerized applications
====

View File

@ -1,3 +1,4 @@
wcnnbdk1 Translating
Content Security Policy, Your Future Best Friend
=====

View File

@ -1,45 +0,0 @@
LinuxBars翻译认领
Five Linux Server Distros Worth Checking Out
====
>Pretty much any of the nearly 300 Linux distributions you'll find listed on Distrowatch can be made to work as servers. Here are those that stand out above the rest.
![](http://windowsitpro.com/site-files/windowsitpro.com/files/imagecache/large_img/uploads/2016/09/cloudservers.jpg)
Pretty much any of the nearly 300 Linux distributions you'll find listed on Distrowatch can be made to work as servers. Since Linux's earliest days, users have been provisioning "all purpose" distributions such as Slackware, Debian and Gentoo to do heavy lifting as servers for home and business. That may be fine for the hobbyist, but its a lot of unnecessary work for the professional.
From the beginning, however, there have been distributions with no other purpose but to serve files and applications, help workstations share common peripherals, serve-up web pages and all the other things we ask servers to do, whether in the cloud, in a data center or on a shelf in a utility closet.
Here's a look at four of the most used Linux server distros, as well as one distro that might fit the bill for smaller businesses.
**Red Hat Enterprise Linux**: Perhaps the best known of Linux server distros, RHEL has a reputation for being a solid distribution ready for the most demanding mission critical tasks -- like running the New York Stock Exchange for instance. It's also backed by Red Hat's best-of-breed support.
The downside? While Red Hat is known for offering customer service and support that's second to none, its support subscriptions aren't cheap. Some might point out, however, that you get what you pay for. Cheaper third party support for RHEL is available, but you might want to do some research before going that route.
**CentOS**: Anyone who likes RHEL but would like to avoid shoveling money to Red Hat for support should take a look at CentOS, which is basically an RHEL fork. Although it's been around since 2004, in 2014 it became officially sponsored by Red Hat, which now employs most of the project's developers. This means that security patches and bug fixes are made available to CentOS soon after they're pushed to Red Hat.
If you're going to deploy CentOS, you'll need people with Linux skills on staff, because as far as technical support goes, you're mainly on your own. The good news is that the CentOS community offers excellent resources, such as mailing lists, web forums, and chat rooms, so help is available to those who search.
**Ubuntu Server**: When Canonical announced many years back that it was coming out with a server edition of Ubuntu, you could hear the snickers. Laughter turned into amazement rather quickly, however, as Ubuntu Server rapidly took hold. This was partly due to the DNA it shares as a derivative of Debian, which has long been a favorite base for Linux servers. Ubuntu filled a gap by adding affordable technical support, superior hardware support, developer tools and lots of polish.
How popular is Ubuntu Server? Recent figures show it being the most deployed operating system both on OpenStack and on the Amazon Elastic Compute Cloud, where it outpaces second place Amazon Linux Amazon Machine Image by a mile and leaves third place Windows in the virtual dust. Another study shows it as the most used Linux web server.
**SUSE Linux Enterprise Server**: This German distro has a large base of users in Europe, and was a top server distro on this side of the Atlantic until PR issues arose after it was bought by Novell in the early part of the century. With those days long behind it, SUSE has been gaining ground in the US, and its use will probably accelerate now that HPE is naming it as its preferred Linux partner.
SUSE Linux Enterprise Server, or SLES, is stable and easy to maintain, which you'd expect for a distro that's been around for nearly as long as Linux itself. Affordable 24/7 "rapid-response" technical support is available, making it suitable for mission critical deployments.
**ClearOS**: Based on RHEL, ClearOS is included here because it's simple enough for anyone, even most non-techies, to configure. Targeted at small to medium sized businesses, it can also be used as an entertainment server by home users. Using a web-based administration interface for ease-of-use, it's built with the premise in mind that "building your IT infrastructure should be as simple as downloading apps on your smart phone."
The latest release, version 7.2, includes capabilities that might not be expected from a "lightweight" offering, such as VM support which includes Microsoft Hyper-V, support for the XFS and BTRFS file systems, as well as support for LVM caching and IPv6. Available in a free version or in an inexpensive "professional" version that comes with a variety of support options.
--------------------------------------------------------------------------------
via: http://windowsitpro.com/industry/five-linux-server-distros-worth-checking-out
作者:[Christine Hall][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://windowsitpro.com/industry/five-linux-server-distros-worth-checking-out

View File

@ -1,207 +0,0 @@
Monitoring Docker Containers with Elasticsearch and cAdvisor
=======
If youre running a Swarm Mode cluster or even a single Docker engine, youll end up asking this question:
>How do I keep track of all thats happening?
The answer is “not easily.”
You need a few things to have a complete overview of stuff like:
1. Number and status of containers
2. If, where, and when a container has been moved to another node
3. Number of containers on a given node
4. Traffic peaks at a given time
5. Orphan volumes and networks
6. Free disk space, free inodes
7. Number of containers against number of veths attached to the docker0 and docker_gwbridge bridges
8. Up and down Swarm nodes
9. Centralize logs
The goal of this post is to demonstrate the use of [Elasticsearch][1] + [Kibana][2] + [cAdvisor][3] as tools to analyze and gather metrics and visualize dashboards for Docker containers.
Later on in this post, you can find a dashboard trying to address a few points from the previous list. There are also points that cant be addressed by simply using cAdvisor, like the status of Swarm Mode nodes.
Also, if you have specific needs that arent covered by cAdvisor or another tool, I encourage you to write your own data collector and data shipper (e.g., [Beats][4]). Note that I wont be showing you how to centralize Docker containers log on Elasticsearch.
>[“How do you keep track of all thats happening in a Swarm Mode cluster? Not easily.” via @fntlnz][5]
### Why Do We Need to Monitor Containers?
Imagine yourself in the classic situation of managing a virtual machine, either just one or several. You are a tmux hero, so you have your sessions preconfigured to do basically everything, monitoring included. Theres a problem in production? You just do a top, htop, iotop, jnettop, whatevertop on all your machines, and youre ready for troubleshooting!
Now imagine that you have the same three nodes but split into 50 containers. You need some history displayed nicely in a single place where you can perform queries to know what happened instead of just risking your life in front of those ncurses tools.
### What Is the Elastic Stack?
The Elastic Stack is a set of tools composed of:
- Elasticsearch
- Kibana
- Logstash
- Beats
Were going to use a few open-source tools from the Elastic Stack, such as Elasticsearch for the JSON-based analytics engine and Kibana to visualize data and create dashboards.
Another important piece of the Elastic Stack is Beats, but in this post, were focused on containers. Theres no official Beat for Docker, so well just use cAdvisor that can natively talk with Elasticsearch.
cAdvisor is a tool that collects, aggregates, and exports metrics about running containers. In our case, those metrics are being exported to an Elasticsearch storage.
Two cool facts about cAdvisor are:
- Its not limited to Docker containers.
- It has its own webserver with a simple dashboard to visualize gathered metrics for the current node.
### Set Up a Test Cluster or BYOI
As I did in my previous posts, my habit is to provide a small script to allow the reader to set up a test environment on which to try out my projects steps in no time. So you can use the following not-for-production-use script to set up a little Swarm Mode cluster with Elasticsearch running as a container.
>If you have enough time/experience, you can BYOI (Bring Your Own Infrastructure).
To follow this post, youll just need:
- One or more nodes running the Docker daemon >= 1.12
- At least a stand-alone Elasticsearch node 2.4.X
Again, note that this post is not about setting up a production-ready Elasticsearch cluster. A single node cluster is not recommended for production. So if youre planning a production installation, please refer to [Elastic guidelines][6].
### A friendly note for early adopters
Im usually an early adopter (and Im already using the latest alpha version in production, of course). But for this post, I chose not to use the latest Elasticsearch 5.0.0 alpha. Their roadmap is not perfectly clear to me, and I dont want be the root cause of your problems!
So the Elasticsearch reference version for this post is the latest stable version, 2.4.0 at the moment of writing.
### Test cluster setup script
As said, I wanted to provide this script for everyone who would like to follow the blog without having to figure out how to create a Swarm cluster and install an Elasticsearch. Of course, you can skip this if you choose to use your own Swarm Mode engines and your own Elasticsearch nodes.
To execute the setup script, youll need:
- [Docker Machine][7] latest version: to provision Docker engines on DigitalOcean
- [DigitalOcean API Token][8]: to allow docker-machine to start nodes on your behalf
![](https://resources.codeship.com/hubfs/CTAs/EVAL/Codeship_Request_Trial_Access.png?t=1473869513342)
### Create Cluster Script
Now that you have everything we need, you can copy the following script in a file named create-cluster.sh:
```
#!/usr/bin/env bash
#
# Create a Swarm Mode cluster with a single master and a configurable number of workers
workers=${WORKERS:-"worker1 worker2"}
#######################################
# Creates a machine on Digital Ocean
# Globals:
# DO_ACCESS_TOKEN The token needed to access DigitalOcean's API
# Arguments:
# $1 the actual name to give to the machine
#######################################
create_machine() {
docker-machine create \
-d digitalocean \
--digitalocean-access-token=$DO_ACCESS_TOKEN \
--digitalocean-size 2gb \
$1
}
#######################################
# Executes a command on the specified machine
# Arguments:
# $1 The machine on which to run the command
# $2..$n The command to execute on that machine
#######################################
machine_do() {
docker-machine ssh $@
}
main() {
if [ -z "$DO_ACCESS_TOKEN" ]; then
echo "Please export a DigitalOcean Access token: https://cloud.digitalocean.com/settings/api/tokens/new"
echo "export DO_ACCESS_TOKEN=<yourtokenhere>"
exit 1
fi
if [ -z "$WORKERS" ]; then
echo "You haven't provided your workers by setting the \$WORKERS environment variable, using the default ones: $workers"
fi
# Create the first and only master
echo "Creating the master"
create_machine master1
master_ip=$(docker-machine ip master1)
# Initialize the swarm mode on it
echo "Initializing the swarm mode"
machine_do master1 docker swarm init --advertise-addr $master_ip
# Obtain the token to allow workers to join
worker_tkn=$(machine_do master1 docker swarm join-token -q worker)
echo "Worker token: ${worker_tkn}"
# Create and join the workers
for worker in $workers; do
echo "Creating worker ${worker}"
create_machine $worker
machine_do $worker docker swarm join --token $worker_tkn $master_ip:2377
done
}
main $@
```
And make it executable:
```
chmod +x create-cluster.sh
```
### Create the cluster
As the name suggests, well use the script to create the cluster. By default, the script will create a cluster with a single master and two workers. If you want to configure the number of workers, you can do that by setting the WORKERS environment variable.
Now, lets create that cluster!
```
./create-cluster.sh
```
Ok, now you can go out for a coffee. This will take a while.
Finally the cluster is ready!
--------------------------------------------------------------------------------
via: https://blog.codeship.com/monitoring-docker-containers-with-elasticsearch-and-cadvisor/
作者:[Lorenzo Fontana][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://blog.codeship.com/author/lorenzofontana/
[1]: https://github.com/elastic/elasticsearch
[2]: https://github.com/elastic/kibana
[3]: https://github.com/google/cadvisor
[4]: https://github.com/elastic/beats
[5]: https://twitter.com/share?text=%22How+do+you+keep+track+of+all+that%27s+happening+in+a+Swarm+Mode+cluster%3F+Not+easily.%22+via+%40fntlnz&url=https://blog.codeship.com/monitoring-docker-containers-with-elasticsearch-and-cadvisor/
[6]: https://www.elastic.co/guide/en/elasticsearch/guide/2.x/deploy.html
[7]: https://docs.docker.com/machine/install-machine/
[8]: https://cloud.digitalocean.com/settings/api/tokens/new

View File

@ -1,3 +1,4 @@
jiajia9linuxer
The Five Principles of Monitoring Microservices
====

View File

@ -1,86 +0,0 @@
jiajia9linuxer
Down and dirty with Windows Nano Server 2016
====
![](http://images.techhive.com/images/article/2016/04/pokes-fun-at-1164459_1280-100654917-primary.idge.jpg)
>Nano Server is a very fast, powerful tool for remotely administering Windows servers, but you need to know what you're doing
There's been a good deal of talk around the [upcoming Nano version of Windows Server 2016][1], the remote-administered, command-line version designed with private clouds and datacenters in mind. But there's also a big difference between talking about it and getting your hands into it. Let's get into the guts.
Nano has no local login, is 64-bit all the way (applications, tools, and agents), and is fast to set up, update, and restart (for the rare times it needs to restart). It's perfect for compute hosts in or out of a cluster, a storage host, a DNS server, an IIS web server, and any server-hosting applications running in a container or virtual-machine guest operating system.
A Nano Server isn't all that fun to play with: You have to know what you want to accomplish. Otherwise, you'll be looking at a remote PowerShell connection and wondering what you're supposed to do next. But if you know what you want, it's very fast and powerful.
Microsoft has provided a [quick-start guide][2] to setting up Nano Server. Here, I take the boots-on-the-ground approach to show you what it's like in the real world.
First, you have to create a .vhd virtual hard drive file. As you can see in Figure 1, I had a few issues with files not being in the right place. PowerShell errors often indicate a mistyped line, but in this case, I had to keep double-checking where I put the files so that it could use the ISO information (which has to be copied and pasted to the server you want to create the .vhd file on). Once you have everything in place, you should see it go through the process of creating the .vhd file.
![](http://images.techhive.com/images/article/2016/09/nano-server-1-100682371-large.idge.jpg)
>Figure 1: One of the many file path errors I got when trying to run the New-NanoServerImage script. Once I worked out the file-location issues, it went through and created the .vhd file (as shown here).
Next, when you create the VM in Hyper-V using the VM wizard, you need to point to an existing virtual hard disk and point to the new .vhd file you created (Figure 2).
![](http://images.techhive.com/images/article/2016/09/nano-server-2-100682368-large.idge.jpg)
>Figure 2: Connecting to a virtual hard disk (the one you created at the start).
When you start up the Nano server, you may get a memory error depending on how much memory you allocated and how much memory the Hyper-V server has left if you have other VMs running. I had to shut off a few VMs and increase the RAM until it finally started up. That was unexpected -- [Microsoft's Nano system][3] requirements say you can run it with 512MB, although it recommends you give it at least 800MB. (I ended up allocating 8GB after 1GB didn't work; I was impatient, so I didn't try increments in between.)
I finally came to the login screen, then signed in to get the Nano Server Recovery Console (Figure 3), which is essentially Nano server's terminal screen.
![](http://images.techhive.com/images/article/2016/09/nano-server-3-100682369-large.idge.jpg)
>Figure 3: The Nano Server Recovery Console.
Once I was in, I thought I was golden. But in trying to figure out a few details (how to join a domain, how to inject drivers I might not have, how to add roles), I realized that some configuration pieces would have been easier to add when I ran the New-NanoServerImage cmdlet by popping in a few more parameters.
However, once you have the server up and running, there are ways to configure it live. It all starts with a Remote PowerShell connection, as Figure 4 shows.
![](http://images.techhive.com/images/article/2016/09/nano-server-4-100682370-large.idge.jpg)
>Figure 4: Getting information from the Nano Server Recovery Console that you can use to perform a PowerShell Remote connection.
Microsoft provides direction on how to make the connection happen, but after trying four different sites, I found MSDN has the clearest (working) direction on the subject. Figure 5 shows the result.
![](http://images.techhive.com/images/article/2016/09/nano-server-5-100682372-large.idge.jpg)
>Figure 5: Making the remote PowerShell connection to your Nano Server.
Note: Once you've done the remote connection the long way, you can connect more quickly using a single line:
```
Enter-PSSession ComputerName "192.168.0.100"-Credential ~\Administrator.
```
If you knew ahead of time that this server was going to be a DNS server or be part of a compute cluster and so on, you would have added those roles or feature packages when you were creating the .vhd image in the first place. If you're looking to do so after the fact, you'll need to make the remote PowerShell connection, then install the NanoServerPackage and import it. Then you can see which packages you want to deploy using Find-NanoServerPackage (shown in Figure 6).
![](http://images.techhive.com/images/article/2016/09/nano-server-6-100682373-large.idge.jpg)
>Figure 6: Once you have installed and imported the NanoServerPackage, you can find the one you need to get your Nano Server up and running with the roles and features you require.
I tested this out by running the DNS package with the following command: `Install-NanoServerPackage Name Microsoft-NanoServer-DNS-Package`. Once it was installed, I had to enable it with the following command: `Enable-WindowsOptionalFeature Online FeatureName DNS-Server-Full-Role`.
Obviously I didn't know these commands ahead of time. I have never run them before in my life, nor had I ever enabled a DNS role this way, but with a little research I had a DNS (Nano) Server up and running.
The next part of the process involves using PowerShell to configure the DNS server. That's a completely different topic and one best researched online. But it doesn't appear to be mind-blowingly difficult once you've learned the cmdlets to use: Add a zone? Use the Add-DNSServerPrimaryZone cmdlet. Add a record in that zone? Use the Add-DNSServerResourceRecordA. And so on.
After doing all this command-line work, you'll likely want proof that any of this is working. You should be able to do a quick review of PowerShell commands and not the many DNS ones that now present themselves (using Get-Command).
But if you need a GUI-based confirmation, you can open Server Manager on a GUI-based server and add the IP address of the Nano Server. Then right-click that server and choose Manage As to provide your credentials (~\Administrator and password). Once you have connected, right-click the server in Server Manager and choose Add Roles and Features; it should show that you have DNS installed as a role, as Figure 7 shows.
![](http://images.techhive.com/images/article/2016/09/nano-server-7-100682374-large.idge.jpg)
>Figure 7: Proving through the GUI that DNS was installed.
Don't bother trying to remote-desktop into the server. There is only so much you can do through the Server Manager tool, and that isn't one of them. And just because you can confirm the DNS role doesn't mean you have the ability to add new roles and features through the GUI. It's all locked down. Nano Server is how you'll make any needed adjustments.
--------------------------------------------------------------------------------
via: http://www.infoworld.com/article/3119770/windows-server/down-and-dirty-with-windows-nano-server-2016.html?utm_source=webopsweekly&utm_medium=email
作者:[J. Peter Bruzzese ][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.infoworld.com/author/J.-Peter-Bruzzese/
[1]: http://www.infoworld.com/article/3049191/windows-server/nano-server-a-slimmer-slicker-windows-server-core.html
[2]: https://technet.microsoft.com/en-us/windows-server-docs/compute/nano-server/getting-started-with-nano-server
[3]: https://technet.microsoft.com/en-us/windows-server-docs/get-started/system-requirements--and-installation

View File

@ -1,365 +0,0 @@
LinuxBars翻译认领
Server Monitoring with Shinken on Ubuntu 16.04
=====
Shinken is an open source computer and network monitoring framework written in python and compatible with Nagios. Shinken can be used on all operating systems that can run python applications like Linux, Unix, and Windows. Shinken was written by Jean Gabes as proof of concept for a new Nagios architecture, but it was turned down by the Nagios author and became an independent network and system monitoring tool that stays compatible with Nagios.
In this tutorial, I will show you how to install Shinken from source and add a Linux host to the monitoring system. I will use Ubuntu 16.04 Xenial Xerus as the operating system for the Shinken server and monitored host.
### Step 1 - Install Shinken Server
Shinken is a python framework, we can install it with pip or install it from source. In this step, we will install Shinken from source.
There are some tasks that have to be completed before we start installing Shinken.
Install some new python packages and create Linux user with the name "shinken":
```
sudo apt-get install python-setuptools python-pip python-pycurl
useradd -m -s /bin/bash shinken
```
Download the Shinken source from GitHub repository:
```
git clone https://github.com/naparuba/shinken.git
cd shinken/
```
Then install Shinken with the command below:
```
git checkout 2.4.3
python setup.py install
```
Next, for better results, we need to install 'python-cherrypy3' from the ubuntu repository:
```
sudo apt-get install python-cherrypy3
```
Now Shinken is installed, next we add Shinken to start at boot time and start it:
```
update-rc.d shinken defaults
systemctl start shinken
```
### Step 2 - Install Shinken Webui2
Webui2 is the Shinken web interface available from shinken.io. The easiest way to install Sshinken webui2 is by using the shinken CLI command (which has to be executed as shinken user).
Login to the shinken user:
```
su - shinken
```
Initialize the shinken configuration file - The command will create a new configuration .shinken.ini:
```
shinken --init
```
And install webui2 with this shinken CLI command:
```
shinken install webui2
```
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/6.png)
Webui2 is installed, but we need to install MongoDB and another python package with pip. Run command below as root:
```
sudo apt-get install mongodb
pip install pymongo>=3.0.3 requests arrow bottle==0.12.8
```
Next, go to the shinken directory and add the new webui2 module by editing the 'broker-master.cfg' file:
```
cd /etc/shinken/brokers/
vim broker-master.cfg
```
Add a new option inside module on line 40:
```
modules webui2
```
Save the file and exit the editor.
Now go to the contacts directory and edit the file 'admin.cfg' for the admin configuration.
```
cd /etc/shinken/contacts/
vim admin.cfg
```
Change the values shown below:
```
contact_name admin # Username 'admin'
password yourpass # Pass 'mypass'
```
Save and exit.
### Step 3 - Install Nagios-plugins and Shinken Packages
In this step, we will install Nagios-plugins and some Perl module. Then install additional shinken packages from shinken.io to perform the monitoring.
Install Nagios-plugins and cpanminus which is required for building and installing the Perl modules:
```
sudo apt-get install nagios-plugins* cpanminus
```
Install these Perl modules with the cpanm command:
```
cpanm Net::SNMP
cpanm Time::HiRes
cpanm DBI
```
Now create new link for utils.pm file to shinken the directory and create a new directory for Log_File_Health:
```
chmod u+s /usr/lib/nagios/plugins/check_icmp
ln -s /usr/lib/nagios/plugins/utils.pm /var/lib/shinken/libexec/
mkdir -p /var/log/rhosts/
touch /var/log/rhosts/remote-hosts.log
```
Next, install the shinken packages ssh and linux-snmp for monitoring SSH and SNMP sources from shinken.io:
```
su - shinken
shinken install ssh
shinken install linux-snmp
```
### Step 4 - Add a New Linux Host/host-one
We will add a new Linux host that shall be monitored by using an Ubuntu 16.04 server with IP address 192.168.1.121 and hostname 'host-one'.
Connect to the Linux host-one:
```
ssh host1@192.168.1.121
```
Install the snmp and snmpd packages from the Ubuntu repository:
```
sudo apt-get install snmp snmpd
```
Next, edit the configuration file 'snmpd.conf' with vim:
```
vim /etc/snmp/snmpd.conf
```
Comment line 15 and uncomment line 17:
```
#agentAddress udp:127.0.0.1:161
agentAddress udp:161,udp6:[::1]:161
```
Comment line 51 and 53, then add new line configuration below:
```
#rocommunity mypass default -V systemonly
#rocommunity6 mypass default -V systemonly
rocommunity mypass
```
Save and exit.
Now start the snmpd service with the systemctl command:
```
systemctl start snmpd
```
Go to the shinken server and define the new host by creating a new file in the 'hosts' directory.
```
cd /etc/shinken/hosts/
vim host-one.cfg
```
Paste configuration below:
```
define host{
use generic-host,linux-snmp,ssh
contact_groups admins
host_name host-one
address 192.168.1.121
_SNMPCOMMUNITY mypass # SNMP Pass Config on snmpd.conf
}
```
Save and exit.
Edit the SNMP configuration on the Shinken server:
```
vim /etc/shinken/resource.d/snmp.cfg
```
Change 'public' to 'mypass' - must be the same password that you used in the snmpd configuration file on the client host-one.
```
$SNMPCOMMUNITYREAD$=mypass
```
Save and exit.
Now reboot both servers - Shinken server and the monitored Linux host:
```
reboot
```
The new Linux host has been added successfully to the Shinken server.
### Step 5 - Access Shinken Webui2
Visit the Shinken webui2 on port 7677 (replace the IP in the URL with your IP):
```
http://192.168.1.120:7767
```
Log in with user admin and your password (the one that you have set in the admin.cfg configuration file).
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/1.png)
Shinken Dashboard in Webui2.
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/2.png)
Our 2 servers are monitored with Shinken.
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/3.png)
List all services that are monitored with linux-snmp.
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/4.png)
Status of all hosts and services.
![](https://www.howtoforge.com/images/server-monitoring-with-shinken-on-ubuntu-16-04/5.png)
### Step 6 - Common Problems with Shinken
- Problems with the NTP server
When you get this error with NTP.
```
TimeSync - CRITICAL ( NTP CRITICAL: No response from the NTP server)
TimeSync - CRITICAL ( NTP CRITICAL: Offset unknown )
```
To solve this problem, install ntp on all Linux hosts.
```
sudo apt-get install ntp ntpdate
```
Edit the ntp configuration:
```
vim /etc/ntp.conf
```
Comment all the pools and replace it with:
```
#pool 0.ubuntu.pool.ntp.org iburst
#pool 1.ubuntu.pool.ntp.org iburst
#pool 2.ubuntu.pool.ntp.org iburst
#pool 3.ubuntu.pool.ntp.org iburst
pool 0.id.pool.ntp.org
pool 1.asia.pool.ntp.org
pool 0.asia.pool.ntp.org
```
Next, add a new line inside restrict:
```
# Local users may interrogate the ntp server more closely.
restrict 127.0.0.1
restrict 192.168.1.120 #shinken server IP address
restrict ::1
NOTE: 192.168.1.120 is the Shinken server IP address.
```
Save and exit.
Start ntp and check the Shinken dashboard:
```
ntpd
```
- Problem check_netint.pl Not Found
Download the source from the github repository to the shinken lib directory:
```
cd /var/lib/shinken/libexec/
wget https://raw.githubusercontent.com/Sysnove/shinken-plugins/master/check_netint.pl
chmod +x check_netint.pl
chown shinken:shinken check_netint.pl
```
- Problem with NetworkUsage
There is error message:
```
ERROR : Unknown interface eth\d+
```
Check your network interface and edit the linux-snmp template.
On my Ubuntu server, the network interface is 'enp0s8', not eth0, so I got this error.
Edit the linux-snmp template packs with vim:
```
vim /etc/shinken/packs/linux-snmp/templates.cfg
```
Add the network interface to line 24:
```
_NET_IFACES eth\d+|em\d+|enp0s8
```
--------------------------------------------------------------------------------
via: https://www.howtoforge.com/tutorial/server-monitoring-with-shinken-on-ubuntu-16-04/
作者:[Muhammad Arul][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.howtoforge.com/tutorial/server-monitoring-with-shinken-on-ubuntu-16-04/
Save and exit.

View File

@ -1,3 +1,4 @@
jiajia9linuxer
Using Ansible to Provision Vagrant Boxes
====

View File

@ -1,99 +0,0 @@
GHLandy Translating
# 5 REASONS WHY YOU SHOULD BE USING OPENSUSE
[![Reasons why you should use OpenSUSE](https://itsfoss.com/wp-content/uploads/2016/09/why-opensuse-is-best.jpg)](https://itsfoss.com/wp-content/uploads/2016/09/why-opensuse-is-best.jpg)
Most of the desktop Linux users stay in 3 categories: Debian/Ubuntu, Fedora, Arch Linux. But today, Ill give you 5 reasons why you should use openSUSE.
Ive always found [openSUSE](https://www.opensuse.org/) to be a bit different kind of a Linux distro. I dont know, but its just so shiny and charismatic. The green chameleon looks awesome. But thats not the reason why openSUSE is the best or better than other Linux distributions.
Dont misunderstand me. I run so many different distros for different purposes and appreciate the work people behind these distros are doing to make computing a joy. But openSUSE always felt, well, sacred. You feel me?
## 5 REASONS WHY OPENSUSE IS BETTER THAN OTHER LINUX DISTRIBUTIONS
Did I just say that openSUSE is the best Linux distribution? No, I didnt. There is no one best Linux distribution. It is really up to your needs what you find as your soulmate.
But here, I am going to list 5 things that I have found that openSUSE does better than other Linux distros. Lets see them.
### #1 COMMUNITY RULES
openSUSE is a great symbol of community driven projects. I have seen a lot of users complain about changes made by the developers in their favorite distro after an update. But not openSUSE. openSUSE is truly community driven and gives its users what they want. Everytime.
### #2 ROCK SOLID OS
Another thing is OS integrity. I can install almost all of the [best Linux desktop environments](https://itsfoss.com/best-linux-desktop-environments/) on the same openSUSE installation which is not possible even on Ubuntu without compromising the stability of the system. This clearly shows how robust the system is. Therefore, openSUSE should appeal to the users wholl be tinkering a lot under the hood.
### #3 EASY TO INSTALL SOFTWARE
We do have lots of awesome package managers in Linux world. From Debian apt-get to the DNF of [Fedora](https://itsfoss.com/fedora-24-review/), all do appeal to the users and sometimes play a great role in attracting users to a particular distro.
openSUSE has again brought a great software delivery method to the table. [software.opensuse.org](https://software.opensuse.org/421/en) is a web-portal that you can use to install software from the repository. All you need to do is to go to the link (on your openSUSE OS of course), use the search box to find your desired software. Click “Direct Install”. Done. Thats all.
Sounds like using Google PlayStore, aint it?
### #4 YAST
[YaST](https://en.opensuse.org/Portal:YaST) is literally the best control center ANY OS in the world has ever had. No arguments there. You can control everything. Networking, Software Update, all the basic settings. Everything. YaST gives you absolute power over your openSUSE installation, be it the enterprise edition or the personal installation. Convenient and everything at one place.
### #5 EXCELLENT OUT OF THE BOX EXPERIENCE
SUSE team is one of the biggest contributors to the Linux kernel. This diligent effort also means that they have excellent support for various hardware.
With such good hardware support, comes great out-of-the-box experience.
### #6 THEY MAKE GREAT PARODY VIDEOS
Wait! There were five reasons that made openSUSE awesome, right?
But I am forced to write it as [Abhishek](https://itsfoss.com/author/abhishek/) wants to me add that openSUSE is the best because they make great Linux parody videos :)
Just kidding but do check out the super awesome [Uptime Funk](https://www.youtube.com/watch?v=zbABy9ul11I)and you would know [why SUSE is the coolest Linux](https://itsfoss.com/suse-coolest-linux-enterprise/).
## LEAP OR TUMBLEWEED? WHICH OPENSUSE SHOULD I USE?
Now if I have convinced you to use openSUSE, let me tell you about the choices you have when it comes to openSUSE. openSUSE comes in two Distributions. The Leap and the Tumbleweed.
![Choice](https://itsfoss.com/wp-content/uploads/2016/09/Untitled-design-2.jpg)
Now although both offer a similar experience and a similar environment, There is a decision You must make before choosing which one of these two to imprint on Your hard disk.
## OPENSUSE : LEAP
[openSUSE Leap](https://en.opensuse.org/Portal:Leap) is for most people. It has a release cycle of 8 months which is followed orthodoxly. Currently, we have openSUSE 42.1\. It contains all the stable packages and provides the smoothest experience of the two.
It is highly suitable for Home, Office and for Business computers. It is for people who need a good OS but wont/cant keep pampering the OS and need it to move aside and let them work. Once setup, you need not worry about anything and focus on your productivity. I also highly recommend Leap for use in libraries and schools.
## OPENSUSE: TUMBLEWEED
The [Tumbleweed version of openSUSE](https://en.opensuse.org/Portal:Tumbleweed) is a rolling release. It very regularly gets updates and always contains the newest set of software running on it. It is recommended for developers, advanced users who want the newest of everything on their system and anybody who wants to contribute to openSUSE.
Let me clarify one thing, though. Tumbleweed is in no way a beta/testing release to the Leap. It is the most bleeding edge stable Linux distro available.
Tumbleweed gives you the fastest updates, but only after the developers assure for the packages stability.
### YOUR SAY?
[](https://itsfoss.com/install-antergos-linux/)[](https://itsfoss.com/linux-national-os/)
Let us know in the comments below what you think of openSUSE? And if you already thinking of using openSUSE, which of the two version would you prefer: Leap or Tumbleweed? Cheers :)
--------------------------------------------------------------------------------
via: https://itsfoss.com/why-use-opensuse/?utm_source=newsletter&utm_medium=email&utm_campaign=5_reasons_why_you_should_use_opensuse_and_other_linux_stories&utm_term=2016-09-19
作者:[Aquil Roshan][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/aquil/

View File

@ -1,60 +0,0 @@
发行版分发者应该禁用 IPv4 映射的 IPv6 地址吗
=============================================
大家都说,互联网向 IPv6 的过渡是件很缓慢的事情。不过在最近几年,可能是由于 IPv4 地址资源的枯竭IPv6 的使用处于[上升态势][1]。相应的,开发者也有兴趣确保软件能在 IPv4 和 IPv6 下工作。但是,正如近期 OpenBSD 邮件列表的讨论所关注的,一个使得向 IPv6 转换更加轻松的机制设计同时也可能导致网络更不安全——并且 Linux 发行版们的默认配置可能并不安全。
### 地址映射
IPv6 在很多方面看起来可能很像 IPv4但它是带有不同地址空间的不同的协议。服务器程序想要接受使用二者之中任意一个协议的连接必须给两个不同的地址族分别打开一个套接字——IPv4 的 AF_INET 和 IPv6 的 AF_INET6。特别是一个程序希望接受使用任意协议到任意主机接口的连接的话需要创建一个绑定到全零通配符地址0.0.0.0)的 AF_INET 套接字和一个绑定到 IPv6 等效地址(写作“::”)的 AF_INET6 套接字。它必须在两个套接字上都监听连接——或者有人会这么认为。
多年前,在 [RFC 3493][2]IETF 指定了一个机制,程序可以使用一个单独的 IPv6 套接字工作在两个协议之上。有了一个启用这个行为的套接字,程序只需要绑定到 :: 来接受使用这两个协议到达所有接口的连接。当创建了一个 IPv4 连接到绑定端口,源地址会像 [RFC 2373][3] 中描述的那样映射到 IPv6。所以举个例子一个使用了这个模式的程序会将一个 192.168.1.1 的传入连接看作来自 ::ffff:192.168.1.1(这个混合的写法就是这种地址通常的写法)。程序也能通过相同的映射方法打开一个到 IPv4 地址的连接。
RFC 要求这个行为要默认实现所以大多数系统这么做了。不过也有些例外OpenBSD 就是其中之一;在那里,希望在两种协议下工作的程序能做的只能是创建两个独立的套接字。但一个在 Linux 中打开两个套接字的程序会遇到麻烦IPv4 和 IPv6 套接字都会尝试绑定到 IPv4 地址,所以不论是哪个后者都会失败。换句话说,一个绑定到 :: 指定端口的套接字的程序会同时绑定到 IPv6 :: 和 IPv4 0.0.0.0 地址的那个端口上。如果程序之后尝试绑定一个 IPv4 套接字到 0.0.0.0 的相同端口上时,这个操作会失败,因为这个端口已经被绑定了。
当然有个办法可以解决这个问题;程序可以调用 setsockopt() 来打开 IPV6_V6ONLY 选项。一个打开两个套接字并且设置了 IPV6_V6ONLY 的程序应该可以在所有的系统间移植。
读者们可能对不是每个程序都能正确处理这一问题没那么震惊。事实证明这些程序的其中之一是网络时间协议Network Time Protocol的 [OpenNTPD][4] 实现。Brent Cook 最近给上游 OpenNTPD 源码[提交了一个小补丁][5],添加了必要的 setsockopt() 调用,它也被提交到了 OpenBSD 中了。尽管那个补丁看起来不大可能被接受,最可能是因为 OpenBSD 式的理由LCTT 译注如前文提到的OpenBSD 并不受这个问题的影响)。
### 安全担忧
正如上文所提到OpenBSD 根本不支持 IPv4 映射的 IPv6 套接字。即使一个程序试着通过将 IPV6_V6ONLY 选项设置为 0 显式地启用地址映射,它的作者会感到沮丧,因为这个设置在 OpenBSD 系统中无效。这个决定背后的原因是这个映射带来了一些安全担忧。攻击打开接口的攻击类型有很多种,但它们最后都会回到规定的两个途径到达相同的端口,每个端口都有它自己的控制规则。
任何给定的服务器系统可能都设置了防火墙规则,描述端口的允许访问权限。也许还会有适当的机制,比如 TCP wrappers 或一个基于 BPF 的过滤器,或一个网络上的路由可以做连接状态协议过滤。结果可能是导致防火墙保护和潜在的所有类型的混乱连接之间的缺口导致同一 IPv4 地址可以通过两个不同的协议到达。如果地址映射是在网络边界完成的,情况甚至会变得更加复杂;参看[这个 2003 年的 RFC 草案][6],它描述了如果映射地址在主机之间传送,一些随之而来的其它攻击场景。
改变系统和软件合适地处理 IPv4 映射的 IPv6 地址当然可以实现。但那增加了系统的整体复杂度,并且可以确定这个改动没有实际完整实现到它应该实现的范围内。如同 Theo de Raadt [说的][7]
**有时候人们将一个坏主意放进了 RFC。之后他们发现不可能将这个主意扔回垃圾箱了。结果就是概念变得如此复杂每个人都得在管理和编码方面是个全职专家。**
我们也根本不清楚这些全职专家有多少在实际配置使用 IPv4 映射的 IPv6 地址的系统和网络。
有人可能会说,尽管 IPv4 映射的 IPv6 地址造成了安全危险,更改一下程序让它关闭部署实现它的系统上的地址映射应该没什么危害。但 Theo 认为不应该这么做,有两个理由。第一个是有许多破损的程序,它们永远不会被修复。但实际的原因是给发行版分发者压力去默认关闭地址映射。正如他说的:“**最终有人会理解这个危害是系统性的并更改系统默认行为使之secure by default**。”
### Linux 上的地址映射
在 Linux 系统,地址映射由一个叫做 net.ipv6.bindv6only 的 sysctl 开关控制;它默认设置为 0启用地址映射。管理员或发行版分发者可以通过将它设置为 1 关闭地址映射但在部署这样一个系统到生产环境之前最好确认软件都能正常工作。一个快速调查显示没有哪个主要发行版分发者改变这个默认值Debian 在 2009 年的 “squeeze” 中[改变了这个默认值][9],但这个改动破坏了足够多的软件包(比如[任何包含 Java 的][10][在经过了一定数量的 Debian 式讨论之后][11],它恢复到了原来的设置。看上去不少程序依赖于默认启用地址映射。
OpenBSD 有自由以“secure by default”的名义打破其核心系统之外的东西Linux 发行版分发者倾向于更难以作出这样的改变。所以那些一般不愿意收到他们用户的不满的发行版分发者,不太可能很快对 bindv6only 的默认设置作出改变。好消息是这个功能作为默认已经很多年了,但很难找到利用的例子。但是,正如我们都知道的,谁都无法保证这样的利用不可能发生。
--------------------------------------------------------------------------------
via: https://lwn.net/Articles/688462/
作者:[Jonathan Corbet][a]
译者:[alim0x](https://github.com/alim0x)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://lwn.net/
[1]: https://www.google.com/intl/en/ipv6/statistics.html
[2]: https://tools.ietf.org/html/rfc3493#section-3.7
[3]: https://tools.ietf.org/html/rfc2373#page-10
[4]: https://github.com/openntpd-portable/
[5]: https://lwn.net/Articles/688464/
[6]: https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
[7]: https://lwn.net/Articles/688465/
[8]: https://lwn.net/Articles/688466/
[9]: https://lists.debian.org/debian-devel/2009/10/msg00541.html
[10]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=560056
[11]: https://lists.debian.org/debian-devel/2010/04/msg00099.html

View File

@ -1,78 +0,0 @@
Instagram Web 服务效率与 Python
===============================================
Instagram 目前是世界上最大规模部署 Django web 框架(该框架完全使用 Python 编写)的主角。我们最初选用 Python 是因为它久负盛名的简洁性与实用性这非常符合我们的哲学思想——“先做简单的事情”。但简洁性也会带来效率方面的折衷。Instagram 的规模在过去两年中已经翻番,并且最近已突破 5 亿用户,所以急需最大程度地提升 web 服务效率以便我们的平台能够继续顺利地扩大。在过去的一年我们已经将效率计划efficiency program提上日程并在过去的六个月我们已经能够做到无需向我们的 Django 层Django tiers添加新的容量来维护我们的用户增长。我们将在本文分享一些由我们构建的工具以及如何使用它们来优化我们的日常部署流程。
### 为何需要提升效率?
Instagram正如所有的软件受限于像服务器和数据中心能源这样的样物理限制。鉴于这些限制在我们的效率计划中有两个我们希望实现的主要目标
1. Instagram 应当能够利用持续代码发布提供正常地通信服务,防止因为自然灾害、区域性网络问题等造成某一个数据中心区丢失。
2. Instagram 应当能够自由地滚动发布新产品和新功能,不必因容量而受阻。
想要实现这些目标我们意识到我们需要持续不断地监控我们的系统并在战斗中回归battle regression
### 定义效率
Web 服务器的瓶颈通常在于每台服务器上可用的 CPU 时间。在这种环境下,效率就意味着利用相同的 CPU 资源完成更多的任务也就是说每秒处理更多的用户请求requests per second, RPS。当我们寻找优化方法时我们面临的第一个最大的挑战就是尝试量化我们当前的效率。到目前为止我们一直在使用“每次请求的平均 CPU 时间”来评估效率,但使用这种指标也有其固有限制:
1. 设备多样性。使用 CPU 时间来测量 CPU 资源并非理想方案,因为它同时受到 CPU 模型与 CPU 负载影响。
1. 请求影响数据。测量每次请求的 CPU 资源并非理想方案因为在使用每次请求测量per-request measurement方案时添加或移除轻量级或重量级的请求也会影响到效率指标。
相对于 CPU 时间来说CPU 指令是一种更好的指标,因为对于相同的请求,它会报告相同的数字,不管 CPU 模型和 CPU 负载情况如何。我们选择使用了一种叫做”每个活动用户per active user“的指标而不是将我们所有的数据链接到每个用户请求上。我们最终采用”每个活动用户在高峰期间的 CPU 指令CPU instruction per active user during peak minute“来测量效率。我们建立好新的度量标准后下一步就是通过对 Django 的分析来学习更多关于我们的回归our regressions
### Django 服务分析
通过分析我们的 Django web 服务,我们希望回答两个主要问题:
1. 一次 CPU 回归会发生吗?
2. 是什么导致了 CPU 回归问题发生以及我们该怎样修复它?
想要回答第一个问题,我们需要追踪”每个活动用户的 CPU 指令CPU-instruction-per-active-user“指标。如果该指标增加我们就知道一次 CPU 回归已经发生了。
我们为此构建的工具叫做 Dynostats。Dynostats 利用 Django 中间件以一定的速率采样用户请求,记录键效率以及性能指标,例如 CPU 总指令数、端到端请求时延、花费在访问内存缓存memcache和数据库服务的时间等。另一方面每个请求都有很多可用于聚合的元数据metadata例如端点名称、HTTP 请求返回码、服务该请求的服务器名称以及请求中最新提交的哈希值hash。对于单个请求记录来说有两个方面非常强大因为我们可以在不同的维度上进行切割那将帮助我们减少任何导致 CPU 回归的原因。例如,我们可以根据他们的端点名称聚合所有请求,正如下面的时间序列图所示,从图中可以清晰地看出在特定端点上是否发生了回归。
![](https://d262ilb51hltx0.cloudfront.net/max/800/1*3iouYiAchYBwzF-v0bALMw.png)
CPU 指令对测量效率很重要——当然它们也很难获得。Python 并没有支持直接访问 CPU 硬件计数器CPU 硬件计数器是指可编程 CPU 寄存器,用于测量性能指标,例如 CPU 指令的公共库。另一方面Linux 内核提供了 `perf_event_open` 系统调用。通过 Python ctypes 桥接技术能够让我们调用标准 C 库编写的系统调用函数,它也为我们提供了兼容 C 的数据类型,从而可以编程硬件计数器并从它们读取数据。
使用 Dynostats我们已经可以找出 CPU 回归,并探究 CPU 回归发生的原因,例如哪个端点受到的影响最多,谁提交了真正会导致 CPU 回归的变更等。然而,当开发者收到他们的变更已经导致一次 CPU 回归发生的通知时,他们通常难以找出问题所在。如果问题很明显,那么回归可能就不会一开始就被提交!
这就是为何我们需要一个 Python 分析器,从而使开发者能够使用它找出回归(一旦 Dynostats 发现了它)发生的根本原因。不同于白手起家,我们决定对一个现成的 Python 分析器 cProfile 做适当的修改。cProfile 模块通常会提供一个统计集合来描述程序不同的部分执行时间和执行频率。我们将 cProfile 的定时器timer替换成了一个从硬件计数器读取的 CPU 指令计数器,以此取代对时间的测量。我们在采样请求后产生数据并把数据发送到数据流水线。我们也会发送一些我们在 Dynostats 所拥有的类似元数据,例如服务器名称、集群、区域、端点名称等。
在数据流水线的另一边我们创建了一个消费数据的尾随者tailer。尾随者的主要功能是解析 cProfile 的统计数据并创建能够表示 Python 函数级别的 CPU 指令的实体。如此,我们能够通过 Python 函数来聚集 CPU 指令,从而更加方便地找出是什么函数导致了 CPU 回归。
### 监控与警报机制
在 Instagram我们 [每天部署 30-50 次后端服务][1]。这些部署中的任何一个都能发生 CPU 回归的问题。因为每次发生通常都包含至少一个区别diff所以找出任何回归是很容易的。我们的效率监控机制包含在每次发布前后都会在 Dynostats 中哦了过扫描 CPU 指令,并且当变更超出某个阈值时发出警告。对于长期会发生 CPU 回归的情况,我们也有一个探测器为负载最繁重的端点提供日常和每周的变更扫描。
部署新的变更并非触发一次 CPU 回归的唯一情况。在许多情况下新的功能和新的代码路径都由全局环境变量global environment variables, GEV控制。 在一个计划好的时间表上,给一个用户子集发布新功能有一些非常一般的实践。我们在 Dynostats 和 cProfile 统计数据中为每个请求添加了这个信息作为额外的元数据字段。来自这些字段的组请求通过转变全局环境变量GEV从而暴露出可能的 CPU 回归问题。这让我们能够在它们对性能造成影响前就捕获到 CPU 回归。
### 接下来是什么?
Dynostats 和我们定制的 cProfile以及我们建立去支持它们的监控和警报机制能够有效地找出大多数导致 CPU 回归的元凶。这些进展已经帮助我们恢复了超过 50% 的不必要的 CPU 回归,否则我们就根本不会知道。
我们仍然还有一些可以提升的方面并可以更加便捷将它们地加入到 Instagram 的日常部署流程中:
1. CPU 指令指标应该要比其它指标如 CPU 时间更加稳定但我们仍然观察了让我们头疼的差异。保持信号“信噪比noise ratio”合理地低是非常重要的这样开发者们就可以集中于真实的回归上。这可以通过引入置信区间confidence intervals的概念来提升并在信噪比过高时发出警报。针对不同的端点变化的阈值也可以设置为不同值。
2. 通过更改 GEV 来探测 CPU 回归的一个限制就是我们要在 Dynostats 中手动启用这些比较的日志输出。当 GEV 逐渐增加,越来越多的功能被开发出来,这就不便于扩展了。
作为替代,我们能够利用一个自动化框架来调度这些比较的日志输出,并对所有的 GEV 进行遍历,然后当检查到回归时就发出警告。
3. cProfile 需要一些增强以便更好地处理装饰器函数以及它们的子函数。
鉴于我们在为 Instagram 的 web 服务构建效率框架中所投入的工作,所以我们对于将来使用 Python 继续扩展我们的服务很有信心。
我们也开始向 Python 语言自身投入更多,并且开始探索从 Python 2 转移 Python 3 之道。我们将会继续探索并做更多的实验以继续提升基础设施与开发者效率,我们期待着很快能够分享更多的经验。
--------------------------------------------------------------------------------
via: https://engineering.instagram.com/web-service-efficiency-at-instagram-with-python-4976d078e366#.tiakuoi4p
作者:[Min Ni][a]
译者:[ChrisLeeGit](https://github.com/chrisleegit)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://engineering.instagram.com/@InstagramEng?source=post_header_lockup
[1]: https://engineering.instagram.com/continuous-deployment-at-instagram-1e18548f01d1#.p5adp7kcz

View File

@ -0,0 +1,315 @@
# 如何运用Python建立你的第一个Slack Bot
[Bots](https://www.fullstackpython.com/bots.html) 是一种像 [Slack](https://slack.com/) 一样实用的互动聊天服务方式. 如果你之前从来没有建立过bot, 这篇文章提供了一个简单的用Python建立你第一个bot的关于 [Slack API](https://api.slack.com/) 集合的入门教程.
我们通过设置你的开发环境, 获得一个Slack API bot标记和我们用Pyhon编码的简单bot.
### 我们所需的工具
我们的bot, 我们将它称作为 "StarterBot", 它需要 Python 和 the Slack API. 然后运行我们需要的Python代码:
* [Python 2 或者 Python 3](https://www.fullstackpython.com/python-2-or-3.html)
* [pip](https://pip.pypa.io/en/stable/) 和 [virtualenv](https://virtualenv.pypa.io/en/stable/) 处理 Python [应用程序依赖关系](https://www.fullstackpython.com/application-dependencies.html)
* 一个你可以拥有API访问和注册Slack Developer Hangout team](http://dev4slack.xoxco.com/)的[免费Slack账号](https://slack.com/)
* 通过Slack团队建立的官方Python [Slack客户端](https://github.com/slackhq/python-slackclient)代码库
* [Slack API 测试标志](https://api.slack.com/tokens)
这也是一个方便你建立本教程的有用[Slack API 文档](https://api.slack.com/)
对于本教程,所有的代码都是在[slack-starterbot](https://github.com/mattmakai/slack-starterbot)公共库里通过MIT许可证的可获得的开放源码.
### 搭建我们的环境
我们现在已经知道我们的项目需要什么样的工具因此我们要获得我们所建立的开发环境。首先到终端上或者用Windows上的命令提示符并且改变你想要存储这个项目的目录。在那个目录里创建一个新的virtualenv以便从其他的Python项目来隔离我们的应用程序依赖关系。
```
virtualenv starterbot
```
Activate the virtualenv 激活virtualenv:
```
source starterbot/bin/activate
```
你的提示现在应该看起来像在一个这样的截图里。
![Command prompt with starterbot's virtualenv activated 已经激活的starterbot's virtualenv的命令提示:](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/virtualenv-activate.png)
这个官方的slackclient API帮助库是通过Slack可以发送和接收消息的Slack通道所建立的。安装slackclient库是通过这个pip命令:
```
pip install slackclient
```
当pip命令完成时你应该看到这样的输出和你将返回的提示.
![Output from using the pip install slackclient command with a virtualenv activated 在已经激活的virtualenv输出用pip安装slackclient的命令.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/pip-install-slackclient.png)
我们也需要从Slack项目获得一个访问提示因此我们的bot可以用它来连接这个Slack API.
### Slack实时消息传递RTMAPI
Slack同意程序通过一个 [网络应用程序API](https://www.fullstackpython.com/application-programming-interfaces.html)访问他们的消息传递通道. 去这个[Slack网络应用程序API页面](https://api.slack.com/) 并且注册建立你自己的Slack项目.你也可以通过一个你拥有管理权限的有效账号登陆.
![Use the sign in button on the top right corner of the Slack API page 在网络应用程序API页面的右上角使用登陆按钮.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/sign-in-slack.png)
然后你可以到[Bot用户页面](https://api.slack.com/bot-users)登陆.
![Custom bot users webpage 定制bot用户网页.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/custom-bot-users.png)
给你的bot起名为 "starterbot" 然后点击 “Add bot integration” 按钮.
![Add a bot integration named starterbot 添加一个bot integration并起名为“starterbot”.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/starterbot.jpg)
这个页面将重新加载你将看到一个新生成的访问令牌。你还可以将标志改成自定义设计。例如我给的这个“Full Stack Python”标志.
![Copy and paste the access token for your new Slack bot为你的新Slack bot复制和粘贴访问提示.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/slack-token.png)
在页面底部点击 "Save Integration"按钮. 你的 bot 现在已经准备好连接Slack's API.
Python开发人员的一个常见的做法是输出秘密令牌提示作为环境变量。输出的Slack令牌名字为“SLACK_BOT_TOKEN”.:
```
export SLACK_BOT_TOKEN='your slack token pasted here'
```
好了我们现在将被作为bot授权使用这个Slack API .
这个是一个更多的我们需要建立我们的bot的信息: 我们的bot的ID. 接下来我们将会写一个简短的脚本来从这个Slack API获得ID.
### 获得我们Bot的ID
这是最后一次写的一些Python代码! 我们将会在编译一个简短的Python脚本来获得StarterBot的ID时获得热身. 这个ID基于Slack项目而改变.
我们需要ID因为当消息被解析为从Slcak RTM在StarterBot上指导的他会允许我们的应用程序作出终止.我们的脚本也会测试我们SLACK_BOT_TOKEN环境变量是否设置正确.
建立一个新文件并命名为print_bot_id.py 并且填写下面的代码.
```
import os调用外部程序
from slackclient import SlackClient从slackclient调用SlackClient
BOT_NAME = 'starterbot'
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
if __name__ == "__main__":
api_call = slack_client.api_call("users.list")
if api_call.get('ok'):
# retrieve all users so we can find our bot检索所有的用户以便我们可以找到我们的bot
users = api_call.get('members')
for user in users:
if 'name' in user and user.get('name') == BOT_NAME:
print("Bot ID for '" + user['name'] + "' is " + user.get('id'))
else:
print("could not find bot user with the name " + BOT_NAME)
```
当我们设置为一个环境变量时我们的代码调用于SlackClient并且为我们的SLACK_BOT_TOKEN而将它实例化. 当脚本通过pyhon命令执行时我们通过会访问Slack API列出所有的Slack用户并且获得匹配一个名字为"satrterbot"的ID.
我们仅仅需要运行一次脚本来获得我们bot的ID.
```
python print_bot_id.py
```
当它运行为我们提供我们bot的ID时脚本会打印出简单的一行输出.
![在你的Slack项目中用Python脚本打印Slack bot的ID.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/printed-bot-id.png)
复制脚本打印出的唯一ID.并将ID作为一个环境变量命名为BOT_ID输出.
```
(starterbot)$ export BOT_ID='bot id returned by script'
```
这个脚本仅仅需要运行一次来获得bot的ID. 我们现在可以使用这个ID在我们的Python应用程序中来运行StarterBot.
### 编码我们的StarterBot
我们通过我们拥有的一切来写我们需要书写的StarterBot代码. 创建一个新文件命名为starterbot.py ,它包括以下代码.
```
import os
import time
from slackclient import SlackClient
```
操作系统和SlackClient调用将会看起来很熟悉因为我们会使用它们在theprint_bot_id.py中.
在我们的依赖关系调用中我们可以使用它们获得环境变量值并且在Slack client中将它们实例化.
```
# starterbot's ID as an environment variable starterbot的ID作为一个环境变量
BOT_ID = os.environ.get("BOT_ID")
# constants 常量
AT_BOT = "<@" + BOT_ID + ">:"
EXAMPLE_COMMAND = "do"
# instantiate Slack & Twilio clients 实例化Slack和Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
```
代码在我们的SLACK_BOT_TOKEN中将SlackClient client实例化并且作为一个环境变量输出.
```
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose 从firehose阅读间延迟1秒
if slack_client.rtm_connect():
print("StarterBot connected and running!")
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")
```
Slack client连接到Slack RTM API WebSocketSlack RTM API 双向通信然后当解析信息来自firehose时会不断循环.如果任何这些消息都指向StarterBot那么一个被称作handle_command的函数会决定做什么.
接下来添加两个函数来解析Slack输出和handle commands.
```
def handle_command(command, channel):
"""
Receives commands directed at the bot and determines if they
are valid commands. If so, then acts on the commands. If not,
returns back what it needs for clarification.
"""
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
"* command with numbers, delimited by spaces."
if command.startswith(EXAMPLE_COMMAND):
response = "Sure...write some more code then I can do that!"
slack_client.api_call("chat.postMessage", channel=channel,
text=response, as_user=True)
def parse_slack_output(slack_rtm_output):
"""
The Slack Real Time Messaging API is an events firehose.
this parsing function returns None unless a message is
directed at the Bot, based on its ID.
"""
output_list = slack_rtm_output
if output_list and len(output_list) > 0:
for output in output_list:
if output and 'text' in output and AT_BOT in output['text']:
# return text after the @ mention, whitespace removed 在@之后提到返回文本,空格删除
return output['text'].split(AT_BOT)[1].strip().lower(), \
output['channel']
return None, None
```
parse_slack_output函数从Slack接受信息并且如果他们指向我们的StarterBot时会作出判断.消息通过给我们bot的ID一个直接命令启动然后交由我们的代码处理.-目前只是通过SLack管道发布一个消息回去告诉用户去多写一些Python代码!
这是整个程序看上去应该如何组合在一起 (你也可以 [在GitHub中查看文件](https://github.com/mattmakai/slack-starterbot/blob/master/starterbot.py)):
```
import os
import time
from slackclient import SlackClient
# 把 starterbot 的 ID作为一个环境变量
BOT_ID = os.environ.get("BOT_ID")
# constants 常量
AT_BOT = "<@" + BOT_ID + ">:"
EXAMPLE_COMMAND = "do"
# 实例化Slack和Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
def handle_command(command, channel):
"""
Receives commands directed at the bot and determines if they
are valid commands. If so, then acts on the commands. If not,
returns back what it needs for clarification.
"""
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
"* command with numbers, delimited by spaces."
if command.startswith(EXAMPLE_COMMAND):
response = "Sure...write some more code then I can do that!"
slack_client.api_call("chat.postMessage", channel=channel,
text=response, as_user=True)
def parse_slack_output(slack_rtm_output):
"""
The Slack Real Time Messaging API is an events firehose.
this parsing function returns None unless a message is
directed at the Bot, based on its ID.
"""
output_list = slack_rtm_output
if output_list and len(output_list) > 0:
for output in output_list:
if output and 'text' in output and AT_BOT in output['text']:
# 在@之后提到返回文本,空格删除
return output['text'].split(AT_BOT)[1].strip().lower(), \
output['channel']
return None, None
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print("StarterBot connected and running!")
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")
```
现在这是我们在这里所有的在命令行上通过python starterbot.py可以启动我们StarterBot的代码.
![当StarterBot开始运行而且连接到API的输出通道.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/starterbot-running.png)
在 Slack 中创建新管道并且把 StarterBot 添加进来,或者直接把 StarterBot 添加进一个已经存在的管道。
![在Slack界面创建一个新通道并且请求StarterBot.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/create-channel.png)
现在在管道中启动 StarterBot。
![在你的Slack通道里给的StarterBot命令.](https://www.fullstackpython.com/source/static/img/160604-simple-python-slack-bot/working-starterbot.png)
当你从bot得到的响应中遇见问题时这是你一种可能你想去做的修改.正如上面所写的这个教程其中一行AT_BOT = "<@" + BOT_ID + ">:",在"@starter"后需要一个冒号或者任何你自己所命名的特定bot.移除这些从AT_BOT结束后的字符串.Slack clients似乎需要在@一个人名后加一个冒号,但这好像是有些不协调的.
### 结束
好吧你现在已经获得一个简易的你可以在代码中很多地方加入你想创建任何特性的StarterBot.
这里有很多你可以使用的Slack RTM API 和 Python.看看通过这些文章你还可以学习到什么:
* 附加一个持久的[relational database 关系数据库](https://www.fullstackpython.com/databases.html) 或者 [NoSQL back-end](https://www.fullstackpython.com/no-sql-datastore.html) 比如 [PostgreSQL](https://www.fullstackpython.com/postgresql.html),[MySQL](https://www.fullstackpython.com/mysql.html) 或者 [SQLite](https://www.fullstackpython.com/sqlite.html) 用来保存和检索用户数据
* 添加另外一个与bot互动的通道 [via SMS](https://www.twilio.com/blog/2016/05/build-sms-slack-bot-python.html) 或者 [phone calls](https://www.twilio.com/blog/2016/05/add-phone-calling-slack-python.html)
* [Integrate other web APIs](https://www.fullstackpython.com/api-integration.html) 比如 [GitHub](https://developer.github.com/v3/), [Twilio](https://www.twilio.com/docs) 或者 [api.ai](https://docs.api.ai/)
有问题? 通过Twitter联系我 [@fullstackpython](https://twitter.com/fullstackpython) or [@mattmakai](https://twitter.com/mattmakai). 这是我在GitHub上的用户名 [mattmakai](https://github.com/mattmakai).
这篇文章还有问题? Fork [this page's source on GitHub 这是在GitHub上的页面源](https://github.com/mattmakai/fullstackpython.com/blob/gh-pages/source/content/posts/160604-build-first-slack-bot-python.markdown).
--------------------------------------------------------------------------------
via: https://www.fullstackpython.com/blog/build-first-slack-bot-python.html
作者: [Matt Makai][a]
译者:[jiajia9llinuxer](https://github.com/jiajia9linuxer)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出aa
[a]: https://www.fullstackpython.com/about-author.html

View File

@ -1,140 +0,0 @@
你必须了解的 Linux 基础网络命令
==================================================
![](https://itsfoss.com/wp-content/uploads/2016/06/Basic-Networking-Commands-Linux.jpg)
摘要:有抱负的 Linux 系统管理员和 Linux 狂热者必须知道的最重要而且基础的 Linux 网络命令合集。
在 Its FOSS 我们并非每天都谈论 Linux 的“命令行方面”。基本上,我更专注于 Linux 的桌面端。但你们读者中的一些人在内部调查(仅面向 It's FOSS newsletter 订阅者)中指出,你们也想学些命令行技巧。速查表也受大部分读者所喜欢和支持。
为此,我编辑了一个 Linux 中基础网络命令的列表。它并不是一个教你如何使用这些命令的教程,而是一个命令合集和他们的简短解释。所以,如果你已经使用过这些命令,你可以用它来快速记住命令。
你可以把这个网页添加为书签以便快速查阅,或下载这些命令的 PDF 版本以便离线使用。
当我还是通信系统工程专业的学生的时候我就有这个 Linux 网络命令的列表了。它帮助我在计算机网络课程获得了高分。希望它也能以同样的方式帮助你。
> 独家内容:[下载 Linux 网络命令速查表][1] 以便将来查阅。你可以打印或保存它以便离线查看。
### Linux 基础网络命令列表
我在计算机网络课程上使用 FreeBSD不过这些 UNIX 命令应该也能在 Linux 上同样工作。
#### 连通性
- __ping <host\>__:发送 ICMP echo 消息(一个包)到主机。这可能会不停地发送直到你按下 Control-C。Ping 通意味着一个包从你的机器通过 ICMP 发送出去,并在 IP 层回显。Ping 告诉你另一个主机是否在运行。
- __telnet <host\> [port]__:与主机在指定的端口通信。默认的 telnet 端口是 23。其它一些常用的端口是
7 —— echo 端口
25 —— SMTP用于发送邮件
79 —— Finger译注[维基百科 - Finger protocal](https://en.wikipedia.org/wiki/Finger_protocol)),提供该网络下其它用户的信息
按 Control-] 以退出 telnet。
#### ARP
ARP 用于将 IP 地址转换为以太网地址。Root 用户可以添加和删除 ARP 记录。当 ARP 记录被污染或者错误时删除他们会有用。Root 显式添加的 ARP 记录是永久的 —— 代理设置的也是。ARP 表保存在内核中动态地被操作。ARP 记录会被缓存,通常在 20 分钟后失效并被删除。
- __arp -a__:打印 ARP 表
- __arp -s <ip_address\> <mac_address\> [pub]__:添加一条记录到表中
- __arp -a -d__:删除 ARP 表中的所有记录
#### 路由
- __netstat -r__:打印路由表。路由表保存在内核中,用于 IP 层路由包到非本地网络。
- __route add__route 命令用于向路由表添加静态(手动输入而非动态)路由路径。所有从该 PC 到那个 IP/子网的流量都会经由指定的网关 IP。它也可以用来设置一个默认路由。例如在 IP/子网处使用 0.0.0.0,就可以发送所有包到特定的网关。
- __routed__:控制动态路由的 BSD 守护程序。开机时启动。它运行 RIP 路由协议。只有 root 用户可用。没有 root 权限你不能运行它。
- __gated__gated 是另一个使用 RIP 的路由守护进程。它同时支持 OSPF、EGP 和 RIP 协议。只有 root 用户可用。
- __traceroute__:用于跟踪 IP 包的路由。它每次发送包时都把跳数加 1从而使得从源地址到目的地之间的所有网关都会返回消息。
- __netstat -rnf inet__:显示 IPv4 的路由表
- __sysctl net.inet.ip.forwarding=1__:启用包转发(把主机变为路由器)
- __route add|delete [-net|-host] <destination\> <gateway\>__:(如 `route add 192.168.20.0/24 192.168.30.4`)添加一条路由
- __route flush__:删除所有路由
- __route add -net 0.0.0.0 192.168.10.2__:添加一条默认路由
- __routed -Pripv2 -Pno_rdisc -d [-s|-q]__:运行 routed 守护进程,使用 RIPv2 协议,不启用 ICMP 自动发现,在前台运行,供给模式或安静模式。
- __route add 224.0.0.0/4 127.0.0.1__:定义 RIPv2 使用的路由(译注:翻译存疑)
- __rtquery -n <host\>__(译注:增加了 host 参数):查询指定主机上的 RIP 守护进程(手动更新路由表)
#### 其它
- __nslookup__:向 DNS 服务器查询,将 IP 转为名称,或反之。例如,`nslookup facebook.com` 会给出 facebook.com 的 IP。
- __ftp <host\> [port]__(译注:原文中 water 应是笔误):传输文件到指定主机。通常可以使用 login="anonymous" , p/w="guest" 登录。
- __rlogin -l <host\>__(译注:添加了 host 参数):使用类似 telnet 的虚拟终端登录到主机
#### 重要文件
- __/etc/hosts__域名到 IP 地址的映射
- __/etc/networks__网络名称到 IP 地址的映射
- __/etc/protocols__协议名称到协议编号的映射
- __/etc/services__TCP/UDP 服务名称到端口号的映射
#### 工具和网络性能分析
- __ifconfig <interface\> <address\> [up]__:启动接口
- __ifconfig <interface\> [down|delete]__:停止接口
- __ethereal &__:在后台打开 `ethereal` 而非前台
- __tcpdump -i -vvv__:抓取和分析包的工具
- __netstat -w [seconds] -I [interface]__:显示网络设置和统计信息
- __udpmt -p [port] -s [bytes] target_host__:发送 UDP 流量
- __udptarget -p [port]__:接收 UDP 流量
- __tcpmt -p [port] -s [bytes] target_host__:发送 TCP 流量
- __tcptarget -p [port]__:接收 TCP 流量
#### 交换机
- __ifconfig sl0 srcIP dstIP__:配置一个序列接口(在此前先执行 `slattach -l /dev/ttyd0`,此后执行 `sysctl net.inet.ip.forwarding=1`
- __telnet 192.168.0.254__:从子网中的一台主机访问交换机
- __sh ru____show running-configuration__:查看当前配置
- __configure terminal__:进入配置模式
- __exit__:进入低级配置模式(译注:翻译存疑)
#### VLAN
- __vlan n__:创建一个 ID 为 n 的 VLAN
- __no vlan N__:删除 ID 为 n 的 VLAN
- __untagged Y__:添加端口 Y 到 VLAN n
- __ifconfig vlan0 create__:创建 vlan0 接口
- __ifconfig vlan0 vlan ID vlandev em0__:连接 vlan0 接口到 em0 之上(译注:翻译存疑),并设置标记为 ID
- __ifconfig vlan0 [up]__:启用虚拟接口
- __tagged Y__:为当前 VLAN 的端口 Y 添加标记帧支持
#### UDP/TCP
- __socklab udp__:使用 UDP 协议运行 `socklab`
- __sock__:创建一个 UDP 套接字,等效于输入 `sock udp``bind`
- __sendto <Socket ID\> <hostname\> <port #\>__:发送数据包
- __recvfrom <Socket ID\> <byte #\>__:从套接字接收数据
- __socklab tcp__:使用 TCP 协议运行 `socklab`
- __passive__:创建一个被动模式的套接字,等效于 `socklab``sock tcp``bind``listen`
- __accept__:接受进来的连接(可以在发起进来的连接之前或之后执行)
- __connect <hostname\> <port #\>__:等效于 `socklab``sock tcp``bind``connect`
- __close__:关闭连接
- __read <byte #\>__:从套接字中读取 n 字节
- __write__:(例如,`write ciao`、`write #10`)向套接字写入 "ciao" 或 10 个字节
#### NAT/防火墙
- __rm /etc/resolv.conf__:禁止地址解析,保证你的过滤和防火墙规则正确工作
- __ipnat -f file_name__:将过滤规则写入文件
- __ipnat -l__:显示活动的规则列表
- __ipnat -C -F__:重新初始化规则表
- __map em0 192.168.1.0/24 -> 195.221.227.57/32 em0__:将 IP 地址映射到接口
- __map em0 192.168.1.0/24 -> 195.221.227.57/32 portmap tcp/udp 20000:50000__:带端口号的映射
- __ipf -f file_name__:将过滤规则写入文件
- __ipf -F -a__:重置规则表
- __ipfstat -I__:在过滤的包上允许访问某些信息(译注:翻译存疑),也包括活动的过滤规则
希望这份基础的 Linux 网络命令合集对你有用。问题和建议总是受欢迎的。
--------------------------------------------------------------------------------
via: https://itsfoss.com/basic-linux-networking-commands
作者:[Abhishek Prakash][a]
译者:[bianjp](https://github.com/bianjp)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[1]: https://drive.google.com/open?id=0By49_3Av9sT1cDdaZnh4cHB4aEk

View File

@ -1,222 +0,0 @@
如何搭建你自己的 Git 服务器
====================
![](https://opensource.com/sites/default/files/styles/image-full-size/public/images/business/bus-big-data.png?itok=sOQHDuID)
现在我们将要学习如何搭建 git 服务器,如何编写自定义的 Git 钩子来在特定的事件触发相应的动作(例如通知),或者是发布你的代码到一个站点。
直到现在,作为一个使用者注意力还是被 Git 影响。这篇文章中我将讨论 Git 的管理,并且设计一个灵活的 Git 框架。你可能会觉得这听起来是 “高阶 Git 技术” 或者 “只有狂热粉才能阅读”的一句委婉的说法,但是事实是这里面的每个任务都不需要很深的知识或者其他特殊的训练,就能立刻理解 Git 的工作原理,有可能需要一丁点关于 Linux 的知识
### 共享 Git 服务器
创建你自己的共享 Git 服务器意外地简单,而且遇到各方面的问题时都很值得。不仅仅是因为它保证你有权限查看自己的代码,它还对于利用扩展来维持 Git 的通信敞开了一扇大门,例如个人 Git 钩子,无限制的数据存储,和持续的整合与发布
如果你知道如何使用 Git 和 SSH那么你已经知道怎么创建一个 Git 服务器了。Git 的设计方式,就是让你在创建或者 clone 一个仓库的时候,就完成了一半服务器的搭建。然后允许用 SSH 访问仓库,而且任何有权限访问的人都可以使用你的仓库,作为 clone 的新仓库的基础。
但是,这是一个小的自组织。按照一些计划你可以以同样的效果创建一些设计优良的 Git 服务器,同时有更好的拓展性。
首要之事:确认你的用户们,现在的用户以及之后的用户都要考虑。如果你是唯一的用户那么没有任何改动的必要。但是如果你试图邀请其他的代码贡献者,那么你应该允许一个专门的分享系统用户给你的开发者们。
假定你有一个可用的服务器如果没有这不成问题Git 会帮忙解决CentOS 的 Raspberry Pi 3 是个不错的开始),然后第一步就是只允许使用 SSH 密钥认证的 SSH 登录。
一旦你启用了 SSH 密钥认证,创建 gituser 用户。这是给你的所有确认的开发者们的公共用户。
```
$ su -c 'adduser gituser'
```
然后切换到刚创建的 gituser 用户,创建一个 `~/.ssh` 的框架,并设置好合适的权限。这很重要,如果权限设置得太开放会使自己受保护的 SSH 默认失败。
```
$ su - gituser
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys
```
`authorized_keys` 文件里包含所有你的开发者们的 SSH 公钥,你开放权限允许他们可以在你的 Git 项目上工作。他们必须创建他们自己的 SSH 密钥对然后把他们的公钥给你。复制公钥到 gituser 用户下的 `authorized_keys` 文件中。例如,为一个叫 Bob 的开发者,执行以下命令:
```
$ cat ~/path/to/id_rsa.bob.pub >> \
/home/gituser/.ssh/authorized_keys
```
只要开发者 Bob 有私钥并且把相对应的公钥给你Bob 就可以用 gituser 用户访问服务器。
但是,你并不是想让你的开发者们能使用服务器,即使只是以 gituser 的身份访问。你只是想给他们访问 Git 仓库的权限。因为这个特殊的原因Git 提供了一个限制的 shell准确的说是 git-shell。以 root 身份执行以下命令,把 git-shell 添加到你的系统中,然后设置成 gituser 用户默认的shell。
```
# grep git-shell /etc/shells || su -c \
"echo `which git-shell` >> /etc/shells"
# su -c 'usermod -s git-shell gituser'
```
现在 gituser 用户只能使用 SSH 来 push 或者 pull Git 仓库,并且无法使用任何一个可以登录的 shell。你应该把你自己添加到和 gituser 一样的组中,在我们的样例服务器中仍是这个组的名字仍是 gituser。
举个例子:
```
# usermod -a -G gituser seth
```
仅剩下的一步就是创建一个 Git 仓库。因为没有人能在服务器上与 Git 交互(也就是说,你之后不能 SSH 到服务器然后直接操作这个仓库),创一个最原始的仓库 。如果你想使用位于服务器上的仓库来完成工作,你可以从它的所在处 clone 下来然后直接在你的 home 目录下工作。
说白了,你不需要让它变成一个空的仓库,你需要像工作在一个正常的仓库一样。但是,一个空的仓库没有 *working tree* (也就是说,使用 `checkout` 并没有任何分支显示)。这很重要,因为远程使用者们并不被允许 push 一个有效的分支(如果你正在 `dev` 分支工作然后突然有人把一些变更 push 到你的工作分支,你会有怎么样的感受?)。因为一个空的仓库可以没有有效的分支,这不会成为一个问题。
你可以把这个仓库放到任何你想放的地方,只要你想要放开权限给用户和用户组,让他们可以在仓库下工作。千万不要保存目录到例如一个用户的 home 目录下,因为有严格的权限控制。保存到一个常规的共享地址,例如 `/opt` 或者 `/usr/local/share`
以 root 身份创建一个空的仓库:
```
# git init --bare /opt/jupiter.git
# chown -R gituser:gituser /opt/jupiter.git
# chmod -R 770 /opt/jupiter.git
```
现在任何一个用户,只要他被认证为 gituser 或者在 gituser 组中,就可以从 jupiter.git 库中读取或者写入。在本地机器尝试以下操作。
```
$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
Cloning into 'jupiter.clone'...
Warning: you appear to have cloned an empty repository.
```
谨记:开发者们一定要把他们的 SSH 公钥加入到 gituser 用户下的 `authorized_keys` 文件里,或者说,如果他们有服务器上的用户(如果你给了他们用户),那么他们的用户必须属于 gituser 用户组。
### Git 钩子
将自己的 Git 服务器跑起来,很赞的一件事就是可以使用 Git 钩子。支持 Git 的设备有时提供一个类钩子接口,但是并没有给你真正的 Git 钩子来访问文件系统。Git 钩子是一个脚本,它将在一个 Git 过程的某些点运行;当一个仓库即将接收一个 commit或者接受一个 commit 之后,或者即将接收一次 push或者一次 push 之后等等
这是一个简单的系统:任何放在 `.git/hooks` 目录下的脚本,使用标准的命名体系,就可按设计好的时间运行。一个脚本是否应该被运行取决于它的名字; pre-push 脚本在 push 之前运行post-received 脚本在 push 之后运行post-receive 脚本在接受 commit 之后运行等等。
脚本可以用任何语言写;如果在你的系统上有可以执行的脚本语言,例如输出 hello world ,那么你就用这个语言来写 Git 钩子脚本。Git 默认会给出一些例子,但是并不能用。
想要动手试一个?这很简单。如果你没有现成的 Git 仓库,首先创建一个 Git 仓库:
```
$ mkdir jupiter
$ cd jupiter
$ git init .
```
然后写一个功能为输出 “hello world” 的 Git 钩子。因为我使用 tsch 作为传统系统的长期支持 shell所以我仍然用它作为我的脚本语言你可以自由的使用自己喜欢的语言BashPythonRubyPerlRustSwiftGo
```
$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" >> \
~/jupiter/.git/hooks/post-commit
$ chmod +x ~/jupiter/.git/hooks/post-commit
```
现在测试它的输出:
```
$ echo "hello world" > foo.txt
$ git add foo.txt
$ git commit -m 'first commit'
! POST-COMMIT SCRIPT TRIGGERED
[master (root-commit) c8678e0] first commit
1 file changed, 1 insertion(+)
create mode 100644 foo.txt
```
然后你已经实现了:你的第一个有功能的 Git 钩子
### 有名的 push-to-web 钩子
Git 钩子最流行的用法就是自动 push 更改的代码到一个正在使用中的网络服务器目录下。这是摆脱 FTP 的很好的方式,对于正在使用的产品保留完整的版本控制,自动整合发布的内容
如果操作正确,在一直以来的网站发布维护中 Git 会完成的很好而且在某种程度上很精准。Git 真的好棒。我不知道谁最初想到这个主意,但是我第一次听到它是从 Emacs 和 Git 方面的专家IBM 的 Bill von Hagen。他的文章包含一系列明确的介绍[Git 改变了分布式网页开发的游戏规则][1]。
### Git 变量
每一个 Git 钩子都有一系列不同的变量对应触发钩子的不同 Git 行为。你需不需要这些变量,主要取决于你写的程序。如果你需要一个当某人 push 代码时候的通用邮件通知,那么你就不需要特殊化,并且甚至也不需要编写额外的脚本,因为已经有现成的适合你的脚本。如果你想在邮件里查看 commit 信息和 commit 的作者,那么你的脚本就会变得相对棘手些。
Git 钩子并不是被用户直接执行所以要弄清楚如何收集可能会误解的重要信息。事实上Git 钩子脚本就像其他的脚本一样,像 BASH, Python, C++ 等等,从标准输入读取参数。不同的是,我们不会给它提供这个输入,所以,你在使用的时候,需要知道可能的输入参数。
在写 Git 钩子之前,看一下 Git 在你的项目目录下 `.git/hooks` 目录中提供的一些例子。举个例子,在这个 `pre-push.sample` 文件里,注释部分说明了如下内容:
```
# $1 -- 即将 push 的远方仓库的名字
# $2 -- 即将 push 的远方仓库的 URL
# 如果 push 的时候,并没有一个命名的远方仓库,那么这两个参数将会一样。
#
# 对于这个表单的标准输入,
# 参数通过行的形式输入
# <local ref> <local sha1> <remote ref> <remote sha1>
```
并不是所有的例子都是这么清晰,而且关于钩子获取变量的文档依旧缺乏(除非你去读 Git 的源码)。但是,如果你有疑问,你可以从[其他用户的尝试中][2]学习,或者你只是写一些基本的脚本,比如 `echo $1, $2, $3` 等等。
### 分支检测示例
我发现,对于生产环境来说有一个共同的需求,就是需要一个只有在特定分支被修改之后,才会触发事件的钩子。以下就是如何跟踪分支的示例。
首先Git 钩子本身是不受版本控制的。 Git 并不会跟踪他自己的钩子,因为对于钩子来说,他是 Git 的一部分而不是你仓库的一部分。所以Git 钩子可以监控你的 Git 服务器上的 Git 仓库的 commit 记录和 push 记录,而不是你本地仓库的一部分。
我们来写一个 post-receive也就是说在 commit 被接受之后触发)钩子。第一步就是需要确定分支名:
```
#!/bin/tcsh
foreach arg ( $< )
set argv = ( $arg )
set refname = $1
end
```
这个 for 循环用来读入第一个参数 `arg($1)` 然后循环用第二个参数 `($2)` 去重写,然后用第三个参数 `($3)` 。在 Bash 中有一个更好的方法,使用 read 命令,并且把值放入数组里。但是,这里是 tcsh并且变量的顺序可以预测的所以这个方法也是可行的。
当我们有了 commit 记录的 refname我们就能使用 Git 去找到这个分支的人类能读的名字:
```
set branch = `git rev-parse --symbolic --abbrev-ref $refname`
echo $branch #DEBUG
```
然后把这个分支名和我们想要触发的事件的分支名关键字进行比较。
```
if ( "$branch" == "master" ) then
echo "Branch detected: master"
git \
--work-tree=/path/to/where/you/want/to/copy/stuff/to \
checkout -f $branch || echo "master fail"
else if ( "$branch" == "dev" ) then
echo "Branch detected: dev"
Git \
--work-tree=/path/to/where/you/want/to/copy/stuff/to \
checkout -f $branch || echo "dev fail"
else
echo "Your push was successful."
echo "Private branch detected. No action triggered."
endif
```
给这个脚本分配可执行权限:
```
$ chmod +x ~/jupiter/.git/hooks/post-receive
```
现在,当一个用户在服务器的 master 分支 commit 代码这个代码就会被复制到一个生产环境的目录dev 分支的一个 commit 记录也会被复制到其他地方,其他分支将不会触发这些操作。
同时,创造一个 pre-commit 脚本也很简单。比如,判断一个用户是否在他们不该 push 的分支上 push 代码,或者对 commit 信息进行解析等等。
Git 钩子也可以变得复杂,而且他们因为 Git 的工作流的抽象层次不同而变得难以理解,但是他们确实是一个强大的系统,让你能够在你的 Git 基础设施上针对所有的行为进行对应的操作。如果你是一个 Git 重度用户,或者一个全职 Git 管理员,那么 Git 钩子是值得学习的。
在我们这个系列之后和最后的文章,我们将会学习如何使用 Git 来管理非文本的二进制数据,比如音频和图片。
--------------------------------------------------------------------------------
via: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
作者:[Seth Kenlon][a]
译者:[maywanting](https://github.com/maywanting)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[1]: http://www.ibm.com/developerworks/library/wa-git/
[2]: https://www.analysisandsolutions.com/code/git-hooks-summary-cheat-sheet.htm

View File

@ -1,192 +0,0 @@
Ohm: 一种可以用两百行代码创造一种语言的 JavaScript 解释器
解释器是一种非常有用的软件库。从概念上简单的说,它们的实现很有挑战并且在计算机科学中经常被认为是暗黑艺术。在这个系列的博文中,我会向你们展示为什么你不需要成为哈利波特就能够很好的控制解释器。但是为了以防万一带上你的魔杖。
我们将探索一种叫做 Ohm 的新的开源库,它使得搭建解释器很简单并且更加容易再利用。在这个系列里,我们使用 Ohm 去识别数字,构建计算器等等。在这个系列的最后你将已经用少于 200 行的代码发明了一种完整的编程语言。这个强大的工具将让你能够做一些你可能过去认为不可能的事情。
###为什么解释器很困难?
解释器非常有用。在很多时候你可能需要一个解释器。一种新的文件格式可能出现,你需要去处理但还没有人为它写了一个库;或者你发现了一种老格式的文件但是现存的解释器不能构建你需要的平台。我已经看到这样的事发生无数次。代码会来来去去但数据却是永恒的。
基础的解释器很简单:只是把一个数据结构转化成另一个。所以为什么感觉你需要成为 邓布利多【魔法师】才能够把它们做出来。
解释器的一些历史性的挑战是很难写,绝大多数工具很老并且假设了大量晦涩难懂的计算机科学知识。如果你在大学里上过编译器课程那么课本里可能也有从 1970 年以来的技术。幸运的是,解释器技术从那时候起已经提高了很多。
代表性地,解释器是通过使用一种叫作形式语法的特殊语法来定义你想要解析的东西这样发明的,然后你需要把它放入像 Bison 和 Yacc 的工具中,这些工具能够产生一堆你需要修改的 C 代码或者链接到你实际写入额的编程语言。另外的选择是用你更喜欢的语言亲自动手写一个解释器,这很慢且很容易出错,在你能够真正使用它之前还有许多额外的工作。
想像一下,是否你关于你想要解析的东西的语法描述也是解释器?如果你能够仅仅直接运行语法,然后在你需要的地方增加挂钩,那是什么?那就是 Ohm 所做的事。
###解释器简介
[Ohm][1]是一种新的解析系统。它类似你可能已经在课本里面看到的语法并且它更强大,使用起来更简单。通过 Ohm, 你能够使用一种灵活的语法以 .ohm 文件格式来写格式定义,然后使用你的宿主语言把语义加入到里面。在这篇博文里,我们将用 JavaScript 作为宿主语言。
Ohm 建立在一个为制造更简单、更灵活的解释器的一个多年调查基础之上。VPRI 的 [STEPS program](pdf) 使用 Ohm 的前驱为许多特殊的工作创造了专门的语言(比如一个有 400 行代码的平行制图描绘器)[Ometa][3].
Ohm 有许多有趣的特点和符号,但是不是要全部解释它们,我认为我们应该只需投入其中并构建一些东西。
###解析整数
让我们来解析一些数字。这看起来会很简单,只需在一个文本串中寻找毗邻的数字,但是让我们尝试去处理所有形式的数字:整数和浮点数,十六进制数和八进制数,科学计数,负数。解析数字很简单,正确解析却很难。
亲自构建这个代码将会很困难,会有很多故障,会伴随有许多特殊的情况,比如有时会相互矛盾。
用 Ohm 构建的解释器涉及三个部分:语法、语义和测试。我通常挑选一个问题的一部分为它写测试,然后构建足够的语法和语义来使测试通过。然后我再挑选问题的另一部分,增加更多的测试,更新语法和语义,从而确保所有的测试能够持续通过。即使我们有了新的强大的工具,写解释器从概念上来说依旧很困难。测试是用一种合理的方式来构建解释器的唯一方法。现在,让我们开始工作。
我们将从整数开始。一个整数由一系列相互毗邻的数字组成。让我们把下面的内容放入一个叫做 grammar.ohm 的文件中:
```
CoolNums {
// just a basic integer
Number = digit+
}
```
这创造了一条撮合一个或多个数字叫作 Number 的单一规则。+ 意味着一个或更多,就像一个常规的表达。当有一个或更多的数字时,这个规则将会撮合它们,如果没有数字或者有一些不是数字的东西将不会撮合。一个数字定义成从 0 到 9 其中的一个字符。数字也是像 Number 一样的规则,但是它是 Ohm 的其中一条构建规则因此我们不需要去定义它。我们可以推翻它如果我们想的话但在这时候这没有任何意义,毕竟我们不打算去发明一种新的数。
现在,我们可以读入这个语法并用 Ohm 库来运行它。
把它放入 test1.js
```
var ohm = require('ohm-js');
var fs = require('fs');
var assert = require('assert');
var grammar = ohm.grammar(fs.readFileSync('src/blog_numbers/syntax1.ohm').toString());
```
Ohm 的语法调用将把文件读入并解释成一个语法对象。现在我们可以增加一些语义。把下面内容增加到你的 JavaScript 文件中:
```
var sem = grammar.createSemantics().addOperation('toJS', {
Number: function(a) {
return parseInt(this.sourceString,10);
}
});
```
这创造了一系列叫作 sem with the operation to JS[伴有 JavaScript 操作的语义] 的语义。这些语义至关重要,一群函数和语法中的每一条规则相匹配。一个函数将会被调用当与它相匹配的语法规则被解析时。上面的 Number 函数将会被调用当语法中的 Number 规则被解析时。语法定义在语言中 chunks[大块] 是什么,语义定义当 chunks[大块] 被解析时应该做什么。
语义函数能够做我们想做的任何事,比如打印初故障信息,创造对象,或者递归调用 toJS 作用于任何子节点。此时我们仅仅想把文本转换成真正的 JavaScript 整数。
所有的语义函数有一个包含一些有用性质的暗含对象。源属性代表输入文本和这个节点相匹配。这个 sourceString[源串] 是一个匹配输入串,调用构建在 JavaScript 中的parseInt 函数会把这个串转换成一个数。parseInt 中 10 这个参数告诉 JavaScript 我们输入的是一个以 10 为基底的数。如果少了这个参数, JavaScript 也会假定以 10 为基底,但是我们把它包含在里面因为后面我们将支持以 16 为基底的数,所以使之明确比较好。
既然我们有一些语法,让我们来实际解析一些东西看一看我们的解释器是否能够工作。如果知道我们的解释器工作?通过测试它,许多许多的测试,每一个边缘情况都需要一个测试。
伴随标准断言 API有一个测试函数能够匹配一些输入并运用我们的语义把它转换成一个数然后比较转换生成的数和我们期望的输入。
```
function test(input, answer) {
var match = grammar.match(input);
if(match.failed()) return console.log("input failed to match " + input + match.message);
var result = sem(match).toJS();
assert.deepEqual(result,answer);
console.log('success = ', result, answer);
}
```
这个函数就是上面这个。现在我们能够为不同的数写一堆测试。如果匹配失败我们的脚本将会丢弃一个例外。如果不能打印成功,让我们尝试一下,把下面这些内容加入到脚本中:
```
test("123",123);
test("999",999);
test("abc",999);
```
然后用节点 test.js 运行脚本
你的输出应该是这样:
```
success = 123 123
success = 999 999
input failed to match abcLine 1, col 1:
> 1 | abc
^
Expected a digit
```
真酷。正如理所当然的那样前两个成功了第三个失败了。更好的是Ohm 自动给了我们一个很棒的错误信息指出匹配失败。
###浮点数
我们的解释器工作了,但是它不能做任何非常有趣的事。让我们把它扩展成既能解析整数又能解析浮点数。改变 grammar.ohm 文件使它看起来像下面这样:
```
CoolNums {
// just a basic integer
Number = float | int
int = digit+
float = digit+ "." digit+
}
```
这把 Number 规则改变成指向一个浮点数或者一个整数。我的意思是,我们把这读成"一个 Number 由一个浮点数或者一个整数构成。”然后整数定义成 digit+, 浮点数定义成 digit+ 后面跟着一个句号然后再跟着另一个 digit+. 这意味着在句号前和句号后都至少要有一个数字。如果一个数中没有一个句号那么它就不是一个浮点数,因此就是一个整数。
现在,让我们再次看一下我们的语义作用。由于我们现在有了新的规则所以我们需要新的作用函数:一个作为整数的,一个作为浮点数的。
```
var sem = grammar.createSemantics().addOperation('toJS', {
Number: function(a) {
return a.toJS();
},
int: function(a) {
console.log("doing int", this.sourceString);
return parseInt(this.sourceString,10);
},
float: function(a,b,c) {
console.log("doing float", this.sourceString);
return parseFloat(this.sourceString);
}
});
```
这里有两件事情需要注意。首先,整数,浮点数和数都有相匹配的语法规则和函数。然而,针对数的作用不再有任何意义。它接收子节点 'a' 然后通过子节点返回 toJS 的结果。换句话说Number 规则简单的返回相匹配的子规则。由于这是在 Ohm 中任何规则的默认行为,因此实际上我们不用去考虑 Number 的作用Ohm 会替我们来做这件事。
第二整数有一个参数然而浮点数有三个a, b, 和 c. 这是由于规则的参数数量。参数数量意味着一个规则里面有多少参数。如果我们回过头去看语法,浮点数的规则是:
```
float = digit+ "." digit+
```
浮点数规则通过三个部分来定义:第一个 digit+, '.', 还有第二个 digit+. 这三个部分都会作为参数传递给浮点数的作用函数。因此浮点数必须有三个参数否则 Ohm 库给出一个错误。在这种情况下我们不用在意参数因为我们仅仅直接攫取了输入串,但是我们仍然需要列表的参数来回避编译器错误。后面我们将实际使用其中一些参数。
现在我们可以为新的浮点数支持添加更多的测试。
```
test("123",123);
test("999",999);
//test("abc",999);
test('123.456',123.456);
test('0.123',0.123);
test('.123',0.123);
```
注意最后一个测试将会失败。一个浮点数必须以一个数开始,即使它仅仅是 0, .123 不是有效的,实际上真正的 JavaScript 语言有相同的规则。
###十六进制数
现在我们已经有了整数和浮点数,但是有一些其他的数的语法可能能够很好的支持:十六进制数和科学计数。十六进制数是是以 16 为基底2的数。十六进制数的数字能从 0 到 9 和从 A 到 F. 十六进制数经常用在计算机科学中当用二进制数据工作时,因为你可以仅仅使用两个数字表示 0 到 255 的数。
在绝大多数源自 C 的编程语言(包括 JavaScript), 十六进制数通过在前面加上 0x' 来向编译器表明后面跟的是一个十六进制数。为了让我们的解释器支持十六进制数,我们只需要添加另一条规则。
```
Number = hex | float | int
int = digit+
float = digit+ "." digit+
hex = "0x" hexDigit+
hexDigit := "0".."9" | "a".."f" | "A".."F"
```
我实际上已经增加了两条规则。'hex' 表明十六进制数是一个 'ox' 后面一个或多个 hexDigits'[十六进制数子] 的串。一个 'hexDigit' 是从 0 到 9, 或从 a 到 f, 或 A 到 F包扩大写和小写的情况的一个字符。我也修改了 Number 规则来识别十六进制数作为其他可能的选择。现在我们只需要另一条针对十六进制数的作用规则。
```
hex: function(a,b) {
return parseInt(this.sourceString,16);
}
```
注意到,在这种情况下,我们把 '16' 作为基数传递给 'parseInt' 因为我们希望 JavaScript 知道这是一个十六进制数。
我略过了一些很重要需要注意的事。针对 'hexDigit' 的规则像下面这样:
```
hexDigit := "0".."9" | "a".."f" | "A".."F"
```
注意我使用的是 ':=' 而不是 '='. 在 Ohm 中,'=' 是当你需要推翻一条规则的时候使用。证明是 Ohm 已经有了针对 'hexDigit' 的默认规则,就像针对 'digit', 'space' 等一堆其他的东西。如果我使用了 '=', Ohm 将会报告一个错误。这是一个检查从而我不能无意识的推翻一个规则。由于新的 hexDigit 规则和 Ohm 的构建规则一样,所以我们可以仅仅对它添加注释然后让 Ohm 来实现它。我留下这个规则仅仅是因为这样我们可以看到它实际上是如何进行的。
Now we can add some more tests and see that our hex digits really work:
现在,我们可以添加更多的测试然后看到十六进制数真的工作。
```
test('0x456',0x456);
test('0xFF',255);
```
###科学计数
最后,让我们来支持科学计数。科学计数是针对非常大或非常小的数比如 1.8×10^3, 在大多数编程语言中科学计数法表示的数会写成这样1.8e3 表示 18000, 或者 1.8e-3 表示 .018. 让我们增加另外一对规则来支持这个指数表示:
```
float = digit+ "." digit+ exp?
exp = "e" "-"? digit+
```
上面增加了一个指数规则通过在浮点数规则末尾加上一个 '?'. '?' 表示 0 或 1所以指数是可选择的但是不能超过一个。增加指数规则也改变了浮点数规则的参数数量所以我们需要为浮点数作用增加又一个参数即使我们不使用它。
```
float: function(a,b,c,d) {
console.log("doing float", this.sourceString);
return parseFloat(this.sourceString);
},
```
现在我们的测试可以通过了:
```
test('4.8e10',4.8e10);
test('4.8e-10',4.8e-10);
```
###结论
Ohm 是构建解释器的一个很棒的工具因为它很容易开始并且你可以递增的增加规则。Ohm 也还有其他我今天没有写到的很棒的特点,比如故障观察仪和子类化。
s.
到目前为止,我们已经使用 Ohm 来把字符串翻译成 JavaScript 数,并且 Ohm 经常由于需要把一个表示转化成另一个这一目的而使用。然而Ohm 还有更多的用途。通过放入以系列不同的语义作用你可以使用 Ohm 来真正处理和计算东西。一个单独的语法可以被许多不同的语义使用,这是 Ohm 其中一个不可思议的特点。
在这个系列的下一篇文章中我将向你们展示如何计算像4.85 + 5 * (238 - 68)/2) 这样的数学表达式,不仅仅是解析数。
额外的挑战:你能够扩展语法来支持八进制数吗?这些以 8 为基底的数能够只用 0 到 7 这几个数字来表示,前面加上一个数字 0 或者字母 o. 看看针对下面这些测试情况是够正确。下次我将给出答案。
```
test('0o77',7*8+7);
test('0o23',0o23);
```
--------------------------------------------------------------------------------
via: https://www.pubnub.com/blog/2016-08-30-javascript-parser-ohm-makes-creating-a-programming-language-easy/?utm_source=javascriptweekly&utm_medium=email
作者:[Josh Marinacci][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.pubnub.com/blog/author/josh/
[1]: https://github.com/cdglabs/ohm
[2]: http://www.vpri.org/pdf/tr2012001_steps.pdf
[3]: http://tinlizzie.org/ometa/

View File

@ -1,80 +0,0 @@
AWS和GCP Spark技术哪家强
===========
>Tianhui Michael Li 和Ariel Mndange-Pfupfu将在今年10月10、12和14号组织一个在线经验分享课程Spark分布式计算入门。该课程的内容包括创建端到端的运行应用程序和精通Spark关键工具。
毋庸置疑云计算将会在未来数据科学领域扮演至关重要的角色。弹性可扩展性和按需分配的计算能力作为云计算的重要资源直接导致云服务提供商集体火拼。其中最大的两股势力正是亚马逊网络服务AWS)【1】和谷歌云平台GCP)【2】。
本文依据构建时间和运营成本对AWS和GCP的Spark工作负载作一个简短比较。实验由我们的学生在数据孵化器进行数据孵化器【3】是一个大数据培训组织专门为公司招聘顶尖数据科学家并为公司职员培训最新的大数据科学技能。尽管内置的Spark效率惊人分布式工作负载的时间和成本亦然可以大到不能忽略不计。因此我们一直努力寻求更高效的技术我们的学生也因此能够学习到最好和最快的工具。
###提交Spark任务到云
Spark是一个类MapReduce但是比MapReduce更灵活、更抽象的并行计算框架。Spark提供Python和Java 编程接口但它更愿意用户使用原生的Scala语言进行应用程序开发。Scala可以把应用程序和依赖文件打包在一个JAR文件从而使Spark任务提交变得简单。
通常情况下Sprark结合HDFS应用于分布式数据存储而与YARN协同工作则应用于集群管理这种堪称完美的配合使得Spark非常适用于AWS的弹性MapReduce(EMR)集群和GCP的Dataproc集群。这两种集群都已有HDFS和YARN预配置不需要额外进行配置。
通过命令行比通过网页接口管理数据、集群和任务具有更高的可扩展性。对AWS而言这意味着客户需要安装CLI。客户必须获得证书并为每个EC2实例创建独立的密钥对。除此之外客户还需要为EMR用户和EMR本身创建规则主要是准入许可规则从而使EMR用户获得足够多的权限。
相比而言GCP的处理流程更加直接。如果客户选择安装Google Cloud SDK并且使用其Google账号登录那么客户即刻可以使用GCP的几乎所有功能而无需其他任何配置。唯一需要提醒的是不要忘记通过API管理器使能计算引擎、Dataproc和云存储JSON的API。
AWS就是这样实现自己喜欢的应用一旦火力全开根本停不下来比如可以通过“aws s3 cp”或者“gsutil cp”命令拷贝客户的数据到云端。再比如客户可以创建自己的输入、输出或者任何其他需要的bucket如此运行一个应用就像创建一个集群或者提交JAR文件一样简单。请确定日志存放的地方毕竟在云环境下跟踪问题或者调试bug有点诡异。
###一分钱一分货
谈及成本Google的服务在以下几个方面更有优势。首先购买计算能力的原始成本更低。4个vCPU和15G RAM的Google计算引擎服务每小时只需0.20美元如果运行Dataproc每小时也只需区区0.24美元。相比之下同等的云配置AWS EMR则需要每小时0.336美元。
其次计费方式。AWS按小时计费即使客户只使用15分钟也要付足1小时的费用。GCP按分钟计费最低计费10分钟。在诸多用户案例中资费方式的不同直接导致成本的巨大差异。
两种云服务都有其他多种定价机制。客户可以使用Sport Instance或Preemptible Instance竞价AWS或GCP的空闲云计算能力。这些服务比专有的、按需服务便宜缺点是不能保证随时有可用的云资源提供服务。在GCP上如果客户长时间每月的25%至100%使用服务可以获取更多折扣。在AWS上预付费或者一次购买大批量服务可以节省不少费用。底线是如果你是一个超级用户并且使用云计算已经成为一种常态那么最好深入研究云计算自建云计算服务。
最后新手在GCP上体验云服务的费用较低。新手只需300美元信用担保就可以免费试用60天GCP提供的全部云服务。AWS只免费提供特定服务的特定试用层级如果运行Spark任务需要付费。这意味着初次体验SparkGCP具有更多选择也少了精打细算和讨价还价的烦恼。
###性能比拼
我们通过实验检测一个典型Spark工作负载的性能与开销。实验分别选择AWS的m3.xlarg和GCP的n1-standard-4它们都是由一个Master和5个核心实例组成的集群。除了规格略有差别虚拟核心和费用都相同。实际上它们在Spark任务的执行时间上也表现的惊人相似。
测试Spark任务包括对数据的解析、过滤、合并和聚合这些数据来自堆栈交换数据转储。通过运行相同的JAR我们首先对大约50M的数据子集进行交叉验证然后将验证扩大到大约9.5G的数据集。
![](https://d3ansictanv2wj.cloudfront.net/1400_img_1_AWS_GCP-25ed6069029112a8439d89999796be18.jpg)
>Figure 1. Credit: Michael Li and Ariel M'ndange-Pfupfu.
![](https://d3ansictanv2wj.cloudfront.net/1400_img_2_AWS_GCP-448714718896b21e32f8b47d4657fc8c.jpg)
>Figure 2. Credit: Michael Li and Ariel M'ndange-Pfupfu.
结果表明短任务在GCP 上具有明显的成本优势这是因为GCP以分钟计费并最终扣除了10分钟的费用而AWS则收取了1小时的费用。但是即使长任务因为计费方式占优GPS仍然具有相当优势。同样值得注意的是存储成本并不包括在此次比较当中。
###结论
AWS是云计算的先驱这甚至体现在API中。AWS拥有巨大的生态系统但其准入模型已略显陈旧配置管理也有些晦涩难解。相比之下Google是云计算领域的新星并且抛光了云计算中一些粗糙的边缘问题。但是GCP缺少一些便捷的功能比如通过简单方法自动结束集群和详细的任务计费信息分解。另外其Python编程接口也不像AWS的Boto那么全面。
如果你初次使用云计算GCP因简单易用别具魅力。即使你已在使用AWS你也许会发现迁移到GCP可能更划算尽管真正从AWS迁移到GCP的代价可能得不偿失。
当然,现在对两种云服务作一个全面的总结还非常困难,因为它们都不是单一的实体,而是由多个实体整合而成的完整生态系统,并且各有利弊。真正的赢家是用户。一个例证就是在数据孵化器,我们的博士数据科学研究员在学习过程中真正体会到成本的下降。虽然我们的大数据企业培训客户可能对价格不那么敏感,他们很欣慰能够更快速地处理企业数据,同时保持价格不增加。数据科学家现在可以享受大量的可选服务,这些都是从竞争激烈的云计算市场得到的实惠。
--------------------------------------------------------------------------------
via: https://www.oreilly.com/ideas/spark-comparison-aws-vs-gcp?utm_source=dbweekly&utm_medium=email
作者:[Michael Li][a] [Ariel M'Ndange-Pfupfu][b]
译者:[firstadream](https://github.com/firstadream)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.oreilly.com/people/76a5b-michael-li
[b]: https://www.oreilly.com/people/Ariel-Mndange-Pfupfu
[1]: https://aws.amazon.com/
[2]: https://cloud.google.com/
[3]: https://www.thedataincubator.com/training.html?utm_source=OReilly&utm_medium=blog&utm_campaign=AWSvsGCP

View File

@ -0,0 +1,446 @@
新手指南 通过 DOCKER 在 Linux 上托管 .NET 核心
=====
这篇文章基于我之前的文章【.NET 核心入门】【】。首先我把应用程序界面【API】从 .NET Core RC1 升级到了 .NET Core 1.0,然后,我增加了对 Docker 的支持并描述了如何在 Linux 生产环境里托管它。
![](http://blog.scottlogic.com/nsoper/assets/noob.png)
我是首次接触 Docker 并且距离成为一名 Linux 高手还有很远的一段路程。因此,这里的很多想法是来自一个新手。
### 安装
按照 https://www.microsoft.com/net/core 上的介绍在你的电脑上安装 .NET 核心。这将会同时在 Windows 上安装 dotnet 命令行工具以及最新的 Visual Studio 工具。
### 源代码
你可以直接到 GitHub 上找最到最新完整的源代码。
### 转换到 .NET CORE 1.0
自然地当我考虑如何把应用程序界面【API】 .NET Core RC1 升级到 .NET Core 1.0 时想到的第一个求助的地方就是谷歌搜索。我是按照下面这两条非常全面的指导来进行升级的:
- [Migrating from DNX to .NET Core CLI][2]
- [Migrating from ASP.NET 5 RC1 to ASP.NET Core 1.0][3]
当你迁移代码的时候,我建议仔细阅读这两条指导,因为我在没有阅读第一篇指导的情况下又尝试浏览第二篇,结果感到非常迷惑和沮丧。
我不想描述细节上的改变因为你可以看 GitHub 上的提交。这儿是我所作改变的摘要:
- 更新 global.json and project.json 上的版本数
- 删除 project.json 上的废弃章节
- 使用轻型 ControllerBase 而不是 Controller 因为我不需要与 MVC 视图相关的方法(这是一个可选的改变)。
- 从辅助方法中去掉前缀比如HttpNotFound -> NotFound
- LogVerbose -> LogTrace
- 名字空间改变: Microsoft.AspNetCore.*
- 使用 SetBasePath 启动(没有它 appsettings.json 将不会被发现)
- 通过 WebHostBuilder 来运行而不是通过 WebApplication.Run 来运行
- 删除 Serilog在写文章的时候它不支持 .NET Core 1.0
唯一令我真正头疼的事是需要移动 Serilog。我本能够执行自己的文件记录器但是我删除了文件记录因为我不想为了这次操作集中精力在这件事情上。
不幸的是,将有大量的第三方开发者扮演追赶 .NET Core 1.0 的角色,我非常同情他们,因为他们通常在休息时间还坚持工作但却依旧根本无法接近微软的可用资源。我建议阅读 Travis Illig 的文章【.NET Core 1.0 发布了,但 Autofac 在哪儿】【4】这是一篇关于第三方开发者观点的文章。
做了这些改变以后,我可以从 project.json 目录恢复、构建并运行 dotnet可以看到应用程序界面【API】又像以前一样工作了。
### 通过 DOCKER 运行
在我写这篇文章的时候, Docker 只能够在 Linux 系统上工作。在 Windows 系统和 OS X 上有 beta 支持 Docker但是它们都必须依赖于虚拟化技术因此我选择把 Ubuntu 14.04 当作虚拟机来运行。如果你还没有安装过 Docker请按照指导来安装。
我最近阅读了一些关于 Docker 的东西,但我直到现在还没有真正用它来干任何事。我假设读者还没有关于 Docker 的知识,因此我会解释我所使用的所有命令。
#### HELLO DOCKER
在 Ubuntu 上安装好 Docker 之后,我所进行的下一步就是按照 https://www.microsoft.com/net/core#docke 上的介绍来开始运行 .NET 核心和 Docker.
首先启动一个已安装有 .NET Core 的 container。
```
docker run -it microsoft/dotnet:latest
```
-it 选项意味着你可以在 container 内交互执行这条命令并按照你所希望的那样自由执行任何 bash 命令。
然后我们可以运行下面这五条命令个来获得在 Docker 内部运行的 Microsofts Hello World .NET 核心控制台运用程序。
1. mkdir hwapp
2. cd hwapp
3. dotnet new
4. dotnet restore
5. dotnet run
你可以通过退出来离开 container然后在 Docker 内运行 ps -a 命令,这会显示你已经创建了一个已退出的 container。你可以通过在 Docker 上运行命令 rm <container_name>. 来整理一下 Container。
#### 安装源代码
我的下一步骤是使用和上面相同的 microsoft/dotnet 图像,但是将我的应用程序的源代码作为数据卷
首先检查有相关提交的仓库:
1. git clone https://github.com/niksoper/aspnet5-books.git
2. cd aspnet5-books/src/MvcLibrary
3. git checkout dotnet-core-1.0
现在启动一个 container 来运行位于 /book 目录下伴有源程序的 .NET Core 1.0。 注意更改 /path/to/repo 这部分文件来匹配你的电脑:
```
docker run -it \
-v /path/to/repo/aspnet5-books/src/MvcLibrary:/books \
microsoft/dotnet:latest
```
现在你可以运行 container 中的应用程序了!
```
cd /books
dotnet restore
dotnet run
```
作为一个概念的证明,这的确很棒,但是我们不想无论何时打算运行一个程序都要考虑如何把源代码安装到 container 里。
#### 增加一个 DOCKERFILE
我的下一步骤是引入一个 Docker 文件,这将允许应用程序很容易在自己的 container 内启动。
我的 Docker 文件和 project.json 一样位于 src/MvcLibrary 目录下,看起来像下面这样:
```
FROM microsoft/dotnet:latest
# 为应用程序源代码创建目录
RUN mkdir -p /usr/src/books
WORKDIR /usr/src/books
# 复制源代码并恢复依赖关系
COPY . /usr/src/books
RUN dotnet restore
# 暴露端口并运行应用程序
EXPOSE 5000
CMD [ "dotnet", "run" ]
```
严格来说RUN mkdir -p /usr/src/books 命令是不需要的,因为 COPY 会自动为丢失的目录创建副本。
Docker 图像是建立在图层里面的,我们从包含 .NET Core 的图像开始,添加另一个从源生成应用程序的层,然后运行这个运用程序。
添加了 Docker 文件以后,我通过运行下面的命令来生成一个图像并使用生成的图像打开一个 container确保在和 Docker 文件相同的目录下进行操作并且你应该使用自己的用户名)。
1. docker build -t niksoper/netcore-books .
2. docker run -it niksoper/netcore-books
你应该看到程序能够和之前一样的运行,不过这一次我们不需要像之前那样安装源代码,因为源代码已经包含在 docker 图像里面了。
#### 暴露并发布端口
应用程序界面【API】用处不大除非我们可以从 container 外面和它进行通信。 Docker 已经有了暴露和发布端口的概念,但这是两件完全不同的事。
通过 Docker 官方文件:
> EXPOSE 指令通知 Docker 上的 container 监听正在运行的特殊网络端口。EXPOSE 指令不能够让 container 访问主机。要使 container 能够访问主机,你必须通过 -p 标志来发布一系列端口或者使用 -P 标志来发布所有暴露的端口
EXPOSE 指令只会将元数据添加到图像上,所以你可以认为它是图像消费者的文件。从技术上讲,我本应该忽略 5000 行 EXPOSE 指令因为我知道应用程序界面【API】正在监听的端口但把它们留下很有用并且是值得推荐的。
在这个阶段我想直接从主机访问应用程序界面【API】因此我需要通过 -p 指令来发布端口,这将允许请求从主机上的端口 5000 转发到 container 上的端口 5000无论这个端口是不是之前通过 Docker 文件暴露的。
```
docker run -d -p 5000:5000 niksoper/netcore-books
```
通过 -d 指令告诉 docker 在分离模式下运行 container因此我们不能看到它的输出但是它依旧会运行和监听端口 5000。你可以通过 docker ps 来证实这件事。
因此,接下来我准备庆祝成功把一个请求从主机转发到了 container 里:
```
curl http://localhost:5000/api/books
```
它不能够工作。
重复进行相同请求我看到了一两个错误56接收失败连接相同等或卷曲复位52来自服务器的空回复。
我返回 docker运行文件然后双重检查我所使用的 -p 选项以及 Docker 文件中的 EXPOSE 指令是否正确。我没有发现任何问题,这让我开始有些沮丧。
重新站起来以后,我决定去咨询当地的一个大师 - Dave Wybourn他也在文章里提到 Docker Swarm他的团队也曾遇到这个实际问题。但问题是我没有配置过 Kestral - 一个全新的轻量级跨平台 web 服务器,用于 .NET 核心。
默认情况下, Kestrel 会监听 http://localhost:5000。但问题是这儿的本地主机是一个回路接口。
通过维基百科:
> 在计算机网络中,本地主机是一个象征着这台电脑的主机名。本地主机可以通过网络回路接口访问在主机上运行的网络服务。通过使用回路接口可以绕过任何硬件网络接口。
在 container 内运行应用是一个新的问题,因为本地主机只能够通过 container 到达。解决方法是更新 Startup.cs 里的主要方法来配置被 Kestral 监听的 URLs
```
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls("http://*:5000") // listen on port 5000 on all network interfaces
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
```
通过这些额外的配置,我可以重建图像,并在 container 中运行应用程序,它将能够接收来自主机的请求:
1. docker build -t niksoper/netcore-books .
2. docker run -d -p 5000:5000 niksoper/netcore-books
3. curl -i http://localhost:5000/api/books
我现在得到下面这些回应:
```
HTTP/1.1 200 OK
日期Tue, 30 Aug 2016 15:25:43 GMT
编码传输: chunked
内容类型: application/json; charset=utf-8
服务器: Kestrel
[{"id":"1","title":"RESTful API with ASP.NET Core MVC 1.0","author":"Nick Soper"}]
```
### 创建 KESTREL
微软的介绍:
>Kestrel 可以很好的处理来自 ASP.NET 的动态内容,然而,网络服务部分的特性没有达到 IISApache 或者 Niginx 那样的全特性服务器好。反向代理服务器可以让你不用去做像处理静态内容,缓存请求,压缩请求,来自 HTTP 服务器的 SSL 终止这样的工作。
因此我需要在 Linux 上把 Nginx 设置成一个反向代理服务器。微软发布了如何在 Linux 生产环境下进行设置的指导教程。我把说明总结在这儿:
1. 通过 dotnet 发布来给应用程序产生一个自包含包。
2. 把已发布的应用程序复制到服务器上
3. 安装并配置 Nginx如同配置一个反向代理服务器一样
4.安装并配置管理员(确保 Nginx 服务器处于运行状态中)
5.安装并配置 AppArmor限制应用的可用资源
6.配置服务器防火墙
7.保护好 Nginx涉及从源代码构建和配置 SSL
这些内容已经超出了本文的范围,因此我将侧重于如何把 Nginx 配置成一个反向代理服务器。自然地,我通过 Docker 来完成这件事。
### 在另一个 CONTAIER 中运行 NGINX
我的目标是在一个二级 Docker container 中运行 Nginx 并把它配置成应用程序 container 的反向代理服务器。
我使用的是来自 Docker Hub 的官方 Nginx 图像。首先我尝试这样做:
```
docker run -d -p 8080:80 --name web nginx
```
这启动了一个运行 Nginx 的 container 并把主机上的 8080 端口映射到了 container 的 80 端口上。现在在浏览器中打开网址 http://localhost:8080 会显示出 Nginx 的默认登录页面。
现在我们证实了运行 Nginx 是多么的简单,我们可以关闭 container.
```
docker rm -f web
```
### 把 NGINX配置成一个反向代理服务器
可以通过像下面这样编辑位于目录 /etc/nginx/conf.d/default.conf 下的配置文件把 Nginx 配置成一个反向代理服务器:
```
server {
listen 80;
location / {
proxy_pass http://localhost:6666;
}
}
```
通过上面的配置可以让 Nginx 代理从 root 到 http://localhost:6666 的所有请求。记住这里的本地主机指的是运行 Nginx 的 container. 我们可以利用卷来使用在 Nginx container 内部的配置文件:
```
docker run -d -p 8080:80 \
-v /path/to/my.conf:/etc/nginx/conf.d/default.conf \
nginx
```
注意:这把一个单一文件从主机映射到 container 中,而不是一个完整目录。
### 在 CONTAINER 间进行通信
Docer 允许内部 container 通过共享虚拟网络进行通信。默认情况下,所有
通过 Dcocker 后台程序启动的 container 都可以访问一种叫做桥的虚拟网络。这使得一个 container 可以被另一个 container 在相同的网络上通过 IP 地址和端口来引用。
你可以通过监测 container 来找到它的 IP 地址。我将从之前创建的 niksoper/netcore-books 图像中启动一个 container 并监测它:
1. docker run -d -p 5000:5000 --name books niksoper/netcore-books
2. docker inspect books
![](http://blog.scottlogic.com/nsoper/assets/docker-inspect-ip.PNG)
我们可以看到这个 container 的 IP 地址是 "IPAddress": "172.17.0.3".
所以现在如果我创建下面的 Nginx 配置文件,并使用这个文件启动一个 Nginx container 它将代理请求到我的应用程序界面【API】:
```
server {
listen 80;
location / {
proxy_pass http://172.17.0.3:5000;
}
}
```
现在我可以使用这个配置文件启动一个 Nginx container注意我把主机上的 8080 端口映射到了 Nginx container 上的 80 端口):
```
docker run -d -p 8080:80 \
-v ~/dev/nginx/my.nginx.conf:/etc/nginx/conf.d/default.conf \
nginx
```
一个到 http://localhost:8080 的请求代理到应用上。注意下面卷反应的服务器标题:
![](http://blog.scottlogic.com/nsoper/assets/nginx-proxy-response.PNG)
### DOCKER Compose
在这个地方,我为自己的进步而感到高兴,但我认为一定还有更好的方法来配置 Nginx可以不需要知道应用程序 container 的确切 IP 地址。另一个当地的大师 Jason Ebbin - Scott Logic DevOps 在这个地方进行了改进,并建议使用 Docker Compose。
作为一个高层次的描述 - Docker Compose 使得一组互相连接的 container 很容易通过声明式语法来启动。我不想再细说 Docker Compose 是如何工作的因为你可以在之前的文章中找到。
我将通过一个我所使用的 docker-compose.yml 文件来启动:
```
version: '2'
services:
books-service:
container_name: books-api
build: .
reverse-proxy:
container_name: reverse-proxy
image: nginx
ports:
- "9090:8080"
volumes:
- ./proxy.conf:/etc/nginx/conf.d/default.conf
```
这是版本 2 的语法,所以为了能够正常工作,你至少需要 1.6 版本的 Docker Compose.
这个文件告诉 Docker 创建两条服务 - 一条是给应用的,另一条是给 Nginx 反向代理服务器的。
### 服务列表
这将从相同目录下的 Docker 文件创建一个叫做 books-api 的 conainer 作为 docker-compose.yml。注意这个 container 不需要发布任何端口,因为只要能够从反向代理服务器访问它就可以,而不需要从主机操作系统访问它。
### 反向代理
这将启动一个基于 nginx 图像叫做 反向代理reverse-proxy的container,并把位于当前目录下的 proxy.conf 文件安装成为配置。它把主机上的 9090 端口映射到 container 中的 8080 端口,这将允许我们在 http://localhost:9090. 上通过主机访问 container.
proxy.conf 文件看起来像下面这样:
```
server {
listen 8080;
location / {
proxy_pass http://books-service:5000;
}
}
```
这儿的关键点是我们现在可以通过名字引用 【服务列表】,因此我们不需要知道 books-api 这个 container 的 IP 地址!
现在我们可以通过一个运行着的反向代理启动两个 container-d 意味着这是独立的,因此我们不能看到来自 container 的输出):
```
docker compose up -d
```
证实我们所创建的 container
```
docker ps
```
最后来证实我们可以通过反向代理来控制应用程序界面【API】
```
curl -i http://localhost:9090/api/books
```
### 发生了什么?
Docker Compose 通过创建一个新的叫做 mvclibrary_default 的虚拟网络来实现这件事,这个虚拟网络同时用于 books-api 和反向代理的 container名字是基于 docker-compose.yml 文件的父目录)。
![](http://blog.scottlogic.com/nsoper/assets/docker-network-ls.PNG)
你可以看到新的网络通过 docker 网络来监测 mvclibrary_default 的所有细节:
![](http://blog.scottlogic.com/nsoper/assets/network-inspect.PNG)
注意 Docker 已经分配了子网“172.18.0.0/16”。/16 部分是无类域内路由选择【CIDR】一个完整的解释已经超出了本文的范围但无类域内路由选择【CIDR】仅表示一个 IP 地址范围。运行 docker 网络来监测桥显示子网“172.17.0.0/16”因此这两个网络是不重叠的。
现在用 docker 来监测 books-api 从而证实应用程序的 container 是使用该网络:
![](http://blog.scottlogic.com/nsoper/assets/docker-inspect-books-api.PNG)
注意 container 的两个别名是 container 标识符3c42db680459和由 docker-compose.yml (服务列表)给出的服务名。我们通过服务列表别名来引用在自定义 Nginx 配置文件中的应用程序的 container。这本可以通过 docker 网络手动创建,但是我喜欢用 Docker Compose因为它可以干净简洁的收捲已创建和相互依存的 container。
### 结论
所以现在我可以通过几个简单的步骤在 Linux 系统上用 Nginx 运行应用程序,不需要对主机操作系统做任何长期的改变:
```
git clone https://github.com/niksoper/aspnet5-books.git
cd aspnet5-books/src/MvcLibrary
git checkout blog-docker
docker-compose up -d
curl -i http://localhost:9090/api/books
```
我知道我在这篇文章中所写的内容不是一个真正的生产准备设置,因为我没有写任何有关下面这些的内容,但是绝大多数下面的这些主题都需要用单独一篇完整的文章来叙述。
- 安全考虑比如防火墙和 SSL 配置
- 如何确保应用程序保持运行状态
- 如何选择需要包含的 Docker 图像(我把所有的都放入了 Dockerfile 中)
- 数据库 - 如何在 container 中管理应用
对我来说这是一个非常有趣的学习经历,因为有一段时间我对探索伴有 ASP.NET 核心的跨平台支持非常好奇使用针对 “Configuratin as Code” 的 Docker Compose 方法来探索一下 DevOps 的世界也是非常愉快并且很有教育意义的。
如果你对 Docker 很好奇,那么我鼓励你来尝试学习它 - 特别地,这是否会让你感到痛苦,谁知道呢,有可能你会喜欢它?
--------------------------------------------------------------------------------
via: http://blog.scottlogic.com/2016/09/05/hosting-netcore-on-linux-with-docker.html?utm_source=webopsweekly&utm_medium=email
作者:[Nick Soper][a]
译者:[ucasFL](https://github.com/ucasFL)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://blog.scottlogic.com/nsoper
[1]: http://blog.scottlogic.com/2016/01/20/restful-api-with-aspnet50.html
[2]: https://docs.microsoft.com/en-us/dotnet/articles/core/migrating-from-dnx
[3]: https://docs.asp.net/en/latest/migration/rc1-to-rtm.html
[4]: http://www.paraesthesia.com/archive/2016/06/29/netcore-rtm-where-is-autofac/

View File

@ -1,322 +0,0 @@
17 个 tar 命令使用例示
=====
Tar (tape archive 磁带归档的缩写LCTT 译注:最初设计用于将打包到磁带上,现在我们大都使用它来实现备份某个分区或者某些重要的目录) 是类 Unix 系统中使用最广泛的命令,用于归档多个文件或者目录到单个归档文件中,并且可以同时对归档文件使用 gzip 或者 bzip2 压缩技术。换句话说tar 命令也可以用于备份:先是归档多个文件和目录到一个单独的 tar 文件,然后在需要之时将 tar 文件中的文件和目录释放出来。
本文将介绍 tar 的 17 个使用例示。
tar 命令语法如下:
```
# tar <选项> <文件>
```
下面列举 tar 命令中一些常用的选项:
```
--delete : 从归档文件 (而非磁带) 中删除
-r, --append : 将文件追加到归档文件中
-t, --list : 列出归档文件中包含的内容
--test-label : 测试归档文件卷标并退出
-u, --update : 将已更新的文件追加到归档文件中
-x, --extract, --get : 释放归档文件中文件及目录
-C, --directory-DIR : 执行归档动作前变更工作目录到 DIR
-f, --file=ARCHIVE : 指定 (将要创建或已存在的) 归档文件名
-j, --bip2 : 对归档文件使用 bzip2 压缩
-J, --xz : 对归档文件使用 xz 压缩
-p, --preserve-permissions : 保留原文件的访问权限
-v, --verbose : 显示命令整个执行过程
-z, gzip : 对归档文件使用 gzip 压缩
```
注 : 在 tar 命令选项中的连接符 ( ) 是可选的 (LCTT 译注:不用 - 也没事)。
### 例示 1创建一个 tar 归档文件
现在来创建一个 tar 文件,将 /etc/ 目录和 /root/anaconda-ks.cfg 文件打包进去。
```
[root@linuxtechi ~]# tar -cvf myarchive.tar /etc /root/anaconda-ks.cfg
```
以上命令会在当前目录创建一个名为 “myarchive” 的 tar 文件,内含 /etc/ 目录和 /root/anaconda-ks.cfg 文件。
其中,‘-c 选项表示要创建 tar 文件,‘-v 选项用于输出 tar 进程到屏幕上,‘-f 选项则是指定归档文件名称。
```
[root@linuxtechi ~]# ls -l myarchive.tar
-rw-r--r--. 1 root root 22947840 Sep 7 00:24 myarchive.tar
[root@linuxtechi ~]#
```
### 例示 2列出归档文件中的内容
在 tar 命令中使用 t 选项可以不用释放其中的文件就可以快速列出文件中包含的内容。
```
[root@linuxtechi ~]# tar -tvf myarchive.tar
```
列出 tar 文件中的指定文件和目录。下列命令尝试查看 anaconda-ks.cfg 文件是否存在于 tar 文件中。
```
[root@linuxtechi ~]# tar -tvf myarchive.tar root/anaconda-ks.cfg
-rw------- root/root 953 2016-08-24 01:33 root/anaconda-ks.cfg
[root@linuxtechi ~]#
```
### 例示 3追加文件到归档 ( tar ) 文件中
-r 选项用于向已有的 tar 文件中追加文件。下面来将 /etc/fstab 添加到 data.tar 中。
```
[root@linuxtechi ~]# tar -rvf data.tar /etc/fstab
```
注:在压缩过的 tar 文件中无法进行追加文件操作。
### 例示 4从 tar 文件中释放文件以及目录
-x 选项用于释放出 tar 文件中的文件和目录。下面来释放上边创建的 tar 文件中的内容。
```
[root@linuxtechi ~]# tar -xvf myarchive.tar
```
这个命令会在当前目录中释放出 myarchive tar 文件中的内容。
### 例示 5释放 tar 文件到指定目录
假如你想要释放 tar 文件中的内容到指定的文件夹或者目录,使用 -C 选项后边加上指定的文件的路径。
```
[root@linuxtechi ~]# tar -xvf myarchive.tar -C /tmp/
```
### 例示 6释放 tar 文件中的指定文件或目录
假设你只要释放 tar 文件中的 anaconda-ks.cfg 到 /tmp 目录。
语法如下:
```
# tar xvf {tar-file } {file-to-be-extracted } -C {path-where-to-extract}
[root@linuxtechi tmp]# tar -xvf /root/myarchive.tar root/anaconda-ks.cfg -C /tmp/
root/anaconda-ks.cfg
[root@linuxtechi tmp]# ls -l /tmp/root/anaconda-ks.cfg
-rw-------. 1 root root 953 Aug 24 01:33 /tmp/root/anaconda-ks.cfg
[root@linuxtechi tmp]#
```
### 例示 7创建并压缩归档文件 ( .tar.gz 或 .tgz )
假设我们需要打包 /etc 和 /opt 文件,并用 gzip 工具将其压缩。可以在 tar 命令中使用 -z 选项来实现。这样 tar 文件的扩展名可以是 .tar.gz 或者 .tgz。
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tar.gz /etc/ /opt/
```
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tgz /etc/ /opt/
```
### 例示 8创建并压缩归档文件 ( .tar.bz2 或 .tbz2 )
假设我们需要打包 /etc 和 /opt 文件,并是用 bzip2 压缩。可以在 tar 命令中使用 -j 选项来实现。这样 tar 文件的扩展名可以是 .tar.bz2 或者 .tbz。
```
[root@linuxtechi ~]# tar -jcpvf myarchive.tar.bz2 /etc/ /opt/
```
```
[root@linuxtechi ~]# tar -jcpvf myarchive.tbz2 /etc/ /opt/
```
### 例示 9排除指定文件或类型后创建 tar 文件
创建 tar文件时在 tar 命令中使用 “exclude” 选项可以排除指定文件或者类型。假设在创建压缩的 tar 文件时要排除 html 文件。
```
[root@linuxtechi ~]# tar -zcpvf myarchive.tgz /etc/ /opt/ --exclude=*.html
```
### 例示 10列出 .tar.gz 或 .tgz 文件中的内容
使用 -t 选项可以查看 tar.gz 或 .tgz 文件中内容。如下:
```
[root@linuxtechi ~]# tar -tvf myarchive.tgz | more
.............................................
drwxr-xr-x root/root 0 2016-09-07 08:41 etc/
-rw-r--r-- root/root 541 2016-08-24 01:23 etc/fstab
-rw------- root/root 0 2016-08-24 01:23 etc/crypttab
lrwxrwxrwx root/root 0 2016-08-24 01:23 etc/mtab -> /proc/self/mounts
-rw-r--r-- root/root 149 2016-09-07 08:41 etc/resolv.conf
drwxr-xr-x root/root 0 2016-09-06 03:55 etc/pki/
drwxr-xr-x root/root 0 2016-09-06 03:15 etc/pki/rpm-gpg/
-rw-r--r-- root/root 1690 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
-rw-r--r-- root/root 1004 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-7
-rw-r--r-- root/root 1690 2015-12-09 04:59 etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Testing-7
-rw-r--r-- root/root 3140 2015-09-15 06:53 etc/pki/rpm-gpg/RPM-GPG-KEY-foreman
..........................................................
```
### 例示 11列出 .tar.bz2 或 .tbz2 文件中的内容
使用 -t 选项可以查看 tar.bz2 或 .tbz2 文件中内容。如下:
```
[root@linuxtechi ~]# tar -tvf myarchive.tbz2 | more
........................................................
rwxr-xr-x root/root 0 2016-08-24 01:25 etc/pki/java/
lrwxrwxrwx root/root 0 2016-08-24 01:25 etc/pki/java/cacerts -> /etc/pki/ca-trust/extracted/java/cacerts
drwxr-xr-x root/root 0 2016-09-06 02:54 etc/pki/nssdb/
-rw-r--r-- root/root 65536 2010-01-12 15:09 etc/pki/nssdb/cert8.db
-rw-r--r-- root/root 9216 2016-09-06 02:54 etc/pki/nssdb/cert9.db
-rw-r--r-- root/root 16384 2010-01-12 16:21 etc/pki/nssdb/key3.db
-rw-r--r-- root/root 11264 2016-09-06 02:54 etc/pki/nssdb/key4.db
-rw-r--r-- root/root 451 2015-10-21 09:42 etc/pki/nssdb/pkcs11.txt
-rw-r--r-- root/root 16384 2010-01-12 15:45 etc/pki/nssdb/secmod.db
drwxr-xr-x root/root 0 2016-08-24 01:26 etc/pki/CA/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/certs/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/crl/
drwxr-xr-x root/root 0 2015-06-29 08:48 etc/pki/CA/newcerts/
drwx------ root/root 0 2015-06-29 08:48 etc/pki/CA/private/
drwx------ root/root 0 2015-11-20 06:34 etc/pki/rsyslog/
drwxr-xr-x root/root 0 2016-09-06 03:44 etc/pki/pulp/
..............................................................
```
### 例示 12解压 .tar.gz 或 .tgz 文件
使用 -x-z 选项来解压 tar.gz 或 .tgz 文件。如下:
```
[root@linuxtechi ~]# tar -zxpvf myarchive.tgz -C /tmp/
```
以上命令将 tar 文件解压到 /tmp 目录。
注:现今的 tar 命令会执行解压动作前自动检查文件的压缩类型,这意味着我们在使用 tar 命令是可以不用指定文件的压缩类型。如下:
```
[root@linuxtechi ~]# tar -xpvf myarchive.tgz -C /tmp/
```
### 例示 13解压 .tar.bz2 或 .tbz2 文件
使用 -j-z 选项来解压 tar.bz2 或 .tbz2 文件。如下:
```
[root@linuxtechi ~]# tar -jxpvf myarchive.tbz2 -C /tmp/
```
```
[root@linuxtechi ~]# tar xpvf myarchive.tbz2 -C /tmp/
```
### 例示 14使用 tar 命令进行定时备份
总有一些实时场景需要我们对指定的文件和目录进行打包,已达到日常备份的目的。假设需要每天备份整个 /opt 命令,可以创建一个带 tar 命令的 cron 任务来完成。如下:
```
[root@linuxtechi ~]# tar -zcvf optbackup-$(date +%Y-%m-%d).tgz /opt/
```
在创建 cron 任务时使用以上命令。
### 例示 15使用 -T 及 -X 创建压缩归档文件
想像这样一个场景:把想要归档和压缩的文件及目录记录到到一个文件,有时候还要排除这个文件记录中的特定路径后,把这个文件当做 tar 命令的传入参数来完成归档任务。
要达到这样的效果,在命令中使用 -T 选项跟记录了归档路径的文件、‘-X 选项跟排除特定路径的文件即可。
假设要归档 /etc、/opt、/home 目录,并排除 /etc/sysconfig/kdump/etc/sysconfig/foreman 文件,可以创建 /root/tar-include/root/tar-exclude 然后分别输入一下内容:
```
[root@linuxtechi ~]# cat /root/tar-include
/etc
/opt
/home
[root@linuxtechi ~]#
[root@linuxtechi ~]# cat /root/tar-exclude
/etc/sysconfig/kdump
/etc/sysconfig/foreman
[root@linuxtechi ~]#
```
运行一下命令来创建一个压缩归档文件。
```
[root@linuxtechi ~]# tar zcpvf mybackup-$(date +%Y-%m-%d).tgz -T /root/tar-include -X /root/tar-exclude
```
### 例示 16查看 .tar、.tgz 和 .tbz2 文件的大小
使用如下命令来查看 (压缩) tar 文件的体积。
```
[root@linuxtechi ~]# tar -czf - data.tar | wc -c
427
[root@linuxtechi ~]# tar -czf - mybackup-2016-09-09.tgz | wc -c
37956009
[root@linuxtechi ~]# tar -czf - myarchive.tbz2 | wc -c
30835317
[root@linuxtechi ~]#
```
### 例示 17分割体积庞大的 tar 文件为多分小文件
类 Unix 系统中使用 split 命令来将大体积文件分割成小体积文件。大体积的 tar 当然也可以使用这个命令来进行分割。
假设需要将 mybackup-2016-09-09.tgz 分割成每份 6 MB 的小文件。
```
Syntax : split -b <Size-in-MB> <tar-file-name>.<extension> “prefix-name”
```
```
[root@linuxtechi ~]# split -b 6M mybackup-2016-09-09.tgz mybackup-parts
```
以上命令会在当前目录分割 mybackup-2016-09-09.tgz 文件成为多个 6 MB 的小文件,文件名为 mybackup-partsaa … mybackup-partsag。如果在要在分割文件后以数字而非字母来区分可以在以上的 split 命令使用 -d 选项。
```
[root@linuxtechi ~]# ls -l mybackup-parts*
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsaa
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsab
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsac
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsad
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsae
-rw-r--r--. 1 root root 6291456 Sep 10 03:05 mybackup-partsaf
-rw-r--r--. 1 root root 637219 Sep 10 03:05 mybackup-partsag
[root@linuxtechi ~]#
```
然后通过网络将这些分割文件转移到其他服务器,就可以合并成为一个单独的 tar 文件了,如下:
```
[root@linuxtechi ~]# cat mybackup-partsa* > mybackup-2016-09-09.tgz
[root@linuxtechi ~]#
```
文毕,希望你喜欢 tar 命令的这几个不同的例示。随时分享你的评论并分享你的心得。
--------------------------------------------------------------------------------
via: http://www.linuxtechi.com/17-tar-command-examples-in-linux/
作者:[Pradeep Kumar ][a]
译者:[GHLandy](https://github.com/GHLandy)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.linuxtechi.com/author/pradeep/

View File

@ -1,126 +0,0 @@
排名前 15 的开源人工智能工具
====
人工智能artificial intelligence, AI是科技研究中最热门的方向之一。像 IBM、谷歌、微软、Facebook 和 亚马逊等公司都在研发上投入大量的资金、或者收购那些在机器学习、神经网络、自然语言和图像处理等领域取得了进展的初创公司。考虑到人们对此感兴趣的程度,我们将不会惊讶于斯坦福的专家在[人工智能报告][1]中得出的结论“越来越强大的人工智能应用可能会对我们的社会和经济产生深远的积极影响这将出现在从现在到2030年的时间段里。”
在最近的一篇[文章][2]中我们概述了45个十分有趣或有前途的人工智能项目。在本文中我们将聚焦于开源的人工智能工具详细的了解下最著名的15个开源人工智能项目。
![](http://www.datamation.com/imagesvr_ce/5668/00AI.jpg)
开源人工智能
以下这些开源人工智能应用都处于人工智能研究的最前沿。
![](http://www.datamation.com/imagesvr_ce/8922/01Caffe.JPG)
### 1. Caffe
它是由[贾扬清][3]在加州大学伯克利分校的读博时创造的Caffe 是一个基于表达体系结构和可扩展代码的深度学习框架。使它声名鹊起的是它的速度,这让它受到研究人员和企业用户的欢迎。根据其网站所言,它可以在一天之内处理 6000 万多个图像而只用一个 NVIDIA K40 GPU。它是由伯克利视野和学习中心BVLC管理的并且由 NVIDIA 和亚马逊等公司资助来支持它的发展。
![](http://www.datamation.com/imagesvr_ce/1232/02CNTK.JPG)
### 2. CNTK
计算网络工具包Computational Network Toolkit的缩写CNIK 是一个微软的开源人工智能工具。不论是在单个 CPU、单个 GPU、多个 GPU 或是拥有多个 GPUs 的多台机器上它都有优异的表现。微软主要用它做语音识别的研究,但是它在机器翻译、图像识别、图像字幕、文本处理、语言理解和语言建模方面都有着良好的应用。
![](http://www.datamation.com/imagesvr_ce/2901/03Deeplearning4j.JPG)
### 3. Deeplearning4j
Deeplearning4j 是一个 java 虚拟机JVM的开源深度学习库。它运行在分布式环境并且集成在 Hadoop 和 Apache Spark 中。这使它可以配置深度神经网络,并且它与 Java、Scala 和 其他 JVM 语言兼容。
这个项目是由一个叫做 Skymind 的商业公司管理的,它为这个项目提供支持、培训和一个企业的发行版。
![](http://www.datamation.com/imagesvr_ce/7269/04DMLT.JPG)
### 4. Distributed Machine Learning Toolkit分布式机器学习工具
和 CNTK 一样分布式机器学习工具Distributed Machine Learning Toolkit, DMTK是微软的开源人工智能工具。作为设计用于大数据的应用程序它的目标是更快的训练人工智能系统。它包括三个主要组件DMTK 框架、LightLDA 主题模型算法和分布式(多义)字嵌入算法。为了证明它的速度,微软声称在一个 8 集群的机器上,他能够 “用 100 万个主题和 1000 万个单词的词汇表(总共 10 万亿参数)训练一个主题模型,在一个文档中收集 1000 亿个符号,”。这一成绩是别的工具无法比拟的。
![](http://www.datamation.com/imagesvr_ce/2890/05H2O.JPG)
### 5. H20
相比起科研H2O 更注重将 AI 服务于企业用户,因此 H2O 有着大量的公司客户比如第一资本金融公司、思科、Nielsen Catalina、PayPal 和泛美都是他的用户。它声称任何人都可以利用机器学习和预测分析的力量来解决业务难题。它可以用于预测建模、风险和欺诈分析、保险分析、广告技术、医疗保健和客户情报。
它有两种开源版本:标准版 H2O 和 Sparking Water 版,他被集成在 Apache Spark 中。也有付费的企业用户支持。
![](http://www.datamation.com/imagesvr_ce/1127/06Mahout.JPG)
### 6. Mahout
它是 Apache 基金项目,是一个开源机器学习框架。根据它的网站所言,它有着三个主要的特性:一个构建可扩展算法的编程环境、像 Spark 和 H2O 一样的预制算法工具和一个叫 Samsara 的矢量数学实验环境。使用 Mahout 的公司有 Adobe、埃森哲咨询公司、Foursquare、英特尔、领英、Twitter、雅虎和其他许多公司。其网站列了出第三方的专业支持。
![](http://www.datamation.com/imagesvr_ce/4038/07MLlib.JPG)
### 7. MLlib
由于其速度Apache Spark 成为一个最流行的大数据处理工具。MLlib 是 Spark 的可扩展机器学习库。它集成了 Hadoop 并可以与 NumPy 和 R 进行交互操作。它包括了许多机器学习算法如分类、回归、决策树、推荐、集群、主题建模、功能转换、模型评价、ML管道架构、ML持续、生存分析、频繁项集和序列模式挖掘、分布式线性代数和统计。
![](http://www.datamation.com/imagesvr_ce/839/08NuPIC.JPG)
### 8. NuPIC
由 Numenta 公司管理的 NuPIC 是一个基于分层暂时记忆Hierarchical Temporal Memory, HTM理论的开源人工智能项目。从本质上讲HTM 试图创建一个计算机系统来模仿人类大脑皮层。他们的目标是创造一个 “在许多认知任务上接近或者超越人类认知能力” 的机器。
除了开源许可Numenta 还提供 NuPic 的商业许可协议,并且它还提供技术专利的许可证。
![](http://www.datamation.com/imagesvr_ce/99/09OpenNN.JPG)
### 9. OpenNN
作为一个为开发者和科研人员设计的具有高级理解力的人工智能OpenNN 是一个实现神经网络算法的 c++ 编程库。它的关键特性包括深度的架构和快速的性能。其网站上可以查到丰富的文档包括一个解释了神经网络的基本知识的入门教程。OpenNN 的付费支持由一家从事预测分析的西班牙公司 Artelnics 提供。
![](http://www.datamation.com/imagesvr_ce/4168/10OpenCyc.JPG)
### 10. OpenCyc
由 Cycorp 公司开发的 OpenCyc 提供了对 Cyc 知识库的访问和常识推理引擎。它拥有超过 239,000 个条目,大约 2,093,000 个三元组和大约 69,000 owl一种类似于链接到外部语义库的命名空间。它在富领域模型、语义数据集成、文本理解、特殊领域的专家系统和游戏 AI 中有着良好的应用。该公司还提供另外两个版本的 Cyc一个免费的用于科研但是不开源和一个提供给企业的但是需要付费。
![](http://www.datamation.com/imagesvr_ce/9761/11Oryx2.JPG)
### 11. Oryx 2
构建在 Apache Spark 和 Kafka 之上的 Oryx 2 是一个专门针对大规模机器学习的应用程序开发框架。它采用一个独特的三层 λ 架构。开发者可以使用 Orys 2 创建新的应用程序,另外它还拥有一些预先构建的应用程序可以用于常见的大数据任务比如协同过滤、分类、回归和聚类。大数据工具供应商 Cloudera 创造了最初的 Oryx 1 项目并且一直积极参与持续发展。
![](http://www.datamation.com/imagesvr_ce/7423/12.%20PredictionIO.JPG)
### 12. PredictionIO
今年的二月, Salesforce 买下 PredictionIO接着在七月他将该平台和商标贡献给 Apache 基金会Apache 基金会将其列为孵育计划。所以当 Salesforce 利用 PredictionIO 技术来发展他的机器学习性能工作将会同步出现在开源版本中。它可以帮助用户创建有机器学习功能的预测引擎这可用于部署能够实时动态查询的Web服务。
![](http://www.datamation.com/imagesvr_ce/6886/13SystemML.JPG)
### 13. SystemML
首先由 IBM 开发 SystemML 现在是一个 Apache 大数据项目。它提供了一个高度可伸缩的平台,可以实现高等数学运算,并且他的算法用 R 或类似 python 的语法写成。企业已经在使用它来跟踪汽车维修客户服务、规划机场交通和连接社会媒体数据与银行客户。他可以在 Spark 或 Hadoop 上运行。
![](http://www.datamation.com/imagesvr_ce/5742/14TensorFlow.JPG)
### 14. TensorFlow
TensorFlow 是一个谷歌的开源人工智能工具。它提供了一个使用数据流图进行数值计算的库。它可以运行在多种不同的有着单或多 CPUs 和 GPUs 的系统,甚至可以在移动设备上运行。它拥有深厚的灵活性、真正的可移植性、自动微分功能并且支持 Python 和 c++。它的网站拥有十分详细的教程列表来帮助开发者和研究人员沉浸于使用或扩展他的功能。
![](http://www.datamation.com/imagesvr_ce/9018/15Torch.JPG)
### 15. Torch
Torch 将自己描述为:“一个优先使用 GPUs 的拥有机器学习算法广泛支持的科学计算框架”,他的特点是灵活性和速度。此外,它可以很容易的运用机器学习、计算机视觉、信号处理、并行处理、图像、视频、音频和网络的包。他依赖一个叫做 LuaJIT 的脚本语言,而 LuaJIT 是基于 Lua 的。
--------------------------------------------------------------------------------
via: http://www.datamation.com/open-source/slideshows/15-top-open-source-artificial-intelligence-tools.html
作者:[Cynthia Harvey][a]
译者:[Chao-zhi](https://github.com/Chao-zhi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.datamation.com/author/Cynthia-Harvey-6460.html
[1]: https://ai100.stanford.edu/sites/default/files/ai_100_report_0906fnlc_single.pdf
[2]: http://www.datamation.com/applications/artificial-intelligence-software-45-ai-projects-to-watch-1.html
[3]: http://daggerfs.com/

View File

@ -1,58 +0,0 @@
在 WordPress 下如何通过 Markdown 来提高工作效率
====
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/09/markdown-wordpress-featured-2.jpg)
Markdown 是一种简单的标记语言,旨在帮助你花费更小的代价来格式化纯文本文档。在 WordPress 下你可以使用 HTML 或者 Visual Editor 来格式化你的文档,但是使用 markdown 可以让格式化文档变得更加容易而且你随时可以导出成很多种格式包括但不限于HTML。
WordPress 没有进行本地 markdown 的支持,但是,如果你希望的话,在你的网站上有多种插件可以添加这种功能。
在这个教程中,我将会演示如何使用流行的 WP-Markdown 插件来添加 WordPress 网站对于 markdown 的支持。
### 安装
通过选择导航栏中的 “Plugins -> Add New”然后在提供的搜索框中输入 “[wp-markdown][1]” 就可以直接安装。插件应该会出现在列表中的第一个。单击 “Install Now” 进行安装。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/markdown-wordpress-install-plugin-1.png)
### 配置
一旦你已经安装了这个插件并且激活它之后,菜单中导航到 “Settings -> Writing” 并向下滚动,直到 markdown 选项。
你可以启用文章、页面和评论中对于 markdown 的支持。如果你只是学习 markdown 的语法,那么你也可以在文章编辑器或者评论地方启用一个帮助栏。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/09/markdown-wordpress-configuration.png)
如果在你的博客文章中也包括代码片段的话,那么启用 “Prettify syntax highlighter” 将会让你的代码片段自动语法高亮。
一旦对于你的选择感觉满意的话,那么就单击 “Save Changes” 来保存你的设置吧。
### 使用 Markdown 来写你的文章
一旦你在自己网站中启用了 markdown 的支持,你就可以立马开始使用了。
通过 “Posts -> Add New” 创建一篇新的文章。你将会注意到默认的视觉和纯文本编辑器已经被 markdown 编辑器所替代。
如果你在配置选项中没有启用 markdown 的帮助栏,你将不会看到 markdown 格式化后的实时预览。然而,只要你的语法是正确的,当你保存或者发布文章的时候,你的 markdown 就会转换成正确的 HTML。
然而,如果你是 markdown 的初学者的话,实时预览这一特征对你会很重要,只需要简单的回到刚才的设置中启用帮助栏选项,你就可以在你的文章底部得到一片不错的实时预览的区域。另外,你也可以在顶部看到很多按钮,它们将帮助你在文章中快速的插入 markdown 元素。如果人们使用它的话,这将是一个潜在的惊人的设置。你可以调整单个应用程序通知的优先级。这将让你自己选择在通知栏看到的东西。
![](https://maketecheasier-2d0f.kxcdn.com/assets/uploads/2016/08/markdown-wordpress-create-post.png)
### 结语
正如你所看到的那样,在 WordPress 网站上添加 markdown 支持是真的容易,你将只需要花费几分钟的时间就可以了。如果对于 markdown 你全然不知的话,或许你也可以查看我们的 [markdown 备忘录][2],它将对于 markdown 语法提供一个全面的参考。
--------------------------------------------------------------------------------
via: https://www.maketecheasier.com/use-markdown-in-wordpress/?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+maketecheasier
作者:[Ayo Isaiah][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.maketecheasier.com/author/ayoisaiah/
[1]: https://wordpress.org/plugins/wp-markdown/
[2]: https://www.maketecheasier.com/productive-with-markdown-cheatsheet/

View File

@ -0,0 +1,200 @@
使用 Elasticsearch 和 cAdvisor 监控 Docker 容器
=======
如果你正在运行 Swarm 模式的集群,或者只运行单台 Docker你都会有下面的疑问
> 我如何才能监控到它们都在干些什么?
这个问题的答案是“很不容易”。
你需要监控下面的参数:
1. 容器的数量和状态。
2. 一台容器是否已经移到另一个节点了,如果是,那是在什么时候,移动到哪个节点?
3. 给定节点上运行着的容器数量。
4. 一段时间内的通信峰值。
5. 孤儿卷和网络LCTT 译注:孤儿卷就是当你删除容器时忘记删除它的卷,这个卷就不会再被使用,但会一直占用资源)。
6. 可用磁盘空间、可用 inode 数。
7. 容器数量与连接在 docker0 和 docker_gwbridge 上的虚拟网卡数量不一致LCTT 译注:当 docker 启动时,它会在宿主机器上创建一个名为 docker0 的虚拟网络接口)。
8. 开启和关闭 Swarm 节点。
9. 收集并集中处理日志。
本文的目标是介绍 [Elasticsearch][1] + [Kibana][2] + [cAdvisor][3] 的用法,使用它们来收集 Docker 容器的参数,分析数据并产生可视化报表。
阅读本文后你可以发现有一个监控仪表盘能够部分解决上述列出的问题。但如果只是使用 cAdvisor有些参数就无法显示出来比如 Swarm 模式的节点。
如果你有一些 cAdvisor 或其他工具无法解决的特殊需求,我建议你开发自己的数据收集器和数据处理器(比如 [Beats][4]),请注意我不会演示如何使用 Elasticsearch 来集中收集 Docker 容器的日志。
> [“你要如何才能监控到 Swarm 模式集群里面发生了什么事情?要做到这点很不容易。” —— @fntlnz][5]
### 我们为什么要监控容器?
想象一下这个经典场景:你在管理一台或多台虚拟机,你把 tmux 工具用得很溜,用各种 session 事先设定好了所有基础的东西,包括监控。然后生产环境出问题了,你使用 `top`、`htop`、`iotop`、`jnettop` 各种 top 来排查,然后你准备好修复故障。
现在重新想象一下你有 3 个节点,包含 50 台容器,你需要在一个地方查看整洁的历史数据,这样你知道问题出在哪个地方,而不是把你的生命浪费在那些字符界面来赌你可以找到问题点。
### 什么是 Elastic Stack
Elastic Stack 就一个工具集,包括以下工具:
- Elasticsearch
- Kibana
- Logstash
- Beats
我们会使用其中一部分工具,比如使用 Elasticsearch 来分析基于 JSON 格式的文本,以及使用 Kibana 来可视化数据并产生报表。
另一个重要的工具是 [Beats][4],但在本文中我们还是把精力放在容器上,官方的 Beats 工具不支持 Docker所以我们选择原生兼容 Elasticsearch 的 cAdvisor。
[cAdvisor][3] 工具负责收集、整合正在运行的容器数据,并导出报表。在本文中,这些报表被到入到 Elasticsearch 中。
cAdvisor 有两个比较酷的特性:
- 它不只局限于 Docker 容器。
- 它有自己的 Web 服务器,可以简单地显示当前节点的可视化报表。
### 设置测试集群,或搭建自己的基础架构
和我[以前的文章][9]一样,我习惯提供一个简单的脚本,让读者不用花很多时间就能部署好和我一样的测试环境。你可以使用以下(非生产环境使用的)脚本来搭建一个 Swarm 模式的集群,其中一个容器运行着 Elasticsearch。
> 如果你有充足的时间和经验,你可以搭建自己的基础架构 (Bring Your Own InfrastructureBYOI)。
如果要继续阅读本文,你需要:
- 运行 Docker 进程的一个或多个节点docker 版本号大于等于 1.12)。
- 至少有一个独立运行的 Elasticsearch 节点(版本号 2.4.X
重申一下,此 Elasticsearch 集群环境不能放在生产环境中使用。生产环境也不推荐使用单节点集群,所以如果你计划安装一个生产环境,请参考 [Elastic 指南][6]。
### 对喜欢尝鲜的用户的友情提示
我就是一个喜欢尝鲜的人(当然我也已经在生产环境中使用了最新的 alpha 版本),但是在本文中,我不会使用最新的 Elasticsearch 5.0.0 alpha 版本,我还不是很清楚这个版本的功能,所以我不想成为那个引导你们出错的关键。
所以本文中涉及的 Elasticsearch 版本为最新稳定版 2.4.0。
### 测试集群部署脚本
前面已经说过,我提供这个脚本给你们,让你们不必费神去部署 Swarm 集群和 Elasticsearch当然你也可以跳过这一步用你自己的 Swarm 模式引擎和你自己的 Elasticserch 节点。
执行这段脚本之前,你需要:
- [Docker Machine][7] 最终版:在 DigitalOcean 中提供 Docker 引擎。
- [DigitalOcean API Token][8]: 让 docker 机器按照你的意思来启动节点。
![](https://resources.codeship.com/hubfs/CTAs/EVAL/Codeship_Request_Trial_Access.png?t=1473869513342)
### 创建集群的脚本
现在万事俱备,你可以把下面的代码拷到 create-cluster.sh 文件中:
```
#!/usr/bin/env bash
#
# Create a Swarm Mode cluster with a single master and a configurable number of workers
workers=${WORKERS:-"worker1 worker2"}
#######################################
# Creates a machine on Digital Ocean
# Globals:
# DO_ACCESS_TOKEN The token needed to access DigitalOcean's API
# Arguments:
# $1 the actual name to give to the machine
#######################################
create_machine() {
docker-machine create \
-d digitalocean \
--digitalocean-access-token=$DO_ACCESS_TOKEN \
--digitalocean-size 2gb \
$1
}
#######################################
# Executes a command on the specified machine
# Arguments:
# $1 The machine on which to run the command
# $2..$n The command to execute on that machine
#######################################
machine_do() {
docker-machine ssh $@
}
main() {
if [ -z "$DO_ACCESS_TOKEN" ]; then
echo "Please export a DigitalOcean Access token: https://cloud.digitalocean.com/settings/api/tokens/new"
echo "export DO_ACCESS_TOKEN=<yourtokenhere>"
exit 1
fi
if [ -z "$WORKERS" ]; then
echo "You haven't provided your workers by setting the \$WORKERS environment variable, using the default ones: $workers"
fi
# Create the first and only master
echo "Creating the master"
create_machine master1
master_ip=$(docker-machine ip master1)
# Initialize the swarm mode on it
echo "Initializing the swarm mode"
machine_do master1 docker swarm init --advertise-addr $master_ip
# Obtain the token to allow workers to join
worker_tkn=$(machine_do master1 docker swarm join-token -q worker)
echo "Worker token: ${worker_tkn}"
# Create and join the workers
for worker in $workers; do
echo "Creating worker ${worker}"
create_machine $worker
machine_do $worker docker swarm join --token $worker_tkn $master_ip:2377
done
}
main $@
```
赋予它可执行权限:
```
chmod +x create-cluster.sh
```
### 创建集群
如文件名所示,我们可以用它来创建集群。默认情况下这个脚本会创建一个 master 和两个 worker如果你想修改 worker 个数,可以设置环境变量 WORKERS。
现在就来创建集群吧。
```
./create-cluster.sh
```
你可以出去喝杯咖啡,因为这需要花点时间。
最后集群部署好了。
--------------------------------------------------------------------------------
via: https://blog.codeship.com/monitoring-docker-containers-with-elasticsearch-and-cadvisor/
作者:[Lorenzo Fontana][a]
译者:[bazz2](https://github.com/bazz2)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://blog.codeship.com/author/lorenzofontana/
[1]: https://github.com/elastic/elasticsearch
[2]: https://github.com/elastic/kibana
[3]: https://github.com/google/cadvisor
[4]: https://github.com/elastic/beats
[5]: https://twitter.com/share?text=%22How+do+you+keep+track+of+all+that%27s+happening+in+a+Swarm+Mode+cluster%3F+Not+easily.%22+via+%40fntlnz&url=https://blog.codeship.com/monitoring-docker-containers-with-elasticsearch-and-cadvisor/
[6]: https://www.elastic.co/guide/en/elasticsearch/guide/2.x/deploy.html
[7]: https://docs.docker.com/machine/install-machine/
[8]: https://cloud.digitalocean.com/settings/api/tokens/new
[9]: https://blog.codeship.com/nginx-reverse-proxy-docker-swarm-clusters/

View File

@ -1,54 +0,0 @@
TaskwarriorLinux下一个很棒的命令行TODO工具
====
Taskwarrior是Ubuntu/Linux下一个简单直接的基于命令行的TODO工具。这个开源软件是我曾用过的最简单的[基于命令行的工具][4]之一。Taskwarrior帮助你更好地组织你自己而不用安装笨重的新工具这有时破坏了TODO工具的目的。
![](https://2.bp.blogspot.com/-pQnRlOUNIxk/V9cuc3ytsBI/AAAAAAAAKHs/yYxyiAk4PwMIE0HTxlrm6arWOAPcBRRywCLcB/s1600/taskwarrior-todo-app.png)
### Taskwarrior一个基于简单的基于命令行帮助完成任务的TODO工具
Taskwarrior是一个开源、跨平台、基于命令行的TODO工具它帮你在终端中管理你的to-do列表。这个工具让你可以轻松地添加任务、展示列表、移除任务。同时在你的默认仓库中就由不用安装新的PPA。在 Ubuntu 16.04 LTS或者相似的发行版中。在终端中按照如下步骤安装Taskwarrior。
```
sudo apt-get install task
```
一个简单的使用如下:
```
$ task add Read a book
Created task 1.
$ task add priority:H Pay the bills
Created task 2.
```
我使用上面截图中的同样一个例子。是的你可以设置优先级H、L或者M。并且你可以使用task或者task next命令来查看你最新创建的to-do列表。比如
```
$ task next
ID Age P Description Urg
-- --- - -------------------------------- ----
2 10s H Pay the bills 6
1 20s Read a book 0
```
完成之后你可以使用task 1 done或者task 2 done来清除列表。[可以在这里][1]找到更加全面的命令和使用案例。同样Taskwarrior是跨平台的这意味着不管怎样你都可以找到一个[满足你需求][2]的版本。如果你需要的话,这里甚至有[一个安卓版][3]。用得开心!
--------------------------------------------------------------------------------
via: http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+techdrivein+%28Tech+Drive-in%29
作者:[Manuel Jose ][a]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+techdrivein+%28Tech+Drive-in%29
[1]: https://taskwarrior.org/docs/
[2]: https://taskwarrior.org/download/
[3]: https://taskwarrior.org/news/news.20160225.html
[4]: http://www.techdrivein.com/search/label/Terminal

View File

@ -0,0 +1,83 @@
一起来看看windows Nano Server 2016
====
![](http://images.techhive.com/images/article/2016/04/pokes-fun-at-1164459_1280-100654917-primary.idge.jpg)
>对于未来的windows服务器管理Nano Server是快速的功能强大的工具但是你需要知道你在做的是什么。
[1]下面谈论即将到来的Windows Server 2016的Nano版本带远程管理和命令行设计还包含私有云和数据中心。但是谈论它和动手用它区别还是很大的让我们深入看下去。
没有本地登录且所有的程序工具和代理都是64位安装升级快捷只需要非常少的时间就能重启。它非常适合做计算节点无论在不在集群存储主机DNS服务器IIS的web服务器在容器中提供主机服务或者虚拟化的客户操作系统。
Nano服务器也并不是太好玩的你必须知道你要完成什么。当你看着远程的PowerShell的连接你应该想想接下来做什么如果你知道你想要做什么的话那它就非常方便和强大。
[2] 微软为设置Nano服务器提供了一个快速入门手册在这我给大家具体展示一下。
首先,你必须创建一个.vhd格式的虚拟磁盘文件。在第一步中我有几个文件不在正确的位置Powershell总是提示不匹配所以我不得不反复查找文件的位置方便我可以用ISO信息需要把它拷贝粘贴到你要创建.vhd文件的服务器上。当你所有的东西都位置正确了你可以开始创建.vhd文件的步骤了。
![](http://images.techhive.com/images/article/2016/09/nano-server-1-100682371-large.idge.jpg)
>步骤一尝试运行New-NanoServerImage脚本时很多文件路径错误我把文件位置的问题搞定后就能进行下去创建.vhd文件了如图所示
接下来你可以用创建VM向导在Hyper-V里面创建VM虚拟机你需要指定一个存在的虚拟磁盘同时指向你新创建的.vhd文件。步骤二
![](http://images.techhive.com/images/article/2016/09/nano-server-2-100682368-large.idge.jpg)
>步骤二:连接虚拟磁盘(一开始创建的)
当你启动Nano服务器的时候你或许会发现有内存错误提示你已经分配了多少内存还有其他VM虚拟机的Hyper-V服务器剩余了多少内存。我已经关闭了一些虚机以提升内存因为微软说Nano服务器最少需要512M内存但是它又推荐你至少800M最后我分配了8G内存因为我给它1G的时候根本不能用为了方便我也没有尝试其他的内存配置。
最后我终于到达登录界面到达Nano Server Recovery Console界面步骤三Nano服务器的基本命令界面。
![](http://images.techhive.com/images/article/2016/09/nano-server-3-100682369-large.idge.jpg)
>步骤3Nano服务器的恢复窗口
本来我以为进到这里会很美好但是当我弄明白几个细节如何加入域弹出个磁盘添加用户我明白一些配置的细节用几个字符运行New-NanoServerImage cmdlet会变得很简单。
然而当你的服务器运行时也有办法确认它的状态就像步骤4所示这一切都始于一个远程PowerShell连接。
![](http://images.techhive.com/images/article/2016/09/nano-server-4-100682370-large.idge.jpg)
>步骤4从Nano服务器恢复窗口得到的信息你可以从远程运行一个Powershell连接。
微软展示了如何创建连接但是尝试了四个不同的方法我发现MSDN是最好的方式步骤5展示。
![](http://images.techhive.com/images/article/2016/09/nano-server-5-100682372-large.idge.jpg)
>步骤5创建到Nano服务器的PowerShell远程连接
提示:创建远程连接,你可以用下面这条命令:
```
Enter-PSSession ComputerName "192.168.0.100"-Credential ~\Administrator.
```
如果你提前知道这台服务器将要做DNS服务器或者集群中的一个计算节点可以事先在.vhd文件中加入一些角色和特定的软件包。如果不太清楚你可以先建立PowerShell连接然后安装NanoServerPackage并导入它你就可以用Find-NanoServerPackage命令来查找你要部署的软件包了步骤6
![](http://images.techhive.com/images/article/2016/09/nano-server-6-100682373-large.idge.jpg)
>步骤6你安装完并导入NanoServerPackage后你可以找到你需要启动服务器的工具以及设置的用户和你需要的一些其他功能包。
我测试了安装DNS安装包用`Install-NanoServerPackage Name Microsoft-NanoServer-DNS-Package`这个命令。安装好后,我用`Enable-WindowsOptionalFeature Online FeatureName DNS-Server-Full-Role`命令启用它。
之前我并不知道这些命令之前也从来没运行过也没有弄过DNS但是现在稍微研究一下我就能用Nano服务器建立一个DNS服务并且运行它。
接下来是用PowerShell来配置DNS服务器。这个复杂一些需要网上研究一下。但是他也不是那么复杂当你学习了使用cmdlets用Add-DNSServerPrimaryZone添加zone用Add-DNSServerResourceRecordA命令在zone中添加记录。
做完这些命令行的工作你可能需要验证是否起效。你可以快速浏览一下PowerShell命令没有太多的DNS命令使用Get-Command命令
如果你需要一个图形化的配置你可以打开Nano服务器的IP地址从一个图形化的主机上用图形管理器。右击需要管理的服务器提供你的验证信息你连接好后在图形管理器中右击然后选择Add Roles and Features它会显示你安装好的DNS服务如步骤7所示。
![](http://images.techhive.com/images/article/2016/09/nano-server-7-100682374-large.idge.jpg)
>步骤7通过图形化界面验证DNS已经安装
不用麻烦登录服务器的远程桌面你可以用服务器管理工具来进行操作。当然你能验证DNS角色不代表你有权限添加新的角色和特性它已经锁住了。你现在可以用Nano服务器做一些需要的调整了。
--------------------------------------------------------------------------------
via: http://www.infoworld.com/article/3119770/windows-server/down-and-dirty-with-windows-nano-server-2016.html?utm_source=webopsweekly&utm_medium=email
作者:[J. Peter Bruzzese ][a]
译者:[jiajia9linuxer](https://github.com/jiajia9linuxer)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: http://www.infoworld.com/author/J.-Peter-Bruzzese/
[1]: http://www.infoworld.com/article/3049191/windows-server/nano-server-a-slimmer-slicker-windows-server-core.html
[2]: https://technet.microsoft.com/en-us/windows-server-docs/compute/nano-server/getting-started-with-nano-server
[3]: https://technet.microsoft.com/en-us/windows-server-docs/get-started/system-requirements--and-installation