Wie kann ich den Distributionsnamen und die Versionsnummer in einem einfachen Shell-Skript ermitteln?

191

Ich arbeite an einem einfachen Bash-Skript, das auf Ubuntu- und CentOS-Distributionen ausgeführt werden kann (Unterstützung für Debian und Fedora / RHEL wäre von Vorteil), und ich muss den Namen und die Version der Distribution kennen, die das Skript ausführt ( um bestimmte Aktionen auszulösen, zum Beispiel das Anlegen von Repositories). Bisher habe ich Folgendes:

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

Dies scheint zu funktionieren und als Release-Name zurückzukehren ubuntuoder centos(ich habe es noch nicht mit anderen versucht). Ich habe jedoch das Gefühl, dass es einen einfacheren und zuverlässigeren Weg geben muss, dies herauszufinden - stimmt das?

Bei RedHat funktioniert das nicht. / etc / redhat-release enthält: Redhat Linux Entreprise Version 5.5

Die Version ist also nicht das dritte Wort, Sie sollten Folgendes verwenden:

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"
Alix Axel
quelle
Sind Sie sicher, dass es +-releasefunktioniert? Sie gehen davon aus, dass dies tatsächlich der Fall /etc/lsb-releaseist. Nennen Sie es also einfach so.
Mikel
@Mikel: Ich ersetzt *mit +dem Kommentar Formatierung zu vermeiden, sollte es sein etc/*-release, scheint es zu funktionieren.
Alix Axel
8
Führen Sie niemals einen Syntaxfehler ein, um die Formatierung korrekt durchzuführen. Außerdem ist die Formatierung nur in der Vorschau falsch, die Endansicht übernimmt die Syntax aus den Tags.
Gilles
Warum erwähnt das niemand uname -rv | grep -i "name_of_distro"und benutzt einen Exit-Code?
Flüchtling

Antworten:

182

OSUnd zu bekommen VER, scheint der neueste Standard zu sein /etc/os-release. Davor gab es lsb_releaseund /etc/lsb-release. Vorher mussten Sie für jede Distribution nach unterschiedlichen Dateien suchen.

Folgendes würde ich vorschlagen

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

Ich denke unamezu bekommen ARCHist immer noch der beste Weg. Aber das Beispiel, das Sie angegeben haben, behandelt offensichtlich nur Intel-Systeme. Ich würde es entweder so nennen BITS:

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

Oder ändern Sie ARCH, um die gebräuchlicheren und doch eindeutigeren Versionen zu werden: x86und x64oder ähnlich:

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

aber das liegt natürlich an dir.

Mikel
quelle
2
Ich würde nach lsb_release suchen und es verwenden, wenn es verfügbar ist, aber es ist nicht überall verfügbar. Zum Beispiel ist es nicht in der Standardinstallation von Fedora 14 enthalten.
Steven D
"Ja wirklich?" Hast du versucht, es mit -und zu buchstabieren _? Vielleicht ist es in /lib/lsboder irgendwo so. Was rpm -qa "lsb*"druckt?
Mikel
1
rpm -qa "lsb*druckt nichts. Demnach ist yum provides */lsb_releasees in einem Paket namens redhat-lsb enthalten, das meiner Meinung nach nicht standardmäßig installiert ist. Ich bin jedoch kein Fedora-Experte. Dies sind nur die Ergebnisse einer zufälligen Fedora-VM, die ich habe und die möglicherweise sehr falsch ist.
Steven D
3
Gerade Fedora 14 in einer VM installiert, und es gibt keine lsb-release, wie Sie sagten.
Mikel
5
Verwenden Sie nicht $OS, $VERSIONusw - vereinbarungs wir nutzen Umgebungsvariablen (PAGER, REDAKTION, SHELL, ...) und interne Shell - Variablen (BASH_VERSION, RANDOM, ...). Alle anderen Variablennamen sollten mindestens einen Kleinbuchstaben enthalten. Diese Konvention vermeidet das versehentliche Überschreiben von Umgebungsvariablen und internen Variablen.
Chris Down
58

Ich würde damit als ersten Schritt gehen:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE haben eine Datei namens zB /etc/gentoo-release. Scheint populär zu sein, schauen Sie auf dieser Seite nach Release-Dateien .

Debian & Ubuntu sollte auch eine haben, /etc/lsb-releasedie Release-Informationen enthält und mit dem vorherigen Befehl angezeigt wird.

Ein weiterer schneller ist uname -rv. Wenn es sich bei dem installierten Kernel um den Standard-Distributionskernel handelt, finden Sie in der Regel manchmal den Namen darin.

