Как проверить, работает ли в Cygwin, Mac или Linux? - PullRequest
275 голосов
/ 12 августа 2010

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

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

Ответы [ 11 ]

293 голосов
/ 12 июня 2013

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

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

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

Дизайн

  1. Используйте uname для получения системной информации (-s параметр).
  2. Используйте expr и substr для работы со строкой.
  3. Используйте if elif fi для выполнения соответствующей работы.
  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) в порядке.
  • ОСX (10.6.8 Snow Leopard) протестирован OK.
  • Windows (64-битная Windows 7) протестирован OK.

Что я выучил

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

Ссылки

247 голосов
/ 12 августа 2010

Обычно 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).

98 голосов
/ 05 января 2015

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

В приведенном ниже фрагменте не требуется (то есть не требует #!/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 <a href="https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux" rel="noreferrer">Windows Subsystem for Linux</a> 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 *1365*
(SCO) UnixWare UnixWare
IBM AIX AIX
IBM i with QSH OS400
HP-UX HP-UX

59 голосов
/ 20 ноября 2015

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

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

9 голосов
/ 13 сентября 2013

Чтобы опираться на ответ Альберта, я хотел бы использовать $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.

8 голосов
/ 13 марта 2013
# 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

3 голосов
/ 12 августа 2010

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

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

Используйте uname -s для запроса имени системы.

  • Mac: Darwin
  • Cygwin: CYGWIN_...
  • Linux: различно, LINUX для большинства
1 голос
/ 13 февраля 2015

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

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
}

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

0 голосов
/ 30 апреля 2019

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

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

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

0 голосов
/ 12 августа 2015

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

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

Итак,

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

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

...