내가 사용하는 모든 컴퓨터에서 사용할 수 있도록 내 파일 .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
힘내 배쉬 / 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
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
오라클을 사용하는 것이 좋겠다고 제안 하고 무료 버전 문자열을 넣었습니다 OSTYPE ==> solaris2.11
. uname
조금 더 깨끗하고해야 할 일이 적습니다.
검출 운영 체제 및 CPU 타입은 너무 쉽게 할 수없는 이식 . 나는 sh
매우 다양한 Unix 플랫폼에서 작동하는 약 100 줄 의 스크립트를 가지고 있습니다 : 1988 년 이래로 사용한 시스템.
핵심 요소는
uname -p
입니다 프로세서 유형 하지만 일반적으로 unknown
현대 유닉스 플랫폼에서.
uname -m
일부 유닉스 시스템에서 "기계 하드웨어 이름"을 제공합니다.
/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
"블라 릴리즈"를 찾는 것 같습니다. 등
bash에서 문서화 된대로 $OSTYPE
및을 사용하십시오 $HOSTTYPE
. 이것이 제가하는 것입니다. 이것으로 충분하지 않고 짝수 uname
또는 uname -a
다른 적절한 옵션으로 충분한 정보를 얻지 못하면 GNU 프로젝트 의 config.guess 스크립트 가 항상 이 목적을 위해 만들어졌습니다.
"uname"을 사용해보십시오. 예를 들어, Linux의 경우 : "uname -a"
매뉴얼 페이지에 따르면 uname은 SVr4 및 POSIX를 준수하므로 Mac OS X 및 Cygwin 에서도 사용할 수 있지만 확인할 수는 없습니다.
BTW : $ 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 하위 시스템을 구체적으로 감지하기 위해 내가 찾은 유일한 솔루션은/proc/sys/kernel/osrelease
uname
또는
uname -a
더 많은 정보를 원한다면
내가 쓴 개인 배쉬 라이브러리와 스크립트 프레임 워크를 사용하는 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은 약간 느리므로 실제로 스크립트를 호출하는 시스템의 파일에 플랫폼 식별을 저장하고 업데이트합니다. 그것은 내 프레임 워크이므로 나에게 효과적이지만 마일리지는 다를 수 있습니다.
이제 스크립트로 shtool을 패키징하는 방법을 찾아야하지만 어려운 것은 아닙니다. 또한 항상 uname 출력으로 넘어갈 수 있습니다.
편집하다:
Teddy가 config.guess
(어떻게 든) 게시물을 놓쳤습니다 . 이들은 매우 유사한 스크립트이지만 동일하지는 않습니다. 나는 개인적으로 다른 용도로 shtool을 사용하며 나에게 아주 잘 작동했습니다.
다음을 사용할 수 있습니다.
OS=$(uname -s)
스크립트에서 OS 변수를 사용할 수 있습니다.
uname -s
은 어떻게 다른지 설명 할 수 uname
있습니까?
아래 는 / etc / lsb-release 및 / etc / os-release (사용중인 Linux 버전 에 따라 다름)를 사용 하는 데비안 및 RedHat 기반 Linux OS 를 감지 하고 이를 기반으로 간단한 조치를 취하는 방법입니다.
#!/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
출력 예를 위한 우분투 리눅스 :
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 배포판에서 위의 메시지를 시도한 결과 다음과 같은 것이 가장 효과적입니다. 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에 대해 동일한 작업을 수행 할 수 있습니다