撰写有效的 Bug 报告
作者:Tom Jones

几年前,我们深受敬重的前 FreeBSD 期刊编辑委员会成员 Kristof Provost 写过一篇关于理想 Bug 报告方式的好文章。遗憾的是,Michael W Lucas 总会在年初就用光我们每期讽刺的额度,所以为了避免“讽刺透支”,决定由我改写 Kristof 的原文,以免出现“反讽破产”。
每个系统维护者都有自己偏好的 Bug 报告与改进请求接收方式。由于 Kristof 是 FreeBSD 中 pf 开发的核心人物,他正是为期刊撰写这篇文章的理想人选。
在被要求改写原文时,Kristof 的回应是:
“我无法在完美的基础上再做改进。”
因此,我来重述 Kristof 的原话,并给你一些入门建议,帮助你更快整理出最重要、最棘手的 Bug。你可以在这里找到他的博文:https://www.sigsegv.be/blog/2014/Mar#bug_reports。
Bug
软件项目常常让人觉得就是由 Bug 堆砌而成;开发者会说一切都是鞋油和胶带粘起来的。造成最大麻烦的问题往往最难捉摸。“深夜,当 12 个并发请求同时打到我们的测地负载均衡器上时……”并不是复杂 Bug 的罕见开头。有时问题的描述甚至是“运行 1000 小时之后……”这种令人头疼的情况。
幸运的是,并非所有 Bug 都如此。FreeBSD 在许多情况下会 panic,对用户而言可能是糟糕的一天,但对开发者而言,panic 消息可能是定位问题的重要线索。和无声的数据损坏相比,我宁愿碰到 panic。
有些 Bug 只是表面问题,比如字段显示不佳,或文档不清晰(是的,我们也认为这算 Bug!)。
无论你的 Bug 是逻辑上的不可能,还是拼写错误,我会给你展示一个框架,帮助你推动修复。
Bug 生命周期
在介绍如何写好 Bug 报告之前,先说说之后会发生什么,因为这能解释为什么你需要在最初报告时尽可能多提供信息。
在 FreeBSD 中,大多数 Bug 会通过邮件列表或 Bug 跟踪系统(bugs.freebsd.org)传播。开发者会定期阅读邮件列表,但最能引起关注的方法还是在 Bug 跟踪系统上提交工单。
新创建的 Bug 会被标记为“new”,处于新 Bug 状态。这时它只是被用户提交,还没有通知到具体的项目领域。
Bugmeister 团队会检查新提交,将其从“new”状态重新分配,并尽量设置正确的分类。开发者可以选择订阅某些类别的 Bug。相关的项目邮件列表也会收到新 Bug 的通知。另外,还会定期发送“该组关注的 Bug”摘要邮件。
Bug 可能会被 Bugmeister 或其他 FreeBSD 项目成员分配给某个开发者。
某个开发者可能决定“接手” Bug,成为该问题的负责人。这通常意味着他决定修复这个 Bug 或分析它。
随后可能会有一些往返沟通,开发者会要求更多信息;如果一切顺利,开发者最终会创建代码审查(在 reviews.freebsd.org 上)。代码审查可能会在 Bug 中引用,也可能只是开发者向熟悉该子系统的同行寻求反馈。
如果需要测试以确认 Bug 是否解决,这会被特别指出。
最终,待代码审查与测试完成,修复就会被提交到 FreeBSD;提交消息通常会包含 Bug 的引用,并附加自动更新。有时修复 Bug 需要多个补丁。
修复提交后,你(用户)就能再次无 Bug 使用软件,前提是你运行的是 CURRENT 快照。许多修复会从 CURRENT 合并到 STABLE 分支(称为 MFC)。如果 Bug 被 MFC,修复就会出现在 STABLE 分支,并包含在下一个点版本中。
从报告问题到修复的过程可能很长;有的问题 20 分钟就能解决,有的问题可能需要数月甚至数年。我见过调试超过十年才关闭的 Bug。
解决问题所需的时间,很大程度上取决于你报告的时机。如果你在提交刚落地后就发现 Bug,很可能当天就能修复。其他 Bug 可能更晚才出现,或只出现在某些 FreeBSD 发行版本的环境中。
修复这些 Bug 的速度,主要取决于 Bug 报告的质量和围绕问题的持续讨论。接下来我们看看好的 Bug 报告该包含什么。
哪里提交 Bug 报告
FreeBSD 项目鼓励用户通过多种渠道分享使用体验。按优先顺序,新 Bug 或有趣 Bug 的报告渠道如下:
在 reviews.freebsd.org 上提交带有清晰测试的易于应用的变更
在 reviews.freebsd.org 上提交临时修补的解决方案
在 bugs.freebsd.org 上提交新的 Bug
直接给开发者发邮件(或其他形式的沟通)
在论坛上抱怨并推测原因
在 IRC、Matrix、Discord 或其他聊天渠道留言
在社交媒体上愤怒发帖,说 FreeBSD 是最差的
前两种方式假定了较高的技术水平。如果这对你来说太难,也没关系,我们依然欢迎 Bug 报告。
我们不要求每个人都能做高级开发,只希望每位报告者在每一步尽可能提供相关细节。
对于拼写错误,大多数用户可以立即提出修复建议,但修改文档需要使用开发者工具,我们并不要求每个人都做到。如果你能使用这些工具,创建审查比提交新 Bug 更好,因为最终的变更无论如何都需要审查。
更复杂的 Bug 也许能立即解决;有些复杂的 Bug 答案很简单。然而,另一些 Bug 很难诊断,在很长一段时间里,我们只能通过一些看似无关的失败来侧面推断。
如果你有任何质量的修复建议,最重要的是把你的建议公开发布。顺着列表往下找,直到找到合适的位置。
如何写好 Bug 报告
应包含的信息
好的 Bug 报告应该包含什么,已经有很多资料可供参考;FreeBSD 中软件的广度使得任何单一模板都很难套用。以下是一些经验法则,告诉你应该包含什么:
关于你环境的详细信息
你期望发生什么
实际发生了什么
期望与实际的差异
这一点并不总是显而易见
触发 Bug 的前因后果
时间因素有助于开发者调试问题。如果 Bug 在重启后立即出现,或只在运行 5 天后才出现,所需的调试策略是不同的
提供哪些资料
系统运行时会生成很多有助于调试的信息,你可能会被要求提供日志,例如:
dmesg的输出panic 消息的完整文本和堆栈跟踪
硬件问题时
pciconf -lv的输出syslog 输出
工具输出和错误信息
提供的资料宁多勿少;如果开发者不得不再来问你一次,可能会耽误至少一周。
环境信息
你需要在描述财富 500 强公司的 Anycast 负载均衡配置和只展示单条防火墙规则之间找到平衡。通常,报告中提供的环境信息少于能够提供的;工具与网络配置的组合有助于开发者理解 Bug。
那么,你的环境包括什么?
我们需要知道你使用的 FreeBSD 版本和有多少台主机。Bug 出现在 14 台和 15 台主机之间这一事实,往往比只知道是 14 台更有意义。
我们需要了解自定义和偏离常规的情况;如果你自己编译了 FreeBSD 或使用软件包,都应该说明。这两种方式我们都支持,但如果你运行的不是 release engineering 版本,那就需要考虑这一点。
如果你运行的不是 FreeBSD,而是 pfSense 或 HardenedBSD 这样的下游发行版,需要一并说明。这并不意味着 FreeBSD 开发者不会帮助你,但隐瞒这一点很可能会惹恼某些人。
这一点很重要,因为下游发行版会使用不同的编译标志、软件包构建 FreeBSD,并附带自己的调优。所有这些都可能导致 Bug 在一个平台上存在而在另一个平台上不存在。
我们真正需要的是你的实际环境,而不是理想化的版本或教程中的示例。
期望与实际
报告问题的另一个关键部分是描述你期望发生什么。有些软件无法做到你想要的,要么现在做不到(由于功能尚在开发),要么永远做不到(因为这根本不是 Bug!)。
ls 不会复制文件或播放视频,但 pfctl 应该能够清除规则状态计数器。请告诉我们你期望的输出和效果,以便我们复核你的所有断言。
提供工具的输出,描述你能测量的实际效果,并标出任何问题。
对你来说工具坏了是显而易见的。你提交的是 Bug,但作为分拣问题的开发者,在发现问题所在方面获得额外帮助至关重要。
许多 Bug 在文本报告中不容易看出,性能问题可能难以关联(也难以诊断和修复)。
请非常清楚说明发生了什么和哪里不正确。
触发 Bug 的过程
对于许多 Bug,触发 Bug 前的事件很重要。“做了 X 之后无法再做 Y” 是一份优秀的 Bug 报告——它暗示了一条通往开发者黄金(见下文)的道路。
“ls 在磁盘满了之后报告错误的文件大小” 能告诉我们很多信息,而 “ls 报告错误的文件大小” 则不能。
在 Bug 出现前后查看 dmesg 可能会有帮助;内核子系统会在那里报告错误和资源耗尽。在 dmesg 中,我们可以看到接口不断上下波动。
提供信息的方式
你提供的信息最好是文本形式。如果有错误消息,应该全部包含;有些软件在执行操作时总是会打印错误消息或奇怪的诊断信息。在 Bug 报告中,你应该尽量包含这些信息。
如果你遇到 panic,可能难以从某处复制粘贴文本。这种情况下,用手机拍照是一种可行的策略;但是,你应该尽量在文件大小和图像清晰度之间取得平衡。理想情况下,你应该拍照并尽可能准确抄录文字。
你的图片托管服务将来很可能会消失,但 FreeBSD Bug 跟踪系统中的文本字符串可以保存几十年。
优秀 Bug 报告的关键:复现步骤
一份优秀的 Bug 报告会包含上述大部分信息,但还会包含开发者黄金:复现用例。
对于简单问题,这可能只是命令调用;但对于某些问题,你可能需要编写协同工作的 shell 脚本。网络 Bug 的复现用例可能很难编写,但得益于 vnet jail,实际上只需一个 shell 脚本就可以做到(事实上,防火墙测试套件就是这样工作的)。
复现用例的目标是将问题的复现简化到最基本的组件。
主动协助
提交 Bug 后,这可能已经足以让开发者感兴趣。如果你能在提交后的 20 分钟内指出回归或新 Bug,很可能立刻引起开发者关注。大多数开发者在提交变更后会关注邮件列表和 src-commits 列表,正是为了捕捉这类报告。
如果你的 Bug 被搁置或过了一段时间才分配给团队,不要慌;这是相当常见的经历。你可以主动联系在相关领域或类似 Ports 上工作的开发者。只要保持礼貌;你在使用志愿者的时间。
开发者接手 Bug 后,可能会问你问题;时间久了,可能会问:“在最新快照上还会出现吗?”
他们可能会请你提供更多信息或测试补丁。某些只出现在特定硬件上的 Bug,如果没人验证,补丁可能会长时间搁置。
有些 Bug 确实很难搞清楚。如果开发者正在和你合作,欢迎提出你认为可能触发 Bug 的理论。有些 Bug 听起来像鬼故事,直到我们找到最终的修复方案。
祝你好运!
撰写并提交 Bug 报告是一件耗费精力的事,有时你会觉得自己的努力无人理睬。但 FreeBSD 是一项志愿者项目,开发者根据兴趣分配时间。我们拥有一群优秀的开发者,他们愿意追踪复杂而隐蔽的问题,但他们需要你的帮助与合作,收集足够的信息来复现和测试。
如果你遵循这里的建议,你会更顺利让 Bug 获得关注,并推动它们被修复。
Tom Jones,FreeBSD 提交者,对保持网络栈高性能充满兴趣。
最后更新于