Come posso ottenere il nome della distribuzione e il numero di versione in un semplice script shell?


191

Sto lavorando a un semplice script bash che dovrebbe essere in grado di funzionare su distribuzioni Ubuntu e CentOS (il supporto per Debian e Fedora / RHEL sarebbe un vantaggio) e ho bisogno di sapere il nome e la versione della distribuzione su cui è in esecuzione lo script ( al fine di innescare azioni specifiche, ad esempio la creazione di repository). Finora quello che ho è questo:

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

Questo sembra funzionare, tornare ubuntuo centos(non ho provato altri) come nome della versione. Tuttavia, ho la sensazione che ci debba essere un modo più semplice e affidabile per scoprirlo - è vero?

Non funziona per RedHat. / etc / redhat-release contiene: Redhat Linux Entreprise versione 5.5

Quindi, la versione non è la terza parola, è meglio usare:

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"

Sei sicuro che +-releasefunzioni? In effetti stai guardando supponendo che lo sarà /etc/lsb-release, quindi forse chiamalo così.
Mikel,

@Mikel: ho sostituito *con +per evitare la formulazione del commento, dovrebbe essere etc/*-release, sembra funzionare.
Alix Axel,

8
Non introdurre mai un errore di sintassi per ottenere la formattazione corretta. Inoltre, la formattazione è errata solo nell'anteprima, la vista finale rileva la sintassi dai tag.
Gilles,

Perché nessuno menziona questo fe uname -rv | grep -i "name_of_distro"e usa il codice di uscita?
fuggitivo

Risposte:


182

Per ottenere OSe VER, sembra essere l'ultimo standard /etc/os-release. Prima di ciò, c'era lsb_releasee /etc/lsb-release. Prima di ciò, dovevi cercare file diversi per ogni distribuzione.

Ecco cosa suggerirei

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

Penso che unameottenere ARCHsia ancora il modo migliore. Ma l'esempio che hai fornito ovviamente gestisce solo i sistemi Intel. O lo definirei BITScosì:

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

O cambia ARCHper essere le versioni più comuni, ma non ambigue: x86e x64simili:

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

ma ovviamente dipende da te.


2
Vorrei controllare lsb_release e usarlo se disponibile, ma non è disponibile ovunque. Ad esempio, non è nell'installazione predefinita di Fedora 14.
Steven D

Veramente? Hai provato a scriverlo con -e _? Forse è dentro /lib/lsbo in qualche posto del genere. Cosa rpm -qa "lsb*"stampa?
Mikel,

1
rpm -qa "lsb*non stampa nulla. Secondo yum provides */lsb_releaseesso è contenuto in un pacchetto chiamato redhat-lsb che immagino non sia installato di default. Tuttavia, non sono un esperto di Fedora, questi sono solo i risultati di una VM Fedora casuale che ho e potrebbero essere molto sbagliati.
Steven D,

3
Ho appena installato Fedora 14 in una VM, e non c'è lsb-release, come hai detto.
Mikel,

5
Non usare $OS, $VERSIONecc. - per convenzione, capitalizziamo le variabili di ambiente (PAGER, EDITOR, SHELL, ...) e le variabili di shell interne (BASH_VERSION, RANDOM, ...). Tutti gli altri nomi di variabili devono contenere almeno una lettera minuscola. Questa convenzione evita di ignorare accidentalmente le variabili ambientali e interne.
Chris Down,

58

Vorrei andare con questo come primo passo:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE hanno un file chiamato eg /etc/gentoo-release. Sembra essere popolare, controlla questo sito per i file di rilascio .

Debian e Ubuntu dovrebbero avere anche un file /etc/lsb-releasecontenente le informazioni sulla versione e verrà mostrato con il comando precedente.

Un altro è veloce uname -rv. Se il kernel installato è il kernel stock distro, di solito a volte troverai il nome lì dentro.


Su Debian, quello è uname -a.
Tshepang,

2
non uname -rvcontiene le informazioni però? uname -astamperà cose come il tipo di processore e il nome host che sono irrilevanti qui. (Ma sia la versione del kernel ( -r) che la versione ( -v) sono necessarie, non tutte le distribuzioni fanno lo stesso lì)
Mat

