¿Cómo detectar el sistema operativo desde un script Bash?
-
23-08-2019 - |
Pregunta
Me gustaría conservar mi .bashrc
y .bash_login
archivos en el control de versiones para poder usarlos entre todas las computadoras que uso.El problema es que tengo algunos alias específicos del sistema operativo, así que estaba buscando una manera de determinar si el script se ejecuta en Mac OS X, Linux o Cygwin.
¿Cuál es la forma correcta de detectar el sistema operativo en un Intento ¿guion?
Solución
Creo que el siguiente debería funcionar. No estoy seguro acerca de win32
sin embargo.
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
Otros consejos
Para mi .bashrc, utilizo el código siguiente:
platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
platform='freebsd'
fi
A continuación, hago algunas cosas como:
if [[ $platform == 'linux' ]]; then
alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
alias ls='ls -G'
fi
Es feo, pero funciona. Es posible utilizar en lugar de case
if
si lo prefiere.
La página de manual de bash dice que el OSTYPE variable almacena el nombre del sistema operativo:
OSTYPE
Puesto automáticamente a una cadena que describe el sistema operativo en el que bash se está ejecutando. El valor predeterminado es sistema- dependiente.
Se establece en linux-gnu
aquí.
$OSTYPE
Usted puede simplemente utilizar predefinido variable de $OSTYPE
por ejemplo:.
case "$OSTYPE" in
solaris*) echo "SOLARIS" ;;
darwin*) echo "OSX" ;;
linux*) echo "LINUX" ;;
bsd*) echo "BSD" ;;
msys*) echo "WINDOWS" ;;
*) echo "unknown: $OSTYPE" ;;
esac
Sin embargo, es no reconocida por las conchas más antiguas (como Bourne shell ).
uname
Otro método consiste en detectar plataforma basada en el comando uname
.
Vea la siguiente secuencia de comandos (listo para incluir en .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
Puede encontrar algún ejemplo práctico en mi .bashrc
.
Aquí es versión similar utilizado en 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
Detección sistema operativo y el tipo de CPU no es tan fácil de hacer portable . Tengo un script sh
de alrededor de 100 líneas que funciona a través de una amplia variedad de plataformas Unix: cualquier sistema que he utilizado desde 1988
Los elementos clave son
-
uname -p
es tipo de procesador pero se encuentra normalmenteunknown
en plataformas Unix modernos. -
uname -m
dará el "nombre de hardware de la máquina" en algunos sistemas Unix. -
/bin/arch
, si es que existe, por lo general dará el tipo de procesador. -
uname
sin argumentos nombrará el sistema operativo.
Finalmente se tiene que pensar en las diferencias entre plataformas y lo bien que quieres que sean. Por ejemplo, sólo para mantener las cosas simples, trato i386
través i686
, cualquier "Pentium*
" y cualquier "AMD*Athlon*
" todos como x86
.
Mi ~/.profile
ejecuta un guión en el arranque que establece una variable de una cadena que indica la combinación de CPU y el sistema operativo. Tengo directorios bin
, man
, lib
y include
específicas de la plataforma que ponerse en marcha en base a eso. Entonces me puse un bote lleno de variables de entorno. Así, por ejemplo, una secuencia de comandos shell volver a formatear correo puede llamar, por ejemplo, $LIB/mailfmt
que es un binario ejecutable específico de la plataforma.
Si desea cortar esquinas , uname -m
y uname
llanura le dirá lo que usted quiere saber en muchas plataformas. Añadir otras cosas cuando lo necesite. (Y el uso case
, no anidado if
!)
Recomiendo usar este código bash completo.
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
más ejemplos ejemplos aquí: https://github.com/coto/server-easy-install/blob/master/lib/core.sh
En bash, uso $OSTYPE
y $HOSTTYPE
, tal como se documenta; esto es lo que hago. Si eso no es suficiente, y si aun uname
o uname -a
(u otras opciones adecuadas) no da suficiente información, siempre existe el guión config.guess del proyecto GNU, hecha exactamente para este fin
Trate de usar "uname". Por ejemplo, en Linux:. "Uname -a"
De acuerdo con la página del manual, uname se ajusta a SVr4 y POSIX, por lo que debe estar disponible en Mac OS X y Cygwin también, pero no puedo confirmar que.
Por cierto: $ OSTYPE también está listo para linux-gnu
aquí:)
Yo sugeriría evitando algunas de estas respuestas. No olvide que usted puede elegir otras formas de comparación de cadenas, lo que aclararía la mayor parte de las variaciones, o código feo ofrecido.
Una de estas soluciones sería una sencilla comprobación, tales como:
if [[ "$OSTYPE" =~ ^darwin ]]; then
¿Qué tiene el beneficio adicional de hacer coincidir cualquier versión de Darwin, a pesar de que es sufijo de versión. Esto también funciona para cualquier variación de Linux
uno puede esperar.
Puede ver algunos ejemplos adicionales dentro de mi dotfiles aquí
escribí estos azúcares en mi .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" ]];
}
Así que puedo hacer cosas como:
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"
uname
o
uname -a
si desea obtener más información
una biblioteca personal y Bash scripting marco que utiliza GNU shtool para hacer una detección de la plataforma en lugar preciso.
shtool GNU es un conjunto muy portable de secuencias de comandos que contiene, entre otras cosas útiles, el comando 'plataforma shtool'. Aquí está la salida de:
shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"
en algunas máquinas diferentes:
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)
Esto produce resultados muy satisfactorios, como se puede ver. shtool GNU es un poco lento, lo que en realidad almacenar y actualizar la identificación plataforma en un archivo en el sistema que llaman mis guiones. Es mi marco, por lo que funciona para mí, pero su experiencia puede variar.
Ahora, usted tiene que encontrar una manera de empaquetar shtool con las secuencias de comandos, pero no es un ejercicio difícil. Siempre se puede recurrir a la salida de uname, también.
EDIT:
Me perdí el mensaje por Teddy sobre config.guess
(de alguna manera). Estos son los scripts muy similares, pero no iguales. Yo personalmente uso shtool para otros usos, así, y que ha estado trabajando muy bien para mí.
Puede utilizar lo siguiente:
OS=$(uname -s)
A continuación, puede utilizar la variable del sistema operativo en el script.
Esto debería ser seguro de usar en todas las distribuciones.
$ cat /etc/*release
Esto produce algo como esto.
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/"
Extracto / remisión a las variables como desee
Nota: En algunas configuraciones. Esto también le puede dar algunos errores que puede pasar por alto.
cat: /etc/upstream-release: Is a directory
A continuación se trata de un planteamiento para detectar Debian y RedHat basada sistema operativo Linux haciendo uso de la / etc / lsb-release y / etc / os de liberación (dependiendo del sabor de Linux que está usando) y tomar una acción simple basado en él.
#!/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
Ejemplo de salida 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]
...
Puede utilizar la cláusula siguiente si y ampliar según sea necesario:
if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
aminute_ago="-v-1M"
elif [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
aminute_ago="-d \"1 minute ago\""
fi
tiendo a mantener mi .bashrc y .bash_alias en un recurso compartido de archivos que todas las plataformas puedan acceder. Así es como yo conquisto el problema en mis .bash_alias:
if [[ -f (name of share)/.bash_alias_$(uname) ]]; then
. (name of share)/.bash_alias_$(uname)
fi
Y tengo por ejemplo una .bash_alias_Linux con:
alias ls='ls --color=auto'
De esta manera sigo plataforma específica y el código portátil independiente, se puede hacer lo mismo para Bashrc
Hacer lo siguiente ayudó a realizar la comprobación correctamente para ubuntu:
if [[ "$OSTYPE" =~ ^linux ]]; then
sudo apt-get install <some-package>
fi
Probé los mensajes anteriores a través de un par de distribuciones de Linux y encontré lo siguiente para trabajar mejor para mí. Es un corto concisa respuesta, palabra exacta que funcione para Bash en Windows también.
OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
Esto comprueba un montón de archivos known
a identfy si la distribución de Linux es Debian o Ubunu, a continuación, el valor predeterminado a la variable $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"
intente lo siguiente:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"