如何在 20 分钟内发布一个正式的 ERC20 通证

Summary: 在这篇教程中，我准备指导你部署你自己的 ERC20 通证到实际的以太坊网络上去。

# 如何在 20 分钟内发布一个正式的 ERC20 通证

<img src="content_image/album_201807_10_222045hwhg7mp7w766v7dz.jpg" alt="" title="">

这段时间以来，以太坊通证很流行。这些通证可以用来代表现实世界的各种价值单位：[黄金](https://digix.global/)、 [谎言](https://www.cnbc.com/2017/08/28/burger-king-russia-cryptocurrency-whoppercoin.html)、 [猫咪](https://www.cryptokitties.co/) 甚至是类似 [公司股票](https://www.investopedia.com/terms/i/initial-coin-offering-ico.asp) 一样的东西。迄今为止，人们已经募集了 [20 亿美元的通证](https://www.forbes.com/sites/chancebarnett/2017/09/23/inside-the-meteoric-rise-of-icos/#57ac46d95670)。那些通证是以 [ERC20](https://theethereum.wiki/w/index.php/ERC20_Token_Standard) 为标准的，人们可以轻松地在钱包之间进行交易。在这篇教程中，我准备指导你部署你自己的 ERC20 通证到真实的以太坊网络上去。

事先准备：

* 一个文本编辑器（[Atom](https://atom.io/) 不错，不过我喜欢 [Vim](http://www.vim.org/)）
* 对命令行和终端（模拟器）有起码的了解。Mac 内置的应用“终端”就很好，不过我喜欢 [iTerm2](https://www.iterm2.com/)
* Chrome 浏览器
* [Node.js 8](https://nodejs.org/)（或更高版本）
* 你的通证的名字。我的准备叫做 HamburgerCoin（汉堡币）

你需要做的第一件事是安装 [MetaMask](https://metamask.io/)。访问 [Metamask 网站](https://metamask.io/) 并点击“Get Chrome Extention”。

Metamask 可以让你通过 Chrome 在以太坊上进行交易。它依靠运行着公开以太坊节点的 [Infura](https://infura.io/) ，所以你不用自己运行以太坊全节点。如果你颇具探索精神，你也可以下载和安装 [Mist](https://github.com/ethereum/mist/releases) 以替代它。运行 Mist 就可以让你运行你自己的以太坊节点。运行自己的节点你就需要将你的计算机与该网络进行同步，这需要不短的时间。从技术上讲这更安全，因为这样你不必信任 Infura 来处理你的交易。Infura 可以忽略你的交易而干预你，但是它并不能偷走你的钱。因为安装 Metamask 比 Mist 更快也更简单，所以我假设你在下面的教程中使用 Metamask。

接着你需要安装 [truffle](http://truffleframework.com/)：

```
 $ npm install -g truffle

```

现在为你自己的新通证创建一个新目录，cd 到其中并初始化你的 truffle 项目。

```
$ mkdir hamburger-coin
$ cd hamburger-coin
$ truffle init

```

很好，你的 truffle 项目已经设置好了！

现在来创建我们的通证。首先我们需要安装 [OpenZepplin](https://github.com/OpenZeppelin) 框架。OpenZepplin 框架包括了大量预先构建好的合约，包括我们要部署的 ERC20 通证合约。

（只需要按下回车接受默认值即可）

```
$ npm init
package name: (hamburger-coin)
version: (1.0.0)
description:
entry point: (truffle.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/masonf/src/hamburger-coin/package.json:

{
  "name": "hamburger-coin",
  "version": "1.0.0",
  "description": "",
  "main": "truffle.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Is this ok? (yes) yes
$ npm install zeppelin-solidity

```

现在我们可以创建我们的通证合约了。创建一个 `contracts/HamburgerCoin.sol` 文件并加入如下内容：

```
pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/StandardToken.sol";

contract HamburgerCoin is StandardToken {
  string public name = "HamburgerCoin";
  string public symbol = "HBC";
  uint public decimals = 2;
  uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);

  function HamburgerCoin() public {
    totalSupply_ = INITIAL_SUPPLY;
    balances[msg.sender] = INITIAL_SUPPLY;
  }
}

```

（LCTT 译注：上述合约内容中指定了合约的名称、符号和供应量。在 ERC20 当中，通证的供应量其实是整数，上述合约中通证的实际供应量是 10000 \* 100 个，出于显示 2 位小数的需求，你在合约浏览器、钱包软件中看到和操作的 1 个通证，实际上在交易中是以 100 个进行的。）

OpenZepplin 的 `StandardToken` 是一个标准的 ERC20 通证。如果你感兴趣，你可以看看它的 [源代码](https://github.com/OpenZeppelin/zeppelin-solidity/tree/master/contracts/token) 以了解是如何工作的。

实际上并不太复杂。该合约有一个 [地址到余额](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/BasicToken.sol#L15) 的映射（LCTT 译注：你可以理解为哈希、关联数组），它也有一个 [允许转账](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/StandardToken.sol#L17) 的列表。你可以看做是支票。你可以写张支票，但是直到它被兑付前，钱并不会被转账。

如果有人要转走一些资金，你可以在合约上调用 [approve](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/StandardToken.sol#L48) 方法，设置你要发送的通证数量。这就像是写支票一样。

然后调用 [transferFrom](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/StandardToken.sol#L26) 会实际进行转账。

我们可以从头写这些合约，但是最好采用经过完备的社区测试的合约。从头写一个 ERC20 通证那就是另外一篇文章了。

试着运行 `compile` 来编译我们的合约：

```
$ truffle compile
Compiling ./contracts/HamburgerCoin.sol...
Compiling zeppelin-solidity/contracts/math/SafeMath.sol...
Compiling zeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling zeppelin-solidity/contracts/token/BasicToken.sol...
Compiling zeppelin-solidity/contracts/token/ERC20.sol...
Compiling zeppelin-solidity/contracts/token/ERC20Basic.sol...
Compiling zeppelin-solidity/contracts/token/MintableToken.sol...
Compiling zeppelin-solidity/contracts/token/StandardToken.sol...
Writing artifacts to ./build/contracts Next you'll need to add a migration file which will tell truffle how to deploy your contract.

```

接下来我们需要增加一个 truffle [迁移](http://truffleframework.com/docs/getting_started/migrations)。

创建 `migrations/2_deploy_hamburgercoin.js` 文件并添加如下内容：

```
var HamburgerCoin = artifacts.require("./HamburgerCoin.sol");

module.exports = function(deployer) {
  deployer.deploy(HamburgerCoin);
};

```

现在让我们配置 truffle 以能够使用 Infura 公共节点。如果我们要部署到公共节点，那就需要钱包的私钥。我们可以将该私钥包含在我们的源代码当中，但是如果任何人可以访问你的源代码（和版本库），他就能够偷走我们所有的汉堡币！要避免这种情况，我们会使用 [dotenv](https://github.com/motdotla/dotenv) node.js 模块。（LCTT 译注：dotenv 用于存储机密信息的文件 .env 是以 “.” 开头的，默认不会进入版本库，当然，如果有人能查看你全部的项目文件，你的私钥还是会被泄露。）

让我们安装部署到 Infura 所需的所有模块。

```
npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet

```

（LCTT 译注：可能安装过程中会有很多警告，大多应该是属于定义了未使用的变量和方法的编译警告，可以忽略。）

现在编辑 `truffle.js` 并（原样）加入如下内容：

```
require('dotenv').config();
const Web3 = require("web3");
const web3 = new Web3();
const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');

var mainNetPrivateKey = Buffer.from(process.env["MAINNET_PRIVATE_KEY"], "hex")
var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");

var ropstenPrivateKey = Buffer.from(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");

module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8545,
      network_id: "*" // Match any network id
    },
    ropsten: {
      provider: ropstenProvider,
      // You can get the current gasLimit by running
      // truffle deploy --network rinkeby
      // truffle(rinkeby)> web3.eth.getBlock("pending", (error, result) =>
      //   console.log(result.gasLimit))
      gas: 4600000,
      gasPrice: web3.toWei("20", "gwei"),
      network_id: "3",
    },
    mainnet: {
      provider: mainNetProvider,
      gas: 4600000,
      gasPrice: web3.toWei("20", "gwei"),
      network_id: "1",
    }
  }
};

```

（LCTT 译注：原文采用 `new Buffer` 来获取私钥设置，但 node.js 升级后，废弃了 `new Buffer` 这种用法，运行时会发出警告，所以上面我修改为使用 `Buffer.from` 。）

接下来我们从 Metamask 中得到我们的私钥：

1. 点击你的 Chrome 窗口右上角的狐狸图标。
2. 点击 “Account 1” 右侧的省略号。
3. 点击 “Export Private Key”。
4. 输入你的密码。
5. 点击该文字以复制私钥到剪贴板。

然后打开 `.env`文件，并像下面这样贴入你的私钥（对于 Ropsten 测试网和 Mainnet 主网，你的私钥是一样的）：

```
ROPSTEN_PRIVATE_KEY="123YourPrivateKeyHere"
MAINNET_PRIVATE_KEY="123YourPrivateKeyHere"

```

接下来，让我们部署到 Ropsten 以太坊测试网。

以太坊测试网是一个你可以测试合约的地方。此外还有 [Kovan](https://kovan-testnet.github.io/website/) 和 [Rinkeby](https://www.rinkeby.io/) 测试网。我在这个教程中选择 Ropsten 是因为现在很容易得到 Ropsten 的测试 ETH。这些测试网都类似，你可以使用任何一个你喜欢的，但是在此教程当中我假设你在使用 Ropsten。访问 <https://faucet.metamask.io/> 以得到一些测试 ETH。从 faucet 得到一些 ETH 后，你就可以部署了。

```
$ truffle deploy --network ropsten
Compiling ./contracts/HamburgerCoin.sol...
Compiling ./contracts/Migrations.sol...
Compiling zeppelin-solidity/contracts/math/SafeMath.sol...
Compiling zeppelin-solidity/contracts/token/BasicToken.sol...
Compiling zeppelin-solidity/contracts/token/ERC20.sol...
Compiling zeppelin-solidity/contracts/token/ERC20Basic.sol...
Compiling zeppelin-solidity/contracts/token/StandardToken.sol...
Writing artifacts to ./build/contracts

Using network 'ropsten'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0xc2bbe6bf5a7c7c7312c43d65de4c18c51c4d620d5bf51481ea530411dcebc499
  Migrations: 0xd827b6f93fcb50631edc4cf8e293159f0c056538
Saving successful migration to network...
  ... 0xe6f92402e6ca0b1d615a310751568219f66b9d78b80a37c6d92ca59af26cf475
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying HamburgerCoin...
  ... 0x02c4d47526772dc524851fc2180b338a6b037500ab298fa2f405f01abdee21c4
  HamburgerCoin: 0x973b1a5c753a2d5d3924dfb66028b975e7ccca51
Saving artifacts...

```

在 “Saving aritfacts” 上面的这行即是你的合约的新地址。

复制并黏贴该地址到 [Ropsten Etherscan 搜索框](https://ropsten.etherscan.io/)，你就能看到你新部署的合约。

现在你可以在任何 ERC20 兼容的钱包，如 [Mist](https://github.com/ethereum/mist) 、[MyEtherWallet](https://www.myetherwallet.com/)（LCTT 译注：或 ImToken 这样的手机应用）里面使用你的通证了。

为了这篇教程，我构建了一个名为 [Etherface](http://etherface.io/) 的钱包来做演示。

首先你需要添加你的通证到 Etherface：

1. 访问 <http://etherface.io/> 。
2. 确认你在 Metamask 中选择了 “Ropsten” 网络。
3. 点击 “Tokens”。
4. 点击右上角的加号按钮。
5. 输入上面的合约地址。

如果你有朋友想要一些汉堡币，你现在就可以发送给他们了。如果没有，你也可以在你的两个账号间测试转账：

1. 在 Metamask 中点击 “切换账号”按钮（在右上角），并改变你的账号为 “Account 2”。
2. 点击 “Account 2” 右边的省略号，然后选择 “Copy Address to clipboard”。
3. 切换回 “Account 1”，这很重要！否则交易会失败。
4. 在 Etherface 中你的余额下点击 “Send”。
5. 黏贴 “Account 2” 的地址。
6. 输入你要发送的数量。
7. Metamask 会弹出确认窗口，点击 “Submit”。
8. 等大约 15-30 秒。
9. 你的 “Account 1” 的余额应该会减少，“Account 2” 现在会有了一些汉堡币！

最后，让我们来部署到主网（LCTT 译注：这会花费你真实的 ETH，你可以通过查看前面部署到 Ropsten 的合约信息中了解花费了多少 gas，以相应估计实际要花费多少 ETH）：

```
$ truffle deploy --network mainnet

```

你可以如前面一样加你的通证到 Etherface ，并发送你新打造的通证给你的朋友们了！


GNU GPL 许可证常见问题解答（六）

# GNU GPL 许可证常见问题解答（六）

本文由高级咨询师薛亮据自由软件基金会（FSF）的[英文原文](https://www.gnu.org/licenses/gpl-faq.html)翻译而成，这篇常见问题解答澄清了在使用 GNU 许可证中遇到许多问题，对于企业和软件开发者在实际应用许可证和解决许可证问题时具有很强的实践指导意义。

1. [关于 GNU 项目、自由软件基金会（FSF）及其许可证的基本问题](/article-9062-1.html)
2. [对于 GNU 许可证的一般了解](/article-8834-1.html)
3. [在您的程序中使用 GNU 许可证](/article-8761-1.html)
4. [依据GNU许可证分发程序](/article-9222-1.html)
5. [在编写其他程序时采用依据 GNU 许可证发布的程序](/article-9448-1.html)
6. 将作品与依据 GNU 许可证发布的代码相结合
7. 关于违反 GNU 许可证的问题

### 6 将作品与依据 GNU 许可证发布的代码相结合

#### 6.1 GPL v3 是否与 GPL v2 兼容？

不兼容。许多要求已经从 GPL v2 变为 GPL v3，这意味 GPL v2 中的精确要求并不体现在 GPL v3 中，反之亦然。例如，GPL v3 的终止条件比 GPL v2 的终止条件更为宽泛，因此与 GPL v2 的终止条件不同。

由于这些差异，两个许可证不兼容：如果您试图将依据 GPL v2 发布的代码与依据 GPL v3 发布的代码组合，则将违反 GPL v2 的第 6 部分。

但是，如果代码依据 GPL “v2 或更高版本”发布，则与 GPL v3 兼容，因为 GPL v3 是其允许的选项之一。

#### 6.2 GPL v2 是否有提供安装信息的要求？

GPL v3 明确要求再分发中包含完整的必要的“安装信息”。GPL v2 不使用该术语，但它需要再分发中包含用于控制可编译和安装可执行文件的脚本以及完整和相应的源代码。这涵盖了 GPL v3 中称为“安装信息”的部分内容，但不包括所有内容。因此，GPL v3 对安装信息的要求较强。

#### 6.3 各种 GNU 许可证之间如何相互兼容？

各种 GNU 许可证彼此之间具有广泛的兼容性。下面是唯一的一种您不能将遵循两种 GNU 许可证的代码结合起来的情况：将遵循旧版本许可证的代码与遵循该许可证新版本的代码进行结合。

以下是 GNU 许可证的各种结合的详细兼容性矩阵，以便为特定情况提供易于使用的参考。它假设有人依据其中一个许可证编写了一些软件，而您希望以某种方式将该软件的代码结合到您要发布的项目（您自己的原始作品或其他人的软件的修改版本）中。在表顶部的列中找到项目的许可证，并在左侧的一行中找到其他代码的许可证。它们交叉的单元格会告诉您这种结合是否被允许。

当我们说“复制代码”时，我们的意思就是：您正在从一个源代码中获取一段代码（无论是否修改），并将其插入到自己的程序中，从而基于第一部分代码形成一个作品。当您编译或运行代码时，“使用库”意味着您不直接复制任何源代码，而是通过链接、导入或其他典型机制将源代码绑定在一起。

矩阵中每个标明 GPL v3 的地方，其关于兼容性的声明也同样适用于 AGPL v3。

**兼容性矩阵**

|  |  |
| --- | --- |
|   | 我希望依据以下许可证许可我的代码 |
| 仅 GPL v2 | GPL v2 或更高版本 | GPL v3 或更高版本 | 仅 LGPL v2.1 | LGPL v2.1 或更高版本 | LGPL v3 或更高版本 |
| 我希望复制遵循右侧许可证的代码： | 仅 GPL v2 | 可以 | 可以 【2】 | 不可以 | 可以，结合作品只能遵循GPL v2 【7】 | 可以，结合作品只能遵循GPL v2 【7】【2】 | 不可以 |
| GPL v2 或更高版本 | 可以 【1】 | 可以 | 可以 | 可以，结合作品需遵循GPL v2或更高版本 【7】 | 可以，结合作品需遵循GPL v2或更高版本 【7】 | 可以，结合作品需遵循GPL v3 【8】 |
| GPL v3 | 不可以 | 可以，结合作品需遵循GPL v3 【3】 | 可以 | 可以，结合作品需遵循GPL v3 【7】 | 可以，结合作品需遵循GPL v3 【7】 | 可以，结合作品需遵循GPL v3 【8】 |
| 仅 LGPL v2.1 | 可以，需依据GPL v2传递复制后代码 【7】 | 可以，需依据GPL v2或更高版本传递复制后代码 【7】 | 可以，需依据GPL v3传递复制后代码 【7】 | 可以 | 可以 【6】 | 可以，需依据GPL v3传递复制后代码 【7】【8】 |
| LGPL v2.1 或更高版本 | 可以，需依据GPL v2传递复制后代码 【7】【1】 | 可以，需依据GPL v2或更高版本传递复制后代码 【7】 | 可以，需依据GPL v3传递复制后代码 【7】 | 可以 【5】 | 可以 | 可以 |
| LGPL v3 | 不可以 | 可以，结合作品需遵循GPL v3 【8】【3】 | 可以，结合作品需遵循GPL v3 【8】 | 可以，结合作品需遵循GPL v3 【7】【8】 | 可以，结合作品需遵循LGPL v3 【4】 | 可以 |
| 我希望使用遵循右侧许可证的库： | 仅 GPL v2 | 可以 | 可以 【2】 | 不可以 | 可以，结合作品只能遵循GPL v2 【7】 | 可以，结合作品只能遵循GPL v2 【7】【2】 | 不可以 |
| GPL v2 或更高版本 | 可以 【1】 | 可以 | 可以 | 可以，结合作品需遵循GPL v2或更高版本 【7】 | 可以，结合作品需遵循GPL v2或更高版本 【7】 | 可以，结合作品需遵循GPL v3 【8】 |
| GPL v3 | 不可以 | 可以，结合作品需遵循GPL v3 【3】 | 可以 | 可以，结合作品需遵循GPL v3 【7】 | 可以，结合作品需遵循GPL v3 【7】 | 可以，结合作品需遵循GPL v3 【8】 |
| 仅LGPL v2.1 | 可以 | 可以 | 可以 | 可以 | 可以 | 可以 |
| LGPL v2.1 或更高版本 | 可以 | 可以 | 可以 | 可以 | 可以 | 可以 |
| LGPL v3 | 不可以 | 可以，结合作品需遵循GPL v3 【9】 | 可以 | 可以 | 可以 | 可以 |

**角注：**

1. 在这种情况下，当结合代码时，您必须遵守 GPL v2 的条款。您不能适用更高版本的条款。
2. 在这种情况下，您可以依据 GPL v2 或更高版本发布您的项目（您的原始作品和/或您收到并修改的作品），请注意，您使用的其他代码仍然只能遵循 GPL v2。只要您的项目依赖于该代码，您将无法将项目的许可证升级到 GPL v3 或更高版本，整个作品（您的项目和其他代码的任意结合）只能依据 GPL v2 的条款传递。
3. 如果您有能力依据 GPL v2 或任何更高版本发布项目，您可以选择依据 GPL v3 或更高版本发布该项目，一旦您执行此操作，您就可以结合依据 GPL v3 发布的代码。
4. 如果您有能力依据 LGPL v2.1 或任何更高版本发布项目，您可以选择依据 LGPL v3 或更高版本发布该项目，一旦您这样做，您就可以结合依据 LGPL v3 发布的代码。
5. 在这种情况下结合代码时，您必须遵守 LGPL v2.1 的条款。您不能适用更高版本 LGPL 中的条款。
6. 如果这样做，只要项目包含仅依据 LGPL v2.1 发布的代码，您将无法将项目的许可证升级到 LGPL v3 或更高版本。
7. LGPL v2.1 允许您将遵循自 GPL v2 之后任何版本 GPL 的代码进行重新许可。如果在这种情况下可以将遵循 LGPL 的代码切换为使用适当版本的 GPL（如表所示），则可以进行此种结合。
8. LGPL v3 是 GPL v3 加上在这种情况下可以忽略的额外权限。
9. 由于 GPL v2 不允许与 LGPL v3 结合，因此在这种情况下，您必须依据 GPL v3 的条款传递项目，因为它允许此种结合。

#### 6.4 <ruby> “聚合” <rp>  （ </rp> <rt>  aggregate </rt> <rp>  ） </rp></ruby>与其他类型的“修改版本”有什么区别？（同 2.25）

“聚合”由多个单独的程序组成，分布在同一个 CD-ROM 或其他媒介中。GPL 允许您创建和分发聚合，即使其他软件的许可证不是自由许可证或与 GPL 不兼容。唯一的条件是，发布“聚合”所使用的许可证不能禁止用户去行使“聚合”中每个程序对应的许可证所赋予用户的权利。

两个单独的程序还是一个程序有两个部分，区分的界限在哪里？这是一个法律问题，最终由法官决定。我们认为，适当的判断标准取决于通信机制（exec、管道、rpc、共享地址空间内的函数调用等）和通信的语义（哪些信息被互换）。

如果模块们被包含在相同的可执行文件中，则它们肯定是被组合在一个程序中。如果模块们被设计为在共享地址空间中链接在一起运行，那么几乎肯定意味着它们组合成为一个程序。

相比之下，管道、套接字和命令行参数是通常在两个独立程序之间使用的通信机制。所以当它们用于通信时，模块们通常是单独的程序。但是，如果通信的语义足够亲密，交换复杂的内部数据结构，那么也可以视为这两个部分合并成了一个更大的程序。

#### 6.5 我在使用 GPL 程序的源代码时是否具有<ruby> “合理使用” <rp>  （ </rp> <rt>  fair use </rt> <rp>  ） </rp></ruby>权限？（同 4.17）

是的，您有。“合理使用”是在没有任何特别许可的情况下允许的使用。由于您不需要开发人员的许可来进行这种使用，无论开发人员在许可证或其他地方对此怎么说，您都可以执行此操作，无论该许可证是 GNU GPL 还是其他自由软件许可证。

但是，请注意，没有全世界范围普适的合理使用原则；什么样的用途被认为“合理”因国而异。

#### 6.6 美国政府可否对遵循 GPL 的程序进行改进并发布？（同 3.14）

可以。如果这些改进是由美国政府雇员在雇佣期间编写的，那么这些改进属于公有领域。不过，GNU GPL 仍然涵盖了整体的改进版本。在这种情况下没有问题。

如果美国政府使用承包商来完成这项工作，那么改进本身可以被 GPL 覆盖。

#### 6.7 GPL 对于与其所覆盖的作品进行静态或动态链接的模块有不同的要求吗？

没有。将 GPL 覆盖的作品静态或动态地链接到其他模块是基于 GPL 覆盖的作品构建结合作品。因此，GNU GPL 的条款和条件将覆盖整个结合作品。另请参阅：6.24 如果我在 GPL 软件中使用了与 GPL 不兼容的库，会出现什么法律问题？

#### 6.8 LGPL 对于与其所覆盖的作品进行静态或动态链接的模块有不同的要求吗？

为了遵守 LGPL（任何现有版本：v2、v2.1 或 v3）：

（1）如果您静态链接到 LGPL 库，您还必须以对象（不一定是源代码）格式提供应用程序，以便用户有机会修改库并重新链接应用程序。

（2）如果您动态链接*已经存在于用户计算机上*的 LGPL 库，则不需要传递库的源代码。另一方面，如果您自己将可执行的 LGPL 库与您的应用程序一起传递，无论是静态还是动态链接，还必须以 LGPL 所提供的方式之一来传递库的源代码。

#### 6.9 如果库依据 GPL（而不是 LGPL）发布，这是否意味着使用它的任何软件必须遵循 GPL 或与 GPL 兼容的许可证？

是的，因为程序实际上与库进行了链接。因此，GPL 的条款适用于整个结合作品。与库链接的软件模块可能遵循与GPL兼容的不同许可证，但整体作品必须遵循 GPL。另见：“2.23 许可证与 GPL 兼容是什么意思？”

#### 6.10 您有一个遵循 GPL 的程序，我想将它与我的代码进行链接，来构建一个专有程序。那么事实上，我链接到您的程序意味着我必须让我的程序遵循 GPL 许可证？

不完全是。这意味着您必须依据与 GPL 兼容的许可证（更准确地说，与您链接的结合作品中所有其他代码所适用的一个或多个 GPL 版本相兼容）发布您的程序。然后，结合作品本身就可以遵循这些 GPL 版本。

#### 6.11 如果是这样的话，有没有机会依据 LGPL 获得您的程序许可？

您可以这么要求，但绝大多数的作者都会坚定不移地说不。GPL 的想法是，如果要将我们的代码包含在程序中，您的程序也必须是自由软件。GPL 的意图是给您施加压力，让您以能够使其成为我们社区一部分的方式来发布您的程序。

您始终拥有不使用我们代码的合法选择。

#### 6.12 我们构建专有软件的项目不能使用遵循 GPL 的某个 GNU 程序。您会为我们提供例外吗？ 这将意味着该程序拥有更多用户。

对不起，我们没有这样的例外。这样做是不对的。

最大化用户数量不是我们的目标。相反，我们正在努力为尽可能多的用户提供至关重要的自由。一般来说，专有软件项目是阻碍而不是实现软件自由的原因。

我们偶尔提供许可证例外来协助一个依据 GPL 以外的许可证生产自由软件的项目。不过，我们必须看到一个很好的理由，即这个项目为什么会推动自由软件的发展。

我们有时也会改变软件包的分发条款，这显然是为自由软件事业服务的正确方法；但是我们对此非常谨慎，所以您必须向我们展示非常有说服力的理由。

#### 6.13 如果一个编程语言解释器是依据 GPL 发布的，这是否意味着由它解释的程序必须遵循与 GPL 兼容的许可证？

当解释器只是解释一种语言时，答案是否定的。被解释程序对于解释器来说只是数据；根据版权法，像GPL这样的自由软件许可证不能限制您使用解释器的数据。您可以使用任何数据（被解释程序），以任何您喜欢的方式运行它，并且没有任何要求规定您必须将数据授权给任何人。

然而，当解释器被扩展以向<ruby> 其他程序 <rp>  （ </rp> <rt>  facilities </rt> <rp>  ） </rp></ruby>（通常但不一定是库）提供<ruby> “绑定” <rp>  （ </rp> <rt>  bindings </rt> <rp>  ） </rp></ruby>时，被解释程序通过这些绑定有效地与其使用的程序相关联。因此，如果这些程序是依据 GPL 发布的，则使用它们的被解释程序必须以与 GPL 兼容的方式发布。JNI（Java Native Interface）是这种绑定机制的一个例子；以这种方式访问的库与调用它们的 Java 程序动态链接。这些库也与解释器联系在一起。如果解释器与这些库静态链接，或者如果它被设计为[与这些特定库动态链接](https://www.gnu.org/licenses/gpl-faq.html#GPLPluginsInNF)，那么也需要以与 GPL 兼容的方式发布。

另一个类似且非常常见的情况是为库提供解释器，它们能够自我解释。例如，Perl 带有许多 Perl 模块，Java 实现带有许多 Java 类。这些库和调用它们的程序总是动态链接在一起。

结果是，如果您选择在程序中使用遵循 GPL 的 Perl 模块或 Java 类，则必须以与 GPL 兼容的方式发布该程序，无论结合后的 Perl 或 Java 程序所依之运行的 Perl 或 Java 解释器中使用什么样的许可证。

#### 6.14 如果编程语言解释器遵循与 GPL 不兼容的许可证，我可以在其上运行遵循 GPL 的程序吗？

当解释器解释一种语言时，答案是肯定的。被解释程序对于解释器来说只是数据；GPL 不会限制您处理程序时所使用的工具。

然而，当解释器被扩展以向<ruby> 其他程序 <rp>  （ </rp> <rt>  facilities </rt> <rp>  ） </rp></ruby>（通常但不一定是库）提供“绑定”时，被解释程序通过这些绑定有效地与其使用的程序相关联。JNI（Java Native Interface）是此种程序的一个例子；以这种方式访问的库与调用它们的 Java 程序动态链接。

因此，如果这些程序是依据与 GPL 不兼容的许可证发布的，则情况就像以任何其他方式跟与 GPL 不兼容的库链接。这意味着：

1. 如果您正在编写代码并将其依据 GPL 发布，您可以声明一个<ruby> 明确例外 <rp>  （ </rp> <rt>  explicit exception </rt> <rp>  ） </rp></ruby>，允许将其链接到与 GPL 不兼容的程序。
2. 如果您依据 GPL 编写并发布程序，并且专门设计了与这些程序配合使用的功能，人们可以将其作为<ruby> 隐性例外 <rp>  （ </rp> <rt>  implicit exception </rt> <rp>  ） </rp></ruby>，允许它们与这些程序进行链接。但是，如果这只是你的打算的话，最好明确地这么说。

您不能把别人遵循 GPL 的代码用于这种方式，或者添加这样的例外。只有该代码的版权所有者才能添加例外。

#### 6.15 如果我将一个模块添加到遵循 GPL 的程序中，我必须使用 GPL 作为我的模块的许可证吗？

GPL 规定，整个结合后的程序必须依据 GPL 发布。所以你的模块必须可以依据 GPL 进行使用。

但是，您可以提供使用您代码的额外授权。如果您愿意，您可以依据比 GPL 更为宽松但与 GPL 兼容的许可证发布模块。许可证列表页面提供了与 [GPL 兼容许可证](https://www.gnu.org/licenses/license-list.html)的部分列表。

#### 6.16 什么时候程序和插件会被认为是单一的结合程序？

这取决于主程序如何调用其插件。如果主程序使用 `fork` 和 `exec` 来调用插件，并通过共享复杂的数据结构或来回传送复杂的数据结构来建立<ruby> 密切通信 <rp>  （ </rp> <rt>  intimate communication </rt> <rp>  ） </rp></ruby>，可以使它们成为一个单一的结合程序。如果主程序使用简单的 `fork` 和 `exec` 来调用插件并且不建立它们之间的密切通信，插件被认为是一个单独的程序。

如果主程序动态地链接插件，并且它们彼此进行函数调用并共享数据结构，我们相信它们形成了一个单一的结合程序，它必须被视为主程序和插件的扩展。如果主程序动态地链接插件，但是它们之间的通信仅限于使用某些选项调用插件的“main”功能，并等待它返回，这是一种<ruby> 临界案例 <rp>  （ </rp> <rt>  borderline case </rt> <rp>  ） </rp></ruby>。

使用共享内存与复杂数据结构进行通信几乎等同于动态链接。

#### 6.17 如果我写了一个用于遵循 GPL 程序的插件，那么对可用于分发我的插件的许可证有什么要求？

请参阅 “6.16 什么时候程序和插件会被认为是单一的结合程序 ？”以确定插件和主程序是否被视为单个结合程序，以及何时将其视为单独的作品。

如果主程序和插件是单个结合程序，则这意味着您必须依据 GPL 或与 GPL 兼容的自由软件许可证授权插件，并以符合 GPL 的方式将源代码进行分发。与其插件分开的主程序对插件没有要求。

#### 6.18 在为非自由程序编写插件时，可以应用 GPL 许可证吗？

请参阅 “6.16 什么时候程序和插件会被认为是单一的结合程序？”以确定插件和主程序是否被视为单个结合程序，以及何时被视为单独的程序。

如果它们组成单一的结合程序，这意味着遵循 GPL 的插件与非自由主程序的结合将违反 GPL。但是，您可以通过向插件的许可证添加例外声明来解决该法律问题，并允许将其与非自由主程序链接。

另请参阅正在编写的[使用非自由库的自由软件的问题](https://www.gnu.org/licenses/gpl-faq.html#FSWithNFLibs)。

#### 6.19 我可以发布一个旨在加载遵循 GPL 的插件的非自由程序吗？

请参阅 “6.16 什么时候程序和插件会被认为是单一的结合程序？”以确定插件和主程序是否被视为单个结合程序，以及何时被视为单独的程序。

如果它们组成单一的结合程序，则主程序必须依据 GPL 或与 GPL 兼容的自由软件许可证发布，并且当主程序为了与这些插件一起使用而被分发时，必须遵循 GPL 的条款。

然而，如果它们是单独的作品，则插件的许可证对主程序没有要求。

另请参阅正在编写的[使用非自由库的自由软件的问题](https://www.gnu.org/licenses/gpl-faq.html#FSWithNFLibs)。

#### 6.20 我想将遵循 GPL 的软件纳入我的专有系统。我只依据 GPL 给予我的权限来使用该软件。我可以这样做吗？（同 5.6）

您不能将遵循 GPL 的软件纳入专有系统。GPL 的目标是授予每个人复制、再分发、理解和修改程序的自由。如果您可以将遵循 GPL 的软件整合到非自由系统中，则可能会使遵循 GPL 的软件不再是自由软件。

包含遵循 GPL 程序的系统是该 GPL 程序的扩展版本。GPL 规定，如果它最终发布的话，任何扩展版本的程序必须依据 GPL 发布。这有两个原因：确保获得软件的用户获得自己应该拥有的自由，并鼓励人们回馈他们所做的改进。

但是，在许多情况下，您可以将遵循 GPL 的软件与专有系统一起分发。要有效地做到这一点，您必须确保自由和非自由程序之间的通信<ruby> 保持一定距离 <rp>  （ </rp> <rt>  arms length </rt> <rp>  ） </rp></ruby>，而不是将它们有效地结合成一个程序。

这种情况与“纳入”遵循 GPL 的软件之间的区别，是一部分实质和一部分形式的问题。实质上是这样的：如果两个程序结合起来，使它们成为一个程序的两个部分，那么您不能将它们视为两个单独的程序。所以整个作品必须遵循 GPL。

如果这两个程序保持良好的分离，就像编译器和内核，或者像编辑器和shell一样，那么您可以将它们视为两个单独的程序，但是您必须恰当执行。这个问题只是一个形式问题：您如何描述您在做什么。为什么我们关心这个？因为我们想确保用户清楚地了解软件集合中遵循 GPL 的软件的自由状态。

如果人们分发遵循 GPL 的软件，将其称为系统（用户已知其中一部分为专有软件）的“一部分”，用户可能不确定其对遵循GPL的软件所拥有的权利。但是如果他们知道他们收到的是一个自由程序加上另外一个程序，那么他们的权利就会很清楚。

#### 6.21 我想将遵循 GPL 的软件纳入我的专有系统。我是否可以通过在 GPL 覆盖的部分和专有部分之间，放置一个遵循与 GPL 兼容的宽松许可证（如 X11 许可证）的<ruby> “封装” <rp>  （ </rp> <rt>  wrapper </rt> <rp>  ） </rp></ruby>模块来实现？

不可以，X11 许可证与 GPL 兼容，因此您可以向遵循 GPL 的程序添加一个模块，并让其遵循 X11 许可证。但是，如果要将它们整合到一个更大的程序中，那么这个整体将包含 GPL 覆盖的部分，所以它必须在 GNU GPL 下作为一个整体获得许可。

专有模块 A 仅通过遵循 X11 许可证的模块 B 与遵循 GPL 的模块 C 通信，该事实在法律上是无关紧要的；重要的是模块 C 包含在整体作品中。

#### 6.22 我可以编写使用非自由库的自由软件吗？

如果您这样做，您的程序将无法在一个自由的环境中完全使用。如果您的程序依赖于一个非自由库来做某件工作，那么在自由软件世界里就不能做这个工作。如果这依赖于一个非自由库来运行，它不能是自由操作系统（例如 GNU）的一部分；这完全成为了自由软件世界里的禁区。

所以请考虑：你可以找到一种方法来完成这项工作，而不使用这个库吗？你可以为该库编写一个自由软件替代选择吗？

如果程序已经使用非自由库编写，那么改变决定也许已经太晚了。您也可以按照目前状态来发布程序，而不是不发布。但是请在 README 文件中提到，对非自由库的需求是一个缺点，并建议更改程序以便在没有非自由库的情况下执行相同的工作。请建议任何想要在程序上进行大量进一步工作的人首先将其从依赖非自由库中解脱出来。

请注意，将某些非自由库与遵循 GPL 的自由软件相结合也可能存在法律问题。有关更多信息，请参阅有关 [GPL 软件与和其不兼容库的问题](https://www.gnu.org/licenses/gpl-faq.html#GPLIncompatibleLibs)。

#### 6.23 我可以将遵循 GPL 的程序与专有系统库链接吗？

每个版本的 GPL 相对于其<ruby> 左版 <rp>  （ </rp> <rt>  copyleft </rt> <rp>  ） </rp></ruby>都有一个例外，通常称为系统库例外。如果您要使用的与 GPL 不兼容的库符合系统库的标准，则使用它们不需要做特别的工作；分发整个程序的源代码的要求不包括那些库，即使您分发包含它们的链接可执行文件。

作为<ruby> “系统库” <rp>  （ </rp> <rt>  system library </rt> <rp>  ） </rp></ruby>的标准在不同版本的 GPL 之间有所不同。GPL v3 在第 1 节中明确定义“系统库”，将其从<ruby> “相应源代码” <rp>  （ </rp> <rt>  Corresponding Source </rt> <rp>  ） </rp></ruby>的定义中排除。GPL v2 在第 3 部分的末尾进行，处理这个问题略有不同。

#### 6.24 如果我在遵循 GPL 的软件中使用了与 GPL 不兼容的库，会出现什么法律问题？

如果您希望程序与未被系统库例外所涵盖的库链接，则需要提供许可来执行此操作。以下是您可以使用的两个许可证通知示例；一个用于 GPL v3，另一个用于 GPL v2。在这两种情况下，您应该将此文本放在您授予此权限的每个文件中。

只有该程序的版权持有人才能合法地按照这些条款发布其软件。如果您自己编写了整个程序，假设您的雇主或学校没有声明版权，您就是版权所有者，因此您可以授权该例外。但是，如果您想在代码中使用其他作者的其他遵循GPL的程序的一部分，那么您无法将例外授权给他们。您必须获得这些程序的版权所有者的批准。

当其他人修改程序时，他们不需要为他们的代码设置同样的例外——是否这样做是他们自己的选择。

如果您打算链接的库不是自由软件，请参阅[使用非自由库编写自由软件部分](https://www.gnu.org/licenses/gpl-faq.html#FSWithNFLibs)。

如果您使用 GPL v3，您可以通过在第 7 节下授予额外权限来实现此目标。以下许可证通知将会执行此操作。您必须使用适合您程序的文本替换括号中的所有文本。如果不是每个人都可以为您打算链接的库分发源代码，则应该删除大括号中的文本；否则，只需删除大括号。

>
> Copyright (C) [年份] [著作权人名称]
>
>
> 本程序为自由软件；您可以根据自由软件基金会发布的 GNU GPL 许可证的条款再分发和/或修改它；无论是依据本许可证的版本3，或（根据您的选择）任何更高版本。
>
>
> 本程序基于希望其有用的目标而分发，但**不提供任何担保**；甚至也**没有适销性或适用于特定用途的默示担保**。有关详细信息，请参阅 GNU GPL 许可证。
>
>
> 您应该已经收到本程序以及 GNU GPL 许可证的副本；如果没有，请参阅 <http://www.gnu.org/licenses>。
>
>
> 依据 GNU GPL v3 第7节的额外许可
>
>
> 如果您通过将[与库的名称]（或库的修改版本）链接或结合来修改本程序，或任何被覆盖的作品，其中包含被[库许可证的名称]的条款所覆盖的部分，则该程序的许可人授予您额外许可来传递所产出的作品。{这种结合的非源代码形式的相应源代码应包括所使用的[库名称]部分的源代码以及被覆盖的作品的源代码。}
>
>
>

如果您使用 GPL v2，您可以为许可证条款提供自己的例外。以下许可证通知将这样做。同样，您必须使用适合您程序的文本替换括号中的所有文本。如果不是每个人都可以为您打算链接的库分发源代码，则应该删除大括号中的文本；否则，只需删除大括号。

>
> Copyright (C) [年份] [著作权人名称]
>
>
> 本程序为自由软件；您可以根据自由软件基金会发布的 GNU GPL 许可证的条款再分发和/或修改它；无论是依据许可证的 v2，或（根据您的选择）任何更高版本。
>
>
> 本程序基于希望其有用的目标而分发，但**不提供任何担保**；甚至也**没有适销性或适用于特定用途的默示担保**。有关详细信息，请参阅 GNU GPL 许可证。
>
>
> 您应该已经收到本程序以及 GNU GPL 许可证的副本；如果没有，请参阅 <http://www.gnu.org/licenses>。
>
>
> 将[您的程序名称]与其他模块静态或动态链接是以[您的程序名称]为基础构建结合作品。因此，GNU GPL 许可证的条款和条件将覆盖整个结合作品。
>
>
> 另外，作为一个特殊例外，[您的程序名称]的版权持有人可以让您将[您的程序名称]与依据 GNU LGPL 发布的自由程序或库以及依据[库的许可证名称]标准发布的[库名称]中包含的代码相结合（或具有相同许可证的此类代码的修改版本）。您可以按照[您的程序名称]所依据的 GNU GPL 的条款和其他有关代码的许可证复制和分发此系统{前提是当 GNU GPL 要求分发源代码时将其他代码的源代码包含在内}。
>
>
> 注意，对[您的程序名称]做出修改版本的人没有义务为其修改版本授予此特殊例外；是否这样做是他们自己的选择。GNU GPL 许可证允许发布一个没有此例外的修改版本；该例外也使得发布一个带有该例外的修改版本成为可能。
>
>
>

#### 6.25 我正在使用 Microsoft Visual C ++（或 Visual Basic）编写 Windows 应用程序，我将依据 GPL 发布它。依据GPL，是否允许将我的程序与 Visual C ++（或 Visual Basic）运行时库动态链接？

您可以将您的程序链接到这些库，并将编译后的程序分发给其他程序。执行此操作时，运行时库是 GPL v3 所定义的“系统库”。这意味着您不需要担心将库的源代码包含在程序的相应源代码中。GPL v2 在第 3 节中提供了类似的例外。

您可能不会随同您的程序以编译后的 DLL 形式分发这些库。为了防止不道德的分发者试图将系统库例外作为漏洞进行利用，GPL 表示，只有库不与程序本身一起分发，库才能被认定为系统库。如果您随同您的程序分发 DLL，则它们将不再符合此例外的资格；那么遵守 GPL 的唯一方法就是提供它们的源代码，而您无法做到。

可以编写只在 Windows 上运行的自由程序，但这不是一个好主意。这些程序将被 Windows <ruby>   “围困”  <rp>  （ </rp> <rt>  trapped </rt> <rp>  ） </rp></ruby>，因此对自由软件世界的贡献为零。

#### 6.26 我想修改遵循 GPL 的程序，并将它们与 Money Guzzler Inc. 的可移植性库链接。我无法分发这些库的源代码，因此，任何想要更改这些版本的用户都必须单独获取这些库。为什么 GPL 不允许这样做？

有两个原因。第一、一般性的原因。如果我们允许 A 公司制作一个专有文件，B 公司分发与该文件相关的遵循 GPL 的软件，其效果等同于将 GPL 撕开一个大洞。对于保持 GPL 软件各种修改和扩展的源代码来说，这如同一张署名空白纸。

让所有用户能够访问源代码是我们的主要目标之一，所以这个结果绝对是我们想要避免的。

更具体地说，根据我们对条款的理解，与 Money Guzzler 库链接的程序版本不会是真正的自由软件——它们不会附带完整的让用户能够更改和重新编译程序的源代码。

#### 6.27 如果模块 Q 的许可证具有与 GPL 不兼容的要求，但是只有当 Q 自身分发时，而不是在较大程序中包含 Q 时，该要求才适用，是否可以使得该许可证与 GPL 兼容？可以将 Q 与遵循 GPL 的程序结合使用吗？

如果程序 P 依据 GPL 被发布，这意味着“任何和所有部分”都可以依据 GPL 进行使用。如果您集成了模块 Q，并依据 GPL 发布结合程序 P + Q，则表示可以依据 GPL 使用 P + Q 的任何部分。P + Q 的一部分是 Q，所以依据 GPL 发布 P + Q 意味着，Q 的任何部分可以依据 GPL 进行使用。换句话说，依据 GPL 获得 P + Q 的用户可以删除 P，所以 Q 仍然遵循 GPL。

如果模块 Q 的许可证允许您授予该许可，则其与 GPL 兼容。否则，它不与 GPL 兼容。

如果 Q 的许可证在不明确的条件下表示，您必须在自己再分发 Q 时做某些事情（与 GPL 不兼容），那么不允许您依据 GPL 分发Q。因此，您也不能依据 GPL 发布 P + Q。所以您不能将 P 与 Q 进行链接或结合。

#### 6.28 在面向对象的语言（如 Java）中，如果我在不修改的情况下使用遵循 GPL 的类，并对其进行子类化，GPL 会以什么方式影响较大的程序？

子类化将会创建衍生作品。因此，当您创建遵循 GPL 的类的子类时，GPL 的条款会影响整个程序。

#### 6.29 分发一个意图链接到 Linux 内核的非自由驱动程序会违反 GPL 吗？

Linux（GNU / Linux 操作系统中的内核）依据 GNU GPL v2 进行分发。分发一个意图链接 Linux 的非自由驱动程序违反 GPL 吗？

是的，这是一种违规行为，因为这样做形成了更大的结合作品。用户期望把这些片段放在一起的事实并不会改变任何事情。

在代码实体部分拥有版权的 Linux 的每个贡献者都可以执行 GPL，我们鼓励他们对那些分发非自由 Linux 驱动程序的人采取行动。

#### 6.30 如何允许在受控接口下将专有模块与我的 GPL 库链接起来？

在声明该文件依据 GNU GPL 进行分发的文本末尾，将以下文本添加到软件包中每个文件的许可证通知中：

>
> 将 ABC 与其他模块静态或动态链接是基于 ABC 创建结合作品。因此，GNU GPL 许可证的条款和条件将覆盖整个结合作品。
>
>
> 作为一个特殊的例外，ABC 的版权所有者可以将 ABC 程序与自由软件程序或依据 GNU LGPL 发布的库以及通过 ABCDEF 界面与 ABC 通信的独立模块相结合。您可以根据 ABC 的 GNU GPL 条款和其他代码的许可证复制和分发此系统，前提是您在 GNU GPL 需要分发源代码时提供该代码的源代码，并且您没有修改 ABCDEF 界面。
>
>
> 请注意，制作 ABC 修改版本的人没有义务为其修改版本授予此特殊例外；是否这样做是他们自己的选择。GNU GPL 许可证允许发布不含此例外的修改版本；此例外也使得发布一个带有该例外的修改版本成为可能。如果您修改了 ABCDEF 界面，此例外不适用于您修改的 ABC 版本，并且您必须在分发修改后的版本时删除此例外。
>
>
> 此例外是依据 GNU GPL 许可证第3版（“GPL v3”）第7节的额外权限。
>
>
>

此例外允许通过指定接口（“ABCDEF”）与遵循不同许可证的模块进行链接，同时确保用户仍然会按照 GPL 通常的方式接收源代码。

只有该程序的版权持有者才能合法授权此例外。如果您自己编写了整个程序，假设您的雇主或学校没有声明版权，您就是版权所有者，因此您可以授权该例外。但是，如果您想在代码中使用其他作者的其他遵循 GPL 程序的一部分，那么您无法对他们的例外进行授权。您必须获得这些程序的版权所有者的批准。

#### 6.31 考虑这种情况：1）X 发布遵循 GPL 的项目的 V1 版本。2）基于对 V1 的修改和新代码开发，Y 对 V2 的改进做出贡献。3）X 想将 V2 转换为非 GPL 许可证。X 需要 Y 的许可吗？

需要。Y 需要依据 GNU GPL 发布其版本，因为它基于 X 的版本 V1。没有任何要求规定 Y 为其代码适用任何其他许可。因此，X 必须获得 Y 的许可才能依据另一个许可证发布该代码。

#### 6.32 我已经编写了一个与许多不同组件链接的应用程序，它们具有不同的许可证。我对我的程序有什么许可要求感到很困惑。您能告诉我可以使用哪些许可证吗？

为了回答这个问题，我们需要看一下你的程序使用的每个组件的列表，该组件的许可证和一个简短的（几句话应该足够）说明你的库如何使用该组件的描述。两个例子是：

* 为了让我的软件工作，它必须链接到遵循 LGPL 的 FOO 库。
* 我的软件进行系统调用（使用我建立的命令行）来运行 BAR 程序，该程序遵循 GPL，“具有允许与 QUUX 链接的特殊例外”。

#### 6.33 可以在依据与 GPL 不兼容的许可证进行许可的文档中使用遵循 GPL 的源代码片段吗？

如果片段足够小，依据“合理使用”或类似的法律，您可以将它们纳入其中，那么可以。否则，不可以。

---

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


# 如何使用 Steam Play 在 Linux 上玩仅限 Windows 的游戏

>
> Steam 的新实验功能允许你在 Linux 上玩仅限 Windows 的游戏。以下是如何在 Steam 中使用此功能。
>
>
>

你已经听说过这个消息。游戏发行平台 [Steam 正在复刻一个 WINE 分支来允许你玩仅限于 Windows 上的游戏](/article-10054-1.html)。对于 Linux 用户来说，这绝对是一个好消息，因为我们总抱怨 Linux 的游戏数量不足。

这个新功能仍处于测试阶段，但你现在可以在 Linux 上试用它并在 Linux 上玩仅限 Windows 的游戏。让我们看看如何做到这一点。

### 使用 Steam Play 在 Linux 中玩仅限 Windows 的游戏

你需要先安装 Steam。Steam 适用于所有主要 Linux 发行版。我已经详细介绍了[在 Ubuntu 上安装 Steam](https://itsfoss.com/install-steam-ubuntu-linux/)，如果你还没有安装 Steam，你可以参考那篇文章。

安装了 Steam 并且你已登录到 Steam 帐户，就可以了解如何在 Steam Linux 客户端中启用 Windows 游戏。

#### 步骤 1：进入帐户设置

运行 Steam 客户端。在左上角，单击 “Steam”，然后单击 “Settings”。

#### 步骤 2：选择加入测试计划

在“Settings”中，从左侧窗口中选择“Account”，然后单击 “Beta participation” 下的 “CHANGE” 按钮。

你应该在此处选择 “Steam Beta Update”。

在此处保存设置后，Steam 将重新启动并下载新的测试版更新。

#### 步骤 3：启用 Steam Play 测试版

下载好 Steam 新的测试版更新后，它将重新启动。到这里就差不多了。

再次进入“Settings”。你现在可以在左侧窗口看到新的 “Steam Play” 选项。单击它并选中复选框：

* Enable Steam Play for supported titles （你可以玩列入白名单的 Windows 游戏）
* Enable Steam Play for all titles （你可以尝试玩所有仅限 Windows 的游戏）

我不记得 Steam 是否会再次重启，但我想这无所谓。你现在应该可以在 Linux 上看到安装仅限 Windows 的游戏的选项了。

比如，我的 Steam 库中有《Age of Empires》，正常情况下这个在 Linux 中没有。但我在 Steam Play 测试版启用所有 Windows 游戏后，现在我可以选择在 Linux 上安装《Age of Empires》了。

*现在可以在 Linux 上安装仅限 Windows 的游戏*

### 有关 Steam Play 测试版功能的信息

在 Linux 上使用 Steam Play 测试版玩仅限 Windows 的游戏有一些事情你需要知道并且牢记。

* 目前，[只有 27 个 Steam Play 中的 Windows 游戏被列入白名单](https://steamcommunity.com/games/221410)。这些白名单游戏可以在 Linux 上无缝运行。
* 你可以使用 Steam Play 测试版尝试任何 Windows 游戏，但它可能不是总能运行。有些游戏有时会崩溃，而某些游戏可能根本无法运行。
* 在测试版中，你无法 Steam 商店中看到适用于 Linux 的 Windows 限定游戏。你必须自己尝试游戏或参考[这个社区维护的列表](https://docs.google.com/spreadsheets/d/1DcZZQ4HL_Ol969UbXJmFG8TzOHNnHoj8Q1f8DIFe8-8/htmlview?sle=true#)以查看该 Windows 游戏的兼容性状态。你也可以通过填写[此表](https://docs.google.com/forms/d/e/1FAIpQLSeefaYQduMST_lg0IsYxZko8tHLKe2vtVZLFaPNycyhY4bidQ/viewform)来为列表做出贡献。
* 如果你在 Windows 中通过 Steam 下载了游戏，你可以[在 Linux 和 Windows 之间共享 Steam 游戏文件](/article-8027-1.html)来节省下载的数据。

我希望本教程能帮助你在 Linux 上运行仅限 Windows 的游戏。你期待在 Linux 上玩哪些游戏？

---

via: <https://itsfoss.com/steam-play/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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/) 荣誉推出


“用户组”在 Linux 上到底是怎么工作的？

# “用户组”在 Linux 上到底是怎么工作的？

<img src="content_image/album_201809_29_132250juu19js98uuo5ukc.jpg" alt="" title="">

嗨！就在上周，我还自认为对 Linux 上的用户和组的工作机制了如指掌。我认为它们的关系是这样的：

1. 每个进程都属于一个用户（比如用户 `julia`）
2. 当这个进程试图读取一个被某个组所拥有的文件时， Linux 会 a. 先检查用户`julia` 是否有权限访问文件。（LCTT 译注：此处应该是指检查文件的所有者是否就是 `julia`） b. 检查 `julia` 属于哪些组，并进一步检查在这些组里是否有某个组拥有这个文件或者有权限访问这个文件。
3. 如果上述 a、b 任一为真（或者“其它”位设为有权限访问），那么这个进程就有权限访问这个文件。

比如说，如果一个进程被用户 `julia` 拥有并且 `julia` 在`awesome` 组，那么这个进程就能访问下面这个文件。

```
r--r--r-- 1 root awesome     6872 Sep 24 11:09 file.txt
```

然而上述的机制我并没有考虑得非常清楚，如果你硬要我阐述清楚，我会说进程可能会在**运行时**去检查 `/etc/group` 文件里是否有某些组拥有当前的用户。

### 然而这并不是 Linux 里“组”的工作机制

我在上个星期的工作中发现了一件有趣的事，事实证明我前面的理解错了，我对组的工作机制的描述并不准确。特别是 Linux **并不会**在进程每次试图访问一个文件时就去检查这个进程的用户属于哪些组。

我在读了《[Linux 编程接口](http://man7.org/tlpi/)》这本书的第九章（“进程资格”）后才恍然大悟（这本书真是太棒了），这才是组真正的工作方式！我意识到之前我并没有真正理解用户和组是怎么工作的，我信心满满的尝试了下面的内容并且验证到底发生了什么，事实证明现在我的理解才是对的。

### 用户和组权限检查是怎么完成的

现在这些关键的知识在我看来非常简单! 这本书的第九章上来就告诉我如下事实：用户和组 ID 是**进程的属性**，它们是：

* 真实用户 ID 和组 ID；
* 有效用户 ID 和组 ID；
* 保存的 set-user-ID 和保存的 set-group-ID；
* 文件系统用户 ID 和组 ID（特定于 Linux);
* 补充的组 ID；

这说明 Linux **实际上**检查一个进程能否访问一个文件所做的组检查是这样的：

* 检查一个进程的组 ID 和补充组 ID（这些 ID 就在进程的属性里，**并不是**实时在 `/etc/group` 里查找这些 ID）
* 检查要访问的文件的访问属性里的组设置
* 确定进程对文件是否有权限访问（LCTT 译注：即文件的组是否是以上的组之一）

通常当访问控制的时候使用的是**有效**用户/组 ID，而不是**真实**用户/组 ID。技术上来说当访问一个文件时使用的是**文件系统**的 ID，它们通常和有效用户/组 ID 一样。（LCTT 译注：这句话针对 Linux 而言。）

### 将一个用户加入一个组并不会将一个已存在的进程（的用户）加入那个组

下面是一个有趣的例子：如果我创建了一个新的组：`panda` 组并且将我自己（`bork`）加入到这个组，然后运行 `groups` 来检查我是否在这个组里：结果是我（`bork`）竟然不在这个组？！

```
bork@kiwi~> sudo addgroup panda
Adding group `panda' (GID 1001) ...
Done.
bork@kiwi~> sudo adduser bork panda
Adding user `bork' to group `panda' ...
Adding user bork to group panda
Done.
bork@kiwi~> groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd

```

`panda` 并不在上面的组里！为了再次确定我们的发现，让我们建一个文件，这个文件被 `panda` 组拥有，看看我能否访问它。

```
$  touch panda-file.txt
$  sudo chown root:panda panda-file.txt
$  sudo chmod 660 panda-file.txt
$  cat panda-file.txt
cat: panda-file.txt: Permission denied
```

好吧，确定了，我（`bork`）无法访问 `panda-file.txt`。这一点都不让人吃惊，我的命令解释器并没有将 `panda` 组作为补充组 ID，运行 `adduser bork panda` 并不会改变这一点。

### 那进程一开始是怎么得到用户的组的呢？

这真是个非常令人困惑的问题，对吗？如果进程会将组的信息预置到进程的属性里面，进程在初始化的时候怎么取到组的呢？很明显你无法给你自己指定更多的组（否则就会和 Linux 访问控制的初衷相违背了……）

有一点还是很清楚的：一个新的进程是怎么从我的命令行解释器（`/bash/fish`）里被**执行**而得到它的组的。（新的）进程将拥有我的用户 ID（`bork`），并且进程属性里还有很多组 ID。从我的命令解释器里执行的所有进程是从这个命令解释器里 `fork()` 而来的，所以这个新进程得到了和命令解释器同样的组。

因此一定存在一个“第一个”进程来把你的组设置到进程属性里，而所有由此进程而衍生的进程将都设置这些组。而那个“第一个”进程就是你的<ruby> 登录程序 <rt>  login shell </rt></ruby>，在我的笔记本电脑上，它是由 `login` 程序（`/bin/login`）实例化而来。登录程序以 root 身份运行，然后调用了一个 C 的库函数 —— `initgroups` 来设置你的进程的组（具体来说是通过读取 `/etc/group` 文件），因为登录程序是以 root 运行的，所以它能设置你的进程的组。

### 让我们再登录一次

好了！假如说我们正处于一个登录程序中，而我又想刷新我的进程的组设置，从我们前面所学到的进程是怎么初始化组 ID 的，我应该可以通过再次运行登录程序来刷新我的进程组并启动一个新的登录命令！

让我们试试下边的方法：

```
$ sudo login bork
$ groups
bork adm cdrom sudo dip plugdev lpadmin sambashare docker lxd panda
$ cat panda-file.txt # it works! I can access the file owned by `panda` now!
```

当然，成功了！现在由登录程序衍生的程序的用户是组 `panda` 的一部分了！太棒了！这并不会影响我其他的已经在运行的登录程序（及其子进程），如果我真的希望“所有的”进程都能对 `panda` 组有访问权限。我必须完全的重启我的登录会话，这意味着我必须退出我的窗口管理器然后再重新登录。（LCTT 译注：即更新进程树的树根进程，这里是窗口管理器进程。）

### newgrp 命令

在 Twitter 上有人告诉我如果只是想启动一个刷新了组信息的命令解释器的话，你可以使用 `newgrp`（LCTT 译注：不启动新的命令解释器），如下：

```
sudo addgroup panda
sudo adduser bork panda
newgrp panda # starts a new shell, and you don't have to be root to run it!
```

你也可以用 `sg panda bash` 来完成同样的效果，这个命令能启动一个`bash` 登录程序，而这个程序就有 `panda` 组。

### seduid 将设置有效用户 ID

其实我一直对一个进程如何以 `setuid root` 的权限来运行意味着什么有点似是而非。现在我知道了，事实上所发生的是：`setuid` 设置了
 “有效用户 ID”! 如果我（`julia`）运行了一个 `setuid root` 的进程（ 比如 `passwd`），那么进程的**真实**用户 ID 将为 `julia`，而**有效**用户 ID 将被设置为 `root`。

`passwd` 需要以 root 权限来运行，但是它能看到进程的真实用户 ID 是 `julia` ，是 `julia` 启动了这个进程，`passwd` 会阻止这个进程修改除了 `julia` 之外的用户密码。

### 就是这些了！

在《[Linux 编程接口](http://man7.org/tlpi/)》这本书里有很多 Linux 上一些功能的罕见使用方法以及 Linux 上所有的事物到底是怎么运行的详细解释，这里我就不一一展开了。那本书棒极了，我上面所说的都在该书的第九章，这章在 1300 页的书里只占了 17 页。

我最爱这本书的一点是我只用读 17 页关于用户和组是怎么工作的内容，而这区区 17 页就能做到内容完备、详实有用。我不用读完所有的 1300 页书就能得到有用的东西，太棒了！

---

via: <https://jvns.ca/blog/2017/11/20/groups/>

作者：[Julia Evans](https://jvns.ca/) 译者：[DavidChen](https://github.com/DavidChenLiang) 校对：[wxy](https://github.com/wxy)

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


# 怎样解决 Ubuntu 中的 “sub process usr bin dpkg returned an error code 1” 错误

>
> 如果你在 Ubuntu Linux 上安装软件时遇到 “sub process usr bin dpkg returned an error code 1”，请按照以下步骤进行修复。
>
>
>

Ubuntu 和其他基于 Debian 的发行版中的一个常见问题是已经损坏的包。你尝试更新系统或安装新软件包时会遇到类似 “Sub-process /usr/bin/dpkg returned an error code” 的错误。

这就是前几天发生在我身上的事。我试图在 Ubuntu 中安装一个电台程序时，它给我了这个错误：

```
Unpacking python-gst-1.0 (1.6.2-1build1) ...
Selecting previously unselected package radiotray.
Preparing to unpack .../radiotray_0.7.3-5ubuntu1_all.deb ...
Unpacking radiotray (0.7.3-5ubuntu1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5.2) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20180209-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for gnome-menus (3.13.3-6ubuntu3.1) ...
Processing triggers for mime-support (3.59ubuntu1) ...
Setting up polar-bookshelf (1.0.0-beta56) ...
ln: failed to create symbolic link '/usr/local/bin/polar-bookshelf': No such file or directory
dpkg: error processing package polar-bookshelf (--configure):
subprocess installed post-installation script returned error exit status 1
Setting up python-appindicator (12.10.1+16.04.20170215-0ubuntu1) ...
Setting up python-gst-1.0 (1.6.2-1build1) ...
Setting up radiotray (0.7.3-5ubuntu1) ...
Errors were encountered while processing:
polar-bookshelf
E: Sub-process /usr/bin/dpkg returned an error code (1)

```

这里最后三行非常重要。

```
Errors were encountered while processing:
polar-bookshelf
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

它告诉我 polar-bookshelf 包引发了问题。这可能对你如何修复这个错误至关重要。

### 修复 Sub-process /usr/bin/dpkg returned an error code (1)

<img src="content_image/album_201809_29_190058wcn5vndtc5zthw7g.jpg" alt="Fix update errors in Ubuntu Linux" title="Fix update errors in Ubuntu Linux">

让我们尝试修复这个损坏的错误包。我将展示几种你可以逐一尝试的方法。最初的那些易于使用，几乎不用动脑子。

在试了这里讨论的每一种方法之后，你应该尝试运行 `sudo apt update`，接着尝试安装新的包或升级。

#### 方法 1：重新配包数据库

你可以尝试的第一种方法是重新配置包数据库。数据库可能在安装包时损坏了。重新配置通常可以解决问题。

```
sudo dpkg --configure -a
```

#### 方法 2：强制安装

如果是之前包安装过程被中断，你可以尝试强制安装。

```
sudo apt-get install -f
```

#### 方法3：尝试删除有问题的包

如果这不是你的问题，你可以尝试手动删除包。但不要对 Linux 内核包（以 linux- 开头）执行此操作。

```
sudo apt remove
```

#### 方法 4：删除有问题的包中的信息文件

这应该是你最后的选择。你可以尝试从 `/var/lib/dpkg/info` 中删除与相关软件包关联的文件。

**你需要了解一些基本的 Linux 命令来了解发生了什么以及如何对应你的问题**

就我而言，我在 polar-bookshelf 中遇到问题。所以我查找了与之关联的文件：

```
ls -l /var/lib/dpkg/info | grep -i polar-bookshelf
-rw-r--r-- 1 root root 2324811 Aug 14 19:29 polar-bookshelf.list
-rw-r--r-- 1 root root 2822824 Aug 10 04:28 polar-bookshelf.md5sums
-rwxr-xr-x 1 root root 113 Aug 10 04:28 polar-bookshelf.postinst
-rwxr-xr-x 1 root root 84 Aug 10 04:28 polar-bookshelf.postrm
```

现在我需要做的就是删除这些文件：

```
sudo mv /var/lib/dpkg/info/polar-bookshelf.* /tmp
```

使用 `sudo apt update`，接着你应该就能像往常一样安装软件了。

#### 哪种方法适合你（如果有效）？

我希望这篇快速文章可以帮助你修复 “E: Sub-process /usr/bin/dpkg returned an error code (1)” 的错误。

如果它对你有用，是那种方法？你是否设法使用其他方法修复此错误？如果是，请分享一下以帮助其他人解决此问题。

---

via: <https://itsfoss.com/dpkg-returned-an-error-code-1/>

作者：[Abhishek Prakash](https://itsfoss.com/author/abhishek/) 选题：[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/) 荣誉推出


Bat：一种具有语法高亮和 Git 集成的 Cat 类命令

Summary: 它是 cat 命令的一个克隆版，具有一些例如语法高亮、 Git 集成和自动分页等非常酷的特性。

# Bat：一种具有语法高亮和 Git 集成的 Cat 类命令

在类 UNIX 系统中，我们使用 `cat` 命令去打印和连接文件。使用 `cat` 命令，我们能将文件目录打印到到标准输出，合成几个文件为一个目标文件，还有追加几个文件到目标文件中。今天，我偶然发现一个具有相似作用的命令叫做 “Bat” ，它是 `cat` 命令的一个克隆版，具有一些例如语法高亮、 Git 集成和自动分页等非常酷的特性。在这个简略指南中，我们将讲述如何在 Linux 中安装和使用 `bat` 命令。

### 安装

Bat 可以在 Arch Linux 的默认软件源中获取。 所以你可以使用 `pacman` 命令在任何基于 arch 的系统上来安装它。

```
$ sudo pacman -S bat
```

在 Debian、Ubuntu、Linux Mint 等系统中，从其[发布页面](https://github.com/sharkdp/bat/releases)下载 **.deb** 文件，然后用下面的命令来安装。

```
$ sudo apt install gdebi
$ sudo gdebi bat_0.5.0_amd64.deb
```

对于其他系统，你也许需要从软件源编译并安装。确保你已经安装了 Rust 1.26 或者更高版本。

然后运行以下命令来安装 Bat：

```
$ cargo install bat
```

或者，你可以从 [Linuxbrew](https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/) 软件包管理中来安装它。

```
$ brew install bat
```

### bat 命令的使用

`bat` 命令的使用与 `cat` 命令的使用非常相似。

使用 `bat` 命令创建一个新的文件:

```
$ bat > file.txt
```

使用 `bat` 命令来查看文件内容，只需要:

```
$ bat file.txt
```

你能同时查看多个文件:

```
$ bat file1.txt file2.txt
```

将多个文件的内容合并至一个单独文件中:

```
$ bat file1.txt file2.txt file3.txt > document.txt
```

就像我之前提到的那样，除了浏览和编辑文件以外，`bat` 命令有一些非常酷的特性。

`bat` 命令支持大多数编程和标记语言的<ruby> 语法高亮 <rt>  syntax highlighting </rt></ruby>。比如，下面这个例子。我将使用 `cat` 和 `bat` 命令来展示 `reverse.py` 的内容。

你注意到区别了吗？ `cat` 命令以纯文本格式显示文件的内容，而 `bat` 命令显示了语法高亮和整齐的文本对齐格式。更好了不是吗？

如果你只想显示行号（而没有表格）使用 `-n` 标记。

```
$ bat -n reverse.py
```

另一个 `bat` 命令中值得注意的特性是它支持<ruby> 自动分页 <rt>  automatic paging </rt></ruby>。 它的意思是当文件的输出对于屏幕来说太大的时候，`bat` 命令自动将自己的输出内容传输到 `less` 命令中，所以你可以一页一页的查看输出内容。

让我给你看一个例子，使用 `cat` 命令查看跨多个页面的文件的内容时，提示符会快速跳至文件的最后一页，你看不到内容的开头和中间部分。

看一下下面的输出：

正如你所看到的，`cat` 命令显示了文章的最后一页。

所以你也许需要去将使用 `cat` 命令的输出传输到 `less` 命令中去从开头一页一页的查看内容。

```
$ cat reverse.py | less
```

现在你可以使用回车键去一页一页的查看输出。然而当你使用 `bat` 命令时这些都是不必要的。`bat` 命令将自动传输跨越多个页面的文件的输出。

```
$ bat reverse.py
```

现在按下回车键去往下一页。

`bat` 命令也支持 <ruby> Git 集成 <rt>     GIT integration   </rt></ruby>，这样您就可以轻松查看/编辑 Git 存储库中的文件。 它与 Git 连接可以显示关于索引的修改。（看左栏）

### 定制 Bat

如果你不喜欢默认主题，你也可以修改它。Bat 同样有修改它的选项。

若要显示可用主题，只需运行：

```
$ bat --list-themes
1337
DarkNeon
Default
GitHub
Monokai Extended
Monokai Extended Bright
Monokai Extended Light
Monokai Extended Origin
TwoDark
```

要使用其他主题，例如 TwoDark，请运行：

```
$ bat --theme=TwoDark file.txt
```

如果你想永久改变主题，在你的 shells 启动文件中加入 `export BAT_THEME="TwoDark"`。

`bat` 还可以选择修改输出的外观。使用 `--style` 选项来修改输出外观。仅显示 Git 的更改和行号但不显示网格和文件头，请使用 `--style=numbers,changes`。

更多详细信息，请参阅 Bat 项目的 GitHub 库（链接在文末）。

最好，这就是目前的全部内容了。希望这篇文章会帮到你。更多精彩文章即将到来，敬请关注！

干杯！

---

via: <https://www.ostechnix.com/bat-a-cat-clone-with-syntax-highlighting-and-git-integration/>

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

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


如何在 Ubuntu 上安装 Cinnamon 桌面环境

Summary: 这篇教程将会为你展示如何在 Ubuntu 上安装 Cinnamon 桌面环境。

锁屏失灵怎么回事

来自河南郑州的 Chrome Mobile 73.0|Android 10 用户

这篇教程将会为你展示如何在 Ubuntu 上安装 Cinnamon 桌面环境。

# 如何在 Ubuntu 上安装 Cinnamon 桌面环境

>
> 这篇教程将会为你展示如何在 Ubuntu 上安装 Cinnamon 桌面环境。
>
>
>

[Cinnamon](http://cinnamon.linuxmint.com/) 是 [Linux Mint](http://www.linuxmint.com/) 的默认桌面环境。不同于 Ubuntu 的 Unity 桌面环境，Cinnamon 是一个更加传统而优雅的桌面环境，其带有底部面板和应用菜单。由于 Cinnamon 桌面以及它类 Windows 的用户界面，许多桌面用户[相较于 Ubuntu 更喜欢 Linux Mint](https://itsfoss.com/linux-mint-vs-ubuntu/)。

现在你无需[安装 Linux Mint](https://itsfoss.com/guide-install-linux-mint-16-dual-boot-windows/) 就能够体验到 Cinnamon了。在这篇教程，我将会展示给你如何在 Ubuntu 18.04，16.04 和 14.04 上安装 Cinnamon。

在 Ubuntu 上安装 Cinnamon 之前，有一些事情需要你注意。有时候，安装的额外桌面环境可能会与你当前的桌面环境有冲突。可能导致会话、应用程序或功能等的崩溃。这就是为什么你需要在做这个决定时谨慎一点的原因。

### 如何在 Ubuntu 上安装 Cinnamon 桌面环境

过去有 Cinnamon 团队为 Ubuntu 提供的一系列的官方 PPA，但现在都已经失效了。不过不用担心，还有一个非官方的 PPA，而且它运行的很完美。这个 PPA 里包含了最新的 Cinnamon 版本。

```
sudo add-apt-repository
ppa:embrosyn/cinnamon
sudo apt update && sudo apt install cinnamon
```

下载的大小大概是 150 MB（如果我没记错的话）。这其中提供的 Nemo（Cinnamon 的文件管理器，基于 Nautilus）和 Cinnamon 控制中心。这些东西提供了一个更加接近于 Linux Mint 的感觉。

### 在 Ubuntu 上使用 Cinnamon 桌面环境

Cinnamon 安装完成后，退出当前会话，在登录界面，点击用户名旁边的 Ubuntu 符号：

之后，它将会显示所有系统可用的桌面环境。选择 Cinnamon。

现在你应该已经登录到有着 Cinnamon 桌面环境的 Ubuntu 中了。你还可以通过同样的方式再回到 Unity 桌面。这里有一张以 Cinnamon 做为桌面环境的 Ubuntu 桌面截图。

看起来是不是像极了 Linux Mint。此外，我并没有发现任何有关 Cinnamon 和 Unity 的兼容性问题。在 Unity 和 Cinnamon 来回切换，它们也依旧工作的很完美。

#### 从 Ubuntu 卸载 Cinnamon

如果你想卸载 Cinnamon，可以使用 PPA Purge 来完成。首先安装 PPA Purge：

```
sudo apt-get install ppa-purge
```

安装完成之后，使用下面的命令去移除该 PPA：

```
sudo ppa-purge ppa:embrosyn/cinnamon
```

更多的信息，我建议你去阅读 [如何从 Linux 移除 PPA](https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/) 这篇文章。

我希望这篇文章能够帮助你在 Ubuntu 上安装 Cinnamon。也可以分享一下你使用 Cinnamon 的经验。

---

via: <https://itsfoss.com/install-cinnamon-on-ubuntu/>

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

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


在 Linux 上操作目录

# 在 Linux 上操作目录

<img src="content_image/album_201809_29_235308iemarrwrgwoye4ar.jpg" alt="" title="">

>
> 让我们继续学习一下 Linux 文件系统的树形结构，并展示一下如何在其中创建你的目录。
>
>
>

如果你不熟悉本系列（以及 Linux），[请查看我们的第一部分](/article-9798-1.html)。在那篇文章中，我们贯穿了 Linux 文件系统的树状结构（或者更确切地说是<ruby> 文件层次结构标准 <rt>  File Hierarchy Standard </rt></ruby>，FHS）。我建议你仔细阅读，确保你理解自己能安全的做哪些操作。因为这一次，我将向你展示目录操作的魅力。

### 新建目录

在破坏之前，先让我们来创建。首先，打开一个终端窗口并使用命令 `mkdir` 创建一个新目录，如下所示：

```
mkdir <directoryname>
```

如果你只输入了目录名称，该目录将显示在您当前所在目录中。如果你刚刚打开一个终端，你当前位置为你的家目录。在这个例子中，我们展示了将要创建的目录与你当前所处位置的关系：

```
$ pwd # 告知你当前所在位置（参见第一部分）
/home/<username>
$ mkdir newdirectory # 创建 /home/<username>/newdirectory
```

（注：你不用输入 `＃` 后面的文本。`#` 后面的文本为注释内容，用于解释发生了什么。它会被 shell 忽略，不会被执行）。

你可以在当前位置中已经存在的某个目录下创建新的目录，方法是在命令行中指定它：

```
mkdir Documents/Letters
```

这将在 `Documents` 目录中创建 `Letters` 目录。

你还可以在路径中使用 `..` 在当前目录的上一级目录中创建目录。假设你进入刚刚创建的 `Documents/Letters/` 目录，并且想要创建`Documents/Memos/` 目录。你可以这样做：

```
cd Documents/Letters # 进入到你刚刚创建的 Letters/ 目录
mkdir ../Memos
```

同样，以上所有内容都是相对于你当前的位置做的。这就是使用了相对路径。

你还可以使用目录的绝对路径：这意味着告诉 `mkdir` 命令将目录放在和根目录（`/`）有关的位置：

```
mkdir /home/<username>/Documents/Letters
```

在上面的命令中将 `<username>` 更改为你的用户名，这相当于从你的主目录执行 `mkdir Documents/Letters`，通过使用绝对路径你可以在目录树中的任何位置完成这项工作。

无论你使用相对路径还是绝对路径，只要命令成功执行，`mkdir` 将静默的创建新目录，而没有任何明显的反馈。只有当遇到某种问题时，`mkdir`才会在你敲下回车键后打印一些反馈。

与大多数其他命令行工具一样，`mkdir` 提供了几个有趣的选项。 `-p` 选项特别有用，因为它允许你嵌套创建目录，即使目录不存在也可以。例如，要在 `Documents/` 中创建一个目录存放写给妈妈的信，你可以这样做：

```
mkdir -p Documents/Letters/Family/Mom
```

`mkdir` 会创建 `Mom/` 之上的整个目录分支，并且也会创建 `Mom/` 目录，无论其上的目录在你敲入该命令时是否已经存在。

你也可以用空格来分隔目录名，来同时创建几个目录：

```
mkdir Letters Memos Reports
```

这将在当前目录下创建目录 `Letters`、`Memos` 和 `Reports`。

### 目录名中可怕的空格

……这带来了目录名称中关于空格的棘手问题。你能在目录名中使用空格吗？是的你可以。那么建议你使用空格吗？不，绝对不建议。空格使一切变得更加复杂，并且可能是危险的操作。

假设您要创建一个名为 `letters mom/` 的目录。如果你不知道如何更好处理，你可能会输入：

```
mkdir letters mom
```

但这是错误的！错误的！错误的！正如我们在上面介绍的，这将创建两个目录 `letters/` 和 `mom/`，而不是一个目录 `letters mom/`。

得承认这是一个小麻烦：你所要做的就是删除这两个目录并重新开始，这没什么大不了。

可是等等！删除目录可是个危险的操作。想象一下，你使用图形工具[Dolphin](https://userbase.kde.org/Dolphin) 或 [Nautilus](https://projects-old.gnome.org/nautilus/screenshots.html) 创建了目录 `letters mom/`。如果你突然决定从终端删除目录 `letters mom`，并且您在同一目录下有另一个名为 `letters` 的目录，并且该目录中包含重要的文档，结果你为了删除错误的目录尝试了以下操作：

```
rmdir letters mom
```

你将会有删除目录 letters 的风险。这里说“风险”，是因为幸运的是`rmdir` 这条用于删除目录的指令，有一个内置的安全措施，如果你试图删除一个非空目录时，它会发出警告。

但是，下面这个：

```
rm -Rf letters mom
```

（注：这是删除目录及其内容的一种非常标准的方式）将完全删除 `letters/` 目录，甚至永远不会告诉你刚刚发生了什么。）

`rm` 命令用于删除文件和目录。当你将它与选项 `-R`（递归删除）和 `-f`（强制删除）一起使用时，它会深入到目录及其子目录中，删除它们包含的所有文件，然后删除子目录本身，然后它将删除所有顶层目录中的文件，再然后是删除目录本身。

`rm -Rf` 是你必须非常小心处理的命令。

我的建议是，你可以使用下划线来代替空格，但如果你仍然坚持使用空格，有两种方法可以使它们起作用。您可以使用单引号或双引号，如下所示：

```
mkdir 'letters mom'
mkdir "letters dad"
```

或者，你可以转义空格。有些字符对 shell 有特殊意义。正如你所见，空格用于在命令行上分隔选项和参数。 “分离选项和参数”属于“特殊含义”范畴。当你想让 shell 忽略一个字符的特殊含义时，你需要转义，你可以在它前面放一个反斜杠（`\`）如：

```
mkdir letters\ mom
mkdir letter\ dad
```

还有其他特殊字符需要转义，如撇号或单引号（`'`），双引号（`“`）和＆符号（`＆`）：

```
mkdir mom\ \&\ dad\'s\ letters
```

我知道你在想什么：如果反斜杠有一个特殊的含义（即告诉 shell 它必须转义下一个字符），这也使它成为一个特殊的字符。然后，你将如何转义转义字符（`\`）？

事实证明，你转义任何其他特殊字符都是同样的方式：

```
mkdir special\\characters
```

这将生成一个名为 `special\characters/` 的目录。

感觉困惑？当然。这就是为什么你应该避免在目录名中使用特殊字符，包括空格。

以防误操作你可以参考下面这个记录特殊字符的列表。（LCTT 译注：此处原文链接丢失。）

### 总结

* 使用 `mkdir <directory name>` 创建新目录。
* 使用 `rmdir <directory name>` 删除目录（仅在目录为空时才有效）。
* 使用 `rm -Rf <directory name>` 来完全删除目录及其内容 —— 请务必谨慎使用。
* 使用相对路径创建相对于当前目录的目录： `mkdir newdir`。
* 使用绝对路径创建相对于根目录(`/`)的目录: `mkdir /home/<username>/newdir`。
* 使用 `..` 在当前目录的上级目录中创建目录： `mkdir ../newdir`。
* 你可以通过在命令行上使用空格分隔目录名来创建多个目录: `mkdir onedir twodir threedir`。
* 同时创建多个目录时，你可以混合使用相对路径和绝对路径: `mkdir onedir twodir /home/<username>/threedir`。
* 在目录名称中使用空格和特殊字符真的会让你很头疼，你最好不要那样做。

有关更多信息，您可以查看 `mkdir`、`rmdir` 和 `rm` 的手册:

```
man mkdir
man rmdir
man rm
```

要退出手册页，请按键盘 `q` 键。

### 下次预告

在下一部分中，你将学习如何创建、修改和删除文件，以及你需要了解的有关权限和特权的所有信息!

通过 Linux 基金会和 edX 免费提供的[“Introduction to Linux”](https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux)课程了解有关Linux的更多信息。

---

via: <https://www.linux.com/blog/learn/2018/5/manipulating-directories-linux>

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

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


如何让 Ping 的输出更简单易读

Summary: 如果你一直在寻找可视化显示 ping 命令输出的工具，那么 Prettyping 肯定会有所帮助。

# 如何让 Ping 的输出更简单易读

众所周知，`ping` 命令可以用来检查目标主机是否可达。使用 `ping` 命令的时候，会发送一个 ICMP Echo 请求，通过目标主机的响应与否来确定目标主机的状态。如果你经常使用 `ping` 命令，你可以尝试一下 `prettyping`。Prettyping 只是将一个标准的 ping 工具增加了一层封装，在运行标准 `ping` 命令的同时添加了颜色和 unicode 字符解析输出，所以它的输出更漂亮紧凑、清晰易读。它是用 `bash` 和 `awk` 编写的自由开源工具，支持大部分类 Unix 操作系统，包括 GNU/Linux、FreeBSD 和 Mac OS X。Prettyping 除了美化 `ping` 命令的输出，还有很多值得注意的功能。

* 检测丢失的数据包并在输出中标记出来。
* 显示实时数据。每次收到响应后，都会更新统计数据，而对于普通 `ping` 命令，只会在执行结束后统计。
* 可以灵活处理“未知信息”（例如错误信息），而不搞乱输出结果。
* 能够避免输出重复的信息。
* 兼容常用的 `ping` 工具命令参数。
* 能够由普通用户执行。
* 可以将输出重定向到文件中。
* 不需要安装，只需要下载二进制文件，赋予可执行权限即可执行。
* 快速且轻巧。
* 输出结果清晰直观。

### 安装 Prettyping

如上所述，Prettyping 是一个绿色软件，不需要任何安装，只要使用以下命令下载 Prettyping 二进制文件：

```
$ curl -O https://raw.githubusercontent.com/denilsonsa/prettyping/master/prettyping
```

将二进制文件放置到 `$PATH`（例如 `/usr/local/bin`）中：

```
$ sudo mv prettyping /usr/local/bin
```

然后对其赋予可执行权限：

```
$ sudo chmod +x /usr/local/bin/prettyping
```

就可以使用了。

### 让 ping 的输出清晰易读

安装完成后，通过 `prettyping` 来 ping 任何主机或 IP 地址，就可以以图形方式查看输出。

```
$ prettyping ostechnix.com
```

输出效果大概会是这样：

如果你不带任何参数执行 `prettyping`，它就会一直运行直到被 `ctrl + c` 中断。

由于 Prettyping 只是一个对普通 `ping` 命令的封装，所以常用的 ping 参数也是有效的。例如使用 `-c 5` 来指定 ping 一台主机的 5 次：

```
$ prettyping -c 5 ostechnix.com
```

Prettyping 默认会使用彩色输出，如果你不喜欢彩色的输出，可以加上 `--nocolor` 参数：

```
$ prettyping --nocolor ostechnix.com
```

同样的，也可以用 `--nomulticolor` 参数禁用多颜色支持：

```
$ prettyping --nomulticolor ostechnix.com
```

使用 `--nounicode` 参数禁用 unicode 字符：

如果你的终端不支持 UTF-8，或者无法修复系统中的 unicode 字体，只需要加上 `--nounicode` 参数就能轻松解决。

Prettyping 支持将输出的内容重定向到文件中，例如执行以下这个命令会将 `prettyping ostechnix.com` 的输出重定向到 `ostechnix.txt` 中：

```
$ prettyping ostechnix.com | tee ostechnix.txt
```

Prettyping 还有很多选项帮助你完成各种任务，例如：

* 启用/禁用延时图例（默认启用）
* 强制按照终端的格式输出（默认自动）
* 在统计数据中统计最后的 n 次 ping（默认 60 次）
* 覆盖对终端尺寸的自动检测
* 指定 awk 解释器路径（默认：`awk`）
* 指定 ping 工具路径（默认：`ping`）

查看帮助文档可以了解更多：

```
$ prettyping --help
```

尽管 Prettyping 没有添加任何额外功能，但我个人喜欢它的这些优点：

* 实时统计 —— 可以随时查看所有实时统计信息，标准 `ping` 命令只会在命令执行结束后才显示统计信息。
* 紧凑的显示 —— 可以在终端看到更长的时间跨度。
* 检测丢失的数据包并显示出来。

如果你一直在寻找可视化显示 `ping` 命令输出的工具，那么 Prettyping 肯定会有所帮助。尝试一下，你不会失望的。

---

via: <https://www.ostechnix.com/prettyping-make-the-output-of-ping-command-prettier-and-easier-to-read/>

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

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


书评：《算法之美（ Algorithms to Live By ）》

Summary: 《算法之美》提出的问题是：“我们可以反过来吗”——我们可以通过学习计算机科学解决问题的方式来帮助我们做出日常决定吗？

# 书评：《算法之美（ Algorithms to Live By ）》

<img src="content_image/album_201810_01_112752vuko5cufxojjmo4x.png" alt="" title="">

又一次为了工作图书俱乐部而读书。除了其它我亲自推荐的书，这是我至今最喜爱的书。

作为计算机科学基础之一的研究领域是算法：我们如何高效地用计算机程序解决问题？这基本上属于数学领域，但是这很少关于理想的或理论上的解决方案，而是更在于最高效地利用有限的资源获得一个充分（如果不能完美）的答案。其中许多问题要么是日常的生活问题，要么与人们密切相关。毕竟，计算机科学的目的是为了用计算机解决实际问题。《<ruby> 算法之美 <rt>  Algorithms to Live By </rt></ruby>》提出的问题是：“我们可以反过来吗”——我们可以通过学习计算机科学解决问题的方式来帮助我们做出日常决定吗？

本书的十一个章节有很多有趣的内容，但也有一个有趣的主题：人类早已擅长这一点。很多章节以一个算法研究和对问题的数学分析作为开始，接着深入到探讨如何利用这些结果做出更好的决策，然后讨论关于人类真正会做出的决定的研究，之后，考虑到典型生活情境的限制，会发现人类早就在应用我们提出的最佳算法的特殊版本了。这往往会破坏本书的既定目标，值得庆幸的是，它决不会破坏对一般问题的有趣讨论，即计算机科学如何解决它们，以及我们对这些问题的数学和技术形态的了解。我认为这本书的自助效用比作者打算的少一些，但有很多可供思考的东西。

（也就是说，值得考虑这种一致性是否太少了，因为人类已经擅长这方面了，更因为我们的算法是根据人类直觉设计的。可能我们的最佳算法只是反映了人类的思想。在某些情况下，我们发现我们的方案和数学上的典范不一样，但是在另一些情况下，它们仍然是我们当下最好的猜想。)

这是那种章节列表是书评里重要部分的书。这里讨论的算法领域有最优停止、探索和利用决策（什么时候带着你发现的最好东西走，以及什么时候寻觅更好的东西），以及排序、缓存、调度、贝叶斯定理（一般还有预测）、创建模型时的过拟合、放松（解决容易的问题而不是你的实际问题）、随机算法、一系列网络算法，最后还有游戏理论。其中每一项都有有用的见解和发人深省的讨论——这些有时显得十分理论化的概念令人吃惊地很好地映射到了日常生活。这本书以一段关于“可计算的善意”的讨论结束：鼓励减少你自己和你交往的人所需的计算和复杂性惩罚。

如果你有计算机科学背景（就像我一样），其中许多都是熟悉的概念，而且你因为被普及了很多新东西或许会有疑惑。然而，请给这本书一个机会，类比法没你担忧的那么令人紧张。作者既小心又聪明地应用了这些原则。这本书令人惊喜地通过了一个重要的合理性检查：涉及到我知道或反复思考过的主题的章节很少有或没有明显的错误，而且能讲出有用和重要的事情。比如，调度的那一章节毫不令人吃惊地和时间管理有关，通过直接跳到时间管理问题的核心而胜过了半数的时间管理类书籍：如果你要做一个清单上的所有事情，你做这些事情的顺序很少要紧，所以最难的调度问题是决定不做哪些事情而不是做这些事情的顺序。

作者在贝叶斯定理这一章节中的观点完全赢得了我的心。本章的许多内容都是关于贝叶斯先验的，以及一个人对过去事件的了解为什么对分析未来的概率很重要。作者接着讨论了著名的棉花糖实验。即给了儿童一个棉花糖以后，儿童被研究者告知如果他们能够克制自己不吃这个棉花糖，等到研究者回来时，会给他们两个棉花糖。克制自己不吃棉花糖（在心理学文献中叫作“延迟满足”）被发现与未来几年更好的生活有关。这个实验多年来一直被引用和滥用于各种各样的宣传，关于选择未来的收益放弃即时的快乐从而拥有成功的生活，以及生活中的失败是因为无法延迟满足。更多的邪恶分析（当然）将这种能力与种族联系在一起，带有可想而知的种族主义结论。

我对棉花糖实验有点兴趣。这是一个百分百让我愤怒咆哮的话题。

《算法之美》是我读过的唯一提到了棉花糖实验并应用了我认为更有说服力的分析的书。这不是一个关于儿童天赋的实验，这是一个关于他们的贝叶斯先验的实验。什么时候立即吃棉花糖而不是等待奖励是完全合理的？当他们过去的经历告诉他们成年人不可靠，不可信任，会在不可预测的时间内消失并且撒谎的时候。而且，更好的是，作者用我之前没有听说过的后续研究和观察支持了这一分析，观察到的内容是，一些孩子会等待一段时间然后“放弃”。如果他们下意识地使用具有较差先验的贝叶斯模型，这就完全合情合理。

这是一本很好的书。它可能在某些地方的尝试有点太勉强（数学上最优停止对于日常生活的适用性比我认为作者想要表现的更加偶然和牵强附会），如果你学过算法，其中一些内容会感到熟悉，但是它的行文思路清晰，简洁，而且编辑得非常好。这本书没有哪一部分对不起它所受到的欢迎，书中的讨论贯穿始终。如果你发现自己“已经知道了这一切”，你可能还会在接下来几页中遇到一个新的概念或一个简洁的解释。有时作者会做一些我从没想到但是回想起来正确的联系，比如将网络协议中的指数退避和司法系统中的选择惩罚联系起来。还有意识到我们的现代通信世界并不是一直联系的，它是不断缓冲的，我们中的许多人正深受缓冲膨胀这一独特现象的苦恼。

我认为你并不必须是计算机科学专业或者精通数学才能读这本书。如果你想深入，每章的结尾都有许多数学上的细节，但是正文总是易读而清晰，至少就我所知是这样（作为一个以计算机科学为专业并学到了很多数学知识的人，你至少可以有保留地相信我）。即使你已经钻研了多年的算法，这本书仍然可以提供很多东西。

这本书我读得越多越喜欢。如果你喜欢阅读这种对生活的分析，我当然是赞成的。

Rating: 9 out of 10

Reviewed: 2017-10-22

---

via: [https://www.eyrie.org/~eagle/reviews/books/1-62779-037-3.html](https://www.eyrie.org/%7Eeagle/reviews/books/1-62779-037-3.html)

作者：[Brian Christian;Tom Griffiths](https://www.eyrie.org) 译者：[GraveAccent](https://github.com/GraveAccent) 校对：[wxy](https://github.com/wxy)

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


一些提高开源代码安全性的工具

Summary: 开源软件的迅速普及带来了对健全安全实践的需求。

开源软件的迅速普及带来了对健全安全实践的需求。

# 一些提高开源代码安全性的工具

>
> 开源软件的迅速普及带来了对健全安全实践的需求。
>
>
>

<img src="content_image/album_201810_01_121112gw07i0bipivsniip.jpg" alt="" title="">

虽然目前开源依然发展势头较好，并被广大的厂商所采用，然而最近由 Black Duck 和 Synopsys 发布的 [2018 开源安全与风险评估报告](https://www.blackducksoftware.com/open-source-security-risk-analysis-2018)指出了一些存在的风险，并重点阐述了对于健全安全措施的需求。这份报告的分析资料素材来自经过脱敏后的 1100 个商业代码库，这些代码所涉及：自动化、大数据、企业级软件、金融服务业、健康医疗、物联网、制造业等多个领域。

这份报告强调开源软件正在被大量的使用，扫描结果中有 96% 的应用都使用了开源组件。然而，报告还指出许多其中存在很多漏洞。具体在 [这里](https://www.prnewswire.com/news-releases/synopsys-report-finds-majority-of-software-plagued-by-known-vulnerabilities-and-license-conflicts-as-open-source-adoption-soars-300648367.html)：

* 令人担心的是扫描的所有结果中，有 78% 的代码库存在至少一个开源的漏洞，平均每个代码库有 64 个漏洞。
* 在经过代码审计过后代码库中，发现超过 54% 的漏洞经验证是高危漏洞。
* 17% 的代码库包括一种已经早已公开的漏洞，包括：Heartbleed、Logjam、Freak、Drown、Poddle。

Synopsys 旗下 Black Duck 的技术负责人 Tim Mackey 称，“这份报告清楚的阐述了：随着开源软件正在被企业广泛的使用，企业与组织也应当使用一些工具来检测可能出现在这些开源软件中的漏洞，以及管理其所使用的开源软件的方式是否符合相应的许可证规则。”

确实，随着越来越具有影响力的安全威胁出现，历史上从未有过我们目前对安全工具和实践的需求。大多数的组织已经意识到网络与系统管理员需要具有相应的较强的安全技能和安全证书。[在一篇文章中](https://www.linux.com/blog/sysadmin-ebook/2017/8/future-proof-your-sysadmin-career-locking-down-security)，我们给出一些具有较大影响力的工具、认证和实践。

Linux 基金会已经在安全方面提供了许多关于安全的信息与教育资源。比如，Linux 社区提供了许多针对特定平台的免费资源，其中 [Linux 工作站安全检查清单](/article-6753-1.html) 其中提到了很多有用的基础信息。线上的一些发表刊物也可以提升用户针对某些平台对于漏洞的保护，如：[Fedora 安全指南](https://docs.fedoraproject.org/en-US/Fedora/19/html/Security_Guide/index.html)、[Debian 安全手册](https://www.debian.org/doc/manuals/securing-debian-howto/index.en.html)。

目前被广泛使用的私有云平台 OpenStack 也加强了关于基于云的智能安全需求。根据 Linux 基金会发布的 [公有云指南](https://www.linux.com/publications/2016-guide-open-cloud)：“据 Gartner 的调研结果，尽管公有云的服务商在安全审查和提升透明度方面做的都还不错，安全问题仍然是企业考虑向公有云转移的最重要的考量之一。”

无论是对于组织还是个人，千里之堤毁于蚁穴，这些“蚁穴”无论是来自路由器、防火墙、VPN 或虚拟机都可能导致灾难性的后果。以下是一些免费的工具可能对于检测这些漏洞提供帮助：

* [Wireshark](https://www.wireshark.org/)，流量包分析工具
* [KeePass Password Safe](http://keepass.info/)，自由开源的密码管理器
* [Malwarebytes](https://www.malwarebytes.com/)，免费的反病毒和勒索软件工具
* [NMAP](http://searchsecurity.techtarget.co.uk/tip/Nmap-tutorial-Nmap-scan-examples-for-vulnerability-discovery)，安全扫描器
* [NIKTO](https://cirt.net/Nikto2)，开源的 web 服务器扫描器
* [Ansible](https://www.ansible.com/)，自动化的配置运维工具，可以辅助做安全基线
* [Metasploit](https://www.metasploit.com/)，渗透测试工具，可辅助理解攻击向量

这里有一些对上面工具讲解的视频。比如 [Metasploit 教学](http://www.computerweekly.com/tutorial/The-Metasploit-Framework-Tutorial-PDF-compendium-Your-ready-reckoner)、[Wireshark 教学](https://www.youtube.com/watch?v=TkCSr30UojM)。还有一些传授安全技能的免费电子书，比如：由 Ibrahim Haddad 博士和 Linux 基金会共同出版的[并购过程中的开源审计](https://www.linuxfoundation.org/resources/open-source-audits-merger-acquisition-transactions/)，里面阐述了多条在技术平台合并过程中，因没有较好的进行开源审计，从而引发的安全问题。当然，书中也记录了如何在这一过程中进行代码合规检查、准备以及文档编写。

同时，我们 [之前提到的一个免费的电子书](https://www.linux.com/news/networking-security-storage-docker-containers-free-ebook-covers-essentials)， 由来自 [The New Stack](http://thenewstack.io/ebookseries/) 编写的“Docker 与容器中的网络、安全和存储”，里面也提到了关于加强容器网络安全的最新技术，以及 Docker 本身可提供的关于提升其网络的安全与效率的最佳实践。这本电子书还记录了关于如何构建安全容器集群的最佳实践。

所有这些工具和资源，可以在很大的程度上预防安全问题，正如人们所说的未雨绸缪，考虑到一直存在的安全问题，现在就应该开始学习这些安全合规资料与工具。

想要了解更多的安全、合规以及开源项目问题，点击[这里](https://www.linuxfoundation.org/projects/security-compliance/)。

---

via: <https://www.linux.com/blog/2018/5/free-resources-securing-your-open-source-code>

作者：[Sam Dean](https://www.linux.com/users/sam-dean) 选题：[lujun9972](https://github.com/lujun9972) 译者：[sd886393](https://github.com/sd886393) 校对：[wxy](https://github.com/wxy)

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


在 Linux 下截屏并编辑的最佳工具

# 在 Linux 下截屏并编辑的最佳工具

>
> 有几种获取屏幕截图并对其进行添加文字、箭头等编辑的方法，这里提及的的屏幕截图工具在 Ubuntu 和其它主流 Linux 发行版中都能够使用。
>
>
>

当我的主力操作系统从 Windows 转换到 Ubuntu 的时候，首要考虑的就是屏幕截图工具的可用性。尽管使用默认的键盘快捷键也可以获取屏幕截图，但如果使用屏幕截图工具，可以更方便地对屏幕截图进行编辑。

本文将会介绍在不适用第三方工具的情况下，如何通过系统自带的方法和工具获取屏幕截图，另外还会介绍一些可用于 Linux 的最佳截图工具。

### 方法 1：在 Linux 中截图的默认方式

你想要截取整个屏幕？屏幕中的某个区域？某个特定的窗口？

如果只需要获取一张屏幕截图，不对其进行编辑的话，那么键盘的默认快捷键就可以满足要求了。而且不仅仅是 Ubuntu ，绝大部分的 Linux 发行版和桌面环境都支持以下这些快捷键：

* `PrtSc` – 获取整个屏幕的截图并保存到 Pictures 目录。
* `Shift + PrtSc` – 获取屏幕的某个区域截图并保存到 Pictures 目录。
* `Alt + PrtSc` –获取当前窗口的截图并保存到 Pictures 目录。
* `Ctrl + PrtSc` – 获取整个屏幕的截图并存放到剪贴板。
* `Shift + Ctrl + PrtSc` – 获取屏幕的某个区域截图并存放到剪贴板。
* `Ctrl + Alt + PrtSc` – 获取当前窗口的 截图并存放到剪贴板。

如上所述，在 Linux 中使用默认的快捷键获取屏幕截图是相当简单的。但如果要在不把屏幕截图导入到其它应用程序的情况下对屏幕截图进行编辑，还是使用屏幕截图工具比较方便。

### 方法 2：在 Linux 中使用 Flameshot 获取屏幕截图并编辑

功能概述：

* 注释 (高亮、标示、添加文本、框选)
* 图片模糊
* 图片裁剪
* 上传到 Imgur
* 用另一个应用打开截图

Flameshot 在去年发布到 [GitHub](https://github.com/lupoDharkael/flameshot)，并成为一个引人注目的工具。

如果你需要的是一个能够用于标注、模糊、上传到 imgur 的新式截图工具，那么 Flameshot 是一个好的选择。

下面将会介绍如何安装 Flameshot 并根据你的偏好进行配置。

如果你用的是 Ubuntu，那么只需要在 Ubuntu 软件中心上搜索，就可以找到 Flameshot 进而完成安装了。要是你想使用终端来安装，可以执行以下命令：

```
sudo apt install flameshot
```

如果你在安装过程中遇到问题，可以按照[官方的安装说明](https://github.com/lupoDharkael/flameshot#installation)进行操作。安装完成后，你还需要进行配置。尽管可以通过搜索来随时启动 Flameshot，但如果想使用 `PrtSc` 键触发启动，则需要指定对应的键盘快捷键。以下是相关配置步骤：

* 进入系统设置中的“键盘设置”
* 页面中会列出所有现有的键盘快捷键，拉到底部就会看见一个 “+” 按钮
* 点击 “+” 按钮添加自定义快捷键并输入以下两个字段：
	+ “名称”： 任意名称均可。
	+ “命令”： `/usr/bin/flameshot gui`
* 最后将这个快捷操作绑定到 `PrtSc` 键上，可能会提示与系统的截图功能相冲突，但可以忽略掉这个警告。

配置之后，你的自定义快捷键页面大概会是以下这样：

*将键盘快捷键映射到 Flameshot*

### 方法 3：在 Linux 中使用 Shutter 获取屏幕截图并编辑

功能概述：

* 注释 (高亮、标示、添加文本、框选)
* 图片模糊
* 图片裁剪
* 上传到图片网站

[Shutter](http://shutter-project.org/) 是一个对所有主流 Linux 发行版都适用的屏幕截图工具。尽管最近已经不太更新了，但仍然是操作屏幕截图的一个优秀工具。

在使用过程中可能会遇到这个工具的一些缺陷。Shutter 在任何一款最新的 Linux 发行版上最常见的问题就是由于缺少了任务栏上的程序图标，导致默认禁用了编辑屏幕截图的功能。 对于这个缺陷，还是有解决方案的。你只需要跟随我们的教程[在 Shutter 中修复这个禁止编辑选项并将程序图标在任务栏上显示出来](https://itsfoss.com/shutter-edit-button-disabled/)。问题修复后，就可以使用 Shutter 来快速编辑屏幕截图了。

同样地，在软件中心搜索也可以找到进而安装 Shutter，也可以在基于 Ubuntu 的发行版中执行以下命令使用命令行安装：

```
sudo apt install shutter
```

类似 Flameshot，你可以通过搜索 Shutter 手动启动它，也可以按照相似的方式设置自定义快捷方式以 `PrtSc` 键唤起 Shutter。

如果要指定自定义键盘快捷键，只需要执行以下命令：

```
shutter -f
```

### 方法 4：在 Linux 中使用 GIMP 获取屏幕截图

功能概述：

* 高级图像编辑功能（缩放、添加滤镜、颜色校正、添加图层、裁剪等）
* 截取某一区域的屏幕截图

如果需要对屏幕截图进行一些预先编辑，GIMP 是一个不错的选择。

通过软件中心可以安装 GIMP。如果在安装时遇到问题，可以参考其[官方网站的安装说明](https://www.gimp.org/downloads/)。

要使用 GIMP 获取屏幕截图，需要先启动程序，然后通过 “File-> Create-> Screenshot” 导航。

打开 Screenshot 选项后，会看到几个控制点来控制屏幕截图范围。点击 “Snap” 截取屏幕截图，图像将自动显示在 GIMP 中可供编辑。

### 方法 5：在 Linux 中使用命令行工具获取屏幕截图

这一节内容仅适用于终端爱好者。如果你也喜欢使用终端，可以使用 “GNOME 截图工具”或 “ImageMagick” 或 “Deepin Scrot”，大部分流行的 Linux 发行版中都自带这些工具。

要立即获取屏幕截图，可以执行以下命令：

#### GNOME 截图工具（可用于 GNOME 桌面）

```
gnome-screenshot
```

GNOME 截图工具是使用 GNOME 桌面的 Linux 发行版中都自带的一个默认工具。如果需要延时获取屏幕截图，可以执行以下命令（这里的 `5` 是需要延迟的秒数）：

```
gnome-screenshot -d -5
```

#### ImageMagick

如果你的操作系统是 Ubuntu、Mint 或其它流行的 Linux 发行版，一般会自带 [ImageMagick](https://www.imagemagick.org/script/index.php) 这个工具。如果没有这个工具，也可以按照[官方安装说明](https://www.imagemagick.org/script/install-source.php)使用安装源来安装。你也可以在终端中执行这个命令：

```
sudo apt-get install imagemagick
```

安装完成后，执行下面的命令就可以获取到屏幕截图（截取整个屏幕）：

```
import -window root image.png
```

这里的 “image.png” 就是屏幕截图文件保存的名称。

要获取屏幕一个区域的截图，可以执行以下命令:

```
import image.png
```

#### Deepin Scrot

Deepin Scrot 是基于终端的一个较新的截图工具。和前面两个工具类似，一般自带于 Linux 发行版中。如果需要自行安装，可以执行以下命令：

```
sudo apt-get install scrot
```

安装完成后，使用下面这些命令可以获取屏幕截图。

获取整个屏幕的截图：

```
scrot myimage.png
```

获取屏幕某一区域的截图：

```
scrot -s myimage.png
```

### 总结

以上是一些在 Linux 上的优秀截图工具。当然还有很多截图工具没有提及（例如用于 KDE 发行版的 [Spectacle](https://www.kde.org/applications/graphics/spectacle/)），但相比起来还是上面几个工具更为好用。

如果你有比文章中提到的更好的截图工具，欢迎讨论！

---

via: <https://itsfoss.com/take-screenshot-linux/>

作者：[Ankush Das](https://itsfoss.com/author/ankush/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[HankChow](https://github.com/HankChow) 校对：[wxy](https://github.com/wxy)

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


openmediavault 入门：一个家庭 NAS 解决方案

Summary: 这个网络附属文件服务提供了一系列可靠的功能，并且易于安装和配置。

原创编译还是”原创“翻译？

这个网络附属文件服务提供了一系列可靠的功能，并且易于安装和配置。

# openmediavault 入门：一个家庭 NAS 解决方案

>
> 这个网络附属文件服务提供了一系列可靠的功能，并且易于安装和配置。
>
>
>

<img src="content_image/album_201810_02_121510fo9izi7w9f9w1koi.jpg" alt="" title="">

面对许多可供选择的云存储方案，一些人可能会质疑一个家庭 NAS（<ruby> 网络附属存储 <rt>  network-attached storage </rt></ruby>）服务器的价值。毕竟，当所有你的文件存储在云上，你就不需要为你自己云服务的维护、更新和安全担忧。

但是，这不完全对，是不是？你有一个家庭网络，所以你已经要负责维护网络的健康和安全。假定你已经维护一个家庭网络，那么[一个家庭 NAS](https://opensource.com/article/18/8/automate-backups-raspberry-pi)并不会增加额外负担。反而你能从少量的工作中得到许多的好处。

你可以为你家里所有的计算机进行备份（你也可以备份到其它地方）。构架一个存储电影、音乐和照片的媒体服务器，无需担心互联网连接是否连通。在家里的多台计算机上处理大型文件，不需要等待从互联网某个其它计算机传输这些文件过来。另外，可以让 NAS 与其他服务配合工作，如托管本地邮件或者家庭 Wiki。也许最重要的是，构架家庭 NAS，数据完全是你的，它始终处于在控制下，随时可访问。

接下来的问题是如何选择 NAS 方案。当然，你可以购买预先搭建好的商品，并在一天内搞定，但是这会有什么乐趣呢？实际上，尽管拥有一个能为你搞定一切的设备很棒，但是有一个可以修复和升级的钻机平台更棒。这就我近期的需求，我选择安装和配置 [openmediavault](https://openmediavault.org)。

### 为什么选择 openmediavault？

市面上有不少开源的 NAS 解决方案，其中有些肯定比 openmediavault 流行。当我询问周遭，例如 [freeNAS](https://freenas.org) 这样的最常被推荐给我。那么为什么我不采纳他们的建议呢？毕竟，用它的人更多。[基于 FreeNAS 官网的一份对比数据](http://www.freenas.org/freenas-vs-openmediavault/)，它包含了很多的功能，并且提供许多支持选项。这当然都对。但是 openmediavault 也不差。它实际上是基于 FreeNAS 早期版本的，虽然它在下载量和功能方面较少，但是对于我的需求而言，它已经相当足够了。

另外一个因素是它让我感到很舒适。openmediavault 的底层操作系统是 [Debian](https://www.debian.org/)，然而 FreeNAS 是 [FreeBSD](https://www.freebsd.org/)。由于我个人对 FreeBSD 不是很熟悉，因此如果我的 NAS 出现故障，必定难于在 FreeBSD 上修复故障。同样的，也会让我觉得难于优化或添加一些服务到这个机器上。当然，我可以学习 FreeBSD 以更熟悉它，但是我已经在家里构架了这个 NAS；我发现，如果完成它只需要较少的“学习机会”，那么构建 NAS 往往会更成功。

当然，每个人情况都不同，所以你要自己调研，然后作出最适合自己方案的决定。FreeNAS 对于许多人似乎都是不错的解决方案。openmediavault 正是适合我的解决方案。

### 安装与配置

在 [openmediavault 文档](https://openmediavault.readthedocs.io/en/latest/installation/index.html)里详细记录了安装步骤，所以我不在这里重述了。如果你曾经安装过任何一个 Linux 发行版，大部分安装步骤都是很类似的（虽然是在相对丑陋的 [Ncurses](https://invisible-island.net/ncurses/) 界面，而不像你或许在现代发行版里见到的）。我按照 [专用的驱动器](https://openmediavault.readthedocs.io/en/latest/installation/via_iso.html) 的说明来安装它。这些说明不但很好，而且相当精炼的。当你搞定这些步骤，就安装好了一个基本的系统，但是你还需要做更多才能真正构建好 NAS 来存储各种文件。例如，专用驱动器方式需要在硬盘驱动器上安装 openmediavault，但那是指你的操作系统的驱动器，而不是和网络上其他计算机共享的驱动器。你需要自己把这些建立起来并且配置好。

你要做的第一件事是加载用来管理的网页界面，并修改默认密码。这个密码和之前你安装过程设置的 root 密码是不同的。这是网页界面的管理员账号，默认的账户和密码分别是 `admin` 和 `openmediavault`，当你登入后要马上修改。

#### 设置你的驱动器

一旦你安装好 openmediavault，你需要它为你做一些工作。逻辑上的第一个步骤是设置好你即将用来作为存储的驱动器。在这里，我假定你已经物理上安装好它们了，所以接下来你要做的就是让 openmediavault 识别和配置它们。第一步是确保这些磁盘是可见的。侧边栏菜单有很多选项，而且被精心的归类了。选择“Storage -> Disks”。一旦你点击该菜单，你应该能够看到所有你已经安装到该服务器的驱动，包括那个你已经用来安装 openmediavault 的驱动器。如果你没有在那里看到所有驱动器，点击“Scan”按钮去看是否能够挂载它们。通常，这不会是一个问题。

你可以独立的挂载和设置这些驱动器用于文件共享，但是对于一个文件服务器，你会想要一些冗余。你想要能够把很多驱动器当作一个单一卷，并能够在某一个驱动器出现故障时恢复你的数据，或者空间不足时安装新驱动器。这意味你将需要一个 [RAID](https://en.wikipedia.org/wiki/RAID)。你想要的什么特定类型的 RAID 的这个主题是一个大坑，值得另写一篇文章专门来讲述它（而且已经有很多关于该主题的文章了），但是简而言之是你将需要不止一个驱动器，最好的情况下，你所有的驱动都存储一样的容量。

openmediavault 支持所有标准的 RAID 级别，所以这里很简单。可以在“Storage -> RAID Management”里配置你的 RAID。配置是相当简单的：点击“Create”按钮，在你的 RAID 阵列里选择你想要的磁盘和你想要使用的 RAID 级别，并给这个阵列一个名字。openmediavault 为你处理剩下的工作。这里没有复杂的命令行，也不需要试图记住 `mdadm` 命令的一些选项参数。在我的例子，我有六个 2TB 驱动器，设置成了 RAID 10。

当你的 RAID 构建好了，基本上你已经有一个地方可以存储东西了。你仅仅需要设置一个文件系统。正如你的桌面系统，一个硬盘驱动器在没有格式化的情况下是没什么用处的。所以下一个你要去的地方的是位于 openmediavault 控制面板里的“Storage -> File Systems”。和配置你的 RAID 一样，点击“Create”按钮，然后跟着提示操作。如果你在你的服务器上只有一个 RAID ，你应该可以看到一个像 `md0` 的东西。你也需要选择文件系统的类别。如果你不能确定，选择标准的 ext4 类型即可。

#### 定义你的共享

亲爱的！你有个地方可以存储文件了。现在你只需要让它在你的家庭网络中可见。可以从在 openmediavault 控制面板上的“Services”部分上配置。当谈到在网络上设置文件共享，主要有两个选择：NFS 或者 SMB/CIFS. 根据以往经验，如果你网络上的所有计算机都是 Linux 系统，那么你使用 NFS 会更好。然而，当你家庭网络是一个混合环境，是一个包含Linux、Windows、苹果系统和嵌入式设备的组合，那么 SMB/CIFS 可能会是你合适的选择。

这些选项不是互斥的。实际上，你可以在服务器上运行这两个服务，同时拥有这些服务的好处。或者你可以混合起来，如果你有一个特定的设备做特定的任务。不管你的使用场景是怎样，配置这些服务是相当简单。点击你想要的服务，从它配置中激活它，和在网络中设定你想要的共享文件夹为可见。在基于 SMB/CIFS 共享的情况下，相对于 NFS 多了一些可用的配置，但是一般用默认配置就挺好的，接着可以在默认基础上修改配置。最酷的事情是它很容易配置，同时也很容易在需要的时候修改配置。

#### 用户配置

基本上已将完成了。你已经在 RAID 中配置了你的驱动器。你已经用一种文件系统格式化了 RAID，并且你已经在格式化的 RAID 上设定了共享文件夹。剩下来的一件事情是配置那些人可以访问这些共享和可以访问多少。这个可以在“Access Rights Management”配置里设置。使用“User”和“Group”选项来设定可以连接到你共享文件夹的用户，并设定这些共享文件的访问权限。

一旦你完成用户配置，就几乎准备好了。你需要从不同客户端机器访问你的共享，但是这是另外一个可以单独写个文章的话题了。

玩得开心！

---

via: <https://opensource.com/article/18/9/openmediavault>

作者：[Jason van Gumster](https://opensource.com/users/mairin) 选题：[lujun9972](https://github.com/lujun9972) 译者：[jamelouis](https://github.com/jamelouis) 校对：[wxy](https://github.com/wxy)

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


备份安装的包并在全新安装的 Ubuntu 上恢复它们

# 备份安装的包并在全新安装的 Ubuntu 上恢复它们

<img src="content_image/album_201810_02_122431zx6c0c5u9bxgxhh7.png" alt="" title="">

在多个 Ubuntu 系统上安装同一组软件包是一项耗时且无聊的任务。你不会想花时间在多个系统上反复安装相同的软件包。在类似架构的 Ubuntu 系统上安装软件包时，有许多方法可以使这项任务更容易。你可以方便地通过 [Aptik](https://www.ostechnix.com/how-to-migrate-system-settings-and-data-from-an-old-system-to-a-newly-installed-ubuntu-system/) 并点击几次鼠标将以前的 Ubuntu 系统的应用程序、设置和数据迁移到新安装的系统中。或者，你可以使用软件包管理器（例如 APT）获取[备份的已安装软件包的完整列表](https://www.ostechnix.com/create-list-installed-packages-install-later-list-centos-ubuntu/#comment-12598)，然后在新安装的系统上安装它们。今天，我了解到还有另一个专用工具可以完成这项工作。来看一下 `apt-clone`，这是一个简单的工具，可以让你为 Debian/Ubuntu 系统创建一个已安装的软件包列表，这些软件包可以在新安装的系统或容器上或目录中恢复。

`apt-clone` 会帮助你处理你想要的情况，

* 在运行类似 Ubuntu（及衍生版）的多个系统上安装一致的应用程序。
* 经常在多个系统上安装相同的软件包。
* 备份已安装的应用程序的完整列表，并在需要时随时随地恢复它们。

在本简要指南中，我们将讨论如何在基于 Debian 的系统上安装和使用 `apt-clone`。我在 Ubuntu 18.04 LTS 上测试了这个程序，但它应该适用于所有基于 Debian 和 Ubuntu 的系统。

### 备份已安装的软件包并在新安装的 Ubuntu 上恢复它们

`apt-clone` 在默认仓库中有。要安装它，只需在终端输入以下命令：

```
$ sudo apt install apt-clone
```

安装后，只需创建已安装软件包的列表，并将其保存在你选择的任何位置。

```
$ mkdir ~/mypackages
$ sudo apt-clone clone ~/mypackages
```

上面的命令将我的 Ubuntu 中所有已安装的软件包保存在 `~/mypackages` 目录下名为 `apt-clone-state-ubuntuserver.tar.gz` 的文件中。

要查看备份文件的详细信息，请运行：

```
$ apt-clone info mypackages/apt-clone-state-ubuntuserver.tar.gz
Hostname: ubuntuserver
Arch: amd64
Distro: bionic
Meta:
Installed: 516 pkgs (33 automatic)
Date: Sat Sep 15 10:23:05 2018
```

如你所见，我的 Ubuntu 服务器总共有 516 个包。

现在，将此文件复制到 USB 或外部驱动器上，并转至要安装同一套软件包的任何其他系统。或者，你也可以将备份文件传输到网络上的系统，并使用以下命令安装软件包：

```
$ sudo apt-clone restore apt-clone-state-ubuntuserver.tar.gz
```

请注意，此命令将覆盖你现有的 `/etc/apt/sources.list` 并将安装/删除软件包。警告过你了！此外，只需确保目标系统是相同的 CPU 架构和操作系统。例如，如果源系统是 18.04 LTS 64 位，那么目标系统必须也是相同的。

如果你不想在系统上恢复软件包，可以使用 `--destination /some/location` 选项将克隆复制到这个文件夹中。

```
$ sudo apt-clone restore apt-clone-state-ubuntuserver.tar.gz --destination ~/oldubuntu
```

在此例中，上面的命令将软件包恢复到 `~/oldubuntu` 中。

有关详细信息，请参阅帮助部分：

```
$ apt-clone -h
```

或者手册页：

```
$ man apt-clone
```

建议阅读：

* [Systemback - 将 Ubuntu 桌面版和服务器版恢复到以前的状态](https://www.ostechnix.com/systemback-restore-ubuntu-desktop-and-server-to-previous-state/)
* [Cronopete - Linux 下的苹果时间机器](https://www.ostechnix.com/cronopete-apples-time-machine-clone-linux/)

就是这些了。希望这个有用。还有更多好东西。敬请期待!

干杯!

---

via: <https://www.ostechnix.com/backup-installed-packages-and-restore-them-on-freshly-installed-ubuntu-system/>

作者：[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/) 荣誉推出


如何在 Linux 中查看进程占用的端口号

# 如何在 Linux 中查看进程占用的端口号

<img src="content_image/album_201810_02_123805zpppw4h5z9bwd5ab.jpg" alt="" title="">

对于 Linux 系统管理员来说，清楚某个服务是否正确地绑定或监听某个端口，是至关重要的。如果你需要处理端口相关的问题，这篇文章可能会对你有用。

端口是 Linux 系统上特定进程之间逻辑连接的标识，包括物理端口和软件端口。由于 Linux 操作系统是一个软件，因此本文只讨论软件端口。软件端口始终与主机的 IP 地址和相关的通信协议相关联，因此端口常用于区分应用程序。大部分涉及到网络的服务都必须打开一个套接字来监听传入的网络请求，而每个服务都使用一个独立的套接字。

**推荐阅读：**

* [在 Linux 上查看进程 ID 的 4 种方法](https://www.2daygeek.com/how-to-check-find-the-process-id-pid-ppid-of-a-running-program-in-linux/)
* [在 Linux 上终止进程的 3 种方法](https://www.2daygeek.com/kill-terminate-a-process-in-linux-using-kill-pkill-killall-command/)

套接字是和 IP 地址、软件端口和协议结合起来使用的，而端口号对传输控制协议（TCP）和用户数据报协议（UDP）协议都适用，TCP 和 UDP 都可以使用 0 到 65535 之间的端口号进行通信。

以下是端口分配类别：

* 0 - 1023： 常用端口和系统端口
* 1024 - 49151： 软件的注册端口
* 49152 - 65535： 动态端口或私有端口

在 Linux 上的 `/etc/services` 文件可以查看到更多关于保留端口的信息。

```
# less /etc/services
# /etc/services:
# $Id: services,v 1.55 2013/04/14 ovasik Exp $
#
# Network services, Internet style
# IANA services version: last updated 2013-04-10
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, most entries here have two entries
# even if the protocol doesn't support UDP operations.
# Updated from RFC 1700, ``Assigned Numbers'' (October 1994). Not all ports
# are included, only the more common ones.
#
# The latest IANA port assignments can be gotten from
# http://www.iana.org/assignments/port-numbers
# The Well Known Ports are those from 0 through 1023.
# The Registered Ports are those from 1024 through 49151
# The Dynamic and/or Private Ports are those from 49152 through 65535
#
# Each line describes one service, and is of the form:
#
# service-name port/protocol [aliases ...] [# comment]

tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote
qotd 17/udp quote
msp 18/tcp # message send protocol (historic)
msp 18/udp # message send protocol (historic)
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
ftp-data 20/tcp
ftp-data 20/udp
# 21 is registered to ftp, but also used by fsp
ftp 21/tcp
ftp 21/udp fsp fspd
ssh 22/tcp # The Secure Shell (SSH) Protocol
ssh 22/udp # The Secure Shell (SSH) Protocol
telnet 23/tcp
telnet 23/udp
# 24 - private mail system
lmtp 24/tcp # LMTP Mail Delivery
lmtp 24/udp # LMTP Mail Delivery
```

可以使用以下六种方法查看端口信息。

* `ss`：可以用于转储套接字统计信息。
* `netstat`：可以显示打开的套接字列表。
* `lsof`：可以列出打开的文件。
* `fuser`：可以列出那些打开了文件的进程的进程 ID。
* `nmap`：是网络检测工具和端口扫描程序。
* `systemctl`：是 systemd 系统的控制管理器和服务管理器。

以下我们将找出 `sshd` 守护进程所使用的端口号。

### 方法 1：使用 ss 命令

`ss` 一般用于转储套接字统计信息。它能够输出类似于 `netstat` 输出的信息，但它可以比其它工具显示更多的 TCP 信息和状态信息。

它还可以显示所有类型的套接字统计信息，包括 PACKET、TCP、UDP、DCCP、RAW、Unix 域等。

```
# ss -tnlp | grep ssh
LISTEN 0 128 *:22 *:* users:(("sshd",pid=997,fd=3))
LISTEN 0 128 :::22 :::* users:(("sshd",pid=997,fd=4))
```

也可以使用端口号来检查。

```
# ss -tnlp | grep ":22"
LISTEN 0 128 *:22 *:* users:(("sshd",pid=997,fd=3))
LISTEN 0 128 :::22 :::* users:(("sshd",pid=997,fd=4))
```

### 方法 2：使用 netstat 命令

`netstat` 能够显示网络连接、路由表、接口统计信息、伪装连接以及多播成员。

默认情况下，`netstat` 会列出打开的套接字。如果不指定任何地址族，则会显示所有已配置地址族的活动套接字。但 `netstat` 已经过时了，一般会使用 `ss` 来替代。

```
# netstat -tnlp | grep ssh
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 997/sshd
tcp6 0 0 :::22 :::* LISTEN 997/sshd
```

也可以使用端口号来检查。

```
# netstat -tnlp | grep ":22"
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1208/sshd
tcp6 0 0 :::22 :::* LISTEN 1208/sshd
```

### 方法 3：使用 lsof 命令

`lsof` 能够列出打开的文件，并列出系统上被进程打开的文件的相关信息。

```
# lsof -i -P | grep ssh
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 11584 root 3u IPv4 27625 0t0 TCP *:22 (LISTEN)
sshd 11584 root 4u IPv6 27627 0t0 TCP *:22 (LISTEN)
sshd 11592 root 3u IPv4 27744 0t0 TCP vps.2daygeek.com:ssh->103.5.134.167:49902 (ESTABLISHED)
```

也可以使用端口号来检查。

```
# lsof -i tcp:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1208 root 3u IPv4 20919 0t0 TCP *:ssh (LISTEN)
sshd 1208 root 4u IPv6 20921 0t0 TCP *:ssh (LISTEN)
sshd 11592 root 3u IPv4 27744 0t0 TCP vps.2daygeek.com:ssh->103.5.134.167:49902 (ESTABLISHED)
```

### 方法 4：使用 fuser 命令

`fuser` 工具会将本地系统上打开了文件的进程的进程 ID 显示在标准输出中。

```
# fuser -v 22/tcp
 USER PID ACCESS COMMAND
22/tcp: root 1208 F.... sshd
 root 12388 F.... sshd
 root 49339 F.... sshd
```

### 方法 5：使用 nmap 命令

`nmap`（“Network Mapper”）是一款用于网络检测和安全审计的开源工具。它最初用于对大型网络进行快速扫描，但它对于单个主机的扫描也有很好的表现。

`nmap` 使用原始 IP 数据包来确定网络上可用的主机，这些主机的服务（包括应用程序名称和版本）、主机运行的操作系统（包括操作系统版本等信息）、正在使用的数据包过滤器或防火墙的类型，以及很多其它信息。

```
# nmap -sV -p 22 localhost

Starting Nmap 6.40 ( http://nmap.org ) at 2018-09-23 12:36 IST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000089s latency).
Other addresses for localhost (not scanned): 127.0.0.1
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)

Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.44 seconds
```

### 方法 6：使用 systemctl 命令

`systemctl` 是 systemd 系统的控制管理器和服务管理器。它取代了旧的 SysV 初始化系统管理，目前大多数现代 Linux 操作系统都采用了 systemd。

**推荐阅读：**

* [chkservice – Linux 终端上的 systemd 单元管理工具](https://www.2daygeek.com/chkservice-a-tool-for-managing-systemd-units-from-linux-terminal/)
* [如何查看 Linux 系统上正在运行的服务](https://www.2daygeek.com/how-to-check-all-running-services-in-linux/)

```
# systemctl status sshd
● sshd.service - OpenSSH server daemon
 Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
 Active: active (running) since Sun 2018-09-23 02:08:56 EDT; 6h 11min ago
 Docs: man:sshd(8)
 man:sshd_config(5)
 Main PID: 11584 (sshd)
 CGroup: /system.slice/sshd.service
 └─11584 /usr/sbin/sshd -D

Sep 23 02:08:56 vps.2daygeek.com systemd[1]: Starting OpenSSH server daemon...
Sep 23 02:08:56 vps.2daygeek.com sshd[11584]: Server listening on 0.0.0.0 port 22.
Sep 23 02:08:56 vps.2daygeek.com sshd[11584]: Server listening on :: port 22.
Sep 23 02:08:56 vps.2daygeek.com systemd[1]: Started OpenSSH server daemon.
Sep 23 02:09:15 vps.2daygeek.com sshd[11589]: Connection closed by 103.5.134.167 port 49899 [preauth]
Sep 23 02:09:41 vps.2daygeek.com sshd[11592]: Accepted password for root from 103.5.134.167 port 49902 ssh2
```

以上输出的内容显示了最近一次启动 `sshd` 服务时 `ssh` 服务的监听端口。但它不会将最新日志更新到输出中。

```
# systemctl status sshd
● sshd.service - OpenSSH server daemon
 Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
 Active: active (running) since Thu 2018-09-06 07:40:59 IST; 2 weeks 3 days ago
 Docs: man:sshd(8)
 man:sshd_config(5)
 Main PID: 1208 (sshd)
 CGroup: /system.slice/sshd.service
 ├─ 1208 /usr/sbin/sshd -D
 ├─23951 sshd: [accepted]
 └─23952 sshd: [net]

Sep 23 12:50:36 vps.2daygeek.com sshd[23909]: Invalid user pi from 95.210.113.142 port 51666
Sep 23 12:50:36 vps.2daygeek.com sshd[23909]: input_userauth_request: invalid user pi [preauth]
Sep 23 12:50:37 vps.2daygeek.com sshd[23911]: pam_unix(sshd:auth): check pass; user unknown
Sep 23 12:50:37 vps.2daygeek.com sshd[23911]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=95.210.113.142
Sep 23 12:50:37 vps.2daygeek.com sshd[23909]: pam_unix(sshd:auth): check pass; user unknown
Sep 23 12:50:37 vps.2daygeek.com sshd[23909]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=95.210.113.142
Sep 23 12:50:39 vps.2daygeek.com sshd[23911]: Failed password for invalid user pi from 95.210.113.142 port 51670 ssh2
Sep 23 12:50:39 vps.2daygeek.com sshd[23909]: Failed password for invalid user pi from 95.210.113.142 port 51666 ssh2
Sep 23 12:50:40 vps.2daygeek.com sshd[23911]: Connection closed by 95.210.113.142 port 51670 [preauth]
Sep 23 12:50:40 vps.2daygeek.com sshd[23909]: Connection closed by 95.210.113.142 port 51666 [preauth]
```

大部分情况下，以上的输出不会显示进程的实际端口号。这时更建议使用以下这个 `journalctl` 命令检查日志文件中的详细信息。

```
# journalctl | grep -i "openssh\|sshd"
Sep 23 02:08:56 vps138235.vps.ovh.ca sshd[997]: Received signal 15; terminating.
Sep 23 02:08:56 vps138235.vps.ovh.ca systemd[1]: Stopping OpenSSH server daemon...
Sep 23 02:08:56 vps138235.vps.ovh.ca systemd[1]: Starting OpenSSH server daemon...
Sep 23 02:08:56 vps138235.vps.ovh.ca sshd[11584]: Server listening on 0.0.0.0 port 22.
Sep 23 02:08:56 vps138235.vps.ovh.ca sshd[11584]: Server listening on :: port 22.
Sep 23 02:08:56 vps138235.vps.ovh.ca systemd[1]: Started OpenSSH server daemon.
```

---

via: <https://www.2daygeek.com/how-to-find-out-which-port-number-a-process-is-using-in-linux/>

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

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


如何在 vi 中创建快捷键

Summary: 那些常见编辑任务的快捷键可以使 Vi 编辑器更容易使用，更有效率。

那些常见编辑任务的快捷键可以使 Vi 编辑器更容易使用，更有效率。

# 如何在 vi 中创建快捷键

>
> 那些常见编辑任务的快捷键可以使 Vi 编辑器更容易使用，更有效率。
>
>
>

<img src="content_image/album_201810_02_231356ep5vy96385vy7s5s.jpg" alt="" title="">

学习使用 [vi 文本编辑器](http://ex-vi.sourceforge.net/) 确实得花点功夫，不过 vi 的老手们都知道，经过一小会儿的锻炼，就可以将基本的 vi 操作融汇贯通。我们都知道“肌肉记忆”，那么学习 vi 的过程可以称之为“手指记忆”。

当你抓住了基础的操作窍门之后，你就可以定制化地配置 vi 的快捷键，从而让其处理的功能更为强大、流畅。我希望下面描述的技术可以加速您的协作、编程和数据操作。

在开始之前，我想先感谢下 Chris Hermansen（是他雇佣我写了这篇文章）仔细地检查了我的另一篇关于使用 vi 增强版本 [Vim](https://www.vim.org/) 的文章。当然还有他那些我未采纳的建议。

首先，我们来说明下面几个惯例设定。我会使用符号 `<RET>` 来代表按下回车，`<SP>` 代表按下空格键，`CTRL-x` 表示一起按下 `Control` 键和 `x` 键（`x` 可以是需要的某个键）。

使用 `map` 命令来进行按键的映射。第一个例子是 `write` 命令，通常你之前保存使用这样的命令：

```
:w<RET>
```

虽然这里只有三个键，不过考虑到我用这个命令实在是太频繁了，我更想“一键”搞定它。在这里我选择逗号键，它不是标准的 vi 命令集的一部分。这样设置：

```
:map , :wCTRL-v<RET>
```

这里的 `CTRL-v` 事实上是对 `<RET>` 做了转义的操作，如果不加这个的话，默认 `<RET>` 会作为这条映射指令的结束信号，而非映射中的一个操作。 `CTRL-v` 后面所跟的操作会翻译为用户的实际操作，而非该按键平常的操作。

在上面的映射中，右边的部分会在屏幕中显示为 `:w^M`，其中 `^` 字符就是指代 `control`，完整的意思就是 `CTRL-m`，表示就是系统中一行的结尾。

目前来说，就很不错了。如果我编辑、创建了十二次文件，这个键位映射就可以省掉了 2\*12 次按键。不过这里没有计算你建立这个键位映射所花费的 11 次按键（计算 `CTRL-v` 和 `:` 均为一次按键）。虽然这样已经省了很多次，但是每次打开 vi 都要重新建立这个映射也会觉得非常麻烦。

幸运的是，这里可以将这些键位映射放到 vi 的启动配置文件中，让其在每次启动的时候自动读取：文件为 `.exrc`，对于 vim 是 `.vimrc`。只需要将这些文件放在你的用户根目录中即可，并在文件中每行写入一个键位映射，之后就会在每次启动 vi 生效直到你删除对应的配置。

在继续说明 `map` 其他用法以及其他的缩写机制之前，这里在列举几个我常用提高文本处理效率的 map 设置：

| 映射 | 显示为 |
| --- | --- |
| `:map X :xCTRL-v<RET>` | `:x^M` |
| `:map X ,:qCTRL-v<RET>` | `,:q^M` |

上面的 `map` 指令的意思是写入并关闭当前的编辑文件。其中 `:x` 是 vi 原本的命令，而下面的版本说明之前的 `map` 配置可以继续用作第二个 `map` 键位映射。

| 映射 | 显示为 |
| --- | --- |
| `:map v :e<SP>` | `:e` |

上面的指令意思是在 vi 编辑器内部切换文件，使用这个时候，只需要按 `v` 并跟着输入文件名，之后按 `<RET>` 键。

| 映射 | 显示为 |
| --- | --- |
| `:map CTRL-vCTRL-e :e<SP>#CTRL-v<RET>` | `:e #^M` |

`#` 在这里是 vi 中标准的符号，意思是最后使用的文件名。所以切换当前与上一个文件的方法就使用上面的映射。

| 映射 | 显示为 |
| --- | --- |
| `map CTRL-vCTRL-r :!spell %>err &CTRL-v<RET>` | `:!spell %>err&^M` |

（注意：在两个例子中出现的第一个 `CRTL-v` 在某些 vi 的版本中是不需要的）其中，`:!` 用来运行一个外部的（非 vi 内部的）命令。在这个拼写检查的例子中，`%` 是 vi 中的符号用来指代目前的文件， `>` 用来重定向拼写检查中的输出到 `err` 文件中，之后跟上 `&` 说明该命令是一个后台运行的任务，这样可以保证在拼写检查的同时还可以进行编辑文件的工作。这里我可以键入 `verr<RET>`（使用我之前定义的快捷键 `v` 跟上 `err`），进入 `spell` 输出结果的文件，之后再输入 `CTRL-e` 来回到刚才编辑的文件中。这样我就可以在拼写检查之后，使用 `CTRL-r` 来查看检查的错误，再通过 `CTRL-e` 返回刚才编辑的文件。

还用很多字符串输入的缩写，也使用了各种 `map` 命令，比如：

```
:map! CTRL-o \fI
:map! CTRL-k \fP
```

这个映射允许你使用 `CTRL-o` 作为 `groff` 命令的缩写，从而让让接下来书写的单词有斜体的效果，并使用 `CTRL-k` 进行恢复。

还有两个类似的映射：

```
:map! rh rhinoceros
:map! hi hippopotamus
```

上面的也可以使用 `ab` 命令来替换，就像下面这样（如果想这么用的话，需要首先按顺序运行： 1、 `unmap! rh`，2、`umap! hi`）：

```
:ab rh rhinoceros
:ab hi hippopotamus
```

在上面 `map!` 的命令中，缩写会马上的展开成原有的单词，而在 `ab` 命令中，单词展开的操作会在输入了空格和标点之后才展开（不过在 Vim 和我的 vi 中，展开的形式与 `map!` 类似）。

想要取消刚才设定的按键映射，可以对应的输入 `:unmap`、 `unmap!` 或 `:unab`。

在我使用的 vi 版本中，比较好用的候选映射按键包括 `g`、`K`、`q`、 `v`、 `V`、 `Z`，控制字符包括：`CTRL-a`、`CTRL-c`、 `CTRL-k`、`CTRL-n`、`CTRL-p`、`CTRL-x`；还有一些其他的字符如 `#`、 `*`，当然你也可以使用那些已经在 vi 中有过定义但不经常使用的字符，比如本文选择 `X` 和 `I`，其中 `X` 表示删除左边的字符，并立刻左移当前字符。

最后，下面的命令

```
:map<RET>
:map!<RET>
:ab
```

将会显示，目前所有的缩写和键位映射。

希望上面的技巧能够更好地更高效地帮助你使用 vi。

---

via: <https://opensource.com/article/18/5/shortcuts-vi-text-editor>

作者：[Dan Sonnenschein](https://opensource.com/users/dannyman)
选题：[lujun9972](https://github.com/lujun9972)
译者：[sd886393](https://github.com/sd886393)
校对：[wxy](https://github.com/wxy)

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


Linux 防火墙：关于 iptables 和 firewalld 的那些事

说了一大堆，也没说明白iptables和fiewalld到底有什么不一样，感觉跑题了

哪里讲了firewall？

为什么只讲了firewalld添加的内容，没有iptables相关使用，放通端口等..

好像只是转载哦

# Linux 防火墙：关于 iptables 和 firewalld 的那些事

>
> 以下是如何使用 iptables 和 firewalld 工具来管理 Linux 防火墙规则。
>
>
>

这篇文章摘自我的书《[Linux in Action](https://www.manning.com/books/linux-in-action?a_aid=bootstrap-it&a_bid=4ca15fc9&chan=opensource)》，尚未发布的第二个曼宁出版项目。

### 防火墙

防火墙是一组规则。当数据包进出受保护的网络区域时，进出内容（特别是关于其来源、目标和使用的协议等信息）会根据防火墙规则进行检测，以确定是否允许其通过。下面是一个简单的例子:

*防火墙可以根据协议或基于目标的规则过滤请求。*

一方面， [iptables](https://en.wikipedia.org/wiki/Iptables) 是 Linux 机器上管理防火墙规则的工具。

另一方面，[firewalld](https://firewalld.org/) 也是 Linux 机器上管理防火墙规则的工具。

你有什么问题吗？如果我告诉你还有另外一种工具，叫做 [nftables](https://wiki.nftables.org/wiki-nftables/index.php/Main_Page)，这会不会糟蹋你的美好一天呢？

好吧，我承认整件事确实有点好笑，所以让我来解释一下。这一切都从 Netfilter 开始，它在 Linux 内核模块级别控制访问网络栈。几十年来，管理 Netfilter 钩子的主要命令行工具是 iptables 规则集。

因为调用这些规则所需的语法看起来有点晦涩难懂，所以各种用户友好的实现方式，如 [ufw](https://en.wikipedia.org/wiki/Uncomplicated_Firewall) 和 firewalld 被引入，作为更高级别的 Netfilter 解释器。然而，ufw 和 firewalld 主要是为解决单独的计算机所面临的各种问题而设计的。构建全方面的网络解决方案通常需要 iptables，或者从 2014 年起，它的替代品 nftables (nft 命令行工具)。

iptables 没有消失，仍然被广泛使用着。事实上，在未来的许多年里，作为一名管理员，你应该会使用 iptables 来保护的网络。但是 nftables 通过操作经典的 Netfilter 工具集带来了一些重要的崭新的功能。

从现在开始，我将通过示例展示 firewalld 和 iptables 如何解决简单的连接问题。

### 使用 firewalld 配置 HTTP 访问

正如你能从它的名字中猜到的，firewalld 是 [systemd](https://en.wikipedia.org/wiki/Systemd) 家族的一部分。firewalld 可以安装在 Debian/Ubuntu 机器上，不过，它默认安装在 RedHat 和 CentOS 上。如果您的计算机上运行着像 Apache 这样的 web 服务器，您可以通过浏览服务器的 web 根目录来确认防火墙是否正在工作。如果网站不可访问，那么 firewalld 正在工作。

你可以使用 `firewall-cmd` 工具从命令行管理 firewalld 设置。添加 `–state` 参数将返回当前防火墙的状态:

```
# firewall-cmd --state
running
```

默认情况下，firewalld 处于运行状态，并拒绝所有传入流量，但有几个例外，如 SSH。这意味着你的网站不会有太多的访问者，这无疑会为你节省大量的数据传输成本。然而，这不是你对 web 服务器的要求，你希望打开 HTTP 和 HTTPS 端口，按照惯例，这两个端口分别被指定为 80 和 443。firewalld 提供了两种方法来实现这个功能。一个是通过 `–add-port` 参数，该参数直接引用端口号及其将使用的网络协议（在本例中为TCP）。 另外一个是通过 `–permanent` 参数，它告诉 firewalld 在每次服务器启动时加载此规则：

```
# firewall-cmd --permanent --add-port=80/tcp
# firewall-cmd --permanent --add-port=443/tcp
```

`–reload` 参数将这些规则应用于当前会话：

```
# firewall-cmd --reload
```

查看当前防火墙上的设置，运行 `–list-services`：

```
# firewall-cmd --list-services
dhcpv6-client http https ssh
```

假设您已经如前所述添加了浏览器访问，那么 HTTP、HTTPS 和 SSH 端口现在都应该是和 `dhcpv6-client` 一样开放的 —— 它允许 Linux 从本地 DHCP 服务器请求 IPv6 IP 地址。

### 使用 iptables 配置锁定的客户信息亭

我相信你已经看到了信息亭——它们是放在机场、图书馆和商务场所的盒子里的平板电脑、触摸屏和 ATM 类电脑，邀请顾客和路人浏览内容。大多数信息亭的问题是，你通常不希望用户像在自己家一样，把他们当成自己的设备。它们通常不是用来浏览、观看 YouTube 视频或对五角大楼发起拒绝服务攻击的。因此，为了确保它们没有被滥用，你需要锁定它们。

一种方法是应用某种信息亭模式，无论是通过巧妙使用 Linux 显示管理器还是控制在浏览器级别。但是为了确保你已经堵塞了所有的漏洞，你可能还想通过防火墙添加一些硬性的网络控制。在下一节中，我将讲解如何使用iptables 来完成。

关于使用 iptables，有两件重要的事情需要记住：你给出的规则的顺序非常关键；iptables 规则本身在重新启动后将无法保持。我会一次一个地在解释这些。

### 信息亭项目

为了说明这一切，让我们想象一下，我们为一家名为 BigMart 的大型连锁商店工作。它们已经存在了几十年；事实上，我们想象中的祖父母可能是在那里购物并长大的。但是如今，BigMart 公司总部的人可能只是在数着亚马逊将他们永远赶下去的时间。

尽管如此，BigMart 的 IT 部门正在尽他们最大努力提供解决方案，他们向你发放了一些具有 WiFi 功能信息亭设备，你在整个商店的战略位置使用这些设备。其想法是，登录到 BigMart.com 产品页面，允许查找商品特征、过道位置和库存水平。信息亭还允许进入 bigmart-data.com，那里储存着许多图像和视频媒体信息。

除此之外，您还需要允许下载软件包更新。最后，您还希望只允许从本地工作站访问 SSH，并阻止其他人登录。下图说明了它将如何工作：

\*信息亭业务流由 iptables 控制。 \*

### 脚本

以下是 Bash 脚本内容：

```
#!/bin/bash
iptables -A OUTPUT -p tcp -d bigmart.com -j ACCEPT
iptables -A OUTPUT -p tcp -d bigmart-data.com -j ACCEPT
iptables -A OUTPUT -p tcp -d ubuntu.com -j ACCEPT
iptables -A OUTPUT -p tcp -d ca.archive.ubuntu.com -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j DROP
iptables -A OUTPUT -p tcp --dport 443 -j DROP
iptables -A INPUT -p tcp -s 10.0.3.1 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 0.0.0.0/0 --dport 22 -j DROP
```

我们从基本规则 `-A` 开始分析，它告诉 iptables 我们要添加规则。`OUTPUT` 意味着这条规则应该成为输出链的一部分。`-p` 表示该规则仅使用 TCP 协议的数据包，正如 `-d` 告诉我们的，目的地址是 [bigmart.com](http://bigmart.com/)。`-j` 参数的作用是当数据包符合规则时要采取的操作是 `ACCEPT`。第一条规则表示允许（或接受）请求。但，往下的规则你能看到丢弃（或拒绝）的请求。

规则顺序是很重要的。因为 iptables 会对一个请求遍历每个规则，直到遇到匹配的规则。一个向外发出的浏览器请求，比如访问 bigmart.com 是会通过的，因为这个请求匹配第一条规则，但是当它到达 `dport 80` 或 `dport 443` 规则时——取决于是 HTTP 还是 HTTPS 请求——它将被丢弃。当遇到匹配时，iptables 不再继续往下检查了。（LCTT 译注：此处原文有误，径改。）

另一方面，向 ubuntu.com 发出软件升级的系统请求，只要符合其适当的规则，就会通过。显然，我们在这里做的是，只允许向我们的 BigMart 或 Ubuntu 发送 HTTP 或 HTTPS 请求，而不允许向其他目的地发送。

最后两条规则将处理 SSH 请求。因为它不使用端口 80 或 443 端口，而是使用 22 端口，所以之前的两个丢弃规则不会拒绝它。在这种情况下，来自我的工作站的登录请求将被接受，但是对其他任何地方的请求将被拒绝。这一点很重要：确保用于端口 22 规则的 IP 地址与您用来登录的机器的地址相匹配——如果不这样做，将立即被锁定。当然，这没什么大不了的，因为按照目前的配置方式，只需重启服务器，iptables 规则就会全部丢失。如果使用 LXC 容器作为服务器并从 LXC 主机登录，则使用主机 IP 地址连接容器，而不是其公共地址。

如果机器的 IP 发生变化，请记住更新这个规则；否则，你会被拒绝访问。

在家玩（是在某种一次性虚拟机上）？太好了。创建自己的脚本。现在我可以保存脚本，使用 `chmod` 使其可执行，并以 `sudo` 的形式运行它。不要担心“igmart-data.com 没找到”之类的错误 —— 当然没找到；它不存在。

```
chmod +X scriptname.sh
sudo ./scriptname.sh
```

你可以使用 `cURL` 命令行测试防火墙。请求 ubuntu.com 奏效，但请求 [manning.com](http://manning.com/) 是失败的 。

```
curl ubuntu.com
curl manning.com
```

### 配置 iptables 以在系统启动时加载

现在，我如何让这些规则在每次信息亭启动时自动加载？第一步是将当前规则保存。使用 `iptables-save` 工具保存规则文件。这将在根目录中创建一个包含规则列表的文件。管道后面跟着 `tee` 命令，是将我的`sudo` 权限应用于字符串的第二部分：将文件实际保存到否则受限的根目录。

然后我可以告诉系统每次启动时运行一个相关的工具，叫做 `iptables-restore` 。我们在上一章节（LCTT 译注：指作者的书）中看到的常规 cron 任务并不适用，因为它们在设定的时间运行，但是我们不知道什么时候我们的计算机可能会决定崩溃和重启。

有许多方法来处理这个问题。这里有一个：

在我的 Linux 机器上，我将安装一个名为 [anacron](https://sourceforge.net/projects/anacron/) 的程序，该程序将在 `/etc/` 目录中为我们提供一个名为 `anacrontab` 的文件。我将编辑该文件并添加这个 `iptables-restore` 命令，告诉它加载那个 .rule 文件的当前内容。当引导后，规则每天（必要时）01:01 时加载到 iptables 中（LCTT 译注：anacron 会补充执行由于机器没有运行而错过的 cron 任务，因此，即便 01:01 时机器没有启动，也会在机器启动会尽快执行该任务）。我会给该任务一个标识符（`iptables-restore`），然后添加命令本身。如果你在家和我一起这样，你应该通过重启系统来测试一下。

```
sudo iptables-save | sudo tee /root/my.active.firewall.rules
sudo apt install anacron
sudo nano /etc/anacrontab
1 1 iptables-restore iptables-restore < /root/my.active.firewall.rules
```

我希望这些实际例子已经说明了如何使用 iptables 和 firewalld 来管理基于 Linux 的防火墙上的连接问题。

---

via: <https://opensource.com/article/18/9/linux-iptables-firewalld>

作者：[David Clinton](https://opensource.com/users/remyd) 选题：[lujun9972](https://github.com/lujun9972) 译者：[heguangzhi](https://github.com/heguangzhi) 校对：[wxy](https://github.com/wxy)

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


5 个给孩子的非常好的 Linux 游戏和教育软件

# 5 个给孩子的非常好的 Linux 游戏和教育软件

Linux 是一个非常强大的操作系统，因此因特网上的大多数服务器都使用它。尽管它算不上是对用户友好的最佳操作系统，但它的多元化还是值的称赞的。对于 Linux 来说，每个人都能在它上面找到他们自己的所需。不论你是用它来写代码、还是用于教学或物联网（IoT），你总能找到一个适合你用的 Linux 发行版。为此，许多人认为 Linux 是未来计算的最佳操作系统。

未来是属于孩子们的，让孩子们了解 Linux 是他们掌控未来的最佳方式。这个操作系统上或许并没有一些像 FIFA 或 PES 那样的声名赫赫的游戏；但是，它为孩子们提供了一些非常好的教育软件和游戏。这里有五款最好的 Linux 教育软件，可以让你的孩子远离游戏。

**相关阅读**：[使用一个 Linux 发行版的新手指南](https://www.maketecheasier.com/beginner-guide-to-using-linux-distro/%09)

### 1、GCompris

如果你正在为你的孩子寻找一款最佳的教育软件，[GCompris](http://www.gcompris.net/downloads-en.html) 将是你的最好的开端。这款软件专门为 2 到 10 岁的孩子所设计。作为所有的 Linux 教育软件套装的巅峰之作，GCompris 为孩子们提供了大约 100 项活动。它囊括了你期望你的孩子学习的所有内容，从阅读材料到科学、地理、绘画、代数、测验等等。

GCompris 甚至有一项活动可以帮你的孩子学习计算机的相关知识。如果你的孩子还很小，你希望他去学习字母、颜色和形状，GCompris 也有这方面的相关内容。更重要的是，它也为孩子们准备了一些益智类游戏，比如国际象棋、井字棋、好记性、以及猜词游戏。GCompris 并不是一个仅在 Linux 上可运行的游戏。它也可以运行在 Windows 和 Android 上。

### 2、TuxMath

很多学生认为数学是门非常难的课程。你可以通过 Linux 教育软件如 [TuxMath](https://tuxmath.en.uptodown.com/ubuntu) 来让你的孩子了解数学技能，从而来改变这种看法。TuxMath 是为孩子开发的顶级的数学教育辅助游戏。在这个游戏中，你的角色是在如雨点般下降的数学问题中帮助 Linux 企鹅 Tux 来保护它的星球。

在它们落下来毁坏 Tux 的星球之前，找到问题的答案，就可以使用你的激光去帮助 Tux 拯救它的星球。数字问题的难度每过一关就会提升一点。这个游戏非常适合孩子，因为它可以让孩子们去开动脑筋解决问题。而且还有助他们学好数学，以及帮助他们开发智力。

### 3、Sugar on a Stick

[Sugar on a Stick](http://wiki.sugarlabs.org/go/Sugar_on_a_Stick/Downloads) 是献给孩子们的学习程序 —— 一个广受好评的全新教学法。这个程序为你的孩子提供一个成熟的教学平台，在那里，他们可以收获创造、探索、发现和思考方面的技能。和 GCompris 一样，Sugar on a Stick 为孩子们带来了包括游戏和谜题在内的大量学习资源。

关于 Sugar on a Stick 最大的一个好处是你可以将它配置在一个 U 盘上。你只要有一台 X86 的 PC，插入那个 U 盘，然后就可以从 U 盘引导这个发行版。Sugar on a Stick 是由 Sugar 实验室提供的一个项目 —— 这个实验室是一个由志愿者运作的非盈利组织。

### 4、KDE Edu Suite

[KDE Edu Suite](https://edu.kde.org/) 是一个用途与众不同的软件包。带来了大量不同领域的应用程序，KDE 社区已经证实，它不仅可以给成年人授权；它还关心年青一代如何适应他们周围的一切。它囊括了一系列孩子们使用的应用程序，从科学到数学、地理等等。

KDE Edu 套件根据长大后所必需的知识为基础，既能够用作学校的教学软件，也能够作为孩子们的学习 APP。它提供了大量的可免费下载的软件包。KDE Edu 套件在主流的 GNU/Linux 发行版都能安装。

### 5、Tux Paint

[Tux Paint](http://www.tuxpaint.org/) 是给孩子们的另一个非常好的 Linux 教育软件。这个屡获殊荣的绘画软件在世界各地被用于帮助培养孩子们的绘画技能，它有一个简洁的、易于使用的界面和有趣的音效，可以高效地帮助孩子去使用这个程序。它也有一个卡通吉祥物去鼓励孩子们使用这个程序。Tux Paint 中有许多绘画工具，它们可以帮助孩子们放飞他们的创意。

### 总结

由于这些教育软件深受孩子们的欢迎，许多学校和幼儿园都使用这些程序进行辅助教学。典型的一个例子就是 [Edubuntu](http://edubuntu.org/)，它是儿童教育领域中广受老师和家长们欢迎的一个基于 Ubuntu 的发行版。

Tux Paint 是另一个非常好的例子，它在这些年越来越流行，它大量地用于学校中教孩子们如何绘画。以上的这个清单并不很详细。还有成百上千的对孩子有益的其它 Linux 教育软件和游戏。

如果你还知道给孩子们的其它非常好的 Linux 教育软件和游戏，在下面的评论区分享给我们吧。

---

via: <https://www.maketecheasier.com/5-best-linux-software-packages-for-kids/>

作者：[Kenneth Kimari](https://www.maketecheasier.com/author/kennkimari/)
 选题：[lujun9972](https://github.com/lujun9972) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


在 Linux 中安全且轻松地管理 Cron 定时任务

Summary: 如果你在处理 Cron 定时任务的时候为了以防万一，可以尝试使用 Crontab UI，它是一个可以在类 Unix 操作系统上安全轻松管理 Cron 定时任务的 Web 页面工具。

# 在 Linux 中安全且轻松地管理 Cron 定时任务

在 Linux 中遇到计划任务的时候，你首先会想到的大概就是 Cron 定时任务了。Cron 定时任务能帮助你在类 Unix 操作系统中计划性地执行命令或者任务。也可以参考一下我们之前的一篇《[关于 Cron 定时任务的新手指导](https://www.ostechnix.com/a-beginners-guide-to-cron-jobs/)》。对于有一定 Linux 经验的人来说，设置 Cron 定时任务不是什么难事，但对于新手来说就不一定了，他们在编辑 crontab 文件的时候不知不觉中犯的一些小错误，也有可能把整个 Cron 定时任务搞挂了。如果你在处理 Cron 定时任务的时候为了以防万一，可以尝试使用 **Crontab UI**，它是一个可以在类 Unix 操作系统上安全轻松管理 Cron 定时任务的 Web 页面工具。

Crontab UI 是使用 NodeJS 编写的自由开源软件。有了 Crontab UI，你在创建、删除和修改 Cron 定时任务的时候就不需要手工编辑 Crontab 文件了，只需要打开浏览器稍微操作一下，就能完成上面这些工作。你可以用 Crontab UI 轻松创建、编辑、暂停、删除、备份 Cron 定时任务，甚至还可以简单地做到导入、导出、部署其它机器上的 Cron 定时任务，它还支持错误日志、邮件发送和钩子。

### 安装 Crontab UI

只需要一条命令就可以安装好 Crontab UI，但前提是已经安装好 NPM。如果还没有安装 NPM，可以参考《[如何在 Linux 上安装 NodeJS](https://www.ostechnix.com/install-node-js-linux/)》这篇文章。

执行这一条命令来安装 Crontab UI。

```
$ npm install -g crontab-ui
```

就是这么简单，下面继续来看看在 Crontab UI 上如何管理 Cron 定时任务。

### 在 Linux 上安全轻松管理 Cron 定时任务

执行这一条命令启动 Crontab UI：

```
$ crontab-ui
```

你会看到这样的输出：

```
Node version: 10.8.0
Crontab UI is running at http://127.0.0.1:8000
```

首先在你的防火墙和路由器上放开 8000 端口，然后打开浏览器访问 `<http://127.0.0.1:8000>`。

注意，默认只有在本地才能访问到 Crontab UI 的控制台页面。但如果你想让 Crontab UI 使用系统的 IP 地址和自定义端口，也就是想让其它机器也访问到本地的 Crontab UI，你需要使用以下这个命令：

```
$ HOST=0.0.0.0 PORT=9000 crontab-ui
Node version: 10.8.0
Crontab UI is running at http://0.0.0.0:9000
```

Crontab UI 就能够通过 `<http://IP-Address>:9000` 这样的 URL 被远程机器访问到了。

Crontab UI 的控制台页面长这样：

从上面的截图就可以看到，Crontab UI 的界面非常简洁，所有选项的含义都能不言自明。

在终端输入 `Ctrl + C` 就可以关闭 Crontab UI。

#### 创建、编辑、运行、停止、删除 Cron 定时任务

点击 “New”，输入 Cron 定时任务的信息并点击 “Save” 保存，就可以创建一个新的 Cron 定时任务了。

1. 为 Cron 定时任务命名，这是可选的；
2. 你想要执行的完整命令；
3. 设定计划执行的时间。你可以按照启动、每时、每日、每周、每月、每年这些指标快速指定计划任务，也可以明确指定任务执行的具体时间。指定好计划时间后，“Jobs” 区域就会显示 Cron 定时任务的句式。
4. 选择是否为某个 Cron 定时任务记录错误日志。

这是我的一个 Cron 定时任务样例。

如你所见，我设置了一个每月清理 `pacman` 缓存的 Cron 定时任务。你也可以设置多个 Cron 定时任务，都能在控制台页面看到。

如果你需要更改 Cron 定时任务中的某些参数，只需要点击 “Edit” 按钮并按照你的需求更改对应的参数。点击 “Run” 按钮可以立即执行 Cron 定时任务，点击 “Stop” 则可以立即停止 Cron 定时任务。如果想要查看某个 Cron 定时任务的详细日志，可以点击 “Log” 按钮。对于不再需要的 Cron 定时任务，就可以按 “Delete” 按钮删除。

#### 备份 Cron 定时任务

点击控制台页面的 “Backup” 按钮并确认，就可以备份所有 Cron 定时任务。

备份之后，一旦 Crontab 文件出现了错误，就可以使用备份来恢复了。

#### 导入/导出其它机器上的 Cron 定时任务

Crontab UI 还有一个令人注目的功能，就是导入、导出、部署其它机器上的 Cron 定时任务。如果同一个网络里的多台机器都需要执行同样的 Cron 定时任务，只需要点击 “Export” 按钮并选择文件的保存路径，所有的 Cron 定时任务都会导出到 `crontab.db` 文件中。

以下是 `crontab.db` 文件的内容：

```
$ cat Downloads/crontab.db
{"name":"Remove Pacman Cache","command":"rm -rf /var/cache/pacman","schedule":"@monthly","stopped":false,"timestamp":"Thu Aug 23 2018 10:34:19 GMT+0000 (Coordinated Universal Time)","logging":"true","mailing":{},"created":1535020459093,"_id":"lcVc1nSdaceqS1ut"}
```

导出成文件以后，你就可以把这个 `crontab.db` 文件放置到其它机器上并导入成 Cron 定时任务，而不需要在每一台主机上手动设置 Cron 定时任务。总之，在一台机器上设置完，导出，再导入到其他机器，就完事了。

#### 在 Crontab 文件获取/保存 Cron 定时任务

你可能在使用 Crontab UI 之前就已经使用 `crontab` 命令创建过 Cron 定时任务。如果是这样，你可以点击控制台页面上的 “Get from crontab” 按钮来获取已有的 Cron 定时任务。

同样地，你也可以使用 Crontab UI 来将新的 Cron 定时任务保存到 Crontab 文件中，只需要点击 “Save to crontab” 按钮就可以了。

管理 Cron 定时任务并没有想象中那么难，即使是新手使用 Crontab UI 也能轻松管理 Cron 定时任务。赶快开始尝试并发表一下你的看法吧。

---

via: <https://www.ostechnix.com/how-to-easily-and-safely-manage-cron-jobs-in-linux/>

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

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


如何在 Ubuntu Linux 中使用 RAR 文件

Summary: Ubuntu 自带的归档管理器却不支持提取 RAR 文件，也不允许创建 RAR 文件。

# 如何在 Ubuntu Linux 中使用 RAR 文件

[RAR](https://www.rarlab.com/rar_file.htm) 是一种非常好的归档文件格式。但相比之下 7-zip 能提供了更好的压缩率，并且默认情况下还可以在多个平台上轻松支持 Zip 文件。不过 RAR 仍然是最流行的归档格式之一。然而 [Ubuntu](https://www.ubuntu.com/) 自带的归档管理器却不支持提取 RAR 文件，也不允许创建 RAR 文件。

办法总比问题多。只要安装 `unrar` 这款由 [RARLAB](https://www.rarlab.com/) 提供的免费软件，就能在 Ubuntu 上支持提取 RAR 文件了。你也可以安装 `rar` 试用版来创建和管理 RAR 文件。

### 提取 RAR 文件

在未安装 `unrar` 的情况下，提取 RAR 文件会报出“未能提取”错误，就像下面这样（以 [Ubuntu 18.04](https://itsfoss.com/things-to-do-after-installing-ubuntu-18-04/) 为例）：

如果要解决这个错误并提取 RAR 文件，请按照以下步骤安装 `unrar`：

打开终端并输入：

```
sudo apt-get install unrar
```

安装 `unrar` 后，直接输入 `unrar` 就可以看到它的用法以及如何使用这个工具处理 RAR 文件。

最常用到的功能是提取 RAR 文件。因此，可以**通过右键单击 RAR 文件并执行提取**，也可以借助此以下命令通过终端执行操作：

```
unrar x FileName.rar
```

结果类似以下这样：

如果压缩文件没放在家目录中，就必须使用 `cd` 命令移动到目标目录下。例如 RAR 文件如果在 `Music` 目录下，只需要使用 `cd Music` 就可以移动到相应的目录，然后提取 RAR 文件。

### 创建和管理 RAR 文件

`unrar` 不允许创建 RAR 文件。因此还需要安装 `rar` 命令行工具才能创建 RAR 文件。

要创建 RAR 文件，首先需要通过以下命令安装 `rar`：

```
sudo apt-get install rar
```

按照下面的命令语法创建 RAR 文件：

```
rar a ArchiveName File_1 File_2 Dir_1 Dir_2
```

按照这个格式输入命令时，它会将目录中的每个文件添加到 RAR 文件中。如果需要某一个特定的文件，就要指定文件确切的名称或路径。

默认情况下，RAR 文件会放置在**家目录**中。

以类似的方式，可以更新或管理 RAR 文件。同样是使用以下的命令语法：

```
rar u ArchiveName Filename
```

在终端输入 `rar` 就可以列出 RAR 工具的相关命令。

### 总结

现在你已经知道如何在 Ubuntu 上管理 RAR 文件了，你会更喜欢使用 7-zip、Zip 或 Tar.xz 吗？

欢迎在评论区中评论。

---

via: <https://itsfoss.com/use-rar-ubuntu-linux/>

作者：[Ankush Das](https://itsfoss.com/author/ankush/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[HankChow](https://github.com/HankChow) 校对：[wxy](https://github.com/wxy)

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


用于 Linux 桌面的 4 个扫描工具

Summary: 使用这些开源软件之一驱动你的扫描仪来实现无纸化办公。

使用这些开源软件之一驱动你的扫描仪来实现无纸化办公。

# 用于 Linux 桌面的 4 个扫描工具

>
> 使用这些开源软件之一驱动你的扫描仪来实现无纸化办公。
>
>
>

<img src="content_image/album_201810_04_210151n9z83648x5zhohh9.png" alt="" title="">

尽管无纸化世界还没有到来，但越来越多的人通过扫描文件和照片来摆脱纸张的束缚。不过，仅仅拥有一台扫描仪还不足够。你还需要软件来驱动扫描仪。

然而问题是许多扫描仪制造商没有与他们的设备适配在一起的软件的 Linux 版本。不过在大多数情况下，即使没有也没多大关系。因为在 Linux 桌面上已经有很好的扫描软件了。它们能够与许多扫描仪配合很好的完成工作。

现在就让我们看看四个简单又灵活的开源 Linux 扫描工具。我已经使用过了下面这些工具（甚至[早在 2014 年](https://opensource.com/life/14/8/3-tools-scanners-linux-desktop)写过关于其中三个工具的文章）并且觉得它们非常有用。希望你也会这样认为。

### Simple Scan

这是我最喜欢的一个软件之一，[Simple Scan](https://gitlab.gnome.org/GNOME/simple-scan) 小巧、快捷、高效且易用。如果你以前见过它，那是因为 Simple Scan 是 GNOME 桌面上的默认扫描应用程序，也是许多 Linux 发行版的默认扫描程序。

你只需单击一下就能扫描文档或照片。扫描过某些内容后，你可以旋转或裁剪它并将其另存为图像（仅限 JPEG 或 PNG 格式）或 PDF 格式。也就是说 Simple Scan 可能会很慢，即使你用较低分辨率来扫描文档。最重要的是，Simple Scan 在扫描时会使用一组全局的默认值，例如 150dpi 用于文本，300dpi 用于照片。你需要进入 Simple Scan 的首选项才能更改这些设置。

如果你扫描的内容超过了几页，还可以在保存之前重新排序页面。如果有必要的话 —— 假如你正在提交已签名的表格 —— 你可以使用 Simple Scan 来发送电子邮件。

### Skanlite

从很多方面来看，[Skanlite](https://www.kde.org/applications/graphics/skanlite/) 是 Simple Scan 在 KDE 世界中的表兄弟。虽然 Skanlite 功能很少，但它可以出色的完成工作。

你可以自己配置这个软件的选项，包括自动保存扫描文件、设置扫描质量以及确定扫描保存位置。 Skanlite 可以保存为以下图像格式：JPEG、PNG、BMP、PPM、XBM 和 XPM。

其中一个很棒的功能是 Skanlite 能够将你扫描的部分内容保存到单独的文件中。当你想要从照片中删除某人或某物时，这就派上用场了。

### Gscan2pdf

这是我另一个最爱的老软件，[gscan2pdf](http://gscan2pdf.sourceforge.net/) 可能会显得很老旧了，但它仍然包含一些比这里提到的其他软件更好的功能。即便如此，gscan2pdf 仍然显得很轻便。

除了以各种图像格式（JPEG、PNG 和 TIFF）保存扫描外，gscan2pdf 还可以将它们保存为 PDF 或 [DjVu](http://en.wikipedia.org/wiki/DjVu) 文件。你可以在单击“扫描”按钮之前设置扫描的分辨率，无论是黑白、彩色还是纸张大小，每当你想要更改任何这些设置时，都可以进入 gscan2pdf 的首选项。你还可以旋转、裁剪和删除页面。

虽然这些都不是真正的杀手级功能，但它们会给你带来更多的灵活性。

### GIMP

你大概会知道 [GIMP](http://www.gimp.org/) 是一个图像编辑工具。但是你恐怕不知道可以用它来驱动你的扫描仪吧。

你需要安装 [XSane](https://en.wikipedia.org/wiki/Scanner_Access_Now_Easy#XSane) 扫描软件和 GIMP XSane 插件。这两个应该都可以从你的 Linux 发行版的包管理器中获得。在软件里，选择“文件>创建>扫描仪/相机”。单击“扫描仪”，然后单击“扫描”按钮即可进行扫描。

如果这不是你想要的，或者它不起作用，你可以将 GIMP 和一个叫作 [QuiteInsane](http://sourceforge.net/projects/quiteinsane/) 的插件结合起来。使用任一插件，都能使 GIMP 成为一个功能强大的扫描软件，它可以让你设置许多选项，如是否扫描彩色或黑白、扫描的分辨率，以及是否压缩结果等。你还可以使用 GIMP 的工具来修改或应用扫描后的效果。这使得它非常适合扫描照片和艺术品。

### 它们真的能够工作吗？

所有的这些软件在大多数时候都能够在各种硬件上运行良好。我将它们与我过去几年来拥有的多台多功能打印机一起使用 —— 无论是使用 USB 线连接还是通过无线连接。

你可能已经注意到我在前一段中写过“大多数时候运行良好”。这是因为我确实遇到过一个例外：一个便宜的 canon 多功能打印机。我使用的软件都没有检测到它。最后我不得不下载并安装 canon 的 Linux 扫描仪软件才使它工作。

你最喜欢的 Linux 开源扫描工具是什么？发表评论，分享你的选择。

---

via: <https://opensource.com/article/18/9/linux-scanner-tools>

作者：[Scott Nesbitt](https://opensource.com/users/scottnesbitt) 选题：[lujun9972](https://github.com/lujun9972) 译者：[way-ww](https://github.com/way-ww) 校对：[wxy](https://github.com/wxy)

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


3 个用于数据科学的顶级 Python 库

Summary: 使用这些库把 Python 变成一个科学数据分析和建模工具。

使用这些库把 Python 变成一个科学数据分析和建模工具。

# 3 个用于数据科学的顶级 Python 库

>
> 使用这些库把 Python 变成一个科学数据分析和建模工具。
>
>
>

Python 的许多特性，比如开发效率、代码可读性、速度等使之成为了数据科学爱好者的首选编程语言。对于想要升级应用程序功能的数据科学家和机器学习专家来说，Python 通常是最好的选择（比如，Andrey Bulezyuk 使用 Python 语言创造了一个优秀的[机器学习应用程序](https://www.liveedu.tv/andreybu/REaxr-machine-learning-model-python-sklearn-kera/oPGdP-machine-learning-model-python-sklearn-kera/)）。

由于 Python 的广泛使用，因此它拥有大量的库，使得数据科学家能够很容易地完成复杂的任务，而且不会遇到许多编码困难。下面列出 3 个用于数据科学的顶级 Python 库。如果你想在数据科学这一领域开始你的职业生涯，就去了解一下它们吧。

### NumPy

[NumPy](http://www.numpy.org/)（数值 Python 的简称）是其中一个顶级数据科学库，它拥有许多有用的资源，从而帮助数据科学家把 Python 变成一个强大的科学分析和建模工具。ＮumPy 是在 BSD 许可证的许可下开源的，它是在科学计算中执行任务的基础 Python 库。SciPy 是一个更大的基于 Python 生态系统的开源工具，而 NumPy 是 SciPy 非常重要的一部分。

NumPy 为 Python 提供了大量数据结构，从而能够轻松地执行多维数组和矩阵运算。除了用于求解线性代数方程和其它数学计算之外，NumPy 还可以用做不同类型通用数据的多维容器。

此外，NumPy 还可以和其他编程语言无缝集成，比如 C/C++ 和 Fortran。NumPy 的多功能性使得它可以简单而快速地与大量数据库和工具结合。比如，让我们来看一下如何使用 NumPy（缩写成 `np`）来实现两个矩阵的乘法运算。

我们首先导入 NumPy 库（在这些例子中，我将使用 Jupyter notebook）：

```
import numpy as np
```

接下来，使用 `eye()` 函数来生成指定维数的单位矩阵：

```
matrix_one = np.eye(3)
matrix_one
```

输出如下：

```
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
```

让我们生成另一个 3x3 矩阵。

我们使用 `arange([starting number], [stopping number])` 函数来排列数字。注意，函数中的第一个参数是需要列出的初始数字，而后一个数字不包含在生成的结果中。

另外，使用 `reshape()` 函数把原始生成的矩阵的维度改成我们需要的维度。为了使两个矩阵“可乘”，它们需要有相同的维度。

```
matrix_two = np.arange(1,10).reshape(3,3)
matrix_two
```

输出如下：

```
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
```

接下来，使用 `dot()` 函数将两个矩阵相乘。

```
matrix_multiply = np.dot(matrix_one, matrix_two)
matrix_multiply
```

相乘后的输出如下：

```
array([[1., 2., 3.],
       [4., 5., 6.],
       [7., 8., 9.]])
```

太好了！

我们成功使用 NumPy 完成了两个矩阵的相乘，而不是使用<ruby> 普通冗长 <rt>  vanilla </rt></ruby>的 Python 代码。

下面是这个例子的完整代码：

```
import numpy as np
#生成一个 3x3 单位矩阵
matrix_one = np.eye(3)
matrix_one
#生成另一个 3x3 矩阵以用来做乘法运算
matrix_two = np.arange(1,10).reshape(3,3)
matrix_two
#将两个矩阵相乘
matrix_multiply = np.dot(matrix_one, matrix_two)
matrix_multiply
```

### Pandas

[Pandas](http://pandas.pydata.org/) 是另一个可以提高你的 Python 数据科学技能的优秀库。就和 NumPy 一样，它属于 SciPy 开源软件家族，可以在 BSD 自由许可证许可下使用。

Pandas 提供了多能而强大的工具，用于管理数据结构和执行大量数据分析。该库能够很好的处理不完整、非结构化和无序的真实世界数据，并且提供了用于整形、聚合、分析和可视化数据集的工具

Pandas 中有三种类型的数据结构：

* Series：一维、相同数据类型的数组
* DataFrame：二维异型矩阵
* Panel：三维大小可变数组

例如，我们来看一下如何使用 Panda 库（缩写成 `pd`）来执行一些描述性统计计算。

首先导入该库：

```
import pandas as pd
```

然后，创建一个<ruby> 序列 <rt>  series </rt></ruby>字典：

```
d = {'Name':pd.Series(['Alfrick','Michael','Wendy','Paul','Dusan','George','Andreas',
   'Irene','Sagar','Simon','James','Rose']),
   'Years of Experience':pd.Series([5,9,1,4,3,4,7,9,6,8,3,1]),
   'Programming Language':pd.Series(['Python','JavaScript','PHP','C++','Java','Scala','React','Ruby','Angular','PHP','Python','JavaScript'])
    }
```

接下来，再创建一个<ruby> 数据框 <rt>  DataFrame </rt></ruby>：

```
df = pd.DataFrame(d)
```

输出是一个非常规整的表：

```
      Name Programming Language  Years of Experience
0   Alfrick               Python                    5
1   Michael           JavaScript                    9
2     Wendy                  PHP                    1
3      Paul                  C++                    4
4     Dusan                 Java                    3
5    George                Scala                    4
6   Andreas                React                    7
7     Irene                 Ruby                    9
8     Sagar              Angular                    6
9     Simon                  PHP                    8
10    James               Python                    3
11     Rose           JavaScript                    1
```

下面是这个例子的完整代码：

```
import pandas as pd
#创建一个序列字典
d = {'Name':pd.Series(['Alfrick','Michael','Wendy','Paul','Dusan','George','Andreas',
   'Irene','Sagar','Simon','James','Rose']),
   'Years of Experience':pd.Series([5,9,1,4,3,4,7,9,6,8,3,1]),
   'Programming Language':pd.Series(['Python','JavaScript','PHP','C++','Java','Scala','React','Ruby','Angular','PHP','Python','JavaScript'])
    }

#创建一个数据框
df = pd.DataFrame(d)
print(df)
```

### Matplotlib

[Matplotlib](https://matplotlib.org/) 也是 Scipy 核心包的一部分，并且在 BSD 许可证下可用。它是一个非常流行的科学库，用于实现简单而强大的可视化。你可以使用这个 Python 数据科学框架来生成曲线图、柱状图、直方图以及各种不同形状的图表，并且不用担心需要写很多行的代码。例如，我们来看一下如何使用 Matplotlib 库来生成一个简单的柱状图。

首先导入该库：

```
from matplotlib import pyplot as plt
```

然后生成 x 轴和 y 轴的数值：

```
x = [2, 4, 6, 8, 10]
y = [10, 11, 6, 7, 4]
```

接下来，调用函数来绘制柱状图：

```
plt.bar(x,y)
```

最后，显示图表：

```
plt.show()
```

柱状图如下：

下面是这个例子的完整代码：

```
#导入 Matplotlib 库
from matplotlib import pyplot as plt
#和 import matplotlib.pyplot as plt 一样

#生成 x 轴的数值
x = [2, 4, 6, 8, 10]

#生成 y 轴的数值
y = [10, 11, 6, 7, 4]

#调用函数来绘制柱状图
plt.bar(x,y)

#显示图表
plt.show()
```

### 总结

Python 编程语言非常擅长数据处理和准备，但是在科学数据分析和建模方面就没有那么优秀了。幸好有这些用于[数据科学](https://www.liveedu.tv/guides/data-science/)的顶级 Python 框架填补了这一空缺，从而你能够进行复杂的数学计算以及创建复杂模型，进而让数据变得更有意义。

你还知道其它的 Python 数据挖掘库吗？你的使用经验是什么样的？请在下面的评论中和我们分享。

---

via: <https://opensource.com/article/18/9/top-3-python-libraries-data-science>

作者：[Dr.Michael J.Garbade](https://opensource.com/users/drmjg) 选题：[lujun9972](https://github.com/lujun9972) 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

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