Как проверить, работает ли в Cygwin, Mac или Linux?

У меня есть скрипт оболочки, который используется как в Windows/Cygwin, так и в Mac и Linux. Для каждой версии нужны немного разные переменные.

Как скрипт shell/bash может определить, запущен ли он в Cygwin, на Mac или в Linux?

10 ответов

Решение

Обычно, uname с его различными опциями скажу вам, в какой среде вы работаете:

pax> uname -a
CYGWIN_NT-5.1 IBM-L3F3936 1.5.25(0.156/4/2) 2008-06-12 19:34 i686 Cygwin

pax> uname -s
CYGWIN_NT-5.1

И, в соответствии с очень полезным schot (в комментариях), uname -s дает Darwin для OSX и Linux для Linux, пока мой Cygwin дает CYGWIN_NT-5.1, Но вам, возможно, придется экспериментировать со всеми видами разных версий.

Итак bash код для такой проверки будет выглядеть следующим образом:

unameOut="$(uname -s)"
case "${unameOut}" in
    Linux*)     machine=Linux;;
    Darwin*)    machine=Mac;;
    CYGWIN*)    machine=Cygwin;;
    MINGW*)     machine=MinGw;;
    *)          machine="UNKNOWN:${unameOut}"
esac
echo ${machine}

Обратите внимание, что я предполагаю, что вы на самом деле работаете в CygWin (bash оболочки), поэтому пути уже должны быть правильно настроены. Как отмечает один комментатор, вы можете запустить bash программа, передавая сценарий, из cmd само по себе, и это может привести к тому, что пути не будут установлены по мере необходимости.

Если вы делаете это, вы несете ответственность за то, чтобы убедиться, что вызываются правильные исполняемые файлы (например, CygWin), возможно, путем предварительного изменения пути или полного указания местоположений исполняемых файлов (например, /c/cygwin/bin/uname).

Вот скрипт bash, который я использовал для определения трех разных типов ОС (GNU/Linux, Mac OS X, Windows NT)

Обращать внимание

  • В вашем bash-скрипте используйте #!/usr/bin/env bash вместо #!/bin/sh чтобы предотвратить проблему, вызванную /bin/sh связан с другой оболочкой по умолчанию на разных платформах, иначе будет ошибка, как неожиданный оператор, вот что произошло на моем компьютере (Ubuntu 64 бит 12.04).
  • Mac OS X 10.6.8 (Snow Leopard) не имеет expr программа, если вы не установите его, поэтому я просто использую uname,

дизайн

  1. использование uname получить системную информацию (-s параметр).
  2. использование expr а также substr разобраться со строкой.
  3. использование ifeliffi сделать соответствующую работу.
  4. Вы можете добавить дополнительную поддержку системы, если хотите, просто следуйте uname -s Спецификация.

Реализация

#!/usr/bin/env bash

if [ "$(uname)" == "Darwin" ]; then
    # Do something under Mac OS X platform        
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
    # Do something under GNU/Linux platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
    # Do something under 32 bits Windows NT platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
    # Do something under 64 bits Windows NT platform
fi

тестирование

  • Linux (Ubuntu 12.04 LTS, Kernel 3.2.0) протестирован нормально.
  • OS X (10.6.8 Snow Leopard) протестирована нормально.
  • Windows (64-битная Windows 7) протестирована.

Что я выучил

  1. Проверьте как открывающие, так и закрывающие котировки.
  2. Проверить отсутствие скобок и скобок {}

Рекомендации

Использование uname -s (--kernel-name) так как uname -o (--operating-system) не поддерживается в некоторых операционных системах, таких как Mac OS, Solaris. Вы также можете использовать только uname без аргумента в качестве аргумента по умолчанию -s (--kernel-name).

Приведенный ниже фрагмент не требует bash (т.е. не требует #!/bin/bash)

#!/bin/sh

case "$(uname -s)" in

   Darwin)
     echo 'Mac OS X'
     ;;

   Linux)
     echo 'Linux'
     ;;

   CYGWIN*|MINGW32*|MSYS*)
     echo 'MS Windows'
     ;;

   # Add here more strings to compare
   # See correspondence table at the bottom of this answer

   *)
     echo 'other OS' 
     ;;
esac

Нижеприведенное Makefile вдохновлен проектом Git ( config.mak.uname )

ifdef MSVC     # Avoid the MingW/Cygwin sections
    uname_S := Windows
else                          # If uname not available => 'not' 
    uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
endif

# Avoid nesting "if .. else if .. else .. endif endif"
# because maintenance of matching if/else/endif is a pain

ifeq ($(uname_S),Windows)
    CC := cl 
endif
ifeq ($(uname_S),OSF1)
    CFLAGS += -D_OSF_SOURCE
endif
ifeq ($(uname_S),Linux)
    CFLAGS += -DNDEBUG
endif
ifeq ($(uname_S),GNU/kFreeBSD)
    CFLAGS += -D_BSD_ALLOC
endif
ifeq ($(uname_S),UnixWare)
    CFLAGS += -Wextra
endif
...

Смотрите также этот полный ответ о uname -s а также Makefile,

Таблица соответствия внизу этого ответа взята из статьи в Википедии о uname, Пожалуйста, внесите свой вклад, чтобы обновлять его (отредактируйте ответ или оставьте комментарий). Вы также можете обновить статью в Википедии и оставить комментарий, чтобы заметить меня о вашем вкладе;-)

Operating System uname -s
Mac OS X Darwin
Cygwin 32-bit (Win-XP) CYGWIN_NT-5.1
Cygwin 32-bit (Win-7 32-bit)CYGWIN_NT-6.1
Cygwin 32-bit (Win-7 64-bit)CYGWIN_NT-6.1-WOW64
Cygwin 64-bit (Win-7 64-bit)CYGWIN_NT-6.1
MinGW (Windows 7 32-bit) MINGW32_NT-6.1
MinGW (Windows 10 64-bit) MINGW64_NT-10.0
Interix (Services for UNIX) Interix MSYS MSYS_NT-6.1 Windows Subsystem for Linux Linux
Android Linux
coreutils Linux
CentOS Linux
Fedora Linux
Gentoo Linux
Red Hat Linux Linux
Linux Mint Linux
openSUSE Linux
Ubuntu Linux
Unity Linux Linux
Manjaro Linux Linux
OpenWRT r40420 Linux
Debian (Linux) Linux
Debian (GNU Hurd) GNU
Debian (kFreeBSD) GNU/kFreeBSD
FreeBSD FreeBSD
NetBSD NetBSD
DragonFlyBSD DragonFly
Haiku Haiku
NonStop NONSTOP_KERNEL
QNX QNX
ReliantUNIX ReliantUNIX-Y
SINIX SINIX-Y
Tru64 OSF1
Ultrix ULTRIX
IRIX 32 bits IRIX
IRIX 64 bits IRIX64
MINIX Minix
Solaris SunOS
UWIN (64-bit Windows 7) UWIN-W7
SYS$UNIX:SH on OpenVMS IS/WB
z/OS USS OS/390
Cray sn5176
(SCO) OpenServer SCO_SV
(SCO) System V SCO_SV
(SCO) UnixWare UnixWare
IBM AIX AIX
IBM i with QSH OS400
HP-UX HP-UX

Bash устанавливает переменную оболочки OSTYPE. От man bash:

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

Это имеет крошечное преимущество перед uname в том, что он не требует запуска нового процесса, поэтому будет выполняться быстрее.

Однако я не могу найти достоверный список ожидаемых значений. Для меня в Ubuntu 14.04 это "linux-gnu". Я поцарапал сеть для некоторых других ценностей. Следовательно:

case "$OSTYPE" in
  linux*)   echo "Linux / WSL" ;;
  darwin*)  echo "Mac OS" ;; 
  win*)     echo "Windows" ;;
  msys*)    echo "MSYS / MinGW / Git Bash" ;;
  cygwin*)  echo "Cygwin" ;;
  bsd*)     echo "BSD" ;;
  solaris*) echo "Solaris" ;;
  *)        echo "unknown: $OSTYPE" ;;
esac

Звездочки важны в некоторых случаях - например, OSX добавляет номер версии ОС после "darwin". Мне сказали, что значение win на самом деле равно win32 - может быть, есть win64?

Возможно, мы могли бы работать вместе, чтобы заполнить таблицу проверенных значений здесь:

  • Linux Ubuntu (включая WSL): linux-gnu
  • Cygwin 64-bit: cygwin
  • Msys / MINGW (Git Bash для Windows): msys

(Пожалуйста, добавьте ваше значение, если оно отличается от существующих записей)

# This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
    echo Cygwin rulez
else 
    echo Unix is king
fi

Если в команде 6 первых символов uname -s указано "CYGWIN", предполагается, что система cygwin

Чтобы опираться на ответ Альберта, мне нравится использовать $COMSPEC для обнаружения Windows:

#!/bin/bash

if [ "$(uname)" == "Darwin" ]
then
 echo Do something under Mac OS X platform
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]
then
  echo Do something under Linux platform
elif [ -n "$COMSPEC" -a -x "$COMSPEC" ]
then 
  echo $0: this script does not support Windows \:\(
fi

Это позволяет избежать анализа вариантов имен Windows для $OS и разбор вариантов uname как MINGW, Cygwin и т. д.

Фон: %COMSPEC% переменная среды Windows, задающая полный путь к командному процессору (он же оболочка Windows). Значение этой переменной обычно %SystemRoot%\system32\cmd.exe который обычно оценивается в C:\Windows\system32\cmd.exe ,

http://en.wikipedia.org/wiki/Uname

Вся информация, которая вам когда-либо понадобится. Google твой друг.

использование uname -s запросить имя системы.

  • Mac: Darwin
  • Cygwin: CYGWIN_...
  • Linux: различный, LINUX для большинства

Подсистема Windows для Linux не существовала, когда задавался этот вопрос. Это дало эти результаты в моем тесте:

uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft

Это означает, что вам нужен uname -r, чтобы отличить его от родного Linux.

Хорошо, вот мой путь.

osis()
{
    local n=0
    if [[ "$1" = "-n" ]]; then n=1;shift; fi

    # echo $OS|grep $1 -i >/dev/null
    uname -s |grep -i "$1" >/dev/null

    return $(( $n ^ $? ))
}

например

osis Darwin &&
{
    log_debug Detect mac osx
}
osis Linux &&
{
    log_debug Detect linux
}
osis -n Cygwin &&
{
    log_debug Not Cygwin
}

Я использую это в моих точечных файлах

Я полагаю, что uname ответ непобедим, в основном с точки зрения чистоты.

Хотя выполнение занимает смешное время, я обнаружил, что тестирование на наличие определенных файлов также дает хорошие и более быстрые результаты, так как я не вызываю исполняемый файл:

Так,

[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running

просто использует быструю проверку наличия файла Bash. Поскольку я сейчас нахожусь на Windows, я не могу сказать вам какие-либо конкретные файлы для Linux и Mac OS X, но я почти уверен, что они существуют.:-)

Использование только этого из командной строки работает очень хорошо, благодаря Джастину:

#!/bin/bash

################################################## #########
# Bash script to find which OS
################################################## #########

OS=`uname`
echo "$OS"

источник

Другие вопросы по тегам