Merge pull request #2 from LCTT/master

updated
This commit is contained in:
aREversez 2022-03-27 15:19:29 +08:00 committed by GitHub
commit a9565386d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 6838 additions and 5784 deletions

View File

@ -0,0 +1,140 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14356-1.html)
[#]: subject: (Why I switched from Mac to Linux)
[#]: via: (https://opensource.com/article/20/3/mac-linux)
[#]: author: (Lee Tusman https://opensource.com/users/leeto)
我为什么从 Mac 转到 Linux
======
> 25 年后,我转到了 Linux简直不能更爽了。以下是我的经历。
![](https://img.linux.net.cn/data/attachment/album/202203/14/093159h433g7j2ytz4g4xz.jpg)
1994 年,我的家人买了一台 Macintosh Performa 475 作为家用电脑。我在学校时曾使用过 Macintosh SE 电脑,并通过《[Mavis Beacon 教你打字][2]》学会了打字,所以我成为 Mac 用户已经超过 25 年了。早在上世纪 90 年代中期,我就被 Mac 的易用性所吸引。它不是以 DOS 命令提示符开始的;它打开的是一个友好的桌面。它很有趣。尽管 Macintosh 的软件比 PC 少得多,但我认为 Mac 的生态系统更好,就凭着 KidPix 和 Hypercard我仍然认为它们是无与伦比的、最直观的 _创意工厂_
即便如此,我仍然感觉到,与 Windows 相比Mac 只是个弟弟。我曾觉得这个公司或许有一天会消失。但几十年后的今天,苹果已经成为一个庞然大物,一个价值万亿美元的公司。但随着发展,它发生了重大变化。有些变化是为了更好的发展,比如更好的稳定性,更简单的硬件选择,更高的安全性,以及更多的可访问性选项。其他的变化让我恼火 —— 不是一下子,而是慢慢地不满意。最重要的是,我对苹果的封闭生态系统感到厌烦 —— 没有 iPhoto 就很难访问照片;必须使用 iTunes即使我不想使用苹果商店的生态系统也得强制捆绑。
随着时间的推移,我发现自己主要是在终端上工作。我使用 iTerm2 和 [Homebrew][3] 软件包管理器。虽然我不能让我所有的 Linux 软件都工作但大部分软件都工作了。我认为我拥有两个世界中最好的东西macOS 的图形操作系统和用户界面,以及快速打开终端会话的能力。
后来,我开始使用通过 Raspbian 启动的树莓派电脑。我还收集了一些从大学的垃圾堆中抢救出来的非常旧的笔记本电脑,因此,出于需要,我决定尝试各种 Linux 发行版。虽然它们都没有成为我的主用机器,但我开始真正喜欢使用 Linux。我开始考虑尝试运行 Linux 发行版作为我的日常用机,但我认为 Macbook 的舒适性和便利性,特别是硬件的尺寸和重量,在非 Mac 笔记本电脑中很难找到。
### 是时候进行转换了?
大约两年前,我开始在工作中使用一台戴尔电脑。那是一台较大的笔记本电脑,集成了 GPU可以双启动 Linux 和 Windows。我用它来进行游戏开发、3D 建模、一些机器学习,以及用 C# 和 Java 进行基本编程。我曾考虑把它作为我的主用机器,但我喜欢我的 Macbook Air 的便携性,所以也继续使用它。
去年秋天,我开始注意到我的 Air 运行时很热,而且风扇开得越来越频繁。我的主用机器开始显得垂垂老矣。多年来,我使用 Mac 的终端来访问类 Unix 的 Darwin 操作系统,我在终端和网页浏览器之间切换的时间越来越多。是时候进行转换了吗?
我开始探索一个类似 Macbook 的 Linux 笔记本电脑的可能性。在做了一些研究、阅读测评和留言板之后,我选择了长期以来备受赞誉的戴尔 XPS 13 开发者版 7390选择了第十代 i7。我选择它是因为我喜欢 Macbook尤其是超薄的 Macbook Air的感觉而对 XPS 13 的评论表明它似乎是类似的笔记本电脑,对其触控板和键盘的评价也真的很好。
最重要的是,它装载了 Ubuntu。虽然买一台电脑擦掉它然后安装一个新的 Linux 发行版是很容易的,但我被这种配合得当的操作系统和硬件所吸引,而且它允许我们进行大量的定制,就像我们在 Linux 中了解而喜爱的一样。因此,当有促销活动时,我毅然决然地购买了它。
### 每天运行 Linux 是什么感觉
如今,我使用 XPS 13 已经有三个月了,我的双启动的 Linux 工作笔记本也有两年了。起初,我以为我会花更多的时间寻找一个更像 Mac 的替代桌面环境或窗口管理器,比如 [Enlightenment][4]。我试过几个,但我不得不说,我喜欢开箱即用的 [GNOME][5] 的简单性。首先,它是精简的;没有太多的 GUI 元素会吸引你的注意力。事实上,它很直观,这份 [概览][6] 只需要几分钟就能看完。 
我可以通过应用程序仪表盘或按网格排布的按钮访问我的应用程序,从而进入应用程序视图。要访问我的文件系统,我点击仪表盘上的“文件”图标。要打开 GNOME 终端,我输入 `Ctrl+Alt+T` 或者直接按下 `Alt+Tab` 来在打开的应用程序和打开的终端之间切换。定义你自己的 [自定义热键快捷方式][7] 也很容易。
除此以外,没有太多要说的。与 Mac 的桌面不同,没有那么多的东西会让人迷失,这意味着让我从工作或我想运行的应用程序中分心的东西更少。我没有看到我在 Mac 上浏览窗口的那么多选项,也不必在导航时花费那么多时间。在 Linux 中,只有文件、应用程序和终端。
我安装了 [i3 平铺式窗口管理器][8] 来做一个测试。我在配置上遇到了一些问题,因为我是用 [德沃夏克键盘][9] 键入的,而 i3 并不适应另一种键盘配置。我想,如果再努力一点,我可以在 i3 中找出一个新的键盘映射,但我主要想找的是简单的平铺功能。
我看了 GNOME 的平铺功能,并感到非常惊喜。你按下 `Super` 键(对我来说,就是有 Windows 标志的那个键 —— 我应该用贴纸盖住它!),然后按一个修饰键。例如,按 `Super + ←` 将你当前的窗口移动到屏幕左侧的贴片上。`Super + →` 移动到右半边。`Super + ↑` 使当前窗口最大化。`Super + ↓` 则恢复到之前的大小。你可以用 `Alt+Tab` 在应用程序窗口之间移动。这些都是默认行为,可以在键盘设置中自定义。
插上耳机或连接到 HDMI 的工作方式与你预期的一样。有时,我打开声音设置,在 HDMI 声音输出或我的外部音频线之间进行切换,就像我在 Mac 或 PC 上那样。触控板的反应很灵敏,我没有注意到与 Macbook 的有什么不同。当我插入一个三键鼠标时,它可以立即工作,即使是用我的蓝牙鼠标和键盘。
#### 软件
我在几分钟内安装了 Atom、VLC、Keybase、Brave 浏览器、Krita、Blender 和 Thunderbird。我在终端用 Apt 软件包管理器安装了其他软件(和平常一样),它比 macOS 的 Homebrew 软件包管理器提供了更多软件包。
#### 音乐
我有许多种听音乐的选择。我使用 Spotify 和 [PyRadio][10] 来串流播放音乐。[Rhythmbox][11] 在 Ubuntu 上是默认安装的;这个简单的音乐播放器可以立即启动,而且毫不臃肿。只需点击菜单,选择“添加音乐”,然后导航到一个音乐目录(它会递归搜索)。你也可以轻松地串流播客或在线广播。
#### 文本和 PDF
我倾向于在带有一些插件的 [Neovim][12] 中用 Markdown 写作,然后用 Pandoc 将我的文档转换为任何最终需要的格式。对于一个带有预览功能的漂亮的 Markdown 编辑器,我下载了 [Ghostwriter][13],一个最集中注意力的写作应用程序。
如果有人给我发了一个微软 Word 文档,我可以用默认的 LibreOffice Writer 应用程序打开它。
偶尔,我也要签署一份文件。用 macOS 的“预览”应用程序和我的 PNG 格式的签名,这很容易,我需要一个 Linux 的对应工具。我发现默认的 PDF 查看器应用程序没有我需要的注释工具。LibreOffice 绘图程序是可以接受的,但不是特别容易使用,而且它偶尔会崩溃。做了一些研究后,我安装了 [Xournal][14],它有我需要的简单的注释工具,可以添加日期、文字和我的签名,而且与 Mac 的预览程序相当。它完全能满足我的需要。
#### 从我的手机中导入图片
我有一个 iPhone。为了把我的图片从手机上拿下来有很多方法可以同步和访问你的文件。如果你有一个不同的手机你的过程可能是不同的。下面是我的方法
1. 用 `sudo apt install gvfs-backends` 来安装 `gvfs-backends`,它是 GNOME 虚拟文件系统的一部分。
2. 获取你的手机的序列号。将你的手机插入你的电脑,在你的 iPhone 上点击“信任”。在你电脑的终端输入:
```
lsusb -v 2> /dev/null | grep -e "Apple Inc" -A 2
```
(感谢 Stack Oveflow 用户 [complistic][15] 提供的这个代码技巧)。
3. 现在打开你的文件系统。
- 按 `Ctrl+L` 打开一个位置并输入:`afc://<你的序列号>`,(请替换 `<你的序列号>`)来打开并导航到你的 DCIM 文件夹。我的照片和视频在 DCIM 文件夹的五个子文件夹内,而不是在照片文件夹内。从这里你可以手动将它们移到你的电脑上。
- 挂载手机文件系统后,你也可以在终端中通过以下方式导航到你的文件:
```
cd /run/user/1001/gvfs/afc:host=<你的序列号>
```
#### 图形、照片、建模和游戏引擎
我是一名教育工作者,教授各种新媒体课程。我的许多同事和学生都订阅了价格昂贵的专有的 Adobe Creative Suite。我喜欢让我的学生知道他们还有其他选择。
对于绘图和图形编辑,我使用 [Krita][16]。这绝对是我的 Photoshop 替代品。对于插图工作,还有 [Inkscape][17] 和 Scribus 的出版软件。对于自动编辑,我使用命令行 [ImageMagick][18] 程序,它已经预装在 Ubuntu 中。
为了管理我的图像,我使用简单的 [Shotwell][19] 应用程序。
对于 3D 建模,我使用并教授开源的 [Blender][20] 软件。在我的学校,我们教 [Unity 3d][21],它有 Linux 版本。它运行良好,但我一直想试试 [Godot][22],一个开源的替代品。
#### 开发
我的 XPS 13 安装了 Chrome 和 Chromium。我还添加了 Firefox 和 [Brave][23] 浏览器。所有都和你在 Mac 或 PC 上习惯的一样。大多数时候,我在 Atom 中进行开发工作,有时在 Visual Studio Code 中进行,这两种软件都很容易安装在 Linux 上。Vim 已经预装在终端,而我首选的终端文本编辑器 Neovim也很容易安装。
几周后,我开始尝试其他终端。我目前最喜欢的是 Enlightenment 基金会的 Terminology。首先它允许你在终端中 [查看图片][24],这在 Mac 的终端中是很难做到的。
### 留在这里
我看不出自己会转回 Mac 作为我的日用电脑。现在,当我使用 Mac 时,我注意到超多的选项和运行一个应用程序或浏览某个地方所需的额外步骤。我还注意到它的运行速度有点慢,或许这只是我个人的感受?
现在我已经转到了一个开源的生态系统和 Linux我很高兴没有必要再转回去。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/3/mac-linux
作者:[Lee Tusman][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/leeto
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_development_programming.png?itok=4OM29-82
[2]: https://en.wikipedia.org/wiki/Mavis_Beacon_Teaches_Typing
[3]: https://brew.sh/
[4]: https://www.enlightenment.org/
[5]: https://opensource.com/downloads/cheat-sheet-gnome-3
[6]: https://help.gnome.org/users/gnome-help/stable/shell-introduction.html.en
[7]: https://docs.fedoraproject.org/en-US/quick-docs/proc_setting-key-shortcut/
[8]: https://opensource.com/article/18/9/i3-window-manager-cheat-sheet
[9]: https://en.wikipedia.org/wiki/Dvorak_keyboard_layout
[10]: https://opensource.com/article/19/11/pyradio
[11]: https://wiki.gnome.org/Apps/Rhythmbox
[12]: https://neovim.io/
[13]: https://wereturtle.github.io/ghostwriter/
[14]: http://xournal.sourceforge.net/
[15]: https://stackoverflow.com/questions/19032162/is-there-a-way-since-ios-7s-release-to-get-the-udid-without-using-itunes-on-a/21522291#21522291
[16]: https://opensource.com/article/19/4/design-posters
[17]: https://opensource.com/article/19/1/inkscape-cheat-sheet
[18]: https://opensource.com/article/17/8/imagemagick
[19]: https://gitlab.gnome.org/GNOME/shotwell/
[20]: https://opensource.com/article/18/4/5-best-blender-video-tutorials-beginners
[21]: https://unity.com/
[22]: https://opensource.com/article/17/12/get-started-developing-games-godot
[23]: https://brave.com/
[24]: https://www.enlightenment.org/about-terminology.md

View File

@ -0,0 +1,166 @@
[#]: collector: (lujun9972)
[#]: translator: (amagicboy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14398-1.html)
[#]: subject: (How to Uninstall Applications from Ubuntu Linux)
[#]: via: (https://itsfoss.com/uninstall-programs-ubuntu/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
初级Ubuntu 中怎么卸载 Linux 应用
=======
![](https://img.linux.net.cn/data/attachment/album/202203/26/151617chxhdszd0lcpcpkz.jpg)
不再使用某个应用程序了?删除它吧。
卸载不再使用的应用是 [最简单释放磁盘空间的方法][1] ,而且可以使系统保持整洁。
在此篇入门教程中,我会介绍几种不同在 Ubuntu 上卸载应用程序的方法。
在 Ubuntu 中有几种方法 [安装应用][2] ,同意也有以下几种方法卸载应用:
- 从 Ubuntu <ruby>软件中心<rt>Software Center</rt></ruby> 卸载应用(桌面用户)
- 用 `apt remove` 命令卸载应用
- 用命令行中删除 Snap 应用(中级到高级用户)
让我们来一个一个了解这些方法。
### 方法 1用 Ubuntu 软件中心卸载应用
在左侧栏或者菜单中找到 Ubuntu <ruby>软件中心<rt>Software Center</rt></ruby>,打开它。
![][3]
<ruby>已安装<rt>Installed</rt></ruby> 栏中列出了已安装的应用。
![][4]
如果你要找的应用不在 <ruby>已安装<rt>Installed</rt></ruby> 栏中,可以使用搜索查找应用。
![][5]
打开已经安装的应用,有一个 <ruby>移除<rt>Remove</rt></ruby> 选项,点击它。
![][6]
这会请求输入账户密码,输入后应用会在几秒内删除。
### 方法2 Ubuntu 命令行卸载应用
安装应用时使用 `apt-get install` 或者 `apt install`
卸载应用时使用 `apt-get remove` 或者 `apt remove` ,而不是 `apt-get uninstall`
按照以下方式使用命令:
```
sudo apt remove program_name
```
执行此操作会请求你的账户密码。当输入密码时,屏幕上不会有提示。输入完后按下回车。
待删除的应用不会立刻被删除。你需要确认。当询问你的确认时,请输入回车或者按下 `Y`
![][7]
请在命令行中输入准确的包的名字,不然会出现 “[不能找到软件包的错误][8]” 错误 。
不要担心记不住具体的应用名字,你可以使用超级有用的 Tab 补全应用名称。 Tab 是你必须知道的 [Linux 命令行技巧][9] 之一。
你只需要输入想要卸载应用的前几个字母,然后按下 `tab` ,会提示以这几个字母开头的已安装应用程序。
找到要卸载的应用名称,输入完整的应用名称然后卸载。
![][10]
如果不知道具体的应用名称或者开头字母,你可以 [列出 Ubuntu 中所有已安装的包][11] ,然后查找符合你记忆的应用名称。
比如,下图的命令会列出所有已安装的应用名称中包含 my 的应用,不仅仅是以 my 开头的应用。
```
apt list --installed | grep -i my
```
![][12]
这非常酷炫对不对?在 Ubuntu 中使用卸载命令时请注意应用名。
#### 补充:使用 apt purge 卸载应用(进阶用户)
当在 Ubuntu 中卸载应用时,应用程序会被卸载,但是会留下细小的、修改过的用户配置文件。这些文件是故意被留下的,因为当你再次安装同样的应用时,会使用这些遗留的配置文件。
如果你想完全卸载应用,你可以使用 `apt purge` 命令代替 `apt remove` 命令,或者在 `apt remove` 命令后再使用它。
```
sudo apt purge program_name
```
注意 `apt purge` 令不会删除保存在用户目录下的数据或者配置文件。
### 方法3 Ubuntu 中卸载 Snap 应用
前面的几种方式可用于使用 `apt` 命令、<ruby>软件中心<rt>Software Center</rt></ruby>或者直接使用 deb 文件安装的应用。
Ubuntu 也推出了一个名为 [Snap][13] 的包管理系统。在<ruby>软件中心<rt>Software Center</rt></ruby>中的大部分应用都是 Snap 包格式。
你可以使用 <ruby>软件中心<rt>Software Center</rt></ruby> 轻松地卸载这些应用,也可以使用命令行卸载。
列出所有已经安装的 Snap 包名字:
```
snap list
```
![][14]
选择你想要卸载的应用,然后卸载,这不会要求你确认是否删除。
```
sudo snap remove package_name
```
### 妙招:用一个神奇的命令清理系统
到此你已经学会怎么卸载应用,现在使用一个简单的命令清理卸载残留,比如不再用到的依赖或 Linux 内核头文件。
在终端输入如下命令:
```
sudo apt autoremove
```
这条命令很安全,而且会释放几百 MB 的磁盘空间。
### 总结
本文一共介绍了三种卸载应用的方法,包括通过图形界面卸载、命令行卸载,以便你了解所有方式。
希望此篇教程对 Ubuntu 初学者有所帮助,欢迎提出问题和建议。
--------------------------------------------------------------------------------
via: https://itsfoss.com/uninstall-programs-ubuntu/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[amagicowboy](https://github.com/amagicboy)
校对:[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://itsfoss.com/free-up-space-ubuntu-linux/
[2]: https://itsfoss.com/remove-install-software-ubuntu/
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/06/ubuntu_software_applications_menu.jpg?resize=800%2C390&ssl=1
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/installed-apps-ubuntu.png?resize=800%2C455&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/search-installed-apps-ubuntu.png?resize=800%2C455&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/remove-applications-ubuntu.png?resize=800%2C487&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/apt-remove-program-ubuntu.png?resize=768%2C424&ssl=1
[8]: https://itsfoss.com/unable-to-locate-package-error-ubuntu/
[9]: https://itsfoss.com/linux-command-tricks/
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/remove-package-ubuntu-linux.png?resize=768%2C424&ssl=1
[11]: https://itsfoss.com/list-installed-packages-ubuntu/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/search-list-installed-apps-ubuntu.png?resize=768%2C424&ssl=1
[13]: https://itsfoss.com/install-snap-linux/
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/list-snap-remove.png?resize=800%2C407&ssl=1

View File

@ -0,0 +1,277 @@
[#]: subject: (Use awk to calculate letter frequency)
[#]: via: (https://opensource.com/article/21/4/gawk-letter-game)
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
[#]: collector: (lujun9972)
[#]: translator: (lkxed)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14375-1.html)
使用 awk 统计字母频率
======
> 编写一个 awk 脚本来找到一组单词中出现次数最多(和最少)的单词。
![](https://img.linux.net.cn/data/attachment/album/202203/20/085052bajyoejnea8cpw5j.jpg)
近一段时间,我开始编写一个小游戏,在这个小游戏里,玩家使用一个个字母块来组成单词。编写这个游戏之前,我需要先知道常见英文单词中每个字母的使用频率,这样一来,我就可以找到一组更有用的字母块。字母频次统计在很多地方都有相关讨论,包括在 [维基百科][2] 上,但我还是想要自己来实现。
Linux 系统在 `/usr/share/dict/words` 文件中提供了一个单词列表,所以我已经有了一个现成的单词列表。然而,尽管这个 `words` 文件包含了很多我想要的单词,却也包含了一些我不想要的。我想要的单词首先不能是复合词(即不包含连接符和空格的单词),也不能是专有名词(即不包含大写字母单词)。为了得到这个结果,我可以运行 `grep` 命令来取出只由小写字母组成的行:
```
$ grep  '^[a-z]*$' /usr/share/dict/words
```
这个正则表达式的作用是让 `grep` 去匹配仅包含小写字母的行。表达式中的字符 `^``$` 分别代表了这一行的开始和结束。`[a-z]` 分组仅匹配从 “a” 到 “z” 的小写字母。
下面是一个输出示例:
```
$ grep  '^[a-z]*$' /usr/share/dict/words | head
a
aa
aaa
aah
aahed
aahing
aahs
aal
aalii
aaliis
```
没错这些都是合法的单词。比如“aahed” 是 “aah” 的过去式,表示在放松时的感叹,而 “aalii” 是一种浓密的热带灌木。
现在我只需要编写一个 `gawk` 脚本来统计出单词中各个字母出现的次数,然后打印出每个字母的相对频率。
### 字母计数
一种使用 `gawk` 来统计字母个数的方式是,遍历每行输入中的每一个字符,然后对 “a” 到 “z” 之间的每个字母进行计数。`substr` 函数会返回一个给定长度的子串,它可以只包含一个字符,也可以是更长的字符串。比如,下面的示例代码能够取到输入中的每一个字符 `c`
```
{
len = length($0); for (i = 1; i <= len; i++) {
c = substr($0, i, 1);
}
}
```
如果使用一个全局字符串变量 `LETTERS` 来存储字母表,我就可以借助 `index` 函数来找到某个字符在字母表中的位置。我将扩展 `gawk` 代码示例,让它在输入数据中只取范围在 “a” 到 “z” 的字母:
```
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
{
len = length($0); for (i = 1; i <= len; i++) {
c = substr($0, i, 1);
ltr = index(LETTERS, c);
}
}
```
需要注意的是,`index` 函数将返回字母在 `LETTERS` 字符串中首次出现的位置,第一个位置返回 1如果没有找到则返回 0。如果我有一个大小为 26 的数组,我就可以利用这个数组来统计每个字母出现的次数。我将在下面的示例代码中添加这个功能,每当一个字母出现在输入中,我就让它对应的数组元素值增加 1使用 `++`
```
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr &gt; 0) {
            ++count[ltr];
        }
    }
}
```
### 打印相对频率
`gawk` 脚本统计完所有的字母后,我希望它能输出每个字母的频率。毕竟,我对输入中各个字母的个数没有兴趣,我更关心它们的 _相对频率_
我将先统计字母 “a” 的个数,然后把它和剩余 “b” 到 “z” 字母的个数比较:
```
END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
}
```
在循环的最后,变量 `min` 会等于最少的出现次数,我可以把它为基准,为字母的个数设定一个参照值,然后计算打印出每个字母的相对频率。比如,如果出现次数最少的字母是 “q”那么 `min` 就会等于 “q” 的出现次数。
接下来,我会遍历每个字母,打印出它和它的相对频率。我通过把每个字母的个数都除以 `min` 的方式来计算出它的相对频率,这意味着出现次数最少的字母的相对频率是 1。如果另一个字母出现的次数恰好是最少次数的两倍那么这个字母的相对频率就是 2。我只关心整数所以 2.1 和 2.9 对我来说是一样的(都是 2
```
END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr <= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}
```
### 最后的完整程序
现在,我已经有了一个能够统计输入中各个字母的相对频率的 `gawk` 脚本:
```
#!/usr/bin/gawk -f
 
# 只统计 a-z 的字符,忽略 A-Z 和其他的字符
 
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr < 0) {
            ++count[ltr];
        }
    }
}
 
# 打印每个字符的相对频率
   
END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr <= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}
```
我将把这段程序保存到名为 `letter-freq.awk` 的文件中,这样一来,我就可以在命令行中更方便地使用它。
如果你愿意的话,你也可以使用 `chmod +x` 命令把这个文件设为可独立执行。第一行中的 `#!/usr/bin/gawk -f` 表示 Linux 会使用 `/usr/bin/gawk` 把这个文件当作一个脚本来运行。由于 `gawk` 命令行使用 `-f` 来指定它要运行的脚本文件名,你需要在末尾加上 `-f`。如此一来,当你在 shell 中执行 `letter-freq.awk`,它会被解释为 `/usr/bin/gawk -f letter-freq.awk`
接下来我将用几个简单的输入来测试这个脚本。比如,如果我给我的 `gawk` 脚本输入整个字母表,每个字母的相对频率都应该是 1
```
$ echo abcdefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1
```
还是使用上述例子,只不过这次我在输入中添加了一个字母 “e”此时的输出结果中“e” 的相对频率会是 2而其他字母的相对频率仍然会是 1
```
$ echo abcdeefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 2
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1
```
现在我可以跨出最大的一步了!我将使用 `grep` 命令和 `/usr/share/dict/words` 文件,统计所有仅由小写字母组成的单词中,各个字母的相对使用频率:
```
$ grep  '^[a-z]*$' /usr/share/dict/words | gawk -f letter-freq.awk
a 53
b 12
c 28
d 21
e 72
f 7
g 15
h 17
i 58
j 1
k 5
l 36
m 19
n 47
o 47
p 21
q 1
r 46
s 48
t 44
u 25
v 6
w 4
x 1
y 13
z 2
```
`/usr/share/dict/words` 文件的所有小写单词中,字母 “j”、“q” 和 “x” 出现的相对频率最低,字母 “z” 也使用得很少。不出意料,字母 “e” 是使用频率最高的。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/4/gawk-letter-game
作者:[Jim Hall][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/jim-hall
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-docdish-typewriterkeys-3.png?itok=NyBwMdK_ (Typewriter keys in multicolor)
[2]: https://en.wikipedia.org/wiki/Letter_frequency

View File

@ -0,0 +1,69 @@
[#]: subject: (5 commands to level-up your Git game)
[#]: via: (https://opensource.com/article/21/4/git-commands)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: (lkxed)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14364-1.html)
五个提升你的 Git 水平的命令
======
> 将这些命令加入到你的工作流中,使 Git 发挥更大的作用。
![](https://img.linux.net.cn/data/attachment/album/202203/17/110616vti9hhsiiq4misra.jpg)
如果你经常使用 Git你可能会知道它非常有名。它可能是最受欢迎的版本控制方案它被一些 [最大的软件项目][2] 用来 [跟踪文件变更][3]。Git 提供了 [健壮的界面][4] 来审阅代码、把实验性的变更合并到已经存在的文件中。得益于 [Git 钩子][5],它以灵活性而闻名。同时,也因为它的强大,它给人们留下了一个“复杂”的印象。
Git 有诸多特性,你不必全部使用,但是如果你正在深入研究 Git 的 <ruby>子命令<rt>subcommands</rt></ruby>,我这里倒是有几个,或许你会觉得有用。
### 1、找到变更
如果你已经熟悉 Git 的基本指令(`fetch`、`add`、`commit`、`push`、`log` 等等),但是希望学习更多,那么从 Git 的检索子命令开始是一个简单安全的选择。检索你的 Git 仓库(你的 _工作树_)并不会做出任何更改,它只是一个报告机制。你不会像使用 `git checkout` 一样承担数据完整性的风险,你只是在向 Git 请求仓库的当前状态和历史记录而已。
[git whatchanged][6] 命令(几乎本身就是一个助记符)可以查看哪些文件在某个<ruby>提交<rt>commit</rt></ruby>中有变更、分别做了什么变更。它是一个简单的、用户友好的命令,因为它把 `show`、`diff-tree` 和 `log` 这三个命令的最佳功能整合到了一个好记的命令中。
### 2、使用 git stash 管理变更
你越多地使用 Git你就会使用 Git 越多。这就是说,一旦你习惯了 Git 的强大功能,你就会更频繁地使用它。有时,你正在处理一大堆文件,忽然意识到了有更紧急的任务要做。这时,在 [git stash][7] 的帮助下,你就可以把所有正在进行的工作收集起来,然后安全地<ruby>暂存<rt>stash</rt></ruby>它们。当你的工作空间变得整洁有序,你就可以把注意力放到别的任务上,晚些时候再把暂存的文件重新加载到工作树里,继续之前的工作。
### 3、使用 git worktree 来得到链接的副本
`git stash` 不够用的时候Git 还提供了强大的 [git worktree][8] 命令。有了它,你可以新建一个 _链接的_ 仓库<ruby>副本<rt>clone</rt></ruby>,组成一个新分支,把 `HEAD` 设置到任意一个提交上,然后基于这个分支开始你的新工作。在这个链接的副本里,你可以进行和主副本完全不同的任务。这是一个避免意外的变更影响当前工作的好办法。当你完成了你的新工作,你可以把新分支推送到远程仓库;也可以把当前的变更归档,晚些时候再处理;还可以从别的工作树中获取它们的变更。无论选择哪一种,你的工作空间之间都会保持相互隔离,任一空间中的变更都不会影响其他空间中的变更,直到你准备好了要合并它们。
### 4、使用 git cherry-pick 来选择合并
这可能听起来很反直觉,但是,你的 Git 水平越高,你可能遇到的合并冲突就会越多。这是因为合并冲突不一定是错误的标志,而是活跃的标志。在学习 Git 中,适应合并时的冲突,并学会如何解决它们是非常重要的。通常的方式或许够用,但是有时候你会需要更加灵活地进行合并,这时候就该 [git cherry-pick][9] 出场了。遴选操作允许你选择部分合并提交,这样一来你就不需要因为一些细微的不协调而拒绝整个合并请求了。
### 5、使用 Git 来管理 $HOME
使用 Git 来管理你的主目录从来没有这么简单过,这都要归功于 Git 可以自由选择管理对象的能力,这是一个在多台计算机之间保持同步的现实可行的选项。但是,想要让它工作顺利,你必须非常明智且谨慎才行。如果你想要了解更多,点击阅读我写的关于 [使用 Git 来管理 $HOME][10] 的小技巧。
### 更好地使用 Git
Git 是一个强大的版本控制系统,你使用得越熟练,就可以越轻松地借助它来完成复杂的任务。今天就尝试一些新的 Git 命令吧,欢迎在评论区分享你最喜欢的 Git 命令。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/4/git-commands
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
[2]: https://opensource.com/article/19/10/how-gnome-uses-git
[3]: https://opensource.com/article/18/2/how-clone-modify-add-delete-git-files
[4]: https://opensource.com/article/18/5/git-branching
[5]: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
[6]: https://opensource.com/article/21/3/git-whatchanged
[7]: https://opensource.com/article/21/3/git-stash
[8]: https://opensource.com/article/21/3/git-worktree
[9]: https://opensource.com/article/21/3/reasons-use-cherry-picking
[10]: https://opensource.com/article/21/3/git-your-home

View File

@ -0,0 +1,74 @@
[#]: subject: (5 handy guides to open source for teachers)
[#]: via: (https://opensource.com/article/21/6/open-source-guides-teachers)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: (lkxed)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14386-1.html)
5 个为教师准备的方便的开源指南
======
![](https://img.linux.net.cn/data/attachment/album/202203/23/162904laqecdh4xraveac7.jpg)
> 我们收集了一些最受欢迎的简明指南,它们既能满足你充分利用暑假的愿望,又能满足你为下一个学期做规划的需要。
对一些老师来说,夏天到了,一个漫长的(希望也是放松的)假期也到了。所有我认识的老师都是自豪的终身学习者,尽管暑假过后,又有一个新学期会到来。为了帮助你充分利用暑假时间,与此同时也为即将到来的下一个学期做好准备,我们收集了一些最受欢迎的 _简明_ 指南。
### 如何让你的学校做好准备(在新冠疫情下)
通过 [在 Linux 上来完成所有相关工作][2]Robert Maynord 老师确保了他的学校为远程学习做好了准备,甚至在疫情前他就这么做了。虽然我们还不知道在今年剩下的时间里会发生什么,但是,如果说新冠疫情向世界展示了什么,那就是 [数字转型][3](指把数字技术融入到教育的各个领域)不仅是可能的,而且对教师和学生来说都是有益的。你可能无权在技术层面上改变课堂的运作方式,但你仍然可以做很多小的改变,为学生创造更灵活的学习体验。
### 为教师准备的终极开源指南
通过本文,你可以学习如何在课堂上 [融入开源原则][4]。开源不仅仅和科技相关,它同时也关于知识共享、团队协作以及为了一个共同目标而努力。你可以把你的教室变成一个共享的空间,让学生们互相学习,就像他们向你学习一样。阅读开源,把开源付诸实践,并鼓励学生们积极参与。
### 8 个为虚拟教室准备的 WordPress 插件
WordPress Web 平台是一个构建网站的强大工具。在教室里,它可以作为教授 Web 技术、创意写作和学术写作的 [一个很好的工具][5]。它也可以被用来帮助远程学习,或者是把日常的学校作业数字化。通过掌握 WordPress 的诸多 [附加功能],你可以从中获取到最大的教育收益。
### 教孩子们写 Python交互式游戏
开源工具可以帮助任何人以一种轻松有趣的方式开始学习 Python —— 那就是制作游戏。当然Python 涉及到很多方面的东西。别担心,我们有一个课程可以带你从安装 Python 开始,通过简单的文本代码和 “<ruby>海龟<rt>turtle</rt></ruby>” 绘图游戏开始你的第一步,一直到中级游戏开发。
1. 首先,安装 Python阅读我们的 [Python 入门文章][7],熟悉编程的概念。单单是这篇文章里的内容就可以作为两节或三节不同课程的基础哦。
2. 然后,如果你熟悉 [Jupyter][8] 库的话,可以学习 [使用 Python 和 Jupyter 来编写一个简单游戏][9]。
3. 接着,你也可以 [在这本 Python 电子书里学到游戏开发的知识][10],里面会教你如何使用 Git、Python 和 PyGame 库。当你学会了这些基础内容,你可以看看 [这本书里的 "游戏测试员" 的有趣创作集合][11]。
如果 Python 对你或你的学生来说太难了,那么看看 [Thine][12] 吧,它是一个简单的基于 HTML 的交互式的讲故事工具。
### 教孩子们玩树莓派(编程)
我们的指南中有一篇 [树莓派入门指南][13],其中探索了各种帮助孩子们学习编程的资源。树莓派的特点是它足够便宜,只要花 35 美元,你就可以买到一个全功能的 Linux 电脑。然后你就在上面做任何事,不管是基本的 Python 学习还是搭建实际的网络服务器因此它有着巨大的教育潜力。你完全可以为每一个学生都配一个树莓派或者你也可以让班里的学生共享一个树莓派Linux 是多用户操作系统,只要设置得当,所有的学生都可以同时使用这个树莓派,直到你说服他们的家长购买更多树莓派)。
### 一起学习
开放课堂的关键之一是要勇敢地和学生一起学习。作为一个老师,你可能习惯了掌握所有的答案,但是数字世界是不断改变和进化的。不要害怕 _和_ 你的学生们一起学习 Python、Linux、树莓派或者任何其他东西一起学习新的基础知识、小技巧和解决问题的新方式。开源是一种经过验证的成功方法所以不要只是教授开源而已还要让开源在你的课堂上得以运用。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/6/open-source-guides-teachers
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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/tips_map_guide_ebook_help_troubleshooting_lightbulb_520.png?itok=L0BQHgjr (Looking at a map)
[2]: https://opensource.com/article/21/5/linux-school-servers
[3]: https://enterprisersproject.com/what-is-digital-transformation
[4]: https://opensource.com/article/20/7/open-source-teachers
[5]: https://opensource.com/article/20/3/wordpress-education
[6]: https://opensource.com/article/20/5/wordpress-plugins-education
[7]: https://opensource.com/article/17/10/python-101
[8]: https://opensource.com/article/18/3/getting-started-jupyter-notebooks
[9]: https://opensource.com/article/20/5/python-games
[10]: https://opensource.com/article/20/10/learn-python-ebook
[11]: https://github.com/MakerBox-NZ?q=pygame&type=&language=&sort=
[12]: https://opensource.com/article/18/2/twine-gaming
[13]: https://opensource.com/article/19/3/teach-kids-program-raspberry-pi

View File

@ -0,0 +1,350 @@
[#]: subject: (Parsing config files with Java)
[#]: via: (https://opensource.com/article/21/7/parsing-config-files-java)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: (lkxed)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14381-1.html)
使用 Java 解析 XML 文件
======
> 在你使用 Java 编写软件时实现持久化配置。
![](https://img.linux.net.cn/data/attachment/album/202203/22/091553wf2gvj20fn4wfgpw.jpg)
当你编写一个应用时,你通常都会希望用户能够定制化他们和应用交互的方式,以及应用与系统进行交互的方式。这种方式通常被称为 “<ruby>偏好<rt>preference</rt></ruby>” 或者 “<ruby>设置<rt>setting</rt></ruby>”,它们被保存在一个 “偏好文件” 或者 “配置文件” 中,有时也直接简称为 “<ruby>配置<rt>config</rt></ruby>”。配置文件可以有很多种格式,包括 INI、JSON、YAML 和 XML。每一种编程语言解析这些格式的方式都不同。本文主要讨论当你在使用 [Java 编程语言][2] 来编写软件时,实现持久化配置的方式。
### 选择一个格式
编写配置文件是一件相当复杂的事情。我曾经试过把配置项使用逗号分隔保存在一个文本文件里,也试过把配置项保存在非常详细的 YAML 和 XML 中。对于配置文件来说,最重要是要有一致性和规律性,它们使你可以简单快速地编写代码,从配置文件中解析出数据;同时,当用户决定要做出修改时,很方便地保存和更新配置。
目前有 [几种流行的配置文件格式][3]。对于大多数常见的配置文件格式Java 都有对应的<ruby><rt>library</rt></ruby>。在本文中,我将使用 XML 格式。对于一些项目,你可能会选择使用 XML因为它的一个突出特点是能够为包含的数据提供大量相关的元数据而在另外一些项目中你可能会因为 XML 的冗长而不选择它。在 Java 中使用 XML 是非常容易的,因为它默认包含了许多健壮的 XML 库。
### XML 基础
讨论 XML 可是一个大话题。我有一本关于 XML 的书,它有超过 700 页的内容。幸运的是,使用 XML 并不需要非常了解它的诸多特性。就像 HTML 一样XML 是一个带有开始和结束标记的分层标记语言,每一个标记(标签)内可以包含零个或更多数据。下面是一个 XML 的简单示例片段:
```
<xml>
  <node>
    <element>Penguin</element>
  </node>
</xml>
```
在这个 <ruby>自我描述的<rt>self-descriptive</rt></ruby> 例子中XML 解析器使用了以下几个概念:
* <ruby>文档<rt>Document</rt></ruby>`<xml>` 标签标志着一个 _文档_ 的开始,`</xml>` 标签标志着这个文档的结束。
* <ruby>节点<rt>Node</rt></ruby>`<node>` 标签代表了一个 _节点_
* <ruby>元素<rt>Element</rt></ruby>`<element>Penguin</element>` 中,从开头的 `<` 到最后的 `>` 表示了一个 _元素_
* <ruby>内容<rt>Content</rt></ruby>`<element>` 元素里,字符串 `Penguin` 就是 _内容_
不管你信不信,只要了解了以上几个概念,你就可以开始编写、解析 XML 文件了。
### 创建一个示例配置文件
要学习如何解析 XML 文件,只需要一个极简的示例文件就够了。假设现在有一个配置文件,里面保存的是关于一个图形界面窗口的属性:
```
<xml>
  <window>
    <theme>Dark</theme>
    <fullscreen>0</fullscreen>
    <icons>Tango</icons>
</window>
</xml>
```
创建一个名为 `~/.config/DemoXMLParser` 的目录:
```
$ mkdir ~/.config/DemoXMLParser
```
在 Linux 中,`~/.config` 目录是存放配置文件的默认位置,这是在 [自由桌面工作组][4] 的规范中定义的。如果你正在使用一个不遵守 <ruby>自由桌面工作组<rt>Freedesktop</rt><ruby> 标准的操作系统,你也仍然可以使用这个目录,只不过你需要自己创建这些目录了。
复制 XML 的示例配置文件,粘贴并保存为 `~/.config/DemoXMLParser/myconfig.xml` 文件。
### 使用 Java 解析 XML
如果你是 Java 的初学者,你可以先阅读我写的 [面向 Java 入门开发者的 7 个小技巧][5]。一旦你对 Java 比较熟悉了打开你最喜爱的集成开发工具IDE创建一个新工程。我会把我的新工程命名为 `myConfigParser`
刚开始先不要太关注依赖导入和异常捕获这些,你可以先尝试用 `javax``java.io` 包里的标准 Java 扩展来实例化一个解析器。如果你使用了 IDE它会提示你导入合适的依赖。如果没有你也可以在文章稍后的部分找到完整的代码里面就有完整的依赖列表。
```
Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
File configFile = new File(configPath.toString(), "myconfig.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
Document doc = null;
doc = builder.parse(configFile);
doc.getDocumentElement().normalize();
```
这段示例代码使用了 `java.nio.Paths` 类来找到用户的主目录,然后在拼接上默认配置文件的路径。接着,它用 `java.io.File` 类来把配置文件定义为一个 `File` 对象。
紧接着,它使用了 `javax.xml.parsers.DocumentBuilder``javax.xml.parsers.DocumentBuilderFactory` 这两个类来创建一个内部的文档构造器,这样 Java 程序就可以导入并解析 XML 数据了。
最后Java 创建一个叫 `doc` 的文档对象,并且把 `configFile` 文件加载到这个对象里。通过使用 `org.w3c.dom` 包,它读取并规范化了 XML 数据。
基本上就是这样啦。理论上来讲,你已经完成了数据解析的工作。可是,如果你不能够访问数据的话,数据解析也没有多少用处嘛。所以,就让我们再来写一些查询,从你的配置中读取重要的属性值吧。
### 使用 Java 访问 XML 的值
从你已经读取的 XML 文档中获取数据,其实就是要先找到一个特定的节点,然后遍历它包含的所有元素。通常我们会使用多个循环语句来遍历节点中的元素,但是为了保持代码可读性,我会尽可能少地使用循环语句:
```
NodeList nodes = doc.getElementsByTagName("window");
for (int i = 0; i < nodes.getLength(); i++) {
Node mynode = nodes.item(i);
System.out.println("Property = " + mynode.getNodeName());
if (mynode.getNodeType() == Node.ELEMENT_NODE) {
Element myelement = (Element) mynode;
System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
}
}
```
这段示例代码使用了 `org.w3c.dom.NodeList` 类,创建了一个名为 `nodes``NodeList` 对象。这个对象包含了所有名字匹配字符串 `window` 的子节点,实际上这样的节点只有一个,因为本文的示例配置文件中只配置了一个。
紧接着,它使用了一个 `for` 循环来遍历 `nodes` 列表。具体过程是:根据节点出现的顺序逐个取出,然后交给一个 `if-then` 子句处理。这个 `if-then` 子句创建了一个名为 `myelement``Element` 对象,其中包含了当前节点下的所有元素。你可以使用例如 `getChildNodes``getElementById` 方法来查询这些元素,项目中还 [记录了][9] 其他查询方法。
在这个示例中,每个元素就是配置的键。而配置的值储存在元素的内容中,你可以使用 `.getTextContent` 方法来提取出配置的值。
在你的 IDE 中运行代码(或者运行编译后的二进制文件):
```
$ java ./DemoXMLParser.java
Property = window
Theme = Dark
Fullscreen = 0
Icon set = Tango
```
下面是完整的代码示例:
```
package myConfigParser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ConfigParser {
public static void main(String[] args) {
Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
File configFile = new File(configPath.toString(), "myconfig.xml");
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
try {
doc = builder.parse(configFile);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
doc.getDocumentElement().normalize();
NodeList nodes = doc.getElementsByTagName("window");
for (int i = 0; i < nodes.getLength(); i++) {
Node mynode = nodes.item(i);
System.out.println("Property = " + mynode.getNodeName());
if (mynode.getNodeType() == Node.ELEMENT_NODE) {
Element myelement = (Element) mynode;
System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
} // close if
} // close for
} // close method
} //close class
```
### 使用 Java 更新 XML
用户时不时地会改变某个偏好项,这时候 `org.w3c.dom` 库就可以帮助你更新某个 XML 元素的内容。你只需要选择这个 XML 元素,就像你读取它时那样。不过,此时你不再使用 `.getTextContent` 方法,而是使用 `.setTextContent` 方法。
```
updatePref = myelement.getElementsByTagName("fullscreen").item(0);
updatePref.setTextContent("1");
System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
```
这么做会改变应用程序内存中的 XML 文档,但是还没有把数据写回到磁盘上。配合使用 `javax``w3c` 库,你就可以把读取到的 XML 内容写回到配置文件中。
```
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer xtransform;
xtransform = transformerFactory.newTransformer();
DOMSource mydom = new DOMSource(doc);
StreamResult streamResult = new StreamResult(configFile);
xtransform.transform(mydom, streamResult);
```
这么做会没有警告地写入转换后的数据,并覆盖掉之前的配置。
下面是完整的代码,包括更新 XML 的操作:
```
package myConfigParser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ConfigParser {
public static void main(String[] args) {
Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
File configFile = new File(configPath.toString(), "myconfig.xml");
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Document doc = null;
try {
doc = builder.parse(configFile);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
doc.getDocumentElement().normalize();
Node updatePref = null;
// NodeList nodes = doc.getChildNodes();
NodeList nodes = doc.getElementsByTagName("window");
for (int i = 0; i < nodes.getLength(); i++) {
Node mynode = nodes.item(i);
System.out.println("Property = " + mynode.getNodeName());
if (mynode.getNodeType() == Node.ELEMENT_NODE) {
Element myelement = (Element) mynode;
System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
updatePref = myelement.getElementsByTagName("fullscreen").item(0);
updatePref.setTextContent("2");
System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
} // close if
}// close for
// write DOM back to the file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer xtransform;
DOMSource mydom = new DOMSource(doc);
StreamResult streamResult = new StreamResult(configFile);
try {
xtransform = transformerFactory.newTransformer();
xtransform.transform(mydom, streamResult);
} catch (TransformerException e) {
e.printStackTrace();
}
} // close method
} //close class
```
### 如何保证配置不出问题
编写配置文件看上去是一个还挺简单的任务。一开始,你可能会用一个简单的文本格式,因为你的应用程序只要寥寥几个配置项而已。但是,随着你引入了更多的配置项,读取或者写入错误的数据可能会给你的应用程序带来意料之外的错误。一种帮助你保持配置过程安全、不出错的方法,就是使用类似 XML 的规范格式,然后依靠你用的编程语言的内置功能来处理这些复杂的事情。
这也正是我喜欢使用 Java 和 XML 的原因。每当我试图读取错误的配置值时Java 就会提醒我。通常,这是由于我在代码中试图获取的节点,并不存在于我期望的 XML 路径中。XML 这种高度结构化的格式帮助了代码保持可靠性,这对用户和开发者来说都是有好处的。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/parsing-config-files-java
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
[2]: https://opensource.com/resources/java
[3]: https://opensource.com/article/21/6/what-config-files
[4]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
[5]: https://opensource.com/article/19/10/java-basics
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+file
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+document
[9]: https://www.w3.org/2003/01/dom2-javadoc/org/w3c/dom/Document.html
[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+ioexception
[12]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element

View File

@ -0,0 +1,226 @@
[#]: subject: (How to Dual Boot Fedora and Windows)
[#]: via: (https://itsfoss.com/dual-boot-fedora-windows/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14401-1.html)
如何双启动 Fedora 和 Windows
======
![][2]
> 这篇详细的教程一步一步地向你展示 **如何双启动 Fedora Linux 和 Windows 10**,附有适当的截图。
双启动 Linux 和 Windows 是一种完全享受这两款操作系统的流行方式。你可以在同一个硬件系统上安装 Linux 和 Windows 两款系统,并在你启动你的硬件系统时选择使用哪款操作系统。
![On the grub screen, you can select the operating system][1]
如果你有一个已经安装 Windows 的系统,你将在这篇教程中学习如何在 Windows 的旁侧安装 Fedora 。
### 在 Windows 的旁侧安装 Fedora
这篇教程是在一款已经安装 Windows采用 GPT 分区和 UEFI 启动的硬件系统的基础上执行的。它应该也适用于其它的带有 MBR 分区和传统 BIOS 的硬件系统,但是我不能确认这一点。
注意:如果你的 Windows 系统使用 BitLocker 加密,在你安装 Fedora 前禁用它会是一个好主意。
#### 必要条件
这里是你需要遵循这篇教程的东西:
* 一个已预装 Windows 的系统
* 良好的互联网连接速度
* 一个至少 4 GB 大小的 USB 接口设备U 盘)
* 可选: 用于备份你的 Windows 现有数据的外部 USB 磁盘。
* 可选: Windows 恢复或可启动磁盘(如果你偶遇一些严重的启动问题,你可以修复它)。
让我们看看步骤。
#### 步骤 1: 制作 Windows 系统的数据备份 [可选]
备份总会是一个好主意。因为你将要处理磁盘分区。在一些罕见的不幸情况下,假设你出错并删除了错误的分区,你将丢失你的数据。
最简单的方法是将文档、视频、音乐、图片和其它的文件夹中的数据复制到一块外部 USB 磁盘中。你可以使用一个外部的机械硬盘(传输速度较慢,但是价格较便宜)或固态硬盘(传输速度较快,但是价格较昂贵),并将重要的文件和文件夹复制到其中。
#### 步骤 2: 为 Fedora 的安装准备一些可用的空间
你需要创建一个分区,你将在其中安装 Fedora 。如果你只有一个 C 驱动器,缩小它的分区。如果你有 D、E 或 F 等多个驱动器,确保你可以移动这些驱动器中的数据到一些其它的分区中,删除或缩小其中的一个驱动器。超过 40 GB 的驱动器分区都能有足够的空间来安装安装 Fedora 。
在 Windows 的菜单中,搜索 “磁盘分区” 并转到 “创建并格式化磁盘分区”。
![][10]
在磁盘管理工具中,右键单件你想要分区的驱动器,并选择 “缩小卷”。
如果你只有一个像这样的分区,你需要为 Linux 腾出一些可用的空间。如果你有一些空间相当大的分区,请使用除 C 驱动器分区外的分区,因为它会擦除数据。
![][11]
#### 步骤 3: 在 Windows 中制作一个 Fedora 的临场 USB
现在,这个步骤可以通过不同的方法来完成。你可以下载 ISO 并使用 [Etcher][12] 或 Rufus 或一些其它的工具来将 ISO 镜像写入 USB 磁盘。
不过Fedora 提供了一个用于下载 ISO 镜像和制作 <ruby>临场 USB<rt>Live USB</rt></ruby> 的专用工具。我将在这篇教程中使用它。Fedora 团队在创建这个工具时付出了很多艰难的努力,因此为什么不使用它呢。
但是,首先, **插入 USB 接口设备**。现在,转到 Fedora 的下载页面:
- [下载 Fedora][13]
你将看到针对 Windows 版本的下载 “Fedora Media Writer” 工具的选项。
![][14]
它将下载一个 exe 文件。在下载完成后,转到你所下载到的文件夹,并双击 `FedoraMediaWriter.exe` 文件来安装 “Fedora Media Writer” 工具。只需要重复点击 “<ruby>下一步<rt>next</rt></ruby>
![][15]
在安装完成后,运行 “Fedora Media Writer” 工具。但是在此之前,**确保你已经插入 USB 设备**。
它将给予你安装各种 Fedora 版本的选项。针对桌面机,选择<ruby>工作站<rt>Workstation</rt></ruby>版本。
![][16]
在接下来的屏幕中,你将会得到一个创建临场 USB 的选项。当你点击这个按钮时,它将开始下载 ISO 文件。它也将识别出你所插入的 USB 接口设备。
你需要良好的互联网访问速度来在一段时间内顺畅地下载 2GB 大小的 ISO 文件。
![][17]
在下载 ISO 后,它会自动地对其进行检验,并给予你将 ISO 镜像写入到 USB 磁盘的选项,例如,创建临场 USB 。点击 “<ruby>写入到磁盘<rt>Write to Disk</rt></ruby>” 按钮。
![][18]
它将花费几分钟来完成安装过程。它显示 “<ruby>完成<rt>Finished</rt></ruby>” 信息后,你可以关闭 “Fedora Media Writer” 工具了。
![][19]
很好!现在你已经准备好了 Fedora 临场 USB 。现在是时候使用它来安装带有图形用户界面的 Fedora 了。
#### 步骤 4: 从 临场 USB 启动并安装 Fedora
一些系统不允许你在使用安全启动的情形下从临场 USB 启动。如果你是这种情况的话,请 [禁用安全启动][20]。
在处于显示硬件系统制造商徽标的屏幕期间,按下 `F2``F10``F12` 按键。如果你不确定是哪个按键,你可以逐个尝试。但是,你要 **快速地** 按下按键 ,否则它将会启动到操作系统之中。
不同品牌计算机的按键是不同的。一些计算机甚至可能使用 `Esc``Del` 按键来完成此目的。
![Quickly press F2, F10 or F12 keys at the screen showing your system manufacturers logo][21]
在一些罕见的情况下,你可能需要 [在 Windows 中访问 UEFI 启动设置][22]。
在 BIOS 设置中,通常,你应该会看到像这样的屏幕。在这里,你可以使用箭头按键来向下移动到 USB 选项,并按下回车键来从 USB 启动。请注意,在不同的系统中,这一屏幕可能会看起来有所不同。
![][23]
如果一切顺利,你应该会看到像下面的一个屏幕。选择第一个选项 “<ruby>启动 Fedora 工作站<rt>Start Fedora Workstation</rt></ruby>”:
![][24]
在数秒后,你应该会启动到 Fedora 临场会话期间,并会看到尝试或安装它的选项。选择 “<ruby>安装到硬盘<rt>Install to Hard Drive</rt></ruby>” 。
![][25]
它会要求选择安装过程的语言选项。
![][26]
接下来的屏幕是很重要的。如果你已经在 “步骤 2” 中创建了可用的空间,你应该能够点击 “<ruby>开始安装<rt>Begin Installation</rt></ruby>” 。如果你在“<ruby>系统<rt>SYSTEM</rt></ruby>”下的磁盘图标上看到一个感叹号,单击它,并查看你能够在这里使用哪种磁盘配置。
如果你有多个磁盘,你可以为 Fedora 选择使用哪个磁盘。
![][27]
选择磁盘,并点击“<ruby>完成<rt>Done</rt></ruby>” 。现在,你应该会看到一条警告信息。在我的实例中,我没有在 “步骤 2” 中创建可用的空间,因此它会抱怨这里没有足够的可用的空间来安装 Fedora 。
![][28]
我点击 “<ruby>回收空间<rt>Reclaim space</rt></ruby>” ,并缩小在这里的 Windows 分区。
![][29]
在这以后,将出现 “<ruby>开始安装<rt>Begin Installation</rt></ruby>” 选项,开启安装过程。
![][30]
现在,它只是一个需要耐心等待的游戏了。将花费数分钟来提取文件并安装它们。
![][31]
当过程完成后,你将看到 “<ruby>结束安装<rt>Finish Installation</rt></ruby>” 按钮,点击它。
![][32]
你将回到 Fedora 临场会话期间。单击右上角的下拉菜单并选择 “<ruby>重新启动<rt>Restart</rt></ruby>” 。
![][33]
现在,当系统启动时,你应该会看到带有启动到 Fedora 和 Windows 选项的 [Grub 启动器][34]。
![][1]
#### 步骤 5: 完成 Fedora 安装
至此你几乎完成了安装。你注意到 Fedora 没有要求你输入用户名和密码了吗?很多发行版(像 Ubuntu 在安装期间会要求你创建一个管理用户。作为另一种方式Fedora 会在你第一次登录到所安装的系统时给予你这个选项。
当你第一次登录时,它会运行一次设置,并创建用户名和密码来作为这次初始化设置的一部分。
![][35]
![][36]
![][37]
在你完成后,你已经用上 Fedora Linux 了。
![][38]
就这样,你可以在同一个硬件系统上以双启动的模式来享受 Fedora Linux 和 Windows 。
如果你在学习这篇教程时有一些问题或者你正在面对一些重大难题,请在评论系统中告诉我。
--------------------------------------------------------------------------------
via: https://itsfoss.com/dual-boot-fedora-windows/
作者:[Abhishek Prakash][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/abhishek/
[b]: https://github.com/lujun9972
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/dual-boot-grub-screen-fedora-windows.jpg?resize=800%2C350&ssl=1
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-windows-dual-boot.jpg?resize=800%2C450&ssl=1
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/03/disc-management-windows.png?resize=800%2C561&ssl=1
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/04/making-free-space-for-dual-boot.jpg?resize=1226%2C728&ssl=1
[12]: https://itsfoss.com/install-etcher-linux/
[13]: https://getfedora.org/en/workstation/download/
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/download-fedora-media-writer-tool.png?resize=800%2C373&ssl=1
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-Fedora-Media-Writer-tool-Windows.png?resize=745%2C581&ssl=1
[16]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-media-writer-1.png?resize=800%2C425&ssl=1
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-media-writer-2.jpg?resize=800%2C422&ssl=1
[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/writing-fedora-iso-to-usb-with-Fedora-Media-Writer-Tool.png?resize=800%2C285&ssl=1
[19]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedoa-live-usb-with-fedora-media-writer.png?resize=800%2C300&ssl=1
[20]: https://itsfoss.com/disable-secure-boot-windows/
[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/04/acer-predator-boot.jpg?resize=800%2C600&ssl=1
[22]: https://itsfoss.com/access-uefi-settings-windows-10/
[23]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/06/select-boot-from-live-usb.jpg?resize=800%2C330&ssl=1
[24]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-live-screen.jpg?resize=800%2C350&ssl=1
[25]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/Fedora-install-screen.jpg?resize=800%2C450&ssl=1
[26]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-1.png?resize=800%2C450&ssl=1
[27]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-2.png?resize=800%2C450&ssl=1
[28]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-3.png?resize=800%2C450&ssl=1
[29]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-4.png?resize=800%2C450&ssl=1
[30]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-5.png?resize=800%2C450&ssl=1
[31]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-6.png?resize=800%2C450&ssl=1
[32]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-7.png?resize=800%2C450&ssl=1
[33]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/restart-gnome-fedora.jpg?resize=799%2C439&ssl=1
[34]: https://itsfoss.com/what-is-grub/
[35]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-1.png?resize=800%2C575&ssl=1
[36]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-2.png?resize=800%2C593&ssl=1
[37]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-3.png?resize=800%2C591&ssl=1
[38]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-completed.jpg?resize=800%2C500&ssl=1

View File

@ -0,0 +1,194 @@
[#]: subject: "Solve the repository impedance mismatch in CI/CD"
[#]: via: "https://opensource.com/article/21/8/impedance-mismatch-cicd"
[#]: author: "Evan \"Hippy\" Slatis https://opensource.com/users/hippyod"
[#]: collector: "lujun9972"
[#]: translator: "lxbwolf"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14396-1.html"
解决 CI/CD 中的仓库阻抗失配
======
> 对齐部署镜像和描述符是很困难的,但是某些策略可以使整个过程更高效。
![](https://img.linux.net.cn/data/attachment/album/202203/26/111748mxu3ovasrvb0iy02.jpg)
在软件架构中,当两个组件之间有某些概念性或技术上的差异时会出现 <ruby>阻抗失配<rt>impedance mismatch</rt></ruby>。这个术语其实是从电子工程中借用的,表示电路中输入和输出的电子阻抗必须要匹配。
在软件开发中存储在镜像仓库中的镜像与存储在源码控制管理系统LCTT 译注SCMSource Code Management中它的<ruby>部署描述符<rt>deployment descriptor</rt></ruby>之间存在阻抗失配。你如何确定存储在 SCM 中的部署描述符表示的是正确的镜像两个仓库追踪数据的方式并不一致因此将一个镜像在镜像仓库中独立存储的不可修改的二进制和它的部署描述符Git 中以文本文件形式存储的一系列修改记录)相匹配并不那么直观。
**注意**:本文假定读者已经熟悉以下概念:
* <ruby>源码控制管理<rt>Source Control Management</rt></ruby>SCM系统和分支
* Docker 或符合 OCI 标准的镜像和容器
* <ruby>容器编排系统<rt>Container Orchestration Platforms</rt></ruby>COP如 Kubernetes
* <ruby>持续集成/持续交付<rt>Continuous Integration/Continuous Delivery</rt></ruby>CI/CD
* <ruby>软件开发生命周期<rt>Software development lifecycle</rt></ruby>SDLC环境
### 阻抗失配SCM 与镜像仓库
为了更好地理解阻抗失配在什么场景下会成为问题请考虑任意项目中的软件开发生命周期环境SDLC如开发、测试或发布环境。
测试环境不会有阻抗失配。现在使用 CI/CD 的最佳实践中开发分支的最新提交都会对应开发环境中的最新部署。因此,一个典型的、成功的 CI/CD 开发流程如下:
1. 向 SCM 的开发分支提交新的修改
2. 新提交触发一次镜像构建
3. 新生成的镜像被推送到镜像仓库,标记为开发中
4. 镜像被部署到容器编排系统COP中的开发环境该镜像的部署描述符也更新为从 SCM 拉取的最新描述符。
换句话说,开发环境中最新的镜像永远与最新的部署描述符匹配。回滚到前一个构建的版本也不是问题,因为 SCM 也会跟着回滚。
最终,随着开发流程继续推进,需要进行更多正式的测试,因此某个镜像 —— 镜像对应着 SCM 中的某次提交 —— 被推到测试环境。如果是一次成功的构建,那么不会有大问题,因为从开发环境推过来的镜像应该会与开发分支的最新提交相对应。
1. 开发环境的最新部署被允许入库,触发入库过程
2. 最新部署的镜像被标记为测试中
3. 镜像在测试环境中被拉取和部署,(该镜像)对应从 SCM 拉取的最新部署描述符
到目前为止,一切都没有问题,对吗?如果出现下面的场景,会有什么问题?
**场景 A**:镜像被推到下游环境,如<ruby>用户验收测试<rt>user acceptance testing </rt></ruby>UAT或者是生产环境。
**场景 B**:测试环境中发现了一个破坏性的 bug镜像需要回滚到某个确定正常的版本。
在任一场景中,开发过程并没有停止,即开发分支上游有了一次或多次新的提交,而这意味着最新的部署描述符已经发生了变化,最新的镜像与之前部署在测试环境中的镜像不一致。对部署描述符的修改可能会也可能不会对之前版本的镜像起作用,但是它们一定是不可信任的。如果它们有了变化,那么它们就一定与目前为止你测试过的想要部署的镜像的部署描述符不一致。
问题的关键是:**如果部署的镜像不是镜像库中的最新版本,你怎么确定与部署的镜像相对应的是 SCM 中的哪个部署描述符?** 一言以蔽之,无法确定。两个库直接有阻抗失配。如果要详细阐述下,那么是有方法可以解决的,但是你需要做很多工作,这部分内容就是文章接下来的主题了。请注意,下面的方案并不是解决问题的唯一办法,但是已经投入到生产环境并已经对很多项目起了作用,而且已经被构建并部署到生产环境中运行了超过一年。
### 二进制与部署描述符
源码通常被构建成一个 Docker 镜像或符合 OCI 标准的镜像该镜像通常被部署到一个容器编排平台COP如 Kubernetes。部署到 COP 需要部署描述符来定义镜像被如何部署以及作为容器运行,如 [Kubernetes 部署][2] 或 [CronJobs][3]。这是因为在镜像和它的部署描述符之间有本质差异,在这里可以看到阻抗失配。在这次讨论中,我们认为镜像是存储在镜像仓库中不可修改的二进制。对源码的任何修改都不会修改镜像,而是用另一个新的镜像去替换它。
相比之下,部署描述符是文本文件,因而可以被认为是源码且可修改。如果遵循最佳实践,那么部署描述符是被存储在 SCM所有修改都会提交而这很容易回溯。
### 解决阻抗失配
建议的解决方案的第一部分,就是提供一个能匹配镜像仓库中的镜像与对保存部署描述符的 SCM 做的代码提交的方法。最直接的解决方案是用源提交的哈希值标记镜像。这个方法可以区分不同版本的镜像、容易分辨,并且提供足够的信息来查找正确的部署描述符,以便镜像更好地部署到 COP。
再回顾下上面的场景:
**场景 A** _镜像被推到下游环境_ 当镜像被从测试环境推到 UAT 环境时,我们可以从镜像的标签中知道应该从 SCM 的哪一次源码提交拉取部署描述符。
**场景 B** _当一个镜像需要在某一环节中回滚_:无论我们选择回滚到那个镜像版本,我们都可以知道从 SCM 的哪一次源码提交拉取正确的部署描述符。
在每一种情景中,无论在某个镜像被部署到测试环境后开发分支有多少次提交和构建,对于每一次升级的镜像,我们都可以找到它当初部署时对应的部署描述符。
然而,这并不是阻抗失配的完整解决方案。再考虑两个场景:
**场景 C** 在负载测试环境中,会尝试对不同的部署描述符进行多次部署,以此来验证某一次构建的表现。
**场景 D** 一个镜像被推送到下游环境,在该环境中部署描述符有一个错误。
在上面的所有场景中,我们都需要修改部署描述符,但是目前为止我们只有一个源码提交哈希。请记住,最佳实践要求我们所有对源码的修改都要先提交到 SCM。某次提交的哈希本身是无法修改的因此我们需要一个比仅仅追踪原来的源码提交哈希更好地解决方案。
解决方案是基于原来的源码提交哈希新建一个分支。我们把这个分支称为**部署分支**。每当一个镜像被推到下游测试或发布环境时,你应该**基于前一个 SDLC 环境的部署分支的最新提交**创建一个新的部署分支。
这样同一个镜像可以重复多次部署到不同的 SDLC 环境,并在后面每个环境中可以感知前面发现的改动或对镜像做的修改。
**注意:** 在某个环境中做的修改是如何影响下一个环境的,是用可以共享数据的工具(如 Helm Charts还是手动剪切、粘贴到其他目录都不在本文讨论的范围内。
因此,当一个镜像被从一个 SDLC 环境中推到下一环境时:
1. 创建一个部署分支
1. 如果镜像是从开发环境中推过来的,那么部署分支就基于构建这个镜像的源码提交哈希创建
2. 否则_部署分支基于当前部署分支的最新提交创建_
2. 镜像被部署到下一个 SDLC 环境,使用的部署描述符是该环境中新创建的部署分支的部署描述符
![deployment branching tree][4]
*图 1部署分支树*
1. 部署分支
2. 下游环境的第一个部署分支,只有一次提交
3. 下游环境的第二个部署分支,只有一次提交
有了部署分支这个解决方案,再回顾下上面的场景 C 和场景 D
**场景 C** 修改已经部署到下游 SDLC 环境中的镜像的部署描述符
**场景 D** 修复某个 SDLC 环境中部署描述符的错误
两个场景中,工作流如下:
1. 把对部署描述符做的修改提交到 SLDC 环境和镜像对应的部署分支
2. 通过部署分支最新提交对应的部署描述符把镜像重新部署到 SLDC 环境
这样,部署分支彻底解决了(存储着代表一次独一无二的构建的单一的、不可修改的镜像的)镜像仓库与(存储着对应一个或多个 SDLC 环境的可修改的部署描述符的SCM 仓库之间的阻抗失配。
### 实践中的思考
这看起来像是行得通的解决方案,但同时它也为开发者和运维人员带来了新的实践中的问题,比如:
A. 为了更好地管理部署分支,部署描述符作为资源应该保存在哪里,是否要与构建镜像的源码保存在同一个 SCM 仓库?
到目前为止,我们都在避免谈论应该把部署描述符放在哪个仓库里。在还没有太多细节需要处理时,我们推荐把所有 SDLC 环境的部署描述符与镜像源码放在同一个 SCM 仓库。当部署分支创建后,镜像的源码可以作为方便找到部署的容器中运行的镜像的引用来使用。
上面提到过,可以通过镜像的标签来关联镜像与原始的源码提交。在一个单独的仓库中查找某次提交的源码的引用,会给开发者带来更大的困难(即便借助工具),这就是没有必要把所有资源都分开存储的原因。
B. 应该在部署分支上修改构建镜像的源码吗?
简答:**不应该**。
详细阐述:不应该,因为永远不要在部署分支上构建镜像,它们是在开发分支上构建的。修改部署分支上定义一个镜像的源码会破坏被部署的镜像的构建记录,而且这些修改并不会对镜像的功能生效。在对比两个部署分支的版本时这也会成为问题。这可能会导致两个版本的功能差异有错误的测试结果(这是使用部署分支的一个很小的额外好处)。
C. 为什么使用镜像 <ruby>标签<rt>tag</rt></ruby><ruby>标记<rt>label</rt></ruby> 不可以吗?
通过 <ruby>标签<rt>tag</rt></ruby> 可以在仓库中很容易地查找镜像,可读性也很好。在一组镜像中读取和查找 <ruby>标记<rt>label</rt></ruby> 的值需要拉取所有镜像的<ruby>清单文件<rt>manifest</rt></ruby>,而这会增加复杂度、降低性能。而且,考虑到历史记录的追踪和不同版本的查找,对不同版本的镜像添加 <ruby>标签<rt>tag</rt></ruby> 也很有必要,因此使用源码提交哈希是保证唯一性,以及保存能即时生效的有用信息的最简单的解决方案。
D. 创建部署分支的最佳实践是怎样的?
DevOps 最重要的三个原则:自动化、自动化、自动化。
依赖资源来持续地强迫遵循最佳实践,充其量只是碰运气,因此在实现镜像的升级、回滚等 CI/CD 流水线时,把自动化部署分支写到脚本里。
E. 对部署分支的命名规范有建议吗?
&lt;**部署分支标识**&gt;-&lt;**环境**&gt;-&lt;**源码提交哈希**&gt;
* **部署分支标识** 所有部署分支范围内唯一的字符串;如 “deployment” 或 “deploy”
* **环境** 部署分支适用的 SDLC 环境;如 “qa”测试环境、 “stg”预生产环境、 或 “prod”生产环境
* **源码提交哈希** 源码提交哈希中包含原来构建被部署的镜像的源码,开发者可以通过它很容易地查找到创建镜像的原始提交,同时也能保证分支名唯一。
例如, `deployment-qa-asdf78s` 表示推到 QA 环境的部署分支, `deployment-stg-asdf78s` 表示推到 STG 环境的部署分支。
F. 你怎么识别环境中运行的哪个镜像版本?
我们的建议是把最新的部署分支提交哈希和源码提交哈希添加到 [标记][5] 中。开发者和运维人员可以通过这两个独一无二的标识符查找到部署的所有东西及其来源。在诸如执行回滚或前滚操作时,使用那些不同版本的部署的选择器也能清理资源碎片。
G. 什么时候应该把部署分支的修改合并回开发分支?
这完全取决于开发团队。
如果你修改的目的是为了做负载测试,只是想验证什么情况会让程序崩溃,那么这些修改不应该被合并回开发分支。另一方面,如果你发现和修复了一个错误,或者对下游环境的部署做了调整,那么就应该把部署分支的修改合并回开发分支。
H. 有现成的部署分支示例让我们试水吗?
[el-CICD][6] 已经在生产上使用这个策略持续一年半应用到超过一百个项目了,覆盖所有的 SDLC 环境,包括管理生产环境的部署。如果你可以访问 [OKD][7]、Red Hat OpenShift lab cluster 或 [Red Hat CodeReady Containers][8],你可以下载[el-CICD 的最新版本][9],参照 [教程][10] 来学习部署分支是何时以怎样的方式创建和使用的。
### 结语
通过实践上面的例子可以帮助你更好的理解开发过程中阻抗失配相关的问题。对齐镜像和部署描述符是成功管理部署的关键部分。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/8/impedance-mismatch-cicd
作者:[Evan "Hippy" Slatis][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/hippyod
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gears_devops_learn_troubleshooting_lightbulb_tips_520.png?itok=HcN38NOk "Tips and gears turning"
[2]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
[3]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
[4]: https://opensource.com/sites/default/files/picture1.png
[5]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
[6]: https://github.com/elcicd
[7]: https://www.okd.io/
[8]: https://cloud.redhat.com/openshift/create/local
[9]: https://github.com/elcicd/el-CICD-RELEASES
[10]: https://github.com/elcicd/el-CICD-docs/blob/master/tutorial.md

View File

@ -0,0 +1,97 @@
[#]: subject: "How to Completely Uninstall Google Chrome From Ubuntu"
[#]: via: "https://itsfoss.com/uninstall-chrome-from-ubuntu/"
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14368-1.html"
如何从 Ubuntu 中彻底卸载 Google Chrome
======
现在,你已经成功地 [在 Ubuntu 上安装 Google Chrome][1]。毕竟,它是世界上最受欢迎的网页浏览器了。
但是,你可能会不喜欢 Google 的产品,因为它们对用户的信息进行追踪和数据挖掘。你决定选择 [Ubuntu 上的其他网页浏览器][2],并且它或许是一个 [非 Chromium 核心的浏览器][3]。
既然你已经不再使用 [Google Chrome][4] 了,那么,把它从 Ubuntu 系统中移除是一个明智的选择。
如何才能做到这一点呢?我来告诉你具体的步骤。
### 从 Ubuntu 中完全移除 Google Chrome
![Illustration for removing Google Chrome from Ubuntu][5]
你可能使用了图形界面的方式安装 Google Chrome但不幸的是你得使用命令行的方式来移除它除非你选择 [使用 Synaptic 软件包管理器][6]。
使用命令行来做这件事也不是很难。首先,按下 [键盘上的 Ctrl+Alt+T 快捷键来打开一个终端][7]。
在终端中输入下面的命令:
```
sudo apt purge google-chrome-stable
```
此时它会向你索要一个密码,这个密码是你的用户账户密码,也就是你用来登录 Ubuntu 系统的密码。
当你输入密码的时候,屏幕上什么也不会显示。这是 Linux 系统的正常行为。继续输入密码,完成后按下回车键。
此时它会让你确认是否删除 Google Chrome输入 `Y` 来确认,或者直接按下回车键也行。
![Removing Google Chrome for Ubuntu][8]
这个操作会从你的 Ubuntu Linux 系统中移除 Google Chrome同时也会移除大多数相关的系统文件。
但是,你的个人设置文件仍然保留在用户主目录中。它包含了 Cookie、会话、书签和其他与你的账户相关的 Chrome 设置信息。当你下次安装 Google Chrome 时,这些文件可以被 Chrome 再次使用。
![Google Chrome leftover settings in Ubuntu][9]
如果你想要彻底地移除 Google Chrome你可能会想要把这些文件也移除掉。那么下面是你需要做的
切换到 `.config` 目录。 **注意 config 前面有个点**`,这是 [Linux 隐藏文件和目录的方式][10]。
```
cd ~/.config
```
然后移除 `google-chrome` 目录:
```
rm -rf google-chrome
```
![Removing the leftover Google Chrome settings from Ubuntu][11]
你也可以仅使用一个命令 `rm -rf ~/.config/google-chrome` 来删除它。因为本教程面向的对象是完完全全的初学者,所以我把这个命令拆分为以上两个步骤来完成,这样可以减少由于拼写问题造成的可能错误。
> 小技巧
>
> 想要你的终端和截图里看起来一样漂亮吗?试试这些 [终端定制小技巧][12]。
我希望这篇快速的入门技巧可以帮助你在 Ubuntu 上摆脱 Google Chrome。
--------------------------------------------------------------------------------
via: https://itsfoss.com/uninstall-chrome-from-ubuntu/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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://itsfoss.com/install-chrome-ubuntu/
[2]: https://itsfoss.com/best-browsers-ubuntu-linux/
[3]: https://itsfoss.com/open-source-browsers-linux/
[4]: https://www.google.com/chrome/index.html
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/removing-google-chrome-ubuntu.png?resize=800%2C450&ssl=1
[6]: https://itsfoss.com/synaptic-package-manager/
[7]: https://itsfoss.com/open-terminal-ubuntu/
[8]: https://itsfoss.com/wp-content/uploads/2021/09/remove-google-chrome-ubuntu.webp
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/google-chrome-ubuntu-leftover-settings.png?resize=800%2C518&ssl=1
[10]: https://itsfoss.com/hide-folders-and-show-hidden-files-in-ubuntu-beginner-trick/
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/remove-google-chrome-leftover-settings-from-Ubuntu.png?resize=800%2C277&ssl=1
[12]: https://itsfoss.com/customize-linux-terminal/

View File

@ -0,0 +1,273 @@
[#]: subject: "How I migrated a WordPress website to a new host"
[#]: via: "https://opensource.com/article/21/9/migrate-wordpress"
[#]: author: "David Both https://opensource.com/users/dboth"
[#]: collector: "lujun9972"
[#]: translator: "lxbwolf"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14371-1.html"
如何把 WordPress 网站迁移到新主机
======
> 使用这个简单的方法来迁移一个网站以及管理防火墙配置。
![(https://img.linux.net.cn/data/attachment/album/202203/19/124316krzvxcr4ff2kr2ji.jpg)]
你有过把一个 WordPress 网站迁移到一台新主机上的需求吗?我曾经迁移过好多次,迁移过程相当简单。当然,的的市场时候我都不会用通用的推荐方法,这次也不例外 —— 我用更简单的方法,这才是我推荐的方法。
这个迁移方法没有破坏性,因此如果出于某些原因你需要还原到原来的服务器上,很容易可以实现。
### 一个 WordPress 网站的组成部分
运行一个基于 [WordPress][2] 的网站有三个重要组成部分WordPress 本身,一个 web 服务器,如 [Apache][3](我正在用),以及 [MariaDB][4]。MariaDB 是 MySQL 的一个分支,功能相似。
业界有大量的 Web 服务器,由于我使用了 Apache 很长时间,因此我推荐用 Apache。你可能需要把 Apache 的配置方法改成你用的 Web 服务器的方法。
### 初始配置
我使用一台 Linux 主机作为防火墙和网络路由。在我的网络中 Web 服务器是另一台主机。我的内部网络使用的是 C 类私有网络地址范围,按 <ruby>[无类别域间路由][5]<rt>Classless Internet Domain Routing</rt></ruby>CIDR方式简单地记作 192.168.0.0/24。
对于防火墙,相比于更复杂的 `firewalld`,我更喜欢用非常简单的 [IPTables][6]。这份防火墙配置中的一行会把 80 端口HTTP接收到的包发送给 Web 服务器。在 `/etc/sysconfig/iptables` 文件中,你可以在注释中看到,我添加了规则,把其他入站服务器连接转发到同一台服务器上合适的端口。
```
# Reroute ports for inbound connections to the appropriate web/email/etc server.
# HTTPD goes to 192.168.0.75
-A PREROUTING -d 45.20.209.41/255.255.255.248 -p tcp -m tcp --dport 80 \
  -j DNAT --to-destination 192.168.0.75:80
```
我使用<ruby>命名虚拟主机<rt>named virtual host</rt></ruby>来配置原来的 Apache Web 服务器,因为我在这个 HTTPD 实例上运行着多个网站。使用命名虚拟主机配置是个不错的方法,因为(像我一样)未来你可能会在运行其他的网站,这个方法可以使其变得容易。
`/etc/httpd/conf/httpd.conf` 中需要迁移的虚拟主机的网站相关部分请参考下面代码。这个片段中不涉及到 IP 地址的修改,因此在新服务器上使用时不需要修改。
```
<VirtualHost *:80>
ServerName www.website1.org
ServerAlias server.org
DocumentRoot "/var/website1/html"
ErrorLog "logs/error_log"
ServerAdmin me@website1.org
<Directory "/var/website1/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
```
在迁移之前,你需要在 `httpd.conf` 的最顶端附近找到 `Listen` 声明并修改成类似下面这样。这个地址是服务器的真实私有 IP 地址,不是公开 IP 地址。
```
Listen 192.168.0.75:80
```
你需要修改新主机上 `Listen` 的 IP 地址。
### 前期工作
准备工作分为以下三步:
* 安装服务
* 配置防火墙
* 配置 web 服务器
#### 安装 Apache 和 MariaDB
如果你的新服务器上还没有 Apache 和 MariaDB那么就安装它们。WordPress 的安装不是必要的。
```
dnf -y install httpd mariadb
```
#### 新服务器防火墙配置
确认下新服务器上的防火墙允许访问 80 端口。你_每台_电脑上都有一个防火墙对吗大部分现代发行版使用的初始化配置包含的防火墙会阻止所有进来的网络流量以此来提高安全等级。
下面片段的第一行内容可能已经在你的 IPTables 或其他基于防火墙的网络过滤器中存在了。它标识已经被识别为来自可接受来源的入站包,并绕过后面的其它 INPUT 过滤规则,这样可以节省时间和 CPU 周期。片段中最后一行标识并放行 80 端口新进来的请求到 HTTPD 的连接。
```
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
<删节>
# HTTP
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
```
下面的示例 `/etc/sysconfig/iptables` 文件是 IPTables 最少规则的例子,可以允许 SSH端口 22和 HTTPD端口 80连接。
```
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# SSHD
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# HTTP
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
# Final disposition for unmatched packets
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
```
在新服务器主机上我需要做的就是在 `/etc/sysconfig/iptables` 文件的防火墙规则里添加上面片段的最后一行,然后重新加载修改后的规则集。
```
iptables-restore /etc/sysconfig/iptables
```
大部分基于红帽的发行版本,如 Fedora使用的是 `firewalld`。我发现对于它的适用场景(如家用、小到中型企业)而言,它过于复杂,因此我不用它。我建议你参照 [firewalld 网页][9] 来向 `firewalld` 添加入站端口 80。
你的防火墙及其配置可能跟这个有些差异,但最终的目的是允许新 Web 服务器 80 端口接收 HTTPD 连接。
#### HTTPD 配置
`/etc/httpd/conf/httpd.conf` 文件中配置 HTTPD。像下面一样在 `Listen` 片段中设置 IP 地址。我的新 Web 服务器 IP 地址是 `192.168.0.125`
```
Listen 192.168.0.125:80
```
复制(对应要迁移的网站的) `VirtualHost` 片段,粘贴到新服务器上 `httpd.conf` 文件的末尾。
### 迁移过程
只有两组数据需要迁移到新服务器 —— 数据库本身和网站目录结构。把两个目录打包成 `tar` 文档。
```
cd /var ; tar -cvf /tmp/website.tar website1/
cd /var/lib ; tar -cvf /tmp/database.tar mysql/
```
把两个 tar 文件复制到新服务器。我通常会把这类文件放到 `/tmp` 下,这个目录就是用来做这种事的。在新服务器上运行下面的命令,把 tar 文档解压到正确的目录。
```
cd /var ; tar -xvf /tmp/website.tar
cd /var/lib ; tar -xvf /tmp/database.tar
```
WordPress 的所有文件都在 `/var/website1` 下,因此不需要在新服务器上安装它。新服务器上不需要执行 WordPress 安装过程。
这个目录就是需要迁移到新服务器上的全部内容。
最后一步是启动(或重启)`mysqld` 和 `httpd` 服务守护进程。WrodPress 不是一个服务,因此不使用守护进程的方式来启动。
```
systemctl start mysqld ; systemctl start httpd
```
启动之后,你应该检查下这些服务的状态。
```
systemctl status mysqld
● mariadb.service - MariaDB 10.5 database server
Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2021-08-21 14:03:44 EDT; 4 days ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Process: 251783 ExecStartPre=/usr/libexec/mariadb-check-socket (code=exited, status=0/SUCCESS)
Process: 251805 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir mariadb.service (code=exited, status=0/SUCCESS)
Process: 251856 ExecStartPost=/usr/libexec/mariadb-check-upgrade (code=exited, status=0/SUCCESS)
Main PID: 251841 (mariadbd)
Status: "Taking your SQL requests now..."
Tasks: 15 (limit: 19003)
Memory: 131.8M
CPU: 1min 31.793s
CGroup: /system.slice/mariadb.service
└─251841 /usr/libexec/mariadbd --basedir=/usr
Aug 21 14:03:43 simba.stmarks-ral.org systemd[1]: Starting MariaDB 10.5 database server...
Aug 21 14:03:43 simba.stmarks-ral.org mariadb-prepare-db-dir[251805]: Database MariaDB is probably initialized in /var/lib/mysql already, n>
Aug 21 14:03:43 simba.stmarks-ral.org mariadb-prepare-db-dir[251805]: If this is not the case, make sure the /var/lib/mysql is empty before>
Aug 21 14:03:44 simba.stmarks-ral.org mariadbd[251841]: 2021-08-21 14:03:44 0 [Note] /usr/libexec/mariadbd (mysqld 10.5.11-MariaDB) startin>
Aug 21 14:03:44 simba.stmarks-ral.org systemd[1]: Started MariaDB 10.5 database server.
systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/httpd.service.d
└─php-fpm.conf
Active: active (running) since Sat 2021-08-21 14:08:39 EDT; 4 days ago
Docs: man:httpd.service(8)
Main PID: 252458 (httpd)
Status: "Total requests: 10340; Idle/Busy workers 100/0;Requests/sec: 0.0294; Bytes served/sec: 616 B/sec"
Tasks: 278 (limit: 19003)
Memory: 44.7M
CPU: 2min 31.603s
CGroup: /system.slice/httpd.service
├─252458 /usr/sbin/httpd -DFOREGROUND
├─252459 /usr/sbin/httpd -DFOREGROUND
├─252460 /usr/sbin/httpd -DFOREGROUND
├─252461 /usr/sbin/httpd -DFOREGROUND
├─252462 /usr/sbin/httpd -DFOREGROUND
└─252676 /usr/sbin/httpd -DFOREGROUND
Aug 21 14:08:39 simba.stmarks-ral.org systemd[1]: Starting The Apache HTTP Server...
Aug 21 14:08:39 simba.stmarks-ral.org httpd[252458]: AH00112: Warning: DocumentRoot [/var/teststmarks-ral/html] does not exist
Aug 21 14:08:39 simba.stmarks-ral.org httpd[252458]: Server configured, listening on: port 80
Aug 21 14:08:39 simba.stmarks-ral.org systemd[1]: Started The Apache HTTP Server.
```
### 最终的修改
现在所需的服务都已经运行了,你可以把 `/etc/sysconfig/iptables` 文件中 HTTDP 的防火墙规则改成下面的样子:
```
-A PREROUTING -d 45.20.209.41/255.255.255.248 -p tcp -m tcp --dport 80 \
  -j DNAT --to-destination 192.168.0.125:80
```
然后重新加载设置的 IPTables 规则。
```
iptables-restore /etc/sysconfig/iptables
```
由于防火墙规则是在防火墙主机上,因此不需要把外部 DNS 入口改成指向新服务器。如果你使用的是内部 DNS 服务器,那么你需要把 IP 地址改成内部 DNS 数据库里的 A 记录。如果你没有用内部 DNS 服务器,那么请确保主机 `/etc/hosts` 文件里新服务器地址设置得没有问题。
### 测试和清理
请确保对新配置进行测试。首先,停止旧服务器上的 `mysqld``httpd` 服务。然后通过浏览器访问网站。如果一切符合预期,那么你可以关掉旧服务器上的 `mysqld``httpd`。如果有失败,你可以把 IPTables 的路由规则改回去到旧服务器上,直到问题解决。
之后我把 MySQL 和 HTTPD 从旧服务器上删除了,这样来确保它们不会意外地被启动。
### 总结
就是这么简单。不需要执行数据库导出和导入的过程,因为 `mysql` 目录下所有需要的东西都已经复制过去了。需要执行导出/导入过程的场景是有网站自己的数据库之外的数据库MariaDB 实例上还有其他网站,而你不想把这些网站复制到新服务器上。
迁移旧服务器上的其他网站也很容易。其他网站依赖的所有数据库都已经随着 MariaDB 的迁移被转移到了新服务器上。你只需要把 `/var/website` 目录迁移到新服务器,添加合适的虚拟主机片段,然后重启 HTTPD。
我遵循这个过程把很多个网站从一个服务器迁移到另一个服务器,每次都没有问题。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/9/migrate-wordpress
作者:[David Both][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/dboth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 "Text editor on a browser, in blue"
[2]: https://wordpress.org/
[3]: https://opensource.com/article/18/2/how-configure-apache-web-server
[4]: https://mariadb.org/
[5]: https://opensource.com/article/16/12/cidr-network-notation-configuration-linux
[6]: https://en.wikipedia.org/wiki/Iptables
[7]: http://www.website1.org
[8]: mailto:me@website1.org
[9]: https://firewalld.org/documentation/howto/open-a-port-or-service.html

View File

@ -0,0 +1,146 @@
[#]: subject: "What you need to know about fuzz testing and Go"
[#]: via: "https://opensource.com/article/22/1/native-go-fuzz-testing"
[#]: author: "Gaurav Kamathe https://opensource.com/users/gkamathe"
[#]: collector: "lujun9972"
[#]: translator: "lxbwolf"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14367-1.html"
你需要了解的 Go 中的模糊测试
======
> Go 团队接受了新增对模糊测试的支持的提议。
![](https://img.linux.net.cn/data/attachment/album/202203/18/103123drbhbozibvt0vtib.jpg)
[Go][2] 的应用越来越广泛。现在它是云原生软件、容器软件、命令行工具和数据库等等的首选语言。Go 很早之前就已经有了内建的 [对测试的支持][3]。这使得写测试代码和运行都相当简单。
### 什么是模糊测试?
<ruby>模糊测试<rt>fuzz testing</rt></ruby>fuzzing是指向你的软件输入非预期的数据。理想情况下这种测试会让你的应用程序崩溃或有非预期的表现。抛开最终的结果从程序对非预期的输入数据的处理结果中你可以得到很多信息这样你就可以增加一些合适的错误处理。
任何一个软件都有对不同来源的输入或数据的接收说明,软件会对这些数据进行处理并返回适当的结果。软件开发后,测试工程师团队对其进行测试,找出软件中的错误,给出测试报告,并(由开发者)修复。通常测试的目的是验证软件的行为是否符合预期。测试又可以细分为不同的类型,如功能测试、集成测试、性能测试等等。每种测试方法关注软件功能的某一个方面,以便发现错误或者提升可靠性或性能。
模糊测试在这一测试过程上更进一步,尝试向软件程序输入一些“无效”或“随机”的数据。这种输入是故意的,期望得到的结果就是程序崩溃或输出异常,这样就可以暴露程序中的错误以便由开发者来修复它们。与其他测试类似,很少需要手动进行模糊测试,业界有大量的模糊测试工具可以将这个过程自动化。
### Go 中的软件测试
举个例子,假如你想测试 `add.go` 中的 `Add()` 函数,你可以在 `add_test.go` 中导入 `testing` 包并把测试体写在以 `TestXXX()` 开头的函数内。
考虑如下代码:
```
func Add(num1, num2 int) int {
}
```
`add_test.go` 文件中,你可能有如下测试代码:
```
import "testing"
func TestAdd(t *testing.T) {
}
```
运行测试:
```
$ go test
```
### 新增对模糊测试的支持
Go 团队已经接受了 [新增对模糊测试的支持的提议][4],以进一步推动这项工作。这涉及到新增一个 `testing.F` 类型,在 `_test.go` 文件中新增 `FuzzXXX()` 函数,在 Go 工具中会新增一个 `-fuzz` 选项来执行这些测试。
`add_test.go` 文件中:
```
func FuzzAdd(f *testing.F) {
}
```
执行以下代码:
```
$ go test -fuzz
```
在本文编写时,这个 [功能还是试验性的][5],但是应该会在 1.18 发布版本中包含。LCTT 译注:[Go 1.18][14] 刚刚发布,已经包含了对模糊测试的支持)目前很多功能如 `-keepfuzzing`、`-race` 等也还没有支持。Go 团队最近发布了一篇 [模糊测试教程][6],值得读一下。
### 安装 gotip 来获取最新的功能
如果你极度渴望在正式发布之前尝试这些功能,你可以使用 `gotip` 来测试即将正式发布的 Go 功能并反馈给他们。你可以使用下面的命令来安装 `gotip`。安装之后,你可以用 `gotip` 程序代替以前的 `go` 程序来编译和运行程序。
```
$ go install golang.org/dl/gotip@latest
$ gotip download
$ gotip version
go version devel go1.18-f009910 Thu Jan 6 16:22:21 2022 +0000 linux/amd64
```
### 社区对于模糊测试的观点
软件社区中经常会讨论模糊测试不同的人对模糊测试有不同的看法。有些人认为这是一种有用的技术可以找到错误尤其是在安全方面。然而考虑到模糊测试所需要的资源CPU、内存有人就认为这是一种浪费而他们更愿意用其他的测试方法。即使在 Go 团队内部,意见也不统一。我们可以看到 Go 的联合创始人 Rob Pike 对模糊测试的使用和在 Go 中的实现是持轻微的怀疑态度的。
> ..._虽然模糊测试有助于发现某类错误但是它会占用大量的 CPU 和存储资源,并且效益成本比率也不明确。我担心为了写模糊测试浪费精力,或者 git 仓库中充斥大量无用的测试数据_
>
> ~[Rob Pike][7]
然而Go 安全团队的另一个成员Filo Sottile似乎对 Go 新增支持模糊测试很乐观,举了很多例子来支持,也希望模糊测试能成为开发过程中的一部分。
> _我想说模糊测试可以发现极端情况下的错误。这是我们作为安全团队对其感兴趣的原因在极端情况下发现的错误可以避免在生产环境中成为弱点。_
>
> _我们希望模糊测试能成为开发的一部分 —— 不只是构建或安全方面 —— 而是整个开发过程:它能提升相关代码的质量..._
>
> ~[Filo Sottile][8]
### 现实中的模糊测试
对我而言模糊测试在发现错误以及让系统变得更安全和更有弹性方面似乎非常有效。举个例子Linux 内核也会使用名为 [syzkaller][9] 的工具进行模糊测试,这个工具已经发现了 [大量][10] 错误。
[AFL][11] 也是比较流行的模糊测试工具,用来测试 C/C++ 写的程序。
之前也有对 Go 程序进行模糊测试的观点,其中之一就是 Filo 在 GitHub 评论中提到的 [go-fuzz][12]。
> _go-fuzz 的记录提供了相当惊人的证据,证明模糊处理能很好地找到人类没有发现的错误。根据我的经验,我们只需要消耗一点点 CPU 的时间就可以得到极端情况下非常高效的测试结果。_
### 为什么在 Go 中新增对模糊测试的原生支持
如果我们的需求是对 Go 程序进行模糊测试,之前的工具像 `go-fuzz` 就可以完成,那么为什么要在这种语言中增加原生支持呢?[Go 模糊测试设计草案][13] 中说明了这样做的一些根本原因。设计的思路是让开发过程更简单,因为前面说的工具增加了开发者的工作量,还有功能缺失。如果你没有接触过模糊测试,那么我建议你读一下设计草案文档。
> 开发者可以使用诸如 `go-fuzz``fzgo`(基于 `go-fuzz`)来解决某些需求。然而,已有的每种解决方案都需要在典型的 Go 测试上做更多的事,而且还缺少关键的功能。相比于其他的 Go 测试(如基准测试和单元测试),模糊测试不应该比它们复杂,功能也不应该比它们少。已有的解决方案增加了额外的开销,比如自定义命令行工具。
### 模糊测试工具
在大家期望 Go 语言新增功能的列表中,模糊测试是其中很受欢迎的一项。虽然现在还是试验性的,但在将要到来的发布版本中会变得更强大。这给了我们足够的时间去尝试它以及探索它的使用场景。我们不应该把它视为一种开销,如果使用得当它会是一种发现错误非常高效的测试工具。使用 Go 的团队应该推动它的使用,开发者可以写简单的模糊测试,测试团队去慢慢扩展以此来使用它全部的能力。
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/1/native-go-fuzz-testing
作者:[Gaurav Kamathe][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/gkamathe
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD "Person using a laptop"
[2]: https://go.dev/
[3]: https://pkg.go.dev/testing
[4]: https://github.com/golang/go/issues/44551
[5]: https://go.dev/blog/fuzz-beta
[6]: https://go.dev/doc/tutorial/fuzz
[7]: https://github.com/golang/go/issues/44551#issuecomment-784584785
[8]: https://github.com/golang/go/issues/44551#issuecomment-784655571
[9]: https://github.com/google/syzkaller
[10]: https://github.com/google/syzkaller/blob/master/docs/linux/found_bugs.md
[11]: https://github.com/google/AFL
[12]: https://github.com/dvyukov/go-fuzz
[13]: https://go.googlesource.com/proposal/+/master/design/draft-fuzzing.md
[14]: https://go.dev/blog/go1.18

View File

@ -0,0 +1,151 @@
[#]: subject: "6 Reasons to Try Nitrux OS"
[#]: via: "https://news.itsfoss.com/reasons-to-try-nitrux-os/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "aREversez"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14359-1.html"
尝试 Nitrux 系统的六大理由
======
> Nitrux OS 是一个基于 Debian 的有趣的 Linux 发行版。还没有试过吗?我认为你应该试试。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/nitrux-os-try.jpg?w=1200&ssl=1)
Nitrux 系统也许算不上 Linux 的主流发行版本之一,但它绝对是一款极其独特的产品。
2019 年,我们 [采访了 Nitrux 的创始人 Uri Herrera][1],了解到 Herrera 等人开发这款系统的初衷:超越传统的 Linux 发行版。
自那之后,过了许久,我们终于迎来了 [Nitrux 2.0 版本][2]。
不要忘了Nitrux 在去年 [放弃基于 Ubuntu而选择了 Debian][3]。
考虑到自 Nitrux 发行以来的数年间,也发生了许多变化,你应该尝试一下这款系统。
这里,我要分享一些体验 [Nitrux 系统][4] 的理由:
### 1、Nitrux 不再基于 Ubuntu
![][5]
人们一般都会推荐基于 Ubuntu 的 Linux 发行版本,来满足日常所需。
当然,在我们 [为新手推荐的 Linux 系统][6] 中,也主要是许多基于 Ubuntu 的版本,但是请不要误会。
我们之所以推荐基于 Ubuntu 的发行版本,唯一的理由在于它们简单易用,支持大量的商业软件。
所以,如果你不是刚开始使用 Linux 系统,同时也想尝试既能让你耳目一新,又不至于使你感到陌生,而且十分稳定的发行版,基于 Debian 的 Nirtux 是一个不错的选择。
你完全不需要在短期内迅速了解这款系统,就可以得心应手地使用终端来完成各项工作。
感兴趣的话,可以参考我们的文章 [Debian vs Ubuntu][7],了解更多。
### 2、专注 AppImage
![][5a]
[AppImage][8] 是一个通用的打包系统,这种软件包不需要任何依赖。你不需要在 Linux 上安装任何软件包管理器或者依赖包,就可以直接运行 AppImage 应用。
AppImage 旨在打造便携、高效的软件包系统,省去安装的步骤,与 Windows 系统的便携版软件非常相似。
Nitrux 操作系统专注 AppImage 应用软件,为你带来流畅的用户体验。
NX 软件中心是一个 GUI 程序,用户可以通过使用 Mauikit该软件中心的 UI 框架),安装、管理 AppImage 应用程序。
### 3、基于 KDE 桌面环境的发行版
![][5b]
Nitrux 操作系统是 [搭载 KDE 桌面环境中最好的 Linux 发行版][9] 之一。 如果你不喜欢 GNOME 或者其他开箱即用的桌面环境DEKDE 会是一个不错的选择。
也许你还不知道, 相较于其他桌面环境,[KDE 可以在很多方面进行定制][10]。
因此,在 KDE 桌面环境下,你可以毫不费力地打造自己的个性化桌面。
### 4、独特的用户体验
![][11]
Nitrux 的用户体验结合了最好的 KDE 桌面环境与 Qt 技术,并对这些进行了调整,为你带来全新的用户体验。
虽然在使用 Nitrux 操作系统时,你不会觉得十分陌生,但是还是会感到有些许的不同。
即使你没有对 Nitrux 系统做任何自定义的设置,开箱即用的体验也足以让它成为 [最优雅的发行版][12] 之一。
### 5、Maui Shell
![][11a]
[Maui Shell][13] 是 Nitrux 用户体验的亮点之一。近来Maui Shell 得到了进一步的完善,将这些呈现在了桌面端和移动端的融合界面上。
尽管 Maui Shell 目前还不成熟,但是外观看起来十分大气简约,就像 [System76 将要推出基于 Rust 的桌面环境][14] 一样令人兴奋。
这也是我们推荐尝试 Nitrux 操作系统最重要的原因之一。时间会证明Nitrux 系统是否将会开启桌面体验的全新时代。
### 6、Xanmod 内核
![][5c]
[Xanmod 内核][15] 是一个定制的主线 Linux 内核版本,对性能进行了适当的调整,附加了一些其他功能。有了它,你的桌面体验一定能得到大幅提升。
自 2.0 版本起Nitrux 操作系统选用 Xanmod 作为默认内核,为用户提供“升级版”的桌面体验。
当然你也可以选择其他 Linux 内核,比如 Liquorix 和 Libre各擅胜场。
如果你不喜欢 Xanmod也可以选择长期支持版的主线内核。在 Nitrux 操作系统上,你完全可以无缝切换使用不同的内核。
- [Nitrux OS][4]
### 总结
诚然,从主流发行版转到像 Nitrux 这样的操作系统,需要考虑各种风险。
但是,**我建议你好好考虑一番:**
Nitrux 这样的发行版热衷于按照他们的愿景来改进事情。
尽管背后没有强大的企业和财力支撑,他们依然可以开发出这款令人惊艳的发行版、开发出 [Maui 项目][16],以及别开生面的 Maui shell。
所以,我认为,我们也应该以己所能,尽己之力,支持这些优秀的发行版。
不过话说回来,每一款 Linux 发行版都会或多或少地存在一些问题。当你试用一款新的发行版时,你需要给它点儿时间,在最终将它作为日常使用的操作系统之前,慢慢地去适应它。
换言之,我推荐你在业余时间试用 Nitrux 操作系统,或者直接装个虚拟机来一探究竟。
我很关注大家对这篇文章的看法,请在下方评论留言。
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/reasons-to-try-nitrux-os/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[aREversez](https://github.com/aREversez)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/nitrux-linux/
[2]: https://news.itsfoss.com/nitrux-2-0-release/
[3]: https://news.itsfoss.com/nitrux-linux-debian/
[4]: https://nxos.org/
[5]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/not-ubuntu-illustration.png?w=1000&ssl=1
[6]: https://itsfoss.com/best-linux-beginners/
[7]: https://linux.cn/article-13746-1.html
[5a]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/appimage-illustration.png?w=1000&ssl=1
[8]: https://itsfoss.com/use-appimage-linux/
[5b]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/kde-illustration.png?w=1000&ssl=1
[9]: https://itsfoss.com/best-kde-distributions/
[10]: https://itsfoss.com/kde-customization/
[11]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/01/nitrux-2-visual.png?resize=1568%2C882&ssl=1
[12]: https://itsfoss.com/beautiful-linux-distributions/
[11a]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2021/12/maui-shell.png?w=1200&ssl=1
[13]: https://news.itsfoss.com/maui-shell-unveiled/
[14]: https://news.itsfoss.com/system76-cosmic-panel/
[5c]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/xanmod-kernel-illustration.png?w=1000&ssl=1
[15]: https://xanmod.org/
[16]: https://mauikit.org

View File

@ -0,0 +1,90 @@
[#]: subject: "Scan documents and old photos on Linux with Skanlite"
[#]: via: "https://opensource.com/article/22/2/scan-documents-skanlite-linux-kde"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14402-1.html"
用 Skanlite 在 Linux 上扫描文件和老照片
======
> 使用这个 Linux KDE 应用,将你的档案数字化。
![](https://img.linux.net.cn/data/attachment/album/202203/27/114937eannabb3zn45lraa.jpg)
虽然现在的世界已经大部分实现了数字化但仍有一些时候你还是需要打印一份表格签字然后把它扫描回来。有时候我发现在手机上拍个快照就够了但有些行业需要比草率的快照更好的复印件因此平板扫描仪是必要的。KDE 项目提供了一个叫做 Skanlite 的应用程序,它可以帮助你导入在平板上扫描的文件,甚至是用联机相机扫描的文件。
### 在 Linux 上安装 Skanlite
你可以从你的软件库中安装 Skanlite。在 Fedora、Mageia 和类似的地方:
```
$ sudo dnf install skanlite
```
在 Elementary、Linux Mint 和其他基于 Debian 的发行版上:
```
$ sudo apt install skanlite
```
### 扫描仪驱动
市场上的大多数扫描仪都与 SANE 扫描仪 API 兼容。SANE 并不是一个真正的驱动而是一个协议可以接收来自图像采集设备的输入并为希望围绕它建立一个应用的程序员提供选项。Skanlite 就是这样一个应用。
我还没有遇到过不与 SANE 接口兼容的扫描仪,但可能也有不与 SANE 接口兼容的扫描仪。在这些情况下,请在制造商的网站上寻找 SANE 或 TWAIN 的驱动,或者寻找它们专有的驱动和扫描仪接口。后者可能无法使用 Skanlite但当你不确定你的扫描仪是否通过标准协议进行通信时Skanlite 总是值得试试。我甚至遇到过打印机和扫描仪的二合一设备,尽管打印机需要一个额外的驱动,但扫描仪却能立即被识别。
### 使用 Skanlite
当你启动 Skanlite 时它首先会在你的系统中搜索图像采集设备。在笔记本电脑上Skanlite 通常会发现网络摄像头是一个有效的输入源(因为它是),但它也会找到连接到你机器上的平板扫描仪。选择你要使用的扫描仪,然后继续。
要看扫描的内容,点击应用程序右下角的“<ruby>预览<rt>Preview</rt></ruby>”按钮。
![Skanlite with custom artwork][2]
这将在右面板上显示一个预览图像。没有任何东西被保存到你的硬盘上,这只是显示你的扫描仪上目前有什么。
### 选择一个扫描区域
如果你只需要扫描仪上的一部分内容,你可以选择一个你想保存的区域。要选择一个单一的区域,在你想保存的区域上点击并拖动你的鼠标。当有一个有效的选择时,当你点击“<ruby>扫描<rt>Scan</rt></ruby>”按钮时,只有你选择的那部分会被保存。
你可以有一个以上的选区,当你需要扫描几个小图像或只扫描一个大文件的特定部分时,这特别有效。要添加一个选区,请点击出现在选区中心的 “+” 图标。
![Adding selections][3]
你可以通过点击 “-” 图标来删除选区,当你有多个活动选区时,该图标会出现。
### 扫描设置
图像采集设置位于左边的面板上。这些控件允许你导入彩色或灰度的图像,并对图像的亮度和对比度进行调整。这些选项是基于软件的,不影响你的扫描仪的行为方式,但它们是常见的调整,在这里做这些调整可以使你不必在 GIM 或 Gwenview 中对图像进行后期处理。
在许多情况下,你的扫描仪可能有可配置的设置,可在 Skanlite 窗口左侧的“<ruby>扫描仪特定选项<rt>Scanner Specific Options</rt></ruby>”标签中找到。有些扫描仪允许你调整色温、亮度、饱和度和其他出现在固件中的属性。可用的选项根据设备和供应商的不同而不同,所以你有可能在这个面板上看到变化,这取决于你与哪种设备的对接。
### 扫描和保存
当你准备好导入图像(或图像的选定区域,如果你已经做了选择)时,点击 Skanlite 窗口右下角的“<ruby>扫描<rt>Scan</rt></ruby>”按钮。根据你的设备,它可能需要一些时间来创建扫描,但当它完成后,会提示你保存或丢弃图像。如果你喜欢你所看到的,点击“<ruby>保存<rt>Save</rt></ruby>”。
图像会被保存到你所配置的任何默认位置。要查看默认位置,点击窗口右下角的“<ruby>设置<rt>Settings</rt></ruby>”按钮。在 “<ruby>Skanlite 设置<rt>Skanlite Settings</rt></ruby>”中,你可以设置默认保存位置、默认名称格式和图像分辨率。你还可以控制每次扫描后是否提示你保存或丢弃图像,或者你是否想要保存所有的东西并在以后进行分类。
### Linux 上的扫描很容易
在 Linux 上扫描文件是如此简单,我很少考虑这个问题。通常不需要你去寻找和安装特殊的驱动或应用,因为像 Skanlite 这样的应用使用开放协议,使这个过程变得简单。下次你有一份需要数字化的拷贝时,用 Skanlite 导入它。
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/2/scan-documents-skanlite-linux-kde
作者:[Seth Kenlon][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/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/documents_papers_file_storage_work.png?itok=YlXpAqAJ (Filing papers and documents)
[2]: https://opensource.com/sites/default/files/skanlite.png (Skanlite with custom artwork)
[3]: https://opensource.com/sites/default/files/skanlite-selection.jpg (Adding selections)

View File

@ -0,0 +1,129 @@
[#]: subject: "Experience the Stunning Cutefish Desktop in Arch Linux"
[#]: via: "https://www.debugpoint.com/2022/02/cutefish-arch-linux-install/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14385-1.html"
在 Arch Linux 中体验令人惊叹的 Cutefish 桌面
======
![](https://img.linux.net.cn/data/attachment/album/202203/23/145712h8q77pe7j9q29hj2.jpg)
> 现在你可以在 Arch Linux 中体验 Cutefish 桌面了。本文概述了在 Arch Linux 系统中安装 Cutefish 桌面环境的步骤。
### Cutefish 桌面
前一阵子,[我们点评了 CutefishOS][2],它带有看起来非常棒的 Cutefish 桌面,得到了我们的读者的积极反应和关注。因此,我们认为这是一个完美的时机,是时候在你最喜欢的 Arch Linux 中体验一下这个桌面了。
在你进入安装部分之前,这里有一些关于 Cutefish 桌面的小知识。
Cutefish 桌面是 [CutefishOS][3] 的一部分,这是一个正在开发的新 Linux 发行版。这个基于 Debian 的 Linux 发行版具有令人难以置信的外观、轻量级的 Cutefish 桌面。
Cutefish 桌面其内部是以 Qt Quick、QML、C++ 和 KDE 框架为基础编写的。这个现代的桌面环境使用 KWin 和 SDDM 进行窗口和显示管理。
Cutefish 桌面为你带来了所寻求的一个完全 macOS 风格的、开箱即用的 Linux 桌面。也就是说,你可以获得令人惊叹的图标、壁纸、全局菜单、带有漂亮通知弹出窗口的顶部栏和底部停靠区。
你可在 [这里] 阅读详细的点评。
### 在 Arch Linux 中安装 Cutefish 桌面
#### 安装基础 Arch 系统
本指南假设在尝试这些步骤之前,你的系统中已经安装好了基本的 Arch Linux。或者如果你也安装了任何基于 Arch 的 Linux 发行版,你也可以尝试。只是在这些情况下要注意显示管理的问题。
如果你是 Arch 的新手,你可以参考我们的 Arch Linux 安装指南。
* [如何使用 archinstall 安装 Arch Linux推荐][4]
* [如何安装 Arch Linux基本指南][5]
#### 安装 Cutefish 桌面
Arch Linux 社区仓库包含了 Cutefish 组,其中有该桌面运行所需的所有组件。它包括核心软件包、原生应用和下面提到的附加工具。
在你的 Arch Linux 系统的终端提示符下,运行下面的命令来安装所有 Cutefish 桌面软件包。
```
pacman -S cutefish
```
![A base Arch Linux prompt][6]
![Install Cutefish in Arch Linux][7]
接下来,我们需要通过下面的命令安装 Xorg 和显示管理器 SDDM。如果你将 Cutefish 桌面安装在安装有其他诸如 GNOME、KDE Plasma 或 Xfce 等桌面环境的 Arch Linux 中,那么请注意,因为你已经安装了一个显示管理器和 Xorg。所以你可以轻松跳过这一步。
```
pacman -S xorg sddm
```
上述命令完成后,通过 systemctl 启用显示管理器。
```
systemctl enable sddm
```
这就是裸机安装 Cutefish 桌面的全部内容。完成后,重启系统,登录后你应该看到 Cutefish 桌面如下。
![Cutefish Desktop in Arch Linux][1]
基础安装需要额外的定制,因为它不像 Cutefish OS 那样接近。
### 安装后的配置
尽管 Arch 仓库中的 Cutefish 组包含了它的原生应用,如计算器和文件管理器,但该桌面缺乏基本的应用,你需要单独安装这些应用来使它成为一个功能齐全的高效桌面。
我建议使用下面的命令来安装以下基本的应用。你可以跳过这一步,或者选择任何其他的应用/组合。
* Firefox 网页浏览器
* Kwrite 文本编辑器
* ttf-freefont 字体
* VLC 媒体播放器
* Gwenview 图像查看器
* GIMP 图像编辑器
* LibreOffice
* Transmission
```
pacman -S firefox ttf-freefont kwrite vlc gwenview gimp libreoffice-still transmission-qt
```
安装后,打开设置,改变你选择的字体。默认字体是 courier它在桌面上看起来很糟糕。
按照你的选择完成所有的定制后,重启系统。然后享受 Arch Linux 中的 Cutefish 桌面。
![The Stunning Login Lock Screen of Cutefish Desktop][9]
### 结束语
这个桌面正在开发中,所以在写这篇文章时,你会发现设置项目不多。例如,没有办法改变分辨率、隐藏停靠区等等。不过,你仍然可以安装额外的应用来使用。如果你想做体验一番,可以去试试。
加油。
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/02/cutefish-arch-linux-install/
作者:[Arindam][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.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/02/Cutefish-Desktop-in-Arch-Linux-1024x575.jpg
[2]: https://www.debugpoint.com/2021/11/cutefish-os-review-2021/
[3]: https://en.cutefishos.com/
[4]: https://www.debugpoint.com/2022/01/archinstall-guide/
[5]: https://www.debugpoint.com/2020/11/install-arch-linux/
[6]: https://www.debugpoint.com/wp-content/uploads/2022/02/A-base-Arch-Linux-prompt.jpg
[7]: https://www.debugpoint.com/wp-content/uploads/2022/02/Install-Cutefish-in-Arch-Linux.jpg
[9]: https://www.debugpoint.com/wp-content/uploads/2022/02/The-Stunning-Login-Lock-Screen-of-Cutefish-Desktop-1024x576.jpg
[10]: https://t.me/debugpoint
[11]: https://twitter.com/DebugPoint
[12]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[13]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,71 @@
[#]: subject: "9 resources to help you contribute to open source in 2022"
[#]: via: "https://opensource.com/article/22/3/contribute-open-source-2022"
[#]: author: "Opensource.com https://opensource.com/users/admin"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14372-1.html"
2021 总结:如何为开源做出贡献
======
> 你准备好推进你的开源之旅了吗?这里有一些如何给开源做贡献的提示和教程。
![](https://img.linux.net.cn/data/attachment/album/202203/19/145149b9uvnnrkfnuzm7uf.jpg)
在 2022 年,开源正变得越来越家喻户晓。但多年来,开源一直被称为企业 IT 领域中潦倒的弱势群体。开源已经以某种形式或方式存在了 [几十年][2],但甚至直到 20 世纪 90 年代末,它才正式有了自己的 [名字][3]。你可能一直都在使用开源技术但却不知道。事实上你目前正在阅读的网站LCTT 译注:指 opensource.com )就是在开源的内容管理系统 [Drupal][4] 上运行的。你的汽车、笔记本电脑、智能手表和电子游戏很可能是 [由 Linux][5] 这个开源操作系统支持的。
红帽公司的年度《[企业开源状况][6]》在最近发布了其中包含了大量的见解对任何在开源技术领域发展的人都有帮助。首先77% 的 IT 领导对企业开源的看法比一年前更积极82% 的 IT 领导更可能选择对开源社区有贡献的供应商。这意味着,参与开源比以往任何时候都更重要。现在是推进你的开源之旅的时候了,无论你在哪里。这里有一些资源可以帮助你踏上这条路。
### 为什么要为开源做贡献?
* 《[是什么激励了开源软件的贡献者?][7]》新的研究发现人们贡献的原因自 21 世纪初以来已经改变。
* 《[现在为开源做贡献的 3 个理由][8]》现在,比以往任何时候都更加是为开源做贡献的理想时机。
* 《[为开源做贡献时的 7 个成功策略][9]》一位作者在为开源项目做贡献的经验帮助她在技术领域找到了她梦想的工作。
### 为开源做出你的第一次贡献
* 《[8 种非编码的方式为开源做贡献][10]》无论你是程序员新手,还是经验丰富的老手,或者根本不是工程师,在编码之外还有很多方式为开源项目做贡献。
* 《[为 Slack 的开源替代方案做贡献的 6 种方式][11]》加入成千上万为 Mattermost 这个开源消息平台贡献代码、翻译、文档等的人。
* 《[任何人都可以为开放实践图书馆做出贡献的 7 种方式][12]》为开放实践图书馆做出贡献是参与全球从业者社区的一种有趣方式,这些从业者都愿意分享他们的知识并改进他们自己的工作方式。
* 《[如果你有一份全职工作,如何为 Kubernetes 做贡献][13]》你可以在业余时间从事最大的开源项目之一的内部工作。
### 鼓励他人为开源做贡献
* 《[为什么你的开源项目需要的不仅仅是程序员][14]》仅仅是开发人员并不能创造出满足各种需求的长保质期的开源项目,是时候欢迎更多的角色和人才了。
* 《[开源贡献者加入的 10 个技巧][15]》让新的贡献者感到自己在社区中受到欢迎,对项目的未来至关重要,因此,在加入时投入时间和注意力是很重要的。
### 分享你对开源贡献的建议
当涉及到参与开源社区时,有无限的可能性。在这里,我们的目标是庆祝社区的不同观点和背景,其中包括你。你的独特故事激励着全球各地的人们参与到开源中来。来吧,[把你的文章想法发给我们][16]
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/3/contribute-open-source-2022
作者:[Opensource.com][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/admin
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
[2]: https://www.redhat.com/en/topics/open-source/what-is-open-source#the-history-of-open-source?intcmp=7013a000002qLH8AAM
[3]: https://opensource.com/article/18/2/coining-term-open-source-software
[4]: https://opensource.com/tags/drupal
[5]: https://opensource.com/article/19/8/everyday-tech-runs-linux
[6]: https://www.redhat.com/en/enterprise-open-source-report/2022?intcmp=7013a000002qLH8AAM
[7]: https://opensource.com/article/21/4/motivates-open-source-contributors
[8]: https://opensource.com/article/20/6/why-contribute-open-source
[9]: https://opensource.com/article/22/1/open-source-contributions-career
[10]: https://opensource.com/life/16/1/8-ways-contribute-open-source-without-writing-code
[11]: https://opensource.com/article/20/7/mattermost
[12]: https://opensource.com/article/21/10/open-practice-library
[13]: https://opensource.com/article/19/11/how-contribute-kubernetes
[14]: https://opensource.com/article/20/9/open-source-role-diversity
[15]: https://opensource.com/article/19/12/open-source-contributors
[16]: https://linux.cn/article-14335-1.html

View File

@ -0,0 +1,93 @@
[#]: subject: "Epic Games Store Now Works on Steam Deck"
[#]: via: "https://news.itsfoss.com/epic-games-steam-deck/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "zd200572"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14374-1.html"
Epic 游戏商店现在可在 Steam Deck 上使用啦
======
> 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/run-epicgames-on-steam-deck-now.png?w=1200&ssl=1)
Steam Deck 在加强对 Linux 平台的游戏支持方面做出了有力推动。
它运行在 **Steam OS 3.0**(基于 Arch并具有 KDE Plasma 桌面环境。感谢 Valve它没有锁定平台并让用户在上面进行试验。
尽管不是每个人都可以拿到它,但这是一款令人兴奋的硬件,可以挑战任天堂 Switch 掌机。
它可能还不支持所有的流行游戏(比如《命运 2》、《堡垒之夜》但它在几个 3A 级大作和独立游戏上取得了不错的进展。你可以到官方的 [Deck 认证][1] 页面查看有关支持游戏的最新信息。
现在,更令人激动的是,事实证明 Steam Deck 也可以使用 [Epic 游戏商店][2]**非官方的**)来运行游戏。但是,怎样运行呢,让我们来一探究竟。
### 通过 Heroic 游戏启动器使用 Epic 游戏商店
是的,这就是 [去年][4] 制作的 [Heroic 游戏启动器][3], 并且已知它可以运行在 Linux 桌面上。
另外,(据 [GamingOnLinux][5])感谢 Liam Dawe他和各位开发者协调成功地在 Steam Deck 上测试运行了 Heroic 游戏启动器(及 [Heroic Bash 启动器][6])。
[![][7]](https://youtu.be/89Dw3I6NJX4)
补充一句,**Heroic Bash 启动器** 是一个为所有已安装的 Heroic 游戏创建启动脚本(.sh 文件)的工具,它允许你直接从终端或者游戏前端/启动器启动游戏,而不必打开 Heroic。
故事的发生是这样的(根据我与 Heroic Bash 启动器开发者的简短交谈):
最初,在 Steam Deck 上实验运行 Epic 游戏商店时Steam 控制器无法工作,因为 Epic 游戏商店是使用 Steam 客户端以一个“非 Steam 游戏”运行的。
所以Heroic Bash 启动器的开发者,[Rishabh Moharir][8](也是这里的一位作者)建议使用他的工具,按照他 [GitHub 上的维基指南][9] 来试试。
Heroic Bash 启动器可以在 Linux 桌面上与 Epic 游戏商店配合使用。所以,这值得一试!
然后,幸运地,它工作了。
### 在 Steam Deck 上安装 Epic 游戏商店
首先,你需要在 Steam Deck 上使用可用的 AppImage 文件在**桌面模式**下安装 **Heroic 游戏启动器**
完成后,你需要登录并下载你选择的游戏。
接下来,你需要下载最新的 [legendary][10] 二进制文件,并在启动器设置中将其设置为替代的 legendary 二进制文件。
你需要在启动器的游戏设置中配置并设置兼容层为 Proton 7.0。
这时,你需要下载最新的 [Heroic Bash 启动器二进制文件][11],然后运行它。
最后,你必须根据这个 [GitHub 上的官方维基指南][9],把游戏添加到 Steam 中(以便在 Steam Deck 的界面中找到它)。
总之,“手工爱好者”们肯定需要花好大一会儿才能使其工作。另外,如果你仍然困惑,你可以在 [维基][12] 上找到包含详细信息的同样的一套步骤和细节,这是 Heroic 游戏启动器团队整理的(或者参考上面的视频)。
对我来说,这听起来可行,应该不会超越大多数 Steam Deck 用户的能力。不幸的是,我无法在印度买到 Steam Deck目前
至于 Steam Deck 上的 Epic 游戏商店的未来,我们只能抱以最好的期望。
你试过 Steam Deck 吗?在下面的评论区让我知道你的看法。
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/epic-games-steam-deck/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[zd200572](https://github.com/zd200572)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://www.steamdeck.com/en/verified
[2]: https://www.epicgames.com/store/en-US/
[3]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher
[4]: https://news.itsfoss.com/heroic-games-launcher/
[5]: https://www.gamingonlinux.com/2022/03/heroic-games-launcher-now-works-nicely-on-steam-deck/
[6]: https://github.com/redromnon/HeroicBashLauncher
[7]: https://i0.wp.com/i.ytimg.com/vi/UvuGAQDagWE/hqdefault.jpg?w=780&ssl=1
[8]: https://news.itsfoss.com/author/rishabh/
[9]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/wiki/Adding-Games-to-Steam-on-Linux
[10]: https://github.com/derrod/legendary/releases/
[11]: https://github.com/redromnon/HeroicBashLauncher/releases/
[12]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/wiki/SteamDeck---Running-Epic-Games

View File

@ -0,0 +1,244 @@
[#]: subject: "Creating and initializing maps in Groovy vs Java"
[#]: via: "https://opensource.com/article/22/3/maps-groovy-vs-java"
[#]: author: "Chris Hermansen https://opensource.com/users/clhermansen"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14378-1.html"
在 Groovy 和 Java 中创建并初始化映射的不同
======
> Java 和 Groovy 中的<ruby>映射<rt>map</rt></ruby>都是非常通用的,它允许<ruby>关键字<rt>key</rt></ruby><ruby><rt>value</rt></ruby>为任意类型,只要继承了 `Object` 类即可。
![](https://img.linux.net.cn/data/attachment/album/202203/21/092532ykbhkq36vbr3bpzg.jpg)
我最近在探索 Java 与 Groovy 在 [创建并初始化<ruby>列表<rt>List</rt></ruby>][2] 和 [在运行时构建<ruby>列表<rt>List</rt></ruby>][3] 方面的一些差异。我观察到就实现这些功能而言Groovy 的简洁和 Java 的繁复形成了鲜明对比。
在这篇文章中,我将实现在 Java 和 Groovy 中创建并初始化<ruby>映射<rt>Map</rt></ruby>。映射为开发支持根据 <ruby>关键字<rt>key</rt></ruby> 检索的结构提供了可能,如果找到了这样一个关键字,它就会返回对应的 <ruby><rt>value</rt></ruby>。今天,很多编程语言都实现了映射,其中包括 Java 和 Groovy也包括了 Python它将映射称为 <ruby>字典<rt>dict</rt></ruby>、Perl、awk 以及许多其他语言。另一个经常被用来描述映射的术语是 <ruby>关联数组<rt>associative array</rt></ruby>,你可以在 [这篇维基百科文章][4] 中了解更多。Java 和 Groovy 中的映射都是非常通用的,它允许关键字和值</rt></ruby>为任意类型,只要继承了 `Object` 类即可。
### 安装 Java 和 Groovy
Groovy 基于 Java因此你需要先安装 Java。你的 Linux 发行版的仓库中可能有最近的比较好的 Java 和 Groovy 版本。或者,你也可以在根据上面链接中的指示来安装 Groovy。对于 Linux 用户来说,[SDKMan][5] 是一个不错的代替选项,你可以使用它来获取多个 Java 和 Groovy 版本,以及许多其他的相关工具。在这篇文章中,我使用的 SDK 发行版是:
* Java: version 11.0.12-open of OpenJDK 11;
* Groovy: version 3.0.8.
### 言归正传
Java 提供了非常多的方式来实例化和初始化映射,并且从 Java 9 之后,添加了一些新的方式。其中最明显的方式就是使用 `java.util.Map.of()` 这个静态方法,下面介绍如何使用它:
```
var m1 = Map.of(
"AF", "Afghanistan",
"AX", "Åland Islands",
"AL", "Albania",
"DZ", "Algeria",
"AS", "American Samoa",
"AD", "Andorra",
"AO", "Angola",
"AI", "Anguilla",
"AQ", "Antarctica");
System.out.println("m1 = " + m1);
System.out.println("m1 is an instance of " + m1.getClass());
```
事实证明,在此种情况下,`Map.of()` 有两个重要的限制。其一,这样创建出来的映射实例是<ruby>不可变的<rt>immutable</rt></ruby>。其二,你最多只能提供 20 个参数,用来表示 10 个<ruby>键值对<rt>key-value pair</rt></ruby>
你可以尝试着添加第 10 对和第 11 对,比方说 "AG", "Antigua and Barbuda" 和 "AR", "Argentina",然后观察会发生什么。你将发现 Java 编译器尝试寻找一个支持 11 个键值对的 `Map.of()` 方法而遭遇失败。
快速查看 [java.util.Map 类的文档][8],你就会找到上述第二个限制的原因,以及解决这个难题的一种方式:
```
var m2 = Map.ofEntries(
Map.entry("AF", "Afghanistan"),
Map.entry("AX", "Åland Islands"),
Map.entry("AL", "Albania"),
Map.entry("DZ", "Algeria"),
Map.entry("AS", "American Samoa"),
Map.entry("AD", "Andorra"),
Map.entry("AO", "Angola"),
Map.entry("AI", "Anguilla"),
Map.entry("AQ", "Antarctica"),
Map.entry("AG", "Antigua and Barbuda"),
Map.entry("AR", "Argentina"),
Map.entry("AM", "Armenia"),
Map.entry("AW", "Aruba"),
Map.entry("AU", "Australia"),
Map.entry("AT", "Austria"),
Map.entry("AZ", "Azerbaijan"),
Map.entry("BS", "Bahamas"),
Map.entry("BH", "Bahrain"),
Map.entry("BD", "Bangladesh"),
Map.entry("BB", "Barbados")
);
System.out.println("m2 = " + m2);
System.out.println("m2 is an instance of " + m2.getClass());
```
这就是一个比较好的解决方式,前提是我不在随后的代码里改变使用 `Map.ofEntries()` 创建并初始化的映射内容。注意,我在上面使用了 `Map.ofEntries()` 来代替 `Map.of()`
然而,假设我想要创建并初始化一个非空的映射,随后往这个映射中添加数据,我需要这样做:
```
var m3 = new HashMap<String,String>(Map.ofEntries(
Map.entry("AF", "Afghanistan"),
Map.entry("AX", "Åland Islands"),
Map.entry("AL", "Albania"),
Map.entry("DZ", "Algeria"),
Map.entry("AS", "American Samoa"),
Map.entry("AD", "Andorra"),
Map.entry("AO", "Angola"),
Map.entry("AI", "Anguilla"),
Map.entry("AQ", "Antarctica"),
Map.entry("AG", "Antigua and Barbuda"),
Map.entry("AR", "Argentina"),
Map.entry("AM", "Armenia"),
Map.entry("AW", "Aruba"),
Map.entry("AU", "Australia"),
Map.entry("AT", "Austria"),
Map.entry("AZ", "Azerbaijan"),
Map.entry("BS", "Bahamas"),
Map.entry("BH", "Bahrain"),
Map.entry("BD", "Bangladesh"),
Map.entry("BB", "Barbados")
));
System.out.println("m3 = " + m3);
System.out.println("m3 is an instance of " + m3.getClass());
m3.put("BY", "Belarus");
System.out.println("BY: " + m3.get("BY"));
```
这里,我把使用 `Map.ofEntries()` 创建出来的不可变映射作为 `HashMap` 的一个构造参数,以此创建了该映射的一个<ruby>可变副本<rt>mutable copy</rt></ruby>,之后我就可以修改它 —— 比如使用 `put()` 方法。
让我们来看看上述过程如何用 Groovy 来实现:
```
def m1 = [
"AF": "Afghanistan",
"AX": "Åland Islands",
"AL": "Albania",
"DZ": "Algeria",
"AS": "American Samoa",
"AD": "Andorra",
"AO": "Angola",
"AI": "Anguilla",
"AQ": "Antarctica",
"AG": "Antigua and Barbuda",
"AR": "Argentina",
"AM": "Armenia",
"AW": "Aruba",
"AU": "Australia",
"AT": "Austria",
"AZ": "Azerbaijan",
"BS": "Bahamas",
"BH": "Bahrain",
"BD": "Bangladesh",
"BB": "Barbados"]
println "m1 = $m1"
println "m1 is an instance of ${m1.getClass()}"
m1["BY"] = "Belarus"
println "m1 = $m1"
```
只看一眼,你就会发现 Groovy 使用了 `def` 关键字而不是 `var` —— 尽管在<ruby>最近模型<rt>late-model</rt><ruby>的 Groovyversion 3+)中,使用 `var` 关键字也是可行的。
你还会发现,你是通过在括号里添加了一个键值对列表来创建一个映射的。不仅如此,这样创建的列表对象还非常有用,这里有几个原因。其一,它是可变的;其二,它是一个 `LinkedHashMap` 的实例,内部维持了数据的插入顺序。所以,当你运行 Java 版本的代码并打印出变量 `m3`,你会看到:
```
m3 = {BB=Barbados, BD=Bangladesh, AD=Andorra, AF=Afghanistan, AG=Antigua and Barbuda, BH=Bahrain, AI=Anguilla, AL=Albania, AM=Armenia, AO=Angola, AQ=Antarctica, BS=Bahamas, AR=Argentina, AS=American Samoa, AT=Austria, AU=Australia, DZ=Algeria, AW=Aruba, AX=Åland Islands, AZ=Azerbaijan}
```
而当你运行 Groovy 版本的代码,你会看到:
```
m1 = [AF:Afghanistan, AX:Åland Islands, AL:Albania, DZ:Algeria, AS:American Samoa, AD:Andorra, AO:Angola, AI:Anguilla, AQ:Antarctica, AG:Antigua and Barbuda, AR:Argentina, AM:Armenia, AW:Aruba, AU:Australia, AT:Austria, AZ:Azerbaijan, BS:Bahamas, BH:Bahrain, BD:Bangladesh, BB:Barbados]
```
再一次,你将看到 Groovy 是如何简化事情的。这样的语法非常直观,有点像 Python 里的字典,并且,即使你有一个超过 10 个键值对的初始列表,你也不需要去记住各种必要的别扭方式。注意我们使用的表达式:
```
m1[“BY”] = “Belarus”
```
而在 Java 中,你需要这样做:
```
m1.put(“BY”, “Belarus”)
```
还有这个映射默认是可变的这么做的利弊很难评判还是得取决于你的需求是什么。我个人觉得Java 在这种情况下的 “默认不可变” 机制,最让我困扰的地方是,它没有一个类似于 `Map.mutableOfMutableEntries()` 的方法。这迫使一些刚学会如何声明和初始化一个映射的程序员,不得不转念去思考该如何把他们手中不可变的映射,转换为可变的。同时我也想问,创建一个不可变的对象然后再舍弃它,这样真的好吗?
另一个值得考虑的事情是Groovy 使用方括号代替 Java 中的 `put()``get()` 方法来进行关键字查找。因此你可以这样写:
```
m1[“ZZ”] = m1[“BY”]
```
而不需要这样写:
```
m1.put(“ZZ”,m1.get(“BY”))
```
有时候,就像使用某个类的实例变量一样来使用映射中的关键字和值是一个好办法。设想你现在有一堆想要设置的属性,在 Groovy 中,它们看起来就像下面这样:
```
def properties = [
      verbose: true,
      debug: false,
      logging: false]
```
然后,你可以改变其中的某个属性,就像下面这样:
```
properties.verbose = false
```
之所以这样能工作,是因为,只要关键字符合特定的规则,你就可以省略引号,然后直接用点操作符来代替方括号。尽管这个功能非常有用,也非常好用,它也同时也意味着,如果你要把一个变量作为一个映射的关键字来使用,你就必须把这个变量包裹在圆括号里,就像下面这样:
```
def myMap = [(k1): v1, (k2): v2]
```
是时候告诉勤奋的读者 Groovy 是一门为编写脚本而量身定制的语言了。映射通常是脚本中的关键元素,它为脚本提供了<ruby>查找表<rt>lookup table</rt></ruby>,并且通常起到了作为内存数据库的作用。我在这里使用的例子是 ISO 3166 规定的两个字母的国家代码和国家名称。对在世界上各个国家的互联网使用者来说,这些代码是很熟悉的。此外,假设我们要编写一个从日志文件中查找互联网主机名,并借此来了解用户的地理位置分布的脚本工具,那么这些代码会是十分有用的部分。
### Groovy 相关资源
[Apache Groovy 网站][10] 上有非常多的文档。另一个很棒的 Groovy 资源是 [Mr. Haki][11]。[Baeldung 网站][12] 提供了大量 Java 和 Groovy 的有用教程。学习 Groovy 还有一个很棒的原因,那就是可以接着学习 [Grails][13],后者是一个优秀的、高效率的全栈 Web 框架。它基于许多优秀组件构建而成,比如有 Hibernate、Spring Boot 和 Micronaut 等。
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/3/maps-groovy-vs-java
作者:[Chris Hermansen][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
[2]: https://opensource.com/article/22/1/creating-lists-groovy-java
[3]: https://opensource.com/article/22/2/accumulating-lists-groovy-vs-java
[4]: https://en.wikipedia.org/wiki/Associative_array
[5]: https://sdkman.io/
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+map
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[8]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Map.html
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[10]: https://groovy-lang.org/
[11]: https://blog.mrhaki.com/
[12]: https://www.baeldung.com/
[13]: https://grails.org/

View File

@ -0,0 +1,147 @@
[#]: subject: "Using Homebrew Package Manager on Fedora Linux"
[#]: via: "https://fedoramagazine.org/using-homebrew-package-manager-on-fedora-linux/"
[#]: author: "Mehdi Haghgoo https://fedoramagazine.org/author/powergame/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14380-1.html"
在 Fedora Linux 上使用 Homebrew 包管理器
======
![](https://img.linux.net.cn/data/attachment/album/202203/21/193616z7kvf71b7z48kn92.jpg)
### 简介
Homebrew 是一个 macOS 的包管理器,用于在 macOS 上安装 UNIX 工具。但是,它也可以在 Linux和 Windows WSL上使用。它是用 Ruby 编写的并提供主机系统macOS 或 Linux可能不提供的软件包因此它在操作系统包管理器之外提供了一个辅助的包管理器。此外它只以非 root 用户身份在前缀 `/home/linuxbrew/.linuxbrew``~/.linuxbrew` 下安装软件包,不会污染系统路径。这个包管理器在 Fedora Linux 上也适用。在这篇文章中,我将尝试告诉你 Homebrew 与 Fedora Linux 包管理器 `dnf` 有什么不同,为什么你可能想在 Fedora Linux 上安装和使用它,以及如何安装。
> 免责声明
>
> 你应该经常检查你在系统上安装的软件包和二进制文件。Homebrew 包通常以非 sudoer 用户运行,并工作在专门的前缀的路径下,因此它们不太可能造成破坏或错误配置。然而,所有的安装操作都要自己承担风险。作者和 Fedora 社区不对任何可能直接或间接因遵循这篇文章而造成的损失负责。
### Homebrew 如何工作
Homebrew 在底层使用 Ruby 和 Git。它使用特殊的 Ruby 脚本从源代码构建软件,这些脚本被称为 “<ruby>配方<rt>formula</rt></ruby>”,看起来像这样(使用 `wget` 包作为例子):
LCTT 译注Homebrew 本身意思是“家酿”,在这个软件中,有各种类似于酿酒的比喻。)
```
class Wget < Formula
homepage "https://www.gnu.org/software/wget/"
url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"
def install
system "./configure", "--prefix=#{prefix}"
system "make", "install"
end
end
```
### Homebrew 与 dnf 有何不同
Homebrew 是一个包管理器,提供了许多 UNIX 软件工具和包的最新版本,例如 FFmpeg、Composer、Minikube 等。当你想安装一些由于某种原因在 Fedora Linux RPM 仓库中没有的软件包时,它就会证明很有用。所以,它并不能取代 `dnf`
### 安装 Homebrew
在开始安装 Homebrew 之前,确保你已经安装了 glibc 和 gcc。这些工具可以在 Fedora 上通过以下方式安装:
```
sudo dnf groupinstall "Development Tools"
```
然后,通过在终端运行以下命令来安装 Homebrew
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
在安装过程中,你会被提示输入你的 `sudo` 密码。另外,你可以选择 Homebrew 的安装前缀,但默认的前缀就可以了。在安装过程中,你将成为 Homebrew 前缀目录的所有者,这样你就不必输入 `sudo` 密码来安装软件包。安装将需要数分钟。完成后,运行以下命令,将 `brew` 添加到你的 `PATH` 中:
```
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bash_profile
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
```
### 安装和检查软件包
要在 Homebrew 上使用“配方”安装一个软件包,只需运行:
```
brew install <formula>
```
`<formula>` 替换为你要安装的“配方”的名称。例如,要安装 Minikube只需运行
```
brew install minikube
```
你也可以用以下方式搜索“配方”:
```
brew search <formula>
```
要获得一个“配方”的信息,请运行:
```
brew info <formula>
```
另外,你可以用以下命令查看所有已安装的“配方”:
```
brew list
```
### 卸载软件包
要从你的 Homebrew 前缀中卸载一个软件包,请运行:
```
brew uninstall <formula>
```
### 升级软件包
要升级一个用 Homebrew 安装的特定软件包,请运行:
```
brew upgrade <formula>
```
要更新 Homebrew 和所有已安装的“配方”到最新版本,请运行:
```
brew update
```
### 总结
Homebrew 是一个简单的包管理器,可以与 `dnf` 一起成为有用的工具(两者完全没有关系)。尽量坚持使用 Fedora 原生的 `dnf` 包管理器,以避免软件冲突。然而,如果你在 Fedora Linux 软件库中没有找到某个软件,那么你也许可以用 Homebrew 找到并安装它。请看 [“配方”列表][2] 以了解有哪些可用的软件。另外Fedora Linux 上的 Homebrew 还不支持图形化应用(在 Homebrew 术语中称为“<ruby>酒桶<rt>cask</rt></ruby>”)。至少,我在安装 GUI 应用时没有成功过。
### 参考资料和进一步阅读
要了解更多关于 Homebrew 的信息,请查看以下资源:
* Homebrew 主页:<https://brew.sh>
* Homebrew 文档:<https://docs.brew.sh>
* 维基百科 Homebrew 页面:<https://en.wikipedia.org/wiki/Homebrew_(package_manager)>
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/using-homebrew-package-manager-on-fedora-linux/
作者:[Mehdi Haghgoo][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/powergame/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2022/03/homebrew_sized-up-816x346.png
[2]: https://formulae.brew.sh/formula/

View File

@ -0,0 +1,229 @@
[#]: subject: "How to use undocumented web APIs"
[#]: via: "https://jvns.ca/blog/2022/03/10/how-to-use-undocumented-web-apis/"
[#]: author: "Julia Evans https://jvns.ca/"
[#]: collector: "lujun9972"
[#]: translator: "lxbwolf"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14358-1.html"
如何调用没有文档说明的 Web API
======
![](https://img.linux.net.cn/data/attachment/album/202203/15/103119ab6yoika09og669a.jpg)
大家好!几天前我写了篇 [小型的个人程序][1] 的文章,里面提到了调用没有文档说明的“秘密” API 很有意思,你需要从你的浏览器中把 cookie 复制出来才能访问。
有些读者问如何实现,因此我打算详细描述下,其实过程很简单。我们还会谈谈在调用没有文档说明的 API 时,可能会遇到的错误和道德问题。
我们用谷歌 Hangouts 举例。我之所以选择它,并不是因为这个例子最有用(我认为官方的 API 更实用),而是因为在这个场景中更有用的网站很多是小网站,而小网站的 API 一旦被滥用,受到的伤害会更大。因此我们使用谷歌 Hangouts因为我 100% 肯定谷歌论坛可以抵御这种试探行为。
我们现在开始!
### 第一步:打开开发者工具,找一个 JSON 响应
我浏览了 <https://hangouts.google.com>,在 Firefox 的开发者工具中打开“<ruby>网络<rt>Network</rt></ruby>”标签,找到一个 JSON 响应。你也可以使用 Chrome 的开发者工具。
打开之后界面如下图:
![][2]
找到其中一条 “<ruby>类型<rt>Type</rt></ruby>” 列显示为 `json` 的请求。
为了找一条感兴趣的请求,我找了好一会儿,突然我找到一条 “people” 的端点,看起来是返回我们的联系人信息。听起来很有意思,我们来看一下。
### 第二步:复制为 cURL
下一步,我在感兴趣的请求上右键,点击 “<rt>复制<rt>Copy</rt></ruby>” -> “<ruby>复制为 cURL<rt>Copy as cURL</rt></ruby>”。
然后我把 `curl` 命令粘贴到终端并运行。下面是运行结果:
```
$ curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' -X POST ........ (省略了大量请求标头)
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
```
你可能会想 —— 很奇怪,“二进制的输出在你的终端上无法正常显示” 是什么错误?原因是,浏览器默认情况下发给服务器的请求头中有 `Accept-Encoding: gzip, deflate` 参数,会把输出结果进行压缩。
我们可以通过管道把输出传递给 `gunzip` 来解压,但是我们发现不带这个参数进行请求会更简单。因此我们去掉一些不相关的请求头。
### 第三步:去掉不相关的请求头
下面是我从浏览器获得的完整 `curl` 命令。有很多行!我用反斜杠(`\`)把请求分开,这样每个请求头占一行,看起来更清晰:
```
curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0' \
-H 'Accept: */*' \
-H 'Accept-Language: en' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'X-HTTP-Method-Override: GET' \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Cookie: REDACTED'
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'X-Goog-AuthUser: 0' \
-H 'Origin: https://hangouts.google.com' \
-H 'Connection: keep-alive' \
-H 'Referer: https://hangouts.google.com/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-site' \
-H 'Sec-GPC: 1' \
-H 'DNT: 1' \
-H 'Pragma: no-cache' \
-H 'Cache-Control: no-cache' \
-H 'TE: trailers' \
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'
```
第一眼看起来内容有很多,但是现在你不需要考虑每一行是什么意思。你只需要把不相关的行删掉就可以了。
我通常通过删掉某行查看是否有错误来验证该行是不是可以删除 —— 只要请求没有错误就一直删请求头。通常情况下,你可以删掉 `Accept*`、`Referer`、`Sec-*`、`DNT`、`User-Agent` 和缓存相关的头。
在这个例子中,我把请求删成下面的样子:
```
curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Origin: https://hangouts.google.com' \
-H 'Cookie: REDACTED'\
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'
```
这样我只需要 4 个请求头:`Authorization`、`Content-Type`、`Origin` 和 `Cookie`。这样容易管理得多。
### 第四步:在 Python 中发请求
现在我们知道了我们需要哪些请求头,我们可以把 `curl` 命令翻译进 Python 程序!这部分是相当机械化的过程,目标仅仅是用 Python 发送与 cUrl 相同的数据。
下面是代码实例。我们使用 Python 的 `requests` 包实现了与前面 `curl` 命令相同的功能。我把整个长请求分解成了元组的数组,以便看起来更简洁。
```
import requests
import urllib
data = [
('personId','101777723'), # I redacted these IDs a bit too
('personId','117533904'),
('personId','111526653'),
('personId','116731406'),
('extensionSet.extensionNames','HANGOUTS_ADDITIONAL_DATA'),
('extensionSet.extensionNames','HANGOUTS_OFF_NETWORK_GAIA_GET'),
('extensionSet.extensionNames','HANGOUTS_PHONE_DATA'),
('includedProfileStates','ADMIN_BLOCKED'),
('includedProfileStates','DELETED'),
('includedProfileStates','PRIVATE_PROFILE'),
('mergedPersonSourceOptions.includeAffinity','CHAT_AUTOCOMPLETE'),
('coreIdParams.useRealtimeNotificationExpandedAcls','true'),
('requestMask.includeField.paths','person.email'),
('requestMask.includeField.paths','person.gender'),
('requestMask.includeField.paths','person.in_app_reachability'),
('requestMask.includeField.paths','person.metadata'),
('requestMask.includeField.paths','person.name'),
('requestMask.includeField.paths','person.phone'),
('requestMask.includeField.paths','person.photo'),
('requestMask.includeField.paths','person.read_only_profile_info'),
('requestMask.includeField.paths','person.organization'),
('requestMask.includeField.paths','person.location'),
('requestMask.includeField.paths','person.cover_photo'),
('requestMask.includeContainer','PROFILE'),
('requestMask.includeContainer','DOMAIN_PROFILE'),
('requestMask.includeContainer','CONTACT'),
('key','REDACTED')
]
response = requests.post('https://people-pa.clients6.google.com/v2/people/?key=REDACTED',
headers={
'X-HTTP-Method-Override': 'GET',
'Authorization': 'SAPISIDHASH REDACTED',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'https://hangouts.google.com',
'Cookie': 'REDACTED',
},
data=urllib.parse.urlencode(data),
)
print(response.text)
```
我执行这个程序后正常运行 —— 输出了一堆 JSON 数据!太棒了!
你会注意到有些地方我用 `REDACTED` 代替了,因为如果我把原始数据列出来你就可以用我的账号来访问谷歌论坛了,这就很不好了。
### 运行结束!
现在我可以随意修改 Python 程序,比如传入不同的参数,或解析结果等。
我不打算用它来做其他有意思的事了,因为我压根对这个 API 没兴趣,我只是用它来阐述请求 API 的过程。
但是你确实可以对返回的一堆 JSON 做一些处理。
### curlconverter 看起来很强大
有人评论说可以使用 <https://curlconverter.com/> 自动把 curl 转换成 Python和一些其他的语言这看起来很神奇 —— 我都是手动转的。我在这个例子里使用了它,看起来一切正常。
### 追踪 API 的处理过程并不容易
我不打算夸大追踪 API 处理过程的难度 —— API 的处理过程并不明显!我也不知道传给这个谷歌论坛 API 的一堆参数都是做什么的!
但是有一些参数看起来很直观,比如 `requestMask.includeField.paths=person.email` 可能表示“包含每个人的邮件地址”。因此我只关心我能看懂的参数,不关心看不懂的。
### (理论上)适用于所有场景
可能有人质疑 —— 这个方法适用于所有场景吗?
答案是肯定的 —— 浏览器不是魔法!浏览器发送给你的服务器的所有信息都是 HTTP 请求。因此如果我复制了浏览器发送的所有的 HTTP 请求头,那么后端就会认为请求是从我的浏览器发出的,而不是用 Python 程序发出的。
当然,我们去掉了一些浏览器发送的请求头,因此理论上后端是可以识别出来请求是从浏览器还是 Python 程序发出的,但是它们通常不会检查。
这里有一些对读者的告诫 —— 一些谷歌服务的后端会通过令人难以理解(对我来说是)方式跟前端通信,因此即使理论上你可以模拟前端的请求,但实际上可能行不通。可能会遭受更多攻击的大型 API 会有更多的保护措施。
我们已经知道了如何调用没有文档说明的 API。现在我们再来聊聊可能遇到的问题。
### 问题 1会话 cookie 过期
一个大问题是我用我的谷歌会话 cookie 作为身份认证,因此当我的浏览器会话过期后,这个脚本就不能用了。
这意味着这种方式不能长久使用(我宁愿调一个真正的 API但是如果我只是要一次性快速抓取一小组数据那么可以使用它。
### 问题 2滥用
如果我正在请求一个小网站,那么我的 Python 脚本可能会把服务打垮,因为请求数超出了它们的处理能力。因此我请求时尽量谨慎,尽量不过快地发送大量请求。
这尤其重要,因为没有官方 API 的网站往往是些小网站且没有足够的资源。
很明显在这个例子中这不是问题 —— 我认为在写这篇文章的过程我一共向谷歌论坛的后端发送了 20 次请求,他们肯定可以处理。
如果你用自己的账号身份过度访问这个 API 并导致了故障,那么你的账号可能会被暂时封禁(情理之中)。
我只下载我自己的数据或公共的数据 —— 我的目的不是寻找网站的弱点。
### 请记住所有人都可以访问你没有文档说明的 API
我认为本文最重要的信息并不是如何使用其他人没有文档说明的 API。虽然很有趣但是也有一些限制而且我也不会经常这么做。
更重要的一点是,任何人都可以这么访问你后端的 API每个人都有开发者工具和网络标签查看你传到后端的参数、修改它们都很容易。
因此如果一个人通过修改某些参数来获取其他用户的信息,这不值得提倡。我认为提供公开 API 的大部分开发者们都知道,但是我之所以再提一次,是因为每个初学者都应该了解。: )
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/2022/03/10/how-to-use-undocumented-web-apis/
作者:[Julia Evans][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[wxy
](https://github.com/wxy
)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://jvns.ca/
[b]: https://github.com/lujun9972
[1]: https://jvns.ca/blog/2022/03/08/tiny-programs/
[2]: https://jvns.ca/images/network-tab.png

View File

@ -0,0 +1,158 @@
[#]: subject: "Piwigo: An Open-Source Google Photos Alternative That You Can Self-Host"
[#]: via: "https://itsfoss.com/piwigo/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14389-1.html"
Piwigo一个你可以自行托管的开源谷歌照片替代品
======
> 如果你想摆脱“谷歌照片”Piwigo 是一个令人印象深刻的开源替代方案,能够自我托管。让我们来探讨一下它的更多信息。
“谷歌照片”是备份你的照片和视频的最流行的选择之一。LCTT 译注:并不是……)
考虑到它是大多数安卓手机的默认选择,使用谷歌照片管理照片/视频是一种无缝体验。
但是,如果你想从它那里转移到一些开源的、对隐私更友好的东西怎么办?不只是谷歌照片,还有其它一些照片托管平台也是专有的。
请看看 Piwigo一个开源的 [照片管理软件][1] 来帮助你。
### Piwigo你可以自行托管的开源照片库
![][2]
[Piwigo][3] 是一个开源解决方案,可以帮助管理你的照片和视频。
你可以选择自己托管,控制你的数据,或者选择云托管(**数据存储在法国,有备份**)。
顺便说一句,该公司起源于法国。
不仅仅是针对个人Piwigo 也为组织和团队量身定做。
如果你担心使用谷歌照片或类似服务上传时的隐私政策Piwigo 可以成为一个出色的替代品。
Piwigo 提供了一系列的功能和细粒度的控制来管理你的照片。
### Piwigo 的功能
![][4]
虽然它是主流服务的一个可行的替代品,但它为个人和组织提供了先进的功能。
一些功能包括:
* 通过云托管(\*.piwigo.com获得你的专用子域
* 能够批量下载
* 创建相册
* 选择照片来分配现有的相册集
* 通过链接分享照片
* 用公共和私人模式进行访问管理
* 能够对用户进行分组,以管理你的相册或照片(对组织/团队来说很有效)。
* 基本分析,以跟踪你的使用情况和使用的存储空间
* 支持向相册/照片添加标签
* 支持深色模式
* 能够编辑照片的元数据
* 过滤器,以快速找到照片/相册
* 支持 JPG/JPEG、PNG 和 GIF 文件(针对个人)
* 支持所有文件类型(仅适用于企业使用)
* 为个人用户提供无限的存储空间
* 支持自定义域名(即使是云托管选项)
* 插件可扩展功能
* 支持主题
* 移动支持(安卓和 iOS
除了上述功能外,你还可以获得改善用户管理和 Piwigo 的整体用户体验的更多选项。
![][5]
我使用其针对个人的云托管选项(**有 30 天的试用期**)对其进行了快速测试。让我分享我的一些见解,以帮助你在尝试之前了解它们。
### 使用 Piwigo 来管理照片
当你注册一个账户时,你可以指定你的自定义子域。
例如,我把我的测试账户放在 **ankushsoul.piwigo.com**
![][6]
任何人都可以通过在他们的浏览器中输入上述 URL 来访问我公开分享的照片/相册。
所以,最好是尽可能保持子域的名称独一无二。在这两种情况下,你也可以将相册/照片限制给登录的用户(或你自己),其他人即使知道你的子域,也无法访问你的照片。
![][7]
你可以前往它的仪表板,检查你的存储使用情况和整体活动情况。
它有两个激活的插件,一个用于内部功能,另一个默认用于打击垃圾信息。
![][8]
你会发现有很多插件可以加强批量管理,启用管理员信息,激活相册的评论,在你的相册上添加到期时间,限制下载,以及访问一些令人兴奋的功能。
你可以花点时间浏览一下现有的插件选择,评估一下它们与谷歌照片相比能有多大用处。
当然,你在任何主流的云照片托管服务中都得不到这种控制。
所以,这很值得探索。
![][9]
对于现有的其他功能,你可以管理多个用户,控制访问,发送通知(通过电子邮件),还可以进行一些维护活动。
总的来说,用户体验是相当好的。它可能没有提供最现代的用户界面,但它可以工作,而且很容易管理。
**注意**:考虑到 Play Store 上的应用没有收到最新的更新,移动体验(在 Android 上)可能并不令人满意。然而,你可以在他们的 GitHub 上找到最新版本的 APK 文件。
### 开始使用 Piwigo
我认为 Piwigo 非常适合各类人使用,从想组织照片的人,到想合作/分享图片的用户,都可以使用。
如果你选择自我托管,你应该查看它的 [文档][10] 和探索 [GitHub 页面][11]。
考虑到你独自管理它,你将需要适当地维护实例,并对你的数据进行备份。
如果你选择 [云托管选项][12](作为个人),定价从每年 **39 欧元** 开始,不限图片文件上传,如果你订阅 3 年,价格会更便宜。
![][13]
个人计划没有提到具体的存储限制(无限)。因此,可以说你不应该有任何问题,除非你开始滥用该服务。
鉴于你在该服务中得到的控制权,大多数用户会更愿意使用云托管服务,而放弃像谷歌照片这样的服务。
企业/组织的定价计划将是昂贵的(每月)。然而,它支持企业的所有文件类型。
- [Piwigo][3]
你认为像 Piwigo 这样的谷歌照片的自行托管替代品如何?你试过吗?云主机选项是主流选项的可行替代品吗?
请在下面的评论中告诉我你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/piwigo/
作者:[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://itsfoss.com/linux-photo-management-software/
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-feature.jpg?resize=800%2C424&ssl=1
[3]: https://piwigo.com/
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-album-edit.png?resize=800%2C451&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-upload.png?resize=800%2C665&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-sign-up.png?resize=800%2C646&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-dashboard.png?resize=800%2C435&ssl=1
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-plugins.png?resize=800%2C499&ssl=1
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-config.png?resize=800%2C632&ssl=1
[10]: https://piwigo.org/doc/doku.php
[11]: https://github.com/Piwigo
[12]: https://piwigo.com/pricing
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-pricing.png?resize=800%2C509&ssl=1

View File

@ -0,0 +1,71 @@
[#]: subject: "Zorin OS 16.1 Brings Much Needed Stability and Improvements"
[#]: via: "https://www.debugpoint.com/2022/03/zorin-os-16-1-release/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14365-1.html"
Zorin OS 16.1 带来了急需的稳定性和改进措施
======
> Zorin OS 16.1 带来了安全补丁、新软件,团队的目标是打造更好的发行版。
Zorin OS 之所以受欢迎,是因为它为 Windows 用户的 Linux 之旅提供了一个完美的起点。由于其简单的设计、优雅的软件包选择和开箱即用的 Windows 外观,它是当今所有用户欢迎和追捧的 Linux 发行版之一。
自 [Zorin OS 16][1] 以来,经过近两个月的时间,这第一个小版本现在可以供已经在运行 16.0 版本的用户下载和升级了。
![Zorin OS 16.1 Desktop][2]
### Zorin OS 16.1 - 新内容
Zorin OS 16.1 为你的系统带来了最新安全补丁,包括 LibreOffice 7.3 办公套件和一些更新的软件包。
如果你刚买了一台新的笔记本电脑或安装了一个新的游戏工作站Zorin OS 16.1 还支持索尼的 PlayStation 5 Dual Sense 游戏控制器和苹果的魔术鼠标 2。此外你还得到了对英特尔第 12 代处理器和英伟达 RTX 3050 显卡的出色支持。
此外由于最新的软件包Zorin 开发人员承诺对汽车 Wi-Fi 和打印机有更好的支持。
下面是这个小版本的更新包和应用的快速总结。
* 基于 Ubuntu 20.04.3 LTS
* Zorin 桌面,基于 GNOME 3.38.4
* LibreOffice 7.3
* Firefox 98
* Linux Kernel 5.13
* GIMP 2.10.18
* Evolution 邮件客户端
如果你想深入了解这些变化,完整的细节可以在[这里][3]找到。
那么,在哪里下载?
### 下载
在你点击下载之前,你应该知道它有一个“专业”版本,带有额外的主题和开箱即用的设置,价值 39 美元,而“核心”版本是完全免费下载的。你可以在下载页面阅读“专业版”和“核心版”的比较。
在我看来,核心版应该足够了,如果你有足够的经验,你可以改变设置,使其成为专业版。因此,我们推荐核心版用于一般用途。
- [下载 Zorin OS 16.1][5]
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/zorin-os-16-1-release/
作者:[Arindam][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.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/2021/12/zorin-os-16-lite-review-xfce/
[2]: https://www.debugpoint.com/wp-content/uploads/2022/03/Zorin-OS-16.1-Desktop-1024x575.jpg
[3]: https://blog.zorin.com/2022/03/10/zorin-os-16-1-released-support-for-ukraine/
[5]: https://zorin.com/os/download/
[6]: https://t.me/debugpoint
[7]: https://twitter.com/DebugPoint
[8]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[9]: https://facebook.com/DebugPoint

View File

@ -3,33 +3,34 @@
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "aREversez"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14382-1.html"
可以替代 Microsoft Office 的 5 款最佳软件 [附对比表]
横向对比 5 款微软 Office 替代品
======
在这篇文章中,我们将推荐 5 款可以替代 Microsoft Office 的最佳软件,并从功能、操作难易程度等方面,对它们进行比较。看一看哪款更适合你?
![](https://img.linux.net.cn/data/attachment/album/202203/22/102722qhd38mnle30sejnt.jpg)
> 在这篇文章中,我们将推荐 5 款可以替代微软 Office 的最佳软件,并从功能、操作难易程度等方面,对它们进行比较。看一看哪款更适合你?
可以说Office 办公软件是微软开发的最优质的软件之一,受到世界各地用户的青睐,广泛应用于各行各业,当属近几十年来软件市场涌现出来的精品。
不过大家都知道Office 不仅没有开发适用于 Linux 的版本而且价格高昂。对于企业用户或者个人用户来说Office 365 的价格就更贵了,远超普通人能接受的价格水平。
不过大家都知道,微软 Office 不仅没有开发适用于 Linux 的版本而且价格高昂。对于企业用户或者个人用户来说Office 365 的价格就更贵了,远超普通人能接受的价格水平。
那么,有哪些软件可以替代 Office 呢?
那么,有哪些软件可以替代微软 Office 呢?
这篇文章推荐 5 款可以替代 Office 的最佳软件。
### 可以替代 Microsoft Office 的最佳软件
这篇文章推荐 5 款可以替代微软 Office 的最佳软件。
### LibreOffice
![LibreOffice][1]
首先推荐的是 [LibreOffice][2]。LibreOffice 是一款免费开源的办公套件,由文档基金会开发维护,支持 Linux, macOS, 以及 Windows 系统。
首先推荐的是 [LibreOffice][2]。LibreOffice 是一款自由开源的办公套件,由文档基金会开发维护,支持 Linux、macOS 以及 Windows 系统。
LibreOffice 套件包括表格工具 [Calc][3], 文字处理工具 Writer, 演示工具 Impress, 画图工具 Draw 以及数据库工具 Base。
LibreOffice 套件包括表格工具 [Calc][3]、文字处理工具 Writer、演示工具 Impress、画图工具 Draw 以及数据库工具 Base。
LibreOffice 办公软件的开发十分很活跃,同时不断提升对 Microsoft Office 的兼容性。如果善加利用LibreOffice 完全可以取代 Office。借助丰富的技术文档和社区资源用户可以迅速掌握 LibreOffice 的使用方法。
LibreOffice 办公软件的开发十分很活跃,同时不断提升对微软 Office 的兼容性。如果善加利用LibreOffice 完全可以取代微软 Office。借助丰富的技术文档和社区资源用户可以迅速掌握 LibreOffice 的使用方法。
企业用户也可以免费使用 LibreOffice如果需要用它来完成关键工作用户也可以购买配置服务和支持服务相关费用十分低廉。
@ -41,57 +42,44 @@ LibreOffice 办公软件的开发十分很活跃,同时不断提升对 Microso
* [帮助文档][6]
* [官方支持论坛][7]
* * *
### Google Docs
![Google Docs][8]
搜索引擎巨头 Google 为用户免费提供一套网页版的办公套件——[Google Docs][9], 其中包括 Docs文档编辑器Sheets表格程序Slides演示程序
搜索引擎巨头谷歌为用户免费提供了一套网页版的办公套件 —— [Google Docs][9],其中包括 Docs文档编辑器、Sheets表格程序Slides演示程序
用户可以在 Google 云盘中免费创建、打开文档。随时随地自由存取。Google Docs 界面设计优美,内置工具栏、高级选项、拼写检查、语音输入功能(仅支持 Chrome 浏览器)、加密功能以及云存储服务。Google 也为 iOS 系统和安卓系统提供了移动端,用户可以在移动设备上轻松打开、编辑文档。
用户可以在谷歌云盘中免费创建、打开文档。随时随地自由存取。Google Docs 界面设计优美,内置工具栏、高级选项、拼写检查、语音输入功能(仅支持 Chrome 浏览器)、加密功能以及云存储服务。谷歌也为 iOS 系统和安卓系统提供了移动端,用户可以在移动设备上轻松打开、编辑文档。
Google Docs 最为人称道的功能在于它的模板。有了这些内置模板,用户可以迅速编辑出一份专业的文档。此外,通过邀请其他 Google 用户,还可以使用多人协作在线编辑功能。
Google Docs 最为人称道的功能在于它的模板。有了这些内置模板,用户可以迅速编辑出一份专业的文档。此外,通过邀请其他谷歌用户,还可以使用多人协作在线编辑功能。
如果你需要更多的功能,可以付费使用 Google Workspace。这是一套全面的整合方案你可以通过 Google Forms 收集信息,使用文档、表格、网站编辑工具 Google Sites、Google 日历等服务编辑信息,保存为文档。
如果你需要更多的功能,可以付费使用 Google Workspace。这是一套全面的整合方案你可以通过 Google Forms 收集信息,并集成到你的文档和表格中、网站编辑工具 Google Sites、Google 日历等服务,保存为文档。
* [主页][9]
* [帮助文档][10]
### OnlyOffice
![OnlyOffice][11]
[OnlyOffice][12]或 ONLYOFFICE是一套免费开源的办公软件,包括文本编辑器、表格工具、演示软件,提供共享文件实时协作编辑、修改痕迹记录查看以及制作可供填写的表格等高级功能。
[OnlyOffice][12]显示名字为 ONLYOFFICE是一套自由开源的办公软件,包括文本编辑器、表格工具、演示软件,提供共享文件实时协作编辑、修改痕迹记录查看以及制作可供填写的表格等高级功能。
外观上OnlyOffice 的功能区模仿了 Office 365 功能区的设计风格能让用户快速上手。此外OnlyOffice 对 Office 文件格式(.docx .xlsx 以及 .pptx的兼容性更好方便用户与他人共享文件。
[][13]
参阅:提升 GNOME 体验的 10 款宝藏软件。[系列一]
外观上OnlyOffice 的功能区模仿了微软 Office 365 功能区的设计风格能让用户快速上手。此外OnlyOffice 对微软 Office 文件格式(.docx .xlsx 以及 .pptx的兼容性更好方便用户与他人共享文件。
值得一提的是OnlyOffice 还推出了需要付费使用的企业版本 —— ONLYOFFICE Workspace。该版本增加了一些其他的高级功能提供即时支持服务非常适合那些预算紧张但对格式兼容性要求又很高的用户。
ONLYOFFICE Workspace 集成了邮箱客户端、客户关系管理产品、项目管理工具以及日历。总体来说ONLYOFFICE Workspace 是一款不错的软件,但也有一些不足拼写检查、打印预览、页面尺寸以及漏洞等问题。不过也不需要过分担心,你可以在 GitHub 上传错误报告,向开发团队寻求帮助。
ONLYOFFICE Workspace 集成了邮箱客户端、客户关系管理产品、项目管理工具以及日历。总体来说ONLYOFFICE Workspace 是一款不错的软件,但也有一些不足,如拼写检查、打印预览、页面尺寸以及漏洞等问题。不过也不需要过分担心,你可以在 GitHub 上传错误报告,向开发团队寻求帮助。
* [主页][12]
* [下载][14]
* [帮助文档][15]
### Softmaker Free Office
### Softmaker FreeOffice
![FreeOffice][16]
[FreeOffice][17] 由 SoftMaker 开发,是一套十分优秀的办公软件,包括 TextMaker (可替代 Word), PlanMaker (可替代 Excel), 以及 Presentations。FreeOffice 提供了两种用户界面带有功能区选项的现代化界面与带有菜单和工具栏的传统界面两种界面都十分受欢迎。此外FreeOffice 还为触控设备提供专有的用户界面与功能。
[FreeOffice][17] 由 SoftMaker 开发,是一套十分优秀的办公软件,包括 TextMaker(可替代 Word、PlanMaker可替代 Excel以及 Presentations可替代 PowerPoint。FreeOffice 提供了两种用户界面带有功能区选项的现代化界面与带有菜单和工具栏的传统界面两种界面都十分受欢迎。此外FreeOffice 还为触控设备提供专有的用户界面与功能。
FreeOffice 采用 Office 的文档格式,能够完美对接主流办公软件。不过相较之下,尽管 ODT 格式的应用并没有那么普遍,但它可以为用户免去许多麻烦
FreeOffice 对 微软 Office 文档格式的兼容性是很好的可以完成大部分工作。然而你在处理开放文档格式ODT文件时可能会遇到一点麻烦因为它的支持有限
FreeOffice 是一款闭源软件。
@ -99,13 +87,11 @@ FreeOffice 是一款闭源软件。
* [下载][18]
* [帮助文档][19]
### WPS Office
![WPS Office][20]
还记得 Kingston Office 吗? 它现在的名字叫做 WPS Office。WPS 取 **W**ord, **P**resentation 与 **S**preadsheets 的首字母组合而成。到今天WPS 办公软件已有 30 年的发展历史是老牌办公软件之一。WPS 作为办公软件,功能齐全,支持移动端在内的各类平台。
还记得金山办公软件吗? 它现在的名字叫做 WPS Office。WPS 取 **W**ord, **P**resentation 与 **S**preadsheets 的首字母组合而成。到今天WPS Office 已有 30 年的发展历史是老牌办公软件之一。WPS 作为办公软件,功能齐全,支持移动端在内的各类平台。
WPS 最具特色的功能在于支持实时协作编辑。使用 WPS团队成员可以同时编辑一份共享文档。WPS 还为用户提供了超过 10 万种文档模板,帮助用户编辑出专业美观的文档与演示文件。
@ -113,25 +99,23 @@ WPS 的标准版本可以免费下载使用,不过有一些高级功能需要
如果你需要额外的功能,比如编辑 PDF 文件、云空间扩容、团队协作以及企业支持,可以考虑付费开通会员,使用 WPS 企业版。
注意,这是一款闭源软件,而且可能会推送广告。该软件由中国金山软件公司开发。
注意,这是一款闭源软件,而且可能会推送广告。LCTT 译注:该公司内部人士表示,免费的 Linux 版没广告。)该软件由中国金山软件公司开发。
* [主页][21]
* [帮助文档][22]
* [下载][23]
### 对比表
下表基于功能以及其他细节,对上述 5 款办公软进行对比总结。
产品 | 价格 | 是否开源 | 优势 | 劣势
---|---|---|---|---
LibreOffice | 免费 | 开源 | 免费;跨平台;支持多种语言;完全支持 ODF 文件格式;对 Office 兼容性最好;开发活跃 | 不提供邮箱应用;不提供项目管理功能;数据库基于 Java
LibreOffice | 免费 | 开源 | 免费;跨平台;支持多种语言;完全支持 ODF 文件格式;对 微软 Office 兼容性最好;开发活跃 | 不提供邮箱应用;不提供项目管理功能;数据库基于 Java
Google Docs | 免费 | 闭源 | 免费;跨平台;良好的文档支持;随时随地存取云文档;完美支持移动端 | 需要网络连接;网络连接导致卡顿或延迟;不提供可供安装的版本
OnlyOffice | 免费 (basic product) | 开源 | 用户界面酷似 Office Office 文件拥有更好的兼容性;云集成;支持插件;跨平台 | 基本功能可能出现问题;云集成服务违反欧盟通用数据保护条例;网页端延迟
FreeOffice | 免费 (基础功能) | 闭源 | 免费;相较于 LibreOffice 更加轻量;支持触屏;良好的 Office 兼容性;跨平台 | 免费版本只包括文档、表格与演示功能;其他产品需要付费;对 ODT 文件格式的支持有限;闭源软件
WPS Office | 免费 | 闭源 | 良好的 Office 兼容性;跨平台;标签界面;支持多语言 | 闭源软件;中国软件公司开发;可能弹出广告
OnlyOffice | 免费(基础功能) | 开源 | 用户界面酷似微软 Office对微软 Office 文件拥有更好的兼容性;云集成;支持插件;跨平台 | 基本功能可能出现问题;云集成服务违反欧盟通用数据保护条例;网页端延迟
FreeOffice | 免费(基础功能)| 闭源 | 免费;相较于 LibreOffice 更加轻量;支持触屏;良好的微软 Office 兼容性;跨平台 | 免费版本只包括文档、表格与演示功能;其他产品需要付费;对 ODT 文件格式的支持有限;闭源软件
WPS Office | 免费 | 闭源 | 良好的微软 Office 兼容性;跨平台;标签界面;支持多语言 | 闭源软件;可能弹出广告
### 我们推荐
@ -139,22 +123,18 @@ WPS Office | 免费 | 闭源 | 良好的 Office 兼容性;跨平台;标签
### 总结
我希望,我们的推荐能帮助你选择适合自己的可替代 Office 的办公软件。 说实话,上述软件没有一个能真正比得上 Office。但是并不是每个人都能付得起 Office 高昂的费用,我相信以上 5 款软件对这部分人来说会是不错的选择。
我希望,我们的推荐能帮助你选择适合自己的可替代微软 Office 的办公软件。 说实话,上述软件没有一个能真正比得上微软 Office。但是并不是每个人都能付得起微软 Office 高昂的费用,我相信以上 5 款软件对这部分人来说会是不错的选择。
_一些图片来源上述软件所属公司_
* * *
我们分享最新技术新闻、软件资讯。欢迎关注我们的 [Telegram][24], [Twitter][25], [YouTube][26] 与 [Facebook][27],精彩不容错过。
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/best-alternatives-microsoft-office-2022/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/aREversez)
校对:[校对者ID](https://github.com/校对者ID)
译者:[aREversez](https://github.com/aREversez)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,61 @@
[#]: subject: "The C4C Linux Distro Rises from the Grave"
[#]: via: "https://news.itsfoss.com/c4c-linux-distro-revived/"
[#]: author: "John Paul https://news.itsfoss.com/author/john/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14377-1.html"
复活的 C4C Linux 发行版
======
> Computers4Christians 项目以定制发行版的形式进行了改革,该发行版为有基督教信仰的人提供了软件。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/c4c-disto-rises-from-the-grave.png?w=1200&ssl=1)
当我刚开始在这里写作时,我介绍了一个 [基督徒的 Linux 发行版][1],距离现在已经有 6 个年头了,让我们来速览一下这个项目在 6 年的时间里都有哪些变化吧。
### 名字变了,性质也变了
当我们第一次碰到 [Computers4Christians][2],他们是一个基督教团体,通过安装 Linux 系统来翻新旧电脑,并把它们捐赠给当地社区。他们大约捐赠了 1000 台翻新的旧电脑。该团体基于 Lubuntu 定制了自己的 Linux 版本,名字叫 “Computers4Christians Linux Project”。
今天Computers4Christians 已经不再捐赠翻新的旧电脑了。取而代之的是,这三个开发者正在专注于开发重命名的 [C4C Ubuntu][3]。
当我问他们为什么决定要继续开发这个发行版时,他们回答说:
> 我们希望引导那些不信奉上帝的人与耶稣·基督建立真正的联系,并借此发展一些信徒。任何人都可以,在几乎任何电脑上,下载、运行临场镜像或者安装我们的 Linux 发行版。C4C Ubuntu 用户可以通过多个版本的圣经、基督教教义、每日灵修、基督教视频和游戏等方式聆听上帝的教诲。我们祈祷每一次的下载、运行和安装 C4C Ubuntu 镜像,都能帮助用户走向基督,或是更接近上帝。“向软弱的人,我就作软弱的人,为要得软弱的人;向甚么样的人,我就作甚么样的人。无论如何总要救些人。” —— 哥林多前书 9:22网络
### C4C Ubuntu 中都有什么?
当前版本的 C4C Ubuntu 基于最新的 Ubuntu LTS20.04.4)构建。它使用 Xfce 桌面环境代替了 GNOME 桌面环境。我问他们为什么决定基于 Ubuntu 而不是 Lubuntu。开发者 Eric Bradshaw 告诉我说,他们之所以切换到 Ubuntu是因为 Lubuntu 的 LXQt 桌面环境有缺陷,而且它在旧电脑上表现不佳。
以下是 C4C Ubuntu 预装的内容:
* 主要的常用软件Catfish、FileZilla、GIMP、Gnash、GnuCash、Gufw、LibreOffice、OpenJDK Java 11、Pidgin、Pinta、Synaptic、Thunderbird 和 VLC。
* 与基督教或圣经相关的软件和媒体十二使徒问答和记忆游戏、圣经、圣经桌面版、8 个圣经知识游戏、10 个圣经经文迷宫探索游戏、Diatheke、117 个 Flash 圣经游戏、24 个有趣的圣经故事、Verse、Wide Margin、西福斯圣经指南、新信徒和门徒的阅读材料以及基督教视频。
* 圣经有声圣经WEB、AKJV、ASV、BBE、ERV、KJV、NHEB 和 WEB。注释MHC、NETnotesfree、Personal 和 TFG。每日灵修DBD 和 SME。词典MLStrong、Robinson、StrongsGreek 和 StrongsHebrew。通用书籍MollColossions 和 Pilgram。地图ABSMaps、eBibleTeacherMaps、EpiphanyMaps、HistMidEast、KretzmannMaps、NETMaps、SmithBibleAtlas 和 SonLightFreeMaps。
* 我们的背景图片包括 150 张不同的“<ruby>上帝的创造<rt>God's creation</rt></ruby>”,提供高清、标准和宽屏等尺寸大小。我们还提供快捷方式或启动器,你可以在“基督教”子菜单中找到它们,点击即可直达 37 个在线的基督教视频集、音乐视频集和 YouTube 频道。
* 预装的 Firefox 上有数百个手工挑选和分类的书签,不管你是要学习 Linux 还是要了解上帝,你都可以找到相关书签。有一个叫 “FoxFilter” 的家长控制扩展可以帮助过滤掉网页上不适当的内容,用户如果觉得有用,可以订阅它。
* C4C Ubuntu 团队引入了 [GNU Gnash 的 snap 包][4],它是一个 Flash 播放器。有了它,用户就可以玩预装的 Flash 圣经游戏了。
如果你想要尝试 C4C Ubuntu你可以在 [这里][5] 找到下载链接。这个网站有很多关于他们的历史版本信息。同时,开发团队也在不断更新这个网站。
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/c4c-linux-distro-revived/
作者:[John Paul][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/john/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/computers-christians-linux/
[2]: https://computers4christians.org/
[3]: https://computers4christians.org/C4C.html
[4]: https://snapcraft.io/gnash-raymii
[5]: https://computers4christians.org/Download.html

View File

@ -0,0 +1,110 @@
[#]: subject: "Gitter: A Cross-Platform Open Source Community Platform for Developers"
[#]: via: "https://itsfoss.com/gitter/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14397-1.html"
Gitter面向开发者的跨平台开源社区平台
======
![](https://img.linux.net.cn/data/attachment/album/202203/26/132222ldtjfcxvfz9kx5jv.jpg)
> 一个为开发者量身定做的跨平台开源解决方案。你可以建立或加入现有的社区来进行协作和互动。
几乎每个网络用户都知道 Slack、Rocket.Chat、Trello、[Nextcloud][1],以及其他一些用于工作沟通和协作的解决方案。
如果你喜欢用 FOSS 来进行团队协作,我们也有一个 [Slack 的开源替代品列表][2]。
但是,作为一个软件开发者,如果你偶然发现了一个开发者社区怎么办?
与 Reddit 或其他社交媒体上的社区不同,你可以进入一个开源平台,在那里,开发者们遇见并就重要的开源项目进行合作。这对于社交协作和同行之间的互动来说,不是很令人兴奋吗?
![][3]
[Gitter][10](现在是 [Element][4] 的一部分,也是一个协作/聊天应用)的目标就是这样。它是一个由开源技术驱动的社区平台([Matrix][5] 协议)。
### Gitter使用开源技术连接的开发者社区
Gitter 是一个令人兴奋的聊天和网络平台,有助于建立或加入现有社区。它可用于 Linux、macOS 和 Windows。
![][6]
它是专门为开发者定制的,可以为他们各自的语言/项目,如 CSS、JavaScript、Bootstrap、NodeJS 等,进行合作/加入社区。
你也可以轻松地创建你的社区,而无需设置任何邀请服务。
![][7]
该平台的关键亮点是,社区是完全开放的,可被搜索引擎索引。对于社区中的对话历史,你不会被任何定价计划所锁定,你所需要查看的是归档。
而且,你在 Gitter 获得的功能还有很多。
### Gitter 的功能
虽然 Gitter 最初是为开发者定制的,但如果你认为它的功能符合你的要求,你可以用它来建立任何类型的社区。
![][8]
* 由一个去中心化的 Matrix 网络支持。
* 可公开加入的社区。
* 能够将你的社区限制在选定的用户中。
* 深色模式主题。
* 访问归档,轻松找到过去的对话。
* 能够导出信息/房间信息。
* 从你的网络中添加用户(例如,如果你使用 Twitter 登录,你可以选择从 Twitter 邀请用户到你的社区)。
* 几个可用的集成GitHub、Bitbucket、Trello、GitLab、Docker Hub、Discourse 等)。
* 支持 GitHub 风格的 Markdown。
* 在同一社区下创建更多的房间,以保持事情的条理性。
* 轻松地分享/嵌入聊天室的链接。
* 帖子系统,以保持对话的整齐。
* 删除/报告信息的能力。
总之Gitter 提供了适合不同社区的各种功能。
而且,通过 GitHub、GitLab 和其他一些网站的集成,它成为开发者和团队的一个完美的合作选择。
![][9]
### 在 Linux 中安装 Gitter.im
开发人员主要专注于网络应用。因此,如果你想避免在你的 Linux 桌面上安装任何东西,请前往 [Gitter.im][10] 并注册/登录以开始使用。
如果你想让它成为一个桌面应用,你可以从其官方网站下载 DEB 包,或者可选择 [Snap 包][11]和 [Flatpak 包][12]。
我在简短的测试中尝试了 Flatpak 包,它在 Ubuntu 20.04 LTS 上运行良好。你可以在你喜欢的任何一个 Linux 发行版上尝试 Flatpak/Snap。
你也可以在你的移动设备上使用它。不幸的是,官方的 Gitter 移动应用已经不再维护。但是,你可以使用 Element 应用来登录房间/社区考虑到两者都是由同一个去中心化的网络即Matrix驱动的。
要了解更多信息,请浏览 [GitLab 页面][13]或前往其网站。
你试过 Gitter 吗?你对它有什么看法?它适合你这个开发者吗?你用它做什么?请在下面的评论中告诉我们你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/gitter/
作者:[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://itsfoss.com/nextcloud/
[2]: https://itsfoss.com/open-source-slack-alternative/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/gitter-dark-mode.png?resize=800%2C536&ssl=1
[4]: https://itsfoss.com/element/
[5]: https://matrix.org/
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/gitter-light-mode.png?resize=800%2C536&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/gitter-communities.png?resize=800%2C398&ssl=1
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/gitter-add-friends.png?resize=800%2C468&ssl=1
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/gitter-integrations.png?resize=800%2C597&ssl=1
[10]: https://gitter.im/
[11]: https://snapcraft.io/gitter-desktop
[12]: https://flathub.org/apps/details/im.gitter.Gitter
[13]: https://gitlab.com/gitterHQ/desktop

View File

@ -0,0 +1,83 @@
[#]: subject: "Ubuntu has a Weird Looking New Logo"
[#]: via: "https://news.itsfoss.com/ubuntu-new-logo/"
[#]: author: "Abhishek https://news.itsfoss.com/author/root/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14370-1.html"
Ubuntu 有了一个“怪怪的”新标志
======
> Ubuntu 已经重新设计了它的标志。不是每个人都会喜欢它。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/ubuntu-unveils-new-logo.png?w=1200&ssl=1)
Ubuntu 的标志包含了多个元素。对粉丝来说,橙色和紫色是 Ubuntu 的特征。
除此之外Ubuntu 的标志上还写有 “ubuntu” 的字样,以及一个橙色的图案。
![Ubuntus old logo][1]
这个橙色的“<ruby>朋友圈<rt>circle of friends</rt></ruby>”图案是 Ubuntu 的身份标识,它象征着:自由、协作、精确和可靠。
这个图案实际上是三个朋友或团队成员“搭在一起”的一个俯视图。你可能在体育运动中见到过这样的画面。
![Image courtesy: Unsplash][2]
### Ubuntu 有了一个全新的标志
但这个图案正在发生变化。[OMG! Ubuntu][3] 报道说Canonical 重新设计了标志的元素、文字和这个“朋友圈”的图案。
在旧的标志中,“朋友圈”图案在粗体 “ubuntu” 文字的右上角。
新的标志改变了这一点。“朋友圈”图案经过重新设计看起来更平滑而且被放置在一个橙色的矩形里。文字也有变化现在使用了更细的字体。“Ubuntu” 中的 “U” 现在是大写的了。
有趣的是,新标志不再包含注册商标符号 “®” 了。
![][4]
Ubuntu 在官方博文中提到了关于新设计的 [这些变化][5]
> 虽然(在设计上)和之前的朋友圈图案保持相对延续性很重要,但是更新后的版本更精简、更专注、更成熟。现在他们的头部在圆圈里,彼此面对,连接也更加直接,这看起来更合理一些。
你可以在这个视频中看到新标志的动画:
[![][6]](https://img.linux.net.cn/static/video/Ubuntu%20new%20logo%20animation-9DHUyz54flA.mp4)
这个新标志将会出现在 Ubuntu 22.04 发行版中。
### 这不是首次重新设计标志
这并不是 Ubuntu 第一次重新设计它的标志。早在 Ubuntu 项目于 2004 年初创时,“朋友圈”图案有三种颜色:黄色、红色和橙色。在 2010 年的时候,它被重新设计,“搭在一起的人” 变成了白色,他们被一个橙色的圆圈围绕着。
![Image courtesy: OMG! Ubuntu][7]
### 你喜欢这个新标志吗?
这次的新设计距离上一次已经过了 13 年。这个新“朋友圈”图案看起来还不错,但我还是觉得这个矩形背景有点怪怪的。
你怎么看?你喜欢 Ubuntu 的新标志吗,还是说更喜欢以前的那个呢?请在下方评论区分享你的观点吧!
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/ubuntu-new-logo/
作者:[Abhishek][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/root/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/ubuntu-old-logo.png?w=1294&ssl=1
[2]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/huddle.jpg?w=800&ssl=1
[3]: https://www.omgubuntu.co.uk/2022/03/ubuntu-has-a-brand-new-logo
[4]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/new-ubuntu-logo.png?w=780&ssl=1
[5]: https://ubuntu.com/blog/a-new-look-for-the-circle-of-friends
[6]: https://i0.wp.com/i.ytimg.com/vi/9DHUyz54flA/hqdefault.jpg?w=780&ssl=1
[6a]: https://youtu.be/9DHUyz54flA
[7]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/ubuntu-logo-comparison.jpg?w=1200&ssl=1

View File

@ -0,0 +1,153 @@
[#]: subject: "Customize GNOME Desktop in Ubuntu with a Clean Look"
[#]: via: "https://www.debugpoint.com/2022/03/customize-gnome-clean-look-2022-1/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14393-1.html"
在 Ubuntu 中定制简洁的 GNOME 桌面
======
> 本教程为你提供了一些简单的步骤来自定义 GNOME 桌面,用最少的努力打造干净的外观。下面如何做的。
![](https://img.linux.net.cn/data/attachment/album/202203/25/095452nw8pt6pxu9owwsks.jpg)
如果你对最喜欢的 GNOME 桌面的样子已经看厌烦了那么你就来对了。让我们安装一些主题图标并进行一些调整以提升你的桌面格调。我们将转换如下桌面GNOME 40.5 和 Ubuntu 21.10)。
![Ubuntu Desktop with GNOME Before Customization][1]
这个定制教程将使用漂亮的 Colloid GTK 主题、Mkos-Big-Sur 图标、一个带有额外扩展的酷炫光标主题,以及 Conky。
### 自定义 GNOME 桌面,用简洁的外观提升它的形象
#### 安装
首先,通过在终端运行以下命令来设置 GNOME Shell 扩展。
```
sudo apt install chrome-gnome-shell
```
然后 [打开这个页面][2],将 GNOME 扩展的插件添加到你的浏览器Chrome/Firefox
![Add Browser Add-on for GNOME Shell Extension][3]
安装“扩展”应用([Flatpak][4]),你可能需要它来改变 GNOME 扩展的设置。
之后,从终端使用以下命令安装 <ruby>GNOME 优化工具<rt>GNOME Tweaks</rt></ruby>。我们将使用这个工具来改变主题和其他设置。
```
sudo apt install gnome-tweaks
```
[下载 Colloid GTK 主题][5]。下载后解压文件。然后将解压后的文件夹复制到你主目录下的 `~/.themes`。如果文件夹不存在,请创建它。完成这些后,打开终端,运行 `install.sh` 文件。
[下载 Mkos-Big-Sur 图标主题][6]。下载完成后,解压文件并将父文件夹复制到你的主目录中的 `~/.icons`
[下载 Vimix 光标主题][7],并按照上述步骤操作。将提取的文件夹复制到 `~/.icons` 目录中。然后打开一个终端,运行 `install.sh` 文件。
现在,安装 Conky 和一些扩展,这些扩展最终会给你的 GNOME 桌面一个干净的外观。要安装 Conky 和 Conky 管理器,打开终端提示符并运行以下命令。
```
sudo apt install conky
sudo add-apt-repository ppa:tomtomtom/conky-manager
sudo apt update && sudo apt install conky-manager2
```
现在,打开下面每个扩展的链接,依次安装它们。要安装时,打开页面,点击 ON/OFF 切换开关(见下图)。它将要求你提供管理员密码和安装许可。
* [Move Clock][8]
* [Dash to Dock][9]
* [Tray Icons][10]
* [Arc Menu][11]
* [User Themes][12]
![GNOME Extension Page][13]
#### 配置
在你完成上述步骤后,做一些基本配置。你可能会看到在你安装上面的 GNOME 扩展时,有些变化已经生效了。例如,在安装上面的 Move Clock 扩展时,时钟应该已经被移到了右边。
##### 优化工具
打开<ruby>优化<rt>GNOME Tweaks</rt></ruby>工具从应用菜单中搜索“Tweaks”进入“<ruby>外观<rt>Apperance</rt></ruby>”。
将应用主题改为 “Colloid Dark”光标主题为 “Vimix Cursors”图标主题为 “Mkos-big-sur”Shell 主题为 “Colloid Dark”。如果你愿意你可以选择浅色主题和不同的选项。
![Apply Themes][15]
##### Arc 菜单
打开“<ruby>扩展<rt>Extension</rt></ruby>”应用,进入 <ruby>Arc 菜单设置<rt>Arc Menu Settings</rt></ruby>
将菜单布局改为 “<ruby>替代菜单布局<rt>Alternative Menu Layout</rt></ruby> > Raven”。
将应用的菜单按钮改成你喜欢的一些图标。在本指南中,我从 [这里][16] 下载了一个 GNOME 图标。并通过 Arc 菜单的 “<ruby>设置<rt>Settings</rt></ruby> > <ruby>按钮外观<rt>Button Appearance</rt></ruby> > <ruby>浏览图标<rt>Browse Icon</rt></ruby>”应用它。它应该看起来像这样。
![Arc Menu Raven][17]
从“<ruby>扩展<rt>Extension</rt></ruby>”程序中打开 “Dash to Dock” 设置。在“<ruby>外观<rt>Appearance</rt></ruby>”选项卡中,改变以下项目:
* 启用收缩到 Dash 的功能
* 自定义窗口计数指示器为 Dash
* 启用自定义 Dash 颜色
* 自定义不透明度为固定
* 不透明度为 12%
在位置和大小选项卡中,将停靠区位置改为底部,图标大小限制为 39px。
如果你喜欢,你可以启动 Conky并下载一张与 Colloid 主题相配的漂亮墙纸。在这个演示中,我[选择了一张漂亮的灰色墙纸][18],它与深色主题搭配看起来非常漂亮。
### 结果
在所有的配置之后,如果一切顺利,你的桌面应该是这样的。
![GNOME Customization in Ubuntu with a simple look-1][19]
![GNOME Customization in Ubuntu with a simple look-2][20]
![GNOME Customization in Ubuntu with a simple look-3][21]
你可以通过多种设置组合来玩转这个主题的不同变体。并创造一个更适合你的外观。
我希望这个指南能帮助你把你的 GNOME 桌面改造成简洁的外观。如果你喜欢这个设置,请在下面的评论中告诉我。
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/customize-gnome-clean-look-2022-1/
作者:[Arindam][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.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/03/Ubuntu-Desktop-with-GNOME-Before-Customization-1024x582.jpg
[2]: https://extensions.gnome.org/
[3]: https://www.debugpoint.com/wp-content/uploads/2022/03/Add-Browser-Add-on-for-GNOME-Shell-Extension.jpg
[4]: https://dl.flathub.org/repo/appstream/org.gnome.Extensions.flatpakref
[5]: https://github.com/vinceliuice/Colloid-gtk-theme/archive/refs/heads/main.zip
[6]: https://github.com/zayronxio/Mkos-Big-Sur/archive/refs/heads/master.zip
[7]: https://github.com/vinceliuice/Vimix-cursors
[8]: https://extensions.gnome.org/extension/2/move-clock/
[9]: https://extensions.gnome.org/extension/307/dash-to-dock/
[10]: https://extensions.gnome.org/extension/2890/tray-icons-reloaded/
[11]: https://extensions.gnome.org/extension/3628/arcmenu/
[12]: https://extensions.gnome.org/extension/19/user-themes/
[13]: https://www.debugpoint.com/wp-content/uploads/2018/05/GNOME-Extension-Page.png
[15]: https://www.debugpoint.com/wp-content/uploads/2022/03/Apply-Themes.jpg
[16]: https://icons.iconarchive.com/icons/tatice/operating-systems/32/Gnome-icon.png
[17]: https://www.debugpoint.com/wp-content/uploads/2022/03/Arch-Menu-Raven.jpg
[18]: https://i.redd.it/1ttvv79apo851.png
[19]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-Customization-in-Ubuntu-with-a-simple-look-1-1024x579.jpg
[20]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-Customization-in-Ubuntu-with-a-simple-look-2-1024x580.jpg
[21]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-Customization-in-Ubuntu-with-a-simple-look-3-1024x576.jpg
[22]: https://t.me/debugpoint
[23]: https://twitter.com/DebugPoint
[24]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[25]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,134 @@
[#]: subject: "Linux Kernel 5.17 Released. This is Whats New"
[#]: via: "https://www.debugpoint.com/2022/03/linux-kernel-5-17/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "wxy"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14384-1.html"
Linux 内核 5.17 发布及新变化
======
> Linux 内核 5.17 已经发布,它具有更好的硬件支持和核心模块改进。下面是对新功能的简要介绍,并附有下载和安装细节。
![Linux 内核 5.17 带来了更多的硬件兼容性][1]
Linux Torvalds [宣发了][2] Linux 内核 5.17,这是 2022 年第二个稳定版主线内核。这个版本的内核模块中引入了对新处理器、显卡、存储和其他硬件组件的支持。
比内核 5.16 发布后的时间表稍有延迟Linux 主线内核 5.17 现在可供下载了。这些更新包括对 AMD Zen 系列设备的温度支持;长期存在的软盘挂起错误,几个 ARM/SoC 支持以及各个子系统的性能改进。
我们已经在第一个候选版本发布时介绍了大部分变化,下面是对 Linux 内核 5.17 新特性的快速回顾。
### Linux 内核 5.17 的新内容
#### 处理器
Linux 内核中的 ARM64 架构现在包括了<ruby>内核并发净化器<rt>Kernel Concurrency Sanitizer</rt></ruby>KCSAN。KSCAN 是一个竞争条件检测器,已经支持了其他架构。而现在 ARM64 也在支持名单上了。另外,<ruby>可扩展矩阵扩展<rt>Scalable Matrix Extensions</rt></ruby>SME的初始工作有望为矩阵操作提供更好、更快的支持。
AMD [带来了][3] 基于 k10temp 的 CPU 温度监控,用于 AMD Zen 系列第 19 代 CPU 型号。
一组广泛的 Arm/SoC 支持 [进入了][4] Linux 内核 5.17 中。其中主要包括新的 Snapdragon 8 Gen 1 和 X65 平台。其他 SoC 包括恩智浦 i.MX8ULP、德州仪器 J721S2 和瑞萨 R-Car S4-8。
CPU 的重大变化之一是加入了 AMD 的 P-state 驱动,这是与 Valve 为 Steam Deck 合作开发的。这将提供更好的电源效率,因为透过 ACPI <ruby>协作处理器性能控制<rt>Collaborative Processor Performance Controls</rt></ruby>CPPC支持可以更加细化的控制电源。
这个内核中另一个重要的 RISC-V 变化是支持 sv48提供了 48 位虚拟地址空间。这使得内核可以对高达 128TB 的虚拟地址空间进行寻址。
这个版本带来了很多笔记本电脑、平板电脑的驱动更新。[这里][5] 有一个列表,主要内容是:
- 为华硕 ROG 笔记本电脑增加了自定义风扇曲线支持。
- 增加了对<ruby>通用手写笔计划<rt>Universal Stylus Initiative</rt></ruby>USI和 NVIDIA Tegra 平板电脑的支持。
- 对基于 AMD 的笔记本电脑的一些性能改进和修复,涉及到睡眠和声音驱动。
#### 显卡
英特尔的 Alder Lake P 显卡经过前一年的多次迭代,现在已经在主线内核上稳定了。这个内核引入了 [对 Raptor Lake S 显卡的首批支持补丁][6]。
英特尔的 Gen Icelake 显卡家族 [获得了][7] 可变刷新率/自适应同步支持。
一些较新的笔记本电脑带来了内置的隐私屏幕,预计更多的 OEM 厂商会效仿。另外值得注意的是GNOME 桌面和其他公司正计划在之后使用这一隐私功能。所以,为了这个以隐私为中心的功能,最初的架构和代码工作都已经包含在这个内核版本中了。
你可以在 [这里][9] 找到一个很好的显卡驱动更新列表。
#### 存储
在内核的每个版本中都会对所有主要的文件系统和存储技术进行增量更新。这个版本也会有一些:
* 主要的更新包括流行的 EXT4 文件系统使用新的 Linux 挂载 API。
* 像往常一样,[F2FS][10]、[Btrfs][11] 和 [XFS][12] 的性能得到改善。
* FS-Cache 和 CacheFiles 模块 [做了][13] 重大重写。
#### 杂项硬件更新
今天谁还在使用软盘?我相信仍然有一些特定的商业用例仍在使用软盘。所以,这就给我们带来了这个特定的补丁,在这个内核版本中。内核中存在一个长期的错误:当系统试图读取一个坏掉的软盘时可能会挂起。所以,这个老毛病终于在这个版本中得到了解决,我希望能让少数仍然使用这种古老存储介质的人为此驻足一下。
其他值得注意的杂项硬件更新包括:
* 任天堂 GameCube/Wii/Wii U 实时时钟 [驱动][14]。
* 一个通用的 USB GNSS<ruby>全球导航卫星系统<rt>Global Navigation Satellite System</rt></ruby>)驱动程序。
* Cirrus CS35L41 高清音频编解码器 [驱动][15]。
* 许多英特尔 Wi-Fi 驱动程序 [改进][16]。
* 英特尔 Alder Lake N [音频][17] 支持。
### 如何下载和安装 Linux 内核 5.17
我们总是建议不要在你的稳定系统中安装最新的主线内核,除非你拥有特定的新硬件或想做实验。对于普通用户来说,最好是通过你的 Linux 发行版(如 Ubuntu、Fedora的官方部署渠道等待内核的更新。
如果你仍然想安装,请按照下面的说明来安装 Linux 内核 5.17。
访问 [主线内核页面][18]。
有两种类型的构建可供选择:**通用**的和**低延迟**的。对于标准的系统,你可以下载通用的构建,大部分时间都可以工作。对于音频录制和其他需要低延迟的设置,请下载低延迟的。
通过终端下载以下四个通用软件包并安装:
```
wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17/amd64/linux-headers-5.17.0-051700-generic_5.17.0-051700.202203202130_amd64.deb
wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17/amd64/linux-headers-5.17.0-051700_5.17.0-051700.202203202130_all.deb
wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17/amd64/linux-image-unsigned-5.17.0-051700-generic_5.17.0-051700.202203202130_amd64.deb
wget -c https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17/amd64/linux-modules-5.17.0-051700-generic_5.17.0-051700.202203202130_amd64.deb
```
安装完毕后,重新启动系统。
低延迟和其他架构ARM的安装指令是一样的。替换上述 `wget` 命令中的软件包名称。你可以在主线内核页面找到它们。
对于 Arch Linux 用户来说,预计 Linux 内核 5.17 发布包将在 2022 年 4 月第一周的 Arch .iso 月度刷新中到达。
随着这个版本的发布,合并窗口将为接下来 Linux 内核 5.18 打开。
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/linux-kernel-5-17/
作者:[Arindam][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.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/03/kernel517-1024x576.png
[2]: https://lkml.org/lkml/2022/3/20/213
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git/commit/?h=hwmon-next&id=6482dd78c00c6d604ac1c757fb2d8a2be2878654
[4]: https://lore.kernel.org/linux-arm-kernel/CAK8P3a0RDZpLtWjMEU1QVWSjOoqRAH6QxQ+ZQnJc8LwaV7m+JQ@mail.gmail.com/
[5]: https://lore.kernel.org/lkml/aea4c26b-25a1-9480-f780-7eb3502a4ce4@redhat.com/T/#u
[6]: https://lore.kernel.org/dri-devel/87ee6f5h9u.fsf@intel.com/
[7]: https://lists.freedesktop.org/archives/intel-gfx/2021-November/284109.html
[8]: https://www.debugpoint.com/2022/01/linux-kernel-5-17-rc1/
[9]: https://lists.freedesktop.org/archives/dri-devel/2022-January/336492.html
[10]: https://lore.kernel.org/lkml/YedlHVEa4sdbvB2F@google.com/
[11]: https://lore.kernel.org/lkml/cover.1641841093.git.dsterba@suse.com/
[12]: https://lore.kernel.org/lkml/YdyxjTFaLWif6BCM@mit.edu/
[13]: https://lore.kernel.org/lkml/510611.1641942444@warthog.procyon.org.uk/
[14]: https://lore.kernel.org/lkml/Yen7oaDXAbd4tFOD@piout.net/
[15]: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git/commit/?h=for-next&id=7b2f3eb492dac7665c75df067e4d8e4869589f4a
[16]: https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=bc11517bc8219314948780570ec92814d14d6602
[17]: https://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git/commit/?h=for-next&id=4d5a628d96532607b2e01e507f951ab19a33fc12
[18]: https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.17
[19]: https://t.me/debugpoint
[20]: https://twitter.com/DebugPoint
[21]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[22]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,73 @@
[#]: subject: "Clear Linux is the First Distro to Offer GNOME 42"
[#]: via: "https://news.itsfoss.com/clear-linux-gnome-42/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14400-1.html"
Clear Linux 是首个提供 GNOME 42 的发行版
======
> 击败了 Arch 和 FedoraClear Linux 的最新版本提供了 GNOME 42 的稳定版本。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/clear-linux-gnome-42.jpg?w=1200&ssl=1)
Clear Linux 是一个开源的滚动发布的发行版,它为云计算和边缘计算的开发者量身定制。
你可能不知道Clear Linux 是一个<ruby>英特尔<rt>Intel</rt></ruby>的项目。它针对英特尔的处理器做了优化,并且提供了一个容器快速部署的环境。
它同时支持了桌面和服务器AWS、Google Compute Engine 和 Azure Hyper-V 等)。
> **注意:** _与即将发布的 Fedora 36 工作站版和 Ubuntu 22.04 长期支持版相比Clear Linux 算不上是一个完美的替代桌面。如果你对这个发行版感兴趣我建议你先在虚拟机上尝试一下。_
令人惊讶的是Clear Linux 的最新发布版看起来会包括 GNOME 42稳定版
更不用提Clear Linux 比 Arch 和 Fedora 更新地还要快,提供了最新的 GNOME 稳定发布版。
### Clear Linux 上的 GNOME 42
![][1]
你可以期待在 Clear Linux 上看到 [最好的 GNOME 42 特性][2]。
根据我的简单使用,其中大部分功能都符合你对 GNOME 42 的预期。
![][3]
文件管理器、日历、照片、天气以及许多其他应用程序都反映出,最新的 GNOME 42 版本升级到了 GTK 4。
当然,在 Clear Linux 上,默认的桌面壁纸会有些不同,但你可以获取到同一套壁纸集的浅色/深色不同版本。
![][4]
我在虚拟机上测试过,它的运行情况和预期的一致,没有显著的缺陷。
如果你已经在使用 Clear Linux 了,或者对它好奇,想要了解更多,你可以在它的 [版本发布说明][5] 中找到更多细节,包括更新的软件包和其他变化。
### 下载附带 GNOME 42 的 Clear Linux
或许你在它的官网下载页面找不到最新的发布版。但是,你可以在 [官方下载仓库][6] 中找到它。
你可以根据自身需求(服务器/桌面),下载到对应的 ISO 文件。现在就开始体验吧!
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/clear-linux-gnome-42/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/clearlinux-gnome-42-home.jpg?w=1269&ssl=1
[2]: https://news.itsfoss.com/gnome-42-features/
[3]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/clearlinux-gnome-42.png?w=868&ssl=1
[4]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/clear-linux-appearance.jpg?w=794&ssl=1
[5]: https://download.clearlinux.org/releases/36060/clear/RELEASENOTES-36030-to-36060
[6]: https://download.clearlinux.org/releases/36060/clear/

View File

@ -0,0 +1,109 @@
[#]: subject: "Xonsh Shell Combines the Best of Bash Shell and Python in Linux Terminal"
[#]: via: "https://itsfoss.com/xonsh-shell/"
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14390-1.html"
Xnosh Shell在 Linux 终端结合 Bash Shell 和 Python 的最佳特性
======
![](https://img.linux.net.cn/data/attachment/album/202203/24/111824ufw1815lyvclnsr2.jpg)
最受欢迎的 shell 是什么?我猜你会回答 bash 或者 zsh没错的确如此。
UNIX 和 Linux 系统上有许多可用的 shell包括 Bash、Ksh、Zsh、Fish 等等。
最近,我碰到了另外一个 shell它结合了 Python 和 bash还蛮特别的。
### Xonsh shell为喜爱 Python 的 Linux 用户而打造
[Xonsh][1] 是一个使用 Python 编写的跨平台 shell 语言和命令提示符。
它结合了 Python 和 Bash shell因此你可以在这个 shell 中直接运行 Python 命令(语句)。你甚至可以把 Python 命令和 shell 命令混合起来使用。
![][2]
听起来不错吧?如果你是一个 Python 程序员的话,你应该会更加兴奋。
### 在 Linux 上安装 Xonsh shell
有多种方式可以在 Linux 系统上安装 Xonsh shell。
你可以使用软件包管理器安装它(主要的 Linux 发行版的仓库中都有 Xonsh shell
在 Ubuntu 和 Debian 上,你可以尝试运行:
```
sudo apt install xonsh
```
因为它本质上是一个 Python 应用,所以你总是可以使用 Pip 来安装(如果你的系统已经安装了的话)。或者,你也可以使用 Conda 来安装 Xonsh。同时它还提供了 AppImage 格式和 Docker 镜像。
你可以自由选择你喜欢的安装方式。
### Xonsh shell 初体验
如果你不熟悉 Linux 的“多 shell”概念和终端的相关知识我推荐你阅读 [我写的一篇终端入门的文章][3]。这篇文章会帮助 Linux 新手弄清楚很多东西。
我在这里简单介绍一下。你的终端运行着一个默认的 shell通常是 bash shell。如果你在系统上安装了其他的 shell你可以 [轻松地切换这些 shell][4]。
要进入 Xonsh shell只需运行一条命令
```
xonsh
```
![][5]
它会建议你运行一个设置向导,然后创建一个 Xonsh shell 的自定义 `rc` 配置文件。这是可选的,你也可以晚些时候再做。
一旦你开始使用它,你就立刻会感觉到一些不同。
当你开始输入一条命令时Xonsh 会自动建议历史记录中的最后一条匹配命令。你可以按下右箭头键确认使用这条自动建议的命令。你也可以按下上、下箭头键来选择历史记录中的其他匹配命令。
![Xonsh shell automatically suggests last matching command from the history as you type][6]
不仅如此,它还支持交互式的 Tab 补全。当你开始输入命令,并按下 `tab` 键,它会显示一个类似于下拉式的交互式菜单。你可以在这个菜单中选择可用的命令。
![Tab completion in Xonsh shell][7]
你可以混合使用 Python 和 bash 命令,并且直接在 shell 中运行它们。
如果你对 [终端定制][8] 感兴趣,你可以花点时间和精力,根据自己的喜好来定制 Tab 补全、按键绑定和颜色样式。
它同时拥有一个叫做 [Xontrib][9] 的用户自定义插件系统,你可以使用这些插件来扩展 Xonsh shell 的功能。
如果你是一个终端爱好者,并渴望学习更多终端知识,你可以浏览它的 [丰富的文档系统][10]。
### 最后
大多数用户坚持使用默认的 Bash shell这很正常。有一些开发者和系统管理员会选择使用 Zsh因为它有很多附加特性。而 Xonsh 完全聚焦在 Python 上,对于 Python 使用者来说它或许具有吸引力。对于其余的人来说Bash 已经足够好了。
你使用过 Xonsh 或者其他的 shell 吗?你用它来代替 Bash 的原因是什么呢?欢迎在评论区留言。
--------------------------------------------------------------------------------
via: https://itsfoss.com/xonsh-shell/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[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://xon.sh/
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xonsh-shell-combines-python-bash.png?resize=800%2C470&ssl=1
[3]: https://itsfoss.com/basic-terminal-tips-ubuntu/
[4]: https://linuxhandbook.com/change-shell-linux/
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xonsh-shell.png?resize=800%2C451&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/auto-suggestions-from-history-in-xonsh-shell.png?resize=800%2C258&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/tab-completion-xonsh-shell.png?resize=800%2C354&ssl=1
[8]: https://itsfoss.com/customize-linux-terminal/
[9]: https://github.com/topics/xontrib
[10]: https://xon.sh/tutorial.html

View File

@ -0,0 +1,120 @@
[#]: subject: "GNOME 42 is Here With Dark Mode, New Screenshot UI, and More Exciting Features"
[#]: via: "https://news.itsfoss.com/gnome-42-release/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14392-1.html"
GNOME 42 发布:深色模式、新的截图界面
======
> GNOME 42 终于到来了,它带来了急需的视觉升级和功能改进。
![](https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/gnome-42.jpg?w=1200&ssl=1)
[GNOME 42][17] 是一个有着显著视觉变化的重大升级。
GNOME 42 提供了许多必要的改进和急需的升级。现在它已经发布了,就让我们来看看一些关键的亮点吧。
### GNOME 42 新特性
鉴于我们已经写了一篇 [详细的文章来介绍 GNOME 42 的新特性][1],请允许我在这里挑选其中最重要的几个来介绍。
[![][2]](https://youtu.be/du-2QpWbiLU)
### 1. 深色模式主题和外观调整
![][3]
尽管其他的一些桌面环境已经有了系统级的深色样式偏好设置,然而 GNOME 此前并不支持该功能。
在 GNOME 42 中GNOME 团队从 elementary OS 团队那里获得了灵感(这要归功于 [elementary OS 6][4] 出色的深色模式)。
你可以注意到,一个新的“<ruby>外观<rt>Appearance</rt></ruby>”选项取代了“<ruby>背景<rt>Background</rt></ruby>”选项,它可以让你在浅色/深色模式间无缝切换。
![][5]
桌面壁纸也有浅色/深色的不同版本,以便在你选择的对应模式时,为你提供最佳的对比度。
### 2. 更新的文件夹图标主题
GNOME 的文件夹图标主题看起来也太古老了。为了摆脱这种印象,它接收了一些视觉更新,以便在浅色/深色主题下看起来更棒:
![][6]
### 3. 新的截图界面
新的 GNOME 42 截图的界面是本次发布的最好的特性之一。
它不仅仅局限于截图,只要简单切换一下,你就可以用它来录制屏幕。它的用户界面看起来很棒,而且在我最初使用的 Fedora 36预发布版中工作良好。
![][7]
### 4. GNOME 应用升级到了 GTK 4
为了与 GNOME 42 的总体用户体验保持一致,得益于 [libadwaita][8],默认应用程序获得了彻底的视觉更新。
不仅限于用户界面,一些 GNOME 应用本身也获得了新特性。
甚至一些第三方的 GNOME 应用,比如 [Fragments 2.0][9],也有了重大改变,以便在 GNOME 42 中提供最佳体验。
### 5. 新的文本编辑器和控制台
![][10]
你会注意到,[现代的 GNOME 文本编辑器][11] 取代了广受欢迎的 Gedit成为了默认的文本编辑器。
并且,你再也找不到 GNOME 终端应用了。取而代之的是,现在有了一个新的终端应用,它提供了一些用户界面的增强,名字叫做“<ruby>控制台<rt>Console</rt></ruby>”。
![][12]
### 其他改进
除了视觉变化,新版本的 GNOME 还进行了性能优化和整个平台的细微改进。其中包括了以下升级:
* 提升了文件检索效率
* 远程桌面功能现在支持 RDP 协议了
* GNOME 网页浏览器现在开启了硬件加速
你可以在 [官方声明][13] 中了解这个版本的所有变化。
### 下载 GNOME 42
你可以在 [GNOME OS][14] 上,通过 Boxes 虚拟机来测试 GNOME 42 最新的稳定构建版本,或者你可以下载 [OpenSUSE Tumbleweed][15](应该会在近期发布)。
尽管 [Intel 的 Clear Linux 似乎在它的最新版本中增加了 GNOME 42][16],但和 Ubuntu 22.04 长期支持版和 Fefora 36 相比,它并不是一个完美的替代桌面。
你也可以尝试附带 GNOME 42 的 Arch或者等待下个月将发布的 Ubuntu 22.04 长期支持版和 Fedora 36.
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/gnome-42-release/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-14267-1.html
[2]: https://i0.wp.com/i.ytimg.com/vi/du-2QpWbiLU/hqdefault.jpg?w=780&ssl=1
[3]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/fedora-36-gnome-42-dark.jpg?resize=1568%2C882&ssl=1
[4]: https://news.itsfoss.com/elementary-os-6-features/
[5]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/gnome-42-dark-mode-wallpaper.jpg?w=1200&ssl=1
[6]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/gnome-42-file-manager-light.jpg?resize=1568%2C1017&ssl=1
[7]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/gnome-42-screenshot.jpg?w=1340&ssl=1
[8]: https://news.itsfoss.com/gnome-libadwaita-library/
[9]: https://news.itsfoss.com/fragments-2-0-release/
[10]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/02/gnome-42-text-editor-alpha.jpg?w=1480&ssl=1
[11]: https://linux.cn/article-14060-1.html
[12]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/console-screenshot-1.png?w=694&ssl=1
[13]: https://release.gnome.org/42/
[14]: https://itsfoss.com/gnome-os/
[15]: https://get.opensuse.org/tumbleweed
[16]: https://news.itsfoss.com/clear-linux-gnome-42/
[17]: https://os.gnome.org/

View File

@ -1,103 +0,0 @@
[#]: subject: "Rocket.Chat and Nextcloud Team up to Offer a Powerful Open-Source Alternative to Office 365, Slack, and Others"
[#]: via: "https://news.itsfoss.com/rocket-chat-nextcloud-collaboration/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Rocket.Chat and Nextcloud Team up to Offer a Powerful Open-Source Alternative to Office 365, Slack, and Others
======
**Warning**: Trying to access array offset on value of type null in **/srv/users/itsfoss/apps/newitsfoss/public/wp-includes/class-wp-block-supports.php** on line **94**
**Warning**: Trying to access array offset on value of type null in **/srv/users/itsfoss/apps/newitsfoss/public/wp-includes/class-wp-block-supports.php** on line **96**
Rocket.Chat is one of the [best open-source slack alternatives][1] and Nextcloud is an all-in-one collaboration platform.
And, they are pretty impressive.
This is why we use [Rocket.Chat][2] for our internal communication and [Nextcloud][3] to manage tasks/documents. Both of them are incredibly useful for what they are capable of.
And, now, it looks like Rocket.Chat and Nextcloud are taking things up a notch by developing a native API integration.
But, what would it do? Let us find out.
### Partnering to Provide a More Powerful Open-Source Platform
![][4]
The primary objective of joining forces is to integrate their existing technologies, offering the best of both worlds.
As far as I am aware, we do not have a full-fledged open-source alternative to Microsoft 365.
Of course, you can combine various open-source technologies and choose to use them as a replacement for Microsoft 365.
But do we want an open-source solution that can replace Microsoft 365 minus the hassles?
**Yes.**
Thats what makes Rocket.Chats collaboration with Nextcloud exciting.
Nextclouds CEO shared his thoughts on this collaboration in the [press release][5]:
> _In a post-pandemic world, solutions like Office 365, Dropbox, and Slack will become more popular. This means that all of our data, communication, and digital lives will be in the hands of some big corporations without control, privacy and with this huge vendor lock-in_
**Frank Karlitschek, Founder and CEO at Nextcloud GmbH**
To add to his thoughts, Rocket.Chats CEO also mentioned the following:
> _This new interaction between Nextcloud and Rocket.Chat puts us one step closer to building the ultimate open-source alternative to MS 365, giving back privacy and data sovereignty to the users._
_Gabriel Engel, Founder, and CEO at Rocket.Chat_
So, we should expect a powerful open-source platform tailored for privacy and security-focused users, with both interesting platforms collaborating.
### New Features for Nextcloud Users
With the integration, Nextcloud customers will be able to access Rocket.Chats features to improve the effectiveness of communication and collaboration.
Some of the new features include:
* Expand collaboration capabilities using Rocket.Chats federation and bridges into Slack and Microsoft Teams.
* Easily collaborate on projects and documents using Rocket.Chats chat right in Nextcloud.
* Use a single productivity platform that integrates with other tools including Nexcloud and keeps all communications and notifications in one place.
* Leverage more advanced user governance features, access levels, and role-based permissions.
* Easily map even the most complex organizational structure into groups, teams, and discussions.
* Securely collaborate and communicate with anyone via the worlds leading social media channels such as Whatsapp, Messenger, Twitter, Instagram, Telegram, and others.
* Turn their chats into productivity tools using integrations with various HR tools, CRM solutions, ticketing systems, project management solutions, and developer tools to build powerful workflows.
* Get access to more services using [Rocket.Chats marketplace of apps][6]
* Ensure full governance of all their communications using message audits, flexible retention policies, powerful engagement analytics and dashboards, and more
* Send advanced message formatting like code snippets, formula syntax, message threads, and more
The Rocket.Chat app is now available in the [Nextcloud marketplace][7]. However, it is still a work in progress, and not ready for production yet.
You should be able to use the new features once the development completes soon enough (mostly, next month). As of now, we do not have any information on any new features being added to Rocket.Chat. Hopefully, there will be something on that with the final release.
_What are your expectations from this partnership? Do you think Rocket.Chats integration with Nextcloud can be an attractive replacement to Office 365, Slack, and Dropbox combined?_
Let me know what you think in the comments down below.
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/rocket-chat-nextcloud-collaboration/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/open-source-slack-alternative/
[2]: https://itsfoss.com/rocket-chat/
[3]: https://itsfoss.com/nextcloud/
[4]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ1MiIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[5]: https://rocket.chat/press-releases/rocket-chat-and-nextcloud
[6]: https://rocket.chat/marketplace
[7]: https://apps.nextcloud.com/apps/rocketchat_nextcloud

View File

@ -1,89 +0,0 @@
[#]: subject: "Epic Games Store Now Works on Steam Deck"
[#]: via: "https://news.itsfoss.com/epic-games-steam-deck/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Epic Games Store Now Works on Steam Deck
======
Steam Deck is already making waves to enhance the game support for the Linux platform.
It runs on **Steam OS 3.0** (based on Arch) and features KDE Plasma. Kudos to Valve for not locking down the platform and letting users experiment with it.
While it is not available for everyone, it is an exciting piece of hardware challenging handheld Nintendo Switch.
It may not support all the popular titles yet (like Destiny 2, Fortnite), but it is making good progress with several AAA and indie titles. You can head to the official page of [Deck Verified][1] to check the latest information about supported games.
Now, to make things more exciting, it turns out that Steam Deck can also run games using the [Epic Games Store][2] (**unofficially**). But, how? Lets find out.
### Using the Epic Games Store with Heroic Games Launcher
Yes, its the same [Heroic Games launcher][3] that was in the making [last year][4], and it is already known to work on a Linux desktop.
And, thanks to Liam Dawe (via [GamingOnLinux][5]), for successfully testing the Heroic Games Launcher (and [Heroic Bash Launcher][6]) on Steam Deck while coordinating with the respective developers.
![][7]
If youre curious: **Heroic Bash Launcher** _is a tool that creates launch scripts (.sh files) for all installed Heroic games and allows you to launch the game directly from the terminal or game frontend/launcher without having any need to open Heroic._
Heres how it all went down (as per my brief chat with the developer of Heroic Bash Launcher):
Initially, with Epic Games Store experiment on Steam Deck, the Steam controller did not work, considering the Epic Games Store ran as a “Non-Steam game” using the Steam client.
So, the developer of Heroic Bash Launcher, [Rishabh Moharir][8] (also a fellow writer here) suggested using his tool to make it work by following his [wiki guide on GitHub][9].
The Heroic Bash Launcher works with Epic Games Store on a Linux desktop. So, it was worth a try!
And, fortunately, it worked!
### Installing Epic Games Store on Steam Deck
First, you need to install the **Heroic Games Launcher** on Steam Deck using the available AppImage file in the **Desktop mode**.
Once done, you need to log in and download the game of your choice.
Next, you need to download the latest binary files for [legendary][10] and set it as the alternative legendary binary from the launchers settings.
You need to configure and set the compatibility layer to Proton 7.0 from the game settings in the launcher.
Thats when you need to download the latest [Heroic Bash Launcher binary][11] and run it.
Finally, you have to add the game to Steam (to find it in Steam Decks UI) following the [official wiki guide on GitHub][9].
Overall, it sure took a while for tinkerers to make it work. And, if you are still confused, you can find the same set of steps with all the details in the [wiki][12] put together by the Heroic Games Launcher team (or refer to the video above).
To me, it sounds doable and should not be an overwhelming process for most Steam Deck users as of now. Unfortunately, I cant get my hands on the Steam Deck in India (yet).
As for the future of Epic Games Store on Steam Deck, we can only hope for the best!
_Have you tried Steam Deck yet? Let me know your thoughts in the comments down below._
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/epic-games-steam-deck/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://www.steamdeck.com/en/verified
[2]: https://www.epicgames.com/store/en-US/
[3]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher
[4]: https://news.itsfoss.com/heroic-games-launcher/
[5]: https://www.gamingonlinux.com/2022/03/heroic-games-launcher-now-works-nicely-on-steam-deck/
[6]: https://github.com/redromnon/HeroicBashLauncher
[7]: https://i0.wp.com/i.ytimg.com/vi/UvuGAQDagWE/hqdefault.jpg?w=780&ssl=1
[8]: https://news.itsfoss.com/author/rishabh/
[9]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/wiki/Adding-Games-to-Steam-on-Linux
[10]: https://github.com/derrod/legendary/releases/
[11]: https://github.com/redromnon/HeroicBashLauncher/releases/
[12]: https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/wiki/SteamDeck---Running-Epic-Games

View File

@ -0,0 +1,107 @@
[#]: subject: "Asahi Linux Distro Improves Apple M1 Support With First Alpha Release"
[#]: via: "https://news.itsfoss.com/asahi-linux-alpha/"
[#]: author: "Jacob Crume https://news.itsfoss.com/author/jacob/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Asahi Linux Distro Improves Apple M1 Support With First Alpha Release
======
In 2020, Apple unveiled the M1 at the WWDC event. This reveal brought significant performance improvements and better power efficiency, although it did have one major drawback.
This was the software support, as it meant that it was no longer possible to boot a “normal” X86 distro on new Apple Mac devices with an M1 ARM chip. Hence, the Asahi Linux project (based on Arch) was born, with the aim to develop all the drivers and tools necessary to make a working Linux installation on Apples ARM-based Macs.
Now, after more than a year of work, the [Asahi Linux project][1] has finally [released][2] its first **Alpha version**, which introduces Linux support for Apple M1 devices.
It is still an alpha release for obvious reasons. But, we will be looking at what you need to know if you ever wanted to run Linux on your Apple M1 machine.
### Supported Devices
Surprisingly, this alpha release already has support for M1, M1 Pro, and M1 Max SoCs (except for the Mac Studio)! Although different devices with these chips do have varying levels of support, a lot of stuff is already working.
Some of the key hardware that works in this release includes:
* Wi-Fi
* USB 2.0
* USB 3.0 on the Mac Mini
* Built-in display on the MacBook Air and Pro
* Built-in touchpad and keyboard
* Ethernet
* HDMI output on the Mac Mini
The result is a reasonably usable desktop Linux experience, with many of the incredible features of Apple Silicon.
Unfortunately, some key features are still missing, most notably the **CPU deep sleep mode, DisplayPort, Touchbar, Bluetooth, Camera, Thunderbolt, HDMI output on MacBooks, and GPU acceleration**.
This shouldnt impact desktop use too much but should be kept in mind.
### App Problems
Of course, you should not expect every application to work seamlessly. And, thats the case with Asahi Linux on Apple M1 hardware. This is limited only to apps that have problems with 16K page registers, although some of these apps are quite popular.
As the base for the most popular web browsers, I was quite surprised to find Chromium on the “known broken list”. While this may be rather off-putting for some users, Firefox does work, so users are still able to access the web.
Other apps confirmed to be broken include:
* Emacs (will be fixed in next few releases)
* Anything that use jemalloc (notably Rust)
* Anything using Libunwind
While not ideal, the software affected is only a small portion of Linux apps, so it shouldnt be too much of a concern.
### Installing Asahi Linux on Apple M1
![][3]
Although we havent focused very much on the working parts of Asahi Linux, it shouldnt be forgotten that it is a monumental achievement to get something working on a closed platform like the Apple Silicon Macs.
If you want to give Asahi Linux a try, there are a few different variants you can install.
I would recommend installing Asahi Linux with a full desktop environment for most users. This will be best for desktop use, and already contains customizations and optimizations to provide the best user experience.
However, the Asahi Linux team understands that some users want more customization, which is why they provide a minimal version as well. This is simply a basic Arch Linux ARM install, which means that you are free to do whatever you would like with it.
Finally, they also provide a basic UEFI environment for booting other distros and OSs (with appropriate driver support). One interesting use for this is to boot OpenBSD, which one of the developers behind Asahi Linux, Mark Kettenis, is working on porting.
Before you get started, it should be noted that you need that least 53 GB of free space.
Once you have decided on an option, it is extremely easy to get Asahi Linux dual-booted with macOS with the command below.
```
curl https://alx.sh | sh
```
It should give you all the instructions you need along the way. You should have a working Linux installation on your M1/M1 Pro/M1 Max computer if done correctly!
**Note:** The installation does not replace macOS with Linux. So, you get a dual-boot system at the end. You cannot easily uninstall it using the installer. However, you can simply delete the disk partition created by it.
You can learn more about it in its [official announcement post][2].
[Asahi Linux][4]
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/asahi-linux-alpha/
作者:[Jacob Crume][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/jacob/
[b]: https://github.com/lujun9972
[1]: https://news.itsfoss.com/asahi-linux-announcement/
[2]: https://asahilinux.org/2022/03/asahi-linux-alpha-release/
[3]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQzOSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[4]: https://asahilinux.org/

View File

@ -0,0 +1,101 @@
[#]: subject: "Linux Mint Debian Edition (LMDE) 5 is Here with Debian 11 Bullseye"
[#]: via: "https://news.itsfoss.com/lmde-5-release/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Linux Mint Debian Edition (LMDE) 5 is Here with Debian 11 Bullseye
======
Linux Mints offering with Debian is always an exciting release to look forward to.
In case you did not know, LMDE is meant to act as a replacement if Ubuntu ever disappears. So, whether you like or hate Ubuntu as a base, you have an impressive alternative without compromising the Linux Mint experience on your desktop.
With the latest LMDE 5 “Elsie”, the Linux Mint team has included all the goodies introduced in [Linux Mint 20.3][1] and [Debian 11 “Bullseye”][2] as its base.
Let me highlight the essential details regarding the new upgrade.
### Linux Mint Debian Edition 5 “Elsie”: Whats New?
![][3]
As you can guess, Linux Mint Debian Edition 5 comes loaded with Cinnamon as its desktop and looks exactly the same as Linux Mints primary offering with Ubuntu as its base.
### Cinnamon 5.2.7
Unlike Linux Mints main edition, you do not get the option for other desktop environments.
![][4]
So, you will have a Cinnamon desktop out-of-the-box with LMDE 5. The latest Cinnamon version includes plenty of improvements to give you a good user experience.
#### 32-bit Support Still Exists
If you are looking for [Linux distributions supporting 32-bit systems][5], LMDE 5 is yet another option that you can opt for.
While it may be irrelevant for most modern desktop users, it is still essential for Linux distributions to support 32-bit systems.
And, it is a good thing that Linux Mints Debian edition still includes support for it.
### Linux Kernel 5.10 LTS
[Linux Kernel 5.10][6] may not be the latest LTS release but it should be great for most hardware configurations (unless you have the latest and greatest from Intel/AMD).
![][7]
### Linux Mint 20.3 Improvements
With LMDE 5, the Linux Mint team has tried their best to add all the improvements [introduced in Linux Mint 20.3][1], with a new Debian base.
![][8]
You can notice the availability of new wallpaper backgrounds and get the latest app additions like “Thingy” or “Library” to manage documents.
In addition to the features, you also get to experience the same visual refresh to the theme with round edges, and slight changes to the theme color.
### Download LMDE 5
Before proceeding to install it, you may want to go through the [official release notes][9] to know about some common issues.
You can download the 64-bit or 32-bit ISO file from the [official site][10].
[Linux Mint Debian Edition 5][10]
If you were using [LMDE 5 beta][11], you do not need to upgrade, but type in a few commands, as per the instructions in the [release announcement][12]:
```
apt install network-manager-config-connectivity-debian plymouth-label pipewire plocate
apt remove mlocate brltty
sudo updatedb
```
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/lmde-5-release/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://news.itsfoss.com/linux-mint-20-3-una-release/
[2]: https://news.itsfoss.com/debian-11-feature/
[3]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ0MCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[4]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjYxNCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[5]: https://itsfoss.com/32-bit-linux-distributions/
[6]: https://news.itsfoss.com/kernel-5-10-release/
[7]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ5NyIgd2lkdGg9IjY5NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[8]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU0NiIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[9]: https://linuxmint.com/rel_elsie.php
[10]: https://www.linuxmint.com/edition.php?id=297
[11]: https://news.itsfoss.com/lmde-5-beta/
[12]: https://blog.linuxmint.com/?p=4287

View File

@ -0,0 +1,94 @@
[#]: subject: "KeePassXC 2.7.0 is a Massive Upgrade with Tags, Improved Auto-Type, and Windows Hello Support"
[#]: via: "https://news.itsfoss.com/keepassxc-2-7-0-release/"
[#]: author: "Rishabh Moharir https://news.itsfoss.com/author/rishabh/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
KeePassXC 2.7.0 is a Massive Upgrade with Tags, Improved Auto-Type, and Windows Hello Support
======
[KeePassXC][1], the open-source password manager, has just got a major upgrade, one that includes some new exciting features and improvements
For those unaware, KeePassXC is the community fork of the classic KeePassX.
KeePassXC is a cross-platform password manager available for Linux, Windows, and macOS. It is built using Qt5 libraries. Moreover, it uses the same database format (.kdbx) as [KeePass][2] (Windows-only password manager).
It also happens to be [one of the best password managers for Linux][3].
Let us look at some of the major highlights of the new release.
### Whats New?
With KeePassXC 2.7.0, you can expect massive changes. Considering a fairly long changelog, I have listed the most significant changes below.
#### Entry Tags
A much-needed feature and one that users most requested, password entries can now be easily tagged and filtered. Moreover, relevant tags will automatically be generated for entries to highlight databases with expired or weak passwords.
![Credits: KeePassXC][4]
A new Tags sub-section has been added under the General tab that displays a row of assigned tags for info on individual entries.
Theres also a dedicated quick selection section, “Database Tags” (as shown in the screenshot above), that will help users filter results based on selected tags.
#### Browser Statistics
The all-new Browser Statistics tab is a new entry to the already existing database reports. It allows users to view and edit entries used by the browser extension.
You can find the path and the URL listed.
![Credits: KeePassXC][5]
#### Improved Auto-Type
A separate **Auto-Type** selection dialog has been introduced for users, especially power users, to quickly and efficiently search entries across databases.
Along with supporting the built-in search syntax, it also allows users to copy data to the clipboard and enter TOTP codes.
![Credits: KeePassXC][6]
#### Other Key Additions
The history of individual entries highlights changes made to fields, letting you quickly identify and revert changes.
Linux users can find improvements made to Secret Service integration and the CLI. On the other hand, Windows and Apple users will be delighted to know that the password manager now supports Windows Hello and macOS Touch ID for quick unlock.
Another interesting thing to note, the crypto backend has now been switched to [Botan][7].
There have been several bug fixes and under-the-hood improvements; you can find more details in the [official changelog][8].
### Wrapping Up
KeePassXC 2.7.0 looks like a promising release, and privacy-focused users should expect a neater experience thanks to a couple of new features.
The convenience of interacting/copying data to sign in to an online account has improved with the changes. So, you might want to give it a try if you havent already.
Users can download KeePassXC by heading to their [official download page][9]. You can find AppImage file, Snap package, Flatpak package, distro-specific packages, and you can also install it using Ubuntu PPA.
[Download KeePassXC 2.7.0][9]
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/keepassxc-2-7-0-release/
作者:[Rishabh Moharir][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/rishabh/
[b]: https://github.com/lujun9972
[1]: https://keepassxc.org/
[2]: https://keepass.info/
[3]: https://itsfoss.com/password-managers-linux/
[4]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU4NyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[5]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU1MyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[6]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ4MCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[7]: https://github.com/randombit/botan
[8]: https://github.com/keepassxreboot/keepassxc/releases/tag/2.7.0
[9]: https://keepassxc.org/download/

View File

@ -0,0 +1,93 @@
[#]: subject: "Whats the Fuss About GNOMEs Libadwaita Library in Linux World?"
[#]: via: "https://news.itsfoss.com/gnome-libadwaita-library/"
[#]: author: "Jacob Crume https://news.itsfoss.com/author/jacob/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Whats the Fuss About GNOMEs Libadwaita Library in Linux World?
======
Back in March 2020, the GNOME project announced a new library called Libadwaita. This promised to fix numerous fundamental issues with GTK, the library GNOME uses to build its desktop environment.
Unfortunately, this announcement also resulted in some significant community backlash. While this hasnt really slowed the adoption of Libadwaita, it seems that some users are now starting to boycott GNOME because of it.
But what impact does Libadwaita have in the real world? And how does this differ for users and developers?
### Main Features Of Libadwaita
While it was originally meant to be a solution to the many GNOME-specific libraries developers needed to use, it has since grow into much more. As Adrian Plazas said in his [blog][1]:
> GNOME needs a blessed library implementing its HIG (Human Interface Guidelines) rapidly, developed in collaboration with its design team.
>
> […]
>
> To solve both GTKs need of independence and GNOMEs need to move faster, we are creating the libadwaita project. This new libadwaita library intends to extend that concept by being the missing code part of Adwaita. The library will be implemented as a direct GTK 4 continuation and replacement of libhandy, and it will be developed by libhandys current developers.
Adrian Plazas
Basically, Libadwaita is meant to be a GNOME-specific version of GTK4, with the GNOME project in complete control of the look and feel of apps. However, it also incorporates a number of other features:
* Adaptive widgets so that apps can work on both desktops, laptops, tablets, and smartphones (like the PinePhone)
* New Adwaita version, following the latest trends in UI design
* Built-in styles for buttons and other widgets
* Built-in in-app notifications
* Improved and more customizable animations
* Speed and fluidity improvements
While all these features are awesome, a select few have divided the community, mostly between developers and users. As someone who has made a number of small little projects with Libadwaita and GTK3 (without Libadwaita), as well as a GNOME user, I want to talk about the different perspectives of different people.
### User Perspective
![][2]
Unfortunately, Libadwaita has been met by immense backlash by some GNOME users. This all stems from one key change in Libadwaita: The inability to theme it. This is because the Adwaita theme is built right into Libadwaita, meaning that it would need to be recompiled every time the theme was changed.
This is a fundamental aspect of Libadwaita, for better or for worse. As a result, some users have decided that this is an attempt by GNOME to lock down their app ecosystem.
However, this does not mean that Libadwaita is dead in the water. From the very beginning, the GNOME developers have been adamant that a theming API would come soon, and it looks like this will happen.
While this wouldnt solve the issue of incompatibility of existing GTK and GNOME themes, it would solve some more fundamental issues. As has been said numerous times, the CSS theming that GTK currently users is much more of a band-aid fix to the problem of theming than a permanent solution. And, as with many open-source projects, this band-aid fix has been built upon to the extent now that there is very little chance of going back.
Libadwaita would go some steps to fixing this, but at the cost of the existing app ecosystem. With all this hate, however, developers continue to implement it. Why might this be?
### Developer Perspective
![][2]
As you saw in the feature list before, there are a huge number of features that help developers tremendously. For me, this has been the ability to create convergent apps, and the sole reason I use Libadwaita.
Unfortunately, as with almost every new GNOME library, there is minimal language-specific documentation available. This is instead replaced with a much more generic, automatically-generated documentation system.
While this is better than nothing, it is still quite lacklustre, especially considering the incredible community of developers GNOME has.
### A Better Solution?
Now, I hope that I have explained everyones position on Libadwaita, except mine. To be honest, I actually quite enjoy developing with it, even with all its teething problems. Unfortunately, I am also a huge fan of theming, and have found Libadwaita apps quite jarring compared to everything else.
However, I think there is a solution. As I said before, Libadwaita was created in response to the faster development pace GNOME needed. However, couldnt this be achieved through a branch from GTK 4?
This would allow GTK to inherit all the exciting features in Libadwaita, as well as allowing a more unified approach to GNOME libraries. As I said before in [my Flutter article][3], I believe that desktop Linux is too fragmented, and this extends to GTK.
What do you think about Libadwaita? Do you support it, or are you going to be boycotting GNOME? Please, I would love to hear your opinions in the comments below!
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/gnome-libadwaita-library/
作者:[Jacob Crume][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/jacob/
[b]: https://github.com/lujun9972
[1]: https://aplazas.pages.gitlab.gnome.org/blog/blog/2021/03/31/introducing-libadwaita.html
[2]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQzOSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[3]: https://news.itsfoss.com/no-flutter-on-linux-desktop/

View File

@ -1,706 +0,0 @@
[#]: subject: "Writing Advanced Web Applications with Go"
[#]: via: "https://www.jtolio.com/2017/01/writing-advanced-web-applications-with-go"
[#]: author: "jtolio.com https://www.jtolio.com/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Writing Advanced Web Applications with Go
======
Web development in many programming environments often requires subscribing to some full framework ethos. With [Ruby][1], its usually [Rails][2] but could be [Sinatra][3] or something else. With [Python][4], its often [Django][5] or [Flask][6]. With [Go][7], its…
If you spend some time in Go communities like the [Go mailing list][8] or the [Go subreddit][9], youll find Go newcomers frequently wondering what web framework is best to use. [There][10] [are][11] [quite][12] [a][13] [few][14] [Go][15] [frameworks][16] ([and][17] [then][18] [some][19]), so which one is best seems like a reasonable question. Without fail, though, the strong recommendation of the Go community is to [avoid web frameworks entirely][20] and just stick with the standard library as long as possible. Heres [an example from the Go mailing list][21] and heres [one from the subreddit][22].
Its not bad advice! The Go standard library is very rich and flexible, much more so than many other languages, and designing a web application in Go with just the standard library is definitely a good choice.
Even when these Go frameworks call themselves minimalistic, they cant seem to help themselves avoid using a different request handler interface than the default standard library [http.Handler][23], and I think this is the biggest source of angst about why frameworks should be avoided. If everyone standardizes on [http.Handler][23], then dang, all sorts of things would be interoperable!
Before Go 1.7, it made some sense to give in and use a different interface for handling HTTP requests. But now that [http.Request][24] has the [Context][25] and [WithContext][26] methods, there truly isnt a good reason any longer.
Ive done a fair share of web development in Go and Im here to share with you both some standard library development patterns Ive learned and some code Ive found myself frequently needing. The code Im sharing is not for use instead of the standard library, but to augment it.
Overall, if this blog post feels like its predominantly plugging various little standalone libraries from my [Webhelp non-framework][27], thats because it is. Its okay, theyre little standalone libraries. Only use the ones you want!
If youre new to Go web development, I suggest reading the Go documentations [Writing Web Applications][28] article first.
### Middleware
A frequent design pattern for server-side web development is the concept of _middleware_, where some portion of the request handler wraps some other portion of the request handler and does some preprocessing or routing or something. This is a big component of how [Express][29] is organized on [Node][30], and how Express middleware and [Negroni][17] middleware works is almost line-for-line identical in design.
Good use cases for middleware are things such as:
* making sure a user is logged in, redirecting if not,
* making sure the request came over HTTPS,
* making sure a session is set up and loaded from a session database,
* making sure we logged information before and after the request was handled,
* making sure the request was routed to the right handler,
* and so on.
Composing your web app as essentially a chain of middleware handlers is a very powerful and flexible approach. It allows you to avoid a lot of [cross-cutting concerns][31] and have your code factored in very elegant and easy-to-maintain ways. By wrapping a set of handlers with middleware that ensures a user is logged in prior to actually attempting to handle the request, the individual handlers no longer need mistake-prone copy-and-pasted code to ensure the same thing.
So, middleware is good. However, if Negroni or other frameworks are any indication, youd think the standard librarys `http.Handler` isnt up to the challenge. Negroni adds its own `negroni.Handler` just for the sake of making middleware easier. Theres no reason for this.
Here is a full middleware implementation for ensuring a user is logged in, assuming a `GetUser(*http.Request)` function but otherwise just using the standard library:
```
func RequireUser(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
user, err := GetUser(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if user == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
h.ServeHTTP(w, req)
})
}
```
Heres how its used (just wrap another handler!):
```
func main() {
http.ListenAndServe(":8080", RequireUser(http.HandlerFunc(myHandler)))
}
```
Express, Negroni, and other frameworks expect this kind of signature for a middleware-supporting handler:
```
type Handler interface {
// don't do this!
ServeHTTP(rw http.ResponseWriter, req *http.Request, next http.HandlerFunc)
}
```
Theres really no reason for adding the `next` argument - it reduces cross-library compatibility. So I say, dont use `negroni.Handler` (or similar). Just use `http.Handler`!
### Composability
Hopefully Ive sold you on middleware as a good design philosophy.
Probably the most commonly-used type of middleware is request routing, or muxing (seems like we should call this demuxing but what do I know). Some frameworks are almost solely focused on request routing. [gorilla/mux][32] seems more popular than any other part of the [Gorilla][33] library. I think the reason for this is that even though the Go standard library is completely full featured and has a good [ServeMux][34] implementation, it doesnt make the right thing the default.
So! Lets talk about request routing and consider the following problem. You, web developer extraordinaire, want to serve some HTML from your web server at `/hello/` but also want to serve some static assets from `/static/`. Lets take a quick stab.
```
package main
import (
"net/http"
)
func hello(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("hello, world!"))
}
func main() {
mux := http.NewServeMux()
mux.Handle("/hello/", http.HandlerFunc(hello))
mux.Handle("/static/", http.FileServer(http.Dir("./static-assets")))
http.ListenAndServe(":8080", mux)
}
```
If you visit `http://localhost:8080/hello/`, youll be rewarded with a friendly “hello, world!” message.
If you visit `http://localhost:8080/static/` on the other hand (assuming you have a folder of static assets in `./static-assets`), youll be surprised and frustrated. This code tries to find the source content for the request `/static/my-file` at `./static-assets/static/my-file`! Theres an extra `/static` in there!
Okay, so this is why `http.StripPrefix` exists. Lets fix it.
```
mux.Handle("/static/", http.StripPrefix("/static",
http.FileServer(http.Dir("./static-assets"))))
```
`mux.Handle` combined with `http.StripPrefix` is such a common pattern that I think it should be the default. Whenever a request router processes a certain amount of URL elements, it should strip them off the request so the wrapped `http.Handler` doesnt need to know its absolute URL and only needs to be concerned with its relative one.
In [Russ Cox][35]s recent [TiddlyWeb backend][36], I would argue that every time `strings.TrimPrefix` is needed to remove the full URL from the handlers incoming path arguments, it is an unnecessary cross-cutting concern, unfortunately imposed by `http.ServeMux`. (An example is [line 201 in tiddly.go][37].)
Id much rather have the default `mux` behavior work more like a directory of registered elements that by default strips off the ancestor directory before handing the request to the next middleware handler. Its much more composable. To this end, Ive written a simple muxer that works in this fashion called [whmux.Dir][38]. It is essentially `http.ServeMux` and `http.StripPrefix` combined. Heres the previous example reworked to use it:
```
package main
import (
"net/http"
"gopkg.in/webhelp.v1/whmux"
)
func hello(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("hello, world!"))
}
func main() {
mux := whmux.Dir{
"hello": http.HandlerFunc(hello),
"static": http.FileServer(http.Dir("./static-assets")),
}
http.ListenAndServe(":8080", mux)
}
```
There are other useful mux implementations inside the [whmux][39] package that demultiplex on various aspects of the request path, request method, request host, or pull arguments out of the request and place them into the context, such as a [whmux.IntArg][40] or [whmux.StringArg][41]. This brings us to [contexts][42].
### Contexts
Request contexts are a recent addition to the Go 1.7 standard library, but the idea of [contexts has been around since mid-2014][43]. As of Go 1.7, they were added to the standard library ([“context”][42]), but are available for older Go releases in the original location ([“golang.org/x/net/context”][44]).
First, heres the definition of the `context.Context` type that `(*http.Request).Context()` returns:
```
type Context interface {
Done() <-chan struct{}
Err() error
Deadline() (deadline time.Time, ok bool)
Value(key interface{}) interface{}
}
```
Talking about `Done()`, `Err()`, and `Deadline()` are enough for an entirely different blog post, so Im going to ignore them at least for now and focus on `Value(interface{})`.
As a motivating problem, lets say that the `GetUser(*http.Request)` method we assumed earlier is expensive, and we only want to call it once per request. We certainly dont want to call it once to check that a user is logged in, and then again when we actually need the `*User` value. With `(*http.Request).WithContext` and `context.WithValue`, we can pass the `*User` down to the next middleware precomputed!
Heres the new middleware:
```
type userKey int
func RequireUser(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
user, err := GetUser(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if user == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, userKey(0), user)
h.ServeHTTP(w, req.WithContext(ctx))
})
}
```
Now, handlers that are protected by this `RequireUser` handler can load the previously computed `*User` value like this:
```
if user, ok := req.Context().Value(userKey(0)).(*User); ok {
// there's a valid user!
}
```
Contexts allow us to pass optional values to handlers down the chain in a way that is relatively type-safe and flexible. None of the above context logic requires anything outside of the standard library.
#### Aside about context keys
There was a curious piece of code in the above example. At the top, we defined a `type userKey int`, and then always used it as `userKey(0)`.
One of the possible problems with contexts is the `Value()` interface lends itself to a global namespace where you can stomp on other context users and use conflicting key names. Above, we used `type userKey` because its an unexported type in your package. It will never compare equal (without a cast) to any other type, including `int`, in Go. This gives us a way to namespace keys to your package, even though the `Value()` method is still a sort of global namespace.
Because the need for this is so common, the `webhelp` package defines a [GenSym()][45] helper that will create a brand new, never-before-seen, unique value for use as a context key.
If we used [GenSym()][45], then `type userKey int` would become `var userKey = webhelp.GenSym()` and `userKey(0)` would simply become `userKey`.
#### Back to whmux.StringArg
Armed with this new context behavior, we can now present a `whmux.StringArg` example:
```
package main
import (
"fmt"
"net/http"
"gopkg.in/webhelp.v1/whmux"
)
var (
pageName = whmux.NewStringArg()
)
func page(w http.ResponseWriter, req *http.Request) {
name := pageName.Get(req.Context())
fmt.Fprintf(w, "Welcome to %s", name)
}
func main() {
// pageName.Shift pulls the next /-delimited string out of the request's
// URL.Path and puts it into the context instead.
pageHandler := pageName.Shift(http.HandlerFunc(page))
http.ListenAndServe(":8080", whmux.Dir{
"wiki": pageHandler,
})
}
```
### Pre-Go-1.7 support
Contexts let you do some pretty cool things. But lets say youre stuck with something before Go 1.7 (for instance, App Engine is currently Go 1.6).
Thats okay! Ive backported all of the neat new context features to Go 1.6 and earlier in a forwards compatible way!
With the [whcompat][46] package, `req.Context()` becomes `whcompat.Context(req)`, and `req.WithContext(ctx)` becomes `whcompat.WithContext(req, ctx)`. The `whcompat` versions work with all releases of Go. Yay!
Theres a bit of unpleasantness behind the scenes to make this happen. Specifically, for pre-1.7 builds, a global map indexed by `req.URL` is kept, and a finalizer is installed on `req` to clean up. So dont change what `req.URL` points to and this will work fine. In practice its not a problem.
`whcompat` adds additional backwards-compatibility helpers. In Go 1.7 and on, the contexts `Done()` channel is closed (and `Err()` is set), whenever the request is done processing. If you want this behavior in Go 1.6 and earlier, just use the [whcompat.DoneNotify][47] middleware.
In Go 1.8 and on, the contexts `Done()` channel is closed when the client goes away, even if the request hasnt completed. If you want this behavior in Go 1.7 and earlier, just use the [whcompat.CloseNotify][48] middleware, though beware that it costs an extra goroutine.
### Error handling
How you handle errors can be another cross-cutting concern, but with good application of context and middleware, it too can be beautifully cleaned up so that the responsibilities lie in the correct place.
Problem statement: your `RequireUser` middleware needs to handle an authentication error differently between your HTML endpoints and your JSON API endpoints. You want to use `RequireUser` for both types of endpoints, but with your HTML endpoints you want to return a user-friendly error page, and with your JSON API endpoints you want to return an appropriate JSON error state.
In my opinion, the right thing to do is to have contextual error handlers, and luckily, we have a context for contextual information!
First, we need an error handler interface.
```
type ErrHandler interface {
HandleError(w http.ResponseWriter, req *http.Request, err error)
}
```
Next, lets make a middleware that registers the error handler in the context:
```
var errHandler = webhelp.GenSym() // see the aside about context keys
func HandleErrWith(eh ErrHandler, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := context.WithValue(whcompat.Context(req), errHandler, eh)
h.ServeHTTP(w, whcompat.WithContext(req, ctx))
})
}
```
Last, lets make a function that will use the registered error handler for errors:
```
func HandleErr(w http.ResponseWriter, req *http.Request, err error) {
if handler, ok := whcompat.Context(req).Value(errHandler).(ErrHandler); ok {
handler.HandleError(w, req, err)
return
}
log.Printf("error: %v", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
}
```
Now, as long as everything uses `HandleErr` to handle errors, our JSON API can handle errors with JSON responses, and our HTML endpoints can handle errors with HTML responses.
Of course, the [wherr][49] package implements this all for you, and the [whjson][49] package even implements a friendly JSON API error handler.
Heres how you might use it:
```
var userKey = webhelp.GenSym()
func RequireUser(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
user, err := GetUser(req)
if err != nil {
wherr.Handle(w, req, wherr.InternalServerError.New("failed to get user"))
return
}
if user == nil {
wherr.Handle(w, req, wherr.Unauthorized.New("no user found"))
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, userKey, user)
h.ServeHTTP(w, req.WithContext(ctx))
})
}
func userpage(w http.ResponseWriter, req *http.Request) {
user := req.Context().Value(userKey).(*User)
w.Header().Set("Content-Type", "text/html")
userpageTmpl.Execute(w, user)
}
func username(w http.ResponseWriter, req *http.Request) {
user := req.Context().Value(userKey).(*User)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{"user": user})
}
func main() {
http.ListenAndServe(":8080", whmux.Dir{
"api": wherr.HandleWith(whjson.ErrHandler,
RequireUser(whmux.Dir{
"username": http.HandlerFunc(username),
})),
"user": RequireUser(http.HandlerFunc(userpage)),
})
}
```
#### Aside about the spacemonkeygo/errors package
The default [wherr.Handle][50] implementation understands all of the [error classes defined in the wherr top level package][51].
These error classes are implemented using the [spacemonkeygo/errors][52] library and the [spacemonkeygo/errors/errhttp][53] extensions. You dont have to use this library or these errors, but the benefit is that your error instances can be extended to include HTTP status code messages and information, which once again, provides for a nice elimination of cross-cutting concerns in your error handling logic.
See the [spacemonkeygo/errors][52] package for more details.
_**Update 2018-04-19:** After a few years of use, my friend condensed some lessons we learned and the best parts of `spacemonkeygo/errors` into a new, more concise, better library, over at [github.com/zeebo/errs][54]. Consider using that instead!_
### Sessions
Gos standard library has great support for cookies, but cookies by themselves arent usually what a developer thinks of when she thinks about sessions. Cookies are unencrypted, unauthenticated, and readable by the user, and perhaps you dont want that with your session data.
Further, sessions can be stored in cookies, but could also be stored in a database to provide features like session revocation and querying. Theres lots of potential details about the implementation of sessions.
Request handlers, however, probably dont care too much about the implementation details of the session. Request handlers usually just want a bucket of keys and values they can store safely and securely.
The [whsess][55] package implements middleware for registering an arbitrary session store (a default cookie-based session store is provided), and implements helpers for retrieving and saving new values into the session.
The default cookie-based session store implements encryption and authentication via the excellent [nacl/secretbox][56] package.
Usage is like this:
```
func handler(w http.ResponseWriter, req *http.Request) {
ctx := whcompat.Context(req)
sess, err := whsess.Load(ctx, "namespace")
if err != nil {
wherr.Handle(w, req, err)
return
}
if loggedIn, _ := sess.Values["logged_in"].(bool); loggedIn {
views, _ := sess.Values["views"].(int64)
sess.Values["views"] = views + 1
sess.Save(w)
}
}
func main() {
http.ListenAndServe(":8080", whsess.HandlerWithStore(
whsess.NewCookieStore(secret), http.HandlerFunc(handler)))
}
```
### Logging
The Go standard library by default doesnt log incoming requests, outgoing responses, or even just what port the HTTP server is listening on.
The [whlog][57] package implements all three. The [whlog.LogRequests][58] middleware will log requests as they start. The [whlog.LogResponses][59] middleware will log requests as they end, along with status code and timing information. [whlog.ListenAndServe][60] will log the address the server ultimately listens on (if you specify “:0” as your address, a port will be randomly chosen, and [whlog.ListenAndServe][60] will log it).
[whlog.LogResponses][59] deserves special mention for how it does what it does. It uses the [whmon][61] package to instrument the outgoing `http.ResponseWriter` to keep track of response information.
Usage is like this:
```
func main() {
whlog.ListenAndServe(":8080", whlog.LogResponses(whlog.Default, handler))
}
```
#### App engine logging
App engine logging is unconventional crazytown. The standard library logger doesnt work by default on App Engine, because App Engine logs _require_ the request context. This is unfortunate for libraries that dont necessarily run on App Engine all the time, as their logging information doesnt make it to the App Engine request-specific logger.
Unbelievably, this is fixable with [whgls][62], which uses my terrible, terrible (but recently improved) [Goroutine-local storage library][63] to store the request context on the current stack, register a new log output, and fix logging so standard library logging works with App Engine again.
### Template handling
Gos standard library [html/template][64] package is excellent, but youll be unsurprised to find theres a few tasks I do with it so commonly that Ive written additional support code.
The [whtmpl][65] package really does two things. First, it provides a number of useful helper methods for use within templates, and second, it takes some friction out of managing a large number of templates.
When writing templates, one thing you can do is call out to other registered templates for small values. A good example might be some sort of list element. You can have a template that renders the list element, and then your template that renders your list can use the list element template in turn.
Use of another template within a template might look like this:
```
<ul>
{{ range .List }}
{{ template "list_element" . }}
{{ end }}
</ul>
```
Youre now rendering the `list_element` template with the list element from `.List`. But what if you want to also pass the current user `.User`? Unfortunately, you can only pass one argument from one template to another. If you have two arguments you want to pass to another template, with the standard library, youre out of luck.
The [whtmpl][65] package adds three helper functions to aid you here, `makepair`, `makemap`, and `makeslice` (more docs under the [whtmpl.Collection][66] type). `makepair` is the simplest. It takes two arguments and constructs a [whtmpl.Pair][67]. Fixing our example above would look like this now:
```
<ul>
{{ $user := .User }}
{{ range .List }}
{{ template "list_element" (makepair . $user) }}
{{ end }}
</ul>
```
The second thing [whtmpl][65] does is make defining lots of templates easy, by optionally automatically naming templates after the name of the file the template is defined in.
For example, say you have three files.
Heres `pkg.go`:
```
package views
import "gopkg.in/webhelp.v1/whtmpl"
var Templates = whtmpl.NewCollection()
```
Heres `landing.go`:
```
package views
var _ = Templates.MustParse(`{{ template "header" . }}
<h1>Landing!</h1>`)
```
And heres `header.go`:
```
package views
var _ = Templates.MustParse(`<title>My website!</title>`)
```
Now, you can import your new `views` package and render the `landing` template this easily:
```
func handler(w http.ResponseWriter, req *http.Request) {
views.Templates.Render(w, req, "landing", map[string]interface{}{})
}
```
### User authentication
Ive written two Webhelp-style authentication libraries that I end up using frequently.
The first is an OAuth2 library, [whoauth2][68]. Ive written up [an example application that authenticates with Google, Facebook, and Github][69].
The second, [whgoth][70], is a wrapper around [markbates/goth][71]. My portion isnt quite complete yet (some fixes are still necessary for optional App Engine support), but will support more non-OAuth2 authentication sources (like Twitter) when it is done.
### Route listing
Surprise! If youve used [webhelp][27] based handlers and middleware for your whole app, you automatically get route listing for free, via the [whroute][72] package.
My web serving codes `main` method often has a form like this:
```
switch flag.Arg(0) {
case "serve":
panic(whlog.ListenAndServe(*listenAddr, routes))
case "routes":
whroute.PrintRoutes(os.Stdout, routes)
default:
fmt.Printf("Usage: %s <serve|routes>\n", os.Args[0])
}
```
Heres some example output:
```
GET /auth/_cb/
GET /auth/login/
GET /auth/logout/
GET /
GET /account/apikeys/
POST /account/apikeys/
GET /project/<int>/
GET /project/<int>/control/<int>/
POST /project/<int>/control/<int>/sample/
GET /project/<int>/control/
Redirect: f(req)
POST /project/<int>/control/
POST /project/<int>/control_named/<string>/sample/
GET /project/<int>/control_named/
Redirect: f(req)
GET /project/<int>/sample/<int>/
GET /project/<int>/sample/<int>/similar[/<*>]
GET /project/<int>/sample/
Redirect: f(req)
POST /project/<int>/search/
GET /project/
Redirect: /
POST /project/
```
### Other little things
[webhelp][27] has a number of other subpackages:
* [whparse][73] assists in parsing optional request arguments.
* [whredir][74] provides some handlers and helper methods for doing redirects in various cases.
* [whcache][75] creates request-specific mutable storage for caching various computations and database loaded data. Mutability helps helper functions that arent used as middleware share data.
* [whfatal][76] uses panics to simplify early request handling termination. Probably avoid this package unless you want to anger other Go developers.
### Summary
Designing your web project as a collection of composable middlewares goes quite a long way to simplify your code design, eliminate cross-cutting concerns, and create a more flexible development environment. Use my [webhelp][27] package if it helps you.
Or dont! Whatever! Its still a free country last I checked.
#### Update
Peter Kieltyka points me to his [Chi framework][77], which actually does seem to do the right things with respect to middleware, handlers, and contexts - certainly much more so than all the other frameworks Ive seen. So, shoutout to Peter and the team at Pressly!
--------------------------------------------------------------------------------
via: https://www.jtolio.com/2017/01/writing-advanced-web-applications-with-go
作者:[jtolio.com][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.jtolio.com/
[b]: https://github.com/lujun9972
[1]: https://www.ruby-lang.org/
[2]: http://rubyonrails.org/
[3]: http://www.sinatrarb.com/
[4]: https://www.python.org/
[5]: https://www.djangoproject.com/
[6]: http://flask.pocoo.org/
[7]: https://golang.org/
[8]: https://groups.google.com/d/forum/golang-nuts
[9]: https://www.reddit.com/r/golang/
[10]: https://revel.github.io/
[11]: https://gin-gonic.github.io/gin/
[12]: http://iris-go.com/
[13]: https://beego.me/
[14]: https://go-macaron.com/
[15]: https://github.com/go-martini/martini
[16]: https://github.com/gocraft/web
[17]: https://github.com/urfave/negroni
[18]: https://godoc.org/goji.io
[19]: https://echo.labstack.com/
[20]: https://medium.com/code-zen/why-i-don-t-use-go-web-frameworks-1087e1facfa4
[21]: https://groups.google.com/forum/#!topic/golang-nuts/R_lqsTTBh6I
[22]: https://www.reddit.com/r/golang/comments/1yh6gm/new_to_go_trying_to_select_web_framework/
[23]: https://golang.org/pkg/net/http/#Handler
[24]: https://golang.org/pkg/net/http/#Request
[25]: https://golang.org/pkg/net/http/#Request.Context
[26]: https://golang.org/pkg/net/http/#Request.WithContext
[27]: https://godoc.org/gopkg.in/webhelp.v1
[28]: https://golang.org/doc/articles/wiki/
[29]: https://expressjs.com/
[30]: https://nodejs.org/en/
[31]: https://en.wikipedia.org/wiki/Cross-cutting_concern
[32]: https://github.com/gorilla/mux
[33]: https://github.com/gorilla/
[34]: https://golang.org/pkg/net/http/#ServeMux
[35]: https://swtch.com/~rsc/
[36]: https://github.com/rsc/tiddly
[37]: https://github.com/rsc/tiddly/blob/8f9145ac183e374eb95d90a73be4d5f38534ec47/tiddly.go#L201
[38]: https://godoc.org/gopkg.in/webhelp.v1/whmux#Dir
[39]: https://godoc.org/gopkg.in/webhelp.v1/whmux
[40]: https://godoc.org/gopkg.in/webhelp.v1/whmux#IntArg
[41]: https://godoc.org/gopkg.in/webhelp.v1/whmux#StringArg
[42]: https://golang.org/pkg/context/
[43]: https://blog.golang.org/context
[44]: https://godoc.org/golang.org/x/net/context
[45]: https://godoc.org/gopkg.in/webhelp.v1#GenSym
[46]: https://godoc.org/gopkg.in/webhelp.v1/whcompat
[47]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#DoneNotify
[48]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#CloseNotify
[49]: https://godoc.org/gopkg.in/webhelp.v1/wherr
[50]: https://godoc.org/gopkg.in/webhelp.v1/wherr#Handle
[51]: https://godoc.org/gopkg.in/webhelp.v1/wherr#pkg-variables
[52]: https://godoc.org/github.com/spacemonkeygo/errors
[53]: https://godoc.org/github.com/spacemonkeygo/errors/errhttp
[54]: https://github.com/zeebo/errs
[55]: https://godoc.org/gopkg.in/webhelp.v1/whsess
[56]: https://godoc.org/golang.org/x/crypto/nacl/secretbox
[57]: https://godoc.org/gopkg.in/webhelp.v1/whlog
[58]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogRequests
[59]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogResponses
[60]: https://godoc.org/gopkg.in/webhelp.v1/whlog#ListenAndServe
[61]: https://godoc.org/gopkg.in/webhelp.v1/whmon
[62]: https://godoc.org/gopkg.in/webhelp.v1/whgls
[63]: https://godoc.org/github.com/jtolds/gls
[64]: https://golang.org/pkg/html/template/
[65]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl
[66]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Collection
[67]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Pair
[68]: https://godoc.org/gopkg.in/go-webhelp/whoauth2.v1
[69]: https://github.com/go-webhelp/whoauth2/blob/v1/examples/group/main.go
[70]: https://godoc.org/gopkg.in/go-webhelp/whgoth.v1
[71]: https://github.com/markbates/goth
[72]: https://godoc.org/gopkg.in/webhelp.v1/whroute
[73]: https://godoc.org/gopkg.in/webhelp.v1/whparse
[74]: https://godoc.org/gopkg.in/webhelp.v1/whredir
[75]: https://godoc.org/gopkg.in/webhelp.v1/whcache
[76]: https://godoc.org/gopkg.in/webhelp.v1/whfatal
[77]: https://github.com/pressly/chi

View File

@ -1,119 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Magic GOPATH)
[#]: via: (https://www.jtolio.com/2017/01/magic-gopath)
[#]: author: (jtolio.com https://www.jtolio.com/)
Magic GOPATH
======
_**Update:** With the advent of Go 1.11 and [Go modules][1], this whole post is now useless. Unset your GOPATH entirely and switch to Go modules today!_
Maybe someday Ill start writing about things besides Go again.
Go requires that you set an environment variable for your workspace called your `GOPATH`. The `GOPATH` is one of the most confusing aspects of Go to newcomers and even relatively seasoned developers alike. Its not immediately clear what would be better, but finding a good `GOPATH` value has implications for your source code repository layout, how many separate projects you have on your computer, how default project installation instructions work (via `go get`), and even how you interoperate with other projects and libraries.
Its taken until Go 1.8 to decide to [set a default][2] and that small change was one of [the most talked about code reviews][3] for the 1.8 release cycle.
After [writing about GOPATH himself][4], [Dave Cheney][5] [asked me][6] to write a blog post about what I do.
### My proposal
I set my `GOPATH` to always be the current working directory, unless a parent directory is clearly the `GOPATH`.
Heres the relevant part of my `.bashrc`:
```
# bash command to output calculated GOPATH.
calc_gopath() {
local dir="$PWD"
# we're going to walk up from the current directory to the root
while true; do
# if there's a '.gopath' file, use its contents as the GOPATH relative to
# the directory containing it.
if [ -f "$dir/.gopath" ]; then
( cd "$dir";
# allow us to squash this behavior for cases we want to use vgo
if [ "$(cat .gopath)" != "" ]; then
cd "$(cat .gopath)";
echo "$PWD";
fi; )
return
fi
# if there's a 'src' directory, the parent of that directory is now the
# GOPATH
if [ -d "$dir/src" ]; then
echo "$dir"
return
fi
# we can't go further, so bail. we'll make the original PWD the GOPATH.
if [ "$dir" == "/" ]; then
echo "$PWD"
return
fi
# now we'll consider the parent directory
dir="$(dirname "$dir")"
done
}
my_prompt_command() {
export GOPATH="$(calc_gopath)"
# you can have other neat things in here. I also set my PS1 based on git
# state
}
case "$TERM" in
xterm*|rxvt*)
# Bash provides an environment variable called PROMPT_COMMAND. The contents
# of this variable are executed as a regular Bash command just before Bash
# displays a prompt. Let's only set it if we're in some kind of graphical
# terminal I guess.
PROMPT_COMMAND=my_prompt_command
;;
*)
;;
esac
```
The benefits are fantastic. If you want to quickly `go get` something and not have it clutter up your workspace, you can do something like:
```
cd $(mktemp -d) && go get github.com/the/thing
```
On the other hand, if youre jumping between multiple projects (whether or not they have the full workspace checked in or are just library packages), the `GOPATH` is set accurately.
More flexibly, if you have a tree where some parent directory is outside of the `GOPATH` but you want to set the `GOPATH` anyways, you can create a `.gopath` file and it will automatically set your `GOPATH` correctly any time your shell is inside that directory.
The whole thing is super nice. I kinda cant imagine doing something else anymore.
### Fin.
--------------------------------------------------------------------------------
via: https://www.jtolio.com/2017/01/magic-gopath
作者:[jtolio.com][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.jtolio.com/
[b]: https://github.com/lujun9972
[1]: https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more
[2]: https://rakyll.org/default-gopath/
[3]: https://go-review.googlesource.com/32019/
[4]: https://dave.cheney.net/2016/12/20/thinking-about-gopath
[5]: https://dave.cheney.net/
[6]: https://twitter.com/davecheney/status/811334240247812097

View File

@ -1,171 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (Starryi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Live video streaming with open source Video.js)
[#]: via: (https://opensource.com/article/20/2/video-streaming-tools)
[#]: author: (Aaron J. Prisk https://opensource.com/users/ricepriskytreat)
Live video streaming with open source Video.js
======
Video.js is a widely used protocol that will serve your live video
stream to a wide range of devices.
![video editing dashboard][1]
Last year, I wrote about [creating a video streaming server with Linux][2]. That project uses the Real-Time Messaging Protocol (RMTP), Nginx web server, Open Broadcast Studio (OBS), and VLC media player.
I used VLC to play our video stream, which may be fine for a small local deployment but isn't very practical on a large scale. First, your viewers have to use VLC, and RTMP streams can provide inconsistent playback. This is where [Video.js][3] comes into play! Video.js is an open source JavaScript framework for creating custom HTML5 video players. Video.js is incredibly powerful, and it's used by a host of very popular websites—largely due to its open nature and how easy it is to get up and running.
### Get started with Video.js
This project is based off of the video streaming project I wrote about last year. Since that project was set to serve RMTP streams, to use Video.js, you'll need to make some adjustments to that Nginx configuration. HTTP Live Streaming ([HLS][4]) is a widely used protocol developed by Apple that will serve your stream better to a multitude of devices. HLS will take your stream, break it into chunks, and serve it via a specialized playlist. This allows for a more fault-tolerant stream that can play on more devices.
First, create a directory that will house the HLS stream and give Nginx permission to write to it:
```
mkdir /mnt/hls
chown www:www /mnt/hls
```
Next, fire up your text editor, open the Nginx.conf file, and add the following under the **application live** section:
```
       application live {
            live on;
            # Turn on HLS
            hls on;
            hls_path /mnt/hls/;
            hls_fragment 3;
            hls_playlist_length 60;
            # disable consuming the stream from nginx as rtmp
            deny play all;
}
```
Take note of the HLS fragment and playlist length settings. You may want to adjust them later, depending on your streaming needs, but this is a good baseline to start with. Next, we need to ensure that Nginx is able to listen for requests from our player and understand how to present it to the user. So, we'll want to add a new section at the bottom of our nginx.conf file.
```
server {
        listen 8080;
        location / {
            # Disable cache
            add_header 'Cache-Control' 'no-cache';
            # CORS setup
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length';
            # allow CORS preflight requests
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            types {
                application/dash+xml mpd;
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /mnt/;
        }
    }
```
Visit Video.js's [Getting started][5] page to download the latest release and check out the release notes. Also on that page, Video.js has a great introductory template you can use to create a very basic web player. I'll break down the important bits of that template and insert the pieces you need to get your new HTML player to use your stream.
The **head** links in the Video.js library from a content-delivery network (CDN). You can also opt to download and store Video.js locally on your web server if you want.
```
&lt;head&gt;
  &lt;link href="<https://vjs.zencdn.net/7.5.5/video-js.css>" rel="stylesheet" /&gt;
  &lt;!-- If you'd like to support IE8 (for Video.js versions prior to v7) --&gt;
  &lt;script src="[https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"\&gt;\][6]&lt;/script&gt;
&lt;/head&gt;
```
Now to the real meat of the player. The **body** section sets the parameters of how the video player will be displayed. Within the **video** element, you need to define the properties of your player. How big do you want it to be? Do you want it to have a poster (i.e., a thumbnail)? Does it need any special player controls? This example defines a simple 600x600 pixel player with an appropriate (to me) thumbnail featuring Beastie (the BSD Demon) and Tux (the Linux penguin).
```
&lt;body&gt;
  &lt;video
    id="my-video"
    class="video-js"
    controls
    preload="auto"
    width="600"
    height="600"
    poster="BEASTIE-TUX.jpg"
    data-setup="{}"
  &gt;
```
Now that you've set how you want your player to look, you need to tell it what to play. Video.js can handle a large number of different formats, including HLS streams.
```
    &lt;source src="<http://MY-WEB-SERVER:8080/hls/STREAM-KEY.m3u8>" type="application/x-mpegURL" /&gt;
    &lt;p class="vjs-no-js"&gt;
      To view this video please enable JavaScript, and consider upgrading to a
      web browser that
      &lt;a href="<https://videojs.com/html5-video-support/>" target="_blank"
        &gt;supports HTML5 video&lt;/a
      &gt;
    &lt;/p&gt;
  &lt;/video&gt;
```
### Record your streams
Keeping a copy of your streams is super easy. Just add the following at the bottom of your **application live** section in the nginx.conf file:
```
# Enable stream recording
record all;
record_path /mnt/recordings/;
record_unique on;
```
Make sure that **record_path** exists and that Nginx has permissions to write to it:
```
`chown -R www:www /mnt/recordings`
```
### Down the stream
That's it! You should now have a spiffy new HTML5-friendly live video player. There are lots of great resources out there on how to expand all your video-making adventures. If you have any questions or suggestions, feel free to reach out to me on [Twitter][7] or leave a comment below.
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/2/video-streaming-tools
作者:[Aaron J. Prisk][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/ricepriskytreat
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/video_editing_folder_music_wave_play.png?itok=-J9rs-My (video editing dashboard)
[2]: https://opensource.com/article/19/1/basic-live-video-streaming-server
[3]: https://videojs.com/
[4]: https://en.wikipedia.org/wiki/HTTP_Live_Streaming
[5]: https://videojs.com/getting-started
[6]: https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"\>\
[7]: https://twitter.com/AKernelPanic

View File

@ -1,68 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (Why I switched from Mac to Linux)
[#]: via: (https://opensource.com/article/20/3/mac-linux)
[#]: author: (Lee Tusman https://opensource.com/users/leeto)
Why I switched from Mac to Linux
======
After 25 years, Lee made the switch to Linux and couldn't be happier.
Here's what he uses.
![Code going into a computer.][1]
In 1994, my family bought a Macintosh Performa 475 as a home computer. I had used Macintosh SE computers in school and learned to type with [Mavis Beacon Teaches Typing][2], so I've been a Mac user for well over 25 years. Back in the mid-1990s, I was attracted to its ease of use. It didn't start with a DOS command prompt; it opened to a friendly desktop. It was playful. And even though there was a lot less software for Macintosh than PCs, I thought the Mac ecosystem was better, just on the strength of KidPix and Hypercard, which I still think of as the unsurpassed, most intuitive _creative stack_.
Even so, I still had the feeling that Mac was an underdog compared to Windows. I remember thinking the company could disappear one day. Flash-forward decades later, and Apple is a behemoth, a trillion-dollar company. But as it evolved, it changed significantly. Some changes have been for the better, such as better stabilization, simpler hardware choices, increased security, and more accessibility options. Other changes annoyed me—not all at once, but slowly. Most significantly, I am annoyed by Apple's closed ecosystem—the difficulty of accessing photos without iPhoto; the necessity of using iTunes; and the enforced bundling of the Apple store ecosystem even when I don't want to use it.
Over time, I found myself working largely in the terminal. I used iTerm2 and the [Homebrew][3] package manager. I couldn't get all my Linux software to work, but much of it did. I thought I had the best of both worlds: the macOS graphical operating system and user interface alongside the ability to jump into a quick terminal session.
Later, I began using Raspberry Pi computers booting Raspbian. I also collected a number of very old laptops rescued from the trash at universities, so, by necessity, I decided to try out various Linux distros. While none of them became my main machine, I started to really enjoy using Linux. I began to consider what it would be like to try running a Linux distro as my daily driver, but I thought the Macbook's comfort and ease, especially the hardware's size and weight, would be hard to find in a non-Mac laptop.
## Time to make the switch?
About two years ago, I began using a Dell for work. It was a larger laptop with an integrated GPU, and dual-booted Linux and Windows. I used it for game development, 3D modeling, some machine learning, and basic programming in C# and Java. I considered making it my primary machine, but I loved the portability of my Macbook Air, and continued to use that as well.
Last fall, I started to notice my Air was running hot, and the fan was coming on more often. My primary machine was starting to show its age. For years, I used the Mac's terminal to access Darwin's Unix-like operating system, and I was spending more and more time bouncing between the terminal and my web browser. Was it time to make the switch?
I began exploring the possibilities for a Macbook-like Linux laptop. After doing some research, reading reviews and message boards, I went with the long-celebrated Dell XPS 13 Developer Edition 7390, opting for the 10th Generation i7. I chose it because I love the feel of the Macbook (and especially the slim Macbook Air), and reviews of the XPS 13 suggested it seemed it was similar, with really positive reviews of the trackpad and keyboard.
Most importantly, it came loaded with Ubuntu. While it's easy enough to get a PC, wipe it, and install a new Linux distro, I was attracted to the cohesive operating system and hardware, but one that allowed a lot of the customization we know and love in Linux. So when there was a sale, I took the plunge and purchased it.
## What it's like to run Linux daily
I've been using the XPS 13 for three months and my dual-booted Linux work laptop for two years. At first, I thought I'd want to spend more time finding an alternate desktop environment or window manager that was more Mac-like, such as [Enlightenment][4]. I tried several, but I have to say, I like the simplicity of running [GNOME][5] out of the box. For one thing, it's minimal; there's not much GUI to get caught up in. In fact, it's intuitive and the [overview][6] takes only a couple minutes to read. 
I can access my applications through the application dash bar or a grid button to get to the application view. To access my file system, I click on the **Files** icon in the dash. To open the GNOME terminal, I type **Ctrl+Alt+T** or just **Alt+Tab** to switch between an open application and an open terminal. It's also easy to define your own [custom hotkey shortcuts][7].
Beyond this, there's not much else to say. Unlike the Mac's desktop, there's not a lot to get lost in, which means there's less to distract me from my work or the applications I want to run. I didn't realize all the options or how much time I spent navigating windows on my Mac. In Linux, there are just files, applications, and the terminal.
I installed the [i3 tiling window manager][8] to do a test run. I had a few issues configuring it because I type in [Dvorak][9], and i3 doesn't adapt to the alternate keyboard configuration. I think with more effort, I could figure out a new keyboard mapping in i3, but the main thing I was looking for was simple tiling.
I looked up GNOME's tiling capabilities and was pleasantly surprised. You press the **Super** key (for me, it's the key with the Windows logo—which I should cover with a sticker!) and then a modifier key. For example, pressing **Super+Left** moves your current window to a tile on the left side of the screen. **Super+Right** moves to the right half. **Super+Up** maximizes the current window. **Super+Down** reverts to the previous size. You can move between app windows with **Alt+Tab**. This is all default behavior and can be customized in the Keyboard settings.
Plugging in headphones or connecting to HDMI works the way you expect. Sometimes, I open the Sound settings to switch between the HDMI sound output or my external audio cable, just as I would on a Mac or PC. The trackpad is responsive, and I haven't noticed any difference from the Macbook's. When I plug in a three-button mouse, it works instantly, even with my Bluetooth mouse and keyboard.
### Software
I installed Atom, VLC, Keybase, Brave Browser, Krita, Blender, and Thunderbird in a matter of minutes. I installed other software with the Apt package manager in the terminal (as normal), which offers many more packages than the Homebrew package manager for macOS.
### Music
I have a variety of options for listening to music. I use Spotify and [PyRadio][10] to stream music. [Rhythmbox][11] is installed by default on Ubuntu; the simple music player launches instantly and without any bloat. Simply click on the menu, choose **Add Music**, and navigate to a directory of audio tracks (it searches recursively). You can also stream podcasts or online radio easily.
### Text and PDFs
I tend to write in Markdown in [Neovim][12] with some plugins, then convert my document using Pandoc to whatever final format is needed. For a nice Markdown editor with preview, I downloaded [Ghostwriter][13], a minimal-focus writing application.
If someone sends me a Microsoft Word document, I can open it using the default LibreOffice Writer application.
Occasionally, I have to sign a document. This is easy with macOS's Preview application and my signature in PNG format, and I needed a Linux equivalent. I found that the default PDF viewer app didn't have the annotation tools I needed. The LibreOffice Draw program was acceptable but not particularly easy to use, and it occasionally crashed. Based on some research, I installed [Xournal][14], which has the simple annotation tools I need to add dates, text, and my signature and is fairly comparable to Mac's Preview app. It works exactly as needed.
### Importing images from my phone
I have an iPhone. To get my images off the phone, there are a number of methods to sync and access your files. If you have a different phone, your process may be different. Here's my method:
1. Install gvfs-backends with **sudo apt install gvfs-backends**, which is part of the GNO

View File

@ -1,236 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (What happens when you update your DNS?)
[#]: via: (https://jvns.ca/blog/how-updating-dns-works/)
[#]: author: (Julia Evans https://jvns.ca/)
What happens when you update your DNS?
======
Ive seen a lot of people get confused about updating their sites DNS records to change the IP address. Why is it slow? Do you really have to wait 2 days for everything to update? Why do some people see the new IP and some people see the old IP? Whats happening?
So I wanted to write a quick exploration of whats happening behind the scenes when you update a DNS record.
### how DNS works: recursive vs authoritative DNS servers
First, we need to explain a little bit about DNS. There are 2 kinds of DNS servers: **authoritative** and **recursive**.
**authoritative** DNS servers (also known as **nameservers**) have a database of IP addresses for each domain theyre responsible for. For example, right now an authoritative DNS server for github.com is ns-421.awsdns-52.com. You can ask it for github.coms IP like this;
```
dig @ns-421.awsdns-52.com github.com
```
**recursive** DNS servers, by themselves, dont know anything about who owns what IP address. They figure out the IP address for a domain by asking the right authoritative DNS servers, and then cache that IP address in case theyre asked again. 8.8.8.8 is a recursive DNS server.
When people visit your website, theyre probably making their DNS queries to a recursive DNS server. So, how do recursive DNS servers work? Lets see!
### how does a recursive DNS server query for github.com?
Lets go through an example of what a recursive DNS server (like 8.8.8.8) does when you ask it for an IP address (A record) for github.com. First if it already has something cached, itll give you what it has cached. But what if all of its caches are expired? Heres what happens:
**step 1**: it has IP addresses for the root DNS servers hardcoded in its source code. You can see this in [unbounds source code here][1]. Lets say it picks `198.41.0.4` to start with. Heres the [official source][2] for those hardcoded IP addresses, also known as a “root hints file”.
**step 2**: Ask the root nameservers about `github.com`.
We can roughly reproduce what happens with `dig`. What this gives us is a new authoritative nameserver to ask: a nameserver for `.com`, with the IP `192.5.6.30`.
```
$ dig @198.41.0.4 github.com
...
com. 172800 IN NS a.gtld-servers.net.
...
a.gtld-servers.net. 172800 IN A 192.5.6.30
...
```
The details of the DNS response are a little more complicated than that in this case, theres an authority section with some NS records and an additional section with A records so you dont need to do an extra lookup to get the IP addresses of those nameservers.
(in practice, 99.99% of the time itll already have the address of the `.com` nameservers cached, but were pretending were really starting from scratch)
**step 3**: Ask the `.com` nameservers about `github.com`.
```
$ dig @192.5.6.30 github.com
...
github.com. 172800 IN NS ns-421.awsdns-52.com.
ns-421.awsdns-52.com. 172800 IN A 205.251.193.165
...
```
We have a new IP address to ask! This one is the nameserver for `github.com`.
**step 4**: Ask the `github.com` nameservers about `github.com`.
Were almost done!
```
$ dig @205.251.193.165 github.com
github.com. 60 IN A 140.82.112.4
```
Hooray!! We have an `A` record for `github.com`! Now the recursive nameserver has `github.com`s IP address and can return it back to you. And it could do all of this by only hardcoding a few IP addresses: the addresses of the root nameservers.
### how to see all of a recursive DNS servers steps: `dig +trace`
When I want to see what a recursive DNS server would do when resolving a domain, I run
```
$ dig @8.8.8.8 +trace github.com
```
This shows all the DNS records that it requests, starting at the root DNS servers all the 4 steps that we just went through.
### lets update some DNS records!
Now that we know the basics of how DNS works, lets update some DNS records and see what happens.
When you update your DNS records, there are two main options:
1. keep the same nameservers
2. change nameservers
### lets talk about TTLs
Weve forgotten something important though! TTLs! You know how we said earlier that the recursive DNS server will cache records until they expire? The way it decides whether the record should expire is by looking at its **TTL** or “time to live”.
In this example, the TTL for the A record githubs nameserver returns for its DNS record is `60`, which means 60 seconds:
```
$ dig @205.251.193.165 github.com
github.com. 60 IN A 140.82.112.4
```
Thats a pretty short TTL, and _in theory_ if everybodys DNS implementation followed the [DNS standard][3] it means that if Github decided to change the IP address for `github.com`, everyone should get the new IP address within 60 seconds. Lets see how that plays out in practice
### option 1: update a DNS record on the same nameservers
First, I updated my nameservers (Cloudflare) to have a new DNS record: an A record that maps `test.jvns.ca` to `1.2.3.4`.
```
$ dig @8.8.8.8 test.jvns.ca
test.jvns.ca. 299 IN A 1.2.3.4
```
This worked immediately! There was no need to wait at all, because there was no `test.jvns.ca` DNS record before that could have been cached. Great. But it looks like the new record is cached for ~5 minutes (299 seconds).
So, what if we try to change that IP? I changed it to `5.6.7.8`, and then ran the same DNS query.
```
$ dig @8.8.8.8 test.jvns.ca
test.jvns.ca. 144 IN A 1.2.3.4
```
Hmm, it seems like that DNS server has the `1.2.3.4` record still cached for another 144 seconds. Interestingly, if I query `8.8.8.8` multiple times I actually get inconsistent results sometimes itll give me the new IP and sometimes the old IP, I guess because 8.8.8.8 actually load balances to a bunch of different backends which each have their own cache.
After I waited 5 minutes, all of the `8.8.8.8` caches had updated and were always returning the new `5.6.7.8` record. Awesome. That was pretty fast!
### you cant always rely on the TTL
As with most internet protocols, not everything obeys the DNS specification. Some ISP DNS servers will cache records for longer than the TTL specifies, like maybe for 2 days instead of 5 minutes. And people can always hardcode the old IP address in their /etc/hosts.
What Id expect to happen in practice when updating a DNS record with a 5 minute TTL is that a large percentage of clients will move over to the new IPs quickly (like within 15 minutes), and then there will be a bunch of stragglers that slowly update over the next few days.
### option 2: updating your nameservers
So weve seen that when you update an IP address without changing your nameservers, a lot of DNS servers will pick up the new IP pretty quickly. Great. But what happens if you change your nameservers? Lets try it!
I didnt want to update the nameservers for my blog, so instead I went with a different domain I own and use in the examples for the [HTTP zine][4]: `examplecat.com`.
Previously, my nameservers were set to dns1.p01.nsone.net. I decided to switch them over to Googles nameservers `ns-cloud-b1.googledomains.com` etc.
When I made the change, my domain registrar somewhat ominiously popped up the message “Changes to examplecat.com saved. Theyll take effect within the next 48 hours”. Then I set up a new A record for the domain, to make it point to `1.2.3.4`
Okay, lets see if that did anything
```
$ dig @8.8.8.8 examplecat.com
examplecat.com. 17 IN A 104.248.50.87
```
No change. If I ask a different DNS server, it knows the new IP:
```
$ dig @1.1.1.1 examplecat.com
examplecat.com. 299 IN A 1.2.3.4
```
but 8.8.8.8 is still clueless. The reason 1.1.1.1 sees the new IP even though I just changed it 5 minutes ago is presumably that nobody had ever queried 1.1.1.1 about examplecat.com before, so it had nothing in its cache.
### nameserver TTLs are much longer
The reason that my registrar was saying “THIS WILL TAKE 48 HOURS” is that the TTLs on NS records (which are how recursive nameservers know which nameserver to ask) are MUCH longer!
The new nameserver is definitely returning the new IP address for `examplecat.com`
```
$ dig @ns-cloud-b1.googledomains.com examplecat.com
examplecat.com. 300 IN A 1.2.3.4
```
But remember what happened when we queried for the `github.com` nameservers, way back?
```
$ dig @192.5.6.30 github.com
...
github.com. 172800 IN NS ns-421.awsdns-52.com.
ns-421.awsdns-52.com. 172800 IN A 205.251.193.165
...
```
172800 seconds is 48 hours! So nameserver updates will in general take a lot longer to expire from caches and propagate than just updating an IP address without changing your nameserver.
### how do your nameservers get updated?
When I update the nameservers for `examplecat.com`, what happens is that he `.com` nameserver gets a new `NS` record with the new domain. Like this:
```
dig ns @j.gtld-servers.net examplecat.com
examplecat.com. 172800 IN NS ns-cloud-b1.googledomains.com
```
But how does that new NS record get there? What happens is that I tell my **domain registrar** what I want the new nameservers to be by updating it on the website, and then my domain registrar tells the `.com` nameservers to make the update.
For `.com`, these updates happen pretty fast (within a few minutes), but I think for some other TLDs the TLD nameservers might not apply updates as quickly.
### your programs DNS resolver library might also cache DNS records
One more reason TTLs might not be respected in practice: many programs need to resolve DNS names, and some programs will also cache DNS records indefinitely in memory (until the program is restarted).
For example, AWS has an article on [Setting the JVM TTL for DNS Name Lookups][5]. I havent written that much JVM code that does DNS lookups myself, but from a little Googling about the JVM and DNS it seems like you can configure the JVM so that it caches every DNS lookup indefinitely. (like [this elasticsearch issue][6])
### thats all!
I hope this helps you understand whats going on when updating your DNS!
As a disclaimer, again TTLs definitely dont tell the whole story about DNS propagation some recursive DNS servers definitely dont respect TTLs, even if the major ones like 8.8.8.8 do. So even if youre just updating an A record with a short TTL, its very possible that in practice youll still get some requests to the old IP for a day or two.
Also, I changed the nameservers for `examplecat.com` back to their old values after publishing this post.
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/how-updating-dns-works/
作者:[Julia Evans][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://jvns.ca/
[b]: https://github.com/lujun9972
[1]: https://github.com/NLnetLabs/unbound/blob/6e0756e819779d9cc2a14741b501cadffe446c93/iterator/iter_hints.c#L131
[2]: https://www.iana.org/domains/root/files
[3]: https://tools.ietf.org/html/rfc1035
[4]: https://wizardzines.com/zines/http/
[5]: https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-jvm-ttl.html
[6]: https://github.com/elastic/elasticsearch/issues/16412

View File

@ -1,359 +0,0 @@
[#]: subject: "D Declarations for C and C++ Programmers"
[#]: via: "https://theartofmachinery.com/2020/08/18/d_declarations_for_c_programmers.html"
[#]: author: "Simon Arneaud https://theartofmachinery.com"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
D Declarations for C and C++ Programmers
======
Because D was originally created by a C++ compiler writer, Walter Bright, [its an easy language for C and C++ programmers to learn][1], but there are little differences in the way declarations work. I learned them piecemeal in different places, but Im going to dump a bunch in this one post.
### `char* p`
If you want to declare a pointer in C, both of the following work:
```
char *p;
char* p;
```
Some people prefer the second form because it puts all the type information to one side. At least, thats what it looks like. Trouble is, you can fall into this trap:
```
char* p, q; // Gotcha! p is a pointer to a char, and q is a char in C
```
“Type information on the left” isnt really how C works. D, on the other hand, _does_ put all the type information to the left, so this works the way it appears:
```
char* p, q; // Both p and q are of type char* in D
```
D also accepts the `char *p` syntax, but the rule I go by is `char *p` when writing C, and `char* p` when writing D, just because that matches how the languages actually work, so no gotchas.
### Digression: how C declarations work
This isnt about D, but helps to make sense of the subtler differences between C and D declarations.
C declarations are implicit about types. `char *p` doesnt really say, “`p` is of type `char*`”; it says “the type of `p` is such that `*p` evaluates to a `char`”. Likewise:
```
int a[8]; // a[i] evaluates to an int (=> a is an array of ints)
int (*f)(double); // (*f)(0.5) evaluates to an int (=> f is a pointer to a function taking a double, returning an int)
```
Theres a kind of theoretical elegance to this implicit approach, but 1) its backwards and makes complex types confusing, 2) the theoretical elegance only goes so far because everythings a special case. For example, `int a[8];` declares an array `a`, but makes the expression `a[8]` undefined. You can only use certain operations, so `int 2*a;` doesnt work, and neither does `double 1.0 + sin(x);`. The expression `4[a]` is equivalent to `a[4]`, but you cant declare an array with `int 4[a];`. C++ gave up on the theory when it introduced reference syntax like `int &x;`.
### `function` and `delegate`
D has a special `function` keyword for declaring function pointers using the “type information on the left” approach. It makes the declaration of function pointers use the same syntax as the declaration of a function:
```
int foo();
int[] bar();
int function() foo_p = &foo;
int[] function() bar_p = &bar;
```
Note that the `&` is _required_ to get the address of a function in D (unlike in C and C++). If you want to have an array of pointers, you just add `[]` to the end of the type, just like you do with any other type. Similarly for making pointers to types:
```
int function()[] foo_pa = [&foo];
int function()* foo_pp = &foo_p;
int function()[]* foo_pap = &foo_pa;
```
Heres the C equivalent for comparison:
```
int (*foo_p)() = &foo;
int (*foo_pa[])() = {&foo};
int (**foo_pp)() = &foo_p;
int (*(*foo_pap)[])() = &foo_pa;
```
Its rare to need these complicated types, but the logic for the D declarations is much simpler.
Theres also the `delegate` keyword, which works in exactly the same way for [“fat function pointers”][2].
### Arrays
The most obvious difference from C is that D uses the “type information on the left” approach:
```
// int a[8]; is an error in D
int[8] a;
```
Another difference is in the order of indices for multidimensional arrays. E.g., this C code:
```
int a[4][64];
```
translates to this in D:
```
int[64][4] a;
```
Heres the rule for understanding the D ordering:
```
T[4] a;
static assert (is(typeof(a[0]) == T));
```
If `T` represents a type, then `T[4]` is always an array of 4 `T`s. Sounds obvious, but it means that if `T` is `int[64]`, `int[64][4]` must be an array of 4 `int[64]`s.
### `auto`
C had `auto` as a storage class keyword since the early days, but it got mostly forgotten because its only allowed in the one place its the default, anyway. (It effectively means “this variable goes on the stack”.) C++ repurposed the keyword to enable automatic type deduction.
You can also use `auto` with automatic type deduction in D, but its not actually required. Type deduction is always enabled in D; you just need to make your declaration unambiguously a declaration. For example, these work in D (but not all in C++):
```
auto x1 = 42;
const x2 = 42;
static x3 = 42;
```
### No need for forward declarations at global scope
This code works:
```
// Legal, but not required in D
// void bar();
void foo()
{
bar();
}
void bar()
{
// ...
}
```
Similarly for structs and classes. Order of definition doesnt matter, and forward declarations arent required.
Order does matter in local scope, though:
```
void foo()
{
// Error!
bar();
void bar()
{
// ...
}
}
```
Either the definition of `bar()` needs to be put before its usage, or `bar()` needs a forward declaration.
### `const()`
The `const` keyword in C declarations can be confusing. (Think `const int *p` vs `int const *p` vs `const int const *p`.) D supports the same syntax, but also allows `const` with parentheses:
```
// non-constant pointer to constant int
const(int)* p1;
// constant pointer to constant int
const(int*) p2;
```
[`const` is transitive in D][3], anyway, and this syntax makes it much clearer. The same parenthetical syntax works with `immutable`, too. Although C-style syntax is supported by D, I always prefer the parenthetical style for a few more reasons.
### `ref`
`ref` is the D alternative to C++s references. In D, `ref` doesnt create a new type, it just controls how the instance of the type is stored in memory (i.e, its a storage class). C++ acts as if references are types, but references have so many special restrictions that theyre effectively like a complex version of a storage class (in Walters words, C++ references try to be both a floor wax and dessert topping). For example, C++ treats `int&` like a type, but forbids declaring an array of `int&`.
As a former C++ programmer, I used to write D function arguments like this:
```
void foo(const ref S s);
```
Now I write them like this:
```
void foo(ref const(S) s);
```
The difference becomes more obvious with more complex types. Treating `ref` like a storage class ends up being cleaner because thats the way it actually is in D.
Currently `ref` is only supported with function arguments or `foreach` loop variables, so you cant declare a regular local variable to be `ref`.
### Function qualifiers
Ds backward-compatible support for the C-style `const` keyword creates an unfortunate gotcha:
```
struct S
{
// Confusing!
const int* foo()
{
// ...
}
}
```
`foo()` doesnt return a `const int*`. The `const` applies to the `foo()` member function itself, meaning that it works on `const` instances of `S` and returns a (non-`const`) `int*`. To avoid that trap, I always use the D-style `const()` syntax, and write member function qualifiers on the right:
```
struct S
{
const(int)* foo()
{
// ...
}
int* bar() const
{
// ...
}
}
```
### Syntax ambiguities
C++ allows initialising struct and class instances without an `=` sign:
```
S s(42);
```
This syntax famously leads to ambiguities with function declaration syntax in special cases (Scott Meyers “most vexing parse”). [People like Herb Sutter have written enough about it.][4] D only supports initialisation with `=`:
```
S s = S(42);
// Alternatively:
auto s = S(42);
```
C syntax has some weird corners, too. Heres a simple one:
```
x*y;
```
That looks like a useless multiplication between two variables, but logically it could be a declaration of `y` as a pointer to a type `x`. Expression and declaration are totally different parses that depend on what the symbol `x` means in this scope. (Even worse, if its a declaration, then the new `y` could shadow an existing `y`, which could affect later parses.) So C compilers need to track symbols in a symbol table while parsing, which is why C has forward declarations in practice.
D sidesteps the ambiguity by requiring a typecast to `void` if you really want to write an arithmetic expression without assigning it to anything:
```
int x, y;
cast(void)(x*y);
```
Ive never seen useful code do that, but that rule helps D parse simply without forward declarations.
Heres another quirk of C syntax. Remember that C declarations work by having a basic type on the left, followed by expressions that evaluate to that type? C allows parentheses in those expressions, and doesnt care about whitespace as long as symbols dont run together. That means these two declarations are equivalent:
```
int x;
int(x);
```
But what if, instead of `int`, we use some symbol that might be a typedef?
```
// Is this a declaration of x, or a function call?
t(x);
```
Just for fun, we can exploit shadowing and Cs archaic type rules:
```
typedef (*x)();
main()
{
x(x);
x(x);
}
```
The first line makes `x` a typedef to a function pointer type. The first `x(x);` redeclares `x` to be a function pointer variable, shadowing the typedef. The second `x(x);` is a function call that passes `x` as an argument. Yes, this code actually compiles, but its undefined behaviour because the function pointer is dereferenced without being initialised.
D avoids this chaos thanks to its “all type information on the left” rule. Theres no need to put parentheses around symbols in declarations, so `x(y);` is always a function call.
--------------------------------------------------------------------------------
via: https://theartofmachinery.com/2020/08/18/d_declarations_for_c_programmers.html
作者:[Simon Arneaud][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://theartofmachinery.com
[b]: https://github.com/lujun9972
[1]: https://ddili.org/ders/d.en/index.html
[2]: https://tour.dlang.org/tour/en/basics/delegates
[3]: https://dlang.org/articles/const-faq.html#transitive-const
[4]: https://herbsutter.com/2013/05/09/gotw-1-solution/

View File

@ -1,120 +0,0 @@
[#]: subject: "Robust and Race-free Server Logging using Named Pipes"
[#]: via: "https://theartofmachinery.com/2020/10/10/logging_with_named_pipes.html"
[#]: author: "Simon Arneaud https://theartofmachinery.com"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Robust and Race-free Server Logging using Named Pipes
======
If you do any server administration work, youll have worked with log files. And if your servers need to be reliable, youll know that log files are common source of problems, especially when you need to rotate or ship them (which is practically always). In particular, moving files around causes race conditions.
Thankfully, there are better ways. With named pipes, you can have a simple and robust logging stack, with no race conditions, and without patching your servers to support some network logging protocol.
### The problems with rotating log files
First, lets talk about the problems. Race conditions are generally a problem with popular file-based logging setups, whether youre rotating logs into archival storage, or shipping them to a remote log processing stack, or whatever. To keep things concrete, though, let me talk about [logrotate][1], just because its a popular tool.
Say you have a log file at `/var/log/foo`. It gets pretty big, and you want to process the logs periodically and start with a new, empty file. So you (or your distro maintainers) set up logrotate with various rules about when to rotate the file.
By default, logrotate will rename the file (to something like `/var/log/foo.1`) and create a new `/var/log/foo` to write to. That (mostly) works for software that runs intermittently (such as a package manager that does software updates). But it wont do any good if the log file is generated by a long-running server. The server only uses the filename when it opens the file; after that it just keeps writing to its open file descriptor. That means it will keep writing to the old file (now named `/var/log/foo.1`), and the new `/var/log/foo` file will stay empty.
To handle this use-case, logrotate supports another mode: `copytruncate`. In this mode, instead of renaming, logrotate will copy the contents of `/var/log/foo` to an archival file, and then truncate the original file to zero length. As long as the server has the log file open in append mode, it will automatically write new logs to the start of the file, without needing to detect the truncation and do a file seek (the kernel handles that).
That `copytruncate` mode creates a race condition, though. Any log lines that are written after the copy but before the truncation will get destroyed. Actually, you tend to get the same race condition even with the default move-and-create mode. Thats because theres not much point just splitting up the logs into multiple files. Most systems are configured to do something like compress the old log file, but ultimately you need to delete the old, uncompressed data, which creates the same race as truncating. (In practice, this race isnt so likely for occasional log writers, like package managers, and the `delay` flag to logrotate makes it rarer, albeit by making the log handling a bit more complicated.)
Some servers, like [Nginx][2], support a modification of the default logrotate mode:
1. Rename the old file
2. Create the new file
3. (New step) notify the server that it needs to reopen its log file.
This works (as long as the logs processor doesnt delete the old file before the server has finished reopening), but it requires special support from the server, and youre out of luck with most software. Theres a lot of software out there, and log file handling just isnt interesting enough to get high on the to-do list. This approach also only works for long-running servers.
I think this is a good point to stop and take a step back. Having multiple processes juggle log files around on disk without any synchronisation is just an inherently painful way to do things. It causes bugs and makes logging stacks complicated ([heres just one of many examples][3]). One alternative is to use some network protocol like MQTT or networked syslog, but, realistically, most servers wont support the one you want. And they shouldnt have to — log files are a great interface for log writers.
Thats okay because *nix “everything is a file” lets us easily get a file interface on the writer side, with a streaming interface on the reader side.
### Named pipes 101
Maybe youve seen pipes in pipelines like this:
```
$ sort user_log.txt | uniq
```
The pipe connecting `sort` and `uniq` is a temporary, anonymous communication channel that `sort` writes to and `uniq` reads from. Named pipes are less common, but theyre also communication channels. The only difference is that they persist on the filesystem as if they were files.
Open up a terminal and `cd` into some temporary working directory. The following creates a named pipe and uses `cat` to open a writer:
```
$ mkfifo p
$ # This cat command will sit waiting for input
$ cat > p
```
Leave that `cat` command waiting, and open up another terminal in the same directory. In this terminal, start your reader:
```
$ # This will sit waiting for data to come over the pipe
$ cat p
```
Now as you type things into the writer end, youll see them appear in the reader end. `cat` will use line buffering in interactive mode, so data will get transferred every time you start a new line.
`cat` doesnt have to know anything about pipes for this to work — the pipe acts like a file as long as you just naïvely read or write to it. But if you check, youll see the data isnt stored anywhere. You can pump gigabytes through a pipe without filling up any disk space. Once the data has been read once, its lost. (You can have multiple readers, but only one will receive any buffer-load of data.)
Another thing that makes pipes useful for communication is their buffering and blocking. You can start writing before any readers open the pipe, and data gets temporarily buffered inside the kernel until a reader comes along. If the reader starts first, its read will block, waiting for data from the writer. (The writer will also block if the pipe buffer gets full.) If you try the two-terminal experiment again with a regular file, youll see that the reader `cat` will eagerly read all the data it can and then exit.
### An annoying problem and a simple solution
Maybe youre seeing how named pipes can help with logging: Servers can write to log “files” that are actually named pipes, and a logging stack can read log data directly from the named pipe without letting a single line fall onto the floor. You do whatever you want with the logs, without any racey juggling of files on disk.
Theres one annoying problem: the writer doesnt need a reader to start writing, but if a reader opens the pipe and then closes it, the writer gets a `SIGPIPE` (“broken pipe”), which will kill it by default. (Try killing the reader `cat` while typing things into the writer to see what I mean.) Similarly, a reader can read without a writer, but if a writer opens the pipe and then closes it, that will be treated like an end of file. Although the named pipe persists on disk, it isnt a stable communication channel if log writers and log readers can restart (as they will on a real server).
Theres a solution thats a bit weird but very simple. Multiple processes can open the pipe for reading and writing, and the pipe will only close when _all_ readers or _all_ writers close it. All we need for a stable logging pipe is a daemon that holds the named pipe open for both reading and writing, without doing any actual reading or writing. I set this up on my personal server last year, and I wrote [a tiny, zero-config program to act as my pipe-holding daemon][4]. It just opens every file in its current working directory for both reading and writing. I run it from a directory that has symbolic links to every named pipe in my logging stack. The program runs in a loop that ends in a `wait()` for a `SIGHUP`. If I ever update the symlinks in the directory, I give the daemon a `kill -HUP` and it reopens them all. Sure, it could do its own directory watching, but the `SIGHUP` approach is simple and predictable, and the whole thing works reliably. Thanks to the pipe buffer, log writers and log readers can be shut down and restarted independently, any time, without breakage.
My server uses the [s6 supervision suite][5] to manage daemons, so I have s6-log reading from each logging pipe. The bottom part of the [s6-log documentation page][6] has some good insights into the problems with popular logging systems, and good ideas about better ways to do things.
### Imagine: a world without log rotation
Strictly speaking, named pipes arent necessary for race-free logs processing. The s6 suite encourages writing logs to some file descriptor (like standard error), and letting the supervision suite make sure those file descriptors point to something useful. However, the named pipe approach adds a few benefits:
* It doesnt require any co-ordination between writer and reader
* It integrates nicely with the software we have today
* It gives things meaningful names (rather than `/dev/fd/4`)
Ive worked with companies that spend about as much on their logging stacks as on their serving infrastructure, and, no, “we do logs processing” isnt in their business models. Of course, log rotation and log shipping arent the only problems to blame, but it feels so wrong that weve made logs so complicated. If you work on any logging system, consider if you really need to juggle log files around. You could be helping to make the world a better place.
--------------------------------------------------------------------------------
via: https://theartofmachinery.com/2020/10/10/logging_with_named_pipes.html
作者:[Simon Arneaud][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://theartofmachinery.com
[b]: https://github.com/lujun9972
[1]: https://github.com/logrotate/logrotate
[2]: https://www.nginx.com/resources/wiki/start/topics/examples/logrotation/
[3]: https://community.splunk.com/t5/Getting-Data-In/Why-copytruncate-logrotate-does-not-play-well-with-splunk/td-p/196112
[4]: https://gitlab.com/sarneaud/fileopenerd
[5]: http://www.skarnet.org/software/s6/index.html
[6]: http://www.skarnet.org/software/s6/s6-log.html

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (hwlife )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,167 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (amagicbowboy)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (How to Uninstall Applications from Ubuntu Linux)
[#]: via: (https://itsfoss.com/uninstall-programs-ubuntu/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
How to Uninstall Applications from Ubuntu Linux
======
Dont use a certain application anymore? Remove it.
In fact, removing programs is one of the [easiest ways to free up disk space on Ubuntu][1] and keep your system clean.
In this beginners tutorial, Ill show you various ways of uninstalling software from Ubuntu.
Did I say various ways? Yes, because there are [various ways of installing applications in Ubuntu][2] and hence various ways of removing them. Youll learn to:
* Remove applications from Ubuntu Software Center (for desktop users)
* Remove applications using apt remove command
* Remove snap applications in command line (intermediate to advanced users)
Lets see these steps one by one.
### Method 1: Remove applications using Ubuntu Software Center
Start the Software Center application. You should find it in the dock on the left side or search for it in the menu.
![][3]
You can see the installed applications in the Installed tab.
![List installed applications][4]
If you dont see a program here, try to use the search feature.
![Search for installed applications][5]
When you open an installed application, you should see the option to remove it. Click on it.
![Removing installed applications][6]
It will ask for your account password. Enter it and the applications will be removed in seconds.
This method works pretty well except in the case when Software Center is misbehaving (it does that a lot) or if the program is a software library or some other command line utility. You can always resort to the terminal in such cases.
### Method 2: Remove programs from Ubuntu using command line
You know that you can use `apt-get install` or `apt install` for installing applications. For uninstalling, you dont use the apt-get uninstall command but `apt-get remove` or `apt remove`.
All you need to do is to use the command in the following fashion:
```
sudo apt remove program_name
```
Youll be asked to enter your account password. When you enter it, nothing is visible on the screen. Thats normal. Just type it blindly and press enter.
The program wont be removed immediately. You need to confirm it. When it asks for your conformation, press the enter key or Y key:
![][7]
Keep in mind that youll have to use the exact package name in the apt remove command otherwise it will throw [unable to locate package error][8].
Dont worry if you dont remember the exact program name. You can utilize the super useful tab completion. Its one of the [most useful Linux command line tips][9] that you must know.
What you can do is to type the first few letters of the program you want to uninstall. And then hit the tab key. It will show all the installed packages that match those letters at the beginning of their names.
When you see the desired package, you can type its complete name and remove it.
![][10]
What if you do not know the exact package name or even the starting letters? Well, you can [list all the installed packages in Ubuntu][11] and grep with whatever your memory serves.
For example, the command below will show all the installed packages that have the string my in its name anywhere, not just the beginning.
```
apt list --installed | grep -i my
```
![][12]
Thats cool, isnt it? Just be careful with the package name when using the remove command in Ubuntu.
#### Tip: Using apt purge for removing package (advanced users)
When you remove a package in Ubuntu, the packaged data is removed, but it may leave small, modified user configuration files. This is intentional because if you install the same program again, it would use those configuration files.
If you want to remove it completely, you can use apt purge command. You can use it instead of apt remove command or after running the apt remove command.
```
sudo apt purge program_name
```
Keep in mind that the purge command wont remove any data or configuration file stored in the home directory of a user.
### Method 3: Uninstall Snap applications in Ubuntu
The previous method works with the DEB packages that you installed using apt command, software center or directly from the deb file.
Ubuntu also has a new packaging system called [Snap][13]. Most of the software you find in the Ubuntu Software Center are in this Snap package format.
You can remove these applications from the Ubuntu Software Center easily but if you want to use the command line, heres what you should do.
List all the snap applications installed to get the package name.
```
snap list
```
![][14]
Now use the package name to remove the application from Ubuntu. You wont be asked for confirmation before removal.
```
sudo snap remove package_name
```
### Bonus Tip: Clean up your system with one magical command
Alright! You learned to remove the applications. Now let me tell you about a simple command that cleans up leftover package traces like dependencies that are no longer used, old Linux kernel headers that wont be used anymore.
In the terminal, just run this command:
```
sudo apt autoremove
```
This is a safe command, and it will easily free up a few hundred MBs of disk space.
### Conclusion
You learned three ways of removing applications from Ubuntu Linux. I covered both GUI and command line methods so that you are aware of all the options.
I hope you find this simple tutorial helpful as an Ubuntu beginner. Questions and suggestions are always welcome.
--------------------------------------------------------------------------------
via: https://itsfoss.com/uninstall-programs-ubuntu/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/free-up-space-ubuntu-linux/
[2]: https://itsfoss.com/remove-install-software-ubuntu/
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/06/ubuntu_software_applications_menu.jpg?resize=800%2C390&ssl=1
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/installed-apps-ubuntu.png?resize=800%2C455&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/search-installed-apps-ubuntu.png?resize=800%2C455&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/remove-applications-ubuntu.png?resize=800%2C487&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/01/apt-remove-program-ubuntu.png?resize=768%2C424&ssl=1
[8]: https://itsfoss.com/unable-to-locate-package-error-ubuntu/
[9]: https://itsfoss.com/linux-command-tricks/
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/remove-package-ubuntu-linux.png?resize=768%2C424&ssl=1
[11]: https://itsfoss.com/list-installed-packages-ubuntu/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/01/search-list-installed-apps-ubuntu.png?resize=768%2C424&ssl=1
[13]: https://itsfoss.com/install-snap-linux/
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/01/list-snap-remove.png?resize=800%2C407&ssl=1

View File

@ -1,286 +0,0 @@
[#]: subject: (Use awk to calculate letter frequency)
[#]: via: (https://opensource.com/article/21/4/gawk-letter-game)
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
Use awk to calculate letter frequency
======
Write an awk script to determine the most (and least) common letters in
a set of words.
![Typewriter keys in multicolor][1]
I recently started writing a game where you build words using letter tiles. To create the game, I needed to know the frequency of letters across regular words in the English language, so I could present a useful set of letter tiles. Letter frequency is discussed in various places, including [on Wikipedia][2], but I wanted to calculate the letter frequency myself.
Linux provides a list of words in the `/usr/share/dict/words` file, so I already have a list of likely words to use. The `words` file contains lots of words that I want, but a few that I don't. I wanted a list of all words that weren't compound words (no hyphens or spaces) or proper nouns (no uppercase letters). To get that list, I can run the `grep` command to pull out only the lines that consist solely of lowercase letters:
```
`$ grep  '^[a-z]*$' /usr/share/dict/words`
```
This regular expression asks `grep` to match patterns that are only lowercase letters. The characters `^` and `$` in the pattern represent the start and end of the line, respectively. The `[a-z]` grouping will match only the lowercase letters **a** to **z**.
Here's a quick sample of the output:
```
$ grep  '^[a-z]*$' /usr/share/dict/words | head
a
aa
aaa
aah
aahed
aahing
aahs
aal
aalii
aaliis
```
And yes, those are all valid words. For example, "aahed" is the past tense exclamation of "aah," as in relaxation. And an "aalii" is a bushy tropical shrub.
Now I just need to write a `gawk` script to do the work of counting the letters in each word, and then print the relative frequency of each letter it finds.
### Counting letters
One way to count letters in `gawk` is to iterate through each character in each input line and count occurrences of each letter **a** to **z**. The `substr` function will return a substring of a given length, such as a single letter, from a larger string. For example, this code example will evaluate each character `c` from the input:
```
{
    len = length($0); for (i = 1; i &lt;= len; i++) {
        c = substr($0, i, 1);
    }
}
```
If I start with a global string `LETTERS` that contains the alphabet, I can use the `index` function to find the location of a single letter in the alphabet. I'll expand the `gawk` code example to evaluate only the letters **a** to **z** in the input:
```
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i &lt;= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
    }
}
```
Note that the index function returns the first occurrence of the letter from the `LETTERS` string, starting with 1 at the first letter, or zero if not found. If I have an array that is 26 elements long, I can use the array to count the occurrences of each letter. I'll add this to my code example to increment (using `++`) the count for each letter as it appears in the input:
```
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i &lt;= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr &gt; 0) {
            ++count[ltr];
        }
    }
}
```
### Printing relative frequency
After the `gawk` script counts all the letters, I want to print the frequency of each letter it finds. I am not interested in the total number of each letter from the input, but rather the _relative frequency_ of each letter. The relative frequency scales the counts so that the letter with the fewest occurrences (such as the letter **q**) is set to 1, and other letters are relative to that.
I'll start with the count for the letter **a**, then compare that value to the counts for each of the other letters **b** to **z**:
```
END {
    min = count[1]; for (ltr = 2; ltr &lt;= 26; ltr++) {
        if (count[ltr] &lt; min) {
            min = count[ltr];
        }
    }
}
```
At the end of that loop, the variable `min` contains the minimum count for any letter. I can use that to provide a scale for the counts to print the relative frequency of each letter. For example, if the letter with the lowest occurrence is **q**, then `min` will be equal to the **q** count.
Then I loop through each letter and print it with its relative frequency. I divide each count by `min` to print the relative frequency, which means the letter with the lowest count will be printed with a relative frequency of 1. If another letter appears twice as often as the lowest count, that letter will have a relative frequency of 2. I'm only interested in integer values here, so 2.1 and 2.9 are the same as 2 for my purposes:
```
END {
    min = count[1]; for (ltr = 2; ltr &lt;= 26; ltr++) {
        if (count[ltr] &lt; min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr &lt;= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}
```
### Putting it all together
Now I have a `gawk` script that can count the relative frequency of letters in its input:
```
#!/usr/bin/gawk -f
 
# only count a-z, ignore A-Z and any other characters
 
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i &lt;= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr &gt; 0) {
            ++count[ltr];
        }
    }
}
 
# print relative frequency of each letter
   
END {
    min = count[1]; for (ltr = 2; ltr &lt;= 26; ltr++) {
        if (count[ltr] &lt; min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr &lt;= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}
```
I'll save that to a file called `letter-freq.awk` so that I can use it more easily from the command line.
If you prefer, you can also use `chmod +x` to make the file executable on its own. The `#!/usr/bin/gawk -f` on the first line means Linux will run it as a script using the `/usr/bin/gawk` program. And because the `gawk` command line uses `-f` to indicate which file it should use as a script, you need that hanging `-f` so that executing `letter-freq.awk` at the shell will be properly interpreted as running `/usr/bin/gawk -f letter-freq.awk` instead.
I can test the script with a few simple inputs. For example, if I feed the alphabet into my `gawk` script, each letter should have a relative frequency of 1:
```
$ echo abcdefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1
```
Repeating that example but adding an extra instance of the letter **e** will print the letter **e** with a relative frequency of 2 and every other letter as 1:
```
$ echo abcdeefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 2
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1
```
And now I can take the big step! I'll use the `grep` command with the `/usr/share/dict/words` file and identify the letter frequency for all words spelled entirely with lowercase letters:
```
$ grep  '^[a-z]*$' /usr/share/dict/words | gawk -f letter-freq.awk
a 53
b 12
c 28
d 21
e 72
f 7
g 15
h 17
i 58
j 1
k 5
l 36
m 19
n 47
o 47
p 21
q 1
r 46
s 48
t 44
u 25
v 6
w 4
x 1
y 13
z 2
```
Of all the lowercase words in the `/usr/share/dict/words` file, the letters **j**, **q**, and **x** occur least frequently. The letter **z** is also pretty rare. Not surprisingly, the letter **e** is the most frequently used.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/4/gawk-letter-game
作者:[Jim Hall][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/jim-hall
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-docdish-typewriterkeys-3.png?itok=NyBwMdK_ (Typewriter keys in multicolor)
[2]: https://en.wikipedia.org/wiki/Letter_frequency

View File

@ -1,67 +0,0 @@
[#]: subject: (5 commands to level-up your Git game)
[#]: via: (https://opensource.com/article/21/4/git-commands)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
5 commands to level-up your Git game
======
Get more use out of Git by adding these commands to your repertoire.
![Business woman on laptop sitting in front of window][1]
If you use Git regularly, you might be aware that it has several reputations. It's probably the most popular version-control solution and is used by some of the [biggest software projects][2] around to [keep track of changes][3] to files. It provides a [robust interface][4] to review and incorporate experimental changes into existing documents. It's well-known for its flexibility, thanks to [Git hooks][5]. And partly because of its great power, it has earned its reputation for being complex.
You don't have to use all of Git's many features, but if you're looking to delve deeper into Git's subcommands, here are some that you might find useful.
### 1\. Finding out what changed
If you're familiar with Git's basics (`fetch`, `add`, `commit`, `push`, `log`, and so on) but you want to learn more, Git subcommands that query are a great, safe place to start. Querying your Git repository (your _work tree_) doesn't make any changes; it's only a reporting mechanism. You're not risking the integrity of your Git checkout; you're only asking Git about its status and history.
The [git whatchanged][6] command (almost a mnemonic itself) is an easy way to see what changed in a commit. A remarkably user-friendly command, it squashes the best features of `show` and `diff-tree` and `log` into one easy-to-remember command.
### 2\. Managing changes with git stash
The more you use Git, the more you use Git. That is, once you've become comfortable with the power of Git, the more often you use its powerful features. Sometimes, you may find yourself in the middle of working with a batch of files when you realize some other task is more urgent. With [git stash][7], you can gather up all the pieces of your work in progress and stash them away for safekeeping. With your workspace decluttered, you can turn your attention to some other task and then reapply stashed files to your work tree later to resume work.
### 3\. Making a linked copy with git worktree
When `git stash` isn't enough, Git also provides the powerful [git worktree][8] command. With it, you can create a new but _linked_ clone of your repository, forming a new branch and setting `HEAD` to whatever commit you want to base your new work on. In this linked clone, you can work on a task unrelated to what your primary clone is focused on. It's a good way to keep your work in progress safe from unintended changes. When you're finished with your new work tree, you can push your new branch to a remote, bundle the changes into an archive for later, or just fetch the changes from your other tree. Whatever you decide, your workspaces are kept separate, and the changes in one don't have to affect changes in the other until you are ready to merge.
### 4\. Selecting merges with git cherry-pick
It may seem counterintuitive, but the better at Git you get, the more merge conflicts you're likely to encounter. That's because merge conflicts aren't necessarily signs of errors but signs of activity. Getting comfortable with merge conflicts and how to resolve them is an important step in learning Git. The usual methods work well, but sometimes you need greater flexibility in how you merge, and for that, there's [git cherry-pick][9]. Cherry-picking merges allows you to be selective in what parts of commits you merge, so you never have to reject a merge request based on a trivial incongruity.
### 5\. Managing $HOME with Git
Managing your home directory with Git has never been easier, and thanks to Git's ability to be selective in what it manages, it's a realistic option for keeping your computers in sync. To work well, though, you must do it judiciously. To get started, read my tips on [managing $HOME with Git][10].
### Getting better at Git
Git is a powerful version-control system, and the more comfortable you become with it, the easier it becomes to use it for complex tasks. Try some new Git commands today, and share your favorites in the comments.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/4/git-commands
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
[2]: https://opensource.com/article/19/10/how-gnome-uses-git
[3]: https://opensource.com/article/18/2/how-clone-modify-add-delete-git-files
[4]: https://opensource.com/article/18/5/git-branching
[5]: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
[6]: https://opensource.com/article/21/3/git-whatchanged
[7]: https://opensource.com/article/21/3/git-stash
[8]: https://opensource.com/article/21/3/git-worktree
[9]: https://opensource.com/article/21/3/reasons-use-cherry-picking
[10]: https://opensource.com/article/21/3/git-your-home

View File

@ -1,76 +0,0 @@
[#]: subject: (5 handy guides to open source for teachers)
[#]: via: (https://opensource.com/article/21/6/open-source-guides-teachers)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
5 handy guides to open source for teachers
======
To help you get the most out of your summer, but also satiate the real
need to plan for the coming school year, we've collected some of our
favorite concise guides to help you plan.
![Looking at a map][1]
For some teachers, summer is here and thus a long (hopefully, relaxing) break. All the teachers I know are proud lifelong learners, though, and at the end of the summer break there's a new school year awaiting. To help you get the most out of your summer, but also satiate the real need to plan for the coming school year, we've collected some of our favorite _concise_ guides to help you plan.
### How to make your school pandemic-ready
By going [all-in on Linux][2], teacher Robert Maynord ensured his school was ready for remote learning—even before it needed to be. We still don't know what the rest of the year has in store, but if there's anything that the pandemic has shown the world, it's that [digital transformation][3] (the integration of digital technology into all areas of education) is not only possible, but beneficial to both teachers and students. You may not have the authority to change the way your classroom operates on a technological level, but there are lots of small changes you can make to create a more agile learning experience for your pupils.
### The ultimate guide to open source for teachers
With this article, you can learn how to [incorporate open source principles][4] in your classroom. Open source is about more than just technology. It's about sharing knowledge, collaborating, working together toward a common goal. You can transform your classroom into a shared space where students learn from each other just as much as they do from you. Read it, put it into practice, and encourage it.
### 8 WordPress plugins for virtual classrooms
The WordPress web platform is a powerful tool for building websites. In the classroom, [it can serve as a great tool][5] to teach both web technology and creative or academic writing. It can also be used to enable remote learning, or to integrate everyday schoolwork with the digital realm. Gain the most benefit from WordPress for educational purposes by mastering its many [add-on features][6].
### Teach kids Python (interactive gaming)
Open source tools can help anyone get started learning Python in an easy and fun way—making games. Of course, Python is a big topic, but we have a curriculum to take you from installing Python, taking your first steps with code with simple text and "turtle" drawing games, all the way to intermediate game development.
1. Start out by installing Python and getting used to how code works in our [Python 101 article.][7] This article alone can probably serve as the basis for two or three distinct classroom lessons.
2. If you're familiar with [Jupyter][8], then learn to [program a simple game with Python and Jupyter][9].
3. You can also learn [game development with this free Python ebook][10], which teaches you how to use Git, Python, and PyGame. Once you've learned the basics, check out [this collection of cool creations from the book's "playtesters"][11].
If Python is too advanced for you or your students, take a look at [Twine][12], a simple HTML-based interactive storytelling tool.
### Teach kids the Raspberry Pi (programming)
This article in our guide to [getting started with the Raspberry Pi][13] explores resources for helping kids learn to program. The Raspberry Pi has the unique quality of costing only $35 USD, while also being a full-powered Linux computer that can be used for anything from basic Python lessons to actual webservers, so it's full of potential for education. It's a reasonable goal to have a Pi per child in your classroom, or you can have a single Pi for the classroom to explore together (Linux is a multi-user OS, so with the right setup all of your students can use one Pi at the same time until you sell their parents or your principle on the value of purchasing more).
### Learn together
Part of an open classroom is being brave enough to learn alongside your students. As a teacher, you might be used to having all the answers, but the digital world is ever-changing and evolving. Don't be afraid to learn Python, Linux, the Raspberry Pi, and anything else _with_ your students. Work together to learn new fundamentals, new tricks, and new ways of solving problems. Open source is a proven and successful methodology, so don't just teach it—make it happen in your classroom.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/6/open-source-guides-teachers
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tips_map_guide_ebook_help_troubleshooting_lightbulb_520.png?itok=L0BQHgjr (Looking at a map)
[2]: https://opensource.com/article/21/5/linux-school-servers
[3]: https://enterprisersproject.com/what-is-digital-transformation
[4]: https://opensource.com/article/20/7/open-source-teachers
[5]: https://opensource.com/article/20/3/wordpress-education
[6]: https://opensource.com/article/20/5/wordpress-plugins-education
[7]: https://opensource.com/article/17/10/python-101
[8]: https://opensource.com/article/18/3/getting-started-jupyter-notebooks
[9]: https://opensource.com/article/20/5/python-games
[10]: https://opensource.com/article/20/10/learn-python-ebook
[11]: https://github.com/MakerBox-NZ?q=pygame&type=&language=&sort=
[12]: https://opensource.com/article/18/2/twine-gaming
[13]: https://opensource.com/article/19/3/teach-kids-program-raspberry-pi

View File

@ -1,134 +0,0 @@
[#]: subject: (How to Make LibreOffice Look Like Microsoft Office)
[#]: via: (https://www.debugpoint.com/2021/06/libreoffice-like-microsoft-office/)
[#]: author: (Arindam https://www.debugpoint.com/author/admin1/)
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
How to Make LibreOffice Look Like Microsoft Office
======
We made an attempt to make the LibreOffice suite look like Microsoft
Office. Is it possible? Lets find out.
[LibreOffice][1] is a free and open-source office productivity suite that provides you a complete collection of applications. It consists of a Word processor (Writer), a spreadsheet program (Calc), Presentation (Impress), and a drawing program (Draw). It also gives you a stand-alone database system LibreOffice Base while LibreOffice Math is a program that helps students, researchers to write formulas and equations.
While, the widely used [Microsoft Office][2] is a paid office productivity suite that gives you excellent programs to perform almost all tasks related to study, office, and enterprise usage.
Both of the programs are different but their objective is the same in terms of functionality. Due to its popularity, Microsoft office is used widely and well known to the users. However, there are many users who prefer the free LibreOffice for their work and activities. Adopting LibreOffice sometimes difficult compared to Microsoft Office although most of the menu items, tools are the same.
That said, if you can make LibreOffice look like Microsoft Office, then it is much easier for first-time users to adopt mostly coming from Microsoft Office background. The look and feel play a big part in users minds including their muscle memory and familiarity of colors, menu items.
Of course, you can not make it exactly like Microsoft Office because of different icons, fonts, etc. However, you can make it look up to a certain amount.
### Make LibreOffice Look Like Microsoft Office
_This guide is prepared in LibreOffice 7.2 (dev) version._
#### 1\. User Interface changes
LibreOffice has a “Ribbon” style toolbar called Tabbed Bar. Although it comes with many options of the toolbar (see below). For this guide, I have used the Tabbed bar option.
* Open LibreOffice and go to `Menu > View > User Interface`.
* Select `Tabbed` from the UI Section.
![tabbed bar option][3]
* Click on Apply to All. LibreOffice also provides an option to apply the toolbar type-specific to Writer or Calc. If you want a different toolbar type, you can choose that way. But I would recommend using the Apply to All to make it consistent.
* Now you should have the Microsoft Office-style Ribbon. Although they are not exactly the same, you get the feel of it.
#### 2\. Microsoft Office Icons for LibreOffice
The Icons in the toolbar play a big part in your workflow. LibreOffice provides some nice icons for your toolbar. The best ones are the
* Karasa Jaga
* Colibre
* Elementary
For this guide, we will use [Office 2013 icon set][4] which is developed by an author. It is available in Devian Art.
* Go to the below link and download the LibreOffice extension file (*.oxt). For the newer versions of LibreOffice, you need to use extension files to install icon sets.
[download office 2013 icon sets for libreoffice][5]
* After download, double click the .oxt file to open. Or, press CTRL+ALT+E to open the Extension Manager and select the downloaded .oxt file using the Add button. Close the window once done.
![Import icon sets in Extension Manager][6]
* Now go to `Tools > Options > View`. From the Icon style choose Office 2013.
* Change the icon size via `Icon Size > Notebookbar > Large`. If you feel the icons are small, you can change them. However, I feel to make it more Office-like, the large settings work better.
![Change icons in Options][7]
And, thats it. Your LibreOffice installation should look like this.
[][8]
SEE ALSO:   LibreOffice 7.2 - New Features and Release Details
![Making LibreOffice look like Microsoft Office in KDE Plasma][9]
![Making LibreOffice look like Microsoft Office in Windows 10][10]
![Making LibreOffice look like Microsoft Office in GNOME][11]
Remember, if you are using Ubuntu, KDE Plasma, or any Linux distribution, the looks may be different. But in my opinion, it looks closer to Microsoft Office in KDE Plasma than GNOME. LibreOffice doesnt look good in GTK based systems at the moment.
In Windows, however, it looks better because it uses system font, color palette.
These are some settings that you can use, however, you can play around with more customizations, icons, and themes as you wish. If you fancy dark mode in LibreOffice, you may want to read our tutorial [how to enable dark mode in LibreOffice][12].
### Closing Notes
Microsoft Office is undoubtedly the market leader in the Office productivity space. There is a reason for it, it comes with decades of development, and its not a free product. In fact, the latest Office 365 Home usage price is around ~7 USD per month for 3 to 4 devices. Which is a bit pricy if you ask me.
Whereas LibreOffice is free and community developed headed by The Document Foundation. Hence, the development is slower and features arrive late. It is not trying to be Microsoft Office but gives millions of users, schools, non-profits, colleges, students an opportunity to work and learn using a free office suite.
Hence, it is beneficial if it can mimic the basic look and feel to make it like Microsoft Office to increase LibreOffice adoption. And I hope this guide serves a little purpose in that direction.
[_Link: Official Feature comparison between LibreOffice and Microsoft Office._][13]
* * *
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2021/06/libreoffice-like-microsoft-office/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: http://libreoffice.com
[2]: http://office.com
[3]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/tabbed-bar-option.jpg
[4]: https://www.deviantart.com/charliecnr/art/Office-2013-theme-for-LibreOffice-512127527
[5]: https://www.deviantart.com/users/outgoing?https://1drv.ms/u/s!ArgKmgFcmBYHhSQkPfyMZRnXX5LJ
[6]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Import-icon-sets-in-Extension-Manager.jpg
[7]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Change-icons-in-Options-1024x574.jpg
[8]: https://www.debugpoint.com/2021/05/libreoffice-7-2/
[9]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-KDE-Plasma-1024x441.jpg
[10]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-Windows-10-1024x554.jpg
[11]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-GNOME-1024x498.jpg
[12]: https://www.debugpoint.com/2020/01/how-to-enable-dark-mode-libreoffice/
[13]: https://wiki.documentfoundation.org/Feature_Comparison:_LibreOffice_-_Microsoft_Office

View File

@ -2,7 +2,7 @@
[#]: via: (https://opensource.com/article/21/6/mom-switch-linux)
[#]: author: (Tomasz https://opensource.com/users/tomaszwaraksa)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (lkxed)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,358 +0,0 @@
[#]: subject: (Parsing config files with Java)
[#]: via: (https://opensource.com/article/21/7/parsing-config-files-java)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
Parsing config files with Java
======
Implement persistent settings when you're writing software in Java.
![Person drinking a hot drink at the computer][1]
When you write an application, you often want users to be able to configure how they interact with it and how it interacts with their system. These are commonly called "preferences" or "settings," and they're stored in "preference files" or "configuration files," or just "configs." There are many different formats for config files, including INI, JSON, YAML, and XML, and every language parses these languages differently. This article discusses some of the ways you can implement persistent settings when you're writing software in the [Java programming language][2].
### Choose a format
Writing configuration files is surprisingly flexible. I've kept configuration options in a simple comma-delimited text file, and I've kept options in highly detailed YAML or XML. The most important thing about configuration files is that they are consistent and predictable. This makes it easy for you to write code that can quickly and easily extract data from the configuration file, as well as save and update options when the user decides to make a change.
There are [several popular formats for configuration files][3]. Java has libraries for most of the common configuration formats, but in this article, I'll use the XML format. For some projects, you might choose to use XML for its inherent ability to provide lots of metadata about the data it contains, while for others, you may choose to avoid it due to its verbosity. Java makes working with XML relatively easy because it includes robust XML libraries by default.
### XML basics
XML is a big topic. Just one of the books I own about XML is over 700 pages. Fortunately, using XML doesn't require in-depth knowledge of all its many features. Like HTML, XML is a hierarchical markup language with opening and closing tags, which may contain zero or more data. Here's a sample snippet of XML:
```
&lt;xml&gt;
  &lt;node&gt;
    &lt;element&gt;Penguin&lt;/element&gt;
  &lt;/node&gt;
&lt;/xml&gt;
```
In this rather self-descriptive example, here are the terms that XML parsers use:
* **Document:** The `<xml>` tag opens a _document_, and the `</xml>` tag closes it.
* **Node:** The `<node>` tag is a _node_.
* **Element:** The `<element>Penguin</element>`, from the first `<` to the last `>`, is an _element_.
* **Content:** In the `<element>` element, the string `Penguin` is the _content_.
Believe it or not, that's all you need to know about XML to be able to write and parse it.
### Create a sample config file
A minimal example of a config file is all you need to learn how to parse XML. Imagine a config file tracking some display properties of a GUI window:
```
&lt;xml&gt;
  &lt;window&gt;
    &lt;theme&gt;Dark&lt;/theme&gt;
    &lt;fullscreen&gt;0&lt;/fullscreen&gt;
    &lt;icons&gt;Tango&lt;/icons&gt;
&lt;/window&gt;
&lt;/xml&gt;
```
Create a directory called `~/.config/DemoXMLParser`:
```
`$ mkdir ~/.config/DemoXMLParser`
```
On Linux, the `~/.config` directory is the default configuration file location, as defined by the [Freedesktop][4] specification. If you're on an operating system that doesn't follow Freedesktop standards, you can still use this location, but you may have to create all the directories yourself.
Copy and paste the sample configuration XML into a file and save it as `~/.config/DemoXMLParser/myconfig.xml`.
### Parse XML with Java
If you're new to Java, start by reading my [7 tips for new Java developers][5] article. Once you're relatively comfortable with Java, open your favorite integrated development environment (IDE) and create a new project. I call mine **myConfigParser**.
Without worrying too much about imports and error catching initially, you can instantiate a parser using the standard Java extensions found in the `javax` and `java.io` libraries. If you're using an IDE, you'll be prompted to import the appropriate libraries; otherwise, you can find a full list of libraries in the complete version of this code later in this article.
```
Path configPath = Paths.get([System][6].getProperty("user.home"), ".config", "DemoXMLParser");
[File][7] configFile = new [File][7](configPath.toString(), "myconfig.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
builder = factory.newDocumentBuilder();
[Document][8] doc = null;
doc = builder.parse(configFile);
doc.getDocumentElement().normalize();
```
This example code uses the `java.nio.Paths` library to locate the user's home directory, adding the default configuration location to the path. Then it defines the configuration file to be parsed as a File object using the `java.io.File` library.
Next, it uses the `javax.xml.parsers.DocumentBuilder` and `javax.xml.parsers.DocumentBuilderFactory` libraries to create an internal document builder so that the Java program can ingest and parse XML data.
Finally, Java builds a document called `doc` and loads the `configFile` file into it. Using `org.w3c.dom` libraries, it normalizes the ingested XML data.
That's essentially it. Technically, you're done parsing the data. But parsed data isn't of much use to you if you can't access it, so write some queries to extract important values from your configuration.
### Accessing XML values with Java
Getting data from your ingested XML document is a matter of referencing a specific node and then "walking" through the elements it contains. It's common to use a series of loops to iterate through elements in nodes, but I'll keep that to a minimum here, just to keep the code easy to read:
```
NodeList nodes = doc.getElementsByTagName("window");
for (int i = 0; i &lt; nodes.getLength(); i++) {
 Node mynode = nodes.item(i);
 System.out.println("Property = " + mynode.getNodeName());
       
 if (mynode.getNodeType() == Node.ELEMENT_NODE) {
   Element myelement = (Element) mynode;
             
   System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
   System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
   System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
 }
}
```
This sample code creates a `NodeList` object called `nodes` using the `org.w3c.dom.NodeList;` library. This object contains any child node with a name that matches the string `window`, which is the only node in the sample config file created in this article.
Next, it creates a for-loop to iterate over the `nodes` list, taking each node in order of appearance and processing it with an if-then loop. The if-then loop creates an `Element` object called `myelement` that contains all elements within the current node. You can query the elements using methods like `getChildNodes`, `getElementById`, and others, as [documented][9] by the project.
In this example, the elements are essentially the configuration keys. The values are stored as the content of the element, which you can extract with the `.getTextContent` method.
Run the code either in your IDE or as a binary:
```
$ java ./DemoXMLParser.java
Property = window
Theme = Dark
Fullscreen = 0
Icon set = Tango
```
Here's the full code:
```
package myConfigParser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ConfigParser {
        public static void main([String][10][] args) {
                Path configPath = Paths.get([System][6].getProperty("user.home"), ".config", "DemoXMLParser");
                [File][7] configFile = new [File][7](configPath.toString(), "myconfig.xml");
                DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = null;
               
                try {
                        builder = factory.newDocumentBuilder();
                } catch (ParserConfigurationException e) {
                        e.printStackTrace();
                }
       
                [Document][8] doc = null;
       
                try {
                        doc = builder.parse(configFile);
                } catch (SAXException e) {
                        e.printStackTrace();
                } catch ([IOException][11] e) {
                        e.printStackTrace();
                }
        doc.getDocumentElement().normalize();
       
        NodeList nodes = doc.getElementsByTagName("window");
        for (int i = 0; i &lt; nodes.getLength(); i++) {
           Node mynode = nodes.item(i);
           [System][6].out.println("Property = " + mynode.getNodeName());
           
           if (mynode.getNodeType() == Node.ELEMENT_NODE) {
               [Element][12] myelement = ([Element][12]) mynode;
               [System][6].out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
               [System][6].out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
               [System][6].out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
           } // close if
        } // close for
    } // close method
} //close class
```
### Updating XML with Java
From time to time, a user is going to change a preference. The `org.w3c.dom` libraries can update the contents of an XML element; you only have to select the XML element the same way you did when reading it. Instead of using the `.getTextContent` method, you use the `.setTextContent` method:
```
updatePref = myelement.getElementsByTagName("fullscreen").item(0);
updatePref.setTextContent("1");
[System][6].out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());  
```
This changes the XML document in your application's memory, but it doesn't write the data back to the drive. Using a combination of `javax` and `w3c` libraries, you can place your ingested XML back into your configuration file:
```
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer xtransform;
xtransform = transformerFactory.newTransformer();
DOMSource mydom = new DOMSource(doc);
StreamResult streamResult = new StreamResult(configFile);
xtransform.transform(mydom, streamResult);
```
This silently overwrites the previous configuration file with transformed data.
Here's the full code, complete with the updater:
```
package myConfigParser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ConfigParser {
        public static void main([String][10][] args) {
                Path configPath = Paths.get([System][6].getProperty("user.home"), ".config", "DemoXMLParser");
                [File][7] configFile = new [File][7](configPath.toString(), "myconfig.xml");
                DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = null;
               
                try {
                        builder = factory.newDocumentBuilder();
                } catch (ParserConfigurationException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
       
                [Document][8] doc = null;
       
                try {
                        doc = builder.parse(configFile);
                } catch (SAXException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch ([IOException][11] e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
        doc.getDocumentElement().normalize();
        Node updatePref = null;
//        NodeList nodes = doc.getChildNodes();
        NodeList nodes = doc.getElementsByTagName("window");
        for (int i = 0; i &lt; nodes.getLength(); i++) {
           Node mynode = nodes.item(i);
           [System][6].out.println("Property = " + mynode.getNodeName());
           
           if (mynode.getNodeType() == Node.ELEMENT_NODE) {
               [Element][12] myelement = ([Element][12]) mynode;
               [System][6].out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
               [System][6].out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
               [System][6].out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
               updatePref = myelement.getElementsByTagName("fullscreen").item(0);
               updatePref.setTextContent("2");
               [System][6].out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());          
           } // close if
           
        }// close for
        // write DOM back to the file
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer xtransform;
        DOMSource mydom = new DOMSource(doc);
        StreamResult streamResult = new StreamResult(configFile);
        try {
                xtransform = transformerFactory.newTransformer();
                xtransform.transform(mydom, streamResult);
        } catch (TransformerException e) {
                e.printStackTrace();
        }
                       
    } // close method
} //close class
```
### Keep configuration trouble-free
Configuration can be a deceptively simple routine. You might start with a simple plain text config format while your application has only a few configurable features, but as you introduce more options, reading or writing incorrect data can cause unexpected behavior from your application. One way to help keep your configuration process safe from failure is to use a strict format like XML and to lean on your programming language's built-in features to handle the complexity.
I like using Java and XML for this very reason. When I try to read the wrong configuration value, Java lets me know, often because the node my code claims to want to read doesn't exist in the XML path I expect. XML's highly structured format helps me keep my code reliable, and that benefits both the users and the developer.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/7/parsing-config-files-java
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
[2]: https://opensource.com/resources/java
[3]: https://opensource.com/article/21/6/what-config-files
[4]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
[5]: https://opensource.com/article/19/10/java-basics
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+file
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+document
[9]: https://www.w3.org/2003/01/dom2-javadoc/org/w3c/dom/Document.html
[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+ioexception
[12]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element

View File

@ -1,242 +0,0 @@
[#]: subject: (How to Dual Boot Fedora and Windows)
[#]: via: (https://itsfoss.com/dual-boot-fedora-windows/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
How to Dual Boot Fedora and Windows
======
_**Brief:** This detailed tutorial shows you **how to dual boot Fedora Linux with Windows 10**, step-by-step, accompanied by proper screenshots._
Dual booting Linux and Windows is one of the popular ways to enjoy the full potential of the two operating systems. You have both Linux and Windows installed on the same system and you can choose which one to use after starting your system.
![On the grub screen, you can select the operating system][1]
If you have a system with Windows installed already, youll learn how to install Fedora alongside Windows in this tutorial.
### Installing Fedora alongside Windows
![][2]
The tutorial has been performed on a system with Windows already installed, GPT partitioning and UEFI boot. It should be applicable to other systems with MBR partitioning and legacy BIOS system as well, but I cannot confirm that.
Note: If your Windows system uses BitLocker encryption, it will be a good idea to disable it first before you go on installing Fedora.
#### Requirements
Heres what youll need to follow this tutorial:
* A system preinstalled with Windows
* Good speed internet connection
* A USB key (pen drive) with at least 4 GB in size
* Optional: External USB disk for making back up of your existing data on Windows.
* Optional: Windows recovery or bootable disk (if you encounter any major boot issues, you can fix with it).
Lets see the steps.
#### Step 1: Make a backup of data on your Windows system [optional]
Backup is always a good idea. You will be dealing with the disk partitions. In the rare unfortunate case, if you make a mistake and delete the wrong partition, youll lose your data.
The simplest way would to be to copy the data in Documents, Videos, Music, Pictures and other folders to an external USB disk. You can use an external HDD (slower but cheaper) or SSD (faster but expensive) and copy the important files and folders on it.
Preview | Product | Price |
---|---|---|---
![SanDisk 500GB Extreme Portable SSD - Up to 1050MB/s - USB-C, USB 3.2 Gen 2 - External Solid State Drive - SDSSDE61-500G-G25][3] ![SanDisk 500GB Extreme Portable SSD - Up to 1050MB/s - USB-C, USB 3.2 Gen 2 - External Solid State Drive - SDSSDE61-500G-G25][3] | [SanDisk 500GB Extreme Portable SSD - Up to 1050MB/s - USB-C, USB 3.2 Gen 2 - External Solid State...][4] | $89.99[][5] | [Buy on Amazon][6]
Preview | Product | Price |
---|---|---|---
![Toshiba Canvio Advance 1TB Portable External Hard Drive USB 3.0, Black - HDTCA10XK3AA][7] ![Toshiba Canvio Advance 1TB Portable External Hard Drive USB 3.0, Black - HDTCA10XK3AA][7] | [Toshiba Canvio Advance 1TB Portable External Hard Drive USB 3.0, Black - HDTCA10XK3AA][8] | $51.99[][5] | [Buy on Amazon][9]
#### Step 2: Make some free space for Fedora installation
You need to create a partition where youll be installing Fedora. If you just have C drive, shrink it. If you have D, E or F drive, see if you can move their data to some other partition and delete or shrink one of them. Anything above 40 GB should be comfortable enough space for Fedora.
In the Windows menu, search for disk partitions and go to Create and format hard disk partitions.
![][10]
In the Disk Management tool, right-click on the drive which you want to partition and select **shrink volume**.
If you have just one partition like this, you need to make some free space out of it for Linux. If you have several partitions of considerable size, use any of them except C drive because it may erase the data.
![][11]
#### Step 3: Making a live USB of Fedora in Windows
Now, this can be done in different ways. You can download the ISO and [use Etcher][12] or Rufus or some other tool to write the ISO image to the USB disk.
However, Fedora provides a dedicated tool for downloading and making live USB. I am going to use that in this tutorial. The Fedora team put some effort in creating this tool, so why not use it.
But first, **plug in the USB key**. Now, go to the download page of Fedora:
[Fedora Download][13]
Youll see the option to download the Fedora Media Writer tool for Windows.
![][14]
It will download an exe file. Once downloaded, go to your downloads folder and double-click the FedoraMediaWriter exe file to install the Fedora Media Writer tool. Just keep on hitting next.
![][15]
Once installed, run the Fedora Media Writer tool. But before that, **make sure that you have plugged in the USB**.
It will give you the option to install various editions of Fedora. For desktops, go with Workstation.
![][16]
On the next screen, youll get the option to create live USB. When you hit that button, it starts downloading the ISO. It will also recognize your inserted USB key.
You need to have a good speed internet connection to download the 2 GB of ISO in a comfortable time span.
![][17]
After downloading the ISO, it checks the download automatically and then gives you the option to write the ISO image to the USB disk, i.e. create the live USB. Hit the “Write to Disk” button.
![][18]
It will take a couple of minutes to complete the process. It displays “Finished” message and you can close the Fedora Media Writer tool now.
![][19]
Good! So now you have the Fedora live USB ready with you. Time to use it for installing Fedora with Windows.
#### Step 4: Boot from live USB and install Fedora
Some systems do not allow you to boot from live USB with secure boot. If thats the case with you, please [disable secure boot][20].
At the screen that shows the logo of your system manufacturer, press the **F2 or F10 or F12** key. You may try pressing all of them one by one if you are not sure of the key. But **be quick** when you do that otherwise it will boot into the operating system.
This key is different for different brand of computers. Some may even use **Esc** or **Del** keys for this purpose.
![Quickly press F2, F10 or F12 keys at the screen showing your system manufacturers logo][21]
In some rare cases, you may have to [access the UEFI boot settings from within Windows][22].
In the BIOS settings, normally, you should see a screen like this. Here, you use the arrow keys to move down to USB option and press enter to boot from the USB. Please note that the screen may look different in different systems.
![][23]
If things go right, you should see a screen like below. **Go with the first option “Start Fedora Workstation”:**
![][24]
After some seconds, you should boot into the live Fedora session and see the option to try or install it. Go with “Install to Hard Drive”.
![][25]
It will ask to choose the language of choice for the installation process.
![][26]
The next screen is important. If you had created the free space in the step 2, you should be able to hit on the “Begin Installation”. If you see an exclamation mark on the disk icon under System, click on it and see what kind of disk configuration you can use here.
If you have more than one disk, you can choose which disk to use for Fedora.
![][27]
Select the disk and click on Done. You may see a warning message now. In my case, I did not create free space in the step 2 and hence it complained that there is not enough free space to install Fedora.
![][28]
I clicked on reclaim space and shrank the Windows partition here.
![][29]
After this, the “Begin Installation” option appeared to start the installation.
![][30]
Now its just a waiting game. It will take a few minutes to extract files and install them.
![][31]
When the process completes, youll see the “Finish Installation” button. Hit it.
![][32]
Youll be back to Fedora live session. Click the top right corner to bring down the menu and select Restart.
![][33]
When the system starts now, you should see the [Grub bootloader][34] screen with option to boot into Fedora and Windows.
![][1]
#### Step 5: Complete Fedora setup
You are almost there. Did you notice that Fedora didnt ask you to enter username and password? Many distributions like Ubuntu ask you to create an admin user during the installation itself. On the other hand, Fedora gives you this option when you log in to the installed system for the first time.
When you first log in, it runs a setup and creation of user and password is part of this initial setup.
![][35]
![][36]
![][37]
Once you do that, you are ready to enjoy Fedora Linux.
![][38]
Thats it. You can enjoy Fedora Linux and Windows in dual boot mode on the same system.
If you have any questions or if you are facing any issues while following this tutorial, please let me know in the comment system.
--------------------------------------------------------------------------------
via: https://itsfoss.com/dual-boot-fedora-windows/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/dual-boot-grub-screen-fedora-windows.jpg?resize=800%2C350&ssl=1
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-windows-dual-boot.jpg?resize=800%2C450&ssl=1
[3]: https://i1.wp.com/m.media-amazon.com/images/I/41zwkV8VfPL._SL160_.jpg?ssl=1
[4]: https://www.amazon.com/dp/B08GTXVG9P?tag=chmod7mediate-20&linkCode=ogi&th=1&psc=1 (SanDisk 500GB Extreme Portable SSD - Up to 1050MB/s - USB-C, USB 3.2 Gen 2 - External Solid State Drive - SDSSDE61-500G-G25)
[5]: https://www.amazon.com/gp/prime/?tag=chmod7mediate-20 (Amazon Prime)
[6]: https://www.amazon.com/dp/B08GTXVG9P?tag=chmod7mediate-20&linkCode=ogi&th=1&psc=1 (Buy on Amazon)
[7]: https://i0.wp.com/m.media-amazon.com/images/I/31-nRLIONWL._SL160_.jpg?ssl=1
[8]: https://www.amazon.com/dp/B08JKFY8FH?tag=chmod7mediate-20&linkCode=ogi&th=1&psc=1 (Toshiba Canvio Advance 1TB Portable External Hard Drive USB 3.0, Black - HDTCA10XK3AA)
[9]: https://www.amazon.com/dp/B08JKFY8FH?tag=chmod7mediate-20&linkCode=ogi&th=1&psc=1 (Buy on Amazon)
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/03/disc-management-windows.png?resize=800%2C561&ssl=1
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/04/making-free-space-for-dual-boot.jpg?resize=1226%2C728&ssl=1
[12]: https://itsfoss.com/install-etcher-linux/
[13]: https://getfedora.org/en/workstation/download/
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/download-fedora-media-writer-tool.png?resize=800%2C373&ssl=1
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-Fedora-Media-Writer-tool-Windows.png?resize=745%2C581&ssl=1
[16]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-media-writer-1.png?resize=800%2C425&ssl=1
[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-media-writer-2.jpg?resize=800%2C422&ssl=1
[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/writing-fedora-iso-to-usb-with-Fedora-Media-Writer-Tool.png?resize=800%2C285&ssl=1
[19]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedoa-live-usb-with-fedora-media-writer.png?resize=800%2C300&ssl=1
[20]: https://itsfoss.com/disable-secure-boot-windows/
[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/04/acer-predator-boot.jpg?resize=800%2C600&ssl=1
[22]: https://itsfoss.com/access-uefi-settings-windows-10/
[23]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/06/select-boot-from-live-usb.jpg?resize=800%2C330&ssl=1
[24]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-live-screen.jpg?resize=800%2C350&ssl=1
[25]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/Fedora-install-screen.jpg?resize=800%2C450&ssl=1
[26]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-1.png?resize=800%2C450&ssl=1
[27]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-2.png?resize=800%2C450&ssl=1
[28]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-3.png?resize=800%2C450&ssl=1
[29]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-4.png?resize=800%2C450&ssl=1
[30]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-5.png?resize=800%2C450&ssl=1
[31]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-6.png?resize=800%2C450&ssl=1
[32]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/installing-fedora-7.png?resize=800%2C450&ssl=1
[33]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/restart-gnome-fedora.jpg?resize=799%2C439&ssl=1
[34]: https://itsfoss.com/what-is-grub/
[35]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-1.png?resize=800%2C575&ssl=1
[36]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-2.png?resize=800%2C593&ssl=1
[37]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-3.png?resize=800%2C591&ssl=1
[38]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/07/fedora-setup-completed.jpg?resize=800%2C500&ssl=1

View File

@ -1,207 +0,0 @@
[#]: subject: "Solve the repository impedance mismatch in CI/CD"
[#]: via: "https://opensource.com/article/21/8/impedance-mismatch-cicd"
[#]: author: "Evan "Hippy" Slatis https://opensource.com/users/hippyod"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Solve the repository impedance mismatch in CI/CD
======
Aligning deployment images and descriptors can be difficult, but here
are few strategies to streamline the process.
![Tips and gears turning][1]
An _impedance mismatch_ in software architecture happens when there's a set of conceptual and technical difficulties between two components. It's actually a term borrowed from electrical engineering, where the impedance of electrical input and output must match for the circuit to work.
In software development, an impedance mismatch exists between images stored in an image repository and its deployment descriptors stored in the SCM. How do you know whether the deployment descriptors stored in the SCM are actually meant for the image in question? The two repositories don't track the data they hold the same way, so matching an image (an immutable binary stored individually in an image repository) to its specific deployment descriptors (text files stored as a series of changes in Git) isn't straightforward.
**NOTE**: This article assumes at least a passing familiarity with the following concepts:
* Source Control Management (SCM) systems and branching
* Docker/OCI-compliant images and containers
* Container Orchestration Platforms (COP) such as Kubernetes
* Continuous Integration/Continuous Delivery (CI/CD)
* Software development lifecycle (SDLC) environments
### Impedance mismatch: SCM and image repositories
To fully understand where this becomes a problem, consider a set of basic Software Development LifeCycle (SDLC) environments typically used in any given project; for example, dev, test, and prod (or release) environments.
The dev environment does not suffer from an impedance mismatch. Best practices, which today include using CI/CD, dictate that the latest commit to your development branch should reflect what's deployed in the development environment. So, given a typical, successful CI/CD development workflow:
1. A commit is made to the development branch in the SCM
2. The commit triggers an image build
3. The new, distinct image is pushed to the image repository and tagged as being in dev
4. The image is deployed to the dev environment in a Container Orchestration Platform (COP) with the latest deployment descriptors pulled from the SCM
In other words, the latest image is always matched to the latest deployment descriptors in the development environment. Rolling back to a previous build isn't an issue, either, because that implies rolling back the SCM, too.
Eventually, though, development progresses to the point where more formal testing needs to occur, so an image—which implicitly relates to a specific commit in the SCM—is promoted to a test environment. Again, assuming a successful build, this isn't much of a problem because the image promoted from development should reflect the latest in the development branch:
1. The latest deployment to development is approved for promotion, and the promotion process is triggered
2. The latest development image tagged as being in test
3. The image is pulled and deployed to the test environment using the latest deployment descriptors pulled from the SCM
So far, so good, right? But what happens in either of the following scenarios?
**Scenario A**. The image is promoted to the next downstream environment, e.g., user acceptance testing (UAT) or even a production environment.
**Scenario B**. A breaking bug is discovered in the test environment, and the image needs to be rolled back to a known good image.
In either scenario, it's not as if development has stopped, which means one or more commits to the development branch may have occurred, which in turn means it's possible the latest deployment descriptors have changed, and the latest image isn't the same as what was previously deployed in test. Changes to the deployment descriptors may or may not apply to older versions of an image, but they certainly can't be trusted. If they have changed, they certainly aren't the same deployment descriptors you've been testing with up to now with the image you want to deploy.
And that's the crux of the problem: I**f the image being deployed isn't the latest from the image repository, how do you identify which deployment descriptors in the SCM apply specifically to the image being deployed?** The short answer is, you can't. The two repositories have an impedance mismatch. The longer answer is that you can, but you have to work for it, which will be the subject of the rest of this article. Note that the following isn't necessarily the only solution to this problem, but it has been put into production and proven to work for dozens of projects that, in turn, have been built and deployed in production for more than a year now.
### Binaries and deployment descriptors
A common artifact produced from building source code is a Docker or OCI-compliant image, and that image will typically be deployed to a Container Orchestration Platform (COP) such as Kubernetes. Deploying to a COP requires deployment descriptors defining how the image is to be deployed and run as a container, e.g., [Kubernetes Deployments][2] or [CronJobs][3]. It is because of the fundamental difference between what an image is and its deployment descriptors where the impedance mismatch manifests itself. For this discussion, think of images as immutable binaries stored in an image repository. Any change in the source code does not change the image but rather replaces it with a distinct, new image.
By contrast, deployment descriptors are text files and thus can be considered source code and mutable. If best practices are being followed, then the deployment descriptors are stored in SCM, and all changes are committed there first to be properly tracked.
### Solving the impedance mismatch
The first part of the proposed solution is to ensure that a method exists of matching the image in the image repository to the source commit in the SCM, which holds the deployment descriptors. The most straightforward solution is to tag the image with its source commit hash. This will keep different versions of the image separate, easily identifiable, and provide enough information to find the correct deployment descriptors so that the image can be properly deployed in the COP.
Reviewing the scenarios above again:
**Scenario A**. _Promoting an image from one downstream environment to the next_: When the image is promoted from test to UAT, the image's tag tells us from which source commit in the SCM to pull the deployment descriptors.
**Scenario B**. _When an image needs to be rolled back in a downstream environment_: Whichever image we choose to roll back to will also tell us from which source commit in the SCM to pull the correct deployment descriptors.
In each case, it doesn't matter how many development branch commits and builds have taken place since a particular image has been deployed in test since every image that's been promoted can find the exact deployment descriptors it was originally deployed with.
This isn't a complete solution to the impedance mismatch, however. Consider two additional scenarios:
**Scenario C**. In a load testing environment, different deployment descriptors are tried at various times to see how a particular build performs.
**Scenario D**. An image is promoted to a downstream environment, and there's an error in the deployment descriptors for that environment.
In each of these scenarios, changes need to be made to the deployment descriptors, but right now all we have is a source commit hash. Remember that best practices require all source code changes to be committed back to SCM first. The commit at that hash is immutable by itself, so a better solution than just tracking the initial source commit hash is clearly needed.
The solution here is a new branch created at the original source commit hash. This will be dubbed a **Deployment Branch**. Every time an image is promoted to a downstream test or release environment, you should create a new Deployment Branch **from the head of the previous SDLC environment's Deployment Branch**.
This will allow the same image to be deployed differently and repeatedly within each SDLC environment and also pick up any changes discovered or applied for that image in each subsequent environment.
**NOTE:** How changes applied in one environment's deployment descriptors are applied to the next, whether by tools that enable sharing values such as Helm Charts or by manually cutting and pasting across directories, is beyond the scope of this article.
So, when an image is promoted from one SDLC environment to the next:
1. A Deployment Branch is created
1. If the image is being promoted from the dev environment, the branch is created from the source commit hash that built the image
2. Otherwise, _the Deployment Branch is created from the head of the current Deployment Branch_
2. The image is deployed into the next SDLC environment using the deployment descriptors from the newly created Deployment Branch for that environment
![deployment branching tree][4]
Figure 1: Deployment branches
1. Development branch
2. First downstream environment's Deployment Branch with a single commit
3. Second downstream environment's Deployment Branch with a single commit
Revisiting Scenarios C and D from above with Deployment Branches as a solution:
**Scenario C**. Change the deployment descriptors for an image deployed to a downstream SDLC environment
**Scenario D**. Fix an error in the deployment descriptors for a particular SDLC environment
In each scenario, the workflow is as follows:
1. Commit the changes to the deployment descriptors to the Deployment Branch for the SLDC environment and image
2. Redeploy the image into the SLDC environment using the deployment descriptors at the head of the Deployment Branch
Thus, Deployment Branches fully resolve the impedance mismatch between image repositories storing a single, immutable image representing a unique build and SCM repositories storing mutable deployment descriptors for one more downstream SDLC environments.
### Practical considerations
While this seems like a workable solution, it also opens up several new practical questions for developers and operations resources alike, such as:
A. Where should deployment descriptors be kept as source to best facilitate Deployment Branch management, i.e., in the same or a different SCM repository than the source that built the image?
Up until now, we've avoided speaking about which repository the deployment descriptors should reside. Without going into too much detail, we recommend putting the deployment descriptors for all SDLC environments into the same SCM repository as the image source. As Deployment Branches are created, the source for the images will follow and act as an easy-to-find reference for what is actually running in the container being deployed.
As mentioned above, images will be associated with the original source commit via their tag. Finding the reference for the source at a particular commit in a separate repository would add a level of difficulty to developers, even with tooling, which is unnecessary by keeping everything in a single repository.
B. Should the source code that built the image be modified on a Deployment Branch?
Short answer: **NEVER**.
Longer answer: No, because images should never be built from Deployment Branches. They're built from development branches. Changing the source that defines an image in a Deployment Branch will destroy the record of what built the image being deployed and doesn't actually modify the functionality of the image. This could also become an issue when comparing two Deployment Branches from different versions. It might give a false positive for differences in functionality between them (a small but additional benefit to using Deployment Branches).
C. Why an image tag? Couldn't image labels be used?
Tags are easily readable and searchable for images stored in a repository. Reading and searching for labels with a particular value over a group of images requires pulling the manifest for each image, which adds complexity and reduces performance. Also, tagging images for different versions is still necessary for historical record and finding different versions, so using the source commit hash is the easiest solution that guarantees uniqueness while also containing instantly useful information.
D. What is the most practical way to create Deployment Branches?
The first three rules of DevOps are _automate_, _automate_, _automate_.
Relying on resources to enforce best practices uniformly is hit and miss at best, so when implementing a CI/CD pipeline for image promotion, rollback, etc., incorporate automated Deployment Branching into the script.
E. Any suggestions for a naming convention for Deployment Branches?
&lt;_**deployment-branch-identifier**_&gt;-&lt;_**env**_&gt;-&lt;_**src-commit-hash**_&gt;
* _**deployment-branch-identifier:**_ A unique string used by every Deployment Branch to identify it as a Deployment Branch; e.g. 'deployment' or 'deploy'
* _**env:**_ The SDLC environment the Deployment Branch pertains to; e.g. 'qa', 'stg', or' prod' for the test, staging, and production environments, respectively
* _**src-commit-hash:**_ The source code commit hash that holds the original code that built the image being deployed, which allows developers to easily find the original commit that created the image while ensuring the branch name is unique
For example, _**deployment-qa-asdf78s**_ or _**deployment-stg-asdf78s**_ for Deployment Branches promoted to the QA and STG environments, respectively.
F. How do you tell which version of the image is running in the environment?
Our suggestion is to [label][5] all your deployment resources with the latest Deployment Branch commit hash and the source commit hash. These two unique identifiers will allow developers and operations personnel to find everything that was deployed and from where. It also makes cleanup of resources trivial using those selectors on deployments of different versions, e.g., on rollback or roll forward operations.
G. When is it appropriate to merge changes from Deployment Branches back into the development branch?
It's completely up to the development team on what makes sense.
If you're making changes for load testing purposes just to see what will break your application, for example, then those changes may not be the best thing to merge back into the development branch. On the other hand, if you find and fix an error or tune a deployment in a downstream environment, merging the Deployment Branch changes back into the development branch makes sense.
H. Is there a working example of Deployment Branching to test with first?
[el-CICD][6] has been successfully using this strategy for a year and a half in production for more than a hundred projects across all SDLC downstream environments, including managing deployments to production. If you have access to an [OKD][7], Red Hat OpenShift lab cluster, or [Red Hat CodeReady Containers][8], you can download the [latest el-CICD version][9] and run through the [tutorial][10] to see how and when Deployment Branches are created and used.
### Wrap up
Using the working example above would be a good exercise to help you better understand the issues surrounding impedance mismatches in development processes. Maintaining alignment between images and deployment descriptors is a critical part of successfully managing deployments.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/8/impedance-mismatch-cicd
作者:[Evan "Hippy" Slatis][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/hippyod
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/gears_devops_learn_troubleshooting_lightbulb_tips_520.png?itok=HcN38NOk (Tips and gears turning)
[2]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
[3]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
[4]: https://opensource.com/sites/default/files/picture1.png
[5]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
[6]: https://github.com/elcicd
[7]: https://www.okd.io/
[8]: https://cloud.redhat.com/openshift/create/local
[9]: https://github.com/elcicd/el-CICD-RELEASES
[10]: https://github.com/elcicd/el-CICD-docs/blob/master/tutorial.md

View File

@ -1,97 +0,0 @@
[#]: subject: "How to Completely Uninstall Google Chrome From Ubuntu"
[#]: via: "https://itsfoss.com/uninstall-chrome-from-ubuntu/"
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
How to Completely Uninstall Google Chrome From Ubuntu
======
So, you managed to [install Google Chrome on Ubuntu][1]. It is the most popular web browser in the world, after all.
But perhaps you dislike Google products for the heavy tracking and data mining they employ on its users. You decided to opt for [other web browsers on Ubuntu][2], perhaps a [non-Chromium browser][3].
Now that you are no longer using it, it would be wise to remove [Google Chrome][4] from Ubuntu.
How to do that? Let me show you the steps.
### Remove Google Chrome completely from Ubuntu
![Illustration for removing Google Chrome from Ubuntu][5]
You probably installed Google Chrome graphically. Unfortunately, youll have to resort to command line for removing it, unless you opt to [use Synaptic Package Manager][6].
It is not too difficult. Press the [Ctrl+Alt+T keyboard shortcut in Ubuntu to open a terminal][7].
Type the following command in the terminal:
```
sudo apt purge google-chrome-stable
```
It asks for a password. It is your user accounts password, the one which you use to log in to your Ubuntu system.
When you type the password, nothing is displayed on the screen. This is normal behavior in Linux. Just type the password blindly and press enter.
It will ask you to confirm the removal of Google Chrome by entering Y or simply pressing the enter key.
![Removing Google Chrome for Ubuntu][8]
This will remove Google Chrome from your Ubuntu Linux system along with most of the system files.
However, the personal setting files remain in your home directory. This includes things like cookie sessions, bookmarks and other Chrome related settings for your user account. If you install Google Chrome again, the same files could be used by Chrome again.
![Google Chrome leftover settings in Ubuntu][9]
If you want to completely uninstall Google Chrome, you may want to remove these files as well. Heres what you should do.
Change to the .config directory. _**Mind the dot before config**_. Thats the [way to hide files and folders in Linux][10].
```
cd ~/.config
```
And now remove the google-chrome directory:
```
rm -rf google-chrome
```
![Removing the leftover Google Chrome settings from Ubuntu][11]
You could have also used rm -rf ~/.config/google-chrome to delete it in one single command. Since this tutorial is focused on absolute beginners, I made it in two steps to reduce the error margin because of a typo.
Tip
Want to make your terminal look beautiful like the ones in the screenshot? Use these [terminal customization tips][12].
I hope this quick beginner tip helped you to get rid of Google Chrome from Ubuntu Linux.
--------------------------------------------------------------------------------
via: https://itsfoss.com/uninstall-chrome-from-ubuntu/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/install-chrome-ubuntu/
[2]: https://itsfoss.com/best-browsers-ubuntu-linux/
[3]: https://itsfoss.com/open-source-browsers-linux/
[4]: https://www.google.com/chrome/index.html
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/removing-google-chrome-ubuntu.png?resize=800%2C450&ssl=1
[6]: https://itsfoss.com/synaptic-package-manager/
[7]: https://itsfoss.com/open-terminal-ubuntu/
[8]: https://itsfoss.com/wp-content/uploads/2021/09/remove-google-chrome-ubuntu.webp
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/google-chrome-ubuntu-leftover-settings.png?resize=800%2C518&ssl=1
[10]: https://itsfoss.com/hide-folders-and-show-hidden-files-in-ubuntu-beginner-trick/
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/09/remove-google-chrome-leftover-settings-from-Ubuntu.png?resize=800%2C277&ssl=1
[12]: https://itsfoss.com/customize-linux-terminal/

View File

@ -1,288 +0,0 @@
[#]: subject: "How I migrated a WordPress website to a new host"
[#]: via: "https://opensource.com/article/21/9/migrate-wordpress"
[#]: author: "David Both https://opensource.com/users/dboth"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
How I migrated a WordPress website to a new host
======
Use this simple approach to migrate a website and manage firewall
configurations.
![Text editor on a browser, in blue][1]
Have you ever needed to migrate a WordPress website to a new host? I have done it several times and found the process to be quite easy. Of course, I don't use the recommended methods for doing most things, and this is no exceptionI use the easy way, and that is what I recommend.
This migration is non-destructive, so it is simple to revert to the original server if that should be necessary for any reason.
### Components of a WordPress website
Three main components are required to run a website based on [WordPress][2]: WordPress itself, a webserver such as [Apache][3] (which I use), and the [MariaDB][4]. MariaDB is a fork of MySQL and is functionally equivalent.
There are plenty of webservers out there, but I prefer Apache because I have used it for so long. You may need to adapt the Apache configuration I use here to whatever webserver you are using.
### The original setup
I use one Linux host as a firewall and router for my network. The webserver is a different host inside my network. My internal network uses what used to be called a class C private network address range, but which is simply referred to as 192.168.0.0/24 in the [Classless Internet Domain Routing (CIDR)][5] methodology.
For the firewall, I use the very simple [IPTables][6], which I prefer over the much more complex `firewalld`. One line in this firewall configuration sends incoming packets on port 80 (HTTP) to the webserver. As you can see by the comments, I placed rules to forward other inbound server connections to the same server on their appropriate ports in the `/etc/sysconfig/iptables` file.
```
# Reroute ports for inbound connections to the appropriate web/email/etc server.
# HTTPD goes to 192.168.0.75
-A PREROUTING -d 45.20.209.41/255.255.255.248 -p tcp -m tcp --dport 80 \
  -j DNAT --to-destination 192.168.0.75:80
```
I set up my original Apache webserver using named virtual hosts because I served multiple websites from this one HTTPD instance. It is always a good idea to use the named virtual host configuration approach because, like me, you may decide to host additional sites later, and this process makes that easier to do.
The virtual host stanza for the website to be moved in `/etc/httpd/conf/httpd.conf` looks like the one below. There are no IP addresses in this stanza, so it needs no changes for use on the new server.
```
&lt;VirtualHost *:80&gt;
   ServerName [www.website1.org][7]
   ServerAlias server.org
DocumentRoot "/var/website1/html"
   ErrorLog "logs/error_log"
   ServerAdmin [me@website1.org][8]
 
&lt;Directory "/var/website1/html"&gt;
      Options Indexes FollowSymLinks
 
AllowOverride None
      Require all granted
 
&lt;/Directory&gt;
&lt;/VirtualHost&gt;
```
The `Listen` directive near the top of the `httpd.conf` file looks like this before the migration. This is the actual IP private address of the server and not the public IP address.
```
`Listen 192.168.0.75:80`
```
You need to change the `Listen` IP address on the new host.
### Preparation
The preparation can be accomplished with three steps:
* Install the services.
* Configure the firewall.
* Configure the webserver.
#### Install Apache and MariaDB
Install Apache and MariaDB if they are not already on your new server. It is not necessary to install WordPress.
```
`dnf -y install httpd mariadb`
```
#### New server firewall configuration
Ensure that the firewall on the new server allows port 80. You do have a firewall on _all_ of your computers, right? Most modern distributions use an initial setup that includes a firewall that blocks all incoming traffic to ensure a higher level of security.
The first line in the snippet below may already be part of your IPTables or other netfilter-based firewall. It identifies inbound packets that have already been recognized as coming from an acceptable source and bypasses additional INPUT filter rules, thus saving time and CPU cycles. The last line in the snippet identifies new incoming connections to HTTPD on port 80 and accepts them.
```
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
&lt;snip&gt;
# HTTP
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
```
The following sample `/etc/sysconfig/iptables` file is an example of a minimal set of IPTables rules that allow incoming connections on SSH (port 22) and HTTPD (port 80) .
```
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
# SSHD
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
# HTTP
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
# Final disposition for unmatched packets
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
```
All I needed on my new server host was to add the last line in the snippet above to my firewall rules in the `/etc/sysconfig/iptables` file and then reload the revised ruleset.
```
`iptables-restore /etc/sysconfig/iptables`
```
Most current Red Hat-based distributions, such as Fedora, use `firewalld`. I don't use it because I find it far more complex than it needs to be for use cases such as home or small to medium businesses. To add inbound port 80 to `firewalld`, I suggest you refer to the [firewalld web page][9].
Your firewall and its configuration details might differ from these, but the objective is to allow incoming connections to HTTPD on port 80 of the new web server.
#### HTTPD configuration
Configure HTTPD in the `/etc/httpd/conf/httpd.conf` file. Set the IP address in the Listen stanza as shown below. The IP address of my new web server is 192.168.0.125.
```
`Listen 192.168.0.125:80`
```
Copy the VirtualHost stanza for the website being moved and paste it at the end of the `httpd.conf` file of the new server.
### The move
Only two sets of data need to be moved to the new server—the database itself and the website directory structure. Create `tar` archives of the two directories.
```
cd /var ; tar -cvf /tmp/website.tar website1/
cd /var/lib ; tar -cvf /tmp/database.tar mysql/
```
Copy those tarballs to the new server. I usually store files like this in `/tmp`, which is what it is for. Run the following commands on the new server to extract the files from the tar archives into the correct directories.
```
cd /var ; tar -xvf /tmp/website.tar
cd /var/lib ; tar -xvf /tmp/database.tar
```
All WordPress files are contained in the `/var/website1`, so they do not need to be installed on the new server. The WordPress installation procedure does not need to be performed on the new server.
This directory is all that needs to be moved to the new server.
The last step before making the switch is to start (or restart) the `mysqld` and `httpd` service daemons. WordPress is not a service, so it is not started as a daemon.
```
`systemctl start mysqld ; systemctl start httpd`
```
You should check the status of these services after starting them.
```
systemctl status mysqld
● mariadb.service - MariaDB 10.5 database server
    Loaded: loaded (/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
    Active: active (running) since Sat 2021-08-21 14:03:44 EDT; 4 days ago
        Docs: man:mariadbd(8)
<https://mariadb.com/kb/en/library/systemd/>
   Process: 251783 ExecStartPre=/usr/libexec/mariadb-check-socket (code=exited, status=0/SUCCESS)
   Process: 251805 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir mariadb.service (code=exited, status=0/SUCCESS)
   Process: 251856 ExecStartPost=/usr/libexec/mariadb-check-upgrade (code=exited, status=0/SUCCESS)
 Main PID: 251841 (mariadbd)
      Status: "Taking your SQL requests now..."
      Tasks: 15 (limit: 19003)
    Memory: 131.8M
        CPU: 1min 31.793s
    CGroup: /system.slice/mariadb.service
└─251841 /usr/libexec/mariadbd --basedir=/usr
Aug 21 14:03:43 simba.stmarks-ral.org systemd[1]: Starting MariaDB 10.5 database server...
Aug 21 14:03:43 simba.stmarks-ral.org mariadb-prepare-db-dir[251805]: Database MariaDB is probably initialized in /var/lib/mysql already, n&gt;
Aug 21 14:03:43 simba.stmarks-ral.org mariadb-prepare-db-dir[251805]: If this is not the case, make sure the /var/lib/mysql is empty before&gt;
Aug 21 14:03:44 simba.stmarks-ral.org mariadbd[251841]: 2021-08-21 14:03:44 0 [Note] /usr/libexec/mariadbd (mysqld 10.5.11-MariaDB) startin&gt;
Aug 21 14:03:44 simba.stmarks-ral.org systemd[1]: Started MariaDB 10.5 database server.
systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Drop-In: /usr/lib/systemd/system/httpd.service.d
└─php-fpm.conf
      Active: active (running) since Sat 2021-08-21 14:08:39 EDT; 4 days ago
        Docs: man:httpd.service(8)
   Main PID: 252458 (httpd)
      Status: "Total requests: 10340; Idle/Busy workers 100/0;Requests/sec: 0.0294; Bytes served/sec: 616 B/sec"
        Tasks: 278 (limit: 19003)
      Memory: 44.7M
        CPU: 2min 31.603s
   CGroup: /system.slice/httpd.service
├─252458 /usr/sbin/httpd -DFOREGROUND
├─252459 /usr/sbin/httpd -DFOREGROUND
├─252460 /usr/sbin/httpd -DFOREGROUND
├─252461 /usr/sbin/httpd -DFOREGROUND
├─252462 /usr/sbin/httpd -DFOREGROUND
└─252676 /usr/sbin/httpd -DFOREGROUND
Aug 21 14:08:39 simba.stmarks-ral.org systemd[1]: Starting The Apache HTTP Server...
Aug 21 14:08:39 simba.stmarks-ral.org httpd[252458]: AH00112: Warning: DocumentRoot [/var/teststmarks-ral/html] does not exist
Aug 21 14:08:39 simba.stmarks-ral.org httpd[252458]: Server configured, listening on: port 80
Aug 21 14:08:39 simba.stmarks-ral.org systemd[1]: Started The Apache HTTP Server.
```
### Making the final switch
Now that the required services are up and running, you can change the firewall rule for HTTPD to the following in the `/etc/sysconfig/iptables` file.
```
-A PREROUTING -d 45.20.209.41/255.255.255.248 -p tcp -m tcp --dport 80 \
  -j DNAT --to-destination 192.168.0.125:80
```
Then reload the IPTables rule set.
```
`iptables-restore /etc/sysconfig/iptables`
```
Because of the firewall rules in the firewall host, it is not necessary to change the external DNS entries to point to the new server. If you use an internal DNS server, you will need to make the IP address change to that A record in your internal DNS database. If you don't use an internal DNS server, be sure to set the correct address for your new server in the `/etc/hosts` files of your host computers.
### Testing and cleanup
Be sure to test your new setup. First, turn off the `mysqld` and `httpd` services on the old server. Then access the website with a browser. If everything works as it should, you can disable `mysqld` and `httpd` on the old server. If there is a failure, you can change the IPTables routing rule back to the old server until the problem is fixed.
I then removed both MySQL and HTTPD from the old server to ensure that they cannot be started accidentally.
### Conclusion
It really is that simple. There is no need to perform export or import procedures on the database because everything necessary is copied over in the `mysql` directory. The only reason you might want to deal with the export/import procedure is if there are databases other than those for the website or sites in the same instance of the MariaDB that you don't want copied to the new server.
Migrating the rest of the websites served by the old server is easy too. All of the databases required for the additional sites have already been moved over with MariaDB. It is only necessary to move the `/var/website` directories to the new server, add the appropriate virtual host stanzas, and restart HTTPD.
I have used this procedure multiple times for migrating a website from one server to another, and it always works well.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/9/migrate-wordpress
作者:[David Both][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/dboth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
[2]: https://wordpress.org/
[3]: https://opensource.com/article/18/2/how-configure-apache-web-server
[4]: https://mariadb.org/
[5]: https://opensource.com/article/16/12/cidr-network-notation-configuration-linux
[6]: https://en.wikipedia.org/wiki/Iptables
[7]: http://www.website1.org
[8]: mailto:me@website1.org
[9]: https://firewalld.org/documentation/howto/open-a-port-or-service.html

View File

@ -1,98 +0,0 @@
[#]: subject: "What is port forwarding?"
[#]: via: "https://opensource.com/article/21/9/what-port-forwarding"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
What is port forwarding?
======
This article demonstrates the most common scenarios for port forwarding.
![Multi-colored and directional network computer cables][1]
Port forwarding transfers network traffic from one network listener (called a "port") to another, either on the same computer or a different computer. Ports, in this context, are not physical objects but a software routine listening for network activity.
When traffic directed at a specific port arrives at a router or a firewall, or other networked application, the response it receives can be defined according to the port it's trying to communicate with. When you use port forwarding, you can catch communication coming in on port 8080, for instance, and forward it on to port 80 instead. The new destination port may be on the same device as the one receiving the signal or on a different device. There are many ways to forward ports, and there are different reasons for doing it. This article demonstrates the most common scenarios.
### Port forwarding with your router
You usually need to forward ports when you host a server at home. Your home router (usually the WiFi appliance you get from your ISP) has a built-in firewall designed to prevent the outside world from getting onto your home network. You can use port forwarding to allow traffic on a specific port through your router's firewall, sending it to a specific IP address on your network.
For instance, say you're hosting a [Minetest server][2] and want to invite friends. For them to get through your router and into your Minetest server, you must forward a port from the router to the computer hosting Minetest. By default, a Minetest server runs on port 30000. You can port forward 30000 on your router to port 30000 on your Minetest server, or you could arbitrarily invent a simpler port for your players to remember and then forward that instead. I find that people inevitably miscount the zeroes in 30000 (especially without the benefit of a comma to help), so I use port 1234 and forward it to my internal 30000 port.
Router interfaces differ from manufacturer to manufacturer, but the idea is the same regardless of what brand of router you have in your home. First, log in to your router.
Its IP address and login information is often printed on the router itself or in its documentation. I own a TP-Link GX90 router, and I log in to it by pointing my web browser to 10.0.1.1, but your router might be 192.168.0.1 or some other address.
My GX90 router calls port forwarding "Virtual servers," which is a category found in the router's **NAT forwarding** tab. NAT stands for _Network Address Translation_. Other routers may just call it **Port forwarding** or **Firewall** or **Services**. It may take a little clicking around to find the right category, or you may need to spend some time studying your router's documentation.
When you find the port forwarding setting, add a new rule that names an external port (1234, in my example) and an internal one (30000). Forward the external port to the internal port on the IP address of the computer you want people to be able to access. If you need help finding your IP address, read Archit Modi's _[How to find your IP address on Linux][3]_ article.
![A sample port forwarding rule][4]
A sample port forwarding rule
(Seth Kenlon, [CC BY-SA 4.0][5])
In this example, I'm forwarding traffic that reaches my home network at port 1234 to port 30000 of my home server located at 10.0.1.2.
Save the rule to proceed.
Next, you need to know your home network's public IP address. You can obtain this from websites like [ifconfig.me][6] or [icanhazip.com][7]. Either open a browser to one of those sites or get the IP using the [curl][8] command:
```
$ curl ifconfig.me
93.184.216.34
```
Your friends can now join your Minetest server by entering the `169.169.23.49:1234` into their Minetest client.
### Port forwarding with a firewall
Sysadmins sometimes need to forward ports for traffic reaching a server. For example, you may want to accept traffic to port 80 but present the user with a service running on port 8065. Without port forwarding, your users would have to remember to append a specific port at the end of the URL they enter into their browser, such as `example.com:8065`.  Most users aren't used to thinking about ports, so intercepting a call to the common web port 80 and redirecting it to the obscure one your web app runs on is a big convenience for your users.
You can forward traffic on a server using [firewall-cmd][9], the front-end command to the `firewalld` daemon.
First, set the ports and protocols you want to forward:
```
$ sudo firewall-cmd \
\--add-forward-port \
port=80:proto=tcp:toport=8065
```
To make the change permanent, use the `--runtime-to-permanent` option:
```
`$ sudo firewall-cmd --runtime-to-permanent`
```
### Network forwarding
In networking, there are other kinds of forwarding aside from port forwarding. For instance, both IP forwarding and proxying are forms of forwarding. As you get familiar with how network information is processed as it's routed, you can try different kinds of forwarding (and watch it with `tcpdump` or similar) to see what works best for your setup.
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/9/what-port-forwarding
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/connections_wires_sysadmin_cable.png?itok=d5WqHmnJ (Multi-colored and directional network computer cables)
[2]: https://opensource.com/alternatives/minecraft#minetest
[3]: https://opensource.com/article/18/5/how-find-ip-address-linux
[4]: https://opensource.com/sites/default/files/uploads/router-port-forward.jpg (A sample port forwarding rule)
[5]: https://creativecommons.org/licenses/by-sa/4.0/
[6]: http://ifconfig.me
[7]: http://icanhazip.com
[8]: https://opensource.com/article/20/5/curl-cheat-sheet
[9]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd

View File

@ -1,163 +0,0 @@
[#]: subject: "What you need to know about fuzz testing and Go"
[#]: via: "https://opensource.com/article/22/1/native-go-fuzz-testing"
[#]: author: "Gaurav Kamathe https://opensource.com/users/gkamathe"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
What you need to know about fuzz testing and Go
======
The Go team has accepted a proposal to add fuzz testing support to the
language.
![Person using a laptop][1]
The usage of [Go][2] is growing rapidly. It is now the preferred language for writing cloud-native software, container software, command-line tools, databases, and more. Go has had built-in [support for testing][3] for quite some time now. It makes writing tests and running them using the Go tool relatively easy.
### What is fuzz testing?
Fuzzing, sometimes also called fuzz testing, is the practice of giving unexpected input to your software. Ideally, this test causes your application to crash, or behave in unexpected ways. Regardless of what happens, you can learn a lot from how your code reacts to data it wasn't programmed to accept, and you can add appropriate error handling.
Any given software program consists of instructions that accept input or data from various sources, then it processes this data and generates appropriate output. As software gets developed, a team of test engineers tests this software to find bugs in the software that can then be reported and fixed. Often, the intent is to see if the software behaves as expected. Testing can further get divided into multiple areas, such as functional testing, integration testing, performance testing, and more. Each focuses on a specific aspect of the software functionality to find bugs or improve reliability or performance.
Fuzzing takes this testing process a step further and tries to provide "invalid" or "random" data to the software program. This is intentional, and the expectation is that the program should crash or behave unexpectedly to uncover bugs in the program so the developers can fix them. Like testing, doing this manually doesn't scale, so many fuzzing tools have been written to automate this process.
### Software testing in Go
As an example to test `Add()` function within `add.go`, you could write tests within `add_test.go` by importing the "testing" package and adding the test functionality within a function starting with `TestXXX()`.
Given this code:
```
func Add(num1, num2 int) int {
}
```
In a file called `add_test.go`, you might have this code for testing:
```
import "testing"
func TestAdd(t *testing.T) {
}
```
Run the test:
```
`$ go test`
```
### Addition of fuzz testing support
The Go team has accepted a [proposal to add fuzz testing support][4] to the language to further this effort. This involves adding a new `testing.F` type, the addition of `FuzzXXX()` functions within the `_test.go` files, and to run these tests with the `-fuzz` option is being added to the Go tool.
In a file called `add_test.go`:
```
func FuzzAdd(f *testing.F) {
}
```
Run the code:
```
`$ go test -fuzz`
```
This [feature is experimental][5] at the time of writing, but it should be included in the 1.18 release. Also, many features like `-keepfuzzing` and `-race` are not supported at the moment. The Go team has recently published [a tutorial on fuzzing][6], which is well worth a read.
### Get the latest features with gotip installation
If you are enthusiastic and wish to try out the feature before the official release, you can utilize `gotip`, which allows you to test upcoming Go features and provide feedback. To install `gotip`, you can use the commands below. After installation, you can use the `gotip` utility to compile and run the program instead of the usual `go` utility.
```
$ go install golang.org/dl/gotip@latest
$ gotip download
$ gotip version
go version devel go1.18-f009910 Thu Jan 6 16:22:21 2022 +0000 linux/amd64
$
```
### Fuzzing opinions in the community
Fuzzing is often a point of discussion among the software community, and we find people on both ends of the spectrum. Some consider it a useful technique to find bugs, especially on the security front. Whereas given the required resources (CPU/memory) for fuzzing, some consider it a waste or prefer other techniques over it. This is even evident in the Go team as well. We can see Go co-founder Rob Pike being slightly skeptical about the uses of fuzzing and its implementation in Go.
> _... Although fuzzing is good at finding certain classes of bugs, it is very expensive in CPU and storage, and cost/benefit ratio remains unclear. I worry about wasting energy and filling up git repos with testdata noise..._
>
> _~_[Rob Pike][7]
However, another member of the Go security team, Filo Sottile, seems quite optimistic about the addition of fuzz support to Go, also backing it up with some examples and wants it to be a part of the development process.
> *I like to say that fuzzing finds bugs at the margin. It's why we are interested in it as the security team: bugs caught at the margin are ones that don't make it into production to become vulnerabilities. *
>
> _We want fuzzing to be part of the development—not build or security—process: make a change to the relevant code…_
>
> _~_[Filo Sottile][8]
### Real-world fuzzing
To me, fuzzing seems quite effective at findings bugs and making systems more secure and resilient. To give an example, even the Linux kernel is fuzz tested using a tool called [syzkaller][9], and it has uncovered a [variety of bugs][10].
[AFL][11]** **is another popular fuzzer, used to fuzz programs written in C/C++.
There were options available for fuzzing Go programs as well in the past, one of them being [go-fuzz][12] which Filo mentions in his GitHub comments
> _The track record of go-fuzz provides pretty amazing evidence that fuzzing is good at finding bugs that humans had not found. In my experience, just a few CPU minutes of fuzzing can be extremely effective at the margin_
### Why add native fuzzing support in Go
If the requirement is to fuzz Go programs and existing tools like `go-fuzz` could do it, why add native fuzzing support to the language? The [Go fuzzing design draft][13] provides some rationale for doing so. The idea was to bring simplicity to the process as using the above tools adds more work for the developer and has many missing features. If you are new to fuzzing, I recommend reading the design draft document.
> Developers could use tools like go-fuzz or fzgo (built on top of go-fuzz) to solve some of their needs. However, each existing solution involves more work than typical Go testing and is missing crucial features. Fuzz testing shouldn't be any more complicated or less feature-complete than other types of Go testing (like benchmarking or unit testing). Existing solutions add extra overhead, such as custom command-line tools,
### Fuzz tooling
Fuzzing is a welcome addition to the Go language's long list of desired features. Although experimental for now, it's expected to become robust in upcoming releases. This gives sufficient time to try it out and explore its use cases. Rather than seeing it as an overhead, it should be seen as an effective testing tool to uncover hidden bugs if used correctly. Teams using Go should encourage its use, starting with developers writing small fuzz tests and testing teams extending it further to utilize its potential fully.
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/1/native-go-fuzz-testing
作者:[Gaurav Kamathe][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/gkamathe
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/laptop_screen_desk_work_chat_text.png?itok=UXqIDRDD (Person using a laptop)
[2]: https://go.dev/
[3]: https://pkg.go.dev/testing
[4]: https://github.com/golang/go/issues/44551
[5]: https://go.dev/blog/fuzz-beta
[6]: https://go.dev/doc/tutorial/fuzz
[7]: https://github.com/golang/go/issues/44551#issuecomment-784584785
[8]: https://github.com/golang/go/issues/44551#issuecomment-784655571
[9]: https://github.com/google/syzkaller
[10]: https://github.com/google/syzkaller/blob/master/docs/linux/found_bugs.md
[11]: https://github.com/google/AFL
[12]: https://github.com/dvyukov/go-fuzz
[13]: https://go.googlesource.com/proposal/+/master/design/draft-fuzzing.md

View File

@ -1,189 +0,0 @@
[#]: subject: "Creating and initializing lists in Java and Groovy"
[#]: via: "https://opensource.com/article/22/1/creating-lists-groovy-java"
[#]: author: "Chris Hermansen https://opensource.com/users/clhermansen"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Creating and initializing lists in Java and Groovy
======
Create and initialize a list of integers, first in Java and then in
Groovy.
![Developing code.][1]
I like the [Groovy programming language][2] a lot. I like it because, in the end, I like Java, even though Java sometimes feels clumsy. And because I like Java so much, I don't find many other JVM languages especially attractive. Kotlin, Scala, and Clojure, for example, don't feel much like Java, pursuing their own perspectives on what makes a good programming language. Groovy is different; in my view, Groovy is the perfect antidote to those situations when a programmer who likes Java just needs something a bit more flexible, compact, and sometimes even straightforward.
A good example is the List data structure, which is used to hold an ordered list of numbers, strings, or objects, and allows the programmer to iterate through those items in an efficient fashion. Especially for people writing and maintaining scripts, "efficiency" is mostly about clear and brief expressions that don't require a bunch of ceremony that obscures the intent of the code.
### Install Java and Groovy
Groovy is based on Java and requires a Java installation as well. Both a recent and decent version of Java and Groovy might be in your Linux distribution's repositories. Otherwise, you can install Groovy by following [these instructions][3]. A nice alternative for Linux users is SDKMan, which can be used to get multiple versions of Java, Groovy, and many other related tools. For this article, I use SDK's releases of:
* Java: version 11.0.12-open of OpenJDK 11
* Groovy: version 3.0.8
### Back to the problem
There have been various ways of instantiating and initializing lists in Java since they were first introduced (I think that was Java 1.5, but please don't quote me). Two current interesting ways involve two different libraries: **java.util.Arrays** and **java.util.List**.
#### Use java.util.Arrays
**java.util.Arrays** defines the static method **asList()**, which can be used to create a list that is backed by an array and is therefore also immutable, though its elements are mutable. Here it is in action:
```
var a1 = [Arrays][4].asList(1,2,3,4,5,6,7,8,9,10); // immutable list of mutable elements
[System][5].out.println("a1 = " + a1);
[System][5].out.println("a1 is an instance of " + a1.getClass());
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.Arrays$ArrayList
a1.set(0,0); // succeeds
[System][5].out.println("a1 = " + a1); // output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1.add(11); // fails producing
// Exception in thread "main" java.lang.UnsupportedOperationException
[System][5].out.println("a1 = " + a1); // not reached
```
#### Use java.util.List
**java.util.List** defines the static method **of().** This can be used to create an immutable list with elements that may or may not be immutable, depending on whether the items in the list of elements are immutable. Here is this version in action:
```
var a2 = [List][6].of(1,2,3,4,5,6,7,8,9,10);
[System][5].out.println("a2 = " + a2);
[System][5].out.println("a2 is an instance of " + a2.getClass());
// output is
// a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a2 is an instance of class java.util.ImmutableCollections$ListN
a2.set(0,0); // fails producing
// Exception in thread "main" java.lang.UnsupportedOperationException
[System][5].out.println("a2 = " + a2); // not reached
a2.add(11); // also fails for same reason if above two lines commented out
[System][5].out.println("a2 = " + a2); // not reached
```
So, I can use either **Arrays.asList()** or **List.of()** if I want a list that can't be grown (or shrunk) and may or may not have alterable elements.
If I want an initialized mutable list I would probably resort to using those immutable-ish lists as arguments to a list constructor, for example:
```
var a1 = new ArrayList&lt;Integer&gt;([Arrays][4].asList(1,2,3,4,5,6,7,8,9,10));
[System][5].out.println("a1 = " + a1);
[System][5].out.println("a1 is an instance of " + a1.getClass());
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.ArrayList
a1.set(0,0);
[System][5].out.println("a1 = " + a1);
//output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1.add(11);
[System][5].out.println("a1 = " + a1);
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
Note that the **Arrays.AsList()** was used to initialize the new **ArrayList&lt;Integer&gt;()**, which created a mutable copy of the argument.
Now maybe it's just me, but this seems like an awful lot of theory—needing to be situationally aware of the details of **java.util.Arrays** or **java.util.List**—just to create and initialize a mutable list of integers, though the actual statement used is not overly "ceremonial." Here it is again, just for reference:
```
`var a1 = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));`
```
### The Groovy approach
Here is the Groovy version of the above:
```
def a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println "a1 = $a1"
println "a1 is an instance of ${a1.getClass()}"
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.ArrayList
a1[0] = 0
println "a1 = $a1"
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1 &lt;&lt; 11
println "a1 = $a1"
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
At a glance, Groovy uses the **def** keyword rather than **var**. I also know that I can create a list representation by putting a list of things—in this case, integers—between brackets. Moreover, the list instance so created is precisely what I want: a mutable instance of **ArrayList**.
Now maybe it's just me, again, but the above seems to be a whole lot simpler—no remembering the semi-immutable results returned by **.of()** or **.asList()** and compensating for them. It's also nice that I can refer to a specific element of the list using the brackets with an index value between them, rather than the method call **set()**, and that the `<<` operator appends to the end of a list so that I don't have to use the method call **add()**. Also, did you notice the lack of semi-colons? Yep, in Groovy, they're optional. And finally, observe the use of string interpolation, with the **$variable** or **${expression}** inside a double-quoted string providing that capability.
Theres more going on "under the covers" in the Groovy world. That definition is an example of dynamic typing (the default in Groovy) versus the static typing of Java. In the Groovy definition line, the type of **a1** is inferred at runtime from the type of the expression evaluated on the right-hand side. Now we all know that dynamic programming languages give us great power and that with great power comes many good opportunities to mess up. But for programmers who don't like dynamic typing, Groovy offers the option of static typing.
### Groovy resources
The Apache Groovy site I mentioned at the beginning has a lot of great documentation. Another excellent Groovy resource is [Mr. Haki][7]. And a really good reason to learn Groovy is to go on and learn [Grails][8], which is a wonderfully productive full-stack web framework built on top of excellent components like Hibernate, Spring Boot, and Micronaut.
This article is dedicated to my very dear friend Anil Mukhi, who passed away on 3 January 2022. Thank you, Anil, for giving me the opportunity to learn so much about Groovy, Grails, and horse racing data.
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/1/creating-lists-groovy-java
作者:[Chris Hermansen][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/clhermansen
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_development_programming.png?itok=M_QDcgz5 (Developing code.)
[2]: http://www.groovy-lang.org/
[3]: http://www.groovy-lang.org/install.html
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+arrays
[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+list
[7]: https://www.mrhaki.com/
[8]: https://grails.org/

View File

@ -1,94 +0,0 @@
[#]: subject: "Scan documents and old photos on Linux with Skanlite"
[#]: via: "https://opensource.com/article/22/2/scan-documents-skanlite-linux-kde"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Scan documents and old photos on Linux with Skanlite
======
Use this Linux KDE application to digitize your archives.
![Filing papers and documents][1]
Although the world has mostly gone digital now, there are still times when you just have to print a form, sign it, and scan it back in. Sometimes, I find that a snapshot on my phone suffices, but some industries require a better copy than a hasty snapshot, and so a flatbed scanner is necessary. The KDE project provides an application called Skanlite that helps you import documents scanned on a flatbed, or even a tethered camera.
### Install Skanlite on Linux
You can install Skanlite from your software repository. On Fedora, Mageia, and similar:
```
`$ sudo dnf install skanlite`
```
On Elementary, Linux Mint, and other Debian-based distributions:
```
`$ sudo apt install skanlite`
```
### Scanner drivers
Most scanners on the market are compatible with the SANE scanner API. SANE isn't really a driver, but a protocol that can receive input from image capture devices and provide options to a programmer looking to build an application around it. Skanlite is one such application.
I've yet to come across a scanner that doesn't interface with SANE, but there are probably scanners out there that don't. In those cases, look on the manufacturer's website for SANE or TWAIN drivers, or else for their proprietary driver and scanner interface. The latter may not be usable with Skanlite, but Skanlite is always worth launching when you're unsure whether your scanner communicates over standard protocols. I've even had printer and scanner combination devices where the scanner is recognized immediately, even though the printer requires an additional driver.
### Using Skanlite
When you launch Skanlite, it first searches your system for image capture devices. On laptops, Skanlite usually discovers the webcam as a valid input source (because it is), but it also locates flatbed scanners attached to your machine. Select the scanner you want to use, and then continue.
To see what's on the scanbed, click the **Preview** button in the bottom right corner of the application.
![Skanlite with custom artwork][2]
(Image courtesy KDE)
This displays a preview image in the right panel. Nothing has been saved to your drive, this only shows you what your scanner has on it at the moment.
### Selecting a scan area
If you only need a portion of what's on the scanner, you can select an area you want to save. To select a single region, click and drag your mouse over the area you want to save. When there's an active selection, only the portion of the document you've selected will be saved when you click the **Scan** button.
You can have more than one selection, which is especially efficient when you need to scan several small images or only specific parts of one larger documents. To add a selection, click the **+** icon that appears in the center of your selection.
![Adding selections][3]
(Image courtesy KDE)
You can remove selections by clicking the **-** icon, which appears when you have multiple active selections.
### Scan settings
Image capture settings are located in the left panel. These controls allow you to import images in color or grayscale, and make adjustments to the brightness and contrast of the image. These options are software-based and don't affect how your scanner behaves, but they're common adjustments to make, and doing those adjustments here can save you from having to post-process the image in GIMP or Gwenview.
In many cases, your scanner may have configurable settings, found in the **Scanner Specific Options** tab on the left of the Skanlite window. Some scanners allow you to adjust color temperature, brightness, saturation, and other attributes that happen in firmware. Available options vary depending on the device and vendor, so you're likely to see changes in this panel depending on which device you're interfacing with.
### Scan and save
When you're ready to import the image (or the selected area of the image, if you've made selections), click the **Scan** button in the bottom right corner of the Skanlite window. Depending on your device, it may take a few moments to create the scan, but when it's done you're prompted to save or discard the image. If you like what you see, click **Save**.
Images are saved to whatever default location you have configured. To see the default location, click the **Settings** button in the bottom right corner of the window. In **Skanlite Settings**, you can set the default save location, the default name format, and the image resolution. You can also control whether you're prompted to save or discard an image after each scan, or whether you prefer to save everything and sort through it later.
### Scanning is easy on Linux
Scanning documents on Linux is so easy, I rarely give it a second thought. There aren't usually special drivers or applications you need to hunt down and install, because applications like Skanlite use open protocols to make the process simple. The next time you have a hard copy that you need to digitize, import it with Skanlite.
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/2/scan-documents-skanlite-linux-kde
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/documents_papers_file_storage_work.png?itok=YlXpAqAJ (Filing papers and documents)
[2]: https://opensource.com/sites/default/files/skanlite.png (Skanlite with custom artwork)
[3]: https://opensource.com/sites/default/files/skanlite-selection.jpg (Adding selections)

View File

@ -2,7 +2,7 @@
[#]: via: "https://opensource.com/article/22/2/casual-gaming-linux-kde"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: translator: "perfiffer"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "

View File

@ -1,150 +0,0 @@
[#]: subject: "Experience the Stunning Cutefish Desktop in Arch Linux"
[#]: via: "https://www.debugpoint.com/2022/02/cutefish-arch-linux-install/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Experience the Stunning Cutefish Desktop in Arch Linux
======
NOW YOU CAN EXPERIENCE THE CUTEFISH DESKTOP IN VANILLA ARCH LINUX. THIS
ARTICLE OUTLINES THE STEPS TO INSTALL THE CUTEFISH DESKTOP ENVIRONMENT
IN ARCH LINUX SYSTEMS.
![Cutefish Desktop in Arch Linux][1]
### Cutefish Desktop
A while back, [we reviewed CutefishOS][2], which features the awesome looking Cutefish desktop, which has received a positive reaction and reaches from the readers of our portal. So, we thought this was a perfect time if you want to do some experiments with this desktop in your favourite Arch Linux. Why not?
Before you jump on to the installation part, here are some nuggets about Cutefish Desktop.
Cutefish Desktop is part of [Cutefish OS][3], a new Linux distribution under development. This Debian based Linux distribution features the incredible looking, lightweight Cutefish Desktop.
The Cutefish Desktop is written on Qt Quick, QML, C++ and KDE Framework for its inner workings. This modern desktop environment uses KWin and SDDM for window and display management.
Cutefish Desktop brings a complete macOS inspired to look for your Linux desktop out-of-the-box. That means you get stunning icons, wallpapers, a global menu, a top bar with nice notification popups and a bottom dock.
You can read a detailed review in our complete [write up here][2].
### Install Cutefish Desktop in Arch Linux
#### Install base Arch System
This guide assumes that you have a base Arch Linux installed in your system before trying these steps. Or, you can try if you have any Arch-based Linux distributions installed as well. Just be careful about the display management in those cases.
You can refer to our guide for Arch Linux installation if you are new to Arch.
* [How to install Arch Linux using archinstall (recommended)][4]
* [How to install Arch Linux (basic guide)][5]
#### Install Cutefish Desktop
The Arch Linux community repository contains the Cutefish group, which have all the component required for this desktop to run. It includes core packages, native applications and additional tools as mentioned below.
At the terminal prompt of your Arch Linux system, run the below command to install all the Cutefish Desktop packages.
```
pacman -S cutefish
```
![A base Arch Linux prompt][6]
![Install Cutefish in Arch Linux][7]
Next, we need to install Xorg and display manager SDDM via the below command. Be careful if you install Cutefish desktop in an Arch install with other desktop environments such as GNOME, KDE Plasma or Xfce. Because you already have a display manager and Xorg installed. So, you can easily skip this step.
```
pacman -S xorg sddm
```
After the above commands are complete, enable the display manager via systemctl.
```
systemctl enable sddm
```
Thats all you need to install Cutefish desktop as bare metal level. Once done, reboot the system, and you should see Cutefish Desktop as below after logging in.
[][8]
SEE ALSO:   How to Install GNOME Desktop in Arch Linux [Complete Guide]
The base install requires additional customization because its not as close as Cutefish OS.
### Post Install Configuration
Although Cutefish group in Arch repo includes its native apps, such as Calculator and file manager, the desktop lacks basic applications that you need to install separately to make it a fully functional and productive desktop.
I recommend installing the following essential apps using the below command for your base installation. You can skip this step or choose any other applications/combinations of your choice.
* Firefox web browser
* Kwrite text editor
* Fonts (ttf-freefont)
* VLC media player
* Gwenview Image viewer
* GIMP Image Editor
* LibreOffice
* Transmission
```
pacman -S firefox ttf-freefont kwrite vlc gwenview gimp libreoffice-still transmission-qt
```
After installation, open the Settings and change the font of your choice. The default font was courier, which looks terrible on the desktop itself.
Reboot the system once you complete all the customizations as per your choice. And enjoy Cutefish desktop in Arch Linux.
![The Stunning Login Lock Screen of Cutefish Desktop][9]
### Closing Notes
This desktop is under development, so you would not find many settings items as of writing this. For example, there is no way to change resolutions, hiding dock and other options. That said, you can still use this with additional applications for your use. If you want to experiment, you can go ahead and try.
Cheers.
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][10], [Twitter][11], [YouTube][12], and [Facebook][13] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/02/cutefish-arch-linux-install/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/02/Cutefish-Desktop-in-Arch-Linux-1024x575.jpg
[2]: https://www.debugpoint.com/2021/11/cutefish-os-review-2021/
[3]: https://en.cutefishos.com/
[4]: https://www.debugpoint.com/2022/01/archinstall-guide/
[5]: https://www.debugpoint.com/2020/11/install-arch-linux/
[6]: https://www.debugpoint.com/wp-content/uploads/2022/02/A-base-Arch-Linux-prompt.jpg
[7]: https://www.debugpoint.com/wp-content/uploads/2022/02/Install-Cutefish-in-Arch-Linux.jpg
[8]: https://www.debugpoint.com/2020/12/gnome-arch-linux-install/
[9]: https://www.debugpoint.com/wp-content/uploads/2022/02/The-Stunning-Login-Lock-Screen-of-Cutefish-Desktop-1024x576.jpg
[10]: https://t.me/debugpoint
[11]: https://twitter.com/DebugPoint
[12]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[13]: https://facebook.com/DebugPoint

View File

@ -1,77 +0,0 @@
[#]: subject: "9 resources to help you contribute to open source in 2022"
[#]: via: "https://opensource.com/article/22/3/contribute-open-source-2022"
[#]: author: "Opensource.com https://opensource.com/users/admin"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
9 resources to help you contribute to open source in 2022
======
Are you ready to advance your open source journey? Here are tips and
tutorials for how to contribute to open source now. Take the poll to
share how long you've been using open source.
![Working from home at a laptop][1]
In 2022, open source is becoming more and more of a household name. But for many years, open source was known as the scrappy underdog of the enterprise IT landscape. Open source has been around for [decades][2] in some form or fashion, but it wasn't even until the late 1990s that it was formalized with its [name][3]. You may have been using open source technology this whole time but didn't know it. In fact, the website you are currently reading is run on the open source content management system, [Drupal][4]. Your car, laptop, smartwatch, and video games are likely [supported by Linux][5], an open source operating system. 
Red Hat's annual [State of Enterprise Open Source][6] was recently released containing a whole lot of insights helpful for anyone growing a career in open source technology. For starters, 77% of IT leaders have a more positive perception of enterprise open source than they did a year ago and 82% of IT leaders are more likely to select a vendor who contributes to the open source community. This means that participating in open source is more important than ever before. Now is the time to advance your open source journey, no matter where you are. Here are a few resources to help you along the way.
### Why contribute to open source?
* [What motivates open source software contributors?][7] New study finds people's reasons for contributing have changed since the early 2000s.
* [3 reasons to contribute to open source now][8] Now, more than ever, is the ideal time to contribute to open source. Heres why.
* [7 strategies for success when contributing to open source][9] An author's experience with contributing to open source projects helped her land her dream job in tech.
### Make your first contribution to open source
* [8 non-code ways to contribute to open source][10] Whether you're a novice programmer, a seasoned veteran, or not an engineer at all, there are many ways to contribute to open source projects beyond coding.
* [6 ways to contribute to an open source alternative to Slack][11] Join thousands who have contributed code, translations, documentation, and more to Mattermost, an open source messaging platform.
* [7 ways anyone can contribute to Open Practice Library][12] Contributing to the Open Practice Library is a fun way to participate in a global community of practitioners who are all willing to share their knowledge and improve their own ways of working.
* [How to contribute to Kubernetes if you have a full-time job][13] You can work on the internals of one of the largest open source projects, even in your spare time.
### Encourage others to contribute to open source
* [Why your open source project needs more than just coders][14] Developers alone don't create open source projects that meet a variety of needs for a long shelf life; it's time to welcome more roles and talent.
* [10 tips for onboarding open source contributors][15] Making new contributors feel welcome in your community is essential to your project's future, so it's important to put time and attention into onboarding them.
### Share your advice for contributing to open source
There are endless possibilities when it comes to participating in the open source community. On Opensource.com, our goal is to celebrate the diverse perspectives and backgrounds of the community—including yours. Your unique story inspires people from all over the globe to get involved with open source. Go ahead and [send us your article idea][16]!
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/3/contribute-open-source-2022
作者:[Opensource.com][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/admin
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
[2]: https://www.redhat.com/en/topics/open-source/what-is-open-source#the-history-of-open-source?intcmp=7013a000002qLH8AAM
[3]: https://opensource.com/article/18/2/coining-term-open-source-software
[4]: https://opensource.com/tags/drupal
[5]: https://opensource.com/article/19/8/everyday-tech-runs-linux
[6]: https://www.redhat.com/en/enterprise-open-source-report/2022?intcmp=7013a000002qLH8AAM
[7]: https://opensource.com/article/21/4/motivates-open-source-contributors
[8]: https://opensource.com/article/20/6/why-contribute-open-source
[9]: https://opensource.com/article/22/1/open-source-contributions-career
[10]: https://opensource.com/life/16/1/8-ways-contribute-open-source-without-writing-code
[11]: https://opensource.com/article/20/7/mattermost
[12]: https://opensource.com/article/21/10/open-practice-library
[13]: https://opensource.com/article/19/11/how-contribute-kubernetes
[14]: https://opensource.com/article/20/9/open-source-role-diversity
[15]: https://opensource.com/article/19/12/open-source-contributors
[16]: https://opensource.com/how-submit-article

View File

@ -1,272 +0,0 @@
[#]: subject: "Creating and initializing maps in Groovy vs Java"
[#]: via: "https://opensource.com/article/22/3/maps-groovy-vs-java"
[#]: author: "Chris Hermansen https://opensource.com/users/clhermansen"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Creating and initializing maps in Groovy vs Java
======
Java and Groovy maps are nicely general, permitting keys and values to
be any classes that extend the Object class.
![Business woman on laptop sitting in front of window][1]
Ive recently explored some of the differences between Java and Groovy when [creating and initializing lists][2] and [building lists at runtime][3]. I observed the simple facilities provided by Groovy for these purposes in comparison to the complexity required in Java.
In this article, I examine creating and initializing maps in Java and Groovy. Maps provide the ability to develop structures you can search by _key_. And if the key gets found, that returns the _value_ associated with that key. Today, maps are implemented in many programming languages, including Java and Groovy, but also Python (where they are called dictionaries), Perl, awk, and many others. Another term commonly used to describe maps is _associative arrays_, which you can read about in [this Wikipedia article][4]. Java and Groovy maps are nicely general, permitting keys and values to be any classes that extend the `Object` class.
### Install Java and Groovy
Groovy is based on Java and requires a Java installation as well. Both a recent and decent version of Java and Groovy might be in your Linux distributions repositories. Or, you can install Groovy following the instructions on the link mentioned above. A nice alternative for Linux users is [SDKMan][5], which you can use to get multiple versions of Java, Groovy, and many other related tools. For this article, Im using SDKs releases of:
* Java: version 11.0.12-open of OpenJDK 11;
* Groovy: version 3.0.8.
### Back to the problem
Java offers a number of ways to instantiate and initialize maps, and since Java 9, several new approaches got added. The most obvious candidate is the static method `java.util.Map.of()` which you can use as follows:     
```
var m1 = [Map][6].of(
    "AF", "Afghanistan",
    "AX", "Åland Islands",
    "AL", "Albania",
    "DZ", "Algeria",
    "AS", "American Samoa",
    "AD", "Andorra",
    "AO", "Angola",
    "AI", "Anguilla",
    "AQ", "Antarctica");
[System][7].out.println("m1 = " + m1);
[System][7].out.println("m1 is an instance of " + m1.getClass());
```
It turns out that `Map.of()` used in this fashion bears two important restrictions. First, the map instance you create this way is immutable. Second, this way you can supply at most 20 arguments, representing ten key-value pairs.
Try adding tenth and eleventh pairs, say "AG", "Antigua and Barbuda", and "AR", "Argentina" to see what happens. Youll see the Java compiler looking for a version of `Map.of()` that accepts 11 pairs and fails.
A quick look at [the documentation for java.util.Map][8] shows the reason for this second limitation, and shows a way out of that conundrum:
```
var m2 = [Map][6].ofEntries(
    [Map][6].entry("AF", "Afghanistan"),
    [Map][6].entry("AX", "Åland Islands"),
    [Map][6].entry("AL", "Albania"),
    [Map][6].entry("DZ", "Algeria"),
    [Map][6].entry("AS", "American Samoa"),
    [Map][6].entry("AD", "Andorra"),
    [Map][6].entry("AO", "Angola"),
    [Map][6].entry("AI", "Anguilla"),
    [Map][6].entry("AQ", "Antarctica"),
    [Map][6].entry("AG", "Antigua and Barbuda"),
    [Map][6].entry("AR", "Argentina"),
    [Map][6].entry("AM", "Armenia"),
    [Map][6].entry("AW", "Aruba"),
    [Map][6].entry("AU", "Australia"),
    [Map][6].entry("AT", "Austria"),
    [Map][6].entry("AZ", "Azerbaijan"),
    [Map][6].entry("BS", "Bahamas"),
    [Map][6].entry("BH", "Bahrain"),
    [Map][6].entry("BD", "Bangladesh"),
    [Map][6].entry("BB", "Barbados")
);
       
[System][7].out.println("m2 = " + m2);
[System][7].out.println("m2 is an instance of " + m2.getClass());
```
As long as I dont need to subsequently change the contents of the map created and initialized with `Map.ofEntries()`, this is a decent solution. Note above that rather than using `Map.of()` as in the first example, I used `Map.ofEntries()`.
However, supposing I want to create and initialize a map instance with some entries and later add to that map, I need to do something like this:
```
var m3 = new HashMap&lt;[String][9],String&gt;([Map][6].ofEntries(
    [Map][6].entry("AF", "Afghanistan"),
    [Map][6].entry("AX", "Åland Islands"),
    [Map][6].entry("AL", "Albania"),
    [Map][6].entry("DZ", "Algeria"),
    [Map][6].entry("AS", "American Samoa"),
    [Map][6].entry("AD", "Andorra"),
    [Map][6].entry("AO", "Angola"),
    [Map][6].entry("AI", "Anguilla"),
    [Map][6].entry("AQ", "Antarctica"),
    [Map][6].entry("AG", "Antigua and Barbuda"),
    [Map][6].entry("AR", "Argentina"),
    [Map][6].entry("AM", "Armenia"),
    [Map][6].entry("AW", "Aruba"),
    [Map][6].entry("AU", "Australia"),
    [Map][6].entry("AT", "Austria"),
    [Map][6].entry("AZ", "Azerbaijan"),
    [Map][6].entry("BS", "Bahamas"),
    [Map][6].entry("BH", "Bahrain"),
    [Map][6].entry("BD", "Bangladesh"),
    [Map][6].entry("BB", "Barbados")
));
[System][7].out.println("m3 = " + m3);
[System][7].out.println("m3 is an instance of " + m3.getClass());
m3.put("BY", "Belarus");
[System][7].out.println("BY: " + m3.get("BY"));
```
Here, by using the immutable map created by `Map.ofEntries()` as an argument to the `HashMap` constructor, I create a mutable copy of it, which I can then alter—for example, with the `put()` method.
Take a look at the Groovy version of the above:
```
def m1 = [
    "AF": "Afghanistan",
    "AX": "Åland Islands",
    "AL": "Albania",
    "DZ": "Algeria",
    "AS": "American Samoa",
    "AD": "Andorra",
    "AO": "Angola",
    "AI": "Anguilla",
    "AQ": "Antarctica",
    "AG": "Antigua and Barbuda",
    "AR": "Argentina",
    "AM": "Armenia",
    "AW": "Aruba",
    "AU": "Australia",
    "AT": "Austria",
    "AZ": "Azerbaijan",
    "BS": "Bahamas",
    "BH": "Bahrain",
    "BD": "Bangladesh",
    "BB": "Barbados"]
println "m1 = $m1"
println "m1 is an instance of ${m1.getClass()}"
m1["BY"] = "Belarus"
println "m1 = $m1"
```
At a glance, you see Groovy uses the `def` keyword rather than `var`—although in late-model Groovy (version 3+), its possible to use `var` instead.
You also see that you can create a map representation by putting a list of key-value pairs between brackets. Moreover, the list instance so created is quite useful for a couple of reasons. First, its mutable, and second, its an instance of `LinkedHashMap`**,** which preserves the order of insertion. So when you run the Java version and print the variable `m3`, you see:
```
`m3 = {BB=Barbados, BD=Bangladesh, AD=Andorra, AF=Afghanistan, AG=Antigua and Barbuda, BH=Bahrain, AI=Anguilla, AL=Albania, AM=Armenia, AO=Angola, AQ=Antarctica, BS=Bahamas, AR=Argentina, AS=American Samoa, AT=Austria, AU=Australia, DZ=Algeria, AW=Aruba, AX=Åland Islands, AZ=Azerbaijan}`
```
When you run the Groovy version, you see:
```
`m1 = [AF:Afghanistan, AX:Åland Islands, AL:Albania, DZ:Algeria, AS:American Samoa, AD:Andorra, AO:Angola, AI:Anguilla, AQ:Antarctica, AG:Antigua and Barbuda, AR:Argentina, AM:Armenia, AW:Aruba, AU:Australia, AT:Austria, AZ:Azerbaijan, BS:Bahamas, BH:Bahrain, BD:Bangladesh, BB:Barbados]`
```
Once again, you see how Groovy simplifies the situation. The syntax is very straightforward, somewhat reminiscent of Pythons dictionaries, and no need to remember the various contortions necessary if you have an initial list longer than ten pairs. Note that we use the expression:
```
`m1[“BY”] = “Belarus”`
```
Rather than the Java:
```
`m1.put(“BY”, “Belarus”)`
```
Also, the map is by default mutable, which is arguably good or bad, depending on the needs. I think what bothers me about the “immutable default” of the Java situation is that there isnt something like `Map.mutableOfMutableEntries()`. This forces the programmer, who has just figured out how to declare and initialize a map, to switch gears and think about just how to convert the immutable map they have into something mutable. I also kind of wonder about the business of creating something immutable just to throw it away.
Another thing to think about is the square brackets as key lookup works to replace both `put()` and `get()` in Java, so you can write:
```
`m1[“ZZ”] = m1[“BY”]`
```
Instead of:
```
`m1.put(“ZZ”,m1.get(“BY”))`
```
Sometimes, its nice to think of keys and their values in the same way you think of fields in the instance of a class. Imagine you have a bunch of properties you want to set: In Groovy, this could look like:
```
def properties = [
      verbose: true,
      debug: false,
      logging: false]
```
And then later you can change it as:
```
`properties.verbose = false`
```
This works because, as long as the key follows certain rules, you can omit the quotes and use the dot operator instead of square brackets. While this can be quite useful and pleasant, it also means that to use the value of a variable as a key value in a map representation, you must enclose the variable in parentheses, like:
```
`def myMap = [(k1): v1, (k2): v2]`
```
This is a good moment to remind the diligent reader that Groovy is particularly well-suited to scripting. Often, maps are a key element in scripts, providing lookup tables and generally functioning as an in-memory database. The example Ive used here is a subset of the ISO 3166 two-character country codes and country names. The codes are familiar to anyone who accesses internet hostnames in countries around the world, which could form a useful part of a scripting utility that looks at internet hostnames in log files to learn about the geographic distribution of users.
### Groovy resources
The [Apache Groovy site][10] has a lot of great documentation. Another great Groovy resource is [Mr. Haki][11]. The [Baeldung site][12] provides a lot of useful how-to in Java and Groovy. And a really great reason to learn Groovy is to go on and learn [Grails][13], which is a wonderfully productive full-stack web framework built on top of excellent components like Hibernate, Spring Boot, and Micronaut.
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/3/maps-groovy-vs-java
作者:[Chris Hermansen][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/clhermansen
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-concentration-focus-windows-office.png?itok=-8E2ihcF (Woman using laptop concentrating)
[2]: https://opensource.com/article/22/1/creating-lists-groovy-java
[3]: https://opensource.com/article/22/2/accumulating-lists-groovy-vs-java
[4]: https://en.wikipedia.org/wiki/Associative_array
[5]: https://sdkman.io/
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+map
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[8]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Map.html
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[10]: https://groovy-lang.org/
[11]: https://blog.mrhaki.com/
[12]: https://www.baeldung.com/
[13]: https://grails.org/

View File

@ -1,171 +0,0 @@
[#]: subject: "Using Homebrew Package Manager on Fedora Linux"
[#]: via: "https://fedoramagazine.org/using-homebrew-package-manager-on-fedora-linux/"
[#]: author: "Mehdi Haghgoo https://fedoramagazine.org/author/powergame/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Using Homebrew Package Manager on Fedora Linux
======
![][1]
### Introduction
Homebrew is a package manager for macOS to install UNIX tools on macOS. But, it can be used on Linux (and Windows WSL) as well. It is written in Ruby and provides software packages that might not be provided by the host system (macOS or Linux), so it offers an auxiliary package manager besides the OS package manager. In addition, it installs packages only to its prefix (either /home/linuxbrew/.linuxbrew or ~/.linuxbrew) as a non-root user, without polluting system paths. This package manager works on Fedora Linux too. In this article, I will try to show you how Homebrew is different from Fedora Linux package manager _dnf_ , why you might want to install and use it on Fedora Linux, and how.
##### Warning
You should always inspect the packages and binaries you are installing on your system. Homebrew packages usually run as a non-sudoer user and to a dedicated prefix so they are quite unlikely to cause harm or misconfigurations. However, do all the installations at your own risk. The author and the Fedora community are not responsible for any damages that might result directly or indirectly from following this article.
### How Homebrew Works
Homebrew uses Ruby and Git behind the scenes. It builds software from source using special Ruby scripts called formulae which look like this (Using wget package as an example):
```
class Wget < Formula
homepage "https://www.gnu.org/software/wget/"
url "https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
sha256 "52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"
def install
system "./configure", "--prefix=#{prefix}"
system "make", "install"
end
end
```
### How Homebrew is Different from _dnf_
Homebrew is a package manager that provides up-to-date versions of many UNIX software tools and packages e.g. ffmpeg, composer, minikube, etc. It proves useful when you want to install some packages that are not available in Fedora Linux _rpm_ repositories for some reason. So, it does not replace _dnf_.
### Install Homebrew
Before starting to install Homebrew, make sure you have glibc and gcc installed. These tools can be installed on Fedora with:
```
sudo dnf groupinstall "Development Tools"
```
Then, install Homebrew by running the following command in a terminal:
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
During the installation you will be prompted for your sudo password. Also, you will have the option to choose the installation prefix for Homebrew, but the default prefix is fine. During the install, you will be made the owner of the Homebrew prefix, so that you will not have to enter the sudo password to install packages. The installation will take several minutes. Once finished, run the following commands to add brew to your PATH:
```
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bash_profile
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
```
### Install and Investigate Packages
To install a package using a formula on Homebrew, simply run:
```
brew install <formula>
```
Replace &lt;formula&gt; with the name of the formula you want to install. For example, to install Minikube, simply run:
```
brew install minikube
```
You can also search for formulae with:
```
brew search <formula>
```
To get information about a formula, run:
```
brew info <formula>
```
Also, you can see all the installed formulae with the following command:
```
brew list
```
### Uninstall Packages
To uninstall a package from your Homebrew prefix, run:
```
brew uninstall <formula>
```
### Upgrade Packages
To upgrade a specific package installed with Homebrew, run:
```
brew upgrade <formula>
```
To update Homebrew and all the installed Formulae to the latest versions, run:
```
brew update
```
### Wrap Up
Homebrew is a simple package manager that can be a helpful tool alongside _dnf_ (The two are not related at all). Try to stick with the native _dnf_ package manager for Fedora to avoid software conflicts. However, if you dont find a piece of software in the Fedora Linux repositories, then you might be able to find and install it with Homebrew. See the [Formulae list][2] for what is available. Also, Homebrew on Fedora Linux does not support graphical applications (called casks in Homebrew terminology) yet. At least, I didnt have any luck installing any GUI apps.
### References and Further Reading
To learn more about Homebrew, check out the following resources:
* Homebrew Homepage: <https://brew.sh>
* Homebrew Docs: <https://docs.brew.sh>
* Wikipedia Homebrew Page: <https://en.wikipedia.org/wiki/Homebrew_(package_manager)>
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/using-homebrew-package-manager-on-fedora-linux/
作者:[Mehdi Haghgoo][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://fedoramagazine.org/author/powergame/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2022/03/homebrew_sized-up-816x346.png
[2]: https://formulae.brew.sh/formula/

View File

@ -1,160 +0,0 @@
[#]: subject: "Piwigo: An Open-Source Google Photos Alternative That You Can Self-Host"
[#]: via: "https://itsfoss.com/piwigo/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Piwigo: An Open-Source Google Photos Alternative That You Can Self-Host
======
**Brief:** _If you are moving away from Google Photos, Piwigo is an impressive open-source alternative with the ability to self-host. Lets explore more about it._
Google Photos is one of the most popular options to back up your photos and videos.
Considering that it is the default choice for most Android phones, it is a seamless experience managing photos/videos using Google Photos.
But, what if you want to move away from it for something open-source and more privacy-friendly? Not just from Google Photos, from proprietary photo hosting platforms overall.
Meet Piwigo, an open-source [photo management software][1] to the rescue.
### Piwigo: Open-Source Photo Library That You Can Self-Host
![][2]
[Piwigo][3] is an open-source solution to help manage your photos and videos.
You can choose to host it yourself, take control of your data, or opt for cloud hosting (**data stored in France, with backups**).
The company has its origins in France, if you are curious.
Not just for individuals, but Piwigo is also tailored for organizations and teams.
If you are worried about the privacy policies when you upload using Google Photos or similar services, Piwigo can be a brilliant replacement.
Piwigo offers a range of features and fine-grained control to manage your photos.
### Features of Piwigo
![][4]
While it is a viable alternative to mainstream services, it offers advanced capabilities for individuals and organizations.
Some features include:
* Get your dedicated subdomain with cloud hosting (*.piwigo.com)
* Ability to download in batch
* Create albums
* Select photos to assign existing album collections
* Share photos by link
* Access management with public and private mode
* Ability to group users to manage your albums or photos (effective for organizations/teams)
* Basic analytics to track your usage and storage used
* Supports adding tags to albums/photos
* Dark mode support
* Ability to edit the photo metadata
* Filters to quickly find a photo/album
* Support for JPG/JPEG, PNG, and GIF files (for individuals)
* Support for all file types (for enterprise use only)
* Unlimited storage for individual users
* Supports custom domain names (even for cloud hosting option)
* Plugins to extend functionalities
* Theme support
* Mobile support (Android and iOS)
In addition to the features mentioned above, you get additional options to improve the user management and the overall user experience with Piwigo.
![][5]
I tested it for a quick overview using its cloud hosting option for individuals (**with a 30-day trial period**). Let me share some of my insights to help you understand them before you try.
### Using Piwigo to Manage Photos
When you sign up for an account, you get to specify your custom subdomain.
For instance, I have my test account on **ankushsoul.piwigo.com**.
![][6]
Anyone can access my publicly shared photos/albums by entering the above URL in their browsers.
So, it is better to keep the subdomains name as unique as possible. In either case, you can also restrict the albums/photos to logged-in users (or to yourself), where no one else can access your photos even if they know your subdomain.
![][7]
You can head to its dashboard to check your storage usage and the overall activity.
There are two activated plugins, one for internal functionality and another to fight spammers by default.
![][8]
You will find plenty of plugins to enhance batch management, enable admin messages, activate comments on albums, add expiration on your albums, limit downloads, and access to several exciting features.
It would be best if you took a moment to browse the available selection of plugins to evaluate how useful they can be compared to Google Photos.
Of course, you do not get this kind of control with any mainstream cloud photo hosting services.
So, it is well worth the exploration.
![][9]
For the rest of the existing features, you can manage multiple users, control access, send notifications (via email), and also get to perform some maintenance activities.
Overall, the user experience is pretty good. It may not offer the most modern user interface, but it works and is easy to manage.
**Note**: The mobile experience (on Android) may not be satisfactory, considering the app available on the Play Store hasnt received any recent updates. However, you can find the latest version APK file on their GitHub.
### Get Started With Piwigo
I think Piwigo is perfect for a range of individuals, starting from someone who wants to organize photos, to users who want to collaborate/share pictures for work.
If you choose to self-host it, you should check out its [documentation][10] and explore the [GitHub page][11].
You will need to maintain the instance properly and have a backup of your data, considering you manage it all alone.
If you opt for the [cloud hosting option][12] (as an individual), the pricing starts at **39 Euros** per year for unlimited image file uploads and will be cheaper if you get a 3-year subscription.
![][13]
The individual plans do not mention a specific storage limit (unlimited). So, it is safe to say that you should not have any issues unless you start abusing the service.
Given the control you get with the service, most users will prefer to use the cloud hosting service and ditch services like Google Photos.
Pricing plans for enterprises/organizations will be expensive (per month). However, it supports all file types for enterprises.
[Piwigo][3]
_What do you think about a self-hosted alternative to Google Photos like Piwigo? Have you tried it? Is the cloud hosting option a viable alternative to mainstream options?_
_Let me know your thoughts in the comments below._
--------------------------------------------------------------------------------
via: https://itsfoss.com/piwigo/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/linux-photo-management-software/
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-feature.jpg?resize=800%2C424&ssl=1
[3]: https://piwigo.com/
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-album-edit.png?resize=800%2C451&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-upload.png?resize=800%2C665&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-sign-up.png?resize=800%2C646&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-dashboard.png?resize=800%2C435&ssl=1
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-plugins.png?resize=800%2C499&ssl=1
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-config.png?resize=800%2C632&ssl=1
[10]: https://piwigo.org/doc/doku.php
[11]: https://github.com/Piwigo
[12]: https://piwigo.com/pricing
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/piwigo-pricing.png?resize=800%2C509&ssl=1

View File

@ -1,85 +0,0 @@
[#]: subject: "Zorin OS 16.1 Brings Much Needed Stability and Improvements"
[#]: via: "https://www.debugpoint.com/2022/03/zorin-os-16-1-release/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Zorin OS 16.1 Brings Much Needed Stability and Improvements
======
ZORIN OS 16.1 WAS RELEASED WITH SECURITY PATCHES, NEW SOFTWARE AND THE
TEAM AIMS FOR A BETTER CAUSE.
Zorin OS is popular because it gives the perfect starting point for Windows users in their Linux journey. Thanks to its simple design, elegant selection of packages and out of the box Windows looks, its one of the popular and sought after Linux Distribution today for all users.
Coming after almost two months since [Zorin OS 16][1], this first point release is now available for download and upgrades for those who are already running the 16.0 version.
![Zorin OS 16.1 Desktop][2]
### Zorin OS 16.1 Whats New
Zorin OS 16.1 brings obvious up to date security patches for your system with goodies such as LibreOffice 7.3 office suites and several updated packages.
If you just bought a new Laptop or set up a new gaming workstation, Zorin OS 16.1 also comes with support for Sonys PlayStation 5 Dual Sense game controller and Apples Magic Mouse 2. Plus, you get excellent support for Intel 12th Gen processors and NVIDIA RTX 3050 graphics cards.
Moreover, Zorin devs promise better support for Wi-Fi cars and printers thanks to the latest packages.
Heres a quick summary of this minor releases updated packages and applications.
* Based on Ubuntu 20.04.3 LTS
* Zorin Desktop is based on GNOME 3.38.4
* LibreOffice 7.3
* Firefox 98
* Linux Kernel 5.13
* GIMP 2.10.18
* Evolution Email client
Full detail is available [here][3] if you care to dig deep into the changes.
So, where to download?
### Download
Before you hit download, you should know that it has a “Pro” version with additional themes and out of the box settings worth $39. And the “Core” version is completely free to download. You can read the comparison between “Pro” and “Core” on the download page.
[][4]
SEE ALSO:   Zorin OS 16 Released with Stunning New Look and Array of Updates
In my opinion, the Core version should be sufficient, and if you are experienced enough, you can change the settings to make it a Pro version. So we recommend the Core version for general use.
Just so you know, if you purchase the Pro version this time (within March 17), you will be helping war-torn Ukraine as the profits foes to humanitarian aid via charities.
[Download Zorin OS 16.1][5]
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][6], [Twitter][7], [YouTube][8], and [Facebook][9] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/zorin-os-16-1-release/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/2021/12/zorin-os-16-lite-review-xfce/
[2]: https://www.debugpoint.com/wp-content/uploads/2022/03/Zorin-OS-16.1-Desktop-1024x575.jpg
[3]: https://blog.zorin.com/2022/03/10/zorin-os-16-1-released-support-for-ukraine/
[4]: https://www.debugpoint.com/2021/08/zorin-os-16-release-announcement/
[5]: https://zorin.com/os/download/
[6]: https://t.me/debugpoint
[7]: https://twitter.com/DebugPoint
[8]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[9]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,209 @@
[#]: subject: "Top 10 Most Beautiful Linux Distributions [Featured]"
[#]: via: "https://www.debugpoint.com/2022/03/beautiful-linux-distributions-2022/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "amagicboy"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Top 10 Most Beautiful Linux Distributions [Featured]
======
WE GIVE YOU THE TOP 10 BEAUTIFUL LINUX DISTRIBUTIONS OF 2022. THEY ARE A
VISUAL TREAT TO YOUR EYES WHILE BEING A ROBUST OPERATING SYSTEM.
The most fantastic thing about [Linux Distributions][1] is you can customize them to any extent to satisfy your visual needs. Whether based on Ubuntu or Fedora, you have all the tools you need to customize a Linux desktop.
But, there are many Linux Distributions that looks stunning without any customization. The developers have made them so that you can experience the visual treat right after installation without any additional effort on customization.
Hence, we compiled a list of the most beautiful Linux distributions you can try right now and give your PC a visual makeover.
### Most Beautiful Linux Distributions of 2022
#### 1\. Zorin OS
The first Linux Distribution which we would like to feature is Zorin OS. The Zorin OS is a beautiful Linux distribution that uses Zorin Desktop based on GNOME. It is perfect for newcomers who wants a nice desktop but are also productive at the same time.
One of the unique features that Zorin OS brings is its ability to transform its look to make it like any other operating system. That means the taskbar, application menu, and the Dock can change with just one click option from its Layout settings, and this gives you the utmost flexibility and out of the box experience while using ZorinOS.
[Read more about Zorin OS][2]
![Zorin OS 16 Desktop][3]
#### 2\. Elementary OS
The elementaryOS is one of the most beautiful Linux distributions today based on Ubuntu Long Term Support (LTS) release. This Linux Distribution uses the stunning Pantheon Desktop environment whose look and feel is inspired by macOS.
The elementary OS is perfect for those coming from macOS to the Linux world as they would find many things familiar, such as gestures and window decorations.
However, you may not find many customization options available in elementary OS settings. You may need to depend on external script commands to make further customization. However, the default looks are beautiful and serve their purpose for the majority of the users.
The most significant advantage of elementary OS is its curated app store. The App Store provides you with all categories of applications specially designed for the elementary OS, which looks and works great.
[Read more about elementaryOS][4]
![elementary OS 6 ODIN Desktop][5]
#### 3\. Deepin OS
The third distribution which we would like to highlight is Deepin OS. The Deepin OS is based on Debian and was created by Deepin Technology Co from China. It uses its own Deepin Desktop Environment based on Qt. The Deepin desktop looks incredible with its widgets, colour schemes, window decorations, wallpapers that give you an out of the box visual treat.
With its well-polished visual components, you may think that it looks almost similar to macOS. And thanks to the Debian “stable” branch, Deepin OS is the perfect choice if you want an excellent looking Linux distribution with stability.
Why is Deepin OS beautiful?
* _Awesome Qt-based Deepin Desktop_
* _Native widgets and dark theme support_
* _Several options to customize the Dock_
* _Transparency, Window effects, CursDockheme, Icon Theme support_
* _Accent Color_
[Read more about Deepin OS][6]
![Deepin 20 Desktop][7]
#### 4\. Cutefish OS
The fourth Linux Distribution which we feature here is [CutefishOS][8]. This Debian and Ubuntu-based Linux distribution feature a natively developed Cutefish desktop. This Linux Distribution is currently under development. But due to its looks, its already making waves across the users base.
Under the hood, CutefishOS is built upon Qt and KDE Framework. This efficient Linux Distribution with Cutefish desktop features the global menu feature at the top bar out of the box.
The customization options are still being worked on as its currently under development. But with the latest release, you get the native dark mode, accent colour, animation effects, dock position (left, right, bottom), among other options.
If you want to experiment with a nice desktop that looks completely different, you may go ahead. Also, you may go over the complete review and tutorials of this desktop presented below.
[Cutefish OS Review][9]
![Cutefish OS][10]
#### 5\. Manjaro KDE Plasma
The Manjaro Linux KDE Edition is one of the best looking Linux distributions today. Based on Arch Linux, Manjaro KDE Edition features the stock KDE Plasma desktop environment with some additional tweaks and widgets. The green colour palette of Manjaro gives you a fresh look and feel. You can customize further with built-in KDE tools and settings and change icons and themes from KDE Stores.
The Manjar KDE Edition is a perfect combination of performance and beauty with the power of Arch Linux. And it is an ideal starting point for the new Arch Linux users.
[Read more about Manjaro KDE Desktop][11]
![Manjaro KDE Plasma][12]
#### 6\. Garuda Linux
The famous Garduda Linux is the 6th OS on this list. Garuda Linux is based on Arch Linux and brings a beautiful desktop for you. It features all major desktop environments with custom-designed icon themes and colour palettes. This operating system uses Zen Kernel, optimized for performance in your hardware.
[][13]
SEE ALSO:   10 Things to Do After Installing Fedora 33
The look and feel are stunning in Garuda Linux. The macOS style looks that you get out of the box. The combination of neon icon theme, lovely colour palette, blur and Transparency with the global menu is perfect for its own.
One of the primary advantages of Garuda is it provides you with the choice of all desktop environments KDE Plasma, GNOME, Xfce, LXQt, MATE and others.
[Read more about Garuda Linux][14]
![Garuda Linux][15]
#### 7\. Linux Mint Cinnamon Edition
We all love Linux Mint because of its simplicity, elegance and stability. It is one of the widely used and famous Linux distributions today. And perhaps the most used Linux distribution after Ubuntu. However, it is not that fancy looking if you compare this with other Linux Distributions here in this list.
But the default Cinnamon desktop looks clean and perfect if you like the legacy user interface, which looks fantastic.
The Linux Mint Cinnamon edition is perfect for all users, especially new users of Linux or even you are migrating from Windows. The default looks and feels with Mints green colour pallette look refreshing.
If you are unable to decide an eye candy Linux distribution with stability, choose the Linux Mint Cinnamon edition without a doubt.
[Read more about Linux Mint][16]
![Linux Mint 20 Cinnamon Edition Desktop][17]
#### 8\. Nitrux OS
[Nitrux Linux][18] is based on Debian, which features a modified version of KDE Plasma desktop called NX Desktop. This unique Linux distribution brings its own set of Nitrux applications built upon Maui kit and Qt. Nitrux is systemd-free and uses OpenRC as an init system. With all these unique features and stunning looks, it is one of the best Linux distributions today.
Nitrux OS default look is perfectly designed with modified KDE Plasma desktop with Kvantum theme engine, icon theme, colour palette and cursor theme. The team behind Nitrux OS also brings a separate desktop called Maui Shell, a beautiful convergent desktop that adapts itself based on screen size.
If you need a KDE Plasma desktop with out of the box modification with stability, then go for Nitrux OS. You wont be disappointed.
[Read more about Nitrux OS][18]
![Nitrux 2.0 + Desktop][19]
#### 9\. Ubuntu Kylin
The Ubuntu Kylin is an official Ubuntu flavour designed explicitly for the Chinese people who use a simplified Chinese script. However, it supports another language as well.
This modified Ubuntu flavour uses Ubuntu Kaylin User Interface (aka UKUI). The UKUI desktop is created using Qt to support MATE Desktop components.
Ubuntu Kylin looks elegant, and it would remind you of a combination of GNOME and KDE Plasma in terms of looks and design.
It features a nicely designed icon set, bottom taskbar, nice application view, app switcher, rounded corner, and more These features are carefully crafted.
[Read more about Ubuntu Kylin][20]
![Ubuntu Kylin Desktop][21]
#### 10\. Pop OS
The Pop OS is developed by System76, which manufactures computer hardware. This Ubuntu-based Linux Distribution comes pre-installed in all the System6 hardware. However, you can separately download and install it from its official repository in your system.
The Pop OS features the default GNOME desktop with additional tweaks and configurations. This desktop features the pre-GNOME 40 era desktop with several extensions and tweaks pre-configured. For example, you get a bottom dock that can be configured to move around in the desktop, a launcher to launch applications, rounded corners and many such features. This desktop also features auto tiling and optimized keyboard navigation to make you more productive.
The look and feel are clean and beautifully designed with a colour palette, built-in dark mode, rounded corners in the application window, and icon theme.
[Read more about Pop OS][22]
![Pop OS 21.10 Desktop][23]
### Closing Notes
I hope this list of beautiful Linux distributions of 2022 helps you decide which one you want for your desktop or laptop. Because these are already configured to look beautiful, they are powerful.
Take your pick and start your Linux journey.
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][24], [Twitter][25], [YouTube][26], and [Facebook][27] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/beautiful-linux-distributions-2022/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/category/distributions
[2]: https://zorin.com
[3]: https://www.debugpoint.com/wp-content/uploads/2021/08/Zorin-OS-16-Desktop-1024x576.jpg
[4]: https://elementary.io/
[5]: https://www.debugpoint.com/wp-content/uploads/2021/08/elementary-OS-6-ODIN-Desktop-1024x576.jpg
[6]: https://www.deepin.org/en/
[7]: https://www.debugpoint.com/wp-content/uploads/2020/09/Deepin-20-Desktop-1024x568.jpg
[8]: https://en.cutefishos.com/
[9]: https://www.debugpoint.com/2021/11/cutefish-os-review-2021/
[10]: https://www.debugpoint.com/wp-content/uploads/2021/11/Cutefish-OS-1024x581.jpg
[11]: https://manjaro.org/downloads/official/kde/
[12]: https://www.debugpoint.com/wp-content/uploads/2022/03/Manjaro-KDE-Plasma-1024x576.jpg
[13]: https://www.debugpoint.com/2020/10/10-things-to-do-fedora-33-after-install/
[14]: https://garudalinux.org/
[15]: https://www.debugpoint.com/wp-content/uploads/2022/03/Garuda-Linux-1024x577.jpg
[16]: https://linuxmint.com/
[17]: https://www.debugpoint.com/wp-content/uploads/2020/07/Linux-Mint-20-Cinnamon-Edition-Desktop-1024x763.png
[18]: https://nxos.org/
[19]: https://www.debugpoint.com/wp-content/uploads/2022/03/Nitrux-2.0-Desktop-1024x581.jpg
[20]: https://www.ubuntukylin.com
[21]: https://www.debugpoint.com/wp-content/uploads/2022/03/Ubuntu-Kylin-Desktop-1024x574.jpg
[22]: https://pop.system76.com/
[23]: https://www.debugpoint.com/wp-content/uploads/2021/12/Pop-OS-21.10-Desktop-1024x579.jpg
[24]: https://t.me/debugpoint
[25]: https://twitter.com/DebugPoint
[26]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[27]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,165 @@
[#]: subject: "XeroLinux: A Beautiful Arch-based Linux With Excellent Customizability by Default"
[#]: via: "https://itsfoss.com/xerolinux/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
XeroLinux: A Beautiful Arch-based Linux With Excellent Customizability by Default
======
Arch Linux is a popular option for Linux users who want more control over their operating system.
While many experienced users customize the Arch Linux experience to provide some of the best user experiences (in terms of its UI), it could be challenging for new Linux users.
If you are not aware of the specifics about Arch Linux, you might want to read out [Ubuntu vs Arch Linux comparison][1] article.
However, some [Arch-based distros][2] aim to offer a more accessible experience without taking the control away.
**XeroLinux** is one of the options that we recently came across.
### XeroLinux: Yet Another Arch-Based Distribution
![][3]
[XeroLinux][4] is a personal project by Steve, a.k.a. [TechXero][5] to offer an “eye-candy” version of Arch Linux.
Note that this is a passion project and not a mainstream distro backed by a big team of contributors (yet). You should try it on a VM or a test machine before replacing it on your primary system.
Here, we feature XeroLinux with a quick review for its pleasant out-of-the-box experience and a few more exciting things.
### **Ease of Installation**
XeroLinux uses [Calamares installer][6] to let you easily install the Linux distribution without needing to rely on the terminal or the [guided Arch installer][7].
While the installation experience is similar to popular Linux distros, you get the ability to select graphics drivers, specific Linux kernels, and tools as you proceed.
![][8]
You get to install System76s power management driver and enable support for Nvidia Optimus Manager to switch graphics for your Laptop. Interesting!
You also get to choose password managers, themes, browsers, and a wide range of different packages at the time of installation, which should make things convenient.
Considering you get all the essential options in the form of a selection, you do not have a lot to worry about post-installation.
![][9]
Once you select whats required, simply restart and start using the desktop.
### **User Experience**
The out-of-the-box experience with XeroLinux is impressive. The overall look and feel of the desktop include many new functional additions like the widgets to show CPU usage, network speed, and more.
It also supports the global menu, making the application window look cleaner and offering a comfortable experience for macOS users to switch to Linux.
![][10]
With all the pre-installed applications, you can easily install new software, uninstall existing tools and perform various operations.
It features both pamac and [Synaptic package manager][11] (available to select during installation). So, you get access to loads of software utilities that you can easily install through either of them.
Other offerings include two file managers (Dolphin and Thunar), Yakuake terminal, Spectacle screenshot, KWrite, Konsole, and other KDE tools in its primary KDE edition.
If you do not prefer the Yakuake terminal emulator, refer to our [list of terminal emulators][12] to find alternatives to it.
![][13]
Not to forget, you get a customized lock screen (or login screen) that looks pretty good!
![][14]
When you boot into the system, you will also notice a **XeroLinux configuration tool**. It lets you perform some essential tasks quickly, like checking for NVIDIA card, installing KVM/QEMU, disabling autostart, installing KDE window tiling, and some other configurations, as shown below.
![][15]
### **Customizability**
XeroLinux features the KDE desktop environment in its main edition. So, naturally, you get endless customization options.
It would be best to refer to our [KDE customization guide][16] to get help with it.
In addition to that, you get to see the [Latte Dock][17], which you can customize and tweak as you like.
![][18]
There are several options to customize the dock; make sure you carefully tweak the settings before things look weird.
![][19]
Moreover, you get the [Kvantum Manager][20] that can help you install external themes.
If that wasnt enough, the developer also makes a few Rice/Themes and Grub themes available that you can find listed on the [official site][4] or the [GitHub repo][21].
In other words, there are some scripts made available by the developer that can help you get a makeover but do note that it is better to customize things yourself so that nothing else breaks.
### **Desktop Environment Options**
The primary edition features KDE, but you also have another XFCE variant if you want to give it a try.
The XFCE edition is tailored for older systems (or if you need to save up system resources).
It did offer a GNOME edition initially, but it dropped support for it due to issues with extensions breaking, with every update. You might want to go through our [KDE Plasma vs GNOME][22] article to know the differences if youre curious about the desktop environments.
### **Performance**
Considering it features the latest available [Linux Kernel 5.16][23], it should work fine with a variety of hardware configurations.
However, I havent tested it on bare metal. As per my experience with it as a virtual machine, it worked well without any peculiar issues.
Heres what the resource usage looks like on its KDE edition:
![][24]
You may notice lower resource usage when using its XFCE variant.
### Should You Try XeroLinux?
I enjoyed the look and feel that I got with XeroLinux.
Not just limited to that, you also get several package choices and the ability to choose the best of Linux right at the time of installation.
[Try XeroLinux][4]
If you know what you need at the time of installation, it should be an attractive Arch-based Linux distribution for you.
Have you tried XeroLinux yet? Let me know your thoughts in the comments below.
--------------------------------------------------------------------------------
via: https://itsfoss.com/xerolinux/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/ubuntu-vs-arch/
[2]: https://itsfoss.com/arch-based-linux-distros/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-home.jpg?resize=800%2C450&ssl=1
[4]: https://xerolinux.xyz/
[5]: https://twitter.com/TechXero
[6]: https://calamares.io/
[7]: https://itsfoss.com/install-arch-linux-virtualbox/
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-install-1.png?resize=800%2C555&ssl=1
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-install.png?resize=800%2C555&ssl=1
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-ui.jpg?resize=800%2C398&ssl=1
[11]: https://itsfoss.com/synaptic-package-manager/
[12]: https://itsfoss.com/linux-terminal-emulators/
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-utilities.jpg?resize=800%2C652&ssl=1
[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-lockscreen.jpg?resize=800%2C546&ssl=1
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-configuration-tool.jpg?resize=800%2C480&ssl=1
[16]: https://itsfoss.com/kde-customization/
[17]: https://github.com/KDE/latte-dock
[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-latte-dock.png?resize=800%2C134&ssl=1
[19]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-latte-dock-options.jpg?resize=800%2C570&ssl=1
[20]: https://store.kde.org/p/1005410/
[21]: https://github.com/xerolinux/xero-layan-git
[22]: https://itsfoss.com/kde-vs-gnome/
[23]: https://news.itsfoss.com/linux-kernel-5-16/
[24]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/xerolinux-resource.png?resize=800%2C468&ssl=1

View File

@ -0,0 +1,142 @@
[#]: subject: "Mabox Linux Beautiful Arch Linux with Openbox [Review]"
[#]: via: "https://www.debugpoint.com/2022/03/mabox-linux-2022/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Mabox Linux Beautiful Arch Linux with Openbox [Review]
======
MABOX LINUX IS A MANJARO LINUX RE-SPIN WITH A LIGHTWEIGHT OPENBOX WINDOW
MANAGER, READY TO USE WITH PRE-CONFIGURED THEMES AND UTILITIES. WE
REVIEW THE DISTRIBUTION IN THIS POST.
If you love window manager, rolling-release-based Arch Linux and are looking for a ready-made Linux distribution with this combination, try Mabox Linux. The Mabox Linux is built on top of the great Manjaro Linux with Openbox Window manager and several native utilities.
Thanks to the Openbox, this Linux distribution is super-lightweight in resource consumption while being a beautiful desktop for everyone to use. The Mabox Linux tools adapted from BunsenLabs and inspired by Crunchbang brings some of their applications.
Lets do a deep dive on this awesome Linux Distribution.
### Mabox Linux Review
#### Installation and Live Medium
One of the advantages of Mabox .ISO is it provides you free and proprietary drivers both the options during the LIVE medium boot process. This helps if you have NVIDIA or other hardware in the system.
The LIVE desktop lets you install Mabox via the Calamares installer. The installation takes around 3 to 4 minutes on standard hardware, and it is error-free in my test.
The installer is managed to detect the other operating systems in the test device.
#### Look and Feel with Customization
Mabox brings a pre-configured Openbox window manager. The stock version looks nice with dark skin and a menu with panels.
The top panel is built using Tint2 and split into two sections. And Left panel gives you shortcuts to the main menu, file manager, web browser. Also, the panel have a different menu for the left and right-click mouse button. The right panel contains a resource monitor, volume control, screenshot shortcut and power menu. The top panel is not continuous and stay on top for application windows for certain themes.
![Mabox Linux with Nord Theme][1]
At the right section of the desktop, the pre-configured Conky script gives you system information with date, time, storage and other displays.
The welcome window gives you quick start shortcuts on settings, help and support with links to documentation.
The window managers are keyboard friendly and sometimes have trouble with the Mouse. But thanks to Openbox and pre-configured Mabox, you can easily use Mouse while increasing your productivity with nifty keyboard shortcuts.
The right-click menu on the desktop gives you easily search and launch options.
![Search and Launch from desktop][2]
If you do not like the default look, you can customize it on your own with just a few clicks via Openbox and Tint2 panel configuration tool.
![Main Application Menu][3]
Mabox has different themes as pre-set, including Panel and Concky scripts. You can click and apply with these stunning Mabox themes. It is one of the excellent features if you do not want to get into the hassles of configuring the panels, colours and Conky on your own.
[][4]
SEE ALSO:   KDE Plasma 5.21 Review - Perhaps the Worthy Linux Desktop to Take on Windows
A good set of nice wallpaper gives you the flexibility to make it look more fabulous in no time.
![Mabox Themes][5]
#### Applications
Mabox Linux packages all necessary applications in its installer image. Here is a quick list of essential applications that are included.
* Terminal terminator
* Xpad quick text pad
* File manager PCManFM
* FSearch for desktop file search
* Flameshot screenshot utility
* Geany text editor
* Audacious music player
* Firefox web browser
Mabox also includes its control centre to manage your system effectively. Mabox control center gives you the option to add/remove applications, update your system, launch several configuration windows for window manager components and many such options.
If you cannot find any settings, you can easily find them in the Mabox control center via its logical grouping of system settings.
![Mabox Control Center][6]
#### What about the performance?
The performance of Mabox Linux is super impressive. Thanks to the Openbox window manager, Mabox only uses around 350+ MB of RAM while the CPU hovers at 2% to 3% during the idle state.
The default installation takes around 5.39 GB of disk space which is unbelievable with all these applications and settings programs pre-installed.
It is so optimized that the highest app consuming more memory is Xorg with 90 MB.
So, I thought of trying out heavy usage performance. And that performance is also surprising. I opened a file manager, Firefox, with three tabs, one text editor for development, a terminal window and the Control Center. With this workload, Mabox only consumes around 920 MB of memory and CPU at 6% to 7%.
![Mabox Linux Heavy Workload Performance][7]
During the [review of several distributions][8], this is the first time I found a distro that did not cross 1 GB of memory during a heavy workload. But the results may vary in different use cases. Still, the metric is impressive.
### Can Mabox Linux be used as daily driver?
If you are familiar and comfortable with Arch Linux with the window manager, you can use Mabox Linux as a daily driver. A few well-packaged Arch Linux distros are available with a window manager, and Mabox is one of the best.
![Mabox Linux Windows 95 pre-configured theme][9]
### Summary
I think the Mabox Linux team did a great job packaging all the components with Arch Linux and presented with a nice Linux Distribution. It does look stunning while consuming very few system resources. With the power of rolling-release based Arch Linux, I think you can trust this distro for long term usage.
You can download Mabox Linux from its [official webpage][10].
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][11], [Twitter][12], [YouTube][13], and [Facebook][14] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/mabox-linux-2022/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/03/Mabox-Linux-with-Nord-Theme-1024x581.jpg
[2]: https://www.debugpoint.com/wp-content/uploads/2022/03/Search-and-Launch-from-desktop.jpg
[3]: https://www.debugpoint.com/wp-content/uploads/2022/03/Main-Application-Menu.jpg
[4]: https://www.debugpoint.com/2021/03/kde-plasma-5-21-review/
[5]: https://www.debugpoint.com/wp-content/uploads/2022/03/Mabox-Themes.jpg
[6]: https://www.debugpoint.com/wp-content/uploads/2022/03/Mabox-Control-Center.jpg
[7]: https://www.debugpoint.com/wp-content/uploads/2022/03/Mabox-Linux-Heavy-Workload-Performance-1024x508.jpg
[8]: https://www.debugpoint.com/tag/linux-distro-review
[9]: https://www.debugpoint.com/wp-content/uploads/2022/03/Mabox-Linux-Windows-95-preconfigured-theme-1-1024x577.jpg
[10]: https://maboxlinux.org/
[11]: https://t.me/debugpoint
[12]: https://twitter.com/DebugPoint
[13]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[14]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,162 @@
[#]: subject: "10 Features Why GNOME 42 is the Greatest Release Ever"
[#]: via: "https://www.debugpoint.com/2022/03/gnome-42-release/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
10 Features Why GNOME 42 is the Greatest Release Ever
======
WE THINK THESE GNOME 42 RELEASE FEATURES MAKE IT ONE OF THE GREAT
RELEASES IN GNOMES HISTORY. HERES WHY.
The GNOME Desktop is the most widely used desktop environment today. And it is probably the only desktop that new users to Linux experience for the first time. GNOME is the default desktop environment for Ubuntu and Fedora Linux. Hence its user base is in millions. 
The upcoming GNOME 42 releases soon. And perhaps its one of the best releases so far in terms of new features, adoption of modern tech and moving away from the legacy codebase. 
The core, look and feel under the hood changes everything looks different for new and experienced users.
![GNOME 42 Desktop][1]
In this article, we would like to give you a tour of 10 features of GNOME 42, which makes it a significant release. 
### Great Features of GNOME 42 Release
#### 1\. Libadwaita and GTK4
The libadwaita library is the modern building block for GTK4 applications. Its the GTK4 port of the libhandy library that defines the visual language of the GNOME desktop. The adoption of libadwaita is complex, and it impacts almost every modules component of the modern GNOME desktop, including the native applications. Imagine how difficult it is for a complete libadwaita and GTK4 adoption in development efforts, testing and other regressions.
The work started in GNOME 41 is now nearing completion in this GNOME 42 release. But what are the changes?
The libadwaita and GTK4 changes are visible in every user interface of the entire desktop. For example, you can see the flat buttons, well-justified labels, new colours, rounded corners, refined controls, etc. 
Hence, from Files to Web, the Shell controls, menu items everything would look stunning with libadwaita and GTK4 in the GNOME 42 release.
#### 2\. Updated GNOME Shell Theme
The GNOME default Shell theme changed in several places. In this release, those items menus, notifications, and overall look are more compact.
The menu items at the top bar, such as the Calendar or the system tray menu, are now closer to the top bar. The spacing between the text and options inside the menu is decreased. 
![GNOME 42 Shell updates][2]
The on-screen display notifications are changed. Earlier, it used to be the large boxes with notification labels that are now changed to “pills” with a lesser display footprint. 
![Revamped OSD and menu in GNOME 42][3]
And also, some inside performance boost makes GNOME 42 much faster than its predecessors.
#### 3\. Adaptive Dark Theme
If you love dark themes and want your app to honour the systems dark look, you are in for a treat. The GNOME 42, with the help of libadwaita, brings native dark mode for all the supported applications. 
If you choose a dark theme for GNOME Shell, the apps also follow that shells system style.
For example, if you choose the below option in the new Text editor, it changes to a dark theme when you change the GNOME Shell theme.
![This option makes it follow dark and light theme automatically][4]
However, this feature needs to be implemented by the app developer to consume the exposed Shell settings.
#### 4\. Revamped System Settings with new Appearances
The fulcrum of the entire GNOME desktop is its settings window. From the settings window, you can tweak most of the desktop behaviour. The setting application itself is a complex app, and its ported to libadwaita. So, the looks of it changed with new styled widgets and controls. 
One of the vital changes in the Settings window is the new Appearance page. This page gives you the option to view and toggle the desktop theme between light and dark. 
The Sharing page in the settings window gives you a redesigned remote desktop dialog showing options and preferences for remote desktop connection via RDP (not VNC).
![Appearance page in Settings][5]
#### 5\. Wallpaper that switches automatically with theme
The above appearance page in settings also gives you a nice side-by-side look of the light and dark version. And when you change the system theme, the wallpaper also changes automatically! This is by far the most remarkable feature that GNOME 42 release brings.
[][6]
SEE ALSO:   10 Things To Do After Installing Linux Mint 19 - Tara
#### 6\. Files icon change
The default folder icons in Files (Nautilus) didnt change for many years. In my opinion, everything changed over the years, but this piece remains the same. In GNOME 42, the folder icons colour in the Files file manager changes to light blue. 
Arguably, blue might not be the best colour considering every aspect. But blue still goes well with GNOMEs default wallpaper and other component pallets. And a change to the default Files look is always welcome.
![Files with new color folders in GNOME 42][7]
#### 7\. A brand new text editor
A new Text Editor replaces the famous and fabulous Gedit in GNOME 42. The Gedit is a powerful and time-tested utility, and replacing all of its functionality takes time. The new Text Editor is built in GTK4 from scratch and brings some outstanding features, including built-in themes and light and dark mode. More features are expected to arrive in Text Editor in future.
To be clear, Gedit doesnt go away. Its still there in the respective Linux distributions repo, and you can install it whatever you want.
You can read our exclusive piece on Gedit and GNOME Text Editor below.
[Features about GNOME Text Editor][8]
[Why Gedit is the great text editor][9]
#### 8\. A native screenshot tool
One of the best features of the GNOME 42 release is the built-in screenshot and screen recording tool. You do not install any additional app for this. Your life will be easier with this tool, which takes care of the screenshot and screen recording with its nifty user interface when you press the `Print Screen` button.
In earlier releases, hitting the Print Screen takes the entire desktop screenshot and saves it. Now, you need to hit Enter key after pressing Print Screen from the keyboard. 
![GNOME 42 introduces new screenshot tool][10]
#### 9\. Stunning Wallpapers
A set of awesome wallpapers is about to treat you and give your favourite GNOME 42 desktop a visual uplift. And the wallpapers also have a dark version, which is set automatically when you choose dark over light.
#### 10\. Other Changes
Some of the misc changes in the GNOME 42 release is the Eye of GNOME (image viewer) received a much-needed performance boost, Web browser GNOME Web now support hardware acceleration and user interface update in Maps. Also, a new Console application is a nice add on to this release which replaces GNOME Terminal.
So, thats about significant changes. But many changes make GNOME 42 release is one of the biggest releases in its history. 
### How to get GNOME 42
GNOME 42 releases on March 23, 2022, and you get to experience it via [GNOME OS][11] right away.
If you plan to get it via Linux Distribution, you have to wait for a little. [Ubuntu 22.04 LTS][12] will feature GNOME 42 (partial), due April 2022. And [Fedora 36][13], which is expected in April as well.
If you are an Arch Linux user, GNOME 42 will arrive soon in the main extra repo. Keep a watch on [this page][14] or check your Arch system via the usual `pacman -Syu` command. 
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][15], [Twitter][16], [YouTube][17], and [Facebook][18] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/gnome-42-release/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-42-Desktop-1024x563.jpg
[2]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-42-Shell-updates.jpg
[3]: https://www.debugpoint.com/wp-content/uploads/2022/03/Revamped-OSD-and-menu-in-GNOME-42.jpg
[4]: https://www.debugpoint.com/wp-content/uploads/2022/03/This-option-makes-it-folow-dar-and-light-theme-automatically.jpg
[5]: https://www.debugpoint.com/wp-content/uploads/2022/03/Appearance-page-in-Settings-1024x708.jpg
[6]: https://www.debugpoint.com/2018/08/10-things-to-do-after-installing-linux-mint-19-tara/
[7]: https://www.debugpoint.com/wp-content/uploads/2022/03/Files-with-new-color-folders-in-GNOME-42.jpg
[8]: https://www.debugpoint.com/2021/12/gnome-text-editor/
[9]: https://www.debugpoint.com/2021/04/gedit-features/
[10]: https://www.debugpoint.com/wp-content/uploads/2022/03/GNOME-42-introduces-new-screenshot-tool-1024x699.jpg
[11]: https://os.gnome.org/
[12]: https://www.debugpoint.com/2022/01/ubuntu-22-04-lts/
[13]: https://www.debugpoint.com/2022/02/fedora-36/
[14]: https://archlinux.org/groups/x86_64/gnome/
[15]: https://t.me/debugpoint
[16]: https://twitter.com/DebugPoint
[17]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[18]: https://facebook.com/DebugPoint

View File

@ -0,0 +1,427 @@
[#]: subject: "Implementing a toy version of TLS 1.3"
[#]: via: "https://jvns.ca/blog/2022/03/23/a-toy-version-of-tls/"
[#]: author: "Julia Evans https://jvns.ca/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Implementing a toy version of TLS 1.3
======
Hello! Recently Ive been thinking about how I find it fun to learn computer networking by implementing working versions of real network protocols.
And it made me wonder Ive implemented toy versions of [traceroute][1], [TCP][2] and [DNS][3]. What about TLS? Could I implement a toy version of that to learn more about how it works?
I asked on Twitter if this would be hard, got [some encouragement and pointers for where to start][4], so I decided to go for it.
This was really fun and I learned a little more about how involved real cryptography is thanks to [cryptopals][5], I already 100% believed that I should not invent my own crypto implementations, and seeing how the crypto in TLS 1.3 works gave me even more of an appreciation for why I shouldnt :)
As a warning: I am really not a cryptography person, I will probably say some incorrect things about cryptography in this post and I absolutely do not know the history of past TLS vulnerabilities that informed TLS 1.3s design.
All of that said, lets go implement some cryptography! All of my hacky code is [on github][6]. I decided to use Go because I heard that Go has good crypto libraries.
### the simplifications
I only wanted to work on this for a few days at most, so I needed to make some pretty dramatic simplifications to make it possible to get it done quickly.
I decided my goal was going to be to download this blogs homepage with TLS. So I dont need to implement a fully general TLS implementation, I just need to successfully connect to one website.
Specifically, this means that:
* I only support one cipher suite
* I dont verify the servers certificate at all, I just ignore it
* my parsing and message formatting can be extremely janky and fragile because I only need to be able to talk to one specific TLS implementation (and believe me, they are)
### an amazing TLS resource: tls13.ulfheim.net
Luckily, before starting this I remembered vaguely that Id seen a website that explained every single byte in a TLS 1.3 connection, with detailed code examples to reproduce every part. Some googling revealed that it was [The New Illustrated TLS Connection][7].
I cant stress enough how helpful this was, I looked at probably more than a hundred times and I only looked at the TLS 1.3 RFC for a few small things.
### some cryptography basics
Before I started working on this, my understanding of TLS was:
1. at the beginning theres some sort of Diffie-Hellman key exchange
2. you use the key exchange to somehow (how???) get an AES symmetric key and encrypt the rest of the connection with AES
This was sort of right, but it turns out its more complicated than that.
Okay, lets get into my hacky toy TLS implementation. It hopefully goes without saying that you should absolutely not use this code for anything.
### step 1: say hello
First we need to send a “Client Hello” message. For my purposes this has just 4 pieces of information in it:
1. A randomly generated public key
2. 32 bytes of random data (the “Client Random”)
3. The domain name I want to connect to (`jvns.ca`)
4. The cipher suites/signature algorithms we want to use (which I just copied from tls.ulfheim.net). This negotiation process is pretty important in general but Im ignoring it because I only support one signature algorithm / cipher suite.
The most interesting part of this to me was part 1 how do I generate the public key?
I was confused about this for a while but it ended up being just 2 lines of code.
```
privateKey := random(32)
publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
```
You can see the rest of the code to generate the [client hello message here][8] but its very boring, its just a lot of bit fiddling.
### elliptic curve cryptography is cool
I am not going to give an explanation of elliptic curve cryptography here, but I just want to say how point out how cool it is that you can:
* generate a random 32-byte string as a private key
* “multiply” the private key by the curves base point to get the public key (this is elliptic curve “multiplication”, where `n * P` means “add P to itself n times”)
* thats it!!
I am not going to say more about elliptic curve cryptography here but I love how simple this is to use it seems a lot straightforward than RSA where your private keys have to be prime numbers.
I dont know if “you can use any 32-byte string as a private key” is true for all elliptic curves or just for this specific elliptic curve ([Curve25519][9]).
### step 2: parse the server hello
Next the server says hello. This is very boring, basically we just need to parse it to get the servers public key which is 32 bytes. [Heres the code though][10].
### step 3: calculate the keys to encrypt the handshake
Now that we have the servers public key and weve sent the server our public key, we can start to calculate the keys were going to use to actually encrypt data.
I was surprised to learn that there are at least 4 different symmetric keys involved in TLS:
* client handshake key/iv (for the data the client sends in the handshake)
* server handshake key/iv (for the data the server sends in the handshaek)
* client application key/iv (for the rest of the data the client sends)
* server application key/iv (for the rest of the data the server sends)
* I think also another key for session resumption, but I didnt implement that
We start out by combining the servers public key and our private key to get a shared secret. This is called “elliptic curve diffie hellman” or ECDH and its pretty simple: “multiply” the servers private key by our public key:
```
sharedSecret, err := curve25519.X25519(session.Keys.Private, session.ServerHello.PublicKey)
```
This gives us a 32-byte secret key that both the client and the server has. Yay!
But we need 96 bytes (16 + 12) * 4 of keys in total. Thats more than 32 bytes!
### time for key derivation
Apparently the way you turn a small key into more keys is called “key derivation”, and TLS 1.3 uses an algorithm called “HKDF” to do this. I honestly do not understand this but here is what my code to do it looks like.
It seems to involve alternately calling `hkdf.Expand` and `hkdf.Extract` over and over again a bunch of times.
```
func (session *Session) MakeHandshakeKeys() {
zeros := make([]byte, 32)
psk := make([]byte, 32)
// ok so far
if err != nil {
panic(err)
}
earlySecret := hkdf.Extract(sha256.New, psk, zeros) // TODO: psk might be wrong
derivedSecret := deriveSecret(earlySecret, "derived", []byte{})
session.Keys.HandshakeSecret = hkdf.Extract(sha256.New, sharedSecret, derivedSecret)
handshakeMessages := concatenate(session.Messages.ClientHello.Contents(), session.Messages.ServerHello.Contents())
cHsSecret := deriveSecret(session.Keys.HandshakeSecret, "c hs traffic", handshakeMessages)
session.Keys.ClientHandshakeSecret = cHsSecret
session.Keys.ClientHandshakeKey = hkdfExpandLabel(cHsSecret, "key", []byte{}, 16)
session.Keys.ClientHandshakeIV = hkdfExpandLabel(cHsSecret, "iv", []byte{}, 12)
sHsSecret := deriveSecret(session.Keys.HandshakeSecret, "s hs traffic", handshakeMessages)
session.Keys.ServerHandshakeKey = hkdfExpandLabel(sHsSecret, "key", []byte{}, 16)
session.Keys.ServerHandshakeIV = hkdfExpandLabel(sHsSecret, "iv", []byte{}, 12)
}
```
This was pretty annoying to get working because I kept passing the wrong arguments to things. The only reason I managed it was because <https://tls13.ulfheim.net> provided a bunch of example inputs and outputs and example code so I was able to write some unit tests and check my code against the sites example implementation.
Anyway, eventually I got all my keys calculated and it was time to start decrypting!
### an aside on IVs
For each key theres also an “IV” which stands for “initialization vector”. The idea seems to be to use a different initialization vector for every message we encrypt/decrypt, for More Security ™.
In this implementation the way we get a different IV for each message is by xoring the IV with the number of messages sent/received so far.
### step 4: write some decryption code
Now that we have all these keys and IVs, we can write a `decrypt` function.
I thought that TLS just used AES, but apparently it uses something called “authentication encryption” on top of AES that I hadnt heard of before.
The wikipedia article explanation of authenticated encryption is actually pretty clear:
> … authenticated encryption can provide security against **chosen ciphertext** attack. In these attacks, an adversary attempts to gain an advantage against a cryptosystem (e.g., information about the secret decryption key) by submitting carefully chosen ciphertexts to some “decryption oracle” and analyzing the decrypted results. Authenticated encryption schemes can recognize improperly-constructed ciphertexts and refuse to decrypt them. This, in turn, prevents the attacker from requesting the decryption of any ciphertext unless it was generated correctly using the encryption algorithm
This makes sense to me because I did some of the cryptopals challenges and theres an attack a bit like this in [cryptopals set 2][11] (I dont know if its the exact same thing).
Anyway, heres some code that uses authenticated encryption the way the TLS 1.3 spec says it should. I think GCM is an authenticated encryption algorithm.
```
func decrypt(key, iv, wrapper []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
additional := wrapper[:5]
ciphertext := wrapper[5:]
plaintext, err := aesgcm.Open(nil, iv, ciphertext, additional)
if err != nil {
panic(err.Error())
}
return plaintext
}
```
### step 5: decrypt the server handshake
Next the server sends some more handshake data. This contains the certificate and some other stuff.
Heres my code for decrypting the handshake. Basically it just reads the encrypted data from the network, decrypts it, and saves it.
```
record := readRecord(session.Conn)
if record.Type() != 0x17 {
panic("expected wrapper")
}
session.Messages.ServerHandshake = decrypt(session.Keys.ServerHandshakeKey, session.Keys.ServerHandshakeIV, record)
```
You might notice that we dont actually _parse_ this data at all thats because we dont need the contents, since were not verifying the servers certificate.
I was surprised that you dont technically need to look at the servers certificate at all to make a TLS connection (though obviously you should verify it!). I thought you would need to at least parse it to get a key out of it or something.
We do need to be able to hash the handshake for the next step though, so we have to store it.
### step 6: derive more keys
We use a hash of the SHA256 handshake data we just got from the server to generate even more symmetric keys. This is almost the last step!
This is almost exactly the same as the key derivation code from before, but Im including it because I was surprised by how much work needed to be done to generate all these keys.
```
func (session *Session) MakeApplicationKeys() {
handshakeMessages := concatenate(
session.Messages.ClientHello.Contents(),
session.Messages.ServerHello.Contents(),
session.Messages.ServerHandshake.Contents())
zeros := make([]byte, 32)
derivedSecret := deriveSecret(session.Keys.HandshakeSecret, "derived", []byte{})
masterSecret := hkdf.Extract(sha256.New, zeros, derivedSecret)
cApSecret := deriveSecret(masterSecret, "c ap traffic", handshakeMessages)
session.Keys.ClientApplicationKey = hkdfExpandLabel(cApSecret, "key", []byte{}, 16)
session.Keys.ClientApplicationIV = hkdfExpandLabel(cApSecret, "iv", []byte{}, 12)
sApSecret := deriveSecret(masterSecret, "s ap traffic", handshakeMessages)
session.Keys.ServerApplicationKey = hkdfExpandLabel(sApSecret, "key", []byte{}, 16)
session.Keys.ServerApplicationIV = hkdfExpandLabel(sApSecret, "iv", []byte{}, 12)
}
```
### step 7: finish the handshake
Next we need to send a “handshake finished” message to the server to verify that everything is done. That code is [here][12].
And now were done the handshake! That was the hard part, sending and receiving the data is relatively easy.
### step 8: make a HTTP request
I wrote a `SendData` function that encrypts and sends data using our keys. This time were using the “application” keys and not the handshake keys. This made making a HTTP request pretty simple:
```
req := fmt.Sprintf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", domain)
session.SendData([]byte(req))
```
### step 9: we can actually decrypt the response!!!
Now comes the moment Id been waiting for — actually decrypting the response from the server!!! But here I needed to learn something else about TLS.
### TLS data comes in blocks
I previously thought that once you established the connection, encrypted TLS data was just a stream. But thats not how it works instead, its transmitted in blocks. Like, youll get a chunk of ~1400 bytes to decrypt, and then another chunk, and then another chunk.
Im not sure why the blocks have the size they do (maybe its so that each one will fit inside a TCP packet ???), but in theory I think they could be up to 65535 bytes, since their size field is 2 bytes. The blocks I got were all 1386 bytes each.
Every time we get a block, we have to:
* calculate a new IV as `old_iv xor num_records_received`
* decrypt it using the key and the new IV
* increment the count of records received
Heres what the `ReceiveData()` function I wrote looks like.
The most interesting part of this is the `iv[11] ^= session.RecordsReceived` thats the part that adjusts the IV for each block.
```
func (session *Session) ReceiveData() []byte {
record := readRecord(session.Conn)
iv := make([]byte, 12)
copy(iv, session.Keys.ServerApplicationIV)
iv[11] ^= session.RecordsReceived
plaintext := decrypt(session.Keys.ServerApplicationKey, iv, record)
session.RecordsReceived += 1
return plaintext
}
```
This `iv[11]` thing assumes that there are less than 255 blocks which obviously is not true in general in TLS, but I was lazy and to download my blogs homepage I only needed 82 blocks.
We actually have to do this when we send data too, but I didnt implement it because we only sent 1 packet.
### problem: getting the whole block of tLS data
I ran into one problem with TCP where sometimes Id try to read a block of TLS data (~1386 bytes), but I wouldnt get the whole thing. I guess the TLS blocks can be split up across multiple TCP packets.
I fixed this in a really dumb way, by just polling the TCP connection in a loop until it gave me the data I wanted. Heres my code to do that:
```
func read(length int, reader io.Reader) []byte {
var buf []byte
for len(buf) != length {
buf = append(buf, readUpto(length-len(buf), reader)...)
}
return buf
}
```
I assume a real TLS implementation would use a thread pool or coroutines or something to manage this.
### step 10: knowing when were done
When the HTTP response is done, we get these bytes: `[]byte{48, 13, 10, 13, 10, 23}`. I dont know what this is supposed to mean exactly but it seems to signal the end of the connection.
So heres the code to receive the HTTP response. Basically we just loop until we see those bytes, then we stop.
```
func (session *Session) ReceiveHTTPResponse() []byte {
var response []byte
for {
pt := session.ReceiveData()
if string(pt) == string([]byte{48, 13, 10, 13, 10, 23}) {
break
}
response = append(response, pt...)
}
return response
}
```
### thats it!
Finally, I ran the program and I downloaded my blogs homepage! It worked! Heres what the results look like:
```
$ go build; ./tiny-tls
HTTP/1.1 200 OK
Date: Wed, 23 Mar 2022 19:37:47 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
... lots more headers and HTML follow...
```
Okay, the results are kind of anticlimactic, its just the same as what youd see if you ran `curl -i https://jvns.ca` except with no formatting. But I was extremely excited when I saw it.
### the block thing is kind of weird
I find it a bit weird that TLS data is sent/received in blocks. I assume it makes sense from a cryptography perspective (because you want to change your IVs frequently or something?).
But from a networking perspective it feels a bit strange. Like, TCP is built on top of a packet system, and then with TLS you sort of have another packet system on top of TCP.
Maybe one of the motivations for QUIC is to design a network protocol which has TLS as more of a first-class citizen, so you dont have this weird packet/stream/packet thing?
### some things I learned
This was really fun! I learned that
* elliptic curve diffie-hellman is very cool, and at least with Curve25519 you can use literally any 32-byte string as a private key
* there are a LOT of different symmetric keys involved in TLS and the key derivation process is pretty complicated
* TLS uses AES with some extra “authenticated encryption” algorithms on top
* TLS data is sent/received as a bunch of blocks, not as a stream
My code truly is terrible, it can connect to my site (`jvns.ca`) and I think literally no other sites.
I wont pretend to understand all the reasons TLS is designed this way, but it was a fun way to spend a couple of days, I feel a little more informed, and I think itll be easier for me to understand things I read about TLS in the future.
### a plug for cryptopals
If you want to learn about cryptography and you havent tried the [cryptopals][5] challenges, I really recommend them you get to implement a lot of attacks on crypto systems and its very fun.
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/2022/03/23/a-toy-version-of-tls/
作者:[Julia Evans][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://jvns.ca/
[b]: https://github.com/lujun9972
[1]: https://jvns.ca/blog/2013/10/31/day-20-scapy-and-traceroute/
[2]: https://jvns.ca/blog/2014/08/12/what-happens-if-you-write-a-tcp-stack-in-python/
[3]: https://jvns.ca/blog/2022/02/01/a-dns-resolver-in-80-lines-of-go/
[4]: https://twitter.com/Lukasaoz/status/1505593360521777157
[5]: https://cryptopals.com/
[6]: https://github.com/jvns/tiny-tls/
[7]: https://tls13.ulfheim.net
[8]: https://github.com/jvns/tiny-tls/blob/cb5a3665c3487ad1f1d5f917ad069c93dd44967e/format.go#L41
[9]: https://en.wikipedia.org/wiki/Curve25519
[10]: https://github.com/jvns/tiny-tls/blob/cb5a3665c3487ad1f1d5f917ad069c93dd44967e/format.go#L98-L131
[11]: https://cryptopals.com/sets/2/challenges/14
[12]: https://github.com/jvns/tiny-tls/blob/cb5a3665c3487ad1f1d5f917ad069c93dd44967e/crypto.go#L177-L183

View File

@ -0,0 +1,141 @@
[#]: subject: "Budibase: An Open-Source Low-Code Platform to Build Modern Business Apps"
[#]: via: "https://itsfoss.com/budibase/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: " "
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Budibase: An Open-Source Low-Code Platform to Build Modern Business Apps
======
You may come across a variety of tools to help you quickly build apps for your business.
However, most of the trusted options are often proprietary products. So, you will be locked into their platform without knowing enough about what you utilize to build the apps.
An open-source solution should be a perfect replacement, giving you peace of mind, and confidence about your critical business apps.
Budibase is one such impressive solution.
### Budibase: Open-Source Low-Code Platform to Make Things Easy
Budibase is an increasingly popular open-source low-code platform that can help you build apps for your business.
You can create apps from scratch or use existing templates to quickly build forms, an agency-client portal, car rental admin panel, a portal for accountants, job application tracker, and many more.
![][1]
While it does make things easy without you needing the necessary programming skills, it also offers control to let you customize the apps to an extent.
It supports a range of data sources: MySQL, Rest API, OracleDB, MongoDB, Google Sheets, and others.
You can choose to self-host it and deploy the applications on your server, or utilize Budibases cloud hosting offering.
### Features of Budibase
[Budibase][2] offers most of the essential features. Let me highlight the important ones here:
* Supports external data sources including MongoDB, MySQL, etc.
* Rest API to pull data.
* Ability to use built-in database for apps or upload a CSV to import data.
* Variety of data types and functionality including attachments, relationships, formulas, and more.
* API integration platform to integrate different APIs and help you build internal apps, forms, and more easily.
* Ability to generate auto-screens using an internal table
* Build single page applications
* Auto-generated CRUD (Create, Read, Update, and Delete) screens
* Private and public applications
* Customize the theme of your app in a few clicks.
* Easy to implement a dark mode theme for your app
* A feature-rich form builder to satisfy a wide range of requirements
* Webhook support
* Third-party integration with Zapier, and more.
* Flexible automation options based on particular triggers.
* Ability to add JavaScript to your automations.
* Self-host option for users with their own infrastructure.
* Free Single Sign-On for authentication/admin.
* User management options to assign team to different apps
* SMTP email support.
* Email templates to match your brand and style.
* OAuth log in support. Limited to Google as of now.
* Charts, Tables, and Cards to present data elegantly.
Overall, there is a lot more to explore once you sign in to the service and check out its offerings.
In my brief usage, I found the user interface comfortable and easy to use. To give you additional insights, I have shared more about using Budibase below.
### Using Budibase to Build an App Quickly
The user experience is the primary factor when using such services.
Budibase does not disappoint you in this regard. You get an excellent user experience when you start using Budibase.
As far as Ive used open-source platforms, the user experience is not always the strong point. But, in this case, its the user experience that makes the tool easy to use.
You can quickly get started building an app, adding your sources, and start designing it in a few clicks.
![][3]
You are welcome to choose the internal database or opt for an external source. The platform lets you edit/create/import data as required.
![][4]
And, in a few clicks (depending on the scale of your application), you can get started designing the screens and tweaking the layout.
![][5]
It is entirely a visual editor, so you get what you see. Add containers, section, forms, cards, charts, and many other elements to the layout.
![][6]
Tweaking the theme is a breeze. So, you can match your brand style/accent or just go creative as per your requirements.
![][7]
You can edit the data seamlessly, create new data fields, and enable search indexes for the data as well.
![][8]
Not to forget, you also get all the automation options to integrate with other services, respond to triggers using webhook, corn jobs, or an app action. These are some of the most important things to build one of the most effective applications for your users.
Heres how it looks when I built a sample application tracking system using Budibase:
![][9]
Of course, you can choose to publish the app on your server or use Budibases cloud offering.
### Final Thoughts
Budibase is an incredibly useful low-code platform that should help individuals and businesses quickly build a variety of applications. You should explore more about it on its official website and [GitHub page][10].
[Budibase][2]
It eliminates the need to hire an expert to build applications for a wide range of use-cases. And, as an open-source platform that you can self-host, it will let you scale up and provide complete control on building apps easily without paying a premium.
You can also opt for its enterprise offering, with premium support and specially tailored service, if the need arises.
--------------------------------------------------------------------------------
via: https://itsfoss.com/budibase/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-home.png?resize=800%2C467&ssl=1
[2]: https://budibase.com/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-data-sources.png?resize=800%2C597&ssl=1
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-edit-fields.png?resize=800%2C693&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-design.png?resize=800%2C477&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-layout.png?resize=800%2C515&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-theme-tweak.png?resize=800%2C696&ssl=1
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibas-application-create.png?resize=800%2C274&ssl=1
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/budibase-sample-app.png?resize=800%2C364&ssl=1
[10]: https://github.com/Budibase/budibase

View File

@ -0,0 +1,168 @@
[#]: subject: "Linux Mint Debian Edition 5 Perfection with Stability [Review]"
[#]: via: "https://www.debugpoint.com/2022/03/linux-mint-debian-edition-5-review/"
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
[#]: collector: "lujun9972"
[#]: translator: "robsean"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Linux Mint Debian Edition 5 Perfection with Stability [Review]
======
WE REVIEW THE RECENTLY RELEASED LINUX MINT DEBIAN EDITION 5 (LMDE 5) IN
TERMS OF PERFORMANCE, STABILITY & USER-FRIENDLINESS. HERES WHAT WE HAVE
FOUND.
The Linux Mint team announced the release of Linux Mint Debian Edition LMDE 5 (LMDE 5) after more than two years since its predecessor LMDE 4 (Debbie). LMDE 5 is based on [Debian 11 Bullseye][1] that brings LTS Linux Kernel 5.10 and Debian package base. Most of the applications and packages are almost identical with Linux Mint 20.3 except the Kernel version.
That said, lets dig in.
### Linux Mint Debian Edition 5 Review
We tested Linux Mint Debian Edition 5 (LMDE 5) in actual older hardware with the below spec.
* Intel Core i3 1st Gen
* 4GB DDR3 SDRAM
* Broadcom chip
* NVIDIA® GeForce® 315M
* SSD Storage
#### ISO Download, LIVE Medium and Installation
Finding the ISO and downloading it from the newly designed Linux Mint website is easy. The LIVE medium boot went fine, and the installation icon at the desktop kicked off the installer.
LMDE uses a modified version of the Debian installer. It is not Calamares. The vanilla Debian installer is tricky and somewhat [confusing for new users][2] [my opinion]. But Linux Mint team makes it very easy to install with just a few steps and removed all the confusing items from the Debian installer.
You need to provide the location, keyboard layout, name and credentials and you are ready to install. The partition system of the installer uses GParted, which is friendly and handy.
So, the installation went smooth in virtual machines and physical hardware for my test.
The physical system took 4 to 5 minutes, while the virtual system took around 3 minutes for installation.
#### First Impression
![Linux Mint Debian Edition 5 \(LMDE5\) Desktop][3]
If you were familiar with Linux Mint earlier with Cinnamon desktop, you would not find any difference in the Debian edition. They are the same. If you are new to Linux Mint Cinnamon, then a nice and clean desktop welcomes you after you finish your installation.
The desktop icons, well-adjusted colours and themes, bottom taskbar, system tray everything is well organised and can get you started in no time.
Whether you use low-end or high-end hardware Linux Mint Debian edition is fast on response and working in applications. The application switching and overall desktop response are solid.
You get well-tested applications and packages that seldom break based on Debian stability. That means no more worries about conflicting packages, missing updates and the usual issues with Linux systems.
#### Pre-Installed Applications
One of the advantages of Linux Mint (not only the Debian Edition) is its pre-loaded applications. Many Linux distributions do not include necessary applications in the ISO installer because of several reasons such as ISO size, etc.
But Linux Mint team thinks about their users and packages all the necessary applications that you need. This takes care of the needs of most of the user base. It helps reduce the end-users burden on searching and installing compatible applications after installing Linux Mint Debian Edition 5.
[][4]
SEE ALSO:   Zorin OS 16 Lite Review - Perfect Combination of Beauty, Performance and Simplicity
For example, with Linux Mint Debian Edition 5, the following essential apps are installed by default and ready to use.
* Pencil Drawing App
* Media: Celluloid media player, Hypnotix, Rythmbox
* Torrent client Transmission 3.0
* Complete Office suite: LibreOffice 7.0
* Email Client: Thunderbird 91.0
* Web browser: Firefox 97.0
Thats not all. You get a dedicated native application for all the below use cases. A user need not to look for a separate app for these.
* Screenshot and screensaver
* Tool for reducing eye strain
* USB format tool and Image Writer
* Sticky Pad
* Synaptic Package Manager
* System backup and restore
* Firewall utility
#### How LMDE5 is performing?
It is always fascinating to see a distro performing as per the expectation. And Linux Mint Debian Edition 5 performed well above expectations.
During an idle state, it is consuming 750 MB of RAM and the CPU is at 2%.
![Performance During the light workload][5]
Then I ran it through a heavy workload with the followings.
* Firefox with three tabs open and one of them playing one YouTube video
* LibreOffice Calc one sheet open
* Drawing app with one instance
* Settings
* One terminal window
* File manager
With the above workload, it is consuming around 1.5 GB of RAM and the CPU is at 14%. Most of the resources are consumed by Firefox, obviously.
![Performance During heavy workload][6]
In my opinion, it is a perfect metric and well-optimised distribution for older hardware. The above metric is measured on the physical system.
#### Connectivity
Connectivity is an integral part of any OS. So, Linux Mint Debian Edition 5 can connect to WiFi (with an old Broadcom chip) and link to Bluetooth speakers without any additional tweaking.
The volume controls worked well with the Bluetooth daemon during my test.
Also, we tested the USB hot plug-in and it is detected and mounted automatically without any problem.
So, no surprises there, which is expected.
### Any Bugs?
I have not encountered any bugs during my test. Everything worked well.
But one of the problems I found when I closed my physical test system laptop lid. It went to standby. But did not wake up. I could not see the login screen. The screen is black without any cursor. I had to do a hard reboot to get into the system.
It might be a hardware-specific issue on my test device. I believe it will not be of any concern for newer systems.
### Summary
To wrap up the Linux Mint Debian Edition 5 review, it is by far the most stable and well optimised Linux Distribution. You can trust this version for your daily driver and if you are planning to use a system for two years or more. So, if you need a non-Ubuntu based stable system, fast, low maintenance and long-running daily driver for your old or new systems, this is a perfect choice. Go for it.
You can download Linux Mint Debian Edition 5 [on the official website][7].
Cheers.
* * *
We bring the latest tech, software news and stuff that matters. Stay in touch via [Telegram][8], [Twitter][9], [YouTube][10], and [Facebook][11] and never miss an update!
##### Also Read
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2022/03/linux-mint-debian-edition-5-review/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: https://www.debugpoint.com/2021/05/debian-11-features/
[2]: https://www.debugpoint.com/2021/01/install-debian-buster/
[3]: https://www.debugpoint.com/wp-content/uploads/2022/03/Linux-Mint-Debian-Edition-5-LMDE5-Desktop-1024x580.jpg
[4]: https://www.debugpoint.com/2021/12/zorin-os-16-lite-review-xfce/
[5]: https://www.debugpoint.com/wp-content/uploads/2022/03/Performance-During-light-workload-1024x606.jpg
[6]: https://www.debugpoint.com/wp-content/uploads/2022/03/Performance-During-heavy-workload-1024x601.jpg
[7]: https://linuxmint.com/edition.php?id=297
[8]: https://t.me/debugpoint
[9]: https://twitter.com/DebugPoint
[10]: https://www.youtube.com/c/debugpoint?sub_confirmation=1
[11]: https://facebook.com/DebugPoint

View File

@ -1,143 +0,0 @@
[#]: subject: "6 Reasons to Try Nitrux OS"
[#]: via: "https://news.itsfoss.com/reasons-to-try-nitrux-os/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "aREversez"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
6大理由让你尝试 Nitrux 系统
======
Nitrux 系统也许算不上 Linux 的主流发行版本之一,但它绝对是一款极其独特的产品。
2019 年,我们[采访了 Nitrux 的创始人 Uri Herrera][1],了解到 Herrera 等人开发这款系统的初衷:超越 Linux 传统的发行版本。
自那之后,过了许久,我们终于迎来了 [Nitrux 2.0 版本][2]。
不要忘了Nitrux 在去年[放弃基于 Ubuntu 而选择 Debian][3]。
考虑到自 Nitrux 发行以来的数年间,也发生了许多大事,所以你应该尝试一下这款系统。
这里,我要分享一些体验 [Nitrux 系统][4]的理由:
### 1\. Nitrux 不再基于 Ubuntu
![][5]
人们一般都会推荐基于 Ubuntu 的 Linux 发行版本,来满足日常所需。
当然,在我们[为新手推荐的 Linux 系统][6]中,也包括了许多基于 Ubuntu 的版本,但是请不要误会。
我们之所以推荐基于 Ubuntu 的发行版本,唯一的理由在于它们简单易用,支持大量的商业软件。
所以,如果你不是刚开始使用 Linux 系统,同时也想尝试既能让你耳目一新,又不至于使你感到陌生,而且十分稳定的发行版,基于 Debian 的 Nirtux 是一个不错的选择。
你完全不需要在短期内迅速了解这款系统,就可以得心应手地使用终端来完成各项工作。
感兴趣的话,可以参考我们的文章 [Debian vs Ubuntu][7],了解更多.
### 2\. 专注 AppImages
![][5]
[AppImage][8] 是通用的软件包系统,没有任何依赖。你不需要在 Linux 上安装任何软件包管理器或者依赖包,就可以直接运行 AppImage 应用。
AppImage 旨在打造便携、高效的软件包系统,省去安装的步骤,与 Windows 系统的便携版软件非常相似。
Nitrux 操作系统专注 AppImage 应用软件,为你带来流畅的用户体验。
NX 软件中心是一个 GUI 程序,用户可以通过使用 Mauikit该软件中心的 UI 框架),安装、管理 AppImage 应用程序。
### 3\. 基于 KDE 桌面环境的发行版本
![][5]
Nitrux 操作系统是[搭载 KDE 桌面环境中最好的 Linux 发行版本][9]之一。 如果你不喜欢 GNOME 或者其他开箱即用的桌面环境KDE 会是一个不错的选择。
也许你还不知道, 相较于其他桌面环境,[KDE 支持自定义配置][10]。
因此,在 KED 桌面环境下,你可以毫不费力地打造自己的个性化桌面。
### 4\. 独特的用户体验
![][11]
Nitrux 的用户体验设计包括了最好的 KDE 桌面环境与 Qt 技术及其调整工具,为你带来全新的用户体验。
虽然在使用 Nitrux 操作系统时,你不会觉得十分陌生,但是还是会感到有些许的不同。
即使你没有对 Nitrux 系统做任何自定义的设置,开箱即用的体验也足以让它成为[最优雅的发行版][12]之一。
### 5\. Maui Shell
![][11]
[Maui Shell][13] 是 Nitrux 用户体验的亮点之一。近来Maui Shell 得到了进一步的完善,将同时支持桌面端和移动端。
尽管 Maui Shell 目前还不成熟,但是外观看起来十分大气简约,就像 [System76 将要推出基于 Rust 的桌面环境][14]一样令人兴奋。
这也是我们推荐尝试 Nitrux 系统最重要的原因之一。时间会证明Nitrux 系统是否将会开启桌面体验的全新时代。
### 6\. Xanmod 内核
![][5]
[Xanmod 内核][15] 是主流 Linux 内核的定制版本,对性能进行了适当的调整,附加了一些其他功能。有了它,你的桌面体验一定能得到大幅提升。
自 2.0 版本起Nitrux 操作系统选用 Xanmod 作为默认内核,为用户提供“升级版”的桌面体验。
当然你也可以选择其他 Linux 内核,比如 Liquorix 和 Libre它们都有着各自的优点。
如果你不喜欢 Xanmod也可以选择主流长期支持版的内核。所以说在 Nitrux 操作系统上,你完全可以修改使用不同的内核。
[Nitrux OS][4]
### 总结
诚然,从主流发行版转到像 Nitrux 这样的操作系统,需要考虑各种风险。
但是,**我建议你好好考虑一番:**
Nitrux 等发行版本在每一次版本升级中,都会尽全力去完善各项功能。
尽管背后没有强大的企业和财力支撑,他们依然可以开发出这款令人惊艳的发行版本、进阶版的 [Maui 项目][16],以及别开生面的 Maui shell.
所以,我认为,我们也应该以己所能,尽己之力,支持这些优秀的发行版。
不过话说回来,每一款 Linux 发行版都会或多或少地存在一些问题。当你试用一款新的发行版本时,你需要给它点儿时间,在最终将它作为日常使用的操作系统之前,慢慢地去适应它。
换言之,我推荐你在业余时间试用 Nitrux 操作系统,或者直接装个虚拟机来一探究竟。
_我很关注大家对这篇文章的看法请在下方评论留言_
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/reasons-to-try-nitrux-os/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[aREversez](https://github.com/aREversez)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/nitrux-linux/
[2]: https://news.itsfoss.com/nitrux-2-0-release/
[3]: https://news.itsfoss.com/nitrux-linux-debian/
[4]: https://nxos.org/
[5]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ2OCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[6]: https://itsfoss.com/best-linux-beginners/
[7]: https://itsfoss.com/debian-vs-ubuntu/
[8]: https://itsfoss.com/use-appimage-linux/
[9]: https://itsfoss.com/best-kde-distributions/
[10]: https://itsfoss.com/kde-customization/
[11]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQzOSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[12]: https://itsfoss.com/beautiful-linux-distributions/
[13]: https://news.itsfoss.com/maui-shell-unveiled/
[14]: https://news.itsfoss.com/system76-cosmic-panel/
[15]: https://xanmod.org/
[16]: https://mauikit.org

View File

@ -0,0 +1,134 @@
[#]: subject: (How to Make LibreOffice Look Like Microsoft Office)
[#]: via: (https://www.debugpoint.com/2021/06/libreoffice-like-microsoft-office/)
[#]: author: (Arindam https://www.debugpoint.com/author/admin1/)
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
如何使 LibreOffice 看起来像 Microsoft Office
======
我们想做一次使 LibreOffice 套件看起来像 Microsoft
Office 的尝试。它能做到吗?让我们探索出方法。
[LibreOffice][1] 是一个自由的和开放源文件的办公室生产力套件,它向你提供了一套完整的应用程序集合。它包含 字处理器 (Writer)、 表格程序(Calc)、演示程序 (Impress) 和 绘图程序 (Draw)。它也给予你一个独立的数据库系统 (LibreOffice Base) 。LibreOffice Math 是一个帮助学生、研究人员编写公式和方程的程序。
然而,广泛使用的 [Microsoft Office][2] 是一个收费的办公室生产力套件,它向你提供了极好的程序来完成几乎所有的关于学习、办公和企业应用的任务。
这两组程序套件是不同的但是它们在功能上的目标是相同的。由于它的流行Microsoft office 被广泛的使用,并被使用者所熟知。不过,这里有很多使用者更喜欢免费的 LibreOffice 来支撑他们的工作和活动。与 Microsoft Office 相比,使用 LibreOffice 有时会很困难 尽管大多数的菜单项和工具都是一样的。
尽管如此。假设你可以使 LibreOffice 看起来像 Microsoft Office ,那么,对于初次使用 LibreOffice 的用户来说会更容易一点 大多数来自使用 Microsoft Office 的经历背景的用户。外观和感觉在用户的思维中起着重要的作用,也包含他们的肌肉记忆和颜色、菜单项的熟悉度。
当然,你不可能使它完全像 Microsoft Office ,因为它们使用了不同的图标、字体等等。不过,你可以将其微调到忽略不计。
### 使 LibreOffice 看起来像 Microsoft Office
_这篇指南是以 LibreOffice 7.2 (开发版) 版本为基础所编写的。_
#### 1\. 用户界面更改
LibreOffice 有一个 “Ribbon” 样式的工具条。尽管它带有很多工具条选项 (查看下文)。但是,对于这篇指南,我使用 Tabbed 工具条选项。
* 打开 LibreOffice 并转到 `Menu > View > User Interface`
* 从 UI 部分中选择 `Tabbed`
![tabbed bar option][3]
* 点击 Apply to All 。LibreOffice 也提供一个应用指定工具条样式到 Writer 和 Calc 的选项。如果你想要一种不同的工具条样式,你可以选择这种方法。但是,我推荐使用 Apply to All 来保持它的一致性。
* 现在,你已经有了 Microsoft Office 样式的 Ribbon 用户界面。尽管它们并不是完全相同,但是你也能感受到它。
#### 2\. 针对 LibreOffice 的 Microsoft Office 图标
工具条中的图标在你的工作流中起着重要的作用。LibreOffice 为你的工具条提供一些极好的图标。其中最好的一些是
* Karasa Jaga
* Colibre
* Elementary
针对这篇指南,我们将使用 [Office 2013 图表集][4] ,它是由一名作家开发的。它可以在 Devian Art 中获得。
* 转到下面的链接并下载 LibreOffice 扩展文件 (*.oxt),针对 LibreOffice 的较新版本,你需要使用扩展文件来安装图标集。
[下载针对 libreoffice 的 office 2013 图标集][5]
* 在下载后,双击 .oxt 文件来将其打开。或者,按下 CTRL+ALT+E 组合按键来打开扩展管理器,并使用 Add 按钮来选择已下载的 .oxt 文件。在完成后关闭窗口。
![Import icon sets in Extension Manager][6]
* 现在,转到 `Tools > Options > View`。从图标样式中选择 Office 2013 。
* 更改图标大小,通过 `Icon Size > Notebookbar > Large` 。如果你感觉图标有点小,你可以更改它们。不过,我感觉要使它更像 Office ,将图标设置的较大一点的效果会更好。
![Change icons in Options][7]
就这样,你的 LibreOffice 应该看起来像这样。
[][8]
请参考: LibreOffice 7.2 - 新功能和Release Details
![Making LibreOffice look like Microsoft Office in KDE Plasma][9]
![Making LibreOffice look like Microsoft Office in Windows 10][10]
![Making LibreOffice look like Microsoft Office in GNOME][11]
记住,如果你正在使用 Ubuntu, KDE Plasma或者任何 Linux 发行版,它们的外观可能会有所不同。但是,在我看来,在 KDE Plasma 中比在 GNOME 中看起来更像 Microsoft Office 。LibreOffice 目前在基于 GTK 的系统中看起来并不太好。
不过,在 Windows 中,它看起来会更像,因为它使用同一个系统的字体和颜色面板。
这里有一些你可以使用的设置不过你可以随心所欲地自由调整更多的定制、图标和h主题。如果你想要 LibreOffice 的暗黑模式,你可能想要阅读我们的教程 [如何在 LibreOffice 中启用 暗黑 模式][12].
### 结束语
Microsoft Office 毫无疑问是办公生产力领域的市场领导者。这是有原因的,它来自数十年的开发。它不是免费的产品,事实上,最新的 Office 365 家庭版本的价格大约是 7 美元/月,可以在 3 到 4 台设备上使用。在我看来,它有点小贵。
然而 LibreOffice 是免费的,由文档基金会领导社区开发的。因此,开发速度较慢、功能出现较晚。它没有尝试成为 Microsoft Office ,但是它却给了数百万的用户、学校、非营利组织、高校、学生一个来工作和学习使用一款免费办公套件的机会。
因此,如果它能够模仿基本的外观和感觉,来使其像 Microsoft Office ,从而调高 LibreOffice 的使用率,那将是有益的。我希望这篇指南能在这平面起到一点作用。
[_链接: LibreOffice 和 Microsoft Office 的官方功能比较。_][13]
* * *
--------------------------------------------------------------------------------
via: https://www.debugpoint.com/2021/06/libreoffice-like-microsoft-office/
作者:[Arindam][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.debugpoint.com/author/admin1/
[b]: https://github.com/lujun9972
[1]: http://libreoffice.com
[2]: http://office.com
[3]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/tabbed-bar-option.jpg
[4]: https://www.deviantart.com/charliecnr/art/Office-2013-theme-for-LibreOffice-512127527
[5]: https://www.deviantart.com/users/outgoing?https://1drv.ms/u/s!ArgKmgFcmBYHhSQkPfyMZRnXX5LJ
[6]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Import-icon-sets-in-Extension-Manager.jpg
[7]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Change-icons-in-Options-1024x574.jpg
[8]: https://www.debugpoint.com/2021/05/libreoffice-7-2/
[9]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-KDE-Plasma-1024x441.jpg
[10]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-Windows-10-1024x554.jpg
[11]: https://www.debugpoint.com/blog/wp-content/uploads/2021/06/Making-LibreOffice-look-like-Microsoft-Office-in-GNOME-1024x498.jpg
[12]: https://www.debugpoint.com/2020/01/how-to-enable-dark-mode-libreoffice/
[13]: https://wiki.documentfoundation.org/Feature_Comparison:_LibreOffice_-_Microsoft_Office

View File

@ -0,0 +1,98 @@
[#]: subject: "What is port forwarding?"
[#]: via: "https://opensource.com/article/21/9/what-port-forwarding"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
什么是端口转发?
======
本文介绍了几种端口转发最常见的使用场景。
![Multi-colored and directional network computer cables][1]
端口转发就是把网络流量从一个网络监听者(称为一个“端口”)发送到另一个上,无论这两个端口是否属于同一台电脑。在这里,端口不是某个物理实体,而是一个监听网络活动的软件程序。
当流量被定向发往到某个特定的端口,它会先到达一个路由器或是防火墙,亦或是其他的网络程序。它最终收到的响应可能会根据它想要通讯的端口来定义。比如,当你使用端口转发时,你可以捕获到发往 8080 端口的流量,然后把它转发到 80 端口。对于接收信号的原端口来说,这个新的目标端口可能和它在同一台设备上,也可能是在另一台设备上。我们在很多情况下都会用到端口转发,实现的方式也有很多。本文将介绍其中最常见的几种使用场景。
### 使用路由器来进行端口转发
如果你在把服务器架设在家里,那么你通常是不需要转发端口的。你的家庭路由器(通常是你从<ruby>网络服务提供商<rt>Internet Service Provider, ISP</rt></ruby>获得的 WiFi 设备)有一个内置的防火墙,它的作用是阻止外面的世界访问到你的家庭网络。通过使用端口转发,你可以允许某个指定端口的流量穿过路由器的防火墙,并发送到局域网中的某个指定的 IP 地址。
比如说,你架设了一个 [Minetest 服务][2],并想要邀请你的朋友们来试试。为了让他们能够“穿过”你的路由器,从而到达这个 Minetest 服务,你必须把路由器上的某个端口转发到托管 Minetest 服务的电脑上。Minetest 服务默认运行在 30000 端口。你可以把路由器的 30000 端口转发到你的电脑的 30000 端口上,或者你也可以随便转发到一个更简单的端口上,这样玩家们会更容易记住它。我发现,当使用 30000 端口的时候,人们时常会少数几个 0特别是没有逗号分隔符的帮助时所以我一般使用路由器的 1234 端口,然后把它转发到我内部的 30000 端口。
每个制造商的路由器接口都不一样,但是不管你用的是什么牌子的路由器,方法都是相同的。首先,你需要登录到你的路由器。
通常,路由器的 IP 地址和登录信息都会打印在路由器上,或者在是它的文档里。我有一个型号为 TP-Link GX90 的路由器,我在浏览器里访问 10.0.1.1 就可以登录它,但你的路由器可能是 192.168.0.1 或者其他的地址。
我的 GX90 路由器把端口转发功能称为“<ruby>虚拟服务器<rt>virtual servers</rt></ruby>它是路由器的“NAT 转发”标签下的一个功能选项。NAT 的意思是 _网络地址转换_。在其他路由器中,这个功能可能直接就叫做“端口转发”,或者叫“防火墙”、“服务”等。找到正确的功能选项可能需要花费一些时间,因此,你可能需要花点时间研究下你的路由器文档。
当你找到了路由器的端口转发设置,添加一个新规则,命名一个外部端口(在我的例子中是 1234和一个内部端口30000。把外部端口转发到内部端口上而内部端口绑定在你想要大家访问的电脑的 IP 地址上。如果你需要一些查询本机 IP 地址的帮助,你可以阅读 Archit Modi 写的 _[在 Linux 上如何查询本地 IP 地址][3]_
![A sample port forwarding rule][4]
一个简单端口转发规则
(图片提供者是 Seth Kenlon遵循[署名-相同方式共享 4.0 国际][5]协议)
在这个例子中,访问家庭网络的 1234 端口的流量,都会被转发到了我的家庭服务器的 30000 端口上,后者的 IP 地址是 10.0.1.2。
在继续之前,先保存这个规则。
接下来,你需要知道你的家庭网络的公网 IP 地址是多少。你可以从 [ifconfig.me][6] 或者 [icanhazip.com][7] 上获得这个地址。你可以在浏览器中打开这两个网站的其中一个,也可以使用 [curl][8] 命令来获取到这个 IP。
```
$ curl ifconfig.me
93.184.216.34
```
现在,你的朋友们就可以在 Minetest 客户端里输入 `169.169.23.49:1234`,加入你的 Minetest 服务器啦。
### 使用防火墙来进行端口转发
系统管理员有时候需要转发访问服务器的流量。比如说,你可能想要接收来自 80 端口的流量,但是用户的服务却运行在 8065 端口。如果不进行端口转发的话,你的用户就不得不在输入浏览器的 URL 末尾,加上一个指定的端口号,例如 `example.com:8065`。大多数用回都不习惯于考虑端口的问题,所以你需要把访问网络通用的 80 端口的请求拦截下来,然后转发到你的网络应用的具体端口,这会给用户带来巨大的方便。
你可以在服务器上使用 [firewall-cmd][9] 来转发流量,它是访问 `firewalld` 后台进程的<ruby>前端<rt>front-end</rt></ruby>命令。
首先,设置好你想要转发的端口和协议:
```
$ sudo firewall-cmd \
\--add-forward-port \
port=80:proto=tcp:toport=8065
```
为使修改永久生效,你需要加上 `--runtime-to-permanent` 选项:
```
`$ sudo firewall-cmd --runtime-to-permanent`
```
### 网络转发
在网络传输中,除了端口转发外,还有其他种类的<ruby>转发<rt>forwarding</rt></ruby>形式,例如 IP 转发和代理等。当你熟悉了网络信息在路由时是怎么被处理的之后,你可以试试不同的转发形式(然后使用 `tcpdump` 或类似的工具)来看看哪一种最好、最符合你的需求。
--------------------------------------------------------------------------------
via: https://opensource.com/article/21/9/what-port-forwarding
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [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/connections_wires_sysadmin_cable.png?itok=d5WqHmnJ (Multi-colored and directional network computer cables)
[2]: https://opensource.com/alternatives/minecraft#minetest
[3]: https://opensource.com/article/18/5/how-find-ip-address-linux
[4]: https://opensource.com/sites/default/files/uploads/router-port-forward.jpg (A sample port forwarding rule)
[5]: https://creativecommons.org/licenses/by-sa/4.0/
[6]: http://ifconfig.me
[7]: http://icanhazip.com
[8]: https://opensource.com/article/20/5/curl-cheat-sheet
[9]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd

View File

@ -0,0 +1,180 @@
[#]: subject: "Creating and initializing lists in Java and Groovy"
[#]: via: "https://opensource.com/article/22/1/creating-lists-groovy-java"
[#]: author: "Chris Hermansen https://opensource.com/users/clhermansen"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
在 Java 和 Groovy 中创建和初始化列表的不同
======
首先在 Java 中创建初始化一个整数列表,然后在 Groovy 中做同样的事。
![Developing code.][1]
我非常喜欢 [Groovy 编程语言][2]。我喜欢它是因为我喜欢 Java尽管 Java 有时候感觉很笨拙。正因为我是那么喜欢 Java其他运行在 JVM 上语言都不能吸引我。比方说 Kotlin、Scala 还有 Clojure 语言,它们感觉上就和 Java 不一样因为它们对于什么是好的编程语言的理解不同。Groovy 和它们都不一样在我看来Groovy 是一个完美的选项,特别是对于一部分程序员来说,他们喜欢 Java但是又需要一个更灵活、更紧凑并且有时候更直接的语言。
<ruby>列表<rt>List</rt></ruby> 这种数据结构是一个很好的例子,它可以容纳一个无序的列表,列表中的元素可以是数字、字符串或者对象,程序员可以用某种方式高效地遍历这些元素,特别是对于编写和维护脚本的人来说,“高效”的关键就是要有简洁清晰的表达,而不需要一大堆“仪式”,把代码的意图都变模糊了。
### 安装 Java 和 Groovy
Groovy 是基于 Java 的,因此需要同时安装一个 Java 才行。你的 Linux 发行版的仓库中可能有最近的比较好的 Java 版本。或者,你也可以在根据 [这些指示][3] 来安装 Groovy。对于 Linux 用户来说SDKMan 是一个不错的代替选项,你可以使用它来获取多个 Java 和 Groovy 版本,以及许多其他的相关工具。在这篇文章中,我使用的 SDK 发行版是:
* Java: version 11.0.12-open of OpenJDK 11
* Groovy: version 3.0.8
### 言归正传
Java 中有很多方法可以实例化并初始化列表,从它最初被引入的时候就有了(我记得是在 Java 1.5 的时候,但请不要引用我的话)。在这些方法里,有两个有趣的方法,它们涉及到了 `java.util.Arrays``java.util.List` 这两个类。
#### 使用 java.util.Arrays 类
`java.util.Arrays` 类定义了一个 `asList()` 静态方法,它可以被用来创建一个基于数组的列表,因此大小是不可变的,尽管其中的元素是可以被修改的。下面是它的使用方式:
```java
var a1 = [Arrays][4].asList(1,2,3,4,5,6,7,8,9,10); // immutable list of mutable elements
[System][5].out.println("a1 = " + a1);
[System][5].out.println("a1 is an instance of " + a1.getClass());
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.Arrays$ArrayList
a1.set(0,0); // succeeds
[System][5].out.println("a1 = " + a1); // output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1.add(11); // fails producing
// Exception in thread "main" java.lang.UnsupportedOperationException
[System][5].out.println("a1 = " + a1); // not reached
```
#### 使用 java.util.List 类
`java.util.List` 类定义了一个 `of()` 静态方法,它可以被用来创建一个不可变的列表,其中的元素是否可变要取决于它们本身是否支持修改。下面是它的使用方式:
```java
var a2 = [List][6].of(1,2,3,4,5,6,7,8,9,10);
[System][5].out.println("a2 = " + a2);
[System][5].out.println("a2 is an instance of " + a2.getClass());
// output is
// a2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a2 is an instance of class java.util.ImmutableCollections$ListN
a2.set(0,0); // fails producing
// Exception in thread "main" java.lang.UnsupportedOperationException
[System][5].out.println("a2 = " + a2); // not reached
a2.add(11); // also fails for same reason if above two lines commented out
[System][5].out.println("a2 = " + a2); // not reached
```
因此,我可以使用 `Arrays.asList()`,也可以使用 `List.of()` 方法,前提是如果我想要的是一个大小不能改变、且不关心元素是否可变的列表。
如果我想要初始化一个可变的列表,我更倾向于把这些不可变的列表作为参数传给一个列表构造器,就像下面这样:
```java
var a1 = new ArrayList<Integer>([Arrays][4].asList(1,2,3,4,5,6,7,8,9,10));
[System][5].out.println("a1 = " + a1);
[System][5].out.println("a1 is an instance of " + a1.getClass());
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.ArrayList
a1.set(0,0);
[System][5].out.println("a1 = " + a1);
//output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1.add(11);
[System][5].out.println("a1 = " + a1);
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
注意,这个 `Arrays.asList()` 方法是用来初始化这个新的 `ArrayList<Integer>()` 的,也就是说,它为这个传进来的列表创建了一个可变的拷贝。
现在,或许只有我这么想,但是这种方式确实看起来需要理解很多关于 `java.util.Arrays``java.util.List` 类的细节才行,而我只是想要创建并初始化一个数字列表而已(尽管真正使用到的语句并没有太多“仪式”)。下面是真正用到的那行代码,仅供参考:
```java
`var a1 = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));`
```
### Groovy 是怎么做的
下面来看看在 Groovy 中如何实现上述需求:
```groovy
def a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println "a1 = $a1"
println "a1 is an instance of ${a1.getClass()}"
// output is
// a1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// a1 is an instance of class java.util.ArrayList
a1[0] = 0
println "a1 = $a1"
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a1 << 11
println "a1 = $a1"
// output is
// a1 = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
```
我们一眼就能发现Groovy 使用了 `def` 关键字而不是 `var` 关键字。我还发现了,仅仅是把一系列的类型(在这个例子里是整数)放进括号里,我就得到了一个创建好的列表。此外,这样创建出来的列表完全就是我想要的:一个可变的 `ArrayList` 实例。
现在,或许再一次只有我这么想,但是上面的代码看起来要简单多得多 —— 不用记住 `.of()``.asList()` 返回的是“<ruby>半不变<rt>semi-mutable</rt></ruby>”的结果,也不用为它们做一些补偿。另外一个好处是,我现在可以使用括号和下标来引用列表中的某个特定元素,而不用这个叫 `set()` 方法。另外,这个跟在列表后面的 `<<` 操作符也很方便,我再也不用调用 `add()` 方法来添加元素啦。还有,你注意到代码中没有分号了吗?没错,在 Groovy 里,句末的分号并不是必须的。最后,我们来看看字符串插值,只要在字符串里用 `$变量` 或者 `${表达式}` 就可以实现了哦!
在 Groovy 世界中还藏着许多“有待发掘”的东西。上面的列表定义其实是一个动态类型Groovy 中默认)和 Java 中的静态类型的对比。在上面的 Groovy 代码定义的那一行,变量 `a1` 的类型是在运行的时候根据等号右边的表达式的计算结果推断出来的。现在我们都知道动态语言可以给我们带来强大的功能有了强大的功能我们有了很多机会去尝试不同的东西。对于那些不喜欢动态类型的程序员来说Groovy 也支持静态类型。
### Groovy 相关资源
Apache Groovy 网站上有非常多的文档。另一个很棒的 Groovy 资源是 [Mr. Haki][7]。学习 Groovy 还有一个很棒的原因,那就是可以接着学习 [Grails][8],后者是一个优秀的、高效率的全栈 Web 框架,基于许多优秀组件构建而成,比如有 Hibernate、Spring Boot 和 Micronaut 等。
本文献给我亲爱的朋友 Anil Mukhi他于 2022 年 1 月 3 日不幸离世。谢谢你Anil让我有机会了解这么多关于 Groovy、Grails 和赛马数据的知识。
--------------------------------------------------------------------------------
via: https://opensource.com/article/22/1/creating-lists-groovy-java
作者:[Chris Hermansen][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [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/code_development_programming.png?itok=M_QDcgz5 (Developing code.)
[2]: http://www.groovy-lang.org/
[3]: http://www.groovy-lang.org/install.html
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+arrays
[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+list
[7]: https://www.mrhaki.com/
[8]: https://grails.org/

View File

@ -1,233 +0,0 @@
[#]: subject: "How to use undocumented web APIs"
[#]: via: "https://jvns.ca/blog/2022/03/10/how-to-use-undocumented-web-apis/"
[#]: author: "Julia Evans https://jvns.ca/"
[#]: collector: "lujun9972"
[#]: translator: "lxbwolf"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
如何调用没有文档说明的 web API
======
大家好!几天前我写了篇[个人 demo 小程序][1],里面提到了调用没有文档说明的“私有” API 很有意思,你需要从你的浏览器中把 cookies 复制出来才能访问。
有些读者问如何实现,因此我打算详细描述下,其实过程很简单。我们还会涉及一点点在调用没有文档说明的 API 时,可能会遇到的麻烦。
我们用谷歌论坛举例。我之所以选择它,不是因为这个例子最有用(我认为官方的 API 更有实践意义),而是因为在这个场景中更有用的网站很多是小网站,而小网站的 API 一旦被滥用,受到的伤害会更大。因此我们使用谷歌论坛,因为我 100% 肯定谷歌论坛对于这种试探请求可以很快恢复。
我们现在开始!
### 第一步:打开开发者工具,找一个 JSON 响应
我浏览了<https://hangouts.google.com>,在 Firefox 的开发者工具中打开网络标签,找到一个 JSON 响应。你也可以使用 Chrome 的开发者工具。
打开之后界面如下图
![][2]
找到其中一条 “Type” 列显示为 ”json“ 的请求。
为了找一条感兴趣的请求,我找了好一会儿,突然我找到一条 ”people“ 的 endpoint看起来是返回我们的联系人信息。听起来很有意思我们来看一下。
### 第二步:复制为 cURL
下一步,我在感兴趣的请求上右键,点击 ”复制“ -> ”复制为 cURL“。
然后我把 `curl` 命令粘贴到终端并运行。下面是运行结果:
```
$ curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' -X POST ........ (a bunch of headers removed)
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
```
你可能会想 —— 很奇怪,”二进制的输出在你的终端上无法正常显示“ 是什么错误?原因是,浏览器默认情况下发给服务器的请求头中有 `Accept-Encoding: gzip, deflate` 参数,会把输出结果进行压缩。
我们可以通过管道把输出传递给 `gunzip` 来解压,但是我们发现不带这个参数进行请求会更简单。因此我们去掉一些不相关的请求头。
### 第三步:去掉不相关的请求头
下面是我从浏览器获得的完整 `curl` 命令。有很多行!我用反斜杠(`\`)把请求分开,这样每个请求头占一行,看起来更清晰。
```
curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0' \
-H 'Accept: */*' \
-H 'Accept-Language: en' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'X-HTTP-Method-Override: GET' \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Cookie: REDACTED'
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'X-Goog-AuthUser: 0' \
-H 'Origin: https://hangouts.google.com' \
-H 'Connection: keep-alive' \
-H 'Referer: https://hangouts.google.com/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-site' \
-H 'Sec-GPC: 1' \
-H 'DNT: 1' \
-H 'Pragma: no-cache' \
-H 'Cache-Control: no-cache' \
-H 'TE: trailers' \
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'
```
第一眼看起来内容有很多,但是现在你不需要考虑每一行是什么意思。你只需要把不相关的行删掉就可以了。
我通常通过删掉某行查看是否有错误来验证该行是不是可以删除 —— 只要请求没有错误就一直删请求头。通常情况下,你可以删掉 `Accept*`、`Referer`、`Sec-*`、`DNT`、`User-Agent` 和缓存相关的头。
在这个例子中,我把请求删成下面的样子:
```
curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Origin: https://hangouts.google.com' \
-H 'Cookie: REDACTED'\
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'
```
这样我只需要 4 个请求头:`Authorization`、`Content-Type`、`Origin` 和 `Cookie`。这样容易管理得多。
### 第四步:在 Python 中发请求
现在我们知道了我们需要哪些请求头,我们可以把 `curl` 命令翻译进 Python 程序!这部分是相当机械化的过程,目标仅仅是用 Python 发送与 curl 相同的数据。
下面是代码实例。我们使用 Python 的 `requests` 包实现了与前面 `curl` 命令相同的功能。我把整个长请求分解成了元组的数组,以便看起来更简洁。
```
import requests
import urllib
data = [
('personId','101777723'), # I redacted these IDs a bit too
('personId','117533904'),
('personId','111526653'),
('personId','116731406'),
('extensionSet.extensionNames','HANGOUTS_ADDITIONAL_DATA'),
('extensionSet.extensionNames','HANGOUTS_OFF_NETWORK_GAIA_GET'),
('extensionSet.extensionNames','HANGOUTS_PHONE_DATA'),
('includedProfileStates','ADMIN_BLOCKED'),
('includedProfileStates','DELETED'),
('includedProfileStates','PRIVATE_PROFILE'),
('mergedPersonSourceOptions.includeAffinity','CHAT_AUTOCOMPLETE'),
('coreIdParams.useRealtimeNotificationExpandedAcls','true'),
('requestMask.includeField.paths','person.email'),
('requestMask.includeField.paths','person.gender'),
('requestMask.includeField.paths','person.in_app_reachability'),
('requestMask.includeField.paths','person.metadata'),
('requestMask.includeField.paths','person.name'),
('requestMask.includeField.paths','person.phone'),
('requestMask.includeField.paths','person.photo'),
('requestMask.includeField.paths','person.read_only_profile_info'),
('requestMask.includeField.paths','person.organization'),
('requestMask.includeField.paths','person.location'),
('requestMask.includeField.paths','person.cover_photo'),
('requestMask.includeContainer','PROFILE'),
('requestMask.includeContainer','DOMAIN_PROFILE'),
('requestMask.includeContainer','CONTACT'),
('key','REDACTED')
]
response = requests.post('https://people-pa.clients6.google.com/v2/people/?key=REDACTED',
headers={
'X-HTTP-Method-Override': 'GET',
'Authorization': 'SAPISIDHASH REDACTED',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'https://hangouts.google.com',
'Cookie': 'REDACTED',
},
data=urllib.parse.urlencode(data),
)
print(response.text)
```
我执行这个程序后正常运行 —— 输出了一堆 JSON 数据!太棒了!
你会注意到有些地方我用 `REDACTED` 代替了,因为如果我把原始数据列出来你就可以用我的账号来访问谷歌论坛了,这就很不好了。
### 运行结束!
现在我可以随意修改 Python 程序,比如传入不同的参数,或解析结果等。
我不打算用它来做其他有意思的事了,因为我压根对这个 API 没兴趣,我只是用它来阐述请求 API 的过程。
但是你确实可以对返回的一堆 JSON 做一些处理。
### curlconverter 看起来很强大
有人评论说可以使用<https://curlconverter.com/>自动把 curl 转换成 Python和一些其他的语言这看起来很神奇 —— 我都是手动转的。我在这个例子里使用了它,看起来一切正常。
### 追踪 API 的处理过程并不容易
我不打算夸大追踪 API 处理过程的难度 —— API 的处理过程并不明显!我也不知道传给这个谷歌论坛 API 的一堆参数都是做什么的!
但是有一些参数看起来很直观,比如 `requestMask.includeField.paths=person.email` 可能表示”包含每个人的邮件地址“。因此我只关心我能看懂的参数,不关心看不懂的。
### (理论上)适用于所有场景
可能有人质疑 —— 这个方法适用于所有场景吗?
答案是肯定的 —— 浏览器不是魔法!浏览器发送给你的服务器的所有信息都是 HTTP 请求。因此如果我复制了浏览器发送的所有的 HTTP 请求头,那么后端就会认为请求是从我的浏览器发出的,而不是用 Python 程序发出的。
当然,我们去掉了一些浏览器发送的请求头,因此理论上后端是可以识别出来请求是从浏览器还是 Python 程序发出的,但是它们通常不会检查。
这里有一些对读者的告诫 —— 一些谷歌服务的后端会通过令人难以理解(对我来说是)方式跟前端通信,因此即使理论上你可以模拟前端的请求,但实际上可能行不通。可能会遭受更多攻击的大型 API 会有更多的保护措施。
我们已经知道了如何调用没有文档说明的 API。现在我们再来聊聊可能遇到的问题。
### 问题 1session cookies 过期
一个大问题是我用我的谷歌 session cookie 作为身份认证,因此当我的浏览器 session 过期后,这个脚本就不能用了。
这意味着这种方式不能长久使用(我宁愿调一个真正的 API但是如果我只是要一次性快速抓取一小组数据那么可以使用它。
### 问题 2滥用
如果我正在请求一个小网站,那么我的 Python 脚本可能会把服务打垮,因为请求数超出了它们的处理能力。因此我请求时尽量谨慎,尽量不过快地发送大量请求。
这尤其重要,因为没有官方 API 的网站往往是些小网站且没有足够的资源。
很明显在这个例子中这不是问题 —— 我认为在写这篇文章的过程我一共向谷歌论坛的后端发送了 20 次请求,他们肯定可以处理。
如果你用自己的账号资格过度访问这个 API 并导致了故障,那么你的账号可能(情理之中)会被暂时封禁。
我只下载我自己的数据或公共的数据 —— 我的目的不是寻找网站的弱点。
### 请记住所有人都可以访问你没有文档说明的 API
我认为本文最重要的信息并不是如何使用其他人没有文档说明的 API。虽然很有趣但是也有一些限制而且我也不会经常这么做。
更重要的一点是,任何人都可以这么访问你后端的 API每个人都有开发者工具和网络标签查看你传到后端的参数、修改它们都很容易。
因此如果一个人通过修改某些参数来获取其他用户的信息,这不值得提倡。我认为提供公开 API 的大部分开发者们都知道,但是我之所以再提一次,是因为每个初学者都应该了解。:)
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/2022/03/10/how-to-use-undocumented-web-apis/
作者:[Julia Evans][a]
选题:[lujun9972][b]
译者:[lxbwolf](https://github.com/lxbwolf)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://jvns.ca/
[b]: https://github.com/lujun9972
[1]: https://jvns.ca/blog/2022/03/08/tiny-programs/
[2]: https://jvns.ca/images/network-tab.png

View File

@ -0,0 +1,78 @@
[#]: subject: "Build Your Own Handheld Linux PC with Raspberry Pi and this Open Source Project"
[#]: via: "https://news.itsfoss.com/penkesu-handheld-linux-pc/"
[#]: author: "John Paul https://news.itsfoss.com/author/john/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
用树莓派和这个开源项目打造你自己的手持 Linux 电脑
======
你是否曾希望有一台适合你手持的、带有键盘的 Linux 笔记本电脑?如果你说有,那么你就很幸运了。一位硬件设计师创造了这样一个设备,并将其设计开源,这样任何人都可以在家里制作它。
### 它是什么?
![][1]
Penkēsu 电脑Penkēsu 是日语中铅笔盒的意思)是由 [Penk Chen][2] 设计。如果这个名字听起来很熟悉,他就是 [CutiePi][3] 背后的设计师。
根据该网站Penk创建这个项目是因为
> 自从 CutiePi 平板电脑成功获得资金并开始发货后,我觉得有必要从事一个新的项目,一个我不需要太担心商业可行性的项目,并提醒自己为什么开始修补。可以说是一个“反弹”项目。
他还说,他目前没有任何大规模生产 Penkēsu 的计划,所以他把计划开源了。“我想公布所有的设计和计划,这样就有足够的信息给任何有兴趣制作的人。”
### 零件
![][1]
Penk 围绕一个 7.9 英寸的触摸屏和一个定制键盘设计了 Penkēsu。内部结构由树莓派 Zero 2 W 和 Li-Po 电池供电。树莓派 Zero 2 W 有一个 1GHz 的 ARM 四核 ARM Cortex-A53 处理器和 512MB 的内存。花 15 美元,应该可以运行大多数为 Pi 设计的 Linux 发行版。
有趣的是Penk 说,“我的 3D 打印机不够精确,无法打印出一个功能齐全的铰链锁”。因此,他决定使用来自 Game Boy Advance SP 的替换铰链。
看起来最困难的部分是键盘,这涉及到一个定制的 PCB。Penk 确实注意到,“如果希望使用其他 40% 的键盘来制作,可以通过编辑 CAD 文件和调整机箱中的隔间大小来完成”。
以下是所需零件的完整清单:
* 显示器
* Waveshare 7.9 英寸电容式触摸屏
* Adafruit DIY HDMI 电缆部件 - 直角适配器,迷你 HDMI 适配器和 20 厘米带状电缆
* 外壳
* Game Boy Advance SP 替代铰链
* 3D 打印部件STL 文件和 STEP 文件)
* 电子产品
* 树莓派 Zero 2 W
* 3.7V 606090或类似尺寸Li-Po 电池
* Adafruit PowerBoost 1000C
* 键盘
* Kailh Low Profile Choc V1 开关 x 48
* MBK Choc Low Profile 键帽 x 48
* 1N4148 二极管 x 48
* Arduino Pro Micro x 1
* PCB x 1 (gerber 文件和 QMK 固件)
详见[网站][4]的完整细节。
你用树莓派做了什么项目?请在下面的评论中分享。
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/penkesu-handheld-linux-pc/
作者:[John Paul][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/john/
[b]: https://github.com/lujun9972
[1]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU4NSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
[2]: https://github.com/penk
[3]: https://itsfoss.com/cutiepi-open-source-tab/
[4]: http://penkesu.computer/

View File

@ -0,0 +1,111 @@
[#]: subject: "Junction: An Application Switcher to Open Files and Links"
[#]: via: "https://itsfoss.com/junction/"
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "geekpi"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
Junction打开文件和链接的应用切换器
======
**简介:** _一个有趣的工具在访问文件或打开链接时使事情变得简单。让我们来看看它吧_
对于那些涉足多个应用访问不同文件和使用各种浏览器打开链接的用户来说,其工作流程往往不是无缝的。
你可能已经习惯了,但这可能不是完成事情的最快方式。
认识一下 **Junction**,一个应用切换器,帮助你用你最喜欢的应用快速打开文件/链接。
### Junction: 开源的 Linux 应用或浏览器切换器
![][1]
虽然我们可以在打开文件时使用右键菜单中的 “**Open with**” 选项来选择某个应用,但这并不是最快的方法。
有了 [Junction][2],你不必寻找你可以希望文件用什么程序打开(或不断改变默认值),而是要将 “**Junction**” 应用设置为你的默认值。
这样每当你打开一个链接或访问一个文件启动电子邮件编辑器等Junction 应用就会启动,向你显示你可能想要访问的相关应用。
此外,它还支持键盘导航,使其成为键盘高级用户的一个有益补充。
![][3]
基本上,每次你想在不同的应用中访问文件/链接时,它都能为你节省一些点击次数。
### Junction 的特点
![][4]
它是一个适合于特定用户群的简单工具。你可能觉得它是多余的,也可能不觉得它是多余的,但在你想尝试的情况下,它的功能应该可以弥补它的不足:
* 通过启动器/切换器选择要打开的应用
* 在启动前显示位置
* 在打开 URL 之前能够编辑它
* 提示不安全的链接
* 键盘导航
* 能够在切换器/启动器中添加更多的应用(它也会记住添加的内容,以便下次使用)。
![][5]
### 使用 Junction 来访问文件和链接
要设置它,你需要启动应用并将 Junction 设置为 Web 的默认值,如下图所示。
![][6]
要在任何文件类型上使用它,你可以前往各自的文件属性,并为它改变默认的应用,如下图所示:
![][7]
对于链接,你可以通过点击 “**Test Junction**” 来测试它,如上面的截图所示。或者,你可以点击其他应用的任何链接,看看 Junction 应用的运行情况。
下面是你试图点击一个链接并让 Junction 帮助你选择时的情况:
![][8]
### 在 Linux 中安装 Junction
Junction 主要以 Flatpak 应用的形式提供。因此,你可以从 [Flathub][9] 安装软件包,或者在软件中心寻找它(如果 Flatpak 集成完毕)。
考虑到你已经设置了 [Flatpak][10],你可以输入以下命令来安装它:
```
flatpak install flathub re.sonny.Junction
```
你也可以查看它的 [GitHub 页面][11],了解更多的使用案例或利用它的技巧/窍门。
[Junction][9]
_你认为像 Junction 这样的应用切换器怎么样它对你有用吗请在下面的评论中告诉我你的想法。_
--------------------------------------------------------------------------------
via: https://itsfoss.com/junction/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/Junction-ft.png?resize=800%2C450&ssl=1
[2]: https://apps.gnome.org/app/re.sonny.Junction/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-action-screenshot.jpg?resize=800%2C450&ssl=1
[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-app-screenshot.jpg?resize=800%2C455&ssl=1
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-app-more.jpg?resize=800%2C540&ssl=1
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-app.jpg?resize=800%2C586&ssl=1
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-properties.png?resize=800%2C511&ssl=1
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2022/03/junction-link-click.jpg?resize=800%2C505&ssl=1
[9]: https://flathub.org/apps/details/re.sonny.Junction
[10]: https://itsfoss.com/flatpak-guide/
[11]: https://github.com/sonnyp/Junction

View File

@ -0,0 +1,154 @@
[#]: subject: "7 Reasons to Try Open Source Secure Messenger Threema"
[#]: via: "https://news.itsfoss.com/reasons-to-try-threema/"
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
[#]: collector: "lujun9972"
[#]: translator: "lkxed"
[#]: reviewer: " "
[#]: publisher: " "
[#]: url: " "
尝试开源的安全通讯软件 “Threema” 的 7 个理由
======
现在已经有很多私密的 WhatsApp 代替品可供我们选择Threema 则是其中最好的可选项之一。
可是,为什么你要考虑尝试它呢?它是“终极的”安全通讯软件吗?
怎么说呢,每个安全通讯软件都只满足特定用户群体的需求。所以,把任何开源的通讯软件当作是“终极的”选项,都是不明智的。
因此,我列举了一些你或许会想尝试 Threema 而不是其他类似选项的理由。
### Threema背景概览
在我开始说明为什么要尝试 [Threema][2] 这款私密通讯软件之前,请允许我再介绍一下它。
Threema 是一个流行的安全通讯软件,它由瑞士团队研发,专注于个人隐私。它也是一个付费软件,你需要在 [Play Store][3] 或者 [App Store] 上,一次性支付费用(大约 4 美元),才能够在你喜爱的移动设备上使用它。
起初,它是一个专有的安全通讯软件,是 [Signal][5] 等其他软件的竞争者。
在 2020 年的时候Threema 决定在 [GitHub][6] 上开源它的所有软件。
你可以下载到移动应用,也可以得到 Linux 桌面(包括 Windows 和 macOS上的支持。遗憾的是它在桌面上目前没有一个独立的客户端。
因此,你需要让移动设备保持开启状态,才能使用桌面上的 Threema就和 WhatsApp Web 的工作方式一样)。
### 下面是你尝试 Threema 的可能理由
如果你正在寻找一个隐私友好的安全通讯软件,并且你的同事/朋友/家人不介意支付一次性费用的话,你可以把它作为一个可选项。
支持你这么做的理由包括:
### 1. 不需要手机号码
![][7]
和 WhatsApp 不同,你不需要使用手机号码来注册 Threema。当然你可以选择添加你的手机号码如果你希望别人能够很快找到你的话。
但是,手机号码只是注册 Threema 的一个选填项。如果你不想让别人知道你的手机号码,你可以使用注册时生成的 **Threema ID**(用户名)。
如果你要和别人交流,你必须分享你的 Threema ID而不是你的手机号码。
值得一提的是,即使在没有 SIM 卡的设备上,它也能完美工作,因为你不必提供手机号码就可以注册成功。
### 2. 开源
虽然这是一个显而易见的理由,但它十分重要。
我非常重视这一点。如果你想要一个值得信赖的 WhatsApp 替代品,你应该倾向于选择一个开发稳定的开源通讯软件。
### 3. 去中心化的基础设施
![][8]
和大多数主流产品不同Threema 提供了一个去中心化的基础设施,以确保更好地抵御审查制度。
换句话说Threema 并不依赖于一个中心服务器架构,也就不会发生“一个错误导致整个网络瘫痪”这种情况。
这个错误可能是一次停电,或者是政府的一次审查/限制服务的行动。
在这些情况下Threema 会是更有用和更有效的选择。
### 4. 收费软件
它是一个收费软件(一次性付费),这也算是一个好消息吗?
对于某些人来说,是的。
如果你想要寻找一个通讯软件,在上面几乎不可能有垃圾消息,或者你不想让你的联系人找到你(或是给你发一些你不想要的信息),那么 Threema 就是你的一个完美选项。
毕竟,为一个出色的开源解决方案而付费是值得的,对吧?
### 5. 可靠的用户界面和特性
![Credits: Threema][9]
Threema 不是一个新产品,它已经开发了好几年了。
因此,它能够提供稳定的用户体验,以及一些激动人心的特性,比如说它支持在群聊中发起投票。
It lets you silently acknowledge messages from a recipient using agree/disagree without triggering a notification to them. This can come in handy at times.
你可以使用“同意/不同意”选项,以一种静默的方式确认接收方是否收到了消息,而不会触发一个发送给他们的通知。
注意,“同意/不同意”的功能只在个人会话中有效。
你也可以使用二维码来验证你的联系人身份,以此来避免<ruby>中间人<rt>man-in-the-middle</rt></ruby>攻击。
和其他的安全通讯软件相比Threema 对平板电脑的支持也不错。
![Credits: Threema][10]
### 6. 瑞士团队 & 遵守 GDRP 准则
你可能会在意开发团队是否会受到所在国家的司法管辖权和隐私法等限制那么对你而言Threema 就是一个理想的私密通讯软件。
Threema 受瑞士的法律约束,而众所周知,瑞士的法律是最重视个人隐私的。
除此之外Threema 还提到了它完全遵守 GDRP 准则。如果你在意这一点的话Threema 是一个不错的选择。
### 7. 在工作中使用 Threema
![][11]
有趣的事Threema 还有另外一个 [独立的版本][11],专注于加强公司内部的通讯安全。
所以如果你需要一个安全通讯平台来作为即时通讯软件的话Threema 将是一个吸引人的选择。
[Try Threema][12]
### 最后,我的一些想法
我已经使用 Threema 很长时间了,我承认我在上面没有很多联系人。
但我还是要说,它的用户体验是极佳的,并且我在 iOS 和 Android 端都使用过相当长的时间。
因此Threema 更适合那些不想对任何有关隐私的特性妥协的严肃用户。
与此同时,作为一款收费软件,并不是每个人都愿意尝试它。但仔细想想,你将会得到一个可靠的注重隐私的通讯软件,它还是开源的,并且会接受定期的审查。
你对这款软件有什么看法?请在评论区分享你的观点吧!
--------------------------------------------------------------------------------
via: https://news.itsfoss.com/reasons-to-try-threema/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[lkxed](https://github.com/lkxed)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://news.itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/private-whatsapp-alternatives/
[2]: https://threema.ch/en/home
[3]: https://play.google.com/store/apps/details?id=ch.threema.app&hl=en_US&gl=US
[4]: https://apps.apple.com/us/app/threema-the-secure-messenger/id578665578
[5]: https://itsfoss.com/install-signal-ubuntu/
[6]: https://github.com/threema-ch
[7]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/threema-phone-number.jpg?w=1200&ssl=1
[8]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/threema-decentralize-1.jpg?w=1200&ssl=1
[9]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/threema-ui.jpg?w=1280&ssl=1
[10]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/threema-tablet.jpg?w=1213&ssl=1
[11]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2022/03/threema-work.png?w=1081&ssl=1
[12]: https://threema.ch/en