mirror of
https://github.com/LCTT/TranslateProject.git
synced 2026-08-23 04:03:29 +08:00
@@ -0,0 +1,76 @@
|
||||
用 autoplank 在多个显示器上使用 Plank 扩展坞
|
||||
======
|
||||
|
||||

|
||||
|
||||
[autoplank][1] 是用 Go 语言编写的小型工具,它为 Plank 扩展坞增加了多显示器支持,而无需创建[多个][2]扩展坞。
|
||||
|
||||
当你将鼠标光标移动到显示器的底部时,`autoplank` 会使用 `xdotool` 检测到你的鼠标移动,并且自动将 Plank 扩展坞移动到该显示器。该工具仅在将 Plank 设置为在屏幕底部的情况下工作(至少目前如此)。
|
||||
|
||||
在 Plank 实际出现在鼠标所在的显示器上前会稍有延迟。开发人员说这是有意设计的,以确保你确实要在该显示器上访问 Plank。显示 Plank 之前的时间延迟目前尚不可配置,但将来可能会改变。
|
||||
|
||||
`autoplank` 可以在 elementary OS 以及其它的桌面环境或发行版上使用。
|
||||
|
||||
Plank 是一个简单的扩展坞,它显示了正在运行的应用程序/窗口的图标。它允许将应用程序固定到扩展坞,并带有一些内置的简单“扩展组件”:剪贴板管理器、时钟、CPU 监视器、显示桌面和垃圾桶。要访问其设置,请按住 `Ctrl` 键,同时右键单击 Plank 扩展坞上的任意位置,然后单击 “Preferences”。
|
||||
|
||||
Plank 默认用在 elementary OS 中,但也可以在任何桌面环境或 Linux 发行版中使用。
|
||||
|
||||
### 安装 autoplank
|
||||
|
||||
在其 GitHub 页面上,提到你需要 Go 1.8 或更高版本才能构建 `autoplank`,但我能够在 Ubuntu 16.04(elementary OS 0.4 Loki)中使用 Go 1.6 成功构建它。
|
||||
|
||||
开发者说:
|
||||
|
||||
1、安装所需的依赖项。
|
||||
|
||||
要构建 `autoplank`,你需要 Go(在 Debian、Ubuntu、elementary OS 等中使用 golang-go)。要获取最新的 Git 代码,你还需要 `git`,要在显示器上检测你的鼠标移动,还需要安装 `xdotool`。
|
||||
|
||||
使用以下命令将它们安装在 Ubuntu、Debian、elementary OS 等中:
|
||||
|
||||
```
|
||||
sudo apt install git golang-go xdotool
|
||||
```
|
||||
|
||||
2、从 [Git][1] 获取最新的 `autoplank`,构建并将其安装在 `/usr/local/bin` 中:
|
||||
|
||||
```
|
||||
git clone https://github.com/abiosoft/autoplank
|
||||
cd autoplank
|
||||
go build -o autoplank
|
||||
sudo mv autoplank /usr/local/bin/
|
||||
```
|
||||
|
||||
你现在可以从主目录中删除 `autoplank` 文件夹。
|
||||
|
||||
当你想卸载 `autoplank` 时,只需删除 `/usr/local/bin/autoplank` 二进制文件(`sudo rm /usr/local/bin/autoplank`)。
|
||||
|
||||
3、将 `autoplank` 添加到启动中。
|
||||
|
||||
如果你想在将 `autoplank` 添加到启动项或为其创建 systemd 服务之前尝试使用 `autoplank`,则只需在终端中键入 `/usr/local/bin/autoplank` 即可启动它。
|
||||
|
||||
要使 `autoplank` 在重新启动后起作用,你需要将其添加到启动项中。确切的操作步骤取决于你的桌面环境,因此我不会确切告诉你如何在每个桌面环境中执行此操作,但是请记住在启动项中将 `/usr/local/bin/autoplank` 设置为可执行文件。
|
||||
|
||||
在 elementary OS 中,你可以打开“系统设置”,然后在“应用程序”的“启动”选项卡上,单击窗口左下角的“+”按钮,然后在“键入自定义命令”字段中添加 “/usr/local/bin/autoplank”:
|
||||
|
||||

