该死，原生移动应用的开发成本太高了！

# 该死，原生移动应用的开发成本太高了！

>
> 一个有价值的命题
>
>
>

我们遇到了一个临界点。除去少数几个特别的的用例之外，使用原生框架和原生应用开发团队构建、维护移动应用再也没有意义了。

*在美国，雇佣 [iOS，Android](http://www.indeed.com/salary)，[JavaScript](http://www.payscale.com/research/US/Skill=JavaScript/Salary) 开发人员的平均花费*

在过去的几年，原生移动应用开发的费用螺旋式上升，无法控制。对没有大量资金的新创业者来说，创建原生应用、MVP 设计架构和原型的难度大大增加。现有的公司需要抓住人才，以便在现有应用上进行迭代开发或者构建一个新的应用。要尽一切努力才能留住最好的人才，与 [世界各地的公司](http://blogs.wsj.com/cio/2016/09/30/tech-talent-war-moves-to-africa/) 拼尽全力[争个](http://www.bizjournals.com/charlotte/how-to/human-resources/2016/12/employers-offer-premium-wages-skilled-workers.html)[高](https://www.cnet.com/news/silicon-valley-talent-wars-engineers-come-get-your-250k-salary/)[下](http://www.nytimes.com/2015/08/19/technology/unicorns-hunt-for-talent-among-silicon-valleys-giants.html)。

*2015 年初，原生方式和混合方式开发 MVP 设计架构的费用[对比](http://www.comentum.com/mobile-app-development-cost.html)*

### 这一切对于我们意味着什么？

如果你的公司很大或者有足够多的现金，旧思维是只要你在原生应用开发方面投入足够多的资金，就高枕无忧。但事实不再如此。

Facebook 是你最不会想到的在人才战中失败的公司（因为他们没有失败），它也遇到了原生应用方面金钱无法解决的问题。他们的移动应用庞大而又复杂，[他们发现编译它竟然需要 15 分钟](https://devchat.tv/react-native-radio/08-bridging-react-native-components-with-tadeu-zagallo)。这意味着哪怕是极小的用户界面改动，比如移动几个点，测试起来都要花费几个小时（甚至几天）。

除了冗长的编译时间，应用的每一个小改动在测试时都需要在两个完全不同的环境（IOS 和 Android）实施，开发团队需要使用两种语言和框架工作，这趟水更浑了。

Facebook 对这个问题的解决方案是 [React Native](https://facebook.github.io/react-native/)。

### 能不能抛弃移动应用，仅面向 Web 呢？

[一些人认为移动应用的末日已到](https://medium.com/javascript-scene/native-apps-are-doomed-ac397148a2c0#.w06yd23ej)。尽管我很欣赏、尊重 [Eric Elliott](https://medium.com/u/c359511de780) 和他的工作，但我们还是通过考察一些近期的数据，进而讨论一下某些相反的观点：

*人们在移动应用上花费的[时间](http://www.smartinsights.com/mobile-marketing/mobile-marketing-analytics/mobile-marketing-statistics/attachment/percent-time-spent-on-mobile-apps-2016/)（2016年4月）*

>
> 人们使用 APP 的时间占使用手机总时长的 90%
>
>
>

目前世界上有 25 亿人在使用移动手机。[这个数字增长到 50 亿的速度会比我们想象的还要快。](http://ben-evans.com/benedictevans/2016/12/8/mobile-is-eating-the-world) 在正常情况下，丢掉 45 亿人的生意，或者抛弃有 45 亿人使用的应用程序是绝对荒唐且行不通的。

老问题是原生移动应用的开发成本对大多数公司来说太高了。然而，面向 web 的开发成本也在增加。[在美国，JavaScript 开发者的平均工资已达到 $97,000.00](http://www.indeed.com/salary?q1=javascript+developer&l1=united+states&tm=1)。

伴随着复杂性的增加以及对高质量 web 开发的需求暴涨，雇佣一个 JavaScript 开发者的平均价格直逼原生应用开发者。论证 web 开发更便宜已经没用了。

### 那混合开发呢？

混合应用是将 HTML5 应用内嵌在原生应用的容器里，并且提供实现原生平台特性所需的权限。Cordova 和 PhoneGap 就是典型的例子。

如果你想构建一个 MVP 设计架构、一个产品原型，或者不担心对原生应用的模仿的用户体验，那么混合应用会很适合你。但谨记如果你最后想把它转为原生应用，整个项目都得重写。

此领域有很多创新的东西，我最喜欢的当属 [Ionic Framework](https://ionicframework.com/)。混合开发正变得越来越好，但还不如原生开发那么流畅自然。

有很多公司，包括最严峻的初创公司，也包括大中规模的公司，混合应用在质量上的表现似乎没有满足客户的要求，给人的感觉是活糙、不够专业。

[听说应用商店里的前 100 名都不是混合应用](https://medium.com/lunabee-studio/why-hybrid-apps-are-crap-6f827a42f549#.lakqptjw6)，我没有证据支持这一观点。如果说有百分之零到百分之五是混合应用，我就不怀疑了。

>
> [我们最大的错误是在 HTML5 身上下了太多的赌注](https://techcrunch.com/2012/09/11/mark-zuckerberg-our-biggest-mistake-with-mobile-was-betting-too-much-on-html5/) — 马克·扎克伯格
>
>
>

### 解决方案

如果你紧跟移动开发动向，那么你绝对听说过像 [NativeScript](https://www.nativescript.org/) 和 [React Native](https://facebook.github.io/react-native/) 这样的项目。

通过这些项目，使用由 JavaScript 写成的基本 UI 组成块，像常规 iOS 和 Android 应用那样，就可以构建出高质量的原生移动应用。

你可以仅用一位工程师，也可以用一个专业的工程师团队，通过 React Native 使用 [现有代码库](https://github.com/necolas/react-native-web) 或者 [底层技术](https://facebook.github.io/react/) 进行跨平台移动应用开发、[原生桌面开发](https://github.com/ptmt/react-native-macos)，甚至还有 web 开发。把你的应用发布到 APP Store 上、 Play Store 上，还有 Web 上。如此可以在保证不丧失原生应用性能和质量的同时，使成本仅占传统开发的一小部分。

通过 React Native 进行跨平台开发时重复使用其中 90% 的代码也不是没有的事，这个范围通常是 80% 到 90%。

如果你的团队使用 React Native, 既可以消除团队之间的分歧，也可以让 UI 和 API 的设计更一致，还可以加快开发速度。

在编译时不需要使用 React Native，在保存时应用可以实时更新，也加快了开发速度。

React Native 还可以使用 [Code Push](http://microsoft.github.io/code-push/) 和 [AppHub](https://apphub.io/) 这样的工具来远程更新你的 JavaScript 代码。这意味着你可以向用户实时推送更新、新特性，快速修复 bug，绕过打包、发布这些工作，绕过 App Store、Google Play Store 的审核，省去了耗时 2 到 7 天的过程（App Store 一直是整个过程的痛点）。混合应用的这些优势原生应用不可能比得上。

如果这个领域的创新力能像刚发行时那样保持，将来你甚至可以为 [Apple Watch](https://github.com/elliottsj/apple-watch-uikit)、[Apple TV](https://github.com/douglowder/react-native-appletv)，和 [Tizen](https://www.tizen.org/blogs/srsaul/2016/samsung-committed-bringing-react-native-tizen) 这样的平台开发应用。

>
> NativeScript 依然是个相当年轻的框架驱动，Angular 版本 2，[上个月刚刚发布测试版](http://angularjs.blogspot.com/2016/09/angular2-final.html)。但只要它保持良好的市场份额，未来就很有前途。
>
>
>

你可能还不知道世界上一些最能创新、最大的科技公司在这类技术上下了很大的赌注，特别是 [React Native](https://facebook.github.io/react-native/)。

我供职过的多家企业以及世界 500 强公司目前都在转移至 React Native。

### 在产品中特别注意使用 React Native

看下面的例子，[这是一个使用 React Native 技术的著名应用列表](https://facebook.github.io/react-native/showcase.html)。

#### Facebook

*Facebook 公司的 React Native 应用*

Facebook 的两款应用 [Ads Manager](https://play.google.com/store/apps/details?id=com.facebook.adsmanager) 和 [Facebook Groups](https://itunes.apple.com/us/app/facebook-groups/id931735837?mt=8) 都在使用 React Native 技术，并且[将会应用到实现动态消息的框架上](https://devchat.tv/react-native-radio/40-navigation-in-react-native-with-eric-vicenti)。

Facebook 也会投入大量的资金创立和维护像 React Native 这样的开源项目，而且开源项目的开发者最近已经创建很多了不起的项目，这是很了不起的工作，像我以及全世界的业务每天都从中享受诸多好处。

#### Instagram

*Instagram*

Instagram 应用的一部分已经使用了 React Native 技术。

#### Airbnb

*Airbnb*

Airbnb 的很多东西正用 React Native 重写。（来自 [Leland Richardson](https://medium.com/u/41a8b1601c59)）

超过 90% 的 Airbnb 旅行平台都是用 React Native 写的。（来自 [spikebrehm](https://medium.com/u/71a78c1b069b)）

#### Vogue

*Vogue 是 2016 年度十佳应用之一*

Vogue 这么突出不仅仅因为它也用 React Native 写成，而是[因为它被苹果公司评为年度十佳应用之一](http://www.highsnobiety.com/2016/12/08/iphone-apps-best-of-the-year-2016/)。

#### 沃尔玛

*Walmart Labs*

查看这篇 [Keerti](https://medium.com/@Keerti) 的[文章](https://medium.com/walmartlabs/react-native-at-walmartlabs-cdd140589560#.azpn97g8t)来了解沃尔玛是怎样看待 React Native 的优势的。

#### 微软

微软在 React Native 身上下的赌注很大。

它早已发布多个开源工具，包括 [Code Push](http://microsoft.github.io/code-push/)、[React Native VS Code](https://github.com/Microsoft/vscode-react-native)，以及 [React Native Windows](https://github.com/ReactWindows/react-native-windows)，旨在帮助开发者向 React Native 领域转移。

微软考虑的是那些已经使用 React Native 为 iOS 和 Android 开发应用的开发者，他们可以重用高达 90% 的代码，不用花费太多额外的时间和成本就可将应用发布到 Windows 上。

微软对 React Native 生态的贡献十分广泛，过去几年在开源界的表现很抢眼。

### 结论

移动应用界面设计和移动应用开发要进行范式转变，下一步就是 React Native 以及与其相似的技术。

#### 公司

如果你的公司正想着削减成本、加快开发速度，而又不想在应用质量和性能上妥协，这是最适合使用 React Native 的时候，它能提高你的净利润。

#### 开发者

如果你是一个开发者，想进入一个将来会快速发展的领域，我强烈推荐你把 React Native 列入你的学习清单。

如果了解 JavaScript，你会入门很快，工具我首推 [Exponent](https://medium.com/u/df61a4267d7a)，其他的就看你怎么想了。使用 Exponent 开发者可以轻松的编译、测试和发布跨 Windows 和 MacOS 两个平台的 React Native 应用。

如果已经是一位原生应用开发者，你更会受益匪浅。因为在需要时你能够胜任深入研究原生应用边缘的工作。虽然不会经常用到，但在团队需要时这可是十分宝贵的能力。

我花了很多时间来学习、指导别人 React Native。因为它让我十分激动，而且使用这个框架创作应用也是我一个平淡的小乐趣。

感谢阅读。

---

作者简介：

教授和构建 React Native 应用的软件开发专家

---

via: <https://hackernoon.com/the-cost-of-native-mobile-app-development-is-too-damn-high-4d258025033a>

作者：[Nader Dabit](https://hackernoon.com/@dabit3) 译者：[fuowang](https://github.com/fuowang) 校对：[wxy](https://github.com/wxy)

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


美联邦法院裁定：GPL 是可执行的合约

Summary: 韩国一家开发了 Hancom Office 办公软件的公司在其字处理软件中集成了开源软件 Ghostscript，但是没有遵守 Ghostscript 的 GPL 许可证而开源，也没有为该软件付费。近日，该韩国公司被美国联邦法院裁定其违约。

GPL本身也是契约精神的一部分。这样的判决确实更体现了美国法律对契约精神的尊重！！！

这种事，国内管不了

淦！早知道就把端午节给GPL了！

你如果使用了GPL的有关协议的软件，你就默认遵守其规定，不然你就是盗用别人的软件。

Hancom真是恶心！剽窃还有理。

# 美联邦法院裁定：GPL 是可执行的合约

韩国一家开发了 Hancom Office 办公软件的公司在其字处理软件中集成了开源软件 Ghostscript，但是没有遵守 Ghostscript 的 GNU GPL 许可证而开源，也没有为该软件付费。近日，该韩国公司被美国联邦法院裁定其违约。

<img src="content_image/album_201705_19_001121wunv51nt0bou0ono.jpg" alt="" title="">

Ghostscript 是一个开源软件，由 Artifex 公司开发，其采用了两种许可证：

* GNU GPL 许可证
* 商业付费许可证

如果要免费使用 Ghostscript，Hancom 就需要遵循该软件的开源许可证，即 GNU GPL。该许可证要求，如果你的软件中使用了采用该许可协议的软件，并公开发布的话，就需要也采用同样的 GNU GPL 许可证开源。也就是说， Hancom 需要开源其整个办公软件套件。

否则，Hancom 就需要向 Ghostscript 的开发商 Artifex 公司支付商业许可证费用。Artifex 允许商业或其它闭源软件开发商绕开严格的开源许可证 GNU GPL，只要付费就行。

但是 Hancom 从 2013 年在其软件中使用了 Ghostscript 之后，却什么都没做：既没有开源其软件，也没有向 Artifex 公司付商业许可证的费用。

在 2016 年底，交涉无果的 Artifex 公司向美国加利福尼亚北部地区法院发起了诉讼。

“在发现 Hancom 违反了 GNU GPL 许可证，侵犯了 Artifex 的 Ghostscript 的宝贵版权之后，Artifex 要求 Hancom 停止其侵权行为，并为其多年无版权使用 Ghostscript 支付合理的版权费用，”该公司陈述到，“Hancom 拒绝了该要求，Artifex 转而寻求本法院责令 Hancom 停止进一步侵权并支付其滥用 Artifex 的开源许可证的费用。”

Artifex 还提到 Hancom 在 2015 年收入了 8630 万美元。

像 GUN GPL 这样的开源许可证的可执行性长期以来一直是一个悬而未决的法律问题。美国联邦巡回法庭在 2006 年的一个判例，雅各布森诉卡泽尔案中，对开源许可证的侵犯裁定可视作对版权申明的处理。但是在本案之前，这种侵犯开源许可证是否可以依法视作侵犯合约并未裁定。

Hancom 尝试发起动议以驳回该诉讼，其认为该公司并未签署任何东西，所以该许可证并不是真正的合约。

“并不是这样”，杰奎琳·斯科特·科里法官在 4 月 25 日的议案中说。她说 GNU GPL “规定了如果用户没有获取商业许可证，即表示同意其条款。原告称被告没有获取商业许可证，并公开表明其在 GNU GPL 下使用 Ghostscript。这些指控足以为合约的存在而辩护。”

科里法官驳回了 Hancom 的动议。按照这样的做法，就树立了像 GNU GPL 这样的开源许可证可以被视作法律合约的先例，在开发商违反了开源许可证时会被起诉。这对于开源社区来说是一个重大胜利。

当然，Artifex 是否可以最终赢得这一诉讼，还要看后继的上诉和裁定。


Summary: 这种称之为“Rowhammer”的攻击起源于过去十多年中将更多的 DRAM（动态随机存取存储器）容量封装进越来越小的芯片中，这将导致在特定情况下存储单元电子可以从相邻两行row的一边泄漏到另一边。

“VUSec 的研究者认为，谷歌的缓解方案将会使得攻击过程更为复杂，但是它不能修复潜在的问题。” 我以为虽然这是一个利用硬件设计缺陷的漏洞，但是需要软件去触发，所以用另一种软件提供一种缓解措施，不失为一种办法。只是现在人类设计的计算机硬件还有软件如此的千疮百孔，不堪一击，还不说来自宇宙的高能射线的威胁，凭这些就像傲游星辰大海实在是有些痴心妄想。

# Rowhammer：针对物理内存的攻击可以取得 Android 设备的 root 权限

>
> 攻击者确实可以在物理存储单元中实现位翻转来达到侵入移动设备与计算机的目的
>
>
>

<img src="content_image/album_201705_19_083412z8b77tcuwebuthhz.jpg" alt="" title="">

研究者们发现了一种新的在不利用任何软件漏洞情况下，利用内存芯片物理设计上的弱点来侵入 Android 设备的方式。这种攻击技术同样可以影响到其它如 ARM 和 X86 架构的设备与计算机。

这种称之为“Rowhammer”的攻击起源于过去十多年中将更多的 DRAM（动态随机存取存储器）容量封装进越来越小的芯片中，这将导致在特定情况下存储单元电子可以从相邻两<ruby> 行 <rt>  row </rt></ruby>的一边泄漏到另一边。（LCTT 译注：参见 [https://en.wikipedia.org/wiki/Row\_hammer）](https://en.wikipedia.org/wiki/Row_hammer%EF%BC%89)

例如，反复且快速的访问相同的物理储存位置，这种被称为 “<ruby> 锤击 <rt>  hammering </rt></ruby>” 的行为可以导致相邻位置的位值从 0 反转成 1，或者相反。

虽然这样的电子干扰已经被生产商知晓并且从可靠性角度研究了一段时间了，因为内存错误能够导致系统崩溃。而研究者们现在展示了在可控方式的触发下它所存在的严重安全隐患。

在 2015 年 4 月，来自谷歌 Project Zero 项目的研究者公布了两份基于内存 “Rowhammer”漏洞对于 x86-64 CPU 架构的 [提权利用](http://www.computerworld.com/article/2895898/google-researchers-hack-computers-using-dram-electrical-leaks.html)。其中一份利用可以使代码从谷歌的 Chrome 浏览器沙盒里逃逸并且直接在系统上执行，另一份可以在 Linux 机器上获取内核级权限。

此后，其他的研究者进行了更深入的调查并且展示了[通过网站中 JaveScript 脚本进行利用的方式](http://www.computerworld.com/article/2954582/security/researchers-develop-astonishing-webbased-attack-on-a-computers-dram.html)甚至能够影响运行在云环境下的[虚拟服务器](http://www.infoworld.com/article/3105889/security/flip-feng-shui-attack-on-cloud-vms-exploits-hardware-weaknesses.html)。然而，对于这项技术是否可以应用在智能手机和移动设备大量使用的 ARM 架构中还是有疑问的。

现在，一队成员来自荷兰阿姆斯特丹自由大学、奥地利格拉茨技术大学和加州大学圣塔芭芭拉分校的 VUSec 小组，已经证明了 Rowhammer 不仅仅可以应用在 ARM 架构上并且甚至比在 x86 架构上更容易。

研究者们将他们的新攻击命名为 Drammer，代表了 Rowhammer 确实存在，并且计划于周三在维也纳举办的第 23 届 ACM 计算机与通信安全大会上展示。这种攻击建立在之前就被发现与实现的 Rowhammer 技术之上。

VUSec 小组的研究者已经制造了一个适用于 Android 设备的恶意应用，当它被执行的时候利用不易察觉的内存位反转在不需要任何权限的情况下就可以获取设备根权限。

研究者们测试了来自不同制造商的 27 款 Android 设备，21 款使用 ARMv7（32-bit）指令集架构，其它 6 款使用 ARMv8（64-bit）指令集架构。他们成功的在 17 款 ARMv7 设备和 1 款 ARMv8 设备上实现了为反转，表明了这些设备是易受攻击的。

此外，Drammer 能够与其它的 Android 漏洞组合使用，例如 [Stagefright](http://www.csoonline.com/article/3045836/security/new-stagefright-exploit-puts-millions-of-android-devices-at-risk.html) 或者 [BAndroid](https://www.vusec.net/projects/bandroid/) 来实现无需用户手动下载恶意应用的远程攻击。

谷歌已经注意到了这一类型的攻击。“在研究者向谷歌漏洞奖励计划报告了这个问题之后，我们与他们进行了密切的沟通来深入理解这个问题以便我们更好的保护用户，”一位谷歌的代表在一份邮件申明中这样说到。“我们已经开发了一个缓解方案，将会包含在十一月的安全更新中。”（LCTT 译注：缓解方案，参见 <https://en.wikipedia.org/wiki/Vulnerability_management>）

VUSec 的研究者认为，谷歌的缓解方案将会使得攻击过程更为复杂，但是它不能修复潜在的问题。

事实上，从软件上去修复一个由硬件导致的问题是不现实的。硬件供应商正在研究相关问题并且有可能在将来的内存芯片中被修复，但是在现有设备的芯片中风险依然存在。

更糟的是，研究者们说，由于有许多因素会影响到攻击的成功与否并且这些因素尚未被研究透彻，因此很难去说有哪些设备会被影响到。例如，内存控制器可能会在不同的电量的情况下展现不同的行为，因此一个设备可能在满电的情况下没有风险，当它处于低电量的情况下就是有风险的。

同样的，在网络安全中有这样一句俗语：<ruby> 攻击将变本加厉，如火如荼 <rt>  Attacks always get getter, they never get worse </rt></ruby>。Rowhammer 攻击已经从理论变成了现实可能，同样的，它也可能会从现在的现实可能变成确确实实的存在。这意味着今天某个设备是不被影响的，在明天就有可能被改进后的 Rowhammer 技术证明它是存在风险的。

Drammer 在 Android 上实现是因为研究者期望研究基于 ARM 设备的影响，但是潜在的技术可以被使用在所有的架构与操作系统上。新的攻击相较于之前建立在运气与特殊特性与特定平台之上并且十分容易失效的技术已经是一个巨大的进步了。

Drammer 攻击的实现依靠于被包括图形、网络、声音等大量硬件子系统所使用的 DMA（直接存储访问）缓存。Drammer 的实现采用了所有操作系统上都有的 Android 的 ION 内存分配器、接口与方法，这给我们带来的警示是该论文的主要贡献之一。

“破天荒的，我们成功地展示了我们可以做到，在不依赖任何特定的特性情况下完全可靠的证明了 Rowhammer”， VUSec 小组中的其中一位研究者 Cristiano Giuffrida 这样说道。“攻击所利用的内存位置并非是 Android 独有的。攻击在任何的 Linux 平台上都能工作 -- 我们甚至怀疑其它操作系统也可以 -- 因为它利用的是操作系统内核内存管理中固有的特性。”

“我期待我们可以看到更多针对其它平台的攻击的变种，”阿姆斯特丹自由大学的教授兼 VUSec 系统安全研究小组的领导者 Herbert Bos 补充道。

在他们的[论文](https://vvdveen.com/publications/drammer.pdf)之外，研究者们也释出了一个 Android 应用来测试 Android 设备在当前所知的技术条件下受到 Rowhammer 攻击时是否会有风险。应用还没有传上谷歌应用商店，可以从 [VUSec Drammer 网站](https://www.vusec.net/projects/drammer/) 下载来手动安装。一个开源的 Rowhammer 模拟器同样能够帮助其他的研究者来更深入的研究这个问题。

---

via:<http://www.csoonline.com/article/3134726/security/physical-ram-attack-can-root-android-and-possibly-other-devices.html>

作者：[Lucian Constantin](http://www.csoonline.com/author/Lucian-Constantin/) 译者：[wcnnbdk1](https://github.com/wcnnbdk1) 校对：[wxy](https://github.com/wxy)

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


# GraphQL 用例：使用 Golang 和 PostgreSQL 构建一个博客引擎 API

<img src="content_image/album_201705_19_111808se294h4oy3b1bobe.jpg" alt="" title="">

### 摘要

GraphQL 在生产环境中似乎难以使用：虽然对于建模功能来说图接口非常灵活，但是并不适用于关系型存储，不管是在实现还是性能方面。

在这篇博客中，我们会设计并实现一个简单的博客引擎 API，它支持以下功能：

* 三种类型的资源（用户、博文以及评论）支持多种功能（创建用户、创建博文、给博文添加评论、关注其它用户的博文和评论，等等。）
* 使用 PostgreSQL 作为后端数据存储（选择它因为它是一个流行的关系型数据库）。
* 使用 Golang（开发 API 的一个流行语言）实现 API。

我们会比较简单的 GraphQL 实现和纯 REST 替代方案，在一种普通场景（呈现博客文章页面）下对比它们的实现复杂性和效率。

### 介绍

GraphQL 是一种 IDL（<ruby> 接口定义语言 <rp>  （ </rp> <rt>  Interface Definition Language </rt> <rp>  ） </rp></ruby>），设计者定义数据类型和并把数据建模为一个<ruby> 图 <rp>  （ </rp> <rt>  graph </rt> <rp>  ） </rp></ruby>。每个顶点都是一种数据类型的一个实例，边代表了节点之间的关系。这种方式非常灵活，能适应任何业务领域。然而，问题是设计过程更加复杂，而且传统的数据存储不能很好地映射到图模型。阅读*附录1*了解更多关于这个问题的详细信息。

GraphQL 在 2014 年由 Facebook 的工程师团队首次提出。尽管它的优点和功能非常有趣而且引人注目，但它并没有得到大规模应用。开发者需要权衡 REST 的设计简单性、熟悉性、丰富的工具和 GraphQL 不会受限于 CRUD（LCTT 译注：Create、Read、Update、Delete） 以及网络性能（它优化了往返服务器的网络）的灵活性。

大部分关于 GraphQL 的教程和指南都跳过了从数据存储获取数据以便解决查询的问题。也就是，如何使用通用目的、流行存储方案（例如关系型数据库）为 GraphQL API 设计一个支持高效数据提取的数据库。

这篇博客介绍构建一个博客引擎 GraphQL API 的流程。它的功能相当复杂。为了和基于 REST 的方法进行比较，它的范围被限制为一个熟悉的业务领域。

这篇博客的文章结构如下：

* 第一部分我们会设计一个 GraphQL 模式并介绍所使用语言的一些功能。
* 第二部分是 PostgreSQL 数据库的设计。
* 第三部分介绍了使用 Golang 实现第一部分设计的 GraphQL 模式。
* 第四部分我们以从后端获取所需数据的角度来比较呈现博客文章页面的任务。

### 相关阅读

* 很棒的 [GraphQL 介绍文档](http://graphql.org/learn/)。
* 该项目的完整实现代码在 [github.com/topliceanu/graphql-go-example](https://github.com/topliceanu/graphql-go-example)。

### 在 GraphQL 中建模一个博客引擎

下述*列表1*包括了博客引擎 API 的全部模式。它显示了组成图的顶点的数据类型。顶点之间的关系，也就是边，被建模为指定类型的属性。

```
type User {
  id: ID
  email: String!
  post(id: ID!): Post
  posts: [Post!]!
  follower(id: ID!): User
  followers: [User!]!
  followee(id: ID!): User
  followees: [User!]!
}

type Post {
  id: ID
  user: User!
  title: String!
  body: String!
  comment(id: ID!): Comment
  comments: [Comment!]!
}

type Comment {
  id: ID
  user: User!
  post: Post!
  title: String
  body: String!
}

type Query {
  user(id: ID!): User
}

type Mutation {
  createUser(email: String!): User
  removeUser(id: ID!): Boolean
  follow(follower: ID!, followee: ID!): Boolean
  unfollow(follower: ID!, followee: ID!): Boolean
  createPost(user: ID!, title: String!, body: String!): Post
  removePost(id: ID!): Boolean
  createComment(user: ID!, post: ID!, title: String!, body: String!): Comment
  removeComment(id: ID!): Boolean
}

```

*列表1*

模式使用 GraphQL DSL 编写，它用于定义自定义数据类型，例如 `User`、`Post` 和 `Comment`。该语言也提供了一系列原始数据类型，例如 `String`、`Boolean` 和 `ID`（它是`String` 的别名，但是有顶点唯一标识符的额外语义）。

`Query` 和 `Mutation` 是语法解析器能识别并用于查询图的可选类型。从 GraphQL API 读取数据等同于遍历图。需要提供这样一个起始顶点；该角色通过 `Query` 类型来实现。在这种情况中，所有图的查询都要从一个由 id `user(id:ID!)` 指定的用户开始。对于写数据，定义了 `Mutation` 顶点。它提供了一系列操作，建模为能遍历（并返回）新创建顶点类型的参数化属性。*列表2*是这些查询的一些例子。

顶点属性能被参数化，也就是能接受参数。在图遍历场景中，如果一个博文顶点有多个评论顶点，你可以通过指定 `comment(id: ID)` 只遍历其中的一个。所有这些都取决于设计，设计者可以选择不提供到每个独立顶点的直接路径。

`!` 字符是一个类型后缀，适用于原始类型和用户定义类型，它有两种语义：

* 当被用于参数化属性的参数类型时，表示这个参数是必须的。
* 当被用于一个属性的返回类型时，表示当顶点被获取时该属性不会为空。
* 也可以把它们组合起来，例如 `[Comment!]!` 表示一个非空 Comment 顶点链表，其中 `[]`、`[Comment]` 是有效的，但 `null, [null], [Comment, null]` 就不是。

*列表2* 包括一系列用于博客 API 的 `curl` 命令，它们会使用 mutation 填充图然后查询图以便获取数据。要运行它们，按照 [topliceanu/graphql-go-example](https://github.com/graphql/graphql-js) 仓库中的指令编译并运行服务。

```
# 创建用户 1、2 和 3 的更改。更改和查询类似，在该情景中我们检索新创建用户的 id 和 email。
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user1@x.co"){id, email}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user2@x.co"){id, email}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createUser(email:"user3@x.co"){id, email}}'
# 为用户添加博文的更改。为了和模式匹配我们需要检索他们的 id，否则会出现错误。
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post1",body:"body1"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:1,title:"post2",body:"body2"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createPost(user:2,title:"post3",body:"body3"){id}}'
# 博文所有评论的更改。`createComment` 需要用户 id，标题和正文。看列表 1 的模式。
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:2,post:1,title:"comment1",body:"comment1"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:1,post:3,title:"comment2",body:"comment2"){id}}'
curl -XPOST http://vm:8080/graphql -d 'mutation {createComment(user:3,post:3,title:"comment3",body:"comment3"){id}}'
# 让用户 3 关注用户 1 和用户 2 的更改。注意 `follow` 更改只返回一个布尔值而不需要指定。
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:1)}'
curl -XPOST http://vm:8080/graphql -d 'mutation {follow(follower:3, followee:2)}'

# 用户获取用户 1 所有数据的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1)}'
# 用户获取用户 2 和用户 1 的关注者的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:2){followers{id, email}}}'
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followers{id, email}}}'
# 检测用户 2 是否被用户 1 关注的查询。如果是，检索用户 1 的 email，否则返回空。
curl -XPOST http://vm:8080/graphql -d '{user(id:2){follower(id:1){email}}}'
# 返回用户 3 关注的所有用户 id 和 email 的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:3){followees{id, email}}}'
# 如果用户 3 被用户 1 关注，就获取用户 3 email 的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){followee(id:3){email}}}'
# 获取用户 1 的第二篇博文的查询，检索它的标题和正文。如果博文 2 不是由用户 1 创建的，就会返回空。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){title,body}}}'
# 获取用户 1 的所有博文的所有数据的查询。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){posts{id,title,body}}}'
# 获取写博文 2 用户的查询，如果博文 2 是由 用户 1 撰写；一个现实语言灵活性的例证。
curl -XPOST http://vm:8080/graphql -d '{user(id:1){post(id:2){user{id,email}}}}'

```

*列表2*

通过仔细设计 mutation 和类型属性，可以实现强大而富有表达力的查询。

### 设计 PostgreSQL 数据库

关系型数据库的设计，一如以往，由避免数据冗余的需求驱动。选择该方式有两个原因：

1. 表明实现 GraphQL API 不需要定制化的数据库技术或者学习和使用新的设计技巧。
2. 表明 GraphQL API 能在现有的数据库之上创建，更具体地说，最初设计用于 REST 后端甚至传统的呈现 HTML 站点的服务器端数据库。

阅读 *附录1* 了解关于关系型和图数据库在构建 GraphQL API 方面的区别。*列表3* 显示了用于创建新数据库的 SQL 命令。数据库模式和 GraphQL 模式相对应。为了支持 `follow/unfollow` 更改，需要添加 `followers` 关系。

```
CREATE TABLE IF NOT EXISTS users (
  id SERIAL PRIMARY KEY,
  email VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS posts (
  id SERIAL PRIMARY KEY,
  user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  title VARCHAR(200) NOT NULL,
  body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS comments (
  id SERIAL PRIMARY KEY,
  user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
  title VARCHAR(200) NOT NULL,
  body TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS followers (
  follower_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  followee_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  PRIMARY KEY(follower_id, followee_id)
);

```

*列表3*

### Golang API 实现

本项目使用的用 Go 实现的 GraphQL 语法解析器是 `github.com/graphql-go/graphql`。它包括一个查询解析器，但不包括模式解析器。这要求开发者利用库提供的结构使用 Go 构建 GraphQL 模式。这和 [nodejs 实现](https://github.com/graphql/graphql-js) 不同，后者提供了一个模式解析器并为数据获取暴露了钩子。因此 *列表1* 中的模式只是作为指导使用，需要转化为 Golang 代码。然而，这个*“限制”*提供了与抽象级别对等的机会，并且了解模式如何和用于检索数据的图遍历模型相关。*列表4* 显示了 `Comment` 顶点类型的实现：

```
var CommentType = graphql.NewObject(graphql.ObjectConfig{
    Name: "Comment",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Type: graphql.NewNonNull(graphql.ID),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                if comment, ok := p.Source.(*Comment); ok == true {
                    return comment.ID, nil
                }
                return nil, nil
            },
        },
        "title": &graphql.Field{
            Type: graphql.NewNonNull(graphql.String),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                if comment, ok := p.Source.(*Comment); ok == true {
                    return comment.Title, nil
                }
                return nil, nil
            },
        },
        "body": &graphql.Field{
            Type: graphql.NewNonNull(graphql.ID),
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                if comment, ok := p.Source.(*Comment); ok == true {
                    return comment.Body, nil
                }
                return nil, nil
            },
        },
    },
})
func init() {
    CommentType.AddFieldConfig("user", &graphql.Field{
        Type: UserType,
        Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            if comment, ok := p.Source.(*Comment); ok == true {
                return GetUserByID(comment.UserID)
            }
            return nil, nil
        },
    })
    CommentType.AddFieldConfig("post", &graphql.Field{
        Type: PostType,
        Args: graphql.FieldConfigArgument{
            "id": &graphql.ArgumentConfig{
                Description: "Post ID",
                Type:        graphql.NewNonNull(graphql.ID),
            },
        },
        Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
                return nil, err
            }
            return GetPostByID(id)
        },
    })
}

```

*列表4*

正如 *列表1* 中的模式，`Comment` 类型是静态定义的一个有三个属性的结构体：`id`、`title` 和 `body`。为了避免循环依赖，动态定义了 `user` 和 `post` 两个其它属性。

Go 并不适用于这种动态建模，它只支持一些类型检查，代码中大部分变量都是 `interface{}` 类型，在使用之前都需要进行类型断言。`CommentType` 是一个 `graphql.Object` 类型的变量，它的属性是 `graphql.Field` 类型。因此，GraphQL DSL 和 Go 中使用的数据结构并没有直接的转换。

每个字段的 `resolve` 函数暴露了 `Source` 参数，它是表示遍历时前一个节点的数据类型顶点。`Comment` 的所有属性都有作为 source 的当前 `CommentType` 顶点。检索`id`、`title` 和 `body` 是一个直接属性访问，而检索 `user` 和 `post` 要求图遍历，也需要数据库查询。由于它们非常简单，这篇文章并没有介绍这些 SQL 查询，但在*参考文献*部分列出的 github 仓库中有。

### 普通场景下和 REST 的对比

在这一部分，我们会展示一个普通的博客文章呈现场景，并比较 REST 和 GraphQL 的实现。关注重点会放在入站/出站请求数量，因为这些是造成页面呈现延迟的最主要原因。

场景：呈现一个博客文章页面。它应该包含关于作者（email）、博客文章（标题、正文）、所有评论（标题、正文）以及评论人是否关注博客文章作者的信息。*图1* 和 *图2* 显示了客户端 SPA、API 服务器以及数据库之间的交互，一个是 REST API、另一个对应是 GraphQL API。

```
+------+                  +------+                  +--------+
|client|                  |server|                  |database|
+--+---+                  +--+---+                  +----+---+
   |      GET /blogs/:id     |                           |
1\. +------------------------->  SELECT * FROM blogs...   |
   |                         +--------------------------->
   |                         <---------------------------+
   <-------------------------+                           |
   |                         |                           |
   |     GET /users/:id      |                           |
2\. +------------------------->  SELECT * FROM users...   |
   |                         +--------------------------->
   |                         <---------------------------+
   <-------------------------+                           |
   |                         |                           |
   | GET /blogs/:id/comments |                           |
3\. +-------------------------> SELECT * FROM comments... |
   |                         +--------------------------->
   |                         <---------------------------+
   <-------------------------+                           |
   |                         |                           |
   | GET /users/:id/followers|                           |
4\. +-------------------------> SELECT * FROM followers.. |
   |                         +--------------------------->
   |                         <---------------------------+
   <-------------------------+                           |
   |                         |                           |
   +                         +                           +

```

*图1*

```
+------+                  +------+                  +--------+
|client|                  |server|                  |database|
+--+---+                  +--+---+                  +----+---+
   |      GET /graphql       |                           |
1\. +------------------------->  SELECT * FROM blogs...   |
   |                         +--------------------------->
   |                         <---------------------------+
   |                         |                           |
   |                         |                           |
   |                         |                           |
2\. |                         |  SELECT * FROM users...   |
   |                         +--------------------------->
   |                         <---------------------------+
   |                         |                           |
   |                         |                           |
   |                         |                           |
3\. |                         | SELECT * FROM comments... |
   |                         +--------------------------->
   |                         <---------------------------+
   |                         |                           |
   |                         |                           |
   |                         |                           |
4\. |                         | SELECT * FROM followers.. |
   |                         +--------------------------->
   |                         <---------------------------+
   <-------------------------+                           |
   |                         |                           |
   +                         +                           +

```

*图2*

*列表5* 是一条用于获取所有呈现博文所需数据的简单 GraphQL 查询。

```
{
  user(id: 1) {
    email
    followers
    post(id: 1) {
      title
      body
      comments {
        id
        title
        user {
          id
          email
        }
      }
    }
  }
}

```

*列表5*

对于这种情况，对数据库的查询次数是故意相同的，但是到 API 服务器的 HTTP 请求已经减少到只有一个。我们认为在这种类型的应用程序中通过互联网的 HTTP 请求是最昂贵的。

为了利用 GraphQL 的优势，后端并不需要进行特别设计，从 REST 到 GraphQL 的转换可以逐步完成。这使得可以测量性能提升和优化。从这一点，API 设计者可以开始优化（潜在的合并） SQL 查询从而提高性能。缓存的机会在数据库和 API 级别都大大增加。

SQL 之上的抽象（例如 ORM 层）通常会和 `n+1` 问题相抵触。在 REST 示例的步骤 4 中，客户端可能不得不在单独的请求中为每个评论的作者请求关注状态。这是因为在 REST 中没有标准的方式来表达两个以上资源之间的关系，而 GraphQL 旨在通过使用嵌套查询来防止这类问题。这里我们通过获取用户的所有关注者来作弊。我们向客户提出了如何确定评论并关注了作者的用户的逻辑。

另一个区别是获取比客户端所需更多的数据，以免破坏 REST 资源抽象。这对于用于解析和存储不需要数据的带宽消耗和电池寿命非常重要。

### 总结

GraphQL 是 REST 的一个可用替代方案，因为：

* 尽管设计 API 更加困难，但该过程可以逐步完成。也是由于这个原因，从 REST 转换到 GraphQL 非常容易，两个流程可以没有任何问题地共存。
* 在网络请求方面更加高效，即使是类似本博客中的简单实现。它还提供了更多查询优化和结果缓存的机会。
* 在用于解析结果的带宽消耗和 CPU 周期方面它更加高效，因为它只返回呈现页面所需的数据。

REST 仍然非常有用，如果：

* 你的 API 非常简单，只有少量的资源或者资源之间关系简单。
* 在你的组织中已经在使用 REST API，而且你已经配置好了所有工具，或者你的客户希望获取 REST API。
* 你有复杂的 ACL（LCTT 译注：Access Control List） 策略。在博客例子中，可能的功能是允许用户良好地控制谁能查看他们的电子邮箱、博客、特定博客的评论、他们关注了谁，等等。优化数据获取同时检查复杂的业务规则可能会更加困难。

### 附录1：图数据库和高效数据存储

尽管将其应用领域数据想象为一个图非常直观，正如这篇博文介绍的那样，但是支持这种接口的高效数据存储问题仍然没有解决。

近年来图数据库变得越来越流行。通过将 GraphQL 查询转换为特定的图数据库查询语言从而延迟解决请求的复杂性似乎是一种可行的方案。

问题是和关系型数据库相比，图并不是一种高效的数据结构。图中一个顶点可能有到任何其它顶点的连接，访问模式比较难以预测因此提供了较少的优化机会。

例如缓存的问题，为了快速访问需要将哪些顶点保存在内存中？通用缓存算法在图遍历场景中可能没那么高效。

数据库分片问题：把数据库切分为更小、没有交叉的数据库并保存到独立的硬件。在学术上，最小切割的图划分问题已经得到了很好的理解，但可能是次优的，而且由于病态的最坏情况可能导致高度不平衡切割。

在关系型数据库中，数据被建模为记录（行或者元组）和列，表和数据库名称都只是简单的命名空间。大部分数据库都是面向行的，意味着每个记录都是一个连续的内存块，一个表中的所有记录在磁盘上一个接一个地整齐地打包（通常按照某个关键列排序）。这非常高效，因为这是物理存储最优的工作方式。HDD 最昂贵的操作是将磁头移动到磁盘上的另一个扇区，因此最小化此类访问非常重要。

很有可能如果应用程序对一条特定记录感兴趣，它需要获取整条记录，而不仅仅是记录中的其中一列。也很有可能如果应用程序对一条记录感兴趣，它也会对该记录周围的记录感兴趣，例如全表扫描。这两点使得关系型数据库相当高效。然而，也是因为这个原因，关系型数据库的最差使用场景就是总是随机访问所有数据。图数据库正是如此。

随着支持更快随机访问的 SSD 驱动器的出现，更便宜的内存使得缓存大部分图数据库成为可能，更好的优化图缓存和分区的技术，图数据库开始成为可选的存储解决方案。大部分大公司也使用它：Facebook 有 Social Graph，Google 有 Knowledge Graph。

---

via: <http://alexandrutopliceanu.ro/post/graphql-with-go-and-postgresql>

作者：[Alexandru Topliceanu](https://github.com/topliceanu) 译者：[ictlyh](https://github.com/ictlyh) 校对：[wxy](https://github.com/wxy)

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


4 个拥有绝佳命令行界面的终端程序

Summary: pgcli 和 mycli 的作者为你介绍几个精心设计的 CLI 程序，以及如何解决一些可发现性问题。

超喜欢补全，这能极大的提高我的工作效率。

大大提高工作效率呢

不错不错

mycli 一执行 drop database xxxx就挂了，果然还是workbench靠谱

很强大

来自湖北武汉的 Chrome Mobile 40.0|Android 4.4 用户

看不懂

看不懂

看不懂

# 4 个拥有绝佳命令行界面的终端程序

>
> 让我们来看几个精心设计的 CLI 程序，以及如何解决一些可发现性问题。
>
>
>

在本文中，我会指出命令行界面的<ruby> 可发现性 <rt>  discoverability </rt></ruby>缺点以及克服这些问题的几种方法。

我喜欢命令行。我第一次接触命令行是在 1997 的 DOS 6.2 上。我学习了各种命令的语法，并展示了如何在目录中列出隐藏的文件（`attrib`）。我会每次仔细检查命令中的每个字符。 当我犯了一个错误，我会从头开始重新输入命令。直到有一天，有人向我展示了如何使用向上和向下箭头按键遍历命令行历史，我被震惊了。

后来当我接触到 Linux 时，让我感到惊喜的是，上下箭头保留了它们遍历历史记录的能力。我仍然很仔细地打字，但是现在，我了解如何盲打，并且我能打的很快，每分钟可以达到 55 个单词的速度。接着有人向我展示了 tab 补完，再一次改变了我的生活。

在 GUI 应用程序中，菜单、工具提示和图标用于向用户展示功能。而命令行缺乏这种能力，但是有办法克服这个问题。在深入解决方案之前，我会来看看几个有问题的 CLI 程序：

**1、 MySQL**

首先让我们看看我们所钟爱的 MySQL REPL。我经常发现自己在输入 `SELECT * FROM` 然后按 `Tab` 的习惯。MySQL 会询问我是否想看到所有的 871 种可能性。我的数据库中绝对没有 871 张表。如果我选择 `yes`，它会显示一堆 SQL 关键字、表、函数等。（LCTT 译注：REPL —— Read-Eval-Print Loop，交互式开发环境）

**2、 Python**

我们来看另一个例子，标准的 Python REPL。我开始输入命令，然后习惯按 `Tab` 键。瞧，插入了一个 `Tab` 字符，考虑到 `Tab` 在 Python 源代码中没有特定作用，这是一个问题。

### 好的用户体验

让我看下设计良好的 CLI 程序以及它们是如何克服这些可发现性问题的。

#### 自动补全： bpython

[Bpython](https://bpython-interpreter.org/) 是对 Python REPL 的一个很好的替代。当我运行 bpython 并开始输入时，建议会立即出现。我没用通过特殊的键盘绑定触发它，甚至没有按下 `Tab` 键。

当我出于习惯按下 `Tab` 键时，它会用列表中的第一个建议补全。这是给 CLI 设计带来可发现性性的一个很好的例子。

bpython 的另一个方面是可以展示模块和函数的文档。当我输入一个函数的名字时，它会显示这个函数附带的签名以及文档字符串。这是一个多么令人难以置信的周到设计啊。

#### 上下文感知补全：mycli

[mycli](http://mycli.net/) 是默认的 MySQL 客户端的现代替代品。这个工具对 MySQL 来说就像 bpython 之于标准 Python REPL 一样。mycli 将在你输入时自动补全关键字、表名、列和函数。

补全建议是上下文相关的。例如，在 `SELECT * FROM` 之后，只有来自当前数据库的表才会列出，而不是所有可能的关键字。

#### 模糊搜索和在线帮助： pgcli

如果您正在寻找 PostgreSQL 版本的 mycli，请看看 [pgcli](http://pgcli.com/)。 与 mycli 一样，它提供了上下文感知的自动补全。菜单中的项目使用模糊搜索缩小范围。模糊搜索允许用户输入整体字符串中的任意子字符串来尝试找到正确的匹配项。

pgcli 和 mycli 在其 CLI 中都实现了这个功能。斜杠命令的文档也作为补全菜单的一部分展示。

#### 可发现性: fish

在传统的 Unix shell（Bash、zsh 等）中，有一种搜索历史记录的方法。此搜索模式由 `Ctrl-R` 触发。当再次调用你上周运行过的命令时，例如 **ssh**或 **docker**，这是一个令人难以置信的有用的工具。 一旦你知道这个功能，你会发现自己经常会使用它。

如果这个功能是如此有用，那为什么不每次都搜索呢？这正是 [**fish** shell](https://fishshell.com/) 所做的。一旦你开始输入命令，**fish** 将开始建议与历史记录类似的命令。然后，你可以按右箭头键接受该建议。

### 命令行规矩

我已经回顾了一些解决可发现性的问题的创新方法，但也有一些基本的命令行功能应该作为每个 REPL 所实现基础功能的一部分：

* 确保 REPL 有可通过箭头键调用的历史记录。确保会话之间的历史持续存在。
* 提供在编辑器中编辑命令的方法。不管你的补全是多么棒，有时用户只需要一个编辑器来制作完美的命令来删除生产环境中所有的表。
* 使用分页器（`pager`）来管道输出。不要让用户滚动他们的终端。哦，要为分页器设置个合理的默认值。（记得添加选项来处理颜色代码。）
* 提供一种通过 `Ctrl-R` 界面或者 fish 式的自动搜索来搜索历史记录的方法。

### 总结

在第 2 节中，我将来看看 Python 中使你能够实现这些技术的特定库。同时，请查看其中一些精心设计的命令行应用程序：

* [bpython](http://bpython-interpreter.org/)或 [ptpython](http://github.com/jonathanslenders/ptpython/)：具有自动补全支持的 Python REPL。
* [http-prompt](https://github.com/eliangcs/http-prompt)：交互式 HTTP 客户端。
* [mycli](http://mycli.net/)：MySQL、MariaDB 和 Percona 的命令行界面，具有自动补全和语法高亮。
* [pgcli](http://pgcli.com/)：具有自动补全和语法高亮，是对 [psql](https://www.postgresql.org/docs/9.2/static/app-psql.html) 的替代工具。
* [wharfee](http://wharfee.com/)：用于管理 Docker 容器的 shell。

*了解更多： Amjith Ramanujam 在 5 月 20 日在波特兰俄勒冈州举办的 [PyCon US 2017](https://us.pycon.org/2017/) 上的谈话“[神奇的命令行工具](https://us.pycon.org/2017/schedule/presentation/518/)”。*

---

作者简介：

Amjith Ramanujam - Amjith Ramanujam 是 pgcli 和 mycli 的创始人。人们认为它们很酷，他表示笑纳赞誉。他喜欢用 Python、Javascript 和 C 编程。他喜欢编写简单易懂的代码，它们有时甚至会成功。

---

via: <https://opensource.com/article/17/5/4-terminal-apps>

作者：[Amjith Ramanujam](https://opensource.com/users/amjith) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


完全指南：如何在 CentOS 7 中安装、配置和安全加固 FTP 服务

Summary: FTP（文件传输协议）是一种用于通过网络在服务器和客户端之间传输文件的传统并广泛使用的标准工具，特别是在不需要身份验证的情况下（允许匿名用户连接到服务器）。我们必须明白，默认情况下 FTP 是不安全的，因为它不加密传输用户凭据和数据。

SELinux有加密功能么？好像没听说过啊。

第9出错，是按照步骤来打的，求解哪里出错了。

你得说什么错误啊？

# 完全指南：如何在 CentOS 7 中安装、配置和安全加固 FTP 服务

FTP（文件传输协议）是一种用于通过网络[在服务器和客户端之间传输文件](http://www.tecmint.com/scp-commands-examples/)的传统并广泛使用的标准工具，特别是在不需要身份验证的情况下（允许匿名用户连接到服务器）。我们必须明白，默认情况下 FTP 是不安全的，因为它不加密传输用户凭据和数据。

在本指南中，我们将介绍在 CentOS/RHEL7 和 Fedora 发行版中安装、配置和保护 FTP 服务器（ VSFTPD 代表 “Very Secure FTP Daemon”）的步骤。

请注意，本指南中的所有命令将以 root 身份运行，如果你不使用 root 帐户操作服务器，请使用 [sudo命令](http://www.tecmint.com/sudoers-configurations-for-setting-sudo-in-linux/) 获取 root 权限。

### 步骤 1：安装 FTP 服务器

1、 安装 vsftpd 服务器很直接，只要在终端运行下面的命令。

```
# yum install vsftpd

```

2、 安装完成后，服务先是被禁用的，因此我们需要手动启动，并设置在下次启动时自动启用：

```
# systemctl start vsftpd
# systemctl enable vsftpd

```

3、 接下来，为了允许从外部系统访问 FTP 服务，我们需要打开 FTP 守护进程监听的 21 端口：

```
# firewall-cmd --zone=public --permanent --add-port=21/tcp
# firewall-cmd --zone=public --permanent --add-service=ftp
# firewall-cmd --reload

```

### 步骤 2： 配置 FTP 服务器

4、 现在，我们会进行一些配置来设置并加密我们的 FTP 服务器，让我们先备份一下原始配置文件 `/etc/vsftpd/vsftpd.conf`：

```
# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig

```

接下来，打开上面的文件，并将下面的选项设置相关的值：

```
anonymous_enable=NO             ### 禁用匿名登录
local_enable=YES        ### 允许本地用户登录
write_enable=YES        ### 允许对文件系统做改动的 FTP 命令
local_umask=022             ### 本地用户创建文件所用的 umask 值
dirmessage_enable=YES           ### 当用户首次进入一个新目录时显示一个消息
xferlog_enable=YES      ### 用于记录上传、下载细节的日志文件
connect_from_port_20=YES        ### 使用端口 20 （ftp-data）用于 PORT 风格的连接
xferlog_std_format=YES          ### 使用标准的日志格式
listen=NO               ### 不要让 vsftpd 运行在独立模式
listen_ipv6=YES             ### vsftpd 将监听 IPv6 而不是 IPv4
pam_service_name=vsftpd         ###  vsftpd 使用的 PAM 服务名
userlist_enable=YES             ### vsftpd 支持载入用户列表
tcp_wrappers=YES        ### 使用 tcp wrappers

```

5、 现在基于用户列表文件 `/etc/vsftpd.userlist` 来配置 FTP 来允许/拒绝用户的访问。

默认情况下，如果设置了 `userlist_enable=YES`，当 `userlist_deny` 选项设置为 `YES` 的时候，`userlist_file=/etc/vsftpd.userlist` 中列出的用户被拒绝登录。

然而， 更改配置为 `userlist_deny=NO`，意味着只有在 `userlist_file=/etc/vsftpd.userlist` 显式指定的用户才允许登录。

```
userlist_enable=YES                   ### vsftpd 将从 userlist_file 给出的文件中载入用户名列表
userlist_file=/etc/vsftpd.userlist    ### 存储用户名的文件
userlist_deny=NO

```

这并不是全部，当用户登录到 FTP 服务器时，它们会进入 chroot jail 中，这是仅作为 FTP 会话主目录的本地根目录。

接下来，我们将介绍如何将 FTP 用户 chroot 到 FTP 用户的家目录（本地 root）中的两种可能情况，如下所述。

6、 接下来添加下面的选项来限制 FTP 用户到它们自己的家目录。

```
chroot_local_user=YES
allow_writeable_chroot=YES

```

`chroot_local_user=YES` 意味着用户可以设置 chroot jail，默认是登录后的家目录。

同样默认的是，出于安全原因，vsftpd 不会允许 chroot jail 目录可写，然而，我们可以添加 `allow_writeable_chroot=YES` 来覆盖这个设置。

保存并关闭文件。

### 步骤 3： 用 SELinux 加密 FTP 服务器

7、现在，让我们设置下面的 SELinux 布尔值来允许 FTP 能读取用户家目录下的文件。请注意，这原本是使用以下命令完成的：

```
# setsebool -P ftp_home_dir on

```

然而，由于这个 bug 报告：<https://bugzilla.redhat.com/show_bug.cgi?id=1097775>，`ftp_home_dir` 指令默认是禁用的。

现在，我们会使用 `semanage` 命令来设置 SELinux 规则来允许 FTP 读取/写入用户的家目录。

```
# semanage boolean -m ftpd_full_access --on

```

这时，我们需要重启 vsftpd 来使目前的设置生效：

```
# systemctl restart vsftpd

```

### 步骤 4： 测试 FTP 服务器

8、 现在我们会用 [useradd 命令](http://www.tecmint.com/add-users-in-linux/)创建一个 FTP 用户来测试 FTP 服务器。

```
# useradd -m -c “Ravi Saive, CEO” -s /bin/bash ravi
# passwd ravi

```

之后，我们如下使用 [echo 命令](http://www.tecmint.com/echo-command-in-linux/)添加用户 ravi 到文件 `/etc/vsftpd.userlist` 中：

```
# echo "ravi" | tee -a /etc/vsftpd.userlist
# cat /etc/vsftpd.userlist

```

9、 现在是时候测试我们上面的设置是否可以工作了。让我们使用匿名登录测试，我们可以从下面的截图看到匿名登录没有被允许。

```
# ftp 192.168.56.10
Connected to 192.168.56.10  (192.168.56.10).
220 Welcome to TecMint.com FTP service.
Name (192.168.56.10:root) : anonymous
530 Permission denied.
Login failed.
ftp>

```

*测试 FTP 匿名登录*

10、 让我们也测试一下没有列在 `/etc/vsftpd.userlist` 中的用户是否有权限登录，下面截图是没有列入的情况：

```
# ftp 192.168.56.10
Connected to 192.168.56.10  (192.168.56.10).
220 Welcome to TecMint.com FTP service.
Name (192.168.56.10:root) : aaronkilik
530 Permission denied.
Login failed.
ftp>

```

*FTP 用户登录失败*

11、 现在最后测试一下列在 `/etc/vsftpd.userlist` 中的用户是否在登录后真的进入了他/她的家目录：

```
# ftp 192.168.56.10
Connected to 192.168.56.10  (192.168.56.10).
220 Welcome to TecMint.com FTP service.
Name (192.168.56.10:root) : ravi
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls

```

*用户成功登录*

警告：使用 `allow_writeable_chroot=YES` 有一定的安全隐患，特别是用户具有上传权限或 shell 访问权限时。

只有当你完全知道你正做什么时才激活此选项。重要的是要注意，这些安全性影响并不是 vsftpd 特定的，它们适用于所有提供了将本地用户置于 chroot jail 中的 FTP 守护进程。

因此，我们将在下一节中看到一种更安全的方法来设置不同的不可写本地根目录。

### 步骤 5： 配置不同的 FTP 家目录

12、 再次打开 vsftpd 配置文件，并将下面不安全的选项注释掉：

```
#allow_writeable_chroot=YES

```

接着为用户（`ravi`，你的可能不同）创建另外一个替代根目录，并将所有用户对该目录的可写权限移除：

```
# mkdir /home/ravi/ftp
# chown nobody:nobody /home/ravi/ftp
# chmod a-w /home/ravi/ftp

```

13、 接下来，在用户存储他/她的文件的本地根目录下创建一个文件夹：

```
# mkdir /home/ravi/ftp/files
# chown ravi:ravi  /home/ravi/ftp/files
# chmod 0700 /home/ravi/ftp/files/

```

接着在 vsftpd 配置文件中添加/修改这些选项：

```
user_sub_token=$USER         ### 在本地根目录下插入用户名
local_root=/home/$USER/ftp   ### 定义任何用户的本地根目录

```

保存并关闭文件。再说一次，有新的设置后，让我们重启服务：

```
# systemctl restart vsftpd

```

14、 现在最后在测试一次查看用户本地根目录就是我们在他的家目录创建的 FTP 目录。

```
# ftp 192.168.56.10
Connected to 192.168.56.10  (192.168.56.10).
220 Welcome to TecMint.com FTP service.
Name (192.168.56.10:root) : ravi
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls

```

*FTP 用户家目录登录成功*

就是这样了！在本文中，我们介绍了如何在 CentOS 7 中安装、配置以及加密的 FTP 服务器，使用下面的评论栏给我们回复，或者分享关于这个主题的任何有用信息。

**建议阅读：** [在 RHEL/CentOS 7 上安装 ProFTPD 服务器](/article-8504-1.html)

在下一篇文章中，我们还将向你介绍如何在 CentOS 7 中[保护使用 SSL/TLS](http://www.tecmint.com/secure-vsftpd-using-ssl-tls-on-centos/)连接的 FTP 服务器，再此之前，请继续关注 TecMint。

---

作者简介：

Aaron Kili 是一名 Linux 和 F.O.S.S 爱好者，即将从事 Linux 系统管理员和网页开发工作，他日前是 TecMint 技术网站的原创作者，非常喜欢使用电脑工作，坚信分享知识是一种美德。

---

via: <http://www.tecmint.com/install-ftp-server-in-centos-7/>

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

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


如何在 Linux 下当个游戏主播

真是一口老血喷在键盘上。连游戏都不能把这个程序员拉到win平台，我只能说他的人生的娱乐部分已经被Linux毁了。默哀1秒。

最好的办法的切换到windows系统当主播

在大陆不怎么适用吧

Minecraft、0 A. D.、Mindustry之类的游戏都可以在Linux上完美运行啊

# 如何在 Linux 下当个游戏主播

也许没有那么多铁杆的游戏玩家使用 Linux，但肯定有很多 Linux 用户喜欢玩游戏。如果你是其中之一，并希望向世界展示 Linux 游戏不再是一个笑话，那么你会喜欢下面这个关于如何捕捉并且/或者以流式播放游戏的快速教程。我在这将用一个名为 “[Open Broadcaster Software Studio](https://obsproject.com/download)” 的软件，这可能是我们所能找到最好的一种。

### 捕获设置

在顶层菜单中，我们选择 “File” → “Settings”，然后我们选择 “Output” 来设置要生成的文件的选项。这里我们可以设置想要的音频和视频的比特率、新创建的文件的目标路径和文件格式。这上面还提供了粗略的质量设置。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_1.png)

如果我们将顶部的输出模式从 “Simple” 更改为 “Advanced”，我们就能够设置 CPU 负载，以控制 OBS 对系统的影响。根据所选的质量、CPU 能力和捕获的游戏，可以设置一个不会导致丢帧的 CPU 负载设置。你可能需要做一些试验才能找到最佳设置，但如果将质量设置为低，则不用太多设置。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_2.png)

接下来，我们转到设置的 “Video” 部分，我们可以设置我们想要的输出视频分辨率。注意缩小过滤（downscaling filtering ）方式，因为它使最终的质量有所不同。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_3.png)

你可能还需要绑定热键以启动、暂停和停止录制。这特别有用，这样你就可以在录制时看到游戏的屏幕。为此，请在设置中选择 “Hotkeys” 部分，并在相应的框中分配所需的按键。当然，你不必每个框都填写，你只需要填写所需的。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_4.png)

如果你对流式传输感兴趣，而不仅仅是录制，请选择 “Stream” 分类的设置，然后你可以选择支持的 30 种流媒体服务，包括 Twitch、Facebook Live 和 Youtube，然后选择服务器并输入 流密钥。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_5.png)

### 设置源

在左下方，你会发现一个名为 “Sources” 的框。我们按下加号来添加一个新的源，它本质上就是我们录制的媒体源。在这你可以设置音频和视频源，但是图像甚至文本也是可以的。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_6.png)

前三个是关于音频源，接下来的两个是图像，JACK 选项用于从乐器捕获的实时音频， Media Source 用于添加文件等。这里我们感兴趣的是 “Screen Capture (XSHM)”、“Video Capture Device (V4L2)” 和 “Window Capture (Xcomposite)” 选项。

屏幕捕获选项让你选择要捕获的屏幕（包括活动屏幕），以便记录所有内容。如工作区更改、窗口最小化等。对于标准批量录制来说，这是一个适合的选项，它可在发布之前进行编辑。

我们来探讨另外两个。Window Capture 将让我们选择一个活动窗口并将其放入捕获监视器。为了将我们的脸放在一个角落，视频捕获设备用于人们可以在我们说话时可以看到我们。当然，每个添加的源都提供了一组选项来供我们实现我们最后要的效果。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_7.png)

添加的来源是可以调整大小的，也可以沿着录制帧的平面移动，因此你可以添加多个来源，并根据需要进行排列，最后通过右键单击执行基本的编辑任务。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_8.png)

### 过渡

最后，如果你正在流式传输游戏会话时希望能够在游戏视图和自己（或任何其他来源）之间切换。为此，请从右下角切换为“Studio Mode”，并添加一个分配给另一个源的场景。你还可以通过取消选中 “Duplicate scene” 并检查 “Transitions” 旁边的齿轮图标上的 “Duplicate sources” 来切换。 当你想在简短评论中显示你的脸部时，这很有帮助。

 [](https://www.howtoforge.com/images/how-to-capture-and-stream-your-gaming-session-on-linux/big/pic_9.png)

这个软件有许多过渡效果，你可以按中心的 “Quick Transitions” 旁边的加号图标添加更多。当你添加它们时，还将会提示你进行设置。

### 总结

OBS Studio 是一个功能强大的免费软件，它工作稳定，使用起来相当简单直接，并且拥有越来越多的扩展其功能的[附加插件](https://obsproject.com/forum/resources/categories/obs-studio-plugins.6/)。如果你需要在 Linux 上记录并且/或者流式传输游戏会话，除了使用 OBS 之外，我无法想到其他更好的解决方案。你有其他类似工具的经验么？ 请在评论中分享也欢迎包含一个展示你技能的视频链接。:)

---

via: <https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/>

作者：[Bill Toulas](https://www.howtoforge.com/tutorial/how-to-capture-and-stream-your-gaming-session-on-linux/) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


5 个提升你开源项目贡献者基数的方法

# 5 个提升你开源项目贡献者基数的方法

<img src="content_image/album_201705_21_171027n9suiytd8bbell9y.jpg" alt="" title="">

许多自由和开源软件项目因解决问题而出现，人们开始为它们做贡献，是因为他们也想修复遇到的问题。当项目的最终用户发现它对他们的需求有用，该项目就开始增长。并且出于分享的目的把人们吸引到同一个项目社区。

就像任何事物都是有寿命的，增长既是开源项目成功的标志，也是开源项目成功的来源。那么项目领导者和维护者如何激励贡献者基数的增长？这里有五种方法。

### 1、 提供好的文档

人们经常低估项目[文档](https://opensource.com/tags/documentation)的重要性。它是项目贡献者的主要信息来源，它会激励他们努力。信息必须是正确和最新的。它应该包括如何构建该软件、如何提交补丁、编码风格指南等步骤。

查看经验丰富的科技作家、编辑 Bob Reselman 的 [7 个创建世界级文档的规则](https://opensource.com/business/16/1/scale-14x-interview-bob-reselman)。

开发人员文档的一个很好的例子是 [Python 开发人员指南](https://docs.python.org/devguide/)。它包括清晰简洁的步骤，涵盖 Python 开发的各个方面。

### 2、 降低进入门槛

如果你的项目有[工单或 bug 追踪工具](https://opensource.com/tags/bugs-and-issues)，请确保将初级任务标记为一个“小 bug” 或“起点”。新的贡献者可以很容易地通过解决这些问题进入项目。追踪工具也是标记非编程任务（如平面设计、图稿和文档改进）的地方。有许多项目成员不是每天都编码，但是却通过这种方式成为推动力。

Fedora 项目维护着一个这样的[易修复和入门级问题的追踪工具](https://fedoraproject.org/easyfix/)。

### 3、 为补丁提供常规反馈

确认每个补丁，即使它只有一行代码，并给作者反馈。提供反馈有助于吸引潜在的候选人，并指导他们熟悉项目。所有项目都应有一个邮件列表和[聊天功能](https://opensource.com/alternatives/slack)进行通信。问答可在这些媒介中发生。大多数项目不会在一夜之间成功，但那些繁荣的列表和沟通渠道为增长创造了环境。

### 4、 推广你的项目

始于解决问题的项目实际上可能对其他开发人员也有用。作为项目的主要贡献者，你的责任是为你的的项目建立文档并推广它。写博客文章，并在社交媒体上分享项目的进展。你可以从简要描述如何成为项目的贡献者开始，并在该描述中提供主要开发者文档的参考连接。此外，请务必提供有关路线图和未来版本的信息。

为了你的听众，看看由 Opensource.com 的社区经理 Rikki Endsley 写的[写作提示](https://opensource.com/business/15/10/what-stephen-king-can-teach-tech-writers)。

### 5、 保持友好

友好的对话语调和迅速的回复将加强人们对你的项目的兴趣。最初，这些问题只是为了寻求帮助，但在未来，新的贡献者也可能会提出想法或建议。让他们有信心他们可以成为项目的贡献者。

记住你一直在被人评头论足！人们会观察项目开发者是如何在邮件列表或聊天上交谈。这些意味着对新贡献者的欢迎和开放程度。当使用技术时，我们有时会忘记人文关怀，但这对于任何项目的生态系统都很重要。考虑一个情况，项目是很好的，但项目维护者不是很受欢迎。这样的管理员可能会驱使用户远离项目。对于有大量用户基数的项目而言，不被支持的环境可能导致分裂，一部分用户可能决定复刻项目并启动新项目。在开源世界中有这样的先例。

另外，拥有不同背景的人对于开源项目的持续增长和源源不断的点子是很重要的。

最后，项目负责人有责任维持和帮助项目成长。指导新的贡献者是项目的关键，他们将成为项目和社区未来的领导者。

阅读：由红帽的内容战略家 Nicole Engard 写的 [7 种让新的贡献者感到受欢迎的方式](https://opensource.com/life/16/5/sumana-harihareswara-maria-naggaga-oscon)。

---

作者简介：

Kushal Das - Kushal Das 是 Python 软件基金会的一名 CPython 核心开发人员和主管。他是一名长期的 FOSS 贡献者和导师，他帮助新人进入贡献世界。他目前在 Red Hat 担任 Fedora 云工程师。他的博客在 <https://kushaldas.in> 。你也可以在 Twitter @kushaldas 上找到他

---

via: <https://opensource.com/article/17/1/expand-project-contributor-base>

作者：[Kushal Das](https://opensource.com/users/kushaldas) 译者：[geekpi](https://github.com/geekpi) 校对：[Bestony](https://github.com/bestony)

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


加个命令行就极客了？话说手机用命令行很不好用，最好买个蓝牙键盘。

还以为要介绍 Termux...

不能替代原来的Launcher，按Home键的时候会返回原来的桌面，达不到防止别人用手机的目的

看来Linux是发展趋势呀

所以可以把它设置成默认launcher，不就可以了吗？

# Linux 极客的 Android：将你的 Android 设备变成 Linux 命令行界面

不管你是一位命令行大师，还是只是不想让你的朋友和家人使用你的 Android 设备，那就看下 T-UI Launcher 这个程序。Unix/Linux 用户一定会喜欢这个。

T-UI Launcher 是一个免费的轻量级 Android 程序，具有类似 Linux 的命令行界面，它可将你的普通 Android 设备变成一个完整的命令行界面。对于喜欢使用基于文本的界面的人来说，这是一个简单、快速、智能的启动器。

#### T-UI Launcher 功能

下面是一些重要的功能：

* 第一次启动后展示快速使用指南。
* 快速且可完全定制。
* 提供自动补全菜单及快速、强大的别名系统。
* 此外，提供预测建议，并提供有用的搜索功能。

它是免费的，你可以从 Google Play 商店[下载并安装它](https://play.google.com/store/apps/details?id=ohi.andre.consolelauncher)，接着在 Android 设备中运行。

安装完成后，第一次启动时你会看到一个快速指南。阅读完成之后，你可以如下面那样使用简单的命令开始使用了。

*T-UI 命令行帮助指南*

要启动一个 app，只要输入几个字母，自动补全功能会在屏幕中展示可用的 app。接着点击你想打开的程序。

```
$ Telegram   ### 启动 telegram
$ WhatsApp   ### 启动 whatsapp
$ Chrome     ### 启动 chrome

```

*T-UI 命令行使用*

要浏览你的 Android 设备状态（电池电量、wifi、移动数据），输入：

```
$ status

```

*Android 电话状态*

其它的有用命令。

```
$ uninstall telegram                ### 卸载 telegram
$ search [google, playstore, youtube, files]    ### 搜索在线应用或本地文件
$ wifi                      ### 打开或关闭 WIFI
$ cp Downloads/* Music              ### 从 Download 文件夹复制所有文件到 Music 文件夹
$ mv Downloads/* Music              ### 从 Download 文件夹移动所有文件到 Music 文件夹

```

就是这样了！在本篇中，我们展示了一个带有类似 Linux CLI（命令界面）的简单而有用的 Android 程序，它可以将你的常规 Android 设备变成一个完整的命令行界面。尝试一下并在下面的评论栏分享你的想法。

---

作者简介：

Aaron Kili 是 Linux 和 F.O.S.S 爱好者，将来的 Linux 系统管理员和网络开发人员，目前是 TecMint 的内容创作者，他喜欢用电脑工作，并坚信分享知识。

---

via: <https://www.tecmint.com/t-ui-launcher-turns-android-device-into-linux-cli/>

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

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


8 个优秀的开源 Markdown 编辑器

Typora

还是喜欢Typora

Typora老感觉插入表格有问题，自己手动插第一行经常出问题或者插不进来，直接右键菜单插会多出一行

来自湖北武汉武汉大学的 Mobile Safari 5.0|iOS 4.3 用户

居然没有typora!!!

注意标题中的开源

来自121.195.114.9的 Chrome 57.0|GNU/Linux 用户

Typora并非开源软件

# 8 个优秀的开源 Markdown 编辑器

### Markdown

首先，对 Markdown 进行一个简单的介绍。Markdown 是由 John Gruber 和 Aaron Swartz 共同创建的一种轻量级纯文本格式语法。Markdown 可以让用户“以易读、易写的纯文本格式来进行写作，然后可以将其转换为有效格式的 XHTML（或 HTML）“。Markdown 语法只包含一些非常容易记住的符号。其学习曲线平缓；你可以在炒蘑菇的同时一点点学习 Markdown 语法（大约 10 分钟）。通过使用尽可能简单的语法，错误率达到了最小化。除了拥有友好的语法，它还具有直接输出干净、有效的（X）HTML 文件的强大功能。如果你看过我的 HTML 文件，你就会知道这个功能是多么的重要。

Markdown 格式语法的主要目标是实现最大的可读性。用户能够以纯文本的形式发布一份 Markdown 格式的文件。用 Markdown 进行文本写作的一个优点是易于在计算机、智能手机和个人之间共享。几乎所有的内容管理系统都支持 Markdown 。它作为一种网络写作格式流行起来，其产生一些被许多服务采用的变种，比如 GitHub 和 Stack Exchange 。

你可以使用任何文本编辑器来写 Markdown 文件。但我建议使用一个专门为这种语法设计的编辑器。这篇文章中所讨论的软件允许你使用 Markdown 语法来写各种格式的专业文档，包括博客文章、演示文稿、报告、电子邮件以及幻灯片等。另外，所有的应用都是在开源许可证下发布的，在 Linux、OS X 和 Windows 操作系统下均可用。

### Remarkable

让我们从 Remarkable 开始。Remarkable 是一个 apt 软件包的名字，它是一个相当有特色的 Markdown 编辑器 — 它并不支持 Markdown 的全部功能特性，但该有的功能特性都有。它使用和 GitHub Markdown 类似的语法。

你可以使用 Remarkable 来写 Markdown 文档，并在实时预览窗口查看更改。你可以把你的文件导出为 PDF 格式（带有目录）和 HTML 格式文件。它有强大的配置选项，从而具有许多样式，因此，你可以把它配置成你最满意的 Markdown 编辑器。

其他一些特性：

* 语法高亮
* 支持 [GitHub 风味的 Markdown](/article-8399-1.html)
* 支持 MathJax - 通过高级格式呈现丰富文档
* 键盘快捷键

在 Debian、Ubuntu、Fedora、SUSE 和 Arch 系统上均有 Remarkable 的可用的简易安装程序。

主页： <https://remarkableapp.github.io/> 许可证： MIT 许可

### Atom

毫无疑问， Atom 是一个神话般的文本编辑器。超过 50 个开源包集合在一个微小的内核上，从而构成 Atom 。伴有 Node.js 的支持，以及全套功能特性，Atom 是我最喜欢用来写代码的编辑器。Atom 的特性在[杀手级开源应用](https://www.ossblog.org/top-software/2/)的文章中有更详细介绍，它是如此的强大。但是作为一个 Markdown 编辑器，Atom 还有许多不足之处，它的默认包不支持 Markdown 的特性。例如，正如上图所展示的，它不支持等价渲染。

但是，开源拥有强大的力量，这是我强烈提倡开源的一个重要原因。Atom 上有许多包以及一些复刻，从而添加了缺失的功能特性。比如，Markdown Preview Plus 提供了 Markdown 文件的实时预览，并伴有数学公式渲染和实时重加载。另外，你也可以尝试一下 [Markdown Preview Enhanced](https://atom.io/packages/markdown-preview-enhanced)。如果你需要自动滚动特性，那么 [markdown-scroll-sync](https://atom.io/packages/markdown-scroll-sync) 可以满足你的需求。我是 [Markdown-Writer](https://atom.io/packages/markdown-writer)和 [Markdown-pdf](https://atom.io/packages/markdown-pdf)的忠实拥趸，后者支持将 Markdown 快速转换为 PDF、PNG 以及 JPEG 文件。

这个方式体现了开源的理念：允许用户通过添加扩展来提供所需的特性。这让我想起了 Woolworths 的 n 种杂拌糖果的故事。虽然需要多付出一些努力，但能收获最好的回报。

主页： <https://atom.io/> 许可证： MIT 许可

### Haroopad

Haroopad 是一个优秀的 Markdown 编辑器，是一个用于创建适宜 Web 的文档的处理器。使用 Haroopad 可以创作各种格式的文档，比如博客文章、幻灯片、演示文稿、报告和电子邮件等。Haroopad 在 Windows、Mac OS X 和 Linux 上均可用。它有 Debian/Ubuntu 的软件包，也有 Windows 和 Mac 的二进制文件。该应用程序使用 node-webkit、CodeMirror，marked，以及 Twitter 的 Bootstrap 。

Haroo 在韩语中的意思是“一天”。

它的功能列表非常可观。请看下面：

* 主题、皮肤和 UI 组件
	+ 超过 30 种不同的编辑主题 - tomorrow-night-bright 和 zenburn 是近期刚添加的
	+ 编辑器中的代码块的语法高亮
	+ Ruby、Python、PHP、Javascript、C、HTML 和 CSS 的语法高亮支持
	+ 基于 CodeMirror，这是一个在浏览器中使用 JavaScript 实现的通用文本编辑器
* 实时预览主题
	+ 基于 markdown-css 的 7 个主题
* 语法高亮
	+ 基于 hightlight.js 的 112 种语言以及 49 种样式
* 定制主题
	+ 基于 CSS （层叠样式表）的样式
* 演示模式 - 对于现场演示非常有用
* 绘图 - 流程图和序列图
* 任务列表
* 扩展 Markdown 语法，支持 TOC（目录）、 GitHub 风味 Markdown 以及数学表达式、脚注和任务列表等
* 字体大小
	+ 使用首选窗口和快捷键来设置编辑器和预览字体大小
* 嵌入富媒体内容
	+ 视频、音频、3D、文本、开放图形以及 oEmbed
	+ 支持大约 100 种主要的网络服务（YouTude、SoundCloud、Flickr 等）
	+ 支持拖放
* 显示模式
	+ 默认：编辑器｜预览器，倒置：预览器｜编辑器，仅编辑器，仅预览器（View -> Mode）
* 插入当前日期和时间
	+ 多种格式支持（Insert -> Data & Time）
* HtML 到 Markdown
	+ 拖放你在 Web 浏览器中选择好的文本
* Markdown 解析选项
* 大纲预览
* 纯粹主义者的 Vim 键位绑定
* Markdown 自动补全
* 导出为 PDF 和 HTML
* 带有样式的 HTML 复制到剪切板可用于所见即所得编辑器
* 自动保存和恢复
* 文件状态信息
* 换行符或空格缩进
* （一、二、三）列布局视图
* Markdown 语法帮助对话框
* 导入和导出设置
* 通过 MathJax 支持 LaTex 数学表达式
* 导出文件为 HTML 和 PDF
* 创建扩展来构建自己的功能
* 高效地将文件转换进博客系统：WordPress、Evernote 和 Tumblr 等
* 全屏模式－尽管该模式不能隐藏顶部菜单栏和顶部工具栏
* 国际化支持：英文、韩文、西班牙文、简体中文、德文、越南文、俄文、希腊文、葡萄牙文、日文、意大利文、印度尼西亚文土耳其文和法文

主页 <http://pad.haroopress.com/> 许可证： GNU GPL v3 许可

### StackEdit

StackEdit 是一个功能齐全的 Markdown 编辑器，基于 PageDown（该 Markdown 库被 Stack Overflow 和其他一些 Stack 交流网站使用）。不同于在这个列表中的其他编辑器，StackEdit 是一个基于 Web 的编辑器。在 Chrome 浏览器上即可使用 StackEdit 。

特性包括：

* 实时预览 HTML，并通过绑定滚动连接特性来将编辑器和预览的滚动条相绑定
* 支持 Markdown Extra 和 GitHub 风味 Markdown，Prettify/Highlight.js 语法高亮
* 通过 MathJax 支持 LaTex 数学表达式
* 所见即所得的控制按键
* 布局配置
* 不同风格的主题支持
* la carte 扩展
* 离线编辑
* 可以与 Google 云端硬盘（多帐户）和 Dropbox 在线同步
* 一键发布到 Blogger、Dropbox、Gist、GitHub、Google Drive、SSH 服务器、Tumblr 和 WordPress

主页： <https://stackedit.io/> 许可证： Apache 许可

### MacDown

MacDown 是在这个列表中唯一一个只运行在 macOS 上的全特性编辑器。具体来说，它需要在 OX S 10.8 或更高的版本上才能使用。它在内部使用 Hoedown 将 Markdown 渲染成 HTML，这使得它的特性更加强大。Heodown 是 Sundown 的一个复活复刻。它完全符合标准，无依赖，具有良好的扩展支持和 UTF-8 感知。

MacDown 基于 Mou，这是专为 Web 开发人员设计的专用解决方案。

它提供了良好的 Markdown 渲染，通过 Prism 提供的语言识别渲染实现代码块级的语法高亮，MathML 和 LaTex 渲染，GTM 任务列表，Jekyll 前端以及可选的高级自动补全。更重要的是，它占用资源很少。想在 OS X 上写 Markdown？MacDown 是我针对 Web 开发者的开源推荐。

主页： <https://macdown.uranusjr.com/> 许可证： MIT 许可

### ghostwriter

ghostwriter 是一个跨平台的、具有美感的、无干扰的 Markdown 编辑器。它内建了 Sundown 处理器支持，还可以自动检测 pandoc、MultiMarkdown、Discount 和 cmark 处理器。它试图成为一个朴实的编辑器。

ghostwriter 有许多很好的功能设置，包括语法高亮、全屏模式、聚焦模式、主题、通过 Hunspell 进行拼写检查、实时字数统计、实时 HTML 预览、HTML 预览自定义 CSS 样式表、图片拖放支持以及国际化支持。Hemingway 模式按钮可以禁用退格键和删除键。一个新的 “Markdown cheat sheet” HUD 窗口是一个有用的新增功能。主题支持很基本，但在 [GitHub 仓库上](https://github.com/jggouvea/ghostwriter-themes)也有一些可用的试验性主题。

ghostwriter 的功能有限。我越来越欣赏这个应用的通用性，部分原因是其简洁的界面能够让写作者完全集中在策划内容上。这一应用非常值得推荐。

ghostwirter 在 Linux 和 Windows 系统上均可用。在 Windows 系统上还有一个便携式的版本可用。

主页： <https://github.com/wereturtle/ghostwriter> 许可证： GNU GPL v3 许可

### Abricotine

Abricotine 是一个为桌面构建的、旨在跨平台且开源的 Markdown 编辑器。它在 Linux、OS X 和 Windows 上均可用。

该应用支持 Markdown 语法以及一些 GitHub 风味的 Markdown 增强（比如表格）。它允许用户直接在文本编辑器中预览文档，而不是在侧窗栏。

该应用有一系列有用的特性，包括拼写检查、以 HTML 格式保存文件或把富文本复制粘贴到邮件客户端。你也可以在侧窗中显示文档目录，展示语法高亮代码、以及助手、锚点和隐藏字符等。它目前正处于早期的开发阶段，因此还有一些很基本的 bug 需要修复，但它值得关注。它有两个主题可用，如果有能力，你也可以添加你自己的主题。

主页： <http://abricotine.brrd.fr/> 许可证： GNU 通用公共许可证 v3 或更高许可

### ReText

ReText 是一个简单而强大的 Markdown 和 reStructureText 文本编辑器。用户可以控制所有输出的格式。它编辑的文件是纯文本文件，但可以导出为 PDF、HTML 和其他格式的文件。ReText 官方仅支持 Linux 系统。

特性包括：

* 全屏模式
* 实时预览
* 同步滚动（针对 Markdown）
* 支持数学公式
* 拼写检查
* 分页符
* 导出为 HTML、ODT 和 PDF 格式
* 使用其他标记语言

主页： <https://github.com/retext-project/retext> 许可证： GNU GPL v2 或更高许可

---

via: <https://www.ossblog.org/markdown-editors/>

作者：[Steve Emms](https://www.ossblog.org/author/steve/) 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

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


人工智能正快速入侵我们生活的五个方面

Summary: 开源项目正在助推人工智能（AI）进步，而且随着技术的成熟，我们将听到更多关于 AI 如何影响我们生活的消息。你有没有考虑过 AI 是如何改变你周围的世界的？让我们来看看我们日益被我们所改变的世界，以及大胆预测一下 AI 对未来影响。

别什么都往 AI 上靠好不好

# 人工智能正快速入侵我们生活的五个方面

>
> 让我们来看看我们已经被人工智能包围的五个真实存在的方面。
>
>
>

<img src="content_image/album_201705_23_033703tnmglbu6l8dm9bl8.png" alt="5 big ways AI is rapidly invading our lives" title="5 big ways AI is rapidly invading our lives">

开源项目[正在助推](https://www.linux.com/news/open-source-projects-are-transforming-machine-learning-and-ai)人工智能（AI）进步，而且随着技术的成熟，我们将听到更多关于 AI 如何影响我们生活的消息。你有没有考虑过 AI 是如何改变你周围的世界的？让我们来看看我们日益被我们所改变的世界，以及大胆预测一下 AI 对未来影响。

### 1. AI 影响你的购买决定

最近 [VentureBeat](https://twitter.com/venturebeat) 上的一篇文章，[“AI 将如何帮助我们解读千禧一代”](http://venturebeat.com/2017/03/16/how-ai-will-help-us-decipher-millennials/)吸引了我的注意。我承认我对人工智能没有思考太多，也没有费力尝试解读千禧一代，所以我很好奇，希望了解更多。事实证明，文章标题有点误导人，“如何卖东西给千禧一代”或许会是一个更准确的标题。

根据这篇文章，千禧一代是“一个令人垂涎的年龄阶段的人群，全世界的市场经理都在争抢他们”。通过分析网络行为 —— 无论是购物、社交媒体或其他活动 - 机器学习可以帮助预测行为模式，这将可以变成有针对性的广告。文章接着解释如何对物联网和社交媒体平台进行挖掘形成数据点。“使用机器学习挖掘社交媒体数据，可以让公司了解千禧一代如何谈论其产品，他们对一个产品类别的看法，他们对竞争对手的广告活动如何响应，还可获得很多数据，用于设计有针对性的广告，"这篇文章解释说。AI 和千禧一代成为营销的未来并不是什么很令人吃惊的事，但是 X 一代和婴儿潮一代，你们也逃不掉呢！（LCTT 译注：X 一代指出生于 20 世纪 60 年代中期至 70 年代末的美国人，婴儿潮是指二战结束后，1946 年初至 1964 年底出生的人）

>
> 人工智能根据行为变化，将包括城市人在内的整个人群设为目标群体。
>
>
>

例如， [Raconteur 上](https://twitter.com/raconteur)的一篇文章 —— “AI 将怎样改变购买者的行为”中解释说，AI 在网上零售行业最大的力量是它能够迅速适应客户行为不断变化的形势。人工智能创业公司 [Fluid AI](http://www.fluid.ai/) 首席执行官 Abhinav Aggarwal 表示，他公司的软件被一个客户用来预测顾客行为，有一次系统注意到在暴风雪期间发生了一个变化。“那些通常会忽略在一天中发送的电子邮件或应用内通知的用户现在正在打开它们，因为他们在家里没有太多的事情可做。一个小时之内，AI 系统就适应了新的情况，并在工作时间开始发送更多的促销材料。”他解释说。

AI 正在改变我们怎样花钱和为什么花钱，但是 AI 是怎样改变我们挣钱的方式的呢？

### 2. 人工智能正在改变我们如何工作

[Fast 公司](https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives)最近的一篇文章“2017 年人工智能将如何改变我们的生活”中说道，求职者将会从人工智能中受益。作者解释说，除更新薪酬趋势之外，人工智能将被用来给求职者发送相关职位空缺信息。当你应该升职的时候，你很可能会得到一个升职的机会。

人工智能也可以被公司用来帮助新入职的员工。文章解释说：“许多新员工在刚入职的几天内会获得大量信息，其中大部分都留不下来。” 相反，机器人可能会随着时间的推移，当新员工需要相关信息时，再向他一点点“告知信息”。

[Inc.](https://twitter.com/Inc) 有一篇文章[“没有偏见的企业：人工智能将如何重塑招聘机制”](http://www.inc.com/bill-carmody/businesses-beyond-bias-how-ai-will-reshape-hiring-practices.html)，观察了人才管理解决方案提供商 [SAP SuccessFactors](https://www.successfactors.com/en_us.html) 是怎样利用人工智能作为一个工作描述“偏见检查器”，以及检查员工赔偿金的偏见。

[《Deloitte 2017 人力资本趋势报告》](https://dupress.deloitte.com/dup-us-en/focus/human-capital-trends.html?id=us:2el:3pr:dup3575:awa:cons:022817:hct17)显示，AI 正在激励组织进行重组。Fast 公司的文章[“AI 是怎样改变公司组织的方式”](https://www.fastcompany.com/3068492/how-ai-is-changing-the-way-companies-are-organized)审查了这篇报告，该报告是基于全球 10,000 多名人力资源和商业领袖的调查结果。这篇文章解释说："许多公司现在更注重文化和环境的适应性，而不是聘请最有资格的人来做某个具体任务，因为知道个人角色必须随 AI 的实施而发展。" 为了适应不断变化的技术，组织也从自上而下的结构转向多学科团队，文章说。

### 3. AI 正在改变教育

>
> AI 将使所有教育生态系统的利益相关者受益。
>
>
>

尽管教育预算正在缩减，但是教室的规模却正在增长。因此利用技术的进步有助于提高教育体系的生产率和效率，并在提高教育质量和负担能力方面发挥作用。根据 VentureBeat 上的一篇文章[“2017 年人工智能将怎样改变教育”](http://venturebeat.com/2017/02/04/how-ai-will-transform-education-in-2017/)，今年我们将看到 AI 对学生们的书面答案进行评分，机器人回答学生的问题，虚拟个人助理辅导学生等等。文章解释说：“AI 将惠及教育生态系统的所有利益相关者。学生将能够通过即时的反馈和指导学习地更好，教师将获得丰富的学习分析和对个性化教学的见解，父母将以更低的成本看到他们的孩子的更好的职业前景，学校能够规模化优质的教育，政府能够向所有人提供可负担得起的教育。"

### 4. 人工智能正在重塑医疗保健

2017 年 2 月 [CB Insights](https://twitter.com/CBinsights) 的一篇文章挑选了 106 个医疗保健领域的人工智能初创公司，它们中的很多在过去几年中提高了第一次股权融资。这篇文章说：“在 24 家成像和诊断公司中，19 家公司自 2015 年 1 月起就首次公开募股。”这份名单上有那些从事于远程病人监测，药物发现和肿瘤学方面人工智能的公司。”

3 月 16 日发表在 TechCrunch 上的一篇关于 AI 进步如何重塑医疗保健的文章解释说：“一旦对人类的 DNA 有了更好的理解，就有机会更进一步，并能根据他们特殊的生活习性为他们提供个性化的见解。这种趋势预示着‘个性化遗传学’的新纪元，人们能够通过获得关于自己身体的前所未有的信息来充分控制自己的健康。”

本文接着解释说，AI 和机器学习降低了研发新药的成本和时间。部分得益于广泛的测试，新药进入市场需要 12 年以上的时间。这篇文章说：“机器学习算法可以让计算机根据先前处理的数据来‘学习’如何做出预测，或者选择（在某些情况下，甚至是产品）需要做什么实验。类似的算法还可用于预测特定化合物对人体的副作用，这样可以加快审批速度。”这篇文章指出，2015 年旧金山的一个创业公司 [Atomwise](http://www.atomwise.com/) 一天内完成了可以减少埃博拉感染的两种新药物的分析，而不是花费数年时间。

>
> AI 正在帮助发现、诊断和治疗新疾病。
>
>
>

另外一个位于伦敦的初创公司 [BenevolentAI](https://twitter.com/benevolent_ai) 正在利用人工智能寻找科学文献中的模式。这篇文章说：“最近，这家公司找到了两种可能对 Alzheimer 起作用的化合物，引起了很多制药公司的关注。"

除了有助于研发新药，AI 正在帮助发现、诊断和治疗新疾病。TechCrunch 上的文章解释说，过去是根据显示的症状诊断疾病，但是现在 AI 正在被用于检测血液中的疾病特征，并利用对数十亿例临床病例分析进行深度学习获得经验来制定治疗计划。这篇文章说：“IBM 的 Watson 正在与纽约的 Memorial Sloan Kettering 合作，消化理解数十年来关于癌症患者和治疗方面的数据，为了向治疗疑难的癌症病例的医生提供和建议治疗方案。”

### 5. AI 正在改变我们的爱情生活

有 195 个国家的超过 5000 万活跃用户通过一个在 2012 年推出的约会应用程序 [Tinder](https://twitter.com/Tinder) 找到潜在的伴侣。在一个 [Forbes 采访播客](https://www.forbes.com/podcasts/the-forbes-interview/#5e962e5624e1)中，Tinder 的创始人兼董事长 Sean Rad spoke 与 Steven Bertoni 对人工智能是如何正在改变人们约会进行过讨论。在[关于此次采访的文章](https://www.forbes.com/sites/stevenbertoni/2017/02/14/tinders-sean-rad-on-how-technology-and-artificial-intelligence-will-change-dating/#4180fc2e5b99)中，Bertoni 引用了 Rad 说的话，他说：“可能有这样一个时刻，Tinder 可以很好的推测你会感兴趣的人，在组织约会中还可能会做很多跑腿的工作”，所以，这个 app 会向用户推荐一些附近的同伴，并更进一步，协调彼此的时间安排一次约会，而不只是向用户显示一些有可能的同伴。

>
> 我们的后代真的可能会爱上人工智能。
>
>
>

你爱上了 AI 吗？我们的后代真的可能会爱上人工智能。Raya Bidshahri 发表在 [Singularity Hub](https://twitter.com/singularityhub) 的一篇文章“AI 将如何重新定义爱情”说，几十年的后，我们可能会认为爱情不再受生物学的限制。

Bidshahri 解释说：“我们的技术符合摩尔定律，正在以惊人的速度增长 —— 智能设备正在越来越多地融入我们的生活。”，他补充道：“到 2029 年，我们将会有和人类同等智慧的 AI，而到 21 世纪 40 年代，AI 将会比人类聪明无数倍。许多人预测，有一天我们会与强大的机器合并，我们自己可能会变成人工智能。”他认为在这样一个世界上那些是不可避免的，人们将会接受与完全的非生物相爱。

这听起来有点怪异，但是相比较于未来机器人将统治世界，爱上 AI 会是一个更乐观的结果。Bidshahri 说：“对 AI 进行编程，让他们能够感受到爱，这将使我们创造出更富有同情心的 AI，这可能也是避免很多人忧虑的 AI 大灾难的关键。”

这份 AI 正在入侵我们生活各领域的清单只是涉及到了我们身边的人工智能的表面。哪些 AI 创新是让你最兴奋的，或者是让你最烦恼的？大家可以在文章评论区写下你们的感受。

---

Rikki Endsley - Rikki Endsley 是开源社区 Opensource.com 的管理员。在过去，她曾做过 Red Hat 开源和标准（OSAS）团队社区传播者；自由技术记者；USENIX 协会的社区管理员；linux 权威杂志 ADMIN 和 Ubuntu User 的合作出版者，还是杂志 Sys Admin 和 UnixReview.com 的主编。在 Twitter 上关注她：@rikkiends。

（图片来源: opensource.com）

---

via: <https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives>

作者：[Rikki Endsley](https://opensource.com/users/rikki-endsley)  译者：[zhousiyu325](https://github.com/zhousiyu325) 校对：[jasminepeng](https://github.com/jasminepeng)

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


从蓝瘦“想哭”到 SELinux 看操作系统安全何在

SELinux 不是所有知名 Linux 发行版都安装的，比如 Ubuntu 就没有。SELinux 也出现过强制访问限制被绕过的漏洞。SELinux 太复杂，一般来说用户敢改动的地方不多。

但 ubuntu 有 AppArmor

看起来很牛

哎，看到ls -Z我就晕汤！

一切需要关闭SELinux才能使用的软件都是流氓软件！！！

审计和SELinux是独立的

但审计日志也受SELinux策略保护

大家都那么专业，我从人类使用角度来说点自己的看法：对于非专业型的小白用户，其实也应该知道点使用电脑方面的常识，而非是说真的像做一个傻瓜式使用者 满足自己使用就可以了，电脑是自己的，让电脑更好的为自己服务，不仅仅是了解如何操作电脑 更要知道电脑内部的概要远离，很多生活中我遇到的都是把电脑当成智能一样存在了，让用户了解电脑，这点linux 和unix 就比window做的好。防火墙 无论是图形还是命令 都能使用户更清楚自己的电脑都有那些东西存在 都在干些什么。

“想哭”这一程序首发有大陆，官方提供汉化。这么良心的产品你们竟然只想着破解？！

# 从蓝瘦“想哭”到 SELinux 看操作系统安全何在

<img src="content_image/album_201705_23_155344ez0pteesx20c02gb.jpg" alt="" title="">

最近一周，来自网络的<ruby> “想哭”勒索病毒 <rp>  （ </rp> <rt>  Wannacry Ransomware </rt> <rp>  ） </rp></ruby>在世界各地同时上演了一部绑匪大片，台词华丽，演技出色，当仁不让地新晋世界第一网红。全球各国除了默默忙于两弹一星足不出户的朝鲜外，无不为之动容。一时间，包括“想哭”病毒在内的各种病毒的各种传闻也火爆网络，我们并不准备跟风刷屏，只是打算本着实事求是的精神，科学的探讨一下如何与它们和睦相处、谈笑风生。

### “想哭”病毒的前世今生

首先，让我们先简要回顾一下主角“想哭”病毒的前世今生。

“想哭”病毒是基于网络攻击框架二次开发的结果，它利用了 NSA（美国国家安全局）的前辈们留下的非物质文化遗产：<ruby> 永恒之蓝 <rp>  （ </rp> <rt>  ETERNAL BLUE </rt> <rp>  ） </rp></ruby> 模块，针对 Windows SMB 服务的实现漏洞植入恶意代码，再结合自己的创新：加密用户文件和显示勒索声明，一代网红勒索病毒由此诞生。从病毒本身的设计流程来看，似乎并不需要高深的编码技巧或深厚的理论根基，然而这也恰恰是这一事件中最值得我们警惕的地方：NSA 泄漏的攻击模块远不止永恒之蓝一种，借助已有攻击框架进行二次开发的难度又如此之低，所以，可以预期，一大波未知的病毒正在来袭的路上。

是不是细思极恐？所谓“知彼知己，百战不<ruby> 殆 <rp>  （ </rp> <rt>  die </rt> <rp>  ） </rp></ruby>”，要想不 die，先要充分了解对手，所以接下来我们进一步了解一下什么是病毒？病毒是如何以危险方式危害公共安全的？又是怎样进入我们的系统的？

病毒是什么，其实是老生常谈了，经常关注医疗卫生领域的朋友都知道：

>
> 病毒由一段基因与蛋白质构成，自身不能实现新陈代谢，通过适当的途径侵入宿主体内，通过宿主细胞的代谢系统实现复制传播。
>
>
>

跑题了？好吧，不要在意这些细节，我们改几个字就能用了：

>
> 病毒由一段可执行代码与数据构成，自身不能在裸机上运行，通过适当的途径侵入宿主操作系统，通过宿主系统中的存储和网络实现复制传播。
>
>
>

Wirth 教授教导我们：

>
> 算法+数据结构=程序，
>
>
> 病毒=代码+数据=算法+数据结构=程序
>
>
>

没错，病毒就是一类特殊的计算机程序，广义上称为恶意软件。与自然界病毒的最大不同之处在于，它们不是纯天然的，而是 100% 人工打造。通常它们怀着对人类的深深的恶意来到世上，行为各不相同，有的在你的屏幕上画个圈圈诅咒你，有的会窃取你设备中的隐私照片，还有的会眨眼间转走你银行卡上的购房首付款......显然，它们的目标还是很一致的：危害人类设备，破坏世界和平。

又扯远了，我们接着来看病毒是如何入侵操作系统的。病毒的入侵无外乎两个途径：主动和被动。所谓主动是针对目标系统尝试发起扫描和攻击，一般是远程发起，当发现了自己能吃定的漏洞之后，就通过各种阴险手段（其实技术实现上大多还是很优雅的）攫取系统权限，进而将恶意代码注入宿主系统中伺机作恶，对此没什么概念的小伙伴可以自行脑补一下《异形》中的人类被寄生的过程。

病毒入侵的另一种方式，我们称之为被动方式。这种方式并不需要系统存在漏洞或缺陷，需要的是用户的经验、常识或智商存在缺陷。它们通过各种伪装诱骗用户去打开或运行自己，包括形形色色让你心动的邮件、链接、不明来源的安装程序等等，一旦获得机会运行，它们会悄无声息的在你的系统中安营扎寨、留下多道后门，然后为所欲为，这类病毒又被形象地称为（特洛伊）木马。

### 如何应对各种病毒威胁

了解了病毒的来龙去脉之后，我们就可以开始讨论如何应对各种病毒层出不穷的威胁了。

对于大多数用户，良好的使用习惯是第一位的。堡垒往往从内部被攻克，再安全的操作系统，再强大的安全机制，都难以阻止用户自我毁灭的脚步。良好的使用习惯中最重要的，是安全更新，安全更新，安全更新！为什么呢？这要先谈一下操作系统漏洞的由来。

漏洞实际是软件缺陷的一种，也就是俗称的 bug，是由于软件开发人员的疏忽而导致程序没有按照预期的方式运行。软件缺陷多种多样，有些很呆，有些很萌，也并不都会对系统安全构成威胁。那些侥幸逃脱开发和测试人员的轮番围剿，随着软件的发布散落人间的软件缺陷，一旦被黑客们发现、策反，并借助自己在系统内部的有利位置，披着合法软件的外衣，做出送人头、坑队友的恶劣行径时，就成为软件系统的公敌：漏洞。越是庞大和复杂的软件越容易产生漏洞，不幸的是操作系统就是一类极其庞大而复杂的软件系统。

虽然操作系统漏洞常常难以完全避免，然而某个漏洞一旦被发现，开发厂商都会在第一时间发布安全更新对问题进行修复。以这次勒索病毒为例，针对被利用的 SMB 服务漏洞，事实上早在一个月前微软就公布了漏洞警告和补丁，提供了安全更新，那些开启自动更新并及时修复了漏洞的用户，他们可以用省下的三个比特币吃着火锅唱着歌，完全不用担心绑匪。所以请划重点：**操作系统安全更新非常重要，不论个人用户、企业用户还是系统管理员，不论服务器，桌面还是移动终端，不论 Windows，Linux 还是 MacOS，都应该尽可能及时地从操作系统厂商处获取安全更新。**

其次，杀毒软件也可以起到一定的安全增强的作用，多数杀毒软件可以借助病毒库对已有病毒的特征进行分析比对，一旦发现用户即将运行的程序中含有病毒或恶意程序，会及时提醒用户，或者自动清除。因此，杀毒软件可以在很大程度上防御已知的、以被动方式入侵系统的病毒。

那么，积极地安全更新、安装杀毒软件就可以解决所有病毒威胁了么？

很不幸，事实并非如此。安全更新和杀毒软件之于病毒威胁正如强身健体之于疾病隐患，可以大幅降低几率，却难以完全避免。为什么？这要从<ruby> 零日 <rp>  （ </rp> <rt>  0-day </rt> <rp>  ） </rp></ruby>漏洞说起。

零日漏洞，听起来就很霸气的一个名字，仿佛给人一种世界末日的感觉。它并不是指具体的某个或某类漏洞，而是指被黑客发现后立刻用来发起攻击的漏洞，这些漏洞尚未公开，用户不知道，软件厂商也不了解，**应对时间为零**。所以，这类漏洞没有检测工具，没有修复方法，传统被动升级防御、病毒特征比对的方式毫无用处，一旦被用来发起攻击，普通系统是毫无招架能力的。那么有没有可以防御零日漏洞的安全的操作系统呢？

### 安全的操作系统与 SELinux

一提到安全的操作系统，总会涌现出很多真知灼见，最脍炙人口的莫过于：

>
> “所有操作系统都有漏洞，所以没有绝对安全的操作系统；所以 Windows 也好，Linux 也好，MacOS 也好，都一样不安全。”
>
>
>

说的好有道理，我竟无言以对，因为前半句就是对本文前半部分的总结，理论正确，逻辑自洽，没什么可黑的。后半句的逻辑却似乎有点烧脑，如果它成立的话，我们不妨试着推广一下，比如：

>
> “任何物质都是有毒性的，没有什么是绝对无毒的。砒霜吃了会中毒，水喝多了也会中毒，所以砒霜和水一样不安全。”
>
>
>

**毒理学有句名言：一切谈毒性不谈剂量的行为都是耍流氓。同样，任何谈操作系统安全不谈体系架构的行为也是耍流氓。**所以面对这种耍流氓的行为，接下来我们要严肃的谈一谈操作系统的安全体系架构。

多年前，永恒之蓝的始作蛹者 NSA 为了防御自家系统，开发了一套安全框架，多年后这套框架被贡献给了 Linux 内核，这就是 SELinux。作为造成这次世界性灾难的幕后大 boss，NSA 为自己定制的 SELinux 又是怎样的一套防具呢？

SELinux 全称 Security Enhanced Linux ，是针对 Linux 的全面安全增强，相比一般的发现漏洞-修复漏洞这种被动挨打的模式，SELinux 具备主动防御能力，可以抵御包括零日漏洞在内的多种攻击。

那么 SELinux 是如何做到的呢？

访问控制是操作系统安全体系中的最核心最关键的机制，它决定了系统中什么样的资源可以被哪些用户以什么样的方式来访问，也就是说普通用户能做什么，入侵者能做什么，应用软件能做什么，恶意软件能做什么，都是访问控制系统决定的。SELinux 的核心访问机制是<ruby> 强制访问控制 <rp>  （ </rp> <rt>  Mandatory Access Control </rt> <rp>  ） </rp></ruby>，简称 MAC，SELinux 的安全特性是建立在 MAC 基础之上的。那么 MAC 何德何能，堪负如此重任？

说到 MAC 强制访问控制就不得不说它的前辈<ruby> 自主访问控制 <rp>  （ </rp> <rt>  Discretionary Access Control </rt> <rp>  ） </rp></ruby>，简称 DAC。传统的操作系统，Windows、MacOS、以及包括早期 Linux 在内的各种Unix的系统权限管理都是采用的自主访问控制，自主访问控制将用户（或用户组）简化为一个标识，系统中的资源（比如文件）都会带上用户标识和对应的访问权限信息，通过这种方式赋予不同用户不同的访问权限，操作系统通过对用户标识的比对和权限信息决定一个用户是否能访问某个资源。打个比方，你认为你家里的东西是只属于你的，在 DAC 看来，只要能进屋的人都对这个屋子里的东西拥有权限，那么你自己开门进屋睡觉也好，小偷撬门进去拿走金银细软也好，都是合法的。

在操作系统中也是如此，几乎所有操作系统中都有一个身影，叫管理员，Administrator 也好，root 也好，都是一群在系统中权力无限大，对任何资源都有完全访问权限的家伙。多数系统服务是以管理员权限运行的，如果它们存在漏洞，被劫持去做一些它们本不该做的事情的时候，DAC 是不会阻拦的，因为它无法区分某个动作是程序正常行为还是恶意行为。在它眼里，身份就是权力的象征，只要认可了你的管理员身份，你说什么都是对的，你做什么都是合法的。

那么 MAC 机制又是怎样的呢？与 DAC 中的混沌不同，MAC 是一个充满秩序的世界，一个一举一动要提出申请的世界。在 MAC 中，一切访问计划都要事先写入安全策略，没有明确的策略允许的任何访问都会被禁止。在上个例子中，作为家中的主人，你需要能够在家睡觉，也是需要明确制定计划的，你需要添加的安全策略看起来是这样的：

* 定义资源类型： 床
* 定义安全域： 休息
* 定义角色： 主人
* 访问规则： 允许 主人 休息时 使用床

如果系统对于你家中的资源访问只添加了这一条安全策略，那么你仍然可以安心的在家睡觉，小偷无论用何种方式进入你家都将寸步难行，接触任何东西的行为都会被禁止，并且一切被禁止的行为尝试都将被另一套完善的监控系统：审计日志记录在案。

明白了这个例子，回到操作系统中我们就很容易看懂 MAC 是如何防范系统带来的安全威胁的：假设我们有一个存在缓冲区溢出漏洞的文件共享服务，与多数系统服务一样使用管理员权限运行。攻击者通过精心构建一个特殊的数据包发送给服务器，使存在漏洞服务器正常的执行流程被劫持，转而执行修改管理员密码的操作。在 DAC 控制下的传统操作系统中，一旦攻击生效，那么管理员密码会被这个平时八竿子打不着的文件服务器修改，攻击者随后可以很容易的登录进入系统。而在 MAC 系统中，文件服务器的可访问的文件是严格受限的，安全策略类似于：

* 允许 系统管理员角色 运行文件服务器 该进程允许访问被共享文件。

安全策略的定义了该服务可以访问的所有资源，攻击者在攻击了文件服务器后，希望修改管理员密码，它需要访问的是 SAM 或 passwd 等的密码管理文件，由于文件服务器进程仅被策略仅允许访问需要被共享的文件，因此对密码管理文件的操作将被拒绝，攻击失效。这种情况下最坏的情形是，攻击者可能非法访问共享文件，因为它仍在安全策略允许范围内。尽管如此，一个系统级的安全漏洞对整个操作系统的影响被限制在了非常小的范围内。

通过细粒度的划分访问权限，将所有应用和服务的访问限制在最小范围内，这就是强制访问控制保护系统不受已知及未知漏洞攻击的原理。

其实 MAC 和 DAC 并不是水火不容的，在包括 SELinux 在内的多数安全框架中，它们是共同生效的，所有的资源（或者准确的说叫客体）访问请求首先要经过 DAC 权限判定，验证通过之后再进一步进行 MAC 的安全策略判定，只有同时符合自主访问控制和强制访问控制规则后才能获得访问权限。

SELinux 中，有三大类 MAC 策略模型，分别是 TE（类型增强），RBAC（角色访问控制）以及 MLS（多级别安全)，每一类模型都针对系统已有服务和应用提供了大量安全策略。一个使用了 SELinux 的典型的服务器操作系统环境，内核中会包含 10 万条以上的安全策略。

### 计算机信息系统的安全等级

了解了 SELinux 及其强制访问框架后，看到攻防两端都造诣深厚的 NSA，你可能会惊叹于矛尖盾厚的美国在信息安全领域的强大的实力。然而我国在这个陆上有东风，海上有航母，天空有北斗的时代，在信息安全这样重要的领域当然不会碌碌无为。我国很早就对信息安全领域展开了全面的研究，公安部对信息安全的各个领域提出了一些列标准，最早在 GB 17859-1999 标准中就根据需求将计算机信息系统的安全级别由低到高，划分为 1-5 共五个等级。在 GB/T 20272-2006 中更进一步对操作系统安全技术提出了具体要求。

从国标安全第三级开始要求操作系统提供强制访问控制，除了要实现 SELinux 中的各类安全模型架构外，还根据最小特权原则开创性的引入三权分立的概念，将普通操作系统中权限不受控制的管理员根据职责分解为系统管理员，安全管理员，审计管理员三个角色。

系统管理员负责“行政”体系，也就是系统中的配置管理，类似网络配置、服务启停（安全服务除外）、设备管理等等；安全管理员负责“立法”，负责安全策略制定、加载以及安全服务的开启；审计管理员的职责类似“司法”，制定违规访问的记录，安全服务的关闭。三个角色的权限之间互相制约，从而避免了恶意入侵者通过获取管理员权限对操作系统的全面控制。同时标准还对用户数据的私密性、完整性提出了严格的保护要求，要求操作系统通过安全标签保障用户数据不被非法读取和篡改。

国标安全四级除了在访问控制和数据保护上提出更为严格要求之外，还要求设计者对操作系统的安全策略模型、安全功能模块进行形式化验证，并进行隐蔽信道分析，对系统抵御攻击能力进行评估，也是目前已有操作系统能达到的最高安全等级。目前普华、凝思等国产操作系统厂商已经开发出了符合国标安全四级的安全操作系统，提供了远高于普通 SELinux 的底层安全保护。

### 结语

信息安全是全方位的，尽管病毒与恶意入侵并非只针对操作系统，单一从操作系统层面无法解决所有的安全问题，然而作为所有上层应用的最底层软件支撑，操作系统却在最终执行层面承载着一切上层软件的安全机制，脱离操作系统构建的安全体系，如同沙滩上的城堡，即使再坚固也将最终失去根基。


朝鲜 180 局的网络战部门让西方国家忧虑

just want to change people's focus, it's a typical trick of the media!

Are you 中国人?

棒子国这方面的新闻，历史证明就没有几个是真的～～～

外国人不是习惯直接用wanna吗？

# 朝鲜 180 局的网络战部门让西方国家忧虑

*本文译自澳大利亚广播公司相关文章，不代表本站及译者、编辑的态度。*

<img src="content_image/album_201705_23_204904prckpnnpyickxyrx.jpg" alt="在夜色的映衬下，部队的军车通过平壤市区" title="Military trucks through Pyongyang">

据脱北者、官方和网络安全专家的消息，朝鲜的情报机关有一个叫做 180 局的特殊部门， 这个部门已经发起过多起胆大且成功的网络战。

近几年，朝鲜被指责在美国、韩国，及其周边的几个国家对金融网络发起多起在线袭击。

网络安全研究人员称他们找到了这个月全球性感染了 150 多个国家 30 多万台计算机的[“想哭”勒索病毒和朝鲜网络战有关联的技术证据](http://www.abc.net.au/news/2017-05-16/researchers-link-wannacry-to-north-korea/8531110)。

平壤称该指控是“荒谬的”。

对朝鲜的关键指控是指朝鲜与一个叫做<ruby> 拉撒路 <rp>  （ </rp> <rt>  Lazarus </rt> <rp>  ） </rp></ruby>的黑客组织有联系，这个组织是在去年在孟加拉国中央银行网络抢劫了 8100 万美元，并在 2014 年攻击了索尼的好莱坞工作室的网络。

美国政府指责朝鲜对索尼公司的黑客袭击，同时美国政府对平壤在孟加拉国银行的盗窃行为提起公诉并要求立案。

由于没有确凿的证据、没有犯罪指控并不能够立案。朝鲜之后也否认了索尼公司和该银行的袭击与其有关。

朝鲜是世界上最封闭的国家之一，它秘密行动的一些细节很难获得。

但研究这个封闭国家的专家和流落到韩国和一些西方国家的的脱北者已经给出了或多或少的提示。

### 黑客们喜欢以雇员身份来作为掩护

金恒光，一位朝鲜前计算机教授，2004 叛逃到韩国，他仍然有着韩国内部的消息来源，他说平壤的网络战目的在于通过侦察总局（RGB）下属的一个叫做 180 局来筹集资金，这个局主要是负责海外的情报机构。

金教授称，“180 局负责入侵金融机构通过漏洞从银行账户提取资金”。

他之前也说过，他以前的一些学生已经加入了朝鲜的网络战略司令部，即朝鲜的网络部队。

>
> “黑客们到海外寻找比朝鲜更好的互联网服务的地方，以免留下痕迹，” 金教授补充说。
>
>
>

他说他们经常用贸易公司、朝鲜的海外分公司和在中国和东南亚合资企业的雇员来作为掩护。

位于华盛顿的战略与国际研究中心的一位名为 James Lewis 的朝鲜专家称，平壤首先把黑客攻击作为间谍活动的工具，然后对韩国和美国的目的进行政治干扰。

他说，“索尼公司事件之后，他们改变方法，通过用黑客来支持犯罪活动来形成国内坚挺的货币经济政策。”

“目前为止，网上毒品，假冒伪劣，走私，都是他们惯用的伎俩”。

[**VIDEO：** 你遇到过勒索病毒吗? (ABC News)](http://www.abc.net.au/news/2017-05-15/have-you-been-hit-by-ransomware/8527854)

### 韩国声称拥有“大量的证据”

美国国防部称在去年提交给国会的一个报告中显示，朝鲜将网络视为有成本效益的、不对称的、可否认的工具，它能够应付来自报复性袭击的很小风险，因为它的“网络”大部分是和因特网分离的。

>
> 报告中说，“它可能从第三方国家使用互联网基础设施。”
>
>
>

韩国政府称，他们拥有朝鲜网络战行动的大量证据。

“朝鲜进行网络战通过第三方国家来掩护网络袭击的来源，并且使用他们的信息和通讯技术设施”，韩国外交部副部长安总基在书面评论中告诉路透社。

除了孟加拉银行抢劫案，他说怀疑平壤也与菲律宾、越南和波兰的银行袭击有关。

去年六月，警察称朝鲜袭击了 160 个韩国公司和政府机构，入侵了大约 14 万台计算机，暗中在它的对手的计算机中植入恶意代码，为进行大规模网络攻击的长期计划而准备。

朝鲜也被怀疑在 2014 年对韩国核反应堆操作系统进行阶段性网络攻击，尽管朝鲜否认与其无关。

根据在一个韩国首尔的杀毒软件厂商 hauri 的高级安全研究员 Simon Choi 的说法，网络袭击是来自于朝鲜在中国的一个基地。

Choi 先生，是一位对朝鲜的黑客能力有广泛的研究的人，他称，“他们在那里行动，不管他们究竟在做什么，他们拥有中国的 IP 地址”。

[题图：脱北者说， 平壤的网络战攻击目的旨在为一个叫做“180局”的部门来筹集资金。(路透社：Damir Sagolj, file)](http://www.abc.net.au/news/2017-05-21/military-trucks-trhough-pyongyang/8545134)

---

via: <http://www.abc.net.au/news/2017-05-21/north-koreas-unit-180-cyber-warfare-cell-hacking/8545106>

作者：[www.abc.net.au](http://www.abc.net.au) 译者：[hwlog](https://github.com/hwlog) 校对：[wxy](https://github.com/wxy)

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


如何在 Linux 中删除超大的（100-200GB）文件

这个也应该要看具体文件系统吧？

感谢分享

创建一个空文件，再用mv覆盖大文件。试过删除差不多二百G日志文件，二、三秒完成，最后重启一下程序~

来自广东广州的 Chrome Mobile 37.0|Android 7.0 用户

好，windows 的删除真的sb是的，拖慢，就应该这种技术嘛

假如大文件叫做bigfile可以直接用如下命令先让其变小文件在删除啊，而且超快:

echo "" >  bigfile

rm bigfile

# 如何在 Linux 中删除超大的（100-200GB）文件

<img src="content_image/album_201705_24_064946fqc1vu7oxi1bixos.jpg" alt="" title="">

通常，要[在 Linux 终端删除一个文件](/article-8123-1.html)，我们使用 rm 命令（删除文件）、shred 命令（安全删除文件）、wipe 命令（安全擦除文件）或者 secure-deletion 工具包（一个安全文件删除工具集合）。

我们可以使用上述任意的工具来处理相对较小的文件。如果我们想要删除超大的文件/文件夹，比如大概 100-200GB，在删除文件（I/O 调度）所花费的时间以及 RAM 占用量方面，就没有你想的那么简单。

在本教程中，我们会解释如何在 Linux 中有效率并可靠地删除大文件/文件夹。

**建议阅读：** [5 个在 Linux 中清空或者删除大文件的方法](/article-8024-1.html)

我们的主要目标是使用一种不会在删除大文件时拖慢系统的技术，合理地占用 I/O。我们可以用 ionice 命令实现这个目标。

### 在 Linux 中使用 ionice 命令删除超大（200GB）文件

ionice 是一个可以对另一个程序设置或获取 I/O 调度级别和优先级的有用程序。如果没有给出参数或者只有 `-p` 参数，那么 ionice 将会查询该进程的当前的 I/O 调度级别以及优先级。

如果我们给出命令名称，如 `rm` 命令，它将使用给定的参数运行此命令。要获取或设置调度参数，请指定[进程的 PID]，如下：

```
# ionice -p PID

```

要指定名字或者调度的数字，使用（0 表示无、1 表示实时、2 表示尽力、3 表示空闲）下面的命令。

以下命令表示 `rm` 会属于空闲 I/O 级别，并且只在其他进程不使用的时候使用 I/O：

```
---- Deleting Huge Files in Linux -----
# ionice -c 3 rm /var/logs/syslog
# ionice -c 3 rm -rf /var/log/apache

```

如果系统中没有很多空闲时间，那么我们希望使用尽力调度级别，并且使用低优先级：

```
# ionice -c 2 -n 6 rm /var/logs/syslog
# ionice -c 2 -n 6 rm -rf /var/log/apache

```

注意：要使用安全的方法删除大文件，我们可以使用先前提到的 `shred`、`wipe` 以及 secure-deletion 工具包中的不同工具，而不是 `rm` 命令。

**建议阅读：**[3 个在 Linux 中永久/安全删除文件/文件夹的方法](/article-8123-1.html)

要获取更多信息，查阅 `ionice` 的手册页：

```
# man ionice

```

就是这样了！你脑海里还有其他的方法么？在评论栏中与我们分享。

---

作者简介：

Aaron Kili 是 Linux 和 F.O.S.S 爱好者，将来的 Linux 系统管理员和网络开发人员，目前是 TecMint 的内容创作者，他喜欢用电脑工作，并坚信分享知识。

---

via: <https://www.tecmint.com/delete-huge-files-in-linux/>

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

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


六月北京，谁是你最想见的开源领袖？

Summary:
传说中的 LC3（LinuxCon + ContainerCon + CloudOpen）大会，将于今年 6 月 19 至 20 日在北京上演中国首秀。
Linux 中国（https://linux.cn/）作为本次 LC3 大会的推广合作伙伴，将全程跟踪报道本次 LC3 大会的最新消息和花絮动态。

弱弱问下，苍老师之类的，算是开源吗

波多老师表示不服

最希望见到强硬派LT和话痨Stallman。

大神云集，有点小激动啊

# 六月北京，谁是你最想见的开源领袖？

传说中的 LC3（LinuxCon + ContainerCon + CloudOpen）大会，将于今年 6 月 19 至 20 日在北京上演中国首秀。

Linux 中国（<https://linux.cn/>）作为本次 LC3 大会的推广合作伙伴，将全程跟踪报道本次 LC3 大会的最新消息和花絮动态。

据官方消息称，此次大会可谓众星云集，演讲嘉宾都是业内最顶尖的开源领袖，其中半数以上的嘉宾都来自海外，比如 Linux 界两位风云级的大神 Linus Torvalds 和 Greg Kroah-Hartman、华为平台首席架构师熊英、谷歌 Kubernetes 技术负责人 David Oppenheimer、OpenStack 基金会的 Jonathan Bryce 等等。**值得一提的是，这也是 Linux 创始人 Linus Torvalds 首次访华！**

下面我来为大家介绍几位参加本次大会的开源领袖：

### Linus Torvalds ——Linux 和 Git 的创始人

Linus Torvalds 先生创建了 Linux 内核，并负责领导广泛使用的 Linux 操作系统的开源开发，被称为“Linux 之父”。他至今仍然是将新代码纳入标准 Linux 内核的最终权威。

Linus Torvalds 于 1991 年研发出 Linux 内核。随后他与志愿者组建了团队，并于 1994 年春季发布了 V1.0 版内核。1996 年，Linus Torvalds 加入 Transmeta，同时继续负责 Linux 的内核开发。2003 年，Linus Torvalds 离开 Transmeta，在开源开发实验室（OSDL）的支持下，他专注于 Linux 内核的研发。开源开发实验室与自由标准组织（Free Standards Group）在 2007 年合并成立新机构“[Linux 基金会](https://www.linuxfoundation.org/)”。

Linus Torvalds 还是著名的分布式版本控制系统 Git 的发明人。Git 现在已经广泛地应用于开源软件和软件产业的开发中，风靡开源界的 GitHub，以及 GitLab 都是以 Git 作为底层的版本控制系统而打造的。

Linus Torvalds 不仅仅享誉于开源界，而且以率真敏锐、观点鲜明而著称。本次来中国参加 LC3 是 Linus Torvalds 首次来华访问，在本次大会上，Linus Torvalds 将与 VMWare 的首席开源官 Dirk Hohndel 展开对话，大家該也很期待!

### Greg Kroah-Hartman——Linux 内核主要维护人

Greg Kroah-Hartman 是在内核级别维护 Linux 的核心开发人员之一。他在 Linux 基金会担任 Linux 基础研究员的角色, 他一直在做 Linux内核稳定分支（-stable）和包括 staging、USB、sysfs 等多个子系统的维护。

在 2012 年 2 月以前，他在 Novell 的 SUSE Labs工作，而后效力于 Linux 基金会，全心致力于 Linux 驱动程序项目。

Greg 在本次大会上将向我们分享 Linux 内核是如何开发的，整个机制是如何运作的。

### 李三琦**——华为产品与解决方案首席技术官**

李三琦博士现任华为产品与解决方案首席技术官。在此之前，他曾担任华为运营商 BG 首席技术官、IT 产品线和核心网产品线首席技术官以及数据中心和媒体网络BU总裁。

他曾创办过多家高科技公司，如中国的高鸿电讯科技有限公司（2000 年被大唐电信集团收购）和美国的 Santera Systems 公司（2003 年被 Tekelec 收购）。他还重组了 Santera Softswitch，成立了 Spatial Wireless 公司（于 2004 年被 Alcatel 收购）。在 2003 至 2007 年间，他担任 Tekelec 首席技术官。在他杰出的职业生涯中，李三琦曾为思科、AT＆T、Verizon、KT 和三星等公司提供技术咨询服务，并在数家高科技创业公司的咨询委员会任职。

李三琦博士拥有 25 项专利，在国际学术期刊和顶级国际会议论文集上发表论文 160 多篇, 并担任过 20 多个博士生的导师。

### 熊英——华为云平台首席架构师

熊英博士现任华为云平台首席架构师，目前主要负责云平台即服务（PaaS）的架构、策略和设计。他在云架构和设计、电子商务以及企业IT系统方面拥有 20 多年的经验。

在加入华为之前，他在微软工作了 8 年，担任 Azure 和 SQL Azure 云平台首席架构师和开发经理。他还在 AT＆T 工作了十多年，担任企业技术架构师和开发经理。

### David Oppenheimer——谷歌 Kubernetes 技术负责人

David Oppenheimer 先生现任谷歌 Kubernetes 技术负责人。在加入 Kubernetes 团队之前，他任职于谷歌 Borg 和 Omega 集群管理系统。

他在本次大会上的演讲主题是 Kubernetes 的资源管理与调度，作为最近发展非常迅速的 K8S 技术的主要负责人之一，David 将以最权威的角度为我们阐述如何有效地分配共享资源（CPU、内存等），以达到更高效的资源利用，并在共享集群中强化隔离。本次讲演也将讨论最新发布的 K8S 1.6 上的新功能，包括容器的细粒度控制，以及如何使用它们来达成策略目标等，最后还将介绍K8S将来的版本发展方向。

### 申元庆——微软亚太科技有限公司董事长

申元庆先生现任微软亚太科技有限公司董事长、微软亚太研发集团首席运营官、微软中国云计算与企业事业部总经理。申元庆及其团队主导大数据、物联网和开发工具的发展战略，以提升微软智能云的客户体验，为中国客户和合作伙伴提供云迁移领域的全面支持。

在微软工作的 20 多年里，申元庆在微软的研发、销售和市场领域担任过多项管理职务。他早期还在微软先进技术中心（ATC）、微软中国创新集团、医疗解决方案集团（HSG）和战略合作集团（SPG）担任过管理职务。加入微软之前，他在IDT工作。他目前还在多家高科技公司担任董事会成员。

### **唐雄燕**——中国联通网络技术研究院首席技术专家

唐雄燕博士现任中国联通网络技术研究院首席技术专家，以及中国通信标准化协会（CCSA）副主席。他在通信技术领域拥有 20 多年的经验。1994 至 1997 年间，他在新加坡和德国进行高速光通信研究。1998 年以来，他一直从事中国电信运营商的技术管理工作。

他的专业领域包括宽带通信、光学和 IP 网络，新一代网络和物联网。近年来，他主要负责中国联通的SDN/NFV项目。

### 唐洪——阿里云首席架构师

唐洪博士现任阿里云首席架构师。他于 2010 年加入阿里云，并在推动阿里云的大型计算引擎 Apsara 的发展中发挥了重要作用。

在加入阿里云之前，他担任第四大搜索引擎公司 Ask.com 的搜索系统基础设施总监。2008 年，他加入雅虎云计算团队并担任资深首席工程师，负责推动 Hadoop 的研发。唐洪博士在高性能计算并行系统、基于集群的分布式计算和存储系统、大型互联网服务和云计算等方面拥有 19 年的研发和行业经验。

### **Dirk Hohndel**——VMware 副总裁兼首席开源官

Dirk Hohndel 先生现任 VMware 首席开源官，负责领导公司的开源项目和战略制定，推动企业创建共同的价值观和流程，以实现 VMware 与开源社区的互动。

在加入 VMware 之前，Dirk 在英特尔工作近 15 年，担任首席 Linux 和开源技术专家，带领英特尔开源业务的发展。在此之前，他曾任德意志银行 SuSE 和 Unix 架构首席技术官。自 20 世纪 90 年代初以来，Dirk 一直是 Linux 和开放源代码的积极开发者和贡献者。作为早期的 Linux 内核开发人员之一，Dirk 多年来致力于 10 多个开源项目。

### Jonathan Bryce——OpenStack 基金会执行董事

Jonathan Bryce 先生现任 OpenStack 基金会执行董事，此前他是 Rackspace Cloud 的创始人。

他一直为构建云而努力。早期担任过 Rackspace 的开发人员，与同事 Todd Morey 一起研究如何搭建一个网络托管环境，能让用户和企业都可以设计、开发和部署他们理想的网站，而所有这些都无需采购技术，操作简便。后来这一设想演变成 Rackspace Cloud。 自此，Bryce 成为 OpenStack 这一开源云软件项目的重要推动力量。从那时起，他一直是首创开源云软件 OpenStack 的主力军。

### Dirk-Peter van Leeuwen——红帽高级副总裁兼亚太区总经理

Dirk-Peter van Leeuwen 先生现任红帽高级副总裁兼亚太区总经理，负责拓展红帽的市场布局，管理红帽在亚太区的所有销售、市场和服务。自 2009 年 9 月到新加坡就任以来，他作为亚太区负责人，使红帽的营收增加了两倍，亚太区至今仍被视为红帽发展最快的地区。

红帽是基于开放源码的商业IT产品和解决方案首屈一指的提供商。

我们因何而聚？这一切都从一个操作系统、一个社区和一个红帽人开始的。 当然，操作系统是 Linux，这是许多人在这里的原因。但是，这个项目的真正明星不是某个人甚至不是红帽，而是一个不断地验证新想法并且改进它们的社区。开源社区为我们带来了改变世界的技术：互联网，云计算，容器等。

他在本次大会上将为我们分享《红帽和开源的力量》。

### Dave Ward——思科系统工程首席技术官兼首席架构师

Dave Ward 先生现任思科系统工程首席技术官兼首席架构师，负责思科的新技术研发。他还担任过思科 IOS-XR 软件首席架构师，凭借在路由、系统软件和网络设计方面的专业知识而备受业内认可。

### **杨志强**——中国移动研究院副院长

杨志强女士现任中国移动研究院副院长，教授级高级工程师，享受国务院政府特殊津贴。

杨志强在通信网络设计、开发和管理方面拥有 30 多年的经验。近年来，她负责核心网研究与规划、大数据与信息安全等领域，率领并完成了中国移动的关键网络战略项目，如中国移动 4G 核心网络试验，基于 TD-LTE 的 VOLTE 网络和面向SDN/NFV的核心网（Novonet）演进。她还带领团队开发和部署了一系列大数据和信息安全产品。

### Jim Zemlin——Linux 基金会执行董事

Jim Zemlin 先生的职业生涯见证了过去十年间的三大技术趋势：移动计算、云计算和开源软件。如今，作为 Linux 基金会执行董事，他凭借丰富经验，推动通过使用开源和 Linux 来加快技术创新。

### 更多讲演人

本次大会将有上百位嘉宾为我们带来近百场从主题演讲到分组讨论的精彩分享，内容涉及开源、Linux、云计算、容器等等最新前沿技术。在近百场的 LC3 会议中, 谁是你最想见的开源领袖呢？关注及对本文评论即有机会获取购票折扣优惠！

有关更多 LC3 会议的详情，请关注 LF Events 官微：

5 月 28 日之前[报名参会](http://www.bagevent.com/event/561769)尚有最后的门票优惠！

（题图素材来自： Pixabay，CC0）


一位老极客的眼中的开发和部署

# 一位老极客的眼中的开发和部署

<img src="content_image/album_201705_25_130756prvhp3r3pt6pmbpy.jpg" alt="" title="">

多年前，我曾是一名 Smalltalk 程序员，这种经验让我以一种不同的视角来观察编程的世界，例如，需要花时间来适应源代码应该存储在文本文件中的这种做法。

我们作为程序员通常会区分“开发”和“部署”，特别是我们在开发的地方所使用的工具不同于我们在之后部署软件时的地点和工具时。而在 Smalltalk 世界里，没有这样的区别。

Smalltalk 构建于虚拟机包含了你的开发环境（IDE、调试器、文本编辑器、版本控制等）的思路之上，如果你需要修改任何一处代码，你得修改内存中运行副本。如果需要的话，你可以为运行中的机器做个快照；如果你想分发你的代码，你可以发送一个运行中的机器的镜像副本（包括 IDE、调试器、文本编辑器、版本控制等）给用户。这就是上世纪 90 年代软件开发的方式（对我们中的一些人来说）。

如今，部署环境与开发环境有了很大的不同。起初，你不要期望那里（指部署环境）有任何开发工具。一旦部署，就没有版本控制、没有调试、没有开发环境。有的是记录和监视，这些在我们的开发环境中都没有，而有一个“构建管道”，它将我们的软件从开发形式转换为部署形式。作为一个例证，Docker 容器则试图重新找回上世纪 90 年代 Smalltalk 程序员部署体验的那种简单性，而避免同样的开发体验。

我想如果 Smalltalk 世界是我唯一的编程方面的体验，让我无法区分开发和部署环境，我可能会偶尔回顾一下它。但是在我成为一名 Smalltalk 程序员之前，我还是一位 APL 程序员，这也是一个可修改的虚拟机镜像的世界，其中开发和部署是无法区分的。因此，我相信，在当前的时代，人们编辑单独的源代码文件，然后运行构建管道以创建在编辑代码时尚不存在的部署作品，然后将这些作品部署给用户。我们已经以某种方式将这种反模式的软件开发制度化，而不断发展的软件环境的需求正在迫使我们找回到上世纪 90 年代的更有效的技术方法。因此才会有 Docker 的成功，所以，我需要提出我的建议。

我有两个建议：我们在运行时系统中实现（并使用）版本控制，以及，我们通过更改运行中的系统来开发软件，而不是用新的运行系统替换它们。这两个想法是相关的。为了安全地更改正在运行的系统，我们需要一些版本控制功能来支持“撤消”功能。也许公平地说，我只提出了一个建议。让我举例来说明。

让我们开始假设一个静态网站。你要修改一些 HTML 文件。你应该如何工作？如果你像大多数开发者一样，你会有两个，也许三个网站 - 一个用于开发，一个用于 QA（或者预发布），一个用于生产。你将直接编辑开发实例中的文件。准备就绪后，你将把你的修改“部署”到预发布实例。在用户验收测试之后，你将再次部署，这次是生产环境。

使用 Occam 的 Razor，让我们可以避免不必要地创建实例。我们需要多少台机器？我们可以使用一台电脑。我们需要多少台 web 服务器？我们可以使用具有多个虚拟主机的单台 web 服务器。如果不使用多个虚拟主机的话，我们可以只使用单个虚拟主机吗？那么我们就需要多个目录，并需要使用 URL 的顶级路径来区分不同的版本，而不是虚拟主机名。但是为什么我们需要多个目录？因为 web 服务器将从文件系统中提供静态文件。我们的问题是，目录有三个不同的版本，我们的解决方案是创建目录的三个不同的副本。这不是正是 Subversion 和 Git 这样的版本控制系统解决的问题吗？制作目录的多个副本以存储多个版本的策略回到了版本控制 CVS 之前的日子。为什么不使用比如说一个空的的 Git 仓库来存储文件呢？要这样做，web 服务器将需要能够从 git 仓库读取文件（参见 [mod\_git](https://github.com/r0ml/mod_git)）。

这将是一个支持版本控制的运行时系统。

使用这样的 web 服务器，使用的版本可以由 cookie 来标识。这样，任何人都可以推送到仓库，用户将继续看到他们发起会话时所分配的版本。版本控制系统有不可改变的提交； 一旦会话开始，开发人员可以在不影响正在运行的用户的情况下快速推送更改。开发人员可以重置其会话以跟踪他们的新提交，因此开发人员或测试人员就可能如普通用户一样查看在同台服务器上同一个 URL 上正在开发或正在测试的版本。作为偶然的副作用，A/B 测试仅仅是将不同的用户分配给不同的提交的情况。所有用于管理多个版本的 git 设施都可以在运行环境中发挥作用。当然，git reset 为我们提供了前面提到的“撤销”功能。

为什么不是每个人都这样做？

一种可能性是，诸如版本控制系统的工具没有被设计为在生产环境中使用。例如，给某人推送到测试分支而不是生产分支的许可是不可能的。对这个方案最常见的反对是，如果发现了一个漏洞，你会想要将某些提交标记为不可访问。这将是另一种更细粒度的权限的情况；开发人员将具有对所有提交的读取权限，但外部用户不会。我们可能需要对现有工具进行一些额外的改造以支持这种模式，但是这些功能很容易理解，并已被设计到其他软件中。例如，Linux （或 PostgreSQL）实现了对不同用户的细粒度权限的想法。

随着云环境变得越来越普及，这些想法变得更加相关：云总是在运行。例如，我们可以看到，AWS 中等价的 “文件系统”（S3）实现了版本控制，所以你可能有一个不同的想法，使用一台 web 服务器提供来自 S3 的资源文件，并根据会话信息选择不同版本的资源文件。重要的并不是哪个实现是最好的，而是支持这种运行时版本控制的愿景。

部署的软件环境应该是“版本感知”的原则，应该扩展到除了服务静态文件的 web 服务器之外的其他工具。在将来的文章中，我将介绍版本库，数据库和应用程序服务器的方法。

---

作者简介：

Robert M. Lefkowitz - Robert（即 r0ml）是一个喜欢复杂编程语言的编程语言爱好者。 他是一个提高清晰度、提高可靠性和最大限度地简化的编程技术收藏家。他通过让计算机更加容易获得来使它普及化。他经常演讲中世纪晚期和早期文艺复兴对编程艺术的影响。

---

via: <https://opensource.com/article/17/1/difference-between-development-deployment>

作者：[Robert M. Lefkowitz](https://opensource.com/users/r0ml) 译者：[geekpi](https://github.com/geekpi) 校对：[Bestony](https://github.com/Bestony)

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


如何使用 Cream 提高 Vim 的用户友好性

Summary: 当我把 Cream 介绍给一些 Linux 新手交流以后，他们的失望就变成了满意。

# 如何使用 Cream 提高 Vim 的用户友好性

>
> Cream 附加包通过把一个更加熟悉的“面孔”置于 Vim 文本编辑器之上，同时保留 Vim 的功能，使其更加容易使用
>
>
>

大约 10 年前，我既使用 Emacs 进行文本编辑，也使用 Vim 进行文本编辑。说到底，我的确是一个热衷于 Emacs 的家伙。尽管 Emacs 在我的心里占据了很重要的地位，但我知道， Vim 也不赖。

一些人，或者像我一样的人，在技术方面有些笨手笨脚。多年来，我和一些 Linux 新手交流，了解到他们想使用 Vim，但是却失望的发现， Vim 编辑器和他们在其它操作系统上使用过的编辑器不一样。

但是，当我把 Cream 介绍给他们以后，他们的失望就变成了满意。Cream 是 Vim 的一个附加包，它使得 Vim 更加容易使用。Cream 让这些 Linux 新手变成了 Vim 的坚决拥护者和忠心用户。

让我们来看一看 Cream 是什么以及它是如何让 Vim 变得更加容易使用的。

### Cream 的安装

在安装 Cream 之前，你需要先在你的电脑上安装好 Vim 和 GVim 的 GUI 组件。我发现最容易完成这件事的方法是使用 Linux 版本的包管理器。

安装好 Vim 以后，便可[下载 Cream 的安装程序](http://cream.sourceforge.net/download.html)，或者你也可以再次使用 Linux 发行版的包管理器进行安装。

安装好 Cream 以后，你可以从应用菜单选择它（比如，**Applications**->**Cream**）或者在程序启动器中输入 `Cream`，从而启动 Cream 。

### Cream 的使用

如果你之前已经使用过 Gvim，那么你会注意到， Cream 几乎没改变该编辑器的外观和感觉。最大的不同是 Cream 的菜单栏和工具栏，它们取代了 Gvim 陈旧的菜单栏和工具栏，新的菜单栏和工具栏的外观和功能分组看起来和其它编辑器的一样。

Cream 的菜单栏对用户隐藏了更多的技术选项，比如指定一个编译器的能力，以及运行 `make` 命令的能力。当你通过使用 Cream 更加熟悉 Vim 以后，你只需要从 **Setting**->**Preferences**->**Behavior** 选择选项，就可以更容易地访问这些特性。有了这些选项，你可以（如果你想）体验到一个兼有 Cream 和传统 Vim 二者优点的强大编辑器。

Cream 并不是仅由菜单驱动。尽管编辑器的功能仅有单击或双击两种方式，但是你也可以使用常见的键盘快捷键来执行操作，比如 `CTRL-O`（打开一个文件），`CTRL-C`（复制文本）。你不需要在几种模式之间切换，也不需要记住一些很难记住的命令。

Cream 开始运行以后，打开一个文件，或者新建一个文件，然后就可以开始输入了。几个我向他们介绍过 Cream 的人说，虽然 Cream 保留了 Vim 的许多典型风格，但是 Cream 使用起来更加舒服。

并不是说 Cream 是 Vim 的简化版，远远不是。事实上， Cream 保留了 Vim 的全部特性，同时，它还有[一系列其他有用的特性](http://cream.sourceforge.net/featurelist.html)。我发现的 Cream 的一些有用的特性包括：

* 一个标签式界面
* 语法高亮（特别是针对 Markdown、LaTeX 和 HTML）
* 自动修正拼写错误
* 字数统计
* 内建文件浏览器

Cream 本身也有许多附加包，可以给编辑器增加一些新的特性。这些特性包括文本加密、清理电子邮件内容，甚至还有一个使用教程。老实说，我还没有发现哪一个附加包是真正有用的，不过你的感受可能会有所不同。

我曾听过一些 Vi/Vim 的狂热分子谴责 Cream “降低”（这是他们的原话）了 Vi/Vim 编辑器的水准。的确，Cream 并不是为他们设计的。它是为那些想快速使用 Vim ，同时保留他们曾经使用过的编辑器的外观和感觉的人准备的。在这种情况下， Cream 是值得赞赏的，它使得 Vim 更加容易使用，更加广泛的被人们使用。

（题图 : opensource.com）

---

via: <https://opensource.com/article/17/5/stir-bit-cream-make-vim-friendlier>

作者：[Scott Nesbitt](https://opensource.com/users/scottnesbitt) 译者：[ucasFL](https://github.com/ucasFL) 校对：[jasminepeng](https://github.com/jasminepeng)

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


怎样在 Linux 命令行下杀死一个进程

kill 依据具体的版本(比如 kill from util-linux 2.28.2) ，支持参数为 processname，而 Ubuntu 带的 kill，则不支持，需要配合 pidof。

咦， kill不是procps包的么，啥时候属于util-linux包的呢？？话说我的kill还是个shell-builtin的呢~~

不同发行版，文件所属包不同，正常。显然这是指外部命令。

# 怎样在 Linux 命令行下杀死一个进程

>
> Linux 的命令行里面有用来停止正在运行的进程的所有所需工具。Jack Wallen 将为您讲述细节。
>
>
>

想像一下：你打开了一个程序（可能来自于你的桌面菜单或者命令行），然后开始使用这个程序，没想到程序会锁死、停止运行、或者意外死机。你尝试再次运行该程序，但是它反馈说原来的进程没有完全关闭。

你该怎么办？你要结束进程。但该如何做？不管你信与不信，最好的解决方法大都在命令行里。值得庆幸的是， Linux 有供用户杀死错误的进程的每个必要的工具，然而，你在执行杀死进程的命令之前，你首先需要知道进程是什么。该如何处理这一类的任务。一旦你能够掌握这种工具，它实际是十分简单的……

让我来介绍给你这些工具。

我来概述的步骤是每个 Linux 发行版都能用的，不论是桌面版还是服务器版。我将限定只使用命令行，请打开你的终端开始输入命令吧。

### 定位进程

杀死一个没有响应的进程的第一个步骤是定位这个进程。我用来定位进程的命令有两个：`top` 和 `ps` 命令。`top` 是每个系统管理员都知道的工具，用 `top` 命令，你能够知道到所有当前正在运行的进程有哪些。在命令行里，输入 `top` 命令能够就看到你正在运行的程序进程（图1）

*图 1： top 命令给出你许多的信息。*

从显示的列表中你能够看到相当重要的信息，举个例子，Chrome 浏览器反映迟钝，依据我们的 `top` 命令显示，我们能够辨别的有四个 Chrome 浏览器的进程在运行，进程的 pid 号分别是 3827、3919、10764 和 11679。这个信息是重要的，可以用一个特殊的方法来结束进程。

尽管 `top` 命令很是方便，但也不是得到你所要信息最有效的方法。 你知道你要杀死的 Chrome 进程是那个，并且你也不想看 `top` 命令所显示的实时信息。 鉴于此，你能够使用 `ps` 命令然后用 `grep` 命令来过滤出输出结果。这个 `ps` 命令能够显示出当前进程列表的快照，然后用 `grep` 命令输出匹配的样式。我们通过 `grep` 命令过滤 `ps` 命令的输出的理由很简单：如果你只输入 `ps` 命令，你将会得到当前所有进程的列表快照，而我们需要的是列出 Chrome 浏览器进程相关的。所以这个命令是这个样子：

```
ps aux | grep chrome

```

这里 `aux` 选项如下所示：

* a = 显示所有用户的进程
* u = 显示进程的用户和拥有者
* x = 也显示不依附于终端的进程

当你搜索图形化程序的信息时，这个 `x` 参数是很重要的。

当你输入以上命令的时候，你将会得到比图 2 更多的信息，而且它有时用起来比 `top` 命令更有效。

*图 2：用 ps 命令来定位所需的内容信息。*

### 结束进程

现在我们开始结束进程的任务。我们有两种可以帮我们杀死错误的进程的信息。

* 进程的名字
* 进程的 ID （PID）

你用哪一个将会决定终端命令如何使用，通常有两个命令来结束进程：

* `kill` - 通过进程 ID 来结束进程
* `killall` - 通过进程名字来结束进程

有两个不同的信号能够发送给这两个结束进程的命令。你发送的信号决定着你想要从结束进程命令中得到的结果。举个例子，你可以发送 `HUP`（挂起）信号给结束进程的命令，命令实际上将会重启这个进程。当你需要立即重启一个进程（比如就守护进程来说），这是一个明智的选择。你通过输入 `kill -l` 可以得到所有信号的列表，你将会发现大量的信号。

*图 3： 可用的结束进程信号。*

最经常使用的结束进程的信号是：

| Signal Name | Single Value | Effect |
| --- | --- | --- |
| SIGHUP | 1 | 挂起 |
| SIGINT | 2 | 键盘的中断信号 |
| SIGKILL | 9 | 发出杀死信号 |
| SIGTERM | 15 | 发出终止信号 |
| SIGSTOP | 17, 19, 23 | 停止进程 |

好的是，你能用信号值来代替信号名字。所以你没有必要来记住所有各种各样的信号名字。

所以，让我们现在用 `kill` 命令来杀死 Chrome 浏览器的进程。这个命令的结构是：

```
kill SIGNAL PID

```

这里 SIGNAL 是要发送的信号，PID 是被杀死的进程的 ID。我们已经知道，来自我们的 `ps` 命令显示我们想要结束的进程 ID 号是 3827、3919、10764 和 11679。所以要发送结束进程信号，我们输入以下命令：

```
kill -9 3827
kill -9 3919
kill -9 10764
kill -9 11679

```

一旦我们输入了以上命令，Chrome 浏览器的所有进程将会成功被杀死。

我们有更简单的方法！如果我们已经知道我们想要杀死的那个进程的名字，我们能够利用 `killall` 命令发送同样的信号，像这样：

```
killall -9 chrome

```

附带说明的是，上边这个命令可能不能捕捉到所有正在运行的 Chrome 进程。如果，运行了上边这个命令之后，你输入 `ps aux | grep chrome` 命令过滤一下，看到剩下正在运行的 Chrome 进程有那些，最好的办法还是回到 `kIll` 命令通过进程 ID 来发送信号值 `9` 来结束这个进程。

### 结束进程很容易

正如你看到的，杀死错误的进程并没有你原本想的那样有挑战性。当我让一个顽固的进程结束的时候，我趋向于用 `killall`命令来作为有效的方法来终止，然而，当我让一个真正的活跃的进程结束的时候，`kill`命令是一个好的方法。

---

via: <https://www.linux.com/learn/intro-to-linux/2017/5/how-kill-process-command-line>

作者：[JACK WALLEN](https://www.linux.com/users/jlwallen) 译者：[hwlog](https://github.com/hwlog) 校对：[wxy](https://github.com/wxy)

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


Summary: Python-mode 是一个 Vim 插件，它使你能够在 Vim 编辑器中更快的利用包括 pylint、rope、pydoc、pyflakes、pep8、autopep8、pep257　和 mccable 在内的各种库来写 Python 代码，这些库提供了一些编码功能，比如静态分析、特征重构、折叠、补全和文档等。

# Python-mode：在 Vim 编辑器中开发 Python 应用的 Vim 插件

<img src="content_image/album_201705_26_162307dc49my9gwrzl1ivv.jpg" alt="" title="">

Python-mode 是一个 Vim 插件，它使你能够在 [Vim 编辑器](https://www.tecmint.com/vi-editor-usage/)中更快的利用包括 pylint、rope、pydoc、pyflakes、pep8、autopep8、pep257　和 mccable 在内的各种库来写 Python 代码，这些库提供了一些编码功能，比如静态分析、特征重构、折叠、补全和文档等。

**推荐阅读：** [如何用 Bash-Support 插件将 Vim 编辑器打造成编写 Bash 脚本的 IDE](/article-8467-1.html)

这个插件包含了所有你在 Vim 编辑器中可以用来开发 Python 应用的特性。

### Python-mode 的特性

它包含下面这些值得一提的特性：

* 支持 Python 2.6+ 至 Python 3.2 版本
* 语法高亮
* 提供 virtualenv 支持
* 支持 Python 式折叠
* 提供增强的 Python 缩进
* 能够在 Vim 中运行 Python 代码
* 能够添加/删除断点
* 支持 Python 代码的快捷移动和操作
* 能够在运行的同时检查代码（pylint、pyflakes、pylama ……）
* 支持自动修复 PEP8 错误
* 允许在 Python 文档中进行搜索
* 支持代码重构
* 支持强代码补全
* 支持定义跳转

在这篇教程中，我将阐述如何在 Linux 中为 Vim 安装设置 Python-mode，从而在 Vim 编辑器中开发 Python 应用。

### 如何在 Linux 系统中为 Vim 安装 Python-mode

首先安装 [Pathogen](https://github.com/tpope/vim-pathogen) （它使得安装插件超级简单，并且运行文件位于私有目录中），从而更加容易的安装 Python-mode

运行下面的命令来获取 `pathogen.vim` 文件和它需要的目录：

```
# mkdir -p ~/.vim/autoload ~/.vim/bundle && \
# curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim

```

然后把下面这些内容加入 `~/.vimrc` 文件中：

```
execute pathogen#infect()
syntax on
filetype plugin indent on

```

安装好 pathogen 以后，你可以像下面这样把 Python-mode 插件放入 `~/.vim/bunble` 目录中：

```
# cd ~/.vim/bundle
# git clone https://github.com/klen/python-mode.git

```

然后像下面这样在 Vim 中重建 `helptags` ：

```
:helptags

```

你需要启用 `filetype-plugin` （`:help filetype-plugin-on`）和 `filetype-indent` （`:help filetype-indent-on`）来使用 Python-mode 。

### 在 Debian 和 Ubuntu 中安装 Python-mode

另一种在 Debian 和 Ubuntu 中安装 Python-mode 的方法是使用 PPA，就像下面这样

```
$ sudo add-apt-repository https://klen.github.io/python-mode/deb main
$ sudo apt-get update
$ sudo apt-get install vim-python-mode

```

如果你遇到消息：“The following signatures couldn’t be verified because the public key is not available”，请运行下面的命令：

```
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B5DF65307000E266

```

现在，使用 `vim-addon-manager` 启用 Python-mode：

```
$ sudo apt install vim-addon-manager
$ vim-addons install python-mode

```

### 在 Linux 中定制 Python-mode

如果想覆盖默认键位绑定，可以在 `.vimrc` 文件中重定义它们，比如：

```
" Override go-to.definition key shortcut to Ctrl-]
let g:pymode_rope_goto_definition_bind = "<C-]>"
" Override run current python file key shortcut to Ctrl-Shift-e
let g:pymode_run_bind = "<C-S-e>"
" Override view python doc key shortcut to Ctrl-Shift-d
let g:pymode_doc_bind = "<C-S-d>"

```

注意，默认情况下， Python-mode 使用 Python 2 进行语法检查。你可以在 `.vimrc` 文件中加入下面这行内容从而启动 Python 3 语法检查。

```
let g:pymode_python = 'python3'

```

你可以在 Python-mode 的 GitHub 仓库找到更多的配置选项： <https://github.com/python-mode/python-mode>

这就是全部内容了。在本教程中，我向你们展示了如何在 Linux 中使用 Python-mode 来配置 Vim 。请记得通过下面的反馈表来和我们分享你的想法。

---

作者简介：

Aaron Kili 是一个 Linux 和 F.O.S.S 爱好者、Linux 系统管理员、网络开发人员，现在也是 TecMint 的内容创作者，他喜欢和电脑一起工作，坚信共享知识。

---

via: <https://www.tecmint.com/python-mode-a-vim-editor-plugin/>

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

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


Go 语言日志指南

# Go 语言日志指南

你是否厌烦了那些使用复杂语言编写的、难以部署的、总是在不停构建的解决方案？Golang 是解决这些问题的好方法，它和 C 语言一样快，又和 Python 一样简单。

但是你是如何使用 Golang 日志监控你的应用程序的呢？Golang 没有异常，只有错误。因此你的第一印象可能就是开发 Golang 日志策略并不是一件简单的事情。不支持异常事实上并不是什么问题，异常在很多编程语言中已经失去了其异常性：它们过于被滥用以至于它们的作用都被忽视了。

在进一步深入之前，我们首先会介绍 Golang 日志的基础，并讨论 Golang 日志标准、元数据意义、以及最小化 Golang 日志对性能的影响。通过日志，你可以追踪用户在你应用中的活动，快速识别你项目中失效的组件，并监控总体性能以及用户体验。

### I. Golang 日志基础

#### 1) 使用 Golang “log” 库

Golang 给你提供了一个称为 “log” 的原生[日志库](https://golang.org/pkg/log/) 。它的日志器完美适用于追踪简单的活动，例如通过使用可用的[选项](https://golang.org/pkg/log/#pkg-constants)在错误信息之前添加一个时间戳。

下面是一个 Golang 中如何记录错误日志的简单例子：

```
package main

import (
    "log"
    "errors"
    "fmt"
    )

func main() {
   /* 定义局部变量 */
  ...

   /* 除法函数，除以 0 的时候会返回错误 */
   ret,err = div(a, b)
if err != nil {
 log.Fatal(err)
    }
    fmt.Println(ret)
}

```

如果你尝试除以 0，你就会得到类似下面的结果：

为了快速测试一个 Golang 函数，你可以使用 [go playground](https://play.golang.org/)。

为了确保你的日志总是能轻易访问，我们建议你把它们写到一个文件：

```
package main
import (
        "log"
        "os"
)
func main() {
        // 按照所需读写权限创建文件
        f, err := os.OpenFile("filename", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
        if err != nil {
                log.Fatal(err)
        }
        // 完成后延迟关闭，而不是习惯!
        defer f.Close()
        //设置日志输出到 f
        log.SetOutput(f)
        //测试用例
        log.Println("check to make sure it works")
}

```

你可以在[这里](https://www.goinggo.net/2013/11/using-log-package-in-go.html)找到 Golang 日志的完整指南，以及 “log” [库](https://golang.org/pkg/log/)内可用函数的完整列表。

现在你就可以记录它们的错误以及根本原因啦。

另外，日志也可以帮你将活动流拼接在一起，查找需要修复的错误上下文，或者调查在你的系统中单个请求如何影响其它应用层和 API。

为了获得更好的日志效果，你首先需要在你的项目中使用尽可能多的上下文丰富你的 Golang 日志，并标准化你使用的格式。这就是 Golang 原生库能达到的极限。使用最广泛的库是 [glog](https://github.com/google/glog) 和 [logrus](https://github.com/sirupsen/logrus)。必须承认还有很多好的库可以使用。如果你已经在使用支持 JSON 格式的库，你就不需要再换其它库了，后面我们会解释。

### II. 为你 Golang 日志统一格式

#### 1) JSON 格式的结构优势

在一个项目或者多个微服务中结构化你的 Golang 日志可能是最困难的事情，但一旦完成就很轻松了。结构化你的日志能使机器可读（参考我们 [收集日志的最佳实践博文](https://logmatic.io/blog/beyond-application-monitoring-discover-logging-best-practices/)）。灵活性和层级是 JSON 格式的核心，因此信息能够轻易被人类和机器解析以及处理。

下面是一个使用 [Logrus/Logmatic.io](https://github.com/logmatic/logmatic-go) 如何用 JSON 格式记录日志的例子：

```
package main
import (
  log "github.com/Sirupsen/logrus"
  "github.com/logmatic/logmatic-go"
)
func main() {
    // 使用 JSONFormatter
    log.SetFormatter(&logmatic.JSONFormatter{})
        // 使用 logrus 像往常那样记录事件
    log.WithFields(log.Fields{"string": "foo", "int": 1, "float": 1.1 }).Info("My first ssl event from golang")
}

```

会输出结果：

```
{
    "date":"2016-05-09T10:56:00+02:00",
    "float":1.1,
    "int":1,
    "level":"info",
    "message":"My first ssl event from golang",
    "String":"foo"
}

```

#### 2) 标准化 Golang 日志

同一个错误出现在你代码的不同部分，却以不同形式被记录下来是一件可耻的事情。下面是一个由于一个变量错误导致无法确定 web 页面加载状态的例子。一个开发者日志格式是：

```
message: 'unknown error: cannot determine loading status from unknown error: missing or invalid arg value client'</span>

```

另一个人的格式却是：

```
unknown error: cannot determine loading status - invalid client</span>

```

强制日志标准化的一个好的解决办法是在你的代码和日志库之间创建一个接口。这个标准化接口会包括所有你想添加到你日志中的可能行为的预定义日志消息。这么做可以防止出现不符合你想要的标准格式的自定义日志信息。这么做也便于日志调查。

由于日志格式都被统一处理，使它们保持更新也变得更加简单。如果出现了一种新的错误类型，它只需要被添加到一个接口，这样每个组员都会使用完全相同的信息。

最常使用的简单例子就是在 Golang 日志信息前面添加日志器名称和 id。你的代码然后就会发送 “事件” 到你的标准化接口，它会继续讲它们转化为 Golang 日志消息。

```
// 主要部分，我们会在这里定义所有消息。
// Event 结构体很简单。为了当所有信息都被记录时能检索它们，
// 我们维护了一个 Id
var (
    invalidArgMessage = Event{1, "Invalid arg: %s"}
    invalidArgValueMessage = Event{2, "Invalid arg value: %s => %v"}
    missingArgMessage = Event{3, "Missing arg: %s"}
)

// 在我们应用程序中可以使用的所有日志事件
func (l *Logger)InvalidArg(name string) {
    l.entry.Errorf(invalidArgMessage.toString(), name)
}
func (l *Logger)InvalidArgValue(name string, value interface{}) {
    l.entry.WithField("arg." + name, value).Errorf(invalidArgValueMessage.toString(), name, value)
}
func (l *Logger)MissingArg(name string) {
    l.entry.Errorf(missingArgMessage.toString(), name)
}

```

因此如果我们使用前面例子中无效的参数值，我们就会得到相似的日志信息：

```
time="2017-02-24T23:12:31+01:00" level=error msg="LoadPageLogger00003 - Missing arg: client - cannot determine loading status" arg.client=<nil> logger.name=LoadPageLogger

```

JSON 格式如下：

```
{"arg.client":null,"level":"error","logger.name":"LoadPageLogger","msg":"LoadPageLogger00003 - Missing arg: client - cannot determine loading status", "time":"2017-02-24T23:14:28+01:00"}

```

### III. Golang 日志上下文的力量

现在 Golang 日志已经按照特定结构和标准格式记录，时间会决定需要添加哪些上下文以及相关信息。为了能从你的日志中抽取信息，例如追踪一个用户活动或者工作流，上下文和元数据的顺序非常重要。

例如在 logrus 库中可以按照下面这样使用 JSON 格式添加 `hostname`、`appname` 和 `session` 参数：

```
// 对于元数据，通常做法是通过复用来重用日志语句中的字段。
  contextualizedLog := log.WithFields(log.Fields{
    "hostname": "staging-1",
    "appname": "foo-app",
    "session": "1ce3f6v"
  })
contextualizedLog.Info("Simple event with global metadata")

```

元数据可以视为 javascript 片段。为了更好地说明它们有多么重要，让我们看看几个 Golang 微服务中元数据的使用。你会清楚地看到是怎么在你的应用程序中跟踪用户的。这是因为你不仅需要知道一个错误发生了，还要知道是哪个实例以及什么模式导致了错误。假设我们有两个按顺序调用的微服务。上下文信息保存在头部（header）中传输：

```
func helloMicroService1(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
// 该服务负责接收所有到来的用户请求
// 我们会检查是否是一个新的会话还是已有会话的另一次调用
session := r.Header.Get("x-session")
if ( session == "") {
session = generateSessionId()
// 为新会话记录日志
}
// 每个请求的 Track Id 都是唯一的，因此我们会为每个会话生成一个
track := generateTrackId()
// 调用你的第二个微服务，添加 session/track
reqService2, _ := http.NewRequest("GET", "http://localhost:8082/", nil)
reqService2.Header.Add("x-session", session)
reqService2.Header.Add("x-track", track)
resService2, _ := client.Do(reqService2)
….

```

当调用第二个服务时：

```
func helloMicroService2(w http.ResponseWriter, r *http.Request) {
// 类似之前的微服务，我们检查会话并生成新的 track
session := r.Header.Get("x-session")
track := generateTrackId()
// 这一次，我们检查请求中是否已经设置了一个 track id，
// 如果是，它变为父 track
parent := r.Header.Get("x-track")
if (session == "") {
w.Header().Set("x-parent", parent)
}
// 为响应添加 meta 信息
w.Header().Set("x-session", session)
w.Header().Set("x-track", track)
if (parent == "") {
w.Header().Set("x-parent", track)
}
// 填充响应
w.WriteHeader(http.StatusOK)
io.WriteString(w, fmt.Sprintf(aResponseMessage, 2, session, track, parent))
}

```

现在第二个微服务中已经有和初始查询相关的上下文和信息，一个 JSON 格式的日志消息看起来类似如下。

在第一个微服务：

```
{"appname":"go-logging","level":"debug","msg":"hello from ms 1","session":"eUBrVfdw","time":"2017-03-02T15:29:26+01:00","track":"UzWHRihF"}

```

在第二个微服务：

```
{"appname":"go-logging","level":"debug","msg":"hello from ms 2","parent":"UzWHRihF","session":"eUBrVfdw","time":"2017-03-02T15:29:26+01:00","track":"DPRHBMuE"}

```

如果在第二个微服务中出现了错误，多亏了 Golang 日志中保存的上下文信息，现在我们就可以确定它是怎样被调用的以及什么模式导致了这个错误。

如果你想进一步深挖 Golang 的追踪能力，这里还有一些库提供了追踪功能，例如 [Opentracing](https://github.com/opentracing/opentracing-go)。这个库提供了一种简单的方式在或复杂或简单的架构中添加追踪的实现。它通过不同步骤允许你追踪用户的查询，就像下面这样：

### IV. Golang 日志对性能的影响

#### 1) 不要在 Goroutine 中使用日志

在每个 goroutine 中创建一个新的日志器看起来很诱人。但最好别这么做。Goroutine 是一个轻量级线程管理器，它用于完成一个 “简单的” 任务。因此它不应该负责日志。它可能导致并发问题，因为在每个 goroutine 中使用 `log.New()` 会重复接口，所有日志器会并发尝试访问同一个 io.Writer。

为了限制对性能的影响以及避免并发调用 io.Writer，库通常使用一个特定的 goroutine 用于日志输出。

#### 2) 使用异步库

尽管有很多可用的 Golang 日志库，要注意它们中的大部分都是同步的（事实上是伪异步）。原因很可能是到现在为止它们中没有一个会由于日志严重影响性能。

但正如 Kjell Hedström 在[他的实验](https://sites.google.com/site/kjellhedstrom2/g2log-efficient-background-io-processign-with-c11/g2log-vs-google-s-glog-performance-comparison)中展示的，使用多个线程创建成千上万日志，即便是在最坏情况下，异步 Golang 日志也会有 40% 的性能提升。因此日志是有开销的，也会对你的应用程序性能产生影响。如果你并不需要处理大量的日志，使用伪异步 Golang 日志库可能就足够了。但如果你需要处理大量的日志，或者很关注性能，Kjell Hedström 的异步解决方案就很有趣（尽管事实上你可能需要进一步开发，因为它只包括了最小的功能需求）。

#### 3）使用严重等级管理 Golang 日志

一些日志库允许你启用或停用特定的日志器，这可能会派上用场。例如在生产环境中你可能不需要一些特定等级的日志。下面是一个如何在 glog 库中停用日志器的例子，其中日志器被定义为布尔值：

```
type Log bool
func (l Log) Println(args ...interface{}) {
    fmt.Println(args...)
}
var debug Log = false
if debug {
    debug.Println("DEBUGGING")
}

```

然后你就可以在配置文件中定义这些布尔参数来启用或者停用日志器。

没有一个好的 Golang 日志策略，Golang 日志可能开销很大。开发人员应该抵制记录几乎所有事情的诱惑 - 尽管它非常有趣！如果日志的目的是为了获取尽可能多的信息，为了避免包含无用元素的日志的白噪音，必须正确使用日志。

### V. 集中化 Golang 日志

如果你的应用程序是部署在多台服务器上的，这样可以避免为了调查一个现象需要连接到每一台服务器的麻烦。日志集中确实有用。

使用日志装箱工具，例如 windows 中的 Nxlog，linux 中的 Rsyslog（默认安装了的）、Logstash 和 FluentD 是最好的实现方式。日志装箱工具的唯一目的就是发送日志，因此它们能够处理连接失效以及其它你很可能会遇到的问题。

这里甚至有一个 [Golang syslog 软件包](https://golang.org/pkg/log/syslog/) 帮你将 Golang 日志发送到 syslog 守护进程。

### 希望你享受你的 Golang 日志之旅

在你项目一开始就考虑你的 Golang 日志策略非常重要。如果在你代码的任意地方都可以获得所有的上下文，追踪用户就会变得很简单。从不同服务中阅读没有标准化的日志是已经很痛苦的事情。一开始就计划在多个微服务中扩展相同用户或请求 id，后面就会允许你比较容易地过滤信息并在你的系统中跟踪活动。

你是在构架一个很大的 Golang 项目还是几个微服务也会影响你的日志策略。一个大项目的主要组件应该有按照它们功能命名的特定 Golang 日志器。这使你可以立即判断出日志来自你的哪一部分代码。然而对于微服务或者小的 Golang 项目，只有较少的核心组件需要它们自己的日志器。但在每种情形中，日志器的数目都应该保持低于核心功能的数目。

你现在已经可以使用 Golang 日志量化决定你的性能或者用户满意度啦！

*如果你有想阅读的特定编程语言，在 Twitter [@logmatic](http://twitter.com/logmatic) 上告诉我们吧。*

---

via: <https://logmatic.io/blog/our-guide-to-a-golang-logs-world/>

作者：[Nils](https://logmatic.io/blog/our-guide-to-a-golang-logs-world/) 译者：[ictlyh](https://github.com/ictlyh) 校对：[wxy](https://github.com/wxy)

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