我有一个shell脚本,可以在Windows/Cygwin,Mac和Linux上使用.每个版本需要稍微不同的变量.
shell/bash脚本如何检测它是在Cygwin,Mac或Linux上运行?
在你的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
参数).
使用expr
和substr
处理字符串.
用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位)测试正常.
检查开盘价和收盘价.
检查是否缺少括号和括号{}
[1] uname - 维基百科
[2] shell脚本语法错误:意外的文件结束
[3] 从Bash脚本中检测操作系统
[4] BASH编程介绍如何操作
通常,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
给出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}
请注意,我假设您实际上在 CygWin(bash
它的shell)中运行,因此路径应该已经正确设置.正如一位评论者所指出的那样,您可以运行bash
程序,从而cmd
自行传递脚本,这可能会导致路径未按需设置.
如果你正在这样做,这是你的责任,以确保正确的可执行文件(即,在Cygwin的)都被调用,可能是由事先修改路径或完全指定可执行文件的位置(例如,/c/cygwin/bin/uname
).
某些操作系统不支持使用uname -s
(--kernel-name
)因为uname -o
(--operating-system
),如Mac OS,Solaris.您也可以使用uname
不带参数,因为默认参数是-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项目(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 -s
和的完整答案Makefile
.
这个答案底部的对应表来自维基百科的文章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
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
(如果它与现有条目不同,请附加您的值)
为了建立在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
这避免了解析Windows名称的$OS
变体,并解析uname
类似MINGW,Cygwin等的变体.
背景:%COMSPEC%
是一个Windows环境变量,指定命令处理器(也称为Windows shell)的完整路径.通常%SystemRoot%\system32\cmd.exe
,此变量的值通常计算为C:\Windows\system32\cmd.exe
.
# 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系统