Jak dowiedzieć się, która wersja Linux działa?

29

Czasami twoje skrypty muszą zachowywać się inaczej w różnych systemach Linux. Jak mogę ustalić, na której wersji systemu Linux działa skrypt?

jldugger
źródło
1
Mówiąc o wersji, masz na myśli wersję jądra? Jaka dystrybucja? Wersja dystrybucyjna?
Chris Upchurch
2
Jestem pewien, że jldugger chce dowiedzieć się, która rodzina dystrybucji działa. Jest mało prawdopodobne, że wersja jądra wpłynie na skrypt, chyba że zależy to od niektórych elementów / sys lub / proc - i nawet wtedy zwykle łatwiej jest założyć na podstawie dystrybucji niż na jądrze.
Mihai Limbăşan

Odpowiedzi:

27

Nie próbuj przyjmować założeń na podstawie tego, co możesz, a czego nie możesz zrobić, ponieważ w ten sposób leży szaleństwo (zobacz także „Wykrywanie agenta użytkownika”). Zamiast tego sprawdź, czy obsługiwane jest to, co chcesz, i jak to zrobić za pomocą dowolnej komendy lub lokalizacji pliku, której chcesz użyć.

Na przykład, jeśli chcesz zainstalować pakiet, możesz wykryć, czy korzystasz z systemu podobnego do Debiana, czy systemu podobnego do RedHat, sprawdzając obecność dpkg lub rpm (najpierw sprawdź dpkg, ponieważ maszyny Debiana mogą mieć polecenie rpm na nich ...). Podejmuj decyzję, co robić w oparciu o to, a nie tylko czy jest to system Debian czy RedHat. W ten sposób automatycznie obsłużysz wszelkie dystrybucje pochodnych, w których nie programowałeś jawnie. Aha, a jeśli twój pakiet wymaga określonych zależności, przetestuj je również i daj użytkownikowi znać, czego brakuje.

Innym przykładem jest majstrowanie przy interfejsach sieciowych. Sprawdź, co zrobić, na podstawie tego, czy istnieje plik / etc / network / interfaces, czy katalog / etc / sysconfig / network-scripts i przejdź od tego.

Tak, to więcej pracy, ale jeśli nie chcesz naprawić wszystkich błędów popełnianych przez twórców stron internetowych w ciągu ostatniej dekady lub więcej, zrobisz to inteligentnie od samego początku.

womble
źródło
1
(Rozszerzając tę ​​odpowiedź) Wykrywanie funkcji jest lepsze w niektórych sytuacjach, ale pamiętaj, aby nigdy nie zgadywać rozkładu na podstawie wykrytych funkcji! Nie myl błędnie odpowiedzi i ustal, czy platforma jest RedHat na podstawie plików w / etc. Jeśli naprawdę potrzebujesz nazwy dystrybucji, sprawdź lsb_release (lub / etc / redhat-release itd.).
Nicholas Wilson
36

Nie ma sposobu dystrybucji krzyżowej. Jednak:

  • Redhat i przyjaciele: Testuj /etc/redhat-release, sprawdzaj zawartość
  • Debian: Testuj /etc/debian_version, sprawdź zawartość
  • Mandriva i przyjaciele: Testuj /etc/version, sprawdzaj zawartość
  • Slackware: Testuj /etc/slackware-version, sprawdź zawartość

