How can I reliably get the operating system's name?

Say I am logged into a remote system, how can I know what it’s running? On most modern Linuxes (Linuces?), you have the lsb_release command:

$ lsb_release -ic    
Distributor ID: LinuxMint
Codename:       debian

Which as far as I can tell just gives the same info as /etc/lsb-release. What if that file is not present? I seem to recall that the lsb_release command is relatively new so what if I have to get the OS of an older system?

In any case, lsb stands for Linux Standard Base so I am assuming it won’t work on non-Linux Unices. As far as I know, there is no way of getting this information from uname so how can I get this on systems that do not use lsb_release?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

lsb_release -a is likely going to be your best option for finding this information out, and being able to do so in a consistent way.

History of LSB

The lsb in that command stands for the project Linux Standards Base which is an umbrella project sponsored by the Linux Foundation to provide generic methods for doing basic kinds of things on various Linux distros.

The project is voluntary and vendors can participate within the project as just a user and also as facilitators of the various specifications around different modules that help to drive standardization within the different Linux distributions.

excerpt from the charter

The LSB workgroup has, as its core goal, to address these two
concerns. We publish a standard that describes the minimum set of APIs
a distribution must support, in consultation with the major
distribution vendors. We also provide tests and tools which measure
support for the standard, and enable application developers to target
the common set. Finally, through our testing work, we seek to prevent
unnecessary divergence between the distributions.

Useful links related to LSB

Criticisms

There are a number of problems with LSB that make it problematic for distros such as Debian. The forced usage of RPM being one. See the Wikipedia article for more on the matter.

Novell

If you search you’ll possibly come across a fairly dated looking page titled: Detecting Underlying Linux Distro from Novell. This is one of the few places I”ve seen an actual list that shows several of the major distros and how you can detect what underlying one you’re using.

excerpt

Novell SUSE         /etc/SUSE-release
Red Hat             /etc/redhat-release, /etc/redhat_version
Fedora              /etc/fedora-release
Slackware           /etc/slackware-release, /etc/slackware-version
Debian              /etc/debian_release, /etc/debian_version,
Mandrake            /etc/mandrake-release
Yellow dog          /etc/yellowdog-release
Sun JDS             /etc/sun-release
Solaris/Sparc       /etc/release
Gentoo              /etc/gentoo-release
UnitedLinux         /etc/UnitedLinux-release
ubuntu              /etc/lsb-release

This same page also includes a handy script which attempts to codify for the above using just vanilla uname commands, and the presence of one of the above files.

NOTE: This list is dated but you could easily drop the dated distros such as Mandrake from the list and replace them with alternatives. This type of a script might be one approach if you’re attempting to support a large swath of Solaris & Linux variants.

Linux Mafia

More searching will turn up the following page maintained on Linuxmafia.com, titled: /etc/release equivalents for sundry Linux (and other Unix) distributions. This is probably the most exhaustive list to date that I’ve seen. You could codify this list with a case/switch statement and include it as part of your software distribution.

In fact there is a script at the bottom of that page that does exactly that. So you could simply download and use the script as 3rd party to your software distribution.

script

#!/bin/sh
# Detects which OS and if it is Linux then it will detect which Linux
# Distribution.

OS=`uname -s`
REV=`uname -r`
MACH=`uname -m`

GetVersionFromFile()
{
    VERSION=`cat $1 | tr "\n" ' ' | sed s/.*VERSION.*=\ // `
}

if [ "${OS}" = "SunOS" ] ; then
    OS=Solaris
    ARCH=`uname -p` 
    OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
elif [ "${OS}" = "AIX" ] ; then
    OSSTR="${OS} `oslevel` (`oslevel -r`)"
elif [ "${OS}" = "Linux" ] ; then
    KERNEL=`uname -r`
    if [ -f /etc/redhat-release ] ; then
        DIST='RedHat'
        PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
        REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
    elif [ -f /etc/SuSE-release ] ; then
        DIST=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
        REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
    elif [ -f /etc/mandrake-release ] ; then
        DIST='Mandrake'
        PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
        REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
    elif [ -f /etc/debian_version ] ; then
        DIST="Debian `cat /etc/debian_version`"
        REV=""

    fi
    if [ -f /etc/UnitedLinux-release ] ; then
        DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
    fi

    OSSTR="${OS} ${DIST} ${REV}(${PSUEDONAME} ${KERNEL} ${MACH})"

fi

echo ${OSSTR}

NOTE: This script should look familiar, it’s an up to date version of the Novell one!

