Como descubro qual versão do Linux está sendo executada?

29

Às vezes, seus scripts precisam se comportar de maneira diferente em diferentes Linuxs. Como posso determinar em qual versão do Linux um script está sendo executado?

jldugger
fonte
1
Por versão, você quer dizer a versão do kernel? Que distribuição? A versão distro?
Chris Upchurch #
2
Tenho certeza que o jldugger deseja descobrir qual família de distribuição o sistema está executando. É improvável que um script seja afetado pela versão do kernel, a menos que dependa de algumas coisas / sys ou / proc - e mesmo assim geralmente é mais fácil assumir com base na distribuição do que no kernel.
Mihai Limbăşan

Respostas:

27

Não tente fazer suposições com base na distribuição do que você pode ou não fazer, pois dessa maneira está a loucura (consulte também "Detecção do agente do usuário"). Em vez disso, detecte se o que você deseja fazer é suportado e como é feito por qualquer comando ou local do arquivo que você deseja usar.

Por exemplo, se você deseja instalar um pacote, pode detectar se está em um sistema semelhante ao Debian ou no sistema RedHat, verificando a existência de dpkg ou rpm (verifique primeiro o dpkg, porque as máquinas Debian podem ter o comando rpm neles ...). Decida o que fazer com base nisso, não apenas se é um sistema Debian ou RedHat. Dessa forma, você suportará automaticamente todas as distribuições derivadas nas quais você não programou explicitamente. Ah, e se o seu pacote exigir dependências específicas, teste-as também e informe ao usuário o que está faltando.

Outro exemplo é mexer com interfaces de rede. Elabore o que fazer com base no fato de haver um arquivo / etc / network / interfaces ou um diretório / etc / sysconfig / network-scripts e siga a partir daí.

Sim, é mais trabalho, mas, a menos que você queira refazer todos os erros que os desenvolvedores da Web cometeram na última década ou mais, você o fará da maneira mais inteligente desde o início.

mulher
fonte
1
(Expandindo esta resposta) A detecção de recursos é preferível em algumas situações, mas certifique-se de nunca tentar adivinhar a distribuição a partir dos recursos que você detectar! Não interprete mal a resposta e verifique se a plataforma é RedHat com base em quais arquivos estão no / etc. Se você realmente precisa do nome da distribuição, verifique lsb_release (ou / etc / redhat-release, e assim por diante).
Nicholas Wilson
36

Não há maneira de distribuição cruzada. Contudo:

  • Redhat e amigos: teste /etc/redhat-release, verifique o conteúdo
  • Debian: Teste /etc/debian_version, verifique o conteúdo
  • Mandriva e amigos: teste /etc/version, verifique o conteúdo
  • Slackware: Teste /etc/slackware-version, verifique o conteúdo