uname -r2.6.32-5-686-bigmeme uname -v#1 SMP Tue Mar 8 22:14:55 UTC 2011su Debian 6. uname -a OTOH dà Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
Tshepang,

la seconda parte di uname -aè -n, cioè nodename == hostname. quindi direi unameche non sarà interessante su Debian. Vieni a pensarci bene, non sono sicuro che sia così utile su RedHat.
Mat

Oh va bene. Quindi è solo per fortuna che ho impostato il mio hostname di default, debian.
Tshepang,

36

lsb_release -a. Funziona su Debian e suppongo Ubuntu, ma non sono sicuro del resto. Normalmente dovrebbe esistere in tutte le distribuzioni GNU / Linux poiché è correlato a LSB (Linux Standard Base).


3
Non è installato di default su Gentoo. Non è stato di default su Fedora ad un certo punto (probabilmente lo è ora)
Mat

2
Funzionava con Debian Squeeze, Fedora 14 e OpenSUSE 11.3. Su Debian e SUSE il pacchetto contenente lsb_release era lsb-release, su Fedora era redhat-lsb. Era già installato su Debian e SUSE, ma non su Fedora. Penso che questa sia la risposta migliore finora. +1.
Faheem Mitha,

3
lsb_release non fa parte dell'installazione minima di CentOS 6.
un programmatore

1
lsb_release -a restituisce "-bash: lsb_release: comando non trovato" su Raspberry con Raspbian ( derivato da Debian 7.1).
Peter Mortensen,

lsb_release -a funziona su Red Hat Enterprise Linux Server versione 6.6 (Santiago)
jwilleke,

21

One-liner, fallback, una riga di output, nessun errore.

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om

Bello grazie. Nota che non funziona ancora su Mac OS X, ma funziona bene su Ubuntu e CentOS (che sono i tre che ho a portata di mano).
Wildcard il

2
Brillante! Perché una risposta così generosa non è in cima?
Neo

13
python -c "import platform;print(platform.platform())"

o solo

python -m platform

9
  1. lsb- * non è installato / non esiste sui sistemi CentOS o Debian di base
  2. / proc / * non esiste su OSX

Prendi un consiglio dagli sviluppatori javascript. Non testare la versione, verificare la capacità. Non è carino, ma funziona. Espandere se necessario.

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
}  

6
Yum potrebbe benissimo essere Red Hat, Scientific Linux o Fedora. C'era un comando appropriato per Fedora che mimava Debian. E così via. Basta classificare qualsiasi cosa con yum poiché CentOS ti offre una gamma di sistemi supportati da Red Hat 4 a Fedora 18, che è circa 8 anni di storia di Linux proprio lì. Se hai bisogno di sapere se <foo> è supportato, controlla nello specifico <foo> invece di indovinare in base all'identificazione della distribuzione (inaffidabile)! Certo, porta a qualcosa di simile agli autotools, ma questo non può essere aiutato (solo grazie a $ DEITY che le guerre Unix sono finite).
vonbrand il

@Vonbrand in effetti, è come dici tu. non provo a distinguere tra i sotto-sapori. e l'ordine che controllo (si spera) rimuove le situazioni più difficili (RHEL con apt-get installato), anche se non ho fatto molte ricerche. se RHEL può avere apt-get installato e gli utenti Ubuntu hanno yum ... beh, sei solo sfortunato.
Orwellophile,

6

In ordine di probabile successo, questi:

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

coprire la maggior parte dei casi (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD e forse altri.


cat /etc/*versionnon funziona (non esiste tale file) su CentOS (almeno su 6.4)
om-nom-nom

Se si esegue il comando in un contenitore, / proc / version conterrà la versione di distribuzione HOST e non quella di distribuzione del contenitore.
Dereckson,

5

Per la maggior parte dei moderni sistemi operativi Linux, il file /etc/os-releasesta diventando davvero standard e viene incluso nella maggior parte dei sistemi operativi. Quindi all'interno del tuo script Bash puoi semplicemente includere il file e avrai accesso a tutte le variabili descritte qui (ad esempio: NOME, VERSIONE, ...)

Quindi sto solo usando questo nel mio script 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

3

Se il file /etc/debian_versionesiste, la distribuzione è Debian o un derivato Debian. Questo file può avere un numero di rilascio; sulla mia macchina è attualmente 6.0.1. Se è in fase di test o instabile, potrebbe indicare testing / unstable oppure potrebbe avere il numero della versione imminente. La mia impressione è che almeno su Ubuntu, questo file sia sempre test / unstable e che non ci contengano il numero di rilascio, ma qualcuno può correggermi se sbaglio.

Fedora (almeno versioni recenti), hanno un file simile, vale a dire /etc/fedora-release.


Le versioni Debian più recenti usano invece / etc / os-release.
Dereckson,

1
@Dereckson Ho controllato la mia macchina sibilante, e ha entrambi /etc/debian_versione /etc/os-release.
Faheem Mitha,

Testato in un chroot di Jessie creato con debootstrap. Ma in effetti, una macchina locale anche sotto Jessie, questa volta installata in modo più convenzionale, contiene un /etc/debian_versionfile. Quindi il modo in cui prepariamo un'installazione Debian potrebbe influenzare i file di rilascio disponibili, questo è interessante.
Dereckson,

Debian os-releasenon include il numero di versione completo di debian_version. Vedi unix.stackexchange.com/questions/382531 .
JdeBP,


1

2 modi da molti:

1) uso

lsb_release -a

L'ho provato su CentOS 5.5 e Ubuntu 10.04

l'output per CentOS è:

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

e per Ubuntu è:

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) inserisci il seguente comando:

cat /etc/*-release

L'ho provato su CentOS 5.5 e Ubuntu 10.04 e funziona benissimo.


lsb_release non è in CentOS 6 (l'installazione minima in corso)
un programmatore

lsb_release -a restituisce "-bash: lsb_release: comando non trovato" su Raspberry con Raspbian ( derivato da Debian 7.1).
Peter Mortensen,

0

Questo script funziona su Debian (potrebbe essere necessario apportare qualche modifica su 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

0

Ecco la mia semplice versione di 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

0

Senza versione, basta solo dist:

cat /etc/issue | head -n +1 | awk '{print $1}'

Una risposta di un anno prima di Yahya Yahyaoui diceva la stessa cosa. Entrambe queste risposte sono state infatti affrontate nel 2011 in risposte che sono state successivamente cancellate. Le ragioni per cui si sbagliano sono ancora valide.
JdeBP,

0

Questo è stato testato su Ubuntu 14 e CentOS 7

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'

@don_crissti Come lo faresti?
BsdHelper,

sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
Caso

@cas Molto bello! Aggiungendolo alla mia cassetta degli attrezzi. Grazie per aver condiviso.
BsdHelper,

0

Trovo un buon script da qui che funziona per la maggior parte delle dist comuni Linux:

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


0

C'è un gioiello rubino sfaccettato , che ti fornisce alcuni fatti sul sistema operativo OS, analizza i file di rilascio del sistema operativo, altri dati e stampa sullo schermo del terminale. Puoi provare è come segue, a partire dall'installazione di rubygems:

# apt-get install rubygems

Si prega di utilizzare il caso sopra che è idoneo per il proprio sistema operativo. Quindi installare la gemma stessa.

# gem install facter

Quindi utilizzare:

$ facter

NOTA: vedere le fonti gemma facter per ottenere maggiori informazioni durante l'installazione.


0

Se qualcuno ha bisogno anche della distribuzione:

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

Produzione:

It is: 18.04

Passare a: lsb_release -sc per ottenere la distro:

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

Produzione:

It is: bionic

-3

Questo comando funziona per le distribuzioni basate su Debian e basate su Redhat: Usando il trfiltro, converti il ​​documento nel formato di una parola per riga e quindi conti la prima riga che contiene il nome della distribuzione.

tr -s ' \011' '\012' < /etc/issue | head -n 1

I commenti sulla risposta ora cancellata del 2011 che dicevano la stessa cosa, si applicano ancora. Così come la risposta errata, ancora una volta cancellata, che diceva che /etc/issuenon conteneva una versione o un nome su zenwalk. Questo è un file modificabile dall'amministratore che contiene un messaggio presentato agli umani che non ha alcuna garanzia di contenere qualcosa che può essere estratto in modo programmatico.
JdeBP,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.