web-dev-qa-db-ja.com

BashスクリプトからOSを検出する方法

私が使用するすべてのコンピュータ間でそれらを使用できるように、私は.bashrcおよび.bash_loginファイルをバージョン管理下に置きたいと思います。問題は、OS固有のエイリアスがいくつかあるため、スクリプトがMac OS X、Linux、または Cygwin のどちらで実行されているかを判断する方法を探していたことです。

Bash スクリプトでオペレーティングシステムを検出するための適切な方法は何ですか?

429
csexton

私は以下がうまくいくはずだと思います。 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
336
Timmmm

私の.bashrcには、次のコードを使用します。

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

それから、私は次のようなことをします。

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

それは醜いですが、うまくいきます。お望みであれば、caseの代わりにifを使用することもできます。

282

Bashのマンページには、変数OSTYPEにオペレーションシステムの名前が格納されていると記載されています。

OSTYPE bashが実行されているオペレーティングシステムを記述する文字列に自動的に設定されます。デフォルトはシステムに依存します。

ここではlinux-gnuに設定されています。

267

$OSTYPE

以下のように、定義済みの$OSTYPE変数を使用することができます。

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

しかし 古いシェル では認識されません (Bourne Shell ).


uname

別の方法はunameコマンドに基づいてプラットフォームを検出することです。

次のスクリプトを参照してください(.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

あなたは私の.bashrc にいくつかの実用的な例を見つけることができます。


これは 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
130
kenorb

オペレーティングシステムとCPUの種類を検出するのは簡単ではありません 移植可能 。私は約100行のshスクリプトを持っています。これは非常に多種多様なUnixプラットフォームで動作します。私が1988年以来使用してきたシステムです。

重要な要素は

  • uname -pプロセッサタイプですが、最近のUnixプラットフォームでは通常unknownです。

  • uname -mは、いくつかのUnixシステムでは「マシンハードウェア名」を与えます。

  • /bin/Archが存在する場合、通常はプロセッサの種類を示します。

  • 引数なしのunameは、オペレーティングシステムの名前です。

最終的には、プラットフォームとの区別について考える必要があるでしょう。例えば、物事を単純にするために、i386からi686まで、およびすべての "Pentium*"などを扱います。 "AMD*Athlon*"はすべてx86と同じです。

私の~/.profileは起動時にスクリプトを実行し、1つの変数にCPUとオペレーティングシステムの組み合わせを示す文字列を設定します。それに基づいてセットアップされるプラットフォーム固有のbinmanlib、およびincludeディレクトリがあります。それから私は環境変数のボートロードを設定しました。たとえば、メールを再フォーマットするためのシェルスクリプトは、プラットフォーム固有の実行可能バイナリである$LIB/mailfmtを呼び出すことができます。

角を切る場合は、uname -mおよび普通のunameを使用すると、多くのプラットフォームで知りたいことがわかります。必要に応じて他のものを追加してください。 (caseをネストしないでifを使ってください!)

35
Norman Ramsey

私はこの完全なbashコードを使うことを勧めます

lowercase(){
    echo "$1" | 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 $2 }'`
            PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F=  '{ print $2 }'`
            REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F=  '{ print $2 }'`
        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

より多くの例はここにあります: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

32
coto

Bashでは、文書化されているように、$OSTYPE$HOSTTYPEを使います。これが私がすることです。それでも十分ではなく、unameuname -a(あるいは他の適切なオプション)でも十分な情報が得られない場合は、常に config.guess スクリプトがあります。この目的のために作成されたGNUプロジェクト。

10
Teddy

これらの答えのいくつかを避けることをお勧めします。他の形式の文字列比較を選択できることを忘れないでください。これにより、バリエーションのほとんど、または提供されている醜いコードを消去できます。

そのような解決策の1つは、次のような単純なチェックです。

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

これは、バージョン接尾辞にもかかわらず、Darwinのどのバージョンにも一致するという追加の利点があります。これはLinuxのあらゆるバリエーションに対しても同様に働きます。

ここに私のドットファイル の中にいくつかの追加の例があります

9
Akiva

"uname"を使ってみてください。たとえば、Linuxでは「uname -a」です。

マニュアルページによると、unameはSVr4とPOSIXに準拠しているので、Mac OS Xと Cygwin でも利用できるはずですが、確認できませんそれ。

ところで:$ OSTYPEもここでlinux-gnuに設定されています:)

9
Joao da Silva

私はこれらの糖を私の.bashrcに書きました:

if_os () { [[ $OSTYPE == *$1* ]]; }
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}" == "$1" ]];
}

だから私は以下のようなことができます:

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"
8
kfix
uname

または

uname -a

もっと情報が欲しいなら

7

私は 個人的なBashライブラリとスクリプトフレームワーク を作成しました。これは GNU shtool を使用してかなり正確なプラットフォーム検出を行います。

GNU shtoolは非常に移植性の高いスクリプトセットで、他にも便利なものとして「shtool platform」コマンドが含まれています。これは以下の出力です。

shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"

いくつかの異なるマシンでは:

Mac OS X Leopard: 
    4.4BSD/Mach3.0 (iX86) Apple Darwin 9.6.0 (i386) Apple Mac OS X 10.5.6 (iX86)

Ubuntu Jaunty server:
    LSB (iX86) GNU/Linux 2.9/2.6 (i686) Ubuntu 9.04 (iX86)