Etc. De um modo geral, verifique /etc/*-releasee /etc/*-version.


Edit: Encontrei um antigo script bash meu (1+ anos) por aí que eu devo ter misturado ao longo dos anos (ele tem um impressionante registro CVS que remonta a 6 anos). Pode não funcionar mais corretamente como está e não se preocupe em encontrar distribuições instaladas para testar, mas deve fornecer um bom ponto de partida. Funciona bem no CentOS, Fedora e Gentoo. O gyaresu testou com sucesso no Debian Lenny.

#!/bin/bash

get_distribution_type()
{
    local dtype
    # Assume unknown
    dtype="unknown"

    # First test against Fedora / RHEL / CentOS / generic Redhat derivative
    if [ -r /etc/rc.d/init.d/functions ]; then
        source /etc/rc.d/init.d/functions
        [ zz`type -t passed 2>/dev/null` == "zzfunction" ] && dtype="redhat"

    # Then test against SUSE (must be after Redhat,
    # I've seen rc.status on Ubuntu I think? TODO: Recheck that)
    elif [ -r /etc/rc.status ]; then
        source /etc/rc.status
        [ zz`type -t rc_reset 2>/dev/null` == "zzfunction" ] && dtype="suse"

    # Then test against Debian, Ubuntu and friends
    elif [ -r /lib/lsb/init-functions ]; then
        source /lib/lsb/init-functions
        [ zz`type -t log_begin_msg 2>/dev/null` == "zzfunction" ] && dtype="debian"

    # Then test against Gentoo
    elif [ -r /etc/init.d/functions.sh ]; then
        source /etc/init.d/functions.sh
        [ zz`type -t ebegin 2>/dev/null` == "zzfunction" ] && dtype="gentoo"

    # For Slackware we currently just test if /etc/slackware-version exists
    # and isn't empty (TODO: Find a better way :)
    elif [ -s /etc/slackware-version ]; then
        dtype="slackware"
    fi
    echo $dtype
}

Observe que isso provavelmente só funcionará corretamente no Bash. Você pode reescrevê-lo para outras conchas.

Dito isto, você pode querer testar recursos, não distribuições. Não estou mais usando isso simplesmente porque se tornou um fardo de manutenção. É mais fácil confiar em ferramentas e soluções de distribuição cruzada.


Conceitualmente, o que faz é, em ordem:

  • Pegue um tipo conhecido de arquivo "common init function function". Esses são específicos da distribuição. Se não existir, pule para a próxima verificação de distribuição.
  • Verifique a existência de uma função específica, conhecida por existir, frequentemente usada e improvável de ser renomeada nesse script principal. Fazemos isso usando o typeBash embutido. type -tretorna functionse esse símbolo é uma função. Anexamos zza saída de type -t 2>/dev/nullporque, se o nome não for definido, a string de saída estará vazia e obteremos um erro de sintaxe sobre a falta de uma mão esquerda para o ==operador. Se o nome que acabamos de verificar não for uma função, pule para a próxima verificação de distribuição, caso contrário, encontramos o tipo de distribuição.
  • Por fim, faça eco do tipo de distribuição para que a saída da função possa ser facilmente usada em um caso .. bloco esac.

Edite caso esteja tentando executar isso como um script direto: esse script deve ser obtido ou incluído em outros scripts. Ele não produz nada por si só, se você o executar como está. Para testá-lo, obtenha-o e, em seguida, chame a função, por exemplo:

source /path/to/this/script.sh
get_distribution_type

no prompt do bash.


Editar: Observe que este script não requer privilégios de root. Peço que você não o execute como root. Não deve prejudicar nada, mas não há necessidade.


Encontrou um link para uma postagem relevante na lista de discussão no log do CVS. Deve ser útil para desembrulhar o espaguete de script init.

Mihai Limbăşan
fonte
Eu não olhei o porquê, mas ele retorna ao prompt do Debian Lenny (5.0).
530 Gareth
gyaresu, você realmente invocou a função get_distribution_type? Eu editei o post para esclarecer (ver na parte inferior.)
Mihai Limbăşan
@gyaresu: Se o problema acima não foi o problema, você pode substituir o log_begin_msg na seção Debian por log_warning_msg e tentar novamente? Pode ter errado o nome da função. De qualquer forma, ele deveria ter retornado "desconhecido" se essa função não fosse antiga, mas ainda assim.
Mihai Limbăşan
@Mihai Doh! Desculpe. Não leu o script corretamente. Era cedo, sem café. Peço desculpas. gyaresu @ debian: ~ / bin $ server_version.sh de origem gyaresu @ debian: ~ / bin $ get_distribution_type debian
Gareth
@gyaresu: Obrigado! Isso é bom, deve ajudar jldugger saber que ele funciona em Debian assim :)
Mihai Limbăşan
17

Você pode encontrar a versão do kernel executando uname -a, localizando a versão da distribuição depende da distribuição.

No Ubuntu e em algum outro sistema operacional, você pode executar lsb_release -aou ler / etc / lsb_release

O Debian armazena a versão em / etc / debian_version

Adam Gibbins
fonte
+1 para lsb_release (também funciona em derivados da Red Hat se o pacote certo está instalado)
Josh Kelley
apenas para a descrição 'lsb_release -ds'.
Flickerfly 12/09
6

A maioria das distros possui um método único para determinar a distribuição específica.

Por exemplo:

Redhat (And derivatives): /etc/redhat-release

SUSE: /etc/SUSE-release

Existe um padrão conhecido como Linux Standard Base ou LSB . Ele define que deve haver um arquivo chamado / etc / lsb-release ou um programa chamado lsb_release que retornará informações sobre sua distribuição Linux.

lsb_release -a
Mark Turner
fonte
E, lsb_releaseé claro, não existe no CentOS 6. #
Justin
6
python -c 'import platform ; print platform.dist()[0]'

código: http://hg.python.org/cpython/file/2.7/Lib/platform.py

jkeogh
fonte
Boa ideia. Eu sugeriria o uso python -c 'import platform; print(platform.dist()[0])', porque dessa maneira também funciona se o python normal usar como padrão python3.
precisa
5

Além das outras respostas: Se você deseja apenas analisar um arquivo, a maioria das distros personaliza o login tty via / etc / issue, por exemplo:

Bem-vindo ao SUSE Linux Enterprise Server 10 SP2 (i586) - Kernel \ r (\ l).

E sim, eu sei que é subótimo. :)


fonte
Pode estar abaixo do ideal, mas está no mesmo lugar.
238 Brad Brad Gilbert
4

O facter é uma ferramenta útil para esse tipo de descoberta, embora provavelmente use alguns dos métodos detalhados acima e exija Ruby.

Cawflands
fonte
2

Tudo que você precisa fazer é digitar uname -ano seu shell favorito. Isso imprimirá o nome e a versão do kernel.


fonte
2

Eu descobri que cat /etc/*release*quase sempre funciona.

ibuys
fonte
2

Concordo com Mark, Adam e Mihai (não posso votar devido à reputação insuficiente). As soluções baseadas no LSB e na sua ESF relativa funcionarão com a maioria das distribuições e provavelmente continuarão trabalhando no futuro. LSB e FHS são seus amigos.

David J. Liszewski
fonte
2

Você também pode obter a versão

cat /proc/version

o / p:

Versão Linux 2.6.17-13mdv ([email protected]) (versão gcc 4.1.2 20070302 (pré-lançamento) (4.1.2-1mdv2007.1)) # 1 SMP Fri Mar 23 19:03:31 UTC 2007

prasanna
fonte
1

A versão do linux é uma pergunta difícil. Se olharmos de perto, temos a versão do kernel que você pode obter com " uname -r". A versão de distribuição é principalmente irrelevante. Algumas distribuições são melhores (distribuições corporativas, como o Redhat Enterprise Linux). Outras distribuições como o Gentoo são basicamente alvos móveis que não possuem nenhuma versão sensata. Se você precisar fazer as coisas com base na versão, dê uma olhada nos principais componentes que são relevantes para você:

Component       Version command
glibc           /lib/libc.so.6
gcc             gcc --version
X               xdpyinfo
libX11          pkg-config --modversion x11
gtk+            pkg-config --modversion gtk+-2.0
qt-4            pkg-config --modversion QtCore

   etc...
Paul de Vrieze
fonte
1

Você também pode verificar o menu Grub, geralmente fornece várias informações sobre a distribuição / versão :-)

Antoine Benkemoun
fonte
-1

O FusionInventory é uma ferramenta de inventário leve multiplataforma que pode obter essas informações em muitas distribuições Linux, mas também em BSDs, Windows, MacOS X e outros departamentos.

Se disponíveis, eles usam lsb_release(como mencionado algumas vezes acima), mas se não tiverem uma lista muito útil de arquivos e expressões regulares para verificar o nome e a versão da distribuição: https://github.com/fusinv/fusioninventory-agent/ blob / 2.2.x / lib / FusionInventory / Agent / Task / Inventory / Input / Linux / Distro / NonLSB.pm # L16 .

Eu recomendaria usar o próprio FusionInventory para obter essas informações, em vez de reimplementar seus próprios scripts com essa lógica, pois a comunidade deles manterá essa funcionalidade atualizada. Você pode usar o agente por si próprio (ele gera um arquivo XML / JSON que é fácil de analisar) ou associá-lo a uma solução mais ampla para gerenciar as máquinas em sua rede como GLPI ou Rudder , dependendo de suas necessidades.

Jonathan Clarke
fonte
Esta seria uma boa solução se não tem dependências externas de módulos Perl
Will Sheppard