¿Cómo puedo obtener el nombre de distribución y el número de versión en un script de shell simple?

191

Estoy trabajando en un script bash simple que debería poder ejecutarse en distribuciones Ubuntu y CentOS (el soporte para Debian y Fedora / RHEL sería una ventaja) y necesito saber el nombre y la versión de la distribución que ejecuta el script ( para activar acciones específicas, por ejemplo, la creación de repositorios). Hasta ahora lo que tengo es esto:

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

Esto parece funcionar, volviendo ubuntuo centos(no he probado otros) como el nombre de la versión. Sin embargo, tengo la sensación de que debe haber una manera más fácil y más confiable de descubrirlo, ¿es eso cierto?

No funciona para RedHat. / etc / redhat-release contiene: Redhat Linux Entreprise versión 5.5

Entonces, la versión no es la tercera palabra, será mejor que uses:

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
fuente
¿Estás seguro de que +-releasefunciona? Efectivamente, estás buscando que así sea /etc/lsb-release, así que quizás solo llámalo así.
Mikel
@Mikel: He sustituido *con +de evitar el comentario de formateo, que debería ser etc/*-release, parece que funciona.
Alix Axel
8
Nunca introduzca un error de sintaxis para obtener el formato correcto. Además, el formato es incorrecto solo en la vista previa, la vista final recoge la sintaxis de las etiquetas.
Gilles
¿Por qué nadie menciona esta fe uname -rv | grep -i "name_of_distro"y usa el código de salida?
fugitivo

Respuestas:

182

Para obtener OSy VER, el último estándar parece ser /etc/os-release. Antes de eso, había lsb_releasey /etc/lsb-release. Antes de eso, tenía que buscar diferentes archivos para cada distribución.

Esto es lo que sugeriría

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

Creo unameque seguir ARCHsiendo la mejor manera. Pero el ejemplo que diste obviamente solo maneja los sistemas Intel. Yo lo llamaría BITSasí:

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

O cambiar ARCHa ser las versiones más comunes, sin embargo, no ambiguos: x86y x64o similar:

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

pero por supuesto eso depende de ti.

Mikel
fuente
2
Buscaría lsb_release y lo usaría si está disponible, pero no está disponible en todas partes. Por ejemplo, no está en la instalación predeterminada de Fedora 14.
Steven D
De Verdad? ¿Intentaste deletrearlo con -y _? Tal vez está en /lib/lsbo en algún lugar así. ¿Qué rpm -qa "lsb*"imprime?
Mikel
1
rpm -qa "lsb*No imprime nada. Según yum provides */lsb_releaseestá contenido en un paquete llamado redhat-lsb que supongo que no está instalado por defecto. Sin embargo, no soy un experto en Fedora, estos son solo los resultados de una máquina virtual Fedora aleatoria que tengo y podrían estar muy equivocados.
Steven D
3
Acabo de instalar Fedora 14 en una VM, y no hay lsb-release, como dijiste.
Mikel
55
No utilice $OS, $VERSIONetc., por convención, capitalizamos las variables de entorno (PAGER, EDITOR, SHELL, ...) y las variables internas de shell (BASH_VERSION, RANDOM, ...). Todos los demás nombres de variables deben contener al menos una letra minúscula. Esta convención evita anular accidentalmente variables ambientales e internas.
Chris Down
58

Iría con esto como primer paso:

ls /etc/*release

Gentoo, RedHat, Arch y SuSE tienen un archivo llamado eg /etc/gentoo-release. Parece ser popular, consulte este sitio sobre archivos de lanzamiento .

Debian y Ubuntu también deberían tener una información /etc/lsb-releaseque contenga la versión, y se mostrará con el comando anterior.

Otro rápido es uname -rv. Si el kernel instalado es el kernel de distribución de stock, generalmente a veces encontrará el nombre allí.

Estera
fuente
En Debian, eso es uname -a.
tshepang
2
aunque no uname -rvcontiene la información? uname -aimprimirá cosas como tipo de procesador y nombre de host que son irrelevantes aquí. (Pero tanto la versión del kernel ( -r) como la versión ( -v) son necesarias, no todas las distribuciones lo hacen allí)
Mat
uname -r da 2.6.32-5-686-bigmemy uname -v da #1 SMP Tue Mar 8 22:14:55 UTC 2011en Debian 6. uname -a OTOH da Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
tshepang
la segunda parte de uname -aes -n, es decir, nodename == hostname. Entonces diría unameque no será interesante en Debian. Ahora que lo pienso, tampoco estoy seguro de que sea tan útil en RedHat.
Mat
Oh ok Así que es sólo por la suerte de que me puse mi nombre de host por defecto, debian.
tshepang
36

lsb_release -a. Funciona en Debian y supongo que Ubuntu, pero no estoy seguro del resto. Normalmente debería existir en todas las distribuciones de GNU / Linux ya que está relacionado con LSB (Linux Standard Base).

sakisk
fuente
3
No está instalado por defecto en Gentoo. Tampoco fue por defecto en Fedora en algún momento (probablemente ahora sí)
Mat
2
Esto funcionó en Debian Squeeze, Fedora 14 y OpenSUSE 11.3. En Debian y SUSE, el paquete que contenía lsb_release era lsb-release, en Fedora era redhat-lsb. Ya estaba instalado en Debian y SUSE, pero no en Fedora. Creo que esta es la mejor respuesta hasta ahora. +1.
Faheem Mitha
3
lsb_release no forma parte de la instalación mínima de CentOS 6.
un codificador
1
lsb_release -a devuelve "-bash: lsb_release: comando no encontrado" en Raspberry con Raspbian ( derivado de Debian 7.1).
Peter Mortensen
lsb_release -a funciona en Red Hat Enterprise Linux Server versión 6.6 (Santiago)
jwilleke
21

One-liner, fallbacks, una línea de salida, sin errores.

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om
Markus
fuente
Hermoso gracias. Tenga en cuenta que esto todavía no funciona en Mac OS X, pero funciona bien en Ubuntu y CentOS (que son los tres que tengo a mano).
Comodín el
2
¡Brillante! ¿Por qué una respuesta tan generosa no en la parte superior?
Neo
13
python -c "import platform;print(platform.platform())"

o solo

python -m platform
Ilya Kharlamov
fuente
9
  1. lsb- * no está instalado / no existe en sistemas CentOS o Debian base
  2. / proc / * no existe en OSX

Tome un consejo de los desarrolladores de JavaScript. No pruebe la versión, pruebe la capacidad. No es bonito, pero funciona. Ampliar según sea necesario.

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
fuente
66
Yum podría muy bien ser Red Hat, Scientific Linux o Fedora. Había un comando apto para que Fedora mimetizara a Debian. Y así. Simplemente clasificando cualquier cosa con yum, ya que CentOS le ofrece una gama de sistemas compatibles desde Red Hat 4 hasta Fedora 18, que son unos 8 años de historia de Linux allí mismo. Si necesita saber si <foo> es compatible, compruebe específicamente <foo> en lugar de adivinar basándose en una identificación de distribución (no confiable). Claro, conduce a algo así como las herramientas automáticas, pero eso no se puede evitar (solo agradezco a $ DEITY que las guerras de Unix han terminado).
vonbrand
@vonbrand de hecho, es como tú dices. No intento diferenciar entre sub-sabores. y el orden en el que me registro (con suerte) elimina la mayoría de las situaciones difíciles (RHEL con apt-get instalado), aunque no hice mucha investigación. si RHEL puede tener apt-get instalado, y los usuarios de Ubuntu tienen yum ... bueno, simplemente no tienes suerte.
Orwellophile
6

En orden de éxito más probable, estos:

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

cubre la mayoría de los casos (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD y quizás otros.

Eelvex
fuente
cat /etc/*versionno funciona (no existe tal archivo) en CentOS (al menos en 6.4)
om-nom-nom
Si ejecuta el comando en un contenedor, / proc / version contendrá la versión de distribución HOST, y no la versión de distribución del contenedor.
Dereckson
5

Para la mayoría de los sistemas operativos modernos de Linux, el archivo /etc/os-releaserealmente se está volviendo estándar y se está incluyendo en la mayoría de los sistemas operativos. Entonces, dentro de su script Bash, puede incluir el archivo y tendrá acceso a todas las variables descritas aquí (por ejemplo: NOMBRE, VERSIÓN, ...)

Así que solo estoy usando esto en mi 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
Chris Maes
fuente
3

Si el archivo /etc/debian_versionexiste, la distribución es Debian o un derivado de Debian. Este archivo puede tener un número de versión; en mi máquina es actualmente 6.0.1. Si está probando o es inestable, puede decir que está probando / inestable, o puede tener el número del próximo lanzamiento. Mi impresión es que al menos en Ubuntu, este archivo siempre está probando / inestable, y que no ponen el número de versión, pero alguien puede corregirme si estoy equivocado.

Fedora (versiones recientes al menos), tienen un archivo similar, a saber /etc/fedora-release.

Faheem Mitha
fuente
Las versiones más recientes de Debian usan / etc / os-release en su lugar.
Dereckson
1
@Dereckson Revisé mi máquina de wheezy, y tiene ambas /etc/debian_versiony /etc/os-release.
Faheem Mitha
Probado en un chroot Jessie creado con debootstrap. Pero, de hecho, una máquina local también bajo Jessie, esta vez instalada de una manera más convencional, contiene un /etc/debian_versionarchivo. Entonces, la forma en que preparamos una instalación de Debian podría afectar los archivos de lanzamiento disponibles, eso es interesante.
Dereckson
Debian os-releaseno incluye el número de versión completo de debian_version. Ver unix.stackexchange.com/questions/382531 .
JdeBP
1

2 maneras de muchos:

1) uso

lsb_release -a

Lo probé en CentOS 5.5 y Ubuntu 10.04

La salida para CentOS es:

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

y para Ubuntu es:

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) ingrese el siguiente comando:

cat /etc/*-release

Lo probé en CentOS 5.5 y Ubuntu 10.04, y funciona bien.

Sam
fuente
lsb_release no está en CentOS 6 (la instalación mínima fwiw)
un codificador
lsb_release -a devuelve "-bash: lsb_release: comando no encontrado" en Raspberry con Raspbian ( derivado de Debian 7.1).
Peter Mortensen
0

Este script funciona en Debian, (puede necesitar algunos ajustes en 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
usuario9869932
fuente
0

Aquí está mi versión 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
niceguy oh
fuente
0

Sin versión, solo dist:

cat /etc/issue | head -n +1 | awk '{print $1}'
coanor
fuente
Una respuesta del año anterior de Yahya Yahyaoui dijo lo mismo. Ambas respuestas fueron abordadas en 2011 en respuestas que desde entonces se han eliminado. Las razones por las que están equivocadas aún se aplican.
JdeBP
0

Esto fue probado en Ubuntu 14 y CentOS 7

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'
BsdHelper
fuente
@don_crissti ¿Cómo lo harías?
BsdHelper
sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
cas
@cas Muy bien! Agregando eso a mi caja de herramientas. Gracias por compartir.
BsdHelper
0

Aquí encuentro un buen script que funciona para la mayoría de los discos de Linux comunes:

#! /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
Mitril
fuente
0

Existe una joya facter ruby, que le brinda algunos datos sobre el sistema operativo del sistema operativo, analiza los archivos de lanzamiento del sistema operativo, otros datos e imprime en la pantalla del terminal. Puede intentarlo de la siguiente manera, comenzando con la instalación de rubygems:

# apt-get install rubygems

Utilice el caso anterior que sea elegible para su sistema operativo. Luego instala la gema misma.

# gem install facter

Luego use:

$ facter

NOTA: Consulte las fuentes de gemas facter para obtener más información sobre la instalación.

Малъ Скрылевъ
fuente
0

Si alguien necesita la distribución también:

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

Salida:

It is: 18.04

Cambie a: lsb_release -sc para obtener la distribución:

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

Salida:

It is: bionic
jturi
fuente
-3

Este comando funciona para distribuciones basadas en Debian y Redhat: con el trfiltro, convierte el documento al formato de una palabra por línea y luego cuenta la primera línea que contiene el nombre de la distribución.

tr -s ' \011' '\012' < /etc/issue | head -n 1
Yahya Yahyaoui
fuente
Los comentarios sobre la respuesta ahora eliminada de 2011 que decía lo mismo, todavía se aplican. Al igual que la respuesta mal colocada, nuevamente ahora eliminada, que decía que /etc/issueno contenía una versión o un nombre en zenwalk. Este es un archivo modificable por el administrador que contiene un mensaje presentado a los humanos que no tiene garantías de contener nada que pueda extraerse mediante programación.
JdeBP