Debian Lenny:
    LSB (iX86) GNU/Linux 2.7/2.6 (i686) Debian GNU/Linux 5.0 (iX86)

ご覧のとおり、これでかなり満足のいく結果が得られます。 GNU shtoolは少し遅いので、私はスクリプトが呼び出すシステム上のファイルにプラットフォームIDを格納して更新します。それは私のフレームワークなので、それは私のために動作しますが、あなたの走行距離は異なるかもしれません。

さて、あなたはあなたのスクリプトでshtoolをパッケージする方法を見つける必要があります、しかしそれは難しい練習ではありません。あなたはいつでもuname出力に頼ることもできます。

編集:

私はconfig.guessについてのTeddyによる投稿を逃しました(どういうわけか)。これらは非常によく似たスクリプトですが、同じではありません。私は個人的に他の用途にもshtoolを使用しています、そしてそれは私のために非常にうまく機能しています。

7
guns

次のものを使用できます。

OS=$(uname -s)

それからあなたはあなたのスクリプトでOS変数を使用することができます。

7
Chetan kapoor

以下はDebianとRedHatベースのLinux OSを使用して/ etc/lsbを検出するアプローチです。 -releaseおよび/ etc/os-release(Linuxによって異なります)あなたが使用しているフレーバー)とそれに基づいて簡単なアクションを取ります。

#!/bin/bash
set -e

YUM_PACKAGE_NAME="python python-devl python-pip openssl-devel"
DEB_PACKAGE_NAME="python2.7 python-dev python-pip libssl-dev"

 if cat /etc/*release | grep ^NAME | grep CentOS; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on CentOS"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Red; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on RedHat"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Fedora; then
    echo "================================================"
    echo "Installing packages $YUM_PACKAGE_NAME on Fedorea"
    echo "================================================"
    yum install -y $YUM_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Ubuntu; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Ubuntu"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Debian ; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Debian"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Mint ; then
    echo "============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Mint"
    echo "============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 Elif cat /etc/*release | grep ^NAME | grep Knoppix ; then
    echo "================================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Kanoppix"
    echo "================================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 else
    echo "OS NOT DETECTED, couldn't install package $PACKAGE"
    exit 1;
 fi

exit 0

出力例Ubuntu Linuxの場合:

delivery@delivery-E5450$ Sudo sh detect_os.sh
[Sudo] password for delivery: 
NAME="Ubuntu"
===============================================
Installing packages python2.7 python-dev python-pip libssl-dev on Ubuntu
===============================================
Ign http://dl.google.com stable InRelease
Get:1 http://dl.google.com stable Release.gpg [916 B]                          
Get:2 http://dl.google.com stable Release [1.189 B] 
...            
5

これはすべてのディストリビューションで安全に使用できるはずです。

$ cat /etc/*release

これはこのようなものを生み出す。

     DISTRIB_ID=LinuxMint
     DISTRIB_RELEASE=17
     DISTRIB_CODENAME=qiana
     DISTRIB_DESCRIPTION="Linux Mint 17 Qiana"
     NAME="Ubuntu"
     VERSION="14.04.1 LTS, Trusty Tahr"
     ID=ubuntu
     ID_LIKE=debian
     PRETTY_NAME="Ubuntu 14.04.1 LTS"
     VERSION_ID="14.04"
     HOME_URL="http://www.ubuntu.com/"
     SUPPORT_URL="http://help.ubuntu.com/"
     BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

必要に応じて抽出/変数への代入

注:セットアップによっては。これにより、無視できるエラーもいくつか発生する可能性があります。

     cat: /etc/upstream-release: Is a directory
5
R J

次のif句を使用して、必要に応じて拡張することができます。

if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
    aminute_ago="-v-1M"
Elif  [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
    aminute_ago="-d \"1 minute ago\""
fi
2
Tahsin Turkoz

私の.bashrcと.bash_aliasは、すべてのプラットフォームがアクセスできるファイル共有に保存する傾向があります。これは私が私の.bash_aliasで問題を克服する方法です:

if [[ -f (name of share)/.bash_alias_$(uname) ]]; then
    . (name of share)/.bash_alias_$(uname)
fi

そして、私は例えば.bash_alias_Linuxを持っています:

alias ls='ls --color=auto'

こうすることで、プラットフォーム固有のコードと移植可能なコードを別々にしています。bashrcでも同じことができます。

1
ericcurtin

LinuxディストリビューションがDebianまたはUbunuの場合、これはknownファイルの束をチェックして識別します。その場合、デフォルトは$OSTYPE変数になります。

os='Uknown'
unamestr="${OSTYPE//[0-9.]/}"
os=$( compgen -G "/etc/*release" > /dev/null  && cat /etc/*release | grep ^NAME | tr -d 'NAME="'  ||  echo "$unamestr")

echo "$os"
0
Kuzeko

次のことを行うことで、ubuntuのチェックが正しく行われました。

if [[ "$OSTYPE" =~ ^linux ]]; then
    Sudo apt-get install <some-package>
fi
0
sandman

私はいくつかのLinuxディストリビューションにまたがって上記のメッセージを試してみましたが、次のものが自分に最適であることがわかりました。これは、Windows上のBashでも機能する、短く簡潔で正確なWordの回答です。

OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
0
intellilogic

これを試して:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
0