如何检查是否在Cygwin,Mac或Linux中运行?

时间:2010-08-12 09:10:23

标签: bash shell cross-platform cygwin

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

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

11 个答案:

答案 0 :(得分:288)

这是我用来检测三种不同操作系统类型(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(Snow Leopard)除非您安装了expr程序,否则我只使用uname

设计

  1. 使用uname获取系统信息(-s参数)。
  2. 使用exprsubstr来处理字符串。
  3. 使用if elif fi进行匹配作业。
  4. 如果需要,您可以添加更多系统支持,只需遵循uname -s规范。
  5. 实施

    #!/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,内核3.2.0)测试正常。
    • OS X(10.6.8 Snow Leopard)测试好了。
    • Windows(Windows 7 64位)测试正常。

    我学到了什么

    1. 检查开盘价和收盘价。
    2. 检查是否缺少括号和大括号{}
    3. 参考

答案 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)。

以下代码段不需要(即不需要#!/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 Ubuntu(包括WSL):linux-gnu
  • Cygwin 64位:cygwin
  • Msys / MINGW(适用于Windows的Git Bash):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查询系统名称。

  • Mac:Darwin
  • Cygwin:CYGWIN_...
  • Linux:各种,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)

询问此问题时,不存在用于Linux的Windows子系统。它在我的测试中给出了以下结果:

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"

source