标签 Bug 下的文章

软件有 bug。任何复杂系统都无法保证每个部分都能按计划工作。Fedora Linux 是一个 非常 复杂的系统,包含几千个包,这些包由全球无数个独立的上游项目创建。每周还有数百个更新。因此,问题是不可避免的。本文介绍了 bug 修复过程以及如何确定 bug 优先级。

发布开发过程

作为一个 Linux 发行项目,我们希望为用户提供完善的、一切正常的体验。我们的发布起始于 “Rawhide”。我们在 Rawhide 中集成了所有更新的自由及开源软件的新版本。我们一直在不断改进正在进行的测试和 持续集成 Continuous Integration 过程,为了让即使是 Rawhide 也能被冒险者安全使用。可是,从本质来讲,Rawhide 始终有点粗糙。

每年两次,我们把这个粗糙的操作系统先后分支到测试版本、最终版本。当我们这么做时,我们齐心协力地寻找问题。我们在 测试日 Test Days 检查特定的区域和功能。制作“ 候选版本 Candidate builds ”,并根据我们的 发布验证测试计划 进行检测。然后我们进入 冻结状态 freeze state ,只有批准的更改可以并入候选版本。这就把候选版本从持续的开发隔离开来,持续的开发不断并入 Rawhide 中。所以,不会引入新的问题。

在发布过程中许多 bug 被粉碎去除,这些 bug 有大有小。当一切按计划进行时,我们为所有用户提供了按计划发布的崭新的 Fedora Linux 版本。(在过去几年里,我们已经可靠地重复这一动作——感谢每一个为之努力工作的人!)如果确实有问题,我们可以将其标记为 发布阻碍 release blocker 。这就意味着我们要等到修复后才能发布。发布阻碍通常代表重大问题,该表达一定会引发对 bug 的关注。

有时,我们遇到的一些问题是持续存在的。可能一些问题已经持续了一两个版本,或者我们还没有达成共识的解决方案。有些问题确实困扰着许多用户,但个别问题并没有达到阻碍发布的程度。我们可以将这些东西标记为 阻碍 blocker 。但这会像锤子一样砸下来。阻碍可能导致最终粉碎该 bug,但也可能导致破坏了周围。如果进度落后,所有其它的 bug 修复、改进以及人们一直在努力的功能,都不能到达用户手中。

按优先顺序排列 bug 流程

所以,我们有另一种方法来解决烦人的 bug。按优先顺序排列 bug 流程,与其他方式不同,可以标出导致大量用户不满意的问题。这里没有锤子,更像是聚光灯。与发布阻碍不同,按优先顺序排列 bug 流程没有一套严格定义的标准。每个 bug 都是根据影响范围和严重性来评估的。

一个由感兴趣的贡献者组成的团队帮助策划一个简短列表,上面罗列着需要注意的问题。然后,我们的工作是将问题匹配到能够解决它们的人。这有助于减轻发布过程中的压力,因为它没有给问题指定任何特定的截止时间。理想情况下,我们能在进入测试阶段之前就发现并解决问题。我们尽量保持列表简短,不会超过几个,这样才会真正有重点。这种做法有助于团队和个人解决问题,因为他们知道我们尊重他们捉襟见肘的时间与精力。

通过这个过程,Fedora 解决了几十个严重而恼人的问题,包括从键盘输入故障到 SELinux 错误,再到数千兆字节大小的旧包更新会逐渐填满你的磁盘。但是我们可以做得更多——我们实际上收到的提案没有达到我们的处理能力上限。因此,如果你知道有什么事情导致了长期挫折或影响了很多人,至今没有达成解决方案,请遵循 按优先顺序排列 bug 流程,提交给我们。

你可以帮助我们

邀请所有 Fedora 贡献者参与按优化顺序排列 bug 的流程。评估会议每两周在 IRC 上举办一次。欢迎任何人加入并帮助我们评估提名的 bug。会议时间和地点参见 日历。Fedora 项目经理在会议开始的前一天将议程发送到 triagedevel 邮件列表。

欢迎报告 bug

当你发现 bug 时,无论大小,我们很感激你能报告 bug。在很多情况下,解决 bug 最好的方式是交给创建该软件的项目。例如,假设渲染数据相机照片的 Darktable 摄影软件出了问题,最好把它带给 Darktable 摄影软件的开发人员。再举个例子,假设 GNOME 或 KDE 桌面环境或组成部分软件出了问题,将这些问题交给这些项目中通常会得到最好的结果。

然而, 如果这是一个特定的 Fedora 问题,比如我们的软件构建或配置或者它的集成方式的问题,请毫不犹豫地 向我们提交 bug。当你知道有一个问题是我们还没有解决的,也要提交给我们。

我知道这很复杂……最好有一个一站式的地方来处理所有 bug。但是请记住,Fedora 打包者大部分是志愿者,他们负责获取上游软件并将其配置到我们系统中。他们并不总是对他们正在使用的软件的代码有深入研究的专家。有疑问的时候,你可以随时提交一个 Fedora bug。Fedora 中负责相应软件包的人可以通过他们与上游软件项目的联系提供帮助。

