我想保持我的.bashrc和.bash_login文件在版本控制,以便我可以在我使用的所有计算机之间使用它们。问题是我有一些操作系统特定的别名,所以我正在寻找一种方法来确定脚本是否在Mac OS X, Linux或Cygwin上运行。
在Bash脚本中检测操作系统的正确方法是什么?
我想保持我的.bashrc和.bash_login文件在版本控制,以便我可以在我使用的所有计算机之间使用它们。问题是我有一些操作系统特定的别名,所以我正在寻找一种方法来确定脚本是否在Mac OS X, Linux或Cygwin上运行。
在Bash脚本中检测操作系统的正确方法是什么?
当前回答
如果有人对检测WSL和WSL版本2感兴趣,我也会使用这个工具。
#!/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};
其他回答
你可以使用下面的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
检测操作系统和CPU类型并不容易移植。我有一个大约100行的sh脚本,可以在非常广泛的Unix平台上运行:自1988年以来我使用过的任何系统。
关键要素是
uname -p是处理器类型,但在现代Unix平台上通常是未知的。 uname -m将在某些Unix系统上给出“机器硬件名称”。 /bin/arch,如果存在,通常会给出处理器的类型。 不带参数的Uname将命名操作系统。
最终,你将不得不考虑平台之间的区别,以及你想把它们做得多好。例如,为了简单起见,我将i386到i686,任何“奔腾*”和任何“AMD*Athlon*”都视为x86。
我的~ /。profile在启动时运行一个a脚本,该脚本将一个变量设置为一个字符串,表示CPU和操作系统的组合。我有特定于平台的bin, man, lib,并包括基于此设置的目录。然后我设置了大量的环境变量。例如,重新格式化邮件的shell脚本可以调用$LIB/mailfmt,这是一个特定于平台的可执行二进制文件。
如果你想抄近路,uname -m和普通的uname会在很多平台上告诉你你想知道什么。当你需要的时候添加其他东西。(和用例,不嵌套if!)
我写了一个个人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有点慢,所以我实际上在脚本调用的系统上的一个文件中存储并更新了平台标识。这是我的框架,所以这对我来说是可行的,但你可能会有所不同。
现在,您必须找到一种方法将shtool打包到脚本中,但这并不难。您还可以总是使用uname输出。
编辑:
我错过了Teddy关于配置的帖子。猜(某种程度上)。这些脚本非常相似,但并不相同。我个人也将shtool用于其他用途,它对我来说工作得很好。
我建议避免回答这些问题。不要忘记,您可以选择其他形式的字符串比较,这将清除大多数变体或丑陋的代码。
其中一个解决方案是简单的检查,例如:
if [[ "$OSTYPE" =~ ^darwin ]]; then
它还有一个额外的好处,就是可以匹配任何版本的达尔文,尽管它有版本后缀。这也适用于任何版本的Linux。
你可以在我的dotfiles中看到一些额外的例子
我在.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"