diff --git a/published/20171027 Share And Upload Files To Compatible Hosting Sites Automatically.md b/published/20171027 Share And Upload Files To Compatible Hosting Sites Automatically.md
new file mode 100644
index 0000000000..fd24ef3c36
--- /dev/null
+++ b/published/20171027 Share And Upload Files To Compatible Hosting Sites Automatically.md
@@ -0,0 +1,240 @@
+自动共享和上传文件到兼容的托管站点
+======
+
+
+
+前阵子我们写了一个关于 [Transfer.sh][1]的指南,它允许你使用命令行通过互联网来分享文件。今天,我们来看看另一种文件分享实用工具 Anypaste。这是一个基于文件类型自动共享和上传文件到兼容托管站点的简单脚本。你不需要去手动登录到托管站点来上传或分享你的文件。Anypaste 将会根据你想上传的文件的类型来**自动挑选合适的托管站点**。简单地说,照片将被上传到图像托管站点,视频被传到视频站点,代码被传到 pastebin。难道不是很酷的吗?Anypaste 是一个完全开源、免费、轻量的脚本,你可以通过命令行完成所有操作。因此,你不需要依靠那些臃肿的、需要消耗大量内存的 GUI 应用来上传和共享文件。
+
+### 安装
+
+正如我所说,这仅仅是一个脚本。所以不存在任何复杂的安装步骤。只需要将脚本下载后放置在你想要运行的位置(例如 `/usr/bin/`),并将其设置为可执行文件后就可以直接使用了。此外,你也可以通过下面的这两条命令来快速安装 Anypaste。
+
+```
+sudo curl -o /usr/bin/anypaste https://anypaste.xyz/sh
+sudo chmod +x /usr/bin/anypaste
+```
+
+就是这样简单。如果需要更新老的 Anypaste 版本,只需要用新的可执行文件覆写旧的即可。
+
+现在,让我们看看一些实例。
+
+### 配置
+
+Anypaste 开箱即用,并不需要特别的配置。默认的配置文件是 `~/.config/anypaste.conf`,这个文件在你第一次运行 Anypaste 时会自动创建。
+
+需要配置的选项只有 `ap_plugins`。Anypaste 使用插件系统上传文件。每个站点(的上传)都由一个特定的插件表示。你可以在 `anypaste.conf` 文件中的 `ap-plugins directive` 位置浏览可用的插件列表。
+
+```
+# List of plugins
+# If there are multiple compatible plugins, precedence is determined
+# by which one is listed first in this array
+ap_plugins=(
+# Videos/Gifs
+'sendvid' 'streamable' 'gfycat'
+# Images
+'tinyimg' 'vgyme'
+# Audio
+'instaudio'
+# Text
+'hastebin' 'ixio' 'sprunge'
+# Documents
+'docdroid'
+# Any file
+'jirafeau' 'fileio'
+)
+[...]
+```
+
+如果你要安装一个新的插件,将它添加进这个列表中就可以了。如果你想禁用一个默认插件,只需要将它从列表中移除即可。如果有多个兼容的插件,排列中的第一个会被选择,因此**顺序很重要**。
+
+### 用法
+
+上传一个简单的文件,例如 `test.png`,可以运行以下命令:
+
+```
+anypaste test.png
+```
+
+输出示例:
+
+```
+Current file: test.png
+Attempting to upload with plugin 'tinyimg'
+######################################################################## 100.0%
+
+Direct Link: https://tinyimg.io/i/Sa1zsjj.png
+
+Upload complete.
+All files processed. Have a nice day!
+```
+
+正如输出结果中所看到的,Anypaste 通过自动匹配图像文件 `test.png` 发现了兼容的托管站点(https://tinyimg.io),并将文件上传到了该站点。此外,Anypaste 也为我们提供了用于直接浏览/下载该文件的链接。
+
+不仅是 png 格式文件,你还可以上传任何其他图片格式的文件。例如,下面的命令将会上传 gif 格式文件:
+
+```
+$ anypaste file.gif
+Current file: file.gif
+Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
+You can set them in /home/sk/.config/anypaste.conf
+Attempting to upload with plugin 'gfycat'
+######################################################################## 100.0%
+Reminder: Gfycat needs time to encode. Your video will not appear right away.
+
+Link: https://gfycat.com/MisguidedQuaintBergerpicard
+Direct(ish) Link: https://thumbs.gfycat.com/MisguidedQuaintBergerpicard-size_restricted.gif
+
+Upload complete.
+All files processed. Have a nice day!
+```
+
+你可以将链接分享给你的家庭、朋友和同事们。下图是我刚刚将图片上传到 gfycat 网站的截图。
+
+![][3]
+
+也可以一次同时上传多个(相同格式或不同格式)文件。
+
+下面的例子提供参考,这里我会上传两个不同的文件,包含一个图片文件和一个视频文件:
+
+```
+anypaste image.png video.mp4
+```
+
+输出示例:
+
+```
+Current file: image.png
+Attempting to upload with plugin 'tinyimg'
+######################################################################## 100.0%
+
+Direct Link: https://tinyimg.io/i/au1PHpg.png
+
+Upload complete.
+Current file: video.mp4
+Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
+You can set them in /home/sk/.config/anypaste.conf
+Attempting to upload with plugin 'sendvid'
+######################################################################## 100.0%
+
+Link: http://sendvid.com/wwy7w96h
+Delete/Edit: http://sendvid.com/wwy7w96h?secret=39c0af2d-d8bf-4d3d-bad3-ad37432a40a5
+
+Upload complete.
+All files processed. Have a nice day!
+```
+
+Anypaste 针对两个文件自动发现了与之相兼容的托管站点并成功上传。
+
+正如你在上述用法介绍部分的例子中注意到的,Anypaste 会自动挑选最佳的插件。此外,你可以指定插件进行文件上传,这里提供一个上传到 gfycat 的案例,运行以下命令:
+
+```
+anypaste -p gfycat file.gif
+```
+
+输出示例:
+
+```
+Current file: file.gif
+Plugin 'streamable' is compatible, but missing config parameters: 'streamable_email' 'streamable_password'
+You can set them in /home/sk/.config/anypaste.conf
+Attempting to upload with plugin 'gfycat'
+######################################################################## 100.0%
+Reminder: Gfycat needs time to encode. Your video will not appear right away.
+
+Link: https://gfycat.com/GrayDifferentCollie
+Direct(ish) Link: https://thumbs.gfycat.com/GrayDifferentCollie-size_restricted.gif
+
+Upload complete.
+All files processed. Have a nice day!
+```
+
+如果要使用特定插件进行文件上传,可以通过以下命令绕过兼容性检查:
+
+```
+anypaste -fp gfycat file.gif
+```
+
+如果你发现在配置文件中忽略了特定的插件,你仍然可以强制 Anypaste 去使用特定的插件,只不过需要加上 `-xp` 参数。
+
+```
+anypaste -xp gfycat file.gif
+```
+
+如果想要以交互模式上传文件,可以在命令后加上 `-i` 标签:
+
+```
+$ anypaste -i file.gif
+Current file: file.gif
+Determine compatible plugins automatically? [Y/n] **n**
+The following plugins were found: 'sendvid' 'streamable' 'gfycat' 'tinyimg' 'vgyme' 'instaudio' 'hastebin' 'ixio' 'sprunge' 'docdroid' 'jirafeau' 'fileio'
+
+Enter the (partial) name of a plugin, or nothing for automatic selection
+**gfycat**
+Attempt to upload with plugin 'gfycat'? [Y/n] **y**
+Attempting to upload with plugin 'gfycat'
+######################################################################## 100.0%
+Reminder: Gfycat needs time to encode. Your video will not appear right away.
+
+Link: https://gfycat.com/WaryAshamedBlackbear
+Direct(ish) Link: https://thumbs.gfycat.com/WaryAshamedBlackbear-size_restricted.gif
+
+Upload complete.
+All files processed. Have a nice day!
+```
+
+正如你所见,Anypaste 首先询问了我是否需要自动确定插件。因为我不想自动寻找插件,所以我回复了 “No”。之后,Anypaste 列出了所有可选择的插件,并要求我从列表中选择一个。同样的,你可以上传和共享不同类型的文件,相关文件会被上传到相兼容的站点。
+
+无论你何时上传一个视频文件,Anypaste 都会将其上传到以下站点中的一个:
+
+ 1. sendvid
+ 2. streamable
+ 3. gfycat
+
+这里注意列表顺序,Anypaste 将首先将文件上传到 sendvid 站点,如果没有 sendvid 的插件可供使用,Anypaste 将会尝试顺序中的另外两个站点。当然你也可以通过更改配置文件来修改顺序。
+
+图像文件上传站点:
+
+ 1. tinyimg.io
+ 2. vgy.me
+
+音频文件上传站点:
+
+ 1. instaud
+
+文本文件上传站点:
+
+ 1. hastebin
+ 2. ix.io
+ 3. sprunge.us
+
+文档上传站点:
+
+ 1. docdroid
+
+其他任意类型的文件上传站点:
+
+ 1. jirafeau
+ 2. file.io
+
+上面列出来的部分站点一段特定的时间后会删除上传的内容,所以在上传和分享内容时应先明确这些站点的条款和条件。
+
+### 结论
+
+在我看来,识别文件并决定将其上传到何处的想法非常棒,而且开发者也以恰当的方式完美地实现了它。毫无疑问,Anypaste 对那些在互联网上需要频繁分享文件的人们非常有用,我希望你也能这么觉得。
+
+这就是今天的全部内容,后面会有越来越多的好东西分享给大家。再见啦!
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/anypaste-share-upload-files-compatible-hosting-sites-automatically/
+
+作者:[SK][a]
+译者:[lixin555](https://github.com/lixin555)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.ostechnix.com/author/sk/
+[1]:https://www.ostechnix.com/easy-fast-way-share-files-internet-command-line/
+[2]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[3]:http://www.ostechnix.com/wp-content/uploads/2017/10/gfycat.png
diff --git a/published/20180207 23 open source audio-visual production tools.md b/published/20180207 23 open source audio-visual production tools.md
new file mode 100644
index 0000000000..3df9236b46
--- /dev/null
+++ b/published/20180207 23 open source audio-visual production tools.md
@@ -0,0 +1,289 @@
+23 款开源的声音、视觉生产工具
+======
+
+> 无论你是要进行音频、图形、视频、动画还是它们的任意组合,都有一个开源工具可以帮助你产生专业水平的结果。
+
+
+
+“开源”在云基础设施、网站托管、嵌入式设备和其他领域已经建立的相当完善。很少数人知道开源在生产专业级的声音视觉素材上也是一个不错的选择。
+
+作为一名产品经理(有时候也是市场支持),我为终端用户提供很多内容:文档、文章、视频教学,甚至是展台物料、白皮书、采访等等。我找到了很多可以帮我制作音频、视频、排版、截屏的开源软件。人们选择开源软件而不是专有软件的[原因][1]有很多,而我也为以下人群编制了一份开源音视频工具清单:
+
+* 想要入坑 GNU/Linux,但需要在原来的操作系统上慢慢从使用跨平台软件开始
+* 热爱开源,但对音视频开源软件所知甚少,不知道该如何选择
+* 想要为创造力充电而探索新的工具,并且不想使用其他人使用过的方法工具
+* 存在某些其他的原因使用开源音视频解决方案(如果是你,不妨在评论里分享一下)
+
+幸运的是,存在着很多开源的音视频创作软件,也存在着很多硬件来支持这些应用。本文清单里的所有软件都符合以下标准:
+
+* 跨平台
+* 开源(软件和驱动)
+* 稳定
+* 积极维护
+* 良好的文档与技术支持
+
+我将清单中的解决方案划分为图形、音频、视频和动画。注意,本文中提到的应用程序并不完全等同于一些有名的私有软件,它们需要花时间来学习,并且可能需要改变你的工作流程,但是学习新的工具能够让体验全新的创造方式。
+
+### 图形
+
+我制作过很多出版和网站使用的图形,包括徽标、横幅、视频节目、草图。这里是一些我用过的开源应用,也包括一同使用的硬件。
+
+#### 软件
+
+**1、[Inkscape][2]**(矢量图)
+
+Inkscape 是一款不错的矢量图编辑器,用来制作 RGB 颜色空间下的 SVG 和 PDF 文件。(它可以制作 CMYK 图像,但不是主要用途)它是为 web 应用制作 SVG 格式的地图和图表的人的救命稻草。你不仅可以使用集成的 XML 编辑器打开文件,也可以用它查看对象的所有参数。但有一个缺点:它在 Mac 上的优化不是很好。有很多样例,可以看[Inkscape 画廊][3]。
+
+**2、[GIMP][4]**(图片编辑器)
+
+GIMP 是我最喜欢的图片编辑程序,它包括了色彩调整、裁剪和拉伸,并且(尤其是)对于网页使用的文件大小进行了优化(很多使用 Photoshop 的同事让我帮他们做这最后一步)。你也可以从头制作并绘制一张图片,但 GIMP 并不是我最喜欢用来做这件事的工具。在 [GIMP Artists on DevianArt][5] 上查看众多的样例。
+
+**3、[Krita][6]**(数字绘画)
+
+当你桌子上摆着一个漂亮的 Wacom 数位板,你肯定想试试真正的数字绘画应用。Krita 就是你创作漂亮插画所需要的工具。在 [Krita 画廊][7] 里看看我说的东西吧。
+
+**4、[Scribus][8]**(桌面印刷系统)
+
+你可以使用 Scribus 来创建一个完整的文档,或者只是把用 Inkscape 或 Libre Office 制作的 PDF 从 RGB 转换到 CMYK。有一个功能我非常喜欢:你可以试着模拟视觉障碍人士使用 Scribus 时的体验。当我发送 PDF 文件给商业印刷公司时全指望 Scribus。尽管出版社可能使用像 InDesign 这样的私有软件创建文档,但如果你用 Scribus 正确的完成一份文档,那么打印时就不会出现任何问题。免费建议:第一次发送文件给印刷公司时,不要告诉印刷公司创建该文档所使用的软件。你可以在 [Scribus 教程][9]中寻找创建文档的例子。
+
+**5、[RawTherapee][10]**(RAW 图像开发工具)
+
+RawTherapee 是我所知道唯一跨平台可替代 Lightroom 的软件。你可以将相机调整到 RAW 模式,然后使用 RawTherapee 来修图。它提供了非常强大的引擎和对图片没有破坏的编辑器。例如,可以见 [Raw Therapee 截图][11]。
+
+**6、[LibreOffice Draw][12]**(桌面印刷系统)
+
+尽管你可能认为 LibraOffice Draw 不是一款专业的桌面印刷解决方案,但它仍然能够在很多情况下帮助你。例如,制作其他人(尽管是那些不懂图形软件的人)以后可以修改的白皮书、图表或海报。它不仅方便使用,而且当创建有趣的文档时也是 Impress 或 PowerPoint 的绝佳替代软件。
+
+#### 图形硬件
+
+**绘图板**
+
+[Wacom][13] 数位板(和兼容设备)通常支持所有的操作系统。
+
+**颜色校正**
+
+颜色校正产品通常可用于所有操作系统,也包括了 GNU/Linux。Datacolor 生产的 [Spyder][14] 在所有平台上都有应用程序的支持。
+
+**扫描仪和打印机**
+
+图形艺术家需要输出(无论是打印还是电子版)的颜色是精确的。但是真正跨平台的设备,以及所有平台都易于安装的驱动,并不像你想的那样普遍。你的最佳选择是兼容 TWAIN 的扫描仪和兼容 Postscript 的打印机。以我的经验,Epson 和 Xerox 的专业级扫描仪和打印机更不容易出现驱动问题,并且它们通常也是开箱即用,拥有漂亮精确的颜色。
+
+### 音频
+
+有许多可供音乐家、视频制作者、游戏制作者、音乐出版商等等人群选择的开源音频软件。这里有一些我曾经用来进行内容创作与声音录制时所使用的软件。
+
+#### 软件
+
+**7、[Ardour][15]**(数字音频录制)
+
+对录音与编辑来说,最专业级的工具选择当然是唾手可得的 Ardour。听起来很棒,它的混音部分非常的完整灵活,能够提供给你喜欢的插件,并且易于回放、编辑、对比修改。我经常用它进行声音录制和视频混音。要找出一些使用 Ardour 录制好的音乐并不容易,因为音乐家们很少表明他们使用的软件。然而,你可以查看它的[截图][16]和一些特性来了解它的功能。
+
+(如果你在寻求一种声音制作方面的“模拟体验”,你可以试试 [Harrison Mixbus][17],它并不是一个开源项目,但是高度基于 Ardour,拥有模拟显示的终端。我非常喜欢用它进行工作,我的客户也喜欢用它制作的声音。Mixbus 也是跨平台的)
+
+**8、[Audacity][18]** (声音编辑)
+
+Audacity 属于“瑞士军刀”级的声音制作软件。它并不完美,但你几乎可以用它做所有的事情。加上非常易于使用,任何人都能在几分钟之内上手。像 Ardour 一样,很难找到一份归功于 Audacity 的作品,但你可以从这些[截图][19]中了解如何使用它。
+
+**9、[LMMS][20]** (音乐制作)
+
+LMMS,设计作为 FL Studio 的替代品,也许使用并不那么广泛,但它非常完整并易于使用。你可以使用自己最喜欢的插件,使用“钢琴键”编辑乐器,使用步定序器播放鼓点,混合音轨...几乎能做任何事情。在我没有时间为音乐家录音的时候我就使用它为视频创建声音片段。查看[最好的 LMMS][21] 榜单来看看一些例子。
+
+**10、[Mixxx][22]** (DJ,音乐混音)
+
+如果你需要强大的混音和播放 DJ 软件,Mixxx 就可以满足你的需求。它与大多数 MIDI 控制器、唱片、专用声卡所兼容。你可以用它管理音乐库、添加音效,做一些有趣的事情。查看它的[功能][23]来了解它是如何工作的。
+
+#### 音频接口硬件
+
+尽管你可以使用任何一个计算机的声卡录制音频,但要录制的很好,就需要一个音频接口——一个录制高质量音频输入的专用的外部声卡。对于跨平台兼容性来说,大多数“兼容 USB”和“兼容 iOS”的音频接口设备应该都能录制 MIDI 或其他音频。下面是一些我用过的一些有名气的跨平台设备。
+
+**[Behringer U-PHORIA UMC22][24]**
+
+UMC22 是你可以考虑的最便宜的选择。但它的前置放大器噪音太大,音腔质量也比较低。
+
+**[Presonus AudioBox USB][25]**
+
+AudioBox USB 是第一个兼容 USB(因此也跨平台)的录音系统。它非常的耐用,经常在二手市场也能见到。
+
+**[Focusrite Scarlett][26]**
+
+Scarlett 在我看来是目前最高质量的跨平台声卡。不同种类的设备可以涵盖 2-18 个输入/输出端口。你可以在二手市场找到它的最初版本,而最新的第二代具有更好的前置放大器与规格。[2i2][27] 型号是我经常使用的那一款。
+
+**[Arturia AudioFuse][28]**
+
+AudioFuse 几乎可以让你接入任何设备,从麦克风到黑胶唱片机再到各种数字输入设备。它具有优质的声音与良好的设计,也是我目前用的最多的一款设备。它是跨平台的,但目前配置软件还不能在 GUN/Linux 上使用。即使我把它从 Windows 电脑上断开,它仍然保留着我的配置。但是讲真,Arturia,劳烦认真考虑做一个 Linux 的软件。
+
+#### MIDI 控制器
+
+MIDI 控制器是一种乐器——例如电子琴、鼓垫等等。可以让你控制音乐软件或者硬件。现有的大多数 USB MIDI 控制器都跨平台并兼容主流的录音编辑软件。基于网页的教程可以帮你对不同的软件进行配置。尽管找到有关在 GNU/Linux 上配置的信息可能比较困难,但它们仍然是可以使用的。我用过许多 Akai 和 M-Audio 设备,没有任何问题。在买乐器之前最好先试一下,至少去听一下它们的音质或体验一下按键触感。
+
+#### 音频编解码器
+
+音频编解码器压缩或解压数字音频,用尽可能小的文件大小获得最佳质量的声音。幸运的是,用于收听或流媒体播放的编解码器恰好是开源的:[FLAC][29]。[Ogg Vorbis][30] 是另一个值得了解的开源音频编解码器;在相同的比特率下比 MP3 好的多。如果你需要输出不同的音频格式,我建议通常存档最好质量的音频,然后再压缩成特定的版本。
+
+### 视频
+
+视频对于品牌的传播是影响巨大的。即使你不是一个视频专家,学习一些基础的东西也是非常明智的。
+
+#### 软件
+
+**11、[VLC][31]** (视频播放器与转换器)
+
+最初是为流媒体而开发的,VLC 现在因能够在所有设备上读取所有的视频格式被人们熟知。它非常的实用,例如,你可以使用它将视频转换成其他编解码格式或容器,也可以用来恢复破损的视频。
+
+**12、[OpenShot][32]** (视频编辑)
+
+OpenShot 是一个简单的软件,但它却可以制作出很好的效果,尤其是在短视频上。(在编辑或改善音质方面有一定的限制,但它也能够完成)我非常喜欢它的移动、拉伸、裁剪工具;用它创建视频的开头或结尾,导出之后使用更复杂的编辑器进行编辑,非常的完美。你可以在 OpenShot 的网站上看这些[例子][33](并获取更多信息)。
+
+**13、[Shotcut][34]** (视频编辑)
+
+我认为 Shotcut 是比 OpenShot 更完整一些的工具——它在你的操作系统上比起其他较为基础的编辑器更具有竞争力,并且它支持 4K 分辨率,具有专业的解码器。尝试一下,我相信你会爱上它的。你可以在这些[视频教程][35]里看一些范例。
+
+**14、[Blender Velvets][36]** (视频编辑、合成、特效)
+
+尽管这一章节不是本文的学习重点,但 Blender Velvets 是你能找到的最强大的解决方案之一。它是由一些视频创作者所制作的一系列扩展工具和脚本的合集,是通过 Blender 3D 制作软件转换成的 2D 视频编辑器。尽管它的复杂度意味着不是我的首选视频编辑器,但你仍可以在 YouTube 和其他网站上找到它的教程,并且一旦你学习了它,你就能通过它做任何事情。观看这个[视频教程][37]来了解它的功能与运作方式。
+
+**15、[Natron][38]**(合成)
+
+我不使用 Natron,但我听说它广受好评。它是 Adobe After Effects 的替代品,但运作方式并不同。想了解更多可以观看一些视频教程,比如这些 Natron 的 [YouTube 频道][39]。
+
+**16、[OBS][40]** (实时编辑、录制、流媒体)
+
+Open Broadcaster Software(OBS)是一个领先的在 YouTube 或 Twitch 上进行现场录制或现场直播电子竞技、电视游戏的解决方案。我经常使用它记录用户的屏幕、会议和聚会。要获取更多信息,查看我曾经在 Opensource.com 上写的关于录制现场汇报的教程,[第一部分:选择你的设备][42]和[第二部分:软件安装][43]。
+
+#### 视频硬件
+
+结论先行:你需要一个强大的工作站以及快速的硬盘和更新的软件和驱动。
+
+**图形处理单元(GPU)**
+
+一部分包含在清单里的软件比如 Blender 和 Shotcut 使用 OpenGL 和硬件加速,这些都高度依赖 GPU。我建议你使用可以负担起的最强大的 GPU。我所使用过的 AMD 和 Nvidia 都有着良好的体验,这取决于使用的平台。不要忘记安装最新的驱动。
+
+**硬盘**
+
+大体上来说,越快越大的硬盘,对视频越好。不要忘记在软件里配置好正确的路径。
+
+**视频录制硬件**
+
+* [Blackmagic Design][44]: Blackmagic 提供了非常好的、专业级的视频录制和回放硬件。驱动支持 Mac、Windows 和 GNU/Linux(但不是所有的发行版)
+* [Epiphan][45]: 在 Epiphan 的专业级 USB 视频录制设备中有一款新型产品,它适用于 HDMI 和高分辨率的屏幕。然而,你也可以在二手市场找到旧的 VGA 设备,因为他们还在继续为 GNU/Linux 和 Windows 上提供专用的驱动程序。
+
+#### 视频编解码
+
+不幸的是,使用开源的编解码器仍然很困难。例如,许多相机使用专有的编解码器录制 H.264 的视频和 AC3 的音频,组成称为 AVCHD 的格式。因此,我们必须务实,尽可能利用现有资源。
+
+好消息是内容产业正在步向开源的编解码器来避免一些费用,并使用开源标准。对于出版和流媒体,[谷歌][46]的 [WebM][46] 便是一款优秀的开源编解码器,并且大多数视频编辑器可以导入这种格式。同样地, [GoPro][47]的超高分辨率和 360° 视频编解码器 [Cineform][47] 现在也进行了开源。希望更多的设备和供应商将会在不久之后使用它。
+
+### 2D 和 3D 动画
+
+动画不是我的专业领域,因此我问了从事于动画内容生产的朋友一些建议并加入到清单中,他的工作包含儿童电影和连续剧。
+
+#### 软件
+
+**17、[Blender][48]** (3D 模型和渲染)
+
+Blender 是顶级的开源跨平台 3D 建模和渲染软件。你可以直接在 Blender 中完成整个项目的工作,或者使用它为电影或视频创建 3D 效果。你能够在网上找到许多视频教程,因此即使它不是一个简单的软件,但也非常容易上手。Blender 是一个非常活跃的项目,经常还会制作一些微电影来展示他们的技术。你可以在 [Blender Open Movies][49] 上观看。
+
+**18、[Synfig Studio][50]** (2D 动画)
+
+第一次用 Synfig 时,它让我想起了那个不错的 Macromedia 老式 Flash 编辑器。在那之后,它已经发展成一个全功能的 2D 动画工作室。你可以使用它制作宣传故事、商业广告、演示、开场或结尾动画以及视频中的转场,或者甚至用它制作全动画的电影。见 [Synfig 作品集][51]。
+
+**19、[TupiTube][52]** (定格 2D 动画)
+
+使用 TupiTube 是一个学习基本 2D 动画的极好方法。你可以将一系列绘画或其他图片转换成一个视频或者创建一个 GIF 循环动画。它是一个相当简单的软件,但非常完整。查看 [TupiTude 的 YouTube][53] 频道获取一些教程和范例。
+
+#### 硬件
+
+动画制作使用与图形设计相同的硬件,因此查看第一小结中的硬件清单获取一些建议。
+
+有一点需要注意:你要用一个强大的 GPU 来进行 3D 建模和渲染。选择可能有些限制,因为这取决于你使用的平台或电脑制造商,但是不要忘记安装最新的驱动。谨慎选择你的显卡:它们非常昂贵,并且在大型的 3D 项目中至关重要,尤其是在渲染步骤中。
+
+### Linux 上的选择
+
+如果你是 GUN/Linux 用户,那么我为你提供了更多不错的选择。它们并不是完全跨平台的,但部分拥有 Windows 版本,还有一些可以在 Mac 上使用 Macports 安装。
+
+**20、[Kdenlive][54]** (视频编辑)
+
+伴随着最新版本的发布(几个月之前),Kdenlive 成为了我最喜欢的视频编辑器,尤其是当我在 Linux 机器上处理一些长视频的时候。如果你经常使用流行的非线性视频编辑器,Kdenlive(全称是 KDE 非线性视频编辑器)对你来说将非常简单。它拥有很棒的视频和音频特效,强大的细节处理能力。并且在 BSD 和 MacOS(尽管它对准的是 GNU/Linux)都能使用,还有望移植到 Windows 上。
+
+**21、[Darktable][55]** (RAW 图像开发)
+
+Darktable 是一款由摄影师制作的非常完整的 DxO PhotoLab 替代品。一些研究型项目使用它当做开发平台并测试一些图像处理算法。它是一个非常活跃的项目,我已经等不及的见到它的跨平台版本了。
+
+**22、[MyPaint][56]** (digital painting数字绘画)
+
+MyPaint 就像数字绘画领域的 light table(LCTT 译注:集成开发环境)。它在 Wacom 设备上表现良好,并且它的笔刷引擎尤其值得赞赏,因此 GIMP 开发人员正在密切的关注它。
+
+**23、[Shutter][57]** (桌面截图)
+
+当我写这篇教程的时候,我使用了许多截图来进行展示。我最喜欢的 GNU/Linux 截图工具就是 Shutter。事实上,我都找不到在 Windows 或 Mac 上能与之抗衡的一些功能。有一点小遗憾:我很期待 Shutter 在将来能够增加新的功能来创建几秒动态的 GIF 截图。
+
+我希望这些足以说服你开源软件是一种非常卓越且可行的音视频内容生产解决方案。如果你正在使用其他开源软件,或者对于使用跨平台软件和硬件进行音视频项目有好的建议,请在评论中分享你的观点。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/2/open-source-audio-visual-production-tools
+
+作者:[Antoine Thomas][a]
+译者:[LuuMing](https://github.com/LuuMing)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://opensource.com/users/ttoine
+[1]:https://opensource.com/resources/what-open-source
+[2]:https://inkscape.org/
+[3]:https://inkscape.org/en/gallery/
+[4]:https://www.gimp.org/
+[5]:https://gimp-artists.deviantart.com/gallery/
+[6]:https://krita.org/
+[7]:https://krita.org/en/features/gallery/
+[8]:https://www.scribus.net/
+[9]:https://www.scribus.net/category/made-with-scribus/
+[10]:http://rawtherapee.com/
+[11]:http://rawtherapee.com/blog/screenshots
+[12]:https://www.libreoffice.org/discover/draw/
+[13]:http://www.wacom.com/en-us
+[14]:http://www.datacolor.com/photography-design/product-overview/#workflow_2
+[15]:https://www.ardour.org/
+[16]:http://ardour.org/features.html
+[17]:http://harrisonconsoles.com/site/mixbus.html
+[18]:http://www.audacityteam.org/
+[19]:http://www.audacityteam.org/about/screenshots/
+[20]:https://lmms.io/
+[21]:https://lmms.io/showcase/
+[22]:https://www.mixxx.org/
+[23]:https://www.mixxx.org/features/
+[24]:http://www.musictri.be/Categories/Behringer/Computer-Audio/Interfaces/UMC22/p/P0AUX
+[25]:https://www.presonus.com/products/audiobox-usb
+[26]:https://us.focusrite.com/scarlett-range
+[27]:https://us.focusrite.com/usb-audio-interfaces/scarlett-2i2
+[28]:https://www.arturia.com/products/audio/audiofuse/overview
+[29]:https://en.wikipedia.org/wiki/FLAC
+[30]:https://xiph.org/vorbis/
+[31]:https://www.videolan.org/
+[32]:https://www.openshot.org/
+[33]:https://www.openshot.org/videos/
+[34]:https://shotcut.com/
+[35]:https://shotcut.org/tutorials/
+[36]:http://blendervelvets.org/
+[37]:http://blendervelvets.org/video-tutorial-new-functions-for-the-blender-velvets/
+[38]:https://natron.fr/
+[39]:https://www.youtube.com/playlist?list=PL2n8LbT_b5IeMwi3AIzqG4Rbg8y7d6Amk
+[40]:https://obsproject.com/
+[41]:https://opensource.com/article/17/7/obs-studio-pro-level-streaming
+[42]:https://opensource.com/article/17/9/equipment-recording-presentations
+[43]:https://opensource.com/article/17/9/equipment-setup-live-presentations
+[44]:https://www.blackmagicdesign.com/
+[45]:https://www.epiphan.com/
+[46]:https://www.webmproject.org/
+[47]:https://fr.gopro.com/news/gopro-open-sources-the-cineform-codec
+[48]:https://www.blender.org/
+[49]:https://www.blender.org/about/projects/
+[50]:https://www.synfig.org/
+[51]:https://www.synfig.org/#portfolio
+[52]:https://maefloresta.com/
+[53]:https://www.youtube.com/channel/UCBavSfmoZDnqZalr52QZRDw
+[54]:https://kdenlive.org/
+[55]:https://www.darktable.org/
+[56]:http://mypaint.org/
+[57]:http://shutter-project.org/
diff --git a/published/20190602 How to Install LEMP (Linux, Nginx, MariaDB, PHP) on Fedora 30 Server.md b/published/20190602 How to Install LEMP (Linux, Nginx, MariaDB, PHP) on Fedora 30 Server.md
new file mode 100644
index 0000000000..c3c7d5d3bf
--- /dev/null
+++ b/published/20190602 How to Install LEMP (Linux, Nginx, MariaDB, PHP) on Fedora 30 Server.md
@@ -0,0 +1,196 @@
+[#]: collector: (lujun9972)
+[#]: translator: (robsean)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11631-1.html)
+[#]: subject: (How to Install LEMP (Linux, Nginx, MariaDB, PHP) on Fedora 30 Server)
+[#]: via: (https://www.linuxtechi.com/install-lemp-stack-fedora-30-server/)
+[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
+
+如何在 Fedora 30 Server 上安装 LEMP(Linux、Nginx、MariaDB、PHP)
+======
+
+在这篇文章中,我们将看看如何在 Fedora 30 Server 上安装 **LEMP** 。LEMP 代表:
+
+ * L -> Linux
+ * E -> Nginx
+ * M -> Maria DB
+ * P -> PHP
+
+我假设 [Fedora 30][1] 已经安装在你的电脑系统上。
+
+
+
+LEMP 是一组强大的软件设置集合,它安装在一个 Linux 服务器上以帮助使用流行的开发平台来构建网站,LEMP 是 LAMP 的一个变种,在其中不是 Apache ,而是使用 EngineX(Nginx),此外,使用 MariaDB 代替 MySQL。这篇入门指南是一个安装 Nginx、Maria DB 和 PHP 的独立指南的作品集合。
+
+### 在 Fedora 30 Server 上安装 Nginx、PHP 7.3 和 PHP-FPM
+
+让我们看看如何在 Fedora 30 Server 上安装 Nginx 和 PHP 以及 PHP FPM。
+
+#### 步骤 1) 切换到 root 用户
+
+在系统上安装 Nginx 的第一步是切换到 root 用户。使用下面的命令:
+
+```
+root@linuxtechi ~]$ sudo -i
+[sudo] password for pkumar:
+[root@linuxtechi ~]#
+```
+
+#### 步骤 2) 使用 dnf 命令安装 Nginx、PHP 7.3 和 PHP FPM
+
+使用下面的 `dnf` 命令安装 Nginx:
+
+```
+[root@linuxtechi ~]# dnf install nginx php php-fpm php-common -y
+```
+
+#### 步骤 3) 安装额外的 PHP 模块
+
+PHP 的默认安装仅自带基本模块和最需要的模块,如果你需要额外的模块,像 PHP 支持的 GD、XML、命令行接口、Zend OPCache 功能等等,你总是能够选择你的软件包,并一次性安装所有的东西。查看下面的示例命令:
+
+```
+[root@linuxtechi ~]# sudo dnf install php-opcache php-pecl-apcu php-cli php-pear php-pdo php-pecl-mongodb php-pecl-redis php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml -y
+```
+
+#### 步骤 4) 开始 & 启用 Nginx 和 PHP-fpm 服务
+
+使用下面的命令来开始并启用 Nginx 服务:
+
+```
+[root@linuxtechi ~]# systemctl start nginx && systemctl enable nginx
+Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
+[root@linuxtechi ~]#
+```
+
+使用下面的命令来开始并启用 PHP-FPM 服务:
+
+```
+[root@linuxtechi ~]# systemctl start php-fpm && systemctl enable php-fpm
+Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service.
+[root@linuxtechi ~]#
+```
+
+#### 步骤 5) 核实 Nginx (Web 服务) 和 PHP 安装
+
+注意:假使操作系统防火墙是启用的,并运行在你的 Fedora 30 系统上,那么使用下面的命令来准许 80 和 443 端口:
+
+```
+[root@linuxtechi ~]# firewall-cmd --permanent --add-service=http
+success
+[root@linuxtechi ~]#
+[root@linuxtechi ~]# firewall-cmd --permanent --add-service=https
+success
+[root@linuxtechi ~]# firewall-cmd --reload
+success
+[root@linuxtechi ~]#
+```
+
+打开网页浏览器,输入下面的 URL: http:// 。
+
+![Test-Page-HTTP-Server-Fedora-30][4]
+
+上面的屏幕证实 Nginx 已经成功地安装。
+
+现在,让我们核实 PHP 安装,使用下面的命令创建一个测试 php 页(`info.php`):
+
+```
+[root@linuxtechi ~]# echo "" > /usr/share/nginx/html/info.php
+[root@linuxtechi ~]#
+```
+
+在网页浏览器中输入下面的 URL, http:///info.php
+
+![Php-info-page-fedora30][6]
+
+上面的页面验证 PHP 7.3.5 已经被成功地安装。现在,让我们安装 MariaDB 数据库服务器。
+
+### 在 Fedora 30 上安装 MariaDB
+
+MariaDB 是 MySQL 数据库的一个极好的替代品,因为它的工作方式与 MySQL 非常类似,并且兼容性也与 MySQL 一致。让我们看看在 Fedora 30 Server 上安装 MariaDB 的步骤。
+
+#### 步骤 1) 切换到 root 用户
+
+在系统上安装 MariaDB 的第一步是切换到 root 用户,或者你可以使用有 root 权限的本地用户。使用下面的命令:
+
+```
+[root@linuxtechi ~]# sudo -i
+[root@linuxtechi ~]#
+```
+
+#### 步骤 2) 使用 dnf 命令安装 MariaDB(10.3)的最新版本
+
+在 Fedora 30 Server 上使用下面的命令来安装 MariaDB:
+
+```
+[root@linuxtechi ~]# dnf install mariadb-server -y
+```
+
+#### 步骤 3) 开启并启用 MariaDB 服务
+
+在步骤 2 中成功地安装 MariaDB 后,接下来的步骤是开启 MariaDB 服务。使用下面的命令:
+
+```
+[root@linuxtechi ~]# systemctl start mariadb.service ; systemctl enable mariadb.service
+```
+
+#### 步骤 4) 保护安装好的 MariaDB
+
+当我们安装 MariaDB 服务器时,因为默认情况下没有 root 密码,在数据库中也会创建匿名用户。因此,要保护安装好的 MariaDB,运行下面的 `mysql_secure_installation` 命令:
+
+```
+[root@linuxtechi ~]# mysql_secure_installation
+```
+
+接下来你将被提示一些问题,仅回答下面展示的问题:
+
+![Secure-MariaDB-Installation-Part1][7]
+
+![Secure-MariaDB-Installation-Part2][8]
+
+#### 步骤 5) 测试 MariaDB 安装
+
+在你安装后,你总是能够测试是否 MariaDB 被成功地安装在 Fedora 30 Server 上。使用下面的命令:
+
+```
+[root@linuxtechi ~]# mysql -u root -p
+Enter password:
+```
+
+接下来,你将被提示一个密码。输入在保护安装好的 MariaDB 期间你设置的密码,接下来你可以看到 MariaDB 欢迎屏幕。
+
+```
+Welcome to the MariaDB monitor. Commands end with ; or \g.
+Your MariaDB connection id is 17
+Server version: 10.3.12-MariaDB MariaDB Server
+
+Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
+
+Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
+
+MariaDB [(none)]>
+```
+
+最后,我们已经在你的 Fedora 30 Server 上成功地完成安装 LEMP(Linux、Nginx、MariaDB 和 PHP)的所有工作。请在下面的反馈部分发布你的评论和建议,我们将尽快在后面回应。
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxtechi.com/install-lemp-stack-fedora-30-server/
+
+作者:[Pradeep Kumar][a]
+选题:[lujun9972][b]
+译者:[robsean](https://github.com/robsean)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.linuxtechi.com/author/pradeep/
+[b]: https://github.com/lujun9972
+[1]: https://www.linuxtechi.com/fedora-30-workstation-installation-guide/
+[2]: https://www.linuxtechi.com/wp-content/uploads/2019/06/LEMP-Stack-Fedora30.jpg
+[3]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Test-Page-HTTP-Server-Fedora-30-1024x732.jpg
+[4]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Test-Page-HTTP-Server-Fedora-30.jpg
+[5]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Php-info-page-fedora30-1024x732.jpg
+[6]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Php-info-page-fedora30.jpg
+[7]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Secure-MariaDB-Installation-Part1.jpg
+[8]: https://www.linuxtechi.com/wp-content/uploads/2019/06/Secure-MariaDB-Installation-Part2.jpg
diff --git a/published/20190725 24 sysadmin job interview questions you should know.md b/published/20190725 24 sysadmin job interview questions you should know.md
new file mode 100644
index 0000000000..b2b6f9b812
--- /dev/null
+++ b/published/20190725 24 sysadmin job interview questions you should know.md
@@ -0,0 +1,235 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11673-1.html)
+[#]: subject: (24 sysadmin job interview questions you should know)
+[#]: via: (https://opensource.com/article/19/7/sysadmin-job-interview-questions)
+[#]: author: (DirectedSoul https://opensource.com/users/directedsoul)
+
+24 个必知必会的系统管理员面试问题
+======
+
+> 即将进行系统管理员工作面试吗?阅读本文,了解你可能会遇到的一些问题以及可能的答案。
+
+
+
+作为一个经常与计算机打交道的极客,在硕士毕业后在 IT 行业选择我的职业是很自然的选择。因此,我认为走上系统管理员之路是正确的路径。在我的职业生涯中,我对求职面试过程非常熟悉。现在来看一下对该职位的预期、职业发展道路,以及一系列常见面试问题及我的回答。
+
+### 系统管理员的典型任务和职责
+
+组织需要了解系统工作原理的人员,以确保数据安全并保持服务平稳运行。你可能会问:“等等,是不是系统管理员还能做更多的事情?”
+
+你是对的。现在,一般来说,让我们看一下典型的系统管理员的日常任务。根据公司的需求和人员的技能水平,系统管理员的任务从管理台式机、笔记本电脑、网络和服务器到设计组织的 IT 策略不等。有时,系统管理员甚至负责购买和订购新的 IT 设备。
+
+那些寻求系统管理工作以作为其职业发展道路的人可能会发现,由于 IT 领域的快速变化是不可避免的,因此难以保持其技能和知识的最新状态。所有人都会想到的下一个自然而然的问题是 IT 专业人员如何掌握最新的更新和技能。
+
+### 简单的问题
+
+这是你将遇到的一些最基本的问题,以及我的答案:
+
+**1、你在 \*nix 服务器上登录后键入的前五个命令是什么?**
+
+> * `lsblk` 以查看所有的块设备信息
+> * `who` 查看谁登录到服务器
+> * `top`,以了解服务器上正在运行的进程
+> * `df -khT` 以查看服务器上可用的磁盘容量
+> * `netstat` 以查看哪些 TCP 网络连接处于活动状态
+
+**2、如何使进程在后台运行,这样做的好处是什么?**
+
+> 你可以通过在命令末尾添加特殊字符 `&` 来使进程在后台运行。通常,执行时间太长并且不需要用户交互的应用程序可以放到后台,以便我们可以在终端中继续工作。([引文][2])
+
+**3、以 root 用户身份运行这些命令是好事还是坏事?**
+
+> 由于两个主要问题,以 root 身份运行(任何命令)是不好的。第一个是*风险*。当你以 **root** 身份登录时,无法避免你由于粗心大意而犯错。如果你尝试以带有潜在危害的方式更改系统,则需要使用 `sudo`,它会引入一个暂停(在你输入密码时),以确保你不会犯错。
+>
+> 第二个原因是*安全*。如果你不知道管理员用户的登录信息,则系统更难被攻击。拥有 root 的访问权限意味着你已经能够进行管理员身份下的一半工作任务。
+
+**4、`rm` 和 `rm -rf` 有什么区别?**
+
+> `rm` 命令本身仅删除指明的文件(而不删除目录)。使用 `-rf` 标志,你添加了两个附加功能:`-r`(或等价的 `-R`、`--recursive`)标志可以递归删除目录的内容,包括隐藏的文件和子目录;而 `-f`(或 `--force`)标志使 `rm` 忽略不存在的文件,并且从不提示你进行确认。
+
+**5、有一个大小约为 15GB 的 `Compress.tgz` 文件。你如何列出其内容,以及如何仅提取出特定文件?**
+
+> 要列出文件的内容:
+>
+> `tar tf archive.tgz`
+>
+> 要提取特定文件:
+>
+> `tar xf archive.tgz filename`
+
+### 有点难度的问题
+
+这是你可能会遇到的一些较难的问题,以及我的答案:
+
+**6、什么是 RAID?什么是 RAID 0、RAID 1、RAID 5、RAID 6 和 RAID 10?**
+
+> RAID(廉价磁盘冗余阵列)是一种用于提高数据存储性能和/或可靠性的技术。RAID 级别为:
+>
+> * RAID 0:也称为磁盘条带化,这是一种分解文件并将数据分布在 RAID 组中所有磁盘驱动器上的技术。它没有防止磁盘失败的保障。([引文][3])
+> * RAID 1:一种流行的磁盘子系统,通过在两个驱动器上写入相同的数据来提高安全性。RAID 1 被称为*镜像*,它不会提高写入性能,但读取性能可能会提高到每个磁盘性能的总和。另外,如果一个驱动器发生故障,则会使用第二个驱动器,发生故障的驱动器需要手动更换。更换后,RAID 控制器会将可工作的驱动器的内容复制到新驱动器上。
+> * RAID 5:一种磁盘子系统,可通过计算奇偶校验数据来提高安全性和提高速度。RAID 5 通过跨三个或更多驱动器交错数据(条带化)来实现此目的。在单个驱动器发生故障时,后续读取可以从分布式奇偶校验计算出,从而不会丢失任何数据。
+> * RAID 6:通过添加另一个奇偶校验块来扩展 RAID 5。此级别至少需要四个磁盘,并且可以在任何两个并发磁盘故障的情况下继续执行读/写操作。RAID 6 不会对读取操作造成性能损失,但由于与奇偶校验计算相关的开销,因此确实会对写入操作造成性能损失。
+> * RAID 10:RAID 10 也称为 RAID 1 + 0,它结合了磁盘镜像和磁盘条带化功能来保护数据。它至少需要四个磁盘,并且跨镜像对对数据进行条带化。只要每个镜像对中的一个磁盘起作用,就可以检索数据。如果同一镜像对中的两个磁盘发生故障,则所有数据将丢失,因为带区集中没有奇偶校验。([引文][4])
+
+**7、`ping` 命令使用哪个端口?**
+
+> `ping` 命令使用 ICMP。具体来说,它使用 ICMP 回显请求和应答包。
+>
+> ICMP 不使用 UDP 或 TCP 通信服务:相反,它使用原始的 IP 通信服务。这意味着,ICMP 消息直接承载在 IP 数据报数据字段中。
+
+**8、路由器和网关之间有什么区别?什么是默认网关?**
+
+> *路由器*描述的是一种通用技术功能(第 3 层转发)或用于该目的的硬件设备,而*网关*描述的是本地网段的功能(提供到其他地方的连接性)。你还可以说“将路由器设置为网关”。另一个术语是“跳”,它描述了子网之间的转发。
+>
+> 术语*默认网关*表示局域网上的路由器,它的责任是作为对局域网外部的计算机通信的第一个联系点。
+
+**9、解释一下 Linux 的引导过程。**
+
+> BIOS -> 主引导记录(MBR) -> GRUB -> 内核 -> 初始化 -> 运行级
+
+**10、服务器启动时如何检查错误消息?**
+
+> 内核消息始终存储在 kmsg 缓冲区中,可通过 `dmesg` 命令查看。
+>
+> 引导出现的问题和错误要求系统管理员结合某些特定命令来查看某些重要文件,这些文件不同版本的 Linux 处理方式不同:
+>
+> * `/var/log/boot.log` 是系统引导日志,其中包含系统引导过程中展开的所有内容。
+> * `/var/log/messages` 存储全局系统消息,包括系统引导期间记录的消息。
+> * `/var/log/dmesg` 包含内核环形缓冲区信息。
+
+**11、符号链接和硬链接有什么区别?**
+
+> *符号链接*(*软链接*)实际是到原始文件的链接,而*硬链接*是原始文件的镜像副本。如果删除原始文件,则该软链接就没有用了,因为它指向的文件不存在了。如果是硬链接,则完全相反。如果删除原始文件,则硬链接仍然包含原始文件中的数据。([引文][5])
+
+**12、如何更改内核参数?你可能需要调整哪些内核选项?**
+
+> 要在类 Unix 系统中设置内核参数,请首先编辑文件 `/etc/sysctl.conf`。进行更改后,保存文件并运行 `sysctl -p` 命令。此命令使更改永久生效,而无需重新启动计算机
+
+**13、解释一下 `/proc` 文件系统。**
+
+> `/proc` 文件系统是虚拟的,并提供有关内核、硬件和正在运行的进程的详细信息。由于 `/proc` 包含虚拟文件,因此称为“虚拟文件系统”。这些虚拟文件具有独特性。其中大多数显示为零字节。
+>
+> 虚拟文件,例如 `/proc/interrupts`、`/proc/meminfo`、`/proc/mounts` 和 `/proc/partitions`,提供了系统硬件的最新信息。其他诸如 `/proc/filesystems` 和 `/proc/sys` 目录提供系统配置信息和接口。
+
+**14、如何在没有密码的情况下以其他用户身份运行脚本?**
+
+> 例如,如果你可以编辑 sudoers 文件(例如 `/private/etc/sudoers`),则可以使用 `visudo` 添加以下[内容][2]:
+>
+> `user1 ALL =(user2)NOPASSWD:/opt/scripts/bin/generate.sh`
+
+**15、什么是 UID 0 toor 帐户?是被入侵了么?**
+
+> `toor` 用户是备用的超级用户帐户,其中 `toor` 是 `root` 反向拼写。它预期与非标准 shell 一起使用,因此 `root` 的默认 shell 不需要更改。
+>
+> 此用途很重要。这些 shell 不是基本发行版的一部分,而是从 ports 或软件包安装的,它们安装在 `/usr/local/bin` 中,默认情况下,位于其他文件系统上。如果 root 的 shell 位于 `/usr/local/bin` 中,并且未挂载包含 `/usr/local/bin` 的文件系统,则 root 无法登录以解决问题,并且系统管理员必须重新启动进入单用户模式来输入 shell 程序的路径。
+
+### 更难的问题
+
+这是你可能会遇到的甚至更困难的问题:
+
+**16、`tracert` 如何工作,使用什么协议?**
+
+> 命令 `tracert`(或 `traceroute`,具体取决于操作系统)使你可以准确地看到在连接到最终目的地的连接链条中所触及的路由器。如果你遇到无法连接或无法 `ping` 通最终目的地的问题,则可以使用 `tracert` 来帮助你确定连接链在何处停止。([引文][6])
+>
+> 通过此信息,你可以联系正确的人;无论是你自己的防火墙、ISP、目的地的 ISP 还是中间的某个位置。 `tracert` 命令像 `ping` 一样使用 ICMP 协议,但也可以使用 TCP 三步握手的第一步来发送 SYN 请求以进行响应。
+
+**17、使用 `chroot` 的主要优点是什么?我们何时以及为什么使用它?在 chroot 环境中,`mount /dev`、`mount /proc` 和 `mount /sys` 命令的作用是什么?**
+
+> chroot 环境的优点是文件系统与物理主机是隔离的,因为 chroot 在文件系统内部有一个单独的文件系统。区别在于 `chroot` 使用新创建的根目录(`/`)作为其根目录。
+>
+> chroot 监狱可让你将进程及其子进程与系统其余部分隔离。它仅应用于不以 root 身份运行的进程,因为 root 用户可以轻松地脱离监狱。
+>
+> 该思路是创建一个目录树,在其中复制或链接运行该进程所需的所有系统文件。然后,你可以使用 `chroot()` 系统调用来告诉它根目录现在位于此新树的基点上,然后启动在该 chroot 环境中运行的进程。由于该命令因此而无法引用修改后的根目录之外的路径,因此它无法在这些位置上执行恶意操作(读取、写入等)。([引文][7])
+
+**18、如何保护你的系统免遭黑客攻击?**
+
+> 遵循最低特权原则和这些做法:
+>
+> * 使用公钥加密,它可提供出色的安全性。
+> * 增强密码复杂性。
+> * 了解为什么要对上述规则设置例外。
+> * 定期检查你的例外情况。
+> * 让具体的人对失败负责。(它使你保持警惕。)([引文][8])
+
+**19、什么是 LVM,使用 LVM 有什么好处?**
+
+> LVM(逻辑卷管理)是一种存储设备管理技术,该技术使用户能够合并和抽象化组件存储设备的物理布局,从而可以更轻松、灵活地进行管理。使用设备映射器的 Linux 内核框架,当前迭代(LVM2)可用于将现有存储设备收集到组中,并根据需要从组合的空间分配逻辑单元。
+
+**20、什么是粘性端口?**
+
+> 粘性端口是网络管理员最好的朋友,也是最头痛的事情之一。它们允许你设置网络,以便通过将交换机上的每个端口锁定到特定的 MAC 地址,仅允许一台(或你指定的数字)计算机在该端口上进行连接。
+
+**21、解释一下端口转发?**
+
+> 尝试与安全的网络内部的系统进行通信时,从外部进行通信可能非常困难,这是很显然的。因此,在路由器本身或其他连接管理设备中使用端口转发表可以使特定流量自动转发到特定目的地。例如,如果你的网络上运行着一台 Web 服务器,并且想从外部授予对该服务器的访问权限,则可以将端口转发设置为该服务器上的端口 80。这意味着在 Web 浏览器中输入你的(外网)IP 地址的任何人都将立即连接到该服务器的网站。
+>
+> 请注意,通常不建议允许从你的网络外部直接访问服务器。
+
+**22、对于 IDS,误报和漏报是什么?**
+
+> 当入侵检测系统(IDS)设备为实际上没有发生的入侵生成警报时,这是误报(假阳性)。如果设备未生成任何警报,而入侵实际上已发生,则为漏报(假阴性)。
+
+**23、解释一下 `:(){ :|:& };:`,如果已经登录系统,如何停止此代码?**
+
+> 这是一枚复刻炸弹。它分解如下:
+>
+> * `:()` 定义了函数,以 `:` 作为函数名,并且空括号表示它不接受任何参数。
+> * `{}` 是函数定义的开始和结束。
+> * `:|:` 将函数 `:` 的副本加载到内存中,并将其输出通过管道传递给函数 `:` 的另一个副本,该副本也必须加载到内存中。
+> * `&` 使前一个命令行成为后台进程,因此即使父进程被自动杀死,子进程也不会被杀死。
+> * `:` 执行该函数,因此连锁反应开始。
+>
+> 保护多用户系统的最佳方法是使用特权访问管理(PAM)来限制用户可以使用的进程数。
+>
+> 复刻炸弹的最大问题是它发起了太多进程。因此,如果你已经登录系统,我们有两种尝试解决此问题的方法。一种选择是执行一个 `SIGSTOP` 命令来停止进程,例如:
+>
+> `killall -STOP -u user1`
+>
+> 如果由于占用了所有进程而无法使用命令行,则必须使用 `exec` 强制其运行:
+>
+> `exec killall -STOP -u user1`
+>
+> 对于复刻炸弹,最好的选择是防患于未然。
+
+**24、什么是 OOM 杀手,它如何决定首先杀死哪个进程?**
+
+> 如果内存被进程彻底耗尽,可能会威胁到系统的稳定性,那么内存不足(OOM)杀手就登场了。
+>
+> OOM 杀手首先必须选择要杀死的最佳进程。*最佳*在这里指的是在被杀死时将释放最大内存的进程,并且对系统来说最不重要。主要目标是杀死最少数量的进程,以最大程度地减少造成的损害,同时最大化释放的内存量。
+>
+> 为了实现此目标,内核为每个进程维护一个 `oom_score`。你可以在 `/proc` 文件系统中的 `pid` 目录下的看到每个进程的 `oom_score`:
+>
+> `$ cat /proc/10292/oom_score`
+>
+> 任何进程的 `oom_score` 值越高,在内存不足的情况下被 OOM 杀手杀死的可能性就越高。([引文][9])
+
+### 总结
+
+系统管理人员的薪水[差别很大][10],有些网站上说年薪在 70,000 到 100,000 美元之间,具体取决于地点、组织的规模以及你的教育水平以及多年的工作经验。系统管理的职业道路最终归结为你对使用服务器和解决那些酷问题的兴趣。现在,我要说,继续前进,实现你的梦想之路吧!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/7/sysadmin-job-interview-questions
+
+作者:[DirectedSoul][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/directedsoul
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_HowToFish_520x292.png?itok=DHbdxv6H (Question and answer.)
+[2]: https://github.com/trimstray/test-your-sysadmin-skills
+[3]: https://www.waytoeasylearn.com/2016/05/netapp-filer-tutorial.html
+[4]: https://searchstorage.techtarget.com/definition/RAID-10-redundant-array-of-independent-disks
+[5]: https://www.answers.com/Q/What_is_hard_link_and_soft_link_in_Linux
+[6]: https://www.wisdomjobs.com/e-university/network-administrator-interview-questions.html
+[7]: https://unix.stackexchange.com/questions/105/chroot-jail-what-is-it-and-how-do-i-use-it
+[8]: https://serverfault.com/questions/391370/how-to-prevent-zero-day-attacks
+[9]: https://unix.stackexchange.com/a/153586/8369
+[10]: https://blog.netwrix.com/2018/07/23/systems-administrator-salary-in-2018-how-much-can-you-earn/
diff --git a/published/20190827 curl exercises.md b/published/20190827 curl exercises.md
new file mode 100644
index 0000000000..35984c6e31
--- /dev/null
+++ b/published/20190827 curl exercises.md
@@ -0,0 +1,82 @@
+[#]: collector: (lujun9972)
+[#]: translator: (hanwckf)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11648-1.html)
+[#]: subject: (curl exercises)
+[#]: via: (https://jvns.ca/blog/2019/08/27/curl-exercises/)
+[#]: author: (Julia Evans https://jvns.ca/)
+
+21 个 curl 命令练习
+======
+
+最近,我对人们如何学习新事物感兴趣。我正在读 Kathy Sierra 的好书《[Badass: Making Users Awesome][1]》,它探讨了有关“刻意练习”的想法。这个想法是,你找到一个可以用三节 45 分钟课程内能够学会的小技能,并专注于学习这项小技能。因此,作为一项练习,我尝试考虑一项能够在三节 45 分钟课程内学会的计算机技能。
+
+我认为使用 `curl` 构造 HTTP 请求也许就是这样的一项技能,所以这里有一些 `curl` 练习作为实验!
+
+### 什么是 curl ?
+
+`curl` 是用于构造 HTTP 请求的命令行工具。我喜欢使用 `curl`,因为它能够很轻松地测试服务器或 API 的行为是否符合预期,但是刚开始接触它的时候会让你感到一些困惑!
+
+下面是一幅解释 `curl` 常用命令行参数的漫画 (在我的 [Bite Size Networking][2] 杂志的第 6 页)。
+
+
+
+### 熟能生巧
+
+对于任何命令行工具,我认为熟练使用是很有帮助的,能够做到只输入必要的命令真是太好了。例如,最近我在测试 Gumroad API,我只需要输入:
+
+```
+curl https://api.gumroad.com/v2/sales \
+ -d "access_token=" \
+ -X GET -d "before=2016-09-03"
+```
+
+就能从命令行中得到想要的结果。
+
+### 21 个 curl 练习
+
+这些练习是用来理解如何使用 `curl` 构造不同种类的 HTTP 请求的,它们是故意有点重复的,基本上包含了我需要 `curl` 做的任何事情。
+
+为了简单起见,我们将对 https://httpbin.org 发起一系列 HTTP 请求,httpbin 接受 HTTP 请求,然后在响应中回显你所发起的 HTTP 请求。
+
+ 1. 请求
+ 2. 请求 ,它将会解析你发起的请求,并且在响应中回显。`curl` 默认发起的是 GET 请求
+ 3. 向 发起 GET 请求
+ 4. 向 发起 GET 请求,但是这次需要添加一些查询参数(设置 `value=panda`)
+ 5. 请求 Google 的 `robots.txt` 文件 ([www.google.com/robots.txt][3])
+ 6. 向 发起 GET 请求,并且设置请求头为 `User-Agent: elephant`
+ 7. 向 发起 DELETE 请求
+ 8. 请求 并获取响应头信息
+ 9. 向 发起请求体为 JSON `{"value": "panda"}` 的 POST 请求
+ 10. 发起与上一次相同的 POST 请求,但是这次要把请求头中的 `Content-Type` 字段设置成 `application/json`(因为 POST 请求需要一个与请求体相匹配的 `Content-Type` 请求头字段)。查看响应体中的 `json` 字段,对比上一次得到的响应体
+ 11. 向 发起 GET 请求,并且在请求头中设置 `Accept-Encoding: gzip`(将会发生什么?为什么会这样?)
+ 12. 将一些 JSON 放在文件中,然后向 发起请求体为该文件的 POST 请求
+ 13. 设置请求头为 `Accept: image/png` 并且向 发起请求,将输出保存为 PNG 文件,然后使用图片浏览器打开。尝试使用不同的 `Accept:` 字段去请求此 URL
+ 14. 向 发起 PUT 请求
+ 15. 请求 并保存为文件,然后使用你的图片编辑器打开这个文件
+ 16. 请求 ,你将会得到空的响应。让 `curl` 显示出响应头信息,并尝试找出响应内容为空的原因
+ 17. 向 发起任意的请求,同时设置一些无意义的请求头(例如:`panda: elephant`)
+ 18. 请求 和 ,然后再次请求它们并且让 curl 显示响应头信息
+ 19. 请求 并且设置用户名和密码(使用 `-u username:password`)
+ 20. 设置 `Accept-Language: es-ES` 的请求头用以下载 Twitter 的西班牙语主页 ()
+ 21. 使用 `curl` 向 Stripe API 发起请求(请查看 了解如何使用,他们会给你一个测试用的 API key)。尝试向 发起相同的请求
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://jvns.ca/blog/2019/08/27/curl-exercises/
+
+作者:[Julia Evans][a]
+选题:[lujun9972][b]
+译者:[hanwckf](https://github.com/hanwckf)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://jvns.ca/
+[b]: https://github.com/lujun9972
+[1]: https://www.amazon.com/Badass-Making-Awesome-Kathy-Sierra/dp/1491919019
+[2]: https://wizardzines.com/zines/bite-size-networking
+[3]: http://www.google.com/robots.txt
diff --git a/published/20190927 5 tips for GNU Debugger.md b/published/20190927 5 tips for GNU Debugger.md
new file mode 100644
index 0000000000..9bb6329a4b
--- /dev/null
+++ b/published/20190927 5 tips for GNU Debugger.md
@@ -0,0 +1,220 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11647-1.html)
+[#]: subject: (5 tips for GNU Debugger)
+[#]: via: (https://opensource.com/article/19/9/tips-gnu-debugger)
+[#]: author: (Tim Waugh https://opensource.com/users/twaugh)
+
+5 个鲜为人知 GNU 调试器(GDB)技巧
+======
+
+> 了解如何使用 gdb 的一些鲜为人知的功能来检查和修复代码。
+
+
+
+[GNU 调试器][2](`gdb`)是一种宝贵的工具,可用于在开发程序时检查正在运行的进程并解决问题。
+
+你可以在特定位置(按函数名称、行号等)设置断点、启用和禁用这些断点、显示和更改变量值,并执行所有调试器希望执行的所有标准操作。但是它还有许多其它你可能没有尝试过的功能。这里有五个你可以尝试一下。
+
+### 条件断点
+
+设置断点是学习使用 GNU 调试器的第一步。程序在达到断点时停止,你可以运行 `gdb` 的命令对其进行检查或更改变量,然后再允许该程序继续运行。
+
+例如,你可能知道一个经常调用的函数有时会崩溃,但仅当它获得某个参数值时才会崩溃。你可以在该函数的开始处设置一个断点并运行程序。每次碰到该断点时都会显示函数参数,并且如果未提供触发崩溃的参数值,则可以继续操作,直到再次调用该函数为止。当这个惹了麻烦的参数触发崩溃时,你可以单步执行代码以查看问题所在。
+
+
+```
+(gdb) break sometimes_crashes
+Breakpoint 1 at 0x40110e: file prog.c, line 5.
+(gdb) run
+[...]
+Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
+5 fprintf(stderr,
+(gdb) continue
+Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
+5 fprintf(stderr,
+(gdb) continue
+```
+
+为了使此方法更具可重复性,你可以在你感兴趣的特定调用之前计算该函数被调用的次数,并在该断点处设置一个计数器(例如,`continue 30` 以使其在接下来的 29 次到达该断点时忽略它)。
+
+但是断点真正强大的地方在于它们在运行时评估表达式的能力,这使你可以自动化这种测试。
+
+```
+break [LOCATION] if CONDITION
+
+(gdb) break sometimes_crashes if !f
+Breakpoint 1 at 0x401132: file prog.c, line 5.
+(gdb) run
+[...]
+Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:5
+5 fprintf(stderr,
+(gdb)
+```
+
+条件断点使你不必让 `gdb` 每次调用该函数时都去问你要做什么,而是让条件断点仅在特定表达式的值为 `true` 时才使 `gdb` 停止在该位置。如果执行到达条件断点的位置,但表达式的计算结果为 `false`,调试器会自动使程序继续运行,而无需询问用户该怎么做。
+
+### 断点命令
+
+GNU 调试器中断点的一个甚至更复杂的功能是能够编写对到达断点的响应的脚本。断点命令使你可以编写一系列 GNU 调试器命令,以在到达该断点时运行。
+
+我们可以使用它来规避在 `sometimes_crashes` 函数中我们已知的错误,并在它提供空指针时使其无害地从该函数返回。
+
+我们可以使用 `silent` 作为第一行,以更好地控制输出。否则,每次命中断点时,即使在运行断点命令之前,也会显示堆栈帧。
+
+```
+(gdb) break sometimes_crashes
+Breakpoint 1 at 0x401132: file prog.c, line 5.
+(gdb) commands 1
+Type commands for breakpoint(s) 1, one per line.
+End with a line saying just "end".
+>silent
+>if !f
+ >frame
+ >printf "Skipping call\n"
+ >return 0
+ >continue
+ >end
+>printf "Continuing\n"
+>continue
+>end
+(gdb) run
+Starting program: /home/twaugh/Documents/GDB/prog
+warning: Loadable section ".note.gnu.property" outside of ELF segments
+Continuing
+Continuing
+Continuing
+#0 sometimes_crashes (f=0x0) at prog.c:5
+5 fprintf(stderr,
+Skipping call
+[Inferior 1 (process 9373) exited normally]
+(gdb)
+```
+
+### 转储二进制内存
+
+GNU 调试器内置支持使用 `x` 命令以各种格式检查内存,包括八进制、十六进制等。但是我喜欢并排看到两种格式:左侧为十六进制字节,右侧为相同字节表示的 ASCII 字符。
+
+当我想逐字节查看文件的内容时,经常使用 `hexdump -C`(`hexdump` 来自 [util-linux][3] 软件包)。这是 `gdb` 的 `x` 命令显示的十六进制字节:
+
+```
+(gdb) x/33xb mydata
+0x404040 : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x01
+0x404048 : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x72
+0x404050 : 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x63
+0x404058 : 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x05
+0x404060 : 0x00
+```
+
+如果你想让 `gdb` 像 `hexdump` 一样显示内存怎么办?这是可以的,实际上,你可以将这种方法用于你喜欢的任何格式。
+
+通过使用 `dump` 命令以将字节存储在文件中,结合 `shell` 命令以在文件上运行 `hexdump` 以及`define` 命令,我们可以创建自己的新的 `hexdump` 命令来使用 `hexdump` 显示内存内容。
+
+```
+(gdb) define hexdump
+Type commands for definition of "hexdump".
+End with a line saying just "end".
+>dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1
+>shell hexdump -C /tmp/dump.bin
+>end
+```
+
+这些命令甚至可以放在 `~/.gdbinit` 文件中,以永久定义 `hexdump` 命令。以下是它运行的例子:
+
+```
+(gdb) hexdump mydata sizeof(mydata)
+00000000 02 01 00 02 00 00 00 01 01 47 00 12 61 74 74 72 |.........G..attr|
+00000010 69 62 75 74 65 73 2d 63 68 61 72 73 65 75 00 05 |ibutes-charseu..|
+00000020 00 |.|
+00000021
+```
+
+### 行内反汇编
+
+有时你想更多地了解导致崩溃的原因,而源代码还不够。你想查看在 CPU 指令级别发生了什么。
+
+`disassemble` 命令可让你查看实现函数的 CPU 指令。但是有时输出可能很难跟踪。通常,我想查看与该函数源代码的特定部分相对应的指令。为此,请使用 `/s` 修饰符在反汇编中包括源代码行。
+
+```
+(gdb) disassemble/s main
+Dump of assembler code for function main:
+prog.c:
+11 {
+ 0x0000000000401158 <+0>: push %rbp
+ 0x0000000000401159 <+1>: mov %rsp,%rbp
+ 0x000000000040115c <+4>: sub $0x10,%rsp
+
+12 int n = 0;
+ 0x0000000000401160 <+8>: movl $0x0,-0x4(%rbp)
+
+13 sometimes_crashes(&n);
+ 0x0000000000401167 <+15>: lea -0x4(%rbp),%rax
+ 0x000000000040116b <+19>: mov %rax,%rdi
+ 0x000000000040116e <+22>: callq 0x401126
+[...snipped...]
+```
+
+这里,用 `info` 寄存器查看所有 CPU 寄存器的当前值,以及用如 `stepi` 这样命令一次执行一条指令,可以使你对程序有了更详细的了解。
+
+### 反向调试
+
+有时,你希望自己可以逆转时间。想象一下,你已经达到了变量的监视点。监视点像是一个断点,但不是在程序中的某个位置设置,而是在表达式上设置(使用 `watch` 命令)。每当表达式的值更改时,执行就会停止,并且调试器将获得控制权。
+
+想象一下你已经达到了这个监视点,并且由该变量使用的内存已更改了值。事实证明,这可能是由更早发生的事情引起的。例如,内存已释放,现在正在重新使用。但是它是何时何地被释放的呢?
+
+GNU 调试器甚至可以解决此问题,因为你可以反向运行程序!
+
+它通过在每个步骤中仔细记录程序的状态来实现此目的,以便可以恢复以前记录的状态,从而产生时间倒流的错觉。
+
+要启用此状态记录,请使用 `target record-full` 命令。然后,你可以使用一些听起来不太可行的命令,例如:
+
+* `reverse-step`,倒退到上一个源代码行
+* `*reverse-next`,它倒退到上一个源代码行,向后跳过函数调用
+* `reverse-finish`,倒退到当前函数即将被调用的时刻
+* `reverse-continue`,它返回到程序中的先前状态,该状态将(现在)触发断点(或其他导致断点停止的状态)
+
+这是运行中的反向调试的示例:
+
+```
+(gdb) b main
+Breakpoint 1 at 0x401160: file prog.c, line 12.
+(gdb) r
+Starting program: /home/twaugh/Documents/GDB/prog
+[...]
+
+Breakpoint 1, main () at prog.c:12
+12 int n = 0;
+(gdb) target record-full
+(gdb) c
+Continuing.
+
+Program received signal SIGSEGV, Segmentation fault.
+0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:7
+7 return *f;
+(gdb) reverse-finish
+Run back to call of #0 0x0000000000401154 in sometimes_crashes (f=0x0)
+ at prog.c:7
+0x0000000000401190 in main () at prog.c:16
+16 sometimes_crashes(0);
+```
+
+这些只是 GNU 调试器可以做的一些有用的事情。还有更多有待发现。你最喜欢 `gdb` 的哪个隐藏的、鲜为人知或令人吃惊的功能?请在评论中分享。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/9/tips-gnu-debugger
+
+作者:[Tim Waugh][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/twaugh
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bug_software_issue_tracking_computer_screen.jpg?itok=6qfIHR5y (Bug tracking magnifying glass on computer screen)
+[2]: https://www.gnu.org/software/gdb/
+[3]: https://en.wikipedia.org/wiki/Util-linux
diff --git a/published/20191004 What-s in an open source name.md b/published/20191004 What-s in an open source name.md
new file mode 100644
index 0000000000..2b6d45c599
--- /dev/null
+++ b/published/20191004 What-s in an open source name.md
@@ -0,0 +1,200 @@
+[#]: collector: (lujun9972)
+[#]: translator: (laingke)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11688-1.html)
+[#]: subject: (What's in an open source name?)
+[#]: via: (https://opensource.com/article/19/10/open-source-name-origins)
+[#]: author: (Joshua Allen Holm https://opensource.com/users/holmja)
+
+开源软件名称中的故事
+======
+
+> 有没有想过你喜欢的开源项目或编程语言的名称来自何处?让我们按字母顺序了解一下流行的技术术语背后的起源故事。
+
+
+
+GNOME、Java、Jupyter、Python……如果你的朋友或家人曾留意过你的工作对话,他们可能会认为你从事文艺复兴时期的民间文学艺术、咖啡烘焙、天文学或动物学工作。这些开源技术的名称从何而来?我们请我们的作者社区提供意见,并汇总了一些我们最喜欢的技术名称的起源故事。
+
+### Ansible
+
+“Ansible”这个名称直接来自科幻小说。Ursula Le Guin 的《Rocannon's World》一书中能进行即时(比光速更快)通信的设备被称为 ansibles(显然来自 “answerable” 一词)。Ansibles 开始流行于科幻小说之中,Orson Scott Card 的《Ender's Game》(后来成为受欢迎的电影)中,该设备控制了许多远程太空飞船。对于控制分布式机器的软件来说,这似乎是一个很好的模型,因此 Michael DeHaan(Ansible 的创建者和创始人)借用了这个名称。
+
+### Apache
+
+[Apache][2] 是最初于 1995 年发布的开源 Web 服务器。它的名称与著名的美国原住民部落无关;相反,它是指对原始软件代码的重复补丁。因此称之为,“一个修补的服务器”。
+
+### awk
+
+“awk(1) 代表着 Aho、Weinberger、Kernighan(作者)”—— Michael Greenberg
+
+### Bash
+
+“最初的 Unix shell,即 Bourne shell,是以其创造者的名字命名的。在开发出来 Bash 时,csh(发音为 ‘seashell’)实际上更受交互登录用户的欢迎。Bash 项目旨在赋予 Bourne shell 新的生命,使其更适合于交互式使用,因此它被命名为 ‘Bourne again shell’,是‘重生’的双关语。”——Ken Gaillot
+
+### C
+
+在早期,AT&T 的 Ken Thompson 和 Dennis Ritchie 发现可以使用更高级的编程语言(而不是低级的、可移植性更低的汇编编程)来编写操作系统和工具。早期有一个叫做 BCPL(基本组合编程语言)的编程系统,Thompson 创建了一个名为 B 的简化版 BCPL,但 B 的灵活性和速度都不高。然后,Ritchie 把 B 的思想扩展成一种叫做 C 的编译语言。”——Jim Hall
+
+### dd
+
+“我想你发表这样一篇文章不能不提到 dd。我的外号叫 Didi。发音正确的话听起来像 ‘dd’。我开始学的是 Unix,然后是 Linux,那是在 1993 年,当时我还是个学生。然后我去了军队,来到了我的部队中少数几个使用 Unix(Ultrix)的部门之一(其它部门主要是 VMS),那里的一个人说:‘这么说,你是一个黑客,对吗?你以为你了解 Unix 吗?好的,那么 dd 这个名字的是怎么来的呢?’我不知道,试着猜道:‘数据复印机?’所以他说,‘我要告诉你 dd 的故事。dd 是转换和复制的缩写(如今人们仍然可以在手册页中看到),但由于 cc 这个缩写已经被 C 编译器占用,所以它被命名为 dd。’就在几年后,我听闻了关于 JCL 的数据定义和 Unix dd 命令不统一的、半开玩笑的语法的真实故事,某种程度是基于此的。”——Yedidyah Bar David
+
+### Emacs
+
+经典的反 vi编辑器,其名称的真正词源并不明显,因为它源自“编辑宏”。但是,它作为一个伟大的宗教亵渎和崇拜的对象,吸引了许多恶作剧般的缩写,例如“Escape Meta Alt Control Shift”(以调侃其对键盘的大量依赖),“8MB 并经常发生内存交换”(从那时起就很吃内存了),“最终分配了所有的计算机存储空间”和 “EMACS 使一台计算机慢”——改编自 Jargon File/Hacker's Dictionary
+
+### Enarx
+
+[Enarx][3] 是机密计算领域的一个新项目。该项目的设计原则之一是它应该是“可替代的”。因此最初的名字是“psilocybin”(著名的魔术蘑菇)。一般情况下,经理级别的人可能会对这个名称有所抵触,因此考虑使用新名称。该项目的两位创始人 Mike Bursell 和 Nathaniel McCallum 都是古老语言极客,因此他们考虑了许多不同的想法,包括 тайна(Tayna——俄语中代表秘密或神秘——虽然俄语并不是一门古老的语言,但你就不要在乎这些细节了),crypticon(希腊语的意思是完全私生的),cryptidion(希腊中表示小密室),arconus(拉丁语中表示秘密的褒义形容词),arcanum(拉丁语中表示秘密的中性形容词)和 ærn(盎格鲁撒克逊人表示地方、秘密的地方、壁橱、住所、房子,或小屋的词汇)。最后,由于各种原因,包括域名和 GitHub 项目名称的可用性,他们选择了 enarx,这是两个拉丁词根的组合:en-(表示内部)和 -arx(表示城堡、要塞或堡垒)。
+
+### GIMP
+
+没有 [GIMP][4] 我们会怎么样?GNU 图像处理项目多年来一直是开源的重要基础。[维基百科][5]指出,“1995 年,[Spencer Kimball][6] 和 [Peter Mattis][7] 在加州大学伯克利分校开始为实验计算设施开发 GIMP,这是一个为期一个学期的项目。”
+
+### GNOME
+
+你有没有想过为什么 GNOME 被称为 GNOME?根据[维基百科][8],GNOME 最初是一个表示“GNU 网络对象模型环境”的缩写词。现在,该名称不再表示该项目,并且该项目已被放弃,但这个名称仍然保留了下来。[GNOME 3][9] 是 Fedora、红帽企业版、Ubuntu、Debian、SUSE Linux 企业版等发行版的默认桌面环境。
+
+### Java
+
+你能想象这种编程语言还有其它名称吗?Java 最初被称为 Oak,但是遗憾的是,Sun Microsystems 的法律团队由于已有该商标而否决了它。所以开发团队又重新给它命名。[据说][10]该语言的工作组在 1995 年 1 月举行了一次大规模的头脑风暴。许多其它名称也被扔掉了,包括 Silk、DNA、WebDancer 等。该团队不希望新名称与过度使用的术语“web”或“net”有任何关系。取而代之的是,他们在寻找更有活力、更有趣、更容易记住的东西。Java 满足了这些要求,并且奇迹般地,团队同意通过了!
+
+### Jupyter
+
+现在许多数据科学家和学生在工作中使用 [Jupyter][11] 笔记本。“Jupyter”这个名字是三种开源计算机语言的融合,这三种语言在这个笔记本中都有使用,在数据科学中也很突出:[Julia][12]、[Python][13] 和 [R][14]。
+
+### Kubernetes
+
+Kubernetes 源自希腊语中的舵手。Kubernetes 项目创始人 Craig McLuckie 在 [2015 Hacker News][15] 回应中证实了这种词源。他坚持航海主题,解释说,这项技术可以驱动集装箱,就像舵手或驾驶员驾驶集装箱船一样,因此,他选择了 Kubernetes 这个名字。我们中的许多人仍然在尝试正确的发音(koo-bur-NET-eez),因此 替代使用 K8s 也是可以接受的。有趣的是,它与英语单词“行政长官”具有相同的词源,也与蒸汽机上的机械负反馈装置相同。
+
+### KDE
+
+那 K 桌面呢?KDE 最初代表“酷桌面环境”。 它由 [Matthias Ettrich][16] 于 1996 年创立。根据[维基百科][17]上的说法,该名称是对 Unix 上 [通用桌面环境][18](CDE)一词的调侃。
+
+### Linux
+
+[Linux][19] 因其发明者 Linus Torvalds 的名字命名的。Linus 最初想将他的作品命名为“Freax”,因为他认为以他自己的名字命名太自负了。根据[维基百科][19]的说法,“赫尔辛基科技大学 Torvalds 的同事 Ari Lemmke 当时是 FTP 服务器的志愿管理员之一,他并不认为‘Freax’是个好名字。因此,他没有征询 Torvalds 就将服务器上的这个项目命名为‘Linux’。”
+
+以下是一些最受欢迎的 Linux 发行版。
+
+#### CentOS
+
+[CentOS][20] 是社区企业操作系统的缩写。它包含来自 Red Hat Enterprise Linux 的上游软件包。
+
+#### Debian
+
+[Debian][21] Linux 创建于 1993 年 9 月,是其创始人 Ian Murdock 和他当时的女友 Debra Lynn 的名字的混成词。
+
+#### RHEL
+
+[Red Hat Linux][22] 得名于它的创始人 Marc Ewing,他戴着一顶祖父送给他的康奈尔大学红色软呢帽。红帽公司成立于 1993 年 3 月 26 日。[Fedora Linux][23] 最初是一个志愿者项目,旨在为红帽发行版提供额外的软件,它的名字来自红帽的“Shadowman”徽标。
+
+#### Ubuntu
+
+[Ubuntu][24] 旨在广泛分享开源软件,它以非洲哲学“人的本质”命名,可以翻译为“对他人的人道主义”或“我之所以是我,是因为我们都是这样的人”。
+
+### Moodle
+
+开源学习平台 [Moodle][25] 是“模块化面向对象动态学习环境”的首字母缩写。Moodle 仍然是领先的线上学习平台。全球有近 10.4 万个注册的 Moodle 网站。
+
+另外两个流行的开源内容管理系统是 Drupal 和 Joomla。Drupal 的名字来自荷兰语 “druppel”,意思是“掉落”。根据维基百科,Joomla 是斯瓦希里语单词“jumla”的[英式拼写][26],在阿拉伯语、乌尔都语和其他语言中是“在一起”的意思。
+
+### Mozilla
+
+[Mozilla][27] 是一个成立于 1998 年的开源软件社区。根据其网站,“Mozilla 项目创建于 1998 年,发布了 Netscape 浏览器套件源代码。其旨在利用互联网上成千上万的程序员的创造力,并推动浏览器市场上前所未有的创新水平。” 这个名字是 [Mosaic] [28] 和 Godzilla 的混成词。
+
+### Nginx
+
+“许多技术人员都试图装酷,并将它念成‘n’‘g’‘n’‘x’。实际上,很少的一些人做点基本的调查工作,就可以很快发现该名称实际上应该被念成是“EngineX”,指的是功能强大的 web 服务器,像个引擎。”——Jean Sebastien Tougne
+
+### Perl
+
+Perl 的创始人 Larry Wall 最初将他的项目命名为“Pearl”。根据维基百科,Wall 想给这种语言起一个有积极含义的简短名字。在 Perl 正式发布之前,Wall 发现了已有 [PEARL][29] 编程语言,于是更改了名称的拼写。
+
+### Piet 和 Mondrian
+
+“有两种编程语言以艺术家 Piet Mondrian 命名。一种叫做‘Piet’,另一种叫做‘Mondrian’。(David Morgan-Mar [写道][30]):‘Piet 是一种编程语言,其中的程序看起来像抽象绘画。该语言以几何抽象艺术的开创者 Piet Mondrian 的名字命名。我曾想将这种语言命名为 Mondrian,但是有人告诉我这会让它看起来像一种很普通的脚本语言。哦,好吧,我想我们不能都是深奥的语言作家。’”——Yuval Lifshitz
+
+### Python
+
+Python 编程语言的独特名称来自其创建者 Guido Van Rossum,他是英国六人喜剧团体 Monty Python 的粉丝。
+
+### Raspberry Pi
+
+Raspberry Pi 以其微小但强大的功能和对低廉的价格而闻名,在开源社区中是最受欢迎的。但是它可爱(和好吃)的名字是从哪里来的呢?在 70 年代和 80 年代,以水果命名的计算机是一种流行的趋势。苹果、橘子、杏……有人饿了吗?根据创始人 Eben Upton 的 [2012 采访] [31],“树莓派”这个名称是对这种趋势的致敬。树莓也很小,但却很有味道。名称中的“Pi”暗示着这样的事实:最初,该计算机只能运行 Python。
+
+### Samba
+
+[Server Message Block][32] 用于在 Linux 上共享 Windows 文件。
+
+### ScummVM
+
+[ScummVM][33](《疯狂大楼》虚拟机的脚本创建实用程序)是一个程序,可以在现代计算机上运行一些经典的计算机冒险游戏。最初,它旨在玩用 SCUMM 构建的 LucasArts 的冒险游戏,该游戏最初用于开发《疯狂大楼》,后来又被用来开发 LucasArts 的其它大多数冒险游戏。目前,ScummVM 支持大量游戏引擎,包括 Sierra Online 的 AGI 和 SCI,但仍保留着名称 ScummVM。
+
+有一个相关的项目 [ResidualVM][34] 之所以得名,是因为它涵盖了 ScummVM 未涵盖的“剩余的” LucasArts 冒险游戏。 ResidualVM 涵盖的 LucasArts 游戏是使用 GrimE(Grim Engine)开发的,该引擎最初用于开发 Grim Fandango,因此 ResidualVM 的名称是双关语。
+
+### SQL
+
+“你可能知道 SQL 代表结构化查询语言,但你知道为什么它经常被读作‘sequel’吗?它是作为原本的‘QUEL’(查询语言)的后续(如结局)而创建的。”——Ken Gaillot
+
+### XFCE
+
+[XFCE][35] 是由 [Olivier Fourdan][36] 创建的一个流行的桌面。它在 1996 年作为 CDE 的替代品出现,最初是 XForms 公共环境的缩写。
+
+### Zsh
+
+Zsh 是一个交互式登录 shell。1990 年,普林斯顿大学的学生 Paul Falstad 写了该 shell 的第一个版本。他在看到当时在普林斯顿大学担任助教的 Zhong Sha 的登录 ID(zsh)后,觉得这个名字听起来像 [shell 的好名字][37],给它起了这个名字。
+
+还有更多的项目和名称还没有包括在这个列表中。请一定要在评论中分享你的收藏。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/open-source-name-origins
+
+作者:[Joshua Allen Holm][a]
+选题:[lujun9972][b]
+译者:[laingke](https://github.com/laingke)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/holmja
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_resume_rh1x.png?itok=S3HGxi6E (A person writing.)
+[2]: https://httpd.apache.org/
+[3]: https://enarx.io
+[4]: https://www.gimp.org/
+[5]: https://en.wikipedia.org/wiki/GIMP
+[6]: https://en.wikipedia.org/wiki/Spencer_Kimball_(computer_programmer)
+[7]: https://en.wikipedia.org/wiki/Peter_Mattis
+[8]: https://en.wikipedia.org/wiki/GNOME
+[9]: https://www.gnome.org/gnome-3/
+[10]: https://www.javaworld.com/article/2077265/so-why-did-they-decide-to-call-it-java-.html
+[11]: https://jupyter.org/
+[12]: https://julialang.org/
+[13]: https://www.python.org/
+[14]: https://www.r-project.org/
+[15]: https://news.ycombinator.com/item?id=9653797
+[16]: https://en.wikipedia.org/wiki/Matthias_Ettrich
+[17]: https://en.wikipedia.org/wiki/KDE
+[18]: https://sourceforge.net/projects/cdesktopenv/
+[19]: https://en.wikipedia.org/wiki/Linux
+[20]: https://www.centos.org/
+[21]: https://www.debian.org/
+[22]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
+[23]: https://getfedora.org/
+[24]: https://ubuntu.com/about
+[25]: https://moodle.org/
+[26]: https://en.wikipedia.org/wiki/Joomla#Historical_background
+[27]: https://www.mozilla.org/en-US/
+[28]: https://en.wikipedia.org/wiki/Mosaic_(web_browser)
+[29]: https://en.wikipedia.org/wiki/PEARL_(programming_language)
+[30]: http://www.dangermouse.net/esoteric/piet.html
+[31]: https://www.techspot.com/article/531-eben-upton-interview/
+[32]: https://www.samba.org/
+[33]: https://www.scummvm.org/
+[34]: https://www.residualvm.org/
+[35]: https://www.xfce.org/
+[36]: https://en.wikipedia.org/wiki/Olivier_Fourdan
+[37]: http://www.zsh.org/mla/users/2005/msg00951.html
diff --git a/published/20191017 Using multitail on Linux.md b/published/20191017 Using multitail on Linux.md
new file mode 100644
index 0000000000..0d8870c9fc
--- /dev/null
+++ b/published/20191017 Using multitail on Linux.md
@@ -0,0 +1,118 @@
+[#]: collector: (lujun9972)
+[#]: translator: (geekpi)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11643-1.html)
+[#]: subject: (Using multitail on Linux)
+[#]: via: (https://www.networkworld.com/article/3445228/using-multitail-on-linux.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+在 Linux 上使用 Multitail
+======
+
+
+
+当你想同时查看多个文件(尤其是日志文件)的活动时,`multitail` 命令会非常有用。它的工作方式类似于多窗口形式的 `tail -f` 命令。也就是说,它显示这些文件的底部和添加的新行。虽然通常使用简单,但是 `multitail` 提供了一些命令行和交互式选项,在开始使用它之前,你应该了解它们。
+
+### 基本 multitail 使用
+
+`multitail` 的最简单用法是在命令行中列出你要查看的文件名称。此命令水平分割屏幕(即顶部和底部),并显示每个文件的底部以及更新。
+
+```
+$ multitail /var/log/syslog /var/log/dmesg
+```
+
+显示内容将像这样拆分:
+
+```
++-----------------------+
+| |
+| |
++-----------------------|
+| |
+| |
++-----------------------+
+```
+
+每个文件都有一行显示该文件的文件编号(从 00 开始)、文件名、文件大小、最新内容的添加日期和时间。每个文件将被分配一半空间,而不论它的大小和活动情况。比如:
+
+```
+content lines from my1.log
+more content
+more lines
+
+00] my1.log 59KB - 2019/10/14 12:12:09
+content lines from my2.log
+more content
+more lines
+
+01] my2.log 120KB - 2019/10/14 14:22:29
+```
+
+请注意,如果你要求 `multitail` 显示非文本文件或者你无权查看的文件,它不会报错。你只是看不到内容。
+
+你还可以使用通配符指定要查看的文件:
+
+```
+$ multitail my*.log
+```
+
+要记住的一件事是,`multitail` 将平均分割屏幕。如果指定的文件太多,那么除非你采取额外的步骤查看之后的文件(参考下面的滚动选项),否则你将只会看到前面 7 个文件的前面几行。确切的结果取决于终端窗口中有多少行可用。
+
+按 `q` 退出 `multitail` 并返回到正常的屏幕视图。
+
+### 分割屏幕
+
+如果你愿意,`multitail` 也可以垂直分割你的终端窗口(即,左和右)。为此,请使用 `-s` 选项。如果指定了三个文件,那么屏幕右侧的窗口将会水平分隔。四个文件的话,你将拥有四个大小相等的窗口。
+
+```
++-----------+-----------+ +-----------+-----------+ +-----------+-----------+
+| | | | | | | | |
+| | | | | | | | |
+| | | | +-----------+ +-----------+-----------+
+| | | | | | | | |
+| | | | | | | | |
++-----------+-----------+ +-----------+-----------+ +-----------+-----------+
+ 2 个文件 3 个文件 4 个文件
+```
+
+如果要将屏幕分为三列,请使用 `multitail -s 3 file1 file2 file3`。
+
+```
++-------+-------+-------+
+| | | |
+| | | |
+| | | |
+| | | |
+| | | |
++-------+-------+-------+
+ 3 个文件带上 -s 3 选项
+```
+
+### 滚动
+
+你可以上下滚动文件,但是需要按下 `b` 弹出选择菜单,然后使用向上和向下箭头按钮选择要滚动浏览的文件。然后按下回车键。然后,你可以再次使用向上和向下箭头在放大的区域中滚动浏览各行。完成后按下 `q` 返回正常视图。
+
+### 获得帮助
+
+在 `multitail` 中按下 `h` 将打开一个帮助菜单,其中描述了一些基本操作,但是手册页提供了更多信息,如果莫想了解更多有关使用此工具的信息,请仔细阅读。
+
+默认情况下,你的系统上不会安装 `multitail`,但是使用 `apt-get` 或 `yum` 可以使你轻松安装。该工具提供了许多功能,不过它是基于字符显示的,窗口边框只是 `q` 和 `x` 的字符串组成的。当你需要关注文件更新时,它非常方便。
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3445228/using-multitail-on-linux.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[geekpi](https://github.com/geekpi)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.flickr.com/photos/glenbowman/7992498919/in/photolist-dbgDtv-gHfRRz-5uRM4v-gHgFnz-6sPqTZ-5uaP7H-USFPqD-pbtRUe-fiKiYn-nmgWL2-pQNepR-q68p8d-dDsUxw-dbgFKG-nmgE6m-DHyqM-nCKA4L-2d7uFqH-Kbqzk-8EwKg-8Vy72g-2X3NSN-78Bv84-buKWXF-aeM4ok-yhweWf-4vwpyX-9hu8nq-9zCoti-v5nzP5-23fL48r-24y6pGS-JhWDof-6zF75k-24y6nHS-9hr19c-Gueh6G-Guei7u-GuegFy-24y6oX5-26qu5iX-wKrnMW-Gueikf-24y6oYh-27y4wwA-x4z19F-x57yP4-24BY6gc-24y6nPo-QGwbkf
+[2]: https://creativecommons.org/licenses/by-sa/2.0/legalcode
+[5]: https://www.facebook.com/NetworkWorld/
+[6]: https://www.linkedin.com/company/network-world
diff --git a/published/20191020 14 SCP Command Examples to Securely Transfer Files in Linux.md b/published/20191020 14 SCP Command Examples to Securely Transfer Files in Linux.md
new file mode 100644
index 0000000000..9fafdca9cf
--- /dev/null
+++ b/published/20191020 14 SCP Command Examples to Securely Transfer Files in Linux.md
@@ -0,0 +1,245 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11669-1.html)
+[#]: subject: (14 SCP Command Examples to Securely Transfer Files in Linux)
+[#]: via: (https://www.linuxtechi.com/scp-command-examples-in-linux/)
+[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
+
+在 Linux 上安全传输文件的 14 SCP 命令示例
+======
+
+
+
+SCP(安全复制)是 Linux 和 Unix 之类的系统中的命令行工具,用于通过网络安全地跨系统传输文件和目录。当我们使用 `scp` 命令将文件和目录从本地系统复制到远程系统时,则在后端与远程系统建立了 ssh 连接。换句话说,我们可以说 `scp` 在后端使用了相同的 SSH 安全机制,它需要密码或密钥进行身份验证。
+
+![scp-command-examples-linux][2]
+
+在本教程中,我们将讨论 14 个有用的 Linux `scp` 命令示例。
+
+`scp` 命令语法:
+
+```
+# scp <选项> <文件或目录> 用户名@目标主机:/<文件夹>
+
+# scp <选项> 用户名@目标主机:/文件 <本地文件夹>
+```
+
+`scp` 命令的第一个语法演示了如何将文件或目录从本地系统复制到特定文件夹下的目标主机。
+
+`scp` 命令的第二种语法演示了如何将目标主机中的文件复制到本地系统中。
+
+下面列出了 `scp` 命令中使用最广泛的一些选项,
+
+* `-C` 启用压缩
+* `-i` 指定识别文件或私钥
+* `-l` 复制时限制带宽
+* `-P` 指定目标主机的 ssh 端口号
+* `-p` 复制时保留文件的权限、模式和访问时间
+* `-q` 禁止 SSH 警告消息
+* `-r` 递归复制文件和目录
+* `-v` 详细输出
+
+现在让我们跳入示例!
+
+### 示例:1)使用 scp 将文件从本地系统复制到远程系统
+
+假设我们要使用 `scp` 命令将 jdk 的 rpm 软件包从本地 Linux 系统复制到远程系统(172.20.10.8),请使用以下命令,
+
+```
+[root@linuxtechi ~]$ scp jdk-linux-x64_bin.rpm root@linuxtechi:/opt
+root@linuxtechi's password:
+jdk-linux-x64_bin.rpm 100% 10MB 27.1MB/s 00:00
+[root@linuxtechi ~]$
+```
+
+上面的命令会将 jdk 的 rpm 软件包文件复制到 `/opt` 文件夹下的远程系统。
+
+### 示例:2)使用 scp 将文件从远程系统复制到本地系统
+
+假设我们想将文件从远程系统复制到本地系统下的 `/tmp` 文件夹,执行以下 `scp` 命令,
+
+```
+[root@linuxtechi ~]$ scp root@linuxtechi:/root/Technical-Doc-RHS.odt /tmp
+root@linuxtechi's password:
+Technical-Doc-RHS.odt 100% 1109KB 31.8MB/s 00:00
+[root@linuxtechi ~]$ ls -l /tmp/Technical-Doc-RHS.odt
+-rwx------. 1 pkumar pkumar 1135521 Oct 19 11:12 /tmp/Technical-Doc-RHS.odt
+[root@linuxtechi ~]$
+```
+
+### 示例:3)使用 scp 传输文件时的详细输出(-v)
+
+在 `scp` 命令中,我们可以使用 `-v` 选项启用详细输出。使用详细输出,我们可以轻松地发现后台确切发生了什么。这对于调试连接、认证和配置等问题非常有用。
+
+```
+root@linuxtechi ~]$ scp -v jdk-linux-x64_bin.rpm root@linuxtechi:/opt
+Executing: program /usr/bin/ssh host 172.20.10.8, user root, command scp -v -t /opt
+OpenSSH_7.8p1, OpenSSL 1.1.1 FIPS 11 Sep 2018
+debug1: Reading configuration data /etc/ssh/ssh_config
+debug1: Reading configuration data /etc/ssh/ssh_config.d/05-redhat.conf
+debug1: Reading configuration data /etc/crypto-policies/back-ends/openssh.config
+debug1: /etc/ssh/ssh_config.d/05-redhat.conf line 8: Applying options for *
+debug1: Connecting to 172.20.10.8 [172.20.10.8] port 22.
+debug1: Connection established.
+…………
+debug1: Next authentication method: password
+root@linuxtechi's password:
+```
+
+### 示例:4)将多个文件传输到远程系统
+
+可以使用 `scp` 命令一次性将多个文件复制/传输到远程系统,在 `scp` 命令中指定多个文件,并用空格隔开,示例如下所示
+
+```
+[root@linuxtechi ~]$ scp install.txt index.html jdk-linux-x64_bin.rpm root@linuxtechi:/mnt
+root@linuxtechi's password:
+install.txt 100% 0 0.0KB/s 00:00
+index.html 100% 85KB 7.2MB/s 00:00
+jdk-linux-x64_bin.rpm 100% 10MB 25.3MB/s 00:00
+[root@linuxtechi ~]$
+```
+
+### 示例:5)在两个远程主机之间传输文件
+
+使用 `scp` 命令,我们可以在两个远程主机之间复制文件和目录,假设我们有一个可以连接到两个远程 Linux 系统的本地 Linux 系统,因此从我的本地 Linux 系统中,我可以使用 `scp` 命令在这两个系统之间复制文件,
+
+命令语法:
+
+```
+# scp 用户名@远程主机1:/<要传输的文件> 用户名@远程主机2:/<文件夹>
+```
+
+示例如下:
+
+```
+# scp root@linuxtechi:~/backup-Oct.zip root@linuxtechi:/tmp
+# ssh root@linuxtechi "ls -l /tmp/backup-Oct.zip"
+-rwx------. 1 root root 747438080 Oct 19 12:02 /tmp/backup-Oct.zip
+```
+
+### 示例:6)递归复制文件和目录(-r)
+
+在 `scp` 命令中使用 `-r` 选项将整个目录从一个系统递归地复制到另一个系统,示例如下所示:
+
+```
+[root@linuxtechi ~]$ scp -r Downloads root@linuxtechi:/opt
+```
+
+使用以下命令验证 `Downloads` 文件夹是否已复制到远程系统,
+
+```
+[root@linuxtechi ~]$ ssh root@linuxtechi "ls -ld /opt/Downloads"
+drwxr-xr-x. 2 root root 75 Oct 19 12:10 /opt/Downloads
+[root@linuxtechi ~]$
+```
+
+### 示例:7)通过启用压缩来提高传输速度(-C)
+
+在 `scp` 命令中,我们可以通过使用 `-C` 选项启用压缩来提高传输速度,它将自动在源主机上启用压缩并在目标主机上解压缩。
+
+```
+root@linuxtechi ~]$ scp -r -C Downloads root@linuxtechi:/mnt
+```
+
+在以上示例中,我们正在启用压缩的情况下传输下载目录。
+
+### 示例:8)复制时限制带宽(-l)
+
+在 `scp` 命令中使用 `-l` 选项设置复制时对带宽使用的限制。带宽以 Kbit/s 为单位指定,示例如下所示:
+
+```
+[root@linuxtechi ~]$ scp -l 500 jdk-linux-x64_bin.rpm root@linuxtechi:/var
+```
+
+### 示例:9)在 scp 时指定其他 ssh 端口(-P)
+
+在某些情况下,目标主机上的 ssh 端口会更改,因此在使用 `scp` 命令时,我们可以使用 `-P` 选项指定 ssh 端口号。
+
+```
+[root@linuxtechi ~]$ scp -P 2022 jdk-linux-x64_bin.rpm root@linuxtechi:/var
+```
+
+在上面的示例中,远程主机的 ssh 端口为 “2022”。
+
+### 示例:10)复制时保留文件的权限、模式和访问时间(-p)
+
+从源复制到目标时,在 `scp` 命令中使用 `-p` 选项保留权限、访问时间和模式。
+
+```
+[root@linuxtechi ~]$ scp -p jdk-linux-x64_bin.rpm root@linuxtechi:/var/tmp
+jdk-linux-x64_bin.rpm 100% 10MB 13.5MB/s 00:00
+[root@linuxtechi ~]$
+```
+
+### 示例:11)在 scp 中以安静模式传输文件(-q)
+
+在 `scp` 命令中使用 `-q` 选项可禁止显示 ssh 的传输进度、警告和诊断消息。示例如下所示:
+
+```
+[root@linuxtechi ~]$ scp -q -r Downloads root@linuxtechi:/var/tmp
+[root@linuxtechi ~]$
+```
+
+### 示例:12)在传输时使用 scp 中的识别文件(-i)
+
+在大多数 Linux 环境中,首选基于密钥的身份验证。在 `scp` 命令中,我们使用 `-i` 选项指定识别文件(私钥文件),示例如下所示:
+
+```
+[root@linuxtechi ~]$ scp -i my_key.pem -r Downloads root@linuxtechi:/root
+```
+
+在上面的示例中,`my_key.pem` 是识别文件或私钥文件。
+
+### 示例:13)在 scp 中使用其他 ssh_config 文件(-F)
+
+在某些情况下,你使用不同的网络连接到 Linux 系统,可能某些网络位于代理服务器后面,因此在这种情况下,我们必须具有不同的 `ssh_config` 文件。
+
+通过 `-F` 选项在 `scp` 命令中指定了不同的 `ssh_config` 文件,示例如下所示:
+
+```
+[root@linuxtechi ~]$ scp -F /home/pkumar/new_ssh_config -r Downloads root@linuxtechi:/root
+root@linuxtechi's password:
+jdk-linux-x64_bin.rpm 100% 10MB 16.6MB/s 00:00
+backup-Oct.zip 100% 713MB 41.9MB/s 00:17
+index.html 100% 85KB 6.6MB/s 00:00
+[root@linuxtechi ~]$
+```
+
+### 示例:14)在 scp 命令中使用其他加密方式(-c)
+
+默认情况下,`scp` 使用 AES-128 加密方式来加密文件。如果你想在 `scp` 命令中使用其他加密方式,请使用 `-c` 选项,后接加密方式名称。
+
+假设我们要在用 `scp` 命令传输文件时使用 3des-cbc 加密方式,请运行以下 `scp` 命令:
+
+```
+[root@linuxtechi ~]# scp -c 3des-cbc -r Downloads root@linuxtechi:/root
+```
+
+使用以下命令列出 `ssh` 和 `scp` 支持的加密方式:
+
+```
+[root@linuxtechi ~]# ssh -Q cipher localhost | paste -d , -s -
+3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,root@linuxtechi,aes128-ctr,aes192-ctr,aes256-ctr,root@linuxtechi,root@linuxtechi,root@linuxtechi
+[root@linuxtechi ~]#
+```
+
+以上就是本教程的全部内容,要获取有关 `scp` 命令的更多详细信息,请参考其手册页。请在下面的评论部分中分享你的反馈和评论。
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxtechi.com/scp-command-examples-in-linux/
+
+作者:[Pradeep Kumar][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.linuxtechi.com/author/pradeep/
+[b]: https://github.com/lujun9972
+[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/scp-command-examples-linux.jpg
+[3]: https://www.linuxtechi.com/cdn-cgi/l/email-protection
diff --git a/published/20191022 How to program with Bash- Logical operators and shell expansions.md b/published/20191022 How to program with Bash- Logical operators and shell expansions.md
new file mode 100644
index 0000000000..31f0e3ef32
--- /dev/null
+++ b/published/20191022 How to program with Bash- Logical operators and shell expansions.md
@@ -0,0 +1,467 @@
+[#]: collector: (lujun9972)
+[#]: translator: (lxbwolf)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11687-1.html)
+[#]: subject: (How to program with Bash: Logical operators and shell expansions)
+[#]: via: (https://opensource.com/article/19/10/programming-bash-logical-operators-shell-expansions)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+怎样用 Bash 编程:逻辑操作符和 shell 扩展
+======
+
+> 学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇。
+
+
+
+Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本。本系列(三篇文章,基于我的 [三集 Linux 自学课程][2])讲解如何在 CLI 使用 Bash 编程。
+
+[第一篇文章][3] 讲解了 Bash 的一些简单命令行操作,包括如何使用变量和控制操作符。第二篇文章探讨文件、字符串、数字等类型和各种各样在执行流中提供控制逻辑的的逻辑运算符,还有 Bash 中的各类 shell 扩展。本系列第三篇也是最后一篇文章,将会探索能重复执行操作的 `for` 、`while` 和 `until` 循环。
+
+逻辑操作符是程序中进行判断的根本要素,也是执行不同的语句组合的依据。有时这也被称为流控制。
+
+### 逻辑操作符
+
+Bash 中有大量的用于不同条件表达式的逻辑操作符。最基本的是 `if` 控制结构,它判断一个条件,如果条件为真,就执行一些程序语句。操作符共有三类:文件、数字和非数字操作符。如果条件为真,所有的操作符返回真值(`0`),如果条件为假,返回假值(`1`)。
+
+这些比较操作符的函数语法是,一个操作符加一个或两个参数放在中括号内,后面跟一系列程序语句,如果条件为真,程序语句执行,可能会有另一个程序语句列表,该列表在条件为假时执行:
+
+
+```
+if [ arg1 operator arg2 ] ; then list
+或
+if [ arg1 operator arg2 ] ; then list ; else list ; fi
+```
+
+像例子中那样,在比较表达式中,空格不能省略。中括号的每部分,`[` 和 `]`,是跟 `test` 命令一样的传统的 Bash 符号:
+
+```
+if test arg1 operator arg2 ; then list
+```
+
+还有一个更新的语法能提供一点点便利,一些系统管理员比较喜欢用。这种格式对于不同版本的 Bash 和一些 shell 如 ksh(Korn shell)兼容性稍差。格式如下:
+
+```
+if [[ arg1 operator arg2 ]] ; then list
+```
+
+#### 文件操作符
+
+文件操作符是 Bash 中一系列强大的逻辑操作符。图表 1 列出了 20 多种不同的 Bash 处理文件的操作符。在我的脚本中使用频率很高。
+
+操作符 | 描述
+---|---
+`-a filename` | 如果文件存在,返回真值;文件可以为空也可以有内容,但是只要它存在,就返回真值
+`-b filename` | 如果文件存在且是一个块设备,如 `/dev/sda` 或 `/dev/sda1`,则返回真值
+`-c filename` | 如果文件存在且是一个字符设备,如 `/dev/TTY1`,则返回真值
+`-d filename` | 如果文件存在且是一个目录,返回真值
+`-e filename` | 如果文件存在,返回真值;与上面的 `-a` 相同
+`-f filename` | 如果文件存在且是一个一般文件,不是目录、设备文件或链接等的其他的文件,则返回 真值
+`-g filename` | 如果文件存在且 `SETGID` 标记被设置在其上,返回真值
+`-h filename` | 如果文件存在且是一个符号链接,则返回真值
+`-k filename` | 如果文件存在且粘滞位已设置,则返回真值
+`-p filename` | 如果文件存在且是一个命名的管道(FIFO),返回真值
+`-r filename` | 如果文件存在且有可读权限(它的可读位被设置),返回真值
+`-s filename` | 如果文件存在且大小大于 0,返回真值;如果一个文件存在但大小为 0,则返回假值
+`-t fd` | 如果文件描述符 `fd` 被打开且被关联到一个终端设备上,返回真值
+`-u filename` | 如果文件存在且它的 `SETUID` 位被设置,返回真值
+`-w filename` | 如果文件存在且有可写权限,返回真值
+`-x filename` | 如果文件存在且有可执行权限,返回真值
+`-G filename` | 如果文件存在且文件的组 ID 与当前用户相同,返回真值
+`-L filename` | 如果文件存在且是一个符号链接,返回真值(同 `-h`)
+`-N filename` | 如果文件存在且从文件上一次被读取后文件被修改过,返回真值
+`-O filename` | 如果文件存在且你是文件的拥有者,返回真值
+`-S filename` | 如果文件存在且文件是套接字,返回真值
+`file1 -ef file2` | 如果文件 `file1` 和文件 `file2` 指向同一设备的同一 INODE 号,返回真值(即硬链接)
+`file1 -nt file2` | 如果文件 `file1` 比 `file2` 新(根据修改日期),或 `file1` 存在而 `file2` 不存在,返回真值
+`file1 -ot file2` | 如果文件 `file1` 比 `file2` 旧(根据修改日期),或 `file1` 不存在而 `file2` 存在
+
+*图表 1:Bash 文件操作符*
+
+以测试一个文件存在与否来举例:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; if [ -e $File ] ; then echo "The file $File exists." ; else echo "The file $File does not exist." ; fi
+The file TestFile1 does not exist.
+[student@studentvm1 testdir]$
+```
+
+创建一个用来测试的文件,命名为 `TestFile1`。目前它不需要包含任何数据:
+
+```
+[student@studentvm1 testdir]$ touch TestFile1
+```
+
+在这个简短的 CLI 程序中,修改 `$File` 变量的值相比于在多个地方修改表示文件名的字符串的值要容易:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; if [ -e $File ] ; then echo "The file $File exists." ; else echo "The file $File does not exist." ; fi
+The file TestFile1 exists.
+[student@studentvm1 testdir]$
+```
+
+现在,运行一个测试来判断一个文件是否存在且长度不为 0(表示它包含数据)。假设你想判断三种情况:
+
+1. 文件不存在;
+2. 文件存在且为空;
+3. 文件存在且包含数据。
+
+因此,你需要一组更复杂的测试代码 — 为了测试所有的情况,使用 `if-elif-else` 结构中的 `elif` 语句:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; if [ -s $File ] ; then echo "$File exists and contains data." ; fi
+[student@studentvm1 testdir]$
+```
+
+在这个情况中,文件存在但不包含任何数据。向文件添加一些数据再运行一次:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is file $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; fi
+TestFile1 exists and contains data.
+[student@studentvm1 testdir]$
+```
+
+这组语句能返回正常的结果,但是仅仅是在我们已知三种可能的情况下测试某种确切的条件。添加一段 `else` 语句,这样你就可以更精确地测试。把文件删掉,你就可以完整地测试这段新代码:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; rm $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
+TestFile1 does not exist or is empty.
+```
+
+现在创建一个空文件用来测试:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; touch $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
+TestFile1 does not exist or is empty.
+```
+
+向文件添加一些内容,然后再测试一次:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is file $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; else echo "$File does not exist or is empty." ; fi
+TestFile1 exists and contains data.
+```
+
+现在加入 `elif` 语句来辨别是文件不存在还是文件为空:
+
+```
+[student@studentvm1 testdir]$ File="TestFile1" ; touch $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; elif [ -e $File ] ; then echo "$File exists and is empty." ; else echo "$File does not exist." ; fi
+TestFile1 exists and is empty.
+[student@studentvm1 testdir]$ File="TestFile1" ; echo "This is $File" > $File ; if [ -s $File ] ; then echo "$File exists and contains data." ; elif [ -e $File ] ; then echo "$File exists and is empty." ; else echo "$File does not exist." ; fi
+TestFile1 exists and contains data.
+[student@studentvm1 testdir]$
+```
+
+现在你有一个可以测试这三种情况的 Bash CLI 程序,但是可能的情况是无限的。
+
+如果你能像保存在文件中的脚本那样组织程序语句,那么即使对于更复杂的命令组合也会很容易看出它们的逻辑结构。图表 2 就是一个示例。 `if-elif-else` 结构中每一部分的程序语句的缩进让逻辑更变得清晰。
+
+
+```
+File="TestFile1"
+echo "This is $File" > $File
+if [ -s $File ]
+ then
+ echo "$File exists and contains data."
+elif [ -e $File ]
+ then
+ echo "$File exists and is empty."
+else
+ echo "$File does not exist."
+fi
+```
+
+*图表 2: 像在脚本里一样重写书写命令行程序*
+
+对于大多数 CLI 程序来说,让这些复杂的命令变得有逻辑需要写很长的代码。虽然 CLI 可能是用 Linux 或 Bash 内置的命令,但是当 CLI 程序很长或很复杂时,创建一个保存在文件中的脚本将更有效,保存到文件中后,可以随时运行。
+
+#### 字符串比较操作符
+
+字符串比较操作符使我们可以对字符串中的字符按字母顺序进行比较。图表 3 列出了仅有的几个字符串比较操作符。
+
+操作符 | 描述
+---|---
+`-z string` | 如果字符串的长度为 0 ,返回真值
+`-n string` |如果字符串的长度不为 0 ,返回真值
+`string1 == string2` 或 `string1 = string2` | 如果两个字符串相等,返回真值。处于遵从 POSIX 一致性,在测试命令中应使用一个等号 `=`。与命令 `[[` 一起使用时,会进行如上描述的模式匹配(混合命令)。
+`string1 != string2` | 两个字符串不相等,返回真值
+`string1 < string2` | 如果对 `string1` 和 `string2` 按字母顺序进行排序,`string1` 排在 `string2` 前面(即基于地区设定的对所有字母和特殊字符的排列顺序)
+`string1 > string2` | 如果对 `string1` 和 `string2` 按字母顺序进行排序,`string1` 排在 `string2` 后面
+
+*图表 3: Bash 字符串逻辑操作符*
+
+首先,检查字符串长度。比较表达式中 `$MyVar` 两边的双引号不能省略(你仍应该在目录 `~/testdir` 下 )。
+
+```
+[student@studentvm1 testdir]$ MyVar="" ; if [ -z "" ] ; then echo "MyVar is zero length." ; else echo "MyVar contains data" ; fi
+MyVar is zero length.
+[student@studentvm1 testdir]$ MyVar="Random text" ; if [ -z "" ] ; then echo "MyVar is zero length." ; else echo "MyVar contains data" ; fi
+MyVar is zero length.
+```
+
+你也可以这样做:
+
+```
+[student@studentvm1 testdir]$ MyVar="Random text" ; if [ -n "$MyVar" ] ; then echo "MyVar contains data." ; else echo "MyVar is zero length" ; fi
+MyVar contains data.
+[student@studentvm1 testdir]$ MyVar="" ; if [ -n "$MyVar" ] ; then echo "MyVar contains data." ; else echo "MyVar is zero length" ; fi
+MyVar is zero length
+```
+
+有时候你需要知道一个字符串确切的长度。这虽然不是比较,但是也与比较相关。不幸的是,计算字符串的长度没有简单的方法。有很多种方法可以计算,但是我认为使用 `expr`(求值表达式)命令是相对最简单的一种。阅读 `expr` 的手册页可以了解更多相关知识。注意表达式中你检测的字符串或变量两边的引号不要省略。
+
+```
+[student@studentvm1 testdir]$ MyVar="" ; expr length "$MyVar"
+0
+[student@studentvm1 testdir]$ MyVar="How long is this?" ; expr length "$MyVar"
+17
+[student@studentvm1 testdir]$ expr length "We can also find the length of a literal string as well as a variable."
+70
+```
+
+关于比较操作符,在我们的脚本中使用了大量的检测两个字符串是否相等(例如,两个字符串是否实际上是同一个字符串)的操作。我使用的是非 POSIX 版本的比较表达式:
+
+```
+[student@studentvm1 testdir]$ Var1="Hello World" ; Var2="Hello World" ; if [ "$Var1" == "$Var2" ] ; then echo "Var1 matches Var2" ; else echo "Var1 and Var2 do not match." ; fi
+Var1 matches Var2
+[student@studentvm1 testdir]$ Var1="Hello World" ; Var2="Hello world" ; if [ "$Var1" == "$Var2" ] ; then echo "Var1 matches Var2" ; else echo "Var1 and Var2 do not match." ; fi
+Var1 and Var2 do not match.
+```
+
+在你自己的脚本中去试一下这些操作符。
+
+#### 数字比较操作符
+
+数字操作符用于两个数字参数之间的比较。像其他类操作符一样,大部分都很容易理解。
+
+操作符 | 描述
+---|---
+`arg1 -eq arg2` | 如果 `arg1` 等于 `arg2`,返回真值
+`arg1 -ne arg2` | 如果 `arg1` 不等于 `arg2`,返回真值
+`arg1 -lt arg2` | 如果 `arg1` 小于 `arg2`,返回真值
+`arg1 -le arg2` | 如果 `arg1` 小于或等于 `arg2`,返回真值
+`arg1 -gt arg2` | 如果 `arg1` 大于 `arg2`,返回真值
+`arg1 -ge arg2` | 如果 `arg1` 大于或等于 `arg2`,返回真值
+
+*图表 4: Bash 数字比较逻辑操作符*
+
+来看几个简单的例子。第一个示例设置变量 `$X` 的值为 1,然后检测 `$X` 是否等于 1。第二个示例中,`$X` 被设置为 0,所以比较表达式返回结果不为真值。
+
+```
+[student@studentvm1 testdir]$ X=1 ; if [ $X -eq 1 ] ; then echo "X equals 1" ; else echo "X does not equal 1" ; fi
+X equals 1
+[student@studentvm1 testdir]$ X=0 ; if [ $X -eq 1 ] ; then echo "X equals 1" ; else echo "X does not equal 1" ; fi
+X does not equal 1
+[student@studentvm1 testdir]$
+```
+
+自己来多尝试一下其他的。
+
+#### 杂项操作符
+
+这些杂项操作符展示一个 shell 选项是否被设置,或一个 shell 变量是否有值,但是它不显示变量的值,只显示它是否有值。
+
+操作符 | 描述
+---|---
+`-o optname` | 如果一个 shell 选项 `optname` 是启用的(查看内建在 Bash 手册页中的 set `-o` 选项描述下面的选项列表),则返回真值
+`-v varname` | 如果 shell 变量 `varname` 被设置了值(被赋予了值),则返回真值
+`-R varname` | 如果一个 shell 变量 `varname` 被设置了值且是一个名字引用,则返回真值
+
+*图表 5: 杂项 Bash 逻辑操作符*
+
+自己来使用这些操作符实践下。
+
+### 扩展
+
+Bash 支持非常有用的几种类型的扩展和命令替换。根据 Bash 手册页,Bash 有七种扩展格式。本文只介绍其中五种:`~` 扩展、算术扩展、路径名称扩展、大括号扩展和命令替换。
+
+#### 大括号扩展
+
+大括号扩展是生成任意字符串的一种方法。(下面的例子是用特定模式的字符创建大量的文件。)大括号扩展可以用于产生任意字符串的列表,并把它们插入一个用静态字符串包围的特定位置或静态字符串的两端。这可能不太好想象,所以还是来实践一下。
+
+首先,看一下大括号扩展的作用:
+
+```
+[student@studentvm1 testdir]$ echo {string1,string2,string3}
+string1 string2 string3
+```
+
+看起来不是很有用,对吧?但是用其他方式使用它,再来看看:
+
+```
+[student@studentvm1 testdir]$ echo "Hello "{David,Jen,Rikki,Jason}.
+Hello David. Hello Jen. Hello Rikki. Hello Jason.
+```
+
+这看起来貌似有点用了 — 我们可以少打很多字。现在试一下这个:
+
+```
+[student@studentvm1 testdir]$ echo b{ed,olt,ar}s
+beds bolts bars
+```
+
+我可以继续举例,但是你应该已经理解了它的用处。
+
+#### ~ 扩展
+
+资料显示,使用最多的扩展是波浪字符(`~`)扩展。当你在命令中使用它(如 `cd ~/Documents`)时,Bash shell 把这个快捷方式展开成用户的完整的家目录。
+
+使用这个 Bash 程序观察 `~` 扩展的作用:
+
+```
+[student@studentvm1 testdir]$ echo ~
+/home/student
+[student@studentvm1 testdir]$ echo ~/Documents
+/home/student/Documents
+[student@studentvm1 testdir]$ Var1=~/Documents ; echo $Var1 ; cd $Var1
+/home/student/Documents
+[student@studentvm1 Documents]$
+```
+
+#### 路径名称扩展
+
+路径名称扩展是展开文件通配模式为匹配该模式的完整路径名称的另一种说法,匹配字符使用 `?` 和 `*`。文件通配指的是在大量操作中匹配文件名、路径和其他字符串时用特定的模式字符产生极大的灵活性。这些特定的模式字符允许匹配字符串中的一个、多个或特定字符。
+
+* `?` — 匹配字符串中特定位置的一个任意字符
+* `*` — 匹配字符串中特定位置的 0 个或多个任意字符
+
+这个扩展用于匹配路径名称。为了弄清它的用法,请确保 `testdir` 是当前工作目录(`PWD`),先执行基本的列出清单命令 `ls`(我家目录下的内容跟你的不一样)。
+
+```
+[student@studentvm1 testdir]$ ls
+chapter6 cpuHog.dos dmesg1.txt Documents Music softlink1 testdir6 Videos
+chapter7 cpuHog.Linux dmesg2.txt Downloads Pictures Templates testdir
+testdir cpuHog.mac dmesg3.txt file005 Public testdir tmp
+cpuHog Desktop dmesg.txt link3 random.txt testdir1 umask.test
+[student@studentvm1 testdir]$
+```
+
+现在列出以 `Do`、`testdir/Documents` 和 `testdir/Downloads` 开头的目录:
+
+```
+Documents:
+Directory01 file07 file15 test02 test10 test20 testfile13 TextFiles
+Directory02 file08 file16 test03 test11 testfile01 testfile14
+file01 file09 file17 test04 test12 testfile04 testfile15
+file02 file10 file18 test05 test13 testfile05 testfile16
+file03 file11 file19 test06 test14 testfile09 testfile17
+file04 file12 file20 test07 test15 testfile10 testfile18
+file05 file13 Student1.txt test08 test16 testfile11 testfile19
+file06 file14 test01 test09 test18 testfile12 testfile20
+
+Downloads:
+[student@studentvm1 testdir]$
+```
+
+然而,并没有得到你期望的结果。它列出了以 `Do` 开头的目录下的内容。使用 `-d` 选项,仅列出目录而不列出它们的内容。
+
+```
+[student@studentvm1 testdir]$ ls -d Do*
+Documents Downloads
+[student@studentvm1 testdir]$
+```
+
+在两个例子中,Bash shell 都把 `Do*` 模式展开成了匹配该模式的目录名称。但是如果有文件也匹配这个模式,会发生什么?
+
+```
+[student@studentvm1 testdir]$ touch Downtown ; ls -d Do*
+Documents Downloads Downtown
+[student@studentvm1 testdir]$
+```
+
+因此所有匹配这个模式的文件也被展开成了完整名字。
+
+#### 命令替换
+
+命令替换是让一个命令的标准输出数据流被当做参数传给另一个命令的扩展形式,例如,在一个循环中作为一系列被处理的项目。Bash 手册页显示:“命令替换可以让你用一个命令的输出替换为命令的名字。”这可能不太好理解。
+
+命令替换有两种格式:\`command\` 和 `$(command)`。在更早的格式中使用反引号(\`),在命令中使用反斜杠(`\`)来保持它转义之前的文本含义。然而,当用在新版本的括号格式中时,反斜杠被当做一个特殊字符处理。也请注意带括号的格式打开个关闭命令语句都是用一个括号。
+
+我经常在命令行程序和脚本中使用这种能力,一个命令的结果能被用作另一个命令的参数。
+
+来看一个非常简单的示例,这个示例使用了这个扩展的两种格式(再一次提醒,确保 `testdir` 是当前工作目录):
+
+```
+[student@studentvm1 testdir]$ echo "Todays date is `date`"
+Todays date is Sun Apr 7 14:42:46 EDT 2019
+[student@studentvm1 testdir]$ echo "Todays date is $(date)"
+Todays date is Sun Apr 7 14:42:59 EDT 2019
+[student@studentvm1 testdir]$
+```
+
+`-seq` 工具用于一个数字序列:
+
+```
+[student@studentvm1 testdir]$ seq 5
+1
+2
+3
+4
+5
+[student@studentvm1 testdir]$ echo `seq 5`
+1 2 3 4 5
+[student@studentvm1 testdir]$
+```
+
+现在你可以做一些更有用处的操作,比如创建大量用于测试的空文件。
+
+```
+[student@studentvm1 testdir]$ for I in $(seq -w 5000) ; do touch file-$I ; done
+```
+
+`seq` 工具加上 `-w` 选项后,在生成的数字前面会用 0 补全,这样所有的结果都等宽,例如,忽略数字的值,它们的位数一样。这样在对它们按数字顺序进行排列时很容易。
+
+`seq -w 5000` 语句生成了 1 到 5000 的数字序列。通过把命令替换用于 `for` 语句,`for` 语句就可以使用该数字序列来生成文件名的数字部分。
+
+#### 算术扩展
+
+Bash 可以进行整型的数学计算,但是比较繁琐(你一会儿将看到)。数字扩展的语法是 `$((arithmetic-expression))` ,分别用两个括号来打开和关闭表达式。算术扩展在 shell 程序或脚本中类似命令替换;表达式结算后的结果替换了表达式,用于 shell 后续的计算。
+
+我们再用一个简单的用法来开始:
+
+```
+[student@studentvm1 testdir]$ echo $((1+1))
+2
+[student@studentvm1 testdir]$ Var1=5 ; Var2=7 ; Var3=$((Var1*Var2)) ; echo "Var 3 = $Var3"
+Var 3 = 35
+```
+
+下面的除法结果是 0,因为表达式的结果是一个小于 1 的整型数字:
+
+```
+[student@studentvm1 testdir]$ Var1=5 ; Var2=7 ; Var3=$((Var1/Var2)) ; echo "Var 3 = $Var3"
+Var 3 = 0
+```
+
+这是一个我经常在脚本或 CLI 程序中使用的一个简单的计算,用来查看在 Linux 主机中使用了多少虚拟内存。 `free` 不提供我需要的数据:
+
+```
+[student@studentvm1 testdir]$ RAM=`free | grep ^Mem | awk '{print $2}'` ; Swap=`free | grep ^Swap | awk '{print $2}'` ; echo "RAM = $RAM and Swap = $Swap" ; echo "Total Virtual memory is $((RAM+Swap))" ;
+RAM = 4037080 and Swap = 6291452
+Total Virtual memory is 10328532
+```
+
+我使用 \` 字符来划定用作命令替换的界限。
+
+我用 Bash 算术扩展的场景主要是用脚本检查系统资源用量后基于返回的结果选择一个程序运行的路径。
+
+### 总结
+
+本文是 Bash 编程语言系列的第二篇,探讨了 Bash 中文件、字符串、数字和各种提供流程控制逻辑的逻辑操作符还有不同种类的 shell 扩展。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/programming-bash-logical-operators-shell-expansions
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[lxbwolf](https://github.com/lxbwolf)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_women_computing_5.png?itok=YHpNs_ss (Women in computing and open source v5)
+[2]: http://www.both.org/?page_id=1183
+[3]: https://linux.cn/article-11552-1.html
diff --git a/published/20191024 Get sorted with sort at the command line.md b/published/20191024 Get sorted with sort at the command line.md
new file mode 100644
index 0000000000..55916bdcad
--- /dev/null
+++ b/published/20191024 Get sorted with sort at the command line.md
@@ -0,0 +1,240 @@
+[#]: collector: (lujun9972)
+[#]: translator: (lxbwolf)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11657-1.html)
+[#]: subject: (Get sorted with sort at the command line)
+[#]: via: (https://opensource.com/article/19/10/get-sorted-sort)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+在命令行用 sort 进行排序
+======
+
+> 在 Linux、BSD 或 Mac 的终端中使用 sort 命令,按自己的需求重新整理数据。
+
+
+
+如果你曾经用过数据表应用程序,你就会知道可以按列的内容对行进行排序。例如,如果你有一个费用列表,你可能希望对它们进行按日期或价格升序抑或按类别进行排序。如果你熟悉终端的使用,你不会仅为了排序文本数据就去使用庞大的办公软件。这正是 [sort][2] 命令的用处。
+
+### 安装
+
+你不必安装 `sort` ,因为它向来都包含在 [POSIX][3] 系统里。在大多数 Linux 系统中,`sort` 命令来自 GNU 组织打包的实用工具集合中。在其他的 POSIX 系统中,像 BSD 和 Mac,默认的 `sort` 命令不是 GNU 提供的,所以有一些选项可能不一样。本文中我尽量对 GNU 和 BSD 两者的实现都进行说明。
+
+### 按字母顺序排列行
+
+`sort` 命令默认会读取文件每行的第一个字符并对每行按字母升序排序后输出。两行中的第一个字符相同的情况下,对下一个字符进行对比。例如:
+
+```
+$ cat distro.list
+Slackware
+Fedora
+Red Hat Enterprise Linux
+Ubuntu
+Arch
+1337
+Mint
+Mageia
+Debian
+$ sort distro.list
+1337
+Arch
+Debian
+Fedora
+Mageia
+Mint
+Red Hat Enterprise Linux
+Slackware
+Ubuntu
+```
+
+使用 `sort` 不会改变原文件。`sort` 仅起到过滤的作用,所以如果你希望按排序后的格式保存数据,你需要用 `>` 或 `tee` 进行重定向。
+
+
+```
+$ sort distro.list | tee distro.sorted
+1337
+Arch
+Debian
+[...]
+$ cat distro.sorted
+1337
+Arch
+Debian
+[...]
+```
+
+### 按列排序
+
+复杂数据集有时候不止需要对每行的第一个字符进行排序。例如,假设有一个动物列表,每个都有其种和属,用可预见的分隔符分隔每一个“字段”(即数据表中的“单元格”)。这类由数据表导出的格式很常见,CSV(以逗号分隔的数据)后缀可以标识这些文件(虽然 CSV 文件不一定用逗号分隔,有分隔符的文件也不一定用 CSV 后缀)。以下数据作为示例:
+
+```
+Aptenodytes;forsteri;Miller,JF;1778;Emperor
+Pygoscelis;papua;Wagler;1832;Gentoo
+Eudyptula;minor;Bonaparte;1867;Little Blue
+Spheniscus;demersus;Brisson;1760;African
+Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
+Eudyptes;chrysocome;Viellot;1816;Southern Rockhopper
+Torvaldis;linux;Ewing,L;1996;Tux
+```
+
+对于这组示例数据,你可以用 `--field-separator` (在 BSD 和 Mac 用 `-t`,在 GNU 上也可以用简写 `-t` )设置分隔符为分号(因为该示例数据中是用分号而不是逗号,理论上分隔符可以是任意字符),用 `--key`(在 BSD 和 Mac 上用 `-k`,在 GNU 上也可以用简写 `-k`)选项指定哪个字段被排序。例如,对每行第二个字段进行排序(计数以 1 开头而不是 0):
+
+```
+sort --field-separator=";" --key=2
+Megadyptes;antipodes;Milne-Edwards;1880;Yellow-eyed
+Eudyptes;chrysocome;Viellot;1816;Sothern Rockhopper
+Spheniscus;demersus;Brisson;1760;African
+Aptenodytes;forsteri;Miller,JF;1778;Emperor
+Torvaldis;linux;Ewing,L;1996;Tux
+Eudyptula;minor;Bonaparte;1867;Little Blue
+Pygoscelis;papua;Wagler;1832;Gentoo
+```
+
+结果有点不容易读,但是 Unix 以构造命令的管道方式而闻名,所以你可以使用 `column` 命令美化输出结果。使用 GNU `column`:
+
+```
+$ sort --field-separator=";" \
+\--key=2 penguins.list | column --table --separator ";"
+Megadyptes antipodes Milne-Edwards 1880 Yellow-eyed
+Eudyptes chrysocome Viellot 1816 Southern Rockhopper
+Spheniscus demersus Brisson 1760 African
+Aptenodytes forsteri Miller,JF 1778 Emperor
+Torvaldis linux Ewing,L 1996 Tux
+Eudyptula minor Bonaparte 1867 Little Blue
+Pygoscelis papua Wagler 1832 Gentoo
+```
+
+对于初学者可能有点不好理解(但是写起来简单),BSD 和 Mac 上的命令选项:
+
+```
+$ sort -t ";" \
+-k2 penguins.list | column -t -s ";"
+Megadyptes antipodes Milne-Edwards 1880 Yellow-eyed
+Eudyptes chrysocome Viellot 1816 Southern Rockhopper
+Spheniscus demersus Brisson 1760 African
+Aptenodytes forsteri Miller,JF 1778 Emperor
+Torvaldis linux Ewing,L 1996 Tux
+Eudyptula minor Bonaparte 1867 Little Blue
+Pygoscelis papua Wagler 1832 Gentoo
+```
+
+当然 `-k` 不一定非要设为 `2`。任意存在的字段都可以被设为排序的键。
+
+### 逆序排列
+
+你可以用 `--reverse`(BSD/Mac 上用 `-r`,GNU 上也可以用简写 `-r`)选项来颠倒已经排好序的列表。
+
+```
+$ sort --reverse alphabet.list
+z
+y
+x
+w
+[...]
+```
+
+你也可以把输出结果通过管道传给命令 [tac][4] 来实现相同的效果。
+
+### 按月排序(仅 GNU 支持)
+
+理想情况下,所有人都按照 ISO 8601 标准来写日期:年、月、日。这是一种合乎逻辑的指定精确日期的方法,也可以很容易地被计算机理解。也有很多情况下,人类用其他的方式标注日期,包括用很名字随意的月份。
+
+幸运的是,GNU `sort` 命令能识别这种写法,并可以按月份的名称正确排序。使用 `--month-sort`(`-M`)选项:
+
+```
+$ cat month.list
+November
+October
+September
+April
+[...]
+$ sort --month-sort month.list
+January
+February
+March
+April
+May
+[...]
+November
+December
+```
+
+月份的全称和简写都可以被识别。
+
+### 人类可读的数字排序(仅 GNU 支持)
+
+另一个人类和计算机的常见混淆点是数字的组合。例如,人类通常把 “1024 kilobytes” 写成 “1KB”,因为人类解析 “1 KB” 比 “1024” 要容易且更快(数字越大,这种差异越明显)。对于计算机来说,一个 9 KB 的字符串要比诸如 1 MB 的字符串大(尽管 9 KB 是 1 MB 很小一部分)。GNU `sort` 命令提供了`--human-numeric-sort`(`-h`)选项来帮助正确解析这些值。
+
+```
+$ cat sizes.list
+2M
+12MB
+1k
+9k
+900
+7000
+$ sort --human-numeric-sort
+900
+7000
+1k
+9k
+2M
+12MB
+```
+
+有一些情况例外。例如,“16000 bytes” 比 “1 KB” 大,但是 `sort` 识别不了。
+
+```
+$ cat sizes0.list
+2M
+12MB
+16000
+1k
+$ sort -h sizes0.list
+16000
+1k
+2M
+12MB
+```
+
+逻辑上来说,这个示例中 16000 应该写成 16 KB,所以也不应该全部归咎于GNU `sort`。只要你确保数字的一致性,`--human-numeric-sort` 可以用一种计算机友好的方式解析成人类可读的数字。
+
+### 随机排序(仅 GNU 支持)
+
+有时候工具也提供了一些与设计初衷相悖的选项。某种程度上说,`sort` 命令提供对一个文件进行随机排序的能力没有任何意义。这个命令的工作流让这个特性变得很方便。你*可以*用其他的命令,像 [shuf][5] ,或者你可以用现在的命令添加一个选项。不管你认为它是一个臃肿的还是极具创造力的用户体验设计,GNU `sort` 命令提供了对文件进行随机排序的功能。
+
+最纯粹的随机排序格式选项是 `--random-sort` 或 `-R`(不要跟 `-r` 混淆,`-r` 是 `--reverse` 的简写)。
+
+```
+$ sort --random-sort alphabet.list
+d
+m
+p
+a
+[...]
+```
+
+每次对文件运行随机排序都会有不同的结果。
+
+### 结语
+
+GNU 和 BSD 的 `sort` 命令还有很多功能,所以花点时间去了解这些选项。你会惊异于 `sort` 的灵活性,尤其是当它和其他的 Unix 工具一起使用时。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/get-sorted-sort
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[lxbwolf](https://github.com/lxbwolf)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl "Coding on a computer"
+[2]: https://en.wikipedia.org/wiki/Sort_(Unix)
+[3]: https://en.wikipedia.org/wiki/POSIX
+[4]: https://opensource.com/article/19/9/tac-command
+[5]: https://www.gnu.org/software/coreutils/manual/html_node/shuf-invocation.html
diff --git a/published/20191028 6 signs you might be a Linux user.md b/published/20191028 6 signs you might be a Linux user.md
new file mode 100644
index 0000000000..42688e4e2b
--- /dev/null
+++ b/published/20191028 6 signs you might be a Linux user.md
@@ -0,0 +1,153 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11635-1.html)
+[#]: subject: (6 signs you might be a Linux user)
+[#]: via: (https://opensource.com/article/19/10/signs-linux-user)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Linux 资深用户的 6 大特征
+======
+
+> 如果你是 Linux 资深用户,则可能会有这些共同倾向。
+
+
+
+Linux 用户千差万别,但是我们许多人都有一些相同的习惯。你可能没有本文列出的任何特征,而且如果你是个 Linux 新用户,你可能还不能理解这些特征……
+
+下面是你可能是 Linux 用户的六个特征。
+
+### 1、理所当然,纪元始于 1970 年 1 月 1 日
+
+关于 Unix 计算机时钟为何在重置时总是将其设置回 1970-01-01 的传闻有很多。但有点令人感到乏味的事实是,Unix “纪元”是用于同步的通用且简单的参考点。例如,万圣节在儒略历中是今年的 304 日,但我们通常将该节日称为 “31 号”。我们知道指的是哪个月的 31 号,因为我们有个共同的参考点:我们知道万圣节在 10 月庆祝,而 10 月是一年中的第十个月,并且我们知道前面每一个月包含多少天。没有这些值,虽然我们可以使用传统的计时方法(如月相)来跟踪特殊的季节性事件,但是计算机显然不具备这种能力。
+
+计算机需要确定且明确定义的值,因此将值 `1970-01-01T00:00:00Z` 选择为 Unix 纪元的开始。每当 [POSIX][2] 计算机的时间不准确时,诸如网络时间协议(NTP)之类的服务就可以向其提供自 `1970-01-01T00:00:00Z` 以来的秒数,计算机可以将其转换为人类易于识别的日期。
+
+日期和时间是在计算中要追踪的著名的复杂事物,主要是因为几乎所有标准都有例外。一个月并不总是有 30 天,一年也不总是有 365 天,甚至每年有多少秒钟也往往会有所不同。如果你正在寻找一个有趣而令人沮丧的编程练习,那么请尝试编程一个可靠的日历应用程序!
+
+### 2、输入超过两个字母你就会觉得麻烦
+
+众所周知,最常见的 Unix 命令都超简短。除了 `cd`、`ls` 和 `mv` 之类的命令外,还有一个命令简直不能再短了:`w`(它根据 `/var/run/utmp` 文件显示当前谁登录了)。
+
+一方面,极短的命令似乎很不直观。新用户可能不会猜测到键入 `ls` 会列出目录。但是,一旦学习命令,它们肯定是越短越好。如果你整天都在终端上度过,那么你键入的击键次数越少就意味着你可以有更多的时间来完成工作。
+
+幸运的是,单字母命令并不太多,因此你可以使用大多数字母作为别名。例如,我经常使用 Emacs,以至于我觉得 `emacs` 的输入时间太长,因此通过将下面这行添加到 `.bashrc` 文件中,将其别名为 `e`:
+
+```
+alias e='emacs'
+```
+
+你也可以临时为命令添加别名。例如,如果你在解决网络问题时发现自己反复运行 [firewall-cmd][3],则可以为当前会话创建别名:
+
+```
+$ alias f='firewall-cmd'
+$ f
+usage: see firewall-cmd man page
+No option specified.
+```
+
+只要你打开着终端,你的别名就会一直存在。当终端一旦关闭,它便会被遗忘。
+
+### 3、做任何事都不应该单击两次以上
+
+Linux 用户喜欢效率。尽管并非每个 Linux 用户都总是急于完成工作,但 Linux 桌面中有一些旨在减少完成任务所需的操作数量的惯例。这里有些例子。
+
+* 在 KDE 文件管理器 Dolphin 中,单击即可打开文件或目录。假定如果要选择一个文件,则可以单击并拖动,也可以 `Ctrl + 点击`。这可能会使习惯于双击所有内容的用户感到困惑,但是一旦你尝试了单击操作,通常就无法返回费力的双击操作。
+* 在大多数 Linux 桌面上,单击鼠标中键可粘贴剪贴板的最新内容。
+* 在许多 Linux 桌面上,可以通过按 `Alt`、`Ctrl` 或 `Shift` 键来修改拖动动作。例如,`Alt + 拖动` 在 KDE 中移动窗口,而 GNOME 中的 `Ctrl + 拖动` 会复制文件而不是移动。
+
+### 4、任何操作你都不会执行三次以上,因为第三次时你已经将它自动化了
+
+请原谅我有点夸张,但是许多 Linux 用户期望他们的计算机比他们更努力地工作。虽然学习如何自动执行常见任务需要花费时间,但在 Linux 上它往往比在其它平台上更容易,因为 Linux 终端和 Linux 操作系统是如此紧密地集成在一起。最容易自动化的是你在终端中已经执行的操作,因为命令只是你在解释器中键入的字符串,而该解释器(终端)不会在乎你是手动键入字符串还是将其指向一个脚本。
+
+例如,如果你发现自己经常将一组文件从一个位置移动到另一个位置,则或许可以将相同的指令序列用作一个脚本,你可以使用单个命令来触发该脚本。假设你每天早上手动执行此操作:
+
+```
+$ cd Documents
+$ trash reports-latest.txt
+$ wget myserver.local/reports/daily/report-latest.txt
+$ cp report-latest.txt reports_daily/2019-31-10.log
+```
+
+这是一个简单的序列,但是每天重复一次并不是消磨时间的最有效方法。做一点点抽象,你可以使用一个简单的脚本将其自动化:
+
+```
+#!/bin/sh
+
+trash $HOME/Documents/reports-latest.txt
+
+wget myserver.local/reports/daily/report-latest.txt \
+ -P $HOME/Documents/udpates_daily/`date --iso-8601`.log
+
+cp $HOME/Documents/udpates_daily/`date --iso-8601`.log \
+ $HOME/Documents/reports-latest.txt
+```
+
+你可以把你的脚本叫做 `get-reports.sh` 并在每天早晨手动启动它,或者甚至可以将其输入到 crontab 中,以便计算机可以执行此任务而无需你进行任何干预。
+
+对于新用户来说,这可能会有点困扰,因为什么和什么是一体的并不总是很明显。例如,如果你经常发现自己打开图像并将其按比例缩小 50%,那么你可能习惯于执行以下操作:
+
+1. 打开你的照片查看器或编辑器
+2. 缩放图像
+3. 将图像导出为修改后的文件
+4. 关闭应用程序
+
+如果你一天要做几次,你可能会对这种重复感到厌倦。但是,由于你是在图形用户界面(GUI)中执行这些操作的,因此你需要知道如何对 GUI 编写脚本以使其自动化。某些应用程序,例如 [GIMP][4],具有丰富的脚本接口,但是其过程显然不同于仅修改一堆命令并将其存储到文件中那么简单。
+
+再说一次,有时在命令行中有与你在 GUI 中所做的等效的操作。将文档从一种文本格式转换为另一种格式可以使用 [Pandoc][5],处理图像可以使用 [Image Magick][6],音乐和视频也可以通过命令行进行编辑和转换,等等。最大的问题是你需要知道要查找什么,通常是学习新的(有时是复杂的)命令。但是,在终端中按比例缩小图像比在 GUI 中显然更简单:
+
+```
+#!/bin/sh
+
+convert "${1}" -scale 50% `basename "${1}" .jpg`_50.jpg
+```
+
+这些麻烦、重复的任务值得研究。你永远不知道你的工作让计算机做起来是有多么的简单和快捷!
+
+### 5、发行版之间跳来跳去
+
+我在家里是一个热情的 Slackware 用户,而在工作时是一个 RHEL 用户。实际上,这不是事实,我现在在工作时是 Fedora 用户。除了有时候我使用 CentOS,偶尔我还会运行 [Mageia][7]。
+
+![Debian on a PowerPC64 box, image CC BY SA Claudio Miranda][8]
+
+*运行在 PowerPC64 机器上的 Debian*
+
+发行版好不好无关紧要,成为 Linux 用户的极致乐趣之一是可以自由决定运行哪个发行版。乍一看,它们基本相同,令人耳目一新。但是根据你的心情,你可能更喜欢 CentOS 的稳定性而不是 Fedora 的不断更新,或者你可能有一天会真正享受 Mageia 的集中控制中心,然后又对原始的 [Debian][9] 配置文件进行模块化乐在其中,而有时你又会完全转向其他操作系统。
+
+![OpenBSD, image CC BY SA Claudio Miranda][10]
+
+*OpenBSD,不是 Linux 发行版*
+
+关键是,Linux 发行版是激情项目,成为其他人的开源激情的一部分很有趣。
+
+### 6、你对开源充满热情
+
+无论你的经验如何,如果你是 Linux 用户,那么你无疑会对开源充满热情。无论你是每天通过[共创艺术品] [11]还是代码来表达你的热情,还是将其升华到只在自由而自在的环境中完成工作,你都生活并构筑于开源之上。因为有了千千万万个你,所以有了开源社区,社区因你而变得更加丰富。
+
+有太多的东西我没有提到。作为 Linux 用户,还有什么可以出卖你的身份?让我们在评论中知道!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/signs-linux-user
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tux_linux_penguin_code_binary.jpg?itok=TxGxW0KY (Tux with binary code background)
+[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
+[3]: https://opensource.com/article/19/7/make-linux-stronger-firewalls
+[4]: https://www.gimp.org/
+[5]: https://opensource.com/article/19/5/convert-markdown-to-word-pandoc
+[6]: https://opensource.com/article/17/8/imagemagick
+[7]: http://mageia.org
+[8]: https://opensource.com/sites/default/files/uploads/debian.png (Debian on a PowerPC64 box)
+[9]: http://debian.org
+[10]: https://opensource.com/sites/default/files/uploads/openbsd.jpg (OpenBSD)
+[11]: http://freesvg.org
diff --git a/published/20191028 How to remove duplicate lines from files with awk.md b/published/20191028 How to remove duplicate lines from files with awk.md
new file mode 100644
index 0000000000..8a5148e708
--- /dev/null
+++ b/published/20191028 How to remove duplicate lines from files with awk.md
@@ -0,0 +1,222 @@
+[#]: collector: (lujun9972)
+[#]: translator: (lxbwolf)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11666-1.html)
+[#]: subject: (How to remove duplicate lines from files with awk)
+[#]: via: (https://opensource.com/article/19/10/remove-duplicate-lines-files-awk)
+[#]: author: (Lazarus Lazaridis https://opensource.com/users/iridakos)
+
+怎样使用 awk 删掉文件中重复的行
+======
+
+> 学习怎样使用 awk 的 `!visited[$0]++` 在不重新排序或改变原排列顺序的前提下删掉重复的行。
+
+
+
+假设你有一个文本文件,你需要删掉所有重复的行。
+
+### TL;DR
+
+*要保持原来的排列顺序*删掉重复行,使用:
+
+```
+awk '!visited[$0]++' your_file > deduplicated_file
+```
+
+### 工作原理
+
+这个脚本维护一个关联数组,索引(键)为文件中去重后的行,每个索引对应的值为该行出现的次数。对于文件的每一行,如果这行(之前)出现的次数为 0,则值加 1,并打印这行,否则值加 1,不打印这行。
+
+我之前不熟悉 `awk`,我想弄清楚这么短小的一个脚本是怎么实现的。我调研了下,下面是调研心得:
+
+* 这个 awk “脚本” `!visited[$0]++` 对输入文件的*每一行*都执行。
+* `visited[]` 是一个[关联数组][2](又名[映射][3])类型的变量。`awk` 会在第一次执行时初始化它,因此我们不需要初始化。
+* `$0` 变量的值是当前正在被处理的行的内容。
+* `visited[$0]` 通过与 `$0`(正在被处理的行)相等的键来访问该映射中的值,即出现次数(我们在下面设置的)。
+* `!` 对表示出现次数的值取反:
+ * 在 `awk` 中,[任意非零的数或任意非空的字符串的值是 `true`][4]。
+ * [变量默认的初始值为空字符串][5],如果被转换为数字,则为 0。
+ * 也就是说:
+ * 如果 `visited[$0]` 的值是一个比 0 大的数,取反后被解析成 `false`。
+ * 如果 `visited[$0]` 的值为等于 0 的数字或空字符串,取反后被解析成 `true` 。
+ * `++` 表示变量 `visited[$0]` 的值加 1。
+ * 如果该值为空,`awk` 自动把它转换为 `0`(数字) 后加 1。
+ * 注意:加 1 操作是在我们取到了变量的值之后执行的。
+
+总的来说,整个表达式的意思是:
+
+ * `true`:如果表示出现次数为 0 或空字符串
+ * `false`:如果出现的次数大于 0
+
+`awk` 由 [模式或表达式和一个与之关联的动作][6] 组成:
+
+```
+<模式/表达式> { <动作> }
+```
+
+如果匹配到了模式,就会执行后面的动作。如果省略动作,`awk` 默认会打印(`print`)输入。
+
+> 省略动作等价于 `{print $0}`。
+
+我们的脚本由一个 `awk` 表达式语句组成,省略了动作。因此这样写:
+
+```
+awk '!visited[$0]++' your_file > deduplicated_file
+```
+
+等于这样写:
+
+```
+awk '!visited[$0]++ { print $0 }' your_file > deduplicated_file
+```
+
+对于文件的每一行,如果表达式匹配到了,这行内容被打印到输出。否则,不执行动作,不打印任何东西。
+
+### 为什么不用 uniq 命令?
+
+`uniq` 命令仅能对相邻的行去重。这是一个示例:
+
+```
+$ cat test.txt
+A
+A
+A
+B
+B
+B
+A
+A
+C
+C
+C
+B
+B
+A
+$ uniq < test.txt
+A
+B
+A
+C
+B
+A
+```
+
+### 其他方法
+
+#### 使用 sort 命令
+
+我们也可以用下面的 [sort][7] 命令来去除重复的行,但是*原来的行顺序没有被保留*。
+
+
+```
+sort -u your_file > sorted_deduplicated_file
+```
+
+#### 使用 cat + sort + cut
+
+上面的方法会产出一个去重的文件,各行是基于内容进行排序的。[通过管道连接命令][8]可以解决这个问题。
+
+
+```
+cat -n your_file | sort -uk2 | sort -nk1 | cut -f2-
+```
+
+**工作原理**
+
+假设我们有下面一个文件:
+
+```
+abc
+ghi
+abc
+def
+xyz
+def
+ghi
+klm
+```
+
+`cat -n test.txt` 在每行前面显示序号:
+
+```
+1 abc
+2 ghi
+3 abc
+4 def
+5 xyz
+6 def
+7 ghi
+8 klm
+```
+
+`sort -uk2` 基于第二列(`k2` 选项)进行排序,对于第二列相同的值只保留一次(`u` 选项):
+
+```
+1 abc
+4 def
+2 ghi
+8 klm
+5 xyz
+```
+
+`sort -nk1` 基于第一列排序(`k1` 选项),把列的值作为数字来处理(`-n` 选项):
+
+```
+1 abc
+2 ghi
+4 def
+5 xyz
+8 klm
+```
+
+最后,`cut -f2-` 从第二列开始打印每一行,直到最后的内容(`-f2-` 选项:留意 `-` 后缀,它表示这行后面的内容都包含在内)。
+
+```
+abc
+ghi
+def
+xyz
+klm
+```
+
+### 参考
+
+* [GNU awk 用户手册][9]
+* [awk 中的数组][2]
+* [Awk — 真值][4]
+* [Awk 表达式][5]
+* [Unix 怎么删除文件中重复的行?][10]
+* [不用排序去掉重复的行(去重)][11]
+* ['!a[$0]++' 工作原理][12]
+
+以上为全文。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/remove-duplicate-lines-files-awk
+
+作者:[Lazarus Lazaridis][a]
+选题:[lujun9972][b]
+译者:[lxbwolf](https://github.com/lxbwolf)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/iridakos
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl (Coding on a computer)
+[2]: http://kirste.userpage.fu-berlin.de/chemnet/use/info/gawk/gawk_12.html
+[3]: https://en.wikipedia.org/wiki/Associative_array
+[4]: https://www.gnu.org/software/gawk/manual/html_node/Truth-Values.html
+[5]: https://ftp.gnu.org/old-gnu/Manuals/gawk-3.0.3/html_chapter/gawk_8.html
+[6]: http://kirste.userpage.fu-berlin.de/chemnet/use/info/gawk/gawk_9.html
+[7]: http://man7.org/linux/man-pages/man1/sort.1.html
+[8]: https://stackoverflow.com/a/20639730/2292448
+[9]: https://www.gnu.org/software/gawk/manual/html_node/
+[10]: https://stackoverflow.com/questions/1444406/how-can-i-delete-duplicate-lines-in-a-file-in-unix
+[11]: https://stackoverflow.com/questions/11532157/remove-duplicate-lines-without-sorting
+[12]: https://unix.stackexchange.com/questions/159695/how-does-awk-a0-work/159734#159734
+[13]: https://opensource.com/sites/default/files/uploads/duplicate-cat.jpg (Duplicate cat)
+[14]: https://iridakos.com/about/
+[15]: http://creativecommons.org/licenses/by-nc/4.0/
diff --git a/published/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md b/published/201911/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md
similarity index 100%
rename from published/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md
rename to published/201911/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md
diff --git a/published/201911/20181109 Must-Have Tools for Writers on the Linux Platform.md b/published/201911/20181109 Must-Have Tools for Writers on the Linux Platform.md
new file mode 100644
index 0000000000..c82c4f1fe2
--- /dev/null
+++ b/published/201911/20181109 Must-Have Tools for Writers on the Linux Platform.md
@@ -0,0 +1,101 @@
+Linux 平台上的写作者必备工具
+======
+
+
+
+我从事作家已有 20 多年了。我撰写了数千篇有关各种技术主题的文章和指南,并撰写了 40 多本小说。因此,书面文字不仅对我很重要,还很熟悉,成为了我的第二种自然交流的方式。在过去的二十年中(而且还在继续),我几乎都是在 Linux 平台上完成的所有工作。我必须承认,在早期,这并不总是那么容易。格式并不总是与编辑器所需要的相吻合,在某些情况下,开源平台根本没有完成工作所需的必要工具。
+
+那时已经过去,现在已经不同了。
+
+Linux 演进和基于 Web 的工具的相得益彰使得它可以让任何写作者都能在 Linux 上完成工作(并且做得很好)。但是你需要什么工具?你可能会惊讶地发现,在某些情况下,使用 100% 开源的工具无法有效完成这项工作。不过即使如此,工作总是可以完成的。让我们来看看我作为技术作家和小说作者一直使用的工具。我将通过小说和非小说类的写作过程来概述这一点(因为过程不同,需要特定的工具)。
+
+对认真的 Linux 硬核用户预先做个预警。很久以前,我就放弃了使用 LaTeX 和 DocBook 之类的工具进行写作。为什么?因为对我而言,重点必须放在内容上,而不是过程上。当你面临最后期限时,必须以效率为先。
+
+### 非小说类
+
+我们将从非虚构写作入手,因为这是两者中较简单的过程。为了编写技术指南,我与不同的编辑人员合作,并且在某些情况下,必须将内容复制/粘贴到 CMS 中。但是就像我的小说一样,整个过程总是从 Google 云端硬盘开始。在这一点上,许多开源纯粹主义者会转身走开。不用担心,你始终可以选择将所有文件保存在本地,也可以使用更开放友好的云服务(例如 [Zoho][1] 或 [nextCloud][2])。
+
+为什么要从云端开始?多年来,我发现我需要能够随时随地访问那些内容。最简单的解决方案是迁移到云上。我对丢失工作成果这件事也很偏执。为此,我使用了 [Insync][3] 之类的工具来使我的 Google 云端硬盘与桌面保持同步。有了桌面同步功能,我知道我的工作成果总是有备份,以防万一 Google 云端硬盘出了问题。
+
+对于那些我必须与之一起将内容输入到内容管理系统(CMS)的客户,该过程到此结束。我可以直接从 Google 文档复制/粘贴到 CMS 中,并完成此操作。当然,对于技术内容,总是涉及到屏幕截图。为此,我使用 [Gimp][4],它使得截取屏幕截图变得简单:
+
+![screenshot with Gimp][6]
+
+*图 1:使用 Gimp 截屏。*
+
+1. 打开 Gimp。
+2. 单击“文件>创建>屏幕快照”。
+3. 选择单个窗口、整个屏幕或要抓取的区域(图 1)。
+4. 单击“抓取”。
+
+我的大多数客户倾向于使用 Google 文档,因为我可以共享文件夹,以便他们可以可靠地访问该内容。我有一些无法使用 Google 文档的客户,因此我必须将文件下载为可以使用的格式。为此,我要做的是下载 .odt 格式,以 [LibreOffice][8] 打开文档(图 2),根据需要设置格式,保存为客户所需的格式,然后发送文档。
+
+![Google Doc][10]
+
+*图 2:在 LibreOffice 中打开我下载的 Google 文档。*
+
+非小说类作品这样就行了。
+
+### 小说类
+
+这里会稍微变得有点复杂。开始的步骤是相同的,因为我总是在 Google 文档中写小说的每个初稿。完成后,我将文件下载到 Linux 桌面,在 LibreOffice 中打开文件,根据需要设置格式,然后另存为编辑器支持的文件类型(不幸的是,这意味着是 .docx)。
+
+该过程的下一步变得有些琐碎。我的编辑更喜欢使用注释来跟踪更改(因为这使我们俩阅读文档和做出更改一样容易)。因此,一个 60k 的 word 文档可以包含成百上千的注释,这会使 LibreOffice 慢的像爬一样。从前,你可以增加用于文档的内存,但是从 LibreOffice 6 开始,这不再可行。这意味着任何较大的、像小说一样长的、带有大量注释的文档都将无法使用。因此,我不得不采取一些极端的措施,使用 [WPS Office][11](图 3)。尽管这不是开源解决方案,但 WPS Office 在文档中包含大量注释的情况下做得很好,因此无需处理 LibreOffice 所带来的麻烦(当处理带有数百个注释的大型文件时)。
+
+![comments][13]
+
+*图 3:WPS 可以轻松处理大量注释。*
+
+一旦我和我的编辑完成了对书的编辑(所有评论都已删除),我就可以在 LibreOffice 中打开文件进行最终格式化。格式化完成后,我将文件保存为 .html 格式,然后以 [Calibre][14] 打开文件以将文件导出为 .mobi 和 .epub 格式。
+
+对于希望在 Amazon、Barnes&Noble、Smashwords 或其他平台上出版的任何人,Calibre 都是必备工具。Caliber 比其他类似解决方案更好地方是,它使你可以直接编辑 .epub 文件(图 4)。对于 Smashword 来说,这是绝对必要的(因为导出过程将添加 Smashwords 转换工具上不接受的元素)。
+
+![Calibre][16]
+
+*图 4:直接在 Calibre 中编辑 epub 文件。*
+
+写作过程结束后(或有时在等待编辑完成一校时),我将开始为书制作封面。该任务完全在 Gimp 中处理(图 5)。
+
+![Using Gimp][19]
+
+*图 5:在 Gimp 中创建 POTUS 的封面。*
+
+这样就完成了在 Linux 平台上创建小说的过程。由于文档的篇幅以及某些编辑人员的工作方式,与创建非小说类的过程相比,它可能会变得有些复杂,但这远没有挑战性。实际上,在 Linux 上创建小说与其他平台一样简单(并且更可靠)。
+
+### 希望这可以帮助你
+
+我希望这可以帮助有抱负的作家有信心在 Linux 平台上进行写作。还有许多其他工具可供使用,但是多年来我在这里列出的工具很好地服务了我。而且,尽管我确实使用了几个专有的工具,但只要它们在 Linux 上都能正常运行,我觉得是可以的。
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/learn/2018/11/must-have-tools-writers-linux-platform
+
+作者:[Jack Wallen][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.linux.com/users/jlwallen
+[b]: https://github.com/lujun9972
+[1]: https://www.zoho.com/
+[2]: https://nextcloud.com/
+[3]: https://www.insynchq.com
+[4]: https://www.gimp.org/
+[5]: /files/images/writingtools1jpg
+[6]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_1.jpg (screenshot with Gimp)
+[7]: /licenses/category/used-permission
+[8]: https://www.libreoffice.org/
+[9]: /files/images/writingtools2jpg
+[10]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_2.jpg (Google Doc)
+[11]: https://www.wps.com/en-US/
+[12]: /files/images/writingtools3jpg
+[13]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_3.jpg (comments)
+[14]: https://calibre-ebook.com/
+[15]: /files/images/writingtools4jpg
+[16]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_4.jpg (Calibre)
+[17]: /licenses/category/creative-commons-zero
+[18]: /files/images/writingtools5jpg
+[19]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_5.jpg (Using Gimp)
+[20]: https://training.linuxfoundation.org/training/introduction-to-open-source-development-git-and-linux/?utm_source=linux.com&utm_medium=article&utm_campaign=lfd201
diff --git a/published/201911/20190328 Can Better Task Stealing Make Linux Faster.md b/published/201911/20190328 Can Better Task Stealing Make Linux Faster.md
new file mode 100644
index 0000000000..338343daee
--- /dev/null
+++ b/published/201911/20190328 Can Better Task Stealing Make Linux Faster.md
@@ -0,0 +1,77 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11607-1.html)
+[#]: subject: (Can Better Task Stealing Make Linux Faster?)
+[#]: via: (https://www.linux.com/blog/can-better-task-stealing-make-linux-faster)
+[#]: author: (Oracle )
+
+更好的任务窃取可以使 Linux 更快吗?
+======
+
+
+
+> Oracle Linux 内核开发人员 Steve Sistare 参与了这场有关内核调度程序改进的讨论。
+
+### 通过可扩展的任务窃取进行负载平衡
+
+Linux 任务调度程序通过将唤醒的任务推送到空闲的 CPU,以及在 CPU 空闲时从繁忙的 CPU 中拉取任务来平衡整个系统的负载。在大型系统上的推送侧和拉取侧,有效的伸缩都是挑战。对于拉取,调度程序搜索连续的更大范围中的所有 CPU,直到找到过载的 CPU,然后从最繁忙的组中拉取任务。这代价非常昂贵,在大型系统上要花费 10 到 100 微秒,因此搜索时间受到平均空闲时间的限制,并且某些范围不会被搜索。并非总能达到平衡,而且闲置的 CPU 依旧闲置。
+
+我实现了一种备用机制,该机制在 `idle_balance()` 中的现有搜索中自身受限并且没有找到之后被调用。我维护了一个过载的 CPU 的位图,当可运行的 CFS 任务计数超过 1 时,CPU 会设置该位。这个位图是稀疏的,每个高速缓存线的有效位数量有限。当许多线程同时设置、清除和访问元素时,这可以减少缓存争用。每个末级缓存都有一个位图。当 CPU 空闲时,它将搜索该位图以查找第一个具有可迁移任务的过载 CPU,然后将其窃取。这种简单的窃取会比单独的 `idle_balance()` 产生更高的 CPU 利用率,因为该搜索的成本很便宜,花费 1 到 2 微秒,因此每次 CPU 即将空闲时都可以调用它。窃取不会减轻全局最繁忙的队列的负担,但是它比根本不执行任何操作要好得多。
+
+### 结果
+
+偷窃仅在调度程序代码中占用少量 CPU 开销即可提高利用率。在以下实验中,以不同数量的组(每个组 40 个任务)运行 hackbench,并对每次运行结果显示 `/proc/schedstat` 中的增量(按 CPU 平均),并增加了这些非标准的统计信息:
+
+* `%find`:在旧函数和新函数中花费的时间百分比,这些函数用于搜索空闲的 CPU 和任务以窃取并设置过载的 CPU 位图。
+* `steal`:任务从另一个 CPU 窃取的次数。经过的时间增加了 8% 到 36%,最多增加了 0.4% 的发现时间。
+
+![load balancing][1]
+
+如下图的绿色曲线所示,新内核的 CPU 繁忙利用率接近 100%,作为比较的基线内核是橙色曲线:
+
+![][3]
+
+根据负载的不同,窃取可将 Oracle 数据库 OLTP 性能提高多达 9%,并且我们已经看到 MySQL、Pgsql、gcc、Java 和网络方面有了一些不错的改进。通常,窃取对上下文切换率高的工作负载最有帮助。
+
+### 代码
+
+截至撰写本文时,这项工作尚未完成,但最新的修补程序系列位于 [https://lkml.org/lkml/2018/12/6/1253][4]。如果你的内核是使用 `CONFIG_SCHED_DEBUG=y` 构建的,则可以使用以下命令验证其是否包含窃取优化:
+
+```
+# grep -q STEAL /sys/kernel/debug/sched_features && echo Yes
+Yes
+```
+
+如果要尝试使用,请注意,对于具有 2 个以上 NUMA 节点的系统,禁用了窃取功能,因为 hackbench 在此类系统上发生了回归,正如我在 [https://lkml.org/lkml/2018/12/6/1250][5] 中解释的那样。但是,我怀疑这种影响是特定于 hackbench 的,并且窃取将有助于多节点系统上的其他工作负载。要尝试使用它,请用内核参数 `sched_steal_node_limit=8`(或更大)重新启动。
+
+### 进一步工作
+
+在将基本盗用算法推向上游之后,我正在考虑以下增强功能:
+
+* 如果在末级缓存中进行窃取找不到候选者,在 LLC 和 NUMA 节点之间进行窃取。
+* 维护稀疏位图以标识 RT 调度类中的偷窃候选者。当前 `pull_rt_task()` 搜索所有运行队列。
+* 从 `idle_balance()` 中删除核心和套接字级别,因为窃取会处理这些级别。当支持跨 LLC 窃取时,完全删除 `idle_balance()`。
+* 维护位图以标识空闲核心和空闲 CPU,以实现推平衡。
+
+这篇文章最初发布于 [Oracle Developers Blog][6]。
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/can-better-task-stealing-make-linux-faster
+
+作者:[Oracle][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.linux.com/author/oracle/
+[b]: https://github.com/lujun9972
+[1]: https://lcom.static.linuxfound.org/sites/lcom/files/linux-load-balancing.png (load balancing)
+[3]: https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/b7a700fe-edc3-4ea0-876a-c91e1850b59b/Image/00c074f4282bcbaf0c10dd153c5dfa76/steal_graph.png
+[4]: https://lkml.org/lkml/2018/12/6/1253
+[5]: https://lkml.org/lkml/2018/12/6/1250
+[6]: https://blogs.oracle.com/linux/can-better-task-stealing-make-linux-faster
diff --git a/published/20190404 Why blockchain (might be) coming to an IoT implementation near you.md b/published/201911/20190404 Why blockchain (might be) coming to an IoT implementation near you.md
similarity index 100%
rename from published/20190404 Why blockchain (might be) coming to an IoT implementation near you.md
rename to published/201911/20190404 Why blockchain (might be) coming to an IoT implementation near you.md
diff --git a/published/20190610 Why containers and Kubernetes have the potential to run almost anything.md b/published/201911/20190610 Why containers and Kubernetes have the potential to run almost anything.md
similarity index 100%
rename from published/20190610 Why containers and Kubernetes have the potential to run almost anything.md
rename to published/201911/20190610 Why containers and Kubernetes have the potential to run almost anything.md
diff --git a/published/201911/20190718 What you need to know to be a sysadmin.md b/published/201911/20190718 What you need to know to be a sysadmin.md
new file mode 100644
index 0000000000..02361c4766
--- /dev/null
+++ b/published/201911/20190718 What you need to know to be a sysadmin.md
@@ -0,0 +1,122 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11608-1.html)
+[#]: subject: (What you need to know to be a sysadmin)
+[#]: via: (https://opensource.com/article/19/7/be-a-sysadmin)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+你需要知道什么才能成为系统管理员?
+======
+
+> 通过获得这些起码的能力,开始你的系统管理员职业。
+
+
+
+昔日的系统管理员整天都在调教用户和摆弄服务器,一天的时间都奔波在几百米长的电缆之间。随着云计算、容器和虚拟机的复杂性的增加,而今依然如此。
+
+以外行人来看,很难准确确定系统管理员的确切职能,因为他们在许多地方都扮演着一个不起眼的角色。没人能在培训中知道自己工作中所需要的一切知识,但是每个人其实都需要一个坚实的基础。如果你想走上系统管理的道路,那么这是你个人自学或在正式培训中应重点关注的内容。
+
+### Bash
+
+当你学习 Bash Shell 时,你学习的不仅是 Bash Shell,你学习的也是 Linux、BSD、MacOS 甚至Windows(在适当条件下)的通用界面。你将了解语法的重要性,因此可以快速适应思科路由器的命令行或微软 PowerShell 等系统,最终你甚至可以学习更强大的语言,如 Python 或 Go。而且,你还会开始进行程序性思考,以便可以分析复杂的问题并将其分解为单个组件,这很关键,因为这就是系统(例如互联网、组织的内部网、Web 服务器、备份解决方案)是如何设计的。
+
+不止于此,还有更多。
+
+由于最近 DevOps 和[容器][2]的发展趋势,了解 Bash shell 变得尤为重要。你的系统管理员职业可能会将你带入一个视基础设施为代码的世界,这通常意味着你必须了解脚本编写的基础知识、[基于 YAML][3]配置的结构,以及如何与[容器][5](运行在[沙盒文件][6]内部的微型 Linux 系统)[交互][4]。你会知道 Bash 是高效管理激动人心的开源技术的门户,因此请进入 [Bash][7] 世界吧。
+
+#### 资源
+
+有很多方法可以在 Bash shell 中进行练习。
+
+尝试一下[便携式 Linux 发行版][8]。你无需安装 Linux 即可使用 Linux,因此,请拿一块闲置的 U 盘,花个晚上或周末的空闲时光,来适应基于文本的界面。
+
+这里有[几篇很棒的][10] [Bash 文章][9]。
+
+要注意的是 Bash 练习的关键在于要练习,你必须有要做的练习才行。而且,在你知道如何使用 Bash 之前,你可能不知道该练习什么。如果是这样,请去 Over The Wire 玩一下 [Bandit][11] 游戏。这是一款针对绝对初学者的游戏,具有 34 个级别的交互式基本技巧,可让你熟悉 Linux shell。
+
+### Web 服务器设置
+
+一旦你习惯了 Bash,你应该尝试设置一个 Web 服务器。并不是所有的系统管理员都会四处设置 Web 服务器甚至维护 Web 服务器,但是你在安装和启动 HTTP 守护程序、配置 Apache 或 Nginx,设置[正确权限][12]和[配置防火墙][13]时所掌握的技能是你每天都需要使用的技能。经过一些努力,你可能会开始注意到自己的某些工作模式。在尝试管理可用于生产环境的软件和硬件之前,你可能认为某些概念是理所当然的,而你在成为新手的管理员角色时,将不再受到它们的影响。起初这可能会令人沮丧,因为每个人都喜欢在自己做好所做的事情,但这实际上是一件好事。让自己接触新技能,那就是你学习的方式。
+
+此外,你在第一步中付出的努力越多,最终当你在默认的 index.html 上看到胜利的“it works!”就越甜蜜!
+
+#### 资源
+
+David Both 撰写了有关 [Apache Web 服务器][14]配置的出色文章。值得一提的是,请逐步阅读他的后续文章,其中介绍了如何在一台计算机上[托管多个站点][15]。
+
+### DHCP
+
+动态主机配置协议(DHCP)是为网络上的设备分配 IP 地址的系统。在家里,ISP(互联网服务提供商)支持的调制解调器或路由器可能内置了 DHCP 服务器,因此可能不在你的权限范围内。如果你曾经登录家用路由器来调整 IP 地址范围或为某些网络设备设置了静态地址,那么你至少对该概念有所了解。你可能会将其理解为对网络上的设备分配了一种 IP 地址形式的电话号码,并且你可能会意识到计算机之间通过广播发送到特定 IP 地址的消息彼此进行通信。消息标头由路径上的路由器读取,每个消息标头都将消息定向到路径上的第二个逻辑路由器,以达到其最终目标。
+
+即使你了解了这些概念,要从对 DHCP 的基本了解再进一步是架设 DHCP 服务器。安装和配置自己的 DHCP 服务器可能会导致家庭网络中的 DHCP 冲突(如果可以的话,请尽量避免这样做,因为它肯定会干掉你的网络,直到解决为止),要控制地址的分配、创建子网,并监控连接和租赁时间。
+
+更重要的是,设置 DHCP 并尝试不同的配置有助于你了解网络之间的关系。你会了解网络如何在数据传输中表示“分区”,以及必须采取哪些步骤才能将信息从一个网络传递到另一个。这对于系统管理员来说至关重要,因为网络肯定是工作中最重要的方面之一。
+
+#### 资源
+
+在运行自己的 DHCP 服务器之前,请确保家庭路由器(如果有)中的 DHCP 服务器处于非活动状态。一旦启动并运行了 DHCP 服务器,请阅读 Archit Modi 的[网络命令指南][16],以获取有关如何探索网络的提示。
+
+### 网络电缆
+
+这听起来很普通,但是熟悉网络电缆的工作方式不仅使你的周末变得非常有趣,而且还使你对数据是如何通过缆线的得到了全新的了解。最好的学习方法是去当地的业余爱好商店并购买五类线剥线钳和压线钳以及一些五类线水晶头。然后回家,拿一根备用的以太网电缆,切断水晶头,花一些时间重新制作网线接头,将电缆重新投入使用。
+
+解决了这个难题后,请再做一次,这次创建一条有效的[交叉电缆][17]。
+
+你现在应该还在沉迷于有关电缆管理。如果你有些强迫症,喜欢沿着地板线或桌子的边缘整齐地排列电缆,或者将电缆绑在一起以保持它们的整齐有序,那么就可以使自己免受永久混乱的电缆困扰。你一开始可能不会理解这样做的必要性,但是当你第一次走进服务器机房时,你会马上知道原因。
+
+### Ansible
+
+[Ansible][18] 是配置管理软件,它在系统管理员和 DevOps 之间架起了一座桥梁。系统管理员使用 Ansible 来配置全新安装的操作系统并在计算机上维护特定的状态。DevOps 使用 Ansible 减少了在工具上花费的时间和精力,从而在开发上可以花费更多的时间和精力。作为系统管理员培训的一部分,你应该学习 Ansible,并着眼于 DevOps 实践,因为 DevOps 现在开创的大多数功能将最终成为将来系统管理中工作流的一部分。
+
+Ansible 的好处是你可以立即开始使用它。它是跨平台的,并且可以向上和向下缩放。对于单用户计算机, Ansible 可能是小题大做,但是话又说回来,Ansible 可能会改变你启动虚拟机的方式,或者可以帮助你同步家庭或[家庭实验室][19]中所有计算机的状态。
+
+
+#### 资源
+
+阅读 Jay LaCroix 的[如何使用 Ansible 管理工作站配置][20]中的典型介绍,以轻松地在日常之中开始使用 Ansible。
+
+### 破坏
+
+由于用户的错误、软件的错误、管理员(就是你!)的错误以及许多其他因素,计算机上会出现问题。无法预测将要失败的原因,因此你的个人系统管理员培训制度的一部分应该是破坏你设置的系统,直到它们失败为止。你自己的实验室基础设施越是脆弱,发现弱点的可能性就越大。而且,你越是经常修复这些弱点,你对解决问题的能力就越有信心。
+
+除了严格设置所有常见的软件和硬件之外,作为系统管理员的主要工作是查找解决方案。有时候,你可能会遇到职位描述之外的问题,甚至可能无法解决,但这完全取决于你的解决方法。
+
+现在,你越多地折腾并努力加以解决,则以系统管理员的身份进行的准备就越充分。
+
+你是系统管理员吗?你是否希望自己为更好的任务做好准备?在下面的评论中写下它们!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/7/be-a-sysadmin
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux11x_cc.png?itok=XMDOouJR (People work on a computer server with devices)
+[2]: https://opensource.com/article/19/6/kubernetes-dump-truck
+[3]: https://www.redhat.com/sysadmin/yaml-tips
+[4]: https://opensource.com/article/19/6/how-ssh-running-container
+[5]: https://opensource.com/resources/what-are-linux-containers
+[6]: https://opensource.com/article/18/11/behind-scenes-linux-containers
+[7]: https://opensource.com/article/18/7/admin-guide-bash
+[8]: https://opensource.com/article/19/6/linux-distros-to-try
+[9]: https://opensource.com/tags/bash
+[10]: https://www.redhat.com/sysadmin/managing-files-linux-terminal
+[11]: http://overthewire.org/wargames/bandit
+[12]: https://opensource.com/article/19/6/understanding-linux-permissions
+[13]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd
+[14]: https://opensource.com/article/18/2/how-configure-apache-web-server
+[15]: https://opensource.com/article/18/3/configuring-multiple-web-sites-apache
+[16]: https://opensource.com/article/18/7/sysadmin-guide-networking-commands
+[17]: https://en.wikipedia.org/wiki/Ethernet_crossover_cable
+[18]: https://opensource.com/sitewide-search?search_api_views_fulltext=ansible
+[19]: https://opensource.com/article/19/6/create-centos-homelab-hour
+[20]: https://opensource.com/article/18/3/manage-workstation-ansible
diff --git a/published/20190801 Linux permissions 101.md b/published/201911/20190801 Linux permissions 101.md
similarity index 100%
rename from published/20190801 Linux permissions 101.md
rename to published/201911/20190801 Linux permissions 101.md
diff --git a/published/20190822 11 Essential Keyboard Shortcuts Google Chrome-Chromium Users Should Know.md b/published/201911/20190822 11 Essential Keyboard Shortcuts Google Chrome-Chromium Users Should Know.md
similarity index 100%
rename from published/20190822 11 Essential Keyboard Shortcuts Google Chrome-Chromium Users Should Know.md
rename to published/201911/20190822 11 Essential Keyboard Shortcuts Google Chrome-Chromium Users Should Know.md
diff --git a/published/20190826 How RPM packages are made- the source RPM.md b/published/201911/20190826 How RPM packages are made- the source RPM.md
similarity index 100%
rename from published/20190826 How RPM packages are made- the source RPM.md
rename to published/201911/20190826 How RPM packages are made- the source RPM.md
diff --git a/published/20190828 Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word.md b/published/201911/20190828 Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word.md
similarity index 100%
rename from published/20190828 Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word.md
rename to published/201911/20190828 Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word.md
diff --git a/published/20190902 How RPM packages are made- the spec file.md b/published/201911/20190902 How RPM packages are made- the spec file.md
similarity index 100%
rename from published/20190902 How RPM packages are made- the spec file.md
rename to published/201911/20190902 How RPM packages are made- the spec file.md
diff --git a/published/20190905 Building CI-CD pipelines with Jenkins.md b/published/201911/20190905 Building CI-CD pipelines with Jenkins.md
similarity index 100%
rename from published/20190905 Building CI-CD pipelines with Jenkins.md
rename to published/201911/20190905 Building CI-CD pipelines with Jenkins.md
diff --git a/published/20190906 6 Open Source Paint Applications for Linux Users.md b/published/201911/20190906 6 Open Source Paint Applications for Linux Users.md
similarity index 100%
rename from published/20190906 6 Open Source Paint Applications for Linux Users.md
rename to published/201911/20190906 6 Open Source Paint Applications for Linux Users.md
diff --git a/published/20190912 How to fix common pitfalls with the Python ORM tool SQLAlchemy.md b/published/201911/20190912 How to fix common pitfalls with the Python ORM tool SQLAlchemy.md
similarity index 100%
rename from published/20190912 How to fix common pitfalls with the Python ORM tool SQLAlchemy.md
rename to published/201911/20190912 How to fix common pitfalls with the Python ORM tool SQLAlchemy.md
diff --git a/published/201911/20191007 7 Java tips for new developers.md b/published/201911/20191007 7 Java tips for new developers.md
new file mode 100644
index 0000000000..c2c90f8679
--- /dev/null
+++ b/published/201911/20191007 7 Java tips for new developers.md
@@ -0,0 +1,215 @@
+[#]: collector: (lujun9972)
+[#]: translator: (robsean)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11620-1.html)
+[#]: subject: (7 Java tips for new developers)
+[#]: via: (https://opensource.com/article/19/10/java-basics)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+给新手 Java 开发者的 7 点提示
+======
+
+> 如果你才刚开始学习 Java 编程,这里有七个你需要知道的基础知识。
+
+
+
+Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Java 的最大优势是,它运行在一个 Java 虚拟机(JVM)中,这是一个翻译 Java 代码为与操作系统兼容的字节码的层。只要有 JVM 存在于你的操作系统上 —— 不管这个操作系统是在一个服务器(或“[无服务器][2]”,也是同样的)、桌面电脑、笔记本电脑、移动设备,或嵌入式设备 —— 那么,Java 应用程序就可以运行在它上面。
+
+这使得 Java 成为程序员和用户的一种流行语言。程序员知道,他们只需要写一个软件版本就能最终得到一个可以运行在任何平台上的应用程序;用户知道,应用程序可以运行在他们的计算机上,而不用管他们使用的是什么样的操作系统。
+
+很多语言和框架是跨平台的,但是没有实现同样的抽象层。使用 Java,你针对的是 JVM,而不是操作系统。对于程序员,当面对一些编程难题时,这是阻力最小的线路,但是它仅在当你知道如何编程 Java 时有用。如果你刚开始学习 Java 编程,这里有你需要知道的七个基础的提示。
+
+但是,首先,如果你不确定是否你安装了 Java ,你可以在一个终端(例如 [Bash][3] 或 [PowerShell][4])中找出来,通过运行:
+
+```
+$ java --version
+openjdk 12.0.2 2019-07-16
+OpenJDK Runtime Environment 19.3 (build 12.0.2+9)
+OpenJDK 64-Bit Server VM 19.3 (build 12.0.2+9, mixed mode, sharing)
+```
+
+如果你得到一个错误,或未返回任何东西,那么你应该安装 [Java 开发套件][5](JDK)来开始 Java 开发。或者,安装一个 Java 运行时环境(JRE),如果你只是需要来运行 Java 应用程序。
+
+### 1、Java 软件包
+
+在 Java 语言中,相关的类被分组到一个*软件包*中。当你下载 JDK 时所获得的 Java 基础库将被分组到以 `java` 或 `javax` 开头的软件包中。软件包提供一种类似于计算机上的文件夹的功能:它们为相关的元素提供结构和定义(以编程术语说,*命名空间*)。额外的软件包可以从独立开发者、开源项目和商业供应商获得,就像可以为任何编程语言获得库一样。
+
+当你写一个 Java 程序时,你应该在你的代码是顶部声明一个软件包名称。如果你只是编写一个简单的应用程序来入门 Java,你的软件包名称可以简单地用你的项目名称。如果你正在使用一个 Java 集成开发环境,如 [Eclipse][6],当你启动一个新的项目时,它为你生成一个合乎情理的软件包名称。
+
+```
+package helloworld;
+
+/**
+ * @author seth
+ * An application written in Java.
+ */
+```
+
+除此之外,你可以通过查找它相对于你的项目整体的路径来确定你的软件包名称。例如,如果你正在写一组类来帮助游戏开发,并且该集合被称为 `jgamer`,那么你可能在其中有一些唯一的类。
+
+```
+package jgamer.avatar;
+
+/**
+ * @author seth
+ * An imaginary game library.
+ */
+```
+
+你的软件包的顶层是 `jgamer`,并且在其内部中每个软件包都是一个独立的派生物,例如 `jgamer.avatar` 和 `jgamer.score` 等等。在你的文件系统里,其目录结构反映了这一点,`jgamer` 是包含文件 `avatar.java` 和 `score.java` 的顶级目录。
+
+### 2、Java 导入
+
+作为一名通晓多种语言的程序员,最大的乐趣是找出是否用 `include`、`import`、`use`、`require`,或一些其它术语来引入你不管使用何种编程语言编写的库。在 Java 中,顺便说一句,当导入你的代码的需要的库时,使用 `import` 关键字。
+
+```
+package helloworld;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * @author seth
+ * A GUI hello world.
+ */
+```
+
+导入是基于该环境的 Java 路径。如果 Java 不知道 Java 库存储在系统上的何处,那么,就不能成功导入。只要一个库被存储在系统的 Java 路径中,那么导入能够成功,并且库能够被用于构建和运行一个 Java 应用程序。
+
+如果一个库并不在 Java 路径中(因为,例如,你正在写你自己的库),那么该库可以与你的应用程序绑定在一起(协议许可),以便导入可以按预期地工作。
+
+### 3、Java 类
+
+Java 类使用关键字 `public class` 声明,以及一个唯一的对应于它的文件名的类名。例如,在项目 `helloworld` 中的一个文件 `Hello.java` 中:
+
+```
+package helloworld;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+
+/**
+ * @author seth
+ * A GUI hello world.
+ */
+
+public class Hello {
+ // this is an empty class
+}
+```
+
+你可以在一个类内部声明变量和函数。在 Java 中,在一个类中的变量被称为*字段*。
+
+### 4、Java 方法
+
+Java 的方法本质上是对象中的函数。基于预期返回的数据类型(例如 `void`、`int`、`float` 等等),它们被定义为 `public`(意味着它们可以被任何其它类访问)或 `private`(限制它们的使用)。
+
+
+```
+ public void helloPrompt(ActionEvent event) {
+ String salutation = "Hello %s";
+
+ string helloMessage = "World";
+ message = String.format(salutation, helloMessage);
+ JOptionPane.showMessageDialog(this, message);
+ }
+
+ private int someNumber (x) {
+ return x*2;
+ }
+```
+
+当直接调用一个方法时,以其类和方法名称来引用。例如,`Hello.someNumber` 指向在 `Hello` 类中的 `someNumber` 方法。
+
+### 5、static
+
+Java 中的 `static` 关键字使代码中的成员可以独立于包含其的对象而被访问。
+
+在面向对象编程中,你编写的代码用作“对象”的模板,这些对象在应用程序运行时产生。例如,你不需要编写一个具体的窗口,而是编写基于 Java 中的窗口类的窗口实例(并由你的代码修改)。由于在应用程序生成它的实例之前,你编写的所有代码都不会“存在”,因此在创建它们所依赖的对象之前,大多数方法和变量(甚至是嵌套类)都无法使用。
+
+然而,有时,在对象被通过应用程序创建前,你需要访问或使用其中的数据。(例如,除非事先知道球是红色时,应用程序无法生成一个红色的球)。对于这些情况,请使用 `static` 关键字。
+
+### 6、try 和 catch
+
+Java 擅长捕捉错误,但是,只有你告诉它遇到错误时该做什么,它才能优雅地恢复。在 Java 中,尝试执行一个动作的级联层次结构以 `try` 开头,出现错误时回落到 `catch`,并以 `finally` 结束。如果 `try` 子句失败,则将调用 `catch`,最后,不管结果如何,总是由 `finally` 来执行一些合理的动作。这里是一个示例:
+
+```
+try {
+ cmd = parser.parse(opt, args);
+
+ if(cmd.hasOption("help")) {
+ HelpFormatter helper = new HelpFormatter();
+ helper.printHelp("Hello ", opt);
+ System.exit(0);
+ }
+ else {
+ if(cmd.hasOption("shell") || cmd.hasOption("s")) {
+ String target = cmd.getOptionValue("tgt");
+ } // else
+ } // fi
+} catch (ParseException err) {
+ System.out.println(err);
+ System.exit(1);
+ } //catch
+ finally {
+ new Hello().helloWorld(opt);
+ } //finally
+} //try
+```
+
+这是一个健壮的系统,它试图避免无法挽回的错误,或者,至少,为你提供让用户提交有用的反馈的选项。经常使用它,你的用户将会感谢你!
+
+### 7、运行 Java 应用程序
+
+Java 文件,通常以 `.java` 结尾,理论上说,可以使用 `java` 命令运行。然而,如果一个应用程序很复杂,运行一个单个文件是否会产生有意义的结果是另外一个问题。
+
+来直接运行一个 `.java` 文件:
+
+```
+$ java ./Hello.java
+```
+
+通常,Java 应用程序以 Java 存档(JAR)文件的形式分发,以 `.jar` 结尾。一个 JAR 文件包含一个清单文件(可以指定主类、项目结构的一些元数据),以及运行应用程序所需的所有代码部分。
+
+要运行一个 JAR 文件,你可以双击它的图标(取决于你的操作系统设置),你也可以从终端中启动它:
+
+```
+$ java -jar ./Hello.jar
+```
+
+### 适合所有人的 Java
+
+Java 是一种强大的语言,由于有了 [OpenJDK][12] 项目及其它的努力,它是一种开放式规范,允许像 [IcedTea][13]、[Dalvik][14] 和 [Kotlin][15] 项目的茁壮成长。学习 Java 是一种准备在各种行业中工作的好方法,而且,[使用 Java 的理由很多][16]。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/java-basics
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[robsean](https://github.com/robsean)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_cafe_brew_laptop_desktop.jpg?itok=G-n1o1-o (Coffee and laptop)
+[2]: https://www.redhat.com/en/resources/building-microservices-eap-7-reference-architecture
+[3]: https://www.gnu.org/software/bash/
+[4]: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6
+[5]: http://openjdk.java.net/
+[6]: http://www.eclipse.org/
+[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+actionevent
+[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
+[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+joptionpane
+[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
+[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+parseexception
+[12]: https://openjdk.java.net/
+[13]: https://icedtea.classpath.org/wiki/Main_Page
+[14]: https://source.android.com/devices/tech/dalvik/
+[15]: https://kotlinlang.org/
+[16]: https://opensource.com/article/19/9/why-i-use-java
diff --git a/published/20191008 5 Best Password Managers For Linux Desktop.md b/published/201911/20191008 5 Best Password Managers For Linux Desktop.md
similarity index 100%
rename from published/20191008 5 Best Password Managers For Linux Desktop.md
rename to published/201911/20191008 5 Best Password Managers For Linux Desktop.md
diff --git a/published/20191013 How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server.md b/published/201911/20191013 How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server.md
similarity index 100%
rename from published/20191013 How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server.md
rename to published/201911/20191013 How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server.md
diff --git a/published/201911/20191018 How to use Protobuf for data interchange.md b/published/201911/20191018 How to use Protobuf for data interchange.md
new file mode 100644
index 0000000000..cecba89611
--- /dev/null
+++ b/published/201911/20191018 How to use Protobuf for data interchange.md
@@ -0,0 +1,489 @@
+[#]: collector: (lujun9972)
+[#]: translator: (wxy)
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11600-1.html)
+[#]: subject: (How to use Protobuf for data interchange)
+[#]: via: (https://opensource.com/article/19/10/protobuf-data-interchange)
+[#]: author: (Marty Kalin https://opensource.com/users/mkalindepauledu)
+
+如何使用 Protobuf 做数据交换
+======
+
+> 在以不同语言编写并在不同平台上运行的应用程序之间交换数据时,Protobuf 编码可提高效率。
+
+
+
+协议缓冲区([Protobufs][2])像 XML 和 JSON 一样,可以让用不同语言编写并在不同平台上运行的应用程序交换数据。例如,用 Go 编写的发送程序可以在 Protobuf 中对以 Go 表示的销售订单数据进行编码,然后用 Java 编写的接收方可以对它进行解码,以获取所接收订单数据的 Java 表示方式。这是在网络连接上的结构示意图:
+
+> Go 销售订单 ---> Pbuf 编码 ---> 网络 ---> Pbuf 界面 ---> Java 销售订单
+
+与 XML 和 JSON 相比,Protobuf 编码是二进制而不是文本,这会使调试复杂化。但是,正如本文中的代码示例所确认的那样,Protobuf 编码在大小上比 XML 或 JSON 编码要有效得多。
+
+Protobuf 以另一种方式提供了这种有效性。在实现级别,Protobuf 和其他编码系统对结构化数据进行序列化和反序列化。序列化将特定语言的数据结构转换为字节流,反序列化是将字节流转换回特定语言的数据结构的逆运算。序列化和反序列化可能成为数据交换的瓶颈,因为这些操作会占用大量 CPU。高效的序列化和反序列化是 Protobuf 的另一个设计目标。
+
+最近的编码技术,例如 Protobuf 和 FlatBuffers,源自 1990 年代初期的 [DCE/RPC][3](分布式计算环境/远程过程调用)计划。与 DCE/RPC 一样,Protobuf 在数据交换中为 [IDL][4](接口定义语言)和编码层做出了贡献。
+
+本文将着眼于这两层,然后提供 Go 和 Java 中的代码示例以充实 Protobuf 的细节,并表明 Protobuf 是易于使用的。
+
+### Protobuf 作为一个 IDL 和编码层
+
+像 Protobuf 一样,DCE/RPC 被设计为与语言和平台无关。适当的库和实用程序允许任何语言和平台用于 DCE/RPC 领域。此外,DCE/RPC 体系结构非常优雅。IDL 文档是一侧的远程过程与另一侧的调用者之间的协定。Protobuf 也是以 IDL 文档为中心的。
+
+IDL 文档是文本,在 DCE/RPC 中,使用基本 C 语法以及元数据的语法扩展(方括号)和一些新的关键字,例如 `interface`。这是一个例子:
+
+```
+[uuid (2d6ead46-05e3-11ca-7dd1-426909beabcd), version(1.0)]
+interface echo {
+ const long int ECHO_SIZE = 512;
+ void echo(
+ [in] handle_t h,
+ [in, string] idl_char from_client[ ],
+ [out, string] idl_char from_service[ECHO_SIZE]
+ );
+}
+```
+
+该 IDL 文档声明了一个名为 `echo` 的过程,该过程带有三个参数:类型为 `handle_t`(实现指针)和 `idl_char`(ASCII 字符数组)的 `[in]` 参数被传递给远程过程,而 `[out]` 参数(也是一个字符串)从该过程中传回。在此示例中,`echo` 过程不会显式返回值(`echo` 左侧的 `void`),但也可以返回值。返回值,以及一个或多个 `[out]` 参数,允许远程过程任意返回许多值。下一节将介绍 Protobuf IDL,它的语法不同,但同样用作数据交换中的协定。
+
+DCE/RPC 和 Protobuf 中的 IDL 文档是创建用于交换数据的基础结构代码的实用程序的输入:
+
+> IDL 文档 ---> DCE/PRC 或 Protobuf 实用程序 ---> 数据交换的支持代码
+
+作为相对简单的文本,IDL 是同样便于人类阅读的关于数据交换细节的文档(特别是交换的数据项的数量和每个项的数据类型)。
+
+Protobuf 可用于现代 RPC 系统,例如 [gRPC][5];但是 Protobuf 本身仅提供 IDL 层和编码层,用于从发送者传递到接收者的消息。与原本的 DCE/RPC 一样,Protobuf 编码是二进制的,但效率更高。
+
+目前,XML 和 JSON 编码仍在通过 Web 服务等技术进行的数据交换中占主导地位,这些技术利用 Web 服务器、传输协议(例如 TCP、HTTP)以及标准库和实用程序等原有的基础设施来处理 XML 和 JSON 文档。 此外,各种类型的数据库系统可以存储 XML 和 JSON 文档,甚至旧式关系型系统也可以轻松生成查询结果的 XML 编码。现在,每种通用编程语言都具有支持 XML 和 JSON 的库。那么,是什么让我们回到 Protobuf 之类的**二进制**编码系统呢?
+
+让我们看一下负十进制值 `-128`。以 2 的补码二进制表示形式(在系统和语言中占主导地位)中,此值可以存储在单个 8 位字节中:`10000000`。此整数值在 XML 或 JSON 中的文本编码需要多个字节。例如,UTF-8 编码需要四个字节的字符串,即 `-128`,即每个字符一个字节(十六进制,值为 `0x2d`、`0x31`、`0x32` 和 `0x38`)。XML 和 JSON 还添加了标记字符,例如尖括号和大括号。有关 Protobuf 编码的详细信息下面就会介绍,但现在的关注点是一个通用点:文本编码的压缩性明显低于二进制编码。
+
+### 在 Go 中使用 Protobuf 的示例
+
+我的代码示例着重于 Protobuf 而不是 RPC。以下是第一个示例的概述:
+
+* 名为 `dataitem.proto` 的 IDL 文件定义了一个 Protobuf 消息,它具有六个不同类型的字段:具有不同范围的整数值、固定大小的浮点值以及两个不同长度的字符串。
+* Protobuf 编译器使用 IDL 文件生成 Go 版本(以及后面的 Java 版本)的 Protobuf 消息及支持函数。
+* Go 应用程序使用随机生成的值填充原生的 Go 数据结构,然后将结果序列化为本地文件。为了进行比较, XML 和 JSON 编码也被序列化为本地文件。
+* 作为测试,Go 应用程序通过反序列化 Protobuf 文件的内容来重建其原生数据结构的实例。
+* 作为语言中立性测试,Java 应用程序还会对 Protobuf 文件的内容进行反序列化以获取原生数据结构的实例。
+
+[我的网站][6]上提供了该 IDL 文件以及两个 Go 和一个 Java 源文件,打包为 ZIP 文件。
+
+最重要的 Protobuf IDL 文档如下所示。该文档存储在文件 `dataitem.proto` 中,并具有常规的`.proto` 扩展名。
+
+#### 示例 1、Protobuf IDL 文档
+
+```
+syntax = "proto3";
+
+package main;
+
+message DataItem {
+ int64 oddA = 1;
+ int64 evenA = 2;
+ int32 oddB = 3;
+ int32 evenB = 4;
+ float small = 5;
+ float big = 6;
+ string short = 7;
+ string long = 8;
+}
+```
+
+该 IDL 使用当前的 proto3 而不是较早的 proto2 语法。软件包名称(在本例中为 `main`)是可选的,但是惯例使用它以避免名称冲突。这个结构化的消息包含八个字段,每个字段都有一个 Protobuf 数据类型(例如,`int64`、`string`)、名称(例如,`oddA`、`short`)和一个等号 `=` 之后的数字标签(即键)。标签(在此示例中为 1 到 8)是唯一的整数标识符,用于确定字段序列化的顺序。
+
+Protobuf 消息可以嵌套到任意级别,而一个消息可以是另外一个消息的字段类型。这是一个使用 `DataItem` 消息作为字段类型的示例:
+
+```
+message DataItems {
+ repeated DataItem item = 1;
+}
+```
+
+单个 `DataItems` 消息由重复的(零个或多个)`DataItem` 消息组成。
+
+为了清晰起见,Protobuf 还支持枚举类型:
+
+```
+enum PartnershipStatus {
+ reserved "FREE", "CONSTRAINED", "OTHER";
+}
+```
+
+`reserved` 限定符确保用于实现这三个符号名的数值不能重复使用。
+
+为了生成一个或多个声明 Protobuf 消息结构的特定于语言的版本,包含这些结构的 IDL 文件被传递到`protoc` 编译器(可在 [Protobuf GitHub 存储库][7]中找到)。对于 Go 代码,可以以通常的方式安装支持的 Protobuf 库(这里以 `%` 作为命令行提示符):
+
+```
+% go get github.com/golang/protobuf/proto
+```
+
+将 Protobuf IDL 文件 `dataitem.proto` 编译为 Go 源代码的命令是:
+
+```
+% protoc --go_out=. dataitem.proto
+```
+
+标志 `--go_out` 指示编译器生成 Go 源代码。其他语言也有类似的标志。在这种情况下,结果是一个名为 `dataitem.pb.go` 的文件,该文件足够小,可以将其基本内容复制到 Go 应用程序中。以下是生成的代码的主要部分:
+
+```
+var _ = proto.Marshal
+
+type DataItem struct {
+ OddA int64 `protobuf:"varint,1,opt,name=oddA" json:"oddA,omitempty"`
+ EvenA int64 `protobuf:"varint,2,opt,name=evenA" json:"evenA,omitempty"`
+ OddB int32 `protobuf:"varint,3,opt,name=oddB" json:"oddB,omitempty"`
+ EvenB int32 `protobuf:"varint,4,opt,name=evenB" json:"evenB,omitempty"`
+ Small float32 `protobuf:"fixed32,5,opt,name=small" json:"small,omitempty"`
+ Big float32 `protobuf:"fixed32,6,opt,name=big" json:"big,omitempty"`
+ Short string `protobuf:"bytes,7,opt,name=short" json:"short,omitempty"`
+ Long string `protobuf:"bytes,8,opt,name=long" json:"long,omitempty"`
+}
+
+func (m *DataItem) Reset() { *m = DataItem{} }
+func (m *DataItem) String() string { return proto.CompactTextString(m) }
+func (*DataItem) ProtoMessage() {}
+func init() {}
+```
+
+编译器生成的代码具有 Go 结构 `DataItem`,该结构导出 Go 字段(名称现已大写开头),该字段与 Protobuf IDL 中声明的名称匹配。该结构字段具有标准的 Go 数据类型:`int32`、`int64`、`float32` 和 `string`。在每个字段行的末尾,是描述 Protobuf 类型的字符串,提供 Protobuf IDL 文档中的数字标签及有关 JSON 信息的元数据,这将在后面讨论。
+
+此外也有函数;最重要的是 `Proto.Marshal`,用于将 `DataItem` 结构的实例序列化为 Protobuf 格式。辅助函数包括:清除 `DataItem` 结构的 `Reset`,生成 `DataItem` 的单行字符串表示的 `String`。
+
+描述 Protobuf 编码的元数据应在更详细地分析 Go 程序之前进行仔细研究。
+
+### Protobuf 编码
+
+Protobuf 消息的结构为键/值对的集合,其中数字标签为键,相应的字段为值。字段名称(例如,`oddA` 和 `small`)是供人类阅读的,但是 `protoc` 编译器的确使用了字段名称来生成特定于语言的对应名称。例如,Protobuf IDL 中的 `oddA` 和 `small` 名称在 Go 结构中分别成为字段 `OddA` 和 `Small`。
+
+键和它们的值都被编码,但是有一个重要的区别:一些数字值具有固定大小的 32 或 64 位的编码,而其他数字(包括消息标签)则是 `varint` 编码的,位数取决于整数的绝对值。例如,整数值 1 到 15 需要 8 位 `varint` 编码,而值 16 到 2047 需要 16 位。`varint` 编码在本质上与 UTF-8 编码类似(但细节不同),它偏爱较小的整数值而不是较大的整数值。(有关详细分析,请参见 Protobuf [编码指南][8])结果是,Protobuf 消息应该在字段中具有较小的整数值(如果可能),并且键数应尽可能少,但每个字段至少得有一个键。
+
+下表 1 列出了 Protobuf 编码的要点:
+
+编码 | 示例类型 | 长度
+---|---|---
+`varint` | `int32`、`uint32`、`int64` | 可变长度
+`fixed` | `fixed32`、`float`、`double` | 固定的 32 位或 64 位长度
+字节序列 | `string`、`bytes` | 序列长度
+
+*表 1. Protobuf 数据类型*
+
+未明确固定长度的整数类型是 `varint` 编码的;因此,在 `varint` 类型中,例如 `uint32`(`u` 代表无符号),数字 32 描述了整数的范围(在这种情况下为 0 到 2^32 - 1),而不是其位的大小,该位大小取决于值。相比之下,对于固定长度类型(例如 `fixed32` 或 `double`),Protobuf 编码分别需要 32 位和 64 位。Protobuf 中的字符串是字节序列;因此,字段编码的大小就是字节序列的长度。
+
+另一个高效的方法值得一提。回想一下前面的示例,其中的 `DataItems` 消息由重复的 `DataItem` 实例组成:
+
+```
+message DataItems {
+ repeated DataItem item = 1;
+}
+```
+
+`repeated` 表示 `DataItem` 实例是*打包的*:集合具有单个标签,在这里是 1。因此,具有重复的 `DataItem` 实例的 `DataItems` 消息比具有多个但单独的 `DataItem` 字段、每个字段都需要自己的标签的消息的效率更高。
+
+了解了这一背景,让我们回到 Go 程序。
+
+### dataItem 程序的细节
+
+`dataItem` 程序创建一个 `DataItem` 实例,并使用适当类型的随机生成的值填充字段。Go 有一个 `rand` 包,带有用于生成伪随机整数和浮点值的函数,而我的 `randString` 函数可以从字符集中生成指定长度的伪随机字符串。设计目标是要有一个具有不同类型和位大小的字段值的 `DataItem` 实例。例如,`OddA` 和 `EvenA` 值分别是 64 位非负整数值的奇数和偶数;但是 `OddB` 和 `EvenB` 变体的大小为 32 位,并存放 0 到 2047 之间的小整数值。随机浮点值的大小为 32 位,字符串为 16(`Short`)和 32(`Long`)字符的长度。这是用随机值填充 `DataItem` 结构的代码段:
+
+```
+// 可变长度整数
+n1 := rand.Int63() // 大整数
+if (n1 & 1) == 0 { n1++ } // 确保其是奇数
+...
+n3 := rand.Int31() % UpperBound // 小整数
+if (n3 & 1) == 0 { n3++ } // 确保其是奇数
+
+// 固定长度浮点数
+...
+t1 := rand.Float32()
+t2 := rand.Float32()
+...
+// 字符串
+str1 := randString(StrShort)
+str2 := randString(StrLong)
+
+// 消息
+dataItem := &DataItem {
+ OddA: n1,
+ EvenA: n2,
+ OddB: n3,
+ EvenB: n4,
+ Big: f1,
+ Small: f2,
+ Short: str1,
+ Long: str2,
+}
+```
+
+创建并填充值后,`DataItem` 实例将以 XML、JSON 和 Protobuf 进行编码,每种编码均写入本地文件:
+
+```
+func encodeAndserialize(dataItem *DataItem) {
+ bytes, _ := xml.MarshalIndent(dataItem, "", " ") // Xml to dataitem.xml
+ ioutil.WriteFile(XmlFile, bytes, 0644) // 0644 is file access permissions
+
+ bytes, _ = json.MarshalIndent(dataItem, "", " ") // Json to dataitem.json
+ ioutil.WriteFile(JsonFile, bytes, 0644)
+
+ bytes, _ = proto.Marshal(dataItem) // Protobuf to dataitem.pbuf
+ ioutil.WriteFile(PbufFile, bytes, 0644)
+}
+```
+
+这三个序列化函数使用术语 `marshal`,它与 `serialize` 意思大致相同。如代码所示,三个 `Marshal` 函数均返回一个字节数组,然后将其写入文件。(为简单起见,忽略可能的错误处理。)在示例运行中,文件大小为:
+
+```
+dataitem.xml: 262 bytes
+dataitem.json: 212 bytes
+dataitem.pbuf: 88 bytes
+```
+
+Protobuf 编码明显小于其他两个编码方案。通过消除缩进字符(在这种情况下为空白和换行符),可以稍微减小 XML 和 JSON 序列化的大小。
+
+以下是 `dataitem.json` 文件,该文件最终是由 `json.MarshalIndent` 调用产生的,并添加了以 `##` 开头的注释:
+
+```
+{
+ "oddA": 4744002665212642479, ## 64-bit >= 0
+ "evenA": 2395006495604861128, ## ditto
+ "oddB": 57, ## 32-bit >= 0 but < 2048
+ "evenB": 468, ## ditto
+ "small": 0.7562016, ## 32-bit floating-point
+ "big": 0.85202795, ## ditto
+ "short": "ClH1oDaTtoX$HBN5", ## 16 random chars
+ "long": "xId0rD3Cri%3Wt%^QjcFLJgyXBu9^DZI" ## 32 random chars
+}
+```
+
+尽管这些序列化的数据写入到本地文件中,但是也可以使用相同的方法将数据写入网络连接的输出流。
+
+### 测试序列化和反序列化
+
+Go 程序接下来通过将先前写入 `dataitem.pbuf` 文件的字节反序列化为 `DataItem` 实例来运行基本测试。这是代码段,其中去除了错误检查部分:
+
+```
+filebytes, err := ioutil.ReadFile(PbufFile) // get the bytes from the file
+...
+testItem.Reset() // clear the DataItem structure
+err = proto.Unmarshal(filebytes, testItem) // deserialize into a DataItem instance
+```
+
+用于 Protbuf 反序列化的 `proto.Unmarshal` 函数与 `proto.Marshal` 函数相反。原始的 `DataItem` 和反序列化的副本将被打印出来以确认完全匹配:
+
+```
+Original:
+2041519981506242154 3041486079683013705 1192 1879
+0.572123 0.326855
+boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk&
+
+Deserialized:
+2041519981506242154 3041486079683013705 1192 1879
+0.572123 0.326855
+boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk&
+```
+
+### 一个 Java Protobuf 客户端
+
+用 Java 写的示例是为了确认 Protobuf 的语言中立性。原始 IDL 文件可用于生成 Java 支持代码,其中涉及嵌套类。但是,为了抑制警告信息,可以进行一些补充。这是修订版,它指定了一个 `DataMsg` 作为外部类的名称,内部类在该 Protobuf 消息后面自动命名为 `DataItem`:
+
+```
+syntax = "proto3";
+
+package main;
+
+option java_outer_classname = "DataMsg";
+
+message DataItem {
+...
+```
+
+进行此更改后,`protoc` 编译与以前相同,只是所期望的输出现在是 Java 而不是 Go:
+
+```
+% protoc --java_out=. dataitem.proto
+```
+
+生成的源文件(在名为 `main` 的子目录中)为 `DataMsg.java`,长度约为 1,120 行:Java 并不简洁。编译然后运行 Java 代码需要具有 Protobuf 库支持的 JAR 文件。该文件位于 [Maven 存储库][9]中。
+
+放置好这些片段后,我的测试代码相对较短(并且在 ZIP 文件中以 `Main.java` 形式提供):
+
+```
+package main;
+import java.io.FileInputStream;
+
+public class Main {
+ public static void main(String[] args) {
+ String path = "dataitem.pbuf"; // from the Go program's serialization
+ try {
+ DataMsg.DataItem deserial =
+ DataMsg.DataItem.newBuilder().mergeFrom(new FileInputStream(path)).build();
+
+ System.out.println(deserial.getOddA()); // 64-bit odd
+ System.out.println(deserial.getLong()); // 32-character string
+ }
+ catch(Exception e) { System.err.println(e); }
+ }
+}
+```
+
+当然,生产级的测试将更加彻底,但是即使是该初步测试也可以证明 Protobuf 的语言中立性:`dataitem.pbuf` 文件是 Go 程序对 Go 语言版的 `DataItem` 进行序列化的结果,并且该文件中的字节被反序列化以产生一个 Java 语言的 `DataItem` 实例。Java 测试的输出与 Go 测试的输出相同。
+
+### 用 numPairs 程序来结束
+
+让我们以一个示例作为结尾,来突出 Protobuf 效率,但又强调在任何编码技术中都会涉及到的成本。考虑以下 Protobuf IDL 文件:
+
+```
+syntax = "proto3";
+package main;
+
+message NumPairs {
+ repeated NumPair pair = 1;
+}
+
+message NumPair {
+ int32 odd = 1;
+ int32 even = 2;
+}
+```
+
+`NumPair` 消息由两个 `int32` 值以及每个字段的整数标签组成。`NumPairs` 消息是嵌入的 `NumPair` 消息的序列。
+
+Go 语言的 `numPairs` 程序(如下)创建了 200 万个 `NumPair` 实例,每个实例都附加到 `NumPairs` 消息中。该消息可以按常规方式进行序列化和反序列化。
+
+#### 示例 2、numPairs 程序
+
+```
+package main
+
+import (
+ "math/rand"
+ "time"
+ "encoding/xml"
+ "encoding/json"
+ "io/ioutil"
+ "github.com/golang/protobuf/proto"
+)
+
+// protoc-generated code: start
+var _ = proto.Marshal
+type NumPairs struct {
+ Pair []*NumPair `protobuf:"bytes,1,rep,name=pair" json:"pair,omitempty"`
+}
+
+func (m *NumPairs) Reset() { *m = NumPairs{} }
+func (m *NumPairs) String() string { return proto.CompactTextString(m) }
+func (*NumPairs) ProtoMessage() {}
+func (m *NumPairs) GetPair() []*NumPair {
+ if m != nil { return m.Pair }
+ return nil
+}
+
+type NumPair struct {
+ Odd int32 `protobuf:"varint,1,opt,name=odd" json:"odd,omitempty"`
+ Even int32 `protobuf:"varint,2,opt,name=even" json:"even,omitempty"`
+}
+
+func (m *NumPair) Reset() { *m = NumPair{} }
+func (m *NumPair) String() string { return proto.CompactTextString(m) }
+func (*NumPair) ProtoMessage() {}
+func init() {}
+// protoc-generated code: finish
+
+var numPairsStruct NumPairs
+var numPairs = &numPairsStruct
+
+func encodeAndserialize() {
+ // XML encoding
+ filename := "./pairs.xml"
+ bytes, _ := xml.MarshalIndent(numPairs, "", " ")
+ ioutil.WriteFile(filename, bytes, 0644)
+
+ // JSON encoding
+ filename = "./pairs.json"
+ bytes, _ = json.MarshalIndent(numPairs, "", " ")
+ ioutil.WriteFile(filename, bytes, 0644)
+
+ // ProtoBuf encoding
+ filename = "./pairs.pbuf"
+ bytes, _ = proto.Marshal(numPairs)
+ ioutil.WriteFile(filename, bytes, 0644)
+}
+
+const HowMany = 200 * 100 * 100 // two million
+
+func main() {
+ rand.Seed(time.Now().UnixNano())
+
+ // uncomment the modulus operations to get the more efficient version
+ for i := 0; i < HowMany; i++ {
+ n1 := rand.Int31() // % 2047
+ if (n1 & 1) == 0 { n1++ } // ensure it's odd
+ n2 := rand.Int31() // % 2047
+ if (n2 & 1) == 1 { n2++ } // ensure it's even
+
+ next := &NumPair {
+ Odd: n1,
+ Even: n2,
+ }
+ numPairs.Pair = append(numPairs.Pair, next)
+ }
+ encodeAndserialize()
+}
+```
+
+每个 `NumPair` 中随机生成的奇数和偶数值的范围在 0 到 20 亿之间变化。就原始数据(而非编码数据)而言,Go 程序中生成的整数总共为 16MB:每个 `NumPair` 为两个整数,总计为 400 万个整数,每个值的大小为四个字节。
+
+为了进行比较,下表列出了 XML、JSON 和 Protobuf 编码的示例 `NumsPairs` 消息的 200 万个 `NumPair` 实例。原始数据也包括在内。由于 `numPairs` 程序生成随机值,因此样本运行的输出有所不同,但接近表中显示的大小。
+
+编码 | 文件 | 字节大小 | Pbuf/其它 比例
+---|---|---|---
+无 | pairs.raw | 16MB | 169%
+Protobuf | pairs.pbuf | 27MB | —
+JSON | pairs.json | 100MB | 27%
+XML | pairs.xml | 126MB | 21%
+
+*表 2. 16MB 整数的编码开销*
+
+不出所料,Protobuf 和之后的 XML 和 JSON 差别明显。Protobuf 编码大约是 JSON 的四分之一,是 XML 的五分之一。但是原始数据清楚地表明 Protobuf 也会产生编码开销:序列化的 Protobuf 消息比原始数据大 11MB。包括 Protobuf 在内的任何编码都涉及结构化数据,这不可避免地会增加字节。
+
+序列化的 200 万个 `NumPair` 实例中的每个实例都包含**四**个整数值:Go 结构中的 `Even` 和 `Odd` 字段分别一个,而 Protobuf 编码中的每个字段、每个标签一个。对于原始数据(而不是编码数据),每个实例将达到 16 个字节,样本 `NumPairs` 消息中有 200 万个实例。但是 Protobuf 标记(如 `NumPair` 字段中的 `int32` 值)使用 `varint` 编码,因此字节长度有所不同。特别是,小的整数值(在这种情况下,包括标签在内)需要不到四个字节进行编码。
+
+如果对 `numPairs` 程序进行了修改,以使两个 `NumPair` 字段的值小于 2048,且其编码为一或两个字节,则 Protobuf 编码将从 27MB 下降到 16MB,这正是原始数据的大小。下表总结了样本运行中的新编码大小。
+
+编码 | 文件 | 字节大小 | Pbuf/其它 比例
+---|---|---|---
+None | pairs.raw | 16MB | 100%
+Protobuf | pairs.pbuf | 16MB | —
+JSON | pairs.json | 77MB | 21%
+XML | pairs.xml | 103MB | 15%
+
+*表 3. 编码 16MB 的小于 2048 的整数*
+
+总之,修改后的 `numPairs` 程序的字段值小于 2048,可减少原始数据中每个四字节整数值的大小。但是 Protobuf 编码仍然需要标签,这些标签会在 Protobuf 消息中添加字节。Protobuf 编码确实会增加消息大小,但是如果要编码相对较小的整数值(无论是字段还是键),则可以通过 `varint` 因子来减少此开销。
+
+对于包含混合类型的结构化数据(且整数值相对较小)的中等大小的消息,Protobuf 明显优于 XML 和 JSON 等选项。在其他情况下,数据可能不适合 Protobuf 编码。例如,如果两个应用程序需要共享大量文本记录或大整数值,则可以采用压缩而不是编码技术。
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/10/protobuf-data-interchange
+
+作者:[Marty Kalin][a]
+选题:[lujun9972][b]
+译者:[wxy](https://github.com/wxy)
+校对:[wxy](https://github.com/wxy)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mkalindepauledu
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
+[2]: https://developers.google.com/protocol-buffers/
+[3]: https://en.wikipedia.org/wiki/DCE/RPC
+[4]: https://en.wikipedia.org/wiki/Interface_description_language
+[5]: https://grpc.io/
+[6]: http://condor.depaul.edu/mkalin
+[7]: https://github.com/protocolbuffers/protobuf
+[8]: https://developers.google.com/protocol-buffers/docs/encoding
+[9]: https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
diff --git a/published/20191021 How to program with Bash- Syntax and tools.md b/published/201911/20191021 How to program with Bash- Syntax and tools.md
similarity index 100%
rename from published/20191021 How to program with Bash- Syntax and tools.md
rename to published/201911/20191021 How to program with Bash- Syntax and tools.md
diff --git a/published/20191022 Initializing arrays in Java.md b/published/201911/20191022 Initializing arrays in Java.md
similarity index 100%
rename from published/20191022 Initializing arrays in Java.md
rename to published/201911/20191022 Initializing arrays in Java.md
diff --git a/published/20191023 How to dual boot Windows 10 and Debian 10.md b/published/201911/20191023 How to dual boot Windows 10 and Debian 10.md
similarity index 100%
rename from published/20191023 How to dual boot Windows 10 and Debian 10.md
rename to published/201911/20191023 How to dual boot Windows 10 and Debian 10.md
diff --git a/published/20191024 Open Source CMS Ghost 3.0 Released with New features for Publishers.md b/published/201911/20191024 Open Source CMS Ghost 3.0 Released with New features for Publishers.md
similarity index 100%
rename from published/20191024 Open Source CMS Ghost 3.0 Released with New features for Publishers.md
rename to published/201911/20191024 Open Source CMS Ghost 3.0 Released with New features for Publishers.md
diff --git a/published/20191025 4 cool new projects to try in COPR for October 2019.md b/published/201911/20191025 4 cool new projects to try in COPR for October 2019.md
similarity index 100%
rename from published/20191025 4 cool new projects to try in COPR for October 2019.md
rename to published/201911/20191025 4 cool new projects to try in COPR for October 2019.md
diff --git a/translated/tech/20191025 How I used the wget Linux command to recover lost images.md b/published/201911/20191025 How I used the wget Linux command to recover lost images.md
similarity index 58%
rename from translated/tech/20191025 How I used the wget Linux command to recover lost images.md
rename to published/201911/20191025 How I used the wget Linux command to recover lost images.md
index c7c33f1666..274a70fff2 100644
--- a/translated/tech/20191025 How I used the wget Linux command to recover lost images.md
+++ b/published/201911/20191025 How I used the wget Linux command to recover lost images.md
@@ -1,36 +1,36 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
+[#]: reviewer: (wxy)
+[#]: publisher: (wxy)
+[#]: url: (https://linux.cn/article-11592-1.html)
[#]: subject: (How I used the wget Linux command to recover lost images)
[#]: via: (https://opensource.com/article/19/10/how-community-saved-artwork-creative-commons)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-我是如何使用 wget 命令恢复丢失的图像的
+丢失的开放剪贴画库和新的公共艺术品图书馆 FreeSVG.org 的诞生
======
> 开放剪贴画库兴衰的故事以及一个新的公共艺术品图书馆 FreeSVG.org 的诞生。
-![White shoes on top of an orange tribal pattern][1]
+
-开放剪贴画库(OCAL)发布于 2004 年,成为了免费插图的来源,任何人都可以出于任何目的使用它们,而无需注明出处或提供任何回报。针对 1990 年代每个家庭办公室书架上的大量剪贴画 CD 以及由闭源公司和艺术品软件提供的艺术品转储,这个网站是开源世界的答复。
+开放剪贴画库(OCAL)发布于 2004 年,成为了免费插图的来源,任何人都可以出于任何目的使用它们,而无需注明出处或提供任何回报。针对 1990 年代每个家庭办公室书架上的大量剪贴画 CD 以及由闭源公司和艺术品软件提供的艺术品转储,这个网站是开源世界的回应。
-最初,这个剪贴画库主要由一些贡献者组成,但是在 2010 年,它重新打造成了一个全新的交互式网站,可以让任何人使用矢量插图应用程序创建和贡献剪贴画。该网站立即获得了来自全球的、各种形式的自由软件和自由文化项目的贡献。[Inkscape][2] 中甚至包含了该库的专用导入器。
+最初,这个剪贴画库主要由一些贡献者提供,但是在 2010 年,它重新打造成了一个全新的交互式网站,可以让任何人使用矢量插图应用程序创建和贡献剪贴画。该网站立即获得了来自全球的、各种形式的自由软件和自由文化项目的贡献。[Inkscape][2] 中甚至包含了该库的专用导入器。
-但是,在 2019 年初,托管开放剪贴画库的网站离线,没有任何警告或解释。它已经成长为有着成千上万的人的社区,起初以为这是暂时的故障。 但是,这个站点一直离线已超过六个月,而没有任何清楚的解释。
+但是,在 2019 年初,托管开放剪贴画库的网站离线了,没有任何警告或解释。它已经成长为有着成千上万的人的社区,起初以为这是暂时的故障。但是,这个网站一直离线已超过六个月,而没有任何清楚的解释。
-谣言开始膨胀。该网站正在更新中(“要偿还数年的技术债务”,网站开发者 Jon Philips 在一封电子邮件中说)。一个 Twitter 帐户声称,该网站遭受了猖狂的 DDoS 攻击。另一个 Twitter 帐户声称,该网站维护者已经成为身份盗用的牺牲品。今天,在撰写本文时,该网站的一个且唯一的页面声明它处于“维护和保护模式”,其含义不清楚,只是用户无法访问其内容。
+谣言开始膨胀。该网站一直在更新中(“要偿还数年的技术债务”,网站开发者 Jon Philips 在一封电子邮件中说)。一个 Twitter 帐户声称,该网站遭受了猖狂的 DDoS 攻击。另一个 Twitter 帐户声称,该网站维护者已经成为身份盗用的牺牲品。今天,在撰写本文时,该网站的一个且唯一的页面声明它处于“维护和保护模式”,其含义不清楚,只是用户无法访问其内容。
### 恢复公地
-网站会随着时间的流逝而消失,但是对其社区而言开放剪贴画库的丢失尤其令人惊讶,因为它被视为一个社区项目。很少有社区成员知道托管该库的站点已经落入一个维护者手中,因此,由于 [CC0 许可证][3],该库中的艺术品归所有人所有,但对它的访问是功能性的由单个维护者执行。而且,由于该站点的社区通过该站点彼此保持联系,因此该维护者实际上拥有该社区。
+网站会随着时间的流逝而消失,但是对其社区而言,开放剪贴画库的丢失尤其令人惊讶,因为它被视为一个社区项目。很少有社区成员知道托管该库的网站已经落入单个维护者手中,因此,由于 [CC0 许可证][3],该库中的艺术品归所有人所有,但对它的访问是由单个维护者功能性拥有的。而且,由于该社区通过网站彼此保持联系,因此该维护者实际上拥有该社区。
-当站点发生故障时,社区以及彼此之间都无法访问其艺术品。没有该站点,就没有社区。
+当网站发生故障时,社区以及成员彼此之间都无法访问剪贴画。没有该网站,就没有社区。
-最初,该网站离线后其上的所有东西都是被封挡的。不过,在几个月之后,用户开始意识到该网站的数据库仍然在线,这意味着用户能够通过输入精确的 URL 访问单个剪贴画。换句话说,你不能通过在网站上到处点击来流量剪贴画文件,但是如果你知道该地址,你就可以在浏览器中访问它。类似的,技术型(或偷懒的)用户意识到能够通过类似 `wget` 的自动 Web 浏览器将网站“抓取”下来。
+最初,该网站离线后其上的所有东西都是被封锁的。不过,在几个月之后,用户开始意识到该网站的数据仍然在线,这意味着用户能够通过输入精确的 URL 访问单个剪贴画。换句话说,你不能通过在网站上到处点击来浏览剪贴画文件,但是如果你确切地知道该地址,你就可以在浏览器中访问它。类似的,技术型(或偷懒的)用户意识到能够通过类似 `wget` 的自动 Web 浏览器将网站“抓取”下来。
-Linux 的 `wget` 命令技术上是一个 Web 浏览器,虽然它不能让你像用 Firefox 一样交互式地浏览。相反,`wget` 可以连到互联网,获取文件或文件集,并下载到你的本次硬盘。然后,你可以在 Firefox 或文本编辑器或最合适的应用程序中打开这些文件,然后查看内容。
+Linux 的 `wget` 命令从技术上来说是一个 Web 浏览器,虽然它不能让你像用 Firefox 一样交互式地浏览。相反,`wget` 可以连到互联网,获取文件或文件集,并下载到你的本次硬盘。然后,你可以在 Firefox、文本编辑器或最合适的应用程序中打开这些文件,查看内容。
通常,`wget` 需要知道要提取的特定文件。如果你使用的是安装了 `wget` 的 Linux 或 macOS,则可以通过下载 [example.com][4] 的索引页来尝试此过程:
@@ -47,25 +47,25 @@ $ tail index.html