mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-29 21:41:00 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
85da25e890
@ -1,44 +1,43 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (gxlct008)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-12984-1.html)
|
||||
[#]: subject: (Go channels are bad and you should feel bad)
|
||||
[#]: via: (https://www.jtolio.com/2016/03/go-channels-are-bad-and-you-should-feel-bad)
|
||||
[#]: author: (jtolio.com https://www.jtolio.com/)
|
||||
|
||||
Go 通道不好,你也应该感到不好受
|
||||
Go 通道是糟糕的,你应该也觉得很糟糕
|
||||
======
|
||||
|
||||
_更新:如果你是从一篇题为 《Go is not good》 的概要文章来看这篇博文的话,那么我想表明的是,我很惭愧自己被列在这样的名单上。 Go 绝对是我使用过的最不糟糕的的编程语言。在我写作本文时,我想遏制我所看到的一种趋势,那就是过度使用 Go 的一些较复杂的部分。我仍然认为 <ruby>
|
||||
通道<rt>Channels</rt>
|
||||
</ruby>可以更好,但是总体而言,Go 很棒。这就像你最喜欢的工具箱中包含 [这个][1] 一样;这个工具可用(即使可能有更多用途),而且它仍然可以是你最喜欢的工具箱!_
|
||||
![](https://img.linux.net.cn/data/attachment/album/202101/05/101049y2995vz8l9mdg4bz.jpg)
|
||||
|
||||
_更新 2:如果我没有指出这项对真实问题的优秀调查,那我将是失职的:[理解 Go 中的实际并发错误][2]。这项调查的一个重要发现是...,Go 通道会导致很多错误。_
|
||||
更新:如果你是从一篇题为 《[糟糕的 Go 语言](https://github.com/ksimka/go-is-not-good)》 的汇编文章看到这篇博文的话,那么我想表明的是,我很惭愧被列在这样的名单上。Go 绝对是我使用过的最不糟糕的的编程语言。在我写作本文时,我是想遏制我所看到的一种趋势,那就是过度使用 Go 的一些较复杂的部分。我仍然认为 <ruby>
|
||||
通道<rt>Channel</rt></ruby>可以更好,但是总体而言,Go 很棒。这就像你最喜欢的工具箱中有 [这个工具][1];它可以有用途(甚至还可能有更多的用途),它仍然可以成为你最喜欢的工具箱!
|
||||
|
||||
从 2010 年中后期开始,我就断断续续地在使用 Google 的 [Go 编程语言][3],自 2012 年 1 月开始(在 Go 1.0 之前!),我就用 Go 为 [Space Monkey][4] 编写了合法的产品代码。我对 Go 的最初体验可以追溯到我在研究 Hoare 的 [通信顺序进程][5] 并发模型和 [Matt Might][7] 的 [UCombinator 研究组][8] 下的 [π-演算][6] 时,作为我([现在已重定向][9])博士工作的一部分,以更好地支持多核开发。Go 就是在那时发布的(多么巧合啊!),我当即就开始学习尝试了。
|
||||
更新 2:如果我没有指出这项对真实问题的优秀调查,那我将是失职的:《[理解 Go 中的实际并发错误][2]》。这项调查的一个重要发现是...Go 通道会导致很多错误。
|
||||
|
||||
从 2010 年中后期开始,我就断断续续地在使用 Google 的 [Go 编程语言][3],自 2012 年 1 月开始(在 Go 1.0 之前!),我就用 Go 为 [Space Monkey][4] 编写了合规的产品代码。我对 Go 的最初体验可以追溯到我在研究 Hoare 的 [通信顺序进程][5] 并发模型和 [Matt Might][7] 的 [UCombinator 研究组][8] 下的 [π-演算][6] 时,作为我([现在已重定向][9])博士工作的一部分,以更好地支持多核开发。Go 就是在那时发布的(多么巧合啊!),我当即就开始学习尝试了。
|
||||
|
||||
它很快就成为了 Space Monkey 开发的核心部分。目前,我们在 Space Monkey 的生产系统有超过 42.5 万行的纯 Go 代码(_不_ 包括我们所有的 vendored 库中的代码量,这将使它接近 150 万行),所以也并不是你见过的最多的 Go 代码,但是对于相对年轻的语言,我们是重度用户。我们之前 [写了我们的 Go 用法][10]。也开源了一些使用率很高的库;许多人似乎是我们的 [OpenSSL 绑定][11](比 [crypto/tls][12] 更快,但请保持 openssl 本身是最新的!)、我们的 [错误处理库][13]、[日志库][14] 和 [度量标准收集库/zipkin 客户端][15] 的粉丝。我们使用 Go、我们热爱 Go、我们认为它是目前为止我们使用过的最不糟糕的、符合我们需求的编程语言。
|
||||
它很快就成为了 Space Monkey 开发的核心部分。目前,我们在 Space Monkey 的生产系统有超过 42.5 万行的纯 Go 代码(_不_ 包括我们所有的 vendored 库中的代码量,这将使它接近 150 万行),所以也并不是你见过的最多的 Go 代码,但是对于相对年轻的语言,我们是重度用户。我们之前 [写了我们的 Go 使用情况][10]。也开源了一些使用率很高的库;许多人似乎是我们的 [OpenSSL 绑定][11](比 [crypto/tls][12] 更快,但请保持 openssl 本身是最新的!)、我们的 [错误处理库][13]、[日志库][14] 和 [度量标准收集库/zipkin 客户端][15] 的粉丝。我们使用 Go、我们热爱 Go、我们认为它是目前为止我们使用过的最不糟糕的、符合我们需求的编程语言。
|
||||
|
||||
尽管我也不认为我能说服自己不要提及我的广泛避免 [goroutine-local-storage 库][16] (尽管它是一个你不应该使用的 hack,但它是一个漂亮的 hack),希望我的其他经历足以证明我在解释我故意煽动性的帖子标题之前知道我在说什么。
|
||||
尽管我也不认为我能说服自己不要提及我的广泛避免使用 [goroutine-local-storage 库][16] (尽管它是一个你不应该使用的魔改技巧,但它是一个漂亮的魔改),希望我的其他经历足以证明我在解释我故意煽动性的帖子标题之前知道我在说什么。
|
||||
|
||||
![][17]
|
||||
|
||||
### 等等,什么?
|
||||
|
||||
如果你在大街上问一个有名的程序员,Go 有什么特别之处? 她很可能会告诉你 Go 最出名的是<ruby>通道<rt>Channels</rt></ruby> 和 goroutine。 Go 的理论基础很大程度上是建立在 Hoare 的 CSP (<ruby>通信顺序进程<rt>Communicating Sequential Processes</rt></ruby>) 模型上的,该模型本身令人着迷且有趣,我坚信,到目前为止,我们产生的收益远远超过了我们的预期。
|
||||
如果你在大街上问一个有名的程序员,Go 有什么特别之处? 她很可能会告诉你 Go 最出名的是<ruby>通道<rt>Channels</rt></ruby> 和 goroutine。 Go 的理论基础很大程度上是建立在 Hoare 的 CSP(<ruby>通信顺序进程<rt>Communicating Sequential Processes</rt></ruby>)模型上的,该模型本身令人着迷且有趣,我坚信,到目前为止,它产生的收益远远超过了我们的预期。
|
||||
|
||||
CSP(和 π-演算)都使用通信作为核心同步原语,因此 Go 会有通道是有道理的。Rob Pike 对 CSP 着迷(有充分的理由)[相当深][18] 已经有一段时间了。([当时][19] 和 [现在][20])。
|
||||
CSP(和 π-演算)都使用通信作为核心同步原语,因此 Go 会有通道是有道理的。Rob Pike 对 CSP 着迷(有充分的理由)[相当深][18] 已经有一段时间了。([当时][19] 和 [现在][20])。
|
||||
|
||||
但是从务实的角度来看(也是 Go 引以为豪的),Go 把通道搞错了。在这一点上,实现的通道在我的书中几乎是一个坚实的反模式。为什么?亲爱的读者,让我细数其中的方法。
|
||||
但是从务实的角度来看(也是 Go 引以为豪的),Go 把通道搞错了。在这一点上,通道的实现在我的书中几乎是一个坚实的反模式。为什么这么说呢?亲爱的读者,让我细数其中的方法。
|
||||
|
||||
#### 你可能最终不会只使用通道。
|
||||
#### 你可能最终不会只使用通道
|
||||
|
||||
Hoare 的 “通信顺序进程” 是一种计算模型,实际上,唯一的同步原语是在通道上发送或接收的。一旦使用 <ruby>互斥量<rt>mutex</rt></ruby>、<ruby>信号量<rt>semaphore</rt></ruby> 或 <ruby>条件变量<rt>condition variable</rt></ruby>、bam,你就不再处于纯 CSP 领域。 Go 程序员经常通过高呼 [缓存的思想][21] “[通过交流共享内存][22]” 来宣扬这种模式和哲学。
|
||||
Hoare 的 “通信顺序进程” 是一种计算模型,实际上,唯一的同步原语是在通道上发送或接收的。一旦使用 <ruby>互斥量<rt>mutex</rt></ruby>、<ruby>信号量<rt>semaphore</rt></ruby> 或 <ruby>条件变量<rt>condition variable</rt></ruby>、bam,你就不再处于纯 CSP 领域。 Go 程序员经常通过高呼 “[通过交流共享内存][22]” 的 [缓存的思想][21] 来宣扬这种模式和哲学。
|
||||
|
||||
|
||||
所以,让我们尝试在 Go 中仅使用 CSP 编写一个小程序!让我们成为高分接收者。我们要做的就是跟踪我们看到的最大的高分值。如此而已。
|
||||
那么,让我们尝试在 Go 中仅使用 CSP 编写一个小程序!让我们成为高分接收者。我们要做的就是跟踪我们看到的最大的高分值。如此而已。
|
||||
|
||||
首先,我们将创建一个 `Game` 结构体。
|
||||
|
||||
@ -82,7 +81,7 @@ type Player interface {
|
||||
}
|
||||
```
|
||||
|
||||
为了处理 `player`,我们假设所有错误都是致命的,并将获得的比分向下传递到通道。
|
||||
为了处理 `Player`,我们假设所有错误都是致命的,并将获得的比分向下传递到通道。
|
||||
|
||||
```
|
||||
func (g *Game) HandlePlayer(p Player) error {
|
||||
@ -100,7 +99,6 @@ func (g *Game) HandlePlayer(p Player) error {
|
||||
|
||||
你圆满完成了自己的开发工作,并开始拥有客户。你将这个游戏服务器公开,就取得了令人难以置信的成功!你的游戏服务器上也许正在创建许多游戏。
|
||||
|
||||
|
||||
很快,你发现人们有时会离开你的游戏。许多游戏不再有任何玩家在玩,但没有任何东西可以阻止游戏运行的循环。死掉的 `(*Game).run` goroutines 让你不知所措。
|
||||
|
||||
**挑战:** 在无需互斥量或 panics 的情况下修复上面的 goroutine 泄漏。实际上,可以滚动到上面的代码,并想出一个仅使用通道来解决此问题的方案。
|
||||
@ -134,17 +132,17 @@ func (g *Game) HandlePlayer(p Player) error {
|
||||
}
|
||||
```
|
||||
|
||||
你想选择哪一个?不要被欺骗了,以为通道的解决方案可以使它在更复杂的情况下更具可读性和可理解性。<ruby>拆解<rt>Teardown</rt></ruby>是非常困难的。这种拆解若用<ruby>互斥量<rt>mutex</rt></ruby>来做那只是小菜一碟,但最困难的是只使用 Go 专用通道来解决。另外,如果有人回复说发送通道的通道更容易推理,那么这将使我立即采取行动。
|
||||
你想选择哪一个?不要被欺骗了,以为通道的解决方案可以使它在更复杂的情况下更具可读性和可理解性。<ruby>拆解<rt>Teardown</rt></ruby>是非常困难的。这种拆解若用<ruby>互斥量<rt>mutex</rt></ruby>来做那只是小菜一碟,但最困难的是只使用 Go 专用通道来解决。另外,如果有人回复说发送通道的通道更容易推理,我马上就是感到头疼。
|
||||
|
||||
重要的是,这个特殊的情况可能真的 **很容易** 解决,而通道有一些运行时的帮助 Go 没有提供!不幸的是,就目前的情况来看,与 Go 的 CSP 版本相比,使用传统的<ruby>同步原语<rt>synchronization primitives</rt></ruby>可以更好地解决很多问题,这是令人惊讶的。稍后,我们将讨论 Go 可以做些什么来简化此案例。
|
||||
重要的是,这个特殊的情况可能真的 **很容易** 解决,而通道有一些运行时的帮助,而 Go 没有提供!不幸的是,就目前的情况来看,与 Go 的 CSP 版本相比,使用传统的<ruby>同步原语<rt>synchronization primitives</rt></ruby>可以更好地解决很多问题,这是令人惊讶的。稍后,我们将讨论 Go 可以做些什么来简化此案例。
|
||||
|
||||
**练习:** 还在怀疑? 试着让上面两种解决方案(channel-only vs mutex-only)在一旦 `bestScore` 大于或等于 100 时,就停止向 `Players` 索要分数。继续打开你的文本编辑器。这是一个很小的玩具问题。
|
||||
**练习:** 还在怀疑? 试着让上面两种解决方案(只使用通道与只使用互斥量channel-only vs mutex-only)在一旦 `bestScore` 大于或等于 100 时,就停止向 `Players` 索要分数。继续打开你的文本编辑器。这是一个很小的玩具问题。
|
||||
|
||||
这里的总结是,如果你想做任何实际的事情,除了通道之外,你还会使用传统的同步原语。
|
||||
|
||||
#### 通道比你自己实现要慢一些
|
||||
|
||||
Go 如此重视 CSP 理论,我认为其中一点就是,运行时应该可以通过通道做一些杀手级的调度优化。也许通道并不总是最直接的基元,但肯定是高效且快速的,对吧?
|
||||
Go 如此重视 CSP 理论,我认为其中一点就是,运行时应该可以通过通道做一些杀手级的调度优化。也许通道并不总是最直接的原语,但肯定是高效且快速的,对吧?
|
||||
|
||||
![][23]
|
||||
|
||||
@ -164,7 +162,7 @@ Go 如此重视 CSP 理论,我认为其中一点就是,运行时应该可以
|
||||
|
||||
#### 通道与其他并发原语组合不佳
|
||||
|
||||
好的,希望我已经说服了你,有时候,你至少还会与除了通道之外的基元进行交互。标准库似乎显然更喜欢传统的同步基元而不是通道。
|
||||
好的,希望我已经说服了你,有时候,你至少还会与除了通道之外的原语进行交互。标准库似乎显然更喜欢传统的同步原语而不是通道。
|
||||
|
||||
你猜怎么着,正确地将通道与互斥量和条件变量一起使用,其实是有一定的挑战性的。
|
||||
|
||||
@ -172,14 +170,13 @@ Go 如此重视 CSP 理论,我认为其中一点就是,运行时应该可以
|
||||
|
||||
![][26]
|
||||
|
||||
实事求是地说,Go 通道也有多种缓冲方式。你可以分配一个固定的空间来考虑可能的缓冲,以便发送和接收是不同的事件,但缓冲区大小是有上限的。Go 并没有提供一种方法来让你拥有任意大小的缓冲区 —— 你必须提前分配缓冲区大小。 *这很好*,我在邮件列表上看到有人在争论,*因为无论如何内存都是有限的*。
|
||||
|
||||
实事求是地说,Go 通道也有多种缓冲方式。你可以分配一个固定的空间来考虑可能的缓冲,以便发送和接收是不同的事件,但缓冲区大小是有上限的。Go 并没有提供一种方法来拥有任意大小的缓冲区--你必须提前分配缓冲区大小。 *这很好*,我已经看到有人在在邮件列表上争论,*因为无论如何内存都是有限的*。
|
||||
|
||||
What.
|
||||
What。
|
||||
|
||||
这是个糟糕的答案。有各种各样的理由来使用一个任意缓冲的通道。如果我们事先知道所有的事情,为什么还要使用 `malloc` 呢?
|
||||
|
||||
没有任意缓冲的通道意味着在 *任何* 通道上的幼稚发送可能会随时阻塞。你想在一个通道上发送,并在互斥下更新其他一些簿记功能吗?小心!你的通道发送可能被阻塞!
|
||||
没有任意缓冲的通道意味着在 *任何* 通道上的幼稚发送可能会随时阻塞。你想在一个通道上发送,并在互斥下更新其他一些记账吗?小心!你的通道发送可能被阻塞!
|
||||
|
||||
```
|
||||
// ...
|
||||
@ -194,7 +191,6 @@ s.mtx.Unlock()
|
||||
|
||||
有一种方法可以在 Go 中的通道上进行非阻塞发送,但这不是默认行为。假设我们有一个通道 `ch := make(chan int)`,我们希望在其上无阻塞地发送值 `1`。以下是在不阻塞的情况下你必须要做的最小量的输入:
|
||||
|
||||
|
||||
```
|
||||
select {
|
||||
case ch <- 1: // it sent
|
||||
@ -206,23 +202,21 @@ default: // it didn't
|
||||
|
||||
综上所述,因为通道上的很多操作都会阻塞,所以需要对哲学家及其就餐仔细推理,才能在互斥量的保护下,成功地将通道操作与之并列使用,而不会造成死锁。
|
||||
|
||||
#### 严格来说,回调更强大,不需要不必要的 goroutines.
|
||||
#### 严格来说,回调更强大,不需要不必要的 goroutines
|
||||
|
||||
![][27]
|
||||
|
||||
每当 API 使用通道时,或者每当我指出通道使某些事情变得困难时,总会有人会指出我应该启动一个 goroutine 来读取该通道,并在读取该通道时进行所需的任何转换或修复。
|
||||
|
||||
呃,不。如果我的代码位于热路径中怎么办?需要通道的实例很少,如果你的 API 可以设计为使用<ruby>互斥量<rt>mutexes</rt></ruby>、<ruby>信号量<rt>semaphores</rt></ruby>和<ruby>回调<rt>callbacks</rt></ruby>,而不使用额外的 goroutine (因为所有事件边缘都是由 API 事件触发的),那么使用通道会迫使我在资源使用中添加另一个内存分配堆栈。是的,goroutine 比线程轻得多,但更轻量并不意味着是最轻量。
|
||||
呃,不。如果我的代码位于热路径中怎么办?需要通道的实例很少,如果你的 API 可以设计为使用<ruby>互斥量<rt>mutexes</rt></ruby>、<ruby>信号量<rt>semaphores</rt></ruby>和<ruby>回调<rt>callbacks</rt></ruby>,而不使用额外的 goroutine (因为所有事件边缘都是由 API 事件触发的),那么使用通道会迫使我在资源使用中添加另一个内存分配堆栈。是的,goroutine 比线程轻得多,但更轻量并不意味着是最轻量。
|
||||
|
||||
|
||||
正如我以前 [在一篇关于使用通道的文章的评论中争论过的][28](lol the internet),如果你使用回调而不是通道,你的 API 可以 *总是* 更通用,*总是* 更灵活,而且占用的资源也会大大减少。"总是" 是一个可怕的词,但我在这里是认真的。有证据级的东西在进行。
|
||||
正如我以前 [在一篇关于使用通道的文章的评论中争论过的][28](呵呵,互联网),如果你使用回调而不是通道,你的 API *总是* 可以更通用,*总是* 更灵活,而且占用的资源也会大大减少。“总是” 是一个可怕的词,但我在这里是认真的。有证据级的东西在进行。
|
||||
|
||||
如果有人向你提供了一个基于回调的 API,而你需要一个通道,你可以提供一个回调,在通道上发送,开销不大,灵活性十足。
|
||||
|
||||
另一方面,如果有人提供了一个基于通道的 API 给你,而你需要一个回调,你必须启动一个 goroutine 来读取通道 *并且* 你必须希望当你完成读取时,没有人试图在通道上发送更多的东西,这样你就会导致阻塞的 goroutine 泄漏。
|
||||
另一方面,如果有人提供了一个基于通道的 API 给你,而你需要一个回调,你必须启动一个 goroutine 来读取通道,*并且* 你必须希望当你完成读取时,没有人试图在通道上发送更多的东西,这样你就会导致阻塞的 goroutine 泄漏。
|
||||
|
||||
|
||||
对于一个超级简单的实际例子,请查看 [context interface][29] (顺便说一下,它是一个非常有用的包,你应该用它来代替 [goroutine-local storage][16] )。
|
||||
对于一个超级简单的实际例子,请查看 [context 接口][29](顺便说一下,它是一个非常有用的包,你应该用它来代替 [goroutine 本地存储][16])。
|
||||
|
||||
```
|
||||
type Context interface {
|
||||
@ -239,6 +233,7 @@ type Context interface {
|
||||
```
|
||||
|
||||
想象一下,你要做的只是在 `Done()` 通道触发时记录相应的错误。你该怎么办?如果你没有在通道中选择的好地方,则必须启动 goroutine 进行处理:
|
||||
|
||||
```
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
@ -255,17 +250,16 @@ go func() {
|
||||
Done(cb func())
|
||||
```
|
||||
|
||||
首先,现在登录非常容易。签出:`ctx.Done(func() { log.Errorf ("canceled:%v", ctx.Err()) })`。但是可以说你确实需要某些选择行为。你可以这样调用它:
|
||||
首先,现在日志记录非常容易。看看:`ctx.Done(func() { log.Errorf ("canceled:%v", ctx.Err()) })`。但是假设你确实需要某些选择行为。你可以这样调用它:
|
||||
|
||||
```
|
||||
ch := make(chan struct{})
|
||||
ctx.Done(func() { close(ch) })
|
||||
```
|
||||
|
||||
瞧!通过使用回调,不会失去表现力。 `ch` 的工作方式类似于用于返回的通道 `Done()`,在日志记录的情况下,我们不需要旋转整个新堆栈。我必须保留堆栈跟踪信息(如果我们的日志包倾向于使用它们);我必须避免将其他堆栈分配和另一个 goroutine 分配给调度程序。
|
||||
瞧!通过使用回调,不会失去表现力。 `ch` 的工作方式类似于用于返回的通道 `Done()`,在日志记录的情况下,我们不需要启动整个新堆栈。我必须保留堆栈跟踪信息(如果我们的日志包倾向于使用它们);我必须避免将其他堆栈分配和另一个 goroutine 分配给调度程序。
|
||||
|
||||
|
||||
下次你使用通道时,问问你自己,如果你用互斥量和条件变量代替,是否有一些 goroutine 可以消除? 如果答案是肯定的,那么修改代码将更加有效。而且,如果你试图使用通道只是为了在集合中使用 `range` 关键字,那么我将不得不请你放下键盘,或者只是回去编写 Python 书籍。
|
||||
下次你使用通道时,问问你自己,如果你用互斥量和条件变量代替,是否可以消除一些 goroutine ? 如果答案是肯定的,那么修改这些代码将更加有效。而且,如果你试图使用通道只是为了在集合中使用 `range` 关键字,那么我将不得不请你放下键盘,或者只是回去编写 Python 书籍。
|
||||
|
||||
![more like Zooey De-channel, amirite][30]
|
||||
|
||||
@ -273,28 +267,25 @@ ctx.Done(func() { close(ch) })
|
||||
|
||||
在通道已关闭的情况下,执行关闭或发送消息将会引发 panics!为什么呢? 如果想要关闭通道,你需要在外部同步它的关闭状态(使用互斥量等,这些互斥量的组合不是很好!),这样其他写入者才不会写入或关闭已关闭的通道,或者只是向前冲,关闭或写入已关闭的通道,并期望你必须恢复所有引发的 panics。
|
||||
|
||||
这是多么怪异的行为。 Go 中几乎所有其他操作都有避免 panic 的方法(例如,类型断言具有 `,ok =` 模式),但是对于通道,你只能自己动手处理它。
|
||||
这是多么怪异的行为。 Go 中几乎所有其他操作都有避免 panic 的方法(例如,类型断言具有 `, ok =` 模式),但是对于通道,你只能自己动手处理它。
|
||||
|
||||
好的,所以当发送失败时,通道会出现 panic。我想这是有一定道理的。但是,与几乎所有其他带有 nil 值的东西不同,发送到 nil 通道不会引发 panic。相反,它将永远阻塞!这很违反直觉。这可能是有用的行为,就像在你的除草器上附加一个开罐器,可能有用(在 Skymall 可以找到)一样,但这肯定是意想不到的。与 nil 映射(执行隐式指针解除引用),nil 接口(隐式指针解除引用),未经检查的类型断言以及其他所有类型交互不同,nil 通道表现出实际的通道行为,就好像为该操作实例化了一个全新的通道一样。
|
||||
好吧,所以当发送失败时,通道会出现 panic。我想这是有一定道理的。但是,与几乎所有其他带有 nil 值的东西不同,发送到 nil 通道不会引发 panic。相反,它将永远阻塞!这很违反直觉。这可能是有用的行为,就像在你的除草器上附加一个开罐器,可能有用(在 Skymall 可以找到)一样,但这肯定是意想不到的。与 nil 映射(执行隐式指针解除引用),nil 接口(隐式指针解除引用),未经检查的类型断言以及其他所有类型交互不同,nil 通道表现出实际的通道行为,就好像为该操作实例化了一个全新的通道一样。
|
||||
|
||||
接收稍微好一点。在已关闭的通道上执行接收会发生什么?好吧,那会是有效操作——你将得到一个零值。好吧,我想这是有道理的。奖金!接收允许你在收到值时进行 `,ok =`样式的检查,以确定通道是否打开。谢天谢地,我们在这里得到 `,ok =`。
|
||||
接收的情况稍微好一点。在已关闭的通道上执行接收会发生什么?好吧,那会是有效操作——你将得到一个零值。好吧,我想这是有道理的。奖励!接收允许你在收到值时进行 `, ok =` 样式的检查,以确定通道是否打开。谢天谢地,我们在这里得到了 `, ok =`。
|
||||
|
||||
但是,如果你从 nil 渠道接收会发生什么呢? *也是永远阻塞!* 耶!不要试图利用这样一个事实:如果你关闭了通道,那么你的通道是 nil!
|
||||
|
||||
### 通道有什么好处?
|
||||
|
||||
当然,通道对于某些事情是有好处的(毕竟它们是一个通用容器),有些事情你只能用它们来做(比如 `select`)。
|
||||
当然,通道对于某些事情是有好处的(毕竟它们是一个通用容器),有些事情你只能用它们来做(比如 `select`)。
|
||||
|
||||
#### 它们是另一种特殊情况下的通用数据结构
|
||||
|
||||
#### 它们是另一个特殊大小写的通用数据结构
|
||||
Go 程序员已经习惯于对泛型的争论,以至于我一提起这个词就能感觉到 PTSD(创伤后应激障碍)的到来。我不是来谈论这件事的,所以擦擦额头上的汗,让我们继续前进吧。
|
||||
|
||||
Go 程序员已经习惯于对泛型的争论,以至于我一提起这个词就能感觉到 PTSD (创伤后应激障碍)的到来。我不是来谈论这件事的,所以擦去额头上的汗水,让我们继续前进吧。
|
||||
无论你对泛型的看法是什么,Go 的映射、切片和通道都是支持泛型元素类型的数据结构,因为它们已经被特殊封装到语言中了。
|
||||
|
||||
无论你对泛型的看法是什么,Go的映射、切片和通道都是支持泛型元素类型的数据结构,因为它们已经被特殊化为语言。
|
||||
|
||||
无论你对泛型的看法如何,Go 的映射、切片和通道都是支持泛型元素类型的数据结构,因为它们在语言中已经过特殊处理。
|
||||
|
||||
在一种不允许你编写自己的泛型容器的语言中,任何允许你更好地管理事物集合的东西都是有价值的。在这里,通道是支持任意值类型的线程安全数据结构。
|
||||
在一种不允许你编写自己的泛型容器的语言中,任何允许你更好地管理事物集合的东西都是有价值的。在这里,通道是一个支持任意值类型的线程安全数据结构。
|
||||
|
||||
所以这很有用!我想这可以省去一些陈词滥调。
|
||||
|
||||
@ -304,8 +295,7 @@ Go 程序员已经习惯于对泛型的争论,以至于我一提起这个词
|
||||
|
||||
使用通道可以做的主要事情是 `select` 语句。在这里,你可以等待固定数量的事件输入。它有点像 epoll,但你必须预先知道要等待多少个套接字。
|
||||
|
||||
|
||||
这是真正有用的语言功能。如果不是 `select`,通道将被彻底清洗。但是我的天呐,让我告诉你,有关你第一次决定可能需要在多个事物中选择,但是你不知道有多少项,因此必须使用 `reflect.Select`。
|
||||
这是真正有用的语言功能。如果不是 `select`,通道将被彻底清洗。但是我的天呐,让我告诉你,第一次决定可能需要在多个事物中选择,但是你不知道有多少项,因此必须使用 `reflect.Select`。
|
||||
|
||||
### 通道如何才能更好?
|
||||
|
||||
@ -313,22 +303,19 @@ Go 程序员已经习惯于对泛型的争论,以至于我一提起这个词
|
||||
|
||||
#### 在条件变量上的 Select !
|
||||
|
||||
We could just obviate the need for channels! This is where I propose we get rid of some sacred cows, but let me ask you this, how great would it be if you could select on any custom synchronization primitive? (A: So great.) If we had that, we wouldn’t need channels at all.
|
||||
|
||||
我们可以不需要通道!这是我提议我们摆脱一些“圣牛”(神圣不可质疑的事物)的地方,但是让我问你,如果你可以选择任何自定义同步原语,那会有多棒? (答:太棒了。)如果有的话,我们根本就不需要通道了。
|
||||
我们可以不需要通道!这是我提议我们摆脱一些“<ruby>圣牛<rt>sacred cows</rt></ruby>”(LCTT 译注:神圣不可质疑的事物)的地方,但是让我问你,如果你可以选择任何自定义同步原语,那会有多棒?(答:太棒了。)如果有的话,我们根本就不需要通道了。
|
||||
|
||||
#### GC 可以帮助我们吗?
|
||||
|
||||
在第一个示例中,如果我们能够使用定向类型的通道垃圾回收来帮助我们进行清理,我们就可以轻松地解决通道的高分服务器清理问题。
|
||||
在第一个示例中,如果我们能够使用定向类型的通道垃圾回收(GC)来帮助我们进行清理,我们就可以轻松地解决通道的高分服务器清理问题。
|
||||
|
||||
![][31]
|
||||
|
||||
如你所知,Go 具有定向类型的通道。 你可以使用仅支持读取的通道类型(`<-chan`)和仅支持写入的通道类型(`chan<-`)。 这太棒了!
|
||||
|
||||
如您所知,Go 具有定向类型的通道。 您可以使用仅支持读取的通道类型(`<-chan`)和仅支持写入的通道类型(`chan <-`)。 这太棒了!
|
||||
Go 也有垃圾回收功能。 很明显,某些类型的记账方式太繁琐了,我们不应该让程序员去处理它们。 我们清理未使用的内存! 垃圾回收非常有用且整洁。
|
||||
|
||||
Go 也有垃圾收集功能。 很明显,某些类型的簿记方式太繁琐了,我们不应该让程序员去处理它们。 我们清理未使用的内存! 垃圾收集非常有用且整洁。
|
||||
|
||||
那么,为什么不帮助清理未使用或死锁的通道读取呢? 与其让 `make(chan Whatever)`返回一个双向通道,不如让它返回两个单向通道(`chanReader, chanWriter:= make(chan Type)`)。
|
||||
那么,为什么不帮助清理未使用或死锁的通道读取呢? 与其让 `make(chan Whatever)` 返回一个双向通道,不如让它返回两个单向通道(`chanReader, chanWriter:= make(chan Type)`)。
|
||||
|
||||
让我们重新考虑一下最初的示例:
|
||||
|
||||
@ -369,38 +356,35 @@ func (g *Game) HandlePlayer(p Player) error {
|
||||
}
|
||||
```
|
||||
|
||||
如果垃圾收集关闭了一个通道,而我们可以证明它永远不会有更多的值,那么这个解决方案是完全可行的。是的,是的,`run` 中的评论暗示着有一把相当大的枪瞄准了你的脚,但至少现在这个问题可以很容易地解决了,而以前确实不是这样。此外,一个聪明的编译器可能会做出适当的证明,以减少这种脚枪造成的损害。
|
||||
如果垃圾回收关闭了一个通道,而我们可以证明它永远不会有更多的值,那么这个解决方案是完全可行的。是的,是的,`run` 中的评论暗示着有一把相当大的枪瞄准了你的脚,但至少现在这个问题可以很容易地解决了,而以前确实不是这样。此外,一个聪明的编译器可能会做出适当的证明,以减少这种脚枪造成的损害。
|
||||
|
||||
#### 其他较小的问题
|
||||
#### 其他小问题
|
||||
|
||||
* **Dup 通道吗?** —— 如果我们可以在通道上使用等效于 `dup` 的系统调用,那么我们也可以很容易地解决多生产者问题。 每个生产者可以关闭自己的 `dup` 版通道,而不会破坏其他生产者。
|
||||
* **修复通道API!** —— 关闭不是幂等的吗? 在已关闭的通道上发送信息引起的 panics 没有办法避免吗? 啊!
|
||||
* **修复通道 API!** —— 关闭不是幂等的吗? 在已关闭的通道上发送信息引起的 panics 没有办法避免吗? 啊!
|
||||
* **任意缓冲的通道** —— 如果我们可以创建没有固定的缓冲区大小限制的缓冲通道,那么我们可以创建非阻塞的通道。
|
||||
|
||||
### 那我们该怎么向大家介绍 Go 呢?
|
||||
|
||||
如果你还没有,请看看我目前最喜欢的编程文章:[你的功能是什么颜色][32]。虽然不是专门针对 Go,但这篇博文比我更有说服力地阐述了为什么 goroutines 是 Go 最好的特性(这也是 Go 在某些应用程序中优于 Rust 的方法之一)。
|
||||
|
||||
如果你还没有,请看看我目前最喜欢的编程文章:《[你的函数是什么颜色][32]》。虽然不是专门针对 Go,但这篇博文比我更有说服力地阐述了为什么 goroutines 是 Go 最好的特性(这也是 Go 在某些应用程序中优于 Rust 的方式之一)。
|
||||
|
||||
如果你还在使用这样的一种编程语言写代码,它强迫你使用类似 `yield` 关键字来获得高性能、并发性或事件驱动的模型,那么你就是活在过去,不管你或其他人是否知道这一点。到目前为止,Go 是我所见过的实现 M:N 线程模型(非 1:1 )的语言中最好的入门者之一,而且这种模型非常强大。
|
||||
|
||||
所以,跟大家说说 goroutines 吧。
|
||||
|
||||
如果非要我选择 Go 的另一个主要特性,那就是接口。静态类型 [<ruby>鸭子模型<rt>duck typing</rt></ruby>][33] 使得扩展,使用你自己或他人的项目变得如此有趣而令人惊奇,这也许值得我改天再写一组完全不同的文字。
|
||||
|
||||
如果非要我选择 Go 的另一个主要特性,那就是接口。静态类型的 <ruby>[鸭子模型][33]<rt>duck typing</rt></ruby> 使得扩展、使用你自己或他人的项目变得如此有趣而令人惊奇,这也许值得我改天再写一组完全不同的文章来介绍它。
|
||||
|
||||
### 所以…
|
||||
|
||||
我一直看到人们争先恐后冲进 Go,渴望充分利用通道来发挥其全部潜力。这是我对你的建议。
|
||||
|
||||
**JUST STAHP IT**
|
||||
|
||||
当你在编写 API 和接口时,尽管“绝不”的建议可能很糟糕,但我非常肯定,从来没有什么时候通道是更好的,我用过的每一个使用通道的 Go API,最后都不得不与之抗争。我从来没有想过“哦 太好了,这里是一个通道;”它总是被一些变体取代,_**这是什么新鲜的地狱?**_
|
||||
**够了!**
|
||||
|
||||
当你在编写 API 和接口时,尽管“绝不”的建议可能很糟糕,但我非常肯定,通道从来没有什么时候好过,我用过的每一个使用通道的 Go API,最后都不得不与之抗争。我从来没有想过“哦 太好了,这里是一个通道;”它总是被一些变体取代,_**这是什么新鲜的地狱?**_
|
||||
|
||||
所以,_请在适当的地方,并且只在适当的地方使用通道。_
|
||||
|
||||
在我使用的所有 Go 代码中,我可以用一只手数出有多少次通道真的是最好的选择。有时候是这样的。太好了!。那就用它们吧。否则就别说了。
|
||||
在我使用的所有 Go 代码中,我可以用一只手数出有多少次通道真的是最好的选择。有时候是这样的。那很好!那就用它们吧。但除此之外,就不要再使用了。
|
||||
|
||||
![][34]
|
||||
|
||||
@ -412,10 +396,10 @@ _特别感谢我的校对读者 Jeff Wendling、[Andrew Harding][35]、[George S
|
||||
|
||||
via: https://www.jtolio.com/2016/03/go-channels-are-bad-and-you-should-feel-bad
|
||||
|
||||
作者:[jtolio.com][a]
|
||||
作者:[jtolds][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[gxlct008](https://github.com/gxlct008)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,76 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn to use the JOE text editor on Linux)
|
||||
[#]: via: (https://opensource.com/article/20/12/joe)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
Learn to use the JOE text editor on Linux
|
||||
======
|
||||
Joe's Own Editor (JOE) is a general text editor that is easy to learn
|
||||
and use.
|
||||
![Person programming on a laptop on a building][1]
|
||||
|
||||
I’m a fan of text editors that make it easy for you to learn how to use them. GNU nano is my favorite example of this: you launch nano, and you see a list of the most common commands along the bottom of the window throughout your entire session. Joe’s Own Editor (that’s `joe` for short) is another great example.
|
||||
|
||||
The `joe` editor uses a terminal-based interface, providing simple text editing capabilities and an easily accessible help screen. It’s written in C, it’s small with a hard dependency only on libc (ncurses is optional), and it’s licensed under the GPL.
|
||||
|
||||
### Installing
|
||||
|
||||
On Linux, you may be able to find JOE in your distribution’s software repository. It’s a little obscure, though, so not all distributions have packaged it. If that’s the case, you can download the source code from [SourceForge][2] and compile it yourself. It’s an easy process:
|
||||
|
||||
|
||||
```
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
### Using JOE
|
||||
|
||||
According to its author, JOE takes inspiration from an application called WordStar and from [GNU Emacs][3]. Most of its basic editing keys are the same as WordStar shortcuts, and the editor itself strives to approximate WordStar. JOE also has some of the key bindings and features of GNU Emacs. This mix of two sources of inspiration can sometimes be disorienting, but then again, weaning yourself off Emacs (or your usual text editor of choice) under any circumstance can be disorienting. The important thing is that JOE offers help, and it’s easy to reach.
|
||||
|
||||
In the top right corner of JOE’s interface, there’s a persistent reminder that you can press **Ctrl+K** followed immediately by **H** to view a help screen. This is a toggle, so once you activate it, the help screen remains displayed at the top of your editor window until dismissed with the same key combo (**^KH** in JOE’s keyboard notation).
|
||||
|
||||
### Keyboard shortcuts
|
||||
|
||||
For all the pride JOE’s author takes in simulating a WordStar user experience, I have to admit it’s lost on me. I’d never heard of WordStar until I read about it in JOE’s documentation, and to me, it seemed to have a completely arbitrary keyboard shortcut scheme. Some are prefixed with **Ctrl+K** as an escape sequence, while others use **Esc** as the prefix, and still others require no escape sequence at all. I couldn’t determine the logic. Editing operations were just as likely as application options to require an escape sequence or not, and few of the letter associations made sense to me (**Ctrl+K** **D** for **save as**, for instance).
|
||||
|
||||
Luckily, JOE lets you cheat on keyboard shortcuts. Upon installation, JOE quietly creates a few symlinks for the `joe` executable. Included are:
|
||||
|
||||
* `jmacs` JOE with Emacs key bindings
|
||||
* `jpico` JOE with Pico (or GNU nano) key bindings
|
||||
* `rjoe` JOE with editing restricted only to the file passed to JOE at launch
|
||||
* `jstar` JOE with WordStar key bindings
|
||||
|
||||
|
||||
|
||||
![Black terminal with white text showing WordStar key bindings][4]
|
||||
|
||||
The persistent help menu remains, so if you’re ever unclear as to what functions you have available to you, refer to them with the help prompt at the top right of the screen. Of course, in Pico/nano mode, the main commands are always visible.
|
||||
|
||||
### Try JOE
|
||||
|
||||
JOE isn’t intended as a text editor you’ll never leave. It won’t become your IDE, email client, web browser, and file manager. In fact, it may not even be your main text editor for all tasks. It focuses on being good at one thing, and that’s general text editing.
|
||||
|
||||
JOE has all of the essential functions you need, like the ability to navigate your text quickly, the ability to select text, copy and paste, and so on. Give JOE a try, using your preferred symlink.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/joe
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_code_programming_laptop.jpg?itok=ormv35tV (Person programming on a laptop on a building)
|
||||
[2]: https://joe-editor.sourceforge.io/
|
||||
[3]: https://opensource.com/article/20/12/emacs
|
||||
[4]: https://opensource.com/sites/default/files/uploads/joe-jstar-31_days-joe-opensource.png (Black terminal with white text showing WordStar key bindings)
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
94
sources/tech/20210104 10 ways Ansible is for everyone.md
Normal file
94
sources/tech/20210104 10 ways Ansible is for everyone.md
Normal file
@ -0,0 +1,94 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (10 ways Ansible is for everyone)
|
||||
[#]: via: (https://opensource.com/article/21/1/ansible)
|
||||
[#]: author: (James Farrell https://opensource.com/users/jamesf)
|
||||
|
||||
10 ways Ansible is for everyone
|
||||
======
|
||||
Expand your knowledge and skills with the top 10 Ansible articles plus
|
||||
five news summaries from 2020.
|
||||
![gears and lightbulb to represent innovation][1]
|
||||
|
||||
Here we are again at the end of another year with a great set of articles about Ansible from Opensource.com. I thought it would be nice to review them in a series of progressively advancing topics. I hope to help stimulate the interest of people just getting started with Ansible. There were also a series of summary articles, which I've included for your casual follow-up.
|
||||
|
||||
### Ansible for beginners
|
||||
|
||||
The first five articles on this year's list are a really good place for Ansible neophytes to start. The first three articles were written by Opensource.com editor Seth Kenlon.
|
||||
|
||||
* If you don't know much about Ansible, [_7 things you can do with Ansible right now_][2] is a great place to start. This is a nice primer that gathers links for managing hardware, cloud, containers, and more.
|
||||
* In [_What's the difference between orchestration and automation?_][3] you will learn some of the terms and baseline technologies that will help kick off your interest in Ansible.
|
||||
* [_How to install software with Ansible_][4] covers a few rudimentary concepts and some good Ansible habits, followed by simple examples on managing software packages on local and remote hosts.
|
||||
* In [_3 lessons I've learned writing Ansible playbooks_][5], set yourself right with good habits handed down by Jeff Geerling, a real Ansible veteran. Source control, documentation, testing, simplification, and optimization are the keys to automation success.
|
||||
* [_My first day using Ansible_][6] outlines Correspondent David Both's thought process for solving a repetitive development task. The article starts with a baseline of what Ansible needs and illustrates some simple plays and tasks.
|
||||
|
||||
|
||||
|
||||
### Ansible projects to try
|
||||
|
||||
Once you have the basics and some good habits, it's time to turn to more specific topics with concrete examples.
|
||||
|
||||
* [_Manage your Raspberry Pi fleet with Ansible_][7] by Ken Fallon walks through an example of deploying and managing fleets of RPi units. It presents concepts of security and maintenance in constrained environments.
|
||||
* In _[Integrate your calendar with Ansible to avoid schedule conflicts][8],_ Nicolas Leiva quickly introduces how to use pre-tasks and conditionals to enforce execution blackout windows in your automation schedule.
|
||||
* Nicolas completes his calendar blackout concept in [_Create an Ansible module for integrating your Google Calendar_][9]. His article dives into writing a custom Ansible module in Go to achieve the desired calendar connection. Nicolas introduces different ways to structure and invoke Go programs and pass the required data to Ansible and receive the desired output.
|
||||
|
||||
|
||||
|
||||
### Elevate your Ansible skills
|
||||
|
||||
Kubernetes is a hot topic these days, and the following articles offer some great examples to learn new skills.
|
||||
|
||||
* In [_Automate your container orchestration with Ansible modules for Kubernetes_][10], Seth Kenlon introduces the Ansible Kubernetes module, walks through a basic Minikube installation for testing, and presents some basic examples of the "k8s" module for pod control.
|
||||
* Jeff Geerling explains the concept of Helm Chart applications, Ansible collections, and executing a fun project to set up your own Minecraft server in a k8s cluster in [_Build a Kubernetes Minecraft server with Ansible's Helm modules_][11].
|
||||
|
||||
|
||||
|
||||
### Other Ansible news
|
||||
|
||||
This year, Mark Phillips delivered a series of "Ansible around the web" news articles covering a wide variety of Ansible topics. They are packed with links to interesting Ansible developments, ranging from basic tutorials, module writing, plugins, Kubernetes, video demonstrations, and Ansible community news. Check them all out—there are valuable nuggets to follow for all interests and skill levels!
|
||||
|
||||
* [_Containers, networks, security, and more Ansible news_][12]
|
||||
* [_Tips for CI/CD pipelines and Windows users, and more Ansible news_][13]
|
||||
* [_Collections signal major shift in Ansible ecosystem, and more Ansible news_][14]
|
||||
* [_Ansible 101 videos with Jeff Geerling, and more Ansible news_][15]
|
||||
* [_Beginner guides, Windows, networking, and more Ansible news_][16]
|
||||
|
||||
|
||||
|
||||
### Have a happy 2021!
|
||||
|
||||
I hope your personal journey with Ansible is already underway and regularly enriched by content from Opensource.com. Tell us in the comments what you might like to learn about Ansible in the coming year, and if you have information to share, please consider [writing an article][17] for Opensource.com.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/ansible
|
||||
|
||||
作者:[James Farrell][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jamesf
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/innovation_lightbulb_gears_devops_ansible.png?itok=TSbmp3_M (gears and lightbulb to represent innovation)
|
||||
[2]: https://opensource.com/article/20/9/ansible
|
||||
[3]: https://opensource.com/article/20/11/orchestration-vs-automation
|
||||
[4]: https://opensource.com/article/20/9/install-packages-ansible
|
||||
[5]: https://opensource.com/article/20/1/ansible-playbooks-lessons
|
||||
[6]: https://opensource.com/article/20/10/first-day-ansible
|
||||
[7]: https://opensource.com/article/20/9/raspberry-pi-ansible
|
||||
[8]: https://opensource.com/article/20/10/calendar-ansible
|
||||
[9]: https://opensource.com/article/20/10/ansible-module-go
|
||||
[10]: https://opensource.com/article/20/9/ansible-modules-kubernetes
|
||||
[11]: https://opensource.com/article/20/10/kubernetes-minecraft-ansible
|
||||
[12]: https://opensource.com/article/20/1/ansible-news-edition-six
|
||||
[13]: https://opensource.com/article/20/2/ansible-news-edition-seven
|
||||
[14]: https://opensource.com/article/20/3/ansible-news-edition-eight
|
||||
[15]: https://opensource.com/article/20/4/ansible-news-edition-nine
|
||||
[16]: https://opensource.com/article/20/5/ansible-news-edition-ten
|
||||
[17]: https://opensource.com/how-submit-article
|
63
sources/tech/20210104 8 Kubernetes insights for 2021.md
Normal file
63
sources/tech/20210104 8 Kubernetes insights for 2021.md
Normal file
@ -0,0 +1,63 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (8 Kubernetes insights for 2021)
|
||||
[#]: via: (https://opensource.com/article/21/1/kubernetes)
|
||||
[#]: author: (Scott McCarty https://opensource.com/users/fatherlinux)
|
||||
|
||||
8 Kubernetes insights for 2021
|
||||
======
|
||||
Review the top five Kubernetes articles of 2020, then preview three
|
||||
tools you should learn about in 2021.
|
||||
![Ship captain sailing the Kubernetes seas][1]
|
||||
|
||||
The end of the year is the perfect time to look back and explore where we've been and where we're going in the Kubernetes world. I particularly want to focus on the ecosystem that formed around Kubernetes in 2020, which several great articles on Opensource.com covered. I'll review them in the order they were published.
|
||||
|
||||
It all started in February with a great article called [_Basic kubectl and Helm commands for beginners_][2] by Jessica Cherry. Jess introduces readers to two simple tools to get started with Kubernetes: kubectl, technically part of Kubernetes, and Helm, which makes it easier to install and set up applications on Kubernetes. These tools are extremely useful for new Kubernetes users.
|
||||
|
||||
In March, Lee Carpenter wrote about [_Directing Kubernetes traffic with Traefik_][3]. The article gives a good background on how networking works in Kubernetes and how to configure things in the application definition (Kube YAML). Before reading Lee's article, I hadn't tracked Kubernetes networking closely for a while, and I learned that Traefik comes preconfigured now as an Ingress controller. Very cool.
|
||||
|
||||
Kubernetes was a popular topic on Opensource.com in March because Manuel Dewald published [_Build a Kubernetes Operator in 10 minutes with Operator SDK_][4]. This article is a bit more advanced than the first two. Manuel explains a powerful concept in Kubernetes called Operators. You can think of Operators as robot sysadmins that are deployed side-by-side with applications on Kubernetes. They do things like installing and upgrading applications, checking database tables, and backing up or restoring data. Manuel shows how to build a simple Operator to install software.
|
||||
|
||||
In June, my friend Chris Collins published [_Manage your Kubernetes cluster with Lens_][5], a user interface that describes itself as "the Kubernetes IDE." Lens runs on a laptop or a jump box and connects to Kubernetes. It gives the ability to gather metrics and cluster status and do a whole bunch of other things.
|
||||
|
||||
In July, Jess Cherry was back with [_A guide to Terraform for Kubernetes beginners_][6]. Some Kubernetes objects, like Deployments, track state changes, but many don't. Jess shows how to use Terraform to control all state changes to a Kubernetes cluster, making it easy to return to a pristine state after testing a bunch of software on a Kubernetes cluster.
|
||||
|
||||
### Bonus tools to learn about in 2021
|
||||
|
||||
And, as we enter this new year, I want to share a few bonus tools to put on your 2021 learning list.
|
||||
|
||||
First, check out [KIND (Kubernetes in Docker)][7]. It lets you run a whole Kubernetes cluster with a single command. But don't let the name fool you; you can also use Podman as the container engine. It's very cool to see these kinds of upstream integrations between different projects. Showing KIND using Podman to fire up Kubernetes would be a great article for 2021!
|
||||
|
||||
Another tool to know about is [KubeInit][8], which uses Ansible to deploy Kubernetes clusters. If you speak Spanish, watch our interview with Carlos Camacho on [OpenShift Commons En Vivo][9].
|
||||
|
||||
Finally, if you are looking for a super-simple way to get started with Kubernetes, check out [Minikube][10]. Like KIND, Minkube can start a Kube cluster with a single command. Also like KIND, there is a driver for Podman ([Minikube Podman Driver][11]). Multiple authors mentioned Minikube in 2020, but it's been a little while since we've had a dedicated article on the tool.
|
||||
|
||||
Like most of us, I am looking forward to 2021 being a better year, and I'm excited to see what great Kubernetes articles are published on Opensource.com!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/kubernetes
|
||||
|
||||
作者:[Scott McCarty][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/fatherlinux
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
|
||||
[2]: http://opensource.com/article/20/2/kubectl-helm-commands
|
||||
[3]: http://opensource.com/article/20/3/kubernetes-traefik
|
||||
[4]: http://opensource.com/article/20/3/kubernetes-operator-sdk
|
||||
[5]: http://opensource.com/article/20/6/kubernetes-lens
|
||||
[6]: http://opensource.com/article/20/7/terraform-kubernetes
|
||||
[7]: https://kind.sigs.k8s.io/docs/contributing/1.0-roadmap
|
||||
[8]: https://github.com/Kubeinit/kubeinit
|
||||
[9]: https://www.youtube.com/watch?v=9_6H7Ahsdm4
|
||||
[10]: https://minikube.sigs.k8s.io/docs/start/
|
||||
[11]: https://minikube.sigs.k8s.io/docs/drivers/podman/
|
@ -0,0 +1,134 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn Fortran by writing a "guess the number" game)
|
||||
[#]: via: (https://opensource.com/article/21/1/fortran)
|
||||
[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
|
||||
|
||||
Learn Fortran by writing a "guess the number" game
|
||||
======
|
||||
Because Fortran was written in the punched card era, its syntax is
|
||||
pretty limited. But you can still write useful and interesting programs
|
||||
with it.
|
||||
![Person typing on a 1980's computer][1]
|
||||
|
||||
The first compiled programming language I learned was Fortran 77. While growing up, I taught myself how to write programs in BASIC on the Apple II and later in QBasic on DOS. But when I went to university to study physics, I learned [Fortran][2].
|
||||
|
||||
Fortran used to be quite common in scientific computing. And once upon a time, all computer systems had a Fortran compiler. Fortran used to be as ubiquitous as Python is today. So if you were a physics student like me, working in the 1990s, you learned Fortran.
|
||||
|
||||
I always thought Fortran was somewhat similar to BASIC, so I quickly took to Fortran whenever I needed to write a quick program to analyze lab data or perform some other numerical analysis. And when I got bored, I wrote a "Guess the number" game in Fortran, where the computer picks a number between one and 100 and asks me to guess the number. The program loops until I guess correctly.
|
||||
|
||||
The "Guess the number" program exercises several concepts in programming languages: how to assign values to variables, how to write statements, and how to perform conditional evaluation and loops. It's a great practical experiment for learning a new programming language.
|
||||
|
||||
### The basics of Fortran programming
|
||||
|
||||
While Fortran has been updated over the years, I am most familiar with Fortran 77, the implementation I learned years ago. Fortran was created when programmers wrote programs on punched cards, so "classic" Fortran is limited to the data you could put on a punched card. That means you could only write classic Fortran programs with these limitations:
|
||||
|
||||
* Only one line of source code per card is allowed.
|
||||
* Only columns 1–72 are recognized (the last eight columns, 73-80, are reserved for the card sorter).
|
||||
* Line numbers ("labels") are in columns 1–5.
|
||||
* Program statements go in columns 7–72.
|
||||
* To continue a program line, enter a continuation character (usually `+`) in column 6.
|
||||
* To create a comment line, enter `C` or `*` in column 1.
|
||||
* Only the characters `A` to `Z` (uppercase), `0` to `9` (numbers), and the special characters `= + - * / ( ) , . $ ' :` and space are used.
|
||||
|
||||
|
||||
|
||||
With these limitations, you can still write very useful and interesting programs.
|
||||
|
||||
### Guess the number in Fortran
|
||||
|
||||
Explore Fortran by writing the "Guess the number" game. This is my implementation:
|
||||
|
||||
|
||||
```
|
||||
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
C PROGRAM TO GUESS A NUMBER 1-100
|
||||
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
PROGRAM GUESSNUM
|
||||
INTEGER SEED, NUMBER, GUESS
|
||||
|
||||
PRINT *, 'ENTER A RANDOM NUMBER SEED'
|
||||
READ *, SEED
|
||||
CALL SRAND(SEED)
|
||||
|
||||
NUMBER = INT( RAND(0) * 100 + 1 )
|
||||
|
||||
PRINT *, 'GUESS A NUMBER BETWEEN 1 AND 100'
|
||||
10 READ *, GUESS
|
||||
|
||||
IF (GUESS.LT.NUMBER) THEN
|
||||
PRINT *, 'TOO LOW'
|
||||
ELSE IF (GUESS.GT.NUMBER) THEN
|
||||
PRINT *, 'TOO HIGH'
|
||||
ENDIF
|
||||
|
||||
IF (GUESS.NE.NUMBER) GOTO 10
|
||||
|
||||
PRINT *, 'THATS RIGHT!'
|
||||
END
|
||||
```
|
||||
|
||||
If you are familiar with other programming languages, you can probably figure out what this program is doing by reading the source code. The first three lines are a comment block to indicate the program's function. The fourth line, `PROGRAM GUESSNUM`, identifies this as a program, and it is closed by the `END` statement on the last line.
|
||||
|
||||
After defining a few variables, the program prompts the user to enter a random number seed. A Fortran program cannot initialize the random number generator from the operating system, so you must always start the random number generator with a "seed" value and the `SRAND` subroutine.
|
||||
|
||||
Fortran generates random numbers between 0 and 0.999... with the `RAND(0)` function. The `0` value tells the `RAND` function to generate another random number. Multiply this random number by 100 to generate a number between 0 and 99.999…, and then add 1 to get a value between 1 and 100.999… The `INT` function truncates this to an integer; thus, the variable `NUMBER` is a random number between 1 and 100.
|
||||
|
||||
The program prompts the user, then enters a loop. Fortran doesn't support the `while` or `do-while` loops available in more modern programming languages. Instead, you must construct your own using labels (line numbers) and `GOTO` statements. That's why the `READ` statement has a line number; you can jump to this label with the `GOTO` at the end of the loop.
|
||||
|
||||
Punched cards did not have the `<` (less than) or `>` (greater than) symbols, so Fortran adopted a different syntax to compare values. To test if one value is less than another, use the `.LT.` (less than) comparison. To test if a value is greater than another, use `.GT.` (greater than). Equal and not equal are `.EQ.` and `.NE.`, respectively.
|
||||
|
||||
In each iteration of the loop, the program tests the user's guess. If the user's guess is less than the random number, the program prints `TOO LOW`, and if the guess is greater than the random number, the program prints `TOO HIGH`. The loop continues until the user's guess is the same as the random number.
|
||||
|
||||
When the loop exits, the program prints `THATS RIGHT!` and ends immediately.
|
||||
|
||||
|
||||
```
|
||||
$ gfortran -Wall -o guess guess.f
|
||||
|
||||
$ ./guess
|
||||
ENTER A RANDOM NUMBER SEED
|
||||
93759
|
||||
GUESS A NUMBER BETWEEN 1 AND 100
|
||||
50
|
||||
TOO LOW
|
||||
80
|
||||
TOO HIGH
|
||||
60
|
||||
TOO LOW
|
||||
70
|
||||
TOO LOW
|
||||
75
|
||||
TOO HIGH
|
||||
73
|
||||
TOO LOW
|
||||
74
|
||||
THATS RIGHT!
|
||||
```
|
||||
|
||||
Every time you run the program, the user needs to enter a different random number seed. If you always enter the same seed, the program will always pick the same random number.
|
||||
|
||||
### Try it in other languages
|
||||
|
||||
This "guess the number" game is a great introductory program when learning a new programming language because it exercises several common programming concepts in a pretty straightforward way. By implementing this simple game in different programming languages, you can demonstrate some core concepts and compare each language's details.
|
||||
|
||||
Do you have a favorite programming language? How would you write the "guess the number" game in it? Follow this article series to see examples of other programming languages that might interest you.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/1/fortran
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
|
||||
[2]: https://en.wikipedia.org/wiki/Fortran
|
@ -0,0 +1,275 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Network address translation part 1 – packet tracing)
|
||||
[#]: via: (https://fedoramagazine.org/network-address-translation-part-1-packet-tracing/)
|
||||
[#]: author: (Florian Westphal https://fedoramagazine.org/author/strlen/)
|
||||
|
||||
Network address translation part 1 – packet tracing
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
The first post in a series about network address translation (NAT). Part 1 shows how to use the iptables/nftables packet tracing feature to find the source of NAT related connectivity problems.
|
||||
|
||||
### Introduction
|
||||
|
||||
Network address translation is one way to expose containers or virtual machines to the wider internet. Incoming connection requests have their destination address rewritten to a different one. Packets are then routed to a container or virtual machine instead. The same technique can be used for load-balancing where incoming connections get distributed among a pool of machines.
|
||||
|
||||
Connection requests fail when network address translation is not working as expected. The wrong service is exposed, connections end up in the wrong container, request time out, and so on. One way to debug such problems is to check that the incoming request matches the expected or configured translation.
|
||||
|
||||
### Connection tracking
|
||||
|
||||
NAT involves more than just changing the ip addresses or port numbers. For instance, when mapping address X to Y, there is no need to add a rule to do the reverse translation. A netfilter system called “conntrack” recognizes packets that are replies to an existing connection. Each connection has its own NAT state attached to it. Reverse translation is done automatically.
|
||||
|
||||
### Ruleset evaluation tracing
|
||||
|
||||
The utility nftables (and, to a lesser extent, iptables) allow for examining how a packet is evaluated and which rules in the ruleset were matched by it. To use this special feature “trace rules” are inserted at a suitable location. These rules select the packet(s) that should be traced. Lets assume that a host coming from IP address C is trying to reach the service on address S and port P. We want to know which NAT transformation is picked up, which rules get checked and if the packet gets dropped somewhere.
|
||||
|
||||
Because we are dealing with incoming connections, add a rule to the prerouting hook point. Prerouting means that the kernel has not yet made a decision on where the packet will be sent to. A change to the destination address often results in packets to get forwarded rather than being handled by the host itself.
|
||||
|
||||
### Initial setup
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# nft 'add table inet trace_debug'
|
||||
# nft 'add chain inet trace_debug trace_pre { type filter hook prerouting priority -200000; }'
|
||||
# nft "insert rule inet trace_debug trace_pre ip saddr $C ip daddr $S tcp dport $P tcp flags syn limit rate 1/second meta nftrace set 1"
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
The first rule adds a new table This allows easier removal of the trace and debug rules later. A single “nft delete table inet trace_debug” will be enough to undo all rules and chains added to the temporary table during debugging.
|
||||
|
||||
The second rule creates a base hook before routing decisions have been made (prerouting) and with a negative priority value to make sure it will be evaluated before connection tracking and the NAT rules.
|
||||
|
||||
The only important part, however, is the last fragment of the third rule: “_meta nftrace set 1″_. This enables tracing events for all packets that match the rule. Be as specific as possible to get a good signal-to-noise ratio. Consider adding a rate limit to keep the number of trace events at a manageable level. A limit of one packet per second or per minute is a good choice. The provided example traces all syn and syn/ack packets coming from host $C and going to destination port $P on the destination host $S. The limit clause prevents event flooding. In most cases a trace of a single packet is enough.
|
||||
|
||||
The procedure is similar for iptables users. An equivalent trace rule looks like this:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# iptables -t raw -I PREROUTING -s $C -d $S -p tcp --tcp-flags SYN SYN --dport $P -m limit --limit 1/s -j TRACE
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
### Obtaining trace events
|
||||
|
||||
Users of the native nft tool can just run the nft trace mode:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# nft monitor trace
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
This prints out the received packet and all rules that match the packet (use CTRL-C to stop it):
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
trace id f0f627 ip raw prerouting packet: iif "veth0" ether saddr ..
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
We will examine this in more detail in the next section. If you use iptables, first check the installed version via the “_iptables –version”_ command. Example:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# iptables --version
|
||||
iptables v1.8.5 (legacy)
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
_(legacy)_ means that trace events are logged to the kernel ring buffer. You will need to check _dmesg or_ _journalctl_. The debug output lacks some information but is conceptually similar to the one provided by the new tools. You will need to check the rule line numbers that are logged and correlate those to the active iptables ruleset yourself. If the output shows _(nf_tables)_, you can use the xtables-monitor tool:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# xtables-monitor --trace
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
If the command only shows the version, you will also need to look at dmesg/journalctl instead. xtables-monitor uses the same kernel interface as the nft monitor trace tool. Their only difference is that it will print events in iptables syntax and that, if you use a mix of both iptables-nft and nft, it will be unable to print rules that use maps/sets and other nftables-only features.
|
||||
|
||||
### Example
|
||||
|
||||
Lets assume you’d like to debug a non-working port forward to a virtual machine or container. The command “ssh -p 1222 10.1.2.3” should provide remote access to a container running on the machine with that address, but the connection attempt times out.
|
||||
|
||||
You have access to the host running the container image. Log in and add a trace rule. See the earlier example on how to add a temporary debug table. The trace rule looks like this:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
nft "insert rule inet trace_debug trace_pre ip daddr 10.1.2.3 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1"
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
After the rule has been added, start nft in trace mode: _nft monitor trace_, then retry the failed ssh command. This will generate a lot of output if the ruleset is large. Do not worry about the large example output below – the next section will do a line-by-line walkthrough.
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
trace id 9c01f8 inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn
|
||||
trace id 9c01f8 inet trace_debug trace_pre rule ip daddr 10.2.1.2 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1 (verdict continue)
|
||||
trace id 9c01f8 inet trace_debug trace_pre verdict continue
|
||||
trace id 9c01f8 inet trace_debug trace_pre policy accept
|
||||
trace id 9c01f8 inet nat prerouting packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn
|
||||
trace id 9c01f8 inet nat prerouting rule ip daddr 10.1.2.3 tcp dport 1222 dnat ip to 192.168.70.10:22 (verdict accept)
|
||||
trace id 9c01f8 inet filter forward packet: iif "enp0" oif "veth21" ether saddr .. ip daddr 192.168.70.10 .. tcp dport 22 tcp flags == syn tcp window 29200
|
||||
trace id 9c01f8 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)
|
||||
trace id 9c01f8 inet filter allowed_dnats rule drop (verdict drop)
|
||||
trace id 20a4ef inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
### Line-by-line trace walkthrough
|
||||
|
||||
The first line generated is the packet id that triggered the subsequent trace output. Even though this is in the same grammar as the nft rule syntax, it contains header fields of the packet that was just received. You will find the name of the receiving network interface (here named “enp0”) the source and destination mac addresses of the packet, the source ip address (can be important – maybe the reporter is connecting from a wrong/unexpected host) and the tcp source and destination ports. You will also see a “trace id” at the very beginning. This identification tells which incoming packet matched a rule. The second line contains the first rule matched by the packet:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
trace id 9c01f8 inet trace_debug trace_pre rule ip daddr 10.2.1.2 tcp dport 1222 tcp flags syn limit rate 6/minute meta nftrace set 1 (verdict continue)
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
This is the just-added trace rule. The first rule is always one that activates packet tracing. If there would be other rules before this, we would not see them. If there is no trace output at all, the trace rule itself is never reached or does not match. The next two lines tell that there are no further rules and that the “trace_pre” hook allows the packet to continue (_verdict accept)_.
|
||||
|
||||
The next matching rule is
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
trace id 9c01f8 inet nat prerouting rule ip daddr 10.1.2.3 tcp dport 1222 dnat ip to 192.168.70.10:22 (verdict accept)
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
This rule sets up a mapping to a different address and port. Provided 192.168.70.10 really is the address of the desired VM, there is no problem so far. If its not the correct VM address, the address was either mistyped or the wrong NAT rule was matched.
|
||||
|
||||
### IP forwarding
|
||||
|
||||
Next we can see that the IP routing engine told the IP stack that the packet needs to be forwarded to another host:
|
||||
|
||||
```
|
||||
trace id 9c01f8 inet filter forward packet: iif "enp0" oif "veth21" ether saddr .. ip daddr 192.168.70.10 .. tcp dport 22 tcp flags == syn tcp window 29200
|
||||
```
|
||||
|
||||
This is another dump of the packet that was received, but there are a couple of interesting changes. There is now an output interface set. This did not exist previously because the previous rules are located before the routing decision (the prerouting hook). The id is the same as before, so this is still the same packet, but the address and port has already been altered. In case there are rules that match “tcp dport 1222” they will have no effect anymore on this packet.
|
||||
|
||||
If the line contains no output interface (oif), the routing decision steered the packet to the local host. Route debugging is a different topic and not covered here.
|
||||
|
||||
trace id 9c01f8 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)
|
||||
|
||||
This tells that the packet matched a rule that jumps to a chain named “allowed_dnats”. The next line shows the source of the connection failure:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
trace id 9c01f8 inet filter allowed_dnats rule drop (verdict drop)
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
The rule unconditionally drops the packet, so no further log output for the packet exists. The next output line is the result of a different packet:
|
||||
|
||||
trace id 20a4ef inet trace_debug trace_pre packet: iif "enp0" ether saddr .. ip saddr 10.2.1.2 ip daddr 10.1.2.3 ip protocol tcp tcp dport 1222 tcp flags == syn
|
||||
|
||||
The trace id is different, the packet however has the same content. This is a retransmit attempt: The first packet was dropped, so TCP re-tries. Ignore the remaining output, it does not contain new information. Time to inspect that chain.
|
||||
|
||||
### Ruleset investigation
|
||||
|
||||
The previous section found that the packet is dropped in a chain named “allowed_dnats” in the inet filter table. Time to look at it:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# nft list chain inet filter allowed_dnats
|
||||
table inet filter {
|
||||
chain allowed_dnats {
|
||||
meta nfproto ipv4 ip daddr . tcp dport @allow_in accept
|
||||
drop
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
The rule that accepts packets in the @allow_in set did not show up in the trace log. Double-check that the address is in the @allow_set by listing the element:
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# nft "get element inet filter allow_in { 192.168.70.10 . 22 }"
|
||||
Error: Could not process rule: No such file or directory
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
As expected, the address-service pair is not in the set. We add it now.
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
# nft "add element inet filter allow_in { 192.168.70.10 . 22 }"
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
Run the query command now, it will return the newly added element.
|
||||
|
||||
```
|
||||
# nft "get element inet filter allow_in { 192.168.70.10 . 22 }"
|
||||
table inet filter {
|
||||
set allow_in {
|
||||
type ipv4_addr . inet_service
|
||||
elements = { 192.168.70.10 . 22 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The ssh command should now work and the trace output reflects the change:
|
||||
|
||||
trace id 497abf58 inet filter forward rule ct status dnat jump allowed_dnats (verdict jump allowed_dnats)
|
||||
|
||||
trace id 497abf58 inet filter allowed_dnats rule meta nfproto ipv4 ip daddr . tcp dport @allow_in accept (verdict accept)
|
||||
|
||||
trace id 497abf58 ip postrouting packet: iif "enp0" oif "veth21" ether .. trace id 497abf58 ip postrouting policy accept
|
||||
|
||||
This shows the packet passes the last hook in the forwarding path – postrouting.
|
||||
|
||||
In case the connect is still not working, the problem is somewhere later in the packet pipeline and outside of the nftables ruleset.
|
||||
|
||||
### Summary
|
||||
|
||||
This Article gave an introduction on how to check for packet drops and other sources of connectivity problems with the nftables trace mechanism. A later post in the series shows how to inspect the connection tracking subsystem and the NAT information that may be attached to tracked flows.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/network-address-translation-part-1-packet-tracing/
|
||||
|
||||
作者:[Florian Westphal][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/strlen/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2020/12/network-address-translation-part-1-816x346.png
|
@ -0,0 +1,75 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Learn to use the JOE text editor on Linux)
|
||||
[#]: via: (https://opensource.com/article/20/12/joe)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
|
||||
学习在 Linux 上使用 JOE 文本编辑器
|
||||
======
|
||||
Joe's Own Editor (JOE)是一款简单易学和使用的通用文本编辑器。
|
||||
![Person programming on a laptop on a building][1]
|
||||
|
||||
我很喜欢那些能让你轻松学会如何使用的文本编辑器。GNU nano 是我最喜欢的例子:你启动 nano,你会在整个会话的窗口底部看到一个最常用的命令列表。Joe's Own Editor(简称 `joe`)是另一个很好的例子。
|
||||
|
||||
`joe` 编辑器使用了一个基于终端的界面,提供了简单的文本编辑功能和一个易于访问的帮助屏幕。它用 C 语言编写,体积小,只对 libc 有硬性依赖(ncurses 是可选的),并且采用 GPL 授权。
|
||||
|
||||
### 安装
|
||||
|
||||
在 Linux 上,你也许能在你的发行版软件仓库中找到 JOE。虽然它有点晦涩,所以并不是所有的发行版都打包了它。如果是这样的话,你可以从 [SourceForge][2] 下载源码,然后自己编译。这是个简单的过程:
|
||||
|
||||
|
||||
```
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
### 使用 JOE
|
||||
|
||||
据其作者介绍,JOE 的灵感来自于一个叫 WordStar 的应用和 [GNU Emacs][3]。它的大部分基本编辑键都与 WordStar 的快捷键相同,编辑器本身也在努力向 WordStar 靠拢。JOE 也有 GNU Emacs 的一些键绑定和功能。这种两种灵感来源的混合有时会让人迷惑,但话又说回来,在任何情况下,让自己脱离 Emacs(或你通常选择的文本编辑器)都会让人迷惑。重要的是,JOE 提供了帮助,而且很容易访问。
|
||||
|
||||
在 JOE 界面右上角,有一个持续的提示,你可以按 **Ctrl+K**,紧接着按 **H** 来查看帮助界面。这是一个切换键,所以一旦你激活它,帮助屏幕就会一直显示在你的编辑器窗口顶部,直到用同样的组合键(JOE 中的键盘符号为 **^KH**)解除。
|
||||
|
||||
### 键盘快捷键
|
||||
|
||||
尽管 JOE 的作者在模拟 WordStar 用户体验方面非常自豪,但我不得不承认,这对我来说是失落的。我从来没有听说过 WordStar,直到我在 JOE 的文档中读到了它,在我看来,它的键盘快捷键方案完全是任意的。有的用 **Ctrl+K** 作为转义序列的前缀,有的用 **Esc**作为前缀,还有的完全不需要转义序列。我无法确定其中的逻辑。编辑操作和应用选项一样,都有可能需要或不需要转义序列,而且很少有字母关联对我来说是有意义的(例如,**Ctrl+K** **D**代表**另存为**)。
|
||||
|
||||
幸运的是,JOE 可以让你在键盘快捷键上作弊。安装后,JOE 会悄悄为 `joe` 可执行文件创建一些符号链接。包括:
|
||||
|
||||
* `jmacs` JOE 使用 Emacs 键绑定
|
||||
* `jpico` JOE 使用 Pico (或 GNU nano) 键绑定
|
||||
* `rjoe` JOE 的编辑只限于启动时传递给 JOE 的文件
|
||||
* `jstar` JOE 使用 WordStar 键绑定
|
||||
|
||||
|
||||
|
||||
![Black terminal with white text showing WordStar key bindings][4]
|
||||
|
||||
持久的帮助菜单仍然存在,所以如果你不清楚有哪些功能可以使用,可以通过屏幕右上方的帮助提示来参考。当然,在 Pico/nano 模式下,主要命令总是可见的。
|
||||
|
||||
### 尝试 JOE
|
||||
|
||||
JOE 并不是一个你永远不会离开的文本编辑器,它不会成为你的 IDE、电子邮件客户端、网络浏览器和文件管理器。事实上,它甚至可能不是你所有任务的主要文本编辑器。它专注于做好一件事,那就是一般的文本编辑。
|
||||
|
||||
JOE 拥有你所需要的所有基本功能,比如能够快速浏览你的文本、能够选择文本、复制和粘贴等等。试试 JOE 吧,使用你喜欢的符号链接。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/12/joe
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_code_programming_laptop.jpg?itok=ormv35tV (Person programming on a laptop on a building)
|
||||
[2]: https://joe-editor.sourceforge.io/
|
||||
[3]: https://opensource.com/article/20/12/emacs
|
||||
[4]: https://opensource.com/sites/default/files/uploads/joe-jstar-31_days-joe-opensource.png (Black terminal with white text showing WordStar key bindings)
|
Loading…
Reference in New Issue
Block a user