Как определить ОС из скрипта Bash? - PullRequest
428 голосов
/ 26 декабря 2008

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

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

Ответы [ 21 ]

335 голосов
/ 22 декабря 2011

Я думаю, что следующее должно работать. Я не уверен насчет 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
282 голосов
/ 26 декабря 2008

Для моего .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, если хотите.

267 голосов
/ 26 декабря 2008

Страница руководства bash сообщает, что в переменной OSTYPE хранится имя операционной системы:

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

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

130 голосов
/ 26 августа 2013

$OSTYPE

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

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
35 голосов
/ 27 декабря 2008

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

Ключевые элементы

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

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

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

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

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

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

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

32 голосов
/ 25 сентября 2010

Я рекомендую использовать этот полный код 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

10 голосов
/ 14 января 2009

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

9 голосов
/ 04 мая 2012

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

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

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

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

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

9 голосов
/ 26 декабря 2008

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

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

Кстати: $ OSTYPE также имеет значение linux-gnu здесь:)

8 голосов
/ 24 марта 2015

Я написал эти сахара в моем .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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...