78

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?

11
  • 1
    unix.stackexchange.com/questions/6345/… for Linux. uname -s should be enough outside Linux (expect possibly for the BSDs).
    – Mat
    Sep 24, 2013 at 18:51
  • Have you checked out facter? facter operatingsystem should do what you want on all the systems facter was made to work with.
    – Joseph R.
    Sep 24, 2013 at 18:53
  • @JosephR. looks good but is not installed by default.
    – terdon
    Sep 24, 2013 at 18:54
  • 1
    I pasted the facter code that gets the operating system name on pastebin. Find it here. It checks many different files to get the name reliably.
    – Joseph R.
    Sep 24, 2013 at 19:01
  • @JosephR. wow, that's a lot of files. I'll port that to bash when I get the chance, that should be portable enough. Thanks!
    – terdon
    Sep 24, 2013 at 19:19

11 Answers 11

86

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 
25
  • 1
    Note: Just did a quick check on machines with AIX and SunOS. They don't seem to have lsb_release installed (and after all, this is Unix not Linux stack). Problem with gcc is that some ppl now start using clang. Also you can never be sure which gcc was used to build (on systems I work with there are at least few versions on each). So my vote goes to Python solution as it seems to be installed now everywhere by default.
    – elmo
    Sep 25, 2013 at 9:16
  • @elmo - yes LSB is Linux Standard Base, so I wouldn't expect either AIX or SunOS to have it. My experience with SunOS is 15+ years, and the majority of vendors whose software I dealt with would usually provide there own shell script similar to the ones I referenced above. Until Solaris 11, Python was not an option. And this is what makes it a difficult nut to crack. If you provide software that needs to run on Solaris 9, 10, 11, AIX, and a couple of Linux distros (SUSE, Ubntu, and RHEL) what do you do? Python is not an option, so you're left with a hand coded shell script.
    – slm
    Sep 25, 2013 at 9:29
  • @elmo - gcc though, an option, doesn't appear to be that appealing to me either. It seems wrought with too many problems, I was demonstrating it merely as an option.
    – slm
    Sep 25, 2013 at 9:31
  • @elmo - look at the code behind that function, hg.python.org/cpython/file/2.7/Lib/platform.py#l259. Big surprise it's using LSB!
    – slm
    Sep 25, 2013 at 9:34
  • @slm: I have access to machine with SunOS 5.10 (which I assume is 10 in your list - I am not that familiar with version numbers/conventions of Sun) and it does have a Python. I have access to machine with AIX 7 and it does have Python. Linux machines obviously have it also. So still Python looks like most portable choice. As for Sun below 10 I am not sure why it wouldn't allow Python to be installed (admittedly current install is lacking i.e. ncurses and ctypes, so who knows). As for Python using LSB it is not surprising at all for Linux if it is default approach.
    – elmo
    Sep 26, 2013 at 10:49
19

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.

9
  • 7
    "I'm sorry if you find duplicates in this list, I produced it quickly with grep." ... | uniq?
    – new123456
    Sep 24, 2013 at 23:12
  • @new123456 Right. Thanks. The key word here is "quickly" :)
    – Joseph R.
    Sep 24, 2013 at 23:26
  • Sorry about unaccepting this but @slm's answer is just too comprehensive to ignore :).
    – terdon
    Sep 25, 2013 at 1:36
  • 5
    what about /etc/os-release ? Jul 24, 2014 at 15:57
  • 2
    @new123456 Technically, that should be ... | sort -u. uniq only finds adjacent unique elements. Feb 18, 2016 at 18:42
10

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])"
2
  • If you are tempted to use this option make sure your OS is supported: hg.python.org/cpython/file/2.7/Lib/platform.py#l259. If not you can add more to the list: coderwall.com/p/cwrenq
    – slm
    Sep 25, 2013 at 9:37
  • 2
    This will not work with ancient Linux distributions. For example: SuSE 7.0 had Python 1.5.2 and the platform module has been added not before the advent of Python 2.3 in 2003 ;-)
    – pefu
    Oct 27, 2015 at 13:56
6

/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."

7
  • Ah, that's a good suggestion, +1. It might not always work though The file /etc/issue is a text file which contains a message or system identification to be printed before the login prompt. It seems to be up to the sysadmin to write whatever he/she desires.
    – terdon
    Sep 24, 2013 at 18:49
  • 3
    /etc/issue is completely unreliable. (I've see systems in version X.Y with an /etc/issue banner saying they were Y.Z following bad patch management. It can contain absolutely anything.)
    – Mat
    Sep 24, 2013 at 18:52
  • It is recommended to fill that file with. legal stuff like who is allowed to login.
    – Nils
    Sep 24, 2013 at 19:06
  • Recommended by security guidelines and auditors. There was once a case at law where a hacker came away without punishment, because there was WELCOME in /etc/issue
    – Nils
    Sep 24, 2013 at 19:36
  • @drewbenn the man page says what I quoted in my first comment, there is nothing there about its needing to contain the system info. It just often does.
    – terdon
    Sep 24, 2013 at 19:42
6

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.

1
  • Thanks but neither is a help when it comes to Unix or any other non-Linux *nix.
    – terdon
    Sep 24, 2013 at 19:19
4

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)
4
  • Wouldn't for f in /etc/*{_version,...*-release}; do [ -f "$f" ] && echo ${f:5:${#f}-13} ; done work equally well on all of them? I don't understand why you would first find all files in /etc.
    – terdon
    May 8, 2014 at 13:43
  • Thank you for your feedback, terdon, but your command gives 0 lines in at least Cent OS and Fedora
    – scrutari
    May 13, 2014 at 12:05
  • 1
    0pointer.de/blog/projects/os-release.html for FAQ
    – weberjn
    Apr 9, 2017 at 10:05
  • 1
    I've always liked: grep -Eh -- "DISTRIB_DESCRIPTION=|PRETTY_NAME=" /etc/*{_version,*-release} 2>/dev/null | cut -d= -f2 | tr -d "\"" | sort -u
    – ikaerom
    Nov 17, 2023 at 23:05
