cse*_*ton 463 bash os-detection
我想保留我.bashrc
和.bash_login
文件的版本控制,以便我可以在我使用的所有计算机之间使用它们.问题是,我有一些特定于操作系统的别名,所以我一直在寻找一种方式来确定脚本在Mac OS X,Linux或运行Cygwin的.
在Bash脚本中检测操作系统的正确方法是什么?
Tim*_*mmm 416
我认为以下内容应该有效.我不确定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
Run Code Online (Sandbox Code Playgroud)
小智 285
对于我的.bashrc,我使用以下代码:
platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
platform='freebsd'
fi
Run Code Online (Sandbox Code Playgroud)
然后我做的事情如下:
if [[ $platform == 'linux' ]]; then
alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
alias ls='ls -G'
fi
Run Code Online (Sandbox Code Playgroud)
这很难看,但它确实有效.如果您愿意,可以使用case
而不是if
.
Joh*_*itb 272
bash手册页说变量OSTYPE存储操作系统的名称:
OSTYPE
自动设置为描述正在执行bash的操作系统的字符串.默认值取决于系统.
它设置在linux-gnu
这里.
ken*_*orb 142
您可以简单地使用预定义的$ OSTYPE变量即:
case "$OSTYPE" in
solaris*) echo "SOLARIS" ;;
darwin*) echo "OSX" ;;
linux*) echo "LINUX" ;;
bsd*) echo "BSD" ;;
msys*) echo "WINDOWS" ;;
*) echo "unknown: $OSTYPE" ;;
esac
Run Code Online (Sandbox Code Playgroud)
另一种方法是基于$OSTYPE
命令检测平台.
请参阅以下脚本(准备包含在.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
Run Code Online (Sandbox Code Playgroud)
Nor*_*sey 35
检测操作系统和CPU类型并不容易移植.我有一个sh
大约100行的脚本,适用于各种各样的Unix平台:自1988年以来我使用过的任何系统.
关键要素是
uname -p
是处理器类型,但通常unknown
在现代Unix平台上.
uname -m
将在某些Unix系统上提供"机器硬件名称".
/bin/arch
,如果它存在,通常会给出处理器的类型.
uname
没有参数将命名操作系统.
最终,您将不得不考虑平台之间的区别以及您想要制作它们的精确程度. 例如,只是为了让事情变得简单,我把i386
通过i686
,任何" Pentium*
"任何" AMD*Athlon*
"所有的x86
.
我~/.profile
在启动时运行一个脚本,它将一个变量设置为一个字符串,表示CPU和操作系统的组合.我有特定于平台的bin
,man
,lib
,和include
基于该是那些获得建立目录.然后我设置了一大堆环境变量.因此,例如,重新格式化邮件的shell脚本可以调用,例如,$LIB/mailfmt
这是特定于平台的可执行二进制文件.
如果你想偷工减料,那么uname -m
普通话uname
会告诉你在许多平台上你想知道什么.在需要时添加其他东西.(并使用case
,而不是嵌套if
!)
cot*_*oto 33
我建议使用这个完整的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
Run Code Online (Sandbox Code Playgroud)
这里有更多示例:https://github.com/coto/server-easy-install/blob/master/lib/core.sh
Bra*_*rad 14
如果有人也有兴趣检测 WSL 与 WSL 版本 2,我会使用此方法。这在 ZSH 和 BASH 中都有效。
#!/usr/bin/env bash
unameOut=$(uname -a)
case "${unameOut}" in
*Microsoft*) OS="WSL";; #must be first since Windows subsystem for linux will have Linux in the name too
*microsoft*) OS="WSL2";; #WARNING: My v2 uses ubuntu 20.4 at the moment slightly different name may not always work
Linux*) OS="Linux";;
Darwin*) OS="Mac";;
CYGWIN*) OS="Cygwin";;
MINGW*) OS="Windows";;
*Msys) OS="Windows";;
*) OS="UNKNOWN:${unameOut}"
esac
echo ${OS};
Run Code Online (Sandbox Code Playgroud)
更新:我还将其添加到我的脚本中,用于检测 M1 与普通 Mac。
if [[ ${OS} == "Mac" ]] && sysctl -n machdep.cpu.brand_string | grep -q 'Apple M1'; then
OS="MacM1"
fi
Run Code Online (Sandbox Code Playgroud)
Ted*_*ddy 10
在bash中,使用$OSTYPE
和$HOSTTYPE
记录; 这就是我做的.如果这还不够,如果偶数uname
或uname -a
(或其他适当的选项)没有提供足够的信息,那么GNU项目中的config.guess脚本总是完全用于此目的.
我在这里写了这些糖.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" ]];
}
Run Code Online (Sandbox Code Playgroud)
所以我可以这样做:
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"
Run Code Online (Sandbox Code Playgroud)
尝试这个:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
Run Code Online (Sandbox Code Playgroud)
uname
Run Code Online (Sandbox Code Playgroud)
要么
uname -a
Run Code Online (Sandbox Code Playgroud)
如果你想了解更多信息
我编写了一个个人Bash库和脚本框架,它使用GNU shtool进行相当准确的平台检测.
GNU shtool是一组非常便携的脚本,除了其他有用的东西之外,还包含'shtool platform'命令.这是输出:
shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"
Run Code Online (Sandbox Code Playgroud)
在几台不同的机器上:
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)
Run Code Online (Sandbox Code Playgroud)
如您所见,这会产生非常令人满意的结果.GNU shtool有点慢,所以我实际上将平台标识存储并更新到我的脚本调用的系统上的文件中.这是我的框架,所以对我有用,但你的里程可能会有所不同.
现在,您必须找到一种方法来使用脚本打包shtool,但这不是一项艰苦的练习.你也总是可以依靠uname输出.
编辑:
我错过了泰迪的帖子config.guess
(某种程度上).这些是非常相似的脚本,但不一样.我个人也将shtool用于其他用途,它对我来说一直很好用.
下面是一种检测基于 Debian 和 RedHat 的Linux 操作系统的方法,该方法使用/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
Run Code Online (Sandbox Code Playgroud)
输出例如用于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]
...
Run Code Online (Sandbox Code Playgroud)
这应该可以安全地用于所有发行版.
$ cat /etc/*release
Run Code Online (Sandbox Code Playgroud)
这产生了这样的东西.
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/"
Run Code Online (Sandbox Code Playgroud)
根据需要提取/分配变量
注意:在某些设置上.这也可能会给您一些您可以忽略的错误.
cat: /etc/upstream-release: Is a directory
Run Code Online (Sandbox Code Playgroud)
您可以使用以下 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
Run Code Online (Sandbox Code Playgroud)