私が使用するすべてのコンピュータ間でそれらを使用できるように、私は.bashrc
および.bash_login
ファイルをバージョン管理下に置きたいと思います。問題は、OS固有のエイリアスがいくつかあるため、スクリプトがMac OS X、Linux、または Cygwin のどちらで実行されているかを判断する方法を探していたことです。
Bash スクリプトでオペレーティングシステムを検出するための適切な方法は何ですか?
私は以下がうまくいくはずだと思います。 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
私の.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
を使用することもできます。
Bashのマンページには、変数OSTYPEにオペレーションシステムの名前が格納されていると記載されています。
OSTYPE
bashが実行されているオペレーティングシステムを記述する文字列に自動的に設定されます。デフォルトはシステムに依存します。
ここではlinux-gnu
に設定されています。
$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
オペレーティングシステムとCPUの種類を検出するのは簡単ではありません 移植可能 。私は約100行のsh
スクリプトを持っています。これは非常に多種多様なUnixプラットフォームで動作します。私が1988年以来使用してきたシステムです。
重要な要素は
uname -p
はプロセッサタイプですが、最近のUnixプラットフォームでは通常unknown
です。
uname -m
は、いくつかのUnixシステムでは「マシンハードウェア名」を与えます。
/bin/Arch
が存在する場合、通常はプロセッサの種類を示します。
引数なしのuname
は、オペレーティングシステムの名前です。
最終的には、プラットフォームとの区別について考える必要があるでしょう。例えば、物事を単純にするために、i386
からi686
まで、およびすべての "Pentium*
"などを扱います。 "AMD*Athlon*
"はすべてx86
と同じです。
私の~/.profile
は起動時にスクリプトを実行し、1つの変数にCPUとオペレーティングシステムの組み合わせを示す文字列を設定します。それに基づいてセットアップされるプラットフォーム固有のbin
、man
、lib
、およびinclude
ディレクトリがあります。それから私は環境変数のボートロードを設定しました。たとえば、メールを再フォーマットするためのシェルスクリプトは、プラットフォーム固有の実行可能バイナリである$LIB/mailfmt
を呼び出すことができます。
角を切る場合は、、uname -m
および普通のuname
を使用すると、多くのプラットフォームで知りたいことがわかります。必要に応じて他のものを追加してください。 (case
をネストしないでif
を使ってください!)
私はこの完全な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
Bashでは、文書化されているように、$OSTYPE
と$HOSTTYPE
を使います。これが私がすることです。それでも十分ではなく、uname
やuname -a
(あるいは他の適切なオプション)でも十分な情報が得られない場合は、常に config.guess スクリプトがあります。この目的のために作成されたGNUプロジェクト。
これらの答えのいくつかを避けることをお勧めします。他の形式の文字列比較を選択できることを忘れないでください。これにより、バリエーションのほとんど、または提供されている醜いコードを消去できます。
そのような解決策の1つは、次のような単純なチェックです。
if [[ "$OSTYPE" =~ ^darwin ]]; then
これは、バージョン接尾辞にもかかわらず、Darwinのどのバージョンにも一致するという追加の利点があります。これはLinux
のあらゆるバリエーションに対しても同様に働きます。
ここに私のドットファイル の中にいくつかの追加の例があります
"uname"を使ってみてください。たとえば、Linuxでは「uname -a」です。
マニュアルページによると、unameはSVr4とPOSIXに準拠しているので、Mac OS Xと Cygwin でも利用できるはずですが、確認できませんそれ。
ところで:$ OSTYPEもここでlinux-gnu
に設定されています:)
私はこれらの糖を私の.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"
uname
または
uname -a
もっと情報が欲しいなら
私は 個人的な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を使用しています、そしてそれは私のために非常にうまく機能しています。
次のものを使用できます。
OS=$(uname -s)
それからあなたはあなたのスクリプトでOS変数を使用することができます。
以下は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]
...
これはすべてのディストリビューションで安全に使用できるはずです。
$ 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
次の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
私の.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でも同じことができます。
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"
次のことを行うことで、ubuntuのチェックが正しく行われました。
if [[ "$OSTYPE" =~ ^linux ]]; then
Sudo apt-get install <some-package>
fi
私はいくつかのLinuxディストリビューションにまたがって上記のメッセージを試してみましたが、次のものが自分に最適であることがわかりました。これは、Windows上のBashでも機能する、短く簡潔で正確なWordの回答です。
OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
これを試して:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"