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?

¿Fue útil?

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 normalmente unknown 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"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top