alternatives命令总结

今天手动编译gcc源码,网上查询资料,再一次遇到了alternatives,就研究了一下,所得记录于此加深印象。

基本用法

# 用alternatives查看目前系统中有哪些java版本
$ alternatives --config java
# 注册新版java
$ sudo alternatives --install /usr/bin/java  java  /usr/local/java/jre1.8.0_131/bin/java  4
# 配置有效java
$ sudo alternatives --config java

说明:

alternatives --install <link> <name> <path> <priority>

其中,
install表示安装
link是符号链接
name则是标识符
path是执行文件的路径
priority则表示优先级
搞搞清楚它是怎么做到的。

alternatives 命令怎么切换软件版本的?

# 当前java版本
$ java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)
# java 确实在 alternatives 命令的管控之下
$ alternatives --list  | grep java
servlet auto    /usr/share/java/tomcat-servlet-3.0-api.jar
java    auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre/bin/java
jre_openjdk     auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre
jre_1.8.0       auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre
jaxp_transform_impl     auto    /usr/share/java/xalan-j2.jar
jaxp_parser_impl        auto    /usr/share/java/xerces-j2.jar
javac   auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/bin/javac
java_sdk_openjdk        auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64
java_sdk_1.8.0  auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64
java_sdk_1.8.0_openjdk  auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64
# 每次执行java命令,它对应的是这个
$ which java
/usr/bin/java
# 实际路径是
$ realpath /usr/bin/java
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre/bin/java
# /usr/bin/java 是符号链接,指向 /etc/alternatives/ 目录下的同名文件
$ ll /usr/bin/java
lrwxrwxrwx 1 root root 22 10月 26 07:38 /usr/bin/java -> /etc/alternatives/java
#  /etc/alternatives/java 也是符号链接,它指向真正的java文件
$ ll /etc/alternatives/java
lrwxrwxrwx 1 root root 73 10月 26 07:38 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/jre/bin/java
$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/

由此可见alternatives命令使用的都是最基本的东西:PATH路径+符号链接。我们可以纯手工实现这些操作,只不过alternatives把这些步骤自动化了,方便。
还有一些小问题,

  1. 切换jdk版本不仅仅是切换一个java命令那么简单,还有对应的javac、javah、javap等等一系列相关命令,怎么处理
  2. gcc不仅仅是一个gcc命令,还有对应的头文件、

另一波alternative设置实例

当时的情况是这样的:CentOS7 yum install 方式安装的gcc版本4.2,源码编译安装gcc 9.2,安装后,两个版本共存,如果默认版本仍然是4.2,使用下面的命令更改。

mv /usr/bin/gcc /usr/bin/gcc-4.8.5
mv /usr/bin/g++ /usr/bin/g++-4.8.5
mv /usr/local/bin/gcc /usr/local/bin/gcc-9.2.0
mv /usr/local/bin/g++ /usr/local/bin/g++-9.2.0

alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8.5 10 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.8.5
alternatives --install /usr/bin/gcc gcc /usr/local/bin/gcc-9.2.0 20 \
--slave /usr/bin/g++ g++ /usr/local/bin/g++-9.2.0
alternatives --config gcc

这里的–slave 的作用:有些软件包由多个可执行文件组成,它们的更改应该是同步进行的,alternatives 系统通过主/从(master/slave)链接的概念实现同步,当主链接改变时,所有相关连的从链接同步改变。主链接和与之关联的从链接构成一个链接组。

总结

先声明一下我的环境。

$ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
$ uname -r
3.10.0-1062.4.1.el7.x86_64
$ alternatives --version
alternatives version 1.7.4

阅读了alternatives命令的手册页,结合我遇到的实际问题以及解决问题的过程,总结如下,加深记忆。

alternative

关键概念

