Как определить ОС по сценарию Bash?

Я хотел бы сохранить файлы .bashrc и .bash_login в управлении версиями, чтобы я мог использовать их между всеми компьютерами, которые я использую. Проблема в том, что у меня есть некоторые специфичные для ОС псевдонимы, поэтому я искал способ определить, работает ли script на Mac OS X X Linux или Cygwin.

Каким образом можно определить операционную систему в Bash script?

Ответ 1

Я думаю, что следующее должно работать. Я не уверен в win32, хотя.

if [[ "$OSTYPE" == "linux-gnu" ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # POSIX compatibility layer and Linux environment emulation for Windows
elif [[ "$OSTYPE" == "msys" ]]; then
        # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
elif [[ "$OSTYPE" == "win32" ]]; then
        # I'm not sure this can happen.
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
else
        # Unknown.
fi

Ответ 2

Для моего .bashrc, я использую следующий код:

platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
   platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
   platform='freebsd'
fi

Затем я делаю что-то вроде:

if [[ $platform == 'linux' ]]; then
   alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
   alias ls='ls -G'
fi

Это некрасиво, но оно работает. Вы можете использовать case вместо if, если хотите.

Ответ 3

В справочной странице bash указано, что переменная OSTYPE хранит имя операционной системы:

OSTYPE Автоматически устанавливает строку, описывающую операционную систему, на которой выполняется bash. По умолчанию используется системно-               зависимыми.

Здесь установлено значение linux-gnu.

Ответ 4

$OSTYPE

Вы можете просто использовать предопределенную переменную $OSTYPE например:

case "$OSTYPE" in
  solaris*) echo "SOLARIS" ;;
  darwin*)  echo "OSX" ;; 
  linux*)   echo "LINUX" ;;
  bsd*)     echo "BSD" ;;
  msys*)    echo "WINDOWS" ;;
  *)        echo "unknown: $OSTYPE" ;;
esac

Однако он не распознается более ранними оболочками (такими как оболочка Борна).


uname

Другой метод - обнаружение платформы по команде uname.

Смотрите следующий скрипт (готов к включению в .bashrc):

# Detect the platform (similar to $OSTYPE)
OS="'uname'"
case $OS in
  'Linux')
    OS='Linux'
    alias ls='ls --color=auto'
    ;;
  'FreeBSD')
    OS='FreeBSD'
    alias ls='ls -G'
    ;;
  'WindowsNT')
    OS='Windows'
    ;;
  'Darwin') 
    OS='Mac'
    ;;
  'SunOS')
    OS='Solaris'
    ;;
  'AIX') ;;
  *) ;;
esac

Вы можете найти практический пример в моем .bashrc.


Вот аналогичная версия, используемая на Travis CI:

case $(uname | tr '[:upper:]' '[:lower:]') in
  linux*)
    export TRAVIS_OS_NAME=linux
    ;;
  darwin*)
    export TRAVIS_OS_NAME=osx
    ;;
  msys*)
    export TRAVIS_OS_NAME=windows
    ;;
  *)
    export TRAVIS_OS_NAME=notset
    ;;
esac

Ответ 5

Обнаружение операционной системы и типа ЦП не так просто сделать портативно. У меня есть сценарий sh около 100 строк, которые работают на очень широком спектре платформ Unix: любая система, которую я использовал с 1988 года.

Ключевыми элементами являются

  • uname -p - это тип процессора, но обычно unknown на современных платформах Unix.

  • uname -m предоставит "имя аппаратного оборудования" в некоторых Unix-системах.

  • /bin/arch, если он существует, обычно дает тип процессора.

  • uname без аргументов будет называться операционной системой.

В конце концов вам придется подумать о различиях между платформами и о том, насколько вы хотите их отличить . Например, просто чтобы все было просто, я рассматриваю i386 через i686, любой " Pentium* " и любой " AMD*Athlon* " как x86.

Мой ~/.profile запускает скрипт при запуске, который устанавливает одну переменную в строку, указывающую комбинацию процессора и операционной системы. У меня есть определенные для платформы файлы bin, man, lib и include которые устанавливаются на основе этого. Затем я установил лодку переменных окружения. Так, например, сценарий оболочки для переформатирования почты может вызывать, например, $LIB/mailfmt который является исполняемым двоичным кодом для конкретной платформы.

Если вы хотите вырезать углы, uname -m и plain uname расскажут вам, что вы хотите знать на многих платформах. Добавьте другие материалы, когда вам это нужно. (И использовать case, а не вложенный, if !)

Ответ 6

Я рекомендую использовать этот полный bash код

lowercase(){
    echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
}

OS=`lowercase \`uname\``
KERNEL=`uname -r`
MACH=`uname -m`