|
||||
|
||||
如[此处][3]的解释,使用 `autoplank` 的另一种方法是通过为其创建 systemd 服务。将 systemd 服务用于 autoplank 的优点是,无论它出于何种原因而崩溃,都可以重新启动 `autoplank`。可以使用 systemd 服务或将 `autoplank` 添加到启动应用程序中(但不要同时使用两者)。
|
||||
|
||||
4、完成此操作后,注销、登录,`autoplank` 应该已在运行,因此你可以将鼠标移至显示器底部以将 Plank 停靠此处。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxuprising.com/2018/08/use-plank-on-multiple-monitors-without.html
|
||||
|
||||
作者:[Logix][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://plus.google.com/118280394805678839070
|
||||
[1]:https://github.com/abiosoft/autoplank
|
||||
[2]:https://answers.launchpad.net/plank/+question/204593
|
||||
[3]:https://github.com/abiosoft/autoplank#optional-create-a-service
|
||||
[4]:https://www.reddit.com/r/elementaryos/comments/95a879/autoplank_use_plank_on_multimonitor_setup/e3r9saq/
|
||||
@@ -0,0 +1,101 @@
|
||||
Linux 平台上的写作者必备工具
|
||||
======
|
||||
|
||||

|
||||
|
||||
我从事作家已有 20 多年了。我撰写了数千篇有关各种技术主题的文章和指南,并撰写了 40 多本小说。因此,书面文字不仅对我很重要,还很熟悉,成为了我的第二种自然交流的方式。在过去的二十年中(而且还在继续),我几乎都是在 Linux 平台上完成的所有工作。我必须承认,在早期,这并不总是那么容易。格式并不总是与编辑器所需要的相吻合,在某些情况下,开源平台根本没有完成工作所需的必要工具。
|
||||
|
||||
那时已经过去,现在已经不同了。
|
||||
|
||||
Linux 演进和基于 Web 的工具的相得益彰使得它可以让任何写作者都能在 Linux 上完成工作(并且做得很好)。但是你需要什么工具?你可能会惊讶地发现,在某些情况下,使用 100% 开源的工具无法有效完成这项工作。不过即使如此,工作总是可以完成的。让我们来看看我作为技术作家和小说作者一直使用的工具。我将通过小说和非小说类的写作过程来概述这一点(因为过程不同,需要特定的工具)。
|
||||
|
||||
对认真的 Linux 硬核用户预先做个预警。很久以前,我就放弃了使用 LaTeX 和 DocBook 之类的工具进行写作。为什么?因为对我而言,重点必须放在内容上,而不是过程上。当你面临最后期限时,必须以效率为先。
|
||||
|
||||
### 非小说类
|
||||
|
||||
我们将从非虚构写作入手,因为这是两者中较简单的过程。为了编写技术指南,我与不同的编辑人员合作,并且在某些情况下,必须将内容复制/粘贴到 CMS 中。但是就像我的小说一样,整个过程总是从 Google 云端硬盘开始。在这一点上,许多开源纯粹主义者会转身走开。不用担心,你始终可以选择将所有文件保存在本地,也可以使用更开放友好的云服务(例如 [Zoho][1] 或 [nextCloud][2])。
|
||||
|
||||
为什么要从云端开始?多年来,我发现我需要能够随时随地访问那些内容。最简单的解决方案是迁移到云上。我对丢失工作成果这件事也很偏执。为此,我使用了 [Insync][3] 之类的工具来使我的 Google 云端硬盘与桌面保持同步。有了桌面同步功能,我知道我的工作成果总是有备份,以防万一 Google 云端硬盘出了问题。
|
||||
|
||||
对于那些我必须与之一起将内容输入到内容管理系统(CMS)的客户,该过程到此结束。我可以直接从 Google 文档复制/粘贴到 CMS 中,并完成此操作。当然,对于技术内容,总是涉及到屏幕截图。为此,我使用 [Gimp][4],它使得截取屏幕截图变得简单:
|
||||
|
||||
![screenshot with Gimp][6]
|
||||
|
||||
*图 1:使用 Gimp 截屏。*
|
||||
|
||||
1. 打开 Gimp。
|
||||
2. 单击“文件>创建>屏幕快照”。
|
||||
3. 选择单个窗口、整个屏幕或要抓取的区域(图 1)。
|
||||
4. 单击“抓取”。
|
||||
|
||||
我的大多数客户倾向于使用 Google 文档,因为我可以共享文件夹,以便他们可以可靠地访问该内容。我有一些无法使用 Google 文档的客户,因此我必须将文件下载为可以使用的格式。为此,我要做的是下载 .odt 格式,以 [LibreOffice][8] 打开文档(图 2),根据需要设置格式,保存为客户所需的格式,然后发送文档。
|
||||
|
||||
![Google Doc][10]
|
||||
|
||||
*图 2:在 LibreOffice 中打开我下载的 Google 文档。*
|
||||
|
||||
非小说类作品这样就行了。
|
||||
|
||||
### 小说类
|
||||
|
||||
这里会稍微变得有点复杂。开始的步骤是相同的,因为我总是在 Google 文档中写小说的每个初稿。完成后,我将文件下载到 Linux 桌面,在 LibreOffice 中打开文件,根据需要设置格式,然后另存为编辑器支持的文件类型(不幸的是,这意味着是 .docx)。
|
||||
|
||||
该过程的下一步变得有些琐碎。我的编辑更喜欢使用注释来跟踪更改(因为这使我们俩阅读文档和做出更改一样容易)。因此,一个 60k 的 word 文档可以包含成百上千的注释,这会使 LibreOffice 慢的像爬一样。从前,你可以增加用于文档的内存,但是从 LibreOffice 6 开始,这不再可行。这意味着任何较大的、像小说一样长的、带有大量注释的文档都将无法使用。因此,我不得不采取一些极端的措施,使用 [WPS Office][11](图 3)。尽管这不是开源解决方案,但 WPS Office 在文档中包含大量注释的情况下做得很好,因此无需处理 LibreOffice 所带来的麻烦(当处理带有数百个注释的大型文件时)。
|
||||
|
||||
![comments][13]
|
||||
|
||||
*图 3:WPS 可以轻松处理大量注释。*
|
||||
|
||||
一旦我和我的编辑完成了对书的编辑(所有评论都已删除),我就可以在 LibreOffice 中打开文件进行最终格式化。格式化完成后,我将文件保存为 .html 格式,然后以 [Calibre][14] 打开文件以将文件导出为 .mobi 和 .epub 格式。
|
||||
|
||||
对于希望在 Amazon、Barnes&Noble、Smashwords 或其他平台上出版的任何人,Calibre 都是必备工具。Caliber 比其他类似解决方案更好地方是,它使你可以直接编辑 .epub 文件(图 4)。对于 Smashword 来说,这是绝对必要的(因为导出过程将添加 Smashwords 转换工具上不接受的元素)。
|
||||
|
||||
![Calibre][16]
|
||||
|
||||
*图 4:直接在 Calibre 中编辑 epub 文件。*
|
||||
|
||||
写作过程结束后(或有时在等待编辑完成一校时),我将开始为书制作封面。该任务完全在 Gimp 中处理(图 5)。
|
||||
|
||||
![Using Gimp][19]
|
||||
|
||||
*图 5:在 Gimp 中创建 POTUS 的封面。*
|
||||
|
||||
这样就完成了在 Linux 平台上创建小说的过程。由于文档的篇幅以及某些编辑人员的工作方式,与创建非小说类的过程相比,它可能会变得有些复杂,但这远没有挑战性。实际上,在 Linux 上创建小说与其他平台一样简单(并且更可靠)。
|
||||
|
||||
### 希望这可以帮助你
|
||||
|
||||
我希望这可以帮助有抱负的作家有信心在 Linux 平台上进行写作。还有许多其他工具可供使用,但是多年来我在这里列出的工具很好地服务了我。而且,尽管我确实使用了几个专有的工具,但只要它们在 Linux 上都能正常运行,我觉得是可以的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/learn/2018/11/must-have-tools-writers-linux-platform
|
||||
|
||||
作者:[Jack Wallen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/users/jlwallen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.zoho.com/
|
||||
[2]: https://nextcloud.com/
|
||||
[3]: https://www.insynchq.com
|
||||
[4]: https://www.gimp.org/
|
||||
[5]: /files/images/writingtools1jpg
|
||||
[6]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_1.jpg (screenshot with Gimp)
|
||||
[7]: /licenses/category/used-permission
|
||||
[8]: https://www.libreoffice.org/
|
||||
[9]: /files/images/writingtools2jpg
|
||||
[10]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_2.jpg (Google Doc)
|
||||
[11]: https://www.wps.com/en-US/
|
||||
[12]: /files/images/writingtools3jpg
|
||||
[13]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_3.jpg (comments)
|
||||
[14]: https://calibre-ebook.com/
|
||||
[15]: /files/images/writingtools4jpg
|
||||
[16]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_4.jpg (Calibre)
|
||||
[17]: /licenses/category/creative-commons-zero
|
||||
[18]: /files/images/writingtools5jpg
|
||||
[19]: https://lcom.static.linuxfound.org/sites/lcom/files/writingtools_5.jpg (Using Gimp)
|
||||
[20]: https://training.linuxfoundation.org/training/introduction-to-open-source-development-git-and-linux/?utm_source=linux.com&utm_medium=article&utm_campaign=lfd201
|
||||
@@ -0,0 +1,77 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11607-1.html)
|
||||
[#]: subject: (Can Better Task Stealing Make Linux Faster?)
|
||||
[#]: via: (https://www.linux.com/blog/can-better-task-stealing-make-linux-faster)
|
||||
[#]: author: (Oracle )
|
||||
|
||||
更好的任务窃取可以使 Linux 更快吗?
|
||||
======
|
||||
|
||||

|
||||
|
||||
> Oracle Linux 内核开发人员 Steve Sistare 参与了这场有关内核调度程序改进的讨论。
|
||||
|
||||
### 通过可扩展的任务窃取进行负载平衡
|
||||
|
||||
Linux 任务调度程序通过将唤醒的任务推送到空闲的 CPU,以及在 CPU 空闲时从繁忙的 CPU 中拉取任务来平衡整个系统的负载。在大型系统上的推送侧和拉取侧,有效的伸缩都是挑战。对于拉取,调度程序搜索连续的更大范围中的所有 CPU,直到找到过载的 CPU,然后从最繁忙的组中拉取任务。这代价非常昂贵,在大型系统上要花费 10 到 100 微秒,因此搜索时间受到平均空闲时间的限制,并且某些范围不会被搜索。并非总能达到平衡,而且闲置的 CPU 依旧闲置。
|
||||
|
||||
我实现了一种备用机制,该机制在 `idle_balance()` 中的现有搜索中自身受限并且没有找到之后被调用。我维护了一个过载的 CPU 的位图,当可运行的 CFS 任务计数超过 1 时,CPU 会设置该位。这个位图是稀疏的,每个高速缓存线的有效位数量有限。当许多线程同时设置、清除和访问元素时,这可以减少缓存争用。每个末级缓存都有一个位图。当 CPU 空闲时,它将搜索该位图以查找第一个具有可迁移任务的过载 CPU,然后将其窃取。这种简单的窃取会比单独的 `idle_balance()` 产生更高的 CPU 利用率,因为该搜索的成本很便宜,花费 1 到 2 微秒,因此每次 CPU 即将空闲时都可以调用它。窃取不会减轻全局最繁忙的队列的负担,但是它比根本不执行任何操作要好得多。
|
||||
|
||||
### 结果
|
||||
|
||||
偷窃仅在调度程序代码中占用少量 CPU 开销即可提高利用率。在以下实验中,以不同数量的组(每个组 40 个任务)运行 hackbench,并对每次运行结果显示 `/proc/schedstat` 中的增量(按 CPU 平均),并增加了这些非标准的统计信息:
|
||||
|
||||
* `%find`:在旧函数和新函数中花费的时间百分比,这些函数用于搜索空闲的 CPU 和任务以窃取并设置过载的 CPU 位图。
|
||||
* `steal`:任务从另一个 CPU 窃取的次数。经过的时间增加了 8% 到 36%,最多增加了 0.4% 的发现时间。
|
||||
|
||||
![load balancing][1]
|
||||
|
||||
如下图的绿色曲线所示,新内核的 CPU 繁忙利用率接近 100%,作为比较的基线内核是橙色曲线:
|
||||
|
||||
![][3]
|
||||
|
||||
根据负载的不同,窃取可将 Oracle 数据库 OLTP 性能提高多达 9%,并且我们已经看到 MySQL、Pgsql、gcc、Java 和网络方面有了一些不错的改进。通常,窃取对上下文切换率高的工作负载最有帮助。
|
||||
|
||||
### 代码
|
||||
|
||||
截至撰写本文时,这项工作尚未完成,但最新的修补程序系列位于 [https://lkml.org/lkml/2018/12/6/1253][4]。如果你的内核是使用 `CONFIG_SCHED_DEBUG=y` 构建的,则可以使用以下命令验证其是否包含窃取优化:
|
||||
|
||||
```
|
||||
# grep -q STEAL /sys/kernel/debug/sched_features && echo Yes
|
||||
Yes
|
||||
```
|
||||
|
||||
如果要尝试使用,请注意,对于具有 2 个以上 NUMA 节点的系统,禁用了窃取功能,因为 hackbench 在此类系统上发生了回归,正如我在 [https://lkml.org/lkml/2018/12/6/1250][5] 中解释的那样。但是,我怀疑这种影响是特定于 hackbench 的,并且窃取将有助于多节点系统上的其他工作负载。要尝试使用它,请用内核参数 `sched_steal_node_limit=8`(或更大)重新启动。
|
||||
|
||||
### 进一步工作
|
||||
|
||||
在将基本盗用算法推向上游之后,我正在考虑以下增强功能:
|
||||
|
||||
* 如果在末级缓存中进行窃取找不到候选者,在 LLC 和 NUMA 节点之间进行窃取。
|
||||
* 维护稀疏位图以标识 RT 调度类中的偷窃候选者。当前 `pull_rt_task()` 搜索所有运行队列。
|
||||
* 从 `idle_balance()` 中删除核心和套接字级别,因为窃取会处理这些级别。当支持跨 LLC 窃取时,完全删除 `idle_balance()`。
|
||||
* 维护位图以标识空闲核心和空闲 CPU,以实现推平衡。
|
||||
|
||||
这篇文章最初发布于 [Oracle Developers Blog][6]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linux.com/blog/can-better-task-stealing-make-linux-faster
|
||||
|
||||
作者:[Oracle][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linux.com/author/oracle/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://lcom.static.linuxfound.org/sites/lcom/files/linux-load-balancing.png (load balancing)
|
||||
[3]: https://cdn.app.compendium.com/uploads/user/e7c690e8-6ff9-102a-ac6d-e4aebca50425/b7a700fe-edc3-4ea0-876a-c91e1850b59b/Image/00c074f4282bcbaf0c10dd153c5dfa76/steal_graph.png
|
||||
[4]: https://lkml.org/lkml/2018/12/6/1253
|
||||
[5]: https://lkml.org/lkml/2018/12/6/1250
|
||||
[6]: https://blogs.oracle.com/linux/can-better-task-stealing-make-linux-faster
|
||||
@@ -0,0 +1,73 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11575-1.html)
|
||||
[#]: subject: (Why blockchain (might be) coming to an IoT implementation near you)
|
||||
[#]: via: (https://www.networkworld.com/article/3386881/why-blockchain-might-be-coming-to-an-iot-implementation-near-you.html)
|
||||
[#]: author: (Jon Gold https://www.networkworld.com/author/Jon-Gold/)
|
||||
|
||||
为什么区块链(可能会)来到你身边的物联网
|
||||
======
|
||||
|
||||
![MF3D / Getty Images][1]
|
||||
|
||||
各个公司发现,物联网与最近其他许多流行的企业级计算技术有着良好的合作关系,以支持加密货币而闻名的创新的分布式信任系统的区块链也不例外。然而,在物联网应用中实施区块链可能具有挑战性,并且需要对技术有深入的了解。
|
||||
|
||||
区块链是一个跟踪各种交易的分布式账本。链上的每个“块”都包含要防止篡改的交易记录或其他数据,并通过加密散列链接到前一个,这意味着对块的任何篡改都将使该链接无效。节点(几乎可以是其中装有 CPU 的任何节点)通过分布式的对等网络进行通信,以共享数据并确保链中数据的有效性。
|
||||
|
||||
北卡罗来纳大学格林波若分校的管理学教授 Nir Kshetri 表示,区块链系统之所以有效,是因为所有的块都必须就它们所保护的数据的细节达成一致。如果有人尝试更改给定节点上先前的事务,则存储在网络上的其余数据会回推回来。“数据的旧记录仍然存在,” Kshetri 说。
|
||||
|
||||
这是一项强大的安全技术 —— 如果没有坏人成功控制给定区块链上的所有(LCTT 译注:应为“大部分”)节点([著名的“51% 攻击”][4]),那么该区块链保护的数据就不会被伪造或以其他方式弄乱。因此,对于在物联网世界某些角落的公司来说,使用区块链是一种有吸引力的选择也就不足为奇了。
|
||||
|
||||
物联网安全初创企业 NXMLabs 的首席技术官兼联合创始人 Jay Fallah 认为,除了区块链能够在网络上安全地分发可信信息的能力这一事实之外,部分原因还在于区块链在技术堆栈中的地位。
|
||||
|
||||
“区块链站在一个非常有趣的交叉点。在过去的 15 年中,在存储、CPU 等方面,计算技术一直在加速发展,但是直到最近,网络技术并没有发生太大变化。”他说,“ 区块链不是网络技术、不是数据技术,而是二者兼具。”
|
||||
|
||||
### 区块链和物联网
|
||||
|
||||
区块链作为物联网世界的部分意义取决于你在和谁交谈以及他们在出售什么,但是最接近的概括可能来自企业区块链供应商 Filament 的首席执行官 Allison Clift-Jenning。
|
||||
|
||||
她说:“在任何地方,人们都想互相信任,并且用的是非常古老的方式,这通常是进入场景的好地方。”
|
||||
|
||||
直接从 Filament 自己的客户群中挑选出来的一个例子是二手车销售。Filament 与“一家主要的底特律汽车制造商”合作,创建了一个受信任的车辆历史平台,该平台基于一种设备,该设备可插入二手车的诊断端口,从那里获取信息,并将该数据写入区块链。像这样,二手车的历史记录就是不可变的,包括它的安全气囊是否曾经打开过,是否被水淹过等等。任何不道德的二手车或不诚实的前车主都无法更改数据,甚至拔掉设备也将意味着记录中存在可疑的空白期。
|
||||
|
||||
SAP 物联网高级副总裁兼全球负责人 Elvira Wallis 表示,当今大多数区块链物联网方案都与信任和数据验证有关。
|
||||
|
||||
她说:“我们遇到的大多数用例都在项目的跟踪和溯源领域,”她举例说明了高端食品的农场到餐桌跟踪系统,该系统使用安装在板条箱和卡车上的区块链节点,这样就可以为物品在运输基础设施中创建无懈可击的记录。(例如,该牛排在这样的温度下冷藏了多长时间,今天运输了多长时间,等等。)
|
||||
|
||||
### 将区块链与物联网一起使用是个好主意吗?
|
||||
|
||||
不同的供应商针对不同的用例出售不同的基于区块链的产品,这些产品使用不同的区块链技术实现,其中一些与加密货币中所使用的经典的、线性的、挖矿式交易区块链不太一样。
|
||||
|
||||
这意味着你目前需要从供应商那里购买特定功能。451 Research 高级分析师 Csilla Zsigri 表示,很少有客户组织拥有可以实施区块链安全系统的内部专家。
|
||||
|
||||
她说,区块链技术的任何智能应用的想法都是发挥其优势,为关键信息创建可信赖的平台。
|
||||
|
||||
Zsigri 说:“这就是我真正看到增值的地方,只是增加了一层信任和验证。”
|
||||
|
||||
专家们一致认为,尽管相当了解基于区块链的物联网应用程序的基本概念,但它并不适用于每个物联网用例。 将区块链应用于非交易系统(尽管有例外,包括 NXM Labs 的用于物联网设备的基于区块链配置的产品)通常不是正确的举动。
|
||||
|
||||
如果不需要在两个不同的参与方之间共享数据,而是简单地将数据从传感器移到后端,那么区块链通常就没有意义,因为它实际上并没有为当前大多数物联网实现中的数据分析增加任何关键的增值。
|
||||
|
||||
“今天,我们仍处于区块链的早期拨号时代。”Clift-Jennings 说,“它比典型的数据库要慢,它甚至无法读取,也常常没有查询引擎。从本质上讲,你并没有真正获得隐私。”
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3386881/why-blockchain-might-be-coming-to-an-iot-implementation-near-you.html
|
||||
|
||||
作者:[Jon Gold][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Jon-Gold/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2019/02/chains_binary_data_blockchain_security_by_mf3d_gettyimages-941175690_2400x1600-100788434-large.jpg
|
||||
[2]: https://www.networkworld.com/article/3224893/internet-of-things/what-is-edge-computing-and-how-it-s-changing-the-network.html
|
||||
[3]: https://www.networkworld.com/article/3291790/data-center/how-edge-networking-and-iot-will-reshape-data-centers.html
|
||||
[4]: https://bitcoinist.com/51-percent-attack-hackers-steals-18-million-bitcoin-gold-btg-tokens/
|
||||
[5]: https://www.facebook.com/NetworkWorld/
|
||||
[6]: https://www.linkedin.com/company/network-world
|
||||
@@ -0,0 +1,63 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11565-1.html)
|
||||
[#]: subject: (Why containers and Kubernetes have the potential to run almost anything)
|
||||
[#]: via: (https://opensource.com/article/19/6/kubernetes-potential-run-anything)
|
||||
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux)
|
||||
|
||||
为什么容器和 Kubernetes 有潜力运行一切
|
||||
======
|
||||
|
||||
> 不仅可以部署简单的应用程序,还可以用 Kubernetes 运维器应对第 2 天运营。
|
||||
|
||||

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

|
||||
|
||||
昔日的系统管理员整天都在调教用户和摆弄服务器,一天的时间都奔波在几百米长的电缆之间。随着云计算、容器和虚拟机的复杂性的增加,而今依然如此。
|
||||
|
||||
以外行人来看,很难准确确定系统管理员的确切职能,因为他们在许多地方都扮演着一个不起眼的角色。没人能在培训中知道自己工作中所需要的一切知识,但是每个人其实都需要一个坚实的基础。如果你想走上系统管理的道路,那么这是你个人自学或在正式培训中应重点关注的内容。
|
||||
|
||||
### Bash
|
||||
|
||||
当你学习 Bash Shell 时,你学习的不仅是 Bash Shell,你学习的也是 Linux、BSD、MacOS 甚至Windows(在适当条件下)的通用界面。你将了解语法的重要性,因此可以快速适应思科路由器的命令行或微软 PowerShell 等系统,最终你甚至可以学习更强大的语言,如 Python 或 Go。而且,你还会开始进行程序性思考,以便可以分析复杂的问题并将其分解为单个组件,这很关键,因为这就是系统(例如互联网、组织的内部网、Web 服务器、备份解决方案)是如何设计的。
|
||||
|
||||
不止于此,还有更多。
|
||||
|
||||
由于最近 DevOps 和[容器][2]的发展趋势,了解 Bash shell 变得尤为重要。你的系统管理员职业可能会将你带入一个视基础设施为代码的世界,这通常意味着你必须了解脚本编写的基础知识、[基于 YAML][3]配置的结构,以及如何与[容器][5](运行在[沙盒文件][6]内部的微型 Linux 系统)[交互][4]。你会知道 Bash 是高效管理激动人心的开源技术的门户,因此请进入 [Bash][7] 世界吧。
|
||||
|
||||
#### 资源
|
||||
|
||||
有很多方法可以在 Bash shell 中进行练习。
|
||||
|
||||
尝试一下[便携式 Linux 发行版][8]。你无需安装 Linux 即可使用 Linux,因此,请拿一块闲置的 U 盘,花个晚上或周末的空闲时光,来适应基于文本的界面。
|
||||
|
||||
这里有[几篇很棒的][10] [Bash 文章][9]。
|
||||
|
||||
要注意的是 Bash 练习的关键在于要练习,你必须有要做的练习才行。而且,在你知道如何使用 Bash 之前,你可能不知道该练习什么。如果是这样,请去 Over The Wire 玩一下 [Bandit][11] 游戏。这是一款针对绝对初学者的游戏,具有 34 个级别的交互式基本技巧,可让你熟悉 Linux shell。
|
||||
|
||||
### Web 服务器设置
|
||||
|
||||
一旦你习惯了 Bash,你应该尝试设置一个 Web 服务器。并不是所有的系统管理员都会四处设置 Web 服务器甚至维护 Web 服务器,但是你在安装和启动 HTTP 守护程序、配置 Apache 或 Nginx,设置[正确权限][12]和[配置防火墙][13]时所掌握的技能是你每天都需要使用的技能。经过一些努力,你可能会开始注意到自己的某些工作模式。在尝试管理可用于生产环境的软件和硬件之前,你可能认为某些概念是理所当然的,而你在成为新手的管理员角色时,将不再受到它们的影响。起初这可能会令人沮丧,因为每个人都喜欢在自己做好所做的事情,但这实际上是一件好事。让自己接触新技能,那就是你学习的方式。
|
||||
|
||||
此外,你在第一步中付出的努力越多,最终当你在默认的 index.html 上看到胜利的“it works!”就越甜蜜!
|
||||
|
||||
#### 资源
|
||||
|
||||
David Both 撰写了有关 [Apache Web 服务器][14]配置的出色文章。值得一提的是,请逐步阅读他的后续文章,其中介绍了如何在一台计算机上[托管多个站点][15]。
|
||||
|
||||
### DHCP
|
||||
|
||||
动态主机配置协议(DHCP)是为网络上的设备分配 IP 地址的系统。在家里,ISP(互联网服务提供商)支持的调制解调器或路由器可能内置了 DHCP 服务器,因此可能不在你的权限范围内。如果你曾经登录家用路由器来调整 IP 地址范围或为某些网络设备设置了静态地址,那么你至少对该概念有所了解。你可能会将其理解为对网络上的设备分配了一种 IP 地址形式的电话号码,并且你可能会意识到计算机之间通过广播发送到特定 IP 地址的消息彼此进行通信。消息标头由路径上的路由器读取,每个消息标头都将消息定向到路径上的第二个逻辑路由器,以达到其最终目标。
|
||||
|
||||
即使你了解了这些概念,要从对 DHCP 的基本了解再进一步是架设 DHCP 服务器。安装和配置自己的 DHCP 服务器可能会导致家庭网络中的 DHCP 冲突(如果可以的话,请尽量避免这样做,因为它肯定会干掉你的网络,直到解决为止),要控制地址的分配、创建子网,并监控连接和租赁时间。
|
||||
|
||||
更重要的是,设置 DHCP 并尝试不同的配置有助于你了解网络之间的关系。你会了解网络如何在数据传输中表示“分区”,以及必须采取哪些步骤才能将信息从一个网络传递到另一个。这对于系统管理员来说至关重要,因为网络肯定是工作中最重要的方面之一。
|
||||
|
||||
#### 资源
|
||||
|
||||
在运行自己的 DHCP 服务器之前,请确保家庭路由器(如果有)中的 DHCP 服务器处于非活动状态。一旦启动并运行了 DHCP 服务器,请阅读 Archit Modi 的[网络命令指南][16],以获取有关如何探索网络的提示。
|
||||
|
||||
### 网络电缆
|
||||
|
||||
这听起来很普通,但是熟悉网络电缆的工作方式不仅使你的周末变得非常有趣,而且还使你对数据是如何通过缆线的得到了全新的了解。最好的学习方法是去当地的业余爱好商店并购买五类线剥线钳和压线钳以及一些五类线水晶头。然后回家,拿一根备用的以太网电缆,切断水晶头,花一些时间重新制作网线接头,将电缆重新投入使用。
|
||||
|
||||
解决了这个难题后,请再做一次,这次创建一条有效的[交叉电缆][17]。
|
||||
|
||||
你现在应该还在沉迷于有关电缆管理。如果你有些强迫症,喜欢沿着地板线或桌子的边缘整齐地排列电缆,或者将电缆绑在一起以保持它们的整齐有序,那么就可以使自己免受永久混乱的电缆困扰。你一开始可能不会理解这样做的必要性,但是当你第一次走进服务器机房时,你会马上知道原因。
|
||||
|
||||
### Ansible
|
||||
|
||||
[Ansible][18] 是配置管理软件,它在系统管理员和 DevOps 之间架起了一座桥梁。系统管理员使用 Ansible 来配置全新安装的操作系统并在计算机上维护特定的状态。DevOps 使用 Ansible 减少了在工具上花费的时间和精力,从而在开发上可以花费更多的时间和精力。作为系统管理员培训的一部分,你应该学习 Ansible,并着眼于 DevOps 实践,因为 DevOps 现在开创的大多数功能将最终成为将来系统管理中工作流的一部分。
|
||||
|
||||
Ansible 的好处是你可以立即开始使用它。它是跨平台的,并且可以向上和向下缩放。对于单用户计算机, Ansible 可能是小题大做,但是话又说回来,Ansible 可能会改变你启动虚拟机的方式,或者可以帮助你同步家庭或[家庭实验室][19]中所有计算机的状态。
|
||||
|
||||
|
||||
#### 资源
|
||||
|
||||
阅读 Jay LaCroix 的[如何使用 Ansible 管理工作站配置][20]中的典型介绍,以轻松地在日常之中开始使用 Ansible。
|
||||
|
||||
### 破坏
|
||||
|
||||
由于用户的错误、软件的错误、管理员(就是你!)的错误以及许多其他因素,计算机上会出现问题。无法预测将要失败的原因,因此你的个人系统管理员培训制度的一部分应该是破坏你设置的系统,直到它们失败为止。你自己的实验室基础设施越是脆弱,发现弱点的可能性就越大。而且,你越是经常修复这些弱点,你对解决问题的能力就越有信心。
|
||||
|
||||
除了严格设置所有常见的软件和硬件之外,作为系统管理员的主要工作是查找解决方案。有时候,你可能会遇到职位描述之外的问题,甚至可能无法解决,但这完全取决于你的解决方法。
|
||||
|
||||
现在,你越多地折腾并努力加以解决,则以系统管理员的身份进行的准备就越充分。
|
||||
|
||||
你是系统管理员吗?你是否希望自己为更好的任务做好准备?在下面的评论中写下它们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/7/be-a-sysadmin
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux11x_cc.png?itok=XMDOouJR (People work on a computer server with devices)
|
||||
[2]: https://opensource.com/article/19/6/kubernetes-dump-truck
|
||||
[3]: https://www.redhat.com/sysadmin/yaml-tips
|
||||
[4]: https://opensource.com/article/19/6/how-ssh-running-container
|
||||
[5]: https://opensource.com/resources/what-are-linux-containers
|
||||
[6]: https://opensource.com/article/18/11/behind-scenes-linux-containers
|
||||
[7]: https://opensource.com/article/18/7/admin-guide-bash
|
||||
[8]: https://opensource.com/article/19/6/linux-distros-to-try
|
||||
[9]: https://opensource.com/tags/bash
|
||||
[10]: https://www.redhat.com/sysadmin/managing-files-linux-terminal
|
||||
[11]: http://overthewire.org/wargames/bandit
|
||||
[12]: https://opensource.com/article/19/6/understanding-linux-permissions
|
||||
[13]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd
|
||||
[14]: https://opensource.com/article/18/2/how-configure-apache-web-server
|
||||
[15]: https://opensource.com/article/18/3/configuring-multiple-web-sites-apache
|
||||
[16]: https://opensource.com/article/18/7/sysadmin-guide-networking-commands
|
||||
[17]: https://en.wikipedia.org/wiki/Ethernet_crossover_cable
|
||||
[18]: https://opensource.com/sitewide-search?search_api_views_fulltext=ansible
|
||||
[19]: https://opensource.com/article/19/6/create-centos-homelab-hour
|
||||
[20]: https://opensource.com/article/18/3/manage-workstation-ansible
|
||||
322
published/20190801 Linux permissions 101.md
Normal file
322
published/20190801 Linux permissions 101.md
Normal file
@@ -0,0 +1,322 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11553-1.html)
|
||||
[#]: subject: (Linux permissions 101)
|
||||
[#]: via: (https://opensource.com/article/19/8/linux-permissions-101)
|
||||
[#]: author: (Alex Juarez https://opensource.com/users/mralexjuarezhttps://opensource.com/users/marcobravohttps://opensource.com/users/greg-p)
|
||||
|
||||
全面介绍 Linux 权限
|
||||
======
|
||||
|
||||
> 知道如何控制用户对文件的访问是一项基本的系统管理技能。
|
||||
|
||||

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

|
||||
|
||||
无可否认,Google Chrome 是[最受欢迎的网络浏览器][1]。它的开源版本 [Chromium][2] 也越来越受欢迎,现在一些 Linux 发行版将其作为默认的网络浏览器。
|
||||
|
||||
如果你经常在台式机上使用它,则可以使用 Google Chrome 键盘快捷键来改善浏览体验。没有必要用你的鼠标移来移去、点来点去。只要掌握这些快捷方式,你可以节省一些时间并提高工作效率。
|
||||
|
||||
我这里使用的名称是 Google Chrome,但是这些快捷方式同样适用于 Chromium 浏览器。
|
||||
|
||||
### 你应该使用的 11 个酷炫的 Chrome 键盘快捷键
|
||||
|
||||
如果你是专业人士,可能已经知道其中一些 Chrome 快捷方式,但是有可能你仍然可以在这里找到一些隐藏的宝石。让我们来看看。
|
||||
|
||||
**键盘快捷键** | **动作**
|
||||
---|---
|
||||
`Ctrl+T` | 打开一个新标签页
|
||||
`Ctrl+N` | 打开一个新窗口
|
||||
`Ctrl+Shift+N` | 打开一个新无痕式窗口
|
||||
`Ctrl+W` | 关闭当前标签页
|
||||
`Ctrl+Shift+T` | 重新打开上一个关闭的标签页
|
||||
`Ctrl+Shift+W` | 关闭窗口
|
||||
`Ctrl+Tab` 和 `Ctrl+Shift+Tab` | 切换到右侧或左侧的标签页
|
||||
`Ctrl+L` | 访问搜索/地址栏
|
||||
`Ctrl+D` | 将网址放入书签
|
||||
`Ctrl+H` | 访问浏览历史
|
||||
`Ctrl+J` | 访问下载历史
|
||||
`Shift+Esc` | 打开 Chrome 任务管理器
|
||||
|
||||
你可以[下载这份有用的 Chrome 键盘快捷键列表来作为快速参考][3]。
|
||||
|
||||
#### 1、用 `Ctrl+T` 打开一个新标签页
|
||||
|
||||
需要打开一个新标签页吗?只需同时按 `Ctrl` 和 `T` 键,你就会打开一个新标签。
|
||||
|
||||
#### 2、使用 `Ctrl+N` 打开一个新窗口
|
||||
|
||||
已经打开太多标签页?是时候打开一个新的窗口。使用 `Ctrl` 和 `N` 键打开一个新的浏览器窗口。
|
||||
|
||||
#### 3、使用 `Ctrl+Shift+N` 隐身
|
||||
|
||||
在线查询航班或酒店价格?隐身可能会有所帮助。使用 `Ctrl+Shift+N` 在 Chrome 中打开一个隐身窗口。
|
||||
|
||||
#### 4、使用 `Ctrl+W` 关闭标签页
|
||||
|
||||
使用 `Ctrl` 和 `W` 键关闭当前标签页。无需将鼠标移到顶部并寻找 `x` 按钮。
|
||||
|
||||
#### 5、不小心关闭了标签页?用 `Ctrl+Shift+T` 重新打开
|
||||
|
||||
这是我最喜欢的 Google Chrome 浏览器快捷方式。当你关闭了原本不想关的标签页时,就不用再懊悔了。使用 `Ctrl+Shift+T`,它将打开最后一个关闭的选项卡。继续按此组合键,它把关闭的选项卡再次打开。
|
||||
|
||||
#### 6、使用 `Ctrl+Shift+W` 关闭整个浏览器窗口
|
||||
|
||||
完成工作了吗?是时候关闭带有所有标签页的整个浏览器窗口了。使用 `Ctrl+Shift+W` 键,浏览器窗口将消失,就像以前不存在一样。
|
||||
|
||||
#### 7、使用 `Ctrl+Tab` 在标签之间切换
|
||||
|
||||
打开的标签页太多了吗?你可以使用 `Ctrl+Tab` 移至右侧标签页。想左移吗?使用 `Ctrl+Shift+Tab`。重复按这些键,你可以在当前浏览器窗口的所有打开的标签页之间移动。
|
||||
|
||||
你也可以使用 `Ctrl+0` 直到 `Ctrl+9` 转到前 10 个标签页之一。但是此 Chrome 键盘快捷键不适用于第 11 个及更多标签页。
|
||||
|
||||
#### 8、使用 `Ctrl+L` 转到搜索/地址栏
|
||||
|
||||
想要输入新的 URL 或快速搜索一些内容。你可以使用 `Ctrl+L`,它将在顶部突出显示地址栏。
|
||||
|
||||
#### 9、用 `Ctrl+D` 收藏当前网站
|
||||
|
||||
找到了有趣的东西?使用 `Ctrl+D` 组合键将其保存在书签中。
|
||||
|
||||
#### 10、使用 `Ctrl+H` 返回历史记录
|
||||
|
||||
你可以使用 `Ctrl+H` 键打开浏览器历史记录。如果你正在寻找前一段时间访问过的页面,或者删除你不想再看到的页面,可以搜索历史记录。
|
||||
|
||||
#### 11、使用 `Ctrl+J` 查看下载
|
||||
|
||||
在 Chrome 中按 `Ctrl+J` 键将带你进入下载页面。此页面将显示你执行的所有下载操作。
|
||||
|
||||
#### 意外惊喜:使用 `Shift+Esc` 打开 Chrome 任务管理器
|
||||
|
||||
很多人甚至都不知道 Chrome 浏览器中有一个任务管理器。Chrome 以消耗系统内存而臭名昭著。而且,当你打开大量标签时,找到罪魁祸首并不容易。
|
||||
|
||||
使用 Chrome 任务管理器,你可以查看所有打开的标签页及其系统利用率统计信息。你还可以看到各种隐藏的进程,例如 Chrome 扩展程序和其他服务。
|
||||
|
||||
![Google Chrome 任务管理器][6]
|
||||
|
||||
### 下载 Chrome 快捷键备忘单
|
||||
|
||||
我知道掌握键盘快捷键取决于习惯,你可以通过反复使用使其习惯。为了帮助你完成此任务,我创建了此 Google Chrome 键盘快捷键备忘单。
|
||||
|
||||
![Google Chrome键盘快捷键备忘单][7]
|
||||
|
||||
你可以[下载以下 PDF 格式的图像][8],进行打印并将其放在办公桌上。这样,你可以一直练习快捷方式。
|
||||
|
||||
如果你对掌握快捷方式感兴趣,还可以查看 [Ubuntu 键盘快捷键][9]。
|
||||
|
||||
顺便问一下,你最喜欢的 Chrome 快捷方式是什么?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/google-chrome-shortcuts/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Usage_share_of_web_browsers
|
||||
[2]: https://www.chromium.org/Home
|
||||
[3]: tmp.3qZNXSy2FC#download-cheatsheet
|
||||
[4]: https://itsfoss.com/command-line-text-editors-linux/
|
||||
[5]: https://itsfoss.com/rid-google-chrome-icons-dock-elementary-os-freya/
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/google-chrome-task-manager.png?w=800&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/08/google-chrome-keyboard-shortcuts-cheat-sheet.png?ssl=1
|
||||
[8]: https://drive.google.com/open?id=1lZ4JgRuFbXrnEXoDQqOt7PQH6femIe3t
|
||||
[9]: https://itsfoss.com/ubuntu-shortcuts/
|
||||
235
published/20190826 How RPM packages are made- the source RPM.md
Normal file
235
published/20190826 How RPM packages are made- the source RPM.md
Normal file
@@ -0,0 +1,235 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11527-1.html)
|
||||
[#]: subject: (How RPM packages are made: the source RPM)
|
||||
[#]: via: (https://fedoramagazine.org/how-rpm-packages-are-made-the-source-rpm/)
|
||||
[#]: author: (Ankur Sinha "FranciscoD" https://fedoramagazine.org/author/ankursinha/)
|
||||
|
||||
RPM 包是如何从源 RPM 制作的
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
在[上一篇文章中,我们研究了什么是 RPM 软件包][2]。它们是包含文件和元数据的档案文件。当安装或卸载 RPM 时,此元数据告诉 RPM 在哪里创建或删除文件。正如你将在上一篇文章中记住的,元数据还包含有关“依赖项”的信息,它可以是“运行时”或“构建时”的依赖信息。
|
||||
|
||||
例如,让我们来看看 `fpaste`。你可以使用 `dnf` 下载该 RPM。这将下载 Fedora 存储库中可用的 `fpaste` 最新版本。在 Fedora 30 上,当前版本为 0.3.9.2:
|
||||
|
||||
```
|
||||
$ dnf download fpaste
|
||||
|
||||
...
|
||||
fpaste-0.3.9.2-2.fc30.noarch.rpm
|
||||
```
|
||||
|
||||
由于这是个构建 RPM,因此它仅包含使用 `fpaste` 所需的文件:
|
||||
|
||||
```
|
||||
$ rpm -qpl ./fpaste-0.3.9.2-2.fc30.noarch.rpm
|
||||
/usr/bin/fpaste
|
||||
/usr/share/doc/fpaste
|
||||
/usr/share/doc/fpaste/README.rst
|
||||
/usr/share/doc/fpaste/TODO
|
||||
/usr/share/licenses/fpaste
|
||||
/usr/share/licenses/fpaste/COPYING
|
||||
/usr/share/man/man1/fpaste.1.gz
|
||||
```
|
||||
|
||||
### 源 RPM
|
||||
|
||||
在此链条中的下一个环节是源 RPM。Fedora 中的所有软件都必须从其源代码构建。我们不包括预构建的二进制文件。因此,要制作一个 RPM 文件,RPM(工具)需要:
|
||||
|
||||
* 给出必须要安装的文件,
|
||||
* 例如,如果要编译出这些文件,则告诉它们如何生成这些文件,
|
||||
* 告知必须在何处安装这些文件,
|
||||
* 该特定软件需要其他哪些依赖才能正常工作。
|
||||
|
||||
源 RPM 拥有所有这些信息。源 RPM 与构建 RPM 相似,但顾名思义,它们不包含已构建的二进制文件,而是包含某个软件的源文件。让我们下载 `fpaste` 的源 RPM:
|
||||
|
||||
```
|
||||
$ dnf download fpaste --source
|
||||
|
||||
...
|
||||
fpaste-0.3.9.2-2.fc30.src.rpm
|
||||
```
|
||||
|
||||
注意文件的结尾是 `src.rpm`。所有的 RPM 都是从源 RPM 构建的。你也可以使用 `dnf` 轻松检查“二进制” RPM 的源 RPM:
|
||||
|
||||
```
|
||||
$ dnf repoquery --qf "%{SOURCERPM}" fpaste
|
||||
fpaste-0.3.9.2-2.fc30.src.rpm
|
||||
```
|
||||
|
||||
另外,由于这是源 RPM,因此它不包含构建的文件。相反,它包含有关如何从中构建 RPM 的源代码和指令:
|
||||
|
||||
```
|
||||
$ rpm -qpl ./fpaste-0.3.9.2-2.fc30.src.rpm
|
||||
fpaste-0.3.9.2.tar.gz
|
||||
fpaste.spec
|
||||
```
|
||||
|
||||
这里,第一个文件只是 `fpaste` 的源代码。第二个是 spec 文件。spec 文件是个配方,可告诉 RPM(工具)如何使用源 RPM 中包含的源代码创建 RPM(档案文件)— 它包含 RPM(工具)构建 RPM(档案文件)所需的所有信息。在 spec 文件中。当我们软件包维护人员添加软件到 Fedora 中时,我们大部分时间都花在编写和完善 spec 文件上。当软件包需要更新时,我们会回过头来调整 spec 文件。你可以在 <https://src.fedoraproject.org/browse/projects/> 的源代码存储库中查看 Fedora 中所有软件包的 spec 文件。
|
||||
|
||||
请注意,一个源 RPM 可能包含构建多个 RPM 的说明。`fpaste` 是一款非常简单的软件,一个源 RPM 生成一个“二进制” RPM。而 Python 则更复杂。虽然只有一个源 RPM,但它会生成多个二进制 RPM:
|
||||
|
||||
```
|
||||
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3
|
||||
python3-3.7.3-1.fc30.src.rpm
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
|
||||
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-devel
|
||||
python3-3.7.3-1.fc30.src.rpm
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
|
||||
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-libs
|
||||
python3-3.7.3-1.fc30.src.rpm
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
|
||||
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-idle
|
||||
python3-3.7.3-1.fc30.src.rpm
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
|
||||
$ sudo dnf repoquery --qf "%{SOURCERPM}" python3-tkinter
|
||||
python3-3.7.3-1.fc30.src.rpm
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
```
|
||||
|
||||
用 RPM 行话来讲,“python3” 是“主包”,因此该 spec 文件将称为 `python3.spec`。所有其他软件包均为“子软件包”。你可以下载 python3 的源 RPM,并查看其中的内容。(提示:补丁也是源代码的一部分):
|
||||
|
||||
```
|
||||
$ dnf download --source python3
|
||||
python3-3.7.4-1.fc30.src.rpm
|
||||
|
||||
$ rpm -qpl ./python3-3.7.4-1.fc30.src.rpm
|
||||
00001-rpath.patch
|
||||
00102-lib64.patch
|
||||
00111-no-static-lib.patch
|
||||
00155-avoid-ctypes-thunks.patch
|
||||
00170-gc-assertions.patch
|
||||
00178-dont-duplicate-flags-in-sysconfig.patch
|
||||
00189-use-rpm-wheels.patch
|
||||
00205-make-libpl-respect-lib64.patch
|
||||
00251-change-user-install-location.patch
|
||||
00274-fix-arch-names.patch
|
||||
00316-mark-bdist_wininst-unsupported.patch
|
||||
Python-3.7.4.tar.xz
|
||||
check-pyc-timestamps.py
|
||||
idle3.appdata.xml
|
||||
idle3.desktop
|
||||
python3.spec
|
||||
```
|
||||
|
||||
### 从源 RPM 构建 RPM
|
||||
|
||||
现在我们有了源 RPM,并且其中有什么内容,我们可以从中重建 RPM。但是,在执行此操作之前,我们应该设置系统以构建 RPM。首先,我们安装必需的工具:
|
||||
|
||||
```
|
||||
$ sudo dnf install fedora-packager
|
||||
```
|
||||
|
||||
这将安装 `rpmbuild` 工具。`rpmbuild` 需要一个默认布局,以便它知道源 RPM 中每个必需组件的位置。让我们看看它们是什么:
|
||||
|
||||
```
|
||||
# spec 文件将出现在哪里?
|
||||
$ rpm -E %{_specdir}
|
||||
/home/asinha/rpmbuild/SPECS
|
||||
|
||||
# 源代码将出现在哪里?
|
||||
$ rpm -E %{_sourcedir}
|
||||
/home/asinha/rpmbuild/SOURCES
|
||||
|
||||
# 临时构建目录是哪里?
|
||||
$ rpm -E %{_builddir}
|
||||
/home/asinha/rpmbuild/BUILD
|
||||
|
||||
# 构建根目录是哪里?
|
||||
$ rpm -E %{_buildrootdir}
|
||||
/home/asinha/rpmbuild/BUILDROOT
|
||||
|
||||
# 源 RPM 将放在哪里?
|
||||
$ rpm -E %{_srcrpmdir}
|
||||
/home/asinha/rpmbuild/SRPMS
|
||||
|
||||
# 构建的 RPM 将放在哪里?
|
||||
$ rpm -E %{_rpmdir}
|
||||
/home/asinha/rpmbuild/RPMS
|
||||
```
|
||||
|
||||
我已经在系统上设置了所有这些目录:
|
||||
|
||||
```
|
||||
$ cd
|
||||
$ tree -L 1 rpmbuild/
|
||||
rpmbuild/
|
||||
├── BUILD
|
||||
├── BUILDROOT
|
||||
├── RPMS
|
||||
├── SOURCES
|
||||
├── SPECS
|
||||
└── SRPMS
|
||||
|
||||
6 directories, 0 files
|
||||
```
|
||||
|
||||
RPM 还提供了一个为你全部设置好的工具:
|
||||
|
||||
```
|
||||
$ rpmdev-setuptree
|
||||
```
|
||||
|
||||
然后,确保已安装 `fpaste` 的所有构建依赖项:
|
||||
|
||||
```
|
||||
sudo dnf builddep fpaste-0.3.9.2-3.fc30.src.rpm
|
||||
```
|
||||
|
||||
对于 `fpaste`,你只需要 Python,并且它肯定已经安装在你的系统上(`dnf` 也使用 Python)。还可以给 `builddep` 命令一个 spec 文件,而不是源 RPM。在手册页中了解更多信息:
|
||||
|
||||
```
|
||||
$ man dnf.plugin.builddep
|
||||
```
|
||||
|
||||
现在我们有了所需的一切,从源 RPM 构建一个 RPM 就像这样简单:
|
||||
|
||||
```
|
||||
$ rpmbuild --rebuild fpaste-0.3.9.2-3.fc30.src.rpm
|
||||
..
|
||||
..
|
||||
|
||||
$ tree ~/rpmbuild/RPMS/noarch/
|
||||
/home/asinha/rpmbuild/RPMS/noarch/
|
||||
└── fpaste-0.3.9.2-3.fc30.noarch.rpm
|
||||
|
||||
0 directories, 1 file
|
||||
```
|
||||
|
||||
`rpmbuild` 将安装源 RPM 并从中构建你的 RPM。现在,你可以使用 `dnf` 安装 RPM 以使用它。当然,如前所述,如果你想在 RPM 中进行任何更改,则必须修改 spec 文件,我们将在下一篇文章中介绍 spec 文件。
|
||||
|
||||
### 总结
|
||||
|
||||
总结一下这篇文章有两点:
|
||||
|
||||
* 我们通常安装使用的 RPM 是包含软件的构建版本的 “二进制” RPM
|
||||
* 构建 RPM 来自于源 RPM,源 RPM 包括用于生成二进制 RPM 所需的源代码和规范文件。
|
||||
|
||||
如果你想开始构建 RPM,并帮助 Fedora 社区维护我们提供的大量软件,则可以从这里开始: <https://fedoraproject.org/wiki/Join_the_package_collection_maintainers>
|
||||
|
||||
如有任何疑问,请发邮件到 [Fedora 开发人员邮件列表][3],我们随时乐意为你提供帮助!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/how-rpm-packages-are-made-the-source-rpm/
|
||||
|
||||
作者:[Ankur Sinha "FranciscoD"][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/ankursinha/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/06/rpm.png-816x345.jpg
|
||||
[2]: https://linux.cn/article-11452-1.html
|
||||
[3]: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/
|
||||
@@ -0,0 +1,84 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11529-1.html)
|
||||
[#]: subject: (Someone Forked GIMP into Glimpse Because Gimp is an Offensive Word)
|
||||
[#]: via: (https://itsfoss.com/gimp-fork-glimpse/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
由于 GIMP 是令人反感的字眼,有人将它复刻了
|
||||
======
|
||||
|
||||
在开源应用程序世界中,当社区成员希望以与其他人不同的方向来开发应用程序时,<ruby>复刻<rt>fork</rt></ruby>是很常见的。最新的具有新闻价值的一个复刻称为 [Glimpse][1],旨在解决用户在使用 <ruby>[GNU 图像处理程序][2]<rt>GNU Image Manipulation Program</rt></ruby>(通常称为 GIMP)时遇到的某些问题。
|
||||
|
||||
### 为什么创建 GIMP 的复刻?
|
||||
|
||||
![][3]
|
||||
|
||||
当你访问 Glimpse 应用的[主页][1]时,它表示该项目的目标是“尝试其他设计方向并修复长期存在的错误。”这听起来并不奇怪。但是,如果你开始阅读该项目的博客文章,则是另外一种印象。
|
||||
|
||||
根据该项目的[第一篇博客文章][4],他们创建了这个复刻是因为他们不喜欢 GIMP 这个名称。根据该帖子,“我们中的许多人不认为该软件的名称适用于所有用户,并且在拒绝该项目的 13 年后,我们决定复刻!”
|
||||
|
||||
如果你想知道为什么这些人认为 GIMP 令人讨厌,他们在[关于页面][5]中回答该问题:
|
||||
|
||||
> “如果英语不是你的母语,那么你可能没有意识到 ‘gimp’ 一词有问题。在某些国家,这被视为针对残疾人的侮辱和针对不受欢迎儿童的操场侮辱。它也可以与成年人同意的某些‘天黑后’活动联系起来。”
|
||||
|
||||
他们还指出,他们并没有使这一举动脱离政治正确或过于敏感。“除了可能给边缘化社区带来的痛苦外,我们当中许多人都有过倡导自由软件的故事,比如在 GNU 图像处理程序没有被专业环境中的老板或同事视为可选项这件事上。”
|
||||
|
||||
他们似乎在回答许多质疑,“不幸的是,我们不得不复刻整个项目来更改其名称,我们认为有关此问题的讨论陷入了僵局,而这是最积极的前进方向。 ”
|
||||
|
||||
看起来 Glimpse 这个名称不是确定不变的。他们的 GitHub 页面上有个关于可能选择其他名称的[提案][7]。也许他们应该放弃 GNU 这个词,我认为 IMP 这个词没有不好的含义。(LCTT 译注:反讽)
|
||||
|
||||
### 分叉之路
|
||||
|
||||
![GIMP 2.10][8]
|
||||
|
||||
[GIMP][6] 已经存在了 20 多年,因此任何形式的复刻都是一项艰巨的任务。当前,[他们正在计划][9]首先在 2019 年 9 月发布 Glimpse 0.1。这将是一个软复刻,这意味着在迁移到新身份时的更改将主要是装饰性的。(LCTT 译注:事实上到本译文发布时,该项目仍然处于蛋疼的 0.1 beta,也许 11 月,也许 12 月,才能发布 0.1 的正式版本。)
|
||||
|
||||
Glimpse 1.0 将是一个硬复刻,他们将积极更改代码库并将其添加到代码库中。他们想将 1.0 移植到 GTK3 并拥有自己的文档。他们估计,直到 2020 年 GIMP 3 发布之后才能做到。
|
||||
|
||||
除了 1.0,Glimpse 团队还计划打响自己的名声。他们计划进行“前端 UI 重写”。他们目前正在讨论[改用哪种语言][10]。D 和 Rust 似乎有很多支持者。随着时间的流逝,他们也[希望][4]“添加新功能以解决普通用户的抱怨”。
|
||||
|
||||
### 最后的思考
|
||||
|
||||
我过去曾经使用过一点 GIMP,但从来没有对它的名称感到困扰。老实说,我很长一段时间都不知道这意味着什么。有趣的是,当我在 Wikipedia 上搜索 GIMP 时,看到了一个 [GIMP 项目][11]的条目,这是纽约的一个现代舞蹈项目,其中包括残疾人。我想 gimp 并不是每个人视为一个贬低词汇的。
|
||||
|
||||
对我来说,更改名称似乎需要大量工作。似乎改写 UI 的想法会使项目看起来更有价值一些。我想知道他们是否会调整它以带来更经典的 UI,例如[使用 Ctrl + S 保存到 GIMP][12] / Glimpse。让我们拭目以待。
|
||||
|
||||
如果你对该项目感兴趣,可以在 [Twitter][14] 上关注他们,查看其 [GitHub 帐户][15],或查看其 [Patreon 页面][16]。
|
||||
|
||||
你觉得被 GIMP 名称冒犯了吗?你是否认为值得对应用程序进行复刻,以便你可以对其进行重命名?在下面的评论中让我们知道。
|
||||
|
||||
如果你觉得这篇文章有趣,请花一点时间在社交媒体、Hacker News 或 [Reddit][17] 上分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/gimp-fork-glimpse/
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://getglimpse.app/
|
||||
[2]: https://www.gimp.org/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/08/gimp-fork-glimpse.png?resize=800%2C450&ssl=1
|
||||
[4]: https://getglimpse.app/posts/so-it-begins/
|
||||
[5]: https://getglimpse.app/about/
|
||||
[6]: https://itsfoss.com/gimp-2-10-release/
|
||||
[7]: https://github.com/glimpse-editor/Glimpse/issues/92
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2018/08/gimp-screenshot.jpg?resize=800%2C508&ssl=1
|
||||
[9]: https://getglimpse.app/posts/six-week-checkpoint/
|
||||
[10]: https://github.com/glimpse-editor/Glimpse/issues/70
|
||||
[11]: https://en.wikipedia.org/wiki/The_Gimp_Project
|
||||
[12]: https://itsfoss.com/how-to-solve-gimp-2-8-does-not-save-in-jpeg-or-png-format/
|
||||
[13]: https://itsfoss.com/wps-office-2016-linux/
|
||||
[14]: https://twitter.com/glimpse_editor
|
||||
[15]: https://github.com/glimpse-editor/Glimpse
|
||||
[16]: https://www.patreon.com/glimpse
|
||||
[17]: https://reddit.com/r/linuxusersgroup
|
||||
289
published/20190902 How RPM packages are made- the spec file.md
Normal file
289
published/20190902 How RPM packages are made- the spec file.md
Normal file
@@ -0,0 +1,289 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11538-1.html)
|
||||
[#]: subject: (How RPM packages are made: the spec file)
|
||||
[#]: via: (https://fedoramagazine.org/how-rpm-packages-are-made-the-spec-file/)
|
||||
[#]: author: (Ankur Sinha "FranciscoD" https://fedoramagazine.org/author/ankursinha/)
|
||||
|
||||
如何编写 RPM 的 spec 文件
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
在[关于 RPM 软件包构建的上一篇文章][2]中,你了解到了源 RPM 包括软件的源代码以及 spec 文件。这篇文章深入研究了 spec 文件,该文件中包含了有关如何构建 RPM 的指令。同样,本文以 `fpaste` 为例。
|
||||
|
||||
### 了解源代码
|
||||
|
||||
在开始编写 spec 文件之前,你需要对要打包的软件有所了解。在这里,你正在研究 `fpaste`,这是一个非常简单的软件。它是用 Python 编写的,并且是一个单文件脚本。当它发布新版本时,可在 Pagure 上找到:<https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz>。
|
||||
|
||||
如该档案文件所示,当前版本为 0.3.9.2。下载它,以便你查看该档案文件中的内容:
|
||||
|
||||
```
|
||||
$ wget https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz
|
||||
$ tar -tvf fpaste-0.3.9.2.tar.gz
|
||||
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/
|
||||
-rw-rw-r-- root/root 25 2018-07-25 02:58 fpaste-0.3.9.2/.gitignore
|
||||
-rw-rw-r-- root/root 3672 2018-07-25 02:58 fpaste-0.3.9.2/CHANGELOG
|
||||
-rw-rw-r-- root/root 35147 2018-07-25 02:58 fpaste-0.3.9.2/COPYING
|
||||
-rw-rw-r-- root/root 444 2018-07-25 02:58 fpaste-0.3.9.2/Makefile
|
||||
-rw-rw-r-- root/root 1656 2018-07-25 02:58 fpaste-0.3.9.2/README.rst
|
||||
-rw-rw-r-- root/root 658 2018-07-25 02:58 fpaste-0.3.9.2/TODO
|
||||
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/
|
||||
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/
|
||||
drwxrwxr-x root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/en/
|
||||
-rw-rw-r-- root/root 3867 2018-07-25 02:58 fpaste-0.3.9.2/docs/man/en/fpaste.1
|
||||
-rwxrwxr-x root/root 24884 2018-07-25 02:58 fpaste-0.3.9.2/fpaste
|
||||
lrwxrwxrwx root/root 0 2018-07-25 02:58 fpaste-0.3.9.2/fpaste.py -> fpaste
|
||||
```
|
||||
|
||||
你要安装的文件是:
|
||||
|
||||
* `fpaste.py`:应该安装到 `/usr/bin/`。
|
||||
* `docs/man/en/fpaste.1`:手册,应放到 `/usr/share/man/man1/`。
|
||||
* `COPYING`:许可证文本,应放到 `/usr/share/license/fpaste/`。
|
||||
* `README.rst`、`TODO`:放到 `/usr/share/doc/fpaste/` 下的其它文档。
|
||||
|
||||
这些文件的安装位置取决于文件系统层次结构标准(FHS)。要了解更多信息,可以在这里阅读:<http://www.pathname.com/fhs/> 或查看 Fedora 系统的手册页:
|
||||
|
||||
```
|
||||
$ man hier
|
||||
```
|
||||
|
||||
#### 第一部分:要构建什么?
|
||||
|
||||
现在我们知道了源文件中有哪些文件,以及它们要存放的位置,让我们看一下 spec 文件。你可以在此处查看这个完整的文件:<https://src.fedoraproject.org/rpms/fpaste/blob/master/f/fpaste.spec>。
|
||||
|
||||
这是 spec 文件的第一部分:
|
||||
|
||||
```
|
||||
Name: fpaste
|
||||
Version: 0.3.9.2
|
||||
Release: 3%{?dist}
|
||||
Summary: A simple tool for pasting info onto sticky notes instances
|
||||
BuildArch: noarch
|
||||
License: GPLv3+
|
||||
URL: https://pagure.io/fpaste
|
||||
Source0: https://pagure.io/releases/fpaste/fpaste-0.3.9.2.tar.gz
|
||||
|
||||
Requires: python3
|
||||
|
||||
%description
|
||||
It is often useful to be able to easily paste text to the Fedora
|
||||
Pastebin at http://paste.fedoraproject.org and this simple script
|
||||
will do that and return the resulting URL so that people may
|
||||
examine the output. This can hopefully help folks who are for
|
||||
some reason stuck without X, working remotely, or any other
|
||||
reason they may be unable to paste something into the pastebin
|
||||
```
|
||||
|
||||
`Name`、`Version` 等称为*标签*,它们定义在 RPM 中。这意味着你不能只是随意写点标签,RPM 无法理解它们!需要注意的标签是:
|
||||
|
||||
* `Source0`:告诉 RPM 该软件的源代码档案文件所在的位置。
|
||||
* `Requires`:列出软件的运行时依赖项。RPM 可以自动检测很多依赖项,但是在某些情况下,必须手动指明它们。运行时依赖项是系统上必须具有的功能(通常是软件包),才能使该软件包起作用。这是 [dnf][3] 在安装此软件包时检测是否需要拉取其他软件包的方式。
|
||||
* `BuildRequires`:列出了此软件的构建时依赖项。这些通常必须手动确定并添加到 spec 文件中。
|
||||
* `BuildArch`:此软件为该计算机体系结构所构建。如果省略此标签,则将为所有受支持的体系结构构建该软件。值 `noarch` 表示该软件与体系结构无关(例如 `fpaste`,它完全是用 Python 编写的)。
|
||||
|
||||
本节提供有关 `fpaste` 的常规信息:它是什么,正在将什么版本制作为 RPM,其许可证等等。如果你已安装 `fpaste`,并查看其元数据时,则可以看到该 RPM 中包含的以下信息:
|
||||
|
||||
```
|
||||
$ sudo dnf install fpaste
|
||||
$ rpm -qi fpaste
|
||||
Name : fpaste
|
||||
Version : 0.3.9.2
|
||||
Release : 2.fc30
|
||||
...
|
||||
```
|
||||
|
||||
RPM 会自动添加一些其他标签,以代表它所知道的内容。
|
||||
|
||||
至此,我们掌握了要为其构建 RPM 的软件的一般信息。接下来,我们开始告诉 RPM 做什么。
|
||||
|
||||
#### 第二部分:准备构建
|
||||
|
||||
spec 文件的下一部分是准备部分,用 `%prep` 代表:
|
||||
|
||||
```
|
||||
%prep
|
||||
%autosetup
|
||||
```
|
||||
|
||||
对于 `fpaste`,这里唯一的命令是 `%autosetup`。这只是将 tar 档案文件提取到一个新文件夹中,并为下一部分的构建阶段做好了准备。你可以在此处执行更多操作,例如应用补丁程序,出于不同目的修改文件等等。如果你查看过 Python 的源 RPM 的内容,那么你会在那里看到许多补丁。这些都将在本节中应用。
|
||||
|
||||
通常,spec 文件中带有 `%` 前缀的所有内容都是 RPM 以特殊方式解释的宏或标签。这些通常会带有大括号,例如 `%{example}`。
|
||||
|
||||
#### 第三部分:构建软件
|
||||
|
||||
下一部分是构建软件的位置,用 `%build` 表示。现在,由于 `fpaste` 是一个简单的纯 Python 脚本,因此无需构建。因此,这里是:
|
||||
|
||||
```
|
||||
%build
|
||||
#nothing required
|
||||
```
|
||||
|
||||
不过,通常来说,你会在此处使用构建命令,例如:
|
||||
|
||||
```
|
||||
configure; make
|
||||
```
|
||||
|
||||
构建部分通常是 spec 文件中最难的部分,因为这是从源代码构建软件的地方。这要求你知道该工具使用的是哪个构建系统,该系统可能是许多构建系统之一:Autotools、CMake、Meson、Setuptools(用于 Python)等等。每个都有自己的命令和语法样式。你需要充分了解这些才能正确构建软件。
|
||||
|
||||
#### 第四部分:安装文件
|
||||
|
||||
软件构建后,需要在 `%install` 部分中安装它:
|
||||
|
||||
```
|
||||
%install
|
||||
mkdir -p %{buildroot}%{_bindir}
|
||||
make install BINDIR=%{buildroot}%{_bindir} MANDIR=%{buildroot}%{_mandir}
|
||||
```
|
||||
|
||||
在构建 RPM 时,RPM 不会修改你的系统文件。在一个可以正常运行的系统上添加、删除或修改文件的风险太大。如果发生故障怎么办?因此,RPM 会创建一个专门打造的文件系统并在其中工作。这称为 `buildroot`。 因此,在 `buildroot` 中,我们创建由宏 `%{_bindir}` 代表的 `/usr/bin` 目录,然后使用提供的 `Makefile` 将文件安装到其中。
|
||||
|
||||
至此,我们已经在专门打造的 `buildroot` 中安装了 `fpaste` 的构建版本。
|
||||
|
||||
#### 第五部分:列出所有要包括在 RPM 中的文件
|
||||
|
||||
spec 文件其后的一部分是文件部分:`%files`。在这里,我们告诉 RPM 从该 spec 文件创建的档案文件中包含哪些文件。`fpaste` 的文件部分非常简单:
|
||||
|
||||
```
|
||||
%files
|
||||
%{_bindir}/%{name}
|
||||
%doc README.rst TODO
|
||||
%{_mandir}/man1/%{name}.1.gz
|
||||
%license COPYING
|
||||
```
|
||||
|
||||
请注意,在这里,我们没有指定 `buildroot`。所有这些路径都是相对路径。`%doc` 和 `%license`命令做的稍微多一点,它们会创建所需的文件夹,并记住这些文件必须放在那里。
|
||||
|
||||
RPM 很聪明。例如,如果你在 `%install` 部分中安装了文件,但未列出它们,它会提醒你。
|
||||
|
||||
#### 第六部分:在变更日志中记录所有变更
|
||||
|
||||
Fedora 是一个基于社区的项目。许多贡献者维护或共同维护软件包。因此,当务之急是不要被软件包做了哪些更改所搞混。为了确保这一点,spec 文件包含的最后一部分是变更日志 `%changelog`:
|
||||
|
||||
```
|
||||
%changelog
|
||||
* Thu Jul 25 2019 Fedora Release Engineering < ...> - 0.3.9.2-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Thu Jan 31 2019 Fedora Release Engineering < ...> - 0.3.9.2-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Tue Jul 24 2018 Ankur Sinha - 0.3.9.2-1
|
||||
- Update to 0.3.9.2
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering < ...> - 0.3.9.1-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering < ..> - 0.3.9.1-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
* Sun Sep 10 2017 Vasiliy N. Glazov < ...> - 0.3.9.1-2
|
||||
- Cleanup spec
|
||||
|
||||
* Fri Sep 08 2017 Ankur Sinha - 0.3.9.1-1
|
||||
- Update to latest release
|
||||
- fixes rhbz 1489605
|
||||
...
|
||||
....
|
||||
```
|
||||
|
||||
spec 文件的*每项*变更都必须有一个变更日志条目。如你在此处看到的,虽然我以维护者身份更新了该 spec 文件,但其他人也做过更改。清楚地记录变更内容有助于所有人知道该 spec 文件的当前状态。对于系统上安装的所有软件包,都可以使用 `rpm` 来查看其更改日志:
|
||||
|
||||
```
|
||||
$ rpm -q --changelog fpaste
|
||||
```
|
||||
|
||||
### 构建 RPM
|
||||
|
||||
现在我们准备构建 RPM 包。如果要继续执行以下命令,请确保遵循[上一篇文章][2]中的步骤设置系统以构建 RPM。
|
||||
|
||||
我们将 `fpaste` 的 spec 文件放置在 `~/rpmbuild/SPECS` 中,将源代码档案文件存储在 `~/rpmbuild/SOURCES/` 中,现在可以创建源 RPM 了:
|
||||
|
||||
```
|
||||
$ cd ~/rpmbuild/SPECS
|
||||
$ wget https://src.fedoraproject.org/rpms/fpaste/raw/master/f/fpaste.spec
|
||||
|
||||
$ cd ~/rpmbuild/SOURCES
|
||||
$ wget https://pagure.io/fpaste/archive/0.3.9.2/fpaste-0.3.9.2.tar.gz
|
||||
|
||||
$ cd ~/rpmbuild/SOURCES
|
||||
$ rpmbuild -bs fpaste.spec
|
||||
Wrote: /home/asinha/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
|
||||
```
|
||||
|
||||
让我们看一下结果:
|
||||
|
||||
```
|
||||
$ ls ~/rpmbuild/SRPMS/fpaste*
|
||||
/home/asinha/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
|
||||
|
||||
$ rpm -qpl ~/rpmbuild/SRPMS/fpaste-0.3.9.2-3.fc30.src.rpm
|
||||
fpaste-0.3.9.2.tar.gz
|
||||
fpaste.spec
|
||||
```
|
||||
|
||||
我们看到源 RPM 已构建。让我们同时构建源 RPM 和二进制 RPM:
|
||||
|
||||
```
|
||||
$ cd ~/rpmbuild/SPECS
|
||||
$ rpmbuild -ba fpaste.spec
|
||||
..
|
||||
..
|
||||
..
|
||||
```
|
||||
|
||||
RPM 将向你显示完整的构建输出,并在我们之前看到的每个部分中详细说明它的工作。此“构建日志”非常重要。当构建未按预期进行时,我们的打包人员将花费大量时间来遍历它们,以跟踪完整的构建路径来查看出了什么问题。
|
||||
|
||||
就是这样!准备安装的 RPM 应该位于以下位置:
|
||||
|
||||
```
|
||||
$ ls ~/rpmbuild/RPMS/noarch/
|
||||
fpaste-0.3.9.2-3.fc30.noarch.rpm
|
||||
```
|
||||
|
||||
### 概括
|
||||
|
||||
我们已经介绍了如何从 spec 文件构建 RPM 的基础知识。这绝不是一份详尽的文档。实际上,它根本不是文档。它只是试图解释幕后的运作方式。简短回顾一下:
|
||||
|
||||
* RPM 有两种类型:源 RPM 和 二进制 RPM。
|
||||
* 二进制 RPM 包含要安装以使用该软件的文件。
|
||||
* 源 RPM 包含构建二进制 RPM 所需的信息:完整的源代码,以及 spec 文件中的有关如何构建 RPM 的说明。
|
||||
* spec 文件包含多个部分,每个部分都有其自己的用途。
|
||||
|
||||
在这里,我们已经在安装好的 Fedora 系统中本地构建了 RPM。虽然这是个基本的过程,但我们从存储库中获得的 RPM 是建立在具有严格配置和方法的专用服务器上的,以确保正确性和安全性。这个 Fedora 打包流程将在以后的文章中讨论。
|
||||
|
||||
你想开始构建软件包,并帮助 Fedora 社区维护我们提供的大量软件吗?你可以[从这里开始加入软件包集合维护者][4]。
|
||||
|
||||
如有任何疑问,请发布到 [Fedora 开发人员邮件列表][5],我们随时乐意为你提供帮助!
|
||||
|
||||
### 参考
|
||||
|
||||
这里有一些构建 RPM 的有用参考:
|
||||
|
||||
* <https://fedoraproject.org/wiki/How_to_create_an_RPM_package>
|
||||
* <https://docs.fedoraproject.org/en-US/quick-docs/create-hello-world-rpm/>
|
||||
* <https://docs.fedoraproject.org/en-US/packaging-guidelines/>
|
||||
* <https://rpm.org/documentation.html>
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/how-rpm-packages-are-made-the-spec-file/
|
||||
|
||||
作者:[Ankur Sinha "FranciscoD"][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/ankursinha/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/06/rpm.png-816x345.jpg
|
||||
[2]: https://linux.cn/article-11527-1.html
|
||||
[3]: https://fedoramagazine.org/managing-packages-fedora-dnf/
|
||||
[4]: https://fedoraproject.org/wiki/Join_the_package_collection_maintainers
|
||||
[5]: https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/
|
||||
246
published/20190905 Building CI-CD pipelines with Jenkins.md
Normal file
246
published/20190905 Building CI-CD pipelines with Jenkins.md
Normal file
@@ -0,0 +1,246 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11546-1.html)
|
||||
[#]: subject: (Building CI/CD pipelines with Jenkins)
|
||||
[#]: via: (https://opensource.com/article/19/9/intro-building-cicd-pipelines-jenkins)
|
||||
[#]: author: (Bryant Son https://opensource.com/users/brson)
|
||||
|
||||
用 Jenkins 构建 CI/CD 流水线
|
||||
======
|
||||
|
||||
> 通过这份 Jenkins 分步教程,构建持续集成和持续交付(CI/CD)流水线。
|
||||
|
||||

|
||||
|
||||
在我的文章《[使用开源工具构建 DevOps 流水线的初学者指南][2]》中,我分享了一个从头开始构建 DevOps 流水线的故事。推动该计划的核心技术是 [Jenkins][3],这是一个用于建立持续集成和持续交付(CI/CD)流水线的开源工具。
|
||||
|
||||
在花旗,有一个单独的团队为专用的 Jenkins 流水线提供稳定的主从节点环境,但是该环境仅用于质量保证(QA)、构建阶段和生产环境。开发环境仍然是非常手动的,我们的团队需要对其进行自动化以在加快开发工作的同时获得尽可能多的灵活性。这就是我们决定为 DevOps 建立 CI/CD 流水线的原因。Jenkins 的开源版本由于其灵活性、开放性、强大的插件功能和易用性而成为显而易见的选择。
|
||||
|
||||
在本文中,我将分步演示如何使用 Jenkins 构建 CI/CD 流水线。
|
||||
|
||||
### 什么是流水线?
|
||||
|
||||
在进入本教程之前,了解有关 CI/CD <ruby>流水线<rt>pipeline</rt></ruby>的知识会很有帮助。
|
||||
|
||||
首先,了解 Jenkins 本身并不是流水线这一点很有帮助。只是创建一个新的 Jenkins 作业并不能构建一条流水线。可以把 Jenkins 看做一个遥控器,在这里点击按钮即可。当你点击按钮时会发生什么取决于遥控器要控制的内容。Jenkins 为其他应用程序 API、软件库、构建工具等提供了一种插入 Jenkins 的方法,它可以执行并自动化任务。Jenkins 本身不执行任何功能,但是随着其它工具的插入而变得越来越强大。
|
||||
|
||||
流水线是一个单独的概念,指的是按顺序连接在一起的事件或作业组:
|
||||
|
||||
> “<ruby>流水线<rt>pipeline</rt></ruby>”是可以执行的一系列事件或作业。
|
||||
|
||||
理解流水线的最简单方法是可视化一系列阶段,如下所示:
|
||||
|
||||
![Pipeline example][4]
|
||||
|
||||
在这里,你应该看到两个熟悉的概念:<ruby>阶段<rt>Stage</rt></ruby>和<ruby>步骤<rt>Step</rt></ruby>。
|
||||
|
||||
* 阶段:一个包含一系列步骤的块。阶段块可以命名为任何名称;它用于可视化流水线过程。
|
||||
* 步骤:表明要做什么的任务。步骤定义在阶段块内。
|
||||
|
||||
在上面的示例图中,阶段 1 可以命名为 “构建”、“收集信息”或其它名称,其它阶段块也可以采用类似的思路。“步骤”只是简单地说放上要执行的内容,它可以是简单的打印命令(例如,`echo "Hello, World"`)、程序执行命令(例如,`java HelloWorld`)、shell 执行命令( 例如,`chmod 755 Hello`)或任何其他命令,只要通过 Jenkins 环境将其识别为可执行命令即可。
|
||||
|
||||
Jenkins 流水线以**编码脚本**的形式提供,通常称为 “Jenkinsfile”,尽管可以用不同的文件名。下面这是一个简单的 Jenkins 流水线文件的示例:
|
||||
|
||||
```
|
||||
// Example of Jenkins pipeline script
|
||||
|
||||
pipeline {
|
||||
stages {
|
||||
stage("Build") {
|
||||
steps {
|
||||
// Just print a Hello, Pipeline to the console
|
||||
echo "Hello, Pipeline!"
|
||||
// Compile a Java file. This requires JDKconfiguration from Jenkins
|
||||
javac HelloWorld.java
|
||||
// Execute the compiled Java binary called HelloWorld. This requires JDK configuration from Jenkins
|
||||
java HelloWorld
|
||||
// Executes the Apache Maven commands, clean then package. This requires Apache Maven configuration from Jenkins
|
||||
mvn clean package ./HelloPackage
|
||||
// List the files in current directory path by executing a default shell command
|
||||
sh "ls -ltr"
|
||||
}
|
||||
}
|
||||
// And next stages if you want to define further...
|
||||
} // End of stages
|
||||
} // End of pipeline
|
||||
```
|
||||
|
||||
从此示例脚本很容易看到 Jenkins 流水线的结构。请注意,默认情况下某些命令(如 `java`、`javac`和 `mvn`)不可用,需要通过 Jenkins 进行安装和配置。 因此:
|
||||
|
||||
> Jenkins 流水线是一种以定义的方式依次执行 Jenkins 作业的方法,方法是将其编码并在多个块中进行结构化,这些块可以包含多个任务的步骤。
|
||||
|
||||
好。既然你已经了解了 Jenkins 流水线是什么,我将向你展示如何创建和执行 Jenkins 流水线。在本教程的最后,你将建立一个 Jenkins 流水线,如下所示:
|
||||
|
||||
![Final Result][5]
|
||||
|
||||
### 如何构建 Jenkins 流水线
|
||||
|
||||
为了便于遵循本教程的步骤,我创建了一个示例 [GitHub 存储库][6]和一个视频教程。
|
||||
|
||||
- [视频](https://img.linux.net.cn/static/video/_-jDPwYgDVKlg.mp4)
|
||||
|
||||
开始本教程之前,你需要:
|
||||
|
||||
* Java 开发工具包(JDK):如果尚未安装,请安装 JDK 并将其添加到环境路径中,以便可以通过终端执行 Java 命令(如 `java jar`)。这是利用本教程中使用的 Java Web Archive(WAR)版本的 Jenkins 所必需的(尽管你可以使用任何其他发行版)。
|
||||
* 基本计算机操作能力:你应该知道如何键入一些代码、通过 shell 执行基本的 Linux 命令以及打开浏览器。
|
||||
|
||||
让我们开始吧。
|
||||
|
||||
#### 步骤一:下载 Jenkins
|
||||
|
||||
导航到 [Jenkins 下载页面][7]。向下滚动到 “Generic Java package (.war)”,然后单击下载文件;将其保存在易于找到的位置。(如果你选择其他 Jenkins 发行版,除了步骤二之外,本教程的其余步骤应该几乎相同。)使用 WAR 文件的原因是它是个一次性可执行文件,可以轻松地执行和删除。
|
||||
|
||||
![Download Jenkins as Java WAR file][8]
|
||||
|
||||
#### 步骤二:以 Java 二进制方式执行 Jenkins
|
||||
|
||||
打开一个终端窗口,并使用 `cd <your path>` 进入下载 Jenkins 的目录。(在继续之前,请确保已安装 JDK 并将其添加到环境路径。)执行以下命令,该命令将 WAR 文件作为可执行二进制文件运行:
|
||||
|
||||
```
|
||||
java -jar ./jenkins.war
|
||||
```
|
||||
|
||||
如果一切顺利,Jenkins 应该在默认端口 8080 上启动并运行。
|
||||
|
||||
![Execute as an executable JAR binary][9]
|
||||
|
||||
#### 步骤三:创建一个新的 Jenkins 作业
|
||||
|
||||
打开一个 Web 浏览器并导航到 `localhost:8080`。除非你有以前安装的 Jenkins,否则应直接转到 Jenkins 仪表板。点击 “Create New Jobs”。你也可以点击左侧的 “New Item”。
|
||||
|
||||
![Create New Job][10]
|
||||
|
||||
#### 步骤四:创建一个流水线作业
|
||||
|
||||
在此步骤中,你可以选择并定义要创建的 Jenkins 作业类型。选择 “Pipeline” 并为其命名(例如,“TestPipeline”)。单击 “OK” 创建流水线作业。
|
||||
|
||||
![Create New Pipeline Job][11]
|
||||
|
||||
你将看到一个 Jenkins 作业配置页面。向下滚动以找到 “Pipeline” 部分。有两种执行 Jenkins 流水线的方法。一种方法是在 Jenkins 上直接编写流水线脚本,另一种方法是从 SCM(源代码管理)中检索 Jenkins 文件。在接下来的两个步骤中,我们将体验这两种方式。
|
||||
|
||||
#### 步骤五:通过直接脚本配置并执行流水线作业
|
||||
|
||||
要使用直接脚本执行流水线,请首先从 GitHub 复制该 [Jenkinsfile 示例][6]的内容。选择 “Pipeline script” 作为 “Destination”,然后将该 Jenkinsfile 的内容粘贴到 “Script” 中。花一些时间研究一下 Jenkins 文件的结构。注意,共有三个阶段:Build、Test 和 Deploy,它们是任意的,可以是任何一个。每个阶段中都有一些步骤;在此示例中,它们只是打印一些随机消息。
|
||||
|
||||
单击 “Save” 以保留更改,这将自动将你带回到 “Job Overview” 页面。
|
||||
|
||||
![Configure to Run as Jenkins Script][12]
|
||||
|
||||
要开始构建流水线的过程,请单击 “Build Now”。如果一切正常,你将看到第一个流水线(如下面的这个)。
|
||||
|
||||
![Click Build Now and See Result][13]
|
||||
|
||||
要查看流水线脚本构建的输出,请单击任何阶段,然后单击 “Log”。你会看到这样的消息。
|
||||
|
||||
![Visit sample GitHub with Jenkins get clone link][14]
|
||||
|
||||
#### 步骤六:通过 SCM 配置并执行流水线作业
|
||||
|
||||
现在,换个方式:在此步骤中,你将通过从源代码控制的 GitHub 中复制 Jenkinsfile 来部署相同的 Jenkins 作业。在同一个 [GitHub 存储库][6]中,通过单击 “Clone or download” 并复制其 URL 来找到其存储库 URL。
|
||||
|
||||
![Checkout from GitHub][15]
|
||||
|
||||
单击 “Configure” 以修改现有作业。滚动到 “Advanced Project Options” 设置,但这一次,从 “Destination” 下拉列表中选择 “Pipeline script from SCM” 选项。将 GitHub 存储库的 URL 粘贴到 “Repository URL” 中,然后在 “Script Path” 中键入 “Jenkinsfile”。 单击 “Save” 按钮保存。
|
||||
|
||||
![Change to Pipeline script from SCM][16]
|
||||
|
||||
要构建流水线,回到 “Task Overview” 页面后,单击 “Build Now” 以再次执行作业。结果与之前相同,除了多了一个称为 “Declaration: Checkout SCM” 的阶段。
|
||||
|
||||
![Build again and verify][17]
|
||||
|
||||
要查看来自 SCM 构建的流水线的输出,请单击该阶段并查看 “Log” 以检查源代码控制克隆过程的进行情况。
|
||||
|
||||
![Verify Checkout Procedure][18]
|
||||
|
||||
### 除了打印消息,还能做更多
|
||||
|
||||
恭喜你!你已经建立了第一个 Jenkins 流水线!
|
||||
|
||||
“但是等等”,你说,“这太有限了。除了打印无用的消息外,我什么都做不了。”那没问题。到目前为止,本教程仅简要介绍了 Jenkins 流水线可以做什么,但是你可以通过将其与其他工具集成来扩展其功能。以下是给你的下一个项目的一些思路:
|
||||
|
||||
* 建立一个多阶段的 Java 构建流水线,从以下阶段开始:从 Nexus 或 Artifactory 之类的 JAR 存储库中拉取依赖项、编译 Java 代码、运行单元测试、打包为 JAR/WAR 文件,然后部署到云服务器。
|
||||
* 实现一个高级代码测试仪表板,该仪表板将基于 Selenium 的单元测试、负载测试和自动用户界面测试,报告项目的运行状况。
|
||||
* 构建多流水线或多用户流水线,以自动化执行 Ansible 剧本的任务,同时允许授权用户响应正在进行的任务。
|
||||
* 设计完整的端到端 DevOps 流水线,该流水线可提取存储在 SCM 中的基础设施资源文件和配置文件(例如 GitHub),并通过各种运行时程序执行该脚本。
|
||||
|
||||
学习本文结尾处的任何教程,以了解这些更高级的案例。
|
||||
|
||||
#### 管理 Jenkins
|
||||
|
||||
在 Jenkins 主面板,点击 “Manage Jenkins”。
|
||||
|
||||
![Manage Jenkins][19]
|
||||
|
||||
#### 全局工具配置
|
||||
|
||||
有许多可用工具,包括管理插件、查看系统日志等。单击 “Global Tool Configuration”。
|
||||
|
||||
![Global Tools Configuration][20]
|
||||
|
||||
#### 增加附加能力
|
||||
|
||||
在这里,你可以添加 JDK 路径、Git、Gradle 等。配置工具后,只需将该命令添加到 Jenkinsfile 中或通过 Jenkins 脚本执行即可。
|
||||
|
||||
![See Various Options for Plugin][21]
|
||||
|
||||
### 后继
|
||||
|
||||
本文为你介绍了使用酷炫的开源工具 Jenkins 创建 CI/CD 流水线的方法。要了解你可以使用 Jenkins 完成的许多其他操作,请在 Opensource.com 上查看以下其他文章:
|
||||
|
||||
* [Jenkins X 入门][22]
|
||||
* [使用 Jenkins 安装 OpenStack 云][23]
|
||||
* [在容器中运行 Jenkins][24]
|
||||
* [Jenkins 流水线入门][25]
|
||||
* [如何与 Jenkins 一起运行 JMeter][26]
|
||||
* [将 OpenStack 集成到你的 Jenkins 工作流中][27]
|
||||
|
||||
你可能对我为你的开源之旅而写的其他一些文章感兴趣:
|
||||
|
||||
* [9 个用于构建容错系统的开源工具][28]
|
||||
* [了解软件设计模式][29]
|
||||
* [使用开源工具构建 DevOps 流水线的初学者指南][2]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/intro-building-cicd-pipelines-jenkins
|
||||
|
||||
作者:[Bryant Son][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brson
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/pipe-pipeline-grid.png?itok=kkpzKxKg (pipelines)
|
||||
[2]: https://linux.cn/article-11307-1.html
|
||||
[3]: https://jenkins.io/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/diagrampipeline.jpg (Pipeline example)
|
||||
[5]: https://opensource.com/sites/default/files/uploads/0_endresultpreview_0.jpg (Final Result)
|
||||
[6]: https://github.com/bryantson/CICDPractice
|
||||
[7]: https://jenkins.io/download/
|
||||
[8]: https://opensource.com/sites/default/files/uploads/2_downloadwar.jpg (Download Jenkins as Java WAR file)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/3_runasjar.jpg (Execute as an executable JAR binary)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/4_createnewjob.jpg (Create New Job)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/5_createpipeline.jpg (Create New Pipeline Job)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/6_runaspipelinescript.jpg (Configure to Run as Jenkins Script)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/7_buildnow4script.jpg (Click Build Now and See Result)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/8_seeresult4script.jpg (Visit sample GitHub with Jenkins get clone link)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/9_checkoutfromgithub.jpg (Checkout from GitHub)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/10_runsasgit.jpg (Change to Pipeline script from SCM)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/11_seeresultfromgit.jpg (Build again and verify)
|
||||
[18]: https://opensource.com/sites/default/files/uploads/12_verifycheckout.jpg (Verify Checkout Procedure)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/13_managingjenkins.jpg (Manage Jenkins)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/14_globaltoolsconfiguration.jpg (Global Tools Configuration)
|
||||
[21]: https://opensource.com/sites/default/files/uploads/15_variousoptions4plugin.jpg (See Various Options for Plugin)
|
||||
[22]: https://opensource.com/article/18/11/getting-started-jenkins-x
|
||||
[23]: https://opensource.com/article/18/4/install-OpenStack-cloud-Jenkins
|
||||
[24]: https://linux.cn/article-9741-1.html
|
||||
[25]: https://opensource.com/article/18/4/jenkins-pipelines-with-cucumber
|
||||
[26]: https://opensource.com/life/16/7/running-jmeter-jenkins-continuous-delivery-101
|
||||
[27]: https://opensource.com/business/15/5/interview-maish-saidel-keesing-cisco
|
||||
[28]: https://opensource.com/article/19/3/tools-fault-tolerant-system
|
||||
[29]: https://opensource.com/article/19/7/understanding-software-design-patterns
|
||||
@@ -0,0 +1,214 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11554-1.html)
|
||||
[#]: subject: (6 Open Source Paint Applications for Linux Users)
|
||||
[#]: via: (https://itsfoss.com/open-source-paint-apps/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
6 款面向 Linux 用户的开源绘图应用程序
|
||||
======
|
||||
|
||||
小时候,当我开始使用计算机(在 Windows XP 中)时,我最喜欢的应用程序是微软的“画图”。我能在它上面涂鸦数个小时。出乎意料,孩子们仍然喜欢这个“画图”应用程序。不仅仅是孩子们,这个简单的“画图”应用程序,在很多情况下都能派上用场。
|
||||
|
||||
你可以找到一堆可以让你绘制/绘图或操作图片的应用程序。然而,其中一些是专有软件。既然你是一名 Linux 用户,为什么不关注一下开源绘图应用程序呢?
|
||||
|
||||
在这篇文章中,我们将列出一些最好的开源绘图应用程序,它们可以替代可用于 Linux 的专有绘画软件。
|
||||
|
||||
### 开源绘图 & 绘制应用程序
|
||||
|
||||
![][1]
|
||||
|
||||
**注意:** 该列表没有特别的排名顺序。
|
||||
|
||||
#### 1、Pinta
|
||||
|
||||
![][2]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* Paint.NET / 微软“画图”的极好替代品
|
||||
* 支持附加组件(有对 WebP 图像的支持)
|
||||
* 支持图层
|
||||
|
||||
[Pinta][3] 是一款令人赞叹的开源绘图应用程序,非常适合绘图和简单的图片编辑。换句话说,它是一款具有精美功能的简单绘图应用程序。
|
||||
|
||||
你可以将 [Pinta][4] 视为 Linux 上的“画图”的一个替代品,但是带有图层支持等等。不仅仅是“画图”,它也可以替代 Windows 上的 Paint.NET。尽管 Paint.NET 更好一些,但 Pinta 似乎是个不错的选择。
|
||||
|
||||
几个附加组件可以用于增强功能,例如[在 Linux 上支持 WebP 图像][5]。除了图层支持之外,你还可以轻松地调整图片大小、添加特效、进行调整(亮度、对比度等等),以及在导出图片时调整其质量。
|
||||
|
||||
##### 如何安装 Pinta ?
|
||||
|
||||
你应该能够在软件中心/应用程序中心/软件包管理器中简单地找到它。只需要输入 “Pinta”,并开始安装它。要么也可以尝试 [Flatpak][6] 软件包。
|
||||
|
||||
或者,你可以在终端中输入下面的命令(Ubuntu/Debian):
|
||||
|
||||
```
|
||||
sudo apt install pinta
|
||||
```
|
||||
|
||||
下载软件包和安装指南的更多信息,参考[官方下载页面][7]。
|
||||
|
||||
#### 2、Krita
|
||||
|
||||
![][8]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* HDR 绘图
|
||||
* 支持 PSD
|
||||
* 支持图层
|
||||
* 笔刷稳定器
|
||||
* 二维动画
|
||||
|
||||
Krita 是 Linux 上最高级的开源绘图应用程序之一。当然,对于本文而言,它可以帮助你绘制草图和在画布上胡写乱画。除此之外,它还提供很多功能。
|
||||
|
||||
例如,如果你的手有点颤抖,它可以帮助你稳定笔刷的笔划。你可以使用内置的矢量工具来创建漫画画板和其它有趣的东西。如果你正在寻找具有全面的颜色管理支持、绘图助理和图层管理的软件,Krita 应该是你最好的选择。
|
||||
|
||||
##### 如何安装 Krita ?
|
||||
|
||||
类似于 pinta,你可以在软件中心/应用程序中心或软件包管理器的列表中找到它。它也可以 [Flatpak 存储库][10]中找到。
|
||||
|
||||
考虑通过终端安装它?输入下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install krita
|
||||
```
|
||||
|
||||
要么你也可以前往它们的[官方下载页面][11]来获取 AppImage 文件并运行它。
|
||||
|
||||
如果你对 AppImage 文件一无所知,查看我们的指南 —— [如何使用 AppImage][12]。
|
||||
|
||||
#### 3、Tux Paint
|
||||
|
||||
![][13]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 给儿童用的一个简单直接的绘图应用程序
|
||||
|
||||
我不是开玩笑,对于 3-12 岁儿童来说,Tux Paint 是最好的开源绘图应用程序之一。当然,当你只想乱画时,那无需选择,所以,在这种情况下,Tux Paint 似乎是最好的选择(即使是成年人!)。
|
||||
|
||||
##### 如何安装 Tuxpaint ?
|
||||
|
||||
Tuxpaint 可以从软件中心或软件包管理器下载。无论哪种情况,在 Ubuntu/Debian 上安装它,在终端中输入下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install tuxpaint
|
||||
```
|
||||
|
||||
关于它的更多信息,前往[官方站点][14]。
|
||||
|
||||
#### 4、Drawpile
|
||||
|
||||
![][15]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 协同绘制
|
||||
* 内置聊天功能,可与其他用户互动
|
||||
* 图层支持
|
||||
* 记录绘制会话
|
||||
|
||||
Drawpile 是一个有趣的开源绘图应用程序,在该程序中,你可以与其他用户实时协作。确切地说,你们可以单个画布中同时绘制。除了这个独特的功能,它还有图层支持、记录绘制会话的能力,甚至还有与协作用户进行交互的聊天功能。
|
||||
|
||||
你可以主持或加入一个公共会话,或通过一个密码与你的朋友建立私有会话。默认情况下,服务器将是你的计算机,但是如果你需要远程服务器那也可以。
|
||||
|
||||
注意,你将需要[注册一个 Drawpile 账户][16] 才能进行协作。
|
||||
|
||||
##### 如何安装 Drawpile ?
|
||||
|
||||
据我所知,你只能在 [Flatpak 存储库][17]的列表中找到它。
|
||||
|
||||
#### 5、MyPaint
|
||||
|
||||
![][19]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 易用的数码画家工具
|
||||
* 支持图层管理
|
||||
* 很多微调你的画笔和绘制的选项
|
||||
|
||||
对于数码画家来说,[MyPaint][20] 是一个简单而强大的工具。它具有许多选项,可以调整以制作出完美的数字画笔笔触。我不是一个数字艺术家(但我是一个涂鸦者),但是我注意到有很多调整笔刷、颜色的选项,和一个添加中间结果暂存器面板的选项。
|
||||
|
||||
它也支持图层管理,也许你需要它。最新的稳定版本已经有几年没有更新了,但是当前的 alpha 构建版本(我测试过)运行良好。如果你正在 Linux 上寻找一个开源绘图应用程序 —— 试试这个。
|
||||
|
||||
##### 如何安装 MyPaint ?
|
||||
|
||||
MyPaint 可在官方存储库中获得。然而,这是老旧的版本。如果你仍然想继续,你可以在软件中心搜索它,或在终端中输入下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install mypaint
|
||||
```
|
||||
|
||||
你可以前往它的官方 [GitHub 发布页面][21]获取最新的 alpha 构建版本,获取 [AppImage 文件][12](任意版本)并使它可执行并启动应用程序。
|
||||
|
||||
#### 6、KolourPaint
|
||||
|
||||
![][22]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 一个 Linux 上的“画图”的简单替代品
|
||||
* 不支持图层管理
|
||||
|
||||
如果你不需要任何图层管理的支持,而只是想要一个开源绘图应用程序来绘制东西 —— 那就是它了。
|
||||
|
||||
[KolourPaint][23] 最初是为 KDE 桌面环境定制的,但是它在其它的桌面环境中也能完美地工作。
|
||||
|
||||
##### 如何安装 KolourPaint ?
|
||||
|
||||
你可以从软件中心安装 KolourPaint,或通过终端使用下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install kolourpaint4
|
||||
```
|
||||
|
||||
你总可以试试 [Flathub][24]。
|
||||
|
||||
### 总结
|
||||
|
||||
如果你在考虑如 GIMP/Inkscape 这样的应用程序,我们在另一篇关于[给数码艺术家的最好 Linux 工具][25]的文章中列出。如果你对更多的选择好奇,我建议你去查看它。
|
||||
|
||||
在这里,我们尝试编写一份 Linux 可用的最佳开源绘图应用程序列表。如果你认为我们错过一些东西,请在下面的评论区告诉我们!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/open-source-paint-apps/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/open-source-paint-apps.png?resize=800%2C450&ssl=1
|
||||
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/pinta.png?ssl=1
|
||||
[3]: https://pinta-project.com/pintaproject/pinta/
|
||||
[4]: https://itsfoss.com/pinta-1-6-ubuntu-linux-mint/
|
||||
[5]: https://itsfoss.com/webp-ubuntu-linux/
|
||||
[6]: https://www.flathub.org/apps/details/com.github.PintaProject.Pinta
|
||||
[7]: https://pinta-project.com/pintaproject/pinta/releases
|
||||
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/09/krita-paint.png?ssl=1
|
||||
[9]: https://itsfoss.com/things-to-do-after-installing-fedora-24/
|
||||
[10]: https://www.flathub.org/apps/details/org.kde.krita
|
||||
[11]: https://krita.org/en/download/krita-desktop/
|
||||
[12]: https://itsfoss.com/use-appimage-linux/
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/tux-paint.jpg?ssl=1
|
||||
[14]: http://www.tuxpaint.org/
|
||||
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/drawpile.png?ssl=1
|
||||
[16]: https://drawpile.net/accounts/signup/
|
||||
[17]: https://flathub.org/apps/details/net.drawpile.drawpile
|
||||
[18]: https://itsfoss.com/ocs-store/
|
||||
[19]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/09/mypaint.png?ssl=1
|
||||
[20]: https://mypaint.org/
|
||||
[21]: https://github.com/mypaint/mypaint/releases
|
||||
[22]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/09/kolourpaint.png?ssl=1
|
||||
[23]: http://kolourpaint.org/
|
||||
[24]: https://flathub.org/apps/details/org.kde.kolourpaint
|
||||
[25]: https://itsfoss.com/best-linux-graphic-design-software/
|
||||
@@ -0,0 +1,194 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11590-1.html)
|
||||
[#]: subject: (How to fix common pitfalls with the Python ORM tool SQLAlchemy)
|
||||
[#]: via: (https://opensource.com/article/19/9/common-pitfalls-python)
|
||||
[#]: author: (Zach Todd https://opensource.com/users/zchtoddhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/liranhaimovitchhttps://opensource.com/users/moshez)
|
||||
|
||||
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
|
||||
======
|
||||
|
||||
> 在使用 SQLAlchemy 时,那些看似很小的选择可能对这种对象关系映射工具包的性能产生重要影响。
|
||||
|
||||
![A python with a package.][1]
|
||||
|
||||
<ruby>对象关系映射<rt>Object-relational mapping</rt></ruby>([ORM][2])使应用程序开发人员的工作更轻松,在很大程度是因为它允许你使用你可能知道的语言(例如 Python)与数据库交互,而不是使用原始 SQL 语句查询。[SQLAlchemy][3] 是一个 Python ORM 工具包,它提供使用 Python 访问 SQL 数据库的功能。它是一个成熟的 ORM 工具,增加了模型关系、强大的查询构造范式、简单的序列化等优点。然而,它的易用性使得人们很容易忘记其背后发生了什么。使用 SQLAlchemy 时做出的看似很小的选择可能产生非常大的性能影响。
|
||||
|
||||
本文解释了开发人员在使用 SQLAlchemy 时遇到的一些最重要的性能问题,以及如何解决这些问题。
|
||||
|
||||
### 只需要计数但检索整个结果集
|
||||
|
||||
有时开发人员只需要一个结果计数,但是没有使用数据库计数功能,而是获取了所有结果,然后使用 Python 中的 `len` 完成计数。
|
||||
|
||||
```
|
||||
count = len(User.query.filter_by(acct_active=True).all())
|
||||
```
|
||||
|
||||
相反,使用 SQLAlchemy 的 `count` 方法将在服务器端执行计数,从而减少发送到客户端的数据。在前面的例子中调用 `all()` 也会导致模型对象的实例化,如果有很多数据,那么时间代价可能会非常昂贵。
|
||||
|
||||
除非还需要做其他的事情,否则只需使用 `count` 方法:
|
||||
|
||||
```
|
||||
count = User.query.filter_by(acct_active=True).count()
|
||||
```
|
||||
|
||||
### 只需要几列时检索整个模型
|
||||
|
||||
在许多情况下,发出查询时只需要几列数据。SQLAlchemy 可以只获取你想要的列,而不是返回整个模型实例。这不仅减少了发送的数据量,还避免了实例化整个对象。使用列数据的元组而不是模型可以快得多。
|
||||
|
||||
```
|
||||
result = User.query.all()
|
||||
for user in result:
|
||||
print(user.name, user.email)
|
||||
```
|
||||
|
||||
反之,使用 `with_entities` 方法只选择所需要的内容:
|
||||
|
||||
```
|
||||
result = User.query.with_entities(User.name, User.email).all()
|
||||
for (username, email) in result:
|
||||
print(username, email)
|
||||
```
|
||||
|
||||
### 每次循环都更新一个对象
|
||||
|
||||
避免使用循环来单独更新集合。虽然数据库可以非常快地执行单个更新,但应用程序和数据库服务器之间的往返时间将快速累加。通常,在合理的情况下争取更少的查询。
|
||||
|
||||
```
|
||||
for user in users_to_update:
|
||||
user.acct_active = True
|
||||
db.session.add(user)
|
||||
```
|
||||
|
||||
改用批量更新方法:
|
||||
|
||||
```
|
||||
query = User.query.filter(user.id.in_([user.id for user in users_to_update]))
|
||||
query.update({"acct_active": True}, synchronize_session=False)
|
||||
```
|
||||
|
||||
### 触发级联删除
|
||||
|
||||
ORM 允许在模型关系上进行简单的配置,但是有一些微妙的行为可能会令人吃惊。大多数数据库通过外键和各种级联选项维护关系完整性。SQLAlchemy 允许你使用外键和级联选项定义模型,但是 ORM 具有自己的级联逻辑,可以取代数据库。
|
||||
|
||||
考虑以下模型:
|
||||
|
||||
```
|
||||
class Artist(Base):
|
||||
__tablename__ = "artist"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
songs = relationship("Song", cascade="all, delete")
|
||||
|
||||
|
||||
class Song(Base):
|
||||
__tablename__ = "song"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
artist_id = Column(Integer, ForeignKey("artist.id", ondelete="CASCADE"))
|
||||
```
|
||||
|
||||
删除歌手将导致 ORM 在 `song` 表上发出 `delete` 查询,从而防止由于外键导致的删除操作。这种行为可能会成为复杂关系和大量记录的瓶颈。
|
||||
|
||||
请包含 `passive_deletes` 选项,以确保让数据库来管理关系。但是,请确保你的数据库具有此功能。例如,SQLite 默认情况下不管理外键。
|
||||
|
||||
```
|
||||
songs = relationship("Song", cascade all, delete", passive_deletes=True)
|
||||
```
|
||||
|
||||
### 当要使用贪婪加载时,应使用延迟加载
|
||||
|
||||
延迟加载是 SQLAlchemy 处理关系的默认方法。从上一个例子构建来看,加载一个歌手时不会同时加载他或她的歌曲。这通常是一个好主意,但是如果总是需要加载某些关系,单独的查询可能会造成浪费。
|
||||
|
||||
如果允许以延迟方式加载关系,像 [Marshmallow][4] 这样流行的序列化框架可以触发级联查询。
|
||||
|
||||
有几种方法可以控制此行为。最简单的方法是通过 relationship 函数本身。
|
||||
|
||||
```
|
||||
songs = relationship("Song", lazy="joined", cascade="all, delete")
|
||||
```
|
||||
|
||||
这将导致一个左连接被添加到任何歌手的查询中,因此,`songs` 集合将立即可用。尽管有更多数据返回给客户端,但往返次数可能会少得多。
|
||||
|
||||
SQLAlchemy 为无法采用这种综合方法的情况提供了更细粒度的控制,可以使用 `joinedload()` 函数在每个查询的基础上切换连接的加载。
|
||||
|
||||
```
|
||||
from sqlalchemy.orm import joinedload
|
||||
|
||||
artists = Artist.query.options(joinedload(Artist.songs))
|
||||
print(artists.songs) # Does not incur a roundtrip to load
|
||||
```
|
||||
|
||||
### 使用 ORM 进行批量记录导入
|
||||
|
||||
导入成千上万条记录时,构建完整模型实例的开销会成为主要瓶颈。想象一下,从一个文件中加载数千首歌曲记录,其中每首歌曲都先被转换为字典。
|
||||
|
||||
```
|
||||
for song in songs:
|
||||
db.session.add(Song(`song))
|
||||
```
|
||||
|
||||
相反,绕过 ORM,只使用核心的 SQLAlchemy 参数绑定功能。
|
||||
|
||||
```
|
||||
batch = []
|
||||
insert_stmt = Song.__table__.insert()
|
||||
for song in songs:
|
||||
if len(batch) > 1000:
|
||||
db.session.execute(insert_stmt, batch)
|
||||
batch.clear()
|
||||
batch.append(song)
|
||||
if batch:
|
||||
db.session.execute(insert_stmt, batch)
|
||||
```
|
||||
|
||||
请记住,此方法会自然而然地跳过你可能依赖的任何客户端 ORM 逻辑,例如基于 Python 的列默认值。尽管此方法比将对象加载为完整的模型实例要快,但是你的数据库可能具有更快的批量加载方法。例如,PostgreSQL 的 `COPY` 命令为加载大量记录提供了最佳性能。
|
||||
|
||||
### 过早调用提交或刷新
|
||||
|
||||
在很多情况下,你需要将子记录与其父记录相关联,反之亦然。一种显然的方法是刷新会话,以便为有问题的记录分配一个 ID。
|
||||
|
||||
```
|
||||
artist = Artist(name="Bob Dylan")
|
||||
song = Song(title="Mr. Tambourine Man")
|
||||
|
||||
db.session.add(artist)
|
||||
db.session.flush()
|
||||
|
||||
song.artist_id = artist.id
|
||||
```
|
||||
|
||||
对于每个请求,多次提交或刷新通常是不必要的,也是不可取的。数据库刷新涉及强制在数据库服务器上进行磁盘写入,在大多数情况下,客户端将阻塞,直到服务器确认已写入数据为止。
|
||||
|
||||
SQLAlchemy 可以在幕后跟踪关系和管理相关键。
|
||||
|
||||
```
|
||||
artist = Artist(name="Bob Dylan")
|
||||
song = Song(title="Mr. Tambourine Man")
|
||||
|
||||
artist.songs.append(song)
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
我希望这一系列常见的陷阱可以帮助你避免这些问题,并使你的应用平稳运行。通常,在诊断性能问题时,测量是关键。大多数数据库都提供性能诊断功能,可以帮助你定位问题,例如 PostgreSQL 的 `pg_stat_statements` 模块。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/common-pitfalls-python
|
||||
|
||||
作者:[Zach Todd][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/zchtoddhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/liranhaimovitchhttps://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python_snake_file_box.jpg?itok=UuDVFLX- (A python with a package.)
|
||||
[2]: https://en.wikipedia.org/wiki/Object-relational_mapping
|
||||
[3]: https://www.sqlalchemy.org/
|
||||
[4]: https://marshmallow.readthedocs.io/en/stable/
|
||||
@@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11523-1.html)
|
||||
[#]: subject: (10 Ways to Customize Your Linux Desktop With GNOME Tweaks Tool)
|
||||
[#]: via: (https://itsfoss.com/gnome-tweak-tool/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
@@ -10,7 +10,8 @@
|
||||
使用 GNOME 优化工具自定义 Linux 桌面的 10 种方法
|
||||
======
|
||||
|
||||
![GNOME Tweak Tool Icon][1]
|
||||
|
||||
![][7]
|
||||
|
||||
你可以通过多种方法来调整 Ubuntu,以自定义其外观和行为。我发现最简单的方法是使用 [GNOME 优化工具][2]。它也被称为 GNOME Tweak 或简单地称为 Tweak(优化)。
|
||||
|
||||
@@ -20,11 +21,11 @@
|
||||
|
||||
### 在 Ubuntu 18.04 或其它版本上安装 GNOME 优化工具
|
||||
|
||||
Gnome 优化工具可从 [Ubuntu 中的 Universe 存储库][3]中安装,因此请确保已在“软件和更新”工具中启用了该工具:
|
||||
GNOME 优化工具可从 [Ubuntu 中的 Universe 存储库][3]中安装,因此请确保已在“软件和更新”工具中启用了该仓库:
|
||||
|
||||
![在 Ubuntu 中启用 Universe 存储库][4]
|
||||
|
||||
之后,你可以从软件中心安装 GNOME 优化工具。只需打开软件中心并搜索 “GNOME Tweaks”并从那里安装它:
|
||||
之后,你可以从软件中心安装 GNOME 优化工具。只需打开软件中心并搜索 “GNOME Tweaks” 并从那里安装它:
|
||||
|
||||
![从软件中心安装 GNOME 优化工具][5]
|
||||
|
||||
@@ -36,45 +37,43 @@ sudo apt install gnome-tweaks
|
||||
|
||||
### 用优化工具定制 GNOME 桌面
|
||||
|
||||
![][7]
|
||||
|
||||
GNOME 优化工具使你可以进行许多设置更改。其中的某些更改(例如墙纸更改、启动应用程序等)也可以在官方的“系统设置”工具中找到。我将重点介绍默认情况下“设置”中不可用的优化。
|
||||
|
||||
#### 1、改变主题
|
||||
|
||||
你可以通过各种方式[在 Ubuntu 中安装新主题][8]。但是,如果要更改为新安装的主题,则必须安装GNOME 优化工具。
|
||||
|
||||
你可以在外观部分找到主题和图标设置。你可以浏览可用的主题和图标并设置所需的主题和图标。更改将立即生效。
|
||||
你可以在“<ruby>外观<rt>Appearance</rt></ruby>”部分找到主题和图标设置。你可以浏览可用的主题和图标并设置你喜欢的主题和图标。更改将立即生效。
|
||||
|
||||
![通过 GNOME 优化更改主题][9]
|
||||
|
||||
#### 2\、禁用动画以提速你的桌面体验
|
||||
#### 2、禁用动画以提速你的桌面体验
|
||||
|
||||
应用程序窗口的打开、关闭、最大化等都有一些细微的动画。你可以禁用这些动画以稍微加快系统的速度,因为它会使用较少的资源。
|
||||
应用程序窗口的打开、关闭、最大化等操作都有一些细微的动画。你可以禁用这些动画以稍微加快系统的速度,因为它会稍微使用一点资源。
|
||||
|
||||
![禁用动画以获得稍快的桌面体验][10]
|
||||
|
||||
#### 3、控制桌面图标
|
||||
|
||||
至少在 Ubuntu 中,你会在桌面上看到“主目录”和“垃圾箱”图标。如果你不喜欢,可以选择禁用它。你还可以选择要在桌面上显示的图标。
|
||||
至少在 Ubuntu 中,你会在桌面上看到“<ruby>家目录<rt>Home</rt></ruby>”和“<ruby>垃圾箱<rt>Trash</rt></ruby>”图标。如果你不喜欢,可以选择禁用它。你还可以选择要在桌面上显示的图标。
|
||||
|
||||
![在 Ubuntu 中控制桌面图标][11]
|
||||
|
||||
#### 4、管理 GNOME 扩展
|
||||
|
||||
我想可能知道 [GNOME 扩展][12]。这些是用于桌面的小型“插件”,可扩展 GNOME 桌面的功能。有[大量的 GNOME 扩展][13],可用于在顶部面板中查看 CPU 消耗、获取剪贴板历史记录等。
|
||||
我想你可能知道 [GNOME 扩展][12]。这些是用于桌面的小型“插件”,可扩展 GNOME 桌面的功能。有[大量的 GNOME 扩展][13],可用于在顶部面板中查看 CPU 消耗、获取剪贴板历史记录等等。
|
||||
|
||||
我已经写了一篇[安装和使用 GNOME 扩展][14]的详细文章。在这里,我假设你已经在使用它们,如果是这种情况,那么可以从 GNOME 优化工具中对其进行管理。
|
||||
我已经写了一篇[安装和使用 GNOME 扩展][14]的详细文章。在这里,我假设你已经在使用它们,如果是这样,可以从 GNOME 优化工具中对其进行管理。
|
||||
|
||||
![管理 GNOME 扩展][15]
|
||||
|
||||
#### 5、改变字体和缩放比例
|
||||
|
||||
你可以[在 Ubuntu 中安装新字体][16],并使用优化工具在系统范围应用字体更改。如果你认为桌面上的图标和文本太小,也可以更改缩放比例。
|
||||
你可以[在 Ubuntu 中安装新字体][16],并使用这个优化工具在系统范围应用字体更改。如果你认为桌面上的图标和文本太小,也可以更改缩放比例。
|
||||
|
||||
![更改字体和缩放比例][17]
|
||||
|
||||
#### 6、控制触摸板行为,例如在键入时禁用触摸板,右键单击触摸板即可正常工作
|
||||
#### 6、控制触摸板行为,例如在键入时禁用触摸板,使触摸板右键单击可以工作
|
||||
|
||||
GNOME 优化工具还允许你在键入时禁用触摸板。如果你在笔记本电脑上快速键入,这将很有用。手掌底部可能会触摸触摸板,并导致光标移至屏幕上不需要的位置。
|
||||
|
||||
@@ -84,35 +83,35 @@ GNOME 优化工具还允许你在键入时禁用触摸板。如果你在笔记
|
||||
|
||||
你还会注意到[当你按下触摸板的右下角以进行右键单击时,什么也没有发生][19]。你的触摸板并没有问题。这是一项系统设置,可对没有实体右键按钮的任何触摸板(例如旧的 Thinkpad 笔记本电脑)禁用这种右键单击功能。两指点击可为你提供右键单击操作。
|
||||
|
||||
你也可以通过在“鼠标单击模拟”下的“区域”中而不是“手指”中找到它。
|
||||
你也可以通过在“<ruby>鼠标单击模拟<rt>Mouse Click Simulation</rt></ruby>”下设置为“<ruby>区域<rt>Area</rt></ruby>”中而不是“<ruby>手指<rt>Fingers</rt></ruby>”来找回这项功能。
|
||||
|
||||
![修复右键单击问题][20]
|
||||
|
||||
你可能必须[重新启动 Ubuntu][21] 才能生效。如果你是 Emacs 爱好者,还可以从 Emacs 强制进行键盘绑定。
|
||||
你可能必须[重新启动 Ubuntu][21] 来使这项更改生效。如果你是 Emacs 爱好者,还可以强制使用 Emacs 键盘绑定。
|
||||
|
||||
#### 7、改变电源设置
|
||||
|
||||
电源这里只有一个设置。盖上盖子后,你可以将笔记本电脑置于挂起模式。
|
||||
电源这里只有一个设置。它可以让你在盖上盖子后将笔记本电脑置于挂起模式。
|
||||
|
||||
![GNOME 优化工具中的电源设置][22]
|
||||
|
||||
#### 8、决定什么显示在顶部面板
|
||||
|
||||
桌面的顶部面板显示了一些重要的信息。在这里有日历、网络图标、系统设置和“活动”选项。
|
||||
桌面的顶部面板显示了一些重要的信息。在这里有日历、网络图标、系统设置和“<ruby>活动<rt>Activities</rt></ruby>”选项。
|
||||
|
||||
你还可以[显示电池百分比][23]、添加日期以及日期和时间,并显示星期数。你还可以启用鼠标热点,以便将鼠标移至屏幕的左上角时可以获得所有正在运行的应用程序的活动视图。
|
||||
你还可以[显示电池百分比][23]、添加日期及时间,并显示星期数。你还可以启用鼠标热角,以便将鼠标移至屏幕的左上角时可以获得所有正在运行的应用程序的活动视图。
|
||||
|
||||
![GNOME 优化工具中的顶部面板设置][24]
|
||||
|
||||
如果将鼠标将焦点放在应用程序窗口上,则会注意到其菜单显示在顶部面板中。如果你不喜欢这样,可以将其关闭,然后应用程序菜单将显示应用程序本身。
|
||||
如果将鼠标焦点放在应用程序窗口上,你会注意到其菜单显示在顶部面板中。如果你不喜欢这样,可以将其关闭,然后应用程序菜单将显示应用程序本身。
|
||||
|
||||
#### 9、配置应用窗口
|
||||
|
||||
你可以决定是否在应用程序窗口中显示最大化和最小化选项(右上角的按钮)。你也可以在左右两边改变它们的位置。
|
||||
你可以决定是否在应用程序窗口中显示最大化和最小化选项(右上角的按钮)。你也可以改变它们的位置到左边或右边。
|
||||
|
||||
![应用程序窗口配置][25]
|
||||
|
||||
还有其他一些配置选项。我不使用它们,但你可以自行探索。
|
||||
这里还有其他一些配置选项。我不使用它们,但你可以自行探索。
|
||||
|
||||
#### 10、配置工作区
|
||||
|
||||
@@ -122,7 +121,7 @@ GNOME 优化工具还允许你围绕工作区配置一些内容。
|
||||
|
||||
### 总结
|
||||
|
||||
对于任何 GNOME 用户,GNOME 优化(Tweaks)工具都是必备工具。它可以帮助你配置桌面的外观和功能。 我感到惊讶的是,该工具甚至没有出现在 Ubuntu 的主存储库中。我认为应该默认安装它,要不,你将需得在 Ubuntu 中手动安装 GNOME 优化工具。
|
||||
对于任何 GNOME 用户,GNOME 优化(Tweaks)工具都是必备工具。它可以帮助你配置桌面的外观和功能。 我感到惊讶的是,该工具甚至没有出现在 Ubuntu 的主存储库中。我认为应该默认安装它,要不,你就得在 Ubuntu 中手动安装 GNOME 优化工具。
|
||||
|
||||
如果你在 GNOME 优化工具中发现了一些此处没有讨论的隐藏技巧,为什么不与大家分享呢?
|
||||
|
||||
@@ -133,7 +132,7 @@ via: https://itsfoss.com/gnome-tweak-tool/
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11522-1.html)
|
||||
[#]: subject: (Fedora 31 is officially here!)
|
||||
[#]: via: (https://fedoramagazine.org/announcing-fedora-31/)
|
||||
[#]: author: (Matthew Miller https://fedoramagazine.org/author/mattdm/)
|
||||
215
published/20191007 7 Java tips for new developers.md
Normal file
215
published/20191007 7 Java tips for new developers.md
Normal file
@@ -0,0 +1,215 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11620-1.html)
|
||||
[#]: subject: (7 Java tips for new developers)
|
||||
[#]: via: (https://opensource.com/article/19/10/java-basics)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
给新手 Java 开发者的 7 点提示
|
||||
======
|
||||
|
||||
> 如果你才刚开始学习 Java 编程,这里有七个你需要知道的基础知识。
|
||||
|
||||

|
||||
|
||||
Java 是一个多功能的编程语言,在某种程度上,它用在几乎所有可能涉及计算机的行业了里。Java 的最大优势是,它运行在一个 Java 虚拟机(JVM)中,这是一个翻译 Java 代码为与操作系统兼容的字节码的层。只要有 JVM 存在于你的操作系统上 —— 不管这个操作系统是在一个服务器(或“[无服务器][2]”,也是同样的)、桌面电脑、笔记本电脑、移动设备,或嵌入式设备 —— 那么,Java 应用程序就可以运行在它上面。
|
||||
|
||||
这使得 Java 成为程序员和用户的一种流行语言。程序员知道,他们只需要写一个软件版本就能最终得到一个可以运行在任何平台上的应用程序;用户知道,应用程序可以运行在他们的计算机上,而不用管他们使用的是什么样的操作系统。
|
||||
|
||||
很多语言和框架是跨平台的,但是没有实现同样的抽象层。使用 Java,你针对的是 JVM,而不是操作系统。对于程序员,当面对一些编程难题时,这是阻力最小的线路,但是它仅在当你知道如何编程 Java 时有用。如果你刚开始学习 Java 编程,这里有你需要知道的七个基础的提示。
|
||||
|
||||
但是,首先,如果你不确定是否你安装了 Java ,你可以在一个终端(例如 [Bash][3] 或 [PowerShell][4])中找出来,通过运行:
|
||||
|
||||
```
|
||||
$ java --version
|
||||
openjdk 12.0.2 2019-07-16
|
||||
OpenJDK Runtime Environment 19.3 (build 12.0.2+9)
|
||||
OpenJDK 64-Bit Server VM 19.3 (build 12.0.2+9, mixed mode, sharing)
|
||||
```
|
||||
|
||||
如果你得到一个错误,或未返回任何东西,那么你应该安装 [Java 开发套件][5](JDK)来开始 Java 开发。或者,安装一个 Java 运行时环境(JRE),如果你只是需要来运行 Java 应用程序。
|
||||
|
||||
### 1、Java 软件包
|
||||
|
||||
在 Java 语言中,相关的类被分组到一个*软件包*中。当你下载 JDK 时所获得的 Java 基础库将被分组到以 `java` 或 `javax` 开头的软件包中。软件包提供一种类似于计算机上的文件夹的功能:它们为相关的元素提供结构和定义(以编程术语说,*命名空间*)。额外的软件包可以从独立开发者、开源项目和商业供应商获得,就像可以为任何编程语言获得库一样。
|
||||
|
||||
当你写一个 Java 程序时,你应该在你的代码是顶部声明一个软件包名称。如果你只是编写一个简单的应用程序来入门 Java,你的软件包名称可以简单地用你的项目名称。如果你正在使用一个 Java 集成开发环境,如 [Eclipse][6],当你启动一个新的项目时,它为你生成一个合乎情理的软件包名称。
|
||||
|
||||
```
|
||||
package helloworld;
|
||||
|
||||
/**
|
||||
* @author seth
|
||||
* An application written in Java.
|
||||
*/
|
||||
```
|
||||
|
||||
除此之外,你可以通过查找它相对于你的项目整体的路径来确定你的软件包名称。例如,如果你正在写一组类来帮助游戏开发,并且该集合被称为 `jgamer`,那么你可能在其中有一些唯一的类。
|
||||
|
||||
```
|
||||
package jgamer.avatar;
|
||||
|
||||
/**
|
||||
* @author seth
|
||||
* An imaginary game library.
|
||||
*/
|
||||
```
|
||||
|
||||
你的软件包的顶层是 `jgamer`,并且在其内部中每个软件包都是一个独立的派生物,例如 `jgamer.avatar` 和 `jgamer.score` 等等。在你的文件系统里,其目录结构反映了这一点,`jgamer` 是包含文件 `avatar.java` 和 `score.java` 的顶级目录。
|
||||
|
||||
### 2、Java 导入
|
||||
|
||||
作为一名通晓多种语言的程序员,最大的乐趣是找出是否用 `include`、`import`、`use`、`require`,或一些其它术语来引入你不管使用何种编程语言编写的库。在 Java 中,顺便说一句,当导入你的代码的需要的库时,使用 `import` 关键字。
|
||||
|
||||
```
|
||||
package helloworld;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* @author seth
|
||||
* A GUI hello world.
|
||||
*/
|
||||
```
|
||||
|
||||
导入是基于该环境的 Java 路径。如果 Java 不知道 Java 库存储在系统上的何处,那么,就不能成功导入。只要一个库被存储在系统的 Java 路径中,那么导入能够成功,并且库能够被用于构建和运行一个 Java 应用程序。
|
||||
|
||||
如果一个库并不在 Java 路径中(因为,例如,你正在写你自己的库),那么该库可以与你的应用程序绑定在一起(协议许可),以便导入可以按预期地工作。
|
||||
|
||||
### 3、Java 类
|
||||
|
||||
Java 类使用关键字 `public class` 声明,以及一个唯一的对应于它的文件名的类名。例如,在项目 `helloworld` 中的一个文件 `Hello.java` 中:
|
||||
|
||||
```
|
||||
package helloworld;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
/**
|
||||
* @author seth
|
||||
* A GUI hello world.
|
||||
*/
|
||||
|
||||
public class Hello {
|
||||
// this is an empty class
|
||||
}
|
||||
```
|
||||
|
||||
你可以在一个类内部声明变量和函数。在 Java 中,在一个类中的变量被称为*字段*。
|
||||
|
||||
### 4、Java 方法
|
||||
|
||||
Java 的方法本质上是对象中的函数。基于预期返回的数据类型(例如 `void`、`int`、`float` 等等),它们被定义为 `public`(意味着它们可以被任何其它类访问)或 `private`(限制它们的使用)。
|
||||
|
||||
|
||||
```
|
||||
public void helloPrompt(ActionEvent event) {
|
||||
String salutation = "Hello %s";
|
||||
|
||||
string helloMessage = "World";
|
||||
message = String.format(salutation, helloMessage);
|
||||
JOptionPane.showMessageDialog(this, message);
|
||||
}
|
||||
|
||||
private int someNumber (x) {
|
||||
return x*2;
|
||||
}
|
||||
```
|
||||
|
||||
当直接调用一个方法时,以其类和方法名称来引用。例如,`Hello.someNumber` 指向在 `Hello` 类中的 `someNumber` 方法。
|
||||
|
||||
### 5、static
|
||||
|
||||
Java 中的 `static` 关键字使代码中的成员可以独立于包含其的对象而被访问。
|
||||
|
||||
在面向对象编程中,你编写的代码用作“对象”的模板,这些对象在应用程序运行时产生。例如,你不需要编写一个具体的窗口,而是编写基于 Java 中的窗口类的窗口实例(并由你的代码修改)。由于在应用程序生成它的实例之前,你编写的所有代码都不会“存在”,因此在创建它们所依赖的对象之前,大多数方法和变量(甚至是嵌套类)都无法使用。
|
||||
|
||||
然而,有时,在对象被通过应用程序创建前,你需要访问或使用其中的数据。(例如,除非事先知道球是红色时,应用程序无法生成一个红色的球)。对于这些情况,请使用 `static` 关键字。
|
||||
|
||||
### 6、try 和 catch
|
||||
|
||||
Java 擅长捕捉错误,但是,只有你告诉它遇到错误时该做什么,它才能优雅地恢复。在 Java 中,尝试执行一个动作的级联层次结构以 `try` 开头,出现错误时回落到 `catch`,并以 `finally` 结束。如果 `try` 子句失败,则将调用 `catch`,最后,不管结果如何,总是由 `finally` 来执行一些合理的动作。这里是一个示例:
|
||||
|
||||
```
|
||||
try {
|
||||
cmd = parser.parse(opt, args);
|
||||
|
||||
if(cmd.hasOption("help")) {
|
||||
HelpFormatter helper = new HelpFormatter();
|
||||
helper.printHelp("Hello <options>", opt);
|
||||
System.exit(0);
|
||||
}
|
||||
else {
|
||||
if(cmd.hasOption("shell") || cmd.hasOption("s")) {
|
||||
String target = cmd.getOptionValue("tgt");
|
||||
} // else
|
||||
} // fi
|
||||
} catch (ParseException err) {
|
||||
System.out.println(err);
|
||||
System.exit(1);
|
||||
} //catch
|
||||
finally {
|
||||
new Hello().helloWorld(opt);
|
||||
} //finally
|
||||
} //try
|
||||
```
|
||||
|
||||
这是一个健壮的系统,它试图避免无法挽回的错误,或者,至少,为你提供让用户提交有用的反馈的选项。经常使用它,你的用户将会感谢你!
|
||||
|
||||
### 7、运行 Java 应用程序
|
||||
|
||||
Java 文件,通常以 `.java` 结尾,理论上说,可以使用 `java` 命令运行。然而,如果一个应用程序很复杂,运行一个单个文件是否会产生有意义的结果是另外一个问题。
|
||||
|
||||
来直接运行一个 `.java` 文件:
|
||||
|
||||
```
|
||||
$ java ./Hello.java
|
||||
```
|
||||
|
||||
通常,Java 应用程序以 Java 存档(JAR)文件的形式分发,以 `.jar` 结尾。一个 JAR 文件包含一个清单文件(可以指定主类、项目结构的一些元数据),以及运行应用程序所需的所有代码部分。
|
||||
|
||||
要运行一个 JAR 文件,你可以双击它的图标(取决于你的操作系统设置),你也可以从终端中启动它:
|
||||
|
||||
```
|
||||
$ java -jar ./Hello.jar
|
||||
```
|
||||
|
||||
### 适合所有人的 Java
|
||||
|
||||
Java 是一种强大的语言,由于有了 [OpenJDK][12] 项目及其它的努力,它是一种开放式规范,允许像 [IcedTea][13]、[Dalvik][14] 和 [Kotlin][15] 项目的茁壮成长。学习 Java 是一种准备在各种行业中工作的好方法,而且,[使用 Java 的理由很多][16]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/java-basics
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_cafe_brew_laptop_desktop.jpg?itok=G-n1o1-o (Coffee and laptop)
|
||||
[2]: https://www.redhat.com/en/resources/building-microservices-eap-7-reference-architecture
|
||||
[3]: https://www.gnu.org/software/bash/
|
||||
[4]: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6
|
||||
[5]: http://openjdk.java.net/
|
||||
[6]: http://www.eclipse.org/
|
||||
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+actionevent
|
||||
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+joptionpane
|
||||
[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
||||
[11]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+parseexception
|
||||
[12]: https://openjdk.java.net/
|
||||
[13]: https://icedtea.classpath.org/wiki/Main_Page
|
||||
[14]: https://source.android.com/devices/tech/dalvik/
|
||||
[15]: https://kotlinlang.org/
|
||||
[16]: https://opensource.com/article/19/9/why-i-use-java
|
||||
@@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11531-1.html)
|
||||
[#]: subject: (5 Best Password Managers For Linux Desktop)
|
||||
[#]: via: (https://itsfoss.com/password-managers-linux/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
@@ -10,11 +10,13 @@
|
||||
5 个 Linux 桌面上的最佳密码管理器
|
||||
======
|
||||
|
||||
_ **密码管理器是创建唯一密码并安全存储它们的有用工具,这样你无需记住密码。了解适用于 Linux 桌面的最佳密码管理器。** _
|
||||
> 密码管理器是创建唯一密码并安全存储它们的有用工具,这样你无需记住密码。了解一下适用于 Linux 桌面的最佳密码管理器。
|
||||
|
||||
密码无处不在。网站、论坛、Web 应用等,你需要为其创建帐户和密码。麻烦的是密码。为各个帐户使用相同的密码会带来安全风险,因为[如果其中一个网站遭到入侵,黑客也会在其他网站上尝试相同的电子邮件密码组合][1]。
|
||||

|
||||
|
||||
但是,为所有新帐户设置唯一的密码意味着你必须记住所有密码,这对普通人而言不太可能。这就是密码管理器可以提供帮助的地方。
|
||||
密码无处不在。网站、论坛、Web 应用等,你需要为其创建帐户和密码。麻烦在于密码,为各个帐户使用相同的密码会带来安全风险,因为[如果其中一个网站遭到入侵,黑客也会在其他网站上尝试相同的电子邮件密码组合][1]。
|
||||
|
||||
但是,为所有新帐户设置独有的密码意味着你必须记住所有密码,这对普通人而言不太可能。这就是密码管理器可以提供帮助的地方。
|
||||
|
||||
密码管理应用会为你建议/创建强密码,并将其存储在加密的数据库中。你只需要记住密码管理器的主密码即可。
|
||||
|
||||
@@ -26,121 +28,111 @@ _ **密码管理器是创建唯一密码并安全存储它们的有用工具,
|
||||
|
||||
### Linux 密码管理器
|
||||
|
||||
可能的非 FOSS 警报!
|
||||
> 可能的非 FOSS 警报!
|
||||
|
||||
我们优先考虑开源软件(有一些专有软件,请不要讨厌我!),并提供适用于 Linux 的独立桌面应用(GUI)。专有软件已高亮显示。
|
||||
> 我们优先考虑开源软件(有一些专有软件,请不要讨厌我!),并提供适用于 Linux 的独立桌面应用(GUI)。专有软件已高亮显示。
|
||||
|
||||
#### 1\. Bitwarden
|
||||
#### 1、Bitwarden
|
||||
|
||||
![][3]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 开源
|
||||
* 免费供个人使用(可选付费升级)
|
||||
* 云服务器的端到端加密
|
||||
* 跨平台
|
||||
* 有浏览器扩展
|
||||
* 命令行工具
|
||||
|
||||
|
||||
* 开源
|
||||
* 免费供个人使用(可选付费升级)
|
||||
* 云服务器的端到端加密
|
||||
* 跨平台
|
||||
* 有浏览器扩展
|
||||
* 命令行工具
|
||||
|
||||
Bitwarden 是 Linux 上最令人印象深刻的密码管理器之一。老实说,直到现在我才知道它。我已经从 [LastPass][4] 切换到了它。我能够轻松地从 LastPass 导入数据,而没有任何问题和困难。
|
||||
|
||||
高级版本的价格仅为每年 10 美元。这似乎是值得的(我已经为个人使用进行了升级)。
|
||||
付费版本的价格仅为每年 10 美元。这似乎是值得的(我已经为个人使用进行了升级)。
|
||||
|
||||
它是一个开源解决方案,因此没有任何可疑之处。你甚至可以将其托管在自己的服务器上,并为你的组织创建密码解决方案。
|
||||
|
||||
除此之外,你还将获得所有必需的功能,例如用于登录的两步验证、导入/导出凭据,指纹短语(唯一键),密码生成器等等。
|
||||
除此之外,你还将获得所有必需的功能,例如用于登录的两步验证、导入/导出凭据、指纹短语(唯一键)、密码生成器等等。
|
||||
|
||||
你可以免费将帐户升级为组织帐户,以便最多与 2 个用户共享你的信息。但是,如果你想要额外的加密存储以及与 5 个用户共享密码的功能,那么高级升级的费用低至每月 1 美元。我认为绝对值得一试!
|
||||
你可以免费将帐户升级为组织帐户,以便最多与 2 个用户共享你的信息。但是,如果你想要额外的加密存储以及与 5 个用户共享密码的功能,那么付费升级的费用低至每月 1 美元。我认为绝对值得一试!
|
||||
|
||||
[Bitwarden][5]
|
||||
- [Bitwarden][5]
|
||||
|
||||
#### 2\. Buttercup
|
||||
#### 2、Buttercup
|
||||
|
||||
![][6]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 开源
|
||||
* 免费,没有高级选项。
|
||||
* 跨平台
|
||||
* 有浏览器扩展
|
||||
* 开源
|
||||
* 免费,没有付费方式。
|
||||
* 跨平台
|
||||
* 有浏览器扩展
|
||||
|
||||
这是 Linux 中的另一个开源密码管理器。Buttercup 可能不是一个非常流行的解决方案。但是,如果你在寻找一种更简单的保存凭据的方法,那么这将是一个不错的开始。
|
||||
|
||||
|
||||
Linux 中的另一个开源密码管理器。Buttercup 可能不是一个非常流行的解决方案。但是,如果你在寻找一种更简单的方法来保存凭据,那么这将是一个不错的开始。
|
||||
|
||||
与其他软件不同,你不必对其云服务器持怀疑态度,因为它只支持离线使用并支持连接 [Dropbox][7]、[OwnCloud] [8]、[Nextcloud][9] 和 [WebDAV][10] 等云服务。
|
||||
与其他软件不同,你不必对怀疑其云服务器的安全,因为它只支持离线使用并支持连接 [Dropbox][7]、[OwnCloud] [8]、[Nextcloud][9] 和 [WebDAV][10] 等云服务。
|
||||
|
||||
因此,如果需要同步数据,那么可以选择云服务。你有不同选择。
|
||||
|
||||
[Buttercup][11]
|
||||
- [Buttercup][11]
|
||||
|
||||
#### 3\. KeePassXC
|
||||
#### 3、KeePassXC
|
||||
|
||||
![][12]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 开源
|
||||
* 简单的密码管理器
|
||||
* 跨平台
|
||||
* 没有移动支持
|
||||
* 开源
|
||||
* 简单的密码管理器
|
||||
* 跨平台
|
||||
* 没有移动设备支持
|
||||
|
||||
|
||||
|
||||
KeePassXC 是 [KeePassX][13] 的社区分支,它最初是 Windows 上 [KeePass][14] 的 Linux 移植。
|
||||
KeePassXC 是 [KeePassX][13] 的社区分支,它最初是 Windows 上 [KeePass][14] 的 Linux 移植版本。
|
||||
|
||||
除非你没意识到,KeePassX 已经多年没有维护。因此,如果你在寻找简单易用的密码管理器,那么 KeePassXC 是一个不错的选择。KeePassXC 可能不是最漂亮或最好的密码管理器,但它确实可以做到该做的事。
|
||||
|
||||
它也是安全和开源的。我认为这值得一试,你说呢?
|
||||
|
||||
[KeePassXC][15]
|
||||
- [KeePassXC][15]
|
||||
|
||||
#### 4\. Enpass (非开源)
|
||||
#### 4、Enpass (非开源)
|
||||
|
||||
![][16]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 专有
|
||||
* 许多功能-包括“可穿戴”设备支持。
|
||||
* Linux 完全免费(具有高级功能)
|
||||
|
||||
|
||||
* 专有软件
|
||||
* 有许多功能,包括对“可穿戴”设备支持。
|
||||
* Linux 完全免费(具有付费支持)
|
||||
|
||||
Enpass 是非常流行的跨平台密码管理器。即使它不是开源解决方案,但还是有很多人依赖它。因此,至少可以肯定它是可行的。
|
||||
|
||||
它提供了很多功能,如果你有可穿戴设备,它也将支持它,这点很少见。
|
||||
它提供了很多功能,如果你有可穿戴设备,它也可以支持它,这点很少见。
|
||||
|
||||
很高兴看到 Enpass 积极管理 Linux 发行版的软件包。另外,请注意,它仅适用于 64 位系统。你可以在它的网站上找到[官方的安装说明] [17]。它需要使用终端,但是我按照步骤进行了测试,它非常好用。
|
||||
很高兴能看到 Enpass 积极管理 Linux 发行版的软件包。另外,请注意,它仅适用于 64 位系统。你可以在它的网站上找到[官方的安装说明] [17]。它需要使用终端,但是我按照步骤进行了测试,它非常好用。
|
||||
|
||||
[Enpass][18]
|
||||
- [Enpass][18]
|
||||
|
||||
#### 5\. myki (非开源)
|
||||
#### 5、myki (非开源)
|
||||
|
||||
![][19]
|
||||
|
||||
主要亮点:
|
||||
|
||||
* 专有
|
||||
* 不使用云服务器存储密码
|
||||
* 专注于本地点对点同步
|
||||
* 能够在移动设备上用指纹 ID 替换密码
|
||||
* 专有软件
|
||||
* 不使用云服务器存储密码
|
||||
* 专注于本地点对点同步
|
||||
* 能够在移动设备上用指纹 ID 替换密码
|
||||
|
||||
这可能不是一个受欢迎的建议,但我发现它很有趣。它是专有软件密码管理器,它让你避免使用云服务器,而是依靠点对点同步。
|
||||
|
||||
因此,如果你不想使用任何云服务器来存储你的信息,那么它适合你。另外值得注意的是,用于 Android 和 iOS 的程序可让你用指纹 ID 替换密码。如果你希望便于在手机上使用,又有桌面密码管理器的基本功能,这似乎是个不错的选择。
|
||||
|
||||
这可能不是一个受欢迎的建议,但我发现它很有趣。它是专有的密码管理器,它让你避免使用云服务器,并依靠点对点同步。
|
||||
|
||||
因此,如果你不想使用任何云服务器来存储你的信息,那么它适合你。另外值得注意的是,用于 Android 和 iOS 的程序可帮助你用指纹 ID 替换密码。如果你希望在手机上使用方便,还有桌面密码管理器的基本功能,这似乎是个不错的选择。
|
||||
|
||||
但是,如果你选择升级到高级版,这有个付费计划供你判断,绝对不便宜。
|
||||
但是,如果你选择升级到付费版,这有个付费计划供你判断,绝对不便宜。
|
||||
|
||||
尝试一下,让我们知道它如何!
|
||||
|
||||
[myki][20]
|
||||
- [myki][20]
|
||||
|
||||
### 其他一些值得说的密码管理器
|
||||
|
||||
@@ -150,13 +142,13 @@ Enpass 是非常流行的跨平台密码管理器。即使它不是开源解决
|
||||
|
||||
如果你正在寻找命令行密码管理器,那你应该试试 [Pass][25]。
|
||||
|
||||
[Password Safe][26] 也是种选择,但它的 Linux 客户端还处于 beta。我不建议依靠 “beta” 程序来存储密码。还有 [Universal Password Manager][27],但它不再维护。你可能也听说过 [Password Gorilla][28],但并它没有积极维护。
|
||||
[Password Safe][26] 也是种选择,但它的 Linux 客户端还处于 beta 阶段。我不建议依靠 “beta” 程序来存储密码。还有 [Universal Password Manager][27],但它不再维护。你可能也听说过 [Password Gorilla][28],但并它没有积极维护。
|
||||
|
||||
**总结**
|
||||
### 总结
|
||||
|
||||
目前,Bitwarden 似乎是我个人的最爱。但是,在 Linux 上有几个选项可供选择。你可以选择提供原生应用的程序,也可选择浏览器插件,选择权在你。
|
||||
目前,Bitwarden 似乎是我个人的最爱。但是,在 Linux 上有几个替代品可供选择。你可以选择提供原生应用的程序,也可选择浏览器插件,选择权在你。
|
||||
|
||||
如果有错过值得尝试的密码管理器,请在下面的评论中告诉我们。与往常一样,我们会根据你的建议扩展列表。
|
||||
如果我有错过值得尝试的密码管理器,请在下面的评论中告诉我们。与往常一样,我们会根据你的建议扩展列表。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@@ -165,7 +157,7 @@ via: https://itsfoss.com/password-managers-linux/
|
||||
作者:[Ankush Das][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/) 荣誉推出
|
||||
|
||||
@@ -1,65 +1,63 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11535-1.html)
|
||||
[#]: subject: (How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server)
|
||||
[#]: via: (https://www.linuxtechi.com/enable-epel-repo-centos8-rhel8-server/)
|
||||
[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
|
||||
|
||||
How to Enable EPEL Repository on CentOS 8 and RHEL 8 Server
|
||||
如何在 CentOS 8 和 RHEL 8 服务器上启用 EPEL 仓库
|
||||
======
|
||||
|
||||
**EPEL** Stands for Extra Packages for Enterprise Linux, it is a free and opensource additional packages repository available for **CentOS** and **RHEL** servers. As the name suggests, EPEL repository provides extra and additional packages which are not available in the default package repositories of [CentOS 8][1] and [RHEL 8][2].
|
||||
EPEL 代表 “Extra Packages for Enterprise Linux”,它是一个自由开源的附加软件包仓库,可用于 CentOS 和 RHEL 服务器。顾名思义,EPEL 仓库提供了额外的软件包,这些软件在 [CentOS 8][1] 和 [RHEL 8][2] 的默认软件包仓库中不可用。
|
||||
|
||||
In this article we will demonstrate how to enable and use epel repository on CentOS 8 and RHEL 8 Server.
|
||||
在本文中,我们将演示如何在 CentOS 8 和 RHEL 8 服务器上启用和使用 EPEL 存储库。
|
||||
|
||||
[![EPEL-Repo-CentOS8-RHEL8][3]][4]
|
||||

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

|
||||
|
||||
<ruby>协议缓冲区<rt>Protocol Buffers</rt></ruby>([Protobufs][2])像 XML 和 JSON 一样,可以让用不同语言编写并在不同平台上运行的应用程序交换数据。例如,用 Go 编写的发送程序可以在 Protobuf 中对以 Go 表示的销售订单数据进行编码,然后用 Java 编写的接收方可以对它进行解码,以获取所接收订单数据的 Java 表示方式。这是在网络连接上的结构示意图:
|
||||
|
||||
> Go 销售订单 ---> Pbuf 编码 ---> 网络 ---> Pbuf 界面 ---> Java 销售订单
|
||||
|
||||
与 XML 和 JSON 相比,Protobuf 编码是二进制而不是文本,这会使调试复杂化。但是,正如本文中的代码示例所确认的那样,Protobuf 编码在大小上比 XML 或 JSON 编码要有效得多。
|
||||
|
||||
Protobuf 以另一种方式提供了这种有效性。在实现级别,Protobuf 和其他编码系统对结构化数据进行<ruby>序列化<rt>serialize</rt></ruby>和<ruby>反序列化<rt>deserialize</rt></ruby>。序列化将特定语言的数据结构转换为字节流,反序列化是将字节流转换回特定语言的数据结构的逆运算。序列化和反序列化可能成为数据交换的瓶颈,因为这些操作会占用大量 CPU。高效的序列化和反序列化是 Protobuf 的另一个设计目标。
|
||||
|
||||
最近的编码技术,例如 Protobuf 和 FlatBuffers,源自 1990 年代初期的 [DCE/RPC][3](<ruby>分布式计算环境/远程过程调用<rt>Distributed Computing Environment/Remote Procedure Call</rt></ruby>)计划。与 DCE/RPC 一样,Protobuf 在数据交换中为 [IDL][4](接口定义语言)和编码层做出了贡献。
|
||||
|
||||
本文将着眼于这两层,然后提供 Go 和 Java 中的代码示例以充实 Protobuf 的细节,并表明 Protobuf 是易于使用的。
|
||||
|
||||
### Protobuf 作为一个 IDL 和编码层
|
||||
|
||||
像 Protobuf 一样,DCE/RPC 被设计为与语言和平台无关。适当的库和实用程序允许任何语言和平台用于 DCE/RPC 领域。此外,DCE/RPC 体系结构非常优雅。IDL 文档是一侧的远程过程与另一侧的调用者之间的协定。Protobuf 也是以 IDL 文档为中心的。
|
||||
|
||||
IDL 文档是文本,在 DCE/RPC 中,使用基本 C 语法以及元数据的语法扩展(方括号)和一些新的关键字,例如 `interface`。这是一个例子:
|
||||
|
||||
```
|
||||
[uuid (2d6ead46-05e3-11ca-7dd1-426909beabcd), version(1.0)]
|
||||
interface echo {
|
||||
const long int ECHO_SIZE = 512;
|
||||
void echo(
|
||||
[in] handle_t h,
|
||||
[in, string] idl_char from_client[ ],
|
||||
[out, string] idl_char from_service[ECHO_SIZE]
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
该 IDL 文档声明了一个名为 `echo` 的过程,该过程带有三个参数:类型为 `handle_t`(实现指针)和 `idl_char`(ASCII 字符数组)的 `[in]` 参数被传递给远程过程,而 `[out]` 参数(也是一个字符串)从该过程中传回。在此示例中,`echo` 过程不会显式返回值(`echo` 左侧的 `void`),但也可以返回值。返回值,以及一个或多个 `[out]` 参数,允许远程过程任意返回许多值。下一节将介绍 Protobuf IDL,它的语法不同,但同样用作数据交换中的协定。
|
||||
|
||||
DCE/RPC 和 Protobuf 中的 IDL 文档是创建用于交换数据的基础结构代码的实用程序的输入:
|
||||
|
||||
> IDL 文档 ---> DCE/PRC 或 Protobuf 实用程序 ---> 数据交换的支持代码
|
||||
|
||||
作为相对简单的文本,IDL 是同样便于人类阅读的关于数据交换细节的文档(特别是交换的数据项的数量和每个项的数据类型)。
|
||||
|
||||
Protobuf 可用于现代 RPC 系统,例如 [gRPC][5];但是 Protobuf 本身仅提供 IDL 层和编码层,用于从发送者传递到接收者的消息。与原本的 DCE/RPC 一样,Protobuf 编码是二进制的,但效率更高。
|
||||
|
||||
目前,XML 和 JSON 编码仍在通过 Web 服务等技术进行的数据交换中占主导地位,这些技术利用 Web 服务器、传输协议(例如 TCP、HTTP)以及标准库和实用程序等原有的基础设施来处理 XML 和 JSON 文档。 此外,各种类型的数据库系统可以存储 XML 和 JSON 文档,甚至旧式关系型系统也可以轻松生成查询结果的 XML 编码。现在,每种通用编程语言都具有支持 XML 和 JSON 的库。那么,是什么让我们回到 Protobuf 之类的**二进制**编码系统呢?
|
||||
|
||||
让我们看一下负十进制值 `-128`。以 2 的补码二进制表示形式(在系统和语言中占主导地位)中,此值可以存储在单个 8 位字节中:`10000000`。此整数值在 XML 或 JSON 中的文本编码需要多个字节。例如,UTF-8 编码需要四个字节的字符串,即 `-128`,即每个字符一个字节(十六进制,值为 `0x2d`、`0x31`、`0x32` 和 `0x38`)。XML 和 JSON 还添加了标记字符,例如尖括号和大括号。有关 Protobuf 编码的详细信息下面就会介绍,但现在的关注点是一个通用点:文本编码的压缩性明显低于二进制编码。
|
||||
|
||||
### 在 Go 中使用 Protobuf 的示例
|
||||
|
||||
我的代码示例着重于 Protobuf 而不是 RPC。以下是第一个示例的概述:
|
||||
|
||||
* 名为 `dataitem.proto` 的 IDL 文件定义了一个 Protobuf 消息,它具有六个不同类型的字段:具有不同范围的整数值、固定大小的浮点值以及两个不同长度的字符串。
|
||||
* Protobuf 编译器使用 IDL 文件生成 Go 版本(以及后面的 Java 版本)的 Protobuf 消息及支持函数。
|
||||
* Go 应用程序使用随机生成的值填充原生的 Go 数据结构,然后将结果序列化为本地文件。为了进行比较, XML 和 JSON 编码也被序列化为本地文件。
|
||||
* 作为测试,Go 应用程序通过反序列化 Protobuf 文件的内容来重建其原生数据结构的实例。
|
||||
* 作为语言中立性测试,Java 应用程序还会对 Protobuf 文件的内容进行反序列化以获取原生数据结构的实例。
|
||||
|
||||
[我的网站][6]上提供了该 IDL 文件以及两个 Go 和一个 Java 源文件,打包为 ZIP 文件。
|
||||
|
||||
最重要的 Protobuf IDL 文档如下所示。该文档存储在文件 `dataitem.proto` 中,并具有常规的`.proto` 扩展名。
|
||||
|
||||
#### 示例 1、Protobuf IDL 文档
|
||||
|
||||
```
|
||||
syntax = "proto3";
|
||||
|
||||
package main;
|
||||
|
||||
message DataItem {
|
||||
int64 oddA = 1;
|
||||
int64 evenA = 2;
|
||||
int32 oddB = 3;
|
||||
int32 evenB = 4;
|
||||
float small = 5;
|
||||
float big = 6;
|
||||
string short = 7;
|
||||
string long = 8;
|
||||
}
|
||||
```
|
||||
|
||||
该 IDL 使用当前的 proto3 而不是较早的 proto2 语法。软件包名称(在本例中为 `main`)是可选的,但是惯例使用它以避免名称冲突。这个结构化的消息包含八个字段,每个字段都有一个 Protobuf 数据类型(例如,`int64`、`string`)、名称(例如,`oddA`、`short`)和一个等号 `=` 之后的数字标签(即键)。标签(在此示例中为 1 到 8)是唯一的整数标识符,用于确定字段序列化的顺序。
|
||||
|
||||
Protobuf 消息可以嵌套到任意级别,而一个消息可以是另外一个消息的字段类型。这是一个使用 `DataItem` 消息作为字段类型的示例:
|
||||
|
||||
```
|
||||
message DataItems {
|
||||
repeated DataItem item = 1;
|
||||
}
|
||||
```
|
||||
|
||||
单个 `DataItems` 消息由重复的(零个或多个)`DataItem` 消息组成。
|
||||
|
||||
为了清晰起见,Protobuf 还支持枚举类型:
|
||||
|
||||
```
|
||||
enum PartnershipStatus {
|
||||
reserved "FREE", "CONSTRAINED", "OTHER";
|
||||
}
|
||||
```
|
||||
|
||||
`reserved` 限定符确保用于实现这三个符号名的数值不能重复使用。
|
||||
|
||||
为了生成一个或多个声明 Protobuf 消息结构的特定于语言的版本,包含这些结构的 IDL 文件被传递到`protoc` 编译器(可在 [Protobuf GitHub 存储库][7]中找到)。对于 Go 代码,可以以通常的方式安装支持的 Protobuf 库(这里以 `%` 作为命令行提示符):
|
||||
|
||||
```
|
||||
% go get github.com/golang/protobuf/proto
|
||||
```
|
||||
|
||||
将 Protobuf IDL 文件 `dataitem.proto` 编译为 Go 源代码的命令是:
|
||||
|
||||
```
|
||||
% protoc --go_out=. dataitem.proto
|
||||
```
|
||||
|
||||
标志 `--go_out` 指示编译器生成 Go 源代码。其他语言也有类似的标志。在这种情况下,结果是一个名为 `dataitem.pb.go` 的文件,该文件足够小,可以将其基本内容复制到 Go 应用程序中。以下是生成的代码的主要部分:
|
||||
|
||||
```
|
||||
var _ = proto.Marshal
|
||||
|
||||
type DataItem struct {
|
||||
OddA int64 `protobuf:"varint,1,opt,name=oddA" json:"oddA,omitempty"`
|
||||
EvenA int64 `protobuf:"varint,2,opt,name=evenA" json:"evenA,omitempty"`
|
||||
OddB int32 `protobuf:"varint,3,opt,name=oddB" json:"oddB,omitempty"`
|
||||
EvenB int32 `protobuf:"varint,4,opt,name=evenB" json:"evenB,omitempty"`
|
||||
Small float32 `protobuf:"fixed32,5,opt,name=small" json:"small,omitempty"`
|
||||
Big float32 `protobuf:"fixed32,6,opt,name=big" json:"big,omitempty"`
|
||||
Short string `protobuf:"bytes,7,opt,name=short" json:"short,omitempty"`
|
||||
Long string `protobuf:"bytes,8,opt,name=long" json:"long,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DataItem) Reset() { *m = DataItem{} }
|
||||
func (m *DataItem) String() string { return proto.CompactTextString(m) }
|
||||
func (*DataItem) ProtoMessage() {}
|
||||
func init() {}
|
||||
```
|
||||
|
||||
编译器生成的代码具有 Go 结构 `DataItem`,该结构导出 Go 字段(名称现已大写开头),该字段与 Protobuf IDL 中声明的名称匹配。该结构字段具有标准的 Go 数据类型:`int32`、`int64`、`float32` 和 `string`。在每个字段行的末尾,是描述 Protobuf 类型的字符串,提供 Protobuf IDL 文档中的数字标签及有关 JSON 信息的元数据,这将在后面讨论。
|
||||
|
||||
此外也有函数;最重要的是 `Proto.Marshal`,用于将 `DataItem` 结构的实例序列化为 Protobuf 格式。辅助函数包括:清除 `DataItem` 结构的 `Reset`,生成 `DataItem` 的单行字符串表示的 `String`。
|
||||
|
||||
描述 Protobuf 编码的元数据应在更详细地分析 Go 程序之前进行仔细研究。
|
||||
|
||||
### Protobuf 编码
|
||||
|
||||
Protobuf 消息的结构为键/值对的集合,其中数字标签为键,相应的字段为值。字段名称(例如,`oddA` 和 `small`)是供人类阅读的,但是 `protoc` 编译器的确使用了字段名称来生成特定于语言的对应名称。例如,Protobuf IDL 中的 `oddA` 和 `small` 名称在 Go 结构中分别成为字段 `OddA` 和 `Small`。
|
||||
|
||||
键和它们的值都被编码,但是有一个重要的区别:一些数字值具有固定大小的 32 或 64 位的编码,而其他数字(包括消息标签)则是 `varint` 编码的,位数取决于整数的绝对值。例如,整数值 1 到 15 需要 8 位 `varint` 编码,而值 16 到 2047 需要 16 位。`varint` 编码在本质上与 UTF-8 编码类似(但细节不同),它偏爱较小的整数值而不是较大的整数值。(有关详细分析,请参见 Protobuf [编码指南][8])结果是,Protobuf 消息应该在字段中具有较小的整数值(如果可能),并且键数应尽可能少,但每个字段至少得有一个键。
|
||||
|
||||
下表 1 列出了 Protobuf 编码的要点:
|
||||
|
||||
编码 | 示例类型 | 长度
|
||||
---|---|---
|
||||
`varint` | `int32`、`uint32`、`int64` | 可变长度
|
||||
`fixed` | `fixed32`、`float`、`double` | 固定的 32 位或 64 位长度
|
||||
字节序列 | `string`、`bytes` | 序列长度
|
||||
|
||||
*表 1. Protobuf 数据类型*
|
||||
|
||||
未明确固定长度的整数类型是 `varint` 编码的;因此,在 `varint` 类型中,例如 `uint32`(`u` 代表无符号),数字 32 描述了整数的范围(在这种情况下为 0 到 2^32 - 1),而不是其位的大小,该位大小取决于值。相比之下,对于固定长度类型(例如 `fixed32` 或 `double`),Protobuf 编码分别需要 32 位和 64 位。Protobuf 中的字符串是字节序列;因此,字段编码的大小就是字节序列的长度。
|
||||
|
||||
另一个高效的方法值得一提。回想一下前面的示例,其中的 `DataItems` 消息由重复的 `DataItem` 实例组成:
|
||||
|
||||
```
|
||||
message DataItems {
|
||||
repeated DataItem item = 1;
|
||||
}
|
||||
```
|
||||
|
||||
`repeated` 表示 `DataItem` 实例是*打包的*:集合具有单个标签,在这里是 1。因此,具有重复的 `DataItem` 实例的 `DataItems` 消息比具有多个但单独的 `DataItem` 字段、每个字段都需要自己的标签的消息的效率更高。
|
||||
|
||||
了解了这一背景,让我们回到 Go 程序。
|
||||
|
||||
### dataItem 程序的细节
|
||||
|
||||
`dataItem` 程序创建一个 `DataItem` 实例,并使用适当类型的随机生成的值填充字段。Go 有一个 `rand` 包,带有用于生成伪随机整数和浮点值的函数,而我的 `randString` 函数可以从字符集中生成指定长度的伪随机字符串。设计目标是要有一个具有不同类型和位大小的字段值的 `DataItem` 实例。例如,`OddA` 和 `EvenA` 值分别是 64 位非负整数值的奇数和偶数;但是 `OddB` 和 `EvenB` 变体的大小为 32 位,并存放 0 到 2047 之间的小整数值。随机浮点值的大小为 32 位,字符串为 16(`Short`)和 32(`Long`)字符的长度。这是用随机值填充 `DataItem` 结构的代码段:
|
||||
|
||||
```
|
||||
// 可变长度整数
|
||||
n1 := rand.Int63() // 大整数
|
||||
if (n1 & 1) == 0 { n1++ } // 确保其是奇数
|
||||
...
|
||||
n3 := rand.Int31() % UpperBound // 小整数
|
||||
if (n3 & 1) == 0 { n3++ } // 确保其是奇数
|
||||
|
||||
// 固定长度浮点数
|
||||
...
|
||||
t1 := rand.Float32()
|
||||
t2 := rand.Float32()
|
||||
...
|
||||
// 字符串
|
||||
str1 := randString(StrShort)
|
||||
str2 := randString(StrLong)
|
||||
|
||||
// 消息
|
||||
dataItem := &DataItem {
|
||||
OddA: n1,
|
||||
EvenA: n2,
|
||||
OddB: n3,
|
||||
EvenB: n4,
|
||||
Big: f1,
|
||||
Small: f2,
|
||||
Short: str1,
|
||||
Long: str2,
|
||||
}
|
||||
```
|
||||
|
||||
创建并填充值后,`DataItem` 实例将以 XML、JSON 和 Protobuf 进行编码,每种编码均写入本地文件:
|
||||
|
||||
```
|
||||
func encodeAndserialize(dataItem *DataItem) {
|
||||
bytes, _ := xml.MarshalIndent(dataItem, "", " ") // Xml to dataitem.xml
|
||||
ioutil.WriteFile(XmlFile, bytes, 0644) // 0644 is file access permissions
|
||||
|
||||
bytes, _ = json.MarshalIndent(dataItem, "", " ") // Json to dataitem.json
|
||||
ioutil.WriteFile(JsonFile, bytes, 0644)
|
||||
|
||||
bytes, _ = proto.Marshal(dataItem) // Protobuf to dataitem.pbuf
|
||||
ioutil.WriteFile(PbufFile, bytes, 0644)
|
||||
}
|
||||
```
|
||||
|
||||
这三个序列化函数使用术语 `marshal`,它与 `serialize` 意思大致相同。如代码所示,三个 `Marshal` 函数均返回一个字节数组,然后将其写入文件。(为简单起见,忽略可能的错误处理。)在示例运行中,文件大小为:
|
||||
|
||||
```
|
||||
dataitem.xml: 262 bytes
|
||||
dataitem.json: 212 bytes
|
||||
dataitem.pbuf: 88 bytes
|
||||
```
|
||||
|
||||
Protobuf 编码明显小于其他两个编码方案。通过消除缩进字符(在这种情况下为空白和换行符),可以稍微减小 XML 和 JSON 序列化的大小。
|
||||
|
||||
以下是 `dataitem.json` 文件,该文件最终是由 `json.MarshalIndent` 调用产生的,并添加了以 `##` 开头的注释:
|
||||
|
||||
```
|
||||
{
|
||||
"oddA": 4744002665212642479, ## 64-bit >= 0
|
||||
"evenA": 2395006495604861128, ## ditto
|
||||
"oddB": 57, ## 32-bit >= 0 but < 2048
|
||||
"evenB": 468, ## ditto
|
||||
"small": 0.7562016, ## 32-bit floating-point
|
||||
"big": 0.85202795, ## ditto
|
||||
"short": "ClH1oDaTtoX$HBN5", ## 16 random chars
|
||||
"long": "xId0rD3Cri%3Wt%^QjcFLJgyXBu9^DZI" ## 32 random chars
|
||||
}
|
||||
```
|
||||
|
||||
尽管这些序列化的数据写入到本地文件中,但是也可以使用相同的方法将数据写入网络连接的输出流。
|
||||
|
||||
### 测试序列化和反序列化
|
||||
|
||||
Go 程序接下来通过将先前写入 `dataitem.pbuf` 文件的字节反序列化为 `DataItem` 实例来运行基本测试。这是代码段,其中去除了错误检查部分:
|
||||
|
||||
```
|
||||
filebytes, err := ioutil.ReadFile(PbufFile) // get the bytes from the file
|
||||
...
|
||||
testItem.Reset() // clear the DataItem structure
|
||||
err = proto.Unmarshal(filebytes, testItem) // deserialize into a DataItem instance
|
||||
```
|
||||
|
||||
用于 Protbuf 反序列化的 `proto.Unmarshal` 函数与 `proto.Marshal` 函数相反。原始的 `DataItem` 和反序列化的副本将被打印出来以确认完全匹配:
|
||||
|
||||
```
|
||||
Original:
|
||||
2041519981506242154 3041486079683013705 1192 1879
|
||||
0.572123 0.326855
|
||||
boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk&
|
||||
|
||||
Deserialized:
|
||||
2041519981506242154 3041486079683013705 1192 1879
|
||||
0.572123 0.326855
|
||||
boPb#T0O8Xd&Ps5EnSZqDg4Qztvo7IIs 9vH66AiGSQgCDxk&
|
||||
```
|
||||
|
||||
### 一个 Java Protobuf 客户端
|
||||
|
||||
用 Java 写的示例是为了确认 Protobuf 的语言中立性。原始 IDL 文件可用于生成 Java 支持代码,其中涉及嵌套类。但是,为了抑制警告信息,可以进行一些补充。这是修订版,它指定了一个 `DataMsg` 作为外部类的名称,内部类在该 Protobuf 消息后面自动命名为 `DataItem`:
|
||||
|
||||
```
|
||||
syntax = "proto3";
|
||||
|
||||
package main;
|
||||
|
||||
option java_outer_classname = "DataMsg";
|
||||
|
||||
message DataItem {
|
||||
...
|
||||
```
|
||||
|
||||
进行此更改后,`protoc` 编译与以前相同,只是所期望的输出现在是 Java 而不是 Go:
|
||||
|
||||
```
|
||||
% protoc --java_out=. dataitem.proto
|
||||
```
|
||||
|
||||
生成的源文件(在名为 `main` 的子目录中)为 `DataMsg.java`,长度约为 1,120 行:Java 并不简洁。编译然后运行 Java 代码需要具有 Protobuf 库支持的 JAR 文件。该文件位于 [Maven 存储库][9]中。
|
||||
|
||||
放置好这些片段后,我的测试代码相对较短(并且在 ZIP 文件中以 `Main.java` 形式提供):
|
||||
|
||||
```
|
||||
package main;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
String path = "dataitem.pbuf"; // from the Go program's serialization
|
||||
try {
|
||||
DataMsg.DataItem deserial =
|
||||
DataMsg.DataItem.newBuilder().mergeFrom(new FileInputStream(path)).build();
|
||||
|
||||
System.out.println(deserial.getOddA()); // 64-bit odd
|
||||
System.out.println(deserial.getLong()); // 32-character string
|
||||
}
|
||||
catch(Exception e) { System.err.println(e); }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
当然,生产级的测试将更加彻底,但是即使是该初步测试也可以证明 Protobuf 的语言中立性:`dataitem.pbuf` 文件是 Go 程序对 Go 语言版的 `DataItem` 进行序列化的结果,并且该文件中的字节被反序列化以产生一个 Java 语言的 `DataItem` 实例。Java 测试的输出与 Go 测试的输出相同。
|
||||
|
||||
### 用 numPairs 程序来结束
|
||||
|
||||
让我们以一个示例作为结尾,来突出 Protobuf 效率,但又强调在任何编码技术中都会涉及到的成本。考虑以下 Protobuf IDL 文件:
|
||||
|
||||
```
|
||||
syntax = "proto3";
|
||||
package main;
|
||||
|
||||
message NumPairs {
|
||||
repeated NumPair pair = 1;
|
||||
}
|
||||
|
||||
message NumPair {
|
||||
int32 odd = 1;
|
||||
int32 even = 2;
|
||||
}
|
||||
```
|
||||
|
||||
`NumPair` 消息由两个 `int32` 值以及每个字段的整数标签组成。`NumPairs` 消息是嵌入的 `NumPair` 消息的序列。
|
||||
|
||||
Go 语言的 `numPairs` 程序(如下)创建了 200 万个 `NumPair` 实例,每个实例都附加到 `NumPairs` 消息中。该消息可以按常规方式进行序列化和反序列化。
|
||||
|
||||
#### 示例 2、numPairs 程序
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
"encoding/xml"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
// protoc-generated code: start
|
||||
var _ = proto.Marshal
|
||||
type NumPairs struct {
|
||||
Pair []*NumPair `protobuf:"bytes,1,rep,name=pair" json:"pair,omitempty"`
|
||||
}
|
||||
|
||||
func (m *NumPairs) Reset() { *m = NumPairs{} }
|
||||
func (m *NumPairs) String() string { return proto.CompactTextString(m) }
|
||||
func (*NumPairs) ProtoMessage() {}
|
||||
func (m *NumPairs) GetPair() []*NumPair {
|
||||
if m != nil { return m.Pair }
|
||||
return nil
|
||||
}
|
||||
|
||||
type NumPair struct {
|
||||
Odd int32 `protobuf:"varint,1,opt,name=odd" json:"odd,omitempty"`
|
||||
Even int32 `protobuf:"varint,2,opt,name=even" json:"even,omitempty"`
|
||||
}
|
||||
|
||||
func (m *NumPair) Reset() { *m = NumPair{} }
|
||||
func (m *NumPair) String() string { return proto.CompactTextString(m) }
|
||||
func (*NumPair) ProtoMessage() {}
|
||||
func init() {}
|
||||
// protoc-generated code: finish
|
||||
|
||||
var numPairsStruct NumPairs
|
||||
var numPairs = &numPairsStruct
|
||||
|
||||
func encodeAndserialize() {
|
||||
// XML encoding
|
||||
filename := "./pairs.xml"
|
||||
bytes, _ := xml.MarshalIndent(numPairs, "", " ")
|
||||
ioutil.WriteFile(filename, bytes, 0644)
|
||||
|
||||
// JSON encoding
|
||||
filename = "./pairs.json"
|
||||
bytes, _ = json.MarshalIndent(numPairs, "", " ")
|
||||
ioutil.WriteFile(filename, bytes, 0644)
|
||||
|
||||
// ProtoBuf encoding
|
||||
filename = "./pairs.pbuf"
|
||||
bytes, _ = proto.Marshal(numPairs)
|
||||
ioutil.WriteFile(filename, bytes, 0644)
|
||||
}
|
||||
|
||||
const HowMany = 200 * 100 * 100 // two million
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
// uncomment the modulus operations to get the more efficient version
|
||||
for i := 0; i < HowMany; i++ {
|
||||
n1 := rand.Int31() // % 2047
|
||||
if (n1 & 1) == 0 { n1++ } // ensure it's odd
|
||||
n2 := rand.Int31() // % 2047
|
||||
if (n2 & 1) == 1 { n2++ } // ensure it's even
|
||||
|
||||
next := &NumPair {
|
||||
Odd: n1,
|
||||
Even: n2,
|
||||
}
|
||||
numPairs.Pair = append(numPairs.Pair, next)
|
||||
}
|
||||
encodeAndserialize()
|
||||
}
|
||||
```
|
||||
|
||||
每个 `NumPair` 中随机生成的奇数和偶数值的范围在 0 到 20 亿之间变化。就原始数据(而非编码数据)而言,Go 程序中生成的整数总共为 16MB:每个 `NumPair` 为两个整数,总计为 400 万个整数,每个值的大小为四个字节。
|
||||
|
||||
为了进行比较,下表列出了 XML、JSON 和 Protobuf 编码的示例 `NumsPairs` 消息的 200 万个 `NumPair` 实例。原始数据也包括在内。由于 `numPairs` 程序生成随机值,因此样本运行的输出有所不同,但接近表中显示的大小。
|
||||
|
||||
编码 | 文件 | 字节大小 | Pbuf/其它 比例
|
||||
---|---|---|---
|
||||
无 | pairs.raw | 16MB | 169%
|
||||
Protobuf | pairs.pbuf | 27MB | —
|
||||
JSON | pairs.json | 100MB | 27%
|
||||
XML | pairs.xml | 126MB | 21%
|
||||
|
||||
*表 2. 16MB 整数的编码开销*
|
||||
|
||||
不出所料,Protobuf 和之后的 XML 和 JSON 差别明显。Protobuf 编码大约是 JSON 的四分之一,是 XML 的五分之一。但是原始数据清楚地表明 Protobuf 也会产生编码开销:序列化的 Protobuf 消息比原始数据大 11MB。包括 Protobuf 在内的任何编码都涉及结构化数据,这不可避免地会增加字节。
|
||||
|
||||
序列化的 200 万个 `NumPair` 实例中的每个实例都包含**四**个整数值:Go 结构中的 `Even` 和 `Odd` 字段分别一个,而 Protobuf 编码中的每个字段、每个标签一个。对于原始数据(而不是编码数据),每个实例将达到 16 个字节,样本 `NumPairs` 消息中有 200 万个实例。但是 Protobuf 标记(如 `NumPair` 字段中的 `int32` 值)使用 `varint` 编码,因此字节长度有所不同。特别是,小的整数值(在这种情况下,包括标签在内)需要不到四个字节进行编码。
|
||||
|
||||
如果对 `numPairs` 程序进行了修改,以使两个 `NumPair` 字段的值小于 2048,且其编码为一或两个字节,则 Protobuf 编码将从 27MB 下降到 16MB,这正是原始数据的大小。下表总结了样本运行中的新编码大小。
|
||||
|
||||
编码 | 文件 | 字节大小 | Pbuf/其它 比例
|
||||
---|---|---|---
|
||||
None | pairs.raw | 16MB | 100%
|
||||
Protobuf | pairs.pbuf | 16MB | —
|
||||
JSON | pairs.json | 77MB | 21%
|
||||
XML | pairs.xml | 103MB | 15%
|
||||
|
||||
*表 3. 编码 16MB 的小于 2048 的整数*
|
||||
|
||||
总之,修改后的 `numPairs` 程序的字段值小于 2048,可减少原始数据中每个四字节整数值的大小。但是 Protobuf 编码仍然需要标签,这些标签会在 Protobuf 消息中添加字节。Protobuf 编码确实会增加消息大小,但是如果要编码相对较小的整数值(无论是字段还是键),则可以通过 `varint` 因子来减少此开销。
|
||||
|
||||
对于包含混合类型的结构化数据(且整数值相对较小)的中等大小的消息,Protobuf 明显优于 XML 和 JSON 等选项。在其他情况下,数据可能不适合 Protobuf 编码。例如,如果两个应用程序需要共享大量文本记录或大整数值,则可以采用压缩而不是编码技术。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/protobuf-data-interchange
|
||||
|
||||
作者:[Marty Kalin][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mkalindepauledu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
|
||||
[2]: https://developers.google.com/protocol-buffers/
|
||||
[3]: https://en.wikipedia.org/wiki/DCE/RPC
|
||||
[4]: https://en.wikipedia.org/wiki/Interface_description_language
|
||||
[5]: https://grpc.io/
|
||||
[6]: http://condor.depaul.edu/mkalin
|
||||
[7]: https://github.com/protocolbuffers/protobuf
|
||||
[8]: https://developers.google.com/protocol-buffers/docs/encoding
|
||||
[9]: https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
|
||||
251
published/20191021 How to program with Bash- Syntax and tools.md
Normal file
251
published/20191021 How to program with Bash- Syntax and tools.md
Normal file
@@ -0,0 +1,251 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (jdh8383)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11552-1.html)
|
||||
[#]: subject: (How to program with Bash: Syntax and tools)
|
||||
[#]: via: (https://opensource.com/article/19/10/programming-bash-part-1)
|
||||
[#]: author: (David Both https://opensource.com/users/dboth)
|
||||
|
||||
怎样用 Bash 编程:语法和工具
|
||||
======
|
||||
|
||||
> 让我们通过本系列文章来学习基本的 Bash 编程语法和工具,以及如何使用变量和控制运算符,这是三篇中的第一篇。
|
||||
|
||||

|
||||
|
||||
Shell 是操作系统的命令解释器,其中 Bash 是我最喜欢的。每当用户或者系统管理员将命令输入系统的时候,Linux 的 shell 解释器就会把这些命令转换成操作系统可以理解的形式。而执行结果返回 shell 程序后,它会将结果输出到 STDOUT(标准输出),默认情况下,这些结果会[显示在你的终端][2]。所有我熟悉的 shell 同时也是一门编程语言。
|
||||
|
||||
Bash 是个功能强大的 shell,包含众多便捷特性,比如:tab 补全、命令回溯和再编辑、别名等。它的命令行默认编辑模式是 Emacs,但是我最喜欢的 Bash 特性之一是我可以将其更改为 Vi 模式,以使用那些储存在我肌肉记忆中的的编辑命令。
|
||||
|
||||
然而,如果你把 Bash 当作单纯的 shell 来用,则无法体验它的真实能力。我在设计一套包含三卷的 [Linux 自学课程][3]时(这个系列的文章正是基于此课程),了解到许多 Bash 的知识,这些是我在过去 20 年的 Linux 工作经验中所没有掌握的,其中的一些知识就是关于 Bash 的编程用法。不得不说,Bash 是一门强大的编程语言,是一个能够同时用于命令行和 shell 脚本的完美设计。
|
||||
|
||||
本系列文章将要探讨如何使用 Bash 作为命令行界面(CLI)编程语言。第一篇文章简单介绍 Bash 命令行编程、变量以及控制运算符。其他文章会讨论诸如:Bash 文件的类型;字符串、数字和一些逻辑运算符,它们能够提供代码执行流程中的逻辑控制;不同类型的 shell 扩展;通过 `for`、`while` 和 `until` 来控制循环操作。
|
||||
|
||||
### Shell
|
||||
|
||||
Bash 是 Bourne Again Shell 的缩写,因为 Bash shell 是 [基于][4] 更早的 Bourne shell,后者是 Steven Bourne 在 1977 年开发的。另外还有很多[其他的 shell][5] 可以使用,但下面四个是我经常见到的:
|
||||
|
||||
* `csh`:C shell 适合那些习惯了 C 语言语法的开发者。
|
||||
* `ksh`:Korn shell,由 David Korn 开发,在 Unix 用户中更流行。
|
||||
* `tcsh`:一个 csh 的变种,增加了一些易用性。
|
||||
* `zsh`:Z shell,集成了许多其他流行 shell 的特性。
|
||||
|
||||
所有 shell 都有内置命令,用以补充或替代核心工具集。打开 shell 的 man 说明页,找到“BUILT-INS”那一段,可以查看都有哪些内置命令。
|
||||
|
||||
每种 shell 都有它自己的特性和语法风格。我用过 csh、ksh 和 zsh,但我还是更喜欢 Bash。你可以多试几个,寻找更适合你的 shell,尽管这可能需要花些功夫。但幸运的是,切换不同 shell 很简单。
|
||||
|
||||
所有这些 shell 既是编程语言又是命令解释器。下面我们来快速浏览一下 Bash 中集成的编程结构和工具。
|
||||
|
||||
### 作为编程语言的 Bash
|
||||
|
||||
大多数场景下,系统管理员都会使用 Bash 来发送简单明了的命令。但 Bash 不仅可以输入单条命令,很多系统管理员可以编写简单的命令行程序来执行一系列任务,这些程序可以作为通用工具,能节省时间和精力。
|
||||
|
||||
编写 CLI 程序的目的是要提高效率(做一个“懒惰的”系统管理员)。在 CLI 程序中,你可以用特定顺序列出若干命令,逐条执行。这样你就不用盯着显示屏,等待一条命令执行完,再输入另一条,省下来的时间就可以去做其他事情了。
|
||||
|
||||
### 什么是“程序”?
|
||||
|
||||
自由在线计算机词典([FOLDOC][6])对于程序的定义是:“由计算机执行的指令,而不是运行它们的物理硬件。”普林斯顿大学的 [WordNet][7] 将程序定义为:“……计算机可以理解并执行的一系列指令……”[维基百科][8]上也有一条不错的关于计算机程序的条目。
|
||||
|
||||
总结下,程序由一条或多条指令组成,目的是完成一个具体的相关任务。对于系统管理员而言,一段程序通常由一系列的 shell 命令构成。Linux 下所有的 shell (至少我所熟知的)都有基本的编程功能,Bash 作为大多数 linux 发行版的默认 shell,也不例外。
|
||||
|
||||
本系列用 Bash 举例(因为它无处不在),假如你使用一个不同的 shell 也没关系,尽管结构和语法有所不同,但编程思想是相通的。有些 shell 支持某种特性而其他 shell 则不支持,但它们都提供编程功能。Shell 程序可以被存在一个文件中被反复使用,或者在需要的时候才创建它们。
|
||||
|
||||
### 简单 CLI 程序
|
||||
|
||||
最简单的命令行程序只有一或两条语句,它们可能相关,也可能无关,在按回车键之前被输入到命令行。程序中的第二条语句(如果有的话)可能取决于第一条语句的操作,但也不是必须的。
|
||||
|
||||
这里需要特别讲解一个标点符号。当你在命令行输入一条命令,按下回车键的时候,其实在命令的末尾有一个隐含的分号(`;`)。当一段 CLI shell 程序在命令行中被串起来作为单行指令使用时,必须使用分号来终结每个语句并将其与下一条语句分开。但 CLI shell 程序中的最后一条语句可以使用显式或隐式的分号。
|
||||
|
||||
### 一些基本语法
|
||||
|
||||
下面的例子会阐明这一语法规则。这段程序由单条命令组成,还有一个显式的终止符:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ echo "Hello world." ;
|
||||
Hello world.
|
||||
```
|
||||
|
||||
看起来不像一个程序,但它确是我学习每个新编程语言时写下的第一个程序。不同语言可能语法不同,但输出结果是一样的。
|
||||
|
||||
让我们扩展一下这段微不足道却又无所不在的代码。你的结果可能与我的有所不同,因为我的家目录有点乱,而你可能是在 GUI 桌面中第一次登录账号。
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ echo "My home directory." ; ls ;
|
||||
My home directory.
|
||||
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
|
||||
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
|
||||
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
|
||||
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1
|
||||
```
|
||||
|
||||
现在是不是更明显了。结果是相关的,但是两条语句彼此独立。你可能注意到我喜欢在分号前后多输入一个空格,这样会让代码的可读性更好。让我们再运行一遍这段程序,这次不要带结尾的分号:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ echo "My home directory." ; ls
|
||||
```
|
||||
|
||||
输出结果没有区别。
|
||||
|
||||
### 关于变量
|
||||
|
||||
像所有其他编程语言一样,Bash 支持变量。变量是个象征性的名字,它指向内存中的某个位置,那里存着对应的值。变量的值是可以改变的,所以它叫“变~量”。
|
||||
|
||||
Bash 不像 C 之类的语言,需要强制指定变量类型,比如:整型、浮点型或字符型。在 Bash 中,所有变量都是字符串。整数型的变量可以被用于整数运算,这是 Bash 唯一能够处理的数学类型。更复杂的运算则需要借助 [bc][9] 这样的命令,可以被用在命令行编程或者脚本中。
|
||||
|
||||
变量的值是被预先分配好的,这些值可以用在命令行编程或者脚本中。可以通过变量名字给其赋值,但是不能使用 `$` 符开头。比如,`VAR=10` 这样会把 `VAR` 的值设为 `10`。要打印变量的值,你可以使用语句 `echo $VAR`。变量名必须以文本(即非数字)开始。
|
||||
|
||||
Bash 会保存已经定义好的变量,直到它们被取消掉。
|
||||
|
||||
下面这个例子,在变量被赋值前,它的值是空(`null`)。然后给它赋值并打印出来,检验一下。你可以在同一行 CLI 程序里完成它:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
|
||||
|
||||
Hello World
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
*注意:变量赋值的语法非常严格,等号(`=`)两边不能有空格。*
|
||||
|
||||
那个空行表明了 `MyVar` 的初始值为空。变量的赋值和改值方法都一样,这个例子展示了原始值和新的值。
|
||||
|
||||
正如之前说的,Bash 支持整数运算,当你想计算一个数组中的某个元素的位置,或者做些简单的算术运算,这还是挺有帮助的。然而,这种方法并不适合科学计算,或是某些需要小数运算的场景,比如财务统计。这些场景有其它更好的工具可以应对。
|
||||
|
||||
下面是个简单的算术题:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
|
||||
Result = 63
|
||||
```
|
||||
|
||||
好像没啥问题,但如果运算结果是浮点数会发生什么呢?
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var1/Var2))"
|
||||
Result = 0
|
||||
[student@studentvm1 ~]$ Var1="7" ; Var2="9" ; echo "Result = $((Var2/Var1))"
|
||||
Result = 1
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
结果会被取整。请注意运算被包含在 `echo` 语句之中,其实计算在 echo 命令结束前就已经完成了,原因是 Bash 的内部优先级。想要了解详情的话,可以在 Bash 的 man 页面中搜索 “precedence”。
|
||||
|
||||
### 控制运算符
|
||||
|
||||
Shell 的控制运算符是一种语法运算符,可以轻松地创建一些有趣的命令行程序。在命令行上按顺序将几个命令串在一起,就变成了最简单的 CLI 程序:
|
||||
|
||||
```
|
||||
command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;
|
||||
```
|
||||
|
||||
只要不出错,这些命令都能顺利执行。但假如出错了怎么办?你可以预设好应对出错的办法,这就要用到 Bash 内置的控制运算符, `&&` 和 `||`。这两种运算符提供了流程控制功能,使你能改变代码执行的顺序。分号也可以被看做是一种 Bash 运算符,预示着新一行的开始。
|
||||
|
||||
`&&` 运算符提供了如下简单逻辑,“如果 command1 执行成功,那么接着执行 command2。如果 command1 失败,就跳过 command2。”语法如下:
|
||||
|
||||
```
|
||||
command1 && command2
|
||||
```
|
||||
|
||||
现在,让我们用命令来创建一个新的目录,如果成功的话,就把它切换为当前目录。确保你的家目录(`~`)是当前目录,先尝试在 `/root` 目录下创建,你应该没有权限:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir/ && cd $Dir
|
||||
mkdir: cannot create directory '/root/testdir/': Permission denied
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
上面的报错信息是由 `mkdir` 命令抛出的,因为创建目录失败了。`&&` 运算符收到了非零的返回码,所以 `cd` 命令就被跳过,前者阻止后者继续运行,因为创建目录失败了。这种控制流程可以阻止后面的错误累积,避免引发更严重的问题。是时候讲点更复杂的逻辑了。
|
||||
|
||||
当一段程序的返回码大于零时,使用 `||` 运算符可以让你在后面接着执行另一段程序。简单语法如下:
|
||||
|
||||
```
|
||||
command1 || command2
|
||||
```
|
||||
|
||||
解读一下,“假如 command1 失败,执行 command2”。隐藏的逻辑是,如果 command1 成功,跳过 command2。下面实践一下,仍然是创建新目录:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir || echo "$Dir was not created."
|
||||
mkdir: cannot create directory '/root/testdir': Permission denied
|
||||
/root/testdir was not created.
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
正如预期,因为目录无法创建,第一条命令失败了,于是第二条命令被执行。
|
||||
|
||||
把 `&&` 和 `||` 两种运算符结合起来才能发挥它们的最大功效。请看下面例子中的流程控制方法:
|
||||
|
||||
```
|
||||
前置 commands ; command1 && command2 || command3 ; 跟随 commands
|
||||
```
|
||||
|
||||
语法解释:“假如 command1 退出时返回码为零,就执行 command2,否则执行 command3。”用具体代码试试:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Dir=/root/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
|
||||
mkdir: cannot create directory '/root/testdir': Permission denied
|
||||
/root/testdir was not created.
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
现在我们再试一次,用你的家目录替换 `/root` 目录,你将会有权限创建这个目录了:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
像 `command1 && command2` 这样的控制语句能够运行的原因是,每条命令执行完毕时都会给 shell 发送一个返回码,用来表示它执行成功与否。默认情况下,返回码为 `0` 表示成功,其他任何正值表示失败。一些系统管理员使用的工具用值为 `1` 的返回码来表示失败,但其他很多程序使用别的数字来表示失败。
|
||||
|
||||
Bash 的内置变量 `$?` 可以显示上一条命令的返回码,可以在脚本或者命令行中非常方便地检查它。要查看返回码,让我们从运行一条简单的命令开始,返回码的结果总是上一条命令给出的。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ ll ; echo "RC = $?"
|
||||
total 1264
|
||||
drwxrwxr-x 2 student student 4096 Mar 2 08:21 chapter25
|
||||
drwxrwxr-x 2 student student 4096 Mar 21 15:27 chapter26
|
||||
-rwxr-xr-x 1 student student 92 Mar 20 15:53 TestFile1
|
||||
drwxrwxr-x. 2 student student 663552 Feb 21 14:12 testdir
|
||||
drwxr-xr-x. 2 student student 4096 Dec 22 13:15 Videos
|
||||
RC = 0
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
在这个例子中,返回码为零,意味着命令执行成功了。现在对 root 的家目录测试一下,你应该没有权限:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ ll /root ; echo "RC = $?"
|
||||
ls: cannot open directory '/root': Permission denied
|
||||
RC = 2
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
本例中返回码是 `2`,表明非 root 用户没有权限进入这个目录。你可以利用这些返回码,用控制运算符来改变程序执行的顺序。
|
||||
|
||||
### 总结
|
||||
|
||||
本文将 Bash 看作一门编程语言,并从这个视角介绍了它的简单语法和基础工具。我们学习了如何将数据输出到 STDOUT,怎样使用变量和控制运算符。在本系列的下一篇文章中,将会重点介绍能够控制指令执行流程的逻辑运算符。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/programming-bash-part-1
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[jdh8383](https://github.com/jdh8383)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dboth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
|
||||
[2]: https://opensource.com/article/18/10/linux-data-streams
|
||||
[3]: http://www.both.org/?page_id=1183
|
||||
[4]: https://opensource.com/19/9/command-line-heroes-bash
|
||||
[5]: https://en.wikipedia.org/wiki/Comparison_of_command_shells
|
||||
[6]: http://foldoc.org/program
|
||||
[7]: https://wordnet.princeton.edu/
|
||||
[8]: https://en.wikipedia.org/wiki/Computer_program
|
||||
[9]: https://www.gnu.org/software/bc/manual/html_mono/bc.html
|
||||
361
published/20191022 Initializing arrays in Java.md
Normal file
361
published/20191022 Initializing arrays in Java.md
Normal file
@@ -0,0 +1,361 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (laingke)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11533-1.html)
|
||||
[#]: subject: (Initializing arrays in Java)
|
||||
[#]: via: (https://opensource.com/article/19/10/initializing-arrays-java)
|
||||
[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
|
||||
|
||||
Java 中初始化数组
|
||||
======
|
||||
|
||||
> 数组是一种有用的数据类型,用于管理在连续内存位置中建模最好的集合元素。下面是如何有效地使用它们。
|
||||
|
||||
![Coffee beans and a cup of coffee][1]
|
||||
|
||||
有使用 C 或者 FORTRAN 语言编程经验的人会对数组的概念很熟悉。它们基本上是一个连续的内存块,其中每个位置都是某种数据类型:整型、浮点型或者诸如此类的数据类型。
|
||||
|
||||
Java 的情况与此类似,但是有一些额外的问题。
|
||||
|
||||
### 一个数组的示例
|
||||
|
||||
让我们在 Java 中创建一个长度为 10 的整型数组:
|
||||
|
||||
```
|
||||
int[] ia = new int[10];
|
||||
```
|
||||
|
||||
上面的代码片段会发生什么?从左到右依次是:
|
||||
|
||||
1. 最左边的 `int[]` 将变量的*类型*声明为 `int` 数组(由 `[]` 表示)。
|
||||
2. 它的右边是变量的名称,当前为 `ia`。
|
||||
3. 接下来,`=` 告诉我们,左侧定义的变量赋值为右侧的内容。
|
||||
4. 在 `=` 的右侧,我们看到了 `new`,它在 Java 中表示一个对象正在*被初始化中*,这意味着已为其分配存储空间并调用了其构造函数([请参见此处以获取更多信息][2])。
|
||||
5. 然后,我们看到 `int[10]`,它告诉我们正在初始化的这个对象是包含 10 个整型的数组。
|
||||
|
||||
因为 Java 是强类型的,所以变量 `ia` 的类型必须跟 `=` 右侧表达式的类型兼容。
|
||||
|
||||
### 初始化示例数组
|
||||
|
||||
让我们把这个简单的数组放在一段代码中,并尝试运行一下。将以下内容保存到一个名为 `Test1.java` 的文件中,使用 `javac` 编译,使用 `java` 运行(当然是在终端中):
|
||||
|
||||
```
|
||||
import java.lang.*;
|
||||
|
||||
public class Test1 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] ia = new int[10]; // 见下文注 1
|
||||
System.out.println("ia is " + ia.getClass()); // 见下文注 2
|
||||
for (int i = 0; i < ia.length; i++) // 见下文注 3
|
||||
System.out.println("ia[" + i + "] = " + ia[i]); // 见下文注 4
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
让我们来看看最重要的部分。
|
||||
|
||||
1. 我们声明和初始化了长度为 10 的整型数组,即 `ia`,这显而易见。
|
||||
2. 在下面的行中,我们看到表达式 `ia.getClass()`。没错,`ia` 是属于一个*类*的*对象*,这行代码将告诉我们是哪个类。
|
||||
3. 在紧接的下一行中,我们看到了一个循环 `for (int i = 0; i < ia.length; i++)`,它定义了一个循环索引变量 `i`,该变量遍历了从 0 到比 `ia.length` 小 1 的序列,这个表达式告诉我们在数组 `ia` 中定义了多少个元素。
|
||||
4. 接下来,循环体打印出 `ia` 的每个元素的值。
|
||||
|
||||
当这个程序编译和运行时,它产生以下结果:
|
||||
|
||||
```
|
||||
me@mydesktop:~/Java$ javac Test1.java
|
||||
me@mydesktop:~/Java$ java Test1
|
||||
ia is class [I
|
||||
ia[0] = 0
|
||||
ia[1] = 0
|
||||
ia[2] = 0
|
||||
ia[3] = 0
|
||||
ia[4] = 0
|
||||
ia[5] = 0
|
||||
ia[6] = 0
|
||||
ia[7] = 0
|
||||
ia[8] = 0
|
||||
ia[9] = 0
|
||||
me@mydesktop:~/Java$
|
||||
```
|
||||
|
||||
`ia.getClass()` 的输出的字符串表示形式是 `[I`,它是“整数数组”的简写。与 C 语言类似,Java 数组以第 0 个元素开始,扩展到第 `<数组大小> - 1` 个元素。如上所见,我们可以看到数组 `ia` 的每个元素都(似乎由数组构造函数)设置为零。
|
||||
|
||||
所以,就这些吗?声明类型,使用适当的初始化器,就完成了吗?
|
||||
|
||||
好吧,并没有。在 Java 中有许多其它方法来初始化数组。
|
||||
|
||||
### 为什么我要初始化一个数组,有其它方式吗?
|
||||
|
||||
像所有好的问题一样,这个问题的答案是“视情况而定”。在这种情况下,答案取决于初始化后我们希望对数组做什么。
|
||||
|
||||
在某些情况下,数组自然会作为一种累加器出现。例如,假设我们正在编程实现计算小型办公室中一组电话分机接收和拨打的电话数量。一共有 8 个分机,编号为 1 到 8,加上话务员的分机,编号为 0。 因此,我们可以声明两个数组:
|
||||
|
||||
```
|
||||
int[] callsMade;
|
||||
int[] callsReceived;
|
||||
```
|
||||
|
||||
然后,每当我们开始一个新的累计呼叫统计数据的周期时,我们就将每个数组初始化为:
|
||||
|
||||
```
|
||||
callsMade = new int[9];
|
||||
callsReceived = new int[9];
|
||||
```
|
||||
|
||||
在每个累计通话统计数据的最后阶段,我们可以打印出统计数据。粗略地说,我们可能会看到:
|
||||
|
||||
```
|
||||
import java.lang.*;
|
||||
import java.io.*;
|
||||
|
||||
public class Test2 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
int[] callsMade;
|
||||
int[] callsReceived;
|
||||
|
||||
// 初始化呼叫计数器
|
||||
|
||||
callsMade = new int[9];
|
||||
callsReceived = new int[9];
|
||||
|
||||
// 处理呼叫……
|
||||
// 分机拨打电话:callsMade[ext]++
|
||||
// 分机接听电话:callsReceived[ext]++
|
||||
|
||||
// 汇总通话统计
|
||||
|
||||
System.out.printf("%3s%25s%25s\n", "ext", " calls made",
|
||||
"calls received");
|
||||
for (int ext = 0; ext < callsMade.length; ext++) {
|
||||
System.out.printf("%3d%25d%25d\n", ext,
|
||||
callsMade[ext], callsReceived[ext]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
这会产生这样的输出:
|
||||
|
||||
```
|
||||
me@mydesktop:~/Java$ javac Test2.java
|
||||
me@mydesktop:~/Java$ java Test2
|
||||
ext calls made calls received
|
||||
0 0 0
|
||||
1 0 0
|
||||
2 0 0
|
||||
3 0 0
|
||||
4 0 0
|
||||
5 0 0
|
||||
6 0 0
|
||||
7 0 0
|
||||
8 0 0
|
||||
me@mydesktop:~/Java$
|
||||
```
|
||||
|
||||
看来这一天呼叫中心不是很忙。
|
||||
|
||||
在上面的累加器示例中,我们看到由数组初始化程序设置的零起始值可以满足我们的需求。但是在其它情况下,这个起始值可能不是正确的选择。
|
||||
|
||||
例如,在某些几何计算中,我们可能需要将二维数组初始化为单位矩阵(除沿主对角线———左上角到右下角——以外所有全是零)。我们可以选择这样做:
|
||||
|
||||
|
||||
```
|
||||
double[][] m = new double[3][3];
|
||||
for (int d = 0; d < 3; d++) {
|
||||
m[d][d] = 1.0;
|
||||
}
|
||||
```
|
||||
|
||||
在这种情况下,我们依靠数组初始化器 `new double[3][3]` 将数组设置为零,然后使用循环将主对角线上的元素设置为 1。在这种简单情况下,我们可以使用 Java 提供的快捷方式:
|
||||
|
||||
```
|
||||
double[][] m = {
|
||||
{1.0, 0.0, 0.0},
|
||||
{0.0, 1.0, 0.0},
|
||||
{0.0, 0.0, 1.0}};
|
||||
```
|
||||
|
||||
这种可视结构特别适用于这种应用程序,在这种应用程序中,它便于复查数组的实际布局。但是在这种情况下,行数和列数只在运行时确定时,我们可能会看到这样的东西:
|
||||
|
||||
```
|
||||
int nrc;
|
||||
// 一些代码确定行数和列数 = nrc
|
||||
double[][] m = new double[nrc][nrc];
|
||||
for (int d = 0; d < nrc; d++) {
|
||||
m[d][d] = 1.0;
|
||||
}
|
||||
```
|
||||
|
||||
值得一提的是,Java 中的二维数组实际上是数组的数组,没有什么能阻止无畏的程序员让这些第二层数组中的每个数组的长度都不同。也就是说,下面这样的事情是完全合法的:
|
||||
|
||||
```
|
||||
int [][] differentLengthRows = {
|
||||
{1, 2, 3, 4, 5},
|
||||
{6, 7, 8, 9},
|
||||
{10, 11, 12},
|
||||
{13, 14},
|
||||
{15}};
|
||||
```
|
||||
|
||||
在涉及不规则形状矩阵的各种线性代数应用中,可以应用这种类型的结构(有关更多信息,请参见[此 Wikipedia 文章][5])。除此之外,既然我们了解到二维数组实际上是数组的数组,那么以下内容也就不足为奇了:
|
||||
|
||||
```
|
||||
differentLengthRows.length
|
||||
```
|
||||
|
||||
可以告诉我们二维数组 `differentLengthRows` 的行数,并且:
|
||||
|
||||
```
|
||||
differentLengthRows[i].length
|
||||
```
|
||||
|
||||
告诉我们 `differentLengthRows` 第 `i` 行的列数。
|
||||
|
||||
### 深入理解数组
|
||||
|
||||
考虑到在运行时确定数组大小的想法,我们看到数组在实例化之前仍需要我们知道该大小。但是,如果在处理完所有数据之前我们不知道大小怎么办?这是否意味着我们必须先处理一次以找出数组的大小,然后再次处理?这可能很难做到,尤其是如果我们只有一次机会使用数据时。
|
||||
|
||||
[Java 集合框架][6]很好地解决了这个问题。提供的其中一项是 `ArrayList` 类,它类似于数组,但可以动态扩展。为了演示 `ArrayList` 的工作原理,让我们创建一个 `ArrayList` 对象并将其初始化为前 20 个[斐波那契数字][7]:
|
||||
|
||||
```
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Test3 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
ArrayList<Integer> fibos = new ArrayList<Integer>();
|
||||
|
||||
fibos.add(0);
|
||||
fibos.add(1);
|
||||
for (int i = 2; i < 20; i++) {
|
||||
fibos.add(fibos.get(i - 1) + fibos.get(i - 2));
|
||||
}
|
||||
|
||||
for (int i = 0; i < fibos.size(); i++) {
|
||||
System.out.println("fibonacci " + i + " = " + fibos.get(i));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码中,我们看到:
|
||||
|
||||
* 用于存储多个 `Integer` 的 `ArrayList` 的声明和实例化。
|
||||
* 使用 `add()` 附加到 `ArrayList` 实例。
|
||||
* 使用 `get()` 通过索引号检索元素。
|
||||
* 使用 `size()` 来确定 `ArrayList` 实例中已经有多少个元素。
|
||||
|
||||
这里没有展示 `put()` 方法,它的作用是将一个值放在给定的索引号上。
|
||||
|
||||
该程序的输出为:
|
||||
|
||||
```
|
||||
fibonacci 0 = 0
|
||||
fibonacci 1 = 1
|
||||
fibonacci 2 = 1
|
||||
fibonacci 3 = 2
|
||||
fibonacci 4 = 3
|
||||
fibonacci 5 = 5
|
||||
fibonacci 6 = 8
|
||||
fibonacci 7 = 13
|
||||
fibonacci 8 = 21
|
||||
fibonacci 9 = 34
|
||||
fibonacci 10 = 55
|
||||
fibonacci 11 = 89
|
||||
fibonacci 12 = 144
|
||||
fibonacci 13 = 233
|
||||
fibonacci 14 = 377
|
||||
fibonacci 15 = 610
|
||||
fibonacci 16 = 987
|
||||
fibonacci 17 = 1597
|
||||
fibonacci 18 = 2584
|
||||
fibonacci 19 = 4181
|
||||
```
|
||||
|
||||
`ArrayList` 实例也可以通过其它方式初始化。例如,可以给 `ArrayList` 构造器提供一个数组,或者在编译过程中知道初始元素时也可以使用 `List.of()` 和 `array.aslist()` 方法。我发现自己并不经常使用这些方式,因为我对 `ArrayList` 的主要用途是当我只想读取一次数据时。
|
||||
|
||||
此外,对于那些喜欢在加载数据后使用数组的人,可以使用 `ArrayList` 的 `toArray()` 方法将其实例转换为数组;或者,在初始化 `ArrayList` 实例之后,返回到当前数组本身。
|
||||
|
||||
Java 集合框架提供了另一种类似数组的数据结构,称为 `Map`(映射)。我所说的“类似数组”是指 `Map` 定义了一个对象集合,它的值可以通过一个键来设置或检索,但与数组(或 `ArrayList`)不同,这个键不需要是整型数;它可以是 `String` 或任何其它复杂对象。
|
||||
|
||||
例如,我们可以创建一个 `Map`,其键为 `String`,其值为 `Integer` 类型,如下:
|
||||
|
||||
```
|
||||
Map<String, Integer> stoi = new Map<String, Integer>();
|
||||
```
|
||||
|
||||
然后我们可以对这个 `Map` 进行如下初始化:
|
||||
|
||||
```
|
||||
stoi.set("one",1);
|
||||
stoi.set("two",2);
|
||||
stoi.set("three",3);
|
||||
```
|
||||
|
||||
等类似操作。稍后,当我们想要知道 `"three"` 的数值时,我们可以通过下面的方式将其检索出来:
|
||||
|
||||
```
|
||||
stoi.get("three");
|
||||
```
|
||||
|
||||
在我的认知中,`Map` 对于将第三方数据集中出现的字符串转换为我的数据集中的一致代码值非常有用。作为[数据转换管道][8]的一部分,我经常会构建一个小型的独立程序,用作在处理数据之前清理数据;为此,我几乎总是会使用一个或多个 `Map`。
|
||||
|
||||
值得一提的是,`ArrayList` 的 `ArrayList` 和 `Map` 的 `Map` 是很可能的,有时也是合理的。例如,假设我们在看树,我们对按树种和年龄范围累计树的数目感兴趣。假设年龄范围定义是一组字符串值(“young”、“mid”、“mature” 和 “old”),物种是 “Douglas fir”、“western red cedar” 等字符串值,那么我们可以将这个 `Map` 中的 `Map` 定义为:
|
||||
|
||||
```
|
||||
Map<String, Map<String, Integer>> counter = new Map<String, Map<String, Integer>>();
|
||||
```
|
||||
|
||||
这里需要注意的一件事是,以上内容仅为 `Map` 的*行*创建存储。因此,我们的累加代码可能类似于:
|
||||
|
||||
```
|
||||
// 假设我们已经知道了物种和年龄范围
|
||||
if (!counter.containsKey(species)) {
|
||||
counter.put(species,new Map<String, Integer>());
|
||||
}
|
||||
if (!counter.get(species).containsKey(ageRange)) {
|
||||
counter.get(species).put(ageRange,0);
|
||||
}
|
||||
```
|
||||
|
||||
此时,我们可以这样开始累加:
|
||||
|
||||
```
|
||||
counter.get(species).put(ageRange, counter.get(species).get(ageRange) + 1);
|
||||
```
|
||||
|
||||
最后,值得一提的是(Java 8 中的新特性)Streams 还可以用来初始化数组、`ArrayList` 实例和 `Map` 实例。关于此特性的详细讨论可以在[此处][9]和[此处][10]中找到。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/initializing-arrays-java
|
||||
|
||||
作者:[Chris Hermansen][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[laingke](https://github.com/laingke)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/clhermansen
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/java-coffee-mug.jpg?itok=Bj6rQo8r (Coffee beans and a cup of coffee)
|
||||
[2]: https://opensource.com/article/19/8/what-object-java
|
||||
[3]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[4]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
||||
[5]: https://en.wikipedia.org/wiki/Irregular_matrix
|
||||
[6]: https://en.wikipedia.org/wiki/Java_collections_framework
|
||||
[7]: https://en.wikipedia.org/wiki/Fibonacci_number
|
||||
[8]: https://towardsdatascience.com/data-science-for-startups-data-pipelines-786f6746a59a
|
||||
[9]: https://stackoverflow.com/questions/36885371/lambda-expression-to-initialize-array
|
||||
[10]: https://stackoverflow.com/questions/32868665/how-to-initialize-a-map-using-a-lambda
|
||||
261
published/20191023 How to dual boot Windows 10 and Debian 10.md
Normal file
261
published/20191023 How to dual boot Windows 10 and Debian 10.md
Normal file
@@ -0,0 +1,261 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wenwensnow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11557-1.html)
|
||||
[#]: subject: (How to dual boot Windows 10 and Debian 10)
|
||||
[#]: via: (https://www.linuxtechi.com/dual-boot-windows-10-debian-10/)
|
||||
[#]: author: (James Kiarie https://www.linuxtechi.com/author/james/)
|
||||
|
||||
如何拥有一个 Windows 10 和 Debian 10 的双系统
|
||||
======
|
||||
|
||||
在无数次劝说自己后,你终于做出了一个大胆的决定,试试 Linux。不过,在完全熟悉 Linux 之前,你依旧需要使用 Windows 10 系统。幸运的是,通过一个双系统引导设置,能让你在启动时,选择自己想要进入的系统。在这个指南中,你会看到如何 如何双重引导 Windows 10 和 Debian 10。
|
||||
|
||||
![如何拥有一个 Windows 10 和 Debian 10 的双系统][2]
|
||||
|
||||
### 前提条件
|
||||
|
||||
在开始之前,确保你满足下列条件:
|
||||
|
||||
* 一个 Debian 10 的可引导 USB 或 DVD
|
||||
* 一个快速且稳定的网络(为了安装更新以及第三方软件)
|
||||
|
||||
另外,记得注意你系统的引导策略(UEFI 或 Legacy),需要确保两个系统使用同一种引导模式。
|
||||
|
||||
### 第一步:在硬盘上创建一个空余分区
|
||||
|
||||
第一步,你需要在你的硬盘上创建一个空余分区。之后,这将是我们安装 Debian 系统的地方。为了实现这一目的,需要使用下图所示的磁盘管理器:
|
||||
|
||||
同时按下 `Windows + R` 键,启动“运行程序”。接下来,输入 `diskmgmt.msc`,按回车键。
|
||||
|
||||
![启动“运行程序”][3]
|
||||
|
||||
这会启动“磁盘管理”窗口,它会显示你 Windows 上所有已有磁盘。
|
||||
|
||||
![磁盘管理][4]
|
||||
|
||||
接下来,你需要为安装的 Debian 系统创建空余空间。为此,你需要缩小其中一个磁盘(卷)上的分区,从而创建一个未分配的新分区。在这个例子里,我会从 D 盘中创建一个 30 GB 的新分区。
|
||||
|
||||
为了缩小一个卷,右键点击它,然后选中选项 “<ruby>缩小<rt>Shrink volume...</rt></ruby>”。
|
||||
|
||||
![缩小卷][5]
|
||||
|
||||
在弹出窗口中,定义你想缩小的空间大小。记住,这是将来要安装 Debian 10 的磁盘空间。我选择了 30000MB(大约 30 GB)。压缩完成后,点击“<ruby>缩小<rt>Shrink</rt></ruby>”。
|
||||
|
||||
![缩小空间][6]
|
||||
|
||||
在缩小操作结束后,你会看到一个如下图所示的未分配分区:
|
||||
|
||||
![未分配分区][7]
|
||||
|
||||
完美!现在可以准备开始安装了。
|
||||
|
||||
### 第二步:开始安装 Debian 10
|
||||
|
||||
空余分区已经创建好了,将你的可引导 USB 或安装 DVD 插入电脑,重新启动系统。记得更改 BIOS 中的引导顺序,需要在启动时按住功能键(通常,根据品牌不同,是 `F9`、`F10` 或 `F12` 中的某一个)。 这一步骤,对系统是否能进入安装媒体来说,至关重要。保存 BIOS 设置,并重启电脑。
|
||||
|
||||
如下图所示,界面会显示一个新的引导菜单:点击 “Graphical install”。
|
||||
|
||||
![图形化界面安装][8]
|
||||
|
||||
下一步,选择你的偏好语言,然后点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![设置语言-Debian10][9]
|
||||
|
||||
接着,选择你的地区,点击“<ruby>继续<rt>Continue</rt></ruby>”。 根据地区,系统会自动选择当地对应的时区。如果你无法找到你所对应的地区,将界面往下拉, 点击“<ruby>其他<rt>Other</rt></ruby>”后,选择相对应位置。
|
||||
|
||||
![选择地区-Debain10][10]
|
||||
|
||||
而后,选择你的键盘布局。
|
||||
|
||||
![设置键盘-Debain10][11]
|
||||
|
||||
接下来,设置系统的主机名,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![设置主机名-Debian10][12]
|
||||
|
||||
下一步,确定域名。如果你的电脑不在域中,直接点击 “<ruby>继续<rt>Continue</rt></ruby>”按钮。
|
||||
|
||||
![设置域名-Debian10][13]
|
||||
|
||||
然后,如图所示,设置 root 密码,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![设置 root 密码-Debian10][14]
|
||||
|
||||
下一步骤,设置账户的用户全名,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![设置用户全名-debain10][15]
|
||||
|
||||
接着,设置与此账户相关联的用户名。
|
||||
|
||||
![指定用户名-Debian10][16]
|
||||
|
||||
下一步,设置用户密码,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![设置用户密码-Debian10][17]
|
||||
|
||||
然后,设置时区。
|
||||
|
||||
![设置时区-Debian10][18]
|
||||
|
||||
这时,你要为 Debian10 安装创建分区。如果你是新手用户,点击菜单中的第一个选项,“<ruby>使用最大的连续空余空间<rt>Use the largest continuous free space</rt></ruby>”,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![使用最大的连续空余空间-debian10][19]
|
||||
|
||||
不过,如果你对创建分区有所了解的话,选择“<ruby>手动<rt>Manual</rt></ruby>” 选项,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![选择手动-Debain10][20]
|
||||
|
||||
接着,选择被标记为 “<ruby>空余空间<rt>FREE SPACE</rt></ruby>” 的磁盘,点击 “<ruby>继续<rt>Continue</rt></ruby>” 。接下来,点击“<ruby>创建新分区<rt>Create a new partition</rt></ruby>”。
|
||||
|
||||
![创建新分区-Debain10][21]
|
||||
|
||||
下一界面,首先确定交换空间大小。我的交换空间大小为 2GB,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![确定交换空间大小-debian10][22]
|
||||
|
||||
点击下一界面的 “<ruby>主分区<rt>Primary</rt></ruby>”,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![磁盘主分区-Debian10][23]
|
||||
|
||||
选择在磁盘 “<ruby>初始位置<rt>beginning</rt></ruby>” 创建新分区后,点击继续。
|
||||
|
||||
![在初始位置创建-Debain10][24]
|
||||
|
||||
选择 “<ruby>Ext 4 日志文件系统<rt>Ext 4 journaling file system</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![选择 Ext4 日志文件系统-debain10][25]
|
||||
|
||||
下个界面选择“<ruby>交换空间<rt>swap space</rt></ruby>” ,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![选择交换空间-debian10][26]
|
||||
|
||||
选中 “<ruby>完成此分区设置<rt>done setting the partition</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![完成此分区设置-debian10][27]
|
||||
|
||||
返回磁盘分区界面,点击 “<ruby>空余空间<rt>FREE SPACE</rt></ruby>”,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![点击空余空间-Debain10][28]
|
||||
|
||||
为了让自己能轻松一点,选中 “<ruby>自动为空余空间分区<rt>Automatically partition the free space</rt></ruby>”后,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![自动为空余空间分区-Debain10][29]
|
||||
|
||||
接着点击 “<ruby>将所有文件存储在同一分区(新手用户推荐)<rt>All files in one partition (recommended for new users)</rt></ruby>”。
|
||||
|
||||
![将所有文件存储在同一分区-debian10][30]
|
||||
|
||||
最后, 点击 “<ruby>完成分区设置,并将改动写入磁盘<rt>Finish partitioning and write changes to disk</rt></ruby>” ,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![完成分区设置,并将改动写入磁盘][31]
|
||||
|
||||
确定你要将改动写入磁盘,点击 “<ruby>是<rt>Yes</rt></ruby>”。
|
||||
|
||||
![将改动写入磁盘-Debian10][32]
|
||||
|
||||
而后,安装程序会开始安装所有必要的软件包。
|
||||
|
||||
当系统询问是否要扫描其他 CD 时,选择 “<ruby>否<rt>No</rt></ruby>” ,并点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![扫描其他CD-No-Debain10][33]
|
||||
|
||||
接着,选择离你最近的镜像站点地区,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![Debian-镜像站点-国家][34]
|
||||
|
||||
然后,选择最适合你的镜像站点,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![选择镜像站点][35]
|
||||
|
||||
如果你打算使用代理服务器,在下面输入具体信息,没有的话就留空,点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![输入代理信息-debian10][36]
|
||||
|
||||
随着安装进程的继续, 你会被问到,是否想参加一个软件包用途调查。你可以选择任意一个选项,之后点击“<ruby>继续<rt>Continue</rt></ruby>”,我选择了“<ruby>否<rt>No</rt></ruby>”。
|
||||
|
||||
![参与调查-debain10][37]
|
||||
|
||||
在软件选择窗口选中你想安装的软件包,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![软件选择-debian10][38]
|
||||
|
||||
安装程序会将选中的软件一一安装,在这期间,你可以去喝杯咖啡休息一下。
|
||||
|
||||
系统将会询问你,是否要将 grub 的引导装载程序安装到主引导记录表(MBR)上。点击 “<ruby>是<rt>Yes</rt></ruby>”,而后点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![安装-grub-bootloader-debian10][39]
|
||||
|
||||
接着,选中你想安装 grub 的硬盘,点击“<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![选择硬盘-安装 grub-Debian10][40]
|
||||
|
||||
最后,安装完成,直接点击 “<ruby>继续<rt>Continue</rt></ruby>”。
|
||||
|
||||
![安装完成-重新启动-debian10][41]
|
||||
|
||||
你现在应该会有一个列出 Windows 和 Debian 的 grub 菜单。为了引导 Debian 系统,往下选择 Debian。之后,你就能看见登录界面。输入密码之后,按回车键。
|
||||
|
||||
![Debian10-登录][42]
|
||||
|
||||
这就完成了!这样,你就拥有了一个全新的 Debian 10 和 Windows 10 双系统。
|
||||
|
||||
![Debian10-Buster-Details][43]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxtechi.com/dual-boot-windows-10-debian-10/
|
||||
|
||||
作者:[James Kiarie][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wenwensnow](https://github.com/wenwensnow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linuxtechi.com/author/james/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/How-to-dual-boot-Windows-and-Debian10.jpg
|
||||
[3]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Launch-Run-dialogue.jpg
|
||||
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Disk-management.jpg
|
||||
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Shrink-volume.jpg
|
||||
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Shrink-space.jpg
|
||||
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Unallocated-partition.jpg
|
||||
[8]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Graphical-Install-Debian10.jpg
|
||||
[9]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Language-Debian10.jpg
|
||||
[10]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-location-Debain10.jpg
|
||||
[11]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Configure-Keyboard-layout-Debain10.jpg
|
||||
[12]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-hostname-Debian10.jpg
|
||||
[13]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-domain-name-Debian10.jpg
|
||||
[14]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Set-root-Password-Debian10.jpg
|
||||
[15]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-fullname-user-debain10.jpg
|
||||
[16]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-username-Debian10.jpg
|
||||
[17]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Specify-user-password-Debian10.jpg
|
||||
[18]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Configure-timezone-Debian10.jpg
|
||||
[19]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Use-largest-continuous-free-space-debian10.jpg
|
||||
[20]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Manual-Debain10.jpg
|
||||
[21]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Create-new-partition-Debain10.jpg
|
||||
[22]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Define-swap-space-debian10.jpg
|
||||
[23]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Partition-Disks-Primary-Debain10.jpg
|
||||
[24]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Start-at-the-beginning-Debain10.jpg
|
||||
[25]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Ext4-Journaling-system-debain10.jpg
|
||||
[26]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-swap-debain10.jpg
|
||||
[27]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Done-setting-partition-debian10.jpg
|
||||
[28]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Click-Free-space-Debain10.jpg
|
||||
[29]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Automatically-partition-free-space-Debain10.jpg
|
||||
[30]: https://www.linuxtechi.com/wp-content/uploads/2019/10/All-files-in-one-partition-debian10.jpg
|
||||
[31]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Finish-partitioning-write-changes-to-disk.jpg
|
||||
[32]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Write-changes-to-disk-Yes-Debian10.jpg
|
||||
[33]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Scan-another-CD-No-Debain10.jpg
|
||||
[34]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian-archive-mirror-country.jpg
|
||||
[35]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-Debian-archive-mirror.jpg
|
||||
[36]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Enter-proxy-details-debian10.jpg
|
||||
[37]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Participate-in-survey-debain10.jpg
|
||||
[38]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Software-selection-debian10.jpg
|
||||
[39]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Install-grub-bootloader-debian10.jpg
|
||||
[40]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Select-hard-drive-install-grub-Debian10.jpg
|
||||
[41]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Installation-complete-reboot-debian10.jpg
|
||||
[42]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian10-log-in.jpg
|
||||
[43]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Debian10-Buster-Details.jpg
|
||||
@@ -0,0 +1,116 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Morisun029)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11534-1.html)
|
||||
[#]: subject: (Open Source CMS Ghost 3.0 Released with New features for Publishers)
|
||||
[#]: via: (https://itsfoss.com/ghost-3-release/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
开源 CMS Ghost 3.0 发布,带来新功能
|
||||
======
|
||||
|
||||
[Ghost][1] 是一个自由开源的内容管理系统(CMS)。如果你还不了解 CMS,那我在此解释一下。CMS 是一种软件,用它可以构建主要专注于创建内容的网站,而无需了解 HTML 和其他与 Web 相关的技术。
|
||||
|
||||
事实上,Ghost 是目前[最好的开源 CMS][2] 之一。它主要聚焦于创建轻量级、快速加载、界面美观的博客。
|
||||
|
||||
Ghost 系统有一个现代直观的编辑器,该编辑器内置 SEO(搜索引擎优化)功能。你也可以用本地桌面(包括 Linux 系统)和移动应用程序。如果你喜欢终端,也可以使用其提供的 CLI(命令行界面)工具。
|
||||
|
||||
让我们看看 Ghost 3.0 带来了什么新功能。
|
||||
|
||||
### Ghost 3.0 的新功能
|
||||
|
||||
![][3]
|
||||
|
||||
我通常对开源的 CMS 解决方案很感兴趣。因此,在阅读了官方公告后,我通过在 Digital Ocean 云服务器上安装新的 Ghost 实例来进一步尝试它。
|
||||
|
||||
与以前的版本相比,Ghost 3.0 在功能和用户界面上的改进给我留下了深刻的印象。
|
||||
|
||||
在此,我将列出一些值得一提的关键点。
|
||||
|
||||
#### 书签卡
|
||||
|
||||
![][5]
|
||||
|
||||
除了编辑器的所有细微更改之外,3.0 版本现在支持通过输入 URL 添加漂亮的书签卡。
|
||||
|
||||
如果你使用过 WordPress(你可能已经注意到,WordPress 需要添加一个插件才能添加类似的卡片),所以该功能绝对是 Ghost 3.0 系统的一个最大改进。
|
||||
|
||||
#### 改进的 WordPress 迁移插件
|
||||
|
||||
我没有专门对此进行测试,但它更新了 WordPress 的迁移插件,可以让你轻松地将帖子(带有图片)克隆到 Ghost CMS。
|
||||
|
||||
基本上,使用该插件,你就能够创建一个存档(包含图片)并将其导入到 Ghost CMS。
|
||||
|
||||
#### 响应式图像库和图片
|
||||
|
||||
为了使用户体验更好,Ghost 团队还更新了图像库(现已为响应式),以便在所有设备上舒适地呈现你的图片集。
|
||||
|
||||
此外,帖子和页面中的图片也更改为响应式的了。
|
||||
|
||||
#### 添加成员和订阅选项
|
||||
|
||||
![Ghost Subscription Model][6]
|
||||
|
||||
虽然,该功能目前还处于测试阶段,但如果你是以此平台作为维持你业务关系的重要发布平台,你可以为你的博客添加成员、订阅选项。
|
||||
|
||||
该功能可以确保只有订阅的成员才能访问你的博客,你也可以选择让未订阅者也可以访问。
|
||||
|
||||
#### Stripe:集成支付功能
|
||||
|
||||
默认情况下,该版本支持 Stripe 付款网关,帮助你轻松启用订阅功能(或使用任何类型的付款的付款方式),而 Ghost 不收取任何额外费用。
|
||||
|
||||
#### 新的应用程序集成
|
||||
|
||||
![][7]
|
||||
|
||||
你现在可以在 Ghost 3.0 的博客中集成各种流行的应用程序/服务。它可以使很多事情自动化。
|
||||
|
||||
#### 默认主题改进
|
||||
|
||||
引入的默认主题(设计)已得到改进,现在也提供了夜间模式。
|
||||
|
||||
你也可以随时选择创建自定义主题(如果没有可用的预置主题)。
|
||||
|
||||
#### 其他小改进
|
||||
|
||||
除了所有关键亮点以外,用于创建帖子/页面的可视编辑器也得到了改进(具有某些拖放功能)。
|
||||
|
||||
我确定还有很多技术方面的更改,如果你对此感兴趣,可以在他们的[更改日志][8]中查看。
|
||||
|
||||
### Ghost 影响力渐增
|
||||
|
||||
要在以 WordPress 为主导的世界中获得认可并不是一件容易的事。但 Ghost 逐渐形成了它的一个专门的发布者社区。
|
||||
|
||||
不仅如此,它的托管服务 [Ghost Pro][9] 现在拥有像 NASA、Mozilla 和 DuckDuckGo 这样的客户。
|
||||
|
||||
在过去的六年中,Ghost 从其 Ghost Pro 客户那里获得了 500 万美元的收入。就从它是致力于开源系统解决方案的非营利组织这一点来讲,这确实是一项成就。
|
||||
|
||||
这些收入有助于它们保持独立,避免风险投资家的外部资金投入。Ghost CMS 的托管客户越多,投入到免费和开源的 CMS 的研发款项就越多。
|
||||
|
||||
总体而言,Ghost 3.0 是迄今为止提供的最好的升级版本。这些功能给我留下了深刻的印象。
|
||||
|
||||
如果你拥有自己的网站,你会使用什么 CMS?你曾经使用过 Ghost 吗?你的体验如何?请在评论部分分享你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/ghost-3-release/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Morisun029](https://github.com/Morisun029)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/recommends/ghost/
|
||||
[2]: https://itsfoss.com/open-source-cms/
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-3.jpg?ssl=1
|
||||
[4]: https://itsfoss.com/recommends/digital-ocean/
|
||||
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-editor-screenshot.png?ssl=1
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-subscription-model.jpg?resize=800%2C503&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/10/ghost-app-integration.jpg?ssl=1
|
||||
[8]: https://ghost.org/faq/upgrades/
|
||||
[9]: https://itsfoss.com/recommends/ghost-pro/
|
||||
@@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11528-1.html)
|
||||
[#]: subject: (4 cool new projects to try in COPR for October 2019)
|
||||
[#]: via: (https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-october-2019/)
|
||||
[#]: author: (Dominik Turecek https://fedoramagazine.org/author/dturecek/)
|
||||
@@ -18,8 +18,7 @@ COPR 是个人软件仓库[集合][2],它不在 Fedora 中。这是因为某
|
||||
|
||||
### Nu
|
||||
|
||||
[Nu][4] 或称为 Nushell 是受 PowerShell 和现代 CLI 工具启发的 shell。通过使用基于结构化数据的方法,Nu 可轻松处理命令的输出,并通过管道传输其他命令。然后将结果显示在可以轻松排序或过滤的表中,并可以用作其他命令的输入。最后,Nu 提供了几个内置命令、多 shell 和对插件的支持。
|
||||
|
||||
[Nu][4] 也被称为 Nushell,是受 PowerShell 和现代 CLI 工具启发的 shell。通过使用基于结构化数据的方法,Nu 可轻松处理命令的输出,并通过管道传输其他命令。然后将结果显示在可以轻松排序或过滤的表中,并可以用作其他命令的输入。最后,Nu 提供了几个内置命令、多 shell 和对插件的支持。
|
||||
|
||||
#### 安装说明
|
||||
|
||||
@@ -58,7 +57,7 @@ sudo dnf install crow-translate
|
||||
|
||||
### dnsmeter
|
||||
|
||||
[dnsmeter][10] 是用于测试域名服务器及其基础设施性能的命令行工具。为此,它发送 DNS 查询并计算答复数,从而测量各种统计数据。除此之外,dnsmeter 可以使用不同的加载步骤,使用 PCAP 文件中的 payload 和欺骗发送者地址。
|
||||
[dnsmeter][10] 是用于测试域名服务器及其基础设施性能的命令行工具。为此,它发送 DNS 查询并计算答复数,从而测量各种统计数据。除此之外,dnsmeter 可以使用不同的加载步骤,使用 PCAP 文件中的载荷和欺骗发送者地址。
|
||||
|
||||
#### 安装说明
|
||||
|
||||
@@ -76,7 +75,7 @@ via: https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-october-2
|
||||
作者:[Dominik Turecek][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/) 荣誉推出
|
||||
|
||||
@@ -91,4 +90,4 @@ via: https://fedoramagazine.org/4-cool-new-projects-to-try-in-copr-for-october-2
|
||||
[7]: https://copr.fedorainfracloud.org/coprs/lyessaadi/notekit/
|
||||
[8]: https://github.com/crow-translate/crow-translate
|
||||
[9]: https://copr.fedorainfracloud.org/coprs/faezebax/crow-translate/
|
||||
[10]: https://github.com/DNS-OARC/dnsmeter
|
||||
[10]: https://github.com/DNS-OARC/dnsmeter
|
||||
@@ -0,0 +1,132 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11592-1.html)
|
||||
[#]: subject: (How I used the wget Linux command to recover lost images)
|
||||
[#]: via: (https://opensource.com/article/19/10/how-community-saved-artwork-creative-commons)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
丢失的开放剪贴画库和新的公共艺术品图书馆 FreeSVG.org 的诞生
|
||||
======
|
||||
|
||||
> 开放剪贴画库兴衰的故事以及一个新的公共艺术品图书馆 FreeSVG.org 的诞生。
|
||||
|
||||

|
||||
|
||||
<ruby>开放剪贴画库<rt>Open Clip Art Library</rt></ruby>(OCAL)发布于 2004 年,成为了免费插图的来源,任何人都可以出于任何目的使用它们,而无需注明出处或提供任何回报。针对 1990 年代每个家庭办公室书架上的大量剪贴画 CD 以及由闭源公司和艺术品软件提供的艺术品转储,这个网站是开源世界的回应。
|
||||
|
||||
最初,这个剪贴画库主要由一些贡献者提供,但是在 2010 年,它重新打造成了一个全新的交互式网站,可以让任何人使用矢量插图应用程序创建和贡献剪贴画。该网站立即获得了来自全球的、各种形式的自由软件和自由文化项目的贡献。[Inkscape][2] 中甚至包含了该库的专用导入器。
|
||||
|
||||
但是,在 2019 年初,托管开放剪贴画库的网站离线了,没有任何警告或解释。它已经成长为有着成千上万的人的社区,起初以为这是暂时的故障。但是,这个网站一直离线已超过六个月,而没有任何清楚的解释。
|
||||
|
||||
谣言开始膨胀。该网站一直在更新中(“要偿还数年的技术债务”,网站开发者 Jon Philips 在一封电子邮件中说)。一个 Twitter 帐户声称,该网站遭受了猖狂的 DDoS 攻击。另一个 Twitter 帐户声称,该网站维护者已经成为身份盗用的牺牲品。今天,在撰写本文时,该网站的一个且唯一的页面声明它处于“维护和保护模式”,其含义不清楚,只是用户无法访问其内容。
|
||||
|
||||
### 恢复公地
|
||||
|
||||
网站会随着时间的流逝而消失,但是对其社区而言,开放剪贴画库的丢失尤其令人惊讶,因为它被视为一个社区项目。很少有社区成员知道托管该库的网站已经落入单个维护者手中,因此,由于 [CC0 许可证][3],该库中的艺术品归所有人所有,但对它的访问是由单个维护者功能性拥有的。而且,由于该社区通过网站彼此保持联系,因此该维护者实际上拥有该社区。
|
||||
|
||||
当网站发生故障时,社区以及成员彼此之间都无法访问剪贴画。没有该网站,就没有社区。
|
||||
|
||||
最初,该网站离线后其上的所有东西都是被封锁的。不过,在几个月之后,用户开始意识到该网站的数据仍然在线,这意味着用户能够通过输入精确的 URL 访问单个剪贴画。换句话说,你不能通过在网站上到处点击来浏览剪贴画文件,但是如果你确切地知道该地址,你就可以在浏览器中访问它。类似的,技术型(或偷懒的)用户意识到能够通过类似 `wget` 的自动 Web 浏览器将网站“抓取”下来。
|
||||
|
||||
Linux 的 `wget` 命令从技术上来说是一个 Web 浏览器,虽然它不能让你像用 Firefox 一样交互式地浏览。相反,`wget` 可以连到互联网,获取文件或文件集,并下载到你的本次硬盘。然后,你可以在 Firefox、文本编辑器或最合适的应用程序中打开这些文件,查看内容。
|
||||
|
||||
通常,`wget` 需要知道要提取的特定文件。如果你使用的是安装了 `wget` 的 Linux 或 macOS,则可以通过下载 [example.com][4] 的索引页来尝试此过程:
|
||||
|
||||
```
|
||||
$ wget example.org/index.html
|
||||
[...]
|
||||
$ tail index.html
|
||||
|
||||
<body><div>
|
||||
<h1>Example Domain</h1>
|
||||
<p>This domain is for illustrative examples in documents.
|
||||
You may use this domain in examples without permission.</p>
|
||||
<p><a href="http://www.iana.org/domains/example">More info</a></p>
|
||||
</div></body></html>
|
||||
```
|
||||
|
||||
为了抓取 OCAL,我使用了 `--mirror` 选项,以便可以只是将 `wget` 指向到包含剪贴画的目录,就可以下载该目录中的所有内容。此操作持续下载了连续四天(96 个小时),最终得到了超过 50,000 个社区成员贡献的 100,000 个 SVG 文件。不幸的是,任何没有适当元数据的文件的作者信息都是无法恢复的,因为此信息被锁定在该数据库中不可访问的文件中,但是 CC0 许可证意味着此问题*在技术上*无关紧要(因为 CC0 文件不需要归属)。
|
||||
|
||||
随意分析了一下下载的文件进行还显示,其中近 45,000 个文件是同一个文件(该网站的徽标)的副本。这是由于指向该网站徽标的重定向引起的(原因未知),仔细分析能够提取到原始的文件,又过了 96 个小时,并且恢复了直到最后一天发布在 OCAL 上的所有剪贴画:总共约有 156,000 张图像。
|
||||
|
||||
SVG 文件通常很小,但这仍然是大量工作,并且会带来一些非常实际的问题。首先,将需要数 GB 的在线存储空间,这样这些剪贴画才能供其先前的社区使用。其次,必须使用一种搜索剪贴画的方法,因为手动浏览 55,000 个文件是不现实的。
|
||||
|
||||
很明显,社区真正需要的是一个平台。
|
||||
|
||||
### 构建新的平台
|
||||
|
||||
一段时间以来,[公共领域矢量图][6] 网站一直在发布公共领域的矢量图。虽然它仍然是一个受欢迎的网站,但是开源用户通常只是将其用作辅助的图片资源,因为其中大多数文件都是 EPS 和 AI 格式的,这两者均与 Adobe 相关。这两种文件格式通常都可以转换为 SVG,但是特性会有所损失。
|
||||
|
||||
当公共领域矢量图网站的维护者(Vedran 和 Boris)得知 OCAL 丢失时,他们决定创建一个面向开源社区的网站。诚然,他们选择了开源 [Laravel][7] 框架作为后端,该框架为网站提供了管理控制台和用户访问权限。该框架功能强大且开发完善,还使他们能够快速响应错误报告和功能请求,并根据需要升级网站。他们正在建立的网站称为 [FreeSVG.org][8],已经是一个强大而繁荣的公共艺术品图书馆。
|
||||
|
||||
从那时起,他们就一直从 OCAL 上载所有剪贴画,并且他们甚至在努力地对这些剪贴画进行标记和分类。作为公共领域矢量图网站的创建者,他们还以 SVG 格式贡献了自己的图像。他们的目标是成为互联网上具有 CC0 许可证的 SVG 图像的主要资源。
|
||||
|
||||
### 贡献
|
||||
|
||||
[FreeSVG.org][8] 的维护者意识到他们已经继承了重要的管理权。他们正在努力对网站上的所有图像加上标题和描述,以便用户可以轻松找到这些剪贴画,并在准备就绪后将其提供给社区,同时坚信同这些剪贴画一样,与这些剪贴画有关的元数据属于创建和使用它们的人。他们还意识到可能会发生无法预料的情况,因此他们会定期为其网站和内容创建备份,并打算在其网站出现故障时向公众提供最新备份。
|
||||
|
||||
如果要为 [FreeSVG.org][9]的知识共享内容添砖加瓦,请下载 [Inkscape][10] 并开始绘制。世界上有很多公共领域的艺术品,例如[历史广告][11]、[塔罗牌][12]和[故事书][13],只是在等待转换为 SVG,因此即使你对自己的绘画技巧没有信心你也可以做出贡献。访问 [FreeSVG 论坛][14]与其他贡献者联系并支持他们。
|
||||
|
||||
*公地*的概念很重要。无论你是学生、老师、图书馆员、小企业主还是首席执行官,[知识共享都会使所有人受益][15]。如果你不直接捐款,那么你随时可以帮助推广。
|
||||
|
||||
这是自由文化的力量:它不仅可以扩展,而且随着更多人的参与,它会变得更好。
|
||||
|
||||
### 艰辛的教训
|
||||
|
||||
从 OCAL 的消亡到 FreeSVG.org 的兴起,开放文化社区已经吸取了一些艰辛的经验。对于以后,以下是我认为最重要的那些。
|
||||
|
||||
#### 维护你的元数据
|
||||
|
||||
如果你是内容创建者,请帮助将来的档案管理员,将元数据添加到文件中。大多数图像、音乐、字体和视频文件格式都可以嵌入 EXIF 数据,其他格式在创建它们的应用程序中具有元数据输入界面。勤于用你的姓名、网站或公共电子邮件以及许可证来标记你的作品。
|
||||
|
||||
#### 做个副本
|
||||
|
||||
不要以为别人在做备份。如果你关心公用数字内容,请自己备份,否则不要指望永远提供它。无论*任何上传到互联网上的内容是永久的*的说法是不是正确的,但这并不意味着你永远可以使用。如果 OCAL 文件不再暗地可用,那么任何人都不太可能成功地从网络上的某个位置或从全球范围内的人们的硬盘中成功地发现全部的 55,000 张图像。
|
||||
|
||||
#### 创建外部渠道
|
||||
|
||||
如果一个社区是由单个网站或实际位置来定义的,那么该社区失去访问该空间的能力就如同解散了一样。如果你是由单个组织或网站驱动的社区的成员,则你应该自己与关心的人共享联系信息,并即使在该网站不可用时也可以建立沟通渠道。
|
||||
|
||||
例如,[Opensource.com][16] 本身维护其作者和通讯者的邮件列表和其他异地渠道,以便在有或没有网站干预或甚至没有网站的情况下相互交流。
|
||||
|
||||
#### 自由文化值得为此努力
|
||||
|
||||
互联网有时被视为懒人社交俱乐部。你可以在需要时登录并在感到疲倦时将其关闭,也可以漫步到所需的任何社交圈。
|
||||
|
||||
但实际上,自由文化可能是项艰难的工作。但是这种艰难从某种意义上讲并不是说要成为其中的一分子很困难,而是你必须努力维护。如果你忽略你所在的社区,那么该社区可能会在你意识到之前就枯萎并褪色。
|
||||
|
||||
花点时间环顾四周,确定你属于哪个社区,如果不是,那么请告诉某人你对他们带给你生活的意义表示赞赏。同样重要的是,请记住,这样你也为社区的生活做出了贡献。
|
||||
|
||||
几周前,知识共享组织在华沙举行了它的全球峰会,令人惊叹的国际盛会...
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/how-community-saved-artwork-creative-commons
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tribal_pattern_shoes.png?itok=e5dSf2hS (White shoes on top of an orange tribal pattern)
|
||||
[2]: https://opensource.com/article/18/1/inkscape-absolute-beginners
|
||||
[3]: https://creativecommons.org/share-your-work/public-domain/cc0/
|
||||
[4]: http://example.com
|
||||
[5]: http://www.iana.org/domains/example"\>More
|
||||
[6]: http://publicdomainvectors.org
|
||||
[7]: https://github.com/viralsolani/laravel-adminpanel
|
||||
[8]: https://freesvg.org
|
||||
[9]: http://freesvg.org
|
||||
[10]: http://inkscape.org
|
||||
[11]: https://freesvg.org/drinking-coffee-vector-drawing
|
||||
[12]: https://freesvg.org/king-of-swords-tarot-card
|
||||
[13]: https://freesvg.org/space-pioneers-135-scene-vector-image
|
||||
[14]: http://forum.freesvg.org/
|
||||
[15]: https://opensource.com/article/18/1/creative-commons-real-world
|
||||
[16]: http://Opensource.com
|
||||
@@ -0,0 +1,406 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11545-1.html)
|
||||
[#]: subject: (Understanding system calls on Linux with strace)
|
||||
[#]: via: (https://opensource.com/article/19/10/strace)
|
||||
[#]: author: (Gaurav Kamathe https://opensource.com/users/gkamathe)
|
||||
|
||||
在 Linux 上用 strace 来理解系统调用
|
||||
======
|
||||
|
||||
> 使用 strace 跟踪用户进程和 Linux 内核之间的交互。
|
||||
|
||||
![Hand putting a Linux file folder into a drawer][1]
|
||||
|
||||
<ruby>系统调用<rt>system call</rt></ruby>是程序从内核请求服务的一种编程方式,而 `strace` 是一个功能强大的工具,可让你跟踪用户进程与 Linux 内核之间的交互。
|
||||
|
||||
要了解操作系统的工作原理,首先需要了解系统调用的工作原理。操作系统的主要功能之一是为用户程序提供抽象机制。
|
||||
|
||||
操作系统可以大致分为两种模式:
|
||||
|
||||
* 内核模式:操作系统内核使用的一种强大的特权模式
|
||||
* 用户模式:大多数用户应用程序运行的地方
|
||||
|
||||
用户大多使用命令行实用程序和图形用户界面(GUI)来执行日常任务。系统调用在后台静默运行,与内核交互以完成工作。
|
||||
|
||||
系统调用与函数调用非常相似,这意味着它们都接受并处理参数然后返回值。唯一的区别是系统调用进入内核,而函数调用不进入。从用户空间切换到内核空间是使用特殊的 [trap][2] 机制完成的。
|
||||
|
||||
通过使用系统库(在 Linux 系统上又称为 glibc),大部分系统调用对用户隐藏了。尽管系统调用本质上是通用的,但是发出系统调用的机制在很大程度上取决于机器(架构)。
|
||||
|
||||
本文通过使用一些常规命令并使用 `strace` 分析每个命令进行的系统调用来探索一些实际示例。这些示例使用 Red Hat Enterprise Linux,但是这些命令运行在其他 Linux 发行版上应该也是相同的:
|
||||
|
||||
```
|
||||
[root@sandbox ~]# cat /etc/redhat-release
|
||||
Red Hat Enterprise Linux Server release 7.7 (Maipo)
|
||||
[root@sandbox ~]#
|
||||
[root@sandbox ~]# uname -r
|
||||
3.10.0-1062.el7.x86_64
|
||||
[root@sandbox ~]#
|
||||
```
|
||||
|
||||
首先,确保在系统上安装了必需的工具。你可以使用下面的 `rpm` 命令来验证是否安装了 `strace`。如果安装了,则可以使用 `-V` 选项检查 `strace` 实用程序的版本号:
|
||||
|
||||
```
|
||||
[root@sandbox ~]# rpm -qa | grep -i strace
|
||||
strace-4.12-9.el7.x86_64
|
||||
[root@sandbox ~]#
|
||||
[root@sandbox ~]# strace -V
|
||||
strace -- version 4.12
|
||||
[root@sandbox ~]#
|
||||
```
|
||||
|
||||
如果没有安装,运行命令安装:
|
||||
|
||||
```
|
||||
yum install strace
|
||||
```
|
||||
|
||||
出于本示例的目的,在 `/tmp` 中创建一个测试目录,并使用 `touch` 命令创建两个文件:
|
||||
|
||||
```
|
||||
[root@sandbox ~]# cd /tmp/
|
||||
[root@sandbox tmp]#
|
||||
[root@sandbox tmp]# mkdir testdir
|
||||
[root@sandbox tmp]#
|
||||
[root@sandbox tmp]# touch testdir/file1
|
||||
[root@sandbox tmp]# touch testdir/file2
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
(我使用 `/tmp` 目录是因为每个人都可以访问它,但是你可以根据需要选择另一个目录。)
|
||||
|
||||
在 `testdir` 目录下使用 `ls` 命令验证该文件已经创建:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# ls testdir/
|
||||
file1 file2
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
你可能每天都在使用 `ls` 命令,而没有意识到系统调用在其下面发挥的作用。抽象地来说,该命令的工作方式如下:
|
||||
|
||||
> 命令行工具 -> 从系统库(glibc)调用函数 -> 调用系统调用
|
||||
|
||||
`ls` 命令内部从 Linux 上的系统库(即 glibc)调用函数。这些库去调用完成大部分工作的系统调用。
|
||||
|
||||
如果你想知道从 glibc 库中调用了哪些函数,请使用 `ltrace` 命令,然后跟上常规的 `ls testdir/`命令:
|
||||
|
||||
```
|
||||
ltrace ls testdir/
|
||||
```
|
||||
|
||||
如果没有安装 `ltrace`,键入如下命令安装:
|
||||
|
||||
```
|
||||
yum install ltrace
|
||||
```
|
||||
|
||||
大量的输出会被堆到屏幕上;不必担心,只需继续就行。`ltrace` 命令输出中与该示例有关的一些重要库函数包括:
|
||||
|
||||
```
|
||||
opendir("testdir/") = { 3 }
|
||||
readdir({ 3 }) = { 101879119, "." }
|
||||
readdir({ 3 }) = { 134, ".." }
|
||||
readdir({ 3 }) = { 101879120, "file1" }
|
||||
strlen("file1") = 5
|
||||
memcpy(0x1665be0, "file1\0", 6) = 0x1665be0
|
||||
readdir({ 3 }) = { 101879122, "file2" }
|
||||
strlen("file2") = 5
|
||||
memcpy(0x166dcb0, "file2\0", 6) = 0x166dcb0
|
||||
readdir({ 3 }) = nil
|
||||
closedir({ 3 })
|
||||
```
|
||||
|
||||
通过查看上面的输出,你或许可以了解正在发生的事情。`opendir` 库函数打开一个名为 `testdir` 的目录,然后调用 `readdir` 函数,该函数读取目录的内容。最后,有一个对 `closedir` 函数的调用,该函数将关闭先前打开的目录。现在请先忽略其他 `strlen` 和 `memcpy` 功能。
|
||||
|
||||
你可以看到正在调用哪些库函数,但是本文将重点介绍由系统库函数调用的系统调用。
|
||||
|
||||
与上述类似,要了解调用了哪些系统调用,只需将 `strace` 放在 `ls testdir` 命令之前,如下所示。 再次,一堆乱码丢到了你的屏幕上,你可以按照以下步骤进行操作:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# strace ls testdir/
|
||||
execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
brk(NULL) = 0x1f12000
|
||||
<<< truncated strace output >>>
|
||||
write(1, "file1 file2\n", 13file1 file2
|
||||
) = 13
|
||||
close(1) = 0
|
||||
munmap(0x7fd002c8d000, 4096) = 0
|
||||
close(2) = 0
|
||||
exit_group(0) = ?
|
||||
+++ exited with 0 +++
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
运行 `strace` 命令后屏幕上的输出就是运行 `ls` 命令的系统调用。每个系统调用都为操作系统提供了特定的用途,可以将它们大致分为以下几个部分:
|
||||
|
||||
* 进程管理系统调用
|
||||
* 文件管理系统调用
|
||||
* 目录和文件系统管理系统调用
|
||||
* 其他系统调用
|
||||
|
||||
分析显示到屏幕上的信息的一种更简单的方法是使用 `strace` 方便的 `-o` 标志将输出记录到文件中。在 `-o` 标志后添加一个合适的文件名,然后再次运行命令:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# strace -o trace.log ls testdir/
|
||||
file1 file2
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
这次,没有任何输出干扰屏幕显示,`ls` 命令如预期般工作,显示了文件名并将所有输出记录到文件 `trace.log` 中。仅仅是一个简单的 `ls` 命令,该文件就有近 100 行内容:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# ls -l trace.log
|
||||
-rw-r--r--. 1 root root 7809 Oct 12 13:52 trace.log
|
||||
[root@sandbox tmp]#
|
||||
[root@sandbox tmp]# wc -l trace.log
|
||||
114 trace.log
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
让我们看一下这个示例的 `trace.log` 文件的第一行:
|
||||
|
||||
```
|
||||
execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
```
|
||||
|
||||
* 该行的第一个单词 `execve` 是正在执行的系统调用的名称。
|
||||
* 括号内的文本是提供给该系统调用的参数。
|
||||
* 符号 `=` 后的数字(在这种情况下为 `0`)是 `execve` 系统调用的返回值。
|
||||
|
||||
现在的输出似乎还不太吓人,对吧。你可以应用相同的逻辑来理解其他行。
|
||||
|
||||
现在,将关注点集中在你调用的单个命令上,即 `ls testdir`。你知道命令 `ls` 使用的目录名称,那么为什么不在 `trace.log` 文件中使用 `grep` 查找 `testdir` 并查看得到的结果呢?让我们详细查看一下结果的每一行:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# grep testdir trace.log
|
||||
execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
stat("testdir/", {st_mode=S_IFDIR|0755, st_size=32, ...}) = 0
|
||||
openat(AT_FDCWD, "testdir/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
回顾一下上面对 `execve` 的分析,你能说一下这个系统调用的作用吗?
|
||||
|
||||
```
|
||||
execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
```
|
||||
|
||||
你无需记住所有系统调用或它们所做的事情,因为你可以在需要时参考文档。手册页可以解救你!在运行 `man` 命令之前,请确保已安装以下软件包:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# rpm -qa | grep -i man-pages
|
||||
man-pages-3.53-5.el7.noarch
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
请记住,你需要在 `man` 命令和系统调用名称之间添加 `2`。如果使用 `man man` 阅读 `man` 命令的手册页,你会看到第 2 节是为系统调用保留的。同样,如果你需要有关库函数的信息,则需要在 `man` 和库函数名称之间添加一个 `3`。
|
||||
|
||||
以下是手册的章节编号及其包含的页面类型:
|
||||
|
||||
* `1`:可执行的程序或 shell 命令
|
||||
* `2`:系统调用(由内核提供的函数)
|
||||
* `3`:库调用(在程序的库内的函数)
|
||||
* `4`:特殊文件(通常出现在 `/dev`)
|
||||
|
||||
使用系统调用名称运行以下 `man` 命令以查看该系统调用的文档:
|
||||
|
||||
```
|
||||
man 2 execve
|
||||
```
|
||||
|
||||
按照 `execve` 手册页,这将执行在参数中传递的程序(在本例中为 `ls`)。可以为 `ls` 提供其他参数,例如本例中的 `testdir`。因此,此系统调用仅以 `testdir` 作为参数运行 `ls`:
|
||||
|
||||
```
|
||||
execve - execute program
|
||||
|
||||
DESCRIPTION
|
||||
execve() executes the program pointed to by filename
|
||||
```
|
||||
|
||||
下一个系统调用,名为 `stat`,它使用 `testdir` 参数:
|
||||
|
||||
```
|
||||
stat("testdir/", {st_mode=S_IFDIR|0755, st_size=32, ...}) = 0
|
||||
```
|
||||
|
||||
使用 `man 2 stat` 访问该文档。`stat` 是获取文件状态的系统调用,请记住,Linux 中的一切都是文件,包括目录。
|
||||
|
||||
接下来,`openat` 系统调用将打开 `testdir`。密切注意返回的 `3`。这是一个文件描述符,将在以后的系统调用中使用:
|
||||
|
||||
```
|
||||
openat(AT_FDCWD, "testdir/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
|
||||
```
|
||||
|
||||
到现在为止一切都挺好。现在,打开 `trace.log` 文件,并转到 `openat` 系统调用之后的行。你会看到 `getdents` 系统调用被调用,该调用完成了执行 `ls testdir` 命令所需的大部分操作。现在,从 `trace.log` 文件中用 `grep` 获取 `getdents`:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# grep getdents trace.log
|
||||
getdents(3, /* 4 entries */, 32768) = 112
|
||||
getdents(3, /* 0 entries */, 32768) = 0
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
`getdents` 的手册页将其描述为 “获取目录项”,这就是你要执行的操作。注意,`getdents` 的参数是 `3`,这是来自上面 `openat` 系统调用的文件描述符。
|
||||
|
||||
现在有了目录列表,你需要一种在终端中显示它的方法。因此,在日志中用 `grep` 搜索另一个用于写入终端的系统调用 `write`:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# grep write trace.log
|
||||
write(1, "file1 file2\n", 13) = 13
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
在这些参数中,你可以看到将要显示的文件名:`file1` 和 `file2`。关于第一个参数(`1`),请记住在 Linux 中,当运行任何进程时,默认情况下会为其打开三个文件描述符。以下是默认的文件描述符:
|
||||
|
||||
* `0`:标准输入
|
||||
* `1`:标准输出
|
||||
* `2`:标准错误
|
||||
|
||||
因此,`write` 系统调用将在标准显示(就是这个终端,由 `1` 所标识的)上显示 `file1` 和 `file2`。
|
||||
|
||||
现在你知道哪个系统调用完成了 `ls testdir/` 命令的大部分工作。但是在 `trace.log` 文件中其它的 100 多个系统调用呢?操作系统必须做很多内务处理才能运行一个进程,因此,你在该日志文件中看到的很多内容都是进程初始化和清理。阅读整个 `trace.log` 文件,并尝试了解 `ls` 命令是怎么工作起来的。
|
||||
|
||||
既然你知道了如何分析给定命令的系统调用,那么就可以将该知识用于其他命令来了解正在执行哪些系统调用。`strace` 提供了许多有用的命令行标志,使你更容易使用,下面将对其中一些进行描述。
|
||||
|
||||
默认情况下,`strace` 并不包含所有系统调用信息。但是,它有一个方便的 `-v` 冗余选项,可以在每个系统调用中提供附加信息:
|
||||
|
||||
```
|
||||
strace -v ls testdir
|
||||
```
|
||||
|
||||
在运行 `strace` 命令时始终使用 `-f` 选项是一种好的作法。它允许 `strace` 对当前正在跟踪的进程创建的任何子进程进行跟踪:
|
||||
|
||||
```
|
||||
strace -f ls testdir
|
||||
```
|
||||
|
||||
假设你只需要系统调用的名称、运行的次数以及每个系统调用花费的时间百分比。你可以使用 `-c` 标志来获取这些统计信息:
|
||||
|
||||
```
|
||||
strace -c ls testdir/
|
||||
```
|
||||
|
||||
假设你想专注于特定的系统调用,例如专注于 `open` 系统调用,而忽略其余部分。你可以使用`-e` 标志跟上系统调用的名称:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# strace -e open ls testdir
|
||||
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libacl.so.1", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libattr.so.1", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
|
||||
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
|
||||
file1 file2
|
||||
+++ exited with 0 +++
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
如果你想关注多个系统调用怎么办?不用担心,你同样可以使用 `-e` 命令行标志,并用逗号分隔开两个系统调用的名称。例如,要查看 `write` 和 `getdents` 系统调用:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# strace -e write,getdents ls testdir
|
||||
getdents(3, /* 4 entries */, 32768) = 112
|
||||
getdents(3, /* 0 entries */, 32768) = 0
|
||||
write(1, "file1 file2\n", 13file1 file2
|
||||
) = 13
|
||||
+++ exited with 0 +++
|
||||
[root@sandbox tmp]#
|
||||
```
|
||||
|
||||
到目前为止,这些示例是明确地运行的命令进行了跟踪。但是,要跟踪已经运行并正在执行的命令又怎么办呢?例如,如果要跟踪用来长时间运行进程的守护程序,该怎么办?为此,`strace` 提供了一个特殊的 `-p` 标志,你可以向其提供进程 ID。
|
||||
|
||||
我们的示例不在守护程序上运行 `strace`,而是以 `cat` 命令为例,如果你将文件名作为参数,通常 `cat` 会显示文件的内容。如果没有给出参数,`cat` 命令会在终端上等待用户输入文本。输入文本后,它将重复给定的文本,直到用户按下 `Ctrl + C` 退出为止。
|
||||
|
||||
从一个终端运行 `cat` 命令;它会向你显示一个提示,并等待在那里(记住 `cat` 仍在运行且尚未退出):
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# cat
|
||||
```
|
||||
|
||||
在另一个终端上,使用 `ps` 命令找到进程标识符(PID):
|
||||
|
||||
```
|
||||
[root@sandbox ~]# ps -ef | grep cat
|
||||
root 22443 20164 0 14:19 pts/0 00:00:00 cat
|
||||
root 22482 20300 0 14:20 pts/1 00:00:00 grep --color=auto cat
|
||||
[root@sandbox ~]#
|
||||
```
|
||||
|
||||
现在,使用 `-p` 标志和 PID(在上面使用 `ps` 找到)对运行中的进程运行 `strace`。运行 `strace` 之后,其输出说明了所接驳的进程的内容及其 PID。现在,`strace` 正在跟踪 `cat` 命令进行的系统调用。看到的第一个系统调用是 `read`,它正在等待文件描述符 `0`(标准输入,这是运行 `cat` 命令的终端)的输入:
|
||||
|
||||
```
|
||||
[root@sandbox ~]# strace -p 22443
|
||||
strace: Process 22443 attached
|
||||
read(0,
|
||||
```
|
||||
|
||||
现在,返回到你运行 `cat` 命令的终端,并输入一些文本。我出于演示目的输入了 `x0x0`。注意 `cat` 是如何简单地重复我输入的内容的。因此,`x0x0` 出现了两次。我输入了第一个,第二个是 `cat` 命令重复的输出:
|
||||
|
||||
```
|
||||
[root@sandbox tmp]# cat
|
||||
x0x0
|
||||
x0x0
|
||||
```
|
||||
|
||||
返回到将 `strace` 接驳到 `cat` 进程的终端。现在你会看到两个额外的系统调用:较早的 `read` 系统调用,现在在终端中读取 `x0x0`,另一个为 `write`,它将 `x0x0` 写回到终端,然后是再一个新的 `read`,正在等待从终端读取。请注意,标准输入(`0`)和标准输出(`1`)都在同一终端中:
|
||||
|
||||
```
|
||||
[root@sandbox ~]# strace -p 22443
|
||||
strace: Process 22443 attached
|
||||
read(0, "x0x0\n", 65536) = 5
|
||||
write(1, "x0x0\n", 5) = 5
|
||||
read(0,
|
||||
```
|
||||
|
||||
想象一下,对守护进程运行 `strace` 以查看其在后台执行的所有操作时这有多大帮助。按下 `Ctrl + C` 杀死 `cat` 命令;由于该进程不再运行,因此这也会终止你的 `strace` 会话。
|
||||
|
||||
如果要查看所有的系统调用的时间戳,只需将 `-t` 选项与 `strace` 一起使用:
|
||||
|
||||
```
|
||||
[root@sandbox ~]#strace -t ls testdir/
|
||||
|
||||
14:24:47 execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
14:24:47 brk(NULL) = 0x1f07000
|
||||
14:24:47 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2530bc8000
|
||||
14:24:47 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
|
||||
14:24:47 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
|
||||
```
|
||||
|
||||
如果你想知道两次系统调用之间所花费的时间怎么办?`strace` 有一个方便的 `-r` 命令,该命令显示执行每个系统调用所花费的时间。非常有用,不是吗?
|
||||
|
||||
```
|
||||
[root@sandbox ~]#strace -r ls testdir/
|
||||
|
||||
0.000000 execve("/usr/bin/ls", ["ls", "testdir/"], [/* 40 vars */]) = 0
|
||||
0.000368 brk(NULL) = 0x1966000
|
||||
0.000073 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb6b1155000
|
||||
0.000047 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
|
||||
0.000119 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
`strace` 实用程序非常有助于理解 Linux 上的系统调用。要了解它的其它命令行标志,请参考手册页和在线文档。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/strace
|
||||
|
||||
作者:[Gaurav Kamathe][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/gkamathe
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/yearbook-haff-rx-linux-file-lead_0.png?itok=-i0NNfDC (Hand putting a Linux file folder into a drawer)
|
||||
[2]: https://en.wikipedia.org/wiki/Trap_(computing)
|
||||
@@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11586-1.html)
|
||||
[#]: subject: (Why I made the switch from Mac to Linux)
|
||||
[#]: via: (https://opensource.com/article/19/10/why-switch-mac-linux)
|
||||
[#]: author: (Matthew Broberg https://opensource.com/users/mbbroberg)
|
||||
|
||||
为什么我从 Mac 换到了 Linux
|
||||
======
|
||||
|
||||
> 感谢这么多的开源开发人员,日常使用 Linux 比以往任何时候都容易得多。
|
||||
|
||||

|
||||
|
||||
自 2004 年开始从事 IT 工作以来,我一直是 Mac 的忠实粉丝。但是几个月前,由于种种原因,我决定将 Linux 用作日常使用的系统。这不是我第一次尝试完全采用 Linux,但是我发现它比以往更加容易。下面是促使我转换的原因。
|
||||
|
||||
### 我在个人电脑上的首次 Linux 体验
|
||||
|
||||
我记得,我抬头看着投影机,而它和我面面相觑。我们俩都不明白为什么它不显示。VGA 线完全接好了,针脚也没有弯折。我按了我所有想到的可能的按键组合,以向我的笔记本电脑发出信号,想让它克服“舞台恐惧症”。
|
||||
|
||||
我在大学里运行 Linux 只是作为实验。而我在 IT 部门的经理是多种口味的倡导者,随着我对桌面支持和编写脚本的信心增强,我想了解更多 Linux 的信息。对我来说,IT 比我的计算机科学学位课程有趣得多,课程的感觉是如此抽象和理论化:“二叉树有啥用?”,我如是想 —— 而我们的系统管理员团队的工作却是如此的真真切切。
|
||||
|
||||
这个故事的结尾是,我登录到 Windows 工作站完成了我的课堂演讲,这标志着我将 Linux 作为我的日常操作系统的第一次尝试的终结。我很欣赏 Linux 的灵活性,但是它缺乏兼容性。我偶尔会写个脚本,脚本通过 SSH 连接到一个机器中以运行另一个脚本,但是我对 Linux 的日常使用仅止于此。
|
||||
|
||||
### 对 Linux 兼容性的全新印象
|
||||
|
||||
几个月前,当我决定再试一次 Linux 时,我曾觉得我遇到更多的兼容性噩梦,但我错了。
|
||||
|
||||
安装过程完成后,我立即插入了 USB-C 集线器以了解兼容性到底如何。一切立即工作。连接 HDMI 的超宽显示器作为镜像显示器弹出到我的笔记本电脑屏幕上,我轻松地将其调整为第二台显示器。USB 连接的网络摄像头对我的[在家工作方式][2]至关重要,它可以毫无问题地显示视频。甚至自从我使用 Mac 以来就一直插在集线器的 Mac 充电器可以为我的非常不 Mac 的硬件充电。
|
||||
|
||||
我的正面体验可能与 USB-C 的一些更新有关,它在 2018 年得到一些所需的关注,因此才能与其他操作系统的体验相媲美。正如 [Phoronix 解释的那样][3]:
|
||||
|
||||
> “USB Type-C 接口为非 USB 信号提供了‘替代模式’扩展,在规范中该替代模式的最大使用场景是支持 DisplayPort。除此之外,另一个替代模式是支持 Thunderbolt 3。DisplayPort 替代模式支持 4K 甚至 8Kx4K 的视频输出,包括多声道音频。
|
||||
>
|
||||
> “虽然 USB-C 替代模式和 DisplayPort 已经存在了一段时间,并且在 Windows 上很常见,但是主线 Linux 内核不支持此功能。所幸的是,多亏英特尔,这种情况正在改变。”
|
||||
>
|
||||
|
||||
而在端口之外,快速浏览一下 [笔记本电脑 Linux][4] 的硬件选择,列出了比我 2000 年代初期所经历的更加完整的选择集。
|
||||
|
||||
与我第一次尝试采用 Linux 相比,这已经天差地别,这是我张开双臂欢迎的。
|
||||
|
||||
### 突破 Apple 的樊篱
|
||||
|
||||
使用 Linux 给我的日常工作流程增加了一些新的麻烦,而我喜欢这种麻烦。
|
||||
|
||||
我的 Mac 工作流程是无缝的:早上打开 iPad,写下关于我今天想要做什么的想法,然后开始在 Safari 中阅读一些文章;移到我的 iPhone 上可以继续阅读;然后登录我的 MacBook,这些地方我进行了多年的微调,已经弄清楚了所有这些部分之间的连接方式。键盘快捷键已内置在我的大脑中;用户体验一如既往。简直不要太舒服了。
|
||||
|
||||
这种舒适需要付出代价。我基本上忘记了我的环境如何运作的,也无法解答我想解答的问题。我是否自定义了一些 [PLIST 文件][5]以获得快捷方式,是不是记得将其签入[我的 dotfiles][6] 当中?当 Firefox 的功能更好时,我为何还如此依赖 Safari 和 Chrome?为什么我不使用基于 Android 的手机代替我的 i-系列产品呢?
|
||||
|
||||
关于这一点,我经常考虑改用基于 Android 的手机,但是我会失去在所有这些设备之间的连接性以及为这种生态系统设计的一些便利。例如,我将无法在 iPhone 上为 Apple TV 输入搜索内容,也无法与其他用 Apple 的朋友用 AirDrop 共享密码。这些功能是同类设备环境的巨大好处,并且是一项了不起的工程。也就是说,这些便利是被生态系统所困的代价。
|
||||
|
||||
我喜欢了解设备的工作方式。我希望能够解释使我的系统变得有趣或容易使用的环境配置,但我也想看看增加一些麻烦对我的观点有什么影响。用 [Marcel Proust][7] 的话来说,“真正的发现之旅不在于寻找新的土地,而在于用新的眼光来看待。”技术的使用是如此的方便,以至于我不再对它的工作原理感到好奇,而 Linux 使我有机会再次有了新的眼光。
|
||||
|
||||
### 受你的启发
|
||||
|
||||
以上所有内容足以成为探索 Linux 的理由,但我也受到了你的启发。尽管所有操作系统都受到开源社区的欢迎,但 Opensource.com 的作者和读者对 Linux 的喜悦是充满感染力的。它激发了我重新潜入的乐趣,我享受这段旅途的乐趣。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/why-switch-mac-linux
|
||||
|
||||
作者:[Matthew Broberg][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mbbroberg
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
|
||||
[2]: https://opensource.com/article/19/8/rules-remote-work-sanity
|
||||
[3]: https://www.phoronix.com/scan.php?page=news_item&px=Linux-USB-Type-C-Port-DP-Driver
|
||||
[4]: https://www.linux-laptop.net/
|
||||
[5]: https://fileinfo.com/extension/plist
|
||||
[6]: https://opensource.com/article/19/3/move-your-dotfiles-version-control
|
||||
[7]: https://www.age-of-the-sage.org/quotations/proust_having_seeing_with_new_eyes.html
|
||||
@@ -0,0 +1,282 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11572-1.html)
|
||||
[#]: subject: (How to Install and Configure Nagios Core on CentOS 8 / RHEL 8)
|
||||
[#]: via: (https://www.linuxtechi.com/install-nagios-core-rhel-8-centos-8/)
|
||||
[#]: author: (James Kiarie https://www.linuxtechi.com/author/james/)
|
||||
|
||||
如何在 CentOS 8/RHEL 8 上安装和配置 Nagios Core
|
||||
======
|
||||
|
||||
Nagios 是一个自由开源的网络和警报引擎,它用于监控各种设备,例如网络设备和网络中的服务器。它支持 Linux 和 Windows,并提供了直观的 Web 界面,可让你轻松监控网络资源。经过专业配置后,它可以在服务器或网络设备下线或者故障时向你发出邮件警报。在本文中,我们说明了如何在 RHEL 8/CentOS 8 上安装和配置 Nagios Core。
|
||||
|
||||
![Install-Nagios-Core-RHEL8-CentOS8][2]
|
||||
|
||||
### Nagios Core 的先决条件
|
||||
|
||||
在开始之前,请先检查并确保有以下各项:
|
||||
|
||||
* RHEL 8/CentOS 8 环境
|
||||
* 能通过 SSH 访问该环境
|
||||
* 快速稳定的互联网连接
|
||||
|
||||
满足上述要求后,我们开始吧!
|
||||
|
||||
### 步骤 1:安装 LAMP
|
||||
|
||||
为了使 Nagios 能够按预期工作,你需要安装 LAMP 或其他 Web 软件,因为它们将在浏览器上运行。为此,请执行以下命令:
|
||||
|
||||
```
|
||||
# dnf install httpd mariadb-server php-mysqlnd php-fpm
|
||||
```
|
||||
|
||||
![Install-LAMP-stack-CentOS8][3]
|
||||
|
||||
你需要确保 Apache Web 服务器已启动并正在运行。为此,请使用以下命令启用并启动 Apache 服务器:
|
||||
|
||||
```
|
||||
# systemctl start httpd
|
||||
# systemctl enable httpd
|
||||
```
|
||||
|
||||
![Start-enable-httpd-centos8][4]
|
||||
|
||||
检查 Apache 服务器运行状态:
|
||||
|
||||
```
|
||||
# systemctl status httpd
|
||||
```
|
||||
|
||||
![Check-status-httpd-centos8][5]
|
||||
|
||||
接下来,我们需要启用并启动 MariaDB 服务器,运行以下命令:
|
||||
|
||||
```
|
||||
# systemctl start mariadb
|
||||
# systemctl enable mariadb
|
||||
```
|
||||
|
||||
![Start-enable-MariaDB-CentOS8][6]
|
||||
|
||||
要检查 MariaDB 状态,请运行:
|
||||
|
||||
```
|
||||
# systemctl status mariadb
|
||||
```
|
||||
|
||||
![Check-MariaDB-status-CentOS8][7]
|
||||
|
||||
另外,你可能会考虑加强或保护服务器,使其不容易受到未经授权的访问。要保护服务器,请运行以下命令:
|
||||
|
||||
```
|
||||
# mysql_secure_installation
|
||||
```
|
||||
|
||||
确保为你的 MySQL 实例设置一个强密码。对于后续提示,请输入 “Y” 并按回车。
|
||||
|
||||
![Secure-MySQL-server-CentOS8][8]
|
||||
|
||||
### 步骤 2:安装必需的软件包
|
||||
|
||||
除了安装 LAMP 外,还需要一些其他软件包来安装和正确配置 Nagios。因此,如下所示安装软件包:
|
||||
|
||||
```
|
||||
# dnf install gcc glibc glibc-common wget gd gd-devel perl postfix
|
||||
```
|
||||
|
||||
![Install-requisite-packages-CentOS8][9]
|
||||
|
||||
### 步骤 3:创建 Nagios 用户帐户
|
||||
|
||||
接下来,我们需要为 Nagios 用户创建一个用户帐户。为此,请运行以下命令:
|
||||
|
||||
```
|
||||
# adduser nagios
|
||||
# passwd nagios
|
||||
```
|
||||
|
||||
![Create-new-user-for-Nagios][10]
|
||||
|
||||
现在,我们需要为 Nagios 创建一个组,并将 Nagios 用户添加到该组中。
|
||||
|
||||
```
|
||||
# groupadd nagiosxi
|
||||
```
|
||||
|
||||
现在添加 Nagios 用户到组中:
|
||||
|
||||
```
|
||||
# usermod -aG nagiosxi nagios
|
||||
```
|
||||
|
||||
另外,将 Apache 用户添加到 Nagios 组:
|
||||
|
||||
```
|
||||
# usermod -aG nagiosxi apache
|
||||
```
|
||||
|
||||
![Add-Nagios-group-user][11]
|
||||
|
||||
### 步骤 4:下载并安装 Nagios Core
|
||||
|
||||
现在,我们可以继续安装 Nagios Core。Nagios 4.4.5 的最新稳定版本于 2019 年 8 月 19 日发布。但首先,请从它的官方网站下载 Nagios tarball 文件。
|
||||
|
||||
要下载 Nagios Core,请首进入 `/tmp` 目录:
|
||||
|
||||
```
|
||||
# cd /tmp
|
||||
```
|
||||
|
||||
接下来下载 tarball 文件:
|
||||
|
||||
```
|
||||
# wget https://assets.nagios.com/downloads/nagioscore/releases/nagios-4.4.5.tar.gz
|
||||
```
|
||||
|
||||
![Download-Nagios-CentOS8][12]
|
||||
|
||||
下载完 tarball 文件后,使用以下命令将其解压缩:
|
||||
|
||||
```
|
||||
# tar -xvf nagios-4.4.5.tar.gz
|
||||
```
|
||||
|
||||
接下来,进入未压缩的文件夹:
|
||||
|
||||
```
|
||||
# cd nagios-4.4.5
|
||||
```
|
||||
|
||||
按此顺序运行以下命令:
|
||||
|
||||
```
|
||||
# ./configure --with-command-group=nagcmd
|
||||
# make all
|
||||
# make install
|
||||
# make install-init
|
||||
# make install-daemoninit
|
||||
# make install-config
|
||||
# make install-commandmode
|
||||
# make install-exfoliation
|
||||
```
|
||||
|
||||
要配置 Apache,请运行以下命令:
|
||||
|
||||
```
|
||||
# make install-webconf
|
||||
```
|
||||
|
||||
### 步骤 5:配置 Apache Web 服务器身份验证
|
||||
|
||||
接下来,我们将为用户 `nagiosadmin` 设置身份验证。请注意不要更改该用户名,否则,可能会要求你进一步的配置,这可能很繁琐。
|
||||
|
||||
要设置身份验证,请运行以下命令:
|
||||
|
||||
```
|
||||
# htpasswd -c /usr/local/nagios/etc/htpasswd.users nagiosadmin
|
||||
```
|
||||
|
||||
![Configure-Apache-webserver-authentication-CentOS8][13]
|
||||
|
||||
系统将提示你输入 `nagiosadmin` 用户的密码。输入并按要求确认密码。在本教程结束时,你将使用该用户登录 Nagios。
|
||||
|
||||
为使更改生效,请重新启动 Web 服务器:
|
||||
|
||||
```
|
||||
# systemctl restart httpd
|
||||
```
|
||||
|
||||
### 步骤 6:下载并安装 Nagios 插件
|
||||
|
||||
插件可以扩展 Nagios 服务器的功能。它们将帮助你监控各种服务、网络设备和应用。要下载插件的 tarball 文件,请运行以下命令:
|
||||
|
||||
```
|
||||
# wget https://nagios-plugins.org/download/nagios-plugins-2.2.1.tar.gz
|
||||
```
|
||||
|
||||
接下来,解压 tarball 文件并进入到未压缩的插件文件夹:
|
||||
|
||||
```
|
||||
# tar -xvf nagios-plugins-2.2.1.tar.gz
|
||||
# cd nagios-plugins-2.2.1
|
||||
```
|
||||
|
||||
要安装插件,请编译源代码,如下所示:
|
||||
|
||||
```
|
||||
# ./configure --with-nagios-user=nagios --with-nagios-group=nagiosxi
|
||||
# make
|
||||
# make install
|
||||
```
|
||||
|
||||
### 步骤 7:验证和启动 Nagios
|
||||
|
||||
成功安装 Nagios 插件后,验证 Nagios 配置以确保一切良好,并且配置中没有错误:
|
||||
|
||||
```
|
||||
# /usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
|
||||
```
|
||||
|
||||
![Verify-Nagios-settings-CentOS8][14]
|
||||
|
||||
接下来,启动 Nagios 并验证其状态:
|
||||
|
||||
```
|
||||
# systemctl start nagios
|
||||
# systemctl status nagios
|
||||
```
|
||||
|
||||
![Start-check-status-Nagios-CentOS8][15]
|
||||
|
||||
如果系统中有防火墙,那么使用以下命令允许 ”80“ 端口:
|
||||
|
||||
```
|
||||
# firewall-cmd --permanent --add-port=80/tcp# firewall-cmd --reload
|
||||
```
|
||||
|
||||
### 步骤 8:通过 Web 浏览器访问 Nagios 面板
|
||||
|
||||
要访问 Nagios,请打开服务器的 IP 地址,如下所示:<http://server-ip/nagios> 。
|
||||
|
||||
这将出现一个弹出窗口,提示输入我们在步骤 5 创建的用户名和密码。输入凭据并点击“Sign In”。
|
||||
|
||||
![Access-Nagios-via-web-browser-CentOS8][16]
|
||||
|
||||
这将引导你到 Nagios 面板,如下所示:
|
||||
|
||||
![Nagios-dashboard-CentOS8][17]
|
||||
|
||||
我们终于成功地在 CentOS 8 / RHEL 8 上安装和配置了 Nagios Core。欢迎你的反馈。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.linuxtechi.com/install-nagios-core-rhel-8-centos-8/
|
||||
|
||||
作者:[James Kiarie][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.linuxtechi.com/author/james/
|
||||
[b]: https://github.com/lujun9972
|
||||
[2]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Install-Nagios-Core-RHEL8-CentOS8.jpg
|
||||
[3]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Install-LAMP-stack-CentOS8.jpg
|
||||
[4]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Start-enable-httpd-centos8.jpg
|
||||
[5]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Check-status-httpd-centos8.jpg
|
||||
[6]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Start-enable-MariaDB-CentOS8.jpg
|
||||
[7]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Check-MariaDB-status-CentOS8.jpg
|
||||
[8]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Secure-MySQL-server-CentOS8.jpg
|
||||
[9]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Install-requisite-packages-CentOS8.jpg
|
||||
[10]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Create-new-user-for-Nagios.jpg
|
||||
[11]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Add-Nagios-group-user.jpg
|
||||
[12]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Download-Nagios-CentOS8.jpg
|
||||
[13]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Configure-Apache-webserver-authentication-CentOS8.jpg
|
||||
[14]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Verify-Nagios-settings-CentOS8.jpg
|
||||
[15]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Start-check-status-Nagios-CentOS8.jpg
|
||||
[16]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Access-Nagios-via-web-browser-CentOS8.jpg
|
||||
[17]: https://www.linuxtechi.com/wp-content/uploads/2019/10/Nagios-dashboard-CentOS8.jpg
|
||||
|
||||
114
published/20191028 SQLite is really easy to compile.md
Normal file
114
published/20191028 SQLite is really easy to compile.md
Normal file
@@ -0,0 +1,114 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11536-1.html)
|
||||
[#]: subject: (SQLite is really easy to compile)
|
||||
[#]: via: (https://jvns.ca/blog/2019/10/28/sqlite-is-really-easy-to-compile/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
SQLite 真的很容易编译
|
||||
======
|
||||
|
||||

|
||||
|
||||
上周,我一直在做一个 SQL 网站(<https://sql-steps.wizardzines.com/>,一个 SQL 示例列表)。我使用 sqlite 运行网站上的所有查询,并且我想在其中一个例子([这个][1])中使用窗口函数。
|
||||
|
||||
但是我使用的是 Ubuntu 18.04 中的 sqlite 版本,它太旧了,不支持窗口函数。所以我需要升级 sqlite!
|
||||
|
||||
事实证明,这个过程超麻烦(如通常一样),但是非常有趣!我想起了一些有关可执行文件和共享库如何工作的信息,结论令人满意。所以我想在这里写下来。
|
||||
|
||||
(剧透:<https://www.sqlite.org/howtocompile.html> 中解释了如何编译 SQLite,它只需花费 5 秒左右,这比我平时从源码编译的体验容易了许多。)
|
||||
|
||||
### 尝试 1:从它的网站下载 SQLite 二进制文件
|
||||
|
||||
[SQLite 的下载页面][2]有一个用于 Linux 的 SQLite 命令行工具的二进制文件的链接。我下载了它,它可以在笔记本电脑上运行,我以为这就完成了。
|
||||
|
||||
但是后来我尝试在构建服务器(Netlify) 上运行它,得到了这个极其奇怪的错误消息:“File not found”。我进行了追踪,并确定 `execve` 返回错误代码 ENOENT,这意味着 “File not found”。这有点令人发狂,因为该文件确实存在,并且有正确的权限。
|
||||
|
||||
我搜索了这个问题(通过搜索 “execve enoen”),找到了[这个 stackoverflow 中的答案][3],它指出要运行二进制文件,你不仅需要二进制文件存在!你还需要它的**加载程序**才能存在。(加载程序的路径在二进制文件内部)
|
||||
|
||||
要查看加载程序的路径,可以使用 `ldd`,如下所示:
|
||||
|
||||
```
|
||||
$ ldd sqlite3
|
||||
linux-gate.so.1 (0xf7f9d000)
|
||||
libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xf7f70000)
|
||||
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7e6e000)
|
||||
libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xf7e4f000)
|
||||
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c73000)
|
||||
/lib/ld-linux.so.2
|
||||
```
|
||||
|
||||
所以 `/lib/ld-linux.so.2` 是加载程序,而该文件在构建服务器上不存在,可能是因为 Xenial(Xenial 是 Ubuntu 16.04,本文应该使用的是 18.04 “Bionic Beaver”)安装程序不支持 32 位二进制文件(?),因此我需要尝试一些不同的东西。
|
||||
|
||||
### 尝试 2:安装 Debian sqlite3 软件包
|
||||
|
||||
好吧,我想我也许可以安装来自 [debian testing 的 sqlite 软件包][4]。尝试从另一个我不使用的 Debian 版本安装软件包并不是一个好主意,但是出于某种原因,我还是决定尝试一下。
|
||||
|
||||
这次毫不意外地破坏了我计算机上的 sqlite(这也破坏了 git),但我设法通过 `sudo dpkg --purge --force-all libsqlite3-0` 恢复了,并使所有依赖于 sqlite 的软件再次工作。
|
||||
|
||||
### 尝试 3:提取 Debian sqlite3 软件包
|
||||
|
||||
我还尝试仅从 Debian sqlite 软件包中提取 sqlite3 二进制文件并运行它。毫不意外,这也行不通,但这个更容易理解:我有旧版本的 libreadline(`.so.7`),但它需要 `.so.8`。
|
||||
|
||||
```
|
||||
$ ./usr/bin/sqlite3
|
||||
./usr/bin/sqlite3: error while loading shared libraries: libreadline.so.8: cannot open shared object file: No such file or directory
|
||||
```
|
||||
|
||||
### 尝试 4:从源代码进行编译
|
||||
|
||||
我花费这么多时间尝试下载 sqlite 二进制的原因是我认为从源代码编译 sqlite 既烦人又耗时。但是显然,下载随便一个 sqlite 二进制文件根本不适合我,因此我最终决定尝试自己编译它。
|
||||
|
||||
这有指导:[如何编译 SQLite][5]。它是宇宙中最简单的东西。通常,编译的感觉是类似这样的:
|
||||
|
||||
* 运行 `./configure`
|
||||
* 意识到我缺少依赖
|
||||
* 再次运行 `./configure`
|
||||
* 运行 `make`
|
||||
* 编译失败,因为我安装了错误版本的依赖
|
||||
* 去做其他事,之后找到二进制文件
|
||||
|
||||
编译 SQLite 的方式如下:
|
||||
|
||||
* [从下载页面下载整合的 tarball][2]
|
||||
* 运行 `gcc shell.c sqlite3.c -lpthread -ldl`
|
||||
* 完成!!!
|
||||
|
||||
所有代码都在一个文件(`sqlite.c`)中,并且没有奇怪的依赖项!太奇妙了。
|
||||
|
||||
对我而言,我实际上并不需要线程支持或 readline 支持,因此我用编译页面上的说明来创建了一个非常简单的二进制文件,它仅使用了 libc 而没有其他共享库。
|
||||
|
||||
```
|
||||
$ ldd sqlite3
|
||||
linux-vdso.so.1 (0x00007ffe8e7e9000)
|
||||
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbea4988000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007fbea4d79000)
|
||||
```
|
||||
|
||||
### 这很好,因为它使体验 sqlite 变得容易
|
||||
|
||||
我认为 SQLite 的构建过程如此简单很酷,因为过去我很乐于[编辑 sqlite 的源码][6]来了解其 B 树的实现方式。
|
||||
|
||||
鉴于我对 SQLite 的了解,这并不令人感到意外(它在受限环境/嵌入式中确实可以很好地工作,因此可以以一种非常简单/最小的方式进行编译是有意义的)。 但这真是太好了!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/2019/10/28/sqlite-is-really-easy-to-compile/
|
||||
|
||||
作者:[Julia Evans][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://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://sql-steps.wizardzines.com/lag.html
|
||||
[2]: https://www.sqlite.org/download.html
|
||||
[3]: https://stackoverflow.com/questions/5234088/execve-file-not-found-when-stracing-the-very-same-file
|
||||
[4]: https://packages.debian.org/bullseye/amd64/sqlite3/download
|
||||
[5]: https://www.sqlite.org/howtocompile.html
|
||||
[6]: https://jvns.ca/blog/2014/10/02/how-does-sqlite-work-part-2-btrees/
|
||||
@@ -0,0 +1,100 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11525-1.html)
|
||||
[#]: subject: (Collapse OS – An OS Created to Run After the World Ends)
|
||||
[#]: via: (https://itsfoss.com/collapse-os/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
Collapse OS:为世界末日创建的操作系统
|
||||
======
|
||||
|
||||
当大多数人考虑为末日后的世界做准备时,想到的第一件事就是准备食物和其他生活必需品。最近,有一个程序员觉得,在社会崩溃之后,创建一个多功能的、且可生存的操作系统同样重要。我们今天将尽我们所能地来了解一下它。
|
||||
|
||||
### Collapse OS:当文明被掩埋在垃圾中
|
||||
|
||||
![][1]
|
||||
|
||||
这里说的操作系统称为 [Collapse OS(崩溃操作系统)][2]。根据该官方网站的说法,Collapse OS 是 “z80 内核以及一系列程序、工具和文档的集合”。 它可以让你:
|
||||
|
||||
* 可在最小的和临时拼凑的机器上运行。
|
||||
* 通过临时拼凑的方式(串行、键盘、显示)进行接口。
|
||||
* 可编辑文本文件。
|
||||
* 编译适用于各种 MCU 和 CPU 的汇编源代码文件。
|
||||
* 从各种存储设备读取和写入。
|
||||
* 自我复制。
|
||||
|
||||
其创造者 [Virgil Dupras][3] 之所以开始这个项目,是因为[他认为][4]“我们的全球供应链在我们到达 2030 年之前就会崩溃”。他是根据<ruby>巴勃罗·塞维尼<rt>Pablo Servigne</rt></ruby>的作品得出了这一结论的。他似乎也觉得并非所有人都会认可[他的观点][4],“话虽如此,我认为不相信到 2030 年可能会发生崩溃也是可以理解的,所以请不要为我的信念而感到受到了冲击。”
|
||||
|
||||
该项目的总体目标是迅速让瓦解崩溃后的文明重新回到计算机时代。电子产品的生产取决于非常复杂的供应链。一旦供应链崩溃,人类将回到一个技术水平较低的时代。要恢复我们以前的技术水平,将需要数十年的时间。Dupras 希望通过创建一个生态系统来跨越几个步骤,该生态系统将与从各种来源搜寻到的更简单的芯片一起工作。
|
||||
|
||||
### z80 是什么?
|
||||
|
||||
最初的 Collapse OS 内核是为 [z80 芯片][5]编写的。作为复古计算机历史的爱好者,我对 [Zilog][6] 和 z80 芯片很熟悉。在 1970 年代后期,Zilog 公司推出了 z80,以和 [Intel 的 8080][7] CPU 竞争。z80 被用于许多早期的个人计算机中,例如 [Sinclair ZX Spectrum][8] 和 [Tandy TRS-80][9]。这些系统中的大多数使用了 [CP/M 操作系统] [10],这是当时最流行的操作系统。(有趣的是,Dupras 最初希望使用[一个开源版本的 CP/M][11],但最终决定[从头开始][12]。)
|
||||
|
||||
在 1981 年 [IBM PC][13] 发布之后,z80 和 CP/M 的普及率开始下降。Zilog 确实发布了其它几种微处理器(Z8000 和 Z80000),但并没有获得成功。该公司将重点转移到了微控制器上。今天,更新后的 z80 后代产品可以在图形计算器、嵌入式设备和消费电子产品中找到。
|
||||
|
||||
Dupras 在 [Reddit][14] 上说,他为 z80 编写了 Collapse OS,因为“它已经投入生产很长时间了,并且因为它被用于许多机器上,所以拾荒者有很大的机会拿到它。”
|
||||
|
||||
### 该项目的当前状态和未来发展
|
||||
|
||||
Collapse OS 的起步相当不错。有足够的内存和存储空间它就可以进行自我复制。它可以在 [RC2014 家用计算机][15]或世嘉 Master System / MegaDrive(Genesis)上运行。它可以读取 SD 卡。它有一个简单的文本编辑器。其内核由用粘合代码连接起来的模块组成。这是为了使系统具有灵活性和适应性。
|
||||
|
||||
还有一个详细的[路线图][16]列出了该项目的方向。列出的目标包括:
|
||||
|
||||
* 支持其他 CPU,例如 8080 和 [6502][17]。
|
||||
* 支持临时拼凑的外围设备,例如 LCD 屏幕、电子墨水显示器和 [ACIA 设备][18]。
|
||||
* 支持更多的存储方式,例如软盘、CD、SPI RAM/ROM 和 AVR MCU。
|
||||
* 使它可以在其他 z80 机器上工作,例如 [TI-83+][19] 和 [TI-84+][20] 图形计算器和 TRS-80s。
|
||||
|
||||
如果你有兴趣帮助或只是想窥视一下这个项目,请访问其 [GitHub 页面][21]。
|
||||
|
||||
### 最后的思考
|
||||
|
||||
坦率地说,我认为 Collapse OS 与其说是一个有用的项目,倒不如说更像是一个有趣的爱好项目(对于那些喜欢构建操作系统的人来说)。当崩溃真的到来时,我认为 GitHub 也会宕机,那么 Collapse OS 将如何分发?我无法想像,得具有多少技能的人才能够从捡来的零件中创建出一个系统。到时候会有新一代的创客们,但大多数创客们会习惯于选择 Arduino 或树莓派来构建项目,而不是从头开始。
|
||||
|
||||
与 Dupras 相反,我最担心的是[电磁脉冲炸弹(EMP)][22] 的使用。这些东西会炸毁所有的电气系统,这意味着将没有任何构建系统的可能。如果没有发生这种事情,我想我们将能够找到过去 30 年制造的那么多的 x86 组件,以保持它们运行下去。
|
||||
|
||||
话虽如此,对于那些喜欢为奇奇怪怪的应用编写低级代码的人来说,Collapse OS 听起来是一个有趣且具有高度挑战性的项目。如果你是这样的人,去检出 [Collapse OS][2] 代码吧。
|
||||
|
||||
让我提个假设的问题:你选择的世界末日操作系统是什么?请在下面的评论中告诉我们。
|
||||
|
||||
如果你觉得这篇文章有趣,请花一点时间在社交媒体、Hacker News 或 [Reddit][23] 上分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/collapse-os/
|
||||
|
||||
作者:[John Paul][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/10/Collapse_OS.jpg?ssl=1
|
||||
[2]: https://collapseos.org/
|
||||
[3]: https://github.com/hsoft
|
||||
[4]: https://collapseos.org/why.html
|
||||
[5]: https://en.m.wikipedia.org/wiki/Z80
|
||||
[6]: https://en.wikipedia.org/wiki/Zilog
|
||||
[7]: https://en.wikipedia.org/wiki/Intel_8080
|
||||
[8]: https://en.wikipedia.org/wiki/ZX_Spectrum
|
||||
[9]: https://en.wikipedia.org/wiki/TRS-80
|
||||
[10]: https://en.wikipedia.org/wiki/CP/M
|
||||
[11]: https://github.com/davidgiven/cpmish
|
||||
[12]: https://github.com/hsoft/collapseos/issues/52
|
||||
[13]: https://en.wikipedia.org/wiki/IBM_Personal_Computer
|
||||
[14]: https://old.reddit.com/r/collapse/comments/dejmvz/collapse_os_bootstrap_postcollapse_technology/f2w3sid/?st=k1gujoau&sh=1b344da9
|
||||
[15]: https://rc2014.co.uk/
|
||||
[16]: https://collapseos.org/roadmap.html
|
||||
[17]: https://en.wikipedia.org/wiki/MOS_Technology_6502
|
||||
[18]: https://en.wikipedia.org/wiki/MOS_Technology_6551
|
||||
[19]: https://en.wikipedia.org/wiki/TI-83_series#TI-83_Plus
|
||||
[20]: https://en.wikipedia.org/wiki/TI-84_Plus_series
|
||||
[21]: https://github.com/hsoft/collapseos
|
||||
[22]: https://en.wikipedia.org/wiki/Electromagnetic_pulse
|
||||
[23]: https://reddit.com/r/linuxusersgroup
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user