有些软件他们的功能相同或类似,能相互替代,比如1)/usr/bin/vi/usr/bin/ed都是本编辑器,相互之间可以作为替代品使用;再比如,2)gcc 4.2gcc 9.2只是版本不同,更是明显的互相替代软件;3)OpenJDK和Oracle JDK以及它们的不同版本都是可以互相替代的。alternatives 系统就是用来解决这些问题的。
以1)为例,可以把/user/bin/vi设为整个系统的默认编辑器,一种方式是,创建符号链接/usr/bin/editro使其默认指向/usr/bin/vi,其他用户和程序使用编辑器的使用只需要调用editor命令即可;当管理员想要更改默认编辑器时,简单的更改/user/bin/editor的指向就行了。
扯两句闲话,像1)这种简单的情形手动完成也很方便,但是a)如果程序多起来的时候,纯靠手工管理容易混乱、忘记;b)有些软件同时包含多个可执行文件,它们的切换应该是整体切换,手动容易乱;c)手工切换要求管理者对软件有十分透彻的理解,否则搞错了怎么办,比如弄错了软件和文档的对应关系,但如果有alternatives系统,然后大家都遵守它的使用规则,让软件发行者负责管理软件中各部分的关联关系,然后一起打包进RPM发行包中,就能大大减轻管理员的负担。
回到正题,1)在alternatives会这样实现/usr/bin/editor—>/etc/alternatives/editor–>/usr/bin/vi,就是在/etc/alternatives/目录下多加了一层间接的符号链接。vi和ed都是文本编辑器,并用/user/bin/editor指向其中的一个,在alternatives系统里,我们说软件vi和ed有相同的通用名(generic name):editro,并把/usr/bin/editor称为链接(link),把/usr/bin/vi/usr/bin/ed都叫做路径(path);这是最基本的情况。而向gcc这样的软件包含多个可执行程序gccg++,这就有了master、slave 链接的概念。
一个generic name下包含多个互相替代品(alternatives),每个互相替代品也叫一个组(group),一个组由至少一个主链接和零至多个从链接组成。
alternatives命令总结_第1张图片
alternative directory:/etc/alternatives:这里保存alternative系统中中间那一层符号链接。
administration directory: /var/lib/alternatives:这里就是alternative系统的数据库,所有的alternative都在这里有登记,并且保存这各个alternative的状态信息。
主从链接是为了解决软件整体性问题:当主链接被设为默认、删除时,从链接会同步处理。
自动模式和手动模式:一个generic name第一次安装后,它处于自动模式;一旦手动设置某个组为默认组,它就变成了手动模式,并一直保持手动模式,直到显式使用命令把他设为自动模式。自动模式的含义是:alternatives系统会在安装、卸载软件时自动更新相关链接;而手动模式下,系统不会对链接做任何修改,一切都由系统管理员说了算。

Each link group is, at any given time, in one of two modes: automatic or manual. When a group is in automatic mode, the alternatives system will automatically decide, as packages are installed and removed, whether and how to update the links. In manual mode, the alternatives system will not change the links; it will leave all the decisions to the system administrator.
最后,同一个name下的各个组有一个相关联的优先级,比如0,30,50,数值越大优先级越高,50就比30高;自动模式下alternatives系统根据优先级选择默认组。

# 1. --install 新注册一个group到generic name中
# alternatives --install link name path priority[--slave slink sname spath]...
$ sudo alternatives --install /usr/bin/gcc gcc /usr/local/bin/gcc 4 --slave /usr/bin/g++ g++ /usr/local/bin/g++
# 2. --display name 显示某个通用名字中包含的组以及各个组的优先级、主从链接
# 3. --list 列出alternative系统中所有的组
$ alternatives --list
$ alternatives --dispaly gcc 
# 4. --config name 交互式更改某个通用名字中的默认组;也可以
# 5. --set name path 直接设置默认组(这里的path是组中的master link的实际路径)
# 6. --auto name 把name的模式设为自动
# 7. --remove name path 删除某个组
# 由此可见,在命令行中,name + path 可以唯一标识一个组。

使用约定

好的辅助工具得配合大家都认同的使用约定才能达到工具的预期效果。
除了管理员手动管理,在同类软件之间切换,alternatives一般由rpm安装包的%pre%post过程调用,把软件添加到某个软件组里,特别是那些本身由包管理系统(apt、yum)负责安装、卸载的软件。

misc

Ubuntu 上,这个命令叫“update-alternatives”。
alternatives 管理的是软件,软件不仅仅包含可执行程序还包括相关的文档(具体就是man手册)、头文件、库文件等等。
Q. alternaitives 管理不同替代品的时候为什么要在/etc/alternatives目录下多加一层间接的符号链接呢?
man 手册页有简单说明,说是这样的好处是所有的配置文件都在/etc/目录下,详细的优点参考FHS。

The generic name is not a direct symbolic link to the selected alternative. Instead, it is a symbolic link to a name in the alternatives directory, which in turn is a symbolic link to the actual file referenced. This is done so that the system administra tor’s changes can be confined within the /etc directory: the FHS (q.v.) gives reasons why this is a Good Thing.

Q. 按道理,OpenJDK和Oracle都应该使用同一个通用名字,但实际情况不是,什么java、jre、openjdk、乱七八糟的。

ref

使用Linux的alternatives命令替换选择软件的版本

你可能感兴趣的:(linux,总结)