You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅用内置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 23:12:35