update-alternatives 是 Linux 系统级工具,用于在已安装的同功能程序间通过软链接切换默认版本;它不安装/卸载软件,也不隔离环境,需手动注册、配置并注意 PATH 与缓存。

update-alternatives 是什么,它真能管多版本 Java/Python/Editor?
能,但不是万能开关。它只负责在多个已安装的同功能程序间做软链接切换,不负责安装、卸载或隔离环境。比如你系统里已有 java-8-openjdk 和 java-17-openjdk,update-alternatives 就能让你用一条命令把 /usr/bin/java 指向其中任一个;但它不会帮你下载 JDK,也不会阻止两个 Java 版本的 jar 文件互相干扰。
常见误用:以为配了 update-alternatives 就等于有了“版本管理器”,结果跑 Maven 时还是报 Unsupported class file major version 61——那是因为 javac 和 java 虽然版本一致,但 M2_HOME 或项目 pom.xml 里指定了不同 JDK 的 toolchain。
怎么注册一个新版本(比如手动编译的 Python 3.12)?
必须显式注册,不能靠“检测自动加入”。核心是三步:准备可执行文件路径、选择优先级、执行 update-alternatives --install。
-
update-alternatives --install /usr/bin/python python /opt/python312/bin/python3.12 100—— 这里/usr/bin/python是逻辑名(被调用的入口),python是组名(所有 python 变体共用这个组),/opt/python312/bin/python3.12是真实路径,100是优先级(数字越大,默认越可能被选中) - 如果还希望
pip也跟着切,得单独再注册一次:update-alternatives --install /usr/bin/pip pip /opt/python312/bin/pip3.12 100 - 注册后必须运行
update-alternatives --config python才真正生效;否则只是“入库”,没“上位”
为什么 update-alternatives --config java 列不出我刚装的 JDK?
大概率是没注册,或者注册时路径写错了。检查三个点:
- 确认
java可执行文件存在且有执行权限:ls -l /usr/lib/jvm/java-17-openjdk-amd64/bin/java(路径因发行版而异) - 注册命令里用的是完整路径,不是目录:
--install ... /usr/lib/jvm/java-17-openjdk-amd64/bin/java✅,不是/usr/lib/jvm/java-17-openjdk-amd64❌ - 检查是否重名冲突:如果之前注册过
java-11用了组名java,新加的必须用同一组名,否则--config java根本看不到它
一个快速验证法:update-alternatives --list java —— 如果报 no alternatives for java,说明组名没注册成功,不是 JDK 没装好。
切换后终端里 which java 没变?
因为 which 查的是 $PATH 中第一个匹配项,而 update-alternatives 修改的是符号链接本身。如果 /usr/bin/java 已被正确指向新目标,但 which java 还显示旧路径,通常只有两种情况:
- 你的 shell 缓存了命令路径:执行
hash -d java或直接hash -r清空整个缓存 -
/usr/bin/java被其他机制覆盖了:比如你用asdf或pyenv设置了shim,它们会把自定义 bin 目录放在$PATH更前面,导致which优先找到 shim 而非/usr/bin/java
最可靠的验证方式永远是:readlink -f $(which java) —— 它会层层解析符号链接,最终告诉你实际执行的是哪个二进制文件。
别指望 update-alternatives 管理所有东西。它适合系统级工具(java、gcc、editor),不适合项目级依赖(如 Node.js 的 nvm、Python 的 venv)。混用时尤其注意 PATH 顺序和 shell 缓存,否则看起来“切了”,其实根本没走新版本。


















