How can I get distribution name and version number in a simple shell script?

I’m working on a simple bash script that should be able to run on Ubuntu and CentOS distributions (support for Debian and Fedora/RHEL would be a plus) and I need to know the name and version of the distribution the script is running (in order to trigger specific actions, for instance the creation of repositories). So far what I’ve got is this:

OS=$(awk '/DISTRIB_ID=/' /etc/*-release | sed 's/DISTRIB_ID=//' | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VERSION=$(awk '/DISTRIB_RELEASE=/' /etc/*-release | sed 's/DISTRIB_RELEASE=//' | sed 's/[.]0/./')

if [ -z "$OS" ]; then
    OS=$(awk '{print $1}' /etc/*-release | tr '[:upper:]' '[:lower:]')
fi

if [ -z "$VERSION" ]; then
    VERSION=$(awk '{print $3}' /etc/*-release)
fi

echo $OS
echo $ARCH
echo $VERSION

This seems to work, returning ubuntu or centos (I haven’t tried others) as the release name. However, I have a feeling that there must be an easier, more reliable way of finding this out — is that true?

It doesn’t work for RedHat.
/etc/redhat-release contains :
Redhat Linux Entreprise release 5.5

So, the version is not the third word, you’d better use :

OS_MAJOR_VERSION=`sed -rn 's/.*([0-9]).[0-9].*/1/p' /etc/redhat-release`
OS_MINOR_VERSION=`sed -rn 's/.*[0-9].([0-9]).*/1/p' /etc/redhat-release`
echo "RedHat/CentOS $OS_MAJOR_VERSION.$OS_MINOR_VERSION"
Asked By: Alix Axel

||

To get OS and VER, the latest standard seems to be /etc/os-release.
Before that, there was lsb_release and /etc/lsb-release. Before that, you had to look for different files for each distribution.

Here’s what I’d suggest

if [ -f /etc/os-release ]; then
    # freedesktop.org and systemd
    . /etc/os-release
    OS=$NAME
    VER=$VERSION_ID
elif type lsb_release >/dev/null 2>&1; then
    # linuxbase.org
    OS=$(lsb_release -si)
    VER=$(lsb_release -sr)
elif [ -f /etc/lsb-release ]; then
    # For some versions of Debian/Ubuntu without lsb_release command
    . /etc/lsb-release
    OS=$DISTRIB_ID
    VER=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
    # Older Debian/Ubuntu/etc.
    OS=Debian
    VER=$(cat /etc/debian_version)
elif [ -f /etc/SuSe-release ]; then
    # Older SuSE/etc.
    ...
elif [ -f /etc/redhat-release ]; then
    # Older Red Hat, CentOS, etc.
    ...
else
    # Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
    OS=$(uname -s)
    VER=$(uname -r)
fi

I think uname to get ARCH is still the best way. But the example you gave obviously only handles Intel systems. I’d either call it BITS like this:

case $(uname -m) in
x86_64)
    BITS=64
    ;;
i*86)
    BITS=32
    ;;
*)
    BITS=?
    ;;
esac

Or change ARCH to be the more common, yet unambiguous versions: x86 and x64 or similar:

case $(uname -m) in
x86_64)
    ARCH=x64  # or AMD64 or Intel64 or whatever
    ;;
i*86)
    ARCH=x86  # or IA32 or Intel32 or whatever
    ;;
*)
    # leave ARCH as-is
    ;;
esac

but of course that’s up to you.

Answered By: Mikel

If you can’t or don’t want to use the LSB release file (due to the dependencies the package brings in), you can look for the distro-specific release files. Bcfg2 has a probe for the distro you might be able to use: http://trac.mcs.anl.gov/projects/bcfg2/browser/doc/server/plugins/probes/group.txt.

Answered By: jsbillings

If the file /etc/debian_version exists, the distribution is Debian, or a Debian derivative. This file may have a release number; on my machine it is currently 6.0.1. If it is testing or unstable, it may say testing/unstable, or it may have the number of the upcoming release. My impression is that on Ubuntu at least, this file is always testing/unstable, and that they don’t put the release number in it, but someone can correct me if I am wrong.

Fedora (recent releases at least), have a similar file, namely /etc/fedora-release.

Answered By: Faheem Mitha

