Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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... No?

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"
share|improve this question
    
Are you sure +-release works? Effectively you're looking assuming it will be /etc/lsb-release, so perhaps just call it that. –  Mikel Jan 24 '11 at 5:57
    
@Mikel: I replaced * with + to avoid the comment formating, it should be etc/*-release, it seems to work. –  Alix Axel Jan 24 '11 at 6:20
5  
Never introduce a syntax error to get formatting right. Besides, the formatting is wrong only in the preview, the final view picks up the syntax from the tags. –  Gilles Jan 24 '11 at 21:07

13 Answers 13

up vote 56 down vote accepted

Most recent distributions have a tool called lsb_release. Your /etc/*-release will be using /etc/lsb-release anyway, so if that file is there, running lsb_release should work too.

I think uname to get ARCH is still the best way.

e.g.

OS=$(lsb_release -si)
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$(lsb_release -sr)

Or you could just source /etc/lsb-release:

. /etc/lsb-release
OS=$DISTRIB_ID
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$DISTRIB_RELEASE

If you have to be compatible with older distributions, there is no single file you can rely on. Either fall back to the output from uname, e.g.

OS=$(uname -s)
ARCH=$(uname -m)
VER=$(uname -r)

or handle each distribution separately:

if [ -f /etc/debian_version ]; then
    OS=Debian  # XXX or Ubuntu??
    VER=$(cat /etc/debian_version)
elif [ -f /etc/redhat-release ]; then
    ...

Of course, you can combine all this:

ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')

if [ -f /etc/lsb-release ]; then
    . /etc/lsb-release
    OS=$DISTRIB_ID
    VER=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
    OS=Debian  # XXX or Ubuntu??
    VER=$(cat /etc/debian_version)
elif [ -f /etc/redhat-release ]; then
    # TODO add code for Red Hat and CentOS here
    ...
else
    OS=$(uname -s)
    VER=$(uname -r)
fi

Finally, your ARCH 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.

share|improve this answer
1  
I would check for lsb_release and use it if available, but it isn't available everywhere. For instance, it isn't in the default install of Fedora 14. –  Steven D Jan 24 '11 at 5:47
    
Really? Did you try spelling it with - and _? Maybe it's in /lib/lsb or somewhere like that. What does rpm -qa "lsb*" print? –  Mikel Jan 24 '11 at 5:56
1  
rpm -qa "lsb* prints nothing. According to yum provides */lsb_release it is contained in a package called redhat-lsb which I guess is not installed by default. However, I'm not a Fedora expert, these are just the results from a random Fedora VM I have and could be very wrong. –  Steven D Jan 24 '11 at 6:01
1  
Just installed Fedora 14 in a VM, and there is no lsb-release, as you said. –  Mikel Jan 24 '11 at 6:07
2  
Don't use $OS, $VERSION, etc -- by convention, we capitalize environment variables (PAGER, EDITOR, SHELL, ...) and internal shell variables (BASH_VERSION, RANDOM, ...). All other variable names should contain at least one lowercase letter. This convention avoids accidentally overriding environmental and internal variables. –  Chris Down Sep 16 '11 at 20:18

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

share|improve this answer

If the file /etc/debian_version, it 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.

share|improve this answer

Type below command

cat /etc/issue

share|improve this answer
    
Which distributions will this work with? –  apoorv020 Mar 29 '11 at 16:40
    
This worked with Ubuntu Lucid but not with Fedora 8. –  apoorv020 Mar 29 '11 at 16:51
3  
/etc/issue is usually modified by administrators thus it's not guaranteed that it will include version information. –  faif Mar 29 '11 at 17:33
    
Works on Mandriva 2010.2 –  Mahmoud Hossam Mar 29 '11 at 21:00
    
Works on OpenSUSE and andLinux. –  TheIndependentAquarius Aug 10 '11 at 9:48

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.

share|improve this answer
1  
It's not installed by default on Gentoo. It wasn't by default on Fedora either at some point (probably is now though) –  Mat Mar 29 '11 at 19:13
1  
This worked on Debian squeeze, Fedora 14, and OpenSUSE 11.3. On Debian and SUSE the package containing lsb_release was lsb-release, on Fedora it was redhat-lsb. It was already installed on Debian and SUSE, but not on Fedora. I think this is the best answer so far. +1. –  Faheem Mitha Mar 29 '11 at 20:09
    