请记住,当你发现一个已通过诊断但尚未得到良好修复的 bug 时,当你看到影响很多人的问题时,或者当有一个长期存在的问题没有得到关注时,请将其提名为高优先级 bug。我们会看以看能做些什么。

附言:标题中的著名图片当然是来自哈佛大学马克 2 号计算机的日志,这里曾是格蕾丝·赫柏少将工作的地方。但是与这个故事的普遍看法相背,这并不是 “bug” 一词第一次用于表示系统问题——它在工程中已经很常见了,这就是为什么发现一个字面上的 “bug” 作为问题的原因是很有趣的。 #nowyouknow #jokeexplainer


via: https://fedoramagazine.org/something-bugging-you-in-fedora-linux-lets-get-it-fixed/

作者:Matthew Miller 选题:lujun9972 译者:DCOLIVERSUN 校对:wxy

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

从发现软件故障到解决它们,这里讲述是开发团队如何压制软件 bug。

1947 年,发现了第一个计算机 bug —— 被困在计算机继电器中的飞蛾。

要是所有的 bug 都能如此简单地发现就好了。随着软件变得越来越复杂,测试和调试的过程也变得更加复杂。如今,软件 bug 的生命周期可能会很长,尽管正确的技术和业务流程可能会有所帮助。对于开源软件,开发人员使用严格的工单服务和协作来查找和解决 bug。

确认计算机 bug

在测试过程中,发现的 bug 会报告给开发团队。质量保证测试人员尽可能详细地描述 bug ,报告他们的系统状态、他们正在进行的过程以及 bug 是如何表现出来的。

尽管如此,一些 bug 从未得到确认;它们可能会在测试中报告,但永远无法在可控环境中重现。在这种情况下,它们可能得不到解决,而是被关闭。

有些计算机 bug 可能很难确认,因为使用的平台种类繁多,用户行为也非常多。有些 bug 只是间歇性地或在非常特殊的情况下发生的,而另一些 bug 可能会出现在随机的情况下。

许多人使用开源软件并与之交互,许多 bug 和问题可能是不可重复的,或者可能没有得到充分的描述。不过,由于每个用户和开发人员也都扮演质量保证测试人员的角色,至少在一定程度上,bug 还是很有可能会发现的。

确认 bug 后,修复工作就开始了。

分配要修复的 bug

已确认的 bug 被分配给负责解决的开发人员或开发团队。在此阶段,需要重现 bug,发现问题,并修复相关代码。如果 bug 的优先级较低,开发人员可以将此 bug 分类为稍后要修复的问题,也可以在该 bug 具有高优先级的情况下直接指派某人修复。无论哪种方式,都会在开发过程中打开一个工单,并且 bug 将成为已知的问题。

在开源解决方案中,开发人员可以进行选择他们想要解决的 bug,要么选择他们最熟悉的程序区域,要么从优先级最高的的开始。综合解决方案,如 GitHub 使得多个开发人员能够轻松地着手解决,而不会干扰彼此的工作。

当将 bug 设置为需要修复时,bug 报告者还可以为该 bug 选择优先级。主要的 bug 可能具有较高的优先级,而仅与外观相关的 bug 可能具有较低的级别。优先级确定开发团队解决这些问题的方式和时间。无论哪种方式,所有的 bug 都需要先解决,然后才能认为产品已完成。在这方面,适当的回溯到优先级高的需求也会很有帮助。

解决 bug

一旦修复了 bug ,通常会将其作为已解决的 bug 发送回质量保证测试人员。然后,质量保证测试人员再次将产品置于其工作中,以重现 bug。如果无法重现 bug ,质量保证测验人员将假定它已得到适当解决。

在开源情况下,任何更改都会被分发,通常是作为正在测试的暂定版本。此测试版本分发给用户,用户再次履行质量保证测试人员的职责并测试产品。

如果 bug 再次出现,问题将被发送回开发团队。在此阶段,该 bug 将重新触发,开发团队有责任重复解决该 bug 的循环。这种情况可能会发生多次,尤其是在 bug 不可预知或间歇性发生的情况下。众所周知,间歇性的 bug 很难解决。

如果该 bug 不再出现,则该问题将被标记为已解决。在某些情况下,最初的 bug 得到了解决,但由于所做的更改,会出现其他 bug。发生这种情况时,可能需要新的 bug 报告,然后重新开始该过程。

关闭 bug

在处理、识别和解决 bug 后,该 bug 将被关闭,开发人员可以转到软件开发和测试的其他阶段。如果始终找不到 bug ,或者开发人员无法重现 bug ,则该 bug 也将被关闭 —— 无论哪种方式,都将开始开发和测试的下一阶段。

在测试版本中对解决方案所做的任何更改都将滚动到产品的下一个版本中。如果 bug 是严重的,则在下一个版本发布之前,可能会为当前用户提供修补程序或修补程序。这在安全问题中很常见。

