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

195

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

Как оболочка / bash script обнаруживает, запущена ли она в Cygwin, на Mac или Linux?

Теги:
cross-platform
cygwin

10 ответов

136
Лучший ответ

Обычно 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, передав script, из cmd, и это может привести к тому, что пути не будут настроены по мере необходимости.

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

  • 8
    Иногда чем меньше, тем больше;) Кстати, в Википедии есть таблица примеров вывода uname по адресу en.wikipedia.org/wiki/Uname
  • 0
    Вывод команды Git Bash uname -s в Windows 7 - MINGW32_NT-6.1 . Также нет префикса /cygdrive , просто /c для C:
Показать ещё 4 комментария
240

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

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

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

Дизайн

  • Используйте uname для получения системной информации (параметр -s).
  • Используйте expr и substr для обработки строки.
  • Используйте if elif fi, чтобы выполнить соответствующее задание.
  • Вы можете добавить дополнительную поддержку системы, если хотите, просто следуйте спецификации 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 (Windows 7 64 бит) протестирована в порядке.

Что я узнал

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

Ссылки

  • 0
    Для MinGW может иметь смысл проверить: [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ] .
  • 1
    Кроме того, я не могу отредактировать ответ, так как это будет только смена одного символа, но для любого, кто копирует ответ Альберта, в проверке MINGW должен быть пробел между " и ] .
Показать ещё 10 комментариев
67

Используйте uname -s, потому что uname -o не поддерживается на некоторых операционных системах в Mac OS, Solaris...

В приведенном ниже фрагменте не требуется (т.е. не требует #!/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 project (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. Пожалуйста, внесите свой вклад, чтобы поддерживать его в актуальном состоянии (отредактируйте ответ или опубликуйте комментарий). Вы также можете обновить статью в Википедии и опубликовать комментарий, чтобы заметить меня о вашем вкладе; -)

См. также более сложное обнаружение ОС, выполненное с помощью сценариев установки Git LSF.

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
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

  • 1
    Большие пальцы за Solaris и исследования выше.
  • 0
    Привет @okutane. Я не понимаю что ты имеешь в виду. Пожалуйста, предоставьте больше деталей. Вы предлагаете что-нибудь? ура
Показать ещё 6 комментариев
31

Bash задает переменную оболочки OSTYPE. Из man bash:

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

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

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

case "$OSTYPE" in
  linux*)   echo "LINUX" ;;
  darwin*)  echo "OSX" ;; 
  win*)     echo "Windows" ;;
  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-бит: cygwin
  • Msys/MINGW (Git bash для Windows): msys

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

  • 1
    Мне уже нравится твой ответ больше, чем мой, идеально подходит в те редкие моменты, когда я нуждался в этом
  • 6
    Технически, это не переменная окружения, это переменная оболочки. Вот почему вы не увидите его в env | grep OSTYPE , но вы увидите его под set | grep OSTYPE
Показать ещё 1 комментарий
8

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

  • 0
    Больше не корректно, так как $ COMSPEC не устанавливается при работе в среде Windows UWS Bash.
8
# This script fragment emits Cygwin rulez under bash/cygwin
if [ "$(expr substr $(uname -s) 1 6)" == "CYGWIN" ];then
    echo Cygwin rulez
else 
    echo Unix is king
fi

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

  • 0
    if [ `uname -s` == CYGWIN* ]; then выглядит лучше и работает так же.
  • 5
    Да, но используйте двойные скобки: [[ $(uname -s) == CYGWIN* ]] . Также обратите внимание, что расширенные регулярные выражения более точны в нашем случае: [[ $(uname -s) =~ ^CYGWIN* ]] .
Показать ещё 1 комментарий
4

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

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

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

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

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

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
}

Я использую это в своем dotfiles

0

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

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

Итак,

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

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

0

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

#!/bin/bash

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

OS=`uname`
echo "$OS"

источник

  • 0
    Что нового в вашем сценарии?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню