【问题标题】:What is the `patchShebangs` command in Nix build expressions?Nix 构建表达式中的 `patchShebangs` 命令是什么?
【发布时间】:2021-07-17 17:21:17
【问题描述】:

在查看Nixpkgs repo 中的包时遇到patchShebangs 命令,并看到它在standard environment 的通用构建器的various phases 中使用,但不确定它的用途或为什么需要它首先。

【问题讨论】:

标签: shell nixpkgs


【解决方案1】:

简而言之:在 Nix 构建期间使用的 shell 脚本不能开箱即用,因为 Nix 会清除环境,因此解释器指令 (shebang) 在脚本的第一行确定用于评估的程序脚本正文,将找不到它。 patchShebangs 在 Nix 商店中查找解释器,并修改脚本 shebang。


0。简介

Nixpkgs manual在描述Nixpkgs standard environmentthe phases of the generic builder时间接提到patchShebangs,说明fixup phase在某一点上

将 shell 脚本的解释器路径重写为在PATH 中找到的路径。例如,/usr/bin/perl 将被重写为在PATH 中找到的/nix/store/some-perl/bin/perl->

请务必注意(解释为 @jonringer's comment),“patchShebangs 命令仅在您获取 $stdenv/setup 设置挂钩的情况下在构建期间可用" (更多内容见下文) "stdenv's (Nixpkgs standard environment's) 默认构建器提供(使用stdenv.mkDerivation 时默认得到这个),这就是为什么起点几乎所有 nix 表达式都是import <nixpkgs> {}, stdenv.mkDerivation,或类似的东西。"

1。 patchShebangs 定义在哪里

Nixpkgs repo 中的文件patch-shebangs.sh(也记录在6.7.4. patch-shebangs.sh)定义了patchShebangs function,而patchShebangs function 又用于实现patchShebangsAutosetup hook 在@ 期间是registered to run 987654336@.

2。为什么在构建 Nix 包时需要 shebang 重写?

根据patch-shebangs.sh顶部的评论:

# This setup hook causes the fixup phase to rewrite all script
# interpreter file names (`#!  /path') to paths found in $PATH.  E.g.,
# /bin/sh will be rewritten to /nix/store/<hash>-some-bash/bin/sh.
# /usr/bin/env gets special treatment so that ".../bin/env python" is
# rewritten to /nix/store/<hash>/bin/python.  Interpreters that are
# already in the store are left untouched.
# A script file must be marked as executable, otherwise it will not be
# considered.

重要提示:上述“脚本文件必须标记为可执行文件,否则将不被视为”的标准是重要的。

shell 脚本中以#! 开头的行称为shebang(以及其他),它是执行shell 的解释器指令,用于解释使用什么程序来破译下面的文本; #! has to consitute an absolute path that points to this executable 之后的字符。例如,#!/usr/bin/python3 将期望在那里找到python3 程序来执行用 Python 编程语言编写的 shell 脚本主体中的命令。

在包构建阶段使用 shell 脚本会出现问题,因为

当 Nix 运行 builder, 时,它最初会完全清除环境(派生中声明的属性除外)。例如,PATH 变量为空。这样做是为了防止在构建过程中使用未声明的输入。例如,如果 PATH 包含 /usr/bin,那么您可能会不小心使用 /usr/bin/gcc->

上面的引用是from the Nix manual,但作为示例显示的构建器使用$stdenv/setup - 一个为构建过程设置原始沙箱环境的shell脚本,取消设置大多数(全部?)环境变量来自调用 shell 和 only including a small number of utilities。 (这样做是为了尽可能使构建可重现。)1

stdenv.mkDerivationthe generic builder 一起使用时通常会隐式调用$stdenv/setup(即,当builder 属性未声明时)但one can write their own builders and invoke it explicitly during the build process

提示:This answer 显示了一种查找特定 Nix 函数定义位置的方法(尽管 it is not infallible)。

作为推论,shebang 指令指向的程序不会在这些位置(或无法从沙盒访问),但它们实际上在(或将在)Nix store 中,因此路径将需要重新指向他们在那里的位置。

注意:generic builder 从派生的 输入 填充 PATH,因此必须确保将这些作为依赖项包含在内。

3。如何使用

3.1 隐式

如上所述,每当构建包时,patchShebangsAuto setup hookfixup phase 期间自动调用patchShebangs - 除非通过设置dontPatchShebangs variable(或dontFixup变量)(参见Nixpkgs manual 中的Variables controlling the fixup phase)。

提醒自己:6.4 Bash Conditional Expressions.

3.1.0 patchShebangs 在自动调用时使用什么脚本?

通常在包安装的脚本上(例如$out/bin)。

还是 Nixpkgs 标准库默认提供的?我认为这些必须足够通用才能在不同的平台上运行,以便 (1) 构建模板,以及 (2) 最后修补脚本 shebangs。 (@jtojnar confirmed this conjecture,但是这部分需要参考,因此是小案例。)

3.1.1 如何使用控制构建阶段的变量?

将它传递给mkDerivation,就像控制构建器的任何其他变量一样。

stdenv.mkDerivation {
  #...
  dontPatchShebangs = true;
  #...
}

3.2 明确

历史记录:最初,patchShebangs 不能在外部调用,但it was later extracted 使其功能也可在其他build phases 中重复使用。

再次,来自the implementation 中的 cmets:

# Run patch shebangs on a directory or file.
# Can take multiple paths as arguments.
# patchShebangs [--build | --host] PATH...

# Flags:
# --build : Lookup commands available at build-time
# --host  : Lookup commands available at runtime

# Example use cases,
# $ patchShebangs --host /nix/store/...-hello-1.0/bin
# $ patchShebangs --build configure

它需要在构建期间直接执行的脚本(包括 shell 脚本)上运行。这些可能是

  1. 来自被打包内容的来源
  2. 由一个人编写,在构建过程中用作助手2

来自网络的具体例子:


脚注

[1]:待办事项:详细了解沙盒的准确构建方式以及禁止和允许的内容。 Quoting @jtojnar举个例子:

/usr/bin/env,沙盒中也不可用。 (为方便起见,NixOS 仅在用户空间中提供了该功能,但 does not carry over to Nix sandbox.

[2]: @jtojnar's comment: "是的,你不需要显式地将它用于仅在运行时执行的脚本,因为它们将由隐式调用处理。"


此线程中的所有链接(希望)都已保存到Internet Archive。 (线程的配乐是this gem。)

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 2020-02-03
    • 2019-11-22
    • 2022-07-22
    • 1970-01-01
    • 2011-04-20
    • 2021-02-16
    • 1970-01-01
    相关资源
    最近更新 更多