Legroom script

Another method I’ve seen employed is to roll your own script, similar to the above Novell method but making use of LSB instead. This article titled: Generic Method to Determine Linux (or UNIX) Distribution Name, shows one such method.

# Determine OS platform
UNAME=$(uname | tr "[:upper:]" "[:lower:]")
# If Linux, try to determine specific distribution
if [ "$UNAME" == "linux" ]; then
    # If available, use LSB to identify distribution
    if [ -f /etc/lsb-release -o -d /etc/lsb-release.d ]; then
        export DISTRO=$(lsb_release -i | cut -d: -f2 | sed s/'^\t'//)
    # Otherwise, use release info file
    else
        export DISTRO=$(ls -d /etc/[A-Za-z]*[_-][rv]e[lr]* | grep -v "lsb" | cut -d'/' -f3 | cut -d'-' -f1 | cut -d'_' -f1)
    fi
fi
# For everything else (or if above failed), just use generic identifier
[ "$DISTRO" == "" ] && export DISTRO=$UNAME
unset UNAME

This chunk of code could be included into a system’s /etc/bashrc or some such file which would then set the environment variable $DISTRO.

gcc

Believe it or not another method is to make use of gcc. If you query the command gcc --version you’ll get the distro that gcc was built for, which is invaribly the same as the system it’s running on.

Fedora 14

$ gcc --version
gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Copyright (C) 2010 Free Software Foundation, Inc.

CentOS 5.x

$ gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)
Copyright (C) 2006 Free Software Foundation, Inc.

CentOS 6.x

$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3)
Copyright (C) 2010 Free Software Foundation, Inc.

Ubuntu 12.04

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.

TL;DR;

So which one should I use? I would tend to go with lsb_release -a for any Linux distributions that I would frequent (RedHat, Debian, Ubuntu, etc.). For situations where you’re supporting systems that don’t provide lsb_release I’d roll my own as part of the distribution of software that I’m providing, similar to one of the above scripts.

UPDATE #1: Follow-up with SuSE

In speaking with @Nils in the comments below it was determined that for whatever reason, SLES11 appeared to drop LSB from being installed by default. It was only an optional installation, which seemed counter for a package that provides this type of key feature.

So I took the opportunity to contact someone from the OpenSuSE project to get a sense of why.

excerpt of email

Hi Rob,

I hope you don't mind me contacting you directly but I found your info here: 
https://en.opensuse.org/User:Rjschwei. I participate on one of the StackExchange 
sites, Unix & Linux and a question recently came up regarding the best option 
for determining the underlying OS.

http://unix.stackexchange.com/questions/92199/how-can-i-reliably-get-the-operating-systems-name/92218?noredirect=1#comment140840_92218

In my answer I suggested using lsb_release, but one of the other users mentioned 
that this command wasn't installed as part of SLES11 which kind of surprised me. 
Anyway we were looking for some way to confirm whether this was intentionally 
dropped from SLES or it was accidental.

Would you know how we could go about confirming this one way or another?

Thanks for reading this, appreciate any help and/or guidance on this.

-Sam Mingolelli
http://unix.stackexchange.com/users/7453/slm

Here’s Rob’s response

Hi,

On 10/01/2013 09:31 AM, Sam Mingo wrote:
- show quoted text -

lsb_release was not dropped in SLES 11. SLES 11 is LSB certified. However, it 
is not installed by default, which is consistent with pretty much every other
distribution. The lsb_release command is part of the lsb-release package.

At present almost every distribution has an entry in /etc such as 
/etc/SuSE-release for SLES and openSUSE. Since this is difficult for ISVs and 
others there is a standardization effort going on driven by the convergence to 
systemd. The standard location for distribution information in the future will 
be /etc/os-release, although Ubuntu will probably do something different.

HTH,    
Robert

--  Robert Schweikert                           MAY THE SOURCE BE WITH YOU    
SUSE-IBM Software Integration Center                   LINUX    
Tech Lead    
Public Cloud Architect 

Solution 2

Since you probably won’t be able to install facter on a remote server, you can mimic what it does to find the OS name. The Ruby code for the operatingsystem fact can be found here on pastebin. Basically, it looks through the different *-release files and others to determine the OS name.

Some of the files it looks at:

/etc/debian_version
/etc/gentoo-release
/etc/fedora-release
/etc/mandriva-release
/etc/mandrake-release
/etc/meego-release
/etc/arch-release
/etc/oracle-release
/etc/enterprise-release
/etc/ovs-release
/etc/vmware-release
/etc/redhat-release
/etc/SuSE-release
/etc/bluewhite64-version
/etc/slamd64-version
/etc/slackware-version
/etc/alpine-release
/etc/system-release
/etc/centos-release

I’m sorry if you find duplicates in this list, I produced it quickly with grep. Should be fairly easy (albeit a bit tedious) to port this to a POSIX shell script.

Solution 3

In case you have python installed (doesn’t matter whether Python 3 or Python 2), you can find out the distribution name without reinventing the wheel:

python -c "import platform;print(platform.linux_distribution()[0])"

Solution 4

/etc/issue should contain the release information. I am fairly certain I’ve seen it on Solaris systems. Here is the file from a modern Debian system:

$ cat /etc/issue
Debian GNU/Linux 7 \n \l

$ 

/etc/issue is also mentioned in the FHS (which isn’t solely for Linux systems), although it is “optional.”

Solution 5

You can’t reliably get the distro name from a single command across all distros. Some are available via /etc/*-release and others are available via the ‘lsb-release’ command.

Solution 6

I used this shell command to get a string indicating Linux distribution:

for f in $(find /etc -type f -maxdepth 1 \( ! -wholename /etc/os-release ! -wholename /etc/lsb-release -wholename /etc/\*release -o -wholename /etc/\*version \) 2> /dev/null); do echo ${f:5:${#f}-13}; done;

this command is based on answers of Joseph R. and slm.

It just seeks for files like /etc/{osname}-release or /etc/{osname}_version and prints particular os name.

It worked in

  • CentOS (centos)
  • RedHat (redhat)
  • Debian (debian)
  • Arch (arch)
  • OpenSUSE (OpenSUSE)
  • Fedora (fedora)
  • Ubuntu (debian)

Solution 7

SNMP is an ubiquitous enough protocol so as to be found in many different kinds of GNU/Linux distributions and UNIX systems.

The system.sysDescr.0 object in the SNMPv2-MIB can help you find out which OS you are contacting, provided there’s an SNMP daemon running in the target system:

Description

A textual description of the entity. This value should
include the full name and version identification of the
system’s hardware type, software operating-system, and
networking software.

Status: current

Access: read-only

The snmpget(1) manpage explains how to retrieve this value with examples.

Solution 8

Since there is no common way to do so, we defined an release-string via the snmp exec-command.

The task of that command is to print out distro and the current major/minor version of the os.

On RH and clones we parse /etc/redhat-release, on SuSe SuSe-release…

Solution 9

From what I’ve managed to glean from this thread you should be able to get the info from damn-near any system using:

if which lsb_release &>> /dev/null; then
    lsb_release -a
elif [ -r /etc/issue ]; then
    cat /etc/issue
else
    ls /etc/ | grep -e '[_-]release$' -e '[_-]version$' | xargs -I % -n 1 cat /etc/%
fi

Solution 10

If a situation called for it, you could find out remotely using snmpwalk [or the SNMP protocal in general]. An example is below:

snmpwalk -Os -c <snmp community string> -v1 <hostname> sysDescr.0

OUPUT:
sysDescr.0 = STRING: Linux example.hostname.com 2.6.32-358.23.2.el6.x86_64 #1 SMP Sat Sep 14 05:32:37 EDT 2013 x86_64

The key to the reliability is whether SNMP is setup correctly in your environment, all hosts have snmp running with proper community strings setup.

Solution 11

Use /etc/os-release:

$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.10 (Cosmic Cuttlefish)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.10"
VERSION_ID="18.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=cosmic
UBUNTU_CODENAME=cosmic

The reasons are well explained in a FAQ by a link http://0pointer.de/blog/projects/os-release.html gratuitously provided by @weberjn in this comment. I just list here one argument against using the lsb_release which is so far the top upvoted answer from 2013.

There’s already the lsb_release tool for this, why don’t you just use that? Well, it’s a very strange interface: a shell script you have to invoke (and hence spawn asynchronously from your C code), and it’s not written to be extensible. It’s an optional package in many distributions, and nothing we’d be happy to invoke as part of early boot in order to show a welcome message. (In times with sub-second userspace boot times we really don’t want to invoke a huge shell script for a triviality like showing the welcome message). The lsb_release tool to us appears to be an attempt of abstracting distribution checks, where standardization of distribution checks is needed. It’s simply a badly designed interface. In our opinion, it has its use as an interface to determine the LSB version itself, but not for checking the distribution or version.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply