T7、RHEL alternatives
ChatGPT 科普,快速解决本人问题,逻辑细节未过多考究,请读者自行甄别
T7.1、概述(Overview)
alternatives
是 Red Hat 系统中的一个 系统级符号链接管理框架,用于在多个软件版本或实现并存时,为系统提供一种统一的“默认程序选择”机制。
常见用途:
- 管理多个版本的 Java (
java
,javac
) - 管理多个版本的编辑器 (
vi
,vim
,nano
) - 管理多个版本的编译器 (
gcc
,clang
) - 管理系统命令的默认实现(如
awk
,python
等)
其核心功能是维护一个称为 link group(链接组) 的元数据集合,自动或手动地将 /usr/bin/<generic>
等通用命令名指向具体实现路径。
T7.2、起源与背景(History)
- 原始实现来自 Debian 系统的
update-alternatives
(Perl 编写)。 - Red Hat 将其机制引入并重写为
/usr/sbin/alternatives
,去掉 Perl 依赖,兼容 RPM 包管理脚本。 - 从 RHEL 5 开始全面内置并作为系统标准组件维护至今。
Debian 与 Red Hat 系列的命令名差异:
发行版 | 命令名 |
---|---|
RHEL / CentOS / Fedora | alternatives |
Debian / Ubuntu | update-alternatives |
T7.3、工作原理(Mechanism)
3.1 链接结构(Link Chain)
典型的三层符号链接结构如下:
/usr/bin/java → /etc/alternatives/java → /usr/lib/jvm/java-11-openjdk/bin/java
解释:
- 用户调用
/usr/bin/java
- 系统通过
/etc/alternatives/java
再次跳转到实际实现 - 这样包管理器只需修改
/etc/alternatives/java
即可全局切换版本
3.2 链接组(Link Group)
- 每个链接组由一个 主链接(master link) 和若干个 从属链接(slave links) 组成。
- 修改主链接时,所有从属链接会同步切换。
- 每个组都有:
- name(名称)
- mode(模式:auto/manual)
- priority(优先级)
- 候选路径(alternatives)
3.3 模式与优先级(Mode & Priority)
模式 | 描述 |
---|---|
auto |
自动模式。系统根据最高优先级自动选择当前实现。 |
manual |
手动模式。管理员手动设置后不会被包升级自动覆盖。 |
每个 alternative 具有一个整数优先级(越大越高)。当组处于 auto
模式时,系统默认选择优先级最高的实现。
T7.4、文件系统结构(Directory Layout)
路径 | 说明 |
---|---|
/usr/bin/<name> |
通用命令入口点(通常为符号链接) |
/etc/alternatives/<name> |
管理层符号链接(由 alternatives 管理) |
/var/lib/alternatives/<name> |
链接组的元数据文件(包含候选、优先级、模式等) |
注意:Debian 系列系统使用
/var/lib/dpkg/alternatives
存储状态。
T7.5、常用命令参考(Command Reference)
5.1 安装新候选
主路径、组名、实际路径、优先级 —— 再配一堆从属:
alternatives --install <link> <name> <path> <priority> \
[--slave <link> <name> <path> ...]
alternatives --install <系统命令路径> <组名> <实际程序路径> <优先级> \
[--slave <从命令路径> <从组名> <从程序路径> ...]
参数 | 说明 |
---|---|
<link> |
主符号链接(master link) 的目标路径,即用户平时执行的命令路径,比如 /usr/bin/java 。这就是最终要被“切换”的命令。 |
<name> |
组名(name of the link group)。用于内部识别同一个 alternatives 组(如 java 、editor 、python )。所有相同 <name> 的候选项属于同一个组。 |
<path> |
实际实现路径(path to real binary),也就是 /etc/alternatives/<name> 最终会指向的文件,比如 /opt/jdk-17/bin/java 。 |
<priority> |
优先级(priority)。整数,越大越优先。只有在组处于自动模式 (--auto ) 时才起作用。系统会选择优先级最高的版本作为默认。 |
--slave <link> <name> <path> |
定义从属符号链接(slave link)。每当 master 切换时,slave 会自动同步切换。可以有多个 --slave 参数。 |
用户命令: /usr/bin/java
│
▼
系统链接: /etc/alternatives/java
│
▼
实际实现: /opt/jdk-17/bin/java
同步切换:
/usr/bin/javac -> /etc/alternatives/javac -> /opt/jdk-17/bin/javac
/usr/share/man/man1/java.1.gz -> /etc/alternatives/java.1.gz -> /opt/jdk-17/man/java.1.gz
# 注册 JDK 11
alternatives --install /usr/bin/java java /usr/lib/jvm/java-11/bin/java 1100 \
--slave /usr/bin/javac javac /usr/lib/jvm/java-11/bin/javac
# 注册 JDK 17
alternatives --install /usr/bin/java java /opt/jdk-17/bin/java 1700 \
--slave /usr/bin/javac javac /opt/jdk-17/bin/javac
alternatives --config java
There are 2 programs which provide 'java'.
Selection Command
-----------------------------------------------
*+ 1 /usr/lib/jvm/java-11/bin/java
2 /opt/jdk-17/bin/java
Enter to keep the current selection[+], or type selection number:
执行 --install
后,系统会做三件事:
- 创建
/etc/alternatives/<name>
符号链接; - 在
/var/lib/alternatives/<name>
写入元数据文件; - 根据模式(auto/manual)更新
/usr/bin/<generic>
链接。
元数据文件示例(摘自 /var/lib/alternatives/java
):
auto
/usr/bin/java
/usr/lib/jvm/java-11/bin/java
1100
/usr/lib/jvm/java-17/bin/java
1700
slave javac /usr/bin/javac /usr/lib/jvm/java-11/bin/javac
slave javac /usr/bin/javac /usr/lib/jvm/java-17/bin/javac
5.2 移除候选
alternatives --remove <name> <path>
alternatives --remove-all <name>
5.3 切换版本
alternatives --config <name> # 交互式选择
alternatives --set <name> <path> # 非交互式设置(切换为 manual 模式)
alternatives --auto <name> # 恢复自动模式
5.4 查询状态
alternatives --list # 列出所有组
alternatives --display <name> # 查看某个组的详细信息
T7.6、实践示例(Practical Examples)
6.1 Java 版本切换
# 注册多个 JDK
alternatives --install /usr/bin/java java /usr/lib/jvm/java-11/bin/java 1100
alternatives --install /usr/bin/java java /usr/lib/jvm/java-17/bin/java 1700
# 查看并切换
alternatives --config java
# 或脚本化切换
alternatives --set java /usr/lib/jvm/java-11/bin/java
6.2 默认编辑器切换
alternatives --config editor
输出:
There are 3 programs which provide 'editor'.
Selection Command
-----------------------------------------------
*+ 1 /usr/bin/vim
2 /usr/bin/nano
3 /usr/bin/vi
Enter to keep the current selection[+], or type selection number: 2
6.3 查询所有 alternatives
alternatives --list
alternatives --display java
输出示例:
java - status is manual.
link currently points to /usr/lib/jvm/java-17/bin/java
/usr/lib/jvm/java-11/bin/java - priority 1100
/usr/lib/jvm/java-17/bin/java - priority 1700
Current 'best' version is /usr/lib/jvm/java-17/bin/java.
T7.7、排错与常见问题(Troubleshooting)
问题 | 原因 | 解决方案 |
---|---|---|
切换后版本不变 | PATH 或 alias 覆盖 | 使用 which <cmd> 与 readlink -f 检查实际路径 |
包升级改变默认实现 | 当前为 auto 模式 | 使用 --set 切换至 manual 模式固定版本 |
用户与 root 看到不一致 | 用户 PATH 配置差异 | 检查用户 shell 配置与 /etc/profile.d |
手动删除路径后报错 | 状态文件未同步 | 使用 --remove 正确移除旧路径 |
T7.8、最佳实践(Best Practices)
- 生产环境固定默认版本
使用alternatives --set
明确设置版本,防止包升级导致默认切换。 - 脚本化部署
将 alternatives 命令集成到配置管理工具(Ansible、Puppet、Chef)中,确保幂等性。 - 使用 slave 保持一致性
对同一软件族(如 Java、GCC),用--slave
同步绑定相关命令。 - 监控与巡检
定期执行alternatives --display
并保存结果,防止意外更改。 - 避免管理用户级别命令
alternatives
仅用于系统范围,不建议用于 per-user 控制(应使用pyenv
、jenv
等)。
T7.9、常见命令速查(Cheat Sheet)
操作 | 命令 |
---|---|
查看所有组 | alternatives --list |
查看单个组详情 | alternatives --display <name> |
手动交互式切换 | alternatives --config <name> |
非交互式切换 | alternatives --set <name> <path> |
切回自动模式 | alternatives --auto <name> |
注册新版本 | alternatives --install <link> <name> <path> <priority> |
移除旧版本 | alternatives --remove <name> <path> |
T7.10、常见误区
错误 | 原因 | 正确做法 |
---|---|---|
在 --install 中写相对路径 |
alternatives 只接受绝对路径 | 所有 <link> 与 <path> 都必须是绝对路径 |
注册多个版本但不带 --slave |
造成 java 与 javac 不一致 |
一定要配 --slave 保证同步 |
修改 /etc/alternatives 手动 ln -sf |
会破坏状态数据库 | 使用 --set 或 --config 官方命令切换 |
priority 太低被忽略 | 优先级数值影响自动模式 | 确保优先级大于现有实现 |