How to manage versions using update-alternatives
Tags: updatealternatives, linux, bash, ubuntu
Published: 2022-11-24 10:05:37

## Background
Recently I needed to run the end to end tests in the older chrome browser as the tool the chrome driver available to me was only working with the older version of chrome.
The solution instead of downgrading my chrome installation was to install multiple versions of chrome-browser. More on this in my recent article [how and where to get older versions of google-chrome](https://dev.to/webduvet/where-and-how-to-get-hands-on-an-older-versions-of-google-chrome-4dj7).
Long story short, I would like to be able to *hotswap* the chrome version. Any python, node or java developer most likely uses some type or form of version manager. In java world people might be using `sdkman` [www.sdkman.org] or node js world us used `nvm` [www.getnvm.org](http://github/nvm).


## What is update-alternatives
> update-alternatives creates, removes, maintains and displays
       information about the symbolic links comprising the Debian
       alternatives system.

It is a tool provided by Debian based distributions which is designed to help to manage multiple versions or different implementations of a command or program, read more on [Debian Alternatives](https://wiki.debian.org/DebianAlternatives). Update-alternatives in Debian based system like Ubuntu is used as default option by `apt`, however, it offers the command-line interface to interact with the settings and to add and remove entries manually.

It can also provide functionality to update something what is called slave links to cater for associated software or manual pages which also need to change when the main target changes.
 The analogy in the nodejs world would be corresponding `npm` installation or in python world it would be corresponding `pip`.

## How to install another version with update-alternatives
if you plan to use **update-alternavives** to e.g. install the multiple node versions you will download the desired version and unpack it in the directory of the choice In my case I need older version of google chrome so it would be  `/opt/google/chromium/1027016/chrome-linux/`.

This will contain binary `/opt/google/chromium/1027016/chrome-linux/chrome`

if you already have `chrome` installed and you did that from the Debian package by

```bash
sudo apt install google-chrome-stable.deb
```
your already have used `update-alternatives` and running
```bash
update-alternatives --display google-chrome
```
will show output:
```bash
google-chrome - auto mode
link best version is /usr/bin/google-chrome-stable
link currently points to /usr/bin/google-chrome-stable
link google-chrome is /usr/bin/google-chrome
/usr/bin/google-chrome-stable - priority 200
```
This indicates that there is only one version of google-chrome and it shows the location and priority for auto mode (the higher version takes precedence).
I don't want to go into too much detail here as it could be found in man pages or online [debian alternatives](https://wiki.debian.org/DebianAlternatives).

Running the following lists the existing links stored by update-alternatives.
```bash
update-alternatives --list google-chrome

?> /usr/bin/google-chrome-stable
```
We can see also here that there is only one. If we follow the symbolic links and investigate further we get to:
```bash
/usr/bin/google-chrome --> /etc/alternatives/google-chrome
/etc/alternatives/google-chrome --> /usr/bin/google-chrome-stable
/usr/bin/google-chrome-stable --> /opt/google/chrome/google-chrome
```
The last one is hard link to executable file and paint a pretty clear picture how the update-alternatives work. `/usr/bin/google-chrome-stable` is an executable and `/usr/bin/google-chrome` is a symbolic link to the executable so we can just type `google-chrome` and it starts the browser. **Update-alternatives** sticks in an extra layer of symbolic links in the middle of which it has the full control.

To add another version to it execute the following
```bash
sudo update-alternatives --install /usr/bin/google-chrome google-chrome /opt/google/chromium/1027016/chrome-linux/chrome
```
if you want to use this as default link in auto mode you can add the priority number at the end, higher number takes precedence. For manual intervention enter the following command:
```bash
sudo update-alternatives --config google-chrome
```
output (depending on given priority nubmer this might differ):
```bash
There are 2 choices for the alternative google-chrome (providing /usr/bin/google-chrome).

Selection    Path                                              Priority   Status
------------------------------------------------------------
  0            /opt/google/chromium/1027016/chrome-linux/chrome   300       auto mode
  1            /opt/google/chromium/1027016/chrome-linux/chrome   300       manual mode
* 2            /usr/bin/google-chrome-stable                      200       manual mode

Press <enter> to keep the current choice[*], or type selection number:
```
if you choose one option the link will no longer be in auto mode, but you can return anytime to automode by running
```bash
sudo update-alternative --auto google-chrome
```

## slave links
As mentioned before, these are associated links which should change when *master* link changes. The examples are **node** and **npm** or **python** and **pip**. It also works with manual pages as some packages install also manual pages. This is also the case when installing google-chrome as deb package as above.
Version managers not based on update-alternatives usually add/edit the entry in `manpath` pointing to the correct man page or edit (add) entry in `$PATH` environment variable.
`update-alternatives` does this via mentioned slave links.

In case of google-chrome, even though it uses update-alternatives by default, it does feature the manual entry, but it does not use slave links and the installer simply copies the man page in the man location. Which prevents update-alternatives to apply sim link here. However, even though we can't do anything with the hard link we can add another manual entry just for the specific version. I'm install chromium so I would be interested to have `chromium manual entry`

manual entry for google chrome can be found here:
```bash
man -w google-chrome
```
We could manually move man entry for google-chrome-stable elsewhere and let update-alternatives utilize slave links, but we could also add another man entry via slave link to demonstrate flexibility. Let's do it.

```bash
sudo update-alternatives --install /usr/bin/google-chrome google-chrome /opt/google/chromium/chrome-linux/chrome \
--slave /usr/share/man/man1/chromium.1.gz chromium.1.gz /opt/google/chromium/chromium.1.gz
```
The result of this will be following. If we use the **google-chrome-stable** the manual entry for chromium via `man chromium` will not be available, but swapping the version for chromium will make the manual entry for chromium available along the original manual entry which is/was set as hard link (actual file).

## Summary
This short articles demonstrate the basic capabilities of the tool **update-alternatives**. More detail can be found on manual pages or on Debian website.


## Links
- [debian alternatives](https://wiki.debian.org/DebianAlternatives)
- [linux man pages](https://linux.die.net/man/8/update-alternatives)