多语言版本管理:nvm、pyenv、mise 的思路
Node 要 18 又要用 22,Python 项目一个要 3.9 一个要 3.12 —— 系统自带的版本永远不够用。版本管理器就是解决这个的。
一、原理:改 PATH
所有版本管理器的核心都一样:
# 安装了多个版本
~/.nvm/versions/node/v18.20.4/bin/node
~/.nvm/versions/node/v22.2.0/bin/node
# 切换版本 = 把某个目录放到 PATH 最前面
export PATH="$HOME/.nvm/versions/node/v22.2.0/bin:$PATH"
# 验证
which node && node -v理解这一点,后面所有工具都不神秘了。
二、Node:nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# 重新登录后
nvm install 22 # 装最新版 22
nvm install 18 # 再装一个
nvm use 22 # 当前 shell 切换
nvm alias default 22 # 设默认
nvm ls # 看装了哪些
nvm ls-remote --lts # 看可装的 LTS 版本
nvm uninstall 18项目级锁定:
echo "22" > .nvmrc
nvm use # 自动读 .nvmrc
# 或写进 package.json 的 engines 字段nvm 是 shell 函数(不是可执行文件),所以需要 source ~/.nvm/nvm.sh,安装脚本会写进 .bashrc。
三、Python:pyenv
curl https://pyenv.run | bash
pyenv install 3.12.3
pyenv install 3.9.19
pyenv versions # 列出
pyenv global 3.12.3 # 全局默认
pyenv local 3.9.19 # 当前目录(生成 .python-version)
pyenv shell 3.12.3 # 仅当前 shell
# 验证
python -V && which pythonpyenv 通过 shim 机制工作:
~/.pyenv/shims/python # 一个转发脚本
# 它根据 .python-version / 环境变量决定调用哪个真实解释器四、统一方案:mise(原 rtx)
如果同时用 Node、Python、Go、Ruby、Terraform……装一堆管理器很烦。mise 一个搞定:
curl https://mise.run | sh
echo 'eval "$(mise activate bash)"' >> ~/.bashrc
mise use node@22 # 当前项目
mise use python@3.12
mise use -g node@22 # 全局
mise ls
mise ls-remote node
mise which node
# 项目里生成 .mise.toml
mise use node@22 python@3.12.mise.toml 内容:
[tools]
node = "22"
python = "3.12"
[env]
NODE_ENV = "production"最大优势:进目录自动切换版本(配合 mise activate),不用手动 nvm use。
五、对比
| 工具 | 语言 | 机制 | 特点 |
|---|---|---|---|
| nvm | Node | shell 函数改 PATH | 生态最成熟 |
| fnm / volta | Node | 独立二进制 | 快,volta 自动切换 |
| pyenv | Python | shim | 稳定 |
| mise | 多语言 | shim + PATH | 统一,推荐新项目用 |
| asdf | 多语言 | 插件 | 老牌,插件多 |
选择建议:
- 只写 Node → nvm(资料最多);
- 只写 Python → pyenv 或系统包 + venv;
- 多语言 / 新开始 → mise;
- 服务器 → 尽量不用版本管理器(见下)。
六、服务器上的注意事项
这是个真实的坑:cron / systemd 里跑的任务,看不到 nvm 装的 node。
因为 nvm 是 shell 函数,只在交互式 shell 里加载。
# 失败:cron 里执行 node 命令
0 3 * * * node /opt/app/run.js # command not found解法几种:
1. 用绝对路径(最稳)
0 3 * * * /root/.nvm/versions/node/v22.2.0/bin/node /opt/app/run.js2. 建一个软链到系统路径
sudo ln -s /root/.nvm/versions/node/v22.2.0/bin/node /usr/local/bin/node
sudo ln -s /root/.nvm/versions/node/v22.2.0/bin/npm /usr/local/bin/npm3. 在脚本里显式 source
#!/usr/bin/env bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm use 22 > /dev/null
node /opt/app/run.js4. 生产环境更推荐:容器化或直接用官方包
# 用 NodeSource 的 apt 源装系统级 node
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs我的做法:开发机用版本管理器,服务器用系统包或容器。服务器上少一层间接,就少一类诡异问题。
七、Python 的额外一层:虚拟环境
版本管理器管「哪个 Python」,虚拟环境管「这个项目装哪些包」。两者不冲突:
pyenv local 3.12.3 # 定版本
python -m venv .venv # 建虚拟环境
source .venv/bin/activate # 激活
pip install -r requirements.txt
# 退出
deactivateNode 的 node_modules 是项目本地的,天然隔离;Python 需要显式建虚拟环境。
八、常见问题
| 现象 | 原因 |
|---|---|
command not found: nvm | 没 source,检查 .bashrc |
换了版本但 node -v 没变 | PATH 里有其他 node 在前面 |
| cron 里找不到命令 | shell 函数没加载(见上) |
| pyenv install 编译失败 | 缺编译依赖,装 build-essential + libssl-dev 等 |
# 排查 PATH 里到底有几个 node
which -a node
type -a node版本管理器解决的是「同一台机器上并存多个版本」。想清楚这一点,工具选哪个都不重要。
