如何检查在Cygwin,Mac或Linux上运行?

我有一个在Windows / Cygwin和Mac和Linux上使用的shell脚本。 每个版本都需要稍微不同的variables。

shell / bash脚本如何检测它是在Cygwin中,在Mac上还是在Linux中运行?

通常,不同的选项会告诉你在什么环境中运行:

 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} 

这里是我用来检测三种不同的操作系统types(GNU / Linux,Mac OS X,Windows NT)的bash脚本,

请注意

  • 在您的bash脚本中,使用#!/usr/bin/env bash而不是#!/bin/sh来防止由/bin/sh引起的问题链接到不同平台的不同默认shell,否则会出现意外操作 ,这就是我的电脑上发生的事情(Ubuntu 64位12.04)。
  • Mac OS X 10.6.8(雪豹)没有expr程序,除非你安装它,所以我只使用uname

devise

  1. 使用uname获取系统信息( -s参数)。
  2. 使用exprsubstr来处理string。
  3. if elif fi做匹配的工作,使用。
  4. 你可以添加更多的系统支持,只要按照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 

testing

  • Linux(Ubuntu 12.04 LTS,Kernel 3.2.0)testingOK。
  • OS X(10.6.8雪豹)testing确定。
  • Windows(Windows 7 64位)testing确定。

我学到的是

  1. 检查开盘和收盘报价。
  2. 检查缺less的圆括号和大括号{}

参考

  • [1] uname – 维基百科
  • shell脚本语法错误:意外的文件结束
  • [3] 从Bash脚本中检测操作系统
  • [4] BASH编程介绍如何

使用uname -s是因为uname -o在某些操作系统上不受支持,如Mac OSSolaris

下面的代码片段不需要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 -sMakefile完美答案 。

这个答案的底部的对应表是从维基百科有关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 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 SYS$UNIX:SH on OpenVMS
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设置shellvariablesOSTYPE。 从man bash

自动设置为描述执行bash的操作系统的string。

这比uname有一个小小的优势,因为它不需要启动一个新的进程,所以执行起来会更快。

但是,我无法find期望值的权威列表。 对于我在Ubuntu 14.04上它被设置为“linux-gnu”。 我已经刮了networking的一些其他的价值观。 因此:

 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在“达尔文”之后追加操作系统版本号。 “赢”的价值实际上是“win32”,我被告知 – 也许有一个“win64”?

也许我们可以一起工作,在这里填充一个validation值表:

  • Linux Ubuntu(包括WSL ): linux-gnu
  • Cygwin 64位: cygwin
  • Msys / msys (Windows版Git Bash): msys

(如果与现有条目不同,请附上您的价值)

 # 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 

如果uname -s命令的前6个字符是“CYGWIN”,则假定为cygwin系统

基于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 

这样可以避免为$OSparsingWindows名称的变体,parsing像MINGW,Cygwin等uname变体。

背景: %COMSPEC%是一个Windows环境variables,指定了命令处理器(即Windowsshell)的完整path。 此variables的值通常是%SystemRoot%\system32\cmd.exe ,通常评估为C:\Windows\system32\cmd.exe

http://en.wikipedia.org/wiki/Uname

所有你需要的信息。 Google是你的朋友。

使用uname -s来查询系统名称。

  • 麦克: Darwin
  • Cygwin: CYGWIN_...
  • Linux:大部分是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中使用这个

在命令行中只使用这个工作非常好,谢谢Justin:

 #!/bin/bash ################################################## ######### # Bash script to find which OS ################################################## ######### OS=`uname` echo "$OS" 

资源

我猜uname答案是无与伦比的,主要是在清洁方面。

虽然执行时间很荒谬,但是我发现testing特定文件的存在也给了我更好更快的结果,因为我没有调用可执行文件:

所以,

[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running

只是使用一个快速的Bash文件存在检查。 因为我现在在Windows上,所以我不能告诉你任何Linuxes和Mac OS X的特定文件,但是我确信它们确实存在。 🙂