如何仅用内置derivation函数实现类似mkShell的shellHook执行效果?
问题分析
你当前的配置无法触发shellHook,核心原因是:你使用的是Nix最底层的builtins.derivation函数,并且自定义了builder和args,完全绕过了nixpkgs中stdenv的初始化流程。而shellHook的自动执行逻辑是stdenv的setup.sh脚本内置的——只有当派生依赖stdenv构建时(比如用pkgs.stdenv.mkDerivation),shellHook才会在source $stdenv/setup后被调用。你的自定义构建脚本没有加载stdenv的初始化逻辑,所以shellHook变量仅被定义但不会被执行。
解决方案
以下是两种不依赖pkgs.mkShell的实现方式:
方案1:使用stdenv.mkDerivation(推荐)
这是最简便的方式,stdenv.mkDerivation是nixpkgs的基础构建工具,并非mkShell的专属依赖,它内置了shellHook的处理逻辑,只需指定空构建命令即可:
let pkgs = import <nixpkgs> {}; in pkgs.stdenv.mkDerivation { name = "hello-shell"; shellHook = '' echo "hello world!" ''; # 空构建命令:仅生成一个空输出,无需实际构建产物 buildCommand = "touch $out"; }
运行nix-shell加载该配置,即可看到shellHook的输出。
方案2:纯用builtins.derivation实现
如果坚持只用Nix内置的builtins.derivation,需要手动让nix-shell启动时执行shellHook。通过自定义shell变量,让bash先执行shellHook再进入交互模式:
let pkgs = import <nixpkgs> {}; in builtins.derivation { name = "hello-shell"; system = builtins.currentSystem; # 定义需要执行的shellHook内容 shellHook = '' echo "hello world!" ''; # 构建脚本:生成空输出(满足derivation必须有$out的要求) builder = "${pkgs.bash}/bin/bash"; args = [ (pkgs.writeScript "dummy-builder.sh" '' mkdir -p $out touch $out/empty '') ]; # 自定义shell启动命令:先执行shellHook,再进入交互式bash inherit (pkgs) bash; shell = "${bash}/bin/bash -c '$shellHook; exec ${bash}/bin/bash'"; }
内容的提问来源于stack exchange,提问作者Wynell
相关产品推荐
相关产品推荐

