mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-01 21:50:13 +08:00
commit
d7adcbb88c
@ -0,0 +1,118 @@
|
||||
如何在 LibreOffice Writer 中创建一个电子书章节模板
|
||||
======
|
||||
|
||||
> 将电子书分成几章,创建电子书会更容易。这是设置模板的分步指南。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/02/102817vmflleeemehetblt.jpg)
|
||||
|
||||
对于很多人来说,使用 word 程序来撰写和发布一本电子书是一种最好的、最容易的、最熟悉的方法。但是,启动你的 word 程序和打字是不够的 —— 你需要遵循一种格式。
|
||||
|
||||
这就是模板的来源。一个模板确保你的电子书有一个一致的外观和体验。幸运的是,创建模板是快速和容易的,并你在其上花费的时间和努力将带给你一本更好感观的书。
|
||||
|
||||
在这篇文章中,我将陪伴你走过如何使用 LibreOffice Writer 创建一个简单的模板,可以用于一本电子书的各个章节。你可以将这个模板用于 PDF 和 EPUB 书籍,并加以修改来满足你的需要。
|
||||
|
||||
### 我的方法
|
||||
|
||||
为什么我着重于为一个章节创建一个模板,而不是为一整本书创建一个模板?因为编写和管理单独的章节比编写和管理单个庞大而僵化的文档更容易。
|
||||
|
||||
通过关注于单独的章节,你可以专心于你需要编写的东西。你可以很容易地四处移动这些章节,给审阅者发单独一章节比发送你的完整原稿更简单而高效。当你写完一章后,你可以简单地把你的章节拼凑在一起来出版这本书(我将在下面讨论如何做到这一点)。但是不要觉得你被这种方法所束缚 —— 如果你更喜欢在单个文件中编写,简单地调整在这篇文章中描述的步骤就行。
|
||||
|
||||
让我们开始吧。
|
||||
|
||||
### 设置页面
|
||||
|
||||
仅当你计划发布你的电子书为一本 PDF 书时,这是很重要的。设置页面意味着你的书将不包含大量的跨越屏幕的让眼睛疲劳的文本。
|
||||
|
||||
选择 **格式 > 页面** 来打开 **页面样式** 窗口。我的 PDF 电子书通常是 5x8 英寸高(大约 13x20cm ,对于我们这些生活在米制世界的人来说)。我也设置页边距为半英寸(约 1.25 cm)。这些是我较喜欢的尺寸;你可以使用任何适合你的尺寸。
|
||||
|
||||
![LibreOffice Page Style window][2]
|
||||
|
||||
*在 LibreOffice Writer 中的页面样式窗口让你设置页边距和页格式。*
|
||||
|
||||
接下来,添加页脚以显示页码。保持页面样式窗口打开着,并单击 **页脚** 选项卡。选择 **在页脚上** 并单击 **确定** 。
|
||||
|
||||
在该页面上,在页脚中单击,然后选择 **插入 > 字段 > 页码**。不要担心页码的位置和外观;我们接下来会处理。
|
||||
|
||||
### 设置你的样式
|
||||
|
||||
像模板本身一样,样式为你的文档提供一种一致的外观和体验。如果你想更改一个标题的字体或大小,例如,你只需要在一个地方完成它,而不是手动应用格式化到每个标题。
|
||||
|
||||
标准化的 LibreOffice 模板带有许多样式,你可以调整它们以适应你的需要。为此,按 `F11` 来打开 **样式和格式** 窗口。
|
||||
|
||||
![LibreOffice styles and formatting][4]
|
||||
|
||||
*使用样式和格式窗口更改字体和其它细节。*
|
||||
|
||||
在一个样式上右键单击,并选择 **修改** 来编辑它。 这里是我在每本中使用的主要样式:
|
||||
|
||||
样式 | 字体 | 间距 / 对齐方式
|
||||
:-: | :-: | :-:
|
||||
标题 1 | Liberation Sans, 36 pt | 上面 36 pt ,下面 48 pt ,左对齐
|
||||
标题 2 | Liberation Sans, 18 pt | 上面 12 pt ,下面 12 pt ,左对齐
|
||||
标题 3 | Liberation Sans, 14 pt | 上面 12 pt ,下面 12 pt ,左对齐
|
||||
正文 | Liberation Sans, 12 pt | 上面 12 pt ,下面 12 pt ,左对齐
|
||||
页脚 | Liberation Sans, 10 pt | 居中对齐
|
||||
|
||||
|
||||
![LibreOffice styles in action][6]
|
||||
|
||||
*这是当我们应用到电子书内容时的一个选择的样式外观。*
|
||||
|
||||
对于大多数书来说,这通常是最小要求。可以随便更改字体和空格来适应你的要求。
|
||||
|
||||
根据你正在编写书的类型,你可能也想创建或修改项目符合样式,以及数字列表、引号、代码示例、数字符号等等。只需要记住始终如一地使用字体以及其大小。
|
||||
|
||||
### 保存你的模板
|
||||
|
||||
选择 **文件 > 另存为** 。在保持对话框中,从格式列表中选择 “ODF 文本文档模板 (.ott)” 。这将保存模板为一个模板,以后你可以快速调用该模板。
|
||||
|
||||
保存模板的最佳位置是 LibreOffice 模板文件夹。例如,在 Linux 中,那是在你的家目录下,在 `.config/libreoffice/4/user/template` 下。
|
||||
|
||||
### 编写你的书
|
||||
|
||||
在你开始编写前,在你的计算机上创建一个文件夹,它将为你的书保存所有的文件 —— 章节、图像、笔记等等。
|
||||
|
||||
当你准备编写时,启动 LibreOffice Writer 并选择 **文件 > 新建 > 模板** 。然后从列表中选择你的模板,并单击 **打开**。
|
||||
|
||||
![LibreOffice Writer template list][8]
|
||||
|
||||
*从你在 LibreOffice Writer 中设置的列表中选择你的模板,并开始编写。*
|
||||
|
||||
然后用一个描述性名称保存文档。
|
||||
|
||||
建议使用像 “第 1 章” 和 “第 2 章” 这样的惯例 —— 在某些时候,你可能决定重新编排你的章节,当你尝试管理这些章节时,它可能会变得混乱。然而,你可以在文件名称中放置章节数字,像 “第 1 章” 或 “一” 。如果你最后要重新排列全书的章节,像这样重命名更容易。
|
||||
|
||||
无需赘言,开始编写吧。记住在模板中使用样式来格式化文本 —— 这就是为什么你要创建模板,对吧?
|
||||
|
||||
### 发布你的电子书
|
||||
|
||||
在完成编写一堆章节后,并准备发布它们时,创建一个主控文档。把一个主控文档作为你所编写章节的一个容器。使用一个主控文档,你可以快速地组装你的书,并任意重新排序你的章节。LibreOffice 的帮助提供了使用[主控文档][9]的详细信息。
|
||||
|
||||
假设你想生成一个 PDF ,不要只是单击**直接导出到 PDF** 按钮。这将创建一个相当不错的 PDF ,但是你可能想优化它。为此,选择 **文件 > 导出为 PDF** ,并在 PDF 选项窗口中轻微调整。你可以在这篇 [LibreOffice Writer 文档][10] 中学到更多东西。
|
||||
|
||||
如果你想创建一个 EPUB 而不是一个 PDF,或者除了一个 PDF 以外,另外创建一个 EPUB,请安装 [Writer2EPUB][11] 扩展。Opensource.com 的 Bryan Behrenshausen 为这个扩展[分享了一些有用的说明][12] 。
|
||||
|
||||
### 结束语
|
||||
|
||||
我们在这里创建的模板是极简单的,但是你可以将其用于一本简单的书,或者作为构建一个复杂模板的起点。不管怎样,这个模板都会让你快速地开始编写和发布你的电子书。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/17/10/creating-ebook-chapter-template-libreoffice-writer
|
||||
|
||||
作者:[Scott Nesbitt][a]
|
||||
译者:[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/scottnesbitt
|
||||
[2]:https://opensource.com/sites/default/files/images/life-uploads/lo-page-style.png (LibreOffice Page Style window)
|
||||
[4]:https://opensource.com/sites/default/files/images/life-uploads/lo-paragraph-style.png (LibreOffice styles and formatting window)
|
||||
[5]:/file/374466
|
||||
[6]:https://opensource.com/sites/default/files/images/life-uploads/lo-styles-in-action.png (Example of LibreOffice styles)
|
||||
[8]:https://opensource.com/sites/default/files/images/life-uploads/lo-template-list.png (Template list - LibreOffice Writer)
|
||||
[9]:https://help.libreoffice.org/Writer/Working_with_Master_Documents_and_Subdocuments
|
||||
[10]:https://help.libreoffice.org/Common/Export_as_PDF
|
||||
[11]:http://writer2epub.it/en/
|
||||
[12]:https://opensource.com/life/13/8/how-create-ebook-open-source-way
|
230
published/20190405 File sharing with Git.md
Normal file
230
published/20190405 File sharing with Git.md
Normal file
@ -0,0 +1,230 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11768-1.html)
|
||||
[#]: subject: (File sharing with Git)
|
||||
[#]: via: (https://opensource.com/article/19/4/file-sharing-git)
|
||||
[#]: author: (Seth Kenlon)
|
||||
|
||||
用 Git 来共享文件
|
||||
======
|
||||
|
||||
> SparkleShare 是一个开源的基于 Git 的 Dropbox 风格的文件共享应用程序。在我们的系列文章中了解有关 Git 鲜为人知的用法。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/10/113645qb2ufvuu2ttimugv.png)
|
||||
|
||||
[Git][2] 是一个少有的能将如此多的现代计算封装到一个程序之中的应用程序,它可以用作许多其他应用程序的计算引擎。虽然它以跟踪软件开发中的源代码更改而闻名,但它还有许多其他用途,可以让你的生活更轻松、更有条理。在这个 Git 系列中,我们将分享七种鲜为人知的使用 Git 的方法。
|
||||
|
||||
今天,我们将看看 SparkleShare,它使用 Git 作为文件共享的基础。
|
||||
|
||||
### 用于文件共享的 Git
|
||||
|
||||
Git 的优点之一是它具有固有的分发能力。它可用来建立共享。即使你只是与自己网络上的其他计算机共享资源库,Git 也会为从共享位置获取文件的行为带来透明性。
|
||||
|
||||
随着其界面的发展,Git 变得非常简单。虽然因用户而异,他们坐下来完成一些工作时的共同点仅仅是 `git pull` 或稍微复杂一点的 `git pull && git checkout -b my-branch`。但是,对于某些人来说,将*命令输入*到他们的计算机中的做法完全是令人困惑或烦恼的。计算机旨在使生活变得轻松,它擅长于重复性工作,因此有更简便的方法可以与 Git 共享文件。
|
||||
|
||||
### SparkleShare
|
||||
|
||||
[SparkleShare][3] 项目是一个基于 Git 的跨平台的、开源的 Dropbox 式的文件共享应用程序。它通过将文件拖放到专门指定的 SparkleShare 目录中的简单操作,自动执行所有 Git 命令,触发添加、提交、推送和拉取过程。因为它基于 Git,所以你可以获得基于差异(diff)的快速推送和拉取,并且继承了 Git 版本控制和后端基础设施(如 Git 挂钩)的所有优点。它可以完全自托管,也可以将其与 [GitLab][4]、GitHub、Bitbucket 等 Git 托管服务一起使用。此外,由于它基本上只是一个 Git 的前端,因此你可以在可能没有 SparkleShare 客户端但有 Git 客户端的设备上访问 SparkleShare 中的文件。
|
||||
|
||||
正如你获得 Git 的所有好处一样,你也会受到所有常见的 Git 限制:使用 SparkleShare 存储数百张照片、音乐和视频是不切实际的,因为 Git 是为文本而设计和优化的。Git 当然可以存储二进制文件的大文件,但是因为它可以跟踪历史记录,因此一旦将文件添加到其中,几乎就不可能完全删除它。这在某种程度上限制了 SparkleShare 对某些人的实用性,但使其非常适合许多工作流程,包括[日程安排][5]。
|
||||
|
||||
#### 安装 SparkleShare
|
||||
|
||||
SparkleShare 是跨平台的,可从[网站][6]获得适用于 Windows 和 Mac 的安装程序。对于 Linux,有一个 [Flatpak][7] 安装包,或者你可以在终端中运行以下命令:
|
||||
|
||||
```
|
||||
$ sudo flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
$ sudo flatpak install flathub org.sparkleshare.SparkleShare
|
||||
```
|
||||
|
||||
### 创建一个 Git 存储库
|
||||
|
||||
SparkleShare 并不是软件即服务(SaaS)。你在计算机上运行 SparkleShare 与 Git 存储库进行通信,而 SparkleShare 并不存储你的数据。如果你还没有与文件夹同步的 Git 存储库,则必须在启动 SparkleShare 之前创建一个文件夹。你有三个选择:托管的 Git、自托管 Git 或自托管 SparkleShare。
|
||||
|
||||
#### 托管的 Git
|
||||
|
||||
SparkleShare 可以使用你能访问的任何 Git 存储库进行存储,因此,如果你拥有 GitLab 或任何其他托管服务的帐户(或创建一个),则它可以成为 SparkleShare 的后端。例如,开源 [Notabug.org][8] 服务是一个类似于 GitHub 和 GitLab 的 Git 托管服务,但其独特性足以证明 SparkleShare 的灵活性。根据用户界面的不同,不同的托管服务创建新存储库的方法也有所不同,但是所有主要存储库都遵循相同的通用模型。
|
||||
|
||||
首先,在托管服务中找到创建新项目或存储库的按钮,单击它以开始。然后逐步完成存储库的创建过程,为存储库提供名称、隐私级别(存储库通常默认为公共),以及是否使用 `README` 文件初始化存储库。无论你是否需要个 `README` 文件,请初始化建立一个。使用一个文件来创建存储库不是绝对必要的,但是它会强制 Git 主机实例化存储库中的 `master` 分支,这有助于确保前端应用程序(例如 SparkleShare)具有要提交并推送的分支。即使文件是几乎空的 `README` 文件,也可以用来查看该文件以确认你已连接成功。
|
||||
|
||||
![Creating a Git repository][9]
|
||||
|
||||
创建存储库后,获取其用于 SSH 克隆的 URL。就像从 Git 项目获得其 URL 一样,你也可以获取此 URL:导航至存储库页面并查找 “Clone” 按钮或字段。
|
||||
|
||||
![Cloning a URL on GitHub][10]
|
||||
|
||||
*GitHub 的克隆 URL。*
|
||||
|
||||
![Cloning a URL on GitLab][11]
|
||||
|
||||
*GitLab 的克隆 URL。*
|
||||
|
||||
这是 SparkleShare 用于获取数据的地址,因此请记下它。你的 Git 存储库现已配置好。
|
||||
|
||||
#### 自托管的 Git
|
||||
|
||||
你可以使用 SparkleShare 访问你有权访问的任何计算机上的 Git 存储库。除了一个 Git 裸存储库外,无需任何特殊设置。但是,如果你想将对 Git 存储库的访问权授予其他任何人,则应运行 [Gitolite][12] 之类的 Git 管理器或 SparkleShare 自己的 Dazzle 服务器来帮助你管理 SSH 密钥和帐户。至少,创建一个特定于 Git 的用户,以便有权访问你的 Git 存储库的用户不会自动获得对服务器其余部分的访问权限。
|
||||
|
||||
以 Git 用户身份登录服务器(如果你非常擅长管理用户和组权限,则可以以自己的用户登录)并创建存储库:
|
||||
|
||||
```
|
||||
$ mkdir ~/sparkly.git
|
||||
$ cd ~/sparkly.git
|
||||
$ git init --bare .
|
||||
```
|
||||
|
||||
你的 Git 存储库现已配置好。
|
||||
|
||||
#### Dazzle
|
||||
|
||||
SparkleShare 的开发人员提供了一个名为 [Dazzle][13] 的 Git 管理系统,以帮助你自托管 Git 存储库。
|
||||
|
||||
在你的服务器上,将 Dazzle 应用程序下载到你的路径中的某个位置:
|
||||
|
||||
```
|
||||
$ curl https://raw.githubusercontent.com/hbons/Dazzle/master/dazzle.sh --output ~/bin/dazzle
|
||||
$ chmod +x ~/bin/dazzle
|
||||
```
|
||||
|
||||
Dazzle 设置了一个特定于 Git 和 SparkleShare 的用户,并且还基于 SparkleShare 应用程序生成的密钥实现了访问权限。现在,只需设置一个项目:
|
||||
|
||||
```
|
||||
$ dazzle create sparkly
|
||||
```
|
||||
|
||||
你的服务器现在已经配置好,可以用作 SparkleShare 托管了。
|
||||
|
||||
### 配置 SparkleShare
|
||||
|
||||
首次启动 SparkleShare 时,系统会提示你配置 SparkleShare 用于存储的服务器。这个过程可能看起来像一个首次运行的安装向导,但实际上是在 SparkleShare 中设置新共享位置的通常过程。与许多共享驱动器应用程序不同,使用 SparkleShare 可以一次配置多个位置。你配置的第一个共享位置并不比你以后可以配置的任何共享位置更重要,并且你也不用注册 SparkleShare 或任何其他服务。你只是将 SparkleShare 指向 Git 存储库,以便它知道如何使第一个 SparkleShare 文件夹保持同步。
|
||||
|
||||
在第一个屏幕上,给出一个身份信息,SparkleShare 将在代表你进行的 Git 提交记录中使用这些信息。你可以使用任何内容,甚至可以使用不代表任何意义的伪造信息。它仅用于提交消息,如果你对审查 Git 后端进程没有兴趣,你可能甚至看不到它们。
|
||||
|
||||
下一个屏幕提示你选择主机类型。如果你使用的是 GitLab、GitHub、Planio 或 Bitbucket,则可以选择一个适当的。否则,请选择“自己的服务器”。
|
||||
|
||||
![Choosing a Sparkleshare host][14]
|
||||
|
||||
在此屏幕底部,你必须输入 SSH 的克隆 URL。如果你是自托管的 Git,则地址类似于 `<ssh://username@example.com>`,而远程路径是为此目的而创建的 Git 存储库的绝对路径。
|
||||
|
||||
根据上面的自托管示例,我虚构的服务器的地址为 `ssh://git@example.com:22122`(`:22122` 表示一个非标准的 SSH 端口),远程路径为 `/home/git/sparkly.git`。
|
||||
|
||||
如果我改用 Notabug.org 帐户,则上例中的地址为 `ssh://git@notabug.org`,路径为 `seth/sparkly.git`。
|
||||
|
||||
SparkleShare 首次尝试连接到主机时会失败,因为你尚未将 SparkleShare 客户端 ID(特定于 SparkleShare 应用程序的 SSH 密钥)复制到 Git 主机。这是预料之中的,所以不要取消该过程。将 SparkleShare 设置窗口保持打开状态,并从系统任务栏中的 SparkleShare 图标处获取客户端 ID。然后将客户端 ID 复制到剪贴板,以便可以将其添加到 Git 主机。
|
||||
|
||||
![Getting the client ID from Sparkleshare][16]
|
||||
|
||||
#### 将你的客户端 ID 添加到托管的 Git 帐户
|
||||
|
||||
除了较小的 UI 差异外,在任何托管服务上添加 SSH 密钥(所有客户端 ID 都是这样)的过程基本上是相同的。在你的 Git 主机的 Web 仪表板中,导航到你的用户设置,然后找到 “SSH 密钥”类别。单击“添加新密钥”按钮(或类似按钮),然后粘贴你的 SparkleShare 客户端 ID 的内容。
|
||||
|
||||
![Adding an SSH key][17]
|
||||
|
||||
保存密钥。如果你希望其他人(例如协作者或家庭成员)能够访问同一存储库,则他们必须向你提供其 SparkleShare 客户端 ID,以便你可以将其添加到帐户中。
|
||||
|
||||
#### 将你的客户端 ID 添加到自托管的 Git 帐户
|
||||
|
||||
SparkleShare 客户端 ID 只是一个 SSH 密钥,因此将其复制并粘贴到 Git 用户的 `~/.ssh/authorized_keys` 文件中。
|
||||
|
||||
#### 使用 Dazzle 添加你的客户 ID
|
||||
|
||||
如果你使用 Dazzle 管理 SparkleShare 项目,请使用以下命令添加客户端 ID:
|
||||
|
||||
```
|
||||
$ dazzle link
|
||||
```
|
||||
|
||||
当 Dazzle 提示你输入该 ID 时,请粘贴在 SparkleShare 菜单中找到的客户端 ID。
|
||||
|
||||
### 使用 SparkleShare
|
||||
|
||||
将客户端 ID 添加到 Git 主机后,在 SparkleShare 窗口中单击“重试”按钮以完成设置。克隆存储库完成后,你可以关闭 SparkleShare 设置窗口,并在你的家目录中找到一个新的 `SparkleShare` 文件夹。如果你设置了带有托管服务的 Git 存储库,并选择包括 `README` 文件或许可证文件,则可以在 SparkleShare 目录中看到它们。
|
||||
|
||||
![Sparkleshare file manager][18]
|
||||
|
||||
此外,有一些隐藏目录,你可以通过在文件管理器中显示隐藏目录来查看。
|
||||
|
||||
![Showing hidden files in GNOME][19]
|
||||
|
||||
使用 SparkleShare 的方式与使用计算机上任何目录的方式相同:将文件放入其中。每当将文件或目录放入 SparkleShare 文件夹时,它都会在后台复制到你的 Git 存储库。
|
||||
|
||||
#### 排除某些文件
|
||||
|
||||
由于 Git 从设计上就是要记住*一切*,因此你可能希望从记录中排除特定的文件类型。排除一些文件是有原因的。通过定义摆脱 SparkleShare 管理的文件,可以避免意外复制大文件。你还可以为自己设计一种方案,使你可以将存储在一个目录中的逻辑上属于同一个文件(例如,MIDI 文件及其 .flac 导出文件),但是可以自己手动备份大文件,而同时让 SparkleShare 备份基于文本的文件。
|
||||
|
||||
如果在系统的文件管理器中看不到隐藏的文件,请显示它们。导航到你的 SparkleShare 文件夹,然后到代表你的存储库的目录,找到一个名为 `.gitignore` 的文件,然后在文本编辑器中将其打开。你可以在 `.gitignore` 中输入文件扩展名或文件名(每行一个),任何与你列出的文件匹配的文件都会被忽略(如文件名所示)。
|
||||
|
||||
```
|
||||
Thumbs.db
|
||||
$RECYCLE.BIN/
|
||||
.DS_Store
|
||||
._*
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
.directory
|
||||
.Trash-*
|
||||
*.wav
|
||||
*.ogg
|
||||
*.flac
|
||||
*.mp3
|
||||
*.m4a
|
||||
*.opus
|
||||
*.jpg
|
||||
*.png
|
||||
*.mp4
|
||||
*.mov
|
||||
*.mkv
|
||||
*.avi
|
||||
*.pdf
|
||||
*.djvu
|
||||
*.epub
|
||||
*.od{s,t}
|
||||
*.cbz
|
||||
```
|
||||
|
||||
你知道最经常遇到哪些文件类型,因此请集中精力处理最有可能潜入你的 SparkleShare 目录的文件。如果你想稍微矫枉过正一些,可以在 Notabug.org 以及整个网上找到 `.gitignore` 文件的好集合。
|
||||
|
||||
通过将这些条目保存在 `.gitignore` 文件中,你可以将不需要发送到 Git 主机的大文件放在 SparkleShare 目录中,SparkleShare 将完全忽略它们。当然,这意味着你需要确保它们可以备份或通过其他方式分发给你的 SparkleShare 协作者。
|
||||
|
||||
### 自动化
|
||||
|
||||
[自动化][20] 是我们与计算机达成的默契之一:计算机执行重复的、无聊的工作,而我们人类要么不擅长做这些,要么不擅长记忆这些。SparkleShare 是一种很好的、简单的自动执行例行数据分发的方法。但不管怎么说,这并不适合每个 Git 存储库。它没有用于高级 Git 功能的接口,它没有暂停按钮或手动管理的操作。没关系,因为它的使用范围是有意限制的。SparkleShare 可以完成它计划要做的事情,它做得很好,而且它是你无需关心的一个 Git 存储库。
|
||||
|
||||
如果你想使用这种稳定的、看不见的自动化,请尝试一下 SparkleShare。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/4/file-sharing-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_cloud21x_cc.png?itok=5UwC92dO
|
||||
[2]: https://git-scm.com/
|
||||
[3]: http://www.sparkleshare.org/
|
||||
[4]: http://gitlab.com
|
||||
[5]: https://opensource.com/article/19/4/calendar-git
|
||||
[6]: http://sparkleshare.org
|
||||
[7]: /business/16/8/flatpak
|
||||
[8]: http://notabug.org
|
||||
[9]: https://opensource.com/sites/default/files/uploads/git-new-repo.jpg (Creating a Git repository)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/github-clone-url.jpg (Cloning a URL on GitHub)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/gitlab-clone-url.jpg (Cloning a URL on GitLab)
|
||||
[12]: http://gitolite.org
|
||||
[13]: https://github.com/hbons/Dazzle
|
||||
[14]: https://opensource.com/sites/default/files/uploads/sparkleshare-host.jpg (Choosing a Sparkleshare host)
|
||||
[15]: mailto:git@notabug.org
|
||||
[16]: https://opensource.com/sites/default/files/uploads/sparkleshare-clientid.jpg (Getting the client ID from Sparkleshare)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/git-ssh-key.jpg (Adding an SSH key)
|
||||
[18]: https://opensource.com/sites/default/files/uploads/sparkleshare-file-manager.jpg (Sparkleshare file manager)
|
||||
[19]: https://opensource.com/sites/default/files/uploads/gnome-show-hidden-files.jpg (Showing hidden files in GNOME)
|
||||
[20]: /downloads/ansible-quickstart
|
226
published/20190406 Run a server with Git.md
Normal file
226
published/20190406 Run a server with Git.md
Normal file
@ -0,0 +1,226 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11795-1.html)
|
||||
[#]: subject: (Run a server with Git)
|
||||
[#]: via: (https://opensource.com/article/19/4/server-administration-git)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth/users/seth)
|
||||
|
||||
使用 Git 来管理 Git 服务器
|
||||
======
|
||||
|
||||
> 借助 Gitolite,你可以使用 Git 来管理 Git 服务器。在我们的系列文章中了解这些鲜为人知的 Git 用途。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/18/132045yrr1pb9n497tfbiy.png)
|
||||
|
||||
正如我在系列文章中演示的那样,[Git][2] 除了跟踪源代码外,还可以做很多事情。信不信由你,Git 甚至可以管理你的 Git 服务器,因此你可以或多或少地使用 Git 本身来运行 Git 服务器。
|
||||
|
||||
当然,这涉及除日常使用 Git 之外的许多组件,其中最重要的是 [Gitolite][3],该后端应用程序可以管理你使用 Git 的每个细微的配置。Gitolite 的优点在于,由于它使用 Git 作为其前端接口,因此很容易将 Git 服务器管理集成到其他基于 Git 的工作流中。Gitolite 可以精确控制谁可以访问你服务器上的特定存储库以及他们具有哪些权限。你可以使用常规的 Linux 系统工具自行管理此类事务,但是如果有好几个用户和不止一两个仓库,则需要大量的工作。
|
||||
|
||||
Gitolite 的开发人员做了艰苦的工作,使你可以轻松地为许多用户提供对你的 Git 服务器的访问权,而又不让他们访问你的整个环境 —— 而这一切,你可以使用 Git 来完成全部工作。
|
||||
|
||||
Gitolite 并**不是**图形化的管理员和用户面板。优秀的 [Gitea][4] 项目可提供这种体验,但是本文重点介绍 Gitolite 的简单优雅和令人舒适的熟悉感。
|
||||
|
||||
### 安装 Gitolite
|
||||
|
||||
假设你的 Git 服务器运行在 Linux 上,则可以使用包管理器安装 Gitolite(在 CentOS 和 RHEL 上为 `yum`,在 Debian 和 Ubuntu 上为 `apt`,在 OpenSUSE 上为 `zypper` 等)。例如,在 RHEL 上:
|
||||
|
||||
```
|
||||
$ sudo yum install gitolite3
|
||||
```
|
||||
|
||||
许多发行版的存储库提供的仍是旧版本的 Gitolite,但最新版本为版本 3。
|
||||
|
||||
你必须具有对服务器的无密码 SSH 访问权限。如果愿意,你可以使用密码登录服务器,但是 Gitolite 依赖于 SSH 密钥,因此必须配置使用密钥登录的选项。如果你不知道如何配置服务器以进行无密码 SSH 访问,请首先学习如何进行操作(Steve Ovens 的 Ansible 文章的[设置 SSH 密钥身份验证][5]部分对此进行了很好的说明)。这是加强服务器管理的安全以及运行 Gitolite 的重要组成部分。
|
||||
|
||||
### 配置 Git 用户
|
||||
|
||||
如果没有 Gitolite,则如果某人请求访问你在服务器上托管的 Git 存储库时,则必须向该人提供用户帐户。Git 提供了一个特殊的外壳,即 `git-shell`,这是一个仅执行 Git 任务的特别的特定 shell。这可以让你有个只能通过非常受限的 Shell 环境来过滤访问你的服务器的用户。
|
||||
|
||||
这个解决方案是一个办法,但通常意味着用户可以访问服务器上的所有存储库,除非你具有用于组权限的良好模式,并在创建新存储库时严格遵循这些权限。这种方式还需要在系统级别进行大量手动配置,这通常是只有特定级别的系统管理员才能做的工作,而不一定是通常负责 Git 存储库的人员。
|
||||
|
||||
Gitolite 通过为需要访问任何存储库的每个人指定一个用户名来完全回避此问题。默认情况下,该用户名是 `git`,并且由于 Gitolite 的文档中假定使用的是它,因此在学习该工具时保留它是一个很好的默认设置。对于曾经使用过 GitLab 或 GitHub 或任何其他 Git 托管服务的人来说,这也是一个众所周知的约定。
|
||||
|
||||
Gitolite 将此用户称为**托管用户**。在服务器上创建一个帐户以充当托管用户(我习惯使用 `git`,因为这是惯例):
|
||||
|
||||
```
|
||||
$ sudo adduser --create-home git
|
||||
```
|
||||
|
||||
为了控制该 `git` 用户帐户,该帐户必须具有属于你的有效 SSH 公钥。你应该已经进行了设置,因此复制你的公钥(**而不是你的私钥**)添加到 `git` 用户的家目录中:
|
||||
|
||||
```
|
||||
$ sudo cp ~/.ssh/id_ed25519.pub /home/git/
|
||||
$ sudo chown git:git /home/git/id_ed25519.pub
|
||||
```
|
||||
|
||||
如果你的公钥不以扩展名 `.pub` 结尾,则 Gitolite 不会使用它,因此请相应地重命名该文件。切换为该用户帐户以运行 Gitolite 的安装程序:
|
||||
|
||||
```
|
||||
$ sudo su - git
|
||||
$ gitolite setup --pubkey id_ed25519.pub
|
||||
```
|
||||
|
||||
安装脚本运行后,`git` 的家用户目录将有一个 `repository` 目录,该目录(目前)包含存储库 `git-admin.git` 和 `testing.git`。这就是该服务器所需的全部设置,现在请登出 `git` 用户。
|
||||
|
||||
### 使用 Gitolite
|
||||
|
||||
管理 Gitolite 就是编辑 Git 存储库中的文本文件,尤其是 `gitolite-admin.git` 中的。你不会通过 SSH 进入服务器来进行 Git 管理,并且 Gitolite 也建议你不要这样尝试。在 Gitolite 服务器上存储你和你的用户的存储库是个**裸**存储库,因此最好不要使用它们。
|
||||
|
||||
```
|
||||
$ git clone git@example.com:gitolite-admin.git gitolite-admin.git
|
||||
$ cd gitolite-admin.git
|
||||
$ ls -1
|
||||
conf
|
||||
keydir
|
||||
```
|
||||
|
||||
该存储库中的 `conf` 目录包含一个名为 `gitolite.conf` 的文件。在文本编辑器中打开它,或使用 `cat` 查看其内容:
|
||||
|
||||
```
|
||||
repo gitolite-admin
|
||||
RW+ = id_ed22519
|
||||
|
||||
repo testing
|
||||
RW+ = @all
|
||||
```
|
||||
|
||||
你可能对该配置文件的功能有所了解:`gitolite-admin` 代表此存储库,并且 `id_ed25519` 密钥的所有者具有读取、写入和管理 Git 的权限。换句话说,不是将用户映射到普通的本地 Unix 用户(因为所有用户都使用 `git` 用户托管用户身份),而是将用户映射到 `keydir` 目录中列出的 SSH 密钥。
|
||||
|
||||
`testing.git` 存储库使用特殊组符号为访问服务器的每个人提供了全部权限。
|
||||
|
||||
#### 添加用户
|
||||
|
||||
如果要向 Git 服务器添加一个名为 `alice` 的用户,Alice 必须向你发送她的 SSH 公钥。Gitolite 使用文件名的 `.pub` 扩展名左边的任何内容作为该 Git 用户的标识符。不要使用默认的密钥名称值,而是给密钥指定一个指示密钥所有者的名称。如果用户有多个密钥(例如,一个用于笔记本电脑,一个用于台式机),则可以使用子目录来避免文件名冲突。例如,Alice 在笔记本电脑上使用的密钥可能是默认的 `id_rsa.pub`,因此将其重命名为`alice.pub` 或类似名称(或让用户根据其计算机上的本地用户帐户来命名密钥),然后将其放入 `gitolite-admin.git/keydir/work/laptop/` 目录中。如果她从她的桌面计算机发送了另一个密钥,命名为 `alice.pub`(与上一个相同),然后将其添加到 `keydir/home/desktop/` 中。另一个密钥可能放到 `keydir/home/desktop/` 中,依此类推。Gitolite 递归地在 `keydir` 中搜索与存储库“用户”相匹配的 `.pub` 文件,并将所有匹配项视为相同的身份。
|
||||
|
||||
当你将密钥添加到 `keydir` 目录时,必须将它们提交回服务器。这是一件很容易忘记的事情,这里有一个使用自动化的 Git 应用程序(例如 [Sparkleshare][7])的真正的理由,因此任何更改都将立即提交给你的 Gitolite 管理员。第一次忘记提交和推送,在浪费了三个小时的你和你的用户的故障排除时间之后,你会发现 Gitolite 是使用 Sparkleshare 的完美理由。
|
||||
|
||||
```
|
||||
$ git add keydir
|
||||
$ git commit -m 'added alice-laptop-0.pub'
|
||||
$ git push origin HEAD
|
||||
```
|
||||
|
||||
默认情况下,Alice 可以访问 `testing.git` 目录,因此她可以使用该目录测试连接性和功能。
|
||||
|
||||
#### 设置权限
|
||||
|
||||
与用户一样,目录权限和组也是从你可能习惯的的常规 Unix 工具中抽象出来的(或可从在线信息查找)。在 `gitolite-admin.git/conf` 目录中的 `gitolite.conf` 文件中授予对项目的权限。权限分为四个级别:
|
||||
|
||||
* `R` 允许只读。在存储库上具有 `R` 权限的用户可以克隆它,仅此而已。
|
||||
* `RW` 允许用户执行分支的快进推送、创建新分支和创建新标签。对于大多数用户来说,这个基本上就像是一个“普通”的 Git 存储库。
|
||||
* `RW+` 允许可能具有破坏性的 Git 动作。用户可以执行常规的快进推送、回滚推送、变基以及删除分支和标签。你可能想要或不希望将其授予项目中的所有贡献者。
|
||||
* `-` 明确拒绝访问存储库。这与未在存储库的配置中列出的用户相同。
|
||||
|
||||
通过调整 `gitolite.conf` 来创建一个新的存储库或修改现有存储库的权限。例如,授予 Alice 权限来管理一个名为 `widgets.git` 的新存储库:
|
||||
|
||||
```
|
||||
repo gitolite-admin
|
||||
RW+ = id_ed22519
|
||||
|
||||
repo testing
|
||||
RW+ = @all
|
||||
|
||||
repo widgets
|
||||
RW+ = alice
|
||||
```
|
||||
|
||||
现在,Alice(也仅有 Alice 一个人)可以克隆该存储库:
|
||||
|
||||
```
|
||||
[alice]$ git clone git@example.com:widgets.git
|
||||
Cloning into 'widgets'...
|
||||
warning: You appear to have cloned an empty repository.
|
||||
```
|
||||
|
||||
在第一次推送时,Alice 必须使用 `-u` 选项将其分支发送到空存储库(如同她在任何 Git 主机上做的一样)。
|
||||
|
||||
为了简化用户管理,你可以定义存储库组:
|
||||
|
||||
```
|
||||
@qtrepo = widgets
|
||||
@qtrepo = games
|
||||
|
||||
repo gitolite-admin
|
||||
RW+ = id_ed22519
|
||||
|
||||
repo testing
|
||||
RW+ = @all
|
||||
|
||||
repo @qtrepo
|
||||
RW+ = alice
|
||||
```
|
||||
|
||||
正如你可以创建组存储库一样,你也可以对用户进行分组。默认情况下存在一个用户组:`@all`。如你所料,它包括所有用户,无一例外。你也可以创建自己的组:
|
||||
|
||||
```
|
||||
@qtrepo = widgets
|
||||
@qtrepo = games
|
||||
|
||||
@developers = alice bob
|
||||
|
||||
repo gitolite-admin
|
||||
RW+ = id_ed22519
|
||||
|
||||
repo testing
|
||||
RW+ = @all
|
||||
|
||||
repo @qtrepo
|
||||
RW+ = @developers
|
||||
```
|
||||
|
||||
与添加或修改密钥文件一样,对 `gitolite.conf` 文件的任何更改都必须提交并推送以生效。
|
||||
|
||||
### 创建存储库
|
||||
|
||||
默认情况下,Gitolite 假设存储库的创建是从上至下进行。例如,有权访问 Git 服务器的项目经理创建了一个项目存储库,并通过 Gitolite 管理仓库添加了开发人员。
|
||||
|
||||
实际上,你可能更愿意向用户授予创建存储库的权限。Gitolite 称这些为“<ruby>野生仓库(通配仓库)<rt>wild repos</rt></ruby>”(我不确定这是关于仓库的形成方式的描述,还是指配置文件所需的通配符)。这是一个例子:
|
||||
|
||||
```
|
||||
@managers = alice bob
|
||||
|
||||
repo foo/CREATOR/[a-z]..*
|
||||
C = @managers
|
||||
RW+ = CREATOR
|
||||
RW = WRITERS
|
||||
R = READERS
|
||||
```
|
||||
|
||||
第一行定义了一组用户:该组称为 `@managers`,其中包含用户 `alice` 和 `bob`。下一行设置了通配符允许创建尚不存在的存储库,放在名为 `foo` 的目录下的创建该存储库的用户名的子目录中。例如:
|
||||
|
||||
```
|
||||
[alice]$ git clone git@example.com:foo/alice/cool-app.git
|
||||
Cloning into cool-app'...
|
||||
Initialized empty Git repository in /home/git/repositories/foo/alice/cool-app.git
|
||||
warning: You appear to have cloned an empty repository.
|
||||
```
|
||||
|
||||
野生仓库的创建者可以使用一些机制来定义谁可以读取和写入其存储库,但是他们是有范围限定的。在大多数情况下,Gitolite 假定由一组特定的用户来管理项目权限。一种解决方案是使用 Git 挂钩来授予所有用户对 `gitolite-admin` 的访问权限,以要求管理者批准将更改合并到 master 分支中。
|
||||
|
||||
### 了解更多
|
||||
|
||||
Gitolite 具有比此介绍性文章所涵盖的更多功能,因此请尝试一下。其[文档][8]非常出色,一旦你通读了它,就可以自定义 Gitolite 服务器,以向用户提供你喜欢的任何级别的控制。Gitolite 是一种维护成本低、简单的系统,你可以安装、设置它,然后基本上就可以将其忘却。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/4/server-administration-git
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/server_data_system_admin.png?itok=q6HCfNQ8 (computer servers processing data)
|
||||
[2]: https://git-scm.com/
|
||||
[3]: http://gitolite.com
|
||||
[4]: http://gitea.io
|
||||
[5]: Setting%20up%20SSH%20key%20authentication
|
||||
[6]: mailto:git@example.com
|
||||
[7]: https://opensource.com/article/19/4/file-sharing-git
|
||||
[8]: http://gitolite.com/gitolite/quick_install.html
|
182
published/20190724 How to make an old computer useful again.md
Normal file
182
published/20190724 How to make an old computer useful again.md
Normal file
@ -0,0 +1,182 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chen-ni)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11746-1.html)
|
||||
[#]: subject: (How to make an old computer useful again)
|
||||
[#]: via: (https://opensource.com/article/19/7/how-make-old-computer-useful-again)
|
||||
[#]: author: (Howard Fosdick https://opensource.com/users/howtech)
|
||||
|
||||
如何把你的老爷机重新利用起来
|
||||
======
|
||||
|
||||
> 按照下面各个步骤,让你的老爷机焕然一新。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/04/064017ztl28cn6jjhnjnaj.jpg)
|
||||
|
||||
你的地下室里是不是有一台用来落灰的旧电脑?为什么不把它利用起来呢?如果你常用的电脑坏了,又想用一个比手机更大的屏幕上网,这时候一台备用电脑可能就派上用场了。或者,它也可以充当一台全家人共用的廉价备用电脑,甚至还可以改造为一台复古游戏机。
|
||||
|
||||
哪怕是一台有十余年历史的老爷机,只要选对了软件,也可以胜任很多新电脑能够完成的任务。其中的关键在于,要使用开源软件。
|
||||
|
||||
我进行电脑翻新已经有二十年了。在这篇文章里,我会分享一下电脑翻新的技巧。此处讨论的范围包括双核笔记本,以及机龄在 5 到 12 年之间的台式机。
|
||||
|
||||
### 检查硬件
|
||||
|
||||
第一步是检查硬件是否运转正常。如果在这个环节忽略了一个问题,后面可能会让你非常头疼。
|
||||
|
||||
灰尘是电子器件的天敌,所以第一件事应该是打开机箱,清除灰尘。[压缩空气设备][2]这时候可能会派上用场。请注意,进行任何接触电脑的操作时,都应该确保[接地][3]。此外,**不要**用清洁布擦拭任何东西。即使是一次小到你无法察觉的静电放电,也可能会导致电路损毁。
|
||||
|
||||
清洁工作完成之后,关闭机箱,检查是否所有硬件都可以正常工作。需要测试的项目包括:
|
||||
|
||||
* 内存
|
||||
* 硬盘
|
||||
* 主板
|
||||
* 外围设备(DVD 驱动器、USB 接口、声卡,等等)
|
||||
|
||||
首先,将计算机启动界面([UEFI][4] 或者是 [BIOS][5] 界面)上的诊断测试依次运行一遍。如果不知道按哪个功能键进入你电脑的启动界面,可以参考 [这份列表][6]。
|
||||
|
||||
此外,也可以使用诸如 [Hirens BootCD][7] 和 [Ultimate Boot CD][8] 之类的免费资源工具包,进行启动界面覆盖不到的测试。这些资源工具包涵盖了数百个测试程序,并且都是免费的,尽管不都开源。运行这些工具包无需安装任何软件,因为它们都是从 U 盘或者 DVD 驱动器启动的。
|
||||
|
||||
测试一定要彻底!对于内存和硬盘来说,基础测试还不够,应该运行深度测试,哪怕是运行一整夜也无妨。只有这样,才能够查出那些不易发现的瞬时故障。
|
||||
|
||||
如果发现了问题,可以参考我的[硬件故障排除快速指南][9],可以帮你解决最常见的硬件问题。
|
||||
|
||||
### 选择软件
|
||||
|
||||
电脑翻新的关键在于,根据手头的硬件资源,恰如其分地安装软件。最核心的三种硬件资源分别是:
|
||||
|
||||
1. 处理器(内核数、速度)
|
||||
2. 内存
|
||||
3. 显存
|
||||
|
||||
可以在启动时的 UEFI/BIOS 界面上,弄清楚你电脑的硬件资源。记得抄下数据,以免遗忘。接下来,可以在 [CPU Benchmark][10] 网站上查看你的处理器,该网站除了提供 CPU 的背景资料,还提供一个 CPU 的性能分数。
|
||||
|
||||
了解了硬件性能之后,就可以选择能够在硬件上高效运行的软件了。软件的选择涉及四个重要的层面:
|
||||
|
||||
1. 操作系统(OS)
|
||||
2. 桌面环境(DE)
|
||||
3. 浏览器
|
||||
4. 应用
|
||||
|
||||
一个优秀的 Linux 发行版可以满足上述全部四个层面。不要试图使用已经停止维护的 Windows 版本,例如 Windows 8、Vista 或者 XP,哪怕已经安装在电脑上了。恶意软件的[风险][11]你是承受不起的。明智的做法是,使用一个更抗病毒的最新版本操作系统。
|
||||
|
||||
那 Windows 7 呢?[维护宽限期][12]至 2020 年 1 月 14 日结束,也就是说,在此日期之前你还可以获得安全补丁,之后就想都别想了。现在正是迁出 Windows 7 的绝佳时机。
|
||||
|
||||
Linux 的巨大优势在于,有许多专门为过时硬件设计的[发行版][13]。此外,[桌面环境][14]和操作系统在 Linux 的设计中是分开的,你可以自行选择搭配。这一点非常重要,因为桌面环境对低端系统的性能有很大影响。(对于 Windows 和 MacOS 来说,你选择的操作系统版本决定了桌面环境,没得可选。)
|
||||
|
||||
Linux 的另一个好处是,拥有数以千计自由且开源的应用,不需要担心激活或者许可的问题。此外,Linux 是可移植的,可以在不同的分区、硬盘、设备或计算机之间,对操作系统和应用进行复制、移动或克隆。(Windows 则不然,使用注册表将系统捆绑在了所安装的计算机上。)
|
||||
|
||||
### 翻新后的电脑能够做什么?
|
||||
|
||||
这里讨论的是大约在 2006 年到 2013 年之间生产的双核计算机,尤其是装载了 [Intel 酷睿 2][15] CPU 或 [AMD 速龙 64 X2][16] 系列处理器的计算机。它们的 [CPU 分数][10] 大多在 1000 到 4000 分之间。这种电脑卖不了几个钱,但用在运行轻量级 Linux 软件上,性能还是足够的。
|
||||
|
||||
有一点需要注意:你的电脑应该至少拥有 2 GB 内存,如果不够就进行升级。就我翻新过的电脑来说,使用者用到的内存(不包括数据缓存)一般在 0.5 到 2 GB 之间,很少超过 2 GB。如果将内存升级到 2GB,系统就不至于进行**内存交换**,即将硬盘当做内存使用。如果想要获得良好性能,这一点十分关键。
|
||||
|
||||
以我自己为例,我用来写作这篇文章的是一台有十年机龄的翻新电脑。取下 1 GB 内存条之后,它只剩下了 1 GB 内存,然后就慢得像一只乌龟。用它浏览网页,或者是做类似的事情,都让人感到灰心,甚至痛苦。一旦把内存条重新装回去,有了 2 GB 内存,它就立马回到了可以使用的状态。
|
||||
|
||||
一台 2 GB 的双核计算机可以满足大多数人的需求,只要安装的是轻量级发行版和浏览器。你可以用它浏览网页、发送电子邮件、编辑文档和电子表格、观看 YouTube 视频、参与 eBay 拍卖竞标、在社交网络上发帖、听播客、查看相簿、管理家庭收支和个人日程、玩游戏,等等。
|
||||
|
||||
### 翻新电脑的局限
|
||||
|
||||
那么,这些老爷机又有什么局限呢?由于它们的并发性能比不上最先进的计算机,所以应该使用轻量级浏览器,同时拦截广告(广告正是让网页加载变慢的罪魁祸首)。如果可以使用虚拟专用网络(VPN)拦截广告,为处理器免除加载广告的负荷,那就再好不过。此外,还需要禁用视频自动播放、Flash 以及网页动画效果;将浏览器上的标签页控制在少数几个,不要同时打开 20 个;以及下载可以开启/禁用 JavaScript 的浏览器扩展。
|
||||
|
||||
让处理器专注于你目前正在做的事情吧,不要同时打开一堆应用,也不要在后台运行很多程序。图像编辑和视频编辑的高级工具可能会很慢;至于运行虚拟机,还是别想了吧。
|
||||
|
||||
那游戏呢?开源软件仓库提供了数以千计的游戏。这就是我为什么将显存列为三种核心硬件资源之一。如果你的电脑没有独立显卡,那很可能只有 32 或者 64 MB 的显存。可以增加一张显卡,将显存提升到 256 或者 512 MB,这样一来,处理器密集型的游戏就会顺畅很多了。如果不确定你的电脑有多少显存,可以参考[这里][17]。请注意,需要确保显卡与电脑的[显卡插槽][18](AGP、PCI-Express 或者 PCI)相匹配,同时使用正确的[连接线][19](VGA、DVI 或者 HDMI)。
|
||||
|
||||
#### 与 Windows 系统的兼容性如何?
|
||||
|
||||
许多人关心 Linux 与 Windows 系统的兼容性如何。首先,对于任何一个 Windows 程序,都有一个 [Linux 版本的替代品][20]。
|
||||
|
||||
退一步说,即使你真的必须要运行某个特定的 Windows 程序,通常也可以借助 [Wine][21] 在 Linux 上运行。可以在 [Wine 数据库][22] 里查找一下你的应用,看看是否可以在 Wine 上运行,顺便学一些特殊安装技巧。[Winetricks][23] 和 [PlayOnLinux][24] 这两个辅助工具可以帮助你进行安装和配置。
|
||||
|
||||
Wine 的另一个优势是可以运行旧版本 Windows(例如 Vista、XP、ME/98/95 和 3.1)上的程序。我认识一个家伙,搭建了一台特别赞的游戏电脑,然后用来玩 XP 上的老游戏。借助 [DOSBox][26],你甚至还可以运行数以千计的[免费 DOS 程序][25]。但是有一点需要注意,如果 Windows 程序可以运行,那么 Windows [病毒][27]也同样可以。你需要保护 Linux 上的 Wine 环境,正如保护任何其他 Windows 环境一样。
|
||||
|
||||
对了,与 Microsoft Office 的兼容性又如何呢?我使用的是 LibreOffice,经常编辑并交换 Word 和 Excel 文件,完全没有问题。不过,你应该避免使用隐晦或者过于专业的功能。
|
||||
|
||||
### 如何选择发行版?
|
||||
|
||||
假设选择了 Linux 作为操作系统,那么你还需要选择桌面环境、浏览器和各种应用。最简单的方法是,安装一个包含了你所需要的一切的发行版。
|
||||
|
||||
通过从 [live USB][28] U 盘或者 DVD 启动,你无需安装任何程序,就可以尝试不同的发行版。关于在 Linux 或 Windows 上创建可启动的 Linux 的方法,可以参考[这里][29]。
|
||||
|
||||
我进行电脑翻新的目的是做慈善,所以无法指望电脑使用者具备任何相应知识。我需要的发行版应该具有以下特性:
|
||||
|
||||
* 用户友好
|
||||
* 具有轻量级界面
|
||||
* 自带各种轻量级应用
|
||||
* 拥有足够大的软件仓库
|
||||
* 历史表现良好
|
||||
* 拥有庞大的用户社区和活跃的论坛
|
||||
* 通过长期维护版本(而不是滚动发布版本)确保稳定性
|
||||
* 更重视可靠性,而不是尖端功能
|
||||
* 可以通过图形化用户界面进行设置,而不是只能通过文本文件进行设置
|
||||
|
||||
许多发行版都能够满足上面的要求。我曾经尝试成功的有 [Mint/Xfce][30]、[Xubuntu][31] 和 [Lubuntu][32]。前两个发行版使用 Xfce 桌面环境,第三个使用 LXQt。相比 GNOME、Unity、KDE、MATE 和 Cinnamon 这些桌面环境,运行上面这两种桌面环境只需要[更少][33]的处理器和内存资源。
|
||||
|
||||
Xfce 和 LXQt 用起来非常简单,我的客户们之前从未见过 Linux,但是都可以自如使用这些简单的、菜单驱动的用户界面。
|
||||
|
||||
对于旧电脑来说,运行最快速、最高效的浏览器是一件非常重要的事情。[很多人觉得][34] Chromium 是最好的浏览器;此外,我还安装了 Firefox Quantum,因为大家比较熟悉它,并且[它的性能][35]可以和 [Chromium 的性能][36]媲美。我还加上了 Opera,因为它速度快,而且有一些独特功能,比如内置的广告拦截,以及免费的[虚拟专用网络][37]。Opera 是免费的,但并非开源。
|
||||
|
||||
无论你使用什么浏览器,一定要拦截广告和追踪器,尽量降低浏览器的负荷。此外,除非得到你的明确批准,否则视频和 Flash 都不应该被允许运行。
|
||||
|
||||
至于应用,我使用的是 Mint/Xfce、Xubuntu 和 Lubuntu 自带的轻量级应用。它们足以满足一切需求了。
|
||||
|
||||
### 行动起来吧
|
||||
|
||||
你是否会对翻新后的电脑感到满意呢?就我来说,我所使用的两台电脑的机龄都已经超过十年了,其中一个装载的是 Intel 双核处理器([eMachines T5274a][38]),另一个装载的是 AMD 速龙 64 x2 处理器([HP dc5750][39]),两台电脑都有 2 GB 内存。它们和我的另一台具备四核 i5 处理器和 16 GB 内存的电脑一样,完全能够胜任我的办公工作。如果说有什么功能是这两台电脑缺失的,那就是运行虚拟机了。
|
||||
|
||||
我们生活在一个非常神奇的年代。只需要付出一点努力,就可以将一台机龄在 5 到 12 年之间的旧电脑,翻新为一台具备实用价值的机器。还有什么比这更有趣吗?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/7/how-make-old-computer-useful-again
|
||||
|
||||
作者:[Howard Fosdick][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chen-ni](https://github.com/chen-ni)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/howtech
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
|
||||
[2]: https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=compressed+air+for+computers&rh=i%3Aaps%2Ck%3Acompressed+air+for+computers
|
||||
[3]: https://www.wikihow.com/Ground-Yourself-to-Avoid-Destroying-a-Computer-with-Electrostatic-Discharge
|
||||
[4]: https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface
|
||||
[5]: http://en.wikipedia.org/wiki/BIOS
|
||||
[6]: http://www.disk-image.com/faq-bootmenu.htm
|
||||
[7]: http://www.hirensbootcd.org/download/
|
||||
[8]: http://www.ultimatebootcd.com/
|
||||
[9]: http://www.rexxinfo.org/Quick_Guide/Quick_Guide_To_Fixing_Computer_Hardware
|
||||
[10]: http://www.cpubenchmark.net/
|
||||
[11]: https://askleo.com/unsupported-software-really-mean/
|
||||
[12]: http://home.bt.com/tech-gadgets/computing/windows-7/windows-7-support-end-11364081315419
|
||||
[13]: https://fossbytes.com/best-lightweight-linux-distros/
|
||||
[14]: http://en.wikipedia.org/wiki/Desktop_environment
|
||||
[15]: https://en.wikipedia.org/wiki/Intel_Core_2
|
||||
[16]: https://en.wikipedia.org/wiki/Athlon_64_X2
|
||||
[17]: http://www.cyberciti.biz/faq/howto-find-linux-vga-video-card-ram/
|
||||
[18]: https://www.onlinecomputertips.com/support-categories/hardware/493-pci-vs-agp-vs-pci-express-video-cards/
|
||||
[19]: https://silentpc.com/articles/video-connectors
|
||||
[20]: http://wiki.linuxquestions.org/wiki/Linux_software_equivalent_to_Windows_software
|
||||
[21]: https://en.wikipedia.org/wiki/Wine_%28software%29
|
||||
[22]: https://appdb.winehq.org/
|
||||
[23]: https://en.wikipedia.org/wiki/Winetricks
|
||||
[24]: https://en.wikipedia.org/wiki/PlayOnLinux
|
||||
[25]: https://archive.org/details/softwarelibrary_msdos
|
||||
[26]: https://en.wikipedia.org/wiki/DOSBox
|
||||
[27]: https://wiki.winehq.org/FAQ#Is_Wine_malware-compatible.3F
|
||||
[28]: https://www.howtogeek.com/howto/linux/create-a-bootable-ubuntu-usb-flash-drive-the-easy-way/
|
||||
[29]: https://unetbootin.github.io/
|
||||
[30]: https://linuxmint.com/
|
||||
[31]: https://xubuntu.org/
|
||||
[32]: https://lubuntu.me/
|
||||
[33]: https://www.makeuseof.com/tag/best-lean-linux-desktop-environment-lxde-vs-xfce-vs-mate/
|
||||
[34]: https://www.zdnet.com/article/chrome-is-the-most-popular-web-browser-of-all/
|
||||
[35]: https://www.laptopmag.com/articles/firefox-quantum-vs-chrome
|
||||
[36]: https://www.zdnet.com/article/just-how-fast-is-firefox-quantum/
|
||||
[37]: http://en.wikipedia.org/wiki/Virtual_private_network
|
||||
[38]: https://www.cnet.com/products/emachines-t5274/specs/
|
||||
[39]: https://community.spiceworks.com/products/7727-hewlett-packard-dc5750-microtower
|
@ -0,0 +1,127 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11752-1.html)
|
||||
[#]: subject: (An advanced look at Python interfaces using zope.interface)
|
||||
[#]: via: (https://opensource.com/article/19/9/zopeinterface-python-package)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshezhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/sethhttps://opensource.com/users/drmjg)
|
||||
|
||||
借助 zope.interface 深入了解 Python 接口
|
||||
======
|
||||
|
||||
> Zope.interface 可以帮助声明存在哪些接口,是由哪些对象提供的,以及如何查询这些信息。
|
||||
|
||||
![Snake charmer cartoon with a yellow snake and a blue snake][1]
|
||||
|
||||
`zope.interface` 库可以克服 Python 接口设计中的歧义性。让我们来研究一下。
|
||||
|
||||
### 隐式接口不是 Python 之禅
|
||||
|
||||
[Python 之禅][2] 很宽松,但是有点自相矛盾,以至于你可以用它来例证任何东西。让我们来思考其中最著名的原则之一:“显示胜于隐式”。
|
||||
|
||||
传统上,在 Python 中会隐含的一件事是预期的接口。比如函数已经记录了它期望一个“类文件对象”或“序列”。但是什么是类文件对象呢?它支持 `.writelines`吗?`.seek` 呢?什么是一个“序列”?是否支持步进切片,例如 `a[1:10:2]`?
|
||||
|
||||
最初,Python 的答案是所谓的“鸭子类型”,取自短语“如果它像鸭子一样行走,像鸭子一样嘎嘎叫,那么它可能就是鸭子”。换句话说,“试试看”,这可能是你能得到的最具隐式的表达。
|
||||
|
||||
为了使这些内容显式地表达出来,你需要一种方法来表达期望的接口。[Zope][3] Web 框架是最早用 Python 编写的大型系统之一,它迫切需要这些东西来使代码明确呈现出来,例如,期望从“类似用户的对象”获得什么。
|
||||
|
||||
`zope.interface` 由 Zope 开发,但作为单独的 Python 包发布。`Zope.interface` 可以帮助声明存在哪些接口,是由哪些对象提供的,以及如何查询这些信息。
|
||||
|
||||
想象编写一个简单的 2D 游戏,它需要各种东西来支持精灵界面(LCTT 译注:“<ruby>精灵<rt> Sprite</rt></ruby>”是指游戏面板中各个组件)。例如,表示一个边界框,但也要表示对象何时与一个框相交。与一些其他语言不同,在 Python 中,将属性访问作为公共接口一部分是一种常见的做法,而不是实现 getter 和 setter。边界框应该是一个属性,而不是一个方法。
|
||||
|
||||
呈现精灵列表的方法可能类似于:
|
||||
|
||||
```
|
||||
def render_sprites(render_surface, sprites):
|
||||
"""
|
||||
sprites 应该是符合 Sprite 接口的对象列表:
|
||||
* 一个名为 "bounding_box" 的属性,包含了边界框
|
||||
* 一个名为 "intersects" 的方法,它接受一个边界框并返回 True 或 False
|
||||
"""
|
||||
pass # 一些做实际渲染的代码
|
||||
```
|
||||
|
||||
该游戏将具有许多处理精灵的函数。在每个函数中,你都必须在随附文档中指定预期。
|
||||
|
||||
此外,某些函数可能期望使用更复杂的精灵对象,例如具有 Z 序的对象。我们必须跟踪哪些方法需要 Sprite 对象,哪些方法需要 SpriteWithZ 对象。
|
||||
|
||||
如果能够使精灵是显式而直观的,这样方法就可以声明“我需要一个精灵”,并有个严格定义的接口,这不是很好吗?来看看 `zope.interface`。
|
||||
|
||||
```
|
||||
from zope import interface
|
||||
|
||||
class ISprite(interface.Interface):
|
||||
|
||||
bounding_box = interface.Attribute(
|
||||
"边界框"
|
||||
)
|
||||
|
||||
def intersects(box):
|
||||
"它和一个框相交吗?"
|
||||
```
|
||||
|
||||
乍看起来,这段代码有点奇怪。这些方法不包括 `self`,而包含 `self` 是一种常见的做法,并且它有一个**属性**。这是在 `zope.interface` 中声明接口的方法。这看起来很奇怪,因为大多数人不习惯严格声明接口。
|
||||
|
||||
这样做的原因是接口显示了如何调用方法,而不是如何定义方法。因为接口不是超类,所以它们可以用来声明数据属性。
|
||||
|
||||
下面是一个能带有圆形精灵的接口的一个实现:
|
||||
|
||||
```
|
||||
@implementer(ISprite)
|
||||
@attr.s(auto_attribs=True)
|
||||
class CircleSprite:
|
||||
x: float
|
||||
y: float
|
||||
radius: float
|
||||
|
||||
@property
|
||||
def bounding_box(self):
|
||||
return (
|
||||
self.x - self.radius,
|
||||
self.y - self.radius,
|
||||
self.x + self.radius,
|
||||
self.y + self.radius,
|
||||
)
|
||||
|
||||
def intersects(self, box):
|
||||
# 当且仅当至少一个角在圆内时,方框与圆相交
|
||||
top_left, bottom_right = box[:2], box[2:]
|
||||
for choose_x_from (top_left, bottom_right):
|
||||
for choose_y_from (top_left, bottom_right):
|
||||
x = choose_x_from[0]
|
||||
y = choose_y_from[1]
|
||||
if (((x - self.x) ` 2 + (y - self.y) ` 2) <=
|
||||
self.radius ` 2):
|
||||
return True
|
||||
return False
|
||||
```
|
||||
|
||||
这**显式**声明了实现了该接口的 `CircleSprite` 类。它甚至能让我们验证该类是否正确实现了接口:
|
||||
|
||||
```
|
||||
from zope.interface import verify
|
||||
|
||||
def test_implementation():
|
||||
sprite = CircleSprite(x=0, y=0, radius=1)
|
||||
verify.verifyObject(ISprite, sprite)
|
||||
```
|
||||
|
||||
这可以由 pytest、nose 或其他测试框架运行,它将验证创建的精灵是否符合接口。测试通常是局部的:它不会测试仅在文档中提及的内容,甚至不会测试方法是否可以在没有异常的情况下被调用!但是,它会检查是否存在正确的方法和属性。这是对单元测试套件一个很好的补充,至少可以防止简单的拼写错误通过测试。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/zopeinterface-python-package
|
||||
|
||||
作者:[Moshe Zadka][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/moshezhttps://opensource.com/users/lauren-pritchetthttps://opensource.com/users/sethhttps://opensource.com/users/drmjg
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/getting_started_with_python.png?itok=MFEKm3gl (Snake charmer cartoon with a yellow snake and a blue snake)
|
||||
[2]: https://en.wikipedia.org/wiki/Zen_of_Python
|
||||
[3]: http://zope.org
|
@ -0,0 +1,137 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11774-1.html)
|
||||
[#]: subject: (Open source interior design with Sweet Home 3D)
|
||||
[#]: via: (https://opensource.com/article/19/10/interior-design-sweet-home-3d)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Sweet Home 3D 开放源码室内设计
|
||||
======
|
||||
|
||||
> 在你去真实世界购物前,在虚拟世界中尝试家具布局、配色方案等等。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/12/092633eyc3c9f7u3gfgj4e.jpg)
|
||||
|
||||
这里有关于如何装饰房间的三大流派:
|
||||
|
||||
1. 购买一堆家具,并把它们塞进房间。
|
||||
2. 仔细测量每件家具,计算房间的理论容量,然后把它们全部塞进房间,忽略你在床上放置一个书架的事实。
|
||||
3. 使用一台计算机进行预先可视化。
|
||||
|
||||
之前,我还实践了鲜为人知的第四个方式:不要家具。然而,自从我成为一个远程工作者,我发现家庭办公需要一些便利的设施,像一张桌子和一张椅子,一个用于存放参考书和技术手册的书架等等。因此,我一直在制定一个使用实际的家具来迁移我的生活和工作空间的计划,在该*计划*上强调由实木制作,而不是牛奶箱子(或胶水和锯末板之类的东西)。我最不想做的一件事:从旧货市场淘到得宝贝带回家时,发现其进不了门,或者比另一件家具大很多。
|
||||
|
||||
是时候做专业人士该做的事了,是时候做视觉预览了。
|
||||
|
||||
### 开放源码室内设计
|
||||
|
||||
[Sweet Home 3D][2] 是一个开源的(GPLv2)室内设计应用程序,可以帮助你绘制你的住宅平面图,然后定义、重新调整大小以及安排家具。你可以使用精确的尺寸来完成这些,精确到一厘米以下,而不使用任何数学运算,仅使用简单的拖拽操作就行。当你完成后,你可以以 3D 方式查看结果。在 Sweet Home 3D 中规划你家的室内设计,就和在 Word 程序中创建基本的表格一样简单。
|
||||
|
||||
### 安装
|
||||
|
||||
Sweet Home 3D 是一个 [Java][3] 应用程序,因此它是平台通用的。它运行在任何可以运行 Java 的操作系统上,包括 Linux、Windows、MacOS 和 BSD 。不用理会你的操作系统,你可以从网站[下载][4]该应用程序。
|
||||
|
||||
* 在 Linux 上,[untar][5] 存档文件。在 `SweetHome3D` 文件上右键单击,并选择**属性**。在**权限**选项卡中,授予文件可执行权限。
|
||||
* 在 MacOS 和 Windows 上,展开存档文件并启动应用程序。当系统提示时,你必需授予它权限来在你的系统上运行。
|
||||
|
||||
![Sweet Home 3D permissions][6]
|
||||
|
||||
在 Linux 上,你也可以像一个 Snap 软件包一样安装 Sweet Home 3D ,前提是你已经安装并启用 **snapd**。
|
||||
|
||||
### 成功的测量
|
||||
|
||||
首先:打开你的卷尺。为充分利用 Sweet Home 3D,你必须知道你所计划的生活空间的实际尺寸。你可能需要测量精度到毫米或 1/16 英寸;你可以自己把握对偏差幅度的容忍度。但是你必需获得基本的尺寸,包括测量墙壁和门窗。
|
||||
|
||||
用你最好的判断力来判断常识。例如,当测量门时,包括门框;虽然从技术上讲它不是*门*本身的一部分,但它可能是你不想用家具遮挡的一部分墙壁空间。
|
||||
|
||||
![Measure twice, execute once][7]
|
||||
|
||||
### 创建一间房间
|
||||
|
||||
当你第一次启动 Sweet Home 3D 时,它会以其默认查看模式来打开一个空白的画布,蓝图视图在顶部面板中,3D 渲染在底部面板中。在我的 [Slackware][8] 桌面计算机上,它可以很好地工作,不过我的桌面计算机也是我的视频编辑和游戏计算机,所以它有一个极好的 3D 渲染显卡。在我的笔记本计算机上,这种视图模式是非常慢的。为了最好的性能(尤其是在一台计没有 3D 渲染的专用计算机上),转到窗口顶部的 **3D 视图** 菜单,并选择 **虚拟访问** 。这个视图模式基于虚拟访客的位置从地面视图渲染你的工作。这意味着你可以控制渲染的内容和时机。
|
||||
|
||||
不管你计算机是否强力,切换到这个视图的有意义的,因为地表以上的 3D 渲染不比蓝图平面图向你提供更多有用的详细信息。在你更改视图模式后,你可以开始设计。
|
||||
|
||||
第一步是定义你家的墙壁。使用**创建墙壁**工具完成,可以在顶部工具栏的**手形**图标右侧找到。绘制墙壁很简单:单击你想要墙壁开始的位置,单击以锚定位置,不断单击锚定,直到你的房间完成。
|
||||
|
||||
![Drawing walls in Sweet Home 3D][9]
|
||||
|
||||
在你闭合墙壁后,按 `Esc` 来退出工具。
|
||||
|
||||
#### 定义一间房间
|
||||
|
||||
Sweet Home 3D 在你如何创建墙壁的问题上是灵活的。你可以先绘制你房子的外部边界,然后再细分内部,或者你可以绘制每个房间作为结成一体的“容器”,最终形成你房子所占的空间量。这种灵活性是能做到的,因为在现实生活中和在 Sweet Home 3D 中,墙壁并不总是用来定义一间房间。为定义一间房间,使用在顶部工具栏的**创建墙壁**按钮右侧的**创建房间**按钮。
|
||||
|
||||
如果房间的地板空间是通过四面墙所定义,你需要做的全部的定义是像一间房间一样在四面墙壁内双击来圈占地方。Sweet Home 3D 将定义该空间为一间房间,并根据你的喜好,以英尺或米为单位向你提供房间的面积。
|
||||
|
||||
对于不规则的房间,你必需使用每次单击来手动定义房间的每个墙角。根据房间形状的复杂性,你可能不得不进行试验来发现你是否需要从你的原点来顺时针或逆时针工作,以避免奇怪的莫比斯条形地板。不过,一般来说,定义一间房间的地板空间是简单的。
|
||||
|
||||
![Defining rooms in Sweet Home 3D][10]
|
||||
|
||||
在你给定房间一层地板后,你可以更改到**箭头**工具,并在房间上双击来给予它一个名称。你也可以设置地板、墙壁、天花板和踢脚线的颜色及纹理。
|
||||
|
||||
![Modifying room floors, ceilings, etc. in Sweet Home 3D][11]
|
||||
|
||||
默认情况下,这些都不会在蓝图视图中渲染。为启用在你蓝图面板中的房间渲染,转到**文件**菜单并选择**首选项**。在**首选项**面板中,设置**平面图中房间渲染**为**地板颜色或纹理**。
|
||||
|
||||
### 门和窗
|
||||
|
||||
在你完成基本的地板平面图后,你可以长期地切换到**箭头**工具。
|
||||
|
||||
你可以在 Sweet Home 3D 的左栏中的**门和窗**类别下找到门和窗。你有很多选择,所以选择最接近你家的东西。
|
||||
|
||||
![Moving a door in Sweet Home 3D][12]
|
||||
|
||||
为放置一扇门或窗到你的平面图中,在你的蓝图平面图中的合适的墙壁上拖拽门或窗。要调整它的位置和大小,请双击门或窗。
|
||||
|
||||
### 添加家具
|
||||
|
||||
随着基本平面图完成,这部分工作感觉像是结束了!从这点继续,你可以摆弄家具布置以及其它装饰。
|
||||
|
||||
你可以在左栏中找到家具,按预期的方式来组织每个房间。你可以拖拽任何项目到你的蓝图平面图中,当你的鼠标悬停在项目的区域上时,使用可视化工具控制方向和大小。在任何项目上双击双击来调整它的颜色和成品表面。
|
||||
|
||||
### 查看和导出
|
||||
|
||||
为了看看你未来的家将会看起来是什么样子,在你的蓝图视图中拖拽“人”图标到一个房间中。
|
||||
|
||||
![Sweet Home 3D rendering][13]
|
||||
|
||||
你可以在现实和空间感受之间找到自己的平衡,你的想象力是你唯一的限制。你可以从 Sweet Home 3D [下载页面][4]获取附加的有用的资源来添加到你的家中。你甚至可以使用**库编辑器**应用程序创建你自己的家具和纹理,它可以从该项目的网站下载。
|
||||
|
||||
Sweet Home 3D 可以导出你的蓝图平面图为 SVG 格式,以便在 [Inkscape][14] 中使用,并且它可以导出你的 3D 模型为 OBJ 格式,以便在 [Blender][15] 中使用。为导出你的蓝图,转到**平面图**菜单,并选择**导出为 SVG 格式**。为导出一个 3D 模型,转到 **3D 视图** 菜单并选择**导出为 OBJ 格式**。
|
||||
|
||||
你也可以拍摄你家的"快照,以便于不打开 Sweet Home 3D 而回顾你的想法。为创建一个快照,转到 **3D 视图**菜单并选择**创建照片**。快照是按照蓝图视图中的人的图标的角度展现的,因此按照需要调整,然后在**创建照片**窗口中单击**创建**按钮。如果你对快照满意,单击**保存**。
|
||||
|
||||
### 甜蜜的家
|
||||
|
||||
在 Sweet Home 3D 中有更多的特色。你可以添加一片天空和一片草坪,为你的照片定位光线,设置天花板高度,给你房子添加另一楼层等等。不管你是打算租一套公寓,还是买一套房子,或是(尚)不存在的房子,Sweet Home 3D 是一款简单迷人的应用程序,当你匆忙购买家具时,它可以帮助你快乐地做出更好的购买选择。因此,你终于可以停止在厨房的柜台上吃早餐以及蹲在地上工作了。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/interior-design-sweet-home-3d
|
||||
|
||||
作者:[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/LIFE_housing.png?itok=s7i6pQL1 (Several houses)
|
||||
[2]: http://www.sweethome3d.com/
|
||||
[3]: https://opensource.com/resources/java
|
||||
[4]: http://www.sweethome3d.com/download.jsp
|
||||
[5]: https://opensource.com/article/17/7/how-unzip-targz-file
|
||||
[6]: https://opensource.com/sites/default/files/uploads/sweethome3d-permissions.png (Sweet Home 3D permissions)
|
||||
[7]: https://opensource.com/sites/default/files/images/life/sweethome3d-measure.jpg (Measure twice, execute once)
|
||||
[8]: http://www.slackware.com/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/sweethome3d-walls.jpg (Drawing walls in Sweet Home 3D)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/sweethome3d-rooms.jpg (Defining rooms in Sweet Home 3D)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/sweethome3d-rooms-modify.jpg (Modifying room floors, ceilings, etc. in Sweet Home 3D)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/sweethome3d-move.jpg (Moving a door in Sweet Home 3D)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/sweethome3d-view.jpg (Sweet Home 3D rendering)
|
||||
[14]: http://inkscape.org
|
||||
[15]: http://blender.org
|
204
published/20191017 Intro to the Linux useradd command.md
Normal file
204
published/20191017 Intro to the Linux useradd command.md
Normal file
@ -0,0 +1,204 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11756-1.html)
|
||||
[#]: subject: (Intro to the Linux useradd command)
|
||||
[#]: via: (https://opensource.com/article/19/10/linux-useradd-command)
|
||||
[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
|
||||
|
||||
Linux useradd 命令介绍
|
||||
======
|
||||
|
||||
> 使用 useradd 命令来添加用户(并且根据需要修改账号)。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/06/225733hv1u7f4z4vbt8u5x.jpg)
|
||||
|
||||
任何计算机系统中,添加用户都是最重要的事之一;本文着重介绍如何在 Linux 系统中添加用户。
|
||||
|
||||
正式开始之前,我先提三个概念。首先,跟大多数操作系统一样,Linux 用户也需要一个账号才能登录。本文只介绍本地账号,不涉及网络账号,如 LDAP。其次,每个账号都有一个名字(username)和一个对应的数字(用户 ID)。最后,每个用户通常都在一个组内,每个组都有一个名字和一个组 ID。
|
||||
|
||||
你可能已经想到了,Linux 提供了添加用户的命令行工具,就是 `useradd` 命令。有些版本也叫 `adduser`。为了方便使用,很多发行版上这个命令是一个指向 `useradd` 命令的符号链接。
|
||||
|
||||
```
|
||||
$ file `which adduser`
|
||||
/usr/sbin/adduser: symbolic link to useradd
|
||||
```
|
||||
|
||||
来看一下 `useradd`。
|
||||
|
||||
> 注意:本文描述的默认环境是 Red Hat Enterprise Linux 8.0。你可能会发现本文描述的这些文件和某些默认值与某些 Linux 发行版或其他 Unix 操作系统(FreeBSD 或 Solaris)偶尔会有差异。
|
||||
|
||||
### 默认处理
|
||||
|
||||
`useradd` 的基本用法相当简单:提供一个用户名就可以添加一个用户。
|
||||
|
||||
```bash
|
||||
$ sudo useradd sonny
|
||||
```
|
||||
|
||||
在本例中,`useradd` 命令创建了一个名为 `sonny` 的账号。此命令同时创建了一个同名的组,`sonny` 被放进了这个组,这个组也是 `sonny` 账号的主组。命令执行时,根据配置文件 `/etc/default/useradd` 和 `/etc/login.defs` 中的不同设置,也会有其他的参数,如语言和 shell。对于一个私人系统或微小的单服务商业环境,这些参数已经足够了。
|
||||
|
||||
上面两个文件控制 `useradd` 的处理,用户的信息保存在 `/etc` 目录下的一些其他文件中,关于这些信息的讲解会贯穿全文。
|
||||
|
||||
| 文件 | 描述 | 域 (加粗的表示由 useradd 命令设置) |
|
||||
| ------ | ------------------------------------ | ------------------------------------------------------------ |
|
||||
| `passwd` | 存储用户账号信息 | **用户名**:未使用:**UID**:**GID**:**备注**:**家目录**:**shell** |
|
||||
| `shadow` | 存储用户账号的安全信息 | **用户名**:加密密码:上次修改时间:最短使用天数:最长使用天数间:**修改前警示天数**:**过期后宽限时间**:未使用 |
|
||||
| `group` | 存储组信息 | **组名**:未使用:**GID**:**成员列表** |
|
||||
|
||||
### 自定义处理
|
||||
|
||||
当管理员需要更好地控制账号时,可以使用命令行来自定义,如指定一个用户的 ID。
|
||||
|
||||
#### 用户和组 ID
|
||||
|
||||
默认情况下,`useradd` 试图使用相同的用户 ID(UID)和主组 ID(GID),但也不完全是。虽然 UID 与 GID 相同不是必须的,但如果相同,会更方便管理员管理。
|
||||
|
||||
下面的场景就是一个 GID 与 UID 不同的例子。现在我添加另一账号,名为 Timmy。通过使用 `getent` 命令来比较 `sonny` 和 `timmy` 两个账号,显示两个用户和对应的主组。
|
||||
|
||||
```bash
|
||||
$ getent passwd sonny timmy
|
||||
sonny:x:1001:1002:Sonny:/home/sonny:/bin/bash
|
||||
timmy:x:1002:1003::/home/timmy:/bin/bash
|
||||
|
||||
$ getent group sonny timmy
|
||||
sonny:x:1002:
|
||||
timmy:x:1003:
|
||||
```
|
||||
|
||||
不幸的是,两者的 UID 和 GID 都不相同。因为默认的处理是,创建用户时,把下一个可用的 UID 赋给用户,然后把同一个数字作为主组 ID 赋给它。然而,当要使用的组 ID 已经被使用时,就再把下一个可用的 GID 赋给它。为了弄清细节,我猜想 1001 这个 GID 已经被使用了,用一个命令确认了一下。
|
||||
|
||||
```bash
|
||||
$ getent group 1001
|
||||
book:x:1001:alan
|
||||
```
|
||||
|
||||
`book` 的 ID 是 `1001`,因此新创建的用户的 GID 都有偏移量 1。这就是为什么系统管理员在用户创建过程中需要多设置一些值的一个实例。为了解决这个问题,我必须先确定下一个可用的 UID 和 GID 是否相同。确定下一个可用值时,可以使用 `getent group` 和 `getent passwd` 命令,通过 `-u` 参数传递要确认的值。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -u 1004 bobby
|
||||
|
||||
$ getent passwd bobby; getent group bobby
|
||||
bobby:x:1004:1004::/home/bobby:/bin/bash
|
||||
bobby:x:1004:
|
||||
```
|
||||
|
||||
另一个需要指定 ID 的场景是,通过 NFS 访问远程系统上的文件时。对于一个给定的用户,当 NFS 所有客户端和服务系统的 ID 都一样时,管理员更容易控制。在我的文章 [使用 autofs 挂载 NFS][2] 中有详细介绍。
|
||||
|
||||
### 更多自定义
|
||||
|
||||
一些其他的指定用户信息的参数也用得比较频繁。这里是一些你会经常用到的参数的概括例子。
|
||||
|
||||
#### 注释
|
||||
|
||||
注释选项是通过 `-c` 参数指定的一个解释文本字段,可以提供一段简短的描述或其他信息。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -c "Bailey is cool" bailey
|
||||
$ getent passwd bailey
|
||||
bailey:x:1011:1011:Bailey is cool:/home/bailey:/bin/bash
|
||||
```
|
||||
|
||||
#### 组
|
||||
|
||||
一个用户可以被指定一个主组和多个次组。`-g` 参数指定主组名称或 GID。如果不指定,`useradd` 会以用户名创建一个主组(前面演示过)。`-G`(大写)参数用一个逗号分隔的组列表来指定此用户所属的组,这些组就是次组。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -G tgroup,fgroup,libvirt milly
|
||||
$ id milly
|
||||
uid=1012(milly) gid=1012(milly) groups=1012(milly),981(libvirt),4000(fgroup),3000(tgroup)
|
||||
```
|
||||
|
||||
#### 家目录
|
||||
|
||||
`useradd` 的默认处理是,在 `/home` 目录下创建用户的家目录。然而,下面的参数可以改写家目录的基础目录。`-b` 设置另一个可以创建家目录的基础目录。例如指定 `/home2` 而不是 `/home`。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -b /home2 vicky
|
||||
$ getent passwd vicky
|
||||
vicky:x:1013:1013::/home2/vicky:/bin/bash
|
||||
```
|
||||
|
||||
`-d` 参数可以指定一个与用户名不同的家目录。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -d /home/ben jerry
|
||||
$ getent passwd jerry
|
||||
jerry:x:1014:1014::/home/ben:/bin/bash
|
||||
```
|
||||
|
||||
#### 目录模板
|
||||
|
||||
指定 `-k` 参数会在创建新用户时,复制 `/etc/skel` 目录下的所有文件到用户的家目录中。这些文件通常是 shell 配置文件,当然也可以是系统管理员想在新建用户时使用的任何文件。
|
||||
|
||||
#### Shell
|
||||
|
||||
`-s` 参数可以指定 shell。如果不指定,则使用默认的 shell。例如,下面的例子中 ,配置文件中定义的 shell 是 `bash`,但 `wally` 这个用户指定的是 `zsh`。
|
||||
|
||||
```bash
|
||||
SHELL=/bin/bash
|
||||
|
||||
$ sudo useradd -s /usr/bin/zsh wally
|
||||
$ getent passwd wally
|
||||
wally:x:1004:1004::/home/wally:/usr/bin/zsh
|
||||
```
|
||||
|
||||
#### 安全
|
||||
|
||||
安全是用户管理的重中之重,因此 `useradd` 命令也提供了很多关于安全的选项。可以使用 `-e` 参数,以 YYYY-MM-DD 的格式指定一个用户的过期时间。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -e 20191231 sammy
|
||||
$ sudo getent shadow sammy
|
||||
sammy:!!:18171:0:99999:7::20191231:
|
||||
```
|
||||
|
||||
当密码过期时,账号也会自动失效。`-f` 参数指定密码过期后经过几天账号失效。如果设为 0,则立即失效。
|
||||
|
||||
```bash
|
||||
$ sudo useradd -f 30 willy
|
||||
$ sudo getent shadow willy
|
||||
willy:!!:18171:0:99999:7:30::
|
||||
```
|
||||
|
||||
### 实例
|
||||
|
||||
生产环境中,创建一个用户账号时会用到多个参数。例如,我要创建一个 Perry 账号,可能会用下面的命令:
|
||||
|
||||
```bash
|
||||
$ sudo useradd -u 1020 -c "Perry Example" \
|
||||
-G tgroup -b /home2 \
|
||||
-s /usr/bin/zsh \
|
||||
-e 20201201 -f 5 perry
|
||||
```
|
||||
|
||||
查看前面的内容来理解每个选项。用下面的命令确认结果:
|
||||
|
||||
```bash
|
||||
$ getent passwd perry; getent group perry; getent shadow perry; id perry
|
||||
perry:x:1020:1020:Perry Example:/home2/perry:/usr/bin/zsh
|
||||
perry:x:1020:
|
||||
perry:!!:18171:0:99999:7:5:20201201:
|
||||
uid=1020(perry) gid=1020(perry) groups=1020(perry),3000(tgroup)
|
||||
```
|
||||
|
||||
### 一点小建议
|
||||
|
||||
`useradd` 命令是所有 Unix(不仅仅是 Linux)系统管理员都必知必会的命令。由于用户创建不能出错,需要第一次就正确,所以理解它的每一个选项很重要。这意味着你需要有一套深思熟虑的命名约定,包括为整个企业环境而不仅仅是一个单系统预留一个专用的 UID/GID 范围,尤其是你为一个成长中的组织工作时。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/linux-useradd-command
|
||||
|
||||
作者:[Alan Formy-Duval][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alanfdoss
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/connection_people_team_collaboration.png?itok=0_vQT8xV (people in different locations who are part of the same team)
|
||||
[2]: https://opensource.com/article/18/6/using-autofs-mount-nfs-shares
|
@ -0,0 +1,168 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11735-1.html)
|
||||
[#]: subject: (How to cohost GitHub and GitLab with Ansible)
|
||||
[#]: via: (https://opensource.com/article/19/11/how-host-github-gitlab-ansible)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
如何使用 Ansible 同步 GitHub 和 GitLab
|
||||
======
|
||||
|
||||
> 通过使用 Ansible 镜像 Git 存储库,保护对重要项目的访问。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/01/104040fbdu68wosg8o99wg.jpg)
|
||||
|
||||
开源无处不在。它在家里的计算机上、在工作场所的计算机上、在互联网上,并且很多都由 [Git][2] 管理。由于 Git 是分布式的,因此许多人也将其视为一种众包的备份解决方案。从理论上讲,每当有人将 Git 存储库克隆到其本地计算机时,他们就创建了该项目源代码的备份。如果有 100 个人这样做,则存储库就有 100 个备份副本。
|
||||
|
||||
从理论上讲,这可以缓解“灾难”的影响,例如当项目维护者[突然决定删除存储库][3]或[莫名其妙地阻止所有流量][4],导致开发人员们无头苍蝇般地寻找谁拥有主分支的最新版本。类似的,整个代码托管站点也会消失。没有人会想到 Google Code、Microsoft CodePlex 或 Gitorious 会在鼎盛时期将被关闭。
|
||||
|
||||
简而言之,如果在过去的几十年中互联网教给了我们一些东西,那就是依靠互联网神奇地创建备份并不是冗余的最可靠途径。
|
||||
|
||||
此外,对于许多人来说,很多开源项目都托管在 GitHub 上是个问题 —— GitHub 并不是开放平台。许多开发人员和用户都希望支持诸如 GitLab 之类的堆栈并与之交互,它具有开源社区版本。
|
||||
|
||||
### 使用 Ansible 管理 Git
|
||||
|
||||
Git 的去中心方式对于解决这个问题很有用。使用纯 Git,你可以使用一个 `push` 命令轻松地将其推到两个或多个存储库。但是,为了使其在发生意外故障时有用,你必须经常与 Git 存储库进行交互(特别是推送)。此外,即使你可能永远不会自己推送或拉出代码,也可能有一些要备份的存储库。
|
||||
|
||||
但是,使用 Ansible,你可以自动执行项目主分支(或其他任何分支)的 Git 拉取,然后自动进行存储库到“异地”镜像的 Git 推送。换句话说,你可以让你的计算机定期从 GitHub 拉取并推送到 GitLab 或 [Gitolite][5] 或 Gitea(或你喜欢的任何 Git 托管主机)。
|
||||
|
||||
### Ansible 模块
|
||||
|
||||
如果不是因其出色的模块集合,那么 Ansible 就没那么出色。像 Python 的第三方库或 Linux 的应用程序一样,这个技术引擎的一个有用而令人惊讶的简单技巧是,Ansible 以其他人贡献的组件而闻名。因为本文正在研究如何有效和可靠地备份 Git 存储库,所以这里使用的模块是 [Git 模块][6]和 [ini_file][7] 模块。
|
||||
|
||||
首先,创建一个名为 `mirror.yaml` 的文件作为<ruby>剧本<rt>playbook</rt></ruby>。你可以像通常使用 Ansible 一样,从 `name` 和 `task` 条目开始。本示例将 `localhost` 添加到 `hosts` 列表中,以便在控制器计算机(你现在坐在前面的计算机)上运行<ruby>动作<rt>play</rt></ruby>,但是在现实生活中,你可能会在特定的主机或一组网络上的主机上运行它。
|
||||
|
||||
```
|
||||
---
|
||||
- name: "Mirror a Git repo with Ansible"
|
||||
hosts: localhost
|
||||
tasks:
|
||||
```
|
||||
|
||||
### Git 拉取和克隆
|
||||
|
||||
如果要进行备份,则需要最新代码的副本。明显,在 Git 仓库中实现这一目标的方法是执行 `git pull`。 但是,`pull` 会假定克隆已经存在,而写得很好的 Ansible 动作(Ansible 脚本)则尽可能少的假定。最好告诉 Ansible 先克隆存储库。
|
||||
|
||||
将你的第一个任务添加到剧本:
|
||||
|
||||
```
|
||||
---
|
||||
- name: "Mirror a Git repo with Ansible"
|
||||
hosts: localhost
|
||||
vars:
|
||||
git_dir: /tmp/soso.git
|
||||
tasks:
|
||||
|
||||
- name: "Clone the git repo"
|
||||
git:
|
||||
repo: 'https://github.com/ozkl/soso.git'
|
||||
dest: '{{ git_dir }}'
|
||||
clone: yes
|
||||
update: yes
|
||||
```
|
||||
|
||||
这个例子使用了开源的、类似于 Unix 的操作系统 soso 作为我要镜像的存储库。这是一个完全任意的选择,绝不意味着我对该存储库的未来缺乏信心。它还使用变量来引用目标文件夹 `/tmp/soso.git`,这很方便,并且如果以后你希望将它扩展为一个通用的镜像脚本也会受益。在现实生活中,你的工作机上可能会比 `/tmp` 具有更永久的位置,例如 `/home/gitmirrors/soso.git` 或 `/opt/gitmirrors/soso.git`。
|
||||
|
||||
运行你的剧本:
|
||||
|
||||
```
|
||||
$ ansible-playbook mirror.yaml
|
||||
```
|
||||
|
||||
首次运行该剧本时,Ansible 会正确检测到 Git 存储库在本地尚不存在,因此将其克隆。
|
||||
|
||||
```
|
||||
PLAY [Ansible Git mirror] ********
|
||||
|
||||
TASK [Gathering Facts] ***********
|
||||
ok: [localhost]
|
||||
|
||||
TASK [Clone git repo] ************
|
||||
changed: [localhost]
|
||||
|
||||
PLAY RECAP ***********************
|
||||
localhost: ok=2 changed=1 failed=0 [...]
|
||||
```
|
||||
|
||||
如果你再次运行该剧本,Ansible 会正确检测到自上次运行以来没有任何更改,并且会报告未执行任何操作:
|
||||
|
||||
```
|
||||
localhost: ok=2 changed=0 failed=0 [...]
|
||||
```
|
||||
|
||||
接下来,必须指示 Ansible 将存储库推送到另一个 Git 服务器。
|
||||
|
||||
### Git 推送
|
||||
|
||||
Ansible 中的 Git 模块不提供 `push` 功能,因此该过程的一部分是手动的。但是,在将存储库推送到备用镜像之前,你必须具有一个镜像,并且必须将镜像配置为备用<ruby>远程服务器<rt>remote</rt></ruby>。
|
||||
|
||||
首先,必须将备用的远程服务器添加到 Git 配置。因为 Git 配置文件是 INI 样式的配置,所以你可以使用 `ini_file` Ansible 模块轻松地添加所需的信息。将此添加到你的剧本:
|
||||
|
||||
```
|
||||
- name: "Add alternate remote"
|
||||
ini_file: dest={{ git_dir }}/.git/config section='remote \"mirrored\"' option=url value='git@gitlab.com:example/soso-mirror.git'
|
||||
tags: configuration
|
||||
```
|
||||
|
||||
为此,你必须在目标服务器上有一个空的存储库(在本例中为 [GitLab.com][9])。如果需要在剧本中创建目标存储库,可以按照 Steve Ovens 的出色文章《[如何使用 Ansible 通过 SSH 设置 Git 服务器][10]》来完成。
|
||||
|
||||
最后,直接使用 Git 将 HEAD 推送到备用远程服务器:
|
||||
|
||||
```
|
||||
- name: "Push the repo to alternate remote"
|
||||
shell: 'git --verbose --git-dir={{ git_dir }}/.git push mirrored HEAD'
|
||||
```
|
||||
|
||||
像往常一样运行该剧本,然后使该过程自动化,这样你就不必再次直接运行它了。你可以使用变量和特定的 Git 命令来调整脚本以适应你的需求,但是通过常规的拉取和推送操作,可以确保驻留在一台服务器上的重要项目可以安全地镜像到另一台服务器上。
|
||||
|
||||
这是完整的剧本,供参考:
|
||||
|
||||
```
|
||||
---
|
||||
- name: "Mirror a Git repository with Ansible"
|
||||
hosts: localhost
|
||||
vars:
|
||||
git_dir: /tmp/soso.git
|
||||
|
||||
tasks:
|
||||
|
||||
- name: "Clone the Git repo"
|
||||
git:
|
||||
repo: 'https://github.com/ozkl/soso.git'
|
||||
dest: '{{ git_dir }}'
|
||||
clone: yes
|
||||
update: yes
|
||||
|
||||
- name: "Add alternate remote"
|
||||
ini_file: dest={{ git_dir }}/.git/config section='remote \"mirrored\"' option=url value='git@gitlab.com:example/soso-mirror.git'
|
||||
tags: configuration
|
||||
|
||||
- name: "Push the repo to alternate remote"
|
||||
shell: 'git --verbose --git-dir={{ git_dir }}/.git push mirrored HEAD'
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/how-host-github-gitlab-ansible
|
||||
|
||||
作者:[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/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
|
||||
[2]: https://opensource.com/resources/what-is-git
|
||||
[3]: https://github.com/AntiMicro/antimicro/issues/3
|
||||
[4]: https://opensource.com/article/19/10/how-community-saved-artwork-creative-commons
|
||||
[5]: https://opensource.com/article/19/4/server-administration-git
|
||||
[6]: https://docs.ansible.com/ansible/latest/modules/git_module.html
|
||||
[7]: https://docs.ansible.com/ansible/latest/modules/ini_file_module.html
|
||||
[8]: mailto:git@gitlab.com
|
||||
[9]: http://GitLab.com
|
||||
[10]: https://opensource.com/article/17/8/ansible-environment-management
|
395
published/20191121 Simulate gravity in your Python game.md
Normal file
395
published/20191121 Simulate gravity in your Python game.md
Normal file
@ -0,0 +1,395 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11780-1.html)
|
||||
[#]: subject: (Simulate gravity in your Python game)
|
||||
[#]: via: (https://opensource.com/article/19/11/simulate-gravity-python)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
在你的 Python 游戏中模拟引力
|
||||
======
|
||||
|
||||
> 学习如何使用 Python 的 Pygame 模块编程电脑游戏,并开始操作引力。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/13/223923k6t4zmvvmo6tfmmg.png)
|
||||
|
||||
真实的世界充满了运动和生活。物理学使得真实的生活如此忙碌和动态。物理学是物质在空间中运动的方式。既然一个电脑游戏世界没有物质,它也就没有物理学规律,使用游戏程序员不得不*模拟*物理学。
|
||||
|
||||
从大多数电脑游戏来说,这里基本上仅有两个方面的物理学是重要的:引力和碰撞。
|
||||
|
||||
当你[添加一个敌人][2]到你的游戏中时,你实现了一些碰撞检测,但是这篇文章要添加更多的东西,因为引力需要碰撞检测。想想为什么引力可能涉及碰撞。如果你不能想到任何原因,不要担心 —— 它会随着你开发示例代码工作而且显然。
|
||||
|
||||
在真实世界中的引力是有质量的物体来相互吸引的倾向性。物体(质量)越大,它施加越大的引力作用。在电脑游戏物理学中,你不必创建质量足够大的物体来证明引力的正确;你可以在电脑游戏世界本身中仅编程一个物体落向假设的最大的对象的倾向。
|
||||
|
||||
### 添加一个引力函数
|
||||
|
||||
记住你的玩家已经有了一个决定动作的属性。使用这个属性来将玩家精灵拉向屏幕底部。
|
||||
|
||||
在 Pygame 中,较高的数字更接近屏幕的底部边缘。
|
||||
|
||||
在真实的世界中,引力影响一切。然而,在平台游戏中,引力是有选择性的 —— 如果你添加引力到你的整个游戏世界,你的所有平台都将掉到地上。反之,你可以仅添加引力到你的玩家和敌人精灵中。
|
||||
|
||||
首先,在你的 `Player` 类中添加一个 `gravity` 函数:
|
||||
|
||||
```
|
||||
def gravity(self):
|
||||
self.movey += 3.2 # 玩家掉落的多快
|
||||
```
|
||||
|
||||
这是一个简单的函数。首先,不管你的玩家是否想运动,你设置你的玩家垂直运动。也就是说,你已经编程你的玩家总是在下降。这基本上就是引力。
|
||||
|
||||
为使引力函数生效,你必须在你的主循环中调用它。这样,当每一个处理循环时,Python 都应用下落运动到你的玩家。
|
||||
|
||||
在这代码中,添加第一行到你的循环中:
|
||||
|
||||
```
|
||||
player.gravity() # 检查引力
|
||||
player.update()
|
||||
```
|
||||
|
||||
启动你的游戏来看看会发生什么。要注意,因为它发生的很快:你是玩家从天空上下落,马上掉出了你的游戏屏幕。
|
||||
|
||||
你的引力模拟是工作的,但是,也许太好了。
|
||||
|
||||
作为一次试验,尝试更改你玩家下落的速度。
|
||||
|
||||
### 给引力添加一个地板
|
||||
|
||||
你的游戏没有办法发现你的角色掉落出世界的问题。在一些游戏中,如果一个玩家掉落出世界,该精灵被删除,并在某个新的位置重生。在另一些游戏中,玩家会丢失分数或一条生命。当一个玩家掉落出世界时,不管你想发生什么,你必须能够侦测出玩家何时消失在屏幕外。
|
||||
|
||||
在 Python 中,要检查一个条件,你可以使用一个 `if` 语句。
|
||||
|
||||
你必需查看你玩家**是否**正在掉落,以及你的玩家掉落的程度。如果你的玩家掉落到屏幕的底部,那么你可以做*一些事情*。简化一下,设置玩家精灵的位置为底部边缘上方 20 像素。
|
||||
|
||||
使你的 `gravity` 函数看起来像这样:
|
||||
|
||||
```
|
||||
def gravity(self):
|
||||
self.movey += 3.2 # 玩家掉落的多快
|
||||
|
||||
if self.rect.y > worldy and self.movey >= 0:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty
|
||||
```
|
||||
|
||||
然后,启动你的游戏。你的精灵仍然下落,但是它停在屏幕的底部。不过,你也许不能*看到*你在地面层之上的精灵。一个简单的解决方法是,在精灵碰撞游戏世界的底部后,通过添加另一个 `-ty` 到它的新 Y 位置,从而使你的精灵弹跳到更高处:
|
||||
|
||||
```
|
||||
def gravity(self):
|
||||
self.movey += 3.2 # 玩家掉落的多快
|
||||
|
||||
if self.rect.y > worldy and self.movey >= 0:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty-ty
|
||||
```
|
||||
|
||||
现在你的玩家在屏幕底部弹跳,恰好在你地面精灵上面。
|
||||
|
||||
你的玩家真正需要的是反抗引力的方法。引力问题是,你不能反抗它,除非你有一些东西来推开引力作用。因此,在接下来的文章中,你将添加地面和平台碰撞以及跳跃能力。在这期间,尝试应用引力到敌人精灵。
|
||||
|
||||
到目前为止,这里是全部的代码:
|
||||
|
||||
```
|
||||
#!/usr/bin/env python3
|
||||
# draw a world
|
||||
# add a player and player control
|
||||
# add player movement
|
||||
# add enemy and basic collision
|
||||
# add platform
|
||||
# add gravity
|
||||
|
||||
# GNU All-Permissive License
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# are permitted in any medium without royalty provided the copyright
|
||||
# notice and this notice are preserved. This file is offered as-is,
|
||||
# without any warranty.
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
import os
|
||||
|
||||
'''
|
||||
Objects
|
||||
'''
|
||||
|
||||
class Platform(pygame.sprite.Sprite):
|
||||
# x location, y location, img width, img height, img file
|
||||
def __init__(self,xloc,yloc,imgw,imgh,img):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.image = pygame.image.load(os.path.join('images',img)).convert()
|
||||
self.image.convert_alpha()
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.y = yloc
|
||||
self.rect.x = xloc
|
||||
|
||||
class Player(pygame.sprite.Sprite):
|
||||
'''
|
||||
Spawn a player
|
||||
'''
|
||||
def __init__(self):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.movex = 0
|
||||
self.movey = 0
|
||||
self.frame = 0
|
||||
self.health = 10
|
||||
self.score = 1
|
||||
self.images = []
|
||||
for i in range(1,9):
|
||||
img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
|
||||
img.convert_alpha()
|
||||
img.set_colorkey(ALPHA)
|
||||
self.images.append(img)
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect()
|
||||
|
||||
def gravity(self):
|
||||
self.movey += 3.2 # how fast player falls
|
||||
|
||||
if self.rect.y > worldy and self.movey >= 0:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty-ty
|
||||
|
||||
def control(self,x,y):
|
||||
'''
|
||||
control player movement
|
||||
'''
|
||||
self.movex += x
|
||||
self.movey += y
|
||||
|
||||
def update(self):
|
||||
'''
|
||||
Update sprite position
|
||||
'''
|
||||
|
||||
self.rect.x = self.rect.x + self.movex
|
||||
self.rect.y = self.rect.y + self.movey
|
||||
|
||||
# moving left
|
||||
if self.movex < 0:
|
||||
self.frame += 1
|
||||
if self.frame > ani*3:
|
||||
self.frame = 0
|
||||
self.image = self.images[self.frame//ani]
|
||||
|
||||
# moving right
|
||||
if self.movex > 0:
|
||||
self.frame += 1
|
||||
if self.frame > ani*3:
|
||||
self.frame = 0
|
||||
self.image = self.images[(self.frame//ani)+4]
|
||||
|
||||
# collisions
|
||||
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
|
||||
for enemy in enemy_hit_list:
|
||||
self.health -= 1
|
||||
print(self.health)
|
||||
|
||||
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
|
||||
for g in ground_hit_list:
|
||||
self.health -= 1
|
||||
print(self.health)
|
||||
|
||||
class Enemy(pygame.sprite.Sprite):
|
||||
'''
|
||||
Spawn an enemy
|
||||
'''
|
||||
def __init__(self,x,y,img):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.image = pygame.image.load(os.path.join('images',img))
|
||||
#self.image.convert_alpha()
|
||||
#self.image.set_colorkey(ALPHA)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = y
|
||||
self.counter = 0
|
||||
|
||||
def move(self):
|
||||
'''
|
||||
enemy movement
|
||||
'''
|
||||
distance = 80
|
||||
speed = 8
|
||||
|
||||
if self.counter >= 0 and self.counter <= distance:
|
||||
self.rect.x += speed
|
||||
elif self.counter >= distance and self.counter <= distance*2:
|
||||
self.rect.x -= speed
|
||||
else:
|
||||
self.counter = 0
|
||||
|
||||
self.counter += 1
|
||||
|
||||
class Level():
|
||||
def bad(lvl,eloc):
|
||||
if lvl == 1:
|
||||
enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
|
||||
enemy_list = pygame.sprite.Group() # create enemy group
|
||||
enemy_list.add(enemy) # add enemy to group
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return enemy_list
|
||||
|
||||
def loot(lvl,lloc):
|
||||
print(lvl)
|
||||
|
||||
def ground(lvl,gloc,tx,ty):
|
||||
ground_list = pygame.sprite.Group()
|
||||
i=0
|
||||
if lvl == 1:
|
||||
while i < len(gloc):
|
||||
ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
|
||||
ground_list.add(ground)
|
||||
i=i+1
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return ground_list
|
||||
|
||||
def platform(lvl,tx,ty):
|
||||
plat_list = pygame.sprite.Group()
|
||||
ploc = []
|
||||
i=0
|
||||
if lvl == 1:
|
||||
ploc.append((0,worldy-ty-128,3))
|
||||
ploc.append((300,worldy-ty-256,3))
|
||||
ploc.append((500,worldy-ty-128,4))
|
||||
|
||||
while i < len(ploc):
|
||||
j=0
|
||||
while j <= ploc[i][2]:
|
||||
plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
|
||||
plat_list.add(plat)
|
||||
j=j+1
|
||||
print('run' + str(i) + str(ploc[i]))
|
||||
i=i+1
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return plat_list
|
||||
|
||||
'''
|
||||
Setup
|
||||
'''
|
||||
worldx = 960
|
||||
worldy = 720
|
||||
|
||||
fps = 40 # frame rate
|
||||
ani = 4 # animation cycles
|
||||
clock = pygame.time.Clock()
|
||||
pygame.init()
|
||||
main = True
|
||||
|
||||
BLUE = (25,25,200)
|
||||
BLACK = (23,23,23 )
|
||||
WHITE = (254,254,254)
|
||||
ALPHA = (0,255,0)
|
||||
|
||||
world = pygame.display.set_mode([worldx,worldy])
|
||||
backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()
|
||||
backdropbox = world.get_rect()
|
||||
player = Player() # spawn player
|
||||
player.rect.x = 0
|
||||
player.rect.y = 0
|
||||
player_list = pygame.sprite.Group()
|
||||
player_list.add(player)
|
||||
steps = 10 # how fast to move
|
||||
|
||||
eloc = []
|
||||
eloc = [200,20]
|
||||
gloc = []
|
||||
#gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]
|
||||
tx = 64 #tile size
|
||||
ty = 64 #tile size
|
||||
|
||||
i=0
|
||||
while i <= (worldx/tx)+tx:
|
||||
gloc.append(i*tx)
|
||||
i=i+1
|
||||
|
||||
enemy_list = Level.bad( 1, eloc )
|
||||
ground_list = Level.ground( 1,gloc,tx,ty )
|
||||
plat_list = Level.platform( 1,tx,ty )
|
||||
|
||||
'''
|
||||
Main loop
|
||||
'''
|
||||
while main == True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit(); sys.exit()
|
||||
main = False
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_LEFT or event.key == ord('a'):
|
||||
print("LEFT")
|
||||
player.control(-steps,0)
|
||||
if event.key == pygame.K_RIGHT or event.key == ord('d'):
|
||||
print("RIGHT")
|
||||
player.control(steps,0)
|
||||
if event.key == pygame.K_UP or event.key == ord('w'):
|
||||
print('jump')
|
||||
|
||||
if event.type == pygame.KEYUP:
|
||||
if event.key == pygame.K_LEFT or event.key == ord('a'):
|
||||
player.control(steps,0)
|
||||
if event.key == pygame.K_RIGHT or event.key == ord('d'):
|
||||
player.control(-steps,0)
|
||||
if event.key == pygame.K_UP or event.key == ord('w'):
|
||||
print('jump')
|
||||
|
||||
if event.key == ord('q'):
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
main = False
|
||||
|
||||
world.blit(backdrop, backdropbox)
|
||||
player.gravity() # check gravity
|
||||
player.update()
|
||||
player_list.draw(world)
|
||||
enemy_list.draw(world)
|
||||
ground_list.draw(world)
|
||||
plat_list.draw(world)
|
||||
for e in enemy_list:
|
||||
e.move()
|
||||
pygame.display.flip()
|
||||
clock.tick(fps)
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
这是仍在进行中的关于使用 [Pygame][4] 模块来在 [Python 3][3] 在创建电脑游戏的第七部分。先前的文章是:
|
||||
|
||||
* [通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程][5]
|
||||
* [使用 Python 和 Pygame 模块构建一个游戏框架][6]
|
||||
* [如何在你的 Python 游戏中添加一个玩家][7]
|
||||
* [用 Pygame 使你的游戏角色移动起来][8]
|
||||
* [如何向你的 Python 游戏中添加一个敌人][2]
|
||||
* [在 Pygame 游戏中放置平台][9]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/simulate-gravity-python
|
||||
|
||||
作者:[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/space_stars_cosmic.jpg?itok=bE94WtN- (Cosmic stars in outer space)
|
||||
[2]: https://linux.cn/article-10883-1.html
|
||||
[3]: https://www.python.org/
|
||||
[4]: https://www.pygame.org
|
||||
[5]: https://linux.cn/article-9071-1.html
|
||||
[6]: https://linux.cn/article-10850-1.html
|
||||
[7]: https://linux.cn/article-10858-1.html
|
||||
[8]: https://linux.cn/article-10874-1.html
|
||||
[9]: https://linux.cn/article-10902-1.html
|
232
published/20191129 How to write a Python web API with Django.md
Normal file
232
published/20191129 How to write a Python web API with Django.md
Normal file
@ -0,0 +1,232 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to write a Python web API with Django)
|
||||
[#]: via: (https://opensource.com/article/19/11/python-web-api-django)
|
||||
[#]: author: (Rachel Waston https://opensource.com/users/rachelwaston)
|
||||
|
||||
如何借助 Django 来编写一个 Python Web API
|
||||
======
|
||||
|
||||
> Django 是 Python API 开发中最流行的框架之一,在这个教程中,我们来学习如何使用它。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/11/142503aio2325mk5weiozz.jpg)
|
||||
|
||||
[Django][2] 所有 Web 框架中最全面的,也是最受欢迎的一个。自 2005 年以来,其流行度大幅上升。
|
||||
|
||||
Django 是由 Django 软件基金会维护,并且获得了社区的大力支持,在全球拥有超过 11,600 名成员。在 Stack Overflow 上,约有 191,000 个带 Django 标签的问题。Spotify、YouTube 和 Instagram 等都使用 Django 来构建应用程序和数据管理。
|
||||
|
||||
本文演示了一个简单的 API,通过它可以使用 HTTP 协议的 GET 方法来从服务器获取数据。
|
||||
|
||||
### 构建一个项目
|
||||
|
||||
首先,为你的 Django 应用程序创建一个目录结构,你可以在系统的任何位置创建:
|
||||
|
||||
```
|
||||
$ mkdir myproject
|
||||
$ cd myproject
|
||||
```
|
||||
|
||||
然后,在项目目录中创建一个虚拟环境来隔离本地包依赖关系:
|
||||
|
||||
```
|
||||
$ python3 -m venv env
|
||||
$ source env/bin/activate
|
||||
```
|
||||
|
||||
在 Windows 上,使用命令 `env\Scripts\activate` 来激活虚拟环境。
|
||||
|
||||
### 安装 Django 和 Django REST framework
|
||||
|
||||
然后,安装 Django 和 Django REST 模块:
|
||||
|
||||
```
|
||||
$ pip3 install django
|
||||
$ pip3 install djangorestframework
|
||||
```
|
||||
|
||||
### 实例化一个新的 Django 项目
|
||||
|
||||
现在你的应用程序已经有了一个工作环境,你必须实例化一个新的 Django 项目。与 [Flask][3] 这样微框架不同的是,Django 有专门的命令来创建(注意第一条命令后的 `.` 字符)。
|
||||
|
||||
```
|
||||
$ django-admin startproject tutorial .
|
||||
$ cd tutorial
|
||||
$ django-admin startapp quickstart
|
||||
```
|
||||
|
||||
Django 使用数据库来管理后端,所以你应该在开始开发之前同步数据库,数据库可以通过 `manage.py` 脚本管理,它是在你运行 `django-admin` 命令时创建的。因为你现在在 `tutorial` 目录,所以使用 `../` 符号来运行脚本,它位于上一层目录:
|
||||
|
||||
```
|
||||
$ python3 ../manage.py makemigrations
|
||||
No changes detected
|
||||
$ python4 ../manage.py migrate
|
||||
Operations to perform:
|
||||
Apply all migrations: admin, auth, contenttypes, sessions
|
||||
Running migrations:
|
||||
Applying contenttypes.0001_initial... OK
|
||||
Applying auth.0001_initial... OK
|
||||
Applying admin.0001_initial... OK
|
||||
Applying admin.0002_logentry_remove_auto_add... OK
|
||||
Applying admin.0003_logentry_add_action_flag_choices... OK
|
||||
Applying contenttypes.0002_remove_content_type_name... OK
|
||||
Applying auth.0002_alter_permission_name_max_length... OK
|
||||
Applying auth.0003_alter_user_email_max_length... OK
|
||||
Applying auth.0004_alter_user_username_opts... OK
|
||||
Applying auth.0005_alter_user_last_login_null... OK
|
||||
Applying auth.0006_require_contenttypes_0002... OK
|
||||
Applying auth.0007_alter_validators_add_error_messages... OK
|
||||
Applying auth.0008_alter_user_username_max_length... OK
|
||||
Applying auth.0009_alter_user_last_name_max_length... OK
|
||||
Applying auth.0010_alter_group_name_max_length... OK
|
||||
Applying auth.0011_update_proxy_permissions... OK
|
||||
Applying sessions.0001_initial... OK
|
||||
```
|
||||
|
||||
### 在 Django 中创建用户
|
||||
|
||||
创建一个名为 `admin`,示例密码为 `password123` 的初始用户:
|
||||
|
||||
```
|
||||
$ python3 ../manage.py createsuperuser \
|
||||
--email admin@example.com \
|
||||
--username admin
|
||||
```
|
||||
|
||||
在提示时创建密码。
|
||||
|
||||
### 在 Django 中实现序列化和视图
|
||||
|
||||
为了使 Django 能够将信息传递给 HTTP GET 请求,必须将信息对象转化为有效的响应数据。Django 为此实现了“序列化类” `serializers`。
|
||||
|
||||
在你的项目中,创建一个名为 `quickstart/serializers.py` 的新模块,使用它来定义一些序列化器,模块将用于数据展示:
|
||||
|
||||
```
|
||||
from django.contrib.auth.models import User, Group
|
||||
from rest_framework import serializers
|
||||
|
||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['url', 'username', 'email', 'groups']
|
||||
|
||||
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = Group
|
||||
fields = ['url', 'name']
|
||||
```
|
||||
|
||||
Django 中的[视图][5]是一个接受 Web 请求并返回 Web 响应的函数。响应可以是 HTML、HTTP 重定向、HTTP 错误、JSON 或 XML 文档、图像或 TAR 文件,或者可以是从 Internet 获得的任何其他内容。要创建视图,打开 `quickstart/views.py` 并输入以下代码。该文件已经存在,并且其中包含一些示例文本,保留这些文本并将以下代码添加到文件中:
|
||||
|
||||
```
|
||||
from django.contrib.auth.models import User, Group
|
||||
from rest_framework import viewsets
|
||||
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
|
||||
|
||||
class UserViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API 允许查看或编辑用户
|
||||
"""
|
||||
queryset = User.objects.all().order_by('-date_joined')
|
||||
serializer_class = UserSerializer
|
||||
|
||||
class GroupViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API 允许查看或编辑组
|
||||
"""
|
||||
queryset = Group.objects.all()
|
||||
serializer_class = GroupSerializer
|
||||
```
|
||||
|
||||
### 使用 Django 生成 URL
|
||||
|
||||
现在,你可以生成 URL 以便人们可以访问你刚起步的 API。在文本编辑器中打开 `urls.py` 并将默认示例代码替换为以下代码:
|
||||
|
||||
```
|
||||
from django.urls import include, path
|
||||
from rest_framework import routers
|
||||
from tutorial.quickstart import views
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'users', views.UserViewSet)
|
||||
router.register(r'groups', views.GroupViewSet)
|
||||
|
||||
# 使用自动路由 URL
|
||||
# 还有登录 URL
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
|
||||
]
|
||||
```
|
||||
|
||||
### 调整你的 Django 项目设置
|
||||
|
||||
这个示例项目的设置模块存储在 `tutorial/settings.py` 中,因此在文本编辑器中将其打开,然后在 `INSTALLED_APPS` 列表的末尾添加 `rest_framework`:
|
||||
|
||||
```
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
'rest_framework',
|
||||
]
|
||||
```
|
||||
|
||||
### 测试 Django API
|
||||
|
||||
现在,你可以测试构建的 API。首先,从命令行启动内置服务器:
|
||||
|
||||
```
|
||||
$ python3 manage.py runserver
|
||||
```
|
||||
|
||||
你可以通过使用 `curl` 导航至 URL `http://localhost:8000/users` 来访问 API:
|
||||
|
||||
```
|
||||
$ curl --get http://localhost:8000/users/?format=json
|
||||
[{"url":"http://localhost:8000/users/1/?format=json","username":"admin","email":"admin@example.com","groups":[]}]
|
||||
```
|
||||
|
||||
使用 Firefox 或你选择的[开源浏览器][6]:
|
||||
|
||||
![一个简单的 Django API][7]
|
||||
|
||||
有关使用 Django 和 Python 的 RESTful API 的更多深入知识,参考出色的 [Django 文档][8]。
|
||||
|
||||
### 为什么要使用 Djago?
|
||||
|
||||
Django 的主要优点:
|
||||
|
||||
1. Django 社区的规模正在不断扩大,因此即使你做一个复杂项目,也会有大量的指导资源。
|
||||
2. 默认包含模板、路由、表单、身份验证和管理工具等功能,你不必寻找外部工具,也不必担心第三方工具会引入兼容性问题。
|
||||
3. 用户、循环和条件的简单结构使你可以专注于编写代码。
|
||||
4. 这是一个成熟且经过优化的框架,它非常快速且可靠。
|
||||
|
||||
Django 的主要缺点:
|
||||
|
||||
1. Django 很复杂!从开发人员视角的角度来看,它可能比简单的框架更难学。
|
||||
2. Django 有一个很大的生态系统。一旦你熟悉它,这会很棒,但是当你深入学习时,它可能会令人感到无所适从。
|
||||
|
||||
对你的应用程序或 API 来说,Django 是绝佳选择。下载并熟悉它,开始开发一个迷人的项目!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/python-web-api-django
|
||||
|
||||
作者:[Rachel Waston][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/rachelwaston
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python-programming-code-keyboard.png?itok=fxiSpmnd (Hands on a keyboard with a Python book )
|
||||
[2]: https://www.djangoproject.com/
|
||||
[3]: https://opensource.com/article/19/11/python-web-api-flask
|
||||
[4]: mailto:admin@example.com
|
||||
[5]: https://docs.djangoproject.com/en/2.2/topics/http/views/
|
||||
[6]: https://opensource.com/article/19/7/open-source-browsers
|
||||
[7]: https://opensource.com/sites/default/files/uploads/django-api.png (A simple Django API)
|
||||
[8]: https://docs.djangoproject.com/en/2.2
|
177
published/20191130 7 maker gifts for kids and teens.md
Normal file
177
published/20191130 7 maker gifts for kids and teens.md
Normal file
@ -0,0 +1,177 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11762-1.html)
|
||||
[#]: subject: (7 maker gifts for kids and teens)
|
||||
[#]: via: (https://opensource.com/article/19/11/maker-gifts-kids)
|
||||
[#]: author: (Jess Weichler https://opensource.com/users/cyanide-cupcake)
|
||||
|
||||
给儿童和青少年的 7 件创客礼物
|
||||
======
|
||||
|
||||
> 这份礼物指南使你轻松完成节日礼物的采购,它们可给婴儿、儿童、青少年及年龄更大的人们带来创造和创新能力。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/08/140516t4ewey9ryu24tpz5.jpg)
|
||||
|
||||
还在纠结这个假期给年轻人买什么礼物?这是我精选的开源礼物,这些礼物将激发未来的创意和灵感。
|
||||
|
||||
### 蜂鸟机器人套件
|
||||
|
||||
![Hummingbird Robotics Kit][2]
|
||||
|
||||
**年龄:**8 岁 - 成人
|
||||
|
||||
**这是什么:**[蜂鸟机器人套件][3]是一套完整的机器人套件,带有微控制器、电机、LED 和传感器。机器人的大脑具有特殊的端口,小手可以轻松地将其连接到机器人的组件上。蜂鸟套件并没有身体,而是鼓励用户自己创建一个。
|
||||
|
||||
**为什么我喜欢它:**蜂鸟可以使用多种编程语言 —— 从可视化编程(BirdBlox、MakeCode、Snap)到代码编程(Python 和 Java)—— 可以随着用户编码技能的提高而可扩展。所有组件均与你在电子商店中找到的组件完全相同,没有像其他机器人套件那样被塑料所遮盖。这使机器人的内部工作不再神秘,并在你需要时易于采购更多零件。
|
||||
|
||||
由于没有固定组装项目,因此蜂鸟是发挥创造力的完美机器人。
|
||||
|
||||
蜂鸟具有开源的软件和固件。它适用于 Linux、Windows、Mac、Chromebook、Android 和 iOS。
|
||||
|
||||
**费用:**起价为 99 美元。
|
||||
|
||||
### Makey Makey 经典版
|
||||
|
||||
![Makey Makey Classic][4]
|
||||
|
||||
**年龄:** 6岁 - 成人
|
||||
|
||||
**这是什么:** [Makey Makey 经典版][5]可将任何导电物体(从棉花糖到你的朋友)变成计算机钥匙。
|
||||
|
||||
你可以使用鳄鱼夹将 Makey Makey 连接到你选择的导电物体上。然后,通过同时触摸两个导电物体来闭合接地和任何触发键之间的电路。Makey Makey 是一种安全的方法,可以安全地在家中探索电力,同时创造与计算机进行交互的有趣方式。
|
||||
|
||||
**为什么我喜欢它:** Makey Makey 可以与 Scratch 开发的视频游戏搭配使用,以创建独特的控制器,使用户进一步沉浸在游戏中。从用卫生纸卷和铝箔制成的工具到互动艺术和故事,可能性是无限的。它可以在具有 USB 端口的 Linux、Windows 和 Mac 计算机上使用。
|
||||
|
||||
**费用:** 49.95 美金
|
||||
|
||||
### Arduino Uno
|
||||
|
||||
![Arduino Uno][6]
|
||||
|
||||
**年龄:** 10 岁 - 成人
|
||||
|
||||
**这是什么:** Arduino 是随同电子套件购买的微控制器,也可以单独购买,它们具有多种版本,而我最喜欢 [Arduino Uno][7]。你可以根据需要从任何电子商店购买其他组件,例如 LED、电机和传感器。
|
||||
|
||||
**为什么我喜欢它:** Arduino Uno 的文档很完善,因此创客们很容易在线上找到教程。Arduino 可以实现从简单到复杂的各种电子项目。Arduino 具有开源的固件和硬件。它适用于 Linux、Mac 和 Windows。
|
||||
|
||||
**费用:** 主板的起价为 22.00 美元。总成本取决于项目和技能水平。
|
||||
|
||||
### DIY 创客套件
|
||||
|
||||
![A maker kit assembled in a quick trip to the hardware store][8]
|
||||
|
||||
**年龄**:8 岁 - 成人
|
||||
|
||||
**这是什么:**当今许多创客、发明家和程序员都是从鼓捣碰巧出现在身边东西开始的。你可以快速前往最近的电子产品商店,为家里的年轻人创建一套出色的创客工具包。这是我的创客工具包中的内容:
|
||||
|
||||
* 护目镜
|
||||
* 锤子
|
||||
* 钉子和螺丝
|
||||
* 碎木
|
||||
* 螺丝起子
|
||||
* 电线
|
||||
* LED
|
||||
* 压电蜂鸣器
|
||||
* 马达
|
||||
* 带引线的 AA 电池组
|
||||
* 剪线钳
|
||||
* 纸板
|
||||
* 美纹纸胶带
|
||||
* 废布
|
||||
* 纽扣
|
||||
* 线程
|
||||
* 针
|
||||
* 拉链
|
||||
* 钩子
|
||||
* 一个很酷的工具盒,用来存放所有东西
|
||||
|
||||
**我为什么喜欢它:**还记得小时候,你把父母带回家的空纸箱变成了宇宙飞船、房屋或超级计算机吗?这就是为大孩子们准备的 DIY 创客工具包。
|
||||
|
||||
原始的组件使孩子们可以尝试并运用他们的想象力。DIY 创客工具包可以完全针对接收者定制。可以放入一些接受这份礼品的人可能从未想到过用之发挥创意的某些组件,例如为下水道提供一些 LED 或木工结构。
|
||||
|
||||
**费用:**不等
|
||||
|
||||
### 启发式游戏篮
|
||||
|
||||
![Heuristic play kit][9]
|
||||
|
||||
**年龄:** 8 个月至 5 岁
|
||||
|
||||
**这是什么:**启发式游戏篮充满了由天然、无毒材料制成的有趣物品,可供婴幼儿使用其五种感官进行探索。这是一种开放式、自娱自乐的游戏。其想法是,成年人将监督(但不指导)儿童使用篮子及其物品半小时,然后将篮子拿走,等下一次再玩。
|
||||
|
||||
创建带有常见家用物品的可爱游戏篮很容易。尝试包括质地、声音、气味、形状和重量各不相同的物品。这里有一些想法可以帮助您入门。
|
||||
|
||||
* 漏勺或脊状柳条篮可容纳所有物品
|
||||
* 木勺子
|
||||
* 金属打蛋器和汤匙
|
||||
* 板刷
|
||||
* 海绵
|
||||
* 小型鸡蛋纸箱
|
||||
* 纸板管
|
||||
* 小擀面杖
|
||||
* 带纹理的毛巾
|
||||
* 岩石
|
||||
* 手铃
|
||||
* 钩针桌巾
|
||||
* 带盖的小铁罐
|
||||
|
||||
游戏篮中不应包括任何容易破碎的东西或足够小到可以装入纸巾卷的东西,因为它们有窒息危险,应将所有物品彻底清洁后再交给孩子。
|
||||
|
||||
**我为什么喜欢它:**游戏篮非常适合感官发育,并可以帮助幼儿提出问题和探索周围的世界。这是培养创客思维方式的重要组成部分!
|
||||
|
||||
很容易获得适合这个游戏篮的物品。你可能已经在家中或附近的二手商店里找到了很多有趣的物品。幼儿使用游戏篮的方式与婴儿不同。随着孩子们开始模仿成人生活并通过他们的游戏讲故事,这些物品将随孩子一起成长。
|
||||
|
||||
**费用:**不等
|
||||
|
||||
### 《Hello Ruby》
|
||||
|
||||
![Hello Ruby book cover][10]
|
||||
|
||||
**年龄**:5-8 岁
|
||||
|
||||
**这是什么:** 《[Hello Ruby][11]:编码历险记》是 Linda Liukas 的插图书,通过有趣的故事讲述了一个遇到各种问题和朋友(每个都用一个码代表)的女孩,向孩子们介绍了编程概念。Liukas 还有其他副标题为《互联网探险》和《计算机内的旅程》的《Hello Ruby》系列书籍,而《编码历险记》已以 20 多种语言出版。
|
||||
|
||||
**为什么我喜欢它:**作者在书中附带了许多免费、有趣和无障碍的活动,可以从 Hello Ruby 网站下载和打印这些活动。这些活动教授编码概念、还涉及艺术表达、沟通、甚至时间安排。
|
||||
|
||||
**费用:**精装书的标价为 17.99 美元,但你可以通过本地或在线书店以较低的价格买到这本书。
|
||||
|
||||
### 《编程少女:学会编程和改变世界》
|
||||
|
||||
![Girls Who Code book cover][12]
|
||||
|
||||
**年龄**:10 岁 - 成人
|
||||
|
||||
**内容是什么:**由《编程少女》的创始人 Reshma Saujani 撰写,《[编程少女:学会编程和改变世界][13]》为年轻女孩(以及男孩)提供了科技领域的实用信息。它涵盖了广泛的主题,包括编程语言、用例、术语和词汇、职业选择以及技术行业人士的个人简介和访谈。
|
||||
|
||||
**为什么我喜欢它:**本书以讲述了大多数面向成年人的网站都没有的技术故事。这些技术涉及许多学科,对于年轻人来说,重要的是要了解他们可以使用它来解决现实世界中的问题并有所作为。
|
||||
|
||||
**成本:**精装书的标价为 17.99 美元,平装书的标价为 10.99 美元,但你可以通过本地或在线书店以更低的价格找到。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/11/maker-gifts-kids
|
||||
|
||||
作者:[Jess Weichler][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/cyanide-cupcake
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_gift_giveaway_box_520x292.png?itok=w1YQhNH1 (Gift box opens with colors coming out)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/hummingbird.png (Hummingbird Robotics Kit)
|
||||
[3]: https://www.birdbraintechnologies.com/hummingbirdbit/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/makeymakey2.jpg (Makey Makey Classic)
|
||||
[5]: https://makeymakey.com/
|
||||
[6]: https://opensource.com/sites/default/files/uploads/arduinouno.jpg (Arduino Uno)
|
||||
[7]: https://www.arduino.cc/
|
||||
[8]: https://opensource.com/sites/default/files/makerbox-makerkit.jpg (A maker kit assembled in a quick trip to the hardware store)
|
||||
[9]: https://opensource.com/sites/default/files/makerbox-sensorykit.jpg (Heuristic play kit)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/helloruby2.jpg (Hello Ruby book cover)
|
||||
[11]: https://www.helloruby.com/
|
||||
[12]: https://opensource.com/sites/default/files/uploads/girlswhocodebook.jpg (Girls Who Code book cover)
|
||||
[13]: https://girlswhocode.com/book/girls-code-learn-code-change-world/
|
@ -1,11 +1,13 @@
|
||||
全球化思考:怎样克服交流中的文化差异
|
||||
======
|
||||
这有一些建议帮助你的全球化开发团队能够更好地理解你们的讨论并能参与其中。
|
||||
|
||||
> 这有一些建议帮助你的全球化开发团队能够更好地理解你们的讨论并能参与其中。
|
||||
|
||||
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/people_remote_teams_world.png?itok=_9DCHEel)
|
||||
|
||||
几周前,我见证了两位同事之间一次有趣的互动,他们分别是 Jason,我们的一位美国员工,和 Raj,一位来自印度的访问工作人员。
|
||||
|
||||
Raj 在印度时,他一般会通过电话参加美国中部时间上午 9 点的每日立会,现在他到美国工作了,就可以和组员们坐在同一间会议室里开会了。Jason 拦下了 Raj,说:“ Raj 你要去哪?你不是一直和我们开电话会议吗?你突然出现在会议室里我还不太适应。” Raj 听了说,“是这样吗?没问题。”就回到自己工位前准备和以前一样参加电话会议了。
|
||||
Raj 在印度时,他一般会通过电话参加美国中部时间上午 9 点的每日立会,现在他到美国工作了,就可以和组员们坐在同一间会议室里开会了。Jason 拦下了 Raj,说:“Raj 你要去哪?你不是一直和我们开电话会议吗?你突然出现在会议室里我还不太适应。” Raj 听了说,“是这样吗?没问题。”就回到自己工位前准备和以前一样参加电话会议了。
|
||||
|
||||
我去找 Raj,问他为什么不去参加每日立会,Raj 说 Jason 让自己给组员们打电话参会,而与此同时,Jason 也在会议室等着 Raj 来参加立会。
|
||||
|
||||
@ -19,7 +21,7 @@ Jason 明显是在开玩笑,但 Raj 把它当真了。这就是在两人互相
|
||||
|
||||
现在是全球化时代,我们的同事很可能不跟我们面对面接触,甚至不在同一座城市,来自不同的国家。越来越多的技术公司拥有全球化的工作场所,和来自世界各地的员工,他们有着不同的背景和经历。这种多样性使得技术公司能够在这个快速发展的科技大环境下拥有更强的竞争力。
|
||||
|
||||
但是这种地域的多样性也会给团队带来挑战。管理和维持团高性能的团队发展对于同地协作的团队来说就有着很大难度,对于有着多样背景成员的全球化团队来说,无疑更加困难。成员之间的交流会发生延迟,误解时有发生,成员之间甚至会互相怀疑,这些都会影响着公司的成功。
|
||||
但是这种地域的多样性也会给团队带来挑战。管理和维持高性能的团队发展对于同地协作的团队来说就有着很大难度,对于有着多样背景成员的全球化团队来说,无疑更加困难。成员之间的交流会发生延迟,误解时有发生,成员之间甚至会互相怀疑,这些都会影响着公司的成功。
|
||||
|
||||
到底是什么因素让全球化交流间发生误解呢?我们可以参照 Erin Meyer 的书《[文化地图][2]》,她在书中将全球文化分为八个类型,其中美国文化被分为低语境文化,与之相对的,日本为高语境文化。
|
||||
|
||||
@ -71,7 +73,7 @@ Jason 明显是在开玩笑,但 Raj 把它当真了。这就是在两人互相
|
||||
|
||||
保持长久关系最好的方法是和你的组员们单独见面。如果你的公司可以报销这些费用,那么努力去和组员们见面吧。和一起工作了很长时间的组员们见面能够使你们的关系更加坚固。我所在的公司就有着周期性交换员工的传统,每隔一段时间,世界各地的员工就会来到美国工作,美国员工再到其他分部工作。
|
||||
|
||||
另一种聚齐组员们的机会的研讨会。研讨会创造的不仅是学习和培训的机会,你还可以挤出一些时间和组员们培养感情。
|
||||
另一种聚齐组员们的机会是研讨会。研讨会创造的不仅是学习和培训的机会,你还可以挤出一些时间和组员们培养感情。
|
||||
|
||||
在如今,全球化经济不断发展,拥有来自不同国家和地区的员工对维持一个公司的竞争力来说越来越重要。即使组员们来自世界各地,团队中会出现一些交流问题,但拥有一支国际化的高绩效团队不是问题。如果你在工作中有什么促进团队交流的小窍门,请在评论中告诉我们吧。
|
||||
|
||||
@ -83,7 +85,7 @@ via: https://opensource.com/article/18/10/think-global-communication-challenges
|
||||
作者:[Avindra Fernando][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Valoniakim](https://github.com/Valoniakim)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,207 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11711-1.html)
|
||||
[#]: subject: (Install Android 8.1 Oreo on Linux To Run Apps & Games)
|
||||
[#]: via: (https://fosspost.org/tutorials/install-android-8-1-oreo-on-linux)
|
||||
[#]: author: (Python Programmer;Open Source Software Enthusiast. Worked On Developing A Lot Of Free Software. The Founder Of Foss Post;Foss Project. Computer Science Major. )
|
||||
|
||||
在 Linux 上安装安卓 8.1 Oreo 来运行应用程序和游戏
|
||||
======
|
||||
|
||||
![](https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/android-8.1-oreo-x86-on-linux.png?resize=1237%2C527&ssl=1)
|
||||
|
||||
[android x86][1] 是一个自由而开源的项目,将谷歌制作的安卓系统从 ARM 架构移植到了 x86 架构,可以让用户在他们的桌面电脑上运行安卓系统来享受所有的安卓功能和应用程序及游戏。
|
||||
|
||||
在前一段时间,android x86 项目完成了安卓 8.1 Oreo 系统的 x86 架构移植。在这篇文章中,我们将解释如何在你的 Linux 系统上安装它,以便你能够随时使用你的安卓 用程序和游戏。
|
||||
|
||||
### 在 Linux 上安装安卓 x86 8.1 Oreo
|
||||
|
||||
#### 准备环境
|
||||
|
||||
首先,让我们下载 android x86 8.1 Oreo 系统镜像。你可以从[这个页面][2]下载它,只需单击 “android-x86_64-8.1-r1.iso” 文件下的 “View” 按钮。
|
||||
|
||||
我们将在我们的 Linux 系统上使用 QEMU 来运行 android x86。QEMU 是一个非常好的模拟器软件,它也是自由而开源的,并且在所有主要的 Linux 发行版存储库中都是可用的。
|
||||
|
||||
在 Ubuntu/Linux Mint/Debian 上安装 QEMU:
|
||||
|
||||
```
|
||||
sudo apt-get install qemu qemu-kvm libvirt-bin
|
||||
```
|
||||
|
||||
在 Fedora 上安装 QEMU:
|
||||
|
||||
```
|
||||
sudo dnf install qemu qemu-kvm
|
||||
```
|
||||
|
||||
对于其它发行版,只需要搜索 “qemu” 和 “qemu-kvm” 软件包,并安装它们。
|
||||
|
||||
在你安装 QEMU 后,我们将需要运行下面的命令来创建 `android.img` 文件,它就像某种分配给安卓系统的磁盘空间。所有安卓文件和系统都将位于该镜像文件中:
|
||||
|
||||
```
|
||||
qemu-img create -f qcow2 android.img 15G
|
||||
```
|
||||
|
||||
我们在这里的意思是,我们想为该安卓系统分配一个最大 15GB 的磁盘空间,但是,你可以更改它到你想要的任意大小(确保它至少大于 5GB)。
|
||||
|
||||
现在,首次启动运行该安卓系统,运行:
|
||||
|
||||
```
|
||||
sudo qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda android.img -cdrom /home/mhsabbagh/android-x86_64-8.1-r1.iso
|
||||
```
|
||||
|
||||
将 `/home/mhsabbagh/android-x86_64-8.1-r1.iso` 替换为你从 android x86 网站下载的文件的路径。关于我们在这里正在使用的其它选项的解释,你可以参考[这篇文章][3]。
|
||||
|
||||
在你运行上面的命令后,该安卓系统将启动:
|
||||
|
||||
![][4]
|
||||
|
||||
#### 安装系统
|
||||
|
||||
从这个窗口中,选择 “Advanced options”, 它将引导到下面的菜单,你应如下在其中选择 “Auto_installation” :
|
||||
|
||||
![][5]
|
||||
|
||||
在这以后,安装器将告知你是否想要继续,选择 “Yes”:
|
||||
|
||||
![][6]
|
||||
|
||||
接下来,安装器将无需你的指示而继续进行:
|
||||
|
||||
![][7]
|
||||
|
||||
最后,你将收到这个信息,它表示你已经成功安装安卓 8.1 :
|
||||
|
||||
![][8]
|
||||
|
||||
现在,关闭 QEMU 窗口即可。
|
||||
|
||||
#### 启动和使用 安卓 8.1 Oreo
|
||||
|
||||
现在,安卓系统已经完全安装在你的 `android.img` 文件中,你应该使用下面的 QEMU 命令来启动它,而不是前面的命令:
|
||||
|
||||
```
|
||||
sudo qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda android.img
|
||||
```
|
||||
|
||||
注意,我们所做的只是移除 `-cdrom` 选项及其参数。这是告诉 QEMU,我们不再想从我们下载的 ISO 文件启动,相反,从这个安装的安卓系统启动。
|
||||
|
||||
你现在能够看到安卓的启动菜单:
|
||||
|
||||
![][9]
|
||||
|
||||
然后,你将进入第一个准备向导,选择你的语言并继续:
|
||||
|
||||
![][10]
|
||||
|
||||
从这里,选择 “Set up as new” 选项:
|
||||
|
||||
![][11]
|
||||
|
||||
然后,安卓将询问你是否想登录到你当前的谷歌账号。这步骤是可选的,但是这很重要,以便你随后可以使用谷歌 Play 商店:
|
||||
|
||||
![][12]
|
||||
|
||||
然后,你将需要接受条款:
|
||||
|
||||
![][13]
|
||||
|
||||
现在,你可以选择你当前的时区:
|
||||
|
||||
![][14]
|
||||
|
||||
系统将询问你是否想启动一些数据收集功能。如果我是你的话,我将简单地全部关闭它们,像这样:
|
||||
|
||||
![][15]
|
||||
|
||||
最后,你将有两种启动类型可供选择,我建议你选择 Launcher3 选项,并使其成为默认项:
|
||||
|
||||
![][16]
|
||||
|
||||
然后,你将看到完整工作的安卓系统主屏幕:
|
||||
|
||||
![][17]
|
||||
|
||||
从现在起,你可以做你想做的任何事情;你可以使用内置的安卓应用程序,或者你可以浏览你的系统设置来根据你的喜好进行调整。你可以更改你的系统的外观和体验,或者你可以像示例一样运行 Chrome :
|
||||
|
||||
![][18]
|
||||
|
||||
你可以开始从谷歌 Play 商店安装一些应用程序程序,像 WhatsApp 和其它的应用程序,以供你自己使用:
|
||||
|
||||
![][19]
|
||||
|
||||
你现在可以用你的系统做任何你想做的事。恭喜!
|
||||
|
||||
### 以后如何轻松地运行安卓 8.1 Oreo
|
||||
|
||||
我们不想总是不得不打开终端窗口,并写那些长长的 QEMU 命令来运行安卓系统,相反,我们想在我们需要时一次单击就运行它。
|
||||
|
||||
为此,我们将使用下面的命令在 `/usr/share/applications` 下创建一个名为 `android.desktop` 的新文件:
|
||||
|
||||
```
|
||||
sudo nano /usr/share/applications/android.desktop
|
||||
```
|
||||
|
||||
并在其中粘贴下面的内容(右键单击然后粘贴):
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=Android 8.1
|
||||
Comment=Run Android 8.1 Oreo on Linux using QEMU
|
||||
Icon=phone
|
||||
Exec=bash -c 'pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY qemu-system-x86_64 -m 2048 -boot d -enable-kvm -smp 3 -net nic -net user -hda /home/mhsabbagh/android.img'
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GTK;
|
||||
```
|
||||
|
||||
再强调一次,你必需使用你系统上的本地镜像路径来替换 `/home/mhsabbagh/android.img` 。然后保存文件(`Ctrl+X`,然后按 `Y`,然后按回车)。
|
||||
|
||||
注意,我们需要使用 `pkexec` 来使用 root 权限运行 QEMU ,因为从较新的版本开始,普通用户不允许通过 libvirt 访问 KVM 技术;这就是为什么它将每次要求你输入 root 密码的原因。
|
||||
|
||||
现在,你将在应用程序菜单中看到安卓图标,你可以在你想使用安卓的任何时间来简单地单击该图标,QEMU 程序将启动:
|
||||
|
||||
![][20]
|
||||
|
||||
### 总结
|
||||
|
||||
我们向你展示如何在你的 Linux 系统上安装和运行安卓 8.1 Oreo 。从现在起,在没有其它一些软件的(像 Blutsticks 和类似的方法)的情况下,你可以更容易地完成基于安卓的任务。在这里,你有一个完整工作和功能的安卓系统,你可以随心所欲地操作它,如果一些东西出错,你可以简单地干掉该镜像文件,然后随时再一次重新运行安装程序。
|
||||
|
||||
你之前尝试过 android x86 吗?你的体验如何?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fosspost.org/tutorials/install-android-8-1-oreo-on-linux
|
||||
|
||||
作者:[M.Hanny Sabbagh][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://fosspost.org/author/mhsabbagh
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://www.android-x86.org/
|
||||
[2]: http://www.android-x86.org/download
|
||||
[3]: https://fosspost.org/tutorials/use-qemu-test-operating-systems-distributions
|
||||
[4]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-16.png?resize=694%2C548&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 40 android 8.1 oreo on linux)
|
||||
[5]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-15.png?resize=673%2C537&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 42 android 8.1 oreo on linux)
|
||||
[6]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-14.png?resize=769%2C469&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 44 android 8.1 oreo on linux)
|
||||
[7]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-13.png?resize=767%2C466&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 46 android 8.1 oreo on linux)
|
||||
[8]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-12.png?resize=750%2C460&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 48 android 8.1 oreo on linux)
|
||||
[9]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-11.png?resize=754%2C456&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 50 android 8.1 oreo on linux)
|
||||
[10]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-10.png?resize=850%2C559&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 52 android 8.1 oreo on linux)
|
||||
[11]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-09.png?resize=850%2C569&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 54 android 8.1 oreo on linux)
|
||||
[12]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-08.png?resize=850%2C562&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 56 android 8.1 oreo on linux)
|
||||
[13]: https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-07-1.png?resize=850%2C561&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 58 android 8.1 oreo on linux)
|
||||
[14]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-06.png?resize=850%2C569&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 60 android 8.1 oreo on linux)
|
||||
[15]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-05.png?resize=850%2C559&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 62 android 8.1 oreo on linux)
|
||||
[16]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-04.png?resize=850%2C553&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 64 android 8.1 oreo on linux)
|
||||
[17]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-03.png?resize=850%2C571&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 66 android 8.1 oreo on linux)
|
||||
[18]: https://i1.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-02.png?resize=850%2C555&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 68 android 8.1 oreo on linux)
|
||||
[19]: https://i2.wp.com/fosspost.org/wp-content/uploads/2019/02/Android-8.1-Oreo-on-Linux-01.png?resize=850%2C557&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 70 android 8.1 oreo on linux)
|
||||
[20]: https://i0.wp.com/fosspost.org/wp-content/uploads/2019/02/Screenshot-at-2019-02-17-1539.png?resize=850%2C557&ssl=1 (Install Android 8.1 Oreo on Linux To Run Apps & Games 72 android 8.1 oreo on linux)
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11708-1.html)
|
||||
[#]: subject: (Netboot a Fedora Live CD)
|
||||
[#]: via: (https://fedoramagazine.org/netboot-a-fedora-live-cd/)
|
||||
[#]: author: (Gregory Bartholomew https://fedoramagazine.org/author/glb/)
|
||||
@ -12,40 +12,38 @@
|
||||
|
||||
![](https://fedoramagazine.org/wp-content/uploads/2019/02/netboot-livecd-816x345.jpg)
|
||||
|
||||
[Live CD][1] 对于很多任务是很有用的,例如:
|
||||
[Live CD][1] 对于很多任务是很有用的,例如:
|
||||
|
||||
* 将操作系统安装到一个硬盘驱动器
|
||||
* 修复一个启动加载程序或执行其它救援模式操作
|
||||
* 为网络浏览提供一个相适应的最小环境
|
||||
* …以及[更多的东西][2]。
|
||||
* 将操作系统安装到一个硬盘驱动器
|
||||
* 修复一个启动加载程序或执行其它救援模式操作
|
||||
* 为 Web 浏览提供一个相适应的最小环境
|
||||
* …以及[更多的东西][2]。
|
||||
|
||||
|
||||
|
||||
因为使用 DVD 和 USB 驱动器来存储你的 Live CD 镜像是一个替代方案,你可以上传它们到一个不太可能丢失或损坏的 [iSCSI][3] 服务器中。这个指南向你展示如何加载你的 Live CD 镜像到一个 ISCSI 服务器上,并使用 [iPXE][4] 启动加载程序来访问它们。
|
||||
作为使用 DVD 和 USB 驱动器来存储你的 Live CD 镜像是一个替代方案,你可以上传它们到一个不太可能丢失或损坏的 [iSCSI][3] 服务器中。这个指南向你展示如何加载你的 Live CD 镜像到一个 ISCSI 服务器上,并使用 [iPXE][4] 启动加载程序来访问它们。
|
||||
|
||||
### 下载一个 Live CD 镜像
|
||||
|
||||
```
|
||||
$ MY_RLSE=27
|
||||
$ MY_LIVE=$(wget -q -O - https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/$MY_RLSE/Workstation/x86_64/iso | perl -ne '/(Fedora[^ ]*?-Live-[^ ]*?\.iso)(?{print $^N})/;')
|
||||
$ MY_NAME=fc$MY_RLSE
|
||||
$ MY_NAME=fc$MY_RLSE
|
||||
$ wget -O $MY_NAME.iso https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/$MY_RLSE/Workstation/x86_64/iso/$MY_LIVE
|
||||
```
|
||||
|
||||
上面的命令下载 Fedora-Workstation-Live-x86_64-27-1.6.iso Fedora Live 镜像,并保存为 fc27.iso 。更改 MY_RLSE 的值来下载其它档案版本。或者,你可以浏览 <https://getfedora.org/> 来下载最新的 Fedora live 镜像。在21之前的版本使用不同的命名约定,必需[在这里手动下载][5]。如果你手动下载一个 Live CD 镜像,设置 MY_NAME 变量为不带有扩展名的文件的基本名称。用此方法,下面部分中命令将引用正确的文件。
|
||||
上面的命令下载 `Fedora-Workstation-Live-x86_64-27-1.6.iso` Fedora Live 镜像,并保存为 `fc27.iso`。更改 `MY_RLSE` 的值来下载其它档案版本。或者,你可以浏览 <https://getfedora.org/> 来下载最新的 Fedora live 镜像。在 21 之前的版本使用不同的命名约定,必需[在这里手动下载][5]。如果你手动下载一个 Live CD 镜像,设置 `MY_NAME` 变量为不带有扩展名的文件的基本名称。用此方法,下面部分中命令将引用正确的文件。
|
||||
|
||||
### 转换 Live CD 镜像
|
||||
|
||||
使用 livecd-iso-to-disk 工具来转换 ISO 文件为一个磁盘镜像,并添加 netroot 参数到嵌入的内核命令行:
|
||||
使用 `livecd-iso-to-disk` 工具来转换 ISO 文件为一个磁盘镜像,并添加 `netroot` 参数到嵌入的内核命令行:
|
||||
|
||||
```
|
||||
$ sudo dnf install -y livecd-tools
|
||||
$ MY_SIZE=$(du -ms $MY_NAME.iso | cut -f 1)
|
||||
$ dd if=/dev/zero of=$MY_NAME.img bs=1MiB count=0 seek=$(($MY_SIZE+512))
|
||||
$ MY_SRVR=server-01.example.edu
|
||||
$ MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find $MY_NAME.img)
|
||||
$ sudo livecd-iso-to-disk --format --extra-kernel-args netroot=iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME $MY_NAME.iso $MY_LOOP
|
||||
$ dd if=/dev/zero of=$MY_NAME.img bs=1MiB count=0 seek=$(($MY_SIZE+512))
|
||||
$ MY_SRVR=server-01.example.edu
|
||||
$ MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find $MY_NAME.img)
|
||||
$ sudo livecd-iso-to-disk --format --extra-kernel-args netroot=iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME $MY_NAME.iso $MY_LOOP
|
||||
$ sudo losetup -d $MY_LOOP
|
||||
```
|
||||
|
||||
@ -53,21 +51,21 @@ $ sudo losetup -d $MY_LOOP
|
||||
|
||||
在你的 ISCSI 服务器上创建一个目录来存储你的 live 镜像,随后上传你修改的镜像到其中。
|
||||
|
||||
**对于 21 及更高发布版本:**
|
||||
对于 21 及更高发布版本:
|
||||
|
||||
```
|
||||
$ MY_FLDR=/images
|
||||
$ MY_FLDR=/images
|
||||
$ scp $MY_NAME.img $MY_SRVR:$MY_FLDR/
|
||||
```
|
||||
|
||||
**对于 21 以前发布版本:**
|
||||
对于 21 以前发布版本:
|
||||
|
||||
```
|
||||
$ MY_FLDR=/images
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find --partscan $MY_NAME.img)
|
||||
$ sudo tune2fs -O ^has_journal ${MY_LOOP}p1
|
||||
$ sudo e2fsck ${MY_LOOP}p1
|
||||
$ sudo dd status=none if=${MY_LOOP}p1 | ssh $MY_SRVR "dd of=$MY_FLDR/$MY_NAME.img"
|
||||
$ MY_FLDR=/images
|
||||
$ MY_LOOP=$(sudo losetup --show --nooverlap --find --partscan $MY_NAME.img)
|
||||
$ sudo tune2fs -O ^has_journal ${MY_LOOP}p1
|
||||
$ sudo e2fsck ${MY_LOOP}p1
|
||||
$ sudo dd status=none if=${MY_LOOP}p1 | ssh $MY_SRVR "dd of=$MY_FLDR/$MY_NAME.img"
|
||||
$ sudo losetup -d $MY_LOOP
|
||||
```
|
||||
|
||||
@ -76,89 +74,86 @@ $ sudo losetup -d $MY_LOOP
|
||||
在你的 iSCSI 服务器上运行下面的命令:
|
||||
|
||||
```
|
||||
$ sudo -i
|
||||
# MY_NAME=fc27
|
||||
# MY_FLDR=/images
|
||||
# MY_SRVR=`hostname`
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# cat << END > /etc/tgt/conf.d/$MY_NAME.conf
|
||||
$ sudo -i
|
||||
# MY_NAME=fc27
|
||||
# MY_FLDR=/images
|
||||
# MY_SRVR=`hostname`
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# cat << END > /etc/tgt/conf.d/$MY_NAME.conf
|
||||
<target iqn.$MY_RVRS:$MY_NAME>
|
||||
backing-store $MY_FLDR/$MY_NAME.img
|
||||
readonly 1
|
||||
allow-in-use yes
|
||||
</target>
|
||||
END
|
||||
backing-store $MY_FLDR/$MY_NAME.img
|
||||
readonly 1
|
||||
allow-in-use yes
|
||||
</target>
|
||||
END
|
||||
# tgt-admin --update ALL
|
||||
```
|
||||
|
||||
### 创建一个可启动 USB 驱动器
|
||||
|
||||
[iPXE][4] 启动加载程序有一个 [sanboot][6] 命令,你可以使用它来连接,并启动你 ISCSI 服务器上运行的live 镜像。它可以用很多不同的[格式][7]编译。最好的工作格式依赖于你正在运行的硬件。例如,下面的说明向你展示如何在一个 USB 驱动器上从 [syslinux][9] 中 [链式加载][8] iPXE。
|
||||
[iPXE][4] 启动加载程序有一个 [sanboot][6] 命令,你可以使用它来连接并启动托管于你 ISCSI 服务器上运行的 live 镜像。它可以以很多不同的[格式][7]编译。最好的工作格式依赖于你正在运行的硬件。例如,下面的说明向你展示如何在一个 USB 驱动器上从 [syslinux][9] 中 [链式加载][8] iPXE。
|
||||
|
||||
首先,下载 iPXE ,并以它的 lkrn 格式构建。这应该作为一个工作站上的普通用户完成:
|
||||
首先,下载 iPXE,并以它的 lkrn 格式构建。这应该作为一个工作站上的普通用户完成:
|
||||
|
||||
```
|
||||
$ sudo dnf install -y git
|
||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||
$ sudo dnf install -y git
|
||||
$ git clone http://git.ipxe.org/ipxe.git $HOME/ipxe
|
||||
$ sudo dnf groupinstall -y "C Development Tools and Libraries"
|
||||
$ cd $HOME/ipxe/src
|
||||
$ make clean
|
||||
$ make bin/ipxe.lkrn
|
||||
$ cd $HOME/ipxe/src
|
||||
$ make clean
|
||||
$ make bin/ipxe.lkrn
|
||||
$ cp bin/ipxe.lkrn /tmp
|
||||
```
|
||||
|
||||
接下来,准备一个带有一个 MSDOS 分区表和一个 FAT32 文件系统的 USB 驱动器。下面的命令假设你已经连接将要格式化的 USB 驱动器。**注意:你要格式正确的驱动器!**
|
||||
|
||||
```
|
||||
$ sudo -i
|
||||
# dnf install -y parted util-linux dosfstools
|
||||
$ sudo -i
|
||||
# dnf install -y parted util-linux dosfstools
|
||||
# echo; find /dev/disk/by-id ! -regex '.*-part.*' -name 'usb-*' -exec readlink -f {} \; | xargs -i bash -c "parted -s {} unit MiB print | perl -0 -ne '/^Model: ([^(]*).*\n.*?([0-9]*MiB)/i && print \"Found: {} = \$2 \$1\n\"'"; echo; read -e -i "$(find /dev/disk/by-id ! -regex '.*-part.*' -name 'usb-*' -exec readlink -f {} \; -quit)" -p "Drive to format: " MY_USB
|
||||
# umount $MY_USB?
|
||||
# wipefs -a $MY_USB
|
||||
# parted -s $MY_USB mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on
|
||||
# umount $MY_USB?
|
||||
# wipefs -a $MY_USB
|
||||
# parted -s $MY_USB mklabel msdos mkpart primary fat32 1MiB 100% set 1 boot on
|
||||
# mkfs -t vfat -F 32 ${MY_USB}1
|
||||
```
|
||||
|
||||
最后,在 USB 驱动器上安装并配置 syslinux ,来链式加载 iPXE :
|
||||
最后,在 USB 驱动器上安装并配置 syslinux ,来链式加载 iPXE:
|
||||
|
||||
```
|
||||
# dnf install -y syslinux-nonlinux
|
||||
# syslinux -i ${MY_USB}1
|
||||
# dd if=/usr/share/syslinux/mbr.bin of=${MY_USB}
|
||||
# MY_MNT=$(mktemp -d)
|
||||
# mount ${MY_USB}1 $MY_MNT
|
||||
# MY_NAME=fc27
|
||||
# MY_SRVR=server-01.example.edu
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# dnf install -y syslinux-nonlinux
|
||||
# syslinux -i ${MY_USB}1
|
||||
# dd if=/usr/share/syslinux/mbr.bin of=${MY_USB}
|
||||
# MY_MNT=$(mktemp -d)
|
||||
# mount ${MY_USB}1 $MY_MNT
|
||||
# MY_NAME=fc27
|
||||
# MY_SRVR=server-01.example.edu
|
||||
# MY_RVRS=$(echo $MY_SRVR | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_SRVR})
|
||||
# cat << END > $MY_MNT/syslinux.cfg
|
||||
ui menu.c32
|
||||
default $MY_NAME
|
||||
timeout 100
|
||||
menu title SYSLINUX
|
||||
label $MY_NAME
|
||||
menu label ${MY_NAME^^}
|
||||
kernel ipxe.lkrn
|
||||
append dhcp && sanboot iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME
|
||||
END
|
||||
# cp /usr/share/syslinux/menu.c32 $MY_MNT
|
||||
# cp /usr/share/syslinux/libutil.c32 $MY_MNT
|
||||
# cp /tmp/ipxe.lkrn $MY_MNT
|
||||
menu label ${MY_NAME^^}
|
||||
kernel ipxe.lkrn
|
||||
append dhcp && sanboot iscsi:$MY_SRVR:::1:iqn.$MY_RVRS:$MY_NAME
|
||||
END
|
||||
# cp /usr/share/syslinux/menu.c32 $MY_MNT
|
||||
# cp /usr/share/syslinux/libutil.c32 $MY_MNT
|
||||
# cp /tmp/ipxe.lkrn $MY_MNT
|
||||
# umount ${MY_USB}1
|
||||
```
|
||||
|
||||
通过简单地编辑 syslinux.cfg 文件,并添加附加的菜单入口,你应该能够使用这同一个 USB 驱动器来网络启动附加的 ISCSI 目标。
|
||||
通过简单地编辑 `syslinux.cfg` 文件,并添加附加的菜单项,你应该能够使用这同一个 USB 驱动器来网络启动附加的 ISCSI 目标。
|
||||
|
||||
这仅是加载 IPXE 的一种方法。你可以直接在你的工作站上安装 syslinux 。再一种选项是编译 iPXE 为一个 EFI 可执行文件,并直接放置它到你的 [ESP][10]中。又一种选项是编译 iPXE 为一个 PXE 加载器,并放置它到你的能够被 DHCP 引用的 TFTP 服务器。最佳的选项依赖于的环境
|
||||
这仅是加载 IPXE 的一种方法。你可以直接在你的工作站上安装 syslinux 。再一种选项是编译 iPXE 为一个 EFI 可执行文件,并直接放置它到你的 [ESP][10] 中。又一种选项是编译 iPXE 为一个 PXE 加载器,并放置它到你的能够被 DHCP 引用的 TFTP 服务器。最佳的选项依赖于的环境
|
||||
|
||||
### 最后说明
|
||||
|
||||
* 如果你以 IPXE 的 EFI 格式编译 IPXE ,你可能想添加 –filename \EFI\BOOT\grubx64.efi 参数到 sanboot 命令。
|
||||
* 能够创建自定义 live 镜像。更多信息参考[创建和使用 live CD][11] 。
|
||||
* 有可能添加 –overlay-size-mb 和 –home-size-mb 参数到 livecd-iso-to-disk 命令来创建永久存储的 live 镜像。然而,如果你有多个并发用户,你将需要设置你的 ISCSI 服务器来管理独立的每个用户可写覆盖。这与 “[如何构建一个网络启动服务器,部分 4][12]” 一文所示类似。
|
||||
* Live 镜像在它们的内核命令行中支持一个 persistenthome 选项(例如, persistenthome=LABEL=HOME)。与经过 CHAP 身份验证的 iSCSI 目标一起使用,对于集权控制主目录,persistenthome 选项为 NFS 提供一个有趣的替代方案。
|
||||
|
||||
|
||||
|
||||
* 如果你以 IPXE 的 EFI 格式编译 IPXE ,你可能想添加 `–filename \EFI\BOOT\grubx64.efi` 参数到 `sanboot` 命令。
|
||||
* 能够创建自定义 live 镜像。更多信息参考[创建和使用 live CD][11]。
|
||||
* 可以添加 `–overlay-size-mb` 和 `–home-size-mb` 参数到 `livecd-iso-to-disk` 命令来创建永久存储的 live 镜像。然而,如果你有多个并发用户,你将需要设置你的 ISCSI 服务器来管理独立的每个用户的可写覆盖。这与 “[如何构建一个网络启动服务器,部分 4][12]” 一文所示类似。
|
||||
* Live 镜像在它们的内核命令行中支持一个 `persistenthome` 选项(例如, `persistenthome=LABEL=HOME`)。与经过 CHAP 身份验证的 iSCSI 目标一起使用,对于中心控制主目录,`persistenthome` 选项为 NFS 提供一个有趣的替代方案。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -167,7 +162,7 @@ via: https://fedoramagazine.org/netboot-a-fedora-live-cd/
|
||||
作者:[Gregory Bartholomew][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[校对者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: (lxbwolf)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11709-1.html)
|
||||
[#]: subject: (How To Set Password Complexity On Linux?)
|
||||
[#]: via: (https://www.2daygeek.com/how-to-set-password-complexity-policy-on-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
@ -12,13 +12,12 @@ Linux 如何设置密码复杂度?
|
||||
|
||||
对于 Linux 系统管理员来说,用户管理是最重要的事之一。这涉及到很多因素,实现强密码策略是用户管理的其中一个方面。移步后面的 URL 查看如何 [在 Linux 上生成一个强密码][1]。它会限制系统未授权的用户的访问。
|
||||
|
||||
所有人都知道 Linux 的默认策略很安全,然而我们还是要做一些微调,这样才更安全。弱密码有安全隐患,因此,请特别注意。移步后面的 URL 查看生成的强密码的 [密码长度和分值][2]。本文将教你在 Linux 中如何实现最安全的策略。
|
||||
所有人都知道 Linux 的默认策略很安全,然而我们还是要做一些微调,这样才更安全。弱密码有安全隐患,因此,请特别注意。移步后面的 URL 查看生成的强密码的[密码长度和分值][2]。本文将教你在 Linux 中如何实现最安全的策略。
|
||||
|
||||
在大多数 Linux 系统中,我们可以用 PAM(pluggable authentication module,译注:可插拔认证模块)来加强密码策略。在下面的路径可以找到这个文件。
|
||||
在大多数 Linux 系统中,我们可以用 PAM(<ruby>可插拔认证模块<rt>pluggable authentication module</rt></ruby>)来加强密码策略。在下面的路径可以找到这个文件。
|
||||
|
||||
在红帽系列的系统中,路径:`/etc/pam.d/system-auth`。
|
||||
|
||||
Debian 系列的系统中,路径:`/etc/pam.d/common-password`。
|
||||
- 在红帽系列的系统中,路径:`/etc/pam.d/system-auth`。
|
||||
- Debian 系列的系统中,路径:`/etc/pam.d/common-password`。
|
||||
|
||||
关于默认的密码过期时间,可以在 `/etc/login.defs` 文件中查看详细信息。
|
||||
|
||||
@ -33,32 +32,30 @@ PASS_MIN_LEN 5
|
||||
PASS_WARN_AGE 7
|
||||
```
|
||||
|
||||
**详细解释:**
|
||||
|
||||
* **`PASS_MAX_DAYS:`**` ` 一个密码可使用的最大天数。
|
||||
* **`PASS_MIN_DAYS:`**` ` 两次密码修改之间最小的间隔天数。
|
||||
* **`PASS_MIN_LEN:`**` ` 密码最小长度。
|
||||
* **`PASS_WARN_AGE:`**` ` 密码过期前给出警告的天数。
|
||||
|
||||
详细解释:
|
||||
|
||||
* `PASS_MAX_DAYS`:一个密码可使用的最大天数。
|
||||
* `PASS_MIN_DAYS`:两次密码修改之间最小的间隔天数。
|
||||
* `PASS_MIN_LEN`:密码最小长度。
|
||||
* `PASS_WARN_AGE`:密码过期前给出警告的天数。
|
||||
|
||||
我们将会展示在 Linux 中如何实现下面的 11 个密码策略。
|
||||
|
||||
* 一个密码可使用的最大天数
|
||||
* 两次密码修改之间最小的间隔天数
|
||||
* 密码过期前给出警告的天数
|
||||
* 密码历史记录/拒绝重复使用密码
|
||||
* 密码最小长度
|
||||
* 最少的大写字母个数
|
||||
* 最少的小写字母个数
|
||||
* 最少的数字个数
|
||||
* 最少的其他字符(符号)个数
|
||||
* 账号锁定 — 重试
|
||||
* 账号解锁时间
|
||||
* 一个密码可使用的最大天数
|
||||
* 两次密码修改之间最小的间隔天数
|
||||
* 密码过期前给出警告的天数
|
||||
* 密码历史记录/拒绝重复使用密码
|
||||
* 密码最小长度
|
||||
* 最少的大写字母个数
|
||||
* 最少的小写字母个数
|
||||
* 最少的数字个数
|
||||
* 最少的其他字符(符号)个数
|
||||
* 账号锁定 — 重试
|
||||
* 账号解锁时间
|
||||
|
||||
### 密码可使用的最大天数是什么?
|
||||
|
||||
这一参数限制一个密码可使用的最大天数。它强制用户在过期前修改他/她的密码。如果他们忘记修改,那么他们会登录不了系统。他们需要联系管理员才能正常登录。这个参数可以在 `/etc/login.defs` 文件中设置。我把这个参数设置为 `90 天`。
|
||||
这一参数限制一个密码可使用的最大天数。它强制用户在过期前修改他/她的密码。如果他们忘记修改,那么他们会登录不了系统。他们需要联系管理员才能正常登录。这个参数可以在 `/etc/login.defs` 文件中设置。我把这个参数设置为 90 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
@ -68,7 +65,7 @@ PASS_MAX_DAYS 90
|
||||
|
||||
### 密码最小天数是什么?
|
||||
|
||||
这个参数限制两次修改之间的最少天数。举例来说,如果这个参数被设置为 15 天,用户今天修改了密码,那么在 15 天之内他都不能修改密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 `15 天`。
|
||||
这个参数限制两次修改之间的最少天数。举例来说,如果这个参数被设置为 15 天,用户今天修改了密码,那么在 15 天之内他都不能修改密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 15 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
@ -78,7 +75,7 @@ PASS_MIN_DAYS 15
|
||||
|
||||
### 密码警告天数是什么?
|
||||
|
||||
这个参数控制密码警告的前置天数,在密码即将过期时会给用户警告提示。在警告天数结束前,用户会收到日常警告提示。这可以提醒用户在密码过期前修改他们的密码,否则我们就需要联系管理员来解锁密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 `10 天`。
|
||||
这个参数控制密码警告的前置天数,在密码即将过期时会给用户警告提示。在警告天数结束前,用户会收到日常警告提示。这可以提醒用户在密码过期前修改他们的密码,否则我们就需要联系管理员来解锁密码。这个参数可以在 `/etc/login.defs` 文件中设置。我设置为 10 天。
|
||||
|
||||
```
|
||||
# vi /etc/login.defs
|
||||
@ -90,7 +87,7 @@ PASS_WARN_AGE 10
|
||||
|
||||
### 密码历史或拒绝重复使用密码是什么?
|
||||
|
||||
这个参数控制密码历史。它记录曾经使用过的密码(禁止使用的曾用密码的个数)。当用户设置新的密码时,它会检查密码历史,如果他们要设置的密码是一个曾经使用过的旧密码,将会发出警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码历史为 `5`。
|
||||
这个参数控制密码历史。它记录曾经使用过的密码(禁止使用的曾用密码的个数)。当用户设置新的密码时,它会检查密码历史,如果他们要设置的密码是一个曾经使用过的旧密码,将会发出警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码历史为 5。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -100,7 +97,7 @@ password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok r
|
||||
|
||||
### 密码最小长度是什么?
|
||||
|
||||
这个参数表示密码的最小长度。当用户设置新密码时,系统会检查这个参数,如果新设的密码长度小于这个参数设置的值,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置最小密码长度为 `12`。
|
||||
这个参数表示密码的最小长度。当用户设置新密码时,系统会检查这个参数,如果新设的密码长度小于这个参数设置的值,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置最小密码长度为 12。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -108,11 +105,11 @@ password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok r
|
||||
password requisite pam_cracklib.so try_first_pass retry=3 minlen=12
|
||||
```
|
||||
|
||||
**try_first_pass retry=3** : 在密码设置交互界面,用户有 3 次机会重设密码。
|
||||
`try_first_pass retry=3`:在密码设置交互界面,用户有 3 次机会重设密码。
|
||||
|
||||
### 设置最少的大写字母个数?
|
||||
|
||||
这个参数表示密码中至少需要的大写字母的个数。这些是密码长度增长参数,可以让密码更长。当用户设置新密码时,系统会检查这个参数,如果密码中没有大写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码(中大写字母)的最小长度为 `1` 个字母。
|
||||
这个参数表示密码中至少需要的大写字母的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有大写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置密码(中的大写字母)的最小长度为 1 个字母。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -122,7 +119,7 @@ password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 ucredit=
|
||||
|
||||
### 设置最少的小写字母个数?
|
||||
|
||||
这个参数表示密码中至少需要的小写字母的个数。这些是密码长度增长参数,可以让密码更长。当用户设置新密码时,系统会检查这个参数,如果密码中没有小写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 `1` 个字母。
|
||||
这个参数表示密码中至少需要的小写字母的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有小写字母,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个字母。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -132,7 +129,7 @@ password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 lcred
|
||||
|
||||
### 设置密码中最少的数字个数?
|
||||
|
||||
这个参数表示密码中至少需要的数字的个数。这些是密码长度增长参数,可以让密码更长。当用户设置新密码时,系统会检查这个参数,如果密码中没有数字,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 `1`。
|
||||
这个参数表示密码中至少需要的数字的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有数字,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个数字。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -142,7 +139,7 @@ password requisite pam_cracklib.so try_first_pass retry=3 minlen=12 dcred
|
||||
|
||||
### 设置密码中最少的其他字符(符号)个数?
|
||||
|
||||
这个参数表示密码中至少需要的特殊符号的个数。这些是密码长度增长参数,可以让密码更长。当用户设置新密码时,系统会检查这个参数,如果密码中没有特殊符号,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 `1` 个字符。
|
||||
这个参数表示密码中至少需要的特殊符号的个数。这些是密码强度参数,可以让密码更健壮。当用户设置新密码时,系统会检查这个参数,如果密码中没有特殊符号,会收到警告提示。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。我设置为 1 个字符。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -163,7 +160,7 @@ account required pam_tally2.so
|
||||
|
||||
### 设定账号解锁时间?
|
||||
|
||||
这个参数表示用户解锁时间。如果一个用户账号在连续认证失败后被锁定了,当过了设定的解锁时间后,就会解锁。设置被锁定中的账号的解锁时间(900 秒 = 15分钟)。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。
|
||||
这个参数表示用户解锁时间。如果一个用户账号在连续认证失败后被锁定了,当过了设定的解锁时间后,才会解锁。设置被锁定中的账号的解锁时间(900 秒 = 15分钟)。这个参数可以在 `/etc/pam.d/system-auth` 文件中设置。
|
||||
|
||||
```
|
||||
# vi /etc/pam.d/system-auth
|
||||
@ -179,7 +176,7 @@ via: https://www.2daygeek.com/how-to-set-password-complexity-policy-on-linux/
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
73
published/201912/20190711 DevOps for introverted people.md
Normal file
73
published/201912/20190711 DevOps for introverted people.md
Normal file
@ -0,0 +1,73 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (XLCYun)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11725-1.html)
|
||||
[#]: subject: (DevOps for introverted people)
|
||||
[#]: via: (https://opensource.com/article/19/7/devops-introverted-people)
|
||||
[#]: author: (Matthew Broberg https://opensource.com/users/mbbroberg)
|
||||
|
||||
内向者的 DevOps
|
||||
======
|
||||
|
||||
> 我们邀请 Opensource.com 的 DevOps 团队,希望他们能够谈一谈作为 DevOps 内向者的休验,同时给 DevOps 外向者一些建议。下面是他们的回答。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/29/103642jmzt6t6mggjjx5yt.jpg)
|
||||
|
||||
我们邀请我们的 [DevOps 团队][2] 谈一谈他们作为一个内向者的体验,并给外向者们一些建议。但是在我们开始了解他们的回答之前,让我们先来定义一下这些词汇。
|
||||
|
||||
### “内向者”是什么意思?
|
||||
|
||||
内向者通常指的是一部分人群,当他们和别人相处的时候,会使他们的能量耗尽,而不是激发他们更多的能量。当我们思考我们是如何恢复能量时,这是一个非常有用的词汇:内向者通常需要更多的独处时间来恢复能量,特别是和一群人在一起很长时间后。关于内向者的一个非常大的误解就是他们一定是“害羞的”,但是科学表明,那不过是另一种不同的性格特征。
|
||||
|
||||
内向性与外向性是通过 [Myers Briggs 类型指标][4] 而为人所知的,现在也常常被称作一个 [光谱][5] 的两端。虽然这个世界看起来好像外向者比内向者要多,但是心理学者则倾向于认为大部分人在光谱上的位置是落在 [中间性格或偏内向性格的][6]。
|
||||
|
||||
现在,我们来看看问答。
|
||||
|
||||
### DevOps 技术主管可以通过哪些方式来让内向者感觉他们是团队的一部分并且愿意分享他们的想法?
|
||||
|
||||
“每个人都会不大一样,所以观察敏锐就很重要了。从 GitLab 过来的一个人告诉我,他们的哲学就是如果他们没有提供任何意见,那么他们就是被排除在外的。如果有人在一个会议上没有提供任何的意见,那就想办法让他们加入进来。**当我知道一个内向者对我们将要讨论的会议论题感兴趣的时候,我会提前请他写一些书面文本。有非常多的会议其实是可以避免的,只要通过把讨论放到 Slack 或者 GitLab 上就行了,内向者会更愿意参与进来**。在站立会议中,每个人都会交代最新的进展,在这个环境下,内向者表现得很好。有时候我们在其实会议上会重复做一些事情,仅仅是为了保证每个人都有时间发言。我同时也会鼓励内向者在工作小组或者社区小组面前发言,以此来锻炼他们的这些技能。”—— 丹·巴克
|
||||
|
||||
“**我觉得别人对我做的最好的事情,就是他们保证了当重大问题来临的时候,我拥有必要的技能去回答它**。彼时,我作为一名非常年轻的入伍空军的一员,我需要给我们部队的高级领导做状态简报的汇报。我必须在任何时候都有一些可用的数据点,以及在实现我们确立的目标的过程中,产生延误以及偏差的背后的原因。那样的经历推动着我从一个‘幕后人员’逐渐变得更加愿意和别人分享自己的观点和想法。”—— 克里斯·肖特
|
||||
|
||||
“**通过文化去领导。为你的同僚一起设计和尝试仪式。**你可以为给你的小组或团队设计一个小的每周仪式,甚至给你的部门或组织设计一个年度的大仪式。它的意义在于去尝试一些事物,并观察你在其中的领导角色。去找到你们文化当中的代沟以及对立。回顾团队的信仰和行为。你能从哪里观察到对立?你们的文化中缺失了什么?从一个小陈述开始‘我从 X 和 Y 之间看到了对立’,或者‘我的团队缺少了 Z’。接着,将代沟与对立转换为问题:写下三个‘我们如何能……(How might we's, HMWs)’。”—— 凯瑟琳·路易斯
|
||||
|
||||
“内向者不是一个不同的群体,他们要么是在分享他们的想法之前想得太多或等得太久的一些人,要么就是一些根本不知道发生了什么的人。我就是第一种,我想太多了,有时候还担心我的意见会被其他人嘲笑,或者没有什么意思,或者想偏了。形成那样的思维方式很难,但它同时也在吞噬着我学习更好事物的机会。有一次,我们团队在讨论一个实现问题。我当时的老大一次又一次地问我,为什么我没有作为团队中更具经验的人参与进来,然后我就(集齐了全宇宙的力量之后)开口说我想说的大家都已经说过了。他说,有时候我可以重复说一次,事情纷繁,如果你能够重复一遍你的想法,即使它已经被讨论过了,也会大有裨益。好吧,虽然它不是一种特别信服的方式,但是我知道了至少有人想听听我怎么说,它给了我一点信心。
|
||||
|
||||
“现在,我所使用的让团队中的人发言的方法是**我经常向内向的人求助,即使我知道解决方法,并且在团队会议和讨论中感谢他们来建立他们的自信心,通过给他们时间让他们一点一点的从他们寡言的本性中走出来,从而跟团队分享很多的知识**。他们在外面的世界中可能仍然会有一点点孤立,但是在团队里面,有些会成为我们可以信赖的人。”—— 阿布希什克·塔姆拉卡尔
|
||||
|
||||
“我给参加会议的内向者的建议是,找一个同样要参加会议的朋友或者同事,这样到时你就会有人可以跟你一起舒服地交谈,在会议开始之前,提前跟其他的与会者(朋友、行业联系人、前同事等等)约着见个面或者吃顿饭,**要注意你的疲劳程度,并且照顾好自己**:如果你需要重新恢复能量,就跳过那些社交或者夜晚的活动,在事后回顾中记录一下自己的感受。”—— 伊丽莎白·约瑟夫
|
||||
|
||||
### 和一个内向者倾向的同事一起工作时,有什么提高生产效率的小建议?
|
||||
|
||||
“在保证质量时,生产效率会越来越具备挑战性。在大多数时候,工作中的一个小憩或者轻松随意的交谈,可能正是我们的创造性活动中需要的一个火花。再说一次,我发现当你的团队中有内向者时, Slack 和 Github 会是一个非常有用的用于交换想法以及和其他人互动的媒介。**我同时也发现,结对编程对于大部分的内向者也非常有用,虽然一对一的交流对于他们来说,并不像交税那么频繁,但是生产质量和效率的提升却是重大的**。但是,当一个内向者在独自工作的时间,团队中的所有人都不应该去打断他们。最好是发个邮件,或者使用没有那么强的侵入性的媒介。”—— 丹·巴克
|
||||
|
||||
“给他们趁手的工具,让他们工作并归档他们的工作。**让他们能够在他们的工作上做到最好**。要足够经常地去检查一下,保证他们没有走偏路,但是要记住,相比外向者而言,这样做是更大的一种让人分心的困扰。”—— 克里斯·肖特
|
||||
|
||||
“**当我低着头的时候,不要打断我。真的,别打断我!**当我沉浸在某件事物中时,这样做会造成我至少需要花费两个小时,才能让我的大脑重新回到之前的状态。感觉很痛苦。真的。你可以发个邮件让我去有白板的地方。然后从客户的角度而不是你的角度——通过画图的方式——分享下有什么问题。要知道,可能同时会有十几个客户问题缠绕在我的脑海中,如果你的问题听起来就是‘这样子做会让我在我的领导面前显得很好’的那一类问题,那么相比我脑袋中已经有的真正的客户问题而言,它不会得到更多的关注的。画个图,给我点时间思考。当我准备分享我的看法的时候,保证有多支马克笔可以使用。准备好接受你对问题的假设有可能完全是错误的。”—— 凯瑟琳·路易斯
|
||||
|
||||
“感谢和鼓励就是解决的方法,感谢可能不是一份工作评估,但是感谢能让人舒服地感受到自己并不仅仅是一个活着的独立实体,**因而每个人都能够感觉到自己是被倾听的,而不是被嘲笑或者低估的**。”—— 阿布希什克·塔姆拉卡尔
|
||||
|
||||
### 结语
|
||||
|
||||
在与内向的 DevOps 爱好者的这次交谈中,我们最大的启迪就是平等:其他人需要被怎样对待,就怎样对待他们,同时你想被怎样对待,就去要求别人怎样对待你。无论你是内向还是外向,我们都需要承认我们并非全以相同的一种方式体验这个世界。我们的同事应当被给予足够的空间以完成他们的工作,通过讨论他们的需求作为了解如何支持他们的开始。我们的差异正是我们的社区如此特别的原因,它让我们的工作对更多的人更加的有用。与别人沟通最有效的方式,就是对于你们两者而言都可行的方式。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/7/devops-introverted-people
|
||||
|
||||
作者:[Matthew Broberg][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[XLCYun](https://github.com/XLCYun)
|
||||
校对:[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/osdc_QandAorange_520x292_0311LL.png?itok=qa3hHSou (Q and A letters)
|
||||
[2]: https://opensource.com/devops-team
|
||||
[3]: https://www.inc.com/melanie-curtin/are-you-shy-or-introverted-science-says-this-is-1-primary-difference.html
|
||||
[4]: https://www.myersbriggs.org/my-mbti-personality-type/mbti-basics/extraversion-or-introversion.htm?bhcp=1
|
||||
[5]: https://lifehacker.com/lets-quit-it-with-the-introvert-extrovert-nonsense-1713772952
|
||||
[6]: https://www.psychologytoday.com/us/blog/the-gen-y-guide/201710/the-majority-people-are-not-introverts-or-extroverts
|
265
published/201912/20191007 Using the Java Persistence API.md
Normal file
265
published/201912/20191007 Using the Java Persistence API.md
Normal file
@ -0,0 +1,265 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (runningwater)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11717-1.html)
|
||||
[#]: subject: (Using the Java Persistence API)
|
||||
[#]: via: (https://opensource.com/article/19/10/using-java-persistence-api)
|
||||
[#]: author: (Stephon Brown https://opensource.com/users/stephb)
|
||||
|
||||
使用 Java 持久化 API
|
||||
======
|
||||
|
||||
> 我们通过为自行车商店构建示例应用程序来学习如何使用 JPA。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/27/000705dymv92hnba2a2322.jpg)
|
||||
|
||||
对应用开发者来说,<ruby>Java 持久化 API<rt>Java Persistence API</rt></ruby>(JPA)是一项重要的 java 功能,需要透彻理解。它为 Java 开发人员定义了如何将对象的方法调用转换为访问、持久化及管理存储在 NoSQL 和关系型数据库中的数据的方案。
|
||||
|
||||
本文通过构建自行车借贷服务的教程示例来详细研究 JPA。此示例会使用 Spring Boot 框架、MongoDB 数据库([已经不开源][2])和 Maven 包管理来构建一个大型应用程序,并且构建一个创建、读取、更新和删除(CRUD)层。这儿我选择 NetBeans 11 作为我的 IDE。
|
||||
|
||||
此教程仅从开源的角度来介绍 Java 持久化 API 的工作原理,不涉及其作为工具的使用说明。这全是关于编写应用程序模式的学习,但对于理解具体的软件实现也很益处。可以从我的 [GitHub 仓库][3]来获取相关代码。
|
||||
|
||||
### Java: 不仅仅是“豆子”
|
||||
|
||||
Java 是一门面向对象的编程语言,自 1996 年发布第一版 Java 开发工具(JDK)起,已经变化了很多很多。要了解其各种发展及其虚拟机本身就是一堂历史课。简而言之,和 Linux 内核很相似,自发布以来,该语言已经向多个方向分支发展。有对社区免费的标准版本、有针对企业的企业版本及由多家供应商提供的开源替代品。主要版本每六个月发布一次,其功能往往差异很大,所以确认选用版本前得先做些研究。
|
||||
|
||||
总而言之,Java 的历史很悠久。本教程重点介绍 Java 11 的开源实现 [JDK 11][4]。因其是仍然有效的长期支持版本之一。
|
||||
|
||||
* **Spring Boot** 是由 Pivotal 公司开发的大型 Spring 框架的一个模块。Spring 是 Java 开发中一个非常流行的框架。它支持各种框架和配置,也为 WEB 应用程序及安全提供了保障。Spring Boot 为快速构建各种类型的 Java 项目提供了基本的配置。本教程使用 Spring Boot 来快速编写控制台应用程序并针对数据库编写测试用例。
|
||||
* **Maven** 是由 Apache 开发的项目/包管理工具。Maven 通过 `POM.xml` 文件来管理包及其依赖项。如果你使用过 NPM 的话,可能会非常熟悉包管理器的功能。此外 Maven 也用来进行项目构建及生成功能报告。
|
||||
* **Lombok** 是一个库,它通过在对象文件里面添加注解来自动创建 getters/setters 方法。像 C# 这些语言已经实现了此功能,Lombok 只是把此功能引入 Java 语言而已。
|
||||
* **NetBeans** 是一款很流行的开源 IDE,专门用于 Java 开发。它的许多工具都随着 Java SE 和 EE 的版本更新而更新。
|
||||
|
||||
我们会用这组工具为一个虚构自行车商店创建一个简单的应用程序。会实现对 `Customer` 和 `Bike` 对象集合的的插入操作。
|
||||
|
||||
### 酿造完美
|
||||
|
||||
导航到 [Spring Initializr][5] 页面。该网站可以生成基于 Spring Boot 和其依赖项的基本项目。选择以下选项:
|
||||
|
||||
1. **项目:** Maven 工程
|
||||
2. **语言:** Java
|
||||
3. **Spring Boot:** 2.1.8(或最稳定版本)
|
||||
4. **项目元数据:** 无论你使用什么名字,其命名约定都是像 `com.stephb` 这样的。
|
||||
* 你可以保留 Artifact 名字为 “Demo”。
|
||||
5. **依赖项:** 添加:
|
||||
* Spring Data MongoDB
|
||||
* Lombok
|
||||
|
||||
点击 **下载**,然后用你的 IDE(例如 NetBeans) 打开此新项目。
|
||||
|
||||
#### 模型层概要
|
||||
|
||||
在项目里面,<ruby>模型<rt>model</rt></ruby>代表从数据库里取出的信息的具体对象。我们关注两个对象:`Customer` 和 `Bike`。首先,在 `src` 目录创建 `dto` 目录;然后,创建两个名为 `Customer.java` 和 `Bike.java` 的 Java 类对象文件。其结构如下示:
|
||||
|
||||
```Java
|
||||
package com.stephb.JavaMongo.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class Customer {
|
||||
|
||||
private @Id String id;
|
||||
private String emailAddress;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String address;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
*Customer.Java*
|
||||
|
||||
```Java
|
||||
package com.stephb.JavaMongo.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class Bike {
|
||||
private @Id String id;
|
||||
private String modelNumber;
|
||||
private String color;
|
||||
private String description;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "This bike model is " + this.modelNumber + " is the color " + this.color + " and is " + description;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Bike.java*
|
||||
|
||||
如你所见,对象中使用 Lombok 注解来为定义的<ruby>属性<rt>properties</rt></ruby>/<ruby>特性<rt>attributes</rt></ruby>生成 getters/setters 方法。如果你不想对该类的所有特性都生成 getters/setters 方法,可以在属性上专门定义这些注解。这两个类会变成容器,里面携带有数据,无论在何处想显示信息都可以使用。
|
||||
|
||||
#### 配置数据库
|
||||
|
||||
我使用 [Mongo Docker][7] 容器来进行此次测试。如果你的系统上已经安装了 MongoDB,则不必运行 Docker 实例。你也可以登录其官网,选择系统信息,然后按照安装说明来安装 MongoDB。
|
||||
|
||||
安装后,就可以使用命令行、GUI(例如 MongoDB Compass)或用于连接数据源的 IDE 驱动程序来与新的 MongoDB 服务器进行交互。到目前为止,可以开始定义数据层了,用来拉取、转换和持久化数据。需要设置数据库访问属性,请导航到程序中的 `applications.properties` 文件,然后添加如下内容:
|
||||
|
||||
```
|
||||
spring.data.mongodb.host=localhost
|
||||
spring.data.mongodb.port=27017
|
||||
spring.data.mongodb.database=BikeStore
|
||||
```
|
||||
|
||||
#### 定义数据访问对象/数据访问层
|
||||
|
||||
<ruby>数据访问层<rt>data access layer</rt></ruby>(DAL)中的<ruby>数据访问对象<rt>data access objects</rt></ruby>(DAO)定义了与数据库中的数据的交互过程。令人惊叹的就是在使用 `spring-boot-starter` 后,查询数据库的大部分工作已经完成。
|
||||
|
||||
让我们从 `Customer` DAO 开始。在 `src` 下的新目录 `dao` 中创建一个接口文件,然后再创建一个名为 `CustomerRepository.java` 的 Java 类文件,其内容如下示:
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo.dao;
|
||||
|
||||
import com.stephb.JavaMongo.dto.Customer;
|
||||
import java.util.List;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
public interface CustomerRepository extends MongoRepository<Customer, String>{
|
||||
@Override
|
||||
public List<Customer> findAll();
|
||||
public List<Customer> findByFirstName(String firstName);
|
||||
public List<Customer> findByLastName(String lastName);
|
||||
}
|
||||
```
|
||||
|
||||
这个类是一个接口,扩展或继承于 `MongoRepository` 类,而 `MongoRepository` 类依赖于 DTO (`Customer.java`)和一个字符串,它们用来实现自定义函数查询功能。因为你已继承自此类,所以你可以访问许多方法函数,这些函数允许持久化和查询对象,而无需实现或引用自己定义的方法函数。例如,在实例化 `CustomerRepository` 对象后,你就可以直接使用 `Save` 函数。如果你需要扩展更多的功能,也可以重写这些函数。我创建了一些自定义查询来搜索我的集合,这些集合对象是我自定义的元素。
|
||||
|
||||
`Bike` 对象也有一个存储源负责与数据库交互。与 `CustomerRepository` 的实现非常类似。其实现如下所示:
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo.dao;
|
||||
|
||||
import com.stephb.JavaMongo.dto.Bike;
|
||||
import java.util.List;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author stephon
|
||||
*/
|
||||
public interface BikeRepository extends MongoRepository<Bike,String>{
|
||||
public Bike findByModelNumber(String modelNumber);
|
||||
@Override
|
||||
public List<Bike> findAll();
|
||||
public List<Bike> findByColor(String color);
|
||||
}
|
||||
```
|
||||
|
||||
#### 运行程序
|
||||
|
||||
现在,你已经有了一种结构化数据的方式,可以对数据进行提取、转换和持久化,然后运行这个程序。
|
||||
|
||||
找到 `Application.java` 文件(有可能不是此名称,具体取决于你的应用程序名称,但都会包含有 “application” )。在定义此类的地方,在后面加上 `implements CommandLineRunner`。这将允许你实现 `run` 方法来创建命令行应用程序。重写 `CommandLineRunner` 接口提供的 `run` 方法,并包含如下内容用来测试 `BikeRepository` :
|
||||
|
||||
```
|
||||
package com.stephb.JavaMongo;
|
||||
|
||||
import com.stephb.JavaMongo.dao.BikeRepository;
|
||||
import com.stephb.JavaMongo.dao.CustomerRepository;
|
||||
import com.stephb.JavaMongo.dto.Bike;
|
||||
import java.util.Scanner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class JavaMongoApplication implements CommandLineRunner {
|
||||
@Autowired
|
||||
private BikeRepository bikeRepo;
|
||||
private CustomerRepository custRepo;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(JavaMongoApplication.class, args);
|
||||
}
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
Scanner scan = new Scanner(System.in);
|
||||
String response = "";
|
||||
boolean running = true;
|
||||
while(running){
|
||||
System.out.println("What would you like to create? \n C: The Customer \n B: Bike? \n X:Close");
|
||||
response = scan.nextLine();
|
||||
if ("B".equals(response.toUpperCase())) {
|
||||
String[] bikeInformation = new String[3];
|
||||
System.out.println("Enter the information for the Bike");
|
||||
System.out.println("Model Number");
|
||||
bikeInformation[0] = scan.nextLine();
|
||||
System.out.println("Color");
|
||||
bikeInformation[1] = scan.nextLine();
|
||||
System.out.println("Description");
|
||||
bikeInformation[2] = scan.nextLine();
|
||||
|
||||
Bike bike = new Bike();
|
||||
bike.setModelNumber(bikeInformation[0]);
|
||||
bike.setColor(bikeInformation[1]);
|
||||
bike.setDescription(bikeInformation[2]);
|
||||
|
||||
bike = bikeRepo.save(bike);
|
||||
System.out.println(bike.toString());
|
||||
|
||||
|
||||
} else if ("X".equals(response.toUpperCase())) {
|
||||
System.out.println("Bye");
|
||||
running = false;
|
||||
} else {
|
||||
System.out.println("Sorry nothing else works right now!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其中的 `@Autowired` 注解会自动依赖注入 `BikeRepository` 和 `CustomerRepository` Bean。我们将使用这些类来从数据库持久化和采集数据。
|
||||
|
||||
已经好了。你已经创建了一个命令行应用程序。该应用程序连接到数据库,并且能够以最少的代码执行 CRUD 操作
|
||||
|
||||
### 结论
|
||||
|
||||
从诸如对象和类之类的编程语言概念转换为用于在数据库中存储、检索或更改数据的调用对于构建应用程序至关重要。Java 持久化 API(JPA)正是为 Java 开发人员解决这一难题的重要工具。你正在使用 Java 操纵哪些数据库呢?请在评论中分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/using-java-persistence-api
|
||||
|
||||
作者:[Stephon Brown][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[runningwater](https://github.com/runningwater)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/stephb
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/java-coffee-beans.jpg?itok=3hkjX5We (Coffee beans)
|
||||
[2]: https://www.techrepublic.com/article/mongodb-ceo-tells-hard-truths-about-commercial-open-source/
|
||||
[3]: https://github.com/StephonBrown/SpringMongoJava
|
||||
[4]: https://openjdk.java.net/projects/jdk/11/
|
||||
[5]: https://start.spring.io/
|
||||
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[7]: https://hub.docker.com/_/mongo
|
||||
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+exception
|
||||
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
@ -1,17 +1,18 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11702-1.html)
|
||||
[#]: subject: (How to type emoji on Linux)
|
||||
[#]: via: (https://opensource.com/article/19/10/how-type-emoji-linux)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
如何在 Linux 系统中输入 emoji
|
||||
======
|
||||
使用 GNOME 桌面可以让你在文字中轻松加入 emoji。
|
||||
|
||||
![A cat under a keyboard.][1]
|
||||
> 使用 GNOME 桌面可以让你在文字中轻松加入 emoji。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/22/003829tsuogoonoxunn33o.jpg)
|
||||
|
||||
emoji 是潜藏在 Unicode 字符空间里的有趣表情图,它们已经风靡于整个互联网。emoji 可以用来在社交媒体上表示自己的心情状态,也可以作为重要文件名的视觉标签,总之它们的各种用法层出不穷。在 Linux 系统中有很多种方式可以输入 Unicode 字符,但 GNOME 桌面能让你更轻松地查找和输入 emoji。
|
||||
|
||||
@ -25,7 +26,6 @@ emoji 是潜藏在 Unicode 字符空间里的有趣表情图,它们已经风
|
||||
|
||||
例如在 Fedora 上:
|
||||
|
||||
|
||||
```
|
||||
$ sudo dnf search emoji
|
||||
emoji-picker.noarch : An emoji selection tool
|
||||
@ -46,35 +46,29 @@ google-noto-emoji-color-fonts.noarch : Google “Noto Color Emoji” colored emo
|
||||
|
||||
要开始设置,首先打开 GNOME 的设置面板。
|
||||
|
||||
1. 在左边侧栏中,选择“<ruby>地区与语言<rt>Region & Language</rt></ruby>”类别
|
||||
2. 点击“<ruby>输入源<rt>Input Sources</rt></ruby>”选项下方的加号(+)打开“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板
|
||||
|
||||
1、在左边侧栏中,选择“<ruby>地区与语言<rt>Region & Language</rt></ruby>”类别。
|
||||
|
||||
2、点击“<ruby>输入源<rt>Input Sources</rt></ruby>”选项下方的加号(+)打开“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板。
|
||||
|
||||
![Add a new input source][5]
|
||||
|
||||
3. 在“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板中,点击底部的菜单按钮
|
||||
|
||||
|
||||
3、在“<ruby>添加输入源<rt>Add an Input Source</rt></ruby>”面板中,点击底部的菜单按钮。
|
||||
|
||||
![Add an Input Source panel][6]
|
||||
|
||||
4. 滑动到列表底部并选择“<ruby>其它<rt>Other</rt></ruby>”
|
||||
5. 在“<ruby>其它<rt>Other</rt></ruby>”列表中,找到“<ruby>其它<rt>Other</rt></ruby>(<ruby>快速输入<rt>Typing Booster</rt></ruby>)”
|
||||
|
||||
4、滑动到列表底部并选择“<ruby>其它<rt>Other</rt></ruby>”。
|
||||
|
||||
5、在“<ruby>其它<rt>Other</rt></ruby>”列表中,找到“<ruby>其它<rt>Other</rt></ruby>(<ruby>快速输入<rt>Typing Booster</rt></ruby>)”。
|
||||
|
||||
![Find Other \(Typing Booster\) in inputs][7]
|
||||
|
||||
6. 点击右上角的“<ruby>添加<rt>Add</rt></ruby>”按钮,将输入源添加到 GNOME 桌面
|
||||
|
||||
|
||||
6、点击右上角的“<ruby>添加<rt>Add</rt></ruby>”按钮,将输入源添加到 GNOME 桌面。
|
||||
|
||||
以上操作完成之后,就可以关闭设置面板了。
|
||||
|
||||
#### 切换到快速输入
|
||||
|
||||
现在 GNOME 桌面的右上角会出现一个新的图标,一般情况下是当前语言的双字母缩写(例如英语是 en,世界语是 eo,西班牙语是 es,等等)。如果你按下了<ruby>超级键<rt>Super key</rt></ruby>(也就是键盘上带有 Linux 企鹅/Windows 徽标/Mac Command 标志的键)+空格键的组合键,就会切换到输入列表中的下一个输入源。在这里,我们只有两个输入源,也就是默认语言和快速输入。
|
||||
现在 GNOME 桌面的右上角会出现一个新的图标,一般情况下是当前语言的双字母缩写(例如英语是 en,世界语是 eo,西班牙语是 es,等等)。如果你按下了<ruby>超级键<rt>Super key</rt></ruby>(也就是键盘上带有 Linux 企鹅/Windows 徽标/Mac Command 标志的键)+ 空格键的组合键,就会切换到输入列表中的下一个输入源。在这里,我们只有两个输入源,也就是默认语言和快速输入。
|
||||
|
||||
你可以尝试使用一下这个组合键,观察图标的变化。
|
||||
|
||||
@ -96,7 +90,7 @@ google-noto-emoji-color-fonts.noarch : Google “Noto Color Emoji” colored emo
|
||||
|
||||
### 使用其它切换方式
|
||||
|
||||
如果你觉得超级键+空格键这个组合用起来不顺手,你也可以换成其它键的组合。在 GNOME 设置面板中选择“<ruby>设备<rt>Device</rt></ruby>”→“<ruby>键盘<rt>Keyboard</rt></ruby>”。
|
||||
如果你觉得“超级键+空格键”这个组合用起来不顺手,你也可以换成其它键的组合。在 GNOME 设置面板中选择“<ruby>设备<rt>Device</rt></ruby>”→“<ruby>键盘<rt>Keyboard</rt></ruby>”。
|
||||
|
||||
在“<ruby>键盘<rt>Keyboard</rt></ruby>”页面中,将“<ruby>切换到下一个输入源<rt>Switch to next input source</rt></ruby>”更改为你喜欢的组合键。
|
||||
|
||||
@ -106,11 +100,9 @@ google-noto-emoji-color-fonts.noarch : Google “Noto Color Emoji” colored emo
|
||||
|
||||
实际上,现代键盘的设计只是为了输入 26 个字母以及尽可能多的数字和符号。但 ASCII 字符的数量已经比键盘上能看到的字符多得多了,遑论上百万个 Unicode 字符。因此,如果你想要在 Linux 应用程序中输入 Unicode,但又不想使用快速输入,你可以尝试一下 Unicode 输入。
|
||||
|
||||
1. 打开任意一种支持输入 Unicode 字符的软件,但仍然使用你的默认输入语言
|
||||
2. 使用 ctrl+shift+U 组合键进入 Unicode 输入模式
|
||||
3. 在 Unicode 输入模式下,只需要输入某个 Unicode 字符的对应序号,就实现了对这个 Unicode 字符的输入。例如 `1F44D` 对应的是 👍,而 `2620` 则对应了 ☠。想要查看所有 Unicode 字符的对应序号,可以参考 [Unicode 规范][11]。
|
||||
|
||||
|
||||
1. 打开任意一种支持输入 Unicode 字符的软件,但仍然使用你的默认输入语言
|
||||
2. 使用 `Ctrl+Shift+U` 组合键进入 Unicode 输入模式
|
||||
3. 在 Unicode 输入模式下,只需要输入某个 Unicode 字符的对应序号,就实现了对这个 Unicode 字符的输入。例如 `1F44D` 对应的是 👍,而 `2620` 则对应了 ☠。想要查看所有 Unicode 字符的对应序号,可以参考 [Unicode 规范][11]。
|
||||
|
||||
### emoji 的实用性
|
||||
|
||||
@ -127,7 +119,7 @@ via: https://opensource.com/article/19/10/how-type-emoji-linux
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
336
published/201912/20191023 How to program with Bash- Loops.md
Normal file
336
published/201912/20191023 How to program with Bash- Loops.md
Normal file
@ -0,0 +1,336 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11714-1.html)
|
||||
[#]: subject: (How to program with Bash: Loops)
|
||||
[#]: via: (https://opensource.com/article/19/10/programming-bash-loops)
|
||||
[#]: author: (David Both https://opensource.com/users/dboth)
|
||||
|
||||
怎样用 Bash 编程:循环
|
||||
======
|
||||
|
||||
> 本文是 Bash 编程系列三篇中的最后一篇,来学习使用循环执行迭代的操作。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/26/111437f9pa3zqqwcc9wwg1.jpg)
|
||||
|
||||
Bash 是一种强大的用于命令行和 shell 脚本的编程语言。本系列的三部分都是基于我的三集 [Linux 自学课程][2] 写的,探索怎么用 CLI 进行 bash 编程。
|
||||
|
||||
本系列的 [第一篇文章][3] 讨论了 bash 编程的一些简单命令行操作,如使用变量和控制操作符。[第二篇文章][4] 探讨了文件、字符串、数字等类型和各种各样在执行流中提供控制逻辑的的逻辑运算符,还有 bash 中不同种类的扩展。本文是第三篇(也是最后一篇),意在考察在各种迭代的操作中使用循环以及怎么合理控制循环。
|
||||
|
||||
### 循环
|
||||
|
||||
我使用过的所有编程语言都至少有两种循环结构来用来执行重复的操作。我经常使用 `for` 循环,然而我发现 `while` 和 `until` 循环也很有用处。
|
||||
|
||||
#### for 循环
|
||||
|
||||
我的理解是,在 bash 中实现的 `for` 命令比大部分语言灵活,因为它可以处理非数字的值;与之形成对比的是,诸如标准 C 语言的 `for` 循环只能处理数字类型的值。
|
||||
|
||||
Bash 版的 `for` 命令基本的结构很简单:
|
||||
|
||||
```
|
||||
for Var in list1 ; do list2 ; done
|
||||
```
|
||||
|
||||
解释一下:“对于 `list1` 中的每一个值,把 `$Var` 设置为那个值,使用该值执行 `list2` 中的程序语句;`list1` 中的值都执行完后,整个循环结束,退出循环。” `list1` 中的值可以是一个简单的显式字符串值,也可以是一个命令执行后的结果(`` 包含其内的命令执行的结果,本系列第二篇文章中有描述)。我经常使用这种结构。
|
||||
|
||||
要测试它,确认 `~/testdir` 仍然是当前的工作目录(PWD)。删除目录下所有东西,来看下这个显式写出值列表的 `for` 循环的简单的示例。这个列表混合了字母和数字 — 但是不要忘了,在 bash 中所有的变量都是字符串或者可以被当成字符串来处理。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rm *
|
||||
[student@studentvm1 testdir]$ for I in a b c d 1 2 3 4 ; do echo $I ; done
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
```
|
||||
|
||||
给变量赋予更有意义的名字,变成前面版本的进阶版:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept" ; done
|
||||
Department Human Resources
|
||||
Department Sales
|
||||
Department Finance
|
||||
Department Information Technology
|
||||
Department Engineering
|
||||
Department Administration
|
||||
Department Research
|
||||
```
|
||||
|
||||
创建几个目录(创建时显示一些处理信息):
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
|
||||
Working on Department Human Resources
|
||||
Working on Department Sales
|
||||
Working on Department Finance
|
||||
Working on Department Information Technology
|
||||
Working on Department Engineering
|
||||
Working on Department Administration
|
||||
Working on Department Research
|
||||
[student@studentvm1 testdir]$ ll
|
||||
total 28
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Administration
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Engineering
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Finance
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Human Resources'
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Information Technology'
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Research
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Sales
|
||||
```
|
||||
|
||||
在 `mkdir` 语句中 `$Dept` 变量必须用引号包裹起来;否则名字中间有空格(如 `Information Technology`)会被当做两个独立的目录处理。我一直信奉的一条实践规则:所有的文件和目录都应该为一个单词(中间没有空格)。虽然大部分现代的操作系统可以处理名字中间有空格的情况,但是系统管理员需要花费额外的精力去确保脚本和 CLI 程序能正确处理这些特例。(即使它们很烦人,也务必考虑它们,因为你永远不知道将拥有哪些文件。)
|
||||
|
||||
再次删除 `~/testdir` 下的所有东西 — 再运行一次下面的命令:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rm -rf * ; ll
|
||||
total 0
|
||||
[student@studentvm1 testdir]$ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
|
||||
Working on Department Human-Resources
|
||||
Working on Department Sales
|
||||
Working on Department Finance
|
||||
Working on Department Information-Technology
|
||||
Working on Department Engineering
|
||||
Working on Department Administration
|
||||
Working on Department Research
|
||||
[student@studentvm1 testdir]$ ll
|
||||
total 28
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Administration
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Engineering
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Finance
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Human-Resources
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Information-Technology
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Research
|
||||
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Sales
|
||||
```
|
||||
|
||||
假设现在有个需求,需要列出一台 Linux 机器上所有的 RPM 包并对每个包附上简短的描述。我为北卡罗来纳州工作的时候,曾经遇到过这种需求。由于当时开源尚未得到州政府的“批准”,而且我只在台式机上使用 Linux,对技术一窍不通的老板(PHB)需要我列出我计算机上安装的所有软件,以便他们可以“批准”一个特例。
|
||||
|
||||
你怎么实现它?有一种方法是,已知 `rpm –qa` 命令提供了 RPM 包的完整描述,包括了白痴老板想要的东西:软件名称和概要描述。
|
||||
|
||||
让我们一步步执行出最后的结果。首先,列出所有的 RPM 包:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rpm -qa
|
||||
perl-HTTP-Message-6.18-3.fc29.noarch
|
||||
perl-IO-1.39-427.fc29.x86_64
|
||||
perl-Math-Complex-1.59-429.fc29.noarch
|
||||
lua-5.3.5-2.fc29.x86_64
|
||||
java-11-openjdk-headless-11.0.ea.28-2.fc29.x86_64
|
||||
util-linux-2.32.1-1.fc29.x86_64
|
||||
libreport-fedora-2.9.7-1.fc29.x86_64
|
||||
rpcbind-1.2.5-0.fc29.x86_64
|
||||
libsss_sudo-2.0.0-5.fc29.x86_64
|
||||
libfontenc-1.1.3-9.fc29.x86_64
|
||||
<snip>
|
||||
```
|
||||
|
||||
用 `sort` 和 `uniq` 命令对列表进行排序和打印去重后的结果(有些已安装的 RPM 包具有相同的名字):
|
||||
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ rpm -qa | sort | uniq
|
||||
a2ps-4.14-39.fc29.x86_64
|
||||
aajohan-comfortaa-fonts-3.001-3.fc29.noarch
|
||||
abattis-cantarell-fonts-0.111-1.fc29.noarch
|
||||
abiword-3.0.2-13.fc29.x86_64
|
||||
abrt-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-ccpp-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-coredump-helper-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-kerneloops-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-pstoreoops-2.11.0-1.fc29.x86_64
|
||||
abrt-addon-vmcore-2.11.0-1.fc29.x86_64
|
||||
<snip>
|
||||
```
|
||||
|
||||
以上命令得到了想要的 RPM 列表,因此你可以把这个列表作为一个循环的输入信息,循环最终会打印每个 RPM 包的详细信息:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done
|
||||
```
|
||||
|
||||
这段代码产出了多余的信息。当循环结束后,下一步就是提取出白痴老板需要的信息。因此,添加一个 `egrep` 命令用来搜索匹配 `^Name` 或 `^Summary` 的行。脱字符(`^`)表示行首,整个命令表示显示所有以 Name 或 Summary 开头的行。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"
|
||||
Name : a2ps
|
||||
Summary : Converts text and other types of files to PostScript
|
||||
Name : aajohan-comfortaa-fonts
|
||||
Summary : Modern style true type font
|
||||
Name : abattis-cantarell-fonts
|
||||
Summary : Humanist sans serif font
|
||||
Name : abiword
|
||||
Summary : Word processing program
|
||||
Name : abrt
|
||||
Summary : Automatic bug detection and reporting tool
|
||||
<snip>
|
||||
```
|
||||
|
||||
在上面的命令中你可以试试用 `grep` 代替 `egrep` ,你会发现用 `grep` 不能得到正确的结果。你也可以通过管道把命令结果用 `less` 过滤器来查看。最终命令像这样:
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt
|
||||
```
|
||||
|
||||
这个命令行程序用到了管道、重定向和 `for` 循环,这些全都在一行中。它把你的 CLI 程序的结果重定向到了一个文件,这个文件可以在邮件中使用或在其他地方作为输入使用。
|
||||
|
||||
这个一次一步构建程序的过程让你能看到每步的结果,以此来确保整个程序以你期望的流程进行且输出你想要的结果。
|
||||
|
||||
白痴老板最终收到了超过 1900 个不同的 RPM 包的清单,我严重怀疑根本就没人读过这个列表。我给了他们想要的东西,没有从他们嘴里听到过任何关于 RPM 包的信息。
|
||||
|
||||
### 其他循环
|
||||
|
||||
Bash 中还有两种其他类型的循环结构:`while` 和 `until` 结构,两者在语法和功能上都类似。这些循环结构的基础语法很简单:
|
||||
|
||||
```
|
||||
while [ expression ] ; do list ; done
|
||||
```
|
||||
|
||||
逻辑解释:表达式(`expression`)结果为 true 时,执行程序语句 `list`。表达式结果为 false 时,退出循环。
|
||||
|
||||
```
|
||||
until [ expression ] ; do list ; done
|
||||
```
|
||||
|
||||
逻辑解释:执行程序语句 `list`,直到表达式的结果为 true。当表达式结果为 true 时,退出循环。
|
||||
|
||||
#### While 循环
|
||||
|
||||
`while` 循环用于当逻辑表达式结果为 true 时执行一系列程序语句。假设你的 PWD 仍是 `~/testdir`。
|
||||
|
||||
最简单的 `while` 循环形式是这个会一直运行下去的循环。下面格式的条件语句永远以 `true` 作为返回。你也可以用简单的 `1` 代替 `true`,结果一样,但是这解释了 true 表达式的用法。
|
||||
|
||||
```
|
||||
[student@studentvm1 testdir]$ X=0 ; while [ true ] ; do echo $X ; X=$((X+1)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
[student@studentvm1 testdir]$
|
||||
```
|
||||
|
||||
既然你已经学了 CLI 的各部分知识,那就让它变得更有用处。首先,为了防止变量 `$X` 在前面的程序或 CLI 命令执行后有遗留的值,设置 `$X` 的值为 0。然后,因为逻辑表达式 `[ true ]` 的结果永远是 1,即 true,在 `do` 和 `done` 中间的程序指令列表会一直执行 — 或者直到你按下 `Ctrl+C` 抑或发送一个 2 号信号给程序。那些程序指令是算数扩展,用来打印变量 `$X` 当前的值并加 1.
|
||||
|
||||
《[系统管理员的 Linux 哲学][5]》的信条之一是追求优雅,实现优雅的一种方式就是简化。你可以用操作符 `++` 来简化这个程序。在第一个例子中,变量当前的值被打印出来,然后变量的值增加了。可以在变量后加一个 `++` 来表示这个逻辑:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((X++)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
```
|
||||
|
||||
现在删掉程序最后的 `| head` 再运行一次。
|
||||
|
||||
在下面这个版本中,变量在值被打印之前就自增了。这是通过在变量之前添加 `++` 操作符实现的。你能看出区别吗?
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((++X)) ; done | head
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
```
|
||||
|
||||
你已经把打印变量的值和自增简化到了一条语句。类似 `++` 操作符,也有 `--` 操作符。
|
||||
|
||||
你需要一个在循环到某个特定数字时终止循环的方法。把 true 表达式换成一个数字比较表达式来实现它。这里有一个循环到 5 终止的程序。在下面的示例代码中,你可以看到 `-le` 是 “小于或等于” 的数字逻辑操作符。整个语句的意思:只要 `$X` 的值小于或等于 5,循环就一直运行。当 `$X` 增加到 6 时,循环终止。
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; while [ $X -le 5 ] ; do echo $((X++)) ; done
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
#### Until 循环
|
||||
|
||||
`until` 命令非常像 `while` 命令。不同之处是,它直到逻辑表达式的值是 `true` 之前,会一直循环。看一下这种结构最简单的格式:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; until false ; do echo $((X++)) ; done | head
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
它用一个逻辑比较表达式来计数到一个特定的值:
|
||||
|
||||
```
|
||||
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((X++)) ; done
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((++X)) ; done
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
[student@studentvm1 ~]$
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
本系列探讨了构建 Bash 命令行程序和 shell 脚本的很多强大的工具。但是这仅仅是你能用 Bash 做的很多有意思的事中的冰山一角,接下来就看你的了。
|
||||
|
||||
我发现学习 Bash 编程最好的方法就是实践。找一个需要多个 Bash 命令的简单项目然后写一个 CLI 程序。系统管理员们要做很多适合 CLI 编程的工作,因此我确信你很容易能找到自动化的任务。
|
||||
|
||||
很多年前,尽管我对其他的 Shell 语言和 Perl 很熟悉,但还是决定用 Bash 做所有系统管理员的自动化任务。我发现,有时稍微搜索一下,我可以用 Bash 实现我需要的所有事情。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/programming-bash-loops
|
||||
|
||||
作者:[David Both][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dboth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/fail_progress_cycle_momentum_arrow.png?itok=q-ZFa_Eh (arrows cycle symbol for failing faster)
|
||||
[2]: http://www.both.org/?page_id=1183
|
||||
[3]: https://linux.cn/article-11552-1.html
|
||||
[4]: https://linux.cn/article-11687-1.html
|
||||
[5]: https://www.apress.com/us/book/9781484237298
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11716-1.html)
|
||||
[#]: subject: (Create virtual machines with Cockpit in Fedora)
|
||||
[#]: via: (https://fedoramagazine.org/create-virtual-machines-with-cockpit-in-fedora/)
|
||||
[#]: author: (Karlis KavacisPaul W. Frields https://fedoramagazine.org/author/karlisk/https://fedoramagazine.org/author/pfrields/)
|
||||
@ -12,19 +12,19 @@
|
||||
|
||||
![][1]
|
||||
|
||||
本文向你展示如何在 Fedora 31 上使用安装 Cockpit 所需软件来创建和管理虚拟机。Cockpit 是一个[交互式管理界面][2],可让你在任何受支持的 Web 浏览器上访问和管理系统。随着 [virt-manager 正逐渐废弃][3],用户被鼓励使用 Cockpit 来替换它。
|
||||
本文向你展示如何在 Fedora 31 上使用安装 Cockpit 所需软件来创建和管理虚拟机。Cockpit 是一个[交互式管理界面][2],可让你在任何受支持的 Web 浏览器上访问和管理系统。随着 [virt-manager 逐渐被废弃][3],鼓励用户使用 Cockpit 来替换它。
|
||||
|
||||
Cockpit 是一个积极开发的项目,它有许多扩展其工作的插件。例如,其中一个是 “Machines”,它与 libvirtd 交互并允许用户创建和管理虚拟机。
|
||||
Cockpit 是一个正在活跃开发的项目,它有许多扩展其工作的插件。例如,其中一个是 “Machines”,它与 libvirtd 交互并允许用户创建和管理虚拟机。
|
||||
|
||||
### 安装软件
|
||||
|
||||
先决所需软件是 _libvirt _、_ cockpit_ 和 _cockpit-machines_。要将它们安装在 Fedora 31 上,请在终端[使用 sudo][4] 运行以下命令:
|
||||
先决所需软件是 `libvirt`、`cockpit` 和 `cockpit-machines`。要将它们安装在 Fedora 31 上,请在终端[使用 sudo][4] 运行以下命令:
|
||||
|
||||
```
|
||||
$ sudo dnf install libvirt cockpit cockpit-machines
|
||||
```
|
||||
|
||||
Cockpit 也在 “Headless Management” 软件包组中。该组对于仅通过网络访问的基于 Fedora 的服务器很有用。在这里,请使用以下命令进行安装:
|
||||
Cockpit 也在 “Headless Management” 软件包组中。该软件组对于仅通过网络访问的基于 Fedora 的服务器很有用。在这里,请使用以下命令进行安装:
|
||||
|
||||
```
|
||||
$ sudo dnf groupinstall "Headless Management"
|
||||
@ -32,7 +32,7 @@ $ sudo dnf groupinstall "Headless Management"
|
||||
|
||||
### 设置 Cockpit 服务
|
||||
|
||||
安装了必要的软件包后,就该启用服务了。 _libvirtd_ 服务运行虚拟机,而 Cockpit 有一个激活的套接字服务,可让你访问 Web GUI:
|
||||
安装了必要的软件包后,就该启用服务了。`libvirtd` 服务运行虚拟机,而 Cockpit 有一个激活的套接字服务,可让你访问 Web GUI:
|
||||
|
||||
```
|
||||
$ sudo systemctl enable libvirtd --now
|
||||
@ -59,35 +59,31 @@ $ sudo systemctl status cockpit.socket
|
||||
|
||||
使用系统的用户名和密码登录界面。你还可以选择是否允许在此会话中将密码用于管理任务。
|
||||
|
||||
选择 _Virtual Machines_,然后选择_ Create VM_ 来创建一台新的虚拟机。控制台为你提供几个选项:
|
||||
选择 “Virtual Machines”,然后选择 “Create VM” 来创建一台新的虚拟机。控制台为你提供几个选项:
|
||||
|
||||
* 使用 Cockpit 的内置库下载操作系统
|
||||
* 使用系统上已下载的安装媒体
|
||||
* 指向系统安装树的 URL
|
||||
* 通过 [PXE][5] 协议通过网络引导媒体
|
||||
|
||||
|
||||
|
||||
输入所有必要的参数。然后选择 _Create_ 启动新虚拟机。
|
||||
输入所有必要的参数。然后选择 “Create” 启动新虚拟机。
|
||||
|
||||
此时,将出现一个图形控制台。大多数现代 Web 浏览器都允许你使用键盘和鼠标与 VM 控制台进行交互。现在,你可以完成安装并使用新的 VM,就像[过去通过 virt-manager][6] 一样。
|
||||
|
||||
* * *
|
||||
|
||||
_照片由 [Miguel Teixeira][7] 发布于 [Flickr][8](CC BY-SA 2.0)_
|
||||
*照片由 [Miguel Teixeira][7] 发布于 [Flickr][8](CC BY-SA 2.0)*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/create-virtual-machines-with-cockpit-in-fedora/
|
||||
|
||||
作者:[Karlis KavacisPaul W. Frields][a]
|
||||
作者:[Karlis Kavacis][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/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/karlisk/https://fedoramagazine.org/author/pfrields/
|
||||
[a]: https://fedoramagazine.org/author/karlisk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/11/create-vm-cockpit-816x345.jpg
|
||||
[2]: https://cockpit-project.org/
|
@ -0,0 +1,82 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11733-1.html)
|
||||
[#]: subject: (Fedora Desktops – Memory Footprints)
|
||||
[#]: via: (https://fedoramagazine.org/fedora-desktops-memory-footprints/)
|
||||
[#]: author: (Troy Dawson https://fedoramagazine.org/author/tdawson/)
|
||||
|
||||
Fedora 上的桌面环境内存占用测试
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Fedora 中有 40 多种桌面环境(DE)。每种桌面环境都有自己的优点和缺点。通常,根据功能、外观和其它品质,选择桌面是一件非常个人的偏好。但有时,你选择的桌面环境还会受到硬件限制。
|
||||
|
||||
本文旨在帮助人们根据桌面环境占用的基准内存来比较 Fedora 桌面环境。为了缩小范围,我们仅查看具有正式 Fedora Live 镜像的桌面环境。
|
||||
|
||||
### 安装与系统配置
|
||||
|
||||
每个桌面环境都安装在自己的 KVM 虚拟机上。每个虚拟机都有 1 个 CPU、4GB 内存、15GB virtio 固态磁盘,以及 RHEL 8.0 kvm 上所有其他标准配置。
|
||||
|
||||
用于安装的镜像是标准的 Fedora 31 Live 镜像。对于 GNOME,该镜像是 “Fedora 工作站”。对于其它桌面,使用了相应的 Spin 版本。未对“<ruby>糖葫芦<rt>Sugar On A Stick</rt></ruby>”(SOAS)进行测试,因为它不容易安装到本地驱动器上。
|
||||
|
||||
用 Live CD 启动虚拟机,然后选择“安装到硬盘”。在安装过程中,仅使用默认值。创建了一个 root 用户和一个普通用户。安装并重新启动后,live 镜像已确认不在虚拟 CDROM 中。
|
||||
|
||||
每个桌面环境的设置都没有改动。它们每个都以 Live CD 环境中默认的设置运行。每个桌面环境都是通过普通用户登录的。打开了一个终端,在每台虚拟机中都使用 `sudo` 运行了 `dnf -y update`。在更新后,在该 sudo 终端中,每台虚拟机都运行 `/sbin/shutdown -h now` 以关闭。
|
||||
|
||||
### 测试方式
|
||||
|
||||
每台机器都已启动。桌面环境已通过普通用户登录。打开了三个桌面终端。xterm 从未使用过,始终用的是该桌面环境的终端,例如 konsole。
|
||||
|
||||
在一个终端中,启动 `top` 并按下 `M`,以显示按内存排序的进程。在另一个终端中,一个简单的 `while` 循环每 30 秒显示一次 `free -m`。第三个终端闲置。
|
||||
|
||||
然后,我等待了 5 分钟。这样就可以让所有启动的服务都启动完成。我记录了最终的 `free` 结果,以及 `top` 中最终的前三名内存使用者。
|
||||
|
||||
### 结果
|
||||
|
||||
* Cinnamon
|
||||
* 使用了624 MB
|
||||
* cinnamon 4.8% / Xorg 2.2% / dnfdragora 1.8%
|
||||
* GNOME
|
||||
* 使用了 612 MB
|
||||
* gnome-shell 6.9% / gnome-software 1.8% / ibus-x11 1.5%
|
||||
* KDE
|
||||
* 使用了 733 MB
|
||||
* plasmashell 6.2% / kwin\_x11 3.6% / akonadi\_mailfil 2.9%
|
||||
* LXDE
|
||||
* 使用了 318 MB
|
||||
* Xorg 1.9% / nm-applet 1.8% / dnfdragora 1.8%
|
||||
* LXQt
|
||||
* 使用了 391 MB
|
||||
* lxqt-panel 2.2% / pcmanfm-qt 2.1% / Xorg 2.1%
|
||||
* MATE
|
||||
* 使用了 465 MB
|
||||
* Xorg 2.5% / dnfdragora 1.8% / caja 1.5%
|
||||
* XFCE
|
||||
* 使用了 448 MB
|
||||
* Xorg 2.3% / xfwm4 2.0% / dnfdragora 1.8%
|
||||
|
||||
|
||||
|
||||
### 结论
|
||||
|
||||
我会让数字说明一切。
|
||||
|
||||
请记住,这些数字来自默认的 Live 安装环境。如果删除或添加服务和功能,则内存使用量将发生变化。但是,如果要根据内存消耗确定桌面环境,这是一个很好的基准。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/fedora-desktops-memory-footprints/
|
||||
|
||||
作者:[Troy Dawson][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/tdawson/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/11/desktop-memory-footprint-816x346.jpg
|
@ -0,0 +1,77 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11712-1.html)
|
||||
[#]: subject: (Customize your Linux desktop with FVWM)
|
||||
[#]: via: (https://opensource.com/article/19/12/fvwm-linux-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 FVWM 自定义 Linux 桌面
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。如果你正在寻找轻巧、快速且简单的 Linux 窗口管理器,那么 FVWM 可以胜任。但是,如果你正在寻找可以深入、探索和魔改的窗口管理器,那么 FVWM 是必须的。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/25/062800dwh3yhfcpx3ggjxp.jpg)
|
||||
|
||||
[FVWM][2] 窗口管理器最早脱胎于对 1993 年的 [TWM][3] 的修改。经过几年的迭代,诞生了一个可高度自定义的环境,它可以配置任何行为、动作或事件。它支持自定义键绑定、鼠标手势、主题、脚本等。
|
||||
|
||||
尽管 FVWM 在安装后即可投入使用,但默认分发版本仅提供了极其少的配置。这是开始自定义桌面环境的良好基础,但是,如果你只想将其用作桌面,那么可能要安装由其它用户发布的完整配置版本。FVWM 有几种不同的分发版,包括模仿 Windows 95 的 FVWM95(至少在外观和布局上)。我尝试了 [FVWM-Crystal][4],这是一个具有一些现代 Linux 桌面约定的现代主题。
|
||||
|
||||
可以从 Linux 发行版的软件仓库中安装要尝试的 FVWM 分发版。如果找不到特定的 FVWM 分发版,那么可以安装基础的 FVWM2 包,然后进入 [Box-Look.org][5] 手动下载主题包。这样就需要更多的工作,但比从头开始构建要少。
|
||||
|
||||
安装后,请注销当前的桌面会话,以便你可以登录 FVWM。默认情况下,会话管理器(KDM、GDM、LightDM 或 XDM,取决于你的设置)将继续登录到以前的桌面,因此你必须在登录之前覆盖该桌面。
|
||||
|
||||
对于 GDM:
|
||||
|
||||
![Select your desktop session in GDM][6]
|
||||
|
||||
对于 KDM:
|
||||
|
||||
![Select your desktop session with KDM][7]
|
||||
|
||||
### FVWM 桌面
|
||||
|
||||
无论你使用什么主题和配置,当你在桌面上单击鼠标左键时,FVWM 至少会显示一个菜单。菜单的内容取决于你所安装的内容。FVWM-Crystal 分发版中的菜单包含对常用首选项的快速访问,例如屏幕分辨率、壁纸设置、窗口装饰等。
|
||||
|
||||
同 FVWM 中的几乎所有东西一样,你可以编辑菜单中你要想的内容,但 FVWM-Crystal 的特色在于其应用菜单栏。应用菜单位于屏幕的左上角,每个图标都包含了相关的应用启动器的菜单。例如,GIMP 图标表示图像编辑器,KDevelop 图标表示集成开发环境(IDE),GNU 图标表示文本编辑器,等等,具体取决于你在系统上安装的程序。
|
||||
|
||||
![FVWM-crystal running on Slackware 14.2][8]
|
||||
|
||||
FVWM-Crystal 还提供了虚拟桌面、任务栏、时钟和应用栏。
|
||||
|
||||
关于背景,你可以使用与 FVWM-Crystal 捆绑在一起的壁纸,也可以使用 `feh` 命令设置自己的壁纸(你可能需要从仓库中安装它)。此命令有一些设置背景的选项,包括 `--bg-scale` 使用你选择的图片缩放填充屏幕,`--bg-fill` 直接填充而不缩放图片,等等。
|
||||
|
||||
```
|
||||
$ feh --bg-scale ~/Pictures/wallpapers/mybackground.jpg
|
||||
```
|
||||
|
||||
大多数配置文件都包含在 `$HOME/.fvwm-crystal` 中,某些系统范围的默认文件位于 `/usr/share/fvwm-crystal`。
|
||||
|
||||
### 自己尝试一下
|
||||
|
||||
FVWM 是大多作为一个桌面构建平台,它也是窗口管理器。它不会为你做到面面俱到,它期望你来配置尽可能的一切。
|
||||
|
||||
如果你正在寻找轻巧、快速且简单的窗口管理器,那么 FVWM 可以胜任。但是,如果你正在寻找可以深入、探索和魔改的窗口管理器,那么 FVWM 是必须的。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/fvwm-linux-desktop
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl (Coding on a computer)
|
||||
[2]: http://www.fvwm.org/
|
||||
[3]: https://en.wikipedia.org/wiki/Twm
|
||||
[4]: https://www.box-look.org/p/1018270/
|
||||
[5]: http://box-look.org
|
||||
[6]: https://opensource.com/sites/default/files/advent-gdm_0.jpg (Select your desktop session in GDM)
|
||||
[7]: https://opensource.com/sites/default/files/advent-kdm.jpg (Select your desktop session with KDM)
|
||||
[8]: https://opensource.com/sites/default/files/advent-fvwm-crystal.jpg (FVWM-crystal running on Slackware 14.2)
|
@ -0,0 +1,56 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (mayunmeiyouming)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11703-1.html)
|
||||
[#]: subject: (What GNOME 2 fans love about the Mate Linux desktop)
|
||||
[#]: via: (https://opensource.com/article/19/12/mate-linux-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
GNOME 2 粉丝喜欢 Mate Linux 桌面的什么?
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。如果你还在怀念 GNOME 2,那么 Mate Linux 桌面将满足你的怀旧情怀。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/22/073751ugrt47kye0begk3k.jpg)
|
||||
|
||||
如果你以前听过这个传闻:当 GNOME3 第一次发布时,很多 GNOME 用户还没有准备好放弃 GNOME 2。[Mate][2](以<ruby>马黛茶<rt>yerba mate</rt></ruby>植物命名)项目的开始是为了延续 GNOME 2 桌面,刚开始时它使用 GTK 2(GNOME 2 所基于的工具包),然后又合并了 GTK 3。由于 Linux Mint 的简单易用,使得该桌面变得非常流行,并且从那时起,它已经普遍用于 Fedora、Ubuntu、Slackware、Arch 和许多其他 Linux 发行版上。今天,Mate 继续提供一个传统的桌面环境,它的外观和感觉与 GNOME 2 完全一样,使用 GTK 3 工具包。
|
||||
|
||||
你可以在你的 Linux 发行版的软件仓库中找到 Mate,也可以下载并[安装][3]一个把 Mate 作为默认桌面的发行版。不过,在你这样做之前,请注意为了提供完整的桌面体验,所以许多 Mate 应用程序都是随该桌面一起安装的。如果你运行的是不同的桌面,你可能会发现自己有多余的应用程序(两个 PDF 阅读器、两个媒体播放器、两个文件管理器,等等)。所以如果你只想尝试 Mate 桌面,可以在虚拟机(例如 [GNOME box][4])中安装基于 Mate 的发行版。
|
||||
|
||||
### Mate 桌面之旅
|
||||
|
||||
Mate 项目不仅仅可以让你想起来 GNOME 2;它就是 GNOME 2。如果你是 00 年代中期 Linux 桌面的粉丝,至少,你会从中感受到 Mate 的怀旧情怀。我不是 GNOME 2 的粉丝,我更倾向于使用 KDE,但是有一个地方我无法想象没有 GNOME 2:[OpenSolaris][5]。OpenSolaris 项目并没有持续太久,在 Sun Microsystems 被并入 Oracle 之前,Ian Murdock 加入 Sun 时它就显得非常突出,我当时是一个初级的 Solaris 管理员,使用 OpenSolaris 来让自己更多学会那种 Unix 风格。这是我使用过 GNOME 2 的唯一平台(因为我一开始不知道如何更改桌面,后来习惯了它),而今天的 [OpenIndiana project][6] 是 OpenSolaris 的社区延续,它通过 Mate 桌面使用 GNOME 2。
|
||||
|
||||
![Mate on OpenIndiana][7]
|
||||
|
||||
Mate 的布局由左上角的三个菜单组成:应用程序、位置和系统。应用程序菜单提供对系统上安装的所有的应用程序启动器的快速访问。位置菜单提供对常用位置(如家目录、网络文件夹等)的快速访问。系统菜单包含全局选项,如关机和睡眠。右上角是一个系统托盘,屏幕底部有一个任务栏和一个虚拟桌面切换栏。
|
||||
|
||||
就桌面设计而言,这是一种稍微有点奇怪的配置。它从早期的 Linux 桌面、MacFinder 和 Windows 中借用了一些相同的部分,但是又创建了一个独特的配置,这种配置很直观而有些熟悉。Mate 执意保持这个模型,而这正是它的用户喜欢的地方。
|
||||
|
||||
### Mate 和开源
|
||||
|
||||
Mate 是一个最直接的例子,展示了开源如何使开发人员能够对抗项目生命的终结。从理论上讲,GNOME 2 会被 GNOME 3 所取代,但它依然存在,因为一个开发人员建立了该代码的一个分支并继续发展了下去。它的发展势头越来越庞大,更多的开发人员加入进来,并且这个让用户喜爱的桌面比以往任何时候都要更好。并不是所有的软件都有第二次机会,但是开源永远是一个机会,否则就永远没有机会。
|
||||
|
||||
使用和支持开源意味着支持用户和开发人员的自由。而且 Mate 桌面是他们的努力的有力证明。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/mate-linux-desktop
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[mayunmeiyouming](https://github.com/mayunmeiyouming)
|
||||
校对:[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/linux_keyboard_desktop.png?itok=I2nGw78_ (Linux keys on the keyboard for a desktop computer)
|
||||
[2]: https://mate-desktop.org/
|
||||
[3]: https://mate-desktop.org/install/
|
||||
[4]: https://opensource.com/article/19/5/getting-started-gnome-boxes-virtualization
|
||||
[5]: https://en.wikipedia.org/wiki/OpenSolaris
|
||||
[6]: https://www.openindiana.org/documentation/faq/#what-is-openindiana
|
||||
[7]: https://opensource.com/sites/default/files/uploads/advent-mate-openindiana_675px.jpg (Mate on OpenIndiana)
|
@ -1,20 +1,22 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11706-1.html)
|
||||
[#]: subject: (Get started with Lumina for your Linux desktop)
|
||||
[#]: via: (https://opensource.com/article/19/12/linux-lumina-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
在 Linux 桌面中开始使用 Lumina
|
||||
======
|
||||
本文是 24 天 Linux 桌面特别系列的一部分。Lumina 是快速、合理的基于 Fluxbox 的快捷方式桌面,它具有你无法缺少的所有功能。
|
||||
![Lightbulb][1]
|
||||
|
||||
多年来,有一个基于 FreeBSD 的桌面操作系统(OS),称为 PC-BSD。它旨在作为一般使用的系统,因此值得注意,因为 BSD 主要用于服务器。大多数时候,PC-BSD 默认带 KDE 桌面,但是 KDE 越来越依赖于 Linux 特定的技术,因此有越来越多的 PC-BSD 从中迁移出来。PC-BSD 变成了 [Trident][2],它的默认桌面是 [Lumina][3],它是一组小部件,它们使用与 KDE 相同的基于 Qt 的工具箱,运行在 Fluxbox 窗口管理器中。
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。Lumina 桌面是让你使用快速、合理的基于 Fluxbox 桌面的捷径,它具有你无法缺少的所有功能。
|
||||
|
||||
你可以在 Linux 发行版的软件仓库或 BSD 的 port 树中找到 Lumina 桌面。如果你安装了 Lumina 并且已经在运行另一个桌面,那么你可能会发现有冗余的应用(两个 PDF 阅读器、两个文件管理器,等等),因为 Lumina 包含一些集成的应用。如果你只想尝试 Lumina 桌面,那么可以在虚拟机如 [GNOME Boxes][4] 中安装基于 Lumina 的 BSD 发行版。
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/23/070658vtgg3wkrpg5g36rs.jpg)
|
||||
|
||||
多年来,有一个名为 PC-BSD 的基于 FreeBSD 的桌面操作系统(OS)。它旨在作为一个常规使用的系统,因此值得注意,因为 BSD 主要用于服务器。大多数时候,PC-BSD 默认带 KDE 桌面,但是 KDE 越来越依赖于 Linux 特定的技术,因此 PC-BSD 越来越从 KDE 迁离。PC-BSD 变成了 [Trident][2],它的默认桌面是 [Lumina][3],它是一组小部件,它们使用与 KDE 相同的基于 Qt 的工具包,运行在 Fluxbox 窗口管理器上。
|
||||
|
||||
你可以在 Linux 发行版的软件仓库或 BSD 的 ports 树中找到 Lumina 桌面。如果你安装了 Lumina 并且已经在运行另一个桌面,那么你可能会发现有冗余的应用(两个 PDF 阅读器、两个文件管理器,等等),因为 Lumina 包含一些集成的应用。如果你只想尝试 Lumina 桌面,那么可以在虚拟机如 [GNOME Boxes][4] 中安装基于 Lumina 的 BSD 发行版。
|
||||
|
||||
如果在当前的操作系统上安装 Lumina,那么必须注销当前的桌面会话,才能登录到新的会话。默认情况下,会话管理器(SDDM、GDM、LightDM 或 XDM,取决于你的设置)将继续登录到以前的桌面,因此你必须在登录之前覆盖该桌面。
|
||||
|
||||
@ -34,13 +36,13 @@ Lumina 提供了一个简单而轻巧的桌面环境。屏幕底部有一个面
|
||||
|
||||
![Lumina desktop running on Project Trident][7]
|
||||
|
||||
Lumina 与几个 Linux 轻量级桌面非常相似,尤其是 LXQT,不同之处在于 Lumina 完全不依赖于基于 Linux 的桌面框架,例如 ConsoleKit、PolicyKit、D-Bus 或 systemd。对于你而言,这是否具有优势取决于所运行的操作系统。毕竟,如果你运行的是可以访问这些功能的 Linux,那么使用不使用这些特性的桌面可能就没有多大意义,还会减少功能。如果你运行的是 BSD,那么在 Fluxbox 中运行 Lumina 部件意味着你不必从 port 安装 Linux 兼容库。
|
||||
Lumina 与几个 Linux 轻量级桌面非常相似,尤其是 LXQT,不同之处在于 Lumina 完全不依赖于基于 Linux 的桌面框架(例如 ConsoleKit、PolicyKit、D-Bus 或 systemd)。对于你而言,这是否具有优势取决于所运行的操作系统。毕竟,如果你运行的是可以访问这些功能的 Linux,那么使用不使用这些特性的桌面可能就没有多大意义,还会减少功能。如果你运行的是 BSD,那么在 Fluxbox 中运行 Lumina 部件意味着你不必从 ports 安装 Linux 兼容库。
|
||||
|
||||
### 为什么要使用 Lumina
|
||||
|
||||
Lumina 设计简单,没有很多功能,你无法通过安装 Fluxbox 以及自己喜欢的组件来实现([PCManFM][8] 用于文件管理、各种 [LXQt 应用][9 ]、[Tint2][10] 面板等)。但它是开源的,开源用户喜欢寻找避免重复发明轮子的方法(几乎与我们喜欢重新发明轮子一样多)。
|
||||
Lumina 设计简单,它没有很多功能,但是你可以安装 Fluxbox 你喜欢的组件(用于文件管理的 [PCManFM][8]、各种 [LXQt 应用][9]、[Tint2][10] 面板等)。在开源中,开源用户喜欢寻找不要重复发明轮子的方法(几乎与我们喜欢重新发明轮子一样多)。
|
||||
|
||||
Lumina 桌面是快速而合理的基于 Fluxbox 的桌面快捷方式,它具有你无法缺少的所有功能,并且你很少需要调整细节。试一试 Lumina 桌面,看看它是否适合你。
|
||||
Lumina 桌面是让你使用快速、合理的基于 Fluxbox 桌面的捷径,它具有你无法缺少的所有功能,并且你很少需要调整细节。试一试 Lumina 桌面,看看它是否适合你。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -49,7 +51,7 @@ via: https://opensource.com/article/19/12/linux-lumina-desktop
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -0,0 +1,90 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Morisun029)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11730-1.html)
|
||||
[#]: subject: (5 interview questions every Kubernetes job candidate should know)
|
||||
[#]: via: (https://opensource.com/article/19/12/kubernetes-interview-questions)
|
||||
[#]: author: (Jessica Repka https://opensource.com/users/jrepka)
|
||||
|
||||
每个 Kubernetes 应聘者应该知道的 5 个面试题
|
||||
======
|
||||
|
||||
> 如果你是要面试 Kubernetes 相关职位的应聘者,这里给出了要提问的问题以及这些问题的重要性。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/31/101229mmjumsesrzhh6rhk.jpg)
|
||||
|
||||
面试对面试官及候选人来说都很不容易。最近,我发现面试 Kubernetes 相关工作的候选人似乎尤其困难。为什么呢?一方面,很难找到可以回答他们问题的人。而且,不管回答者回答的怎样,都很难确定他们是否有正确的经验。
|
||||
|
||||
跳过这个问题,让我们来看看面试 [Kubernetes][2] 求职者时应该提问的一些问题。
|
||||
|
||||
### Kubernetes 是什么?
|
||||
|
||||
我发现这个问题是面试中最好的问题之一。我经常听到有人说“我用 Kubernetes 工作”,但是当我问道“Kubernetes 是什么”时,从来都没有得到过一个满意答案。
|
||||
|
||||
我最喜欢 [Chris Short][3] 给出的答案:“Kubernetes 就是带有一些 YAML 文件的 API 。”
|
||||
|
||||
虽然他的回答没有错,但我会给你更详细的解释。 Kubernetes 是一个可移植容器的编排工具,用于自动执行管理、监控、扩展和部署容器化应用程序。
|
||||
|
||||
我认为“用于部署容器化应用程序的编排工具”这个回答可能与你期望的答案差不多了。能回答出这个,我觉得已经很不错了。尽管许多人认为 Kubernetes 做了更多更棒的工作,但总的来说,它为其核心功能——容器编排——添加了许多 API。
|
||||
|
||||
我认为,这是你在面试中可以提问的最好的问题之一,因为它至少证明了候选人是否知道 Kubernetes 是什么。
|
||||
|
||||
### Kubernetes 的节点和 Pod 有什么区别?
|
||||
|
||||
该问题揭示了候选人对 Kubernetes 复杂性的初步了解。它将面试对话转换为对体系结构的概述,并可能导向许多有趣的后续细节问题。我已经听到了无数次关于该问题的错误解释了。
|
||||
|
||||
[节点][4] 是工作计算机。该计算机可以是虚拟机(VM)或物理计算机,具体取决于你是在虚拟机监控程序上运行还是在裸机上运行。该节点包含用于运行容器的服务,包括 kubelet、kube-proxy 和容器运行时。
|
||||
|
||||
[Pod][5] 包括:一个或多个**容器**、具有共享**网络**和**存储**,以及有关如何运行一起部署的容器的**规范**。这四个细节都很重要。更进一步,职位申请人应从技术层面解释,Pod 是 Kubernetes 可以创建和管理的最小可部署单元,而不是容器。
|
||||
|
||||
对于这个问题,我听到的最好的简答是:“节点是计算机,而 Pod 是容器运行于其中的东西。”这个区别很重要。Kubernetes 管理员的大部分工作是知道什么时间要部署什么,而节点的部署成本可能非常非常高,具体取决于它们的运行位置。我不希望有人一遍又一遍地部署节点,他们需要做的就是部署一堆 Pod。
|
||||
|
||||
### kubectl 是什么?(你怎么发音?)
|
||||
|
||||
这个问题是我优先级较高的问题之一,但可能与你和你的团队无关。在我的团队中,我们不会使用图形化界面来管理 Kubernetes 环境,我们使用命令行操作。
|
||||
|
||||
那么什么是 [kubectl][6]?它是 Kubernetes 的命令行界面。你可以从该界面获取并设置任何内容,从收集日志和事件到编辑部署环境和机密文件。随机提问候选人关于如何使用此工具对测试候选人对 kubectl 的熟悉度是很有帮助的。
|
||||
|
||||
你是怎么读的?好吧,你随便吧(对此有很大的分歧),但是我很高兴向你介绍我朋友 [Waldo][7] 的精彩视频演示。
|
||||
|
||||
### 命名空间是什么?
|
||||
|
||||
在多次面试中,我都没有得到关于这个问题的答案。我不确定在其他环境中使用的命名空间是否会在我所在的团队经常使用。我在这里给出一个简短的答案:命名空间是 Pod 中的虚拟集群。这种抽象可以使你将多个虚拟集保留在多个环境中以此来进行隔离。
|
||||
|
||||
### 容器是什么?
|
||||
|
||||
了解 Pod 中正在部署的内容总是有帮助的,因为如果都不知道其中部署的是什么,何谈部署?容器是打包代码及其所有依赖项的软件的标准单元。我收到了两个可以接受的答案,其中包括:a)精简的操作系统镜像,以及 b)在受限的操作系统环境中运行的应用程序。如果你可以叫得出使用 [Docker][8] 以外的其他容器的编排软件(例如你最喜欢的公共云的容器服务),则可以得到加分。
|
||||
|
||||
### 其他问题
|
||||
|
||||
如果你想知道为什么我没有在此问题列表中添加更多问题,那么我可以给出一个简单的答案:我所列出的这些问题是在面试候选人时应了解的最基本的问题。接下来的问题应该是基于具体的团队、环境及组织。当你仔细研究这些内容时,尝试寻找有关技术如何相互作用的有趣问题,以了解人们如何应对基础架构挑战。考虑一下你的团队最近遇到的挑战(中断),要求逐步进行部署,或者考虑改善团队积极想要改进的策略(例如减少部署时间)。问题越不抽象,对面试后真正重要的技能的询问就越多。
|
||||
|
||||
没有两个环境是完全相同的。这也适用于面试中。我在每次面试中都会混合提问。我也有一个测试面试者的小环境。我经常发现回答问题是最容易的部分,而你所做的工作才是对你的真正的考验。
|
||||
|
||||
我给面试官的最后一点建议是:如果你遇到一个很有潜力但没有经验的候选人时,请给他们一个证明自己的机会。如果当初没有人看到我的潜力,没有给我机会的话,我不会拥有今天的知识和经验。
|
||||
|
||||
还有哪些重要的问题?请留言告诉我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/kubernetes-interview-questions
|
||||
|
||||
作者:[Jessica Repka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Morisun029](https://github.com/Morisun029)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jrepka
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/collab-team-pair-programming-code-keyboard.png?itok=kBeRTFL1 (Pair programming)
|
||||
[2]: https://kubernetes.io/
|
||||
[3]: https://twitter.com/ChrisShort
|
||||
[4]: https://kubernetes.io/docs/concepts/architecture/nodes/
|
||||
[5]: https://kubernetes.io/docs/concepts/workloads/pods/pod/
|
||||
[6]: https://kubernetes.io/docs/reference/kubectl/kubectl/
|
||||
[7]: https://opensource.com/article/18/12/kubectl-definitive-pronunciation-guide
|
||||
[8]: https://opensource.com/resources/what-docker
|
||||
[9]: https://enterprisersproject.com/article/2019/2/kubernetes-job-interview-questions-how-prepare
|
@ -0,0 +1,207 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11720-1.html)
|
||||
[#]: subject: (Build a retro Apple desktop with the Linux MLVWM)
|
||||
[#]: via: (https://opensource.com/article/19/12/linux-mlvwm-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 Linux MLVWM 打造复古苹果桌面
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。如果老式的苹果电脑是用开源 POSIX 构建的呢?你可以通过构建 Macintosh 式的虚拟窗口管理器来实现。
|
||||
|
||||
![Person typing on a 1980's computer][1]
|
||||
|
||||
想象一下穿越到另一段平行历史,Apple II GS 和 MacOS 7 是基于开源 [POSIX][2] 构建的,它使用了与现代 Linux 相同的所有惯例,例如纯文本配置文件和模块化系统设计。这样的操作系统将为其用户带来什么?你可以使用 [Macintosh 式的虚拟窗口管理器(MLVWM)][3]来回答这些问题(甚至更多!)。
|
||||
|
||||
![MLVWM running on Slackware 14.2][4]
|
||||
|
||||
### 安装 MLVWM
|
||||
|
||||
MLVWM 安装并不容易,并且可能不在你的发行版软件仓库中。如果你有时间理解翻译不佳的 README 文件,编辑一些配置文件,收集并调整一些旧的 .xpm 图片,编辑一两个 Xorg 选项,那么你就可以体验 MLVWM。不管怎么说,这是一个新奇的窗口管理器,其最新版本可以追溯到 2000 年。
|
||||
|
||||
要编译 MLVWM,你必须安装 imake,它提供了 `xmkmf` 命令。你可以从发行版的软件仓库中安装 imake,也可以直接从 [Freedesktop.org][5] 获得。假设你已经有 `xmkmf` 命令,请进入包含 MLVWM 源码的目录,然后运行以下命令进行构建:
|
||||
|
||||
```
|
||||
$ xmkmf -a
|
||||
$ make
|
||||
```
|
||||
|
||||
构建后,编译后的 `mlvwm` 二进制文件位于 `mlvwm` 目录中。将其移动到[你的 PATH][6] 的任何位置:
|
||||
|
||||
```
|
||||
$ mv mlvwm/mlvwm /usr/local/bin/
|
||||
```
|
||||
|
||||
#### 编辑配置文件
|
||||
|
||||
现在已经安装好 MLVWM,但是如果不调整几个配置文件并仔细放好所需的图像文件,它将无法正确启动。示例配置文件位于你下载的源代码的 `sample_rc` 目录中。将文件 `Mlvwm-Netscape` 和 `Mlvwm-Xterm` 复制到你的主目录:
|
||||
|
||||
```
|
||||
$ cp sample_rc/Mlvwm-{Netscape,Xterm} $HOME
|
||||
```
|
||||
|
||||
将 `Mlvwmrc` 改名为 `$HOME/.mlvwmrc`(是的,即使示例文件的名称看似是大写字母,但你也必须使用小写的 “m”):
|
||||
|
||||
```
|
||||
$ cp sample_rc/Mlvwmrc $HOME/.mlvwmrc
|
||||
```
|
||||
|
||||
打开 `.mlwmrc` 并找到第 54-55 行,它们定义了 MLVWM 在菜单和 UI 中使用的像素图的路径(`IconPath`):
|
||||
|
||||
```
|
||||
# Set icon search path. It needs before "Style".
|
||||
IconPath /usr/local/include/X11/pixmaps:/home2/tak/bin/pixmap
|
||||
```
|
||||
|
||||
调整路径以匹配你填充图像的路径(我建议使用 `$HOME/.local/share/pixmaps`)。MLVWM 不提供像素图,因此需要你提供构建桌面所需图标。
|
||||
|
||||
即使你有位于系统其他位置的像素图(例如 `/usr/share/pixmaps`),也要这样做,因为你需要调整像素图的大小,你可能也不想在系统范围内执行此操作。
|
||||
|
||||
```
|
||||
# Set icon search path. It needs before "Style".
|
||||
IconPath /home/seth/.local/share/pixmaps
|
||||
```
|
||||
|
||||
#### 选择像素图
|
||||
|
||||
你已将 `.local/share/pixmaps` 目录定义为像素图源路径,但是该目录和图像均不存在。创建目录:
|
||||
|
||||
```
|
||||
$ mkdir -p $HOME/.local/share/pixmaps
|
||||
```
|
||||
|
||||
现在,配置文件将图像分配给菜单项和 UI 元素,但是系统中不存在这些图像。要解决此问题,请通读配置文件并找到每个 .xpm 图像。对于配置中列出的每个图像,将具有相同文件名的图像(或更改配置文件中的文件名)添加到你的 IconPath 目录。
|
||||
|
||||
`.mlvwmrc` 文件的注释很好,因此你可以大致了解要编辑的内容。无论如何,这只是第一步。你可以随时回来更改桌面外观。
|
||||
|
||||
这有些例子。
|
||||
|
||||
此代码块设置屏幕左上角的图标:
|
||||
|
||||
```
|
||||
# Register the menu
|
||||
Menu Apple, Icon label1.xpm, Stick
|
||||
```
|
||||
|
||||
`label1.xpm` 图像实际上在源代码的 `pixmap` 目录中,但我更喜欢使用来自 `/usr/share/pixmaps` 的 `Penguin.xpm`(在 Slackware 上)。无论使用什么,都必须将自定义像素图放在 `~/.local/share/pixmaps` 中,并在配置中更改像素图的名称,或者重命名像素图以匹配配置文件中当前的名称。
|
||||
|
||||
此代码块定义了左侧菜单中列出的应用:
|
||||
|
||||
```
|
||||
"About this Workstation..." NonSelect, Gray, Action About
|
||||
"" NonSelect
|
||||
"Terminal" Icon mini-display.xpm, Action Exec "kterm" exec kterm -ls
|
||||
"Editor" Action Exec "mule" exec mule, Icon mini-edit.xpm
|
||||
"calculator" Action Exec "xcal" exec xcalc, Icon mini-calc.xpm
|
||||
END
|
||||
```
|
||||
|
||||
通过遵循与配置文件中相同的语法,你可以自定义像素图并将自己的应用添加到菜单中(例如,我将 `mule` 更改为 `emacs`)。这是你在 MLVWM GUI 中打开应用的入口,因此请列出你要快速访问的所有内容。你可能还希望包括指向 `/usr/share/applications` 文件夹的快捷方式。
|
||||
|
||||
```
|
||||
"Applications" Icon Penguin.xpm, Action Exec "thunar /usr/share/applications" exec thunar /usr/share/applications
|
||||
```
|
||||
|
||||
完成编辑配置文件并将自己的图像添加到 IconPath 目录后,必须将所有像素图的大小都调整为大约 16x16 像素。(MLVWM 的默认设置不一致,因此存在变化空间。)你可以使用 ImageMagick 进行批量操作:
|
||||
|
||||
```
|
||||
$ for i in ~/.local/share/mlvwm-pixmaps/*xpm ; do convert -resize '16x16^' $i; done
|
||||
```
|
||||
|
||||
### 启动 MLVWM
|
||||
|
||||
最简单的运行 MLVWM 的方式是让 Xorg 完成大部分工作。首先,你必须创建一个 `$HOME/.xinitrc` 文件。我从 Slackware 复制了这个,它也是从 Xorg 拿来的:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
# $XConsortium: xinitrc.cpp,v 1.4 91/08/22 11:41:34 rws Exp $
|
||||
|
||||
userresources=$HOME/.Xresources
|
||||
usermodmap=$HOME/.Xmodmap
|
||||
sysresources=/etc/X11/xinit/.Xresources
|
||||
sysmodmap=/etc/X11/xinit/.Xmodmap
|
||||
|
||||
# merge in defaults and keymaps
|
||||
|
||||
if [ -f $sysresources ]; then
|
||||
xrdb -merge $sysresources
|
||||
fi
|
||||
|
||||
if [ -f $sysmodmap ]; then
|
||||
xmodmap $sysmodmap
|
||||
fi
|
||||
|
||||
if [ -f $userresources ]; then
|
||||
xrdb -merge $userresources
|
||||
fi
|
||||
|
||||
if [ -f $usermodmap ]; then
|
||||
xmodmap $usermodmap
|
||||
fi
|
||||
|
||||
# Start the window manager:
|
||||
if [ -z "$DESKTOP_SESSION" -a -x /usr/bin/ck-launch-session ]; then
|
||||
exec ck-launch-session /usr/local/bin/mlvwm
|
||||
else
|
||||
exec /usr/local/bin/mlvwm
|
||||
fi
|
||||
```
|
||||
|
||||
根据此文件,`startx` 命令的默认操作是启动 MLVWM。但是,你的发行版可能对于图形服务器启动(或被终止以重新启动)时会发生的情况有其他做法,因此此文件可能对你没有什么帮助。在许多发行版上,你可以添加 .desktop 文件到 `/usr/share/xsessions` 中,以将其列在 GDM 或 KDM 菜单中,因此创建名为 `mlvwm.desktop` 的文件并输入:
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=Mlvwm
|
||||
Comment=Macintosh-like virtual window manager
|
||||
Exec=/usr/local/bin/mlvwm
|
||||
TryExec=ck-launch-session /usr/local/bin/mlvwm
|
||||
Type=Application
|
||||
```
|
||||
|
||||
从桌面会话注销并重新登录到 MLVWM。默认情况下,会话管理器(KDM、GDM 或 LightDM,具体取决于你的设置)将继续登录到以前的桌面,因此在登录之前必须覆盖它。
|
||||
|
||||
对于 GDM:
|
||||
|
||||
![][7]
|
||||
|
||||
对于 SDDM:
|
||||
|
||||
![][8]
|
||||
|
||||
#### 强制启动
|
||||
|
||||
如果 MLVWM 无法启动,请尝试安装 XDM,这是一个轻量级会话管理器,它不会查询 `/usr/share/xsessions` 的内容,而是执行经过身份验证用户的所有 `.xinitrc` 操作。
|
||||
|
||||
![MLVWM][9]
|
||||
|
||||
### 打造自己的复古苹果
|
||||
|
||||
MLVWM 桌面未经打磨、不完美、模仿到位且充满乐趣。你看到的许多菜单项都是未实现的,但你可以使它们变得活跃且有意义。
|
||||
|
||||
这是一次让你时光倒流、改变历史,让老式苹果系列电脑成为开源堡垒的机会。成为一名修正主义者,设计你自己的复古苹果桌面,最重要的是,它有乐趣。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/linux-mlvwm-desktop
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
|
||||
[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
|
||||
[3]: http://www2u.biglobe.ne.jp/~y-miyata/mlvwm.html
|
||||
[4]: https://opensource.com/sites/default/files/uploads/advent-mlvwm-file.jpg (MLVWM running on Slackware 14.2)
|
||||
[5]: http://cgit.freedesktop.org/xorg/util/imake
|
||||
[6]: https://opensource.com/article/17/6/set-path-linux
|
||||
[7]: https://opensource.com/sites/default/files/advent-gdm_2.jpg
|
||||
[8]: https://opensource.com/sites/default/files/advent-kdm_1.jpg
|
||||
[9]: https://opensource.com/sites/default/files/uploads/advent-mlvwm-chess.jpg (MLVWM)
|
131
published/201912/20191218 How tracking pixels work.md
Normal file
131
published/201912/20191218 How tracking pixels work.md
Normal file
@ -0,0 +1,131 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chen-ni)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11721-1.html)
|
||||
[#]: subject: (How tracking pixels work)
|
||||
[#]: via: (https://jvns.ca/blog/how-tracking-pixels-work/)
|
||||
[#]: author: (Julia Evans https://jvns.ca/)
|
||||
|
||||
网络广告商的像素追踪是如何工作的?
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/27/214125hvpv4e5ijepa0aqj.jpg)
|
||||
|
||||
昨天,我和一名记者谈到了一个问题:广告商是如何在互联网上对人们进行追踪的?我们津津有味地查看了 Firefox 的开发者工具(虽然我不是一个互联网隐私专家,但至少还会使用开发者工具中的“network”标签页),从中我终于弄明白<ruby>像素追踪<rt>tracking pixels</rt></ruby>在实际中是如何工作的了。
|
||||
|
||||
### 问题:Facebook 怎么知道你逛了 Old Navy?
|
||||
|
||||
我时常听人们说起这种有些诡异的上网经历:你在线上浏览了一个商品,一天之后,竟然看到了同一款靴子(或者是别的什么你当时浏览的商品)的广告。这就是所谓的“再营销”,但它到底是如何实现的呢?
|
||||
|
||||
在本文中,我们来进行一个小实验,看看 Facebook 究竟是怎么知道你在线上浏览了什么商品的。这里使用 Facebook 作为示例,只是因为很容易找到使用了 Facebook 像素追踪技术的网站;其实,几乎所有互联网广告公司都会使用类似的追踪技术。
|
||||
|
||||
### 准备:允许第三方追踪器,同时关闭广告拦截器
|
||||
|
||||
我使用的浏览器是 Firefox,但是 Firefox 默认拦截了很多这种类型的追踪,所以需要修改 Firefox 的隐私设置,才能让这种追踪生效。
|
||||
|
||||
首先,我将隐私设置从默认设置([截图][1])修改为允许第三方追踪器的个性化设置([截图][2]),然后禁用了一些平时运行的隐私保护扩展。
|
||||
|
||||
![截图][1]
|
||||
|
||||
![截图][2]
|
||||
|
||||
### 像素追踪:关键不在于 gif,而在于请求参数
|
||||
|
||||
像素追踪是网站用来追踪你的一个 1x1 大小的 gif。就其本身而言,一个小小的 1x1 gif 显然起不到什么作用。那么,像素追踪到底是如何进行追踪的?其中涉及两个方面:
|
||||
|
||||
1. 通过使用像素追踪上的**请求参数**,网站可以添加额外的信息,比如你正在访问的页面。这样一来,请求的就不是 `https://www.facebook.com/tr/`(这个链接是一个 44 字节大小的 1x1 gif),而是 `https://www.facebook.com/tr/?the_website_you're_on`。(邮件营销人员会使用类似的技巧,通过为像素追踪指定一个独特的 URL,弄清楚你是否打开了某一封邮件。)
|
||||
2. 在发送该请求的同时,还发送了相应的 cookie。这样一来广告商就可以知道,访问 oldnavy.com 的这个人和在同一台电脑上使用 Facebook 的是同一个人。
|
||||
|
||||
### Old Navy 网站上的 Facebook 像素追踪
|
||||
|
||||
为了对此进行验证,我在 Old Navy(GAP 旗下的一个服装品牌)网站上浏览了一个商品,相应的 URL 是 `https://oldnavy.gap.com/browse/product.do?pid=504753002&cid=1125694&pcid=1135640&vid=1&grid=pds_0_109_1`(这是一件“男款短绒格子花呢大衣”)。
|
||||
|
||||
在我浏览这个商品的同时,页面上运行的 Javascript(用的应该是[这段代码][4])向 facebook.com 发送了一个请求。在开发者工具中,该请求看上去是这样的:(我屏蔽了大部分 cookie 值,因为其中有一些是我的登录 cookie)
|
||||
|
||||
![][5]
|
||||
|
||||
下面对其进行拆解分析:
|
||||
|
||||
1. 我的浏览器向如下 URL 发送了一个请求;
|
||||
|
||||
```
|
||||
https://www.facebook.com/tr/?id=937725046402747&ev=PageView&dl=https%3A%2F%2Foldnavy.gap.com%2Fbrowse%2Fproduct.do%3Fpid%3D504753002%26cid%3D1125694%26pcid%3Dxxxxxx0%26vid%3D1%26grid%3Dpds_0_109_1%23pdp-page-content&rl=https%3A%2F%2Foldnavy.gap.com%2Fbrowse%2Fcategory.do%3Fcid%3D1135640%26mlink%3D5155%2Cm_mts_a&if=false&ts=1576684838096&sw=1920&sh=1080&v=2.9.15&r=stable&a=tmtealium&ec=0&o=30&fbp=fb.1.1576684798512.1946041422&it=15xxxxxxxxxx4&coo=false&rqm=GET
|
||||
```
|
||||
2. 与该请求同时发送的,还有一个名为 `fr` 的 cookie,取值为
|
||||
|
||||
```
|
||||
10oGXEcKfGekg67iy.AWVdJq5MG3VLYaNjz4MTNRaU1zg.Bd-kxt.KU.F36.0.0.Bd-kx6.
|
||||
```
|
||||
(估计是我的 Facebook 广告追踪 ID)
|
||||
|
||||
在所发送的像素追踪查询字符串里,有三个值得注意的地方:
|
||||
|
||||
* 我当前访问的页面:`https://oldnavy.gap.com/browse/product.do?pid=504753002&cid=1125694&pcid=1135640&vid=1&grid=pds_0_109_1#pdp-page-content`
|
||||
* 引导我来到当前页面的上一级页面:`https://oldnavy.gap.com/browse/category.do?cid=1135640&mlink=5155,m_mts_a`;
|
||||
* 作为我的身份标识的 cookie:`10oGXEcKfGekg67iy.AWVdJq5MG3VLYaNjz4MTNRaU1zg.Bd-kxt.KU.F36.0.0.Bd-kx6.`
|
||||
|
||||
### 下面来逛逛 Facebook!
|
||||
|
||||
下面来逛逛 Facebook 吧。我之前已经登入了 Facebook,猜猜看,我的浏览器发送给 Facebook 的 cookie 是什么?
|
||||
|
||||
不出所料,正是之前见过的 `fr` cookie:`10oGXEcKfGekg67iy.AWVdJq5MG3VLYaNjz4MTNRaU1zg.Bd-kxt.KU.F36.0.0.Bd-kx6.`。Facebook 现在一定知道我(Julia Evans,这个 Facebook 账号所关联的人)在几分钟之前访问了 Old Navy 网站,并且浏览了“男款短绒格子花呢大衣”,因为他们可以使用这个 cookie 将数据串联起来。
|
||||
|
||||
### 这里涉及到的是第三方 cookie
|
||||
|
||||
Facebook 用来追踪我访问了哪些网站的 cookie,属于所谓的“第三方 cookie”,因为 Old Navy 的网站使用它为一个第三方(即 facebook.com)确认我的身份。这和用来维持登录状态的“第一方 cookie”有所不同。
|
||||
|
||||
Safari 和 Firefox 默认都会拦截许多第三方 cookie(所以需要更改 Firefox 的隐私设置,才能够进行这个实验),而 Chrome 目前并不进行拦截(很可能是因为 Chrome 的所有者正是一个广告公司)。(LCTT 译注:Chrome 可以设置阻拦)
|
||||
|
||||
### 网站上的像素追踪有很多
|
||||
|
||||
如我所料,网站上的像素追踪有 **很多**。比如,wrangler.com 在我的浏览器里加载了来自不同域的 19 个不同的像素追踪。wrangler.com 上的像素追踪分别来自:`ct.pinterest.com`、`af.monetate.net`、`csm.va.us.criteo.net`、`google-analytics.com`、`dpm.demdex.net`、`google.ca`、`a.tribalfusion.com`、`data.photorank.me`、`stats.g.doubleclick.net`、`vfcorp.dl.sc.omtrdc.net`、`ib.adnxs.com`、`idsync.rlcdn.com`、`p.brsrvr.com`,以及 `adservice.google.com`。
|
||||
|
||||
Firefox 贴心地指出,如果使用 Firefox 的标准隐私设置,其中的大部分追踪器都会被拦截:
|
||||
|
||||
![][8]
|
||||
|
||||
### 浏览器的重要性
|
||||
|
||||
浏览器之所以如此重要,是因为你的浏览器最终决定了发送你的什么信息、发送到哪些网站。Old Navy 网站上的 Javascript 可以请求你的浏览器向 Facebook 发送关于你的追踪信息,但浏览器可以拒绝执行。浏览器的决定可以是:“哈,我知道 facebook.com/tr/ 是一个像素追踪,我不想让我的用户被追踪,所以我不会发送这个请求”。
|
||||
|
||||
浏览器还可以允许用户对上述行为进行配置,方法包括更改浏览器设置,以及安装浏览器扩展(所以才会有如此多的隐私保护扩展)。
|
||||
|
||||
### 摸清其中原理,实为一件趣事
|
||||
|
||||
在我看来,弄清楚 cookie/像素追踪是怎么用于对你进行追踪的,实在是一件趣事(尽管有点吓人)。我之前大概明白其中的道理,但是并没有亲自查看过像素追踪上的 cookie,也没有看过发送的查询参数上究竟包含什么样的信息。
|
||||
|
||||
当然,明白了其中的原理,也就更容易降低被追踪的概率了。
|
||||
|
||||
### 可以采取的措施
|
||||
|
||||
为了尽量避免在互联网上被追踪,我采取了几种简单的措施:
|
||||
|
||||
* 安装一个广告拦截器(比如 ublock origin 之类)。广告拦截器可以针对许多追踪器的域进行拦截。
|
||||
* 使用目前默认隐私保护强度更高的 Firefox/Safari,而不是 Chrome。
|
||||
* 使用 [Facebook Container][9] 这个 Firefox 扩展。该扩展针对 Facebook 进一步采取了防止追踪的措施。
|
||||
|
||||
虽然在互联网上被追踪的方式还有很多(尤其是在使用手机应用的时候,因为在这种情况下,你没有和像对浏览器一样的控制程度),但是能够理解这种追踪方法的工作原理,稍微减少一些被追踪的可能性,也总归是一件好事。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://jvns.ca/blog/how-tracking-pixels-work/
|
||||
|
||||
作者:[Julia Evans][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chen-ni](https://github.com/chen-ni)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://jvns.ca/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://jvns.ca/images/trackers.png
|
||||
[2]: https://jvns.ca/images/firefox-insecure-settings.png
|
||||
[3]: https://oldnavy.gap.com/browse/product.do?pid=504753002&cid=1125694&pcid=1135640&vid=1&grid=pds_0_109_1
|
||||
[4]: https://developers.facebook.com/docs/facebook-pixel/implementation/
|
||||
[5]: https://jvns.ca/images/fb-old-navy.png
|
||||
[6]: https://oldnavy.gap.com/browse/product.do?pid=504753002&cid=1125694&pcid=1135640&vid=1&grid=pds_0_109_1#pdp-page-content
|
||||
[7]: https://oldnavy.gap.com/browse/category.do?cid=1135640&mlink=5155,m_mts_a
|
||||
[8]: https://jvns.ca/images/firefox-helpful.png
|
||||
[9]: https://addons.mozilla.org/en-CA/firefox/addon/facebook-container/
|
@ -0,0 +1,179 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11722-1.html)
|
||||
[#]: subject: (How to Start, Stop & Restart Services in Ubuntu and Other Linux Distributions)
|
||||
[#]: via: (https://itsfoss.com/start-stop-restart-services-linux/)
|
||||
[#]: author: (Sergiu https://itsfoss.com/author/sergiu/)
|
||||
|
||||
如何在 Ubuntu 和其他 Linux 发行版中启动、停止和重启服务
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/28/081645vee5lkult55kituu.jpg)
|
||||
|
||||
服务是必不可少的后台进程,它通常随系统启动,并在关机时关闭。如果你是系统管理员,那么你会定期处理服务。如果你是普通桌面用户,你可能会遇到需要重启服务的情况,例如[安装 Barrier 来用于在计算机之间共享鼠标和键盘][1]。或[在使用 ufw 设置防火墙][2]时。
|
||||
|
||||
今天,我将向你展示两种管理服务的方式。你将学习在 Ubuntu 或任何其他 Linux 发行版中启动、停止和重启服务。
|
||||
|
||||
> systemd 与 init
|
||||
>
|
||||
> 如今,Ubuntu 和许多其他发行版都使用 systemd 而不是旧的 init。
|
||||
>
|
||||
> 在 systemd 中,可以使用 `systemctl` 命令管理服务。
|
||||
>
|
||||
> 在 init 中,你可以使用 `service` 命令管理服务。
|
||||
>
|
||||
> 你会注意到,即使你的 Linux 系统使用 systemd,它仍然可以使用 `service` 命令(与 init 系统一起使用的)。这是因为 `service` 命令实际上已重定向到 `systemctl`。systemd 引入了向后兼容性,因为系统管理员们习惯使用 `service` 命令。
|
||||
>
|
||||
> 在本教程中,我将同时展示 `systemctl` 和 `service` 命令。
|
||||
|
||||
我用的是 Ubuntu 18.04,但其他版本的过程也一样。
|
||||
|
||||
### 方法 1:使用 systemd 在 Linux 中管理服务
|
||||
|
||||
我从 systemd 开始,因为它被广泛接受。
|
||||
|
||||
#### 1、列出所有服务
|
||||
|
||||
为了管理服务,你首先需要知道系统上有哪些服务可用。你可以使用 systemd 的命令列出 Linux 系统上的所有服务:
|
||||
|
||||
```
|
||||
systemctl list-unit-files --type service -all
|
||||
```
|
||||
|
||||
![systemctl list-unit-files][3]
|
||||
|
||||
此命令将输出所有服务的状态。服务状态有<ruby>启用<rt>enabled</rt></ruby>、<ruby>禁用<rt>disabled</rt></ruby>、<ruby>屏蔽<rt>masked</rt></ruby>(在取消屏蔽之前处于非活动状态)、<ruby>静态<rt>static</rt></ruby>和<ruby>已生成<rt>generated</rt></ruby>。
|
||||
|
||||
与 [grep 命令][4] 结合,你可以仅显示正在运行的服务:
|
||||
|
||||
```
|
||||
sudo systemctl | grep running
|
||||
```
|
||||
|
||||
![Display running services systemctl][5]
|
||||
|
||||
现在,你知道了如何引用所有不同的服务,你可以开始主动管理它们。
|
||||
|
||||
**注意:** 下列命令中的 `<service-name>` 应该用你想管理的服务名代替。(比如:network-manager、ufw 等)
|
||||
|
||||
#### 2、启动服务
|
||||
|
||||
要在 Linux 中启动服务,你只需使用它的名字:
|
||||
|
||||
```
|
||||
systemctl start <service-name>
|
||||
```
|
||||
|
||||
#### 3、停止服务
|
||||
|
||||
要停止 systemd 服务,可以使用 `systemctl` 命令的 `stop` 选项:
|
||||
|
||||
```
|
||||
systemctl stop <service-name>
|
||||
```
|
||||
|
||||
#### 4、重启服务
|
||||
|
||||
要重启 systemd 服务,可以使用:
|
||||
|
||||
```
|
||||
systemctl restart <service-name>
|
||||
```
|
||||
|
||||
#### 5、检查服务状态
|
||||
|
||||
你可以通过打印服务状态来确认你已经成功执行特定操作:
|
||||
|
||||
```
|
||||
systemctl status <service-name>
|
||||
```
|
||||
|
||||
这将以以下方式输出:
|
||||
|
||||
![systemctl status][6]
|
||||
|
||||
这是 systemd 的内容。现在切换到 init。
|
||||
|
||||
### 方法 2:使用 init 在 Linux 中管理服务
|
||||
|
||||
init 的命令和 systemd 的一样简单。
|
||||
|
||||
#### 1、列出所有服务
|
||||
|
||||
要列出所有 Linux 服务,使用:
|
||||
|
||||
```
|
||||
service --status-all
|
||||
```
|
||||
|
||||
![service –status-all][7]
|
||||
|
||||
前面的 `[ – ]` 代表**禁用**,`[ + ]` 代表**启用**。
|
||||
|
||||
#### 2、启动服务
|
||||
|
||||
要在 Ubuntu 和其他发行版中启动服务,使用命令:
|
||||
|
||||
```
|
||||
service <service-name> start
|
||||
```
|
||||
|
||||
#### 3、停止服务
|
||||
|
||||
停止服务同样简单。
|
||||
|
||||
```
|
||||
service <service-name> stop
|
||||
```
|
||||
|
||||
#### 4、重启服务
|
||||
|
||||
如果你想重启服务,命令是:
|
||||
|
||||
```
|
||||
service <service-name> restart
|
||||
```
|
||||
|
||||
#### 5、检查服务状态
|
||||
|
||||
此外,要检查是否达到了预期的结果,你可以输出服务状态:
|
||||
|
||||
```
|
||||
service <service-name> status
|
||||
```
|
||||
|
||||
这将以以下方式输出:
|
||||
|
||||
![service status][8]
|
||||
|
||||
最重要的是,这将告诉你某项服务是否处于活跃状态(正在运行)。
|
||||
|
||||
### 总结
|
||||
|
||||
今天,我详细介绍了两种在 Ubuntu 或任何其他 Linux 系统上管理服务的非常简单的方法。 希望本文对你有所帮助。
|
||||
|
||||
你更喜欢哪种方法? 让我在下面的评论中知道!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/start-stop-restart-services-linux/
|
||||
|
||||
作者:[Sergiu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/sergiu/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/keyboard-mouse-sharing-between-computers/
|
||||
[2]: https://itsfoss.com/set-up-firewall-gufw/
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/systemctl_list_services.png?ssl=1
|
||||
[4]: https://linuxhandbook.com/grep-command-examples/
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/systemctl_grep_running.jpg?ssl=1
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/systemctl_status.jpg?ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/service_status_all.png?ssl=1
|
||||
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/service_status.jpg?ssl=1
|
@ -0,0 +1,70 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11728-1.html)
|
||||
[#]: subject: (Customize your Linux desktop with KDE Plasma)
|
||||
[#]: via: (https://opensource.com/article/19/12/linux-kde-plasma)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 KDE Plasma 定制 Linux 桌面
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。如果你认为没有太多自定义桌面的需要,KDE Plasma 可能适合你。
|
||||
|
||||
![5 pengiuns floating on iceburg][1]
|
||||
|
||||
KDE 社区的 Plasma 桌面是开源桌面环境中的巅峰之作。KDE 很早就进入了 Linux 桌面环境市场,但是由于它的基础 Qt 工具包当时没有完全开放的许可证,因此才有 [GNOME][2] 桌面。在此之后,Qt 开源了,并且 KDE(及其衍生产品,例如 [Trinity 桌面][3])开始蓬勃发展。
|
||||
|
||||
你可能会在发行版的软件仓库中找到 KDE 桌面,或者可以下载并安装将 KDE 作为默认桌面的发行版。在安装之前,请注意,KDE 提供了完整、集成且强大的桌面体验,因此会同时安装几个 KDE 应用。如果你已经在运行其他桌面,那么将发现有几个冗余的应用(两个 PDF 阅读器、多个媒体播放器、两个或多个文件管理器,等等)。如果你只想尝试而不是一直使用 KDE 桌面,那么可以在虚拟机,如 [GNOME Boxes][4] 中安装基于 KDE 的发行版,也可以尝试使用可引导的操作系统,例如 [Porteus][5]。
|
||||
|
||||
### KDE 桌面之旅
|
||||
|
||||
乍一看,[KDE Plasma][6] 桌面相对无聊,但让人感到舒适。它有行业标准的布局:左下角弹出应用菜单,中间是任务栏,右边是系统托盘。这正是你对标准家用或商用计算机的期望。
|
||||
|
||||
![KDE Plasma desktop][7]
|
||||
|
||||
但是,使 KDE 与众不同的是,你几乎可以更改任何想要的东西。Qt 工具包可以以令人惊讶的方式分割和重新排列,这意味着你实质上可以使用 KDE 的部件作为基础来设计自己的桌面。桌面行为的可用设置也很多。KDE 可以充当标准桌面、平铺窗口管理器以及两者之间的任意形式。你可以通过窗口类、角色、类型、标题或它们的任意组合来创建自己的窗口规则,因此,如果希望特定应用的行为不同于其他行为,那么可以创建全局设置的例外。
|
||||
|
||||
此外,它还有丰富的小部件集合,使你可以自定义与桌面交互的方式。它有一个类似 GNOME 的全屏应用启动器,一个类似 Unity 的 dock 启动器和仅有图标的任务栏,以及一个传统的任务栏。你可以在屏幕的任何边缘上创建和放置面板。
|
||||
|
||||
![A slightly customized KDE desktop][8]
|
||||
|
||||
实际上,它有太多的自定义项了,因此 KDE 最常见的批评之一是它的*太过可定制化*,所以请记住,自定义项是可选的。你可以在默认配置下使用 Plasma 桌面,并仅在你认为必要时逐步进行更改。Plasma 桌面配置选项最重要的不是它们的数目,而是它们容易发现和直观,它们都在系统设置应用或者右键单击中。
|
||||
|
||||
事实是,在 KDE 上,几乎绝不会只有一种方法可以完成任何给定的任务,并且它的用户将这个视为其最大的优势。KDE 中没有隐含的工作流,只有默认的。并且可以更改所有默认设置,直到你需要桌面做的成为你的习惯。
|
||||
|
||||
### 一致性和集成
|
||||
|
||||
KDE 社区以一致性和集成为荣,出色的开发人员、社区管理以及 KDE 库使其成为可能。KDE 的开发人员不只是桌面开发人员。它们提供了[惊人的应用集合][9],每个应用都使用 KDE 库创建,这些库扩展并标准化了常见的 Qt 小部件。使用 KDE 几个月后,无论是打开 [DigiKam][10] 进行照片管理,还是打开 Kmail 来检查电子邮件,还是打开 KTorrent 来获取最新的 ISO 或者使用 Dolphin 管理文件,你的肌肉记忆会在你思考之前直接带你进入对应 UI。
|
||||
|
||||
![KDE on Porteus][11]
|
||||
|
||||
### 尝试 KDE
|
||||
|
||||
KDE 适合所有人。使用其默认设置可获得流畅、原始的桌面体验,或对其进行自定义以使其成为自己专属。它是一个稳定、有吸引力且强大的桌面环境,可能有你想要在 Linux 完成要做的事的一切。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/linux-kde-plasma
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003499_01_linux31x_cc.png?itok=Pvim4U-B (5 pengiuns floating on iceburg)
|
||||
[2]: https://opensource.com/article/19/12/gnome-linux-desktop
|
||||
[3]: https://opensource.com/article/19/12/linux-trinity-desktop-environment-tde
|
||||
[4]: https://opensource.com/article/19/5/getting-started-gnome-boxes-virtualization
|
||||
[5]: https://opensource.com/article/19/6/linux-distros-to-try
|
||||
[6]: https://kde.org/plasma-desktop
|
||||
[7]: https://opensource.com/sites/default/files/uploads/advent-kde-presskit.jpg (KDE Plasma desktop)
|
||||
[8]: https://opensource.com/sites/default/files/uploads/advent-kde-dock.jpg (A slightly customized KDE desktop)
|
||||
[9]: https://kde.org/applications/
|
||||
[10]: https://opensource.com/life/16/5/how-use-digikam-photo-management
|
||||
[11]: https://opensource.com/sites/default/files/uploads/advent-kde.jpg (KDE on Porteus)
|
@ -0,0 +1,129 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11726-1.html)
|
||||
[#]: subject: (How to Update Grub on Ubuntu and Other Linux Distributions)
|
||||
[#]: via: (https://itsfoss.com/update-grub/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
如何在 Ubuntu 和其它 Linux 发行版上更新 grub
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/29/110155d51bhogs5ezp5p71.png)
|
||||
|
||||
在这篇文章中,你将学习在 Ubuntu 或任何其它 Linux 发行版上更新 grub 。你也将学习一个或两个关于更新这个 grub 过程如何工作的事情。
|
||||
|
||||
### 如何更新 grub
|
||||
|
||||
Ubuntu 和很多其它的 Linux 发行版提供一个易使用的称为 `update-grub` 命令行实用程序。
|
||||
|
||||
为更新 grub ,你所要的全部工作就是使用 `sudo` 在终端中运行这个命令。
|
||||
|
||||
```
|
||||
sudo update-grub
|
||||
```
|
||||
|
||||
你应该看到一个像这样的输出:
|
||||
|
||||
```
|
||||
[email protected]:~$ sudo update-grub
|
||||
[sudo] password for abhishek:
|
||||
Sourcing file `/etc/default/grub'
|
||||
Generating grub configuration file ...
|
||||
Found linux image: /boot/vmlinuz-5.0.0-37-generic
|
||||
Found initrd image: /boot/initrd.img-5.0.0-37-generic
|
||||
Found linux image: /boot/vmlinuz-5.0.0-36-generic
|
||||
Found initrd image: /boot/initrd.img-5.0.0-36-generic
|
||||
Found linux image: /boot/vmlinuz-5.0.0-31-generic
|
||||
Found initrd image: /boot/initrd.img-5.0.0-31-generic
|
||||
Found Ubuntu 19.10 (19.10) on /dev/sda4
|
||||
Found MX 19 patito feo (19) on /dev/sdb1
|
||||
Adding boot menu entry for EFI firmware configuration
|
||||
done
|
||||
```
|
||||
|
||||
你可能看到一个类似的称为 `update-grub2` 的命令。不需要在 `update-grub` 和 `update-grub2` 之间感到害怕或不知所措。这两个命令执行相同的动作。
|
||||
|
||||
大约在 10 年前,当 grub2 刚刚被引进时,`update-grub2` 命令也被引进。现在,`update-grub2` 只是一个链接到 `update-grub` 的符号,它们都更新 grub2 配置(因为 grub2 是默认的)。
|
||||
|
||||
#### 不能找到 update-grub 命令?这里是在这种情况下该做什么
|
||||
|
||||
它可能是,你的 Linux 发行版可能没有可用的 `update-grub` 命令。
|
||||
|
||||
在这种情况下你该做什么?你如何在这样一个 Linux 发行版上更新 grub ?
|
||||
|
||||
在这里不需要惊慌。`update-grub` 命令只是一个入口,用于运行 `grub-mkconfig -o /boot/grub/grub.cfg` 来生成 grub2 配置文件。
|
||||
|
||||
这意味着你可以在任意 Linux 发行版上使用下面的命令更新 grub :
|
||||
|
||||
```
|
||||
sudo grub-mkconfig -o /boot/grub/grub.cfg
|
||||
```
|
||||
|
||||
当然,记住 `update-grub` 命令比上面的命令容易很多,这是为什么它在一开始被创建的原因。
|
||||
|
||||
### update-grub 是如何工作的?
|
||||
|
||||
当你安装一个 Linux 发行版时,它(通常)要求你安装 [grub 启动引导程序][1]。
|
||||
|
||||
grub 的一部分安装在 MBR/ESP 分区上。grub 的剩余部分保留在 Linux 发行版的 `/boot/grub` 目录中。
|
||||
|
||||
依据它的 [man 页面][2],`update-grub` 通过查找 `/boot` 目录来工作。所有以 [vmlinuz-][3] 开头的文件将被作为内核来对待,并且它们将得到一个 grub 菜单项。它也将为与所找到内核版本相同的 [ramdisk][4] 镜像添加 initrd 行。
|
||||
|
||||
它也使用 [os-prober][5] 为其它操作系统查找所有磁盘分区。如果找到其它操作系统,它添加它们到 grub 菜单。
|
||||
|
||||
![Representational image of Grub Menu][6]
|
||||
|
||||
### 为什么你需要更新 grub ?
|
||||
|
||||
在有很多场景下你需要更新 grub。
|
||||
|
||||
假设你修改 grub 配置文件(`/etc/default/grub`)以 [更改默认启动顺序][7] 或减少默认启动时间。除非你更新 grub ,否则你的修改将不会生效。
|
||||
|
||||
另一种情况是,你在同一个电脑系统上安装多个 Linux 发行版。
|
||||
|
||||
例如,在我的 Intel NUC 上,我有两个磁盘。第一个磁盘有 Ubuntu 19.10 ,并且我在其上面安装了 Ubuntu 18.04 。第二个操作系统(Ubuntu 18.04)安装了其自己的 grub ,现在 grub 启动屏幕由 Ubuntu 18.04 grub 控制。
|
||||
|
||||
在第二个磁盘上,我安装了 MX Linux ,但是这次我没有安装 grub。我希望现有的 grub(由 Ubuntu 18.04 控制)来处理所有的操作系统项目。
|
||||
|
||||
现在,在这种情况中,在 Ubuntu 18.04 上的 grub 需要更新,以便它能够看到 [MX Linux][8] 。
|
||||
|
||||
![][9]
|
||||
|
||||
如上图所示,当我更新 grub 时,它在 18.04 上找到很多安装的 Linux 内核, 以及在不同的分区上 Ubntu 19.10 和 MX Linux 。
|
||||
|
||||
如果你想让 MX Linux 控制 grub ,我可以使用 [grub-install][10] 命令来在 MX Linux 上安装 grub,然后在 MX Linux 上的 grub 将开始控制 grub 启动屏幕。你已经明白这点,对吧?
|
||||
|
||||
使用一个像 [Grub Customizer][11] 的 GUI 工具是在 grub 中进行更改的一种简单的方法。
|
||||
|
||||
### 最后…
|
||||
|
||||
最初,我打算保持它为一篇短文作为一种快速提示。但是后来我想解释一些与之相关的东西,以便(相对)新的 Linux 用户能够学到更多,而不仅仅是一个简单命令。
|
||||
|
||||
你喜欢它吗?你有一些问题或建议吗?请随意发表评论。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/update-grub/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/GNU_GRUB
|
||||
[2]: https://manpages.debian.org/testing/grub-legacy/update-grub.8.en.html
|
||||
[3]: https://www.ibm.com/developerworks/community/blogs/mhhaque/entry/anatomy_of_the_initrd_and_vmlinuz?lang=en
|
||||
[4]: https://en.wikipedia.org/wiki/Initial_ramdisk
|
||||
[5]: https://packages.debian.org/sid/utils/os-prober
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/grub_screen.png?ssl=1
|
||||
[7]: https://itsfoss.com/grub-customizer-ubuntu/
|
||||
[8]: https://mxlinux.org/
|
||||
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/update_grub.png?ssl=1
|
||||
[10]: https://www.gnu.org/software/grub/manual/grub/html_node/Installing-GRUB-using-grub_002dinstall.html
|
||||
[11]: https://itsfoss.com/customize-grub-linux/
|
@ -0,0 +1,69 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11718-1.html)
|
||||
[#]: subject: (Why your Python code needs to be beautiful and explicit)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-beauty-clarity)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
为什么 Python 代码要写得美观而明确
|
||||
======
|
||||
|
||||
> 欢迎阅读“Python 光明节(Pythonukkah)”系列文章,这个系列文章将会讨论《Python 之禅》。我们首先来看《Python 之禅》里的前两个原则:美观与明确。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/27/091634drq96c2fojzp6okr.png)
|
||||
|
||||
早在 1999 年,Python 的贡献者之一,Tim Peters 就提出了《[Python 之禅][2]》,直到二十年后的今天,《Python 之禅》中的 19 条原则仍然对整个社区都产生着深远的影响。为此,就像庆典光明的<ruby>光明节<rt>Hanukkah</rt></ruby>一样,我们举行了这一次的“<ruby>Python 光明节<rt>Pythonukkah</rt></ruby>”。首先,我们会讨论《Python 之禅》中的前两个原则:美观和明确。
|
||||
|
||||
> “Hanukkah is the Festival of Lights,
|
||||
>
|
||||
> Instead of one day of presents, we get eight crazy nights.”
|
||||
>
|
||||
> —亚当·桑德勒,[光明节之歌][3]
|
||||
|
||||
### 美观胜于丑陋
|
||||
|
||||
著名的《[<ruby>计算机程序的构造和解释<rt>Structure and Interpretation of Computer Programs</rt></ruby>][4]》中有这么一句话:<ruby>代码是写给人看的,只是恰好能让机器运行。<rt>Programs must be written for people to read and only incidentally for machines to execute.</rt></ruby>机器并不在乎代码的美观性,但人类在乎。
|
||||
|
||||
阅读美观的代码对人们来说是一种享受,这就要求在整套代码中保持一致的风格。使用诸如 [Black][5]、[flake8][6]、[Pylint][7] 这一类工具能够有效地接近这一个目标。
|
||||
|
||||
但实际上,只有人类自己才知道什么才是真正的美观。因此,代码审查和协同开发是其中的不二法门,同时,在开发过程中倾听别人的意见也是必不可少的。
|
||||
|
||||
最后,个人的主观能动性也很重要,否则一切工具和流程都会变得毫无意义。只有意识到美观的重要性,才能主动编写出美观的代码。
|
||||
|
||||
这就是为什么美观在众多原则当中排到了首位,它让“美”成为了 Python 社区的一种价值。如果有人要问,”我们*真的*在乎美吗?“社区会以代码给出肯定的答案。
|
||||
|
||||
### 明确胜于隐晦
|
||||
|
||||
人类会欢庆光明、惧怕黑暗,那是因为光能够让我们看到难以看清的事物。同样地,尽管有些时候我们会不自觉地把代码写得含糊不清,但明确地编写代码确实能够让我们理解很多抽象的概念。
|
||||
|
||||
“为什么类方法中要将 `self` 显式指定为第一个参数?”
|
||||
|
||||
这个问题已经是老生常谈了,但网络上很多流传已久的回答都是不准确的。在编写<ruby>元类<rt>metaclass</rt></ruby>时,显式指定 `self` 参数就显得毫无意义。如果你没有编写过元类,希望你可以尝试一下,这是很多 Python 程序员的必经之路。
|
||||
|
||||
显式指定 `self` 参数的原因并不是 Python 的设计者不想将这样的元类视为“默认”元类,而是因为第一个参数必须是*显式*的。
|
||||
|
||||
即使 Python 中确实允许非显式的情况存在(例如上下文变量),但我们还是应该提出疑问:某个东西是不是有存在的必要呢?如果非显式地传递参数会不会出现问题呢?有些时候,由于种种原因,这是会有问题的。总之,在写代码时一旦能够优先考虑到明确性,至少意味着能对不明确的地方提出疑问并对结果作出有效的估计。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/zen-python-beauty-clarity
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/search_find_code_python_programming.png?itok=ynSL8XRV "Searching for code"
|
||||
[2]: https://www.python.org/dev/peps/pep-0020/
|
||||
[3]: https://en.wikipedia.org/wiki/The_Chanukah_Song
|
||||
[4]: https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs
|
||||
[5]: https://opensource.com/article/19/5/python-black
|
||||
[6]: https://opensource.com/article/19/5/python-flake8
|
||||
[7]: https://opensource.com/article/19/10/python-pylint-introduction
|
||||
|
@ -0,0 +1,113 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11732-1.html)
|
||||
[#]: subject: (App Highlight: Falkon Open Source Web Browser from KDE)
|
||||
[#]: via: (https://itsfoss.com/falkon-browser/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
应用推荐:来自 KDE 的 Falkon 开源 Web 浏览器
|
||||
======
|
||||
|
||||
> Falkon 是基于 QtWebEngine 的 Web 浏览器,它以前称为 Qupzilla。在本周的“应用推荐”中,我们来看看这个开源软件。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/31/105027tblfjlzn9xx8keud.png)
|
||||
|
||||
### Falkon:适用于 Linux(和 Windows)的开源 Web 浏览器
|
||||
|
||||
![][1]
|
||||
|
||||
首先,[Falkon][2] 并不是一款新的 Web 浏览器。它自 2010 年以来一直在开发中,但被称为 Qupzilla。2017 年,QupZilla 移到 KDE 旗下,并更名为 Falkon。处于 KDE 旗下意味着项目会按照 KDE 标准积极维护。
|
||||
|
||||
它使用 [QtWebEngine][3] 渲染引擎,这是 Chromium 核心的简化版本。
|
||||
|
||||
在本文中,我将仔细研究它提供的功能以及与 Linux 上其他主流 Web 浏览器的不同之处。
|
||||
|
||||
### Falkon 浏览器的功能
|
||||
|
||||
我认为它可能不是流行的浏览器,但我发现它足以浏览现代 Web 服务。让我重点介绍 Falkon 的主要功能,如果你觉得它很有趣,请尝试一下。
|
||||
|
||||
#### 简单的用户界面
|
||||
|
||||
![][4]
|
||||
|
||||
我知道这不完全是一项“功能”,但是用户体验(UX)至关重要。尽管是轻量级的浏览器,但你会拥有一个不错的界面。你不会觉得使用的是一款源自 2000 年早期的浏览器。
|
||||
|
||||
#### AdBlock 扩展
|
||||
|
||||
![][5]
|
||||
|
||||
它附带了 AdBlock 扩展程序,如果你想在浏览网站时摆脱广告,它的效果很好。你还可以自定义 AdBlock 扩展的行为。
|
||||
|
||||
#### DuckDuckGo 作为默认搜索引擎
|
||||
|
||||
如果你不喜欢使用 Google,那么这是一件好事,它将这个[主打隐私的搜索引擎][6]设为默认搜索引擎。
|
||||
|
||||
#### 会话管理器
|
||||
|
||||
![][7]
|
||||
|
||||
Falkon 在浏览器菜单的可用选项中包含了一个有用的会话管理器。你可以用它还原特定的近期会话,这应该能派上用场。
|
||||
|
||||
#### 扩展支持
|
||||
|
||||
![][8]
|
||||
|
||||
它确实支持添加扩展,但你不能从 Chrome/Firefox 插件市场添加扩展。你只能选择有限的一组扩展。
|
||||
|
||||
#### 主题支持
|
||||
|
||||
Falkon 还允许你在某种程度上自定义外观。如果要更改浏览器的外观,可以尝试一下。
|
||||
|
||||
![][9]
|
||||
|
||||
#### 其他基本设置
|
||||
|
||||
![][10]
|
||||
|
||||
我还尝试了其他设置/功能,例如添加书签或管理密码。或者,管理网页的通知。我还试了 YouTube,没有任何问题。
|
||||
|
||||
当然,这不是一个详尽的评测。但是,Falkon 确实拥有浏览器中需要的所有基本功能(除非你有特定要求)。
|
||||
|
||||
### 安装 Falkon 浏览器
|
||||
|
||||
你可以在软件中心轻松找到 Falkon 浏览器。如果没有,你可以从它的[官方下载页面][11]中找到 Flatpak/Snap 包。你还可以在下载页面上找到 Windows 的安装程序。
|
||||
|
||||
[Download Falkon Browser][11]
|
||||
|
||||
### 总结
|
||||
|
||||
作为 KDE 产品,Falkon 是为 KDE 桌面环境量身定制的。一些 KDE 发行版(例如 OpenMandriva)使用 Falkon 作为默认的 Web 浏览器。
|
||||
|
||||
Falkon 浏览器适合那些正在寻求轻巧且功能丰富的 Web 浏览器的人。值得尝试的另一个替代是 [Midori][12]。
|
||||
|
||||
我认为,除非你需要大量的扩展、跨平台同步并且需要访问某些特定于浏览器的网站,不然它是一个很好的替代浏览器。
|
||||
|
||||
你如何看待 Falkon 浏览器?请在下面的评论中让我知道你的想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/falkon-browser/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-browser-screenshot.jpg?ssl=1
|
||||
[2]: https://www.falkon.org/
|
||||
[3]: https://wiki.qt.io/QtWebEngine
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-browser.png?ssl=1
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-adblock.jpg?ssl=1
|
||||
[6]: https://itsfoss.com/privacy-search-engines/
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/session-manager-falkon.jpg?ssl=1
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-browser-extensions.png?ssl=1
|
||||
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-browser-theme.png?ssl=1
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/falkon-browser-preference.png?ssl=1
|
||||
[11]: https://www.falkon.org/download/
|
||||
[12]: https://itsfoss.com/midori-browser/
|
@ -0,0 +1,116 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11724-1.html)
|
||||
[#]: subject: (Unix is turning 50. What does that mean?)
|
||||
[#]: via: (https://www.networkworld.com/article/3511428/unix-is-turning-50-what-does-that-mean.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
Unix 即将迎来 50 岁
|
||||
======
|
||||
|
||||
Unix 时间(又称为“<ruby>纪元时间<rt>epoch time</rt></ruby>”)是自 1970 年 1 月 1 日以来经过的秒数。当 Unix 即将 50 岁时,让我们看一下让内核开发人员担心的地方。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/28/120311hzghpxux1hp5t4xo.jpg)
|
||||
|
||||
对于 Unix 而言,2020 年是重要的一年。在这一年年初,Unix 进入 50 岁。
|
||||
|
||||
尽管 Unix 的某些早期开发早于其“纪元”的正式开始,但 1970 年 1 月 1 日仍然是 POSIX 时间的零点,也是公认的 Unix 的万物之始。自那一刻算起,2020 年 1 月 1 日将是其 50 周年。(LCTT 译注:实际上,在 1971/11/3 出版的第一版《Unix 程序员手册》中,将 1971/1/1 作为 Unix 纪元的开始,并且一秒钟记录 60 个数,但是后来发现这样 32 位整型数字只能记录两年多,后来这个纪元被一再重新定义,改为从 1970/1/1 开始,每秒 1 个数。)
|
||||
|
||||
### Unix 时间与人类时间
|
||||
|
||||
就人类时间而言,50 年是很重要的。就 Unix 时间而言,50 年没有什么特别的。48.7 年同样重要。
|
||||
|
||||
Unix(包括 Linux)系统将日期/时间值存储为自 1970-01-01 00:00:00 UTC 以来经过的秒数(32 位整型)。要确定自该时间以来经过了多少秒钟,看看 Unix 时间值是什么样子,你可以发出如下命令:
|
||||
|
||||
```
|
||||
$ date +%s
|
||||
1576883876
|
||||
```
|
||||
|
||||
`%s` 参数告诉 `date` 命令将当前日期/时间显示为自 1970-01-01 开始以来的秒数。
|
||||
|
||||
### Unix 系统可以管理多少时间?
|
||||
|
||||
要了解 Unix 系统可以容纳多少时间,我们需要查看 32 位字段的容量。可以这样计算:
|
||||
|
||||
```
|
||||
$ echo '2^32' | bc
|
||||
4294967296
|
||||
```
|
||||
|
||||
但是,由于 Unix 需要容纳负数,因此它会为数字的符号保留一位,从而将其减少为:
|
||||
|
||||
```
|
||||
$ echo '2^31' | bc
|
||||
2147483648
|
||||
```
|
||||
|
||||
并且,由于 Unix 计数以 0 开头,这意味着我们有 2,147,483,648 个值,但最大的可能值为 2,147,483,647 个。Unix 日期/时间值不能超过该数字——就像汽车上的里程表可能不能超过 999,999 英里一样。加 1 该值就变为了 -2147483648。(LCTT 译注:此处原文描述有误,已修改。在达到最大值之后,即 2038/1/19 03:14:07,下 1 秒导致符号位变为 1,其余 31 位为 0,即 -2147483648,时间变为 1901/12/13 20:45:52,这就是 Y2K38 问题。)
|
||||
|
||||
### 一年有多少秒?
|
||||
|
||||
大多数年份的秒数可以这样计算:每天的小时数乘以每小时的分钟数乘以每分钟的秒数乘以一年中的天数:
|
||||
|
||||
```
|
||||
$ expr 24 \* 60 \* 60 \* 365
|
||||
31536000
|
||||
```
|
||||
|
||||
在闰年,我们再增加一天:
|
||||
|
||||
```
|
||||
$ expr 24 \* 60 \* 60 \* 366
|
||||
31622400
|
||||
```
|
||||
|
||||
(LCTT 译注:Unix 时间将一天精确定义为 24 * 60 * 60 = 86400 秒,忽略闰秒。)
|
||||
|
||||
### Unix 将如何庆祝其 50 岁生日?
|
||||
|
||||
2020 年 1 月 1 日中午 12:00 是纪元时间的 1577836800。这个计算有些棘手,但主要是因为我们必须适应闰年。自该纪元开始以来,我们经历了 12 个闰年,从 1972 年开始,到上一个闰年是 2016 年。而且,当我们达到 2020 年时,我们将有 38 个常规年份。
|
||||
|
||||
这是使用 `expr` 命令进行的计算,以计算这 50 年的秒数:
|
||||
|
||||
```
|
||||
$ expr 24 \* 60 \* 60 \* 365 \* 38 + 24 \* 60 \* 60 \* 366 \* 12
|
||||
1577836800
|
||||
```
|
||||
|
||||
前半部分是计算 38 个非闰年的秒数。然后,我们加上闰年的 366 天的类似计算。或者,你可以使用前面介绍的每年秒数,然后执行以下操作:
|
||||
|
||||
```
|
||||
$ expr 31536000 \* 38 + 31622400 \* 12
|
||||
1577836800
|
||||
```
|
||||
|
||||
这种跟踪日期和时间的方式使 Unix 系统完全不受 Y2K 恐慌的影响,1999 年末人们开始担心进入 2000 年会对计算机系统造成严重破坏,但是实际遇到的问题比人们担心的少得多。实际上,只有以两位数格式存储年份的应用程序才会将年份变为 00,以表示时间倒退。尽管如此,许多应用程序开发人员还是做了很多额外的繁琐工作,以确保 2000 年到来时,他们的系统不会出现严重问题。
|
||||
|
||||
### Unix 时间何时会遇到问题?
|
||||
|
||||
在 2038 年之前,Unix 系统不会遇到 Y2K 类型的问题,直到如上所述存储的日期将超过其 32 位空间分配。但这距离现在已经只有 18 年了,内核开发人员已经在研究如何避免灾难。但现在开始恐慌还为时过早。
|
||||
|
||||
2038 年的问题有时称为 Y2K38 问题。我们必须在 2038 年 1 月 19 日星期二之前解决这个问题。如果问题到时候仍未解决,则该日期之后的系统可能会认为是 1901 年。解决该问题的一种方法是切换为日期/时间信息的 64 位表示形式。有些人认为,即使那样,也会有比听起来更复杂的问题。无论如何,恐慌还为时过早。并且,与此同时,也许在新年前夜演唱了《Auld Lang Syne》之后,你可以向 Unix 唱《生日快乐》歌了。Unix 50 岁了,这仍然是大事。
|
||||
|
||||
(LCTT 译注:建议阅读一下 Unix 时间的[维基百科][6]页面,有更多有趣和不为人知的信息。)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3511428/unix-is-turning-50-what-does-that-mean.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][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/Sandra-Henry_Stocker/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://images.idgesg.net/images/article/2017/10/birthday-cake-candles-100739452-large.jpg
|
||||
[2]: https://creativecommons.org/publicdomain/zero/1.0/
|
||||
[3]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE20773&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[4]: https://www.facebook.com/NetworkWorld/
|
||||
[5]: https://www.linkedin.com/company/network-world
|
||||
[6]: https://en.wikipedia.org/wiki/Unix_time
|
504
published/20191205 Add jumping to your Python platformer game.md
Normal file
504
published/20191205 Add jumping to your Python platformer game.md
Normal file
@ -0,0 +1,504 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (cycoe)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11790-1.html)
|
||||
[#]: subject: (Add jumping to your Python platformer game)
|
||||
[#]: via: (https://opensource.com/article/19/12/jumping-python-platformer-game)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
为你的 Python 平台类游戏添加跳跃功能
|
||||
======
|
||||
|
||||
> 在本期使用 Python Pygame 模块编写视频游戏中,学会如何使用跳跃来对抗重力。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/16/214917c8mxn82fot82fx88.jpg)
|
||||
|
||||
在本系列的 [前一篇文章][2] 中,你已经模拟了重力。但现在,你需要赋予你的角色跳跃的能力来对抗重力。
|
||||
|
||||
跳跃是对重力作用的暂时延缓。在这一小段时间里,你是向*上*跳,而不是被重力拉着向下落。但你一旦到达了跳跃的最高点,重力就会重新发挥作用,将你拉回地面。
|
||||
|
||||
在代码中,这种变化被表示为变量。首先,你需要为玩家精灵建立一个变量,使得 Python 能够跟踪该精灵是否正在跳跃中。一旦玩家精灵开始跳跃,他就会再次受到重力的作用,并被拉回最近的物体。
|
||||
|
||||
### 设置跳跃状态变量
|
||||
|
||||
你需要为你的 `Player` 类添加两个新变量:
|
||||
|
||||
* 一个是为了跟踪你的角色是否正在跳跃中,可通过你的玩家精灵是否站在坚实的地面来确定
|
||||
* 一个是为了将玩家带回地面
|
||||
|
||||
将如下两个变量添加到你的 `Player` 类中。在下方的代码中,注释前的部分用于提示上下文,因此只需要添加最后两行:
|
||||
|
||||
```
|
||||
self.movex = 0
|
||||
self.movey = 0
|
||||
self.frame = 0
|
||||
self.health = 10
|
||||
# 此处是重力相关变量
|
||||
self.collide_delta = 0
|
||||
self.jump_delta = 6
|
||||
```
|
||||
|
||||
第一个变量 `collide_delta` 被设为 0 是因为在正常状态下,玩家精灵没有处在跳跃中的状态。另一个变量 `jump_delta` 被设为 6,是为了防止精灵在第一次进入游戏世界时就发生反弹(实际上就是跳跃)。当你完成了本篇文章的示例,尝试把该变量设为 0 看看会发生什么。
|
||||
|
||||
### 跳跃中的碰撞
|
||||
|
||||
如果你是跳到一个蹦床上,那你的跳跃一定非常优美。但是如果你是跳向一面墙会发生什么呢?(千万不要去尝试!)不管你的起跳多么令人印象深刻,当你撞到比你更大更硬的物体时,你都会立马停下。(LCTT 译注:原理参考动量守恒定律)
|
||||
|
||||
为了在你的视频游戏中模拟这一点,你需要在你的玩家精灵与地面等东西发生碰撞时,将 `self.collide_delta` 变量设为 0。如果你的 `self.collide_delta` 不是 0 而是其它的什么值,那么你的玩家就会发生跳跃,并且当你的玩家与墙或者地面发生碰撞时无法跳跃。
|
||||
|
||||
在你的 `Player` 类的 `update` 方法中,将地面碰撞相关代码块修改为如下所示:
|
||||
|
||||
```
|
||||
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
|
||||
for g in ground_hit_list:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty-ty
|
||||
self.collide_delta = 0 # 停止跳跃
|
||||
if self.rect.y > g.rect.y:
|
||||
self.health -=1
|
||||
print(self.health)
|
||||
```
|
||||
|
||||
这段代码块检查了地面精灵和玩家精灵之间发生的碰撞。当发生碰撞时,它会将玩家 Y 方向的坐标值设置为游戏窗口的高度减去一个瓷砖的高度再减去另一个瓷砖的高度。以此保证了玩家精灵是站在地面*上*,而不是嵌在地面里。同时它也将 `self.collide_delta` 设为 0,使得程序能够知道玩家未处在跳跃中。除此之外,它将 `self.movey` 设为 0,使得程序能够知道玩家当前未受到重力的牵引作用(这是游戏物理引擎的奇怪之处,一旦玩家落地,也就没有必要继续将玩家拉向地面)。
|
||||
|
||||
此处 `if` 语句用来检测玩家是否已经落到地面之*下*,如果是,那就扣除一点生命值作为惩罚。此处假定了你希望当你的玩家落到地图之外时失去生命值。这个设定不是必需的,它只是平台类游戏的一种惯例。更有可能的是,你希望这个事件能够触发另一些事件,或者说是一种能够让你的现实世界玩家沉迷于让精灵掉到屏幕之外的东西。一种简单的恢复方式是在玩家精灵掉落到地图之外时,将 `self.rect.y` 重新设置为 0,这样它就会在地图上方重新生成,并落到坚实的地面上。
|
||||
|
||||
### 撞向地面
|
||||
|
||||
模拟的重力使你玩家的 Y 坐标不断增大(LCTT 译注:此处原文中为 0,但在 Pygame 中越靠下方 Y 坐标应越大)。要实现跳跃,完成如下代码使你的玩家精灵离开地面,飞向空中。
|
||||
|
||||
在你的 `Player` 类的 `update` 方法中,添加如下代码来暂时延缓重力的作用:
|
||||
|
||||
```
|
||||
if self.collide_delta < 6 and self.jump_delta < 6:
|
||||
self.jump_delta = 6*2
|
||||
self.movey -= 33 # 跳跃的高度
|
||||
self.collide_delta += 6
|
||||
self.jump_delta += 6
|
||||
```
|
||||
|
||||
根据此代码所示,跳跃使玩家精灵向空中移动了 33 个像素。此处是*负* 33 是因为在 Pygame 中,越小的数代表距离屏幕顶端越近。
|
||||
|
||||
不过此事件视条件而定,只有当 `self.collide_delta` 小于 6(缺省值定义在你 `Player` 类的 `init` 方法中)并且 `self.jump_delta` 也于 6 的时候才会发生。此条件能够保证直到玩家碰到一个平台,才能触发另一次跳跃。换言之,它能够阻止空中二段跳。
|
||||
|
||||
在某些特殊条件下,你可能不想阻止空中二段跳,或者说你允许玩家进行空中二段跳。举个栗子,如果玩家获得了某个战利品,那么在他被敌人攻击到之前,都能够拥有空中二段跳的能力。
|
||||
|
||||
当你完成本篇文章中的示例,尝试将 `self.collide_delta` 和 `self.jump_delta` 设置为 0,从而获得百分之百的几率触发空中二段跳。
|
||||
|
||||
### 在平台上着陆
|
||||
|
||||
目前你已经定义了在玩家精灵摔落地面时的抵抗重力条件,但此时你的游戏代码仍保持平台与地面置于不同的列表中(就像本文中做的很多其他选择一样,这个设定并不是必需的,你可以尝试将地面作为另一种平台)。为了允许玩家精灵站在平台之上,你必须像检测地面碰撞一样,检测玩家精灵与平台精灵之间的碰撞。将如下代码放于你的 `update` 方法中:
|
||||
|
||||
```
|
||||
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
|
||||
for p in plat_hit_list:
|
||||
self.collide_delta = 0 # 跳跃结束
|
||||
self.movey = 0
|
||||
```
|
||||
|
||||
但此处还有一点需要考虑:平台悬在空中,也就意味着玩家可以通过从上面或者从下面接触平台来与之互动。
|
||||
|
||||
确定平台如何与玩家互动取决于你,阻止玩家从下方到达平台也并不稀奇。将如下代码加到上方的代码块中,使得平台表现得像天花板或者说是藤架。只有在玩家精灵跳得比平台上沿更高时才能跳到平台上,但会阻止玩家从平台下方跳上来:
|
||||
|
||||
```
|
||||
if self.rect.y > p.rect.y:
|
||||
self.rect.y = p.rect.y+ty
|
||||
else:
|
||||
self.rect.y = p.rect.y-ty
|
||||
```
|
||||
|
||||
此处 `if` 语句代码块的第一个子句阻止玩家精灵从平台正下方跳到平台上。如果它检测到玩家精灵的坐标比平台更大(在 Pygame 中,坐标更大意味着在屏幕的更下方),那么将玩家精灵新的 Y 坐标设置为当前平台的 Y 坐标加上一个瓷砖的高度。实际效果就是保证玩家精灵距离平台一个瓷砖的高度,防止其从下方穿过平台。
|
||||
|
||||
`else` 子句做了相反的事情。当程序运行到此处时,如果玩家精灵的 Y 坐标*不*比平台的更大,意味着玩家精灵是从空中落下(不论是由于玩家刚刚从此处生成,或者是玩家执行了跳跃)。在这种情况下,玩家精灵的 Y 坐标被设为平台的 Y 坐标减去一个瓷砖的高度(切记,在 Pygame 中更小的 Y 坐标代表在屏幕上的更高处)。这样就能保证玩家在平台*上*,除非他从平台上跳下来或者走下来。
|
||||
|
||||
你也可以尝试其他的方式来处理玩家与平台之间的互动。举个栗子,也许玩家精灵被设定为处在平台的“前面”,他能够无障碍地跳跃穿过平台并站在上面。或者你可以设计一种平台会减缓而又不完全阻止玩家的跳跃过程。甚至你可以通过将不同平台分到不同列表中来混合搭配使用。
|
||||
|
||||
### 触发一次跳跃
|
||||
|
||||
目前为此,你的代码已经模拟了所有必需的跳跃条件,但仍缺少一个跳跃触发器。你的玩家精灵的 `self.jump_delta` 初始值被设置为 6,只有当它比 6 小的时候才会触发更新跳跃的代码。
|
||||
|
||||
为跳跃变量设置一个新的设置方法,在你的 `Player` 类中创建一个 `jump` 方法,并将 `self.jump_delta` 设为小于 6 的值。通过使玩家精灵向空中移动 33 个像素,来暂时减缓重力的作用。
|
||||
|
||||
|
||||
```
|
||||
def jump(self,platform_list):
|
||||
self.jump_delta = 0
|
||||
```
|
||||
|
||||
不管你相信与否,这就是 `jump` 方法的全部。剩余的部分在 `update` 方法中,你已经在前面实现了相关代码。
|
||||
|
||||
要使你游戏中的跳跃功能生效,还有最后一件事情要做。如果你想不起来是什么,运行游戏并观察跳跃是如何生效的。
|
||||
|
||||
问题就在于你的主循环中没有调用 `jump` 方法。先前你已经为该方法创建了一个按键占位符,现在,跳跃键所做的就是将 `jump` 打印到终端。
|
||||
|
||||
### 调用 jump 方法
|
||||
|
||||
在你的主循环中,将*上*方向键的效果从打印一条调试语句,改为调用 `jump` 方法。
|
||||
|
||||
注意此处,与 `update` 方法类似,`jump` 方法也需要检测碰撞,因此你需要告诉它使用哪个 `plat_list`。
|
||||
|
||||
```
|
||||
if event.key == pygame.K_UP or event.key == ord('w'):
|
||||
player.jump(plat_list)
|
||||
```
|
||||
|
||||
如果你倾向于使用空格键作为跳跃键,使用 `pygame.K_SPACE` 替代 `pygame.K_UP` 作为按键。另一种选择,你可以同时使用两种方式(使用单独的 `if` 语句),给玩家多一种选择。
|
||||
|
||||
现在来尝试你的游戏吧!在下一篇文章中,你将让你的游戏卷动起来。
|
||||
|
||||
![Pygame 平台类游戏][3]
|
||||
|
||||
以下是目前为止的所有代码:
|
||||
|
||||
```
|
||||
#!/usr/bin/env python3
|
||||
# draw a world
|
||||
# add a player and player control
|
||||
# add player movement
|
||||
# add enemy and basic collision
|
||||
# add platform
|
||||
# add gravity
|
||||
# add jumping
|
||||
|
||||
# GNU All-Permissive License
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# are permitted in any medium without royalty provided the copyright
|
||||
# notice and this notice are preserved. This file is offered as-is,
|
||||
# without any warranty.
|
||||
|
||||
import pygame
|
||||
import sys
|
||||
import os
|
||||
|
||||
'''
|
||||
Objects
|
||||
'''
|
||||
|
||||
class Platform(pygame.sprite.Sprite):
|
||||
# x 坐标,y 坐标,图像宽度,图像高度,图像文件
|
||||
def __init__(self,xloc,yloc,imgw,imgh,img):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.image = pygame.image.load(os.path.join('images',img)).convert()
|
||||
self.image.convert_alpha()
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.y = yloc
|
||||
self.rect.x = xloc
|
||||
|
||||
class Player(pygame.sprite.Sprite):
|
||||
'''
|
||||
生成一个玩家
|
||||
'''
|
||||
def __init__(self):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.movex = 0
|
||||
self.movey = 0
|
||||
self.frame = 0
|
||||
self.health = 10
|
||||
self.collide_delta = 0
|
||||
self.jump_delta = 6
|
||||
self.score = 1
|
||||
self.images = []
|
||||
for i in range(1,9):
|
||||
img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
|
||||
img.convert_alpha()
|
||||
img.set_colorkey(ALPHA)
|
||||
self.images.append(img)
|
||||
self.image = self.images[0]
|
||||
self.rect = self.image.get_rect()
|
||||
|
||||
def jump(self,platform_list):
|
||||
self.jump_delta = 0
|
||||
|
||||
def gravity(self):
|
||||
self.movey += 3.2 # how fast player falls
|
||||
|
||||
if self.rect.y > worldy and self.movey >= 0:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty
|
||||
|
||||
def control(self,x,y):
|
||||
'''
|
||||
控制玩家移动
|
||||
'''
|
||||
self.movex += x
|
||||
self.movey += y
|
||||
|
||||
def update(self):
|
||||
'''
|
||||
更新精灵位置
|
||||
'''
|
||||
|
||||
self.rect.x = self.rect.x + self.movex
|
||||
self.rect.y = self.rect.y + self.movey
|
||||
|
||||
# 向左移动
|
||||
if self.movex < 0:
|
||||
self.frame += 1
|
||||
if self.frame > ani*3:
|
||||
self.frame = 0
|
||||
self.image = self.images[self.frame//ani]
|
||||
|
||||
# 向右移动
|
||||
if self.movex > 0:
|
||||
self.frame += 1
|
||||
if self.frame > ani*3:
|
||||
self.frame = 0
|
||||
self.image = self.images[(self.frame//ani)+4]
|
||||
|
||||
# 碰撞
|
||||
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
|
||||
for enemy in enemy_hit_list:
|
||||
self.health -= 1
|
||||
#print(self.health)
|
||||
|
||||
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
|
||||
for p in plat_hit_list:
|
||||
self.collide_delta = 0 # stop jumping
|
||||
self.movey = 0
|
||||
if self.rect.y > p.rect.y:
|
||||
self.rect.y = p.rect.y+ty
|
||||
else:
|
||||
self.rect.y = p.rect.y-ty
|
||||
|
||||
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
|
||||
for g in ground_hit_list:
|
||||
self.movey = 0
|
||||
self.rect.y = worldy-ty-ty
|
||||
self.collide_delta = 0 # stop jumping
|
||||
if self.rect.y > g.rect.y:
|
||||
self.health -=1
|
||||
print(self.health)
|
||||
|
||||
if self.collide_delta < 6 and self.jump_delta < 6:
|
||||
self.jump_delta = 6*2
|
||||
self.movey -= 33 # how high to jump
|
||||
self.collide_delta += 6
|
||||
self.jump_delta += 6
|
||||
|
||||
class Enemy(pygame.sprite.Sprite):
|
||||
'''
|
||||
生成一个敌人
|
||||
'''
|
||||
def __init__(self,x,y,img):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.image = pygame.image.load(os.path.join('images',img))
|
||||
self.movey = 0
|
||||
#self.image.convert_alpha()
|
||||
#self.image.set_colorkey(ALPHA)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = x
|
||||
self.rect.y = y
|
||||
self.counter = 0
|
||||
|
||||
|
||||
def move(self):
|
||||
'''
|
||||
敌人移动
|
||||
'''
|
||||
distance = 80
|
||||
speed = 8
|
||||
|
||||
self.movey += 3.2
|
||||
|
||||
if self.counter >= 0 and self.counter <= distance:
|
||||
self.rect.x += speed
|
||||
elif self.counter >= distance and self.counter <= distance*2:
|
||||
self.rect.x -= speed
|
||||
else:
|
||||
self.counter = 0
|
||||
|
||||
self.counter += 1
|
||||
|
||||
if not self.rect.y >= worldy-ty-ty:
|
||||
self.rect.y += self.movey
|
||||
|
||||
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
|
||||
for p in plat_hit_list:
|
||||
self.movey = 0
|
||||
if self.rect.y > p.rect.y:
|
||||
self.rect.y = p.rect.y+ty
|
||||
else:
|
||||
self.rect.y = p.rect.y-ty
|
||||
|
||||
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
|
||||
for g in ground_hit_list:
|
||||
self.rect.y = worldy-ty-ty
|
||||
|
||||
|
||||
class Level():
|
||||
def bad(lvl,eloc):
|
||||
if lvl == 1:
|
||||
enemy = Enemy(eloc[0],eloc[1],'yeti.png') # 生成敌人
|
||||
enemy_list = pygame.sprite.Group() # 创建敌人组
|
||||
enemy_list.add(enemy) # 将敌人添加到敌人组
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return enemy_list
|
||||
|
||||
def loot(lvl,lloc):
|
||||
print(lvl)
|
||||
|
||||
def ground(lvl,gloc,tx,ty):
|
||||
ground_list = pygame.sprite.Group()
|
||||
i=0
|
||||
if lvl == 1:
|
||||
while i < len(gloc):
|
||||
ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
|
||||
ground_list.add(ground)
|
||||
i=i+1
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return ground_list
|
||||
|
||||
def platform(lvl,tx,ty):
|
||||
plat_list = pygame.sprite.Group()
|
||||
ploc = []
|
||||
i=0
|
||||
if lvl == 1:
|
||||
ploc.append((0,worldy-ty-128,3))
|
||||
ploc.append((300,worldy-ty-256,3))
|
||||
ploc.append((500,worldy-ty-128,4))
|
||||
|
||||
while i < len(ploc):
|
||||
j=0
|
||||
while j <= ploc[i][2]:
|
||||
plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
|
||||
plat_list.add(plat)
|
||||
j=j+1
|
||||
print('run' + str(i) + str(ploc[i]))
|
||||
i=i+1
|
||||
|
||||
if lvl == 2:
|
||||
print("Level " + str(lvl) )
|
||||
|
||||
return plat_list
|
||||
|
||||
'''
|
||||
Setup
|
||||
'''
|
||||
worldx = 960
|
||||
worldy = 720
|
||||
|
||||
fps = 40 # 帧率
|
||||
ani = 4 # 动画循环
|
||||
clock = pygame.time.Clock()
|
||||
pygame.init()
|
||||
main = True
|
||||
|
||||
BLUE = (25,25,200)
|
||||
BLACK = (23,23,23 )
|
||||
WHITE = (254,254,254)
|
||||
ALPHA = (0,255,0)
|
||||
|
||||
world = pygame.display.set_mode([worldx,worldy])
|
||||
backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()
|
||||
backdropbox = world.get_rect()
|
||||
player = Player() # 生成玩家
|
||||
player.rect.x = 0
|
||||
player.rect.y = 0
|
||||
player_list = pygame.sprite.Group()
|
||||
player_list.add(player)
|
||||
steps = 10 # how fast to move
|
||||
jump = -24
|
||||
|
||||
eloc = []
|
||||
eloc = [200,20]
|
||||
gloc = []
|
||||
#gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]
|
||||
tx = 64 # 瓷砖尺寸
|
||||
ty = 64 # 瓷砖尺寸
|
||||
|
||||
i=0
|
||||
while i <= (worldx/tx)+tx:
|
||||
gloc.append(i*tx)
|
||||
i=i+1
|
||||
|
||||
enemy_list = Level.bad( 1, eloc )
|
||||
ground_list = Level.ground( 1,gloc,tx,ty )
|
||||
plat_list = Level.platform( 1,tx,ty )
|
||||
|
||||
'''
|
||||
主循环
|
||||
'''
|
||||
while main == True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit(); sys.exit()
|
||||
main = False
|
||||
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_LEFT or event.key == ord('a'):
|
||||
print("LEFT")
|
||||
player.control(-steps,0)
|
||||
if event.key == pygame.K_RIGHT or event.key == ord('d'):
|
||||
print("RIGHT")
|
||||
player.control(steps,0)
|
||||
if event.key == pygame.K_UP or event.key == ord('w'):
|
||||
print('jump')
|
||||
|
||||
if event.type == pygame.KEYUP:
|
||||
if event.key == pygame.K_LEFT or event.key == ord('a'):
|
||||
player.control(steps,0)
|
||||
if event.key == pygame.K_RIGHT or event.key == ord('d'):
|
||||
player.control(-steps,0)
|
||||
if event.key == pygame.K_UP or event.key == ord('w'):
|
||||
player.jump(plat_list)
|
||||
|
||||
if event.key == ord('q'):
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
main = False
|
||||
|
||||
# world.fill(BLACK)
|
||||
world.blit(backdrop, backdropbox)
|
||||
player.gravity() # 检查重力
|
||||
player.update()
|
||||
player_list.draw(world) # 刷新玩家位置
|
||||
enemy_list.draw(world) # 刷新敌人
|
||||
ground_list.draw(world) # 刷新地面
|
||||
plat_list.draw(world) # 刷新平台
|
||||
for e in enemy_list:
|
||||
e.move()
|
||||
pygame.display.flip()
|
||||
clock.tick(fps)
|
||||
```
|
||||
|
||||
本期是使用 [Pygame][5] 模块在 [Python 3][4] 中创建视频游戏连载系列的第 7 期。往期文章为:
|
||||
|
||||
* [通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程][6]
|
||||
* [使用 Python 和 Pygame 模块构建一个游戏框架][7]
|
||||
* [如何在你的 Python 游戏中添加一个玩家][8]
|
||||
* [用 Pygame 使你的游戏角色移动起来][9]
|
||||
* [如何向你的 Python 游戏中添加一个敌人][10]
|
||||
* [在 Pygame 游戏中放置平台][11]
|
||||
* [在你的 Python 游戏中模拟引力][2]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/jumping-python-platformer-game
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[cycoe](https://github.com/cycoe)
|
||||
校对:[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/arcade_game_gaming.jpg?itok=84Rjk_32 (Arcade games)
|
||||
[2]: https://linux.cn/article-11780-1.html
|
||||
[3]: https://opensource.com/sites/default/files/uploads/pygame-jump.jpg (Pygame platformer)
|
||||
[4]: https://www.python.org/
|
||||
[5]: https://www.pygame.org/
|
||||
[6]: https://linux.cn/article-9071-1.html
|
||||
[7]: https://linux.cn/article-10850-1.html
|
||||
[8]: https://linux.cn/article-10858-1.html
|
||||
[9]: https://linux.cn/article-10874-1.html
|
||||
[10]: https://linux.cn/article-10883-1.html
|
||||
[11]: https://linux.cn/article-10902-1.html
|
320
published/20191210 Lessons learned from programming in Go.md
Normal file
320
published/20191210 Lessons learned from programming in Go.md
Normal file
@ -0,0 +1,320 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11778-1.html)
|
||||
[#]: subject: (Lessons learned from programming in Go)
|
||||
[#]: via: (https://opensource.com/article/19/12/go-common-pitfalls)
|
||||
[#]: author: (Eduardo Ferreira https://opensource.com/users/edufgf)
|
||||
|
||||
Go 并发编程中的经验教训
|
||||
======
|
||||
|
||||
> 通过学习如何定位并发处理的陷阱来避免未来处理这些问题时的困境。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/13/150539n217ak1vcf717uzx.jpg)
|
||||
|
||||
在复杂的分布式系统进行任务处理时,你通常会需要进行并发的操作。在 [Mode.net][2] 公司,我们每天都要和实时、快速和灵活的软件打交道。而没有一个高度并发的系统,就不可能构建一个毫秒级的动态地路由数据包的全球专用网络。这个动态路由是基于网络状态的,尽管这个过程需要考虑众多因素,但我们的重点是链路指标。在我们的环境中,链路指标可以是任何跟网络链接的状态和当前属性(如链接延迟)有关的任何内容。
|
||||
|
||||
### 并发探测链接监控
|
||||
|
||||
我们的动态路由算法 [H.A.L.O.][4](<ruby>逐跳自适应链路状态最佳路由<rt>Hop-by-Hop Adaptive Link-State Optimal Routing</rt></ruby>)部分依赖于链路指标来计算路由表。这些指标由位于每个 PoP(<ruby>存活节点<rt>Point of Presence</rt></ruby>)上的独立组件收集。PoP 是表示我们的网络中单个路由实体的机器,通过链路连接并分布在我们的网络拓扑中的各个位置。某个组件使用网络数据包探测周围的机器,周围的机器回复数据包给前者。从接收到的探测包中可以获得链路延迟。由于每个 PoP 都有不止一个临近节点,所以这种探测任务实质上是并发的:我们需要实时测量每个临近连接点的延迟。我们不能串行地处理;为了计算这个指标,必须尽快处理每个探测。
|
||||
|
||||
![latency computation graph][6]
|
||||
|
||||
### 序列号和重置:一个重新排列场景
|
||||
|
||||
我们的探测组件互相发送和接收数据包,并依靠序列号进行数据包处理。这旨在避免处理重复的包或顺序被打乱的包。我们的第一个实现依靠特殊的序列号 0 来重置序列号。这个数字仅在组件初始化时使用。主要的问题是我们考虑了递增的序列号总是从 0 开始。在该组件重启后,包的顺序可能会重新排列,某个包的序列号可能会轻易地被替换成重置之前使用过的值。这意味着,后继的包都会被忽略掉,直到排到重置之前用到的序列值。
|
||||
|
||||
### UDP 握手和有限状态机
|
||||
|
||||
这里的问题是该组件重启前后的序列号是否一致。有几种方法可以解决这个问题,经过讨论,我们选择了实现一个带有清晰状态定义的三步握手协议。这个握手过程在初始化时通过链接建立会话。这样可以确保节点通过同一个会话进行通信且使用了适当的序列号。
|
||||
|
||||
为了正确实现这个过程,我们必须定义一个有清晰状态和过渡的有限状态机。这样我们就可以正确管理握手过程中的所有极端情况。
|
||||
|
||||
![finite state machine diagram][7]
|
||||
|
||||
会话 ID 由握手的初始化程序生成。一个完整的交换顺序如下:
|
||||
|
||||
1. 发送者发送一个 `SYN(ID)` 数据包。
|
||||
2. 接收者存储接收到的 `ID` 并发送一个 `SYN-ACK(ID)`。
|
||||
3. 发送者接收到 `SYN-ACK(ID)` 并发送一个 `ACK(ID)`。它还发送一个从序列号 0 开始的数据包。
|
||||
4. 接收者检查最后接收到的 `ID`,如果 ID 匹配,则接受 `ACK(ID)`。它还开始接受序列号为 0 的数据包。
|
||||
|
||||
### 处理状态超时
|
||||
|
||||
基本上,每种状态下你都需要处理最多三种类型的事件:链接事件、数据包事件和超时事件。这些事件会并发地出现,因此你必须正确处理并发。
|
||||
|
||||
* 链接事件包括网络连接或网络断开的变化,相应的初始化一个链接会话或断开一个已建立的会话。
|
||||
* 数据包事件是控制数据包(`SYN`/`SYN-ACK`/`ACK`)或只是探测响应。
|
||||
* 超时事件在当前会话状态的预定超时时间到期后触发。
|
||||
|
||||
这里面临的最主要的问题是如何处理并发的超时到期和其他事件。这里很容易陷入死锁和资源竞争的陷阱。
|
||||
|
||||
### 第一种方法
|
||||
|
||||
本项目使用的语言是 [Golang][8]。它确实提供了原生的同步机制,如自带的通道和锁,并且能够使用轻量级线程来进行并发处理。
|
||||
|
||||
![gophers hacking together][9]
|
||||
|
||||
*gopher 们聚众狂欢*
|
||||
|
||||
首先,你可以设计两个分别表示我们的会话和超时处理程序的结构体。
|
||||
|
||||
```go
|
||||
type Session struct {
|
||||
State SessionState
|
||||
Id SessionId
|
||||
RemoteIp string
|
||||
}
|
||||
|
||||
type TimeoutHandler struct {
|
||||
callback func(Session)
|
||||
session Session
|
||||
duration int
|
||||
timer *timer.Timer
|
||||
}
|
||||
```
|
||||
|
||||
`Session` 标识连接会话,内有表示会话 ID、临近的连接点的 IP 和当前会话状态的字段。
|
||||
|
||||
`TimeoutHandler` 包含回调函数、对应的会话、持续时间和指向调度计时器的指针。
|
||||
|
||||
每一个临近连接点的会话都包含一个保存调度 `TimeoutHandler` 的全局映射。
|
||||
|
||||
```
|
||||
SessionTimeout map[Session]*TimeoutHandler
|
||||
```
|
||||
|
||||
下面方法注册和取消超时:
|
||||
|
||||
```go
|
||||
// schedules the timeout callback function.
|
||||
func (timeout* TimeoutHandler) Register() {
|
||||
timeout.timer = time.AfterFunc(time.Duration(timeout.duration) * time.Second, func() {
|
||||
timeout.callback(timeout.session)
|
||||
})
|
||||
}
|
||||
|
||||
func (timeout* TimeoutHandler) Cancel() {
|
||||
if timeout.timer == nil {
|
||||
return
|
||||
}
|
||||
timeout.timer.Stop()
|
||||
}
|
||||
```
|
||||
|
||||
你可以使用类似下面的方法来创建和存储超时:
|
||||
|
||||
```go
|
||||
func CreateTimeoutHandler(callback func(Session), session Session, duration int) *TimeoutHandler {
|
||||
if sessionTimeout[session] == nil {
|
||||
sessionTimeout[session] := new(TimeoutHandler)
|
||||
}
|
||||
|
||||
timeout = sessionTimeout[session]
|
||||
timeout.session = session
|
||||
timeout.callback = callback
|
||||
timeout.duration = duration
|
||||
return timeout
|
||||
}
|
||||
```
|
||||
|
||||
超时处理程序创建后,会在经过了设置的 `duration` 时间(秒)后执行回调函数。然而,有些事件会使你重新调度一个超时处理程序(与 `SYN` 状态时的处理一样,每 3 秒一次)。
|
||||
|
||||
为此,你可以让回调函数重新调度一次超时:
|
||||
|
||||
```go
|
||||
func synCallback(session Session) {
|
||||
sendSynPacket(session)
|
||||
|
||||
// reschedules the same callback.
|
||||
newTimeout := NewTimeoutHandler(synCallback, session, SYN_TIMEOUT_DURATION)
|
||||
newTimeout.Register()
|
||||
|
||||
sessionTimeout[state] = newTimeout
|
||||
}
|
||||
```
|
||||
|
||||
这次回调在新的超时处理程序中重新调度自己,并更新全局映射 `sessionTimeout`。
|
||||
|
||||
### 数据竞争和引用
|
||||
|
||||
你的解决方案已经有了。可以通过检查计时器到期后超时回调是否执行来进行一个简单的测试。为此,注册一个超时,休眠 `duration` 秒,然后检查是否执行了回调的处理。执行这个测试后,最好取消预定的超时时间(因为它会重新调度),这样才不会在下次测试时产生副作用。
|
||||
|
||||
令人惊讶的是,这个简单的测试发现了这个解决方案中的一个问题。使用 `cancel` 方法来取消超时并没有正确处理。以下顺序的事件会导致数据资源竞争:
|
||||
|
||||
1. 你有一个已调度的超时处理程序。
|
||||
2. 线程 1:
|
||||
1. 你接收到一个控制数据包,现在你要取消已注册的超时并切换到下一个会话状态(如发送 `SYN` 后接收到一个 `SYN-ACK`)
|
||||
2. 你调用了 `timeout.Cancel()`,这个函数调用了 `timer.Stop()`。(请注意,Golang 计时器的停止不会终止一个已过期的计时器。)
|
||||
3. 线程 2:
|
||||
1. 在取消调用之前,计时器已过期,回调即将执行。
|
||||
2. 执行回调,它调度一次新的超时并更新全局映射。
|
||||
4. 线程 1:
|
||||
1. 切换到新的会话状态并注册新的超时,更新全局映射。
|
||||
|
||||
两个线程并发地更新超时映射。最终结果是你无法取消注册的超时,然后你也会丢失对线程 2 重新调度的超时的引用。这导致处理程序在一段时间内持续执行和重新调度,出现非预期行为。
|
||||
|
||||
### 锁也解决不了问题
|
||||
|
||||
使用锁也不能完全解决问题。如果你在处理所有事件和执行回调之前加锁,它仍然不能阻止一个过期的回调运行:
|
||||
|
||||
```go
|
||||
func (timeout* TimeoutHandler) Register() {
|
||||
timeout.timer = time.AfterFunc(time.Duration(timeout.duration) * time._Second_, func() {
|
||||
stateLock.Lock()
|
||||
defer stateLock.Unlock()
|
||||
|
||||
timeout.callback(timeout.session)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
现在的区别就是全局映射的更新是同步的,但是这还是不能阻止在你调用 `timeout.Cancel()` 后回调的执行 —— 这种情况出现在调度计时器过期了但是还没有拿到锁的时候。你还是会丢失一个已注册的超时的引用。
|
||||
|
||||
### 使用取消通道
|
||||
|
||||
你可以使用取消通道,而不必依赖不能阻止到期的计时器执行的 golang 函数 `timer.Stop()`。
|
||||
|
||||
这是一个略有不同的方法。现在你可以不用再通过回调进行递归地重新调度;而是注册一个死循环,这个循环接收到取消信号或超时事件时终止。
|
||||
|
||||
新的 `Register()` 产生一个新的 go 线程,这个线程在超时后执行你的回调,并在前一个超时执行后调度新的超时。返回给调用方一个取消通道,用来控制循环的终止。
|
||||
|
||||
```go
|
||||
func (timeout *TimeoutHandler) Register() chan struct{} {
|
||||
cancelChan := make(chan struct{})
|
||||
|
||||
go func () {
|
||||
select {
|
||||
case _ = <- cancelChan:
|
||||
return
|
||||
case _ = <- time.AfterFunc(time.Duration(timeout.duration) * time.Second):
|
||||
func () {
|
||||
stateLock.Lock()
|
||||
defer stateLock.Unlock()
|
||||
|
||||
timeout.callback(timeout.session)
|
||||
} ()
|
||||
}
|
||||
} ()
|
||||
|
||||
return cancelChan
|
||||
}
|
||||
|
||||
func (timeout* TimeoutHandler) Cancel() {
|
||||
if timeout.cancelChan == nil {
|
||||
return
|
||||
}
|
||||
timeout.cancelChan <- struct{}{}
|
||||
}
|
||||
```
|
||||
|
||||
这个方法给你注册的所有超时提供了取消通道。一个取消调用向通道发送一个空结构体并触发取消操作。然而,这并不能解决前面的问题;可能在你通过通道取消之前以及超时线程拿到锁之前,超时时间就已经到了。
|
||||
|
||||
这里的解决方案是,在拿到锁**之后**,检查一下超时范围内的取消通道。
|
||||
|
||||
```go
|
||||
case _ = <- time.AfterFunc(time.Duration(timeout.duration) * time.Second):
|
||||
func () {
|
||||
stateLock.Lock()
|
||||
defer stateLock.Unlock()
|
||||
|
||||
select {
|
||||
case _ = <- handler.cancelChan:
|
||||
return
|
||||
default:
|
||||
timeout.callback(timeout.session)
|
||||
}
|
||||
} ()
|
||||
}
|
||||
```
|
||||
|
||||
最终,这可以确保在拿到锁之后执行回调,不会触发取消操作。
|
||||
|
||||
### 小心死锁
|
||||
|
||||
这个解决方案看起来有效;但是还是有个隐患:[死锁][10]。
|
||||
|
||||
请阅读上面的代码,试着自己找到它。考虑下描述的所有函数的并发调用。
|
||||
|
||||
这里的问题在取消通道本身。我们创建的是无缓冲通道,即发送的是阻塞调用。当你在一个超时处理程序中调用取消函数时,只有在该处理程序被取消后才能继续处理。问题出现在,当你有多个调用请求到同一个取消通道时,这时一个取消请求只被处理一次。当多个事件同时取消同一个超时处理程序时,如连接断开或控制包事件,很容易出现这种情况。这会导致死锁,可能会使应用程序停机。
|
||||
|
||||
![gophers on a wire, talking][11]
|
||||
|
||||
*有人在听吗?*
|
||||
|
||||
(已获得 Trevor Forrey 授权。)
|
||||
|
||||
这里的解决方案是创建通道时指定缓存大小至少为 1,这样向通道发送数据就不会阻塞,也显式地使发送变成非阻塞的,避免了并发调用。这样可以确保取消操作只发送一次,并且不会阻塞后续的取消调用。
|
||||
|
||||
```go
|
||||
func (timeout* TimeoutHandler) Cancel() {
|
||||
if timeout.cancelChan == nil {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case timeout.cancelChan <- struct{}{}:
|
||||
default:
|
||||
// can’t send on the channel, someone has already requested the cancellation.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
在实践中你学到了并发操作时出现的常见错误。由于其不确定性,即使进行大量的测试,也不容易发现这些问题。下面是我们在最初的实现中遇到的三个主要问题:
|
||||
|
||||
#### 在非同步的情况下更新共享数据
|
||||
|
||||
这似乎是个很明显的问题,但如果并发更新发生在不同的位置,就很难发现。结果就是数据竞争,由于一个更新会覆盖另一个,因此对同一数据的多次更新中会有某些更新丢失。在我们的案例中,我们是在同时更新同一个共享映射里的调度超时引用。(有趣的是,如果 Go 检测到在同一个映射对象上的并发读写,会抛出致命错误 — 你可以尝试下运行 Go 的[数据竞争检测器](https://golang.org/doc/articles/race_detector.html))。这最终会导致丢失超时引用,且无法取消给定的超时。当有必要时,永远不要忘记使用锁。
|
||||
|
||||
![gopher assembly line][13]
|
||||
|
||||
*不要忘记同步 gopher 们的工作*
|
||||
|
||||
#### 缺少条件检查
|
||||
|
||||
在不能仅依赖锁的独占性的情况下,就需要进行条件检查。我们遇到的场景稍微有点不一样,但是核心思想跟[条件变量][14]是一样的。假设有个一个生产者和多个消费者使用一个共享队列的经典场景,生产者可以将一个元素添加到队列并唤醒所有消费者。这个唤醒调用意味着队列中的数据是可访问的,并且由于队列是共享的,消费者必须通过锁来进行同步访问。每个消费者都可能拿到锁;然而,你仍然需要检查队列中是否有元素。因为在你拿到锁的瞬间并不知道队列的状态,所以还是需要进行条件检查。
|
||||
|
||||
在我们的例子中,超时处理程序收到了计时器到期时发出的“唤醒”调用,但是它仍需要检查是否已向其发送了取消信号,然后才能继续执行回调。
|
||||
|
||||
![gopher boot camp][15]
|
||||
|
||||
*如果你要唤醒多个 gopher,可能就需要进行条件检查*
|
||||
|
||||
#### 死锁
|
||||
|
||||
当一个线程被卡住,无限期地等待一个唤醒信号,但是这个信号永远不会到达时,就会发生这种情况。死锁可以通过让你的整个程序停机来彻底杀死你的应用。
|
||||
|
||||
在我们的案例中,这种情况的发生是由于多次发送请求到一个非缓冲且阻塞的通道。这意味着向通道发送数据只有在从这个通道接收完数据后才能返回。我们的超时线程循环迅速从取消通道接收信号;然而,在接收到第一个信号后,它将跳出循环,并且再也不会从这个通道读取数据。其他的调用会一直被卡住。为避免这种情况,你需要仔细检查代码,谨慎处理阻塞调用,并确保不会发生线程饥饿。我们例子中的解决方法是使取消调用成为非阻塞调用 — 我们不需要阻塞调用。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/go-common-pitfalls
|
||||
|
||||
作者:[Eduardo Ferreira][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/edufgf
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/go-golang.png?itok=OAW9BXny (Goland gopher illustration)
|
||||
[2]: http://mode.net
|
||||
[3]: https://en.wikipedia.org/wiki/Metrics_%28networking%29
|
||||
[4]: https://people.ece.cornell.edu/atang/pub/15/HALO_ToN.pdf
|
||||
[5]: https://en.wikipedia.org/wiki/Point_of_presence
|
||||
[6]: https://opensource.com/sites/default/files/uploads/image2_0_3.png (latency computation graph)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/image3_0.png (finite state machine diagram)
|
||||
[8]: https://golang.org/
|
||||
[9]: https://opensource.com/sites/default/files/uploads/image4.png (gophers hacking together)
|
||||
[10]: https://en.wikipedia.org/wiki/Deadlock
|
||||
[11]: https://opensource.com/sites/default/files/uploads/image5_0_0.jpg (gophers on a wire, talking)
|
||||
[12]: https://golang.org/doc/articles/race_detector.html
|
||||
[13]: https://opensource.com/sites/default/files/uploads/image6.jpeg (gopher assembly line)
|
||||
[14]: https://en.wikipedia.org/wiki/Monitor_%28synchronization%29#Condition_variables
|
||||
[15]: https://opensource.com/sites/default/files/uploads/image7.png (gopher boot camp)
|
@ -0,0 +1,128 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11776-1.html)
|
||||
[#]: subject: (Make VLC More Awesome With These Simple Tips)
|
||||
[#]: via: (https://itsfoss.com/simple-vlc-tips/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
这些简单的技巧使 VLC 更加出色
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/13/090635eu9va9999rr4ue92.jpeg)
|
||||
|
||||
如果 [VLC][1] 不是最好的播放器,那它也是[最好的开源视频播放器][2]之一。大多数人不知道的是,它不仅仅是视频播放器。
|
||||
|
||||
你可以进行许多复杂的任务,如直播视频、捕捉设备等。只需打开菜单,你就可以看到它有多少选项。
|
||||
|
||||
我们有一个详细的教程,讨论一些[专业的 VLC 技巧][3],但这些对于普通用户太复杂。
|
||||
|
||||
这就是为什么我要写另一篇文章的原因,来向你展示一些可以在 VLC 中使用的简单技巧。
|
||||
|
||||
### 使用这些简单技巧让 VLC 做更多事
|
||||
|
||||
让我们看看除了播放视频文件之外,你还可以使用 VLC 做什么。
|
||||
|
||||
#### 1、使用 VLC 观看 YouTube 视频
|
||||
|
||||
![][4]
|
||||
|
||||
如果你不想在 [YouTube][5] 上观看令人讨厌的广告,或者只想体验没有打扰地观看 YouTube 视频,你可以使用 VLC。
|
||||
|
||||
是的,在 VLC 上流式传输 YouTube 视频是非常容易的。
|
||||
|
||||
只需启动 VLC 播放器,前往媒体设置,然后单击 ”Open Network Stream“ 或使用快捷方式 `CTRL + N`。
|
||||
|
||||
![][6]
|
||||
|
||||
接下来,你只需要粘贴要观看的视频的 URL。有一些选项可以调整,但通常你无需担心这些。如果你好奇,你可以点击 ”Advanced options“ 来探索。
|
||||
|
||||
你还可以通过这种方式向 YouTube 视频添加字幕。然而,[一个更简单的带字幕观看 Youtube 视频的办法是使用 Penguin 字幕播放器][7]。
|
||||
|
||||
#### 2、将视频转换为不同格式
|
||||
|
||||
![][8]
|
||||
|
||||
你可以[在 Linux 命令行使用 ffmpeg 转换视频][9]。你还可以使用图形工具,如 [HandBrake 转换视频格式][10]。
|
||||
|
||||
但是,如果你不想用一个单独的应用来转码视频,你可以使用 VLC 播放器来完成该工作。
|
||||
|
||||
为此,只需点击 VLC 上的媒体选项,然后单击 “Convert/Save”,或者在 VLC 播放器处于活动状态时按下快捷键 `CTRL + R`。接下来,你需要从计算机/硬盘或者 URL 导入你想保存/转换的的视频。
|
||||
|
||||
不管是什么来源,只需选择文件后点击 “Convert/Save” 按钮。你现在会看到另外一个窗口可以更改 “Profile” 设置。点击并选择你想转换的格式(并保存)。
|
||||
|
||||
你还可以在转换之前通过在屏幕底部设置目标文件夹来更改转换文件的存储路径。
|
||||
|
||||
#### 3、从源录制音频/视频
|
||||
|
||||
![Vlc Advanced Controls][11]
|
||||
|
||||
你是否想在 VLC 播放器中录制正在播放的音频/视频?
|
||||
|
||||
如果是的话,有一个简单的解决方案。只需通过 “View”,然后点击 “Advanced Controls”。
|
||||
|
||||
完成后,你会看到一个新按钮(包括 VLC 播放器中的红色录制按钮)。
|
||||
|
||||
#### 4、自动下载字幕
|
||||
|
||||
![][12]
|
||||
|
||||
是的,你可以[使用 VLC 自动下载字幕][13]。你甚至不必在单独的网站上查找字幕。你只需点击
|
||||
“View”->“VLSub”。
|
||||
|
||||
默认情况下,它是禁用的,因此当你单击该选项时,它会被激活,并允许你搜索/下载想要的字幕。
|
||||
|
||||
[VLC 还能让你使用简单的键盘快捷键同步字幕][14]
|
||||
|
||||
#### 5、截图
|
||||
|
||||
![][15]
|
||||
|
||||
你可以在观看视频时使用 VLC 获取一些视频的截图/图像。你只需在视频播放/暂停时右击播放器,你会看到一组选项,点击 “Video”->“Take Snapshot”。
|
||||
|
||||
如果安装了旧版本,你可能在右键时看到截图选项。
|
||||
|
||||
#### 额外技巧:给视频添加音频/视频效果
|
||||
|
||||
在菜单中,进入 “Tools” 选项。单击 “Effects and Filters”,或者在 VLC 播放器窗口中按 `CTRL + E` 打开选项。
|
||||
|
||||
好了,你可以观察你给视频添加的音频和视频效果了。你也许无法实时看到效果,因此你需要调整并保存来看发生了什么。
|
||||
|
||||
![][16]
|
||||
|
||||
我建议在修改视频之前保存一份原始视频备份。
|
||||
|
||||
#### 你最喜欢的 VLC 技巧是什么?
|
||||
|
||||
我分享了一些我最喜欢的 VLC 技巧。你知道什么你经常使用的很酷的 VLC 技巧吗?为什么不和我们分享呢?我可以把它添加到列表中。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/simple-vlc-tips/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.videolan.org/
|
||||
[2]: https://itsfoss.com/video-players-linux/
|
||||
[3]: https://itsfoss.com/vlc-pro-tricks-linux/
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/youtube-video-stream.jpg?ssl=1
|
||||
[5]: https://www.youtube.com/
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/youtube-video-play.jpg?ssl=1
|
||||
[7]: https://itsfoss.com/penguin-subtitle-player/
|
||||
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc-video-convert.jpg?ssl=1
|
||||
[9]: https://itsfoss.com/ffmpeg/
|
||||
[10]: https://itsfoss.com/handbrake/
|
||||
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc-advanced-controls.png?ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc-subtitles-automatic.png?ssl=1
|
||||
[13]: https://itsfoss.com/download-subtitles-automatically-vlc-media-player-ubuntu/
|
||||
[14]: https://itsfoss.com/how-to-synchronize-subtitles-with-movie-quick-tip/
|
||||
[15]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc-snapshot.png?ssl=1
|
||||
[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc-effects-screenshot.jpg?ssl=1
|
139
published/20191215 How to Add Border Around Text in GIMP.md
Normal file
139
published/20191215 How to Add Border Around Text in GIMP.md
Normal file
@ -0,0 +1,139 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11799-1.html)
|
||||
[#]: subject: (How to Add Border Around Text in GIMP)
|
||||
[#]: via: (https://itsfoss.com/gimp-text-outline/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
在 GIMP 中如何在文本周围添加边框
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/19/230506fzkyktqglfcyzkuh.jpg)
|
||||
|
||||
这个简单的教程介绍了在 [GIMP][1] 中显示文本的轮廓的步骤。文本轮廓可以帮助你在其它颜色下高亮显示该文本。
|
||||
|
||||
![Outlined Text created in GIMP][2]
|
||||
|
||||
让我们看看如何在你的文本周围添加一个边框。
|
||||
|
||||
### 在 GIMP 中添加文本轮廓
|
||||
|
||||
整个过程可以用这些简单的步骤描述:
|
||||
|
||||
* 创建文本,并复制它的轮廓路径
|
||||
* 添加一层新的透明层,并添加轮廓路径到透明层中
|
||||
* 更改轮廓的大小,给它添加一种不同的颜色
|
||||
|
||||
这就是全部的东西。不用担心,我将使用适当地截图详细的展示每个步骤。按照这个教程,你应该能够为文本添加轮廓,即使你在此之前从未使用过 GIMP 。
|
||||
|
||||
仅需要确保你已经 [在 Linux 上安装 GIMP][3],或者也可以使用的其它任何操作系统。
|
||||
|
||||
这篇教程在 GIMP 2.10 版本下演示。
|
||||
|
||||
#### 步骤 1: 创建你的主要文本,并复制它的轮廓
|
||||
|
||||
打开 GIMP ,并通过转到 “菜单 -> 文件 -> 新建” 来创建一个新的文件。你应该可以使用 `Ctrl+N` 键盘快捷键。
|
||||
|
||||
![Create New File][4]
|
||||
|
||||
你可以在这里选择画布的大小。你也可以选择要白色背景或一种透明背景。它在 “高级选项 -> 颜色” 配置文件下。
|
||||
|
||||
我选择默认的白色背景。它在以后能够更改。
|
||||
|
||||
现在从左边栏的工具箱中选择文本工具。
|
||||
|
||||
![Adding text in GIMP][5]
|
||||
|
||||
写你想要的文本。你可以根据你的选择以更改文本的字体、大小和对齐方式。我保持这篇文章的文本的默认左对齐。
|
||||
|
||||
我故意为文本选择一种浅色,以便难于阅读。在这篇教程中我将添加一个深色轮廓到这个浅色的文本。
|
||||
|
||||
![Text added in GIMP][6]
|
||||
|
||||
当你写完文本后,右键文本框并选择 “文本的路径” 。
|
||||
|
||||
![Right click on the text box and select ‘Path from Text’][7]
|
||||
|
||||
#### 步骤 2: 添加一个带有文本轮廓的透明层
|
||||
|
||||
现在,转到顶部菜单,转到“层”,并添加一个新层。
|
||||
|
||||
![Use Shift+Ctrl+N to add a new layer][8]
|
||||
|
||||
确保添加新层为透明的。你可以给它一个合适的名称,像“文本大纲”。单击确定来添加这个透明层。
|
||||
|
||||
![Add a transparent layer][9]
|
||||
|
||||
再次转到菜单,这次转到 “选择” ,并单击 “来自路径” 。你将看到你的文本应该被高亮显示。
|
||||
|
||||
![Go to Select and choose From Path][10]
|
||||
|
||||
总的来说,你只创建了一个透明层,它有像你的原文一样相同的文本(但是透明)。现在你需要做的是在这个层上增加文本的大小。
|
||||
|
||||
#### 步骤 3: 通过增加它的大小和更改它的颜色来添加文本轮廓
|
||||
|
||||
为此,再次在菜单中转到 “选择” ,这次选择 “增加”。这将允许增大透明层上的文本的大小。
|
||||
|
||||
![Grow the selection on the additional layer][11]
|
||||
|
||||
以 5 或 10 像素增加,或者你喜欢的任意像素。
|
||||
|
||||
![Grow it by 5 or 10 pixel][12]
|
||||
|
||||
你选择需要做是使用一种你选择的颜色来填充这个扩大的选择区。因为我的原文是浅色,在这里我将为轮廓使用背景色。
|
||||
|
||||
如果尚未选择的话,先选择你的主图像层。这些层在右侧栏中可视。然后转到工具箱并选择油漆桶工具。为你的轮廓选择想要的颜色。
|
||||
|
||||
选择使用该工具来填充黑色到你的选择区。记住。你填充文本外部的轮廓,而不是文本本身。
|
||||
|
||||
![Fill the outline of the text with a different color][13]
|
||||
|
||||
在这里你完成了很多。使用 `Ctrl+Shift+A` 来取消你当前的选择区。
|
||||
|
||||
![Outline added to the text][14]
|
||||
|
||||
如此,你现在已经在 GIMP 中成功地添加轮廓到你的文本。它是在白色背景中,如果你想要一个透明背景,只需要在右侧栏的图层菜单中删除背景层。
|
||||
|
||||
![Remove the white background layer if you want a transparent background][15]
|
||||
|
||||
如果你对结果感到满意,保存文件未 PNG 文件(来保留透明背景),或你喜欢的任何文件格式。
|
||||
|
||||
### 你使它工作了吗?
|
||||
|
||||
就这样。这就是你在 GIMP 中为添加一个文本轮廓而需要做的全部工作。
|
||||
|
||||
我希望你发现这个 GIMP 教程有帮助。你可能想查看另一个 [关于在 GIMP 中添加一个水印的简单教程][16]。
|
||||
|
||||
如果你有问题或建议,请在下面自由留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/gimp-text-outline/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[robsean](https://github.com/robsean)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.gimp.org/
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/outlined_text_GIMP.png?ssl=1
|
||||
[3]: https://itsfoss.com/gimp-2-10-release/
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/12/create_outline_text_gimp_1.jpeg?ssl=1
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_2.jpg?ssl=1
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp-3.jpg?ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_4.jpg?ssl=1
|
||||
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_5.jpg?ssl=1
|
||||
[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_6.jpg?ssl=1
|
||||
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_7.jpg?ssl=1
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_8.jpg?ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_9.jpg?ssl=1
|
||||
[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_10.jpg?ssl=1
|
||||
[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_11.jpg?ssl=1
|
||||
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/outline_text_gimp_12.jpg?ssl=1
|
||||
[16]: https://itsfoss.com/add-watermark-gimp-linux/
|
@ -0,0 +1,118 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11770-1.html)
|
||||
[#]: subject: (App Highlight: Open Source Disk Partitioning Tool GParted)
|
||||
[#]: via: (https://itsfoss.com/gparted/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
应用推荐:开源磁盘分区工具 GParted
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/10/220015lp58jjjt22xfppjj.jpg)
|
||||
|
||||
> GParted 是一个可用于 Linux 发行版的非常受欢迎且免费的分区编辑器。在这里,我们简要地介绍一下它提供的功能。
|
||||
|
||||
### GParted:一个自由开源的图形化分区管理器
|
||||
|
||||
![][1]
|
||||
|
||||
GParted 无疑是 [Linux 下的最好的分区管理器][2]之一。用户界面非常简单而可以完成任务。
|
||||
|
||||
在某些情况下,你最终还是会使用 [GParted][3] 来修复或格式化你的 USB 驱动器。我有一个[在 Ubuntu 中使用“磁盘”应用程序不能格式化的 USB 磁盘][4],而这是 GParted 用来救援的地方。
|
||||
|
||||
所以,它是一个非常有用的工具,有很多出色的功能。让我为你们重点介绍一下。
|
||||
|
||||
> 警告!
|
||||
>
|
||||
> 进行磁盘分区是一件危险的工作。除非绝对必要,否则不要做。否则,你可能最终擦除了整个磁盘。
|
||||
|
||||
### GParted 的功能
|
||||
|
||||
从简单地格式化任务到重要的分区任务,你可以使用 GParted 做很多事。我将使用一些屏幕截图突出关键功能,以帮助你在安装它前进一步了解它。
|
||||
|
||||
#### 创建分区表
|
||||
|
||||
你可以为新磁盘创建一个新的分区表,也可以擦除你现存的磁盘内容来修改分区表。
|
||||
|
||||
![][5]
|
||||
|
||||
你能够选择 msdos、gpt、atari,以及更多类型的分区表。
|
||||
|
||||
#### 创建、移动、标记、删除和修改分区表
|
||||
|
||||
你可以使用 GParted 中一系列选项来轻松地创建、标记、删除或修改分区表。
|
||||
|
||||
![][6]
|
||||
|
||||
当然,你必须要谨慎你要做的事情。
|
||||
|
||||
好的是,GParted 可以确保你不能直接应用任何更改 —— 在你点击应用更改之前,它将排队你选择的操作/任务,并在你执行前最后再要求确认一次。
|
||||
|
||||
顶部的对号标记符号 `✓` 可以让你确认更改,然后你的更改才会生效。
|
||||
|
||||
这是分区可用选项的另一个屏幕截图:
|
||||
|
||||
![][7]
|
||||
|
||||
#### 尝试数据救援
|
||||
|
||||
除了编辑分区以外,你也可以试着使用“尝试数据救援”功能以[在 Linux 中恢复丢失的数据][8],如下面的屏幕截图所示。
|
||||
|
||||
![][9]
|
||||
|
||||
值得注意的是,默认情况下你没有安装此功能 —— 你只是能看到这个选项。因此,要使这个数据恢复功能可以正常工作,你必须使用下面的命令来单独地安装 gpart (在基于 Ubuntu/Debian 的发行版上):
|
||||
|
||||
```
|
||||
sudo apt install gpart
|
||||
```
|
||||
|
||||
除了所有这些关键功能以外,它支持各种存储设备和文件系统。你可以从其官方网站的[功能列表][10]中了解到更多信息。
|
||||
|
||||
### 在 Ubuntu 和其它 Linux 发行版上安装 GParted
|
||||
|
||||
你可能已经预安装了 GParted 。所以,务必核实一下。如果你尚未安装它,则可以进入软件中心安装它。
|
||||
|
||||
如果你想使用终端,简单地键入下面的命令:
|
||||
|
||||
```
|
||||
sudo apt install gparted
|
||||
```
|
||||
|
||||
如上所述,如果你想要使用数据恢复选项,除了安装 gparted 软件包外,还应该安装 gpart 软件包。
|
||||
|
||||
如果你使用的是其它 Linux 发行版,你可以在各自的软件管理器中找到它,或者直接查看[官方下载操作说明][11]。
|
||||
|
||||
- [下载 GParted][11]
|
||||
|
||||
### 总结
|
||||
|
||||
当涉及处理磁盘管理和分区时,GParted 是一个非常有用且重要的工具。但是,因为显而易见的原因,当你使用它时,你必须要小心。
|
||||
|
||||
你尝试过 GParted 吗?你在 Linux 上使用的其它哪个分区工具?请在下面的评论中分享你的经验。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/gparted/
|
||||
|
||||
作者:[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://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/gparted-screenshot.png?ssl=1
|
||||
[2]: https://itsfoss.com/partition-managers-linux/
|
||||
[3]: https://gparted.org/
|
||||
[4]: https://itsfoss.com/format-usb-drive-sd-card-ubuntu/
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/gparted-create-partition-table.png?ssl=1
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/gparted-modify-partitions.png?ssl=1
|
||||
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/gparted-partition-options.png?ssl=1
|
||||
[8]: https://itsfoss.com/recover-deleted-files-linux/
|
||||
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/gparted-attempt-data-rescue-feature.png?ssl=1
|
||||
[10]: https://gparted.org/features.php
|
||||
[11]: https://gparted.org/download.php
|
189
published/20191219 Kubernetes namespaces for beginners.md
Normal file
189
published/20191219 Kubernetes namespaces for beginners.md
Normal file
@ -0,0 +1,189 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11749-1.html)
|
||||
[#]: subject: (Kubernetes namespaces for beginners)
|
||||
[#]: via: (https://opensource.com/article/19/12/kubernetes-namespaces)
|
||||
[#]: author: (Jessica Cherry https://opensource.com/users/jrepka)
|
||||
|
||||
Kubernetes 命名空间入门
|
||||
======
|
||||
|
||||
> 命名空间是什么?你为什么需要它?
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/05/094542qnq3qc3nrkkrjanh.jpg)
|
||||
|
||||
kubernetes <ruby>命名空间<rt>namespace</rt></ruby>是什么?正如 Shakespeare 以前写过的,我们所谓的命名空间,或者任何其他名字,就是虚拟集群。通过虚拟集群,意味着 kubernetes 可以在单个集群上提供多个 kubernetes 的集群,类似一个在其主机抽象出来的虚拟机。[kubernetes 文档][2] 中的解释:
|
||||
|
||||
> kubernetes 在一个物理集群上提供了多个虚拟集群。这些虚拟集群被称为命名空间。
|
||||
|
||||
你为什么需要命名空间?一言以蔽之:隔离。
|
||||
|
||||
隔离有很多优点,如它提供了安全和干净的环境。如果你是基础设施的所属者,并且要为开发者提供环境,隔离就相当重要。你最不需要的就是,一个不熟悉你集群是如何搭建的人去修改系统配置 —— 这可能导致所有人都无法登录。
|
||||
|
||||
### 初始命名空间
|
||||
|
||||
一个集群的三个初始命名空间:`default`、`kube-system` 和 `kube-public`。虽然技术上你可以用这三个命名空间作部署,但我还是推荐你把这三个命名空间留作系统配置用,而不是你的项目。
|
||||
|
||||
* `Default` 用于某些没有指明命名空间的部署,这是一种快速创建混乱的做法,如果你在没有正确信息的情况下做了很多部署,将很难清理。我不会去动它,因为它只有这一个用途,而且在不止一种情况下误导过我。
|
||||
* `Kube-system` 是 Kubernetes 系统相关的所有对象组成的命名空间。任何对此命名空间的部署都可能是危险的操作,可能对系统本身造成不可挽回的破坏。没错,我试过;所以我不推荐。
|
||||
* `Kube-public` 所有人可读,但是这个命名空间是为系统保留的。
|
||||
|
||||
### 用命名空间来实现隔离
|
||||
|
||||
我用了多种方式通过命名空间来实现隔离。我经常用命名空间来把多个用户项目分割到不同的环境。这种方式可以有效防止跨项目的污染,因为命名空间提供了独立的环境。例如,用户可以安装不同版本的 Jenkins,如果它们的环境变量是在不同的命名空间,就不会冲突。
|
||||
|
||||
这种隔离对于清理也很有帮助。如果开发小组的多个项目突然被废弃,你可以用命令 `kubectl delete ns <$NAMESPACENAME>` 一键删除命名空间,清理命名空间内的所有东西。(请确认被删除的是正确的命名空间。我曾经在生产环境删除了错误的命名空间,这很不好。)
|
||||
|
||||
如果你是基础设施所有者,请谨慎操作,因为这可能会引发其他团队的的故障或引发其他问题。例如,如果你创建了一个特定的命名空间,里面有特殊的额外安全的 DNS 功能,但是其他人删除了它,那么命名空间内的所有 pod 和它们运行的应用都会被清空。所有的**删除**操作在真正实施之前都应该由同事(通过 [GitOps][3])评审一下。
|
||||
|
||||
虽然官方文档不建议 [10 人以下团队][2] 使用多个命名空间,但出于架构需要,在我自己的集群上还是用了多个命名空间。集群越干净越好。
|
||||
|
||||
### 关于命名空间管理员应该知道的
|
||||
|
||||
首先,命名空间不能嵌套。部署只能在一个命名空间中进行。对于版本化项目,你不一定要用命名空间,你可以使用标签来区分有相同名字的版本化应用。命名空间使用配额来为不同的用户划分资源;例如,*某个命名空间最多能有 x 个节点*。最后,所有的命名空间对于该资源类型只能使用一个独一无二的名字。
|
||||
|
||||
### 命名空间命令操作
|
||||
|
||||
你需要安装 [Minikube][4]、[Helm][5] 和 [kubectl][6] 命令行,才能使用下面的命名空间命令。我的文章《[安全扫描你的 DevOps 流水线][7]》中有它们的安装教程,你也可以去每个项目的官方主页去找安装教程。我使用的是最新的 Minikube。手动安装很快,第一次就能成功运行。
|
||||
|
||||
获取你的第一组命名空间:
|
||||
|
||||
```
|
||||
jess@Athena:~$ kubectl get namespace
|
||||
NAME STATUS AGE
|
||||
default Active 5m23s
|
||||
kube-public Active 5m24s
|
||||
kube-system Active 5m24s
|
||||
```
|
||||
|
||||
创建一个命名空间:
|
||||
|
||||
```
|
||||
jess@Athena:~$ kubectl create namespace athena
|
||||
namespace/athena created
|
||||
```
|
||||
|
||||
现在开发者可以部署到你创建的命名空间了;例如,这里是一个简短的 Helm chart:
|
||||
|
||||
```
|
||||
jess@Athena:~$ helm install teset-deploy stable/redis --namespace athena
|
||||
NAME: teset-deploy
|
||||
LAST DEPLOYED: Sat Nov 23 13:47:43 2019
|
||||
NAMESPACE: athena
|
||||
STATUS: deployed
|
||||
REVISION: 1
|
||||
TEST SUITE: None
|
||||
NOTES:
|
||||
` Please be patient while the chart is being deployed `
|
||||
Redis can be accessed via port 6379 on the following DNS names from within your cluster:
|
||||
|
||||
teset-deploy-redis-master.athena.svc.cluster.local for read/write operations
|
||||
teset-deploy-redis-slave.athena.svc.cluster.local for read-only operations
|
||||
```
|
||||
|
||||
获取你的密码:
|
||||
|
||||
```
|
||||
export REDIS_PASSWORD=$(kubectl get secret --namespace athena teset-deploy-redis -o jsonpath="{.data.redis-password}" | base64 --decode)
|
||||
```
|
||||
|
||||
连接你的 redis 服务:
|
||||
|
||||
1. 运行一个你可以作为客户端用的 Redis pod:
|
||||
|
||||
```bash
|
||||
kubectl run --namespace athena teset-deploy-redis-client --rm --tty -i --restart='Never' \
|
||||
--env REDIS_PASSWORD=$REDIS_PASSWORD \
|
||||
--image docker.io/bitnami/redis:5.0.7-debian-9-r0 -- bash
|
||||
```
|
||||
|
||||
2. 使用 Redis CLI 连接:
|
||||
|
||||
```bash
|
||||
redis-cli -h teset-deploy-redis-master -a $REDIS_PASSWORD
|
||||
redis-cli -h teset-deploy-redis-slave -a $REDIS_PASSWORD
|
||||
```
|
||||
|
||||
从集群外连接你的数据库:
|
||||
|
||||
```bash
|
||||
kubectl port-forward --namespace athena svc/teset-deploy-redis-master 6379:6379 &
|
||||
redis-cli -h 127.0.0.1 -p 6379 -a $REDIS_PASSWORD
|
||||
```
|
||||
|
||||
现在这一套部署已经完成了,你有一个在命名空间 `test-deploy` 中部署的 chart。
|
||||
|
||||
查看你的命名空间中有哪些 pod:
|
||||
|
||||
```
|
||||
jess@Athena:~$ kubectl get pods --namespace athena
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
teset-deploy-redis-master-0 1/1 Running 0 2m38s
|
||||
teset-deploy-redis-slave-0 1/1 Running 0 2m38s
|
||||
teset-deploy-redis-slave-1 1/1 Running 0 90s
|
||||
```
|
||||
|
||||
现在,你已经正式把你的应用隔离到了一个命名空间,创建了一个只在内部通信的虚拟集群。
|
||||
|
||||
一键删除所有东西:
|
||||
|
||||
```bash
|
||||
jess@Athena:~$ kubectl delete namespace athena
|
||||
namespace "athena" deleted
|
||||
```
|
||||
|
||||
因为这会删除应用的所有内部配置,所以这个删除操作可能会持续一段时间,持续时间取决于你的部署到底有多大。
|
||||
|
||||
再次检查一下所有东西是否被删除了:
|
||||
|
||||
```bash
|
||||
jess@Athena:~$ kubectl get pods --all-namespaces
|
||||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||
kube-system coredns-5644d7b6d9-4vxv6 1/1 Running 0 32m
|
||||
kube-system coredns-5644d7b6d9-t5wn7 1/1 Running 0 32m
|
||||
kube-system etcd-minikube 1/1 Running 0 31m
|
||||
kube-system kube-addon-manager-minikube 1/1 Running 0 32m
|
||||
kube-system kube-apiserver-minikube 1/1 Running 0 31m
|
||||
kube-system kube-controller-manager-minikube 1/1 Running 0 31m
|
||||
kube-system kube-proxy-5tdmh 1/1 Running 0 32m
|
||||
kube-system kube-scheduler-minikube 1/1 Running 0 31m
|
||||
kube-system storage-provisioner 1/1 Running 0 27m
|
||||
```
|
||||
|
||||
这是一个所有 pod 及它们存在于的已知命名空间的列表。你可以看到,之前创建的应用和命名空间现在已经不在了。
|
||||
|
||||
### 命名空间实践
|
||||
|
||||
当前我是出于安全考虑才使用命名空间,如限制用户的权限。你可以限制所有的东西 —— 从哪些角色可以访问命名空间,到命名空间可使用的集群资源(CPU 等)的配额等级。例如,我通过资源配额和<ruby>基于角色的访问控制<rt>role-based access control</rt></ruby>(RBAC)配置来确保只有允许的服务账号可以访问命名空间。
|
||||
|
||||
对于隔离方面的安全,我不希望我的私人 Jenkins 应用可以通过一个信任的本地网络被当做一个有公共 IP 地址的安全镜像来访问(我不得不假定,可能会被侵袭)。
|
||||
|
||||
如果你很难提前计算出到底要在你的云平台上部署多少节点(或者,就我而言,是在[搞崩][8]我的家庭服务器之前我能部署多少个),那么命名空间在预算方面也很有用。虽然这超出了本文的讨论范围,而且很复杂,但值得你去调研和使用来防止你的集群过分扩展。
|
||||
|
||||
### 总结
|
||||
|
||||
命名空间是一个很好的隔离项目和应用的方法。本文仅是一个关于命名空间的简短介绍,所以我建议你更深入地研究下命名空间,在你的实践中更多地去使用它们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/kubernetes-namespaces
|
||||
|
||||
作者:[Jessica Cherry][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jrepka
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
|
||||
[2]: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
|
||||
[3]: https://www.weave.works/blog/gitops-operations-by-pull-request
|
||||
[4]: https://kubernetes.io/docs/tasks/tools/install-minikube/
|
||||
[5]: https://helm.sh/
|
||||
[6]: https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
[7]: https://opensource.com/article/19/7/security-scanning-your-devops-pipeline
|
||||
[8]: https://en.wikipedia.org/wiki/Segmentation_fault
|
@ -0,0 +1,101 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11734-1.html)
|
||||
[#]: subject: (Why Vim fans love the Herbstluftwm Linux window manager)
|
||||
[#]: via: (https://opensource.com/article/19/12/herbstluftwm-linux-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
为什么 Vim 爱好者喜欢 Herbstluftwm Linux 窗口管理器
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。如果你是 Vim 爱好者,请试试 Herbstluftwm,这是一个受到 “Vim 方式”启发的平铺式 Linux 窗口管理器。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/201912/31/215943pisvzwkm8mvsefhm.jpg)
|
||||
|
||||
每个人都喜欢 Vim(除了 Dvorak 和 Emacs 用户)。Vim 非常流行,它不仅仅是个编辑器,还有整个都使用 Vim 键绑定来浏览网页的 Web 浏览器,在非常流行的 [Zsh][2] 终端仿真器中也有 Vim 模式。此外,还有一个名为 [herbstluftwm][3] 的窗口管理器,它部分模仿了 “Vim 方式”。Herbstluftwm 取消了窗口,而是在程序载入和使用时使用平铺的贴片或者象限代替。你可以使用键盘(`Alt+h`、`Alt+j`、`Alt+k` 和 `Alt+l`)从一个平铺贴片移动到另一个平铺贴片。
|
||||
|
||||
可以从发行版软件仓库安装 Herbstluftwm。安装后,请退出当前桌面会话,以便可以登录到新会话。默认情况下,会话管理器(KDM、GDM、LightDM 或 XDM,具体取决于你的设置)将继续登录到以前的桌面,因此在登录之前必须覆盖它。
|
||||
|
||||
在 GDM 中:
|
||||
|
||||
![][5]
|
||||
|
||||
在 SDDM 中:
|
||||
|
||||
![][6]
|
||||
|
||||
### Herbstluftwm 桌面之旅
|
||||
|
||||
第一次登录 Herbstluftwm 时,你只会看到一个绿屏,边缘有深绿色边框。你所看到的是初始的平铺贴片,其中没有加载任何应用程序。要启动默认应用,请按 `Alt+Enter`。
|
||||
|
||||
![][4]
|
||||
|
||||
文档中强调使用 `$HOME/.config/herbstluftwm/autostart` 作为登录时启动重要应用的配置文件。对于不必在每次登录时启动的应用,可以使用 xterm 作为启动守护进程。与往常一样,在命令后加一个 `&` 符号会将 shell 的控制权返回给你。例如,要启动 Emacs:
|
||||
|
||||
```
|
||||
% emacs &
|
||||
```
|
||||
|
||||
这将在新的平铺贴片中启动 Emacs 窗口,然后返回命令行。
|
||||
|
||||
![Emacs running in Herbstluftwm][7]
|
||||
|
||||
#### 切换平铺贴片
|
||||
|
||||
要从一个平铺贴片移动到另一个平铺贴片,请使用经典的 `h`、`j`、`k` 或 `l` 与 `Alt` 的 Vim 导航组合键。例如,要从终端切换到其下方的平铺贴片中的应用(即屏幕底部),请按 `Alt+j`。要返回,请按 `Alt+k`。左移和右移分别为 `Alt+h` 和 `Alt+l`。
|
||||
|
||||
#### 分割屏幕
|
||||
|
||||
你可以使用 `Alt+o` 垂直分割屏幕,使用 `Alt+u` 水平分割屏幕。
|
||||
|
||||
要删除空白平铺贴片,请移动到该平铺贴片,然后按 `Alt+r`。
|
||||
|
||||
### 配置 herbstluftwm
|
||||
|
||||
除了 `Alt` 键绑定外,你还可通过 `herbstclient` 命令与 Herbstluftwm 进行通信。此命令可以在 shell 中交互,或者你可在配置文件中保留你的首选项。
|
||||
|
||||
你可以查看 Herbstluftwm 中的所有可用属性:
|
||||
|
||||
```
|
||||
$ herbstclient attr
|
||||
```
|
||||
|
||||
Herbstluftwm 的默认行为定义在其默认配置文件中,你可以将其复制到你的家目录并进行修改。启动后,Herbstluftwm 执行配置文件中包含的命令。例如,你觉得使用以 `Alt` 为中心的键绑定很笨拙(它传统上是应用内保留快捷键),那你可以在配置文件中更改触发 Herbstluftwm 操作的键:
|
||||
|
||||
```
|
||||
% mkdir ~/.config/herbstluftwm
|
||||
% cp /usr/xdg/herbstluftwm/autostart ~/.config/herbstluftwm
|
||||
% sed -i 's/Mod=Mod1/Mod=Mod4/' ~/.config/herbstluftwm
|
||||
% herbstclient reload
|
||||
```
|
||||
|
||||
这将使 Herbstluftwm 的修饰键更改为 `Super` 键(“Windows” 或 “Tux” 键,具体取决于你的键盘)。
|
||||
|
||||
使用 `autostart` 文件,你可以设置自定义键绑定,为特定类型的应用创建标签,以便以一致的方式平铺应用,并执行更多操作。
|
||||
|
||||
### 为何你要尝试 herbstluftwm
|
||||
|
||||
Herbstluftwm 是一个平铺窗口管理器的很好例子。它默认平铺窗口,并允许用户定义全局规则的例外。它使用类似 Vim 的导航方式,但可以快速简单地覆盖它。它可能是你一直在寻找的平铺管理器,所以请马上尝试一下。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/herbstluftwm-linux-desktop
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/openstack_python_vim_2.jpg?itok=4fza48WU (OpenStack source code (Python) in VIM)
|
||||
[2]: https://opensource.com/article/19/9/getting-started-zsh
|
||||
[3]: https://herbstluftwm.org
|
||||
[4]: https://opensource.com/sites/default/files/uploads/advent-herbsluftwm.png (Herbstluftwm)
|
||||
[5]: https://opensource.com/sites/default/files/advent-gdm_1.jpg
|
||||
[6]: https://opensource.com/sites/default/files/advent-kdm_0.jpg
|
||||
[7]: https://opensource.com/sites/default/files/uploads/advent-herbsluftwm-emacs.jpg (Emacs running in Herbstluftwm)
|
154
published/20191221 Pop-_OS vs Ubuntu- Which One is Better.md
Normal file
154
published/20191221 Pop-_OS vs Ubuntu- Which One is Better.md
Normal file
@ -0,0 +1,154 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11744-1.html)
|
||||
[#]: subject: (Pop!_OS vs Ubuntu: Which One is Better?)
|
||||
[#]: via: (https://itsfoss.com/pop-os-vs-ubuntu/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Pop!_OS 与 Ubuntu:哪个更棒?
|
||||
======
|
||||
|
||||
好吧,你可能会发现从[最佳 Linux 发行版][1]列表中选择一个发行版很容易,但是,将两个类似的 Linux 发行版进行比较通常会令人困惑,就像 Pop!_OS 与 Ubuntu 一样。
|
||||
|
||||
有趣的是,Pop!\_OS 是基于 [Ubuntu][2] 的。那么,Pop!\_OS 和 Ubuntu 之间有什么区别呢?为什么要从中选择一个呢?
|
||||
|
||||
在本文中,我将比较 Pop!_OS 和 Ubuntu(两者都是我的最爱)。
|
||||
|
||||
**注意:**你可能会发现一些武断的观点,而本文只是一份比较的参考。随着 Linux 发行版的不断开发和更新,随着时间的流逝,很多事情都会改变。
|
||||
|
||||
### 比较 Ubuntu 和 Pop!_OS
|
||||
|
||||
![Pop!_OS Vs Ubuntu][3]
|
||||
|
||||
发现相似之处可帮助你区分其他差异之处。因此,让我们从一些明显的相似之处开始。
|
||||
|
||||
就像我提到的,Pop!\_OS 是基于 Ubuntu 之上的 Linux 发行版。因此,当你使用 Pop!\_OS 时,你将获得使用 Ubuntu 的所有好处(从技术上说,其核心是一样的)。
|
||||
|
||||
它们都默认带有 [GNOME 桌面环境][4],因此它们具有相似的用户界面(UI)。
|
||||
|
||||
在不讨论所有底层差异的情况下,我将在这里重点介绍一些重要的差异。
|
||||
|
||||
#### 用户体验及主题
|
||||
|
||||
![Pop!_OS][5]
|
||||
|
||||
许多用户认为 Pop!_OS 只是具有不同外观的 Ubuntu。
|
||||
|
||||
根据我的经验,我觉得这并非完全正确。
|
||||
|
||||
是的,它们俩都很喜欢 [GNOME 桌面环境][4] —— 但是,Pop!_OS 让人感觉更加优美。
|
||||
|
||||
除了外观之外,[Ubuntu 还通过添加程序坞和其他一些小花巧来定制了 GNOME 的体验][6]。如果你喜欢定制的 GNOME 体验,可能会发现它更好。
|
||||
|
||||
但是,如果你更喜欢纯粹的 GNOME 体验,Pop!_OS 默认情况下为你提供的就是这样。
|
||||
|
||||
在你亲自尝试之前,我无法说服你。但是,Pop!_OS 中的总体配色方案、图标和主题可以说是令人愉悦的高级用户体验。
|
||||
|
||||
这可能是一个主观的事情,但这是我所观察到的。你还可以查看 Ubuntu 19.10 的视频教程,亲自感受一下。
|
||||
|
||||
#### 易于安装第三方应用
|
||||
|
||||
![Pop Os PPA][7]
|
||||
|
||||
Ubuntu 非常重视 Snap 软件包。这增加了它提供的应用程序的数量。
|
||||
|
||||
但是 Snap 软件包存在一些重要的问题。它们占用了过多的磁盘空间,并且启动要花费大量的时间。
|
||||
|
||||
这就是为什么我更喜欢使用应用程序的 APT 版本的原因。
|
||||
|
||||
我为什么要说这个呢?
|
||||
|
||||
因为 Pop!_OS 具有其[自己的官方 PPA][8],并已默认启用。你会在此处找到一些有用的应用程序,例如 Android Studio、TensorFlow。无需下载 Android Studio 的 1GB 大的 Snap 程序包。只需使用 [apt-get install][9]就可以了。
|
||||
|
||||
#### 预装应用
|
||||
|
||||
![Ubuntu installation slideshow][10]
|
||||
|
||||
对于某些人来说,它可能不是最大的问题,但是拥有大量预安装的应用程序可能会影响体验和性能。即使不影响性能,某些用户也只喜欢较少的预装应用程序。
|
||||
|
||||
与 Ubuntu 相比,Pop!_OS 捆绑了更少的默认应用程序(潜在地减少了胖软件)。
|
||||
|
||||
再一次提醒,这是主观的看法。如果你希望预安装更多应用程序,则可以考虑使用 Ubuntu 而不是 Pop!_OS。
|
||||
|
||||
#### Snap 软件包支持
|
||||
|
||||
![][11]
|
||||
|
||||
对于熟悉 Snap 程序包的用户来说,Ubuntu 的软件中心是比 Pop!_OS 商店更好的解决方案,因为你可以在软件中心中列出 Snap 程序包。
|
||||
|
||||
你无法在软件中心中过滤 Snap 软件包,但是当你在软件中心中发现一个 Snap 软件包(查看应用程序来源的详细信息为 “Snap store”/“Snapcraft”)时安装它就更容易了。
|
||||
|
||||
可能你会感到困惑,Pop!\_OS 也确实支持 Snap 软件包。但是,你不会在 Pop!\_OS 商店中找到它们,这是唯一的区别。
|
||||
|
||||
如果不确定什么是 Snap 软件包及其功能,可以查看我们的文章《[在 Linux 上安装 Snap 应用][12]》。
|
||||
|
||||
#### 单独的 NVIDIA/AMD ISO 文件
|
||||
|
||||
![ISOs][13]
|
||||
|
||||
从技术上讲,它不是内部比较的一部分,而是某些用户关心的一个因素。
|
||||
|
||||
因此,值得强调的是 Pop!_OS 提供了单独的 ISO。一个用于带 NVIDIA 显卡的系统,另一个用于带/不带 AMD 显卡的系统。
|
||||
|
||||
使用 Ubuntu 19.10,你可以在 Ubuntu ISO 上获得 NVIDIA 驱动程序,但 AMD 显卡没有这个。
|
||||
|
||||
#### 可靠性与问题
|
||||
|
||||
毫无疑问,这两个[发行版都适合初学者][14],并且相当可靠。如果你想要更好的可靠性和更少的问题,则可能希望一直使用长期支持(LTS)版本。
|
||||
|
||||
当出现新版本的 Ubuntu 时,Pop!_OS 将在其上开发,并有可能解决用户在 Ubuntu 原始发行版上遇到的问题,然后再进行新的升级。这给它们带来了一点优势,但这没什么实质性的不同,因为这些修复最终都可以运用于 Ubuntu。
|
||||
|
||||
#### 性能
|
||||
|
||||
性能将高度取决于你所安装的内容以及所安装的硬件配置。
|
||||
|
||||
除非你有一个超级旧的系统,否则这两个发行版似乎都表现良好。
|
||||
|
||||
我的机器是 i5-7400 处理器和 16GB 的 RAM(带有 GTX 1050ti 显卡),我发现两种发行版上的体验都足够好。
|
||||
|
||||
当然,你可以手动进行一些优化调整以满足要求——无论它们中的哪个不满足你的硬件配置。
|
||||
|
||||
但是,如果你想使用 System76 笔记本电脑,那么 Pop!\_OS 将可以证明自己是 [Linux 领域的苹果][15],因为 Pop!\_OS 是针对其硬件量身定制的,与 Ubuntu 有所不同。
|
||||
|
||||
#### 硬件兼容性
|
||||
|
||||
在比较其他 Linux 发行版时,这绝对是要考虑的事情。但是,在这种情况下,实际上并没有太大的区别。
|
||||
|
||||
你可能会考虑 Pop!_OS 一直在使用较新的硬件配置,因为他们主要是为他们的笔记本电脑量身定制具有各种配置的 OS。而且,这只是一个观察,而不是事实。
|
||||
|
||||
### 结语
|
||||
|
||||
我知道在不亲自尝试的情况下从两个流行的 Linux 发行版中选择一个并不容易。如果可能的话,我建议你在进行比较的同时尝试两者,以供参考。
|
||||
|
||||
你在这两者之间有何选择?我在比较中错过了什么吗?在下面的评论中让我知道。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/pop-os-vs-ubuntu/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/best-linux-distributions/
|
||||
[2]: https://ubuntu.com/
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/pop_os_vs_ubuntu.png?ssl=1
|
||||
[4]: https://www.gnome.org/
|
||||
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/11/pop-os-UI.jpg?ssl=1
|
||||
[6]: https://itsfoss.com/gnome-tricks-ubuntu/
|
||||
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/11/pop-os-ppa.jpg?ssl=1
|
||||
[8]: https://launchpad.net/~system76/+archive/ubuntu/pop/
|
||||
[9]: https://itsfoss.com/apt-get-linux-guide/
|
||||
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/08/install-ubuntu-linux-on-intel-nuc-14_tutorial.jpg?resize=800%2C516&ssl=1
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/11/snapcraft.jpg?ssl=1
|
||||
[12]: https://itsfoss.com/install-snap-linux/
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/11/iso-amd-nvidia-pop-os.jpg?ssl=1
|
||||
[14]: https://itsfoss.com/best-linux-beginners/
|
||||
[15]: https://www.phoronix.com/scan.php?page=news_item&px=System76-Integrated-Vision
|
@ -0,0 +1,90 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11745-1.html)
|
||||
[#]: subject: (Chill out with the Linux Equinox Desktop Environment)
|
||||
[#]: via: (https://opensource.com/article/19/12/ede-linux-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
轻松使用 Linux Equinox 桌面环境
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。EDE 不是最迷人、最小或效率最高的桌面。但它的柔和、安宁让人平静,它让人感到熟悉舒缓,它的图标主题也很有趣。
|
||||
|
||||
我还没有认真用过 Fast Light Toolkit([FLTK] [2]),但我是 C++ GUI 工具箱的粉丝,它非常易于学习,并且即使进行更新也很可靠。当我发现有一个用 FLTK 构建的桌面环境时,我很想尝试一下,并且我很快为我的决定感到高兴。[Equinox 桌面环境(EDE)][3] 是用 C++ 和 FLTK 为 Unix 桌面编写的快速、简单的桌面环境。它使用通用的桌面约定,因此外观和感觉都非常熟悉,并且在使用几天后,我发现它的简单性提供了我所喜欢的最低限度的优雅。
|
||||
|
||||
![EDE desktop][4]
|
||||
|
||||
### 安装 EDE
|
||||
|
||||
你可能会发现 EDE 包含在发行版的软件仓库中,但你也可以在它的 [SourceForge 仓库][5]中找到它。如果你已经在运行其他桌面环境,你可以安全地在同一系统上安装 EDE,因为它仅带来了一些额外的应用,这些应用程序特定于 EDE,因此它们不会妨碍你的其他桌面。
|
||||
|
||||
EDE 只是桌面环境,它使用 [Pekwm][6] 窗口管理器来处理布局。
|
||||
|
||||
安装 EDE 之后,注销当前的桌面会话,以便你可以登录到新的会话。默认情况下,会话管理器(KDM、GDM、LightDM 或 XDM,取决于你的设置)将继续登录到以前的桌面环境,因此你必须在登录之前覆盖该桌面环境。
|
||||
|
||||
在 GDM 中:
|
||||
|
||||
![][7]
|
||||
|
||||
在 SDDM 中:
|
||||
|
||||
![][8]
|
||||
|
||||
首次启动 EDE 时,可能会提示你确认一些启动任务。在我的 Slackware 工作站上,KDE 将某些服务标记为启动任务(例如 HPLIP 打印监视器和蓝牙守护程序),并且 EDE 在一个确认框中显示了它们。
|
||||
|
||||
![Importing desktop services in EDE][9]
|
||||
|
||||
设置一次后,你无需再次进行设置。
|
||||
|
||||
### EDE 桌面之旅
|
||||
|
||||
EDE 的布局恰恰是大多数人在桌面上所期望的布局:左侧的应用菜单、中间的任务栏、右侧的系统托盘。这是标准的现成布局,不会让任何人感到困惑。这是一个可以安全地装在 Linux 上并且可以自信地给任何没有使用过 Linux 的人使用的桌面。他们将以舒适的方式很快地适应这个桌面。
|
||||
|
||||
你可以单击鼠标右键打开一个小型桌面菜单。这可以让你在桌面上创建应用启动器、创建文件夹并设置一些主题选项。
|
||||
|
||||
屏幕底部的面板是可伸缩的,因此你可以根据需要在全屏模式下工作。单击屏幕右下角的时钟来调出日历和时区设置。
|
||||
|
||||
EDE 有一个小的配置应用,可用于设置一些简单的选项:
|
||||
|
||||
* 背景和图标设置
|
||||
* 屏幕保护程序设置
|
||||
* 时间和时钟
|
||||
* 系统铃声
|
||||
* 键盘
|
||||
* 偏好应用
|
||||
|
||||
![EDE Configuration Place][10]
|
||||
|
||||
EDE 的功能不多。没有文件管理器、文本编辑器、绘画程序或纸牌游戏。你必须安装你想在桌面运行的程序。这意味着你可以从各种各样的 Linux 应用中进行选择,并使用你最喜欢的。
|
||||
|
||||
### EDE 总结
|
||||
|
||||
我发现 EDE 至少作为一种“假日”桌面而言,它的简单性令人舒适。它值得一看。它不是最迷人的桌面,也不是最精简的、也不是最高效的。但它的柔和、安宁让人平静,它让人感到熟悉舒缓,并且它的图标主题充满乐趣和生气。EDE 是一个以其缓慢而稳定的步调而自豪的桌面。
|
||||
|
||||
如果你想放松心情使用一个干净和令人愉悦的界面,请试试 EDE。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/ede-linux-desktop
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/penguin.igloo_.png?itok=K92O7H6b (Linux penguin at the north pole beside an igloo)
|
||||
[2]: https://www.fltk.org/
|
||||
[3]: https://sourceforge.net/projects/ede/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/advent-ede.jpg (EDE desktop)
|
||||
[5]: http://ede.sf.net
|
||||
[6]: https://opensource.com/article/19/12/pekwm-linux-desktop
|
||||
[7]: https://opensource.com/sites/default/files/advent-gdm_2.jpg
|
||||
[8]: https://opensource.com/sites/default/files/advent-kdm_1.jpg
|
||||
[9]: https://opensource.com/sites/default/files/uploads/advent-ede-init.jpg (Importing desktop services in EDE)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/advent-ede-conf.jpg (EDE Configuration Place)
|
@ -0,0 +1,110 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11741-1.html)
|
||||
[#]: subject: (Darktable 3 Released With GUI Rework and New Features)
|
||||
[#]: via: (https://itsfoss.com/darktable-3-release/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
Darktable 3 发布,带来重新打造的 UI 及新的功能
|
||||
======
|
||||
|
||||
> 这是给摄影爱好者的圣诞节礼物。Darktable 3.0 刚刚发布了。
|
||||
|
||||
[Darktable][1] 是[在 Linux 上编辑 RAW 图像的最佳应用之一][2]。你可以将其视为 [Adobe Lightroom 的自由开源替代品][3]。
|
||||
|
||||
Darktable 3 是一个主版本更新,它带来了大量的功能改进和重新打造的用户界面。现在,GUI 完全由 GTK+ CSS 规则所控制,这使得整个 GUI 都可定制主题。它默认有八个主题。
|
||||
|
||||
借助 3000 多个提交和 553 个拉取请求,新版本修复了 66 个 bug 并添加了许多新功能。
|
||||
|
||||
让我们看看这个新版本带来了什么功能。
|
||||
|
||||
### Darktable 3.0 的新功能
|
||||
|
||||
![Darktable 3.0 Screenshot][4]
|
||||
|
||||
以下是重要的新功能:
|
||||
|
||||
* 重新打造的 UI
|
||||
* 用于处理 3D RGB Lut 变换的新模块
|
||||
* 对“降噪(轮廓化)”模块进行了许多改进
|
||||
* 添加了新的“剔除”模式和时间轴视图
|
||||
* 对“降噪(轮廓化)”模块进行了许多改进
|
||||
* 新色调均衡器的基本和电影 RGB 模块
|
||||
* 更好的 4K/5K 显示支持
|
||||
* 撤消/重做支持更多操作
|
||||
* 针对 CPU 和 SSE 路径的许多代码优化
|
||||
* 支持导出到 Google 相册
|
||||
* 支持更多的相机,白平衡预设和噪点配置
|
||||
* 大量的 bug 修复和功能改进
|
||||
|
||||
你可以在 [GitHub 发行说明][5]中了解所有更改。
|
||||
|
||||
### 在 Linux 上安装 Darktable 3.0
|
||||
|
||||
让我们看看如何获取最新的 Darktable 版本。
|
||||
|
||||
#### 在基于 Ubuntu 的发行版上安装 Darktable 3.0
|
||||
|
||||
Ubuntu 仓库中有 Darktable,但你不能得到马上最新的版本。对于 LTS 版本,它的更新可能需要几个月的时间。
|
||||
|
||||
不用担心!Darktable 提供了[自己的 PPA][6] 来在基于 Ubuntu 的发行版上安装最新版本。
|
||||
|
||||
不幸的是,此 Darktable PPA 尚未随新版本更新。
|
||||
|
||||
不用担心了!多亏了我们的朋友 [Ubuntu Handbook 的 Ji M][7],我们有一个非正式的 PPA,可以轻松地在 Ubuntu 和其他基于 Ubuntu 的发行版上安装 Darktable 3.0。
|
||||
|
||||
打开终端,并使用这些命令:
|
||||
|
||||
```
|
||||
sudo add-apt-repository ppa:ubuntuhandbook1/darktable
|
||||
sudo apt update
|
||||
sudo apt install darktable
|
||||
```
|
||||
|
||||
#### 卸载 Darktable 3
|
||||
|
||||
要删除通过此 PPA 安装的 Darktable,你可以先卸载该应用:
|
||||
|
||||
```
|
||||
sudo apt remove darktable
|
||||
```
|
||||
|
||||
接着[删除 PPA][8]:
|
||||
|
||||
```
|
||||
sudo add-apt-repository -r ppa:ubuntuhandbook1/darktable
|
||||
```
|
||||
|
||||
#### 在其他 Linux 发行版上安装 Darktable
|
||||
|
||||
你可以等待到你的发行版的软件管理器提供新版本。
|
||||
|
||||
你也可以从 GitHub 发布页面(位于页面底部)下载 tarball 或所有源代码。
|
||||
|
||||
- [下载 Darktable 3.0][5]
|
||||
|
||||
使用 Darktable 3,你可以更好地编辑自己的假期照片:)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/darktable-3-release/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.darktable.org/
|
||||
[2]: https://itsfoss.com/raw-image-tools-linux/
|
||||
[3]: https://itsfoss.com/open-source-photoshop-alternatives/
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/darktable_3_screenshot.jpg?ssl=1
|
||||
[5]: https://github.com/darktable-org/darktable/releases/tag/release-3.0.0
|
||||
[6]: https://launchpad.net/~pmjdebruijn/+archive/ubuntu/darktable-release
|
||||
[7]: http://ubuntuhandbook.org/index.php/2019/12/install-darktable-3-0-0-ubuntu-18-04-19-10/
|
||||
[8]: https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/
|
57
published/20191227 10 resources to boost your Git skills.md
Normal file
57
published/20191227 10 resources to boost your Git skills.md
Normal file
@ -0,0 +1,57 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11737-1.html)
|
||||
[#]: subject: (10 resources to boost your Git skills)
|
||||
[#]: via: (https://opensource.com/article/19/12/git-resources)
|
||||
[#]: author: (Joshua Allen Holm https://opensource.com/users/holmja)
|
||||
|
||||
10 个提高 Git 技能的资源
|
||||
======
|
||||
|
||||
> 年末总结一下 Git 的最佳表现。以下是告诉你可以在新的一年中以新奇的方式使用 Git 的十篇文章。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/02/093934q5ifu46u4nuq4lgi.jpg)
|
||||
|
||||
2019 年过去了,是时候回顾一下我们(opensource.com)今年发表的有关 Git 的前 10 篇文章了。
|
||||
|
||||
这些文章包括从用例和教程到一些非常有趣的(甚至有些非常规的)使用 Git 的方法。所有这些文章都可以帮助你提高 Git 技能,但是,如果你确实需要 Git 入门介绍,请务必查看我们的《[Git 入门:术语入门][2]》文章,并下载我们的 [Git 备忘单][3]。
|
||||
|
||||
1. Molly de Blanc 写的《[GNOME 项目如何使用 Git][4]》考察了 GNOME 项目采用的自托管 GitLab 实例的做法,该实例作为 GNOME 项目集中保存对 GNOME 做出的贡献的位置。De Blanc 从事于非编码职位,因此她的文章还探讨了切换到 GitLab 如何使主要角色不是编写代码的贡献者受益。
|
||||
2. Ahmad Awais 写的《[Emoji-Log:编写 Git 提交信息的新方法][5]》解释了如何使用 Emoji-Log(一种直白的、开源的 Git 提交日志标准)来编写更好、更用户友好的 Git 提交消息。本文概述了 Emoji-Log 背后的理论以及可添加到 `.bashrc`、`.zshrc` 或 `.gitconfig` 中的配置示例,以便你快速开始使用 Emoji-Log。
|
||||
3. 在《[用 Git 管理你的每日行程][6]》中,Seth Kenlon 解释了如何使用 Git 来管理日历。通过结合 Org 模式、Git 和其他一些工具,Kenlon 描述了如何创建可在设备之间同步的基于 Git 的日历工作流。
|
||||
4. 《[用 Git 作为聊天应用的后端][7]》,Seth Kenlon 探索了另一种使用 Git 的非常规方式。在本文中,他探讨了 GIC,这是一个用 Node.js 编写的聊天客户端,其中 Git 用作后端数据库。GIC 是一个概念验证模型,不是供产品环境使用的东西,但是它提供了一个有趣的示例,说明了使用 Git 的真正独特方法。
|
||||
5. Alan Formy-Duval 的《[Git 学习实用练习][8]》是一份他为提高 Git 技能而努力的编年史。他分享了自己的经验,以使其他人受益于他所学,而 Git 新手将从这篇对 Git 核心功能的出色概述中受益匪浅。
|
||||
6. 《[用 Git 帮助写作者更好地完成工作][9]》的作者 Seth Kenlon 着眼于写作者如何从基于 Git 的工作流中受益。本文介绍了如何使用 Git 和 Atom 利用 Markdown 进行书写。通过遵循本文中的示例,写作者可以轻松地将复杂的版本控制系统添加到其编写工作流中。
|
||||
7. Sachin Patil 在《[如何使用 Magit 管理 Git 项目][10]》中,解释了如何使用 Emacs 的 Magit 扩展来管理 Git 存储库。本文提供了有关如何在 Emacs 中执行一系列关键 Git 任务的清晰示例。这些示例带有说明各种任务的屏幕截图。
|
||||
8. 《[把“点文件”放到版本控制中][11]》的作者 Matthew Broberg 演示了如何使用 Git 存储放在主目录中的点文件。将你的点文件存储在 Git 存储库中,可以更轻松地在计算机之间共享系统配置,并且,如果你愿意的话,也可以与其他人共享配置。这篇文章也有不要共享哪些文件的警告,因为共享错误的点文件会将其暴露给其他人。
|
||||
9. Austin Dewey 的《[4 种用于 Git 加密的机密管理工具][12]》在本文中比较了 Git-crypt、BlackBox、SOPS 和 Transcrypt,研究了在 Git 中存储机密的工具。本文涵盖四个主要领域:支持的加密类型、每个项目的目标、项目的工作流和差异以及其他功能。
|
||||
10. Seth Kenlon 的《[使用 Git 管理 Git 服务器][13]》解释了如何使用 Gitolite 管理 Git 服务器。Gitolite 是使用 Git 来管理 Git 服务器的“管理杂项的后端应用程序”。本文演示了如何安装、配置和使用 Gitolite,并提供了清晰的示例详细说明了该过程的每个步骤。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/git-resources
|
||||
|
||||
作者:[Joshua Allen Holm][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/holmja
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/button_push_open_keyboard_file_organize.png?itok=KlAsk1gx (open source button on keyboard)
|
||||
[2]: https://opensource.com/article/19/2/git-terminology
|
||||
[3]: https://opensource.com/downloads/cheat-sheet-git
|
||||
[4]: https://opensource.com/article/19/10/how-gnome-uses-git
|
||||
[5]: https://linux.cn/article-10627-1.html
|
||||
[6]: https://linux.cn/article-11320-1.html
|
||||
[7]: https://linux.cn/article-11342-1.html
|
||||
[8]: https://opensource.com/article/19/5/practical-learning-exercise-git
|
||||
[9]: https://linux.cn/article-11499-1.html
|
||||
[10]: https://opensource.com/article/19/1/how-use-magit
|
||||
[11]: https://linux.cn/article-11419-1.html
|
||||
[12]: https://opensource.com/article/19/2/secrets-management-tools-git
|
||||
[13]: https://opensource.com/article/19/4/server-administration-git
|
@ -0,0 +1,120 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chen-ni)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11791-1.html)
|
||||
[#]: subject: (Explained! Why Your Distribution Still Using an ‘Outdated’ Linux Kernel?)
|
||||
[#]: via: (https://itsfoss.com/why-distros-use-old-kernel/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
为什么你的发行版仍然在使用“过时的”Linux 内核?
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/16/225806jbqyacu3loolobae.png)
|
||||
|
||||
[检查一下你的系统所使用的 Linux 内核版本][1],你十有八九会发现,按照 Linux 内核官网提供的信息,该内核版本已经达到使用寿命终期(EOL)了。
|
||||
|
||||
一个软件一旦达到了使用寿命终期,那么就意味着它再也不会得到 bug 修复和维护了。
|
||||
|
||||
这自然会引发一连串问题:为什么我的 Linux 发行版会使用一个已经达到使用寿命终期的内核呢?这样做有没有安全风险?我的系统还安全吗?
|
||||
|
||||
下面将逐一解答这些问题。
|
||||
|
||||
> **总结**
|
||||
>
|
||||
> 上游内核维护与你的发行版的内核维护是两个不同的概念。
|
||||
>
|
||||
> 例如,根据 Linux 内核官网,Linux 内核 4.15 版本可能已经达到使用寿命终期了,但是在 2023 年 4 月之前,Ubuntu 18.04 长期维护版本将会继续使用这个版本,并通过向后移植安全补丁和修复 bug 来提供维护。
|
||||
|
||||
### 检查 Linux 内核版本,以及是否达到使用寿命终期
|
||||
|
||||
首先,查看你的系统所使用的 Linux 内核版本:
|
||||
|
||||
```
|
||||
uname -r
|
||||
```
|
||||
|
||||
我使用的是 Ubuntu 18.04,输出的 Linux 内核版本如下:
|
||||
|
||||
```
|
||||
abhishek@itsfoss:~$ uname -r
|
||||
5.0.0-37-generic
|
||||
```
|
||||
|
||||
接下来,可以到 [Linux 内核官网][2]上看看哪些 Linux 内核版本仍然在维护状态。在网站主页上就可以看到相关信息。
|
||||
|
||||
你看到的内核版本状态应该类似于下图:
|
||||
|
||||
![Linux 内核状态][3]
|
||||
|
||||
如果你的内核版本没有列在内核官网主页上,就说明该版本已经达到了使用寿命终期。
|
||||
|
||||
可以看到,5.0 内核版本并不在列,这说明该内核版本已经不再得到维护。事实上,该版本在 [2019 年 6 月就已经达到使用寿命终期了][4]。
|
||||
|
||||
不幸的是,Linux 内核的生命周期没有任何规律可循。不是说常规的内核稳定发布版可以得到 X 月的维护、长期维护版本(LTS)可以得到 Y 年的维护。没有这回事。
|
||||
|
||||
根据实际需求,可能会存在内核的多个 LTS 版本,其使用寿命终期各不相同。在[这个页面][5]上可以查到这些 LTS 版本的相关信息,包括计划的使用寿命终期。
|
||||
|
||||
那么问题来了:既然 Linux 内核官网上明确表示 5.0 版本的内核已经达到了使用寿命终期,Ubuntu 为什么还在提供这个内核版本呢?
|
||||
|
||||
### 你的发行版使用的 Linux 内核已经达到了使用寿命终期,但是没关系!
|
||||
|
||||
![][6]
|
||||
|
||||
你是否想过,为什么 Ubuntu/Debian/Fedora 等发行版被称为 Linux “发行版”?这是因为,它们“发行” Linux 内核。
|
||||
|
||||
这些发行版会对 Linux 内核进行不同的修改,并添加各种 GUI 元素(包括桌面环境、显示服务器等)以及软件,然后再呈现给用户。
|
||||
|
||||
按照通常的工作流,Linux 发行版会选择一个内核,提供给其用户,然后在接下来的几个月、几年中,甚至是达到内核的使用寿命终期之后,仍然会继续使用该内核。
|
||||
|
||||
这样能够保障安全吗?其实是可以的,因为 **发行版会通过向后移植全部的重要修补来维护内核**。
|
||||
|
||||
换句话说,你的 Linux 发行版会确保 Linux 内核没有漏洞和 bug,并且已经通过向后移植获得了重要的新特性。在“过时的旧版本 Linux 内核”上,其实有着数以千计的改动。
|
||||
|
||||
如果 Linux 内核网站上说某个内核版本已经达到了使用寿命终期,那么就意味着 Linux 内核的核心维护团队不会再对该内核版本进行升级和打补丁了。
|
||||
|
||||
但与此同时,Debian/Ubuntu 或者其他发行版的开发者们会继续工作,通过从(由内核核心团队维护的)更新的内核版本中迁移相关的修改,维持这个老版本的生命力。
|
||||
|
||||
重点在于,即使你的发行版看上去是在使用一个已经过时的 Linux 内核,其实该内核也得到了良好的维护,并非是真的过时了。
|
||||
|
||||
### 你是否应该使用最新的稳定内核版本?
|
||||
|
||||
![][7]
|
||||
|
||||
新的 Linux 内核稳定版本每隔 2 到 3 个月发布一次,有不少用户跃跃欲试。
|
||||
|
||||
实话说,除非有十分充分的理由,否则不应该使用最新版本的稳定内核。你使用的发行版并不会提供这个选项,你也不能指望通过在键盘上敲出 `sudo apt give-me-the-latest-stable-kernel` 解决问题。
|
||||
|
||||
此外,手动[安装主流 Linux 内核版本][8]本身就是一个挑战。即使安装成功,之后每次发布 bug 修复的时候,负责更新内核的就会是你了。此外,当新内核达到使用寿命终期之后,你就有责任将它升级到更新的内核版本了。和常规的 [Ubuntu 更新][9]不同,内核升级无法通过 `apt upgrade` 完成。
|
||||
|
||||
同样需要记住的是,切换到主流内核之后,可能就无法使用你的发行版提供的一些驱动程序和补丁了。
|
||||
|
||||
正如 [Greg Kroah-Hartman][10]所言,“**你能使用的最好的内核,就是别人在维护的内核。**”除了你的 Linux 发行版之外,又有谁更胜任这份工作呢!
|
||||
|
||||
希望你对这个主题已经有了更好的理解。下回发现你的系统正在使用的内核版本已经达到使用寿命终期的时候,希望你不会感到惊慌失措。
|
||||
|
||||
欢迎在下面的评论区中留下你的疑问或建议。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/why-distros-use-old-kernel/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chen-ni](https://github.com/chen-ni)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/find-which-kernel-version-is-running-in-ubuntu/
|
||||
[2]: https://www.kernel.org/
|
||||
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/linux-kernel-status.jpg?ssl=1
|
||||
[4]: http://lkml.iu.edu/hypermail/linux/kernel/1906.0/02354.html
|
||||
[5]: https://www.kernel.org/category/releases.html
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/Keep_Calm_and_Trust_Your_Distribution.png?ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/12/using_latest_kernel.png?ssl=1
|
||||
[8]: https://wiki.ubuntu.com/Kernel/MainlineBuilds
|
||||
[9]: https://itsfoss.com/update-ubuntu/
|
||||
[10]: https://en.wikipedia.org/wiki/Greg_Kroah-Hartman
|
@ -0,0 +1,92 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "nacyro"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-11742-1.html"
|
||||
[#]: subject: "10 articles to enhance your security aptitude"
|
||||
[#]: via: "https://opensource.com/article/19/12/security-resources"
|
||||
[#]: author: "Ben Cotton https://opensource.com/users/bcotton"
|
||||
|
||||
10 篇强化你的安全能力的文章
|
||||
======
|
||||
|
||||
> 无论你是新手还是想要增加技能,这十篇安全文章中都有适合你的内容。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/03/004344rco51cnc153ns1zz.jpg)
|
||||
|
||||
如果安全是一个过程(确实如此),那么理所当然的,不同的项目(及其贡献者)的情况各有不同。有些应用程序经历了多年的安全测试,由在信息安全领域工作了几十年的人员所设计。而另外一些则是由开发人员在他们的第一个开源项目中开发的全新项目。毫不奇怪,这十大安全文章囊括了代表这一范围的经验。我们有介绍基本安全实践的文章,也有深入探讨更高级主题的文章。
|
||||
|
||||
无论你是新手还是想要增加你在传奇职业生涯中获得的技能,2019 年十大安全文章中都有适合你的内容。
|
||||
|
||||
### 《安全强化你的 Linux 服务器的七个步骤》
|
||||
|
||||
安全如舍,地基不牢,房屋不稳。Patrick H. Mullins 的杰作《[安全强化你的 Linux 服务器的七个步骤][2]》让你从 Linux 服务器的基本安全步骤开始。即使你有很多管理服务器的经验,本文也提供了一个很好的清单以确保你掌握了基础知识。在此基础上,你可以开始添加额外的安全层。
|
||||
|
||||
### 《使用防火墙让你的 Linux 更加强大》
|
||||
|
||||
七步捍卫你的 Linux 服务器中的一步即是启用防火墙。但什么**是**防火墙,它是如何工作的呢? Seth Kenlon 在《[使用防火墙让你的 Linux 更加强大][3]》一文中回答了这些问题,然后详细描述了为了更好的安全性应如何配置你的防火墙。使用 firewalld 与 Network Manager,你可以为不同的网络设置不同的防火墙配置。例如,这允许你在家庭网络上进行信任配置,并在你最喜欢的咖啡店的 WiFi 网络上进行更多疑的配置。
|
||||
|
||||
### 《用集中日志减少安全风险》
|
||||
|
||||
保护系统安全,只有开始,没有结束:安全是一个过程而不是状态。**保持**系统安全工作的一部分即是密切关注所发生的事情。集中化日志是实现这一点的一种方法,尤其是在管理多系统时。在《[减少集中日志的安全风险][4]》中 Hannah Suarez 分享了要如何开始(她这篇文章基于她在 FOSDEM'19 [自由及开源软件开发者欧洲会议] 中的闪电演讲)。
|
||||
|
||||
### 《在 SSH 中使用 GPG 密钥》
|
||||
|
||||
大多数人都会为 SSH 的密钥认证使用 SSH 密钥。为什么不呢?毕竟 SSH 就在名字里。从安全的角度来看,这些方法非常好。但若想简化某些形式的密钥分发与备份还有另一种方法,Brian Exelbierd 的三部曲系列介绍了《[如何启用使用 GPG 子钥的 SSH 访问][5]》、《[如何导入现有 SSH 密钥][6]》、《[如何将备份量减少到单个密钥文件][7]》
|
||||
|
||||
### 《使用 Seahorse 图形化管理 SSH 密钥》
|
||||
|
||||
并不是所有人都喜欢用 GPG 作为 SSH 密钥,但这并不意味着你在密钥管理上会不顺利。Seahorse 是一个在 GNOME 桌面中用于管理 SSH 密钥及其他身份验证方法的图形化工具。Alan Formy-Duval 的《[使用 Seahorse 图形化管理 SSH 密钥》对新手用户特别有帮助。
|
||||
|
||||
### 《安全扫描你的 DevOps 流程》
|
||||
|
||||
如今到处都是容器。但它们容纳着什么?了解容器满足你的安全策略是保持安全性的重要部分。幸运的是,你可以使用开源工具来帮助自动化合规检查。Jessica Cherry(原名: Repka)的《[安全扫描你的 DevOps 流程][9]》是一个循序渐进的教程,向你展示了如何使用 Jenkins 构建系统和 Anchore 检查服务为容器镜像和注册库创建扫描流程。
|
||||
|
||||
### 《4 种开源云安全工具》
|
||||
|
||||
云服务的一大优点是你的数据可以从任何地方访问。云服务的一个缺点是你的数据可以从任何地方访问。如果你使用的是 “-as-a-Service”(LCTT 译注: 某某即服务,如 IaaS、PaaS、Saa)产品,那么你需要确保它们是经过安全配置的。Anderson Silva、Alison Naylor、Travis McPeak 和 Rich Monk 联合推出《[4 种开源云安全工具][10]》以帮助在使用 GitHub 和 AWS 时提高安全性。如果你正在寻找被不小心提交的机密信息,或尝试从一开始就阻止这些机密信息被提交,这篇文章提供了工具。
|
||||
|
||||
### 《如何使用 OpenSSL:哈希、数字签名等》
|
||||
|
||||
许多信息安全是基于数学的:特别是用于加密数据和验证用户或文件内容的加密函数。在《[开始使用 OpenSSL:密码学基础][11]》中进行介绍后,Marty Kalin 深入讨论了《[如何使用 OpenSSL:哈希、数字签名等][12]》的细节,解释了如何使用 OpenSSL 实用程序来探索这些常用但不常被理解的概念。
|
||||
|
||||
### 《使用树莓派和 Kali Linux 学习计算机安全》
|
||||
|
||||
廉价硬件与开源软件构成了一个很好的组合,特别是对于那些希望边做边学的人来说。在《[使用树莓派和 Kali Linux 学习计算机安全][13]》这篇文章中,Anderson Silva 介绍了面向安全的 Kali Linux 发行版。这是一篇短文,但它满是关于文档和安全相关项目的有用的链接,你可以在自己的树莓派上使用它们。
|
||||
|
||||
### 《量子计算会打破现有的安全体系吗?》
|
||||
|
||||
这篇文章的余下部分是浪费吗?量子计算会让我们对安全的所知变得过时吗?好消息是:回答是否定的,但是量子计算仍然可以在更广泛的范围内对安全和计算世界产生深远的影响。在《[量子计算会打破现有的安全体系吗?][14]》一文中,Mike Bursell 剖析了它好坏两方面的影响,当然,量子计算可能会让加密的破解变得更容易,但如果坏人一开始就无法获得你的数据,那也没有关系。
|
||||
|
||||
### 展望 2020
|
||||
|
||||
安全永远是重要的,(正如那篇量子计算文章所建议的)未来几年将是该领域的一个有趣时期。在 2020 年,我们的文章将着眼于开源安全的前沿,并帮助向不断增长的开源社区解释基础知识。如果你有一个你想要我们报导的主题,请在评论中分享它,或者更进一步 —— 如果你想写一篇文章,就写给我们吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/security-resources
|
||||
|
||||
作者:[Ben Cotton][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[nacyro](https://github.com/nacyro)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bcotton
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_security_cc.png?itok=3V07Lpko "A secure lock."
|
||||
[2]: https://linux.cn/article-11444-1.html
|
||||
[3]: https://linux.cn/article-11093-1.html
|
||||
[4]: https://opensource.com/article/19/2/reducing-security-risks-centralized-logging
|
||||
[5]: https://opensource.com/article/19/4/gpg-subkeys-ssh
|
||||
[6]: https://opensource.com/article/19/4/gpg-subkeys-ssh-multiples
|
||||
[7]: https://opensource.com/article/19/4/gpg-subkeys-ssh-manage
|
||||
[8]: https://opensource.com/article/19/4/ssh-keys-seahorse
|
||||
[9]: https://opensource.com/article/19/7/security-scanning-your-devops-pipeline
|
||||
[10]: https://linux.cn/article-11432-1.html
|
||||
[11]: https://opensource.com/article/19/6/cryptography-basics-openssl-part-1
|
||||
[12]: https://opensource.com/article/19/6/cryptography-basics-openssl-part-2
|
||||
[13]: https://opensource.com/article/19/3/computer-security-raspberry-pi
|
||||
[14]: https://linux.cn/article-10566-1.html
|
||||
[15]: https://opensource.com/how-submit-article
|
@ -0,0 +1,99 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11748-1.html)
|
||||
[#]: subject: (Fixing “VLC is Unable to Open the MRL” Error [Quick Tip])
|
||||
[#]: via: (https://itsfoss.com/vlc-is-unable-to-open-the-mrl/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
修复 “VLC is Unable to Open the MRL” 错误
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/05/084139mzlt1lfivilnnbkl.jpg)
|
||||
|
||||
一个使用 [VLC 的技巧][1]是使用 [VLC] [2] 播放 YouTube 和其他在线视频。这可以帮助你[观看带有字幕的在线视频][3]。
|
||||
|
||||
但是事情并不总是这么简单,因为有时使用 VLC 打开 YouTube 视频时会遇到此错误:
|
||||
|
||||
> Your input can’t be opened: VLC is unable to open the MRL '<https://youtubeurl.com>'. Check the log for details.
|
||||
|
||||
![VLC error while playing YouTube videos][4]
|
||||
|
||||
这是因为 Google 不想让你使用任何第三方应用观看 YouTube,因为这样他们就无法正常收集数据。
|
||||
|
||||
因此,他们不断修改服务端,以使第三发开发更难与 Youtube 集成。
|
||||
|
||||
以 [youtube-dl][5] 为例。你会发现自己无法突然[下载 YouTube 视频] [6],最简单的方案是安装最新版本的 youtube-dl。
|
||||
|
||||
对于 VLC 也是如此。如果你[在 Ubuntu 或任何你用的系统中安装了最新的 VLC][7],那么可能不会看到此错误。
|
||||
|
||||
### 修复 “VLC is unable to open the MRL” 错误
|
||||
|
||||
让我向你展示对于 YouTube 的修复步骤。
|
||||
|
||||
进入 VLC 媒体播放器的官方 Github 仓库页面的[这个页面][8],并使用 `Ctrl+S` 保存文件:
|
||||
|
||||
现在,你需要做的是用此下载文件替换 `lib/vlc/lua/playlist` 目录中的 `youtube.luac`(注意 luac 中的 “c”)。
|
||||
|
||||
#### Linux 中的步骤
|
||||
|
||||
如果你使用的是 Linux,请打开终端并使用 [locate 命令][9]查找 `youtube.luac` 文件的确切位置:
|
||||
|
||||
```
|
||||
locate youtube.luac
|
||||
```
|
||||
|
||||
当你得到文件的路径时,只需将该文件替换为下载的文件即可。我相信你可以完成这项简单的任务。
|
||||
|
||||
对我而言,以下是文件路径:
|
||||
|
||||
```
|
||||
abhishek@itsfoss:~$ locate youtube.lua
|
||||
/usr/lib/x86_64-linux-gnu/vlc/lua/playlist/youtube.luac
|
||||
```
|
||||
|
||||
因此,我要做的就是将下载的文件移到该位置并替换它的内容:
|
||||
|
||||
```
|
||||
sudo cp ~/Downloads/youtube.lua /usr/lib/x86_64-linux-gnu/vlc/lua/playlist/youtube.luac
|
||||
```
|
||||
|
||||
你现在应该可以在 VLC 中播放 YouTube 视频了。
|
||||
|
||||
#### Windows 中的步骤
|
||||
|
||||
如果你使用的是 Windows,那么应遵循以下步骤:
|
||||
|
||||
* 将下载的 `youtube.lua` 文件重命名为 `youtube.luac`
|
||||
* 复制此文件并将其粘贴到 `C:\Program Files (x86)\VideoLAN\VLC\lua\playlist\`
|
||||
|
||||
就是这些了。
|
||||
|
||||
如果你在 Dailymotion 或其他视频流网站上遇到问题,那么可以从 VLC 仓库的[此处][10]下载它们各自的 lua 文件,并替换 VLC 安装中的现有 lua 文件。
|
||||
|
||||
我希望这个快速提示可以解决 VLC 无法为你播放 YouTube 视频的问题。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/vlc-is-unable-to-open-the-mrl/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://itsfoss.com/simple-vlc-tips/
|
||||
[2]: https://www.videolan.org/index.html
|
||||
[3]: https://itsfoss.com/penguin-subtitle-player/
|
||||
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/vlc_error_input_cant_be_played.png?ssl=1
|
||||
[5]: https://itsfoss.com/download-youtube-linux/
|
||||
[6]: https://itsfoss.com/download-youtube-videos-ubuntu/
|
||||
[7]: https://itsfoss.com/install-latest-vlc/
|
||||
[8]: https://raw.githubusercontent.com/videolan/vlc/master/share/lua/playlist/youtube.lua
|
||||
[9]: https://linuxhandbook.com/locate-command/
|
||||
[10]: https://github.com/videolan/vlc/tree/master/share/lua/playlist
|
@ -0,0 +1,67 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (BrunoJu)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11760-1.html)
|
||||
[#]: subject: (10 Ansible resources to accelerate your automation skills)
|
||||
[#]: via: (https://opensource.com/article/19/12/ansible-resources)
|
||||
[#]: author: (James Farrell https://opensource.com/users/jamesf)
|
||||
|
||||
提升自动化技巧的 10 篇 Ansible 文章
|
||||
======
|
||||
|
||||
> 今年,准备好,用出色的 Ansible 自动化技能装备自己的技能包吧。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/07/231057fbtfjwrn29ficxj0.jpg)
|
||||
|
||||
今年我关注了大量关于 Ansible 的文章,以下这些内容都值得每个人学习,无论是否是 Ansible 的新手。
|
||||
|
||||
这些文章值得大家标记为书签,或者设置个计划任务(亦或者是设置一个 Tower/AWX 任务),用来提醒自己常读常新。
|
||||
|
||||
如果你是 Ansible 的新手,那么就从这些文章开始着手吧:
|
||||
|
||||
* 《[Ansible 快速入门指南][2]》拥有一些对新手非常有用的信息,同时还介绍了一些更高级的话题。
|
||||
* 《[你需要知道的 10 个 Ansible 模块][3]》和《[5 个 Ansible 运维任务][4]》(译文)这两篇文章有每一位 Ansible 管理员都应该熟悉并认真研习的一些最基础的 Ansible 功能。
|
||||
* 《[如何使用 Ansible 记录流程][5]》这篇文章是对一些额外话题的纵览,我猜你一定会感到很有趣。
|
||||
|
||||
剩余的这些文章包含了更多高级的话题,比如 Windows 管理、测试、硬件、云和容器,甚至包括了一个案例研究,如何管理那些对技术有兴趣的孩子的需求。
|
||||
|
||||
我希望你能像我一样好好享受 Ansible 带来的乐趣。不要停止学习哦!
|
||||
|
||||
1. 《[Ansible 如何为我的家庭带来和平][6]》这个异想天开的案例,你能看到如何利用 Ansible 为孩子们快速部署一个新的笔记本(或者重装旧笔记本)
|
||||
2. Taz Brown 和 Abner Malivert 的《[适用于 Windows 管理员的 Ansible][7]》:你知道 Ansible 也可以管理 Windows 的节点吗?这篇文章以部署一个 IIS 为案例,阐述了基础的 Ansible 服务器和 Windows 客户端的安装。
|
||||
3. Shashank Hegde 的《[你需要知道的 10 个 Ansible 模块][3]》是个学习你最应该知道的那些最常见、最基础的 Ansible 模块的好文章。运行命令、安装软件包和操作文件是许多有用的自动化工作的基础。
|
||||
4. Marco Bravo 的《[如何使用 Ansible 记录流程][5]》:Ansible 的 YAML 文件易于阅读,因此它们可以被用于记录完成任务所需的手动步骤。这一特性可以帮助你调试与扩展,这令工作变得异常轻松。同时,这篇文章还包含关于测试和分析等 Ansible 相关主题的指导。
|
||||
5. Clement Verna 的《[使用 Testinfra 和 Ansible 验证服务器状态][8]》(译文):测试环节是任何一个 CI/CD DevOps 流程不可或缺的一部分。所以为什么不把测试 Ansible 的运行结果也纳入其中呢?这个测试架构 Testinfra 的入门级文章可以帮助你检查配置结果。
|
||||
6. Mark Phillips 的《[Ansible 硬件起步][9]》:这个世界并不是完全已经被容器和虚拟机所占据。许多系统管理员仍然需要管理众多硬件资源。通过 Ansible 与一点 PXE、DHCP 以及其他技巧的结合,你可以创建一个方便的管理框架使硬件易于启动和运行。
|
||||
7. Jairo da Silva Junior 的《[你需要了解的关于 Ansible 模块的知识][10]》:模块给 Ansible 带来了巨大的潜力,已经有许多模块可以拿来利用。但如果没有你所需的模块,那你可以尝试给自己打造一个。看看这篇文章吧,它能让你了解如何从零开始打造自己所需的模块。
|
||||
8. Mark Phillips 的《[5 个 Ansible 运维任务][4]》(译文):这是另一个有关于如何使用 Ansible 来管理常见的系统操作任务的文章。这里描述了一系列可以取代命令行操作的 Tower(或 AWX)的案例。
|
||||
9. Chris Short 的《[Ansible 快速入门指南][2]》是个可以下载的 PDF 文档。它可以作为一本随时拿来翻阅的手册。这篇文章的开头有助于初学者入门。同时,还包括了一些其他的研究领域,比如模块测试、系统管理任务和针对 K8S 对象的管理。
|
||||
10. Mark Phillips 的《[Ansible 参考指南,带有 Ansible Tower 和 GitHub 的 CI/CD,等等][11]》:这是一篇每月进行总结更新的文章,充满了有趣的链接。话题包括了 Ansible 的基础内容、管理 Netapp 的 E 系列存储产品、调试、打补丁包和其他一些相关内容。文章中还包括了一些视频以及一些聚会的链接。请查看详情。
|
||||
|
||||
如果你也有一些你喜爱的 Ansible 文章,那请留言告诉我们吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/ansible-resources
|
||||
|
||||
作者:[James Farrell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[BrunoJu](https://github.com/BrunoJu)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jamesf
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/chaos_engineer_monster_scary_devops_gear_kubernetes.png?itok=GPYLvfVh (Gears above purple clouds)
|
||||
[2]: https://opensource.com/article/19/2/quickstart-guide-ansible
|
||||
[3]: https://opensource.com/article/19/9/must-know-ansible-modules
|
||||
[4]: https://linux.cn/article-11312-1.html
|
||||
[5]: https://opensource.com/article/19/4/ansible-procedures
|
||||
[6]: https://opensource.com/article/19/9/ansible-documentation-kids-laptops
|
||||
[7]: https://opensource.com/article/19/2/ansible-windows-admin
|
||||
[8]: https://linux.cn/article-10943-1.html
|
||||
[9]: https://opensource.com/article/19/5/hardware-bootstrapping-ansible
|
||||
[10]: https://opensource.com/article/19/3/developing-ansible-modules
|
||||
[11]: https://opensource.com/article/19/7/ansible-news-edition-one
|
@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11751-1.html)
|
||||
[#]: subject: (12 programming resources for coders of all levels)
|
||||
[#]: via: (https://opensource.com/article/19/12/programming-resources)
|
||||
[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjny)
|
||||
|
||||
12 个给全等级码农们的编程资源
|
||||
======
|
||||
|
||||
> 无论你身处编程旅程中的何处,这 12 篇编程文章都有你需要学习一些东西。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/05/102002cdjy66jucbcfs6dg.jpg)
|
||||
|
||||
> “学习计算机编程的最佳时间是 20 年前,其次是现在。”
|
||||
> — 计算机科学的谚语(也许是)
|
||||
|
||||
无论你是新程序员、经验丰富的 Web 开发人员、后端大师、头发花白的系统程序员,还是其他神秘物种的计算机极客?无论你身处广阔的软件开发人员生态系统中的何处,在我们领域中唯一不变的就是需要了解新技术及其应用方法。这是过去一年来阅读量最大的 Opensource.com 文章的集合,我很高兴在这里与你分享它们。
|
||||
|
||||
### 好好学习
|
||||
|
||||
无论你的技能或兴趣是什么,学习如何编写计算机程序都可以将特定领域的知识变成一种超能力。不幸的是,至少从现在开始,还不可能通过坐在计算机前面接受电磁辐射就能学会如何编程。在这之前,我推荐这些出色的文章来帮助激发你的编程技能。它们解决了一些重要的问题,例如考虑学习哪种语言以及不同的入门方式。
|
||||
|
||||
* [你应该学习哪种编程语言?][2](译文)
|
||||
* [学习 Python 的 12 个方式][3](译文)
|
||||
* [你可以使用树莓派学习的三种流行编程语言][4](译文)
|
||||
* [利用 Python 引导孩子的计算机思维][5](译文)
|
||||
|
||||
### 天天向上
|
||||
|
||||
经验丰富的程序员知道,与学习编程相比,唯一更难的就是使你的技能和知识保持最新。但是我们是[自学成才][6]的一族,总是希望提高我们的专业知识和理解力。即使我们不期望使用新技术,我们也知道总会有人问起它们。这些有关 Rust、WebAssembly 和 Podman 的文章是开始学习软件技术一些即将出现的趋势的好地方。
|
||||
|
||||
* [为什么要在 WebAssembly 中使用 Rust?][7]
|
||||
* [使用 WebAssembly 扩展命令行领域][8]
|
||||
* [免 root 的 Podman 如何工作?][9]
|
||||
* [为什么选择 Rust 作为你的下一种编程语言][10]
|
||||
|
||||
### 老兵不死
|
||||
|
||||
尽管新技术层出不穷,但回顾过去可以帮助你前进。当今惊人的技术是建立在昨天的工具之上的,即使我们从未使用这些传奇语言编写过代码,它也将使我们很好地理解这些工具的功能和局限性。这一系列文章集中于 C 语言、用 AWK 编写的实际应用程序,以及对流行度下降但也许还没有消亡的计算机语言的有趣讨论。
|
||||
|
||||
* [C 的巨大影响] [11]
|
||||
* [如何写好 C main 函数][12](译文)
|
||||
* [用 AWK 喝咖啡][13](译文)
|
||||
* [你最喜欢的“死”语言是什么?][14]
|
||||
|
||||
### 学习不止
|
||||
|
||||
无论你在编程过程中处于何处,总有更多东西需要学习。我希望这些来自 2019 年的顶级资源能帮助你为 2020 年做好准备。感谢作者们和你——读者。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/programming-resources
|
||||
|
||||
作者:[Erik O'Shaughnessy][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/jnyjny
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/OSDC_women_computing_3.png?itok=qw2A18BM (Woman sitting in front of her computer)
|
||||
[2]: https://linux.cn/article-10769-1.html
|
||||
[3]: https://linux.cn/article-11280-1.html
|
||||
[4]: https://linux.cn/article-10661-1.html
|
||||
[5]: https://linux.cn/article-11116-1.html
|
||||
[6]: https://en.wikipedia.org/wiki/Autodidacticism
|
||||
[7]: https://opensource.com/article/19/2/why-use-rust-webassembly
|
||||
[8]: https://opensource.com/article/19/4/command-line-playgrounds-webassembly
|
||||
[9]: https://opensource.com/article/19/2/how-does-rootless-podman-work
|
||||
[10]: https://opensource.com/article/19/10/choose-rust-programming-language
|
||||
[11]: https://opensource.com/article/19/10/command-line-heroes-c
|
||||
[12]: https://linux.cn/article-10949-1.html
|
||||
[13]: https://linux.cn/article-10555-1.html
|
||||
[14]: https://opensource.com/article/19/6/favorite-dead-language
|
84
published/20200101 5 predictions for Kubernetes in 2020.md
Normal file
84
published/20200101 5 predictions for Kubernetes in 2020.md
Normal file
@ -0,0 +1,84 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11758-1.html)
|
||||
[#]: subject: (5 predictions for Kubernetes in 2020)
|
||||
[#]: via: (https://opensource.com/article/20/1/kubernetes-2020)
|
||||
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux)
|
||||
|
||||
2020 年对 Kubernetes 的 5 个预测
|
||||
======
|
||||
|
||||
> 以及,对 2019 年最受欢迎的 Kubernetes 文章的回顾。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/07/094358qucr5o2lu2lo23od.jpg)
|
||||
|
||||
你是怎么追踪一个广受欢迎的项目(如 Kubernetes)的发展轨迹?你是怎么了解它发展到什么程度了?如果你在为这个项目作贡献或加入了特殊兴趣组(SIG),可能你会在潜移默化中了解到它的发展轨迹,但如果你的全日工作不涉及到为 Kubernetes 作贡献,那么你可能需要一点关于未来的预测来帮助你了解。对于一个诸如 Kubernetes 的快速发展的项目,年末是回顾过去的一年和展望新的一年的最好时机。
|
||||
|
||||
今年,Kubernetes 取得了很大的进展。除了去查看源码、文档、会议笔记,你也可以去浏览博客。为了深入了解,我在 Opensource.com 上找到了 Kubernetes 排名前十的文章。通过这些文章,我们能了解开发者们更喜欢读和写哪些话题的文章。我们开始吧!
|
||||
|
||||
- [为什么数据科学家喜欢Kubernetes][13]
|
||||
- [Kubernetes 机密信息和 ConfigMap 简介][14]
|
||||
- [怎样在 Kubernetes 上运行 PostgreSQL][15](译文)
|
||||
- [为什么说 Kubernetes 是一辆翻斗车][16](译文)
|
||||
- [安全扫描你的 DevOps 流程][17]
|
||||
- [在 Kubernetes 上部署 InfluxDB 和 Grafana 以收集 Twitter 统计信息][18]
|
||||
- [使用 Kubernetes 操作器扩展 PostgreSQL][19]
|
||||
- [使用 Kubernetes 控制器减少系统管理员的工作量][20]
|
||||
- [将 Kubernetes 带到裸金属边缘计算][21]
|
||||
- [为什么你不必担心 Kubernetes][22]
|
||||
|
||||
首先,我要指明这些文章中有 5 篇是关于 Kubernetes 工作负载的扩展以及它们可以运行在什么场景。这些工作负载涵盖数据科学、PostgreSQL、InfluxDB、Grafana(不仅仅监控集群本身)和边缘计算。从历史角度看,Kubernetes 和容器都是在虚拟机上运行的,尤其是运行在由云提供的基础设施上时。抛开对于 Kubernetes 的兴趣因素,这也表明了终端用户们极度希望在裸机上安装 Kubernetes(参照 [用 OpenShift 在裸机环境运行 Kubernetes][2])。
|
||||
|
||||
其次,也有很多开发者希望了解操作相关的知识以及 Kubernetes 的最佳实践。从 [Kubernetes 操作器][3] 到 [Kubernetes 控制器][4],从 [机密信息][5] 到 [ConfigMaps][6],开发者和运维人员都希望能找到简化部署和管理工作的最佳实践。我们经常纠结在怎么去修改配置文件或别人会怎么配置,而不去回头想想这些配置是怎么让应用部署运转的(不是怎么安装,也不是怎么运行 Kubernetes)。
|
||||
|
||||
最后,人们似乎对入门教程真的感兴趣。事实上,构建 Kubernetes 所需了解的信息太多了,以至于让人们望而却步,也使他们走了错误的路。流行度高的文章中有几篇讲述了为什么你需要了解用 Kubernetes 运行应用程序,而不仅仅是安装它。就像最佳实践类的文章一样,人们也通常不会回头分析在入门时他们应该在什么地方花费时间。我一直秉持的理念是,把有限的时间和金钱投入到如何使用某项技术上,而不是如何构建它。
|
||||
|
||||
### 2020 年对 Kubernetes 的 5 个预测
|
||||
|
||||
回顾了 2019 年的相关主题,这些主题告诉我们 2020 年将如何发展?结合这些文章中的观点,加上我自己的看法,我来分享下我对于 2020 年以及未来发展趋势的想法:
|
||||
|
||||
1. 工作负载扩展。我会关注高性能计算、AI/ML 以及使用操作器的有状态工作负载。
|
||||
2. 更多的生产中的最佳实践,尤其是跟一些成熟的标准相关的,像 PCI、HIPAA、NIST 等等。
|
||||
3. 提升免 root 和更安全的[运行时类][7](如 [gVisor][8]、[Kata Containers][9] 等等)的安全性。
|
||||
4. 在部署和开发者们共享应用时,把 Kubernetes 清单的更好的规范标准作为部署的核心要素。如 [podman 生成 kube][10]、[podman 运行 kube][11],还有多合一 Kubernetes 环境,如 [CodeReady Containers (CRC)][12]
|
||||
5. 一个前所未有的网络、存储和专业硬件(如 GPU 等等)供应商的生态系统,为 Kubernetes 提供 BoB(LCTT 译注:best of breed,单项最佳品牌)解决方案(在自由软件中,我们相信开放的生态系统好过垂直整合的解决方案)。
|
||||
|
||||
期待 Kubernetes 在新的一年里再创辉煌!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/1/kubernetes-2020
|
||||
|
||||
作者:[Scott McCarty][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[lxbwolf](https://github.com/lxbwolf)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/fatherlinux
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
|
||||
[2]: https://blog.openshift.com/kubernetes-on-metal-with-openshift/
|
||||
[3]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/
|
||||
[4]: https://kubernetes.io/docs/concepts/architecture/controller/
|
||||
[5]: https://kubernetes.io/docs/concepts/configuration/secret/
|
||||
[6]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
|
||||
[7]: https://kubernetes.io/docs/concepts/containers/runtime-class/
|
||||
[8]: https://gvisor.dev/
|
||||
[9]: https://katacontainers.io/
|
||||
[10]: https://developers.redhat.com/blog/2019/01/29/podman-kubernetes-yaml/
|
||||
[11]: https://www.redhat.com/en/blog/rhel-81-minor-release-major-new-container-capabilities
|
||||
[12]: https://developers.redhat.com/products/codeready-containers/overview
|
||||
[13]: https://opensource.com/article/19/1/why-data-scientists-love-kubernetes
|
||||
[14]: https://opensource.com/article/19/6/introduction-kubernetes-secrets-and-configmaps
|
||||
[15]: https://linux.cn/article-10762-1.html
|
||||
[16]: https://linux.cn/article-11011-1.html
|
||||
[17]: https://opensource.com/article/19/7/security-scanning-your-devops-pipeline
|
||||
[18]: https://opensource.com/article/19/2/deploy-influxdb-grafana-kubernetes
|
||||
[19]: https://opensource.com/article/19/2/scaling-postgresql-kubernetes-operators
|
||||
[20]: https://opensource.com/article/19/3/reducing-sysadmin-toil-kubernetes-controllers
|
||||
[21]: https://opensource.com/article/19/3/bringing-kubernetes-bare-metal-edge
|
||||
[22]: https://opensource.com/article/19/10/kubernetes-complex-business-problem
|
@ -0,0 +1,85 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (nacyro)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11753-1.html)
|
||||
[#]: subject: (9 cheat sheets and guides to enhance your tech skills)
|
||||
[#]: via: (https://opensource.com/article/20/1/cheat-sheets-guides)
|
||||
[#]: author: (Lauren Pritchett https://opensource.com/users/lauren-pritchett)
|
||||
|
||||
九个提升程序员技术技能的备忘单和指南
|
||||
======
|
||||
|
||||
> 用我们最新的编程备忘单和指南来为新年开局,它适合所有技能水平的人。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202001/05/233115etzm6hv4a3z5yvhg.jpg)
|
||||
|
||||
对刚接触命令行的新程序员来说备忘单是完美的。然而,即便是最有经验的程序员也需要时不时地依靠参考资料。假如你刚好敲不出那个讨厌的快捷键,那么手边有个备忘单就很赞了。这是一份我们可供下载指南的综述,它将助你在 2020 年取得成功。
|
||||
|
||||
### 备忘单
|
||||
|
||||
#### Markdown
|
||||
|
||||
[Markdown][2] 不仅针对程序员,任何人都可以借助它为纯文本文档增添语法和结构。此备忘单提供了使用 CommonMark 规范的 Markdown 基础要点。它还包括 GitHub 和 GitLab 的语法。
|
||||
|
||||
#### Linux 权限和用户
|
||||
|
||||
用这个 Linux 备忘单把[用户管理][3]命令放在手边。快速学习如何增删用户、查看历史以及设置权限。
|
||||
|
||||
#### Bash
|
||||
|
||||
一旦你了解了 [Bash][4],在命令行中就蕴含了无限可能。我们的 Bash 备忘单可以帮助你更有效地使用键盘快捷键。不知不觉间,你就能在睡眠中(字面意义上)运行脚本。
|
||||
|
||||
#### Linux 常用命令
|
||||
|
||||
毫不奇怪,我们的 [Linux 常用命令备忘单][5]是如此受欢迎。这个备忘单包含了开始安装软件和导览文件系统的要点。为自己和你的同事打印出来吧。
|
||||
|
||||
#### 微服务
|
||||
|
||||
似乎每个人都在谈论[微服务][6],而且理由很充分。微服务使应用程序模块化,因此更容易构建和维护。它不再只是这个备忘单上的流行语。在[微服务开源指南][7]中了解重要的术语并学习更多关于微服务的基础知识。
|
||||
|
||||
#### Java
|
||||
|
||||
此备忘单非常适合初级和中级 [Java][8] 程序员。它包括重要的上下文以及处理导入、变量、类等的代码。
|
||||
|
||||
#### pip
|
||||
|
||||
程序员爱用 [pip][9] 命令来帮助安装、管理和使用 Python 软件包。然而,pip 可以做的远不止这些。这个备忘单将教你如何构建 wheels 和 record 包。
|
||||
|
||||
### 指南
|
||||
|
||||
#### 七个不可或缺的 PyPI 库
|
||||
|
||||
[这组 Python 教程][10]将帮助你学习如何更快地编写扩展、格式化代码、自动化测试、确保代码一致性,以及更多使用 PyPI 库的方法。
|
||||
|
||||
#### 开始学习 Kubernetes
|
||||
|
||||
在这份平易近人的[指南][11]中,作者 Scott McCarty 用了一个出人意料的类比来解释 Kubernetes 的价值和上手步骤。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/1/cheat-sheets-guides
|
||||
|
||||
作者:[Lauren Pritchett][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[nacyro](https://github.com/nacyro)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/lauren-pritchett
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/checklist_hands_team_collaboration.png?itok=u82QepPk (a checklist for a team)
|
||||
[2]: https://opensource.com/downloads/cheat-sheet-markdown
|
||||
[3]: https://opensource.com/downloads/linux-permissions-cheat-sheet
|
||||
[4]: https://opensource.com/downloads/bash-cheat-sheet
|
||||
[5]: https://opensource.com/downloads/linux-common-commands-cheat-sheet
|
||||
[6]: https://opensource.com/downloads/microservices-cheat-sheet
|
||||
[7]: https://opensource.com/article/19/11/microservices-cheat-sheet
|
||||
[8]: https://opensource.com/downloads/java-cheat-sheet
|
||||
[9]: https://opensource.com/downloads/pip-cheat-sheet
|
||||
[10]: https://opensource.com/downloads/7-essential-pypi-libraries
|
||||
[11]: https://opensource.com/downloads/getting-started-kubernetes-ebook
|
||||
[12]: https://opensource.com/users/fatherlinux
|
||||
[13]: https://opensource.com/downloads/cheat-sheets
|
||||
[14]: https://opensource.com/email-newsletter
|
@ -0,0 +1,122 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11764-1.html)
|
||||
[#]: subject: (Signal: A Secure, Open Source Messaging App)
|
||||
[#]: via: (https://itsfoss.com/signal-messaging-app/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Signal:安全、开源的聊天应用
|
||||
======
|
||||
|
||||
> Signal 是一款智能手机上的安全开源聊天应用。它还提供了适用于 Linux、Windows 和 macOS 的独立桌面应用。在本文中,我们来看看它的功能和可用性。
|
||||
|
||||
### 对于关注隐私的人来说,Signal 是 WhatsApp(和 Telegram)的绝佳替代品
|
||||
|
||||
![Signal App On Linux][1]
|
||||
|
||||
Signal 是一款关注隐私的开源应用。像[爱德华·斯诺登][2]这样的隐私权倡导者建议使用它。
|
||||
|
||||
它可能没有 Telegram 或 WhatsApp 这么多的功能。但是,如果你想在交流时增强隐私,这是一个可靠的开源方案。
|
||||
|
||||
你可以在智能手机([iOS][3]/[Android][4])上安装,也可以在 Linux、Windows 和 macOS 上安装。
|
||||
|
||||
### Signal 的功能
|
||||
|
||||
**注意:** 某些功能是智能手机特有的。你可能无法在桌面应用上看到所有功能。
|
||||
|
||||
另请注意,目前,Signal 需要电话号码才能注册。如果你不想公开自己的私人电话号码,则可以使用 Google 语音或类似服务。
|
||||
|
||||
正如我已经提到的,这是为增强你的隐私而量身定制的。因此,用户体验可能不是你见过“最佳”的。但是,从隐私/安全角度考虑,我认为这是一个不错的选择。
|
||||
|
||||
![Signal Features][5]
|
||||
|
||||
#### 消失的消息
|
||||
|
||||
你可以为对话中的消息设置一个计时器,以便根据它自动删除消息。
|
||||
|
||||
本质上,对话中的任何人都可以激活此功能。因此,你可以控制对话中的消息时保留还是消失。
|
||||
|
||||
#### 用作默认短信应用
|
||||
|
||||
如果你想在短信中使用开源应用,那么只需进入 Signal 的设置,并将其设置为短信和彩信的默认设置。
|
||||
|
||||
#### 屏幕安全
|
||||
|
||||
有一个巧妙的功能可以阻止应用内截图,它就是“屏幕安全”。
|
||||
|
||||
如果你开启它,那么你将无法为应用中的任何对话截图。你可以从应用设置中找到启用或禁用它的选项。
|
||||
|
||||
它可能并不是对所有人有用,但你可以尝试一下。
|
||||
|
||||
#### 安全数字
|
||||
|
||||
如果你想与朋友一起验证加密的安全性,只需点击个人资料并向下滚动找到“查看安全数字”。
|
||||
|
||||
你可以扫描验证或者看一眼并标记为已验证。
|
||||
|
||||
#### 锁定消息
|
||||
|
||||
如果你使用了锁(密码/指纹)来保护应用,那么即使你的设备已解锁,你也无法在通知中看到消息。
|
||||
|
||||
因此,当 Signal 处于锁定状态收到通知时,你会注意到通知的内容为 “**Locked Message**”,这对于注重隐私的用户来说是一个加分项。
|
||||
|
||||
#### 其它功能
|
||||
|
||||
![][6]
|
||||
|
||||
如你所期待的聊天应用,你可以使用几个标签,并且可以根据需要创建一个组。但是,你无法管理你的组,你只能添加成员和更改群头像。
|
||||
|
||||
此外,Signal 还为其应用支持生物识别。
|
||||
|
||||
### 在 Ubuntu/Linux 上安装 Signal
|
||||
|
||||
不幸的是,你无法在你的 Linux 发行版上找到 .deb 或者 .AppImage。因此,你需要根据[官方安装说明][7]在终端上安装。
|
||||
|
||||
在终端中输入以下内容:
|
||||
|
||||
```
|
||||
curl -s https://updates.signal.org/desktop/apt/keys.asc | sudo apt-key add -
|
||||
echo "deb [arch=amd64] https://updates.signal.org/desktop/apt xenial main" | sudo tee -a /etc/apt/sources.list.d/signal-xenial.list
|
||||
sudo apt update && sudo apt install signal-desktop
|
||||
```
|
||||
|
||||
只需在终端中一个接一个地复制并粘贴命令。
|
||||
|
||||
[Download Signal for Other Devices][7]
|
||||
|
||||
### 我对 Signal 的想法
|
||||
|
||||
我已经使用 Signal 有几年了,它的功能已经得到了改善。但是,我仍然认为可以改善用户体验。
|
||||
|
||||
在隐私方面,(在我看来)这绝对是我们已有软件的一个很好的替代方案。你可以尝试一下,看看它的使用效果如何。
|
||||
|
||||
如果你想尝试一下它,也可以看看它的 [GitHub 页面][8]以获取最新的开发和 beta 版本。
|
||||
|
||||
与 WhatsApp 甚至 [Linux 上的 Telegram][9] 相比,Signal 可能不是流行的聊天应用。但是,你可以自己尝试一下,并鼓励你的朋友使用它。
|
||||
|
||||
你尝试过了吗?在下面的评论中,让我知道你对 “Signal” 的看法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/signal-messaging-app/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/signal-shot.jpg?ssl=1
|
||||
[2]: https://en.wikipedia.org/wiki/Edward_Snowden
|
||||
[3]: https://apps.apple.com/us/app/signal-private-messenger/id874139669
|
||||
[4]: https://play.google.com/store/apps/details?id=org.thoughtcrime.securesms&hl=en_IN
|
||||
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/12/signal-phone.jpg?ssl=1
|
||||
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/12/signal-shot-1.jpg?ssl=1
|
||||
[7]: https://signal.org/download/
|
||||
[8]: https://github.com/signalapp
|
||||
[9]: https://itsfoss.com/install-telegram-desktop-linux/
|
@ -0,0 +1,99 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-11766-1.html)
|
||||
[#]: subject: (GNOME has a ‘Secret’ Screen Recorder. Here’s How to Use it!)
|
||||
[#]: via: (https://itsfoss.com/gnome-screen-recorder/)
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
|
||||
GNOME 有一个“隐藏”的屏幕录像机
|
||||
======
|
||||
|
||||
[GNOME][1] 是[最受欢迎的桌面环境][2]之一。它有现代的 UI,并且带有许多特定于 GNOME 的应用,这些应用与桌面整体外观完美融合。
|
||||
|
||||
你可以根据自己的喜好来[调整 GNOME][3],但我不在这里讨论。GNOME 桌面有一些你可能不知道的隐藏功能。
|
||||
|
||||
这种不太显眼的功能之一是内置的屏幕录像机。
|
||||
|
||||
是的,你没有看错。如果你使用的是 GNOME 桌面,那么不必安装其他的 [Linux 屏幕录像机][4]。你只需要知道正确的快捷键即可。
|
||||
|
||||
### 立即使用 GNOME 屏幕录像机录制屏幕
|
||||
|
||||
要快速打开 GNOME 屏幕录像机,你需要[在 Ubuntu 或其他带有 GNOME 桌面的发行版中按下此快捷键][5]:
|
||||
|
||||
```
|
||||
Ctrl + Alt + Shift + R
|
||||
```
|
||||
|
||||
这将会立即开始录制你的桌面。你可以通过顶部的系统托盘区域的红点了解到正在录制:
|
||||
|
||||
![The red dot in the system tray area indicates that screen recording is in progress][6]
|
||||
|
||||
#### 增加录制时间
|
||||
|
||||
默认的最大录制时间仅为 30 秒。但是可以增加。
|
||||
|
||||
打开终端并使用以下命令:
|
||||
|
||||
```
|
||||
gsettings set org.gnome.settings-daemon.plugins.media-keys max-screencast-length 300
|
||||
```
|
||||
|
||||
在上面的命令中,我将录音的最大长度增加到 300 秒(即 5 分钟)。你可以将其更改为任何其它值,但应以秒为单位。
|
||||
|
||||
如果你**不希望最长录音时间有任何限制,请将其设置为 `0`**,之后它会在你手动停止或者磁盘空间不足才会停止。
|
||||
|
||||
#### 停止屏幕录制
|
||||
|
||||
如前所述,你的桌面录制将在达到最大时间限制后自动停止。
|
||||
|
||||
要在此之前停止录制,你可以按下相同的组合键:
|
||||
|
||||
```
|
||||
Ctrl + Alt + Shift + R
|
||||
```
|
||||
|
||||
你的录制内容将以 [webm][7] 格式保存在家目录的 `Videos` 文件夹中。
|
||||
|
||||
#### 局限性
|
||||
|
||||
尽管使用这个小工具可以方便地快速录制桌面,但是与功能强大的 [Simple Screen Recorder][8] 这样的屏幕录制工具相比,它有一些局限性。
|
||||
|
||||
* 录制开始之前没有时间延迟选项
|
||||
* 没有暂停和播放选项
|
||||
* 它录制整个屏幕。无法仅录制应用窗口、特定区域或特定屏幕(如果你有多个屏幕)。
|
||||
* 视频以 webm 格式保存在用户的 `Videos` 目录中。你无法更改。你必须使用 [HandBrake 之类的工具将视频转换为其他格式][9]。
|
||||
|
||||
如你所见,这个秘密的 GNOME 屏幕录像机与 [Kazam][10] 之类的工具或其他此类工具所提供的功能相差很远。但是,它并不会尝试成为全功能的屏幕录像机。它只是为你提供录制屏幕的快速方法。
|
||||
|
||||
GNOME 是一个多功能的现代桌面环境。你可以大量地[调整 GNOME][3]。[GNOME 扩展][11]为桌面自定义提供了另一个维度。
|
||||
|
||||
该屏幕录像机是 GNOME 的隐藏功能之一,就像你自己很难轻易找到的挂起选项。
|
||||
|
||||
你喜欢它吗?你是否还想与我们分享其他隐藏的 GNOME 功能?请在评论区留言。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/gnome-screen-recorder/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://gnome.org/
|
||||
[2]: https://itsfoss.com/best-linux-desktop-environments/
|
||||
[3]: https://itsfoss.com/gnome-tweak-tool/
|
||||
[4]: https://itsfoss.com/best-linux-screen-recorders/
|
||||
[5]: https://itsfoss.com/ubuntu-shortcuts/
|
||||
[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/gnome_screen_recording.jpg?ssl=1
|
||||
[7]: https://www.webmproject.org/about/
|
||||
[8]: https://itsfoss.com/record-screen-ubuntu-simplescreenrecorder/
|
||||
[9]: https://itsfoss.com/handbrake/
|
||||
[10]: https://itsfoss.com/kazam-screen-recorder/
|
||||
[11]: https://itsfoss.com/best-gnome-extensions/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user