2018年6月

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

进程出错的时候,您可能会想要中止或是杀掉这个进程。在本文中,我们将探索在命令行和图形界面中终止进程或是应用程序,这里我们使用 gedit 作为样例程序。

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

Ctrl + C

在命令行中调用 gedit (如果您没有使用 gedit & 命令)程序的一个问题是 shell 会话被阻塞,没法释放命令行提示符。在这种情况下,Ctrl + CCtrlC 的组合键) 会很管用。这会终止 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 灰屏或挂起?现在你可以像上面一样获得进程的 PID 来杀掉它,或者使用 xkill 命令终止应用程序。

 title=

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

参阅手册,了解上述命令更多信息。您还可以接续探索 pkillpgrep 命令。


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

作者:Sachin Patil 选题:lujun9972 译者:CYLeft 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

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

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

 title=

我 DIY 的绘图仪;在这里看它工作的视频

由于我是一个很怀旧的人,我真的很喜欢最初的 Arduino Uno。下面是我用到的其它东西的一个清单(仅供参考,其中一些我也不是很满意):

  • FabScan shield:承载步进电机驱动器。
  • SilentStepSticks:步进电机驱动器,因为 Arduino 自身不能处理步进电机所需的电压和电流。因此我使用了一个 Trinamic TMC2130 芯片,但它是工作在单独模式。这些替换为 Pololu 4988,但是它们运转更安静。
  • SilentStepStick 保护装置:一个防止你的电机驱动器转动过快的二极管(相信我,你肯定会需要它的)。
  • 步进电机:我选择的是使用 12 V 电压的 NEMA 17 电机(如,来自 WatterottSparkFun 的型号)。
  • 直线导杆
  • 木制的基板
  • 木螺丝
  • GT2 皮带
  • GT2 同步滑轮

这是我作为个人项目而设计的。如果你想找到一个现成的工具套件,你可以从 German Make 杂志上找到 MaXYposi

硬件安装

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

 title=

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

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

 title=

电机上的皮带路由

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

Arduino and Shield

Arduino 堆叠配置(高清大图

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

软件配置

基础部分

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

使用 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 号电机
启用25
方向47
步进36

在我们使用这些针脚之前,我们需要在代码的 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 给它提供一个很大的路径(很多的路径)去绘制。(在这个视频中展示了如何绘制 Hilbert 曲线)

设计一个好用的握笔器

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

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

 title=

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

笔是用一个小夹具固定住的(图上展示的是一个大小为 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 博客中并授权重分发。


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

作者:Heiko W.Rupp 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

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

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

在生产中分析

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

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

为什么?

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

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

启用

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 天。

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

阅读火焰图

Brendan Gregg 非常全面地解释了火焰图可视化。Stackdriver Profiler 增加了一点它自己的特点。

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

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

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

过滤

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

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

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

作者:JBD 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

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

container orchestrator

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

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

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

诱因和威胁模型

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

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

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

最小权限原则

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

内核缺省安全

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

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

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

可信引导和节点引入

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

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

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

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

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

Docker Swarm

引导信任

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

Docker Security

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

节点身份发布和管理

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

身份发布

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

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

身份标识延期

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

Docker secrets

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

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

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

传输安全

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

Swarm Mode

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

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

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

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

Docker Swarm Security

安全分发机密

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

Docker Secrets

在主机上,Docker 企业版能确保机密仅提供给它们指定的容器。在同一个主机上的其它容器并不能访问它们。Docker 以一个临时文件系统的方式显露机密给一个容器,确保机密总是保存在内存中,并且从不写入到磁盘。这种方式比其它竞争的替代者更加安全,比如,在环境变量中存储它们。一旦这个任务完成,这个机密将永远消失。

存储机密

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

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

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

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

Docker Secrets

在传统的编排器中,挽回一台被攻陷的主机是一个缓慢而复杂的过程。使用 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 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

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

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

同步决策,要求参与者实时地进行互动,而这对那些需要 大块完整时间工作 Maker's Schedule 的人来说代价非常大,而且对于远程团队来说这也不现实。我们会发现这种会议最后浪费的时间让人难以置信。

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

怎样才能异步决策呢?

所需工具

中心化的异步沟通渠道

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

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

公司团队可以从一个更加现代化的协作工具中收益,这类工具更易使用并提供了更加强大的多媒体功能。不管你用的是哪个工具,关键在于要创建一个能让大量的人员有效沟通并异步地讨论各种主题的渠道。要创建一个一致而活跃的社区,使用一个 繁忙的渠道要好过建立多个渠道

构建共识的机制

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

案例管理系统

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

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

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

成功的案例

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

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

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


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

作者:Bertrand Delacretaz 译者:lujun9972 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

摘要

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

  • 对比现有配置,手动在新配置文件中改动
  • 利用 sedawk 等工具配合改动
  • 采用 diffpatch 制作增量补丁的方式改动

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

diff 介绍

diff 是一个文件比较工具,可以逐行比较两个文件的不同,其中它有三种输出方式,分别是 normalcontext 以及 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 指定补丁文件
  • -pNumdiff 生成的补丁中,第一二行是文件信息,其中文件名是可以包含路径的,例如 --- /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 桌面部分功能无法使用,因此需要迁移到新配置,接下来则应用 diffpatch 实现迁移,当然你也可以单纯使用 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  ### 打完补丁直接使用

总结

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

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