Jak mogę uzyskać nazwę dystrybucji i numer wersji w prostym skrypcie powłoki?

191

Pracuję nad prostym skryptem bash, który powinien być w stanie uruchomić na dystrybucjach Ubuntu i CentOS (wsparcie dla Debiana i Fedory / RHEL byłoby plusem) i muszę znać nazwę i wersję dystrybucji, w której działa skrypt ( w celu uruchomienia określonych działań, na przykład tworzenia repozytoriów). Jak dotąd mam to:

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

Wygląda na to, że działa, powraca ubuntulub centos(nie próbowałem innych) jako nazwa wydania. Mam jednak wrażenie, że musi istnieć łatwiejszy i bardziej niezawodny sposób na znalezienie tego - czy to prawda?

To nie działa dla RedHat. / etc / redhat-release zawiera: Redhat Linux Entreprise wydanie 5.5

Więc wersja nie jest trzecim słowem, lepiej użyj:

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
źródło
Czy na pewno +-releasedziała? Efektywnie wyglądasz, zakładając, że tak będzie /etc/lsb-release, więc może po prostu nazwij to tak.
Mikel
@Mikel: Wymieniłem *w +celu uniknięcia komentarz formatowania, powinno być etc/*-release, wydaje się działać.
Alix Axel
8
Nigdy nie wprowadzaj błędu składniowego, aby uzyskać prawidłowe formatowanie. Poza tym formatowanie jest nieprawidłowe tylko w podglądzie, ostateczny widok przejmuje składnię ze znaczników.
Gilles
Dlaczego nikt nie wspomina o tym fe uname -rv | grep -i "name_of_distro"i nie używa kodu wyjścia?
zbieg z

Odpowiedzi:

182

Aby uzyskać OSi VER, wydaje się, że najnowszy standard /etc/os-release. Wcześniej było lsb_releasei /etc/lsb-release. Wcześniej trzeba było szukać różnych plików dla każdej dystrybucji.

Oto, co zasugeruję

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

Myślę, że unameaby dostać się ARCHjest nadal najlepszym sposobem. Ale podany przez ciebie przykład oczywiście dotyczy tylko systemów Intel. Nazwałbym to BITStak:

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

Lub zmień ARCHna bardziej popularne, ale jednoznaczne wersje: x86i x64podobne:

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

ale oczywiście to zależy od ciebie.

Mikel
źródło
2
Sprawdziłbym lsb_release i użyłem go, jeśli jest dostępny, ale nie jest dostępny wszędzie. Na przykład nie ma go w domyślnej instalacji Fedory 14.
Steven D
Naprawdę? Czy próbowałeś przeliterować to za pomocą -i _? Może jest w /lib/lsbczymś takim. Co rpm -qa "lsb*"drukuje?
Mikel
1
rpm -qa "lsb*nic nie drukuje. Zgodnie z yum provides */lsb_releasenim jest zawarty w pakiecie o nazwie redhat-lsb, który, jak sądzę, nie jest domyślnie instalowany. Jednak nie jestem ekspertem od Fedory, są to tylko wyniki losowej maszyny wirtualnej Fedory, którą mam i mogą się bardzo mylić.
Steven D
3
Właśnie zainstalowałem Fedorę 14 na maszynie wirtualnej i nie ma lsb-release, jak powiedziałeś.
Mikel
5
Nie używać $OS, $VERSIONitp - umownie możemy wykorzystać zmienne środowiskowe (pager, redaktor, SHELL, ...) i wewnętrzne zmienne powłoki (BASH_VERSION, losowe, ...). Wszystkie pozostałe nazwy zmiennych powinny zawierać co najmniej jedną małą literę. Konwencja ta pozwala uniknąć przypadkowego zastąpienia zmiennych środowiskowych i wewnętrznych.
Chris Down,
58

Chciałbym to zrobić jako pierwszy krok:

ls /etc/*release

Gentoo, RedHat, Arch i SuSE mają plik o nazwie np /etc/gentoo-release. Wydaje się być popularny, sprawdź tę stronę o plikach wydania .

Debian i Ubuntu powinny również /etc/lsb-releasezawierać informacje o wydaniu i będą wyświetlane z poprzednim poleceniem.

Kolejny szybki to uname -rv. Jeśli zainstalowane jądro jest standardowym jądrem dystrybucji, zwykle znajdziesz tam nazwę.

Mata
źródło
To na Debianie uname -a.
tshepang
2
nie uname -rvzawiera informacji? uname -awypisze rzeczy, takie jak typ procesora i nazwa hosta, które nie są tu istotne. (Ale zarówno wydanie jądra ( -r), jak i wersja ( -v) są konieczne, nie wszystkie dystrybucje robią to tam samo)
Mat
uname -r daje 2.6.32-5-686-bigmemi uname -v daje #1 SMP Tue Mar 8 22:14:55 UTC 2011na Debianie 6. uname -a OTOH daje Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
tshepang
druga część uname -ato -n, tj. nazwa węzła == nazwa hosta. powiedziałbym, unameże nie będzie interesujący na Debianie. Pomyśl o tym, ale nie jestem pewien, czy jest on tak przydatny w RedHat.
Mat.
No dobrze Więc to po prostu szczęście, że mogę ustawić jako domyślną nazwę hosta, debian.
tshepang
36

lsb_release -a. Działa na Debianie i chyba Ubuntu, ale nie jestem pewien co do reszty. Zwykle powinien istnieć we wszystkich dystrybucjach GNU / Linux, ponieważ jest związany z LSB (Linux Standard Base).

sakisk
źródło
3
Nie jest domyślnie instalowany w Gentoo. W pewnym momencie Fedora też nie była (domyślnie już teraz)
Mat.
2
Działa to na ściśnięciu Debiana, Fedorze 14 i OpenSUSE 11.3. W Debianie i SUSE pakiet zawierający lsb_release to lsb-release, w Fedorze to redhat-lsb. Został już zainstalowany na Debianie i SUSE, ale nie na Fedorze. Myślę, że to jak dotąd najlepsza odpowiedź. +1.
Faheem Mitha
3
lsb_release nie jest częścią minimalnej instalacji CentOS 6.
program kodujący
1
lsb_release -a zwraca "-bash: lsb_release: komenda nie znaleziona" na Raspberry z Raspbian ( pochodna Debian 7.1).
Peter Mortensen
lsb_release -a działa na serwerze Red Hat Enterprise Linux Server 6.6 (Santiago)
jwilleke
21

Jednowarstwowy, awarie, jedna linia wyników, bez błędów.

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om
Markus
źródło
Pięknie dziękuję. Zauważ, że to wciąż nie działa w systemie Mac OS X, ale działa dobrze w Ubuntu i CentOS (są to trzy, które mam pod ręką).
Wildcard
2
Znakomity! Dlaczego taka bajeczna odpowiedź nie jest na topie?
Neo
13
python -c "import platform;print(platform.platform())"

Lub tylko

python -m platform
Ilya Kharlamov
źródło
9
  1. lsb- * nie jest zainstalowany / nie istnieje na podstawowych systemach CentOS lub Debian
  2. / proc / * nie istnieje w OSX

Weź napiwek od programistów javascript. Nie testuj wersji, testuj możliwości. To nie jest ładne, ale działa. Rozwiń w razie potrzeby.

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
źródło
6
Yum mógłby równie dobrze być Red Hat, Scientific Linux lub Fedora. Komenda Fedora naśladowała Debiana. I tak dalej. Wystarczy sklasyfikować wszystko za pomocą yum, ponieważ CentOS daje ci szereg obsługiwanych systemów, od Red Hat 4 do Fedory 18, czyli około 8 lat historii Linuksa właśnie tam. Jeśli chcesz wiedzieć, czy <foo> jest obsługiwany, w szczególności sprawdź <foo> zamiast zgadywania na podstawie (nierzetelnej) identyfikacji dystrybucji! Jasne, prowadzi to do czegoś w rodzaju automatycznych narzędzi, ale nic na to nie można poradzić (wystarczy podziękować $ DEITY, że wojny unixowe się skończyły).
vonbrand
@vonbrand rzeczywiście jest tak, jak mówisz. nie próbuję rozróżniać sub-smaków. a kolejność, w której się melduję (mam nadzieję) usuwa najbardziej trudne sytuacje (RHEL z zainstalowanym apt-get), chociaż nie przeprowadziłem wielu badań. jeśli RHEL może zainstalować apt-get, a użytkownicy Ubuntu mają mniam ... cóż, po prostu nie masz szczęścia.
Orwellophile
6

W kolejności najbardziej prawdopodobnego sukcesu:

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

obejmuje większość przypadków (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD i być może inne.

Eelvex
źródło
cat /etc/*versionnie działa (nie ma takiego pliku) na CentOS (przynajmniej na 6.4)
om-nom-nom
Jeśli uruchomisz polecenie w kontenerze, / proc / version będzie zawierał wersję dystrybucyjną HOST, a nie wersję dystrybucyjną kontenera.
Dereckson
5

W przypadku większości współczesnych systemów Linux, plik /etc/os-releasenaprawdę staje się standardem i włącza się do większości systemów operacyjnych. Tak więc w skrypcie Bash możesz po prostu dołączyć plik i będziesz mieć dostęp do wszystkich opisanych tutaj zmiennych (na przykład: NAZWA, WERSJA, ...)

Używam tego w moim skrypcie Bash:

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
źródło
3

Jeśli plik /etc/debian_versionistnieje, dystrybucja to Debian lub pochodna Debiana. Ten plik może mieć numer wydania; na moim komputerze jest obecnie 6.0.1. Jeśli jest testowany lub niestabilny, może powiedzieć testowanie / niestabilny lub może mieć numer nadchodzącego wydania. Mam wrażenie, że przynajmniej na Ubuntu ten plik zawsze testuje / jest niestabilny i że nie umieszczają w nim numeru wydania, ale ktoś może mnie poprawić, jeśli się mylę.

Fedora (przynajmniej ostatnie wydania) mają podobny plik, a mianowicie /etc/fedora-release.

Faheem Mitha
źródło
Nowsze wersje Debiana używają / etc / os-release.
Dereckson
1
@Dereckson Sprawdziłem wheezy maszynę, a to ma zarówno /etc/debian_versioni /etc/os-release.
Faheem Mitha
Testowane w chroocie Jessie utworzonym za pomocą narzędzia debootstrap. Ale w rzeczywistości lokalna maszyna również pod Jessie, tym razem zainstalowana w bardziej konwencjonalny sposób, zawiera /etc/debian_versionplik. Tak więc sposób, w jaki przygotowujemy instalację Debiana, może wpłynąć na dostępne pliki wydania, to interesujące.
Dereckson
Debian os-releasenie zawiera pełnego numeru wersji z debian_version. Zobacz unix.stackexchange.com/questions/382531 .
JdeBP
1

2 sposoby z wielu:

1) użyj

lsb_release -a

Przetestowałem to na CentOS 5.5 i Ubuntu 10.04

wyjście dla CentOS to:

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

a dla Ubuntu jest:

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) wprowadź następujące polecenie:

cat /etc/*-release

Przetestowałem to na CentOS 5.5 i Ubuntu 10.04 i działa dobrze.

Sam
źródło
lsb_release nie znajduje się w CentOS 6 (min. instalacja fwiw)
koder
lsb_release -a zwraca "-bash: lsb_release: komenda nie znaleziona" na Raspberry z Raspbian ( pochodna Debian 7.1).
Peter Mortensen
0

Ten skrypt działa na Debianie (może wymagać drobnych poprawek w 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
użytkownik9869932
źródło
0

Oto moja prosta wersja chech_distro. ^^;

#!/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
niceguy oh
źródło
0

Bez wersji wystarczy tylko dist:

cat /etc/issue | head -n +1 | awk '{print $1}'
coanor
źródło
Odpowiedź rok wcześniej Yahya Yahyaoui powiedziała to samo. Obie te odpowiedzi zostały w rzeczywistości uwzględnione w 2011 r. W odpowiedziach, które zostały później usunięte. Powody, dla których się mylą, nadal obowiązują.
JdeBP
0

Zostało to przetestowane na Ubuntu 14 i CentOS 7

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'
BsdHelper
źródło
@don_crissti Jak byś to zrobił?
BsdHelper
sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
cas
@cas Very nice! Dodanie tego do mojego zestawu narzędzi. Dziękuję za udostępnienie.
BsdHelper
0

Znajduję stąd dobry skrypt , który działa na większość popularnych Linuksów:

#! /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
źródło
0

Jest rubinowy klejnot faktera , który podaje kilka faktów na temat systemu operacyjnego, analizuje pliki wersji systemu operacyjnego, inne dane i drukuje na ekranie terminala. Możesz spróbować w następujący sposób, zaczynając od instalacji rubygemów:

# apt-get install rubygems

Użyj powyższego przypadku, który jest odpowiedni dla twojego systemu operacyjnego. Następnie zainstaluj sam klejnot.

# gem install facter

Następnie użyj:

$ facter

UWAGA: Zobacz źródła klejnotów w celu uzyskania dodatkowych informacji podczas instalacji.

Малъ Скрылевъ
źródło
0

Jeśli ktoś również potrzebuje dystrybucji:

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

Wynik:

It is: 18.04

Zmień na: lsb_release -sc, aby uzyskać dystrybucję:

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

Wynik:

It is: bionic
jturi
źródło
-3

To polecenie działa w przypadku dystrybucji opartych na Debianie i Redhat: Korzystając z trfiltra, konwertujesz dokument do formatu jednego słowa na linię, a następnie zliczasz pierwszy wiersz zawierający nazwę dystrybucji.

tr -s ' \011' '\012' < /etc/issue | head -n 1
Yahya Yahyaoui
źródło
Nadal obowiązują komentarze do usuniętej odpowiedzi z 2011 roku, które mówiły to samo. Podobnie jak źle umieszczona odpowiedź, ponownie teraz usunięta, która mówi, że /etc/issuenie zawierała wersji ani nazwy na zenwalk. Jest to plik, który można modyfikować przez administratora, zawierający komunikat prezentowany ludziom, który nie ma gwarancji, że zawiera wszystko , co można wyciągnąć programowo.
JdeBP