Как узнать, какая версия Linux работает?

29

Иногда ваши скрипты должны вести себя по-разному на разных Linux. Как я могу определить, на какой версии Linux работает скрипт?

jldugger
источник
1
Под версией вы подразумеваете версию ядра? Какое распределение? Дистрибутивная версия?
Крис Апчерч
2
Я уверен, что jldugger хочет выяснить, какое семейство дистрибутивов работает в системе. Маловероятно, что скрипт будет зависеть от версии ядра, если он не зависит от некоторых компонентов / sys или / proc - и даже в этом случае обычно легче предположить, основываясь на распространении, чем на ядре.
Михай Лимбашан

Ответы:

27

Не пытайтесь делать предположения, основанные на дистрибутиве, относительно того, что вы можете и не можете сделать, потому что в этом и заключается безумие (см. Также «Обнаружение агента пользователя»). Вместо этого определите, поддерживается ли то, что вы хотите сделать, и как это делается с помощью любой команды или местоположения файла, которое вы хотите использовать.

Например, если вы хотите установить пакет, вы можете определить, находитесь ли вы в Debian-подобной системе или в RedHat-подобной системе, проверив наличие dpkg или rpm (сначала проверьте dpkg, потому что машины Debian могут иметь команда rpm на них ...). Примите решение о том, что делать, основываясь на этом, а не только на том, является ли это системой Debian или RedHat. Таким образом, вы автоматически будете поддерживать любые производные дистрибутивы, в которых вы явно не программировали. О, и если вашему пакету требуются определенные зависимости, то тоже проверьте их и сообщите пользователю, что им не хватает.

Другой пример - возиться с сетевыми интерфейсами. Подумайте, что делать, основываясь на том, есть ли файл / etc / network / interfaces или каталог / etc / sysconfig / network-scripts, и перейдите оттуда.

Да, это больше работы, но если вы не хотите исправить все ошибки, которые веб-разработчики допустили за последнее десятилетие или более, вы сделаете это с умом с самого начала.

romble
источник
1
(Продолжая этот ответ) В некоторых ситуациях предпочтительнее обнаружение функций, но убедитесь, что вы никогда не пытаетесь угадать распределение по обнаруженным функциям! Не читайте неправильно ответ и выясните, является ли платформа RedHat, основываясь на том, какие файлы находятся в / etc. Если вам действительно нужно имя дистрибутива, проверьте lsb_release (или / etc / redhat-release, и так далее).
Николас Уилсон
36

Там нет пути кросс-распределения. Тем не мение:

  • Redhat и друзья: проверить /etc/redhat-release, проверить содержимое
  • Debian: проверить /etc/debian_version, проверить содержимое
  • Мандрива и друзья: проверить /etc/version, проверить содержание
  • Slackware: проверить /etc/slackware-version, проверить содержимое

