Jak stwierdzić, czy jest to Fedora, czy Debian za pomocą skryptu powłoki

0

Uczę się podstaw pisania skryptów i próbuję napisać skrypt, aby zdecydować, jaki smak Linux ma uruchamiać. Opracowałem następującą prostą wersję:

#!/bin/sh
     which yum >/dev/null && { echo Fedora flavour; exit 0; }
     which zypper >/dev/null && { echo Suse of sorts; exit 0; }
     which apt-get >/dev/null && { echo Debian based;  }

Czy jest bardziej wdzięczny sposób, aby zdecydować, na którym smaku Linuxa używam? Czy istnieje sposób na włączenie Uniksa - lub uczynienie go generycznym dla Xnix?

Wielkie dzięki.

Edycja: nie jest to duplikat Jak rozpoznać używaną dystrybucję Linuksa? z następujących powodów: W przypadku Ubuntu cat /etc/lsb-releasedziała jak urok, w przypadku RedHata tak nie jest. ls /etc/*releaserobi, ale wyświetla trzy foldery. cat /proc/versionwygląda obiecująco, ale potrzebuje magii wyrażeń regularnych.

Lefty G. Balogh
źródło
@ Golimar, dzięki. Prawie, ale nie do końca to, czego szukam. W Ubuntu, cat / etc / lsb-release działa jak urok, w RedHat tak nie jest. Wydanie ls / etc / * tak, ale zawiera trzy foldery, więc potrzebuję więcej kopania. cat / proc / wersja wygląda obiecująco, ale potrzebuje magii wyrażeń regularnych. W każdym razie dzięki.
Lefty G Balogh,
/etc/lsb-releasebędzie działać na dystrybucjach rodziny Red Hat, jeśli zainstalujesz pakiety LSB - ale my domyślnie nie.
mattdm,
Myślę, że to jest duplikatem - fakt, że odpowiedź jest, że starał się nie jest wyczerpująca, nie czyni go mniej.
mattdm

Odpowiedzi:

1

Próbowałem z:

cat /etc/*release | grep "^ID="

Mam to także z Ubuntu i Centos.

Zumo de Vidrio
źródło
Prawie idealnie. Instancja AWS Suse sprawiała mi trudność, ale ogólnie rzecz biorąc: less /etc/os-release | grep "^ID="robi wszystko na wszystkich trzech. Dzięki. Zdecydowanie +1.
Lefty G Balogh,
@LeftyGBalogh Racja, wszyscy trzej używają systemd, zobacz moją odpowiedź.
mattdm,
0

Podzielę się kodem skryptu, który wykonuję, który obsługuje ponad 12 różnych systemów Linux i wykrywa, czy system jest oparty na uzbrojeniu. Na początku jest tablica, na której musisz umieścić obsługiwany system Linux. Ma dwie fazy. Pierwszym z nich jest przeszukanie słów w tablicy na podstawie wyniku polecenia uname. Drugim jest sprawdzenie specjalnej istniejącej w / etc, która zależy od dystrybucji.

#!/bin/bash

is_arm=0

#Distros vars
known_compatible_distros=(
                        "Wifislax"
                        "Kali"
                        "Parrot"
                        "Backbox"
                        "Blackarch"
                        "Cyborg"
                        "Ubuntu"
                        "Debian"
                        "SuSE"
                        "CentOS"
                        "Gentoo"
                        "Fedora"
                        "Red Hat"
                        "Arch"
                        "OpenMandriva"
                    )

known_arm_compatible_distros=(
                        "Raspbian"
                        "Parrot arm"
                        "Kali arm"
                    )

#First phase of Linux distro detection based on uname output
function detect_distro_phase1() {

    for i in "${known_compatible_distros[@]}"; do
        uname -a | grep "${i}" -i > /dev/null
        if [ "$?" = "0" ]; then
            distro="${i^}"
            break
        fi
    done
}

#Second phase of Linux distro detection based on architecture and version file
function detect_distro_phase2() {

    if [ "${distro}" = "Unknown Linux" ]; then
        if [ -f ${osversionfile_dir}"centos-release" ]; then
            distro="CentOS"
        elif [ -f ${osversionfile_dir}"fedora-release" ]; then
            distro="Fedora"
        elif [ -f ${osversionfile_dir}"gentoo-release" ]; then
            distro="Gentoo"
        elif [ -f ${osversionfile_dir}"openmandriva-release" ]; then
            distro="OpenMandriva"
        elif [ -f ${osversionfile_dir}"redhat-release" ]; then
            distro="Red Hat"
        elif [ -f ${osversionfile_dir}"SuSE-release" ]; then
            distro="SuSE"
        elif [ -f ${osversionfile_dir}"debian_version" ]; then
            distro="Debian"
            if [ -f ${osversionfile_dir}"os-release" ]; then
                extra_os_info=$(cat < ${osversionfile_dir}"os-release" | grep "PRETTY_NAME")
                if [[ "${extra_os_info}" =~ Raspbian ]]; then
                    distro="Raspbian"
                    is_arm=1
                elif [[ "${extra_os_info}" =~ Parrot ]]; then
                    distro="Parrot arm"
                    is_arm=1
                fi
            fi
        fi
    fi

    detect_arm_architecture
}

#Detect if arm architecture is present on system
function detect_arm_architecture() {

    distro_already_known=0
    uname -m | grep -i "arm" > /dev/null

    if [[ "$?" = "0" ]] && [[ "${distro}" != "Unknown Linux" ]]; then

        for item in "${known_arm_compatible_distros[@]}"; do
            if [ "${distro}" = "${item}" ]; then
                distro_already_known=1
            fi
        done

        if [ ${distro_already_known} -eq 0 ]; then
            distro="${distro} arm"
            is_arm=1
        fi
    fi
}

detect_distro_phase1
detect_distro_phase2

echo "${distro}"
echo "${is_arm}"

Oczywiście można to poprawić ... może zmienić łańcuch „elif” na skrzynkę lub coś w tym rodzaju… ale to w pełni działa. Mam nadzieję, że ci to pomoże.

OscarAkaElvis
źródło
Hej Oscar, wielkie dzięki, niezła robota. Szybko przetestowałem to na kilku maszynach. 2 serwery RHEL, jeden w AWS - i nic nie zwraca dla systemu operacyjnego, a 0 dla uzbrojenia. AWS Suse niczego nie echa. Ubuntu działa jak urok. Masz pomysł, gdzie mogę się pomylić?
Lefty G Balogh,
Przepraszam, nigdy nie korzystałem z Suse AWS. Wygląda na to, że słowo „suse” nie pojawia się w danych wyjściowych uname -apolecenia Suse AWS i wydaje się też, że nie ma SuSE-releasepliku w / etc. Aby to zmodyfikować, aby wykryć, że musisz sprawdzić, jaka jest nazwa pliku istniejącego w / etc i dodać „elif” o tej nazwie w fazie 2 wykrywania. W przypadku Red Hat chyba działa, ponieważ serwery Red Hat zawsze mają redhat-releaseplik w / etc, prawda?
OscarAkaElvis
Redhat ma, /etc/redhat-releaseale uname -all nie zwraca nazwy / rodziny dystrybucji. Ani Suse. Zobacz poniżej: RHEL - Linux <servername> <xx.xx.xx>.20.1.el7.x86_64 #1 SMP Thu Sep 24 12:23:56 EDT 2015 x86_64 x86_64 x86_64 GNU/LinuxSuse - Linux ip-<xx.xx.xx.xx>.us-west-2.compute.internal 4.4.21-69-default #1 SMP Tue Oct 25 10:58:20 UTC 2016 (9464f67) x86_64 x86_64 x86_64 GNU/LinuxUbuntu -Linux ip-<xx.xx.xx.xx> 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Lefty G Balogh
1
Nie ma problemu, ponieważ istnieje faza 2. Jeśli nie nazwa w wyjściu uname, szuka pliku w etc, więc Red Hat musi działać! czy masz plik o nazwie / etc / redhat-release? jeśli tak, musi zostać wykryty jako czerwony kapelusz
OscarAkaElvis,
0

Więc rozłączyłem się i po dniu kopania znalazłem to: http://linuxmafia.com/faq/Admin/release-files.html

Następnie praca / scalenie i testowanie następnego dnia zaowocowało uruchomieniem następującego skryptu, który został przetestowany

  • Solaris
  • Czerwony kapelusz
  • Ubuntu
  • SuSe

Jeśli ktoś z was ma sposób na sprawdzenie innych dystrybucji, byłbym bardzo zobowiązany.

#!/bin/sh
# Detects which OS and if it is Linux then it will detect which Linux
# Distribution.
# from http://linuxmafia.com/faq/Admin/release-files.html
#


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

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

if [ "${OS}" = "Darwin" ]; then
    OIFS="$IFS"
    IFS=$'\n'
    set `sw_vers` > /dev/null
    DIST=`echo $1 | tr "\n" ' ' | sed 's/ProductName:[ ]*//'`
    VERSION=`echo $2 | tr "\n" ' ' | sed 's/ProductVersion:[ ]*//'`
    BUILD=`echo $3 | tr "\n" ' ' | sed 's/BuildVersion:[ ]*//'`
    OSSTR="${OS} ${DIST} ${REV}(SORRY_NO_PSEUDONAME ${BUILD} ${MACH})"
    IFS="$OIFS"

elif [ "${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=""
    elif [ -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}
Lefty G. Balogh
źródło
0

Na współczesnych Fedorach i Debianie (oraz Arch, CentOS, CoreOS, Mageia, openSUSE, Red Hat Enterprise Linux, SUSE Linux Enterprise Server, Ubuntu i inne) najłatwiej jest spojrzeć na /etc/os-releaselub uruchomić hostnamectl status.

W skrypcie możesz po prostu zrobić

#!/bin/sh
source /etc/os-release
echo $PRETTY_NAME

Oczywiście, jeśli chcesz zidentyfikować również stare wersje lub niesystemowe dystrybucje, możesz po prostu zacząć od powyższego, ale jeśli /etc/os-releasenie istnieje, przejdź do dalszej heurystyki.

Aby uzyskać więcej informacji, zobacz Wykrywanie nazwy i wersji dystrybucji systemu Linux w dokumentacji przepełnienia stosu.

mattdm
źródło
RedHat, Centos i SUSE nie są oparte na Debianie.
andrej
@andrej Oczywiście, że nie są. Ale powyższe będzie działać na wszystkich z nich, przy założeniu wystarczająco nowych wersji.
mattdm