- [][12] [][13]
-**Q.bo One detail view (left) and Qboard detail**
-(click images to enlarge)
-
+[][11]
-Q.bo One 也可类似地与基于 Linux 的 [Jibo][24] “社交机器人”相比,它于 2014 年在 Indiegogo 推出,最后达到 360 万美元。然而,Jibo 还没有出货,[最近的推迟][25]迫使它在今年的某个时候发布一个版本。
+*Q.bo One 套件*
+
+与 2010 年的 Qbo 不同,Q.bo One 除了球面头部之外无法移动,它可以在双重伺服系统的帮助下在底座上旋转,以便跟踪声音和动作。Robotis Dynamixel 舵机同样开源,树莓派基于 [TurtleBot 3][23] 机器人工具包,除了左右之外,还可以上下移动。
+
+[][12]
+
+*Q.bo One 细节*
+
+[][13]
+
+*Qboard 细节*
+
+Q.bo One 类似于基于 Linux 的 [Jibo][24] “社交机器人”,它于 2014 年在 Indiegogo 众筹,最后达到 360 万美元。然而,Jibo 还没有出货,[最近的推迟][25]迫使它在今年的某个时候发布一个版本。
-|

-**Q.bo One** |
+*Q.bo One*
-我们大胆预测 Q.bo One 将会在 2017 年接近 12 月出货。核心技术和 AI 软件已被证明,而 Raspberry Pi 和 Arduino 技术也是如此。Qboard 主板已经由 Arrow 制造和认证。
+我们大胆预测 Q.bo One 将会在 2017 年接近 12 月出货。核心技术和 AI 软件已被证明,而树莓派和 Arduino 技术也是如此。Qboard 主板已经由 Arrow 制造和认证。
-开源设计表明, 即使是移动版本也不会有问题。这使它更像是滚动的人形生物 [Pepper][14],一个来自 Softbank 和 Aldeberan 类似的人工智能对话机器人。
+开源设计表明,即使是移动版本也不会有问题。这使它更像是滚动的人形生物 [Pepper][14],这是一个来自 Softbank 和 Aldeberan 类似的人工智能对话机器人。
-Q.bo One 自原版以来添加了一些技巧,例如由 20 个 LED 组成的“嘴巴”, 它以不同的、可编程的方式在语音中模仿嘴唇移动。如果你想点击机器人获得关注,那么它的头上还有三个触摸传感器。但是,你真正需要做的就是说话,而 Q.bo One 会像一个可卡犬一样转身并凝视着你。
+Q.bo One 自原始版以来添加了一些技巧,例如由 20 个 LED 组成的“嘴巴”, 它以不同的、可编程的方式在语音中模仿嘴唇开合。如果你想点击机器人获得关注,那么它的头上还有三个触摸传感器。但是,你其实只需要说话就行,而 Q.bo One 会像一个可卡犬一样转身并凝视着你。
-接口和你在 Raspberry Pi 3 上的一样,它在我们的[2017 黑客电路板调查][15]中消灭了其他对手。为 RPi 3 的 WiFi 和蓝牙安装了天线。
+接口和你在树莓派 3 上的一样,它在我们的 [2017 黑客电路板调查][15]中消灭了其他对手。为树莓派 3 的 WiFi 和蓝牙安装了天线。
-
- [][16] [][17]
-**Q.bo One software architecture (left) and Q.bo One with Scratch screen**
-(click images to enlarge)
-
+[][16]
+
+*Q.bo One 软件架构*
+
+[][17]
+
+*Q.bo One 及 Scratch 编程*
Qboard(也称为 Q.board)在 Atmel ATSAMD21 MCU 上运行 Arduino 代码,并有三个麦克风、扬声器、触摸传感器、Dynamixel 控制器和用于嘴巴的 LED 矩阵。其他功能包括 GPIO、I2C接口和可连接到台式机的 micro-USB 口。
@@ -66,19 +70,17 @@ Q.bo One 可以识别脸部和追踪移动,机器人甚至可以在镜子中
基于 Raspbian 的软件使用 OpenCV 进行视觉处理,并可以使用各种语言(包括 C++)进行编程。该软件还提供了 IBM Bluemix、NodeRED 和 ROS 的钩子。大概你也可以整合 [Alexa][18] 或 [Google Assistant][19]语音代理,虽然 Thecorpora 没有提及这一点。
-
**更多信息**
-Q.bo One 在 7 月中旬在 Indiegogo 上架,起价为 $369 的完整套件和 $499 的所有组合
-。出货量预计在 2017 年 12 月。更多信息请参见[ Q.bo One 的 Indiegogo 页面][20] 和[ Thecorpora 网站][21]。
+Q.bo One 在 7 月中旬在 Indiegogo 上架,起价为完整套件 $369 和完整组合 $499 。出货预计在 2017 年 12 月。更多信息请参见 [Q.bo One 的 Indiegogo 页面][20] 和[Thecorpora 网站][21]。
--------------------------------------------------------------------------------
via: http://linuxgizmos.com/open-source-social-robot-kit-runs-on-raspberry-pi-and-arduino/
-作者:[ Eric Brown][a]
+作者:[Eric Brown][a]
译者:[geekpi](https://github.com/geekpi)
-校对:[校对者ID](https://github.com/校对者ID)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/published/20170703 Brewing beer with Linux python and raspberry pi.md b/published/20170703 Brewing beer with Linux python and raspberry pi.md
new file mode 100644
index 0000000000..08a7a1cd55
--- /dev/null
+++ b/published/20170703 Brewing beer with Linux python and raspberry pi.md
@@ -0,0 +1,159 @@
+用 Linux、Python 和树莓派酿制啤酒
+============================================================
+
+> 怎样在家用 Python 和树莓派搭建一个家用便携的自制酿啤酒装置
+
+
+
+大约十年前我开始酿制自制啤酒,和许多自己酿酒的人一样,我开始在厨房制造提纯啤酒。这需要一些设备并且做出来后确实是好的啤酒,最终,我用一个放入了所有大麦的大贮藏罐作为我的麦芽浆桶。几年之后我一次酿制过 5 加仑啤酒,但是酿制 10 加仑时也会花费同样的时间和效用(只是容器比之前大些),之前我就是这么做的。容量提升到 10 加仑之后,我偶然看到了 [StrangeBrew Elsinore][38] ,我意识到我真正需要的是将整个酿酒过程转换成全电子化的,用树莓派来运行它。
+
+建造自己的家用电动化酿酒系统需要大量这方面的技术信息,许多学习酿酒的人是在 [TheElectricBrewery.com][28] 这个网站起步的,只不过将那些控制版搭建在一起是十分复杂的,尽管最简单的办法在这个网站上总结的很好。当然你也能用[一个小成本的方法][26]并且依旧可以得到相同的结果 —— 用一个热水壶和热酒容器通过一个 PID 控制器来加热你的酿酒原料。但是我认为这有点太无聊(这也意味着你不能体验到完整的酿酒过程)。
+
+### 需要用到的硬件
+
+在我开始我的这个项目之前, 我决定开始买零件,我最基础的设计是一个可以将液体加热到 5500 瓦的热酒容器(HLT)和开水壶,加一个活底的麦芽浆桶,我通过一个 50 英尺的不锈钢线圈在热酒容器里让泵来再循环麦芽浆(["热量交换再循环麦芽浆系统, 也叫 HERMS][27])。同时我需要另一个泵来在热酒容器里循环水,并且把水传输到麦芽浆桶里,整个电子部件全部是用树莓派来控制的。
+
+建立我的电子酿酒系统并且尽可能的自动化意味着我需要以下的组件:
+
+* 一个 5500 瓦的电子加热酒精容器(HLT)
+* 能够放入加热酒精容器里的 50 英尺(0.5 英寸)的不锈钢线圈(热量交换再循环麦芽浆系统)
+* 一个 5500 瓦的电子加热水壶
+* 多个固态继电器加热开关
+* 2 个高温食品级泵
+* 泵的开关用继电器
+* 可拆除装置和一个硅管
+* 不锈钢球阀
+* 一个测量温度的探针
+* 很多线
+* 一个来容纳这些配件的电路盒子
+
+
+
+*酿酒系统 (photo by Christopher Aedo. [CC BY-SA 4.0)][5]*
+
+建立酿酒系统的电气化方面的细节 [The Electric Brewery][28] 这个网站概括的很好,这里我不再重复,当你计划用树莓派代替这个 PID 控制器的话,你可以读以下的建议。
+
+一个重要的事情需要注意,固态继电器(SSR)信号电压,许多教程建议使用一个 12 伏的固态继电器来关闭电路,树莓派的 GPIO 针插口只支持 3 伏输出电压,然而,必须购买继电器将电压变为 3 伏。
+
+
+
+*Inkbird SSR (photo by Christopher Aedo. [CC BY-SA 4.0)][6]*
+
+要运行酿酒系统,你的树莓派必须做两个关键事情:测量来自几个不同位置的温度,用继电器开关来控制加热元件,树莓派很容易来处理这些任务。
+
+这里有一些不同的方法来将温度传感器连到树莓派上,但是我找到了最方便的方法用[单总线][29]。这就可以让多个传感器分享相同的线路(实际上是三根线),这三根线可以使酿酒系统的多个设备更方便的工作,如果你要从网上找一个防水的 DS18B20 温度传感器,你可以会找到很多选择。我用的是[日立 DS18B20 防水温度传感器][30]。
+
+要控制加热元件,树莓派包括了几个用来软件寻址的总线扩展器(GPIO),它会通过在某个文件写入 0 或者 1 让你发送3.3v 的电压到一个继电器,在我第一次了解树莓派是怎样工作的时候,这个[用 GPIO 驱动继电器的树莓派教程][46]对我来说是最有帮助的,总线扩展器控制着多个固态继电器,通过酿酒软件来直接控制加热元件的开关。
+
+我首先将所有部件放到这个电路盒子,因为这将成为一个滚动的小车,我要让它便于移动,而不是固定不动的,如果我有一个店(比如说在车库、工具房、或者地下室),我需要要用一个装在墙上的更大的电路盒,而现在我找到一个大小正好的[防水工程盒子][31],能放进每件东西,最后它成为小巧紧凑工具盒,并且能够工作。在左下角是和树莓派连接的为总线扩展器到单总线温度探针和[固态继电器][32]的扩展板。
+
+要保持 240v 的固态继电器温度不高,我在盒子上切了个洞,在盒子的外面用 CPU 降温凝胶把[铜片散热片][33]安装到盒子外面的热槽之间。它工作的很好,盒子里没有温度上的问题了,在盒子盖上我放了两个开关为 120v 的插座,加两个240v 的 led 来显示加热元件是否通电。我用干燥器的插座和插头,所以可以很容易的断开电热水壶的连接。首次尝试每件事情都工作正常。(第一次绘制电路图必有回报)
+
+这个照片来自“概念”版,最终生产系统应该有两个以上的固态继电器,以便 240v 的电路两个针脚能够切换,另外我将通过软件来切换泵的开关。现在通过盒子前面的物理开关控制它们,但是也很容易用继电器控制它们。
+
+
+
+*控制盒子 (photo by Christopher Aedo. [CC BY-SA 4.0)][7]*
+
+唯一剩下有点棘手的事情是温度探针的压合接头,这个探针安装在加热酒精容器和麦芽浆桶球形的最底部阀门前的 T 字型接头上。当液体流过温度传感器,温度可以准确显示。我考虑加一个套管到热水壶里,但是对于我的酿造工艺没有什么用。最后,我买到了[四分之一英寸的压合接头][34],它们工作完美。
+
+### 软件
+
+一旦硬件整理好,我就有时间来处理软件了,我在树莓派上跑了最新的 [Raspbian 发行版][35],操作系统方面没有什么特别的。
+
+我开始使用 [Strangebrew Elsinore][36] 酿酒软件,当我的朋友问我是否我听说过 [Hosehead][37](一个基于树莓派的酿酒控制器),我找到了 [Strangebrew Elsinore][36] 。我认为 [Hosehead][37] 很棒,但我并不是要买一个酿酒控制器,而是要挑战自己,搭建一个自己的。
+
+设置 [Strangebrew Elsinore][36] 很简单,其[文档][38]直白,没有遇到任何的问题。尽管 Strangebrew Elsinore 工作的很好,但在我的一代树莓派上运行 java 有时是费力的,不止崩溃一次。我看到这个软件开发停顿也很伤心,似乎他们也没有更多贡献者的大型社区(尽管有很多人还在用它)。
+
+#### CraftBeerPi
+
+之后我偶然遇到了一个用 Python 写的 [CraftbeerPI][39],它有活跃的贡献者支持的开发社区。原作者(也是当前维护者) Manuel Fritsch 在贡献和反馈问题处理方面做的很好。克隆[这个仓库][40]然后开始只用了我一点时间。其 README 文档也是一个连接 DS1820 温度传感器的好例子,同时也有关于硬件接口到树莓派或者[芯片电脑][41] 的注意事项。
+
+在启动的时候,CraftbeerPI 引导用户通过一个设置过程来发现温度探针是否可用,并且让你指定哪个 GPIO 总线扩展器指针来管理树莓派上哪个配件。
+
+
+
+*CraftBeerPi (photo by Christopher Aedo. [CC BY-SA 4.0)][8]*
+
+用这个系统进行自制酿酒是容易的,我能够依靠它掌握可靠的温度,我能输入多个温度段来控制麦芽浆温度,用CraftbeerPi 酿酒的日子有一点点累,但是我很高兴用传统的手工管理丙烷燃烧器的“兴奋”来换取这个系统的有效性和持续性。
+
+CraftBeerPI 的用户友好性鼓舞我设置了另一个控制器来运行“发酵室”。就我来说,那是一个二手冰箱,我用了 50 美元加上放在里面的 25 美元的加热器。CraftBeerPI 很容易控制电器元件的冷热,你也能够设置多个温度阶段。举个例子,这个图表显示我最近做的 IPA 进程的发酵温度。发酵室发酵麦芽汁在 67F° 的温度下需要 4 天,然后每 12 小时上升一度直到温度到达 72F°。剩下两天温度保持不变是为了双乙酰生成。之后 5 天温度降到 65F°,这段时间是让啤酒变“干”,最后啤酒发酵温度直接降到 38F°。CraftBeerPI 可以加入各个阶段,让软件管理发酵更加容易。
+
+
+
+*SIPA 发酵设置 (photo by Christopher Aedo. [CC BY-SA 4.0)][9]*
+
+我也试验过用[液体比重计][42]来对酵啤酒的比重进行监测,通过蓝牙连接的浮动传感器可以达到。有一个整合的计划能让 CraftbeerPi 很好工作,现在它记录这些比重数据到谷歌的电子表格里。一旦这个液体比重计能连接到发酵控制器,设置的自动发酵设置会基于酵母的活动性直接运行且更加容易,而不是在 4 天内完成主要发酵,可以在比重稳定 24 小时后设定温度。
+
+像这样的一些项目,构想并计划改进和增加组件是很容易,不过,我很高兴今天经历过的事情。我用这种装置酿造了很多啤酒,每次都能达到预期的麦芽汁比率,而且啤酒一直都很美味。我的最重要的消费者 —— 就是我!很高兴我可以随时饮用。
+
+
+
+*随时饮用 (photo by Christopher Aedo. [CC BY-SA 4.0)][10]*
+
+这篇文章基于 Christopher 的开放的西部的讲话《用Linux、Python 和树莓派酿制啤酒》。
+
+(题图:[Quinn Dombrowski][21]. Modified by Opensource.com. [CC BY-SA 4.0][22])
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Christopher Aedo 从他的学生时代就从事并且贡献于开源软件事业。最近他在 IBM 领导一个极棒的上游开发者团队,同时他也是开发者拥护者。当他不再工作或者实在会议室演讲的时候,他可能在波特兰市俄勒冈州用树莓派酿制和发酵一杯美味的啤酒。
+
+----
+via: https://opensource.com/article/17/7/brewing-beer-python-and-raspberry-pi
+
+作者:[Christopher Aedo][a]
+译者:[hwlife](https://github.com/hwlife)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/docaedo
+[1]:https://opensource.com/tags/raspberry-pi?src=raspberry_pi_resource_menu1
+[2]:https://opensource.com/resources/what-raspberry-pi?src=raspberry_pi_resource_menu2
+[3]:https://opensource.com/article/16/12/getting-started-raspberry-pi?src=raspberry_pi_resource_menu3
+[4]:https://opensource.com/article/17/2/raspberry-pi-submit-your-article?src=raspberry_pi_resource_menu4
+[5]:https://creativecommons.org/licenses/by-sa/4.0/
+[6]:https://creativecommons.org/licenses/by-sa/4.0/
+[7]:https://creativecommons.org/licenses/by-sa/4.0/
+[8]:https://creativecommons.org/licenses/by-sa/4.0/
+[9]:https://creativecommons.org/licenses/by-sa/4.0/
+[10]:https://creativecommons.org/licenses/by-sa/4.0/
+[11]:https://opensource.com/file/358661
+[12]:https://opensource.com/file/358666
+[13]:https://opensource.com/file/358676
+[14]:https://opensource.com/file/359061
+[15]:https://opensource.com/file/358681
+[16]:https://opensource.com/file/359071
+[17]:https://opensource.com/article/17/7/brewing-beer-python-and-raspberry-pi?rate=fbKzT1V9gqGsmNCTuQIashC1xaHT5P_2LUaeTn6Kz1Y
+[18]:https://www.openwest.org/custom/description.php?id=139
+[19]:https://www.openwest.org/
+[20]:https://opensource.com/user/145976/feed
+[21]:https://www.flickr.com/photos/quinndombrowski/
+[22]:https://creativecommons.org/licenses/by-sa/4.0/
+[23]:https://github.com/DougEdey/SB_Elsinore_Server
+[24]:https://opensource.com/tags/raspberry-pi
+[25]:http://www.theelectricbrewery.com/
+[26]:http://www.instructables.com/id/Electric-Brewery-Control-Panel-on-the-Cheap/
+[27]:https://byo.com/hops/item/1325-rims-and-herms-brewing-advanced-homebrewing
+[28]:http://theelectricbrewery.com/
+[29]:https://en.wikipedia.org/wiki/1-Wire
+[30]:https://smile.amazon.com/gp/product/B018KFX5X0/
+[31]:http://amzn.to/2hupFCr
+[32]:http://amzn.to/2hL8JDS
+[33]:http://amzn.to/2i4DYwy
+[34]:https://www.brewershardware.com/CF1412.html
+[35]:https://www.raspberrypi.org/downloads/raspbian/
+[36]:https://github.com/DougEdey/SB_Elsinore_Server
+[37]:https://brewtronix.com/
+[38]:http://dougedey.github.io/SB_Elsinore_Server/
+[39]:http://www.craftbeerpi.com/
+[40]:https://github.com/manuel83/craftbeerpi
+[41]:https://www.nextthing.co/pages/chip
+[42]:https://tilthydrometer.com/
+[43]:https://opensource.com/users/docaedo
+[44]:https://opensource.com/users/docaedo
+[45]:https://opensource.com/article/17/7/brewing-beer-python-and-raspberry-pi#comments
+[46]:http://www.susa.net/wordpress/2012/06/raspberry-pi-relay-using-gpio/
\ No newline at end of file
diff --git a/published/20170714 Creating TCP IP port forwarding tunnels with SSH The 8 possible scenarios using OpenSSH.md b/published/20170714 Creating TCP IP port forwarding tunnels with SSH The 8 possible scenarios using OpenSSH.md
new file mode 100644
index 0000000000..4f5a75e902
--- /dev/null
+++ b/published/20170714 Creating TCP IP port forwarding tunnels with SSH The 8 possible scenarios using OpenSSH.md
@@ -0,0 +1,347 @@
+通过 SSH 实现 TCP / IP 隧道(端口转发):使用 OpenSSH 可能的 8 种场景
+============================================================
+
+对于 [Secure Shell (SSH)][21] 这样的网络协议来说,其主要职责就是在终端模式下访问一个远程系统。因为 SSH 协议对传输数据进行了加密,所以通过它在远端系统执行命令是安全的。此外,我们还可以在这种加密后的连接上通过创建隧道(端口转发)的方式,来实现两个不同终端间的互联。凭借这种方式,只要我们能通过 SSH 创建连接,就可以绕开防火墙或者端口禁用的限制。
+
+这个话题在网络领域有大量的应用和讨论:
+
+* [Wikipedia: SSH Tunneling][12]
+* [O’Reilly: Using SSH Tunneling][13]
+* [Ssh.com: Tunneling Explained][14]
+* [Ssh.com: Port Forwarding][15]
+* [SecurityFocus: SSH Port Forwarding][16]
+* [Red Hat Magazine: SSH Port Forwarding][17]
+
+我们在接下来的内容中并不讨论端口转发的细节,而是准备介绍一个如何使用 [OpenSSH][22] 来完成 TCP 端口转发的速查表,其中包含了八种常见的场景。有些 SSH 客户端,比如 [PuTTY][23],也允许通过界面配置的方式来实现端口转发。而我们着重关注的是通过 OpenSSH 来实现的的方式。
+
+在下面的例子当中,我们假设环境中的网络划分为外部网络(network1)和内部网络(network2)两部分,并且这两个网络之间,只能在 externo1 与 interno1 之间通过 SSH 连接的方式来互相访问。外部网络的节点之间和内部网络的节点之间是完全联通的。
+
+
+
+### 场景 1
+
+> 在 externo1 节点访问由 interno1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = localhost / 主机 = localhost )
+
+externo1 节点可以通过 OpenSSH 连接到 interno1 节点,之后我们想通过其访问运行在 5900 端口上的 VNC 服务。
+
+
+
+我们可以通过下面的命令来实现:
+
+```
+externo1 $ ssh -L 7900:localhost:5900 user@interno1
+```
+
+现在,我们可以在 externo1 节点上确认下 7900 端口是否处于监听状态中:
+
+```
+externo1 $ netstat -ltn
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+Tcp 0 0 127.0.0.1:7900 0.0.0.0:* LISTEN
+...
+```
+
+我们只需要在 externo1 节点上执行如下命令即可访问 internal 节点的 VNC 服务:
+
+```
+externo1 $ vncviewer localhost::7900
+```
+
+注意:在 [vncviewer 的 man 手册](http://www.realvnc.com/products/free/4.1/man/vncviewer.html)中并未提及这种修改端口号的方式。在 [About VNCViewer configuration of the output TCP port][18] 中可以看到。这也是 [the TightVNC vncviewer][19] 所介绍的的。
+
+### 场景 2
+
+> 在 externo2 节点上访问由 interno1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost)
+
+这次的场景跟方案 1 的场景的类似,但是我们这次想从 externo2 节点来连接到 interno1 上的 VNC 服务:
+
+
+
+正确的命令如下:
+
+```
+externo1 $ ssh -L 0.0.0.0:7900:localhost:5900 user@interno1
+```
+
+看起来跟方案 1 中的命令类似,但是让我们看看 `netstat` 命令的输出上的区别。7900 端口被绑定到了本地(`127.0.0.1`),所以只有本地进程可以访问。这次我们将端口关联到了 `0.0.0.0`,所以系统允许任何 IP 地址的机器访问 7900 这个端口。
+
+```
+externo1 $ netstat -ltn
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+Tcp 0 0 0.0.0.0:7900 0.0.0.0:* LISTEN
+...
+```
+
+所以现在在 externo2 节点上,我们可以执行:
+
+```
+externo2 $ vncviewer externo1::7900
+```
+
+来连接到 interno1 节点上的 VNC 服务。
+
+除了将 IP 指定为 `0.0.0.0` 之外,我们还可以使用参数 `-g`(允许远程机器使用本地端口转发),完整命令如下:
+
+```
+externo1 $ ssh -g -L 7900:localhost:5900 user@interno1
+```
+
+这条命令与前面的命令能实现相同效果:
+
+```
+externo1 $ ssh -L 0.0.0.0:7900:localhost:5900 user@interno1
+```
+
+换句话说,如果我们想限制只能连接到系统上的某个 IP,可以像下面这样定义:
+
+```
+externo1 $ ssh -L 192.168.24.80:7900:localhost:5900 user@interno1
+
+externo1 $ netstat -ltn
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+Tcp 0 0 192.168.24.80:7900 0.0.0.0:* LISTEN
+...
+```
+
+### 场景 3
+
+> 在 interno1 上访问由 externo1 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / 主机 = localhost)
+
+在场景 1 中 SSH 服务器与 TCP 服务(VNC)提供者在同一个节点上。现在我们想在 SSH 客户端所在的节点上,提供一个 TCP 服务(VNC)供 SSH 服务端来访问:
+
+
+
+将方案 1 中的命令参数由 `-L` 替换为 `-R`。
+
+完整命令如下:
+
+```
+externo1 $ ssh -R 7900:localhost:5900 user@interno1
+```
+
+然后我们就能看到 interno1 节点上对 7900 端口正在监听:
+
+```
+interno1 $ netstat -lnt
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+Tcp 0 0 127.0.0.1:7900 0.0.0.0:* LISTEN
+...
+```
+
+现在在 interno1 节点上,我们可以使用如下命令来访问 externo1 上的 VNC 服务:
+
+```
+interno1 $ vncviewer localhost::7900
+```
+
+### 场景 4
+
+> interno2 使用 externo1 上提供的 TCP 服务(远端端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost)
+
+与场景 3 类似,但是现在我们尝试指定允许访问转发端口的 IP(就像场景 2 中做的一样)为 `0.0.0.0`,这样其他节点也可以访问 VNC 服务:
+
+
+
+正确的命令是:
+
+```
+externo1 $ ssh -R 0.0.0.0:7900:localhost:5900 user@interno1
+```
+
+但是这里有个重点需要了解,出于安全的原因,如果我们直接执行该命令的话可能不会生效,因为我们需要修改 SSH 服务端的一个参数值 `GatewayPorts`,它的默认值是:`no`。
+
+> GatewayPorts
+>
+> 该参数指定了远程主机是否允许客户端访问转发端口。默认情况下,sshd(8) 只允许本机进程访问转发端口。这是为了阻止其他主机连接到该转发端口。GatewayPorts 参数可用于让 sshd 允许远程转发端口绑定到非回环地址上,从而可以让远程主机访问。当参数值设置为 “no” 的时候只有本机可以访问转发端口;“yes” 则表示允许远程转发端口绑定到通配地址上;或者设置为 “clientspecified” 则表示由客户端来选择哪些主机地址允许访问转发端口。默认值是 “no”。
+
+如果我们没有修改服务器配置的权限,我们将不能使用该方案来进行端口转发。这是因为如果没有其他的限制,用户可以开启一个端口(> 1024)来监听来自外部的请求并转发到 `localhost:7900`。
+
+参照这个案例:[netcat][24] ( [Debian # 310431: sshd_config should warn about the GatewayPorts workaround.][25] )
+
+所以我们修改 `/etc/ssh/sshd_config`,添加如下内容:
+
+```
+GatewayPorts clientspecified
+```
+
+然后,我们使用如下命令来重载修改后的配置文件(在 Debian 和 Ubuntu 上)。
+
+```
+sudo /etc/init.d/ssh reload
+```
+
+我们确认一下现在 interno1 节点上存在 7900 端口的监听程序,监听来自不同 IP 的请求:
+
+```
+interno1 $ netstat -ltn
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State
+...
+Tcp 0 0 0.0.0.0:7900 0.0.0.0:* LISTEN
+...
+```
+
+然后我们就可以在 interno2 节点上使用 VNC 服务了:
+
+```
+interno2 $ internal vncviewer1::7900
+```
+
+### 场景 5
+
+> 在 externo1 上使用由 interno2 提供的 TCP 服务(本地端口转发 / 绑定地址 localhost / 主机 = interno2 )
+
+
+
+在这种场景下我们使用如下命令:
+
+```
+externo1 $ ssh -L 7900:interno2:5900 user@interno1
+```
+
+然后我们就能在 externo1 节点上,通过执行如下命令来使用 VNC 服务了:
+
+```
+externo1 $ vncviewer localhost::7900
+```
+
+### 场景 6
+
+> 在 interno1 上使用由 externo2 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / host = externo2)
+
+
+
+在这种场景下,我们使用如下命令:
+
+```
+externo1 $ ssh -R 7900:externo2:5900 user@interno1
+```
+
+然后我们可以在 interno1 上通过执行如下命令来访问 VNC 服务:
+
+```
+interno1 $ vncviewer localhost::7900
+```
+
+### 场景7
+
+> 在 externo2 上使用由 interno2 提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = interno2)
+
+
+
+本场景下,我们使用如下命令:
+
+```
+externo1 $ ssh -L 0.0.0.0:7900:interno2:5900 user@interno1
+```
+
+或者:
+
+```
+externo1 $ ssh -g -L 7900:interno2:5900 user@interno1
+```
+
+然后我们就可以在 externo2 上执行如下命令来访问 vnc 服务:
+
+```
+externo2 $ vncviewer externo1::7900
+```
+
+### 场景 8
+
+> 在 interno2 上使用由 externo2 提供的 TCP 服务(远程端口转发 / 绑定地址 = 0.0.0.0 / 主机 = externo2)
+
+
+
+本场景下我们使用如下命令:
+
+```
+externo1 $ ssh -R 0.0.0.0:7900:externo2:5900 user@interno1
+```
+
+SSH 服务器需要配置为:
+
+```
+GatewayPorts clientspecified
+```
+
+就像我们在场景 4 中讲过的那样。
+
+然后我们可以在 interno2 节点上执行如下命令来访问 VNC 服务:
+
+```
+interno2 $ internal vncviewer1::7900
+```
+
+如果我们需要一次性的创建多个隧道,使用配置文件的方式替代一个可能很长的命令是一个更好的选择。假设我们只能通过 SSH 的方式访问某个特定网络,同时又需要创建多个隧道来访问该网络内不同服务器上的服务,比如 VNC 或者 [远程桌面][26]。此时只需要创建一个如下的配置文件 `$HOME/redirects` 即可(在 SOCKS 服务器 上)。
+
+```
+# SOCKS server
+DynamicForward 1080
+
+# SSH redirects
+LocalForward 2221 serverlinux1: 22
+LocalForward 2222 serverlinux2: 22
+LocalForward 2223 172.16.23.45:22
+LocalForward 2224 172.16.23.48:22
+
+# RDP redirects for Windows systems
+LocalForward 3391 serverwindows1: 3389
+LocalForward 3392 serverwindows2: 3389
+
+# VNC redirects for systems with "vncserver"
+LocalForward 5902 serverlinux1: 5901
+LocalForward 5903 172.16.23.45:5901
+```
+
+然后我们只需要执行如下命令:
+
+```
+externo1 $ ssh -F $HOME/redirects user@interno1
+```
+
+--------------------------------------------------------------------------------
+
+via: https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/
+
+作者:[Ahmad][a]
+译者:[toutoudnf](https://github.com/toutoudnf)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://wesharethis.com/author/ahmad/
+[1]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#
+[2]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_1_Use_onexterno1a_TCP_service_offered_byinterno1Local_port_forwarding_bind_address_localhost_host_localhost
+[3]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_2_Use_onexterno2a_TCP_service_offered_byinterno1Local_port_forwarding_bind_address_0000_host_localhost
+[4]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_3_Use_ininterno1a_TCP_service_offered_byexterno1Remote_port_forwarding_bind_address_localhost_host_localhost
+[5]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_4_Use_ininterno2a_TCP_service_offered_byexterno1Remote_port_forwarding_bind_address_0000_host_localhost
+[6]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_5_Use_inexterno1a_TCP_service_offered_byinterno2Local_port_forwarding_bind_address_localhost_host_interno2
+[7]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_6_Use_ininterno1a_TCP_service_offered_byexterno2Remote_port_forwarding_bind_address_localhost_host_externo2
+[8]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_7_Use_inexterno2a_TCP_service_offered_byinterno2Local_port_forwarding_bind_address_0000_host_interno2
+[9]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_8_Use_ininterno2a_TCP_service_offered_byexterno2Remote_port_forwarding_bind_address_0000_host_externo2
+[10]:https://wesharethis.com/author/ahmad/
+[11]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#comments
+[12]:http://en.wikipedia.org/wiki/Tunneling_protocol#SSH_tunneling
+[13]:http://www.oreillynet.com/pub/a/wireless/2001/02/23/wep.html
+[14]:http://www.ssh.com/support/documentation/online/ssh/winhelp/32/Tunneling_Explained.html
+[15]:http://www.ssh.com/support/documentation/online/ssh/adminguide/32/Port_Forwarding.html
+[16]:http://www.securityfocus.com/infocus/1816
+[17]:http://magazine.redhat.com/2007/11/06/ssh-port-forwarding/
+[18]:http://www.realvnc.com/pipermail/vnc-list/2006-April/054551.html
+[19]:http://www.tightvnc.com/vncviewer.1.html
+[20]:https://bufferapp.com/add?url=https%3A%2F%2Fwesharethis.com%2F2017%2F07%2Fcreating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh%2F&text=Creating%20TCP%20/%20IP%20(port%20forwarding)%20tunnels%20with%20SSH:%20The%208%20possible%20scenarios%20using%20OpenSSH
+[21]:http://en.wikipedia.org/wiki/Secure_Shell
+[22]:http://www.openssh.com/
+[23]:http://www.chiark.greenend.org.uk/~sgtatham/putty/
+[24]:http://en.wikipedia.org/wiki/Netcat
+[25]:http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310431
+[26]:http://en.wikipedia.org/wiki/Remote_Desktop_Services
diff --git a/translated/tech/20170726 Writing a Linux Debugger Part 9 Handling variables.md b/published/20170726 Writing a Linux Debugger Part 9 Handling variables.md
similarity index 77%
rename from translated/tech/20170726 Writing a Linux Debugger Part 9 Handling variables.md
rename to published/20170726 Writing a Linux Debugger Part 9 Handling variables.md
index 455b184d94..8b378e38ec 100644
--- a/translated/tech/20170726 Writing a Linux Debugger Part 9 Handling variables.md
+++ b/published/20170726 Writing a Linux Debugger Part 9 Handling variables.md
@@ -1,118 +1,79 @@
开发一个 Linux 调试器(九):处理变量
============================================================
-变量是偷偷摸摸的。有时,它们会很高兴地呆在寄存器中,但是一转头就会跑到堆栈中。为了优化,编译器可能会完全将它们从窗口中抛出。无论变量在内存中的移动频率如何,我们都需要一些方法在调试器中跟踪和操作它们。这篇文章将会教你如何处理调试器中的变量,并使用 `libelfin` 演示一个简单的实现。
-
-* * *
+变量是偷偷摸摸的。有时,它们会很高兴地呆在寄存器中,但是一转头就会跑到堆栈中。为了优化,编译器可能会完全将它们从窗口中抛出。无论变量在内存中的如何移动,我们都需要一些方法在调试器中跟踪和操作它们。这篇文章将会教你如何处理调试器中的变量,并使用 `libelfin` 演示一个简单的实现。
### 系列文章索引
-1. [设置][1]
-
+1. [准备环境][1]
2. [断点][2]
-
3. [寄存器和内存][3]
-
4. [ELF 和 DWARF][4]
-
-5. [源和信号][5]
-
-6. [源码级单步调试][6]
-
+5. [源码和信号][5]
+6. [源码级逐步执行][6]
7. [源码级断点][7]
-
8. [堆栈展开][8]
-
9. [处理变量][9]
-
10. [高级话题][10]
-* * *
+在开始之前,请确保你使用的 `libelfin` 版本是[我分支上的 `fbreg`][11]。这包含了一些 hack 来支持获取当前堆栈帧的基址并评估位置列表,这些都不是由原生的 `libelfin` 提供的。你可能需要给 GCC 传递 `-gdwarf-2` 参数使其生成兼容的 DWARF 信息。但是在实现之前,我将详细说明 DWARF 5 最新规范中的位置编码方式。如果你想要了解更多信息,那么你可以从[这里][12]获取该标准。
-在开始之前,请确保你使用的 `libelfin` 版本是[我分支上的 `fbreg`][11]。这包含了一些 hack 来支持获取当前堆栈帧的基址并评估位置列表,这些都不是由原生的 `libelfin` 提供的。你可能需要给 GCC 传递 `-gdwarf-2` 参数使其生成兼容的 DWARF 信息。但是在实现之前,我将详细说明 DWARF 5 最新规范中的位置编码方式。如果你想要了解更多信息,那么你可以从[这里][12]获取标准。
+### DWARF 位置
-### DWARF 未知
+某一给定时刻的内存中变量的位置使用 `DW_AT_location` 属性编码在 DWARF 信息中。位置描述可以是单个位置描述、复合位置描述或位置列表。
-使用 `DW_AT_location` 属性在 DWARF 信息中编码给定时刻内存中变量的位置。位置描述可以是单个位置描述,复合位置描述或位置列表。
+* 简单位置描述:描述了对象的一个连续的部分(通常是所有部分)的位置。简单位置描述可以描述可寻址存储器或寄存器中的位置,或缺少位置(具有或不具有已知值)。比如,`DW_OP_fbreg -32`: 一个整个存储的变量 - 从堆栈帧基址开始的32个字节。
+* 复合位置描述:根据片段描述对象,每个对象可以包含在寄存器的一部分中或存储在与其他片段无关的存储器位置中。比如, `DW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2`:前四个字节位于寄存器 3 中,后两个字节位于寄存器 10 中的一个变量。
+* 位置列表:描述了具有有限生存期或在生存期内更改位置的对象。比如:
+ * ``
+ * `[ 0]DW_OP_reg0`
+ * `[ 1]DW_OP_reg3`
+ * `[ 2]DW_OP_reg2`
+ * 根据程序计数器的当前值,位置在寄存器之间移动的变量。
-* 简单的位置描述描述对象的一个连续的部分(通常是所有)的位置。简单位置描述可以描述可寻址存储器或寄存器中的位置,或缺少位置(具有或不具有已知值)。
- * 比如:
- * `DW_OP_fbreg -32`
-
- * 一个完全存储的变量 - 从堆栈帧基址开始的32个字节
-
-* 复合位置描述根据片段描述对象,每个对象可以包含在寄存器的一部分中或存储在与其他片段无关的存储器位置中。
- * 比如:
- * `DW_OP_reg3 DW_OP_piece 4 DW_OP_reg10 DW_OP_piece 2`
-
- * 前四个字节位于寄存器 3 中,后两个字节位于寄存器 10 中的一个变量。
-
-* 位置列表描述了具有有限周期或在周期内更改位置的对象。
- * 比如:
- * ``
- * `[ 0]DW_OP_reg0`
-
- * `[ 1]DW_OP_reg3`
-
- * `[ 2]DW_OP_reg2`
-
- * 根据程序计数器的当前值,位置在寄存器之间移动的变量
-
-根据位置描述的种类,`DW_AT_location` 以三种不同的方式进行编码。`exprloc` 编码简单和复合的位置描述。它们由一个字节长度组成,后跟一个 DWARF 表达式或位置描述。`loclist` 和 `loclistptr` 的编码位置列表。它们在 `.debug_loclists` 部分中提供索引或偏移量,该部分描述了实际的位置列表。
+根据位置描述的种类,`DW_AT_location` 以三种不同的方式进行编码。`exprloc` 编码简单和复合的位置描述。它们由一个字节长度组成,后跟一个 DWARF 表达式或位置描述。`loclist` 和 `loclistptr` 的编码位置列表,它们在 `.debug_loclists` 部分中提供索引或偏移量,该部分描述了实际的位置列表。
### DWARF 表达式
-使用 DWARF 表达式计算变量的实际位置。这包括操作堆栈值的一系列操作。有很多 DWARF 操作可用,所以我不会详细解释它们。相反,我会从每一个表达式中给出一些例子,给你一个可用的东西。另外,不要害怕这些; `libelfin` 将为我们处理所有这些复杂性。
+使用 DWARF 表达式计算变量的实际位置。这包括操作堆栈值的一系列操作。有很多 DWARF 操作可用,所以我不会详细解释它们。相反,我会从每一个表达式中给出一些例子,给你一个可用的东西。另外,不要害怕这些;`libelfin` 将为我们处理所有这些复杂性。
* 字面编码
- * `DW_OP_lit0`、`DW_OP_lit1`。。。`DW_OP_lit31`
- * 将字面值压入堆栈
-
+ * `DW_OP_lit0`、`DW_OP_lit1`……`DW_OP_lit31`
+ * 将字面量压入堆栈
* `DW_OP_addr `
* 将地址操作数压入堆栈
-
* `DW_OP_constu `
* 将无符号值压入堆栈
-
* 寄存器值
* `DW_OP_fbreg `
* 压入在堆栈帧基址找到的值,偏移给定值
-
- * `DW_OP_breg0`、`DW_OP_breg1`。。。 `DW_OP_breg31 `
+ * `DW_OP_breg0`、`DW_OP_breg1`…… `DW_OP_breg31 `
* 将给定寄存器的内容加上给定的偏移量压入堆栈
-
* 堆栈操作
* `DW_OP_dup`
* 复制堆栈顶部的值
-
* `DW_OP_deref`
* 将堆栈顶部视为内存地址,并将其替换为该地址的内容
-
* 算术和逻辑运算
* `DW_OP_and`
* 弹出堆栈顶部的两个值,并压回它们的逻辑 `AND`
-
* `DW_OP_plus`
* 与 `DW_OP_and` 相同,但是会添加值
-
* 控制流操作
* `DW_OP_le`、`DW_OP_eq`、`DW_OP_gt` 等
* 弹出前两个值,比较它们,并且如果条件为真,则压入 `1`,否则为 `0`
-
* `DW_OP_bra `
* 条件分支:如果堆栈的顶部不是 `0`,则通过 `offset` 在表达式中向后或向后跳过
-
* 输入转化
* `DW_OP_convert `
* 将堆栈顶部的值转换为不同的类型,它由给定偏移量的 DWARF 信息条目描述
-
* 特殊操作
* `DW_OP_nop`
- * 什么都能不做!
+ * 什么都不做!
### DWARF 类型
-DWARF 的类型表示需要足够强大来为调试器用户提供有用的变量表示。用户经常希望能够在应用程序级别进行调试,而不是在机器级别进行调试,并且他们需要了解他们的变量正在做什么。
+DWARF 类型的表示需要足够强大来为调试器用户提供有用的变量表示。用户经常希望能够在应用程序级别进行调试,而不是在机器级别进行调试,并且他们需要了解他们的变量正在做什么。
DWARF 类型与大多数其他调试信息一起编码在 DIE 中。它们可以具有指示其名称、编码、大小、字节等的属性。无数的类型标签可用于表示指针、数组、结构体、typedef 以及 C 或 C++ 程序中可以看到的任何其他内容。
@@ -168,7 +129,7 @@ struct test{
```
-每个成员都有一个名称,一个类型(它是一个 DIE 偏移量),一个声明文件和行,以及一个字节偏移到该成员所在的结构体中。类型指向下一个。
+每个成员都有一个名称、一个类型(它是一个 DIE 偏移量)、一个声明文件和行,以及一个指向其成员所在的结构体的字节偏移。其类型指向如下。
```
< 1><0x00000063> DW_TAG_base_type
@@ -195,11 +156,9 @@ struct test{
如你所见,我笔记本电脑上的 `int` 是一个 4 字节的有符号整数类型,`float`是一个 4 字节的浮点数。整数数组类型通过指向 `int` 类型作为其元素类型,`sizetype`(可以认为是 `size_t`)作为索引类型,它具有 `2a` 个元素。 `test *` 类型是 `DW_TAG_pointer_type`,它引用 `test` DIE。
-* * *
-
### 实现简单的变量读取器
-如上所述,`libelfin` 将处理我们大部分的复杂性。但是,它并没有实现用于表示可变位置的所有不同方法,并且在我们的代码中处理这些将变得非常复杂。因此,我现在选择只支持 `exprloc`。请随意添加对更多类型表达式的支持。如果你真的有勇气,请提交补丁到 `libelfin` 中来帮助完成必要的支持!
+如上所述,`libelfin` 将为我们处理大部分复杂性。但是,它并没有实现用于表示可变位置的所有方法,并且在我们的代码中处理这些将变得非常复杂。因此,我现在选择只支持 `exprloc`。请根据需要添加对更多类型表达式的支持。如果你真的有勇气,请提交补丁到 `libelfin` 中来帮助完成必要的支持!
处理变量主要是将不同部分定位在存储器或寄存器中,读取或写入与之前一样。为了简单起见,我只会告诉你如何实现读取。
@@ -305,29 +264,27 @@ void debugger::read_variables() {
编写一些具有一些变量的小功能,不用优化并带有调试信息编译它,然后查看是否可以读取变量的值。尝试写入存储变量的内存地址,并查看程序改变的行为。
-* * *
-
已经有九篇文章了,还剩最后一篇!下一次我会讨论一些你可能会感兴趣的更高级的概念。现在你可以在[这里][13]找到这个帖子的代码。
--------------------------------------------------------------------------------
via: https://blog.tartanllama.xyz/writing-a-linux-debugger-variables/
-作者:[ Simon Brand][a]
+作者:[Simon Brand][a]
译者:[geekpi](https://github.com/geekpi)
-校对:[校对者ID](https://github.com/校对者ID)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.twitter.com/TartanLlama
-[1]:https://blog.tartanllama.xyz/writing-a-linux-debugger-setup/
-[2]:https://blog.tartanllama.xyz/writing-a-linux-debugger-breakpoints/
-[3]:https://blog.tartanllama.xyz/writing-a-linux-debugger-registers/
-[4]:https://blog.tartanllama.xyz/writing-a-linux-debugger-elf-dwarf/
-[5]:https://blog.tartanllama.xyz/writing-a-linux-debugger-source-signal/
-[6]:https://blog.tartanllama.xyz/writing-a-linux-debugger-dwarf-step/
-[7]:https://blog.tartanllama.xyz/writing-a-linux-debugger-source-break/
-[8]:https://blog.tartanllama.xyz/writing-a-linux-debugger-unwinding/
+[1]:https://linux.cn/article-8626-1.html
+[2]:https://linux.cn/article-8645-1.html
+[3]:https://linux.cn/article-8663-1.html
+[4]:https://linux.cn/article-8719-1.html
+[5]:https://linux.cn/article-8812-1.html
+[6]:https://linux.cn/article-8813-1.html
+[7]:https://linux.cn/article-8890-1.html
+[8]:https://linux.cn/article-8930-1.html
[9]:https://blog.tartanllama.xyz/writing-a-linux-debugger-variables/
[10]:https://blog.tartanllama.xyz/writing-a-linux-debugger-advanced-topics/
[11]:https://github.com/TartanLlama/libelfin/tree/fbreg
diff --git a/translated/tech/20170801 Writing a Linux Debugger Part 10 Advanced topics.md b/published/20170801 Writing a Linux Debugger Part 10 Advanced topics.md
similarity index 53%
rename from translated/tech/20170801 Writing a Linux Debugger Part 10 Advanced topics.md
rename to published/20170801 Writing a Linux Debugger Part 10 Advanced topics.md
index 7e0d882082..61a02eb69d 100644
--- a/translated/tech/20170801 Writing a Linux Debugger Part 10 Advanced topics.md
+++ b/published/20170801 Writing a Linux Debugger Part 10 Advanced topics.md
@@ -1,95 +1,68 @@
开发一个 Linux 调试器(十):高级主题
============================================================
-我们终于来到这个系列的最后一篇文章!这一次,我将对调试中的一些更高级的概念进行高层的概述:远程调试、共享库支持、表达式计算和多线程支持。这些想法实现起来比较复杂,所以我不会详细说明如何做,但是如果有的话,我很乐意回答有关这些概念的问题。
-
-* * *
+我们终于来到这个系列的最后一篇文章!这一次,我将对调试中的一些更高级的概念进行高层的概述:远程调试、共享库支持、表达式计算和多线程支持。这些想法实现起来比较复杂,所以我不会详细说明如何做,但是如果你有问题的话,我很乐意回答有关这些概念的问题。
### 系列索引
1. [准备环境][1]
-
2. [断点][2]
-
3. [寄存器和内存][3]
-
4. [Elves 和 dwarves][4]
-
5. [源码和信号][5]
-
6. [源码层逐步执行][6]
-
7. [源码层断点][7]
-
8. [调用栈][8]
-
9. [处理变量][9]
-
10. [高级主题][10]
-* * *
-
### 远程调试
-远程调试对于嵌入式系统或不同环境的调试非常有用。它还在高级调试器操作和与操作系统和硬件的交互之间设置了一个很好的分界线。事实上,像 GDB 和 LLDB 这样的调试器即使在调试本地程序时也可以作为远程调试器运行。一般架构是这样的:
+远程调试对于嵌入式系统或对不同环境进行调试非常有用。它还在高级调试器操作和与操作系统和硬件的交互之间设置了一个很好的分界线。事实上,像 GDB 和 LLDB 这样的调试器即使在调试本地程序时也可以作为远程调试器运行。一般架构是这样的:

-调试器是我们通过命令行交互的组件。也许如果你使用的是 IDE,那么顶层中另一个层可以通过_机器接口_与调试器进行通信。在目标机器上(可能与本机一样)有一个 _debug stub_ ,它理论上是一个非常小的操作系统调试库的包装程序,它执行所有的低级调试任务,如在地址上设置断点。我说“在理论上”,因为如今 stub 变得越来越大。例如,我机器上的 LLDB debug stub 大小是 7.6MB。debug stub 通过一些使用特定于操作系统的功能(在我们的例子中是 “ptrace”)和被调试进程以及通过远程协议的调试器通信。
+调试器是我们通过命令行交互的组件。也许如果你使用的是 IDE,那么在其上有另一个层可以通过_机器接口_与调试器进行通信。在目标机器上(可能与本机一样)有一个调试存根 ,理论上它是一个非常小的操作系统调试库的包装程序,它执行所有的低级调试任务,如在地址上设置断点。我说“在理论上”,因为如今调试存根变得越来越大。例如,我机器上的 LLDB 调试存根大小是 7.6MB。调试存根通过使用一些特定于操作系统的功能(在我们的例子中是 `ptrace`)和被调试进程以及通过远程协议的调试器通信。
-最常见的远程调试协议是 GDB 远程协议。这是一种基于文本的数据包格式,用于在调试器和 debug
- stub 之间传递命令和信息。我不会详细介绍它,但你可以在[这里][11]阅读你想知道的。如果你启动 LLDB 并执行命令 `log enable gdb-remote packets`,那么你将获得通过远程协议发送的所有数据包的跟踪。在 GDB 上,你可以用 `set remotelogfile ` 做同样的事情。
+最常见的远程调试协议是 GDB 远程协议。这是一种基于文本的数据包格式,用于在调试器和调试存根之间传递命令和信息。我不会详细介绍它,但你可以在[这里][11]进一步阅读。如果你启动 LLDB 并执行命令 `log enable gdb-remote packets`,那么你将获得通过远程协议发送的所有数据包的跟踪信息。在 GDB 上,你可以用 `set remotelogfile ` 做同样的事情。
-作为一个简单的例子,这是数据包设置断点:
+作为一个简单的例子,这是设置断点的数据包:
```
$Z0,400570,1#43
-
```
`$` 标记数据包的开始。`Z0` 是插入内存断点的命令。`400570` 和 `1` 是参数,其中前者是设置断点的地址,后者是特定目标的断点类型说明符。最后,`#43` 是校验值,以确保数据没有损坏。
GDB 远程协议非常易于扩展自定义数据包,这对于实现平台或语言特定的功能非常有用。
-* * *
-
### 共享库和动态加载支持
-调试器需要知道调试程序加载了哪些共享库,以便它可以设置断点,获取源代码级别的信息和符号等。除查找被动态链接的库之外,调试器还必须跟踪在运行时通过 `dlopen` 加载的库。为了打到这个目的,动态链接器维护一个 _交会结构体_。该结构体维护共享描述符的链表以及指向每当更新链表时调用的函数的指针。这个结构存储在 ELF 文件的 `.dynamic` 段中,在程序执行之前被初始化。
+调试器需要知道被调试程序加载了哪些共享库,以便它可以设置断点、获取源代码级别的信息和符号等。除查找被动态链接的库之外,调试器还必须跟踪在运行时通过 `dlopen` 加载的库。为了达到这个目的,动态链接器维护一个 _交汇结构体_。该结构体维护共享库描述符的链表,以及一个指向每当更新链表时调用的函数的指针。这个结构存储在 ELF 文件的 `.dynamic` 段中,在程序执行之前被初始化。
一个简单的跟踪算法:
-* 追踪程序在 ELF 头中查找程序的入口(或者可以使用存储在 `/proc//aux` 中的辅助向量)
-
+* 追踪程序在 ELF 头中查找程序的入口(或者可以使用存储在 `/proc//aux` 中的辅助向量)。
* 追踪程序在程序的入口处设置一个断点,并开始执行。
-
* 当到达断点时,通过在 ELF 文件中查找 `.dynamic` 的加载地址找到交汇结构体的地址。
-
* 检查交汇结构体以获取当前加载的库的列表。
-
-* 链接器更新函数上设置断点
-
-* 每当到达断点时,列表都会更新
-
+* 链接器更新函数上设置断点。
+* 每当到达断点时,列表都会更新。
* 追踪程序无限循环,继续执行程序并等待信号,直到追踪程序信号退出。
我给这些概念写了一个小例子,你可以在[这里][12]找到。如果有人有兴趣,我可以将来写得更详细一点。
-* * *
-
### 表达式计算
表达式计算是程序的一项功能,允许用户在调试程序时对原始源语言中的表达式进行计算。例如,在 LLDB 或 GDB 中,可以执行 `print foo()` 来调用 `foo` 函数并打印结果。
-根据表达的复杂程度,有几种不同的计算方法。如果表达式只是一个简单的标识符,那么调试器可以查看调试信息,找到变量并打印出该值,就像我们在本系列最后一部分中所做的那样。如果表达式有点复杂,则可能将代码编译成中间表达式 (IR) 并解释来获得结果。例如,对于某些表达式,LLDB 将使用 Clang 将表达式编译为 LLVM IR 并将其解释。如果表达式更复杂,或者需要调用某些函数,那么代码可能需要 JIT 到目标并在被调试者的地址空间中执行。这涉及到调用 `mmap` 来分配一些可执行内存,然后将编译的代码复制到该块并执行。LLDB 通过使用 LLVM 的 JIT 功能来实现。
+根据表达式的复杂程度,有几种不同的计算方法。如果表达式只是一个简单的标识符,那么调试器可以查看调试信息,找到该变量并打印出该值,就像我们在本系列最后一部分中所做的那样。如果表达式有点复杂,则可能将代码编译成中间表达式 (IR) 并解释来获得结果。例如,对于某些表达式,LLDB 将使用 Clang 将表达式编译为 LLVM IR 并将其解释。如果表达式更复杂,或者需要调用某些函数,那么代码可能需要 JIT 到目标并在被调试者的地址空间中执行。这涉及到调用 `mmap` 来分配一些可执行内存,然后将编译的代码复制到该块并执行。LLDB 通过使用 LLVM 的 JIT 功能来实现。
-如果你想更多地了解 JIT 编译,我强烈推荐[ Eli Bendersky 关于这个主题的文章][13]。
-
-* * *
+如果你想更多地了解 JIT 编译,我强烈推荐 [Eli Bendersky 关于这个主题的文章][13]。
### 多线程调试支持
-本系列展示的调试器仅支持单线程应用程序,但是为了调试大多数真实程序,多线程支持是非常需要的。支持这一点的最简单的方法是跟踪线程创建并解析 procfs 以获取所需的信息。
+本系列展示的调试器仅支持单线程应用程序,但是为了调试大多数真实程序,多线程支持是非常需要的。支持这一点的最简单的方法是跟踪线程的创建,并解析 procfs 以获取所需的信息。
Linux 线程库称为 `pthreads`。当调用 `pthread_create` 时,库会使用 `clone` 系统调用来创建一个新的线程,我们可以用 `ptrace` 跟踪这个系统调用(假设你的内核早于 2.5.46)。为此,你需要在连接到调试器之后设置一些 `ptrace` 选项:
@@ -97,7 +70,7 @@ Linux 线程库称为 `pthreads`。当调用 `pthread_create` 时,库会使用
ptrace(PTRACE_SETOPTIONS, m_pid, nullptr, PTRACE_O_TRACECLONE);
```
-现在当 `clone` 被调用时,该进程将收到我们的老朋友 `SIGTRAP` 发出信号。对于本系列中的调试器,你可以将一个例子添加到 `handle_sigtrap` 来处理新线程的创建:
+现在当 `clone` 被调用时,该进程将收到我们的老朋友 `SIGTRAP` 信号。对于本系列中的调试器,你可以将一个例子添加到 `handle_sigtrap` 来处理新线程的创建:
```
case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
@@ -115,32 +88,30 @@ GDB 使用 `libthread_db`,它提供了一堆帮助函数,这样你就不需
多线程支持中最复杂的部分是调试器中线程状态的建模,特别是如果你希望支持[不间断模式][15]或当你计算中涉及不止一个 CPU 的某种异构调试。
-* * *
-
### 最后!
-呼!这个系列花了很长时间才写完,但是我在这个过程中学到了很多东西,我希望它是有帮助的。如果你聊有关调试或本系列中的任何问题,请在 Twitter [@TartanLlama][16]或评论区联系我。如果你有想看到的其他任何调试主题,让我知道我或许会再发其他的文章。
+呼!这个系列花了很长时间才写完,但是我在这个过程中学到了很多东西,我希望它是有帮助的。如果你有关于调试或本系列中的任何问题,请在 Twitter [@TartanLlama][16]或评论区联系我。如果你有想看到的其他任何调试主题,让我知道我或许会再发其他的文章。
--------------------------------------------------------------------------------
via: https://blog.tartanllama.xyz/writing-a-linux-debugger-advanced-topics/
-作者:[Simon Brand ][a]
+作者:[Simon Brand][a]
译者:[geekpi](https://github.com/geekpi)
-校对:[校对者ID](https://github.com/校对者ID)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.twitter.com/TartanLlama
-[1]:https://blog.tartanllama.xyz/writing-a-linux-debugger-setup/
-[2]:https://blog.tartanllama.xyz/writing-a-linux-debugger-breakpoints/
-[3]:https://blog.tartanllama.xyz/writing-a-linux-debugger-registers/
-[4]:https://blog.tartanllama.xyz/writing-a-linux-debugger-elf-dwarf/
-[5]:https://blog.tartanllama.xyz/writing-a-linux-debugger-source-signal/
-[6]:https://blog.tartanllama.xyz/writing-a-linux-debugger-dwarf-step/
-[7]:https://blog.tartanllama.xyz/writing-a-linux-debugger-source-break/
-[8]:https://blog.tartanllama.xyz/writing-a-linux-debugger-unwinding/
-[9]:https://blog.tartanllama.xyz/writing-a-linux-debugger-variables/
+[1]:https://linux.cn/article-8626-1.html
+[2]:https://linux.cn/article-8645-1.html
+[3]:https://linux.cn/article-8663-1.html
+[4]:https://linux.cn/article-8719-1.html
+[5]:https://linux.cn/article-8812-1.html
+[6]:https://linux.cn/article-8813-1.html
+[7]:https://linux.cn/article-8890-1.html
+[8]:https://linux.cn/article-8930-1.html
+[9]:https://linux.cn/article-8936-1.html
[10]:https://blog.tartanllama.xyz/writing-a-linux-debugger-advanced-topics/
[11]:https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
[12]:https://github.com/TartanLlama/dltrace
diff --git a/translated/tech/20170818 Go vs .NET Core in terms of HTTP performance.md b/published/20170818 Go vs .NET Core in terms of HTTP performance.md
similarity index 83%
rename from translated/tech/20170818 Go vs .NET Core in terms of HTTP performance.md
rename to published/20170818 Go vs .NET Core in terms of HTTP performance.md
index ed12da0b10..14b8eb9258 100644
--- a/translated/tech/20170818 Go vs .NET Core in terms of HTTP performance.md
+++ b/published/20170818 Go vs .NET Core in terms of HTTP performance.md
@@ -1,4 +1,4 @@
-论 HTTP 性能,Go 与 .NET Core 谁争雌雄
+论 HTTP 性能,Go 与 .NET Core 一争雌雄
============================================================

@@ -9,25 +9,25 @@
因为是新出的,我不想立马就比较两个不同的东西,所以我耐心等待,想等发布更稳定的版本后再进行。
-本周一,微软[发布 .NET Core 2.0 版本][7],因此,我准备开始。您们认为呢?
+本周一(8 月 14 日),微软[发布 .NET Core 2.0 版本][7],因此,我准备开始。您们认为呢?
-如前面所提的,我们会比较他们相同的东西,比如应用程序、预期响应及运行时的稳定性,所以我们不会把像对 `JSON` 或者 `XML` 的编码、解码这些烦多的事情加入比较游戏中来,仅仅只会使用简单的文本消息。为了公平起见,我们会分别使用 Go 和 .NET Core 的[ MVC 架构模式][8]。
+如前面所提的,我们会比较它们相同的东西,比如应用程序、预期响应及运行时的稳定性,所以我们不会把像对 JSON 或者 XML 的编码、解码这些烦多的事情加入比较游戏中来,仅仅只会使用简单的文本消息。为了公平起见,我们会分别使用 Go 和 .NET Core 的 [MVC 架构模式][8]。
-### 先决条件
+### 参赛选手
-[Go][9] (或者 Golang): 是一种[快速增长][10]的开源编程语言,旨在构建出简单、快捷和稳定可靠的应用软件。
+[Go][9] (或称 Golang): 是一种[快速增长][10]的开源编程语言,旨在构建出简单、快捷和稳定可靠的应用软件。
用于支持 Go 语言的 MVC web 框架并不多,还好我们找到了 Iris ,可胜任此工作。
-[Iris][11]: 支持 Go 语言的快速、简单和高效的微型 Web 框架。它为您的下一代网站、API 或分布式应用程序奠定了精美的表现方式和易于使用的基础。
+[Iris][11]: 支持 Go 语言的快速、简单和高效的微型 Web 框架。它为您的下一代网站、API 或分布式应用程序奠定了精美的表现方式和易于使用的基础。
-[C#][12]: 是一种通用的,面向对象的编程语言。其开发团队由 [Anders Hejlsberg][13] 领导。
+[C#][12]: 是一种通用的、面向对象的编程语言。其开发团队由 [Anders Hejlsberg][13] 领导。
-[.NET Core][14]: 跨平台,可以在极少时间内开发出高性能的应用程序。
+[.NET Core][14]: 跨平台,可以在极少时间内开发出高性能的应用程序。
-从 [https://golang.org/dl][15] 下载 Go ,从 [https://www.microsoft.com/net/core][16] 下载 .NET Core。
+可从 [https://golang.org/dl][15] 下载 Go ,从 [https://www.microsoft.com/net/core][16] 下载 .NET Core。
-在下载和安装好这些软件后,还需要在 Go 端安装 Iris。安装很简单,仅仅只需要打开终端,然后执行如下语句:
+在下载和安装好这些软件后,还需要为 Go 安装 Iris。安装很简单,仅仅只需要打开终端,然后执行如下语句:
```
go get -u github.com/kataras/iris
@@ -37,31 +37,27 @@ go get -u github.com/kataras/iris
#### 硬件
-* 处理器: Intel(R) Core(TM) i7–4710HQ CPU @ 2.50GHz 2.50GHz
-
-* 内存: 8.00 GB
+* 处理器: Intel(R) Core(TM) i7–4710HQ CPU @ 2.50GHz 2.50GHz
+* 内存: 8.00 GB
#### 软件
-* 操作系统: 微软 Windows [10.0.15063 版本], 电源计划设置为“高性能”
-
-* HTTP 基准工具: [https://github.com/codesenberg/bombardier][1], 使用最新的 1.1 版本。
-
-* .NET Core: [https://www.microsoft.com/net/core][2], 使用最新的 2.0 版本。
-
-* Iris: [https://github.com/kataras/iris][3], 使用基于 [Go 1.8.3][4] 构建的新新 8.3 版本。
+* 操作系统: 微软 Windows [10.0.15063 版本], 电源计划设置为“高性能”
+* HTTP 基准工具: [https://github.com/codesenberg/bombardier][1], 使用最新的 1.1 版本。
+* .NET Core: [https://www.microsoft.com/net/core][2], 使用最新的 2.0 版本。
+* Iris: [https://github.com/kataras/iris][3], 使用基于 [Go 1.8.3][4] 构建的最新 8.3 版本。
两个应用程序都通过请求路径 “api/values/{id}” 返回文本“值”。
-.NET Core MVC
-
+##### .NET Core MVC

+
Logo 由 [Pablo Iglesias][5] 设计。
可以使用 `dotnet new webapi` 命令创建项目,其 `webapi` 模板会为您生成代码,代码包含 `GET` 请求方法的 `返回“值”`。
- _源代码_
+源代码:
```
using System;
@@ -165,8 +161,7 @@ namespace netcore_mvc.Controllers
}
```
-
- _运行 .NET Core web 服务项目_
+运行 .NET Core web 服务项目:
```
$ cd netcore-mvc
@@ -177,7 +172,7 @@ Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
```
- _运行和定位 HTTP 基准工具_
+运行和定位 HTTP 基准工具:
```
$ bombardier -c 125 -n 5000000 http://localhost:5000/api/values/5
@@ -193,13 +188,13 @@ Statistics Avg Stdev Max
Throughput: 8.91MB/s
```
-Iris MVC
-
+##### Iris MVC

+
Logo 由 [Santosh Anand][6] 设计。
- _源代码_
+源代码:
```
package main
@@ -217,7 +212,6 @@ func main() {
view raw
```
-
```
package controllers
@@ -242,8 +236,7 @@ func (vc *ValuesController) Put() {}
func (vc *ValuesController) Delete() {}
```
-
- _运行 Go web 服务项目_
+运行 Go web 服务项目:
```
$ cd iris-mvc
@@ -252,7 +245,7 @@ Now listening on: http://localhost:5000
Application started. Press CTRL+C to shut down.
```
- _运行和定位 HTTP 基准工具_
+运行和定位 HTTP 基准工具:
```
$ bombardier -c 125 -n 5000000 http://localhost:5000/api/values/5
@@ -275,55 +268,44 @@ Statistics Avg Stdev Max
#### 总结
* 完成 `5000000 个请求`的时间 - 越短越好。
-
* 请求次数/每秒 - 越大越好。
-
* 等待时间 — 越短越好。
-
* 吞吐量 — 越大越好。
-
* 内存使用 — 越小越好。
-
* LOC (代码行数) — 越少越好。
-.NET Core MVC 应用程序,使用 86 行代码,运行 2 分钟 8 秒,每秒接纳 39311.56 个请求,平均每秒有 3.19ms 等待,最大时到 229.73ms,内存使用大约为 126MB(不包括 dotnet 框架)。
+.NET Core MVC 应用程序,使用 86 行代码,运行 2 分钟 8 秒,每秒接纳 39311.56 个请求,平均 3.19ms 等待,最大时到 229.73ms,内存使用大约为 126MB(不包括 dotnet 框架)。
-Iris MVC 应用程序,使用 27 行代码,运行 47 秒,每秒接纳 105643.71 个请求,平均每秒有 1.18ms 等待,最大时到 22.01ms,内存使用大约为 12MB。
+Iris MVC 应用程序,使用 27 行代码,运行 47 秒,每秒接纳 105643.71 个请求,平均 1.18ms 等待,最大时到 22.01ms,内存使用大约为 12MB。
> 还有另外一个模板的基准,滚动到底部。
-2017 年 8 月 20 号更新
+**2017 年 8 月 20 号更新**
[Josh Clark] [24] 和 [Scott Hanselman] [25]在此 [tweet 评论] [26]上指出,.NET Core `Startup.cs` 文件中 `services.AddMvc();` 这行可以替换为 `services.AddMvcCore();`。我听从他们的意见,修改代码,重新运行基准,该文章的 .NET Core 应用程序的基准输出已经修改。
+@topdawgevh @shanselman 他们也在使用 `AddMvc()` 而不是 `AddMvcCore()` ...,难道都不包含中间件?
-@topdawgevh @shanselman 他们也在使用 AddMvc() 而不是 AddMvcCore() ...,难道都不包含中间件?
-
- — @clarkis117
+ — @clarkis117
@clarkis117 @topdawgevh Cool @MakisMaropoulos @ben_a_adams @davidfowl 我们来看看。认真学习下怎么使用更简单的性能默认值。
- — @shanselman
+ — @shanselman
@shanselman @clarkis117 @topdawgevh @ben_a_adams @davidfowl @shanselman @ben_a_adams @davidfowl 谢谢您们的反馈意见。我已经修改,更新了结果,没什么不同。对其它的建议,我非常欢迎。
- — @MakisMaropoulos
-
->它有点稍微的不同但相差不大(从 8.61MB/s 到 8.91MB/s)
-
+ — @MakisMaropoulos
+> 它有点稍微的不同但相差不大(从 8.61MB/s 到 8.91MB/s)
想要了解跟 `services.AddMvc()` 标准比较结果的,可以点击[这儿][27]。
-* * *
-
### 想再多了解点儿吗?
我们再制定一个基准,产生 `1000000 次请求`,这次会通过视图引擎由模板生成 `HTML` 页面。
#### .NET Core MVC 使用的模板
-
```
using System;
@@ -477,8 +459,7 @@ https://github.com/kataras/iris/tree/master/_benchmarks/netcore-mvc-templates
```
- _运行 .NET Core 服务项目_
-
+运行 .NET Core 服务项目:
```
$ cd netcore-mvc-templates
@@ -489,7 +470,7 @@ Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
```
- _运行和定位 HTTP 基准工具_
+运行 HTTP 基准工具:
```
Bombarding http://localhost:5000 with 1000000 requests using 125 connections
@@ -620,10 +601,7 @@ https://github.com/kataras/iris/tree/master/_benchmarks/iris-mvc-templates
```
-
-
- _运行 Go 服务项目_
-
+运行 Go 服务项目:
```
$ cd iris-mvc-templates
@@ -633,7 +611,7 @@ Application started. Press CTRL+C to shut down.
```
- _运行和定位 HTTP 基准工具_
+运行 HTTP 基准工具:
```
Bombarding http://localhost:5000 with 1000000 requests using 125 connections
@@ -648,22 +626,17 @@ Statistics Avg Stdev Max
Throughput: 192.51MB/s
```
-总结
+#### 总结
* 完成 `1000000 个请求`的时间 - 越短越好。
-
* 请求次数/每秒 - 越大越好。
-
* 等待时间 — 越短越好。
-
* 内存使用 — 越小越好。
-
* 吞吐量 — 越大越好。
+.NET Core MVC 模板应用程序,运行 1 分钟 20 秒,每秒接纳 11738.60 个请求,同时每秒生成 89.03M 页面,平均 10.10ms 等待,最大时到 1.97s,内存使用大约为 193MB(不包括 dotnet 框架)。
-.NET Core MVC 模板应用程序,运行 1 分钟 20 秒,每秒接纳 11738.60 个请求,同时每秒生成 89.03M 页面,平均每秒有 10.10ms 等待,最大时到 1.97s,内存使用大约为 193MB(不包括 dotnet 框架)。
-
-Iris MVC 模板应用程序,运行 37 秒,每秒接纳 26656.76 个请求,同时每秒生成 192.51M 页面,平均每秒有 1.18ms 等待,最大时到 22.52ms,内存使用大约为 17MB。
+Iris MVC 模板应用程序,运行 37 秒,每秒接纳 26656.76 个请求,同时每秒生成 192.51M 页面,平均 1.18ms 等待,最大时到 22.52ms,内存使用大约为 17MB。
### 接下来呢?
@@ -673,10 +646,6 @@ Iris MVC 模板应用程序,运行 37 秒,每秒接纳 26656.76 个请求,
我也需要亲自感谢下 [dev.to][34] 团队,感谢把我的这篇文章分享到他们的 Twitter 账户。
-论 HTTP 性能,Go 与 .NET Core 谁争雌雄 {作者:@MakisMaropoulos} https://t.co/IXL5LSpnjX
-
- — @ThePracticalDev
-
感谢大家真心反馈,玩得开心!
@@ -684,15 +653,15 @@ Iris MVC 模板应用程序,运行 37 秒,每秒接纳 26656.76 个请求,
很多人联系我,希望看到一个基于 .NET Core 的较低级别 Kestrel 的基准测试文章。
-因此我完成了,请点击下面的链接来了解 Kestrel 和 Iris 之间的性能差异,它还包含一个会话存储管理基准!
+因此我完成了,请点击下面的[链接][35]来了解 Kestrel 和 Iris 之间的性能差异,它还包含一个会话存储管理基准!
--------------------------------------------------------------------------------
via: https://hackernoon.com/go-vs-net-core-in-terms-of-http-performance-7535a61b67b8
-作者:[ Gerasimos Maropoulos][a]
+作者:[Gerasimos Maropoulos][a]
译者:[runningwater](https://github.com/runningwater)
-校对:[校对者ID](https://github.com/校对者ID)
+校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
@@ -731,3 +700,4 @@ via: https://hackernoon.com/go-vs-net-core-in-terms-of-http-performance-7535a61b
[32]:https://github.com/kataras/iris/tree/master/_benchmarks
[33]:https://github.com/kataras/iris
[34]:https://dev.to/kataras/go-vsnet-core-in-terms-of-http-performance
+[35]:https://medium.com/@kataras/iris-go-vs-net-core-kestrel-in-terms-of-http-performance-806195dc93d5
\ No newline at end of file
diff --git a/published/20170907 Seven things about Linux you may not have known so far.md b/published/20170907 Seven things about Linux you may not have known so far.md
new file mode 100644
index 0000000000..8ba018c076
--- /dev/null
+++ b/published/20170907 Seven things about Linux you may not have known so far.md
@@ -0,0 +1,104 @@
+关于 Linux 你可能不是非常了解的七件事
+===
+
+
+
+使用 Linux 最酷的事情之一就是随着时间的推移,你可以不断获得新的知识。每天,你都可能会遇到一个新的实用工具,或者只是一个不太熟悉的奇技淫巧,但是却非常有用。这些零碎的东西并不总是能够改变生活,但是却是专业知识的基础。
+
+即使是专家,也不可能事事皆知。无论你有多少经验,可能总会有更多的东西需要你去学习。所以,在这儿我列出了七件关于 Linux 你可能不知道的事情。
+
+### 一个查找命令历史的交互模式
+
+你可能对 `history` 命令非常熟悉,它会读取 bash 历史,然后以编号列表的方式输出到标准输出(`stdout`)。然而,如果你在 `curl` 命令的海洋里寻找一个特定的链接(URL),那么这个列表并不总是那么容易阅读的。
+
+你还可以有另一个选择,Linux 有一个交互式的反向搜索可以帮助你解决这个问题。你可以通过快捷键 `ctrl+r`启动交互模式,然后进入一个交互提示中,它将会根据你提供的字符串来向后搜索 bash 历史,你可以通过再次按下 `ctrl+r` 向后搜索更老的命令,或者按下 `ctrl+s` 向前搜索。
+
+注意,`ctrl+s` 有时会与 XON/XOFF 流控制冲突,即 XON/XOFF 流控制也会使用该快捷键。你可以通过运行 `stty -ixon` 命令来禁用该快捷键。在你的个人电脑上,这通常是有用的,但是在禁用前,确保你不需要 XON/XOFF 。
+
+### Cron 不是安排任务的唯一方式
+
+Cron 任务对于任何水平的系统管理员,无论是毫无经验的初学者,还是经验丰富的专家来说,都是非常有用的。但是,如果你需要安排一个一次性的任务,那么 `at` 命令为你提供了一个快捷的方式来创建任务,从而你不需要接触 crontab 。
+
+`at` 命令的运行方式是在后面紧跟着你想要运行任务的运行时间。时间是灵活的,因为它支持许多时间格式。包括下面这些例子:
+
+```
+at 12:00 PM September 30 2017
+at now + 1 hour
+at 9:00 AM tomorrow
+```
+
+当你以带参数的方式输入 `at` 命令以后,将会提示你该命令将在你的 Linux 系统上运行。这可能是一个备份脚本,一套维护任务,或者甚至是一个普通的 bash 命令。如果要结束任务,可以按 `ctrl+d` 。
+
+另外,你可以使用 `atq` 命令查看当前用户的所有任务,或者使用 `sudo atq` 查看所有用户的任务。它将会展示出所有排定好的任务,并且每个任务都伴有一个 ID 。如果你想取消一个排定好的任务,可以使用 `atrm` 命令,并且以任务 ID 作为参数。
+
+### 你可以按照功能搜索命令,而不仅仅是通过名字
+
+记住命令的名字非常困难,特别是对于初学者来说。幸运的是,Linux 附带了一个通过名字和描述来搜索 man 页面的工具。
+
+下次,如果你没有记住你想要使用的工具的名称,你可以尝试使用 `apropos` 命令加上你想要干的事情的描述。比如,`apropos build filesystem` 将会返回一系列名字和描述包括了 “build” 和 “filesystem” 单词的工具。
+
+`apropos` 命令接受一个或多个字符串作为参数,但同时它也有其他参数,比如你可以使用 `-r` 参数,从而通过正则表达式来搜索。
+
+### 一个允许你来管理系统版本的替代系统
+
+如果你曾进行过软件开发,你就会明白跨项目管理不同版本的语言的支持的重要性。许多 Linux 发行版都有工具可以来处理不同的内建版本。
+
+可执行文件比如 `java` 往往符号链接到目录 `/etc/alternatives` 下。反过来,该目录会将符号链接存储为二进制文件并提供一个管理这些链接的接口。Java 可能是替代系统最常管理的语言,但是,经过一些配置,它也可以作为其他应用程序替代品,比如 NVM 和 RVM (NVM 和 RVM 分别是 NodeJS 和 Ruby 的版本管理器)。
+
+在基于 Debian 的系统中,你可以使用 `update-alternatives` 命令创建和管理这些链接。在 CentOS 中,这个工具就叫做 `alternatives` 。通过更改你的 alternatives 文件中的链接,你便可以安装一个语言的多个版本,并且在不同的情况下使用不同的二进制。这个替代系统也提供了对任何你可能在命令行运行的程序的支持。
+
+### `shred` 命令是更加安全的删除文件方式
+
+我们大多数时候总是使用 `rm` 命令来删除文件。但是文件去哪儿了呢?真相是 `rm` 命令所做的事情并不是像你所想像的那样,它仅仅删除了文件系统和硬盘上的数据的硬链接。硬盘上的数据依旧存在,直到被另一个应用重写覆盖。对于非常敏感的数据来说,这会带来一个很大的安全隐患。
+
+`shred` 命令是 `rm` 命令的升级版。当你使用 `shred` 命令删除一个文件之后,文件中的数据会被多次随机覆写。甚至有一个选项可以在随机覆写之后对所有的数据进行清零。
+
+如果你想安全的删除一个文件并且以零覆盖,那么可以使用下面的命令:
+
+`shred -u -z [file name]`
+
+同时,你也可以使用 `-n` 选项和一个数字作为参数,从而指定在随机覆盖数据的时候迭代多少次。
+
+### 通过自动更正来避免输入很长的无效文件路径
+
+有多少次,你输入一个文件的绝对路径,然而却看到“没有该文件或目录”的消息。任何人都会明白输入一个很长的字符串的痛苦。幸运的是,有一个很简单的解决办法。
+
+内建的 `shopt` 命令允许你设置不同的选项来改变 shell 的行为。设置 `cdspell` 选项是避免输入文件路径时一个字母出错的头痛的一个简单方式。你可以通过运行 `shopt -s cdspell` 命令来启用该选项。启用该选项后,当你想要切换目录时,会自动更正为最匹配的目录。
+
+Shell 选项是节省时间的一个好方法(更不用说减少麻烦),此外还有许许多多的其他选项。如果想查看你的系统中所有选项的完整列表,可以运行不带参数的 `shopt` 命令。需要注意的是,这是 bash 的特性,如果你运行 zsh 或者其他可供选择的 shell,可能无法使用。
+
+### 通过子 shell 返回到当前目录
+
+如果你曾经配置过一个比较复杂的系统,那么你可能会发现你需要频繁的更换目录,从而很难跟踪你所在的位置。如果在运行完一个命令后自动返回到当前位置,不是很好吗?
+
+Linux 系统实际上提供了一个解决该问题的方法,并且非常简单。如果你想通过 `cd` 命令进入另一个目录完成一些任务,然后再返回当前工作目录,那么你可以将命令置于括号中。你可以在你的 Linux 系统上尝试下面这个命令。记住你当前的工作目录,然后运行:
+
+```
+(cd /etc && ls -a)
+```
+
+该命令会输出 `/etc` 目录的内容。现在,检查你的当前工作目录。它和执行该命令前的目录一样,而不是 `/etc` 目录。
+
+它是如何工作的呢?运行一个括号中的命令会创建一个子 shell 或一个当前 shell 进程的复刻副本。该子 shell 可以访问所有的父变量,反之则不行。所以请记住,你是在运行一个非常复杂的单行命令。
+
+在并行处理中经常使用子 shell ,但是在命令行中,它也能为你带来同样的力量,从而使你在浏览文件系统时更加容易。
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Phil Zona 是 Linux Academy 的技术作家。他编写了 AWS、Microsoft Azure 和 Linux 系统管理的指南和教程。他同时也管理着 Cloud Assessments 博客,该博客旨在帮助个人通过技术实现他们的事业目标。
+
+-----------------
+
+via: http://opensourceforu.com/2017/09/top-7-things-linux-may-not-known-far/
+
+作者:[PHIL ZONA][a]
+译者:[ucasFL](https://github.com/ucasFL)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://opensourceforu.com/author/phil-zona/
+[1]:http://opensourceforu.com/2017/09/top-7-things-linux-may-not-known-far/#disqus_thread
+[2]:http://opensourceforu.com/author/phil-zona/
diff --git a/sources/talk/20170421 A Window Into the Linux Desktop.md b/sources/talk/20170421 A Window Into the Linux Desktop.md
deleted file mode 100644
index 2091ead8e8..0000000000
--- a/sources/talk/20170421 A Window Into the Linux Desktop.md
+++ /dev/null
@@ -1,103 +0,0 @@
-traslating---geekp
-
-A Window Into the Linux Desktop
-============================================================
-
-
-
-
-
-"What can it do that Windows can't?"
-
-That is the first question many people ask when considering Linux for their desktop. While the open source philosophy that underpins Linux is a good enough draw for some, others want to know just how different its look, feel and functionality can get. To a degree, that depends on whether you choose a desktop environment or a window manager.
-
-If you want a desktop experience that is lightning fast and uncompromisingly efficient, foregoing the classic desktop environment for a window manager might be for you.
-
-### What's What
-
-"Desktop environment" is the technical term for a typical, full-featured desktop -- that is, the complete graphical layout of your system. Besides displaying your programs, the desktop environment includes accoutrements such as app launchers, menu panels and widgets.
-
-In Microsoft Windows, the desktop environment consists of, among other things, the Start menu, the taskbar of open applications and notification center, all the Windows programs that come bundled with the OS, and the frames enclosing open applications (with a dash, square and X in the upper right corner).
-
-There are many similarities in Linux.
-
-The Linux [Gnome][3] desktop environment, for instance, has a slightly different design, but it shares all of the Microsoft Windows basics -- from an app menu to a panel showing open applications, to a notification bar, to the windows framing programs.
-
-Window program frames rely on a component for drawing them and letting you move and resize them: It's called the "window manager." So, as they all have windows, every desktop environment includes a window manager.
-
-However, not every window manager is part of a desktop environment. You can run window managers by themselves, and there are reasons to consider doing just that.
-
-### Out of Your Environment
-
-For the purpose of this column, references to "window manager" refer to those that can stand alone. If you install a window manager on an existing Linux system, you can log out without shutting down, choose the new window manager on your login screen, and log back in.
-
-You might not want to do this without researching your window manager first, though, because you will be greeted by a blank screen and sparse status bar that may or may not be clickable.
-
-There typically is a straightforward way to bring up a terminal in a window manager, because that's how you edit its configuration file. There you will find key- and mouse-bindings to launch programs, at which point you actually can use your new setup.
-
-In the popular i3 window manager, for instance, you can launch a terminal by hitting the Super (i.e., Windows) key plus Enter -- or press Super plus D to bring up the app launcher. There you can type an app name and hit Enter to open it. All the existing apps can be found that way, and they will open to full screen once selected.
-
- [][4] (Click Image to Enlarge)
-
-i3 is also a tiling window manager, meaning it ensures that all windows expand to evenly fit the screen, neither overlapping nor wasting space. When a new window pops up, it reduces the existing windows, nudging them aside to make room. Users can toggle to open the next window either vertically or horizontally adjacent.
-
-### Features Can Be Friends or Foes
-
-Desktop environments have their advantages, of course. First and foremost, they provide a feature-rich, recognizable interface. Each has its signature style, but overall they provide unobtrusive default settings out of the box, which makes desktop environments ready to use right from the start.
-
-Another strong point is that desktop environments come with a constellation of programs and media codecs, allowing users to accomplish simple tasks immediately. Further, they include handy features like battery monitors, wireless widgets and system notifications.
-
-As comprehensive as desktop environments are, the large software base and user experience philosophy unique to each means there are limits on how far they can go. That means they are not always very configurable. With desktop environments that emphasize flashy looks, oftentimes what you see is what you get.
-
-Many desktop environments are notoriously heavy on system resources, so they're not friendly to lower-end hardware. Because of the visual effects running on them, there are more things that can go wrong, too. I once tried tweaking networking settings that were unrelated to the desktop environment I was running, and the whole thing crashed. When I started a window manager, I was able to change the settings.
-
-Those prioritizing security may want to avoid desktop environments, since more programs means greater attack surface -- that is, entry points where malicious actors can break in.
-
-However, if you want to give a desktop environment a try, XFCE is a good place to start, as its smaller software base trims some bloat, leaving less clutter behind if you don't stick with it.
-
-It's not the prettiest at first sight, but after downloading some GTK theme packs (every desktop environment serves up either these or Qt themes, and XFCE is in the GTK camp) and enabling them in the Appearance section of settings, you easily can touch it up. You can even shop around at this [centralized gallery][5] to find the theme you like best.
-
-### You Can Save a Lot of Time... if You Take the Time First
-
-If you'd like to see what you can do outside of a desktop environment, you'll find a window manager allows plenty of room to maneuver.
-
-More than anything, window managers are about customization. In fact, their customizability has spawned numerous galleries hosting a vibrant community of users whose palette of choice is a window manager.
-
-The modest resource needs of window managers make them ideal for lower specs, and since most window managers don't come with any programs, they allow users who appreciate modularity to add only those they want.
-
-Perhaps the most noticeable distinction from desktop environments is that window managers generally focus on efficiency by emphasizing mouse movements and keyboard hotkeys to open programs or launchers.
-
-Keyboard-driven window managers are especially streamlined, since you can bring up new windows, enter text or more keyboard commands, move them around, and close them again -- all without moving your hands from the home row. Once you acculturate to the design logic, you will be amazed at how quickly you can blaze through your tasks.
-
-In spite of the freedom they provide, window managers have their drawbacks. Most significantly, they are extremely bare-bones out of the box. Before you can make much use of one, you'll have to spend time reading your window manager's documentation for configuration syntax, and probably some more time getting the hang of said syntax.
-
-Although you will have some user programs if you switched from a desktop environment (the likeliest scenario), you also will start out missing familiar things like battery indicators and network widgets, and it will take some time to set up new ones.
-
-If you want to dive into window managers, i3 has [thorough documentation][6] and straightforward configuration syntax. The configuration file doesn't use any programming language -- it simply defines a variable-value pair on each line. Creating a hotkey is as easy as writing "bindsym", the key combination, and the action for that combination to launch.
-
-While window managers aren't for everyone, they offer a distinctive computing experience, and Linux is one of the few OSes that allows them. No matter which paradigm you ultimately go with, I hope this overview gives you enough information to feel confident about the choice you've made -- or confident enough to venture out of your familiar zone and see what else is available.
-
---------------------------------------------------------------------------------
-
-作者简介:
-
-**Jonathan Terrasi** has been an ECT News Network columnist since 2017\. His main interests are computer security (particularly with the Linux desktop), encryption, and analysis of politics and current affairs. He is a full-time freelance writer and musician. His background includes providing technical commentaries and analyses in articles published by the Chicago Committee to Defend the Bill of Rights.
-
-
------------
-
-via: http://www.linuxinsider.com/story/84473.html?rss=1
-
-作者:[ ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:
-[1]:http://www.linuxinsider.com/story/84473.html?rss=1#
-[2]:http://www.linuxinsider.com/perl/mailit/?id=84473
-[3]:http://en.wikipedia.org/wiki/GNOME
-[4]:http://www.linuxinsider.com/article_images/2017/84473_1200x750.jpg
-[5]:http://www.xfce-look.org/
-[6]:https://i3wm.org/docs/
diff --git a/sources/tech/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md b/sources/tech/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md
index f0944d8fe9..cb86edc19a 100644
--- a/sources/tech/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md
+++ b/sources/tech/20160611 How To Code Like The Top Programmers At NASA — 10 Critical Rules.md
@@ -1,3 +1,5 @@
+translating by penghuster
+
How To Code Like The Top Programmers At NASA — 10 Critical Rules
============================================================
diff --git a/sources/tech/20170403 Introducing Flashback an Internet mocking tool.md b/sources/tech/20170403 Introducing Flashback an Internet mocking tool.md
index 25e1328d9c..0cb55ef14f 100644
--- a/sources/tech/20170403 Introducing Flashback an Internet mocking tool.md
+++ b/sources/tech/20170403 Introducing Flashback an Internet mocking tool.md
@@ -1,3 +1,5 @@
+translating---geekpi
+
Introducing Flashback, an Internet mocking tool
============================================================
diff --git a/sources/tech/20170617 What all you need to know about HTML5.md b/sources/tech/20170617 What all you need to know about HTML5.md
deleted file mode 100644
index b5adee5fb2..0000000000
--- a/sources/tech/20170617 What all you need to know about HTML5.md
+++ /dev/null
@@ -1,272 +0,0 @@
-What all you need to know about HTML5
-============================================================
-
-
- __
-
- _HTML5, the fifth and current version of the HTML standard, is a markup language used to structure and present content on the World Wide Web. This article will help readers get acquainted with it._
-
-HTML5 has evolved through the cooperation between the W3C and the Web Hypertext Application Technology Working Group. It is a higher version of HTML, and its many new elements make your pages more semantic and dynamic. It was developed to provide a greater Web experience for everyone. HTML5 offers great features that make the Web more dynamic and interactive.
-
-The new features of HTML5 are:
-
-* New sets of tags such as and
-
-*