И т.д. Вообще говоря, проверьте /etc/*-releaseи /etc/*-version.


Редактировать: Нашел старый (1+ лет) мой скрипт bash, который лежал без дела, и который я, должно быть, выковывал вместе на протяжении многих лет (он имеет впечатляющий журнал CVS за 6 лет). Он может больше не работать должным образом, как есть, и я могу Не беспокойтесь о том, чтобы найти установленные дистрибутивы для тестирования, но это должно послужить хорошей отправной точкой. Он отлично работает на CentOS, Fedora и Gentoo. gyaresu успешно проверил его на 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
}

Обратите внимание, что это, вероятно, будет работать правильно только в Bash. Вы могли бы переписать его для других оболочек.

Тем не менее, вы можете проверить возможности, а не дистрибутивы. Я больше этим не пользуюсь просто потому, что это стало бременем для обслуживания. Проще полагаться на кросс-дистрибутивные инструменты и решения.


Концептуально, что он делает, по порядку:

  • Извлеките файл с известным типом «общая функция сценария инициализации». Это зависит от распределения. Если он не существует, перейдите к следующей проверке распространения.
  • Проверьте наличие определенной, известной, часто используемой и вряд ли переименованной функции из этого основного сценария. Мы делаем это с помощью typeвстроенного Bash. type -tвозвращает, functionесли этот символ является функцией. Мы подходим zzк выводу из, type -t 2>/dev/nullпотому что, если имя не определено, выходная строка будет пустой, и мы получим синтаксическую ошибку об отсутствующей левой руке ==оператора. Если имя, которое мы только что проверили, не является функцией, перейдите к следующей проверке распространения, в противном случае мы нашли тип распространения.
  • Наконец, укажите тип распределения, чтобы выходные данные функции можно было легко использовать в блоке case ... esac.

Отредактируйте, если вы пытаетесь запустить его как прямой сценарий: предполагается, что этот сценарий получен из других сценариев или включен в него. Он ничего не выводит сам по себе, если вы запускаете его как есть. Чтобы проверить это, создайте его, а затем вызовите функцию, например:

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

в приглашении bash.


Изменить: Обратите внимание, что этот скрипт не требует привилегий root. Я призываю вас не запускать его как root. Ничего не должно навредить, но в этом нет необходимости.


Нашел ссылку на соответствующую запись в списке рассылки в журнале CVS. Должно быть полезно при распаковке спагетти сценария инициализации.

Михай Лимбашан
источник
Я не посмотрел почему, но он возвращает приглашение Debian Lenny (5.0).
Гарет
gyaresu, вы на самом деле вызывали функцию get_distribution_type? Я отредактировал пост, чтобы уточнить (см. Внизу.)
Михай Лимбашан
@gyaresu: Если вышеописанное не было проблемой, не могли бы вы попробовать заменить log_begin_msg в разделе Debian на log_warning_msg и повторить попытку? Возможно, ошиблись именем функции. В любом случае, он должен был вернуть «неизвестно», если бы эта функция была не раньше, но все же.
Михай Лимбашан
@ Михай Дох! Сожалею. Не правильно прочитал сценарий. Был рано, кофе нет. Мои извинения. gyaresu @ debian: ~ / bin $ source server_version.sh gyaresu @ debian: ~ / bin $ get_distribution_type debian
Гарет,
@gyaresu: Спасибо! Это хорошо, должно помочь jldugger знать, что он работает и на Debian :)
Михай Лимбашан
17

Вы можете найти версию ядра, запустив ее uname -a, обнаружив, что версия дистрибутива зависит от дистрибутива.

В Ubuntu и некоторых других ОС вы можете запустить lsb_release -aили прочитать / etc / lsb_release

Debian хранит версию в / etc / debian_version

Адам Гиббинс
источник
+1 для lsb_release (также работает с производными Red Hat, если установлен правильный пакет)
Джош Келли
только для описания «lsb_release -ds».
flickerfly
6

Большинство дистрибутивов имеют уникальный метод определения конкретного распределения.

Например:

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

SUSE: /etc/SUSE-release

Существует стандарт, известный как Linux Standard Base или LSB . Он определяет, что должен быть файл с именем / etc / lsb-release или программа с именем lsb_release, которая будет выводить информацию о вашем дистрибутиве Linux.

lsb_release -a
Марк Тернер
источник
И, конечно же, lsb_releaseне существует на CentOS 6.
Джастин
6
python -c 'import platform ; print platform.dist()[0]'

код: http://hg.python.org/cpython/file/2.7/Lib/platform.py

jkeogh
источник
Отличная идея. Я бы предложил использовать python -c 'import platform; print(platform.dist()[0])', потому что таким образом это также работает, если обычный питон по умолчанию равен python3.
heinrich5991
5

В дополнение к другим ответам: Если вы просто хотите проанализировать один файл, большинство дистрибутивов персонализируют логин tty через / etc / issue, например:

Добро пожаловать в SUSE Linux Enterprise Server 10 SP2 (i586) - Ядро \ r (\ l).

И да, я знаю, что это неоптимально. :)

Узел
источник
Это может быть неоптимальным, но это в том же месте.
Брэд Гилберт
4

Facter - удобный инструмент для такого рода открытий, хотя он, вероятно, использует некоторые из методов, описанных выше, и требует Ruby.

Cawflands
источник
2

Все, что вам нужно сделать, это набрать uname -aв вашей любимой оболочке. Это выведет имя и версию ядра.


источник
2

Я обнаружил, что cat /etc/*release*почти всегда работает.

ibuys
источник
2

Я согласен с Марком, Адамом и Михаем (не могу голосовать из-за недостаточной репутации). Решения, основанные на LSB и его относительной FHS, будут работать с большинством дистрибутивов и, вероятно, продолжат работать в будущем. LSB и FHS - твои друзья.

Дэвид Дж. Лишевски
источник
2

Вы также можете получить версию по

cat /proc/version

о / р:

Версия Linux 2.6.17-13mdv (rtp@octopus.mandriva.com) (версия gcc 4.1.2 20070302 (предварительная версия) (4.1.2-1mdv2007.1)) # 1 SMP пт 23 марта 19:03:31 UTC 2007

прасанна
источник
1

Версия linux - сложный вопрос. Если присмотреться, то у нас есть версия ядра, которую вы можете получить с помощью " uname -r". Дистрибутивная версия в основном не имеет значения. Некоторые дистрибутивы лучше (корпоративные дистрибутивы, такие как Redhat Enterprise Linux). Другие дистрибутивы, такие как Gentoo, - это движущиеся цели, у которых вообще нет разумной версии. Если вам нужно сделать что-то на основе версии, взгляните на основные компоненты, которые имеют отношение к вам:

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...
Поль де Вриз
источник
1

Вы также можете проверить меню Grub, которое обычно дает вам кучу информации о дистрибутиве / версии :-)

Антуан Бенкемун
источник
-1

FusionInventory - это кроссплатформенный легкий инструмент для инвентаризации, который может получить эту информацию во многих дистрибутивах Linux, а также на BSD, Windows, MacOS X и других устройствах.

Если доступно, они используют lsb_release(как упоминалось несколько раз выше), но если нет, у них есть очень полезный список файлов и регулярных выражений для проверки имени и версии дистрибутива: https://github.com/fusinv/fusioninventory-agent/ blob / 2.2.x / lib / FusionInventory / Агент / Задача / Инвентаризация / Входные данные / Linux / Distro / NonLSB.pm # L16 .

Я бы порекомендовал использовать саму FusionInventory для получения этой информации, а не переопределять собственные сценарии с помощью этой логики, поскольку их сообщество будет поддерживать эту функциональность в актуальном состоянии. Вы можете использовать агент самостоятельно (он выводит файл XML / JSON, который легко анализировать) или объединить его с более широким решением для управления машинами в вашей сети, такими как GLPI или Rudder , в зависимости от ваших потребностей.

Джонатан Кларк
источник
Это было бы хорошим решением, если бы у него не было внешних зависимостей модулей Perl
Уилл Шеппард