软件 bug 可能很难找到,但通过遵循过程,开发人员可以使开发更快、更容易、更一致。质量保证是这一过程的重要组成部分,因为质量保证测试人员必须发现和识别 bug ,并帮助开发人员重现这些 bug 。在 bug 不再发生之前,无法关闭和解决 bug。

开源的解决方案分散了质量保证测试、开发和缓解的负担,这往往导致 bug 被更快、更全面地发现和缓解。但是,由于开源技术的性质,此过程的速度和准确性通常取决于解决方案的受欢迎程度及其维护和开发团队的敬业精神。

Rich Butkevic 是一个 PMP 项目经理认证,,敏捷开发框架认证(certified scrum master) 并且 维护 Project Zendo,这是供项目管理专业人员去发现、简化和改进其项目成果策略的网站。可以在 Richbutkevic.com 或者使用 LinkedIn 与 Rich 联系。


via: https://opensource.com/article/18/6/life-cycle-software-bug

作者:Rich Butkevic 选题:lujun9972 译者:lixinyuxx 校对:wxy

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

十月初的时候我在贝洛奥里藏特的 巴西 Python 大会 Python Brasil 上做了主题演讲。这是稍加改动过的演讲文稿。你可以在这里观看演讲视频。

我爱 bug

我目前是 Pilot.com 的一位高级工程师,负责给创业公司提供自动记账服务。在此之前,我曾是 Dropbox 的桌面客户端组的成员,我今天将分享关于我当时工作的一些故事。更早之前,我是 Recurse Center 的导师,给身在纽约的程序员提供临时的训练环境。在成为工程师之前,我在大学攻读天体物理学并在金融界工作过几年。

但这些都不重要——关于我你唯一需要知道的是,我爱 bug。我爱 bug 因为它们有趣。它们富有戏剧性。调试一个好的 bug 的过程可以非常迂回曲折。一个好的 bug 像是一个有趣的笑话或者或者谜语——你期望看到某种结果,但却事与愿违。

在这个演讲中我会给你们讲一些我曾经热爱过的 bug,解释为什么我如此爱 bug,然后说服你们也同样去热爱 bug。

Bug 1 号

好,让我们直接来看第一个 bug。这是我在 Dropbox 工作时遇到的一个 bug。你们或许听说过,Dropbox 是一个将你的文件从一个电脑上同步到云端和其他电脑上的应用。

        +--------------+     +---------------+
        |              |     |               |
        |  元数据服务器  |     |     块服务器    |
        |              |     |               |
        +-+--+---------+     +---------+-----+
          ^  |                         ^
          |  |                         |
          |  |     +----------+        |
          |  +---> |          |        |
          |       |   客户端   +--------+
          +--------+          |
                   +----------+

这是个极度简化的 Dropbox 架构图。桌面客户端在你的电脑本地运行,监听文件系统的变动。当它检测到文件改动时,它读取改变的文件,并把它的内容 hash 成 4 MB 大小的文件块。这些文件块被存放在后端一个叫做 块服务器 blockserver 的巨大的 键值对数据库 key-value store 中。

当然,我们想避免多次上传同一个文件块。可以想见,如果你在编写一份文档,你应该大部分时候都在改动文档最底部——我们不想一遍又一遍地上传开头部分。所以在上传文件块到块服务器之前之前,客户端会先和一个负责管理元数据和权限等等的服务器沟通。客户端会询问这个 元数据服务器 metaserver 它是需要这个文件块,还是已经见过这个文件块了。元数据服务器会返回每一个文件块是否需要上传。

所以这些请求和响应看上去大概是这样:客户端说“我有一个改动过的文件,分为这些文件块,它们的 hash 是 'abcd,deef,efgh'。服务器响应说“我有前两块,但需要你上传第三块”。然后客户端会把那个文件块上传到块服务器。

                +--------------+     +---------------+
                |              |     |               |
                |  元数据服务器  |     |     块服务器    |
                |              |     |               |
                +-+--+---------+     +---------+-----+
                  ^  |                         ^
                  |  | '有, 有, 无'             |
'abcd,deef,efgh'  |  |     +----------+        | efgh: [内容]
                  |  +---> |          |        |
                  |        |   客户端   +--------+
                  +--------+          |
                           +----------+

这是问题的背景。下面是 bug。

                +--------------+
                |              |
                |    块服务器    |
                |              |
                +-+--+---------+
                  ^  |
                  |  |   '???'
'abcdldeef,efgh'  |  |     +----------+
     ^            |  +---> |          |
     ^            |        |   客户端  +
                  +--------+          |
                           +----------+

有时候客户端会提交一个奇怪的请求:每个 hash 值应该包含 16 个字母,但它却发送了 33 个字母——所需数量的两倍加一。服务器不知道该怎么处理它,于是会抛出一个异常。我们收到这个异常的报告,于是去查看客户端的记录文件,然后会看到非常奇怪的事情——客户端的本地数据库损坏了,或者 python 抛出 MemoryError,没有一个合乎情理的。

