标明版本!所有程序都必须报告其版本
摘要
本文主张在所有软件程序中强制进行版本标记,以改进事件响应,并以i3窗口管理器的版本报告系统作为案例研究,同时涵盖了使用Go和NixOS的实现细节。
<p>最近,在一次生产事件响应中,我在不到一小时内正确猜到了宕机的根本原因(真棒!),并提交了一个修复方案来排除它,但随后却因为没有版本号和部署的可见性而花费了许多小时在黑暗中摸索……😞</p>
<p>这次经历让我再次思考软件版本管理,更具体地说是构建信息(构建版本、版本标记,随你怎么称呼)和版本报告。我意识到,对于i3窗口管理器,我在十多年前就已经很好地解决了这个问题,所以工作中这个问题显然没有得到解决,这真的出乎意料。</p>
<p>在本文中,我将解释三个简单的步骤(标记它!连接它!报告它!)如何足以为您在事件响应期间节省数小时的延误和压力。</p>
<h2 id="low-versioning-standards">为什么我们的版本管理标准如此之低?</h2>
<p>每件家用电器都有极其详细的版本信息!看这台洗碗机:</p>
<a href="https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/2026-04-04-feuermurmel-dishwasher-versioning.jpg"><img
srcset="https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/2026-04-04-feuermurmel-dishwasher-versioning_hu_1d046eb0df440b85.jpg 2x,https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/2026-04-04-feuermurmel-dishwasher-versioning_hu_1a09cac140bcb1d2.jpg 3x"
src="https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/2026-04-04-feuermurmel-dishwasher-versioning_hu_9dd1db4e61dd3ec0.jpg"
alt="一台洗碗机,带有许多精确的版本信息" title="一台洗碗机,带有许多精确的版本信息"
width="600"
height="450"
style="
border: 1px solid #000;
"
loading="lazy"></a>
<p><em>(感谢Feuermurmel给我这个可爱的例子!)</em></p>
<p>我观察过几次家用电器维修,印象是如果维修人员无法识别电器,他们很可能甚至不愿意碰它。</p>
<p>那么,为什么我们在计算机领域的标准如此之低呢?当然,消费产品通常多少会有版本号,而且通常足够好(除了像USB 3.2 Gen 1×2这样的!)。但最近,我遇到了太多开发者构建版本没有充分版本化的问题!</p>
<h2 id="software-versioning">软件版本管理</h2>
<p>与带有金属铭牌的家用电器不同,软件不断更新,并运行在我们通常看不见的地方和结构中。</p>
<p>让我们深入研究一下我们需要什么来提高版本管理标准!</p>
<p>通常,软件有一个<strong>名称</strong>和一些不同粒度的<strong>版本号</strong>:</p>
<ul>
<li>Chrome</li>
<li>Chrome 146</li>
<li>Chrome 146.0.7680.80</li>
<li>Chrome f08938029c887ea624da7a1717059788ed95034d-refs/branch-heads/7680_65@{#34}</li>
</ul>
<p>所有这些都标识了我电脑上的Chrome浏览器,但粒度不同。</p>
<p>根据上下文,所有都是正确且有用的。以下每个示例:</p>
<ol>
<li>“这个在我这边Chrome上能用,你测试过Firefox吗?”</li>
<li>“Chrome 146包含损坏的中键点击粘贴和导航功能”</li>
<li>“我运行的是Chrome 146.0.7680.80,无法重现你的问题”</li>
<li>“在Chrome f08938029c887ea624da7a1717059788ed95034d-refs/branch-heads/7680_65@{#34}之上应用此补丁,然后按照以下步骤重现:[…]”</li>
</ol>
<p>在创建<a href="https://i3wm.org">i3窗口管理器</a>之后,我很快就了解到,对于用户支持,程序能够清晰地标识自身非常有价值。让我用下面的案例研究来说明。</p>
<h2 id="i3-moreversion">案例研究:i3的<code>--version</code>和<code>--moreversion</code></h2>
<p>当运行<code>i3 --version</code>时,您将看到如下输出:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>% i3 --version
</span></span><span style="display:flex;"><span>i3 version 4.24 (2024-11-06) © 2009 Michael Stapelberg and contributors
</span></span></code></pre></div><p>每一个词都是经过深思熟虑并有目的地放置的。让我剖析一下:</p>
<ol>
<li><code>i3 version 4.24</code>:我本可以缩短为<code>i3 4.24</code>或<code>i3 v4.24</code>,但我认为明确表达会很有帮助,因为<code>i3</code>这个名字很短。用户可能会喃喃自语“什么是i-3-4-2-4?”,但当在其中加入“version”时,含义就是i3是一个计算机的东西(→一个计算机程序),存在版本4.24。</li>
<li><code>(2024-11-06)</code>是发布日期,这样您可以立即判断“<code>4.24</code>”是否近期。</li>
<li><code>© 2009 Michael Stapelberg</code>表明项目何时开始以及谁是主要负责人。</li>
<li><code>and contributors</code>感谢许多帮助过的人。i3从来不是一个单人项目;它一直是一个团队努力的结果。</li>
</ol>
<p>在进行用户支持时,有一些问题在概念上很容易向受影响的用户提出,并能产生对开发者非常有价值的答案:</p>
<ol>
<li>问题:“您使用的是哪个版本的i3?”
<ul>
<li>由于i3不是典型的在窗口中运行的程序(而是一个窗口管理器/桌面环境),因此没有“帮助”→“关于”菜单选项。</li>
<li>相反,我们开始问:“<code>i3 --version</code>的输出是什么?”</li>
</ul>
</li>
<li>问题:“<em>您报告的是一个新问题还是已有问题?为了确认,您能否尝试回退到之前使用的i3版本?</em>”。“回退”的技术术语是降级、回滚或还原。
<ul>
<li>根据Linux发行版的不同,这要么很简单,要么是场噩梦。</li>
<li>使用NixOS,这很简单:你只需通过在选择引导加载程序中的版本,启动到较旧的系统“生成”。或者如果您的配置有版本控制,在git中还原。</li>
<li>对于像Debian Linux或Arch Linux这样的命令式Linux发行版,如果您没有做文件系统级别的快照,那么在升级系统后没有简单可靠的方法可以回退。如果幸运的话,您只需<code>apt install</code>旧版本的i3。但您可能会遇到依赖冲突(“版本地狱”)。</li>
<li>我知道使用<a href="https://snapshot.debian.org/">snapshot.debian.org</a>运行旧版本Debian是<em>可能的</em>,但至少在我上次尝试时,它不太实用。</li>
</ul>
</li>
<li>您能检查问题是否仍然存在于最新的i3开发版本中吗?
<ul>
<li>当然,我也可以尝试用最新的发布版本来重现用户的问题,<strong>然后</strong>在最新的开发版本上<strong>再试一次</strong>。</li>
<li>但这样,验证步骤就转移到了受影响的用户,这很好,因为它可以筛选出高度积极的bug报告者(bug报告更有可能导致修复!),并且让用户<em>两次</em>重现bug,从而判断它是否是一个不稳定的问题、难以重现、重现步骤是否正确等。</li>
<li>一个自然的后续问题:“<em>这个代码变更能让问题消失吗?</em>”现在有了开发环境的受影响用户很容易测试。</li>
</ul>
</li>
</ol>
<p>根据多次提出这些问题的经验,我注意到这些调试会话的一些模式。作为回应,我在i3 v4.3(2012年9月发布)中引入了另一种方式让i3报告其版本:一个<code>--moreversion</code>标志!现在我可以问用户第一个问题的一个小变体:“</p>
查看缓存全文
缓存时间: 2026/05/16 03:31
# 盖章!所有程序必须报告其版本
来源:https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/
目录
- [为什么我们的版本号标准如此之低?](#低版本号标准)
- [软件版本号](#软件版本号)
- [案例研究:i3 的 `--version` 和 `--moreversion`](#i3-更多版本信息)
- 开发者构建版本
- 最有用的:嵌入版本控制系统修订版本
- Go 总是嵌入版本号!🥳
- Go 版本报告
- 在 NixOS 下嵌入 VCS 修订版本
- Nix Go 构建的详细情况
- 我的解决方式:Nix git buildinfo overlay
- 干净利落的修复
- 结论:盖章!打通!报告!
最近,在一次生产事故响应中,我在不到一小时内正确猜出了故障的根本原因(酷!),并提交了一个修复方案来排除它,结果却因为缺乏版本号和回滚的可见性而花了很多小时在黑暗中摸索……😞 这个经历让我重新思考软件版本号,更具体地说,是构建信息(构建版本、版本盖章,随你怎么叫)和版本报告。我意识到,对于 i3 窗口管理器,我在十多年前就已经解决了这个问题,所以工作中这个问题显然没有得到解决,这真的出乎意料。在本文中,我将解释三个简单的步骤(盖章它!打通它!报告它!)如何足以在事故响应期间为你节省数小时的延迟和压力。
## 为什么我们的版本号标准如此之低?
每个家用电器都有极其详细的版本信息!看看这台洗碗机:
[一台带有精确版本信息的洗碗机](https://michael.stapelberg.ch/posts/2026-04-05-stamp-it-all-programs-must-report-their-version/2026-04-04-feuermurmel-dishwasher-versioning.jpg)
*(感谢 Feuermurmel 给我发送这个可爱的例子!)*
我观察过几次家用电器维修,给我的印象是,如果维修人员无法识别电器,他们很可能根本不会碰它。那么为什么我们在计算机领域的标准这么低呢?当然,消费产品通常都会以某种方式进行版本号标记,而且通常已经足够好了(USB 3.2 Gen 1×2 这种除外)。但最近,我遇到了太多开发者构建版本,它们都没有得到适当的版本号标记!
## 软件版本号
与带有冲压金属板的物理家用电器不同,软件不断更新,并在我们通常无法看到的地方和结构中运行。让我们深入探讨我们需要什么来提高版本号标准吧!
通常,软件有一个**名称**和一些不同粒度的**版本号**:
- Chrome
- Chrome 146
- Chrome 146.0.7680.80
- Chrome f08938029c887ea624da7a1717059788ed95034d-refs/branch-heads/7680_65@{\#34}
所有这些都标识了我电脑上的 Chrome 浏览器,但粒度和信息量不同。它们都是正确且有意义的,具体取决于场景。以下是对每个例子的一种用法:
1. “这个功能在 Chrome 上对我有用,你在 Firefox 上测试了吗?”
2. “Chrome 146 存在中键点击粘贴并导航的 bug”
3. “我运行的是 Chrome 146.0.7680.80,并且无法复现你的问题”
4. “在此 Chrome 版本 f08938029c887ea624da7a1717059788ed95034d-refs/branch-heads/7680_65@{\#34} 之上打上这个补丁,然后按照以下步骤复现:\[...\]”
在创建了 [i3 窗口管理器](https://i3wm.org/) 之后,我很快了解到,对于用户支持来说,程序清晰地标识自身是非常有价值的。让我通过以下案例研究来说明。
## 案例研究:i3 的 `--version` 和 `--moreversion`
运行 `i3 --version` 时,你会看到类似这样的输出:
```
% i3 --version
i3 version 4.24 (2024-11-06) © 2009 Michael Stapelberg and contributors
```
每个词都是经过仔细斟酌和安排的。让我来剖析一下:
1. `i3 version 4.24`:我本可以缩短为 `i3 4.24` 或 `i3 v4.24`,但我认为明确说出来会有帮助,因为 `i3` 这个名字太短了。用户可能会喃喃自语“什么是 i-3-4-2-4?”,而放上“version”一词,就暗示了 i3 是某种计算机事物(→ 一个计算机程序),并且存在 4.24 这个版本。
2. `(2024-11-06)` 是发布日期,这样你就能立即判断“`4.24`”是否是新近的。
3. `© 2009 Michael Stapelberg` 标志着项目何时开始以及谁是其背后的主要人物。
4. `and contributors` 则对许多帮助过的人给予了认可。i3 从来不是一个单人项目;它始终是一个团队的努力。
在进行用户支持时,有几个问题在概念上很容易询问受影响的用户,并为开发者产生非常有价值的答案:
1. 问题:“你正在使用哪个版本的 i3?”—— 由于 i3 不是一个典型的在窗口中运行的程序(而是一个窗口管理器/桌面环境),因此没有“帮助 → 关于”菜单选项。
- 相反,我们开始问:`i3 --version` 的输出是什么?
2. 问题:“*你是在报告一个新问题还是一个已有问题?为了确认,你能尝试回到你之前使用的 i3 版本吗?*”。“回去”的技术术语是降级、回滚或还原。
- 取决于 Linux 发行版,这要么是微不足道的,要么是噩梦。
- 对于 NixOS 来说,这很简单:你只需在引导加载程序中选择一个较旧的系统“世代”来引导即可。或者如果配置文件是版本控制的,你可以在 git 中还原。
- 对于像 Debian Linux 或 Arch Linux 这样的命令式 Linux 发行版,如果你没有对文件系统进行快照,那么在系统升级后就没有简单且可靠的方法回去了。如果你幸运的话,你可能只需 `apt install` 旧版本的 i3。但你也可能遇到依赖冲突(“版本地狱”)。
- 我知道使用 [snapshot.debian.org](https://snapshot.debian.org/) 可以*运行*旧版本的 Debian,但至少在我上次尝试时,它并不太实用。
3. 你能检查一下这个问题在最新的 i3 开发版本中是否仍然存在吗?
- 当然,我也可以尝试用最新的发布版本复现用户的问题,**然后再额外一次**用最新的开发版本复现。
- 但这样一来,验证步骤就转移到了受影响的用户身上,这很好,因为这样能筛选出高度积极的 bug 报告者(bug 报告实际被修复的可能性更高!),并且让用户自己复现 bug *两次*,从而判断这是一个不稳定的问题、难以复现、复现说明是否正确等等。
- 一个自然的后续问题是:“*这个代码更改能让问题消失吗?*” 对于现在有了开发环境的受影响用户来说,这很容易测试。
根据我多次问这些问题的经验,我注意到了这些调试会话过程中的一些模式。作为回应,我在 i3 v4.3(2012 年 9 月发布)中引入了另一种让 i3 报告其版本的方式:`--moreversion` 标志!现在我可以问用户第一个问题的微小变体:`i3 --moreversion` 的输出是什么?
注意这句话在口头交流中也很容易传递,比如在计算机聚会上:
> **Michael:** 你用的是哪个版本?
> **用户:** 怎么查?
> **Michael:** 运行这个命令:`i3 --version`
> **用户:** 显示 4.24。
> **Michael:** 很好,这个版本足够新,包含了那个 bug 修复。现在,我们需要更多版本信息!请运行 `i3 --moreversion` 并告诉我你看到了什么。
当你运行 `i3 --moreversion` 时,它不仅仅报告你调用的 i3 程序的版本,它还会通过 i3 的 IPC(进程间通信)接口连接到正在运行的 i3 窗口管理器进程,并报告正在运行的 i3 进程的版本,以及其它对用户有帮助的关键细节,比如加载了哪个配置文件以及它上次更改的时间:
```
% i3 --moreversion
Binary i3 version: 4.24 (2024-11-06) © 2009 Michael Stapelberg and...
Running i3 version: 4.24 (2024-11-06) (pid 2521)
Loaded i3 config: /home/michael/.config/i3/config (main) (last modified: 2026-03-15T23:09:27 CET, 1101585 seconds ago)
The i3 binary you just called: /nix/store/0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24/bin/i3
The i3 binary you are running: i3
```
这第一眼看上去可能有很多细节,但让我解释一下为什么这个输出是这么有价值的调试工具:
1. 通过 IPC 接口连接到 i3 本身就是一个有趣的测试。如果用户能看到 `i3 --moreversion` 的输出,那就意味着他们也将能够运行调试命令,比如 `i3-msg -t get_tree > /tmp/tree.json` 来捕获完整的布局状态。
2. 在调试会话期间,运行 `i3 --moreversion` 是一个简单的检查,可以查看你刚刚构建的版本是否真的生效(参见 `Running i3 version` 这一行)。
- 请注意,这也是在生产事故期间相关的检查:验证*实际运行*的版本是否与*应该运行*的版本一致。
3. 显示已加载配置文件的完整路径会使用户清楚他们是否编辑了错误的文件。如果路径本身不够充分,修改时间(同时显示绝对时间和相对时间)将会标记出编辑了错误的文件。
顺便说一句,我用 NixOS,所以我自动获得了一个稳定的标识符 (`0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24`) 来表示*i3 的特定构建版本*。
```
% ls -l $(which i3)
lrwxrwxrwx 1 root root 58 1970-01-01 01:00 /run/current-system/sw/bin/i3 -> /nix/store/0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24/bin/i3
```
要查看产生此 Nix 存储输出(`0zn9r4263...-i3-4.24`)的构建配方(Nix 术语中的“派生式”),我可以运行 `nix derivation show`:
```
% nix derivation show /nix/store/0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24
{
"/nix/store/z7ly4kvgixf29rlz01ji4nywbajfifk4-i3-4.24.drv": {
[...]
```
如果你好奇,点击展开完整的 `nix derivation show` 输出
```
% nix derivation show /nix/store/0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24
{
"/nix/store/z7ly4kvgixf29rlz01ji4nywbajfifk4-i3-4.24.drv": {
"args": [
"-e",
"/nix/store/l622p70vy8k5sh7y5wizi5f2mic6ynpg-source-stdenv.sh",
"/nix/store/shkw4qm9qcw5sc5n1k5jznc83ny02r39-default-builder.sh"
],
"builder": "/nix/store/6ph0zypyfc09fw6hlc1ygjvk2hv4j9vd-bash-5.3p3/bin/bash",
"env": {
"NIX_MAIN_PROGRAM": "i3",
"__structuredAttrs": "",
"buildInputs": "/nix/store/58q0dn2lbm2p04qmds0aymwdd1fr5j67-libxcb-1.17.0-dev /nix/store/3fcfw014z5i05ay1ag0hfr6p81mb1kzw-libxcb-keysyms-0.4.1-dev /nix/store/2cdrqvd3av1dmxna9xjqv1jccibpvg6m-libxcb-util-0.4.1-dev /nix/store/256alp82fhdgbxx475dp7mk8m29y53rh-libxcb-wm-0.4.2-dev /nix/store/nr44nfhj48abr3s6afqy1fjq4qmr23lz-xcb-util-xrm-1.3 /nix/store/ml4cfhhw6af6qq6g3dn7g5j5alrnii88-libxkbcommon-1.11.0-dev /nix/store/6hnzjg09fd5xkkrdj437wyaj952nlg45-libstartup-notification-0.12 /nix/store/9m0938zahq7kcfzzix4kkpm8d1iz3nmq-libx11-1.8.12-dev /nix/store/vz5gd0rv0m2kjca50gacz0zq9qh7i8xf-pcre2-10.46-dev /nix/store/334cvqpqc9f0plv0aks71g352w6hai0c-libev-4.33 /nix/store/6s3fw10c0441wv53bybjg50fh8ag1561-yajl-2.1.0-unstable-2024-02-01 /nix/store/d6aw2004h90dwlsfcsygzzj4pzm1s31a-libxcb-cursor-0.1.6-dev /nix/store/84mhqfj9amzyvxhp37yh3b0zd8sq0a7p-perl-5.40.0 /nix/store/l6bslkrp59gaknypf1jrs5vbb2xmcwym-pango-1.57.0-dev /nix/store/7s7by82nq8bahsh195qr0mnn9ac8ljmm-perl5.40.0-AnyEvent-I3-0.19 /nix/store/9ml0p4x1cx5k1lla91bxgramc0amsfkf-perl5.40.0-X11-XCB-0.20 /nix/store/67j1sx7qcn6f7qvq1kh3z8i5mpajgq3r-perl5.40.0-IPC-Run-20231003.0 /nix/store/859x84mz38bcq0r7hwksk4b5apcsmf2w-perl5.40.0-ExtUtils-PkgConfig-1.16 /nix/store/q1qydg6frfpq9jkhnymfsjzf71x9jswr-perl5.40.0-Inline-C-0.82",
"builder": "/nix/store/6ph0zypyfc09fw6hlc1ygjvk2hv4j9vd-bash-5.3p3/bin/bash",
"checkPhase": "runHook preCheck\n\ntest_failed=\n# \"| cat\" disables fancy progress reporting which makes the log unreadable.\n./complete-run.pl -p 1 --keep-xserver-output | cat || test_failed=\"complete-run.pl returned $?\"\nif [ -z \"$test_failed\" ]; then\n # Apparently some old versions of `complete-run.pl` did not return a\n # proper exit code, so check the log for signs of errors too.\n grep -q '^not ok' latest/complete-run.log && test_failed=\"test log contains errors\" ||:\nfi\nif [ -n \"$test_failed\" ]; then\n echo \"***** Error: $test_failed\"\n echo \"===== Test log =====\"\n cat latest/complete-run.log\n echo \"===== End of test log =====\"\n false\nfi\n\nrunHook postCheck\n",
"cmakeFlags": "",
"configureFlags": "",
"debug": "/nix/store/20rgxn6fpywd229vka9dnjiaprypxirh-i3-4.24-debug",
"depsBuildBuild": "",
"depsBuildBuildPropagated": "",
"depsBuildTarget": "",
"depsBuildTargetPropagated": "",
"depsHostHost": "",
"depsHostHostPropagated": "",
"depsTargetTarget": "",
"depsTargetTargetPropagated": "",
"doCheck": "1",
"doInstallCheck": "",
"mesonFlags": "-Ddocs=true -Dmans=true",
"name": "i3-4.24",
"nativeBuildInputs": "/nix/store/x06h0jfzv99c3dmb8pj8wbmy0v9wj6bd-pkg-config-wrapper-0.29.2 /nix/store/pcdnznc797nmf9svii18k3c5v22sqihs-make-shell-wrapper-hook /nix/store/nzg469dkg5dj7lv4p50pi8zmwzxx73hr-meson-1.9.1 /nix/store/rlcn0x0j22nbhhf8wfp8cwfxgh65l82r-ninja-1.13.1 /nix/store/hs4pgi40k5nbl0fpf0jx8i5f6zrdv63v-install-shell-files /nix/store/84mhqfj9amzyvxhp37yh3b0zd8sq0a7p-perl-5.40.0 /nix/store/xiqlw1h0i6a6v59skrg9a7rg3qpanqy7-asciidoc-10.2.1 /nix/store/300facd5m37fwqrypjcikn09vqs488zv-xmlto-0.0.29 /nix/store/yk7avh2szvm6bi5dwgzz4c2iciaipj2p-docbook-xml-4.5 /nix/store/d5qdxn0rjl9s7xfc1rca33gya0fhcvkm-docbook-xsl-nons-1.79.2 /nix/store/2y1r1cpza3lpk7v6y9mf75ak0pswilwi-find-xml-catalogs-hook /nix/store/r989dk196nl9frhnfsa1lb7knhbyjxw6-separate-debug-info.sh /nix/store/xlhipdkyqksxvp73cznnij5q6ilbbqd9-xorg-server-21.1.21-dev /nix/store/i8nxxmw5rzhxlx3n12s3lvplwwap6mpc-xvfb-run-1+g87f6705 /nix/store/a198i9cnhn6y5cajkdxg0hhcrmalazjr-xdotool-3.20211022.1 /nix/store/b4dnjyq2i4kjg8xswkjd7lwfcdps94j8-setxkbmap-1.3.4 /nix/store/cxdbw6iqj1a1r69wb55xl5nwi7abfllb-xrandr-1.5.3 /nix/store/5k4mv2a1qrciv12wywlkgpslc6swyv58-which-2.23",
"out": "/nix/store/0zn9r4263fjpqah6vdzlalfn0ahp8xc2-i3-4.24",
"outputs": "out debug",
"patches": "",
"pname": "i3",
"postInstall": "wrapProgram \"$out/bin/i3-save-tree\" --prefix PERL5LIB \":\" \"$PERL5LIB\"\nfor program in $out/bin/i3-sensible-*; do\n sed -i 's/which/command -v/' $program\ndone\n\ninstallManPage man/*.1\n",
"postPatch": "patchShebangs .\n\n# This testcase generates a Perl executable file with a shebang, and\n# patchShebangs can't replace a shebang in the middle of a file.\nif [ -f testcases/t/318-i3-dmenu-desktop.t ]; then\n substituteInPlace testcases/t/318-i3-dmenu-desktop.t \\\n --replace-fail \"#!/usr/bin/
相似文章
Linux漏洞、禁运失效与补丁窗口缩短
一份关于2026年5月发现的三个严重Linux本地权限提升漏洞的报告,强调了披露模型的崩溃及其对生产环境的影响。
包管理器中的补丁与分支策略
本文探讨了在上游维护者未能解决漏洞时,针对不同语言包管理器修补和分支依赖项的策略。文章对比了系统包管理器强大的修补能力与语言注册表的局限性,并详细介绍了在各种生态系统中使用 Git 覆盖和分支等变通方法。
无法预防这种情况,唯一频繁发生此类事件的包管理器如此表示
讽刺文章指出npm注册表中反复出现的供应链攻击,与Go和Rust等更安全的生态系统形成对比,并嘲笑JavaScript社区对这种漏洞的接受态度。
Debian 必须提供可复现的软件包
讨论 Debian 分发可复现软件包的要求,以确保构建的一致性和安全性。
我的软件北极星
作者提出了一套软件开发的优先级列表:对最终用户的有用性、正确性、可维护性和效率,认为所有工作都应致力于最大化用户效用。