容器化，原子化发行版以及 Linux 的未来

Summary: 容器支持者认为未来属于容器化操作系统，而其他人或许有不同看法。

容器支持者认为未来属于容器化操作系统，而其他人或许有不同看法。

>
> 容器支持者认为未来属于容器化操作系统，而其他人或许有不同看法。
>
>
>

![](/data/attachment/album/201806/02/060715t3keov434go5vo4l.jpg)

自从 Linus Torvalds 在 1991 年发布 Linux 以来，Linux 已历经漫长的岁月。它已经成为企业级领域的主流操作系统。同时，我们看到桌面级领域出现了很多改进和调整，但在过去的 25 年来，主流 Linux 发行版的模式很大程度上没有变化。基于软件包管理的传统模式依然统治着桌面级和服务器级市场。

但随着 Google 发布了基于 Linux 的 Chrome OS，情况出现了微妙的转变，Chrome OS 采用镜像模式。Core OS (目前归属于 Red Hat) 受 Google 启发推出了一款操作系统 Container Linux，主要面向企业级用户。

Container Linux 改变了操作系统更新的方式，也改变了应用分发和更新的方式。这会是 Linux 发行版的未来吗？这是否会取代基于软件包的传统发行版模式呢？

### 三种模式

SLE (SUSE Linux Enterprise) 的产品管理总监 Matthias Eckermann 认为目前存在 3 种模式，而不是 2 种。Eckermann 提到：“除了传统模式（RHEL/SLE）和镜像模式（RedHat 的 Atomic Host），还存在第三种模型：事务模式。[SUSE CaaS 平台](https://www.suse.com/products/caas-platform/) 及 SUSE MicroOS 就采用这种模式。”

### 差异有哪些

Linux 用户对传统模式非常熟悉，它由独立的软件包和共享库组成。这种模式有独特的优势，让应用开发者无需将共享库捆绑在应用中。由于库不会多次引入，使得系统简洁和轻便。这也让用户无需下载很多软件包，节省了带宽。发行版对软件包全权负责，通过推送系统级别的更新，可以轻松地解决安全隐患。

RHEL （Red Hat Enterprise Linux）的产品管理总监 Ron Pacheco 表示，“传统的打包方式继续为我们提供精心构建和优化操作系统的机会，以便支持需要经过时间考验的任务关键型工作负载。”

但传统模式也有一些弊端。应用开发者受限使用发行版包含的库，使其无法从发行版不支持的新软件中获益。这也可能导致不同版本之间相互冲突。最终，传统模式给管理员增加了挑战，使其难以让软件包一直处于最新版本状态。

### 镜像模式

镜像模式应运而生。Eckermann 表示，“镜像模式解决了传统模式遇到的问题，它在每次迭代更新时替换整个操作系统，而不是单个的软件包”。

Pacheco 表示，“当我们用镜像作为操作系统的代名词进行讨论时，我们真正关心的是可编程式的开发和部署以及更好的集成式生命周期管理”，基于 RHEL 搭建的 OpenShift 被他用作示例。

Pacheco 认为基于镜像的操作系统是一种延续，从手工打造并部署镜像，到可大规模管理的高度自动化基础设施；无论客户使用哪种类型，都需要运行同样的应用。他说，“你肯定不希望使用一个完全不同的部署模式，这需要重做很多工作”。

镜像模式用新的库和软件包替代来整个操作系统，但也面临一系列问题。在镜像模式中，需要重建镜像才能适应特殊环境的需求。例如，用户有特殊需求，需要安装特定硬件的驱动或安装底层监控功能，镜像模式无法满足，需要重新设计功能以实现细粒度操作。

### 事务模式

第三种模式采用事务更新，基于传统的软件包更新，但将全部的软件包视为一个镜像，就像镜像那样在一次操作中更新全部软件包。

Eckermann 表示，“由于安装或回滚时操作对象是打包在一起的单一软件包，用户在需要时能够做相应的调整，这就是差别所在。结合传统模式和镜像模式的优点，避免两种模式的缺点，事务模式给用户提供了额外的灵活性。”

Pacheco 表示，将精心构造的工作负载部署成镜像的做法越来越成为主流，因为这种部署方式具有一致性和可靠性，而且可以弹性部署。“这正是我们用户目前的做法，部署环境包括在预置设备或公有/私有云上创建并部署的虚拟机，或在传统的裸机上。”

Pacheco 建议我们将这几种模式视为操作系统角色的进化和扩展，而不是仅仅“使用场景的比较和对比”。

### 原子化更新的问世

Google 的 Chrome OS 和 Core OS 为我们普及了事务更新的概念，该模型也被 Red Hat 和 SUSE 采用。

Eckermann 表示，“我们必须认识到，用于容器主机的操作系统已经不再是关注点 —— 至少不是管理员的关注点。RedHat Atomic 主机和 SUSE CaaS 平台都解决了该问题，实现方式在用户看来很相似。”

SUSE CaaS 平台、Red Hat Atomic Host和 Container Linux （前身是 Core OS）提供的[<ruby> 不可变基础设施 <rt>  Immutable infrastructure </rt></ruby>](https://www.digitalocean.com/community/tutorials/what-is-immutable-infrastructure) 推广了事务更新的使用。Red Hat 高级技术产品经理 Ben Breard 表示，“在事务模式中，主机总是会变更到已确认正确的新状态，这让我们更有信心执行更新，进而实现更快速的功能流、安全优势以及易于采用的操作模式。”

这些新型操作系统使用 Linux 容器将应用与底层系统隔离，解除了传统模式中基础设施更新的诸多限制。

Breard 补充道，“当编排层可以智能处理更新、部署，甚至最终实现无缝操作时，我们才会真正意识到该模式的威力和好处”。

### 展望未来

Linux 的未来会是什么样子？不同的人会给出不同的回答。容器支持者认为未来属于容器化的操作系统，但依然拥有庞大市场的 Linux 供应商显然不这么认为。

当被问到原子化发行版是否会在很久以后将替换传统发行版时，Eckermann 表示，“如果我回答肯定的，那么表示我顺应潮流；如果回答是否定的，意味着我还是站在传统阵营。然而，我的回答是否定的，即 atomic 发行版在很久以后也不会替换传统发行版，传统负载和容器化负载将在数据中心、私有云以及公有云环境中共存。”

Pacheco 认为，从 Linux 的部署增长情况来看，一般情况下很难想象一种模式替换另一种模式。与其将多种模式视为相互竞争的关系，不如将原子化发行版视为操作系统进化和部署的一部分。

此外，在一些使用案例中，我们需要同时使用多种 Linux 发行版。Eckermann 表示，“想一想银行和保险公司中大量的 PL/1 和 Cobol 系统。再想一想内存数据库和核心数据总线系统。”

这些应用大多数无法进行容器化。就我们目前来看，容器化不是解决所有问题的万金油。总是会同时存在多种不同的技术。

Eckermann 相信，随着时间的推移，大量新的开发和部署将采用容器化，但仍然有不错的理由，促使我们在企业级环境中保留传统的部署方式和应用。

Pacheco 认为，“用户需要经历业务、设计和文化的转型，才能最大化基于容器的部署带来的优势。好消息是业界已经认识到并开始大规模转变，就像历史上大型机转变成 UNIX，UNIX 转变成 x86，x86 转变成虚拟化那样”。

### 结论

很明显，未来容器化负载的使用量会持续增长，也就意味着原子化发行版的需求量持续增长。与此同时，仍会有不少工作负载运行在传统发行版中。重要的是，这两类用户都在新模式上大规模投入，以便市场改变时可以做相应的策略改变。从外部观察者的视角来看，未来属于事务/原子化模式。我们已经见证了数据中心的发展，我们花了很长时间完成了从每个服务器一个应用到“函数即服务”模型的转变。Linux 发行版进入原子化时代的日子也不会太远了。

---

via: <https://www.linux.com/blog/2018/4/containerization-atomic-distributions-and-future-linux>

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

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


保护你的 Fedora 系统免受这个 DHCP 漏洞

Summary: 前几天在 dhcp-client 中发现并披露了一个严重的安全漏洞。此 DHCP 漏洞会对你的系统和数据造成高风险，尤其是在使用不受信任的网络，如非你拥有的 WiFi 接入点时。

![](/data/attachment/album/201806/02/062337ncbcmjgkp9ltm404.jpg)

前几天在 `dhcp-client` 中发现并披露了一个严重的安全漏洞。此 DHCP 漏洞会对你的系统和数据造成高风险，尤其是在使用不受信任的网络，如非你拥有的 WiFi 接入点时。

动态主机控制协议（DHCP）能让你的系统从其加入的网络中获取配置。你的系统将请求 DHCP 数据，并且通常是由路由器等服务器应答。服务器为你的系统提供必要的数据以进行自我配置。例如，你的系统如何在加入无线网络时正确进行网络配置。

但是，本地网络上的攻击者可能会利用此漏洞。使用在 NetworkManager 下运行的 `dhcp-client` 脚本中的漏洞，攻击者可能能够在系统上以 root 权限运行任意命令。这个 DHCP 漏洞使你的系统和数据处于高风险状态。该漏洞已分配 CVE-2018-1111，并且有 [Bugzilla 来跟踪 bug](https://bugzilla.redhat.com/show_bug.cgi?id=1567974)。

### 防范这个 DHCP 漏洞

新的 dhcp 软件包包含了 Fedora 26、27 和 28 以及 Rawhide 的修复程序。维护人员已将这些更新提交到 updates-testing 仓库。对于大多数用户而言，它们应该在这篇文章的大约一天左右的时间内在稳定仓库出现。所需的软件包是：

* Fedora 26: dhcp-4.3.5-11.fc26
* Fedora 27: dhcp-4.3.6-10.fc27
* Fedora 28: dhcp-4.3.6-20.fc28
* Rawhide: dhcp-4.3.6-21.fc29

#### 更新稳定的 Fedora 系统

要在稳定的 Fedora 版本上立即更新，请[使用 sudo](https://fedoramagazine.org/howto-use-sudo/) 运行此命令。如有必要，请在提示时输入你的密码：

```
sudo dnf --refresh --enablerepo=updates-testing update dhcp-client

```

之后，使用标准稳定仓库进行更新。要从稳定的仓库更新 Fedora 系统，请使用以下命令：

```
sudo dnf --refresh update dhcp-client

```

#### 更新 Rawhide 系统

如果你的系统是 Rawhide，请使用以下命令立即下载和更新软件包：

```
mkdir dhcp && cd dhcp
koji download-build --arch={x86_64,noarch} dhcp-4.3.6-21.fc29
sudo dnf update ./dhcp-*.rpm

```

在每日的 Rawhide compose 后，只需运行 `sudo dnf update` 即可获取更新。

### Fedora Atomic Host

针对 Fedora Atomic Host 的修复程序版本为 28.20180515.1。要获得更新，请运行以下命令：

```
atomic host upgrade -r

```

此命令将重启系统以应用升级。

---

via: <https://fedoramagazine.org/protect-fedora-system-dhcp-flaw/>

作者：[Paul W. Frields](https://fedoramagazine.org/author/pfrields/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


如何在 Ubuntu 18.04 服务器上安装和配置 KVM

Summary: 我们可以通过 virt-manager 的图形用户界面或使用 virt-install 和 virsh 命令在命令行界面来创建和管理基于 KVM 的虚拟机。

![](/data/attachment/album/201806/03/085134fdm943c199801h99.jpg)

**KVM**（基于内核的虚拟机）是一款为类 Linux 系统提供的开源的全虚拟化解决方案，KVM 使用虚拟化扩展（如 **Intel VT** 或 **AMD-V**）提供虚拟化功能。无论何时我们在任何 Linux 机器上安装 KVM，都会通过加载诸如 `kvm-intel.ko`（基于 Intel 的机器）和 `kvm-amd.ko`（基于 amd 的机器）的内核模块，使其成为<ruby> 管理程序 <rt>  hyervisor </rt></ruby>（LCTT 译注：一种监控和管理虚拟机运行的核心软件层）。

KVM 允许我们安装和运行多个虚拟机（Windows 和 Linux）。我们可以通过 `virt-manager` 的图形用户界面或使用 `virt-install` 和 `virsh` 命令在命令行界面来创建和管理基于 KVM 的虚拟机。

在本文中，我们将讨论如何在 Ubuntu 18.04 LTS 服务器上安装和配置 **KVM 管理程序**。我假设你已经在你的服务器上安装了 Ubuntu 18.04 LTS 。接下来登录到您的服务器执行以下步骤。

### 第一步：确认您的硬件是否支持虚拟化

执行 `egrep` 命令以验证您的服务器的硬件是否支持虚拟化，

```
linuxtechi@kvm-ubuntu18-04:~$ egrep -c '(vmx|svm)' /proc/cpuinfo
1

```

如果输出结果大于 0，就意味着您的硬件支持虚拟化。重启，进入 BIOS 设置中启用 VT 技术。

现在使用下面的命令安装 `kvm-ok` 实用程序，该程序用于确定您的服务器是否能够运行硬件加速的 KVM 虚拟机。

```
linuxtechi@kvm-ubuntu18-04:~$ sudo apt install cpu-checker

```

运行 kvm-ok 命令确认输出结果，

```
linuxtechi@kvm-ubuntu18-04:~$ sudo kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

```

### 第二步：安装 KVM 及其依赖包

运行下面的 apt 命令安装 KVM 及其依赖项：

```
linuxtechi@kvm-ubuntu18-04:~$ sudo apt update
linuxtechi@kvm-ubuntu18-04:~$ sudo apt install qemu qemu-kvm libvirt-bin  bridge-utils  virt-manager

```

只要上图相应的软件包安装成功，那么你的本地用户（对于我来说是 `linuxtechi`）将被自动添加到 `libvirtd` 群组。

### 第三步：启动并启用 libvirtd 服务

我们在 Ubuntu 18.04 服务器上安装 qemu 和 libvirtd 软件包之后，它就会自动启动并启用 `libvirtd` 服务，如果 `libvirtd` 服务没有开启，则运行以下命令开启，

```
linuxtechi@kvm-ubuntu18-04:~$ sudo service libvirtd start
linuxtechi@kvm-ubuntu18-04:~$ sudo update-rc.d libvirtd enable

```

现在使用下面的命令确认 libvirtd 服务的状态，

```
linuxtechi@kvm-ubuntu18-04:~$ service libvirtd status

```

输出结果如下所示：

![](/data/attachment/album/201806/03/085144x9t8jwaj9tw9yt2j.jpg)

### 第四步：为 KVM 虚拟机配置桥接网络

只有通过桥接网络，KVM 虚拟机才能访问外部的 KVM 管理程序或主机。在Ubuntu 18.04中，网络由 `netplan` 实用程序管理，每当我们新安装一个 Ubuntu 18.04 系统时，会自动创建一个名称为 `/etc/netplan/50-cloud-init.yaml` 文件，其配置了静态 IP 和桥接网络，`netplan` 实用工具将引用这个文件。

截至目前，我已经在此文件配置了静态 IP，文件的具体内容如下：

```
network:
  ethernets:
    ens33:
      addresses: [192.168.0.51/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [192.168.0.1]
      dhcp4: no
      optional: true
  version: 2

```

我们在这个文件中添加桥接网络的配置信息，

```
linuxtechi@kvm-ubuntu18-04:~$ sudo vi /etc/netplan/50-cloud-init.yaml

network:
  version: 2
  ethernets:
    ens33:
      dhcp4: no
      dhcp6: no

  bridges:
    br0:
      interfaces: [ens33]
      dhcp4: no
      addresses: [192.168.0.51/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [192.168.0.1]

```

正如你所看到的，我们已经从接口（`ens33`）中删除了 IP 地址，并将该 IP 添加到 `br0` 中，并且还将接口（`ens33`）添加到 `br0`。使用下面的 `netplan` 命令使更改生效，

```
linuxtechi@kvm-ubuntu18-04:~$ sudo netplan apply

```

如果您想查看 debug 日志请使用以下命令，

```
linuxtechi@kvm-ubuntu18-04:~$ sudo netplan --debug  apply

```

现在使用以下方法确认网络桥接状态：

```
linuxtechi@kvm-ubuntu18-04:~$ sudo networkctl status -a

```

![](/data/attachment/album/201806/03/085145q448qge8l45a5df4.jpg)

```
linuxtechi@kvm-ubuntu18-04:~$ ifconfig

```

![](/data/attachment/album/201806/03/085145tatja7tghlmrstmp.jpg)

### 第五步：创建虚拟机（使用 virt-manager 或 virt-install 命令）

有两种方式创建虚拟机：

* `virt-manager`（图形化工具）
* `virt-install`（命令行工具）

#### 使用 virt-manager 创建虚拟机

通过执行下面的命令启动 `virt-manager`：

```
linuxtechi@kvm-ubuntu18-04:~$ sudo virt-manager

```

![](/data/attachment/album/201806/03/085146oa6k63e5zcda4a65.jpg)

创建一个新的虚拟机：

![](/data/attachment/album/201806/03/085146ck5l2z0zaii2ik77.jpg)

点击“下一步”然后选择 ISO 镜像文件，我使用的是 RHEL 7.3 iso 镜像。

![](/data/attachment/album/201806/03/085146vbntoble1nngbetj.jpg)

点击“下一步”。

在接下来的几个窗口中，系统会提示要求您为 VM 分配内存，处理器数量和磁盘空间。

并指定虚拟机名字和桥接网络名：

![](/data/attachment/album/201806/03/085147byhkyn5nc9ow9omw.jpg)

点击“结束”。

![RHEL7-3-Installation-Virt-Manager](/data/attachment/album/201806/03/085148rx8j9alj80lab3xa.jpg)

接下来只需要按照屏幕指示安装系统。

#### 使用virt-install命令从命令行界面创建虚拟机

使用下面的 `virt-install` 命令从终端创建一个虚拟机，它将在命令行界面中开始安装，并根据您对虚拟机的名字，说明，ISO 文件位置和桥接配置的设置创建虚拟机。

```
linuxtechi@kvm-ubuntu18-04:~$ sudo virt-install  -n DB-Server  --description "Test VM for Database"  --os-type=Linux  --os-variant=rhel7  --ram=1096  --vcpus=1  --disk path=/var/lib/libvirt/images/dbserver.img,bus=virtio,size=10  --network bridge:br0 --graphics none  --location /home/linuxtechi/rhel-server-7.3-x86_64-dvd.iso --extra-args console=ttyS0

```

本文到此为止，我希望这篇文章能帮助你能够在 Ubuntu 18.04 服务器上成功安装 KVM。 除此之外，KVM 也是 Openstack 默认的管理程序。

阅读更多：“[如何使用 virsh 命令创建，还原和删除 KVM 虚拟机快照](https://www.linuxtechi.com/create-revert-delete-kvm-virtual-machine-snapshot-virsh-command/)”。

---

via: <https://www.linuxtechi.com/install-configure-kvm-ubuntu-18-04-server/>

作者：[Pradeep Kumar](http://www.linuxtechi.com/author/pradeep/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wyxplus](https://github.com/wyxplus) 校对：[wxy](https://github.com/wxy)

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


使用 Quagga 实现 Linux 动态路由

Summary: 学习如何使用 Quagga 套件的路由协议去管理动态路由。

学习如何使用 Quagga 套件的路由协议去管理动态路由。

>
> 学习如何使用 Quagga 套件的路由协议去管理动态路由。
>
>
>

![network](/data/attachment/album/201806/03/105608rlzwdzcmiaan0zh7.png "network")

迄今为止，本系列文章中，我们已经在 [Linux 局域网路由新手指南：第 1 部分](/article-9657-1.html) 中学习了复杂的 IPv4 地址，在 [Linux 局域网路由新手指南：第 2 部分](/article-9675-1.html) 中学习了如何去手工创建静态路由。

今天，我们继续使用 [Quagga](https://www.quagga.net/) 去管理动态路由，这是一个安装完后就不用理它的的软件。Quagga 是一个支持 OSPFv2、OSPFv3、RIP v1 和 v2、RIPng、以及 BGP-4 的路由协议套件，并全部由 zebra 守护程序管理。

OSPF 的意思是<ruby> 最短路径优先 <rt>  Open Shortest Path First </rt></ruby>。OSPF 是一个内部网关协议（IGP）;它可以用在局域网和跨因特网的局域网互联中。在你的网络中的每个 OSPF 路由器都包含整个网络的拓扑，并计算通过网络的最短路径。OSPF 会通过多播的方式自动对外传播它检测到的网络变化。你可以将你的网络分割为区域，以保持路由表的可管理性；每个区域的路由器只需要知道离开它的区域的下一跳接口地址，而不用记录你的网络的整个路由表。

RIP，即路由信息协议，是一个很老的协议，RIP 路由器向网络中周期性多播它的整个路由表，而不是像 OSPF 那样只多播网络的变化。RIP 通过跳数来测量路由，任何超过 15 跳的路由它均视为不可到达。RIP 设置很简单，但是 OSPF 在速度、效率以及弹性方面更佳。

BGP-4 是边界网关协议版本 4。这是用于因特网流量路由的外部网关协议（EGP）。你不会用到 BGP 协议的，除非你是因特网服务提供商。

### 准备使用 OSPF

在我们的小型 KVM 测试实验室中，用两台虚拟机表示两个不同的网络，然后将另一台虚拟机配置为路由器。创建两个网络：net1 是 192.168.110.0/24 ，而 net2 是 192.168.120.0/24。启用 DHCP 是明智的，否则你要分别进入这三个虚拟机，去为它们设置静态地址。Host 1 在 net1 中，Host 2 在 net2 中，而路由器同时与这两个网络连接。设置 Host 1 的网关地址为 192.168.110.126，Host 2 的网关地址为 192.168.120.136。

* Host 1： 192.168.110.125
* Host 2：192.168.120.135
* Router：192.168.110.126 和 192.168.120.136

在路由器上安装 Quagga。在大多数 Linux 中它是 quagga 软件包。在 Debian 上还有一个单独的文档包 quagga-doc。取消 `/etc/sysctl.conf` 配置文件中如下这一行的注释去启用包转发功能：

```
net.ipv4.ip_forward=1

```

然后，运行 `sysctl -p` 命令让变化生效。

### 配置 Quagga

查看你的 Quagga 包中的示例配置文件，比如，`/usr/share/doc/quagga/examples/ospfd.conf.sample`。除非你的 Linux 版本按你的喜好做了创新，否则，一般情况下配置文件应该在 `/etc/quagga` 目录中。大多数 Linux 版本在这个目录下有两个文件，`vtysh.conf` 和 `zebra.conf`。它们提供了守护程序运行所需要的最小配置。除非你的发行版做了一些特殊的配置，否则，zebra 总是首先运行，当你启动 ospfd 的时候，它将自动启动。Debian/Ubuntu 是一个特例，稍后我们将会说到它。

每个路由器守护程序将读取它自己的配置文件，因此，我们必须创建 `/etc/quagga/ospfd.conf`，并输入如下内容：

```
!/etc/quagga/ospfd.conf
hostname router1
log file /var/log/quagga/ospfd.log
router ospf
  ospf router-id 192.168.110.15
  network 192.168.110.0/0 area 0.0.0.0
  network 192.168.120.0/0 area 0.0.0.0
access-list localhost permit 127.0.0.1/32
access-list localhost deny any
line vty
  access-class localhost

```

你可以使用感叹号（`!`）或者井号（`#`）去注释掉这些行。我们来快速浏览一下这些选项。

* `hostname` 可以是你希望的任何内容。这里不是一般意义上的 Linux 主机名，但是，当你使用 `vtysh` 或者 `telnet` 登入时，你将看到它们。
* `log file` 是你希望用于保存日志的任意文件。
* `router` 指定路由协议。
* `ospf router-id` 是任意的 32 位数字。使用路由器的一个 IP 地址就是很好的选择。
* `network` 定义你的路由器要通告的网络。
* `access-list` 限制 `vtysh` 登入，它是 Quagga 命令行 shell，它允许本地机器登入，并拒绝任何远程管理。

### Debian/Ubuntu

在你启动守护程序之前，Debian/Ubuntu 相对其它的 Debian 衍生版可能多需要一步到多步。编辑 `/etc/quagga/daemons` ，除了 `zebra=yes` 和 `ospfd=yes` 外，使其它所有的行的值为 `no`。

然后，在 Debian 上运行 `ospfd` 去启动 Quagga：

```
# systemctl start quagga

```

在大多数的其它 Linux 上，包括 Fedora 和 openSUSE，用如下命令启动 `ospfd`：

```
# systemctl start ospfd

```

现在，Host 1 和 Host 2 将可以互相 ping 通对方和路由器。

这里用了许多篇幅去描述非常简单的设置。在现实中，路由器将连接两个交换机，然后为连接到这个交换机上的所有电脑提供一个网关。你也可以在你的路由器上添加更多的网络接口，这样你的路由器就可以为更多的网络提供路由服务，或者也可以直接连接到其它路由器上，或者连接到连接其它路由器的骨干网络上。

你或许不愿意如此麻烦地手工配置网络接口。最简单的方法是使用你的 DHCP 服务器去宣告你的路由器。如果你使用了 Dnsmasq，那么你就有了一个 DHCP 和 DNS 的一体化解决方案。

还有更多的配置选项，比如，加密的密码保护。更多内容请查看 [Quagga 路由套件](https://www.quagga.net/) 的官方文档。

---

via: <https://www.linux.com/learn/intro-to-linux/2018/3/dynamic-linux-routing-quagga>

作者：[CARLA SCHRODER](https://www.linux.com/users/cschroder) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


Audacity 快速指南：快速消除背景噪音

Summary: 在这个快速指南中，我们会学习如何使用 Fedora 中的 Audacity 快速移除音频文件中的背景噪音。

![](/data/attachment/album/201806/03/110200t2nw5y8z0sl7z85n.png)

当在笔记本电脑上录制声音时 —— 比如首次简单地录屏 —— 许多用户通常使用内置麦克风。但是，这些小型麦克风也会捕获很多背景噪音。在这个快速指南中，我们会学习如何使用 Fedora 中的 [Audacity](https://www.audacityteam.org/) 快速移除音频文件中的背景噪音。

### 安装 Audacity

Audacity 是 Fedora 中用于混合、剪切和编辑音频文件的程序。在 Fedora 上它支持各种开箱即用的格式 - 包括 MP3 和 OGG。从软件中心安装 Audacity。

![](/data/attachment/album/201806/03/110201oxhzhndxcndkm2xh.jpg)

如果你更喜欢终端，请使用以下命令：

```
sudo dnf install audacity

```

### 导入您的音频、样本背景噪音

安装 Audacity 后，打开程序，使用 “File > Import” 菜单项导入你的声音。这个例子使用了一个[来自 freesound.org 添加了噪音的声音](https://freesound.org/people/levinj/sounds/8323/)：

* <https://ryanlerch.fedorapeople.org/noise.ogg?_=1>

接下来，采样要滤除的背景噪音。导入音轨后，选择仅包含背景噪音的音轨区域。然后从菜单中选择 “Effect > Noise Reduction”，然后按下 “Get Noise Profile” 按钮。

![](/data/attachment/album/201806/03/110203shoxlp5p1giccgvi.gif)

### 过滤噪音

接下来，选择你要过滤噪音的音轨区域。通过使用鼠标进行选择，或者按 `Ctrl + a` 来选择整个音轨。最后，再次打开 “Effect > Noise Reduction” 对话框，然后单击确定以应用滤镜。

![](/data/attachment/album/201806/03/110203bzryaorbq8rqhs66.gif)

此外，调整设置，直到你的音轨听起来更好。这里是原始文件，接下来是用于比较的降噪音轨（使用默认设置）：

* <https://ryanlerch.fedorapeople.org/sidebyside.ogg?_=2>

---

via: <https://fedoramagazine.org/audacity-quick-tip-quickly-remove-background-noise/>

作者：[Ryan Lerch](https://fedoramagazine.org/introducing-flatpak/) 选题：[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/) 荣誉推出


diff 与 patch 的使用

![](/data/attachment/album/201806/03/112057zvh0tuwx1lljehhs.jpg)

### 摘要

在 Linux 的日常使用中，我们经常需要修改一些配置文件，然而在软件升级以后，经常会面临配置更新后与原配置部分不兼容的问题（当然我们更多的可能是来制作软件升级的补丁）。在这种情况下我们通常有两种选择：

* 对比现有配置，手动在新配置文件中改动
* 利用 `sed`、`awk` 等工具配合改动
* 采用 `diff` 与 `patch` 制作增量补丁的方式改动

本文主要通过一个升级`awesome` 配置的例子，对第三种方法进行介绍和讲解。

### diff 介绍

`diff` 是一个文件比较工具，可以逐行比较两个文件的不同，其中它有三种输出方式，分别是 `normal`， `context` 以及 `unified`。区别如下：

* `normal` 方式为默认输出方式，不需要加任何参数
* `context` 相较于 `normal` 模式的简单输出，`contetx` 模式会输出修改过部分的上下文，默认是前后 **3** 行。使用参数 `-c`
* `unified` 合并上下文模式则为新的上下文输出模式，同样为前后 **3** 行，只不过把上下文合并了显示了。使用参数 `-u`

**注**：本文主要介绍 `unified` 模式

其他常用参数：

* `-r` 递归处理目录
* `-N` 将缺失的文件当作空白文件处理

#### diff 语法与文件格式

```
diff [options] old new

```

先来看一个简单的例子：

```
$ cat test1
linux
linux
linux
linux

```

```
$ cat test2
locez
linux
locez
linux

```

此时输入 `diff -urN test1 test2` 会输出以下信息：

```
--- test1   2018-05-12 18:39:41.508375114 +0800
+++ test2   2018-05-12 18:41:00.124031736 +0800
@@ -1,4 +1,4 @@
+locez
 linux
-linux
-linux
+locez
 linux

```

先看前面 2 行，这两行为文件的基本信息，`---` 开头为改变前的文件，`+++` 开头为更新后的文件。

```
--- test1   2018-05-12 18:39:41.508375114 +0800
+++ test2   2018-05-12 18:41:00.124031736 +0800

```

第三行为上下文描述块，其中 `-1,4` 为旧文件的 4 行上下文，`+1,4` 为新文件的：

```
@@ -1,4 +1,4 @@

```

而具体到块里面的内容，前面有 `-` 号的则为删除，有 `+` 号为新增，不带符号则未做改变，仅仅是上下文输出。

### patch 介绍

`patch` 是一个可以将 `diff` 生成的**补丁**应用到源文件，生成一个打过补丁版本的文件。语法：

```
patch [oiption] [originalfile [patchfile]]

```

常用参数：

* `-i` 指定补丁文件
* `-pNum` 在 `diff` 生成的补丁中，第一二行是文件信息，其中文件名是可以包含路径的，例如 `--- /tmp/test1 2018-05-12 18:39:41.508375114 +0800` 其中 `-p0` 代表完整的路径 `/tmp/test1`，而 `-p1` 则指 `tmp/test1`，`-pN` 依此类推
* `-E` 删除应用补丁后为空文件的文件
* `-o` 输出到一个文件而不是直接覆盖文件

### 应用

awesome 桌面 3.5 与 4.0 之间的升级是不兼容的，所以在升级完 4.0 以后，awesome 桌面部分功能无法使用，因此需要迁移到新配置，接下来则应用 `diff` 与 `patch` 实现迁移，当然你也可以单纯使用 `diff` 找出不同，然后手动修改新配置。

现在有以下几个文件：

* `rc.lua.3.5` 3.5 版本的默认配置文件，未修改
* `rc.lua.myconfig` 基于 3.5 版本的个人配置文件
* `rc.lua.4.2` 4.2 新默认配置，未修改

思路为利用 `diff` 提取出个人配置与 3.5 默认配置文件的增量补丁，然后把补丁应用在 4.2 的文件上实现迁移。

#### 制作补丁

```
$ diff -urN rc.lua.3.5 rc.lua.myconfig  > mypatch.patch

```

#### 应用补丁

```
$ patch rc.lua.4.2 -i mypatch.patch -o rc.lua
patching file rc.lua (read from rc.lua.4.2)
Hunk #1 FAILED at 38.
Hunk #2 FAILED at 55.
Hunk #3 succeeded at 101 with fuzz 1 (offset 5 lines).
Hunk #4 succeeded at 276 with fuzz 2 (offset 29 lines).
2 out of 4 hunks FAILED -- saving rejects to file rc.lua.rej

```

显然应用没有完全成功，其中在 38 行以及 55 行应用失败，并记录在 `rc.lua.rej` 里。

```
$ cat rc.lua.rej
--- rc.lua.3.5  2018-05-12 19:15:54.922286085 +0800
+++ rc.lua.myconfig 2018-05-12 19:13:35.057911463 +0800
@@ -38,10 +38,10 @@

 -- {{{ Variable definitions
 -- Themes define colours, icons, font and wallpapers.
-beautiful.init("@AWESOME_THEMES_PATH@/default/theme.lua")
+beautiful.init("~/.config/awesome/default/theme.lua")

 -- This is used later as the default terminal and editor to run.
-terminal = "xterm"
+terminal = "xfce4-terminal"
 editor = os.getenv("EDITOR") or "nano"
 editor_cmd = terminal .. " -e " .. editor

@@ -55,18 +55,18 @@
 -- Table of layouts to cover with awful.layout.inc, order matters.
 local layouts =
 {
-    awful.layout.suit.floating,
-    awful.layout.suit.tile,
-    awful.layout.suit.tile.left,
-    awful.layout.suit.tile.bottom,
-    awful.layout.suit.tile.top,
+--    awful.layout.suit.floating,
+--    awful.layout.suit.tile,
+--    awful.layout.suit.tile.left,
+--    awful.layout.suit.tile.bottom,
+--    awful.layout.suit.tile.top,
     awful.layout.suit.fair,
     awful.layout.suit.fair.horizontal,
     awful.layout.suit.spiral,
     awful.layout.suit.spiral.dwindle,
     awful.layout.suit.max,
     awful.layout.suit.max.fullscreen,
-    awful.layout.suit.magnifier
+--    awful.layout.suit.magnifier
 }
 -- }}}

```

这里是主题，终端，以及常用布局的个人设置。

#### 修正补丁

再次通过对比补丁文件与 4.2 文件，发现 38 行区块是要删除的东西不匹配，而 55 行区块则是上下文与要删除的内容均不匹配，导致不能应用补丁，于是手动修改补丁

```
$ vim mypatch.patch

```

```
--- rc.lua.3.5  2018-05-12 19:15:54.922286085 +0800
+++ rc.lua.myconfig 2018-05-12 19:13:35.057911463 +0800
@@ -38,10 +38,10 @@

 -- {{{ Variable definitions
 -- Themes define colours, icons, font and wallpapers.
-beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
+beautiful.init("~/.config/awesome/default/theme.lua")

 -- This is used later as the default terminal and editor to run.
-terminal = "xterm"
+terminal = "xfce4-terminal"
 editor = os.getenv("EDITOR") or "nano"
 editor_cmd = terminal .. " -e " .. editor

@@ -55,18 +55,18 @@

 -- Table of layouts to cover with awful.layout.inc, order matters.
 awful.layout.layouts = {
-    awful.layout.suit.floating,
-    awful.layout.suit.tile,
-    awful.layout.suit.tile.left,
-    awful.layout.suit.tile.bottom,
-    awful.layout.suit.tile.top,
+--    awful.layout.suit.floating,
+--    awful.layout.suit.tile,
+--    awful.layout.suit.tile.left,
+--    awful.layout.suit.tile.bottom,
+--    awful.layout.suit.tile.top,
     awful.layout.suit.fair,
     awful.layout.suit.fair.horizontal,
     awful.layout.suit.spiral,
     awful.layout.suit.spiral.dwindle,
     awful.layout.suit.max,
     awful.layout.suit.max.fullscreen,
-    awful.layout.suit.magnifier,
+--    awful.layout.suit.magnifier,
     awful.layout.suit.corner.nw,
     -- awful.layout.suit.corner.ne,
     -- awful.layout.suit.corner.sw,
....
....

```

输出省略显示，有兴趣的读者可以仔细与`rc.lua.rej` 文件对比，看看笔者是怎样改的。

#### 再次应用补丁

```
$ patch rc.lua.4.2 -i mypatch.patch -o rc.lua
patching file rc.lua (read from rc.lua.4.2)
Hunk #1 succeeded at 41 (offset 3 lines).
Hunk #2 succeeded at 57 with fuzz 2 (offset 2 lines).
Hunk #3 succeeded at 101 with fuzz 1 (offset 5 lines).
Hunk #4 succeeded at 276 with fuzz 2 (offset 29 lines).
$ cp rc.lua ~/.config/awesome/rc.lua  ### 打完补丁直接使用

```

### 总结

`diff` 与 `patch` 配合使用，能当增量备份，而且还可以将补丁分发给他人使用，而且在日常的软件包打补丁也具有重要的意义，特别是内核补丁或者一些驱动补丁，打补丁遇到错误时候可以尝试自己修改，已满足自身特殊要求，修改的时候一定要抓住 2 个非常重要的要素：

1. 要修改的内容是否匹配？特别是要删除的
2. 上下文是否满足，特别是距离要修改的地方前后一行，以及上下文的行数是否满足，默认是 3 行上下文


异步决策：帮助远程团队走向成功

Summary: 更好的沟通和少量的会议并不是白日梦。这里告诉您异步决策是如何实现这一切的。

更好的沟通和少量的会议并不是白日梦。这里告诉您异步决策是如何实现这一切的。

>
> 更好的沟通和少量的会议并不是白日梦。这里告诉您异步决策是如何实现这一切的。
>
>
>

![](/data/attachment/album/201806/03/171213hlgf9fz879w8k9xl.png)

异步决策能够让地理和文化上分散的软件团队更有效率地做出决策。本文就将讨论一下实现异步决策所需要的一些原则和工具。

同步决策，要求参与者实时地进行互动，而这对那些需要<ruby> <a href="http://www.paulgraham.com/makersschedule.html">  大块完整时间工作 </a> <rt>  Maker's Schedule </rt></ruby>的人来说代价非常大，而且对于远程团队来说这也不现实。我们会发现这种会议最后浪费的时间让人难以置信。

相比之下，异步决策常应用于大型开源项目中（比如我常参与的 Apache 软件基金会 ASF）。它为团队提供了一种尽可能少开会的有效方法。很多开源项目每年只开很少的几次会议（有的甚至完全没开过会），然而开发团队却始终如一地在生产高质量的软件。

怎样才能异步决策呢？

### 所需工具

#### 中心化的异步沟通渠道

异步决策的第一步就是构建一个中心化的异步沟通渠道。你所使用的技术必须能让所有的团队成员都获得同样的信息，并能进行<ruby> 线索讨论 <rt>  threaded discussions </rt></ruby>，也就是说你要既能对一个主题进行发散也要能封禁其他主题的讨论。想一想航海专用无线电台，其中广播渠道的作用只是为了引起特定人员的注意，这些人然后再创建一个子渠道来进行详细的讨论。

很多开源项目依旧使用邮件列表作为中心渠道，不过很多新一代的软件开发者可能会觉得这个方法又古老又笨拙。邮件列表需要遵循大量的准则才能有效的管理热门项目，比如你需要进行有意义的引用，每个线索只讨论一个主题，保证 [标题与内容相吻合](https://grep.codeconsult.ch/2017/11/10/large-mailing-lists-survival-guide/)。虽然这么麻烦，但使用得当的话，再加上一个经过索引的归档系统，邮件列表依然在创建中心渠道的工具中占据绝对主导的地位。

公司团队可以从一个更加现代化的协作工具中收益，这类工具更易使用并提供了更加强大的多媒体功能。不管你用的是哪个工具，关键在于要创建一个能让大量的人员有效沟通并异步地讨论各种主题的渠道。要创建一个一致而活跃的社区，使用一个 [繁忙的渠道要好过建立多个渠道](https://grep.codeconsult.ch/2011/12/06/stefanos-mazzocchis-busy-list-pattern/)。

#### 构建共识的机制

第二个工具是一套构建共识的机制，这样你才不会陷入死循环从而确保能做出决策。做决策最理想的情况就是一致同意，而次佳的就是达成共识，也就是 “有决策权的人之间广泛形成了一致的看法”。强求完全一致的赞同或者允许一票否决都会阻碍决策的制定，因此 ASF 中只在非常有限的决策类型中允许否决权。[ASF 投票制度](http://www.apache.org/foundation/voting.html) 为类似 ASF 这样没有大老板的松散组织构建了一个久经考验的，用于达成共识的好方法。当共识无法自然产生时也可以使用该套制度。

#### 案例管理系统

如上所述，我们通常在项目的中心渠道中构建共识。但是在讨论一些复杂的话题时，使用案例管理系统这一第三方的工具很有意义。小组可以使用中心渠道专注于非正式的讨论和头脑风暴上，当讨论要转变成一个决策时将其转到一个更加结构化的案例管理系统中去。

案例管理系统能够更精确地组织决策。小型团队不用做太多决策可以不需要它，但很多团队会发现能有一个相对独立的地方讨论决策的细节并保存相关信息会方便很多。

案例管理系统不一定就是个很复杂的软件; 在 ASF 中我们所使用的只是简单的问题跟踪软件而已，这些基于网页的系统原本是创建来进行软件支持和 bug 管理的。每个案例列在一个单独的网页上，还有一些历史的注释和动作信息。该途径可以很好的追踪决策是怎么制定出来的。比如，某些非紧急的决策或者复杂的决策可能会花很长时间才会制定出来，这时有一个地方能够了解这些决策的历史就很有用了。新来的团队成员也能很快地了解到最近做出了哪些决策，哪些决策还在讨论，每个决策都有那些人参与其中，每个决策的背景是什么。

### 成功的案例

ASF 董事会中的九名董事在每个月的电话会议上只做很少的一些决策，耗时不超过 2 个小时。在准备这些会议之前，大多数的决策都预先通过异步的方式决定好了。这使得我们可以在会议上集中讨论复杂和难以确定的问题，而不是讨论那些已经达成普遍或部分共识的问题上。

软件世界外的一个有趣的案例是 [瑞士联邦委员会的周会](https://www.admin.ch/gov/en/start/federal-council/tasks/decision-making/federal-council-meeting.html)，它的运作方式跟 ASF 很类似。团队以异步决策构建共识的方式来准备会议。会议议程由一组不同颜色编码的列表组成，这些颜色标识了那些事项可以很快通过批准，那些事项需要进一步的讨论，哪些事项特别的复杂。这使得只要 7 个人就能每年忙完超过 2500 项决策，共 50 个周会，每个周会只需要几个小时时间。我觉得这个效率已经很高了。

就我的经验来看，异步决策带来的好处完全值得上为此投入的时间和工具。而且它也能让团队成员更快乐，这也是成功的关键因素之一。

---

via: <https://opensource.com/article/17/12/asynchronous-decision-making>

作者：[Bertrand Delacretaz](https://opensource.com) 译者：[lujun9972](https://github.com/lujun9972) 校对：[wxy](https://github.com/wxy)

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


最小权限的容器编排

![](/data/attachment/album/201806/03/215723n53ak5ndex3bapnk.jpg)

Docker 平台和容器已经成为打包、部署、和管理应用程序的标准。为了在一个集群内协调跨节点的容器，必须有一个关键的能力：一个容器编排器。

![container orchestrator](/data/attachment/album/201806/03/215736pd1dhdoumu8ilhdi.jpg)

对于关键的集群化以及计划的任务，编排器是起重大作用的，比如：

* 管理容器计划和资源分配。
* 支持服务发现和无缝的应用程序部署。
* 分配应用程序运行必需的资源。

不幸的是，在这种环境下，编排器的分布式特性和资源的短暂性使得确保编排器的安全是一个极具挑战性的任务。在这篇文章中，我们将讨论容器编排器安全模型中没有考虑到的、但是很重要的这方面的详细情况，以及 Docker 企业版中如何使用内置的编排性能、Swarm 模式，去克服这些问题。

### 诱因和威胁模型

使用 swarm 模式的 Docker 企业版的其中一个主要目标是提供一个内置安全特性的编排器。为达到这个目标，我们部署了第一个在我们心目中认为的以最小权限原则设计的容器编排器。

在计算机科学中，一个分布式系统所要求的最小权限原则是，系统中的每个参与者仅仅能访问它正当目的所需要的信息和资源。不是更多，也不是更少。

>
> “一个进程必须仅仅能去访问它的正当目的所需要的信息和资源”
>
>
>

#### 最小权限原则

在一个 Docker 企业版集群中的每个节点分配的角色：既不是管理者（manager），也不是工人（worker）。这些角色为节点定义了一个很粗粒度的权限级别：分别进行管理和任务执行。尽管如此，不用理会它的角色，通过使用加密的方式，来保证一个节点仅仅有执行它的任务所需要的信息和资源。结果是，确保集群安全变得更容易了，甚至可以防止大多数的有经验的攻击者模式：攻击者控制了底层通讯网络，或者甚至攻陷了集群节点。

### 内核缺省安全

这是一个很老的安全最大化状态：如果它不是缺省的，就没人用它。Docker Swarm 模式将缺省安全这一概念融入了核心，并且使用这一机制去解决编排器生命周期中三个很难并且很重要的部分：

1. 可信引导和节点引入。
2. 节点身份发布和管理。
3. 认证、授权和加密的信息存储和传播。

我们来分别看一下这三个部分：

#### 可信引导和节点引入

确保集群安全的第一步，没有别的，就是严格控制成员和身份。管理员不能依赖它们节点的身份，并且在节点之间强制实行绝对的负载隔离。这意味着，未授权的节点不能允许加入到集群中，并且，已经是集群一部分的节点不能改变身份，突然去伪装成另一个节点。

为解决这种情况，通过 Docker 企业版 Swarm 模式管理的节点，维护了健壮的、不可改变的身份。期望的特性是，通过使用两种关键的构建块去保证加密：

1. 为集群成员使用<ruby> 安全加入令牌 <rt>  Secure join token </rt></ruby>。
2. 从一个集中化的认证机构发行的内嵌唯一身份的证书。

##### 加入 Swarm

要加入 Swarm，节点需要一份<ruby> 安全加入令牌 <rt>  Secure join token </rt></ruby>的副本。在集群内的每个操作角色的令牌都是独一无二的 —— 现在有两种类型的节点：工人（workers）和管理者（managers）。由于这种区分，拥有一个工人令牌的节点将不允许以管理者角色加入到集群。唯一得到这个特殊令牌的方式是通过 swarm 的管理 API 去向集群管理者请求一个。

令牌是安全的并且是随机生成的，它还有一个使得令牌泄露更容易被检测到的特殊语法：一个可以在你的日志和仓库中很容易监视的特殊前缀。幸运的是，即便发现一个泄露，令牌也可以很容易去更新，并且，推荐你经常去更新它们 —— 特别是，在一段时间中你的集群不进行扩大的情况下。

![Docker Swarm](/data/attachment/album/201806/03/215739qv7uv8sbyv87hfvx.jpg)

##### 引导信任

作为它的身份标识创建的一部分，一个新的节点将向任意一个网络管理者请求发布一个新的身份。但是，在我们下面的威胁模型中，所有的通讯可以被一个第三方拦截。这种请求存在的问题是：一个节点怎么知道与它进行对话的对方是合法的管理者？

![Docker Security](/data/attachment/album/201806/03/215739sbxzyy3i5yi7yv41.jpg)

幸运的是，Docker 有一个内置机制可以避免这种情况。这个加入令牌被主机用于加入 Swarm，包含了一个根 CA 证书的哈希串。所以，主机可以使用单向 TLS，并且使用这个哈希串去验证它加入的 Swarm 是否正确：如果管理者持有的证书没有被正确的 CA 哈希串签名，节点就知道它不可信任。

#### 节点身份发布和管理

在一个 Swarm 中，身份标识是内嵌在每个节点都单独持有的一个 x509 证书中。在一个最小权限原则的表现形式中，证书的私钥被绝对限制在主机的原始位置。尤其是，管理者不能访问除了它自己的私钥以外的任何一个私钥。

##### 身份发布

要接收它们的证书而无需共享它们的私钥，新的主机通过发布一个证书签名请求（CSR）来开始，管理者收到证书签名请求之后，转换成一个证书。这个证书成为这个新的主机的身份标识，使这个节点成为 Swarm 的一个完全合格成员！

![](/data/attachment/album/201806/03/215742n1acrwxccxngwici.jpg)

当和安全引导机制一起使用时，发行身份标识的这个机制来加入节点是缺省安全的：所有的通讯部分都是经过认证的、授权的，并且非敏感信息从来都不会以明文方式进行交换。

##### 身份标识延期

尽管如此，给一个 Swarm 中安全地加入节点，仅仅是 “故事” 的一部分。为降低证书的泄露或者失窃造成的影响，并且移除管理 CRL 列表的复杂性，Swarm 模式为身份标识使用了较短存活周期的证书。这些证书缺省情况下三个月后将过期，但是，也可以配置为一个小时后即刻过期！

![Docker secrets](/data/attachment/album/201806/03/215742hud947n983d3s7a8.jpg)

较短的证书过期时间意味着不能手动去处理证书更新，所以，通常会使用一个 PKI 系统。对于 Swarm，所有的证书是以一种不中断的方式进行自动更新的。这个过程很简单：使用一个相互认证的 TLS 连接去证明一个特定身份标识的所有者，一个 Swarm 节点定期生成一个新的公钥/私钥密钥对，并且用相关的 CSR 去签名发送，创建一个维持相同身份标识的完整的新证书。

#### 经过认证、授权、和加密的信息存储和传播。

在一个正常的 Swarm 的操作中，关于任务的信息被发送给去运行的工人（worker）节点。这里不仅仅包含将被一个节点运行的容器的信息；也包含那个容器运行所必需的资源的所有信息，包括敏感的机密信息，比如，私钥、密码和 API 令牌。

##### 传输安全

事实上，参与 Swarm 的每个节点都拥有一个独一无二的 X509 格式的证书，因此，节点之间的通讯安全是没有问题的：节点使用它们各自的证书，与另一个连接方进行相互认证、继承机密、真实性、和 TLS 的完整性。

![Swarm Mode](/data/attachment/album/201806/03/215744kv6j5j6118rrrlrl.jpg)

关于 Swarm 模式的一个有趣的细节是，本质上它是使用了一个推送模式：仅管理者被允许去发送信息到工人们（workers）—— 显著降低了暴露在低权限的工人节点面前的管理者节点的攻击面。

##### 将负载严格隔离进安全区域

管理者节点的其中一个责任是，去决定发送到每个工人（worker）节点的任务是什么。管理者节点使用多种策略去做这个决定；根据每个节点和每个负载的特性，去跨 Swarm 去安排负载。

在使用 Swarm 模式的 Docker 企业版中，管理者节点通过使用附加到每个单个节点标识上的安全标签，去影响这些安排决定。这些标签允许管理者将节点组与不同的安全区域连接到一起，以限制敏感负载暴露，以及使相关机密信息更安全。

![Docker Swarm Security](/data/attachment/album/201806/03/215744hfd4zgcgzfrmthde.jpg)

##### 安全分发机密

除了加快身份标识发布过程之外，管理者节点还有存储和分发工人节点所需要的任何资源的任务。机密信息像任何其它类型的资源一样处理，并且基于安全的 mTLS 连接，从管理者推送到工人节点。

![Docker Secrets](/data/attachment/album/201806/03/215745uoodd3k3e43kivvv.jpg)

在主机上，Docker 企业版能确保机密仅提供给它们指定的容器。在同一个主机上的其它容器并不能访问它们。Docker 以一个临时文件系统的方式显露机密给一个容器，确保机密总是保存在内存中，并且从不写入到磁盘。这种方式比其它竞争的替代者更加安全，比如，[在环境变量中存储它们](https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/)。一旦这个任务完成，这个机密将永远消失。

##### 存储机密

在管理者主机上的机密总是保持加密的。缺省情况下，加密这些机密的密钥（被称为数据加密密钥，DEK）是以明文的方式存储在硬盘上的。这使得那些对安全性要求较低的人可以轻松地去使用 Docker Swarm 模式。

但是，如果你运行一个生产集群，我们推荐你启用自动锁定模式。当自动锁定模式启用后，一个重新更新过的 DEK 被一个独立的加密密钥的密钥（KEK）所加密。这个密钥从不被存储在集群中；管理者有责任将它存储在一个安全可靠的地方，并且当集群启动的时候可以提供它。这就是所谓的 “解锁” Swarm。

根据 Raft 故障容错一致性算法，Swarm 模式支持多个管理者。在这个场景中，无缝扩展了机密存储的安全性。每个管理者主机除了共享密钥之外，还有一个唯一的磁盘加密密钥。幸运的是，Raft 日志在磁盘上也是加密的，并且，在自动锁定模式下，没有 KEK 同样是不可访问的。

#### 当一个节点被攻陷后发生了什么？

![Docker Secrets](/data/attachment/album/201806/03/215746h7dbkd33obobtk66.jpg)

在传统的编排器中，挽回一台被攻陷的主机是一个缓慢而复杂的过程。使用 Swarm 模式，恢复它就像运行一个 Docker 节点的 `rm` 命令一样容易。这是从集群中删除一个受影响的节点，而 Docker 将去处理剩下的事情，即，重新均衡负载，并且确保其它的主机已经知道，而不会去与受影响的节点通讯。

正如我们看到的那样，感谢最小权限的编排器，甚至是，如果攻击者在主机上持续活动，它们将被从剩余的网络上切断。主机的证书 —— 它的身份标识 —— 被列入黑名单，因此，管理者也不能有效访问它。

### 结论

使用 Swarm 模式的 Docker 企业版，在缺省情况下确保了编排器的所有关键区域的安全：

* 加入集群。阻止恶意节点加入到集群。
* 把主机分组为安全区域。阻止攻击者的横向移动。
* 安排任务。任务将仅被委派到允许的节点。
* 分配资源。恶意节点不能 “盗取” 其它的负载或者资源。
* 存储机密。从不明文保存并且从不写入到工人节点的磁盘上。
* 与工人节点的通讯。使用相互认证的 TLS 加密。

因为 Swarm 模式的持续改进，Docker 团队正在努力将最小权限原则进一步推进。我们正在处理的一个任务是：如果一个管理者被攻陷了，怎么去保证剩下的节点的安全？路线图已经有了，其中一些功能已经可以使用，比如，白名单功能，仅允许特定的 Docker 镜像，阻止管理者随意运行负载。这是通过 Docker 可信内容来实现的。

---

via: <https://blog.docker.com/2017/10/least-privilege-container-orchestration/>

作者：[Diogo Mónica](https://blog.docker.com/author/diogo/) 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


Go 程序的持续分析

Summary: Google 最有趣的部分之一就是我们规模庞大的持续分析服务。

Google 最有趣的部分之一就是我们规模庞大的持续分析服务。

![](/data/attachment/album/201806/04/110004y0orb4eeepzovqed.png)

Google 最有趣的部分之一就是我们规模庞大的持续分析服务。我们可以看到谁在使用 CPU 和内存，我们可以持续地监控我们的生产服务以争用和阻止配置文件，并且我们可以生成分析和报告，并轻松地告诉我们可以进行哪些有重要影响的优化。

我简单研究了 [Stackdriver Profiler](https://cloud.google.com/profiler/)，这是我们的新产品，它填补了针对云端用户在云服务范围内分析服务的空白。请注意，你无需在 Google 云平台上运行你的代码即可使用它。实际上，我现在每天都在开发时使用它。它也支持 Java 和 Node.js。

### 在生产中分析

pprof 可安全地用于生产。我们针对 CPU 和堆分配分析的额外会增加 5% 的开销。一个实例中每分钟收集 10 秒。如果你有一个 Kubernetes Pod 的多个副本，我们确保进行分摊收集。例如，如果你拥有一个 pod 的 10 个副本，模式，那么开销将变为 0.5％。这使用户可以一直进行分析。

我们目前支持 Go 程序的 CPU、堆、互斥和线程分析。

### 为什么？

在解释如何在生产中使用分析器之前，先解释为什么你想要在生产中进行分析将有所帮助。一些非常常见的情况是：

* 调试仅在生产中可见的性能问题。
* 了解 CPU 使用率以减少费用。
* 了解争用的累积和优化的地方。
* 了解新版本的影响，例如看到 canary 和产品级之间的区别。
* 通过[关联](https://rakyll.org/profiler-labels/)分析样本以了解延迟的根本原因来丰富你的分布式经验。

### 启用

Stackdriver Profiler 不能与 `net/http/pprof` 处理程序一起使用，并要求你在程序中安装和配置一个一行的代理。

```
go get cloud.google.com/go/profiler

```

在你的主函数中，启动分析器：

```
if err := profiler.Start(profiler.Config{
   Service:        "indexing-service",
   ServiceVersion: "1.0",
   ProjectID:      "bamboo-project-606", // optional on GCP
}); err != nil {
   log.Fatalf("Cannot start the profiler: %v", err)
}

```

当你运行你的程序后，profiler 包将每分钟报告给分析器 10 秒钟。

### 可视化

当分析被报告给后端后，你将在 <https://console.cloud.google.com/profiler> 上看到火焰图。你可以按标签过滤并更改时间范围，也可以按服务名称和版本进行细分。数据将会长达 30 天。

![](/data/attachment/album/201806/04/110031zrl3tvppvs2v67s3.gif)

你可以选择其中一个分析，按服务，区域和版本分解。你可以在火焰中移动并通过标签进行过滤。

### 阅读火焰图

[Brendan Gregg](http://www.brendangregg.com/flamegraphs.html) 非常全面地解释了火焰图可视化。Stackdriver Profiler 增加了一点它自己的特点。

![](/data/attachment/album/201806/04/110038t61nopp64mzoimvo.png)

我们将查看一个 CPU 分析，但这也适用于其他分析。

1. 最上面的 x 轴表示整个程序。火焰上的每个框表示调用路径上的一帧。框的宽度与执行该函数花费的 CPU 时间成正比。
2. 框从左到右排序，左边是花费最多的调用路径。
3. 来自同一包的帧具有相同的颜色。这里所有运行时功能均以绿色表示。
4. 你可以单击任何框进一步展开执行树。

![](/data/attachment/album/201806/04/110040svh65h9nh44v96oz.png)

你可以将鼠标悬停在任何框上查看任何帧的详细信息。

### 过滤

你可以显示、隐藏和高亮符号名称。如果你特别想了解某个特定调用或包的消耗，这些信息非常有用。

![](/data/attachment/album/201806/04/110047mix5uqofmoefimug.png)

1. 选择你的过滤器。你可以组合多个过滤器。在这里，我们将高亮显示 `runtime.memmove`。
2. 火焰将使用过滤器过滤帧并可视化过滤后的框。在这种情况下，它高亮显示所有 `runtime.memmove` 框。

---

via: <https://medium.com/google-cloud/continuous-profiling-of-go-programs-96d4416af77b>

作者：[JBD](https://medium.com/@rakyll?source=post_header_lockup) 译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

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


如何使用 Arduino 制作一个绘图仪

Summary: 使用开源硬件和软件的 DIY 绘图仪可以自动地绘制、雕刻。

使用开源硬件和软件的 DIY 绘图仪可以自动地绘制、雕刻。

>
> 使用开源硬件和软件的 DIY 绘图仪可以自动地绘制、雕刻。
>
>
>

![](/data/attachment/album/201806/04/201132zgx6x2yqywrwyucq.png)

在上学时，科学系的壁橱里藏着一台惠普绘图仪。虽然我在上学的期间可以经常使用它，但我还是想拥有一台属于自己的绘图仪。许多年之后，步进电机已经很容易获得了，我又在从事电子产品和微控制器方面的工作，最近，我看到有人用丙烯酸塑料（acrylic）制作了一个显示器。这件事启发了我，并最终制作了我自己的绘图仪。

![The plotter in action ](/data/attachment/album/201806/04/201133gnzj86j6m8a35jh5.png "The plotter in action ")

*我 DIY 的绘图仪；在这里看它工作的[视频](https://twitter.com/pilhuhn/status/948205323726344193)。*

由于我是一个很怀旧的人，我真的很喜欢最初的 [Arduino Uno](https://en.wikipedia.org/wiki/Arduino#Official_boards)。下面是我用到的其它东西的一个清单（仅供参考，其中一些我也不是很满意）：

* [FabScan shield](http://www.watterott.com/de/Arduino-FabScan-Shield)：承载步进电机驱动器。
* [SilentStepSticks](http://www.watterott.com/de/SilentStepStick-TMC2130)：步进电机驱动器，因为 Arduino 自身不能处理步进电机所需的电压和电流。因此我使用了一个 Trinamic TMC2130 芯片，但它是工作在单独模式。这些替换为 Pololu 4988，但是它们运转更安静。
* [SilentStepStick 保护装置](http://www.watterott.com/de/SilentStepStick-Protector)：一个防止你的电机驱动器转动过快的二极管（相信我，你肯定会需要它的）。
* 步进电机：我选择的是使用 12 V 电压的 NEMA 17 电机（如，来自 [Watterott](http://www.watterott.com/de/Schrittmotor-incl-Anschlusskabel) 和 [SparkFun](https://www.sparkfun.com/products/9238) 的型号）。
* [直线导杆](https://www.ebay.de/itm/CNC-Set-12x-600mm-Linearfuhrung-Linear-Guide-Rail-Stage-3D-/322917927292?hash=item4b2f68897c)
* 木制的基板
* 木螺丝
* GT2 皮带
* [GT2 同步滑轮](http://www.watterott.com/de/OpenBuilds-GT2-2mm-Aluminium-Timing-Pulley)

这是我作为个人项目而设计的。如果你想找到一个现成的工具套件，你可以从 German Make 杂志上找到 [MaXYposi](https://www.heise.de/make/artikel/MaXYposi-Projektseite-zum-universellen-XY-Portalroboter-von-Make-3676050.html)。

### 硬件安装

正如你所看到的，我刚开始做的太大了。这个绘图仪并不合适放在我的桌子上。但是，没有关系，我只是为了学习它（并且，我也将一些东西进行重新制作，下次我将使用一个更小的横梁）。

![Plotter base plate with X-axis and Y-axis rails](/data/attachment/album/201806/04/201134tufjyjyjsv3k92db.jpg "Plotter base plate with X-axis and Y-axis rails")

*带 X 轴和 Y 轴轨道的绘图仪基板*

皮带安装在轨道的侧面，并且用它将一些辅助轮和电机挂在一起：

![The belt routing on the motor](/data/attachment/album/201806/04/201134ni04ih6c9mhh94d6.jpg "The belt routing on the motor")

*电机上的皮带路由*

我在 Arduino 上堆叠了几个组件。Arduino 在最下面，它之上是 FabScan shield，接着是一个安装在 1 和 2 号电机槽上的 StepStick 保护装置，SilentStepStick 在最上面。注意，SCK 和 SDI 针脚没有连接。

![Arduino and Shield](/data/attachment/album/201806/04/201135foawg8gclon84jzt.jpg)

*Arduino 堆叠配置（[高清大图](https://www.dropbox.com/s/7bp3bo5g2ujser8/IMG_20180103_110111.jpg?dl=0)）*

注意将电机的连接线接到正确的针脚上。如果有疑问，就去查看它的数据表，或者使用欧姆表去找出哪一对线是正确的。

### 软件配置

#### 基础部分

虽然像 [grbl](https://github.com/gnea/grbl) 这样的软件可以解释诸如像装置移动和其它一些动作的 G-codes，并且，我也可以将它刷进 Arduino 中，但是我很好奇，想更好地理解它是如何工作的。（我的 X-Y 绘图仪软件可以在 [GitHub](https://github.com/pilhuhn/xy-plotter) 上找到，不过我不提供任何保修。）

使用 StepStick（或者其它兼容的）驱动器去驱动步进电机，基本上只需要发送一个高电平信号或者低电平信号到各自的针脚即可。或者使用 Arduino 的术语：

```
digitalWrite(stepPin, HIGH);
delayMicroseconds(30);
digitalWrite(stepPin, LOW);

```

在 `stepPin` 的位置上是步进电机的针脚编号：3 是 1 号电机，而 6 是 2 号电机。

在步进电机能够工作之前，它必须先被启用。

```
digitalWrite(enPin, LOW);

```

实际上，StepStick 能够理解针脚的三个状态：

* Low：电机已启用
* High：电机已禁用
* Pin 未连接：电机已启用，但在一段时间后进入节能模式

电机启用后，它的线圈已经有了力量并用来保持位置。这时候几乎不可能用手来转动它的轴。这样可以保证很好的精度，但是也意味着电机和驱动器芯片都“充满着”力量，并且也因此会发热。

最后，也是很重要的，我们需要一个决定绘图仪方向的方法：

```
digitalWrite(dirPin, direction);

```

下面的表列出了功能和针脚：

| 功能 | 1 号电机 | 2 号电机 |
| --- | --- | --- |
| 启用 | 2 | 5 |
| 方向 | 4 | 7 |
| 步进 | 3 | 6 |

在我们使用这些针脚之前，我们需要在代码的 `setup()` 节中设置它的 `OUTPUT` 模式。

```
pinMode(enPin1, OUTPUT);
pinMode(stepPin1, OUTPUT);
pinMode(dirPin1, OUTPUT);
digitalWrite(enPin1, LOW);

```

了解这些知识后，我们可以很容易地让步进电机四处移动：

```
    totalRounds = ...
    for (int rounds =0 ; rounds < 2*totalRounds; rounds++) {
       if (dir==0){ // set direction
         digitalWrite(dirPin2, LOW);
       } else {
         digitalWrite(dirPin2, HIGH);
       }
       delay(1); // give motors some breathing time
       dir = 1-dir; // reverse direction
       for (int i=0; i < 6400; i++) {
         int t = abs(3200-i) / 200;
         digitalWrite(stepPin2, HIGH);
         delayMicroseconds(70 + t);
         digitalWrite(stepPin2, LOW);
         delayMicroseconds(70 + t);
       }
    }

```

这将使滑块向左和向右移动。这些代码只操纵一个步进电机，但是，对于一个 X-Y 绘图仪，我们要考虑两个轴。

#### 命令解释器

我开始做一个简单的命令解释器去使用规范的路径，比如：

```
"X30|Y30|X-30 Y-30|X-20|Y-20|X20|Y20|X-40|Y-25|X40 Y25

```

用毫米来描述相对移动（1 毫米等于 80 步）。

绘图仪软件实现了一个 *持续模式* ，这可以允许一台 PC 给它提供一个很大的路径（很多的路径）去绘制。（在这个[视频](https://twitter.com/pilhuhn/status/949737734654124032)中展示了如何绘制 Hilbert 曲线）

### 设计一个好用的握笔器

在上面的第一张图中，绘图笔是细绳子绑到 Y 轴上的。这样绘图也不精确，并且也无法在软件中实现提笔和下笔（如示例中的大黑点）。

因此，我设计了一个更好用的、更精确的握笔器，它使用一个伺服器去提笔和下笔。可以在下面的这张图中看到这个新的、改进后的握笔器，上面视频链接中的 Hilbert 曲线就是使用它绘制的。

![Servo to raise/lower the pen ](/data/attachment/album/201806/04/201135q6wwy5ww6994w6u9.jpg "Servo to raise/lower the pen ")

*图中的特写镜头就是伺服器臂提起笔的图像*

笔是用一个小夹具固定住的（图上展示的是一个大小为 8 的夹具，它一般用于将线缆固定在墙上）。伺服器臂能够提起笔；当伺服器臂放下来的时候，笔就会被放下来。

#### 驱动伺服器

驱动伺服器是非常简单的：只需要提供位置，伺服器就可以完成所有的工作。

```
#include <Servo.h>

// Servo pin
#define servoData PIN_A1

// Positions
#define PEN_UP 10
#define PEN_DOWN 50

Servo penServo;

void setup() {
  // Attach to servo and raise pen
  penServo.attach(servoData);
  penServo.write(PEN_UP);
}

```

我把伺服器接头连接在 FabScan shield 的 4 号电机上，因此，我将用 1 号模拟针脚。

放下笔也很容易：

```
  penServo.write(PEN_DOWN);

```

### 进一步扩展

我的进一步扩展的其中一项就是添加一些终止检测器，但是，我也可以不用它们，进而使用 TMC2130 的 StallGuard 模式来代替。这些检测器也可以用于去实现一个 `home` 命令。

以后，我或许还将添加一个真实的 Z 轴，这样它就可以对一个木头进行铣削雕刻，或者钻一个 PCB 板，或者雕刻一块丙烯酸塑料，或者 … （我还想到了用激光）。

这篇文章最初发布在 [Some Things to Remember](http://pilhuhn.blogspot.com/2018/01/homegrown-xy-plotter-with-arduino.html) 博客中并授权重分发。

---

via: <https://opensource.com/article/18/3/diy-plotter-arduino>

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

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


如何在 Linux 系统中结束进程或是中止程序

Summary: 在 Linux 中有几种使用命令行或图形界面终止一个程序的方式。

在 Linux 中有几种使用命令行或图形界面终止一个程序的方式。

>
> 在 Linux 中有几种使用命令行或图形界面终止一个程序的方式。
>
>
>

![](/data/attachment/album/201806/04/221410kjzxqzhnwxy5ng6n.jpg)

进程出错的时候，您可能会想要中止或是杀掉这个进程。在本文中，我们将探索在命令行和图形界面中终止进程或是应用程序，这里我们使用 [gedit](https://wiki.gnome.org/Apps/Gedit) 作为样例程序。

### 使用命令行或字符终端界面

#### Ctrl + C

在命令行中调用 `gedit` （如果您没有使用 `gedit &` 命令）程序的一个问题是 shell 会话被阻塞，没法释放命令行提示符。在这种情况下，`Ctrl + C` （`Ctrl` 和 `C` 的组合键） 会很管用。这会终止 `gedit` ，并且所有的工作都将丢失（除非文件已经被保存）。`Ctrl + C` 会给 `gedit` 发送了 `SIGINT` 信号。这是一个默认终止进程的停止信号，它将指示 shell 停止 `gedit` 的运行，并返回到主函数的循环中，您将返回到提示符。

```
$ gedit
^C

```

#### Ctrl + Z

它被称为挂起字符。它会发送 `SIGTSTP` 信号给进程。它也是一个停止信号，但是默认行为不是杀死进程，而是挂起进程。

下面的命令将会停止（杀死/中断） `gedit` 的运行，并返回到 shell 提示符。

```
$ gedit
^Z
[1]+  Stopped                 gedit
$

```

一旦进程被挂起（以 `gedit` 为例），将不能在 `gedit` 中写入或做任何事情。而在后台，该进程变成了一个作业，可以使用 `jobs` 命令验证。

```
$ jobs
[1]+  Stopped                 gedit

```

`jobs` 允许您在单个 shell 会话中控制多个进程。您可以终止，恢复作业，或是根据需要将作业移动到前台或是后台。

让我们在后台恢复 `gedit`，释放提示符以运行其它命令。您可以通过 `bg` 命令来做到，后跟作业 ID（注意上面的 `jobs` 命令显示出来的 `[1]`，这就是作业 ID）。

```
$ bg 1
[1]+ gedit &

```

这和直接使用 `gedit &` 启动程序效果差不多：

```
$ gedit &

```

### 使用 kill

`kill` 命令提供信号的精确控制，允许您通过指定信号名或是信号数字为进程发送信号，后跟进程 ID 或是 PID。

我喜欢 `kill` 命令的一点是它也能够根据作业 ID 控制进程。让我们使用 `gedit &` 命令在后台开启 `gedit` 服务。假设通过 `jobs` 命令我得到了一个 `gedit` 的作业 ID，让我们为 `gedit` 发送 `SIGINT` 信号：

```
$ kill -s SIGINT %1

```

作业 ID 需要使用 `%` 前缀，不然 `kill` 会将其视作 PID。

不明确指定信号，`kill` 仍然可以工作。此时，默认会发送能中断进程的 `SIGTERM` 信号。执行 `kill -l` 可以查看信号名列表，使用 `man kill` 命令阅读手册。

### 使用 killall

如果您不想使用特定的工作 ID 或者 PID，`killall` 允许您使用特定的进程名。中断 `gedit` 最简单的 `killall` 使用方式是：

```
$ killall gedit

```

它将终止所有名为 `gedit` 的进程。和 `kill` 相似，默认发送的信号是 `SIGTERM`。使用 `-I` 选项忽略进程名的大小写。

```
$ gedit &
[1] 14852

$ killall -I GEDIT
[1]+  Terminated              gedit

```

查看手册学习更多 `killall` 命令选项（如 `-u`）。

### 使用 xkill

您是否遇见过播放器崩溃，比如 [VLC](https://www.videolan.org/vlc/index.html) 灰屏或挂起？现在你可以像上面一样获得进程的 PID 来杀掉它，或者使用 `xkill` 命令终止应用程序。

![Using xkill](/data/attachment/album/201806/04/221425pvqtbbhuvpcqhiu4.png "Using xkill")

`xkill` 允许您使用鼠标关闭窗口。仅需在终端执行 `xkill` 命令，它将会改变鼠标光标为一个 **X** 或是一个小骷髅图标。在你想关闭的进程窗口上点击 **x**。小心使用 `xkill`，如手册描述的一致，它很危险。我已经提醒过您了！

参阅手册，了解上述命令更多信息。您还可以接续探索 `pkill` 和 `pgrep` 命令。

---

via: <https://opensource.com/article/18/5/how-kill-process-stop-program-linux>

作者：[Sachin Patil](https://opensource.com/users/psachin) 选题：[lujun9972](https://github.com/lujun9972) 译者：[CYLeft](https://github.com/CYLeft) 校对：[wxy](https://github.com/wxy)

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


3 个 Python 模板库比较

>
> 你的下一个 Python 项目需要一个模板引擎来自动生成 HTML 吗？这有几种选择。
>
>
>

![](/data/attachment/album/201806/04/223936dcd4s2zszs4g3qu1.png)

在我的日常工作中，我花费大量的时间将各种来源的数据转化为可读的信息。虽然很多时候这只是电子表格或某种类型的图表或其他数据可视化的形式，但也有其他时候，将数据以书面形式呈现是有意义的。

但我的头疼地方就是复制和粘贴。如果你要将数据从源头移动到标准化模板，则不应该复制和粘贴。这很容易出错，说实话，这会浪费你的时间。

因此，对于我定期发送的任何遵循一个共同的模式的信息，我倾向于找到某种方法来自动化至少一部分信息。也许这涉及到在电子表格中创建一些公式，一个快速 shell 脚本或其他解决方案，以便使用从外部源提取的信息自动填充模板。

但最近，我一直在探索 Python 模板来完成从其他数据集创建报告和图表的大部分工作。

Python 模板引擎非常强大。我的简化报告创建的使用案例仅仅触及了它的皮毛。许多开发人员正在利用这些工具来构建完整的 web 应用程序和内容管理系统。但是，你并不需要有一个复杂的 web 应用程序才能使用 Python 模板工具。

### 为什么选择模板？

每个模板工具都不甚相同，你应该阅读文档以了解其确切的用法。但让我们创建一个假设的例子。假设我想创建一个简短的页面，列出我最近编写的所有 Python 主题。就像这样：

```
<html>
  <head>
    <title>My Python articles</title>
  </head>
  <body>

    <p>These are some of the things I have written about Python:</p>
    <ul>
      <li>Python GUIs</li>
      <li>Python IDEs</li>
      <li>Python web scrapers</li>
    </ul>

  </body>
</html>

```

当它仅仅是这三个项目时，维护它是很简单的。但是当我想添加第四个、第五个或第六十七个时会发生什么？我可以从包含我所有页面列表的 CSV 文件或其他数据文件生成它，而不是手动编码此页面吗？我可以轻松地为我写的每个主题创建重复内容吗？我可以以编程方式更改每个页面上的文本标题吗？这就是模板引擎可以发挥作用的地方。

有许多不同的选择，今天我将与你其中分享三个，顺序不分先后：[Mako](http://www.makotemplates.org/)、 [Jinja2](http://jinja.pocoo.org/) 和 [Genshi](https://genshi.edgewall.org/)。

### Mako

[Mako](http://www.makotemplates.org/) 是以 MIT 许可证发布的 Python 模板工具，专为快速展现而设计的（与 Jinja2 不同）。Reddit 已经使用 Mako 来展现他们的网页，它同时也是 Pyramid 和 Pylons 等 web 框架的默认模板语言。它相当简单且易于使用。你可以使用几行代码来设计模板；支持 Python 2.x 和 3.x，它是一个功能强大且功能丰富的工具，具有[良好的文档](http://docs.makotemplates.org/en/latest/)，这一点我认为是必须的。其功能包括过滤器、继承、可调用块和内置缓存系统，这些系统可以被大型或复杂的 web 项目导入。

### Jinja2

Jinja2 是另一个快速且功能全面的选项，可用于 Python 2.x 和 3.x，遵循 BSD 许可证。Jinja2 从功能角度与 Mako 有很多重叠，因此对于新手来说，你在两者之间的选择可能会归结为你喜欢的格式化风格。Jinja2 还将模板编译为字节码，并具有 HTML 转义、沙盒、模板继承和模板沙盒部分的功能。其用户包括 Mozilla、 SourceForge、 NPR、 Instagram 等，并且还具有[强大的文档](http://jinja.pocoo.org/docs/2.10/)。与 Mako 在模板内部使用 Python 逻辑不同的是，Jinja2 使用自己的语法。

### Genshi

[Genshi](https://genshi.edgewall.org/) 是我会提到的第三个选择。它是一个 XML 工具，具有强大的模板组件，所以如果你使用的数据已经是 XML 格式，或者你需要使用网页以外的格式，Genshi 可能成为你的一个很好的解决方案。HTML 基本上是一种 XML（好吧，不是精确的，但这超出了本文的范围，有点卖弄学问了），因此格式化它们非常相似。由于我通常使用的很多数据都是 XML 或其他类型的数据，因此我非常喜欢使用我可以用于多种事物的工具。

发行版目前仅支持 Python 2.x，尽管 Python 3 支持存在于主干中，但我提醒你，它看起来并没有得到有效的开发。Genshi 遵循 BSD 许可证提供。

### 示例

因此，在上面的假设示例中，我不会每次写新主题时都更新 HTML 文件，而是通过编程方式对其进行更新。我可以创建一个模板，如下所示：

```
<html>
  <head>
    <title>My Python articles</title>
  </head>
  <body>

    <p>These are some of the things I have written about Python:</p>
    <ul>
      %for topic in topics:
      <li>${topic}</li>
      %endfor
    </ul>

  </body>
</html>

```

然后我可以使用我的模板库来迭代每个主题，比如使用 Mako，像这样：

```
from mako.template import Template

mytemplate = Template(filename='template.txt')
print(mytemplate.render(topics=("Python GUIs","Python IDEs","Python web scrapers")))

```

当然，在现实世界的用法中，我不会将这些内容手动地列在变量中，而是将它们从外部数据源（如数据库或 API）中提取出来。

这些不是仅有的 Python 模板引擎。如果你正在开始创建一个将大量使用模板的新项目，那么你考虑的可能不仅仅是这三种选择。在 [Python 维基](https://wiki.python.org/moin/Templating)上查看更全面的列表，以获得更多值得考虑的项目。

---

via: <https://opensource.com/resources/python/template-libraries>

作者：[Jason Baker](https://opensource.com/users/jason-baker) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


Linux vs. Unix：有什么不同？

Summary: 深入了解这两个有许多共同的传统和相同的目标的操作系统之间的不同。

深入了解这两个有许多共同的传统和相同的目标的操作系统之间的不同。

>
> 深入了解这两个有许多共同的传统和相同的目标的操作系统之间的不同。
>
>
>

![](/data/attachment/album/201806/05/221628zcsu1oi3ofe6ei1c.jpg)

如果你是位二、三十岁的软件开发人员，那么你已经成长在一个由 Linux 主导的世界。数十年来，它一直是数据中心的重要参与者，尽管很难找到明确的操作系统市场份额报告，但 Linux 的数据中心操作系统份额可能高达 70%，而 Windows 及其变体几乎涵盖了所有剩余的百分比。使用任何主流公共云服务的开发人员都可以预期目标系统会运行 Linux。近些年来，随着 Android 和基于 Linux 的嵌入式系统在智能手机、电视、汽车和其他设备中的应用，Linux 已经随处可见。

即便如此，大多数软件开发人员，甚至是那些在这场历史悠久的 “Linux 革命”中长大的软件开发人员，也都听过说 Unix。它听起来与 Linux 相似，你可能已经听到人们互换使用这些术语。或者你也许听说过 Linux 被称为“类 Unix ”操作系统。

那么，Unix 是什么？漫画中提到了像巫师一样留着“灰胡子”，坐在发光的绿色屏幕后面，写着 C 代码和 shell 脚本，由老式的、滴灌的咖啡提供动力。但是，Unix 的历史比上世纪 70 年代那些留着胡子的 C 程序员要丰富得多。虽然详细介绍 Unix 历史和 “Unix 与 Linux” 比较的文章比比皆是，但本文将提供高级背景和列出这些互补世界之间的主要区别。

### Unix 的起源

Unix 的历史始于 20 世纪 60 年代后期的 AT&T 贝尔实验室，有一小组程序员希望为 PDP-7 编写一个多任务、多用户操作系统。这个贝尔实验室研究机构的团队中最著名的两名成员是 Ken Thompson 和 Dennis Ritchie。尽管 Unix 的许多概念都是其前身（[Multics](https://en.wikipedia.org/wiki/Multics)）的衍生物，但 Unix 团队早在 70 年代就决定用 C 语言重写这个小型操作系统，这是将 Unix 与其他操作系统区分开来的原因。当时，操作系统很少，更不要说可移植的操作系统。相反，由于它们的设计和底层语言的本质，操作系统与他们所编写的硬件平台紧密相关。而通过 C 语言重构 Unix、Unix 现在可以移植到许多硬件体系结构中。

除了这种新的可移植性，之所以使得 Unix 迅速扩展到贝尔实验室以外的其他研究和学术机构甚至商业用途，是因为操作系统设计原则的几个关键点吸引了用户和程序员们。首先是 Ken Thompson 的 [Unix 哲学](https://en.wikipedia.org/wiki/Unix_philosophy)成为模块化软件设计和计算的强大模型。Unix 哲学推荐使用小型的、专用的程序组合起来完成复杂的整体任务。由于 Unix 是围绕文件和管道设计的，因此这种“管道”模式的输入和输出程序的组合成一组线性的输入操作，现在仍然流行。事实上，目前的云功能即服务（FaaS）或无服务器计算模型要归功于 Unix 哲学的许多传统。

### 快速增长和竞争

到 70 年代末和 80 年代，Unix 成为了一个操作系统家族的起源，它遍及了研究和学术机构以及日益增长的商业 Unix 操作系统业务领域。Unix 不是开源软件，Unix 源代码可以通过与它的所有者 AT&T 达成协议来获得许可。第一个已知的软件许可证于 1975 年出售给<ruby> 伊利诺伊大学 <rt>  University of Illinois </rt></ruby>。

Unix 在学术界迅速发展，在 Ken Thompson 在上世纪 70 年代的学术假期间，伯克利成为一个重要的活动中心。通过在伯克利的各种有关 Unix 的活动，Unix 软件的一种新的交付方式诞生了：<ruby> 伯克利软件发行版 <rt>  Berkeley Software Distribution </rt></ruby>（BSD）。最初，BSD 不是 AT&T Unix 的替代品，而是一种添加类似于附加软件和功能。在 1979 年， 2BSD（第二版伯克利软件发行版）出现时，伯克利研究生 Bill Joy 已经添加了现在非常有名的程序，例如 `vi` 和 C shell（`/bin/csh`）。

除了成为 Unix 家族中最受欢迎的分支之一的 BSD 之外，Unix 的商业产品的爆发贯穿了二十世纪八、九十年代，其中包括 HP-UX、IBM 的 AIX、 Sun 的 Solaris、 Sequent 和 Xenix 等。随着分支从根源头发展壮大，“[Unix 战争](https://en.wikipedia.org/wiki/Unix_wars)”开始了，标准化成为社区的新焦点。POSIX 标准诞生于 1988 年，其他标准化后续工作也开始通过 The Open Group 在 90 年代到来。

在此期间，AT&T 和 Sun 发布了 System V Release 4（SVR4），许多商业供应商都采用了这一版本。另外，BSD 系列操作系统多年来一直在增长，最终一些开源的变体在现在熟悉的 [BSD许可证](https://en.wikipedia.org/wiki/BSD_licenses)下发布。这包括 FreeBSD、 OpenBSD 和 NetBSD，每个在 Unix 服务器行业的目标市场略有不同。这些 Unix 变体今天仍然有一些在使用，尽管人们已经看到它们的服务器市场份额缩小到个位数字（或更低）。在当今的所有 Unix 系统中，BSD 可能拥有最大的安装基数。另外，每台 Apple Mac 硬件设备从历史的角度看都可以算做是 BSD ，这是因为 OS X（现在是 macOS）操作系统是 BSD 衍生产品。

虽然 Unix 的全部历史及其学术和商业变体可能需要更多的篇幅，但为了我们文章的重点，让我们来讨论 Linux 的兴起。

### 进入 Linux

今天我们所说的 Linux 操作系统实际上是 90 年代初期的两个努力的结合。Richard Stallman 希望创建一个真正的自由而开放源代码的专有 Unix 系统的替代品。他正在以 GNU 的名义开发实用程序和程序，这是一种递归的说法，意思是“GNU‘s not Unix!”。虽然当时有一个内核项目正在进行，但事实证明这是一件很困难的事情，而且没有内核，自由和开源操作系统的梦想无法实现。而这是 Linus Torvald 的工作 —— 生产出一种可工作和可行的内核，他称之为 Linux -- 它将整个操作系统带入了生活。鉴于 Linus 使用了几个 GNU 工具（例如 GNU 编译器集合，即 [GCC](https://en.wikipedia.org/wiki/GNU_Compiler_Collection)），GNU 工具和 Linux 内核的结合是完美的搭配。

Linux 发行版采用了 GNU 的组件、Linux 内核、MIT 的 X-Windows GUI 以及可以在开源 BSD 许可下使用的其它 BSD 组件。像 Slackware 和 Red Hat 这样的发行版早期的流行给了 20 世纪 90 年代的“普通 PC 用户”一个进入 Linux 操作系统的机会，并且让他们在工作和学术生活中可以使用许多 Unix 系统特有的功能和实用程序。

由于所有 Linux 组件都是自由和开放的源代码，任何人都可以通过一些努力来创建一个 Linux 发行版，所以不久后发行版的总数达到了数百个。今天，[distrowatch.com](https://distrowatch.com/) 列出了 312 种各种形式的独特的 Linux 发行版。当然，许多开发人员通过云提供商或使用流行的免费发行版来使用 Linux，如 Fedora、 Canonical 的 Ubuntu、 Debian、 Arch Linux、 Gentoo 和许多其它变体。随着包括 IBM 在内的许多企业从专有 Unix 迁移到 Linux 上并提供了中间件和软件解决方案，商用 Linux 产品在自由和开源组件之上提供支持变得可行。红帽公司围绕 Red Hat Enterprise Linux（红帽企业版 Linux） 建立了商业支持模式，德国供应商 SUSE 使用 SUSE Linux Enterprise Server（SLES）也提供了这种模式。

### 比较 Unix 和 Linux

到目前为止，我们已经了解了 Unix 的历史以及 Linux 的兴起，以及 GNU/自由软件基金会对 Unix 的自由和开源替代品的支持。让我们来看看这两个操作系统之间的差异，它们有许多共同的传统和许多相同的目标。

从用户体验角度来看，两者差不多！Linux 的很大吸引力在于操作系统在许多硬件体系结构（包括现代 PC）上的可用性以及类似使用 Unix 系统管理员和用户熟悉的工具的能力。

由于 POSIX 的标准和合规性，在 Unix 上编写的软件可以针对 Linux 操作系统进行编译，通常只有少量的移植工作量。在很多情况下，Shell 脚本可以在 Linux 上直接使用。虽然一些工具在 Unix 和 Linux 之间有着略微不同的标志或命令行选项，但许多工具在两者上都是相同的。

一方面要注意的是，macOS 硬件和操作系统作为主要针对 Linux 的开发平台的流行可能归因于类 BSD 的 macOS 操作系统。许多用于 Linux 系统的工具和脚本可以在 macOS 终端内轻松工作。Linux 上的许多开源软件组件都可以通过 [Homebrew](https://brew.sh/) 等工具轻松获得。

Linux 和 Unix 之间的其他差异主要与许可模式有关：开源与专有许可软件。另外，在 Unix 发行版中缺少一个影响软件和硬件供应商的通用内核。对于 Linux，供应商可以为特定的硬件设备创建设备驱动程序，并期望在合理的范围内它可以在大多数发行版上运行。由于 Unix 家族的商业和学术分支，供应商可能必须为 Unix 的变体编写不同的驱动程序，并且需要许可和其他相关的权限才能访问 SDK 或软件的分发模型，以跨越多个二进制设备驱动程序的 Unix 变体。

随着这两个社区在过去十年中的成熟，Linux 的许多优点已经在 Unix 世界中被采用。当开发人员需要来自不属于 Unix 的 GNU 程序的功能时，许多 GNU 实用程序可作为 Unix 系统的附件提供。例如，IBM 的 AIX 为 Linux 应用程序提供了一个 AIX Toolbox，其中包含数百个 GNU 软件包（如 Bash、 GCC、 OpenLDAP 和许多其他软件包），这些软件包可添加到 AIX 安装包中以简化 Linux 和基于 Unix 的 AIX 系统之间的过渡。

专有的 Unix 仍然活着而且还不错，许多主要供应商承诺支持其当前版本，直到 2020 年。不言而喻，Unix 还会在可预见的将来一直出现。此外，Unix 的 BSD 分支是开源的，而 NetBSD、 OpenBSD 和 FreeBSD 都有强大的用户基础和开源社区，它们可能不像 Linux 那样显眼或活跃，但在最近的服务器报告中，在 Web 服务等领域它们远高于专有 Unix 的数量。

Linux 已经显示出其超越 Unix 的显著优势在于其在大量硬件平台和设备上的可用性。<ruby> 树莓派 <rt>  Raspberry Pi </rt></ruby>受到业余爱好者的欢迎，它是由 Linux 驱动的，为运行 Linux 的各种物联网设备打开了大门。我们已经提到了 Android 设备，汽车（包括 Automotive Grade Linux）和智能电视，其中 Linux 占有巨大的市场份额。这个星球上的每个云提供商都提供运行 Linux 的虚拟服务器，而且当今许多最受欢迎的原生云架构都是基于 Linux 的，无论你是在谈论容器运行时还是 Kubernetes，或者是许多正在流行的无服务器平台。

其中一个最显著的代表 Linux 的优势是近年来微软的转变。如果你十年前告诉软件开发人员，Windows 操作系统将在 2016 年“运行 Linux”，他们中的大多数人会歇斯底里地大笑。 但是 Windows Linux 子系统（WSL）的存在和普及，以及最近宣布的诸如 Docker 的 Windows 移植版，包括 LCOW（Windows 上的 Linux 容器）支持等功能都证明了 Linux 在整个软件世界中所产生的影响 —— 而且显然还会继续存在。

---

via: <https://opensource.com/article/18/5/differences-between-linux-and-unix>

作者：[Phil Estes](https://opensource.com/users/estesp) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


使用 GNU Parallel 提高 Linux 命令行执行效率

Summary: 将您的计算机变成一个多任务的动力室。

将您的计算机变成一个多任务的动力室。

>
> 将您的计算机变成一个多任务的动力室。
>
>
>

![](/data/attachment/album/201806/06/101823qlborkn96moromor.jpg)

你是否有过这种感觉，你的主机运行速度没有预期的那么快？我也曾经有过这种感觉，直到我发现了 GNU Parallel。

GNU Parallel 是一个 shell 工具，可以并行执行任务。它可以解析多种输入，让你可以同时在多份数据上运行脚本或命令。你终于可以使用全部的 CPU 了！

如果你用过 `xargs`，上手 Parallel 几乎没有难度。如果没有用过，这篇教程会告诉你如何使用，同时给出一些其它的用例。

### 安装 GNU Parallel

GNU Parallel 很可能没有预装在你的 Linux 或 BSD 主机上，你可以从软件源中安装。以 Fedora 为例：

```
$ sudo dnf install parallel

```

对于 NetBSD：

```
# pkg_add parallel

```

如果各种方式都不成功，请参考[项目主页](https://www.gnu.org/software/parallel)。

### 从串行到并行

正如其名称所示，Parallel 的强大之处是以并行方式执行任务；而我们中不少人平时仍然以串行方式运行任务。

当你对多个对象执行某个命令时，你实际上创建了一个任务队列。一部分对象可以被命令处理，剩余的对象需要等待，直到命令处理它们。这种方式是低效的。只要数据够多，总会形成任务队列；但与其只使用一个任务队列，为何不使用多个更小规模的任务队列呢？

假设你有一个图片目录，你希望将目录中的图片从 JEEG 格式转换为 PNG 格式。有多种方法可以完成这个任务。可以手动用 GIMP 打开每个图片，输出成新格式，但这基本是最差的选择，费时费力。

上述方法有一个漂亮且简洁的变种，即基于 shell 的方案：

```
$ convert 001.jpeg 001.png
$ convert 002.jpeg 002.png
$ convert 003.jpeg 003.png
... 略 ...

```

对于初学者而言，这是一个不小的转变，而且看起来是个不小的改进。不再需要图像界面和不断的鼠标点击，但仍然是费力的。

进一步改进：

```
$ for i in *jpeg; do convert $i $i.png ; done

```

至少，这一步设置好任务执行，让你节省时间去做更有价值的事情。但问题来了，这仍然是串行操作；一张图片转换完成后，队列中的下一张进行转换，依此类推直到全部完成。

使用 Parallel:

```
$ find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png

```

这是两条命令的组合：`find` 命令，用于收集需要操作的对象；`parallel` 命令，用于对象排序并确保每个对象按需处理。

* `find . -name "*jpeg"` 查找当前目录下以 `jpeg` 结尾的所有文件。
* `parallel` 调用 GNU Parallel。
* `-I%` 创建了一个占位符 `%`，代表 `find` 传递给 Parallel 的内容。如果不使用占位符，你需要对 `find` 命令的每一个结果手动编写一个命令，而这恰恰是你想要避免的。
* `--max-args 1` 给出 Parallel 从队列获取新对象的速率限制。考虑到 Parallel 运行的命令只需要一个文件输入，这里将速率限制设置为 1。假如你需要执行更复杂的命令，需要两个文件输入（例如 `cat 001.txt 002.txt > new.txt`），你需要将速率限制设置为 2。
* `convert % %.png` 是你希望 Parallel 执行的命令。

组合命令的执行效果如下：`find` 命令收集所有相关的文件信息并传递给 `parallel`，后者（使用当前参数）启动一个任务，（无需等待任务完成）立即获取参数行中的下一个参数（LCTT 译注：管道输出的每一行对应 `parallel` 的一个参数，所有参数构成参数行）；只要你的主机没有瘫痪，Parallel 会不断做这样的操作。旧任务完成后，Parallel 会为分配新任务，直到所有数据都处理完成。不使用 Parallel 完成任务大约需要 10 分钟，使用后仅需 3 至 5 分钟。

### 多个输入

只要你熟悉 `find` 和 `xargs` （整体被称为 GNU 查找工具，或 `findutils`），`find` 命令是一个完美的 Parallel 数据提供者。它提供了灵活的接口，大多数 Linux 用户已经很习惯使用，即使对于初学者也很容易学习。

`find` 命令十分直截了当：你向 `find` 提供搜索路径和待查找文件的一部分信息。可以使用通配符完成模糊搜索；在下面的例子中，星号匹配任何字符，故 `find` 定位（文件名）以字符 `searchterm` 结尾的全部文件：

```
$ find /path/to/directory -name "*searchterm"

```

默认情况下，`find` 逐行返回搜索结果，每个结果对应 1 行：

```
$ find ~/graphics -name "*jpg"
/home/seth/graphics/001.jpg
/home/seth/graphics/cat.jpg
/home/seth/graphics/penguin.jpg
/home/seth/graphics/IMG_0135.jpg

```

当使用管道将 `find` 的结果传递给 `parallel` 时，每一行中的文件路径被视为 `parallel` 命令的一个参数。另一方面，如果你需要使用命令处理多个参数，你可以改变队列数据传递给 `parallel` 的方式。

下面先给出一个不那么实际的例子，后续会做一些修改使其更加有意义。如果你安装了 GNU Parallel，你可以跟着这个例子操作。

假设你有 4 个文件，按照每行一个文件的方式列出，具体如下：

```
$ echo ada > ada ; echo lovelace > lovelace
$ echo richard > richard ; echo stallman > stallman
$ ls -1
ada
lovelace
richard
stallman

```

你需要将两个文件合并成第三个文件，后者同时包含前两个文件的内容。这种情况下，Parallel 需要访问两个文件，使用 `-I%` 变量的方式不符合本例的预期。

Parallel 默认情况下读取 1 个队列对象：

```
$ ls -1 | parallel echo
ada
lovelace
richard
stallman

```

现在让 Parallel 每个任务使用 2 个队列对象：

```
$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman

```

现在，我们看到行已经并合并；具体而言，`ls -1` 的两个查询结果会被同时传送给 Parallel。传送给 Parallel 的参数涉及了任务所需的 2 个文件，但目前还只是 1 个有效参数：（对于两个任务分别为）“ada lovelace” 和 “richard stallman”。你真正需要的是每个任务对应 2 个独立的参数。

值得庆幸的是，Parallel 本身提供了上述所需的解析功能。如果你将 `--max-args` 设置为 `2`，那么 `{1}` 和 `{2}` 这两个变量分别代表传入参数的第一和第二部分：

```
$ ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person

```

在上面的命令中，变量 `{1}` 值为 `ada` 或 `richard` （取决于你选取的任务），变量 `{2}` 值为 `lovelace` 或 `stallman`。通过使用重定向符号（放到引号中，防止被 Bash 识别，以便 Parallel 使用），（两个）文件的内容被分别重定向至新文件 `ada_lovelace.person` 和 `richard_stallman.person`。

```
$ ls -1
ada
ada_lovelace.person
lovelace
richard
richard_stallman.person
stallman

$ cat ada_*person
ada lovelace
$ cat ri*person
richard stallman

```

如果你整天处理大量几百 MB 大小的日志文件，那么（上述）并行处理文本的方法对你帮忙很大；否则，上述例子只是个用于上手的示例。

然而，这种处理方法对于很多文本处理之外的操作也有很大帮助。下面是来自电影产业的真实案例，其中需要将一个目录中的视频文件和（对应的）音频文件进行合并。

```
$ ls -1
12_LS_establishing-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...略...

```

使用同样的方法，使用下面这个简单命令即可并行地合并文件：

```
$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv

```

### 简单粗暴的方式

上述花哨的输入输出处理不一定对所有人的口味。如果你希望更直接一些，可以将一堆命令甩给 Parallel，然后去干些其它事情。

首先，需要创建一个文本文件，每行包含一个命令：

```
$ cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar

```

接着，将文件传递给 Parallel：

```
$ parallel --jobs 6 < jobs2run

```

现在文件中对应的全部任务都在被 Parallel 执行。如果任务数量超过允许的数目（LCTT 译注：应该是 `--jobs` 指定的数目或默认值），Parallel 会创建并维护一个队列，直到任务全部完成。

### 更多内容

GNU Parallel 是个强大而灵活的工具，还有很多很多用例无法在本文中讲述。工具的 man 页面提供很多非常酷的例子可供你参考，包括通过 SSH 远程执行和在 Parallel 命令中使用 Bash 函数等。[YouTube](https://www.youtube.com/watch?v=OpaiGYxkSuQ&list=PL284C9FF2488BC6D1) 上甚至有一个系列，包含大量操作演示，让你可以直接从 GNU Parallel 团队学习。GNU Paralle 的主要维护者还发布了官方使用指导手册，可以从 [Lulu.com](http://www.lulu.com/shop/ole-tange/gnu-parallel-2018/paperback/product-23558902.html) 获取。

GNU Parallel 有可能改变你完成计算的方式；即使没有，也会至少改变你主机花在计算上的时间。马上上手试试吧！

---

via: <https://opensource.com/article/18/5/gnu-parallel>

作者：[Seth Kenlon](https://opensource.com/users/seth) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

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


使用 Buildah 创建小体积的容器

Summary: 技术问题推动了开源协作的力量。

技术问题推动了开源协作的力量。

>
> 技术问题推动了开源协作的力量。
>
>
>

![](/data/attachment/album/201806/06/104008xf00r3xfqjh03913.png)

我最近加入了 Red Hat，在这之前我在另外一家科技公司工作了很多年。在我的上一份工作岗位上，我开发了不少不同类型的软件产品，这些产品是成功的，但都有版权保护。不仅法规限制了我们不能在公司外将软件共享，而且我们在公司内部也基本不进行共享。在那时，我觉得这很有道理：公司花费了时间、精力和预算用于开发软件，理应保护并要求软件涉及的利益。

时间如梭，去年我加入 Red Hat 并培养出一种完全不同的理念。[Buildah 项目](https://github.com/projectatomic/buildah)是我最早加入的项目之一，该项目用于构建 OCI (Open Container Initiative) 标准的镜像，特别擅长让你精简创建好的镜像的体积。那时 Buildah 还处于非常早期的阶段，包含一些瑕疵，不适合用于生产环境。

刚接触项目不久，我做了一些小变更，然后询问公司内部 git 仓库地址，以便提交我做的变更。收到的回答是：没有内部仓库，直接将变更提交到 GitHub 上。这让我感到困惑，将我的变更提交到 GitHub 意味着：任何人都可以查看这部分代码并在他们自己的项目中使用。况且代码还有一些瑕疵，这样做简直有悖常理。但作为一个新人，我只是惊讶地摇了摇头并提交了变更。

一年后，我终于相信了开源软件的力量和价值。我仍为 Buildah 项目工作，我们最近遇到的一个主题很形象地说明了这种力量和价值。这个标题为 [Buildah 镜像体积并不小？](https://github.com/projectatomic/buildah/issues/532) 的工单由 Tim Dudgeon (@tdudgeon) 提出。简而言之，他发现使用 Buildah 创建的镜像比使用 Docker 创建的镜像体积更大，而且 Buildah 镜像中并不包含一些额外应用，但 Docker 镜像中却包含它们。

为了比较，他首先操作如下：

```
$ docker pull centos:7
$ docker images
REPOSITORY            TAG              IMAGE ID                 CREATED             SIZE
docker.io/centos          7                   2d194b392dd1        2 weeks ago         195 MB

```

他发现 Docker 镜像的体积为 195MB。Tim 接着使用 Buildah 创建了一个（基于 scratch 的）最小化镜像，仅仅将 `coreutils` 和 `bash` 软件包加入到镜像中，使用的脚本如下：

```
$ cat  ./buildah-base.sh
#!/bin/bash

set -x

# build a minimal image
newcontainer=$(buildah from scratch)
scratchmnt=$(buildah mount $newcontainer)

# install the packages
yum install --installroot $scratchmnt bash coreutils --releasever 7 --setopt install_weak_deps=false -y
yum clean all -y --installroot $scratchmnt --releasever 7

sudo buildah config --cmd /bin/bash $newcontainer

# set some config info
buildah config --label name=centos-base $newcontainer

# commit the image
buildah unmount $newcontainer
buildah commit $newcontainer centos-base

$ sudo ./buildah-base.sh

$ sudo buildah images
IMAGE ID               IMAGE NAME                                             CREATED AT            SIZE
8379315d3e3e     docker.io/library/centos-base:latest           Mar 25, 2018 17:08   212.1 MB

```

Tim 想知道为何 Buildah 镜像体积反而大 17MB，毕竟 `python` 和 `yum` 软件包都没有安装到 Buildah 镜像中，而这些软件已经安装到 Docker 镜像中。这个结果并不符合预期，在 Github 的相关主题中引发了广泛的讨论。

不仅 Red Hat 的员工参与了讨论，还有不少公司外人士也加入了讨论，这很有意义。值得一提的是，GitHub 用户 @pixdrift 主导了很多重要的讨论并提出很多发现，他指出在这个 Buildah 镜像中文档和语言包就占据了比 100MB 略多一点的空间。Pixdrift 建议在 yum 安装器中强制指定语言，据此提出如下修改过的 `buildah-bash.sh` 脚本：

```
#!/bin/bash

set -x

# build a minimal image
newcontainer=$(buildah from scratch)
scratchmnt=$(buildah mount $newcontainer)

# install the packages
yum install --installroot $scratchmnt bash coreutils --releasever 7 --setopt=install_weak_deps=false --setopt=tsflags=nodocs --setopt=override_install_langs=en_US.utf8 -y
yum clean all -y --installroot $scratchmnt --releasever 7

sudo buildah config --cmd /bin/bash $newcontainer

# set some config info
buildah config --label name=centos-base $newcontainer

# commit the image
buildah unmount $newcontainer
buildah commit $newcontainer centos-base

```

Tim 运行这个新脚本，得到的镜像体积缩减至 92MB，相比之前的 Buildah 镜像体积减少了 120MB，这比较接近我们的预期；然而，出于工程师的天性，56% 的体积缩减不能让他们满足。讨论继续深入下去，涉及如何移除个人语言包以节省更多空间。如果想了解讨论细节，点击 [Buildah 镜像体积并不小？](https://github.com/projectatomic/buildah/issues/532) 这个链接。说不定你也能给出有帮助的点子，甚至更进一步成为 Buildah 项目的贡献者。这个主题的解决从一个侧面告诉我们，Buildah 软件可以多么快速和容易地创建体积最小化的容器，该容器仅包含你高效运行任务所需的软件。额外的好处是，你无需运行一个守护进程。

这个镜像体积缩减的主题让我意识到开源软件的力量。来自不同公司的大量开发者，在一天多的时间内，以开放讨论的形式进行合作解决问题。虽然解决这个具体问题并没有修改已有代码，但 Red Hat 公司外开发者对 Buildah 做了很多代码贡献，进而帮助项目变得更好。这些贡献也吸引了更多人才关注项目代码；如果像之前那样，代码作为版权保护软件的一部分放置在私有 git 仓库中，不会获得上述好处。我只用了一年的时间就转向拥抱 [开源方式](https://twitter.com/opensourceway)，而且可能不会再转回去了。

文章最初发表于 [Project Atomic](http://www.projectatomic.io/blog/2018/04/open-source-what-a-concept/)，已获得转载许可。

---

via: <https://opensource.com/article/18/5/containers-buildah>

作者：[Tom Sweeney](https://opensource.com/users/tomsweeneyredhat) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

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


5 个理由，开源助你求职成功

Summary: 为开源项目工作可以给你或许从其他地方根本得不到的经验和人脉。

为开源项目工作可以给你或许从其他地方根本得不到的经验和人脉。

>
> 为开源项目工作可以给你或许从其他地方根本得不到的经验和人脉。
>
>
>

![](/data/attachment/album/201806/06/110106s2klxgan0c4n305f.png)

你正在在繁华的技术行业中寻找工作吗？无论你是寻找新挑战的技术团体老手，还是正在寻找第一份工作的毕业生，参加开源项目都是可以让你在众多应聘者中脱颖而出的好方法。以下是从事开源项目工作可以增强你求职竞争力的五个理由。

### 1、 获得项目经验

或许从事开源项目工作能带给你的最明显的好处是提供了项目经验。如果你是一个学生，你可能没有很多实质上的项目可以在你的简历中展示。如果你还在工作，由于保密限制，或者你对正在完成的任务不感兴趣，你不能或者不能很详细的讨论你当前的项目。无论那种情况，找出并参加那些有吸引力的，而且又正好可以展现你的技能的开源项目，无疑对求职有帮助。这些项目不仅在众多简历中引人注目，而且可以是面试环节中完美的谈论主题。

另外，很多开源项目托管在公共仓库（比如 [Github](https://github.com/dbaldwin/DronePan) ）上，所以对任何想参与其中的任何人，获取这些项目的源代码都异常简单。同时，你对项目的公开代码贡献，也能很方便的被招聘单位或者潜在雇主找到。开源项目提供了一个可以让你以一种更实际的的方式展现你的技能，而不是仅仅在面试中纸上谈兵。

### 2、 学会提问

开源项目团体的新成员总会有机会去学习大量的新技能。他们肯定会发现该项目独特的的多种交流方式、结构层次、文档格式和其他的方方面面。在刚刚参与到项目中时，你需要问大量的问题，才能找准自己的定位。正如俗语说得好，没有愚蠢的问题。开源社区提倡好奇心，特别是在问题答案不容易找到的时候。

在从事开源项目工作初期，对项目的不熟悉感会驱使个人去提问，去经常提问。这可以帮助参与者学会提问。学会去分辨问什么，怎么问，问谁。学会提问在找工作、[面试](https://www.thebalance.com/why-you-should-ask-questions-in-a-job-interview-1669548)，甚至生活中都非常有用。解决问题和寻求帮助的能力在人才市场中都非常重要。

### 3、 获取新的技能与持续学习

大量的软件项目同时使用很多不同的技术。很少有贡献者可以熟悉项目中的所有技术。即使已经在项目中工作了一段时间后，很多人很可能不能对项目中所用的所有技术都熟悉。

虽然一个开源项目中的老手可能会对项目的一些特定的方面不熟悉，但是新手不熟悉的显然更多。这种情况产生了大量的学习机会。在一个人刚开始从事开源工作时，可能只是去提高项目中的一些小功能，甚至很可能是在他熟悉的领域。但是以后的旅程就大不相同了。

从事项目的某一方面的工作可能会把你带进一个不熟悉的领域，可能会驱使你开始新的学习。而从事开源项目的工作，可能会把你带向一个你以前可能从没用过的技术。这会激起新的激情，或者，至少促进你继续学习（[这正是雇主渴望具备的能力](https://www.computerworld.com/article/3177442/it-careers/lifelong-learning-is-no-longer-optional.html)）。

### 4、增加人脉

开源项目被不同的社区维护和支持。一些人在他们的业余时间进行开源工作，他们都有各自的经历、兴趣和人脉。正如他们所说，“你了解什么人决定你成为什么人”。不通过开源项目，可能你永远不会遇到特定的人。或许你和世界各地的人一起工作，或许你和你的邻里有联系。但是，你不知道谁能帮你找到下一份工作。参加开源项目扩展人脉的可能性将对你寻找下一份（或者第一份）工作极有帮助。

### 5、 建立自信

最后，参与开源项目可能给你新的自信。很多科技企业的新员工会有些[冒充者综合症](https://en.wikipedia.org/wiki/Impostor_syndrome)。由于没有完成重要工作，他们会感到没有归属感，好像自己是冒名顶替的那个人，认为自己配不上他们的新职位。在被雇佣前参加开源项目可以最小化这种问题。

开源项目的工作往往是独立完成的，但是对于项目来说，所有的贡献是一个整体。开源社区具有强大的包容性和合作性，只要你有所贡献，一定会被看到。别的社区成员（特别是更高级的成员）对你肯定无疑也是一种回报。在你进行代码提交时获得的认可可以提高你的自信，打败冒充者综合症。这份自信也会被带到面试，新职位，等等。

这只是从事开源工作的一些好处。如果你知道更多的好处，请在下方评论区留言分享。

### 关于作者

Sophie Polson ：一名研究计算机科学的杜克大学的学生。通过杜克大学 2017 秋季课程 “开源世界（ Open Source World ）”，开始了开源社区的冒险。对探索 [DevOps](https://en.wikipedia.org/wiki/DevOps) 十分有兴趣。在 2018 春季毕业后，将成为一名软件工程师。

---

via: <https://opensource.com/article/18/1/5-ways-turn-open-source-new-job>

作者：[Sophie Polson](https://opensource.com/users/sophiepolson) 译者：[Lontow](https://github.com/lontow) 校对：[wxy](https://github.com/wxy)

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

<sup> <sup>  <sup>   <sup>    <sup>     ^    </sup>   </sup>  </sup> </sup></sup>


IT 自动化：如何去实现

Summary: 想要你的整个团队都登上 IT 自动化之旅吗？ IT 执行者们分享了他们的战略。

想要你的整个团队都登上 IT 自动化之旅吗？ IT 执行者们分享了他们的战略。

>
> 想要你的整个团队都登上 IT 自动化之旅吗？ IT 执行者们分享了他们的战略。
>
>
>

![](/data/attachment/album/201806/06/190848x5k8u2o85bu9krmt.jpg)

在任何重要的项目或主动变更刚开始的时候，IT 的管理者在前进的道路上面临着普遍的抉择。

第一条路径看上去是提供了一个从 A 到 B 的最短路径：简单的把项目强制分配给每个人去执行，本质来说就是你要么按照要求去做要么就不要做了。

第二条路径可能看上去会不是很直接，因为要通过这条路径你需要花时间去解释项目背后的策略以及原因。你会沿着这条路线设置停靠站点而不是从起点到终点的马拉松：“这就是我们正在做的 —— 和为什么我们这么做。”

猜想一下哪条路径会赢得更好的结果？

如果你选的是路径 2，你肯定是以前都经历过这两条路径——而且经历了第一次的结局。让人们参与到重大变革中总会是最明智的选择。

IT 领导者也知道重大的变革总会带来严重的恐慌、怀疑，和其他的挑战。IT 自动化确实是很正确的改变。这个术语对某些人来说是很可怕的，而且容易被曲解。帮助人们理解你的公司需要 IT 自动化的必要性的原因以及如何去实现是达到你的目标和策略的重要步骤。

[**阅读我们的相关文章，**[**IT自动化最佳实践：持久成功的7个关键点**](https://enterprisersproject.com/article/2018/1/it-automation-best-practices-7-keys-long-term-success?sc_cid=70160000000h0aXAAQ)。]

考虑到这一点，我们咨询了许多 IT 管理者关于如何在你的组织中实现 IT 自动化。

### 1、向人们展示它的优点

我们要面对的一点事实是：自我利益和自我保护是本能。利用人们的这种本能是一个吸引他们的好方法：向他们展示自动化策略将如何让他们和他们的工作获益。自动化将会是软件管道中的一个特定过程意味着将会减少在半夜呼叫团队同事来解决故障？它将能让一些人丢弃技术含量低的技能，用更有策略、高效的有序工作代替手工作业，这将会帮助他们的职业生涯更进一步？

“向他们传达他们能得到什么好处，自动化将会如何让他们的客户和公司受益，”来自 ADP 全球首席技术官 vipual Nagrath 的建议。“将现在的状态和未来光明的未来进行对比，展现公司将会变得如何稳定，敏捷，高效和安全。”

这样的方法同样适用于 IT 领域之外的其他领域；只要在向非技术领域的股东们解读利益的时候解释清楚一些术语即可，Nagrath 说道。

设置好前后的情景是一个不错的帮助人们理解的更透彻的故事机。

“你要描述一幅人们能够联想到的当前状态的画面，” Nagrath 说。“描述现在是什么工作，但也要重点强调是什么导致团队的工作效率不够敏捷。”然后再阐释自动化过程将如何提高现在的状态。

### 2、将自动化和特定的商业目标绑定在一起

一个强有力的案列的一部分要确保人们理解你不只是在追逐潮流趋势。如果只是为了自动化而自动化，人们会很快察觉到进而会更加抵制的——也许在 IT 界更是如此。

“自动化需要商业需求的驱动，例如收入和运营开销，” Cyxtera的副总裁和首席信息安全官 David Emerson 说道。“没有自动化的努力是自我辩护的，而且任何技术专长都不应该被当做一种手段，除非它是公司的一项核心能力。”

像 Nagrath 一样，Emerson 建议将达到自动化的商业目标和奖励措施挂钩，用迭代式的循序渐进的方式推进这些目标和相关的激励措施。

### 3、 将自动化计划分解为可管理的条目

即使你的自动化策略字面上是“一切都自动化”，对大多数组织来说那也是很艰难的，而且可能是没有灵活性的。你需要制定一个强有力的方案，将自动化目标分解为可管理的目标计划。而且这将能够创造很大的灵活性来适应之后漫长的道路。

“当制定一个自动化方案的时候，我建议详细的阐明推进自动化进程的奖励措施，而且允许迭代朝着目标前进来介绍和证明利益处于一个低风险水平，”Emerson 说道。

GA Connector 的创始人 Sergey Zuev 分享了一个为什么自动化如此重要的快节奏体验的报告——它将怎样为你的策略建立一个强壮持久的论点。Zuevz 应该知道：他的公司的自动化工具将公司的客户关系应用数据导入谷歌分析。但实际上是公司的内部经验使顾客培训进程自动化从而出现了一个闪耀的时刻。

“起初， 我们曾尝试去建立整个培训机制，结果这个项目搁浅了好几个月，”Zuev 说道。“认识到这将无法继续下去之后，我们决定挑选其中的一个能够有巨大的时效的领域，而且立即启动。结果我们只用了一周就实现了其中的电子邮件序列的目标，而且我们已经从被亵渎的体力劳动中获益。”

### 4、 出售主要部分也有好处

循序渐进的方法并不会阻碍构建一个宏伟的蓝图。就像以个人或者团队的水平来制定方案是一个好主意，帮助人们理解全公司的利益也是一个不错的主意。

“如果我们能够加速达到商业需求所需的时间，那么一切质疑将会平息。”

AHEAD 的首席技术官 Eric Kaplan 赞同通过小范围的胜利来展示自动化的价值是一个赢得人心的聪明策略。但是那些所谓的“小的”的价值揭示能够帮助你提高人们的整体形象。Kaplan 指出个人和组织间的价值是每个人都可以容易联系到的领域。

“最能展现的地方就是你能够节约多少时间，”Kaaplan 说。“如果我们能够加速达到商业需求所需的时间，那么一切质疑将会消失。”

时间和可伸缩性是业务和 IT 同事的强大优势，都复制业务的增长，可以把握。

“自动化的结果是灵活伸缩的——每个人只需较少的努力就能保持和改善你的 IT 环境”，红帽的全球服务副总裁 John Allessio 最近提到。“如果增加人力是提升你的商业的唯一途径，那么灵活伸缩就是白日梦。自动化减少了你的人力需求而且提供了 IT 演进所需的灵活性和韧性。”(详细内容请参考他的文章，[DevOps 团队对 CIO 的真正需求是什么。])

### 5、 推广你的成果。

在你自动化策略的开始时，你可能是在目标和要达到目标的预期利益上制定方案。但随着你的自动化策略的不断演进，没有什么能够比现实中的实际结果令人信服。

“眼见为实，”ADP 的首席技术官 Nagrath 说。“没有什么比追踪记录能够平息质疑。”

那意味着，不仅仅要达到你的目标，还要准时的完成——这是迭代的循序渐进的方法论的另一个不错的解释。

而量化的结果如比利润的提高或者成本的节省可以大声宣扬出来，Nagrath 建议他的 IT 领导者同行在讲述你们的自动化故事的时候不要仅仅止步于此。

为自动化提供案例也是一个定性的讨论，通过它我们能够促进问题的预防，归总商业的连续性，减伤失败或错误，而且能够在他们处理更有价值的任务时承担更多的责任。

---

via: <https://enterprisersproject.com/article/2018/1/how-make-case-it-automation>

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

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


最好的 Linux 工具献给老师和学生们

![](/data/attachment/album/201806/06/211205d26t06htv9scjthx.jpg)

Linux 是一个适合每个人的平台。如果你有一份合适的工作，Linux 已经可以满足或超过它的需求，其中一个工作是教育。如果你是一名教师或一名学生，Linux 已经准备好帮助你在几乎任何级别的教育系统领域中畅游。从辅助学习、写作论文、管理课程，到管理整个机构，Linux 已经全部涵盖了。

如果你不确定，请让我介绍一下 Linux 准备好的一些工具。其中一些工具几乎没有学习曲线，而另一些工具则需要一个全面的系统管理员来安装、设置和管理。我们将从简单开始，然后到复杂。

### 学习辅助工具

每个人的学习方式都有所不同，每个班级都需要不同的学习类型和水平。幸运的是，Linux 有很多学习辅助工具。让我们来看几个例子：

闪卡 —— [KWordQuiz](https://edu.kde.org/kwordquiz/)（图 1）是适用于 Linux 平台的许多闪卡应用程序之一。KWordQuiz 使用 kvtml 文件格式，你可以下载大量预制的、人们贡献的文件。 KWordQuiz 是 KDE 桌面环境的一部分，但可以安装在其他桌面上（KDE 依赖文件将与闪卡应用程序一起安装）。

![](/data/attachment/album/201806/06/211239ga9ag4gpg9vv4pii.png)

### 语言工具

由于全球化进程，外语已成为教育的重要组成部分。你会发现很多语言工具，包括 [Kiten](https://edu.kde.org/kiten/)（图 2）—— KDE 桌面的日语汉字浏览器。

![](/data/attachment/album/201806/06/211241iz3tmm9pa0ttm9n3.jpg)

如果日文不是你的母语，你可以试试 [Jargon Informatique](http://jargon.asher256.com/index.php)。这本词典完全是法文的，所以如果你对这门语言还不熟悉，你可能要需要 [Google 翻译](https://translate.google.com/)的帮助才能坚持下去。

### Writing Aids / Note Taking

Linux 拥有你需要的所有东西比如记录一个主题，撰写那些学期论文。让我们从记笔记开始。如果你熟悉 Microsoft OneNote，你一定会喜欢 [BasKet Note Pads](http://basket.kde.org/)。有了这个应用程序，你可以为主题创建<ruby> 笔记本 <rt>  basket </rt></ruby>，并添加任何东西——注释、链接、图像、交叉引用（到其他笔记本─图 3）、应用程序启动器、从文件加载等等。

![](/data/attachment/album/201806/06/211243qys4y33kjjnjnu6a.jpg)

你可以创建任意形式的笔记本，可以移动元素来满足你的需求。如果你更喜欢有序的感觉，那么创建一个表状的 basket 来保留那些封装的笔记。

当然，所有 Linux 写作辅助工具都是由 [LibreOffice](http://www.libreoffice.com) 发展而来。LibreOffice 是大多数 Linux 发行版默认的办公套件，它能打开文本文档、电子表格、演示文稿、数据库、公式和绘图。

在教育环境中使用 LibreOffice 的一个警告是，你很可能不得不将文档以 MS Office 格式保存。

### 为教育而生的发行版

所有这些都是关于 Linux 面向学生的应用程序，你可以看看专门为教育而开发的一个发行版。最好的是 [Edubuntu](http://www.edubuntu.org/)。这种平易的 Linux 发行版旨在让 Linux 进入学校、家庭和社区。Edubuntu 使用默认的 Ubuntu 桌面（Unity shell）并添加以下软件：

* KDE 教育套件
* GCompris
* Celestia
* Tux4Kids
* Epoptes
* LTSP
* GBrainy
* 等等

Edubuntu 并不是唯一的发行版。如果你想测试其他特定于教育的 Linux 发行版，以下是简短列表：

* Debian-Edu
* Fedora Education Spin
* Guadalinux-Edu
* OpenSuse-Edu
* Qimo
* Uberstudent

### 课堂/机构管理

这是 Linux 平台真正闪耀的地方。有许多专门用于管理的工具。我们先来看看教室特有的工具。

[iTalc](http://italc.sourceforge.net/) 是一个强大的课堂教学环境。借助此工具，教师可以查看和控制学生桌面（支持 Linux 和 Windows）。iTalc 系统允许教师查看学生桌面上发生了什么，控制他们的桌面，锁定他们的桌面，对桌面演示，打开或关闭桌面，向学生桌面发送文本消息等等。

[aTutor](http://www.atutor.ca/)（图 4）是一个开源的学习管理系统（LMS），专注于开发在线课程和电子学习内容。一个老师真正发挥的就是创建和管理在线考试和测验。当然，aTutor 不限于测试的目的，有了这个强大的软件，学生和老师可以享受：

* 社交网络
* 配置文件
* 消息
* 自适应导航
* 工作组
* 文件存储
* 小组博客
* 以及更多。

![](/data/attachment/album/201806/06/211244sdkl4rmjm6643zhz.png)

课程资料易于创建和部署（你甚至可以将考试/测验分配给特定的学习小组）。

[Moodle](https://moodle.org/) 是目前使用最广泛的教育管理软件之一。通过 Moodle，你可以管理、教授、学习甚至参与孩子的教育。这个强大的软件为教师和学生、考试、日历、论坛、文件管理、课程管理（图 5）、通知、进度跟踪、大量注册、批量课程创建、考勤等提供协作工具。

![](/data/attachment/album/201806/06/211247q7p6mgwm3w76p2wl.png)

[OpenSIS](http://www.opensis.com/) 意即开源学生信息系统，在管理你的教育机构方面做得很好。有一个免费的社区版，但即使使用付费版本，你也可以期待将学区的拥有成本降低高达 75％（与专有解决方案相比）。

OpenSIS 包括以下特点或模块：

* 出席情况（图 6）
* 联系信息
* 学生人口统计
* 成绩簿
* 计划
* 健康记录
* 报告卡

![](/data/attachment/album/201806/06/211248bvjydyzxvd0ri0ro.png)

OpenSIS 有四个版本，在[这里](http://www.opensis.com/compare_edition.php)查看它们的功能比较。

[vufind](http://vufind-org.github.io/vufind/) 是一个优秀的图书馆管理系统，允许学生和教师轻松浏览图书馆资源，例如：

* 目录记录
* 本地缓存期刊
* 数字图书馆项目
* 机构知识库
* 机构书目
* 其他图书馆集合和资源

Vufind 系统允许用户登录，通过认证的用户可以节省资源以便快速回忆，并享受“更像这样”的结果。

这份列表仅仅触及了 Linux 在教育领域可用性的一点皮毛。而且，正如你所期望的那样，每个工具都是高度可定制且开放源代码的 —— 所以如果软件不能精确地满足你的需求，那么你可以自由（在大多数情况下）修改源代码并进行更改。

Linux 与教育齐头并进。无论你是老师，学生还是管理员，你都会找到大量工具来帮助教育机构开放，灵活和强大。

---

via: <https://www.linux.com/news/best-linux-tools-teachers-and-students>

作者：[Jack Wallen](https://www.linux.com/users/jlwallen) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)

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


Pidgin：Skype for Business 的开源替代品

Summary: 用可以和 Office 365 协同工作的开源软件换下你的专有化的沟通软件。

用可以和 Office 365 协同工作的开源软件换下你的专有化的沟通软件。

>
> 用可以和 Office 365 协同工作的开源软件换下你的专有化的沟通软件。
>
>
>

![](/data/attachment/album/201806/06/214708qillzt9lj59llwn6.png)

技术正处在一个有趣的十字路口，Linux 统治服务器领域，但微软统治企业桌面。 Office 365、Skype for Business、Microsoft Teams、OneDrive、Outlook ......等等，这些是支配企业工作空间的是微软软件和服务。

如果你可以使用自由和开源程序替换该专有软件，并使其与你别无选择，但只能使用的 Office 365 的后端一起工作？是的，因为这正是我们要用 Pidgin 做的，它是 Skype 的开源替代品。

### 安装 Pidgin 和 SIPE

微软的 Office Communicator 变成了 Microsoft Lync，它成为我们今天所知的 Skype for Business。现在有针对 Linux 的[付费软件](https://tel.red/linux.php)提供了与 Skype for Business 相同的功能，但 [Pidgin](https://pidgin.im/) 是 GNU GPL 授权的、完全自由开源的选择。

Pidgin 可以在几乎每个 Linux 发行版的仓库中找到，因此，使用它不应该是一个问题。唯一不能在 Pidgin 中使用的 Skype 功能是屏幕共享，并且文件共享可能会失败，但有办法解决这个问题。

你还需要一个 [SIPE](http://sipe.sourceforge.net/) 插件，因为它是使 Pidgin 成为 Skype for Business 替代品的秘密武器的一部分。请注意，`sipe` 库在不同的发行版中有不同的名称。例如，库在 System76 的 Pop\_OS! 中是 `pidgin-sipe`，而在 Solus 3 仓库中是 `sipe`。

满足了先决条件，你可以开始配置 Pidgin。

### 配置 Pidgin

首次启动 Pidgin 时，点击 “Add” 添加一个新帐户。在基本选项卡（如下截图所示）中，选择 “Protocol” 下拉菜单中的 “Office Communicator”，然后在 “Username” 字段中输入你的“公司电子邮件地址”。

![](/data/attachment/album/201806/06/214717uwb25xfzmz48xvpj.png)

接下来，点击高级选项卡。在 “Server[:Port]” 字段中输入 “sipdir.online.lync.com:443”，在 “User Agent” 中输入 “UCCAPI/16.0.6965.5308 OC/16.0.6965.2117”。

你的高级选项卡现在应该如下所示：

![](/data/attachment/album/201806/06/214729zvgn2uze89n9kg48.png)

你不需要对“Proxy”选项卡或“Voice and Video”选项卡进行任何更改。只要确定，请确保 “Proxy type” 设置为 “Use Global Proxy Settings”，并且在“Voice and Video”选项卡中，“Use silence suppression” 复选框为**取消选中**。

![](/data/attachment/album/201806/06/214737tnoi9gi3jjef3veo.png)

![](/data/attachment/album/201806/06/214743qn884f546p6468a6.png)

完成这些配置后，点击 “Add”，系统会提示你输入电子邮件帐户的密码。

### 添加联系人

要将联系人添加到好友列表，请点击**好友窗口**中的 “Manage Accounts”。将鼠标悬停在你的帐户上，然后选择 “Contact Search” 查找你的同事。如果您在使用姓氏和名字进行搜索时遇到任何问题，请尝试使用你同事的完整电子邮件地址进行搜索，你就会找到正确的人。

你现在已经开始使用 Skype for Business 替代产品，该产品可为你提供 98％ 的功能，从你的桌面上消除专有软件。

---

via: <https://opensource.com/article/18/4/pidgin-open-source-replacement-skype-business>

作者：[Ray Shimko](https://opensource.com/users/shickmo) 选题：[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/) 荣誉推出


Git 分支操作介绍

>
> 在这个 Git 入门系列的第三篇中，我们来学习一下如何添加和删除 Git 分支。
>
>
>

![](/data/attachment/album/201806/07/232158l3slzxx33kezcc5x.jpg)

在本系列的前两篇文章中，我们[开始使用 Git](/article-9319-1.html)，学会如何[克隆项目，修改、增加和删除内容](/article-9517-1.html)。在这第三篇文章中，我将介绍 Git 分支，为何以及如何使用分支。

![树枝](/data/attachment/album/201806/07/232258bokj2oqrqh5ior0i.jpg "tree branches")

不妨用树来描绘 Git 仓库。图中的树有很多分支，或长或短，或从树干延伸或从其它分支延伸。在这里，我们用树干比作仓库的 master 分支，其中 `master` 代指 ”master 分支”，是 Git 仓库的中心分支或第一个分支。为简单起见，我们假设 `master` 是树干，其它分支都是从该分支分出的。

### 为何在 Git 仓库中使用分支

使用分支的主要理由为：

* 如果你希望为项目增加新特性，但很可能会影响当前可正常工作的代码。对于该项目的活跃用户而言，这是很糟糕的事情。与其将特性加入到其它人正在使用的 `master` 分支，更好的方法是在仓库的其它分支中变更代码，下面会给出具体的工作方式。
* 更重要的是，[Git 其设计](https://en.wikipedia.org/wiki/Git)用于协作。如果所有人都在你代码仓库的 `master` 分支上操作，会引发很多混乱。对编程语言或项目的知识和阅历因人而异；有些人可能会编写有错误或缺陷的代码，也可能会编写你觉得不适合该项目的代码。使用分支可以让你核验他人的贡献并选择适合的加入到项目中。（这里假设你是代码库唯一的所有者，希望对增加到项目中的代码有完全的控制。在真实的项目中，代码库有多个具有合并代码权限的所有者）

### 创建分支

让我们回顾[本系列上一篇文章](/article-9517-1.html)，看一下在我们的 Demo 目录中分支是怎样的。如果你没有完成上述操作，请按照文章中的指示从 GitHub 克隆代码并进入 Demo 目录。运行如下命令：

```
pwd
git branch
ls -la

```

`pwd` 命令（是当前工作目录的英文缩写）返回当前你所处的目录（以便确认你在 `Demo` 目录中），`git branch` 列出该项目在你主机上的全部分支，`ls -la` 列出当前目录下的所有文件。你的终端输出类似于：

![终端输出](/data/attachment/album/201806/07/232259fulowhuxc3vmyuyv.png "Terminal output")

在 `master` 分支中，只有一个文件 `README.md`。（Git 会友好地忽略掉其它目录和文件。）

接下来，运行如下命令：

```
git status
git checkout -b myBranch
git status

```

第一条命令 `git status` 告知你当前位于 `branch master`，（就像在终端中看到的那样）它与 `origin/master` 处于同步状态，这意味着 master 分支的本地副本中的全部文件也出现在 GitHub 中。两份副本没有差异，所有的提交也是一致的。

下一条命令 `git checkout -b myBranch` 中的 `-b` 告知 Git 创建一个名为 `myBranch` 的新分支，然后 `checkout` 命令将我们切换到新创建的分支。运行第三条命令 `git status` 确保你已经位于刚创建的分支下。

如你所见，`git status` 告知你当前处于 `myBranch` 分支，没有变更需要提交。这是因为我们既没有增加新文件，也没有修改已有文件。

![终端输出](/data/attachment/album/201806/07/232307zypoojs93o2zjgt9.png "Terminal output")

如果希望以可视化的方式查看分支，可以运行 `gitk` 命令。如果遇到报错 `bash: gitk: command not found...`，请先安装 `gitk` 软件包（找到你操作系统对应的安装文档，以获得安装方式）。

（LCTT 译注：需要在有 X 服务器的终端运行 `gitk`，否则会报错）

下图展示了我们在 Demo 项目中的所作所为：你最后一次提交（的对应信息）是 `Delete file.txt`，在此之前有三次提交。当前的提交用黄点标注，之前的提交用蓝点标注，黄点和 `Delete file.txt` 之间的三个方块展示每个分支所在的位置（或者说每个分支中的最后一次提交的位置）。由于 `myBranch` 刚创建，提交状态与 `master` 分支及其对应的记为 `remotes/origin/master` 的远程 `master` 分支保持一致。（非常感谢来自 Red Hat 的 [Peter Savage](https://opensource.com/users/psav) 让我知道 `gitk` 这个工具）

![Gitk 输出](/data/attachment/album/201806/07/232308luoexoj2j3lo22l3.png "Gitk output")

下面让我们在 `myBranch` 分支下创建一个新文件并观察终端输出。运行如下命令：

```
echo "Creating a newFile on myBranch" > newFile
cat newFile
git status

```

第一条命令中的 `echo` 创建了名为 `newFile` 的文件，接着 `cat newFile` 打印出文件内容，最后 `git status` 告知你我们 `myBranch` 分支的当前状态。在下面的终端输出中，Git 告知 `myBranch` 分支下有一个名为 `newFile` 的文件当前处于 `untracked` 状态。这表明我们没有让 Git 追踪发生在文件 `newFile` 上的变更。

![终端输出](/data/attachment/album/201806/07/232318mp3a74p35nnl9ztt.png "Terminal output")

下一步是增加文件，提交变更并将 `newFile` 文件推送至 `myBranch` 分支（请回顾本系列上一篇文章获得更多细节）。

```
git add newFile
git commit -m "Adding newFile to myBranch"
git push origin myBranch

```

在上述命令中，`push` 命令使用的分支参数为 `myBranch` 而不是 `master`。Git 添加 `newFile` 并将变更推送到你 GitHub 账号下的 Demo 仓库中，告知你在 GitHub 上创建了一个与你本地副本分支 `myBranch` 一样的新分支。终端输出截图给出了运行命令的细节及命令输出。

![终端输出](/data/attachment/album/201806/07/232321zg9070fg08c9cnft.png "Terminal output")

当你访问 GitHub 时，在分支选择的下拉列表中可以发现两个可供选择的分支。

![GitHub](/data/attachment/album/201806/07/232339fb7lfez7jnkzbele.png "GitHub")

点击 `myBranch` 切换到 `myBranch` 分支，你可以看到在此分支上新增的文件。

![GitHub](/data/attachment/album/201806/07/232350w3c7phg2cswcbvs7.png "GitHub")

截至目前，我们有两个分支：一个是 `master` 分支，只有一个 `README.md` 文件；另一个是 `myBranch` 分支，有两个文件。

你已经知道如何创建分支了，下面我们再创建一个分支。输入如下命令：

```
git checkout master
git checkout -b myBranch2
touch newFile2
git add newFile2
git commit -m "Adding newFile2 to myBranch2"
git push origin myBranch2

```

我不再给出终端输出，需要你自己尝试，但你可以在 [GitHub 代码库](https://github.com/kedark3/Demo/tree/myBranch2) 中验证你的结果。

### 删除分支

由于我们增加了两个分支，下面删除其中的一个（`myBranch`），包括两步：

1. **删除本地分支** 你不能删除正在操作的分支，故切换到 `master` 分支 （或其它你希望保留的分支），命令及终端输出如下：

![](/data/attachment/album/201806/07/232356sfpovd4o9cjjnsps.png)

`git branch` 可以列出可用的分支，使用 `checkout` 切换到 `master` 分支，然后使用 `git branch -D myBranch` 删除该分支。再次运行 `git branch` 检查是否只剩下两个分支（而不是三个）。
2. **删除 GitHub 上的分支** 使用如下命令删除 `myBranch` 的远程分支：

```
git push origin :myBranch

```

![Terminal output](/data/attachment/album/201806/07/232357g7s9vioukdh729k2.png "Terminal output")

上面 `push` 命令中分支名称前面的冒号（`:`）告知 GitHub 删除分支。另一种写法为：

```
git push -d origin myBranch

```

其中 `-d` (也可以用 `--delete`) 也用于告知 GitHub 删除你的分支。

我们学习了 Git 分支的使用，在本系列的下一篇文章中，我们将介绍如何执行 `fetch` 和 `rebase` 操作，对于多人同时的贡献的项目而言，这是很必须学会的。

---

via: <https://opensource.com/article/18/5/git-branching>

作者：[Kedar Vijay Kulkarni](https://opensource.com/users/kkulkarn) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

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


GDPR 将如何影响开源社区？

Summary: 许多组织正在争先恐后地了解隐私法的变化如何影响他们的工作。

许多组织正在争先恐后地了解隐私法的变化如何影响他们的工作。

>
> 许多组织正在争先恐后地了解隐私法的变化如何影响他们的工作。
>
>
>

![](/data/attachment/album/201806/07/235158c1xuqmxx71xx75hm.jpg)

2018 年 5 月 25 日，[<ruby> 通用数据保护条例 <rt>  General Data Protection Regulation, GDPR </rt></ruby>](https://www.eugdpr.org/eugdpr.org.html) 开始生效。欧盟出台的该条例将在全球范围内对企业如何保护个人数据产生重大影响。影响也会波及到开源项目以及开源社区。

### GDPR 概述

GDPR 于 2016 年 4 月 14 日在欧盟议会通过，从 2018 年 5 月 25 日起开始生效。GDPR 用于替代 95/46/EC 号<ruby> 数据保护指令 <rt>  Data Protection Directive </rt></ruby>，该指令被设计用于“协调欧洲各国数据隐私法，保护和授权全体欧盟公民的数据隐私，改变欧洲范围内企业处理数据隐私的方式”。

GDPR 目标是在当前日益数据驱动的世界中保护欧盟公民的个人数据。

### 它对谁生效

GDPR 带来的最大改变之一是影响范围的扩大。不管企业本身是否位于欧盟，只要涉及欧盟公民个人数据的处理，GDPR 就会对其生效。

大部分提及 GDPR 的网上文章关注销售商品或服务的公司，但关注影响范围时，我们也不要忘记开源项目。有几种不同的类型，包括运营开源社区的（营利性）软件公司和非营利性组织（例如，开源软件项目及其社区）。对于面向全球的社区，几乎总是会有欧盟居民加入其中。

如果一个面向全球的社区有对应的在线平台，包括网站、论坛和问题跟踪系统等，那么很可能会涉及欧盟居民的个人数据处理，包括姓名、邮箱地址甚至更多。这些处理行为都需要遵循 GDPR。

### GDPR 带来的改变及其影响

相比被替代的指令，GDPR 带来了[很多改变](https://www.eugdpr.org/key-changes.html)，强化了对欧盟居民数据和隐私的保护。正如前文所说，一些改变给社区带来了直接的影响。我们来看看若干改变。

#### 授权

我们假设社区为成员提供论坛，网站中包含若干个用于注册的表单。要遵循 GDPR，你不能再使用冗长、无法辨识的隐私策略和条件条款。无论是每种特殊用途，在论坛注册或使用网站表单注册，你都需要获取明确的授权。授权必须是无条件的、具体的、通知性的以及无歧义的。

以表单为例，你需要提供一个复选框，处于未选中状态并给出个人数据用途的明确说明，一般是当前使用的隐私策略和条件条款附录的超链接。

#### 访问权

GDPR 赋予欧盟公民更多的权利。其中一项权利是向企业查询个人数据包括哪些，保存在哪里；如果<ruby> 数据相关人 <rt>  data subject </rt></ruby>（例如欧盟公民）提出获取相应数据副本的需求，企业还应免费提供数字形式的数据。

#### 遗忘权

欧盟居民还从 GDPR 获得了“遗忘权”，即数据擦除。该权利是指，在一定限制条件下，企业必须删除个人数据，甚至可能停止其自身或第三方机构后续处理申请人的数据。

上述三种改变要求你的平台软件也要遵循 GDPR 的某些方面。需要提供特定的功能，例如获取并保存授权，提取数据并向数据相关人提供数字形式的副本，以及删除数据相关人对应的数据等。

#### 泄露通知

在 GDPR 看来，不经数据相关人授权情况下使用或偷取个人数据都被视为<ruby> 数据泄露 <rt>  data breach </rt></ruby>。一旦发现，你应该在 72 小时内通知社区成员，除非这些个人数据不太可能给<ruby> 自然人 <rt>  natural persons </rt></ruby>的权利与自由带来风险。GDPR 强制要求执行泄露通知。

#### 披露记录

企业负责提供一份记录，用于详细披露个人数据处理的过程和目的等。该记录用于证明企业遵从 GDPR 要求，维护了一份个人数据处理行为的记录；同时该记录也用于审计。

#### 罚款

不遵循 GDPR 的企业最高可面临全球年收入总额 4% 或 2000 万欧元 （取两者较大值）的罚款。根据 GDPR，“最高处罚针对严重的侵权行为，包括未经用户充分授权的情况下处理数据，以及违反设计理念中核心隐私部分”。

### 补充说明

本文不应用于法律建议或 GDPR 合规的指导书。我提到了可能对开源社区有影响的条约部分，希望引起大家对 GDPR 及其影响的关注。当然，条约包含了更多你需要了解和可能需要遵循的条款。

你自己也可能认识到，当运营一个面向全球的社区时，需要行动起来使其遵循 GDPR。如果在社区中，你已经遵循包括 ISO 27001，NIST 和 PCI DSS 在内的健壮安全标准，你已经先人一步。

可以从如下网站/资源中获取更多关于 GDPR 的信息：

* [GDPR 官网](https://www.eugdpr.org/eugdpr.org.html) (欧盟提供)
* [官方条约 （欧盟） 2016/679](http://eur-lex.europa.eu/legal-content/EN/TXT/?qid=1520531479111&uri=CELEX:32016R0679) （GDPR，包含翻译）
* [GDPR 是什么？ 领导人需要知道的 8 件事](https://enterprisersproject.com/article/2018/4/what-gdpr-8-things-leaders-should-know) （企业人项目）
* [如何规避 GDPR 合规审计：最佳实践](https://enterprisersproject.com/article/2017/9/avoiding-gdpr-compliance-audit-best-practices) （企业人项目）

### 关于作者

Robin Muilwijk 是一名互联网和电子政务顾问，在 Red Hat 旗下在线发布平台 Opensource.com 担任社区版主，在 Open Organization 担任大使。此外，Robin 还是 eZ 社区董事会成员，[eZ 系统](http://ez.no) 社区的管理员。Robin 活跃在社交媒体中，促进和支持商业和生活领域的开源项目。可以在 Twitter 上关注 [Robin Muilwijk](https://opensource.com/users/robinmuilwijk) 以获取更多关于他的信息。[更多关于我的信息](https://opensource.com/users/robinmuilwijk)

---

via: <https://opensource.com/article/18/4/gdpr-impact>

作者: [Robin Muilwijk](https://opensource.com/users/robinmuilwijk) 选题者: [lujun9972](https://github.com/lujun9972) 译者: [pinewall](https://github.com/pinewall) 校对: [wxy](https://github.com/wxy)

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


一些常见的并发编程错误

![](/data/attachment/album/201806/08/005141b113xwdldwcv1wgv.jpg)

Go 是一个内置支持并发编程的语言。借助使用 `go` 关键字去创建<ruby> 协程 <rt>  goroutine </rt></ruby>（轻量级线程）和在 Go 中提供的 [使用](https://go101.org/article/channel-use-cases.html) [信道](https://go101.org/article/channel.html) 和 [其它的并发](https://go101.org/article/concurrent-atomic-operation.html) [同步方法](https://go101.org/article/concurrent-synchronization-more.html)，使得并发编程变得很容易、很灵活和很有趣。

另一方面，Go 并不会阻止一些因 Go 程序员粗心大意或者缺乏经验而造成的并发编程错误。在本文的下面部分将展示一些在 Go 编程中常见的并发编程错误，以帮助 Go 程序员们避免再犯类似的错误。

### 需要同步的时候没有同步

代码行或许 [不是按出现的顺序运行的](https://go101.org/article/memory-model.html)。

在下面的程序中有两个错误。

* 第一，在 `main` 协程中读取 `b` 和在新的 协程 中写入 `b` 可能导致数据争用。
* 第二，条件 `b == true` 并不能保证在 `main` 协程 中的 `a != nil`。在新的协程中编译器和 CPU 可能会通过 [重排序指令](https://go101.org/article/memory-model.html) 进行优化，因此，在运行时 `b` 赋值可能发生在 `a` 赋值之前，在 `main` 协程 中当 `a` 被修改后，它将会让部分 `a` 一直保持为 `nil`。

```
package main

import (
    "time"
    "runtime"
)

func main() {
    var a []int // nil
    var b bool  // false

    // a new goroutine
    go func () {
        a = make([]int, 3)
        b = true // write b
    }()

    for !b { // read b
        time.Sleep(time.Second)
        runtime.Gosched()
    }
    a[0], a[1], a[2] = 0, 1, 2 // might panic
}

```

上面的程序或者在一台计算机上运行的很好，但是在另一台上可能会引发异常。或者它可能运行了 *N* 次都很好，但是可能在第 *(N+1)* 次引发了异常。

我们将使用 `sync` 标准包中提供的信道或者同步方法去确保内存中的顺序。例如，

```
package main

func main() {
    var a []int = nil
    c := make(chan struct{})

    // a new goroutine
    go func () {
        a = make([]int, 3)
        c <- struct{}{}
    }()

    <-c
    a[0], a[1], a[2] = 0, 1, 2
}

```

### 使用 `time.Sleep` 调用去做同步

我们先来看一个简单的例子。

```
package main

import (
    "fmt"
    "time"
)

func main() {
    var x = 123

    go func() {
        x = 789 // write x
    }()

    time.Sleep(time.Second)
    fmt.Println(x) // read x
}

```

我们预期程序将打印出 `789`。如果我们运行它，通常情况下，它确定打印的是 `789`。但是，这个程序使用的同步方式好吗？No！原因是 Go 运行时并不保证 `x` 的写入一定会发生在 `x` 的读取之前。在某些条件下，比如在同一个操作系统上，大部分 CPU 资源被其它运行的程序所占用的情况下，写入 `x` 可能就会发生在读取 `x` 之后。这就是为什么我们在正式的项目中，从来不使用 `time.Sleep` 调用去实现同步的原因。

我们来看一下另外一个示例。

```
package main

import (
    "fmt"
    "time"
)

var x = 0

func main() {
    var num = 123
    var p = &num

    c := make(chan int)

    go func() {
        c <- *p + x
    }()

    time.Sleep(time.Second)
    num = 789
    fmt.Println(<-c)
}

```

你认为程序的预期输出是什么？`123` 还是 `789`？事实上它的输出与编译器有关。对于标准的 Go 编译器 1.10 来说，这个程序很有可能输出是 `123`。但是在理论上，它可能输出的是 `789`，或者其它的随机数。

现在，我们来改变 `c <- *p + x` 为 `c <- *p`，然后再次运行这个程序。你将会发现输出变成了 `789` （使用标准的 Go 编译器 1.10）。这再次说明它的输出是与编译器相关的。

是的，在上面的程序中存在数据争用。表达式 `*p` 可能会被先计算、后计算、或者在处理赋值语句 `num = 789` 时计算。`time.Sleep` 调用并不能保证 `*p` 发生在赋值语句处理之前进行。

对于这个特定的示例，我们将在新的协程创建之前，将值保存到一个临时值中，然后在新的协程中使用临时值去消除数据争用。

```
...
    tmp := *p + x
    go func() {
        c <- tmp
    }()
...

```

### 使协程挂起

挂起协程是指让协程一直处于阻塞状态。导致协程被挂起的原因很多。比如，

* 一个协程尝试从一个 nil 信道中或者从一个没有其它协程给它发送值的信道中检索数据。
* 一个协程尝试去发送一个值到 nil 信道，或者发送到一个没有其它的协程接收值的信道中。
* 一个协程被它自己死锁。
* 一组协程彼此死锁。
* 当运行一个没有 `default` 分支的 `select` 代码块时，一个协程被阻塞，以及在 `select` 代码块中 `case` 关键字后的所有信道操作保持阻塞状态。

除了有时我们为了避免程序退出，特意让一个程序中的 `main` 协程保持挂起之外，大多数其它的协程挂起都是意外情况。Go 运行时很难判断一个协程到底是处于挂起状态还是临时阻塞。因此，Go 运行时并不会去释放一个挂起的协程所占用的资源。

在 [谁先响应谁获胜](https://go101.org/article/channel-use-cases.html#first-response-wins) 的信道使用案例中，如果使用的 future 信道容量不够大，当尝试向 Future 信道发送结果时，一些响应较慢的信道将被挂起。比如，如果调用下面的函数，将有 4 个协程处于永远阻塞状态。

```
func request() int {
    c := make(chan int)
    for i := 0; i < 5; i++ {
        i := i
        go func() {
            c <- i // 4 goroutines will hang here.
        }()
    }
    return <-c
}

```

为避免这 4 个协程一直处于挂起状态， `c` 信道的容量必须至少是 `4`。

在 [实现谁先响应谁获胜的第二种方法](https://go101.org/article/channel-use-cases.html#first-response-wins-2) 的信道使用案例中，如果将 future 信道用做非缓冲信道，那么有可能这个信息将永远也不会有响应而挂起。例如，如果在一个协程中调用下面的函数，协程可能会挂起。原因是，如果接收操作 `<-c` 准备就绪之前，五个发送操作全部尝试发送，那么所有的尝试发送的操作将全部失败，因此那个调用者协程将永远也不会接收到值。

```
func request() int {
    c := make(chan int)
    for i := 0; i < 5; i++ {
        i := i
        go func() {
            select {
            case c <- i:
            default:
            }
        }()
    }
    return <-c
}

```

将信道 `c` 变成缓冲信道将保证五个发送操作中的至少一个操作会发送成功，这样，上面函数中的那个调用者协程将不会被挂起。

### 在 `sync` 标准包中拷贝类型值

在实践中，`sync` 标准包中的类型值不会被拷贝。我们应该只拷贝这个值的指针。

下面是一个错误的并发编程示例。在这个示例中，当调用 `Counter.Value` 方法时，将拷贝一个 `Counter` 接收值。作为接收值的一个字段，`Counter` 接收值的各个 `Mutex` 字段也会被拷贝。拷贝不是同步发生的，因此，拷贝的 `Mutex` 值可能会出错。即便是没有错误，拷贝的 `Counter` 接收值的访问保护也是没有意义的。

```
import "sync"

type Counter struct {
    sync.Mutex
    n int64
}

// This method is okay.
func (c *Counter) Increase(d int64) (r int64) {
    c.Lock()
    c.n += d
    r = c.n
    c.Unlock()
    return
}

// The method is bad. When it is called, a Counter
// receiver value will be copied.
func (c Counter) Value() (r int64) {
    c.Lock()
    r = c.n
    c.Unlock()
    return
}

```

我们只需要改变 `Value` 接收类型方法为指针类型 `*Counter`，就可以避免拷贝 `Mutex` 值。

在官方的 Go SDK 中提供的 `go vet` 命令将会报告潜在的错误值拷贝。

### 在错误的地方调用 `sync.WaitGroup` 的方法

每个 `sync.WaitGroup` 值维护一个内部计数器，这个计数器的初始值为 0。如果一个 `WaitGroup` 计数器的值是 0，调用 `WaitGroup` 值的 `Wait` 方法就不会被阻塞，否则，在计数器值为 0 之前，这个调用会一直被阻塞。

为了让 `WaitGroup` 值的使用有意义，当一个 `WaitGroup` 计数器值为 0 时，必须在相应的 `WaitGroup` 值的 `Wait` 方法调用之前，去调用 `WaitGroup` 值的 `Add` 方法。

例如，下面的程序中，在不正确位置调用了 `Add` 方法，这将使最后打印出的数字不总是 `100`。事实上，这个程序最后打印的数字可能是在 `[0, 100)` 范围内的一个随意数字。原因就是 `Add` 方法的调用并不保证一定会发生在 `Wait` 方法调用之前。

```
package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var wg sync.WaitGroup
    var x int32 = 0
    for i := 0; i < 100; i++ {
        go func() {
            wg.Add(1)
            atomic.AddInt32(&x, 1)
            wg.Done()
        }()
    }

    fmt.Println("To wait ...")
    wg.Wait()
    fmt.Println(atomic.LoadInt32(&x))
}

```

为让程序的表现符合预期，在 `for` 循环中，我们将把 `Add` 方法的调用移动到创建的新协程的范围之外，修改后的代码如下。

```
...
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            atomic.AddInt32(&x, 1)
            wg.Done()
        }()
    }
...

```

### 不正确使用 futures 信道

在 [信道使用案例](https://go101.org/article/channel-use-cases.html) 的文章中，我们知道一些函数将返回 [futures 信道](https://go101.org/article/channel-use-cases.html#future-promise)。假设 `fa` 和 `fb` 就是这样的两个函数，那么下面的调用就使用了不正确的 future 参数。

```
doSomethingWithFutureArguments(<-fa(), <-fb())

```

在上面的代码行中，两个信道接收操作是顺序进行的，而不是并发的。我们做如下修改使它变成并发操作。

```
ca, cb := fa(), fb()
doSomethingWithFutureArguments(<-c1, <-c2)

```

### 没有等协程的最后的活动的发送结束就关闭信道

Go 程序员经常犯的一个错误是，还有一些其它的协程可能会发送值到以前的信道时，这个信道就已经被关闭了。当这样的发送（发送到一个已经关闭的信道）真实发生时，将引发一个异常。

这种错误在一些以往的著名 Go 项目中也有发生，比如在 Kubernetes 项目中的 [这个 bug](https://github.com/kubernetes/kubernetes/pull/45291/files?diff=split) 和 [这个 bug](https://github.com/kubernetes/kubernetes/pull/39479/files?diff=split)。

如何安全和优雅地关闭信道，请阅读 [这篇文章](https://go101.org/article/channel-closing.html)。

### 在值上做 64 位原子操作时没有保证值地址 64 位对齐

到目前为止（Go 1.10），在标准的 Go 编译器中，在一个 64 位原子操作中涉及到的值的地址要求必须是 64 位对齐的。如果没有对齐则导致当前的协程异常。对于标准的 Go 编译器来说，这种失败仅发生在 32 位的架构上。请阅读 [内存布局](https://go101.org/article/memory-layout.html) 去了解如何在一个 32 位操作系统上保证 64 位对齐。

### 没有注意到大量的资源被 `time.After` 函数调用占用

在 `time` 标准包中的 `After` 函数返回 [一个延迟通知的信道](https://go101.org/article/channel-use-cases.html#timer)。这个函数在某些情况下用起来很便捷，但是，每次调用它将创建一个 `time.Timer` 类型的新值。这个新创建的 `Timer` 值在通过传递参数到 `After` 函数指定期间保持激活状态，如果在这个期间过多的调用了该函数，可能会有太多的 `Timer` 值保持激活，这将占用大量的内存和计算资源。

例如，如果调用了下列的 `longRunning` 函数，将在一分钟内产生大量的消息，然后在某些周期内将有大量的 `Timer` 值保持激活，即便是大量的这些 `Timer` 值已经没用了也是如此。

```
import (
    "fmt"
    "time"
)

// The function will return if a message arrival interval
// is larger than one minute.
func longRunning(messages <-chan string) {
    for {
        select {
        case <-time.After(time.Minute):
            return
        case msg := <-messages:
            fmt.Println(msg)
        }
    }
}

```

为避免在上述代码中创建过多的 `Timer` 值，我们将使用一个单一的 `Timer` 值去完成同样的任务。

```
func longRunning(messages <-chan string) {
    timer := time.NewTimer(time.Minute)
    defer timer.Stop()

    for {
        select {
        case <-timer.C:
            return
        case msg := <-messages:
            fmt.Println(msg)
            if !timer.Stop() {
                <-timer.C
            }
        }

        // The above "if" block can also be put here.

        timer.Reset(time.Minute)
    }
}

```

### 不正确地使用 `time.Timer` 值

在最后，我们将展示一个符合语言使用习惯的 `time.Timer` 值的使用示例。需要注意的一个细节是，那个 `Reset` 方法总是在停止或者 `time.Timer` 值释放时被使用。

在 `select` 块的第一个 `case` 分支的结束部分，`time.Timer` 值被释放，因此，我们不需要去停止它。但是必须在第二个分支中停止定时器。如果在第二个分支中 `if` 代码块缺失，它可能至少在 `Reset` 方法调用时，会（通过 Go 运行时）发送到 `timer.C` 信道，并且那个 `longRunning` 函数可能会早于预期返回，对于 `Reset` 方法来说，它可能仅仅是重置内部定时器为 0，它将不会清理（耗尽）那个发送到 `timer.C` 信道的值。

例如，下面的程序很有可能在一秒内而不是十秒时退出。并且更重要的是，这个程序并不是 DRF 的（LCTT 译注：data race free，多线程程序的一种同步程度）。

```
package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Now()
    timer := time.NewTimer(time.Second/2)
    select {
    case <-timer.C:
    default:
        time.Sleep(time.Second) // go here
    }
    timer.Reset(time.Second * 10)
    <-timer.C
    fmt.Println(time.Since(start)) // 1.000188181s
}

```

当 `time.Timer` 的值不再被其它任何一个东西使用时，它的值可能被停留在一种非停止状态，但是，建议在结束时停止它。

在多个协程中如果不按建议使用 `time.Timer` 值并发，可能会有 bug 隐患。

我们不应该依赖一个 `Reset` 方法调用的返回值。`Reset` 方法返回值的存在仅仅是为了兼容性目的。

---

via: <https://go101.org/article/concurrent-common-mistakes.html>

作者：<go101.org> 译者：[qhwdw](https://github.com/qhwdw) 校对：[wxy](https://github.com/wxy)

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


基于 FUSE 的 Bittorrent 文件系统

![](/data/attachment/album/201806/08/073727d0blkrxr005qkvxc.png)

Bittorrent 已经存在了很长时间，它可以从互联网上共享和下载数据。市场上有大量的 GUI 和 CLI 的 Bittorrent 客户端。有时，你不能坐下来等待你的下载完成。你可能想要立即观看内容。这就是 **BTFS** 这个不起眼的文件系统派上用场的地方。使用 BTFS，你可以将种子文件或磁力链接挂载为目录，然后在文件树中作为只读目录。这些文件的内容将在程序读取时按需下载。由于 BTFS 在 FUSE 之上运行，因此不需要干预 Linux 内核。

### 安装 BTFS

BTFS 存在于大多数 Linux 发行版的默认仓库中。

在 Arch Linux 及其变体上，运行以下命令来安装 BTFS。

```
$ sudo pacman -S btfs

```

在Debian、Ubuntu、Linux Mint 上：

```
$ sudo apt-get install btfs

```

在 Gentoo 上：

```
# emerge -av btfs

```

BTFS 也可以使用 [Linuxbrew](https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/) 包管理器进行安装。

```
$ brew install btfs

```

### 用法

BTFS 的使用非常简单。你所要做的就是找到 .torrent 文件或磁力链接，并将其挂载到一个目录中。种子文件或磁力链接的内容将被挂载到你选择的目录内。当一个程序试图访问该文件进行读取时，实际的数据将按需下载。此外，像 `ls` 、`cat` 和 `cp` 这样的工具能按照预期的方式来操作种子。像 `vlc` 和 `mplayer` 这样的程序也可以不加修改地工作。玩家甚至不知道实际内容并非物理存在于本地磁盘中，而是根据需要从 peer 中收集。

创建一个目录来挂载 torrent/magnet 链接：

```
$ mkdir mnt

```

挂载 torrent/magnet 链接：

```
$ btfs video.torrent mnt

```

![](/data/attachment/album/201806/08/073727kqbnx4rq6rg4u83r.png)

cd 到目录：

```
$ cd mnt

```

然后，开始观看！

```
$ vlc <path-to-video.mp4>

```

给 BTFS 一些时间来找到并获取网站 tracker。一旦加载了真实数据，BTFS 将不再需要 tracker。

![](/data/attachment/album/201806/08/073729snquq6g2unwm2fgz.png)

要卸载 BTFS 文件系统，只需运行以下命令：

```
$ fusermount -u mnt

```

现在，挂载目录中的内容将消失。要再次访问内容，你需要按照上面的描述挂载 torrent。

BTFS 会将你的 VLC 或 Mplayer 变成爆米花时间。挂载你最喜爱的电视节目或电影的种子文件或磁力链接，然后开始观看，无需下载整个种子内容或等待下载完成。种子或磁力链接的内容将在程序访问时按需下载。

就是这些了。希望这些有用。还会有更好的东西。敬请关注！

干杯！

---

via: <https://www.ostechnix.com/btfs-a-bittorrent-filesystem-based-on-fuse/>

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


解决构建全球社区带来的挑战

Summary: 全球开源社区通常面临着语音壁垒、文化差异以及其它的挑战。如何去解决它们呢？

全球开源社区通常面临着语音壁垒、文化差异以及其它的挑战。如何去解决它们呢？

>
> 全球开源社区通常面临着语音壁垒、文化差异以及其它的挑战。如何去解决它们呢？
>
>
>

![配图 ](/data/attachment/album/201806/08/075508z5ytolbu5h569xt5.png)

今天的开源组织参与人员来自于全世界。你能预见到组建在线社区可能遇到哪些困难吗？有没有什么办法能够克服这些困难呢？

为开源社区贡献力量的人共同合作推动软件的开发和发展。在过去，人们是面对面或者通过邮件和电话来交流的。今天，科技孕育出了在线交流——人们只需要进入一个聊天室或消息渠道就能一起工作了。比如，你可以早上跟摩洛哥的人一起工作，到了晚上又跟夏威夷的人一起工作。

### 全球社区的三个挑战

任何一个团队合作过的人都知道意见分歧是很难被克服的。对于在线社区来说，语言障碍、不同的时区，以及文化差异也带来了新的挑战。

#### 语言障碍

英语是开源社区中的主流语言，因此英语不好的人会很难看懂文档和修改意见。为了克服这个问题，吸引其他地区的社区成员，你需要邀请双语者参与到社区中来。问问周围的人——你会发现意想不到的精通其他语言的人。社区的双语成员可以帮助别人跨越语言障碍，并且可以通过翻译软件和文档来扩大项目的受众范围。

人们使用的编程语言也不一样。你可能喜欢用 Bash 而其他人则可能更喜欢 Python、Ruby、C 等其他语言。这意味着，人们可能由于编程语言的原因而难以为你的代码库做贡献。项目负责人为项目选择一门被软件社区广泛认可的语言至关重要。如果你选择了一门偏门的语言，则很少人能够参与其中。

#### 不同的时区

时区为开源社区带来了另一个挑战。比如，若你在芝加哥，想与一个在伦敦的成员安排一次视频会议，你需要调整 8 小时的时差。根据合作者的地理位置，你可能要在深夜或者清晨工作。

肉身转移，可以让你的团队在同一个时区工作可以帮助克服这个挑战，但这种方法只有极少数社区才能够负担的起。我们还可以定期举行虚拟会议讨论项目，建立一个固定的时间和地点以供所有人来讨论未决的事项，即将发布的版本等其他主题。

不同的时区也可以成为你的优势，因为团队成员可以全天候的工作。若你拥有一个类似 IRC 这样的实时交流平台，用户可以在任意时间都能找到人来回答问题。

#### 文化差异

文化差异是开源组织面临的最大挑战。世界各地的人都有不同的思考方式、计划以及解决问题的方法。政治环境也会影响工作环境并影响决策。

作为项目负责人，你应该努力构建一种能包容不同看法的环境。文化差异可以鼓励社区沟通。建设性的讨论总是对项目有益，因为它可以帮助社区成员从不同角度看待问题。不同意见也有助于解决问题。

要成功开源，团队必须学会拥抱差异。这不简单，但多样性最终会使社区收益。

### 加强在线沟通的其他方法

* **本地化：** 在线社区成员可能会发现位于附近的贡献者——去见个面并组织一个本地社区。只需要两个人就能组建一个社区了。可以邀请其他当地用户或雇员参与其中；他们甚至还能为以后的聚会提供场所呢。
* **组织活动：** 组织活动是构建本地社区的好方法，而且费用也不高。你可以在当地的咖啡屋或者啤酒厂聚会，庆祝最新版本的发布或者某个核心功能的实现。组织的活动越多，人们参与的热情就越高（即使只是因为单纯的好奇心）。最终，可能会找到一家公司为你提供聚会的场地，或者为你提供赞助。
* **保持联系：** 每次活动后，联系本地社区成员。收起电子邮箱地址或者其他联系方式并邀请他们参与到你的交流平台中。邀请他们为其他社区做贡献。你很可能会发现很多当地的人才，运气好的话，甚至可能发现新的核心开发人员！
* **分享经验：** 本地社区是一种非常有价值的资源，对你，对其他社区来说都是。与可能受益的人分享你的发现和经验。如果你不清楚（LCTT 译注：这里原文是说 sure，但是根据上下文，这里应该是 not sure）如何策划一场活动或会议，可以咨询其他人的意见。也许能找到一些有经验的人帮你走到正轨。
* **关注文化差异：** 记住，文化规范因地点和人而异，因此在清晨安排某项活动可能适用于一个地方的人，但是不合适另一个地方的人。当然，你可以（也应该）利用其他社区的参考资料来更好地理解这种差异性，但有时你也需要通过试错的方式来学习。不要忘了分享你所学到的东西，让别人也从中获益。
* **检查个人观点：** 避免在工作场合提出带有很强主观色彩的观点（尤其是与政治相关的观点）。这会抑制开放式的沟通和问题的解决。相反，应该专注于鼓励与团队成员展开建设性讨论。如果你发现陷入了激烈的争论中，那么后退一步，冷静一下，然后再从更加积极的角度出发重新进行讨论。讨论必须是有建设性的，从多个角度讨论问题对社区有益。永远不要把自己的主观观念放在社区的总体利益之前。
* **尝试异步沟通：** 这些天，实时通讯平台已经引起了大家的关注，但除此之外还别忘了电子邮件。如果没有在网络平台上找到人的话，可以给他们发送一封电子邮件。有可能你很快就能得到回复。考虑使用那些专注于异步沟通的平台，比如 [Twist](https://twistapp.com)，也不要忘了查看并更新论坛和维基。
* **使用不同的解决方案：** 并不存在一个单一的完美的解决方法，学习最有效的方法还是通过经验来学习。从反复试验中你可以学到很多东西。不要害怕失败；你会从失败中学到很多东西从而不停地进步。

### 社区需要营养

将社区想象成是一颗植物的幼苗。你需要每天给它浇水，提供阳光和氧气。社区也是一样：倾听贡献者的声音，记住你在与活生生的人进行互动，他们需要以合适的方式进行持续的交流。如果社区缺少了人情味，人们会停止对它的贡献。

最后，请记住，每个社区都是不同的，没有一种单一的解决方法能够适用于所有社区。坚持不断地从社区中学习并适应这个社区。

---

via: <https://opensource.com/article/17/12/working-worldwide-communities>

作者：[José Antonio Rey](https://opensource.com/users/jose) 译者：[lujun9972](https://github.com/lujun9972) 校对：[wxy](https://github.com/wxy)

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


面向数据科学的 Anaconda Python 入门

>
> Anaconda 是一个完备的、开源的数据科学软件包，拥有超过 600 万社区用户。
>
>
>

![](/data/attachment/album/201806/08/221955rc3dj0j3m4bj811m.png)

像很多人一样，我一直努力加入到快速发展的数据科学领域。我上过 Udemy 的 [R](https://www.r-project.org/) 及 [Python](https://www.python.org/) 语言编程课，那时我分别下载并安装了应用程序。当我试图解决各种依赖关系，安装类似 [Numpy](http://www.numpy.org/) 和 [Matplotlib](https://matplotlib.org/) 这样的数据科学扩展包时，我了解了 [Anaconda Python 发行版](https://www.anaconda.com/distribution/)。

Anaconda 是一个完备的、[开源](https://docs.anaconda.com/anaconda/eula)的数据科学包，拥有超过 600 万社区用户。[下载](https://www.anaconda.com/download/#linux)和安装 Anaconda 都很容易，支持的操作系统包括 Linux, MacOS 及 Windows。

我感谢 Anaconda 降低了初学者的学习门槛。发行版自带 1000 多个数据科学包以及 [Conda](https://conda.io/) 包和虚拟环境管理器，让你无需单独学习每个库的安装方法。就像 Anaconda 官网上提到的，“Anaconda 库中的 Python 和 R 语言的 conda 包是我们在安全环境中修订并编译得到的优化二进制程序，可以在你系统上工作”。

我推荐使用 [Anaconda Navigator](https://docs.anaconda.com/anaconda/navigator/)，它是一个桌面 GUI 系统，包含了发行版自带的全部应用的链接，包括 [RStudio](https://www.rstudio.com/)、 [iPython](https://ipython.org/)、 [Jupyter Notebook](http://jupyter.org/)、 [JupyterLab](https://blog.jupyter.org/jupyterlab-is-ready-for-users-5a6f039b8906)、 [Spyder](https://spyder-ide.github.io/)、 [Glue](http://glueviz.org/) 和 [Orange](https://orange.biolab.si/)。默认环境采用 Python 3.6，但你可以轻松安装 Python 3.5、 Python 2.7 或 R。[文档](https://orange.biolab.si/)十分详尽，而且用户社区极好，可以提供额外的支持。

### 安装 Anaconda

为在我的 Linux 笔记本（I3 CPU，4GB 内存）上安装 Anaconda，我下载了 Anaconda 5.1 Linux 版安装器并运行 `md5sum` 进行文件校验：

```
$ md5sum Anaconda3-5.1.0-Linux-x86_64.sh

```

接着按照[安装文档](https://docs.anaconda.com/anaconda/install/linux)的说明，无论是否在 Bash shell 环境下，执行如下 shell 命令：

```
$ bash Anaconda3-5.1.0-Linux-x86_64.sh

```

我完全按照安装指南操作，运行这个精心编写的脚本，大约花费 5 分钟可以完成安装。安装过程中会提示：“是否希望安装器将 Anaconda 的安装路径加入到你的 `/home/<user>/.bashrc`？”我选择允许并重启了 shell，这会让 `.bashrc` 中的环境变量生效。

安装完成后，我启动了 Anaconda Navigator，具体操作是在 shell 中执行如下命令：

```
$ anaconda-navigator

```

Anaconda Navigator 每次启动时会检查是否有可更新的软件包，如果有，会提醒你进行更新。

![](/data/attachment/album/201806/08/221956rh8w4z8jia86zc08.png)

按照提醒进行更新即可，无需使用命令行。Anaconda 初次启动会有些慢，如果涉及更新会额外花费几分钟。

当然，你也可以通过执行如下命令手动更新：

```
$ conda update anaconda-navigator

```

### 浏览和安装应用

Navigator 启动后，可以很容易地浏览 Anaconda 发行版包含的应用。按照文档所述，64 位 Python 3.6 版本的 Anaconda [支持 499 个软件包](https://docs.anaconda.com/anaconda/packages/py3.6_linux-64)。我浏览的第一个应用是 [Jupyter QtConsole](http://qtconsole.readthedocs.io/en/stable/)，这个简单易用的 GUI 支持内联数据 (inline figures) 和语法高亮。

![](/data/attachment/album/201806/08/221958g2fwftxt6vo51ftt.png)

发行版中包含 Jupyter Notebook，故无需另外安装（不像我用的其它 Python 环境那样）。

![](/data/attachment/album/201806/08/222003js5883nrn8x5xyxn.png)

我习惯使用的 RStudio 并没有默认安装，但安装它也仅需点击一下鼠标。其它应用的启动或安装也仅需点击一下鼠标，包括 JupyterLab、 Orange、 Glue 和 Spyder 等。

![](/data/attachment/album/201806/08/222008qppgzof0uapu8puc.png)

Anaconda 发行版的一个强大功能是创建多套环境。假如我需要创建一套与默认 Python 3.6 不同的 Python 2.7 的环境，可以在 shell 中执行如下命令：

```
$ conda create -n py27 python=2.7 anaconda

```

Conda 负责整个安装流程，如需启动它，仅需在 shell 中执行如下命令：

```
$ anaconda-navigator

```

在 Anaconda GUI 的 “Applications on” 下拉菜单中选取 **py27** 即可。

![](/data/attachment/album/201806/08/222012khbq8pzjjqd6huvb.png)

### 更多内容

如果你想了解更多关于 Anaconda 的信息，可供参考的资源十分丰富。不妨从检索 [Anaconda 社区](https://www.anaconda.com/community/)及对应的[邮件列表](https://groups.google.com/a/continuum.io/forum/#!forum/anaconda)开始。

你是否在使用 Anaconda 发行版及 Navigator 呢？欢迎在评论中留下你的使用感想。

---

via: <https://opensource.com/article/18/4/getting-started-anaconda-python>

作者：[Don Watkins](https://opensource.com/users/don-watkins) 选题：[lujun9972](https://github.com/lujun9972) 译者：[pinewall](https://github.com/pinewall) 校对：[wxy](https://github.com/wxy)

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