我有一个在Windows / Cygwin,Mac和Linux上使用的shell脚本。每个版本需要稍微不同的变量。
shell / bash脚本如何检测它是在Cygwin,Mac或Linux上运行?
答案 0 :(得分:288)
#!/usr/bin/env bash
而不是#!/bin/sh
来防止/bin/sh
链接到不同平台中不同默认shell的问题,或者会出现等错误意外的运算符,这就是我的计算机上发生的事情(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
答案 1 :(得分:237)
通常,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
为OSX提供Darwin
,为Linux提供Linux
,而我的Cygwin提供{{1} }}。但您可能需要尝试各种不同的版本。
所以进行此类检查的CYGWIN_NT-5.1
代码将遵循:
bash
请注意,我假设您实际上在 CygWin(它的unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) machine=Linux;;
Darwin*) machine=Mac;;
CYGWIN*) machine=Cygwin;;
MINGW*) machine=MinGw;;
*) machine="UNKNOWN:${unameOut}"
esac
echo ${machine}
shell)中运行,因此路径应该已经正确设置。正如一位评论者所指出的,您可以从bash
本身运行bash
程序并传递脚本,这可能会导致路径未按需设置。
如果你 这样做,你有责任确保调用正确的可执行文件(即CygWin),可能是事先修改路径或完全指定可执行文件位置(例如, cmd
)。
答案 2 :(得分:95)
使用 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 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
...
另见this complete answer about uname -s
and Makefile
。
此答案底部的对应表来自Wikipedia article about 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
答案 3 :(得分:57)
Bash设置shell变量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会在“达尔文”之后添加操作系统版本号。 “赢”'价值实际上是' win32'我被告知 - 也许有一个' win64'?
也许我们可以合作在一起填充一张经过验证的值表:
linux-gnu
cygwin
msys
(如果它与现有条目不同,请附加您的值)
答案 4 :(得分:9)
基于Albert的回答,我喜欢使用$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
这可以避免解析$OS
的Windows名称变体,并解析uname
的变体,如MINGW,Cygwin等。
背景:%COMSPEC%
是一个Windows环境变量,指定命令处理器(也称为Windows shell)的完整路径。此变量的值通常为%SystemRoot%\system32\cmd.exe
,通常评估为C:\Windows\system32\cmd.exe
。
答案 5 :(得分:8)
# This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
echo Cygwin rulez
else
echo Unix is king
fi
如果uname -s命令的6个第一个字符是“CYGWIN”,则假定使用cygwin系统
答案 6 :(得分:3)
http://en.wikipedia.org/wiki/Uname
您需要的所有信息。谷歌是你的朋友。
使用uname -s
查询系统名称。
Darwin
CYGWIN_...
LINUX
为大多数答案 7 :(得分: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 ^ $? ))
}
e.g。
osis Darwin &&
{
log_debug Detect mac osx
}
osis Linux &&
{
log_debug Detect linux
}
osis -n Cygwin &&
{
log_debug Not Cygwin
}
我在dotfiles
中使用此功能答案 8 :(得分:0)
我认为uname的答案是无与伦比的,主要是在清洁方面。
尽管执行需要一段荒谬的时间,但我发现测试特定文件的存在也给了我更好更快的结果,因为我没有调用可执行文件:
所以,
[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running
只使用快速Bash文件存在检查。就像我现在在Windows上一样,我无法从头脑中告诉你Linux和Mac OS X的任何特定文件,但我确信它们确实存在。 : - )
答案 9 :(得分:0)
uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft
这意味着您需要uname -r才能将其与本机Linux区别开。
答案 10 :(得分:-1)
从命令行使用此功能非常好, 感谢贾斯汀:
#!/bin/bash
################################################## #########
# Bash script to find which OS
################################################## #########
OS=`uname`
echo "$OS"