更深入的理解 Python 中的迭代

Summary: 在这篇文章中，我们将深入探讨 Python 的 for 循环来看看它们在底层如何工作，以及为什么它们会按照它们的方式工作。

>
> 深入探讨 Python 的 `for` 循环来看看它们在底层如何工作，以及为什么它们会按照它们的方式工作。
>
>
>

![](/data/attachment/album/201805/26/080352ai3a6qticbnnbb8o.jpg)

Python 的 `for` 循环不会像其他语言中的 `for` 循环那样工作。在这篇文章中，我们将深入探讨 Python 的 `for` 循环来看看它们在底层如何工作，以及为什么它们会按照它们的方式工作。

### 循环的问题

我们将通过看一些“陷阱”开始我们的旅程，在我们了解循环如何在 Python 中工作之后，我们将再次看看这些问题并解释发生了什么。

#### 问题 1：循环两次

假设我们有一个数字列表和一个生成器，生成器会返回这些数字的平方：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> squares = (n**2 for n in numbers)

```

我们可以将生成器对象传递给 `tuple` 构造器，从而使其变为一个元组：

```
>>> tuple(squares)
(1, 4, 9, 25, 49)

```

如果我们使用相同的生成器对象并将其传给 `sum` 函数，我们可能会期望得到这些数的和，即 `88`。

```
>>> sum(squares)
0

```

但是我们得到了 `0`。

#### 问题 2：包含的检查

让我们使用相同的数字列表和相同的生成器对象：

```
>>> numbers = [1, 2, 3, 5, 7]

>>> squares = (n**2 for n in numbers)

```

如果我们询问 `9` 是否在 `squares` 生成器中，Python 将会告诉我们 9 在 `squares` 中。但是如果我们再次询问相同的问题，Python 会告诉我们 9 不在 `squares` 中。

```
>>> 9 in squares
True
>>> 9 in squares
False

```

我们询问相同的问题两次，Python 给了两个不同的答案。

#### 问题 3 ：拆包

这个字典有两个键值对：

```
>>> counts = {'apples': 2, 'oranges': 1}

```

让我们使用多个变量来对这个字典进行拆包：

```
>>> x, y = counts

```

你可能会期望当我们对这个字典进行拆包时，我们会得到键值对或者得到一个错误。

但是解包字典不会引发错误，也不会返回键值对。当你解包一个字典时，你会得到键：

```
>>> x
'apples'

```

### 回顾：Python 的 for 循环

在我们了解一些关于这些 Python 片段的逻辑之后，我们将回到这些问题。

Python 没有传统的 `for` 循环。为了解释我的意思，让我们看一看另一种编程语言的 `for` 循环。

这是一种传统 C 风格的 `for` 循环，用 JavaScript 编写：

```
let numbers = [1, 2, 3, 5, 7];
for (let i = 0; i < numbers.length; i += 1) {
    print(numbers[i])
}

```

JavaScript、 C、 C++、 Java、 PHP 和一大堆其他编程语言都有这种风格的 `for` 循环，但是 Python **确实没有**。

Python **确实没有** 传统 C 风格的 `for` 循环。在 Python 中确实有一些我们称之为 `for` 循环的东西，但是它的工作方式类似于 [foreach 循环](https://en.wikipedia.org/wiki/Foreach_loop)。

这是 Python 的 `for` 循环的风格：

```
numbers = [1, 2, 3, 5, 7]
for n in numbers:
    print(n)

```

与传统 C 风格的 `for` 循环不同，Python 的 `for` 循环没有索引变量，没有索引变量初始化，边界检查，或者索引递增。Python 的 `for` 循环完成了对我们的 `numbers` 列表进行遍历的所有工作。

因此，当我们在 Python 中确实有 `for` 循环时，我们没有传统 C 风格的 `for` 循环。我们称之为 for 循环的东西的工作机制与之相比有很大的不同。

### 定义：可迭代和序列

既然我们已经解决了 Python 世界中无索引的 `for` 循环，那么让我们在此之外来看一些定义。

**可迭代**是任何你可以用 Python 中的 `for` 循环遍历的东西。可迭代意味着可以遍历，任何可以遍历的东西都是可迭代的。

```
for item in some_iterable:
    print(item)

```

序列是一种非常常见的可迭代类型，列表，元组和字符串都是序列。

```
>>> numbers = [1, 2, 3, 5, 7]
>>> coordinates = (4, 5, 7)
>>> words = "hello there"

```

序列是可迭代的，它有一些特定的特征集。它们可以从 `0` 开始索引，以小于序列的长度结束，它们有一个长度并且它们可以被切分。列表，元组，字符串和其他所有序列都是这样工作的。

```
>>> numbers[0]
1
>>> coordinates[2]
7
>>> words[4]
'o'

```

Python 中很多东西都是可迭代的，但不是所有可迭代的东西都是序列。集合、字典、文件和生成器都是可迭代的，但是它们都不是序列。

```
>>> my_set = {1, 2, 3}
>>> my_dict = {'k1': 'v1', 'k2': 'v2'}
>>> my_file = open('some_file.txt')
>>> squares = (n**2 for n in my_set)

```

因此，任何可以用 `for` 循环遍历的东西都是可迭代的，序列只是一种可迭代的类型，但是 Python 也有许多其他种类的迭代器。

### Python 的 for 循环不使用索引

你可能认为，Python 的 `for` 循环在底层使用了索引进行循环。在这里我们使用 `while` 循环和索引手动遍历：

```
numbers = [1, 2, 3, 5, 7]
i = 0
while i < len(numbers):
    print(numbers[i])
    i += 1

```

这适用于列表，但它不会对所有东西都起作用。这种循环方式**只适用于序列**。

如果我们尝试用索引去手动遍历一个集合，我们会得到一个错误：

```
>>> fruits = {'lemon', 'apple', 'orange', 'watermelon'}
>>> i = 0
>>> while i < len(fruits):
...     print(fruits[i])
...     i += 1
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: 'set' object does not support indexing

```

集合不是序列，所以它们不支持索引。

我们不能使用索引手动对 Python 中的每一个迭代对象进行遍历。对于那些不是序列的迭代器来说，这是行不通的。

### 迭代器驱动 for 循环

因此，我们已经看到，Python 的 `for` 循环在底层不使用索引。相反，Python 的 `for` 循环使用**迭代器**。

迭代器就是可以驱动可迭代对象的东西。你可以从任何可迭代对象中获得迭代器，你也可以使用迭代器来手动对它的迭代进行遍历。

让我们来看看它是如何工作的。

这里有三个可迭代对象：一个集合，一个元组和一个字符串。

```
>>> numbers = {1, 2, 3, 5, 7}
>>> coordinates = (4, 5, 7)
>>> words = "hello there"

```

我们可以使用 Python 的内置 `iter` 函数来访问这些迭代器，将一个迭代器传递给 `iter` 函数总会给我们返回一个迭代器，无论我们正在使用哪种类型的迭代器。

```
>>> iter(numbers)
<set_iterator object at 0x7f2b9271c860>
>>> iter(coordinates)
<tuple_iterator object at 0x7f2b9271ce80>
>>> iter(words)
<str_iterator object at 0x7f2b9271c860>

```

一旦我们有了迭代器，我们可以做的事情就是通过将它传递给内置的 `next` 函数来获取它的下一项。

```
>>> numbers = [1, 2, 3]
>>> my_iterator = iter(numbers)
>>> next(my_iterator)
1
>>> next(my_iterator)
2