Itd. Ogólnie rzecz biorąc, sprawdź /etc/*-releasei /etc/*-version.


Edycja: Znalazłem mój stary (ponad 1-letni) skrypt bash leżący wokół, który musiałem ułożyć razem przez lata (ma imponujący dziennik CVS sprzed 6 lat). Może już nie działać poprawnie w obecnej postaci i mogę nie będzie Ci przeszkadzać, aby znaleźć zainstalowane dystrybucje do przetestowania, ale powinno to zapewnić dobry punkt wyjścia. Działa dobrze na CentOS, Fedorze i Gentoo. gyaresu przetestował go z powodzeniem na Debianie Lennym.

#!/bin/bash

get_distribution_type()
{
    local dtype
    # Assume unknown
    dtype="unknown"

    # First test against Fedora / RHEL / CentOS / generic Redhat derivative
    if [ -r /etc/rc.d/init.d/functions ]; then
        source /etc/rc.d/init.d/functions
        [ zz`type -t passed 2>/dev/null` == "zzfunction" ] && dtype="redhat"

    # Then test against SUSE (must be after Redhat,
    # I've seen rc.status on Ubuntu I think? TODO: Recheck that)
    elif [ -r /etc/rc.status ]; then
        source /etc/rc.status
        [ zz`type -t rc_reset 2>/dev/null` == "zzfunction" ] && dtype="suse"

    # Then test against Debian, Ubuntu and friends
    elif [ -r /lib/lsb/init-functions ]; then
        source /lib/lsb/init-functions
        [ zz`type -t log_begin_msg 2>/dev/null` == "zzfunction" ] && dtype="debian"

    # Then test against Gentoo
    elif [ -r /etc/init.d/functions.sh ]; then
        source /etc/init.d/functions.sh
        [ zz`type -t ebegin 2>/dev/null` == "zzfunction" ] && dtype="gentoo"

    # For Slackware we currently just test if /etc/slackware-version exists
    # and isn't empty (TODO: Find a better way :)
    elif [ -s /etc/slackware-version ]; then
        dtype="slackware"
    fi
    echo $dtype
}

Zauważ, że prawdopodobnie będzie to działać poprawnie tylko w Bash. Możesz przepisać go dla innych powłok.

Biorąc to pod uwagę, możesz chcieć przetestować funkcje, a nie dystrybucje. Nie używam tego już po prostu dlatego, że stało się to obciążeniem konserwacyjnym. Łatwiej jest polegać na narzędziach i rozwiązaniach do dystrybucji krzyżowej.


Pod względem koncepcyjnym polega on na:

  • Pobierz znany typ pliku „typowa funkcja skryptu inicjującego”. Są one specyficzne dla dystrybucji. Jeśli nie istnieje, przejdź do następnej kontroli dystrybucji.
  • Sprawdź istnienie określonej, znanej, często używanej i mało prawdopodobnej zmiany nazwy funkcji z tego podstawowego skryptu. Robimy to za pomocą typewbudowanego Bash. type -tzwraca, functionjeśli ten symbol jest funkcją. Przechodzimy zzdo wyjścia, type -t 2>/dev/nullponieważ jeśli nazwa nie zostanie zdefiniowana, łańcuch wyjściowy byłby pusty i otrzymalibyśmy błąd składniowy dotyczący brakującej lewej ręki do ==operatora. Jeśli nazwa, którą właśnie sprawdziliśmy, nie jest funkcją, przejdź do następnej kontroli dystrybucji, w przeciwnym razie znaleźliśmy typ dystrybucji.
  • Na koniec powtórz typ dystrybucji, aby wynik funkcji mógł być łatwo wykorzystany w bloku case .. esac.

Edytuj na wypadek, gdybyś próbował uruchomić to jako prosty skrypt: ten skrypt powinien być pozyskiwany lub dołączany z innych skryptów. Nie wyprowadza niczego samodzielnie, jeśli uruchomisz go takim, jaki jest. Aby to przetestować, zrób to, a następnie wywołaj funkcję, np .:

source /path/to/this/script.sh
get_distribution_type

po znaku zachęty.


Edycja: Należy pamiętać, że ten skrypt nie wymaga uprawnień roota. Nalegam, abyś nie uruchamiał go jako root. Nic nie powinno zaszkodzić, ale nie ma takiej potrzeby.


Znaleziono link do odpowiedniego wpisu na liście mailingowej w dzienniku CVS. Powinien być przydatny w rozpakowywaniu spaghetti ze skryptem inicjującym.

Mihai Limbăşan
źródło
Nie patrzyłem na dlaczego, ale powraca do pytania w Debianie Lennym (5.0).
Gareth
gyaresu, czy faktycznie wywołałeś funkcję get_distribution_type? Zredagowałem post, aby wyjaśnić (patrz na dole).
Mihai Limbăşan
@gyaresu: Jeśli powyższy problem nie był problemem, czy możesz spróbować zastąpić log_begin_msg w sekcji Debian log_warning_msg i spróbować ponownie? Być może nazwa funkcji była niepoprawna. W każdym razie powinien był zwrócić „nieznany”, jeśli ta funkcja nie była jeszcze zmieniona, ale nadal.
Mihai Limbăşan
@Mihai Doh! Przepraszam. Nie przeczytałem poprawnie skryptu. Było wcześnie, bez kawy. Przepraszam. gyaresu @ debian: ~ / bin $ source server_version.sh gyaresu @ debian: ~ / bin $ get_distribution_type debian
Gareth
@gyaresu: Dzięki! To dobrze, powinno pomóc jlduggerowi wiedzieć, że działa również na Debianie :)
Mihai Limbăşan
17

Możesz znaleźć wersję jądra, uruchamiając uname -a, znalezienie wersji dystrybucji zależy od dystrybucji.

W systemie Ubuntu i niektórych innych systemach operacyjnych można uruchomić lsb_release -alub odczytać plik / etc / lsb_release

Debian przechowuje wersję w / etc / debian_version

Adam Gibbins
źródło
+1 dla lsb_release (działa również na pochodnych Red Hata, jeśli zainstalowany jest odpowiedni pakiet)
Josh Kelley
tylko dla opisu „lsb_release -ds”.
flickerfly
6

Większość dystrybucji ma unikalną metodę określania konkretnego rozkładu.

Na przykład:

Redhat (And derivatives): /etc/redhat-release

SUSE: /etc/SUSE-release

Istnieje standard znany jako Linux Standard Base lub LSB . Określa, że ​​powinien istnieć plik o nazwie / etc / lsb-release lub program o nazwie lsb_release, który wyśle ​​echo informacji o dystrybucji Linuksa.

lsb_release -a
Mark Turner
źródło
I oczywiście lsb_releasenie istnieje w CentOS 6.
Justin
6
python -c 'import platform ; print platform.dist()[0]'

kod: http://hg.python.org/cpython/file/2.7/Lib/platform.py

jkeogh
źródło
Świetny pomysł. Sugerowałbym użycie python -c 'import platform; print(platform.dist()[0])', ponieważ w ten sposób działa również, jeśli normalnym pythonem jest domyślnie Python3.
heinrich5991,
5

Oprócz innych odpowiedzi: Jeśli chcesz tylko parsować jeden plik, większość dystrybucji spersonalizuje login tty przez / etc / issue np .:

Witamy w SUSE Linux Enterprise Server 10 SP2 (i586) - Kernel \ r (\ l).

I tak, wiem, że nie jest optymalny. :)

Węzeł
źródło
Może nie być optymalny, ale jest w tym samym miejscu.
Brad Gilbert
4

facter jest przydatnym narzędziem do tego rodzaju odkryć, chociaż prawdopodobnie wykorzystuje niektóre z metod opisanych powyżej i wymaga Ruby.

Cawflands
źródło
2

Wszystko, co musisz zrobić, to wpisać uname -aulubioną powłokę. Spowoduje to wydrukowanie nazwy i wersji jądra.


źródło
2

Przekonałem się, że cat /etc/*release*prawie zawsze działa.

ibuys
źródło
2

Zgadzam się z Markiem, Adamem i Mihai (nie mogę głosować z powodu niewystarczającej reputacji). Rozwiązania oparte na LSB i jego względnym FHS będą działać z większością dystrybucji i prawdopodobnie będą nadal działać w przyszłości. LSB i FHS są twoimi przyjaciółmi.

David J. Liszewski
źródło
2

Możesz także pobrać wersję przez

cat /proc/version

o / p:

Wersja Linux 2.6.17-13mdv ([email protected]) (gcc wersja 4.1.2 20070302 (wersja wstępna) (4.1.2-1mdv2007.1)) # 1 SMP Pt 23 marca 19:03:31 UTC 2007

prasanna
źródło
1

Wersja Linuksa jest trudnym pytaniem. Jeśli spojrzymy na to wąsko, mamy wersję jądra, którą można uzyskać za pomocą „ uname -r”. Wersja dystrybucji jest w większości nieistotna. Niektóre dystrybucje są lepsze (dystrybucje dla przedsiębiorstw, takie jak Redhat Enterprise Linux). Inne dystrybucje, takie jak Gentoo, są w zasadzie ruchomymi celami, które nie mają żadnej sensownej wersji. Jeśli potrzebujesz robić rzeczy w zależności od wersji, spójrz na główne komponenty, które są dla Ciebie odpowiednie:

Component       Version command
glibc           /lib/libc.so.6
gcc             gcc --version
X               xdpyinfo
libX11          pkg-config --modversion x11
gtk+            pkg-config --modversion gtk+-2.0
qt-4            pkg-config --modversion QtCore

   etc...
Paul de Vrieze
źródło
1

Możesz także sprawdzić menu Grub, zwykle daje ci sporo informacji o dystrybucji / wersji :-)

Antoine Benkemoun
źródło
-1

FusionInventory to wieloplatformowe lekkie narzędzie do inwentaryzacji, które może uzyskiwać te informacje na wielu dystrybucjach Linuksa, ale także na BSD, Windows, MacOS X i innych unikach.

Jeśli są dostępne, używają lsb_release(jak wspomniano kilka razy powyżej), ale jeśli nie, mają bardzo przydatną listę plików i wyrażeń regularnych, aby sprawdzić nazwę i wersję dystrybucji: https://github.com/fusinv/fusioninventory-agent/ blob / 2.2.x / lib / FusionInventory / Agent / Task / Inventory / Input / Linux / Distro / NonLSB.pm # L16 .

Polecam skorzystanie z samego FusionInventory, aby uzyskać te informacje, zamiast ponownego wdrażania własnych skryptów za pomocą tej logiki, ponieważ ich społeczność będzie utrzymywać tę funkcjonalność na bieżąco. Możesz użyć agenta jako takiego (generuje on plik XML / JSON, który jest łatwy do analizy) lub połączyć go z szerszym rozwiązaniem do zarządzania komputerami w sieci, takimi jak GLPI lub Rudder , w zależności od potrzeb.

Jonathan Clarke
źródło
Byłoby to dobre rozwiązanie, gdyby nie miał zewnętrznych zależności modułów Perla
Will Sheppard