首页 文章

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

提问于
浏览
263

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

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

10 回答

  • -1

    我认为uname的答案是无与伦比的,主要是在清洁方面 .

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

    所以,

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

    只是使用快速Bash文件存在检查 . 由于我现在在Windows上,我不能告诉你任何针对Linux和Mac OS X的特定文件,但我很确定它们确实存在 . :-)

  • 54

    通常, 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提供 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}
    

    请注意,我实际上在CygWin(它的 bash shell)中运行,因此路径应该已经正确设置 . 正如一位评论者指出的那样,您可以从 cmd 本身运行 bash 程序并传递脚本,这可能会导致路径未按需设置 .

    如果你这样做,你有责任确保正在调用正确的可执行文件(即CygWin),可能是事先修改路径或完全指定可执行位置(例如, /c/cygwin/bin/uname ) .

  • 278

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

    注意

    • 在bash脚本中,使用 #!/usr/bin/env bash 而不是 #!/bin/sh 来防止 /bin/sh 链接到不同平台上的不同默认shell引起的问题,或者会出现意外操作符等错误,这就是我的计算机上发生的事情(Ubuntu 64位12.04) .

    • Mac OS X 10.6.8(Snow Leopard)没有 expr 程序,除非你安装它,所以我只使用 uname .

    设计

    • 使用 uname 获取系统信息( -s 参数) .

    • 使用 exprsubstr 来处理字符串 .

    • 使用 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
    

    测试

    • Linux(Ubuntu 12.04 LTS,内核3.2.0)测试好了 .

    • OS X(10.6.8 Snow Leopard)测试好了 .

    • Windows(Windows 7 64位)测试好了 .

    我学到了什么

    • 检查开盘价和收盘价 .

    • 检查是否缺少括号和括号{}

    参考文献

  • 228

    使用 uname -s--kernel-name ),因为某些操作系统不支持 uname -o--operating-system )作为Mac OS,Solaris . 您也可以使用 uname without argument 作为默认参数 -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 . 请提供帮助以使其保持最新(编辑答案或发表评论) . 您还可以更新维基百科文章并发表评论以通知我您的贡献;-)

    操作系统单元-s
    Mac OS XDarwin
    Cygwin 32位(Win-XP)CYGWIN_NT-5.1
    Cygwin 32位(Win-7 32位)CYGWIN_NT-6.1
    Cygwin 32位(Win-7 64位)CYGWIN_NT-6.1-WOW64
    Cygwin 64位(Win-7 64位)CYGWIN_NT-6.1
    MinGW(Windows 7 32位)MINGW32_NT-6.1
    MinGW(Windows 10 64位)MINGW64_NT-10.0
    Interix(UNIX服务)Interix MSYSMSYS_NT-6.1适用于LinuxLinux的Windows子系统
    AndroidLinux
    coreutilsLinux
    CentOSLinux
    FedoraLinux
    GentooLinux
    Red Hat LinuxLinux
    Linux MintLinux
    openSUSELinux
    UbuntuLinux
    Unity LinuxLinux
    Manjaro LinuxLinux
    OpenWRT r40420Linux
    Debian(Linux)Linux
    Debian(GNU Hurd)GNU
    Debian(kFreeBSD)GNU / kFreeBSD
    FreeBSDFreeBSD
    NetBSDNetBSD
    DragonFlyBSDDragonFly
    HaikuHaiku
    NonStopNONSTOP_KERNEL
    QNXQNX
    ReliantUNIXReliantUNIX-Y
    SINIXSINIX-Y
    Tru64OSF1
    UltrixULTRIX
    IRIX 32 bitsIRIX
    IRIX 64位IRIX64
    MINIXMinix
    SolarisSunOS
    UWIN(64位Windows 7)UWIN-W7
    SYS $ UNIX:Open on OpenVMSIS / WB上的SH
    z / OS USSOS / 390
    Craysn5176
    (SCO)OpenServerSCO_SV
    (SCO)系统VSCO_SV
    (SCO)UnixWareUnixWare
    IBM AIXAIX
    IBM i使用QSHOS400
    HP-UXHP-UX

  • 4

    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在'darwin'之后附加OS版本号 . 'win'值实际上是'win32',我被告知 - 也许有'win64'?

    也许我们可以在这里共同填写一份经过验证的值表:

    • Linux Ubuntu(包括WSL): linux-gnu

    • Cygwin 64位: cygwin

    • Msys / MINGW(适用于Windows的Git Bash): msys

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

  • 1

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

  • 9
    # 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系统

  • 8

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

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

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

    • Mac: Darwin

    • Cygwin: CYGWIN_...

    • Linux:各种各样, LINUX 为最多

  • 0

    好的,这是我的方式 .

    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中使用此功能

  • 91

    感谢贾斯汀,只使用命令行中的这个工作非常好

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

    source

相关问题