lsb_release is not part of the CentOS 6 minimal install. –  a coder Oct 8 '13 at 15:30
    
lsb_release -a returns "-bash: lsb_release: command not found" on Raspberry with Raspbian (Debian 7.1 derived). –  Peter Mortensen Jun 5 at 11:32

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.

share|improve this answer
    
On Debian, that's uname -a. –  Tshepang Mar 29 '11 at 20:31
1  
doesn't uname -rv contain the info though? uname -a will print things like type of processor and hostname that are irrelevant here. (But both kernel release (-r) and version (-v) are necessary, not all distros do it the same there) –  Mat Mar 29 '11 at 20:34
    
uname -r gives 2.6.32-5-686-bigmem and uname -v gives #1 SMP Tue Mar 8 22:14:55 UTC 2011 on Debian 6. uname -a OTOH gives Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux. –  Tshepang Mar 29 '11 at 22:22
    
the second part of uname -a is -n, i.e. nodename == hostname. so I'd say uname will not be interesting on Debian. Come to think of it, I'm not sure it is so useful on RedHat either. –  Mat Mar 29 '11 at 22:26
    
Oh, ok. So it's just by luck that I set my hostname as default, debian. –  Tshepang Mar 29 '11 at 22:29

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.

share|improve this answer
    
cat /etc/*version does not work (there is no such file) on CentOS (at least on 6.4) –  om-nom-nom Oct 23 '13 at 12:32

Most of the time lsb_release -a or lsb_release -si will work.

Or you can use a script like this to handle the case where lsb_release is not available.

if [ -f /etc/lsb-release ]; then
    . /etc/lsb-release
    DISTRO=$DISTRIB_ID
elif [ -f /etc/debian_version ]; then
    DISTRO=Debian
    # XXX or Ubuntu
elif [ -f /etc/redhat-release ]; then
    DISTRO="Red Hat"
    # XXX or CentOS or Fedora
else
    DISTRO=$(uname -s)
fi

echo "$DISTRO"

If you're typing it interactively, and so prefer something easy to type, and don't care what the output is, you can just do.

lsb_release -sd || cat /etc/*release
share|improve this answer
1  
This will not work on modern Fedoras as there is no /etc/lsb-release file anymore. Add /etc/os-release too. –  lzap Apr 17 '13 at 12:16
    
@lzap But Fedora still has /etc/redhat-release, right? I'm grouping Red Hat and Fedora together, but you could add more specific code under the /etc/redhat-release branch, e.g. by reading the contents of /etc/redhat-release. –  Mikel Apr 29 '13 at 17:22
    
Right, thats true. –  lzap Apr 30 '13 at 11:27
1  
CentOS uses /etc/centos-release –  a coder Oct 8 '13 at 15:31

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

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om
share|improve this answer
2  
“No errors”? Yes errors: “bash: lsb_release: command not found”. –  manatwork Nov 22 '11 at 14:48

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.

share|improve this answer
    
lsb_release is not in CentOS 6 (the min install fwiw) –  a coder Oct 8 '13 at 15:34
    
lsb_release -a returns "-bash: lsb_release: command not found" on Raspberry with Raspbian (Debian 7.1 derived). –  Peter Mortensen Jun 5 at 11:34
  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, test 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 AmgiaOS, CPM, and modified cable modems here.
     ;;
esac
}  
share|improve this answer
    
Yum could very well be Red Hat, Scientific Linux, or Fedora. There was an apt command for Fedora mimiking Debian's. And so on. Just clasifying anything with yum as CentOS gives you a range of supported systems from Red Hat 4 to Fedora 18, that is some 8 years of Linux history right there. If you need to know if <foo> is supported, specifically check for <foo> instead of guessing based on (unreliable) distribution identification! Sure, it leads to something of the ilk of autotools, but that can't be helped (just thank $DEITY that the Unix wars are over). –  vonbrand Jan 18 '13 at 3:21
    
@vonbrand indeed, it is as you say. i don't attempt to differentiate between sub-flavours. and the order i check in (hopefully) removes most tricky situations (RHEL with apt-get installed), although i didn't do a lot of research. if RHEL can have apt-get installed, and Ubuntu users have yum... well, you're just bang out of luck. –  Orwellophile Jan 22 '13 at 2:40

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
share|improve this answer

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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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