️ 传统方案的痛苦#
在 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...,所有的工具和环境变量就全部就绪了!
为什么这很酷?#
- 版本隔离:项目 A 用 Python 3.9,项目 B 用 Python 3.12,互不干扰。
- 团队同步:把
flake.nix、flake.lock和.envrc一起交给同事,并匹配目标平台;锁定文件固定输入修订,而运行服务、外部下载和系统状态仍可能影响实际结果。
授权与 shell 集成
direnv allow 会授权当前目录的 .envrc 执行 shell 代码,先阅读其内容。Home Manager 配置要配合相应 shell 集成;目录切换恢复的是环境变量,不会自动停止 shellHook 启动的数据库。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。