diff --git a/published/20190319 How to set up a homelab from hardware to firewall.md b/published/20190319 How to set up a homelab from hardware to firewall.md new file mode 100644 index 0000000000..54c24e7a14 --- /dev/null +++ b/published/20190319 How to set up a homelab from hardware to firewall.md @@ -0,0 +1,107 @@ +[#]: collector: (lujun9972) +[#]: translator: (wyxplus) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13262-1.html) +[#]: subject: (How to set up a homelab from hardware to firewall) +[#]: via: (https://opensource.com/article/19/3/home-lab) +[#]: author: (Michael Zamot https://opensource.com/users/mzamot) + +如何从硬件到防火墙建立一个家庭实验室 +====== + +> 了解一下用于构建自己的家庭实验室的硬件和软件方案。 + +![](https://img.linux.net.cn/data/attachment/album/202104/02/215222t2fiqpt17gfpkkii.jpg) + +你有想过创建一个家庭实验室吗?或许你想尝试不同的技术,构建开发环境、亦或是建立自己的私有云。拥有一个家庭实验室的理由很多,本教程旨在使入门变得更容易。 + +规划家庭实验室时,需要考虑三方面:硬件、软件和维护。我们将在这里查看前两方面,并在以后的文章中讲述如何节省维护计算机实验室的时间。 + +### 硬件 + +在考虑硬件需求时,首先要考虑如何使用实验室以及你的预算、噪声、空间和电力使用情况。 + +如果购买新硬件过于昂贵,请搜索当地的大学、广告以及诸如 eBay 或 Craigslist 之类的网站,能获取二手服务器的地方。它们通常很便宜,并且服务器级的硬件可以使用很多年。你将需要三类硬件:虚拟化服务器、存储设备和路由器/防火墙。 + +#### 虚拟化服务器 + +一个虚拟化服务器允许你去运行多个共享物理机资源的虚拟机,同时最大化利用和隔离资源。如果你弄坏了一台虚拟机,无需重建整个服务器,只需虚拟一个好了。如果你想进行测试或尝试某些操作而不损坏整个系统,仅需要新建一个虚拟机来运行即可。 + +在虚拟服务器中,需考虑两个最重要的因素是 CPU 的核心数及其运行速度以及内存容量。如果没有足够的资源够全部虚拟机共享,那么它们将被过度分配并试着获取其他虚拟机的 CPU 的周期和内存。 + +因此,考虑一个多核 CPU 的平台。你要确保 CPU 支持虚拟化指令(因特尔的 VT-x 指令集和 AMD 的 AMD-V 指令集)。能够处理虚拟化的优质的消费级处理器有因特尔的 i5 或 i7 和 AMD 的 Ryzen 处理器。如果你考虑服务器级的硬件,那么因特尔的志强系列和 AMD 的 EPYC 都是不错的选择。内存可能很昂贵,尤其是最近的 DDR4 内存。当我们估计所需多少内存时,请为主机操作系统的内存至少分配 2 GB 的空间。 + +如果你担心电费或噪声,则诸如因特尔 NUC 设备之类的解决方案虽然外形小巧、功耗低、噪音低,但是却以牺牲可扩展性为代价。 + +#### NAS + +如果希望装有硬盘驱动器的计算机存储你的所有个人数据,电影,图片等,并为虚拟化服务器提供存储,则需要网络附加存储Network-attached storage(NAS)。 + +在大多数情况下,你不太可能需要一颗强力的 CPU。实际上,许多商业 NAS 的解决方案使用低功耗的 ARM CPU。支持多个 SATA 硬盘的主板是必须的。如果你的主板没有足够的端口,请使用主机总线适配器host bus adapter(HBA)SAS 控制器添加额外的端口。 + +网络性能对于 NAS 来说是至关重要的,因此最好选择千兆gigabit网络(或更快网络)。 + +内存需求根据你的文件系统而有所不同。ZFS 是 NAS 上最受欢迎的文件系统之一,你需要更多内存才能使用诸如缓存或重复数据删除之类的功能。纠错码Error-correcting code(ECC)的内存是防止数据损坏的最佳选择(但在购买前请确保你的主板支持)。最后但同样重要的,不要忘记使用不间断电源uninterruptible power supply(UPS),因为断电可能会使得数据出错。 + +#### 防火墙和路由器 + +你是否曾意识到,廉价的路由器/防火墙通常是保护你的家庭网络不受外部环境影响的主要部分?这些路由器很少及时收到安全更新(如果有的话)。现在害怕了吗?好吧,[确实][2]! + +通常,你不需要一颗强大的 CPU 或是大量内存来构建你自己的路由器/防火墙,除非你需要高吞吐率或是执行 CPU 密集型任务,像是虚拟私有网络服务器或是流量过滤。在这种情况下,你将需要一个支持 AES-NI 的多核 CPU。 + +你可能想要至少 2 个千兆或更快的以太网卡Ethernet network interface cards(NIC),这不是必需的,但我推荐使用一个管理型交换机来连接你自己的装配的路由器,以创建 VLAN 来进一步隔离和保护你的网络。 + +![Home computer lab PfSense][4] + +### 软件 + +在选择完你的虚拟化服务器、NAS 和防火墙/路由器后,下一步是探索不同的操作系统和软件,以最大程度地发挥其作用。尽管你可以使用 CentOS、Debian或 Ubuntu 之类的常规 Linux 发行版,但是与以下软件相比,它们通常花费更多的时间进行配置和管理。 + +#### 虚拟化软件 + +[KVM][5](基于内核的虚拟机Kernel-based Virtual Machine)使你可以将 Linux 变成虚拟机监控程序,以便可以在同一台机器中运行多个虚拟机。最好的是,KVM 作为 Linux 的一部分,它是许多企业和家庭用户的首选。如果你愿意,可以安装 [libvirt][6] 和 [virt-manager][7] 来管理你的虚拟化平台。 + +[Proxmox VE][8] 是一个强大的企业级解决方案,并且是一个完全开源的虚拟化和容器平台。它基于 Debian,使用 KVM 作为其虚拟机管理程序,并使用 LXC 作为容器。Proxmox 提供了强大的网页界面、API,并且可以扩展到许多群集节点,这很有用,因为你永远不知道何时实验室容量不足。 + +[oVirt][9](RHV)是另一种使用 KVM 作为虚拟机管理程序的企业级解决方案。不要因为它是企业级的,就意味着你不能在家中使用它。oVirt 提供了强大的网页界面和 API,并且可以处理数百个节点(如果你运行那么多服务器,我可不想成为你的邻居!)。oVirt 用于家庭实验室的潜在问题是它需要一套最低限度的节点:你将需要一个外部存储(例如 NAS)和至少两个其他虚拟化节点(你可以只在一个节点上运行,但你会遇到环境维护方面的问题)。 + +#### 网络附加存储软件 + +[FreeNAS][10] 是最受欢迎的开源 NAS 发行版,它基于稳定的 FreeBSD 操作系统。它最强大的功能之一是支持 ZFS 文件系统,该文件系统提供了数据完整性检查、快照、复制和多个级别的冗余(镜像、条带化镜像和条带化)。最重要的是,所有功能都通过功能强大且易于使用的网页界面进行管理。在安装 FreeNAS 之前,请检查硬件是否支持,因为它不如基于 Linux 的发行版那么广泛。 + +另一个流行的替代方法是基于 Linux 的 [OpenMediaVault][11]。它的主要功能之一是模块化,带有可扩展和添加特性的插件。它包括的功能包括基于网页管理界面,CIFS、SFTP、NFS、iSCSI 等协议,以及卷管理,包括软件 RAID、资源配额,访问控制列表access control lists(ACL)和共享管理。由于它是基于 Linux 的,因此其具有广泛的硬件支持。 + +#### 防火墙/路由器软件 + +[pfSense][12] 是基于 FreeBSD 的开源企业级路由器和防火墙发行版。它可以直接安装在服务器上,甚至可以安装在虚拟机中(以管理虚拟或物理网络并节省空间)。它有许多功能,可以使用软件包进行扩展。尽管它也有命令行访问权限,但也可以完全使用网页界面对其进行管理。它具有你所希望路由器和防火墙提供的所有功能,例如 DHCP 和 DNS,以及更高级的功能,例如入侵检测(IDS)和入侵防御(IPS)系统。你可以侦听多个不同接口或使用 VLAN 的网络,并且只需鼠标点击几下即可创建安全的 VPN 服务器。pfSense 使用 pf,这是一种有状态的数据包筛选器,它是为 OpenBSD 操作系统开发的,使用类似 IPFilter 的语法。许多公司和组织都有使用 pfSense。 + +* * * + +考虑到所有的信息,是时候动手开始建立你的实验室了。在之后的文章中,我将介绍运行家庭实验室的第三方面:自动化进行部署和维护。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/19/3/home-lab + +作者:[Michael Zamot (Red Hat)][a] +选题:[lujun9972][b] +译者:[wyxplus](https://github.com/wyxplus) +校对:[wxy](https://github.com/wxy) + +本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 + +[a]: https://opensource.com/users/mzamot +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_keyboard_laptop_development_code_woman.png?itok=vbYz6jjb +[2]: https://opensource.com/article/18/5/how-insecure-your-router +[3]: /file/427426 +[4]: https://opensource.com/sites/default/files/uploads/pfsense2.png (Home computer lab PfSense) +[5]: https://www.linux-kvm.org/page/Main_Page +[6]: https://libvirt.org/ +[7]: https://virt-manager.org/ +[8]: https://www.proxmox.com/en/proxmox-ve +[9]: https://ovirt.org/ +[10]: https://freenas.org/ +[11]: https://www.openmediavault.org/ +[12]: https://www.pfsense.org/ diff --git a/translated/tech/20210318 Reverse Engineering a Docker Image.md b/published/20210318 Reverse Engineering a Docker Image.md similarity index 79% rename from translated/tech/20210318 Reverse Engineering a Docker Image.md rename to published/20210318 Reverse Engineering a Docker Image.md index 9ffb64ac2b..0afe15981d 100644 --- a/translated/tech/20210318 Reverse Engineering a Docker Image.md +++ b/published/20210318 Reverse Engineering a Docker Image.md @@ -3,16 +3,18 @@ [#]: author: (Simon Arneaud https://theartofmachinery.com) [#]: collector: (lujun9972) [#]: translator: (DCOLIVERSUN) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13258-1.html) -Docker 镜像逆向工程 +一次 Docker 镜像的逆向工程 ====== -本文介绍的内容开始于一个咨询陷阱:政府组织 A 让政府组织 B 开发一个网络应用程序。政府机构 B 把部分工作外包给某个人。后来,项目的托管和维护被外包给一家私人公司 C。C 公司发现,之前外包的人(过世很久了)已经构建了一个自定义的 Docker 镜像,并使镜像成为系统构建的依赖项,但这个人没有提交原始的 Dockerfile。C 公司有合同义务管理这个 Docker 镜像,可是他们他们没有源代码。C 公司偶尔叫我进去做各种工作,所以处理一些关于这个神秘 Docker 镜像的事情就成了我的工作。 +![](https://img.linux.net.cn/data/attachment/album/202104/01/215523oajrgjo77irb7nun.jpg) -幸运的是,这个 Docker 镜像格式比它应有的样子透明多了。虽然还需要做一些侦查工作,但只要解剖一个镜像文件,就能发现很多东西。例如,这里有一个 [Prettier 代码格式][1]镜像可供快速浏览。 +这要从一次咨询的失误说起:政府组织 A 让政府组织 B 开发一个 Web 应用程序。政府机构 B 把部分工作外包给某个人。后来,项目的托管和维护被外包给一家私人公司 C。C 公司发现,之前外包的人(已经离开很久了)构建了一个自定义的 Docker 镜像,并将其成为系统构建的依赖项,但这个人没有提交原始的 Dockerfile。C 公司有合同义务管理这个 Docker 镜像,可是他们他们没有源代码。C 公司偶尔叫我进去做各种工作,所以处理一些关于这个神秘 Docker 镜像的事情就成了我的工作。 + +幸运的是,Docker 镜像的格式比想象的透明多了。虽然还需要做一些侦查工作,但只要解剖一个镜像文件,就能发现很多东西。例如,这里有一个 [Prettier 代码格式化][1] 的镜像可供快速浏览。 首先,让 Docker 守护进程daemon拉取镜像,然后将镜像提取到文件中: @@ -42,7 +44,7 @@ manifest.json repositories ``` -如你所见,Docker 在命名时经常使用哈希hash。我们看看 `manifest.json`。它在难以阅读的压缩 JSON 中,不过 [`jq` JSON Swiss Army knife][2]可以很好地打印 JSON: +如你所见,Docker 在命名时经常使用哈希hash。我们看看 `manifest.json`。它是以难以阅读的压缩 JSON 写的,不过 [JSON 瑞士军刀 jq][2] 可以很好地打印 JSON: ``` $ jq . manifest.json @@ -61,7 +63,7 @@ $ jq . manifest.json ] ``` -请注意,这三层对应三个 hash 命名的目录。我们以后再看。现在,让我们看看 `Config` 键指向的 JSON 文件。文件名有点长,所有我把第一点放在这里: +请注意,这三个Layer对应三个以哈希命名的目录。我们以后再看。现在,让我们看看 `Config` 键指向的 JSON 文件。它有点长,所以我只在这里转储第一部分: ``` $ jq . 88f38be28f05f38dba94ce0c1328ebe2b963b65848ab96594f8172a9c3b0f25b.json | head -n 20 @@ -87,9 +89,9 @@ $ jq . 88f38be28f05f38dba94ce0c1328ebe2b963b65848ab96594f8172a9c3b0f25b.json | h "Image": "sha256:93e72874b338c1e0734025e1d8ebe259d4f16265dc2840f88c4c754e1c01ba0a", ``` -最重要的是 `history` 列表,它列出了镜像中的每一层。Docker 镜像由这些层堆叠而成。Dockerfile 中几乎每条命令都会变成一个层,描述该命令对镜像所做的更改。如果你执行 `RUN script.sh` 命令,创建 `really_big_file`,然后你用 `RUN rm really_big_file` 命令删除文件,Docker 镜像实际生成两层:一个包含 `really_big_file`,一个包含 `.wh.really_big_file` 记录来删除它。整个镜像文件大小不变。这就是为什么你会经常看到像 `RUN script.sh && rm really_big_file` 这样的 Dockerfile 命令链接在一起——它保障所有更改都合并到一层中。 +最重要的是 `history` 列表,它列出了镜像中的每一层。Docker 镜像由这些层堆叠而成。Dockerfile 中几乎每条命令都会变成一个层,描述该命令对镜像所做的更改。如果你执行 `RUN script.sh` 命令创建了 `really_big_file`,然后用 `RUN rm really_big_file` 命令删除文件,Docker 镜像实际生成两层:一个包含 `really_big_file`,一个包含 `.wh.really_big_file` 记录来删除它。整个镜像文件大小不变。这就是为什么你会经常看到像 `RUN script.sh && rm really_big_file` 这样的 Dockerfile 命令链接在一起——它保障所有更改都合并到一层中。 -以下是 Docker 镜像中记录的所有层。注意,大多数层不改变文件系统镜像,并且 `empty_layer` 标记为 true。以下只有三个层是非空的,与我们之前描述的相符。 +以下是该 Docker 镜像中记录的所有层。注意,大多数层不改变文件系统镜像,并且 `empty_layer` 标记为 `true`。以下只有三个层是非空的,与我们之前描述的相符。 ``` $ jq .history 88f38be28f05f38dba94ce0c1328ebe2b963b65848ab96594f8172a9c3b0f25b.json @@ -162,7 +164,7 @@ m=${NODEJS_VERSION} && npm install -g prettier@${PRETTIER_VERSION} && np ] ``` -太棒了!所有的命令都在 `created_by` 字段中,我们几乎可以用这些命令重建 Dockerfile。但不是完全可以。最上面的 `ADD` 命令实际上没有给我们需要添加的文件。`COPY` 命令也没有全部信息。因为 `FROM` 命令会扩展到继承基础 Docker 镜像的所有层,所以可能会跟丢该命令。 +太棒了!所有的命令都在 `created_by` 字段中,我们几乎可以用这些命令重建 Dockerfile。但不是完全可以。最上面的 `ADD` 命令实际上没有给我们需要添加的文件。`COPY` 命令也没有全部信息。我们还失去了 `FROM` 语句,因为它们扩展成了从基础 Docker 镜像继承的所有层。 我们可以通过查看时间戳timestamp,按 Dockerfile 对层进行分组。大多数层的时间戳相差不到一分钟,代表每一层构建所需的时间。但是前两层是 `2020-04-24`,其余的是 `2020-04-29`。这是因为前两层来自一个基础 Docker 镜像。理想情况下,我们可以找出一个 `FROM` 命令来获得这个镜像,这样我们就有了一个可维护的 Dockerfile。 @@ -215,7 +217,7 @@ $ cat etc/alpine-release 3.11.6 ``` -如果你拉取、解压 `alpine:3.11.6`,你会发现里面有一个非空层,`layer.tar`与 Prettier 镜像基础层中的 `layer.tar` 是一样的。 +如果你拉取、解压 `alpine:3.11.6`,你会发现里面有一个非空层,`layer.tar` 与 Prettier 镜像基础层中的 `layer.tar` 是一样的。 出于兴趣,另外两个非空层是什么?第二层是包含 Prettier 安装包的主层。它有 528 个条目,包含 Prettier、一堆依赖项和证书更新: @@ -264,7 +266,7 @@ $ tar tf 6c37da2ee7de579a0bf5495df32ba3e7807b0a42e2a02779206d165f55f1ba70/layer. work/ ``` -[原始 Dockerfile 在 Prettier 的 git repo 中][4] +[原始 Dockerfile 在 Prettier 的 git 仓库中][4]。 -------------------------------------------------------------------------------- @@ -273,7 +275,7 @@ via: https://theartofmachinery.com/2021/03/18/reverse_engineering_a_docker_image 作者:[Simon Arneaud][a] 选题:[lujun9972][b] 译者:[DCOLIVERSUN](https://github.com/DCOLIVERSUN) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/translated/tech/20210324 Read and write files with Bash.md b/published/20210324 Read and write files with Bash.md similarity index 73% rename from translated/tech/20210324 Read and write files with Bash.md rename to published/20210324 Read and write files with Bash.md index 2e493db99b..d4e0e2b79e 100644 --- a/translated/tech/20210324 Read and write files with Bash.md +++ b/published/20210324 Read and write files with Bash.md @@ -3,14 +3,16 @@ [#]: author: (Seth Kenlon https://opensource.com/users/seth) [#]: collector: (lujun9972) [#]: translator: (geekpi) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13259-1.html) 用 Bash 读写文件 ====== -学习 Bash 读取和写入数据的不同方式,以及何时使用每种方法。 -![bash logo on green background][1] + +> 学习 Bash 读取和写入数据的不同方式,以及何时使用每种方法。 + +![](https://img.linux.net.cn/data/attachment/album/202104/01/223653bc334ac33e5e4pwe.jpg) 当你使用 Bash 编写脚本时,有时你需要从一个文件中读取数据或向一个文件写入数据。有时文件可能包含配置选项,而另一些时候这个文件是你的用户用你的应用创建的数据。每种语言处理这个任务的方式都有些不同,本文将演示如何使用 Bash 和其他 [POSIX][2] shell 处理数据文件。 @@ -26,15 +28,16 @@ ### 使用 Bash 读取文件 -除了是 [shell][5] 之外,Bash 还是一种脚本语言。有几种方法可以从 Bash 中读取数据。你可以创建一种数据流并解析输出, 或者你可以将数据加载到内存中. 这两种方法都是有效的获取信息的方法,但每种方法都有相当具体的用例。 +除了是 [shell][5] 之外,Bash 还是一种脚本语言。有几种方法可以从 Bash 中读取数据。你可以创建一种数据流并解析输出, 或者你可以将数据加载到内存中。这两种方法都是有效的获取信息的方法,但每种方法都有相当具体的用例。 -#### 在 Bash 中 source 文件 +#### 在 Bash 中援引文件 -当你在 Bash 中 “source” 一个文件时,你会让 Bash 读取文件的内容,期望它包含有效的数据,Bash 可以将这些数据放入它建立的数据模型中。你不会从任何旧文件中获取数据,但你可以使用这种方法来读取配置文件和函数。 +当你在 Bash 中 “援引source” 一个文件时,你会让 Bash 读取文件的内容,期望它包含有效的数据,Bash 可以将这些数据放入它建立的数据模型中。你不会想要从旧文件中援引数据,但你可以使用这种方法来读取配置文件和函数。 + +(LCTT 译注:在 Bash 中,可以通过 `source` 或 `.` 命令来将一个文件读入,这个行为称为 “sourcing”,英文原意为“一次性(试)采购”、“寻找供应商”、“获得”等,考虑到 Bash 的语境和发音,我建议可以翻译为“援引”,或有不当,供大家讨论参考 —— wxy) 例如,创建一个名为 `example.sh` 的文件,并输入以下内容: - ``` #!/bin/sh @@ -45,7 +48,6 @@ echo "The meaning of life is $var" 运行这段代码,看见失败了: - ``` $ bash ./example.sh ./example.sh: line 3: greet: command not found @@ -54,7 +56,6 @@ The meaning of life is Bash 没有一个叫 `greet` 的命令,所以无法执行那一行,也没有一个叫 `var` 的变量记录,所以文件没有意义。为了解决这个问题,建立一个名为 `include.sh` 的文件: - ``` greet() {     echo "Hello ${1}" @@ -63,8 +64,7 @@ greet() { var=42 ``` -修改你的 `example.sh` 脚本,加入 `source` 命令: - +修改你的 `example.sh` 脚本,加入一个 `source` 命令: ``` #!/bin/sh @@ -76,8 +76,7 @@ greet opensource.com echo "The meaning of life is $var" ``` -运行脚本,看见已经可以了: - +运行脚本,可以看到工作了: ``` $ bash ./example.sh @@ -89,8 +88,7 @@ The meaning of life is 42 #### 在 Bash 中解析文件 -另一种让数据“进入” Bash 的方法是将其解析为数据流。有很多方法可以做到这一点. 你可以使用 `grep` 或 `cat` 或任何可以获取数据并管道输出到标准输出的命令。另外,你可以使用 Bash 内置的东西:重定向。重定向本身并不是很有用, 所以在这个例子中, 我也使用内置的 `echo` 命令来打印重定向的结果: - +另一种让数据“进入” Bash 的方法是将其解析为数据流。有很多方法可以做到这一点. 你可以使用 `grep` 或 `cat` 或任何可以获取数据并管道输出到标准输出的命令。另外,你可以使用 Bash 内置的东西:重定向。重定向本身并不是很有用,所以在这个例子中,我也使用内置的 `echo` 命令来打印重定向的结果: ``` #!/bin/sh @@ -100,15 +98,13 @@ echo $( < include.sh ) 将其保存为 `stream.sh` 并运行它来查看结果: - ``` $ bash ./stream.sh greet() { echo "Hello ${1}" } var=42 $ ``` -对于 `include.sh` 文件中的每一行,Bash 都会将该行打印(或 echo)到你的终端。先用管道把它传送到一个合适的解析器是用 Bash 读取数据的常用方法。例如, 假设 `include.sh` 是一个配置文件, 它的键和值对用一个等号(`=`)分开. 你可以用 `awk` 甚至 `cut` 来获取值: - +对于 `include.sh` 文件中的每一行,Bash 都会将该行打印(或 `echo`)到你的终端。先用管道把它传送到一个合适的解析器是用 Bash 读取数据的常用方法。例如, 假设 `include.sh` 是一个配置文件, 它的键和值对用一个等号(`=`)分开. 你可以用 `awk` 甚至 `cut` 来获取值: ``` #!/bin/sh @@ -120,7 +116,6 @@ echo $myVar 试着运行这个脚本: - ``` $ bash ./stream.sh 42 @@ -132,12 +127,11 @@ $ bash ./stream.sh 例如, 要创建一个包含输出的新文件, 使用一个重定向符号: - ``` #!/bin/sh TZ=UTC -date > date.txt +date > date.txt ``` 运行脚本几次: @@ -153,17 +147,15 @@ Tue Feb 23 22:25:12 UTC 2021 要追加数据,使用两个重定向符号: - ``` #!/bin/sh TZ=UTC -date >> date.txt +date >> date.txt ``` 运行脚本几次: - ``` $ bash ./date.sh $ bash ./date.sh @@ -177,7 +169,7 @@ Tue Feb 23 22:25:22 UTC 2021 ### Bash 轻松编程 -Bash 的优势在于简单易学,因为只需要一些基本的概念,你就可以构建复杂的程序。完整的文档请参考 GNU.org 上的[优秀的 Bash 文档][6]。 +Bash 的优势在于简单易学,因为只需要一些基本的概念,你就可以构建复杂的程序。完整的文档请参考 GNU.org 上的 [优秀的 Bash 文档][6]。 -------------------------------------------------------------------------------- @@ -186,7 +178,7 @@ via: https://opensource.com/article/21/3/input-output-bash 作者:[Seth Kenlon][a] 选题:[lujun9972][b] 译者:[geekpi](https://github.com/geekpi) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/translated/tech/20210326 How to read and write files in C.md b/published/20210326 How to read and write files in C.md similarity index 66% rename from translated/tech/20210326 How to read and write files in C.md rename to published/20210326 How to read and write files in C.md index 63b71f7a6a..721eda3db0 100644 --- a/translated/tech/20210326 How to read and write files in C.md +++ b/published/20210326 How to read and write files in C.md @@ -3,22 +3,22 @@ [#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99) [#]: collector: (lujun9972) [#]: translator: (wyxplus) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13263-1.html) 如何用 C++ 读写文件 ====== -如果你知道如何在 C++ 中使用输入输出I/O流,那么你便能够(原则上)处理任何类型的输入输出设备。 +> 如果你知道如何在 C++ 中使用输入输出(I/O)流,那么(原则上)你便能够处理任何类型的输入输出设备。 -![Computer screen with files or windows open][1] +![](https://img.linux.net.cn/data/attachment/album/202104/02/224507a2fq6ofotf4ff4rf.jpg) -在 C++ 中,可以通过将输入输出流与流运算符 `>>` 和 `<<` 结合使用来进行文件读写。当读写文件的时候,这些运算符将应用于代表硬盘驱动器上文件类的实例上。这种基于流的方法有个巨大的优势:从 C++ 的角度,无论你要读取或写入的内容是文件、数据库、控制台,亦或是你通过网络连接的另外一台电脑,这都无关紧要。因此,知道如何使用流运算符来写入文件能够被利用到其他领域。 +在 C++ 中,对文件的读写可以通过使用输入输出流与流运算符 `>>` 和 `<<` 来进行。当读写文件的时候,这些运算符被应用于代表硬盘驱动器上文件类的实例上。这种基于流的方法有个巨大的优势:从 C++ 的角度,无论你要读取或写入的内容是文件、数据库、控制台,亦或是你通过网络连接的另外一台电脑,这都无关紧要。因此,知道如何使用流运算符来写入文件能够被转用到其他领域。 ### 输入输出流类 -C++ 标准库提供了 [ios_base][2] 类。该类充当所有 I/O 流的基类,例如 [basic_ofstream][3] 和 [basic_ifstream][4]。本例将使用特殊的类型来读写字符,`ifstream` 和 `ofstream`。 +C++ 标准库提供了 [ios_base][2] 类。该类作为所有 I/O 流的基类,例如 [basic_ofstream][3] 和 [basic_ifstream][4]。本例将使用读/写字符的专用类型 `ifstream` 和 `ofstream`。 - `ofstream`:输出文件流,并且其能通过插入运算符 `<<` 来实现。 - `ifstream`:输入文件流,并且其能通过提取运算符 `>>` 来实现。 @@ -31,11 +31,11 @@ C++ 标准库提供了 [ios_base][2] 类。该类充当所有 I/O 流的基类 本例程是非常简单:实例化了一个 `ofstream` 来写入,和实例化一个 `ifstream` 来读取。 - ``` -#include <iostream> // cout, cin, cerr etc... -#include <fstream> // ifstream, ofstream -#include <string> +#include // cout, cin, cerr etc... +#include // ifstream, ofstream +#include + int main() { @@ -50,12 +50,13 @@ int main() std::ofstream fileSink(sFilename); // Creates an output file stream if (!fileSink) { - std::cerr << "Canot open " << sFilename << std::endl; + std::cerr << "Canot open " << sFilename << std::endl; exit(-1); } /* std::endl will automatically append the correct EOL */ - fileSink << "Hello Open Source World!" << std::endl; + fileSink << "Hello Open Source World!" << std::endl; + /****************************************** * * @@ -66,17 +67,17 @@ int main() std::ifstream fileSource(sFilename); // Creates an input file stream if (!fileSource) { - std::cerr << "Canot open " << sFilename << std::endl; + std::cerr << "Canot open " << sFilename << std::endl; exit(-1); } else { // Intermediate buffer std::string buffer; - // By default, the >> operator reads word by workd (till whitespace) - while (fileSource >> buffer) + // By default, the >> operator reads word by workd (till whitespace) + while (fileSource >> buffer) { - std::cout << buffer << std::endl; + std::cout << buffer << std::endl; } } @@ -88,22 +89,20 @@ int main() ![Console screenshot][8] -(Stephan Avenwedde, [CC BY-SA 4.0][9]) - -这是个简易、适合初学者的例子。如果你想去使用该代码在你自己的应用中,最好遵从以下建议: +这是个简化的、适合初学者的例子。如果你想去使用该代码在你自己的应用中,请注意以下几点: * 文件流在程序结束的时候自动关闭。如果你想继续执行,那么应该通过调用 `close()` 方法手动关闭。 - * 这些文件流类继承自 [basic_ios][10](在多个级别上),并且重载了 `!` 运算符。这使你可以进行简单的检查,是否可以访问该流。在 [cppreference.com][11] 上,你可以找到该检查何时会(或不会)成功的概述,并且可以进一步实现错误处理。 + * 这些文件流类继承自 [basic_ios][10](在多个层次上),并且重载了 `!` 运算符。这使你可以进行简单的检查是否可以访问该流。在 [cppreference.com][11] 上,你可以找到该检查何时会(或不会)成功的概述,并且可以进一步实现错误处理。 * 默认情况下,`ifstream` 停在空白处并跳过它。要逐行读取直到到达 [EOF][13] ,请使用 `getline(...)` 方法。 - * 为了读写二进制文件,请将 `std::ios::binary` 标志传递给构造函数:这样可以防止 [EOL][13] 字符附加到每一行。 + * 为了读写二进制文件,请将 `std::ios::binary` 标志传递给构造函数:这样可以防止 [EOL][13] 字符附加到每一行。 ### 从系统角度进行写入 -写入文件时,数据将写入系统的内存写入缓冲区中。当系统收到系统调用 [sync][14] 时,此缓冲区的内容将被写入硬盘。这也是你在不告知系统的情况下,不要卸下 U 盘的原因。通常,守护进程会定期调用 _sync_。为了安全起见,也可以手动调用 _sync_: +写入文件时,数据将写入系统的内存写入缓冲区中。当系统收到系统调用 [sync][14] 时,此缓冲区的内容将被写入硬盘。这也是你在不告知系统的情况下,不要卸下 U 盘的原因。通常,守护进程会定期调用 `sync`。为了安全起见,也可以手动调用 `sync()`: ``` -#include <unistd.h> // needs to be included +#include // needs to be included sync(); ``` @@ -119,7 +118,7 @@ via: https://opensource.com/article/21/3/ccc-input-output 作者:[Stephan Avenwedde][a] 选题:[lujun9972][b] 译者:[wyxplus](https://github.com/wyxplus) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 diff --git a/published/20210326 Why you should care about service mesh.md b/published/20210326 Why you should care about service mesh.md new file mode 100644 index 0000000000..9e387a2342 --- /dev/null +++ b/published/20210326 Why you should care about service mesh.md @@ -0,0 +1,67 @@ +[#]: subject: (Why you should care about service mesh) +[#]: via: (https://opensource.com/article/21/3/service-mesh) +[#]: author: (Daniel Oh https://opensource.com/users/daniel-oh) +[#]: collector: (lujun9972) +[#]: translator: (geekpi) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13261-1.html) + +为什么需要关心服务网格 +====== + +> 在微服务环境中,服务网格为开发和运营提供了好处。 + +![](https://img.linux.net.cn/data/attachment/album/202104/02/201409os5r13omp5p5bssb.jpg) + +很多开发者不知道为什么要关心[服务网格][2]Service Mesh。这是我在开发者见面会、会议和实践研讨会上关于云原生架构的微服务开发的演讲中经常被问到的问题。我的回答总是一样的:“只要你想简化你的微服务架构,它就应该运行在 Kubernetes 上。” + +关于简化,你可能也想知道,为什么分布式微服务必须设计得如此复杂才能在 Kubernetes 集群上运行。正如本文所解释的那样,许多开发人员通过服务网格解决了微服务架构的复杂性,并通过在生产中采用服务网格获得了额外的好处。 + +### 什么是服务网格? + +服务网格是一个专门的基础设施层,用于提供一个透明的、独立于代码的 (polyglot) 方式,以消除应用代码中的非功能性微服务能力。 + +![Before and After Service Mesh][3] + +### 为什么服务网格对开发者很重要 + +当开发人员将微服务部署到云时,无论业务功能如何,他们都必须解决非功能性微服务功能,以避免级联故障。这些功能通常可以体现在服务发现、日志、监控、韧性resiliency、认证、弹性elasticity和跟踪等方面。开发人员必须花费更多的时间将它们添加到每个微服务中,而不是开发实际的业务逻辑,这使得微服务变得沉重而复杂。 + +随着企业加速向云计算转移,服务网格 可以提高开发人员的生产力。Kubernetes 加服务网格平台不需要让服务负责处理这些复杂的问题,也不需要在每个服务中添加更多的代码来处理云原生的问题,而是负责向运行在该平台上的任何应用(现有的或新的,用任何编程语言或框架)提供这些服务。那么微服务就可以轻量级,专注于其业务逻辑,而不是云原生的复杂性。 + +### 为什么服务网格对运维很重要 + +这并没有回答为什么运维团队需要关心在 Kubernetes 上运行云原生微服务的服务网格。因为运维团队必须确保在 Kubernetes 环境上的大型混合云和多云上部署新的云原生应用的强大安全性、合规性和可观察性。 + +服务网格由一个用于管理代理路由流量的控制平面和一个用于注入边车Sidecar的数据平面组成。边车允许运维团队做一些比如添加第三方安全工具和追踪所有服务通信中的流量,以避免安全漏洞或合规问题。服务网格还可以通过在图形面板上可视化地跟踪指标来提高观察能力。 + +### 如何开始使用服务网格 + +对于开发者和运维人员,以及从应用开发到平台运维来说,服务网格可以更有效地管理云原生功能。 + +你可能想知道从哪里开始采用服务网格来配合你的微服务应用和架构。幸运的是,有许多开源的服务网格项目。许多云服务提供商也在他们的 Kubernetes 平台中提供 服务网格。 + +![CNCF Service Mesh Landscape][5] + +你可以在 [CNCF Service Mesh Landscape][6] 页面中找到最受欢迎的服务网格项目和服务的链接。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/3/service-mesh + +作者:[Daniel Oh][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/daniel-oh +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_analytics_cloud.png?itok=eE4uIoaB (Net catching 1s and 0s or data in the clouds) +[2]: https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh +[3]: https://opensource.com/sites/default/files/uploads/vm-vs-service-mesh.png (Before and After Service Mesh) +[4]: https://creativecommons.org/licenses/by-sa/4.0/ +[5]: https://opensource.com/sites/default/files/uploads/service-mesh-providers.png (CNCF Service Mesh Landscape) +[6]: https://landscape.cncf.io/card-mode?category=service-mesh&grouping=category diff --git a/published/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md b/published/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md new file mode 100644 index 0000000000..11f3c7231c --- /dev/null +++ b/published/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md @@ -0,0 +1,98 @@ +[#]: subject: (NewsFlash: A Modern Open-Source Feed Reader With Feedly Support) +[#]: via: (https://itsfoss.com/newsflash-feedreader/) +[#]: author: (Ankush Das https://itsfoss.com/author/ankush/) +[#]: collector: (lujun9972) +[#]: translator: (DCOLIVERSUN) +[#]: reviewer: (wxy) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-13264-1.html) + +NewsFlash: 一款支持 Feedly 的现代开源 Feed 阅读器 +====== + +![](https://img.linux.net.cn/data/attachment/album/202104/03/001037r2udx6u6xqu5sqzu.jpg) + +有些人可能认为 RSS 阅读器已经不再,但它们仍然坚持在这里,特别是当你不想让大科技算法来决定你应该阅读什么的时候。Feed 阅读器可以帮你自助选择阅读来源。 + +我最近遇到一个很棒的 RSS 阅读器 NewsFlash。它支持通过基于网页的 Feed 阅读器增加 feed,例如 [Feedly][1] 和 NewsBlur。这是一个很大的安慰,因为如果你已经使用这种服务,就不必人工导入 feed,这节省了你的工作。 + +NewsFlash 恰好是 [FeedReadeer][2] 的精神继承者,原来的 FeedReader 开发人员也参与其中。 + +如果你正在找适用的 RSS 阅读器,我们整理了 [Linux Feed 阅读器][3] 列表供您参考。 + +### NewsFlash: 一款补充网页 RSS 阅读器账户的 Feed 阅读器 + +![][4] + +请注意,NewsFlash 并不只是针对基于网页的 RSS feed 账户量身定做的,你也可以选择使用本地 RSS feed,而不必在多设备间同步。 + +不过,如果你在用是任何一款支持的基于网页的 feed 阅读器,那么 NewsFlash 特别有用。 + +这里,我将重点介绍 NewsFlash 提供的一些功能。 + +### NewsFlash 功能 + +![][5] + + * 支持桌面通知 + * 快速搜索、过滤 + * 支持标签 + * 便捷、可重定义的键盘快捷键 + * 本地 feed + * OPML 文件导入/导出 + * 无需注册即可在 Feedly 库中轻松找到不同 RSS Feed + * 支持自定义字体 + * 支持多主题(包括深色主题) + * 启动/禁止缩略图 + * 细粒度调整定期同步间隔时间 + * 支持基于网页的 Feed 账户,例如 Feedly、Fever、NewsBlur、feedbin、Miniflux + +除上述功能外,当你调整窗口大小时,还可以打开阅读器视图,这是一个细腻的补充功能。 + +![newsflash 截图1][6] + +账户重新设置也很容易,这将删除所有本地数据。是的,你可以手动清除缓存并设置到期时间,并为你关注的所有 feed 设置一个用户数据存在本地的到期时间。 + +### 在 Linux 上安装 NewsFlash + +你无法找到适用于各种 Linux 发行版的官方软件包,只有 [Flatpak][8]。 + +对于 Arch 用户,可以从 [AUR][9] 下载。 + +幸运的是,[Flatpak][10] 软件包可以让你轻松在 Linux 发行版上安装 NewsFlash。具体请参阅我们的 [Flatpak 指南][11]。 + +你可以参考 NewsFlash 的 [GitLab 页面][12] 去解决大部分问题。 + +### 结束语 + +我现在用 NewsFlash 作为桌面本地解决方案,不用基于网页的服务。你可以通过直接导出 OPML 文件在移动 feed 应用上得到相同的 feed。这已经被我验证过了。 + +用户界面易于使用,也提供了数一数二的新版 UX。虽然这个 RSS 阅读器看似简单,但提供了你可以找到的所有重要功能。 + +你怎么看 NewsFlash?你喜欢用其他类似产品吗?欢迎在评论区中分享你的想法。 + +-------------------------------------------------------------------------------- + +via: https://itsfoss.com/newsflash-feedreader/ + +作者:[Ankush Das][a] +选题:[lujun9972][b] +译者:[DCOLIVERSUN](https://github.com/DCOLIVERSUN) +校对:[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://feedly.com/ +[2]: https://jangernert.github.io/FeedReader/ +[3]: https://itsfoss.com/feed-reader-apps-linux/ +[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash.jpg?resize=945%2C648&ssl=1 +[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash-screenshot.jpg?resize=800%2C533&ssl=1 +[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash-screenshot-1.jpg?resize=800%2C532&ssl=1 +[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/04/best-feed-reader-apps-linux.jpg?fit=800%2C450&ssl=1 +[8]: https://flathub.org/apps/details/com.gitlab.newsflash +[9]: https://itsfoss.com/aur-arch-linux/ +[10]: https://itsfoss.com/what-is-flatpak/ +[11]: https://itsfoss.com/flatpak-guide/ +[12]: https://gitlab.com/news-flash/news_flash_gtk diff --git a/sources/tech/20200423 4 open source chat applications you should use right now.md b/sources/tech/20200423 4 open source chat applications you should use right now.md index 25aa100c53..9d7fbb78ca 100644 --- a/sources/tech/20200423 4 open source chat applications you should use right now.md +++ b/sources/tech/20200423 4 open source chat applications you should use right now.md @@ -1,5 +1,5 @@ [#]: collector: (lujun9972) -[#]: translator: ( ) +[#]: translator: (wyxplus) [#]: reviewer: ( ) [#]: publisher: ( ) [#]: url: ( ) diff --git a/sources/tech/20210329 Manipulate data in files with Lua.md b/sources/tech/20210329 Manipulate data in files with Lua.md deleted file mode 100644 index 7d47bed036..0000000000 --- a/sources/tech/20210329 Manipulate data in files with Lua.md +++ /dev/null @@ -1,97 +0,0 @@ -[#]: subject: (Manipulate data in files with Lua) -[#]: via: (https://opensource.com/article/21/3/lua-files) -[#]: author: (Seth Kenlon https://opensource.com/users/seth) -[#]: collector: (lujun9972) -[#]: translator: (geekpi) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) - -Manipulate data in files with Lua -====== -Understand how Lua handles reading and writing data. -![Person standing in front of a giant computer screen with numbers, data][1] - -Some data is ephemeral, stored in RAM, and only significant while an application is running. But some data is meant to be persistent, stored on a hard drive for later use. When you program, whether you're working on a simple script or a complex suite of tools, it's common to need to read and write files. Sometimes a file may contain configuration options, and other times the file is the data that your user is creating with your application. Every language handles this task a little differently, and this article demonstrates how to handle data files with Lua. - -### Installing Lua - -If you're on Linux, you can install Lua from your distribution's software repository. On macOS, you can install Lua from [MacPorts][2] or [Homebrew][3]. On Windows, you can install Lua from [Chocolatey][4]. - -Once you have Lua installed, open your favorite text editor and get ready to code. - -### Reading a file with Lua - -Lua uses the `io` library for data input and output. The following example creates a function called `ingest` to read data from a file and then parses it with the `:read` function. When opening a file in Lua, there are several modes you can enable. Because I just need to read data from this file, I use the `r` (for "read") mode: - - -``` -function ingest(file) -   local f = io.open(file, "r") -   local lines = f:read("*all") -   f:close() -   return(lines) -end - -myfile=ingest("example.txt") -print(myfile) -``` - -In the code, notice that the variable `myfile` is created to trigger the `ingest` function, and therefore, it receives whatever that function returns. The `ingest` function returns the lines (from a variable intuitively called `lines`) of the file. When the contents of the `myfile` variable are printed in the final step, the lines of the file appear in the terminal. - -If the file `example.txt` contains configuration options, then I would write some additional code to parse that data, probably using another Lua library depending on whether the configuration was stored as an INI file or YAML file or some other format. If the data were an SVG graphic, I'd write extra code to parse XML, probably using an SVG library for Lua. In other words, the data your code reads can be manipulated once it's loaded into memory, but all that's required to load it is the `io` library. - -### Writing data to a file with Lua - -Whether you're storing data your user is creating with your application or just metadata about what the user is doing in an application (for instance, game saves or recent songs played), there are many good reasons to store data for later use. In Lua, this is achieved through the `io` library by opening a file, writing data into it, and closing the file: - - -``` -function exgest(file) -   local f = io.open(file, "a") -   io.output(f) -   io.write("hello world\n") -   io.close(f) -end - -exgest("example.txt") -``` - -To read data from the file, I open the file in `r` mode, but this time I use `a` (for "append") to write data to the end of the file. Because I'm writing plain text into a file, I added my own newline character (`\n`). Often, you're not writing raw text into a file, and you'll probably use an additional library to write a specific format instead. For instance, you might use an INI or YAML library to help write configuration files, an XML library to write XML, and so on. - -### File modes - -When opening files in Lua, there are some safeguards and parameters to define how a file should be handled. The default is `r`, which permits you to read data only: - - * **r** for read only - * **w** to overwrite or create a new file if it doesn't already exist - * **r+** to read and overwrite - * **a** to append data to a file or make a new file if it doesn't already exist - * **a+** to read data, append data to a file, or make a new file if it doesn't already exist - - - -There are a few others (`b` for binary formats, for instance), but those are the most common. For the full documentation, refer to the excellent Lua documentation on [Lua.org/manual][5]. - -### Lua and files - -Like other programming languages, Lua has plenty of library support to access a filesystem to read and write data. Because Lua has a consistent and simple syntax, it's easy to perform complex processing on data in files of any format. Try using Lua for your next software project, or as an API for your C or C++ project. - --------------------------------------------------------------------------------- - -via: https://opensource.com/article/21/3/lua-files - -作者:[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/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data) -[2]: https://opensource.com/article/20/11/macports -[3]: https://opensource.com/article/20/6/homebrew-mac -[4]: https://opensource.com/article/20/3/chocolatey -[5]: http://lua.org/manual diff --git a/sources/tech/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md b/sources/tech/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md deleted file mode 100644 index c618c66205..0000000000 --- a/sources/tech/20210330 NewsFlash- A Modern Open-Source Feed Reader With Feedly Support.md +++ /dev/null @@ -1,106 +0,0 @@ -[#]: subject: (NewsFlash: A Modern Open-Source Feed Reader With Feedly Support) -[#]: via: (https://itsfoss.com/newsflash-feedreader/) -[#]: author: (Ankush Das https://itsfoss.com/author/ankush/) -[#]: collector: (lujun9972) -[#]: translator: (DCOLIVERSUN) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) - -NewsFlash: A Modern Open-Source Feed Reader With Feedly Support -====== - -Some may choose to believe that RSS readers are dead, but they’re here to stay. Especially when you don’t want the Big tech algorithm to decide what you should read. With a feed reader, you can choose your own reading sources. - -I’ve recently come across a fantastic RSS reader NewsFlash. It also supports adding feeds through web-based feed readers like [Feedly][1] and NewsBlur. That’s a big relief because if you are already such a service, you don’t have to import your feeds manually. - -NewsFlash happens to be the spiritual successor to [FeedReader][2] with the original developer involved as well. - -In case you’re wondering, we’ve already covered a list of [Feed Reader apps for Linux][3] if you’re looking for more options. - -### NewsFlash: A Feed Reader To Complement Web-based RSS Reader Account - -![][4] - -It is important to note that NewsFlash isn’t just tailored for web-based RSS feed accounts, you can choose to use local RSS feeds as well without needing to sync them on multiple devices. - -However, it is specifically helpful if you’re using any of the supported web-based feed readers. - -Here, I’ll be highlighting some of the features that it offers. - -### Features of NewsFlash - -![][5] - - * Desktop Notifications support - * Fast search and filtering - * Supports tagging - * Useful keyboard shortcuts that can be later customized - * Local feeds - * Import/Export OPML files - * Easily discover various RSS Feeds using Feedly’s library without needing to sign up for the service - * Custom Font Support - * Multiple themes supported (including a dark theme) - * Ability to enable/disable the Thumbnails - * Tweak the time for regular sync intervals - * Support for web-based Feed accounts like Feedly, Fever, NewsBlur, feedbin, Miniflux - - - -In addition to the features mentioned, it also opens the reader view when you re-size the window, so that’s a subtle addition. - -![newsflash screenshot 1][6] - -If you want to reset the account, you can easily do that as well – which will delete all your local data as well. And, yes, you can manually clear the cache and set an expiry for user data to exist locally for all the feeds you follow. - -**Recommended Read:** - -![][7] - -#### [6 Best Feed Reader Apps for Linux][3] - -Extensively use RSS feeds to stay updated with your favorite websites? Take a look at the best feed reader applications for Linux. - -### Installing NewsFlash in Linux - -You do not get any official packages available for various Linux distributions but limited to a [Flatpak][8]. - -For Arch users, you can find it available in [AUR][9]. - -Fortunately, the [Flatpak][10] package makes it easy for you to install it on any Linux distro you use. You can refer to our [Flatpak guide][11] for help. - -In either case, you can refer to its [GitLab page][12] and compile it yourself. - -### Closing Thoughts - -I’m currently using it by moving away from web-based services as a local solution on my desktop. You can simply export the OPML file to get the same feeds on any of your mobile feed applications, that’s what I’ve done. - -The user interface is easy to use and provides a modern UX, if not the best. You can find all the essential features available while being a simple-looking RSS reader as well. - -What do you think about NewsFlash? Do you prefer using something else? Feel free to share your thoughts in the comments. - --------------------------------------------------------------------------------- - -via: https://itsfoss.com/newsflash-feedreader/ - -作者:[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://feedly.com/ -[2]: https://jangernert.github.io/FeedReader/ -[3]: https://itsfoss.com/feed-reader-apps-linux/ -[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash.jpg?resize=945%2C648&ssl=1 -[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash-screenshot.jpg?resize=800%2C533&ssl=1 -[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/03/newsflash-screenshot-1.jpg?resize=800%2C532&ssl=1 -[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/04/best-feed-reader-apps-linux.jpg?fit=800%2C450&ssl=1 -[8]: https://flathub.org/apps/details/com.gitlab.newsflash -[9]: https://itsfoss.com/aur-arch-linux/ -[10]: https://itsfoss.com/what-is-flatpak/ -[11]: https://itsfoss.com/flatpak-guide/ -[12]: https://gitlab.com/news-flash/news_flash_gtk diff --git a/sources/tech/20210401 Find what changed in a Git commit.md b/sources/tech/20210401 Find what changed in a Git commit.md new file mode 100644 index 0000000000..19b5308d88 --- /dev/null +++ b/sources/tech/20210401 Find what changed in a Git commit.md @@ -0,0 +1,136 @@ +[#]: subject: (Find what changed in a Git commit) +[#]: via: (https://opensource.com/article/21/4/git-whatchanged) +[#]: author: (Seth Kenlon https://opensource.com/users/seth) +[#]: collector: (lujun9972) +[#]: translator: (DCOLIVERSUN) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +Find what changed in a Git commit +====== +Git offers several ways you can quickly see which files changed in a +commit. +![Code going into a computer.][1] + +If you use Git every day, you probably make a lot of commits. If you're using Git every day in a project with other people, it's safe to assume that _everyone_ is making lots of commits. Every day. And this means you're aware of how disorienting a Git log can become, with a seemingly eternal scroll of changes and no sign of what's been changed. + +So how do you find out what file changed in a specific commit? It's easier than you think. + +### Find what file changed in a commit + +To find out which files changed in a given commit, use the `git log --raw` command. It's the fastest and simplest way to get insight into which files a commit affects. The `git log` command is underutilized in general, largely because it has so many formatting options, and many users get overwhelmed by too many choices and, in some cases, unclear documentation. + +The log mechanism in Git is surprisingly flexible, though, and the `--raw` option provides a log of commits in your current branch, plus a list of each file that had changes made to it. + +Here's the output of a standard `git log`: + + +``` +$ git log +commit fbbbe083aed75b24f2c77b1825ecab10def0953c (HEAD -> dev, origin/dev) +Author: tux <[tux@example.com][2]> +Date:   Sun Nov 5 21:40:37 2020 +1300 + +    exit immediately from failed download + +commit 094f9948cd995acfc331a6965032ea0d38e01f03 (origin/master, master) +Author: Tux <[tux@example.com][2]> +Date:   Fri Aug 5 02:05:19 2020 +1200 + +    export makeopts from etc/example.conf + +commit 76b7b46dc53ec13316abb49cc7b37914215acd47 +Author: Tux <[tux@example.com][2]> +Date:   Sun Jul 31 21:45:24 2020 +1200 + +    fix typo in help message +``` + +Even when the author helpfully specifies in the commit message which files changed, the log is fairly terse. + +Here's the output of `git log --raw`: + + +``` +$ git log --raw +commit fbbbe083aed75b24f2c77b1825ecab10def0953c (HEAD -> dev, origin/dev) +Author: tux <[tux@example.com][2]> +Date:   Sun Nov 5 21:40:37 2020 +1300 + +    exit immediately from failed download + +:100755 100755 cbcf1f3 4cac92f M        src/example.lua + +commit 094f9948cd995acfc331a6965032ea0d38e01f03 (origin/master, master) +Author: Tux <[tux@example.com][2]> +Date:   Fri Aug 5 02:05:19 2020 +1200 + +    export makeopts from etc/example.conf +    +:100755 100755 4c815c0 cbcf1f3 M     src/example.lua +:100755 100755 71653e1 8f5d5a6 M     src/example.spec +:100644 100644 9d21a6f e33caba R100  etc/example.conf  etc/example.conf-default + +commit 76b7b46dc53ec13316abb49cc7b37914215acd47 +Author: Tux <[tux@example.com][2]> +Date:   Sun Jul 31 21:45:24 2020 +1200 + +    fix typo in help message + +:100755 100755 e253aaf 4c815c0 M        src/example.lua +``` + +This tells you exactly which file was added to the commit and how the file was changed (`A` for added, `M` for modified, `R` for renamed, and `D` for deleted). + +### Git whatchanged + +The `git whatchanged` command is a legacy command that predates the log function. Its documentation says you're not meant to use it in favor of `git log --raw` and implies it's essentially deprecated. However, I still find it a useful shortcut to (mostly) the same output (although merge commits are excluded), and I anticipate creating an alias for it should it ever be removed. If you don't need to merge commits in your log (and you probably don't, if you're only looking to see files that changed), try `git whatchanged` as an easy mnemonic. + +### View changes + +Not only can you see which files changed, but you can also make `git log` display exactly what changed in the files. Your Git log can produce an inline diff, a line-by-line display of all changes for each file, with the `--patch` option: + + +``` +commit 62a2daf8411eccbec0af69e4736a0fcf0a469ab1 (HEAD -> master) +Author: Tux <[Tux@example.com][3]> +Date:   Wed Mar 10 06:46:58 2021 +1300 + +    commit + +diff --git a/hello.txt b/hello.txt +index 65a56c3..36a0a7d 100644 +\--- a/hello.txt ++++ b/hello.txt +@@ -1,2 +1,2 @@ + Hello +-world ++opensource.com +``` + +In this example, the one-word line "world" was removed from `hello.txt` and the new line "opensource.com" was added. + +These patches can be used with common Unix utilities like [diff and patch][4], should you need to make the same changes manually elsewhere. The patches are also a good way to summarize the important parts of what new information a specific commit introduces. This is an invaluable overview when you've introduced a bug during a sprint. To find the cause of the error faster, you can ignore the parts of a file that didn't change and review just the new code. + +### Simple commands for complex results + +You don't have to understand refs and branches and commit hashes to view what files changed in a commit. Your Git log was designed to report Git activity to you, and if you want to format it in a specific way or extract specific information, it's often a matter of wading through many screens of documentation to put together the right command. Luckily, one of the most common requests about Git history is available with just one or two options: `--raw` and `--patch`. And if you can't remember `--raw`, just think, "Git, what changed?" and type `git whatchanged`. + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/4/git-whatchanged + +作者:[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/code_computer_development_programming.png?itok=4OM29-82 (Code going into a computer.) +[2]: mailto:tux@example.com +[3]: mailto:Tux@example.com +[4]: https://opensource.com/article/18/8/diffs-patches diff --git a/sources/tech/20210401 Partition a drive on Linux with GNU Parted.md b/sources/tech/20210401 Partition a drive on Linux with GNU Parted.md new file mode 100644 index 0000000000..64d5afb8f7 --- /dev/null +++ b/sources/tech/20210401 Partition a drive on Linux with GNU Parted.md @@ -0,0 +1,194 @@ +[#]: subject: (Partition a drive on Linux with GNU Parted) +[#]: via: (https://opensource.com/article/21/4/linux-parted-cheat-sheet) +[#]: author: (Seth Kenlon https://opensource.com/users/seth) +[#]: collector: (lujun9972) +[#]: translator: ( ) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +Partition a drive on Linux with GNU Parted +====== +Learn the basics of partitioning a new storage device, then download our +cheat sheet to keep info close at hand. +![Cheat Sheet cover image][1] + +In the 21st century, we tend to take data storage for granted. We have lots of it, it's relatively affordable, and there are many different types of storage available. No matter how much cloud storage space you're given for free, there's nothing quite like having a physical hard drive for your really important (or really big, when you live on a slow network) data. However, few hard drives are sold right off the shelf, ready to use—in an ideal configuration, at least. Whether you're buying a new drive or setting up a system with a different configuration, you need to know how to partition a drive on Linux. + +This article demonstrates GNU Parted, one of the best tools for partitioning drives. If you prefer to use a graphical application instead of a terminal command, read my article on [formatting drives for Linux][2]. + +### Disk labels, partitions, and filesystems + +A hard drive doesn't _technically_ require much software to serve as a storage device. However, using a drive without modern conventions like a partition table and filesystem is difficult, impractical, and unsafe for your data. + +There are three important concepts you need to know about hard drives: + + * A **disk label** or **partition table** is metadata placed at the start of a drive, serving as a clue for the computer reading it about what kind of storage is available and where it's located on the drive. + * A **partition** is a boundary identifying where a filesystem is located. For instance, if you have a 512GB drive, you can have a partition on that device that takes up the entire drive (512GB), or two partitions that each take 256GB each, or three partitions taking up some other variation of sizes, and so on. + * A **filesystem** is a storage scheme agreed upon by a hard drive and a computer. A computer must know how to read a filesystem to piece together all the data stored on the drive, and it must know how to write data back to the filesystem to maintain the data's integrity. + + + +The GNU Parted application manages the first two concepts: disk labels and partitions. Parted has some awareness of filesystems, but it leaves the details of filesystem implementation to other tools like `mkfs`. + +**[Download the [GNU Parted cheat sheet][3]]** + +### Locating the drive + +Before using GNU Parted, you must be certain where your drive is located on your system. First, attach the hard drive you want to format to your system, and then use the `parted` command to see what's attached to your computer: + + +``` +$ parted /dev/sda print devices +/dev/sda (2000GB) +/dev/sdb (1000GB) +/dev/sdc (1940MB) +``` + +The device you most recently attached gets a name later in the alphabet than devices that have been attached longer. In this example, `/dev/sdc` is most likely the drive I just attached. I can confirm that by its size because I know that the USB thumb drive I attached is only 2GB (1940MB is close enough), compared to my workstation's main drives, which are terabytes in size. If you're not sure, then you can get more information about the drive you think is the one you want to partition: + + +``` +$ parted /dev/sdc print +Model: Yoyodyne Tiny Drive 1.0 (scsi)     +Disk /dev/sdc: 1940MB +Sector size (logical/physical): 512B/512B +Partition Table: msdos +Disk Flags: + +Number  Start   End     Size    File system  Name  Flags + 1      1049kB  2048kB  1024kB  BS           Bloat  Hidden + 2      2049kB  1939MB  1937MB  FAT32        MyDrive +``` + +Some drives provide more metadata than others. This one identifies itself as a drive from Yoyodyne, which is exactly the branding on the physical drive. Furthermore, it contains a small hidden partition at the front of the drive with some bloatware followed by a Windows-compatible FAT32 partition. This is definitely the drive I intend to reformat. + +Before continuing, _make sure_ you have identified the correct drive you want to partition. _Repartitioning the wrong drive results in lost data._ For safety, all potentially destructive commands in this article reference the `/dev/sdX` device, which you are unlikely to have on your system. + +### Creating a disk label or partition table + +To create a partition on a drive, the drive must have a disk label. A disk label is also called a _partition table_, so Parted accepts either term. + +To create a disk label, use the `mklabel` or `mktable` subcommand: + + +``` +`$ parted /dev/sdX mklabel gpt` +``` + +This command creates a **gpt** label at the front of the drive located at `/dev/sdX`, erasing any label that may exist. This is a quick process because all that's being replaced is metadata about partitions. + +### Creating a partition + +To create a partition on a drive, use the `mkpart` subcommand, followed by an optional name for your partition, followed by the partition's start and end points. If you only need one partition on your drive, then sizing is easy: start at 1 and end at 100%. Use the `--align opt` option to allow Parted to adjust the position of the partition boundaries for best performance: + + +``` +$ parted /dev/sdX --align opt \ +mkpart example 1 100% +``` + +View your new partition with the `print` subcommand: + + +``` +$ parted /dev/sdX print +Model: Yoyodyne Tiny Drive 1.0 (scsi) +Disk /dev/sdi: 1940MB +Sector size (logical/physical): 512B/512B +Partition Table: gpt +Disk Flags: + +Number  Start   End     Size   + 1      1049kB  1939MB  1938MB +``` + +You don't have to use the whole disk for one partition. The advantage to a partition is that more than one filesystem can exist on a drive without interfering with the other partition(s). When sizing partitions, you can use the `unit` subcommand to set what kind of measurements you want to use. Parted understands sectors, cylinders, heads, bytes, kilobytes, megabytes, gigabytes, terabytes, and percentages. + +You can also specify what filesystem you intend to use a partition for. This doesn't create the filesystem, but it does provide metadata that could be useful to you later. + +Here's a 50-50 split, one for an XFS filesystem and another for an EXT4 filesystem: + + +``` +$ parted /dev/sdX --align opt \ +mkpart xfs 1 50% +$ parted /dev/sdX --align opt \ +mkpart ext4 51% 100% +``` + +### Naming a partition + +In addition to marking what filesystem a partition is for, you can also name each partition. Some file managers and utilities read partition names, which can help you identify drives. For instance, I often have several different drives attached on my media workstation, each belonging to a different project. When creating these drives, I name both the partition and the filesystem so that, no matter how I'm looking at my system, the locations with important data are clearly labeled. + +To name a partition, you must know its number: + + +``` +$ parted /dev/sdX print +[...] +Number  Start   End     Size   File system  Name     Flags + 1      1049kB  990MB   989MB  xfs          example + 2      1009MB  1939MB  930MB  ext4         noname +``` + +To name partition 1: + + +``` +$ parted /dev/sdX name 1 example +$ parted /dev/sdX print +[...] +Number  Start   End     Size   File system  Name     Flags + 1      1049kB  990MB   989MB  xfs          example + 2      1009MB  1939MB  930MB  ext4         noname +``` + +### Create a filesystem + +For your drive to be useful, you must create a filesystem in your new partition. GNU Parted doesn't do that because it's only a partition manager. The Linux command to create a filesystem on a drive is `mkfs`, but there are helpful utilities aliased for you to use to create a specific kind of filesystem. For instance, `mkfs.ext4` creates an EXT4 filesystem, while `mkfs.xfs` creates an XFS filesystem, and so on. + +Your partition is located "in" the drive, so instead of creating a filesystem on `/dev/sdX`, you create your filesystem in `/dev/sdX1` for the first partition, `/dev/sdX2` for the second partition, and so on. + +Here's an example of creating an XFS filesystem: + + +``` +`$ sudo mkfs.xfs -L mydrive /dev/sdX1` +``` + +### Download our cheat sheet + +Parted is a flexible and powerful command. You can issue it commands, as demonstrated in this article, or activate an interactive mode so that you're constantly "connected" to a drive you specify: + + +``` +$ parted /dev/sdX +(parted) print +[...] +Number  Start   End     Size   File system  Name     Flags + 1      1049kB  990MB   989MB  xfs          example + 2      1009MB  1939MB  930MB  ext4         noname + +(parted) name 1 mydrive +(parted) +``` + +If you intend to use Parted often, [download our GNU Parted cheat sheet][3] so that you have all the subcommands you need close at hand. + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/4/linux-parted-cheat-sheet + +作者:[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/coverimage_cheat_sheet.png?itok=lYkNKieP (Cheat Sheet cover image) +[2]: https://opensource.com/article/18/11/partition-format-drive-linux#gui +[3]: https://opensource.com/downloads/parted-cheat-sheet diff --git a/sources/tech/20210401 Use awk to calculate letter frequency.md b/sources/tech/20210401 Use awk to calculate letter frequency.md new file mode 100644 index 0000000000..afc6449ff1 --- /dev/null +++ b/sources/tech/20210401 Use awk to calculate letter frequency.md @@ -0,0 +1,286 @@ +[#]: 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 <= 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 <= 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 <= len; i++) { +        c = substr($0, i, 1); +        ltr = index(LETTERS, c); +  +        if (ltr > 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 <= 26; ltr++) { +        if (count[ltr] < 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 <= 26; ltr++) { +        if (count[ltr] < min) { +            min = count[ltr]; +        } +    } +  +    for (ltr = 1; ltr <= 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 <= len; i++) { +        c = substr($0, i, 1); +        ltr = index(LETTERS, c); +  +        if (ltr > 0) { +            ++count[ltr]; +        } +    } +} +  +# print relative frequency of each letter +    +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); +    } +} +``` + +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 diff --git a/sources/tech/20210401 Wrong Time Displayed in Windows-Linux Dual Boot Setup- Here-s How to Fix it.md b/sources/tech/20210401 Wrong Time Displayed in Windows-Linux Dual Boot Setup- Here-s How to Fix it.md index d1e626b69a..fd32676c3b 100644 --- a/sources/tech/20210401 Wrong Time Displayed in Windows-Linux Dual Boot Setup- Here-s How to Fix it.md +++ b/sources/tech/20210401 Wrong Time Displayed in Windows-Linux Dual Boot Setup- Here-s How to Fix it.md @@ -2,7 +2,7 @@ [#]: via: (https://itsfoss.com/wrong-time-dual-boot/) [#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/) [#]: collector: (lujun9972) -[#]: translator: ( ) +[#]: translator: (geekpi) [#]: reviewer: ( ) [#]: publisher: ( ) [#]: url: ( ) diff --git a/sources/tech/20210402 20 ways to be more productive and respect yourself.md b/sources/tech/20210402 20 ways to be more productive and respect yourself.md new file mode 100644 index 0000000000..58b66e1e88 --- /dev/null +++ b/sources/tech/20210402 20 ways to be more productive and respect yourself.md @@ -0,0 +1,104 @@ +[#]: subject: (20 ways to be more productive and respect yourself) +[#]: via: (https://opensource.com/article/21/4/productivity-roundup) +[#]: author: (Jen Wike Huger https://opensource.com/users/jen-wike) +[#]: collector: (lujun9972) +[#]: translator: ( ) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +20 ways to be more productive and respect yourself +====== +Open source tools and more efficient processes can give you an edge over +your to-do list. +![Kanban-style organization action][1] + +The need to be productive is ingrained in who we are as human beings on some level. We oftentimes have to do yoga and meditate and breathe deeply in order to consciously slow down our minds and bodies, but when we do it helps us focus and be more productive when the time comes. Instead of constantly moving and doing, we should take periods of thoughtful breaks... or veg out in front of the TV or a sunset. And sleep at night! Then, when we're ready again, we can tackle that to-do list. Rinse and repeat. + +Honoring this cycle of moving through active and restful states, our productivity series this year brought to us by author [Kevin Sonney][2] showcases open source tools and more efficient processes while paying attention to healthy practices for incorporating them and respecting the person doing the implementing, you. + +### Tools and technology + +The software, the apps, and the programs... they are the tools we wield when we're ready to sit down and get stuff done. Here are nine open source tools you should know. + + * [Improve your productivity with this lightweight Linux desktop][3] + * [3 plain text note-taking tools][4] + * [How to use KDE's productivity suite, Kontact][5] + * [How Nextcloud is the ultimate open source productivity suite][6] + * [Schedule appointments with an open source alternative to Doodle][7] + * [Use Joplin to find your notes faster][8] + * [Use your Raspberry Pi as a productivity powerhouse][9] + + + +### Processes and practices + +#### Email + +Despite the criticism, is email still a favorite way for you to get stuff done? Improve on this process even more with these tips: + + * [3 email rules to live by in 2021][10] + * [3 steps to achieving Inbox Zero][11] + * [Organize your task list using labels][12] + * [3 tips for automating your email filters][13] + * [3 email mistakes and how to avoid them][14] + + + +#### Calendars + +We often need to work with others and ask important questions to get work done and tasks completed, so scheduling meetings is an important part of being productive. + + * [Gain control of your calendar with this simple strategy][15] + + + +#### Mind games + +Preparing and caring for our mental state while we work is critical to being productive. Kevin shows us how to prioritize, reflect, take care, reduce stress, rest, and focus.   + + * [How I prioritize tasks on my to-do list][16] + * [Tips for incorporating self-care into your daily routine][17] + * [Why keeping a journal improves productivity][18] + * [3 stress-free steps to tackling your task list][19] + * [4 tips for preventing notification fatigue][20] + * [Open source tools and tips for staying focused][21] + * [How I de-clutter my digital workspace][22] + + + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/4/productivity-roundup + +作者:[Jen Wike Huger][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/jen-wike +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/kanban_trello_organize_teams_520.png?itok=ObNjCpxt (Kanban-style organization action) +[2]: https://opensource.com/users/ksonney +[3]: https://opensource.com/article/21/1/elementary-linux +[4]: https://opensource.com/article/21/1/plain-text +[5]: https://opensource.com/article/21/1/kde-kontact +[6]: https://opensource.com/article/21/1/nextcloud-productivity +[7]: https://opensource.com/article/21/1/open-source-scheduler +[8]: https://opensource.com/article/21/1/notes-joplin +[9]: https://opensource.com/article/21/1/raspberry-pi-productivity +[10]: https://opensource.com/article/21/1/email-rules +[11]: https://opensource.com/article/21/1/inbox-zero +[12]: https://opensource.com/article/21/1/labels +[13]: https://opensource.com/article/21/1/email-filter +[14]: https://opensource.com/article/21/1/email-mistakes +[15]: https://opensource.com/article/21/1/calendar-time-boxing +[16]: https://opensource.com/article/21/1/prioritize-tasks +[17]: https://opensource.com/article/21/1/self-care +[18]: https://opensource.com/article/21/1/open-source-journal +[19]: https://opensource.com/article/21/1/break-down-tasks +[20]: https://opensource.com/article/21/1/alert-fatigue +[21]: https://opensource.com/article/21/1/stay-focused +[22]: https://opensource.com/article/21/1/declutter-workspace diff --git a/sources/tech/20210402 A practical guide to using the git stash command.md b/sources/tech/20210402 A practical guide to using the git stash command.md new file mode 100644 index 0000000000..804a6bac81 --- /dev/null +++ b/sources/tech/20210402 A practical guide to using the git stash command.md @@ -0,0 +1,240 @@ +[#]: subject: (A practical guide to using the git stash command) +[#]: via: (https://opensource.com/article/21/4/git-stash) +[#]: author: (Ramakrishna Pattnaik https://opensource.com/users/rkpattnaik780) +[#]: collector: (lujun9972) +[#]: translator: ( ) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +A practical guide to using the git stash command +====== +Learn how to use the git stash command and when you should use it. +![woman on laptop sitting at the window][1] + +Version control is an inseparable part of software developers' daily lives. It's hard to imagine any team developing software without using a version control tool. It's equally difficult to envision any developer who hasn't worked with (or at least heard of) Git. In the 2018 Stackoverflow Developer Survey, 87.2% of the 74,298 participants [use Git][2] for version control. + +Linus Torvalds created git in 2005 for developing the Linux kernel. This article walks through the `git stash` command and explores some useful options for stashing changes. It assumes you have basic familiarity with [Git concepts][3] and a good understanding of the working tree, staging area, and associated commands. + +### Why is git stash important? + +The first thing to understand is why stashing changes in Git is important. Assume for a moment that Git doesn't have a command to stash changes. Suppose you are working on a repository with two branches, A and B. The A and B branches have diverged from each other for quite some time and have different heads. While working on some files in branch A, your team asks you to fix a bug in branch B. You quickly save your changes to A and try to check out branch B with `git checkout B`. Git immediately aborts the operation and throws the error, "Your local changes to the following files would be overwritten by checkout … Please commit your changes or stash them before you switch branches." + +There are few ways to enable branch switching in this case: + + * Create a commit at that point in branch A, commit and push your changes to fix the bug in B, then check out A again and run `git reset HEAD^` to get your changes back. + * Manually keep the changes in files not tracked by Git. + + + +The second method is a bad idea. The first method, although appearing conventional, is less flexible because the unfinished saved changes are treated as a checkpoint rather than a patch that's still a work in progress. This is exactly the kind of scenario git stash is designed for. + +Git stash saves the uncommitted changes locally, allowing you to make changes, switch branches, and perform other Git operations. You can then reapply the stashed changes when you need them. A stash is locally scoped and is not pushed to the remote by `git push`. + +### How to use git stash + +Here's the sequence to follow when using git stash: + + 1. Save changes to branch A. + 2. Run `git stash`. + 3. Check out branch B. + 4. Fix the bug in branch B. + 5. Commit and (optionally) push to remote. + 6. Check out branch A + 7. Run `git stash pop` to get your stashed changes back. + + + +Git stash stores the changes you made to the working directory locally (inside your project's .git directory; `/.git/refs/stash`, to be precise) and allows you to retrieve the changes when you need them. It's handy when you need to switch between contexts. It allows you to save changes that you might need at a later stage and is the fastest way to get your working directory clean while keeping changes intact. + +### How to create a stash + +The simplest command to stash your changes is `git stash`: + + +``` +$ git stash +Saved working directory and index state WIP on master; d7435644 Feat: configure graphql endpoint +``` + +By default, `git stash` stores (or "stashes") the uncommitted changes (staged and unstaged files) and overlooks untracked and ignored files. Usually, you don't need to stash untracked and ignored files, but sometimes they might interfere with other things you want to do in your codebase. + +You can use additional options to let `git stash` take care of untracked and ignored files: + + * `git stash -u` or `git stash --include-untracked` stash untracked files. + * `git stash -a` or `git stash --all` stash untracked files and ignored files. + + + +To stash specific files, you can use the command `git stash -p` or `git stash –patch`: + + +``` +$ git stash --patch +diff --git a/.gitignore b/.gitignore +index 32174593..8d81be6e 100644 +\--- a/.gitignore ++++ b/.gitignore +@@ -3,6 +3,7 @@ + # dependencies + node_modules/ + /.pnp ++f,fmfm + .pnp.js + + # testing +(1/1) Stash this hunk [y,n,q,a,d,e,?]? +``` + +### Listing your stashes + +You can view your stashes with the command `git stash list`. Stashes are saved in a last-in-first-out (LIFO) approach: + + +``` +$ git stash list +stash@{0}: WIP on master: d7435644 Feat: configure graphql endpoint +``` + +By default, stashes are marked as WIP on top of the branch and commit that you created the stash from. However, this limited amount of information isn't helpful when you have multiple stashes, as it becomes difficult to remember or individually check their contents. To add a description to the stash, you can use the command `git stash save `: + + +``` +$ git stash save "remove semi-colon from schema" +Saved working directory and index state On master: remove semi-colon from schema + +$ git stash list +stash@{0}: On master: remove semi-colon from schema +stash@{1}: WIP on master: d7435644 Feat: configure graphql endpoint +``` + +### Retrieving stashed changes + +You can reapply stashed changes with the commands `git stash apply` and `git stash pop`. Both commands reapply the changes stashed in the latest stash (that is, `stash@{0}`). A `stash` reapplies the changes while `pop` removes the changes from the stash and reapplies them to the working copy. Popping is preferred if you don't need the stashed changes to be reapplied more than once. + +You can choose which stash you want to pop or apply by passing the identifier as the last argument: + + +``` +`$ git stash pop stash@{1}` +``` + +or + + +``` +`$ git stash apply stash@{1}` +``` + +### Cleaning up the stash + +It is good practice to remove stashes that are no longer needed. You must do this manually with the following commands: + + * `git stash clear` empties the stash list by removing all the stashes. + * `git stash drop ` deletes a particular stash from the stash list. + + + +### Checking stash diffs + +The command `git stash show ` allows you to view the diff of a stash: + + +``` +$ git stash show stash@{1} +console/console-init/ui/.graphqlrc.yml        |   4 +- +console/console-init/ui/generated-frontend.ts | 742 +++++++++--------- +console/console-init/ui/package.json          |   2 +- +``` + +To get a more detailed diff, pass the `--patch` or `-p` flag: + + +``` +$ git stash show stash@{0} --patch +diff --git a/console/console-init/ui/package.json b/console/console-init/ui/package.json +index 755912b97..5b5af1bd6 100644 +\--- a/console/console-init/ui/package.json ++++ b/console/console-init/ui/package.json +@@ -1,5 +1,5 @@ + { +\- "name": "my-usepatternfly", +\+ "name": "my-usepatternfly-2", +  "version": "0.1.0", +  "private": true, +  "proxy": "" +diff --git a/console/console-init/ui/src/AppNavHeader.tsx b/console/console-init/ui/src/AppNavHeader.tsx +index a4764d2f3..da72b7e2b 100644 +\--- a/console/console-init/ui/src/AppNavHeader.tsx ++++ b/console/console-init/ui/src/AppNavHeader.tsx +@@ -9,8 +9,8 @@ import { css } from "@patternfly/react-styles"; + +interface IAppNavHeaderProps extends PageHeaderProps { +\- toolbar?: React.ReactNode; +\- avatar?: React.ReactNode; +\+ toolbar?: React.ReactNode; +\+ avatar?: React.ReactNode; +} + +export class AppNavHeader extends React.Component<IAppNavHeaderProps>{ +  render() +``` + +### Checking out to a new branch + +You might come across a situation where the changes in a branch and your stash diverge, causing a conflict when you attempt to reapply the stash. A clean fix for this is to use the command `git stash branch `, which creates a new branch based on the commit the stash was created _from_ and pops the stashed changes to it: + + +``` +$ git stash branch test_2 stash@{0} +Switched to a new branch 'test_2' +On branch test_2 +Changes not staged for commit: +(use "git add <file>..." to update what will be committed) +(use "git restore <file>..." to discard changes in working directory) +modified: .graphqlrc.yml +modified: generated-frontend.ts +modified: package.json +no changes added to commit (use "git add" and/or "git commit -a") +Dropped stash@{0} (fe4bf8f79175b8fbd3df3c4558249834ecb75cd1) +``` + +### Stashing without disturbing the stash reflog + +In rare cases, you might need to create a stash while keeping the stash reference log (reflog) intact. These cases might arise when you need a script to stash as an implementation detail. This is achieved by the `git stash create` command; it creates a stash entry and returns its object name without pushing it to the stash reflog: + + +``` +$ git stash create "sample stash" +63a711cd3c7f8047662007490723e26ae9d4acf9 +``` + +Sometimes, you might decide to push the stash entry created via `git stash create` to the stash reflog: + + +``` +$ git stash store -m "sample stash testing.." "63a711cd3c7f8047662007490723e26ae9d4acf9" +$ git stash list +stash @{0}: sample stash testing.. +``` + +### Conclusion + +I hope you found this article useful and learned something new. If I missed any useful options for using stash, please let me know in the comments. + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/4/git-stash + +作者:[Ramakrishna Pattnaik][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/rkpattnaik780 +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop) +[2]: https://insights.stackoverflow.com/survey/2018#work-_-version-control +[3]: https://opensource.com/downloads/cheat-sheet-git diff --git a/sources/tech/20210402 Read and write files with Groovy.md b/sources/tech/20210402 Read and write files with Groovy.md new file mode 100644 index 0000000000..091c3c9c40 --- /dev/null +++ b/sources/tech/20210402 Read and write files with Groovy.md @@ -0,0 +1,181 @@ +[#]: subject: (Read and write files with Groovy) +[#]: via: (https://opensource.com/article/21/4/groovy-io) +[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen) +[#]: collector: (lujun9972) +[#]: translator: ( ) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +Read and write files with Groovy +====== +Learn how the Groovy programming language handles reading from and +writing to files. +![Woman programming][1] + +Two common tasks that new programmers need to learn are how to read from and write to files stored on a computer. Some examples are when data and configuration files created in one application need to be read by another application, or when a third application needs to write info, warnings, and errors to a log file or to save its results for someone else to use. + +Every language has a few different ways to read from and write to files. This article covers some of these details in the [Groovy programming language][2], which is based on Java but with a different set of priorities that make Groovy feel more like Python. The first thing a new-to-Groovy programmer sees is that it is much less verbose than Java. The next observation is that it is (by default) dynamically typed. The third is that Groovy has closures, which are somewhat like lambdas in Java but provide access to the entire enclosing context (Java lambdas restrict what can be accessed). + +My fellow correspondent Seth Kenlon has written about [Java input and output (I/O)][3]. I'll jump off from his Java code to show you how it's done in Groovy. + +### Install Groovy + +Since Groovy is based on Java, it requires a Java installation. You may be able to find a recent and decent version of Java and Groovy in your Linux distribution's repositories. Or you can install Groovy by following the instructions on [Groovy's download page][4]. 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, I'm using my distro's OpenJDK11 release and SDKMan's Groovy 3.0.7 release. + +### Read a file with Groovy + +Start by reviewing Seth's Java program for reading files: + + +``` +import java.io.File; +import java.util.Scanner; +import java.io.FileNotFoundException; + +public class Ingest { +  public static void main([String][6][] args) { + +      try { +          [File][7] myFile = new [File][7]("example.txt"); +          Scanner myScanner = new Scanner(myFile); +          while (myScanner.hasNextLine()) { +              [String][6] line = myScanner.nextLine(); +              [System][8].out.println(line); +          } +          myScanner.close(); +      } catch ([FileNotFoundException][9] ex) { +          ex.printStackTrace(); +      } //try +    } //main +} //class +``` + +Now I'll do the same thing in Groovy: + + +``` +def myFile = new [File][7]('example.txt') +def myScanner = new Scanner(myFile) +while (myScanner.hasNextLine()) { +        def line = myScanner.nextLine() +        println(line) +} +myScanner.close() +``` + +Groovy looks like Java but less verbose. The first thing to notice is that all those `import` statements are already done in the background. And since Groovy is partly intended to be a scripting language, by omitting the definition of the surrounding `class` and `public static void main`, Groovy will construct those things in the background. + +The semicolons are also gone. Groovy supports their use but doesn't require them except in cases like when you want to put multiple statements on the same line. Aaaaaaaaand the single quotes—Groovy supports either single or double quotes for delineating strings, which is handy when you need to put double quotes inside a string, like this: + + +``` +`'"I like this Groovy stuff", he muttered to himself.'` +``` + +Note also that `try...catch` is gone. Groovy supports `try...catch` but doesn't require it, and it will give a perfectly good error message and stack trace just like the `ex.printStackTrace()` call does in the Java example. + +Groovy adopted the `def` keyword and inference of type from the right-hand side of a statement long before Java came up with the `var` keyword, and Groovy allows it everywhere. Aside from using `def`, though, the code that does the main work looks quite similar to the Java version. Oh yeah, except that Groovy also has this nice metaprogramming ability built in, which among other things, lets you write `println()` instead of `System.out.println()`. This similarity is way more than skin deep and allows Java programmers to get traction with Groovy very quickly. + +And just like Python programmers are always looking for the pythonic way to do stuff, there is Groovy that looks like Java, and then there is… groovier Groovy. This solves the same problem but uses Groovy's `with` method to make the code more DRY ("don't repeat yourself") and to automate closing the input file: + + +``` +new Scanner(new [File][7]('example.txt')).with { +    while (hasNextLine()) { +      def line = nextLine() +      println(line) +    } +} +``` + +What's between `.with {` and `}` is a closure body. Notice that you don't need to write `myScanner.hasNextLine()` nor `myScanner.nextLine()` as `with` exposes those methods directly to the closure body.  Also the with gets rid of the need to code myScanner.close() and so we don't actually need to declare myScanner at all. + +Run it: + + +``` +$ groovy ingest1.groovy +Caught: java.io.[FileNotFoundException][9]: example.txt (No such file or directory) +java.io.[FileNotFoundException][9]: example.txt (No such file or directory) +        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native [Method][10]) +        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) +        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) +        at ingest1.run(ingest1.groovy:1) +        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native [Method][10]) +        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) +        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) +$ +``` + +Note the "file not found" exception; this is because there isn't a file called `example.txt` yet. Note also that the files are from things like `java.io`. + +So I'll write something into that file… + +### Write data to a file with Groovy + +Combining what I shared previously about, well, being "groovy": + + +``` +new [FileWriter][11]("example.txt", true).with { +        write("Hello world\n") +        flush() +} +``` + +Remember that `true` after the file name means "append to the file," so you can run this a few times: + + +``` +$ groovy exgest.groovy +$ groovy exgest.groovy +$ groovy exgest.groovy +$ groovy exgest.groovy +``` + +Then you can read the results with `ingest1.groovy`: + + +``` +$ groovy ingest1.groovy +Hello world +Hello world +Hello world +Hello world +$ +``` + +The call to `flush()` is used because the `with` / `write` combo didn't do a flush before close. Groovy isn't always shorter! + +### Groovy resources + +The Apache Groovy site has a lot of great [documentation][12]. Another great Groovy resource is [Mr. Haki][13]. And a really great reason to learn Groovy is to learn [Grails][14], 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/21/4/groovy-io + +作者:[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/programming-code-keyboard-laptop-music-headphones.png?itok=EQZ2WKzy (Woman programming) +[2]: https://groovy-lang.org/ +[3]: https://opensource.com/article/21/3/io-java +[4]: https://groovy.apache.org/download.html +[5]: https://sdkman.io/ +[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string +[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+system +[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+filenotfoundexception +[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+method +[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+filewriter +[12]: https://groovy-lang.org/documentation.html +[13]: https://blog.mrhaki.com/ +[14]: https://grails.org/ diff --git a/translated/tech/20190319 How to set up a homelab from hardware to firewall.md b/translated/tech/20190319 How to set up a homelab from hardware to firewall.md deleted file mode 100644 index 4b3e4de26e..0000000000 --- a/translated/tech/20190319 How to set up a homelab from hardware to firewall.md +++ /dev/null @@ -1,111 +0,0 @@ -[#]: collector: (lujun9972) -[#]: translator: (wyxplus) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) -[#]: subject: (How to set up a homelab from hardware to firewall) -[#]: via: (https://opensource.com/article/19/3/home-lab) -[#]: author: (Michael Zamot https://opensource.com/users/mzamot) - -如何从硬件到防火墙建立一个家庭实验室 -====== - -查看用于构建自己的家庭实验室的硬件和软件方案。 - -![][1] - -你有想过创建一个家庭实验室吗?或许你想尝试不同的技术,构建开发环境、亦或是建立自己的私有云。对于拥有一个家庭实验室有很多理由,本教程旨在使入门变得更容易。 - -规划家庭实验室时,需要考虑三方面:硬件、软件和维护。我们将在这里查看前两方面,并在以后的文章中讲述如何节省维护计算机实验室的时间。 - -### 硬件 - - -在考虑硬件需求时,首先要考虑如何使用实验室以及你的预算,噪声,空间和电源使用情况。 - - -如果购买新硬件过于昂贵,请搜索当地的大学,广告以及诸如 eBay 或 Craigslist 之类的网站,能获取二手服务器的地方。它们通常很便宜,并且服务器级的硬件可以使用很多年。你将需要三类硬件:虚拟化服务器,存储设备和路由器/防火墙。 - -#### 虚拟化服务器 - -一个虚拟化服务器允许你去运行多个共享物理机资源的虚拟机,同时最大化利用和隔离资源。如果你打算销毁一台虚拟机,无需重建整个服务器,因为其仅是一个虚拟机。如果你想进行测试或尝试某些操作而不损坏整个系统,仅需要新建一个虚拟机来运行即可。 - -在虚拟服务器中,需考虑两个最重要的因素是 CPU 的核心数及其运行速度以及内存容量。如果没有足够的资源够全部虚拟机共享,那么它们将被重复分配并试着获取其他虚拟机的 CPU 的周期和内存。 - -因此,考虑一个多核 CPU 的平台。你要确保 CPU 支持虚拟化指令(因特尔的 VT-x 指令集和 AMD 的 AMD-V 指令集)。能够处理虚拟化优质消费级处理器有因特尔的 i5 或 i7 和 AMD 的 Ryzen 处理器。如果你考虑服务器级的硬件,那么因特尔的志强系列和 AMD 的 EPYC 都是不错的选择。内存可能很昂贵,尤其是最近的 DDR4 内存。当我们估计所需多少内存时,请为主机操作系统的内存至少分配 2 GB 的空间。 - -如果你担心电费或噪声,则诸如因特尔 NUC 设备之类的解决方案虽然外形小巧,功耗低,噪音低,但是却以牺牲可扩展性为代价。 - -#### 网络附加存储Network-attached storage(NAS) - -如果希望装有硬盘驱动器的计算机存储你的所有个人数据,电影,图片等,并为虚拟化服务器提供存储,则需要网络附加存储(NAS)。 - -在大多数情况下,你不太可能需要一颗强力的 CPU。实际上,许多商业 NAS 的解决方案使用低功耗的 ARM CPU。主板能支持多个 SATA 硬盘。如果你的主板没有足够的端口,请使用主机总线适配器host bus adapter(HBA)SAS 控制器添加其他功能。 - -网络性能对于 NAS 来说是至关重要的,因此最好选择千兆gigabit网络(或更快网络)。 - -内存需求将根据你的文件系统而有所不同。ZFS 是 NAS 上最受欢迎的文件系统之一,你将需要更多内存才能使用诸如缓存或重复数据删除之类的功能。纠错码Error-correcting code(ECC)的内存是防止数据损坏的最佳选择(但在购买前请确保你的主板支持)。最后但同样重要的,不要忘记使用不间断电源uninterruptible power supply(UPS),因为断电可能会使得数据出错。 - - -#### 防火墙和路由器 - -你是否曾意识到,廉价的路由器/防火墙通常是保护你的家庭网络不受外部环境影响的主要部分?这些路由器很少及时收到安全更新(如果有的话)。现在害怕了吗?好吧,[确实][2]! - -通常,你不需要一颗强大的 CPU 或是大内存来构建你自己的路由器/防火墙,除非你需要高吞吐率或是执行 CPU 密集型任务,像是 VPN 服务器或是流量过滤。在这种情况下,你将需要一个支持 AES-NI 的多核 CPU。 - -你可能想要至少 2 个千兆或更快的以太网卡Ethernet network interface cards(NIC),这不是必需的,但我推荐使用一个管理型交换机来连接你自己的装配的路由器,以创建 VLAN 来进一步隔离和保护你的网络。 - -![Home computer lab PfSense][4] - -### 软件 - -在选择完你的虚拟化服务器、NAS 和防火墙/路由器后,下一步是探索不同的操作系统和软件,以最大程度地发挥其作用。尽管你可以使用 CentOS、Debian或 Ubuntu 之类的常规 Linux 发行版,但是与以下软件相比,它们通常花费更多的时间进行配置和管理。 - -#### 虚拟化软件 - -**[KVM][5]**(基于内核的虚拟机Kernel-based Virtual Machine)使你可以将 Linux 变成虚拟机监控程序,以便可以在同一台机器中运行多个虚拟机。最好的是,KVM 作为 Linux 的一部分,它是许多企业和家庭用户的首选。如果你愿意,可以安装 **[libvirt][6]** 和 **[virt-manager][7]** 来管理你的虚拟化平台。 - - -**[Proxmox VE][8]** 是一个强大的企业级解决方案,并且是一个完整的开源虚拟化和容器平台。它基于 Debian,使用 KVM 作为其虚拟机管理程序,并使用 LXC 作为容器。Proxmox 提供了强大的网页界面,API,并且可以扩展到许多群集节点,这很有用,因为你永远不知道何时实验室容量不足。 - -**[oVirt][9](RHV)** 是另一种使用 KVM 作为虚拟机管理程序的企业级解决方案。不要仅仅因为它是企业,并不意味着你不能在家中使用它。oVirt 提供了强大的网页界面和 API,并且可以处理数百个节点(如果你正在运行那么多服务器,我不想成为你的邻居!)。oVirt 用于家庭实验室的潜在问题是它至少需要一些的节点集:你将需要一个外部存储(例如 NAS)和至少两个其他虚拟化节点(你可以仅在一个上运行它,但是你可能会在维护环境时遇到问题)。 - -#### 网络附加存储软件 - -**[FreeNAS][10]** 是最受欢迎的开源 NAS 发行版,它基于稳定的 FreeBSD 操作系统。它最强大的功能之一是支持 ZFS 文件系统,该文件系统提供了数据完整性检查、快照、复制和多个级别的冗余(镜像,条带化镜像和条带化)。最重要的是,所有功能都通过功能强大且易于使用的网页界面进行管理。在安装 FreeNAS 之前,请检查硬件是否支持,因为它不如基于 Linux 的发行版那么广泛。 - -另一个流行的替代方法是基于 Linux 的 **[OpenMediaVault][11]**。它的主要功能之一是模块化,带有可扩展和添加特性的插件。它包括的功能包括基于网页管理界面和协议,例如 CIFS,SFTP,NFS,iSCSI。以及卷管理,包括软件 RAID,资源分配,访问控制列表access control lists(ACL)和共享管理。由于它是基于 Linux 的,因此其具有广泛的硬件支持。 - -#### 防火墙/路由器软件 - -**[pfSense][12]** 是基于 FreeBSD 的开源企业级路由器和防火墙发行版。它可以直接安装在服务器上,甚至可以安装在虚拟机中(以管理虚拟或物理网络并节省空间)。它有许多功能,可以使用软件包进行扩展。尽管它也有命令行访问权限,但也可以完全使用网页界面对其进行管理。它具有你所希望路由器和防火墙提供的所有功能,例如 DHCP 和 DNS,以及更高级的功能,例如入侵检测(IDS)和入侵防御(IPS)系统。你可以侦听多个不同接口或使用 VLAN 的网络,并且只需鼠标点击几下即可创建安全的 VPN 服务器。pfSense 使用 pf,这是一种有状态的数据包筛选器,它是使用类似于 IPFilter 的语法为 OpenBSD 操作系统开发的。许多公司和组织都有使用 pfSense。 - -* * * - -考虑到所有的信息,是时候动手开始建立你的实验室了。在之后的文章中,我将介绍运行家庭实验室的第三方面:自动化进行部署和维护。 - --------------------------------------------------------------------------------- - -via: https://opensource.com/article/19/3/home-lab - -作者:[Michael Zamot (Red Hat)][a] -选题:[lujun9972][b] -译者:[wyxplus](https://github.com/wyxplus) -校对:[校对者ID](https://github.com/校对者ID) - -本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 - -[a]: https://opensource.com/users/mzamot -[b]: https://github.com/lujun9972 -[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_keyboard_laptop_development_code_woman.png?itok=vbYz6jjb -[2]: https://opensource.com/article/18/5/how-insecure-your-router -[3]: /file/427426 -[4]: https://opensource.com/sites/default/files/uploads/pfsense2.png (Home computer lab PfSense) -[5]: https://www.linux-kvm.org/page/Main_Page -[6]: https://libvirt.org/ -[7]: https://virt-manager.org/ -[8]: https://www.proxmox.com/en/proxmox-ve -[9]: https://ovirt.org/ -[10]: https://freenas.org/ -[11]: https://www.openmediavault.org/ -[12]: https://www.pfsense.org/ diff --git a/translated/tech/20210326 Why you should care about service mesh.md b/translated/tech/20210326 Why you should care about service mesh.md deleted file mode 100644 index 8c555106ed..0000000000 --- a/translated/tech/20210326 Why you should care about service mesh.md +++ /dev/null @@ -1,70 +0,0 @@ -[#]: subject: (Why you should care about service mesh) -[#]: via: (https://opensource.com/article/21/3/service-mesh) -[#]: author: (Daniel Oh https://opensource.com/users/daniel-oh) -[#]: collector: (lujun9972) -[#]: translator: (geekpi) -[#]: reviewer: ( ) -[#]: publisher: ( ) -[#]: url: ( ) - -为什么你要关心 Service Mesh -====== -在微服务环境中,Service Mesh 为开发和运营提供了好处。 -![Net catching 1s and 0s or data in the clouds][1] - -很多开发者不知道为什么要关心 [Service Mesh][2]。这是我在开发者见面会、会议和实践研讨会上关于云原生架构的微服务开发的演讲中经常被问到的问题。我的回答总是一样的:“只要你想简化你的微服务架构,你就应该在 Kubernetes 上运行。” - -关于简化,你可能也想知道,为什么分布式微服务必须设计得如此复杂才能在 Kubernetes 集群上运行。正如本文所解释的那样,许多开发人员通过 Service Mesh 解决了微服务架构的复杂性,并通过在生产中采用 Service Mesh 获得了额外的好处。 - -### 什么是 Service Mesh? - -Service Mesh 是一个专门的基础设施层,用于提供一个透明的、独立于代码的 (polyglot) 方式,以消除应用代码中的非功能性微服务能力。 - - -![Before and After Service Mesh][3] - -(Daniel Oh, [CC BY-SA 4.0][4]) - -### 为什么 Service Mesh 对开发者很重要 - -当开发人员将微服务部署到云时,无论业务功能如何,他们都必须解决非功能性微服务功能,以避免级联故障。这些功能通常可以体现在服务发现、日志、监控、韧性、认证、弹性和跟踪等方面。开发人员必须花费更多的时间将它们添加到每个微服务中,而不是开发实际的业务逻辑,这使得微服务变得沉重而复杂。 - -随着企业加速向云计算转移,Service Mesh 可以提高开发人员的生产力。Kubernetes 加 Service Mesh 平台不需要让服务负责处理这些复杂的问题,也不需要在每个服务中添加更多的代码来处理云原生的问题,而是负责向运行在该平台上的任何应用(现有的或新的,用任何编程语言或框架)提供这些服务。那么微服务就可以轻量级,专注于其业务逻辑,而不是云原生的复杂性。 - -### 为什么 Service Mesh 对运维很重要 - -这并没有回答为什么运维团队需要关心在 Kubernetes 上运行云原生微服务的 Service Mesh。因为运维团队必须确保在 Kubernetes 环境上的大型混合云和多云上部署新的云原生应用的强大安全性、合规性和可观察性。 - -Service Mesh 由一个用于管理代理路由流量的 control plane 和一个用于注入 Sidecar 的 data plane 组成。Sidecar 允许运维团队做一些比如添加第三方安全工具和追踪所有服务通信中的流量,以避免安全漏洞或合规问题。Service Mesh 还可以通过在图形面板上可视化地跟踪指标来提高观察能力。 - -### 如何开始使用 Service Mesh - -对于开发者和运维人员,以及从应用开发到平台运营来说,Service Mesh 可以更有效地管理云原生功能。 - -你可能想知道从哪里开始采用 Service Mesh 来配合你的微服务应用和架构。幸运的是,有许多开源的 Service Mesh 项目。许多云服务提供商也在他们的 Kubernetes 平台中提供 Service Mesh。 - -![CNCF Service Mesh Landscape][5] - -(Daniel Oh, [CC BY-SA 4.0][4]) - -你可以在 [CNCF Service Mesh Landscape][6] 页面中找到最受欢迎的 Service Mesh 项目和服务的链接。 - --------------------------------------------------------------------------------- - -via: https://opensource.com/article/21/3/service-mesh - -作者:[Daniel Oh][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://opensource.com/users/daniel-oh -[b]: https://github.com/lujun9972 -[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_analytics_cloud.png?itok=eE4uIoaB (Net catching 1s and 0s or data in the clouds) -[2]: https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh -[3]: https://opensource.com/sites/default/files/uploads/vm-vs-service-mesh.png (Before and After Service Mesh) -[4]: https://creativecommons.org/licenses/by-sa/4.0/ -[5]: https://opensource.com/sites/default/files/uploads/service-mesh-providers.png (CNCF Service Mesh Landscape) -[6]: https://landscape.cncf.io/card-mode?category=service-mesh&grouping=category diff --git a/translated/tech/20210329 Manipulate data in files with Lua.md b/translated/tech/20210329 Manipulate data in files with Lua.md new file mode 100644 index 0000000000..dfbae5c7fb --- /dev/null +++ b/translated/tech/20210329 Manipulate data in files with Lua.md @@ -0,0 +1,97 @@ +[#]: subject: (Manipulate data in files with Lua) +[#]: via: (https://opensource.com/article/21/3/lua-files) +[#]: author: (Seth Kenlon https://opensource.com/users/seth) +[#]: collector: (lujun9972) +[#]: translator: (geekpi) +[#]: reviewer: ( ) +[#]: publisher: ( ) +[#]: url: ( ) + +用 Lua 操作文件中的数据 +====== +了解 Lua 如何处理数据的读写。 +![Person standing in front of a giant computer screen with numbers, data][1] + +有些数据是临时的,存储在 RAM 中,只有在应用运行时才有意义。但有些数据是要持久的,存储在硬盘上供以后使用。当你编程时,无论是简单的脚本还是复杂的工具套件,通常都需要读取和写入文件。有时文件可能包含配置选项,而另一些时候这个文件是你的用户用你的应用创建的数据。每种语言都会以不同的方式处理这项任务,本文将演示如何使用 Lua 处理文件数据。 + +### 安装 Lua + +如果你使用的是 Linux,你可以从你的发行版软件库中安装 Lua。在 macOS 上,你可以从 [MacPorts][2] 或 [Homebrew][3] 安装 Lua。在 Windows 上,你可以从 [Chocolatey][4] 安装 Lua。 + +安装 Lua 后,打开你最喜欢的文本编辑器并准备开始。 + +### 用 Lua 读取文件 + +Lua 使用 `io` 库进行数据输入和输出。下面的例子创建了一个名为 `ingest` 的函数来从文件中读取数据,然后用 `:read` 函数进行解析。在 Lua 中打开一个文件时,有几种模式可以启用。因为我只需要从这个文件中读取数据,所以我使用 `r`(代表”读“)模式: + + +``` +function ingest(file) +   local f = io.open(file, "r") +   local lines = f:read("*all") +   f:close() +   return(lines) +end + +myfile=ingest("example.txt") +print(myfile) +``` + +在这段代码中,注意到变量 `myfile` 是为了触发 `ingest` 函数而创建的,因此,它接收该函数返回的任何内容。`ingest` 函数返回文件的行数(从一个称为 `lines` 的变量中)。当最后一步打印 `myfile` 变量的内容时,文件的行数就会出现在终端中。 + +如果文件 `example.txt` 中包含了配置选项,那么我会写一些额外的代码来解析这些数据,可能会使用另一个 Lua 库,这取决于配置是以 INI 文件还是 YAML 文件或其他格式存储。如果数据是 SVG 图形,我会写额外的代码来解析 XML,可能会使用 Lua 的 SVG 库。换句话说,你的代码读取的数据一旦加载到内存中,就可以进行操作,但是它们都需要加载 `io` 库。 + +### 用 Lua 将数据写入文件 + +无论你是要存储用户用你的应用创建的数据,还是仅仅是关于用户在应用中做了什么的元数据(例如,游戏保存或最近播放的歌曲),都有很多很好的理由来存储数据供以后使用。在 Lua 中,这是通过 `io` 库实现的,打开一个文件,将数据写入其中,然后关闭文件: + + +``` +function exgest(file) +   local f = io.open(file, "a") +   io.output(f) +   io.write("hello world\n") +   io.close(f) +end + +exgest("example.txt") +``` + +为了从文件中读取数据,我以 `r` 模式打开文件,但这次我使用 `a` (用于”追加“)将数据写到文件的末尾。因为我是将纯文本写入文件,所以我添加了自己的换行符(`/n`)。通常情况下,你并不是将原始文本写入文件,你可能会使用一个额外的库来代替写入一个特定的格式。例如,你可能会使用 INI 或 YAML 库来帮助编写配置文件,使用 XML 库来编写 XML,等等。 + +### 文件模式 + +在 Lua 中打开文件时,有一些保护措施和参数来定义如何处理文件。默认值是 `r`,允许你只读数据: + + * **r** 只读 + * **w** 如果文件不存在,覆盖或创建一个新文件。 + * **r+** 读取和覆盖。 + * **a** 追加数据到文件中,或在文件不存在的情况下创建一个新文件。 + * **a+** 读取数据,将数据追加到文件中,或文件不存在的话,创建一个新文件。 + + + +还有一些其他的(例如,`b` 代表二进制格式),但这些是最常见的。关于完整的文档,请参考 [Lua.org/manual][5] 上的优秀 Lua 文档。 + +### Lua 和文件 + +和其他编程语言一样,Lua 有大量的库支持来访问文件系统来读写数据。因为 Lua 有一个一致且简单语法,所以很容易对任何格式的文件数据进行复杂的处理。试着在你的下一个软件项目中使用 Lua,或者作为 C 或 C++ 项目的 API。 + +-------------------------------------------------------------------------------- + +via: https://opensource.com/article/21/3/lua-files + +作者:[Seth Kenlon][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://opensource.com/users/seth +[b]: https://github.com/lujun9972 +[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data) +[2]: https://opensource.com/article/20/11/macports +[3]: https://opensource.com/article/20/6/homebrew-mac +[4]: https://opensource.com/article/20/3/chocolatey +[5]: http://lua.org/manual