Как определить ОС по сценарию Bash?
Я хотел бы сохранить файлы .bashrc
и .bash_login
в управлении версиями, чтобы я мог использовать их между всеми компьютерами, которые я использую. Проблема в том, что у меня есть некоторые специфичные для ОС псевдонимы, поэтому я искал способ определить, работает ли script на Mac OS X X Linux или Cygwin.
Каким образом можно определить операционную систему в Bash script?
Ответы
Ответ 1
Я думаю, что следующее должно работать. Я не уверен в 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
Ответ 2
Для моего .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
, если хотите.
Ответ 3
В справочной странице bash указано, что переменная OSTYPE хранит имя операционной системы:
OSTYPE
Автоматически устанавливает строку, описывающую операционную систему, на которой выполняется bash. По умолчанию используется системно- зависимыми.
Здесь установлено значение linux-gnu
.
Ответ 4
$OSTYPE
Вы можете просто использовать предопределенную переменную $OSTYPE
например:
case "$OSTYPE" in
solaris*) echo "SOLARIS" ;;
darwin*) echo "OSX" ;;
linux*) echo "LINUX" ;;
bsd*) echo "BSD" ;;
msys*) echo "WINDOWS" ;;
*) echo "unknown: $OSTYPE" ;;
esac
Однако он не распознается более ранними оболочками (такими как оболочка Борна).
Другой метод - обнаружение платформы по команде 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
Ответ 5
Обнаружение операционной системы и типа ЦП не так просто сделать портативно. У меня есть сценарий sh
около 100 строк, которые работают на очень широком спектре платформ Unix: любая система, которую я использовал с 1988 года.
Ключевыми элементами являются
-
uname -p
- это тип процессора, но обычно unknown
на современных платформах Unix.
-
uname -m
предоставит "имя аппаратного оборудования" в некоторых Unix-системах.
-
/bin/arch
, если он существует, обычно дает тип процессора.
-
uname
без аргументов будет называться операционной системой.
В конце концов вам придется подумать о различиях между платформами и о том, насколько вы хотите их отличить . Например, просто чтобы все было просто, я рассматриваю i386
через i686
, любой " Pentium*
" и любой " AMD*Athlon*
" как x86
.
Мой ~/.profile
запускает скрипт при запуске, который устанавливает одну переменную в строку, указывающую комбинацию процессора и операционной системы. У меня есть определенные для платформы файлы bin
, man
, lib
и include
которые устанавливаются на основе этого. Затем я установил лодку переменных окружения. Так, например, сценарий оболочки для переформатирования почты может вызывать, например, $LIB/mailfmt
который является исполняемым двоичным кодом для конкретной платформы.
Если вы хотите вырезать углы, uname -m
и plain uname
расскажут вам, что вы хотите знать на многих платформах. Добавьте другие материалы, когда вам это нужно. (И использовать case
, а не вложенный, if
!)
Ответ 6
Я рекомендую использовать этот полный 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
Ответ 7
В bash используйте $OSTYPE
и $HOSTTYPE
, как описано; вот что я делаю. Если этого недостаточно, и если даже uname
или uname -a
(или другие соответствующие параметры) не дают достаточной информации, всегда будет config.guess script из проекта GNU, сделанного именно для этой цели.
Ответ 8
Попробуйте использовать "uname". Например, в Linux: "uname -a".
Согласно странице руководства, uname соответствует SVr4 и POSIX, поэтому он должен быть доступен на Mac OS X и Cygwin тоже, но я не могу это подтвердить.
BTW: $OSTYPE также устанавливается на linux-gnu
здесь:)
Ответ 9
Я бы предложил избежать некоторых из этих ответов. Не забывайте, что вы можете выбрать другие формы сравнения строк, которые прояснят большинство вариантов или предлагаемый уродливый код.
Одним из таких решений будет простая проверка, например:
if [[ "$OSTYPE" =~ ^darwin ]]; then
У кого есть дополнительное преимущество при сопоставлении любой версии Дарвина, несмотря на его суффикс версии. Это также работает для любых вариантов Linux
, которые можно ожидать.
Вы можете увидеть некоторые дополнительные примеры в моих dotfiles здесь
Ответ 10
Я написал эти сахара в моем .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"
Ответ 11
uname
или
uname -a
если вы хотите получить дополнительную информацию
Ответ 12
Я написал личную библиотеку 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.
EDIT:
Я пропустил сообщение Тедди около config.guess
(так или иначе). Это очень похожие сценарии, но не то же самое. Я лично использую shtool для других целей, и он работает для меня хорошо.
Ответ 13
Вы можете использовать следующее:
OS=$(uname -s)
то вы можете использовать переменную ОС в script.
Ответ 14
Это должно быть безопасно для использования на всех дистрибутивах.
$ 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
Ответ 15
Ниже представлен подход к обнаружению 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
Пример вывода для Ubuntu Linux:
[email protected]$ 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]
...
Ответ 16
Вы можете использовать следующее условие 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
Ответ 17
Я стараюсь хранить мои .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
Ответ 18
Выполнение следующего помогло корректно выполнить проверку для ubuntu:
if [[ "$OSTYPE" =~ ^linux ]]; then
sudo apt-get install <some-package>
fi
Ответ 19
Я пробовал вышеуказанные сообщения на нескольких дистрибутивах Linux и нашел, что для меня лучше всего работать. Его короткий, сжатый точный ответ на слово, который работает и для Bash для Windows.
OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
Ответ 20
Это проверяет кучу known
файлов для идентификации, если дистрибутив linux - Debian или Ubunu, тогда по умолчанию используется переменная $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"
Ответ 21
попробуй это:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"