如何从 Bash 脚本中检测操作系统?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/394230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:51:52  来源:igfitidea点击:

How to detect the OS from a Bash script?

bashos-detection

提问by csexton

I would like to keep my .bashrcand .bash_loginfiles in version control so that I can use them between all the computers I use. The problem is I have some OS specific aliases so I was looking for a way to determine if the script is running on Mac OS X, Linux or Cygwin.

我想将我的.bashrc.bash_login文件保持在版本控制中,以便我可以在我使用的所有计算机之间使用它们。问题是我有一些特定于操作系统的别名,所以我正在寻找一种方法来确定脚本是在 Mac OS X、Linux 还是Cygwin 上运行

What is the proper way to detect the operating system in a Bashscript?

Bash脚本中检测操作系统的正确方法是什么?

采纳答案by Timmmm

I think the following should work. I'm not sure about win32though.

我认为以下应该有效。我不确定win32

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # POSIX compatibility layer and Linux environment emulation for Windows
elif [[ "$OSTYPE" == "msys" ]]; then
        # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
elif [[ "$OSTYPE" == "win32" ]]; then
        # I'm not sure this can happen.
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
else
        # Unknown.
fi

回答by Nicolas Martyanoff

For my .bashrc, I use the following code:

对于我的 .bashrc,我使用以下代码:

platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
   platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
   platform='freebsd'
fi

Then I do somethings like:

然后我做这样的事情:

if [[ $platform == 'linux' ]]; then
   alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
   alias ls='ls -G'
fi

It's ugly, but it works. You may use caseinstead of ifif you prefer.

这很丑陋,但它有效。如果您愿意,可以使用case代替if

回答by Johannes Schaub - litb

The bash manpage says that the variable OSTYPE stores the name of the operation system:

bash 手册页说变量 OSTYPE 存储操作系统的名称:

OSTYPEAutomatically set to a string that describes the operating system on which bash is executing. The default is system- dependent.

OSTYPE自动设置为描述执行 bash 的操作系统的字符串。默认值取决于系统。

It is set to linux-gnuhere.

设置到linux-gnu这里。

回答by kenorb

$OSTYPE

$OSTYPE

You can simply use pre-defined $OSTYPEvariable e.g.:

您可以简单地使用预定义的$OSTYPE变量,例如:

case "$OSTYPE" in
  solaris*) echo "SOLARIS" ;;
  darwin*)  echo "OSX" ;; 
  linux*)   echo "LINUX" ;;
  bsd*)     echo "BSD" ;;
  msys*)    echo "WINDOWS" ;;
  *)        echo "unknown: $OSTYPE" ;;
esac

However it's not recognized by the older shells(such as Bourne shell).

但是,旧的 shell(例如Bourne shell无法识别它。



uname

uname

Another method is to detect platform based on unamecommand.

另一种方法是基于uname命令检测平台。

See the following script (ready to include in .bashrc):

请参阅以下脚本(已准备好包含在 .bashrc 中):

# Detect the platform (similar to $OSTYPE)
OS="`uname`"
case $OS in
  'Linux')
    OS='Linux'
    alias ls='ls --color=auto'
    ;;
  'FreeBSD')
    OS='FreeBSD'
    alias ls='ls -G'
    ;;
  'WindowsNT')
    OS='Windows'
    ;;
  'Darwin') 
    OS='Mac'
    ;;
  'SunOS')
    OS='Solaris'
    ;;
  'AIX') ;;
  *) ;;
esac

You can find some practical example in my .bashrc.

您可以在我的.bashrc.



Here is similar version used on Travis CI:

这是Travis CI上使用的类似版本:

case $(uname | tr '[:upper:]' '[:lower:]') in
  linux*)
    export TRAVIS_OS_NAME=linux
    ;;
  darwin*)
    export TRAVIS_OS_NAME=osx
    ;;
  msys*)
    export TRAVIS_OS_NAME=windows
    ;;
  *)
    export TRAVIS_OS_NAME=notset
    ;;
esac

回答by Norman Ramsey

Detecting operating system and CPU typeis not so easy to do portably. I have a shscript of about 100 lines that works across a very wide variety of Unix platforms: any system I have used since 1988.

检测操作系统和 CPU 类型并不是那么容易便携。我有一个sh大约 100 行的脚本,可以在非常广泛的 Unix 平台上运行:自 1988 年以来我使用过的任何系统。

The key elements are

关键要素是

  • uname -pis processor typebut is usually unknownon modern Unix platforms.

  • uname -mwill give the "machine hardware name" on some Unix systems.

  • /bin/arch, if it exists, will usually give the type of processor.

  • unamewith no arguments will name the operating system.

  • uname -p处理器类型,但通常unknown在现代 Unix 平台上。

  • uname -m将在某些 Unix 系统上给出“机器硬件名称”。

  • /bin/arch,如果存在,通常会给出处理器的类型。

  • uname不带参数将命名操作系统。

Eventually you will have to think about the distinctions between platforms and how fine you want to make them.For example, just to keep things simple, I treat i386through i686, any "Pentium*" and any "AMD*Athlon*" all as x86.

最终,您将不得不考虑平台之间的区别以及您想让它们做得多好。例如,只是为了让事情变得简单,我把i386通过i686,任何“ Pentium*”任何“ AMD*Athlon*”所有的x86

My ~/.profileruns an a script at startup which sets one variable to a string indicating the combination of CPU and operating system. I have platform-specific bin, man, lib, and includedirectories that get set up based on that. Then I set a boatload of environment variables. So for example, a shell script to reformat mail can call, e.g., $LIB/mailfmtwhich is a platform-specific executable binary.

