bash 如何检查是否在 Cygwin、Mac 或 Linux 中运行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3466166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if running in Cygwin, Mac or Linux?
提问by bastibe
I have a shell script that is used both on Windows/Cygwin and Mac and Linux. It needs slightly different variables for each versions.
我有一个在 Windows/Cygwin、Mac 和 Linux 上都使用的 shell 脚本。每个版本都需要稍微不同的变量。
How can a shell/bash script detect whether it is running in Cygwin, on a Mac or in Linux?
shell/bash 脚本如何检测它是在 Cygwin、Mac 还是 Linux 中运行?
采纳答案by paxdiablo
Usually, uname
with its various options will tell you what environment you're running in:
通常,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
And, according to the very helpful schot
(in the comments), uname -s
gives Darwin
for OSX and Linux
for Linux, while my Cygwin gives CYGWIN_NT-5.1
. But you may have to experiment with all sorts of different versions.
而且,根据非常有帮助schot
(在评论),uname -s
给人Darwin
的OSX和Linux
Linux版,而我的Cygwin的给予CYGWIN_NT-5.1
。但是您可能必须尝试各种不同的版本。
So the bash
code to do such a check would be along the lines of:
因此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}
Note that I'm assuming here that you're actually running withinCygWin (the bash
shell of it) so paths should already be correctly set up. As one commenter notes, you can run the bash
program, passing the script, from cmd
itself and this may result in the paths not being set up as needed.
请注意,我在这里假设您实际上是在CygWin(bash
它的外壳)中运行,因此路径应该已经正确设置。正如一位评论者所指出的,您可以运行该bash
程序,并从其cmd
自身传递脚本,这可能会导致未根据需要设置路径。
If you aredoing that, it's your responsibility to ensure the correct executables (i.e., the CygWin ones) are being called, possibly by modifying the path beforehand or fully specifying the executable locations (e.g., /c/cygwin/bin/uname
).
如果你正在这样做,这是你的责任,以确保正确的可执行文件(即,在Cygwin的)都被调用,可能通过修改路径提前或完全指定可执行文件的位置(例如,/c/cygwin/bin/uname
)。
回答by Albert
Here is the bash script I used to detect three different OS type (GNU/Linux, Mac OS X, Windows NT)
这是我用来检测三种不同操作系统类型(GNU/Linux、Mac OS X、Windows NT)的 bash 脚本
Pay attention
请注意
- In your bash script, use
#!/usr/bin/env bash
instead of#!/bin/sh
to prevent the problem caused by/bin/sh
linked to different default shell in different platforms, or there will be error like unexpected operator, that's what happened on my computer (Ubuntu 64 bits 12.04). - Mac OS X 10.6.8 (Snow Leopard) do not have
expr
program unless you install it, so I just useuname
.
- 在你的 bash 脚本中,使用
#!/usr/bin/env bash
而不是#!/bin/sh
防止/bin/sh
链接到不同平台的不同默认 shell导致的问题,否则会出现意外操作符之类的错误,这就是我的电脑(Ubuntu 64 位 12.04)发生的情况。 - Mac OS X 10.6.8 (Snow Leopard) 没有安装
expr
程序,除非你安装它,所以我只使用uname
.
Design
设计
- Use
uname
to get the system information (-s
parameter). - Use
expr
andsubstr
to deal with the string. - Use
if
elif
fi
to do the matching job. - You can add more system support if you want, just follow the
uname -s
specification.
- 使用
uname
来获取系统信息(-s
参数)。 - 使用
expr
和substr
来处理字符串。 - 用
if
elif
fi
做匹配工作。 - 如果需要,您可以添加更多系统支持,只需遵循
uname -s
规范即可。
Implementation
执行
#!/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
Testing
测试
- Linux (Ubuntu 12.04 LTS, Kernel 3.2.0) tested OK.
- OS X (10.6.8 Snow Leopard) tested OK.
- Windows (Windows 7 64 bit) tested OK.
- Linux(Ubuntu 12.04 LTS,内核 3.2.0)测试正常。
- OS X (10.6.8 Snow Leopard) 测试正常。
- Windows(Windows 7 64 位)测试正常。
What I learned
我学到的是
- Check for both opening and closing quotes.
- Check for missing parentheses and braces {}
- 检查开盘价和收盘价。
- 检查缺少的括号和大括号 {}
References
参考
- [1] uname - wikipedia
- [2] shell script syntax error: unexpected end of file
- [3] Detect the OS from a Bash script
- [4] BASH Programming Introduction HOW-TO
- [1] uname - 维基百科
- [2] shell 脚本语法错误:文件意外结束
- [3]从 Bash 脚本检测操作系统
- [4] BASH编程介绍HOW-TO
回答by olibre
Use uname -s
(--kernel-name
) because uname -o
(--operating-system
) is not supported on some Operating Systems such as Mac OSand Solaris. You may also use just uname
without any argumentsince the default argument is -s
(--kernel-name
).
使用uname -s
( --kernel-name
) 是因为uname -o
( --operating-system
) 在某些操作系统(例如Mac OS和Solaris)上不受支持。您也可以使用 justuname
而不带任何参数,因为默认参数是-s
( --kernel-name
)。
The below snippet does not require bash(i.e. does not require #!/bin/bash
)
下面的代码段不需要bash(即不需要#!/bin/bash
)
#!/bin/sh
case "$(uname -s)" in
Darwin)
echo 'Mac OS X'
;;
Linux)
echo 'Linux'
;;
CYGWIN*|MINGW32*|MSYS*|MINGW*)
echo 'MS Windows'
;;
# Add here more strings to compare
# See correspondence table at the bottom of this answer
*)
echo 'Other OS'
;;
esac
The below Makefile
is inspired from Git project (config.mak.uname
).
下面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
...
See also this complete answer about uname -s
and Makefile
.
The correspondence table in the bottom of this answer is from Wikipedia article about uname
. Please contribute to keep it up-to-date (edit the answer or post a comment). You may also update the Wikipedia article and post a comment to notify me about your contribution ;-)
这个答案底部的对应表来自维基百科关于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
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
回答by Jonathan Hartley
Bash sets the shell variable OSTYPE. From man bash
:
Bash 设置 shell 变量 OSTYPE。来自man bash
:
Automatically set to a string that describes the operating system on which bash is executing.
自动设置为描述执行 bash 的操作系统的字符串。
This has a tiny advantage over uname
in that it doesn't require launching a new process, so will be quicker to execute.
uname
与它相比,这有一个微小的优势,因为它不需要启动新进程,因此执行起来会更快。
However, I'm unable to find an authoritative list of expected values. For me on Ubuntu 14.04 it is set to 'linux-gnu'. I've scraped the web for some other values. Hence:
但是,我无法找到权威的预期值列表。对我来说,在 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
The asterisks are important in some instances - for example OSX appends an OS version number after the 'darwin'. The 'win' value is actually 'win32', I'm told - maybe there is a 'win64'?
星号在某些情况下很重要 - 例如 OSX 在“达尔文”之后附加一个操作系统版本号。'win' 值实际上是 'win32',有人告诉我 - 也许有一个 'win64'?
Perhaps we could work together to populate a table of verified values here:
也许我们可以一起在这里填充一个验证值表:
- Linux Ubuntu (incl. WSL):
linux-gnu
- Cygwin 64-bit:
cygwin
- Msys/MINGW (Git Bash for Windows):
msys
- Linux Ubuntu(包括WSL):
linux-gnu
- Cygwin 64 位:
cygwin
- Msys/MINGW(Windows 版 Git Bash):
msys
(Please append your value if it differs from existing entries)
(如果与现有条目不同,请附加您的值)
回答by Steve Jansen
To build upon Albert's answer, I like to use $COMSPEC
for detecting Windows:
为了建立在 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 # This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
echo Cygwin rulez
else
echo Unix is king
fi
: this script does not support Windows \:\(
fi
This avoids parsing variants of Windows names for $OS
, and parsing variants of uname
like MINGW, Cygwin, etc.
这避免了解析 Windows 名称的$OS
变体,以及解析uname
MINGW、Cygwin 等的变体。
Background: %COMSPEC%
is a Windows environmental variable specifying the full path to the command processor (aka the Windows shell). The value of this variable is typically %SystemRoot%\system32\cmd.exe
, which typically evaluates to C:\Windows\system32\cmd.exe
.
背景:%COMSPEC%
是一个 Windows 环境变量,指定命令处理器(又名 Windows shell)的完整路径。此变量的值通常为%SystemRoot%\system32\cmd.exe
,其计算结果通常为C:\Windows\system32\cmd.exe
。
回答by Jan Helge
uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft
If the 6 first chars of uname -s command is "CYGWIN", a cygwin system is assumed
如果 uname -s 命令的前 6 个字符是“CYGWIN”,则假定是 cygwin 系统
回答by rubenvb
http://en.wikipedia.org/wiki/Uname
http://en.wikipedia.org/wiki/Uname
All the info you'll ever need. Google is your friend.
您需要的所有信息。谷歌是你的朋友。
Use uname -s
to query the system name.
使用uname -s
查询系统名称。
- Mac:
Darwin
- Cygwin:
CYGWIN_...
- Linux: various,
LINUX
for most
- 苹果电脑:
Darwin
- 赛格温:
CYGWIN_...
- Linux:各种,
LINUX
大多数
回答by A Fog
Windows Subsystem for Linux did not exist when this question was asked. It gave these results in my test:
问这个问题时,Linux 的 Windows 子系统不存在。它在我的测试中给出了这些结果:
osis()
{
local n=0
if [[ "" = "-n" ]]; then n=1;shift; fi
# echo $OS|grep -i >/dev/null
uname -s |grep -i "" >/dev/null
return $(( $n ^ $? ))
}
This means that you need uname -r to distinguish it from native Linux.
这意味着您需要使用 uname -r 来将其与本机 Linux 区分开来。
回答by wener
Ok, here is my way.
好的,这是我的方式。
osis Darwin &&
{
log_debug Detect mac osx
}
osis Linux &&
{
log_debug Detect linux
}
osis -n Cygwin &&
{
log_debug Not Cygwin
}
e.g.
例如
##代码##I use this in my dotfiles
我在我的dotfiles 中使用它
回答by Charles Roberto Canato
I guess the uname answer is unbeatable, mainly in terms of cleanliness.
我想 uname 的答案是无与伦比的,主要是在清洁方面。
Although it takes a ridiculous time to execute, I found that testing for specific files presence also gives me good and quicker results, since I'm not invoking an executable:
虽然执行需要很长时间,但我发现测试特定文件的存在也给了我很好和更快的结果,因为我没有调用可执行文件:
So,
所以,
[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running
[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running
just uses a quick Bash file presence check. As I'm on Windows right now, I can't tell you any specific files for Linuxes and Mac OS X from my head, but I'm pretty sure they do exist. :-)
只使用快速的 Bash 文件存在检查。由于我现在在 Windows 上,我无法从脑海中告诉您任何适用于 Linux 和 Mac OS X 的特定文件,但我很确定它们确实存在。:-)