mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-25 23:11:02 +08:00
commit
29f8729fed
@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (chenmu-kk)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12497-1.html)
|
||||
[#]: subject: (Developer happiness: What you need to know)
|
||||
[#]: via: (https://opensource.com/article/19/2/developer-happiness)
|
||||
[#]: author: (Bart Copeland https://opensource.com/users/bartcopeland)
|
||||
|
||||
开发者的福音:你需要知道的事
|
||||
======
|
||||
|
||||
> 开发者需要快速编程的工具和自由,而不会因为合规性和安全性所困扰。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202008/07/214051ki2zitovo8zzynco.jpg)
|
||||
|
||||
一个人需要合适的工具来完成工作。比如说没有比修车修到一半,却发现你没有完成工作的专业工具更沮丧的事情了。同样的道理也适用在开发者身上:你需要工具来发挥你的才能,而不会因为合规性和安全性的需求打断你的工作流程,这样你才可以更快速地编码。
|
||||
|
||||
根据 ActiveState 的研究《[2018 年开发者调查:开源运行时的痛苦][1]》显示,超过一半的开发人员(具体为 51%),每天只需要花费 1-4 小时的时间进行编程。换句话说,大多数开发人员花费不到一半的时间编程。根据调查,一半的开发人员认为安全是他们最大的担忧之一,但是由于公司政策方面的原因,67% 的开发人员选择在编程时不添加新的语言。
|
||||
|
||||
结果是开发人员不得不投入更多的精力在非编码的活动上,例如在构建软件和语言之后检查软件的安全性和合规性标准。而且由于公司政策的原因,他们无法选择适合的开发工具或语言。他们的满意度会下降,同时风险提高。
|
||||
|
||||
因此,开发人员无法将时间投入在高价值的工作上。这会带来额外的商业风险,因为他们的软件上市时间变慢了,并且公司因为没有授权开发人员在不受公司政策影响的前提下决定“最佳的”技术的能力,从而增加了技术债务。
|
||||
|
||||
### 纳入安全性和合规性的工作流程
|
||||
|
||||
我们如何解决这个问题呢?一种方式是通过四个简单的步骤将安全性和合规性的工作流程集成到软件开发中:
|
||||
|
||||
#### 1、集中你的力量
|
||||
|
||||
获得所有相关人员的支持,这是一个经常被遗忘但却至关重要的第一步。确保考虑到了广泛的利益相关者,包括:
|
||||
|
||||
* 开发运维(DevOps)
|
||||
* 开发人员
|
||||
* 信息安全
|
||||
* 合法/合规
|
||||
* IT 安全
|
||||
|
||||
利益相关者想要了解相关的商业利益,因此要为消除软件构建后的安全和合规性检查点提供坚实的理由。你可以在构建你的商业案例中考虑以下任何一个(或者全部)因素:节省时间、机会成本和开发人员生产力。在开发流程中,你也可以通过集成安全性和合规性来避免语言的改造。
|
||||
|
||||
#### 2、寻找可信赖的资源
|
||||
|
||||
接下来,选择可使用的可信资源,以及他们的许可证和安全要求。考虑到如下相关信息:
|
||||
|
||||
* 基于环境或应用程序类型的使用限制以及每种语言的版本控制
|
||||
* 允许哪些开源组件,例如,特定的程序包
|
||||
* 哪种环境类型可以使用哪种许可证(例如,研究与生产)
|
||||
* 安全级别的定义、可接受的脆弱性风险等级、什么样的风险级别会触发一个措施,这个措施是什么并且谁来负责它的执行
|
||||
|
||||
#### 3、从一开始就纳入安全性和合规性
|
||||
|
||||
纳入安全性和合规性的工作流程的结果是,它最终将安全性和合规性融入到代码的第一行。它消除了公司政策的拖累,因为你是按照规范进行编码,而不是必须事后解决问题。但要做到这一点,请考虑在构建代码时采用自动扫描代码的机制,以及使用无代理监控你的运行时代码。你可以节省时间,还可以通过编程实施策略来确保整个组织的合规性。
|
||||
|
||||
#### 4、监控、报告和更新
|
||||
|
||||
出现新的漏洞,新的补丁和版本也会出现。所以,将代码部署到生产中以及运行代码时,需要考虑安全性和合规性。你需要知道哪些(如果有的话)代码存在风险以及该代码在何处运行。所以,部署和运行代码的过程应该包括监视、报告和更新生产中的代码。
|
||||
|
||||
通过一开始就在你的软件开发过程中集成安全性和合规性,你还可以在部署后跟踪代码的运行位置,并在新的威胁出现时获得警报。你也能追踪当你的应用程序何时受到攻击,并通过自动执行软件策略做出响应。
|
||||
|
||||
如果你的软件开发过程中已经引入了安全性和合规性的工作流程,你将会提高你的生产率。你将能够通过增加编码时间、提高安全性和稳定性、以及在维护和发现安全性和合规性的威胁方面节省的成本和时间来衡量价值。
|
||||
|
||||
### 集成所带来的幸福
|
||||
|
||||
如果你不开发和更新软件,你的组织将无法前进。开发人员是公司成功的关键,这意味着他们需要快速编写代码的工具和自由。尽管合规性和安全性至关重要,但你不能让这个需求阻碍你的发展。开发人员显然很担心安全性,因此最好的办法就是“左移”,从一开始就集成安全性和合规性的工作流程。你将可以做更多的事情,在第一次就可以完成,而花费更少的时间进行代码更新。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/2/developer-happiness
|
||||
|
||||
作者:[Bart Copeland][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chenmu-kk](https://github.com/chenmu-kk)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/bartcopeland
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.activestate.com/company/press/press-releases/activestate-developer-survey-examines-open-source-challenges/
|
@ -0,0 +1,341 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12511-1.html)
|
||||
[#]: subject: (How to use OpenSSL: Hashes, digital signatures, and more)
|
||||
[#]: via: (https://opensource.com/article/19/6/cryptography-basics-openssl-part-2)
|
||||
[#]: author: (Marty Kalin https://opensource.com/users/mkalindepauledu)
|
||||
|
||||
如何使用 OpenSSL:哈希值、数字签名等
|
||||
======
|
||||
|
||||
> 通过 OpenSSL 深入了解密码学的细节:哈希值、数字签名、数字证书等。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202008/13/150012t7zwwk6x7wr69wih.jpg)
|
||||
|
||||
[本系列的第一篇文章][2]通过 OpenSSL 库和命令行实用程序介绍了哈希、加密/解密、数字签名和数字证书。这第二篇文章将对细节进行深入探讨。让我们从计算中无处不在的哈希开始,并考虑是什么使哈希函数*具备密码学意义*。
|
||||
|
||||
### 密码学哈希
|
||||
|
||||
OpenSSL 源代码的[下载页面](https://www.openssl.org/source/)包含了一个带有最新版本的表格。每个版本都有两个<ruby>哈希值<rt>hash</rt></ruby>:160 位 SHA1 和 256 位 SHA256。这些值可以用来验证下载的文件是否与存储库中的原始文件相匹配:下载者在本地重新计算下载文件的哈希值,然后将结果与原始文件进行比较。现代系统有计算这种哈希值的实用程序。例如,Linux 有 `md5sum` 和 `sha256sum`。OpenSSL 本身也提供了类似的命令行实用程序。
|
||||
|
||||
哈希值被用于计算的许多领域。例如,比特币区块链使用 SHA256 哈希值作为区块标识符。挖比特币就是生成一个低于指定阈值的 SHA256 哈希值,也就是至少有 N 个前导零的哈希值。(N 的值可以上升或下降,这取决于特定时间的挖矿生产力)。作为一个兴趣点,如今的矿机是为并行生成 SHA256 哈希值而设计的硬件集群。在 2018 年的一个高峰期,全球的比特币矿工每秒产生约 7500 万个<ruby>太哈希值<rt>terahash</rt></ruby> —— 这真是一个不可思议的数字。
|
||||
|
||||
网络协议也使用哈希值(在这里通常叫做“<ruby>校验和<rt>checksum</rt></ruby>”)来支持消息的完整性;也就是说,保证收到的消息与发送的消息是一样的。消息发送者计算消息的校验和,并将结果与消息一起发送。当消息到达时,接收方重新计算校验和。如果发送的校验和与重新计算的校验和不一致,那么消息在传输过程中可能出现了一些问题,或者发送的校验和出现了问题,或者两者都出现了问题。在这种情况下,应该重新发送消息和它的校验和,或者至少应该触发一个错误情况。(如 UDP 这样的低级网络协议不会理会校验和。)
|
||||
|
||||
哈希的其他例子大家都很熟悉。比如一个网站,要求用户用密码进行验证,用户在浏览器中输入密码,然后,他们通过 HTTPS 连接到服务器,密码从浏览器加密发送到服务器。一旦密码到达服务器,就会被解密,然后进行数据库表的查询。
|
||||
|
||||
在这个查询表中应该存储什么?存储密码本身是有风险的。风险要小得多的方式是存储一个由密码生成的哈希值,也许在计算哈希值之前“加一些<ruby>盐<rt>salt</rt></ruby>(额外的位)改善口味”。你的密码可能会被发送到 Web 服务器上,但网站可以向你保证,密码不会存储在那里。
|
||||
|
||||
哈希值还出现在安全的各个领域。例如,<ruby>基于哈希值的消息认证码<rt>hash-based message authentication code</rt></ruby>([HMAC][3])使用一个哈希值和一个秘密的<ruby>加密密钥<rt>cryptographic key</rt></ruby>来认证通过网络发送的消息。HMAC 码轻量级且易于在程序中使用,在 Web 服务中很受欢迎。一个 X509 数字证书包括一个称为<ruby>指纹<rt>fingerprint</rt></ruby>的哈希值,它可以方便证书验证。一个存放于内存中的<ruby>可信存储<rt>truststore</rt></ruby>可以实现为一个以这种指纹为键的查找表 —— 作为一个支持恒定查找时间的<ruby>哈希映射<rt>hash map</rt></ruby>。来自传入的证书的指纹可以与可信存储中的密钥进行比较,以确定是否匹配。
|
||||
|
||||
<ruby>密码学哈希函数<rt>cryptographic hash function</rt></ruby>应该具有什么特殊属性?它应该是<ruby>单向<rt>one-way</rt></ruby>的,这意味着很难被逆转。一个加密哈希函数应该是比较容易计算的,但是计算它的反函数(将哈希值映射回输入位串的函数)在计算上应该是困难的。下面是一个描述,用 `chf` 作为加密哈希函数,我的密码 `foobar` 作为样本输入。
|
||||
|
||||
```
|
||||
+---+
|
||||
foobar—>|chf|—>hash value ## 简单直接
|
||||
+--–+
|
||||
```
|
||||
|
||||
相比之下,逆向操作是不可行的:
|
||||
|
||||
```
|
||||
+-----------+
|
||||
hash value—>|chf inverse|—>foobar ## 棘手困难
|
||||
+-----------+
|
||||
```
|
||||
|
||||
例如,回忆一下 SHA256 哈希函数。对于一个任意长度为 N > 0 的输入位串,这个函数会生成一个 256 位的固定长度的哈希值;因此,这个哈希值甚至不会反映出输入位串的长度 N,更不用说字符串中每个位的值了。顺便说一下,SHA256 不容易受到<ruby>[长度扩展攻击][4]<rt>length extension attack</rt></ruby>。唯一有效的逆向工程方法是通过蛮力搜索将计算出的 SHA256 哈希值逆向返回到输入位串,这意味着需要尝试所有可能的输入位串,直到找到与目标哈希值匹配的位串。这样的搜索在 SHA256 这样一个完善的加密哈希函数上是不可行的。
|
||||
|
||||
现在,最后一个回顾的知识点是<ruby>有序<rt>in order</rt></ruby>。加密哈希值是统计学上的唯一,而不是无条件的唯一,这意味着两个不同的输入位串产生相同的哈希值是不太可能的,但也不是不可能的 —— 这称之为<ruby>碰撞<rt>collision</rt></ruby>。[生日问题][5]提供了一个很好的反直觉的碰撞例子。对各种哈希算法的<ruby>抗碰撞性<rt>collision resistance</rt></ruby>有着广泛的研究。例如,MD5(128 位哈希值)在大约 2^21 次哈希之后,抗碰撞能力就会崩溃。对于 SHA1(160 位哈希值),大约在 2^61 次哈希后开始崩溃。
|
||||
|
||||
对于 SHA256 的抗碰撞能力的剖析,目前还没有一个很好的估计。这个事实并不奇怪。SHA256 有 2^256 个不同的哈希值范围,这个数字的十进制表示法有 78 位之多! 那么,SHA256 哈希会不会发生碰撞呢?当然可能,但可能性极小。
|
||||
|
||||
在下面的命令行示例中,有两个输入文件被用作位串源:`hashIn1.txt` 和 `hashIn2.txt`。第一个文件包含 `abc`,第二个文件包含 `1a2b3c`。
|
||||
|
||||
为了便于阅读,这些文件包含的是文本,但也可以使用二进制文件代替。
|
||||
|
||||
在命令行(百分号 `%` 是提示符)使用 Linux `sha256sum` 实用程序对这两个文件进行处理产生以下哈希值(十六进制):
|
||||
|
||||
```
|
||||
% sha256sum hashIn1.txt
|
||||
9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3 hashIn1.txt
|
||||
|
||||
% sha256sum hashIn2.txt
|
||||
3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13 hashIn2.txt
|
||||
```
|
||||
|
||||
OpenSSL 哈希对应的结果与预期相同:
|
||||
|
||||
```
|
||||
% openssl dgst -sha256 hashIn1.txt
|
||||
SHA256(hashIn1.txt)= 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3
|
||||
|
||||
% openssl dgst -sha256 hashIn2.txt
|
||||
SHA256(hashIn2.txt)= 3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13
|
||||
```
|
||||
|
||||
这种对密码学哈希函数的研究,为我们仔细研究数字签名及其与密钥对的关系奠定了基础。
|
||||
|
||||
### 数字签名
|
||||
|
||||
顾名思义,<ruby>数字签字<rt>digital signature</rt></ruby>可以附在文件或其他一些电子<ruby>工件<rt>artifact</rt></ruby>(如程序)上,以证明其真实性。因此,这种签名类似于纸质文件上的手写签名。验证数字签名就是要确认两件事:第一,被担保的工件在签名被附上后没有改变,因为它部分是基于文件的加密学哈希值。第二,签名属于一个人(例如 Alice),只有她才能获得一对密钥中的私钥。顺便说一下,对代码(源码或编译后的代码)进行数字签名已经成为程序员的普遍做法。
|
||||
|
||||
让我们来了解一下数字签名是如何创建的。如前所述,没有公钥和私钥对就没有数字签名。当使用 OpenSSL 创建这些密钥时,有两个独立的命令:一个是创建私钥,另一个是从私钥中提取匹配的公钥。这些密钥对用 base64 编码,在这个过程中可以指定它们的大小。
|
||||
|
||||
<ruby>私钥<rt>private key</rt></ruby>由数值组成,其中两个数值(一个<ruby>模数<rt>modulus</rt></ruby>和一个<ruby>指数<rt>exponent</rt></ruby>)组成了公钥。虽然私钥文件包含了<ruby>公钥<rt>public key</rt></ruby>,但提取出来的公钥并**不会**透露相应私钥的值。
|
||||
|
||||
因此,生成的带有私钥的文件包含了完整的密钥对。将公钥提取到自己的文件中是很实用的,因为这两把钥匙有不同的用途,而这种提取方式也将私钥可能被意外公开的危险降到最低。
|
||||
|
||||
接下来,这对密钥的私钥被用来生成目标工件(如电子邮件)的哈希值,从而创建签名。在另一端,接收者的系统使用这对密钥的公钥来验证附在工件上的签名。
|
||||
|
||||
现在举个例子。首先,用 OpenSSL 生成一个 2048 位的 RSA 密钥对:
|
||||
|
||||
```
|
||||
openssl genpkey -out privkey.pem -algorithm rsa 2048
|
||||
```
|
||||
|
||||
在这个例子中,我们可以舍去 `-algorithm rsa` 标志,因为 `genpkey` 默认为 RSA 类型。文件的名称(`privkey.pem`)是任意的,但是<ruby>隐私增强邮件<rt>Privacy Enhanced Mail</rt></ruby>(PEM)扩展名 `.pem` 是默认 PEM 格式的惯用扩展名。(如果需要的话,OpenSSL 有命令可以在各种格式之间进行转换。)如果需要更大的密钥大小(例如 4096),那么最后一个参数 `2048` 可以改成 `4096`。这些大小总是二的幂。
|
||||
|
||||
下面是产生的 `privkey.pem` 文件的一个片断,它是 base64 编码的:
|
||||
|
||||
```
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANnlAh4jSKgcNj/Z
|
||||
JF4J4WdhkljP2R+TXVGuKVRtPkGAiLWE4BDbgsyKVLfs2EdjKL1U+/qtfhYsqhkK
|
||||
...
|
||||
-----END PRIVATE KEY-----
|
||||
```
|
||||
|
||||
接下来的命令就会从私钥中提取出这对密钥的公钥:
|
||||
|
||||
```
|
||||
openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem
|
||||
```
|
||||
|
||||
由此产生的 `pubkey.pem` 文件很小,可以在这里完整地显示出来:
|
||||
|
||||
```
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ5QIeI0ioHDY/2SReCeFnYZJY
|
||||
z9kfk11RrilUbT5BgIi1hOAQ24LMilS37NhHYyi9VPv6rX4WLKoZCmkeYaWk/TR5
|
||||
4nbH1E/AkniwRoXpeh5VncwWMuMsL5qPWGY8fuuTE27GhwqBiKQGBOmU+MYlZonO
|
||||
O0xnAKpAvysMy7G7qQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
```
|
||||
|
||||
现在,有了密钥对,数字签名就很容易了 —— 在本例中,源文件 `client.c` 是要签名的工件:
|
||||
|
||||
```
|
||||
openssl dgst -sha256 -sign privkey.pem -out sign.sha256 client.c
|
||||
```
|
||||
|
||||
`client.c` 源文件的摘要是 SHA256,私钥在前面创建的 `privkey.pem` 文件中。由此产生的二进制签名文件是 `sign.sha256`,这是一个任意的名字。要得到这个文件的可读版本(比如 base64),后续命令是:
|
||||
|
||||
```
|
||||
openssl enc -base64 -in sign.sha256 -out sign.sha256.base64
|
||||
```
|
||||
|
||||
文件 `sign.sha256.base64` 现在包含如下内容:
|
||||
|
||||
```
|
||||
h+e+3UPx++KKSlWKIk34fQ1g91XKHOGFRmjc0ZHPEyyjP6/lJ05SfjpAJxAPm075
|
||||
VNfFwysvqRGmL0jkp/TTdwnDTwt756Ej4X3OwAVeYM7i5DCcjVsQf5+h7JycHKlM
|
||||
o/Jd3kUIWUkZ8+Lk0ZwzNzhKJu6LM5KWtL+MhJ2DpVc=
|
||||
```
|
||||
|
||||
或者,可执行文件 `client` 也可以被签名,由此产生的 base64 编码签名将如预期的不同:
|
||||
|
||||
```
|
||||
VMVImPgVLKHxVBapJ8DgLNJUKb98GbXgehRPD8o0ImADhLqlEKVy0HKRm/51m9IX
|
||||
xRAN7DoL4Q3uuVmWWi749Vampong/uT5qjgVNTnRt9jON112fzchgEoMb8CHNsCT
|
||||
XIMdyaPtnJZdLALw6rwMM55MoLamSc6M/MV1OrJnk/g=
|
||||
```
|
||||
|
||||
这一过程的最后一步是用公钥验证数字签名。作为验证的一个重要步骤,应重新计算用于签署工件(在本例中,是可执行的 `client` 程序)的哈希值,因为验证过程应表明工件在签署后是否发生了变化。
|
||||
|
||||
有两个 OpenSSL 命令用于这个目的。第一条命令是对 base64 签名进行解码。
|
||||
|
||||
```
|
||||
openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha256
|
||||
```
|
||||
|
||||
第二条是核实签名:
|
||||
|
||||
```
|
||||
openssl dgst -sha256 -verify pubkey.pem -signature sign.sha256 client
|
||||
```
|
||||
|
||||
第二条命令的输出,应该是这样的:
|
||||
|
||||
```
|
||||
Verified OK
|
||||
```
|
||||
|
||||
为了了解验证失败时的情况,一个简短但有用的练习是将最后一个 OpenSSL 命令中的可执行的 `client` 文件替换为源文件 `client.c`,然后尝试验证。另一个练习是改变 `client` 程序,无论多么轻微,然后再试一次。
|
||||
|
||||
### 数字证书
|
||||
|
||||
<ruby>数字证书<rt>digital certificate</rt></ruby>汇集了到目前为止所分析的各个部分:哈希值、密钥对、数字签名和加密/解密。生产级证书的第一步是创建一个<ruby>证书签名请求<rt>certificate signing request</rt></ruby>(CSR),然后将其发送给<ruby>证书颁发机构<rt>certificate authority</rt></ruby>(CA)。在 OpenSSL 的例子中,要做到这一点,请运行:
|
||||
|
||||
```
|
||||
openssl req -out myserver.csr -new -newkey rsa:4096 -nodes -keyout myserverkey.pem
|
||||
```
|
||||
|
||||
这个例子生成了一个 CSR 文档,并将该文档存储在文件 `myserver.csr`(base64 文本)中。这里的目的是:CSR 文档要求 CA 保证与指定域名相关联的身份,域名也就是 CA 所说的<ruby>通用名<rt>common name</rt></ruby>(CN)。
|
||||
|
||||
尽管可以使用现有的密钥对,但这个命令也会生成一个新的密钥对。请注意,在诸如 `myserver.csr` 和 `myserverkey.pem` 等名称中使用 `server` 暗示了数字证书的典型用途:作为与 www.google.com 等域名相关的 Web 服务器的身份担保。
|
||||
|
||||
然而,无论数字证书如何使用,同样使用这个命令都会创建一个 CSR。它还会启动一个问题/回答的交互式会话,提示有关域名的相关信息,以便与请求者的数字证书相连接。这个交互式会话可以通过在命令中提供基本的信息,用反斜杠来续行一步完成。`-subj` 标志提供了所需的信息。
|
||||
|
||||
```
|
||||
% openssl req -new \
|
||||
-newkey rsa:2048 -nodes -keyout privkeyDC.pem \
|
||||
-out myserver.csr \
|
||||
-subj "/C=US/ST=Illinois/L=Chicago/O=Faulty Consulting/OU=IT/CN=myserver.com"
|
||||
```
|
||||
|
||||
产生的 CSR 文件在发送给 CA 之前可以进行检查和验证。这个过程可以创建具有所需格式(如 X509)、签名、有效期等的数字证书。
|
||||
|
||||
```
|
||||
openssl req -text -in myserver.csr -noout -verify
|
||||
```
|
||||
|
||||
这是输出的一个片断:
|
||||
|
||||
```
|
||||
verify OK
|
||||
Certificate Request:
|
||||
Data:
|
||||
Version: 0 (0x0)
|
||||
Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e:de:73:
|
||||
…
|
||||
Exponent: 65537 (0x10001)
|
||||
Attributes:
|
||||
a0:00
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
…
|
||||
```
|
||||
|
||||
### 自签证书
|
||||
|
||||
在开发 HTTPS 网站的过程中,手头有一个不用经过 CA 流程的数字证书是很方便的。在 HTTPS 握手的认证阶段,<ruby>自签证书<rt>self-signed certificate</rt></ruby>就能满足要求,尽管任何现代浏览器都会警告说这样的证书毫无价值。继续这个例子,自签证书的 OpenSSL 命令(有效期为一年,使用 RSA 公钥)如下:
|
||||
|
||||
```
|
||||
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout myserver.pem -out myserver.crt
|
||||
```
|
||||
|
||||
下面的 OpenSSL 命令呈现了生成的证书的可读版本:
|
||||
|
||||
```
|
||||
openssl x509 -in myserver.crt -text -noout
|
||||
```
|
||||
|
||||
这是自签证书的部分输出:
|
||||
|
||||
```
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 13951598013130016090 (0xc19e087965a9055a)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
|
||||
Validity
|
||||
Not Before: Apr 11 17:22:18 2019 GMT
|
||||
Not After : Apr 10 17:22:18 2020 GMT
|
||||
Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (4096 bit)
|
||||
Modulus:
|
||||
00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e:de:73:
|
||||
...
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
|
||||
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
3a:eb:8d:09:53:3b:5c:2e:48:ed:14:ce:f9:20:01:4e:90:c9:
|
||||
...
|
||||
```
|
||||
|
||||
如前所述,RSA 私钥包含的值是用来生成公钥的。但是,给定的公钥**不会**泄露匹配的私钥。关于底层数学理论的介绍,见 <https://simple.wikipedia.org/wiki/RSA_algorithm>。
|
||||
|
||||
数字证书与用于生成该证书的密钥对之间存在着重要的对应关系,即使证书只是自签的:
|
||||
|
||||
* 数字证书包含构成公钥的指数和模数值。这些值是最初生成的 PEM 文件中密钥对的一部分,在本例中,是文件 `myserver.pem`。
|
||||
* <ruby>指数<rt>exponent</rt></ruby>几乎总是 65,537(如本例中),所以可以忽略。
|
||||
* 密钥对的<ruby>模数<rt>modulus</rt></ruby>应该与数字证书的模数相匹配。
|
||||
|
||||
模数是一个很大的值,为了便于阅读,可以进行哈希处理。下面是两个 OpenSSL 命令,它们检查相同的模数,从而确认数字证书是基于 PEM 文件中的密钥对。
|
||||
|
||||
```
|
||||
% openssl x509 -noout -modulus -in myserver.crt | openssl sha1 ## 证书中的模数
|
||||
(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
|
||||
|
||||
% openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## 密钥中的模数
|
||||
(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
|
||||
```
|
||||
|
||||
所产生的哈希值匹配,从而确认数字证书是基于指定的密钥对。
|
||||
|
||||
### 回到密钥分发问题上
|
||||
|
||||
让我们回到第一部分末尾提出的一个问题:`client` 程序和 Google Web 服务器之间的 TLS 握手。握手协议有很多种,即使是用在 `client` 例子中的 Diffie-Hellman 版本也有不同的方式。尽管如此,`client` 例子遵循了一个共同的模式。
|
||||
|
||||
首先,在 TLS 握手过程中,`client` 程序和 Web 服务器就<ruby>加密套件<rt>cipher suite</rt></ruby>达成一致,其中包括要使用的算法。在本例中,该套件是 `ECDHE-RSA-AES128-GCM-SHA256`。
|
||||
|
||||
现在值得关注的两个要素是 RSA 密钥对算法和 AES128 块密码,用于在握手成功的情况下对消息进行加密和解密。关于加密/解密,这个过程有两种流派:<ruby>对称<rt>symmetric</rt></ruby>和<ruby>非对称<rt>asymmetric</rt></ruby>。在对称流派中,加密和解密使用的是*相同的*密钥,这首先就引出了<ruby>密钥分发问题<rt>key distribution problem</rt></ruby>。如何将密钥安全地分发给双方?在非对称流派中,一个密钥用于加密(在这种情况下,是 RSA 公钥),但另一个密钥用于解密(在这种情况下,是来自同一对密钥的 RSA 私钥)。
|
||||
|
||||
`client` 程序拥有来认证证书的 Google Web 服务器的公钥,而 Web 服务器拥有来自同一对密钥的私钥。因此,`client` 程序可以向 Web 服务器发送加密信息,而 Web 服务器可以单独对该通信进行解密。
|
||||
|
||||
在 TLS 的情况下,对称方式有两个显著的优势:
|
||||
|
||||
* 在 `client` 程序与 Google Web 服务器之间的互动中,认证是单向的。Google Web 服务器向 `client` 程序发送三张证书,但 `client` 程序并没有向 Web 服务器发送证书,因此,Web 服务器没有来自客户端的公钥,无法加密发给客户端的消息。
|
||||
* 使用 AES128 的对称加密/解密比使用 RSA 密钥的非对称加密/解密快了**近千倍**。
|
||||
|
||||
TLS 握手将两种加密/解密方式巧妙地结合在一起。在握手过程中,`client` 程序会生成随机位,即所谓的<ruby>预主密<rt>pre-master secret</rt></ruby>(PMS)。然后,`client` 程序用服务器的公钥对 PMS 进行加密,并将加密后的 PMS 发送给服务器,服务器再用 RSA 密钥对的私钥对 PMS 信息进行解密:
|
||||
|
||||
```
|
||||
+-------------------+ encrypted PMS +--------------------+
|
||||
client PMS--->|server’s public key|--------------->|server’s private key|--->server PMS
|
||||
+-------------------+ +--------------------+
|
||||
```
|
||||
|
||||
在这个过程结束时,`client` 程序和 Google Web 服务器现在拥有相同的 PMS 位。每一方都使用这些位生成一个<ruby>主密码<rt>master secret</rt></ruby>,并立即生成一个称为<ruby>会话密钥<rt>session key</rt></ruby>的对称加密/解密密钥。现在有两个不同但等价的会话密钥,连接的每一方都有一个。在 `client` 的例子中,会话密钥是 AES128 类的。一旦在 `client` 程序和 Google Web 服务器两边生成了会话密钥,每一边的会话密钥就会对双方的对话进行保密。如果任何一方(例如,`client` 程序)或另一方(在这种情况下,Google Web 服务器)要求重新开始握手,握手协议(如 Diffie-Hellman)允许整个 PMS 过程重复进行。
|
||||
|
||||
### 总结
|
||||
|
||||
在命令行上说明的 OpenSSL 操作也可以通过底层库的 API 完成。这两篇文章重点使用了这个实用程序,以保持例子的简短,并专注于加密主题。如果你对安全问题感兴趣,OpenSSL 是一个很好的开始地方,并值得深入研究。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-2
|
||||
|
||||
作者:[Marty Kalin][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mkalindepauledu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_os_rh2x.png?itok=jbRfXinl (A person working.)
|
||||
[2]: https://linux.cn/article-11810-1.html
|
||||
[3]: https://en.wikipedia.org/wiki/HMAC
|
||||
[4]: https://en.wikipedia.org/wiki/Length_extension_attack
|
||||
[5]: https://en.wikipedia.org/wiki/Birthday_problem
|
||||
[6]: http://www.google.com
|
@ -1,42 +1,38 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12477-1.html)
|
||||
[#]: subject: (Bash Script to Check How Long the High CPU/Memory Consumption Processes Runs on Linux)
|
||||
[#]: via: (https://www.2daygeek.com/bash-script-to-check-how-long-the-high-cpu-memory-consumption-processes-runs-on-linux/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
Bash Script to Check How Long the High CPU/Memory Consumption Processes Runs on Linux
|
||||
实用脚本:检查高 CPU / 内存消耗进程
|
||||
======
|
||||
|
||||
In the past, we have written three different articles to identify this using Linux commands.
|
||||
![](https://img.linux.net.cn/data/attachment/album/202008/01/205420jllu1nsngu9qszu5.jpg)
|
||||
|
||||
You can access them immediately by going to the relevant URLs below.
|
||||
过去,我们写了三篇不同的文章来使用 Linux 命令来识别这些进程。
|
||||
|
||||
* **[How to Find High CPU Consumption Processes in Linux][1]**
|
||||
* **[How to Find Out Top Memory Consuming Processes in Linux][2]**
|
||||
* **[Five Ways to Check How Long a Process Has Been Running in Linux][3]**
|
||||
你可以通过下面相关的 URL 立即访问:
|
||||
|
||||
* [如何在 Linux 中找出 CPU 占用高的进程][1]
|
||||
* [如何在 Linux 中找出内存消耗最大的进程][2]
|
||||
* [在 Linux 中如何查找一个命令或进程的执行时间][3]
|
||||
|
||||
本教程中包含两个脚本,它们可以帮助你确定 Linux 上高 CPU/内存消耗进程的运行时间。
|
||||
|
||||
Two scripts are included in this tutorial, which helps you to identify how long the high CPU/memory consumption processes are running on Linux.
|
||||
该脚本将显示进程 ID、进程的所有者、进程的名称以及进程的运行时间。这将帮助你确定哪些(必须事先完成)作业正在超时运行。这可以使用 `ps` 命令来实现。
|
||||
|
||||
The script will show you the process ID, the owner of the process, the name of the process and how long the processes are running.
|
||||
### 什么是 ps 命令
|
||||
|
||||
This will help you identify which jobs are running overtime (which must be completed beforehand).
|
||||
`ps` 是<ruby>进程状态<rt>processes status</rt></ruby>,它显示有关系统上活动/正在运行的进程的信息。
|
||||
|
||||
This can be achieved using the ps command.
|
||||
它提供了当前进程的快照以及详细信息,例如用户名、用户 ID、CPU 使用率、内存使用率、进程开始日期和时间等。
|
||||
|
||||
### What’s ps Command
|
||||
#### 1)检查高 CPU 消耗进程在 Linux 上运行了多长时间的 Bash 脚本
|
||||
|
||||
ps stands for processes status, it display the information about the active/running processes on the system.
|
||||
|
||||
It provides a snapshot of the current processes along with detailed information like username, user id, cpu usage, memory usage, process start date and time command name etc.
|
||||
|
||||
### 1) Bash Script to Check How Long the High CPU Consumption Processes Runs on Linux
|
||||
|
||||
This script will help you to identify how long the high CPU consumption processes has been running on Linux.
|
||||
该脚本将帮助你确定高 CPU 消耗进程在 Linux 上运行了多长时间。
|
||||
|
||||
```
|
||||
# vi /opt/scripts/long-running-cpu-proc.sh
|
||||
@ -56,13 +52,13 @@ done | column -t
|
||||
echo "--------------------------------------------------"
|
||||
```
|
||||
|
||||
Set an executable **[Linux file permission][4]** to **“long-running-cpu-proc.sh”** file.
|
||||
给 `long-running-cpu-proc.sh` 设置可执行的 [Linux 文件权限][4]。
|
||||
|
||||
```
|
||||
# chmod +x /opt/scripts/long-running-cpu-proc.sh
|
||||
```
|
||||
|
||||
When you run this script, you will get an output like the one below.
|
||||
运行此脚本时,你将获得类似以下的输出:
|
||||
|
||||
```
|
||||
# sh /opt/scripts/long-running-cpu-proc.sh
|
||||
@ -82,9 +78,9 @@ daygeek 6301 Web 57:40
|
||||
----------------------------------------------------
|
||||
```
|
||||
|
||||
### 2) Bash Script to Check How Long the High Memory Consumption Processes Runs on Linux
|
||||
#### 2)检查高内存消耗进程在 Linux 上运行了多长时间的 Bash 脚本
|
||||
|
||||
This script will help you to identify how long the top memory consumption processes has been running on Linux.
|
||||
该脚本将帮助你确定最大的内存消耗进程在 Linux 上运行了多长时间。
|
||||
|
||||
```
|
||||
# sh /opt/scripts/long-running-memory-proc.sh
|
||||
@ -104,13 +100,13 @@ done | column -t
|
||||
echo "--------------------------------------------------"
|
||||
```
|
||||
|
||||
Set an executable Linux file permission to **“long-running-memory-proc.sh”** file.
|
||||
给 `long-running-memory-proc.sh` 设置可执行的 Linux 文件权限。
|
||||
|
||||
```
|
||||
# chmod +x /opt/scripts/long-running-memory-proc.sh
|
||||
```
|
||||
|
||||
When you run this script, you will get an output like the one below.
|
||||
运行此脚本时,你将获得类似以下的输出:
|
||||
|
||||
```
|
||||
# sh /opt/scripts/long-running-memory-proc.sh
|
||||
@ -136,14 +132,14 @@ via: https://www.2daygeek.com/bash-script-to-check-how-long-the-high-cpu-memory-
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/how-to-find-high-cpu-consumption-processes-in-linux/
|
||||
[2]: https://www.2daygeek.com/linux-find-top-memory-consuming-processes/
|
||||
[3]: https://www.2daygeek.com/how-to-check-how-long-a-process-has-been-running-in-linux/
|
||||
[1]: https://linux.cn/article-11678-1.html
|
||||
[2]: https://linux.cn/article-11542-1.html
|
||||
[3]: https://linux.cn/article-10261-1.html
|
||||
[4]: https://www.2daygeek.com/understanding-linux-file-permissions/
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (PsiACE)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12056-1.html)
|
||||
[#]: subject: (Building a Messenger App: Conversations)
|
||||
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-conversations/)
|
||||
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
|
||||
@ -10,16 +10,18 @@
|
||||
构建一个即时消息应用(三):对话
|
||||
======
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/30/193824w7xsj2ixs8frsal8.jpg)
|
||||
|
||||
本文是该系列的第三篇。
|
||||
|
||||
* [第一篇:模式][1]
|
||||
* [第二篇:OAuth][2]
|
||||
|
||||
在我们的即时消息应用中,消息表现为两个参与者对话的堆叠。如果你想要开始异常对话,就应该向应用提供你想要交谈的用户,而当对话创建后(如果该对话此前并不存在),就可以向该对话发送消息。
|
||||
在我们的即时消息应用中,消息表现为两个参与者对话的堆叠。如果你想要开始一场对话,就应该向应用提供你想要交谈的用户,而当对话创建后(如果该对话此前并不存在),就可以向该对话发送消息。
|
||||
|
||||
就前端而言,我们可能想要显示一份近期对话列表。并在此处显示对话的最后一条消息以及另一个参与者的姓名和头像。
|
||||
|
||||
在这篇帖子中,我们将会编写一些端点(endpoints)来完成像「创建对话」、「获取对话列表」以及「找到单个对话」这样的任务。
|
||||
在这篇帖子中,我们将会编写一些<ruby>端点<rt>endpoint</rt></ruby>来完成像“创建对话”、“获取对话列表”以及“找到单个对话”这样的任务。
|
||||
|
||||
首先,要在主函数 `main()` 中添加下面的路由。
|
||||
|
||||
@ -45,7 +47,7 @@ func requireJSON(handler http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
```
|
||||
|
||||
如果请求(request)不是 JSON 格式,那么它会返回 `415 Unsupported Media Type`(不支持的媒体类型)错误。
|
||||
如果<ruby>请求<rt>request</rt></ruby>不是 JSON 格式,那么它会返回 `415 Unsupported Media Type`(不支持的媒体类型)错误。
|
||||
|
||||
### 创建对话
|
||||
|
||||
@ -58,7 +60,7 @@ type Conversation struct {
|
||||
}
|
||||
```
|
||||
|
||||
就像上面的代码那样,对话中保持对另一个参与者和最后一条消息的引用,还有一个 bool 类型的字段,用来告知是否有未读消息。
|
||||
就像上面的代码那样,对话中保持对另一个参与者和最后一条消息的引用,还有一个 `bool` 类型的字段,用来告知是否有未读消息。
|
||||
|
||||
```go
|
||||
type Message struct {
|
||||
@ -188,7 +190,7 @@ type Errors struct {
|
||||
}
|
||||
```
|
||||
|
||||
然后,我们开始执行 SQL 事务。收到的仅仅是用户名,但事实上,我们需要知道实际的用户 ID 。因此,事务的第一项内容是查询另一个参与者的 ID 和头像。如果找不到该用户,我们将会返回 `404 Not Found`(未找到) 错误。另外,如果找到的用户恰好和「当前已验证用户」相同,我们应该返回 `403 Forbidden`(拒绝处理)错误。这是由于对话只应当在两个不同的用户之间发起,而不能是同一个。
|
||||
然后,我们开始执行 SQL 事务。收到的仅仅是用户名,但事实上,我们需要知道实际的用户 ID 。因此,事务的第一项内容是查询另一个参与者的 ID 和头像。如果找不到该用户,我们将会返回 `404 Not Found`(未找到) 错误。另外,如果找到的用户恰好和“当前已验证用户”相同,我们应该返回 `403 Forbidden`(拒绝处理)错误。这是由于对话只应当在两个不同的用户之间发起,而不能是同一个。
|
||||
|
||||
然后,我们试图找到这两个用户所共有的对话,所以需要使用 `INTERSECT` 语句。如果存在,只需要通过 `/api/conversations/{conversationID}` 重定向到该对话并将其返回。
|
||||
|
||||
@ -265,11 +267,11 @@ func getConversations(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
```
|
||||
|
||||
该处理程序仅对数据库进行查询。它通过一些联接来查询对话表……首先,从消息表中获取最后一条消息。然后依据「ID 与当前已验证用户不同」的条件,从参与者表找到对话的另一个参与者。然后联接到用户表以获取该用户的用户名和头像。最后,再次联接参与者表,并以相反的条件从该表中找出参与对话的另一个用户,其实就是当前已验证用户。我们会对比消息中的 `messages_read_at` 和 `created_at` 两个字段,以确定对话中是否存在未读消息。然后,我们通过 `user_id` 字段来判定该消息是否属于「我」(指当前已验证用户)。
|
||||
该处理程序仅对数据库进行查询。它通过一些联接来查询对话表……首先,从消息表中获取最后一条消息。然后依据“ID 与当前已验证用户不同”的条件,从参与者表找到对话的另一个参与者。然后联接到用户表以获取该用户的用户名和头像。最后,再次联接参与者表,并以相反的条件从该表中找出参与对话的另一个用户,其实就是当前已验证用户。我们会对比消息中的 `messages_read_at` 和 `created_at` 两个字段,以确定对话中是否存在未读消息。然后,我们通过 `user_id` 字段来判定该消息是否属于“我”(指当前已验证用户)。
|
||||
|
||||
注意,此查询过程假定对话中只有两个用户参与,它也仅仅适用于这种情况。另外,该设计也不很适用于需要显示未读消息数量的情况。如果需要显示未读消息的数量,我认为可以在 `participants` 表上添加一个`unread_messages_count` `INT` 字段,并在每次创建新消息的时候递增它,如果用户已读则重置该字段。
|
||||
|
||||
接下来需要遍历每一条记录,通过扫描每一个存在的对话来建立一个对话切片(an slice of conversations)并在最后进行响应。
|
||||
接下来需要遍历每一条记录,通过扫描每一个存在的对话来建立一个<ruby>对话切片<rt>slice of conversations</rt></ruby>并在最后进行响应。
|
||||
|
||||
### 找到单个对话
|
||||
|
||||
@ -329,7 +331,7 @@ func getConversation(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
在下一篇帖子中,我们将会看到如何创建并列出消息。
|
||||
|
||||
[Souce Code][3]
|
||||
- [源代码][3]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -338,7 +340,7 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
|
||||
作者:[Nicolás Parada][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[PsiACE](https://github.com/PsiACE)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,18 +1,20 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "FSSlc"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-12051-1.html"
|
||||
[#]: subject: "ffsend – Easily And Securely Share Files From Linux Command Line Using Firefox Send Client"
|
||||
[#]: via: "https://www.2daygeek.com/ffsend-securely-share-files-folders-from-linux-command-line-using-firefox-send-client/"
|
||||
[#]: author: "Vinoth Kumar https://www.2daygeek.com/author/vinoth/"
|
||||
|
||||
ffsend - 在 Linux 命令行中通过 FireFox Send 服务来简单安全地分享文件
|
||||
ffsend:在命令行中通过 FireFox Send 分享文件
|
||||
======
|
||||
|
||||
Linux 用户更偏爱使用 `scp` 或 `rsync` 来进行文件或目录的复制拷贝。很多新的可选方式正发生在 Linux 上,因为 Linux 是开源的,所以任何人都可以为 Linux 开发一个安全软件。
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/29/202308w7ormrouomij2dzq.jpg)
|
||||
|
||||
在过去我们已经写了多篇有关安全分享这个话题的文章,它们分别是 **[OnionShare][1]** , **[Magic Wormhole][2]** , **[Transfer.sh][3]** 和 **[Dcp – Dat Copy][4]**.
|
||||
Linux 用户偏爱使用 `scp` 或 `rsync` 来进行文件或目录的复制拷贝。不过在 Linux 上正出现了许多新的可选方式,因为 Linux 是开源的,所以任何人都可以为 Linux 开发一个安全软件。
|
||||
|
||||
在过去我们已经写了多篇有关安全分享这个话题的文章,它们分别是 [OnionShare][1]、[Magic Wormhole][2]、[Transfer.sh][3] 和 [Dcp – Dat Copy][4]。
|
||||
|
||||
今天我们甚至还将继续讨论这个话题,我们将介绍名为 `ffsend` 的工具。
|
||||
|
||||
@ -22,33 +24,33 @@ Linux 用户更偏爱使用 `scp` 或 `rsync` 来进行文件或目录的复制
|
||||
|
||||
它允许我们通过一个安全、私密、加密的链接,使用一个简单的命令来轻易安全地分享文件和目录。
|
||||
|
||||
使用 Firefox 的 Send 服务,文件可以被共享,最大允许的文件大小为 2GB(译者注:现在官网上写的是最大 1GB,登录后最大 2.5GB)。其他人可以通过这个工具或者网页浏览器来下载这些被分享的文件。
|
||||
通过 Firefox 的 Send 服务共享的文件最大大小为 2GB(LCTT 译注:现在官网上写的是最大 1GB,登录后最大 2.5GB)。其他人可以通过这个工具或者网页浏览器来下载这些分享的文件。
|
||||
|
||||
所有的文件总是在客户端被加密,并且秘钥将不会被远程主机所分享。另外,你还可以为上传的文件设置密码。
|
||||
所有的文件都是在客户端加密的,并且秘钥将不会被共享到远程主机。另外,你还可以为上传的文件额外设置一个密码。
|
||||
|
||||
被上传的文件在被下载(默认被下载 1 次,最多可被下载 10 次)后或者 24 小时后,它们将被自动删除。这将确保你的文件不会永远的保留在网络上。
|
||||
上传的文件在下载(默认被下载 1 次,最多可被下载 10 次)后或者 24 小时后,就会自动删除。这将确保你的文件不会一直保留在网络上。
|
||||
|
||||
该工具当前处于 alpha 阶段,使用时请自担风险。而且,当前只有有限个安装选项可用。
|
||||
该工具当前处于 alpha 阶段,使用时请自担风险。而且,当前只有有限的安装方式可用。
|
||||
|
||||
### ffsend 的特点:
|
||||
|
||||
* 全功能且友好的命令行工具
|
||||
* 安全地上传和下载文件与目录
|
||||
* 在客户端总是被加密
|
||||
* 额外的密码保护,密码生成和可配置下载次数限制
|
||||
* 内置文件或目录的打包和解压
|
||||
* 可以简单地管理你的历史分享记录
|
||||
* 能够使用你自己的发送主机
|
||||
* 查看或者删除共享文件
|
||||
* 全功能且使用友好的命令行工具
|
||||
* 可以安全地上传和下载文件与目录
|
||||
* 总是在客户端加密
|
||||
* 可用额外的密码进行保护、密码生成和可配置下载次数限制
|
||||
* 内置的文件或目录的打包和解压
|
||||
* 可以轻松地管理你的历史分享记录
|
||||
* 能够使用你自己的 Send 主机
|
||||
* 审查或者删除共享文件
|
||||
* 精准的错误报告
|
||||
* 由加密或上传下载导致的低内存消耗
|
||||
* 无需集成就可被用在脚本中
|
||||
* 低内存消耗,用于加密或上传下载
|
||||
* 无需交互,可以集成在脚本中
|
||||
|
||||
### 如何在 LInux 中安装 ffsend 呢?
|
||||
|
||||
当前除了 Debian 和 Arch Linux 系统,其他发行版还没有相应的安装包(译者注:这个信息已过时,最新内容请看[这里](https://github.com/timvisee/ffsend#install))。然而,我们可以轻易地根据我们自己的操作系统和架构下载到相应的预编译二进制文件。
|
||||
当前除了 Debian 和 Arch Linux 系统,其他发行版还没有相应的安装包(LCTT 译注:这个信息已过时,最新内容请看[这里](https://github.com/timvisee/ffsend#install))。然而,我们可以轻易地根据我们自己的操作系统和架构下载到相应的预编译二进制文件。
|
||||
|
||||
运行下面的命令来为你的操作系统下载 `ffsend` 最新可用的版本(译者注:当前最新版本为 v0.2.58):
|
||||
运行下面的命令来为你的操作系统下载 `ffsend` 最新可用的版本(LCTT 译注:当前最新版本为 v0.2.58):
|
||||
|
||||
```
|
||||
$ wget https://github.com/timvisee/ffsend/releases/download/v0.1.2/ffsend-v0.1.2-linux-x64.tar.gz
|
||||
@ -91,20 +93,20 @@ To show all subcommands, features and other help:
|
||||
ffsend help [SUBCOMMAND]
|
||||
```
|
||||
|
||||
对于使用基于 Arch Linux 系统的用户可以简单地借助 **[AUR Helper][6]** 来安装它,因为这个包已经在 AUR 软件仓库中了。
|
||||
对于使用基于 Arch Linux 系统的用户可以简单地借助 [AUR 助手][6]来安装它,因为这个包已经在 AUR 软件仓库中了。
|
||||
|
||||
```
|
||||
$ yay -S ffsend
|
||||
```
|
||||
|
||||
对于使用 **`Debian/Ubuntu`** 系统的用户,使用 **[DPKG 命令][7]** 来安装 `ffsend`。
|
||||
对于使用 Debian/Ubuntu 系统的用户,使用 [DPKG 命令][7]来安装 `ffsend`。
|
||||
|
||||
```
|
||||
$ wget https://github.com/timvisee/ffsend/releases/download/v0.1.2/ffsend_0.1.2_amd64.deb
|
||||
$ sudo dpkg -i ffsend_0.1.2_amd64.deb
|
||||
```
|
||||
|
||||
### 如何使用 ffsend 来发送文件?
|
||||
### 如何使用 ffsend
|
||||
|
||||
这并不复杂,我们可以简单地通过下面的语法来发送文件。
|
||||
|
||||
@ -240,56 +242,19 @@ $ ffsend delete https://send.firefox.com/download/69afaab1f9/#5z51_94jtxcUCJNNvf
|
||||
File deleted
|
||||
```
|
||||
|
||||
另外,你还可以通过使用 firefox 浏览其打开 https://send.firefox.com/ 来完成相应的分享。
|
||||
### 如何在浏览器中使用 Send
|
||||
|
||||
另外,你还可以通过使用 firefox 浏览器打开 https://send.firefox.com/ 来完成相应的分享。
|
||||
|
||||
只需要拖拽该文件就可以上传它:
|
||||
|
||||
![][11]
|
||||
|
||||
一旦该文件被下载,它将展示 100% 的下载状态。
|
||||
|
||||
![][12]
|
||||
|
||||
想查看其他的可能选项,请浏览它对应的 man 信息或者帮助页:
|
||||
|
||||
```
|
||||
$ ffsend --help
|
||||
ffsend 0.1.2
|
||||
Tim Visee
|
||||
Easily and securely share files from the command line.
|
||||
A fully featured Firefox Send client.
|
||||
|
||||
USAGE:
|
||||
ffsend [FLAGS] [OPTIONS] [SUBCOMMAND]
|
||||
|
||||
FLAGS:
|
||||
-f, --force Force the action, ignore warnings
|
||||
-h, --help Prints help information
|
||||
-i, --incognito Don't update local history for actions
|
||||
-I, --no-interact Not interactive, do not prompt
|
||||
-q, --quiet Produce output suitable for logging and automation
|
||||
-V, --version Prints version information
|
||||
-v, --verbose Enable verbose information and logging
|
||||
-y, --yes Assume yes for prompts
|
||||
|
||||
OPTIONS:
|
||||
-H, --history Use the specified history file [env: FFSEND_HISTORY]
|
||||
-t, --timeout Request timeout (0 to disable) [env: FFSEND_TIMEOUT]
|
||||
-T, --transfer-timeout Transfer timeout (0 to disable) [env: FFSEND_TRANSFER_TIMEOUT]
|
||||
|
||||
SUBCOMMANDS:
|
||||
upload Upload files [aliases: u, up]
|
||||
download Download files [aliases: d, down]
|
||||
debug View debug information [aliases: dbg]
|
||||
delete Delete a shared file [aliases: del]
|
||||
exists Check whether a remote file exists [aliases: e]
|
||||
help Prints this message or the help of the given subcommand(s)
|
||||
history View file history [aliases: h]
|
||||
info Fetch info about a shared file [aliases: i]
|
||||
parameters Change parameters of a shared file [aliases: params]
|
||||
password Change the password of a shared file [aliases: pass, p]
|
||||
|
||||
The public Send service that is used as default host is provided by Mozilla.
|
||||
This application is not affiliated with Mozilla, Firefox or Firefox Send.
|
||||
```
|
||||
想查看其他的可能选项,请浏览它对应的 man 信息或者帮助页。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -298,16 +263,16 @@ via: https://www.2daygeek.com/ffsend-securely-share-files-folders-from-linux-com
|
||||
作者:[Vinoth Kumar][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[FSSlc](https://github.com/FSSlc)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/vinoth/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/onionshare-secure-way-to-share-files-sharing-tool-linux/
|
||||
[1]: https://linux.cn/article-9177-1.html
|
||||
[2]: https://www.2daygeek.com/wormhole-securely-share-files-from-linux-command-line/
|
||||
[3]: https://www.2daygeek.com/transfer-sh-easy-fast-way-share-files-over-internet-from-command-line/
|
||||
[4]: https://www.2daygeek.com/dcp-dat-copy-secure-way-to-transfer-files-between-linux-systems/
|
||||
[4]: https://linux.cn/article-10516-1.html
|
||||
[5]: https://github.com/timvisee/ffsend
|
||||
[6]: https://www.2daygeek.com/category/aur-helper/
|
||||
[7]: https://www.2daygeek.com/dpkg-command-to-manage-packages-on-debian-ubuntu-linux-mint-systems/
|
@ -0,0 +1,137 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (mengxinayan)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12053-1.html)
|
||||
[#]: subject: (Basic Vim Commands You Need to Know to Work in Vim Editor)
|
||||
[#]: via: (https://www.2daygeek.com/basic-vim-commands-cheat-sheet-quick-start-guide/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
必知必会的 Vim 编辑器基础命令
|
||||
======
|
||||
|
||||
如果你是一名系统管理员或者开发者,当你在终端工作时有时会需要编辑一个文件。在 Linux 系统中有几种文件编辑器,你可以根据需求选择合适的文件编辑器。在这里,我想推荐 Vim 编辑器。
|
||||
|
||||
### 为什么推荐 Vim 编辑器
|
||||
|
||||
相对于创建新文件,你更多是修改已经存在的文件。在这种情况下,Vim 快捷键可以有效地满足你的需求。
|
||||
|
||||
下列文章可以帮助你了解对文件和目录的操作。
|
||||
|
||||
- [Linux 基础:对文件和目录进行操作的 Linux 和 Unix 命令][1]
|
||||
- [在 Linux 中查看不同文件格式的 10 种方法][2]
|
||||
|
||||
### 什么是 Vim
|
||||
|
||||
Vim 是被 Linux 管理员和开发者广泛使用的最流行和功能强大的编辑器之一。它可以通过高度的自定义配置来提高文本编辑效率。它是在众多 Unix 默认安装的 Vi 编辑器的升级版。
|
||||
|
||||
Vim 通常被称为“程序员的编辑器”,但并不限于此,它也可用于编辑任何类型的文件。它具有许多功能,例如:多次撤销、多窗口和缓冲区、语法高亮、命令行编辑、文件名补全、可视选择等等。你可以使用 `:help` 命令来获取在线帮助。
|
||||
|
||||
### 理解 Vim 的模式
|
||||
|
||||
Vim 有两种模式,详细介绍如下:
|
||||
|
||||
**命令模式:** 当启动 Vim 编辑器后,默认处在命令模式下。你可以在文件中移动并且修改内容,剪切、复制和粘贴文件的一部分,同时发出命令执行更多操作(按 `ESC` 键进入命令模式)
|
||||
|
||||
**插入模式:** 插入模式用于在给定的文档位置插入文本(按 `i` 键进入插入模式)
|
||||
|
||||
### 我如何知道我正使用哪种 Vim 模式呢?
|
||||
|
||||
如果你正在使用插入模式,你会在编辑器的底部看到 `INSERT`。如果编辑器底部没有显示任何内容,或者在编辑器底部显示了文件名,则处于 “命令模式”。
|
||||
|
||||
### 命令模式下的光标移动
|
||||
|
||||
Vim 快捷键允许你使用不同的方式来移动光标:
|
||||
|
||||
* `G` – 跳转到文件最后一行
|
||||
* `gg` – 跳转到文件首行
|
||||
* `$` – 跳转到行末尾
|
||||
* `0`(数字 0) – 跳转到行开头
|
||||
* `w` – 跳转到下一个单词的开始(单词的分隔符可以是空格或其他符号)
|
||||
* `W` – 跳转到下一个单词的开始(单词的分隔符只能是空格)
|
||||
* `b` – 跳转到下一个单词的末尾(单词的分隔符可以是空格或其他符号)
|
||||
* `B` – 跳转到下一个单词的末尾(单词的分隔符只能是空格)
|
||||
|
||||
* `PgDn` 键 – 向下移动一页
|
||||
* `PgUp` 键 – 向上移动一页
|
||||
* `Ctrl+d` – 向下移动半页
|
||||
* `Ctrl+u` – 向上移动半页
|
||||
|
||||
### 插入模式:插入文字
|
||||
|
||||
下面的 Vim 快捷键允许你根据需要在光标的不同位置插入内容。
|
||||
|
||||
* `i` – 在光标之前插入
|
||||
* `a` – 在光标之后插入
|
||||
* `I` – 在光标所在行的开头插入。当光标位于行中间时,这个键很有用
|
||||
* `A` – 在光标所在行的末尾插入。
|
||||
* `o` – 在光标所在行的下面插入新行
|
||||
* `O` – 在光标所在行的上面插入新行
|
||||
* `ea` – 在单词的末尾插入
|
||||
|
||||
### 拷贝、粘贴和删除一行
|
||||
|
||||
* `yy` – 复制一行
|
||||
* `p` / `P` – 将内容粘贴到光标之后 / 之前
|
||||
* `dd` – 删除一行
|
||||
* `dw` – 删除一个单词
|
||||
|
||||
### 在 Vim 中搜索和替换匹配的模式
|
||||
|
||||
* `/模式` – 向后搜索给定的模式
|
||||
* `?模式` – 向前搜索给定的模式
|
||||
* `n` – 向后重复搜索之前给定的模式
|
||||
* `N` – 向前重复搜索之前给定的模式
|
||||
* `:%s/旧模式/新模式/g` – 将文件中所有的旧模式替换为新模式
|
||||
* `:s/旧模式/新模式/g` – 将当前行中所有的旧模式替换为新模式
|
||||
* `:%s/旧模式/新模式/gc` – 逐个询问是否文件中的旧模式替换为新模式
|
||||
|
||||
### 如何在 Vim 编辑器中跳转到特定行
|
||||
|
||||
你可以根据需求以两种方式达到该目的,如果你不知道行号,建议采用第一种方法。
|
||||
|
||||
通过打开文件并运行下面的命令来显示行号
|
||||
|
||||
```
|
||||
:set number
|
||||
```
|
||||
|
||||
当你设置好显示行号后,按 `:n` 跳转到相应的行号。例如,如果你想跳转到第 15 行,请输入:
|
||||
|
||||
```
|
||||
:15
|
||||
```
|
||||
|
||||
如果你已经知道行号,请使用以下方法在打开文件时直接跳转到相应行。例如,如果在打开文件时直接跳转到 20 行,请输入下面的命令:
|
||||
|
||||
```
|
||||
$ vim +20 [文件名]
|
||||
```
|
||||
|
||||
### 撤销操作/恢复上一次操作/重复上一次操作
|
||||
|
||||
* `u` – 撤销更改
|
||||
* `Ctrl+r` – 恢复更改
|
||||
* `.` – 重复上一条命令
|
||||
|
||||
### 保存和退出 Vim
|
||||
|
||||
* `:w` – 保存更改但不退出 vim
|
||||
* `:wq` – 写并退出
|
||||
* `:q!` – 强制退出
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/basic-vim-commands-cheat-sheet-quick-start-guide/
|
||||
|
||||
作者:[Magesh Maruthamuthu][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[萌新阿岩](https://github.com/mengxinayan)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/linux-basic-commands-file-directory-manipulation/
|
||||
[2]: https://www.2daygeek.com/unix-linux-command-to-view-file/
|
@ -1,29 +1,32 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12049-1.html)
|
||||
[#]: subject: (Run Kubernetes on a Raspberry Pi with k3s)
|
||||
[#]: via: (https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s)
|
||||
[#]: author: (Lee Carpenter https://opensource.com/users/carpie)
|
||||
|
||||
使用 K3s 在树莓派上运行 Kubernetes 集群
|
||||
======
|
||||
> 跟随接下来的介绍,自己搭建一个三节点的 Kubernetes 集群。
|
||||
|
||||
![A ship wheel with someone steering][1]
|
||||
> 跟随接下来的介绍,自己搭建一个三节点的 Kubernetes 集群。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/29/121559p44e3dfrerf3zver.jpg)
|
||||
|
||||
我对在树莓派上搭建 [Kubernetes][2] 集群已经感兴趣很长时间了,只要照着网上的教程,我可以在由三个树莓派组成的集群中搭建一套 Kubernetes 并正常运行。但在这种情况下,主节点上的内存和 CPU 资源捉襟见肘,执行 Kubernetes 任务的时候往往性能不佳,想要升级 Kubernetes 就更不可能了。
|
||||
|
||||
这个时候,我发现了 [K3s][3] 这个项目。K3s 誉为可用于资源受限环境下的轻量级 Kubernetes,它还针对 ARM 处理器做出了优化,这让 Kubernetes 集群可以在树莓派上运行得更好。在下文中,我们将会使用 K3s 来创建一个 Kubernetes 集群。
|
||||
这个时候,我非常激动地发现了 [K3s][3] 这个项目。K3s 被誉为在可用于资源受限环境下的轻量级 Kubernetes,它还针对 ARM 处理器做出了优化,这让 Kubernetes 集群可以在树莓派上运行得更好。在下文中,我们将会使用 K3s 来创建一个 Kubernetes 集群。
|
||||
|
||||
- [video](https://youtu.be/6PqxJhV-t1s)
|
||||
|
||||
### 准备
|
||||
|
||||
要按照本文介绍的方式创建 Kubernetes 集群,首先需要准备:
|
||||
|
||||
* 至少一个树莓派(包括 SD 卡和电源)
|
||||
* 网线
|
||||
* 将所有树莓派连接到一起的交换机或路由器
|
||||
* 至少一个树莓派(包括 SD 卡和电源)
|
||||
* 网线
|
||||
* 将所有树莓派连接到一起的交换机或路由器
|
||||
|
||||
我们会通过在线安装的方式安装 K3s,因此还需要可以连接到互联网。
|
||||
|
||||
@ -35,7 +38,6 @@
|
||||
|
||||
为了不需要通过 IP 来引用某一个节点,我们将每个节点的主机名记录到 PC 的 `/etc/hosts` 文件当中:
|
||||
|
||||
|
||||
```
|
||||
echo -e "192.168.0.50\tkmaster" | sudo tee -a /etc/hosts
|
||||
echo -e "192.168.0.51\tknode1" | sudo tee -a /etc/hosts
|
||||
@ -48,20 +50,17 @@ echo -e "192.168.0.52\tknode2" | sudo tee -a /etc/hosts
|
||||
|
||||
在主节点上安装 Raspbian 完成后,启动树莓派并通过 `ssh` 连接上去:
|
||||
|
||||
|
||||
```
|
||||
ssh pi@kmaster
|
||||
```
|
||||
|
||||
执行以下命令安装 K3s:
|
||||
|
||||
在主节点上执行以下命令安装 K3s:
|
||||
|
||||
```
|
||||
curl -sfL https://get.k3s.io | sh -
|
||||
```
|
||||
|
||||
等到命令跑完以后,一个单节点集群就已经运行起来了。还在这个树莓派上执行:
|
||||
|
||||
等到命令跑完以后,一个单节点集群就已经运行起来了。让我们检查一下,还在这个树莓派上执行:
|
||||
|
||||
```
|
||||
sudo kubectl get nodes
|
||||
@ -69,7 +68,6 @@ sudo kubectl get nodes
|
||||
|
||||
就会看到这样的输出:
|
||||
|
||||
|
||||
```
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
kmaster Ready master 2m13s v1.14.3-k3s.1
|
||||
@ -77,8 +75,7 @@ kmaster Ready master 2m13s v1.14.3-k3s.1
|
||||
|
||||
### 获取<ruby>连接令牌<rt>join token</rt></ruby>
|
||||
|
||||
之后我们需要部署工作节点。在工作节点上安装 K3s 的时候,会需要用到连接令牌,它放置在主节点的文件系统上。首先把连接令牌打印出来保存以便后续使用:
|
||||
|
||||
之后我们需要部署工作节点。在工作节点上安装 K3s 的时候,会需要用到连接令牌,它放置在主节点的文件系统上。首先把连接令牌保存出来以便后续使用:
|
||||
|
||||
```
|
||||
sudo cat /var/lib/rancher/k3s/server/node-token
|
||||
@ -90,17 +87,15 @@ sudo cat /var/lib/rancher/k3s/server/node-token
|
||||
|
||||
启动主机名为 `knode1` 的树莓派,通过 `ssh` 连接上去:
|
||||
|
||||
|
||||
```
|
||||
ssh pi@knode1
|
||||
```
|
||||
|
||||
在这个树莓派上,安装 K3s 的过程和之前差不多,但需要另外加上一些参数,表示它是一个工作节点,需要连接到一个已有的集群上:
|
||||
|
||||
|
||||
```
|
||||
curl -sfL <http://get.k3s.io> | K3S_URL=<https://192.168.0.50:6443> \
|
||||
K3S_TOKEN=<刚才保存下来的连接令牌> sh -
|
||||
curl -sfL http://get.k3s.io | K3S_URL=https://192.168.0.50:6443 \
|
||||
K3S_TOKEN=刚才保存下来的连接令牌 sh -
|
||||
```
|
||||
|
||||
`K3S_TOKEN` 的值需要替换成刚才保存下来的实际的连接令牌。完成之后,在主机名为 `knode2` 的树莓派上重复这个安装过程。
|
||||
@ -109,20 +104,17 @@ K3S_TOKEN=<刚才保存下来的连接令牌> sh -
|
||||
|
||||
现在如果我们想要查看或者更改集群,都必须 `ssh` 到集群的主节点才能使用 `kubectl`,这是比较麻烦的。因此我们会将 `kubectl` 放到 PC 上使用。首先,在主节点上获取一些必要的配置信息,`ssh` 到 `kmaster` 上执行:
|
||||
|
||||
|
||||
```
|
||||
sudo cat /etc/rancher/k3s/k3s.yaml
|
||||
```
|
||||
|
||||
复制上面命令的输出,创建一个目录用来放置配置文件:
|
||||
|
||||
复制上面命令的输出,然后在你的 PC 上创建一个目录用来放置配置文件:
|
||||
|
||||
```
|
||||
mkdir ~/.kube
|
||||
```
|
||||
|
||||
将复制好的内容写入到 `~/.kube/config` 文件中,然后将
|
||||
|
||||
将复制好的内容写入到 `~/.kube/config` 文件中,然后编辑该文件,将
|
||||
|
||||
```
|
||||
server: https://localhost:6443
|
||||
@ -130,26 +122,22 @@ server: https://localhost:6443
|
||||
|
||||
改为
|
||||
|
||||
|
||||
```
|
||||
server: https://kmaster:6443
|
||||
```
|
||||
|
||||
出于安全考虑,只对自己保留这个配置文件的读写权限:
|
||||
|
||||
|
||||
```
|
||||
chmod 600 ~/.kube/config
|
||||
```
|
||||
|
||||
如果 PC 上还没有安装 `kubectl` 的话,就可以开始安装了。Kubernetes 官方网站上有各种平台安装 `kubectl` 的[方法说明][5],我使用的是 Ubuntu 的衍生版 Linux Mint,所以我的安装方法是这样的:
|
||||
|
||||
|
||||
```
|
||||
sudo apt update && sudo apt install -y apt-transport-https
|
||||
curl -s <https://packages.cloud.google.com/apt/doc/apt-key.gpg> | sudo apt-key add -
|
||||
echo "deb <https://apt.kubernetes.io/> kubernetes-xenial main" | \
|
||||
sudo tee -a /etc/apt/sources.list.d/kubernetes.list
|
||||
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
|
||||
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
|
||||
sudo apt update && sudo apt install kubectl
|
||||
```
|
||||
|
||||
@ -157,14 +145,12 @@ sudo apt update && sudo apt install kubectl
|
||||
|
||||
现在在 PC 上就可以查看 Kubernetes 集群了:
|
||||
|
||||
|
||||
```
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
输出大概会是这样:
|
||||
|
||||
|
||||
```
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
kmaster Ready master 12m v1.14.3-k3s.1
|
||||
@ -176,11 +162,10 @@ knode1 Ready worker 103s v1.14.3-k3s.1
|
||||
|
||||
### K3s 的彩蛋
|
||||
|
||||
如果执行 `kubectl get pods --all-namespaces`,就会看到其它服务的一些 pod,比如 [Traefik][6]。Traefik 在这里起到是反向代理和负载均衡器的作用,它可以让流量从单个入口进入集群后引导到集群中的各个服务。Kubernetes 支持这种机制,但 Kubernetes 本身不提供这个功能,因此 Traefik 是一个不错的选择,K3s 安装后立即可用的优点也得益于此。
|
||||
如果执行 `kubectl get pods --all-namespaces`,就会看到其它服务的一些 Pod,比如 [Traefik][6]。Traefik 在这里起到是反向代理和负载均衡器的作用,它可以让流量从单个入口进入集群后引导到集群中的各个服务。Kubernetes 支持这种机制,但 Kubernetes 本身不提供这个功能,因此 Traefik 是一个不错的选择,K3s 安装后立即可用的优点也得益于此。
|
||||
|
||||
在后续的文章中,我们会继续探讨 Traefik 在 Kubernetes ingress 中的应用,以及在集群中部署其它组件。敬请关注。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s
|
||||
@ -188,7 +173,7 @@ via: https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s
|
||||
作者:[Lee Carpenter][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/) 荣誉推出
|
||||
|
@ -0,0 +1,104 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12052-1.html)
|
||||
[#]: subject: (How to write effective documentation for your open source project)
|
||||
[#]: via: (https://opensource.com/article/20/3/documentation)
|
||||
[#]: author: (Kevin Xu https://opensource.com/users/kevin-xu)
|
||||
|
||||
如何为你的开源项目编写实用的文档
|
||||
======
|
||||
|
||||
> 一份优质的文档可以让很多用户对你的项目路人转粉。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/29/215343srdknc1o8kplbu8z.jpg)
|
||||
|
||||
好的代码很多时候并不代表一切。或许你能用最精巧的代码解决了世界上最迫切需要解决的问题,但如果你作为一个开源开发者,没能用准确的语言将你的作品公之于世,你的代码也只能成为沧海遗珠。因此,技术写作和文档编写是很重要的技能。
|
||||
|
||||
一般来说,项目中的文档是最受人关注的部分,很多用户会通过文档来决定自己是否应该对某个项目开始学习或研究。所以,我们不能忽视技术写作和文档编写的工作,尤其要重点关注其中的“<ruby>入门<rt>Getting Started</rt></ruby>”部分,这会对你项目的发展起到关键性的作用。
|
||||
|
||||
对于很多人来说,写作是一件令人厌烦甚至恐惧的事情。我们这些工程师出身的人,更多学习的是“写代码”而不是学习“为代码写文档”。不少人会把英语作为自己的第二语言或者第三语言,他们可能会对英语写作感到不自信甚至害怕(我的母语是汉语,英语是作为我的第二语言学习的,所以我也能感受到这种痛苦)。
|
||||
|
||||
但如果你希望自己的项目能在全球范围内产生一定的影响力,英语就是你必须使用的语言,这是一个无法避免的现实。但不必害怕,我在写这篇文章的时候就考虑到了这些可能带来的挑战,并给出了我的一些建议。
|
||||
|
||||
### 五条有用的写作建议
|
||||
|
||||
这五条建议你马上就可以用起来,尽管看起来似乎有些浅显,但在技术写作时却经常被忽视。
|
||||
|
||||
1. **使用主动语态**:感受一下[主动语态][2]下的“你可以这样更改配置(You can change these configurations by...)”和被动语态下的“配置可以这样更改(These configurations can be changed by…)”有什么不同之处。
|
||||
2. **使用简洁明了的句子**:可以借助 [Hemingway App][3] 或者 [Grammarly][4] 这样的工具,尽管它们并不开源。
|
||||
3. **保持条理性**:你可以在文档中通过写标题、划重点、引链接等方式,把各类信息划分为不同的部分,避免将所有内容都杂糅在一大段冗长的文字当中。
|
||||
4. **提高可读性**:除了单纯的文字之外,运用图表也是从多种角度表达的手段之一。
|
||||
5. **注意拼写和语法**:必须记得检查文档中是否有拼写错误或者语法错误。
|
||||
|
||||
只要在文档的写作和编辑过程中应用到这些技巧,你就能够和读者建立起沟通和信任。
|
||||
|
||||
* **高效沟通**:对于工程师们来说,阅读长篇大论的冗长文字,还不如去看小说。在阅读技术文档时,他们总是希望能够从中快速准确地获取到有用的信息。因此,技术文档的最佳风格应该是精简而有效的,不过这并不代表文档中不能出现类似幽默、emoji 甚至段子这些东西,这些元素可以当你的文档更有个性、更使人印象深刻。当然,具体的实现方式就因人而异了
|
||||
* **建立信任**:你需要取得文档读者们的信任,这在一个项目的前期尤为重要。读者对你的信任除了来源于你代码的质量,还跟你文档编写的质量有关。所以你不仅要打磨代码,还要润色好相关的文档,这也是上面第 5 点建议拼写和语法检查的原因。
|
||||
|
||||
### 从编写“入门”文档开始
|
||||
|
||||
现在,最需要花费功夫的应该就是“入门”部分了,这是一篇技术文档最重要的部分,[二八定律][5]在这里得到了充分体现:访问一个项目的大部分流量都会落在项目文档上,而访问项目文档的大部分流量则会落在文档的“入门”部分中。因此,如果文档的“入门”部分写得足够好,项目就会吸引到很多用户,反之,用户会对你的项目敬而远之。
|
||||
|
||||
那么如何写好“入门”部分呢?我建议按照以下三步走:
|
||||
|
||||
1. **任务化**:入门指南应该以任务为导向。这里的任务指的是对于开发者来说可以完成的离散的小项目,而不应该包含太多涉及到体系结构、核心概念等的抽象信息,因此在“入门”部分只需要提供一个简单明了的概述就可以了。也不要在“入门”部分大谈这个项目如何优秀地解决了问题,这个话题可以放在文档中别的部分进行说明。总而言之,“入门”部分最好是给出一些主要的操作步骤,这样显得开门见山。
|
||||
2. **30 分钟内能够完成**:这一点的核心是耗时尽可能短,不宜超过 30 分钟,这个时间上限是考虑到用户可能对你的项目并不了解。这一点很重要,大部分愿意浏览文档的人都是有技术基础的,但对你的项目也仅仅是一知半解。首先让这些读者尝试进行一些相关操作,在收到一定效果后,他们才会愿意花更多时间深入研究整个项目。因此,你可以从耗时这个角度来评估你的文档“入门”部分有没有需要改进之处。
|
||||
3. **有意义的任务**:这里“有意义”的含义取决于你的开源项目。最重要的是认真思考并将“入门”部分严格定义为一项任务,然后交给你的读者去完成。这个项目的价值应该在这项有意义的任务中有所体现,不然读者可能会感觉这是一个浪费时间的行为。
|
||||
|
||||
提示:假如你的项目是一个分布式数据库,那么达到“整个集群在某些节点故障的情况下可以不中断地保持可用”的目标就可以认为是“有意义”的;假如你的项目是一个数据分析工具或者是商业智能工具,“有意义”的目标也可以是“加载数据后能快速生成多种可视化效果的仪表板”。总之,无论你的项目需要达到什么“有意义”的目标,都应该能在笔记本电脑上本地快速实现。
|
||||
|
||||
[Linkerd 入门][6]就是一个很好的例子。Linkerd 是一个开源的 Kubernetes <ruby>服务网格<rt>Service Mesh</rt></ruby>,当时我对 Kubernetes 了解并不多,也不熟悉服务网格。但我在自己的笔记本电脑上很轻松地就完成了其中的任务,同时也加深了对服务网格的理解。
|
||||
|
||||
上面提到的三步过程是一个很有用的框架,对一篇文档“入门”部分的设计和量化评估很有帮助。今后你如果想将你的[开源项目产品化][7],这个框架还可能对<ruby>实现价值的时间<rt>time-to-value</rt></ruby>产生影响。
|
||||
|
||||
### 其它核心部分
|
||||
|
||||
认真写好“入门”部分之后,你的文档中还需要有这五个部分:架构设计、生产环境使用指导、使用案例、参考资料以及未来展望,这五个部分在一份完整的文档中是必不可少的。
|
||||
|
||||
* **架构设计**:这一部分需要深入探讨整个项目架构设计的依据,“入门”部分中那些一笔带过的关键细节就应该在这里体现。在产品化过程中,这个部分将会是[产品推广计划][8]的核心,因此通常会包含一些可视化呈现的内容,期望的效果是让更多用户长期参与到项目中来。
|
||||
* **生产环境使用指导**:对于同一个项目,在生产环境中部署比在笔记本电脑上部署要复杂得多。因此,指导用户认真使用就尤为重要。同时,有些用户可能对项目很感兴趣,但对生产环境下的使用有所顾虑,而指导和展示的过程则正好能够吸引到这类潜在的用户。
|
||||
* **使用案例**:<ruby>社会认同<rt>social proof</rt></ruby>的力量是有目共睹的,所以很有必要列出正在生产环境使用这个项目的其他用户,并把这些信息摆放在显眼的位置。这个部分的浏览量甚至仅次于“入门”部分。
|
||||
* **参考资料**:这个部分是对项目的一些详细说明,让用户得以进行详细的研究以及查阅相关信息。一些开源作者会在这个部分事无巨细地列出项目中的每一个细节和<ruby>边缘情况<rt>edge case</rt></ruby>,这种做法可以理解,但不推荐在项目初期就在这个部分花费过多的时间。你可以采取更折中的方式,在质量和效率之间取得平衡,例如提供一些相关社区的链接、Stack Overflow 上的标签或单独的 FAQ 页面。
|
||||
* **未来展望**:你需要制定一个简略的时间表,规划这个项目的未来发展方向,这会让用户长期保持兴趣。尽管项目在当下可能并不完美,但要让用户知道你仍然有完善这个项目的计划。这个部分也能让整个社区构建一个强大的生态,因此还要向用户提供表达他们对未来展望的看法的交流区。
|
||||
|
||||
以上这几个部分或许还没有在你的文档中出现,甚至可能会在后期才能出现,尤其是“使用案例”部分。尽管如此,还是应该在文档中逐渐加入这些部分。如果用户对“入门”部分已经感觉良好,那以上这几个部分将会提起用户更大的兴趣。
|
||||
|
||||
最后,请在“入门”部分、README 文件或其它显眼的位置注明整个项目所使用的许可证。这个细节会让你的项目更容易通过最终用户的审核。
|
||||
|
||||
### 花 20% 的时间写作
|
||||
|
||||
一般情况下,我建议把整个项目 10% 到 20% 的时间用在文档写作上。也就是说,如果你是全职进行某一个项目的,文档写作需要在其中占半天到一天。
|
||||
|
||||
再细致一点,应该将写作纳入到常规的工作流程中,这样它就不再是一件孤立的琐事,而是日常的事务。文档写作应该随着工作进度同步进行,切忌将所有写作任务都堆积起来最后完成,这样才可以帮助你的项目达到最终目标:吸引用户、获得信任。
|
||||
|
||||
* * *
|
||||
|
||||
*特别鸣谢云原生计算基金会的布道师 [Luc Perkins][9] 给出的宝贵意见。*
|
||||
|
||||
*本文首发于 [COSS Media][10] 并经许可发布。*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/documentation
|
||||
|
||||
作者:[Kevin Xu][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/kevin-xu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-docdish-typewriter-pink.png?itok=OXJBtyYf (A pink typewriter)
|
||||
[2]: https://www.grammar-monster.com/glossary/active_voice.htm
|
||||
[3]: http://www.hemingwayapp.com/
|
||||
[4]: https://www.grammarly.com/
|
||||
[5]: https://en.wikipedia.org/wiki/Pareto_principle
|
||||
[6]: https://linkerd.io/2/getting-started/
|
||||
[7]: https://opensource.com/article/19/11/products-open-source-projects
|
||||
[8]: https://opensource.com/article/20/2/product-marketing-open-source-project
|
||||
[9]: https://twitter.com/lucperkins
|
||||
[10]: https://coss.media/open-source-documentation-technical-writing-101/
|
@ -1,36 +1,38 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12048-1.html)
|
||||
[#]: subject: (4 Markdown tools for the Linux command line)
|
||||
[#]: via: (https://opensource.com/article/20/3/markdown-apps-linux-command-line)
|
||||
[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
|
||||
|
||||
4 个 Linux 命令行下的 Markdown 工具
|
||||
======
|
||||
命令行 Markdown 工具快速、强大、灵活。以下是 4 个值得试一下的工具。
|
||||
![A person working.][1]
|
||||
|
||||
在处理 [Markdown][2] 格式的文件时,命令行工具会占据主导地位。它们轻巧、快速、强大、灵活,它们大多数都遵循 Unix 哲学只做好一件事。
|
||||
> 命令行 Markdown 工具快速、强大、灵活。以下是 4 个值得试一下的工具。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/29/112110pbd22dku6b2g6ku6.jpg)
|
||||
|
||||
(在 Linux 上)在处理 [Markdown][2] 格式的文件时,命令行工具会占据主导地位。它们轻巧、快速、强大、灵活,它们大多数都遵循 Unix 哲学只做好一件事。
|
||||
|
||||
看一下这四个程序,它们可以帮助你在命令行中更有效地处理 Markdown 文件。
|
||||
|
||||
### mdless
|
||||
|
||||
如果你使用过一段时间的 Linux 命令行,那么你可能对名为 [less][3] 的文本查看器很熟悉。当然,你可以使用 less 查看 Markdown 文件,但结果有点枯燥。如何在终端中查看 Markdown 文件效果更好一点?来使用 [mdless][4]。
|
||||
如果你使用过一段时间的 Linux 命令行,那么你可能对名为 [less][3] 的文本查看器很熟悉。当然,你可以使用 `less` 查看 Markdown 文件,但结果有点枯燥。如何在终端中查看 Markdown 文件效果更好一点?来使用 [mdless][4]。
|
||||
|
||||
![mdless][5]
|
||||
|
||||
你可以使用键盘上的箭头键四处移动,并且 mdless 提供了很好的搜索功能。
|
||||
你可以使用键盘上的箭头键四处移动,并且 `mdless` 提供了很好的搜索功能。
|
||||
|
||||
mdless 不仅会显示文本,而且还会渲染标题、粗体和斜体等格式。它还可以显示表格并语法高亮代码块。你还可以创建一个或多个主题文件来[定制][6] mdless 的外观。
|
||||
`mdless` 不仅会显示文本,而且还会渲染标题、粗体和斜体等格式。它还可以显示表格并语法高亮代码块。你还可以创建一个或多个主题文件来[定制][6] `mdless` 的外观。
|
||||
|
||||
### Markdown lint 工具
|
||||
|
||||
你在快速输入时会犯错误。如果你在使用 Markdown(或其他任何标记语言)时丢失了一些格式,那么在将文件转换为另一种格式时可能会有问题。
|
||||
|
||||
程序员通常使用名为 _linter_ 的工具来检查语法是否正确。你可以使用 [Markdown lint 工具][7]对 Markdown 执行相同的操作。
|
||||
程序员通常使用名为 linter 的工具来检查语法是否正确。你可以使用 [Markdown lint 工具][7]对 Markdown 执行相同的操作。
|
||||
|
||||
在你对 Markdown 文件运行该工具时,它会根据[规则集][8]检查格式。这些规则控制着文档的结构,包括标题级别的顺序、不正确的缩进和间距、代码块问题、文件中存在 HTML 等等。
|
||||
|
||||
@ -40,25 +42,25 @@ mdless 不仅会显示文本,而且还会渲染标题、粗体和斜体等格
|
||||
|
||||
### mdmerge
|
||||
|
||||
合并任何类型的文件可能会很痛苦。例如,我在整理一本电子书。它是一篇文章集,最初发布在我的[每周邮件][10]中。这些文章都放在单独的文件中,作为受虐狂,我以凌乱,手动的方式将它们组合在一起。
|
||||
合并任何类型的文件可能会很痛苦。例如,我在整理一本电子书。它是一篇文章集,最初发布在我的[每周邮件][10]中。这些文章都放在单独的文件中,作为受虐狂,我以凌乱、手动的方式将它们组合在一起。
|
||||
|
||||
我希望在开始项目之前就了解了 [mdmerge][11]。这样我可以节省很多时间和精力。
|
||||
我希望在开始这个项目之前就知道 [mdmerge][11]。这样我可以节省很多时间和精力。
|
||||
|
||||
mdmerge,你可能已经从名称中猜到了它的作用,它将两个或多个 Markdown 文件合并为一个文件。你无需在命令行中输入文件名。相反,你可以将它们添加到名为 book.txt 的文件中,并将其用作 mdmerge 的输入文件。
|
||||
`mdmerge`,你可能已经从名称中猜到了它的作用,它将两个或多个 Markdown 文件合并为一个文件。你无需在命令行中输入文件名。相反,你可以将它们添加到名为 `book.txt` 的文件中,并将其用作 `mdmerge` 的输入文件。
|
||||
|
||||
这并不是 mdmerge 能做的一切。你可以添加对另一个文档的引用(使用 Markdown 格式引用或一段源代码),然后将其放入主文档中。这样一来,你就可以创建针对特定受众定制的[主文档] [12]。
|
||||
这并不是 `mdmerge` 能做的一切。你可以添加对另一个文档的引用(使用 Markdown 格式引用或一段源代码),然后将其放入主文档中。这样一来,你就可以创建针对特定受众定制的[主文档][12]。
|
||||
|
||||
mdmerge 不会是你一直使用的程序之一。当你需要时,你会很高兴硬盘上有它。
|
||||
`mdmerge` 不会是你经常使用的程序。但当你需要时,你会很高兴硬盘上有它。
|
||||
|
||||
### bashblog
|
||||
|
||||
[bashblog][13] 并不是严格上的 Markdown 工具。它获取 Markdown 文件,并使用它们来构建简单的博客或网站。你可以将 bashblog 视为[静态站点生成器][14],但是它没有很多脆弱的依赖关系。一切几乎都在一个不到 50KB 的 shell 脚本中。
|
||||
严格说 [bashblog][13] 并不是 Markdown 工具。它获取 Markdown 文件,并使用它们来构建简单的博客或网站。你可以将 bashblog 视为[静态站点生成器][14],但是它没有很多脆弱的依赖关系。一切几乎都在一个不到 50KB 的 shell 脚本中。
|
||||
|
||||
要使用 bashblog,只需在计算机上安装 Markdown 处理器即可。在此,你可以编辑 Shell 脚本添加有关博客的信息,例如标题、名字、社交媒体链接等。然后运行脚本。之后会在默认文本编辑器中新建一篇文章。开始输入。
|
||||
要使用 bashblog,只需在计算机上安装 Markdown 处理器即可。在此,你可以编辑 Shell 脚本添加有关博客的信息,例如标题、名字、社交媒体链接等。然后运行该脚本。之后会在默认文本编辑器中新建一篇文章。开始输入。
|
||||
|
||||
保存文章后,你可以发布它或将其另存为草稿。如果你选择发布文章,那么 bashblog 会将你的博客、文章和所有内容生成为一组 HTML 文件,你可以将它们上传到 Web 服务器。
|
||||
|
||||
它开箱即用,你的博客会平淡无奇,但可以使用。你可以根据自己喜好编辑站点的 CSS 文件来改变外观。
|
||||
它开箱即用,你的博客或许会平淡无奇,但可以使用。你可以根据自己喜好编辑站点的 CSS 文件来改变外观。
|
||||
|
||||
![bashblog][15]
|
||||
|
||||
@ -66,12 +68,12 @@ mdmerge 不会是你一直使用的程序之一。当你需要时,你会很高
|
||||
|
||||
当然,Panddoc 是一个非常强大的工具,可以将 Markdown 文件转换为其他标记语言。但是,在命令行上使用 Markdown 要比 Pandoc 多。
|
||||
|
||||
如果你需要 Pandoc 修复,请查看我们在 Opensource.com 上发布的文章:
|
||||
如果你需要 Pandoc,请查看我们发布的文章:
|
||||
|
||||
* [使用 Pandoc 在命令行中转换文件][16]
|
||||
* [使用 Pandoc 将你的书变成网站和 ePub] [17]
|
||||
* [如何使用 Pandoc 生成论文] [18]
|
||||
* [使用 Pandoc 将 Markdown 文件转换为 word 文档] [19]
|
||||
* [在命令行使用 Pandoc 进行文件转换][16]
|
||||
* [使用 Pandoc 将你的书转换成网页和电子书][17]
|
||||
* [用 Pandoc 生成一篇调研论文][18]
|
||||
* [使用 pandoc 将 Markdown 转换为格式化文档][19]
|
||||
|
||||
|
||||
|
||||
@ -82,7 +84,7 @@ via: https://opensource.com/article/20/3/markdown-apps-linux-command-line
|
||||
作者:[Scott Nesbitt][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/) 荣誉推出
|
||||
|
||||
@ -103,7 +105,7 @@ via: https://opensource.com/article/20/3/markdown-apps-linux-command-line
|
||||
[13]: https://github.com/cfenollosa/bashblog
|
||||
[14]: https://en.wikipedia.org/wiki/Web_template_system#Static_site_generators
|
||||
[15]: https://opensource.com/sites/default/files/uploads/bashblog.png (bashblog)
|
||||
[16]: https://opensource.com/article/18/9/intro-pandoc
|
||||
[17]: https://opensource.com/article/18/10/book-to-website-epub-using-pandoc
|
||||
[18]: https://opensource.com/article/18/9/pandoc-research-paper
|
||||
[19]: https://opensource.com/article/19/5/convert-markdown-to-word-pandoc
|
||||
[16]: https://linux.cn/article-10228-1.html
|
||||
[17]: https://linux.cn/article-10287-1.html
|
||||
[18]: https://linux.cn/article-10179-1.html
|
||||
[19]: https://linux.cn/article-11160-1.html
|
@ -0,0 +1,208 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12047-1.html)
|
||||
[#]: subject: (7 open hardware projects working to solve COVID-19)
|
||||
[#]: via: (https://opensource.com/article/20/3/open-hardware-covid19)
|
||||
[#]: author: (Harris Kenny https://opensource.com/users/harriskenny)
|
||||
|
||||
应对新冠病毒的 7 个开源硬件项目
|
||||
======
|
||||
|
||||
> 开源硬件解决方案可以为抵御新型冠状病毒的传播和痛苦做出贡献。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/29/103909f50gm91z22twuv23.jpg)
|
||||
|
||||
开源[硬件][2]运动长期以来一直主张维修权的重要性,完全拥有所购买的技术,并能够像音乐一样重新组合和复制部件。因此,在这个充满挑战的时期内,开源硬件为由冠状病毒大流行引起的一些问题提供了一些答案。
|
||||
|
||||
### 背景概述
|
||||
|
||||
首先,全球的硬件开发人员正在努力使用开源解决供应链中的弱点,在过去 30 年中,这种理念推动了新软件技术的大量涌现。过去在硬件运动方面的成功,如 [RepRap Project][3]、[Open Source Ecology][4] 和 [Open Source Beehives][5],证明了这一点是可以做到的。
|
||||
|
||||
对于使用 3D 打印和其他技术按需生产安全设备和按需制造它的替换零件,创客们的兴趣日益增加。例如,香港理工大学实验室为医院工作人员提供 [3D 打印面罩][6]。意大利初创公司 Isinnova 与米兰 FabLab 合作,为受重灾的意大利北部提供用于呼吸机的 [3D 打印替换阀][7]。公司们还发布了设计以适应我们的物理接触需求,例如 Materialise 的 [3D 打印免提开门器][8]。这些更换零件和解决问题的示例是一个很好的起点,为挽救生命做出了努力。
|
||||
|
||||
另一种传统的硬件技术正在加速发展:缝纫。法新社报道说,全球急需口罩,来自世界卫生组织的指导也指明了其重要性。随着一次性口罩要优先供给于医护人员,捷克共和国的人们[开始缝制自己的口罩][9]。(重复使用的口罩确实会带来细菌问题。)Facebook 小组“捷克缝制口罩”开始在他们的国家解决这个问题,成千上万的成员开始用起了他们的家用缝纫机。
|
||||
|
||||
开源硬件设备和机械项目也越来越受欢迎。首先,有一些测试性设备具备高精度且功能强大。其次,在没有其他选择方案的情况下,有一些医疗设备(顶多)可以归类为现场级。这些项目将在下面详细概述。
|
||||
|
||||
为了解更多信息,我与总部位于芝加哥的 [Tapster Robotics][10] 的创始人兼首席执行官 Jason Huggins 进行了交谈。Tapster Robotics 使用 3D 打印、计算机数控(CNC)加工和 [Arduino][11] 等开源电子产品设计和制造台式机器人。他兼具技术知识和工业能力,具有很高的影响力。他想投入自己公司的资源来帮助这场斗争。
|
||||
|
||||
“基本上,我们现在正处于第二次世界大战的动员时刻。即使我不是医生,我们仍然应该遵循希波克拉底誓言。无论我做什么,我都不想让问题变得更糟”,Huggins 解释,他认为:“作为对策,世卫组织执行主任 Michael Ryan 博士发表了这样的评论:‘速度胜过完美’。”
|
||||
|
||||
> 哇!
|
||||
>
|
||||
> 这个人是疾病传播的全球权威。如果您是领导者(无论以何种身份),请注意。如果不是,也请注意。
|
||||
>
|
||||
> [pic.twitter.com/bFogaekehM][12]
|
||||
>
|
||||
> — Jim RichardsSh🎙wgram(@JIMrichards1010)[2020 年 3 月 15 日][13]
|
||||
|
||||
Huggins 在应需提供方面具有丰富的经验。他的努力有助于 [Healthcare.gov][14] 在挑战性的最初启动后得以扩展。他还创建了软件行业标准的测试框架 Selenium 和 Appium。有了这一经验,他的建议非常值得考虑。
|
||||
|
||||
我还与 [Tyson Law][15] 的西雅图律师 Mark Tyson 进行了交谈,他的合作对象是初创公司和小型企业。他在快速发展的行业中与敏捷公司合作有着直接的经验。在阐述整个问题时,Tyson 说到:
|
||||
|
||||
> 《<ruby>善良的撒玛利亚人法<rt>Good Samaritan law</rt></ruby>》保护志愿者(即“好撒玛利亚人”)免于因其在紧急情况下提供援助的决定而承担责任。尽管这些法律的具体内容因州而异,但它们具有共同的公共政策依据:即鼓励旁观者帮助遇到紧急情况的其他人。可以想象,除了传统的把车祸的受害者从伤害中拉出来之外,这种理论依据可以证明在不太传统的环境中应用这类法律的合理性。
|
||||
|
||||
对于这种特定情况,Tyson 指出:
|
||||
|
||||
> “在采取行动之前,创客们明智的做法是与律师沟通一下,以针对特定的州进行风险评估。还应谨慎地要求大型机构(例如医院或保险公司)通过合同接受潜在的责任风险,例如,通过使用赔偿协议,使医院或其保险人同意赔偿创客们的责任。”
|
||||
|
||||
Tyson 明白情况的紧迫性和严重性。使用合同的这种选择并不意味着障碍。相反,这可能是一种帮助其大规模采用的方法,以更快地产生更大的变化。这取决于你或你的机构。
|
||||
|
||||
综上所述,让我们探索正在使用或正在开发中的项目(可能很快就可以部署)。
|
||||
|
||||
### 7 个与新冠病毒对抗的开源硬件项目
|
||||
|
||||
#### Opentrons
|
||||
|
||||
[Opentrons][16] 的开源实验室自动化平台由一套开源硬件、经过验证的实验室器具、消耗品、试剂和工作站组成。Opentrons 表示,其产品可以“在下订单后几天内每天自动进行多达 2400 个测试”的系统,可以极大地帮助提高[新冠病毒测试规模][17]。它计划在 7 月 1 日之前提升到多达 100 万个测试样本。
|
||||
|
||||
![Opentrons roadmap graphic][18]
|
||||
|
||||
*来自 Opentrons [网站][17],版权所有*
|
||||
|
||||
该公司已经在与联邦和地方政府机构合作,以确定其系统是否可以在[紧急使用授权][19]下用于临床诊断。 Opentrons 在 [Apache 2.0 许可证][20]下共享。我最初是从与该项目有联系的生物学家 Kristin Ellis 那里得知它的。
|
||||
|
||||
#### Chai 的 Open qPCR
|
||||
|
||||
Chai 的 [Open qPCR][21] 设备使用[聚合酶链反应][22](PCR)快速检测物品表面(例如,门把手和电梯按钮)上的拭子,以查看是否存在新型冠状病毒。这种在 [Apache 2.0 许可证][23]下共享的开源硬件使用 [BeagleBone][24] 低功耗 Linux 计算机。Chai 的 Open qPCR 提供的数据可以使公共卫生、公民和企业领导者做出有关清洁、缓解、关闭设施、接触追踪和测试的更明智的决策。
|
||||
|
||||
#### OpenPCR
|
||||
|
||||
[OpenPCR][25] 是 Chai Open qPCR 的创建者 Josh Perfetto 和 Jessie Ho 的 PCR 测试设备套件。与他们的前一个项目相比,这更像是一种 DIY 开源设备,但它具有相同的使用场景:使用环境测试来识别野外冠状病毒。正如该项目页面所指出的那样,“能够检测这些病原体的传统实时 PCR 设备通常花费超过 30,000 美元,而且不适合在现场使用。”由于 OpenPCR 是用户构建的工具包,并且在 [GPLv3.0 许可证][26]下共享,因此该设备旨在使分子诊断的访问大众化。
|
||||
|
||||
![OpenPCR][27]
|
||||
|
||||
*来自 OpenPCR [网站][25],版权所有*
|
||||
|
||||
而且,就像任何优秀的开源项目一样,它也有一个衍生产品!瑞士的 [Gaudi Labs][29] 推出的 [WildOpenPCR][28] 也以 [GPLv3.0 许可证][30]共享。
|
||||
|
||||
#### PocketPCR
|
||||
|
||||
Gaudi Labs 的 [PocketPCR][31] 热循环仪可通过升高和降低小试管中液体的温度来激活生物反应。它可以通过简单的 USB 电源适配器供电,该适配器可以绑定到设备上,也可以单独使用,不使用计算机或智能手机时可使用预设参数。
|
||||
|
||||
![PocketPCR][32]
|
||||
|
||||
*来自 PocketPCR [网站][31],版权所有*
|
||||
|
||||
与本文所述的其他 PCR 产品一样,此设备可能有助于对冠状病毒进行环境测试,尽管其项目页面并未明确说明。PocketPCR 在 [GPLv3.0 许可证][33]下共享。
|
||||
|
||||
#### Open Lung 低资源呼吸机
|
||||
|
||||
[Open Lung 低资源呼吸机][34]是一种快速部署的呼吸机,它以[气囊阀罩][35](BVM)(也称为 Ambu 气囊)为核心组件。Ambu 气囊已批量生产,经过认证,体积小,机械简单,并且适用于侵入性导管和口罩。 Open Lung 呼吸机使用微电子技术来感测和控制气压和流量,以实现半自主运行。
|
||||
|
||||
![Open Lung ventilator][36]
|
||||
|
||||
*Open Lung,[GitLab][37]*
|
||||
|
||||
这个早期项目拥有一支由数百名贡献者组成的大型团队,领导者包括:Colin Keogh、David Pollard、Connall Laverty 和 Gui Calavanti。它是以 [GPLv3.0 许可证][38]共享的。
|
||||
|
||||
#### Pandemic 呼吸机
|
||||
|
||||
[Pandemic 呼吸机][39]是 DIY 呼吸机的原型。像 RepRap 项目一样,它在设计中使用了常用的硬件组件。该项目已由用户 Panvent 于 10 多年前上传到 Instructables,并且有六个主要的生产步骤。该项目是以 [CC BY-NC-SA 许可证][39]共享的。
|
||||
|
||||
#### Folding at Home
|
||||
|
||||
[Folding at Home][40] 是一个分布式计算项目,用于模拟蛋白质动力学,包括蛋白质折叠的过程以及与多种疾病有关的蛋白质运动。这是一个面向公民科学家、研究人员和志愿者的行动呼吁,类似于退役的 [SETI@Home 项目][41]使用家中的计算机来运行解码计算。如果你是具备强大计算机硬件功能的技术人员,那么这个项目适合你。
|
||||
|
||||
![Markov state model][42]
|
||||
|
||||
*Vincent Voelz,CC BY-SA 3.0*
|
||||
|
||||
Folding at Home 项目使用马尔可夫状态模型(如上所示)来建模蛋白质可能采取的形状和折叠途径,以寻找新的治疗机会。你可以在华盛顿大学生物物理学家 Greg Bowman 的帖子《[它是如何运作的以及如何提供帮助][43]》中找到有关该项目的更多信息。
|
||||
|
||||
该项目涉及来自许多国家和地区(包括香港、克罗地亚、瑞典和美国)的财团的学术实验室、贡献者和公司赞助者。 在 [GitHub][45] 上,[在混合了 GPL 和专有许可证][44]下共享,并且可以在 Windows、macOS 和 GNU/Linux(例如 Debian、Ubuntu、Mint、RHEL、CentOS、Fedora)。
|
||||
|
||||
### 许多其他有趣的项目
|
||||
|
||||
这些项目只是在开源硬件领域中解决或治疗新冠病毒活动中的一小部分。在研究本文时,我发现了其他值得探索的项目,例如:
|
||||
|
||||
* Coronavirus Tech Handbook 提供的[开源呼吸机、氧气浓缩器等][46]
|
||||
* 来自 ProjectOpenAir 的 [有用的工程][47]
|
||||
* Hackaday 上的[开源呼吸机黑客马拉松][48]
|
||||
* 约翰·霍普金斯急诊医学住院医师 Julian Botta 的[简单开源机械呼吸机规范][49]
|
||||
* [与冠状病毒有关的网络钓鱼、恶意软件和随机软件正在增加][50],作者:Shannon Morse
|
||||
* [将低成本的 CPAP 鼓风机转换为基本呼吸机][51],作者: jcl5m1
|
||||
* [A.I.R.E. 论坛上关于开源呼吸器和风扇的讨论][52](西班牙语)
|
||||
* [关于新冠病毒的开源医疗硬件的特殊问题][53],作者:Elsevier HardwareX
|
||||
|
||||
这些项目遍布全球,而这种全球合作正是我们所需要的,因为病毒无视国界。新冠病毒大流行在不同时期以不同方式影响国家,因此我们需要一种分布式方法。
|
||||
|
||||
正如我和同事 Steven Abadie 在 [OSHdata 2020 报告][54]中所写的那样,开源硬件运动是全球性运动。参与该认证项目的个人和组织遍布全球 35 个国家地区和每个半球。
|
||||
|
||||
![Open source hardware map][55]
|
||||
|
||||
*OSHdata,CC BY-SA 4.0 国际版*
|
||||
|
||||
如果你有兴趣加入这场与全球开源硬件开发人员的对话,请加入[开源硬件峰会的 Discord][56] 服务器,并通过专用渠道进行有关新冠病毒的讨论。你在这里可以找到机器人专家、设计师、艺术家、固件和机械工程师、学生、研究人员以及其他共同为这场战争而战的人。希望可以看到你。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/open-hardware-covid19
|
||||
|
||||
作者:[Harris Kenny][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/harriskenny
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/health_heartbeat.png?itok=P-GXea-p (open on blue background with heartbeat symbol)
|
||||
[2]: https://opensource.com/resources/what-open-hardware
|
||||
[3]: https://reprap.org/wiki/RepRap
|
||||
[4]: https://www.opensourceecology.org/
|
||||
[5]: https://www.osbeehives.com/
|
||||
[6]: https://www.scmp.com/news/hong-kong/health-environment/article/3052135/polytechnic-university-lab-3d-printing-face
|
||||
[7]: https://www.3dprintingmedia.network/covid-19-3d-printed-valve-for-reanimation-device/
|
||||
[8]: https://www.3dprintingmedia.network/materialise-shows-3d-printed-door-opener-for-coronavirus-containment-efforts/
|
||||
[9]: https://news.yahoo.com/stitch-time-czechs-sew-combat-virus-mask-shortage-205213804.html
|
||||
[10]: http://tapster.io/
|
||||
[11]: https://opensource.com/life/15/5/arduino-or-raspberry-pi
|
||||
[12]: https://t.co/bFogaekehM
|
||||
[13]: https://twitter.com/JIMrichards1010/status/1239140710558969857?ref_src=twsrc%5Etfw
|
||||
[14]: http://Healthcare.gov
|
||||
[15]: https://www.marktysonlaw.com/
|
||||
[16]: https://opentrons.com/
|
||||
[17]: https://blog.opentrons.com/testing-for-covid-19-with-opentrons/
|
||||
[18]: https://opensource.com/sites/default/files/uploads/opentrons.png (Opentrons roadmap graphic)
|
||||
[19]: https://www.fda.gov/regulatory-information/search-fda-guidance-documents/policy-diagnostics-testing-laboratories-certified-perform-high-complexity-testing-under-clia-prior
|
||||
[20]: https://github.com/Opentrons/opentrons/blob/edge/LICENSE
|
||||
[21]: https://www.chaibio.com/openqpcr
|
||||
[22]: https://en.wikipedia.org/wiki/Polymerase_chain_reaction
|
||||
[23]: https://github.com/chaibio/chaipcr
|
||||
[24]: https://beagleboard.org/bone
|
||||
[25]: https://openpcr.org/
|
||||
[26]: https://github.com/jperfetto/OpenPCR/blob/master/license.txt
|
||||
[27]: https://opensource.com/sites/default/files/uploads/openpcr.png (OpenPCR)
|
||||
[28]: https://github.com/GenericLab/WildOpenPCR
|
||||
[29]: http://www.gaudi.ch/GaudiLabs/?page_id=328
|
||||
[30]: https://github.com/GenericLab/WildOpenPCR/blob/master/license.txt
|
||||
[31]: http://gaudi.ch/PocketPCR/
|
||||
[32]: https://opensource.com/sites/default/files/uploads/pocketpcr.png (PocketPCR)
|
||||
[33]: https://github.com/GaudiLabs/PocketPCR/blob/master/LICENSE
|
||||
[34]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor
|
||||
[35]: https://en.wikipedia.org/wiki/Bag_valve_mask
|
||||
[36]: https://opensource.com/sites/default/files/uploads/open-lung.png (Open Lung ventilator)
|
||||
[37]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor/-/blob/master/images/CONCEPT_1_MECH.png
|
||||
[38]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor/-/blob/master/LICENSE
|
||||
[39]: https://www.instructables.com/id/The-Pandemic-Ventilator/
|
||||
[40]: https://foldingathome.org/
|
||||
[41]: https://setiathome.ssl.berkeley.edu/
|
||||
[42]: https://opensource.com/sites/default/files/uploads/foldingathome.png (Markov state model)
|
||||
[43]: https://foldingathome.org/2020/03/15/coronavirus-what-were-doing-and-how-you-can-help-in-simple-terms/
|
||||
[44]: https://en.wikipedia.org/wiki/Folding@home
|
||||
[45]: https://github.com/FoldingAtHome
|
||||
[46]: https://coronavirustechhandbook.com/hardware
|
||||
[47]: https://app.jogl.io/project/121#about
|
||||
[48]: https://hackaday.com/2020/03/12/ultimate-medical-hackathon-how-fast-can-we-design-and-deploy-an-open-source-ventilator/
|
||||
[49]: https://docs.google.com/document/d/1FNPwrQjB1qW1330s5-S_-VB0vDHajMWKieJRjINCNeE/edit?fbclid=IwAR3ugu1SGMsacwKi6ycAKJFOMduInSO4WVM8rgmC4CgMJY6cKaGBNR14mpM
|
||||
[50]: https://www.youtube.com/watch?v=dmQ1twpPpXA
|
||||
[51]: https://github.com/jcl5m1/ventilator
|
||||
[52]: https://foro.coronavirusmakers.org/
|
||||
[53]: https://www.journals.elsevier.com/hardwarex/call-for-papers/special-issue-on-open-source-covid19-medical-hardware
|
||||
[54]: https://oshdata.com/2020-report
|
||||
[55]: https://opensource.com/sites/default/files/uploads/oshdata-country.png (Open source hardware map)
|
||||
[56]: https://discord.gg/duAtG5h
|
@ -0,0 +1,120 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12059-1.html)
|
||||
[#]: subject: (Meet DebianDog – Puppy sized Debian Linux)
|
||||
[#]: via: (https://itsfoss.com/debiandog/)
|
||||
[#]: author: (John Paul https://itsfoss.com/author/john/)
|
||||
|
||||
体验 DebianDog:Puppy 式的 Debian Linux
|
||||
======
|
||||
|
||||
不久前,我偶然发现了一个有趣的 Linux 项目。这个项目旨在为 Debian 和基于 Debian 的系统创建一个小型的现场版 CD,类似于 [Puppy Linux 项目][1] 。让我们看看 DebianDog 。
|
||||
|
||||
### DebianDog 是什么?
|
||||
|
||||
正如字面所述,[DebianDog][2] “是一个被塑造成一个外观和动作都像 Puppy Linux 的小型 Debian 现场版 CD。没有改动 Debian 结构和方式,Debian 的文档对 DebianDog 来说是完全有效的。你可以使用 `apt-get` 或 synaptic 来访问所有的 Debian 存储库。”
|
||||
|
||||
![DebianDog][3]
|
||||
|
||||
对于那些不熟悉 [Puppy Linux][1] 的人来说,该项目是 “多个 Linux 发行版的一个集合,建立在相同的共享准则之上”。这些准则能够实现快速、小型(300 MB 或更少)、易于使用。这里有为支持 Ubuntu, Slackware 和 Raspbian 软件包构建的 Puppy Linux 变种。
|
||||
|
||||
DebianDog 和 Puppy Linux 之间最大的不同是,Puppy Linux 有其自己的软件包管理器 [Puppy 软件包管理器][4] 。如上所述,DebianDog 使用 Debian 软件包管理器及其软件包。甚至 DebianDog 网站也试图澄清这一点:“它不是 Puppy Linux,并且也与基于 Debian 的 Puppy 无关。”
|
||||
|
||||
### 为什么一些人使用 DebianDog ?
|
||||
|
||||
安装 DebianDog(或其任何衍生产品)的主要原因是让一台较旧电脑重焕新生。在 DebianDog 上的每个版本都有一个 32 位版本。它们还有更轻量级的桌面环境/窗口管理器,例如 [Openbox][5] 或 [Trinity Desktop][6] 环境。它们中大多数也都有一个 systemd 的可替代版本。它们也安装更轻的应用程序,例如 [PCManFM][7] 。
|
||||
|
||||
### DebianDog 有哪些可用的变体版本?
|
||||
|
||||
尽管 DebianDog 在本系列中是第一个,但是该项目被称为 ‘Dog Linux’ ,提供各种基于Debian 和 Ubuntu的流行发行版的 ‘Dog 变体’。
|
||||
|
||||
#### DebianDog Jessie
|
||||
|
||||
DebianDog 的第一个(也是最初的)版本是 DebianDog Jessie。它有两个 [32 位版本][8] ,一个使用 [Joe’s Window Manager (JWM)][9] 作为默认桌面环境,另一个使用 XFCE 作为默认桌面环境。systemd 和 sysvinit 都是可用的。它还有一个 [64 位版本][10]。DebianDog Jessie 基于 Debian 8.0(Jessie)。Debian 8.0 的支持将于 2020 年 6 月 30 日结束,因此安装需谨慎。
|
||||
|
||||
#### StretchDog
|
||||
|
||||
[StretchDog][12] 基于 Debian 9.0(Stretch)。它有 32 位和 64 位两种版本可用。Openbox 是默认的窗口管理器,但是我们可以切换到 JWM 。Debian 9.0 的支持将于 2022 年 6 月 30 日结束。
|
||||
|
||||
#### BusterDog
|
||||
|
||||
[BusterDog][13] 是很有趣的。它基于 [Debian 10][14](Buster)。它不使用 systemd,反而像 [AntiX][16] 一样使用 [elogind][15] 。Debian 10.0 的支持将于 2024 年 6 月结束。
|
||||
|
||||
#### MintPup
|
||||
|
||||
[MintPup][17] 基于 [Linux Mint][18] 17.1。现场版 CD 仅有 32 位版本。你也可以使用 “apt-get 或 synaptic 访问 Ubuntu/Mint 的存储库”。考虑到 Mint 17 已经到了生命的尽头,这一版本必须避免使用。
|
||||
|
||||
#### XenialDog
|
||||
|
||||
XenialDog 有 [32 位][19]和 [64 位][20] 两种变种,基于 Ubuntu 16.04 LTS 。两个变种都使用 Openbox 作为默认版本,JWM 可选。Ubuntu 16.04 LTS 的支持将于 2021 年 4 月结束, 因此安装需谨慎。
|
||||
|
||||
#### TrinityDog
|
||||
|
||||
[TrintyDog][21] 有两种变体。一个基于 Debian 8 ,另一个基于 Debian 9 。两种变体都有 32 位版本,并且都使用 [Trinity Desktop Environment][6] ,以此得名。
|
||||
|
||||
![TrinityDog][11]
|
||||
|
||||
#### BionicDog
|
||||
|
||||
你应该能够从名称猜到。[BionicDog][23] 基于 [Ubuntu 18.04 LTS][24]。主要版本有 32 位和 64 位两个版本,Openbox 是默认的窗口管理器。这里也有一个使用 [Cinnamon desktop][25] 的版本,并且只有 64 位版本。
|
||||
|
||||
![BionicDog][22]
|
||||
|
||||
### 结束语
|
||||
|
||||
我喜欢任何 [想让较旧电脑系统有用的 Linux 项目][26]。但是,通过 DebianDog 项目提供的大多数操作系统不再受支持,或者接近它们的生命尽头。从长远来看,这就不那么有用了。
|
||||
|
||||
**我不建议在你的主计算机上使用它。**在现场版 USB 中或一台闲置的系统上尝试它。此外,如果你想使用较新的基础系统,[你可以创建][27]你自己的现场版 CD 。
|
||||
|
||||
似乎冥冥中自有天意,我总是在探索鲜为人知的 Linux 发行版的路上艰难地前行,像 [FatDog64][28]、[4M Linux][29] 以及 [Vipper Linux][30] 。虽然我不建议使用它们,但是知晓这些项目的存在的意义总是好的。
|
||||
|
||||
你对 DebianDog 有什么看法?你最最喜欢的 Puppy 式的操作系统是什么?请在下面的评论区中告诉我们。
|
||||
|
||||
如果你觉得这篇文章很有趣,请花点时间在社交媒体、黑客新闻或 Reddit 上分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/debiandog/
|
||||
|
||||
作者:[John Paul][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/john/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://puppylinux.com/
|
||||
[2]: https://debiandog.github.io/doglinux/
|
||||
[3]: https://www.linuxinsider.com/article_images/2017/84328_990x556.jpg
|
||||
[4]: http://wikka.puppylinux.com/PPM?redirect=no
|
||||
[5]: http://openbox.org/wiki/Main_Page
|
||||
[6]: https://www.trinitydesktop.org/
|
||||
[7]: https://wiki.lxde.org/en/PCManFM
|
||||
[8]: https://debiandog.github.io/doglinux/zz01debiandogjessie.html
|
||||
[9]: https://en.wikipedia.org/wiki/JWM
|
||||
[10]: https://debiandog.github.io/doglinux/zz02debiandog64.html
|
||||
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/TrinityDog.jpg?ssl=1
|
||||
[12]: https://debiandog.github.io/doglinux/zz02stretchdog.html
|
||||
[13]: https://debiandog.github.io/doglinux/zz03busterdog.html
|
||||
[14]: https://itsfoss.com/debian-10-buster/
|
||||
[15]: https://github.com/elogind/elogind
|
||||
[16]: https://antixlinux.com/
|
||||
[17]: https://debiandog.github.io/doglinux/zz04mintpup.html
|
||||
[18]: https://linuxmint.com/
|
||||
[19]: https://debiandog.github.io/doglinux/zz05xenialdog.html
|
||||
[20]: https://debiandog.github.io/doglinux/zz05zxenialdog.html
|
||||
[21]: https://debiandog.github.io/doglinux/zz06-trinitydog.html
|
||||
[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/BionicDog.jpg?ssl=1
|
||||
[23]: https://debiandog.github.io/doglinux/zz06-zbionicdog.html
|
||||
[24]: https://itsfoss.com/ubuntu-18-04-released/
|
||||
[25]: https://en.wikipedia.org/wiki/Cinnamon_(desktop_environment)
|
||||
[26]: https://itsfoss.com/lightweight-linux-beginners/
|
||||
[27]: https://github.com/DebianDog/MakeLive
|
||||
[28]: https://itsfoss.com/fatdog64-linux-review/
|
||||
[29]: https://itsfoss.com/4mlinux-review/
|
||||
[30]: https://itsfoss.com/viperr-linux-review/
|
||||
[31]: https://reddit.com/r/linuxusersgroup
|
@ -0,0 +1,108 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (HankChow)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12057-1.html)
|
||||
[#]: subject: (How open source software is fighting COVID-19)
|
||||
[#]: via: (https://opensource.com/article/20/3/open-source-software-covid19)
|
||||
[#]: author: (Jeff Stern https://opensource.com/users/jeffstern)
|
||||
|
||||
开源软件在应对新冠病毒中的贡献
|
||||
======
|
||||
|
||||
> 在新冠疫情爆发之际,涌现了数以千计的开源项目,今天我们来了解其中四个。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202003/30/210613wchojyc5rrwh8y5k.jpg)
|
||||
|
||||
在当前紧张的疫情环境下,保持专注和积极性是一个很大的挑战。而研究开源社区如何应对这一次疫情爆发,对于我来说却成为了一种宣泄。
|
||||
|
||||
从今年一月底开始,整个开源社区已经贡献了数以千计关于冠状病毒或新冠病毒的[开源软件仓库][2],其中涉及的内容包括但不限于数据集、模型、可视化、Web 应用、移动应用,且大多数都使用了 JavaScript 和 Python 编写。
|
||||
|
||||
之前我们分享过一些关于[开源硬件创客们在帮助][3]遏制冠状病毒传播方面做的贡献,现在将继续分享四个由开源社区作出的应对冠状病毒和新冠病毒的项目,这体现了开发者们和整个开源社区在当下对整个世界的影响力。
|
||||
|
||||
### 1. PennSignals:CHIME
|
||||
|
||||
![CHIME by PennSignals][4]
|
||||
|
||||
<ruby>新冠病毒流行病医院影响模型<rt>COVID-19 Hospital Impact Model for Epidemics</rt></ruby>([CHIME][5])是由宾夕法尼亚大学 Penn Medicine 机构的数据科学家们建立的开源在线应用,它可以让医院更好地了解本次新型冠状病毒对医院需求的影响。
|
||||
|
||||
医院的管理人员可以通过 CHIME 来大致预测未来几天和几周内将会有多少患者需要住院治疗,并推算 ICU 和呼吸机的需求量。只需要输入当前住院患者数以及一些相关的变量,就可以看到未来几天内需求的变化情况。
|
||||
|
||||
CHIME 主要使用 Python 开发,并通过 [Pandas][6] 这个开源库实现了大部分的数据转换和数值计算,最终得出相关的估计值。Pandas 的背后有一个强大的团队进行支持,它是在数据分析方面被广泛使用的 Python 库之一。和很多其它的开源项目一样,Pandas 团队的收入大部分来源于[用户的资金支持][7]。
|
||||
|
||||
### 2. Locale.ai:实时新冠病毒可视化
|
||||
|
||||
![Locale.ai COVID-19 visualization][8]
|
||||
|
||||
实时显示世界各地病例数量分布的地图可以让我们直观了解新冠病毒的规模和扩散程度。Locale.ai 就开发了这样一个开源、可交互的[新冠病毒已知病例可视化分布图][9],这个图会根据最新的可靠数据实时进行更新。
|
||||
|
||||
这个项目有趣的地方在于,它的数据是是通过 GitHub 用户 ExpDev07 创建的[开源 API][10] 进行检索的,这个 API 的数据来源是[约翰·霍普金斯大学的开源数据集][11],而约翰·霍普金斯大学这份聚合了多个来源的数据集则是 GitHub 上新冠病毒相关的最受欢迎的项目。这就是开源领域中分支带来的一大好处。
|
||||
|
||||
Locale.ai 的这个图表通过 [Vue.js][11] 开发。Vue.js 是一个在 Web 应用开发方面非常流行的框架,它是由[尤雨溪][12]创造并维护的。值得一提的是,尤雨溪是少数以全职参与开源项目维护的人之一。
|
||||
|
||||
### 3. BlankerL:DXY-COVID-19-Crawler
|
||||
|
||||
![BlankerL DXY-COVID-19-Crawler][13]
|
||||
|
||||
[DXY-COVID-19-Crawler][14] 建立于今年 1 月份,是开源社区对新冠病毒最早发起响应的项目之一。当时该病毒主要在中国范围内传播,中国医学界通过[丁香园][15]网站来进行病例的报告和跟踪。为了使这些疫情信息具有更高的可读性和易用性,GitHub 用户 BlankerL 开发了一个爬虫,系统地从丁香园网站获取数据,并通过 API 和数据仓库的方式对外公开。这些数据也被学术研究人员用于研究病毒传播趋势和制作相关的可视化图表。到目前为止,DXY-COVID-19-Crawler 这个项目已经获得了超过 1300 个星标和近 300 次的复刻。
|
||||
|
||||
BlankerL 使用 Python 和 [Beautiful Soup][16] 库开发了这个爬虫。Beautiful Soup 是 Python 开发者用于从页面 HTML DOM 中提取信息的库,它由 Leonard Richardson 维护,这位作者另外还全职担任软件架构师。
|
||||
|
||||
### 4. 东京新冠病毒工作组网站
|
||||
|
||||
![City of Tokyo's COVID-19 Task Force site][17]
|
||||
|
||||
世界各地很多城市都在网络上持续更新当地的新冠病毒信息。东京都政府则为此创建了一个[综合性的网站][18],让东京当地居民、在东京设有办事处的公司以及到东京的游客了解最新情况,并采取相应的预防措施。
|
||||
|
||||
这个网站的不同之处在于它是由东京都政府[开源][19]的。这个项目受到了来自 180 多名用户的贡献,日本的[长野市、千叶市、福冈市][20]还对这个网站进行了改造。这个项目是城市公共建设更好地服务大众的有力示范。
|
||||
|
||||
这个开源网站也使用了很多开源技术。通过 [Tidelift][21],我留意到项目中存在了 1365 个依赖项,而这都是由 38 个由开发者明确使用的直接依赖项所依赖的。也就是说,超过一千多个开源项目(包括 [Nuxt.js][22]、[Prettier][23]、[Babel][24]、[Ajv][25] 等等)都为东京向市民共享信息提供了帮助。
|
||||
|
||||
![Dependencies in Tokyo's COVID-19 Task Force site][26]
|
||||
|
||||
### 其它项目
|
||||
|
||||
除此以外,还有很多[应对新冠病毒的重要项目][27]正在公开进行当中。在这次研究中,开源社区应对流行病以及利用开源技术开展工作的方式让我深受启发。接下来的一段时间都是应对疫情的关键时期,我们也可以继续在开源社区中寻找到更大的动力。
|
||||
|
||||
如果你也参与到了新冠病毒相关的开源项目当中,欢迎在评论区分享。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/open-source-software-covid19
|
||||
|
||||
作者:[Jeff Stern][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/jeffstern
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/Medical%20costs.jpg?itok=ke57j6cs (symbols showing healthcare)
|
||||
[2]: https://github.com/search?q=coronavirus+OR+covid19
|
||||
[3]: https://linux.cn/article-12047-1.html
|
||||
[4]: https://opensource.com/sites/default/files/uploads/chime_pennsignals.png (CHIME by PennSignals)
|
||||
[5]: http://penn-chime.phl.io/
|
||||
[6]: https://tidelift.com/subscription/pkg/pypi-pandas
|
||||
[7]: https://pandas.pydata.org/about/sponsors.html
|
||||
[8]: https://opensource.com/sites/default/files/uploads/locale-ai-visualization.png (Locale.ai COVID-19 visualization)
|
||||
[9]: https://github.com/localeai/covid19-live-visualization
|
||||
[10]: https://github.com/CSSEGISandData/COVID-19
|
||||
[11]: https://tidelift.com/subscription/pkg/npm-vue
|
||||
[12]: https://blog.tidelift.com/vuejs-evan-you-javascript-framework
|
||||
[13]: https://opensource.com/sites/default/files/uploads/dxy-covid-19-crawler.png (BlankerL DXY-COVID-19-Crawler)
|
||||
[14]: https://github.com/BlankerL/DXY-COVID-19-Crawler
|
||||
[15]: https://dxy.cn
|
||||
[16]: https://blog.tidelift.com/beautiful-soup-is-now-part-of-the-tidelift-subscription
|
||||
[17]: https://opensource.com/sites/default/files/uploads/tokyo-covid19-task-force.png (City of Tokyo's COVID-19 Task Force site)
|
||||
[18]: https://stopcovid19.metro.tokyo.lg.jp/en/
|
||||
[19]: https://github.com/tokyo-metropolitan-gov/covid19
|
||||
[20]: https://github.com/tokyo-metropolitan-gov/covid19/issues/1802
|
||||
[21]: https://tidelift.com/
|
||||
[22]: https://tidelift.com/subscription/pkg/npm-nuxt
|
||||
[23]: https://blog.tidelift.com/prettier-is-now-part-of-the-tidelift-subscriptions
|
||||
[24]: https://tidelift.com/subscription/pkg/npm-babel
|
||||
[25]: https://blog.tidelift.com/ajv-is-now-part-of-the-tidelift-subscription
|
||||
[26]: https://opensource.com/sites/default/files/uploads/tokyo-dependencies.png (Dependencies in Tokyo's COVID-19 Task Force site)
|
||||
[27]: https://github.com/soroushchehresa/awesome-coronavirus
|
@ -0,0 +1,627 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (silentdawn-zz)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12499-1.html)
|
||||
[#]: subject: (Share data between C and Python with this messaging library)
|
||||
[#]: via: (https://opensource.com/article/20/3/zeromq-c-python)
|
||||
[#]: author: (Cristiano L. Fontana https://opensource.com/users/cristianofontana)
|
||||
|
||||
使用 ZeroMQ 消息库在 C 和 Python 间共享数据
|
||||
======
|
||||
|
||||
> ZeroMQ 是一个快速灵活的消息库,用于数据收集和不同编程语言间的数据共享。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202008/08/202106uale11l1qf11slzw.jpg)
|
||||
|
||||
作为软件工程师,我有多次在要求完成指定任务时感到浑身一冷的经历。其中有一次,我必须在一些新的硬件基础设施和云基础设施之间写一个接口,这些硬件需要 C 语言,而云基础设施主要是用 Python。
|
||||
|
||||
实现的方式之一是 [用 C 写扩展模块][2],Python 支持 C 扩展的调用。快速浏览文档后发现,这需要编写大量的 C 代码。这样做的话,在有些情况下效果还不错,但不是我喜欢的方式。另一种方式就是将两个任务放在不同的进程中,并使用 [ZeroMQ 消息库][3] 在两者之间交换消息。
|
||||
|
||||
在发现 ZeroMQ 之前,遇到这种类型的情况时,我选择了编写扩展的方式。这种方式不算太差,但非常费时费力。如今,为了避免那些问题,我将一个系统细分为独立的进程,通过 [通信套接字][4] 发送消息来交换信息。这样,不同的编程语言可以共存,每个进程也变简单了,同时也容易调试。
|
||||
|
||||
ZeroMQ 提供了一个更简单的过程:
|
||||
|
||||
1. 编写一小段 C 代码,从硬件读取数据,然后把发现的东西作为消息发送出去。
|
||||
2. 使用 Python 编写接口,实现新旧基础设施之间的对接。
|
||||
|
||||
[Pieter Hintjens][5] 是 ZeroMQ 项目发起者之一,他是个拥有 [有趣视角和作品][6] 的非凡人物。
|
||||
|
||||
### 准备
|
||||
|
||||
本教程中,需要:
|
||||
|
||||
* 一个 C 编译器(例如 [GCC][7] 或 [Clang][8])
|
||||
* [libzmq 库][9]
|
||||
* [Python 3][10]
|
||||
* [ZeroMQ 的 Python 封装][11]
|
||||
|
||||
Fedora 系统上的安装方法:
|
||||
|
||||
```
|
||||
$ dnf install clang zeromq zeromq-devel python3 python3-zmq
|
||||
```
|
||||
|
||||
Debian 和 Ubuntu 系统上的安装方法:
|
||||
|
||||
```
|
||||
$ apt-get install clang libzmq5 libzmq3-dev python3 python3-zmq
|
||||
```
|
||||
|
||||
如果有问题,参考对应项目的安装指南(上面附有链接)。
|
||||
|
||||
### 编写硬件接口库
|
||||
|
||||
因为这里针对的是个设想的场景,本教程虚构了包含两个函数的操作库:
|
||||
|
||||
* `fancyhw_init()` 用来初始化(设想的)硬件
|
||||
* `fancyhw_read_val()` 用于返回从硬件读取的数据
|
||||
|
||||
将库的完整代码保存到文件 `libfancyhw.h` 中:
|
||||
|
||||
```
|
||||
#ifndef LIBFANCYHW_H
|
||||
#define LIBFANCYHW_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This is the fictitious hardware interfacing library
|
||||
|
||||
void fancyhw_init(unsigned int init_param)
|
||||
{
|
||||
srand(init_param);
|
||||
}
|
||||
|
||||
int16_t fancyhw_read_val(void)
|
||||
{
|
||||
return (int16_t)rand();
|
||||
}
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
这个库可以模拟你要在不同语言实现的组件间交换的数据,中间有个随机数发生器。
|
||||
|
||||
### 设计 C 接口
|
||||
|
||||
下面从包含管理数据传输的库开始,逐步实现 C 接口。
|
||||
|
||||
#### 需要的库
|
||||
|
||||
开始先加载必要的库(每个库的作用见代码注释):
|
||||
|
||||
```
|
||||
// For printf()
|
||||
#include <stdio.h>
|
||||
// For EXIT_*
|
||||
#include <stdlib.h>
|
||||
// For memcpy()
|
||||
#include <string.h>
|
||||
// For sleep()
|
||||
#include <unistd.h>
|
||||
|
||||
#include <zmq.h>
|
||||
|
||||
#include "libfancyhw.h"
|
||||
```
|
||||
|
||||
#### 必要的参数
|
||||
|
||||
定义 `main` 函数和后续过程中必要的参数:
|
||||
|
||||
```
|
||||
int main(void)
|
||||
{
|
||||
const unsigned int INIT_PARAM = 12345;
|
||||
const unsigned int REPETITIONS = 10;
|
||||
const unsigned int PACKET_SIZE = 16;
|
||||
const char *TOPIC = "fancyhw_data";
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 初始化
|
||||
|
||||
所有的库都需要初始化。虚构的那个只需要一个参数:
|
||||
|
||||
```
|
||||
fancyhw_init(INIT_PARAM);
|
||||
```
|
||||
|
||||
ZeroMQ 库需要实打实的初始化。首先,定义对象 `context`,它是用来管理全部的套接字的:
|
||||
|
||||
```
|
||||
void *context = zmq_ctx_new();
|
||||
|
||||
if (!context)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
```
|
||||
|
||||
之后定义用来发送数据的套接字。ZeroMQ 支持若干种套接字,各有其用。使用 `publish` 套接字(也叫 `PUB` 套接字),可以复制消息并分发到多个接收端。这使得你可以让多个接收端接收同一个消息。没有接收者的消息将被丢弃(即不会入消息队列)。用法如下:
|
||||
|
||||
```
|
||||
void *data_socket = zmq_socket(context, ZMQ_PUB);
|
||||
```
|
||||
|
||||
套接字需要绑定到一个具体的地址,这样客户端就知道要连接哪里了。本例中,使用了 [TCP 传输层][15](当然也有 [其它选项][16],但 TCP 是不错的默认选择):
|
||||
|
||||
```
|
||||
const int rb = zmq_bind(data_socket, "tcp://*:5555");
|
||||
|
||||
if (rb != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
```
|
||||
|
||||
下一步, 计算一些后续要用到的值。 注意下面代码中的 `TOPIC`,因为 `PUB` 套接字发送的消息需要绑定一个主题。主题用于供接收者过滤消息:
|
||||
|
||||
```
|
||||
const size_t topic_size = strlen(TOPIC);
|
||||
const size_t envelope_size = topic_size + 1 + PACKET_SIZE * sizeof(int16_t);
|
||||
|
||||
printf("Topic: %s; topic size: %zu; Envelope size: %zu\n", TOPIC, topic_size, envelope_size);
|
||||
```
|
||||
|
||||
#### 发送消息
|
||||
|
||||
启动一个发送消息的循环,循环 `REPETITIONS` 次:
|
||||
|
||||
```
|
||||
for (unsigned int i = 0; i < REPETITIONS; i++)
|
||||
{
|
||||
...
|
||||
```
|
||||
|
||||
发送消息前,先填充一个长度为 `PACKET_SIZE` 的缓冲区。本库提供的是 16 个位的有符号整数。因为 C 语言中 `int` 类型占用空间大小与平台相关,不是确定的值,所以要使用指定宽度的 `int` 变量:
|
||||
|
||||
```
|
||||
int16_t buffer[PACKET_SIZE];
|
||||
|
||||
for (unsigned int j = 0; j < PACKET_SIZE; j++)
|
||||
{
|
||||
buffer[j] = fancyhw_read_val();
|
||||
}
|
||||
|
||||
printf("Read %u data values\n", PACKET_SIZE);
|
||||
```
|
||||
|
||||
消息的准备和发送的第一步是创建 ZeroMQ 消息,为消息分配必要的内存空间。空白的消息是用于封装要发送的数据的:
|
||||
|
||||
```
|
||||
zmq_msg_t envelope;
|
||||
|
||||
const int rmi = zmq_msg_init_size(&envelope, envelope_size);
|
||||
if (rmi != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_msg_init_size(): %s\n", zmq_strerror(errno));
|
||||
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
现在内存空间已分配,数据保存在 ZeroMQ 消息 “信封”中。函数 `zmq_msg_data()` 返回一个指向封装数据缓存区顶端的指针。第一部分是主题,之后是一个空格,最后是二进制数。主题和二进制数据之间的分隔符采用空格字符。需要遍历缓存区的话,使用类型转换和 [指针算法][18]。(感谢 C 语言,让事情变得直截了当。)做法如下:
|
||||
|
||||
```
|
||||
memcpy(zmq_msg_data(&envelope), TOPIC, topic_size);
|
||||
memcpy((void*)((char*)zmq_msg_data(&envelope) + topic_size), " ", 1);
|
||||
memcpy((void*)((char*)zmq_msg_data(&envelope) + 1 + topic_size), buffer, PACKET_SIZE * sizeof(int16_t))
|
||||
```
|
||||
|
||||
通过 `data_socket` 发送消息:
|
||||
|
||||
```
|
||||
const size_t rs = zmq_msg_send(&envelope, data_socket, 0);
|
||||
if (rs != envelope_size)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_msg_send(): %s\n", zmq_strerror(errno));
|
||||
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
使用数据之前要先解除封装:
|
||||
|
||||
```
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
printf("Message sent; i: %u, topic: %s\n", i, TOPIC);
|
||||
```
|
||||
|
||||
#### 清理
|
||||
|
||||
C 语言不提供 [垃圾收集][20] 功能,用完之后记得要自己扫尾。发送消息之后结束程序之前,需要运行扫尾代码,释放分配的内存:
|
||||
|
||||
```
|
||||
const int rc = zmq_close(data_socket);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_close(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const int rd = zmq_ctx_destroy(context);
|
||||
|
||||
if (rd != 0)
|
||||
{
|
||||
printf("Error occurred during zmq_ctx_destroy(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
```
|
||||
|
||||
#### 完整 C 代码
|
||||
|
||||
保存下面完整的接口代码到本地名为 `hw_interface.c` 的文件:
|
||||
|
||||
```
|
||||
// For printf()
|
||||
#include <stdio.h>
|
||||
// For EXIT_*
|
||||
#include <stdlib.h>
|
||||
// For memcpy()
|
||||
#include <string.h>
|
||||
// For sleep()
|
||||
#include <unistd.h>
|
||||
|
||||
#include <zmq.h>
|
||||
|
||||
#include "libfancyhw.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const unsigned int INIT_PARAM = 12345;
|
||||
const unsigned int REPETITIONS = 10;
|
||||
const unsigned int PACKET_SIZE = 16;
|
||||
const char *TOPIC = "fancyhw_data";
|
||||
|
||||
fancyhw_init(INIT_PARAM);
|
||||
|
||||
void *context = zmq_ctx_new();
|
||||
|
||||
if (!context)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void *data_socket = zmq_socket(context, ZMQ_PUB);
|
||||
|
||||
const int rb = zmq_bind(data_socket, "tcp://*:5555");
|
||||
|
||||
if (rb != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const size_t topic_size = strlen(TOPIC);
|
||||
const size_t envelope_size = topic_size + 1 + PACKET_SIZE * sizeof(int16_t);
|
||||
|
||||
printf("Topic: %s; topic size: %zu; Envelope size: %zu\n", TOPIC, topic_size, envelope_size);
|
||||
|
||||
for (unsigned int i = 0; i < REPETITIONS; i++)
|
||||
{
|
||||
int16_t buffer[PACKET_SIZE];
|
||||
|
||||
for (unsigned int j = 0; j < PACKET_SIZE; j++)
|
||||
{
|
||||
buffer[j] = fancyhw_read_val();
|
||||
}
|
||||
|
||||
printf("Read %u data values\n", PACKET_SIZE);
|
||||
|
||||
zmq_msg_t envelope;
|
||||
|
||||
const int rmi = zmq_msg_init_size(&envelope, envelope_size);
|
||||
if (rmi != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_msg_init_size(): %s\n", zmq_strerror(errno));
|
||||
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(zmq_msg_data(&envelope), TOPIC, topic_size);
|
||||
|
||||
memcpy((void*)((char*)zmq_msg_data(&envelope) + topic_size), " ", 1);
|
||||
|
||||
memcpy((void*)((char*)zmq_msg_data(&envelope) + 1 + topic_size), buffer, PACKET_SIZE * sizeof(int16_t));
|
||||
|
||||
const size_t rs = zmq_msg_send(&envelope, data_socket, 0);
|
||||
if (rs != envelope_size)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_msg_send(): %s\n", zmq_strerror(errno));
|
||||
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
zmq_msg_close(&envelope);
|
||||
|
||||
printf("Message sent; i: %u, topic: %s\n", i, TOPIC);
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
const int rc = zmq_close(data_socket);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
printf("ERROR: ZeroMQ error occurred during zmq_close(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const int rd = zmq_ctx_destroy(context);
|
||||
|
||||
if (rd != 0)
|
||||
{
|
||||
printf("Error occurred during zmq_ctx_destroy(): %s\n", zmq_strerror(errno));
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
用如下命令编译:
|
||||
|
||||
```
|
||||
$ clang -std=c99 -I. hw_interface.c -lzmq -o hw_interface
|
||||
```
|
||||
|
||||
如果没有编译错误,你就可以运行这个接口了。贴心的是,ZeroMQ `PUB` 套接字可以在没有任何应用发送或接受数据的状态下运行,这简化了使用复杂度,因为这样不限制进程启动的次序。
|
||||
|
||||
运行该接口:
|
||||
|
||||
```
|
||||
$ ./hw_interface
|
||||
Topic: fancyhw_data; topic size: 12; Envelope size: 45
|
||||
Read 16 data values
|
||||
Message sent; i: 0, topic: fancyhw_data
|
||||
Read 16 data values
|
||||
Message sent; i: 1, topic: fancyhw_data
|
||||
Read 16 data values
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
输出显示数据已经通过 ZeroMQ 完成发送,现在要做的是让一个程序去读数据。
|
||||
|
||||
### 编写 Python 数据处理器
|
||||
|
||||
现在已经准备好从 C 程序向 Python 应用传送数据了。
|
||||
|
||||
#### 库
|
||||
|
||||
需要两个库帮助实现数据传输。首先是 ZeroMQ 的 Python 封装:
|
||||
|
||||
```
|
||||
$ python3 -m pip install zmq
|
||||
```
|
||||
|
||||
另一个就是 [struct 库][21],用于解码二进制数据。这个库是 Python 标准库的一部分,所以不需要使用 `pip` 命令安装。
|
||||
|
||||
Python 程序的第一部分是导入这些库:
|
||||
|
||||
```
|
||||
import zmq
|
||||
import struct
|
||||
```
|
||||
|
||||
#### 重要参数
|
||||
|
||||
使用 ZeroMQ 时,只能向常量 `TOPIC` 定义相同的接收端发送消息:
|
||||
|
||||
```
|
||||
topic = "fancyhw_data".encode('ascii')
|
||||
|
||||
print("Reading messages with topic: {}".format(topic))
|
||||
```
|
||||
|
||||
#### 初始化
|
||||
|
||||
下一步,初始化上下文和套接字。使用 `subscribe` 套接字(也称为 `SUB` 套接字),它是 `PUB` 套接字的天生伴侣。这个套接字发送时也需要匹配主题。
|
||||
|
||||
```
|
||||
with zmq.Context() as context:
|
||||
socket = context.socket(zmq.SUB)
|
||||
|
||||
socket.connect("tcp://127.0.0.1:5555")
|
||||
socket.setsockopt(zmq.SUBSCRIBE, topic)
|
||||
|
||||
i = 0
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### 接收消息
|
||||
|
||||
启动一个无限循环,等待接收发送到 `SUB` 套接字的新消息。这个循环会在你按下 `Ctrl+C` 组合键或者内部发生错误时终止:
|
||||
|
||||
```
|
||||
try:
|
||||
while True:
|
||||
|
||||
... # we will fill this in next
|
||||
|
||||
except KeyboardInterrupt:
|
||||
socket.close()
|
||||
except Exception as error:
|
||||
print("ERROR: {}".format(error))
|
||||
socket.close()
|
||||
```
|
||||
|
||||
这个循环等待 `recv()` 方法获取的新消息,然后将接收到的内容从第一个空格字符处分割开,从而得到主题:
|
||||
|
||||
|
||||
```
|
||||
binary_topic, data_buffer = socket.recv().split(b' ', 1)
|
||||
```
|
||||
|
||||
#### 解码消息
|
||||
|
||||
Python 此时尚不知道主题是个字符串,使用标准 ASCII 编解码器进行解码:
|
||||
|
||||
```
|
||||
topic = binary_topic.decode(encoding = 'ascii')
|
||||
|
||||
print("Message {:d}:".format(i))
|
||||
print("\ttopic: '{}'".format(topic))
|
||||
```
|
||||
|
||||
下一步就是使用 `struct` 库读取二进制数据,它可以将二进制数据段转换为明确的数值。首先,计算数据包中数值的组数。本例中使用的 16 个位的有符号整数对应的是 `struct` [格式字符][22] 中的 `h`:
|
||||
|
||||
```
|
||||
packet_size = len(data_buffer) // struct.calcsize("h")
|
||||
|
||||
print("\tpacket size: {:d}".format(packet_size))
|
||||
```
|
||||
|
||||
知道数据包中有多少组数据后,就可以通过构建一个包含数据组数和数据类型的字符串,来定义格式了(比如“`16h`”):
|
||||
|
||||
```
|
||||
struct_format = "{:d}h".format(packet_size)
|
||||
```
|
||||
|
||||
将二进制数据串转换为可直接打印的一系列数字:
|
||||
|
||||
```
|
||||
data = struct.unpack(struct_format, data_buffer)
|
||||
|
||||
print("\tdata: {}".format(data))
|
||||
```
|
||||
|
||||
#### 完整 Python 代码
|
||||
|
||||
下面是 Python 实现的完整的接收端:
|
||||
|
||||
```
|
||||
#! /usr/bin/env python3
|
||||
|
||||
import zmq
|
||||
import struct
|
||||
|
||||
topic = "fancyhw_data".encode('ascii')
|
||||
|
||||
print("Reading messages with topic: {}".format(topic))
|
||||
|
||||
with zmq.Context() as context:
|
||||
socket = context.socket(zmq.SUB)
|
||||
|
||||
socket.connect("tcp://127.0.0.1:5555")
|
||||
socket.setsockopt(zmq.SUBSCRIBE, topic)
|
||||
|
||||
i = 0
|
||||
|
||||
try:
|
||||
while True:
|
||||
binary_topic, data_buffer = socket.recv().split(b' ', 1)
|
||||
|
||||
topic = binary_topic.decode(encoding = 'ascii')
|
||||
|
||||
print("Message {:d}:".format(i))
|
||||
print("\ttopic: '{}'".format(topic))
|
||||
|
||||
packet_size = len(data_buffer) // struct.calcsize("h")
|
||||
|
||||
print("\tpacket size: {:d}".format(packet_size))
|
||||
|
||||
struct_format = "{:d}h".format(packet_size)
|
||||
|
||||
data = struct.unpack(struct_format, data_buffer)
|
||||
|
||||
print("\tdata: {}".format(data))
|
||||
|
||||
i += 1
|
||||
|
||||
except KeyboardInterrupt:
|
||||
socket.close()
|
||||
except Exception as error:
|
||||
print("ERROR: {}".format(error))
|
||||
socket.close()
|
||||
```
|
||||
|
||||
将上面的内容保存到名为 `online_analysis.py` 的文件。Python 代码不需要编译,你可以直接运行它。
|
||||
|
||||
运行输出如下:
|
||||
|
||||
```
|
||||
$ ./online_analysis.py
|
||||
Reading messages with topic: b'fancyhw_data'
|
||||
Message 0:
|
||||
topic: 'fancyhw_data'
|
||||
packet size: 16
|
||||
data: (20946, -23616, 9865, 31416, -15911, -10845, -5332, 25662, 10955, -32501, -18717, -24490, -16511, -28861, 24205, 26568)
|
||||
Message 1:
|
||||
topic: 'fancyhw_data'
|
||||
packet size: 16
|
||||
data: (12505, 31355, 14083, -19654, -9141, 14532, -25591, 31203, 10428, -25564, -732, -7979, 9529, -27982, 29610, 30475)
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
### 小结
|
||||
|
||||
本教程介绍了一种新方式,实现从基于 C 的硬件接口收集数据,并分发到基于 Python 的基础设施的功能。借此可以获取数据供后续分析,或者转送到任意数量的接收端去。它采用了一个消息库实现数据在发送者和处理者之间的传送,来取代同样功能规模庞大的软件。
|
||||
|
||||
本教程还引出了我称之为“软件粒度”的概念,换言之,就是将软件细分为更小的部分。这种做法的优点之一就是,使得同时采用不同的编程语言实现最简接口作为不同部分之间沟通的组件成为可能。
|
||||
|
||||
实践中,这种设计使得软件工程师能以更独立、合作更高效的方式做事。不同的团队可以专注于数据分析的不同方面,可以选择自己中意的实现工具。这种做法的另一个优点是实现了零代价的并行,因为所有的进程都可以并行运行。[ZeroMQ 消息库][3] 是个令人赞叹的软件,使用它可以让工作大大简化。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/zeromq-c-python
|
||||
|
||||
作者:[Cristiano L. Fontana][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[silentdawn-zz](https://github.com/译者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/cristianofontana
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
|
||||
[2]: https://docs.python.org/3/extending/extending.html
|
||||
[3]: https://zeromq.org/
|
||||
[4]: https://en.wikipedia.org/wiki/Network_socket
|
||||
[5]: https://en.wikipedia.org/wiki/Pieter_Hintjens
|
||||
[6]: http://hintjens.com/
|
||||
[7]: https://gcc.gnu.org/
|
||||
[8]: https://clang.llvm.org/
|
||||
[9]: https://github.com/zeromq/libzmq#installation-of-binary-packages-
|
||||
[10]: https://www.python.org/downloads/
|
||||
[11]: https://zeromq.org/languages/python/
|
||||
[12]: http://www.opengroup.org/onlinepubs/009695399/functions/srand.html
|
||||
[13]: http://www.opengroup.org/onlinepubs/009695399/functions/rand.html
|
||||
[14]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
|
||||
[15]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
|
||||
[16]: http://zguide.zeromq.org/page:all#Plugging-Sockets-into-the-Topology
|
||||
[17]: http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html
|
||||
[18]: https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29%23C_and_C++
|
||||
[19]: http://www.opengroup.org/onlinepubs/009695399/functions/memcpy.html
|
||||
[20]: https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)
|
||||
[21]: https://docs.python.org/3/library/struct.html
|
||||
[22]: https://docs.python.org/3/library/struct.html#format-characters
|
@ -0,0 +1,62 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (JonnieWayy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12479-1.html)
|
||||
[#]: subject: (How failure-driven development makes you successful)
|
||||
[#]: via: (https://opensource.com/article/20/3/failure-driven-development)
|
||||
[#]: author: (Jessica Cherry https://opensource.com/users/jrepka)
|
||||
|
||||
屡屡失败犯错的我为什么没有被开除
|
||||
======
|
||||
|
||||
> 我是词典里 “失败” 一词旁边的插图,这就是为什么我擅长我的工作的原因。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202008/02/212013q5jjc78ihwd72cij.jpg)
|
||||
|
||||
我的职称是高级软件工程师,但我最亲近的同事并不这么称呼我。由于我摧毁一切,他们管我叫“樱桃炸弹”(正巧我姓“樱桃”)。我定期会遇到的失败已经可以影响到我们的季度性收益和停机时间。简单的来说,我就是你所听说过的生产灾难:“别动,啥都别做,无论何时何地。”
|
||||
|
||||
我的职业生涯始于支持服务台,在那里我写了一些循环,破坏了高端客户的服务器。我曾在没有警告的情况下将生产应用程序关闭了长达八个小时,并且在试图使得情况好转的过程中摧毁了无数个集群,有几次只是因为我打错了字。
|
||||
|
||||
我是我们在 [Kubernetes][2] 中设有灾难恢复(DR)集群的原因。我是个混乱的工程师,我们有一个应用程序,它的故障恢复计划还从未测试过,而我在没有警告的情况下,就教人们如何快速行动和排除故障。我作为可能失败的最好例子而存在,这实际上是有史以来最酷的事情。
|
||||
|
||||
### 我和消失的 K8s 集群
|
||||
|
||||
我的正式职责之一涉及到我们的应用架构。对于任何形式的架构改动,我都要进行代码的编写与测试,看看有什么可能性。近来,据说这成了我老板史诗级的痛苦,这只是轻描淡写。
|
||||
|
||||
我们在 Kubernetes 上运行我们的大多数基础架构,Kubernetes 以其弹性著称。尽管有这样的声誉,我还是使得两个集群,好吧,消失了。你可能会好奇我是怎么做到的,很容易,`terraform destroy`。我们通过 [Terraform][3] 以代码的方式管理我们的基础架构,并且不需要任何软件知识就知道 `destroy` 可做坏事。在你惊慌失措之前,好吧,是开发集群,所以我还活着。
|
||||
|
||||
鉴于此,你们肯定会问我为什么还没丢掉饭碗,以及为什么我要写下这些事情。这很好回答:我仍然有工作,是因为我更新的基础架构代码比起起初的代码工作得更好更快了。我写下这些是因为每个人都会经常性地遭遇失败,这是非常非常正常的。如果你没有时不时遭遇失败,我认为你并没有足够努力地学习。
|
||||
|
||||
### 破坏东西并培训人们
|
||||
|
||||
你可能还会认为永远不会有人让我去培训任何人。那是最糟糕的主意,因为(就像我的团队开玩笑说的)你永远都不应该做我所做的事情。但是我的老板却让我定期去训练新人。我甚至为整个团队提供使用我们的基础设施或代码的培训,教人们如何建立自己的基础设施。
|
||||
|
||||
原因是这样的:失败是你迈向成功的第一步。失败的教训绝不只是“备份是个绝佳的主意”。不,从失败中,你学会了更快地恢复、更快地排除故障并且在你工作中取得惊人的进步。当你在工作中变得惊人的时候,你就可以培训其他人,教给他们什么事情不要做,并且帮助他们去理解一切是如何工作的。由于你的经验,他们会比你开始时更进一步 —— 而且他们也很可能以新的、惊人的、史诗般的方式失败,每个人都可以从中学到东西。
|
||||
|
||||
### 你的成功取决于你的失败
|
||||
|
||||
没有人生来就具有软件工程和云基础架构方面的天赋,就像没有人天生就会走路。我们都是从滚动和翻爬开始的。从那时起,我们学会爬行,然后能够站立一会儿。当我们开始走路后,我们会跌倒并且擦伤膝盖,撞到手肘,还有,比如像我哥哥,走着走着撞上桌子的尖角,然后在眉毛中间缝了针。
|
||||
|
||||
凡事都需要时间去学习。一路上阅读手边能获得的一切来帮助你,但这永远只是个开始。完美是无法实现的幻想,你必须通过失败来取得成功。
|
||||
|
||||
每走一步,我的失败都教会我如何把事情做得更好。
|
||||
|
||||
最终,你的成功和你累积的失败一样多,这标志着你成功的程度。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/failure-driven-development
|
||||
|
||||
作者:[Jessica Cherry][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[JonnieWayy](https://github.com/JonnieWayy)
|
||||
校对:[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/fail_failure_celebrate.png?itok=LbvDAEZF (failure sign at a party, celebrating failure)
|
||||
[2]: https://www.redhat.com/en/topics/containers/what-is-kubernetes
|
||||
[3]: https://github.com/hashicorp/terraform
|
@ -0,0 +1,220 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "mr-ping"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-12125-1.html"
|
||||
[#]: subject: "Different Ways To Update Linux Kernel For Ubuntu"
|
||||
[#]: via: "https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/"
|
||||
[#]: author: "SK https://www.ostechnix.com/author/sk/"
|
||||
|
||||
升级 Ubuntu Linux 内核的几种不同方法
|
||||
======
|
||||
|
||||
![](https://www.ostechnix.com/wp-content/uploads/2019/01/ubuntu-linux-kernel-720x340.png)
|
||||
|
||||
这个指南里介绍了 7 种为 Ubuntu 升级 Linux 内核的不同方法。这 7 种方法里,有 5 种需要重启系统来使新内核生效,其他两种则不用。升级之前,**强烈建议你将重要数据进行备份!** 这里提到的所有方法只在 Ubuntu 中测试过。我们并不确定这些方法是不是也能适用于其他 Ubuntu 的特色发行版(如: Xubuntu)和衍生发行版(如:Linux Mint)。
|
||||
|
||||
### 第一部分:需要重启的内核升级
|
||||
|
||||
以下方法需要你重启系统以便新的内核生效。以下所有方法都建议在个人系统或测试系统中进行。重要的事儿再说一遍,请备份好你 Ubuntu 中的重要数据、配置文件和其他重要的东西。
|
||||
|
||||
#### 方法 1 - 使用 dpkg 升级 Linux 内核(手动方式)
|
||||
|
||||
这个方法可以帮助你从 [kernel.ubuntu.com][1] 网站手动下载可用的最新 Linux 内核。如果你打算安装最新版(而不是稳定版或者正式发布版),那这种方法对你会很有用。从以上链接下载 Linux 内核版本。编写这个指南的时候,最新的可用版本是 **5.0-rc1**,最新的稳定版是 **v4.20**。
|
||||
|
||||
![][3]
|
||||
|
||||
点击你所选择的 Linux 内核版本链接,找到你对应的架构(“Build for XXX”)的那部分。然后下载符合以下格式的两个文件(其中 X.Y.Z 是最高版本号):
|
||||
|
||||
1. linux-image-*X.Y.Z*-generic-*.deb
|
||||
2. linux-modules-X.Y.Z*-generic-*.deb
|
||||
|
||||
在终端中改变到文件所在的目录,然后执行此命令手动安装内核:
|
||||
|
||||
```
|
||||
$ sudo dpkg --install *.deb
|
||||
```
|
||||
|
||||
重启系统,使用新内核:
|
||||
|
||||
```
|
||||
$ sudo reboot
|
||||
```
|
||||
|
||||
检查是否如你所愿:
|
||||
|
||||
```
|
||||
$ uname -r
|
||||
```
|
||||
|
||||
对于分步的说明,请查看下列链接中对应的部分。
|
||||
|
||||
+ [在基于 RPM 和 DEB 的系统中安装 Linux 内核 4.15](https://www.ostechnix.com/install-linux-kernel-4-15-rpm-deb-based-systems/)
|
||||
|
||||
以上的指南是针对的是 4.15 版本,不过安装最新版本的所有的步骤都是一样的。
|
||||
|
||||
**优势:** 不必联网(你可以从任何系统中下载 Linux 内核来使用)
|
||||
|
||||
**缺点:** 手动更新,需要重启系统。
|
||||
|
||||
#### 方法 2 - 用 apt-get 来升级 Linux 内核(推荐方法)
|
||||
|
||||
这是在类 Ubuntu 系统中升级 Linux 内核的推荐方法。不同于上一个方法,这种方法会从 Ubuntu 官方仓库下载、安装内核版本,而不是从 **kernel.ubuntu.com**网站。
|
||||
|
||||
要升级包括内核的整个系统,只需要执行:
|
||||
|
||||
```
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get upgrade
|
||||
```
|
||||
|
||||
如果只希望升级内核,运行:
|
||||
|
||||
```
|
||||
$ sudo apt-get upgrade linux-image-generic
|
||||
```
|
||||
|
||||
**优势:** 简单。推荐方法。
|
||||
|
||||
**缺点:** 需要联网,需要重启。
|
||||
|
||||
从官方库中升级内核是最接近开箱即用的方法,并且不会出什么问题。如果是生产环境的系统,这是最为推荐的升级 Linux 内核的方法。
|
||||
|
||||
方法 1 和方法 2 都需要用户去介入到升级 Linux 内核的过程中。而下边的方法(3、 4、 5)则几乎是全自动的。
|
||||
|
||||
#### 方法 3 - 使用 Ukuu 升级 Linux 内核
|
||||
|
||||
**Ukuu**是一个 Gtk GUI 和命令行工具,它可以从 kernel.ubuntu.com 下载最新的 Linux 主线内核,并自动安装到你的 Ubuntu 桌面版和服务器版中。Ukku 不仅简化了手动下载和安装新内核的过程,同时也会帮助你安全地移除旧的和不再需要的内核。更多细节可以参照以下指南。
|
||||
|
||||
+ [Ukuu:在 Ubuntu 系统中安装和升级 Linux 内核的简单方法](https://www.ostechnix.com/ukuu-an-easy-way-to-install-and-upgrade-linux-kernel-in-ubuntu-based-systems/)
|
||||
|
||||
**优势:** 易于安装使用。自动安装主线内核。
|
||||
|
||||
**缺点:** 需要联网,需要重启。
|
||||
|
||||
#### 方法 4 - 使用 UKTools 升级 Linux 内核
|
||||
|
||||
跟 Ukuu 差不多,**UKTools** 也会从 kernel.ubuntu.com 网站获取最新的稳定内核并且自动安装到 Ubuntu 以及类似于 Linux Mint 的延伸发行版中。关于UKTools的更多详情,请参见下面的链接。
|
||||
|
||||
+ [UKTools:升级Ubuntu及其衍生产品中的最新Linux内核](https://www.ostechnix.com/uktools-upgrade-latest-linux-kernel-in-ubuntu-and-derivatives/)
|
||||
|
||||
**优势:** 简单,自动。
|
||||
|
||||
**缺点:** 需要联网,需要重启。
|
||||
|
||||
#### 方法 5 - 使用 Linux 内核实用程序更新 Linux 内核
|
||||
|
||||
**Linux 内核实用程序**是目前另一个用于升级类 Ubuntu 系统 Linux 内核的程序。实质上,它是一个由一系列 Bash 脚本构成的合集,用于编译并且可以选择性地为 Debian(LCTT 译注:Ubuntu 的上游发行版)及其衍生发行版升级内核。它包含三个实用程序,一个用于手动编译、安装来自于 [http://www.kernel.org][4] 网站的源码内核,另一个用于安装来自 <https://kernel.ubuntu.com> 网站的预编译的内核,第三个脚本用于移除旧内核。更多细节请浏览以下链接。
|
||||
|
||||
+ [Linux 内核实用程序:编译和更新最新的 Linux 内核的脚本,适用于 Debian 及其衍生产品](https://www.ostechnix.com/linux-kernel-utilities-scripts-compile-update-latest-linux-kernel-debian-derivatives/)
|
||||
|
||||
**优势:** 简单,自动。
|
||||
|
||||
**缺点:** 需要联网,需要重启。
|
||||
|
||||
### 第二部分:无需重启的内核升级
|
||||
|
||||
我之前说过,上边所有的方法都需要你重启服务器(LCTT 译注:也可以是桌面版)来启用新内核。如果是个人系统或者测试系统,可以这么办。但对于无法停机的生产环境系统该怎么办呢?一点问题没有,这时候<ruby>实时补丁<rt>livepatching</rt></ruby>就派上用场了。
|
||||
|
||||
**实时补丁**(或者叫热补丁)允许你在不重启的情况下安装 Linux 更新或补丁,使你的服务器处于最新的安全级别。这对 web 主机、游戏服务器这类需要不间断在线的服务器来说是很有价值的。事实上,任何情况下,服务器都应该保持在不间断运行的状态下。由于 Linux 供应商只会在出于修复安全漏洞的目的下维护补丁,所以如果安全性是你最关注的问题时,这种方式再适合不过了。
|
||||
|
||||
以下两种方法不需要重启,对于生产环境和执行关键任务的 Ubuntu 服务器的 Linux 内核更新非常有用。
|
||||
|
||||
#### 方法 6 – 使用 Canonical 实时补丁服务来更新 Linux 内核
|
||||
|
||||
![][5]
|
||||
|
||||
[Canonical 实时补丁服务][6]可以在不需要重启 Ubuntu 系统的情况下自动应用内核更新、补丁和安全补丁。它可以减少Ubuntu系统的停机时间,并保证系统的安全。Canonical 实时补丁服务可以在安装过程当中或安装之后进行设置。如果你使用的是 Ubuntu 桌面版,软件更新器会自动检查内核补丁的更新,并通知你。在基于控制台的系统中,则需要你定期运行 `apt-get update` 命令来进行升级。由于需要你手动运行 `apt-get upgrade` 命令它才会安装内核的安全补丁,所以算是半自动的。
|
||||
|
||||
实时补丁对三个及以下系统免费,如果多于三个,你需要升级成名为 **Ubuntu Advantage** 的企业支持方案套件。这个套件包括 **Kernel 实时补丁**及以下服务:
|
||||
|
||||
* 扩展安全维护 – Ubuntu 生命周期后的重要安全更新
|
||||
* Landscape – 针对大规模使用 Ubuntu 的系统管理工具
|
||||
* 知识库 – 由 Ubuntu 专家撰写的私人文章和教程
|
||||
* 电话和网站支持
|
||||
|
||||
**价格**
|
||||
|
||||
Ubuntu Advantage 包含三种付费计划,即基本计划、标准计划和高级计划。最基础的计划(基本计划)从 **单物理节点 225 美元/年**和**单VPS 75美元/年**开始计价。对于 Ubuntu 服务器版和桌面版看上去没有按月订阅。你可以在[此处][7]浏览所有计划的细节信息。
|
||||
|
||||
**优势:** 简单。半自动化。无需重启。支持三个免费系统。
|
||||
|
||||
**缺点:** 4 个以上主机的话非常昂贵。没有补丁回滚。
|
||||
|
||||
##### 开启 Canonical 实时补丁
|
||||
|
||||
如果你想在安装后设置实时补丁服务,依照以下方法逐步执行:
|
||||
|
||||
从 [https://auth.livepatch.canonical.com/][8] 获取一个密钥。
|
||||
|
||||
```
|
||||
$ sudo snap install canonical-livepatch
|
||||
$ sudo canonical-livepatch enable your-key
|
||||
```
|
||||
|
||||
#### 方法 7 - 使用 KernelCare 升级 Linux 内核
|
||||
|
||||
![][9]
|
||||
|
||||
[KernelCare][10] 是最新的实时补丁方案。它是 [CloudLinux][11] 推出的产品。KernelCare 可以运行在 Ubuntu 和其他的 Linux 发行版中。它每四个小时检查一遍补丁的发布,并在无需确认的情况下安装它们。如果更新后存在问题,可以将补丁进行回滚。
|
||||
|
||||
**价格**
|
||||
|
||||
费用,每台服务器:**4 美元/月**,**45 美元/年**。
|
||||
|
||||
跟 Ubuntu 实时补丁相比,KernelCare 看起来非常便宜、实惠。好的方面在于**也可以按月订阅**。另一个前者不具备的功能是支持其他 Linux 发行版,如 Red Hat、CentOS、Debian、Oracle Linux、Amazon Linux 以及 OpenVZ、Proxmox 等虚拟化平台。
|
||||
|
||||
你可以在[此处][12]了解 KernelCare 的所有特性和简介,以及所有的付费计划的细节。
|
||||
|
||||
**优势:** 简单。全自动化。覆盖范围更广的操作系统。补丁回滚。无需重启。对非营利组织提供免费许可。价格低廉。
|
||||
|
||||
**缺点:** 不是免费的(除了30天的试用期)。
|
||||
|
||||
##### 开启 KernelCare 服务
|
||||
|
||||
在 [https://cloudlinux.com/kernelcare-free-trial5][14] 获取一个 30 天免费试用密钥。
|
||||
|
||||
执行以下命令开启 KernelCare 并注册秘钥。
|
||||
|
||||
```
|
||||
$ sudo wget -qq -O - https://repo.cloudlinux.com/kernelcare/kernelcare_install.sh | bash
|
||||
$ sudo /usr/bin/kcarectl --register KEY
|
||||
```
|
||||
|
||||
如果你正在寻找一种经济实惠且可靠的商业服务来保持 Linux 服务器上的 Linux 内核更新,那么 KernelCare 是个不错的选择。
|
||||
|
||||
*由来自 Cloud Linux 的技术撰稿人和内容作者 Paul A. Jacobs 提供。*
|
||||
|
||||
到此,希望这边文章能对你有所帮助。如果你觉得还有其他的工具和方法需要列在这里,可以在留言区给我们留言。我会根据反馈检查和更新这篇指南的。
|
||||
|
||||
接下来会有更多好东西给大家呈现,敬请期待。
|
||||
|
||||
Cheers!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/
|
||||
|
||||
作者:[SK][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[mr-ping](https://github.com/mr-ping)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.ostechnix.com/author/sk/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: http://kernel.ubuntu.com/~kernel-ppa/mainline/
|
||||
[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
|
||||
[3]: http://www.ostechnix.com/wp-content/uploads/2019/01/Ubuntu-mainline-kernel.png
|
||||
[4]: http://www.kernel.org
|
||||
[5]: http://www.ostechnix.com/wp-content/uploads/2019/01/Livepatch.png
|
||||
[6]: https://www.ubuntu.com/livepatch
|
||||
[7]: https://www.ubuntu.com/support/plans-and-pricing
|
||||
[8]: https://auth.livepatch.canonical.com/
|
||||
[9]: http://www.ostechnix.com/wp-content/uploads/2019/01/KernelCare.png
|
||||
[10]: https://www.kernelcare.com/
|
||||
[11]: https://www.cloudlinux.com/
|
||||
[12]: https://www.kernelcare.com/update-kernel-linux/
|
||||
[13]: https://www.kernelcare.com/pricing/
|
||||
[14]: https://cloudlinux.com/kernelcare-free-trial5
|
142
published/202004/20190116 Best Audio Editors For Linux.md
Normal file
142
published/202004/20190116 Best Audio Editors For Linux.md
Normal file
@ -0,0 +1,142 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MFGJT)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12095-1.html)
|
||||
[#]: subject: (Best Audio Editors For Linux)
|
||||
[#]: via: (https://itsfoss.com/best-audio-editors-linux)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
Linux 上的最佳音频编辑工具推荐
|
||||
======
|
||||
|
||||
在 Linux 上,有很多种音频编辑器可供你选用。不论你是一个专业的音乐制作人,还是只想学学怎么做出超棒的音乐的爱好者,这些强大的音频编辑器都是很有用的工具。
|
||||
|
||||
对于专业级的使用,我总是建议使用 [DAW][1](数码音频工作站)。但并不是每个人都需要全部的功能,所以你也应该了解一些最简单的音频编辑器。
|
||||
|
||||
在本文中,我们将讨论几款 DAW 和基础的音频编辑器,而且它们都是在 Linux 和(可能)其它操作系统上可以使用的**自由开源**的解决方案。
|
||||
|
||||
### Linux 上的最佳音频编辑器
|
||||
|
||||
![Best audio editors and DAW for Linux][2]
|
||||
|
||||
我们不会关注 DAW 提供的所有功能,而只是关注基本的音频编辑功能。不过,你仍然可以把以下内容看作是 Linux 的最佳 DAW 名单。
|
||||
|
||||
**安装说明:**你可以在 AppCenter 或软件中心中找到所有提到的音频编辑器或 DAW。如果你在这两个地方没有找到它们,请前往它们的官方网站获取更多信息。
|
||||
|
||||
#### 1、Audacity
|
||||
|
||||
![Audacity audio editor][3]
|
||||
|
||||
[Audacity](https://www.audacityteam.org/) 是 Linux 中最基本音频编辑器之一,但是它也很强大。它是一个自由开源的跨平台工具。肯定已经有很多人了解这个软件了。
|
||||
|
||||
现在的它相比它最初流行的时候有了很大的改进。我记得我以前试着通过从音频中去除人声来制作卡拉 OK 伴奏。现在有些时候,你仍然可以这么做。
|
||||
|
||||
**特性:**
|
||||
|
||||
它还支持包含 VST 效果的插件。当然,你不应该期望它支持 VST 乐器。
|
||||
|
||||
* 通过麦克风或混音器进行现场录制
|
||||
* 支持同时从多种音频格式的多个文件中批量导出/导入内容
|
||||
* 支持 LADSPA、LV2、Nyquist、VST 和 Audio Unit 的效果插件
|
||||
* 使用简单,带有剪切、粘贴、删除和拷贝的功能
|
||||
* 可观测声音频率的频谱模式
|
||||
|
||||
#### 2、LMMS
|
||||
|
||||
![LMMS audio editor][4]
|
||||
|
||||
[LMMS](https://lmms.io/) 是一个自由开源的(跨平台)数码音频工作站。它包括所有基本的音频编辑功能以及许多高级功能。
|
||||
|
||||
你可以混音、组合音频,或使用 VST 设备创造音频。LMMS 支持这些功能。此外,它还自带一些样本音频、预设、VST 设备和特效来帮助你起步。此外,你还可以得到一个频谱分析仪,以便进行高级的音频编辑工作。
|
||||
|
||||
**特性:**
|
||||
|
||||
* 基于 MIDI 的音符回放
|
||||
* 支持 VST 设备
|
||||
* 原生支持多采样
|
||||
* 内置压缩器、限制器、延迟功能、混响功能、失真功能和低音增强器
|
||||
|
||||
#### 3、Ardour
|
||||
|
||||
![Ardour audio editor][5]
|
||||
|
||||
[Ardour](https://ardour.org/) 是另一个自由开源的数码音频工作站。只要你有音频接口,Ardour 就支持它的使用。当然,你也可以无限地添加多声道音轨。这些多声道音轨也可以被指派到不同的混音带,以方便编辑和录音。
|
||||
|
||||
你也可以导入一个视频,编辑其中的音频,然后导出新的视频。它提供了许多内置插件,并且支持 VST 插件。
|
||||
|
||||
**特性:**
|
||||
|
||||
* 非线性编辑
|
||||
* 垂直窗口堆叠,便于导航
|
||||
* <ruby>静默消除功能<rt>strip silence</rt></ruby>,<ruby>推拉修剪功能<rt>push-pull trimming</rt></ruby>,和用以短暂片段或基于基于音符开始的编辑的 Rhythm Ferret。
|
||||
|
||||
#### 4、Cecilia
|
||||
|
||||
![Cecilia audio editor][6]
|
||||
|
||||
[Cecilia](http://ajaxsoundstudio.com/software/cecilia/) 不是一个普通的音频编辑器。它的使用者一般是音效设计师或者正在努力成为音效设计师的人。 Cecilia 实际上是一个音频信号处理环境。它可以让你的作品余音绕梁。
|
||||
|
||||
你还可以得到内置的音效与合成模组和插件。Cecilia 为一个明确的目的而生:如果你正在找音效设计工具,这是你的不二之选!
|
||||
|
||||
**特性:**
|
||||
|
||||
* 利用模块来完成更多工作(UltimateGrainer —— 最先进的颗粒化处理工具,RandomAccumulator —— 记录变量速度的累加器,UpDistoRes——通过上采样和谐振低通滤波器创造失真效果的工具)
|
||||
* 自动保存调制设定
|
||||
|
||||
#### 5、Mixxx
|
||||
|
||||
![Mixxx audio DJ][7]
|
||||
|
||||
如果你想要在混合和录制一些东西的同时能够有一个虚拟的 DJ 工具,[Mixxx](https://www.mixxx.org/) 将是完美的工具。你可以用到 BPM、音调,并使用主同步功能来匹配歌曲的节奏和节拍。另外,不要忘记它也是一个 Linux 的自由开源的软件。
|
||||
|
||||
它还支持自定义 DJ 设备。所以,如果你有 DJ 设备或者 MIDI,你可以用这个工具录制你的现场混音。
|
||||
|
||||
**特性:**
|
||||
|
||||
* 播送和录制你的歌曲的 DJ 混音
|
||||
* 可以连接到你的设备并且现场演奏
|
||||
* 音调检测和 BPM 检测
|
||||
|
||||
#### 6、Rosegarden
|
||||
|
||||
![Rosegarden audio editor][9]
|
||||
|
||||
[Rosegarden](https://www.rosegardenmusic.com/) 是另一个令人赞叹的 Linux 的自由开源的音频编辑器。它既不是一个功能齐全的 DAW,也不是一个基本的音频编辑工具。它是两者的混合体,并带有一些缩减的功能。
|
||||
|
||||
我不会向专业人士推荐这款软件,但如果你经营家庭音乐工作室或只是想体验一下,这将是 Linux 上可以安装的最好的音频编辑器之一。
|
||||
|
||||
**特性:**
|
||||
|
||||
* 乐谱编辑
|
||||
* 录音、混音以及采样
|
||||
|
||||
### 小结
|
||||
|
||||
这些是你可以找到的 Linux 上的最棒的一些音频编辑器了。不论你是需要 DAW,一个剪切/粘贴的编辑工具,或者仅仅想要一个拥有基础的混音和录音功能的音频编辑工具,上述软件都能够满足你的需求。
|
||||
|
||||
如果在这篇文章中我们遗漏了你最喜欢的一些音频工具,可以在原文下方评论中回复告诉我们。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/best-audio-editors-linux
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[MFGJT](https://github.com/MFGJT)
|
||||
校对:[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://en.wikipedia.org/wiki/Digital_audio_workstation
|
||||
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors-800x450.jpeg?resize=800%2C450&ssl=1
|
||||
[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/audacity-audio-editor.jpg?fit=800%2C591&ssl=1
|
||||
[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/lmms-daw.jpg?fit=800%2C472&ssl=1
|
||||
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/ardour-audio-editor.jpg?fit=800%2C639&ssl=1
|
||||
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/cecilia.jpg?fit=800%2C510&ssl=1
|
||||
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/mixxx.jpg?fit=800%2C486&ssl=1
|
||||
[8]: https://itsfoss.com/dj-mixxx-2/
|
||||
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/rosegarden.jpg?fit=800%2C391&ssl=1
|
||||
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors.jpeg?fit=800%2C450&ssl=1
|
@ -0,0 +1,156 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12113-1.html)
|
||||
[#]: subject: (Installing Kali Linux on VirtualBox: Quickest & Safest Way)
|
||||
[#]: via: (https://itsfoss.com/install-kali-linux-virtualbox/)
|
||||
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
|
||||
|
||||
在 VirtualBox 上安装 Kali Linux:最快速和最安全的方法
|
||||
======
|
||||
|
||||
> 这篇教程向你展示如何在 Windows 和 Linux 中以最快的方式在 VirtualBox 上安装 Kali Linux。
|
||||
|
||||
[Kali Linux][1] 是 [最适合脆弱性测试和安全爱好者的 Linux 发行版][2] 之一。
|
||||
|
||||
因为它涉及一个像黑客之类的敏感话题,就像一把双刃剑。我们过去在详细的 Kali Linux 评论中讨论过,所以我不会再次赘述。
|
||||
|
||||
虽然你可以通过替换现有的操作系统的形式安装 Kali Linux,但是通过虚拟机来使用它可能会是更好、更安全的选择。
|
||||
|
||||
使用 VirtualBox,你可以在 Windows/Linux 系统中将 Kail Linux 作为常规应用程序使用。这和在系统中运行 VLC 或游戏几乎是一样的。
|
||||
|
||||
在虚拟机中使用 Kali Linux 是安全的。不管你在 Kali Linux 做什么都不会影响你的 ‘宿主系统’(即你原来的 Windows 或 Linux 操作系统)。你的实际操作系统将不会受到影响,并且在你的宿主系统中数据也是安全的。
|
||||
|
||||
![][3]
|
||||
|
||||
### 如何在 VirtualBox 中安装 Kali Linux
|
||||
|
||||
在这里我会使用 [VirtualBox][4]。它是一个非常好的开源虚拟化解决方案,几乎适合于任何人,无论是专业使用或个人使用。它是免费提供的。
|
||||
|
||||
在这篇文章中,我们将特别讨论 Kali Linux,但你也可以安装几乎任何其他的操作系统,只要有 ISO 文件或预建的虚拟机保存文件就可以安装。
|
||||
|
||||
**注意:**同样的步骤适用于运行 VirtualBox 的 Windows 或 Linux。
|
||||
|
||||
如上所述 ,你可以安装 Windows 或 Linux 作为你的宿主系统。但是,在我已安装 Windows 10 的情况下(别仇恨我!),我会尝试着在其上的 VirtualBox 中一步步地安装 Kali Linux 。
|
||||
|
||||
并且,最棒的是,即使你碰巧使用一个 Linux 发行版作为你的主要操作系统,也将使用同样的步骤!
|
||||
|
||||
想知道如何做?让我们来看看…
|
||||
|
||||
- [video](https://youtu.be/TGOiAsSdADs)
|
||||
|
||||
### 在 VirtualBox 上安装 Kali Linux 的分步指南
|
||||
|
||||
我们将使用一个专门为 VirtualBox 定制的 Kali Linux 镜像。你也可以下载 Kali Linux 的 ISO 文件,并创建一个新的虚拟机,但是当你有一个简单的选择时,为什么还这样做呢?
|
||||
|
||||
#### 1、下载并安装 VirtualBox
|
||||
|
||||
第一件要做的事是从甲骨文的官方网站下载和安装 VirtualBox。
|
||||
|
||||
- [下载 VirtualBox][6]
|
||||
|
||||
在你下载了安装器之后,只需要双击它来安装 VirtualBox。在 [Ubuntu][7]/Fedora Linux 安装 VirtualBox 也是一样的方式。
|
||||
|
||||
#### 2、下载即用型的 Kali Linux 虚拟镜像
|
||||
|
||||
在安装成功后,前往 [Offensive Security 的下载页面][8] 来下载适用于 VirtualBox 的虚拟机镜像。如果你改变主意使用 [VMware][9],那里也有适用的。
|
||||
|
||||
![][10]
|
||||
|
||||
如你所见,文件大小大约 3 GB,你应该使用 torrent 方式,或者使用一个[下载管理器][11]来下载它。
|
||||
|
||||
- [下载 Kali Linux 虚拟镜像][8]
|
||||
|
||||
#### 3、在 Virtual Box 上安装 Kali Linux
|
||||
|
||||
当你安装 VirtualBox 并下载 Kali Linux 镜像后,你只需要将其导入到 VirtualBox 中就可以使其正常工作。
|
||||
|
||||
这里是如何导入 Kali Linux 的 VirtualBox 镜像:
|
||||
|
||||
##### 步骤 1
|
||||
|
||||
启动 VirtualBox。你会看到一个<ruby>导入<rt>Import</rt></ruby> 按钮,点击它。
|
||||
|
||||
![点击导入按钮][12]
|
||||
|
||||
##### 步骤 2
|
||||
|
||||
接下来,浏览刚刚下载的文件,选择要导入的文件(如下图所示)。文件名应该以“kali linux”开始,以 .ova 扩展名结束。
|
||||
|
||||
![导入 Kali Linux 镜像][13]
|
||||
|
||||
选择后,单击<ruby>下一步<er>Next</rt></.ruby>继续进行。
|
||||
|
||||
##### 步骤 3
|
||||
|
||||
现在,你会看到要导入的虚拟机的设置。所以,你可以自定义它们或者不自定义,这是你的选择。采用默认设置也是可以的。
|
||||
|
||||
你需要选择一个有足够可用存储空间的路径。在 Windows 上,我绝不建议使用 C: 盘。
|
||||
|
||||
![将硬盘驱动器导入为 VDI][14]
|
||||
|
||||
在这里,“将硬盘驱动器导入为 VDI”指的是通过分配存储器空间集来虚拟挂载硬盘驱动器。
|
||||
|
||||
在你完成设置后,单击<ruby>导入<rt>Import</rt></ruby>,等待一段时间。
|
||||
|
||||
##### 步骤 4
|
||||
|
||||
你现在将看到它被列在虚拟机列表中。所以,只需点击<ruby>开始<rt>Start</rt></ruby>来启动它。
|
||||
|
||||
你可能会在开始时得到一个 USB 2.0 端口控制器的错误,你可以禁用它来解决问题,或者只需按照屏幕上的指示来安装一个附加软件包修复问题。然后就大功告成了!
|
||||
|
||||
![Kali Linux 运行在 VirtualBox 中][15]
|
||||
|
||||
以前 Kali Linux 中的默认用户名是 root,默认密码是 toor。但从 2020 年 1 月起,Kali Linux 就不使用 root 账号了。现在,默认账号和密码都是 kali。
|
||||
|
||||
你应该可以用它来登录系统了。
|
||||
|
||||
请注意,在尝试安装一个新的应用程序或尝试破解 WiFi 密码之前,请先[更新 Kali Linux][16] 。
|
||||
|
||||
我希望这篇指南能帮助您在 VirtualBox 上很容易地安装 Kali Linux。当然,Kali Linux 有很多有用的渗透测试工具 – 祝你好运!
|
||||
|
||||
**提示** : Kali Linux 和 Ubuntu 都是基于 Debian 的,如果你在使用 Kali Linux 时遇到任何问题或错误,你可以按照互联网上的 Ubuntu 和 Debian 的教程解决。
|
||||
|
||||
### 奖励: 免费的 Kali Linux 指南书
|
||||
|
||||
如果你刚刚开始使用 Kali Linux, 那么了解如何使用 Kali Linux 就很有必要了。
|
||||
|
||||
Kali Linux 背后的公司 Offensive Security 制作了一本指南书,讲解了 Linux 的基础知识、Kali Linux 的基础知识、配置和设置,书中还有一些关于渗透测试和安全工具的章节。
|
||||
|
||||
基本上,它包含你上手 Kali Linux 所需要的一切东西。更重要的是,这本书可以免费下载。
|
||||
|
||||
- [免费下载《揭秘 Kali Linux》][17]
|
||||
|
||||
如果你在 VirtualBox 上使用 Kali Linux 时遇到问题,请在下面的评论中告诉我们,或者直接分享你的经验。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/install-kali-linux-virtualbox/
|
||||
|
||||
作者:[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://www.kali.org/
|
||||
[2]: https://itsfoss.com/linux-hacking-penetration-testing/
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box.png?resize=800%2C450&ssl=1
|
||||
[4]: https://www.virtualbox.org/
|
||||
[5]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
|
||||
[6]: https://www.virtualbox.org/wiki/Downloads
|
||||
[7]: https://itsfoss.com/install-virtualbox-ubuntu/
|
||||
[8]: https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/
|
||||
[9]: https://itsfoss.com/install-vmware-player-ubuntu-1310/
|
||||
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box-image.jpg?resize=800%2C347&ssl=1
|
||||
[11]: https://itsfoss.com/4-best-download-managers-for-linux/
|
||||
[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-import-kali-linux.jpg?ssl=1
|
||||
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-linux-next.jpg?ssl=1
|
||||
[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-kali-linux-settings.jpg?ssl=1
|
||||
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-on-windows-virtualbox.jpg?resize=800%2C429&ssl=1
|
||||
[16]: https://linuxhandbook.com/update-kali-linux/
|
||||
[17]: https://kali.training/downloads/Kali-Linux-Revealed-1st-edition.pdf
|
@ -0,0 +1,91 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12060-1.html)
|
||||
[#]: subject: (10 moments that shaped Linux history)
|
||||
[#]: via: (https://opensource.com/article/19/4/top-moments-linux-history)
|
||||
[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
|
||||
|
||||
塑造 Linux 历史的 10 个时刻
|
||||
======
|
||||
|
||||
> 自 1991 年诞生以来,Linux 已经走了漫长的一段路,而这些事件标志着它的发展。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/01/093243wukmsiwdkkwfrg00.jpg)
|
||||
|
||||
在 2018 年 8 月,Opensource.com 发布了一项包含七个选项的民意测验,询问读者:[Linux 历史上最重要的时刻是什么?][2]我觉得我需要扩大这个清单,并提出我认为的 10 个在塑造 Linux 历史上发挥了重要作用的时刻。
|
||||
|
||||
### 1、Linus 发布 Linux
|
||||
|
||||
Linus Torvalds 最初是在 1991 年将 Linux 当成一个业余爱好发布到世上的。结果这个业余爱好成了他的职业!
|
||||
|
||||
### 2、出现 Linux 发行版
|
||||
|
||||
1993 年,出现了几个 Linux 发行版,需要特别指出的有 [Debian][3]、[Red Hat][4] 和 [Slackware][5]。这个时刻之所以重要是因为它们证明了 Linux 在市场认可度和开发水平方面的成就,使其能够在 1990 年代动荡的操作系统战争、浏览器战争和协议战争中生存下来。相反,那时许多成熟的、商业的和专有的产品并没有活过千禧年之交!
|
||||
|
||||
### 3、IBM 斥巨资投注 Linux
|
||||
|
||||
2000 年,IBM 宣布将在 Linux 上投资 10 亿美元。Richard Richtmyer 在他的 CNN Money [有关投资的文章][6] 中写道:“这一声明强调了蓝色巨人对 Linux 的承诺,标志着将这个替代操作系统推向主流商业市场的重大进展。”
|
||||
|
||||
### 4、好莱坞接纳 Linux
|
||||
|
||||
在 2002 年,整个好莱坞电影业似乎都采用了 Linux。[迪尼斯][7]、[梦工厂][8] 和 [工业光魔][9] 都在那一年开始用 Linux 制作电影。
|
||||
|
||||
### 5、Linux 得到政府认可
|
||||
|
||||
2003 年,美国政府对 Linux 的接受是它的又一个重要时刻。红帽 Linux 被[授予][10]美国防部通用操作环境(COE)认证。这很重要,因为政府(特别是情报和军事机构)对计算机系统有非常严格的要求,以防止攻击和支持国家安全。这为其他机构使用 Linux 打开了大门。在那年晚些时候,[美国国家气象局宣布][11],它将用运行 Linux 的新计算机代替过时的系统。
|
||||
|
||||
### 6、我管理的系统
|
||||
|
||||
这个“时刻”确实是我个人经历的集合。随着在 2000 年代我的职业发展,我发现自己管理的几种类型的系统和设备都运行着 Linux。我在 VMware ESX、F5 Big-IP、Check Point UTM Edge、Cisco ASA 和 PIX 这些地方发现了 Linux。这使我意识到 Linux 确实可行并且可以继续存在下去。
|
||||
|
||||
### 7、Ubuntu
|
||||
|
||||
2004 年,Mark Shuttleworth 创立了 Canonical,该公司基于 Debian 发行版提供了易于使用的 Linux 桌面:[Ubuntu Linux][12]。我认为 Ubuntu Linux 帮助扩展了桌面 Linux 安装基数。从休闲的家庭用户到专业软件开发人员,它使 Linux 出现在更多人面前。
|
||||
|
||||
### 8、Google 的 Linux
|
||||
|
||||
Google 发行了两种基于 Linux 内核的操作系统:2008 年中期的 Android 移动操作系统和 2011 年在 Chromebook 上运行的 Chrome OS。在那之后,已经售出了数百万部 Android 手机和 Chromebook。
|
||||
|
||||
### 9、云计算即 Linux
|
||||
|
||||
在过去这十年左右的时间里,云计算已经从互联网计算的宏伟愿景变成了我们如何个人和专业地使用计算机的全新方式。云计算领域中的主要参与者都是构建于 Linux 之上的,包括 [Amazon Web Services(AWS)][13]、[Google Cloud Services(GCS)][14] 和 [Linode][15]。即使在一些我们不能确信的地方(例如 Microsoft Azure),也很好地支持运行 Linux 工作负载。
|
||||
|
||||
### 10、我的汽车运行着 Linux
|
||||
|
||||
你的也一样!许多汽车制造商几年前开始引入 Linux。这导致了名为 [汽车级 Linux(AGL)][16] 的协作开源项目的形成。丰田和斯巴鲁等主要汽车制造商已经联合开发基于 Linux 的汽车娱乐、导航和引擎管理系统。
|
||||
|
||||
### 分享你的最爱
|
||||
|
||||
这是我从贯穿我的职业生涯的 Linux 文章和事件的档案库中提取出来的主观清单,因此可能还有其他更值得注意的时刻。请分享你的评论吧。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/4/top-moments-linux-history
|
||||
|
||||
作者:[Alan Formy-Duval][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/alanfdoss
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_penguin_green.png?itok=ENdVzW22 (Penguin with green background)
|
||||
[2]: https://opensource.com/article/18/8/linux-history
|
||||
[3]: https://www.debian.org/doc/manuals/project-history/ch-intro.en.html
|
||||
[4]: https://brand.redhat.com/foundations/history
|
||||
[5]: https://opensource.com/article/18/7/stackware-turns-25
|
||||
[6]: https://money.cnn.com/2000/12/12/technology/ibm_linux
|
||||
[7]: https://www.nytimes.com/2002/06/18/business/technology-disney-shifting-to-linux-for-film-animation.html
|
||||
[8]: https://www.linux.com/news/stallion-and-penguin-dreamworks-uses-linux-create-new-animated-film
|
||||
[9]: https://www.linuxjournal.com/article/6011
|
||||
[10]: https://www.cnet.com/news/government-tips-hat-to-red-hat
|
||||
[11]: https://www.computerworld.com/article/2574142/national-weather-service-migrates-to-linux-based-ibm-workstations.html
|
||||
[12]: https://www.ubuntu.com/about
|
||||
[13]: https://aws.amazon.com/amazon-linux-2
|
||||
[14]: https://cloud.google.com
|
||||
[15]: https://www.linode.com/docs/getting-started
|
||||
[16]: https://www.automotivelinux.org
|
@ -0,0 +1,233 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (MjSeven)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12064-1.html)
|
||||
[#]: subject: (Run your blog on GitHub Pages with Python)
|
||||
[#]: via: (https://opensource.com/article/19/5/run-your-blog-github-pages-python)
|
||||
[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani)
|
||||
|
||||
使用 Python 在 GitHub 上运行你的博客
|
||||
======
|
||||
|
||||
> 使用 Pelican 创建博客,这是一个基于 Python 的平台,与 GitHub 配合的不错。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/02/101030cy0t0f0e0jvf5e5e.jpg)
|
||||
|
||||
[GitHub][2] 是一个非常流行的用于源代码控制的 Web 服务,它使用 [Git][3] 同步本地文件和 GitHub 服务器上保留的副本,这样你就可以轻松地共享和备份你的工作。
|
||||
|
||||
除了为代码仓库提供用户界面之外,GitHub 还运允许用户直接从仓库[发布网页][4]。GitHub 推荐的网站生成软件包是 [Jekll][5],是使用 Ruby 编写的。因为我是 [Python][6] 的忠实粉丝,所以我更喜欢 [Pelican][7],这是一个基于 Python 的博客平台,可与 GitHub 很好地协同工作。
|
||||
|
||||
Pelican 和 Jekll 都可以将 [Markdown][8] 或 [reStructuredText][9] 中编写的内容转换为 HTML 以生成静态网站,并且两个生成器都支持定制的主题。
|
||||
|
||||
在本文中,我将介绍如何安装 Pelican、设置 GitHub 仓库、运行快速入门帮助、编写一些 Markdown 文件以及发布第一篇博客。我假设你有一个 [GitHub 账户][10],熟悉[基础的 Git 命令][11],并且想使用 Pelican 发布博客。
|
||||
|
||||
### 安装 Pelican 并创建仓库
|
||||
|
||||
首先,你必须在本地计算机上安装 Pelican 和 `ghp-import`。使用 Python 软件包安装工具 [pip][12](你有,对吧?),这非常容易:
|
||||
|
||||
```
|
||||
$ pip install pelican ghp-import Markdown
|
||||
```
|
||||
|
||||
然后,打开浏览器并在 GitHub 上为你新鲜出炉的博客创建一个新仓库,命名如下(在此处以及整个教程中,用 GitHub 用户名替换 `username`):
|
||||
|
||||
```
|
||||
https://GitHub.com/username/username.github.io
|
||||
```
|
||||
|
||||
让它保持为空,稍后我们用引人注目的博客内容来填充它。
|
||||
|
||||
使用命令行(确保正确),将这个空 Git 仓库克隆到本地计算机:
|
||||
|
||||
```
|
||||
$ git clone <https://GitHub.com/username/username.github.io> blog
|
||||
$ cd blog
|
||||
```
|
||||
|
||||
### 奇怪的把戏...
|
||||
|
||||
在 GitHub 上发布 Web 内容有一个不太引入注意的技巧,对于托管在名为 `username.github.io` 的仓库的用户页面,其内容由 `master` 分支提供服务。
|
||||
|
||||
我强烈建议所有的 Pelican 配置文件和原始的 Markdown 文件都不要保留在 `master` 中,`master` 中只保留 Web 内容。因此,我将 Pelican 配置和原始内容保留在一个我喜欢称为 `content` 的单独分支中。(你可以随意创建一个分支,但以下内容沿用 `content`。)我喜欢这种结构,因为我可以放弃掉 `master` 中的所有文件,然后用 `content` 分支重新填充它。
|
||||
|
||||
```
|
||||
$ git checkout -b content
|
||||
Switched to a new branch 'content'
|
||||
```
|
||||
|
||||
### 配置 Pelican
|
||||
|
||||
现在该进行内容配置了。Pelican 提供了一个很棒的初始化工具 `pelican-quickstart`,它会询问你有关博客的一系列问题。
|
||||
|
||||
```
|
||||
$ pelican-quickstart
|
||||
Welcome to pelican-quickstart v3.7.1.
|
||||
|
||||
This script will help you create a new Pelican-based website.
|
||||
|
||||
Please answer the following questions so this script can generate the files
|
||||
needed by Pelican.
|
||||
|
||||
> Where do you want to create your new web site? [.]
|
||||
> What will be the title of this web site? Super blog
|
||||
> Who will be the author of this web site? username
|
||||
> What will be the default language of this web site? [en]
|
||||
> Do you want to specify a URL prefix? e.g., http://example.com (Y/n) n
|
||||
> Do you want to enable article pagination? (Y/n)
|
||||
> How many articles per page do you want? [10]
|
||||
> What is your time zone? [Europe/Paris] US/Central
|
||||
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) y
|
||||
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) y
|
||||
> Do you want to upload your website using FTP? (y/N) n
|
||||
> Do you want to upload your website using SSH? (y/N) n
|
||||
> Do you want to upload your website using Dropbox? (y/N) n
|
||||
> Do you want to upload your website using S3? (y/N) n
|
||||
> Do you want to upload your website using Rackspace Cloud Files? (y/N) n
|
||||
> Do you want to upload your website using GitHub Pages? (y/N) y
|
||||
> Is this your personal page (username.github.io)? (y/N) y
|
||||
Done. Your new project is available at /Users/username/blog
|
||||
```
|
||||
|
||||
你可以对每个问题都采用默认值,但除了以下这些问题:
|
||||
|
||||
* 网站标题,应该唯一且特殊
|
||||
* 网站作者,可以是个人用户名或你的全名
|
||||
* 时区,可能你不在巴黎
|
||||
* 上传到 GitHub 页面,我们选择 `y`
|
||||
|
||||
回答完所有问题后,Pelican 会在当前目录中留下以下内容:
|
||||
|
||||
```
|
||||
$ ls
|
||||
Makefile content/ develop_server.sh*
|
||||
fabfile.py output/ pelicanconf.py
|
||||
publishconf.py
|
||||
```
|
||||
|
||||
你可以查看 [Pelican 文档][13]来了解如何使用这些文件,但**现在**我们要做的是完成手头的工作。说实话,我也没有阅读文档。
|
||||
|
||||
### 继续
|
||||
|
||||
将所有 Pelican 生成的文件添加到本地 Git 仓库的 `content` 分支,提交更改,然后将本地更改推送到 Github 上托管的远程仓库:
|
||||
|
||||
```
|
||||
$ git add .
|
||||
$ git commit -m 'initial pelican commit to content'
|
||||
$ git push origin content
|
||||
```
|
||||
|
||||
这件事情并不是特别令人兴奋,但是如果我们需要撤销这些文件之一的修改时,这将非常方便。
|
||||
|
||||
### 终于
|
||||
|
||||
终于,现在你得到一个博客了!你所有的博客文章、照片、图像、PDF 等都将位于 `content` 目录中,它最初是空的。要开始创建第一篇博客和关于页面,输入:
|
||||
|
||||
```
|
||||
$ cd content
|
||||
$ mkdir pages images
|
||||
$ cp /Users/username/SecretStash/HotPhotoOfMe.jpg images
|
||||
$ touch first-post.md
|
||||
$ touch pages/about.md
|
||||
```
|
||||
|
||||
接下来,在你喜欢的文本编辑器中打开 `first-post.md`,并添加以下内容:
|
||||
|
||||
```
|
||||
title: First Post on My Sweet New Blog
|
||||
date: <today's date>
|
||||
author: Your Name Here
|
||||
|
||||
# I am On My Way To Internet Fame and Fortune!
|
||||
|
||||
This is my first post on my new blog. While not super informative it
|
||||
should convey my sense of excitement and eagerness to engage with you,
|
||||
the reader!
|
||||
```
|
||||
|
||||
前三行是 Pelican 用于组织内容的元数据。有很多不同的元数据可供你选择。再说一次,文档是你了解更多选项的最佳选择。
|
||||
|
||||
现在,打开空白文件 `pages/about.md` 并添加以下文本:
|
||||
|
||||
```
|
||||
title: About
|
||||
date: <today's date>
|
||||
|
||||
![So Schmexy][my_sweet_photo]
|
||||
|
||||
Hi, I am <username> and I wrote this epic collection of Interweb
|
||||
wisdom. In days of yore, much of this would have been deemed sorcery
|
||||
and I would probably have been burned at the stake.
|
||||
|
||||
😆
|
||||
|
||||
[my_sweet_photo]: {static}/images/HotPhotoOfMe.jpg
|
||||
```
|
||||
|
||||
现在,`content` 目录中将包含三个新的 Web 内容,在 `content` 分支中还有很多内容。
|
||||
|
||||
### 发布
|
||||
|
||||
不要急,马上要见到成果了!
|
||||
|
||||
剩下要做的就是:
|
||||
|
||||
* 运行 Pelican 以在 `output` 中生成静态 HTML 文件:
|
||||
|
||||
```
|
||||
$ pelican content -o output -s publishconf.py
|
||||
```
|
||||
* 使用 `ghp-import` 将 `output` 目录的内容添加到 `master` 分支中:
|
||||
|
||||
```
|
||||
$ ghp-import -m "Generate Pelican site" --no-jekyll -b master output
|
||||
```
|
||||
* 将本地 `master` 分支推送到远程仓库:
|
||||
|
||||
```
|
||||
$ git push origin master
|
||||
```
|
||||
* 提交新内容并将其推送到 `content` 分支
|
||||
|
||||
```
|
||||
$ git add content
|
||||
$ git commit -m 'added a first post, a photo and an about page'
|
||||
$ git push origin content
|
||||
```
|
||||
|
||||
### OMG,我成功了
|
||||
|
||||
现在最激动的时候到了,当你想要看到你发布给大家的博客内容时,打开浏览器输入:
|
||||
|
||||
```
|
||||
https://username.github.io
|
||||
```
|
||||
|
||||
恭喜你可以在 GitHub 上发布自己的博客了!当你想添加更多页面或文章时,都可以按照上面的步骤来。希望你可以愉快地发布博客。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/5/run-your-blog-github-pages-python
|
||||
|
||||
作者:[Erik O'Shaughnessy][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/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani
|
||||
[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 (Raspberry Pi and Python)
|
||||
[2]: https://github.com/
|
||||
[3]: https://git-scm.com
|
||||
[4]: https://help.github.com/en/categories/github-pages-basics
|
||||
[5]: https://jekyllrb.com
|
||||
[6]: https://python.org
|
||||
[7]: https://blog.getpelican.com
|
||||
[8]: https://guides.github.com/features/mastering-markdown
|
||||
[9]: http://docutils.sourceforge.net/docs/user/rst/quickref.html
|
||||
[10]: https://github.com/join?source=header-home
|
||||
[11]: https://git-scm.com/docs
|
||||
[12]: https://pip.pypa.io/en/stable/
|
||||
[13]: https://docs.getpelican.com
|
125
published/202004/20190605 What is GraphQL.md
Normal file
125
published/202004/20190605 What is GraphQL.md
Normal file
@ -0,0 +1,125 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12070-1.html)
|
||||
[#]: subject: (What is GraphQL?)
|
||||
[#]: via: (https://opensource.com/article/19/6/what-is-graphql)
|
||||
[#]: author: (Zach Lendon https://opensource.com/users/zachlendon)
|
||||
|
||||
什么是 GraphQL?
|
||||
======
|
||||
|
||||
> GraphQL 是一种查询语言、一个执行引擎,也是一种规范,它让开发人员重新思考如何构建客户端和 API 应用。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/04/112938odz6sbw6hzwsh7f6.jpg)
|
||||
|
||||
GraphQL 是当今软件技术中最大的流行语之一。但它*究竟*是什么?是像 [SQL][2] 一样的查询语言吗?是像 [JVM][3] 这样的执行引擎?还是像 [XML][4] 这样的规范?
|
||||
|
||||
如果你回答上面这些都是,那么你是对的![GraphQL][5] 是一种查询语言的语法、是一种编程语言无关的执行引擎,也是一种不断发展的规范。
|
||||
|
||||
让我们深入了解一下 GraphQL 如何成为所有这些东西的,并了解一下人们为什么对它感到兴奋。
|
||||
|
||||
### 查询语言
|
||||
|
||||
GraphQL 作为查询语言似乎是合理的 —— 毕竟 “QL” 似乎重要到出现在名称中。但是我们查询什么呢?看一个示例查询请求和相应的响应可能会有所帮助。
|
||||
|
||||
以下的用户查询:
|
||||
|
||||
```
|
||||
{
|
||||
user(id: 4) {
|
||||
name
|
||||
email
|
||||
phoneNumber
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可能会返回下面的 JSON 结果:
|
||||
|
||||
```
|
||||
{
|
||||
"user": {
|
||||
"name": "Zach Lendon"
|
||||
“email”: “zach@hydrate.io”
|
||||
“phoneNumber”: “867-5309”
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
想象一下,客户端应用查询用户详细信息、获取结果,并使用它填充配置屏幕。作为查询语言,GraphQL 的核心优势之一是客户端应用可以*只请求它需要*的数据,并期望以一致的方式返回这些数据。
|
||||
|
||||
那么 GraphQL 响应返回的*什么*呢?这就是执行引擎发挥的作用,通常是以 GraphQL 服务器的形式出现。
|
||||
|
||||
### 执行引擎
|
||||
|
||||
![GraphQL execution engine][7]
|
||||
|
||||
GraphQL 执行引擎负责处理 GraphQL 查询并返回 JSON 响应。所有 GraphQL 服务器由两个核心组件组成,分别定义了执行引擎的结构和行为:模式和解析器。
|
||||
|
||||
GraphQL 模式是一种自定义类型语言,它公开哪些查询既允许(有效),又由 GraphQL 服务器实现处理。上面用户示例查询的模式可能如下所示:
|
||||
|
||||
```
|
||||
type User {
|
||||
name: String
|
||||
email: String
|
||||
phoneNumber: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
user: User
|
||||
}
|
||||
```
|
||||
|
||||
此模式定义了一个返回用户的用户查询。客户端可以通过用户查询请求用户上的任何字段,并且 GraphQL 服务器将仅返回请求的字段。通过使用强类型模式,GraphQL 服务器可以根据定义的模式验证传入的查询,以确保是有效的。
|
||||
|
||||
确定查询有效后,就会由 GraphQL 服务器的解析器处理。解析器函数支持每个 GraphQL 类型的每个字段。我们的这个用户查询的示例解析器可能如下所示:
|
||||
|
||||
```
|
||||
Query: {
|
||||
user(obj, args, context, info) {
|
||||
return context.db.loadUserById(args.id).then(
|
||||
userData => new User(userData)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
虽然上面的例子是用 JavaScript 编写的,但 GraphQL 服务器可以用任意语言编写。这是因为 GraphQL 也是*也是*一种规范!
|
||||
|
||||
### 规范
|
||||
|
||||
GraphQL 规范定义了 GraphQL 实现必须遵循的功能和特性。作为一个在开放网络基金会的最终规范协议([OWFa 1.0][8])下提供的开放规范,技术社区可以审查 GraphQL 实现必须符合规范的要求,并帮助制定 GraphQL 的未来。
|
||||
|
||||
虽然该规范对 GraphQL 的语法,什么是有效查询以及模式的工作方式进行了非常具体的说明,但它没有提供有关如何存储数据或 GraphQL 服务器应使用哪种编程语言实现的指导。这在软件领域是非常强大的,也是相对独特的。它允许以各种编程语言创建 GraphQL 服务器,并且由于它们符合规范,因此客户端会确切知道它们的工作方式。GraphQL 服务器已经有多种语言实现,人们不仅可以期望像 JavaScript、Java和 C# 这样的语言,还可以使用 Go、Elixir 和 Haskell 等。服务器实现所使用的语言不会成为采用过程的障碍。它不仅存在多种语言实现,而且它们都是开源的。如果没有你选择的语言的实现,那么可以自己实现。
|
||||
|
||||
### 总结
|
||||
|
||||
GraphQL 是开源 API 领域中一个令人兴奋的、相对较新的参与者。它将查询语言、执行引擎与开源规范结合在一起,它定义了 GraphQL 实现的外观和功能。
|
||||
|
||||
GraphQL 已经开始改变企业对构建客户端和 API 应用的看法。通过将 GraphQL 作为技术栈的一部分,前端开发人员可以自由地查询所需的数据,而后端开发人员可以将客户端应用需求与后端系统架构分离。通常,公司在使用 GraphQL 的过程中,首先会在其现有的后端服务之上构建一个 GraphQL API “层”。这使得客户端应用开始获得他们所追求的性能和运营效率,同时使后端团队有机会确定他们可能需要在 GraphQL 层后面的“幕后”进行哪些更改。通常,这些更改都是为了优化,这些优化有助于确保使用 GraphQL 的应用可以尽可能高效地运行。由于 GraphQL 提供了抽象性,因此系统团队可以进行更改的同时继续在其 GraphQL API 级别上遵守 GraphQL 的“合约”。
|
||||
|
||||
由于 GraphQL 相对较新,因此开发人员仍在寻找新颖而激动人心的方法来利用它构建更好的软件解决方案。GraphQL 将如何改变你构建应用的方式,它是否对得起众望所归?只有一种方法可以找到答案 —— 用 GraphQL 构建一些东西!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/6/what-is-graphql
|
||||
|
||||
作者:[Zach Lendon][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/zachlendon
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/analytics-graphs-charts.png?itok=sersoqbV (Analytics: Charts and Graphs)
|
||||
[2]: https://opensource.com/article/18/2/getting-started-sql
|
||||
[3]: https://www.cubrid.org/blog/understanding-jvm-internals/
|
||||
[4]: https://www.w3.org/TR/xml/
|
||||
[5]: http://graphql.org/
|
||||
[6]: mailto:zach@hydrate.io
|
||||
[7]: https://opensource.com/sites/default/files/pictures/graphql-execution-engine.png (GraphQL execution engine)
|
||||
[8]: http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0---patent-only
|
262
published/202004/20190612 How to write a loop in Bash.md
Normal file
262
published/202004/20190612 How to write a loop in Bash.md
Normal file
@ -0,0 +1,262 @@
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "chunibyo-wly"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-12088-1.html"
|
||||
[#]: subject: "How to write a loop in Bash"
|
||||
[#]: via: "https://opensource.com/article/19/6/how-write-loop-bash"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
|
||||
如何在 Bash 中使用循环
|
||||
======
|
||||
|
||||
> 使用循环和查找命令批量自动对多个文件进行一系列的操作。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/08/225655by8i8k7uyppp18ph.jpg)
|
||||
|
||||
人们希望学习批处理命令的一个普遍原因是要得到批处理强大的功能。如果你希望批量的对文件执行一些指令,构造一个可以重复运行在那些文件上的命令就是一种方法。在编程术语中,这被称作*执行控制*,`for` 循环就是其中最常见的一种。
|
||||
|
||||
`for` 循环可以详细描述你希望计算机对你指定的每个数据对象(比如说文件)所进行的操作。
|
||||
|
||||
### 一般的循环
|
||||
|
||||
使用循环的一个简单例子是对一组文件进行分析。这个循环可能没什么用,但是这是一个安全的证明自己有能力独立处理文件夹里每一个文件的方法。首先,创建一个文件夹然后拷贝一些文件(例如 JPEG、PNG 等类似的文件)至文件夹中生成一个测试环境。你可以通过文件管理器或者终端来完成创建文件夹和拷贝文件的操作:
|
||||
|
||||
```bash
|
||||
$ mkdir example
|
||||
$ cp ~/Pictures/vacation/*.{png,jpg} example
|
||||
```
|
||||
|
||||
切换到你刚创建的那个新文件夹,然后列出文件并确认这个测试环境是你需要的:
|
||||
|
||||
```
|
||||
$ cd example
|
||||
$ ls -1
|
||||
cat.jpg
|
||||
design_maori.png
|
||||
otago.jpg
|
||||
waterfall.png
|
||||
```
|
||||
|
||||
在循环中逐一遍历文件的语法是:首先声明一个变量(例如使用 `f` 代表文件),然后定义一个你希望用变量循环的数据集。在这种情况下,使用 `*` 通配符来遍历当前文件夹下的所有文件(通配符 `*` 匹配*所有文件*)。然后使用一个分号(`;`)来结束这个语句。
|
||||
|
||||
```
|
||||
$ for f in * ;
|
||||
```
|
||||
|
||||
取决于你个人的喜好,你可以选择在这里按下回车键。在语法完成前,shell 是不会尝试执行这个循环的。
|
||||
|
||||
接下来,定义你想在每次循环中进行的操作。简单起见,使用 `file` 命令来得到 `f` 变量(使用 `$` 告诉 shell 使用这个变量的值,无论这个变量现在存储着什么)所存储着的文件的各种信息:
|
||||
|
||||
```
|
||||
do file $f ;
|
||||
```
|
||||
|
||||
使用另一个分号结束这一行,然后关闭这个循环:
|
||||
|
||||
```
|
||||
done
|
||||
```
|
||||
|
||||
按下回车键启动 shell 对当前文件夹下*所有东西*的遍历。`for` 循环将会一个一个的将文件分配给变量 `f` 并且执行你的命令:
|
||||
|
||||
```
|
||||
$ for f in * ; do
|
||||
> file $f ;
|
||||
> done
|
||||
cat.jpg: JPEG image data, EXIF standard 2.2
|
||||
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
otago.jpg: JPEG image data, EXIF standard 2.2
|
||||
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
```
|
||||
|
||||
你也可以用这种形式书写命令:
|
||||
|
||||
```
|
||||
$ for f in *; do file $f; done
|
||||
cat.jpg: JPEG image data, EXIF standard 2.2
|
||||
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
otago.jpg: JPEG image data, EXIF standard 2.2
|
||||
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
```
|
||||
|
||||
对你的 shell 来说,多行和单行的格式没有什么区别,并且会输出完全一样的结果。
|
||||
|
||||
### 一个实用的例子
|
||||
|
||||
下面是一个循环在日常使用中的实用案例。假如你拥有一堆假期拍的照片想要发给你的朋友。但你的照片太大了,无法通过电子邮件发送,上传到[图片分享服务][2]也不方便。因此你想为你的照片创建小型的 web 版本,但是你不希望花费太多时间在一个一个的压缩图片体积上。
|
||||
|
||||
首先,在你的 Linux、BSD 或者 Mac 上使用包管理器安装 ImageMagick 命令。例如,在 Fedora 和 RHEL 上:
|
||||
|
||||
```
|
||||
$ sudo dnf install ImageMagick
|
||||
```
|
||||
|
||||
在 Ubuntu 和 Debian 上:
|
||||
|
||||
```
|
||||
$ sudo apt install ImageMagick
|
||||
```
|
||||
|
||||
在 BSD 上,使用 `ports` 或者 [pkgsrc][3] 安装。在 Mac 上,使用 [Homebrew][4] 或者 [MacPorts][5] 安装。
|
||||
|
||||
在你安装了 ImageMagick 之后,你就拥有一系列可以用来操作图片的新命令了。
|
||||
|
||||
为你将要创建的文件建立一个目标文件夹:
|
||||
|
||||
```
|
||||
$ mkdir tmp
|
||||
```
|
||||
|
||||
使用下面的循环可以将每张图片减小至原来大小的 33%。
|
||||
|
||||
```
|
||||
$ for f in * ; do convert $f -scale 33% tmp/$f ; done
|
||||
```
|
||||
|
||||
然后就可以在 `tmp` 文件夹中看到已经缩小了的照片了。
|
||||
|
||||
你可以在循环体中使用任意数量的命令,因此如果你需要对一批文件进行复杂的操作,可以将你的命令放在一个 `for` 循环的 `do` 和 `done` 语句之间。例如,假设你希望将所有处理过的图片拷贝至你的网站所托管的图片文件夹并且在本地系统移除这些文件:
|
||||
|
||||
```
|
||||
$ for f in * ; do
|
||||
convert $f -scale 33% tmp/$f
|
||||
scp -i seth_web tmp/$f seth@example.com:~/public_html
|
||||
trash tmp/$f ;
|
||||
done
|
||||
```
|
||||
|
||||
你的计算机会对 `for` 循环中处理的每一个文件自动的执行 3 条命令。这意味着假如你仅仅处理 10 张图片,也会省下输入 30 条指令和更多的时间。
|
||||
|
||||
### 限制你的循环
|
||||
|
||||
一个循环常常不需要处理所有文件。在示例文件夹中,你可能需要处理的只是 JPEG 文件:
|
||||
|
||||
```
|
||||
$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done
|
||||
$ ls -m tmp
|
||||
cat.jpg, otago.jpg
|
||||
```
|
||||
|
||||
或者,你希望重复特定次数的某个操作而不仅仅只处理文件。`for` 循环的变量的值是被你赋给它的(不管何种类型的)数据所决定的,所以你可以创建一个循环遍历数字而不只是文件:
|
||||
|
||||
```
|
||||
$ for n in {0..4}; do echo $n ; done
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
```
|
||||
|
||||
### 更多循环
|
||||
|
||||
现在你了解的知识已经足够用来创建自己的循环体了。直到你对循环非常熟悉之前,尽可能的在需要处理的文件的*副本*上进行操作。使用内置的保护措施可以预防损坏自己的数据和制造不可复现的错误,例如偶然将一个文件夹下的所有文件重命名为同一个名字,就可能会导致他们的相互覆盖。
|
||||
|
||||
更进一步的 `for` 循环话题,请继续阅读。
|
||||
|
||||
### 不是所有的 shell 都是 Bash
|
||||
|
||||
关键字 `for` 是内置在 Bash shell 中的。许多类似的 shell 会使用和 Bash 同样的关键字和语法,但是也有某些 shell ,比如 [tcsh][7],使用不同的关键字,例如 `foreach`。
|
||||
|
||||
tcsh 的语法与 Bash 类似,但是它更为严格。例如在下面的例子中,不要在你的终端的第 2、3 行键入 `foreach?` 。它只是提示你仍处在构建循环的过程中。
|
||||
|
||||
```
|
||||
$ foreach f (*)
|
||||
foreach? file $f
|
||||
foreach? end
|
||||
cat.jpg: JPEG image data, EXIF standard 2.2
|
||||
design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
otago.jpg: JPEG image data, EXIF standard 2.2
|
||||
waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
|
||||
```
|
||||
|
||||
在 tcsh 中,`foreach` 和 `end` 都必须单独的在一行中出现。因此你不能像 Bash 或者其他类似的 shell 一样只使用一行命令创建一个 `for` 循环。
|
||||
|
||||
### for 循环与 find 命令
|
||||
|
||||
理论上,你可能会用到不支持 `for` 循环的 shell,或者你只是更想使用其他命令的一些特性来完成和循环一样的工作。
|
||||
|
||||
使用 `find` 命令是另一个实现 `for` 循环功能的途径。这个命令提供了多种方法来定义循环中包含哪些文件的范围以及[并行][8]处理的选项。
|
||||
|
||||
`find` 命令顾名思义就是帮助你查询存储在硬盘里的文件。它的用法很简单:提供一个你希望它查询的位置的路径,接着 `find` 就会查询这个路径下面的所有文件和文件夹。
|
||||
|
||||
```
|
||||
$ find .
|
||||
.
|
||||
./cat.jpg
|
||||
./design_maori.png
|
||||
./otago.jpg
|
||||
./waterfall.png
|
||||
```
|
||||
|
||||
你可以通过添加名称的某些部分来过滤搜索结果:
|
||||
|
||||
```
|
||||
$ find . -name "*jpg"
|
||||
./cat.jpg
|
||||
./otago.jpg
|
||||
```
|
||||
|
||||
`find` 命令非常好的地方在于你可以通过 `-exec` 参数标志将它查询到的每一个文件放入循环中。例如,只对存放在你的 `example` 文件夹下的 PNG 图片进行体积压缩操作:
|
||||
|
||||
```
|
||||
$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
|
||||
$ ls -m tmp
|
||||
design_maori.png, waterfall.png
|
||||
```
|
||||
|
||||
在 `-exec` 短语中,括号 `{}` 表示的是 `find` 正在处理的条目(换句话说,每一个被找到的以 PNG 结尾的文件)。`-exec` 短语必须使用分号结尾,但是 Bash 中常常也会使用分号。为了解决这个二义性问题,你的 `结束符` 可以使用反斜杠加上一个分号(`\;`),使得 `find` 命令可以知道这个结束符是用来标识自己结束使用的。
|
||||
|
||||
`find` 命令的操作非常棒,某些情况下它甚至可以表现得更棒。比如说,在一个新的进程中使用同一条命令查找 PNG 文件,你可能就会得到一些错误信息:
|
||||
|
||||
```
|
||||
$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;
|
||||
convert: unable to open image `tmp/./tmp/design_maori.png':
|
||||
No such file or directory @ error/blob.c/OpenBlob/2643.
|
||||
...
|
||||
```
|
||||
|
||||
看起来 `find` 不只是定位了当前文件夹(`.`)下的所有 PNG 文件,还包括已经处理并且存储到了 `tmp` 下的文件。在一些情况下,你可能希望 `find` 查询当前文件夹下再加上其子文件夹下的所有文件。`find` 命令是一个功能强大的递归工具,特别体现在处理一些文件结构复杂的情境下(比如用来放置存满了音乐人音乐专辑的文件夹),同时你也可以使用 `-maxdepth` 选项来限制最大的递归深度。
|
||||
|
||||
只在当前文件夹下查找 PNG 文件(不包括子文件夹):
|
||||
|
||||
```
|
||||
$ find . -maxdepth 1 -name "*png"
|
||||
```
|
||||
|
||||
上一条命令的最大深度再加 1 就可以查找和处理当前文件夹及下一级子文件夹下面的文件:
|
||||
|
||||
```
|
||||
$ find . -maxdepth 2 -name "*png"
|
||||
```
|
||||
|
||||
`find` 命令默认是查找每一级文件夹。
|
||||
|
||||
### 循环的乐趣与收益
|
||||
|
||||
你使用的循环越多,你就可以越多的省下时间和力气,并且可以应对庞大的任务。虽然你只是一个用户,但是通过使用循环,可以使你的计算机完成困难的任务。
|
||||
|
||||
你可以并且应该就像使用其他的命令一样使用循环。在你需要重复处理单个或多个文件时,尽可能的使用这个命令。无论如何,这也算是一项需要被严肃对待的编程活动,因此如果你需要在一些文件上完成复杂的任务,你应该多花点时间在规划自己的工作流上面。如果你可以在一份文件上完成你的工作,接下来将操作包装进 `for` 循环里就相对简单了,这里面唯一的“编程”的需要只是理解变量是如何工作的并且进行充分的规划工作将已处理过的文件和未处理过的文件分开。经过一段时间的练习,你就可以从一名 Linux 用户升级成一位知道如何使用循环的 Linux 用户,所以开始让计算机为你工作吧!
|
||||
|
||||
---
|
||||
|
||||
via: https://opensource.com/article/19/6/how-write-loop-bash
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[chunibyo-wly](https://github.com/chunibyo-wly)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux 中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth/users/goncasousa/users/howtopamm/users/howtopamm/users/seth/users/wavesailor/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U "bash logo on green background"
|
||||
[2]: http://nextcloud.com
|
||||
[3]: http://pkgsrc.org
|
||||
[4]: http://brew.sh
|
||||
[5]: https://www.macports.org
|
||||
[6]: mailto:seth@example.com
|
||||
[7]: https://en.wikipedia.org/wiki/Tcsh
|
||||
[8]: https://opensource.com/article/18/5/gnu-parallel
|
91
published/202004/20190612 Why use GraphQL.md
Normal file
91
published/202004/20190612 Why use GraphQL.md
Normal file
@ -0,0 +1,91 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12075-1.html)
|
||||
[#]: subject: (Why use GraphQL?)
|
||||
[#]: via: (https://opensource.com/article/19/6/why-use-graphql)
|
||||
[#]: author: (Zach Lendon https://opensource.com/users/zachlendon/users/goncasousa/users/patrickhousley)
|
||||
|
||||
为什么使用 GraphQL?
|
||||
======
|
||||
|
||||
> 以下是 GraphQL 在标准 REST API 技术上获得发展的原因。
|
||||
|
||||
[](https://img.linux.net.cn/data/attachment/album/202004/05/105820rdnjrppprjdjddfd.jpg)
|
||||
|
||||
正如我[以前][3]所写,[GraphQL][2] 是一种下一代 API 技术,它正在改变客户端应用程序与后端系统的通信方式以及后端系统的设计方式。
|
||||
|
||||
由于一开始就从创建它的组织 Facebook 获得了支持,并得到了其他技术巨头(如 Github、Twitter 和 AirBnB)的支持,因此 GraphQL 作为应用程序系统的关键技术的地位似乎是稳固的 —— 无论现在还是将来。
|
||||
|
||||
### GraphQL 的崛起
|
||||
|
||||
移动应用程序性能和组织敏捷性重要性的提高为 GraphQL 登上现代企业体系结构的顶端提供了助推器。
|
||||
|
||||
鉴于 [REST][4] 是一种非常流行的体系结构风格,早已提供了数据交互机制,与 [REST][4] 相比,GraphQL 这项新技术具有哪些优势呢?GraphQL 中的 “QL” 代表着查询语言,而这是一个很好的起点。
|
||||
|
||||
借助 GraphQL,组织内的不同客户端应用程序可以轻松地仅查询所需数据,这一点超越了其它 REST 方法,并带来了实际应用程序性能的提高。使用传统的 [REST][4] API 端点,客户端应用程序将详询服务器资源,并接受包含了与请求匹配的所有数据的响应。如果来自 [REST][4] API 端点的成功响应返回 35 个字段,那么客户端应用程序就会收到 35 个字段。
|
||||
|
||||
### 获取的问题
|
||||
|
||||
传统上,[REST][4] API 没有为客户端应用程序提供简便的方法来仅检索或只更新它们关心的数据。这通常被描述为“<ruby>过度获取<rt>over-fetching</rt></ruby>”的问题。随着移动应用程序在人们的日常生活中的普遍使用,过度获取问题会给现实世界带来不良后果。移动应用程序发出的每个请求、每一个字节的接受和发送,对终端用户的性能影响越来越大。数据连接速度较慢的用户尤其会受到不太好的 API 设计方案的影响。使用移动应用程序而性能体验不佳的客户更有可能不购买产品或不使用服务。低效的 API 设计只会浪费企业的钱。
|
||||
|
||||
并非只有“过度获取”是问题,“欠缺获取”同样也是问题。默认情况下,端点只返回客户端实际需要的部分数据,这需要客户端进行额外的调用以满足其数据需求,这就产生了额外的 HTTP 请求。由于过度和欠缺的获取问题及其对客户端应用程序性能的影响,促进有效获取的 API 技术才有机会在市场上引起轰动 —— GraphQL 大胆地介入并填补了这一空白。
|
||||
|
||||
### REST 的应对
|
||||
|
||||
[REST][4] API 设计师不甘心不战而退,他们试图通过以下几种方式来应对移动应用程序性能问题:
|
||||
|
||||
* “包含”和“排除”查询参数,允许客户端应用程序通过可能较长的查询格式来指定所需的字段。
|
||||
* “复合”服务,将多个端点组合在一起,以使客户端应用程序在其发出的请求数量和接收到的数据方面更高效。
|
||||
|
||||
尽管这些模式是 [REST][4] API 社区为解决移动客户端所面临的挑战而做出的英勇尝试,但它们在以下几个关键方面仍存在不足:
|
||||
|
||||
* 包含和排除查询键/值对很快就会变得混乱,特别是对于需要用嵌套“点表示法”语法(或类似方法)以对目标数据进行包含和排除的深层对象图而言,更是如此。此外,在此模型中调试查询字符串的问题通常需要手动分解 URL。
|
||||
* 包含和排除查询的服务器的实现往往是自定义的,因为基于服务器的应用程序没有标准的方式来处理包含和排除查询的使用,就像没有定义包含和排除查询的标准方式一样。
|
||||
* 复合服务的兴起形成了更加紧密耦合的后端和前端系统,这就需要加强协调以交付项目,并且将曾经的敏捷项目转回瀑布式开发。这种协调和耦合还有一个痛苦的副作用,那就是减宦了组织的敏捷性。此外,顾名思义,组合服务不是 RESTful。
|
||||
|
||||
### GraphQL 的起源
|
||||
|
||||
对于 Facebook 来说,从其 2011-2012 年基于 HTML5 版本的旗舰移动应用程序中感受到的痛点和体验,才造就了 GraphQL。Facebook 工程师意识到提高性能至关重要,因此意识到他们需要一种新的 API 设计来确保最佳性能。可能考虑到上述 [REST][4] 的局限性,并且需要支持许多 API 客户端的不同需求,因此人们可以理解是什么导致其共同创建者 Lee Byron 和 Dan Schaeffer(那时尚是 Facebook 员工)创建了后来被称之为 GraphQL 的技术的早期种子。
|
||||
|
||||
通过 GraphQL 查询语言,客户端(通常是单个 GraphQL 端点)应用程序通常可以显著减少所需的网络调用数量,并确保仅检索所需的数据。在许多方面,这可以追溯到早期的 Web 编程模型,在该模型中,客户端应用程序代码会直接查询后端系统 —— 比如说,有些人可能还记得 10 到 15 年前在 JSP 上用 JSTL 编写 SQL 查询的情形吧!
|
||||
|
||||
现在最大的区别是使用 GraphQL,我们有了一个跨多种客户端和服务器语言和库实现的规范。借助 GraphQL 这样一种 API 技术,我们通过引入 GraphQL 应用程序中间层来解耦后端和前端应用程序系统,该层提供了一种机制,以与组织的业务领域相一致的方式来访问组织数据。
|
||||
|
||||
除了解决软件工程团队遇到的技术挑战之外,GraphQL 还促进了组织敏捷性的提高,特别是在企业中。启用 GraphQL 的组织敏捷性通常归因于以下因素:
|
||||
|
||||
* GraphQL API 设计人员和开发人员无需在客户端需要一个或多个新字段时创建新的端点,而是能够将这些字段包含在现有的图实现中,从而以较少的开发工作量和跨应用程序系统的较少更改的方式展示出新功能。
|
||||
* 通过鼓励 API 设计团队将更多的精力放在定义对象图上,而不是在专注于客户端应用程序交付上,前端和后端软件团队为客户交付解决方案的速度日益解耦。
|
||||
|
||||
### 采纳之前的注意事项
|
||||
|
||||
尽管 GraphQL 具有引人注目的优势,但 GraphQL 并非没有实施挑战。一些例子包括:
|
||||
|
||||
* 为 [REST][4] API 建立的缓存机制更加成熟。
|
||||
* 使用 [REST][4] 来构建 API 的模式更加完善。
|
||||
* 尽管工程师可能更喜欢 GraphQL 等新技术,但与 GraphQL 相比,市场上的人才库更多是从事于构建基于 [REST][4] 的解决方案。
|
||||
|
||||
### 结论
|
||||
|
||||
通过同时提高性能和组织敏捷性,GraphQL 在过去几年中被企业采纳的数量激增。但是,与 API 设计的 RESTful 生态系统相比,它确实还需要更成熟一些。
|
||||
|
||||
GraphQL 的一大优点是,它并不是作为替代 API 解决方案的批发替代品而设计的。相反,GraphQL 可以用来补充或增强现有的 API。因此,鼓励企业探索在 GraphQL 对其最有意义的地方逐步采用 GraphQL —— 在他们发现它对应用程序性能和组织敏捷性具有最大的积极影响的地方。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/6/why-use-graphql
|
||||
|
||||
作者:[Zach Lendon][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/zachlendon/users/goncasousa/users/patrickhousley
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_graph_stats_blue.png?itok=OKCc_60D
|
||||
[2]: https://graphql.org/
|
||||
[3]: https://linux.cn/article-12070-1.html
|
||||
[4]: https://en.wikipedia.org/wiki/Representational_state_transfer
|
98
published/202004/20190712 What is Silverblue.md
Normal file
98
published/202004/20190712 What is Silverblue.md
Normal file
@ -0,0 +1,98 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12153-1.html)
|
||||
[#]: subject: (What is Silverblue?)
|
||||
[#]: via: (https://fedoramagazine.org/what-is-silverblue/)
|
||||
[#]: author: (Tomáš Popela https://fedoramagazine.org/author/tpopela/)
|
||||
|
||||
Silverblue 是什么?
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Fedora Silverblue 在 Fedora 世界内外越来越受欢迎。因此,根据社区的反馈,以下是关于这个项目的一些有趣问题的答案。如果你有任何其他与 Silverblue 相关的问题,请在评论区留言,我们会在未来的文章中回答。
|
||||
|
||||
### Silverblue 是什么?
|
||||
|
||||
Silverblue 是新一代桌面操作系统的代号,之前被称为 Atomic Workstation。该操作系统是通过利用 [rpm-ostree 项目][2]创建的映像来交付的。这种系统的主要优点是速度、安全性、原子更新和不变性。
|
||||
|
||||
### “Silverblue” 到底是什么意思?
|
||||
|
||||
“Team Silverblue” 或简称 “Silverblue”,没有任何隐藏的含义。该项目以前被称为 Atomic Workstation,大约两个月后更名时选中了这个名字。在这个过程中,审查过 150 多个单词或单词组合。最终选择了 “Silverblue”,因为它有一个可用的域名以及社交网络账号。人们可以把它看成是 Fedora 的蓝色品牌的一个新的品牌形象,可以用在诸如“加油,Silverblue 团队!”或“想加入该团队,改进 Silverblue 吗?”这样的短语中。
|
||||
|
||||
### 何谓 ostree?
|
||||
|
||||
[OSTree(或 libostree)是一个项目][3],它结合了一个类似 Git 的提交和下载可引导文件系统树的模型,以及用于部署它们和管理引导加载程序配置的层。OSTree 由 rpm-ostree 使用,这是 Silverblue 使用的一个基于包/镜像的混合系统。它原子化地复制了一个基础操作系统,并允许用户在需要时在基础操作系统之上“层叠”传统的 RPM。
|
||||
|
||||
### 为何使用 Silverblue?
|
||||
|
||||
因为它可以让你专注于你的工作,而不是你正在运行的操作系统。因为系统的更新是原子式的,所以它更稳健。你唯一需要做的事情就是重新启动到新的镜像中。此外,如果当前启动的镜像有什么问题,你可以很容易地重启/回滚到之前可以工作的镜像,如果有的话。如果没有,你可以使用 `ostree` 命令下载并启动过去生成的任何其他镜像。
|
||||
|
||||
另一个好处是可以在不同的分支(或者用旧的语境说就是不同的 Fedora 风味版本)之间轻松切换。你可以轻松地尝试 [Rawhide][4] 或 [updates-testing][5] 分支,然后返回到包含当前稳定版本的分支。另外,如果你想尝试一些新奇的东西,也可以考虑试试 Silverblue。
|
||||
|
||||
### 不可变的操作系统有什么好处?
|
||||
|
||||
其中一个主要的好处是安全。基础操作系统是以只读的形式挂载的,因此不能被恶意软件修改。唯一可以改变系统的方法是通过 `rpm-ostree` 实用程序。
|
||||
|
||||
另一个好处是健壮性。普通用户几乎不可能在不小心或无意中删除了一些系统库后,导致操作系统回到不启动或无法正常工作的状态。试着想想你过去的这些经历,就可以明白 Silverblue 可以如何帮助你。
|
||||
|
||||
### 如何在 Silverblue 中管理应用程序和包?
|
||||
|
||||
对于图形化用户界面的应用程序,建议使用 [Flatpak][6] —— 如果应用程序是以 Flatpak 的形式提供的话。用户可以选择来自 Fedora 的 Flatpak,和从 Fedora 包及 Fedora 自己的基础架构中构建的 Flatpak,或者是目前有更广泛的交付品的 Flathub。用户可以通过已经支持 Fedora Silverblue 的 GNOME “软件”轻松安装它们。
|
||||
|
||||
用户首先发现的一件事就是操作系统中没有预装 `dnf`。主要原因是它不能在 Silverblue 上工作 —— 它的部分功能被 `rpm-ostree` 命令所取代。用户可以通过使用 `rpm-ostree install PACKAGE` 来层叠传统的软件包。但只有在没有其他方法的情况下,才应该使用这种方式。这是因为从存储库中提取新的系统镜像时,每次更改系统镜像时都必须重新构建系统镜像,以容纳层叠的包或从基础操作系统中删除及替换为其他版本的包。
|
||||
|
||||
Fedora Silverblue 自带的默认 GUI 应用程序集是基础操作系统的一部分。团队正在努力将它们移植到 Flatpak 上,这样它们就可以通过这种方式分发。其中一个好处是,基础操作系统将变得更小,更容易维护和测试,用户可以更容易修改他们的默认安装环境。如果你想看一下它是怎么做的,或者有什么帮助,可以看看官方的[文档][7]。
|
||||
|
||||
### 什么是 Toolbox?
|
||||
|
||||
[Toolbox][8] 是一个让普通用户可以轻松使用容器的项目。它通过使用 podman 的无 root 容器环境来实现。Toolbox 可以让你在常规的 Fedora 环境中轻松、快速地创建一个容器,你可以在这个容器上折腾或开发,而与你的操作系统分离。
|
||||
|
||||
### Silverblue 有路线图吗?
|
||||
|
||||
形式上没有,因为我们正在关注在测试过程中发现的问题和社区的反馈。我们目前正在使用 Fedora 的 [Taiga][9] 来进行规划。
|
||||
|
||||
### Silverblue 的发布周期是多少?
|
||||
|
||||
它和普通的 Fedora Workstation 是一样的。每 6 个月发布一次新版本,支持期为 13 个月。团队计划每两周(或更长时间)发布一次更新,而不是像现在这样每天发布一次。这样一来,更新可以在发送给其他用户之前,由 QA 和社区志愿者进行更彻底的测试。
|
||||
|
||||
### 不可变操作系统的未来前景如何?
|
||||
|
||||
从我们的角度来看,桌面的未来会走向到不可变的操作系统。这对用户来说是最安全的,Android、ChromeOS、ChromeOS、最近的 macOS Catalina 全都在底层采用了这种方式。而对于 Linux 桌面来说,一些第三方软件期望写到操作系统的问题还是存在的。HP 打印机驱动程序就是一个很好的例子。
|
||||
|
||||
另一个问题是系统中的部分软件如何分发和安装。字体就是一个很好的例子。目前在 Fedora 中,它们是以 RPM 包的形式分发的。如果你想使用它们,你必须层叠它们,然后重新启动到新创建的包含它们的镜像中。
|
||||
|
||||
### 标准版 Workstation 的前景如何?
|
||||
|
||||
Silverblue 有可能会取代普通的 Workstation 版本。但 Silverblue 要提供与 Workstation 版本相同的功能和用户体验还有很长的路要走。在此期间,这两款桌面产品将同时推出。
|
||||
|
||||
### Atomic Workstation 或 Fedora CoreOS 与这些有什么关系?
|
||||
|
||||
Atomic Workstation 是在更名为 Fedora Silverblue 之前的项目名称。
|
||||
|
||||
Fedora CoreOS 是一个不同但相似的项目。它与 Silverblue 共享一些基本技术,如 `rpm-ostree`、`toolbox` 等。尽管如此,CoreOS 是一个更简约、专注于容器、自动更新的操作系统。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/what-is-silverblue/
|
||||
|
||||
作者:[Tomáš Popela][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/tpopela/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2019/07/what-is-fedora-silverblue-816x345.jpg
|
||||
[2]: https://rpm-ostree.readthedocs.io/en/latest/
|
||||
[3]: https://ostree.readthedocs.io/en/latest/
|
||||
[4]: https://fedoraproject.org/wiki/Releases/Rawhide
|
||||
[5]: https://fedoraproject.org/wiki/QA:Updates_Testing
|
||||
[6]: https://flatpak.org/
|
||||
[7]: https://docs.fedoraproject.org/en-US/flatpak/tutorial/
|
||||
[8]: https://github.com/debarshiray/toolbox
|
||||
[9]: https://teams.fedoraproject.org/project/silverblue/
|
@ -0,0 +1,251 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (messon007)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12135-1.html)
|
||||
[#]: subject: (9 open source cloud native projects to consider)
|
||||
[#]: via: (https://opensource.com/article/19/8/cloud-native-projects)
|
||||
[#]: author: (Bryant Son https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo)
|
||||
|
||||
值得关注的 9 个开源云原生项目
|
||||
======
|
||||
|
||||
> 工作中用了容器?熟悉这些出自云原生计算基金会的项目吗?
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/21/222735oa1wib1wgypoiwpp.jpg)
|
||||
|
||||
随着用容器来开发应用的实践变得流行,[云原生应用][2]也在增长。云原生应用的定义为:
|
||||
|
||||
> “云原生技术用于开发使用打包在容器中的服务所构建的应用程序,以微服务的形式部署,并通过敏捷的 DevOps 流程和持续交付工作流在弹性基础设施上进行管理。”
|
||||
|
||||
这个定义提到了构成云原生应用的不可或缺的四个元素:
|
||||
|
||||
1. 容器
|
||||
2. 微服务
|
||||
3. DevOps
|
||||
4. 持续集成和持续交付 (CI/CD)
|
||||
|
||||
尽管这些技术各有各自独特的历史,但它们之间却相辅相成,在短时间内实现了云原生应用和工具的惊人的指数级增长。这个[云原生计算基金会(CNCF)][4]信息图呈现了当今云原生应用生态的规模和广度。
|
||||
|
||||
![Cloud-Native Computing Foundation applications ecosystem][5]
|
||||
|
||||
*云原生计算基金会项目*
|
||||
|
||||
我想说,瞧着吧!这仅仅是一个开始。正如 NodeJS 的出现引发了无数的 JavaScript 工具的爆炸式增长一样,容器技术的普及也推动了云原生应用的指数增长。
|
||||
|
||||
好消息是,有几个组织负责监管并将这些技术连接在一起。 其中之一是 <ruby>[开放容器倡议][6]<rt>Open Containers Initiative</rt></ruby>(OCI),它是一个轻量级的、开放的治理机构(或项目),“它是在 Linux 基金会的支持下形成的,其明确目的是创建开放的行业标准的容器格式和运行时。” 另一个是 CNCF,它是“一个致力于使云原生计算普及和可持续发展的开源软件基金会”。
|
||||
|
||||
通常除了围绕云原生应用建立社区之外,CNCF 还帮助项目围绕其云原生应用建立结构化管理。CNCF 创建了成熟等级的概念(沙箱级、孵化级或毕业级),分别与下图中的“创新者”、“早期采用者”和“早期大量应用”相对应。
|
||||
|
||||
![CNCF project maturity levels][7]
|
||||
|
||||
*CNCF 项目成熟等级*
|
||||
|
||||
CNCF 为每个成熟等级制定了详细的[标准][8](为方便读者而列在下面)。获得技术监督委员会(TOC)三分之二的同意才能转为孵化或毕业级。
|
||||
|
||||
**沙箱级**
|
||||
|
||||
> 要想成为沙箱级,一个项目必须至少有两个 TOC 赞助商。 有关详细过程,请参见《CNCF 沙箱指南 v1.0》。
|
||||
|
||||
**孵化级**
|
||||
|
||||
> 注:孵化级是我们期望对项目进行全面的尽职调查的起点。
|
||||
>
|
||||
> 要进入孵化级,项目除了满足沙箱级的要求之外还要满足:
|
||||
>
|
||||
> * 证明至少有三个独立的最终用户已成功将其用于生产,且 TOC 判断这些最终用户具有足够的质量和范围。
|
||||
> * 提交者的数量要合理。提交者定义为具有提交权的人,即可以接受部分或全部项目贡献的人。
|
||||
> * 显示出有大量持续提交和合并贡献。
|
||||
> * 由于这些指标可能会根据项目的类型、范围和大小而有很大差异,所以 TOC 有权决定是否满足这些标准的活动水平。
|
||||
|
||||
**毕业级**
|
||||
|
||||
> 要从沙箱或孵化级毕业,或者要使一个新项目作为已毕业项目加入,项目除了必须满足孵化级的标准外还要满足:
|
||||
>
|
||||
> * 至少有两个来自组织的提交者。
|
||||
> * 已获得并保持了“核心基础设施计划最佳实践徽章”。
|
||||
> * 已完成独立的第三方安全审核,并发布了具有与以下示例类似的范围和质量的结果(包括已解决的关键漏洞):<https://github.com/envoyproxy/envoy#security-audit>,并在毕业之前需要解决所有关键的漏洞。
|
||||
> * 采用《CNCF 行为准则》。
|
||||
> * 明确规定项目治理和提交流程。最好将其列在 `GOVERNANCE.md` 文件中,并引用显示当前提交者和荣誉提交者的 `OWNERS.md` 文件。
|
||||
> * 至少有一个主仓的项目采用者的公开列表(例如,`ADOPTERS.md` 或项目网站上的徽标)。
|
||||
> * 获得 TOC 的绝大多数票,进入毕业阶段。如果项目能够表现出足够的成熟度,则可以尝试直接从沙箱级过渡到毕业级。项目可以无限期保持孵化状态,但是通常预计它们会在两年内毕业。
|
||||
|
||||
### 值得关注的 9 个项目
|
||||
|
||||
本文不可能涵盖所有的 CNCF 项目,我将介绍最有趣的 9 个毕业和孵化的开源项目。
|
||||
|
||||
名称|授权类型|简要描述
|
||||
---|---|---
|
||||
[Kubernetes][9] | Apache 2.0 | 容器编排平台
|
||||
[Prometheus][10] | Apache 2.0 | 系统和服务监控工具
|
||||
[Envoy][11] | Apache 2.0 | 边缘和服务代理
|
||||
[rkt][12] | Apache 2.0 | Pod 原生的容器引擎
|
||||
[Jaeger][13] | Apache 2.0 | 分布式跟踪系统
|
||||
[Linkerd][14] | Apache 2.0 | 透明服务网格
|
||||
[Helm][15] | Apache 2.0 | Kubernetes 包管理器
|
||||
[Etcd][16] | Apache 2.0 | 分布式键值存储
|
||||
[CRI-O][17] | Apache 2.0 | 专门用于 Kubernetes 的轻量级运行时环境
|
||||
|
||||
我也创建了视频材料来介绍这些项目。
|
||||
|
||||
- [video](https://youtu.be/3cDxYO2GK4w)
|
||||
|
||||
### 毕业项目
|
||||
|
||||
毕业的项目被认为是成熟的,已被许多组织采用的,并且严格遵守了 CNCF 的准则。以下是三个最受欢迎的开源 CNCF 毕业项目。(请注意,其中一些描述来源于项目的网站并被做了改编。)
|
||||
|
||||
#### Kubernetes(希腊语“舵手”)
|
||||
|
||||
Kubernetes! 说起云原生应用,怎么能不提 Kubernetes 呢? Google 发明的 Kubernetes 无疑是最著名的基于容器的应用程序的容器编排平台,而且它还是一个开源工具。
|
||||
|
||||
什么是容器编排平台?通常,一个容器引擎本身可以管理几个容器。但是,当你谈论数千个容器和数百个服务时,管理这些容器变得非常复杂。这就是容器编排引擎的用武之地。容器编排引擎通过自动化容器的部署、管理、网络和可用性来帮助管理大量的容器。
|
||||
|
||||
Docker Swarm 和 Mesosphere Marathon 也是容器编排引擎,但是可以肯定地说,Kubernetes 已经赢得了这场比赛(至少现在是这样)。Kubernetes 还催生了像 [OKD][18] 这样的容器即服务(CaaS)平台,它是 Kubernetes 的 Origin 社区发行版,并成了 [Red Hat OpenShift][19] 的一部分。
|
||||
|
||||
想开始学习,请访问 [Kubernetes GitHub 仓库][9],并从 [Kubernetes 文档][20]页面访问其文档和学习资源。
|
||||
|
||||
#### Prometheus(普罗米修斯)
|
||||
|
||||
Prometheus 是 2012 年在 SoundCloud 上构建的一个开源的系统监控和告警工具。之后,许多公司和组织都采用了 Prometheus,并且该项目拥有非常活跃的开发者和用户群体。现在,它已经成为一个独立的开源项目,独立于公司之外进行维护。
|
||||
|
||||
![Prometheus’ architecture][21]
|
||||
|
||||
*Prometheus 的架构*
|
||||
|
||||
理解 Prometheus 的最简单方法是可视化一个生产系统,该系统需要 24(小时)x 365(天)都可以正常运行。没有哪个系统是完美的,也有减少故障的技术(称为容错系统),但是,如果出现问题,最重要的是尽快发现问题。这就是像 Prometheus 这样的监控工具的用武之地。Prometheus 不仅仅是一个容器监控工具,但它在云原生应用公司中最受欢迎。此外,其他开源监视工具,包括 [Grafana][22],都借助了 Prometheus。
|
||||
|
||||
开始使用 Prometheus 的最佳方法是下载其 [GitHub 仓库][10]。在本地运行 Prometheus 很容易,但是你需要安装一个容器引擎。你可以在 [Prometheus 网站][23]上查看详细的文档。
|
||||
|
||||
#### Envoy(使者)
|
||||
|
||||
Envoy(或 Envoy 代理)是专为云原生应用设计的开源的边缘代理和服务代理。由 Lyft 创建的 Envoy 是为单一服务和应用而设计的高性能的 C++ 开发的分布式代理,同时也是为由大量微服务组成的服务网格架构而设计的通信总线和通用数据平面。Envoy 建立在 Nginx、HAProxy、硬件负载均衡器和云负载均衡器等解决方案的基础上,Envoy 与每个应用相伴(并行)运行,并通过提供平台无关的方式提供通用特性来抽象网络。
|
||||
|
||||
当基础设施中的所有服务流量都经过 Envoy 网格时,很容易就可以通过一致的可观测性来可视化问题域,调整整体性能,并在单个位置添加基础功能。基本上,Envoy 代理是一个可帮助组织为生产环境构建容错系统的服务网格工具。
|
||||
|
||||
服务网格应用有很多替代方案,例如 Uber 的 [Linkerd][24](下面会讨论)和 [Istio][25]。Istio 通过将其部署为 [Sidecar][26] 并利用了 [Mixer][27] 的配置模型,实现了对 Envoy 的扩展。Envoy 的显著特性有:
|
||||
|
||||
* 包括所有的“<ruby>入场筹码<rt>table stakes</rt></ruby>(LCTT 译注:引申为基础必备特性)”特性(与 Istio 这样的控制平面组合时)
|
||||
* 带载运行时 99% 数据可达到低延时
|
||||
* 可以作为核心的 L3/L4 过滤器,提供了开箱即用的 L7 过滤器
|
||||
* 支持 gRPC 和 HTTP/2(上行/下行)
|
||||
* 由 API 驱动,并支持动态配置和热重载
|
||||
* 重点关注指标收集、跟踪和整体可监测性
|
||||
|
||||
要想了解 Envoy,证实其能力并实现其全部优势,需要丰富的生产级环境运行的经验。你可以在其[详细文档][28]或访问其 [GitHub][11] 仓库了解更多信息。
|
||||
|
||||
### 孵化项目
|
||||
|
||||
下面是六个最流行的开源的 CNCF 孵化项目。
|
||||
|
||||
#### rkt(火箭)
|
||||
|
||||
rkt, 读作“rocket”,是一个 Pod 原生的容器引擎。它有一个命令行接口用来在 Linux 上运行容器。从某种意义上讲,它和其他容器如 [Podman][29]、Docker 和 CRI-O 相似。
|
||||
|
||||
rkt 最初是由 CoreOS (后来被 Red Hat 收购)开发的,你可以在其网站上找到详细的[文档][30],以及在 [GitHub][12] 上访问其源代码。
|
||||
|
||||
#### Jaeger(贼鸥)
|
||||
|
||||
Jaeger 是一个开源的端到端的分布式追踪系统,适用于云端应用。在某种程度上,它是像 Prometheus 这样的监控解决方案。但它有所不同,因为其使用场景有所扩展:
|
||||
|
||||
* 分布式事务监控
|
||||
* 性能和延时优化
|
||||
* 根因分析
|
||||
* 服务依赖性分析
|
||||
* 分布式上下文传播
|
||||
|
||||
Jaeger 是一项 Uber 打造的开源技术。你可以在其网站上找到[详细文档][31],以及在 [GitHub][13] 上找到其源码。
|
||||
|
||||
#### Linkerd
|
||||
|
||||
像创建 Envoy 代理的 Lyft 一样,Uber 开发了 Linkerd 开源解决方案用于生产级的服务维护。在某些方面,Linkerd 就像 Envoy 一样,因为两者都是服务网格工具,旨在提供平台级的可观测性、可靠性和安全性,而无需进行配置或代码更改。
|
||||
|
||||
但是,两者之间存在一些细微的差异。 尽管 Envoy 和 Linkerd 充当代理并可以通过所连接的服务进行上报,但是 Envoy 并不像 Linkerd 那样被设计为 Kubernetes Ingress 控制器。Linkerd 的显著特点包括:
|
||||
|
||||
* 支持多种平台(Docker、Kubernetes、DC/OS、Amazon ECS 或任何独立的机器)
|
||||
* 内置服务发现抽象,可以将多个系统联合在一起
|
||||
* 支持 gRPC、HTTP/2 和 HTTP/1.x请 求和所有的 TCP 流量
|
||||
|
||||
你可以在 [Linkerd 网站][32]上阅读有关它的更多信息,并在 [GitHub][14] 上访问其源码。
|
||||
|
||||
#### Helm(舵轮)
|
||||
|
||||
Helm 基本上就是 Kubernetes 的包管理器。如果你使用过 Apache Maven、Maven Nexus 或类似的服务,你就会理解 Helm 的作用。Helm 可帮助你管理 Kubernetes 应用程序。它使用“Helm Chart”来定义、安装和升级最复杂的 Kubernetes 应用程序。Helm 并不是实现此功能的唯一方法;另一个流行的概念是 [Kubernetes Operators][33],它被 Red Hat OpenShift 4 所使用。
|
||||
|
||||
你可以按照其文档中的[快速开始指南][34]或 [GitHub 指南][15]来试用 Helm。
|
||||
|
||||
#### Etcd
|
||||
|
||||
Etcd 是一个分布式的、可靠的键值存储,用于存储分布式系统中最关键的数据。其主要特性有:
|
||||
|
||||
* 定义明确的、面向用户的 API(gRPC)
|
||||
* 自动 TLS,可选的客户端证书验证
|
||||
* 速度(可达每秒 10,000 次写入)
|
||||
* 可靠性(使用 Raft 实现分布式)
|
||||
|
||||
Etcd 是 Kubernetes 和许多其他技术的默认的内置数据存储方案。也就是说,它很少独立运行或作为单独的服务运行;相反,它以集成到 Kubernetes、OKD/OpenShift 或其他服务中的形式来运作。还有一个 [etcd Operator][35] 可以用来管理其生命周期并解锁其 API 管理功能:
|
||||
|
||||
你可以在 [etcd 文档][36]中了解更多信息,并在 [GitHub][16]上访问其源码。
|
||||
|
||||
#### CRI-O
|
||||
|
||||
CRI-O 是 Kubernetes 运行时接口的 OCI 兼容实现。CRI-O 用于各种功能,包括:
|
||||
|
||||
* 使用 runc(或遵从 OCI 运行时规范的任何实现)和 OCI 运行时工具运行
|
||||
* 使用容器/镜像进行镜像管理
|
||||
* 使用容器/存储来存储和管理镜像层
|
||||
* 通过容器网络接口(CNI)来提供网络支持
|
||||
|
||||
CRI-O 提供了大量的[文档][37],包括指南、教程、文章,甚至播客,你还可以访问其 [GitHub 页面][17]。
|
||||
|
||||
我错过了其他有趣且开源的云原生项目吗?请在评论中提醒我。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/8/cloud-native-projects
|
||||
|
||||
作者:[Bryant Son][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[messon007](https://github.com/messon007)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_cloud_cc.png?itok=XSV7yR9e (clouds in the sky with blue pattern)
|
||||
[2]: https://opensource.com/article/18/7/what-are-cloud-native-apps
|
||||
[3]: https://thenewstack.io/10-key-attributes-of-cloud-native-applications/
|
||||
[4]: https://www.cncf.io
|
||||
[5]: https://opensource.com/sites/default/files/uploads/cncf_1.jpg (Cloud-Native Computing Foundation applications ecosystem)
|
||||
[6]: https://www.opencontainers.org
|
||||
[7]: https://opensource.com/sites/default/files/uploads/cncf_2.jpg (CNCF project maturity levels)
|
||||
[8]: https://github.com/cncf/toc/blob/master/process/graduation_criteria.adoc
|
||||
[9]: https://github.com/kubernetes/kubernetes
|
||||
[10]: https://github.com/prometheus/prometheus
|
||||
[11]: https://github.com/envoyproxy/envoy
|
||||
[12]: https://github.com/rkt/rkt
|
||||
[13]: https://github.com/jaegertracing/jaeger
|
||||
[14]: https://github.com/linkerd/linkerd
|
||||
[15]: https://github.com/helm/helm
|
||||
[16]: https://github.com/etcd-io/etcd
|
||||
[17]: https://github.com/cri-o/cri-o
|
||||
[18]: https://www.okd.io/
|
||||
[19]: https://www.openshift.com
|
||||
[20]: https://kubernetes.io/docs/home
|
||||
[21]: https://opensource.com/sites/default/files/uploads/cncf_3.jpg (Prometheus’ architecture)
|
||||
[22]: https://grafana.com
|
||||
[23]: https://prometheus.io/docs/introduction/overview
|
||||
[24]: https://linkerd.io/
|
||||
[25]: https://istio.io/
|
||||
[26]: https://istio.io/docs/reference/config/networking/v1alpha3/sidecar
|
||||
[27]: https://istio.io/docs/reference/config/policy-and-telemetry
|
||||
[28]: https://www.envoyproxy.io/docs/envoy/latest
|
||||
[29]: https://podman.io
|
||||
[30]: https://coreos.com/rkt/docs/latest
|
||||
[31]: https://www.jaegertracing.io/docs/1.13
|
||||
[32]: https://linkerd.io/2/overview
|
||||
[33]: https://coreos.com/operators
|
||||
[34]: https://helm.sh/docs
|
||||
[35]: https://github.com/coreos/etcd-operator
|
||||
[36]: https://etcd.io/docs/v3.3.12
|
||||
[37]: https://github.com/cri-o/cri-o/blob/master/awesome.md
|
185
published/202004/20190822 How the Linux desktop has grown.md
Normal file
185
published/202004/20190822 How the Linux desktop has grown.md
Normal file
@ -0,0 +1,185 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12068-1.html)
|
||||
[#]: subject: (How the Linux desktop has grown)
|
||||
[#]: via: (https://opensource.com/article/19/8/how-linux-desktop-grown)
|
||||
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
|
||||
|
||||
Linux 桌面史话
|
||||
======
|
||||
|
||||
> 自 20 世纪 90 年代初以来,Linux 桌面已从一个简单的窗口管理器发展为一个完整的桌面。让我们一起来回顾一下 Linux 桌面的历史。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/03/142430kei55auvvv254aka.jpg)
|
||||
|
||||
我第一次安装 Linux 是在 1993 年。那时,安装这种操作系统没有太多的选择。早期,许多人只是从别人那里复制一个运行中的镜像。然后有人有了一个很好的想法,创建一个 Linux 的“发行版”,让你可以自定义要安装的软件。这就是 Softlanding Linux 系统(SLS),也是我首次接触 Linux。
|
||||
|
||||
当时我的 386 PC 虽然内存不多,但已经足够了。SLS 1.03 需要 2MB 的内存才能运行,如果要编译程序,则需要 4MB 的内存。如果要运行 X 窗口系统,则需要多达 8MB 的内存!而我的电脑正好有足够的内存来运行 X 窗口系统。
|
||||
|
||||
因为我是在命令行中成长的,所以图形化的用户界面对我来说并不重要,但它确实很方便,我可以在不同的窗口中运行应用程序,并在任务间轻松切换。
|
||||
|
||||
从我第一次尝试 Linux 开始,我就迷上了它。从那以后,我一直在台式机上使用 Linux。和许多人一样,我也曾有一段时间以双引导配置运行 Linux,这样我就可以跳回到 MS-DOS 和 Windows 来运行某些程序。直到 1998 年,我终于冒了个险,全面投身于 Linux 之中。
|
||||
|
||||
在过去的 26 年中,我看着 Linux 桌面逐渐成熟。在这段时间里,我还尝试了各种有趣的桌面环境,下面我来分享一下 Linux 桌面的历史。
|
||||
|
||||
### X 和窗口管理器
|
||||
|
||||
Linux 上的第一个“桌面”还不是桌面。相反,它们是运行在 X 窗口系统上的“<ruby>窗口管理器<rt>window manager</rt></ruby>”(WM)。X 提供了图形用户界面的基本构件,比如在屏幕上创建窗口,并提供键盘和鼠标输入。就其本身而言,X 的用处并不大。为了使 X 图形环境变得有用,你需要一种方法来管理会话中的所有窗口。这就出现了<ruby>窗口管理器<rt>window manager</rt></ruby>。运行 xterm 或 xclock 之类的 X 程序就会在一个窗口中打开该程序。窗口管理器可以跟踪窗口并进行基本的内部管理,例如让你可以来回移动窗口并将其最小化。其余的事情取决于你自己。你可以通过将程序名列在 `~/.xinitrc` 文件中以在 X 开始时启动这些程序,但是通常,你会从 xterm 中运行新程序。
|
||||
|
||||
在 1993 年,最常见的窗口管理器是 TWM,它的历史可以追溯到 1988 年。TWM 相当简单,仅仅提供了基本的窗口管理功能。
|
||||
|
||||
![TWM on SLS 1.05][2]
|
||||
|
||||
*SLS 1.05 上的 TWM,显示了 xterm、xclock 和 Emacs 编辑器*
|
||||
|
||||
另一个早期的窗口管理器是 OpenLook 虚拟窗口管理器(OLVWM)。OpenLook 是 Sun 微系统公司在 20世纪 80 年代开发的图形用户界面,后来被移植到其它 Unix 平台。作为一个*虚拟*窗口管理器,OLVWM 支持多个工作区。
|
||||
|
||||
![OLVWM on SLS 1.05][3]
|
||||
|
||||
*SLS 1.05 上的 OLVWM,显示了 xterm 和虚拟工作区选择器*
|
||||
|
||||
当 Linux 开始流行起来的时候,没多久就有人创建出性能更流畅、界面更好的新窗口管理器。这些新的窗口管理器中首先出现的是虚拟窗口管理器 FVWM。FVWM 比 TWM 或 OLVWM 更具现代感。但是,我们仍然没有桌面。
|
||||
|
||||
![FVWM on SLS 1.05][4]
|
||||
|
||||
*SLS 1.05 上的 FVWM,显示了 xterm 和文件管理器*
|
||||
|
||||
以现代的眼光来看,TWM 和 FVWM 可能看起来很朴素。但重要的是要想想当时其它图形环境是什么样子。 Windows 当时的版本看起来也相当简单。Windows 版本 1 到版本 3 使用了一个称为“程序管理器”的普通启动器。
|
||||
|
||||
![Windows 3.11][5]
|
||||
|
||||
*Windows 3.11,显示程序管理器和记事本编辑器*
|
||||
|
||||
1995 年 8 月,微软发布了 Windows 95,改变了现代 PC 桌面的格局。当然,我当时对此印象很深刻。我曾觉得 Windows 3.x 笨拙而丑陋,但 Windows 95 却流畅而漂亮。更重要的是,我们现在将 Windows 95 视为“**桌面**”。新的“桌面”隐喻是一个巨大的进步。你可以在桌面上放置图标——事实上,Windows 95 提供了两个默认的桌面图标,分别是“我的电脑”(用于打开文件管理器)和“回收站”(用于放置以后要删除的文件)。
|
||||
|
||||
但是,更重要的是,Windows 95 桌面的意味着*整合*。程序管理器不见了,取而代之的是屏幕底部的任务栏,可让你使用更简单的“开始”菜单启动新程序。任务栏是多功能的,还通过一系列的按钮显示了你正在运行的程序,而托盘显示了时间、扬声器音量和其它简单的控件。你可以在这个新桌面上右键单击任何对象, Windows 95 会为你提供一个上下文相关的菜单,其中又你可以执行的操作。
|
||||
|
||||
![Windows 95][6]
|
||||
|
||||
*Windows 95,显示了记事本编辑器*
|
||||
|
||||
与以前版本的 Windows 甚至其它 Linux 窗口管理器相比,Windows 95 的界面更加流畅并且易于使用。值得一提的是,Linux 开发人员创建了一个模仿 Windows 95 界面的 FVWM 的新版本。名为 FVWM95 的新窗口管理器仍然不是桌面,但它看起来非常漂亮。新的任务栏让你可以使用“开始”菜单启动新的 X 程序。任务栏还可以使用类似于 Windows 95 的按钮显示了正在运行的程序。
|
||||
|
||||
![FVWM95 on Red Hat Linux 5.2][7]
|
||||
|
||||
*在 Red Hat Linux 5.2 上的 FVWM95,显示了 xterm 和一个带有 xterm 图标、文件管理器和其他程序的快速访问程序启动器*
|
||||
|
||||
虽然 FVWM95 和其他窗口管理器都在改进,但核心问题仍然存在:Linux 并没有真正的桌面。它具有一堆窗口管理器,仅此而已。使用图形用户界面的 Linux 应用程序(基本上意味着它们是 X 应用程序)看起来形态各异且工作方式也不同。除了 X 窗口系统提供的简单的纯文本复制/粘贴功能外,你不能从一个应用程序复制和粘贴到另一个应用程序里。Linux 真正需要的是在其图形用户界面中进行彻底的重新打造,以创建它的第一个桌面。
|
||||
|
||||
### Linux 桌面之初啼
|
||||
|
||||
在 1996 年,Matthias Ettrich 有感于 X 之下 Linux 应用程序体验不一致的困扰。他想使找个更易于使用的图形环境,而且更重要的是,他想让所有东西都“集成”在一起,就像真正的桌面一样。
|
||||
|
||||
Matthias 开始了<ruby>K 桌面环境<rt>K Desktop Environment</rt></ruby>(KDE)的工作。那个 K 代表着 “Kool”(LCTT 译注:即 Cool)。但是 KDE 这个名字也意味着可以类似<ruby>通用桌面环境<rt>Common Desktop Environment</rt></ruby>(CDE)的做法,而 CDE 是“大 Unix”世界的标准。尽管到了 1996 年,CDE 看起来已经有点过时了。CDE 基于 Motif 部件集,这也是 FVWM 所模仿的设计。KDE 1.0 于 1998 年 7 月完成,与 FVWM95 等普通窗口管理器相比,它有了明显改进。
|
||||
|
||||
![KDE 1.0][8]
|
||||
|
||||
*K 桌面环境(KDE)版本 1.0。图片来源:Paul Brown / KDE*
|
||||
|
||||
KDE 是 Linux 向前迈出的一大步。最终,Linux 有了一个真正的桌面,集成了应用程序和更多现代的桌面图标。KDE 的设计与 Windows 95 并无不同。屏幕底部有一个任务栏,它提供了相当于 Windows 95 的“开始”菜单以及一些应用程序的快捷键。KDE 还支持虚拟桌面,这些桌面被巧妙地标记为 “One”、“ Two”、“Three” 和 “Four”。正在运行的应用程序通过位于屏幕顶部单独的任务栏的按钮表示。
|
||||
|
||||
但并不是每个人都对 KDE 感到满意。为了将 GUI 从系统中抽象出来,KDE 使用了 Trolltech 的 Qt 工具套件库。不幸的是,Qt 并不是以自由软件的许可证进行分发的。Trolltech 允许 Qt 在自由软件应用程序中免费使用,但在商业或专有应用程序中要收取使用费。而且这种二分法与自由软件不符。这给 Linux 发行版带来了问题:它们应该包括 KDE 吗?还是默认使用 FVWM 这样老式但属于自由软件的图形用户界面?
|
||||
|
||||
面对这种情况,Miguel de Icaza 和 Federico Mena 于 1997 年开始开发新的 Linux 桌面上。这个新项目被称为 GNOME,即<ruby>GNU 网络对象模型环境<rt>GNU Network Object Model Environment</rt></ruby>的缩写。GNOME 旨在成为一个完全自由的软件,并使用了一个不同的工具套件库 —— 来自 GIMP 图像编辑器的 GTK。GTK 从字面上的意思 <ruby>GIMP 工具套件<rt>GIMP Tool Kit</rt></ruby>。当 GNOME 1.0 终于在 1999 年发布时,Linux 又多了一个现代化的桌面环境。
|
||||
|
||||
![GNOME 1.0][9]
|
||||
|
||||
*GNOME 1.0 版。图片来源:GNOME 文档项目*
|
||||
|
||||
有两个 Linux 桌面环境固然很棒,但“KDE 与 GNOME”之争仍持续了一段时间。到了 1999 年,Trolltech 以新的公共许可证 <ruby>Q 公共许可证<rt>Q Public License</rt></ruby>(QPL)重新发布了 Qt 库。但是,新许可证有其自身的包袱—-QPL 仅适用于 Qt 在开源软件项目中的使用,而不适用于商业项目。因此,<ruby>自由软件基金会<rt>Free Software Foundation</rt></ruby>(FSF)认为 QPL 与 <ruby>GNU 通用公共许可证<rt>GNU General Public License</rt></ruby>(GNU GPL)[不兼容][10]。这个许可证问题一直持续到 2000 年 Trolltech 在 GNU GPL v2 下重新发布 Qt 库。
|
||||
|
||||
### 随着时间的发展
|
||||
|
||||
Linux 桌面继续走向成熟。KDE 和 GNOME 进行了一场友好的竞争,促使双方都在增加了新的功能,还互相交流了思想和观念。到了 2004 年,GNOME 和 KDE 都取得了长足的进步,但只是给用户界面带来了渐进式的变化。
|
||||
|
||||
KDE 2 和 3 继续依赖屏幕底部的任务栏概念,但并入了用于运行应用程序的按钮。KDE 最明显的变化之一是添加了 Konqueror 浏览器,该浏览器首次出现在 KDE 2 中。
|
||||
|
||||
![KDE 2.2.2 \(2001\) showing the Konqueror browser][11]
|
||||
|
||||
*KDE 2.2.2(2001),显示了 Konqueror 浏览器。图片来源:Paul Brown / KDE*
|
||||
|
||||
![KDE 3.2.2][12]
|
||||
|
||||
*Fedora Core 2 上的 KDE 3.2.2(2004),显示了 Konqueror 文件管理器(使用 Fedora Core 2 主题)*
|
||||
|
||||
GNOME 2 也使用了任务栏概念,但将任务栏一分为二:屏幕顶部的任务栏用于启动应用程序并响应桌面提示,屏幕底部的任务栏用于显示正在运行的应用程序。我把这两个任务栏称之为“你可以做的事情”(顶部)和“你正在做的事情”(底部)。除了精简的用户界面外,GNOME 还添加了由 Eazel 开发的更新过的文件管理器,名为 Nautilus。
|
||||
|
||||
![GNOME 2.6.0][13]
|
||||
|
||||
*Fedora Core 2 上的 GNOME 2.6.0(2004),显示了 Nautilus 文件管理器(使用 Fedora Core 2 主题)*
|
||||
|
||||
随着时间的流逝,KDE 和 GNOME 走了不同的道路。两者都提供了功能丰富、健壮且现代化的桌面环境,但是却具有不同的用户界面目标。2011 年,GNOME 和 KDE 在桌面界面上出现了很大的偏差。KDE 4.6(2011 年 1 月)和 KDE 4.7(2011 年 7 月)提供了更传统的桌面感受,同时继续根植于许多用户熟悉的任务栏概念。当然,KDE 的底层发生很多变化,但是它仍然保留了熟悉的外观。
|
||||
|
||||
![KDE 4.6][14]
|
||||
|
||||
*KDE 4.6,显示 Gwenview 图像查看器。图片来源:KDE*
|
||||
|
||||
2011 年,GNOME 以一个新的桌面概念彻底改变了走向。GNOME 3 旨在创建一个更简单、更精简的桌面体验,使用户能够专注于自己的工作。任务栏消失了,取而代之的是屏幕顶部的黑色状态栏,其中包括音量和网络控件,显示了时间和电池状态,并允许用户通过重新设计过的菜单启动新程序。
|
||||
|
||||
菜单的变化最具最戏剧性。单击“活动”菜单或将鼠标移到“活动”的“热角”,所有打开的应用程序会显示为单独的窗口。用户还可以从“概述”中单击“应用程序”选项卡以启动新程序。“概述”还提供了一个内部集成的搜索功能。
|
||||
|
||||
![GNOME 3.0][15]
|
||||
|
||||
*GNOME 3.0,显示 GNOME 图片应用程序。图片来源:GNOME*
|
||||
|
||||
![GNOME 3.0][16]
|
||||
|
||||
*GNOME 3.0,显示活动概述。图片来源:GNOME*
|
||||
|
||||
### 你的桌面之选
|
||||
|
||||
拥有两个 Linux 桌面意味着用户有很大的选择余地。有些人喜欢 KDE,而另一些人喜欢 GNOME。没关系,选择最适合你的桌面就行。
|
||||
|
||||
可以肯定的是,KDE 和 GNOME 都有拥护者和批评者。例如,GNOME 因为放弃任务栏而改成“活动概述”而受到了不少批评。也许最著名的批评者是 Linus Torvalds,他在 2011 年[大声斥责并抛弃了][17]新的 GNOME,将其视为“邪恶的烂摊子”,然后在两年后又[回到了][18] GNOME。
|
||||
|
||||
其他人也对 GNOME 3 提出了类似的批评,以至于一些开发人员复刻 GNOME 2 的源代码创建了 MATE 桌面。MATE(是<ruby>MATE 高级传统环境<rt>MATE Advanced Traditional Environment</rt></ruby>的递归缩写)延续了 GNOME 2 的传统任务栏界面。
|
||||
|
||||
无论如何,毫无疑问当今两个最受欢迎的 Linux 桌面是 KDE 和 GNOME。它们的当前版本非常成熟,功能也很丰富。KDE 5.16(2019)和 GNOME 3.32(2019)都试图简化和精简 Linux 桌面体验,但是方式有所不同。GNOME 3.32 继续致力于极简外观,删除所有分散用户注意力的用户界面元素,以便用户可以专注于其应用程序和工作。KDE 5.16 采用了更为熟悉的任务栏方法,但也增加了其他视觉上的改进和亮点,尤其是改进的小部件处理和图标。
|
||||
|
||||
![KDE 5.16 Plasma][19]
|
||||
|
||||
*KDE 5.16 Plasma。图片来源:KDE*
|
||||
|
||||
![GNOME 3.32][20]
|
||||
|
||||
*GNOME 3.32。图片来源:GNOME*
|
||||
|
||||
同时,你也不会完全失去它们之间的兼容性。每个主要的 Linux 发行版都提供了兼容性库,因此你可以在运行 GNOME 的同时来运行 KDE 应用程序。当你真正想使用的应用程序是为其他桌面环境编写的,这一点非常有用。你可以在 GNOME 上运行 KDE 应用程序,反之亦然。
|
||||
|
||||
我认为这种态势不会很快改变,这是一件好事。KDE 和 GNOME 之间的良性竞争使这两个阵营的开发人员可以避免故步自封。无论你使用 KDE 还是 GNOME,你都将拥有一个集成度很高的现代化桌面。而最重要的是,这意味着 Linux 拥有自由软件最好的特点:选择。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/8/how-linux-desktop-grown
|
||||
|
||||
作者:[Jim Hall][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/jim-hallhttps://opensource.com/users/jason-bakerhttps://opensource.com/users/jlacroixhttps://opensource.com/users/doni08521059https://opensource.com/users/etc-eterahttps://opensource.com/users/marcobravohttps://opensource.com/users/alanfdoss
|
||||
[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/sites/default/files/uploads/twm-sls105.png (TWM on SLS 1.05)
|
||||
[3]: https://opensource.com/sites/default/files/uploads/olvwm-sls105.png (OLVWM on SLS 1.05)
|
||||
[4]: https://opensource.com/sites/default/files/uploads/fvwm-sls105.png (FVWM on SLS 1.05)
|
||||
[5]: https://opensource.com/sites/default/files/uploads/win311.png (Windows 3.11)
|
||||
[6]: https://opensource.com/sites/default/files/uploads/win95.png (Windows 95)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/fvwm95-rh52.png (FVWM95 on Red Hat Linux 5.2)
|
||||
[8]: https://opensource.com/sites/default/files/uploads/kde1.png (KDE 1.0)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/gnome10.png (GNOME 1.0)
|
||||
[10]: https://www.linuxtoday.com/developer/2000090500121OPLFKE
|
||||
[11]: https://opensource.com/sites/default/files/uploads/kde_2.2.2.png (KDE 2.2.2 (2001) showing the Konqueror browser)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/kde322-fc2.png (KDE 3.2.2)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/gnome26-fc2.png (GNOME 2.6.0)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/kde46.png (KDE 4.6)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/gnome30.png (GNOME 3.0)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/gnome30-overview.png (GNOME 3.0)
|
||||
[17]: https://www.theregister.co.uk/2011/08/05/linus_slams_gnome_three/
|
||||
[18]: https://www.phoronix.com/scan.php?page=news_item&px=MTMxNjc
|
||||
[19]: https://opensource.com/sites/default/files/uploads/kde516.png (KDE 5.16 Plasma)
|
||||
[20]: https://opensource.com/sites/default/files/uploads/gnome332.png (GNOME 3.32)
|
@ -0,0 +1,155 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12152-1.html)
|
||||
[#]: subject: (How to make a Halloween lantern with Inkscape)
|
||||
[#]: via: (https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape)
|
||||
[#]: author: (Jess Weichler https://opensource.com/users/cyanide-cupcake)
|
||||
|
||||
如何使用 Inkscape 制作万圣节灯笼
|
||||
======
|
||||
|
||||
> 使用开源软件为你最喜欢的万圣节鬼屋制作一个有趣和怪异的装饰品。
|
||||
|
||||
![万圣节 - 背光飞行的蝙蝠][1]
|
||||
|
||||
使用开源软件装饰一个独一无二的万圣节灯笼!
|
||||
|
||||
通常,灯笼的一部分结构体是不透明的,以阻挡内部的光线。灯笼之所以成为灯笼,是因为其去掉了一些东西 :从结构体上切开的窗口,这样光线就可以射出。虽然对于照明来说不实用,但是一个有着怪异形状窗口和隐藏暗色轮廓的灯笼却可以令人兴奋,并创造出很多乐趣。
|
||||
|
||||
这篇演示如何使用 [Inkscape][2] 创建你自己的灯笼。如果还没有 Inkscape ,在 Linux 上,你可以从软件库中安装它,在 MacOS 和 Windows 上,你可以从[Inkscape 网站][3] 上下载它.
|
||||
|
||||
### 使用材料
|
||||
|
||||
* 模板([A4][4] 或[信纸][5]大小)
|
||||
* 卡片纸(黑色是传统色)
|
||||
* 描图纸(可选)
|
||||
* 裁纸刀、尺子、切割垫板(可使用工艺切割机/激光切割机代替)
|
||||
* 工艺胶
|
||||
* LED 茶灯"蜡烛"
|
||||
|
||||
安全注意事项:这个项目只使用电池操作的蜡烛。
|
||||
|
||||
### 理解模板
|
||||
|
||||
首先,从上面的链接下载你所在区域(A4 或信纸)的合适的模板,然后在 Inkscape 中打开它。
|
||||
|
||||
![灯笼模板荧光屏][6]
|
||||
|
||||
灰白色的棋盘格背景是透明的(从技术角度来说,它是 alpha 通道。)
|
||||
|
||||
黑色基板构成了灯笼。现在,没有窗口可以让光线穿过;灯笼有一个非镂空的黑色基板。你将在 Inkscape 中使用**并集**和**差集**选项来数字化的设计窗口。
|
||||
|
||||
蓝色虚线表示折线。橙色实线表示参考线。采光窗口不应该放在橙色盒子的外面。
|
||||
|
||||
模板的左侧是你可以在你设计中使用的一些预先制作好的对象。
|
||||
|
||||
### 创建一个窗口或形状
|
||||
|
||||
1. 创建一个看起来像你想要的窗口样式的对象。可以使用 Inkscape 左侧工具栏中的一些形状工具来创建对象。此外,你可以下载共创或公共领域的剪贴画,并导入 PNG 文件到你的项目中。
|
||||
2. 当你对对象的形状满意时,在顶部菜单中选择“路径” -> “对象转化成路径” 将其转换为一个路径(而不是一个形状,Inkscape 视其为两种不同的对象)。
|
||||
|
||||
![对象到路径 菜单][7]
|
||||
|
||||
3. 在基板形状的上面放置对象。
|
||||
4. 选择对象和黑色基板。通过先单击一个,并按住 `Shift` 按键,再选择另一个来完成。
|
||||
5. 从顶部菜单选择“路径” -> “差集” 来从基板的对象中移除形状。这将创建灯笼中的一个窗口。
|
||||
|
||||
![路径 > 差集 菜单][8]
|
||||
|
||||
### 添加对象到窗口中
|
||||
|
||||
在制作了一个窗口后,你可以添加对象到其中来创建一个场景。
|
||||
|
||||
提示:
|
||||
|
||||
* 所有的对象,包括文本,必须连接到灯笼的基板,否则,在切割后会掉落下来,并留下一片空白。
|
||||
* 避免小而复杂的细微之处。即使使用激光切割机或工艺切割机等机器,也很难切割这些细微之处。
|
||||
|
||||
1. 创建或导入一个对象。
|
||||
2. 放置对象到窗口内,以便它至少接触基板的两侧。
|
||||
3. 选择对象后,从顶部菜单选择“连接” -> “对象转化成路径”。
|
||||
|
||||
![对象到路径 菜单][9]
|
||||
|
||||
4. 选择对象和黑色基板,通过在按住 `Shift` 按键的同时单击每一个来完成。
|
||||
5. 选择“路径” -> “并集”来使对象和基板合二为一。
|
||||
|
||||
### 添加文本
|
||||
|
||||
文本既可以从基板剪出文字来创建一个窗口(就像我对星星所做的那样),或者也可以添加到一个窗口上(它可以阻挡来自灯笼内部的光线)。如果你要创建一个窗口,只需要执行下面的步骤 1 和步骤 2,然后使用“差集”来从基板移除文本。
|
||||
|
||||
1. 从左侧边栏中选择文本工具来创建文本。粗体字体效果最好。
|
||||
|
||||
![文本工具][10]
|
||||
|
||||
2. 选择你的文本,然后从顶部菜单选择“路径” -> “对象转化成路径”。这将转换文本对象为一个路径。注意,这个步骤意味着你将不能再编辑该文本,所以,*只有当*你确定你拥有想要的单词后,执行这个步骤。
|
||||
3. 在你转换文本后,你可以按键盘上的 `F2` 来激活节点编辑器工具,当选择使用这个工具时,可以清楚地显示文本的节点。
|
||||
|
||||
![选中的文本使用节点编辑器][11]
|
||||
|
||||
4. 取消文本分组。
|
||||
5. 调整每个字母,以便使其与相邻字母或基板稍微重叠。
|
||||
|
||||
![重叠文本][12]
|
||||
|
||||
6. 为将所有的字母彼此连接,并连接到基板,重新选择所有文本和基板,然后选择“路径” -> “并集”。
|
||||
|
||||
![使用 路径 > 并集 连接字母和基板][13]
|
||||
|
||||
### 准备打印
|
||||
|
||||
下面是手工切割灯笼的说明。如果使用激光切割机或工艺切割机,遵循硬件所需要的技巧来准备好你的文件。
|
||||
|
||||
1. 在“图层”面板中,单击“安全”图层旁边的“眼睛”图标来隐藏安全线。如果你看不到图层面板,通过顶部菜单选择“图层” -> “图层”来显示它。
|
||||
2. 选择黑色基板。在“填充和笔划”面板中,设置填充为“X”(意味着*不填充*),设置“笔划”为纯黑色(对于喜欢十六进制的粉丝来说是 `#000000ff` )。
|
||||
|
||||
![设置填充和笔划][14]
|
||||
|
||||
3. 使用“文件” -> “打印”来打印你的图案。
|
||||
4. 使用一把工艺刀和直尺,小心地绕着每一条黑线切割。在蓝色虚线上轻划,然后折叠。
|
||||
|
||||
![裁剪灯笼][15]
|
||||
|
||||
5. 要完成窗口的制作,剪切描图纸为每个窗口的大小,然后粘贴它到灯笼的内侧。
|
||||
|
||||
![添加描图纸][16]
|
||||
|
||||
6. 在折条处把灯笼的边粘在一起。
|
||||
7. 接通电池供电的 LED 蜡烛,并放置它到你灯笼中。
|
||||
|
||||
![完成灯笼][17]
|
||||
|
||||
现在你的灯笼已经完成了,准备好点亮你的鬼屋了。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape
|
||||
|
||||
作者:[Jess Weichler][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/cyanide-cupcake
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/halloween_bag_bat_diy.jpg?itok=24M0lX25 (Halloween - backlit bat flying)
|
||||
[2]: https://opensource.com/article/18/1/inkscape-absolute-beginners
|
||||
[3]: http://inkscape.org
|
||||
[4]: https://www.dropbox.com/s/75qzjilg5ak2oj1/papercraft_lantern_A4_template.svg?dl=0
|
||||
[5]: https://www.dropbox.com/s/8fswdge49jwx91n/papercraft_lantern_letter_template%20.svg?dl=0
|
||||
[6]: https://opensource.com/sites/default/files/uploads/lanterntemplate_screen.png (Lantern template screen)
|
||||
[7]: https://opensource.com/sites/default/files/uploads/lantern1.png (Object to path menu)
|
||||
[8]: https://opensource.com/sites/default/files/uploads/lantern2.png (Object > Difference menu)
|
||||
[9]: https://opensource.com/sites/default/files/uploads/lantern3.png (Object to path menu)
|
||||
[10]: https://opensource.com/sites/default/files/uploads/lantern4.png (Text tool)
|
||||
[11]: https://opensource.com/sites/default/files/uploads/lantern5.png (Text selected with Node editor)
|
||||
[12]: https://opensource.com/sites/default/files/uploads/lantern6.png (Overlapping the text)
|
||||
[13]: https://opensource.com/sites/default/files/uploads/lantern7.png (Connecting letters and base with Path > Union)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/lantern8.png (Setting fill and stroke)
|
||||
[15]: https://opensource.com/sites/default/files/uploads/lantern9.jpg (Cutting out the lantern)
|
||||
[16]: https://opensource.com/sites/default/files/uploads/lantern10.jpg (Adding tracing paper)
|
||||
[17]: https://opensource.com/sites/default/files/uploads/lantern11.jpg (Completed lantern)
|
@ -0,0 +1,158 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (robsean)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12082-1.html)
|
||||
[#]: subject: (Use the Fluxbox Linux desktop as your window manager)
|
||||
[#]: via: (https://opensource.com/article/19/12/fluxbox-linux-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
使用 Fluxbox 桌面作为你的窗口管理器
|
||||
======
|
||||
|
||||
> 本文是 24 天 Linux 桌面特别系列的一部分。Fluxbox 对系统资源的占用非常轻量,但它拥有重要的 Linux 桌面功能,让你的用户体验轻松、高效、快捷。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/07/113105p0ng5skkn5kmvdm0.jpg)
|
||||
|
||||
桌面的概念可谓是仁者见仁智者见智。很多人把桌面看作一个家的基地,或者一个舒适的客厅,甚至是一个字面意义上的桌面,在其中放置着他们经常使用的记事本、最好的笔和铅笔,还有他们最喜欢的咖啡杯。KDE、 GNOME、Pantheon 等等在 Linux 上提供了这种舒适的生活方式。
|
||||
|
||||
但是对一些用户来说,桌面只是一个空荡荡的显示器空间,这是还没有任何可以自由浮动的应用程序窗口直接投射到他们的视网膜上的副作用。对于这些用户来说,桌面是一个空的空间,他们可以在上面运行应用程序 —— 无论是大型办公软件和图形套件,还是一个简单的终端窗口,或是来管理服务的托盘小程序。这种操作 [POSIX][2] 计算机的模式由来已久,该家族树的一支是 *box 窗口管理器:Blackbox、Fluxbox 和 Openbox。
|
||||
|
||||
[Fluxbox][3] 是一个 X11 系统的窗口管理器,它基于一个较老的名为 Blackbox 的项目。当我发现 Linux 时,Blackbox 的开发已进入衰退期,因此我就喜欢上了 Fluxbox ,此后我至少在一个以上的常用的系统上使用过它。它是用 C++ 编写的,并在 MIT 开源许可证下授权。
|
||||
|
||||
### 安装 Fluxbox
|
||||
|
||||
你很可能会在你的 Linux 发行版的软件库中找到 Fluxbox,但是你也可以在 [Fluxbox.org][4] 上找到它。如果你正在运行另外一个桌面,在同一个系统上安装 Fluxbox 是安全的,因为 Fluxbox 不会预设任何配置或附带的应用程序。
|
||||
|
||||
在安装 Fluxbox 后,注销你当前的桌面会话,以便你可以登录一个新的桌面会话。默认情况下,你的桌面会话管理器 (KDM、GDM、LightDM 或 XDM,取决于你的安装设置) 将继续让登录到之前的桌面,所以你在登录前必需要覆盖上一个桌面。
|
||||
|
||||
使用 GDM 覆盖一个桌面:
|
||||
|
||||
![在 GDM 中选择你的桌面会话][5]
|
||||
|
||||
或者使用 KDM:
|
||||
|
||||
![使用 KDM 选择你的桌面会话][6]
|
||||
|
||||
### 配置 Fluxbox 桌面
|
||||
|
||||
当你第一次登录到桌面时,屏幕基本是空的,因为 Fluxbox 提供的所有东西是面板(用于任务栏、系统托盘等等)和用于应用程序窗口的窗口装饰品。
|
||||
|
||||
![在 CentOS 7 上的默认 Fluxbox 配置][7]
|
||||
|
||||
如果你的发行版提供一个简单的 Fluxbox 桌面,你可以使用 `feh` 命令(你可能需要从你的发行版的软件库中安装它)来为你的桌面设置背景。这个命令有几个用于设置背景的选项,包括使用你选择的墙纸来填充屏幕的 `--bg-fill` 选项,来按比例缩放的 `--bg-scale` 等等选项。
|
||||
|
||||
```
|
||||
$ feh --bg-fill ~/photo/oamaru/leaf-spiral.jpg
|
||||
```
|
||||
|
||||
![应用主题的 Fluxbox ][8]
|
||||
|
||||
默认情况下,Fluxbox 自动生成一个菜单,在桌面上任意位置右键单击可用该菜单,这给予你访问应用程序的能力。根据你的发行版的不同,这个菜单可能非常小,也可能列出 `/usr/share/applications` 目录中的所有启动程序。
|
||||
|
||||
Fluxbox 配置是在文本文件中设置的,这些文本文件包含在 `$HOME/.fluxbox` 目录中。你可以:
|
||||
|
||||
* 在 `keys` 中设置键盘快捷键
|
||||
* 在 `startup` 中启动的服务和应用程序
|
||||
* 在 `init` 设置桌面首选项(例如工作区数量、面板位置等等)
|
||||
* 在 `menu` 中设置菜单项
|
||||
|
||||
该文本配置文件非常易于推断,但是你也可以(并且是应该)阅读 Fluxbox 的[文档][9]。
|
||||
|
||||
例如,这是我的典型菜单(或者说至少有它的基本结构):
|
||||
|
||||
```
|
||||
# 为使用你自己的菜单,复制这些文本到 ~/.fluxbox/menu,然后编辑
|
||||
# ~/.fluxbox/init ,并更改 session.menuFile 文件路径到 ~/.fluxbox/menu
|
||||
|
||||
[begin] (fluxkbox)
|
||||
[submenu] (apps) {}
|
||||
[submenu] (txt) {}
|
||||
[exec] (Emacs 23 (text\)) { x-terminal-emulator -T "Emacs (text)" -e /usr/bin/emacs -nw} <>
|
||||
[exec] (Emacs (X11\)) {/usr/bin/emacs} <>
|
||||
[exec] (LibreOffice) {/usr/bin/libreoffice}
|
||||
[end]
|
||||
[submenu] (code) {}
|
||||
[exec] (qtCreator) {/usr/bin/qtcreator}
|
||||
[exec] (eclipse) {/usr/bin/eclipse}
|
||||
[end]
|
||||
[submenu] (graphics) {}
|
||||
[exec] (ksnapshot) {/usr/bin/ksnapshot}
|
||||
[exec] (gimp) {/usr/bin/gimp}
|
||||
[exec] (blender) {/usr/bin/blender}
|
||||
[end]
|
||||
[submenu] (files) {}
|
||||
[exec] (dolphin) {/usr/bin/dolphin}
|
||||
[exec] (konqueror) { /usr/bin/kfmclient openURL $HOME }
|
||||
[end]
|
||||
[submenu] (network) {}
|
||||
[exec] (firefox) {/usr/bin/firefox}
|
||||
[exec] (konqueror) {/usr/bin/konqueror}
|
||||
[end]
|
||||
[end]
|
||||
## 更改窗口管理器或工作环境
|
||||
[submenu] (environments) {}
|
||||
[restart] (flux) {/usr/bin/startfluxbox}
|
||||
[restart] (ratpoison) {/usr/bin/ratpoison}
|
||||
[exec] (openIndiana) {/home/kenlon/qemu/startSolaris.sh}
|
||||
[end]
|
||||
|
||||
[config] (config)
|
||||
[submenu] (styles) {}
|
||||
[stylesdir] (/usr/share/fluxbox/styles)
|
||||
[stylesdir] (~/.fluxbox/styles)
|
||||
[end]
|
||||
[workspaces] (workspaces)
|
||||
[reconfig] (reconfigure)
|
||||
[restart] (restart)
|
||||
[exit] (exeunt)
|
||||
[end]
|
||||
```
|
||||
|
||||
该菜单也提供一些首选项设置,例如,选择一个主题,从 Fluxbox 会话中重启或注销的能力。
|
||||
|
||||
我使用键盘快捷键来启动大多数的应用程序,这些快捷键写入到 `keys` 配置文件中。这里有一些示例(`Mod4` 按键是 `Super` 键,我使用其来指定全局快捷键):
|
||||
|
||||
```
|
||||
# 打开应用程序
|
||||
Mod4 t :Exec konsole
|
||||
Mod4 k :Exec konqueror
|
||||
Mod4 z :Exec fbrun
|
||||
Mod4 e :Exec emacs
|
||||
Mod4 f :Exec firefox
|
||||
Mod4 x :Exec urxvt
|
||||
Mod4 d :Exec dolphin
|
||||
Mod4 q :Exec xscreensaver-command -activate
|
||||
Mod4 3 :Exec ksnapshot
|
||||
```
|
||||
|
||||
在这些快捷方式和一个打开的终端之间,在我工作日的大部分时间内很少使用鼠标,因此从一个控制器切换到另一个控制器不会浪费时间。并且因为 Fluxbox 很好地避开了控制器之间切换的方法,因此在其中操作没有一丝干扰。
|
||||
|
||||
### 为什么你应该使用 Fluxbox
|
||||
|
||||
Fluxbox 对系统资源的占用非常轻量,但是它拥有重要的功能,可以使你的用户体验轻松、快速、高效。它很容易定制,并且允许你定义你自己的工作流。你不必使用 Fluxbox 的面板,因为还有其它优秀的面板。你甚至可以鼠标中键点击并拖动两个独立的应用程序窗口到彼此之中,以便它们成为一个窗口,每个窗口都有自己的选项卡。
|
||||
|
||||
可能性是无穷的,所以今天就在你的 Linux 上尝试一下 Fluxbox 的简单稳定吧!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/fluxbox-linux-desktop
|
||||
|
||||
作者:[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/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
|
||||
[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
|
||||
[3]: http://fluxbox.org
|
||||
[4]: http://fluxbox.org/download/
|
||||
[5]: https://opensource.com/sites/default/files/advent-gdm_0.jpg (Select your desktop session in GDM)
|
||||
[6]: https://opensource.com/sites/default/files/advent-kdm.jpg (Select your desktop session with KDM)
|
||||
[7]: https://opensource.com/sites/default/files/advent-fluxbox-default.jpg (Default Fluxbox configuration on CentOS 7)
|
||||
[8]: https://opensource.com/sites/default/files/advent-fluxbox-green.jpg (Fluxbox with a theme applied)
|
||||
[9]: http://fluxbox.org/features/
|
@ -0,0 +1,103 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12123-1.html)
|
||||
[#]: subject: (Relive Linux history with the ROX desktop)
|
||||
[#]: via: (https://opensource.com/article/19/12/linux-rox-desktop)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
用 ROX 桌面重温 Linux 历史
|
||||
======
|
||||
|
||||
> 这篇文章是 Linux 桌面 24 天特别系列的一部分。如果你想来一次有趣的时光之旅,ROX 桌面非常值得一试。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/18/151533n196wag64gwhs0ga.jpg)
|
||||
|
||||
[ROX][2] 桌面已经不再积极开发,而它的遗留问题至今仍然存在,但即使在它活跃开发的时候,它也是一个另类的 Linux 桌面。当其他的桌面感觉与旧式的 Unix 或 Windows 界面大致相似时,ROX 则属于 BeOS、AmigaOS 和 [RISC OS][3] 桌面阵营。
|
||||
|
||||
它专注于拖放式操作(这使得它的可访问性对某些用户来说并不理想)、点击式操作、弹出式上下文菜单,以及一个独特的应用程序目录系统,无需安装即可运行本地应用程序。
|
||||
|
||||
### 安装 ROX
|
||||
|
||||
如今,ROX 基本上都被遗弃了,只剩下一点残渣碎片留给用户自己去收集整理。幸运的是,这个难题相对来说比较容易解决,但是当你在发行版的软件仓库中找到 ROX 桌面的碎片时,不要被迷惑了,因为那并不是 ROX 桌面全部的碎片。ROX 常用的部分 —— 文件管理器([ROX-Filer][4])和终端([ROXTerm][5]) —— 似乎在大多数流行的发行版软件仓库中都有存在,你可以将它们作为独立的应用程序安装(并使用)。然而,要运行 ROX 桌面,你必须同时安装 ROX-Session 和它所依赖的库。
|
||||
|
||||
我在 Slackware 14.2 上安装了 ROX,但它应该可以在任何 Linux 或 BSD 系统上运行。
|
||||
|
||||
首先,你必须从其版本库中安装 [ROX-lib2][6]。你要安装 ROX-lib2,按照它的理念,只需下载tarball、[解压][7],然后将 `ROX-lib` 目录移动到 `/usr/local/lib` 下就行。
|
||||
|
||||
接下来,你要安装 [ROX-Session][8]。这可能需要从源码中编译,因为它很可能不在你的软件仓库中。编译过程需要编译工具,这些工具在 Slackware 上是默认提供的,但在其他发行版中往往会被省略,以节省初始下载空间。根据你的发行版不同,你必须安装的包的名称也不同,所以请参考文档来了解具体内容。例如,在 Debian 发行版中,你可以在 [Debian 的 wiki][9] 中了解构建需求,而在 Fedora 发行版中,请参考 [Fedora 的文档][10]。安装了构建工具后,执行自定义的 ROX-Session 构建脚本。
|
||||
|
||||
```
|
||||
$ ./AppRun
|
||||
```
|
||||
|
||||
这个脚本会自己管理构建和安装,并提示你需要 root 权限,以在你的登录屏上将其添加为一个选项。
|
||||
|
||||
如果你还没有从你的软件库中安装 ROX-Filer,请在继续之前安装。
|
||||
|
||||
这些组件共同组成了一个完整的 ROX 桌面。要登录到新桌面,请从当前桌面会话中注销。默认情况下,你的会话管理器(KDM、GDM、LightDM 或 XDM,视你的设置而定)会继续登录到你之前的桌面,所以在登录前必须覆盖。
|
||||
|
||||
使用 SDDM:
|
||||
|
||||
![][11]
|
||||
|
||||
使用 GDM:
|
||||
|
||||
![][12]
|
||||
|
||||
### ROX 桌面特性
|
||||
|
||||
ROX 桌面默认情况下很简单,屏幕底部有一个面板,桌面上有一个通往主目录的快捷方式图标。面板中包含了一些常用位置的快捷方式。这就是 ROX 桌面的全部功能,至少在安装后就是这样。如果你想要时钟、日历或系统托盘,你需要找到提供这些功能的应用程序。
|
||||
|
||||
![Default ROX desktop][13]
|
||||
|
||||
虽然没有任务栏,但当你将窗口最小化时,它就会成为桌面上的一个临时图标。你可以点击该图标,将其窗口恢复到以前的大小和位置。
|
||||
|
||||
面板也可以进行一些修改。你可以在其中放置不同的快捷方式,甚至可以创建自己的小程序。
|
||||
|
||||
它没有应用菜单,也没有上下文菜单中的应用快捷方式。相反,你可以手动导航到 `/usr/share/applications`,或者你可以将你的应用目录或目录添加到 ROX 面板中。
|
||||
|
||||
![ROX desktop][14]
|
||||
|
||||
ROX 桌面的工作流程集中在鼠标驱动上,让人联想到 Mac OS 7.5 和 8 系统。通过 ROX-filer,你可以管理权限、文件管理、<ruby>内省<rt>introspection</rt></ruby>、脚本启动、后台设置,以及几乎所有你能想到的东西,只要你有足够的耐心,就可以实现点击式的交互。对于高级用户来说,这似乎很慢,但 ROX 设法让它变得相对无痛,而且非常直观。
|
||||
|
||||
### 应用程序目录、AppRun 和 AppImage
|
||||
|
||||
ROX 桌面有一个优雅的惯例,按照此惯例,包含一个名为 `AppRun` 的脚本的目录就可以像一个应用程序一样被执行。这意味着,要制作一个 ROX 应用程序,你所要做的就是将代码编译到一个目录中,将一个名为`AppRun` 的脚本放在该目录的根目录下,来执行你所编译的二进制文件,然后将该目录标记为可执行即可。ROX-Filer 会按照你设置的方式来显示一个目录,并以特殊的图标和颜色显示一个目录。当你点击一个应用程序目录,ROX-Filer 会自动运行里面的 `AppRun` 脚本。它的外观和行为就像一个已经安装好的应用程序,但它是在用户的主目录下的本地目录,不需要特殊的权限。
|
||||
|
||||
这是一个方便的功能,但它是那些你使用时感觉很好的小功能之一,因为它很容易做到。它绝不是必要的,它只是比在本地建立一个应用程序,将目录隐藏在某个不显眼的地方,并建立一个快速的 `.desktop` 文件作为你的启动器,要领先了几步。然而,应用程序目录的概念已经当做灵感被 [AppImage][16] 打包系统所 [借鉴][15]。
|
||||
|
||||
### 为什么应该试试 ROX 桌面
|
||||
|
||||
把 ROX 设置好并使用是有些困难的,它似乎真的被抛弃了。然而,它的遗产在今天以多种方式继续存在,它是 Linux 历史上的一段迷人而有趣的历史。它可能不会成为你的主要桌面,但如果你想来一次有趣的回溯之旅,那么 ROX 非常值得一试。探索它、定制它,看看它包含了哪些巧妙的想法。也许还有一些隐藏的宝石可以让开源社区受益。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/12/linux-rox-desktop
|
||||
|
||||
作者:[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/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
|
||||
[2]: http://rox.sourceforge.net/desktop/
|
||||
[3]: https://www.riscosopen.org/content/
|
||||
[4]: http://rox.sourceforge.net/desktop/ROX-Filer
|
||||
[5]: http://roxterm.sourceforge.net/
|
||||
[6]: http://rox.sourceforge.net/desktop/ROX-Lib
|
||||
[7]: https://opensource.com/article/17/7/how-unzip-targz-file
|
||||
[8]: http://rox.sourceforge.net/desktop/ROX-Session.html
|
||||
[9]: https://wiki.debian.org/BuildingTutorial
|
||||
[10]: https://docs.pagure.org/docs-fedora/installing-software-from-source.html
|
||||
[11]: https://opensource.com/sites/default/files/advent-kdm_0.jpg
|
||||
[12]: https://opensource.com/sites/default/files/advent-gdm_1.jpg
|
||||
[13]: https://opensource.com/sites/default/files/uploads/advent-rox.jpg (Default ROX desktop)
|
||||
[14]: https://opensource.com/sites/default/files/uploads/advent-rox-custom.jpg (ROX desktop)
|
||||
[15]: https://github.com/AppImage/AppImageKit/wiki/AppDir
|
||||
[16]: https://appimage.org/
|
@ -0,0 +1,68 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12161-1.html)
|
||||
[#]: subject: (The Difference Between DNF and YUM, Why is Yum Replaced by DNF?)
|
||||
[#]: via: (https://www.2daygeek.com/comparison-difference-between-dnf-vs-yum/)
|
||||
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
|
||||
|
||||
DNF 和 Yum 的区别,为什么 Yum 会被 DNF 取代?
|
||||
======
|
||||
|
||||
由于 Yum 中许多长期存在的问题仍未得到解决,因此 [Yum 包管理器][1]已被 [DNF 包管理器][2]取代。这些问题包括性能差、内存占用过多、依赖解析速度变慢等。
|
||||
|
||||
DNF 使用 `libsolv` 进行依赖解析,由 SUSE 开发和维护,旨在提高性能。
|
||||
|
||||
Yum 主要是用 Python 编写的,它有自己的应对依赖解析的方法。它的 API 没有完整的文档,它的扩展系统只允许 Python 插件。
|
||||
|
||||
Yum 是 RPM 的前端工具,它管理依赖关系和资源库,然后使用 RPM 来安装、下载和删除包。
|
||||
|
||||
为什么他们要建立一个新的工具,而不是修复现有的问题呢?
|
||||
|
||||
Ales Kozamblak 解释说,这个修复在技术上是不可行的,而且 Yum 团队还没有准备好立即接受修改。
|
||||
|
||||
另外,最大的挑战是,Yum 有 56000 行代码,但 DNF 只有 29000 行代码。
|
||||
|
||||
所以除了分叉,没有办法解决。
|
||||
|
||||
不过 Yum 的运行情况还算可以。
|
||||
|
||||
|
||||
编号 | DNF(Dandified YUM) | YUM(Yellowdog Updater, Modified)
|
||||
---|---|---
|
||||
1 | DNF 使用 libsolv 来解析依赖关系,由 SUSE 开发和维护 | YUM 使用公开的 API 来解析依赖关系
|
||||
2 | API 有完整的文档 | API 没有完整的文档
|
||||
3 | 由 C、C++、Python 编写的 | 只用 Python 编写
|
||||
4 | DNF 目前在 Fedora、RHEL 8、CentOS 8、OEL 8 和 Mageia 6/7 中使用 | YUM 目前在 RHEL 6/7、CentOS 6/7、OEL 6/7 中使用
|
||||
5 | DNF 支持各种扩展 | Yum 只支持基于 Python 的扩展
|
||||
6 | API 有良好的文档,因此很容易创建新的功能 | 因为 API 没有正确的文档化,所以创建新功能非常困难
|
||||
7 | DNF 在同步存储库的元数据时,使用的内存较少 | 在同步存储库的元数据时,YUM 使用了过多的内存
|
||||
8 | DNF 使用满足性算法来解决依赖关系解析(它是用字典的方法来存储和检索包和依赖信息)| 由于使用公开 API 的原因,Yum 依赖性解析变得迟钝
|
||||
9 | 从内存使用量和版本库元数据的依赖性解析来看,性能都不错 | 总的来说,在很多因素的影响下,表现不佳
|
||||
10 | DNF 更新:在 DNF 更新过程中,如果包中包含不相关的依赖,则不会更新 | YUM 将在没有验证的情况下更新软件包
|
||||
11 | 如果启用的存储库没有响应,DNF 将跳过它,并继续使用可用的存储库处理事务 | 如果有存储库不可用,YUM 会立即停止
|
||||
12 | `dnf update` 和 `dnf upgrade` 是等价的 | 在 Yum 中则不同
|
||||
13 | 安装包的依赖关系不更新 | Yum 为这种行为提供了一个选项
|
||||
14 | 清理删除的包:当删除一个包时,DNF 会自动删除任何没有被用户明确安装的依赖包 | Yum 不会这样做
|
||||
15 | 存储库缓存更新计划:默认情况下,系统启动后 10 分钟后,DNF 每小时会对配置的存储库检查一次更新。这个动作由系统定时器单元 `dnf-makecache.timer` 控制 | Yum 也会这样做
|
||||
16 | 内核包不受 DNF 保护。不像 Yum,你可以删除所有的内核包,包括运行中的内核包 | Yum 不允许你删除运行中的内核
|
||||
17 | libsolv:用于解包和读取资源库。hawkey: 为 libsolv 提供简化的 C 和 Python API 库。librepo: 提供 C 和 Python(类似 libcURL)API 的库,用于下载 Linux 存储库元数据和软件包。libcomps: 是 yum.comps 库的替代品。它是用纯 C 语言编写的库,有 Python 2 和 Python 3 的绑定。| Yum 不使用单独的库来执行这些功能
|
||||
18 | DNF 包含 29000 行代码 | Yum 包含 56000 行代码
|
||||
19 | DNF 由 Ales Kozumplik 开发 | YUM 由 Zdenek Pavlas、Jan Silhan 和团队成员开发
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/comparison-difference-between-dnf-vs-yum/
|
||||
|
||||
作者:[Magesh Maruthamuthu][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.2daygeek.com/author/magesh/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
|
||||
[2]: https://www.2daygeek.com/linux-dnf-command-examples-manage-packages-fedora-centos-rhel-systems/
|
@ -1,27 +1,28 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (caiichenr)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12087-1.html)
|
||||
[#]: subject: (Why your Python code should be flat and sparse)
|
||||
[#]: via: (https://opensource.com/article/19/12/zen-python-flat-sparse)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
|
||||
为何你的 Python 代码应是扁平与稀疏的
|
||||
======
|
||||
本文是 Python 之禅特别系列当中的一篇,此篇着眼于其中第五与第六条原则:扁平与稀疏。
|
||||
![Digital creative of a browser on the internet][1]
|
||||
|
||||
[Python之禅][2] 得名如此,正是由于它那简明扼要的规则被设计出的意图在于让读者进行深入地思考,而绝不单是为编程提供一份易于遵守的指南。
|
||||
> 本文是 Python 之禅特别系列的第三篇,此篇着眼于其中第五与第六条原则:扁平与稀疏。
|
||||
|
||||
读后不去三思其意,断然难以体会 Python 之禅的妙处。倘若 Python 之禅仅仅罗列出一组清晰的法则,那法则之间的矛盾只能算作一种错误。然而用作引导读者去为最优方案沉思的工具,矛盾却是绝佳的。
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/08/191645uiniiy56keig95gi.jpg)
|
||||
|
||||
### 扁平胜过嵌套 Flat is better than nested.
|
||||
[Python 之禅][2] 之所以得名,正是由于它那简明扼要的规则被设计出的意图在于让读者进行深入地思考,而绝不单是为编程提供一份易于遵守的指南。
|
||||
|
||||
迫于对缩进的强硬要求,Python 对“扁平化”的需求显然远超它者。其余编程语言为了缓解对缩进的需求,通常会在嵌套结构里加入一种“欺诈”的手段。用以说明此点,不妨一同看看JavaScript。
|
||||
读后不去三思其意,断然难以体会 Python 之禅的妙处。倘若 Python 之禅仅仅罗列出一组清晰的法则,那法则之间的矛盾是一种缺憾,然而作为引导读者沉思最优方案沉思的工具,矛盾却是绝佳的。
|
||||
|
||||
JavaScript 是原生异步的,这意味着程序员用 JavaScript 写的代码会用到大量的回调函数。
|
||||
### <ruby>扁平胜过嵌套<rt>Flat is better than nested</rt></ruby>
|
||||
|
||||
迫于对缩进的强硬要求,Python 对“扁平化”的需求显然远超它者。其余编程语言为了缓解对缩进的需求,通常会在嵌套结构里加入一种“作弊”的手段。为了理解这一点,不妨一同来看看 JavaScript。
|
||||
|
||||
JavaScript 本质上是异步的,这意味着程序员用 JavaScript 写的代码会用到大量的回调函数。
|
||||
|
||||
```
|
||||
a(function(resultsFromA) {
|
||||
@ -33,8 +34,7 @@ a(function(resultsFromA) {
|
||||
}
|
||||
```
|
||||
|
||||
忽略这段代码的具体内容,只去观察这段代码的形状与缩进带来极右点的方式。这种独特的“箭头”图形在我们扫看代码时格外扎眼,这种写法也因此被视作不可取,甚至得到了“回调地狱”的绰号。不过,在 JavaScript 中,这种反映嵌套关系的缩进可以通过“欺诈”来回避。
|
||||
|
||||
忽略这段代码的具体内容,只去观察这段代码的形状与缩进带来一个最右边的点的方式。这种独特的“箭头”图形在我们扫看代码时格外扎眼,这种写法也因此被视作不可取,甚至得到了“回调地狱”的绰号。不过,在 JavaScript 中,这种反映嵌套关系的缩进可以通过“作弊”来回避。
|
||||
|
||||
```
|
||||
a(function(resultsFromA) {
|
||||
@ -46,10 +46,9 @@ c(resultsFromC,
|
||||
}}}
|
||||
```
|
||||
|
||||
Python 并没有提供这种欺诈手段:每一级嵌套在代码中都如实的对应着一层缩进。因此,Python 深层的嵌套关系在_视觉_上也一定是深层嵌套的。这使得“回调地狱”的问题对于 Python 而言要比在 JavaScript 中严重得多:嵌套的回调函数必定带来缩进,而绝无使用花括号来“欺诈”的可能。
|
||||
|
||||
这项挑战与 Python 之禅的指导原则相结合后,在我参与的库中催生出了一个优雅的解决方案。我们在 [Twisted][3] 框架里提出了 _deferred_ 抽象,日后 JavaScript 中流行的 _promise_ 抽象亦是受其启发而生。正是由于 Python 对整洁代码的坚守,方能推动 Python 开发者去发掘新的,强力的抽象。
|
||||
Python 并没有提供这种作弊手段:每一级嵌套在代码中都如实的对应着一层缩进。因此,Python 深层的嵌套关系在*视觉*上也一定是深层嵌套的。这使得“回调地狱”的问题对于 Python 而言要比在 JavaScript 中严重得多:嵌套的回调函数必定带来缩进,而绝无使用花括号来“作弊”的可能。
|
||||
|
||||
这项挑战与 Python 之禅的指导原则相结合后,在我参与的库中催生出了一个优雅的解决方案。我们在 [Twisted][3] 框架里提出了 deferred 抽象,日后 JavaScript 中流行的 promise 抽象亦是受其启发而生。正是由于 Python 对整洁代码的坚守,方能推动 Python 开发者去发掘新的、强力的抽象。
|
||||
|
||||
```
|
||||
future_value = future_result()
|
||||
@ -58,11 +57,11 @@ future_value.addCallback(b)
|
||||
future_value.addCallback(c)
|
||||
```
|
||||
|
||||
(现代 JavaScript 程序员也许会觉得这段代码十分眼熟:Promises 着实受到了 Twisted 里 deferreds 抽象的深远影响。)
|
||||
(现代 JavaScript 程序员也许会觉得这段代码十分眼熟:promise 着实受到了 Twisted 里 deferred 抽象的深远影响。)
|
||||
|
||||
### 稀疏胜过密集 Sparse is better than dense.
|
||||
### <ruby>稀疏胜过密集<rt>Sparse is better than dense</rt></ruby>
|
||||
|
||||
最易降低代码密集程度的方法是引入嵌套。这种习惯也正是有关稀疏的原则要随着前一条提出的原因:在竭尽所能地降低代码密集性之后,我们往往会遗留下_密集_的代码或数据结构。此处的密集,是指塞进过量信息的小段代码,它们会导致错误发生后的解析变得困难。
|
||||
最易降低代码密集程度的方法是引入嵌套。这种习惯也正是有关稀疏的原则要随着前一条提出的原因:在竭尽所能地减少嵌套之后,我们往往会遗留下*密集的*代码或数据结构。此处的密集,是指塞进过量信息的小段代码,它们会导致错误发生后的解析变得困难。
|
||||
|
||||
这种密集性唯有通过创造性的思考方可改善,此外别无捷径。Python 之禅并不为我们提供简单的解决方案,它只会指明改善代码的方向,而非提供“如何”去做的向导。
|
||||
|
||||
@ -75,7 +74,7 @@ via: https://opensource.com/article/19/12/zen-python-flat-sparse
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[caiichenr](https://github.com/caiichenr)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
172
published/202004/20200211 Navigating man pages in Linux.md
Normal file
172
published/202004/20200211 Navigating man pages in Linux.md
Normal file
@ -0,0 +1,172 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12127-1.html)
|
||||
[#]: subject: (Navigating man pages in Linux)
|
||||
[#]: via: (https://www.networkworld.com/article/3519853/navigating-man-pages-in-linux.html)
|
||||
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
|
||||
|
||||
在 Linux 中遨游手册页的海洋
|
||||
======
|
||||
|
||||
> Linux 系统上的手册页可以做的不仅仅是提供特定命令的信息。它们可以帮助你发现你没有意识到的命令。
|
||||
|
||||
![Hello I'm Nik][1]
|
||||
|
||||
手册页提供了关于 Linux 命令的基本信息,很多用户经常参考它,但手册页的内容比我们很多人意识到的要多得多。
|
||||
|
||||
你总是可以输入一个像 `man who` 这样的命令,然后得到 `who` 命令的工作原理的漂亮描述,但是探索你可能不知道的命令可能会更有启发。例如,你可以使用 `man` 命令来帮助找到一些处理非常具有挑战性的任务的命令,或者显示一些选项,这些选项可以帮助你以新的更好的方式使用你已经知道的命令。
|
||||
|
||||
让我们来浏览一些选项,看看最终的结果是什么。
|
||||
|
||||
### 用 man 去识别命令
|
||||
|
||||
`man` 命令可以帮助你按主题查找命令。例如,如果你要找一个计算文件中的行数的命令,你可以提供一个关键字。在下面的例子中,我们把关键字 “count” 放在了引号中,并添加了空格,这样我们就不会得到与 “accounts” 或 “accounting” 相关的命令,而是得到那些可以为我们做一些计算的命令。
|
||||
|
||||
```
|
||||
$ man -k ' count '
|
||||
anvil (8postfix) - Postfix session count and request rate control
|
||||
cksum (1) - checksum and count the bytes in a file
|
||||
sum (1) - checksum and count the blocks in a file
|
||||
timer_getoverrun (2) - get overrun count for a POSIX per-process timer
|
||||
```
|
||||
|
||||
为了显示与新用户账户相关的命令,我们可以尝试使用这样的命令。
|
||||
|
||||
```
|
||||
$ man -k "new user"
|
||||
newusers (8) - update and create new users in batch
|
||||
useradd (8) - create a new user or update default new user information
|
||||
zshroadmap (1) - informal introduction to the zsh manual The Zsh Manual, …
|
||||
```
|
||||
|
||||
需要说明的是,上面的第三项只是提到 “new users” 类似的内容,并不是设置、删除或配置用户账号的命令。`man` 命令只是在命令描述中匹配了一些词,作用很像 `apropos` 命令。注意上面列出的每个命令后面的括号中的数字。这些数字与包含这些命令的手册页的分区有关。
|
||||
|
||||
### 确定手册页的分区
|
||||
|
||||
`man` 命令的分区将其内容划分为不同的类别。要列出这些类别,请键入 `man man`,并查看类似下面的描述。你的系统中很可能没有第 9 分区的命令。
|
||||
|
||||
- `1`:可执行程序或 shell 命令
|
||||
- `2`:系统调用(内核提供的函数)
|
||||
- `3`:库调用(程序库内的函数)
|
||||
- `4`:特殊文件(通常在可以 `/dev` 中找到)
|
||||
- `5`:文件格式和惯例,例如 `/etc/passwd`
|
||||
- `6`:游戏
|
||||
- `7`:杂项(包括宏包和约定),例如 `man`(7)、`groff`(7)
|
||||
- `8`:系统管理命令(通常只由 root 用户使用)
|
||||
- `9`:内核例程(非标准)
|
||||
|
||||
手册页涵盖了比我们通常认为的“命令”更多的内容。从上面的描述中可以看到,它们涵盖了系统调用、库调用、特殊文件等等。
|
||||
|
||||
下面的列表显示了 Linux 系统中的手册页的实际存储位置。这些目录上的日期会有所不同,因为随着更新,其中一些分区会有新的内容,而另一些则不会。
|
||||
|
||||
```
|
||||
$ ls -ld /usr/share/man/man?
|
||||
drwxr-xr-x 2 root root 98304 Feb 5 16:27 /usr/share/man/man1
|
||||
drwxr-xr-x 2 root root 65536 Oct 23 17:39 /usr/share/man/man2
|
||||
drwxr-xr-x 2 root root 270336 Nov 15 06:28 /usr/share/man/man3
|
||||
drwxr-xr-x 2 root root 4096 Feb 4 10:16 /usr/share/man/man4
|
||||
drwxr-xr-x 2 root root 28672 Feb 5 16:25 /usr/share/man/man5
|
||||
drwxr-xr-x 2 root root 4096 Oct 23 17:40 /usr/share/man/man6
|
||||
drwxr-xr-x 2 root root 20480 Feb 5 16:25 /usr/share/man/man7
|
||||
drwxr-xr-x 2 root root 57344 Feb 5 16:25 /usr/share/man/man8
|
||||
```
|
||||
|
||||
注意,为了节省空间,手册页文件一般都是 gzip 压缩的。每当你使用 `man` 命令时,`man` 命令会根据需要解压。
|
||||
|
||||
```
|
||||
$ ls -l /usr/share/man/man1 | head -10
|
||||
total 12632
|
||||
lrwxrwxrwx 1 root root 9 Sep 5 06:38 [.1.gz -> test.1.gz
|
||||
-rw-r--r-- 1 root root 563 Nov 7 05:07 2to3-2.7.1.gz
|
||||
-rw-r--r-- 1 root root 592 Apr 23 2016 411toppm.1.gz
|
||||
-rw-r--r-- 1 root root 2866 Aug 14 10:36 a2query.1.gz
|
||||
-rw-r--r-- 1 root root 2361 Sep 9 15:13 aa-enabled.1.gz
|
||||
-rw-r--r-- 1 root root 2675 Sep 9 15:13 aa-exec.1.gz
|
||||
-rw-r--r-- 1 root root 1142 Apr 3 2018 aaflip.1.gz
|
||||
-rw-r--r-- 1 root root 3847 Aug 14 10:36 ab.1.gz
|
||||
-rw-r--r-- 1 root root 2378 Aug 23 2018 ac.1.gz
|
||||
```
|
||||
|
||||
### 按分区列出的手册页
|
||||
|
||||
即使只看第 1 分区的前 10 个手册页(如上所示),你也可能会看到一些新的命令 —— 也许是 `a2query` 或 `aaflip`(如上所示)。
|
||||
|
||||
探索命令的更好策略是按分区列出命令,不查看文件本身,而是使用 `man` 命令向你显示命令并提供每个命令的简要说明。
|
||||
|
||||
在下面的命令中,`-s 1` 指示 `man` 显示第 1 分区中的命令信息。`-k .` 使该命令对所有命令都有效,而不是指定一个特定的关键字;如果没有这个,`man` 命令就会回过头来问:“你想要什么手册页?”所以,使用关键字来选择一组相关的命令,或者使用点来显示一个分区中的所有命令。
|
||||
|
||||
```
|
||||
$ man -s 1 -k .
|
||||
2to3-2.7 (1) - Python2 to Python3 converter
|
||||
411toppm (1) - convert Sony Mavica .411 image to ppm
|
||||
as (1) - the portable GNU assembler.
|
||||
baobab (1) - A graphical tool to analyze disk usage
|
||||
busybox (1) - The Swiss Army Knife of Embedded Linux
|
||||
cmatrix (1) - simulates the display from "The Matrix"
|
||||
expect_dislocate (1) - disconnect and reconnect processes
|
||||
red (1) - line-oriented text editor
|
||||
enchant (1) - a spellchecker
|
||||
…
|
||||
```
|
||||
|
||||
### 有多少手册页?
|
||||
|
||||
如果你对每个分区中有多少手册页感到好奇,可以使用以下命令按分区对它们进行计数:
|
||||
|
||||
```
|
||||
$ for num in {1..8}
|
||||
> do
|
||||
> man -s $num -k . | wc -l
|
||||
> done
|
||||
2382
|
||||
493
|
||||
2935
|
||||
53
|
||||
441
|
||||
11
|
||||
245
|
||||
919
|
||||
```
|
||||
|
||||
确切的数量可能有所不同,但是大多数 Linux 系统的命令数量差不多。如果我们使用命令将这些数字加在一起,我们可以看到运行该命令的系统上有将近 7500 个手册页。有很多命令,系统调用等。
|
||||
|
||||
```
|
||||
$ for num in {1..8}
|
||||
> do
|
||||
> num=`man -s $num -k . | wc -l`
|
||||
> tot=`expr $num + $tot`
|
||||
> echo $tot
|
||||
> done
|
||||
2382
|
||||
2875
|
||||
5810
|
||||
5863
|
||||
6304
|
||||
6315
|
||||
6560
|
||||
7479 <=== total
|
||||
```
|
||||
|
||||
阅读手册页可以学到很多东西,但是以其他方式浏览手册页可以帮助你了解系统上可能不知道的命令。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3519853/navigating-man-pages-in-linux.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/2019/10/field-note_play-book_playbook_map_navigation_journey_by-hello-i-m-nik-via-unsplash-100813507-large.jpg
|
||||
[2]: https://creativecommons.org/publicdomain/zero/1.0/
|
||||
[3]: https://www.networkworld.com/slideshow/153439/linux-best-desktop-distros-for-newbies.html#tk.nww-infsb
|
||||
[4]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
|
||||
[5]: https://www.facebook.com/NetworkWorld/
|
||||
[6]: https://www.linkedin.com/company/network-world
|
@ -0,0 +1,173 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12156-1.html)
|
||||
[#]: subject: (Manage complex Git workspaces with Great Teeming Workspaces)
|
||||
[#]: via: (https://opensource.com/article/20/2/git-great-teeming-workspaces)
|
||||
[#]: author: (Daniel Gryniewicz https://opensource.com/users/dang)
|
||||
|
||||
使用 GTWS 管理复杂的 Git 工作空间
|
||||
======
|
||||
|
||||
> GTWS 是一系列脚本,它使我们在开发环境中管理不同的项目和项目的各个版本变得很容易。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/27/182149xh9s7kb5bkf5875b.jpg)
|
||||
|
||||
[Great Teeming Workspaces][2](GTWS)是一个 Git 的复杂工作空间管理工具包,它使我们在开发环境中管理不同的项目和项目的各个版本变得很容易。
|
||||
|
||||
有点像 Python 的 [venv][3],但不是为 Python 语言准备的。GTWS 用来管理多个项目的多个版本的工作空间。你可以很容易地创建、更新、进入和离开工作空间,每个项目或版本的组合(最多)有一个本地的 origin,用来与 upstream 同步 — 其余的所有工作空间都从本地的 origin 更新。
|
||||
|
||||
### 部署
|
||||
|
||||
```
|
||||
${GTWS_ORIGIN}/<project>/<repo>[/<version>]
|
||||
${GTWS_BASE_SRCDIR}/<project>/<version>/<workspacename>/{<repo>[,<repo>...]}
|
||||
```
|
||||
|
||||
源代码目录的每一级(包括全局的家目录)可以包含一个 `.gtwsrc` 文件,这个文件中维护与当前级相关的设置和 bash 代码。每一级的配置会覆盖上一级。
|
||||
|
||||
### 安装
|
||||
|
||||
用下面的命令检出 GTWS:
|
||||
|
||||
```
|
||||
git clone https://github.com/dang/gtws.git
|
||||
```
|
||||
|
||||
配置你的 `${HOME}/.gtwsrc`。它应该包含 `GTWS_ORIGIN`,也可以再包含 `GTWS_SETPROMPT`。
|
||||
|
||||
把仓库目录加到环境变量中:
|
||||
|
||||
```
|
||||
export PATH="${PATH}:/path/to/gtws
|
||||
```
|
||||
|
||||
### 配置
|
||||
|
||||
通过级联 `.gtwsrc` 文件来进行配置。它从根目录向下遍历,会执行在每级目录中找到的 `.gtwsrc` 文件。下级目录的文件会覆盖上一级。
|
||||
|
||||
在你最上层的文件 `~/.gtws/.gtwsrc` 中进行如下设置:
|
||||
|
||||
* `GTWS_BASE_SRCDIR`:所有项目源文件目录树的基目录。默认为 `$HOME/src`。
|
||||
* `GTWS_ORIGIN`: 指定 origin git 目录树的路径。默认为 `$HOME/origin`。
|
||||
* `GTWS_SETPROMPT`: 可选配置。如果配置了这个参数,shell 提示符会有工作空间的名字。
|
||||
* `GTWS_DEFAULT_PROJECT`: 不指定项目或项目未知时默认的项目名。如果不指定,使用命令行时必须指明项目。
|
||||
* `GTWS_DEFAULT_PROJECT_VERSION`: 检出的默认版本。默认为 `master`。
|
||||
|
||||
在每个项目的根目录进行以下设置:
|
||||
|
||||
* `GTWS_PROJECT`: 项目的名字(和基目录)。
|
||||
* `gtws_project_clone`: 这个函数用于克隆一个项目的指定版本。如果未定义,它会假定项目的 origin 对每一个版本都有一个单独的目录,这样会导致克隆一堆 Git 仓库。
|
||||
* `gtws_project_setup`: 在克隆完所有的仓库后,可以选择是否调用这个函数,调用后可以对项目进行必要的配置,如在 IDE 中配置工作空间。
|
||||
|
||||
在项目版本级进行以下设置:
|
||||
|
||||
* `GTWS_PROJECT_VERSION:` 项目的版本。用于正确地从 origin 拉取代码。类似 Git 中的分支名字。
|
||||
|
||||
下面这些参数可以在目录树的任意地方进行配置,如果能生效,它们可以被重写多次:
|
||||
|
||||
* `GTWS_PATH_EXTRA`: 这些是工作空间中加到路径后的额外的路径元素。
|
||||
* `GTWS_FILES_EXTRA`: 这些是不在版本控制内,但应该在工作空间中被检出的额外的文件。这些文件包括 `.git/info/exclude`,每个文件都与仓库的基目录相关联。
|
||||
|
||||
### origin 目录
|
||||
|
||||
`GTWS_ORIGIN` (大部分脚本中)指向拉取和推送的原始 Git 检出目录。
|
||||
|
||||
`${GTWS_ORIGIN}` 部署:
|
||||
|
||||
* `/<project>`
|
||||
* 这是一个项目的仓库的基目录。
|
||||
* 如果指定了 `gtws_project_clone`,你可以配置任意的部署路径。
|
||||
* 如果没有指定 `gtws_project_clone`,这个路径下必须有个名为 `git` 的子目录,且 `git` 目录下有一系列用来克隆的裸 Git 仓库。
|
||||
|
||||
### 工作流示例
|
||||
|
||||
假设你有一个项目名为 `Foo`,它的 upstream 为 `github.com/foo/foo.git`。这个仓库有个名为 `bar` 的子模块,它的 upstream 是 `github.com/bar/bar.git`。Foo 项目在 master 分支开发,使用稳定版本的分支。
|
||||
|
||||
为了能在 Foo 中使用 GTWS,你首先要配置目录结构。本例中假设你使用默认的目录结构。
|
||||
|
||||
* 配置你最上层的 `.gtwsrc`:
|
||||
* `cp ${GTWS_LOC}/examples/gtwsrc.top ~/.gtwsrc`
|
||||
* 根据需要修改 `~/.gtwsrc`。
|
||||
* 创建顶级目录:
|
||||
* `mkdir -p ~/origin ~/src`
|
||||
* 创建并配置项目目录:
|
||||
* `mkdir -p ~/src/foo`
|
||||
|
||||
`cp ${GTWS_LOC}/examples/gtwsrc.project ~/src/foo/.gtwsrc`
|
||||
* 根据需要修改 `~/src/foo/.gtwsrc`。
|
||||
* 创建并配置 master 版本目录:
|
||||
* `mkdir -p ~/src/foo/master`
|
||||
|
||||
`cp ${GTWS_LOC}/examples/gtwsrc.version ~/src/foo/master/.gtwsrc`
|
||||
* 根据需要修改 `~/src/foo/master/.gtwsrc`。
|
||||
* 进入版本目录并创建一个临时工作空间来配置镜像:
|
||||
* `mkdir -p ~/src/foo/master/tmp`
|
||||
|
||||
`cd ~/src/foo/master/tmp`
|
||||
|
||||
`git clone --recurse-submodules git://github.com/foo/foo.git`
|
||||
|
||||
`cd foo`
|
||||
|
||||
`gtws-mirror -o ~/origin -p foo`(译注:这个地方原文有误,不加 `-s` 参数会报错)
|
||||
* 上面命令会创建 `~/origin/foo/git/foo.git` 和 `~/origin/foo/submodule/bar.git`。
|
||||
* 以后的克隆操作会从这些 origin 而不是 upstream 克隆。
|
||||
* 现在可以删除工作空间了。
|
||||
|
||||
到现在为止,Foo 的 master 分支的工作可以结束了。假设你现在想修复一个 bug,名为 `bug1234`。你可以脱离你当前的工作空间为修复这个 bug 单独创建一个工作空间,之后在新创建的工作空间中开发。
|
||||
|
||||
* 进入版本目录,创建一个新的工作空间:
|
||||
* `cd ~/src/foo/master`
|
||||
|
||||
`mkws bug1234`
|
||||
* 上面的命令创建了 `bug1234/`,在这个目录下检出了 Foo(和它的子模块 `bar`),并创建了 `build/foo` 来构建它。
|
||||
* 有两种方式进入工作空间:
|
||||
* `cd ~/src/foo/master/bug1234`
|
||||
|
||||
`startws`
|
||||
|
||||
或者
|
||||
|
||||
`cd ~/src/foo/master/`
|
||||
|
||||
`startws bug1234`
|
||||
* 上面的命令在 `bug1234` 工作空间中开启了一个子 shell。这个 shell 有 GTWS 的环境和你在各级 `.gtwsrc` 文件中设置的环境。它也把你工作空间的基目录加入到了 CD,因此你可以从 base 路径 `cd` 到相关的目录中。
|
||||
* 现在你可以修复 `bug1234` 了,构建、测试、提交你的修改。当你可以把代码推送到 upstream 时,执行下面的命令:
|
||||
|
||||
`cd foo`
|
||||
|
||||
`wspush`
|
||||
* `wspush` 会把代码推送到与你工作空间相关的分支 — 先推送到本地的 origin,再推送到 upstream。
|
||||
* 当 upstream 有修改时,你可以用下面的命令同步到本地:
|
||||
|
||||
`git sync`
|
||||
* 上面的命令调用了 GTWS 的 `git-sync` 脚本,会从本地 origin 更新代码。使用下面的命令来更新本地的 origin:
|
||||
|
||||
`git sync -o`
|
||||
* 上面的命令会更新你本地的 origin 和子模块的镜像,然后用那些命令来更新你的检出仓库的代码。`git-sync` 也有一些其他的很好的工鞥。
|
||||
* 当要结束工作空间中的工作时,直接退出 shell:
|
||||
|
||||
`exit`
|
||||
* 你可以在任何时间重复进入工作空间,也可以在同一时间在相同的工作空间中开多个 shell。
|
||||
* 当你不需要某个工作空间时,你可以使用 `rmws` 来删除它,或者直接删除它的目录树。
|
||||
* 还有一个脚本 `tmws` 使用 tmux 进入工作空间,能创建一系列的窗口/窗格,这完美契合我的工作流。你可以根据你自己的需求来修改它。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/2/git-great-teeming-workspaces
|
||||
|
||||
作者:[Daniel Gryniewicz][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/dang
|
||||
[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]: https://github.com/dang/gtws
|
||||
[3]: https://docs.python.org/3/library/venv.html
|
@ -0,0 +1,117 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (lxbwolf)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12130-1.html)
|
||||
[#]: subject: (Getting started with Linux firewalls)
|
||||
[#]: via: (https://opensource.com/article/20/2/firewall-cheat-sheet)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Linux 防火墙入门教程
|
||||
======
|
||||
|
||||
> 防火墙是你的计算机防止网络入侵的第一道屏障。为确保你的安全,请下载我们的备忘单。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/20/104205paugcytauqctqw6c.jpg)
|
||||
|
||||
合理的防火墙是你的计算机防止网络入侵的第一道屏障。你在家里上网,通常互联网服务提供会在路由中搭建一层防火墙。当你离开家时,那么你计算机上的那层防火墙就是仅有的一层,所以配置和控制好你 Linux 电脑上的防火墙很重要。如果你维护一台 Linux 服务器,那么知道怎么去管理你的防火墙同样重要,只要掌握了这些知识你才能保护你的服务器免于本地或远程非法流量的入侵。
|
||||
|
||||
### 安装防火墙
|
||||
|
||||
很多 Linux 发行版本已经自带了防火墙,通常是 `iptables`。它很强大并可以自定义,但配置起来有点复杂。幸运的是,有开发者写出了一些前端程序来帮助用户控制防火墙,而不需要写冗长的 iptables 规则。
|
||||
|
||||
在 Fedora、CentOS、Red Hat 和一些类似的发行版本上,默认安装的防火墙软件是 `firewalld`,通过 `firewall-cmd` 命令来配置和控制。在 Debian 和大部分其他发行版上,可以从你的软件仓库安装 firewalld。Ubuntu 自带的是<ruby>简单防火墙<rt>Uncomplicated Firewall</rt></ruby>(ufw),所以要使用 firewalld,你必须启用 `universe` 软件仓库:
|
||||
|
||||
```
|
||||
$ sudo add-apt-repository universe
|
||||
$ sudo apt install firewalld
|
||||
```
|
||||
|
||||
你还需要停用 ufw:
|
||||
|
||||
```
|
||||
$ sudo systemctl disable ufw
|
||||
```
|
||||
|
||||
没有理由*不用* ufw。它是一个强大的防火墙前端。然而,本文重点讲 firewalld,因为大部分发行版都支持它而且它集成到了 systemd,systemd 是几乎所有发行版都自带的。
|
||||
|
||||
不管你的发行版是哪个,都要先激活防火墙才能让它生效,而且需要在启动时加载:
|
||||
|
||||
```
|
||||
$ sudo systemctl enable --now firewalld
|
||||
```
|
||||
|
||||
### 理解防火墙的域
|
||||
|
||||
Firewalld 旨在让防火墙的配置工作尽可能简单。它通过建立<ruby>域<rt>zone</rt></ruby>来实现这个目标。一个域是一组的合理、通用的规则,这些规则适配大部分用户的日常需求。默认情况下有九个域。
|
||||
|
||||
* `trusted`:接受所有的连接。这是最不偏执的防火墙设置,只能用在一个完全信任的环境中,如测试实验室或网络中相互都认识的家庭网络中。
|
||||
* `home`、`work`、`internal`:在这三个域中,接受大部分进来的连接。它们各自排除了预期不活跃的端口进来的流量。这三个都适合用于家庭环境中,因为在家庭环境中不会出现端口不确定的网络流量,在家庭网络中你一般可以信任其他的用户。
|
||||
* `public`:用于公共区域内。这是个偏执的设置,当你不信任网络中的其他计算机时使用。只能接收选定的常见和最安全的进入连接。
|
||||
* `dmz`:DMZ 表示隔离区。这个域多用于可公开访问的、位于机构的外部网络、对内网访问受限的计算机。对于个人计算机,它没什么用,但是对某类服务器来说它是个很重要的选项。
|
||||
* `external`:用于外部网络,会开启伪装(你的私有网络的地址被映射到一个外网 IP 地址,并隐藏起来)。跟 DMZ 类似,仅接受经过选择的传入连接,包括 SSH。
|
||||
* `block`:仅接收在本系统中初始化的网络连接。接收到的任何网络连接都会被 `icmp-host-prohibited` 信息拒绝。这个一个极度偏执的设置,对于某类服务器或处于不信任或不安全的环境中的个人计算机来说很重要。
|
||||
* `drop`:接收的所有网络包都被丢弃,没有任何回复。仅能有发送出去的网络连接。比这个设置更极端的办法,唯有关闭 WiFi 和拔掉网线。
|
||||
|
||||
你可以查看你发行版本的所有域,或通过配置文件 `/usr/lib/firewalld/zones` 来查看管理员设置。举个例子:下面是 Fefora 31 自带的 `FedoraWorkstation` 域:
|
||||
|
||||
```
|
||||
$ cat /usr/lib/firewalld/zones/FedoraWorkstation.xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<zone>
|
||||
<short>Fedora Workstation</short>
|
||||
<description>Unsolicited incoming network packets are rejected from port 1 to 1024, except for select network services. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
|
||||
<service name="dhcpv6-client"/>
|
||||
<service name="ssh"/>
|
||||
<service name="samba-client"/>
|
||||
<port protocol="udp" port="1025-65535"/>
|
||||
<port protocol="tcp" port="1025-65535"/>
|
||||
</zone>
|
||||
```
|
||||
|
||||
### 获取当前的域
|
||||
|
||||
任何时候你都可以通过 `--get-active-zones` 选项来查看你处于哪个域:
|
||||
|
||||
```
|
||||
$ sudo firewall-cmd --get-active-zones
|
||||
```
|
||||
|
||||
输出结果中,会有当前活跃的域的名字和分配给它的网络接口。笔记本电脑上,在默认域中通常意味着你有个 WiFi 卡:
|
||||
|
||||
```
|
||||
FedoraWorkstation
|
||||
interfaces: wlp61s0
|
||||
```
|
||||
|
||||
### 修改你当前的域
|
||||
|
||||
要更改你的域,请将网络接口重新分配到不同的域。例如,把例子中的 `wlp61s0` 卡修改为 public 域:
|
||||
|
||||
```
|
||||
$ sudo firewall-cmd --change-interface=wlp61s0 --zone=public
|
||||
```
|
||||
|
||||
你可以在任何时候、任何理由改变一个接口的活动域 —— 无论你是要去咖啡馆,觉得需要增加笔记本的安全策略,还是要去上班,需要打开一些端口进入内网,或者其他原因。在你凭记忆学会 `firewall-cmd` 命令之前,你只要记住了关键词 `change` 和 `zone`,就可以慢慢掌握,因为按下 `Tab` 时,它的选项会自动补全。
|
||||
|
||||
### 更多信息
|
||||
|
||||
你可以用你的防火墙干更多的事,比如自定义已存在的域,设置默认域,等等。你对防火墙越了解,你在网上的活动就越安全,所以我们创建了一个[备忘单][2]便于速查和参考。
|
||||
|
||||
- 下载你的 [防火墙备忘单][2]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/2/firewall-cheat-sheet
|
||||
|
||||
作者:[Seth Kenlon][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/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coverimage_cheat_sheet.png?itok=lYkNKieP (Cheat Sheet cover image)
|
||||
[2]: https://opensource.com/downloads/firewall-cmd-cheat-sheet
|
183
published/202004/20200309 Fish - A Friendly Interactive Shell.md
Normal file
183
published/202004/20200309 Fish - A Friendly Interactive Shell.md
Normal file
@ -0,0 +1,183 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12069-1.html)
|
||||
[#]: subject: (Fish – A Friendly Interactive Shell)
|
||||
[#]: via: (https://fedoramagazine.org/fish-a-friendly-interactive-shell/)
|
||||
[#]: author: (Michal Konečný https://fedoramagazine.org/author/zlopez/)
|
||||
|
||||
Fish:一个友好的交互式 Shell
|
||||
======
|
||||
|
||||
![Fish — A Friendly Interactive Shell][1]
|
||||
|
||||
你是否正在寻找 bash 的替代品?你是否在寻找更人性化的东西?不用再看了,因为你刚发现了 fish!
|
||||
|
||||
Fish(友好的交互式 shell)是一个智能且用户友好的命令行 shell,可在 Linux、MacOS 和其他操作系统上运行。可以将其用于终端的日常工作和脚本编写。用 fish 编写的脚本比相同的 bash 版本具有更少的神秘性。
|
||||
|
||||
### Fish 的用户友好功能
|
||||
|
||||
* **建议**:Fish 会提示你之前写过的命令。当经常输入相同命令时,这样可以提高生产率。
|
||||
* **健全的脚本能力**:Fish 避免使用那些隐秘字符。这提供了更清晰和更友好的语法。
|
||||
* **基于手册页的补全**:Fish 会根据命令的手册页自动补全参数。
|
||||
* **语法高亮**:Fish 会高亮显示命令语法以使其在视觉上友好。
|
||||
|
||||
### 安装
|
||||
|
||||
#### Fedora 工作站
|
||||
|
||||
使用 `dnf` 命令安装 fish:
|
||||
|
||||
```
|
||||
$ sudo dnf install fish
|
||||
```
|
||||
|
||||
安装 `util-linux-user` 包,然后使用适当的参数运行 `chsh`(更改 shell 程序)命令,将 fish 设置为默认 shell 程序:
|
||||
|
||||
```
|
||||
$ sudo dnf install util-linux-user
|
||||
$ chsh -s /usr/bin/fish
|
||||
```
|
||||
|
||||
你需要注销然后重新登录,更改才能生效。
|
||||
|
||||
#### Fedora Silverblue
|
||||
|
||||
由于它不是 GUI 应用,因此你需要使用 `rpm-ostree` 将其加到层内。使用以下命令在 Fedora Silverblue 上安装 fish:
|
||||
|
||||
```
|
||||
$ rpm-ostree install fish
|
||||
```
|
||||
|
||||
在 Fedora Silverblue 上,你需要重启 PC 才能切换到新的 ostree 镜像。
|
||||
|
||||
如果你想在 Fedora Silverblue 用 fish 作为主要 shell,最简单的方法是更新 `/etc/passwd` 文件。找到你的用户,并将 `/bin/bash` 更改为 `/usr/bin/fish`。
|
||||
|
||||
你需要 [root 权限][2]来编辑 `/etc/passwd` 文件。另外,你需要注销并重新登录才能使更改生效。
|
||||
|
||||
### 配置
|
||||
|
||||
fish 的用户配置文件在 `~/.config/fish/config.fish`。要更改所有用户的配置,请编辑 `/etc/fish/config.fish`。
|
||||
|
||||
用户配置文件必须手动创建。安装脚本不会创建 `~/.config/fish/config.fish`。
|
||||
|
||||
以下是两个个配置示例以及它们的 bash 等效项,以帮助你入门:
|
||||
|
||||
#### 创建别名
|
||||
|
||||
* `~/.bashrc`:`alias ll='ls -lh'`
|
||||
* `~/.config/fish/config.fish`: `alias ll='ls -lh'`
|
||||
|
||||
#### 设置环境变量
|
||||
|
||||
* `~/.bashrc`:`export PATH=$PATH:~/bin`
|
||||
* `~/.config/fish/config.fish`:`set -gx PATH $PATH ~/bin`
|
||||
|
||||
### 使用 fish 工作
|
||||
|
||||
将 fish 配置为默认 shell 程序后,命令提示符将类似于下图所示。如果尚未将 fish 配置为默认 shell,只需运行 `fish` 命令以在当前终端会话中启动。
|
||||
|
||||
![][3]
|
||||
|
||||
在你开始输入命令时,你会注意到语法高亮显示:
|
||||
|
||||
![][4]
|
||||
|
||||
很酷,不是吗?🙂
|
||||
|
||||
你还将在输入时看到建议的命令。例如,再次开始输入上一个命令:
|
||||
|
||||
![][5]
|
||||
|
||||
注意输入时出现的灰色文本。灰色文本显示建议之前编写的命令。要自动补全,只需按 `CTRL+F`。
|
||||
|
||||
通过输入连接号(`–`)然后使用 `TAB` 键,它会根据前面命令的手册页获取参数建议:
|
||||
|
||||
![][6]
|
||||
|
||||
如果你按一次 `TAB`,它将显示前几个建议(或所有建议,如果只有少量参数可用)。如果再次按 `TAB`,它将显示所有建议。如果连续三次按 `TAB`,它将切换到交互模式,你可以使用箭头键选择一个参数。
|
||||
|
||||
除此之外,fish 的工作与大多数其他 shell 相似。其他差异已经写在文档中。因此,找到你可能感兴趣的其他功能应该不难。
|
||||
|
||||
### 让 fish 变得更强大
|
||||
|
||||
使用 [powerline][7] 使 fish 变得更强大。Powerline 可以为 fish 的界面添加命令执行时间、彩色化 git 状态、当前 git 分支等。
|
||||
|
||||
在安装 powerline 之前,你必须先安装 [Oh My Fish][8]。Oh My Fish 扩展了 fish 的核心基础架构,以支持安装其他插件。安装 Oh My Fish 的最简单方法是使用 `curl` 命令:
|
||||
|
||||
```
|
||||
> curl -L https://get.oh-my.fish | fish
|
||||
```
|
||||
|
||||
如果你不想直接将安装命令管道传给 `fish`,请参见 Oh My Fish 的 [README][9] 的安装部分,以了解其他安装方法。
|
||||
|
||||
Fish 的 powerline 插件是 [bobthefish][7]。Bobthefish 需要 `powerline-fonts` 包。
|
||||
|
||||
在 Fedora 工作站上:
|
||||
|
||||
```
|
||||
> sudo dnf install powerline-fonts
|
||||
```
|
||||
|
||||
在 Fedora Silverblue 上:
|
||||
|
||||
```
|
||||
> rpm-ostree install powerline-fonts
|
||||
```
|
||||
|
||||
在 Fedora Silverblue 上,你必须重启以完成字体的安装。
|
||||
|
||||
安装 `powerline-fonts` 之后,安装 `bobthefish`:
|
||||
|
||||
```
|
||||
> omf install bobthefish
|
||||
```
|
||||
|
||||
现在你可以通过 powerline 体验 fish 的全部奇妙之处:
|
||||
|
||||
![][10]
|
||||
|
||||
### 更多资源
|
||||
|
||||
查看这些网页,了解更多 fish 内容:
|
||||
|
||||
* [官网][11]
|
||||
* [文档][12]
|
||||
* [教程][13]
|
||||
* [常见问题][14]
|
||||
* [在线体验][15]
|
||||
* [邮件列表][16]
|
||||
* [GitHub][17]
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/fish-a-friendly-interactive-shell/
|
||||
|
||||
作者:[Michal Konečný][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/zlopez/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/03/fish-816x345.jpg
|
||||
[2]: https://fedoramagazine.org/howto-use-sudo/
|
||||
[3]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-00-35.png
|
||||
[4]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-19-24.png
|
||||
[5]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-25-31.png
|
||||
[6]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-58-07.png
|
||||
[7]: https://github.com/oh-my-fish/theme-bobthefish
|
||||
[8]: https://github.com/oh-my-fish/oh-my-fish
|
||||
[9]: https://github.com/oh-my-fish/oh-my-fish/blob/master/README.md#installation
|
||||
[10]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-15-38-07.png
|
||||
[11]: https://fishshell.com/
|
||||
[12]: https://fishshell.com/docs/current/index.html
|
||||
[13]: https://fishshell.com/docs/current/tutorial.html
|
||||
[14]: https://fishshell.com/docs/current/faq.html
|
||||
[15]: https://rootnroll.com/d/fish-shell/
|
||||
[16]: https://sourceforge.net/projects/fish/lists/fish-users
|
||||
[17]: https://github.com/fish-shell/fish-shell/
|
@ -0,0 +1,381 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12049-1.html)
|
||||
[#]: subject: (Directing Kubernetes traffic with Traefik)
|
||||
[#]: via: (https://opensource.com/article/20/3/kubernetes-traefik)
|
||||
[#]: author: (Lee Carpenter https://opensource.com/users/carpie)
|
||||
|
||||
使用 Traefik 引导 Kubernetes 流量
|
||||
======
|
||||
|
||||
> 将流量引入 Kubernetes 树莓派集群的分步指南。
|
||||
|
||||
![Digital creative of a browser on the internet][1]
|
||||
|
||||
在本文中,我们将部署几个简单的网站,并学习如何使用 Traefik 将来自外部世界的流量引入到我们的集群中。之后,我们还将学习如何删除 Kubernetes 资源。让我们开始吧!
|
||||
|
||||
- [video](https://img.linux.net.cn/static/video/Ingressing%20with%20k3s-QcC-5fRhsM8.mp4)
|
||||
|
||||
### 准备
|
||||
|
||||
要继续阅读本文,你只需要我们在上一篇文章中构建的 [k3s 树莓派集群][2]。由于你的集群将从网络上拉取镜像,因此该集群需要能够访问互联网。
|
||||
|
||||
出于解释目的,本文将显示一些配置文件和示例 HTML 文件。所有示例文件都可以在[此处][3]下载。
|
||||
|
||||
### 部署一个简单的网站
|
||||
|
||||
之前,我们使用 `kubectl` 进行了直接部署。但是,这不是典型的部署方法。一般情况都会使用 YAML 配置文件,这也是我们要在本文中使用的配置文件。我们将从顶部开始,并以自顶向下的方式创建该配置文件。
|
||||
|
||||
### 部署配置
|
||||
|
||||
首先是部署配置。配置如下所示,并在下面进行说明。我通常以 [Kubernetes 文档][4]中的示例为起点,然后根据需要对其进行修改。例如,下面的配置是复制了[部署文档][5]中的示例后修改的。
|
||||
|
||||
创建一个文件 `mysite.yaml`,其内容如下:
|
||||
|
||||
```
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysite-nginx
|
||||
labels:
|
||||
app: mysite-nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mysite-nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mysite-nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
其中大部分是样板。重要的部分,我们会将该部署命名为 `mysite-nginx`,并为其加上同名的 `app` 标签。我们指定了一个<ruby>副本<rt>replica</rt></ruby>,这意味着将只创建一个 Pod。我们还指定了一个容器,我们将其命名为 `nginx`。我们将<ruby>镜像<rt>image</rt></ruby>指定为 `nginx`。这意味着在部署时,k3s 将从 DockerHub 下载 `nginx` 镜像并从中创建一个 Pod。最后,我们指定了<ruby>容器端口<rt>containerPort</rt></ruby>为 `80`,这只意味着在容器内部 Pod 会监听 `80` 端口。
|
||||
|
||||
我在上面强调了“在容器内部”,因为这是一个重要的区别。由于我们是按容器配置的,因此只能在容器内部访问它,并且进一步将其限制为内部网络。这对于允许多个容器在同一容器端口上监听所是必要的。换句话说,通过这种配置,其他一些 Pod 也可以在其容器端口 80 上侦听,并且不会与此容器冲突。为了提供对该 Pod 的正式访问权限,我们需要一个<ruby>服务<rt>service</rt></ruby>配置。
|
||||
|
||||
### 服务配置
|
||||
|
||||
在 Kubernetes 中,<ruby>服务<rt>service</rt></ruby>是一种抽象。它提供了一种访问 Pod 或 Pod 集合的方法。当连接到服务时,服务会路由到单个 Pod,或者如果定义了多个 Pod 副本,会通过负载均衡路由到多个 Pod。
|
||||
|
||||
可以在同一配置文件中指定该服务,这就是我们将在此处要做的。用 `---` 分隔配置区域,将以下内容添加到 `mysite.yaml` 中:
|
||||
|
||||
```
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mysite-nginx-service
|
||||
spec:
|
||||
selector:
|
||||
app: mysite-nginx
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
```
|
||||
|
||||
在此配置中,我们将服务命名为 `mysite-nginx-service`。我们提供了一个<ruby>选择器<rt>selector</rt></ruby>:`app: mysite-nginx`。这是服务选择其路由到的应用程序容器的方式。请记住,我们为容器提供了 `app` 标签:`mysite-nginx` 。这就是服务用来查找我们的容器的方式。最后,我们指定服务协议为 `TCP`,在端口 `80` 上监听。
|
||||
|
||||
### 入口配置
|
||||
|
||||
<ruby>入口<rt>Ingress</rt></ruby>配置指定了如何将流量从集群外部传递到集群内部的服务。请记住,k3s 预先配置了 Traefik 作为入口控制器。因此,我们将编写特定于 Traefik 的入口配置。将以下内容添加到 `mysite.yaml` 中(不要忘了用 `---` 分隔):
|
||||
|
||||
```
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mysite-nginx-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "traefik"
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: mysite-nginx-service
|
||||
servicePort: 80
|
||||
```
|
||||
|
||||
在此配置中,我们将入口记录命名为 `mysite-nginx-ingress`。我们告诉 Kubernetes,我们希望 `traefik` 成为我们的入口控制器,再加上 `kubernetes.io/ingress.class` 的注解。
|
||||
|
||||
在<ruby>规则<rt>rules</rt></ruby>部分中,我们基本上是说,当 `http` 流量进入时,并且 `path` 匹配 `/`(或其下的任何内容),将其路由到由 `serviceName mysite-nginx-service` 指定的<ruby>后端<rt>backend</rt></ruby>服务中,并将其路由到 `servicePort 80`。这会将传入的 HTTP 流量连接到我们之前定义的服务。
|
||||
|
||||
### 需要部署的东西
|
||||
|
||||
就配置而言,就是这样了。如果我们现在部署,我们将获得默认的 nginx 页面,但这不是我们想要的。让我们创建一些简单但可自定义的部署方式。创建具有以下内容的文件 `index.html`:
|
||||
|
||||
```
|
||||
<html>
|
||||
<head><title>K3S!</title>
|
||||
<style>
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: midnightblue;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
div {
|
||||
text-align: center;
|
||||
font-size: 8rem;
|
||||
text-shadow: 3px 3px 4px dimgrey;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>Hello from K3S!</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
我们尚未介绍 Kubernetes 中的存储机制,因此在这里我们偷懒一下,仅将该文件存储在 Kubernetes 配置映射中。这不是我们推荐的部署网站的方式,但对于我们的目的来说是可行的。运行以下命令:
|
||||
|
||||
```
|
||||
kubectl create configmap mysite-html --from-file index.html
|
||||
```
|
||||
|
||||
该命令从本地文件 `index.html` 创建名为 `mysite-html` 的<ruby>配置映射<rt>configmap</rt></ruby>资源。这实际上是在 Kubernetes 资源中存储一个文件(或一组文件),我们可以在配置中调出该文件。它通常用于存储配置文件(因此而得名),我们在这里稍加滥用。在以后的文章中,我们将讨论 Kubernetes 中适当的存储解决方案。
|
||||
|
||||
创建配置映射后,让我们将其挂载在我们的 `nginx` 容器中。我们分两个步骤进行。首先,我们需要指定一个<ruby>卷<rt>volume</rt></ruby>来调出配置映射。然后我们需要将该卷挂载到 `nginx` 容器中。通过在 `mysite.yaml` 中的 `container` 后面的 `spec` 标签下添加以下内容来完成第一步:
|
||||
|
||||
```
|
||||
volumes:
|
||||
- name: html-volume
|
||||
configMap:
|
||||
name: mysite-html
|
||||
```
|
||||
|
||||
这告诉 Kubernetes 我们要定义一个名为 `html-volume` 的卷,并且该卷应包含名为 `html-volume`(我们在上一步中创建的)的配置映射的内容。
|
||||
|
||||
接下来,在 `nginx` 容器规范中的<ruby>端口<rt>ports</rt></ruby>下方,添加以下内容:
|
||||
|
||||
```
|
||||
volumeMounts:
|
||||
- name: html-volume
|
||||
mountPath: /usr/share/nginx/html
|
||||
```
|
||||
|
||||
这告诉 Kubernetes,对于 `nginx` 容器,我们想在容器中的 `/usr/share/nginx/html` 路径上挂载名为 `html-volume` 的卷。 为什么要使用 `/usr/share/nginx/html`?那个位置就是 `nginx` 镜像提供 HTML 服务的地方。通过在该路径上挂载卷,我们用该卷内容替换了默认内容。
|
||||
|
||||
作为参考,配置文件的 `deployment` 部分现在应如下所示:
|
||||
|
||||
```
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysite-nginx
|
||||
labels:
|
||||
app: mysite-nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mysite-nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mysite-nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html-volume
|
||||
mountPath: /usr/share/nginx/html
|
||||
volumes:
|
||||
- name: html-volume
|
||||
configMap:
|
||||
name: mysite-html
|
||||
```
|
||||
|
||||
### 部署它!
|
||||
|
||||
现在我们准备部署! 我们可以这样做:
|
||||
|
||||
```
|
||||
kubectl apply -f mysite.yaml
|
||||
```
|
||||
|
||||
你应该看到类似于以下内容:
|
||||
|
||||
```
|
||||
deployment.apps/mysite-nginx created
|
||||
service/mysite-nginx-service created
|
||||
ingress.networking.k8s.io/mysite-nginx-ingress created
|
||||
```
|
||||
|
||||
这意味着 Kubernetes 为我们指定的三个配置分别创建了资源。使用以下方法检查 Pod 的状态:
|
||||
|
||||
```
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
如果看到状态为 `ContainerCreating`,请给它一些时间并再次运行 `kubectl get pods`。通常,第一次会花一些时间,因为 k3s 必须下载 `nginx` 镜像来创建 Pod。一段时间后,你应该看到 `Running` 的状态。
|
||||
|
||||
### 尝试一下!
|
||||
|
||||
Pod 运行之后,就该尝试了。打开浏览器,然后在地址栏中输入 `kmaster`。
|
||||
|
||||
![][6]
|
||||
|
||||
恭喜你!你已经在 k3s 集群上部署了一个网站!
|
||||
|
||||
### 另一个
|
||||
|
||||
因此,现在我们有了一个运行单个网站的整个 k3s 集群。但是我们可以有更多的网站!如果我们要在同一集群中提供另一个网站怎么办?让我们看看如何做到这一点。
|
||||
|
||||
同样,我们需要部署一些东西。碰巧我的狗有一条她想让全世界都知道的信息,她想了好久了。因此,我专门为她制作了一些 HTML(可从示例 zip 文件中获得)。同样,我们将使用配置映射的技巧来托管这些 HTML。这次我们将把整个目录(`html` 目录)放到配置映射中,但是调用是相同的。
|
||||
|
||||
```
|
||||
kubectl create configmap mydog-html --from-file html
|
||||
```
|
||||
|
||||
现在,我们需要为此站点创建一个配置文件。它几乎与用于 `mysite.yaml` 的完全相同,因此首先将 `mysite.yaml` 复制为 `mydog.yaml`。现在将 `mydog.yaml` 修改为:
|
||||
|
||||
```
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mydog-nginx
|
||||
labels:
|
||||
app: mydog-nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mydog-nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mydog-nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts:
|
||||
- name: html-volume
|
||||
mountPath: /usr/share/nginx/html
|
||||
volumes:
|
||||
- name: html-volume
|
||||
configMap:
|
||||
name: mydog-html
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mydog-nginx-service
|
||||
spec:
|
||||
selector:
|
||||
app: mydog-nginx
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: mydog-nginx-ingress
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "traefik"
|
||||
traefik.frontend.rule.type: PathPrefixStrip
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /mydog
|
||||
backend:
|
||||
serviceName: mydog-nginx-service
|
||||
servicePort: 80
|
||||
```
|
||||
|
||||
我们只需进行搜索并将 `mysite` 替换为 `mydog`即可完成大多数修改。其他两个修改在入口部分中。我们将 `path` 更改为 `/mydog`,并添加了一个注解 `traefik.frontend.rule.type: PathPrefixStrip`。
|
||||
|
||||
`/mydog` 路径的规范指示 Traefik 将以 `/mydog` 路径开头的所有传入请求路由到 `mydog-nginx-service`。任何其他路径将继续路由到 `mysite-nginx-service`。
|
||||
|
||||
新的注解 `PathPrefixStrip` 告诉 Traefik 在将请求发送到 `mydog-nginx-service` 之前先去除前缀 `/mydog`。我们这样做是因为 `mydog-nginx` 应用程序不需要前缀。这意味着我们可以简单地通过更改入口记录中的前缀来更改挂载的服务的位置。
|
||||
|
||||
现在我们可以像以前一样进行部署:
|
||||
|
||||
```
|
||||
kubectl apply -f mydog.yaml
|
||||
```
|
||||
|
||||
现在,我的狗的消息应该可以在 <http://kmaster/mydog/> 上找到。
|
||||
|
||||
![][7]
|
||||
|
||||
|
||||
呼!消息发出去了!也许今晚我们都可以睡一觉。
|
||||
|
||||
因此,现在,我们有了一个 k3s 集群,该集群托管了两个网站,Traefik 根据路径名决定将请求传递给哪个服务!但是,不仅限于基于路径的路由,我们也可以使用基于主机名的路由,我们将在以后的文章中进行探讨。
|
||||
|
||||
另外,我们刚刚托管的网站是标准的未加密 HTML 网站,而如今的所有内容都使用 SSL/TLS 加密。在我们的下一篇文章中,我们将为 k3s 集群添加支持以托管 SSL/TLS HTTPS 站点!
|
||||
|
||||
### 清理
|
||||
|
||||
在开始之前,由于本文主要涉及的是示例站点,因此我想向你展示如何删除内容,以防万一你不希望将这些示例丢在集群中。
|
||||
|
||||
对于大多数配置,只需使用与部署时使用的相同配置文件运行 `delete` 命令即可撤消配置。因此,让我们同时清理 `mysite` 和 `mydog`。
|
||||
|
||||
```
|
||||
kubectl delete -f mysite.yaml
|
||||
kubectl delete -f mydog.yaml
|
||||
```
|
||||
|
||||
由于我们是手动创建配置映射的,因此我们也需要手动删除它们。
|
||||
|
||||
```
|
||||
kubectl delete configmap mysite-html
|
||||
kubectl delete configmap mydog-html
|
||||
```
|
||||
|
||||
现在,如果我们执行 `kubectl get pods`,我们应该看到我们的 nginx Pod 不存在了。
|
||||
|
||||
```
|
||||
$ kubectl get pods
|
||||
No resources found in default namespace.
|
||||
```
|
||||
|
||||
一切都清理了。
|
||||
|
||||
请在下面的评论中告诉我你对这个项目有什么想法。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/kubernetes-traefik
|
||||
|
||||
作者:[Lee Carpenter][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/carpie
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
|
||||
[2]: https://linux.cn/article-12049-1.html
|
||||
[3]: https://gitlab.com/carpie/ingressing_with_k3s/-/archive/master/ingressing_with_k3s-master.zip
|
||||
[4]: https://kubernetes.io/docs/
|
||||
[5]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
|
||||
[6]: https://opensource.com/sites/default/files/uploads/mysite.jpg
|
||||
[7]: https://opensource.com/sites/default/files/uploads/mydog.jpg
|
@ -0,0 +1,227 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (cycoe)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12150-1.html)
|
||||
[#]: subject: (What you need to know about variables in Emacs)
|
||||
[#]: via: (https://opensource.com/article/20/3/variables-emacs)
|
||||
[#]: author: (Clemens Radermacher https://opensource.com/users/clemera)
|
||||
|
||||
关于 Emacs 中的变量你需要知道的事情
|
||||
======
|
||||
|
||||
> 学习 Elisp 是如何处理变量的,以及如何在你的脚本与配置中使用它们。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/25/190905pq1qfk1f8f9qs9v8.jpg)
|
||||
|
||||
GNU Emacs 是由 C 和 Emacs Lisp(Elisp,Lisp 编程语言的一种方言)写成,它是一个编辑器的同时,又碰巧是 Elisp 的沙盒。因此,理解 Elisp 中的一些基本编程概念会对你有一些帮助。
|
||||
|
||||
如果你是 [Emacs][2] 新手,请先阅读 Sacha Chua 的《[给 Emacs 新手的资源][3]》精品帖。本篇文章假定你熟悉常见的 Emacs 术语,并且能够阅读并求值 Elisp 代码的简单片段。最好你也听说过变量作用域的概念,知道它在其它编程语言中的作用。本篇文章中的示例假定你使用的是相对较新的 Emacs 版本([v.25 之后的版本][4])。
|
||||
|
||||
[Elisp 手册][5] 包含了 Elisp 的方方面面,但它是写给那些有明确查找目标的人们的(它在这方面也做得相当棒)。但是很多人想要能够在更高的层次上解释 Elisp 概念的材料,同时将信息压缩成最精华的部分。本篇文章也正是我回应这种呼声的一次尝试,为读者描绘基础的大体轮廓。使他们能在配置中用上这些技巧,也让他们在手册中查询细节变得更容易。
|
||||
|
||||
### 全局变量
|
||||
|
||||
用 `defcustom` 定义的用户设置和用 `defvar` 或 `defconst` 定义的变量是全局的。使用 `defcustom` 或 `defvar` 声明变量的一个非常重要的原因是,当一个变量已经被<ruby>绑定<rt>bind</rt></ruby>,对它们进行重新求值不会覆盖掉已有的值。举个栗子,如果你在初始化文件中对 `my-var` 进行如下绑定:
|
||||
|
||||
```
|
||||
(setq my-var nil)
|
||||
```
|
||||
|
||||
对如下表达式求值不会将变量覆盖为 `t`:
|
||||
|
||||
```
|
||||
(defvar my-var t)
|
||||
```
|
||||
|
||||
注意此处有*一个例外*:如果你用 `C-M-x` 快捷键对上述声明求值,它将调用 `eval-defun` 函数,并将变量覆盖为 `t`。通过此方式,你可以按需将变量强制覆盖。这种行为是刻意而为之的:你可能知道,Emacs 中的许多特性是按需加载的,也可以称为自动加载。如果那些文件中的声明将变量覆盖为它们的默认值,那它也就覆盖了你初始化文件中的设置。
|
||||
|
||||
### 用户选项
|
||||
|
||||
用户选项就是使用 `defcustom` 声明的全局变量。与使用 `defvar` 声明的变量不同,这些变量可以用 `M-x customize` 界面来配置。据我所知,大部分人因为觉得它开销较大而不经常使用。一旦你知道如何在你的初始化文件中设置变量,也就没有理由一定要去使用它了。许多用户没有意识到的一个细节是,通过 `customize` 的方式设置用户选项能够执行代码,有的时间可用来运行一些附加的配置说明:
|
||||
|
||||
```
|
||||
(defcustom my-option t
|
||||
"My user option."
|
||||
:set (lambda (sym val)
|
||||
(set-default sym val)
|
||||
(message "Set %s to %s" sym val)))
|
||||
```
|
||||
|
||||
若你对这段代码求值,并键入 `M-x customize-option RET my-option RET` 运行 `customize` 界面,lambda 匿名函数就会被调用,回显区域就会显示出该选项的符号名与值。
|
||||
|
||||
如果你在初始化文件中使用 `setq` 改变该选项的值,那么匿名函数不会运行。要想在 Elisp 中正确设置一个选项,你需要使用函数 `customize-set-variable`。或者,人们在他们的配置文件中使用了各种版本的 `csetq` 宏来自动处理(如你所愿,你可以通过 GitHub 的代码搜索发现更复杂的变体)。
|
||||
|
||||
```
|
||||
(defmacro csetq (sym val)
|
||||
`(funcall (or (get ',sym 'custom-set) 'set-default) ',sym ,val))
|
||||
```
|
||||
|
||||
若你正在使用 [use-package][6] 宏,`:custom` 关键字会替你处理好以上这些。
|
||||
|
||||
在你将以上代码放入到你的初始化文件中之后,你便可以使用 `csetq` 宏在设置变量的同时运行任何现存的 `setter` 函数。要证明这点,你可以使用此宏来改变上面定义的选项,并观察回显区域的消息输出。
|
||||
|
||||
```
|
||||
(csetq my-option nil)
|
||||
```
|
||||
|
||||
### 动态绑定与词法绑定
|
||||
|
||||
当你在使用其它编程语言时,你可能不会意识到动态绑定与词法绑定的区别。当今的大部分编程语言使用词法绑定,并且在学习变量作用域与变量查找时也没有必要去了解它们之间的区别。
|
||||
|
||||
如此看来,Emacs Lisp 比较特殊因为动态绑定是默认选项,词法绑定需要显式启用。这里有一些历史遗留原因,但在实际使用中,你应该*时刻*启用词法绑定,因为它更快并且不容易出错。要启用词法绑定,只需将如下的注释行作为你的 Emacs Lisp 文件的第一行:
|
||||
|
||||
```
|
||||
;;; -*- lexical-binding: t; -*-
|
||||
```
|
||||
|
||||
另一种方式,你可以调用 `add-file-local-variable-prop-line`,在你选择将变量 `lexical-binding` 置为 `t` 后,会自动插入如上的注释行。
|
||||
|
||||
在加载包含如上特殊格式行的文件时,Emacs 会相应地设置变量,这意味着该缓冲区中的代码加载时启用了词法绑定。若要采用交互式的方式,你可以调用 `M-x eval-buffer` 命令,它会将词法绑定考虑在内。
|
||||
|
||||
既然你已经知道了如何启用词法绑定,那么了解这些术语的含义就很明智了。对于动态绑定,在程序执行期间建立的最后一个绑定将用于变量查找。你可以通过将以下代码放入空缓冲区并执行 `M-x eval buffer`,以对此进行测试:
|
||||
|
||||
```
|
||||
(defun a-exists-only-in-my-body (a)
|
||||
(other-function))
|
||||
|
||||
(defun other-function ()
|
||||
(message "I see `a', its value is %s" a))
|
||||
|
||||
(a-exists-only-in-my-body t)
|
||||
```
|
||||
|
||||
你可能会很惊讶地发现,在 `other-function` 中查找变量 `a` 竟然成功了。
|
||||
|
||||
若你在顶部添加了特殊的词法绑定注释后,重新运行前面的示例,这段代码将抛出 `variable is void` 错误,因为 `other-functioin` 无法识别变量 `a`。如果你使用的是其它编程语言,这才是你所期望的行为。
|
||||
|
||||
启用词法绑定后,作用域会由周围的代码所定义。这并不单单是性能原因,时间也已经表明了词法绑定才是更受喜爱的。
|
||||
|
||||
### 特殊变量与动态绑定
|
||||
|
||||
如你所知,`let` 用于临时建立局部绑定:
|
||||
|
||||
```
|
||||
(let ((a "I'm a")
|
||||
(b "I'm b"))
|
||||
(message "Hello, %s. Hello %s" a b))
|
||||
```
|
||||
|
||||
接下来有趣的是——使用 `defcustom`、`defvar` 以及 `defconst` 定义的变量被称为*特殊变量*,不论词法绑定是否启用,它们都将使用动态绑定:
|
||||
|
||||
```
|
||||
;;; -*- lexical-binding: t; -*-
|
||||
|
||||
(defun some-other-function ()
|
||||
(message "I see `c', its value is: %s" c))
|
||||
|
||||
(defvar c t)
|
||||
|
||||
(let ((a "I'm lexically bound")
|
||||
(c "I'm special and therefore dynamically bound"))
|
||||
(some-other-function)
|
||||
(message "I see `a', its values is: %s" a))
|
||||
```
|
||||
|
||||
通过 `C-h e` 切换至 `Messages` 缓冲区,查看上述示例输出的消息。
|
||||
|
||||
使用 `let` 或者函数参数绑定的局部变量会遵循由 `lexical-binding` 变量定义的查找规则,但使用 `defvar`、`defconst` 或 `defcustom` 定义的全局变量,能够沿着调用栈在 `let` 表达式中被修改。
|
||||
|
||||
这种技巧允许方便地进行特殊定制,并且经常在 Emacs 中被使用。这并不奇怪,毕竟 Emacs Lisp 最开始只提供动态绑定作为唯一选择。下面是一个常见的示例,说明如何向只读缓冲区临时写入数据:
|
||||
|
||||
```
|
||||
(let ((inhibit-read-only t))
|
||||
(insert ...))
|
||||
```
|
||||
|
||||
这是另一个常见的示例,如何进行大小写敏感的搜索:
|
||||
|
||||
```
|
||||
(let ((case-fold-search nil))
|
||||
(some-function-which-uses-search ...))
|
||||
```
|
||||
|
||||
动态绑定允许你采用作者未曾预料的方式对函数进行修改。对于像 Emacs 这样设计使用的程序来说,这是个强大的工具与特性。
|
||||
|
||||
有一点需要注意:你可能会意外地使用局部变量名,该变量在其他地方被声明为特殊变量。防止这种冲突的一个技巧是避免在局部变量名中使用下划线。在我当前的 Emacs 会话中,以下代码只留下少数潜在冲突的候选:
|
||||
|
||||
```
|
||||
(let ((vars ()))
|
||||
(mapatoms
|
||||
(lambda (cand)
|
||||
(when (and (boundp cand)
|
||||
(not (keywordp cand))
|
||||
(special-variable-p cand)
|
||||
(not (string-match "-"
|
||||
(symbol-name cand))))
|
||||
(push cand vars))))
|
||||
vars) ;; => (t obarray noninteractive debugger nil)
|
||||
```
|
||||
|
||||
### 缓冲区局部变量
|
||||
|
||||
每个缓冲区都能够拥有变量的一个局部绑定。这就意味着对于任何变量,都会首先在当前缓冲区中查找缓冲区局部变量取代默认值。局部变量是 Emacs 中一个非常重要的特性,比如它们被主模式用来建立缓冲区范围内的行为与设置。
|
||||
|
||||
事实上你已经在本文中见过*缓冲区局部变量*——也就是将 `lexical-binding` 在缓冲区范围内设置为 `t` 的特殊注释行。在 Emacs 中,在特殊注释行中定义的缓冲区局部变量也被称为*文件局部变量*。
|
||||
|
||||
任何的全局变量都可以用缓冲区局部变量来遮掩,比如上面定义的变量 `my-var`,你可用如下方式设置局部变量:
|
||||
|
||||
```
|
||||
(setq-local my-var t)
|
||||
;; or (set (make-local-variable 'my-var) t)
|
||||
```
|
||||
|
||||
此时 `my-var` 对于你在对上述代码进行求值时对应的缓冲区来说就是局部变量。若你对它调用 `describe-variable`,文档会同时告诉你局部与全局的值。从编程的角度来讲,你可以分别用 `buffer-local-value` 获取局部值,用 `default-value` 获取全局值。若要移除局部值,你可以调用 `kill-local-variable`。
|
||||
|
||||
另一个需要注意的重要性质就是,一旦一个变量成为缓冲区局部变量,后续在该缓冲区中使用的 `setq` 都将只能设置局部的值。要想设置默认值,你需要使用 `setq-default`。
|
||||
|
||||
因为局部变量意味着对缓冲区的定制,它们也就经常被用于模式钩子中。一个典型的例子如下所示:
|
||||
|
||||
```
|
||||
(add-hook 'go-mode-hook
|
||||
(defun go-setup+ ()
|
||||
(setq-local compile-command
|
||||
(if (string-suffix-p "_test.go" buffer-file-name)
|
||||
"go test -v"
|
||||
(format "go run %s"
|
||||
(shell-quote-argument
|
||||
(file-name-nondirectory buffer-file-name)))))))
|
||||
```
|
||||
|
||||
这将设置 `go-mode` 缓冲区中 `M-x compile` 使用的编译命令。
|
||||
|
||||
另一个重要的方面就是一些变量会*自动*成为缓冲区局部变量。这也就意味着当你使用 `setq` 设置这样一个变量时,它会针对当前缓冲区设置局部绑定。这个特性不应该被经常使用,因为这种隐式的行为并不好。不过如果你想的话,你可以使用如下方法创建自动局部变量:
|
||||
|
||||
```
|
||||
(defvar-local my-automatical-local-var t)
|
||||
;; or (make-variable-buffer-local 'my-automatical-local-var)
|
||||
```
|
||||
|
||||
变量 `indent-tabs-mode` 就是 Emacs 内建的一个例子。如果你在初始化文件中使用 `setq` 改变变量的值,根本不会影响默认值。只有在你加载初始化文件时正处在当前的缓冲区的局部值会被改变。因此,你需要使用 `setq-default` 来改变 `indent-tabs-mode` 的默认值。
|
||||
|
||||
### 结语
|
||||
|
||||
Emacs 是一个强大的编辑器,并且随着你的定制它将变得更加强大。现在,你知道了 Elisp 是如何处理变量的,以及你应如何在你自己的脚本与配置中使用它们。
|
||||
|
||||
*本篇文章此前采用 CC BY-NC-SA 4.0 许可证发布在 [With-Emacs][7] 上,经过修改(带有合并请求)并在作者允许的情况下重新发布。*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/3/variables-emacs
|
||||
|
||||
作者:[Clemens Radermacher][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/clemera
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming_keyboard_coding.png?itok=E0Vvam7A (Programming keyboard.)
|
||||
[2]: https://www.gnu.org/software/emacs/
|
||||
[3]: http://sachachua.com/blog/p/27144
|
||||
[4]: https://www.gnu.org/software/emacs/download.html
|
||||
[5]: https://www.gnu.org/software/emacs/manual/html_node/elisp/
|
||||
[6]: https://github.com/jwiegley/use-package#customizing-variables
|
||||
[7]: https://with-emacs.com/posts/tutorials/almost-all-you-need-to-know-about-variables/
|
@ -1,8 +1,8 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12106-1.html)
|
||||
[#]: subject: (Make SSL certs easy with k3s)
|
||||
[#]: via: (https://opensource.com/article/20/3/ssl-letsencrypt-k3s)
|
||||
[#]: author: (Lee Carpenter https://opensource.com/users/carpie)
|
||||
@ -12,31 +12,31 @@
|
||||
|
||||
> 如何在树莓派上使用 k3s 和 Let's Encrypt 来加密你的网站。
|
||||
|
||||
![Files in a folder][1]
|
||||
![](https://img.linux.net.cn/data/attachment/album/202004/13/153032ncp8q55pjwdj8ppj.jpg)
|
||||
|
||||
在[上一篇文章][2]中,我们在 k3s 集群上部署了几个简单的网站。那些是未加密的网站。很好,它们可以工作,但是未加密的网站有点太过时了!如今,大多数网站都是加密的。在本文中,我们将安装 [cert-manager][3] 并将其用于在集群上以部署采用 TLS 加密的网站。这些网站不仅会被加密,而且还会使用有效的公共证书,这些证书会从 [Let's Encrypt][4] 自动获取和更新!让我们开始吧!
|
||||
在[上一篇文章][2]中,我们在 k3s 集群上部署了几个简单的网站。那些是未加密的网站。不错,它们可以工作,但是未加密的网站有点太过时了!如今,大多数网站都是加密的。在本文中,我们将安装 [cert-manager][3] 并将其用于在集群上以部署采用 TLS 加密的网站。这些网站不仅会被加密,而且还会使用有效的公共证书,这些证书会从 [Let's Encrypt][4] 自动获取和更新!让我们开始吧!
|
||||
|
||||
### 所需材料
|
||||
### 准备
|
||||
|
||||
要继续阅读本文,你将需要我们在上一篇文章中构建的 [k3s 树莓派集群][5]。另外,你需要拥有一个公用静态 IP 地址,并有一个可以为其创建 DNS 记录的域名。如果你有一个动态 DNS 提供程序为你提供域名,可能也行。但是,在本文中,我们将使用静态 IP 和 [CloudFlare][6] 来手动创建 DNS 的 A 记录。
|
||||
要继续阅读本文,你将需要我们在上一篇文章中构建的 [k3s 树莓派集群][5]。另外,你需要拥有一个公用静态 IP 地址,并有一个可以为其创建 DNS 记录的域名。如果你有一个动态 DNS 提供程序为你提供域名,可能也行。但是,在本文中,我们使用静态 IP 和 [CloudFlare][6] 来手动创建 DNS 的 A 记录。
|
||||
|
||||
我们在本文中创建配置文件时,如果你不想键入它们,则可以在[此处][7]进行下载。
|
||||
|
||||
### 我们为什么使用 cert-manager?
|
||||
|
||||
Traefik(预先捆绑了 k3s)实际上具有内置的 Let's Encrypt 支持,因此你可能想知道为什么我们要安装第三方软件包来做同样的事情。在撰写本文时,Traefik 中的 Let's Encrypt 支持检索证书并将其存储在文件中。cert-manager 会检索证书并将其存储在 Kubernetes 的 “<ruby>机密信息<rt>secrets</rt></ruby>” 中。我认为,“机密信息”可以简单地按名称引用,因此更易于使用。这就是我们在本文中使用 cert-manager 的主要原因。
|
||||
Traefik(在 k3s 预先捆绑了)实际上具有内置的 Let's Encrypt 支持,因此你可能想知道为什么我们要安装第三方软件包来做同样的事情。在撰写本文时,Traefik 中的 Let's Encrypt 支持检索证书并将其存储在文件中。而 cert-manager 会检索证书并将其存储在 Kubernetes 的 “<ruby>机密信息<rt>secret</rt></ruby>” 中。我认为,“机密信息”可以简单地按名称引用,因此更易于使用。这就是我们在本文中使用 cert-manager 的主要原因。
|
||||
|
||||
### 安装 cert-manager
|
||||
|
||||
通常,我们只是遵循 cert-manager 的[文档][8]在 Kubernetes 上进行安装。但是,由于我们使用的是 ARM 体系结构,因此我们需要进行一些更改,以便我们可以完成这个操作。
|
||||
|
||||
第一步是创建 cert-manager 命名空间。命名空间有助于将 cert-manager 的<ruby>吊舱<rt>Pod</rt></ruby>排除在我们的默认命名空间之外,因此当我们使用自己的“吊舱”执行 `kubectl get pods` 之类的操作时,我们不必看到它们。创建名称空间很简单:
|
||||
第一步是创建 cert-manager 命名空间。命名空间有助于将 cert-manager 的 Pod 排除在我们的默认命名空间之外,因此当我们使用自己的 Pod 执行 `kubectl get pods` 之类的操作时,我们不必看到它们。创建名称空间很简单:
|
||||
|
||||
```
|
||||
kubectl create namespace cert-manager
|
||||
```
|
||||
|
||||
这份安装说明会告诉你下载 cert-manager 的 YAML 配置文件并将其一步全部应用到你的集群。我们需要将其分为两个步骤,以便为基于 ARM 的树莓派修改文件。我们将下载文件并一步一步进行转换:
|
||||
安装说明会让你下载 cert-manager 的 YAML 配置文件并将其一步全部应用到你的集群。我们需要将其分为两个步骤,以便为基于 ARM 的树莓派修改文件。我们将下载文件并一步一步进行转换:
|
||||
|
||||
```
|
||||
curl -sL \
|
||||
@ -44,8 +44,7 @@ https://github.com/jetstack/cert-manager/releases/download/v0.11.0/cert-manager.
|
||||
sed -r 's/(image:.*):(v.*)$/\1-arm:\2/g' > cert-manager-arm.yaml
|
||||
```
|
||||
|
||||
这会下载配置文件,并将所有包含的 docker 镜像更新为 ARM 版本。来检查一下它做了什么:
|
||||
|
||||
这会下载配置文件,并将包含的所有 docker 镜像更新为 ARM 版本。来检查一下它做了什么:
|
||||
|
||||
```
|
||||
$ grep image: cert-manager-arm.yaml
|
||||
@ -54,23 +53,23 @@ $ grep image: cert-manager-arm.yaml
|
||||
image: "quay.io/jetstack/cert-manager-webhook-arm:v0.11.0"
|
||||
```
|
||||
|
||||
如我们所见,三个镜像现在在镜像名称上添加了 `-arm`。现在我们有了正确的文件,我们只需将其应用于集群:
|
||||
如我们所见,三个镜像现在在镜像名称上添加了 `-arm`。现在我们有了正确的文件,我们只需将其应用于集群:
|
||||
|
||||
```
|
||||
kubectl apply -f cert-manager-arm.yaml
|
||||
```
|
||||
|
||||
这将安装所有的 cert-manager。我们可以通过 `kubectl --namespace cert-manager get pods` 来检查安装何时完成,直到所有“吊舱”都处于 `Running` 状态。
|
||||
这将安装 cert-manager 的全部。我们可以通过 `kubectl --namespace cert-manager get pods` 来检查安装何时完成,直到所有 Pod 都处于 `Running` 状态。
|
||||
|
||||
这实际上就完成了 cert-manager 的安装!
|
||||
这就完成了 cert-manager 的安装!
|
||||
|
||||
### Let's Encrypt 概述
|
||||
|
||||
Let's Encrypt 的好处是,它们免费为我们提供了经过公共验证的 TLS 证书!这意味着我们可以拥有一个完全有效的、可供任何人访问的 TLS 加密网站,这些家庭或业余的爱好活动挣不到钱,也无需自己掏腰包购买 TLS 证书!以及,当通过 cert-manager 使用 Let's Encrypt 的证书时,获得证书的整个过程是自动化的,证书的续订也是自动的!
|
||||
Let's Encrypt 的好处是,它免费为我们提供了经过公共验证的 TLS 证书!这意味着我们可以拥有一个完全有效的、可供任何人访问的 TLS 加密网站,这些家庭或业余的爱好活动挣不到钱,也无需自己掏腰包购买 TLS 证书!以及,当通过 cert-manager 使用 Let's Encrypt 的证书时,获得证书的整个过程是自动化的,证书的续订也是自动的!
|
||||
|
||||
但它是如何工作的?下面是该过程的简化说明。我们(或代表我们的 cert-manager)向 Let's Encrypt 发出我们拥有的域名的证书请求。Let's Encrypt 通过使用 ACME DNS 或 HTTP 验证机制来验证我们是否拥有该域。如果验证成功,则 Let's Encrypt 将向我们提供证书,这些证书将由 cert-manager 安装在我们的网站(或其他 TLS 加密的终结点)中。在需要重复此过程之前,这些证书可以使用 90 天。但是,cert-manager 会自动为我们更新证书。
|
||||
但它是如何工作的?下面是该过程的简化说明。我们(或代表我们的 cert-manager)向 Let's Encrypt 发出我们拥有的域名的证书请求。Let's Encrypt 通过使用 ACME DNS 或 HTTP 验证机制来验证我们是否拥有该域。如果验证成功,则 Let's Encrypt 将向我们提供证书,这些证书将由 cert-manager 安装在我们的网站(或其他 TLS 加密的端点)中。在需要重复此过程之前,这些证书可以使用 90 天。但是,cert-manager 会自动为我们更新证书。
|
||||
|
||||
在本文中,我们将使用 HTTP 验证方法,因为它更易于设置并且适用于大多数情况。以下是幕后将发生的基本过程。cert-manager 将向 Let's Encrypt 发出证书请求。作为回应,Let's Encrypt 将发出所有权验证的<ruby>质询<rt>challenges</rt></ruby>。这个质询是将一个 HTTP 资源放在请求证书的域名下的一个特定 URL 上。从理论上讲,如果我们可以将该资源放在该 URL 上,并且让 Let's Encrypt 可以远程获取它,那么我们实际上必须是该域的所有者。否则,要么我们无法将资源放置在正确的位置,要么我们无法操纵 DNS 以使 Let's Encrypt 访问它。在这种情况下,cert-manager 会将资源放在正确的位置,并自动创建一个临时的 `Ingress` 记录,以将流量路由到正确的位置。如果 Let's Encrypt 可以读到该质询要求的资源并正确无误,它将把证书发回给 cert-manager。然后,cert-manager 将证书存储为“机密信息”,然后我们的网站(或其他任何网站)将使用这些证书通过 TLS 保护我们的流量。
|
||||
在本文中,我们将使用 HTTP 验证方法,因为它更易于设置并且适用于大多数情况。以下是幕后发生的基本过程。cert-manager 向 Let's Encrypt 发出证书请求。作为回应,Let's Encrypt 发出所有权验证的<ruby>质询<rt>challenges</rt></ruby>。这个质询是将一个 HTTP 资源放在请求证书的域名下的一个特定 URL 上。从理论上讲,如果我们可以将该资源放在该 URL 上,并且让 Let's Encrypt 可以远程获取它,那么我们实际上必须是该域的所有者。否则,要么我们无法将资源放置在正确的位置,要么我们无法操纵 DNS 以使 Let's Encrypt 访问它。在这种情况下,cert-manager 会将资源放在正确的位置,并自动创建一个临时的 `Ingress` 记录,以将流量路由到正确的位置。如果 Let's Encrypt 可以读到该质询要求的资源并正确无误,它将把证书发回给 cert-manager。cert-manager 将证书存储为“机密信息”,然后我们的网站(或其他任何网站)将使用这些证书通过 TLS 保护我们的流量。
|
||||
|
||||
### 为该质询设置网络
|
||||
|
||||
@ -78,11 +77,11 @@ Let's Encrypt 的好处是,它们免费为我们提供了经过公共验证的
|
||||
|
||||
为了使质询过程正常运行,我们需要一个我们要申请证书的域名,以将其路由到端口 80 上的 k3s 集群。为此,我们需要告诉世界上的 DNS 系统它的位置。因此,我们需要将域名映射到我们的公共 IP 地址。如果你不知道你的公共 IP 地址是什么,可以访问 [WhatsMyIP][9] 之类的地方,它会告诉你。接下来,我们需要输入 DNS 的 A 记录,该记录将我们的域名映射到我们的公共 IP 地址。为了使此功能可靠地工作,你需要一个静态的公共 IP 地址,或者你可以使用动态 DNS 提供商。一些动态 DNS 提供商会向你颁发一个域名,你可以按照以下说明使用它。我没有尝试过,所以不能肯定地说它适用于所有提供商。
|
||||
|
||||
对于本文,我们将假设有一个静态公共 IP 并使用 CloudFlare 来设置 DNS 的 A 记录。如果愿意,可以使用自己的 DNS 提供程序。重要的是你可以设置 A 记录。
|
||||
对于本文,我们假设有一个静态公共 IP,并使用 CloudFlare 来设置 DNS 的 A 记录。如果愿意,可以使用自己的 DNS 服务器。重要的是你可以设置 A 记录。
|
||||
|
||||
在本文的其余部分中,我将使用 [k3s.carpie.net][10] 作为示例域,因为这是我拥有的域。你显然会用自己拥有的任何域替换它。
|
||||
在本文的其余部分中,我将使用 [k3s.carpie.net][10] 作为示例域名,因为这是我拥有的域。你显然会用自己拥有的任何域名替换它。
|
||||
|
||||
为示例起见,假设我们的公共 IP 地址是 198.51.100.42。我们将转到我们的 DNS 提供商的 DNS 记录部分,并添加一个名为 [k3s.carpie.net][10] 的类型为 `A` 的记录(CloudFlare 已经假定了域的部分,因此我们只需输入 `k3s`),然后输入 `198.51.100.42` 作为 IPv4 地址。
|
||||
为示例起见,假设我们的公共 IP 地址是 198.51.100.42。我们转到我们的 DNS 提供商的 DNS 记录部分,并添加一个名为 [k3s.carpie.net][10] 的类型为 `A` 的记录(CloudFlare 已经假定了域的部分,因此我们只需输入 `k3s`),然后输入 `198.51.100.42` 作为 IPv4 地址。
|
||||
|
||||
![][11]
|
||||
|
||||
@ -95,17 +94,17 @@ $ dig +short k3s.carpie.net
|
||||
198.51.100.42
|
||||
```
|
||||
|
||||
继续运行以上命令,直到可以返回 IP 才行。关于 CloudFlare 有个小注释:ClouldFlare 提供了通过代理流量来隐藏你的实际 IP 的服务。在这种情况下,我们取回的是 CloudFlare 的 IP,而不是我们的 IP。 但对于我们的目的,这应该可以正常工作。
|
||||
继续运行以上命令,直到可以返回 IP 才行。关于 CloudFlare 有个小注释:ClouldFlare 提供了通过代理流量来隐藏你的实际 IP 的服务。在这种情况下,我们取回的是 CloudFlare 的 IP,而不是我们的 IP。但对于我们的目的,这应该可以正常工作。
|
||||
|
||||
网络配置的最后一步是配置路由器,以将端口 80 和 443 上的传入流量路由到我们的 k3s 集群。可悲的是,路由器配置页面的差异很大,因此我无法确切地说明你的外观是什么样子。大多数时候,我们需要的管理页面位于“端口转发”或类似内容下。我甚至看到过它列在“游戏”之下(显然是端口转发主要用于的游戏)!让我们看看我的路由器的配置如何。
|
||||
|
||||
![][12]
|
||||
|
||||
如果你和我的设置一样,则转到 192.168.0.1 登录到路由器管理应用程序。对于此路由器,它位于 “ NAT / QoS” -> “端口转发”。在这里,我们将端口 80/TCP 协议设置为转发到 192.168.0.50(主节点 `kmaster` 的 IP)的端口 80。我们还将端口 443 设置为也映射到 `kmaster`。从技术上讲,这对于质询来说并不是必需的,但是在本文的结尾,我们将部署一个启用 TLS 的网站,并且需要映射 443 来进行访问。因此,现在进行映射很方便。我们保存并应用更改,应该一切顺利!
|
||||
如果你和我的环境一样,则转到 192.168.0.1 登录到路由器管理应用程序。对于此路由器,它位于 “ NAT/QoS” -> “端口转发”。在这里,我们将端口 80/TCP 协议设置为转发到 192.168.0.50(主节点 `kmaster` 的 IP)的端口 80。我们还设置端口 443 也映射到 `kmaster`。从技术上讲,这对于质询来说并不是必需的,但是在本文的结尾,我们将部署一个启用 TLS 的网站,并且需要映射 443 来进行访问。因此,现在进行映射很方便。我们保存并应用更改,应该一切顺利!
|
||||
|
||||
### 配置 cert-manager 来使用 Let's Encrypt(暂存环境)
|
||||
|
||||
现在,我们需要配置 cert-manager 来通过 Let's Encrypt 颁发证书。Let's Encrypt 为我们提供了一个暂存(例如用于测试)环境,以便审视我们的配置。这样它更能容忍错误和请求的频率。如果我们对生产环境做了错误的操作,我们很快就好发现自己被暂时禁止访问了!因此,我们将使用暂存环境手动测试请求。
|
||||
现在,我们需要配置 cert-manager 来通过 Let's Encrypt 颁发证书。Let's Encrypt 为我们提供了一个暂存(例如用于测试)环境,以便审视我们的配置。这样它更能容忍错误和请求的频率。如果我们对生产环境做了错误的操作,我们很快就会发现自己被暂时禁止访问了!因此,我们将使用暂存环境手动测试请求。
|
||||
|
||||
创建一个文件 `letsencrypt-issuer-staging.yaml`,内容如下:
|
||||
|
||||
@ -132,7 +131,7 @@ spec:
|
||||
|
||||
请确保将电子邮件地址更新为你的地址。如果出现问题或我们弄坏了一些东西,这就是 Let's Encrypt 与我们联系的方式!
|
||||
|
||||
现在,我们使用以下方法创建发行者:
|
||||
现在,我们使用以下方法创建<ruby>发行者<rt>issuer</rt></ruby>:
|
||||
|
||||
```
|
||||
kubectl apply -f letsencrypt-issuer-staging.yaml
|
||||
@ -150,7 +149,6 @@ kubectl get clusterissuers
|
||||
|
||||
创建一个包含以下内容的证书请求文件 `le-test-certificate.yaml`:
|
||||
|
||||
|
||||
```
|
||||
apiVersion: cert-manager.io/v1alpha2
|
||||
kind: Certificate
|
||||
@ -167,7 +165,7 @@ spec:
|
||||
- k3s.carpie.net
|
||||
```
|
||||
|
||||
该记录仅表示我们要使用名为 `letsencrypt-staging`(我们在上一步中创建的)的 `ClusterIssuer` 来请求域 [k3s.carpie.net][10] 的证书,并在 Kubernetes 的机密信息中名为 `k3s-carpie-net-tls` 文件中存储该证书。
|
||||
该记录仅表示我们要使用名为 `letsencrypt-staging`(我们在上一步中创建的)的 `ClusterIssuer` 来请求域 [k3s.carpie.net][10] 的证书,并在 Kubernetes 的机密信息中名为 `k3s-carpie-net-tls` 的文件中存储该证书。
|
||||
|
||||
像平常一样应用它:
|
||||
|
||||
@ -188,11 +186,11 @@ NAME READY SECRET AGE
|
||||
k3s-carpie-net True k3s-carpie-net-tls 30s
|
||||
```
|
||||
|
||||
我们走在幸福之路!(这里的关键是`READY` 是 `True`)。
|
||||
我们走在幸福之路!(这里的关键是 `READY` 应该是 `True`)。
|
||||
|
||||
### 解决证书颁发问题
|
||||
|
||||
上面是幸福的道路。如果 `READY` 为 `False`,我们可以等等它,然后再次花点时间检查状态。如果它一直是 `False`,那么我们就有一个需要解决的问题。此时,我们可以遍历 Kubernetes 资源链,直到找到一条告诉我们问题的状态消息。
|
||||
上面是幸福的道路。如果 `READY` 为 `False`,我们可以等等它,然后再次花点时间检查状态。如果它一直是 `False`,那么我们就有需要解决的问题。此时,我们可以遍历 Kubernetes 资源链,直到找到一条告诉我们问题的状态消息。
|
||||
|
||||
假设我们执行了上面的请求,而 `READY` 为 `False`。我们可以从以下方面开始故障排除:
|
||||
|
||||
@ -200,7 +198,7 @@ k3s-carpie-net True k3s-carpie-net-tls 30s
|
||||
kubectl describe certificates k3s-carpie-net
|
||||
```
|
||||
|
||||
这将返回很多信息。通常,有用的内容位于 `Events:` 部分,该部分通常位于底部。假设最后一个事件是 `Created new CertificateRequest resource "k3s-carpie-net-1256631848`。然后我们<ruby>描述<rt> describe</rt></ruby>一些该请求:
|
||||
这将返回很多信息。通常,有用的内容位于 `Events:` 部分,该部分通常位于底部。假设最后一个事件是 `Created new CertificateRequest resource "k3s-carpie-net-1256631848`。然后我们<ruby>描述<rt>describe</rt></ruby>一下该请求:
|
||||
|
||||
```
|
||||
kubectl describe certificaterequest k3s-carpie-net-1256631848
|
||||
@ -211,7 +209,7 @@ kubectl describe certificaterequest k3s-carpie-net-1256631848
|
||||
那么,我们可以描述该顺序:
|
||||
|
||||
```
|
||||
`kubectl describe orders default/k3s-carpie-net-1256631848-2342473830`
|
||||
kubectl describe orders default/k3s-carpie-net-1256631848-2342473830
|
||||
```
|
||||
|
||||
假设有一个事件,事件为 `Created Challenge resource "k3s-carpie-net-1256631848-2342473830-1892150396" for domain "k3s.carpie.net"`。让我们描述一下该质询:
|
||||
@ -220,7 +218,7 @@ kubectl describe certificaterequest k3s-carpie-net-1256631848
|
||||
kubectl describe challenges k3s-carpie-net-1256631848-2342473830-1892150396
|
||||
```
|
||||
|
||||
从这里返回的最后一个事件是 `Presented challenge using http-01 challenge mechanism`。看起来没问题,因此我们浏览一下描述的输出,并看到一条消息 `Waiting for http-01 challenge propagation: failed to perform self check GET request … no such host`。终于!我们发现了问题!在这种情况下,`no such host` 意味着 DNS 查找失败,因此我们需要返回并手动检查我们的 DNS 设置,正确解析域的 DNS,并进行所需的任何更改。
|
||||
从这里返回的最后一个事件是 `Presented challenge using http-01 challenge mechanism`。看起来没问题,因此我们浏览一下描述的输出,并看到一条消息 `Waiting for http-01 challenge propagation: failed to perform self check GET request ... no such host`。终于!我们发现了问题!在这种情况下,`no such host` 意味着 DNS 查找失败,因此我们需要返回并手动检查我们的 DNS 设置,正确解析域的 DNS,并进行所需的任何更改。
|
||||
|
||||
### 清理我们的测试证书
|
||||
|
||||
@ -231,9 +229,9 @@ kubectl delete certificates k3s-carpie-net
|
||||
kubectl delete secrets k3s-carpie-net-tls
|
||||
```
|
||||
|
||||
### 配置 cert-manager 以使用 Let's Encrypt(生产环境)
|
||||
### 配置 cert-manager 以使用 Let's Encrypt(生产环境)
|
||||
|
||||
现在我们已经有了测试证书,是时候移动到生产环境了。就像我们在 Let's Encrypt 暂存环境中配置 cert-manager 一样,我们现在也需要对生产环境进行同样的操作。创建一个名为 `letsencrypt-issuer-production.yaml` 的文件(如果需要,可以复制和修改暂存环境的文件),其内容如下:
|
||||
现在我们已经有了测试证书,是时候移动到生产环境了。就像我们在 Let's Encrypt 暂存环境中配置 cert-manager 一样,我们现在也需要对生产环境进行同样的操作。创建一个名为 `letsencrypt-issuer-production.yaml` 的文件(如果需要,可以复制和修改暂存环境的文件),其内容如下:
|
||||
|
||||
```
|
||||
apiVersion: cert-manager.io/v1alpha2
|
||||
@ -266,7 +264,7 @@ kubectl apply -f letsencrypt-issuer-production.yaml
|
||||
|
||||
### 申请我们网站的证书
|
||||
|
||||
重要的是要注意,我们到目前为止完成的所有步骤都是一次性设置的!对于将来的任何其他申请,我们可以从这个说明开始!
|
||||
重要的是需要注意,我们到目前为止完成的所有步骤都只需要进行一次!而对于将来的任何其他申请,我们可以从这个说明开始!
|
||||
|
||||
让我们部署在[上一篇文章][13]中部署的同样站点。(如果仍然可用,则可以修改 YAML 文件。如果没有,则可能需要重新创建并重新部署它)。
|
||||
|
||||
@ -296,7 +294,7 @@ spec:
|
||||
secretName: k3s-carpie-net-tls
|
||||
```
|
||||
|
||||
请注意,上面仅显示了 `mysite.yaml` 的 `Ingress` 部分。所做的更改是添加了注释 `cert-manager.io/cluster-issuer: letsencrypt-prod`。这告诉 traefik 创建证书时使用哪个发行者。 唯一的其他增加是 `tls:` 块。这告诉 traefik 我们希望在主机 [k3s.carpie.net][10] 上具有 TLS 功能,并且我们希望 TLS 证书文件存储在机密信息 `k3s-carpie-net-tls` 中。
|
||||
请注意,上面仅显示了 `mysite.yaml` 的 `Ingress` 部分。所做的更改是添加了注解 `cert-manager.io/cluster-issuer: letsencrypt-prod`。这告诉 traefik 创建证书时使用哪个发行者。 其他唯一增加的是 `tls:` 块。这告诉 traefik 我们希望在主机 [k3s.carpie.net][10] 上具有 TLS 功能,并且我们希望 TLS 证书文件存储在机密信息 `k3s-carpie-net-tls` 中。
|
||||
|
||||
请记住,我们没有创建这些证书!(好吧,我们创建了名称相似的测试证书,但我们删除了这些证书。)Traefik 将读取这些配置并继续寻找机密信息。当找不到时,它会看到注释说我们想使用 `letsencrypt-prod` 发行者来获取它。由此,它将提出请求并为我们安装证书到机密信息之中!
|
||||
|
||||
@ -311,17 +309,17 @@ via: https://opensource.com/article/20/3/ssl-letsencrypt-k3s
|
||||
作者:[Lee Carpenter][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/carpie
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/files_documents_paper_folder.png?itok=eIJWac15 (Files in a folder)
|
||||
[2]: https://carpie.net/articles/ingressing-with-k3s
|
||||
[2]: https://linux.cn/article-12081-1.html
|
||||
[3]: https://cert-manager.io/
|
||||
[4]: https://letsencrypt.org/
|
||||
[5]: https://opensource.com/article/20/3/kubernetes-raspberry-pi-k3s
|
||||
[5]: https://linux.cn/article-12049-1.html
|
||||
[6]: https://cloudflare.com/
|
||||
[7]: https://gitlab.com/carpie/k3s_using_certmanager/-/archive/master/k3s_using_certmanager-master.zip
|
||||
[8]: https://cert-manager.io/docs/installation/kubernetes/
|
||||
@ -329,5 +327,5 @@ via: https://opensource.com/article/20/3/ssl-letsencrypt-k3s
|
||||
[10]: http://k3s.carpie.net
|
||||
[11]: https://opensource.com/sites/default/files/uploads/ep011_dns_example.png
|
||||
[12]: https://opensource.com/sites/default/files/uploads/ep011_router.png
|
||||
[13]: https://carpie.net/articles/ingressing-with-k3s#deploying-a-simple-website
|
||||
[13]:https://linux.cn/article-12081-1.html
|
||||
[14]: http://cert-manager.io/cluster-issuer
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user