.bashrc
と.bash_login
ファイルをバージョン管理下に置いて、使用するすべてのコンピュータ間でそれらを使用できるようにしたいと考えています。問題は、OS固有のエイリアスがあるため、スクリプトがMac OS X、Linux、またはCygwinで実行されているかどうかを確認する方法を探していたということです。
Bashスクリプトでオペレーティングシステムを検出する適切な方法は何ですか?
.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
msys
Git Bash / msysGitとcygwin
Cygwin を取得します
msys
;
。
source somefile ;
、が表示されますsyntax error near unexpected token elif
。
私の.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
ます。
platform="$(uname | tr '[:upper:]' '[:lower:]')"
でしょうか?それから間違いなくケースを処理しますか?非常に特定の出力への依存関係をハードコーディングするのは奇妙に思えます。
bashのマンページには、変数OSTYPEにオペレーティングシステムの名前が格納されていると記載されています。
OSTYPE
bashが実行されているオペレーティングシステムを説明する文字列に自動的に設定されます。デフォルトはシステム依存です。
linux-gnu
こちらに設定されています。
os=${OSTYPE//[0-9.]/}
case $OSTYPE in darwin*) echo I am a Mac ;; esac
if [[ $OSTYPE == darwin* ]]; then echo I am a Mac;fi
$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シェルなど)では認識されません。
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
uname
ます。Oracleは慣習を厳しくしており、無料のバージョン文字列をに付けていOSTYPE ==> solaris2.11
ます。 uname
少しすっきりとしていて、作業が少なくて済みます。
オペレーティングシステムとCPUの種類を検出することは、移植性の高い方法で行うのは簡単ではありません。私は、sh
非常に多種多様なUnixプラットフォームで動作する約100行のスクリプトを持っています。1988年以降に使用したすべてのシステムです。
重要な要素は
uname -p
あるプロセッサの種類が、通常であるunknown
近代的なUnixプラットフォーム上で。
uname -m
一部のUnixシステムでは「マシンハードウェア名」が表示されます。
/bin/arch
が存在する場合、通常はプロセッサのタイプを示します。
uname
引数を指定しないと、オペレーティングシステムが指定されます。
最終的には、プラットフォーム間の違いとそれらをどの程度細かくしたいかについて考える必要があります。 たとえば、物事をシンプルに保つために、私はをi386
介してi686
、「Pentium*
」と「AMD*Athlon*
」をすべてとして扱いx86
ます。
私は、~/.profile
CPUとオペレーティングシステムの組み合わせを示す文字列に一つの変数を設定し、起動時にスクリプトを実行します。私は、プラットフォーム固有を持ってbin
、man
、lib
、およびinclude
それに基づいて設定しますディレクトリ。次に、環境変数のボートロードを設定します。したがって、たとえば、メールを再フォーマットするためのシェルスクリプトは、たとえば、$LIB/mailfmt
プラットフォーム固有の実行可能バイナリを呼び出すことができます。
あなたがカットコーナーにしたい場合は、uname -m
と平野はuname
あなたが多くのプラットフォーム上で知って欲しいものを教えてくれます。必要なときに他のものを追加します。(そしてcase
、ネストではなくif
!を使用してください)
uname -s
ですか?
この完全な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
ls /etc
、「何とかリリース」を探すのが最も簡単なように思えます。 、その他
文書化されているよう$OSTYPE
に$HOSTTYPE
、bashではandを使用します。これが私がすることです。それでも不十分な場合、uname
またはor uname -a
(または他の適切なオプション)で十分な情報が得られない場合は、この目的のために作成されたGNUプロジェクトのconfig.guessスクリプトが常に存在します。
「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"
if_nix gnu
&の両方に対してtrueを返します if_os linux
。
echo $OSTYPE
ます。具体的にはwin 10 bashサブシステムを検出するために、私が見つけた唯一の解決策は「Microsoft」をチェックすることでした/proc/sys/kernel/osrelease
uname
または
uname -a
詳細情報が必要な場合
私は、GNU shtoolを使用してかなり正確なプラットフォーム検出を行う、個人用のBashライブラリとスクリプトフレームワークを作成しました。
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
(どういうわけか)テディの投稿を見逃しました。これらは非常によく似たスクリプトですが、同じではありません。個人的には他の用途にもshtoolを使用しており、私にとっては非常にうまく機能しています。
次のものを使用できます。
OS=$(uname -s)
その後、スクリプトでOS変数を使用できます。
uname -s
に違うのですuname
か?
以下は、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
[user@host ~]$ cat /etc/*release CentOS release 6.4 (Final) CentOS release 6.4 (Final) CentOS release 6.4 (Final)
cat: /etc/*release: No such file or directory
これを試して:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
cat: /etc/*-release: No such file or directory
zsh: no matches found: /etc/*release
-これはLinuxシステムでのみ機能すると思います...
いくつかのLinuxディストリビューションで上記のメッセージを試してみたところ、次のことが最もうまく機能することがわかりました。これは、WindowsのBashでも機能する、短くて簡潔な正確な単語の答えです。
OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
OS=$( ([[ -f /etc/*release ]] && cat /etc/*release | grep ^NAME | tr -d 'NAME="') || echo "Unknown" )
これはエラーをスローせずに動作します。
OS=$( $(compgen -G "/etc/*release" > /dev/null) && cat /etc/*release | grep ^NAME | tr -d 'NAME="') || $( echo "${OSTYPE//[0-9.]/}")
私は、すべてのプラットフォームがアクセスできるファイル共有に.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でも同じことができます