Как получить имя дистрибутива и номер версии в простом сценарии оболочки?


191

Я работаю над простым bash-скриптом, который должен быть в состоянии работать в дистрибутивах Ubuntu и CentOS (поддержка Debian и Fedora / RHEL была бы плюсом), и мне нужно знать имя и версию дистрибутива, в котором работает скрипт ( для того, чтобы вызвать конкретные действия, например, создание хранилищ). Пока что у меня есть это:

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

Это , кажется , работать, возвращаясь ubuntuили centos(я не пробовал другие) в качестве имени выпуска. Однако у меня есть ощущение, что должен быть более простой и надежный способ выяснить это - правда ли это?

Это не работает для RedHat. / etc / redhat-release содержит: Redhat Linux Entreprise выпуск 5.5

Итак, версия не третье слово, вам лучше использовать:

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"

Вы уверены, что +-releaseработает? По сути, вы ищете, если это /etc/lsb-releaseтак, так что, возможно, просто назовите это так.
Микель

@Mikel: Я заменил *на, +чтобы избежать формирования комментариев, должно быть etc/*-release, это похоже на работу.
Аликс Аксель

8
Никогда не вводите синтаксическую ошибку для правильного форматирования. Кроме того, форматирование является неправильным только в предварительном просмотре, окончательное представление выбирает синтаксис из тегов.
Жиль

Почему никто не упоминает об этом uname -rv | grep -i "name_of_distro"и не использует код выхода?
Беглец

Ответы:


182

Для того, чтобы получить OSи VER, последний стандарт , кажется /etc/os-release. До этого было lsb_releaseи /etc/lsb-release. До этого вам приходилось искать разные файлы для каждого дистрибутива.

Вот что я бы посоветовал

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

Я думаю, unameчто получить ARCHвсе еще лучший способ. Но приведенный вами пример, очевидно, касается только систем Intel. Я бы назвал это BITSтак:

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

Или изменить , ARCHчтобы быть более распространенными, но однозначные варианты: x86и x64или аналогичные:

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

но, конечно, это зависит от вас.


2
Я бы проверил lsb_release и использовал бы его, если он доступен, но он доступен не везде. Например, это не входит в стандартную установку Fedora 14.
Steven D

В самом деле? Вы пытались записать это с помощью -и _? Может быть, это /lib/lsbили где-то так. Что rpm -qa "lsb*"печатает?
Микель

1
rpm -qa "lsb*ничего не печатает. В соответствии с yum provides */lsb_releaseэтим он содержится в пакете с именем redhat-lsb, который, по-моему, не установлен по умолчанию. Тем не менее, я не эксперт по Fedora, это просто результаты случайной виртуальной машины Fedora, которая у меня есть, и я могу ошибаться.
Стивен Д.

3
Просто установил Fedora 14 в ВМ, а там нет lsb-release, как ты сказал.
Микель

5
Не используйте $OSи $VERSIONт. Д. - по договоренности мы используем заглавные переменные среды (PAGER, EDITOR, SHELL, ...) и переменные внутренней оболочки (BASH_VERSION, RANDOM, ...). Все остальные имена переменных должны содержать хотя бы одну строчную букву. Это соглашение позволяет избежать случайного переопределения внешних и внутренних переменных.
Крис Даун

58

Я бы пошел с этим в качестве первого шага:

ls /etc/*release

Gentoo, RedHat, Arch & SuSE имеют файл с именем eg /etc/gentoo-release. Кажется популярным, проверьте этот сайт на предмет релиз-файлов .

У Debian & Ubuntu должен быть /etc/lsb-releaseфайл с информацией о выпуске, который будет отображаться с предыдущей командой.

Еще один быстрый uname -rv. Если установленное ядро ​​является стандартным дистрибутивным ядром, вы обычно можете найти его там.


На Debian это так uname -a.
Чепанг

2
не uname -rvсодержит информацию, хотя? uname -aбудет печатать такие вещи, как тип процессора и имя хоста, которые здесь не имеют значения. (Но необходимы и kernel release ( -r), и version ( -v), не все дистрибутивы делают это там одинаково)
Mat

uname -r дает 2.6.32-5-686-bigmemи uname -v дает #1 SMP Tue Mar 8 22:14:55 UTC 2011на Debian 6. uname -a OTOH дает Linux debian 2.6.32-5-686-bigmem #1 SMP Tue Mar 8 22:14:55 UTC 2011 i686 GNU/Linux.
Чепанг

вторая часть uname -a- -nэто имя узла == имя хоста. так что я бы сказал, unameчто не будет интересно на Debian. Если подумать, я не уверен, что это так полезно на RedHat.
Мат

О хорошо Так что мне просто повезло, что я установил имя хоста по умолчанию debian.
Чепанг

36

lsb_release -a, Работает на Debian, и я думаю, Ubuntu, но я не уверен в остальном. Обычно он должен существовать во всех дистрибутивах GNU / Linux, поскольку он связан с LSB (Linux Standard Base).


3
Он не установлен по умолчанию в Gentoo. Это не было по умолчанию на Fedora либо в какой-то момент (возможно, сейчас, хотя)
Мат

2
Это работало на Debian Squeeze, Fedora 14 и OpenSUSE 11.3. В Debian и SUSE пакет, содержащий lsb_release, был lsb-release, в Fedora это был redhat-lsb. Он уже был установлен на Debian и SUSE, но не на Fedora. Я думаю, что это лучший ответ на данный момент. +1.
Фахим Митха

3
lsb_release не является частью минимальной установки CentOS 6.
кодер

1
lsb_release -a возвращает "-bash: lsb_release: команда не найдена" в Raspberry с Raspbian (производная от Debian 7.1).
Питер Мортенсен

lsb_release -a работает с Red Hat Enterprise Linux Server версии 6.6 (Сантьяго)
jwilleke

21

Один вкладыш, запасные варианты, одна строка вывода, ошибок нет.

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

Красиво, спасибо. Обратите внимание, что это по-прежнему не работает в Mac OS X, но оно прекрасно работает в Ubuntu и CentOS (которые мне пригодятся).
Подстановочный

2
Brilliant! Почему такой красивый ответ не на вершине?
Neo


9
  1. lsb- * не установлен / не существует в базовых системах CentOS или Debian
  2. / proc / * не существует в OSX

Воспользуйтесь советами разработчиков JavaScript. Не проверяйте версию, проверяйте ее возможности. Это не красиво, но это работает. Расширяйте по мере необходимости.

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 вполне может быть Red Hat, Scientific Linux или Fedora. Была подходящая команда для Fedora, имитирующая Debian. И так далее. Просто объясните что-нибудь с помощью yum, поскольку CentOS предоставляет вам широкий выбор поддерживаемых систем от Red Hat 4 до Fedora 18, что составляет 8 лет истории Linux. Если вам нужно знать, поддерживается ли <foo>, определите для <foo>, вместо того, чтобы угадывать, основываясь на (ненадежной) идентификации распространения! Конечно, это приводит к чему-то вроде автоинструментов, но с этим ничего не поделаешь (просто поблагодарите $ DEITY за то, что войны в Unix закончились).
vonbrand

@ Vonbrand действительно, это, как вы говорите. я не пытаюсь различать подвкусы. и порядок, в котором я регистрируюсь (надеюсь), удаляет большинство хитрых ситуаций (RHEL с установленным apt-get), хотя я не проводил много исследований. если у RHEL может быть установлен apt-get, а у пользователей Ubuntu есть yum ... ну, вам просто не повезло.
Орвеллофил

6

В порядке наиболее вероятного успеха, они:

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

охватывает большинство случаев (AFAIK): Debian, Ubuntu, Slackware, Suse, Redhat, Gentoo, * BSD и, возможно, другие.


cat /etc/*versionне работает (такого файла нет) на CentOS (хотя бы на 6.4)
om-nom-nom

Если вы запустите команду в контейнере, то / proc / version будет содержать версию распространения HOST, а не версию распространения контейнера.
Дерексон

5

Для большинства современных систем ОС Linux этот файл /etc/os-releaseдействительно становится стандартным и включается в большинство ОС. Таким образом, в вашем скрипте Bash вы можете просто включить файл, и у вас будет доступ ко всем переменным, описанным здесь (например: NAME, VERSION, ...)

Так что я просто использую это в моем скрипте 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

Если файл /etc/debian_versionсуществует, дистрибутив - Debian или производная Debian. Этот файл может иметь номер выпуска; на моей машине это в данный момент 6.0.1. Если он тестовый или нестабильный, он может сказать «тестирование / нестабильный», или он может иметь номер следующего выпуска. У меня сложилось впечатление, что, по крайней мере, в Ubuntu этот файл всегда тестируется / нестабилен, и что в него не входит номер выпуска, но кто-то может исправить меня, если я ошибаюсь.

У Fedora (по крайней мере, последние выпуски) есть похожий файл, а именно /etc/fedora-release.


Более новые версии Debian используют / etc / os-release.
Дерексон

1
@Dereckson Я проверил свой хриплый аппарат, и у него есть и то, /etc/debian_versionи другое /etc/os-release.
Фахим Мита

Протестировано в chroot Джесси, созданной с помощью debootstrap. Но на самом деле, локальная машина также под управлением Джесси, на этот раз установленная более обычным способом, содержит /etc/debian_versionфайл. Поэтому то, как мы готовим установку Debian, может повлиять на доступные файлы релизов, это интересно.
Дерексон

Debian's os-releaseне включает полный номер версии от debian_version. См. Unix.stackexchange.com/questions/382531 .
JdeBP

2

Если вы не можете или не хотите использовать файл релиза LSB (из-за зависимостей, входящих в пакет), вы можете искать специфичные для дистрибутива файлы релиза. У Bcfg2 есть зонд для дистрибутива, который вы можете использовать: http://trac.mcs.anl.gov/projects/bcfg2/browser/doc/server/plugins/probes/group.txt


1

2 способа из многих:

1) использовать

lsb_release -a

Я тестировал его на CentOS 5.5 и Ubuntu 10.04

выход для 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

и для 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) введите следующую команду:

cat /etc/*-release

Я протестировал его на CentOS 5.5 и Ubuntu 10.04, и он отлично работает.


lsb_release отсутствует в CentOS 6 (минимальная установка fwiw)
кодер

lsb_release -a возвращает "-bash: lsb_release: команда не найдена" в Raspberry с Raspbian (производная от Debian 7.1).
Питер Мортенсен

0

Этот скрипт работает на Debian, (возможно, потребуется немного изменить 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

Вот моя простая версия 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

Без версии, только только dist:

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

Ответ Яхья Яхъяуи годом ранее сказал то же самое. Оба эти ответа фактически были рассмотрены в 2011 году в ответах, которые были впоследствии удалены. Причины, по которым они ошибаются, все еще применяются.
JdeBP

0

Это было проверено на Ubuntu 14 и CentOS 7

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

@don_crissti Как бы вы это сделали?
BsdHelper

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

@cas Очень приятно! Добавив это к моему набору инструментов. Спасибо, что поделились.
BsdHelper

0

Я считаю , хороший сценарий отсюда , который работает для большинства распространенного dists 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

Существует так называемый гем ruby, который дает вам некоторые факты об ОС OS, он анализирует файлы релизов ОС, другие данные и распечатывает их на экране терминала. Вы можете попробовать это следующим образом, начиная с установки rubygems:

# apt-get install rubygems

Пожалуйста, используйте приведенный выше случай, который подходит для вашей ОС. Затем установите сам драгоценный камень.

# gem install facter

Тогда используйте:

$ facter

ПРИМЕЧАНИЕ: см. Источники драгоценных камней facter, чтобы получить больше информации при установке.


0

Если кому-то также нужен дистрибутив:

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

Выход:

It is: 18.04

Измените на: lsb_release -sc, чтобы получить дистрибутив:

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

Выход:

It is: bionic

-3

Эта команда работает для дистрибутивов на основе Debian и Redhat: Используя trфильтр, вы конвертируете документ в формат по одному слову на строку, а затем подсчитываете первую строку, содержащую имя дистрибутива.

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

Комментарии к удаленному в 2011 году ответу, в котором говорится то же самое, все еще применяются. Как и неправильный ответ, теперь снова удаленный, который сказал, что /etc/issueне содержит версию или имя на zenwalk. Это модифицируемый администратором файл, содержащий сообщение, представленное людям, без гарантий , что он может содержать что-либо, что можно извлечь программным путем.
JdeBP
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.