```

迭代器是有状态的，这意味着一旦你从它们中消耗了一项，它就消失了。

如果你从迭代器中请求 `next` 项，但是其中没有更多的项了，你将得到一个 `StopIteration` 异常：

```
>>> next(my_iterator)
3
>>> next(my_iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

```

所以你可以从每个迭代中获得一个迭代器，迭代器唯一能做的事情就是用 `next` 函数请求它们的下一项。如果你将它们传递给 `next`，但它们没有下一项了，那么就会引发 `StopIteration` 异常。

你可以将迭代器想象成 Pez 分配器（LCTT 译注：Pez 是一个结合玩具的独特复合式糖果），不能重新分配。你可以把 Pez 拿出去，但是一旦 Pez 被移走，它就不能被放回去，一旦分配器空了，它就没用了。

### 没有 for 的循环

既然我们已经了解了迭代器和 `iter` 以及 `next` 函数，我们将尝试在不使用 `for` 循环的情况下手动遍历迭代器。

我们将通过尝试将这个 `for` 循环变为 `while` 循环：

```
def funky_for_loop(iterable, action_to_do):
    for item in iterable:
        action_to_do(item)

```

为了做到这点，我们需要：

1. 从给定的可迭代对象中获得迭代器
2. 反复从迭代器中获得下一项
3. 如果我们成功获得下一项，就执行 `for` 循环的主体
4. 如果我们在获得下一项时得到了一个 `StopIteration` 异常，那么就停止循环

```
def funky_for_loop(iterable, action_to_do):
    iterator = iter(iterable)
    done_looping = False
    while not done_looping:
        try:
            item = next(iterator)
        except StopIteration:
            done_looping = True
        else:
            action_to_do(item)

```

我们只是通过使用 `while` 循环和迭代器重新定义了 `for` 循环。

上面的代码基本上定义了 Python 在底层循环的工作方式。如果你理解内置的 `iter` 和 `next` 函数的遍历循环的工作方式，那么你就会理解 Python 的 `for` 循环是如何工作的。

事实上，你不仅仅会理解 `for` 循环在 Python 中是如何工作的，所有形式的遍历一个可迭代对象都是这样工作的。

<ruby> 迭代器协议 <rt>  iterator protocol </rt></ruby> 是一种很好表示 “在 Python 中遍历迭代器是如何工作的”的方式。它本质上是对 `iter` 和 `next` 函数在 Python 中是如何工作的定义。Python 中所有形式的迭代都是由迭代器协议驱动的。

迭代器协议被 `for` 循环使用（正如我们已经看到的那样）：

```
for n in numbers:
    print(n)

```

多重赋值也使用迭代器协议：

```
x, y, z = coordinates

```

星型表达式也是用迭代器协议：

```
a, b, *rest = numbers
print(*numbers)

```

许多内置函数依赖于迭代器协议：

```
unique_numbers = set(numbers)

```

在 Python 中任何与迭代器一起工作的东西都可能以某种方式使用迭代器协议。每当你在 Python 中遍历一个可迭代对象时，你将依赖于迭代器协议。

### 生成器是迭代器

所以你可能会想：迭代器看起来很酷，但它们看起来像一个实现细节，我们作为 Python 的使用者，可能不需要关心它们。

我有消息告诉你：在 Python 中直接使用迭代器是很常见的。

这里的 `squares` 对象是一个生成器：

```
>>> numbers = [1, 2, 3]
>>> squares = (n**2 for n in numbers)

```

生成器是迭代器，这意味着你可以在生成器上调用 `next` 来获得它的下一项：

```
>>> next(squares)
1
>>> next(squares)
4

```

但是如果你以前用过生成器，你可能也知道可以循环遍历生成器：

```
>>> squares = (n**2 for n in numbers)
>>> for n in squares:
...     print(n)
...
1
4
9

```

如果你可以在 Python 中循环遍历某些东西，那么它就是**可迭代的**。

所以**生成器是迭代器**，但是生成器也是可迭代的，这又是怎么回事呢？

### 我欺骗了你

所以在我之前解释迭代器如何工作时，我跳过了它们的某些重要的细节。

#### 生成器是可迭代的

我再说一遍：Python 中的每一个迭代器都是可迭代的，意味着你可以循环遍历迭代器。

因为迭代器也是可迭代的，所以你可以使用内置 `next` 函数从可迭代对象中获得迭代器：

```
>>> numbers = [1, 2, 3]
>>> iterator1 = iter(numbers)
>>> iterator2 = iter(iterator1)

```

请记住，当我们在可迭代对象上调用 `iter` 时，它会给我们返回一个迭代器。

当我们在迭代器上调用 `iter` 时，它会给我们返回它自己：

```
>>> iterator1 is iterator2
True

```

迭代器是可迭代的，所有的迭代器都是它们自己的迭代器。

```
def is_iterator(iterable):
    return iter(iterable) is iterable

```

迷惑了吗？

让我们回顾一些这些措辞。

* 一个**可迭代对象**是你可以迭代的东西
* 一个**迭代对象器**是一种实际上遍历可迭代对象的代理

此外，在 Python 中迭代器也是可迭代的，它们充当它们自己的迭代器。

所以迭代器是可迭代的，但是它们没有一些可迭代对象拥有的各种特性。

迭代器没有长度，它们不能被索引：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> iterator = iter(numbers)
>>> len(iterator)
TypeError: object of type 'list_iterator' has no len()
>>> iterator[0]
TypeError: 'list_iterator' object is not subscriptable

```

从我们作为 Python 程序员的角度来看，你可以使用迭代器来做的唯一有用的事情是将其传递给内置的 `next` 函数，或者对其进行循环遍历：

```
>>> next(iterator)
1
>>> list(iterator)
[2, 3, 5, 7]

```

如果我们第二次循环遍历迭代器，我们将一无所获：

```
>>> list(iterator)
[]

```

你可以把迭代器看作是**惰性迭代器**，它们是**一次性使用**，这意味着它们只能循环遍历一次。

正如你在下面的真值表中所看到的，可迭代对象并不总是迭代器，但是迭代器总是可迭代的：

| 对象 | 可迭代？ | 迭代器？ |
| --- | --- | --- |
| 可迭代对象 | V | ? |
| 迭代器 | V | V |
| 生成器 | V | V |
| 列表 | V | X |

### 全部的迭代器协议

让我们从 Python 的角度来定义迭代器是如何工作的。

可迭代对象可以被传递给 `iter` 函数，以便为它们获得迭代器。

迭代器：

* 可以传递给 `next` 函数，它将给出下一项，如果没有下一项，那么它将会引发 `StopIteration` 异常
* 可以传递给 `iter` 函数，它会返回一个自身的迭代器

这些语句反过来也是正确的：

* 任何可以在不引发 `TypeError` 异常的情况下传递给 `iter` 的东西都是可迭代的
* 任何可以在不引发 `TypeError` 异常的情况下传递给 `next` 的东西都是一个迭代器
* 当传递给 `iter` 时，任何返回自身的东西都是一个迭代器

这就是 Python 中的迭代器协议。

#### 迭代器的惰性

迭代器允许我们一起工作，创建**惰性可迭代对象**，即在我们要求它们提供下一项之前，它们不做任何事情。因为可以创建惰性迭代器，所以我们可以创建无限长的迭代器。我们可以创建对系统资源比较保守的迭代器，可以节省我们的内存，节省 CPU 时间。

### 迭代器无处不在

你已经在 Python 中看到过许多迭代器，我也提到过生成器是迭代器。Python 的许多内置类型也是迭代器。例如，Python 的 `enumerate` 和 `reversed` 对象就是迭代器。

```
>>> letters = ['a', 'b', 'c']
>>> e = enumerate(letters)
>>> e
<enumerate object at 0x7f112b0e6510>
>>> next(e)
(0, 'a')

```

在 Python 3 中，`zip`, `map` 和 `filter` 也是迭代器。

```
>>> numbers = [1, 2, 3, 5, 7]
>>> letters = ['a', 'b', 'c']
>>> z = zip(numbers, letters)
>>> z
<zip object at 0x7f112cc6ce48>
>>> next(z)
(1, 'a')

```

Python 中的文件对象也是迭代器。

```
>>> next(open('hello.txt'))
'hello world\n'

```

在 Python 标准库和第三方库中内置了大量的迭代器。这些迭代器首先惰性迭代器一样，延迟工作直到你请求它们下一项。

### 创建你自己的迭代器

知道你已经在使用迭代器是很有用的，但是我希望你也知道，你可以创建自己的迭代器和你自己的惰性迭代器。

下面这个类构造了一个迭代器接受一个可迭代的数字，并在循环结束时提供每个数字的平方。

```
class square_all:
    def __init__(self, numbers):
        self.numbers = iter(numbers)
    def __next__(self):
        return next(self.numbers) * 2
    def __iter__(self):
        return self

```

但是在我们开始对该类的实例进行循环遍历之前，没有任何工作要做。

这里，我们有一个无限长的可迭代对象 `count`，你可以看到 `square_all` 接受 `count` 而不用完全循环遍历这个无限长的迭代：

```
>>> from itertools import count
>>> numbers = count(5)
>>> squares = square_all(numbers)
>>> next(squares)
25
>>> next(squares)
36

```

这个迭代器类是有效的，但我们通常不会这样做。通常，当我们想要做一个定制的迭代器时，我们会生成一个生成器函数：

```
def square_all(numbers):
    for n in numbers:
        yield n**2

```

这个生成器函数等价于我们上面所做的类，它的工作原理是一样的。

这种 `yield` 语句似乎很神奇，但它非常强大：`yield` 允许我们在调用 `next` 函数之间暂停生成器函数。`yield` 语句是将生成器函数与常规函数分离的东西。

另一种实现相同迭代器的方法是使用生成器表达式。

```
def square_all(numbers):
    return (n**2 for n in numbers)

```

这和我们的生成器函数确实是一样的，但是它使用的语法看起来[像是一个列表推导一样](http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/)。如果你需要在代码中使用惰性迭代，请考虑迭代器，并考虑使用生成器函数或生成器表达式。

### 迭代器如何改进你的代码

一旦你已经接受了在代码中使用惰性迭代器的想法，你就会发现有很多可能来发现或创建辅助函数，以此来帮助你循环遍历和处理数据。

#### 惰性求和

这是一个 `for` 循环，它对 Django queryset 中的所有工作时间求和：

```
hours_worked = 0
for event in events:
    if event.is_billable():
        hours_worked += event.duration

```

下面是使用生成器表达式进行惰性评估的代码：

```
billable_times = (
    event.duration
    for event in events
    if event.is_billable()
)

hours_worked = sum(billable_times)

```

请注意，我们代码的形状发生了巨大变化。

将我们的计算工作时间变成一个惰性迭代器允许我们能够命名以前未命名（`billable_times`）的东西。这也允许我们使用 `sum` 函数，我们以前不能使用 `sum` 函数是因为我们甚至没有一个可迭代对象传递给它。迭代器允许你从根本上改变你组织代码的方式。

#### 惰性和打破循环

这段代码打印出日志文件的前 10 行：

```
for i, line in enumerate(log_file):
    if i >= 10:
        break
    print(line)

```

这段代码做了同样的事情，但是我们使用的是 `itertools.islice` 函数来惰性地抓取文件中的前 10 行：

```
from itertools import islice
first_ten_lines = islice(log_file, 10)
for line in first_ten_lines:
    print(line)

```

我们定义的 `first_ten_lines` 变量是迭代器，同样，使用迭代器允许我们给以前未命名的东西命名(`first_ten_lines`)。命名事物可以使我们的代码更具描述性，更具可读性。

作为奖励，我们还消除了在循环中使用 `break` 语句的需要，因为 `islice` 实用函数为我们处理了中断。

你可以在标准库中的 [itertools](https://docs.python.org/3/library/itertools.html) 中找到更多的迭代辅助函数，以及诸如 [boltons](https://boltons.readthedocs.io) 和 [more-itertools](https://more-itertools.readthedocs.io) 之类的第三方库。

#### 创建自己的迭代辅助函数

你可以在标准库和第三方库中找到用于循环的辅助函数，但你也可以自己创建！

这段代码列出了序列中连续值之间的差值列表。

```
current = readings[0]
for next_item in readings[1:]:
    differences.append(next_item - current)
    current = next_item

```

请注意，这段代码中有一个额外的变量，我们每次循环时都要指定它。还要注意，这段代码只适用于我们可以切片的东西，比如序列。如果 `readings` 是一个生成器，一个 zip 对象或其他任何类型的迭代器，那么这段代码就会失败。

让我们编写一个辅助函数来修复代码。

这是一个生成器函数，它为给定的迭代中的每个项目提供了当前项和下一项：

```
def with_next(iterable):
    """Yield (current, next_item) tuples for each item in iterable."""
    iterator = iter(iterable)
    current = next(iterator)
    for next_item in iterator:
        yield current, next_item
        current = next_item

```

我们从可迭代对象中手动获取一个迭代器，在它上面调用 `next` 来获取第一项，然后循环遍历迭代器获取后续所有的项目，跟踪后一个项目。这个函数不仅适用于序列，而且适用于任何类型迭代。

这段代码和以前代码是一样的，但是我们使用的是辅助函数而不是手动跟踪 `next_item`：

```
differences = []
for current, next_item in with_next(readings):
    differences.append(next_item - current)

```

请注意，这段代码不会挂在我们循环周围的 `next_item` 上，`with_next` 生成器函数处理跟踪 `next_item` 的工作。

还要注意，这段代码已足够紧凑，如果我们愿意，我们甚至可以[将方法复制到列表推导中来](http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/)。

```
differences = [
    (next_item - current)
    for current, next_item in with_next(readings)
]

```

### 再次回顾循环问题

现在我们准备回到之前看到的那些奇怪的例子并试着找出到底发生了什么。

#### 问题 1：耗尽的迭代器

这里我们有一个生成器对象 `squares`：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> squares = (n**2 for n in numbers)

```

如果我们把这个生成器传递给 `tuple` 构造函数，我们将会得到它的一个元组：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> squares = (n**2 for n in numbers)
>>> tuple(squares)
(1, 4, 9, 25, 49)

```

如果我们试着计算这个生成器中数字的和，使用 `sum`,我们就会得到 `0`：

```
>>> sum(squares)
0

```

这个生成器现在是空的：我们已经把它耗尽了。如果我们试着再次创建一个元组，我们会得到一个空元组：

```
>>> tuple(squares)
()

```

生成器是迭代器，迭代器是一次性的。它们就像 Hello Kitty Pez 分配器那样不能重新加载。

#### 问题 2：部分消耗一个迭代器

再次使用那个生成器对象 `squares`：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> squares = (n**2 for n in numbers)

```

如果我们询问 `9` 是否在 `squares` 生成器中，我们会得到 `True`：

```
>>> 9 in squares
True

```

但是我们再次询问相同的问题，我们会得到 `False`：

```
>>> 9 in squares
False

```

当我们询问 `9` 是否在迭代器中时，Python 必须对这个生成器进行循环遍历来找到 `9`。如果我们在检查了 `9` 之后继续循环遍历，我们只会得到最后两个数字，因为我们已经在找到 9 之前消耗了这些数字：

```
>>> numbers = [1, 2, 3, 5, 7]
>>> squares = (n**2 for n in numbers)
>>> 9 in squares
True
>>> list(squares)
[25, 49]

```

询问迭代器中是否包含某些东西将会部分地消耗迭代器。如果没有循环遍历迭代器，那么是没有办法知道某个东西是否在迭代器中。

#### 问题 3：拆包是迭代

当你在字典上循环时，你会得到键：

```
>>> counts = {'apples': 2, 'oranges': 1}
>>> for key in counts:
...     print(key)
...
apples
oranges

```

当你对一个字典进行拆包时，你也会得到键：

```
>>> x, y = counts
>>> x, y
('apples', 'oranges')

```

循环依赖于迭代器协议，可迭代对象拆包也依赖于有迭代器协议。拆包一个字典与在字典上循环遍历是一样的，两者都使用迭代器协议，所以在这两种情况下都得到相同的结果。

### 回顾

序列是迭代器，但是不是所有的迭代器都是序列。当有人说“迭代器”这个词时，你只能假设他们的意思是“你可以迭代的东西”。不要假设迭代器可以被循环遍历两次、询问它们的长度或者索引。

迭代器是 Python 中最基本的可迭代形式。如果你想在代码中做一个惰性迭代，请考虑迭代器，并考虑使用生成器函数或生成器表达式。

最后，请记住，Python 中的每一种迭代都依赖于迭代器协议，因此理解迭代器协议是理解 Python 中的循环的关键。

这里有一些我推荐的相关文章和视频：

* [Loop Like a Native](https://nedbatchelder.com/text/iter.html)， Ned Batchelder 在 PyCon 2013 的讲演
* [Loop Better](https://www.youtube.com/watch?v=V2PkkMS2Ack) ，这篇文章是基于这个讲演的
* [The Iterator Protocol: How For Loops Work](http://treyhunner.com/2016/12/python-iterator-protocol-how-for-loops-work/)，我写的关于迭代器协议的短文
* [Comprehensible Comprehensions](https://www.youtube.com/watch?v=5_cJIcgM7rw)，关于推导和迭代器表达器的讲演
* [Python: Range is Not an Iterator](http://treyhunner.com/2018/02/python-range-is-not-an-iterator/)，我关于范围和迭代器的文章
* [Looping Like a Pro in Python](https://www.youtube.com/watch?v=u8g9scXeAcI)，DB 的 PyCon 2017 讲演

本文是基于作者去年在 [DjangoCon AU](https://www.youtube.com/watch?v=JYuE8ZiDPl4)、 [PyGotham](https://www.youtube.com/watch?v=Wd7vcuiMhxU) 和 [North Bay Python](https://www.youtube.com/watch?v=V2PkkMS2Ack) 中发表的 Loop Better 演讲。有关更多内容，请参加将于 2018 年 5 月 9 日至 17 日在 Columbus， Ohio 举办的 [PYCON](https://us.pycon.org/2018/)。

---

via: <https://opensource.com/article/18/3/loop-better-deeper-look-iteration-python>

作者：[Trey Hunner](https://opensource.com/users/treyhunner) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


DevOps 如何消除了 Ranger 社区的瓶颈

>
> 拥抱 DevOps 让 Ranger 成员们变得更灵活、快捷和成为开发者社区更有价值的成员。
>
>
>

![](/data/attachment/album/201805/26/234527kiri747ofifrv6r3.png)

Visual Studio 的<ruby> 应用周期管理 <rt>  Application Lifecycle Management </rt></ruby>（ALM）项目 —— [Ranger](https://aka.ms/vsaraboutus) 是一个志愿者社区，它提供专业的指导、实践经验、以及开发者社区的漏洞修补解决方案。它创建于 2006 年，作为微软内部社区去 “将产品组与大家相连接，并去除推广阻力”。 在 2009 时，社区已经有超过 200 位成员，这导致了协作和计划面临很大的挑战，在依赖和手工流程上产生了瓶颈，并导致了开发者社区不断增加的延迟和各种报怨。在 2010 时，计划进一步去扩充包括微软最有价值专家（MVP）在内的分布在全球的社区。

这个社区被分割成十几个活跃的团队。每个团队都致力于通过它的生命周期去设计、构建和支持一个指导或处理项目。在以前，团队的瓶颈在团队管理级别上，原因是严格的、瀑布式的流程和高度依赖一个或多个项目经理。在制作、发布和“为什么、做什么、和怎么做”驱动的决定上，项目经理都要介入其中。另外，缺乏一个实时的指标阻止了团队对他们的解决方案效率的监控，以及对来自社区的关于 bug 和常见问题的关注。

是时候去寻找一些做好这些事情的方法了，更好地实现开发者社区的价值。

### DevOps 去“灭火”

>
> “DevOps 是人员、流程和产品的结合，使我们的最终用户能够持续传递价值。” --[Donovan Brown](http://donovanbrown.com/post/what-is-devops)
>
>
>

为解决这些挑战，社区停止了所有对新项目的冲刺，去探索敏捷实践和新产品。致力于使社区重新活跃起来，为找到促进自治、掌控、和目标的方法，正如在 Daniel H. Pink 的书《[Drive](http://www.danpink.com/books/drive/)》中所说的那样，对僵化的流程和产品进行彻底的改革。

>
> “成熟的自组织、自管理和跨职能团队，在自治、掌控和目标上茁壮成长。" --Drive, Daniel H. Pink.
>
>
>

从文化开始 —— 人 —— 第一步是去拥抱 DevOps。社区实现了 [Scrum](http://www.scrumguides.org/scrum-guide.html) 框架，使用 [kanban](https://leankit.com/learn/kanban/what-is-kanban/) 去提升工程化流程，并且通过可视化去提升透明度、意识和最重要的东西 —— 信任。使用自组织团队后，传统的等级制度和指挥系统消失了。自管理促使团队去积极监视和设计它们自己的流程。

在 2010 年 4 月份，社区再次实施了另外的关键一步，切换并提交它们的文化、流程、以及产品到云上。虽然开放的“为社区而社区”的核心 [解决方案](https://aka.ms/vsarsolutions) 仍然是指导和补充，但是在开源解决方案（OSS）上大量增加投资去研究和共享 DevOps 转换的成就。

持续集成（CI）和持续交付（CD）使用自动化流水线代替了死板的人工流程。这使得团队在不受来自项目经理的干预的情况下为早期问题和早期应用者部署解决方案。增加遥测技术可以使团队关注他们的解决方案，以及在用户注意到它们之前，检测和处理未知的问题。

DevOps 转变是一个持续进化的过程，通过实验去探索和验证人、流程和产品的改革。最新的试验引入了流水线革新，它可以持续提升价值流。自动扫描组件、持续地以及静默地检查安全、协议和开源组件的品质。部署环和特性标志允许团队对所有或者特定用户进行更细粒度的控制。

在 2017 年 10 月，社区将大部分的私有版本控制仓库转移到 [GitHub](https://github.com/ALM-Rangers) 上。将所有仓库转移所有者和管理职责到 ALM DevOps Rangers 社区，给团队提供自治和机会，去激励更多的社区对开源解决方案作贡献。团队被授权向他们的最终用户交付质量和价值。

### 好处和成就

拥抱 DevOps 使 Ranger 社区变得更加敏捷，实现了对市场的快速反应和快速学习和反应的流程，减少了宝贵的时间投入，并宣布自治。

下面是从这个转变中观察到的一个列表，排列没有特定的顺序：

* 自治、掌控和目标是核心。
* 从可触摸的和可迭代的东西开始 —— 避免摊子铺的过大。
* 可触摸的和可操作的指标很重要 —— 确保不要掺杂其它东西。
* 人（文化）的转变是最具挑战的部分。
* 没有蓝图；任何一个组织和任何一个团队都是独一无二的。
* 转变是一个持续的过程。
* 透明和可视非常关键。
* 使用工程化流程去强化预期行为。

转换变化表：

|  | 过去 | 当前 | 想象 |
| --- | --- | --- | --- |
| 分支 | 服务于发布隔离 | 特性 | 主分支 |
| 构建 | 手动且易错 | 自动而一致 |  |
| 问题检测 | 来自用户 | 主动感知 |  |
| 问题解决 | 几天到几周 | 几分钟到几天 | 几分钟 |
| 计划 | 详细的设计 | 原型与故事板 |  |
| 流程管理 | 2 个流程经理（PM） | 0.25 个 PM | 0.125 个 PM |
| 发布终止 | 6 到 12 个月 | 3 到 5 周期 | 每个周期 |
| 发布 | 手动且易错 | 自动而一致 |  |
| 周期 | 1 个月 | 3 周 |  |
| 团队规模 | 10 到 15 | 2 到 5 |  |
| 构建时间 | 几小时 | 几秒钟 |  |
| 发布时间 | 几天 | 几分钟 |  |

但是，我们还没有做完，相反，我们就是一个令人兴奋的、持续不断的、几乎从不结束的转变的一部分。

如果你想去学习更多的关于我们的转变、有益的经验、以及想知道我们所经历的挑战，请查看 [转变到 DevOps 文化的记录](https://github.com/ALM-Rangers/Guidance/blob/master/src/Stories/our-journey-of-transforming-to-a-devops-culture.md)。"

---

via: <https://opensource.com/article/17/11/devops-rangers-transformation>

作者：[Willy Schaub](https://opensource.com/users/wpschaub) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Linux 中找到你的 IP 地址

Summary: 每个网站都有一个独有的公开 IP 地址，可供任何人从任何地方访问。

每个网站都有一个独有的公开 IP 地址，可供任何人从任何地方访问。

>
> 每个网站都有一个独有的公开 IP 地址，可供任何人从任何地方访问。
>
>
>

![](/data/attachment/album/201805/27/071823dewmmmiw8dwmapwp.jpg)

<ruby> 互联网协议 <rt>  Internet Protocol </rt></ruby>（IP）不需要介绍 —— 我们每天都在使用它。即使你不直接使用它，当你在浏览器上输入 website-name.com 时，它会查找该 URL 的 IP 地址，然后加载该网站。

我们将 IP 地址分为两类：私有和公共。私有 IP 地址是你的无线路由（和公司内网）提供的私有 IP 地址。它们的范围是 10.xxx、172.16.xx-172.31.xx 和 192.168.xx，其中 x=0 到 255。公有 IP 地址，顾名思义，是“公共”的，你可以在世界上任何地方访问它。每个网站都有一个唯一的 IP 地址，任何人可在任何地点访问，这可被视为公共 IP 地址。

此外，还有两种类型的 IP 地址：IPv4 和 IPv6。

IPv4 地址格式为 x.x.x.x，其中 x=0 到 255。有 2 32（大约 40 亿个）可能的 IPv4 地址。

IPv6 地址使用更复杂的十六进制。总的比特数是 128，这意味着有 2 128 （340 后面有 36 个零！）个可能的 IPv6 地址。IPv6 已经被引入解决了可预见的 IPv4 地址耗尽问题。

作为网络工程师，我建议不要与任何人共享你机器的公有 IP 地址。你的 WiFi 路由器有公共 IP，即 WAN（广域网）IP 地址，并且连接到该 WiFi 的任何设备都是相同的。连接到相同 WiFi 的所有设备都有上面所说的私有 IP 地址。例如，我的笔记本电脑的 IP 地址 192.168.0.5，而我的电话是 192.168.0.8。这些是私有 IP 地址，但两者都有相同的公有 IP 地址。

以下命令将列出IP地址列表，以查找你计算机的公有 IP 地址：

1. `ifconfig.me`
2. `curl -4/-6 icanhazip.com`
3. `curl ipinfo.io/ip`
4. `curl api.ipify.org`
5. `curl checkip.dyndns.org`
6. `dig +short myip.opendns.com @resolver1.opendns.com`
7. `host myip.opendns.com resolver1.opendns.com`
8. `curl ident.me`
9. `curl bot.whatismyipaddress.com`
10. `curl ipecho.net/plain`

以下命令将为你提供接口的私有 IP 地址：

1. `ifconfig -a`
2. `ip addr (ip a)`
3. `hostname -I | awk ‘{print $1}’`
4. `ip route get 1.2.3.4 | awk '{print $7}'`
5. `(Fedora) Wifi-Settings→ click the setting icon next to the Wifi name that you are connected to → Ipv4 and Ipv6 both can be seen`
6. `nmcli -p device show`

*注意：一些工具需要根据你正在使用的 Linux 发行版安装在你的系统上。另外，一些提到的命令使用第三方网站来获取 IP*

---

via: <https://opensource.com/article/18/5/how-find-ip-address-linux>

作者：[Archit Modi](https://opensource.com/users/architmodi) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


zzupdate：单条命令升级 Ubuntu 18.04 LTS

Summary: 我们可以只通过一条命令使用 zzupdate 工具中将 Ubuntu PC/Server 从一个版本升级到另一个版本。

Ubuntu 18.04 版本已经发布，并得到各个社区的一致好评，因为 Ubuntu 18.04 可能是 Ubuntu 多年来最令人兴奋的版本。

通常情况下，Ubuntu 及其衍生版可以使用命令从一个版本升级到最新版本或者其它版本，这也是官方推荐的升级方式。

### Ubuntu 18.04 特性/亮点

这次更新包含大量改进和新功能，这里只列举的几个主要的。如果您想要更详细的更新信息，请访问 [Ubuntu 18.04 官方](https://wiki.ubuntu.com/BionicBeaver/ReleaseNotes) 页面。

* 使用 Linux 4.15 内核，提供了从上游继承的新功能
* 它具有最新版本的 GNOME 3.28
* 它提供了与 RHEL 相似的最简安装选项，该选项可安装只包含一个 web 浏览器和核心系统程序的基本桌面环境
* 对于新安装，交换文件将取代默认的交换分区
* 您可以启用 Livepatch 安装内核更新而无需重新启动
* 笔记本电脑在使用电池供电时会在无操作 20 分钟后自动待机
* 不再提供 32 位的 Ubuntu 桌面安装程序映像

注意：

1. 不要忘记备份重要数据。如果升级出现问题，我们将重新安装并恢复数据。
2. 安装所需时间取决于您的网络状况和安装的程序。

![](/data/attachment/album/201805/27/071719gd2db2ddoddd2d2o.jpg)

### zzupdate 是什么？

我们可以只通过一条命令使用 [zzupdate](https://github.com/TurboLabIt/zzupdate) 工具中将 Ubuntu PC/Server 从一个版本升级到另一个版本。它是一个自由开源工具，使用它不需要任何脚本知识，因为它只需要配置文件即可运行。

工具中提供两个默认 shell 文件。`setup.sh` 自动安装、更新代码，将脚本转换为一个简单的 zzupdate shell 命令。`zzupdate.sh` 将执行版本间的升级。

### 如何安装 zzupdate？

要安装 `zzupdate`，只需执行以下命令：

```
$ curl -s https://raw.githubusercontent.com/TurboLabIt/zzupdate/master/setup.sh | sudo sh
.
.
Installing...
-------------
Cloning into 'zzupdate'...
remote: Counting objects: 57, done.
remote: Total 57 (delta 0), reused 0 (delta 0), pack-reused 57
Unpacking objects: 100% (57/57), done.
Checking connectivity... done.
Already up-to-date.

Setup completed!
----------------
See https://github.com/TurboLabIt/zzupdate for the quickstart guide.

```

将 Ubuntu 系统从一个版本升级到另一个版本，您不需要输入很多命令，也不需要重新启动，只需要运行下面的 `zzupdate` 命令并坐下喝杯咖啡就可以了。

请注意，当您远程升级系统时，建议您使用以下的工具来帮助您在任何断开连接时重新连接会话。

建议阅读： [如何让一个进程/命令在 SSH 连接断开后继续运行](https://www.2daygeek.com/how-to-keep-a-process-command-running-after-disconnecting-ssh-session/)

### 如何配置 zzupdate（可选）

默认情况下，`zzupdate` 可以开箱即用，不需要配置任何东西。当然，如果您想要自己配置一些内容也是可以的。复制提供的示例配置文件 `zzupdate.default.conf` 到 `zzupdate.conf`，并在 `zzupdate.conf` 中配置您的首选项。

```
$ sudo cp /usr/local/turbolab.it/zzupdate/zzupdate.default.conf /etc/turbolab.it/zzupdate.conf

```

打开文件，默认配置如下。

```
$ sudo nano /etc/turbolab.it/zzupdate.conf

REBOOT=1
REBOOT_TIMEOUT=15
VERSION_UPGRADE=1
VERSION_UPGRADE_SILENT=0
COMPOSER_UPGRADE=1
SWITCH_PROMPT_TO_NORMAL=0

```

* `REBOOT=1`：系统在更新完成后自动重启
* `REBOOT_TIMEOUT=15`：重启的默认超时值
* `VERSION_UPGRADE=1`：执行从一个版本到另一个版本的版本升级
* `VERSION_UPGRADE_SILENT=0`：禁用自动升级
* `COMPOSER_UPGRADE=1`：自动升级
* `SWITCH_PROMPT_TO_NORMAL=0`：如果值为 `0`，将寻找相同种类的版本升级。例如您正在运行 LTS 的版本，那么将寻找 LTS 的版本升级，而不是用于正常版本升级。如果值为 `1`，那么无论您是运行 LTS 还是正常版本，都会查找最新版本

我现在正在使用 Ubuntu 17.10 ，查看一下详细信息。

```
$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=17.10
DISTRIB_CODENAME=artful
DISTRIB_DESCRIPTION="Ubuntu 17.10"
NAME="Ubuntu"
VERSION="17.10 (Artful Aardvark)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 17.10"
VERSION_ID="17.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=artful
UBUNTU_CODENAME=artful

```

要升级 Ubuntu 到最新版本，只需要执行以下命令：

```
$ sudo zzupdate

O===========================================================O
 zzupdate - Wed May 2 17:31:16 IST 2018
O===========================================================O

Self-update and update of other zzScript
----------------------------------------
.
.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Updating...
----------
Already up-to-date.

Setup completed!
----------------
See https://github.com/TurboLabIt/zzupdate for the quickstart guide.

Channel switching is disabled: using pre-existing setting
---------------------------------------------------------

Cleanup local cache
-------------------

Update available packages informations
--------------------------------------
Hit:1 https://download.docker.com/linux/ubuntu artful InRelease
Ign:2 http://dl.google.com/linux/chrome/deb stable InRelease
Hit:3 http://security.ubuntu.com/ubuntu artful-security InRelease
Hit:4 http://in.archive.ubuntu.com/ubuntu artful InRelease
Hit:5 http://dl.google.com/linux/chrome/deb stable Release
Hit:6 http://in.archive.ubuntu.com/ubuntu artful-updates InRelease
Hit:7 http://in.archive.ubuntu.com/ubuntu artful-backports InRelease
Hit:9 http://ppa.launchpad.net/notepadqq-team/notepadqq/ubuntu artful InRelease
Hit:10 http://ppa.launchpad.net/papirus/papirus/ubuntu artful InRelease
Hit:11 http://ppa.launchpad.net/twodopeshaggy/jarun/ubuntu artful InRelease
.
.
UPGRADE PACKAGES
----------------
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
The following packages were automatically installed and are no longer required:
.
.
Interactively upgrade to a new release, if any
----------------------------------------------

Reading cache

Checking package manager
Reading package lists... Done
Building dependency tree
Reading state information... Done
Ign http://dl.google.com/linux/chrome/deb stable InRelease
Hit https://download.docker.com/linux/ubuntu artful InRelease
Hit http://security.ubuntu.com/ubuntu artful-security InRelease
Hit http://dl.google.com/linux/chrome/deb stable Release
Hit http://in.archive.ubuntu.com/ubuntu artful InRelease
Hit http://in.archive.ubuntu.com/ubuntu artful-updates InRelease
Hit http://in.archive.ubuntu.com/ubuntu artful-backports InRelease
Hit http://ppa.launchpad.net/notepadqq-team/notepadqq/ubuntu artful InRelease
Hit http://ppa.launchpad.net/papirus/papirus/ubuntu artful InRelease
Hit http://ppa.launchpad.net/twodopeshaggy/jarun/ubuntu artful InRelease
Fetched 0 B in 6s (0 B/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done

```

我们需要按下回车键禁用第三方仓库以继续升级。

```
Updating repository information

Third party sources disabled

Some third party entries in your sources.list were disabled. You can
re-enable them after the upgrade with the 'software-properties' tool
or your package manager.

To continue please press [ENTER]
.
.
Get:35 http://in.archive.ubuntu.com/ubuntu bionic-updates/universe i386 Packages [2,180 B]
Get:36 http://in.archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [1,644 B]
Fetched 38.2 MB in 6s (1,276 kB/s)

Checking package manager
Reading package lists... Done
Building dependency tree
Reading state information... Done

Calculating the changes

Calculating the changes

```

开始下载 `Ubuntu 18.04 LTS` 软件包，所需时间取决于您的网络状况，一般情况下这将需要几分钟。

```
Do you want to start the upgrade?

63 installed packages are no longer supported by Canonical. You can
still get support from the community.

4 packages are going to be removed. 175 new packages are going to be
installed. 1307 packages are going to be upgraded.

You have to download a total of 999 M. This download will take about
12 minutes with your connection.

Installing the upgrade can take several hours. Once the download has
finished, the process cannot be canceled.

Continue [yN] Details [d]y
Fetching
Get:1 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 base-files amd64 10.1ubuntu2 [58.2 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 debianutils amd64 4.8.4 [85.7 kB]
Get:3 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 bash amd64 4.4.18-2ubuntu1 [614 kB]
Get:4 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 locales all 2.27-3ubuntu1 [3,612 kB]
.
.
Get:1477 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 liblouisutdml-bin amd64 2.7.0-1 [9,588 B]
Get:1478 http://in.archive.ubuntu.com/ubuntu bionic/universe amd64 libtbb2 amd64 2017~U7-8 [110 kB]
Get:1479 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 libyajl2 amd64 2.1.0-2build1 [20.0 kB]
Get:1480 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 usb-modeswitch amd64 2.5.2+repack0-2ubuntu1 [53.6 kB]
Get:1481 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 usb-modeswitch-data all 20170806-2 [30.7 kB]
Get:1482 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 xbrlapi amd64 5.5-4ubuntu2 [61.8 kB]
Fetched 999 MB in 6s (721 kB/s)

```

安装新软件包时，很少有服务需要重新启动。 点击 `Yes` 按钮，它会自动重启所需的服务。

```
Upgrading
Inhibiting until Ctrl+C is pressed...
Preconfiguring packages ...
Preconfiguring packages ...
Preconfiguring packages ...
Preconfiguring packages ...
(Reading database ... 441375 files and directories currently installed.)
Preparing to unpack .../base-files_10.1ubuntu2_amd64.deb ...
Warning: Stopping motd-news.service, but it can still be activated by:
 motd-news.timer
Unpacking base-files (10.1ubuntu2) over (9.6ubuntu102) ...
Setting up base-files (10.1ubuntu2) ...
Installing new version of config file /etc/debian_version ...
Installing new version of config file /etc/issue ...
Installing new version of config file /etc/issue.net ...
Installing new version of config file /etc/lsb-release ...
motd-news.service is a disabled or a static unit, not starting it.
(Reading database ... 441376 files and directories currently installed.)
.
.
Progress: [ 80%]

Progress: [ 85%]

Progress: [ 90%]

Progress: [ 95%]

```

现在删除旧版的、系统不再需要的包。点击 `y` 以删除。

```
Searching for obsolete software
 ing package lists... 97%
 ding package lists... 98%
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading state information... 23%
Reading state information... 47%
Reading state information... 71%
Reading state information... 94%
Reading state information... Done

Remove obsolete packages?

88 packages are going to be removed.

Continue [yN] Details [d]y
.
.
.
done
Removing perlmagick (8:6.9.7.4+dfsg-16ubuntu6) ...
Removing snapd-login-service (1.23-0ubuntu1) ...
Processing triggers for libc-bin (2.27-3ubuntu1) ...
Processing triggers for man-db (2.8.3-2) ...
Processing triggers for dbus (1.12.2-1ubuntu1) ...
Fetched 0 B in 0s (0 B/s)

```

升级成功，需要重启系统。点击 `y` 以重启系统。

```
System upgrade is complete.

Restart required

To finish the upgrade, a restart is required.
If you select 'y' the system will be restarted.

Continue [yN]y

```

注意： 少数情况下，会要求您确认配置文件替换以继续安装。

查看升级后的系统详情：

```
$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04 LTS"
NAME="Ubuntu"
VERSION="18.04 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

```

---

via: <https://www.2daygeek.com/zzupdate-single-command-to-upgrade-ubuntu-18-04/>

作者：[PRAKASH SUBRAMANIAN](https://www.2daygeek.com/author/prakash/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[XiatianSummer](https://github.com/XiatianSummer) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


为什么 Oil States 案对于开源界是个好消息

>
> 提要：对于面临滥用专利制度的实体发起诉讼威胁的技术公司和创新者来说，此案是一个重大胜利。
>
>
>

![Why Oil States is good for open source](/data/attachment/album/201805/27/162348bnjodo79vdjdj14o.jpg "Why Oil States is good for open source")

对于面临滥用专利制度的实体发起诉讼威胁的技术公司和创新者来说，日前美国最高法院对 [Oil States 诉 Greene’s Energy 案](https://www.supremecourt.gov/opinions/17pdf/16-712_87ad.pdf)做出的[裁决是一个重大胜利](http://www.scotusblog.com/wp-content/uploads/2017/11/16-712-bsac-Dell.pdf)。此类滥用专利制度的实体试图从创新者和创造就业机会的企业身上攫取价值。

在 Oil States 案中，美国最高法院对美国专利商标局（USPTO）一项旨在质疑此前授权但存在问题的专利是否有效的行政程序是否违宪做出了裁决。<ruby> 专利流氓 <rp>  （ </rp> <rt>  patent trolls </rt> <rp>  ） </rp></ruby>最喜欢利用此类专利发起诉讼。这一称为<ruby> “双方复审” <rp>  （ </rp> <rt>  inter partes review </rt> <rp>  ） </rp></ruby>的程序已经成为一种应对基于可能无效专利而轻率发起的侵权主张的重要工具，其成本远低于在联邦法院检验此类专利有效性的成本。

美国国会根据<ruby> 《2011年美国发明法案》 <rp>  （ </rp> <rt>  America Invents Act of 2011 </rt> <rp>  ） </rp></ruby>创建了这种双方复审程序，以清理美国国会所认为的大量被不当授权的专利。此类专利被专利流氓用于向创新者谋取费用。自 2012 年实施该程序以来，已经有 7000 多份申请被提交，主要是为了审查计算机和高科技领域的可疑专利，并且有超过 1300 项权利主张被裁定无效。

在 7 比 2 的多数意见中，托马斯法官表示：“授予专利的决定是涉及公共权利的事项。双方复审只是对该授权过程的再审，美国国会已经授权美国专利商标局实施此种再审。”法官认为双方复审程序并没有侵犯专利权人所拥有的案件需由联邦法院裁决（在联邦法院无效专利的成本更高，诉讼费用明显更为昂贵）的宪法权利。

与开发、销售或实施复杂技术的任何实体一样，开发或实施开源软件的成功企业是专利流氓诉讼威胁的颇有吸引力的目标。因此，确认双方复审程序的合宪性不仅提高了专利系统的质量，而且也保留了一种工具来保护开源技术免受那些滥用专利系统的实体的攻击。

美国专利商标局打算评估双方复审程序的实施情况，这可能会影响其作为防御工具的有效性。但科技行业人士应继续让政策制定者保留《2011 年美国发明法案》所带来的有益变革，以保护创新并阻止滥用专利的行为。

---

作者简介：Matt Krupnick 是<ruby> 红帽公司 <rp>  （ </rp> <rt>  Red Hat </rt> <rp>  ） </rp></ruby>公共政策总监，于 2017 年加入红帽公司，负责政策制定以及为一系列对红帽公司及开源技术有潜在影响的各种政策问题提供建议。

译者简介：薛亮，集慧智佳知识产权咨询公司高级咨询师，擅长专利检索、专利分析、竞争对手跟踪、FTO 分析、开源软件知识产权风险分析，致力于为互联网企业、高科技公司提供知识产权咨询服务。

![](/data/attachment/album/201805/27/162328ymc7cnr7cybn64bu.jpg)


在 Ubuntu Snap 应用商店上发现的加密货币 ‘恶意软件’ 是怎么回事？

最近，有发现称一些 Ubuntu Snap 应用商店上的应用包含加密货币挖矿程序。Canonical 公司迅速下架了这些违规的应用，但是留下了几个有待回答的问题。

### 在 Snap 应用商店上发现了加密矿工

![Crypto Miner Malware on Ubuntu Snap Store](/data/attachment/album/201805/27/172420wm01d161f17s3q7v.jpg)

5 月 11 号，一位名叫 [tarwirdur](https://github.com/tarwirdur) 的用户在 [snapcraft.io repository](https://github.com/canonical-websites/snapcraft.io/issues/651) 开了一个新的工单 ，他提到一个由 Nicolas Tomb 开发，叫做 2048buntu 的 snap 应用包含加密货币矿工。tarwirdur 询问，他怎样才能出于安全的原因而“投诉该应用” 。tarwirdur 后来发表说其它由 Nicolas Tomb 开发的 snap 应用也都包含加密货币矿工。

看起来该 snap 应用使用了 systemd 在系统启动时自动地运行代码，并在用户不知情的情况下在后台运行。

>
> 对那些不熟悉相关术语的人来说，<ruby> 加密货币 <rt>  cryptocurrency </rt></ruby><ruby> 矿工 <rt>  miner </rt></ruby>是一段使用计算机的主处理器或者图形处理器来“挖掘”数字货币的程序。“挖矿”通常涉及到解决一个数学等式。在这种情况下，如果你在运行 2048buntu 游戏，这个游戏将会额外使用处理器的计算能力去进行加密货币的挖掘。
>
>
>

Snapcraft 团队迅速地下架了所有由该违规者开发的应用来做出回应。他们同时也开展了调查。

### 隐匿者发声

5 月 13 号，一位同名为 Nicolas Tomb 的 Disqus 用户在 OMGUbuntu 的新闻报道上发表了[评论](https://disqus.com/home/discussion/omgubuntu/malware_found_on_the_ubuntu_snap_store/#comment-3899153046)，他在评论中称自己向 snap 应用中添加了加密货币矿工，从而获取收益。他为他的行为道歉，同时承诺将所有挖矿所得的收益送给 Ubuntu 基金会。

我们不能确认这个评论就是由 Nicolas Tomb 发表的，因为这个 Disqus 账户最近才被创建，也只有一条评论与之相关联。现在，我们假设他是。

### Canonical 公司发表了声明

5 月 15 号，Canonical 公司在这种情况下发表了一份声明。标题为 [“在 Snap 应用商店中的信任与安全”](https://blog.ubuntu.com/2018/05/15/trust-and-security-in-the-snap-store)，声明开头重申了当下的情况。他们也补充道[重新发布的 snap 应用中已经被删除了加密货币挖矿程序](https://forum.snapcraft.io/t/action-against-snap-store-malware/5417/8)。

Canonical 公司随后尝试调查 Nicolas Tomb 的动机。他们指出，他告诉他们说自己这样做是为了通过应用赚钱（如上所诉），而当面对质疑时就停止了。他们也指出“挖掘加密货币本身并非不合法和不道德的”。然而，他们仍对他没有在 snap 应用描述中披露加密矿工这件事表示了不满意。

随后 Canonical 公司将话题转移到审核软件上。根据这份申明，Snap 应用商店将会采用一种类似 iOS、Android、Windows 的质量控制系统，这个系统将有“自动化的检查点，安装包必须在被接受前通过检查，同时在特殊问题被标记时会进行人工审核”。

然后，Canonical 公司声称“对大规模的软件仓库来说，只接受每个单独文件都被仔细审核过的软件是不可能的”。因此，他们需要信任软件源而不是内容。毕竟，软件源是现在 Ubuntu 软件仓库系统的基础。

Canonical 公司紧接着谈到了 Snap 应用的未来。他们承认现在的系统是不完美的。他们也在不断地进行改善。他们“在开发非常有趣的安全功能，这些功能将会在改善系统安全性同时提升人们在服务器或桌面上进行软件开发的体验”。

其中一个他们正在开发的功能是查看一个软件发布者是否已通过验证。其他的改进包括：“将所有 AppArmor 内核补丁递交到上游”和其它底层修复。

### 一些关于“Snap 应用商店中的恶意软件”的想法

基于我所了解的所有内容，我产生了一些想法和问题。

#### 这种挖矿软件运行多久了？

首先，这些挖矿软件存在于 Snap 应用商店多久了？因为它们已经被下架了，我们没有这样的数据。我可以通过 Google 快照抓取一些 2048buntu 页面的图片，但这没有提供任何可用的信息。根据该软件运行时间，多少系统安装过，挖掘出了什么加密货币，我们能否知道违规者获取的是一点钱还是一笔钱。一个更长远的问题是：Canonical 公司将来有能力捕捉到这样的违规情况吗？

#### 这真的是一个恶意软件吗？

许多新闻网站将之报道为恶意软件感染。我想我甚至可以看到这个事件被称为 Linux 的第一个恶意软件。我不确定这个术语是否精确。Dictionary.com 这样定义 [恶意软件](http://www.dictionary.com/browse/malware?s=t)：“意图损害计算机、移动设备、计算机系统或者计算机网络，或者对其运作进行部分控制的软件”。

这个有问题的 snap 应用并没有损害或者控制涉及到的计算机。它同样没有感染其他计算机。它也不能这样做，因为所有的 snap 应用位于沙盒之中。它们最多利用了处理器的计算能力，就是这样。所以，我不会称之为恶意软件。

#### 无孔不入

Nicolas Tomb 使用的一个辩解是在他上传应用的时候 Snap 应用商店没有任何反对加密货币挖矿的规则。（我敢向你打赌他们正在纠正这个错误。）他们之所以没有这样的规则，原因很简单，之前没有人做过这种事。如果 Tomb 想正确地做事，他应该提前询问是否允许这种行为。而事实是他似乎没有指出他知道 Canonical 公司可能会拒绝的事实。至少，Canonical 公司会告诉他将这些写在软件的描述中。

#### 一看就不对劲

![](/data/attachment/album/201805/27/172421oxxxs7kw2q2v44wm.png)

如我之前说的，我从 Google 快照获取了一个 2048buntu 的页面截图。仅仅看它就会感觉到一些危险的信号。首先，截图中几乎没有真实的描述。它是这样描述的“类似 2048 的游戏。这个游戏用 ubuntu 主题克隆了流行的游戏 2048。”哇，这将会引来容易上当受骗的人。当我读到类似空洞的描述时，我会多考虑下。

我注意到的另一件事是软件的大小。2048buntu 的 1.0 版本大小将近 140 MB。一个简单的游戏怎么需要这么多的空间？有用 Javascript 写的浏览器版本大概只用了不到它的四分之一。其他 snap 应用商店的 2048 游戏的大小没有一个达到了这个软件的一半。

然后，它有个许可证。这是一个使用了 Ubuntu 主题的流行游戏的克隆。它怎么能被认为是专有软件？我确信，其他合法的开发者会因为该内容而使用了 FOSS （自由开源软件）许可证来上传它。

单是这些因素就使得这个 snap 应用很特殊，应该进行审核。

#### 谁是 Nicolas Tomb？

当第一次了解到这些之后，我决定看看我能否找出造成这些混乱的人。当我搜索 Nicolas Tomb 的时候，我什么都没找到。所有我找到的只是一大堆关于加密货币挖矿 snap 应用的新闻和文章，以及去 tomb of St. Nicolas 旅游的信息。在 Twiter 和 Github 上都没有 Nicolas Tomb 的标志。看起来似乎是为了上传这些 snap 应用才创建的名称。

这同样引出了 Canonical 公司发表的申明中的一点，关于验证发布者。上一次我查看的时候，相当多的 snap 应用不是由应用的维护者发布的。这让我感到担忧。我更乐意相信由 Mozilla 基金会发布的 firefox 的 snap 应用，而不是 Leonard Borsch。如果对应用维护者来说关注应用的 snap 版本太耗费精力，应该有办法让维护者在他们软件的 snap 版本上贴上批准的标签。就像是 Firefox 的 snap 版本由 Fredrick 发布，经 Mozilla 基金会批准。这样才能让用户对下载的内容更放心。

#### 无疑 Snap 应用商店还有改善的空间

在我看来，Snap 应用商店团队应该实现的第一个特性是报告可疑应用的方式。tarwirdur 必须找到该网站的 Github 页面才行。而大多数用户不会想到这一点。如果 Snap 应用商店不能审核每一行代码，那么使用户能够报告问题是退而求其次的办法。即使评分系统也是一个不差的补充。我确信一定有部分人因为 2048buntu 使用了太多系统资源而给它很低的评分。

### 结论

从我所知道的情况来说，我认为这是某个人创建了一些简单的应用，在每个应用中嵌入了加密货币矿工，之后将这些应用上传到 Snap 应用商店，想着捞一笔钱。一旦他们被抓了，他们就声称这仅仅为了通过应用程序获利。如果真的是这样，他们应该在 snap 应用的描述中提到才对。隐藏加密矿工并不是什么[新鲜事](https://krebsonsecurity.com/2018/03/who-and-what-is-coinhive/)。他们通常是一种盗取计算能力的方法。

我希望 Canonical 公司已经具备了解决这个问题的功能，盼望这些功能能很快出来。

你对 Snap 应用商店的“恶意软件风波”有什么看法？你将如何改善这种情况？请在下面的评论中告诉我们。

如果你觉得这篇文章有趣，请花费一点时间将它分享到社交媒体上。

---

via: <https://itsfoss.com/snapstore-cryptocurrency-saga/>

作者：[John Paul](https://itsfoss.com/author/john/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[paperzhang](https://github.com/paperzhang) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Cron 任务入门指南

![](/data/attachment/album/201805/28/004507fa4g4x4g89mqt9xm.jpg)

**Cron** 是您可以在任何类 Unix 操作系统中找到的最有用的实用程序之一。它用于安排命令在特定时间执行。这些预定的命令或任务被称为 “Cron 任务”。Cron 通常用于运行计划备份、监视磁盘空间、定期删除不再需要的文件（例如日志文件）、运行系统维护任务等等。在本简要指南中，我们将看到 Linux 中 Cron 任务的基本用法。

### Cron 任务入门指南

cron 任务的典型格式是：

```
分钟(0-59) 小时(0-24) 日(1-31) 月(1-12) 星期(0-6) 要执行的命令

```

只需记住 cron 任务的格式或打印下面的插图并将其放在你桌面上即可。

![](/data/attachment/album/201805/28/004509fp0o3pzi04ayawak.png)

在上图中，星号表示特定的时间块。

要显示当前登录用户的 crontab 文件的内容：

```
$ crontab -l

```

要编辑当前用户的 cron 任务，请执行以下操作：

```
$ crontab -e

```

如果这是第一次编辑此文件，会询问你使用哪个编辑器来编辑此文件。

```
no crontab for sk - using an empty one

Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed

Choose 1-4 [1]:

```

选择适合你的编辑器。这里是一个示例 crontab 文件的样子。

![](/data/attachment/album/201805/28/004511urkcd7d1drcrdc1d.png)

在这个文件中，你需要添加你的 cron 任务。

要编辑其他用户的 crontab，例如 ostechnix，请执行：

```
$ crontab -u ostechnix -e

```

让我们看看一些例子。

要 **每分钟** 执行一次 cron 任务，需使用如下格式。

```
* * * * * <command-to-execute>

```

要每 5 分钟运行一次 cron 任务，请在 crontab 文件中添加以下内容。

```
*/5 * * * * <command-to-execute>

```

要在每 1/4 个小时（每 15 分钟）运行一次 cron 任务，请添加以下内容：

```
*/15 * * * * <command-to-execute>

```

要每小时的第 30 分钟运行一次 cron 任务，请运行：

```
30 * * * * <command-to-execute>

```

您还可以使用逗号定义多个时间间隔。例如，以下 cron 任务每小时运行三次，分别在第 0、 5 和 10 分钟运行：

```
0,5,10 * * * * <command-to-execute>

```

每半小时运行一次 cron 任务：

```
*/30 * * * * <command-to-execute>

```

每小时运行一次：

```
0 * * * * <command-to-execute>

```

每 2 小时运行一次：

```
0 */2 * * * <command-to-execute>

```

每天运行一项（在 00:00 运行）：

```
0 0 * * * <command-to-execute>

```

每天凌晨 3 点运行：

```
0 3 * * * <command-to-execute>

```

每周日运行：

```
0 0 * * SUN <command-to-execute>

```

或使用，

```
0 0 * * 0 <command-to-execute>

```

它将在每周日的午夜 00:00 运行。

星期一至星期五每天运行一次，亦即每个工作日运行一次：

```
0 0 * * 1-5 <command-to-execute>

```

这项工作将于 00:00 开始。

每个月运行一次：

```
0 0 1 * * <command-to-execute>

```

于每月第 1 天的 16:15 运行：

```
15 16 1 * * <command-to-execute>

```

每季度运行一次，亦即每隔 3 个月的第 1 天运行：

```
0 0 1 */3 * <command-to-execute>

```

在特定月份的特定时间运行：

```
5 0 * 4 * <command-to-execute>

```

每个四月的 00:05 运行。

每 6 个月运行：

```
0 0 1 */6 * <command-to-execute>

```

这个定时任务将在每六个月的第一天的 00:00 运行。

每年运行：

```
0 0 1 1 * <command-to-execute>

```

这项 cron 任务将于 1 月份的第一天的 00:00 运行。

我们也可以使用以下字符串来定义任务。

`@reboot` 在每次启动时运行一次。 `@yearly` 每年运行一次。 `@annually`（和 `@yearly` 一样）。 `@monthly` 每月运行一次。 `@weekly` 每周运行一次。 `@daily` 每天运行一次。 `@midnight` （和 `@daily` 一样）。 `@hourly` 每小时运行一次。

例如，要在每次重新启动服务器时运行任务，请将此行添加到您的 crontab 文件中。

```
@reboot <command-to-execute>

```

要删除当前用户的所有 cron 任务：

```
$ crontab -r

```

还有一个名为 [crontab.guru](https://crontab.guru/) 的专业网站，用于学习 cron 任务示例。这个网站提供了很多 cron 任务的例子。

有关更多详细信息，请查看手册页。

```
$ man crontab

```

那么，就是这样。到此为止，您应该对 cron 任务以及如何实时使用它们有了一个基本的了解。后续还会介绍更多的优秀工具。敬请关注！！

干杯!

---

via: <https://www.ostechnix.com/a-beginners-guide-to-cron-jobs/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[KevinSJ](https://github.com/KevinSJ) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 X 中启动用户软件

![](/data/attachment/album/201805/28/215431k8cpcr4cpc4ckb9k.jpg)

目前有很多方法可以在开启用户会话时启动软件。

这是一篇试图将所有方法聚集在一起的文章。某些部分可能不精确或不正确，但这是一个开始，如果我收到更正，我很乐意保持更新。

### x11-common

```
man xsession

```

* 由显示管理器启动，如 `/usr/share/lightdm/lightdm.conf.d/01_debian.conf` 或 `/etc/gdm3/Xsession`。
* Debian 特定。
* 在 `/etc/X11/Xsession.d/` 中运行脚本。
* `/etc/X11/Xsession.d/40x11-common_xsessionrc` 引用 `~/.xsessionrc` ，它能比设置环境变量能做的多一点，因为它在 X 会话启动时运行。
* 最后，它启动会话管理器（`gnome-session`、`xfce4-session` 等等）。

### systemd --user

* <https://wiki.archlinux.org/index.php/Systemd/User>
* 由 `pam_systemd` 启动，所以在环境变量中可能没有设置 `DISPLAY` 变量。
* 管理单元：
	+ `/usr/lib/systemd/user/` 由已安装的软件包提供的单元。
	+ `~/.local/share/systemd/user/` 由安装在家目录的软件包提供的单元。
	+ `/etc/systemd/user/` 由系统管理员提供的系统范围的用户的单元。
	+ `~/.config/systemd/user/` ，用户自己放置的单元。
* 当设置 X 会话和 `DISPLAY` 变量时，启动 systemd 用户单元的技巧是从 `.desktop` 自启动文件调用 `systemctl start`。

### dbus 激活

* <https://dbus.freedesktop.org/doc/system-activation.txt>
* 进行 dbus 请求的用户进程可以触发启动服务器程序。
* 对于系统调试，有没有一种方法可以监控哪些服务正在启动 dbus ？

### X 会话管理器

* <https://en.wikipedia.org/wiki/X_session_manager>
* 由 `x11-common` 的 `Xsession.d` 运行。
* 运行 freedesktop 自动启动的 `.desktop` 文件。
* 运行桌面环境特定的软件。

### xdg 自动启动

* <https://specifications.freedesktop.org/autostart-spec/autostart-spec-latest.html>
* 由会话管理器运行。
* 如果存在 `/etc/xdg/autostart/foo.desktop` 和 `~/.config/autostart/foo.desktop` ，那么只会使用 `~/.config/autostart/foo.desktop`，因为 `~/.config/autostart/` 比 `/etc/xdg/autostart/` 更重要。
* 是顺序的还是并行？

### 其他启动注意事项

#### ~/.Xauthority

要连接到 X 服务器，客户端需要从 `~/.Xauthority` 发送一个令牌，这证明他们可以读取用户的隐私数据。

`~/.Xauthority` 包含显示管理器生成的一个令牌，并在启动时传递给 X。

要查看它的内容，请使用 `xauth -i -f ~/.Xauthority list`。

---

via: <http://www.enricozini.org/blog/2018/debian/starting-user-software/>

作者：[Enrico Zini](http://www.enricozini.org/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在终端中显示图片

Summary: Linux 上有许多 GUI 图片浏览器。但我尚未听说或使用过任何在终端中显示图片的应用程序。幸运的是，我刚刚发现了一个可用于在终端中显示图像的名叫 FIM 的图像查看器。

![](/data/attachment/album/201805/29/070700z6mmvldnva6akrek.png)

Linux 上有许多 GUI 图片浏览器。但我尚未听说或使用过任何在终端中显示图片的应用程序。幸运的是，我刚刚发现了一个可用于在终端中显示图像的名叫 **FIM** 的图像查看器。FIM 引起了我的注意，是因为与大多数 GUI 图片浏览器相比，它非常轻巧。毫不迟疑，让我们来看看它能做什么。

### 使用 FIM 在终端中显示图像

**FIM** 意即 **F**bi **IM**proved。对于那些不知道的人，**Fbi** 是指 Linux 中的 **f**rame **b**uffer **i**mageviewer。它使用系统的帧缓冲器直接从命令行显示图像。默认情况下，它能用终端显示 bmp、gif、jpeg、PhotoCD、png、ppm、tiff 和 xwd。对于其他格式，它会尝试使用 ImageMagick 的转换。

FIM 基于 Fbi，它是一款高度可高度定制及脚本化的图像浏览器，非常适合使用 Vim 文本编辑器或 Mutt 等软件的用户。它会以全屏显示图像，并可通过键盘快捷键控制（如调整大小、翻转、缩放）。与 Fbi 不同的是，FIM 是通用的：它可以打开许多文件格式，并且可以在以下视频模式下显示图片：

* 使用 Linux framebuffer 设备，以图形方式呈现
* 在 X / Xorg 下，使用 SDL 库，以图形方式呈现
* 在 X / Xorg 下，使用 Imlib2 库，以图形方式呈现。
* 在任何文本控制台中使用 AAlib 库呈现为 ASCII 字符画

FIM 是完全免费且开源的。

### 安装 FIM

基于 DEB 的系统，如 Ubuntu、Linux Mint， 可从默认的仓库中获取 FIM 图像查看器。因此，你可以使用如下命令安装fbi：

```
$ sudo apt-get install fim

```

如果它在你使用的 Linux 发行版的仓库中不包含 FIM，则可以下载源代码进行编译和安装，如下所示。

```
wget http://download.savannah.nongnu.org/releases/fbi-improved/fim-0.6-trunk.tar.gz
wget http://download.savannah.nongnu.org/releases/fbi-improved/fim-0.6-trunk.tar.gz.sig
gpg --search 'dezperado autistici org'
＃按照屏幕上的说明，从密钥服务器导入密钥
gpg --verify fim-0.6-trunk.tar.gz.sig

```

```
tar xzf fim-0.6-trunk.tar.gz
cd fim-0.6-trunk
./configure --help=short
＃阅读./configure --help=short 的输出：你可以在 ./configure 中添加选项
./configure
make
su -c“make install”

```

### FIM用法

安装完成后，您可以使用以下命令以“自动缩放”显示的图像：

```
$ fim -a dog.jpg

```

这里是我的 Ubuntu 主机的示例输出。

![](/data/attachment/album/201805/29/070702b4qqxma1u4ixrtrw.png)

正如你在上面的屏幕截图中看到的，FIM 没有使用任何外部 GUI 图片浏览器。相反，它使用我们系统的帧缓冲器来显示图像。

如果当前目录中有多个 .jpg 文件，可以使用通配符打开所有文件，如下所示。

```
$ fim -a * .jpg

```

要打开目录中的所有图像，例如 `Pictures`，请运行：

```
$ fim Pictures/

```

我们也可以在文件夹及其子文件夹中递归地打开图像，然后像下面那样对列表进行排序。

```
$ fim -R Pictures/ --sort

```

要以 ASCII 格式渲染图像，可以使用 `-t` 标志。

```
$ fim -t dog.jpg

```

要退出 Fim，请按 `ESC` 或 `q`。

#### 键盘快捷键

您可以使用各种键盘快捷键来管理图像。例如，要加载下一张图像和之前的图像，请按下 `PgUp` / `PgDown` 键。成倍放大或缩小，请使用 `+` / `-` 键。以下是用于在FIM中控制图像的常用按键。

* `PageUp` / `Down`：上一张/下一张图片
* `+` / `-` ：放大/缩小
* `a`：自动缩放
* `w`：自适应宽度
* `h`：自适应高度
* `j` / `k`：平移/向上
* `f` / `m`：翻转/镜像
* `r` / `R`：旋转（顺时针/逆时针）
* `ESC` / `q`：退出

有关完整详细信息，请参阅手册页。

```
$ man fim

```

那么，就是这样。希望这对你有所帮助。后续还会介绍更多的优秀工具。敬请关注！

干杯!

---

via: <https://www.ostechnix.com/how-to-display-images-in-the-terminal/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[KevinSJ](https://github.com/KevinSJ) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


DevOps 接下来会发生什么：要关注的 5 个趋势

Summary: 专家们权衡了 DevOps 团队最近会有何期望。

专家们权衡了 DevOps 团队最近会有何期望。

>
> 专家们权衡了 DevOps 团队最近会有何期望。
>
>
>

![](/data/attachment/album/201805/29/073014kx8s8oa778ii8i7i.png)

“DevOps” 一词通常认为是来源于 [这篇 2008 年关于敏捷基础设施和运营的讲演中](http://www.jedi.be/presentations/agile-infrastructure-agile-2008.pdf)。现在的 IT 词汇中，它无处不在，这个“混搭”的词汇出现还不到 10 年：我们还在研究它在 IT 中更现代化的工作方法。

诚然，多年来一直在 “从事 DevOps” 的人积累了丰富的知识。但是大多数的 DevOps 环境 —— 人与 [文化](https://enterprisersproject.com/article/2017/9/5-ways-nurture-devops-culture) 、流程与方法、工具与技术的融合 —— 还远远没有成熟。

更多的变化即将到来。Robert Reeves 说 “DevOps 是一个过程，一种算法”，他是 [Datical](https://www.datical.com/) 的 CTO， “它的绝对目标就是随着时间进行改变和演进”，这就是重点。

那我们预计接下来会发生什么呢？这里有一些专家们观察到的重要趋势。

### 1、 预计 DevOps、容器、以及微服务之间的相互依赖会增强

驱动 DevOps 发展的文化本身可能会演进。当然，DevOps 仍然将在根本上摧毁传统的 IT 孤岛和瓶颈，但这样做的理由可能会变得更加急迫。证据 A & B： [对容器和微服务的兴趣](https://enterprisersproject.com/article/2017/9/microservices-and-containers-6-things-know-start-time) 与日俱增。这个技术组合很强大、可连续扩展、与规划和 [持续进行的管理](https://enterprisersproject.com/article/2017/10/microservices-and-containers-6-management-tips-long-haul)配合最佳。

Arvind Soni 说 “影响 DevOps 的其中一个主要因素是向微服务转变”，他是 [Netsil](https://netsil.com/) 的产品副总裁，补充道，容器和业务流程，使开发者打包和交付的速度越来越快。DevOps 团队的任务可能是帮助去加速打包并管理越来越复杂的微服务弹性架构。

### 2、 预计 ”安全网“ 更少

DevOps 使团队可以更快更敏捷地去构建软件，部署速度也更快更频繁、同时还能提升软件质量和稳定性。但是好的 IT 领导通常都不会忽视管理风险，因此，早期大量的 DevOps 迭代都是使用了安全防护 —— 从后备的不重要业务开始的。为了实现更快的速度和敏捷性，越来越多的团队将抛弃他们的 ”辅助轮“（LCTT 译注：意思说减少了安全防护措施）。

Nic Grange 说 “随着团队的成熟，他们决定不再需要一些早期增加的安全 ‘防护栏’ 了”，他是 [Retriever Communications](http://retrievercommunications.com/) 的 CTO。Grange 给出了一个阶段展示的服务器的示例：随着 DevOps 团队的成熟，他们决定不再需要阶段展示的服务器了，尤其是他们很少在试生产环境中发现问题。（Grange 指出，这一举措对于缺乏 DevOps 经验的团队来说，不可轻易效仿）

Grange 说 “这个团队可能在监视和发现并解决生产系统中出现的问题的能力上有足够的信心”，“部署过程和测试阶段，如果没有任何证据证明它的价值，那么它可能会把整个进度拖慢”。

### 3、 预计 DevOps 将在其它领域大面积展开

DevOps 将两个传统的 IT 部门（开发和运营）结合的更紧密。越来越多的公司看到了这种结合的好处，这种文化可能会传播开来。这种情况在一些组织中已经出现，在 “DevSecOps” 一词越来越多出现的情况下，它反映出了在软件开发周期中有意地、越来越早地包含了安全性。

Derek Weeks 说 “DevSecOps 不仅是一个工具，它是将安全思维更早地集成到开发实践中”，它是 [Sonatype](https://www.sonatype.com/) 的副总裁和 DevOps 拥挤者。

[Red Hat](https://www.redhat.com/en/) 的安全策略师 Kirsten Newcomer 说，这种做法并不是一个技术挑战，而是一个文化挑战。

Newcomer 说 “从历史来看，安全团队都是从开发团队中分离出来的 —— 每个团队在它们不同的 IT 领域中形成了各自的专长” ，“它并不需要这种方法。每个关心安全性的企业也关心他们通过软件快速交付业务价值的能力，这些企业正在寻找方法，将安全放进应用程序的开发周期中。它们采用 DevSecOps 通过 CI/CD 流水线去集成安全实践、工具和自动化。为了做的更好，他们整合他们的团队 —— 将安全专家整合到应用程序开发团队中，参与到从设计到产品部署的全过程中。这种做法使双方都看到了价值 —— 每个团队都扩充了它们的技能和知识，使他们成为更有价值的技术专家。DevOps 做对了 —— 或者说是 DevSecOps —— 提升了 IT 安全性。”

除了安全以外，还可以让 DevOps 扩展到其它领域，比如数据库团队、QA，甚至是 IT 以外的潜在领域。

Datical 的 Reeves 说 “这是一件非常 DevOps 化的事情：发现相互掣肘的地方并解决它们”，“对于以前采用 DevOps 的企业来说，安全和数据库是他们面临的最大瓶颈。”

### 4、 预计 ROI 将会增加

Eric Schabell 说，“由于公司深入推进他们的 DevOps 工作，IT 团队在方法、流程、容器和微服务方面的投资将得到更多的回报。” 他是 Red Hat 的全球技术传播总监，Schabell 说 “‘圣杯’将移动的更快、完成的更多、并且变得更灵活。由于这些组件找到了更宽阔的天地，组织在应用程序中更有归属感时，结果就会出现。”

“每当新兴技术获得我们的关注时，任何事都有一个令人兴奋的学习曲线，但当认识到它应用很困难的时候，同时也会经历一个从兴奋到幻灭的低谷。最终，我们将开始看到从低谷中爬出来，并收获到应用 DevOps、容器、和微服务的好处。”

### 5、 预计成功的指标将持续演进

Mike Kail 说 “我相信 DevOps 文化的两个核心原则 —— 自动化和可衡量是从来不会变的”，它是 [CYBRIC](https://www.cybric.io/) 的 CTO，也是 Yahoo 前 CIO。“总是有办法去自动化一个任务，或者提升一个已经自动化的解决方案，而随着时间的推移，重要的事情是测量可能的变化和扩展。这个成熟的过程是一个永不停步的旅行，而不是一个目的地或者已完成的任务。”

在 DevOps 的精神中，成熟和学习也与协作者和分享精神有关。Kail 认为，对于敏捷方法和 DevOps 文化来说，它仍然为时尚早，这意味着它们还有足够的增长空间。

Kail 说 “随着越来越多的成熟组织持续去测量可控指标，我相信（希望） —— 这些经验应该被广泛的分享，以便我们去学习并改善它们。”

作为 Red Hat 技术传播专家，[Gordon Haff](https://enterprisersproject.com/user/gordon-haff) 最近注意到，组织使用业务成果相关的因素去改善他们的 DevOps 指标的工作越来越困难。 [Haff 写道](https://enterprisersproject.com/article/2017/7/devops-metrics-are-you-measuring-what-matters) “你或许并不真正关心你的开发者写了多少行代码、服务器是否在一夜之间出现了硬件故障、或者你的测试覆盖面是否全面”。事实上，你可能并不直接关心你的网站的响应速度和更新快慢。但是你要注意的是，这些指标可能与消费者放弃购物车或者转到你的竞争对手那里有关。”

与业务成果相关的一些 DevOps 指标的例子包括，消费者交易金额（作为消费者花销统计的指标）和净推荐值（消费者推荐公司产品和服务的意愿）。关于这个主题更多的内容，请查看这篇完整的文章—— [DevOps 指标：你是否测量了重要的东西](https://enterprisersproject.com/article/2017/7/devops-metrics-are-you-measuring-what-matters)。

### 唯一不变的就是改变

顺利说一句，如果你希望这件事一蹴而就，那你就要倒霉了。

Reeves 说 “如果你认为今天发布非常快，那你就什么也没有看到”，“这就是为什么要让相关者包括数据库团队进入到 DevOps 中的重要原因。因为今天这两组人员的冲突会随着发布速度的提升而呈指数级增长。”

---

via: <https://enterprisersproject.com/article/2017/10/what-s-next-devops-5-trends-watch>

作者：[Kevin Casey](https://enterprisersproject.com/user/kevin-casey) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


四个 Linux 上的网络信息嗅探工具

Summary: 在计算机网络中，数据是暴露的，因为数据包传输是无法隐藏的

在计算机网络中，数据是暴露的，因为数据包传输是无法隐藏的

![network](/data/attachment/album/201805/30/051915svsqx6cuu1d1ht6t.jpg "network")

在计算机网络中，数据是暴露的，因为数据包传输是无法隐藏的，所以让我们来使用 `whois`、`dig`、`nmcli` 和 `nmap` 这四个工具来嗅探网络吧。

请注意，不要在不属于自己的网络上运行 `nmap` ，因为这有可能会被其他人认为恶意攻击。

### 精简和详细域名信息查询

您可能已经注意到，之前我们用常用的老式 `whois` 命令查询域名信息，但现如今似乎没有提供同过去一样的详细程度。我们使用该命令查询 linux.com 的域名描述信息：

```
$ whois linux.com
Domain Name: LINUX.COM
Registry Domain ID: 4245540_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.namecheap.com
Registrar URL: http://www.namecheap.com
Updated Date: 2018-01-10T12:26:50Z
Creation Date: 1994-06-02T04:00:00Z
Registry Expiry Date: 2018-06-01T04:00:00Z
Registrar: NameCheap Inc.
Registrar IANA ID: 1068
Registrar Abuse Contact Email: abuse@namecheap.com
Registrar Abuse Contact Phone: +1.6613102107
Domain Status: ok https://icann.org/epp#ok
Name Server: NS5.DNSMADEEASY.COM
Name Server: NS6.DNSMADEEASY.COM
Name Server: NS7.DNSMADEEASY.COM
DNSSEC: unsigned
[...]

```

有很多令人讨厌的法律声明。但在哪有联系信息呢？该网站位于 `whois.namecheap.com` 站点上（见上面输出的第三行）：

```
$ whois -h whois.namecheap.com linux.com

```

我就不复制出来了，因为这实在太长了，包含了注册人，管理员和技术人员的联系信息。怎么回事啊，露西尔？（LCTT 译注：《行尸走肉》中尼根的棒子）有一些注册库，比如 .com 和 .net 是精简注册库，保存了一部分有限的域名信息。为了获取完整信息请使用 `-h` 或 `--host` 参数，该参数便会从域名的 `注册服务机构` 中获取。

大部分顶级域名是有详细的注册信息，如 .info。试着使用 `whois blockchain.info` 命令来查看。

想要摆脱这些烦人的法律声明？使用 `-H` 参数。

### DNS 解析

使用 `dig` 命令比较从不同的域名服务器返回的查询结果，去除陈旧的信息。域名服务器记录缓存各地的解析信息，并且不同的域名服务器有不同的刷新间隔。以下是一个简单的用法：

```
$ dig linux.com
<<>> DiG 9.10.3-P4-Ubuntu <<>> linux.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<<- opcode: QUERY, status: NOERROR, id: 13694
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1440
;; QUESTION SECTION:
;linux.com. IN A

;; ANSWER SECTION:
linux.com. 10800 IN A 151.101.129.5
linux.com. 10800 IN A 151.101.65.5
linux.com. 10800 IN A 151.101.1.5
linux.com. 10800 IN A 151.101.193.5

;; Query time: 92 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Tue Jan 16 15:17:04 PST 2018
;; MSG SIZE rcvd: 102

```

注意下靠近末尾的这行信息：`SERVER: 127.0.1.1#53(127.0.1.1)`，这是您默认的缓存解析器。当地址是本地时，就表明您的电脑上安装了 DNS 服务。在我看来这就是一个 Dnsmasq 工具（LCTT 译注：是一个小巧且方便地用于配置 DNS 和 DHCP 的工具），该工具被用作网络管理：

```
$ ps ax|grep dnsmasq
2842 ? S 0:00 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground
--no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid
--listen-address=127.0.1.1

```

`dig` 命令默认是返回 A 记录，也就是域名。IPv6 则有 AAAA 记录：

```
$ $ dig linux.com AAAA
[...]
;; ANSWER SECTION:
linux.com. 60 IN AAAA 64:ff9b::9765:105
linux.com. 60 IN AAAA 64:ff9b::9765:4105
linux.com. 60 IN AAAA 64:ff9b::9765:8105
linux.com. 60 IN AAAA 64:ff9b::9765:c105
[...]

```

仔细检查下，发现 linux.com 有 IPv6 地址。很好！如果您的网络服务支持 IPv6 那么您就可以用 IPv6 连接。（令人难过的是，我的移动宽带则没提供 IPv6）

假设您能对您的域名做一些 DNS 改变，又或是您使用 `dig` 查询的结果有误。试着用一个公共 DNS，如 OpenNIC：

```
$ dig @69.195.152.204 linux.com
[...]
;; Query time: 231 msec
;; SERVER: 69.195.152.204#53(69.195.152.204)

```

`dig` 回应您正在的查询是来自 69.195.152.204。您可以查询各种服务并且比较结果。

### 上游域名服务器

我想知道我的上游域名服务器（LCTT 译注：此处指解析器）是谁。为了查询，我首先看下 `/etc/resolv/conf` 的配置信息:

```
$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.1.1

```

好吧，不过我已经知道了。您的 Linux 发行版可能配置不同，您会看到您的上游服务器。接下来我们来试试网络管理器命令行工具 `nmcli`：

```
$ nmcli dev show | grep DNS
IP4.DNS[1]: 192.168.1.1

```

很好，现在我们已经知道了，其实那是我的移动热点，我能确认。我能够登录到简易管理面板，来查询上游服务器。然而许多用户级互联网网关不会让您看到或改变这些设置，因此只能尝试其他的方法，如 [我的域名服务器是什么？](http://www.whatsmydnsserver.com/)

### 查找在您的网络中 IPv4 地址

您的网络上有哪些 IPv4 地址已启用并正在使用中？

```
$ nmap -sn 192.168.1.0/24
Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 14:03 PST
Nmap scan report for Mobile.Hotspot (192.168.1.1)
Host is up (0.011s latency).
Nmap scan report for studio (192.168.1.2)
Host is up (0.000071s latency).
Nmap scan report for nellybly (192.168.1.3)
Host is up (0.015s latency)
Nmap done: 256 IP addresses (2 hosts up) scanned in 2.23 seconds

```

每个人都想去扫描自己的局域网中开放的端口。下面的例子是寻找服务和他们的版本号：

```
$ nmap -sV 192.168.1.1/24

Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 16:46 PST
Nmap scan report for Mobile.Hotspot (192.168.1.1)
Host is up (0.0071s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp filtered ssh
53/tcp open domain dnsmasq 2.55
80/tcp open http GoAhead WebServer 2.5.0

Nmap scan report for studio (192.168.1.102)
Host is up (0.000087s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
631/tcp open ipp CUPS 2.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 256 IP addresses (2 hosts up) scanned in 11.65 seconds

```

这些是有趣的结果。让我们尝试从不同的互联网连接进行相同的操作，以查看这些服务是否暴露于互联网中。如果您有智能手机，相当于您有第二个网络。您可以下载应用程序，还可以为您的 Linux 电脑提供热点。从热点控制面板获取广域网IP地址，然后重试：

```
$ nmap -sV 12.34.56.78

Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 17:05 PST
Nmap scan report for 12.34.56.78
Host is up (0.0061s latency).
All 1000 scanned ports on 12.34.56.78 are closed

```

果然不出所料，结果和我想象的一样（LCTT 译注：这些服务和信息没有被暴露在公网上）。可以用手册来查询这些命令，以便了解更多有趣的嗅探技术。

了解更多 Linux 的相关知识可以从 Linux 基金会和 edX（LCTT译注：edX 是麻省理工和哈佛大学于 2012 年 4 月联手创建的大规模开放在线课堂平台）中获取免费的 [“介绍 Linux”](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)课程。

---

via: <https://www.linux.com/learn/intro-to-linux/2018/1/4-tools-network-snooping-linux>

作者：[Carla Schroder](https://www.linux.com/users/cschroder) 译者：[wyxplus](https://github.com/wyxplus) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在 Linux 中安装 Ncurses 库

Summary: GNU Ncurses 是一个允许用户编写基于文本的用户界面（TUI）的编程库。许多基于文本的游戏都是使用这个库创建的。

![](/data/attachment/album/201805/30/052558qxq9b12iz8qk8nqh.png)

**GNU Ncurses** 是一个允许用户编写基于文本的用户界面（TUI）的编程库。许多基于文本的游戏都是使用这个库创建的。一个受欢迎的例子是 [PacVim](https://www.ostechnix.com/pacvim-a-cli-game-to-learn-vim-commands/)，这是一款学习 VIM 命令的 CLI 游戏。在这篇简要的指南中，我将解释如何在类 Unix 操作系统中安装 Ncurses 库。

### 在 Linux 中安装 Ncurses 库

Ncurses 在大多数 Linux 发行版的默认仓库中都有。例如，你可以使用以下命令将其安装在基于 Arch 的系统上：

```
$ sudo pacman -S ncurses

```

在RHEL、CentOS 上：

```
$ sudo yum install ncurses-devel

```

在 Fedora 22 和更新版本上：

```
$ sudo dnf install ncurses-devel

```

在 Debian、Ubuntu、Linux Mint 上：

```
$ sudo apt-get install libncurses5-dev libncursesw5-dev

```

默认仓库中的 GNU ncureses 可能有点老了。如果你想要最新的稳定版本，可以从源代码进行编译和安装，如下所示。

从[这里](https://ftp.gnu.org/pub/gnu/ncurses/)下载最新的 ncurses 版本。在写这篇文章时，最新版本是 6.1。

```
$ wget https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.1.tar.gz

```

解压 tar 文件：

```
$ tar xzf ncurses-6.1.tar.gz

```

这将在当前目录中创建一个名为 ncurses-6.1 的文件夹。cd 到该目录：

```
$ cd ncurses-6.1
$ ./configure --prefix=/opt/ncurses

```

最后，使用以下命令进行编译和安装：

```
$ make
$ sudo make install

```

使用命令验证安装：

```
$ ls -la /opt/ncurses

```

就是这样。Ncurses 已经安装在 Linux 发行版上。继续使用 Ncurses 创建漂亮的 TUI。

还会有更多的好东西。敬请关注！

干杯!

---

via: <https://www.ostechnix.com/how-to-install-ncurses-library-in-linux/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


你应该知道关于 Ubuntu 18.04 的一些事

[Ubuntu 18.04 版本](/article-9583-1.html) 已经到来。我可以在各种 Facebook 群组和论坛中看到许多来自 Ubuntu 用户的提问。我还在 Facebook 和 Instagram 上组织了 Q&A 会议，以了解 Ubuntu 用户对 Ubuntu 18.04 的想法。

我试图在这里回答关于 Ubuntu 18.04 的常见问题。如果您有任何疑问，我希望这能帮助您解决疑问。如果您仍有问题，请随时在下面的评论区提问。

### Ubuntu 18.04 中有什么值得期待

![Ubuntu 18.04 Frequently Asked Questions](/data/attachment/album/201805/30/053816snzvlyp5y1w681la.png)

解释一下，这里的一些问答会受到我个人的影响。如果您是一位经验丰富或了解 Ubuntu 的用户，其中一些问题可能对您而言很简单。如果是这样的话，就请忽略这些问题。

#### 我能够在 Ubuntu 18.04 中安装 Unity 吗？

当然能够哦！

Canonical 公司知道有些人喜欢 Unity。这就是为什么它已经在 Universe 软件库（LCTT译者注：社区维护的软件库）中提供了 Unity 7。但这是一个社区维护版，官方并不直接参与开发。

不过我建议是使用默认的 GNOME，除非您真的无法容忍它，再在 [Ubuntu 18.04 上安装 Unity](https://itsfoss.com/use-unity-ubuntu-17-10/)。

#### GNOME 是什么版本？

在这次发行的 Ubuntu 18.04 版本中，GNOME 版本号是 3.28。

#### 我能够安装原装的 GNOME 吗？

当然没问题！

因为存在一些 GNOME 用户可能不喜欢 Ubuntu 18.04 中的 Unity 风格。在 Ubuntu 中的 main（LCTT译者注：官方支持的软件库）和 universe 软件库有安装包可安装，能使您在 [Ubuntu 18.04 中安装原装的 GNOME](https://itsfoss.com/vanilla-gnome-ubuntu/)。

#### GNOME 中的内存泄漏已修复了吗？

已经修复了。[GNOME 3.28 中臭名昭着的内存泄漏](https://feaneron.com/2018/04/20/the-infamous-gnome-shell-memory-leak/) 已经被修复了，并且 [Ubuntu 官方已经在测试这个修复程序](https://community.ubuntu.com/t/help-test-memory-leak-fixes-in-18-04-lts/5251)。

澄清一点，内存泄漏不是由 Ubuntu 系统引起的。它影响了所有使用 GNOME 3.28 的 Linux 发行版。GNOME 3.28.1 发布了一个新的补丁修复内存泄漏问题。

#### Ubuntu 18.04 将会被支持多久？

这是一个长期支持（LTS）版本，与任何 LTS 版本一样，官方会支持五年。这意味着 Ubuntu 18.04 将在 2023 年 4 月之前能获得安全和维护更新。这对于除 Ubuntu Studio 之外的所有基于 Ubuntu 的 Linux 发行版也一样。

#### Ubuntu 18.04 什么时候发布的？

Ubuntu 18.04 LTS 在 4 月 26 日发布。 所有基于 Ubuntu 的 Linux 发行版，如 Kubuntu、Lubuntu、Xubuntu、Budgie、MATE 等都会在同一天发布其 18.04 版本。

不过 [Ubuntu Studio 不会有 18.04 的 LTS 版本](https://www.omgubuntu.co.uk/2018/04/ubuntu-studio-plans-to-reboot)。

#### 是否能从 16.04/17.10 升级到 Ubuntu 18.04？我可以从使用 Unity 的 Ubuntu 16.04 升级到使用 GNOME 的 Ubuntu 18.04 吗？

绝对没问题。当 Ubuntu 18.04 LTS 发布后，您可以很容易的升级到最新版。

如果您使用的是 Ubuntu 17.10，请确保在“软件和更新”->“更新”中，将“有新版本时通知我”设置为“适用任何新版本”。

![Get notified for a new version in Ubuntu](/data/attachment/album/201805/30/053816kppftzz77ff1spcf.jpg)

如果您使用的是 Ubuntu 16.04，请确保在“软件和更新”->“更新”中，将“有新版本时通知我”设置为“适用长期支持版本”。

![Ubuntu 18.04 upgrade from Ubuntu 16.04](/data/attachment/album/201805/30/053817khhdff1i601aalhv.png)

然后您应该能获得有关新版本更新的系统通知。之后，升级到 Ubuntu 18.04 只需要点击几下鼠标而已。

即使 Ubuntu 16.04 使用的是 Unity，但您仍然可以 [升级到使用 GNOME 的 Ubuntu 18.04](https://itsfoss.com/upgrade-ubuntu-version/)。

#### 升级到 Ubuntu 18.04 意味着什么？我会丢失数据吗？

如果您使用的是 Ubuntu 17.10 或 Ubuntu 16.04，系统会提示您可升级到 Ubuntu 18.04。如果您从互联网上下载 1.5 Gb 的数据不成问题，则只需点击几下鼠标，即可在 30 分钟内升级到 Ubuntu 18.04。

您不需要通过 U 盘来重装系统。升级过程完成后，您将可以使用新的 Ubuntu 版本。

通常，您的数据和文档等在升级过程中是安全的。但是，对重要文档进行备份始终是一个好的习惯。

#### 我什么时候能升级到 Ubuntu 18.04？

如果您使用的是 Ubuntu 17.10 并且正确设置（设置方法在之前提到的问题中），那么在 Ubuntu 18.04 发布的几天内应该会通知您升级到 Ubuntu 18.04。为避免 Ubuntu 服务器在发布时的负载量过大，因此不是每个人都会在同一天收到升级提示。

对于 Ubuntu 16.04 用户，可能需要几周时间才能正式收到 Ubuntu 18.04 升级提示。通常，这将在第一次发布 Ubuntu 18.04.1 之后提示。该版本修复了 18.04 中发现的新 bug。

#### 如果我升级到 Ubuntu 18.04，我可以降级到 17.10/16.04？

抱歉，并不行。尽管升级到新版本很容易，但没有降级的选项。如果您想回到 Ubuntu 16.04，只能重新安装。

#### 我能使用 Ubuntu 18.04 在 32 位系统上吗？

可以，但最好不要这样做。

如果您已经在使用 32 位版本的 Ubuntu 16.04 或 17.10，您依旧可以升级到 Ubuntu 18.04。 但是，您找到不到 32 位的 Ubuntu 18.04 ISO 镜像。换句话说，您无法安装 32 位版本的 Ubuntu 18.04。

有一个好消息是，Ubuntu MATE、Lubuntu 等其他官方版本仍然具有其新版本的 32 位 ISO 镜像。

无论如何，如果您使用一个 32 位系统，那么很可能您的计算机硬件性能过低。在这样的电脑上使用轻量级 [Ubuntu MATE](https://ubuntu-mate.org/) 或 [Lubuntu](https://lubuntu.net/) 系统会更好。

#### 我可以在哪下载 Ubuntu 18.04？

18.04 已经发布了，您可以从其网站获得 Ubuntu 18.04 的 ISO 镜像。您既可以直接官网下载，也能用种子下载。其他官方版本将在其官方网站上提供下载。

#### 我应该重新安装 Ubuntu 18.04 还是从 16.04/17.10 升级上来？

如果您有重新安装的机会，建议备份您的数据并重新安装 Ubuntu 18.04。

从现有版本升级到 18.04 是一个方便的选择。不过，就我个人而言，它仍然保留了旧版本的依赖包。重新安装还是比较干净。

#### 对于重新安装来说，我应该安装 Ubuntu 16.04 还是 Ubuntu 18.04？

如果您要在计算机上安装 Ubuntu，请尽量使用 Ubuntu 18.04 而不是 16.04。

他们都是长期支持版本，并被支持很长一段时间。Ubuntu 16.04 会获得维护和安全更新服务直到 2021 年，而 18.04 则会到 2023 年。

不过，我建议您使用 Ubuntu 18.04。任何 LTS 版本都会在 [一段时间内获得硬件更新支持](https://www.ubuntu.com/info/release-end-of-life)（我认为是两年半的时间内）。之后，它只获得维护更新。如果您有更新的硬件，您将在 18.04 获得更好的支持。

此外，许多应用程序开发人员将很快开始关注 Ubuntu 18.04。新创建的 PPA 可能仅在几个月内支持 18.04。所以使用 18.04 比 16.04 更好。

#### 安装打印机-扫描仪驱动程序比使用 CLI 安装会更容易吗？

在打印机方面，我不是专家，所以我的观点是基于我在这方面有限的知识。大多数新打印机都支持 [IPP协议](https://www.pwg.org/ipp/everywhere.html)，因此它们应该在 Ubuntu 18.04 中能够获到很好的支持。 然而对较旧的打印机我则无法保证。

#### Ubuntu 18.04 是否对 Realtek 和其他 WiFi 适配器有更好的支持？

抱歉，没有关于这部分的具体信息。

#### Ubuntu 18.04 的系统要求？

对于默认的 GNOME 版本，最好您应该有 [4 GB 的内存以便正常使用](https://help.ubuntu.com/community/Installation/SystemRequirements)。使用过去 8 年中发布的处理器也可以运行。但任何比这性能更差的硬件建议使用 [轻量级 Linux 发行版](https://itsfoss.com/lightweight-linux-beginners/)，例如 [Lubuntu](https://lubuntu.net/)。

#### 有关 Ubuntu 18.04 的其问题？

如果还有其他疑问，请随时在下方评论区留言。如果您认为应将其他信息添加到列表中，请告诉我。

（LCTT 译注：本文原文写于 Ubuntu 18.04 LTS 发布之前，译文翻译于发布之后，因此对部分内容做了修改。）

---

via: <https://itsfoss.com/ubuntu-18-04-faq/>

作者：[Abhishek Prakash](http://itsfoss.com/author/abhishek/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wyxplus](https://github.com/wyxplus) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


微服务 vs. 整体服务：如何选择

Summary: 任何一种架构都是有利有弊的，而能满足你组织的独特需要的决策才是正确的选择。

任何一种架构都是有利有弊的，而能满足你组织的独特需要的决策才是正确的选择。

>
> 任何一种架构都是有利有弊的，而能满足你组织的独特需要的决策才是正确的选择。
>
>
>

![](/data/attachment/album/201805/30/055802hiuhbwgl09093gu6.jpg)

对于许多初创公司来说，传统的知识认为，从单一整体架构开始，而不是使用微服务。但是，我们还有别的选择吗？

这本新书 —— 《[初创公司的微服务](https://buttercms.com/books/microservices-for-startups/)》，从许多 CIO 们理解的微服务的角度，解释了微服务的优点与缺点。

对于初创公司，虽然不同的 CTO 对此给出的建议是不同的，但是他们都一致认为环境和性能很重要。如果你正考虑你的业务到底是采用微服务还是单一整体架构更好，下面讨论的这些因素正好可以为你提供一些参考。

### 理解范围

首先，我们先来准确定义我们所谓的 “整体服务” 和 “微服务” 是什么。

微服务是一种方法，它开发一个单一的应用程序来作为构成整体服务的小服务，每个小服务都运行在它自己的进程中，并且使用一个轻量级的机制进行通讯，通常是一个 HTTP 资源的 API。这些服务都围绕业务能力来构建，并且可依赖全自动部署机制来独立部署。

一个整体应用程序是按单个的、统一的单元来构建，并且，通常情况下它是基于一个大量的代码来实现的。一般来说，一个整体服务是由三部分组成的：数据库、客户端用户界面（由 HTML 页面和/或运行在浏览器中的 JavaScript 组成）、以及服务器端应用程序。

“系统架构处于一个范围之中”，Zachary Crockett，[Particle](https://www.particle.io/Particle) 的 CTO，在一次访谈中，他说，“在讨论微服务时，人们倾向于关注这个范围的一端：许多极小的应用程序给其它应用程序传递了过多的信息。在另一端，有一个巨大的整体服务做了太多的事情。在任何现实中的系统上，在这两个极端之间有很多合适的面向服务的架构”。

根据你的情况不同，不论是使用整体服务还是微服务都有很多很好的理由。

“我们希望为每个服务使用最好的工具”，Julien Lemoine 说，他是 Algolia 的 CTO。

与很多人的想法正好相反，整体服务并不是过去遗留下来的过时的架构。在某些情况下，整体服务是非常理想的。我采访了 Steven Czerwinski 之后，更好地理解了这一点，他是 [Scaylr](https://www.scalyr.com/) 的工程主管，前谷歌员工。

“尽管我们在谷歌时有使用微服务的一些好的经验，我们现在 [在 Scalyr] 却使用的是整体服务的架构，因为一个整体服务架构意味着我们的工作量更少，我们只有两位工程师。“ 他解释说。（采访他时，Scaylr 正处于早期阶段）

但是，如果你的团队使用微服务的经验很丰富，并且你对你们的发展方向有明确的想法，微服务可能是一个很好的替代者。

Julien Lemoine，[Algolia](https://www.algolia.com/) 的 CTO，在这个问题上，他认为：“我们通常从使用微服务开始，主要目的是我们可以使用不同的技术来构建我们的服务，因为如下的两个主要原因：

* 我们想为每个服务使用最好的工具。我们的搜索 API 是在底层做过高度优化的，而 C++ 是非常适合这项工作的。他说，在任何其它地方都使用 C++ 是一种生产力的浪费，尤其是在构建仪表板方面。
* 我们希望使用最好的人才，而只使用一种技术将极大地限制我们的选择。这就是为什么在公司中有不同语言的原因。

”

如果你的团队已经准备好从一开始就使用微服务，这样你的组织从一开始就可以适应微服务环境的开发节奏。

### 权衡利弊

在你决定那种方法更适合你的组织之前，考虑清楚每种方法的优缺点是非常重要的。

### 整体服务

#### 优点：

* **很少担心横向联系：** 大多数应用程序开发者都担心横向联系，比如，日志、速度限制、以及像审计跟踪和 DoS 防护这样的安全特性。当所有的东西都运行在同一个应用程序中时，通过组件钩子来处理这些关注点就非常容易了。
* **运营开销很少：** 只需要为一个应用程序设置日志、监视、以及测试。一般情况下，部署也相对要简单。
* **性能：** 一个整体的架构可能会有更好的性能，因为共享内存的访问速度要比进程间通讯（IPC）更快。

#### 缺点：

* **紧耦合：** 整体服务的应用程序倾向于紧耦合，并且应用程序是整体进化的，分离特定用途的服务是非常困难的，比如，独立扩展或者代码维护。
* **理解起来很困难：** 当你想查看一个特定的服务或者控制器时，因为依赖、副作用、和其它的不可预见因素，整体架构理解起来更困难。

### 微服务

#### 优点：

* **非常好组织：** 微服务架构一般很好组织它们，因为每个微服务都有一个特定的工作，并且还不用考虑其它组件的工作。
* **解耦合：** 解耦合的服务是能够非常容易地进行重组织和重配置，以服务于不同的应用程序（比如，同时向 Web 客户端和公共 API 提供服务）。它们在一个大的集成系统中，也允许快速、独立分发单个部分。
* **性能：** 根据组织的情况，微服务可以提供更好的性能，因为你可以分离热点服务，并根据其余应用程序的情况来扩展它们。
* **更少的错误：** 微服务允许系统中的不同部分，在维护良好边界的前提下进行并行开发。这样将使连接不该被连接的部分变得更困难，比如，需要连接的那些紧耦合部分。

#### 缺点：

* **跨每个服务的横向联系点：** 由于你构建了一个新的微服务架构，你可能会发现在设计时没有预料到的很多横向联系的问题。这也将导致需要每个横向联系点的独立模块（比如，测试）的开销增加，或者在其它服务层面因封装横向联系点，所导致的所有流量都需要路由。最终，即便是整体服务架构也倾向于通过横向联系点的外部服务层来路由流量，但是，如果使用整体架构，在项目更加成熟之前，也不过只是推迟了工作成本。
* **更高的运营开销：** 微服务在它所属的虚拟机或容器上部署非常频繁，导致虚拟机争用激增。这些任务都是使用容器管理工具进行频繁的自动化部署的。

### 决策时刻

当你了解了每种方法的利弊之后，如何在你的初创公司使用这些信息？通过与这些 CTO 们的访谈，这里有三个问题可以指导你的决策过程：

**你是在熟悉的领域吗？**

如果你的团队有以前的一些领域的经验（比如，电子商务）和了解你的客户需求，那么分割成微服务是低风险的。如果你从未做过这些，从另一个角度说，整体服务或许是一个更安全的选择。

**你的团队做好准备了吗？**

你的团队有使用微服务的经验吗？如果明年，你的团队扩充到现在的四倍，将为微服务提供更好的环境？评估团队大小对项目的成功是非常重要的。

**你的基础设施怎么样？**

实施微服务，你需要基于云的基础设施。

David Strauss，[Pantheon](https://pantheon.io/) 的 CTO，他解释说："[以前]，你使用整体服务是因为，你希望部署在一个数据库上。每个单个的微服务都需要配置数据库服务器，然后，扩展它将是一个很重大的任务。只有大的、技术力量雄厚的组织才能做到。现在，使用像谷歌云和亚马逊 AWS 这样的云服务，为部署一个小的东西而不需要为它们中的每个都提供持久存储，对于这种需求你有很多的选择。“

### 评估业务风险

技术力量雄厚的初创公司为追求较高的目标，可以考虑使用微服务。但是微服务可能会带来业务风险。Strauss 解释说，“许多团队一开始就过度构建他们的项目。每个人都认为，他们的公司会成为下一个 ‘独角兽’，因此，他们使用微服务构建任何一个东西，或者一些其它的高扩展性的基础设施。但是这通常是一种错误的做法”。Strauss 说，在那种情况下，他们认为需要扩大规模的领域往往并不是一开始真正需要扩展的领域，最后的结果是浪费了时间和努力。

### 态势感知

最终，环境是关键。以下是一些来自 CTO 们的提示：

#### 什么时候使用整体服务

* **你的团队还在创建阶段：** 你的团队很小 —— 也就是说，有 2 到 5 位成员 —— 还无法应对大范围、高成本的微服务架构。
* **你正在构建的是一个未经证实的产品或者概念验证：** 如果你将一个全新的产品推向市场，随着时间的推移，它有可能会成功，而对于一个快速迭代的产品，整体架构是最合适的。这个提示也同样适用于概念验证，你的目标是尽可能快地学习，即便最终你可能会放弃它。
* **你没有使用微服务的经验：** 除非你有合理的理由证明早期学习阶段的风险可控，否则，一个整体的架构更适用于一个没有经验的团队。

#### 什么时候开始使用微服务

* **你需要快速、独立的分发服务：** 微服务允许在一个大的集成系统中快速、独立分发单个部分。请注意，根据你的团队规模，获取与整体服务的比较优势，可能需要一些时间。
* **你的平台中的某些部分需要更高效：** 如果你的业务要求集中处理 PB 级别的日志卷，你可能需要使用一个像 C++ 这样的更高效的语言来构建这个服务，尽管你的用户仪表板或许还是用 [Ruby on Rails](http://rubyonrails.org/) 构建的。
* **计划扩展你的团队：** 使用微服务，将让你的团队从一开始就开发独立的小服务，而服务边界独立的团队更易于按需扩展。

要决定整体服务还是微服务更适合你的组织，要坦诚并正确认识自己的环境和能力。这将有助于你找到业务成长的最佳路径。

### 关于作者

jakelumetta - Jake 是 ButterCMS 的 CEO，它是一个 [API-first CMS](https://buttercms.com/)。他喜欢搅动出黄油双峰，以及构建让开发者工作更舒适的工具，喜欢他的更多内容，请在 Twitter 上关注 [@ButterCMS](https://twitter.com/ButterCMS)，订阅 [他的博客](https://buttercms.com/blog/)。[关于他的更多信息](https://opensource.com/users/jakelumetta)……

---

via: <https://opensource.com/article/18/1/how-choose-between-monolith-microservices>

作者：[jakelumetta](https://opensource.com/users/jakelumetta)  译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


如何在无响应的 Linux 系统中杀掉内存消耗最大的进程

![](/data/attachment/album/201805/31/092105lkgrxeb8ytxxat8r.png)

作为一名博客作者，我收藏了很多博客、网站和论坛用来寻找 Linux 和 Unix 相关的内容。有时候，我在浏览器中开启了非常多的标签页，导致操作系统会无响应好几分钟。我不能移动我的鼠标，也不能杀掉一个进程或关闭任何开启的标签页。在这种情况下，我别无选择，只能强制重启系统。当然我也用了 **OneTab** （LCTT 译注：OneTab 是一个 Chrome 的 Extension，可以将标签页转化成一个列表保存。）和 **Greate Suspender** （LCTT 译注：Great Suspender 是一个 Chrome 的 Extension， 可以自动冻结标签页）这样浏览器拓展，但它们在这里也起不到太大的作用。 我经常耗尽我的内存。而这就是 **Early OOM** 起作用的时候了。在情况严重时，它会杀掉一个未响应系统中的内存消耗最大的进程。Early OOM 每秒会检测可用内存和空余交换区 10 次，一旦两者都低于 10%，它就会把最大的进程杀死。

### 为什么用 Early OOM？为什么不用系统内置的 OOM killer？

在继续讨论下去之前，我想先简短的介绍下 OOM killer，也就是 **O**ut **O**f **M**emory killer。OOM killer 是一个由内核在可用内存非常低的时候使用的进程。它的主要任务是不断的杀死进程，直到释放出足够的内存，使内核正在运行的其它进程能顺利运行。OOM killer 会找到系统中最不重要并且能释放出最多内存的进程，然后杀掉他们。在 `/proc` 目录下的 `pid` 目录中，我们可以看到每个进程的 `oom_score`。

示例：

```
$ cat /proc/10299/oom_score
1

```

一个进程的 `oom_score` 的值越高，这个进程越有可能在系统内存耗尽的时候被 OOM killer 杀死。

Early OOM 的开发者表示，相对于内置的 OOM killer，Early OOM 有一个很大的优点。就像我之前说的那样，OOM killer 会杀掉 `oom_score` 最高的进程，而这也导致 Chrome 浏览器总是会成为第一个被杀死的进程。为了避免这种情况发生，Early OOM 使用 `/proc/*/status` 而不是 `echo f > /proc/sysrq-trigger`（LCTT 译注：这条命令会调用 OOM killer 杀死进程）。开发者还表示，手动触发 OOM killer 在最新版本的 Linux 内核中很可能不会起作用。

### 安装 Early OOM

Early OOM 在 AUR（Arch User Repository）中可以找到，所以你可以在 Arch 和它的衍生版本中使用任何 AUR 工具安装它。

使用 [Pacaur](https://www.ostechnix.com/install-pacaur-arch-linux/)：

```
pacaur -S earlyoom

```

使用 [Packer](https://www.ostechnix.com/install-packer-arch-linux-2/)：

```
packer -S earlyoom

```

使用 [Yaourt](https://www.ostechnix.com/install-yaourt-arch-linux/)：

```
yaourt -S earlyoom

```

启用并启动 Early OOM 守护进程：

```
sudo systemctl enable earlyoom
sudo systemctl start earlyoom

```

在其它的 Linux 发行版中，可以按如下方法编译安装它：

```
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
sudo make install

```

### Early OOM - 杀掉无响应 Linux 系统中的最大的进程

运行如下命令启动 Early OOM：

```
earlyoom

```

如果是通过编译源代码安装的， 运行如下命令启动 Early OOM：

```
./earlyoom

```

示例输出：

```
earlyoom 0.12
mem total: 3863 MiB, min: 386 MiB (10 %)
swap total: 2047 MiB, min: 204 MiB (10 %)
mem avail: 1770 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1772 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1772 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1771 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1784 MiB (46 %), swap free: 2047 MiB (99 %)
[...]

```

就像你在上面的输出中可以看到的，Early OOM 将会显示你有多少内存和交换区，以及有多少可用的内存和交换区。记住它会一直保持运行，直到你按下 `CTRL+C`。

如果可用的内存和交换区大小都低于 10%，Early OOM 将会自动杀死最大的进程，直到系统有足够的内存可以流畅的运行。你也可以根据你的需求配置最小百分比值。

设置最小的可用内存百分比，运行：

```
earlyoom -m <PERCENT_HERE>

```

设置最小可用交换区百分比, 运行：

```
earlyoom -s <PERCENT_HERE>

```

在帮助部分，可以看到更多详细信息：

```
$ earlyoom -h
earlyoom 0.12
Usage: earlyoom [OPTION]...

 -m PERCENT set available memory minimum to PERCENT of total (default 10 %)
 -s PERCENT set free swap minimum to PERCENT of total (default 10 %)
 -M SIZE set available memory minimum to SIZE KiB
 -S SIZE set free swap minimum to SIZE KiB
 -k use kernel oom killer instead of own user-space implementation
 -i user-space oom killer should ignore positive oom_score_adj values
 -d enable debugging messages
 -v print version information and exit
 -r INTERVAL memory report interval in seconds (default 1), set to 0 to
 disable completely
 -p set niceness of earlyoom to -20 and oom_score_adj to -1000
 -h this help text

```

现在，你再也不用担心内存消耗最高的进程了。希望这能给你帮助。更多的好内容将会到来，敬请期待。

谢谢！

---

via: <https://www.ostechnix.com/kill-largest-process-unresponsive-linux-system/>

作者：[Aditya Goturu](https://www.ostechnix.com) 译者：[cizezsy](https://github.com/cizezsy) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


/dev/[u]random：对熵的解释

Summary: 当谈到 /dev/random 和 /dev/urandom 的主题时，你总是会听到这个词：“熵（Entropy）”。

![](/data/attachment/album/201805/31/100548t7ueq7ssu8ss78pp.jpg)

### 熵

当谈到 `/dev/random` 和 `/dev/urandom` 的主题时，你总是会听到这个词：“<ruby> 熵 <rt>  Entropy </rt></ruby>”。每个人对此似乎都有自己的比喻。那为我呢？我喜欢将熵视为“随机果汁”。它是果汁，随机数需要它变得更随机。

如果你曾经生成过 SSL 证书或 GPG 密钥，那么可能已经看到过像下面这样的内容：

```
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
++++++++++..+++++.+++++++++++++++.++++++++++...+++++++++++++++...++++++
+++++++++++++++++++++++++++++.+++++..+++++.+++++.+++++++++++++++++++++++++>.
++++++++++>+++++...........................................................+++++
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 290 more bytes)

```

通过在键盘上打字并移动鼠标，你可以帮助生成熵或随机果汁。

你可能会问自己……为什么我需要熵？以及为什么它对于随机数真的变得随机如此重要？那么，假设我们的熵的来源仅限于键盘、鼠标和磁盘 IO 的数据。但是我们的系统是一个服务器，所以我知道没有鼠标和键盘输入。这意味着唯一的因素是你的 IO。如果它是一个单独的、几乎不使用的磁盘，你将拥有较低的熵。这意味着你的系统随机的能力很弱。换句话说，我可以玩概率游戏，并大幅减少破解 ssh 密钥或者解密你认为是加密会话的时间。

好的，但这是很难实现的对吧？不，实际上并非如此。看看这个 [Debian OpenSSH 漏洞](http://jhurani.com/linux/2017/11/01/%22https://jblevins.org/log/ssh-vulnkey%22)。这个特定的问题是由于某人删除了一些负责添加熵的代码引起的。有传言说，他们因为它导致 valgrind 发出警告而删除了它。然而，在这样做的时候，随机数现在少了很多随机性。事实上，熵少了很多，因此暴力破解变成了一个可行的攻击向量。

希望到现在为止，我们理解了熵对安全性的重要性。无论你是否意识到你正在使用它。

### /dev/random 和 /dev/urandom

`/dev/urandom` 是一个伪随机数生成器，缺乏熵它也**不会**停止。

`/dev/random` 是一个真随机数生成器，它会在缺乏熵的时候停止。

大多数情况下，如果我们正在处理实际的事情，并且它不包含你的核心信息，那么 `/dev/urandom` 是正确的选择。否则，如果就使用 `/dev/random`，那么当系统的熵耗尽时，你的程序就会变得有趣。无论它直接失败，或只是挂起——直到它获得足够的熵，这取决于你编写的程序。

### 检查熵

那么，你有多少熵？

```
[root@testbox test]# cat /proc/sys/kernel/random/poolsize
4096
[root@testbox test]# cat /proc/sys/kernel/random/entropy_avail
2975

```

`/proc/sys/kernel/random/poolsize`，说明熵池的大小（以位为单位）。例如：在停止抽水之前我们应该储存多少随机果汁。`/proc/sys/kernel/random/entropy_avail` 是当前池中随机果汁的数量（以位为单位）。

### 我们如何影响这个数字？

这个数字可以像我们使用它一样耗尽。我可以想出的最简单的例子是将 `/dev/random` 定向到 `/dev/null` 中：

```
[root@testbox test]# cat /dev/random > /dev/null &
[1] 19058
[root@testbox test]# cat /proc/sys/kernel/random/entropy_avail
0
[root@testbox test]# cat /proc/sys/kernel/random/entropy_avail
1

```

影响这个最简单的方法是运行 [Haveged](http://www.issihosts.com/haveged/)。Haveged 是一个守护进程，它使用处理器的“抖动”将熵添加到系统熵池中。安装和基本设置非常简单。

```
[root@b08s02ur ~]# systemctl enable haveged
Created symlink from /etc/systemd/system/multi-user.target.wants/haveged.service to /usr/lib/systemd/system/haveged.service.
[root@b08s02ur ~]# systemctl start haveged

```

在流量相对中等的机器上：

```
[root@testbox ~]# pv /dev/random > /dev/null
  40 B 0:00:15 [   0 B/s] [                    <=>                                                                                ]
  52 B 0:00:23 [   0 B/s] [                           <=>                                                                                ]
  58 B 0:00:25 [5.92 B/s] [                              <=>                                                                                ]
  64 B 0:00:30 [6.03 B/s] [                                  <=>                                                                                ]
^C
[root@testbox ~]# systemctl start haveged
[root@testbox ~]# pv /dev/random > /dev/null
7.12MiB 0:00:05 [1.43MiB/s] [                <=>                                                                                ]
15.7MiB 0:00:11 [1.44MiB/s] [                                    <=>                                                                                ]
27.2MiB 0:00:19 [1.46MiB/s] [                                                               <=>                                                                                ]
  43MiB 0:00:30 [1.47MiB/s] [                                                                                <=>                                                                    ]
^C

```

使用 `pv` 我们可以看到我们通过管道传递了多少数据。正如你所看到的，在运行 `haveged` 之前，我们是 2.1 位/秒（B/s）。而在开始运行 `haveged` 之后，加入处理器的抖动到我们的熵池中，我们得到大约 1.5MiB/秒。

---

via: <http://jhurani.com/linux/2017/11/01/entropy-explained.html>

作者：[James J](https://jblevins.org/log/ssh-vulnkey) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


4 个现在就该去装的 Firefox 扩展

Summary: 合适的扩展能极大地增强你的浏览器功能，但是仔细的选择也是很重要的。

合适的扩展能极大地增强你的浏览器功能，但是仔细的选择也是很重要的。

>
> 合适的扩展能极大地增强你的浏览器功能，但是仔细的选择也是很重要的。
>
>
>

![](/data/attachment/album/201805/31/103037e6tq4oqog7tt74g1.jpg)

正如我在关于 Firefox 扩展的[原创文章](https://opensource.com/article/18/1/top-5-firefox-extensions)中提到的，web 浏览器已成为许多用户计算机体验的关键组件。现代浏览器已经发展成为功能强大且可扩展的平台，扩展可以添加或修改其功能。Firefox 的扩展是使用 WebExtensions API（一种跨浏览器开发系统）构建的。

在第一篇文章中，我问读者：“你应该安装哪些扩展？” 重申一下，这一决定主要取决于你如何使用浏览器，你对隐私的看法，你对扩展程序开发人员的信任程度以及其他个人偏好。自文章发表以来，我推荐的一个扩展（Xmarks）已经停止维护。另外，该文章收到了大量的反馈，在这篇更新中，这些反馈已经被考虑到。

我想再次指出，浏览器扩展通常需要能够阅读和（或）更改你访问的网页上的所有内容。你应该仔细考虑这一点。如果扩展程序修改了你访问的所有网页的访问权限，那么它可能成为键盘记录程序、拦截信用卡信息、在线跟踪、插入广告以及执行各种其他恶意活动。这并不意味着每个扩展程序都会暗中执行这些操作，但在安装任何扩展程序之前，你应该仔细考虑安装源，涉及的权限，风险配置文件以及其他因素。请记住，你可以使用配置文件来管理扩展如何影响你的攻击面 —— 例如，使用没有扩展的专用配置文件来执行网上银行等任务。

考虑到这一点，这里有你可能想要考虑的四个开源 Firefox 扩展。

### uBlock Origin

![ublock origin ad blocker screenshot](/data/attachment/album/201805/31/103048tgmwn61vnmevzzvw.png "ublock origin ad blocker screenshot")

我的第一个建议保持不变。[uBlock Origin](https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/) 是一款快速、低内存消耗、广泛的拦截器，它不仅可以拦截广告，而且还可以执行你自己的内容过滤。 uBlock Origin 的默认行为是使用多个预定义的过滤器列表来拦截广告、跟踪器和恶意软件站点。它允许你任意添加列表和规则，甚至可以锁定到默认拒绝模式。尽管它很强大，但它已被证明是高效和高性能的。它将继续定期更新，并且是该功能的最佳选择之一。

### Privacy Badger

![privacy badger ad blocker](/data/attachment/album/201805/31/103053z81zl3z9e3gazbe4.png "privacy badger ad blocker screenshot")

我的第二个建议也保持不变。如果说有什么区别的话，那就是自从我上一篇文章发表以来，隐私问题更被关注了，这使得这个扩展成为一个简单的建议。顾名思义，[Privacy Badger](https://www.eff.org/privacybadger) 是一个专注于隐私的扩展，可以拦截广告和其他第三方跟踪器。这是电子前哨基金会基金会（EFF）的一个项目，他们说：

>
> Privacy Badger 的诞生是我们希望能够推荐一个单独的扩展，它可以自动分析和拦截任何违反用户同意原则的追踪器或广告；在用户没有任何设置、有关知识或配置的情况下，它可以很好地运行；它是由一个明确为其用户而不是为广告商工作的组织所产生的；它使用了算法的方法来决定什么被跟踪，什么没有被跟踪。”
>
>
>

为什么 Privacy Badger 会出现在这个列表上，它的功能与上一个扩展看起来很类似？因为一些原因：首先，它从根本上工作原理与 uBlock Origin 不同。其次，深度防御的实践是一项合理的策略。说到深度防御，EFF 还维护着 [HTTPS Everywhere](https://www.eff.org/https-everywhere) 扩展，它自动确保 https 用于许多主流网站。当你安装 Privacy Badger 时，你也可以考虑使用 HTTPS Everywhere。

如果你开始认为这篇文章只是对上一篇文章的重新讨论，那么以下是我的建议分歧。

### Bitwarden

![Bitwarden](/data/attachment/album/201805/31/103054q6t8njyg6wgmmmxk.png "Bitwarden")

在上一篇文章中推荐 LastPass 时，我提到这可能是一个有争议的选择。这无疑属实。无论你是否应该使用密码管理器 —— 如果你使用，那么是否应该选择带有浏览器插件的密码管理器 —— 这是一个备受争议的话题，答案很大程度上取决于你的个人风险状况。我认为大多数普通的计算机用户应该使用一个，因为它比最常见的选择要好得多：在任何地方都使用相同的弱密码！我仍然相信这一点。

[Bitwarden](https://bitwarden.com/) 自从我上次点评以后确实更成熟了。像 LastPass 一样，它对用户友好，支持双因素身份验证，并且相当安全。与 LastPass 不同的是，它是[开源的](https://github.com/bitwarden)。它可以使用或不使用浏览器插件，并支持从其他解决方案（包括 LastPass）导入。它的核心功能完全免费，它还有一个 10 美元/年的高级版本。

### Vimium-FF

![Vimium](/data/attachment/album/201805/31/103056ucganu5h52jjc11m.png "Vimium")

[Vimium](https://addons.mozilla.org/en-US/firefox/addon/vimium-ff/) 是另一个开源的扩展，它为 Firefox 键盘快捷键提供了类似 Vim 一样的导航和控制，其称之为“黑客的浏览器”。对于 `Ctrl+x`、 `Meta+x` 和 `Alt+x`，分别对应 `<c-x>`、`<m-x>` 和 `<a-x>`，默认值可以轻松定制。一旦你安装了 Vimium，你可以随时键入 `?` 来查看键盘绑定列表。请注意，如果你更喜欢 Emacs，那么也有一些针对这些键绑定的扩展。无论哪种方式，我认为键盘快捷键是未充分利用的生产力推动力。

### 额外福利: Grammarly

不是每个人都有幸在 Opensource.com 上撰写专栏 —— 尽管你应该认真考虑为这个网站撰写文章；如果你有问题，有兴趣，或者想要一个导师，伸出手，让我们聊聊吧。但是，即使没有专栏撰写，正确的语法在各种各样的情况下都是有益的。试一下 [Grammarly](https://www.grammarly.com/)。不幸的是，这个扩展不是开源的，但它确实可以确保你输入的所有东西都是清晰的 、有效的并且没有错误。它通过扫描你文本中的常见的和复杂的语法错误来实现这一点，涵盖了从主谓一致到文章使用，到修饰词的放置这些所有内容。它的基本功能是免费的，它有一个高级版本，每月收取额外的费用。我在这篇文章中使用了它，它发现了许多我的校对没有发现的错误。

再次说明，Grammarly 是这个列表中包含的唯一不是开源的扩展，因此如果你知道类似的高质量开源替代品，请在评论中告诉我们。

这些扩展是我发现有用并推荐给其他人的扩展。请在评论中告诉我你对更新建议的看法。

---

via: <https://opensource.com/article/18/5/firefox-extensions>

作者：[Jeremy Garcia](https://opensource.com/users/jeremy-garcia) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


编写有趣且有价值的 Systemd 服务

Summary: 每次开机之后需要启动服务器，每次关机之前需要安全地关闭服务进程，十分繁琐和麻烦。

![](/data/attachment/album/201805/31/231539hsg1ybtwt09sb430.png)

让我们假设你希望搭建一个游戏服务器，运行 [Minetest](https://www.minetest.net/) 这款非常酷、开源的，以采集 & 合成为主题的沙盒游戏。你希望将游戏运行在位于客厅的服务器中，以便搭建完成后可供你的学校或朋友使用。你知道内核邮件列表的管理就不过就是如此，那么对你来说也是足够的。

但你很快发现每次开机之后需要启动服务进程，每次关机之前需要安全地关闭服务器，十分繁琐和麻烦。

最初，你可能用守护进程的方式运行服务器：

```
minetest --server &

```

记住进程 PID 以便后续使用。

接着，你还需要通过邮件或短信的方式将服务器已经启动的信息告知你的朋友。然后你就可以开始游戏了。

转眼之间，已经凌晨三点，今天的战斗即将告一段落。但在你关闭主机、睡个好觉之前，还需要做一些操作。首先，你需要通知其它玩家服务器即将关闭，找到记录我们之前提到的 PID 的纸条，然后友好地关闭 Minetest 服务进程。

```
kill -2 <PID>

```

这是因为直接关闭主机电源很可能导致文件损坏。下一步也是最后一步，关闭主机电源。

一定有方法能让事情变得更简单。

### 让 Systemd 服务拯救你

让我们从构建一个普通用户可以（手动）运行的 systemd 服务开始，然后再逐步增加内容。

不需要管理员权限即可运行的服务位于 `~/.config/systemd/user/`，故首先需要创建这个目录：

```
cd
mkdir -p ~/.config/systemd/user/

```

有很多类型的 systemd 单元 (曾经叫做 systemd 脚本)，包括“计时器”和“路径”等，但我们这里关注的是“服务”类型。在 `~/.config/systemd/user/` 目录中创建 `minetest.service` 文件，使用文本编辑器打开并输入如下内容：

```
# minetest.service

[Unit]
Description= Minetest server
Documentation= https://wiki.minetest.net/Main_Page

[Service]
Type= simple
ExecStart= /usr/games/minetest --server

```

可以看到该单元中包含不同的段，其中 `[Unit]` 段主要为用户提供信息，给出该单元的描述及如何获得更多相关文档。

脚本核心位于 `[Service]` 段，首先使用 `Type` 指令确定服务类型。服务[有多种类型](http://man7.org/linux/man-pages/man5/systemd.service.5.html)，下面给出两个示例。如果你运行的进程设置环境变量、调用另外一个进程（主进程）、退出运行，那么你应该使用的服务类型为 `forking`。如果你希望在你的单元对应进程结束运行前阻断其他单元运行，那么你应该使用的服务类型为 `oneshot`。

但 Minetest 服务器的情形与上面两种都不同，你希望启动服务器并使其在后台持续运行；这种情况下应该使用 `simple` 类型。

下面来看 `ExecStart` 指令，它给出 systemd 需要运行的程序。在本例中，你希望在后台运行 `minetest` 服务器。如上所示，你可以在可执行程序后面添加参数，但不能将一系列 Bash 命令通过管道连接起来。下面给出的例子无法工作：

```
ExecStart: lsmod | grep nvidia > videodrive.txt

```

如果你需要将 Bash 命令通过管道连接起来，可以将其封装到一个脚本中，然后运行该脚本。

还需要注意一点，systemd 要求你给出程序的完整路径。故如果你想使用 `simple` 类型运行类似 `ls` 的命令，你需要使用 `ExecStart= /bin/ls`。

另外还有 `ExecStop` 指令用于定制服务终止的方式。我们会在第二部分讨论这个指令，但你要了解，如果你没有指定 `ExecStop`，systemd 会帮你尽可能友好地终止进程。

`systemd.directives` 的帮助页中包含完整指令列表，另外你可以在该[网站](http://man7.org/linux/man-pages/man7/systemd.directives.7.html)上找到同样的列表，点击即可查看每个指令的具体信息。

虽然只有 6 行，但你的 `minetest.service` 已经是一个有完整功能的 systemd 单元。执行如下命令启动服务：

```
systemd --user start minetest

```

执行如下命令终止服务：

```
systemd --user stop minetest

```

选项 `--user` 告知 systemd 在你的本地目录中检索服务并用你的用户权限执行服务。

我们的服务器管理故事到此完成了第一部分。在第二部分，我们将在启动和终止服务的基础上，学习如何给用户发邮件、告知用户服务器的可用性。敬请期待。

可以通过 Linux 基金会和 edX 的免费课程 “[Linux 入门](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)”学习更多 Linux 知识。

---

via: <https://www.linux.com/blog/learn/intro-to-linux/2018/5/writing-systemd-services-fun-and-profit>

作者：[Paul Brown](https://www.linux.com/users/bro66) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


在 Linux 中如何归档文件和目录

![](/data/attachment/album/201806/01/100218qf1bmyu9bv4mlyzx.png)

在我们之前的教程中，我们讨论了如何[使用 gzip 和 bzip2 压缩和解压缩文件](https://www.ostechnix.com/how-to-compress-and-decompress-files-in-linux/)。在本教程中，我们将学习如何在 Linux 归档文件。归档和压缩有什么不同吗？你们中的一些人可能经常认为这些术语有相同的含义。但是，这两者完全不同。归档是将多个文件和目录（相同或不同大小）组合成一个文件的过程。另一方面，压缩是减小文件或目录大小的过程。归档通常用作系统备份的一部分，或者将数据从一个系统移至另一个系统时。希望你了解归档和压缩之间的区别。现在，让我们进入主题。

### 归档文件和目录

归档文件和目录最常见的程序是：

1. tar
2. zip

这是一个很大的话题，所以，我将分两部分发表这篇文章。在第一部分中，我们将看到如何使用 tar 命令来归档文件和目录。

### 使用 tar 命令归档文件和目录

**Tar** 是一个 Unix 命令，代表 **T**ape **A**rchive（磁带归档）。它用于将多个文件（相同或不同大小）组合或存储到一个文件中。在 tar 实用程序中有 4 种主要的操作模式。

1. `c` – 从文件或目录中建立归档
2. `x` – 提取归档
3. `r` – 将文件追加到归档
4. `t` – 列出归档的内容

有关完整的模式列表，参阅 man 手册页。

#### 创建一个新的归档

为了本指南，我将使用名为 `ostechnix` 的文件夹，其中包含三种不同类型的文件。

```
$ ls ostechnix/
file.odt image.png song.mp3

```

现在，让我们为 `ostechnix` 目录创建一个新的 tar 归档。

```
$ tar cf ostechnix.tar ostechnix/

```

这里，`c` 标志指的是创建新的归档，`f` 是指定归档文件。

同样，对当前工作目录中的一组文件创建归档文件，使用以下命令：

```
$ tar cf archive.tar file1 file2 file 3

```

#### 提取归档

要在当前目录中提取归档文件，只需执行以下操作：

```
$ tar xf ostechnix.tar

```

我们还可以使用 `C` 标志（大写字母 C）将归档提取到不同的目录中。例如，以下命令将归档文件提取到 `Downloads` 目录中。

```
$ tar xf ostechnix.tar -C Downloads/

```

或者，转到 `Downloads` 文件夹并像下面一样提取其中的归档。

```
$ cd Downloads/
$ tar xf ../ostechnix.tar

```

有时，你可能想要提取特定类型的文件。例如，以下命令提取 “.png” 类型的文件。

```
$ tar xf ostechnix.tar --wildcards "*.png"

```

#### 创建 gzip 和 bzip 格式的压缩归档

默认情况下，tar 创建归档文件以 `.tar` 结尾。另外，`tar` 命令可以与压缩实用程序 `gzip` 和 `bzip` 结合使用。文件结尾以 `.tar` 为扩展名使用普通 tar 来归档文件，文件以 `tar.gz` 或 `.tgz` 结尾使用 `gzip` 归档并压缩文件，文件以 `tar.bz2` 或 `.tbz` 结尾使用 `bzip` 归档并压缩。

首先，让我们来创建一个 gzip 归档：

```
$ tar czf ostechnix.tar.gz ostechnix/

```

或者：

```
$ tar czf ostechnix.tgz ostechnix/

```

这里，我们使用 `z` 标志来使用 gzip 压缩方法压缩归档文件。

你可以使用 `v` 标志在创建归档时查看进度。

```
$ tar czvf ostechnix.tar.gz ostechnix/
ostechnix/
ostechnix/file.odt
ostechnix/image.png
ostechnix/song.mp3

```

这里，`v` 指显示进度。

从一个文件列表创建 gzip 归档文件：

```
$ tar czf archive.tgz file1 file2 file3

```

要提取当前目录中的 gzip 归档文件，使用：

```
$ tar xzf ostechnix.tgz

```

要提取到其他文件夹，使用 `-C` 标志：

```
$ tar xzf ostechnix.tgz -C Downloads/

```

现在，让我们创建 **bzip 归档**。为此，请使用下面的 `j` 标志。

创建一个目录的归档：

```
$ tar cjf ostechnix.tar.bz2 ostechnix/

```

或

```
$ tar cjf ostechnix.tbz ostechnix/

```

从一个列表文件中创建归档：

```
$ tar cjf archive.tar.bz2 file1 file2 file3

```

或

```
$ tar cjf archive.tbz file1 file2 file3

```

为了显示进度，使用 `v` 标志。

现在，在当前目录下，让我们提取一个 bzip 归档。这样做：

```
$ tar xjf ostechnix.tar.bz2

```

或者，提取归档文件到其他目录：

```
$ tar xjf ostechnix.tar.bz2 -C Downloads

```

#### 一次创建多个目录和/或文件的归档

这是 `tar` 命令的另一个最酷的功能。要一次创建多个目录或文件的 gzip 归档文件，使用以下文件：

```
$ tar czvf ostechnix.tgz Downloads/ Documents/ ostechnix/file.odt

```

上述命令创建 `Downloads`、 `Documents` 目录和 `ostechnix` 目录下的 `file.odt` 文件的归档，并将归档保存在当前工作目录中。

#### 在创建归档时跳过目录和/或文件

这在备份数据时非常有用。你可以在备份中排除不重要的文件或目录，这是 `–exclude` 选项所能帮助的。例如你想要创建 `/home` 目录的归档，但不希望包括 `Downloads`、 `Documents`、 `Pictures`、 `Music` 这些目录。

这是我们的做法：

```
$ tar czvf ostechnix.tgz /home/sk --exclude=/home/sk/Downloads --exclude=/home/sk/Documents --exclude=/home/sk/Pictures --exclude=/home/sk/Music

```

上述命令将对我的 `$HOME` 目录创建一个 gzip 归档，其中不包括 `Downloads`、`Documents`、`Pictures` 和 `Music` 目录。要创建 bzip 归档，将 `z` 替换为 `j`，并在上例中使用扩展名 `.bz2`。

#### 列出归档文件但不提取它们

要列出归档文件的内容，我们使用 `t` 标志。

```
$ tar tf ostechnix.tar
ostechnix/
ostechnix/file.odt
ostechnix/image.png
ostechnix/song.mp3

```

要查看详细输出，使用 `v` 标志。

```
$ tar tvf ostechnix.tar
drwxr-xr-x sk/users 0 2018-03-26 19:52 ostechnix/
-rw-r--r-- sk/users 9942 2018-03-24 13:49 ostechnix/file.odt
-rw-r--r-- sk/users 36013 2015-09-30 11:52 ostechnix/image.png
-rw-r--r-- sk/users 112383 2018-02-22 14:35 ostechnix/song.mp3

```

#### 追加文件到归档

文件或目录可以使用 `r` 标志添加/更新到现有的归档。看看下面的命令：

```
$ tar rf ostechnix.tar ostechnix/ sk/ example.txt

```

上面的命令会将名为 `sk` 的目录和名为 `exmple.txt` 添加到 `ostechnix.tar` 归档文件中。

你可以使用以下命令验证文件是否已添加：

```
$ tar tvf ostechnix.tar
drwxr-xr-x sk/users 0 2018-03-26 19:52 ostechnix/
-rw-r--r-- sk/users 9942 2018-03-24 13:49 ostechnix/file.odt
-rw-r--r-- sk/users 36013 2015-09-30 11:52 ostechnix/image.png
-rw-r--r-- sk/users 112383 2018-02-22 14:35 ostechnix/song.mp3
drwxr-xr-x sk/users 0 2018-03-26 19:52 sk/
-rw-r--r-- sk/users 0 2018-03-26 19:39 sk/linux.txt
-rw-r--r-- sk/users 0 2018-03-26 19:56 example.txt

```

### TL;DR

创建 tar 归档：

* **普通 tar 归档：** `tar -cf archive.tar file1 file2 file3`
* **Gzip tar 归档：** `tar -czf archive.tgz file1 file2 file3`
* **Bzip tar 归档：** `tar -cjf archive.tbz file1 file2 file3`

提取 tar 归档：

* **普通 tar 归档：** `tar -xf archive.tar`
* **Gzip tar 归档：** `tar -xzf archive.tgz`
* **Bzip tar 归档：** `tar -xjf archive.tbz`

我们只介绍了 `tar` 命令的基本用法，这些对于开始使用 `tar` 命令足够了。但是，如果你想了解更多详细信息，参阅 man 手册页。

```
$ man tar

```

好吧，这就是全部了。在下一部分中，我们将看到如何使用 Zip 实用程序来归档文件和目录。

干杯！

---

via: <https://www.ostechnix.com/how-to-archive-files-and-directories-in-linux-part-1/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Orbital Apps：新一代 Linux 程序

Summary: Orbital Apps 或 ORB（Open Runnable Bundle）apps（开放可运行程序包），一个自由的、跨平台的开源程序集合

![](/data/attachment/album/201806/01/100858lobqssaekkxqepeo.jpg)

今天，我们要了解 **Orbital Apps** 或 **ORB**（**O**pen **R**unnable **B**undle）**apps**（开放可运行程序包），一个自由的、跨平台的开源程序集合。所有 ORB 程序都是可移动的。你可以将它们安装在你的 Linux 系统或 USB 驱动器上，以便你可以在任何系统上使用相同的程序。它们不需要 root 权限，并且没有依赖关系。所有必需的依赖关系都包含在程序中。只需将 ORB 程序复制到 USB 驱动器并将其插入到任何 Linux 系统中就立即开始使用它们。所有设置和配置以及程序的数据都将存储在 USB 驱动器上。由于不需要在本地驱动器上安装程序，我们可以在联机或脱机的计算机上运行应用程序。这意味着我们不需要 Internet 来下载任何依赖。

ORB 程序压缩了 60％，因此我们甚至可以从小型 USB 驱动器存储和使用它们。所有 ORB 应用程序都使用 PGP / RSA 进行签名，并通过 TLS 1.2 进行分发。所有应用程序打包时都不做任何修改，甚至不会重新编译。以下是当前可用的便携式 ORB 应用程序列表。

* abiword
* audacious
* audacity
* darktable
* deluge
* filezilla
* firefox
* gimp
* gnome-mplayer
* hexchat
* inkscape
* isomaster
* kodi
* libreoffice
* qbittorrent
* sound-juicer
* thunderbird
* tomahawk
* uget
* vlc
* 未来还有更多

Orb 是开源的，所以如果你是开发人员，欢迎协作并添加更多程序。

### 下载并使用可移动 ORB 程序

正如我已经提到的，我们不需要安装可移动 ORB 程序。但是，ORB 团队强烈建议你使用 **ORB 启动器** 来获得更好的体验。 ORB 启动器是一个小的安装程序（小于 5MB），它可帮助你启动 ORB 程序，并获得更好，更流畅的体验。

让我们先安装 ORB 启动器。为此，[下载 ORB 启动器](https://www.orbital-apps.com/documentation/orb-launcher-all-installers)。你可以手动下载 ORB 启动器的 ISO 并将其挂载到文件管理器上。或者在终端中运行以下任一命令来安装它：

```
$ wget -O - https://www.orbital-apps.com/orb.sh | bash

```

如果你没有 wget，请运行：

```
$ curl https://www.orbital-apps.com/orb.sh | bash

```

询问时输入 root 用户和密码。

就是这样。Orbit 启动器已安装并可以使用。

现在，进入 [ORB 可移动程序下载页面](https://www.orbital-apps.com/download/portable_apps_linux/)，并下载你选择的程序。在本教程中，我会下载 Firefox。

下载完后，进入下载位置并双击 ORB 程序来启动它。点击 Yes 确认。

![](/data/attachment/album/201806/01/100859vz6m5g5cuuutqkef.png)

Firefox ORB 程序能用了！

![](/data/attachment/album/201806/01/100902rqqvddddrvq1rgdk.png)

同样，你可以立即下载并运行任何程序。

如果你不想使用 ORB 启动器，请将下载的 `.orb` 安装程序设置为可执行文件，然后双击它进行安装。不过，建议使用 ORB 启动器，它可让你在使用 ORB 程序时更轻松、更顺畅。

就我测试的 ORB 程序而言，它们打开即可使用。希望这篇文章有帮助。今天就是这些。祝你有美好的一天！

干杯！！

---

via: <https://www.ostechnix.com/orbitalapps-new-generation-ubuntu-linux-applications/>

作者：[SK](https://www.ostechnix.com/author/sk/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Systemd 服务：比启动停止服务更进一步

![](/data/attachment/album/201806/02/052652hpe1dx1e7191tlx8.jpg)

在上一篇[文章](/article-9700-1.html)中，我们展示了如何创建一个 systemd 服务并使普通用户可以启动和终止游戏服务器。但到目前为止，使用这个服务并不比直接运行服务器高明多少。让我们更进一步，让其可以向玩家发邮件，包括在服务器可用时通知玩家，在服务器关闭前警告玩家：

```
# minetest.service

[Unit]
Description= Minetest server
Documentation= https://wiki.minetest.net/Main_Page

[Service]
Type= simple

ExecStart= /usr/games/minetest --server
ExecStartPost= /home/<username>/bin/mtsendmail.sh "Ready to rumble?" "Minetest Starting up"

TimeoutStopSec= 180
ExecStop= /home/<username>/bin/mtsendmail.sh "Off to bed. Nightie night!" "
  Minetest Stopping in 2 minutes"
ExecStop= /bin/sleep 120
ExecStop= /bin/kill -2 $MAINPID

```

这里涉及几个新的指令。首先是 `ExecStartPost` 指令，该指令可以在主进程启动后马上执行任何你指定的操作。在本例中，你执行了一个自定义脚本 `mtsendmail` (内容如下)，该脚本以邮件形式通知你的朋友服务器已经启动。

```
#!/bin/bash
# mtsendmail
echo $1 | mutt -F /home/<username>/.muttrc -s "$2" my_minetest@mailing_list.com

```

我们使用 [Mutt](http://www.mutt.org/) 这个命令后邮件客户端发送消息。虽然从实际效果来看，上述脚本仅有 1 行，但 systemd 单元的参数中不能包含管道及重定向操作，故我们需要将其封装到脚本中。

顺便提一下，还有一个 `ExecStartPre` 指令，用于在服务主进程执行之前进行指定操作。

接下来我们看到，关闭服务器涉及了好几条指令。`TimeoutStopSec` 指令用于设置 systemd 友好关闭服务的最大等候时间，默认值大约是 90 秒。超过这个最大等候时间，systemd 会强制关闭服务并报错。考虑到你希望在彻底关闭服务器前给用户预留几分钟的时间，你需要将超时时间提高至 3 分钟，这样 systemd 就不会误认为服务关闭时出现问题。

接下来是关闭服务的具体指令部分。虽然没有 `ExecStopPre` 这样的指令，但你可以通过多次使用 `ExecStop` 指令实现关闭服务器前执行操作的目标。多个 `ExecStop` 指令按从上到下的顺序依次运行，这样你就可以在服务器真正关闭前向用户发送消息。

通过这个特性，你首先应该向你的朋友发邮件，警告其服务器即将关闭，然后等待两分钟，最后关闭服务器。可以使用 `Ctrl + c` 关闭 Minetest 服务器，该操作会被转换为一个中断信号（`SIGINT`）；当你执行 `kill -2 $MAINPID` 时就会发送该中断信号，其中 `$MAINPID` 是 systemd 变量，用于记录你服务中主进程的 PID 信息。

看上去好多了！如果你此时启动服务：

```
systemctl --user start minetest

```

服务会启动 Minetest 服务器并向你的用户发送邮件。关闭服务的情形基本类似，只不过会额外留给用户 2 分钟时间退出登录。

### 开机自启动

下一步我们让你的服务在主机启动后立即可用，在主机关闭时自动关闭。

我们需要将你的服务文件移动到系统服务目录，即 `/etc/systemd/system/`：

```
sudo mv /home/<username>/.config/systemd/user/minetest.service /etc/systemd/system/

```

如果你希望此时启动该服务，你需要拥有超级用户权限：

```
sudo systemctl start minetest

```

另外，可以使用如下命令检查服务状态：

```
sudo systemctl status minetest

```

你会发现服务很糟糕地处于失败状态，这是因为 systemd 不能通过上下文信息、特征、配置文件得知具体使用哪个用户运行该服务。在单元文件中增加 `User` 指令可以解决这个问题。

```
# minetest.service

[Unit]
Description= Minetest server
Documentation= https://wiki.minetest.net/Main_Page

[Service]
Type= simple
User= <username>

ExecStart= /usr/games/minetest --server
ExecStartPost= /home/<username>/bin/mtsendmail.sh "Ready to rumble?"
  "Minetest Starting up"

TimeoutStopSec= 180
ExecStop= /home/<username>/bin/mtsendmail.sh "Off to bed. Nightie night!"
  "Minetest Stopping in 2 minutes"
ExecStop= /bin/sleep 120
ExecStop= /bin/kill -2 $MAINPID

```

systemd 从 `User` 指令中得知应使用哪个用户的环境变量来正确运行该服务。你可以使用 root 用户，但这可能产生安全风险；使用你的个人用户会好一些，但不少管理员的做法是为服务单独创建一个用户，这样可以有效地将服务与其它用户和系统组件相互隔离。

下一步我们让你的服务在系统启动时自动启动，系统关闭时自动关闭。要达到这个目的，你需要 *启用* 你的服务；但在这之前，你还需要告知 systemd 从哪里 *安装* 它。

对于 systemd 而言，*安装* 意味着告知 systemd 在系统启动的具体哪个步骤激活你的服务。以通用 Unix 打印系统（`cups.service`）为例，它的启动在网络框架启动之后、其它打印服务启动之前。又如，`minetest.server` 需要使用用户邮件（及其它组件），需要等待网络和普通用户对应的服务就绪后才可启动。

你只需要在单元文件中添加一个新段和新指令：

```
...
[Install]
WantedBy= multi-user.target

```

你可以将其理解为“等待多用户系统的全部内容就绪”。systemd 中的“目标”类似于旧系统中的运行级别，可以用于将主机转移到一个或另一个状态，也可以像本例中这样让你的服务等待指定状态出现后运行。

你的最终 `minetest.service` 文件如下：

```
# minetest.service
[Unit]
Description= Minetest server
Documentation= https://wiki.minetest.net/Main_Page

[Service]
Type= simple
User= <username>

ExecStart= /usr/games/minetest --server
ExecStartPost= /home/<username>/bin/mtsendmail.sh "Ready to rumble?"
  "Minetest Starting up"

TimeoutStopSec= 180
ExecStop= /home/<username>/bin/mtsendmail.sh "Off to bed. Nightie night!"
  "Minetest Stopping in 2 minutes"
ExecStop= /bin/sleep 120
ExecStop= /bin/kill -2 $MAINPID

[Install]
WantedBy= multi-user.target

```

在尝试新的服务之前，你还需要对邮件脚本做一些调整：

```
#!/bin/bash
# mtsendmail

sleep 20
echo $1 | mutt -F /home/<username>/.muttrc -s "$2" my_minetest@mailing_list.com
sleep 10

```

这是因为系统需要一定的时间启动邮件系统（这里等待 20 秒），也需要一定时间完成邮件发送（这里等待 10 秒）。注意脚本中的等待时间数值适用于我的系统，你可能需要针对你的系统调整数值。

大功告成啦。执行如下操作：

```
sudo systemctl enable minetest

```

你的 Minetest 服务将在系统启动时自动启动，在系统关闭时友好关闭并通知你的用户。

### 总结

事实上 Debian、 Ubuntu 和一些族类的发行版提供了 `minetest-server` 这个特别的软件包，可以提供一部分上述功能，（但不包括邮件通知功能）。即使如此，你还是可以建立你独有的自定义服务；事实上，你目前建立的服务比 Debian 默认提供的服务更加通用，可以提供更多功能。

更进一步的说，我们这里描述的流程可以让你将大多数简单服务器转换为服务，类型可以是游戏、网站应用或其它应用。同时，这也是你名副其实地踏入 systemd 大师殿堂的第一步。

---

via: <https://www.linux.com/blog/learn/2018/5/systemd-services-beyond-starting-and-stopping>

作者：[Paul Brown](https://www.linux.com/users/bro66) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


你可以用 Linux 中的 IP 工具做 3 件有用的事情

Summary: 如何使用 IP 工具来快速轻松地找到你的 IP 地址、显示路由表等等。

如何使用 IP 工具来快速轻松地找到你的 IP 地址、显示路由表等等。

>
> 如何使用 IP 工具来快速轻松地找到你的 IP 地址、显示路由表等等。
>
>
>

![](/data/attachment/album/201806/02/054023w7grjr6cjew6gz3e.jpg)

`ifconfig` 命令在 Linux 上被弃用已有十多年的时间了，而 `iproute2` 项目包含了神奇的工具 `ip`。许多在线教程资源仍然采用旧的命令行工具，如 `ifconfig`、`route` 和 `netstat`。本教程的目标是分享一些可以使用 `ip` 工具轻松完成的网络相关的事情。

### 找出你的 IP 地址

```
[dneary@host]$ ip addr show
[snip]
44: wlp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 5c:e0:c5:c7:f0:f1 brd ff:ff:ff:ff:ff:ff
        inet 10.16.196.113/23 brd 10.16.197.255 scope global dynamic wlp4s0
        valid_lft 74830sec preferred_lft 74830sec
        inet6 fe80::5ee0:c5ff:fec7:f0f1/64 scope link
        valid_lft forever preferred_lft forever

```

`ip addr show` 会告诉你很多关于你的所有网络链接设备的信息。在这里，我的无线以太网卡（`wlp4s0`）是 IPv4 地址（`inet` 字段）`10.16.196.113/23`。 `/23` 表示 32 位 IP 地址中的 23 位将被该子网中的所有 IP 地址共享。子网中的 IP 地址范围从 `10.16.196.0` 到 `10.16.197.254`。子网的广播地址（IP 地址后面的 `brd` 字段）`10.16.197.255` 保留给子网上所有主机的广播流量。

我们能只使用 `ip addr show dev wlp4s0` 来显示单个设备的信息。

### 显示你的路由表

```
[dneary@host]$ ip route list
default via 10.16.197.254 dev wlp4s0 proto static metric 600
10.16.196.0/23 dev wlp4s0 proto kernel scope link src 10.16.196.113 metric 601
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown

```

路由表是本地主机帮助网络流量确定去哪里的方式。它包含一组路标，将流量发送到特定的接口，以及在其旅途中的特定下一个地点。

如果你运行任何虚拟机或容器，它们将获得自己的 IP 地址和子网，这可能会使这些路由表非常复杂，但在单个主机中，通常有两条指令。对于本地流量，将其发送到本地以太网上，并且网络交换机将找出（使用称为 ARP 的协议）哪个主机拥有目标 IP 地址，并且要将流量发送到哪里。对于到互联网的流量，将其发送到本地网关节点，它将更好地了解如何到达目的地。

在上面的情况中，第一行代表外部流量的外部网关，第二行代表本地流量，第三行代表主机上运行的虚拟机的虚拟网桥，但该链接当前未激活。

### 监视你的网络配置

```
[dneary@host]$ ip monitor all
[dneary@host]$ ip -s link list wlp4s0

```

`ip monitor` 命令可用于监视路由表（网络接口上的网络寻址）的更改或本地主机上 ARP 表的更改。此命令在调试与容器和网络相关的网络问题时特别有用，如当两个虚拟机应该能彼此通信，但实际不能。

在使用 `all` 时，`ip monitor` 会报告所有的更改，前缀以 `[LINK]`（网络接口更改）、`[ROUTE]`（更改路由表）、`[ADDR]`（IP 地址更改）或 `[NEIGH]`（与马无关 —— 与邻居的 ARP 地址相关的变化）。

你还可以监视特定对象上的更改（例如，特定的路由表或 IP 地址）。

另一个适用于许多命令的有用选项是 `ip -s`，它提供了一些统计信息。添加第二个 `-s` 选项可以添加更多统计信息。上面的 `ip -s link list wlp4s0` 会给出很多关于接收和发送的数据包的信息、丢弃的数据包数量、检测到的错误等等。

### 提示：缩短你的命令

一般来说，对于 `ip` 工具，你只需要包含足够的字母来唯一标识你想要做的事情。你可以使用 `ip mon` 来代替 `ip monitor`。你可以使用 `ip a l`，而不是 `ip addr list`，并且可以使用 `ip r`来代替 `ip route`。`ip link list` 可以缩写为 `ip l ls`。要了解可用于更改命令行为的许多选项，请浏览 [ip 手册页](https://www.systutorials.com/docs/linux/man/8-ip-route/)。

---

via: <https://opensource.com/article/18/5/useful-things-you-can-do-with-IP-tool-Linux>

作者：[Dave Neary](https://opensource.com/users/dneary) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出