tutorial scripts script resueltos español ejercicios ejemplos bash os-detection

bash - español - scripts linux ejercicios resueltos



¿Cómo detectar el sistema operativo desde un script Bash? (21)

Me gustaría mantener mis archivos .bashrc y .bash_login 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 script de Bash ?


A continuación se muestra un enfoque para detectar el sistema operativo Linux basado en Debian y RedHat haciendo uso de la versión / etc / lsb-release y / etc / os (según el tipo de Linux que esté usando) y realice una acción simple basada en ella.

#!/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 para 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] ...


Creo que lo siguiente debería funcionar. Aunque no estoy seguro de 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


Detectar el sistema operativo y el tipo de CPU no es tan fácil de hacer de manera portátil . Tengo un script sh de aproximadamente 100 líneas que funciona en una gran variedad de plataformas Unix: cualquier sistema que haya usado desde 1988.

Los elementos clave son

  • uname -p es un tipo de procesador, pero generalmente es unknown en las plataformas Unix modernas.

  • uname -m le dará el "nombre del hardware de la máquina" en algunos sistemas Unix.

  • /bin/arch , si existe, generalmente dará el tipo de procesador.

  • uname sin argumentos nombrará el sistema operativo.

Eventualmente, tendrá que pensar en las distinciones entre plataformas y qué tan bien desea hacerlas. Por ejemplo, solo para mantener las cosas simples, trato de i386 a i686 , cualquier " Pentium* " y cualquier " AMD*Athlon* " como x86 .

Mi ~/.profile Ejecuta un script al inicio que establece una variable en una cadena que indica la combinación de CPU y sistema operativo. Tengo directorios específicos de plataforma, man , lib e include directorios que se configuran en función de eso. Luego configuro un barco cargado de variables de entorno. Por ejemplo, un script de shell para reformatear el correo puede llamar, por ejemplo, $LIB/mailfmt que es un binario ejecutable específico de la plataforma.

Si desea cortar esquinas , uname -m y plain uname le dirán lo que desea saber en muchas plataformas. Agrega otras cosas cuando las necesites. (Y case uso, no anidado if !)


En bash, use $OSTYPE y $HOSTTYPE , como se documenta; esto es lo que hago. Si eso no es suficiente, y si incluso uname o uname -a (u otras opciones apropiadas) no brindan suficiente información, siempre config.guess script config.guess del proyecto GNU, hecho exactamente para este propósito.


Escribí una biblioteca Bash personal y un marco de scripting que utiliza shtool de GNU para hacer una detección de plataforma bastante precisa.

GNU shtool es un conjunto de scripts muy portátil 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 unas pocas 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 bastante satisfactorios, como se puede ver. GNU shtool es un poco lento, por lo que realmente almaceno y actualizo la identificación de la plataforma en un archivo en el sistema al que llaman mis scripts. Es mi marco, por lo que funciona para mí, pero su kilometraje puede variar.

Ahora, tendrás que encontrar una manera de empaquetar shtool con tus scripts, pero no es un ejercicio difícil. Siempre puedes recurrir a la salida uname, también.

EDITAR:

Me perdí la publicación de Teddy sobre config.guess (de alguna manera). Estos son scripts muy similares, pero no iguales. Personalmente uso shtool también para otros usos, y me ha funcionado bastante bien.


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"


Esto debería ser seguro para 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/"

Extraer / asignar a las variables como desee

Nota: En algunas configuraciones. Esto también puede darte algunos errores que puedes ignorar.

cat: /etc/upstream-release: Is a directory


Esto verifica un montón de archivos known para identificar si la distribución de Linux es Debian o Ubunu, y por defecto es 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"


Hacer lo siguiente ayudó a realizar la comprobación correctamente para ubuntu:

if [[ "$OSTYPE" =~ ^linux ]]; then sudo apt-get install <some-package> fi


La página de manual de bash dice que la variable OSTYPE almacena el nombre del sistema operativo:

OSTYPE Establece automáticamente una cadena que describe el sistema operativo en el que se está ejecutando bash. El valor predeterminado es dependiente del sistema.

Se establece en linux-gnu aquí.


Para mi .bashrc, uso el siguiente código:

platform=''unknown'' unamestr=`uname` if [[ "$unamestr" == ''Linux'' ]]; then platform=''linux'' elif [[ "$unamestr" == ''FreeBSD'' ]]; then platform=''freebsd'' fi

Entonces hago cosas como:

if [[ $platform == ''linux'' ]]; then alias ls=''ls --color=auto'' elif [[ $platform == ''freebsd'' ]]; then alias ls=''ls -G'' fi

Es feo, pero funciona. Puede utilizar el case lugar de si lo prefiere.


Probé los mensajes anteriores en algunas distribuciones de Linux y encontré que lo siguiente funciona mejor para mí. Es una respuesta de palabra exacta, breve y concisa que también funciona para Bash en Windows.

OS=$(cat /etc/*release | grep ^NAME | tr -d ''NAME="'') #$ echo $OS # Ubuntu


Puede usar la siguiente cláusula if y expandirla 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


Puedes usar lo siguiente:

OS=$(uname -s)

entonces puedes usar la variable OS en tu script.


Recomiendo usar este completo código 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

más ejemplos de ejemplos aquí: https://github.com/coto/server-easy-install/blob/master/lib/core.sh


Simplemente puede usar la variable $ OSTYPE predefinida, es decir:

case "$OSTYPE" in solaris*) echo "SOLARIS" ;; darwin*) echo "OSX" ;; linux*) echo "LINUX" ;; bsd*) echo "BSD" ;; msys*) echo "WINDOWS" ;; *) echo "unknown: $OSTYPE" ;; esac

Otro método es detectar la plataforma basada en el comando uname .

Vea el siguiente script (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

Puedes encontrar algún ejemplo práctico en mi .bashrc .


Tiendo a mantener mis archivos .bashrc y .bash_alias en un recurso compartido de archivos al que pueden acceder todas las plataformas. Así es como 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 un .bash_alias_Linux con:

alias ls=''ls --color=auto''

De esta manera mantengo el código de la plataforma específica y el código portátil por separado, puede hacer lo mismo para .bashrc


Trate de usar "uname". Por ejemplo, en Linux: "uname -a".

De acuerdo con la página del manual, uname cumple con SVr4 y POSIX, por lo que también debería estar disponible en Mac OS X y Cygwin , pero no puedo confirmarlo.

BTW: $ OSTYPE también se establece en linux-gnu aquí :)


Yo sugeriría evitar algunas de estas respuestas. No olvide que puede elegir otras formas de comparación de cadenas, que aclararían la mayoría de las variaciones, o el código feo ofrecido.

Una de esas soluciones sería una simple comprobación, como:

if [[ "$OSTYPE" =~ ^darwin ]]; then

Lo que tiene el beneficio adicional de hacer coincidir cualquier versión de Darwin, a pesar de su sufijo. Esto también funciona para cualquier variación de Linux uno pueda esperar.

Puedes ver algunos ejemplos adicionales dentro de mis dotfiles here


prueba esto:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d ''"'') echo "Determined platform: $DISTRO"


uname

o

uname -a

si quieres mas informacion