22 update-alternatives:管理命令和文件的多个版本 #
系统上往往会安装同一个工具的多个版本。为了让管理员可以选择,以及能一起安装和使用多个不同的版本,备选项系统提供了以一致的方式管理此类版本的功能。
22.1 概述 #
    在 SUSE Linux Enterprise Server 上,有些程序执行的是相同或类似的任务。例如,如果系统上既安装了 Java 1.7,也安装了 Java 1.8,则会从 RPM 软件包中调用备选项系统脚本 (update-alternatives)。备选项系统默认将参照版本 1.8:版本越高,优先级就越高。不过,管理员可以更改该默认设置,并可将通用名称指向版本 1.7。
   
本章使用了下列术语:
- 管理目录
- 默认的 - /var/lib/rpm/alternatives目录,其中包含有关备选项当前状态的信息。
- 替代方案
- 文件系统中某个特定文件的名称,可使用备选项系统通过通用名称访问。 
- 备选项目录
- 包含符号链接的默认 - /etc/alternatives目录。
- 通用名称
- 该名称(例如 - /usr/bin/edit)参照可通过备选项系统使用的多个文件中的一个。
- 链接组
- 一组相关的符号链接,可作为一个组更新。 
- 主链接
- 链接组中用于确定如何配置组中其他链接的链接。 
- 从属链接
- 链接组中受主链接控制的链接。 
- 符号链接 (symlink)
- 在同一文件系统中作为另一个文件的参照的文件。备选项系统使用备选项目录中的符号链接在一个文件的各个版本之间切换。 - 管理员可通过 - update-alternatives命令修改备选项目录中的符号链接。
    备选项系统提供 update-alternatives 命令,用来创建、去除、维护和显示有关符号链接的信息。虽然这些符号链接通常指向命令,但它们也可以指向 JAR 存档、手册页及其他文件。本章中的示例使用了命令和手册页,但它们也适用于其他文件类型。
   
备选项系统使用备选项目录来收集指向可能的备选项的链接。安装包含备选项的新软件包时,就会将新的备选项添加至系统。是否将新软件包的备选项选为默认值取决于它的优先级和设置的模式。版本较高的软件包优先级也较高。备选项系统可以在两种模式下工作:
- 自动模式: 在此模式下,备选项系统会确保组中的链接指向适合组且优先级最高的备选项。 
- 手动模式: 在此模式下,备选项系统不会对系统管理员的设置进行任何更改。 
    例如,在备选项系统中,java 命令具有以下链接层次结构:
   
22.2 使用案例 #
    默认从 RPM 软件包中调用 update-alternatives 脚本。安装或去除一个软件包时,该脚本会处理该软件包所有的符号链接。不过,您可以从命令行中手动运行该脚本,以便:
   
- 显示通用名称的当前备选项。 
- 更改备选项的默认值。 
- 为备选项创建一组相关的文件。 
22.3 获取备选项的概览 #
要检索所有已配置备选项的名称,请使用:
>ls /var/lib/alternatives
要获取所有已配置备选项的概览及其值,请使用
>sudoupdate-alternatives --get-selectionsasadmin auto /usr/bin/asadmin-2.7 awk auto /usr/bin/gawk chardetect auto /usr/bin/chardetect-3.6 dbus-launch auto /usr/bin/dbus-launch.x11 default-displaymanager auto /usr/lib/X11/displaymanagers/gdm [...]
22.4 查看有关特定备选项的细节 #
    检查备选项最简单的方法就是查看命令的符号链接。例如,要确定 java 命令参照的是什么,请使用以下命令:
   
>readlink --canonicalize /usr/bin/java/usr/lib64/jvm/jre-10-openjdk/bin/java
    如果您看到相同的路径(在本例中为 /usr/bin/java),则说明此命令没有备选项。
   
    要查看全部的备选项(包括从属链接),请使用 --display 选项:
   
>sudoupdate-alternatives --display javajava - auto mode link best version is /usr/lib64/jvm/jre-1.8.0-openjdk/bin/java link currently points to /usr/lib64/jvm/jre-1.8.0-openjdk/bin/java link java is /usr/bin/java slave java.1.gz is /usr/share/man/man1/java.1.gz slave jre is /usr/lib64/jvm/jre slave jre_exports is /usr/lib64/jvm-exports/jre slave keytool is /usr/bin/keytool slave keytool.1.gz is /usr/share/man/man1/keytool.1.gz slave orbd is /usr/bin/orbd slave orbd.1.gz is /usr/share/man/man1/orbd.1.gz [...]
22.5 设置备选项的默认版本 #
/usr/bin 中的命令默认会参照优先级最高的备选项目录。例如,java 命令默认会显示下面的版本号:
   
>java -versionopenjdk version "10.0.1" 2018-04-17 OpenJDK Runtime Environment (build 10.0.1+10-suse-lp150.1.11-x8664) OpenJDK 64-Bit Server VM (build 10.0.1+10-suse-lp150.1.11-x8664, mixed mode)
    要将默认 java 命令更改为参照先前的版本,请运行:
   
>sudoupdate-alternatives --config javaroot's password: There are 2 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib64/jvm/jre-10-openjdk/bin/java 2005 auto mode 1 /usr/lib64/jvm/jre-1.8.0-openjdk/bin/java 1805 manual mode 2 /usr/lib64/jvm/jre-10-openjdk/bin/java 2005 manual mode 3 /usr/lib64/jvm/jre-11-openjdk/bin/java 0 manual mode Press <enter> to keep the current choice[*], or type selection number:
    根据您的系统和安装的版本,具体的 Java 版本号会有所不同。选择 1 之后,java 会显示下面的版本号:
   
