Using lsb_release for better install scripts
Did you know there’s a command to find out the “codename” of a Debian or Ubuntu distribution? I dig into this command more and use it to help create a bootstrapped postgres installation script usable across different Ubuntu or Debian distributions.
I hope this will inspire you to use lsb_release
more in your
installation scripts for automatic installation and setup.
This article will take you about four minutes to read.
Introduction
I was setting up an automated installation of postgres in my vagrant/virtualbox setup and need to configure the correct repository.
The repository needed for postgres depends on the version of the linux distribution, configured on the top level of the Vagrant file:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.provider 'virtualbox' do |v|
v.memory = 512
v.cpus = 2
end
end
postgres complication??
As a database, postgres has specific builds for each operating
system. When installing on Debian-based system like Ubuntu, postgres
uses the codename
of the distribution to organize their builds.
The debian repository entry is in the form:
echo "deb http://apt.postgresql.org/pub/repos/apt/ <distribution codename>-pgdg main" > /etc/apt/sources.list.d/pgdg.list
Where distribution codename
would be the codename of the
distribution.
Distribution Codename?!
Where does the distribution codename come from?? Isn’t a number enough?
Yes, a number would be enough (i.e. Ubuntu 16.04) there can be multiple releases of a version of a distribution: betas, release candidates, security fixes, etc.
Also, a “codename” can be easier to remember than just a number and harder to fat-finger. :-)
Examples of recent Ubuntu codenames:
- Ubuntu 16.04 - Xenial Xerus
- Ubuntu 18.04 - Bionic Beaver
- Ubuntu 20.04 - Focal Fossa
and recent Debian codenames:
- Debian 8 - Jessie
- Debian 9 - Stretch
- Debian 10 - Buster
How to combine this information with postgres’ archive requirement?
Solution 1: Hardcode
I can just write the version into the postgres script:
echo "deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main" > /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
That would work, it did for me the first time and if I always use the same distribution, this will work perfectly. I will have to remember what the distribution’s codename is in the script.
Solution 2: Argument
What if I change distributions? Ubuntu 16.04 did come out in 2016… almost five years ago! It’s Long Term Support will end soon and I don’t want to be using gasp an unsupported operating system!
When I update the distribution used for the vagrantbox, I would need
to remember to update this entry too. I don’t want to always remember
that, (as easy as it is to grep
or sed
.)
Another solution: I can set up the vagrant file to pass in a parameter of the distribution name, like for which version of ruby to install:
config.vm.provision :shell, path: "vagrant_scripts/install-ruby.sh", args: "2.5", privileged: false
and in the script, access it:
rvm use --default --install $1
The postgres example would be:
From the Vagrantfile
:
config.vm.provision :shell, path: "vagrant_scripts/install-postgres.sh", args: "xenial"
The corresponding install-postgres.sh
file contents:
echo "deb http://apt.postgresql.org/pub/repos/apt/ $1-pgdg main" > /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
That’s getting better. The Vagrantfile calling the install-postgres
script will manage the version the script uses.
Solution 3: lsb_release
What if I don’t want to remember to update the install-postgres.sh
file each time I change distributions, like when I want to experiment
with the newer versions and not commit to it for production systems?
What if I want to have the postgres install script to be portable, using it in vagrant setup as well as straight up command-line installs?
The argument approach would still work, as long as we pass the parameter into the script.
Can we do better?
Can the script be “bootstrapped” itself? Meaning, one can run it anywhere and just do the right thing?
Yes, by using lsb_release
, the script can retrieve the
distribution’s codename consistently and without human intervention:
The install-postgres.sh
file:
echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
Nice - now the install-postgres.sh
file will be usable without
passing information in:
The Vagrantfile
would call it as:
config.vm.provision :shell, path: "vagrant_scripts/install-postgres.sh"
Less is definitely more here. ;-)
lsb_release
If you want to find out more about lsb_release
, the manpage has
further details and additional options for the command:
$ man lsb_release
lsb_release(1) General Commands Manual lsb_release(1)
NAME
lsb_release - print distribution-specific information
SYNOPSIS
lsb_release [options]
Additional option, -a
shows more information:
vagrant@ubuntu-xenial:~/rgr$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.6 LTS
Release: 16.04
Codename: xenial
Conclusion
What started as a way to automate installation of postgres more turned
into a dive into a linux utility: lsb_release
, that returns details
of the distribution, such as it’s codename, release, and description.
I will be using this information more to help automate installation scripts wherever I can.