如果你以前没见过这个问题,可能会觉得毫无头绪。但当你见过一次之后,你以后每次看到都能轻松地认出它来。给你一个提示:在那些 33 个字母的字符串中,l 经常会代替逗号出现。其他经常出现的字符是:

l \x0c < $ ( . -

英文逗号的 ASCII 码是 44。l 的 ASCII 码是 108。它们的二进制表示如下:

bin(ord(',')): 0101100  
bin(ord('l')): 1101100  

你会注意到 l 和逗号只差了一位。问题就出在这里:发生了位反转。桌面客户端使用的内存中的一位发生了错误,于是客户端开始向服务器发送错误的请求。

这是其他经常代替逗号出现的字符的 ASCII 码:

,    : 0101100
l    : 1101100
\x0c : 0001100
<    : 0111100
$    : 0100100
(    : 0101000
.    : 0101110
-    : 0101101

位反转是真的!

我爱这个 bug 因为它证明了位反转是可能真实发生的事情,而不只是一个理论上的问题。实际上,它在某些情况下会比平时更容易发生。其中一种情况是用户使用的是低配或者老旧的硬件,而运行 Dropbox 的电脑很多都是这样。另外一种会造成很多位反转的地方是外太空——在太空中没有大气层来保护你的内存不受高能粒子和辐射的影响,所以位反转会十分常见。

你大概非常在乎在宇宙中运行的程序的正确性——你的代码或许事关国际空间站中宇航员的性命,但即使没有那么重要,也还要考虑到在宇宙中很难进行软件更新。如果你的确需要让你的程序能够处理位反转,有很多硬件和软件措施可供你选择,Katie Betchold 还关于这个问题做过一个非常有意思的讲座

在刚才那种情况下,Dropbox 并不需要处理位反转。出现内存损坏的是用户的电脑,所以即使我们可以检测到逗号字符的位反转,但如果这发生在其他字符上我们就不一定能检测到了,而且如果从硬盘中读取的文件本身发生了位反转,那我们根本无从得知。我们能改进的地方很少,于是我们决定无视这个异常并继续程序的运行。这种 bug 一般都会在客户端重启之后自动解决。

不常见的 bug 并非不可能发生

这是我最喜欢的 bug 之一,有几个原因。第一,它提醒我注意不常见和不可能之间的区别。当规模足够大的时候,不常见的现象会以值得注意的频率发生。

覆盖面广的 bug

这个 bug 第二个让我喜欢的地方是它覆盖面非常广。每当桌面客户端和服务器交流的时候,这个 bug 都可能悄然出现,而这可能会发生在系统里很多不同的端点和组件当中。这意味着许多不同的 Dropbox 工程师会看到这个 bug 的各种版本。你第一次看到它的时候,你 真的 会满头雾水,但在那之后诊断这个 bug 就变得很容易了,而调查过程也非常简短:你只需找到中间的字母,看它是不是个 l

文化差异

这个 bug 的一个有趣的副作用是它展示了服务器组和客户端组之间的文化差异。有时候这个 bug 会被服务器组的成员发现并展开调查。如果你的 服务器 上发生了位反转,那应该不是个偶然——这很可能是内存损坏,你需要找到受影响的主机并尽快把它从集群中移除,不然就会有损坏大量用户数据的风险。这是个事故,而你必须迅速做出反应。但如果是用户的电脑在破坏数据,你并没有什么可以做的。

分享你的 bug

如果你在调试一个难搞的 bug,特别是在大型系统中,不要忘记跟别人讨论。也许你的同事以前就遇到过类似的 bug。若是如此,你可能会节省很多时间。就算他们没有见过,也不要忘记在你解决了问题之后告诉他们解决方法——写下来或者在组会中分享。这样下次你们组遇到类似的问题时,你们都会早有准备。

Bug 如何帮助你进步

Recurse Center

在加入 Dropbox 之前,我曾在 Recurse Center 工作。它的理念是建立一个社区让正在自学的程序员们聚到一起来提高能力。这就是 Recurse Center 的全部了:我们没有大纲、作业、截止日期等等。唯一的前提条件是我们都想要成为更好的程序员。参与者中有的人有计算机学位但对自己的实际编程能力不够自信,有的人已经写了十年 Java 但想学 Clojure 或者 Haskell,还有各式各样有着其他的背景的参与者。

我在那里是一位导师,帮助人们更好地利用这个自由的环境,并参考我们从以前的参与者那里学到的东西来提供指导。所以我的同事们和我本人都非常热衷于寻找对成年自学者最有帮助的学习方法。

刻意练习

在学习方法这个领域有很多不同的研究,其中我觉得最有意思的研究之一是刻意练习的概念。刻意练习理论意在解释专业人士和业余爱好者的表现的差距。它的基本思想是如果你只看内在的特征——不论先天与否——它们都无法非常好地解释这种差距。于是研究者们,包括最初的 Ericsson、Krampe 和 Tesch-Romer,开始寻找能够解释这种差距的理论。他们最终的答案是在刻意练习上所花的时间。

他们给刻意练习的定义非常精确:不是为了收入而工作,也不是为了乐趣而玩耍。你必须尽自己能力的极限,去做一个和你的水平相称的任务(不能太简单导致你学不到东西,也不能太难导致你无法取得任何进展)。你还需要获得即时的反馈,知道自己是否做得正确。

这非常令人兴奋,因为这是一套能够用来建立专业技能的系统。但难点在于对于程序员来说这些建议非常难以实施。你很难知道你是否处在自己能力的极限。也很少有即时的反馈帮助你改进——有时候你能得到任何反馈都已经算是很幸运了,还有时候你需要等几个月才能得到反馈。对于在 REPL 中做的简单的事情你可以很快地得到反馈,但如果你在做一个设计上的决定或者技术上的选择,你在很长一段时间里都无法得到反馈。

但是在有一类编程工作中刻意练习是非常有用的,它就是 debug。如果你写了一份代码,那么当时你是理解这份代码是如何工作的。但你的代码有 bug,所以你的理解并不完全正确。根据定义来说,你正处在你理解能力的极限上——这很好!你马上要学到新东西了。如果你可以重现这个 bug,那么这是个宝贵的机会,你可以获得即时的反馈,知道自己的修改是否正确。

像这样的 bug 也许能让你学到关于你的程序的一些小知识,但你也可能会学到一些关于运行你的代码的系统的一些更复杂的知识。我接下来要讲一个关于这种 bug 的故事。

Bug 2 号

这也是我在 Dropbox 工作时遇到的 bug。当时我正在调查为什么有些桌面客户端没有像我们预期的那样持续发送日志。我开始调查客户端的日志系统并且发现了很多有意思的 bug。我会挑一些跟这个故事有关的 bug 来讲。

和之前一样,这是一个非常简化的系统架构。

                                   +--------------+
                                   |              |
               +---+  +----------> |   日志服务器   |
               |日志|  |            |              |
               +---+  |            +------+-------+
                      |                   |
                +-----+----+              |  200 ok
                |          |              |
                |  客户端   |  <-----------+
                |          |
                +-----+----+
                      ^
                      +--------+--------+--------+
                      |        ^        ^        |
                   +--+--+  +--+--+  +--+--+  +--+--+
                   | 日志 |  | 日志 |  | 日志 |  | 日志 |
                   |     |  |     |  |     |  |     |
                   |     |  |     |  |     |  |     |
                   +-----+  +-----+  +-----+  +-----+

桌面客户端会生成日志。这些日志会被压缩、加密并写入硬盘。然后客户端会间歇性地把它们发送给服务器。客户端从硬盘读取日志并发送给日志服务器。服务器会将它解码并存储,然后返回 200。

如果客户端无法连接到日志服务器,它不会让日志目录无限地增长。超过一定大小之后,它会开始删除日志来让目录大小不超过一个最大值。

最初的两个 bug 本身并不严重。第一个 bug 是桌面客户端向服务器发送日志时会从最早的日志而不是最新的日志开始。这并不是很好——比如服务器会在客户端报告异常的时候让客户端发送日志,所以你可能最在乎的是刚刚生成的日志而不是在硬盘上的最早的日志。

第二个 bug 和第一个相似:如果日志目录的大小达到了上限,客户端会从最新的日志而不是最早的日志开始删除。同理,你总是会丢失一些日志文件,但你大概更不在乎那些较早的日志。

第三个 bug 和加密有关。有时服务器会无法对一个日志文件解码(我们一般不知道为什么——也许发生了位反转)。我们在后端没有正确地处理这个错误,而服务器会返回 500。客户端看到 500 之后会做合理的反应:它会认为服务器停机了。所以它会停止发送日志文件并且不再尝试发送其他的日志。

对于一个损坏的日志文件返回 500 显然不是正确的行为。你可以考虑返回 400,因为问题出在客户端的请求上。但客户端同样无法修复这个问题——如果日志文件现在无法解码,我们后也永远无法将它解码。客户端正确的做法是直接删除日志文件然后继续运行。实际上,这正是客户端在成功上传日志文件并从服务器收到 200 的响应时的默认行为。所以我们说,好——如果日志文件无法解码,就返回 200。

所有这些 bug 都很容易修复。前两个 bug 出在客户端上,所以我们在 alpha 版本修复了它们,但大部分的客户端还没有获得这些改动。我们在服务器代码中修复了第三个 bug 并部署了新版的服务器。

激增

突然日志服务器集群的流量开始激增。客服团队找到我们并问我们是否知道原因。我花了点时间把所有的部分拼到一起。

在修复之前,这四件事情会发生:

  1. 日志文件从最早的开始发送
  2. 日志文件从最新的开始删除
  3. 如果服务器无法解码日志文件,它会返回 500
  4. 如果客户端收到 500,它会停止发送日志

一个存有损坏的日志文件的客户端会试着发送这个文件,服务器会返回 500,客户端会放弃发送日志。在下一次运行时,它会尝试再次发送同样的文件,再次失败,并再次放弃。最终日志目录会被填满,然后客户端会开始删除最新的日志文件,而把损坏的文件继续保留在硬盘上。

这三个 bug 导致的结果是:如果客户端在任何时候生成了损坏的日志文件,我们就再也不会收到那个客户端的日志了。

问题是,处于这种状态的客户端比我们想象的要多很多。任何有一个损坏文件的客户端都会像被关在堤坝里一样,无法再发送日志。现在这个堤坝被清除了,所有这些客户端都开始发送它们的日志目录的剩余内容。

我们的选择

好的,现在文件从世界各地的电脑如洪水般涌来。我们能做什么?(当你在一个有 Dropbox 这种规模,尤其是这种桌面客户端的规模的公司工作时,会遇到这种有趣的事情:你可以非常轻易地对自己造成 DDoS 攻击)。

当你部署的新版本发生问题时,第一个选项是回滚。这是非常合理的选择,但对于这个问题,它无法帮助我们。我们改变的不是服务器的状态而是客户端的——我们删除了那些出错文件。将服务器回滚可以防止更多客户端进入这种状态,但它并不能解决根本问题。

那扩大日志集群的规模呢?我们试过了——然后因为处理能力增加了,我们开始收到更多的请求。我们又扩大了一次,但你不可能一直这么下去。为什么不能?因为这个集群并不是独立的。它会向另一个集群发送请求,在这里是为了处理异常。如果你的一个集群正在被 DDoS,而你持续扩大那个集群,你最终会把它依赖的集群也弄坏,然后你就有两个问题了。

我们考虑过的另一个选择是减低负载——你不需要每一个日志文件,所以我们可以直接无视一些请求。一个难点是我们并没有一个很好的方法来区分好的请求和坏的请求。我们无法快速地判断哪些日志文件是旧的,哪些是新的。

我们最终使用的是一个 Dropbox 里许多不同场合都用过的一个解决方法:我们有一个自定义的头字段,chillout,全世界所有的客户端都遵守它。如果客户端收到一个有这个头字段的响应,它将在字段所标注的时间内不再发送任何请求。很早以前一个英明的程序员把它加到了 Dropbox 客户端里,在之后这些年中它已经不止一次地起了作用。

了解你的系统

这个 bug 的第一个教训是要了解你的系统。我对于客户端和服务器之间的交互有不错的理解,但我并没有考虑到当服务器和所有这些客户端同时交互的时候会发生什么。这是一个我没有完全搞懂的层面。

了解你的工具

第二个教训是要了解你的工具。如果出了差错,你有哪些选项?你能撤销你做的迁移吗?你如何知道事情出了差错,你又如何发现更多信息?所有这些事情都应该在危机发生之前就了解好——但如果你没有,你会在危机发生时学到它们并不会再忘记。

功能开关 & 服务器端功能控制

第三个教训是专门针对移动端和桌面应用开发者的:你需要服务器端功能控制和功能开关。当你发现一个问题时如果你没有服务器端的功能控制,你可能需要几天或几星期来推送新版本或者提交新版本到应用商店中,然后问题才能得到解决。这是个很糟糕的处境。Dropbox 桌面客户端不需要经过应用商店的审查过程,但光是把一个版本推送给上千万的用户就已经要花很多时间。相比之下,如果你能在新功能遇到问题的时候在服务器上翻转一个开关:十分钟之后你的问题就已经解决了。

这个策略也有它的代价。加入很多的功能开关会大幅提高你的代码的复杂度。而你的测试代码更是会成指数地复杂化:要考虑 A 功能和 B 功能都开启,或者仅开启一个,或者都不开启的情况——然后每个功能都要相乘一遍。让工程师们在事后清理他们的功能开关是一件很难的事情(我自己也有这个毛病)。另外,桌面客户端会同时有好几个版本有人使用,也会加大思考难度。

但是它的好处——啊,当你需要它的时候,你真的是很需要它。

如何去爱 bug

我讲了几个我爱的 bug,也讲了为什么要爱 bug。现在我想告诉你如何去爱 bug。如果你现在还不爱 bug,我知道唯一一种改变的方法,那就是要有成长型心态。

社会学家 Carol Dweck 做了很多关于人们如何看待智力的研究。她找到两种不同的看待智力的心态。第一种,她叫做固定型心态,认为智力是一个固定的特征,人类无法改变自己智力的多寡。另一种心态叫做成长型心态。在成长型心态下,人们相信智力是可变的而且可以通过努力来增强。

Dweck 发现一个人看待智力的方式——固定型还是成长型心态——可以很大程度地影响他们选择任务的方式、面对挑战的反应、认知能力、甚至是他们的诚信度。

【我在新西兰 Kiwi Pycon 会议所做的主题演讲中也讨论过成长型心态,所以在此只摘录一部分内容。你可以在这里找到完整版的演讲稿】

关于诚信的发现:

在这之后,他们让学生们给笔友写信讲这个实验,信中说“我们在学校做了这个实验,这是我得的分数”。他们发现 因智力而受到表扬的学生中几乎一半人谎报了自己的分数 ,而因努力而受表扬的学生则几乎没有人不诚实。

关于努力:

数个研究发现有着固定型心态的人会不愿真正去努力,因为他们认为这意味着他们不擅长做他们正努力去做的这件事情。Dweck 写道,“如果每当一个任务需要努力的时候你就会怀疑自己的智力,那么你会很难对自己的能力保持自信。”

关于面对困惑:

他们发现有成长型心态的学生大约能理解 70% 的内容,不论里面是否有难懂的段落。在有固定型心态的学生中,那些被分配没有难懂段落的手册的学生同样可以理解大约 70%。但那些看到了难懂段落的持固定型心态的学生的记忆则降到了 30%。有着固定型心态的学生非常不擅长从困惑中恢复。

这些发现表明成长型心态对 debug 至关重要。我们必须从从困惑中重整旗鼓,诚实地面对我们理解上的不足,并时不时地在寻找答案的路上努力奋斗——成长型心态会让这些都变得更简单而且不那么痛苦。

热爱你的 bug

我在 Recurse Center 工作时会直白地欢迎挑战,我就是这样学会热爱我的 bug 的。有时参与者会坐到我身边说“唉,我觉得我遇到了个奇怪的 Python bug”,然后我会说“太棒了,我 奇怪的 Python bug!” 首先,这百分之百是真的,但更重要的是,我这样是在对参与者强调,找到让自己觉得困难的事情是一种成就,而他们做到了这一点,这是件好事。

像我之前说过的,在 Recurse Center 没有截止日期也没有作业,所以这种态度没有任何成本。我会说,“你现在可以花一整天去在 Flask 里找出这个奇怪的 bug 了,多令人兴奋啊!”在 Dropbox 和之后的 Pilot,我们有产品需要发布,有截止日期,还有用户,于是我并不总是对在奇怪的 bug 上花一整天而感到兴奋。所以我对有截止日期的现实也是感同身受。但是如果我有 bug 需要解决,我就必须得去解决它,而抱怨它的存在并不会帮助我之后更快地解决它。我觉得就算在截止日期临近的时候,你也依然可以保持这样的心态。

如果你热爱你的 bug,你可以在解决困难问题时获得更多乐趣。你可以担心得更少而更加专注,并且从中学到更多。最后,你可以和你的朋友和同事分享你的 bug,这将会同时帮助你自己和你的队友们。

鸣谢!

在此向给我的演讲提出反馈以及给我的演讲提供其他帮助的人士表示感谢:

  • Sasha Laundy
  • Amy Hanlon
  • Julia Evans
  • Julian Cooper
  • Raphael Passini Diniz 以及其他的 Python Brasil 组织团队成员

via: http://akaptur.com/blog/2017/11/12/love-your-bugs/

作者:Allison Kaptur 译者:yixunx 校对:wxy

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

Linux 上使用 Xfce 桌面环境或许是又快又灵活的 — 但是它目前在遭受着一个很严重的缺陷影响。

使用这个轻量级 GNOME 和 KDE 替代品 Xfce 桌面的用户报告说,其选用的默认壁纸会造成笔记本电脑显示器和液晶显示器的损坏!!!

有确凿的照片证据来支持此观点。

Xfce Bug #12117

“桌面默认开机画面造成显示器损坏!” 某用户在 Xfce 的 Bugzilla Bug 提交区尖叫道。

“默认桌面壁纸导致我的动物去抓它,从我的液晶显示器掉落下来塑料!能让我们选择不同的壁纸吗?我不想再有划痕,谁想呢?让我们结束这老鼠游戏吧。” (LCTT 译注:原文是 whu not,可能想打 who not,也许因屏幕坏了太激动打错字了)

缺陷 flaw — 或者说是这 爪爪 claw ? — 不是个别用户的桌面遇到问题。其他用户也重现了这个问题,尽管不太一样,在这第二个例子,是 红迪网友 Redditor 的不同图片证实的:

目前不知道这锅是 Xfce 的还是猫猫的。如果是后者就没希望修复了,就像便宜的 Android 手机商品(LCTT 译注:原文这里是用 cats 这个单词,是 catalogues 的缩写,一语双关“猫”。原文作者也是个猫奴,#TeamCat 成员)从来得不到他们的 OEM 厂商的升级。

值得庆幸的是 Xubuntu 用户们并没有受到这“爪爪”问题的影响。这是因为它这个基于 Xfce 的 Ubuntu 特色版带有自己的非老鼠的桌面壁纸。

对其他 Linux 发行版的 Xfce 用户来说,“爪爪们”显然对其桌面倒不是那么感兴趣。

已经有人已经提出了一个补丁修复这个问题,但是上游尚未接受。如果你们关注了 bug #12117 ,就可以在你们自己的系统上手动应用这个补丁,去下载以下图片并设置成桌面壁纸。


via: http://www.omgubuntu.co.uk/2017/03/xfce-wallpaper-cat-bug

作者:JOEY SNEDDON 译者:ddvio 校对:jasminepeng

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

之前,Ed 写了篇文章《软件透明度》,主旨是如果软件开发的过程是透明的,那么软件对恶意的后门(以及无心的安全漏洞)就更具抵抗性。

软件透明的因素包括公开源代码,可以阅读源代码或为一个项目反馈的问题做出贡献,以及参与内部开发讨论。他提到一种情况,在这儿我想详细讨论一下:在2008年,Debian项目(一个用于web服务器的很流行的linux发行版),宣称Debian中OpenSSL的伪随机数生成器遭到破解,已经不安全了。

首先,了解一些背景信息:伪随机数生成器(PRNG)就是一个程序,假定代号为F。给定一个随机种子s,则会得到一个看起来随机的长的二进制序列F(s)。如果我和你都使用同样的种子s,两个人会得到同样的二进制序列。但是如果我随机选择一个s,也不告诉你s是什么,你根本不能够推测F(s)的结果,如你所期望的,F(s)就是随机的。OpenSSL中的PRNG试图从系统中抓取不可预测的信息(称之为"熵"),比如当前进程ID,或者很有可能是不同的内存内容(比如,由其它一些进程控制或可能控制的未初始化的内存)等等。把这些东西转换成种子s,就会得到随机比特流F(s)。

2006年,为了解决一个用于查找软件内存存取bug的工具警告问题,一名Debian维护者决定注释掉OpenSSL PRNG里的两行代码。但是这两行代码非常重要,它们负责抓取几乎所有的不可预测的熵,以作为OpenSSL PRNG的种子。没有这些代码,PRNG只有总共32,767个选择可作为种子s,因而也只有这么多的F(s)供选择。

这样一来,很多依赖于OpenSSL随机数生成器的程序,其实并没有它们以为的那么多的随机选择。比如,一个这样的程序要为SSL(安全网络浏览)和SSH(安全远程登录)生成秘钥。严格来说,这些秘钥必须是随机的:如果你可以猜到我的秘钥,你就可以破解我使用该秘钥保护的任何东西。这意味着你有能力读取加密的通讯信息,登录到远程服务器,或者伪造看起来似乎是真实的信息。这个漏洞是2006年第一次引入,而且进入到Ubuntu中(另一个流行的linux发行版,广泛应用于网络服务器)。漏洞影响到数以千计的服务器而且存在了很长一段时间,因为只是给受影响的服务器打补丁还不足以解决问题,必须替换掉任何在漏洞存在情况下生成的秘钥。

顺便说一句,为伪随机数生成器寻找熵是个著名难题。事实上,在今天来看要解决这个问题依然是个巨大的挑战。随机错误难以检测,因为当你盯着输出看时,每次运行程序结果都不一样,就像随机的一样。弱随机性很难发现,但是它可以使(貌似)安全的加密系统失效。不过,Debian中的那个漏洞很醒目,被发现后在安全社区引起了很多嘲笑

于是有人问,这是个故意设置的后门吗?似乎不大可能。做出这个更改的代码维护者 Kurt Roeckx,后来成为Debian项目的主管。这意味着他是个可靠的家伙,不是为了插入漏洞而由NSA伪造出来的身份。想进入Debian项目组的核心,需要做出巨大的努力,那真是出了名的难进。这样看来,错误根本不是有意为之,而是一系列失误导致的,而且后果严重。

漏洞确实是在一个透明的环境下发生的。所做的任何一件事都是公开的。但是漏洞还是引入了,而且长时间未被注意到。部分原因在于,透明引起了很多混乱,导致本应发现这个显而易见的漏洞的人们也都没太在意。 另外,也因为漏洞本身太过微妙,一个随意的观察者很难发现修改带来的影响。

这是否意味着软件透明没什么帮助? 我可不这么认为。许多人都赞同透明软件要比不透明软件更安全。但是这也并不表示漏洞不会产生,或者认为有其他人都看着呢而我们自己就可以掉以轻心。

至少,多年以后,透明可以让我们回顾,究竟是什么导致了某个漏洞--本文例子中,就是工程上的纰漏,而非人为破坏。

via: https://freedom-to-tinker.com/blog/kroll/software-transparency-debian-openssl-bug/

译者:l3b2w1 校对:jasminepeng

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

  开源办公软件套装 LibreOffice 3.6.7 版发布,这个版本是 LibreOffice 3.6 系列的最后一个版本,所以称之为 3.6 最终版。

  这个版本主要修复了前一版的 Bug 。超过 50 个以上的 Bug 被修复,其中最大的 Bug 应该是在 Writer 中复选框的怪异问题和在某些版本的 Linux 中无法加载 LiberOffice 的问题。

  除了发布这个版本外,昨天,The Document Foundation 还邀请大家一起来查看 LibreOffice4.1 的新功能

  LivreOffice 下载地址:http://www.libreoffice.org/download/

https://img.linux.net.cn/data/attachment/album/201307/19/080928tebbz4od5ce7wg4v.jpg

已同步至 linux的微博