>java -versionjava version "1.8.0_171" OpenJDK Runtime Environment (IcedTea 3.8.0) (build 1.8.0_171-b11 suse-lp150.2.3.1-x86_64) OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)
另外,请记住以下几点:
- 在手动模式下安装另一个 Java 版本时,备选项系统既不会更改链接,也不会更改通用名称。 
- 在自动模式下安装另一个 Java 版本时,备选项系统会更改 Java 主链接及所有从属链接(如第 22.4 节 “查看有关特定备选项的细节”中所示)。要检查主/从关系,请使用: - >- sudo- update-alternatives --display java
22.6 安装自定义备选项 #
本节介绍如何在系统上设置自定义备选项。
       不要安装 python3 的自定义备选项。/usr/bin/python3 没有更新备选项,并且始终指向特定的已测试版本。创建指向其他版本(如 python 3.11)的自定义 python3 备选项会破坏依赖的系统工具。
     
示例做了以下假设:
- 具有类似功能的脚本有两个,分别是 - foo-2和- foo-3。
- 这些脚本存储在 - /usr/local/bin目录中,以免与- /usr/bin中的系统工具产生任何冲突。
- 有一个主链接 - foo指向- foo-2或- foo-3。
要在您的系统上提供备选项,请执行以下步骤:
- 将您的脚本复制到 - /usr/local/bin目录中。
- 让脚本可执行: - >- sudo- chmod +x /usr/local/bin/foo-{2,3}
- 针对两个脚本运行 - update-alternatives:- >- sudoupdate-alternatives --install \ /usr/local/bin/foo 1\ foo 2\ /usr/local/bin/foo-2 3\ 200 4- >- sudoupdate-alternatives --install \ /usr/local/bin/foo 1\ foo 2\ /usr/local/bin/foo-3 3\ 300 4- --install后面的选项具有以下含义:
- 检查主链接: - >- sudo- update-alternatives --display foofoo - auto mode link best version is /usr/local/bin/foo-3 link currently points to /usr/local/bin/foo-3 link foo is /usr/local/bin/foo /usr/local/bin/foo-2 - priority 200 /usr/local/bin/foo-3 - priority 300
    完成所述步骤后,便可以使用主链接 /usr/local/bin/foo 了。
   
如果需要,可以安装其他的备选项。要去除备选项,请使用以下命令:
>sudoupdate-alternatives --remove foo /usr/local/bin/foo-2
去除此脚本之后,foo 组的备选项系统看上去如下所示:
>sudoupdate-alternatives --display foofoo - auto mode link best version is /usr/local/bin/foo-3 link currently points to /usr/local/bin/foo-3 link foo is /usr/local/bin/foo /usr/local/bin/foo-3 - priority 300
22.7 定义依赖备选项 #
如果您有备选项,则仅凭脚本本身不足以完成任务。大部分命令都不是独立的 — 它们随附其他文件,例如扩展、配置或手册页。要创建依赖于主链接的备选项,请使用从属备选项。
我们假设要扩展第 22.6 节 “安装自定义备选项”中的示例,并提供手册页和配置文件:
- foo-2.1.gz和- foo-3.1.gz这两个手册页,存储在- /usr/local/man/man1目录中。
- foo-2.conf和- foo-3.conf这两个配置文件,存储在- /etc中。
请执行以下步骤将其他文件添加至备选项中:
- 将配置文件复制到 - /etc中:- >- sudo- cp foo-{2,3}.conf /etc
- 将手册页复制到 - /usr/local/man/man1目录中:- >- sudo- cp foo-{2,3}.1.gz /usr/local/man/man1/
- 使用 - --slave选项将从属链接添加至主脚本:- >- sudo- update-alternatives --install \ /usr/local/bin/foo foo /usr/local/bin/foo-2 200 \ --slave /usr/local/man/man1/foo.1.gz \ foo.1.gz \ /usr/local/man/man1/foo-2.1.gz \ --slave /etc/foo.conf \ foo.conf \ /etc/foo-2.conf- >- sudo- update-alternatives --install \ /usr/local/bin/foo foo /usr/local/bin/foo-3 300 \ --slave /usr/local/man/man1/foo.1.gz \ foo.1.gz \ /usr/local/man/man1/foo-3.1.gz \ --slave /etc/foo.conf \ foo.conf \ /etc/foo-3.conf
- 检查主链接: - foo - auto mode link best version is /usr/local/bin/foo-3 link currently points to /usr/local/bin/foo-3 link foo is /usr/local/bin/foo slave foo.1.gz is /usr/local/man/man1/foo.1.gz slave foo.conf is /etc/foo.conf /usr/local/bin/foo-2 - priority 200 slave foo.1.gz: /usr/local/man/man1/foo-2.1.gz slave foo.conf: /etc/foo-2.conf /usr/local/bin/foo-3 - priority 300 slave foo.1.gz: /usr/local/man/man1/foo-3.1.gz slave foo.conf: /etc/foo-3.conf 
    如果您使用 update-alternatives --config foo 将链接更改为 foo-2,则所有从属链接也会随之更改。