T7、RHEL alternatives

作者: Brinnatt 分类: 小工具 发布时间: 2025-10-09 11:55

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

解释:

  1. 用户调用 /usr/bin/java
  2. 系统通过 /etc/alternatives/java 再次跳转到实际实现
  3. 这样包管理器只需修改 /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 组(如 javaeditorpython)。所有相同 <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 后,系统会做三件事:

  1. 创建 /etc/alternatives/<name> 符号链接;
  2. /var/lib/alternatives/<name> 写入元数据文件;
  3. 根据模式(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 控制(应使用 pyenvjenv 等)。

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 造成 javajavac 不一致 一定要配 --slave 保证同步
修改 /etc/alternatives 手动 ln -sf 会破坏状态数据库 使用 --set--config 官方命令切换
priority 太低被忽略 优先级数值影响自动模式 确保优先级大于现有实现
标签云