Matte
quelle
Unter Debian ist das so uname -a.
Tshepang
2
nicht uname -rvjedoch die Informationen enthalten? uname -adruckt Dinge wie Prozessortyp und Hostname, die hier nicht relevant sind. (Aber sowohl kernel release ( -r) als auch version ( -v) sind notwendig, nicht alle Distributionen machen es dort gleich)
Mat
uname -r gibt 2.6.32-5-686-bigmemund uname -v gibt #1 SMP Tue Mar 8 22:14:55 UTC 2011unter Debian 6. uname -a OTOH gibt Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
Tshepang
Der zweite Teil von uname -aist -n, dh Knotenname == Hostname. Ich würde also sagen uname, dass Debian nicht interessant sein wird. Ich bin mir nicht sicher, ob es für RedHat so nützlich ist.
Mat
Oh ok. Es ist also nur ein Glücksfall, dass ich meinen Hostnamen als Standard festgelegt habe debian.
Tshepang
36

lsb_release -a. Funktioniert mit Debian und ich denke Ubuntu, aber ich bin nicht sicher, was den Rest betrifft. Normalerweise sollte es in allen GNU / Linux-Distributionen vorhanden sein, da es mit LSB (Linux Standard Base) zusammenhängt.

Sakisk
quelle
3
Es ist nicht standardmäßig auf Gentoo installiert. Auf Fedora war es auch nicht standardmäßig eingestellt (wahrscheinlich ist es das jetzt)
Mat
2
Dies funktionierte unter Debian Squeeze, Fedora 14 und OpenSUSE 11.3. Unter Debian und SUSE war das Paket mit lsb_release lsb-release, unter Fedora redhat-lsb. Es war bereits auf Debian und SUSE installiert, aber nicht auf Fedora. Ich denke das ist die beste Antwort bis jetzt. +1.
Faheem Mitha
3
lsb_release ist nicht Teil der Minimalinstallation von CentOS 6.
ein Kodierer
1
lsb_release -a gibt "-bash: lsb_release: Befehl nicht gefunden" auf Raspberry mit Raspbian (von Debian 7.1 abgeleitet) zurück.
Peter Mortensen
lsb_release -a funktioniert auf Red Hat Enterprise Linux Server Version 6.6 (Santiago)
jwilleke
21

Einzeilig, Fallbacks, eine Ausgabezeile, keine Fehler.

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om
Markus
quelle
Schön, danke. Beachten Sie, dass dies unter Mac OS X immer noch nicht funktioniert, aber unter Ubuntu und CentOS (die drei, die ich zur Hand habe).
Wildcard
2
Brillant! Warum so eine schöne Antwort nicht ganz oben?
Neo
13
python -c "import platform;print(platform.platform())"

oder nur

python -m platform
Ilya Kharlamov
quelle
9
  1. lsb- * ist nicht installiert / existiert nicht auf CentOS- oder Debian- Basissystemen
  2. / proc / * existiert unter OSX nicht

Nehmen Sie einen Tipp von Javascript-Entwicklern. Testen Sie nicht die Version, sondern die Fähigkeit. Es ist nicht schön, aber es funktioniert. Erweitern Sie nach Bedarf.

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
}  
Orwellophile
quelle
6
Yum könnte sehr gut Red Hat, Scientific Linux oder Fedora sein. Es gab einen passenden Befehl für Fedora, der Debians nachahmt. Und so weiter. Wenn Sie einfach alles mit yum klassifizieren, erhalten Sie unter CentOS eine Reihe von unterstützten Systemen, von Red Hat 4 bis Fedora 18, also ungefähr 8 Jahre Linux-Geschichte. Wenn Sie wissen möchten, ob <foo> unterstützt wird, suchen Sie nach <foo>, anstatt anhand der (unzuverlässigen) Verteilungsidentifikation zu raten! Sicher, es führt zu einer Art Autotool, aber dem kann nicht geholfen werden (nur danke $ DEITY, dass die Unix-Kriege vorbei sind).
Vonbrand
@vonbrand in der Tat ist es, wie Sie sagen. ich versuche nicht zwischen subaromen zu unterscheiden. und die Reihenfolge, in der ich einchecke (hoffentlich), beseitigt die schwierigsten Situationen (RHEL mit installiertem apt-get), obwohl ich nicht viel recherchiert habe. Wenn RHEL apt-get installiert haben kann und Ubuntu-Benutzer yum haben, dann haben Sie einfach Pech.
Orwellophile
6

In der Reihenfolge des wahrscheinlichsten Erfolgs sind dies:

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

decken die meisten Fälle (AFAIK) ab: Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD und vielleicht andere.

