17

I am trying to create a script that requires me to print the debian codename so that I may echo it into the sources.list file.

I am trying to make this script work across any version of Debian, so I had hoped to set a bash variable of the release codename. This would be simple to do (with lsb_release -c), however our deployment images do not contain lsb_release by default - and with this script being required to fix the sources.list, installing lsb-release with apt-get would not be an option.

I have found numerous ways to get the release number and other info about the system, but cannot find a reliable place to get the codename.

Any ideas would be greatly appreciated!

(OS I am testing this with is Debian Squeeze)

1
  • 2
    If you googled this while considering dropping lsb_release, check out it's source code and see if you're willing to reinvent all that
    – mehov
    Jan 30 '20 at 11:55

11 Answers 11

24

You can use /etc/os-release:

(
  . /etc/os-release
  printf '%s\n' "$VERSION"
)
7 (wheezy)
17

squeeze does not ship with /etc/os-release, this is my 'hack':

dpkg --status tzdata|grep Provides|cut -f2 -d'-'
1
  • Yooo, bro. This is sick! Exactly what I needed. Anything else in Linux Mint LMDE (Debian Edition) doesn't display the Debian version that the Mint was built on. But your solution does. Thanks!
    – GTodorov
    Aug 16 '19 at 15:36
7

You can get the codename of your Debian distribution from /etc/os-release. Instead of attempting to parse this file, you can source it into a fresh environment, so as not to impact your current environment, and execute an echo command in that new environment.

env -i bash -c '. /etc/os-release; echo $VERSION_CODENAME'

To break it down:

  • env : Run a command in a new environment.
  • -i : Do not inherit the environment variables from the existing environment.
  • bash : Run bash so that we have a shell to source the os-release file into, and to run the echo command.
  • -c : Tell bash we want to execute a command rather than start an interactive shell.
  • . /etc/os-release : Source the contents of os-release into our new environment. os-release contains a few lines setting environment variables, and this will set those environment variables in our new environment.
  • ; : Separate this command and run the next command.
  • echo $VERSION_CODENAME : Echo out the code name that was set by the os-release file.
3
  • 1
    Great answer, I learned you to use such files from it. I used it like this echo "$(. /etc/os-release && echo $VERSION_CODENAME" but noticed that there's no $VERSION_CODENAME in stretch. Very sad news.
    – Himura
    Oct 14 '19 at 11:03
  • 2
    I fixed it like this echo "$(. /etc/os-release && echo ${VERSION_CODENAME-stretch})" which seems ok for my task, but it looks bad
    – Himura
    Oct 14 '19 at 11:08
  • 1
    This looks like the most elegant approach (at least thanks to no parsing involved)
    – mehov
    Jan 30 '20 at 11:53
6

You can print code along with version number of debian:

root@debian:/home/mohsen# grep "VERSION=" /etc/os-release |awk -F= {' print $2'}|sed s/\"//g
8 (jessie)

OR you can bare your code name from number and pranthese:

grep "VERSION=" /etc/os-release |awk -F= {' print $2'}|sed s/\"//g |sed s/[0-9]//g | sed s/\)$//g |sed s/\(//g
jessie
4
  • Or, more idiomatically: awk -F= '/VERSION=/ {gsub(/"/,""); print $2}' /etc/os-release
    – jasonwryan
    Jan 24 '15 at 3:58
  • 1
    @jasonwryan Even awk -F"[=\"]+" '/VERSION=/ {print $2}' /etc/os-release
    – Costas
    Jan 24 '15 at 12:41
  • @Costas my output is only codename. Jan 24 '15 at 13:07
  • 4
    If you'd like just code-name it is much simple awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release
    – Costas
    Jan 24 '15 at 13:28
2

For systemd:

hostnamectl | grep "Operating System"

output:

  Operating System: Debian GNU/Linux 8 (jessie)
2
  • It works for me.
    – AnthonyB
    Jan 14 '17 at 9:21
  • This surely does not work on Debian Squeeze as Debian Squeeze did not have a systemd package. And even with Debian 8 Jessie (where systemd became the default init system), hostnamectl is only installed if systemd is installed, so this solution won't work if the system in question uses one of the other 3 or 4 init systems Debian offers. Apr 6 '17 at 13:06
1

this one might (or might not) be an alternate approach to what bcoca wrote on Debian squeeze - i tested it Ubuntu 18.04:

$ cat /etc/debian_version
buster/sid
0

Another heuristic is to see where the packages for the currently running OS come from.

Simple (and probably error-prone) variant:

fgrep -r /debian/ /etc/apt/sources.list \
    | egrep -v '^ *#' \
    | awk '{print $3}' \
    | egrep -v '[-/]'  \
    | uniq

A more reliable way is to parse the details out of the output of apt-cache policy (without further parameter):

apt-cache policy \
    | fgrep o=Debian, \
    | fgrep ,l=Debian, \
    | fgrep ,c=main, \
    | awk -F '[,=]' '{print $6}'

apt-cache policy lists all APT repositories in use on the local system. We filter out those which originate from Debian, which are labeled just Debian (i.e. not those labeled e.g. Debian debug), then only look at the main archive (not contrib or non-free) and then select the according value.

An even more stable approach would be to not rely on the element order and find the n= value in the remaining line:

apt-cache policy \
    | fgrep o=Debian, \
    | fgrep ,l=Debian, \
    | fgrep ,c=main, \
    | egrep -o 'n=[^, ]*' \
    | awk -F= '{print $2}'

Yet another possibility would be to parse the /var/lib/apt/lists/*Release files yourself instead of letting apt-cache do that:

egrep -l '^Origin: Debian$' /var/lib/apt/lists/*Release \
    | xargs egrep -l '^Label: Debian$' \
    | xargs egrep -L 'Codename: .*-' \
    | xargs fgrep Codename \
    | awk '{print $2}'
0

My need was to add some URL in sources.list. And to be able to dynamically put version code name, I use this piece of code (rely on the fact that code name is between parenthesis) : Inspired by @PersianGulf answer.

grep "VERSION=" /etc/os-release |awk -F= {' print tolower($2)'}|sed s/\.*\(//g | sed s/" ".*\"//g

0

Expanding upon @Costas answer, that command didn't work for 16.04 where it returned the full name "Xerial Xerus" but I only wanted "xerial" as that is how the repo I was trying to pull from separated the different versions. This command adds that only the first word will be returned, and that it will be all lowercase:

awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release | awk '{print $1}' | awk '{ print tolower($0) }'

This works for "jessie" as well

0

Only using grep:

grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release

Try it (output as of writing this post):

$ docker run --rm debian:stable-slim grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release
stretch
0

I'm going to leave this here :)

sed -e "0,/_.*_/s/.*_\(.*\)_.*/\1/;t;d" /var/lib/apt/cdroms.list

Edit: It's matching the first _<string>_ inside /var/lib/apt/cdroms.list

1
  • This did show jessie after upgrading to stretch, while env -i bash -c '. /etc/os-release; echo $VERSION_CODENAME' returned the correct version: stretch Oct 5 '20 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.