Как проверить, работает ли в 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
,
дизайн
- использование
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 (64-битная Windows 7) протестирована.
Что я выучил
- Проверьте как открывающие, так и закрывающие котировки.
- Проверить отсутствие скобок и скобок {}
Рекомендации
Использование 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"