У меня есть оболочка 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
[ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]
.
"
и ]
.
Используйте uname -s
, потому что uname -o
не поддерживается на некоторых операционных системах в Mac OS, Solaris...
В приведенном ниже фрагменте не требуется 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 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
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-gnu
cygwin
msys
(добавьте свое значение, если оно отличается от существующих записей)
env | grep OSTYPE
, но вы увидите его под set | grep OSTYPE
Чтобы основываться на ответе Альберта, мне нравится использовать $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
.
# 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
if [ `uname -s` == CYGWIN* ]; then
выглядит лучше и работает так же.
[[ $(uname -s) == CYGWIN* ]]
. Также обратите внимание, что расширенные регулярные выражения более точны в нашем случае: [[ $(uname -s) =~ ^CYGWIN* ]]
.
http://en.wikipedia.org/wiki/Uname
Вся информация, которая вам когда-либо понадобится. Google - ваш друг.
Используйте uname -s
для запроса имени системы.
Darwin
CYGWIN_...
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
Я думаю, что ответ 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"
MINGW32_NT-6.1
. Также нет префикса/cygdrive
, просто/c
дляC: