У меня есть оболочка script, которая используется как для Windows/Cygwin, так и для Mac и Linux. Для каждой версии требуется несколько разные переменные.
Как оболочка / bash script обнаруживает, запущена ли она в Cygwin, на Mac или Linux?
У меня есть оболочка script, которая используется как для Windows/Cygwin, так и для Mac и Linux. Для каждой версии требуется несколько разные переменные.
Как оболочка / bash script обнаруживает, запущена ли она в Cygwin, на Mac или Linux?
Обычно 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).
#!/usr/bin/env bash вместо #!/bin/sh, чтобы предотвратить проблему, вызванную /bin/sh, связанную с другой оболочкой по умолчанию на разных платформах, или возникнет ошибка, например, неожиданный оператор, что произошло на моем компьютере (Ubuntu 64 бит 12.04).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
Используйте 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 
MSYS2  MSYS_NT-10.0-17763 
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-gnucygwinmsys(Пожалуйста, добавьте ваше значение, если оно отличается от существующих записей)
# 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 для запроса имени системы.
DarwinCYGWIN_...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
}
Я использую это в своем dotfiles
Подсистема Windows для Linux не существовала, когда задавался этот вопрос. Это дало эти результаты в моем тесте:
uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft
 Это означает, что вам нужно uname -r, чтобы отличить его от родного Linux.
Я думаю, что ответ 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"