Merge pull request #1 from LCTT/master

Update from LCTT
This commit is contained in:
algzjh
2019-12-06 18:46:09 +08:00
committed by GitHub
375 changed files with 42960 additions and 7833 deletions

View File

@@ -0,0 +1,289 @@
23 款开源的声音、视觉生产工具
======
> 无论你是要进行音频、图形、视频、动画还是它们的任意组合,都有一个开源工具可以帮助你产生专业水平的结果。
![](https://img.linux.net.cn/data/attachment/album/201912/04/093037w8ab8v0voz0b5u88.jpg)
“开源”在云基础设施、网站托管、嵌入式设备和其他领域已经建立的相当完善。很少数人知道开源在生产专业级的声音视觉素材上也是一个不错的选择。
作为一名产品经理(有时候也是市场支持),我为终端用户提供很多内容:文档、文章、视频教学,甚至是展台物料、白皮书、采访等等。我找到了很多可以帮我制作音频、视频、排版、截屏的开源软件。人们选择开源软件而不是专有软件的[原因][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 的替代品,也许使用并不那么广泛,但它非常完整并易于使用。你可以使用自己最喜欢的插件,使用“钢琴键”编辑乐器,使用<ruby>步定序器<rt>step sequencer</rt></ruby>播放鼓点,混合音轨...几乎能做任何事情。在我没有时间为音乐家录音的时候我就使用它为视频创建声音片段。查看[最好的 LMMS][21] 榜单来看看一些例子。
**10、[Mixxx][22]** DJ音乐混音
如果你需要强大的混音和播放 DJ 软件Mixxx 就可以满足你的需求。它与大多数 MIDI 控制器、唱片、专用声卡所兼容。你可以用它管理音乐库、添加音效,做一些有趣的事情。查看它的[功能][23]来了解它是如何工作的。
#### 音频接口硬件
尽管你可以使用任何一个计算机的声卡录制音频,但要录制的很好,就需要一个音频接口——一个录制高质量音频输入的专用的外部声卡。对于跨平台兼容性来说,大多数“兼容 USB”和“兼容 iOS”的音频接口设备应该都能录制 MIDI 或其他音频。下面是一些我用过的一些有名气的跨平台设备。
**[Behringer U-PHORIA UMC22][24]**
UMC22 是你可以考虑的最便宜的选择。但它的前置放大器噪音太大,<ruby>音腔<rt>box</rt></ruby>质量也比较低。
**[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 SoftwareOBS是一个领先的在 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全称是 <ruby>KDE 非线性视频编辑器<rt>KDE Non-Linear Video Editor</rt></ruby>)对你来说将非常简单。它拥有很棒的视频和音频特效,强大的细节处理能力。并且在 BSD 和 MacOS尽管它对准的是 GNU/Linux都能使用还有望移植到 Windows 上。
**21、[Darktable][55]** RAW 图像开发)
Darktable 是一款由摄影师制作的非常完整的 DxO PhotoLab 替代品。一些研究型项目使用它当做开发平台并测试一些图像处理算法。它是一个非常活跃的项目,我已经等不及的见到它的跨平台版本了。
**22、[MyPaint][56]** digital painting数字绘画
MyPaint 就像数字绘画领域的 light tableLCTT 译注:集成开发环境)。它在 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/

View File

@@ -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 上安装 LEMPLinux、Nginx、MariaDB、PHP
======
在这篇文章中,我们将看看如何在 Fedora 30 Server 上安装 **LEMP** 。LEMP 代表:
* L -> Linux
* E -> Nginx
* M -> Maria DB
* P -> PHP
我假设 [Fedora 30][1] 已经安装在你的电脑系统上。
![](https://img.linux.net.cn/data/attachment/album/201912/01/103537wil7hd36dhcxdh03.jpg)
LEMP 是一组强大的软件设置集合,它安装在一个 Linux 服务器上以帮助使用流行的开发平台来构建网站LEMP 是 LAMP 的一个变种,在其中不是 Apache ,而是使用 EngineXNginx此外使用 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://<Your-Server-IP> 。
![Test-Page-HTTP-Server-Fedora-30][4]
上面的屏幕证实 Nginx 已经成功地安装。
现在,让我们核实 PHP 安装,使用下面的命令创建一个测试 php 页(`info.php`
```
[root@linuxtechi ~]# echo "<?php phpinfo(); ?>" > /usr/share/nginx/html/info.php
[root@linuxtechi ~]#
```
在网页浏览器中输入下面的 URL http://<Your-Server-IP>/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 命令安装 MariaDB10.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 上成功地完成安装 LEMPLinux、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

View File

@@ -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 页)。
![](https://jvns.ca/images/curl.jpeg)
### 熟能生巧
对于任何命令行工具,我认为熟练使用是很有帮助的,能够做到只输入必要的命令真是太好了。例如,最近我在测试 Gumroad API我只需要输入
```
curl https://api.gumroad.com/v2/sales \
-d "access_token=<SECRET>" \
-X GET -d "before=2016-09-03"
```
就能从命令行中得到想要的结果。
### 21 个 curl 练习
这些练习是用来理解如何使用 `curl` 构造不同种类的 HTTP 请求的,它们是故意有点重复的,基本上包含了我需要 `curl` 做的任何事情。
为了简单起见,我们将对 https://httpbin.org 发起一系列 HTTP 请求httpbin 接受 HTTP 请求,然后在响应中回显你所发起的 HTTP 请求。
1. 请求 <https://httpbin.org>
2. 请求 <https://httpbin.org/anything>,它将会解析你发起的请求,并且在响应中回显。`curl` 默认发起的是 GET 请求
3. 向 <https://httpbin.org/anything> 发起 GET 请求
4. 向 <https://httpbin.org/anything> 发起 GET 请求,但是这次需要添加一些查询参数(设置 `value=panda`
5. 请求 Google 的 `robots.txt` 文件 ([www.google.com/robots.txt][3])
6. 向 <https://httpbin.org/anything> 发起 GET 请求,并且设置请求头为 `User-Agent: elephant`
7. 向 <https://httpbin.org/anything> 发起 DELETE 请求
8. 请求 <https://httpbin.org/anything> 并获取响应头信息
9. 向 <https://httpbin.com/anything> 发起请求体为 JSON `{"value": "panda"}` 的 POST 请求
10. 发起与上一次相同的 POST 请求,但是这次要把请求头中的 `Content-Type` 字段设置成 `application/json`(因为 POST 请求需要一个与请求体相匹配的 `Content-Type` 请求头字段)。查看响应体中的 `json` 字段,对比上一次得到的响应体
11. 向 <https://httpbin.org/anything> 发起 GET 请求,并且在请求头中设置 `Accept-Encoding: gzip`(将会发生什么?为什么会这样?)
12. 将一些 JSON 放在文件中,然后向 <https://httpbin.org/anything> 发起请求体为该文件的 POST 请求
13. 设置请求头为 `Accept: image/png` 并且向 <https://httpbin.org/image> 发起请求,将输出保存为 PNG 文件,然后使用图片浏览器打开。尝试使用不同的 `Accept:` 字段去请求此 URL
14. 向 <https://httpbin.org/anything> 发起 PUT 请求
15. 请求 <https://httpbin.org/image/jpeg> 并保存为文件,然后使用你的图片编辑器打开这个文件
16. 请求 <https://www.twitter.com>,你将会得到空的响应。让 `curl` 显示出响应头信息,并尝试找出响应内容为空的原因
17. 向 <https://httpbin.org/anything> 发起任意的请求,同时设置一些无意义的请求头(例如:`panda: elephant`
18. 请求 <https://httpbin.org/status/404> 和 <https://httpbin.org/status/200>,然后再次请求它们并且让 curl 显示响应头信息
19. 请求 <https://httpbin.org/anything> 并且设置用户名和密码(使用 `-u username:password`
20. 设置 `Accept-Language: es-ES` 的请求头用以下载 Twitter 的西班牙语主页 (<https://twitter.com>)
21. 使用 `curl` 向 Stripe API 发起请求(请查看 <https://stripe.com/docs/development> 了解如何使用,他们会给你一个测试用的 API key。尝试向 <https://httpbin.org/anything> 发起相同的请求
--------------------------------------------------------------------------------
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

View File

@@ -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 的一些鲜为人知的功能来检查和修复代码。
![](https://img.linux.net.cn/data/attachment/album/201912/05/203701ss8onfvpsnvnsnn5.jpg)
[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 <mydata> : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x01
0x404048 <mydata+8> : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x72
0x404050 <mydata+16>: 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x63
0x404058 <mydata+24>: 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x05
0x404060 <mydata+32>: 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 <sometimes_crashes>
[...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

View File

@@ -0,0 +1,444 @@
[#]: collector: (lujun9972)
[#]: translator: (PsiACE)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11510-1.html)
[#]: subject: (Building a Messenger App: OAuth)
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-oauth/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
构建一个即时消息应用OAuth
======
[上一篇:模式](https://linux.cn/article-11396-1.html)。
在这篇帖子中,我们将会通过为应用添加社交登录功能进入后端开发。
社交登录的工作方式十分简单:用户点击链接,然后重定向到 GitHub 授权页面。当用户授予我们对他的个人信息的访问权限之后,就会重定向回登录页面。下一次尝试登录时,系统将不会再次请求授权,也就是说,我们的应用已经记住了这个用户。这使得整个登录流程看起来就和你用鼠标单击一样快。
如果进一步考虑其内部实现的话,过程就会变得复杂起来。首先,我们需要注册一个新的 [GitHub OAuth 应用][2]。
这一步中,比较重要的是回调 URL。我们将它设置为 `http://localhost:3000/api/oauth/github/callback`。这是因为,在开发过程中,我们总是在本地主机上工作。一旦你要将应用交付生产,请使用正确的回调 URL 注册一个新的应用。
注册以后,你将会收到“客户端 id”和“安全密钥”。安全起见请不要与任何人分享他们 👀
顺便让我们开始写一些代码吧。现在,创建一个 `main.go` 文件:
```
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"net/url"
"os"
"strconv"
"github.com/gorilla/securecookie"
"github.com/joho/godotenv"
"github.com/knq/jwt"
_ "github.com/lib/pq"
"github.com/matryer/way"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
)
var origin *url.URL
var db *sql.DB
var githubOAuthConfig *oauth2.Config
var cookieSigner *securecookie.SecureCookie
var jwtSigner jwt.Signer
func main() {
godotenv.Load()
port := intEnv("PORT", 3000)
originString := env("ORIGIN", fmt.Sprintf("http://localhost:%d/", port))
databaseURL := env("DATABASE_URL", "postgresql://root@127.0.0.1:26257/messenger?sslmode=disable")
githubClientID := os.Getenv("GITHUB_CLIENT_ID")
githubClientSecret := os.Getenv("GITHUB_CLIENT_SECRET")
hashKey := env("HASH_KEY", "secret")
jwtKey := env("JWT_KEY", "secret")
var err error
if origin, err = url.Parse(originString); err != nil || !origin.IsAbs() {
log.Fatal("invalid origin")
return
}
if i, err := strconv.Atoi(origin.Port()); err == nil {
port = i
}
if githubClientID == "" || githubClientSecret == "" {
log.Fatalf("remember to set both $GITHUB_CLIENT_ID and $GITHUB_CLIENT_SECRET")
return
}
if db, err = sql.Open("postgres", databaseURL); err != nil {
log.Fatalf("could not open database connection: %v\n", err)
return
}
defer db.Close()
if err = db.Ping(); err != nil {
log.Fatalf("could not ping to db: %v\n", err)
return
}
githubRedirectURL := *origin
githubRedirectURL.Path = "/api/oauth/github/callback"
githubOAuthConfig = &oauth2.Config{
ClientID: githubClientID,
ClientSecret: githubClientSecret,
Endpoint: github.Endpoint,
RedirectURL: githubRedirectURL.String(),
Scopes: []string{"read:user"},
}
cookieSigner = securecookie.New([]byte(hashKey), nil).MaxAge(0)
jwtSigner, err = jwt.HS256.New([]byte(jwtKey))
if err != nil {
log.Fatalf("could not create JWT signer: %v\n", err)
return
}
router := way.NewRouter()
router.HandleFunc("GET", "/api/oauth/github", githubOAuthStart)
router.HandleFunc("GET", "/api/oauth/github/callback", githubOAuthCallback)
router.HandleFunc("GET", "/api/auth_user", guard(getAuthUser))
log.Printf("accepting connections on port %d\n", port)
log.Printf("starting server at %s\n", origin.String())
addr := fmt.Sprintf(":%d", port)
if err = http.ListenAndServe(addr, router); err != nil {
log.Fatalf("could not start server: %v\n", err)
}
}
func env(key, fallbackValue string) string {
v, ok := os.LookupEnv(key)
if !ok {
return fallbackValue
}
return v
}
func intEnv(key string, fallbackValue int) int {
v, ok := os.LookupEnv(key)
if !ok {
return fallbackValue
}
i, err := strconv.Atoi(v)
if err != nil {
return fallbackValue
}
return i
}
```
安装依赖项:
```
go get -u github.com/gorilla/securecookie
go get -u github.com/joho/godotenv
go get -u github.com/knq/jwt
go get -u github.com/lib/pq
ge get -u github.com/matoous/go-nanoid
go get -u github.com/matryer/way
go get -u golang.org/x/oauth2
```
我们将会使用 `.env` 文件来保存密钥和其他配置。请创建这个文件,并保证里面至少包含以下内容:
```
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
```
我们还要用到的其他环境变量有:
* `PORT`:服务器运行的端口,默认值是 `3000`
* `ORIGIN`:你的域名,默认值是 `http://localhost:3000/`。我们也可以在这里指定端口。
* `DATABASE_URL`Cockroach 数据库的地址。默认值是 `postgresql://root@127.0.0.1:26257/messenger?sslmode=disable`
* `HASH_KEY`:用于为 cookie 签名的密钥。没错,我们会使用已签名的 cookie 来确保安全。
* `JWT_KEY`:用于签署 JSON <ruby>网络令牌<rt>Web Token</rt></ruby>的密钥。
因为代码中已经设定了默认值,所以你也不用把它们写到 `.env` 文件中。
在读取配置并连接到数据库之后,我们会创建一个 OAuth 配置。我们会使用 `ORIGIN` 信息来构建回调 URL就和我们在 GitHub 页面上注册的一样)。我们的数据范围设置为 “read:user”。这会允许我们读取公开的用户信息这里我们只需要他的用户名和头像就够了。然后我们会初始化 cookie 和 JWT 签名器。定义一些端点并启动服务器。
在实现 HTTP 处理程序之前,让我们编写一些函数来发送 HTTP 响应。
```
func respond(w http.ResponseWriter, v interface{}, statusCode int) {
b, err := json.Marshal(v)
if err != nil {
respondError(w, fmt.Errorf("could not marshal response: %v", err))
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(statusCode)
w.Write(b)
}
func respondError(w http.ResponseWriter, err error) {
log.Println(err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
```
第一个函数用来发送 JSON而第二个将错误记录到控制台并返回一个 `500 Internal Server Error` 错误信息。
### OAuth 开始
所以,用户点击写着 “Access with GitHub” 的链接。该链接指向 `/api/oauth/github`,这将会把用户重定向到 github。
```
func githubOAuthStart(w http.ResponseWriter, r *http.Request) {
state, err := gonanoid.Nanoid()
if err != nil {
respondError(w, fmt.Errorf("could not generte state: %v", err))
return
}
stateCookieValue, err := cookieSigner.Encode("state", state)
if err != nil {
respondError(w, fmt.Errorf("could not encode state cookie: %v", err))
return
}
http.SetCookie(w, &http.Cookie{
Name: "state",
Value: stateCookieValue,
Path: "/api/oauth/github",
HttpOnly: true,
})
http.Redirect(w, r, githubOAuthConfig.AuthCodeURL(state), http.StatusTemporaryRedirect)
}
```
OAuth2 使用一种机制来防止 CSRF 攻击,因此它需要一个“状态”(`state`)。我们使用 `Nanoid()` 来创建一个随机字符串,并用这个字符串作为状态。我们也把它保存为一个 cookie。
### OAuth 回调
一旦用户授权我们访问他的个人信息,他将会被重定向到这个端点。这个 URL 的查询字符串上将会包含状态(`state`)和授权码(`code` `/api/oauth/github/callback?state=&code=`
```
const jwtLifetime = time.Hour * 24 * 14
type GithubUser struct {
ID int `json:"id"`
Login string `json:"login"`
AvatarURL *string `json:"avatar_url,omitempty"`
}
type User struct {
ID string `json:"id"`
Username string `json:"username"`
AvatarURL *string `json:"avatarUrl"`
}
func githubOAuthCallback(w http.ResponseWriter, r *http.Request) {
stateCookie, err := r.Cookie("state")
if err != nil {
http.Error(w, http.StatusText(http.StatusTeapot), http.StatusTeapot)
return
}
http.SetCookie(w, &http.Cookie{
Name: "state",
Value: "",
MaxAge: -1,
HttpOnly: true,
})
var state string
if err = cookieSigner.Decode("state", stateCookie.Value, &state); err != nil {
http.Error(w, http.StatusText(http.StatusTeapot), http.StatusTeapot)
return
}
q := r.URL.Query()
if state != q.Get("state") {
http.Error(w, http.StatusText(http.StatusTeapot), http.StatusTeapot)
return
}
ctx := r.Context()
t, err := githubOAuthConfig.Exchange(ctx, q.Get("code"))
if err != nil {
respondError(w, fmt.Errorf("could not fetch github token: %v", err))
return
}
client := githubOAuthConfig.Client(ctx, t)
resp, err := client.Get("https://api.github.com/user")
if err != nil {
respondError(w, fmt.Errorf("could not fetch github user: %v", err))
return
}
var githubUser GithubUser
if err = json.NewDecoder(resp.Body).Decode(&githubUser); err != nil {
respondError(w, fmt.Errorf("could not decode github user: %v", err))
return
}
defer resp.Body.Close()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
respondError(w, fmt.Errorf("could not begin tx: %v", err))
return
}
var user User
if err = tx.QueryRowContext(ctx, `
SELECT id, username, avatar_url FROM users WHERE github_id = $1
`, githubUser.ID).Scan(&user.ID, &user.Username, &user.AvatarURL); err == sql.ErrNoRows {
if err = tx.QueryRowContext(ctx, `
INSERT INTO users (username, avatar_url, github_id) VALUES ($1, $2, $3)
RETURNING id
`, githubUser.Login, githubUser.AvatarURL, githubUser.ID).Scan(&user.ID); err != nil {
respondError(w, fmt.Errorf("could not insert user: %v", err))
return
}
user.Username = githubUser.Login
user.AvatarURL = githubUser.AvatarURL
} else if err != nil {
respondError(w, fmt.Errorf("could not query user by github ID: %v", err))
return
}
if err = tx.Commit(); err != nil {
respondError(w, fmt.Errorf("could not commit to finish github oauth: %v", err))
return
}
exp := time.Now().Add(jwtLifetime)
token, err := jwtSigner.Encode(jwt.Claims{
Subject: user.ID,
Expiration: json.Number(strconv.FormatInt(exp.Unix(), 10)),
})
if err != nil {
respondError(w, fmt.Errorf("could not create token: %v", err))
return
}
expiresAt, _ := exp.MarshalText()
data := make(url.Values)
data.Set("token", string(token))
data.Set("expires_at", string(expiresAt))
http.Redirect(w, r, "/callback?"+data.Encode(), http.StatusTemporaryRedirect)
}
```
首先,我们会尝试使用之前保存的状态对 cookie 进行解码。并将其与查询字符串中的状态进行比较。如果它们不匹配,我们会返回一个 `418 I'm teapot`(未知来源)错误。
接着,我们使用授权码生成一个令牌。这个令牌被用于创建 HTTP 客户端来向 GitHub API 发出请求。所以最终我们会向 `https://api.github.com/user` 发送一个 GET 请求。这个端点将会以 JSON 格式向我们提供当前经过身份验证的用户信息。我们将会解码这些内容,一并获取用户的 ID、登录名用户名和头像 URL。
然后我们将会尝试在数据库上找到具有该 GitHub ID 的用户。如果没有找到,就使用该数据创建一个新的。
之后,对于新创建的用户,我们会发出一个将用户 ID 作为主题(`Subject`)的 JSON 网络令牌,并使用该令牌重定向到前端,查询字符串中一并包含该令牌的到期日(`Expiration`)。
这一 Web 应用也会被用在其他帖子,但是重定向的链接会是 `/callback?token=&expires_at=`。在那里,我们将会利用 JavaScript 从 URL 中获取令牌和到期日,并通过 `Authorization` 标头中的令牌以 `Bearer token_here` 的形式对 `/api/auth_user` 进行 GET 请求,来获取已认证的身份用户并将其保存到 localStorage。
### Guard 中间件
为了获取当前已经过身份验证的用户,我们设计了 Guard 中间件。这是因为在接下来的文章中,我们会有很多需要进行身份认证的端点,而中间件将会允许我们共享这一功能。
```
type ContextKey struct {
Name string
}
var keyAuthUserID = ContextKey{"auth_user_id"}
func guard(handler http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var token string
if a := r.Header.Get("Authorization"); strings.HasPrefix(a, "Bearer ") {
token = a[7:]
} else if t := r.URL.Query().Get("token"); t != "" {
token = t
} else {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
var claims jwt.Claims
if err := jwtSigner.Decode([]byte(token), &claims); err != nil {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, keyAuthUserID, claims.Subject)
handler(w, r.WithContext(ctx))
}
}
```
首先,我们尝试从 `Authorization` 标头或者是 URL 查询字符串中的 `token` 字段中读取令牌。如果没有找到,我们需要返回 `401 Unauthorized`(未授权)错误。然后我们将会对令牌中的申明进行解码,并使用该主题作为当前已经过身份验证的用户 ID。
现在,我们可以用这一中间件来封装任何需要授权的 `http.handlerFunc`,并且在处理函数的上下文中保有已经过身份验证的用户 ID。
```
var guarded = guard(func(w http.ResponseWriter, r *http.Request) {
authUserID := r.Context().Value(keyAuthUserID).(string)
})
```
### 获取认证用户
```
func getAuthUser(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
authUserID := ctx.Value(keyAuthUserID).(string)
var user User
if err := db.QueryRowContext(ctx, `
SELECT username, avatar_url FROM users WHERE id = $1
`, authUserID).Scan(&user.Username, &user.AvatarURL); err == sql.ErrNoRows {
http.Error(w, http.StatusText(http.StatusTeapot), http.StatusTeapot)
return
} else if err != nil {
respondError(w, fmt.Errorf("could not query auth user: %v", err))
return
}
user.ID = authUserID
respond(w, user, http.StatusOK)
}
```
我们使用 Guard 中间件来获取当前经过身份认证的用户 ID 并查询数据库。
这一部分涵盖了后端的 OAuth 流程。在下一篇帖子中,我们将会看到如何开始与其他用户的对话。
- [源代码][3]
--------------------------------------------------------------------------------
via: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
译者:[PsiACE](https://github.com/PsiACE)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
[2]: https://github.com/settings/applications/new
[3]: https://github.com/nicolasparada/go-messenger-demo

View File

@@ -0,0 +1,261 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11499-1.html)
[#]: subject: (How writers can get work done better with Git)
[#]: via: (https://opensource.com/article/19/4/write-git)
[#]: author: (Seth Kenlon https://opensource.com/users/sethhttps://opensource.com/users/noreplyhttps://opensource.com/users/seth)
用 Git 帮助写作者更好地完成工作
======
> 如果你是一名写作者,你也能从使用 Git 中受益。在我们的系列文章中了解有关 Git 鲜为人知的用法。
![](https://img.linux.net.cn/data/attachment/album/201910/24/222747ltajik2ymzmmttha.png)
[Git][2] 是一个少有的能将如此多的现代计算封装到一个程序之中的应用程序,它可以用作许多其他应用程序的计算引擎。虽然它以跟踪软件开发中的源代码更改而闻名,但它还有许多其他用途,可以让你的生活更轻松、更有条理。在这个 Git 系列中,我们将分享七种鲜为人知的使用 Git 的方法。
今天我们来看看写作者如何使用 Git 更好的地完成工作。
### 写作者的 Git
有些人写小说,也有人撰写学术论文、诗歌、剧本、技术手册或有关开源的文章。许多人都在做一些各种写作。相同的是,如果你是一名写作者,或许能从使用 Git 中受益。尽管 Git 是著名的计算机程序员所使用的高度技术性工具,但它也是现代写作者的理想之选,本文将向你演示如何改变你的书写方式以及为什么要这么做的原因。
但是,在谈论 Git 之前,重要的是先谈谈“副本”(或者叫“内容”,对于数字时代而言)到底是什么,以及为什么它与你的交付*媒介*不同。这是 21 世纪,大多数写作者选择的工具是计算机。尽管计算机看似擅长将副本的编辑和布局等过程结合在一起,但写作者还是(重新)发现将内容与样式分开是一个好主意。这意味着你应该在计算机上像在打字机上而不是在文字处理器中进行书写。以计算机术语而言,这意味着以*纯文本*形式写作。
### 以纯文本写作
这个假设曾经是毫无疑问的:你知道自己的写作所要针对的市场,你可以为书籍、网站或软件手册等不同市场编写内容。但是,近来各种市场趋于扁平化:你可能决定在纸质书中使用为网站编写的内容,并且纸质书可能会在以后发布 EPUB 版本。对于你的内容的数字版本,读者才是最终控制者:他们可以在你发布内容的网站上阅读你的文字,也可以点击 Firefox 出色的[阅读视图][3],还可能会打印到纸张上,或者可能会使用 Lynx 将网页转储到文本文件中,甚至可能因为使用屏幕阅读器而根本看不到你的内容。
你只需要逐字写下你的内容,而将交付工作留给发布者。即使你是自己发布,将字词作为写作作品的一种源代码也是一种更聪明、更有效的工作方式,因为在发布时,你可以使用相同的源(你的纯文本)生成适合你的目标输出(用于打印的 PDF、用于电子书的 EPUB、用于网站的 HTML 等)。
用纯文本编写不仅意味着你不必担心布局或文本样式,而且也不再需要专门的工具。无论是手机或平板电脑上的基本的记事本应用程序、计算机附带的文本编辑器,还是从互联网上下载的免费编辑器,任何能够产生文本内容的工具对你而言都是有效的“文字处理器”。无论你身在何处或在做什么,几乎可以在任何设备上书写,并且所生成的文本可以与你的项目完美集成,而无需进行任何修改。
而且Git 专门用来管理纯文本。
### Atom 编辑器
当你以纯文本形式书写时,文字处理程序会显得过于庞大。使用文本编辑器更容易,因为文本编辑器不会尝试“有效地”重组输入内容。它使你可以将脑海中的单词输入到屏幕中,而不会受到干扰。更好的是,文本编辑器通常是围绕插件体系结构设计的,这样应用程序本身很基础(它用来编辑文本),但是你可以围绕它构建一个环境来满足你的各种需求。
[Atom][4] 编辑器就是这种设计理念的一个很好的例子。这是一个具有内置 Git 集成的跨平台文本编辑器。如果你不熟悉纯文本格式,也不熟悉 Git那么 Atom 是最简单的入门方法。
#### 安装 Git 和 Atom
首先,请确保你的系统上已安装 Git。如果运行 Linux 或 BSD则 Git 在软件存储库或 ports 树中可用。你使用的命令将根据你的发行版而有所不同。例如在 Fedora 上:
```
$ sudo dnf install git
```
你也可以下载并安装适用于 [Mac][5] 和 [Windows][6] 的 Git。
你不需要直接使用 Git因为 Atom 会充当你的 Git 界面。下一步是安装 Atom。
如果你使用的是 Linux请通过软件安装程序或适当的命令从软件存储库中安装 Atom例如
```
$ sudo dnf install atom
```
Atom 当前没有在 BSD 上构建。但是,有很好的替代方法,例如 [GNU Emacs][7]。对于 Mac 和 Windows 用户,可以在 [Atom 网站][4]上找到安装程序。
安装完成后,启动 Atom 编辑器。
#### 快速指导
如果要使用纯文本和 Git则需要适应你的编辑器。Atom 的用户界面可能比你习惯的更加动态。实际上,你可以将它视为 Firefox 或 Chrome而不是文字处理程序因为它具有可以根据需要打开或关闭的选项卡和面板甚至还可以安装和配置附件。尝试全部掌握 Atom 如许之多的功能是不切实际的,但是你至少可以知道有什么功能。
当打开 Atom 时,它将显示一个欢迎屏幕。如果不出意外,此屏幕很好地介绍了 Atom 的选项卡式界面。你可以通过单击 Atom 窗口顶部选项卡上的“关闭”图标来关闭欢迎屏幕,并使用“文件 > 新建文件”创建一个新文件。
使用纯文本格式与使用文字处理程序有点不同,因此这里有一些技巧,以人可以理解的方式编写内容,并且 Git 和计算机可以解析,跟踪和转换。
#### 用 Markdown 书写
如今,当人们谈论纯文本时,大多是指 Markdown。Markdown 与其说是格式不如说是样式这意味着它旨在为文本提供可预测的结构以便计算机可以检测自然的模式并智能地转换文本。Markdown 有很多定义,但是最好的技术定义和备忘清单在 [CommonMark 的网站][8]上。
```
# Chapter 1
This is a paragraph with an *italic* word and a **bold** word in it.
And it can even reference an image.
![An image will render here.](drawing.jpg)
```
从示例中可以看出Markdown 读起来感觉不像代码,但可以将其视为代码。如果你遵循 CommonMark 定义的 Markdown 规范,那么一键就可以可靠地将 Markdown 的文字转换为 .docx、.epub、.html、MediaWiki、.odt、.pdf、.rtf 和各种其他的格式,而*不会*失去格式。
你可以认为 Markdown 有点像文字处理程序的样式。如果你曾经为出版社撰写过一套样式来控制章节标题及其样式,那基本上就是一回事,除了不是从下拉菜单中选择样式以外,你需要给你的文字添加一些小记号。对于任何习惯“以文字交谈”的现代阅读者来说,这些表示法都是很自然的,但是在呈现文本时,它们会被精美的文本样式替换掉。实际上,这就是文字处理程序在后台秘密进行的操作。文字处理器显示粗体文本,但是如果你可以看到使文本变为粗体的生成代码,则它与 Markdown 很像(实际上,它是更复杂的 XML。使用 Markdown 可以消除这种代码和样式之间的阻隔,一方面看起来更可怕一些,但另一方面,你可以在几乎所有可以生成文本的东西上书写 Markdown 而不会丢失任何格式信息。
Markdown 文件流行的文件扩展名是 .md。如果你使用的平台不知道 .md 文件是什么,则可以手动将该扩展名与 Atom 关联,或者仅使用通用的 .txt 扩展名。文件扩展名不会更改文件的性质。它只会改变你的计算机决定如何处理它的方式。Atom 和某些平台足够聪明,可以知道该文件是纯文本格式,无论你给它以什么扩展名。
#### 实时预览
Atom 具有 “Markdown 预览” 插件,该插件可以向你显示正在编写的纯文本 Markdown 及其(通常)呈现的方式。
![Atom's preview screen][9]
要激活此预览窗格,请选择“包 > Markdown 预览 > 切换预览” 或按 `Ctrl + Shift + M`
此视图为你提供了两全其美的方法。无需承担为你的文本添加样式的负担就可以写作,而你也可以看到一个通用的示例外观,至少是以典型的数字化格式显示文本的外观。当然,关键是你无法控制文本的最终呈现方式,因此不要试图调整 Markdown 来强制以某种方式显示呈现的预览。
#### 每行一句话
你的高中写作老师不会看你的 Markdown。
一开始它不那么自然但是在数字世界中保持每行一个句子更有意义。Markdown 会忽略单个换行符(当你按下 `Return``Enter` 键时),并且只在单个空行之后才会创建一个新段落。
![Writing in Atom][10]
每行写一个句子的好处是你的工作更容易跟踪。也就是说,假如你在段落的开头更改了一个单词,如果更改仅限于一行而不是一个长的段落中的一个单词,那么 Atom、Git 或任何应用程序很容易以有意义的方式突出显示该更改。换句话说,对一个句子的更改只会影响该句子,而不会影响整个段落。
你可能会想:“许多文字处理器也可以跟踪更改,它们可以突出显示已更改的单个单词。”但是这些修订跟踪器绑定在该字处理器的界面上,这意味着你必须先打开该字处理器才能浏览修订。在纯文本工作流程中,你可以以纯文本形式查看修订,这意味着无论手头有什么,只要该设备可以处理纯文本(大多数都可以),就可以进行编辑或批准编辑。
诚然写作者通常不会考虑行号但它对于计算机有用并且通常是一个很好的参考点。默认情况下Atom 为文本文档的行进行编号。按下 `Enter` 键或 `Return` 键后,一*行*就是一行。
![Writing in Atom][11]
如果(在 Atom 的)一行的行号中有一个点而不是一个数字,则表示它是上一行折叠的一部分,因为它超出了你的屏幕。
#### 主题
如果你是一个在意视觉形象的人,那么你可能会非常注重自己的写作环境。即使你使用普通的 Markdown 进行编写,也并不意味着你必须使用程序员的字体或在使你看起来像码农的黑窗口中进行书写。修改 Atom 外观的最简单方法是使用[主题包][12]。主题设计人员通常将深色主题与浅色主题区分开因此你可以根据需要使用关键字“Dark”或“Light”进行搜索。
要安装主题,请选择“编辑 > 首选项”。这将在 Atom 界面中打开一个新标签页。是的,标签页可以用于处理文档*和*用于配置及控制面板。在“设置”标签页中,单击“安装”类别。
在“安装”面板中,搜索要安装的主题的名称。单击搜索字段右侧的“主题”按钮,以仅搜索主题。找到主题后,单击其“安装”按钮。
![Atom's themes][13]
要使用已安装的主题或根据喜好自定义主题,请导航至“设置”标签页中的“主题”类别中。从下拉菜单中选择要使用的主题。更改会立即进行,因此你可以准确了解主题如何影响你的环境。
你也可以在“设置”标签的“编辑器”类别中更改工作字体。Atom 默认采用等宽字体,程序员通常首选这种字体。但是你可以使用系统上的任何字体,无论是衬线字体、无衬线字体、哥特式字体还是草书字体。无论你想整天盯着什么字体都行。
作为相关说明默认情况下Atom 会在其屏幕上绘制一条垂直线,以提示编写代码的人员。程序员通常不想编写太长的代码行,因此这条垂直线会提醒他们不要写太长的代码行。不过,这条竖线对写作者而言毫无意义,你可以通过禁用 “wrap-guide” 包将其删除。
要禁用 “wrap-guide” 软件包,请在“设置”标签中选择“折行”类别,然后搜索 “wrap-guide”。找到该程序包后单击其“禁用”按钮。
#### 动态结构
创建长文档时,我发现每个文件写一个章节比在一个文件中写整本书更有意义。此外,我不会以明显的语法 ` chapter-1.md``1.example.md` 来命名我的章节,而是以章节标题或关键词(例如 `example.md`)命名。为了将来为自己提供有关如何编写本书的指导,我维护了一个名为 `toc.md` (用于“目录”)的文件,其中列出了各章的(当前)顺序。
我这样做是因为,无论我多么相信第 6 章都不可能出现在第 1 章之前,但在我完成整本书之前,几乎难以避免我会交换一两个章节的顺序。我发现从一开始就保持动态变化可以帮助我避免重命名混乱,也可以帮助我避免僵化的结构。
### 在 Atom 中使用 Git
每位写作者的共同点是两件事:他们为流传而写作,而他们的写作是一段旅程。你不能一坐下来写作就完成了最终稿件。顾名思义,你有一个初稿。该草稿会经过修订,你会仔细地将每个修订保存一式两份或三份的备份,以防万一你的文件损坏了。最终,你得到了所谓的最终草稿,但很有可能你有一天还会回到这份最终草稿,要么恢复好的部分,要么修改坏的部分。
Atom 最令人兴奋的功能是其强大的 Git 集成。无需离开 Atom你就可以与 Git 的所有主要功能进行交互,跟踪和更新项目、回滚你不喜欢的更改、集成来自协作者的更改等等。最好的学习方法就是逐步学习,因此这是在一个写作项目中从始至终在 Atom 界面中使用 Git 的方法。
第一件事:通过选择 “视图 > 切换 Git 标签页” 来显示 Git 面板。这将在 Atom 界面的右侧打开一个新标签页。现在没什么可看的,所以暂时保持打开状态就行。
#### 建立一个 Git 项目
你可以认为 Git 被绑定到一个文件夹。Git 目录之外的任何文件夹都不知道 Git而 Git 也不知道外面。Git 目录中的文件夹和文件将被忽略,直到你授予 Git 权限来跟踪它们为止。
你可以通过在 Atom 中创建新的项目文件夹来创建 Git 项目。选择 “文件 > 添加项目文件夹”,然后在系统上创建一个新文件夹。你创建的文件夹将出现在 Atom 窗口的左侧“项目面板”中。
#### Git 添加文件
右键单击你的新项目文件夹然后选择“新建文件”以在项目文件夹中创建一个新文件。如果你要导入文件到新项目中请右键单击该文件夹然后选择“在文件管理器中显示”以在系统的文件查看器中打开该文件夹Linux 上为 Dolphin 或 NautilusMac 上为 Finder在 Windows 上是 Explorer然后拖放文件到你的项目文件夹。
在 Atom 中打开一个项目文件(你创建的空文件或导入的文件)后,单击 Git 标签中的 “<ruby>创建存储库<rt>Create Repository</rt></ruby>” 按钮。在弹出的对话框中,单击 “<ruby>初始化<rt>Init</rt></ruby>” 以将你的项目目录初始化为本地 Git 存储库。 Git 会将 `.git` 目录(在系统的文件管理器中不可见,但在 Atom 中可见)添加到项目文件夹中。不要被这个愚弄了:`.git` 目录是 Git 管理的,而不是由你管理的,因此一般你不要动它。但是在 Atom 中看到它可以很好地提醒你正在由 Git 管理的项目中工作。换句话说,当你看到 `.git` 目录时,就有了修订历史记录。
在你的空文件中,写一些东西。你是写作者,所以输入一些单词就行。你可以随意输入任何一组单词,但要记住上面的写作技巧。
`Ctrl + S` 保存文件,该文件将显示在 Git 标签的 “<ruby>未暂存的改变<rt>Unstaged Changes</rt></ruby>” 部分中。这意味着该文件存在于你的项目文件夹中,但尚未提交给 Git 管理。通过单击 Git 选项卡右上方的 “<ruby>暂存全部<rt>Stage All</rt></ruby>” 按钮,以允许 Git 跟踪这些文件。如果你使用过带有修订历史记录的文字处理器,则可以将此步骤视为允许 Git 记录更改。
#### Git 提交
你的文件现在已暂存。这意味着 Git 知道该文件存在,并且知道自上次 Git 知道该文件以来,该文件已被更改。
Git 的<ruby>提交<rt>commit</rt></ruby>会将你的文件发送到 Git 的内部和永久存档中。如果你习惯于文字处理程序,这就类似于给一个修订版命名。要创建一个提交,请在 Git 选项卡底部的“<ruby>提交<rt>Commit</rt></ruby>”消息框中输入一些描述性文本。你可能会感到含糊不清或随意写点什么,但如果你想在将来知道进行修订的原因,那么输入一些有用的信息会更有用。
第一次提交时,必须创建一个<ruby>分支<rt>branch</rt></ruby>。Git 分支有点像另外一个空间,它允许你从一个时间轴切换到另一个时间轴,以进行你可能想要也可能不想要永久保留的更改。如果最终喜欢该更改,则可以将一个实验分支合并到另一个实验分支,从而统一项目的不同版本。这是一个高级过程,不需要先学会,但是你仍然需要一个活动分支,因此你必须为首次提交创建一个分支。
单击 Git 选项卡最底部的“<ruby>分支<rt>Branch</rt></ruby>”图标,以创建新的分支。
![Creating a branch][14]
通常将第一个分支命名为 `master`,但不是必须如此;你可以将其命名为 `firstdraft` 或任何你喜欢的名称,但是遵守当地习俗有时会使谈论 Git和查找问题的答案变得容易一些因为你会知道有人提到 “master” 时,它们的真正意思是“主干”而不是“初稿”或你给分支起的什么名字。
在某些版本的 Atom 上UI 也许不会更新以反映你已经创建的新分支。不用担心,做了提交之后,它会创建分支(并更新 UI。按下 “<ruby>提交<rt>Commit</rt></ruby>” 按钮,无论它显示的是 “<ruby>创建脱离的提交<rt>Create detached commit</rt></ruby>” 还是 “<ruby>提交到主干<rt>Commit to master</rt></ruby>。
提交后,文件的状态将永久保留在 Git 的记忆之中。
#### 历史记录和 Git 差异
一个自然而然的问题是你应该多久做一次提交。这并没有正确的答案。使用 `Ctrl + S` 保存文件和提交到 Git 是两个单独的过程,因此你会一直做这两个过程。每当你觉得自己已经做了重要的事情或打算尝试一个可能会被干掉的疯狂的新想法时,你可能都会想要做次提交。
要了解提交对工作流程的影响,请从测试文档中删除一些文本,然后在顶部和底部添加一些文本。再次提交。 这样做几次,直到你在 Git 标签的底部有了一小段历史记录,然后单击其中一个提交以在 Atom 中查看它。
![Viewing differences][15]
查看过去的提交时,你会看到三种元素:
1. 绿色文本是该提交中已被添加到文档中的内容。
2. 红色文本是该提交中已从文档中删除的内容。
3. 其他所有文字均未做更改。
#### 远程备份
使用 Git 的优点之一是,按照设计它是分布式的,这意味着你可以将工作提交到本地存储库,并将所做的更改推送到任意数量的服务器上进行备份。你还可以从这些服务器中拉取更改,以便你碰巧正在使用的任何设备始终具有最新更改。
为此,你必须在 Git 服务器上拥有一个帐户。有几种免费的托管服务,其中包括 GitHub这个公司开发了 Atom但奇怪的是 GitHub 不是开源的;而 GitLab 是开源的。相比私有软件,我更喜欢开源,在本示例中,我将使用 GitLab。
如果你还没有 GitLab 帐户,请注册一个帐户并开始一个新项目。项目名称不必与 Atom 中的项目文件夹匹配,但是如果匹配,则可能更有意义。你可以将项目保留为私有,在这种情况下,只有你和任何一个你给予了明确权限的人可以访问它,或者,如果你希望该项目可供任何互联网上偶然发现它的人使用,则可以将其公开。
不要将 README 文件添加到项目中。
创建项目后,它将为你提供有关如何设置存储库的说明。如果你决定在终端中或通过单独的 GUI 使用 Git这是非常有用的信息但是 Atom 的工作流程则有所不同。
单击 GitLab 界面右上方的 “<ruby>克隆<rt>Clone</rt></ruby>” 按钮。这显示了访问 Git 存储库必须使用的地址。复制 “SSH” 地址(而不是 “https” 地址)。
在 Atom 中,点击项目的 `.git` 目录,然后打开 `config` 文件。将下面这些配置行添加到该文件中,调整 `url` 值的 `seth/example.git` 部分以匹配你自己独有的地址。
```
[remote "origin"]
url = git@gitlab.com:seth/example.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
```
在 Git 标签的底部,出现了一个新按钮,标记为 “<ruby>提取<rt>Fetch</rt></ruby>”。由于你的服务器是全新的服务器,因此没有可供你提取的数据,因此请右键单击该按钮,然后选择“<ruby>推送<rt>Push</rt></ruby>”。这会将你的更改推送到你的 GitLab 帐户,现在你的项目已备份到 Git 服务器上。
你可以在每次提交后将更改推送到服务器。它提供了即刻的异地备份,并且由于数据量通常很少,因此它几乎与本地保存一样快。
### 撰写而 Git
Git 是一个复杂的系统,不仅对修订跟踪和备份有用。它还支持异步协作并鼓励实验。本文介绍了一些基础知识,但还有更多关于 Git 的文章和整本的书,以及如何使用它使你的工作更高效、更具弹性和更具活力。 从使用 Git 完成小任务开始,使用的次数越多,你会发现自己提出的问题就越多,最终你将学到的技巧越多。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/4/write-git
作者:[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/sethhttps://opensource.com/users/noreplyhttps://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/write-hand_0.jpg?itok=Uw5RJD03 (Writing Hand)
[2]: https://git-scm.com/
[3]: https://support.mozilla.org/en-US/kb/firefox-reader-view-clutter-free-web-pages
[4]: http://atom.io
[5]: https://git-scm.com/download/mac
[6]: https://git-scm.com/download/win
[7]: http://gnu.org/software/emacs
[8]: https://commonmark.org/help/
[9]: https://opensource.com/sites/default/files/uploads/atom-preview.jpg (Atom's preview screen)
[10]: https://opensource.com/sites/default/files/uploads/atom-para.jpg (Writing in Atom)
[11]: https://opensource.com/sites/default/files/uploads/atom-linebreak.jpg (Writing in Atom)
[12]: https://atom.io/themes
[13]: https://opensource.com/sites/default/files/uploads/atom-theme.jpg (Atom's themes)
[14]: https://opensource.com/sites/default/files/uploads/atom-branch.jpg (Creating a branch)
[15]: https://opensource.com/sites/default/files/uploads/git-diff.jpg (Viewing differences)
[16]: mailto:git@gitlab.com

View File

@@ -0,0 +1,151 @@
[#]: collector: (lujun9972)
[#]: translator: (laingke)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11478-1.html)
[#]: subject: (What is a Java constructor?)
[#]: via: (https://opensource.com/article/19/6/what-java-constructor)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
什么是 Java 构造器?
======
> 构造器是编程的强大组件。使用它们来释放 Java 的全部潜力。
![](https://img.linux.net.cn/data/attachment/album/201910/18/230523hdx7sy804xdtxybb.jpg)
在开源、跨平台编程领域Java 无疑(?)是无可争议的重量级语言。尽管有许多[伟大的跨平台][2][框架][3],但很少有像 [Java][4] 那样统一和直接的。
当然Java 也是一种非常复杂的语言具有自己的微妙之处和惯例。Java 中与<ruby>构造器<rt> constructor</rt></ruby>有关的最常见问题之一是:它们是什么,它们的作用是什么?
简而言之:构造器是在 Java 中创建新<ruby>对象<rt>object</rt></ruby>时执行的操作。当 Java 应用程序创建一个你编写的类的实例时,它将检查构造器。如果(该类)存在构造器,则 Java 在创建实例时将运行构造器中的代码。这几句话中包含了大量的技术术语,但是当你看到它的实际应用时就会更加清楚,所以请确保你已经[安装了 Java][5] 并准备好进行演示。
### 没有使用构造器的开发日常
如果你正在编写 Java 代码那么你已经在使用构造器了即使你可能不知道它。Java 中的所有类都有一个构造器因为即使你没有创建构造器Java 也会在编译代码时为你生成一个。但是,为了进行演示,请忽略 Java 提供的隐藏构造器(因为默认构造器不添加任何额外的功能),并观察没有显式构造器的情况。
假设你正在编写一个简单的 Java 掷骰子应用程序,因为你想为游戏生成一个伪随机数。
首先,你可以创建骰子类来表示一个骰子。你玩了很久[《龙与地下城》][6],所以你决定创建一个 20 面的骰子。在这个示例代码中,变量 `dice` 是整数 20表示可能的最大掷骰数一个 20 边骰子的掷骰数不能超过 20。变量 `roll` 是最终的随机数的占位符,`rand` 用作随机数种子。
```
import java.util.Random;
public class DiceRoller {
private int dice = 20;
private int roll;
private Random rand = new Random();
```
接下来,在 `DiceRoller` 类中创建一个函数,以执行计算机模拟模子滚动所必须采取的步骤:从 `rand` 中获取一个整数并将其分配给 `roll`变量,考虑到 Java 从 0 开始计数但 20 面的骰子没有 0 值的情况,`roll` 再加 1 ,然后打印结果。
```
import java.util.Random;
public class DiceRoller {
private int dice = 20;
private int roll;
private Random rand = new Random();
```
最后,产生 `DiceRoller` 类的实例并调用其关键函数 `Roller`
```
// main loop
public static void main (String[] args) {
System.out.printf("You rolled a ");
DiceRoller App = new DiceRoller();
App.Roller();
}
}
```
只要你安装了 Java 开发环境(如 [OpenJDK][10]),你就可以在终端上运行你的应用程序:
```
$ java dice.java
You rolled a 12
```
在本例中,没有显式构造器。这是一个非常有效和合法的 Java 应用程序,但是它有一点局限性。例如,如果你把游戏《龙与地下城》放在一边,晚上去玩一些《快艇骰子》,你将需要六面骰子。在这个简单的例子中,更改代码不会有太多的麻烦,但是在复杂的代码中这不是一个现实的选择。解决这个问题的一种方法是使用构造器。
### 构造函数的作用
这个示例项目中的 `DiceRoller` 类表示一个虚拟骰子工厂:当它被调用时,它创建一个虚拟骰子,然后进行“滚动”。然而,通过编写一个自定义构造器,你可以让掷骰子的应用程序询问你希望模拟哪种类型的骰子。
大部分代码都是一样的,除了构造器接受一个表示面数的数字参数。这个数字还不存在,但稍后将创建它。
```
import java.util.Random;
public class DiceRoller {
private int dice;
private int roll;
private Random rand = new Random();
// constructor
public DiceRoller(int sides) {
dice = sides;
}
```
模拟滚动的函数保持不变:
```
public void Roller() {
roll = rand.nextInt(dice);
roll += 1;
System.out.println (roll);
}
```
代码的主要部分提供运行应用程序时提供的任何参数。这的确会是一个复杂的应用程序,你需要仔细解析参数并检查意外结果,但对于这个例子,唯一的预防措施是将参数字符串转换成整数类型。
```
public static void main (String[] args) {
System.out.printf("You rolled a ");
DiceRoller App = new DiceRoller( Integer.parseInt(args[0]) );
App.Roller();
}
```
启动这个应用程序,并提供你希望骰子具有的面数:
```
$ java dice.java 20
You rolled a 10
$ java dice.java 6
You rolled a 2
$ java dice.java 100
You rolled a 44
```
构造器已接受你的输入,因此在创建类实例时,会将 `sides` 变量设置为用户指定的任何数字。
构造器是编程的功能强大的组件。练习用它们来解开了 Java 的全部潜力。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/6/what-java-constructor
作者:[Seth Kenlon][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/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/build_structure_tech_program_code_construction.png?itok=nVsiLuag
[2]: https://opensource.com/resources/python
[3]: https://opensource.com/article/17/4/pyqt-versus-wxpython
[4]: https://opensource.com/resources/java
[5]: https://openjdk.java.net/install/index.html
[6]: https://opensource.com/article/19/5/free-rpg-day
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+random
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[10]: https://openjdk.java.net/
[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+integer

View File

@@ -0,0 +1,257 @@
[#]: collector: (lujun9972)
[#]: translator: (lnrCoder)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11480-1.html)
[#]: subject: (How to Install and Configure PostgreSQL on Ubuntu)
[#]: via: (https://itsfoss.com/install-postgresql-ubuntu/)
[#]: author: (Sergiu https://itsfoss.com/author/sergiu/)
如何在 Ubuntu 上安装和配置 PostgreSQL
======
> 本教程中,你将学习如何在 Ubuntu Linux 上安装和使用开源数据库 PostgreSQL。
[PostgreSQL][1] (又名 Postgres) 是一个功能强大的自由开源的关系型数据库管理系统 ([RDBMS][2]) ,其在可靠性、稳定性、性能方面获得了业内极高的声誉。它旨在处理各种规模的任务。它是跨平台的,而且是 [macOS Server][3] 的默认数据库。
如果你喜欢简单易用的 SQL 数据库管理器,那么 PostgreSQL 将是一个正确的选择。PostgreSQL 对标准的 SQL 兼容的同时提供了额外的附加特性,同时还可以被用户大量扩展,用户可以添加数据类型、函数并执行更多的操作。
之前我曾论述过 [在 Ubuntu 上安装 MySQL][4]。在本文中,我将向你展示如何安装和配置 PostgreSQL以便你随时可以使用它来满足你的任何需求。
![][5]
### 在 Ubuntu 上安装 PostgreSQL
PostgreSQL 可以从 Ubuntu 主存储库中获取。然而,和许多其它开发工具一样,它可能不是最新版本。
首先在终端中使用 [apt 命令][7] 检查 [Ubuntu 存储库][6] 中可用的 PostgreSQL 版本:
```
apt show postgresql
```
在我的 Ubuntu 18.04 中,它显示 PostgreSQL 的可用版本是 1010+190 表示版本 10而 PostgreSQL 版本 11 已经发布。
```
Package: postgresql
Version: 10+190
Priority: optional
Section: database
Source: postgresql-common (190)
Origin: Ubuntu
```
根据这些信息,你可以自主决定是安装 Ubuntu 提供的版本还是还是获取 PostgreSQL 的最新发行版。
我将向你介绍这两种方法:
#### 方法一:通过 Ubuntu 存储库安装 PostgreSQL
在终端中,使用以下命令安装 PostgreSQL
```
sudo apt update
sudo apt install postgresql postgresql-contrib
```
根据提示输入你的密码,依据于你的网速情况,程序将在几秒到几分钟安装完成。说到这一点,随时检查 [Ubuntu 中的各种网络带宽][8]。
> 什么是 postgresql-contrib?
> postgresql-contrib 或者说 contrib 包,包含一些不属于 PostgreSQL 核心包的实用工具和功能。在大多数情况下,最好将 contrib 包与 PostgreSQL 核心一起安装。
#### 方法二:在 Ubuntu 中安装最新版本的 PostgreSQL 11
要安装 PostgreSQL 11, 你需要在 `sources.list` 中添加官方 PostgreSQL 存储库和证书,然后从那里安装它。
不用担心,这并不复杂。 只需按照以下步骤。
首先添加 GPG 密钥:
```
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
```
现在,使用以下命令添加存储库。如果你使用的是 Linux Mint则必须手动替换你的 Mint 所基于的 Ubuntu 版本号:
```
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
```
现在一切就绪。使用以下命令安装 PostgreSQL
```
sudo apt update
sudo apt install postgresql postgresql-contrib
```
> PostgreSQL GUI 应用程序
> 你也可以安装用于管理 PostgreSQL 数据库的 GUI 应用程序pgAdmin
> `sudo apt install pgadmin4`
### PostgreSQL 配置
你可以通过执行以下命令来检查 PostgreSQL 是否正在运行:
```
service postgresql status
```
通过 `service` 命令,你可以启动、关闭或重启 `postgresql`。输入 `service postgresql` 并按回车将列出所有选项。现在,登录该用户。
默认情况下PostgreSQL 会创建一个拥有所权限的特殊用户 `postgres`。要实际使用 PostgreSQL你必须先登录该账户
```
sudo su postgres
```
你的提示符会更改为类似于以下的内容:
```
postgres@ubuntu-VirtualBox:/home/ubuntu$
```
现在,使用 `psql` 来启动 PostgreSQL Shell
```
psql
```
你应该会看到如下提示符:
```
postgress=#
```
你可以输入 `\q` 以退出,输入 `\?` 获取帮助。
要查看现有的所有表,输入如下命令:
```
\l
```
输出内容类似于下图所示(单击 `q` 键退出该视图):
![PostgreSQL Tables][10]
使用 `\du` 命令,你可以查看 PostgreSQL 用户:
![PostgreSQLUsers][11]
你可以使用以下命令更改任何用户(包括 `postgres`)的密码:
```
ALTER USER postgres WITH PASSWORD 'my_password';
```
**注意:**将 `postgres` 替换为你要更改的用户名,`my_password` 替换为所需要的密码。另外,不要忘记每条命令后面的 `;`(分号)。
建议你另外创建一个用户(不建议使用默认的 `postgres` 用户)。为此,请使用以下命令:
```
CREATE USER my_user WITH PASSWORD 'my_password';
```
运行 `\du`,你将看到该用户,但是,`my_user` 用户没有任何的属性。来让我们给它添加超级用户权限:
```
ALTER USER my_user WITH SUPERUSER;
```
你可以使用以下命令删除用户:
```
DROP USER my_user;
```
要使用其他用户登录,使用 `\q` 命令退出,然后使用以下命令登录:
```
psql -U my_user
```
你可以使用 `-d` 参数直接连接数据库:
```
psql -U my_user -d my_db
```
你可以使用其他已存在的用户调用 PostgreSQL。例如我使用 `ubuntu`。要登录,从终端执行以下命名:
```
psql -U ubuntu -d postgres
```
**注意:**你必须指定一个数据库(默认情况下,它将尝试将你连接到与登录的用户名相同的数据库)。
如果遇到如下错误:
```
psql: FATAL: Peer authentication failed for user "my_user"
```
确保以正确的用户身份登录,并使用管理员权限编辑 `/etc/postgresql/11/main/pg_hba.conf`
```
sudo vim /etc/postgresql/11/main/pg_hba.conf
```
**注意:**用你的版本替换 `11`(例如 `10`)。
对如下所示的一行进行替换:
```
local all postgres peer
```
替换为:
```
local all postgres md5
```
然后重启 PostgreSQL
```
sudo service postgresql restart
```
使用 PostgreSQL 与使用其他 SQL 类型的数据库相同。由于本文旨在帮助你进行初步的设置,因此不涉及具体的命令。不过,这里有个 [非常有用的要点][12] 可供参考! 另外, 手册(`man psql`)和 [文档][13] 也非常有用。
### 总结
阅读本文有望指导你完成在 Ubuntu 系统上安装和准备 PostgreSQL 的过程。如果你不熟悉 SQL你应该阅读 [基本的 SQL 命令][15]。
如果你有任何问题或疑惑,请随时在评论部分提出。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-postgresql-ubuntu/
作者:[Sergiu][a]
选题:[lujun9972][b]
译者:[lnrCoder](https://github.com/lnrCoder)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/sergiu/
[b]: https://github.com/lujun9972
[1]: https://www.postgresql.org/
[2]: https://www.codecademy.com/articles/what-is-rdbms-sql
[3]: https://www.apple.com/in/macos/server/
[4]: https://itsfoss.com/install-mysql-ubuntu/
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-postgresql-ubuntu.png?resize=800%2C450&ssl=1
[6]: https://itsfoss.com/ubuntu-repositories/
[7]: https://itsfoss.com/apt-command-guide/
[8]: https://itsfoss.com/network-speed-monitor-linux/
[9]: https://itsfoss.com/fix-gvfsd-smb-high-cpu-ubuntu/
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/07/postgresql_tables.png?fit=800%2C303&ssl=1
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/07/postgresql_users.png?fit=800%2C244&ssl=1
[12]: https://gist.github.com/Kartones/dd3ff5ec5ea238d4c546
[13]: https://www.postgresql.org/docs/manuals/
[14]: https://itsfoss.com/sync-any-folder-with-dropbox/
[15]: https://itsfoss.com/basic-sql-commands/

View File

@@ -0,0 +1,273 @@
[#]: collector: (lujun9972)
[#]: translator: (Morisun029)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11468-1.html)
[#]: subject: (Mutation testing is the evolution of TDD)
[#]: via: (https://opensource.com/article/19/8/mutation-testing-evolution-tdd)
[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
变异测试是测试驱动开发TDD的演变
======
> 测试驱动开发技术是根据大自然的运作规律创建的,变异测试自然成为 DevOps 演变的下一步。
![Ants and a leaf making the word "open"][1]
在 “[故障是无懈可击的开发运维中的一个特点][2]”,我讨论了故障在通过征求反馈来交付优质产品的过程中所起到的重要作用。敏捷 DevOps 团队就是用故障来指导他们并推动开发进程的。<ruby>[测试驱动开发][3]<rt>Test-driven development</rt></ruby>TDD是任何敏捷 DevOps 团队评估产品交付的[必要条件][4]。以故障为中心的 TDD 方法仅在与可量化的测试配合使用时才有效。
TDD 方法仿照大自然是如何运作的以及自然界在进化博弈中是如何产生赢家和输家为模型而建立的。
### 自然选择
![查尔斯·达尔文][5]
1859 年,<ruby>[查尔斯·达尔文][6]<rt>Charles Darwin</rt></ruby>在他的《<ruby>[物种起源][7]<rt>On the Origin of Species</rt></ruby>》一书中提出了进化论学说。达尔文的论点是,自然变异是由生物个体的自发突变和环境压力共同造成的。环境压力淘汰了适应性较差的生物体,而有利于其他适应性强的生物的发展。每个生物体的染色体都会发生变异,而这些自发的变异会携带给下一代(后代)。然后在自然选择下测试新出现的变异性 —— 当下存在的环境压力是由变异性的环境条件所导致的。
这张简图说明了调整适应环境条件的过程。
![环境压力对鱼类的影响][8]
*图1. 不同的环境压力导致自然选择下的不同结果。图片截图来源于[理查德·道金斯的一个视频][9]。*
该图显示了一群生活在自己栖息地的鱼。栖息地各不相同(海底或河床底部的砾石颜色有深有浅),每条鱼长的也各不相同(鱼身图案和颜色也有深有浅)。
这张图还显示了两种情况(即环境压力的两种变化):
1. 捕食者在场
2. 捕食者不在场
在第一种情况下,在砾石颜色衬托下容易凸显出来的鱼被捕食者捕获的风险更高。当砾石颜色较深时,浅色鱼的数量会更少一些。反之亦然,当砾石颜色较浅时,深色鱼的数量会更少。
在第二种情况下,鱼完全放松下来进行交配。在没有捕食者和没有交配仪式的情况下,可以预料到相反的结果:在砾石背景下显眼的鱼会有更大的机会被选来交配并将其特性传递给后代。
### 选择标准
变异性在进行选择时,绝不是任意的、反复无常的、异想天开的或随机的。选择过程中的决定性因素通常是可以度量的。该决定性因素通常称为测试或目标。
一个简单的数学例子可以说明这一决策过程。(在该示例中,这种选择不是由自然选择决定的,而是由人为选择决定。)假设有人要求你构建一个小函数,该函数将接受一个正数,然后计算该数的平方根。你将怎么做?
敏捷 DevOps 团队的方法是快速验证失败。谦虚一点,先承认自己并不真的知道如何开发该函数。这时,你所知道的就是如何描述你想做的事情。从技术上讲,你已准备好进行单元测试。
“<ruby>单元测试<rt>unit test</rt></ruby>”描述了你的具体期望结果是什么。它可以简单地表述为“给定数字 16我希望平方根函数返回数字 4”。你可能知道 16 的平方根是 4。但是你不知道一些较大数字例如 533的平方根。
但至少,你已经制定了选择标准,即你的测试或你的期望值。
### 进行故障测试
[.NET Core][10] 平台可以演示该测试。.NET 通常使用 xUnit.net 作为单元测试框架。(要跟随进行这个代码示例,请安装 .NET Core 和 xUnit.net。
打开命令行并创建一个文件夹,在该文件夹实现平方根解决方案。例如,输入:
```
mkdir square_root
```
再输入:
```
cd square_root
```
为单元测试创建一个单独的文件夹:
```
mkdir unit_tests
```
进入 `unit_tests` 文件夹下(`cd unit_tests`),初始化 xUnit 框架:
```
dotnet new xunit
```
现在,转到 `square_root` 下, 创建 `app` 文件夹:
```
mkdir app
cd app
```
如果有必要的话,为你的代码创建一个脚手架:
```
dotnet new classlib
```
现在打开你最喜欢的编辑器开始编码!
在你的代码编辑器中,导航到 `unit_tests` 文件夹,打开 `UnitTest1.cs`
`UnitTest1.cs` 中自动生成的代码替换为:
```
using System;
using Xunit;
using app;
namespace unit_tests{
public class UnitTest1{
Calculator calculator = new Calculator();
[Fact]
public void GivenPositiveNumberCalculateSquareRoot(){
var expected = 4;
var actual = calculator.CalculateSquareRoot(16);
Assert.Equal(expected, actual);
}
}
}
```
该单元测试描述了变量的**期望值**应该为 4。下一行描述了**实际值**。建议通过将输入值发送到称为`calculator` 的组件来计算**实际值**。对该组件的描述是通过接收数值来处理`CalculateSquareRoot` 信息。该组件尚未开发。但这并不重要,我们在此只是描述期望值。
最后,描述了触发消息发送时发生的情况。此时,判断**期望值**是否等于**实际值**。如果是,则测试通过,目标达成。如果**期望值**不等于**实际值**,则测试失败。
接下来,要实现称为 `calculator` 的组件,在 `app` 文件夹中创建一个新文件,并将其命名为`Calculator.cs`。要实现计算平方根的函数,请在此新文件中添加以下代码:
```
namespace app {
public class Calculator {
public double CalculateSquareRoot(double number) {
double bestGuess = number;
return bestGuess;
}
}
}
```
在测试之前,你需要通知单元测试如何找到该新组件(`Calculator`)。导航至 `unit_tests` 文件夹,打开 `unit_tests.csproj` 文件。在 `<ItemGroup>` 代码块中添加以下代码:
```
<ProjectReference Include="../app/app.csproj" />
```
保存 `unit_test.csproj` 文件。现在,你可以运行第一个测试了。
切换到命令行,进入 `unit_tests` 文件夹。运行以下命令:
```
dotnet test
```
运行单元测试,会输出以下内容:
![单元测试失败后xUnit的输出结果][12]
*图2. 单元测试失败后 xUnit 的输出结果*
正如你所看到的,单元测试失败了。期望将数字 16 发送到 `calculator` 组件后会输出数字 4但是输出`Actual`)的是 16。
恭喜你!创建了第一个故障。单元测试为你提供了强有力的反馈机制,敦促你修复故障。
### 修复故障
要修复故障,你必须要改进 `bestGuess`。当下,`bestGuess` 仅获取函数接收的数字并返回。这不够好。
但是,如何找到一种计算平方根值的方法呢? 我有一个主意 —— 看一下大自然母亲是如何解决问题的。
### 效仿大自然的迭代
在第一次(也是唯一的)尝试中要得出正确值是非常难的(几乎不可能)。你必须允许自己进行多次尝试猜测,以增加解决问题的机会。允许多次尝试的一种方法是进行迭代。
要迭代,就要将 `bestGuess` 值存储在 `previousGuess` 变量中,转换 `bestGuess` 的值,然后比较两个值之间的差。如果差为 0则说明问题已解决。否则继续迭代。
这是生成任何正数的平方根的函数体:
```
double bestGuess = number;
double previousGuess;
do {
previousGuess = bestGuess;
bestGuess = (previousGuess + (number/previousGuess))/2;
} while((bestGuess - previousGuess) != 0);
return bestGuess;
```
该循环(迭代)将 `bestGuess` 值集中到设想的解决方案。现在,你精心设计的单元测试通过了!
![单元测试通过了][13]
*图 3. 单元测试通过了。*
### 迭代解决了问题
正如大自然母亲解决问题的方法,在本练习中,迭代解决了问题。增量方法与逐步改进相结合是获得满意解决方案的有效方法。该示例中的决定性因素是具有可衡量的目标和测试。一旦有了这些,就可以继续迭代直到达到目标。
### 关键点!
好的,这是一个有趣的试验,但是更有趣的发现来自于使用这种新创建的解决方案。到目前为止,`bestGuess` 从开始一直把函数接收到的数字作为输入参数。如果更改 `bestGuess` 的初始值会怎样?
为了测试这一点,你可以测试几种情况。 首先,在迭代多次尝试计算 25 的平方根时,要逐步细化观察结果:
![25 平方根的迭代编码][14]
*图 4. 通过迭代来计算 25 的平方根。*
以 25 作为 `bestGuess` 的初始值,该函数需要八次迭代才能计算出 25 的平方根。但是,如果在设计 `bestGuess` 初始值上犯下荒谬的错误,那将怎么办? 尝试第二次,那 100 万可能是 25 的平方根吗? 在这种明显错误的情况下会发生什么?你写的函数是否能够处理这种低级错误。
直接来吧。回到测试中来,这次以一百万开始:
![逐步求精法][15]
*图 5. 在计算 25 的平方根时,运用逐步求精法,以 100 万作为 bestGuess 的初始值。*
哇! 以一个荒谬的数字开始,迭代次数仅增加了两倍(从八次迭代到 23 次)。增长幅度没有你直觉中预期的那么大。
### 故事的寓意
啊哈! 当你意识到,迭代不仅能够保证解决问题,而且与你的解决方案的初始猜测值是好是坏也没有关系。 不论你最初理解得多么不正确,迭代过程以及可衡量的测试/目标,都可以使你走上正确的道路并得到解决方案。
图 4 和 5 显示了陡峭而戏剧性的燃尽图。一个非常错误的开始,迭代很快就产生了一个绝对正确的解决方案。
简而言之,这种神奇的方法就是敏捷 DevOps 的本质。
### 回到一些更深层次的观察
敏捷 DevOps 的实践源于人们对所生活的世界的认知。我们生活的世界存在不确定性、不完整性以及充满太多的困惑。从科学/哲学的角度来看,这些特征得到了<ruby>[海森堡的不确定性原理][16]<rt>Heisenberg's Uncertainty Principle</rt></ruby>(涵盖不确定性部分),<ruby>[维特根斯坦的逻辑论哲学][17]<rt>Wittgenstein's Tractatus Logico-Philosophicus</rt></ruby>(歧义性部分),<ruby>[哥德尔的不完全性定理][18]<rt>Gödel's incompleteness theorems</rt></ruby>(不完全性方面)以及<ruby>[热力学第二定律][19]<rt>Second Law of Thermodynamics</rt></ruby>(无情的熵引起的混乱)的充分证明和支持。
简而言之,无论你多么努力,在尝试解决任何问题时都无法获得完整的信息。因此,放下傲慢的姿态,采取更为谦虚的方法来解决问题对我们会更有帮助。谦卑会给为你带来巨大的回报,这个回报不仅是你期望的一个解决方案,还会有它的副产品。
### 总结
大自然在不停地运作,这是一个持续不断的过程。大自然没有总体规划。一切都是对先前发生的事情的回应。 反馈循环是非常紧密的,明显的进步/倒退都是逐步实现的。大自然中随处可见,任何事物的都在以一种或多种形式逐步完善。
敏捷 DevOps 是工程模型逐渐成熟的一个非常有趣的结果。DevOps 基于这样的认识,即你所拥有的信息总是不完整的,因此你最好谨慎进行。获得可衡量的测试(例如,假设、可测量的期望结果),进行简单的尝试,大多数情况下可能失败,然后收集反馈,修复故障并继续测试。除了同意每个步骤都必须要有可衡量的假设/测试之外,没有其他方法。
在本系列的下一篇文章中,我将仔细研究变异测试是如何提供及时反馈来推动实现结果的。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/8/mutation-testing-evolution-tdd
作者:[Alex Bunardzic][a]
选题:[lujun9972][b]
译者:[Morisun029](https://github.com/Morisun029)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/alex-bunardzic
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520X292_openanttrail-2.png?itok=xhD3WmUd (Ants and a leaf making the word "open")
[2]: https://opensource.com/article/19/7/failure-feature-blameless-devops
[3]: https://en.wikipedia.org/wiki/Test-driven_development
[4]: https://www.merriam-webster.com/dictionary/conditio%20sine%20qua%20non
[5]: https://opensource.com/sites/default/files/uploads/darwin.png (Charles Darwin)
[6]: https://en.wikipedia.org/wiki/Charles_Darwin
[7]: https://en.wikipedia.org/wiki/On_the_Origin_of_Species
[8]: https://opensource.com/sites/default/files/uploads/environmentalconditions2.png (Environmental pressures on fish)
[9]: https://www.youtube.com/watch?v=MgK5Rf7qFaU
[10]: https://dotnet.microsoft.com/
[11]: https://xunit.net/
[12]: https://opensource.com/sites/default/files/uploads/xunit-output.png (xUnit output after the unit test run fails)
[13]: https://opensource.com/sites/default/files/uploads/unit-test-success.png (Unit test successful)
[14]: https://opensource.com/sites/default/files/uploads/iterating-square-root.png (Code iterating for the square root of 25)
[15]: https://opensource.com/sites/default/files/uploads/bestguess.png (Stepwise refinement)
[16]: https://en.wikipedia.org/wiki/Uncertainty_principle
[17]: https://en.wikipedia.org/wiki/Tractatus_Logico-Philosophicus
[18]: https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems
[19]: https://en.wikipedia.org/wiki/Second_law_of_thermodynamics

View File

@@ -0,0 +1,184 @@
[#]: collector: (lujun9972)
[#]: translator: (amwps290)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11477-1.html)
[#]: subject: "How to Install Linux on Intel NUC"
[#]: via: "https://itsfoss.com/install-linux-on-intel-nuc/"
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
在 Intel NUC 上安装 Linux
======
![](https://img.linux.net.cn/data/attachment/album/201910/18/221221pw3hbbi3bbbbprr4.jpg)
在上周,我买了一台 [InteL NUC][1]。虽然它是如此之小,但它与成熟的桌面型电脑差别甚小。实际上,大部分的[基于 Linux 的微型 PC][2] 都是基于 Intel NUC 构建的。
我买了第 8 代 Core i3 处理器的“<ruby>准系统<rt>barebone</rt></ruby>” NUC。准系统意味着该设备没有 RAM、没有硬盘显然也没有操作系统。我添加了一个 [Crucial 的 8 GB 内存条][3](大约 33 美元)和一个 [240 GB 的西数的固态硬盘][4](大约 45 美元)。
现在,我已经有了一台不到 400 美元的电脑。因为我已经有了一个电脑屏幕和键鼠套装,所以我没有把它们计算在内。
![在我的办公桌上放着一个崭新的英特尔 NUC NUC8i3BEH后面有树莓派 4][5]
我买这个 Intel NUC 的主要原因就是我想在实体机上测试各种各样的 Linux 发行版。我已经有一个 [树莓派 4][6] 设备作为一个入门级的桌面系统,但它是一个 [ARM][7] 设备,因此,只有少数 Linux 发行版可用于树莓派上。LCTT 译注:新发布的 Ubuntu 19.10 支持树莓派 4B
*这个文章里的亚马逊链接是(原文的)受益连接。请参阅我们的[受益政策][8]。*
### 在 NUC 上安装 Linux
现在我准备安装 Ubuntu 18.04 长期支持版,因为我现在就有这个系统的安装文件。你也可以按照这个教程安装其他的发行版。在最重要的分区之前,前边的步骤都大致相同。
#### 第一步:创建一个 USB 启动盘
你可以在 Ubuntu 官网下载它的安装文件。使用另一个电脑去[创建一个 USB 启动盘][9]。你可以使用像 [Rufus][10] 和 [Etcher][11] 这样的软件。在 Ubuntu上你可以使用默认的启动盘创建工具。
#### 第二步:确认启动顺序是正确的
将你的 USB 启动盘插入到你的电脑并开机。一旦你看到 “Intel NUC” 字样出现在你的屏幕上,快速的按下 `F2` 键进入到 BIOS 设置中。
![Intel NUC 的 BIOS 设置][12]
在这里,只是确认一下你的第一启动项是你的 USB 设备。如果不是,切换启动顺序。
如果你修改了一些选项,按 `F10` 键保存退出,否则直接按下 `ESC` 键退出 BIOS 设置。
#### 第三步:正确分区,安装 Linux
现在当机器重启的时候,你就可以看到熟悉的 Grub 界面,可以让你试用或者安装 Ubuntu。现在我们选择安装它。
开始的几个安装步骤非常简单,选择键盘的布局,是否连接网络还有一些其他简单的设置。
![在安装 Ubuntu Linux 时选择键盘布局][14]
你可能会使用常规安装,默认情况下会安装一些有用的应用程序。
![][15]
接下来的是要注意的部分。你有两种选择:
* “<ruby>擦除磁盘并安装 Ubuntu<rt>Erase disk and install Ubuntu</rt></ruby>”:最简单的选项,它将在整个磁盘上安装 Ubuntu。如果你只想在 Intel NUC 上使用一个操作系统请选择此选项Ubuntu 将负责剩余的工作。
* “<ruby>其他选项<rt>Something else</rt></ruby>”:这是一个控制所有选择的高级选项。就我而言,我想在同一 SSD 上安装多个 Linux 发行版。因此,我选择了此高级选项。
![][16]
**如果你选择了“<ruby>擦除磁盘并安装 Ubuntu<rt>Erase disk and install Ubuntu</rt></ruby>”,点击“<ruby>继续<rt>Continue</rt></ruby>”,直接跳到第四步,**
如果你选择了高级选项,请按照下面剩下的部分进行操作。
选择固态硬盘,然后点击“<ruby>新建分区表<rt>New Partition Table</rt></ruby>”。
![][17]
它会给你显示一个警告。直接点击“<ruby>继续<rt>Continue</rt></ruby>”。
![][18]
现在你就可以看到你 SSD 磁盘里的空闲空间。我的想法是为 EFI bootloader 创建一个 EFI 系统分区。一个根(`/`)分区,一个主目录(`/home`)分区。这里我并没有创建[交换分区][19]。Ubuntu 会根据自己的需要来创建交换分区。我也可以通过[创建新的交换文件][32]来扩展交换分区。
我将在磁盘上保留近 200 GB 的可用空间,以便可以在此处安装其他 Linux 发行版。你可以将其全部用于主目录分区。保留单独的根分区和主目录分区可以在你需要重新安装系统时帮你保存里面的数据。
选择可用空间,然后单击加号以添加分区。
![][20]
一般来说100MB 足够 EFI 的使用,但是某些发行版可能需要更多空间,因此我要使用 500MB 的 EFI 分区。
![][21]
接下来,我将使用 20GB 的根分区。如果你只使用一个发行版,则可以随意地将其增加到 40GB。
根目录(`/`)是系统文件存放的地方。你的程序缓存和你安装的程序将会有一些文件放在这个目录下边。我建议你可以阅读一下 [Linux 文件系统层次结构][22]来了解更多相关内容。
填入分区的大小,选择 Ext4 文件系统,选择 `/` 作为挂载点。
![][24]
接下来是创建一个主目录分区,我再说一下,如果你仅仅想使用一个 Linux 发行版。那就把剩余的空间都使用完吧。为主目录分区选择一个合适的大小。
主目录是你个人的文件,比如文档、图片、音乐、下载和一些其他的文件存储的地方。
![][25]
既然你创建好了 EFI 分区、根分区、主目录分区,那你就可以点击“<ruby>现在安装<rt>Install Now</rt></ruby>”按钮安装系统了。
![][26]
它将会提示你新的改变将会被写入到磁盘,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![][27]
#### 第四步:安装 Ubuntu
事情到了这就非常明了了。现在选择你的分区或者以后选择也可以。
![][28]
接下来,输入你的用户名、主机名以及密码。
![][29]
看 7-8 分钟的幻灯片就可以安装完成了。
![][30]
一旦安装完成,你就可以重新启动了。
![][31]
当你重启的时候,你必须要移除你的 USB 设备,否则你将会再次进入安装系统的界面。
这就是在 Intel NUC 设备上安装 Linux 所需要做的一切。坦白说,你可以在其他任何系统上使用相同的过程。
### Intel NUC 和 Linux 在一起:如何使用它?
我非常喜欢 Intel NUC。它不占用太多的桌面空间而且有足够的能力去取代传统的桌面型电脑。你可以将它的内存升级到 32GB。你也可以安装两个 SSD 硬盘。总之,它提供了一些配置和升级范围。
如果你想购买一个桌面型的电脑,我非常推荐你购买使用 [Intel NUC][1] 迷你主机。如果你不想自己安装系统,那么你可以购买一个[基于 Linux 的已经安装好的系统迷你主机][2]。
你是否已经有了一个 Intel NUC有一些什么相关的经验你有什么相关的意见与我们分享吗可以在下面评论。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-linux-on-intel-nuc/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[amwps290](https://github.com/amwps290)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://www.amazon.com/Intel-NUC-Mainstream-Kit-NUC8i3BEH/dp/B07GX4X4PW?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B07GX4X4PW "Intel NUC"
[2]: https://itsfoss.com/linux-based-mini-pc/
[3]: https://www.amazon.com/Crucial-Single-PC4-19200-SODIMM-260-Pin/dp/B01BIWKP58?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B01BIWKP58 "8GB RAM from Crucial"
[4]: https://www.amazon.com/Western-Digital-240GB-Internal-WDS240G1G0B/dp/B01M9B2VB7?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B01M9B2VB7 "240 GB Western Digital SSD"
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/intel-nuc.jpg?resize=800%2C600&ssl=1
[6]: https://itsfoss.com/raspberry-pi-4/
[7]: https://en.wikipedia.org/wiki/ARM_architecture
[8]: https://itsfoss.com/affiliate-policy/
[9]: https://itsfoss.com/create-live-usb-of-ubuntu-in-windows/
[10]: https://rufus.ie/
[11]: https://www.balena.io/etcher/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/08/boot-screen-nuc.jpg?ssl=1
[13]: https://itsfoss.com/find-which-kernel-version-is-running-in-ubuntu/
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-1_tutorial.jpg?ssl=1
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-2_tutorial.jpg?ssl=1
[16]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-3_tutorial.jpg?ssl=1
[17]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-4_tutorial.jpg?ssl=1
[18]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-5_tutorial.jpg?ssl=1
[19]: https://itsfoss.com/swap-size/
[20]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-6_tutorial.jpg?ssl=1
[21]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-7_tutorial.jpg?ssl=1
[22]: https://linuxhandbook.com/linux-directory-structure/
[23]: https://itsfoss.com/share-folders-local-network-ubuntu-windows/
[24]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-8_tutorial.jpg?ssl=1
[25]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-9_tutorial.jpg?ssl=1
[26]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-10_tutorial.jpg?ssl=1
[27]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-11_tutorial.jpg?ssl=1
[28]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-12_tutorial.jpg?ssl=1
[29]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-13_tutorial.jpg?ssl=1
[30]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-14_tutorial.jpg?ssl=1
[31]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-15_tutorial.jpg?ssl=1
[32]: https://itsfoss.com/create-swap-file-linux/

View File

@@ -0,0 +1,214 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11487-1.html)
[#]: subject: (Installation Guide of Manjaro 18.1 (KDE Edition) with Screenshots)
[#]: via: (https://www.linuxtechi.com/install-manjaro-18-1-kde-edition-screenshots/)
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
Manjaro 18.1KDE安装图解
======
在 Manjaro 18.0Illyria发布一年之际该团队发布了他们的下一个重要版本即 Manjaro 18.1,代号为 “Juhraya”。该团队还发布了一份官方声明称 Juhraya 包含了许多改进和错误修复。
### Manjaro 18.1 中的新功能
以下列出了 Manjaro 18.1 中的一些新功能和增强功能:
* 可以在 LibreOffice 或 Free Office 之间选择
* Xfce 版的新 Matcha 主题
* 在 KDE 版本中重新设计了消息传递系统
* 使用 bhau 工具支持 Snap 和 FlatPak 软件包
### 最小系统需求
* 1 GB RAM
* 1 GHz 处理器
* 大约 30 GB 硬盘空间
* 互联网连接
* 启动介质USB/DVD
### 安装 Manjaro 18.1KDE 版)的分步指南
要在系统中开始安装 Manjaro 18.1KDE 版),请遵循以下步骤:
#### 步骤 1) 下载 Manjaro 18.1 ISO
在安装之前,你需要从位于 [这里][1] 的官方下载页面下载 Manjaro 18.1 的最新副本。由于我们这里介绍的是 KDE 版本,因此我们选择 KDE 版本。但是对于所有桌面环境(包括 Xfce、KDE 和 Gnome 版本),安装过程都是相同的。
#### 步骤 2) 创建 USB 启动盘
从 Manjaro 下载页面成功下载 ISO 文件后,就可以创建 USB 磁盘了。将下载的 ISO 文件复制到 USB 磁盘中,然后创建可引导磁盘。确保将你的引导设置更改为使用 USB 引导,并重新启动系统。
#### 步骤 3) Manjaro Live 版安装环境
系统重新启动时,它将自动检测到 USB 驱动器,并开始启动进入 Manjaro Live 版安装屏幕。
![Boot-Manjaro-18-1-kde-installation][3]
接下来,使用箭头键选择 “<ruby>启动Manjaro x86\_64 kde<rt>Boot: Manjaro x86\_64 kde</rt></ruby>”,然后按回车键以启动 Manjaro 安装程序。
#### 安装 4) 选择启动安装程序
接下来,将启动 Manjaro 安装程序如果你已连接到互联网Manjaro 将自动检测你的位置和时区。单击 “<ruby>启动安装程序<rt>Launch Installer</rt></ruby>”,开始在系统中安装 Manjaro 18.1 KDE 版本。
![Choose-Launch-Installaer-Manjaro18-1-kde][4]
#### 步骤 5) 选择语言
接下来,安装程序将带你选择你的首选语言。
![Choose-Language-Manjaro18-1-Kde-Installation][5]
选择你想要的语言,然后单击“<ruby>下一步<rt>Next</rt></ruby>”。
#### 步骤 6) 选择时区和区域
在下一个屏幕中,选择所需的时区和区域,然后单击“<ruby>下一步<rt>Next</rt></ruby>”继续。
![Select-Location-During-Manjaro18-1-KDE-Installation][6]
#### 步骤 7) 选择键盘布局
在下一个屏幕中,选择你喜欢的键盘布局,然后单击“<ruby>下一步<rt>Next</rt></ruby>”继续。
![Select-Keyboard-Layout-Manjaro18-1-kde-installation][7]
#### 步骤 8) 选择分区类型
这是安装过程中非常关键的一步。 它将允许你选择分区方式:
* 擦除磁盘
* 手动分区
* 并存安装
* 替换分区
如果在 VM虚拟机中安装 Manjaro 18.1,则将看不到最后两个选项。
如果你不熟悉 Manjaro Linux那么我建议你使用第一个选项<ruby>擦除磁盘<rt>Erase Disk</rt></ruby>),它将为你自动创建所需的分区。如果要创建自定义分区,则选择第二个选项“<ruby>手动分区<rt>Manual Partitioning</rt></ruby>”,顾名思义,它将允许我们创建自己的自定义分区。
在本教程中,我将通过选择“<ruby>手动分区<rt>Manual Partitioning</rt></ruby>”选项来创建自定义分区:
![Manual-Partition-Manjaro18-1-KDE][8]
选择第二个选项,然后单击“<ruby>下一步<rt>Next</rt></ruby>”继续。
如我们所见,我有 40 GB 硬盘,因此我将在其上创建以下分区,
* `/boot`         2GBext4
* `/`             10 GBext4
* `/home`        22 GBext4
* `/opt`         4 GBext4
* <ruby>交换分区<rt>Swap</rt></ruby>       2 GB
当我们在上方窗口中单击“<ruby>下一步<rt>Next</rt></ruby>”时,将显示以下屏幕,选择“<ruby>新建分区表<rt>new partition table</rt></ruby>”:
![Create-Partition-Table-Manjaro18-1-Installation][9]
点击“<ruby>确定<rt>OK</rt></ruby>”。
现在选择可用空间,然后单击“<ruby>创建<rt>create</rt></ruby>”以将第一个分区设置为大小为 2 GB 的 `/boot`
![boot-partition-manjaro-18-1-installation][10]
单击“<ruby>确定<rt>OK</rt></ruby>”以继续操作,在下一个窗口中再次选择可用空间,然后单击“<ruby>创建<rt>create</rt></ruby>”以将第二个分区设置为 `/`,大小为 10 GB
![slash-root-partition-manjaro18-1-installation][11]
同样,将下一个分区创建为大小为 22 GB 的 `/home`
![home-partition-manjaro18-1-installation][12]
到目前为止,我们已经创建了三个分区作为主分区,现在创建下一个分区作为扩展分区:
![Extended-Partition-Manjaro18-1-installation][13]
单击“<ruby>确定<rt>OK</rt></ruby>”以继续。
创建大小分别为 5 GB 和 2 GB 的 `/opt` 和交换分区作为逻辑分区。
![opt-partition-manjaro-18-1-installation][14]
![swap-partition-manjaro18-1-installation][15]
完成所有分区的创建后,单击“<ruby>下一步<rt>Next</rt></ruby>”:
![choose-next-after-partition-creation][16]
#### 步骤 9) 提供用户信息
在下一个屏幕中,你需要提供用户信息,包括你的姓名、用户名、密码、计算机名等:
![User-creation-details-manjaro18-1-installation][17]
提供所有信息后,单击“<ruby>下一步<rt>Next</rt></ruby>”继续安装。
在下一个屏幕中,系统将提示你选择办公套件,因此请做出适合你的选择:
![Office-Suite-Selection-Manjaro18-1][18]
单击“<ruby>下一步<rt>Next</rt></ruby>”以继续。
#### 步骤 10) 摘要信息
在完成实际安装之前,安装程序将向你显示你选择的所有详细信息,包括语言、时区、键盘布局和分区信息等。单击“<ruby>安装<rt>Install</rt></ruby>”以继续进行安装过程。
![Summary-manjaro18-1-installation][19]
#### 步骤 11) 进行安装
现在,实际的安装过程开始,一旦完成,请重新启动系统以登录到 Manjaro 18.1 KDE 版:
![Manjaro18-1-Installation-Progress][20]
![Restart-Manjaro-18-1-after-installation][21]
#### 步骤 12) 安装成功后登录
重新启动后,我们将看到以下登录屏幕,使用我们在安装过程中创建的用户凭据登录:
![Login-screen-after-manjaro-18-1-installation][22]
点击“<ruby>登录<rt>Login</rt></ruby>”。
![KDE-Desktop-Screen-Manjaro-18-1][23]
就是这样!你已经在系统中成功安装了 Manjaro 18.1 KDE 版,并探索了所有令人兴奋的功能。请在下面的评论部分中发表你的反馈和建议。
--------------------------------------------------------------------------------
via: https://www.linuxtechi.com/install-manjaro-18-1-kde-edition-screenshots/
作者:[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]: https://manjaro.org/download/official/kde/
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[3]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Boot-Manjaro-18-1-kde-installation.jpg
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Choose-Launch-Installaer-Manjaro18-1-kde.jpg
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Choose-Language-Manjaro18-1-Kde-Installation.jpg
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Select-Location-During-Manjaro18-1-KDE-Installation.jpg
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Select-Keyboard-Layout-Manjaro18-1-kde-installation.jpg
[8]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Manual-Partition-Manjaro18-1-KDE.jpg
[9]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Create-Partition-Table-Manjaro18-1-Installation.jpg
[10]: https://www.linuxtechi.com/wp-content/uploads/2019/09/boot-partition-manjaro-18-1-installation.jpg
[11]: https://www.linuxtechi.com/wp-content/uploads/2019/09/slash-root-partition-manjaro18-1-installation.jpg
[12]: https://www.linuxtechi.com/wp-content/uploads/2019/09/home-partition-manjaro18-1-installation.jpg
[13]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Extended-Partition-Manjaro18-1-installation.jpg
[14]: https://www.linuxtechi.com/wp-content/uploads/2019/09/opt-partition-manjaro-18-1-installation.jpg
[15]: https://www.linuxtechi.com/wp-content/uploads/2019/09/swap-partition-manjaro18-1-installation.jpg
[16]: https://www.linuxtechi.com/wp-content/uploads/2019/09/choose-next-after-partition-creation.jpg
[17]: https://www.linuxtechi.com/wp-content/uploads/2019/09/User-creation-details-manjaro18-1-installation.jpg
[18]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Office-Suite-Selection-Manjaro18-1.jpg
[19]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Summary-manjaro18-1-installation.jpg
[20]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Manjaro18-1-Installation-Progress.jpg
[21]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Restart-Manjaro-18-1-after-installation.jpg
[22]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Login-screen-after-manjaro-18-1-installation.jpg
[23]: https://www.linuxtechi.com/wp-content/uploads/2019/09/KDE-Desktop-Screen-Manjaro-18-1.jpg

View File

@@ -0,0 +1,186 @@
[#]: collector: (lujun9972)
[#]: translator: (Morisun029)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11483-1.html)
[#]: subject: (Mutation testing by example: How to leverage failure)
[#]: via: (https://opensource.com/article/19/9/mutation-testing-example-tdd)
[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzic)
变异测试:如何利用故障?
======
> 使用事先设计好的故障以确保你的代码达到预期的结果,并遵循 .NET xUnit.net 测试框架来进行测试。
![](https://img.linux.net.cn/data/attachment/album/201910/20/200030ipm13zmi08mv8z34.jpg)
[在变异测试是 TDD 的演变][2] 一文中,我谈到了迭代的力量。在可度量的测试中,迭代能够保证找到问题的解决方案。在那篇文章中,我们讨论了迭代法帮助确定实现计算给定数字平方根的代码。
我还演示了最有效的方法是找到可衡量的目标或测试,然后以最佳猜测值开始迭代。正如所预期的,第一次测试通常会失败。因此,必须根据可衡量的目标或测试对失败的代码进行完善。根据运行结果,对测试值进行验证或进一步加以完善。
在此模型中,学习获得解决方案的唯一方法是反复失败。这听起来有悖常理,但它确实有效。
按照这种分析,本文探讨了在构建包含某些依赖项的解决方案时使用 DevOps 的最佳方法。第一步是编写一个预期结果失败的用例。
### 依赖性问题是你不能依赖它们
正如<ruby>迈克尔·尼加德<rt>Michael Nygard</rt></ruby>在《[没有终结状态的架构][3]》中机智的表示的那样依赖问题是一个很大的话题最好留到另一篇文章中讨论。在这里你将会看到依赖项给项目带来的一些潜在问题以及如何利用测试驱动开发TDD来避免这些陷阱。
首先,找到现实生活中的一个挑战,然后看看如何使用 TDD 解决它。
### 谁把猫放出来?
![一只猫站在屋顶][4]
在敏捷开发环境中,通过定义期望结果开始构建解决方案会很有帮助。通常,在 <ruby>[用户故事][5]<rt>user story</rt></ruby> 中描述期望结果:
> 我想使用我的家庭自动化系统HAS来控制猫何时可以出门因为我想保证它在夜间的安全。
现在你已经有了一个用户故事,你需要通过提供一些功能要求(即指定验收标准)来对其进行详细说明。 从伪代码中描述的最简单的场景开始:
> 场景 1在夜间关闭猫门
>
> * 用时钟监测到了晚上的时间
> * 时钟通知 HAS 系统
> * HAS 关闭支持物联网IoT的猫门
### 分解系统
开始构建之前你需要将正在构建的系统HAS进行分解分解为依赖项。你必须要做的第一件事是识别任何依赖项如果幸运的话你的系统没有依赖项这将会更容易但是这样的系统可以说不是非常有用
从上面的简单场景中,你可以看到所需的业务成果(自动控制猫门)取决于对夜间情况监测。这种依赖性取决于时钟。但是时钟是无法区分白天和夜晚的。需要你来提供这种逻辑。
正在构建的系统中的另一个依赖项是能够自动访问猫门并启用或关闭它。该依赖项很可能取决于具有 IoT 功能的猫门提供的 API。
### 依赖管理面临快速失败
为了满足依赖项,我们将构建确定当前时间是白天还是晚上的逻辑。本着 TDD 的精神,我们将从一个小小的失败开始。
有关如何设置此练习所需的开发环境和脚手架的详细说明,请参阅我的[上一篇文章][2]。我们将重用相同的 NET 环境和 [xUnit.net][6] 框架。
接下来,创建一个名为 HAS“家庭自动化系统”的新项目创建一个名为 `UnitTest1.cs` 的文件。在该文件中,编写第一个失败的单元测试。在此单元测试中,描述你的期望结果。例如,当系统运行时,如果时间是晚上 7 点,负责确定是白天还是夜晚的组件将返回值 `Nighttime`
这是描述期望值的单元测试:
```
using System;
using Xunit;
namespace unittest
{
public class UnitTest1
{
DayOrNightUtility dayOrNightUtility = new DayOrNightUtility();
[Fact]
public void Given7pmReturnNighttime()
{
var expected = "Nighttime";
var actual = dayOrNightUtility.GetDayOrNight();
Assert.Equal(expected, actual);
}
}
}
```
至此,你可能已经熟悉了单元测试的结构。快速复习一下:在此示例中,通过给单元测试一个描述性名称`Given7pmReturnNighttime` 来描述期望结果。然后,在单元测试的主体中,创建一个名为 `expected` 的变量,并为该变量指定期望值(在该示例中,值为 `Nighttime`)。然后,为实际值指定一个 `actual`(在组件或服务处理一天中的时间之后可用)。
最后,通过断言期望值和实际值是否相等来检查是否满足期望结果:`Assert.Equal(expected, actual)`
你还可以在上面的列表中看到名为 `dayOrNightUtility` 的组件或服务。该模块能够接收消息`GetDayOrNight`,并且返回 `string` 类型的值。
同样,本着 TDD 的精神,描述的组件或服务还尚未构建(仅为了后面说明在此进行描述)。构建这些是由所描述的期望结果来驱动的。
`app` 文件夹中创建一个新文件,并将其命名为 `DayOrNightUtility.cs`。将以下 C 代码添加到该文件中并保存:
```
using System;
namespace app {
public class DayOrNightUtility {
public string GetDayOrNight() {
string dayOrNight = "Undetermined";
return dayOrNight;
}
}
}
```
现在转到命令行,将目录更改为 `unittests` 文件夹,然后运行:
```
[Xunit.net 00:00:02.33] unittest.UnitTest1.Given7pmReturnNighttime [FAIL]
Failed unittest.UnitTest1.Given7pmReturnNighttime
[...]
```
恭喜,你已经完成了第一个失败的单元测试。单元测试的期望结果是 `DayOrNightUtility` 方法返回字符串 `Nighttime`,但相反,它返回是 `Undetermined`
### 修复失败的单元测试
修复失败的测试的一种快速而粗略的方法是将值 `Undetermined` 替换为值 `Nighttime` 并保存更改:
```
using System;
namespace app {
public class DayOrNightUtility {
public string GetDayOrNight() {
string dayOrNight = "Nighttime";
return dayOrNight;
}
}
}
```
现在运行,成功了。
```
Starting test execution, please wait...
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 2.6470 Seconds
```
但是,对值进行硬编码基本上是在作弊,最好为 `DayOrNightUtility` 方法赋予一些智能。修改 `GetDayOrNight` 方法以包括一些时间计算逻辑:
```
public string GetDayOrNight() {
string dayOrNight = "Daylight";
DateTime time = new DateTime();
if(time.Hour < 7) {
dayOrNight = "Nighttime";
}
return dayOrNight;
}
```
该方法现在从系统获取当前时间,并与 `Hour` 比较,查看其是否小于上午 7 点。如果小于,则处理逻辑将 `dayOrNight` 字符串值从 `Daylight` 转换为 `Nighttime`。现在,单元测试通过。
### 测试驱动解决方案的开始
现在,我们已经开始了基本的单元测试,并为我们的时间依赖项提供了可行的解决方案。后面还有更多的测试案例需要执行。
在下一篇文章中,我将演示如何对白天时间进行测试以及如何在整个过程中利用故障。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/mutation-testing-example-tdd
作者:[Alex Bunardzic][a]
选题:[lujun9972][b]
译者:[Morisun029](https://github.com/Morisun029)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/alex-bunardzic
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/fail_failure_celebrate.png?itok=LbvDAEZF (failure sign at a party, celebrating failure)
[2]: https://linux.cn/article-11468-1.html
[3]: https://www.infoq.com/presentations/Architecture-Without-an-End-State/
[4]: https://opensource.com/sites/default/files/uploads/cat.png (Cat standing on a roof)
[5]: https://www.agilealliance.org/glossary/user-stories
[6]: https://xunit.net/
[7]: http://www.google.com/search?q=new+msdn.microsoft.com

View File

@@ -0,0 +1,105 @@
[#]: collector: (lujun9972)
[#]: translator: (hopefully2333)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11498-1.html)
[#]: subject: (How DevOps professionals can become security champions)
[#]: via: (https://opensource.com/article/19/9/devops-security-champions)
[#]: author: (Jessica Repka https://opensource.com/users/jrepka)
DevOps 专业人员如何成为网络安全拥护者
======
> 打破信息孤岛,成为网络安全的拥护者,这对你、对你的职业、对你的公司都会有所帮助。
![](https://img.linux.net.cn/data/attachment/album/201910/24/202520u09xw2vm4w2jm0mx.jpg)
安全是 DevOps 中一个被误解了的部分,一些人认为它不在 DevOps 的范围内,而另一些人认为它太过重要(并且被忽视),建议改为使用 DevSecOps。无论你同意哪一方的观点网络安全都会影响到我们每一个人这是很明显的事实。
每年,[黑客行为的统计数据][3] 都会更加令人震惊。例如,每 39 秒就有一次黑客行为发生,这可能会导致你为公司写的记录、身份和专有项目被盗。你的安全团队可能需要花上几个月(也可能是永远找不到)才能发现这次黑客行为背后是谁,目的是什么,人在哪,什么时候黑进来的。
运维专家面对这些棘手问题应该如何是好?呐我说,现在是时候成为网络安全的拥护者,变为解决方案的一部分了。
### 孤岛势力范围的战争
在我和我本地的 IT 安全ITSEC团队一起肩并肩战斗的岁月里我注意到了很多事情。一个很大的问题是安全团队和 DevOps 之间关系紧张,这种情况非常普遍。这种紧张关系几乎都是来源于安全团队为了保护系统、防范漏洞所作出的努力(例如,设置访问控制或者禁用某些东西),这些努力会中断 DevOps 的工作并阻碍他们快速部署应用程序。
你也看到了,我也看到了,你在现场碰见的每一个人都有至少一个和它有关的故事。一小撮的怨恨最终烧毁了信任的桥梁,要么是花费一段时间修复,要么就是两个团体之间开始一场小型的地盘争夺战,这个结果会使 DevOps 实现起来更加艰难。
### 一种新观点
为了打破这些孤岛并结束势力战争,我在每个安全团队中都选了至少一个人来交谈,了解我们组织日常安全运营里的来龙去脉。我开始做这件事是出于好奇,但我持续做这件事是因为它总是能带给我一些有价值的、新的观点。例如,我了解到,对于每个因为失败的安全性而被停止的部署,安全团队都在疯狂地尝试修复 10 个他们看见的其他问题。他们反应的莽撞和尖锐是因为他们必须在有限的时间里修复这些问题,不然这些问题就会变成一个大问题。
考虑到发现、识别和撤销已完成操作所需的大量知识,或者指出 DevOps 团队正在做什么(没有背景信息)然后复制并测试它。所有的这些通常都要由人手配备非常不足的安全团队完成。
这就是你的安全团队的日常生活,并且你的 DevOps 团队看不到这些。ITSEC 的日常工作意味着超时加班和过度劳累,以确保公司,公司的团队,团队里工作的所有人能够安全地工作。
### 成为安全拥护者的方法
这些是你成为你的安全团队的拥护者之后可以帮到它们的。这意味着,对于你做的所有操作,你必须仔细、认真地查看所有能够让其他人登录的方式,以及他们能够从中获得什么。
帮助你的安全团队就是在帮助你自己。将工具添加到你的工作流程里以此将你知道的要干的活和他们知道的要干的活结合到一起。从小事入手例如阅读公共漏洞披露CVE并将扫描模块添加到你的 CI/CD 流程里。对于你写的所有代码,都会有一个开源扫描工具,添加小型开源工具(例如下面列出来的)在长远看来是可以让项目更好的。
**容器扫描工具:**
* [Anchore Engine][5]
* [Clair][6]
* [Vuls][7]
* [OpenSCAP][8]
**代码扫描工具:**
* [OWASP SonarQube][9]
* [Find Security Bugs][10]
* [Google Hacking Diggity Project][11]
**Kubernetes 安全工具:**
* [Project Calico][12]
* [Kube-hunter][13]
* [NeuVector][14]
### 保持你的 DevOps 态度
如果你的工作角色是和 DevOps 相关的,那么学习新技术和如何运用这项新技术创造新事物就是你工作的一部分。安全也是一样。我在 DevOps 安全方面保持到最新,下面是我的方法的列表。
* 每周阅读一篇你工作的方向里和安全相关的文章.
* 每周查看 [CVE][15] 官方网站,了解出现了什么新漏洞.
* 尝试做一次黑客马拉松。一些公司每个月都要这样做一次;如果你觉得还不够、想了解更多,可以访问 Beginner Hack 1.0 网站。
* 每年至少一次和那你的安全团队的成员一起参加安全会议,从他们的角度来看事情。
### 成为拥护者是为了变得更好
你应该成为你的安全的拥护者,下面是我们列出来的几个理由。首先是增长你的知识,帮助你的职业发展。第二是帮助其他的团队,培养新的关系,打破对你的组织有害的孤岛。在你的整个组织内建立由很多好处,包括设置沟通团队的典范,并鼓励人们一起工作。你同样能促进在整个组织中分享知识,并给每个人提供一个在安全方面更好的内部合作的新契机。
总的来说,成为一个网络安全的拥护者会让你成为你整个组织的拥护者。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/devops-security-champions
作者:[Jessica Repka][a]
选题:[lujun9972][b]
译者:[hopefully2333](https://github.com/hopefully2333)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/jrepka
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_3reasons.png?itok=k6F3-BqA (A lock on the side of a building)
[2]: https://opensource.com/article/19/1/what-devsecops
[3]: https://hostingtribunal.com/blog/hacking-statistics/
[4]: https://opensource.com/article/18/8/what-cicd
[5]: https://github.com/anchore/anchore-engine
[6]: https://github.com/coreos/clair
[7]: https://vuls.io/
[8]: https://www.open-scap.org/
[9]: https://github.com/OWASP/sonarqube
[10]: https://find-sec-bugs.github.io/
[11]: https://resources.bishopfox.com/resources/tools/google-hacking-diggity/
[12]: https://www.projectcalico.org/
[13]: https://github.com/aquasecurity/kube-hunter
[14]: https://github.com/neuvector/neuvector-helm
[15]: https://cve.mitre.org/
[16]: https://www.hackerearth.com/challenges/hackathon/beginner-hack-10/

View File

@@ -0,0 +1,189 @@
[#]: collector: (lujun9972)
[#]: translator: (Morisun029)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11494-1.html)
[#]: subject: (Mutation testing by example: Failure as experimentation)
[#]: via: (https://opensource.com/article/19/9/mutation-testing-example-failure-experimentation)
[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzichttps://opensource.com/users/jocunddew)
变异测试:基于故障的试验
======
> 基于 .NET 的 xUnit.net 测试框架,开发一款自动猫门的逻辑,让门在白天开放,夜间锁定。
![Digital hand surrounding by objects, bike, light bulb, graphs][1]
在本系列的[第一篇文章][2]中,我演示了如何使用设计的故障来确保代码中的预期结果。在第二篇文章中,我将继续开发示例项目:一款自动猫门,该门在白天开放,夜间锁定。
在此提醒一下,你可以按照[此处的说明][3]使用 .NET 的 xUnit.net 测试框架。
### 关于白天时间
回想一下测试驱动开发TDD围绕着大量的单元测试。
第一篇文章中实现了满足 `Given7pmReturnNighttime` 单元测试期望的逻辑。但还没有完,现在,你需要描述当前时间大于 7 点时期望发生的结果。这是新的单元测试,称为 `Given7amReturnDaylight`
```
[Fact]
public void Given7amReturnDaylight()
{
var expected = "Daylight";
var actual = dayOrNightUtility.GetDayOrNight();
Assert.Equal(expected, actual);
}
```
现在,新的单元测试失败了(越早失败越好!):
```
Starting test execution, please wait...
[Xunit.net 00:00:01.23] unittest.UnitTest1.Given7amReturnDaylight [FAIL]
Failed unittest.UnitTest1.Given7amReturnDaylight
[...]
```
期望接收到字符串值是 `Daylight`,但实际接收到的值是 `Nighttime`
### 分析失败的测试用例
经过仔细检查,代码本身似乎已经出现问题。 事实证明,`GetDayOrNight` 方法的实现是不可测试的!
看看我们面临的核心挑战:
1. `GetDayOrNight` 依赖隐藏输入。
`dayOrNight` 的值取决于隐藏输入(它从内置系统时钟中获取一天的时间值)。
2. `GetDayOrNight` 包含非确定性行为。
从系统时钟中获取到的时间值是不确定的。(因为)该时间取决于你运行代码的时间点,而这一点我们认为这是不可预测的。
3. `GetDayOrNight` API 的质量差。
该 API 与具体的数据源(系统 `DateTime`)紧密耦合。
4. `GetDayOrNight` 违反了单一责任原则。
该方法实现同时使用和处理信息。优良作法是一种方法应负责执行一项职责。
5. `GetDayOrNight` 有多个更改原因。
可以想象内部时间源可能会更改的情况。同样,很容易想象处理逻辑也将改变。这些变化的不同原因必须相互隔离。
6. 当(我们)尝试了解 `GetDayOrNight` 行为时,会发现它的 API 签名不足。
最理想的做法就是通过简单的查看 API 的签名,就能了解 API 预期的行为类型。
7. `GetDayOrNight` 取决于全局共享可变状态。
要不惜一切代价避免共享的可变状态!
8. 即使在阅读源代码之后,也无法预测 `GetDayOrNight` 方法的行为。
这是一个严重的问题。通过阅读源代码,应该始终非常清晰,系统一旦开始运行,便可以预测出其行为。
### 失败背后的原则
每当你遇到工程问题时,建议使用久经考验的<ruby>分而治之<rt>divide and conquer</rt></ruby>策略。在这种情况下,遵循<ruby>关注点分离<rt>separation of concerns</rt></ruby>的原则是一种可行的方法。
> 关注点分离SoC是一种用于将计算机程序分为不同模块的设计原理以便每个模块都可以解决一个关注点。关注点是影响计算机程序代码的一组信息。关注点可以和要优化代码的硬件的细节一样概括也可以和要实例化的类的名称一样具体。完美体现 SoC 的程序称为模块化程序。
>
> [出处][4]
`GetDayOrNight` 方法应仅与确定日期和时间值表示白天还是夜晚有关。它不应该与寻找该值的来源有关。该问题应留给调用客户端。
必须将这个问题留给调用客户端,以获取当前时间。这种方法符合另一个有价值的工程原理——<ruby>控制反转<rt>inversion of control</rt></ruby>。Martin Fowler [在这里][5]详细探讨了这一概念。
> 框架的一个重要特征是用户定义的用于定制框架的方法通常来自于框架本身,而不是从用户的应用程序代码调用来的。该框架通常在协调和排序应用程序活动中扮演主程序的角色。控制权的这种反转使框架有能力充当可扩展的框架。用户提供的方法为框架中的特定应用程序量身制定泛化算法。
>
> -- [Ralph Johnson and Brian Foote][6]
### 重构测试用例
因此,代码需要重构。摆脱对内部时钟的依赖(`DateTime` 系统实用程序):
```
DateTime time = new DateTime();
```
删除上述代码(在你的文件中应该是第 7 行)。通过将输入参数 `DateTime` 时间添加到 `GetDayOrNight` 方法,进一步重构代码。
这是重构的类 `DayOrNightUtility.cs`
```
using System;
namespace app {
public class DayOrNightUtility {
public string GetDayOrNight(DateTime time) {
string dayOrNight = "Nighttime";
if(time.Hour >= 7 && time.Hour < 19) {
dayOrNight = "Daylight";
}
return dayOrNight;
}
}
}
```
重构代码需要更改单元测试。 需要准备 `nightHour``dayHour` 的测试数据,并将这些值传到`GetDayOrNight` 方法中。 以下是重构的单元测试:
```
using System;
using Xunit;
using app;
namespace unittest
{
public class UnitTest1
{
DayOrNightUtility dayOrNightUtility = new DayOrNightUtility();
DateTime nightHour = new DateTime(2019, 08, 03, 19, 00, 00);
DateTime dayHour = new DateTime(2019, 08, 03, 07, 00, 00);
[Fact]
public void Given7pmReturnNighttime()
{
var expected = "Nighttime";
var actual = dayOrNightUtility.GetDayOrNight(nightHour);
Assert.Equal(expected, actual);
}
[Fact]
public void Given7amReturnDaylight()
{
var expected = "Daylight";
var actual = dayOrNightUtility.GetDayOrNight(dayHour);
Assert.Equal(expected, actual);
}
}
}
```
### 经验教训
在继续开发这种简单的场景之前,请先回顾复习一下本次练习中所学到的东西。
运行无法测试的代码很容易在不经意间制造陷阱。从表面上看这样的代码似乎可以正常工作。但是遵循测试驱动开发TDD的实践首先描述期望结果然后才描述实现暴露了代码中的严重问题。
这表明 TDD 是确保代码不会太凌乱的理想方法。TDD 指出了一些问题区域例如缺乏单一责任和存在隐藏输入。此外TDD 有助于删除不确定性代码,并用行为明确的完全可测试代码替换它。
最后TDD 帮助交付易于阅读、逻辑易于遵循的代码。
在本系列的下一篇文章中,我将演示如何使用在本练习中创建的逻辑来实现功能代码,以及如何进行进一步的测试使其变得更好。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/mutation-testing-example-failure-experimentation
作者:[Alex Bunardzic][a]
选题:[lujun9972][b]
译者:[Morisun029](https://github.com/Morisun029)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/alex-bunardzic
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
[2]: https://linux.cn/article-11483-1.html
[3]: https://linux.cn/article-11468-1.html
[4]: https://en.wikipedia.org/wiki/Separation_of_concerns
[5]: https://martinfowler.com/bliki/InversionOfControl.html
[6]: http://www.laputan.org/drc/drc.html
[7]: http://www.google.com/search?q=new+msdn.microsoft.com

View File

@@ -0,0 +1,120 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11485-1.html)
[#]: subject: (Essential Accessories for Intel NUC Mini PC)
[#]: via: (https://itsfoss.com/intel-nuc-essential-accessories/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
英特尔 NUC 迷你 PC 的基本配件
======
![](https://img.linux.net.cn/data/attachment/album/201910/20/224650me0qoiqjeiysqqph.jpg)
几周前,我买了一台 [英特尔 NUC 迷你 PC][1]。我[在上面安装了 Linux][2],我非常喜欢它。这个小巧的无风扇机器取代了台式机那庞大的 CPU。
英特尔 NUC 通常采用准系统形式,这意味着它没有任何内存、硬盘,也显然没有操作系统。许多[基于 Linux 的微型 PC][3] 定制化英特尔 NUC 并添加磁盘、RAM 和操作系统将它出售给终端用户。
不用说,它不像大多数其他台式机那样带有键盘、鼠标或屏幕。
[英特尔 NUC][4] 是一款出色的设备,如果你要购买台式机,我强烈建议你购买它。如果你正在考虑购买英特尔 NUC你需要买一些配件以便开始使用它。
### 基本的英特尔 NUC 配件
![][5]
*文章中的 Amazon 链接是(原文的)受益链接。请阅读我们的[受益政策][6]。
#### 外围设备:显示器、键盘和鼠标
这很容易想到。你需要有屏幕、键盘和鼠标才能使用计算机。你需要一台有 HDMI 连接的显示器和一个 USB 或无线键盘鼠标。如果你已经有了这些东西,那你可以继续。
如果你正在寻求建议,我建议购买 LG IPS LED 显示器。我有两台 22 英寸的型号,我对它提供的清晰视觉效果感到满意。
这些显示器有一个简单的固定支架。如果要使显示器可以上下移动并纵向旋转,请尝试使用 [HP EliteDisplay 显示器][7]。
![HP EliteDisplay Monitor][8]
我在多屏设置中同时连接了三台显示器。一台显示器连接到指定的 HDMI 端口。两台显示器通过 [Club 3D 的 Thunderbolt 转 HDMI 分配器][9]连接到 Thunderbolt 端口。
你也可以选择超宽显示器。我对此没有亲身经历。
#### 内存
英特尔 NUC 有两个内存插槽,最多可支持 32GB 内存。由于我的是 i3 核心处理器,因此我选择了 [Crucial 的 8GB DDR4 内存][11],价格约为 $33。
![][12]
8 GB 内存在大多数情况下都没问题,但是如果你的是 i7 核心处理器,那么可以选择 [16GB 内存][13],价格约为 $67。你可以加两条以获得最大 32GB。选择全在于你。
#### 硬盘(重要)
英特尔 NUC 同时支持 2.5 英寸驱动器和 M.2 SSD因此你可以同时使用两者以获得更多存储空间。
2.5 英寸插槽可同时容纳 SSD 和 HDD。我强烈建议选择 SSD因为它比 HDD 快得多。[480GB 2.5 英寸][14]的价格是 $60。我认为这是一个合理的价格。
![][15]
2.5 英寸驱动器的标准 SATA 口速度为 6 Gb/秒。根据你是否选择 NVMe SSDM.2 插槽可能会更快。 NVMe非易失性内存主机控制器接口规范SSD 的速度比普通 SSD也称为 SATA SSD快 4 倍。但是它们可能也比 SATA M2 SSD 贵一些。
当购买 M.2 SSD 时,请检查产品图片。无论是 NVMe 还是 SATA SSD都应在磁盘本身的图片中提到。你可以考虑使用[经济的三星 EVO NVMe M.2 SSD][16]。
![Make sure that your are buying the faster NVMe M2 SSD][17]
M.2 插槽和 2.5 英寸插槽中的 SATA SSD 具有相同的速度。这就是为什么如果你不想选择昂贵的 NVMe SSD建议你选择 2.5 英寸 SATA SSD并保留 M.2 插​​槽供以后升级。
#### 交流电源线
当我拿到 NUC 时,为惊讶地发现,尽管它有电源适配器,但它并没有插头。
正如一些读者指出的那样,你可能有完整的电源线。这取决于你的地理区域和供应商。因此,请检查产品说明和用户评论,以验证其是否具有完整的电源线。
![][10]
#### 其他配套配件
你需要使用 HDMI 线缆连接显示器。如果你要购买新显示器,通常应会有一根线缆。
如果要使用 M.2 插槽,那么可能需要螺丝刀。英特尔 NUC 是一款出色的设备,你只需用手旋转四个脚即可拧开底部面板。你必须打开设备才能放置内存和磁盘。
![Intel NUC with Security Cable | Image Credit Intel][18]
NUC 还有防盗孔,可与防盗绳一起使用。在业务环境中,建议使用防盗绳保护计算机安全。购买[防盗绳几美元][19]便可节省数百美元。
### 你使用什么配件?
这些就是我在使用和建议使用的英特尔 NUC 配件。你呢?如果你有一台 NUC你会使用哪些配件并推荐给其他 NUC 用户?
--------------------------------------------------------------------------------
via: https://itsfoss.com/intel-nuc-essential-accessories/
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://www.amazon.com/Intel-NUC-Mainstream-Kit-NUC8i3BEH/dp/B07GX4X4PW?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B07GX4X4PW (barebone Intel NUC mini PC)
[2]: https://linux.cn/article-11477-1.html
[3]: https://itsfoss.com/linux-based-mini-pc/
[4]: https://www.intel.in/content/www/in/en/products/boards-kits/nuc.html
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/intel-nuc-accessories.png?ssl=1
[6]: https://itsfoss.com/affiliate-policy/
[7]: https://www.amazon.com/HP-EliteDisplay-21-5-Inch-1FH45AA-ABA/dp/B075L4VKQF?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B075L4VKQF (HP EliteDisplay monitors)
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/hp-elitedisplay-monitor.png?ssl=1
[9]: https://www.amazon.com/Club3D-CSV-1546-USB-C-Multi-Monitor-Splitter/dp/B06Y2FX13G?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B06Y2FX13G (thunderbolt to HDMI splitter from Club 3D)
[10]: https://img.linux.net.cn/data/attachment/album/201910/20/224718eebvzvvvm0b6f3ow.jpg
[11]: https://www.amazon.com/Crucial-Single-PC4-19200-SODIMM-260-Pin/dp/B01BIWKP58?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B01BIWKP58 (8GB DDR4 RAM from Crucial)
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/crucial-ram.jpg?ssl=1
[13]: https://www.amazon.com/Crucial-Single-PC4-19200-SODIMM-260-Pin/dp/B019FRBHZ0?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B019FRBHZ0 (16 GB RAM)
[14]: https://www.amazon.com/Green-480GB-Internal-SSD-WDS480G2G0A/dp/B01M3POPK3?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B01M3POPK3 (480 GB 2.5)
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/wd-green-ssd.png?ssl=1
[16]: https://www.amazon.com/Samsung-970-EVO-500GB-MZ-V7E500BW/dp/B07BN4NJ2J?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B07BN4NJ2J (Samsung EVO is a cost effective NVMe M.2 SSD)
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/samsung-evo-nvme.jpg?ssl=1
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/intel-nuc-security-cable.jpg?ssl=1
[19]: https://www.amazon.com/Kensington-Combination-Laptops-Devices-K64673AM/dp/B005J7Y99W?psc=1&SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B005J7Y99W (few dollars in the security cable)

View File

@@ -1,34 +1,34 @@
[#]: collector: (lujun9972)
[#]: translator: (way-ww)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (How to Run the Top Command in Batch Mode)
[#]: via: (https://www.2daygeek.com/linux-run-execute-top-command-in-batch-mode/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
[#]: collector: "lujun9972"
[#]: translator: "way-ww"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-11491-1.html"
[#]: subject: "How to Run the Top Command in Batch Mode"
[#]: via: "https://www.2daygeek.com/linux-run-execute-top-command-in-batch-mode/"
[#]: author: "Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/"
How to Run the Top Command in Batch Mode
如何在批处理模式下运行 top 命令
======
The **[Linux Top command][1]** is the best and most well known command that everyone uses to **[monitor Linux system performance][2]**.
![](https://img.linux.net.cn/data/attachment/album/201910/22/235420ylswdescv5ddffit.jpg)
You probably already know most of the options available, except for a few options, and if Im not wrong, “batch more” is one of the options.
[top 命令][1] 是每个人都在使用的用于 [监控 Linux 系统性能][2] 的最好的命令。你可能已经知道 `top` 命令的绝大部分操作,除了很少的几个操作,如果我没错的话,批处理模式就是其中之一。
Most script writer and developers know this because this option is mainly used when writing the script.
大部分的脚本编写者和开发人员都知道这个,因为这个操作主要就是用来编写脚本。
If youre not sure about this, dont worry were here to explain this.
如果你不了解这个,不用担心,我们将在这里介绍它。
### What is “Batch Mode” in the Top Command
### 什么是 top 命令的批处理模式
The “Batch Mode” option allows you to send top command output to other programs or to a file.
批处理模式允许你将 `top` 命令的输出发送至其他程序或者文件中。
In this mode, top will not accept input and runs until the iterations limit youve set with the “-n” command-line option.
在这个模式中,`top` 命令将不会接收输入并且持续运行,直到迭代次数达到你用 `-n` 选项指定的次数为止。
If you want to fix any performance issues on the Linux server, you need to **[understand the top command output][3]** correctly.
如果你想解决 Linux 服务器上的任何性能问题,你需要正确的 [理解 top 命令的输出][3]。
### 1) How to Run the Top Command in Batch Mode
### 1) 如何在批处理模式下运行 top 命令
By default, the top command sort the results based on CPU usage, so when you run the below top command in batch mode, it does the same and prints the first 35 lines.
默认地,`top` 命令按照 CPU 的使用率来排序输出结果,所以当你在批处理模式中运行以下命令时,它会执行同样的操作并打印前 35 行:
```
# top -bc | head -35
@@ -70,9 +70,9 @@ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
46 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 [kmpath_rdacd]
```
### 2) How to Run the Top Command in Batch Mode and Sort the Output Based on Memory Usage
### 2) 如何在批处理模式下运行 top 命令并按内存使用率排序结果
Run the below top command to sort the results based on memory usage in batch mode.
在批处理模式中运行以下命令按内存使用率对结果进行排序:
```
# top -bc -o +%MEM | head -n 20
@@ -99,19 +99,17 @@ KiB Swap: 1048572 total, 514640 free, 533932 used. 2475984 avail Mem
8632 nobody 20 0 256844 25744 2216 S 0.0 0.7 0:00.03 /usr/sbin/httpd -k start
```
**Details of the above command:**
上面命令的详细信息:
* **-b :** Batch mode operation
* **-c :** To print the absolute path of the running process
* **-o :** To specify fields for sorting processes
* **head :** Output the first part of files
* **-n :** To print the first “n” lines
* `-b`:批处理模式选项
* `-c`:打印运行中的进程的绝对路径
* `-o`:指定进行排序的字段
* `head`:输出文件的第一部分
* `-n`:打印前 n 行
### 3) 如何在批处理模式下运行 top 命令并按照指定的用户进程对结果进行排序
### 3) How to Run the Top Command in Batch Mode and Sort the Output Based on a Specific User Process
If you want to sort results based on a specific user, run the below top command.
如果你想要按照指定用户进程对结果进行排序请运行以下命令:
```
# top -bc -u mysql | head -n 10
@@ -126,15 +124,13 @@ KiB Swap: 1048572 total, 514640 free, 533932 used. 2649412 avail Mem
18105 mysql 20 0 1453900 156888 8816 S 0.0 4.0 2:16.42 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
```
### 4) How to Run the Top Command in Batch Mode and Sort the Output Based on the Process Age
### 4) 如何在批处理模式下运行 top 命令并按照处理时间进行排序
Use the below top command to sort the results based on the age of the process in batch mode. It shows the total CPU time the task has used since it started.
But if you want to check how long a process has been running on Linux, go to the following article.
* **[Five Ways to Check How Long a Process Has Been Running in Linux][4]**
在批处理模式中使用以下 `top` 命令按照处理时间对结果进行排序。这展示了任务从启动以来已使用的总 CPU 时间。
但是如果你想要检查一个进程在 Linux 上运行了多长时间请看接下来的文章:
* [检查 Linux 中进程运行时间的五种方法][4]
```
# top -bc -o TIME+ | head -n 20
@@ -161,9 +157,9 @@ KiB Swap: 1048572 total, 514640 free, 533932 used. 2440332 avail Mem
342 root 20 0 39472 2940 2752 S 0.0 0.1 1:18.17 /usr/lib/systemd/systemd-journald
```
### 5) How to Run the Top Command in Batch Mode and Save the Output to a File
### 5) 如何在批处理模式下运行 top 命令并将结果保存到文件中
If you want to share the output of the top command to someone for troubleshooting purposes, redirect the output to a file using the following command.
如果出于解决问题的目的,你想要和别人分享 `top` 命令的输出,请使用以下命令重定向输出到文件中:
```
# top -bc | head -35 > top-report.txt
@@ -207,11 +203,11 @@ KiB Swap: 1048572 total, 514640 free, 533932 used. 2659084 avail Mem
36 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 [crypto]
```
### How to Sort Output Based on Specific Fields
### 如何按照指定字段对结果进行排序
In the latest version of the top command release, press the **“f”** key to sort the fields via the field letter.
`top` 命令的最新版本中, 按下 `f` 键进入字段管理界面。
To sort with a new field, use the **“up/down”** arrow to select the correct selection, and then press **“s”** to sort it. Finally press **“q”** to exit from this window.
要使用新字段进行排序, 请使用 `up`/`down` 箭头选择正确的选项,然后再按下 `s` 键进行排序。最后按 `q` 键退出此窗口。
```
Fields Management for window 1:Def, whose current sort field is %CPU
@@ -269,9 +265,9 @@ Fields Management for window 1:Def, whose current sort field is %CPU
nsUSER = USER namespace Inode
```
For older version of the top command, press the **“shift+f”** or **“shift+o”** key to sort the fields via the field letter.
`top` 命令的旧版本,请按 `shift+f``shift+o` 键进入字段管理界面进行排序。
To sort with a new field, select the corresponding sort **field letter**, and then press **“Enter”** to sort it.
要使用新字段进行排序,请选择相应的排序字段字母, 然后按下回车键排序。
```
Current Sort Field: N for window 1:Def
@@ -322,8 +318,8 @@ via: https://www.2daygeek.com/linux-run-execute-top-command-in-batch-mode/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
译者:[way-ww](https://github.com/way-ww)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@@ -0,0 +1,161 @@
[#]: collector: (lujun9972)
[#]: translator: (wenwensnow)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11504-1.html)
[#]: subject: (Use GameHub to Manage All Your Linux Games in One Place)
[#]: via: (https://itsfoss.com/gamehub/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
用 GameHub 集中管理你 Linux 上的所有游戏
======
你在 Linux 上是怎么[玩游戏的呢][1]? 让我猜猜,要不就是从软件中心直接安装,要不就选 Steam、GOG、Humble Bundle 等平台,对吧?但是,如果你有多个游戏启动器和客户端,又要如何管理呢?好吧,对我来说这简直令人头疼 —— 这也是我发现 [GameHub][2] 这个应用之后,感到非常高兴的原因。
GameHub 是为 Linux 发行版设计的一个桌面应用,它能让你“集中管理你的所有游戏”。这听起来很有趣,是不是?下面让我来具体说明一下。
![][3]
### 集中管理不同平台 Linux 游戏的 GameHub
让我们看看,对玩家来说,让 GameHub 成为一个[不可或缺的 Linux 应用][4]的功能,都有哪些。
#### Steam、GOG & Humble Bundle 支持
![][5]
它支持 Steam、[GOG][6] 和 [Humble Bundle][7] 账户整合。你可以登录你的 GameHub 账号,从而在你的库管理器中管理所有游戏。
对我来说,我在 Steam 上有很多游戏Humble Bundle 上也有一些。我不能确保它支持所有平台,但可以确信的是,主流平台游戏是没有问题的。
#### 支持原生游戏
![][8]
[有很多网站专门推荐 Linux 游戏,并支持下载][9]。你可以通过下载安装包,或者添加可执行文件,从而管理原生游戏。
可惜的是,现在无法在 GameHub 内搜索 Linux 游戏。如上图所示,你需要分别下载游戏,随后再将其添加到 GameHub 中。
#### 模拟器支持
用模拟器,你可以在 [Linux 上玩复古游戏][10]。正如上图所示,你可以添加模拟器(并导入模拟的镜像)。
你可以在 [RetroArch][11] 查看已有的模拟器,但也能根据需求添加自定义模拟器。
#### 用户界面
![Gamehub 界面选项][12]
当然,用户体验很重要。因此,探究下用户界面都有些什么,也很有必要。
我个人觉得,这一应用很容易使用,并且黑色主题是一个加分项。
#### 手柄支持
如果你习惯在 Linux 系统上用手柄玩游戏 —— 你可以轻松在设置里添加,启用或禁用它。
#### 多个数据提供商
因为它需要获取你的游戏信息(或元数据),也意味着它需要一个数据源。你可以看到下图列出的所有数据源。
![Data Providers Gamehub][13]
这里你什么也不用做 —— 但如果你使用的是 steam 之外的其他平台,你需要为 [IDGB 生成一个 API 密钥][14]。
我建议只有出现 GameHub 中的提示/通知,或有些游戏在 GameHub 上没有任何描述/图片/状态时,再这么做。
#### 兼容性选项
![][15]
你有不支持在 Linux 上运行的游戏吗?
不用担心GameHub 上提供了多种兼容工具,如 Wine/Proton你可以利用它们来玩游戏。
我们无法确定具体哪个兼容工具适用于你 —— 所以你需要自己亲自测试。然而,对许多游戏玩家来说,这的确是个很有用的功能。
### GameHub: 如何安装它呢?
![][18]
首先,你可以直接在软件中心或者应用商店内搜索。 它在 “Pop!_Shop” 之下。所以,它在绝大多数官方源中都能找到。
如果你在这些地方都没有找到,你可以手动添加源,并从终端上安装它,你需要输入以下命令:
```
sudo add-apt-repository ppa:tkashkin/gamehub
sudo apt update
sudo apt install com.github.tkashkin.gamehub
```
如果你遇到了 “add-apt-repository command not found” 这个错误,你可以看看,[add-apt-repository not found error.][19]这篇文章,它能帮你解决这一问题。
这里还提供 AppImage 和 FlatPak 版本。 在[官网][2] 上,你可以针对找到其他 Linux 发行版的安装手册。
同时,你还可以从它的 [GitHub 页面][20]下载之前版本的安装包.
[GameHub][2]
### 如何在 GameHub 上管理你的游戏?
在启动程序后,你可以将自己的 Steam/GOG/Humble Bundle 账号添加进来。
对于 Steam你需要在 Linux 发行版上安装 Steam 客户端。一旦安装完成,你可以轻松将账号中的游戏导入 GameHub。
![][16]
对于 GOG & Humble Bundle登录后就能直接在 GameHub 上管理游戏了。
如果你想添加模拟器或者本地安装文件,点击窗口右上角的 “+” 按钮进行添加。
### 如何安装游戏?
对于 Steam 游戏,它会自动启动 Steam 客户端,从而下载/安装游戏(我希望之后安装游戏,可以不用启动 Steam
![][17]
但对于 GOG/Humble Bundle登录后就能直接、下载安装游戏。必要的话对于那些不支持在 Linux 上运行的游戏,你可以使用兼容工具。
无论是模拟器游戏,还是本地游戏,只需添加安装包或导入模拟器镜像就可以了。这里没什么其他步骤要做。
### 注意
GameHub 是相当灵活的一个集中游戏管理应用。 用户界面和选项设置也相当直观。
你之前是否使用过这一应用呢?如果有,请在评论里写下你的感受。
而且,如果你想尝试一些与此功能相似的工具/应用,请务必告诉我们。
--------------------------------------------------------------------------------
via: https://itsfoss.com/gamehub/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[wenwensnow](https://github.com/wenwensnow)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/linux-gaming-guide/
[2]: https://tkashkin.tk/projects/gamehub/
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-home-1.png?ssl=1
[4]: https://itsfoss.com/essential-linux-applications/
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-platform-support.png?ssl=1
[6]: https://www.gog.com/
[7]: https://www.humblebundle.com/monthly?partner=itsfoss
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-native-installers.png?ssl=1
[9]: https://itsfoss.com/download-linux-games/
[10]: https://itsfoss.com/play-retro-games-linux/
[11]: https://www.retroarch.com/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-appearance.png?ssl=1
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/data-providers-gamehub.png?ssl=1
[14]: https://www.igdb.com/api
[15]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-windows-game.png?fit=800%2C569&ssl=1
[16]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-library.png?ssl=1
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-compatibility-layer.png?ssl=1
[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/gamehub-install.jpg?ssl=1
[19]: https://itsfoss.com/add-apt-repository-command-not-found/
[20]: https://github.com/tkashkin/GameHub/releases

View File

@@ -0,0 +1,98 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11469-1.html)
[#]: subject: (Command line quick tips: Locate and process files with find and xargs)
[#]: via: (https://fedoramagazine.org/command-line-quick-tips-locate-and-process-files-with-find-and-xargs/)
[#]: author: (Ben Cotton https://fedoramagazine.org/author/bcotton/)
命令行技巧:使用 find 和 xargs 查找和处理文件
======
![][1]
`find` 是日常工具箱中功能强大、灵活的命令行程序之一。它如它名字所暗示的:查找符合你指定条件的文件和目录。借助 `-exec``-delete` 之类的参数,你可以让它对找到的文件进行操作。
在[命令行提示][2]系列的这一期中,你将会看到 `find` 命令的介绍,并学习如何使用内置命令或使用 `xargs` 命令处理文件。
### 查找文件
`find` 至少要加上查找的路径。例如,此命令将查找(并打印)系统上的每个文件:
```
find /
```
由于一切皆文件,因此你会看到大量的输出。这可能无法帮助你找到所需的内容。你可以更改路径参数缩小范围,但这实际上并没有比使用 `ls` 命令更好。因此,你需要考虑要查找的内容。
也许你想在家目录中查找所有 JPEG 文件。 `-name` 参数允许你将结果限制为与给定模式匹配的文件。
```
find ~ -name '*jpg'
```
但是等等!如果其中一些扩展名是大写怎么办? `-iname` 类似于 `-name`,但不区分大小写:
```
find ~ -iname '*jpg'
```
很好!但是 8.3 命名方案出自 1985 年。某些图片的扩展名可能是 .jpeg。幸运的是我们可以将模式使用“或”`-o`)进行组合。括号需要转义,以便使 `find` 命令而不是 shell 程序尝试解释它们。
```
find ~ \( -iname 'jpeg' -o -iname 'jpg' \)
```
更进一步。如果你有一些以 `jpg` 结尾的目录怎么办?(我不懂你为什么将目录命名为 `bucketofjpg` 而不是 `pictures`?)我们可以加上 `-type` 参数来仅查找文件:
```
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f
```
或者,也许你想找到那些名字奇怪的目录,以便之后可以重命名它们:
```
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type d
```
最近你拍摄了很多照片,因此使用 `-mtime`(修改时间)将范围缩小到最近一周修改过的文件。 `-7` 表示 7 天或更短时间内修改的所有文件。
```
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7
```
### 使用 xargs 进行操作
`xargs` 命令从标准输入流中获取参数,并基于它们执行命令。继续使用上一节中的示例,假设你要将上周修改过的家目录中的所有 JPEG 文件复制到 U 盘,以便插到电子相册上。假设你已经将 U 盘挂载到 `/media/photo_display`
```
find ~ \( -iname '*jpeg' -o -iname '*jpg' \) -type f -mtime -7 -print0 | xargs -0 cp -t /media/photo_display
```
这里的 `find` 命令与以前的版本略有不同。`-print0` 命令让输出有一些更改:它不使用换行符,而是添加了一个 `null` 字符。`xargs``-0`(零)选项可调整解析以达到预期效果。这很重要,不然对包含空格、引号或其他特殊字符的文件名执行操作可能无法按预期进行。对文件采取任何操作时,都应使用这些选项。
`cp` 命令的 `-t` 参数很重要,因为 `cp` 通常要求目的地址在最后。你可以不使用 `xargs` 而使用 `find``-exec` 执行此操作,但是 `xargs` 的方式会更快,尤其是对于大量文件,因为它会单次调用 `cp`
### 了解更多
这篇文章仅仅是 `find` 可以做的事情的表面。 `find` 支持基于权限、所有者、访问时间等的测试。它甚至可以将搜索路径中的文件与其他文件进行比较。将测试与布尔逻辑相结合,可以为你提供惊人的灵活性,以精确地找到你要查找的文件。使用内置命令或管道传递给 `xargs`,你可以快速处理大量文件。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/command-line-quick-tips-locate-and-process-files-with-find-and-xargs/
作者:[Ben Cotton][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://fedoramagazine.org/author/bcotton/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2018/10/commandlinequicktips-816x345.jpg
[2]: https://fedoramagazine.org/?s=command+line+quick+tips
[3]: https://opensource.com/article/18/4/how-use-find-linux
[4]: https://unsplash.com/@wflwong?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[5]: https://unsplash.com/s/photos/search?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText

View File

@@ -1,8 +1,8 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11481-1.html)
[#]: subject: (Top 10 open source video players for Linux)
[#]: via: (https://opensourceforu.com/2019/10/top-10-open-source-video-players-for-linux/)
[#]: author: (Stella Aldridge https://opensourceforu.com/author/stella-aldridge/)
@@ -10,15 +10,15 @@
Linux 中的十大开源视频播放器
======
[![][1]][2]
![][1]
_选择合适的视频播放器有助于确保你获得最佳的观看体验,并为你提供[创建视频网站][3]的工具。你甚至可以根据个人喜好自定义正在观看的视频。_
> 选择合适的视频播放器有助于确保你获得最佳的观看体验,并为你提供[创建视频网站][3]的工具。你甚至可以根据个人喜好自定义正在观看的视频。
因此,为了帮助你挑选适合你需求的最佳播放器,我们列出了 Linux 中十大开源播放器。
因此,为了帮助你挑选适合你需求的最佳播放器,我们列出了 Linux 中十大开源播放器。
让我们来看看:
**1\. XBMC Kodi 媒体中心**
### 1、XBMC Kodi 媒体中心
这是一个灵活的跨平台播放器,核心使用 C++ 编写,并提供 Python 脚本作为附加组件。使用 Kodi 的好处包括:
@@ -28,11 +28,9 @@ _选择合适的视频播放器有助于确保你获得最佳的观看体验
* 有很多不错的附加组件,如视频和音频流插件、主题、屏幕保护程序等
* 它支持多种格式,如 MPEG-1、2、4、RealVideo、HVC、HEVC 等
### 2、VLC 媒体播放器
**2\. VLC 媒体播放器**
由于该播放器在一系列操作系统上具有令人印象深刻的功能和可用性,他在列表上是理所当然的。它使用 C、C++ 和 Objective C 编写用户无需使用插件这要归功于它对解码库的广泛支持。VLC 媒体播放器的优势包括:
由于该播放器在一系列操作系统上具有令人印象深刻的功能和可用性,它出现在列表上是理所当然的。它使用 C、C++ 和 Objective C 编写用户无需使用插件这要归功于它对解码库的广泛支持。VLC 媒体播放器的优势包括:
* 在 Linux 上支持 DVD 播放器
* 能够播放 .iso 文件
@@ -40,54 +38,45 @@ _选择合适的视频播放器有助于确保你获得最佳的观看体验
* 可以直接从 U 盘或外部驱动器运行
* API 支持和浏览器支持(通过插件)
**3\. BomiCMPlayer**
### 3、BomiCMPlayer
这个灵活和强大的播放器被许多普通用户选择,它的优势有:
* 易于使用的图形用户界面 GUI
* 易于使用的图形用户界面GUI
* 令人印象深刻的播放能力
* 恢复播放的选项
* 可以恢复播放
* 支持字幕,可以渲染多个字幕文件
![][4]
### 4、Miro 音乐与视频播放器
**[![][4]][5]
4\. Miro Music and Video Player**
以前被称为 Democracy Player DTV Miro 由分享文化基金会Participatory Culture Foundation重新开发是一个不错的跨平台音频视频播放器。令人印象深刻因为
以前被称为 Democracy PlayerDTVMiro 由<ruby>参与文化基金会<rt>Participatory Culture Foundation</rt></ruby>重新开发,是一个不错的跨平台音频视频播放器。令人印象深刻,因为:
* 支持一些高清音频和视频
* 提供超过 40 种语言版本
* 可以播放多种文件格式例如QuickTime、WMV、MPEG 文件、音频视频接口 AVI、XVID
* 可以播放多种文件格式例如QuickTime、WMV、MPEG 文件、AVI、XVID
* 一旦可用,可以自动通知用户并下载视频
### 5、SMPlayer
**5\. SMPlayer**
这个跨平台的媒体播放器,只使用 C++ 的 Qt 库编写,它是一个强大的,多功能播放器。我们喜欢它,因为:
这个跨平台的媒体播放器,只使用 C++ 的 Qt 库编写,它是一个强大的多功能播放器。我们喜欢它,因为:
* 有多语言选择
* 支持所有默认格式
* 支持 EDL 文件,你可以配置从 Internet 获取的字幕
* 支持 EDL 文件,你可以配置从互联网获取的字幕
* 可从互联网下载的各种皮肤
* 倍速播放
**6\. MPV Player**
### 6、MPV 播放器
它用 C、Objective-C、Lua 和 Python 编写,免费、易于使用,并且有许多新功能,便于使用。主要加分是:
* 可以编译为一个库,公开客户端 API从而增强控制
* 允许媒体编码
* 平滑
* 平滑动
**7\. Deepin Movie**
### 7、Deepin Movie
此播放器是开源媒体播放器的一个极好的例子,它有很多优势,包括:
@@ -95,45 +84,37 @@ _选择合适的视频播放器有助于确保你获得最佳的观看体验
* 各种格式的视频文件可以通过这个播放器轻松播放
* 流媒体功能能让用户享受许多在线视频资源
### 8、Gnome 视频
以前称为 Totem这是 Gnome 桌面环境的播放器。
**8\. Gnome Videos**
以前称为 Totem这是 Gnome 桌面环境选择的播放器。
完全用 C 编写,使用 GStreamer 多媒体框架构建,另外的版本(&gt;2.7.1)使用 xine 作为后端。它是很棒的,因为:
完全用 C 编写,使用 GStreamer 多媒体框架构建,高于 2.7.1 的版本使用 xine 作为后端。它是很棒的,因为:
它支持大量的格式,包括:
* Supports for direct video playback from Internet channels such as Apple
* SHOUTcast、SMIL、M3U、Windows 媒体播放器格式等
* 你可以在播放过程中调整灯光设置,如亮度和对比度
* 加载 SubRip 字幕
* 支持从互联网频道(如 Apple直接播放视频
**9\. Xine Multimedia Player**
### 9、Xine 多媒体播放器
我们列表中用 C 编写的另外一个跨平台多媒体播放器。这是一个全能播放器,因为:
* 它支持物理媒体以及视频设备。3gp MatroskaMKV、 MOV Mp4、音频格式
* 它支持物理媒体以及视频设备。3gpMKV、 MOVMp4、音频格式
* 网络协议V4L、DVB 和 PVR 等
* 它可以手动校正音频和视频流的同步
### 10、ExMPlayer
**10\. ExMPlayer**
最后单同样重要的一个ExMPlayer 是一个惊人的、强大的 MPlayer 的 GUI 前端。它的优点包括:
最后但同样重要的一个ExMPlayer 是一个惊人的、强大的 MPlayer 的 GUI 前端。它的优点包括:
* 可以播放任何媒体格式
* 支持网络流和字幕
* 易于使用的音频转换器
* 高品质的音频提取,而不会影响音质
上面的视频播放器在 Linux 上工作得很好。我们建议你尝试一下,选择一个最适合你的播放器。
上面这些视频播放器在 Linux 上工作得很好。我们建议你尝试一下,选择一个最适合你的播放器。
--------------------------------------------------------------------------------
@@ -142,7 +123,7 @@ via: https://opensourceforu.com/2019/10/top-10-open-source-video-players-for-lin
作者:[Stella Aldridge][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@@ -0,0 +1,71 @@
[#]: collector: (lujun9972)
[#]: translator: (lnrCoder)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11492-1.html)
[#]: subject: (DevSecOps pipelines and tools: What you need to know)
[#]: via: (https://opensource.com/article/19/10/devsecops-pipeline-and-tools)
[#]: author: (Sagar Nangare https://opensource.com/users/sagarnangare)
你需要知道的 DevSecOps 流程及工具
======
> DevSecOps 对 DevOps 进行了改进,以确保安全性仍然是该过程的一个重要部分。
![](https://img.linux.net.cn/data/attachment/album/201910/23/002010fvzh282e8ghhdzpk.jpg)
到目前为止DevOps 在 IT 世界中已广为人知,但其并非完美无缺。试想一下,你在一个项目的现代应用程序交付中实施了所有 DevOps 工程实践。你已经到达开发流程的末尾,但是渗透测试团队(内部或外部)检测到安全漏洞并提出了报告。现在,你必须重新启动所有流程,并要求开发人员修复该漏洞。
在基于 DevOps 的软件开发生命周期SDLC系统中这并不繁琐但它确实会浪费时间并影响交付进度。如果从 SDLC 初期就已经集成了安全性,那么你可能已经跟踪到了该故障,并在开发流程中就消除了它。但是,如上述情形那样,将安全性推到开发流程的最后将导致更长的开发生命周期。
这就是引入 DevSecOps 的原因,它以自动化的方式巩固了整个软件交付周期。
在现代 DevOps 方法中,组织广泛使用容器托管应用程序,我们看到 [Kubernetes][2] 和 [Istio][3] 使用的较多。但是这些工具都有其自身的漏洞。例如云原生计算基金会CNCF最近完成了一项 [kubernetes 安全审计][4]发现了几个问题。DevOps 开发流程中使用的所有工具在流程运行时都需要进行安全检查DevSecOps 会推动管理员去监视工具的存储库以获取升级和补丁。
### 什么是 DevSecOps?
与 DevOps 一样DevSecOps 是开发人员和 IT 运营团队在开发和部署软件应用程序时所遵循的一种思维方式或文化。它将主动和自动化的安全审计以及渗透测试集成到敏捷应用程序开发中。
要使用 [DevSecOps][5],你需要:
* 从 SDLC 开始就引入安全性概念,以最大程度地减少软件代码中的漏洞。
* 确保每个人(包括开发人员和 IT 运营团队)共同承担在其任务中遵循安全实践的责任。
* 在 DevOps 工作流程开始时集成安全控件、工具和流程。这些将在软件交付的每个阶段启用自动安全检查。
DevOps 一直致力于在开发和发布过程中包括安全性以及质量保证QA、数据库管理和其他所有方面。然而DevSecOps 是该过程的一个演进,以确保安全永远不会被遗忘,成为该过程的一个重要部分。
### 了解 DevSecOps 流程
典型的 DevOps 流程有不同的阶段;典型的 SDLC 流程包括计划、编码、构建、测试、发布和部署等阶段。在 DevSecOps 中,每个阶段都会应用特定的安全检查。
* **计划**:执行安全性分析并创建测试计划,以确定在何处、如何以及何时进行测试的方案。
* **编码**:部署整理工具和 Git 控件以保护密码和 API 密钥。
* **构建**在构建执行代码时请结合使用静态应用程序安全测试SAST工具来跟踪代码中的缺陷然后再部署到生产环境中。这些工具针对特定的编程语言。
* **测试**在运行时使用动态应用程序安全测试DAST工具来测试您的应用程序。 这些工具可以检测与用户身份验证授权SQL 注入以及与 API 相关的端点相关的错误。
* **发布**:在发布应用程序之前,请使用安全分析工具来进行全面的渗透测试和漏洞扫描。
* **部署**:在运行时完成上述测试后,将安全的版本发送到生产中以进行最终部署。
### DevSecOps 工具
SDLC 的每个阶段都有可用的工具。有些是商业产品,但大多数是开源的。在我的下一篇文章中,我将更多地讨论在流程的不同阶段使用的工具。
随着基于现代 IT 基础设施的企业安全威胁的复杂性增加DevSecOps 将发挥更加关键的作用。然而DevSecOps 流程将需要随着时间的推移而改进,而不是仅仅依靠同时实施所有安全更改即可。这将消除回溯或应用交付失败的可能性。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/devsecops-pipeline-and-tools
作者:[Sagar Nangare][a]
选题:[lujun9972][b]
译者:[lnrCoder](https://github.com/lnrCoder)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/sagarnangare
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LAW-Internet_construction_9401467_520x292_0512_dc.png?itok=RPkPPtDe (An intersection of pipes.)
[2]: https://opensource.com/resources/what-is-kubernetes
[3]: https://opensource.com/article/18/9/what-istio
[4]: https://www.cncf.io/blog/2019/08/06/open-sourcing-the-kubernetes-security-audit/
[5]: https://resources.whitesourcesoftware.com/blog-whitesource/devsecops

View File

@@ -0,0 +1,124 @@
[#]: collector: (lujun9972)
[#]: translator: (singledo)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11470-1.html)
[#]: subject: (How to Unzip a Zip File in Linux [Beginners Tutorial])
[#]: via: (https://itsfoss.com/unzip-linux/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
新手教程:如何在 Linux 下解压 Zip 文件
======
> 本文将会向你展示如何在 Ubuntu 和其他 Linux 发行版本上解压文件。终端和图形界面的方法都会讨论。
[Zip][1] 是一种创建压缩存档文件的最普通、最流行的方法。它也是一种古老的文件归档文件格式,这种格式创建于 1989 年。由于它的广泛使用,你会经常遇见 zip 文件。
在更早的一份教程里,我介绍了[如何在 Linux 上用 zip 压缩一个文件夹][2]。在这篇面向初学者的快速教程中,我会介绍如何在 Linux 上解压文件。
先决条件:检查你是否安装了 `unzip`
为了解压 zip 归档文件,你必须在你的系统上安装了 unzip 软件包。大多数现代的的 Linux 发行版本提供了解压 zip 文件的支持,但是对这些 zip 文件进行校验以避免以后出现损坏总是没有坏处的。
在基于 [Unbutu][3] 和 [Debian][4] 的发行版上,你能够使用下面的命令来安装 `unzip`。如果你已经安装了,你会被告知已经被安装。
```
sudo apt install unzip
```
一旦你能够确认你的系统中安装了 `unzip`,你就可以通过 `unzip` 来解压 zip 归档文件。
你也能够使用命令行或者图形工具来达到目的,我会向你展示两种方法:
### 使用命令行解压文件
在 Linux 下使用 `unzip` 命令是非常简单的。在你放 zip 文件的目录,用下面的命令:
```
unzip zipped_file.zip
```
你可以给 zip 文件提供解压路径而不是解压到当前所在路径。你会在终端输出中看到提取的文件:
```
unzip metallic-container.zip -d my_zip
Archive: metallic-container.zip
inflating: my_zip/625993-PNZP34-678.jpg
inflating: my_zip/License free.txt
inflating: my_zip/License premium.txt
```
上面的命令有一个小问题。它会提取 zip 文件中所有的内容到现在的文件夹。你会在当前文件夹下留下一堆没有组织的文件,这不是一件很好的事情。
#### 解压到文件夹下
在 Linux 命令行下,对于把文件解压到一个文件夹下是一个好的做法。这种方式下,所有的提取文件都会被存储到你所指定的文件夹下。如果文件夹不存在,会创建该文件夹。
```
unzip zipped_file.zip -d unzipped_directory
```
现在 `zipped_file.zip` 中所有的内容都会被提取到 `unzipped_directory` 中。
由于我们在讨论好的做法,这里有另一个注意点,我们可以查看压缩文件中的内容而不用实际解压。
#### 查看压缩文件中的内容而不解压压缩文件
```
unzip -l zipped_file.zip
```
下面是该命令的输出:
```
unzip -l metallic-container.zip
Archive: metallic-container.zip
Length Date Time Name
--------- ---------- ----- ----
6576010 2019-03-07 10:30 625993-PNZP34-678.jpg
1462 2019-03-07 13:39 License free.txt
1116 2019-03-07 13:39 License premium.txt
--------- -------
6578588 3 files
```
在 Linux 下,还有些 `unzip` 的其它用法,但我想你现在已经对在 Linux 下使用解压文件有了足够的了解。
### 使用图形界面来解压文件
如果你使用桌面版 Linux那你就不必总是使用终端。在图形化的界面下我们又要如何解压文件呢? 我使用的是 [GNOME 桌面][7],不过其它桌面版 Linux 发行版也大致相同。
打开文件管理器,然后跳转到 zip 文件所在的文件夹下。在文件上点击鼠标右键,你会在弹出的窗口中看到 “提取到这里”,选择它。
![Unzip File in Ubuntu][8]
`unzip` 命令不同这个提取选项会创建一个和压缩文件名相同的文件夹LCTT 译注:文件夹没有 `.zip` 扩展名),并且把压缩文件中的所有内容存储到创建的文件夹下。相对于 `unzip` 命令的默认行为是将压缩文件提取到当前所在的文件下,图形界面的解压对于我来说是一件非常好的事情。
这里还有一个选项“提取到……”,你可以选择特定的文件夹来存储提取的文件。
你现在知道如何在 Linux 解压文件了。你也许还对学习[在 Linux 下使用 7zip][9] 感兴趣?
--------------------------------------------------------------------------------
via: https://itsfoss.com/unzip-linux/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[octopus](https://github.com/singledo)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/Zip_(file_format)
[2]: https://itsfoss.com/linux-zip-folder/
[3]: https://ubuntu.com/
[4]: https://www.debian.org/
[5]: tmp.eqEocGssC8#terminal
[6]: tmp.eqEocGssC8#gui
[7]: https://gnome.org/
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/unzip-files-ubuntu.jpg?ssl=1
[9]: https://itsfoss.com/use-7zip-ubuntu-linux/

View File

@@ -0,0 +1,68 @@
[#]: collector: (lujun9972)
[#]: translator: (Morisun029)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11506-1.html)
[#]: subject: (How to use IoT devices to keep children safe?)
[#]: via: (https://opensourceforu.com/2019/10/how-to-use-iot-devices-to-keep-children-safe/)
[#]: author: (Andrew Carroll https://opensourceforu.com/author/andrew-carroll/)
如何使用物联网设备来确保儿童安全?
======
![][1]
IoT (物联网)设备正在迅速改变我们的生活。这些设备无处不在,从我们的家庭到其它行业。根据一些预测数据,到 2020 年,将会有 100 亿个 IoT 设备。到 2025 年,该数量将增长到 220 亿。目前,物联网已经在很多领域得到了应用,包括智能家居、工业生产过程、农业甚至医疗保健领域。伴随着如此广泛的应用,物联网显然已经成为近年来的热门话题之一。
多种因素促成了物联网设备在多个学科的爆炸式增长。这其中包括低成本处理器和无线连接的的可用性,以及开源平台的信息交流推动了物联网领域的创新。与传统的应用程序开发相比,物联网设备的开发成指数级增长,因为它的资源是开源的。
在解释如何使用物联网设备来保护儿童之前,必须对物联网技术有基本的了解。
### IoT 设备是什么?
IoT 设备是指那些在没有人类参与的情况下彼此之间可以通信的设备。因此,许多专家并不将智能手机和计算机视为物联网设备。此外,物联网设备必须能够收集数据并且能将收集到的数据传送到其他设备或云端进行处理。
然而,在某些领域中,我们需要探索物联网的潜力。儿童往往是脆弱的,他们很容易成为犯罪分子和其他蓄意伤害者的目标。无论在物理世界还是数字世界中,儿童都很容易面临犯罪的威胁。因为父母不能始终亲自到场保护孩子;这就是为什么需要监视工具了。
除了适用于儿童的可穿戴设备外,还有许多父母监视应用程序,例如 Xnspy可实时监控儿童并提供信息的实时更新。这些工具可确保儿童安全。可穿戴设备确保儿童身体上的安全性而家长监控应用可确保儿童的上网安全。
由于越来越多的孩子花费时间在智能手机上,毫无意外地,他们也就成为诈骗分子的主要目标。此外,由于恋童癖、网络自夸和其他犯罪在网络上的盛行,儿童也有可能成为网络欺凌的目标。
这些解决方案够吗?我们需要找到物联网解决方案,以确保孩子们在网上和线下的安全。在当代,我们如何确保孩子的安全?我们需要提出创新的解决方案。 物联网可以帮助保护孩子在学校和家里的安全。
### 物联网的潜力
物联网设备提供的好处很多。举例来说,父母可以远程监控自己的孩子,而又不会显得太霸道。因此,儿童在拥有安全环境的同时也会有空间和自由让自己变得独立。
而且,父母也不必在为孩子的安全而担忧。物联网设备可以提供 7x24 小时的信息更新。像 Xnspy 之类的监视应用程序在提供有关孩子的智能手机活动信息方面更进了一步。随着物联网设备变得越来越复杂,拥有更长使用寿命的电池只是一个时间问题。诸如位置跟踪器之类的物联网设备可以提供有关孩子下落的准确详细信息,所以父母不必担心。
虽然可穿戴设备已经非常好了,但在确保儿童安全方面,这些通常还远远不够。因此,要为儿童提供安全的环境,我们还需要其他方法。许多事件表明,儿童在学校比其他任何公共场所都容易受到攻击。因此,学校需要采取安全措施,以确保儿童和教师的安全。在这一点上,物联网设备可用于检测潜在威胁并采取必要的措施来防止攻击。威胁检测系统包括摄像头。系统一旦检测到威胁,便可以通知当局,如一些执法机构和医院。智能锁等设备可用于封锁学校(包括教室),来保护儿童。除此之外,还可以告知父母其孩子的安全,并立即收到有关威胁的警报。这将需要实施无线技术,例如 Wi-Fi 和传感器。因此,学校需要制定专门用于提供教室安全性的预算。
智能家居实现拍手关灯,也可以让你的家庭助手帮你关灯。同样,物联网设备也可用在屋内来保护儿童。在家里,物联网设备(例如摄像头)为父母在照顾孩子时提供 100 的可见性。当父母不在家里时,可以使用摄像头和其他传感器检测是否发生了可疑活动。其他设备(例如连接到这些传感器的智能锁)可以锁门和窗,以确保孩子们的安全。
同样,可以引入许多物联网解决方案来确保孩子的安全。
### 有多好就有多坏
物联网设备中的传感器会创建大量数据。数据的安全性是至关重要的一个因素。收集的有关孩子的数据如果落入不法分子手中会存在危险。因此需要采取预防措施。IoT 设备中泄露的任何数据都可用于确定行为模式。因此,必须对提供不违反用户隐私的安全物联网解决方案投入资金。
IoT 设备通常连接到 Wi-Fi用于设备之间传输数据。未加密数据的不安全网络会带来某些风险。这样的网络很容易被窃听。黑客可以使用此类网点来入侵系统。他们还可以将恶意软件引入系统从而使系统变得脆弱、易受攻击。此外对设备和公共网络例如学校的网络的网络攻击可能导致数据泄露和私有数据盗用。 因此,在实施用于保护儿童的物联网解决方案时,保护网络和物联网设备的总体计划必须生效。
物联网设备保护儿童在学校和家里的安全的潜力尚未发现有什么创新。我们需要付出更多努力来保护连接 IoT 设备的网络安全。此外,物联网设备生成的数据可能落入不法分子手中,从而造成更多麻烦。因此,这是物联网安全至关重要的一个领域。
--------------------------------------------------------------------------------
via: https://opensourceforu.com/2019/10/how-to-use-iot-devices-to-keep-children-safe/
作者:[Andrew Carroll][a]
选题:[lujun9972][b]
译者:[Morisun029](https://github.com/Morisun029)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensourceforu.com/author/andrew-carroll/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/10/Visual-Internet-of-things_EB-May18.jpg?resize=696%2C507&ssl=1 (Visual Internet of things_EB May18)
[2]: https://i0.wp.com/opensourceforu.com/wp-content/uploads/2019/10/Visual-Internet-of-things_EB-May18.jpg?fit=900%2C656&ssl=1

View File

@@ -0,0 +1,98 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11519-1.html)
[#]: subject: (Object-Oriented Programming and Essential State)
[#]: via: (https://theartofmachinery.com/2019/10/13/oop_and_essential_state.html)
[#]: author: (Simon Arneaud https://theartofmachinery.com)
面向对象编程和根本状态
======
![](https://img.linux.net.cn/data/attachment/album/201910/30/232452kvdivhgb9b2yi0ug.jpg)
早在 2015 年Brian Will 撰写了一篇有挑衅性的博客:[面向对象编程:一个灾难故事][1]。他随后发布了一个名为[面向对象编程很糟糕][2]的视频,该视频更加详细。我建议你花些时间观看视频,下面是我的一段总结:
> OOP 的柏拉图式理想是一堆相互解耦的对象它们彼此之间发送无状态消息。没有人真的像这样制作软件Brian 指出这甚至没有意义:对象需要知道向哪个对象发送消息,这意味着它们需要相互引用。该视频大部分讲述的是这样一个痛点:人们试图将对象耦合以实现控制流,同时假装它们是通过设计解耦的。
总的来说,他的想法与我自己的 OOP 经验产生了共鸣:对象没有问题,但是我一直不满意的是*面向*对象建模程序控制流,并且试图使代码“正确地”面向对象似乎总是在创建不必要的复杂性。
有一件事我认为他无法完全解释。他直截了当地说“封装没有作用”,但在脚注后面加上“在细粒度的代码级别”,并继续承认对象有时可以奏效,并且在库和文件级别封装是可以的。但是他没有确切解释为什么有时会奏效,有时却没有奏效,以及如何和在何处划清界限。有人可能会说这使他的 “OOP 不好”的说法有缺陷,但是我认为他的观点是正确的,并且可以在根本状态和偶发状态之间划清界限。
如果你以前从未听说过“<ruby>根本<rt>essential</rt></ruby>”和“<ruby>偶发<rt>accidental</rt></ruby>”这两个术语的使用,那么你应该阅读 Fred Brooks 的经典文章《[没有银弹][3]》。(顺便说一句,他写了许多很棒的有关构建软件系统的文章。)我以前曾写过[关于根本和偶发的复杂性的文章][4],这里有一个简短的摘要:软件是复杂的。部分原因是因为我们希望软件能够解决混乱的现实世界问题,因此我们将其称为“根本复杂性”。“偶发复杂性”是所有其它的复杂性,因为我们正尝试使用硅和金属来解决与硅和金属无关的问题。例如,对于大多数程序而言,用于内存管理或在内存与磁盘之间传输数据或解析文本格式的代码都是“偶发的复杂性”。
假设你正在构建一个支持多个频道的聊天应用。消息可以随时到达任何频道。有些频道特别有趣,当有新消息传入时,用户希望得到通知。而其他频道静音:消息被存储,但用户不会受到打扰。你需要跟踪每个频道的用户首选设置。
一种实现方法是在频道和频道设置之间使用<ruby>映射<rt>map</rt></ruby>(也称为哈希表、字典或关联数组)。注意,映射是 Brian Will 所说的可以用作对象的抽象数据类型ADT
如果我们有一个调试器并查看内存中的映射对象,我们将看到什么?我们当然会找到频道 ID 和频道设置数据(或至少指向它们的指针)。但是我们还会找到其它数据。如果该映射是使用红黑树实现的,我们将看到带有红/黑标签和指向其他节点的指针的树节点对象。与频道相关的数据是根本状态,而树节点是偶发状态。不过,请注意以下几点:该映射有效地封装了它的偶发状态 —— 你可以用 AVL 树实现的另一个映射替换该映射,并且你的聊天程序仍然可以使用。另一方面,映射没有封装根本状态(仅使用 `get()``set()` 方法访问数据并不是封装)。事实上,映射与根本状态是尽可能不可知的,你可以使用基本相同的映射数据结构来存储与频道或通知无关的其他映射。
这就是映射 ADT 如此成功的原因它封装了偶发状态并与根本状态解耦。如果你思考一下Brian 用封装描述的问题就是尝试封装根本状态。其他描述的好处是封装偶发状态的好处。
要使整个软件系统都达到这一理想状况相当困难,但扩展开来,我认为它看起来像这样:
* 没有全局的可变状态
* 封装了偶发状态(在对象或模块或以其他任何形式)
* 无状态偶发复杂性封装在单独函数中,与数据解耦
* 使用诸如依赖注入之类的技巧使输入和输出变得明确
* 组件可由易于识别的位置完全拥有和控制
其中有些违反了我很久以来的直觉。例如,如果你有一个数据库查询函数,如果数据库连接处理隐藏在该函数内部,并且唯一的参数是查询参数,那么接口会看起来会更简单。但是,当你使用这样的函数构建软件系统时,协调数据库的使用实际上变得更加复杂。组件不仅以自己的方式做事,而且还试图将自己所做的事情隐藏为“实现细节”。数据库查询需要数据库连接这一事实从来都不是实现细节。如果无法隐藏某些内容,那么显露它是更合理的。
我对将面向对象编程和函数式编程放在对立的两极非常警惕但我认为从函数式编程进入面向对象编程的另一极端是很有趣的OOP 试图封装事物,包括无法封装的根本复杂性,而纯函数式编程往往会使事情变得明确,包括一些偶发复杂性。在大多数时候,这没什么问题,但有时候(比如[在纯函数式语言中构建自我指称的数据结构][5])设计更多的是为了函数编程,而不是为了简便(这就是为什么 [Haskell 包含了一些“<ruby>逃生出口<rt>escape hatches</rt></ruby>”][6])。我之前写过一篇[所谓“<ruby>弱纯性<rt>weak purity</rt></ruby>”的中间立场][7]。
Brian 发现封装对更大规模有效,原因有几个。一个是,由于大小的原因,较大的组件更可能包含偶发状态。另一个是“偶发”与你要解决的问题有关。从聊天程序用户的角度来看,“偶发的复杂性”是与消息、频道和用户等无关的任何事物。但是,当你将问题分解为子问题时,更多的事情就变得“根本”。例如,在解决“构建聊天应用”问题时,可以说频道名称和频道 ID 之间的映射是偶发的复杂性,而在解决“实现 `getChannelIdByName()` 函数”子问题时,这是根本复杂性。因此,封装对于子组件的作用比对父组件的作用要小。
顺便说一句在视频的结尾Brian Will 想知道是否有任何语言支持*无法*访问它们所作用的范围的匿名函数。[D][8] 语言可以。 D 中的匿名 Lambda 通常是闭包,但是如果你想要的话,也可以声明匿名无状态函数:
```
import std.stdio;
void main()
{
int x = 41;
// Value from immediately executed lambda
auto v1 = () {
return x + 1;
}();
writeln(v1);
// Same thing
auto v2 = delegate() {
return x + 1;
}();
writeln(v2);
// Plain functions aren't closures
auto v3 = function() {
// Can't access x
// Can't access any mutable global state either if also marked pure
return 42;
}();
writeln(v3);
}
```
--------------------------------------------------------------------------------
via: https://theartofmachinery.com/2019/10/13/oop_and_essential_state.html
作者:[Simon Arneaud][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://theartofmachinery.com
[b]: https://github.com/lujun9972
[1]: https://medium.com/@brianwill/object-oriented-programming-a-personal-disaster-1b044c2383ab
[2]: https://www.youtube.com/watch?v=QM1iUe6IofM
[3]: http://www.cs.nott.ac.uk/~pszcah/G51ISS/Documents/NoSilverBullet.html
[4]: https://theartofmachinery.com/2017/06/25/compression_complexity_and_software.html
[5]: https://wiki.haskell.org/Tying_the_Knot
[6]: https://en.wikibooks.org/wiki/Haskell/Mutable_objects#The_ST_monad
[7]: https://theartofmachinery.com/2016/03/28/dirtying_pure_functions_can_be_useful.html
[8]: https://dlang.org

View File

@@ -0,0 +1,79 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11476-1.html)
[#]: subject: (Use sshuttle to build a poor mans VPN)
[#]: via: (https://fedoramagazine.org/use-sshuttle-to-build-a-poor-mans-vpn/)
[#]: author: (Paul W. Frields https://fedoramagazine.org/author/pfrields/)
使用 shuttle 构建一个穷人的虚拟专网
======
![][1]
如今,企业网络经常使用“虚拟专用网络”[来保证员工通信安全][2]。但是,使用的协议有时会降低性能。如果你可以使用 SSH 连接远程主机,那么你可以设置端口转发。但这可能会很痛苦,尤其是在你需要与该网络上的许多主机一起使用的情况下。试试 `sshuttle`,它可以通过 SSH 访问来设置快速简易的虚拟专网。请继续阅读以获取有关如何使用它的更多信息。
`sshuttle` 正是针对上述情况而设计的。远程端的唯一要求是主机必须有可用的 Python。这是因为 `sshuttle` 会构造并运行一些 Python 代码来帮助传输数据。
### 安装 sshuttle
`sshuttle` 被打包在官方仓库中,因此很容易安装。打开一个终端,并[使用 sudo][3] 来运行以下命令:
```
$ sudo dnf install sshuttle
```
安装后,你可以在手机页中找到相关信息:
```
$ man sshuttle
```
### 设置虚拟专网
最简单的情况就是将所有流量转发到远程网络。这不一定是一个疯狂的想法,尤其是如果你不在自己家里这样的受信任的本地网络中。将 `-r` 选项与 SSH 用户名和远程主机名一起使用:
```
$ sshuttle -r username@remotehost 0.0.0.0/0
```
但是,你可能希望将该虚拟专网限制为特定子网,而不是所有网络流量。(有关子网的完整讨论超出了本文的范围,但是你可以在[维基百科][4]上阅读更多内容。)假设你的办公室内部使用了预留的 A 类子网 10.0.0.0 和预留的 B 类子网 172.16.0.0。上面的命令变为:
```
$ sshuttle -r username@remotehost 10.0.0.0/8 172.16.0.0/16
```
这非常适合通过 IP 地址访问远程网络的主机。但是,如果你的办公室是一个拥有大量主机的大型网络,该怎么办?名称可能更方便,甚至是必须的。不用担心,`sshuttle` 还可以使用 `dns` 选项转发 DNS 查询:
```
$ sshuttle --dns -r username@remotehost 10.0.0.0/8 172.16.0.0/16
```
要使 `sshuttle` 以守护进程方式运行,请加上 `-D` 选项。它会以 syslog 兼容的日志格式发送到 systemd 日志中。
根据本地和远程系统的功能,可以将 `sshuttle` 用于基于 IPv6 的虚拟专网。如果需要,你还可以设置配置文件并将其与系统启动集成。如果你想阅读更多有关 `sshuttle` 及其工作方式的信息,请[查看官方文档][5]。要查看代码,请[进入 GitHub 页面][6]。
*题图由 [Kurt Cotoaga][7] 拍摄并发表在 [Unsplash][8] 上。*
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/use-sshuttle-to-build-a-poor-mans-vpn/
作者:[Paul W. Frields][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://fedoramagazine.org/author/pfrields/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2019/10/sshuttle-816x345.jpg
[2]: https://en.wikipedia.org/wiki/Virtual_private_network
[3]: https://fedoramagazine.org/howto-use-sudo/
[4]: https://en.wikipedia.org/wiki/Subnetwork
[5]: https://sshuttle.readthedocs.io/en/stable/index.html
[6]: https://github.com/sshuttle/sshuttle
[7]: https://unsplash.com/@kydroon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
[8]: https://unsplash.com/s/photos/shuttle?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText

View File

@@ -0,0 +1,166 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11523-1.html)
[#]: subject: (10 Ways to Customize Your Linux Desktop With GNOME Tweaks Tool)
[#]: via: (https://itsfoss.com/gnome-tweak-tool/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
使用 GNOME 优化工具自定义 Linux 桌面的 10 种方法
======
![][7]
你可以通过多种方法来调整 Ubuntu以自定义其外观和行为。我发现最简单的方法是使用 [GNOME 优化工具][2]。它也被称为 GNOME Tweak 或简单地称为 Tweak优化
在过去的教程中,我已经多次介绍过它。在这里,我列出了你可以使用此工具执行的所有主要优化。
我在这里使用的是 Ubuntu但是这些步骤应该适用于使用 GNOME 桌面环境的任何 Linux 发行版。
### 在 Ubuntu 18.04 或其它版本上安装 GNOME 优化工具
GNOME 优化工具可从 [Ubuntu 中的 Universe 存储库][3]中安装,因此请确保已在“软件和更新”工具中启用了该仓库:
![在 Ubuntu 中启用 Universe 存储库][4]
之后,你可以从软件中心安装 GNOME 优化工具。只需打开软件中心并搜索 “GNOME Tweaks” 并从那里安装它:
![从软件中心安装 GNOME 优化工具][5]
或者,你也可以使用命令行通过 [apt 命令][6]安装此软件:
```
sudo apt install gnome-tweaks
```
### 用优化工具定制 GNOME 桌面
GNOME 优化工具使你可以进行许多设置更改。其中的某些更改(例如墙纸更改、启动应用程序等)也可以在官方的“系统设置”工具中找到。我将重点介绍默认情况下“设置”中不可用的优化。
#### 1、改变主题
你可以通过各种方式[在 Ubuntu 中安装新主题][8]。但是如果要更改为新安装的主题则必须安装GNOME 优化工具。
你可以在“<ruby>外观<rt>Appearance</rt></ruby>”部分找到主题和图标设置。你可以浏览可用的主题和图标并设置你喜欢的主题和图标。更改将立即生效。
![通过 GNOME 优化更改主题][9]
#### 2、禁用动画以提速你的桌面体验
应用程序窗口的打开、关闭、最大化等操作都有一些细微的动画。你可以禁用这些动画以稍微加快系统的速度,因为它会稍微使用一点资源。
![禁用动画以获得稍快的桌面体验][10]
#### 3、控制桌面图标
至少在 Ubuntu 中,你会在桌面上看到“<ruby>家目录<rt>Home</rt></ruby>”和“<ruby>垃圾箱<rt>Trash</rt></ruby>”图标。如果你不喜欢,可以选择禁用它。你还可以选择要在桌面上显示的图标。
![在 Ubuntu 中控制桌面图标][11]
#### 4、管理 GNOME 扩展
我想你可能知道 [GNOME 扩展][12]。这些是用于桌面的小型“插件”,可扩展 GNOME 桌面的功能。有[大量的 GNOME 扩展][13],可用于在顶部面板中查看 CPU 消耗、获取剪贴板历史记录等等。
我已经写了一篇[安装和使用 GNOME 扩展][14]的详细文章。在这里,我假设你已经在使用它们,如果是这样,可以从 GNOME 优化工具中对其进行管理。
![管理 GNOME 扩展][15]
#### 5、改变字体和缩放比例
你可以[在 Ubuntu 中安装新字体][16],并使用这个优化工具在系统范围应用字体更改。如果你认为桌面上的图标和文本太小,也可以更改缩放比例。
![更改字体和缩放比例][17]
#### 6、控制触摸板行为例如在键入时禁用触摸板使触摸板右键单击可以工作
GNOME 优化工具还允许你在键入时禁用触摸板。如果你在笔记本电脑上快速键入,这将很有用。手掌底部可能会触摸触摸板,并导致光标移至屏幕上不需要的位置。
在键入时自动禁用触摸板可解决此问题。
![键入时禁用触摸板][18]
你还会注意到[当你按下触摸板的右下角以进行右键单击时,什么也没有发生][19]。你的触摸板并没有问题。这是一项系统设置,可对没有实体右键按钮的任何触摸板(例如旧的 Thinkpad 笔记本电脑)禁用这种右键单击功能。两指点击可为你提供右键单击操作。
你也可以通过在“<ruby>鼠标单击模拟<rt>Mouse Click Simulation</rt></ruby>”下设置为“<ruby>区域<rt>Area</rt></ruby>”中而不是“<ruby>手指<rt>Fingers</rt></ruby>”来找回这项功能。
![修复右键单击问题][20]
你可能必须[重新启动 Ubuntu][21] 来使这项更改生效。如果你是 Emacs 爱好者,还可以强制使用 Emacs 键盘绑定。
#### 7、改变电源设置
电源这里只有一个设置。它可以让你在盖上盖子后将笔记本电脑置于挂起模式。
![GNOME 优化工具中的电源设置][22]
#### 8、决定什么显示在顶部面板
桌面的顶部面板显示了一些重要的信息。在这里有日历、网络图标、系统设置和“<ruby>活动<rt>Activities</rt></ruby>”选项。
你还可以[显示电池百分比][23]、添加日期及时间,并显示星期数。你还可以启用鼠标热角,以便将鼠标移至屏幕的左上角时可以获得所有正在运行的应用程序的活动视图。
![GNOME 优化工具中的顶部面板设置][24]
如果将鼠标焦点放在应用程序窗口上,你会注意到其菜单显示在顶部面板中。如果你不喜欢这样,可以将其关闭,然后应用程序菜单将显示应用程序本身。
#### 9、配置应用窗口
你可以决定是否在应用程序窗口中显示最大化和最小化选项(右上角的按钮)。你也可以改变它们的位置到左边或右边。
![应用程序窗口配置][25]
这里还有其他一些配置选项。我不使用它们,但你可以自行探索。
#### 10、配置工作区
GNOME 优化工具还允许你围绕工作区配置一些内容。
![在 Ubuntu 中配置工作区][26]
### 总结
对于任何 GNOME 用户GNOME 优化Tweaks工具都是必备工具。它可以帮助你配置桌面的外观和功能。 我感到惊讶的是,该工具甚至没有出现在 Ubuntu 的主存储库中。我认为应该默认安装它,要不,你就得在 Ubuntu 中手动安装 GNOME 优化工具。
如果你在 GNOME 优化工具中发现了一些此处没有讨论的隐藏技巧,为什么不与大家分享呢?
--------------------------------------------------------------------------------
via: https://itsfoss.com/gnome-tweak-tool/
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/gnome-tweak-tool-icon.png?ssl=1
[2]: https://wiki.gnome.org/action/show/Apps/Tweaks?action=show&redirect=Apps%2FGnomeTweakTool
[3]: https://itsfoss.com/ubuntu-repositories/
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/03/enable-repositories-ubuntu.png?ssl=1
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/install-gnome-tweaks-tool.jpg?ssl=1
[6]: https://itsfoss.com/apt-command-guide/
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/customize-gnome-with-tweak-tool.jpg?ssl=1
[8]: https://itsfoss.com/install-themes-ubuntu/
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/change-theme-ubuntu-gnome.jpg?ssl=1
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/disable-animation-ubuntu-gnome.jpg?ssl=1
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/desktop-icons-ubuntu.jpg?ssl=1
[12]: https://extensions.gnome.org/
[13]: https://itsfoss.com/best-gnome-extensions/
[14]: https://itsfoss.com/gnome-shell-extensions/
[15]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/manage-gnome-extension-tweaks-tool.jpg?ssl=1
[16]: https://itsfoss.com/install-fonts-ubuntu/
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/change-fonts-ubuntu-gnome.jpg?ssl=1
[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/disable-touchpad-while-typing-ubuntu.jpg?ssl=1
[19]: https://itsfoss.com/fix-right-click-touchpad-ubuntu/
[20]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/enable-right-click-ubuntu.jpg?ssl=1
[21]: https://itsfoss.com/schedule-shutdown-ubuntu/
[22]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/power-settings-gnome-tweaks-tool.jpg?ssl=1
[23]: https://itsfoss.com/display-battery-ubuntu/
[24]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/top-panel-settings-gnome-tweaks-tool.jpg?ssl=1
[25]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/windows-configuration-ubuntu-gnome-tweaks.jpg?ssl=1
[26]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/configure-workspaces-ubuntu.jpg?ssl=1

View File

@@ -1,16 +1,16 @@
[#]: collector: (lujun9972)
[#]: translator: (algzjh)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11474-1.html)
[#]: subject: (4 Free and Open Source Alternatives to Adobe Photoshop)
[#]: via: (https://itsfoss.com/open-source-photoshop-alternatives/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
Adobe Photoshop 的 4 种免费开源替代品
Adobe Photoshop 的 4 种自由开源替代品
======
_**想寻找免费的 Photoshop 替代品? 这里有一些最好的免费开源软件,你可以用它们来代替 Adobe Photoshop。**_
> 想寻找免费的 Photoshop 替代品?这里有一些最好的自由开源软件,你可以用它们来代替 Adobe Photoshop。
Adobe Photoshop 是一个可用于 Windows 和 macOS 的高级图像编辑和设计工具。毫无疑问,几乎每个人都知道它。其十分受欢迎。在 Linux 上,你可以在虚拟机中使用 Windows 或[通过 Wine][1] 来使用 Photoshop但这并不是一种理想的体验。
@@ -18,40 +18,38 @@ Adobe Photoshop 是一个可用于 Windows 和 macOS 的高级图像编辑和设
请注意 Photoshop 不仅仅是一个图片编辑器。摄影师、数码艺术家、专业编辑使用它用于各种用途。此处的替代软件可能不具备 Photoshop 的所有功能,但你可以将它们用于在 Photoshop 中完成的各种任务。
### 适用于 Linux, Windows 和 macOS 的 Adobe Photoshop 的开源替代品
### 适用于 LinuxWindows 和 macOS 的 Adobe Photoshop 的开源替代品
![][2]
最初,我想只关注 Linux 中的 Photoshop 替代品,但为什么要把这个列表局限于 Linux 呢?其他操作系统用户也可使用开源软件。
_**如果你正在使用 Linux则所有提到的软件都应该可以在你的发行版的存储库中找到。你可以使用软件中心或包管理器进行安装。**_
**如果你正在使用 Linux则所有提到的软件都应该可以在你的发行版的存储库中找到。你可以使用软件中心或包管理器进行安装。**
对于其他平台,请查看官方项目网站以获取安装文件。
_该列表没有特定的排名顺序_.
*该列表没有特定的排名顺序*
#### 1\. GIMP: 真正的 Photoshop 替代品
#### 1GIMP真正的 Photoshop 替代品
![][3]
主要特点:
* 可定制的界面
* 数字修饰
* 数字修饰
* 照片增强(使用变换工具)
* 支持广泛的硬件(压敏平板、音乐数字接口等)
* 几乎支持所有主要的图像文件
* 支持图层管理
**可用平台:** Linux, Windows 和 macOS
可用平台Linux、Windows 和 macOS
[GIMP][4] 是我处理任何事情的必备工具,无论任务多么基础/高级。也许,这是你在 Linux 下最接近 Photoshop 的替代品。除此之外,它还是一个开源和免费的解决方案,适合希望在 Linux 上创作伟大作品的艺术家。
它具有任何类型的图像处理所必需的所有功能。当然,还有图层管理支持。根据你的经验水平,利用率会有所不同。因此,如果你想充分利用它,则应阅读 [文档][5] 并遵循 [官方教程][6].
它具有任何类型的图像处理所必需的所有功能。当然,还有图层管理支持。根据你的经验水平,利用率会有所不同。因此,如果你想充分利用它,则应阅读 [文档][5] 并遵循 [官方教程][6]
#### 2\. Krita
#### 2Krita
![][7]
@@ -61,15 +59,13 @@ _该列表没有特定的排名顺序_.
* 转换工具
* 丰富的笔刷/绘图工具
可用平台Linux、Windows 和 macOS
**可用平台:** Linux, Windows 和 macOS
[Krita][8] 是一个令人印象深刻的数字绘画开源工具。图层管理支持和转换工具的存在使它成为 Photoshop 的基本编辑任务的替代品之一。
[Krita][8] 是一个令人印象深刻的开源的数字绘画工具。图层管理支持和转换工具的存在使它成为 Photoshop 的基本编辑任务的替代品之一。
如果你喜欢素描/绘图,这将对你很有帮助。
#### 3\. Darktable
#### 3Darktable
![][9]
@@ -79,15 +75,13 @@ _该列表没有特定的排名顺序_.
* 支持多种图像格式
* 多个带有混合运算符的图像操作模块
**可用平台:** Linux, Windows 和 macOS
可用平台Linux、Windows 和 macOS
[Darktable][10] 是一个由摄影师制作的开源摄影工作流应用程序。它可以让你在数据库中管理你的数码底片。从你的收藏中,显影 RAW 格式的图像并使用可用的工具对其进行增强。
从基本的图像编辑工具到支持混合运算符的多个图像模块,你将在探索中发现许多。
#### 4\. Inkscape
#### 4Inkscape
![][11]
@@ -96,18 +90,16 @@ _该列表没有特定的排名顺序_.
* 创建对象的工具(最适合绘图/素描)
* 支持图层管理
* 用于图像处理的转换工具
* 颜色选择器RGBHSLCMYK色轮CMS
* 颜色选择器RGBHSLCMYK色轮CMS
* 支持所有主要文件格式
可用平台Linux、Windows 和 macOS
**可用平台:** Linux, Windows 和 macOS
[Inkscape][12] 是一个非常流行的开源矢量图形编辑器,许多专业人士都使用它。它提供了灵活的设计工具,可帮助你创建/操作漂亮的艺术作品。从技术上说,它是 Adobe Illustrator 的直接替代品,但它也提供了一些技巧,可以帮助你将其作为 Photoshop 的替代品。
[Inkscape][12] 是一个非常流行的开源矢量图形编辑器,许多专业人士都使用它。它提供了灵活的设计工具,可帮助你创作漂亮的艺术作品。从技术上说,它是 Adobe Illustrator 的直接替代品,但它也提供了一些技巧,可以帮助你将其作为 Photoshop 的替代品。
与 GIMP 的官方资源类似,你可以利用 [Inkscape 的教程][13] 来最大程度地利用它。
**在你看来,真正的 Photoshop 替代品是什么?**
### 在你看来,真正的 Photoshop 替代品是什么?
很难提供与 Adobe Photoshop 完全相同的功能。然而,如果你遵循官方文档和资源,则可以使用上述 Photoshop 替代品做很多很棒的事情。
@@ -122,7 +114,7 @@ via: https://itsfoss.com/open-source-photoshop-alternatives/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[algzjh](https://github.com/algzjh)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@@ -1,38 +1,30 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11490-1.html)
[#]: subject: (Bash Script to Delete Files/Folders Older Than “X” Days in Linux)
[#]: via: (https://www.2daygeek.com/bash-script-to-delete-files-folders-older-than-x-days-in-linux/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
Bash Script to Delete Files/Folders Older Than “X” Days in Linux
在 Linux 中使用 Bash 脚本删除早于 “X” 天的文件/文件夹
======
**[Disk Usage][1]** Monitoring tools are capable of alerting us when a given threshold is reached.
[磁盘使用率][1] 监控工具能够在达到给定阈值时提醒我们。但它们无法自行解决 [磁盘使用率][2] 问题。需要手动干预才能解决该问题。
But they dont have the ingenuity to fix the **[disk usage][2]** problem on their own.
如果你想完全自动化此类操作,你会做什么。是的,可以使用 bash 脚本来完成。
Manual intervention is needed to solve the problem.
该脚本可防止来自 [监控工具][3] 的警报,因为我们会在填满磁盘空间之前删除旧的日志文件。
But if you want to fully automate this kind of activity, what you will do.
我们过去做了很多 shell 脚本。如果要查看,请进入下面的链接。
Yes, it can be done using the bash script.
* [如何使用 shell 脚本自动化日常活动?][4]
This script prevents alerts from **[monitoring tool][3]** because we delete old log files before filling the disk space.
我在本文中添加了两个 bash 脚本,它们有助于清除旧日志。
We have added many useful shell scripts in the past. If you want to check them out, go to the link below.
### 1在 Linux 中删除早于 “X” 天的文件夹的 Bash 脚本
* **[How to automate day to day activities using shell scripts?][4]**
Ive added two bash scripts to this article, which helps clear up old logs.
### 1) Bash Script to Delete a Folders Older Than “X” Days in Linux
We have a folder named **“/var/log/app/”** that contains 15 days of logs and we are going to delete 10 days old folders.
我们有一个名为 `/var/log/app/` 的文件夹,其中包含 15 天的日志,我们将删除早于 10 天的文件夹。
```
$ ls -lh /var/log/app/
@@ -54,9 +46,9 @@ drwxrw-rw- 3 root root 24K Oct 14 23:52 app_log.14
drwxrw-rw- 3 root root 24K Oct 15 23:52 app_log.15
```
This script will delete 10 days old folders and send folder list via mail.
该脚本将删除早于 10 天的文件夹,并通过邮件发送文件夹列表。
You can change the value **“-mtime X”** depending on your requirement. Also, replace your email id instead of us.
你可以根据需要修改 `-mtime X` 的值。另外,请替换你的电子邮箱,而不是用我们的。
```
# /opt/script/delete-old-folders.sh
@@ -81,13 +73,13 @@ rm $MESSAGE /tmp/folder.out
fi
```
Set an executable permission to **delete-old-folders.sh”** file.
`delete-old-folders.sh` 设置可执行权限。
```
# chmod +x /opt/script/delete-old-folders.sh
```
Finally add a **[cronjob][5]** to automate this. It runs daily at 7AM.
最后添加一个 [cronjob][5] 自动化此任务。它于每天早上 7 点运行。
```
# crontab -e
@@ -95,7 +87,7 @@ Finally add a **[cronjob][5]** to automate this. It runs daily at 7AM.
0 7 * * * /bin/bash /opt/script/delete-old-folders.sh
```
You will get an output like the one below.
你将看到类似下面的输出。
```
Application log folders are deleted older than 20 days
@@ -107,17 +99,15 @@ Oct 14 /var/log/app/app_log.14
Oct 15 /var/log/app/app_log.15
```
### 2) Bash Script to Delete a Files Older Than “X” Days in Linux
### 2)在 Linux 中删除早于 “X” 天的文件的 Bash 脚本
We have a folder named **“/var/log/apache/”** that contains 15 days of logs and we are going to delete 10 days old files.
The articles below are related to this topic, so you may be interested to read.
* **[How To Find And Delete Files Older Than “X” Days And “X” Hours In Linux?][6]**
* **[How to Find Recently Modified Files/Folders in Linux][7]**
* **[How To Automatically Delete Or Clean Up /tmp Folder Contents In Linux?][8]**
我们有一个名为 `/var/log/apache/` 的文件夹其中包含15天的日志我们将删除 10 天前的文件。
以下文章与该主题相关,因此你可能有兴趣阅读。
* [如何在 Linux 中查找和删除早于 “X” 天和 “X” 小时的文件?][6]
* [如何在 Linux 中查找最近修改的文件/文件夹][7]
* [如何在 Linux 中自动删除或清理 /tmp 文件夹内容?][8]
```
# ls -lh /var/log/apache/
@@ -139,9 +129,9 @@ The articles below are related to this topic, so you may be interested to read.
-rw-rw-rw- 3 root root 24K Oct 15 23:52 2daygeek_access.15
```
This script will delete 10 days old files and send folder list via mail.
该脚本将删除 10 天前的文件并通过邮件发送文件夹列表。
You can change the value **“-mtime X”** depending on your requirement. Also, replace your email id instead of us.
你可以根据需要修改 `-mtime X` 的值。另外,请替换你的电子邮箱,而不是用我们的。
```
# /opt/script/delete-old-files.sh
@@ -166,13 +156,13 @@ rm $MESSAGE /tmp/file.out
fi
```
Set an executable permission to **delete-old-files.sh”** file.
`delete-old-files.sh` 设置可执行权限。
```
# chmod +x /opt/script/delete-old-files.sh
```
Finally add a **[cronjob][5]** to automate this. It runs daily at 7AM.
最后添加一个 [cronjob][5] 自动化此任务。它于每天早上 7 点运行。
```
# crontab -e
@@ -180,7 +170,7 @@ Finally add a **[cronjob][5]** to automate this. It runs daily at 7AM.
0 7 * * * /bin/bash /opt/script/delete-old-folders.sh
```
You will get an output like the one below.
你将看到类似下面的输出。
```
Apache Access log files are deleted older than 20 days
@@ -198,8 +188,8 @@ via: https://www.2daygeek.com/bash-script-to-delete-files-folders-older-than-x-d
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@@ -0,0 +1,79 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11495-1.html)
[#]: subject: (Linux sudo flaw can lead to unauthorized privileges)
[#]: via: (https://www.networkworld.com/article/3446036/linux-sudo-flaw-can-lead-to-unauthorized-privileges.html)
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
Linux sudo 漏洞可能导致未经授权的特权访问
======
![](https://img.linux.net.cn/data/attachment/album/201910/23/173934huyi6siys2u33w9z.png)
> 在 Linux 中利用新发现的 sudo 漏洞可以使某些用户以 root 身份运行命令,尽管对此还有所限制。
[sudo][1] 命令中最近发现了一个严重漏洞,如果被利用,普通用户可以 root 身份运行命令,即使在 `/etc/sudoers` 文件中明确禁止了该用户这样做。
`sudo` 更新到版本 1.8.28 应该可以解决该问题,因此建议 Linux 管理员尽快这样做。
如何利用此漏洞取决于 `/etc/sudoers` 中授予的特定权限。例如,一条规则允许用户以除了 root 用户之外的任何用户身份来编辑文件,这实际上将允许该用户也以 root 用户身份来编辑文件。在这种情况下,该漏洞可能会导致非常严重的问题。
用户要能够利用此漏洞,需要在 `/etc/sudoers` 中为**用户**分配特权,以使该用户可以以其他用户身份运行命令,并且该漏洞仅限于以这种方式分配的命令特权。
此问题影响 1.8.28 之前的版本。要检查你的 `sudo` 版本,请使用以下命令:
```
$ sudo -V
Sudo version 1.8.27 <===
Sudoers policy plugin version 1.8.27
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.27
```
该漏洞已在 CVE 数据库中分配了编号 [CVE-2019-14287][4]。它的风险是,任何被指定能以任意用户运行某个命令的用户,即使被明确禁止以 root 身份运行,它都能逃脱限制。
下面这些行让 `jdoe` 能够以除了 root 用户之外的其他身份使用 `vi` 编辑文件(`!root` 表示“非 root”同时 `nemo` 有权运行以除了 root 身份以外的任何用户使用 `id` 命令:
```
# affected entries on host "dragonfly"
jdoe dragonfly = (ALL, !root) /usr/bin/vi
nemo dragonfly = (ALL, !root) /usr/bin/id
```
但是,由于存在漏洞,这些用户中要么能够绕过限制并以 root 编辑文件,或者以 root 用户身份运行 `id` 命令。
攻击者可以通过指定用户 ID 为 `-1``4294967295` 来以 root 身份运行命令。
```
sudo -u#-1 id -u
```
或者
```
sudo -u#4294967295 id -u
```
响应为 `1` 表明该命令以 root 身份运行(显示 root 的用户 ID
苹果信息安全团队的 Joe Vennix 找到并分析该问题。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3446036/linux-sudo-flaw-can-lead-to-unauthorized-privileges.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.networkworld.com/article/3236499/some-tricks-for-using-sudo.html
[4]: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-14287
[5]: https://www.facebook.com/NetworkWorld/
[6]: https://www.linkedin.com/company/network-world

View File

@@ -0,0 +1,207 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11505-1.html)
[#]: subject: (How to Configure Rsyslog Server in CentOS 8 / RHEL 8)
[#]: via: (https://www.linuxtechi.com/configure-rsyslog-server-centos-8-rhel-8/)
[#]: author: (James Kiarie https://www.linuxtechi.com/author/james/)
如何在 CentOS8/RHEL8 中配置 Rsyslog 服务器
======
![](https://img.linux.net.cn/data/attachment/album/201910/27/062908v4nnzgf7bhnplgvg.jpg)
Rsyslog 是一个自由开源的日志记录程序,在 CentOS 8 和 RHEL 8 系统上默认可用。它提供了一种从客户端节点到单个中央服务器的“集中日志”的简单有效的方法。日志集中化有两个好处。首先,它简化了日志查看,因为系统管理员可以在一个中心节点查看远程服务器的所有日志,而无需登录每个客户端系统来检查日志。如果需要监视多台服务器,这将非常有用,其次,如果远程客户端崩溃,你不用担心丢失日志,因为所有日志都将保存在中心的 Rsyslog 服务器上。rsyslog 取代了仅支持 UDP 协议的 syslog。它以优异的功能扩展了基本的 syslog 协议,例如在传输日志时支持 UDP 和 TCP 协议,增强的过滤功能以及灵活的配置选项。让我们来探讨如何在 CentOS 8 / RHEL 8 系统中配置 Rsyslog 服务器。
![configure-rsyslog-centos8-rhel8][2]
### 预先条件
我们将搭建以下实验环境来测试集中式日志记录过程:
* Rsyslog 服务器       CentOS 8 Minimal    IP 地址: 10.128.0.47
* 客户端系统          RHEL 8 Minimal      IP 地址: 10.128.0.48
通过上面的设置,我们将演示如何设置 Rsyslog 服务器,然后配置客户端系统以将日志发送到 Rsyslog 服务器进行监视。
让我们开始!
### 在 CentOS 8 上配置 Rsyslog 服务器
默认情况下Rsyslog 已安装在 CentOS 8 / RHEL 8 服务器上。要验证 Rsyslog 的状态,请通过 SSH 登录并运行以下命令:
```
$ systemctl status rsyslog
```
示例输出:
![rsyslog-service-status-centos8](https://www.linuxtechi.com/wp-content/uploads/2019/10/rsyslog-service-status-centos8.jpg)
如果由于某种原因 Rsyslog 不存在,那么可以使用以下命令进行安装:
```
$ sudo yum install rsyslog
```
接下来,你需要修改 Rsyslog 配置文件中的一些设置。打开配置文件:
```
$ sudo vim /etc/rsyslog.conf
```
滚动并取消注释下面的行,以允许通过 UDP 协议接收日志:
```
module(load="imudp") # needs to be done just once
input(type="imudp" port="514")
```
![rsyslog-conf-centos8-rhel8](https://www.linuxtechi.com/wp-content/uploads/2019/10/rsyslog-conf-centos8-rhel8.jpg)
同样,如果你希望启用 TCP rsyslog 接收,请取消注释下面的行:
```
module(load="imtcp") # needs to be done just once
input(type="imtcp" port="514")
```
![rsyslog-conf-tcp-centos8-rhel8](https://www.linuxtechi.com/wp-content/uploads/2019/10/rsyslog-conf-tcp-centos8-rhel8.jpg)
保存并退出配置文件。
要从客户端系统接收日志,我们需要在防火墙上打开 Rsyslog 默认端口 514。为此请运行
```
# sudo firewall-cmd --add-port=514/tcp --zone=public --permanent
```
接下来,重新加载防火墙保存更改:
```
# sudo firewall-cmd --reload
```
示例输出:
![firewall-ports-rsyslog-centos8](https://www.linuxtechi.com/wp-content/uploads/2019/10/firewall-ports-rsyslog-centos8.jpg)
接下来,重启 Rsyslog 服务器:
```
$ sudo systemctl restart rsyslog
```
要在启动时运行 Rsyslog运行以下命令
```
$ sudo systemctl enable rsyslog
```
要确认 Rsyslog 服务器正在监听 514 端口,请使用 `netstat` 命令,如下所示:
```
$ sudo netstat -pnltu
```
示例输出:
![netstat-rsyslog-port-centos8](https://www.linuxtechi.com/wp-content/uploads/2019/10/netstat-rsyslog-port-centos8.jpg)
完美!我们已经成功配置了 Rsyslog 服务器来从客户端系统接收日志。
要实时查看日志消息,请运行以下命令:
```
$ tail -f /var/log/messages
```
现在开始配置客户端系统。
### 在 RHEL 8 上配置客户端系统
与 Rsyslog 服务器一样,登录并通过以下命令检查 rsyslog 守护进程是否正在运行:
```
$ sudo systemctl status rsyslog
```
示例输出:
![client-rsyslog-service-rhel8](https://www.linuxtechi.com/wp-content/uploads/2019/10/client-rsyslog-service-rhel8.jpg)
接下来,打开 rsyslog 配置文件:
```
$ sudo vim /etc/rsyslog.conf
```
在文件末尾,添加以下行:
```
*.* @10.128.0.47:514 # Use @ for UDP protocol
*.* @@10.128.0.47:514 # Use @@ for TCP protocol
```
保存并退出配置文件。就像 Rsyslog 服务器一样,打开 514 端口,这是防火墙上的默认 Rsyslog 端口:
```
$ sudo firewall-cmd --add-port=514/tcp --zone=public --permanent
```
接下来,重新加载防火墙以保存更改:
```
$ sudo firewall-cmd --reload
```
接下来,重启 rsyslog 服务:
```
$ sudo systemctl restart rsyslog
```
要在启动时运行 Rsyslog请运行以下命令
```
$ sudo systemctl enable rsyslog
```
### 测试日志记录操作
已经成功安装并配置 Rsyslog 服务器和客户端后,就该验证你的配置是否按预期运行了。
在客户端系统上,运行以下命令:
```
# logger "Hello guys! This is our first log"
```
现在进入 Rsyslog 服务器并运行以下命令来实时查看日志消息:
```
# tail -f /var/log/messages
```
客户端系统上命令运行的输出显示在了 Rsyslog 服务器的日志中,这意味着 Rsyslog 服务器正在接收来自客户端系统的日志:
![centralize-logs-rsyslogs-centos8](https://www.linuxtechi.com/wp-content/uploads/2019/10/centralize-logs-rsyslogs-centos8.jpg)
就是这些了!我们成功设置了 Rsyslog 服务器来接收来自客户端系统的日志信息。
--------------------------------------------------------------------------------
via: https://www.linuxtechi.com/configure-rsyslog-server-centos-8-rhel-8/
作者:[James Kiarie][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.linuxtechi.com/author/james/
[b]: https://github.com/lujun9972
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/configure-rsyslog-centos8-rhel8.jpg

View File

@@ -0,0 +1,82 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11497-1.html)
[#]: subject: (Kubernetes networking, OpenStack Train, and more industry trends)
[#]: via: (https://opensource.com/article/19/10/kubernetes-openstack-and-more-industry-trends)
[#]: author: (Tim Hildred https://opensource.com/users/thildred)
每周开源点评Kubernetes 网络、OpenStack Train 以及更多的行业趋势
======
> 开源社区和行业趋势的每周总览。
![Person standing in front of a giant computer screen with numbers, data][1]
作为我在具有开源开发模型的企业软件公司担任高级产品营销经理的角色的一部分,我为产品营销人员、经理和其他影响者定期发布有关开源社区,市场和行业趋势的定期更新。以下是该更新中我和他们最喜欢的五篇文章。
### OpenStack Train 中最令人兴奋的功能
- [文章地址][2]
> 考虑到 Train 版本必须提供的所有技术优势([你可以在此处查看版本亮点][3]),你可能会对 Red Hat 认为这些将使我们的电信和企业客户受益的顶级功能及其用例感到好奇。以下我们对该版本最兴奋的功能的概述。
**影响**OpenStack 对我来说就像 Shia LaBeouf它在几年前达到了炒作的顶峰然后继续产出了好的作品。Train 版本看起来是又一次令人难以置信的创新下降。
### 以 Ansible 原生的方式构建 Kubernetes 操作器
- [文章地址][4]
> 操作器简化了 Kubernetes 上复杂应用程序的管理。它们通常是用 Go 语言编写的,并且需要懂得 Kubernetes 内部的专业知识。但是还有另一种进入门槛较低的选择。Ansible 是操作器 SDK 中的一等公民。使用 Ansible 可以释放应用程序工程师的精力,最大限度地利用时间来自动化和协调你的应用程序,并使用一种简单的语言在新的和现有的平台上进行操作。在这里我们可以看到如何做。
**影响**这就像你发现可以用搅拌器和冷冻香蕉制作出不错的冰淇淋一样Ansible通常被认为很容易掌握可以使你比你想象的更容易地做一些令人印象深刻的操作器魔术。
### Kubernetes 网络:幕后花絮
- [文章地址][5]
> 尽管围绕该主题有很多很好的资源(链接在[这里][6]),但我找不到一个示例,可以将所有的点与网络工程师喜欢和讨厌的命令输出连接起来,以显示背后实际发生的情况。因此,我决定从许多不同的来源收集这些信息,以期帮助你更好地了解事物之间的联系。
**影响**:这是一篇对复杂主题(带有图片)阐述的很好的作品。保证可以使 Kubenetes 网络的混乱程度降低 10
### 保护容器供应链
- [文章地址][7]
> 随着容器、软件即服务和函数即服务的出现,人们开始着眼于在使用现有服务、函数和容器映像的过程中寻求新的价值。[Red Hat][8] 的容器首席产品经理 Scott McCarty 表示关注这个重点既有优点也有缺点。“它使我们能够集中精力编写满足我们需求的新应用程序代码同时将对基础架构的关注转移给其他人身上”McCarty 说,“容器处于一个最佳位置,提供了足够的控制,而卸去了许多繁琐的基础架构工作。”但是,容器也会带来与安全性相关的劣势。
**影响**:我在一个由大约十位安全人员组成的小组中,可以肯定地说,整天要考虑软件安全性需要一定的倾向。当你长时间凝视深渊时,它也凝视着你。如果你不是如此倾向的软件开发人员,请听取 Scott 的建议并确保你的供应商考虑安全。
### 15 岁的 Fedora为何 Matthew Miller 看到 Linux 发行版的光明前景
- [文章链接][9]
> 在 TechRepublic 的一个大范围采访中Fedora 项目负责人 Matthew Miller 讨论了过去的经验教训、软件容器的普遍采用和竞争性标准、Fedora 的潜在变化以及包括 systemd 在内的热门话题。
**影响**:我喜欢 Fedora 项目的原因是它的清晰度;该项目知道它代表什么。像 Matt 这样的人就是为什么能看到光明前景的原因。
*我希望你喜欢这张上周让我印象深刻的列表,并在下周一回来了解更多的开放源码社区、市场和行业趋势。*
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/kubernetes-openstack-and-more-industry-trends
作者:[Tim Hildred][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/thildred
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data)
[2]: https://www.redhat.com/en/blog/look-most-exciting-features-openstack-train
[3]: https://releases.openstack.org/train/highlights.html
[4]: https://www.cncf.io/webinars/building-kubernetes-operators-in-an-ansible-native-way/
[5]: https://itnext.io/kubernetes-networking-behind-the-scenes-39a1ab1792bb
[6]: https://github.com/nleiva/kubernetes-networking-links
[7]: https://www.devprojournal.com/technology-trends/open-source/securing-the-container-supply-chain/
[8]: https://www.redhat.com/en
[9]: https://www.techrepublic.com/article/fedora-at-15-why-matthew-miller-sees-a-bright-future-for-the-linux-distribution/

View File

@@ -0,0 +1,93 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11502-1.html)
[#]: subject: (Pylint: Making your Python code consistent)
[#]: via: (https://opensource.com/article/19/10/python-pylint-introduction)
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
Pylint让你的 Python 代码保持一致
======
> 当你想要争论代码复杂性时Pylint 是你的朋友。
![OpenStack source code \(Python\) in VIM][1]
Pylint 是更高层级的 Python 样式强制程序。而 [flake8][2] 和 [black][3] 检查的是“本地”样式:换行位置、注释的格式、发现注释掉的代码或日志格式中的错误做法之类的问题。
默认情况下Pylint 非常激进。它将对每样东西都提供严厉的意见,从检查是否实际实现声明的接口到重构重复代码的可能性,这对新用户来说可能会很多。一种温和地将其引入项目或团队的方法是先关闭*所有*检查器,然后逐个启用检查器。如果你已经在使用 flake8、black 和 [mypy][4]这尤其有用Pylint 有相当多的检查器和它们在功能上重叠。
但是Pylint 独有之处之一是能够强制执行更高级别的问题:例如,函数的行数或者类中方法的数量。
这些数字可能因项目而异,并且可能取决于开发团队的偏好。但是,一旦团队就参数达成一致,使用自动工具*强制化*这些参数非常有用。这是 Pylint 闪耀的地方。
### 配置 Pylint
要以空配置开始,请将 `.pylintrc` 设置为
```
[MESSAGES CONTROL]
disable=all
```
这将禁用所有 Pylint 消息。由于其中许多是冗余的,这是有道理的。在 Pylint 中,`message` 是一种特定的警告。
你可以通过运行 `pylint` 来确认所有消息都已关闭:
```
$ pylint <my package>
```
通常,向 `pylint` 命令行添加参数并不是一个好主意:配置 `pylint` 的最佳位置是 `.pylintrc`。为了使它做*一些*有用的事,我们需要启用一些消息。
要启用消息,在 `.pylintrc` 中的 `[MESSAGES CONTROL]` 下添加
```
enable=<message>,
...
```
对于看起来有用的“消息”Pylint 称之为不同类型的警告)。我最喜欢的包括 `too-many-lines``too-many-arguments``too-many-branches`。所有这些会限制模块或函数的复杂性,并且无需进行人工操作即可客观地进行代码复杂度测量。
*检查器*是*消息*的来源:每条消息只属于一个检查器。许多最有用的消息都在[设计检查器][5]下。默认数字通常都不错,但要调整最大值也很简单:我们可以在 `.pylintrc` 中添加一个名为 `DESIGN` 的段。
```
[DESIGN]
max-args=7
max-locals=15
```
另一个有用的消息来源是“重构”检查器。我已启用一些最喜欢的消息有 `consider-using-dict-comprehension``stop-iteration-return`(它会查找正确的停止迭代的方式是 `return` 而使用了 `raise StopIteration` 的迭代器)和 `chained-comparison`,它将建议使用如 `1 <= x < 5`,而不是不太明显的 `1 <= x && 5 > 5` 的语法。
最后是一个在性能方面消耗很大的检查器,但它非常有用,就是 `similarities`。它会查找不同部分代码之间的复制粘贴来强制执行“不要重复自己”DRY 原则)。它只启用一条消息:`duplicate-code`。默认的 “最小相似行数” 设置为 4。可以使用 `.pylintrc` 将其设置为不同的值。
```
[SIMILARITIES]
min-similarity-lines=3
```
### Pylint 使代码评审变得简单
如果你厌倦了需要指出一个类太复杂,或者两个不同的函数基本相同的代码评审,请将 Pylint 添加到你的[持续集成][6]配置中,并且只需要对项目复杂性准则的争论一次就行。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/python-pylint-introduction
作者:[Moshe Zadka][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://opensource.com/users/moshez
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/openstack_python_vim_2.jpg?itok=4fza48WU (OpenStack source code (Python) in VIM)
[2]: https://opensource.com/article/19/5/python-flake8
[3]: https://opensource.com/article/19/5/python-black
[4]: https://opensource.com/article/19/5/python-mypy
[5]: https://pylint.readthedocs.io/en/latest/technical_reference/features.html#design-checker
[6]: https://opensource.com/business/15/7/six-continuous-integration-tools

View File

@@ -0,0 +1,193 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11513-1.html)
[#]: subject: (Transition to Nftables)
[#]: via: (https://opensourceforu.com/2019/10/transition-to-nftables/)
[#]: author: (Vijay Marcel D https://opensourceforu.com/author/vijay-marcel/)
过渡到 nftables
======
![](https://img.linux.net.cn/data/attachment/album/201910/29/085827o8b7rbswjjr7ijsr.jpg)
> 开源世界中的每个主要发行版都在演进,逐渐将 nftables 作为了默认防火墙。换言之,古老的 iptables 现在已经消亡。本文是有关如何构建 nftables 的教程。
当前,有一个与 nftables 兼容的 iptables-nft 后端,但是很快,即使是它也不再提供了。另外,正如 Red Hat 开发人员所指出的那样,有时它可能会错误地转换规则。我们需要知道如何构建自己的 nftables而不是依赖于 iptables 到 nftables 的转换器。
在 nftables 中,所有地址族都遵循一个规则。与 iptables 不同nftables 在用户空间中运行iptables 中的每个模块都运行在内核(空间)中。它很少需要更新内核,并带有一些新功能,例如映射、地址族和字典。
### 地址族
地址族确定要处理的数据包的类型。在 nftables 中有六个地址族,它们是:
* ip
* ipv6
* inet
* arp
* bridge
* netdev
在 nftables 中ipv4 和 ipv6 协议可以被合并为一个称为 inet 的单一地址族。因此,我们不需要指定两个规则:一个用于 ipv4另一个用于 ipv6。如果未指定地址族它将默认为 ip 协议,即 ipv4。我们感兴趣的领域是 inet 地址族,因为大多数家庭用户将使用 ipv4 或 ipv6 协议。
### nftables
典型的 nftables 规则包含三个部分:表、链和规则。
表是链和规则的容器。它们由其地址族和名称来标识。链包含 inet/arp/bridge/netdev 等协议所需的规则并具有三种类型过滤器、NAT 和路由。nftables 规则可以从脚本加载,也可以在终端键入,然后另存为规则集。
对于家庭用户默认链为过滤器。inet 系列包含以下钩子:
* Input
* Output
* Forward
* Pre-routing
* Post-routing
### 使用脚本还是不用?
最大的问题之一是我们是否可以使用防火墙脚本。答案是:这是你自己的选择。这里有一些建议:如果防火墙中有数百条规则,那么最好使用脚本,但是如果你是典型的家庭用户,则可以在终端中键入命令,然后(保存并在重启时)加载规则集。每种选择都有其自身的优缺点。在本文中,我们将在终端中键入它们以构建防火墙。
nftables 使用一个名为 `nft` 的程序来添加、创建、列出、删除和加载规则。确保使用以下命令将 nftables 与 conntrackd 和 netfilter-persistent 软件包一起安装,并删除 iptables
```
apt-get install nftables conntrackd netfilter-persistent
apt-get purge iptables
```
`nft` 需要以 root 身份运行或使用 `sudo` 运行。使用以下命令分别列出、刷新、删除规则集和加载脚本。
```
nft list ruleset
nft flush ruleset
nft delete table inet filter
/usr/sbin/nft -f /etc/nftables.conf
```
### 输入策略
就像 iptables 一样,防火墙将包含三部分:输入(`input`)、转发(`forward`)和输出(`output`)。在终端中,为输入(`input`)策略键入以下命令。在开始之前,请确保已刷新规则集。我们的默认策略将会删除所有内容。我们将在防火墙中使用 inet 地址族。将以下规则以 root 身份添加或使用 `sudo` 运行:
```
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0 \; counter \; policy drop \; }
```
你会注意到有一个名为 `priority 0` 的东西。这意味着赋予该规则更高的优先级。挂钩通常赋予负整数,这意味着更高的优先级。每个挂钩都有自己的优先级,过滤器链的优先级为 0。你可以检查 nftables Wiki 页面以查看每个挂钩的优先级。
要了解你计算机中的网络接口,请运行以下命令:
```
ip link show
```
它将显示已安装的网络接口,一个是本地主机、另一个是以太网端口或无线端口。以太网端口的名称如下所示:`enpXsY`,其中 `X``Y` 是数字,无线端口也是如此。我们必须允许本地主机的流量,并且仅允许从互联网建立的传入连接。
nftables 具有一项称为裁决语句的功能,用于解析规则。裁决语句为 `accept``drop``queue``jump``goto``continue``return`。由于这是一个很简单的防火墙,因此我们将使用 `accept``drop` 处理数据包。
```
nft add rule inet filter input iifname lo accept
nft add rule inet filter input iifname enpXsY ct state new, established, related accept
```
接下来,我们必须添加规则以保护我们免受隐秘扫描。并非所有的隐秘扫描都是恶意的,但大多数都是。我们必须保护网络免受此类扫描。第一组规则列出了要测试的 TCP 标志。在这些标志中,第二组列出了要与第一组匹配的标志。
```
nft add rule inet filter input iifname enpXsY tcp flags \& \(syn\|fin\) == \(syn\|fin\) drop
nft add rule inet filter input iifname enpXsY tcp flags \& \(syn\|rst\) == \(syn\|rst\) drop
nft add rule inet filter input iifname enpXsY tcp flags \& \(fin\|rst\) == \(fin\|rst\) drop
nft add rule inet filter input iifname enpXsY tcp flags \& \(ack\|fin\) == fin drop
nft add rule inet filter input iifname enpXsY tcp flags \& \(ack\|psh\) == psh drop
nft add rule inet filter input iifname enpXsY tcp flags \& \(ack\|urg\) == urg drop
```
记住,我们在终端中键入这些命令。因此,我们必须在一些特殊字符之前添加一个反斜杠,以确保终端能够正确解释该斜杠。如果你使用的是脚本,则不需要这样做。
### 关于 ICMP 的警告
互联网控制消息协议ICMP是一种诊断工具因此不应完全丢弃该流量。完全阻止 ICMP 的任何尝试都是不明智的,因为它还会导致停止向我们提供错误消息。仅启用最重要的控制消息,例如回声请求、回声应答、目的地不可达和超时等消息,并拒绝其余消息。回声请求和回声应答是 `ping` 的一部分。在输入策略中,我们仅允许回声应答、而在输出策略中,我们仅允许回声请求。
```
nft add rule inet filter input iifname enpXsY icmp type { echo-reply, destination-unreachable, time-exceeded } limit rate 1/second accept
nft add rule inet filter input iifname enpXsY ip protocol icmp drop
```
最后,我们记录并丢弃所有无效数据包。
```
nft add rule inet filter input iifname enpXsY ct state invalid log flags all level info prefix \”Invalid-Input: \”
nft add rule inet filter input iifname enpXsY ct state invalid drop
```
### 转发和输出策略
在转发和输出策略中,默认情况下我们将丢弃数据包,仅接受已建立连接的数据包。
```
nft add chain inet filter forward { type filter hook forward priority 0 \; counter \; policy drop \; }
nft add rule inet filter forward ct state established, related accept
nft add rule inet filter forward ct state invalid drop
nft add chain inet filter output { type filter hook output priority 0 \; counter \; policy drop \; }
```
典型的桌面用户只需要端口 80 和 443 即可访问互联网。最后,允许可接受的 ICMP 协议并在记录无效数据包时丢弃它们。
```
nft add rule inet filter output oifname enpXsY tcp dport { 80, 443 } ct state established accept
nft add rule inet filter output oifname enpXsY icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 1/second accept
nft add rule inet filter output oifname enpXsY ip protocol icmp drop
nft add rule inet filter output oifname enpXsY ct state invalid log flags all level info prefix \”Invalid-Output: \”
nft add rule inet filter output oifname enpXsY ct state invalid drop
```
现在我们必须保存我们的规则集,否则重新启动时它将丢失。为此,请运行以下命令:
```
sudo nft list ruleset. > /etc/nftables.conf
```
我们须在引导时加载 nftables以下将在 systemd 中启用 nftables 服务:
```
sudo systemctl enable nftables
```
接下来,编辑 nftables 单元文件以删除 `Execstop` 选项,以避免在每次引导时刷新规则集。该文件通常位于 `/etc/systemd/system/sysinit.target.wants/nftables.service`。现在重新启动nftables
```
sudo systemctl restart nftables
```
### 在 rsyslog 中记录日志
当你记录丢弃的数据包时,它们直接进入 syslog这使得读取该日志文件非常困难。最好将防火墙日志重定向到单独的文件。在 `/var/log` 目录中创建一个名为 `nftables` 的目录,并在其中创建两个名为 `input.log``output.log` 的文件,分别存储输入和输出日志。确保系统中已安装 rsyslog。现在转到 `/etc/rsyslog.d` 并创建一个名为 `nftables.conf` 的文件,其内容如下:
```
:msg,regex,”Invalid-Input: “ -/var/log/nftables/Input.log
:msg,regex,”Invalid-Output: “ -/var/log/nftables/Output.log & stop
```
现在,我们必须确保日志是可管理的。为此,使用以下代码在 `/etc/logrotate.d` 中创建另一个名为 `nftables` 的文件:
```
/var/log/nftables/* { rotate 5 daily maxsize 50M missingok notifempty delaycompress compress postrotate invoke-rc.d rsyslog rotate > /dev/null endscript }
```
重新启动 nftables。现在你可以检查你的规则集。如果你觉得在终端中键入每个命令很麻烦则可以使用脚本来加载 nftables 防火墙。我希望本文对保护你的系统有用。
--------------------------------------------------------------------------------
via: https://opensourceforu.com/2019/10/transition-to-nftables/
作者:[Vijay Marcel D][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://opensourceforu.com/author/vijay-marcel/
[b]: https://github.com/lujun9972
[1]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2017/01/REHfirewall-1.jpg?resize=696%2C481&ssl=1 (REHfirewall)
[2]: https://i1.wp.com/opensourceforu.com/wp-content/uploads/2017/01/REHfirewall-1.jpg?fit=900%2C622&ssl=1

View File

@@ -0,0 +1,183 @@
[#]: collector: (lujun9972)
[#]: translator: (lnrCoder)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11503-1.html)
[#]: subject: (How to Get the Size of a Directory in Linux)
[#]: via: (https://www.2daygeek.com/find-get-size-of-directory-folder-linux-disk-usage-du-command/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
如何获取 Linux 中的目录大小
======
你应该已经注意到,在 Linux 中使用 [ls 命令][1] 列出的目录内容中,目录的大小仅显示 4KB。这个大小正确吗如果不正确那它代表什么又该如何获取 Linux 中的目录或文件夹大小?这是一个默认的大小,是用来存储磁盘上存储目录的元数据的大小。
Linux 上有一些应用程序可以 [获取目录的实际大小][2]。其中,磁盘使用率(`du`)命令已被 Linux 管理员广泛使用。
我将向您展示如何使用各种选项获取文件夹大小。
### 什么是 du 命令?
[du 命令][3] 表示 <ruby>磁盘使用率<rt>Disk Usage</rt></ruby>。这是一个标准的 Unix 程序,用于估计当前工作目录中的文件空间使用情况。
它使用递归方式总结磁盘使用情况,以获取目录及其子目录的大小。
如同我说的那样, 使用 `ls` 命令时,目录大小仅显示 4KB。参见下面的输出。
```
$ ls -lh | grep ^d
drwxr-xr-x 3 daygeek daygeek 4.0K Aug 2 13:57 Bank_Details
drwxr-xr-x 2 daygeek daygeek 4.0K Mar 15 2019 daygeek
drwxr-xr-x 6 daygeek daygeek 4.0K Feb 16 2019 drive-2daygeek
drwxr-xr-x 13 daygeek daygeek 4.0K Jan 6 2019 drive-mageshm
drwxr-xr-x 15 daygeek daygeek 4.0K Sep 29 21:32 Thanu_Photos
```
### 1) 在 Linux 上如何只获取父目录的大小
使用以下 `du` 命令格式获取给定目录的总大小。在该示例中,我们将得到 `/home/daygeek/Documents` 目录的总大小。
```
$ du -hs /home/daygeek/Documents
$ du -h --max-depth=0 /home/daygeek/Documents/
20G /home/daygeek/Documents
```
详细说明:
* `du` 这是一个命令
* `-h` 以易读的格式显示大小 (例如 1K 234M 2G)
* `-s` 仅显示每个参数的总数
* `--max-depth=N` 目录的打印深度
### 2) 在 Linux 上如何获取每个目录的大小
使用以下 `du` 命令格式获取每个目录(包括子目录)的总大小。
在该示例中,我们将获得每个 `/home/daygeek/Documents` 目录及其子目录的总大小。
```
$ du -h /home/daygeek/Documents/ | sort -rh | head -20
20G /home/daygeek/Documents/
9.6G /home/daygeek/Documents/drive-2daygeek
6.3G /home/daygeek/Documents/Thanu_Photos
5.3G /home/daygeek/Documents/Thanu_Photos/Camera
5.3G /home/daygeek/Documents/drive-2daygeek/Thanu-videos
3.2G /home/daygeek/Documents/drive-mageshm
2.3G /home/daygeek/Documents/drive-2daygeek/Thanu-Photos
2.2G /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month
916M /home/daygeek/Documents/drive-mageshm/Tanisha
454M /home/daygeek/Documents/drive-mageshm/2g-backup
415M /home/daygeek/Documents/Thanu_Photos/WhatsApp Video
300M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Jan-2017
288M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Oct-2017
226M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Sep-2017
219M /home/daygeek/Documents/Thanu_Photos/WhatsApp Documents
213M /home/daygeek/Documents/drive-mageshm/photos
163M /home/daygeek/Documents/Thanu_Photos/WhatsApp Video/Sent
161M /home/daygeek/Documents/Thanu_Photos/WhatsApp Images
154M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/June-2017
150M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Nov-2016
```
### 3) 在 Linux 上如何获取每个目录的摘要
使用如下 `du` 命令格式仅获取每个目录的摘要。
```
$ du -hs /home/daygeek/Documents/* | sort -rh | head -10
9.6G /home/daygeek/Documents/drive-2daygeek
6.3G /home/daygeek/Documents/Thanu_Photos
3.2G /home/daygeek/Documents/drive-mageshm
756K /home/daygeek/Documents/Bank_Details
272K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-TouchInterface1.png
172K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-NightLight.png
164K /home/daygeek/Documents/ConfigServer Security and Firewall (csf) Cheat Sheet.pdf
132K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-Todo.png
112K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-ZorinAutoTheme.png
96K /home/daygeek/Documents/distro-info.xlsx
```
### 4) 在 Linux 上如何获取每个目录的不含子目录的大小
使用如下 `du` 命令格式来展示每个目录的总大小,不包括子目录。
```
$ du -hS /home/daygeek/Documents/ | sort -rh | head -20
5.3G /home/daygeek/Documents/Thanu_Photos/Camera
5.3G /home/daygeek/Documents/drive-2daygeek/Thanu-videos
2.3G /home/daygeek/Documents/drive-2daygeek/Thanu-Photos
1.5G /home/daygeek/Documents/drive-mageshm
831M /home/daygeek/Documents/drive-mageshm/Tanisha
454M /home/daygeek/Documents/drive-mageshm/2g-backup
300M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Jan-2017
288M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Oct-2017
253M /home/daygeek/Documents/Thanu_Photos/WhatsApp Video
226M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Sep-2017
219M /home/daygeek/Documents/Thanu_Photos/WhatsApp Documents
213M /home/daygeek/Documents/drive-mageshm/photos
163M /home/daygeek/Documents/Thanu_Photos/WhatsApp Video/Sent
154M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/June-2017
150M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Nov-2016
127M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Dec-2016
100M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Oct-2016
94M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Nov-2017
92M /home/daygeek/Documents/Thanu_Photos/WhatsApp Images
90M /home/daygeek/Documents/drive-2daygeek/Thanu-photos-by-month/Dec-2017
```
### 5) 在 Linux 上如何仅获取一级子目录的大小
如果要获取 Linux 上给定目录的一级子目录(包括其子目录)的大小,请使用以下命令格式。
```
$ du -h --max-depth=1 /home/daygeek/Documents/
3.2G /home/daygeek/Documents/drive-mageshm
4.0K /home/daygeek/Documents/daygeek
756K /home/daygeek/Documents/Bank_Details
9.6G /home/daygeek/Documents/drive-2daygeek
6.3G /home/daygeek/Documents/Thanu_Photos
20G /home/daygeek/Documents/
```
### 6) 如何在 du 命令输出中获得总计
如果要在 `du` 命令输出中获得总计,请使用以下 `du` 命令格式。
```
$ du -hsc /home/daygeek/Documents/* | sort -rh | head -10
20G total
9.6G /home/daygeek/Documents/drive-2daygeek
6.3G /home/daygeek/Documents/Thanu_Photos
3.2G /home/daygeek/Documents/drive-mageshm
756K /home/daygeek/Documents/Bank_Details
272K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-TouchInterface1.png
172K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-NightLight.png
164K /home/daygeek/Documents/ConfigServer Security and Firewall (csf) Cheat Sheet.pdf
132K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-Todo.png
112K /home/daygeek/Documents/user-friendly-zorin-os-15-has-been-released-ZorinAutoTheme.png
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/find-get-size-of-directory-folder-linux-disk-usage-du-command/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[lnrCoder](https://github.com/lnrCoder)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.2daygeek.com/author/magesh/
[b]: https://github.com/lujun9972
[1]: https://www.2daygeek.com/linux-unix-ls-command-display-directory-contents/
[2]: https://www.2daygeek.com/how-to-get-find-size-of-directory-folder-linux/
[3]: https://www.2daygeek.com/linux-check-disk-usage-files-directories-size-du-command/

View File

@@ -0,0 +1,149 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11518-1.html)
[#]: subject: (Building container images with the ansible-bender tool)
[#]: via: (https://opensource.com/article/19/10/building-container-images-ansible)
[#]: author: (Tomas Tomecek https://opensource.com/users/tomastomecek)
使用 ansible-bender 构建容器镜像
======
> 了解如何使用 Ansible 在容器中执行命令。
![](https://img.linux.net.cn/data/attachment/album/201910/30/090738vzbifzfpa6qz9bij.jpg)
容器和 [Ansible][2] 可以很好地融合在一起:从管理和编排到供应和构建。在本文中,我们将重点介绍构建部分。
如果你熟悉 Ansible就会知道你可以编写一系列任务`ansible-playbook` 命令将为你执行这些任务。你知道吗,如果你编写 Dockerfile 并运行 `podman build`,你还可以在容器环境中执行此类命令,并获得相同​​的结果。
这是一个例子:
```
- name: Serve our file using httpd
hosts: all
tasks:
- name: Install httpd
package:
name: httpd
state: installed
- name: Copy our file to httpds webroot
copy:
src: our-file.txt
dest: /var/www/html/
```
你可以在 Web 服务器本地或容器中执行这个剧本,并且只要你记得先创建 `our-file.txt`,它就可以工作。
但是这里缺少了一些东西。你需要启动并配置httpd 以便提供文件。这是容器构建和基础架构供应之间的区别:构建镜像时,你只需准备内容;而运行容器是另一项任务。另一方面,你可以将元数据附加到容器镜像,它会默认运行命令。
这有个工具可以帮助。试试看 `ansible-bender` 怎么样?
```
$ ansible-bender build the-playbook.yaml fedora:30 our-httpd
```
该脚本使用 `ansible-bender` 对 Fedora 30 容器镜像执行该剧本,并将生成的容器镜像命名为 `our-httpd`
但是,当你运行该容器时,它不会启动 httpd因为它不知道如何操作。你可以通过向该剧本添加一些元数据来解决此问题
```
- name: Serve our file using httpd
hosts: all
vars:
ansible_bender:
base_image: fedora:30
target_image:
name: our-httpd
cmd: httpd -DFOREGROUND
tasks:
- name: Install httpd
package:
name: httpd
state: installed
- name: Listen on all network interfaces.
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
line: Listen 0.0.0.0:80
- name: Copy our file to httpds webroot
copy:
src: our-file.txt
dest: /var/www/html
```
现在你可以构建镜像(从这里开始,请以 root 用户身份运行所有命令。目前Buildah 和 Podman 不会为无 root 容器创建专用网络):
```
# ansible-bender build the-playbook.yaml
PLAY [Serve our file using httpd] ****************************************************
TASK [Gathering Facts] ***************************************************************
ok: [our-httpd-20191004-131941266141-cont]
TASK [Install httpd] *****************************************************************
loaded from cache: 'f053578ed2d47581307e9ba3f64f4b4da945579a082c6f99bd797635e62befd0'
skipping: [our-httpd-20191004-131941266141-cont]
TASK [Listen on all network interfaces.] *********************************************
changed: [our-httpd-20191004-131941266141-cont]
TASK [Copy our file to httpds webroot] **********************************************
changed: [our-httpd-20191004-131941266141-cont]
PLAY RECAP ***************************************************************************
our-httpd-20191004-131941266141-cont : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Getting image source signatures
Copying blob sha256:4650c04b851c62897e9c02c6041a0e3127f8253fafa3a09642552a8e77c044c8
Copying blob sha256:87b740bba596291af8e9d6d91e30a01d5eba9dd815b55895b8705a2acc3a825e
Copying blob sha256:82c21252bd87532e93e77498e3767ac2617aa9e578e32e4de09e87156b9189a0
Copying config sha256:44c6dc6dda1afe28892400c825de1c987c4641fd44fa5919a44cf0a94f58949f
Writing manifest to image destination
Storing signatures
44c6dc6dda1afe28892400c825de1c987c4641fd44fa5919a44cf0a94f58949f
Image 'our-httpd' was built successfully \o/
```
镜像构建完毕,可以运行容器了:
```
# podman run our-httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.2.106. Set the 'ServerName' directive globally to suppress this message
```
是否提供文件了?首先,找出你容器的 IP
```
# podman inspect -f '{{ .NetworkSettings.IPAddress }}' 7418570ba5a0
10.88.2.106
```
你现在可以检查了:
```
$ curl http://10.88.2.106/our-file.txt
Ansible is ❤
```
你文件内容是什么?
这只是使用 Ansible 构建容器镜像的介绍。如果你想了解有关 `ansible-bender` 可以做什么的更多信息,请查看它的 [GitHub][3] 页面。构建快乐!
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/building-container-images-ansible
作者:[Tomas Tomecek][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://opensource.com/users/tomastomecek
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/blocks_building.png?itok=eMOT-ire (Blocks for building)
[2]: https://www.ansible.com/
[3]: https://github.com/ansible-community/ansible-bender

View File

@@ -0,0 +1,106 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11515-1.html)
[#]: subject: (Using SSH port forwarding on Fedora)
[#]: via: (https://fedoramagazine.org/using-ssh-port-forwarding-on-fedora/)
[#]: author: (Paul W. Frields https://fedoramagazine.org/author/pfrields/)
在 Fedora 上使用 SSH 端口转发
======
![](https://img.linux.net.cn/data/attachment/album/201910/29/123804dql3aqqlghza9txt.jpg)
你可能已经熟悉使用 [ssh 命令][2]访问远程系统。`ssh` 命令背后所使用的协议允许终端的输入和输出流经[安全通道][3]。但是你知道也可以使用 `ssh` 来安全地发送和接收其他数据吗?一种方法是使用“<ruby>端口转发<rt>port forwarding</rt></ruby>”,它允许你在进行 `ssh` 会话时安全地连接网络端口。本文向你展示了它是如何工作的。
### 关于端口
标准 Linux 系统已分配了一组网络端口,范围是 0 - 65535。系统会保留 0 - 1023 的端口以供系统使用。在许多系统中,你不能选择使用这些低端口号。通常有几个端口用于运行特定的服务。你可以在系统的 `/etc/services` 文件中找到这些定义。
你可以认为网络端口是类似的物理端口或可以连接到电缆的插孔。端口可以连接到系统上的某种服务,类似物理插孔后面的接线。一个例子是 Apache Web 服务器(也称为 `httpd`)。对于 HTTP 非安全连接Web 服务器通常要求在主机系统上使用端口 80对于 HTTPS 安全连接通常要求使用 443。
当你连接到远程系统(例如,使用 Web 浏览器)时,你是将浏览器“连接”到你的主机上的端口。这通常是一个随机的高端口号,例如 54001。你的主机上的端口连接到远程主机上的端口例如 443来访问其安全的 Web 服务器。
那么,当你有这么多可用端口时,为什么还要使用端口转发呢?这是 Web 开发人员生活中的几种常见情况。
### 本地端口转发
想象一下,你正在名为 `remote.example.com` 的远程系统上进行 Web 开发。通常,你是通过 `ssh` 进入此系统的,但是它位于防火墙后面,而且该防火墙很少允许其他类型的访问,并且会阻塞大多数其他端口。要尝试你的网络应用,能够使用浏览器访问远程系统会很有帮助。但是,由于使用了讨厌的防火墙,你无法通过在浏览器中输入 URL 的常规方法来访问它。
本地转发使你可以通过 `ssh` 连接来建立可通过远程系统访问的端口。该端口在系统上显示为本地端口(因而称为“本地转发”)。
假设你的网络应用在 `remote.example.com` 的 8000 端口上运行。要将那个系统的 8000 端口本地转发到你系统上的 8000 端口,请在开始会话时将 `-L` 选项与 `ssh` 结合使用:
```
$ ssh -L 8000:localhost:8000 remote.example.com
```
等等,为什么我们使用 `localhost` 作为转发目标?这是因为从 `remote.example.com` 的角度来看,你是在要求主机使用其自己的端口 8000。回想一下任何主机通常可以通过网络连接 `localhost` 而连接到自身。)现在那个端口连接到你系统的 8000 端口了。`ssh` 会话准备就绪后,将其保持打开状态,然后可以在浏览器中键入 `http://localhost:8000` 来查看你的 Web 应用。现在,系统之间的流量可以通过 `ssh` 隧道安全地传输!
如果你有敏锐的眼睛,你可能已经注意到了一些东西。如果我们要 `remote.example.com` 转发到与 `localhost` 不同的主机名怎么办?如果它可以访问该网络上另一个系统上的端口,那么通常可以同样轻松地转发该端口。例如,假设你想访问也在该远程网络中的 `db.example.com` 的 MariaDB 或 MySQL 服务。该服务通常在端口 3306 上运行。因此,即使你无法 `ssh` 到实际的 `db.example.com` 主机,你也可以使用此命令将其转发:
```
$ ssh -L 3306:db.example.com:3306 remote.example.com
```
现在,你可以在 `localhost` 上运行 MariaDB 命令,而实际上是在使用 `db.example.com` 主机。
### 远程端口转发
远程转发让你可以进行相反操作。想象一下,你正在为办公室的朋友设计一个 Web 应用,并想向他们展示你的工作。不过,不幸的是,你在咖啡店里工作,并且由于网络设置,他们无法通过网络连接访问你的笔记本电脑。但是,你同时使用着办公室的 `remote.example.com` 系统,并且仍然可在这里登录。你的 Web 应用似乎在本地 5000 端口上运行良好。
远程端口转发使你可以通过 `ssh` 连接从本地系统建立端口的隧道,并使该端口在远程系统上可用。在开始 `ssh` 会话时,只需使用 `-R` 选项:
```
$ ssh -R 6000:localhost:5000 remote.example.com
```
现在,当在公司防火墙内的朋友打开浏览器时,他们可以进入 `http://remote.example.com:6000` 查看你的工作。就像在本地端口转发示例中一样,通信通过 `ssh` 会话安全地进行。
默认情况下,`sshd` 守护进程运行在设置的主机上,因此**只有**该主机可以连接它的远程转发端口。假设你的朋友希望能够让其他 `example.com` 公司主机上的人看到你的工作,而他们不在 `remote.example.com` 上。你需要让 `remote.example.com` 主机的所有者将以下选项**之一**添加到 `/etc/ssh/sshd_config` 中:
```
GatewayPorts yes # 或
GatewayPorts clientspecified
```
第一个选项意味着 `remote.example.com` 上的所有网络接口都可以使用远程转发的端口。第二个意味着建立隧道的客户端可以选择地址。默认情况下,此选项设置为 `no`
使用此选项,你作为 `ssh` 客户端仍必须指定可以共享你这边转发端口的接口。通过在本地端口之前添加网络地址范围来进行此操作。有几种方法可以做到,包括:
```
$ ssh -R *:6000:localhost:5000 # 所有网络
$ ssh -R 0.0.0.0:6000:localhost:5000 # 所有网络
$ ssh -R 192.168.1.15:6000:localhost:5000 # 单个网络
$ ssh -R remote.example.com:6000:localhost:5000 # 单个网络
```
### 其他注意事项
请注意,本地和远程系统上的端口号不必相同。实际上,有时你甚至可能无法使用相同的端口。例如,普通用户可能不会在默认设置中转发到系统端口。
另外,可以限制主机上的转发。如果你需要在联网主机上更严格的安全性,那么这你来说可能很重要。 `sshd` 守护程进程的 `PermitOpen` 选项控制是否以及哪些端口可用于 TCP 转发。默认设置为 `any`,这让上面的所有示例都能正常工作。要禁止任何端口转发,请选择 `none`,或仅允许的特定的“主机:端口”。有关更多信息,请在手册页中搜索 `PermitOpen` 来配置 `sshd` 守护进程:
```
$ man sshd_config
```
最后,请记住,只有在 `ssh` 会话处于打开状态时才会端口转发。如果需要长时间保持转发活动,请尝试使用 `-N` 选项在后台运行会话。确保控制台已锁定,以防止在你离开控制台时其被篡夺。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/using-ssh-port-forwarding-on-fedora/
作者:[Paul W. Frields][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://fedoramagazine.org/author/pfrields/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2019/10/ssh-port-forwarding-816x345.jpg
[2]: https://en.wikipedia.org/wiki/Secure_Shell
[3]: https://fedoramagazine.org/open-source-ssh-clients/

View File

@@ -0,0 +1,96 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11509-1.html)
[#]: subject: (MX Linux 19 Released With Debian 10.1 Buster & Other Improvements)
[#]: via: (https://itsfoss.com/mx-linux-19/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
随着 Debian 10.1 “Buster” 的发布MX Linux 19 也发布了
======
MX Linux 18 是我在[最佳 Linux 发行版][1]中的主要推荐的发行版之一,特别是当你在考虑 Ubuntu 以外的发行版时。
它基于 Debian 9.6 “Stretch”具有令人难以置信的快速流畅的体验。
现在作为该发行版的主要升级版本MX Linux 19 带来了许多重大改进和变更。在这里,我们将看一下主要亮点。
### MX Linux 19 中的新功能
- [视频](https://player.vimeo.com/video/368459760)
#### Debian 10 “Buster”
这个值得一提,因为 Debian 10 实际上是 MX Linux 18 所基于的 Debian 9.6 “Stretch” 的主要升级。
如果你对 Debian 10 “Buster” 的变化感到好奇,建议你阅读有关 [Debian 10 “Buster” 的新功能][3]的文章。
#### Xfce 桌面 4.14
![MX Linux 19][4]
[Xfce 4.14][5] 正是 Xfce 开发团队提供的最新产品。就个人而言,我不是 Xfce 桌面环境的粉丝,但是当你在 Linux 发行版(尤其是 MX Linux 19上使用它时它超快的性能会让你惊叹。
或许你会感兴趣,我们也有一个快速指南来帮助你[自定义 Xfce][6]。
#### 升级的软件包及最新的 Debian 内核 4.19
除了 [GIMP][7]、MESA、Firefox 等的更新软件包之外,它还随附有 Debian “Buster” 可用的最新内核 4.19。
#### 升级的 MX 系列应用
如果你以前使用过 MX Linux则可能会知道它已经预装了有用的 MX 系列应用,可以帮助你快速完成更多工作。
像 MX-installer 和 MX-packageinstaller 这样的应用程序得到了显著改进。
除了这两个以外,所有其他 MX 工具也已不同程度的进行了更新和修复错误、添加了新的翻译(或只是改善了用户体验)。
#### 其它改进
考虑到这是一次重大升级,很明显,底层的更改要多于表面(包括最新的 antiX live 系统更新)。
你可以在他们的[官方公告][8]中查看更多详细信息。你还可以从开发人员那里观看以下视频,它介绍了 MX Linux 19 中的所有新功能:
- [视频](https://youtu.be/4XVHA4l4Zrc)
### 获取 MX Linux 19
即使是你现在正在使用 MX Linux 18 版本,你也[无法][9]升级到 MX Linux 19。你需要像其他人一样进行全新安装。
你可以从此页面下载 MX Linux 19
- [下载 MX Linux 19][10]
### 结语
在 MX Linux 18 上,我在使用 WiFi 适配器时遇到了问题,通过[论坛][11]解决了该问题,但看来 MX Linux 19 仍未解决该问题。因此,如果你在安装 MX Linux 19 之后遇到了相同的问题,你可能想要查看一下我的[论坛帖子][11]。
如果你使用的是 MX Linux 18那么这绝对是一个令人印象深刻的升级。
你尝试过了吗?你对新的 MX Linux 19 版本有何想法?让我知道你在以下评论中的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/mx-linux-19/
作者:[Ankush Das][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://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-11411-1.html
[2]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
[3]: https://linux.cn/article-11071-1.html
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/mx-linux-19.jpg?ssl=1
[5]: https://xfce.org/about/news
[6]: https://itsfoss.com/customize-xfce/
[7]: https://itsfoss.com/gimp-2-10-release/
[8]: https://mxlinux.org/blog/mx-19-patito-feo-released/
[9]: https://mxlinux.org/migration/
[10]: https://mxlinux.org/download-links/
[11]: https://forum.mxlinux.org/viewtopic.php?t=52201

View File

@@ -0,0 +1,85 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11522-1.html)
[#]: subject: (Fedora 31 is officially here!)
[#]: via: (https://fedoramagazine.org/announcing-fedora-31/)
[#]: author: (Matthew Miller https://fedoramagazine.org/author/mattdm/)
Fedora 31 正式发布
======
![][1]
这里,我们很荣幸地宣布 Fedora 31 的发布。感谢成千上万的 Fedora 社区成员和贡献者的辛勤工作,我们现在正在庆祝又一次的准时发布。这已成为一种惯例!
如果你只想立即获取它,请立即访问 <https://getfedora.org/>。要了解详细信息,请继续阅读!
### 工具箱
如果你还没有使用过 [Fedora 工具箱][2],那么现在是尝试一下的好时机。这是用于启动和管理个人工作区容器的简单工具,你可以在一个单独的环境中进行开发或试验。它只需要在命令行运行 `toolbox enter` 就行。
这种容器化的工作流程对于基于 ostree 的 Fedora 变体(如 CoreOS、IoT 和 Silverblue的用户至关重要但在任何工作站甚至服务器系统上也非常有用。在接下来的几个月中希望对该工具及其相关的用户体验进行更多增强非常欢迎你提供反馈。
### Fedora 风味版
Fedora 的“版本”是针对特定的“展示柜”用途输出的。
Fedora 工作站版本专注于台式机,以及希望获得“可以工作的” Linux 操作系统体验的特定软件开发人员。此版本具有 GNOME 3.34,它带来了显著的性能增强,在功耗较低的硬件上尤其明显。
Fedora 服务器版本以易于部署的方式为系统管理员带来了最新的、最先进的开源服务器软件。
而且,我们还有处于预览状态下的 Fedora CoreOS一个定义了现代容器世界分类的操作系统和[Fedora IoT][3](用于“边缘计算”用例)。(敬请期待计划中的给该物联网版本的征集名称的活动!)
当然,我们不仅仅提供的是各种版本。还有面向各种受众和用例的 [Fedora Spins][4] 和 [Labs][5],包括 [Fedora 天文学][6] 版本,为业余和专业的天文学家带来了完整的开源工具链,以及支持各种桌面环境(例如 [KDE Plasma][7] 和 [Xfce][8])。
而且,请不要忘记我们的替代架构 [ARM AArch64、Power 和 S390x][9]。特别要注意的是,我们对包括 Rock960、RockPro64 和 Rock64 在内的 Rockchip 片上系统设备的支持得到了改善,并初步支持了 “[panfrost][10]”,这是一种较新的开源 3D 加速图形驱动程序 Arm Mali "midgard" GPU。
不过,如果你使用的是只支持 32 位的 i686 旧系统,那么该找个替代方案了,[我们的基本系统告别了 32 位 Intel 架构][11]。
### 常规改进
无论你使用哪种 Fedora 版本,你都将获得开源世界所提供的最新版本。遵循 “[First][12]” 准则,我们启用了 CgroupsV2如果你使用的是 Docker[请确保检查一下][13]。Glibc 2.30 和 NodeJS 12 是 Fedora 31 中许多更新的软件包之一。而且,我们已经将 `python` 命令切换为 Python 3请记住Python 2 在[今年年底][14]生命期就终止了。
我们很高兴你能试用新版本!转到 <https://getfedora.org/> 并立即下载吧。或者,如果你已经在运行 Fedora 操作系统,请遵循简单的[升级说明][15]就行。
### 万一出现问题……
如果遇到问题,请查看 [Fedora 31 常见错误][16]页面,如果有疑问,请访问我们的 [Ask Fedora][17] 用户支持平台。
### 谢谢大家
感谢在此发行周期中成千上万为 Fedora 项目做出贡献的人们,尤其是那些为使该发行版再次按时发行而付出更多努力的人。而且,如果你本周在波特兰参加 [USENIX LISA][18],请在博览会大厅,在 Red Hat、Fedora 和 CentOS 展位找到我。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/announcing-fedora-31/
作者:[Matthew Miller][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://fedoramagazine.org/author/mattdm/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2019/10/fedora31-816x345.jpg
[2]: https://docs.fedoraproject.org/en-US/fedora-silverblue/toolbox/
[3]: https://iot.fedoraproject.org/
[4]: https://spins.fedoraproject.org/
[5]: https://labs.fedoraproject.org/
[6]: https://labs.fedoraproject.org/en/astronomy/
[7]: https://spins.fedoraproject.org/en/kde/
[8]: https://spins.fedoraproject.org/en/xfce/
[9]: https://alt.fedoraproject.org/alt/
[10]: https://panfrost.freedesktop.org/
[11]: https://fedoramagazine.org/in-fedora-31-32-bit-i686-is-86ed/
[12]: https://docs.fedoraproject.org/en-US/project/#_first
[13]: https://fedoraproject.org/wiki/Common_F31_bugs#Docker_package_no_longer_available_and_will_not_run_by_default_.28due_to_switch_to_cgroups_v2.29
[14]: https://pythonclock.org/
[15]: https://docs.fedoraproject.org/en-US/quick-docs/upgrading/
[16]: https://fedoraproject.org/wiki/Common_F31_bugs
[17]: http://ask.fedoraproject.org
[18]: https://www.usenix.org/conference/lisa19

View File

@@ -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
======
![](https://img.linux.net.cn/data/attachment/album/201912/05/053423mpnrn95hqqknzheq.jpg)
当你想同时查看多个文件(尤其是日志文件)的活动时,`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

View File

@@ -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 资深用户,则可能会有这些共同倾向。
![](https://img.linux.net.cn/data/attachment/album/201912/02/093348ek4jcyvj4wahytwq.jpg)
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` 会<ruby>列出<rt>list</rt></ruby>目录。但是,一旦学习命令,它们肯定是越短越好。如果你整天都在终端上度过,那么你键入的击键次数越少就意味着你可以有更多的时间来完成工作。
幸运的是,单字母命令并不太多,因此你可以使用大多数字母作为别名。例如,我经常使用 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

View File

@@ -0,0 +1,76 @@
用 autoplank 在多个显示器上使用 Plank 扩展坞
======
![](https://3.bp.blogspot.com/-BNHa6rP_kGk/W22cJrT3ghI/AAAAAAAABWA/TAKZgxJfYuwz-Me-M135-LWYl5qvs6cIwCLcBGAs/s640/plank-dock.png)
[autoplank][1] 是用 Go 语言编写的小型工具,它为 Plank 扩展坞增加了多显示器支持,而无需创建[多个][2]扩展坞。
当你将鼠标光标移动到显示器的底部时,`autoplank` 会使用 `xdotool` 检测到你的鼠标移动,并且自动将 Plank 扩展坞移动到该显示器。该工具仅在将 Plank 设置为在屏幕底部的情况下工作(至少目前如此)。
在 Plank 实际出现在鼠标所在的显示器上前会稍有延迟。开发人员说这是有意设计的,以确保你确实要在该显示器上访问 Plank。显示 Plank 之前的时间延迟目前尚不可配置,但将来可能会改变。
`autoplank` 可以在 elementary OS 以及其它的桌面环境或发行版上使用。
Plank 是一个简单的扩展坞,它显示了正在运行的应用程序/窗口的图标。它允许将应用程序固定到扩展坞并带有一些内置的简单“扩展组件”剪贴板管理器、时钟、CPU 监视器、显示桌面和垃圾桶。要访问其设置,请按住 `Ctrl` 键,同时右键单击 Plank 扩展坞上的任意位置,然后单击 “Preferences”。
Plank 默认用在 elementary OS 中,但也可以在任何桌面环境或 Linux 发行版中使用。
### 安装 autoplank
在其 GitHub 页面上,提到你需要 Go 1.8 或更高版本才能构建 `autoplank`,但我能够在 Ubuntu 16.04elementary OS 0.4 Loki中使用 Go 1.6 成功构建它。
开发者说:
1、安装所需的依赖项。
要构建 `autoplank`,你需要 Go在 Debian、Ubuntu、elementary OS 等中使用 golang-go。要获取最新的 Git 代码,你还需要 `git`,要在显示器上检测你的鼠标移动,还需要安装 `xdotool`
使用以下命令将它们安装在 Ubuntu、Debian、elementary OS 等中:
```
sudo apt install git golang-go xdotool
```
2、从 [Git][1] 获取最新的 `autoplank`,构建并将其安装在 `/usr/local/bin` 中:
```
git clone https://github.com/abiosoft/autoplank
cd autoplank
go build -o autoplank
sudo mv autoplank /usr/local/bin/
```
你现在可以从主目录中删除 `autoplank` 文件夹。
当你想卸载 `autoplank` 时,只需删除 `/usr/local/bin/autoplank` 二进制文件(`sudo rm /usr/local/bin/autoplank`)。
3、将 `autoplank` 添加到启动中。
如果你想在将 `autoplank` 添加到启动项或为其创建 systemd 服务之前尝试使用 `autoplank`,则只需在终端中键入 `/usr/local/bin/autoplank` 即可启动它。
要使 `autoplank` 在重新启动后起作用,你需要将其添加到启动项中。确切的操作步骤取决于你的桌面环境,因此我不会确切告诉你如何在每个桌面环境中执行此操作,但是请记住在启动项中将 `/usr/local/bin/autoplank` 设置为可执行文件。
在 elementary OS 中,你可以打开“系统设置”,然后在“应用程序”的“启动”选项卡上,单击窗口左下角的“+”按钮,然后在“键入自定义命令”字段中添加 “/usr/local/bin/autoplank”
![](https://4.bp.blogspot.com/-hbh1PLDX-0A/W22eIhEQ1iI/AAAAAAAABWM/GkgrzaPPjA8CHnxF5L4UPPUG_vPa9VT-gCLcBGAs/s640/autoplank-startup-elementaryos.png)
如[此处][3]的解释,使用 `autoplank` 的另一种方法是通过为其创建 systemd 服务。将 systemd 服务用于 autoplank 的优点是,无论它出于何种原因而崩溃,都可以重新启动 `autoplank`。可以使用 systemd 服务或将 `autoplank` 添加到启动应用程序中(但不要同时使用两者)。
4、完成此操作后注销、登录`autoplank` 应该已在运行,因此你可以将鼠标移至显示器底部以将 Plank 停靠此处。
--------------------------------------------------------------------------------
via: https://www.linuxuprising.com/2018/08/use-plank-on-multiple-monitors-without.html
作者:[Logix][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://plus.google.com/118280394805678839070
[1]:https://github.com/abiosoft/autoplank
[2]:https://answers.launchpad.net/plank/+question/204593
[3]:https://github.com/abiosoft/autoplank#optional-create-a-service
[4]:https://www.reddit.com/r/elementaryos/comments/95a879/autoplank_use_plank_on_multimonitor_setup/e3r9saq/

View File

@@ -0,0 +1,101 @@
Linux 平台上的写作者必备工具
======
![](https://img.linux.net.cn/data/attachment/album/201911/25/000129eee2zydelz22vj9h.jpg)
我从事作家已有 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]
*图 3WPS 可以轻松处理大量注释。*
一旦我和我的编辑完成了对书的编辑(所有评论都已删除),我就可以在 LibreOffice 中打开文件进行最终格式化。格式化完成后,我将文件保存为 .html 格式,然后以 [Calibre][14] 打开文件以将文件导出为 .mobi 和 .epub 格式。
对于希望在 Amazon、BarnesNoble、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

View File

@@ -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 更快吗?
======
![](https://img.linux.net.cn/data/attachment/album/201911/23/235729l71755he6e4mpvkq.jpg)
> 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

View File

@@ -0,0 +1,73 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11575-1.html)
[#]: subject: (Why blockchain (might be) coming to an IoT implementation near you)
[#]: via: (https://www.networkworld.com/article/3386881/why-blockchain-might-be-coming-to-an-iot-implementation-near-you.html)
[#]: author: (Jon Gold https://www.networkworld.com/author/Jon-Gold/)
为什么区块链(可能会)来到你身边的物联网
======
![MF3D / Getty Images][1]
各个公司发现,物联网与最近其他许多流行的企业级计算技术有着良好的合作关系,以支持加密货币而闻名的创新的分布式信任系统的区块链也不例外。然而,在物联网应用中实施区块链可能具有挑战性,并且需要对技术有深入的了解。
区块链是一个跟踪各种交易的分布式账本。链上的每个“块”都包含要防止篡改的交易记录或其他数据,并通过加密散列链接到前一个,这意味着对块的任何篡改都将使该链接无效。节点(几乎可以是其中装有 CPU 的任何节点)通过分布式的对等网络进行通信,以共享数据并确保链中数据的有效性。
北卡罗来纳大学格林波若分校的管理学教授 Nir Kshetri 表示,区块链系统之所以有效,是因为所有的块都必须就它们所保护的数据的细节达成一致。如果有人尝试更改给定节点上先前的事务,则存储在网络上的其余数据会回推回来。“数据的旧记录仍然存在,” Kshetri 说。
这是一项强大的安全技术 —— 如果没有坏人成功控制给定区块链上的所有LCTT 译注:应为“大部分”)节点([著名的“51 攻击”][4]),那么该区块链保护的数据就不会被伪造或以其他方式弄乱。因此,对于在物联网世界某些角落的公司来说,使用区块链是一种有吸引力的选择也就不足为奇了。
物联网安全初创企业 NXMLabs 的首席技术官兼联合创始人 Jay Fallah 认为,除了区块链能够在网络上安全地分发可信信息的能力这一事实之外,部分原因还在于区块链在技术堆栈中的地位。
“区块链站在一个非常有趣的交叉点。在过去的 15 年中在存储、CPU 等方面,计算技术一直在加速发展,但是直到最近,网络技术并没有发生太大变化。”他说,“ 区块链不是网络技术、不是数据技术,而是二者兼具。”
### 区块链和物联网
区块链作为物联网世界的部分意义取决于你在和谁交谈以及他们在出售什么,但是最接近的概括可能来自企业区块链供应商 Filament 的首席执行官 Allison Clift-Jenning。
她说:“在任何地方,人们都想互相信任,并且用的是非常古老的方式,这通常是进入场景的好地方。”
直接从 Filament 自己的客户群中挑选出来的一个例子是二手车销售。Filament 与“一家主要的底特律汽车制造商”合作,创建了一个受信任的车辆历史平台,该平台基于一种设备,该设备可插入二手车的诊断端口,从那里获取信息,并将该数据写入区块链。像这样,二手车的历史记录就是不可变的,包括它的安全气囊是否曾经打开过,是否被水淹过等等。任何不道德的二手车或不诚实的前车主都无法更改数据,甚至拔掉设备也将意味着记录中存在可疑的空白期。
SAP 物联网高级副总裁兼全球负责人 Elvira Wallis 表示,当今大多数区块链物联网方案都与信任和数据验证有关。
她说:“我们遇到的大多数用例都在项目的跟踪和溯源领域,”她举例说明了高端食品的农场到餐桌跟踪系统,该系统使用安装在板条箱和卡车上的区块链节点,这样就可以为物品在运输基础设施中创建无懈可击的记录。(例如,该牛排在这样的温度下冷藏了多长时间,今天运输了多长时间,等等。)
### 将区块链与物联网一起使用是个好主意吗?
不同的供应商针对不同的用例出售不同的基于区块链的产品,这些产品使用不同的区块链技术实现,其中一些与加密货币中所使用的经典的、线性的、挖矿式交易区块链不太一样。
这意味着你目前需要从供应商那里购买特定功能。451 Research 高级分析师 Csilla Zsigri 表示,很少有客户组织拥有可以实施区块链安全系统的内部专家。
她说,区块链技术的任何智能应用的想法都是发挥其优势,为关键信息创建可信赖的平台。
Zsigri 说:“这就是我真正看到增值的地方,只是增加了一层信任和验证。”
专家们一致认为,尽管相当了解基于区块链的物联网应用程序的基本概念,但它并不适用于每个物联网用例。 将区块链应用于非交易系统(尽管有例外,包括 NXM Labs 的用于物联网设备的基于区块链配置的产品)通常不是正确的举动。
如果不需要在两个不同的参与方之间共享数据,而是简单地将数据从传感器移到后端,那么区块链通常就没有意义,因为它实际上并没有为当前大多数物联网实现中的数据分析增加任何关键的增值。
“今天我们仍处于区块链的早期拨号时代。”Clift-Jennings 说,“它比典型的数据库要慢,它甚至无法读取,也常常没有查询引擎。从本质上讲,你并没有真正获得隐私。”
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3386881/why-blockchain-might-be-coming-to-an-iot-implementation-near-you.html
作者:[Jon Gold][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.networkworld.com/author/Jon-Gold/
[b]: https://github.com/lujun9972
[1]: https://images.idgesg.net/images/article/2019/02/chains_binary_data_blockchain_security_by_mf3d_gettyimages-941175690_2400x1600-100788434-large.jpg
[2]: https://www.networkworld.com/article/3224893/internet-of-things/what-is-edge-computing-and-how-it-s-changing-the-network.html
[3]: https://www.networkworld.com/article/3291790/data-center/how-edge-networking-and-iot-will-reshape-data-centers.html
[4]: https://bitcoinist.com/51-percent-attack-hackers-steals-18-million-bitcoin-gold-btg-tokens/
[5]: https://www.facebook.com/NetworkWorld/
[6]: https://www.linkedin.com/company/network-world

View File

@@ -0,0 +1,63 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11565-1.html)
[#]: subject: (Why containers and Kubernetes have the potential to run almost anything)
[#]: via: (https://opensource.com/article/19/6/kubernetes-potential-run-anything)
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux)
为什么容器和 Kubernetes 有潜力运行一切
======
> 不仅可以部署简单的应用程序,还可以用 Kubernetes 运维器应对第 2 天运营。
![](https://img.linux.net.cn/data/attachment/album/201911/12/011140mp75sd0ynppd77da.jpg)
在我的第一篇文章 [为什么说 Kubernetes 是一辆翻斗车][2] 中,我谈到了 Kubernetes 如何在定义、分享和运行应用程序方面很出色,类似于翻斗车在移动垃圾方面很出色。在第二篇中,[如何跨越 Kubernetes 学习曲线][3],我解释了 Kubernetes 的学习曲线实际上与运行任何生产环境中的应用程序的学习曲线相同,这确实比学习所有传统组件要容易(如负载均衡器、路由器、防火墙、交换机、集群软件、集群文件系统等)。这是 DevOps是开发人员和运维人员之间的合作用于指定事物在生产环境中的运行方式这意味着双方都需要学习。在第三篇 [Kubernetes 基础:首先学习如何使用][4] 中,我重新设计了 Kubernetes 的学习框架,重点是驾驶翻斗车而不是制造或装备翻斗车。在第四篇文章 [帮助你驾驭 Kubernetes 的 4 个工具][5] 中,我分享了我喜爱的工具,这些工具可帮助你在 Kubernetes 中构建应用程序(驾驶翻斗车)。
在这最后一篇文章中,我会分享我为什么对在 Kubernetes 上运行应用程序的未来如此兴奋的原因。
从一开始Kubernetes 就能够很好地运行基于 Web 的工作负载容器化的。Web 服务器、Java 和相关的应用程序服务器PHP、Python等之类的工作负载都可以正常工作。该平台处理诸如 DNS、负载平衡和 SSH`kubectl exec` 取代)之类的支持服务。在我的职业生涯的大部分时间里,这些都是我在生产环境中运行的工作负载,因此,我立即意识到,除了 DevOps 之外,除了敏捷之外,使用 Kubernetes 运行生产环境工作负载的强大功能。即使是我们几乎不改变我们的文化习惯,也可以提高效率。调试和退役变得非常容易,而这对于传统 IT 来说是极为困难的。因此从早期开始Kubernetes 就用一种单一的配置语言Kube YAML/Json为我提供了对生产环境工作负载进行建模所需的所有基本原语。
但是,如果你需要运行具有复制功能的多主 MySQL会发生什么情况使用 Galera 的冗余数据呢?你如何进行快照和备份?那么像 SAP 这样复杂的工作呢?使用 Kubernetes简单的应用程序Web 服务器等)的第 0 天(部署)相当简单,但是没有解决第 2 天的运营和工作负载。这并不是说,具有复杂工作负载的第 2 天运营要比传统 IT 难解决,而是使用 Kubernetes 并没有使它们变得更容易。每个用户都要设计自己的天才想法来解决这些问题,这基本上是当今的现状。在过去的五年中,我遇到的第一类问题是复杂工作负载的第 2 天操作。LCTT 译注:在软件生命周期中,第 0 天是指软件的设计阶段;第 1 天是指软件的开发和部署阶段;第 2 天是指生产环境中的软件运维阶段。)
值得庆幸的是,随着 Kubernetes <ruby>运维器<rt>Operator</rt></ruby>的出现,这种情况正在改变。随着运维器的出现,我们现在有了一个框架,可以将第 2 天的运维知识汇总到平台中。现在,我们可以应用我在 [Kubernetes 基础:首先学习如何使用][4] 中描述的相同的定义状态、实际状态的方法,现在我们可以定义、自动化和维护各种各样的系统管理任务。
LCTT 译注: Operator 是 Kubernetes 中的一种可以完成运维工程师的特定工作的组件,业界大多没有翻译这个名词,此处仿运维工程师例首倡翻译为“运维器”。)
我经常将运维器称为“系统管理机器人”,因为它们实质上是在第 2 天的工作中整理出一堆运维知识,该知识涉及<ruby>主题专家<rt>Subject Matter Expert</rt></ruby>SME、例如数据库管理员或系统管理员针对的工作负载类型数据库、Web 服务器等),通常会记录在 Wiki 中的某个地方。这些知识放在 Wiki 中的问题是,为了将该知识应用于解决问题,我们需要:
1. 生成事件,通常监控系统会发现故障,然后我们创建故障单
2. SME 人员必须对此问题进行调查,即使这是我们之前见过几百万次的问题
3. SME 人员必须执行该知识(执行备份/还原、配置 Galera 或事务复制等)
通过运维器,所有这些 SME 知识都可以嵌入到单独的容器镜像中,该镜像在有实际工作负荷之前就已部署。 我们部署运维器容器然后运维器部署和管理一个或多个工作负载实例。然后我们使用“运维器生命周期管理器”Katacoda 教程)之类的方法来管理运维器。
因此,随着我们进一步使用 Kubernetes我们不仅简化了应用程序的部署而且简化了整个生命周期的管理。运维器还为我们提供了工具可以管理具有深层配置要求群集、复制、修复、备份/还原)的非常复杂的有状态应用程序。而且,最好的地方是,构建容器的人员可能是做第 2 天运维的主题专家,因此现在他们可以将这些知识嵌入到操作环境中。
### 本系列的总结
Kubernetes 的未来是光明的,就像之前的虚拟化一样,工作负载的扩展是不可避免的。学习如何驾驭 Kubernetes 可能是开发人员或系统管理员可以对自己的职业发展做出的最大投资。随着工作负载的增多,职业机会也将增加。因此,这是驾驶一辆令人惊叹的 [在移动垃圾时非常优雅的翻斗车][2]……
你可能想在 Twitter 上关注我,我在 [@fatherlinux][6] 上分享有关此主题的很多内容。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/6/kubernetes-potential-run-anything
作者:[Scott McCarty][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/fatherlinux
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/fail_progress_cycle_momentum_arrow.png?itok=q-ZFa_Eh (arrows cycle symbol for failing faster)
[2]: https://opensource.com/article/19/6/kubernetes-dump-truck
[3]: https://opensource.com/article/19/6/kubernetes-learning-curve
[4]: https://opensource.com/article/19/6/kubernetes-basics
[5]: https://opensource.com/article/19/6/tools-drive-kubernetes
[6]: https://twitter.com/fatherlinux

View File

@@ -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)
你需要知道什么才能成为系统管理员?
======
> 通过获得这些起码的能力,开始你的系统管理员职业。
![](https://img.linux.net.cn/data/attachment/album/201911/24/103900w5m09jyyyeyrnovu.jpg)
昔日的系统管理员整天都在调教用户和摆弄服务器,一天的时间都奔波在几百米长的电缆之间。随着云计算、容器和虚拟机的复杂性的增加,而今依然如此。
以外行人来看,很难准确确定系统管理员的确切职能,因为他们在许多地方都扮演着一个不起眼的角色。没人能在培训中知道自己工作中所需要的一切知识,但是每个人其实都需要一个坚实的基础。如果你想走上系统管理的道路,那么这是你个人自学或在正式培训中应重点关注的内容。
### 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

View File

@@ -0,0 +1,322 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11553-1.html)
[#]: subject: (Linux permissions 101)
[#]: via: (https://opensource.com/article/19/8/linux-permissions-101)
[#]: author: (Alex Juarez https://opensource.com/users/mralexjuarezhttps://opensource.com/users/marcobravohttps://opensource.com/users/greg-p)
全面介绍 Linux 权限
======
> 知道如何控制用户对文件的访问是一项基本的系统管理技能。
![](https://img.linux.net.cn/data/attachment/album/201911/08/233101y043rn4ua00r3lqn.jpg)
了解 Linux 权限以及如何控制哪些用户可以访问文件是系统管理的一项基本技能。
本文将介绍标准 Linux 文件系统权限,并进一步研究特殊权限,以及使用 `umask` 来解释默认权限作为文章的结束。
### 理解 ls 命令的输出
在讨论如何修改权限之前,我们需要知道如何查看权限。通过 `ls` 命令的长列表参数(`-l`)为我们提供了有关文件的许多信息。
```
$ ls -lAh
total 20K
-rwxr-xr--+ 1 root root    0 Mar  4 19:39 file1
-rw-rw-rw-. 1 root root    0 Mar  4 19:39 file10
-rwxrwxr--+ 1 root root    0 Mar  4 19:39 file2
-rw-rw-rw-. 1 root root    0 Mar  4 19:39 file8
-rw-rw-rw-. 1 root root    0 Mar  4 19:39 file9
drwxrwxrwx. 2 root root 4.0K Mar  4 20:04 testdir
```
为了理解这些是什么意思,让我们将关于权限的输出分解为各个部分。单独理解每个部分会更容易。
让我们看看在上面的输出中的最后一行的每个组件:
```
drwxrwxrwx. 2 root root 4.0K Mar  4 20:04 testdir
```
第 1 节 | 第 2 节 | 第 3 节 | 第 4 节 | 第 5 节 | 第 6 节 | 第 7 节
---|---|---|---|---|---|---
`d` | `rwx` | `rwx` | `rwx` | `.` | `root` | `root`
第 1 节(左侧)显示文件的类型。
符号 | 类型
---|---
`d` | 目录
`-` | 常规文件
`l` | 软链接
`ls` 的 [info 页面][2]完整列出了不同的文件类型。
每个文件都有三种访问方式:
* 属主
*
* 所有其他人
  
第 2、3 和 4 节涉及用户(属主)、组和“其他用户”权限。每个部分都可以包含 `r`(读取)、`w`(写入)和 `x`(执行)权限的组合。
每个权限还分配了一个数值,这在以八进制表示形式讨论权限时很重要。
权限 | 八进制值
---|---
`r` | 4
`w` | 2
`x` | 1
第 5 节描述了其他替代访问方法,例如 SELinux 或文件访问控制列表FACL
访问方法 | 字符
---|---
没有其它访问方法 | `-`
SELinux | `.`
FACL | `+`
各种方法的组合 | `+`
第 6 节和第 7 节分别是属主和组的名称。
### 使用 chown 和 chmod
#### chown 命令
`chown`(更改所有权)命令用于更改文件的用户和组的所有权。
要将文件 `foo` 的用户和组的所有权更改为 `root`,我们可以使用以下命令:
```
$ chown root:root foo
$ chown root: foo
```
在用户名后跟冒号(`:`)运行该命令将同时设置用户和组所有权。
要仅将文件 `foo` 的用户所有权设置为 `root` 用户,请输入:
```
$ chown root foo
```
要仅更改文件 `foo` 的组所有权,请在组之前加冒号:
```
$ chown :root foo
```
#### chmod 命令
`chmod`(更改模式)命令控制属主、组以及既不是属主也不属于与文件关联的组的所有其他用户的文件许可权。
`chmod` 命令可以以八进制(例如 `755``644` 等)和符号(例如 `u+rwx``g-rwx``o=rw`)格式设置权限。
八进制表示法将 4 个“点”分配给“读取”,将 2 个“点”分配给“写入”,将 1 个点分配给“执行”。如果要给用户(属主)分配“读取”权限,则将 4 分配给第一个插槽,但是如果要添加“写入”权限,则必须添加 2。如果要添加“执行”则要添加 1。我们对每种权限类型执行此操作属主、组和其他。
例如,如果我们想将“读取”、“写入”和“执行”分配给文件的属主,但仅将“读取”和“执行”分配给组成员和所有其他用户,则我们应使用 `755`(八进制格式)。这是属主的所有权限位(`4+2+1`),但组和其他权限的所有权限位只有 `4``1``4+1`)。
> 细分为4+2+1=74+1=5 和 4+1=5。
如果我们想将“读取”和“写入”分配给文件的属主,而只将“读取”分配给组的成员和所有其他用户,则可以如下使用 `chmod`
```
$ chmod 644 foo_file
```
在下面的示例中,我们在不同的分组中使用符号表示法。注意字母 `u``g``o` 分别代表“用户”(属主)、“组”和“其他”。我们将 `u``g``o``+``-``=` 结合使用来添加、删除或设置权限位。
要将“执行”位添加到所有权权限集中:
```
$ chmod u+x foo_file
```
要从组成员中删除“读取”、“写入”和“执行”:
```
$ chmod g-rwx foo_file
```
要将所有其他用户的所有权设置为“读取”和“写入”:
```
$ chmod o=rw
```
### 特殊位:设置 UID、设置 GID 和粘滞位
除了标准权限外,还有一些特殊的权限位,它们具有一些别的用处。
#### 设置用户 IDsuid
当在文件上设置 `suid` 时,将以文件的属主的身份而不是运行该文件的用户身份执行操作。一个[好的例子][3]是 `passwd` 命令。它需要设置 `suid` 位,以便更改密码的操作具有 root 权限。
```
$ ls -l /bin/passwd
-rwsr-xr-x. 1 root root 27832 Jun 10  2014 /bin/passwd
```
设置 `suid` 位的示例:
```
$ chmod u+s /bin/foo_file_name
```
#### 设置组 IDsgid
`sgid` 位与 `suid` 位类似,操作是在目录的组所有权下完成的,而不是以运行命令的用户身份。
一个使用 `sgid` 的例子是,如果多个用户正在同一个目录中工作,并且目录中创建的每个文件都需要具有相同的组权限。下面的示例创建一个名为 `collab_dir` 的目录,设置 `sgid` 位,并将组所有权更改为 `webdev`
```
$ mkdir collab_dir
$ chmod g+s collab_dir
$ chown :webdev collab_dir
```
现在,在该目录中创建的任何文件都将具有 `webdev` 的组所有权,而不是创建该文件的用户的组。
```
$ cd collab_dir
$ touch file-sgid
$ ls -lah file-sgid
-rw-r--r--. 1 root webdev 0 Jun 12 06:04 file-sgid
```
#### “粘滞”位
粘滞位表示,只有文件所有者才能删除该文件,即使组权限允许该文件可以删除。通常,在 `/tmp` 这样的通用或协作目录上,此设置最有意义。在下面的示例中,“所有其他人”权限集的“执行”列中的 `t` 表示已应用粘滞位。
```
$ ls -ld /tmp
drwxrwxrwt. 8 root root 4096 Jun 12 06:07 /tmp/
```
请记住这不会阻止某个人编辑该文件它只是阻止他们删除该目录的内容LCTT 译注:即删除目录下文件)。
我们将粘滞位设置为:
```
$ chmod o+t foo_dir
```
你可以自己尝试在目录上设置粘滞位并赋予其完整的组权限,以便多个属于同一组的用户可以在目录上进行读取、写入和执行。
接着,以每个用户的身份创建文件,然后尝试以另一个用户的身份删除它们。
如果一切配置正确,则一个用户应该不能从另一用户那里删除文件。
请注意这些位中的每个位也可以用八进制格式设置SUID = 4、SGID = 2 和 粘滞位 = 1。LCTT 译注:这里是四位八进制数字)
```
$ chmod 4744
$ chmod 2644
$ chmod 1755
```
#### 大写还是小写?
如果要设置特殊位时看到大写的 `S``T` 而不是小写的字符(如我们之前所见),那是因为不存在(对应的)底层的执行位。为了说明这一点,下面的示例创建一个设置了粘滞位的文件。然后,我们可以添加和删除执行位以演示大小写更改。
```
$ touch file cap-ST-demo
$ chmod 1755 cap-ST-demo
$ ls -l cap-ST-demo
-rwxr-xr-t. 1 root root 0 Jun 12 06:16 cap-ST-demo
$ chmod o-x cap-X-demo
$ ls -l cap-X-demo
-rwxr-xr-T. 1 root root 0 Jun 12 06:16 cap-ST-demo
```
#### 有条件地设置执行位
至此,我们使用小写的 `x` 设置了执行位,而无需询问任何问题即可对其进行设置。我们还有另一种选择:使用大写的 `X` 而不是小写的,它将仅在权限组中某个位置已经有执行位时才设置执行位。这可能是一个很难解释的概念,但是下面的演示将帮助说明它。请注意,在尝试将执行位添加到组特权之后,该位没有被设置上。
```
$ touch cap-X-file
$ ls -l cap-X-file
-rw-r--r--. 1 root root 0 Jun 12 06:31 cap-X-file
$ chmod g+X cap-X-file
$ ls -l cap-X-file
-rw-r--r--. 1 root root 0 Jun 12 06:31 cap-X-file
```
在这个类似的例子中,我们首先使用小写的 `x` 将执行位添加到组权限,然后使用大写的 `X` 为所有其他用户添加权限。这次,大写的 `X`设置了该权限。
```
$ touch cap-X-file
$ ls -l cap-X-file
-rw-r--r--. 1 root root 0 Jun 12 06:31 cap-X-file
$ chmod g+x cap-X-file
$ ls -l cap-X-file
-rw-r-xr--. 1 root root 0 Jun 12 06:31 cap-X-file
$ chmod o+X cap-X-file
ls -l cap-X-file
-rw-r-xr-x. 1 root root 0 Jun 12 06:31 cap-X-file
```
### 理解 umask
`umask` 会屏蔽(或“阻止”)默认权限集中的位,以定义文件或目录的权限。例如,`umask`输出中的 `2` 表示它至少在默认情况下阻止了文件的“写入”位。
使用不带任何参数的 `umask` 命令可以使我们看到当前的 `umask` 设置。共有四列:第一列为特殊的`suid``sgid` 或粘滞位而保留,其余三列代表属主、组和其他人的权限。
```
$ umask
0022
```
为了理解这意味着什么,我们可以用 `-S` 标志来执行 `umask`(如下所示)以解释屏蔽位的结果。例如,由于第三列中的值为 `2`,因此将“写入”位从组和其他部分中屏蔽掉了;只能为它们分配“读取”和“执行”。
```
$ umask -S
u=rwx,g=rx,o=rx
```
要查看文件和目录的默认权限集是什么,让我们将 `umask` 设置为全零。这意味着我们在创建文件时不会掩盖任何位。
```
$ umask 000
$ umask -S
u=rwx,g=rwx,o=rwx
$ touch file-umask-000
$ ls -l file-umask-000
-rw-rw-rw-. 1 root root 0 Jul 17 22:03 file-umask-000
```
现在,当我们创建文件时,我们看到所有部分的默认权限分别为“读取”(`4`)和“写入”(`2`),相当于八进制表示 `666`
我们可以对目录执行相同的操作,并看到其默认权限为 `777`。我们需要在目录上使用“执行”位,以便可以遍历它们。
```
$ mkdir dir-umask-000
$ ls -ld dir-umask-000
drwxrwxrwx. 2 root root 4096 Jul 17 22:03 dir-umask-000/
```
### 总结
管理员还有许多其他方法可以控制对系统文件的访问。这些权限是 Linux 的基本权限,我们可以在这些基础上进行构建。如果你的工作为你引入了 FACL 或 SELinux你会发现它们也建立在这些文件访问的首要规则之上。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/8/linux-permissions-101
作者:[Alex Juarez][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/mralexjuarezhttps://opensource.com/users/marcobravohttps://opensource.com/users/greg-p
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux-penguins.png?itok=yKOpaJM_ (Penguins)
[2]: https://www.gnu.org/software/texinfo/manual/info-stnd/info-stnd.html
[3]: https://www.theurbanpenguin.com/using-a-simple-c-program-to-explain-the-suid-permission/

View File

@@ -0,0 +1,131 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11556-1.html)
[#]: subject: (11 Essential Keyboard Shortcuts Google Chrome/Chromium Users Should Know)
[#]: via: (https://itsfoss.com/google-chrome-shortcuts/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
Chrome/Chromium 用户必知必会的 11 个基本快捷键
======
> 掌握这些 Google Chrome 键盘快捷键,以获得更好、更流畅、更高效的 Web 浏览体验。还包括可下载的备忘单。
![](https://img.linux.net.cn/data/attachment/album/201911/09/214207wh96q76ejacnn5as.png)
无可否认Google Chrome 是[最受欢迎的网络浏览器][1]。它的开源版本 [Chromium][2] 也越来越受欢迎,现在一些 Linux 发行版将其作为默认的网络浏览器。
如果你经常在台式机上使用它,则可以使用 Google Chrome 键盘快捷键来改善浏览体验。没有必要用你的鼠标移来移去、点来点去。只要掌握这些快捷方式,你可以节省一些时间并提高工作效率。
我这里使用的名称是 Google Chrome但是这些快捷方式同样适用于 Chromium 浏览器。
### 你应该使用的 11 个酷炫的 Chrome 键盘快捷键
如果你是专业人士,可能已经知道其中一些 Chrome 快捷方式,但是有可能你仍然可以在这里找到一些隐藏的宝石。让我们来看看。
**键盘快捷键** | **动作**
---|---
`Ctrl+T` | 打开一个新标签页
`Ctrl+N` | 打开一个新窗口
`Ctrl+Shift+N` | 打开一个新无痕式窗口
`Ctrl+W` | 关闭当前标签页
`Ctrl+Shift+T` | 重新打开上一个关闭的标签页
`Ctrl+Shift+W` | 关闭窗口
`Ctrl+Tab``Ctrl+Shift+Tab` | 切换到右侧或左侧的标签页
`Ctrl+L` | 访问搜索/地址栏
`Ctrl+D` | 将网址放入书签
`Ctrl+H` | 访问浏览历史
`Ctrl+J` | 访问下载历史
`Shift+Esc` | 打开 Chrome 任务管理器
你可以[下载这份有用的 Chrome 键盘快捷键列表来作为快速参考][3]。
#### 1、用 `Ctrl+T` 打开一个新标签页
需要打开一个新标签页吗?只需同时按 `Ctrl``T` 键,你就会打开一个新标签。
#### 2、使用 `Ctrl+N` 打开一个新窗口
已经打开太多标签页?是时候打开一个新的窗口。使用 `Ctrl``N` 键打开一个新的浏览器窗口。
#### 3、使用 `Ctrl+Shift+N` 隐身
在线查询航班或酒店价格?隐身可能会有所帮助。使用 `Ctrl+Shift+N` 在 Chrome 中打开一个隐身窗口。
#### 4、使用 `Ctrl+W` 关闭标签页
使用 `Ctrl``W` 键关闭当前标签页。无需将鼠标移到顶部并寻找 `x` 按钮。
#### 5、不小心关闭了标签页用 `Ctrl+Shift+T` 重新打开
这是我最喜欢的 Google Chrome 浏览器快捷方式。当你关闭了原本不想关的标签页时,就不用再懊悔了。使用 `Ctrl+Shift+T`,它将打开最后一个关闭的选项卡。继续按此组合键,它把关闭的选项卡再次打开。
#### 6、使用 `Ctrl+Shift+W` 关闭整个浏览器窗口
完成工作了吗?是时候关闭带有所有标签页的整个浏览器窗口了。使用 `Ctrl+Shift+W` 键,浏览器窗口将消失,就像以前不存在一样。
#### 7、使用 `Ctrl+Tab` 在标签之间切换
打开的标签页太多了吗?你可以使用 `Ctrl+Tab` 移至右侧标签页。想左移吗?使用 `Ctrl+Shift+Tab`。重复按这些键,你可以在当前浏览器窗口的所有打开的标签页之间移动。
你也可以使用 `Ctrl+0` 直到 `Ctrl+9` 转到前 10 个标签页之一。但是此 Chrome 键盘快捷键不适用于第 11 个及更多标签页。
#### 8、使用 `Ctrl+L` 转到搜索/地址栏
想要输入新的 URL 或快速搜索一些内容。你可以使用 `Ctrl+L`,它将在顶部突出显示地址栏。
#### 9、用 `Ctrl+D` 收藏当前网站
找到了有趣的东西?使用 `Ctrl+D` 组合键将其保存在书签中。
#### 10、使用 `Ctrl+H` 返回历史记录
你可以使用 `Ctrl+H` 键打开浏览器历史记录。如果你正在寻找前一段时间访问过的页面,或者删除你不想再看到的页面,可以搜索历史记录。
#### 11、使用 `Ctrl+J` 查看下载
在 Chrome 中按 `Ctrl+J` 键将带你进入下载页面。此页面将显示你执行的所有下载操作。
#### 意外惊喜:使用 `Shift+Esc` 打开 Chrome 任务管理器
很多人甚至都不知道 Chrome 浏览器中有一个任务管理器。Chrome 以消耗系统内存而臭名昭著。而且,当你打开大量标签时,找到罪魁祸首并不容易。
使用 Chrome 任务管理器,你可以查看所有打开的标签页及其系统利用率统计信息。你还可以看到各种隐藏的进程,例如 Chrome 扩展程序和其他服务。
![Google Chrome 任务管理器][6]
### 下载 Chrome 快捷键备忘单
我知道掌握键盘快捷键取决于习惯,你可以通过反复使用使其习惯。为了帮助你完成此任务,我创建了此 Google Chrome 键盘快捷键备忘单。
![Google Chrome键盘快捷键备忘单][7]
你可以[下载以下 PDF 格式的图像][8],进行打印并将其放在办公桌上。这样,你可以一直练习快捷方式。
如果你对掌握快捷方式感兴趣,还可以查看 [Ubuntu 键盘快捷键][9]。
顺便问一下,你最喜欢的 Chrome 快捷方式是什么?
--------------------------------------------------------------------------------
via: https://itsfoss.com/google-chrome-shortcuts/
作者:[Abhishek Prakash][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://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://en.wikipedia.org/wiki/Usage_share_of_web_browsers
[2]: https://www.chromium.org/Home
[3]: tmp.3qZNXSy2FC#download-cheatsheet
[4]: https://itsfoss.com/command-line-text-editors-linux/
[5]: https://itsfoss.com/rid-google-chrome-icons-dock-elementary-os-freya/
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/google-chrome-task-manager.png?w=800&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/google-chrome-keyboard-shortcuts-cheat-sheet.png?ssl=1
[8]: https://drive.google.com/open?id=1lZ4JgRuFbXrnEXoDQqOt7PQH6femIe3t
[9]: https://itsfoss.com/ubuntu-shortcuts/

View File

@@ -0,0 +1,235 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11527-1.html)
[#]: subject: (How RPM packages are made: the source RPM)
[#]: via: (https://fedoramagazine.org/how-rpm-packages-are-made-the-source-rpm/)
[#]: author: (Ankur Sinha "FranciscoD" https://fedoramagazine.org/author/ankursinha/)
RPM 包是如何从源 RPM 制作的
======
![][1]
在[上一篇文章中,我们研究了什么是 RPM 软件包][2]。它们是包含文件和元数据的档案文件。当安装或卸载 RPM 时,此元数据告诉 RPM 在哪里创建或删除文件。正如你将在上一篇文章中记住的,元数据还包含有关“依赖项”的信息,它可以是“运行时”或“构建时”的依赖信息。
例如,让我们来看看 `fpaste`。你可以使用 `dnf` 下载该 RPM。这将下载 Fedora 存储库中可用的 `fpaste` 最新版本。在 Fedora 30 上,当前版本为 0.3.9.2
```
$ dnf download fpaste
...
fpaste-0.3.9.2-2.fc30.noarch.rpm
```
由于这是个构建 RPM因此它仅包含使用 `fpaste` 所需的文件:
```
$ rpm -qpl ./fpaste-0.3.9.2-2.fc30.noarch.rpm
/usr/bin/fpaste
/usr/share/doc/fpaste
/usr/share/doc/fpaste/README.rst
/usr/share/doc/fpaste/TODO
/usr/share/licenses/fpaste
/usr/share/licenses/fpaste/COPYING
/usr/share/man/man1/fpaste.1.gz
```
### 源 RPM
在此链条中的下一个环节是源 RPM。Fedora 中的所有软件都必须从其源代码构建。我们不包括预构建的二进制文件。因此,要制作一个 RPM 文件RPM工具需要
* 给出必须要安装的文件,
* 例如,如果要编译出这些文件,则告诉它们如何生成这些文件,
* 告知必须在何处安装这些文件,
* 该特定软件需要其他哪些依赖才能正常工作。
源 RPM 拥有所有这些信息。源 RPM 与构建 RPM 相似,但顾名思义,它们不包含已构建的二进制文件,而是包含某个软件的源文件。让我们下载 `fpaste` 的源 RPM
```
$ dnf download fpaste --source
...
fpaste-0.3.9.2-2.fc30.src.rpm
```
注意文件的结尾是 `src.rpm`。所有的 RPM 都是从源 RPM 构建的。你也可以使用 `dnf` 轻松检查“二进制” RPM 的源 RPM
```
$ dnf repoquery --qf "%{SOURCERPM}" fpaste
fpaste-0.3.9.2-2.fc30.src.rpm
```
另外,由于这是源 RPM因此它不包含构建的文件。相反它包含有关如何从中构建 RPM 的源代码和指令:
```
$ rpm -qpl ./fpaste-0.3.9.2-2.fc30.src.rpm
fpaste-0.3.9.2.tar.gz
fpaste.spec
```
这里,第一个文件只是 `fpaste` 的源代码。第二个是 spec 文件。spec 文件是个配方,可告诉 RPM工具如何使用源 RPM 中包含的源代码创建 RPM档案文件— 它包含 RPM工具构建 RPM档案文件所需的所有信息。在 spec 文件中。当我们软件包维护人员添加软件到 Fedora 中时,我们大部分时间都花在编写和完善 spec 文件上。当软件包需要更新时,我们会回过头来调整 spec 文件。你可以在 <https://src.fedoraproject.org/browse/projects/> 的源代码存储库中查看 Fedora 中所有软件包的 spec 文件。
请注意,一个源 RPM 可能包含构建多个 RPM 的说明。`fpaste` 是一款非常简单的软件,一个源 RPM 生成一个“二进制” RPM。而 Python 则更复杂。虽然只有一个源 RPM但它会生成多个二进制 RPM
```
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3
python3-3.7.3-1.fc30.src.rpm
python3-3.7.4-1.fc30.src.rpm
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-devel
python3-3.7.3-1.fc30.src.rpm
python3-3.7.4-1.fc30.src.rpm
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-libs
python3-3.7.3-1.fc30.src.rpm
python3-3.7.4-1.fc30.src.rpm
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-idle
python3-3.7.3-1.fc30.src.rpm
python3-3.7.4-1.fc30.src.rpm
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-tkinter
python3-3.7.3-1.fc30.src.rpm
python3-3.7.4-1.fc30.src.rpm
```
用 RPM 行话来讲“python3” 是“主包”,因此该 spec 文件将称为 `python3.spec`。所有其他软件包均为“子软件包”。你可以下载 python3 的源 RPM并查看其中的内容。提示补丁也是源代码的一部分
```
$ dnf download --source python3
python3-3.7.4-1.fc30.src.rpm
$ rpm -qpl ./python3-3.7.4-1.fc30.src.rpm
00001-rpath.patch
00102-lib64.patch
00111-no-static-lib.patch
00155-avoid-ctypes-thunks.patch
00170-gc-assertions.patch
00178-dont-duplicate-flags-in-sysconfig.patch
00189-use-rpm-wheels.patch
00205-make-libpl-respect-lib64.patch
00251-change-user-install-location.patch
00274-fix-arch-names.patch
00316-mark-bdist_wininst-unsupported.patch
Python-3.7.4.tar.xz
check-pyc-timestamps.py
idle3.appdata.xml
idle3.desktop
python3.spec
```
### 从源 RPM 构建 RPM
现在我们有了源 RPM并且其中有什么内容我们可以从中重建 RPM。但是在执行此操作之前我们应该设置系统以构建 RPM。首先我们安装必需的工具
```
$ sudo dnf install fedora-packager
```
这将安装 `rpmbuild` 工具。`rpmbuild` 需要一个默认布局,以便它知道源 RPM 中每个必需组件的位置。让我们看看它们是什么:
```
# spec 文件将出现在哪里?
$ rpm -E %{_specdir}
/home/asinha/rpmbuild/SPECS
# 源代码将出现在哪里?
$ rpm -E %{_sourcedir}
/home/asinha/rpmbuild/SOURCES
# 临时构建目录是哪里?
$ rpm -E %{_builddir}
/home/asinha/rpmbuild/BUILD
# 构建根目录是哪里?
$ rpm -E %{_buildrootdir}
/home/asinha/rpmbuild/BUILDROOT
# 源 RPM 将放在哪里?
$ rpm -E %{_srcrpmdir}
/home/asinha/rpmbuild/SRPMS
# 构建的 RPM 将放在哪里?
$ rpm -E %{_rpmdir}
/home/asinha/rpmbuild/RPMS
```
我已经在系统上设置了所有这些目录:
```
$ cd
$ tree -L 1 rpmbuild/
rpmbuild/
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
6 directories, 0 files
```
RPM 还提供了一个为你全部设置好的工具:
```
$ rpmdev-setuptree
```
然后,确保已安装 `fpaste` 的所有构建依赖项:
```
sudo dnf builddep fpaste-0.3.9.2-3.fc30.src.rpm
```
对于 `fpaste`,你只需要 Python并且它肯定已经安装在你的系统上`dnf` 也使用 Python。还可以给 `builddep` 命令一个 spec 文件,而不是源 RPM。在手册页中了解更多信息
```
$ man dnf.plugin.builddep
```
现在我们有了所需的一切,从源 RPM 构建一个 RPM 就像这样简单:
```
$ rpmbuild --rebuild fpaste-0.3.9.2-3.fc30.src.rpm
..
..
$ tree ~/rpmbuild/RPMS/noarch/
/home/asinha/rpmbuild/RPMS/noarch/
└── fpaste-0.3.9.2-3.fc30.noarch.rpm
0 directories, 1 file
```
`rpmbuild` 将安装源 RPM 并从中构建你的 RPM。现在你可以使用 `dnf` 安装 RPM 以使用它。当然,如前所述,如果你想在 RPM 中进行任何更改,则必须修改 spec 文件,我们将在下一篇文章中介绍 spec 文件。
### 总结
总结一下这篇文章有两点:
* 我们通常安装使用的 RPM 是包含软件的构建版本的 “二进制” RPM
* 构建 RPM 来自于源 RPM源 RPM 包括用于生成二进制 RPM 所需的源代码和规范文件。
如果你想开始构建 RPM并帮助 Fedora 社区维护我们提供的大量软件,则可以从这里开始: <https://fedoraproject.org/wiki/Join_the_package_collection_maintainers>
如有任何疑问,请发邮件到 [Fedora 开发人员邮件列表][3],我们随时乐意为你提供帮助!
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/how-rpm-packages-are-made-the-source-rpm/
作者:[Ankur Sinha "FranciscoD"][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://fedoramagazine.org/author/ankursinha/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2019/06/rpm.png-816x345.jpg
[2]: https://linux.cn/article-11452-1.html
[3]: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/

View File

@@ -0,0 +1,84 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11529-1.html)
[#]: subject: (Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word)
[#]: via: (https://itsfoss.com/gimp-fork-glimpse/)
[#]: author: (John Paul https://itsfoss.com/author/john/)
由于 GIMP 是令人反感的字眼,有人将它复刻了
======
在开源应用程序世界中,当社区成员希望以与其他人不同的方向来开发应用程序时,<ruby>复刻<rt>fork</rt></ruby>是很常见的。最新的具有新闻价值的一个复刻称为 [Glimpse][1],旨在解决用户在使用 <ruby>[GNU 图像处理程序][2]<rt>GNU Image Manipulation Program</rt></ruby>(通常称为 GIMP时遇到的某些问题。
### 为什么创建 GIMP 的复刻?
![][3]
当你访问 Glimpse 应用的[主页][1]时,它表示该项目的目标是“尝试其他设计方向并修复长期存在的错误。”这听起来并不奇怪。但是,如果你开始阅读该项目的博客文章,则是另外一种印象。
根据该项目的[第一篇博客文章][4],他们创建了这个复刻是因为他们不喜欢 GIMP 这个名称。根据该帖子,“我们中的许多人不认为该软件的名称适用于所有用户,并且在拒绝该项目的 13 年后,我们决定复刻!”
如果你想知道为什么这些人认为 GIMP 令人讨厌,他们在[关于页面][5]中回答该问题:
> “如果英语不是你的母语,那么你可能没有意识到 gimp 一词有问题。在某些国家,这被视为针对残疾人的侮辱和针对不受欢迎儿童的操场侮辱。它也可以与成年人同意的某些‘天黑后’活动联系起来。”
他们还指出,他们并没有使这一举动脱离政治正确或过于敏感。“除了可能给边缘化社区带来的痛苦外,我们当中许多人都有过倡导自由软件的故事,比如在 GNU 图像处理程序没有被专业环境中的老板或同事视为可选项这件事上。”
他们似乎在回答许多质疑,“不幸的是,我们不得不复刻整个项目来更改其名称,我们认为有关此问题的讨论陷入了僵局,而这是最积极的前进方向。 ”
看起来 Glimpse 这个名称不是确定不变的。他们的 GitHub 页面上有个关于可能选择其他名称的[提案][7]。也许他们应该放弃 GNU 这个词,我认为 IMP 这个词没有不好的含义。LCTT 译注:反讽)
### 分叉之路
![GIMP 2.10][8]
[GIMP][6] 已经存在了 20 多年,因此任何形式的复刻都是一项艰巨的任务。当前,[他们正在计划][9]首先在 2019 年 9 月发布 Glimpse 0.1。这将是一个软复刻这意味着在迁移到新身份时的更改将主要是装饰性的。LCTT 译注:事实上到本译文发布时,该项目仍然处于蛋疼的 0.1 beta也许 11 月,也许 12 月,才能发布 0.1 的正式版本。)
Glimpse 1.0 将是一个硬复刻,他们将积极更改代码库并将其添加到代码库中。他们想将 1.0 移植到 GTK3 并拥有自己的文档。他们估计,直到 2020 年 GIMP 3 发布之后才能做到。
除了 1.0Glimpse 团队还计划打响自己的名声。他们计划进行“前端 UI 重写”。他们目前正在讨论[改用哪种语言][10]。D 和 Rust 似乎有很多支持者。随着时间的流逝,他们也[希望][4]“添加新功能以解决普通用户的抱怨”。
### 最后的思考
我过去曾经使用过一点 GIMP但从来没有对它的名称感到困扰。老实说我很长一段时间都不知道这意味着什么。有趣的是当我在 Wikipedia 上搜索 GIMP 时,看到了一个 [GIMP 项目][11]的条目,这是纽约的一个现代舞蹈项目,其中包括残疾人。我想 gimp 并不是每个人视为一个贬低词汇的。
对我来说,更改名称似乎需要大量工作。似乎改写 UI 的想法会使项目看起来更有价值一些。我想知道他们是否会调整它以带来更经典的 UI例如[使用 Ctrl + S 保存到 GIMP][12] / Glimpse。让我们拭目以待。
如果你对该项目感兴趣,可以在 [Twitter][14] 上关注他们,查看其 [GitHub 帐户][15],或查看其 [Patreon 页面][16]。
你觉得被 GIMP 名称冒犯了吗?你是否认为值得对应用程序进行复刻,以便你可以对其进行重命名?在下面的评论中让我们知道。
如果你觉得这篇文章有趣请花一点时间在社交媒体、Hacker News 或 [Reddit][17] 上分享。
--------------------------------------------------------------------------------
via: https://itsfoss.com/gimp-fork-glimpse/
作者:[John Paul][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://itsfoss.com/author/john/
[b]: https://github.com/lujun9972
[1]: https://getglimpse.app/
[2]: https://www.gimp.org/
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/08/gimp-fork-glimpse.png?resize=800%2C450&ssl=1
[4]: https://getglimpse.app/posts/so-it-begins/
[5]: https://getglimpse.app/about/
[6]: https://itsfoss.com/gimp-2-10-release/
[7]: https://github.com/glimpse-editor/Glimpse/issues/92
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/08/gimp-screenshot.jpg?resize=800%2C508&ssl=1
[9]: https://getglimpse.app/posts/six-week-checkpoint/
[10]: https://github.com/glimpse-editor/Glimpse/issues/70
[11]: https://en.wikipedia.org/wiki/The_Gimp_Project
[12]: https://itsfoss.com/how-to-solve-gimp-2-8-does-not-save-in-jpeg-or-png-format/
[13]: https://itsfoss.com/wps-office-2016-linux/
[14]: https://twitter.com/glimpse_editor
[15]: https://github.com/glimpse-editor/Glimpse
[16]: https://www.patreon.com/glimpse
[17]: https://reddit.com/r/linuxusersgroup

View File

@@ -0,0 +1,289 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11538-1.html)
[#]: subject: (How RPM packages are made: the spec file)
[#]: via: (https://fedoramagazine.org/how-rpm-packages-are-made-the-spec-file/)
[#]: author: (Ankur Sinha "FranciscoD" https://fedoramagazine.org/author/ankursinha/)
如何编写 RPM 的 spec 文件
======
![][1]
在[关于 RPM 软件包构建的上一篇文章][2]中,你了解到了源 RPM 包括软件的源代码以及 spec 文件。这篇文章深入研究了 spec 文件,该文件中包含了有关如何构建 RPM 的指令。同样,本文以 `fpaste` 为例。
### 了解源代码
在开始编写 spec 文件之前,你需要对要打包的软件有所了解。在这里,你正在研究 `fpaste`,这是一个非常简单的软件。它是用 Python 编写的,并且是一个单文件脚本。当它发布新版本时,可在 Pagure 上找到:<https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz>。
如该档案文件所示,当前版本为 0.3.9.2。下载它,以便你查看该档案文件中的内容:
```
$ wget https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz
$ tar -tvf fpaste-0.3.9.2.tar.gz
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/
-rw-rw-r-- root/root 25 2018-07-25 02:58 fpaste-0.3.9.2/.gitignore
-rw-rw-r-- root/root 3672 2018-07-25 02:58 fpaste-0.3.9.2/CHANGELOG
-rw-rw-r-- root/root 35147 2018-07-25 02:58 fpaste-0.3.9.2/COPYING
-rw-rw-r-- root/root 444 2018-07-25 02:58 fpaste-0.3.9.2/Makefile
-rw-rw-r-- root/root 1656 2018-07-25 02:58 fpaste-0.3.9.2/README.rst
-rw-rw-r-- root/root 658 2018-07-25 02:58 fpaste-0.3.9.2/TODO
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/en/
-rw-rw-r-- root/root 3867 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/en/fpaste.1
-rwxrwxr-x root/root 24884 2018-07-25 02:58 fpaste-0.3.9.2/fpaste
lrwxrwxrwx root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/fpaste.py -> fpaste
```
你要安装的文件是:
* `fpaste.py`:应该安装到 `/usr/bin/`
* `docs/man/en/fpaste.1`:手册,应放到 `/usr/share/man/man1/`
* `COPYING`:许可证文本,应放到 `/usr/share/license/fpaste/`
* `README.rst``TODO`:放到 `/usr/share/doc/fpaste/` 下的其它文档。
这些文件的安装位置取决于文件系统层次结构标准FHS。要了解更多信息可以在这里阅读<http://www.pathname.com/fhs/> 或查看 Fedora 系统的手册页:
```
$ man hier
```
#### 第一部分:要构建什么?
现在我们知道了源文件中有哪些文件,以及它们要存放的位置,让我们看一下 spec 文件。你可以在此处查看这个完整的文件:<https://src.fedoraproject.org/rpms/fpaste/blob/master/f/fpaste.spec>。
这是 spec 文件的第一部分:
```
Name: fpaste
Version: 0.3.9.2
Release: 3%{?dist}
Summary: A simple tool for pasting info onto sticky notes instances
BuildArch: noarch
License: GPLv3+
URL: https://pagure.io/fpaste
Source0: https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz
Requires: python3
%description
It is often useful to be able to easily paste text to the Fedora
Pastebin at http://paste.fedoraproject.org and this simple script
will do that and return the resulting URL so that people may
examine the output. This can hopefully help folks who are for
some reason stuck without X, working remotely, or any other
reason they may be unable to paste something into the pastebin
```
`Name``Version` 等称为*标签*,它们定义在 RPM 中。这意味着你不能只是随意写点标签RPM 无法理解它们!需要注意的标签是:
* `Source0`:告诉 RPM 该软件的源代码档案文件所在的位置。
* `Requires`列出软件的运行时依赖项。RPM 可以自动检测很多依赖项,但是在某些情况下,必须手动指明它们。运行时依赖项是系统上必须具有的功能(通常是软件包),才能使该软件包起作用。这是 [dnf][3] 在安装此软件包时检测是否需要拉取其他软件包的方式。
* `BuildRequires`:列出了此软件的构建时依赖项。这些通常必须手动确定并添加到 spec 文件中。
* `BuildArch`:此软件为该计算机体系结构所构建。如果省略此标签,则将为所有受支持的体系结构构建该软件。值 `noarch` 表示该软件与体系结构无关(例如 `fpaste`,它完全是用 Python 编写的)。
本节提供有关 `fpaste` 的常规信息:它是什么,正在将什么版本制作为 RPM其许可证等等。如果你已安装 `fpaste`,并查看其元数据时,则可以看到该 RPM 中包含的以下信息:
```
$ sudo dnf install fpaste
$ rpm -qi fpaste
Name : fpaste
Version : 0.3.9.2
Release : 2.fc30
...
```
RPM 会自动添加一些其他标签,以代表它所知道的内容。
至此,我们掌握了要为其构建 RPM 的软件的一般信息。接下来,我们开始告诉 RPM 做什么。
#### 第二部分:准备构建
spec 文件的下一部分是准备部分,用 `prep` 代表:
```
%prep
%autosetup
```
对于 `fpaste`,这里唯一的命令是 `autosetup`。这只是将 tar 档案文件提取到一个新文件夹中,并为下一部分的构建阶段做好了准备。你可以在此处执行更多操作,例如应用补丁程序,出于不同目的修改文件等等。如果你查看过 Python 的源 RPM 的内容,那么你会在那里看到许多补丁。这些都将在本节中应用。
通常spec 文件中带有 `` 前缀的所有内容都是 RPM 以特殊方式解释的宏或标签。这些通常会带有大括号,例如 `{example}`
#### 第三部分:构建软件
下一部分是构建软件的位置,用 `build` 表示。现在,由于 `fpaste` 是一个简单的纯 Python 脚本,因此无需构建。因此,这里是:
```
%build
#nothing required
```
不过,通常来说,你会在此处使用构建命令,例如:
```
configure; make
```
构建部分通常是 spec 文件中最难的部分因为这是从源代码构建软件的地方。这要求你知道该工具使用的是哪个构建系统该系统可能是许多构建系统之一Autotools、CMake、Meson、Setuptools用于 Python等等。每个都有自己的命令和语法样式。你需要充分了解这些才能正确构建软件。
#### 第四部分:安装文件
软件构建后,需要在 `install` 部分中安装它:
```
%install
mkdir -p %{buildroot}%{_bindir}
make install BINDIR=%{buildroot}%{_bindir} MANDIR=%{buildroot}%{_mandir}
```
在构建 RPM 时RPM 不会修改你的系统文件。在一个可以正常运行的系统上添加、删除或修改文件的风险太大。如果发生故障怎么办因此RPM 会创建一个专门打造的文件系统并在其中工作。这称为 `buildroot`。 因此,在 `buildroot` 中,我们创建由宏 `{_bindir}` 代表的 `/usr/bin` 目录,然后使用提供的 `Makefile` 将文件安装到其中。
至此,我们已经在专门打造的 `buildroot` 中安装了 `fpaste` 的构建版本。
#### 第五部分:列出所有要包括在 RPM 中的文件
spec 文件其后的一部分是文件部分:`files`。在这里,我们告诉 RPM 从该 spec 文件创建的档案文件中包含哪些文件。`fpaste` 的文件部分非常简单:
```
%files
%{_bindir}/%{name}
%doc README.rst TODO
%{_mandir}/man1/%{name}.1.gz
%license COPYING
```
请注意,在这里,我们没有指定 `buildroot`。所有这些路径都是相对路径。`doc``license`命令做的稍微多一点,它们会创建所需的文件夹,并记住这些文件必须放在那里。
RPM 很聪明。例如,如果你在 `install` 部分中安装了文件,但未列出它们,它会提醒你。
#### 第六部分:在变更日志中记录所有变更
Fedora 是一个基于社区的项目。许多贡献者维护或共同维护软件包。因此当务之急是不要被软件包做了哪些更改所搞混。为了确保这一点spec 文件包含的最后一部分是变更日志 `changelog`
```
%changelog
* Thu Jul 25 2019 Fedora Release Engineering < ...> - 0.3.9.2-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Jan 31 2019 Fedora Release Engineering < ...> - 0.3.9.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Jul 24 2018 Ankur Sinha - 0.3.9.2-1
- Update to 0.3.9.2
* Fri Jul 13 2018 Fedora Release Engineering < ...> - 0.3.9.1-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Wed Feb 07 2018 Fedora Release Engineering < ..> - 0.3.9.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Sun Sep 10 2017 Vasiliy N. Glazov < ...> - 0.3.9.1-2
- Cleanup spec
* Fri Sep 08 2017 Ankur Sinha - 0.3.9.1-1
- Update to latest release
- fixes rhbz 1489605
...
....
```
spec 文件的*每项*变更都必须有一个变更日志条目。如你在此处看到的,虽然我以维护者身份更新了该 spec 文件,但其他人也做过更改。清楚地记录变更内容有助于所有人知道该 spec 文件的当前状态。对于系统上安装的所有软件包,都可以使用 `rpm` 来查看其更改日志:
```
$ rpm -q --changelog fpaste
```
### 构建 RPM
现在我们准备构建 RPM 包。如果要继续执行以下命令,请确保遵循[上一篇文章][2]中的步骤设置系统以构建 RPM。
我们将 `fpaste` 的 spec 文件放置在 `~/rpmbuild/SPECS` 中,将源代码档案文件存储在 `~/rpmbuild/SOURCES/` 中,现在可以创建源 RPM 了:
```
$ cd ~/rpmbuild/SPECS
$ wget https://src.fedoraproject.org/rpms/fpaste/raw/master/f/fpaste.spec
$ cd ~/rpmbuild/SOURCES
$ wget https://pagure.io/fpaste/archive/0.3.9.2/fpaste-0.3.9.2.tar.gz
$ cd ~/rpmbuild/SOURCES
$ rpmbuild -bs fpaste.spec
Wrote: /home/asinha/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
```
让我们看一下结果:
```
$ ls ~/rpmbuild/SRPMS/fpaste*
/home/asinha/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
$ rpm -qpl ~/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
fpaste-0.3.9.2.tar.gz
fpaste.spec
```
我们看到源 RPM 已构建。让我们同时构建源 RPM 和二进制 RPM
```
$ cd ~/rpmbuild/SPECS
$ rpmbuild -ba fpaste.spec
..
..
..
```
RPM 将向你显示完整的构建输出,并在我们之前看到的每个部分中详细说明它的工作。此“构建日志”非常重要。当构建未按预期进行时,我们的打包人员将花费大量时间来遍历它们,以跟踪完整的构建路径来查看出了什么问题。
就是这样!准备安装的 RPM 应该位于以下位置:
```
$ ls ~/rpmbuild/RPMS/noarch/
fpaste-0.3.9.2-3.fc30.noarch.rpm
```
### 概括
我们已经介绍了如何从 spec 文件构建 RPM 的基础知识。这绝不是一份详尽的文档。实际上,它根本不是文档。它只是试图解释幕后的运作方式。简短回顾一下:
* RPM 有两种类型:源 RPM 和 二进制 RPM。
* 二进制 RPM 包含要安装以使用该软件的文件。
* 源 RPM 包含构建二进制 RPM 所需的信息:完整的源代码,以及 spec 文件中的有关如何构建 RPM 的说明。
* spec 文件包含多个部分,每个部分都有其自己的用途。
  
在这里,我们已经在安装好的 Fedora 系统中本地构建了 RPM。虽然这是个基本的过程但我们从存储库中获得的 RPM 是建立在具有严格配置和方法的专用服务器上的,以确保正确性和安全性。这个 Fedora 打包流程将在以后的文章中讨论。
你想开始构建软件包,并帮助 Fedora 社区维护我们提供的大量软件吗?你可以[从这里开始加入软件包集合维护者][4]。
如有任何疑问,请发布到 [Fedora 开发人员邮件列表][5],我们随时乐意为你提供帮助!
### 参考
这里有一些构建 RPM 的有用参考:
* <https://fedoraproject.org/wiki/How_to_create_an_RPM_package>
* <https://docs.fedoraproject.org/en-US/quick-docs/create-hello-world-rpm/>
* <https://docs.fedoraproject.org/en-US/packaging-guidelines/>
* <https://rpm.org/documentation.html>
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/how-rpm-packages-are-made-the-spec-file/
作者:[Ankur Sinha "FranciscoD"][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://fedoramagazine.org/author/ankursinha/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2019/06/rpm.png-816x345.jpg
[2]: https://linux.cn/article-11527-1.html
[3]: https://fedoramagazine.org/managing-packages-fedora-dnf/
[4]: https://fedoraproject.org/wiki/Join_the_package_collection_maintainers
[5]: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/

View File

@@ -0,0 +1,246 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11546-1.html)
[#]: subject: (Building CI/CD pipelines with Jenkins)
[#]: via: (https://opensource.com/article/19/9/intro-building-cicd-pipelines-jenkins)
[#]: author: (Bryant Son https://opensource.com/users/brson)
用 Jenkins 构建 CI/CD 流水线
======
> 通过这份 Jenkins 分步教程构建持续集成和持续交付CI/CD流水线。
![](https://img.linux.net.cn/data/attachment/album/201911/07/001349rbbbswpeqnnteeee.jpg)
在我的文章《[使用开源工具构建 DevOps 流水线的初学者指南][2]》中,我分享了一个从头开始构建 DevOps 流水线的故事。推动该计划的核心技术是 [Jenkins][3]这是一个用于建立持续集成和持续交付CI/CD流水线的开源工具。
在花旗,有一个单独的团队为专用的 Jenkins 流水线提供稳定的主从节点环境但是该环境仅用于质量保证QA、构建阶段和生产环境。开发环境仍然是非常手动的我们的团队需要对其进行自动化以在加快开发工作的同时获得尽可能多的灵活性。这就是我们决定为 DevOps 建立 CI/CD 流水线的原因。Jenkins 的开源版本由于其灵活性、开放性、强大的插件功能和易用性而成为显而易见的选择。
在本文中,我将分步演示如何使用 Jenkins 构建 CI/CD 流水线。
### 什么是流水线?
在进入本教程之前,了解有关 CI/CD <ruby>流水线<rt>pipeline</rt></ruby>的知识会很有帮助。
首先,了解 Jenkins 本身并不是流水线这一点很有帮助。只是创建一个新的 Jenkins 作业并不能构建一条流水线。可以把 Jenkins 看做一个遥控器在这里点击按钮即可。当你点击按钮时会发生什么取决于遥控器要控制的内容。Jenkins 为其他应用程序 API、软件库、构建工具等提供了一种插入 Jenkins 的方法它可以执行并自动化任务。Jenkins 本身不执行任何功能,但是随着其它工具的插入而变得越来越强大。
流水线是一个单独的概念,指的是按顺序连接在一起的事件或作业组:
> “<ruby>流水线<rt>pipeline</rt></ruby>”是可以执行的一系列事件或作业。
理解流水线的最简单方法是可视化一系列阶段,如下所示:
![Pipeline example][4]
在这里,你应该看到两个熟悉的概念:<ruby>阶段<rt>Stage</rt></ruby>和<ruby>步骤<rt>Step</rt></ruby>。
* 阶段:一个包含一系列步骤的块。阶段块可以命名为任何名称;它用于可视化流水线过程。
* 步骤:表明要做什么的任务。步骤定义在阶段块内。
在上面的示例图中,阶段 1 可以命名为 “构建”、“收集信息”或其它名称,其它阶段块也可以采用类似的思路。“步骤”只是简单地说放上要执行的内容,它可以是简单的打印命令(例如,`echo "Hello, World"`)、程序执行命令(例如,`java HelloWorld`、shell 执行命令( 例如,`chmod 755 Hello`)或任何其他命令,只要通过 Jenkins 环境将其识别为可执行命令即可。
Jenkins 流水线以**编码脚本**的形式提供,通常称为 “Jenkinsfile”尽管可以用不同的文件名。下面这是一个简单的 Jenkins 流水线文件的示例:
```
// Example of Jenkins pipeline script
pipeline {
  stages {
    stage("Build") {
      steps {
          // Just print a Hello, Pipeline to the console
          echo "Hello, Pipeline!"
          // Compile a Java file. This requires JDKconfiguration from Jenkins
          javac HelloWorld.java
          // Execute the compiled Java binary called HelloWorld. This requires JDK configuration from Jenkins
          java HelloWorld
          // Executes the Apache Maven commands, clean then package. This requires Apache Maven configuration from Jenkins
          mvn clean package ./HelloPackage
          // List the files in current directory path by executing a default shell command
          sh "ls -ltr"
      }
   }
   // And next stages if you want to define further...
  } // End of stages
} // End of pipeline
```
从此示例脚本很容易看到 Jenkins 流水线的结构。请注意,默认情况下某些命令(如 `java``javac``mvn`)不可用,需要通过 Jenkins 进行安装和配置。 因此:
> Jenkins 流水线是一种以定义的方式依次执行 Jenkins 作业的方法,方法是将其编码并在多个块中进行结构化,这些块可以包含多个任务的步骤。
好。既然你已经了解了 Jenkins 流水线是什么,我将向你展示如何创建和执行 Jenkins 流水线。在本教程的最后,你将建立一个 Jenkins 流水线,如下所示:
![Final Result][5]
### 如何构建 Jenkins 流水线
为了便于遵循本教程的步骤,我创建了一个示例 [GitHub 存储库][6]和一个视频教程。
- [视频](https://img.linux.net.cn/static/video/_-jDPwYgDVKlg.mp4)
开始本教程之前,你需要:
* Java 开发工具包JDK如果尚未安装请安装 JDK 并将其添加到环境路径中,以便可以通过终端执行 Java 命令(如 `java jar`)。这是利用本教程中使用的 Java Web ArchiveWAR版本的 Jenkins 所必需的(尽管你可以使用任何其他发行版)。
* 基本计算机操作能力:你应该知道如何键入一些代码、通过 shell 执行基本的 Linux 命令以及打开浏览器。
让我们开始吧。
#### 步骤一:下载 Jenkins
导航到 [Jenkins 下载页面][7]。向下滚动到 “Generic Java package (.war)”,然后单击下载文件;将其保存在易于找到的位置。(如果你选择其他 Jenkins 发行版,除了步骤二之外,本教程的其余步骤应该几乎相同。)使用 WAR 文件的原因是它是个一次性可执行文件,可以轻松地执行和删除。
![Download Jenkins as Java WAR file][8]
#### 步骤二:以 Java 二进制方式执行 Jenkins
打开一个终端窗口,并使用 `cd <your path>` 进入下载 Jenkins 的目录。(在继续之前,请确保已安装 JDK 并将其添加到环境路径。)执行以下命令,该命令将 WAR 文件作为可执行二进制文件运行:
```
java -jar ./jenkins.war
```
如果一切顺利Jenkins 应该在默认端口 8080 上启动并运行。
![Execute as an executable JAR binary][9]
#### 步骤三:创建一个新的 Jenkins 作业
打开一个 Web 浏览器并导航到 `localhost:8080`。除非你有以前安装的 Jenkins否则应直接转到 Jenkins 仪表板。点击 “Create New Jobs”。你也可以点击左侧的 “New Item”。
![Create New Job][10]
#### 步骤四:创建一个流水线作业
在此步骤中,你可以选择并定义要创建的 Jenkins 作业类型。选择 “Pipeline” 并为其命名例如“TestPipeline”。单击 “OK” 创建流水线作业。
![Create New Pipeline Job][11]
你将看到一个 Jenkins 作业配置页面。向下滚动以找到 “Pipeline” 部分。有两种执行 Jenkins 流水线的方法。一种方法是在 Jenkins 上直接编写流水线脚本,另一种方法是从 SCM源代码管理中检索 Jenkins 文件。在接下来的两个步骤中,我们将体验这两种方式。
#### 步骤五:通过直接脚本配置并执行流水线作业
要使用直接脚本执行流水线,请首先从 GitHub 复制该 [Jenkinsfile 示例][6]的内容。选择 “Pipeline script” 作为 “Destination”然后将该 Jenkinsfile 的内容粘贴到 “Script” 中。花一些时间研究一下 Jenkins 文件的结构。注意共有三个阶段Build、Test 和 Deploy它们是任意的可以是任何一个。每个阶段中都有一些步骤在此示例中它们只是打印一些随机消息。
单击 “Save” 以保留更改,这将自动将你带回到 “Job Overview” 页面。
![Configure to Run as Jenkins Script][12]
要开始构建流水线的过程,请单击 “Build Now”。如果一切正常你将看到第一个流水线如下面的这个
![Click Build Now and See Result][13]
要查看流水线脚本构建的输出,请单击任何阶段,然后单击 “Log”。你会看到这样的消息。
![Visit sample GitHub with Jenkins get clone link][14]
#### 步骤六:通过 SCM 配置并执行流水线作业
现在,换个方式:在此步骤中,你将通过从源代码控制的 GitHub 中复制 Jenkinsfile 来部署相同的 Jenkins 作业。在同一个 [GitHub 存储库][6]中,通过单击 “Clone or download” 并复制其 URL 来找到其存储库 URL。
![Checkout from GitHub][15]
单击 “Configure” 以修改现有作业。滚动到 “Advanced Project Options” 设置,但这一次,从 “Destination” 下拉列表中选择 “Pipeline script from SCM” 选项。将 GitHub 存储库的 URL 粘贴到 “Repository URL” 中,然后在 “Script Path” 中键入 “Jenkinsfile”。 单击 “Save” 按钮保存。
![Change to Pipeline script from SCM][16]
要构建流水线,回到 “Task Overview” 页面后,单击 “Build Now” 以再次执行作业。结果与之前相同,除了多了一个称为 “Declaration: Checkout SCM” 的阶段。
![Build again and verify][17]
要查看来自 SCM 构建的流水线的输出,请单击该阶段并查看 “Log” 以检查源代码控制克隆过程的进行情况。
![Verify Checkout Procedure][18]
### 除了打印消息,还能做更多
恭喜你!你已经建立了第一个 Jenkins 流水线!
“但是等等”,你说,“这太有限了。除了打印无用的消息外,我什么都做不了。”那没问题。到目前为止,本教程仅简要介绍了 Jenkins 流水线可以做什么,但是你可以通过将其与其他工具集成来扩展其功能。以下是给你的下一个项目的一些思路:
* 建立一个多阶段的 Java 构建流水线,从以下阶段开始:从 Nexus 或 Artifactory 之类的 JAR 存储库中拉取依赖项、编译 Java 代码、运行单元测试、打包为 JAR/WAR 文件,然后部署到云服务器。
* 实现一个高级代码测试仪表板,该仪表板将基于 Selenium 的单元测试、负载测试和自动用户界面测试,报告项目的运行状况。
* 构建多流水线或多用户流水线,以自动化执行 Ansible 剧本的任务,同时允许授权用户响应正在进行的任务。
* 设计完整的端到端 DevOps 流水线,该流水线可提取存储在 SCM 中的基础设施资源文件和配置文件(例如 GitHub并通过各种运行时程序执行该脚本。
学习本文结尾处的任何教程,以了解这些更高级的案例。
#### 管理 Jenkins
在 Jenkins 主面板,点击 “Manage Jenkins”。
![Manage Jenkins][19]
#### 全局工具配置
有许多可用工具,包括管理插件、查看系统日志等。单击 “Global Tool Configuration”。
![Global Tools Configuration][20]
#### 增加附加能力
在这里,你可以添加 JDK 路径、Git、Gradle 等。配置工具后,只需将该命令添加到 Jenkinsfile 中或通过 Jenkins 脚本执行即可。
![See Various Options for Plugin][21]
### 后继
本文为你介绍了使用酷炫的开源工具 Jenkins 创建 CI/CD 流水线的方法。要了解你可以使用 Jenkins 完成的许多其他操作,请在 Opensource.com 上查看以下其他文章:
* [Jenkins X 入门][22]
* [使用 Jenkins 安装 OpenStack 云][23]
* [在容器中运行 Jenkins][24]
* [Jenkins 流水线入门][25]
* [如何与 Jenkins 一起运行 JMeter][26]
* [将 OpenStack 集成到你的 Jenkins 工作流中][27]
你可能对我为你的开源之旅而写的其他一些文章感兴趣:
* [9 个用于构建容错系统的开源工具][28]
* [了解软件设计模式][29]
* [使用开源工具构建 DevOps 流水线的初学者指南][2]
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/intro-building-cicd-pipelines-jenkins
作者:[Bryant Son][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/brson
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/pipe-pipeline-grid.png?itok=kkpzKxKg (pipelines)
[2]: https://linux.cn/article-11307-1.html
[3]: https://jenkins.io/
[4]: https://opensource.com/sites/default/files/uploads/diagrampipeline.jpg (Pipeline example)
[5]: https://opensource.com/sites/default/files/uploads/0_endresultpreview_0.jpg (Final Result)
[6]: https://github.com/bryantson/CICDPractice
[7]: https://jenkins.io/download/
[8]: https://opensource.com/sites/default/files/uploads/2_downloadwar.jpg (Download Jenkins as Java WAR file)
[9]: https://opensource.com/sites/default/files/uploads/3_runasjar.jpg (Execute as an executable JAR binary)
[10]: https://opensource.com/sites/default/files/uploads/4_createnewjob.jpg (Create New Job)
[11]: https://opensource.com/sites/default/files/uploads/5_createpipeline.jpg (Create New Pipeline Job)
[12]: https://opensource.com/sites/default/files/uploads/6_runaspipelinescript.jpg (Configure to Run as Jenkins Script)
[13]: https://opensource.com/sites/default/files/uploads/7_buildnow4script.jpg (Click Build Now and See Result)
[14]: https://opensource.com/sites/default/files/uploads/8_seeresult4script.jpg (Visit sample GitHub with Jenkins get clone link)
[15]: https://opensource.com/sites/default/files/uploads/9_checkoutfromgithub.jpg (Checkout from GitHub)
[16]: https://opensource.com/sites/default/files/uploads/10_runsasgit.jpg (Change to Pipeline script from SCM)
[17]: https://opensource.com/sites/default/files/uploads/11_seeresultfromgit.jpg (Build again and verify)
[18]: https://opensource.com/sites/default/files/uploads/12_verifycheckout.jpg (Verify Checkout Procedure)
[19]: https://opensource.com/sites/default/files/uploads/13_managingjenkins.jpg (Manage Jenkins)
[20]: https://opensource.com/sites/default/files/uploads/14_globaltoolsconfiguration.jpg (Global Tools Configuration)
[21]: https://opensource.com/sites/default/files/uploads/15_variousoptions4plugin.jpg (See Various Options for Plugin)
[22]: https://opensource.com/article/18/11/getting-started-jenkins-x
[23]: https://opensource.com/article/18/4/install-OpenStack-cloud-Jenkins
[24]: https://linux.cn/article-9741-1.html
[25]: https://opensource.com/article/18/4/jenkins-pipelines-with-cucumber
[26]: https://opensource.com/life/16/7/running-jmeter-jenkins-continuous-delivery-101
[27]: https://opensource.com/business/15/5/interview-maish-saidel-keesing-cisco
[28]: https://opensource.com/article/19/3/tools-fault-tolerant-system
[29]: https://opensource.com/article/19/7/understanding-software-design-patterns

View File

@@ -0,0 +1,214 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11554-1.html)
[#]: subject: (6 Open Source Paint Applications for Linux Users)
[#]: via: (https://itsfoss.com/open-source-paint-apps/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
6 款面向 Linux 用户的开源绘图应用程序
======
小时候,当我开始使用计算机(在 Windows XP 中)时,我最喜欢的应用程序是微软的“画图”。我能在它上面涂鸦数个小时。出乎意料,孩子们仍然喜欢这个“画图”应用程序。不仅仅是孩子们,这个简单的“画图”应用程序,在很多情况下都能派上用场。
你可以找到一堆可以让你绘制/绘图或操作图片的应用程序。然而,其中一些是专有软件。既然你是一名 Linux 用户,为什么不关注一下开源绘图应用程序呢?
在这篇文章中,我们将列出一些最好的开源绘图应用程序,它们可以替代可用于 Linux 的专有绘画软件。
### 开源绘图 & 绘制应用程序
![][1]
**注意:** 该列表没有特别的排名顺序。
#### 1、Pinta
![][2]
主要亮点:
* Paint.NET / 微软“画图”的极好替代品
* 支持附加组件(有对 WebP 图像的支持)
* 支持图层
[Pinta][3] 是一款令人赞叹的开源绘图应用程序,非常适合绘图和简单的图片编辑。换句话说,它是一款具有精美功能的简单绘图应用程序。
你可以将 [Pinta][4] 视为 Linux 上的“画图”的一个替代品,但是带有图层支持等等。不仅仅是“画图”,它也可以替代 Windows 上的 Paint.NET。尽管 Paint.NET 更好一些,但 Pinta 似乎是个不错的选择。
几个附加组件可以用于增强功能,例如[在 Linux 上支持 WebP 图像][5]。除了图层支持之外,你还可以轻松地调整图片大小、添加特效、进行调整(亮度、对比度等等),以及在导出图片时调整其质量。
##### 如何安装 Pinta
你应该能够在软件中心/应用程序中心/软件包管理器中简单地找到它。只需要输入 “Pinta”并开始安装它。要么也可以尝试 [Flatpak][6] 软件包。
或者你可以在终端中输入下面的命令Ubuntu/Debian
```
sudo apt install pinta
```
下载软件包和安装指南的更多信息,参考[官方下载页面][7]。
#### 2、Krita
![][8]
主要亮点:
* HDR 绘图
* 支持 PSD
* 支持图层
* 笔刷稳定器
* 二维动画
Krita 是 Linux 上最高级的开源绘图应用程序之一。当然,对于本文而言,它可以帮助你绘制草图和在画布上胡写乱画。除此之外,它还提供很多功能。
例如如果你的手有点颤抖它可以帮助你稳定笔刷的笔划。你可以使用内置的矢量工具来创建漫画画板和其它有趣的东西。如果你正在寻找具有全面的颜色管理支持、绘图助理和图层管理的软件Krita 应该是你最好的选择。
##### 如何安装 Krita
类似于 pinta你可以在软件中心/应用程序中心或软件包管理器的列表中找到它。它也可以 [Flatpak 存储库][10]中找到。
考虑通过终端安装它?输入下面的命令:
```
sudo apt install krita
```
要么你也可以前往它们的[官方下载页面][11]来获取 AppImage 文件并运行它。
如果你对 AppImage 文件一无所知,查看我们的指南 —— [如何使用 AppImage][12]。
#### 3、Tux Paint
![][13]
主要亮点:
* 给儿童用的一个简单直接的绘图应用程序
我不是开玩笑,对于 3-12 岁儿童来说Tux Paint 是最好的开源绘图应用程序之一。当然当你只想乱画时那无需选择所以在这种情况下Tux Paint 似乎是最好的选择(即使是成年人!)。
##### 如何安装 Tuxpaint
Tuxpaint 可以从软件中心或软件包管理器下载。无论哪种情况,在 Ubuntu/Debian 上安装它,在终端中输入下面的命令:
```
sudo apt install tuxpaint
```
关于它的更多信息,前往[官方站点][14]。
#### 4、Drawpile
![][15]
主要亮点:
* 协同绘制
* 内置聊天功能,可与其他用户互动
* 图层支持
* 记录绘制会话
Drawpile 是一个有趣的开源绘图应用程序,在该程序中,你可以与其他用户实时协作。确切地说,你们可以单个画布中同时绘制。除了这个独特的功能,它还有图层支持、记录绘制会话的能力,甚至还有与协作用户进行交互的聊天功能。
你可以主持或加入一个公共会话,或通过一个密码与你的朋友建立私有会话。默认情况下,服务器将是你的计算机,但是如果你需要远程服务器那也可以。
注意,你将需要[注册一个 Drawpile 账户][16] 才能进行协作。
##### 如何安装 Drawpile
据我所知,你只能在 [Flatpak 存储库][17]的列表中找到它。
#### 5、MyPaint
![][19]
主要亮点:
* 易用的数码画家工具
* 支持图层管理
* 很多微调你的画笔和绘制的选项
对于数码画家来说,[MyPaint][20] 是一个简单而强大的工具。它具有许多选项,可以调整以制作出完美的数字画笔笔触。我不是一个数字艺术家(但我是一个涂鸦者),但是我注意到有很多调整笔刷、颜色的选项,和一个添加中间结果暂存器面板的选项。
它也支持图层管理,也许你需要它。最新的稳定版本已经有几年没有更新了,但是当前的 alpha 构建版本(我测试过)运行良好。如果你正在 Linux 上寻找一个开源绘图应用程序 —— 试试这个。
##### 如何安装 MyPaint
MyPaint 可在官方存储库中获得。然而,这是老旧的版本。如果你仍然想继续,你可以在软件中心搜索它,或在终端中输入下面的命令:
```
sudo apt install mypaint
```
你可以前往它的官方 [GitHub 发布页面][21]获取最新的 alpha 构建版本,获取 [AppImage 文件][12](任意版本)并使它可执行并启动应用程序。
#### 6、KolourPaint
![][22]
主要亮点:
* 一个 Linux 上的“画图”的简单替代品
* 不支持图层管理
如果你不需要任何图层管理的支持,而只是想要一个开源绘图应用程序来绘制东西 —— 那就是它了。
[KolourPaint][23] 最初是为 KDE 桌面环境定制的,但是它在其它的桌面环境中也能完美地工作。
##### 如何安装 KolourPaint
你可以从软件中心安装 KolourPaint或通过终端使用下面的命令
```
sudo apt install kolourpaint4
```
你总可以试试 [Flathub][24]。
### 总结
如果你在考虑如 GIMP/Inkscape 这样的应用程序,我们在另一篇关于[给数码艺术家的最好 Linux 工具][25]的文章中列出。如果你对更多的选择好奇,我建议你去查看它。
在这里,我们尝试编写一份 Linux 可用的最佳开源绘图应用程序列表。如果你认为我们错过一些东西,请在下面的评论区告诉我们!
--------------------------------------------------------------------------------
via: https://itsfoss.com/open-source-paint-apps/
作者:[Ankush Das][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://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/open-source-paint-apps.png?resize=800%2C450&ssl=1
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/pinta.png?ssl=1
[3]: https://pinta-project.com/pintaproject/pinta/
[4]: https://itsfoss.com/pinta-1-6-ubuntu-linux-mint/
[5]: https://itsfoss.com/webp-ubuntu-linux/
[6]: https://www.flathub.org/apps/details/com.github.PintaProject.Pinta
[7]: https://pinta-project.com/pintaproject/pinta/releases
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/krita-paint.png?ssl=1
[9]: https://itsfoss.com/things-to-do-after-installing-fedora-24/
[10]: https://www.flathub.org/apps/details/org.kde.krita
[11]: https://krita.org/en/download/krita-desktop/
[12]: https://itsfoss.com/use-appimage-linux/
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/tux-paint.jpg?ssl=1
[14]: http://www.tuxpaint.org/
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/drawpile.png?ssl=1
[16]: https://drawpile.net/accounts/signup/
[17]: https://flathub.org/apps/details/net.drawpile.drawpile
[18]: https://itsfoss.com/ocs-store/
[19]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/mypaint.png?ssl=1
[20]: https://mypaint.org/
[21]: https://github.com/mypaint/mypaint/releases
[22]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/kolourpaint.png?ssl=1
[23]: http://kolourpaint.org/
[24]: https://flathub.org/apps/details/org.kde.kolourpaint
[25]: https://itsfoss.com/best-linux-graphic-design-software/

View File

@@ -0,0 +1,194 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11590-1.html)
[#]: subject: (How to fix common pitfalls with the Python ORM tool SQLAlchemy)
[#]: via: (https://opensource.com/article/19/9/common-pitfalls-python)
[#]: author: (Zach Todd https://opensource.com/users/zchtoddhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/liranhaimovitchhttps://opensource.com/users/moshez)
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
======
> 在使用 SQLAlchemy 时,那些看似很小的选择可能对这种对象关系映射工具包的性能产生重要影响。
![A python with a package.][1]
<ruby>对象关系映射<rt>Object-relational mapping</rt></ruby>[ORM][2])使应用程序开发人员的工作更轻松,在很大程度是因为它允许你使用你可能知道的语言(例如 Python与数据库交互而不是使用原始 SQL 语句查询。[SQLAlchemy][3] 是一个 Python ORM 工具包,它提供使用 Python 访问 SQL 数据库的功能。它是一个成熟的 ORM 工具,增加了模型关系、强大的查询构造范式、简单的序列化等优点。然而,它的易用性使得人们很容易忘记其背后发生了什么。使用 SQLAlchemy 时做出的看似很小的选择可能产生非常大的性能影响。
本文解释了开发人员在使用 SQLAlchemy 时遇到的一些最重要的性能问题,以及如何解决这些问题。
### 只需要计数但检索整个结果集
有时开发人员只需要一个结果计数,但是没有使用数据库计数功能,而是获取了所有结果,然后使用 Python 中的 `len` 完成计数。
```
count = len(User.query.filter_by(acct_active=True).all())
```
相反,使用 SQLAlchemy 的 `count` 方法将在服务器端执行计数,从而减少发送到客户端的数据。在前面的例子中调用 `all()` 也会导致模型对象的实例化,如果有很多数据,那么时间代价可能会非常昂贵。
除非还需要做其他的事情,否则只需使用 `count` 方法:
```
count = User.query.filter_by(acct_active=True).count()
```
### 只需要几列时检索整个模型
在许多情况下发出查询时只需要几列数据。SQLAlchemy 可以只获取你想要的列,而不是返回整个模型实例。这不仅减少了发送的数据量,还避免了实例化整个对象。使用列数据的元组而不是模型可以快得多。
```
result = User.query.all()
for user in result:
    print(user.name, user.email)
```
反之,使用 `with_entities` 方法只选择所需要的内容:
```
result = User.query.with_entities(User.name, User.email).all()
for (username, email) in result:
    print(username, email)
```
### 每次循环都更新一个对象
避免使用循环来单独更新集合。虽然数据库可以非常快地执行单个更新,但应用程序和数据库服务器之间的往返时间将快速累加。通常,在合理的情况下争取更少的查询。
```
for user in users_to_update:
  user.acct_active = True
  db.session.add(user)
```
改用批量更新方法:
```
query = User.query.filter(user.id.in_([user.id for user in users_to_update]))
query.update({"acct_active": True}, synchronize_session=False)
```
### 触发级联删除
ORM 允许在模型关系上进行简单的配置但是有一些微妙的行为可能会令人吃惊。大多数数据库通过外键和各种级联选项维护关系完整性。SQLAlchemy 允许你使用外键和级联选项定义模型,但是 ORM 具有自己的级联逻辑,可以取代数据库。
考虑以下模型:
```
class Artist(Base):
    __tablename__ = "artist"
    id = Column(Integer, primary_key=True)
    songs = relationship("Song", cascade="all, delete")
class Song(Base):
    __tablename__ = "song"
    id = Column(Integer, primary_key=True)
    artist_id = Column(Integer, ForeignKey("artist.id", ondelete="CASCADE"))
```
删除歌手将导致 ORM 在 `song` 表上发出 `delete` 查询,从而防止由于外键导致的删除操作。这种行为可能会成为复杂关系和大量记录的瓶颈。
请包含 `passive_deletes` 选项以确保让数据库来管理关系。但是请确保你的数据库具有此功能。例如SQLite 默认情况下不管理外键。
```
songs = relationship("Song", cascade all, delete", passive_deletes=True)
```
### 当要使用贪婪加载时,应使用延迟加载
延迟加载是 SQLAlchemy 处理关系的默认方法。从上一个例子构建来看,加载一个歌手时不会同时加载他或她的歌曲。这通常是一个好主意,但是如果总是需要加载某些关系,单独的查询可能会造成浪费。
如果允许以延迟方式加载关系,像 [Marshmallow][4] 这样流行的序列化框架可以触发级联查询。
有几种方法可以控制此行为。最简单的方法是通过 relationship 函数本身。
```
songs = relationship("Song", lazy="joined", cascade="all, delete")
```
这将导致一个左连接被添加到任何歌手的查询中,因此,`songs` 集合将立即可用。尽管有更多数据返回给客户端,但往返次数可能会少得多。
SQLAlchemy 为无法采用这种综合方法的情况提供了更细粒度的控制,可以使用 `joinedload()` 函数在每个查询的基础上切换连接的加载。
```
from sqlalchemy.orm import joinedload
artists = Artist.query.options(joinedload(Artist.songs))
print(artists.songs) # Does not incur a roundtrip to load
```
### 使用 ORM 进行批量记录导入
导入成千上万条记录时,构建完整模型实例的开销会成为主要瓶颈。想象一下,从一个文件中加载数千首歌曲记录,其中每首歌曲都先被转换为字典。
```
for song in songs:
    db.session.add(Song(`song))
```
相反,绕过 ORM只使用核心的 SQLAlchemy 参数绑定功能。
```
batch = []
insert_stmt = Song.__table__.insert()
for song in songs:
    if len(batch) &gt; 1000:
       db.session.execute(insert_stmt, batch)
       batch.clear()
    batch.append(song)
if batch:
    db.session.execute(insert_stmt, batch)
```
请记住,此方法会自然而然地跳过你可能依赖的任何客户端 ORM 逻辑,例如基于 Python 的列默认值。尽管此方法比将对象加载为完整的模型实例要快但是你的数据库可能具有更快的批量加载方法。例如PostgreSQL 的 `COPY` 命令为加载大量记录提供了最佳性能。
### 过早调用提交或刷新
在很多情况下,你需要将子记录与其父记录相关联,反之亦然。一种显然的方法是刷新会话,以便为有问题的记录分配一个 ID。
```
artist = Artist(name="Bob Dylan")
song = Song(title="Mr. Tambourine Man")
db.session.add(artist)
db.session.flush()
song.artist_id = artist.id
```
对于每个请求,多次提交或刷新通常是不必要的,也是不可取的。数据库刷新涉及强制在数据库服务器上进行磁盘写入,在大多数情况下,客户端将阻塞,直到服务器确认已写入数据为止。
SQLAlchemy 可以在幕后跟踪关系和管理相关键。
```
artist = Artist(name="Bob Dylan")
song = Song(title="Mr. Tambourine Man")
artist.songs.append(song)
```
### 总结
我希望这一系列常见的陷阱可以帮助你避免这些问题,并使你的应用平稳运行。通常,在诊断性能问题时,测量是关键。大多数数据库都提供性能诊断功能,可以帮助你定位问题,例如 PostgreSQL 的 `pg_stat_statements` 模块。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/common-pitfalls-python
作者:[Zach Todd][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/zchtoddhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/liranhaimovitchhttps://opensource.com/users/moshez
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python_snake_file_box.jpg?itok=UuDVFLX- (A python with a package.)
[2]: https://en.wikipedia.org/wiki/Object-relational_mapping
[3]: https://www.sqlalchemy.org/
[4]: https://marshmallow.readthedocs.io/en/stable/

View File

@@ -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 编程,这里有七个你需要知道的基础知识。
![](https://img.linux.net.cn/data/attachment/album/201911/28/120421di3744urqnyyr6xi.jpg)
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 <options>", 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

View File

@@ -0,0 +1,193 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11531-1.html)
[#]: subject: (5 Best Password Managers For Linux Desktop)
[#]: via: (https://itsfoss.com/password-managers-linux/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
5 个 Linux 桌面上的最佳密码管理器
======
> 密码管理器是创建唯一密码并安全存储它们的有用工具,这样你无需记住密码。了解一下适用于 Linux 桌面的最佳密码管理器。
![](https://img.linux.net.cn/data/attachment/album/201911/03/102528e97mr0ls89lz9rrr.jpg)
密码无处不在。网站、论坛、Web 应用等,你需要为其创建帐户和密码。麻烦在于密码,为各个帐户使用相同的密码会带来安全风险,因为[如果其中一个网站遭到入侵,黑客也会在其他网站上尝试相同的电子邮件密码组合][1]。
但是,为所有新帐户设置独有的密码意味着你必须记住所有密码,这对普通人而言不太可能。这就是密码管理器可以提供帮助的地方。
密码管理应用会为你建议/创建强密码,并将其存储在加密的数据库中。你只需要记住密码管理器的主密码即可。
主流的现代浏览器(例如 Mozilla Firefox 和 Google Chrome内置了密码管理器。这有帮助但是你只能在浏览器上使用它。
有一些第三方专门的密码管理器,其中一些还提供 Linux 的原生桌面应用。在本文中,我们将筛选出可用于 Linux 的最佳密码管理器。
继续之前,我还建议你仔细阅读 [Linux 的免费密码生成器][2],来为你生成强大的唯一密码。
### Linux 密码管理器
> 可能的非 FOSS 警报!
> 我们优先考虑开源软件(有一些专有软件,请不要讨厌我!),并提供适用于 Linux 的独立桌面应用GUI。专有软件已高亮显示。
#### 1、Bitwarden
![][3]
主要亮点:
* 开源
* 免费供个人使用(可选付费升级)
* 云服务器的端到端加密
* 跨平台
* 有浏览器扩展
* 命令行工具
Bitwarden 是 Linux 上最令人印象深刻的密码管理器之一。老实说,直到现在我才知道它。我已经从 [LastPass][4] 切换到了它。我能够轻松地从 LastPass 导入数据,而没有任何问题和困难。
付费版本的价格仅为每年 10 美元。这似乎是值得的(我已经为个人使用进行了升级)。
它是一个开源解决方案,因此没有任何可疑之处。你甚至可以将其托管在自己的服务器上,并为你的组织创建密码解决方案。
除此之外,你还将获得所有必需的功能,例如用于登录的两步验证、导入/导出凭据、指纹短语(唯一键)、密码生成器等等。
你可以免费将帐户升级为组织帐户,以便最多与 2 个用户共享你的信息。但是,如果你想要额外的加密存储以及与 5 个用户共享密码的功能,那么付费升级的费用低至每月 1 美元。我认为绝对值得一试!
- [Bitwarden][5]
#### 2、Buttercup
![][6]
主要亮点:
* 开源
* 免费,没有付费方式。
* 跨平台
* 有浏览器扩展
这是 Linux 中的另一个开源密码管理器。Buttercup 可能不是一个非常流行的解决方案。但是,如果你在寻找一种更简单的保存凭据的方法,那么这将是一个不错的开始。
与其他软件不同,你不必对怀疑其云服务器的安全,因为它只支持离线使用并支持连接 [Dropbox][7]、[OwnCloud] [8]、[Nextcloud][9] 和 [WebDAV][10] 等云服务。
因此,如果需要同步数据,那么可以选择云服务。你有不同选择。
- [Buttercup][11]
#### 3、KeePassXC
![][12]
主要亮点:
* 开源
* 简单的密码管理器
* 跨平台
* 没有移动设备支持
KeePassXC 是 [KeePassX][13] 的社区分支,它最初是 Windows 上 [KeePass][14] 的 Linux 移植版本。
除非你没意识到KeePassX 已经多年没有维护。因此,如果你在寻找简单易用的密码管理器,那么 KeePassXC 是一个不错的选择。KeePassXC 可能不是最漂亮或最好的密码管理器,但它确实可以做到该做的事。
它也是安全和开源的。我认为这值得一试,你说呢?
- [KeePassXC][15]
#### 4、Enpass (非开源)
![][16]
主要亮点:
* 专有软件
* 有许多功能,包括对“可穿戴”设备支持。
* Linux 完全免费(具有付费支持)
Enpass 是非常流行的跨平台密码管理器。即使它不是开源解决方案,但还是有很多人依赖它。因此,至少可以肯定它是可行的。
它提供了很多功能,如果你有可穿戴设备,它也可以支持它,这点很少见。
很高兴能看到 Enpass 积极管理 Linux 发行版的软件包。另外,请注意,它仅适用于 64 位系统。你可以在它的网站上找到[官方的安装说明] [17]。它需要使用终端,但是我按照步骤进行了测试,它非常好用。
- [Enpass][18]
#### 5、myki (非开源)
![][19]
主要亮点:
* 专有软件
* 不使用云服务器存储密码
* 专注于本地点对点同步
* 能够在移动设备上用指纹 ID 替换密码
这可能不是一个受欢迎的建议,但我发现它很有趣。它是专有软件密码管理器,它让你避免使用云服务器,而是依靠点对点同步。
因此,如果你不想使用任何云服务器来存储你的信息,那么它适合你。另外值得注意的是,用于 Android 和 iOS 的程序可让你用指纹 ID 替换密码。如果你希望便于在手机上使用,又有桌面密码管理器的基本功能,这似乎是个不错的选择。
但是,如果你选择升级到付费版,这有个付费计划供你判断,绝对不便宜。
尝试一下,让我们知道它如何!
- [myki][20]
### 其他一些值得说的密码管理器
即使没有为 Linux 提供独立的应用,但仍有一些密码管理器值得一提。
如果你需要使用基于浏览器的(扩展)密码管理器,建议你尝试使用 [LastPass][21]、[Dashlane][22] 和 [1Password][23]。LastPass 甚至提供了 [Linux 客户端(和命令行工具)][24]。
如果你正在寻找命令行密码管理器,那你应该试试 [Pass][25]。
[Password Safe][26] 也是种选择,但它的 Linux 客户端还处于 beta 阶段。我不建议依靠 “beta” 程序来存储密码。还有 [Universal Password Manager][27],但它不再维护。你可能也听说过 [Password Gorilla][28],但并它没有积极维护。
### 总结
目前Bitwarden 似乎是我个人的最爱。但是,在 Linux 上有几个替代品可供选择。你可以选择提供原生应用的程序,也可选择浏览器插件,选择权在你。
如果我有错过值得尝试的密码管理器,请在下面的评论中告诉我们。与往常一样,我们会根据你的建议扩展列表。
--------------------------------------------------------------------------------
via: https://itsfoss.com/password-managers-linux/
作者:[Ankush Das][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://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://medium.com/@computerphonedude/one-of-my-old-passwords-was-hacked-on-6-different-sites-and-i-had-no-clue-heres-how-to-quickly-ced23edf3b62
[2]: https://itsfoss.com/password-generators-linux/
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/bitward.png?ssl=1
[4]: https://www.lastpass.com/
[5]: https://bitwarden.com/
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/buttercup.png?ssl=1
[7]: https://www.dropbox.com/
[8]: https://owncloud.com/
[9]: https://nextcloud.com/
[10]: https://en.wikipedia.org/wiki/WebDAV
[11]: https://buttercup.pw/
[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/KeePassXC.png?ssl=1
[13]: https://www.keepassx.org/
[14]: https://keepass.info/
[15]: https://keepassxc.org
[16]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/enpass.png?ssl=1
[17]: https://www.enpass.io/support/kb/general/how-to-install-enpass-on-linux/
[18]: https://www.enpass.io/
[19]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/myki.png?ssl=1
[20]: https://myki.com/
[21]: https://lastpass.com/
[22]: https://www.dashlane.com/
[23]: https://1password.com/
[24]: https://lastpass.com/misc_download2.php
[25]: https://www.passwordstore.org/
[26]: https://pwsafe.org/
[27]: http://upm.sourceforge.net/
[28]: https://github.com/zdia/gorilla/wiki

View File

@@ -1,65 +1,63 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11535-1.html)
[#]: subject: (How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server)
[#]: via: (https://www.linuxtechi.com/enable-epel-repo-centos8-rhel8-server/)
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server
如何在 CentOS 8 RHEL 8 服务器上启用 EPEL 仓库
======
**EPEL** Stands for Extra Packages for Enterprise Linux, it is a free and opensource additional packages repository available for **CentOS** and **RHEL** servers. As the name suggests, EPEL repository provides extra and additional packages which are not available in the default package repositories of [CentOS 8][1] and [RHEL 8][2].
EPEL 代表 “Extra Packages for Enterprise Linux”,它是一个自由开源的附加软件包仓库,可用于 CentOS 和 RHEL 服务器。顾名思义EPEL 仓库提供了额外的软件包,这些软件在 [CentOS 8][1] [RHEL 8][2] 的默认软件包仓库中不可用。
In this article we will demonstrate how to enable and use epel repository on CentOS 8 and RHEL 8 Server.
在本文中,我们将演示如何在 CentOS 8 RHEL 8 服务器上启用和使用 EPEL 存储库。
[![EPEL-Repo-CentOS8-RHEL8][3]][4]
![](https://img.linux.net.cn/data/attachment/album/201911/04/113307wz4y3lnczzlxzn2j.jpg)
### Prerequisites of EPEL Repository
### EPEL 仓库的先决条件
* Minimal CentOS 8 and RHEL 8 Server
* Root or sudo admin privileges
* Internet Connection
* 最小化安装的 CentOS 8 RHEL 8 服务器
* root sudo 管理员权限
* 网络连接
### 在 RHEL 8.x 服务器上安装并启用 EPEL 仓库
### Install and Enable EPEL Repository on RHEL 8.x Server
Login or ssh to your RHEL 8.x server and execute the following dnf command to install EPEL rpm package,
登录或 SSH 到你的 RHEL 8.x 服务器,并执行以下 `dnf` 命令来安装 EPEL rpm 包,
```
[root@linuxtechi ~]# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
```
Output of above command would be something like below,
上面命令的输出将如下所示,
![dnf-install-epel-repo-rehl8][3]
![dnf-install-epel-repo-rehl8][5]
Once epel rpm package is installed successfully then it will automatically enable and configure its yum / dnf repository.  Run following dnf or yum command to verify whether EPEL repository is enabled or not,
EPEL rpm 包成功安装后,它将自动启用并配置其 yum/dnf 仓库。运行以下 `dnf``yum` 命令,以验证是否启用了 EPEL 仓库,
```
[root@linuxtechi ~]# dnf repolist epel
Or
或者
[root@linuxtechi ~]# dnf repolist epel -v
```
![epel-repolist-rhel8][3]
![epel-repolist-rhel8][6]
### Install and Enable EPEL Repository on CentOS 8.x Server
### 在 CentOS 8.x 服务器上安装并启用 EPEL 仓库
Login or ssh to your CentOS 8 server and execute following dnf or yum command to install **epel-release** rpm package. In CentOS 8 server, epel rpm package is available in its default package repository.
登录或 SSH 到你的 CentOS 8 服务器,并执行以下 `dnf``yum` 命令来安装 `epel-release` rpm 软件包。在 CentOS 8 服务器中EPEL rpm 在其默认软件包仓库中。
```
[root@linuxtechi ~]# dnf install epel-release -y
Or
或者
[root@linuxtechi ~]# yum install epel-release -y
```
Execute the following commands to verify the status of epel repository on CentOS 8 server,
执行以下命令来验证 CentOS 8 服务器上 EPEL 仓库的状态,
```
[root@linuxtechi ~]# dnf repolist epel
[root@linuxtechi ~]# dnf repolist epel
Last metadata expiration check: 0:00:03 ago on Sun 13 Oct 2019 04:18:05 AM BST.
repo id repo name status
*epel Extra Packages for Enterprise Linux 8 - x86_64 1,977
@@ -82,11 +80,11 @@ Total packages: 1,977
[root@linuxtechi ~]#
```
Above commands output confirms that we have successfully enabled epel repo. Lets perform some basic operations on EPEL repo.
以上命令的输出说明我们已经成功启用了 EPEL 仓库。让我们在 EPEL 仓库上执行一些基本操作。
### List all available packages from epel repository
### 列出 EPEL 仓库种所有可用包
If you want to list all the packages from epel repository then run the following dnf command,
如果要列出 EPEL 仓库中的所有的软件包,请运行以下 `dnf` 命令,
```
[root@linuxtechi ~]# dnf repository-packages epel list
@@ -116,33 +114,35 @@ zvbi-fonts.noarch 0.2.35-9.el8 epel
[root@linuxtechi ~]#
```
### Search a package from epel repository
### 从 EPEL 仓库中搜索软件包
Lets assume if we want to search Zabbix package in epel repository, execute the following dnf command,
假设我们要搜索 EPEL 仓库中的 Zabbix 包,请执行以下 `dnf` 命令,
```
[root@linuxtechi ~]# dnf repository-packages epel list | grep -i zabbix
```
Output of above command would be something like below,
上面命令的输出类似下面这样,
![epel-repo-search-package-centos8][3]
![epel-repo-search-package-centos8][7]
### Install a package from epel repository
### 从 EPEL 仓库安装软件包
Lets assume we want to install htop package from epel repo, then issue the following dnf command,
假设我们要从 EPEL 仓库安装 htop 包,运行以下 `dnf` 命令,
Syntax:
语法:
# dnf enablerepo=”epel” install &lt;pkg_name&gt;
```
# dnf enablerepo=”epel” install <包名>
```
```
[root@linuxtechi ~]# dnf --enablerepo="epel" install htop -y
```
**Note:** If we dont specify the “**enablerepo=epel**” in above command then it will look for htop package in all available package repositories.
注意:如果我们在上面的命令中未指定 `enablerepo=epel`,那么它将在所有可用的软件包仓库中查找 htop 包。
Thats all from this article, I hope above steps helps you to enable and configure EPEL repository on CentOS 8 and RHEL 8 Server, please dont hesitate to share your comments and feedback in below comments section.
本文就是这些内容了,我希望上面的步骤能帮助你在 CentOS 8 RHEL 8 服务器上启用并配置 EPEL 仓库,请在下面的评论栏分享你的评论和反馈。
--------------------------------------------------------------------------------
@@ -150,8 +150,8 @@ via: https://www.linuxtechi.com/enable-epel-repo-centos8-rhel8-server/
作者:[Pradeep Kumar][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
@@ -161,3 +161,6 @@ via: https://www.linuxtechi.com/enable-epel-repo-centos8-rhel8-server/
[2]: https://www.linuxtechi.com/install-configure-kvm-on-rhel-8/
[3]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/10/EPEL-Repo-CentOS8-RHEL8.jpg
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/10/dnf-install-epel-repo-rehl8.jpg
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/10/epel-repolist-rhel8.jpg
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/10/epel-repo-search-package-centos8.jpg

View File

@@ -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 编码可提高效率。
![](https://img.linux.net.cn/data/attachment/album/201911/22/075757pn2fxfth30ntwefg.jpg)
<ruby>协议缓冲区<rt>Protocol Buffers</rt></ruby>[Protobufs][2])像 XML 和 JSON 一样,可以让用不同语言编写并在不同平台上运行的应用程序交换数据。例如,用 Go 编写的发送程序可以在 Protobuf 中对以 Go 表示的销售订单数据进行编码,然后用 Java 编写的接收方可以对它进行解码,以获取所接收订单数据的 Java 表示方式。这是在网络连接上的结构示意图:
> Go 销售订单 ---> Pbuf 编码 ---> 网络 ---> Pbuf 界面 ---> Java 销售订单
与 XML 和 JSON 相比Protobuf 编码是二进制而不是文本这会使调试复杂化。但是正如本文中的代码示例所确认的那样Protobuf 编码在大小上比 XML 或 JSON 编码要有效得多。
Protobuf 以另一种方式提供了这种有效性。在实现级别Protobuf 和其他编码系统对结构化数据进行<ruby>序列化<rt>serialize</rt></ruby>和<ruby>反序列化<rt>deserialize</rt></ruby>。序列化将特定语言的数据结构转换为字节流,反序列化是将字节流转换回特定语言的数据结构的逆运算。序列化和反序列化可能成为数据交换的瓶颈,因为这些操作会占用大量 CPU。高效的序列化和反序列化是 Protobuf 的另一个设计目标。
最近的编码技术,例如 Protobuf 和 FlatBuffers源自 1990 年代初期的 [DCE/RPC][3]<ruby>分布式计算环境/远程过程调用<rt>Distributed Computing Environment/Remote Procedure Call</rt></ruby>)计划。与 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

View File

@@ -0,0 +1,251 @@
[#]: collector: (lujun9972)
[#]: translator: (jdh8383)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11552-1.html)
[#]: subject: (How to program with Bash: Syntax and tools)
[#]: via: (https://opensource.com/article/19/10/programming-bash-part-1)
[#]: author: (David Both https://opensource.com/users/dboth)
怎样用 Bash 编程:语法和工具
======
> 让我们通过本系列文章来学习基本的 Bash 编程语法和工具,以及如何使用变量和控制运算符,这是三篇中的第一篇。
![](https://img.linux.net.cn/data/attachment/album/201911/08/092559r5wdg0w97dtf350j.jpg)
Shell 是操作系统的命令解释器,其中 Bash 是我最喜欢的。每当用户或者系统管理员将命令输入系统的时候Linux 的 shell 解释器就会把这些命令转换成操作系统可以理解的形式。而执行结果返回 shell 程序后,它会将结果输出到 STDOUT标准输出默认情况下这些结果会[显示在你的终端][2]。所有我熟悉的 shell 同时也是一门编程语言。
Bash 是个功能强大的 shell包含众多便捷特性比如tab 补全、命令回溯和再编辑、别名等。它的命令行默认编辑模式是 Emacs但是我最喜欢的 Bash 特性之一是我可以将其更改为 Vi 模式,以使用那些储存在我肌肉记忆中的的编辑命令。
然而,如果你把 Bash 当作单纯的 shell 来用,则无法体验它的真实能力。我在设计一套包含三卷的 [Linux 自学课程][3]时(这个系列的文章正是基于此课程),了解到许多 Bash 的知识,这些是我在过去 20 年的 Linux 工作经验中所没有掌握的,其中的一些知识就是关于 Bash 的编程用法。不得不说Bash 是一门强大的编程语言,是一个能够同时用于命令行和 shell 脚本的完美设计。
本系列文章将要探讨如何使用 Bash 作为命令行界面CLI编程语言。第一篇文章简单介绍 Bash 命令行编程、变量以及控制运算符。其他文章会讨论诸如Bash 文件的类型;字符串、数字和一些逻辑运算符,它们能够提供代码执行流程中的逻辑控制;不同类型的 shell 扩展;通过 `for``while``until` 来控制循环操作。
### Shell
Bash 是 Bourne Again Shell 的缩写,因为 Bash shell 是 [基于][4] 更早的 Bourne shell后者是 Steven Bourne 在 1977 年开发的。另外还有很多[其他的 shell][5] 可以使用,但下面四个是我经常见到的:
* `csh`C shell 适合那些习惯了 C 语言语法的开发者。
* `ksh`Korn shell由 David Korn 开发,在 Unix 用户中更流行。
* `tcsh`:一个 csh 的变种,增加了一些易用性。
* `zsh`Z shell集成了许多其他流行 shell 的特性。
所有 shell 都有内置命令,用以补充或替代核心工具集。打开 shell 的 man 说明页找到“BUILT-INS”那一段可以查看都有哪些内置命令。
每种 shell 都有它自己的特性和语法风格。我用过 csh、ksh 和 zsh但我还是更喜欢 Bash。你可以多试几个寻找更适合你的 shell尽管这可能需要花些功夫。但幸运的是切换不同 shell 很简单。
所有这些 shell 既是编程语言又是命令解释器。下面我们来快速浏览一下 Bash 中集成的编程结构和工具。
### 作为编程语言的 Bash
大多数场景下,系统管理员都会使用 Bash 来发送简单明了的命令。但 Bash 不仅可以输入单条命令,很多系统管理员可以编写简单的命令行程序来执行一系列任务,这些程序可以作为通用工具,能节省时间和精力。
编写 CLI 程序的目的是要提高效率(做一个“懒惰的”系统管理员)。在 CLI 程序中,你可以用特定顺序列出若干命令,逐条执行。这样你就不用盯着显示屏,等待一条命令执行完,再输入另一条,省下来的时间就可以去做其他事情了。
### 什么是“程序”?
自由在线计算机词典([FOLDOC][6])对于程序的定义是:“由计算机执行的指令,而不是运行它们的物理硬件。”普林斯顿大学的 [WordNet][7] 将程序定义为:“……计算机可以理解并执行的一系列指令……”[维基百科][8]上也有一条不错的关于计算机程序的条目。
总结下,程序由一条或多条指令组成,目的是完成一个具体的相关任务。对于系统管理员而言,一段程序通常由一系列的 shell 命令构成。Linux 下所有的 shell 至少我所熟知的都有基本的编程功能Bash 作为大多数 linux 发行版的默认 shell也不例外。
本系列用 Bash 举例(因为它无处不在),假如你使用一个不同的 shell 也没关系,尽管结构和语法有所不同,但编程思想是相通的。有些 shell 支持某种特性而其他 shell 则不支持但它们都提供编程功能。Shell 程序可以被存在一个文件中被反复使用,或者在需要的时候才创建它们。
### 简单 CLI 程序
最简单的命令行程序只有一或两条语句,它们可能相关,也可能无关,在按回车键之前被输入到命令行。程序中的第二条语句(如果有的话)可能取决于第一条语句的操作,但也不是必须的。
这里需要特别讲解一个标点符号。当你在命令行输入一条命令,按下回车键的时候,其实在命令的末尾有一个隐含的分号(`;`)。当一段 CLI shell 程序在命令行中被串起来作为单行指令使用时,必须使用分号来终结每个语句并将其与下一条语句分开。但 CLI shell 程序中的最后一条语句可以使用显式或隐式的分号。
### 一些基本语法
下面的例子会阐明这一语法规则。这段程序由单条命令组成,还有一个显式的终止符:
```
[student@studentvm1 ~]$ echo "Hello world." ;
Hello world.
```
看起来不像一个程序,但它确是我学习每个新编程语言时写下的第一个程序。不同语言可能语法不同,但输出结果是一样的。
让我们扩展一下这段微不足道却又无所不在的代码。你的结果可能与我的有所不同,因为我的家目录有点乱,而你可能是在 GUI 桌面中第一次登录账号。
```
[student@studentvm1 ~]$ echo "My home directory." ; ls ;
My home directory.
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1
```
现在是不是更明显了。结果是相关的,但是两条语句彼此独立。你可能注意到我喜欢在分号前后多输入一个空格,这样会让代码的可读性更好。让我们再运行一遍这段程序,这次不要带结尾的分号:
```
[student@studentvm1 ~]$ echo "My home directory." ; ls
```
输出结果没有区别。
### 关于变量
像所有其他编程语言一样Bash 支持变量。变量是个象征性的名字,它指向内存中的某个位置,那里存着对应的值。变量的值是可以改变的,所以它叫“变~量”。
Bash 不像 C 之类的语言,需要强制指定变量类型,比如:整型、浮点型或字符型。在 Bash 中,所有变量都是字符串。整数型的变量可以被用于整数运算,这是 Bash 唯一能够处理的数学类型。更复杂的运算则需要借助 [bc][9] 这样的命令,可以被用在命令行编程或者脚本中。
变量的值是被预先分配好的,这些值可以用在命令行编程或者脚本中。可以通过变量名字给其赋值,但是不能使用 `$` 符开头。比如,`VAR=10` 这样会把 `VAR` 的值设为 `10`。要打印变量的值,你可以使用语句 `echo $VAR`。变量名必须以文本(即非数字)开始。
Bash 会保存已经定义好的变量,直到它们被取消掉。
下面这个例子,在变量被赋值前,它的值是空(`null`)。然后给它赋值并打印出来,检验一下。你可以在同一行 CLI 程序里完成它:
```
[student@studentvm1 ~]$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
Hello World
[student@studentvm1 ~]$
```
*注意:变量赋值的语法非常严格,等号(`=`)两边不能有空格。*
那个空行表明了 `MyVar` 的初始值为空。变量的赋值和改值方法都一样,这个例子展示了原始值和新的值。
正如之前说的Bash 支持整数运算,当你想计算一个数组中的某个元素的位置,或者做些简单的算术运算,这还是挺有帮助的。然而,这种方法并不适合科学计算,或是某些需要小数运算的场景,比如财务统计。这些场景有其它更好的工具可以应对。
下面是个简单的算术题:
```
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63
```
好像没啥问题,但如果运算结果是浮点数会发生什么呢?
```
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1/Var2))"
Result = 0
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var2/Var1))"
Result = 1
[student@studentvm1 ~]$
```
结果会被取整。请注意运算被包含在 `echo` 语句之中,其实计算在 echo 命令结束前就已经完成了,原因是 Bash 的内部优先级。想要了解详情的话,可以在 Bash 的 man 页面中搜索 “precedence”。
### 控制运算符
Shell 的控制运算符是一种语法运算符,可以轻松地创建一些有趣的命令行程序。在命令行上按顺序将几个命令串在一起,就变成了最简单的 CLI 程序:
```
command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;
```
只要不出错,这些命令都能顺利执行。但假如出错了怎么办?你可以预设好应对出错的办法,这就要用到 Bash 内置的控制运算符, `&&``||`。这两种运算符提供了流程控制功能,使你能改变代码执行的顺序。分号也可以被看做是一种 Bash 运算符,预示着新一行的开始。
`&&` 运算符提供了如下简单逻辑,“如果 command1 执行成功,那么接着执行 command2。如果 command1 失败,就跳过 command2。”语法如下
```
command1 && command2
```
现在,让我们用命令来创建一个新的目录,如果成功的话,就把它切换为当前目录。确保你的家目录(`~`)是当前目录,先尝试在 `/root` 目录下创建,你应该没有权限:
```
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir/ && cd $Dir
mkdir: cannot create directory '/root/testdir/': Permission denied
[student@studentvm1 ~]$
```
上面的报错信息是由 `mkdir` 命令抛出的,因为创建目录失败了。`&&` 运算符收到了非零的返回码,所以 `cd` 命令就被跳过,前者阻止后者继续运行,因为创建目录失败了。这种控制流程可以阻止后面的错误累积,避免引发更严重的问题。是时候讲点更复杂的逻辑了。
当一段程序的返回码大于零时,使用 `||` 运算符可以让你在后面接着执行另一段程序。简单语法如下:
```
command1 || command2
```
解读一下,“假如 command1 失败,执行 command2”。隐藏的逻辑是如果 command1 成功,跳过 command2。下面实践一下仍然是创建新目录
```
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir || echo "$Dir was not created."
mkdir: cannot create directory '/root/testdir': Permission denied
/root/testdir was not created.
[student@studentvm1 ~]$
```
正如预期,因为目录无法创建,第一条命令失败了,于是第二条命令被执行。
`&&``||` 两种运算符结合起来才能发挥它们的最大功效。请看下面例子中的流程控制方法:
```
前置 commands ; command1 && command2 || command3 ; 跟随 commands
```
语法解释:“假如 command1 退出时返回码为零,就执行 command2否则执行 command3。”用具体代码试试
```
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
mkdir: cannot create directory '/root/testdir': Permission denied
/root/testdir was not created.
[student@studentvm1 ~]$
```
现在我们再试一次,用你的家目录替换 `/root` 目录,你将会有权限创建这个目录了:
```
[student@studentvm1 ~]$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
[student@studentvm1 testdir]$
```
`command1 && command2` 这样的控制语句能够运行的原因是,每条命令执行完毕时都会给 shell 发送一个返回码,用来表示它执行成功与否。默认情况下,返回码为 `0` 表示成功,其他任何正值表示失败。一些系统管理员使用的工具用值为 `1` 的返回码来表示失败,但其他很多程序使用别的数字来表示失败。
Bash 的内置变量 `$?` 可以显示上一条命令的返回码,可以在脚本或者命令行中非常方便地检查它。要查看返回码,让我们从运行一条简单的命令开始,返回码的结果总是上一条命令给出的。
```
[student@studentvm1 testdir]$ ll ; echo "RC = $?"
total 1264
drwxrwxr-x 2 student student 4096 Mar 2 08:21 chapter25
drwxrwxr-x 2 student student 4096 Mar 21 15:27 chapter26
-rwxr-xr-x 1 student student 92 Mar 20 15:53 TestFile1
drwxrwxr-x. 2 student student 663552 Feb 21 14:12 testdir
drwxr-xr-x. 2 student student 4096 Dec 22 13:15 Videos
RC = 0
[student@studentvm1 testdir]$
```
在这个例子中,返回码为零,意味着命令执行成功了。现在对 root 的家目录测试一下,你应该没有权限:
```
[student@studentvm1 testdir]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 testdir]$
```
本例中返回码是 `2`,表明非 root 用户没有权限进入这个目录。你可以利用这些返回码,用控制运算符来改变程序执行的顺序。
### 总结
本文将 Bash 看作一门编程语言,并从这个视角介绍了它的简单语法和基础工具。我们学习了如何将数据输出到 STDOUT怎样使用变量和控制运算符。在本系列的下一篇文章中将会重点介绍能够控制指令执行流程的逻辑运算符。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/programming-bash-part-1
作者:[David Both][a]
选题:[lujun9972][b]
译者:[jdh8383](https://github.com/jdh8383)
校对:[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/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
[2]: https://opensource.com/article/18/10/linux-data-streams
[3]: http://www.both.org/?page_id=1183
[4]: https://opensource.com/19/9/command-line-heroes-bash
[5]: https://en.wikipedia.org/wiki/Comparison_of_command_shells
[6]: http://foldoc.org/program
[7]: https://wordnet.princeton.edu/
[8]: https://en.wikipedia.org/wiki/Computer_program
[9]: https://www.gnu.org/software/bc/manual/html_mono/bc.html

View File

@@ -0,0 +1,361 @@
[#]: collector: (lujun9972)
[#]: translator: (laingke)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11533-1.html)
[#]: subject: (Initializing arrays in Java)
[#]: via: (https://opensource.com/article/19/10/initializing-arrays-java)
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
Java 中初始化数组
======
> 数组是一种有用的数据类型,用于管理在连续内存位置中建模最好的集合元素。下面是如何有效地使用它们。
![Coffee beans and a cup of coffee][1]
有使用 C 或者 FORTRAN 语言编程经验的人会对数组的概念很熟悉。它们基本上是一个连续的内存块,其中每个位置都是某种数据类型:整型、浮点型或者诸如此类的数据类型。
Java 的情况与此类似,但是有一些额外的问题。
### 一个数组的示例
让我们在 Java 中创建一个长度为 10 的整型数组:
```
int[] ia = new int[10];
```
上面的代码片段会发生什么?从左到右依次是:
1. 最左边的 `int[]` 将变量的*类型*声明为 `int` 数组(由 `[]` 表示)。
2. 它的右边是变量的名称,当前为 `ia`
3. 接下来,`=` 告诉我们,左侧定义的变量赋值为右侧的内容。
4.`=` 的右侧,我们看到了 `new`,它在 Java 中表示一个对象正在*被初始化中*,这意味着已为其分配存储空间并调用了其构造函数([请参见此处以获取更多信息][2])。
5. 然后,我们看到 `int[10]`,它告诉我们正在初始化的这个对象是包含 10 个整型的数组。
因为 Java 是强类型的,所以变量 `ia` 的类型必须跟 `=` 右侧表达式的类型兼容。
### 初始化示例数组
让我们把这个简单的数组放在一段代码中,并尝试运行一下。将以下内容保存到一个名为 `Test1.java` 的文件中,使用 `javac` 编译,使用 `java` 运行(当然是在终端中):
```
import java.lang.*;
public class Test1 {
public static void main(String[] args) {
int[] ia = new int[10]; // 见下文注 1
System.out.println("ia is " + ia.getClass()); // 见下文注 2
for (int i = 0; i < ia.length; i++) // 见下文注 3
System.out.println("ia[" + i + "] = " + ia[i]); // 见下文注 4
}
}
```
让我们来看看最重要的部分。
1. 我们声明和初始化了长度为 10 的整型数组,即 `ia`,这显而易见。
2. 在下面的行中,我们看到表达式 `ia.getClass()`。没错,`ia` 是属于一个*类*的*对象*,这行代码将告诉我们是哪个类。
3. 在紧接的下一行中,我们看到了一个循环 `for (int i = 0; i < ia.length; i++)`,它定义了一个循环索引变量 `i`,该变量遍历了从 0 到比 `ia.length` 小 1 的序列,这个表达式告诉我们在数组 `ia` 中定义了多少个元素。
4. 接下来,循环体打印出 `ia` 的每个元素的值。
当这个程序编译和运行时,它产生以下结果:
```
me@mydesktop:~/Java$ javac Test1.java
me@mydesktop:~/Java$ java Test1
ia is class [I
ia[0] = 0
ia[1] = 0
ia[2] = 0
ia[3] = 0
ia[4] = 0
ia[5] = 0
ia[6] = 0
ia[7] = 0
ia[8] = 0
ia[9] = 0
me@mydesktop:~/Java$
```
`ia.getClass()` 的输出的字符串表示形式是 `[I`,它是“整数数组”的简写。与 C 语言类似Java 数组以第 0 个元素开始,扩展到第 `<数组大小> - 1` 个元素。如上所见,我们可以看到数组 `ia` 的每个元素都(似乎由数组构造函数)设置为零。
所以,就这些吗?声明类型,使用适当的初始化器,就完成了吗?
好吧,并没有。在 Java 中有许多其它方法来初始化数组。
### 为什么我要初始化一个数组,有其它方式吗?
像所有好的问题一样,这个问题的答案是“视情况而定”。在这种情况下,答案取决于初始化后我们希望对数组做什么。
在某些情况下,数组自然会作为一种累加器出现。例如,假设我们正在编程实现计算小型办公室中一组电话分机接收和拨打的电话数量。一共有 8 个分机,编号为 1 到 8加上话务员的分机编号为 0。 因此,我们可以声明两个数组:
```
int[] callsMade;
int[] callsReceived;
```
然后,每当我们开始一个新的累计呼叫统计数据的周期时,我们就将每个数组初始化为:
```
callsMade = new int[9];
callsReceived = new int[9];
```
在每个累计通话统计数据的最后阶段,我们可以打印出统计数据。粗略地说,我们可能会看到:
```
import java.lang.*;
import java.io.*;
public class Test2 {
public static void main(String[] args) {
int[] callsMade;
int[] callsReceived;
// 初始化呼叫计数器
callsMade = new int[9];
callsReceived = new int[9];
// 处理呼叫……
// 分机拨打电话callsMade[ext]++
// 分机接听电话callsReceived[ext]++
// 汇总通话统计
System.out.printf("%3s%25s%25s\n", "ext", " calls made",
"calls received");
for (int ext = 0; ext < callsMade.length; ext++) {
System.out.printf("%3d%25d%25d\n", ext,
callsMade[ext], callsReceived[ext]);
}
}
}
```
这会产生这样的输出:
```
me@mydesktop:~/Java$ javac Test2.java
me@mydesktop:~/Java$ java Test2
ext calls made calls received
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0
8 0 0
me@mydesktop:~/Java$
```
看来这一天呼叫中心不是很忙。
在上面的累加器示例中,我们看到由数组初始化程序设置的零起始值可以满足我们的需求。但是在其它情况下,这个起始值可能不是正确的选择。
例如,在某些几何计算中,我们可能需要将二维数组初始化为单位矩阵(除沿主对角线———左上角到右下角——以外所有全是零)。我们可以选择这样做:
```
double[][] m = new double[3][3];
for (int d = 0; d < 3; d++) {
m[d][d] = 1.0;
}
```
在这种情况下,我们依靠数组初始化器 `new double[3][3]` 将数组设置为零,然后使用循环将主对角线上的元素设置为 1。在这种简单情况下我们可以使用 Java 提供的快捷方式:
```
double[][] m = {
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}};
```
这种可视结构特别适用于这种应用程序,在这种应用程序中,它便于复查数组的实际布局。但是在这种情况下,行数和列数只在运行时确定时,我们可能会看到这样的东西:
```
int nrc;
// 一些代码确定行数和列数 = nrc
double[][] m = new double[nrc][nrc];
for (int d = 0; d < nrc; d++) {
m[d][d] = 1.0;
}
```
值得一提的是Java 中的二维数组实际上是数组的数组,没有什么能阻止无畏的程序员让这些第二层数组中的每个数组的长度都不同。也就是说,下面这样的事情是完全合法的:
```
int [][] differentLengthRows = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9},
{10, 11, 12},
{13, 14},
{15}};
```
在涉及不规则形状矩阵的各种线性代数应用中,可以应用这种类型的结构(有关更多信息,请参见[此 Wikipedia 文章][5])。除此之外,既然我们了解到二维数组实际上是数组的数组,那么以下内容也就不足为奇了:
```
differentLengthRows.length
```
可以告诉我们二维数组 `differentLengthRows` 的行数,并且:
```
differentLengthRows[i].length
```
告诉我们 `differentLengthRows``i` 行的列数。
### 深入理解数组
考虑到在运行时确定数组大小的想法,我们看到数组在实例化之前仍需要我们知道该大小。但是,如果在处理完所有数据之前我们不知道大小怎么办?这是否意味着我们必须先处理一次以找出数组的大小,然后再次处理?这可能很难做到,尤其是如果我们只有一次机会使用数据时。
[Java 集合框架][6]很好地解决了这个问题。提供的其中一项是 `ArrayList` 类,它类似于数组,但可以动态扩展。为了演示 `ArrayList` 的工作原理,让我们创建一个 `ArrayList` 对象并将其初始化为前 20 个[斐波那契数字][7]
```
import java.lang.*;
import java.util.*;
public class Test3 {
public static void main(String[] args) {
ArrayList<Integer> fibos = new ArrayList<Integer>();
fibos.add(0);
fibos.add(1);
for (int i = 2; i < 20; i++) {
fibos.add(fibos.get(i - 1) + fibos.get(i - 2));
}
for (int i = 0; i < fibos.size(); i++) {
System.out.println("fibonacci " + i + " = " + fibos.get(i));
}
}
}
```
上面的代码中,我们看到:
* 用于存储多个 `Integer``ArrayList` 的声明和实例化。
* 使用 `add()` 附加到 `ArrayList` 实例。
* 使用 `get()` 通过索引号检索元素。
* 使用 `size()` 来确定 `ArrayList` 实例中已经有多少个元素。
这里没有展示 `put()` 方法,它的作用是将一个值放在给定的索引号上。
该程序的输出为:
```
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci 2 = 1
fibonacci 3 = 2
fibonacci 4 = 3
fibonacci 5 = 5
fibonacci 6 = 8
fibonacci 7 = 13
fibonacci 8 = 21
fibonacci 9 = 34
fibonacci 10 = 55
fibonacci 11 = 89
fibonacci 12 = 144
fibonacci 13 = 233
fibonacci 14 = 377
fibonacci 15 = 610
fibonacci 16 = 987
fibonacci 17 = 1597
fibonacci 18 = 2584
fibonacci 19 = 4181
```
`ArrayList` 实例也可以通过其它方式初始化。例如,可以给 `ArrayList` 构造器提供一个数组,或者在编译过程中知道初始元素时也可以使用 `List.of()``array.aslist()` 方法。我发现自己并不经常使用这些方式,因为我对 `ArrayList` 的主要用途是当我只想读取一次数据时。
此外,对于那些喜欢在加载数据后使用数组的人,可以使用 `ArrayList``toArray()` 方法将其实例转换为数组;或者,在初始化 `ArrayList` 实例之后,返回到当前数组本身。
Java 集合框架提供了另一种类似数组的数据结构,称为 `Map`(映射)。我所说的“类似数组”是指 `Map` 定义了一个对象集合,它的值可以通过一个键来设置或检索,但与数组(或 `ArrayList`)不同,这个键不需要是整型数;它可以是 `String` 或任何其它复杂对象。
例如,我们可以创建一个 `Map`,其键为 `String`,其值为 `Integer` 类型,如下:
```
Map<String, Integer> stoi = new Map<String, Integer>();
```
然后我们可以对这个 `Map` 进行如下初始化:
```
stoi.set("one",1);
stoi.set("two",2);
stoi.set("three",3);
```
等类似操作。稍后,当我们想要知道 `"three"` 的数值时,我们可以通过下面的方式将其检索出来:
```
stoi.get("three");
```
在我的认知中,`Map` 对于将第三方数据集中出现的字符串转换为我的数据集中的一致代码值非常有用。作为[数据转换管道][8]的一部分,我经常会构建一个小型的独立程序,用作在处理数据之前清理数据;为此,我几乎总是会使用一个或多个 `Map`
值得一提的是,`ArrayList``ArrayList``Map``Map` 是很可能的有时也是合理的。例如假设我们在看树我们对按树种和年龄范围累计树的数目感兴趣。假设年龄范围定义是一组字符串值“young”、“mid”、“mature” 和 “old”物种是 “Douglas fir”、“western red cedar” 等字符串值,那么我们可以将这个 `Map` 中的 `Map` 定义为:
```
Map<String, Map<String, Integer>> counter = new Map<String, Map<String, Integer>>();
```
这里需要注意的一件事是,以上内容仅为 `Map` 的*行*创建存储。因此,我们的累加代码可能类似于:
```
// 假设我们已经知道了物种和年龄范围
if (!counter.containsKey(species)) {
counter.put(species,new Map<String, Integer>());
}
if (!counter.get(species).containsKey(ageRange)) {
counter.get(species).put(ageRange,0);
}
```
此时,我们可以这样开始累加:
```
counter.get(species).put(ageRange, counter.get(species).get(ageRange) + 1);
```
最后值得一提的是Java 8 中的新特性Streams 还可以用来初始化数组、`ArrayList` 实例和 `Map` 实例。关于此特性的详细讨论可以在[此处][9]和[此处][10]中找到。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/initializing-arrays-java
作者:[Chris Hermansen][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/clhermansen
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/java-coffee-mug.jpg?itok=Bj6rQo8r (Coffee beans and a cup of coffee)
[2]: https://opensource.com/article/19/8/what-object-java
[3]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[5]: https://en.wikipedia.org/wiki/Irregular_matrix
[6]: https://en.wikipedia.org/wiki/Java_collections_framework
[7]: https://en.wikipedia.org/wiki/Fibonacci_number
[8]: https://towardsdatascience.com/data-science-for-startups-data-pipelines-786f6746a59a
[9]: https://stackoverflow.com/questions/36885371/lambda-expression-to-initialize-array
[10]: https://stackoverflow.com/questions/32868665/how-to-initialize-a-map-using-a-lambda

View File

@@ -0,0 +1,261 @@
[#]: collector: (lujun9972)
[#]: translator: (wenwensnow)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11557-1.html)
[#]: subject: (How to dual boot Windows 10 and Debian 10)
[#]: via: (https://www.linuxtechi.com/dual-boot-windows-10-debian-10/)
[#]: author: (James Kiarie https://www.linuxtechi.com/author/james/)
如何拥有一个 Windows 10 和 Debian 10 的双系统
======
在无数次劝说自己后,你终于做出了一个大胆的决定,试试 Linux。不过在完全熟悉 Linux 之前,你依旧需要使用 Windows 10 系统。幸运的是,通过一个双系统引导设置,能让你在启动时,选择自己想要进入的系统。在这个指南中,你会看到如何 如何双重引导 Windows 10 和 Debian 10。
![如何拥有一个 Windows 10 和 Debian 10 的双系统][2]
### 前提条件
在开始之前,确保你满足下列条件:
* 一个 Debian 10 的可引导 USB 或 DVD
* 一个快速且稳定的网络(为了安装更新以及第三方软件)
另外记得注意你系统的引导策略UEFI 或 Legacy需要确保两个系统使用同一种引导模式。
### 第一步:在硬盘上创建一个空余分区
第一步,你需要在你的硬盘上创建一个空余分区。之后,这将是我们安装 Debian 系统的地方。为了实现这一目的,需要使用下图所示的磁盘管理器:
同时按下 `Windows + R` 键,启动“运行程序”。接下来,输入 `diskmgmt.msc`,按回车键。
![启动“运行程序”][3]
这会启动“磁盘管理”窗口,它会显示你 Windows 上所有已有磁盘。
![磁盘管理][4]
接下来,你需要为安装的 Debian 系统创建空余空间。为此,你需要缩小其中一个磁盘(卷)上的分区,从而创建一个未分配的新分区。在这个例子里,我会从 D 盘中创建一个 30 GB 的新分区。
为了缩小一个卷,右键点击它,然后选中选项 “<ruby>缩小<rt>Shrink volume...</rt></ruby>”。
![缩小卷][5]
在弹出窗口中,定义你想缩小的空间大小。记住,这是将来要安装 Debian 10 的磁盘空间。我选择了 30000MB大约 30 GB。压缩完成后点击“<ruby>缩小<rt>Shrink</rt></ruby>”。
![缩小空间][6]
在缩小操作结束后,你会看到一个如下图所示的未分配分区:
![未分配分区][7]
完美!现在可以准备开始安装了。
### 第二步:开始安装 Debian 10
空余分区已经创建好了,将你的可引导 USB 或安装 DVD 插入电脑,重新启动系统。记得更改 BIOS 中的引导顺序,需要在启动时按住功能键(通常,根据品牌不同,是 `F9``F10``F12` 中的某一个)。 这一步骤,对系统是否能进入安装媒体来说,至关重要。保存 BIOS 设置,并重启电脑。
如下图所示,界面会显示一个新的引导菜单:点击 “Graphical install”。
![图形化界面安装][8]
下一步,选择你的偏好语言,然后点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![设置语言-Debian10][9]
接着,选择你的地区,点击“<ruby>继续<rt>Continue</rt></ruby>”。 根据地区,系统会自动选择当地对应的时区。如果你无法找到你所对应的地区,将界面往下拉, 点击“<ruby>其他<rt>Other</rt></ruby>”后,选择相对应位置。
![选择地区-Debain10][10]
而后,选择你的键盘布局。
![设置键盘-Debain10][11]
接下来,设置系统的主机名,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![设置主机名-Debian10][12]
下一步,确定域名。如果你的电脑不在域中,直接点击 “<ruby>继续<rt>Continue</rt></ruby>”按钮。
![设置域名-Debian10][13]
然后,如图所示,设置 root 密码,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![设置 root 密码-Debian10][14]
下一步骤,设置账户的用户全名,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![设置用户全名-debain10][15]
接着,设置与此账户相关联的用户名。
![指定用户名-Debian10][16]
下一步,设置用户密码,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![设置用户密码-Debian10][17]
然后,设置时区。
![设置时区-Debian10][18]
这时,你要为 Debian10 安装创建分区。如果你是新手用户,点击菜单中的第一个选项,“<ruby>使用最大的连续空余空间<rt>Use the largest continuous free space</rt></ruby>”,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![使用最大的连续空余空间-debian10][19]
不过,如果你对创建分区有所了解的话,选择“<ruby>手动<rt>Manual</rt></ruby>” 选项,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![选择手动-Debain10][20]
接着,选择被标记为 “<ruby>空余空间<rt>FREE SPACE</rt></ruby>” 的磁盘,点击 “<ruby>继续<rt>Continue</rt></ruby>” 。接下来,点击“<ruby>创建新分区<rt>Create a new partition</rt></ruby>”。
![创建新分区-Debain10][21]
下一界面,首先确定交换空间大小。我的交换空间大小为 2GB点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![确定交换空间大小-debian10][22]
点击下一界面的 “<ruby>主分区<rt>Primary</rt></ruby>”,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![磁盘主分区-Debian10][23]
选择在磁盘 “<ruby>初始位置<rt>beginning</rt></ruby>” 创建新分区后,点击继续。
![在初始位置创建-Debain10][24]
选择 “<ruby>Ext 4 日志文件系统<rt>Ext 4 journaling file system</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![选择 Ext4 日志文件系统-debain10][25]
下个界面选择“<ruby>交换空间<rt>swap space</rt></ruby>” ,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![选择交换空间-debian10][26]
选中 “<ruby>完成此分区设置<rt>done setting the partition</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![完成此分区设置-debian10][27]
返回磁盘分区界面,点击 “<ruby>空余空间<rt>FREE SPACE</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![点击空余空间-Debain10][28]
为了让自己能轻松一点,选中 “<ruby>自动为空余空间分区<rt>Automatically partition the free space</rt></ruby>”后,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![自动为空余空间分区-Debain10][29]
接着点击 “<ruby>将所有文件存储在同一分区(新手用户推荐)<rt>All files in one partition (recommended for new users)</rt></ruby>”。
![将所有文件存储在同一分区-debian10][30]
最后, 点击 “<ruby>完成分区设置,并将改动写入磁盘<rt>Finish partitioning and write changes to disk</rt></ruby>” ,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![完成分区设置,并将改动写入磁盘][31]
确定你要将改动写入磁盘,点击 “<ruby>是<rt>Yes</rt></ruby>”。
![将改动写入磁盘-Debian10][32]
而后,安装程序会开始安装所有必要的软件包。
当系统询问是否要扫描其他 CD 时,选择 “<ruby>否<rt>No</rt></ruby>” ,并点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![扫描其他CD-No-Debain10][33]
接着,选择离你最近的镜像站点地区,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![Debian-镜像站点-国家][34]
然后,选择最适合你的镜像站点,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![选择镜像站点][35]
如果你打算使用代理服务器,在下面输入具体信息,没有的话就留空,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![输入代理信息-debian10][36]
随着安装进程的继续, 你会被问到,是否想参加一个软件包用途调查。你可以选择任意一个选项,之后点击“<ruby>继续<rt>Continue</rt></ruby>”,我选择了“<ruby>否<rt>No</rt></ruby>”。
![参与调查-debain10][37]
在软件选择窗口选中你想安装的软件包,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![软件选择-debian10][38]
安装程序会将选中的软件一一安装,在这期间,你可以去喝杯咖啡休息一下。
系统将会询问你,是否要将 grub 的引导装载程序安装到主引导记录表MBR上。点击 “<ruby>是<rt>Yes</rt></ruby>”,而后点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![安装-grub-bootloader-debian10][39]
接着,选中你想安装 grub 的硬盘,点击“<ruby>继续<rt>Continue</rt></ruby>”。
![选择硬盘-安装 grub-Debian10][40]
最后,安装完成,直接点击 “<ruby>继续<rt>Continue</rt></ruby>”。
![安装完成-重新启动-debian10][41]
你现在应该会有一个列出 Windows 和 Debian 的 grub 菜单。为了引导 Debian 系统,往下选择 Debian。之后你就能看见登录界面。输入密码之后按回车键。
![Debian10-登录][42]
这就完成了!这样,你就拥有了一个全新的 Debian 10 和 Windows 10 双系统。
![Debian10-Buster-Details][43]
--------------------------------------------------------------------------------
via: https://www.linuxtechi.com/dual-boot-windows-10-debian-10/
作者:[James Kiarie][a]
选题:[lujun9972][b]
译者:[wenwensnow](https://github.com/wenwensnow)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.linuxtechi.com/author/james/
[b]: https://github.com/lujun9972
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/How-to-dual-boot-Windows-and-Debian10.jpg
[3]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Launch-Run-dialogue.jpg
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Disk-management.jpg
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Shrink-volume.jpg
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Shrink-space.jpg
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Unallocated-partition.jpg
[8]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Graphical-Install-Debian10.jpg
[9]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Language-Debian10.jpg
[10]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-location-Debain10.jpg
[11]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Configure-Keyboard-layout-Debain10.jpg
[12]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-hostname-Debian10.jpg
[13]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-domain-name-Debian10.jpg
[14]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-root-Password-Debian10.jpg
[15]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-fullname-user-debain10.jpg
[16]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-username-Debian10.jpg
[17]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-user-password-Debian10.jpg
[18]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Configure-timezone-Debian10.jpg
[19]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Use-largest-continuous-free-space-debian10.jpg
[20]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Manual-Debain10.jpg
[21]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Create-new-partition-Debain10.jpg
[22]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Define-swap-space-debian10.jpg
[23]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Partition-Disks-Primary-Debain10.jpg
[24]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Start-at-the-beginning-Debain10.jpg
[25]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Ext4-Journaling-system-debain10.jpg
[26]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-swap-debain10.jpg
[27]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Done-setting-partition-debian10.jpg
[28]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Click-Free-space-Debain10.jpg
[29]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Automatically-partition-free-space-Debain10.jpg
[30]: https://www.linuxtechi.com/wp-content/uploads/2019/10/All-files-in-one-partition-debian10.jpg
[31]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Finish-partitioning-write-changes-to-disk.jpg
[32]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Write-changes-to-disk-Yes-Debian10.jpg
[33]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Scan-another-CD-No-Debain10.jpg
[34]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian-archive-mirror-country.jpg
[35]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Debian-archive-mirror.jpg
[36]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Enter-proxy-details-debian10.jpg
[37]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Participate-in-survey-debain10.jpg
[38]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Software-selection-debian10.jpg
[39]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Install-grub-bootloader-debian10.jpg
[40]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-hard-drive-install-grub-Debian10.jpg
[41]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Installation-complete-reboot-debian10.jpg
[42]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian10-log-in.jpg
[43]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian10-Buster-Details.jpg

View File

@@ -0,0 +1,116 @@
[#]: collector: (lujun9972)
[#]: translator: (Morisun029)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11534-1.html)
[#]: subject: (Open Source CMS Ghost 3.0 Released with New features for Publishers)
[#]: via: (https://itsfoss.com/ghost-3-release/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
开源 CMS Ghost 3.0 发布,带来新功能
======
[Ghost][1] 是一个自由开源的内容管理系统CMS。如果你还不了解 CMS那我在此解释一下。CMS 是一种软件,用它可以构建主要专注于创建内容的网站,而无需了解 HTML 和其他与 Web 相关的技术。
事实上Ghost 是目前[最好的开源 CMS][2] 之一。它主要聚焦于创建轻量级、快速加载、界面美观的博客。
Ghost 系统有一个现代直观的编辑器,该编辑器内置 SEO搜索引擎优化功能。你也可以用本地桌面包括 Linux 系统)和移动应用程序。如果你喜欢终端,也可以使用其提供的 CLI命令行界面工具。
让我们看看 Ghost 3.0 带来了什么新功能。
### Ghost 3.0 的新功能
![][3]
我通常对开源的 CMS 解决方案很感兴趣。因此,在阅读了官方公告后,我通过在 Digital Ocean 云服务器上安装新的 Ghost 实例来进一步尝试它。
与以前的版本相比Ghost 3.0 在功能和用户界面上的改进给我留下了深刻的印象。
在此,我将列出一些值得一提的关键点。
#### 书签卡
![][5]
除了编辑器的所有细微更改之外3.0 版本现在支持通过输入 URL 添加漂亮的书签卡。
如果你使用过 WordPress你可能已经注意到WordPress 需要添加一个插件才能添加类似的卡片),所以该功能绝对是 Ghost 3.0 系统的一个最大改进。
#### 改进的 WordPress 迁移插件
我没有专门对此进行测试,但它更新了 WordPress 的迁移插件,可以让你轻松地将帖子(带有图片)克隆到 Ghost CMS。
基本上,使用该插件,你就能够创建一个存档(包含图片)并将其导入到 Ghost CMS。
#### 响应式图像库和图片
为了使用户体验更好Ghost 团队还更新了图像库(现已为响应式),以便在所有设备上舒适地呈现你的图片集。
此外,帖子和页面中的图片也更改为响应式的了。
#### 添加成员和订阅选项
![Ghost Subscription Model][6]
虽然,该功能目前还处于测试阶段,但如果你是以此平台作为维持你业务关系的重要发布平台,你可以为你的博客添加成员、订阅选项。
该功能可以确保只有订阅的成员才能访问你的博客,你也可以选择让未订阅者也可以访问。
#### Stripe集成支付功能
默认情况下,该版本支持 Stripe 付款网关,帮助你轻松启用订阅功能(或使用任何类型的付款的付款方式),而 Ghost 不收取任何额外费用。
#### 新的应用程序集成
![][7]
你现在可以在 Ghost 3.0 的博客中集成各种流行的应用程序/服务。它可以使很多事情自动化。
#### 默认主题改进
引入的默认主题(设计)已得到改进,现在也提供了夜间模式。
你也可以随时选择创建自定义主题(如果没有可用的预置主题)。
#### 其他小改进
除了所有关键亮点以外,用于创建帖子/页面的可视编辑器也得到了改进(具有某些拖放功能)。
我确定还有很多技术方面的更改,如果你对此感兴趣,可以在他们的[更改日志][8]中查看。
### Ghost 影响力渐增
要在以 WordPress 为主导的世界中获得认可并不是一件容易的事。但 Ghost 逐渐形成了它的一个专门的发布者社区。
不仅如此,它的托管服务 [Ghost Pro][9] 现在拥有像 NASA、Mozilla 和 DuckDuckGo 这样的客户。
在过去的六年中Ghost 从其 Ghost Pro 客户那里获得了 500 万美元的收入。就从它是致力于开源系统解决方案的非营利组织这一点来讲,这确实是一项成就。
这些收入有助于它们保持独立避免风险投资家的外部资金投入。Ghost CMS 的托管客户越多,投入到免费和开源的 CMS 的研发款项就越多。
总体而言Ghost 3.0 是迄今为止提供的最好的升级版本。这些功能给我留下了深刻的印象。
如果你拥有自己的网站,你会使用什么 CMS你曾经使用过 Ghost 吗?你的体验如何?请在评论部分分享你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/ghost-3-release/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[Morisun029](https://github.com/Morisun029)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/recommends/ghost/
[2]: https://itsfoss.com/open-source-cms/
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-3.jpg?ssl=1
[4]: https://itsfoss.com/recommends/digital-ocean/
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-editor-screenshot.png?ssl=1
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-subscription-model.jpg?resize=800%2C503&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-app-integration.jpg?ssl=1
[8]: https://ghost.org/faq/upgrades/
[9]: https://itsfoss.com/recommends/ghost-pro/

View File

@@ -0,0 +1,93 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-11528-1.html)
[#]: subject: (4 cool new projects to try in COPR for October 2019)
[#]: via: (https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-october-2019/)
[#]: author: (Dominik Turecek https://fedoramagazine.org/author/dturecek/)
COPR 仓库中 4 个很酷的新项目2019.10
======
![][1]
COPR 是个人软件仓库[集合][2],它不在 Fedora 中。这是因为某些软件不符合轻松打包的标准;或者它可能不符合其他 Fedora 标准尽管它是自由而开源的。COPR 可以在 Fedora 套件之外提供这些项目。COPR 中的软件不受 Fedora 基础设施的支持,或者是由项目自己背书的。但是,这是一种尝试新的或实验性的软件的一种巧妙的方式。
本文介绍了 COPR 中一些有趣的新项目。如果你第一次使用 COPR请参阅 [COPR 用户文档][3]。
### Nu
[Nu][4] 也被称为 Nushell是受 PowerShell 和现代 CLI 工具启发的 shell。通过使用基于结构化数据的方法Nu 可轻松处理命令的输出并通过管道传输其他命令。然后将结果显示在可以轻松排序或过滤的表中并可以用作其他命令的输入。最后Nu 提供了几个内置命令、多 shell 和对插件的支持。
#### 安装说明
该[仓库][5]目前为 Fedora 30、31 和 Rawhide 提供 Nu。要安装 Nu请使用以下命令
```
sudo dnf copr enable atim/nushell
sudo dnf install nushell
```
### NoteKit
[NoteKit][6] 是一个笔记程序。它支持 Markdown 来格式化笔记,并支持使用鼠标创建手绘笔记的功能。在 NoteKit 中,笔记以树状结构进行排序和组织。
#### 安装说明
该[仓库][7]目前为 Fedora 29、30、31 和 Rawhide 提供 NoteKit。要安装 NoteKit请使用以下命令
```
sudo dnf copr enable lyessaadi/notekit
sudo dnf install notekit
```
### Crow Translate
[Crow Translate][8] 是一个翻译程序。它可以翻译文本并且可以对输入和结果发音它还提供命令行界面。对于翻译Crow Translate 使用 Google、Yandex 或 Bing 的翻译 API。
#### 安装说明
该[仓库][9]目前为 Fedora 30、31 和 Rawhide 以及 Epel 8 提供 Crow Translate。要安装 Crow Translate请使用以下命令
```
sudo dnf copr enable faezebax/crow-translate
sudo dnf install crow-translate
```
### dnsmeter
[dnsmeter][10] 是用于测试域名服务器及其基础设施性能的命令行工具。为此,它发送 DNS 查询并计算答复数从而测量各种统计数据。除此之外dnsmeter 可以使用不同的加载步骤,使用 PCAP 文件中的载荷和欺骗发送者地址。
#### 安装说明
该仓库目前为 Fedora 29、30、31、Rawhide 以及 Epel 7 提供 dnsmeter。要安装 dnsmeter请使用以下命令
```
sudo dnf copr enable @dnsoarc/dnsmeter
sudo dnf install dnsmeter
```
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-october-2019/
作者:[Dominik Turecek][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://fedoramagazine.org/author/dturecek/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2017/08/4-copr-945x400.jpg
[2]: https://copr.fedorainfracloud.org/
[3]: https://docs.pagure.org/copr.copr/user_documentation.html#
[4]: https://github.com/nushell/nushell
[5]: https://copr.fedorainfracloud.org/coprs/atim/nushell/
[6]: https://github.com/blackhole89/notekit
[7]: https://copr.fedorainfracloud.org/coprs/lyessaadi/notekit/
[8]: https://github.com/crow-translate/crow-translate
[9]: https://copr.fedorainfracloud.org/coprs/faezebax/crow-translate/
[10]: https://github.com/DNS-OARC/dnsmeter

Some files were not shown because too many files have changed in this diff Show More