~/.profile在启动时运行一个脚本,它将一个变量设置为一个字符串,指示 CPU 和操作系统的组合。我有特定于平台的binmanlib,和include基于该是那些获得建立目录。然后我设置了一大堆环境变量。因此,例如,重新格式化邮件的 shell 脚本可以调用,例如,$LIB/mailfmt它是特定于平台的可执行二进制文件。

If you want to cut corners, uname -mand plain unamewill tell you what you want to know on many platforms. Add other stuff when you need it. (And use case, not nested if!)

如果你想偷工减料uname -mplainuname会在很多平台上告诉你你想知道什么。需要时添加其他内容。(并使用case,不嵌套if!)

回答by coto

I recommend to use this complete bash code

我建议使用这个完整的 bash 代码

lowercase(){
    echo "" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
}

OS=`lowercase \`uname\``
KERNEL=`uname -r`
MACH=`uname -m`

if [ "{$OS}" == "windowsnt" ]; then
    OS=windows
elif [ "{$OS}" == "darwin" ]; then
    OS=mac
else
    OS=`uname`
    if [ "${OS}" = "SunOS" ] ; then
        OS=Solaris
        ARCH=`uname -p`
        OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
    elif [ "${OS}" = "AIX" ] ; then
        OSSTR="${OS} `oslevel` (`oslevel -r`)"
    elif [ "${OS}" = "Linux" ] ; then
        if [ -f /etc/redhat-release ] ; then
            DistroBasedOn='RedHat'
            DIST=`cat /etc/redhat-release |sed s/\ release.*//`
            PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/SuSE-release ] ; then
            DistroBasedOn='SuSe'
            PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
            REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
        elif [ -f /etc/mandrake-release ] ; then
            DistroBasedOn='Mandrake'
            PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/debian_version ] ; then
            DistroBasedOn='Debian'
            DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F=  '{ print  }'`
            PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F=  '{ print  }'`
            REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F=  '{ print  }'`
        fi
        if [ -f /etc/UnitedLinux-release ] ; then
            DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
        fi
        OS=`lowercase $OS`
        DistroBasedOn=`lowercase $DistroBasedOn`
        readonly OS
        readonly DIST
        readonly DistroBasedOn
        readonly PSUEDONAME
        readonly REV
        readonly KERNEL
        readonly MACH
    fi

fi

more examples examples here: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

更多示例示例:https: //github.com/coto/server-easy-install/blob/master/lib/core.sh

回答by Teddy

In bash, use $OSTYPEand $HOSTTYPE, as documented; this is what I do. If that is not enough, and if even unameor uname -a(or other appropriate options) does not give enough information, there's always the config.guessscript from the GNU project, made exactly for this purpose.

在 bash 中,使用$OSTYPEand $HOSTTYPE,如文档所述;这就是我所做的。如果这还不够,甚至unameuname -a(或其他适当的选项)没有提供足够的信息,那么总是有来自 GNU 项目的config.guess脚本,正是为此目的而制作的。

回答by Joao da Silva

Try using "uname". For example, in Linux: "uname -a".

尝试使用“uname”。例如,在 Linux 中:“uname -a”。

According to the manual page, uname conforms to SVr4 and POSIX, so it should be available on Mac OS X and Cygwintoo, but I can't confirm that.

根据手册页,uname 符合 SVr4 和 POSIX,所以它应该也适用于 Mac OS X 和Cygwin,但我无法确认。

BTW: $OSTYPE is also set to linux-gnuhere :)

顺便说一句:$OSTYPE 也设置在linux-gnu这里 :)

回答by Akiva

I would suggest avoiding some of these answers. Don't forget that you can choose other forms of string comparison, which would clear up most of the variations, or ugly code offered.

我建议避免其中一些答案。不要忘记,您可以选择其他形式的字符串比较,这将清除大多数变体或提供的丑陋代码。

One such solution would be a simple check, such as:

一个这样的解决方案是一个简单的检查,例如:

if [[ "$OSTYPE" =~ ^darwin ]]; then

if [[ "$OSTYPE" =~ ^darwin ]]; then

Which has the added benefit of matching any version of Darwin, despite it's version suffix. This also works for any variations of Linuxone may expect.

尽管它是版本后缀,但它具有匹配任何版本的 Darwin 的额外好处。这也适用于Linux人们可能期望的任何变化。

You can see some additional examples within my dotfiles here

您可以在此处查看我的 dotfiles 中的一些其他示例

回答by kfix

I wrote these sugars in my .bashrc:

我在我的.bashrc:

if_os () { [[ $OSTYPE == ** ]]; }
if_nix () { 
    case "$OSTYPE" in
        *linux*|*hurd*|*msys*|*cygwin*|*sua*|*interix*) sys="gnu";;
        *bsd*|*darwin*) sys="bsd";;
        *sunos*|*solaris*|*indiana*|*illumos*|*smartos*) sys="sun";;
    esac
    [[ "${sys}" == "" ]];
}

So I can do stuff like:

所以我可以做这样的事情:

if_nix gnu && alias ls='ls --color=auto' && export LS_COLORS="..."
if_nix bsd && export CLICOLORS=on && export LSCOLORS="..."
if_os linux && alias psg="ps -FA | grep" #alternative to pgrep
if_nix bsd && alias psg="ps -alwx | grep -i" #alternative to pgrep
if_os darwin && alias finder="open -R"