2

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.

4
  • Thanks, but the accepted answer already addresses this in the quote in the end which explains that /etc/os-release is going to become more standard. However, that file isn't always there on all systems which is why the accepted answer gives more portable alternatives. Also, I don't know why you're mentioning C code, the question isn't about invoking anything from C.
    – terdon
    Nov 6, 2018 at 10:35
  • @terdon I am just curious what are those systems in 2018 where /etc/os-release is absent? I guess that their user base is miserable compared to systems where lsb_release is not shipped by default. At least I couldn't use your accepted answer on Fedora. As for C comment, it is not my, but a quote from systemd 0pointer.de link that I provided. Nov 6, 2018 at 15:16
  • Yes, I know it's not yours, I was just wondering why you felt that a quote about C code was relevant. And as far as I know, os-release is mostly or exclusively a Linux thing. It seems to be defined by FreeDesktop.org, so maybe some Unix flavors also use it, but I doubt you'll find it in most or in embedded systems or any non-GUI system etc. Finally, don't forget that many places still use very old machines for reasons of stability.
    – terdon
    Nov 6, 2018 at 15:55
  • The quote is about lsb_release and you can replace C with Go and get the same argument. The overhead of running lsb_release is much higher from both security and performance points than just parsing static file. I don't believe in very old machines providing stability. Heartbleed and friends should have taken them away long ago, so just use /etc/os-release Nov 10, 2018 at 12:28
1

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.

1
  • Drawback is that this is a static string that is not automatically maintained.
    – Nils
    Sep 24, 2013 at 19:17
1

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

4
  • 1
    Who is 'we'? And how about Unix?
    – terdon
    Sep 24, 2013 at 19:15
  • @terdon we is our team at work. On Unix you can do the same if the corresponding extension is compiled into snmpd.
    – Nils
    Sep 24, 2013 at 19:39
  • Ah, I thought you were a part of some standards group :)
    – terdon
    Sep 24, 2013 at 19:42
  • @terdon You start developing site-standards when you have to manage more than 80 servers. We developed this method so we could monitor wether the os is outdated (EoL minor or even major number)
    – Nils
    Sep 24, 2013 at 19:50
1

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
5
  • 3
    don't parse output of ls! Sep 24, 2013 at 23:17
  • @heinrich5991 why not?
    – Sammitch
    Sep 24, 2013 at 23:31
  • Technically, he isn't parsing the output of ls. He's lexing the output of ls. But yeah... This is wrong because /etc/issue is completely unreliable. Completely, entirely, totally unreliable. Also, your assumption that no one might put a non-os-related file ending in 'release' or 'version' is unwise. Feb 18, 2016 at 18:50
  • @ParthianShot So mainly you want to complain about the second and third levels of fallback in the case that the more reliable options are not available?
    – Sammitch
    Feb 19, 2016 at 0:58
  • @Sammitch more reliable options Well, for one thing, there's only one option. So even assuming I agreed with your assumption that it's more reliable (which I don't), let's not start pluralizing things. Second, if someone actually used your solution, and it utterly failed half the time, they wouldn't be consoled by the fact that it was failing in an "else if". None of my systems have lsb installed by default. Feb 19, 2016 at 14:09
1

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.

4
  • What's snpwalk? Where can I find it? Also, that just prints "Linux", no distribution information (which is what I want, uname can give me Linux). Does it work on non-Linux OSs? On UNIX say, or BSD or OSX?
    – terdon
    Nov 13, 2014 at 14:52
  • snmpwalk is a Linux command line utility. It doesn't just print "Linux" it also prints the kernel version which is really the only thing you need. If SNMP is configured on your other hosts, whether it is UNIX, BSD, OSX, snmpwalk will work as it is a standard (v1|v2c|v3), and it will even work across the water on Windows hosts as well. See also snmpget or snmpgetnext.
    – xpros
    Nov 13, 2014 at 16:30
  • Sounds good but could you please edit your answer and explain where we can find it. It's not int he Debian repos for example. Also, please explain what it gives that uname -a doesn't and how it can tell me the name of the distribution which is what this question is about. Anyway, even assuming it can return this info, seeing as it's a non-standard utility and needs to be installed, I'm not sure it would be useful here. The idea is to log on to a remote system and find out the OS (including distribution if it's Linux).
    – terdon
    Nov 13, 2014 at 16:42
  • it also prints the kernel version which is really the only thing you need But... that's the whole point of this question. If that was really all you needed, you could just use uname -a. The kernel is an important part of an operating system, but it's not the entire operating system. Filesystem layout and userland utilities (e.g. package manager) matter. Feb 18, 2016 at 18:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .