Como posso obter o nome da distribuição e o número da versão em um simples shell script?

191

Estou trabalhando em um script bash simples que deve ser capaz de executar nas distribuições Ubuntu e CentOS (suporte para Debian e Fedora / RHEL seria uma vantagem) e preciso saber o nome e a versão da distribuição que o script está executando ( para acionar ações específicas, por exemplo, a criação de repositórios). Até agora, o que eu tenho é o seguinte:

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

Isso parece funcionar, retornando ubuntuou centos(eu não tentei outros) como o nome do release. No entanto, sinto que deve haver uma maneira mais fácil e confiável de descobrir isso - isso é verdade?

Não funciona para o RedHat. / etc / redhat-release contém: Redhat Linux Entreprise release 5.5

Portanto, a versão não é a terceira palavra, é melhor usar:

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
fonte
Você tem certeza que +-releasefunciona? Efetivamente, você parece assumir que será /etc/lsb-release, então talvez chame assim.
Mikel
@ Mikel: Eu substituí *com +para evitar a formatação de comentários, deve ser etc/*-release, parece funcionar.
Alix Axel
8
Nunca introduza um erro de sintaxe para obter a formatação correta. Além disso, a formatação está incorreta apenas na visualização, a visualização final pega a sintaxe das tags.
Gilles
Por que ninguém menciona esse fe uname -rv | grep -i "name_of_distro"e usa o código de saída?
fugitivo

Respostas:

182

Para obter OSe VER, o último padrão parece ser /etc/os-release. Antes disso, havia lsb_releasee /etc/lsb-release. Antes disso, era necessário procurar arquivos diferentes para cada distribuição.

Aqui está o que eu sugeriria

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

Eu acho unameque conseguir ARCHainda é o melhor caminho. Mas o exemplo que você deu obviamente lida apenas com os sistemas Intel. Eu chamaria BITSassim:

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

Ou mude ARCHpara ser a versão mais comum, porém não ambígua: x86e x64ou 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

mas é claro que depende de você.

Mikel
fonte
2
Eu procuraria pelo lsb_release e o usaria se disponível, mas não está disponível em todos os lugares. Por exemplo, ele não está na instalação padrão do Fedora 14.
Steven D
Realmente? Você tentou escrever com -e _? Talvez esteja em /lib/lsbalgum lugar assim. O que rpm -qa "lsb*"imprime?
Mikel
11
rpm -qa "lsb*imprime nada. De acordo com yum provides */lsb_releaseele, está contido em um pacote chamado redhat-lsb, que eu acho que não está instalado por padrão. No entanto, eu não sou especialista no Fedora, estes são apenas os resultados de uma VM aleatória do Fedora que eu tenho e podem estar muito errados.
Steven D
3
Acabei de instalar o Fedora 14 em uma VM e não existe lsb-release, como você disse.
Mikel
5
Não use $OS, $VERSIONetc - por convenção, capitalizamos variáveis ​​de ambiente (PAGER, EDITOR, SHELL, ...) e variáveis ​​internas do shell (BASH_VERSION, RANDOM, ...). Todos os outros nomes de variáveis ​​devem conter pelo menos uma letra minúscula. Esta convenção evita a substituição acidental de variáveis ​​ambientais e internas.
Chris Baixo
58

Eu iria com isso como um primeiro passo:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE têm um arquivo chamado por exemplo /etc/gentoo-release. Parece ser popular, consulte este site sobre arquivos de lançamento .

O Debian e o Ubuntu devem ter um /etc/lsb-releaseque também contenha informações sobre a versão e aparecerá com o comando anterior.

Outra rápida é uname -rv. Se o kernel instalado é o kernel de distribuição padrão, geralmente você encontrará o nome lá.

Esteira
fonte
No Debian, é isso uname -a.
21811 tshepang
2
não uname -rvcontém as informações? uname -aimprimirá coisas como tipo de processador e nome do host que são irrelevantes aqui. (Mas tanto a liberação do kernel ( -r) quanto a versão ( -v) são necessárias, nem todas as distros fazem o mesmo por lá) #
187
uname -r2.6.32-5-686-bigmeme uname -v#1 SMP Tue Mar 8 22:14:55 UTC 2011no 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.
21411 tshepang
a segunda parte de uname -aé -n, ie nodename == hostname. então eu diria unameque não será interessante no Debian. Venha para pensar sobre isso, não tenho certeza se é tão útil no RedHat também.
Mat
Ah ok. Por isso, é apenas por sorte que eu defino meu nome de host como padrão debian,.
21411 tshepang
36

lsb_release -a. Funciona no Debian e acho que o Ubuntu, mas não tenho certeza sobre o resto. Normalmente, ele deve existir em todas as distribuições GNU / Linux, pois está relacionado ao LSB (Linux Standard Base).

sakisk
fonte
3
Não está instalado por padrão no Gentoo. Não foi por padrão no Fedora, quer em algum ponto (provavelmente é agora embora)
Mat
2
Isso funcionou no Debian squeeze, Fedora 14 e OpenSUSE 11.3. No Debian e no SUSE, o pacote contendo lsb_release era lsb-release, no Fedora era redhat-lsb. Ele já estava instalado no Debian e no SUSE, mas não no Fedora. Eu acho que essa é a melhor resposta até agora. +1.
Faheem Mitha 29/03
3
lsb_release não faz parte da instalação mínima do CentOS 6.
um codificador
11
lsb_release -a retorna "-bash: lsb_release: command not found" no Raspberry com Raspbian ( derivado do Debian 7.1).
Peter Mortensen
lsb_release -a funciona no Red Hat Enterprise Linux Server versão 6.6 (Santiago)
jwilleke
21

Uma linha, fallbacks, uma linha de saída, sem erros.

lsb_release -ds 2>/dev/null || cat /etc/*release 2>/dev/null | head -n1 || uname -om
Markus
fonte
Bonito obrigado. Observe que isso ainda não funciona no Mac OS X, mas funciona bem no Ubuntu e no CentOS (que são os três que eu tenho à mão).
Curinga
2
Brilhante! Por que uma resposta tão bonita não está no topo?
Neo
13
python -c "import platform;print(platform.platform())"

ou apenas

python -m platform
Ilya Kharlamov
fonte
9
  1. lsb- * não está instalado / não existe nos sistemas CentOS ou Debian base
  2. / proc / * não existe no OSX

Dê uma dica dos desenvolvedores de javascript. Não teste para a versão, teste para a capacidade. Não é bonito, mas funciona. Expanda conforme necessário.

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
fonte
6
Yum poderia muito bem ser Red Hat, Scientific Linux ou Fedora. Havia um comando apt para o Fedora imitando o Debian. E assim por diante. Basta classificar qualquer coisa com o yum, pois o CentOS oferece uma variedade de sistemas suportados, do Red Hat 4 ao Fedora 18, ou seja, cerca de 8 anos de história do Linux. Se você precisar saber se o <foo> é suportado, verifique especificamente o <foo> em vez de adivinhar com base na identificação da distribuição (não confiável)! Claro, isso leva a algo do tipo de ferramentas automáticas, mas isso não pode ser ajudado (apenas agradeça a $ DEITY que as guerras do Unix terminaram).
vonbrand
@ vonbrand de fato, é como você diz. Eu não tento diferenciar sub-sabores. e a ordem de check-in (espero) remove as situações mais complicadas (RHEL com o apt-get instalado), embora eu não tenha feito muita pesquisa. se o RHEL pode ter o apt-get instalado e os usuários do Ubuntu o yum ... bem, você está sem sorte.
Orwellophile
6

Na ordem do sucesso mais provável, estes:

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

cobrir a maioria dos casos (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD e talvez outros.

Eelvex
fonte
cat /etc/*versionnão funciona (não existe esse arquivo) no CentOS (pelo menos no 6.4)
om-nom-nom
Se você executar o comando em um contêiner, / proc / version conterá a versão de distribuição HOST, e não a distribuição.
Dereckson
5

Para a maioria dos sistemas Linux modernos, o arquivo /etc/os-releaseestá realmente se tornando padrão e está sendo incluído na maioria dos sistemas operacionais. Portanto, dentro do seu script Bash, você pode incluir apenas o arquivo e terá acesso a todas as variáveis ​​descritas aqui (por exemplo: NAME, VERSION, ...)

Então, eu estou apenas usando isso no meu 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
fonte
3

Se o arquivo /etc/debian_versionexistir, a distribuição é Debian ou um derivado do Debian. Este arquivo pode ter um número de versão; na minha máquina está atualmente 6.0.1. Se estiver testando ou instável, pode dizer que está testando / instável ou pode ter o número da próxima versão. Minha impressão é que no Ubuntu, pelo menos, esse arquivo está sempre testando / instável e que eles não colocam o número do release, mas alguém pode me corrigir se eu estiver errado.

O Fedora (lançamentos recentes, pelo menos), tem um arquivo semelhante, a saber /etc/fedora-release.

Faheem Mitha
fonte
Versões mais recentes do Debian usam / etc / os-release.
Dereckson
11
@Deckeckson eu verifiquei minha máquina chiado, e tem ambos /etc/debian_versione /etc/os-release.
Faheem Mitha 24/03
Testado em um chroot Jessie criado com debootstrap. Mas, de fato, uma máquina local também sob Jessie, desta vez instalada de maneira mais convencional, contém um /etc/debian_versionarquivo. Portanto, a maneira como preparamos uma instalação Debian pode afetar os arquivos de lançamento disponíveis, isso é interessante.
Dereckson 28/03
O Debian os-releasenão inclui o número da versão completa de debian_version. Consulte unix.stackexchange.com/questions/382531 .
JdeBP
1

2 maneiras de muitos:

1) use

lsb_release -a

Eu testei no CentOS 5.5 e Ubuntu 10.04

a saída para o 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 para o 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) digite o seguinte comando:

cat /etc/*-release

Eu testei no CentOS 5.5 e no Ubuntu 10.04, e funciona bem.

Sam
fonte
lsb_release não é no CentOS 6 (a instalar min fwiw)
um codificador
lsb_release -a retorna "-bash: lsb_release: command not found" no Raspberry com Raspbian ( derivado do Debian 7.1).
Peter Mortensen
0

Este script funciona no Debian, (pode precisar de alguns ajustes no 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
user9869932
fonte
0

Aqui está minha versão simples do 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
fonte
0

Sem versão, apenas apenas dist:

cat /etc/issue | head -n +1 | awk '{print $1}'
coanor
fonte
Uma resposta de um ano antes, de Yahya Yahyaoui, disse a mesma coisa. De fato, essas duas respostas foram abordadas em 2011 em respostas que foram excluídas desde então. As razões pelas quais eles estão errados ainda se aplicam.
21417 JdeBP
0

Isso foi testado no Ubuntu 14 e CentOS 7

cat /etc/os-release | grep "PRETTY_NAME" | sed 's/PRETTY_NAME=//g' | sed 's/["]//g' | awk '{print $1}'
BsdHelper
fonte
@don_crissti Como você faria isso?
BsdHelper 23/11/2015
sed -n -e '/PRETTY_NAME/ s/^.*=\|"\| .*//gp' /etc/os-release
cas 23/11
@cas Muito bom! Adicionando isso à minha caixa de ferramentas. Obrigado por compartilhar.
BsdHelper
0

Eu acho um bom script daqui que funciona para a maioria dos discos Linux comuns:

#! /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
Mithril
fonte
0

Existe uma faceta ruby gem, que fornece alguns fatos sobre o SO, ele analisa os arquivos de liberação do SO, outros dados e imprime na tela do terminal. Você pode tentar da seguinte forma, começando com a instalação do rubygems:

# apt-get install rubygems

Use o caso acima que é elegível para o seu sistema operacional. Em seguida, instale a própria jóia.

# gem install facter

Então use:

$ facter

NOTA: Consulte as fontes das pedras preciosas para obter mais informações sobre a instalação.

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

Se alguém precisar da distribuição também:

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

Resultado:

It is: 18.04

Mude para: lsb_release -sc para obter a distribuição:

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

Resultado:

It is: bionic
jturi
fonte
-3

Este comando funciona para distribuições baseadas no Debian e no Redhat: Usando o trfiltro, você converte o documento para o formato de uma palavra por linha e depois conta a primeira linha que contém o nome da distribuição.

tr -s ' \011' '\012' < /etc/issue | head -n 1
Yahya Yahyaoui
fonte
Os comentários sobre a resposta agora excluída de 2011 que diziam a mesma coisa ainda se aplicam. Assim como a resposta mal colocada, novamente excluída, disse que /etc/issuenão continha uma versão ou um nome no zenwalk. Este é um arquivo modificável pelo administrador que contém uma mensagem apresentada a humanos que não tem garantias de conter qualquer coisa que possa ser extraída programaticamente.
JdeBP 29/07