Eelvex
quelle
cat /etc/*versionfunktioniert nicht (es gibt keine solche Datei) auf CentOS (mindestens auf 6.4)
om-nom-nom
Wenn Sie den Befehl in einem Container ausführen, enthält / proc / version die HOST-Distributionsversion und nicht die Container-Distributionsversion.
Dereckson,
5

Bei den meisten modernen Linux-Betriebssystemen wird die Datei /etc/os-releasezum Standard und in den meisten Betriebssystemen enthalten. In Ihrem Bash-Skript können Sie also einfach die Datei einfügen und haben Zugriff auf alle hier beschriebenen Variablen (zum Beispiel: NAME, VERSION, ...).

Also benutze ich dies nur in meinem Bash-Skript:

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
Chris Maes
quelle
3

Wenn die Datei /etc/debian_versionexistiert, ist die Distribution Debian oder ein Debian-Derivat. Diese Datei hat möglicherweise eine Versionsnummer. auf meinem Rechner ist es derzeit 6.0.1. Wenn es getestet oder instabil ist, wird möglicherweise "testing / unstable" oder die Nummer der bevorstehenden Version angezeigt. Mein Eindruck ist, dass zumindest unter Ubuntu diese Datei immer testet / instabil ist und dass sie die Versionsnummer nicht enthält, aber jemand kann mich korrigieren, wenn ich falsch liege.

Fedora (zumindest in den letzten Releases) hat eine ähnliche Datei, nämlich /etc/fedora-release.

Faheem Mitha
quelle
Neuere Debian-Versionen verwenden stattdessen / etc / os-release.
Dereckson,
1
@Dereckson Ich habe mein keuchendes Gerät überprüft und es hat beides /etc/debian_versionund /etc/os-release.
Faheem Mitha
Getestet in einer Jessie-Chroot, die mit debootstrap erstellt wurde. Aber in der Tat enthält ein lokaler Computer, der auch unter Jessie installiert wurde, eine /etc/debian_versionDatei. Die Art und Weise, wie wir eine Debian-Installation vorbereiten, könnte sich auf die verfügbaren Release-Dateien auswirken, das ist interessant.
Dereckson
Debians os-releaseenthält nicht die vollständige Versionsnummer von debian_version. Siehe unix.stackexchange.com/questions/382531 .
JdeBP
1

2 Wege von vielen:

1) verwenden

lsb_release -a

Ich habe es auf CentOS 5.5 und Ubuntu 10.04 getestet

Die Ausgabe für CentOS ist:

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

und für Ubuntu ist:

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) folgenden Befehl eingeben:

cat /etc/*-release

Ich habe es auf CentOS 5.5 und Ubuntu 10.04 getestet und es funktioniert einwandfrei.

Sam
quelle
lsb_release ist nicht in CentOS 6 (die min install fwiw)
ein Coder
lsb_release -a gibt "-bash: lsb_release: Befehl nicht gefunden" auf Raspberry mit Raspbian (von Debian 7.1 abgeleitet) zurück.
Peter Mortensen
0

Dieses Skript funktioniert unter Debian (muss unter Ubuntu möglicherweise angepasst werden)

#!/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
user9869932
quelle
0

Hier ist meine einfache 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
oh niceguy
quelle
0

Ohne Version nur dist:

cat /etc/issue | head -n +1 | awk '{print $1}'
coanor
quelle
Eine Antwort von Yahya Yahyaoui aus einem Jahr zuvor sagte dasselbe. Beide Antworten wurden im Jahr 2011 tatsächlich in Antworten angesprochen, die inzwischen gelöscht wurden. Die Gründe, aus denen sie falsch sind, gelten weiterhin.
JdeBP
0

Dies wurde auf Ubuntu 14 und CentOS 7 getestet

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'
BsdHelper
quelle
@don_crissti Wie würdest du das machen?
BsdHelper
sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
cas
@cas Sehr schön! Das meiner Toolbox hinzufügen. Ich danke Ihnen für das Teilen.
BsdHelper
0

Von hier aus finde ich ein gutes Skript , das für die meisten gängigen Linux-Benutzer geeignet ist:

#! /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
Mithril
quelle
0

Es gibt einen facter Ruby Gem, die Ihnen einige Fakten über os OS gibt es analysiert OS Release - Dateien, andere Daten und druckt auf Terminal - Bildschirm. Sie können Folgendes versuchen, beginnend mit der Rubygems-Installation:

# apt-get install rubygems

Bitte verwenden Sie den obigen Fall, der für Ihr Betriebssystem geeignet ist. Dann installieren Sie den Edelstein selbst.

# gem install facter

Dann benutze:

$ facter

ANMERKUNG: Weitere Informationen zur Installation finden Sie in den Quellen der Facter Gems.

Малъ Скрылевъ
quelle
0

Wenn jemand auch die Distribution braucht:

#!/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

Ausgabe:

It is: 18.04

Wechseln Sie zu: lsb_release -sc, um die Distribution zu erhalten:

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

Ausgabe:

It is: bionic
jturi
quelle
-3

Dieser Befehl funktioniert für Debian- und Redhat-basierte Distributionen: Mit dem trFilter konvertieren Sie das Dokument in ein zeilenweises Format und zählen dann die erste Zeile, die den Distributionsnamen enthält.

tr -s ' \011' '\012' < /etc/issue | head -n 1
Yahya Yahyaoui
quelle
Die Kommentare zu der jetzt gelöschten Antwort aus dem Jahr 2011, die dasselbe sagten, gelten immer noch. Ebenso wie die falsch platzierte Antwort, die nun wieder gelöscht wird, dass /etc/issuediese keine Version oder einen Namen auf zenwalk enthielt. Dies ist eine vom Administrator veränderbare Datei, die eine Nachricht enthält, die Menschen präsentiert wird und keine Garantie dafür hat, dass sie alles enthält, was programmgesteuert herausgezogen werden kann.
JdeBP