关于bash:如何检查是否在cygwin、mac或linux中运行?

How to check if running in Cygwin, Mac or Linux?

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

shell/bash脚本如何检测它是在cygwin、mac还是在linux中运行?


下面是我用来检测三种不同操作系统类型(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

设计

  • 使用uname获取系统信息(-s参数)。
  • 使用exprsubstr处理字符串。
  • 使用ifeliffi进行匹配工作。
  • 如果需要,您可以添加更多的系统支持,只需遵循uname -s规范即可。
  • 实施

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/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雪豹)测试正常。
    • Windows(Windows 7 64位)测试正常。

    我学到了什么

  • 检查左引号和右引号。
  • 检查是否缺少括号和大括号
  • 工具书类

    • [1]UNAME-维基百科
    • [2]Shell脚本语法错误:意外的文件结尾
    • [3]从bash脚本检测操作系统
    • [4]bash编程简介


    通常,uname及其各种选项将告诉您运行的环境:

    1
    2
    3
    4
    5
    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 -sDarwin给osx,Linux给linux,而我的cygwin给CYGWIN_NT-5.1。但是你可能需要尝试各种不同的版本。

    因此,执行这种检查的bash代码将沿着以下行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)来实现的。


    使用uname -s(--kernel-name),因为uname -o(--operating-system)是SUPPORTED是一些操作系统为Mac OS,Solaris。你可能也使用的是uname没有argument作为默认的argument是-s(--kernel-name)。 </P >

    在下面的代码片段并不需要攻击(即,并不需要#!/bin/bash) </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #!/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

    在下面的MakefileNEA的灵感是从项目(config.mak.uname)。 </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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。。。。。。。 </P >

    在桌面的信件中的本底的答案是从维基百科的文章关于uname。。。。。。。请contribute来保持它的升到date(编辑的答案或后a comment)。你可能也在维基百科的文章和更新后的评论来通知我们关于你的贡献;) </P >

    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 </P >


    bash变量ostype套壳。从man bash

    Automatically set to a string that describes the operating system on
    which bash is executing.

    这有一个小的优势,在那上面uname它不需要发射一个新的流程,所以将两quicker execute。

    然而,我unable找到权威的预期值的列表。我对它是14.04 Ubuntu Linux上的羚羊。在我们的网站scraped一些其他的值。hence:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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

    《asterisks是在一些重要的instances -例如,我们appends OSX版本号后的达尔文。"双赢"的价值实际上Win32的冰的关税也许有一个Win64上?

    也许我们可以一起工作的两个populate table of a值来验证:

    • Ubuntu Linux操作系统(包括:linux-gnuWSL)
    • Cygwin的64位:cygwin
    • MSYS / MinGW(Git Bash的Windows msys):

    (请你append value if it differs从现有的条目)


    基于艾伯特的回答,我喜欢用$COMSPEC来探测窗户:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/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


    1
    2
    3
    4
    5
    6
    # 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系统


    http://en.wikipedia.org/wiki/uname网站

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

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

    • MAC:Darwin
    • 塞格温:江户十一〔13〕。
    • linux:variable,大多数是Linux

    好的,这里是我的方式。 </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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 ^ $? ))
    }

    辩护人。 </P >

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    osis Darwin &&
    {
        log_debug Detect mac osx
    }
    osis Linux &&
    {
        log_debug Detect linux
    }
    osis -n Cygwin &&
    {
        log_debug Not Cygwin
    }

    我用这个在我的dotfiles </P >


    我猜答案的信息是unbeatable,主要在大学cleanliness术语。 </P >

    尽管从它把ridiculous to execute a时,我发现那试验特异性文件的车轮也给了我很好的和quicker结果,因为我不invoking安executable: </P >

    所以, </P >

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

    使用的是一个快速的bash在场的文件检查。As I’m是Windows的权利,现在,我不能告诉你任何特定文件的方法linuxes和Mac OS X的从我的头,但我很担心,他们做的存在。:-) </P >


    只在命令行中使用这个命令行非常好,多亏了贾斯汀:

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash

    ################################################## #########
    # Bash script to find which OS
    ################################################## #########

    OS=`uname`
    echo"$OS"

    来源