Comment obtenir le nom de la distribution et le numéro de version dans un script shell simple?


191

Je travaille sur un script bash simple qui devrait pouvoir fonctionner sur les distributions Ubuntu et CentOS (la prise en charge de Debian et de Fedora / RHEL serait un plus) et j'ai besoin de connaître le nom et la version de la distribution que le script exécute ( afin de déclencher des actions spécifiques, par exemple la création de référentiels). Jusqu'à présent, voici ce que j'ai:

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

Cela semble fonctionner, revenir ubuntuou centos(je n'ai pas essayé d'autres) comme nom de version. Cependant, j’ai le sentiment qu’il doit exister un moyen plus facile et plus fiable de le savoir - est-ce vrai?

Cela ne fonctionne pas pour RedHat. / etc / redhat-release contient: Redhat Linux Entreprise version 5.5

Donc, la version n'est pas le troisième mot, vous feriez mieux d'utiliser:

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"

Êtes-vous sûr que ça +-releasemarche? Effectivement, vous pensez que ce sera le cas /etc/lsb-release, alors appelez simplement cela.
Mikel

@ Mikel: J'ai remplacé *par +pour éviter les commentaires de formatage, cela devrait être etc/*-release, cela semble fonctionner.
Alix Axel le

8
Ne jamais introduire une erreur de syntaxe pour obtenir un formatage correct. En outre, la mise en forme est incorrecte uniquement dans l'aperçu, la vue finale récupère la syntaxe à partir des balises.
Gilles le

Pourquoi personne ne mentionne cette fe uname -rv | grep -i "name_of_distro"et utilise le code de sortie?
Fugitif

Réponses:


182

Pour obtenir OSet VER, le dernier standard semble être /etc/os-release. Avant cela, il y avait lsb_releaseet /etc/lsb-release. Avant cela, vous deviez rechercher différents fichiers pour chaque distribution.

Voici ce que je suggère

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

Je pense unameque ARCHc'est toujours le meilleur moyen d'obtenir. Mais l'exemple que vous avez donné ne traite évidemment que des systèmes Intel. Je l'appellerais soit BITScomme ça:

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

Ou changer ARCHpour être les versions les plus courantes, mais sans ambiguïté: x86et x64ou similaire:

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

mais bien sûr que ça vous regarde.


2
Je voudrais vérifier lsb_release et l'utiliser s'il est disponible, mais ce n'est pas disponible partout. Par exemple, il ne fait pas partie de l'installation par défaut de Fedora 14.
Steven D

Vraiment? Avez-vous essayé de l'orthographier avec -et _? Peut-être que c'est dans /lib/lsbou quelque part comme ça. Qu'est-ce que l' rpm -qa "lsb*"impression?
Mikel

1
rpm -qa "lsb*imprime rien. Selon yum provides */lsb_releasecela, il est contenu dans un paquet appelé redhat-lsb qui, je suppose, n’est pas installé par défaut. Cependant, je ne suis pas un expert de Fedora, ce ne sont que les résultats d'un ordinateur virtuel Fedora aléatoire que j'ai et pourraient être très erronés.
Steven D

3
Vous venez d’installer Fedora 14 sur une machine virtuelle et il n’y en a pas lsb-release, comme vous l’avez dit.
Mikel

5
Ne pas utiliser $OS, $VERSIONetc - par convention, nous capitalisons les variables d' environnement (PAGER, EDITEUR, SHELL, ...) et des variables shell internes (BASH_VERSION, RANDOM, ...). Tous les autres noms de variables doivent contenir au moins une lettre minuscule. Cette convention évite de passer outre aux variables environnementales et internes accidentellement.
Chris Down

58

J'irais avec ceci dans un premier temps:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE ont un fichier appelé par exemple /etc/gentoo-release. Semble être populaire, consultez ce site sur les fichiers de version .

Debian et Ubuntu devraient avoir un /etc/lsb-releasefichier contenant les informations de publication et s'afficheront avec la commande précédente.

Un autre rapide est uname -rv. Si le noyau installé est le noyau stock distro, vous habituellement trouverez parfois le nom là - dedans.


Sur Debian, c'est uname -a.
Tshepang

2
ne uname -rvcontient pas l'information si? uname -aaffichera des éléments tels que le type de processeur et le nom d’hôte qui ne sont pas pertinents ici. (Mais la version du noyau ( -r) et la version ( -v) sont nécessaires, toutes les distributions ne le font pas de la même manière)
Mat

uname -r donne 2.6.32-5-686-bigmemet uname -v donne #1 SMP Tue Mar 8 22:14:55 UTC 2011sur Debian 6. uname -a OTOH donne Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
Tshepang

la deuxième partie de uname -ais -n, c'est-à-dire nodename == hostname. donc je dirais que unamecela ne sera pas intéressant pour Debian. À bien y penser, je ne suis pas sûr que ce soit si utile sur RedHat non plus.
Mat

Ah d'accord. Il est donc juste par chance que je mets mon nom d' hôte par défaut, debian.
Tshepang

36

lsb_release -a. Fonctionne sur Debian et Ubuntu, je suppose, mais je ne suis pas sûr du reste. Normalement, il devrait exister dans toutes les distributions GNU / Linux car il est lié à LSB (Linux Standard Base).


3
Ce n'est pas installé par défaut sur Gentoo. Ce ne fut pas par défaut sur Fedora soit à un moment donné (est probablement maintenant bien)
Mat

2
Cela fonctionnait sous Debian Squeeze, Fedora 14 et OpenSUSE 11.3. Sous Debian et SUSE, le paquet contenant lsb_release était lsb-release, sous Fedora, redhat-lsb. Il était déjà installé sur Debian et SUSE, mais pas sur Fedora. Je pense que c'est la meilleure réponse jusqu'à présent. +1
Faheem Mitha

3
lsb_release ne fait pas partie de l'installation minimale de CentOS 6.
un codeur

1
lsb_release -a renvoie "-bash: lsb_release: commande introuvable" sur Raspberry avec Raspbian ( dérivé de Debian 7.1).
Peter Mortensen

lsb_release -a fonctionne sur la version 6.6 du serveur Red Hat Enterprise Linux (Santiago)
jwilleke le

21

One-Liner, repli, une ligne de sortie, pas d'erreur.

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

Magnifique merci. Notez que cela ne fonctionne toujours pas sous Mac OS X, mais fonctionne très bien sous Ubuntu et CentOS (les trois que j’ai sous la main).
Wildcard

2
Brillant! Pourquoi une réponse aussi détaillée ne figure-t-elle pas au sommet?
Neo

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

ou juste

python -m platform

9
  1. lsb- * n'est pas installé / n'existe pas sur les systèmes CentOS ou Debian de base
  2. / proc / * n'existe pas sous OSX

Prenez un conseil des développeurs javascript. Ne testez pas la version, testez la capacité. Ce n'est pas joli, mais ça marche. Développez si nécessaire.

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 pourrait très bien être Red Hat, Scientific Linux ou Fedora. Il y avait une commande appropriée pour Fedora mimiking Debian. Etc. Il suffit de classer n'importe quoi avec yum car CentOS vous propose une gamme de systèmes pris en charge, de Red Hat 4 à Fedora 18, soit environ 8 ans d’histoire de Linux. Si vous avez besoin de savoir si <foo> est pris en charge, recherchez spécifiquement <foo> au lieu de deviner sur la base d'une identification de distribution (non fiable)! Bien sûr, cela mène à quelque chose du genre de l'autotools, mais rien ne peut y remédier (il suffit de remercier $ DEITY pour la fin des guerres Unix).
vonbrand

@vonbrand en effet, c'est comme vous le dites. Je ne tente pas de différencier les sous-saveurs. et la commande que je vérifie (espérons-le) supprime les situations les plus difficiles (RHEL avec apt-get installed), bien que je n'ai pas fait beaucoup de recherche. Si RHEL peut installer apt-get et que les utilisateurs Ubuntu ont miam ... eh bien, vous n'avez que de la chance.
Orwellophile

6

Par ordre de succès le plus probable, ceux-ci:

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

autant que je sache (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD et peut-être d’autres.


cat /etc/*versionne fonctionne pas (il n'y a pas de fichier de ce type) sur CentOS (au moins le 6.4)
om-nom-nom

Si vous exécutez la commande dans un conteneur, / proc / version contiendra la version de la distribution HOST, et non la distribution du conteneur.
Dereckson

5

Pour la plupart des systèmes d'exploitation Linux modernes, le fichier /etc/os-releasedevient vraiment standard et est inclus dans la plupart des systèmes d'exploitation. Donc, dans votre script Bash, vous pouvez simplement inclure le fichier et vous aurez accès à toutes les variables décrites ici (par exemple: NOM, VERSION, ...)

Donc, je ne fais que l'utiliser dans mon 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

Si le fichier /etc/debian_versionexiste, la distribution est Debian ou un dérivé de Debian. Ce fichier peut avoir un numéro de version; sur ma machine c'est actuellement 6.0.1. S'il teste ou est instable, il peut dire test / unstable ou le numéro de la prochaine version. Mon impression est que sur Ubuntu au moins, ce fichier est toujours en cours de test / instable, et qu’il n’y met pas le numéro de version, mais que quelqu'un puisse me corriger si je me trompe.

Fedora (au moins les versions récentes), ont un fichier similaire, à savoir /etc/fedora-release.


Les versions plus récentes de Debian utilisent plutôt / etc / os-release.
Dereckson

1
@Dereckson J'ai vérifié ma machine wheezy, et elle a les deux /etc/debian_versionet /etc/os-release.
Faheem Mitha

Testé dans un chroot Jessie créé avec debootstrap. Mais en effet, une machine locale également sous Jessie, cette fois installée de manière plus conventionnelle, contient un /etc/debian_versionfichier. Donc, la façon dont nous préparons une installation Debian pourrait affecter les fichiers de version disponibles, c'est intéressant.
Dereckson

Debian os-releasen'inclut pas le numéro de version complet de debian_version. Voir unix.stackexchange.com/questions/382531 .
JdeBP


1

2 façons de beaucoup:

1) utiliser

lsb_release -a

Je l'ai testé sur CentOS 5.5 et Ubuntu 10.04

la sortie pour CentOS est:

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

et pour Ubuntu est:

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) entrez la commande suivante:

cat /etc/*-release

Je l'ai testé sur CentOS 5.5 et Ubuntu 10.04, et cela fonctionne bien.


lsb_release n'est pas dans CentOS 6 (le min install fwiw)
un codeur

lsb_release -a renvoie "-bash: lsb_release: commande introuvable" sur Raspberry avec Raspbian ( dérivé de Debian 7.1).
Peter Mortensen

0

Ce script fonctionne sur Debian, (peut-être nécessiter quelques modifications sur 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

Voici ma version simple de 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

Sans version, juste seulement dist:

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

Une réponse de Yahya Yahyaoui, un an plus tôt, disait la même chose. En fait, ces deux réponses ont été abordées en 2011 dans des réponses qui ont été supprimées depuis. Les raisons pour lesquelles ils ont tort s'appliquent toujours.
JdeBP

0

Ceci a été testé sur Ubuntu 14 et CentOS 7

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

@don_crissti Comment le ferais-tu?
BsdHelper

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

@cas Très bien! Ajouter cela à ma boîte à outils. Merci pour le partage.
BsdHelper

0

Je trouve un bon scénario d'ici qui fonctionne pour la plupart dists linux communs:

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

Il existe une gemme ruby de faction , qui fournit des informations sur le système d’exploitation, analyse les fichiers de versions de système d’exploitation et d’autres données, puis les affiche sur l’écran du terminal. Vous pouvez essayer comme suit, en commençant par l’installation de rubygems:

# apt-get install rubygems

Veuillez utiliser le cas ci-dessus qui est éligible pour votre système d'exploitation. Ensuite, installez la gemme elle-même.

# gem install facter

Alors utilisez:

$ facter

REMARQUE: Voir les sources de gemmes du facteur pour obtenir plus d’informations lors de l’installation.


0

Si quelqu'un a aussi besoin de la distribution:

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

Sortie:

It is: 18.04

Remplacez-le par: lsb_release -sc pour obtenir la distribution:

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

Sortie:

It is: bionic

-3

Cette commande fonctionne pour les distributions basées sur Debian et Redhat: à l'aide d'un trfiltre, convertissez le document au format d'un mot par ligne, puis comptez la première ligne contenant le nom de la distribution.

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

Les commentaires sur la réponse maintenant supprimée de 2011 qui disait la même chose s'appliquent toujours. De même que la réponse mal placée, à nouveau maintenant supprimée, celle qui /etc/issuene contenait pas de version ni de nom sur zenwalk. Il s’agit d’un fichier pouvant être modifié par l’ administrateur et contenant un message présenté à l’homme sans garantie de contenir quoi que ce soit pouvant être extrait par programme.
JdeBP
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.