在这篇文章中,我们来详细介绍一下 Ubuntu (以及其他基于 Debian 的发行版) 中的 update-alternatives
命令。
一句话总结
update-alternatives
是一个强大的命令行工具,用于在系统中管理多个提供相同功能的程序版本(例如多个版本的 Java、Python、Cuda、文本编辑器等),并方便地切换系统默认使用的版本。
为什么需要 update-alternatives
?
在 Linux 系统中,很多命令或程序都有一个标准的名称,比如 java
, python
, editor
, cc
(C 编译器) 等。但你的系统上可能同时安装了多个实现这些功能的软件。
举个例子:Java
你可能同时安装了:
- OpenJDK 11
- OpenJDK 17
- Oracle Java 8
当你在终端输入 java -version
时,系统应该执行哪一个?
如果没有 update-alternatives
,你可能会:
手动创建或修改 /usr/bin/java
这个符号链接(symlink),让它指向你想要的 Java 可执行文件。这样做有几个很大的问题:
- 混乱且易出错:你需要手动管理很多链接,容易搞错。
- 会被包管理器覆盖:当你通过
apt
更新或安装新的 Java 版本时,包管理器可能会自动覆盖你手动创建的链接,导致你的设置失效。 - 不安全:直接修改
/usr/bin
目录下的文件不是一个好习惯。
update-alternatives
的解决方案:
它创建了一个中间层,提供了一个统一、安全、且能与包管理器(apt
)和谐共存的管理机制。
它的工作原理是两级符号链接:
- 一个永久的、通用的符号链接,如
/usr/bin/java
。 - 这个链接指向
update-alternatives
的管理目录,如/etc/alternatives/java
。 /etc/alternatives/java
这个链接才最终指向你选择的具体程序版本,如/usr/lib/jvm/java-11-openjdk-amd64/bin/java
。
/usr/bin/java ──> /etc/alternatives/java ──> /usr/lib/jvm/java-17-openjdk-amd64/bin/java
(通用命令) (alternatives 管理的链接) (实际的程序文件)
当你切换版本时,update-alternatives
只会修改第 2 步的链接 (/etc/alternatives/java
),而 /usr/bin/java
保持不变。这样做既安全又高效。
核心概念
- Name (名称):一个抽象的名字,代表一类功能。例如
java
,editor
,python
。 - Link (链接):指向
/etc/alternatives/<name>
的通用符号链接。例如/usr/bin/java
。 - Alternative (备选项):一个具体的程序路径。例如
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
。 - Priority (优先级):一个整数,用于“自动模式”。数字越高的备选项,在自动模式下越有可能被选为默认值。通常,新版本的软件会有更高的优先级。
- Mode (模式):
auto
(自动模式):系统根据“优先级”最高的备选项来自动设置默认版本。manual
(手动模式):由系统管理员(你)明确指定一个版本作为默认值,忽略优先级。
常用命令
假设我们以管理 java
为例。
1. 显示某个命令的所有可用备选项
这是最常用的查询命令,可以查看当前状态、所有备选项和它们的优先级。
sudo update-alternatives --display java
输出示例:
java - auto mode
link best version is /usr/lib/jvm/java-11-openjdk-amd64/bin/java
link currently points to /usr/lib/jvm/java-11-openjdk-amd64/bin/java
link /usr/bin/java is /etc/alternatives/java
slave /usr/share/man/man1/java.1.gz is /etc/alternatives/java.1.gz
/usr/lib/jvm/java-11-openjdk-amd64/bin/java - priority 1111
slave java.1.gz: /usr/lib/jvm/java-11-openjdk-amd64/man/man1/java.1.gz
/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java - priority 1081
slave java.1.gz: /usr/lib/jvm/java-8-openjdk-amd64/jre/man/man1/java.1.gz
从这个输出我们可以看到:
- 当前是
auto mode
(自动模式)。 - 当前链接指向 Java 11。
- 有两个备选项:Java 11 (优先级 1111) 和 Java 8 (优先级 1081)。
2. 交互式地切换默认版本
这是最推荐、最安全的切换方式。
sudo update-alternatives --config java
系统会列出所有可用的备选项,并让你输入数字来选择:
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode
2 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode
Press <enter> to keep the current choice[*], or type selection number:
*
号表示当前选中的版本。0
选项让你回到自动模式。- 输入
2
然后回车,系统就会将默认的java
命令切换到 Java 8。
3. (高级) 手动添加一个新的备选项
当你手动安装了一个软件(没有通过 apt
),它不会自动注册到 update-alternatives
系统中。这时你需要手动添加。
语法:
sudo update-alternatives --install <link> <name> <path> <priority>
<link>
: 通用命令的路径,如/usr/bin/java
。<name>
: 抽象名称,如java
。<path>
: 你安装的程序的实际路径。<priority>
: 你为它设定的优先级。
示例: 假设你手动下载并解压了 Oracle JDK 18到 /opt/jdk-18
,你想把它添加到系统中。
sudo update-alternatives --install /usr/bin/java java /opt/jdk-18/bin/java 1800
执行后,当你再次运行 sudo update-alternatives --config java
时,就会看到这个新的选项。
4. (高级) 移除一个备选项
如果一个备选项对应的软件你已经删除了,或者你不再需要它,可以将其移除。
# 首先用 --display 确认要移除的备选项的 <path>
sudo update-alternatives --display java
# 然后移除
sudo update-alternatives --remove java /opt/jdk-18/bin/java
总结
update-alternatives
是一个优雅且必不可少的系统管理工具,它带来了以下好处:
- 标准化:为多版本软件管理提供了一个统一的接口。
- 灵活性:让用户可以轻松在不同版本间切换。
- 与包管理器集成:通过
apt
安装的软件会自动注册,卸载时也会自动移除,无需手动干预。 - 安全性:避免了直接操作
/usr/bin
等系统关键目录,将配置集中在/etc/alternatives
。
对于日常使用,你只需要记住 sudo update-alternatives --display <name>
(查看) 和 sudo update-alternatives --config <name>
(切换) 就足够了。
希望这个解释对您有帮助!