lsb_release -a. Works on Debian and I guess Ubuntu, but I’m not sure about the rest. Normally it should exist in all GNU/Linux distributions since it is LSB (Linux Standard Base) related.

Answered By: sakisk

I’d go with this as a first step:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE have a file called e.g. /etc/gentoo-release. Seems to be popular, check this site about release-files.

Debian & Ubuntu should have a /etc/lsb-release which contains release info also, and will show up with the previous command.

Another quick one is uname -rv. If the kernel installed is the stock distro kernel, you’ll usually sometimes find the name in there.

Answered By: Mat

In order of most probable success, these:

cat /etc/*version
cat /proc/version #linprocfs/version for FreeBSD when "linux" enabled
cat /etc/*release
uname -rv

cover most cases (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, *BSD and perhaps others.

Answered By: Eelvex

One-liner, fallbacks, one line of output, no errors.

( lsb_release -ds || cat /etc/*release || uname -om ) 2>/dev/null | head -n1
Answered By: Markus

2 ways from many:

1) use

lsb_release -a

I tested it on CentOS 5.5 and Ubuntu 10.04

the output for CentOS is:

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch 
Distributor ID: CentOS
Description:    CentOS release 5.5 (Final)
Release:        5.5
Codename:       Final

and for Ubuntu is:

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch
Distributor ID: CentOS
Description:    CentOS release 5.5 (Final)
Release:        5.5
Codename:       Final

2) enter the following command:

cat /etc/*-release

I tested it on CentOS 5.5 and Ubuntu 10.04, and it works fine.

Answered By: Sam
  1. lsb-* isn’t installed/doesn’t exist on base CentOS or Debian systems
  2. /proc/* doesn’t exist on OSX

Take a tip from JavaScript developers: Don’t test for the version, but for the capability. It’s not pretty, but it works. Expand as necessary.

function os_type {
case `uname` in
  Linux )
     LINUX=1
     which yum && { echo "CentOS"; return; }
     which zypper && { echo "openSUSE"; return; }
     which apt-get && { echo "Debian"; return; }
     ;;
  Darwin )
     DARWIN=1
     ;;
  * )
     # Handle AmigaOS, CPM, and modified cable modems.
     ;;
esac
}
Answered By: Orwellophile

This script works on Debian, (may need some tweak on Ubuntu)

#!/usr/bin/env bash

echo "Finding Debian/ Ubuntu Codename..."

CODENAME=`cat /etc/*-release | grep "VERSION="`
CODENAME=${CODENAME##*(}
CODENAME=${CODENAME%%)*}

echo "$CODENAME"
# => saucy, precise, lucid, wheezy, squeeze
Answered By: user9869932

For most modern Linux OS systems, the file /etc/os-release is really becoming standard and is getting included in most OS. So inside your Bash script you can just include the file, and you will have access to all variables described here (for example: NAME, VERSION, …)

So I’m just using this in my Bash script:

if [ -f /etc/os-release ]
then
        . /etc/os-release
else
        echo "ERROR: I need the file /etc/os-release to determine what my distribution is..."
        # If you want, you can include older or distribution specific files here...
        exit
fi
Answered By: Chris Maes

This command works for Debian based and Redhat based distributions:
Using tr filter, you convert the document to one-word-per-line format and then count the first line which contains the distribution name.

tr -s ' 11' '12' < /etc/issue | head -n 1
Answered By: Yahya Yahyaoui
python -m platform

sample outputs:

Ubuntu:

Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic

Debian:

Linux-4.14.117-grsec-grsec+-x86_64-with-debian-buster-sid

Centos:

Linux-3.10.0-957.1.3.el7.x86_64-x86_64-with-centos-7.6.1810-Core

Mac OS X:

Darwin-17.7.0-x86_64-i386-64bit

See platform module docs if you need a specific value from that line. For example, if you need the Linux distro name only, use

python -c "import platform;print(platform.linux_distribution()[0])"
Answered By: Ilya Kharlamov

Here is my simple chech_distro version. ^^;

#!/usr/bin/env bash
check_distro2(){
    if [[ -e /etc/redhat-release ]]
    then
      DISTRO=$(cat /etc/redhat-release)
    elif [[ -e /usr/bin/lsb_release ]]
    then
      DISTRO=$(lsb_release -d | awk -F ':' '{print $2}')
    elif [[ -e /etc/issue ]]
    then
      DISTRO=$(cat /etc/issue)
    else
      DISTRO=$(cat /proc/version)
    fi
    }

    check_distro2
    echo $DISTRO
Answered By: niceguy oh

Without version, just only dist:

cat /etc/issue | head -n +1 | awk '{print $1}'
Answered By: coanor

This was tested on Ubuntu 14 and CentOS 7

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'
Answered By: BsdHelper

I find a good script from here which works for most of common linux dists:

#! /bin/bash
# return an awkable string consisting of
#    unix OS type, or
#    Linux dist, or
#    a long guess (based on /proc), or
#    no clue

giveUp () {
   echo "Unknown"
   exit 0
}

# keep this easily awkable, prepending an initial clue
versionGuess () {
   if [ -e /proc/version ]; then
      echo -n "Unsure "
      cat /proc/version
      exit 0
   fi
   return 1
}

# if we have ignition, print and exit
gotDist () {
   [ -n "$1" ] && echo "$1" && exit 0
}

# we are only interested in a single word "dist" here
# various malformations can occur; admin will have to code appropately based on output
linuxRelease () {
   if [ -r /etc/lsb-release ]; then
      dist=$(grep 'DISTRIB_ID' /etc/lsb-release | sed 's/DISTRIB_ID=//' | head -1)
      gotDist "$dist"
   fi

   dist=$(find /etc/ -maxdepth 1 -name '*release' 2> /dev/null | sed 's//etc///' | sed 's/-release//' | head -1)
   gotDist "$dist"

   dist=$(find /etc/ -maxdepth 1 -name '*version' 2> /dev/null | sed 's//etc///' | sed 's/-version//' | head -1)
   gotDist "$dist"

   return 1
}

# start with uname and branch the decision from there
dist=$(uname -s 2> /dev/null)
if [ "$dist" = "Linux" ]; then
   linuxRelease
   versionGuess
   giveUp
elif [ -n "$dist" ]; then
   echo "$dist"
   exit 0
else
   versionGuess
   giveUp
fi

# we shouldn't get here
giveUp
# done
Answered By: Mithril

Since the question doesn’t specify restriction to /bin/sh etc, there is the solution with ruby shell interpreter.

There is a facter ruby gem, which gives you some facts about os OS, it analyzes OS release files, other data and prints to terminal screen. You can try is as follows, begining with rubygems installation:

# apt-get install ruby rubygems

Please use the case above that is eligible for your OS. Then install the gem itself.

# gem install facter

Then use:

$ facter

NOTE: See the facter gem sources to get more info in installation.

If somebody needs the distro as well:

#!/usr/bin/env bash

LINUX_VERSION_NAME=`lsb_release -sr`


# Distribution specific installation
if [[ ${LINUX_VERSION_NAME} == "18.04" ]]
then
    echo "It is: ${LINUX_VERSION_NAME}"

else
    echo "It is not ${LINUX_VERSION_NAME}"
fi

Output:

It is: 18.04

Change to: lsb_release -sc to get the distro:

LINUX_VERSION_NAME=`lsb_release -sc`


# Distribution specific installation
if [[ ${LINUX_VERSION_NAME} == "bionic" ]]
then
    echo "It is: ${LINUX_VERSION_NAME}"

else
    echo "It is not ${LINUX_VERSION_NAME}"
fi

Output:

It is: bionic
Answered By: jturi

Some distros use *-issue files, some use *-version, some use *-release, or any combination of those 3 variations. Dirty and dirty way :

[root@radio ~]# for file in /etc/{*issue*,*version*,*release*}; do [[ -f $file ]] || continue; echo -- $file; cat $file; done;
-- /etc/issue
S
Kernel r on an m

-- /etc/issue.net
S
Kernel r on an m
-- /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
-- /etc/centos-release-upstream
Derived from Red Hat Enterprise Linux 7.8 (Source)
-- /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

-- /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
-- /etc/system-release
CentOS Linux release 7.9.2009 (Core)
-- /etc/system-release-cpe
cpe:/o:centos:centos:7
[root@radio ~]#
Answered By: ychaouche
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.