OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 082

Nix-shell、devShell 与 direnv 的递进用法

把临时工具、项目锁定环境和目录自动加载分成三个明确步骤。

所在专题Nix 开发环境与二进制兼容 ↗
约 4 分钟阅读开始阅读

️ 传统方案的痛苦#

在 Arch Linux 中,如果你为了编译一个 Python 项目安装了 gcc, libxml2, libxslt,这些包会留在全局环境中,直到显式移除,并可能给不同项目带来版本冲突。 在 NixOS:你可以在项目目录下定义环境,退出后恢复外层 shell;store 内对象仍需等垃圾回收释放。

️ 第一阶段:nix-shell#

临时进入一个环境。

nix-shell -p python311 python311Packages.requests gcc
# 此时你进入了一个包含这些包的子 shell
# 退出后,这些包依然在 /nix/store,但你的 PATH 会被恢复原状

第二阶段:Flake 驱动的 devShells#

在现代工作流中,我们会在项目的 flake.nix 里定义环境:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  outputs = { self, nixpkgs, ... }:
  let
    pkgs = nixpkgs.legacyPackages.x86_64-linux;
  in {
    devShells.x86_64-linux.default = pkgs.mkShell {
      # 运行时依赖
      buildInputs = [ pkgs.python3 ];
      # 构建时环境变量
      shellHook = ''
        echo "欢迎进入 Python 开发环境!"
        export MY_VAR="foo"
      '';
    };
  };
}

运行 nix develop 即可进入。

第三阶段:Direnv 自动化#

每次手动运行 nix develop 很繁琐。配合 direnv,你只需进入目录,环境就会自动加载。

1. 开启 direnv

在 Home Manager 中:

{
  programs.direnv = {
    enable = true;
    nix-direnv.enable = true;
  };
}

2. 在项目中使用

在项目根目录创建 .envrc:

use flake

运行一次 direnv allow。下次你 cd 进这个目录,终端会自动提示 direnv: loading...,所有的工具和环境变量就全部就绪了!

为什么这很酷?#

  1. 版本隔离:项目 A 用 Python 3.9,项目 B 用 Python 3.12,互不干扰。
  2. 团队同步:把 flake.nix、flake.lock 和 .envrc 一起交给同事,并匹配目标平台;锁定文件固定输入修订,而运行服务、外部下载和系统状态仍可能影响实际结果。

授权与 shell 集成

direnv allow 会授权当前目录的 .envrc 执行 shell 代码,先阅读其内容。Home Manager 配置要配合相应 shell 集成;目录切换恢复的是环境变量,不会自动停止 shellHook 启动的数据库。

参考与延伸

  1. 声明式 shell 教程 ↗
  2. nix-direnv ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Nix 开发环境与二进制兼容

  1. 01Nix-shell、devShell 与 direnv 的递进用法
  2. 02Nix 开发环境:多语言、数据库与全栈示例
  3. 03Python、uv 与 Matplotlib/Qt 的依赖边界
  4. 04nix-ld:预编译 ELF、加载器与库路径
  5. 05Overlays、override 与 overrideAttrs
CONTINUE READING / 下一篇Overlays、override 与 overrideAttrs

在现有包定义上调整参数、添加补丁,并让系统实际消费 overlay。