if [ "{$OS}" == "windowsnt" ]; then
    OS=windows
elif [ "{$OS}" == "darwin" ]; then
    OS=mac
else
    OS=`uname`
    if [ "${OS}" = "SunOS" ] ; then
        OS=Solaris
        ARCH=`uname -p`
        OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
    elif [ "${OS}" = "AIX" ] ; then
        OSSTR="${OS} `oslevel` (`oslevel -r`)"
    elif [ "${OS}" = "Linux" ] ; then
        if [ -f /etc/redhat-release ] ; then
            DistroBasedOn='RedHat'
            DIST=`cat /etc/redhat-release |sed s/\ release.*//`
            PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/SuSE-release ] ; then
            DistroBasedOn='SuSe'
            PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
            REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
        elif [ -f /etc/mandrake-release ] ; then
            DistroBasedOn='Mandrake'
            PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/debian_version ] ; then
            DistroBasedOn='Debian'
            DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F=  '{ print $2 }'`
            PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F=  '{ print $2 }'`
            REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F=  '{ print $2 }'`
        fi
        if [ -f /etc/UnitedLinux-release ] ; then
            DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
        fi
        OS=`lowercase $OS`
        DistroBasedOn=`lowercase $DistroBasedOn`
        readonly OS
        readonly DIST
        readonly DistroBasedOn
        readonly PSUEDONAME
        readonly REV
        readonly KERNEL
        readonly MACH
    fi

fi

Примеры примеров: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

Ответ 7

В bash используйте $OSTYPE и $HOSTTYPE, как описано; вот что я делаю. Если этого недостаточно, и если даже uname или uname -a (или другие соответствующие параметры) не дают достаточной информации, всегда будет config.guess script из проекта GNU, сделанного именно для этой цели.

Ответ 8

Попробуйте использовать "uname". Например, в Linux: "uname -a".

Согласно странице руководства, uname соответствует SVr4 и POSIX, поэтому он должен быть доступен на Mac OS X и Cygwin тоже, но я не могу это подтвердить.

BTW: $OSTYPE также устанавливается на linux-gnu здесь:)

Ответ 9

Я бы предложил избежать некоторых из этих ответов. Не забывайте, что вы можете выбрать другие формы сравнения строк, которые прояснят большинство вариантов или предлагаемый уродливый код.

Одним из таких решений будет простая проверка, например:

if [[ "$OSTYPE" =~ ^darwin ]]; then

У кого есть дополнительное преимущество при сопоставлении любой версии Дарвина, несмотря на его суффикс версии. Это также работает для любых вариантов Linux, которые можно ожидать.

Вы можете увидеть некоторые дополнительные примеры в моих dotfiles здесь

Ответ 10

Я написал эти сахара в моем .bashrc:

if_os () { [[ $OSTYPE == *$1* ]]; }
if_nix () { 
    case "$OSTYPE" in
        *linux*|*hurd*|*msys*|*cygwin*|*sua*|*interix*) sys="gnu";;
        *bsd*|*darwin*) sys="bsd";;
        *sunos*|*solaris*|*indiana*|*illumos*|*smartos*) sys="sun";;
    esac
    [[ "${sys}" == "$1" ]];
}

Поэтому я могу делать такие вещи, как:

if_nix gnu && alias ls='ls --color=auto' && export LS_COLORS="..."
if_nix bsd && export CLICOLORS=on && export LSCOLORS="..."
if_os linux && alias psg="ps -FA | grep" #alternative to pgrep
if_nix bsd && alias psg="ps -alwx | grep -i" #alternative to pgrep
if_os darwin && alias finder="open -R"

Ответ 11

uname

или

uname -a

если вы хотите получить дополнительную информацию

Ответ 12

Я написал личную библиотеку Bash и структуру сценариев, в которой используется GNU shtool, чтобы сделать довольно точное обнаружение платформы.

GNU shtool - очень портативный набор скриптов, который содержит среди других полезных вещей команду "shtool platform". Вот результат:

shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"

на нескольких разных машинах:

Mac OS X Leopard: 
    4.4BSD/Mach3.0 (iX86) Apple Darwin 9.6.0 (i386) Apple Mac OS X 10.5.6 (iX86)

Ubuntu Jaunty server:
    LSB (iX86) GNU/Linux 2.9/2.6 (i686) Ubuntu 9.04 (iX86)

Debian Lenny:
    LSB (iX86) GNU/Linux 2.7/2.6 (i686) Debian GNU/Linux 5.0 (iX86)

Это дает довольно удовлетворительные результаты, как вы можете видеть. GNU shtool немного медленнее, поэтому я фактически храню и обновляю идентификацию платформы в файле в системе, который вызывает мои сценарии. Это моя структура, так что это работает для меня, но ваш пробег может меняться.

Теперь вам нужно будет найти способ пакетного shtool с вашими скриптами, но это не сложное упражнение. Вы также можете всегда возвращаться к выводу uname.

EDIT:

Я пропустил сообщение Тедди около config.guess (так или иначе). Это очень похожие сценарии, но не то же самое. Я лично использую shtool для других целей, и он работает для меня хорошо.

Ответ 13

Вы можете использовать следующее:

OS=$(uname -s)

то вы можете использовать переменную ОС в script.

Ответ 14

Это должно быть безопасно для использования на всех дистрибутивах.

$ cat /etc/*release

Это создает что-то вроде этого.

     DISTRIB_ID=LinuxMint
     DISTRIB_RELEASE=17
     DISTRIB_CODENAME=qiana
     DISTRIB_DESCRIPTION="Linux Mint 17 Qiana"
     NAME="Ubuntu"
     VERSION="14.04.1 LTS, Trusty Tahr"
     ID=ubuntu
     ID_LIKE=debian
     PRETTY_NAME="Ubuntu 14.04.1 LTS"
     VERSION_ID="14.04"
     HOME_URL="http://www.ubuntu.com/"
     SUPPORT_URL="http://help.ubuntu.com/"
     BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

Извлечь/назначить переменные, как вы пожелаете

Примечание. На некоторых настройках. Это также может привести к некоторым ошибкам, которые вы можете игнорировать.

     cat: /etc/upstream-release: Is a directory

Ответ 15

Ниже представлен подход к обнаружению Debian и RedHat на базе ОС Linux с использованием /etc/lsb-release и /etc/os-release (в зависимости от используемого вами вкуса Linux) и выполните на основе этого простое действие.

#!/bin/bash
set -e

YUM_PACKAGE_NAME="python python-devl python-pip openssl-devel"
DEB_PACKAGE_NAME="python2.7 python-dev python-pip libssl-dev"

 if cat /etc/*release | grep ^NAME | grep CentOS; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on CentOS"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Red; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on RedHat"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Fedora; then
    echo "================================================"
    echo "Installing packages $YUM_PACKAGE_NAME on Fedorea"
    echo "================================================"
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Ubuntu; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Ubuntu"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Debian ; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Debian"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Mint ; then
    echo "============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Mint"
    echo "============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Knoppix ; then
    echo "================================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Kanoppix"
    echo "================================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 else
    echo "OS NOT DETECTED, couldn't install package $PACKAGE"
    exit 1;
 fi

exit 0

Пример вывода для Ubuntu Linux:

[email protected]$ sudo sh detect_os.sh
[sudo] password for delivery: 
NAME="Ubuntu"
===============================================
Installing packages python2.7 python-dev python-pip libssl-dev on Ubuntu
===============================================
Ign http://dl.google.com stable InRelease
Get:1 http://dl.google.com stable Release.gpg [916 B]                          
Get:2 http://dl.google.com stable Release [1.189 B] 
...            

Ответ 16

Вы можете использовать следующее условие if и расширить его при необходимости:

if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
    aminute_ago="-v-1M"
elif  [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
    aminute_ago="-d \"1 minute ago\""
fi

Ответ 17

Я стараюсь хранить мои .bashrc и .bash_alias в общем доступе к файлу, доступ к которому доступны всем платформам. Вот как я побеждаю проблему в моем .bash_alias:

if [[ -f (name of share)/.bash_alias_$(uname) ]]; then
    . (name of share)/.bash_alias_$(uname)
fi

И у меня есть, например,.bash_alias_Linux с:

alias ls='ls --color=auto'

Таким образом, я сохраняю отдельную платформу и переносимый код, вы можете сделать то же самое для .bashrc

Ответ 18

Выполнение следующего помогло корректно выполнить проверку для ubuntu:

if [[ "$OSTYPE" =~ ^linux ]]; then
    sudo apt-get install <some-package>
fi

Ответ 19

Я пробовал вышеуказанные сообщения на нескольких дистрибутивах Linux и нашел, что для меня лучше всего работать. Его короткий, сжатый точный ответ на слово, который работает и для Bash для Windows.

OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu

Ответ 20

Это проверяет кучу known файлов для идентификации, если дистрибутив linux - Debian или Ubunu, тогда по умолчанию используется переменная $OSTYPE.

os='Uknown'
unamestr="${OSTYPE//[0-9.]/}"
os=$( compgen -G "/etc/*release" > /dev/null  && cat /etc/*release | grep ^NAME | tr -d 'NAME="'  ||  echo "$unamestr")

echo "$os"

Ответ 21

попробуй это:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"