Come rilevare il sistema operativo da uno script Bash?

Vorrei mantenere i miei file .bashrc e .bash_login nel controllo della versione in modo che io possa usarli tra tutti i computer che uso. Il problema è che ho alcuni alias specifici del sistema operativo, quindi stavo cercando un modo per determinare se lo script è in esecuzione su Mac OS X, Linux o Cygwin .

Qual è il modo corretto per rilevare il sistema operativo in uno script Bash ?

Per il mio .bashrc, utilizzo il seguente codice:

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

Allora faccio qualcosa come:

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

È brutto, ma funziona. Puoi usare case invece di if preferisci.

La manpage di bash dice che la variabile OSTYPE memorizza il nome del sistema operativo:

OSTYPE automaticamente su una stringa che descrive il sistema operativo su cui bash è in esecuzione. L’impostazione predefinita dipende dal sistema.

È impostato su linux-gnu qui.

Penso che il seguente dovrebbe funzionare. Non sono sicuro di win32 però.

 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 

Puoi semplicemente utilizzare la variabile $ OSTYPE predefinita, ad es .:

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

Un altro metodo è quello di rilevare la piattaforma in base al comando uname .

Vedi il seguente script (pronto per includere in .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 

Puoi trovare alcuni esempi pratici nel mio .bashrc .

Rilevare il sistema operativo e il tipo di CPU non è così facile da fare portabilmente . Ho uno sh script di circa 100 linee che funziona su una vasta gamma di piattaforms Unix: qualsiasi sistema che ho usato dal 1988.

Gli elementi chiave sono

  • uname -p è un tipo di processore, ma di solito è unknown sulle moderne piattaforms Unix.

  • uname -m darà il “nome hardware della macchina” su alcuni sistemi Unix.

  • /bin/arch , se esiste, di solito fornisce il tipo di processore.

  • uname senza argomenti chiamerà il sistema operativo.

Alla fine dovrai pensare alle distinzioni tra le piattaforms e a quanto bene vuoi farle. Ad esempio, per mantenere le cose semplici, considero i386 tramite i686 , qualsiasi ” Pentium* ” e qualsiasi ” AMD*Athlon* ” tutto come x86 .

Il mio ~/.profile esegue uno script all’avvio che imposta una variabile su una stringa che indica la combinazione di CPU e sistema operativo. include bin , man , lib e specifici della piattaforma e include directory che vengono impostate in base a ciò. Quindi ho impostato una barca di variabili d’ambiente. Ad esempio, uno script di shell per riformattare la posta può chiamare, ad esempio $LIB/mailfmt che è un eseguibile specifico della piattaforma.

Se vuoi tagliare gli angoli , uname -m e plain uname ti diranno cosa vuoi sapere su molte piattaforms. Aggiungi altre cose quando ne hai bisogno. (E usa il case , non annidato if !)

Raccomando di usare questo codice 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 

altri esempi di esempi qui: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

In bash, usa $OSTYPE e $HOSTTYPE , come documentato; questo è ciò che faccio. Se ciò non è sufficiente, e anche se uname o uname -a (o altre opzioni appropriate) non forniscono abbastanza informazioni, c’è sempre lo script config.guess dal progetto GNU, realizzato esattamente per questo scopo.

Prova a usare “uname”. Ad esempio, in Linux: “uname -a”.

Secondo la pagina di manuale, uname è conforms a SVr4 e POSIX, quindi dovrebbe essere disponibile anche su Mac OS X e Cygwin , ma non posso confermarlo.

BTW: $ OSTYPE è anche impostato su linux-gnu qui 🙂

Suggerirei di evitare alcune di queste risposte. Non dimenticare che puoi scegliere altre forms di confronto delle stringhe, che chiarirebbero la maggior parte delle varianti o il brutto codice offerto.

Una soluzione di questo tipo sarebbe un semplice controllo, come ad esempio:

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

Il che ha il vantaggio di abbinare qualsiasi versione di Darwin, nonostante sia il suffisso della versione. Questo funziona anche per tutte le varianti di Linux ci si potrebbe aspettare.

Puoi vedere alcuni esempi aggiuntivi all’interno dei miei dot qui

 uname 

o

 uname -a 

se vuoi maggiori informazioni

Ho scritto una libreria Bash personale e un framework di scripting che utilizza GNU shtool per eseguire un rilevamento della piattaforma piuttosto accurato.

GNU shtool è un set di script molto portabile che contiene, tra le altre cose utili, il comando ‘shtool platform’. Ecco l’output di:

 shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)" 

su alcune macchine diverse:

 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) 

Questo produce risultati abbastanza soddisfacenti, come puoi vedere. GNU shtool è un po ‘lento, quindi immagazzino e aggiorno l’identificazione della piattaforma in un file sul sistema che i miei script chiamano. È la mia struttura, quindi funziona per me, ma il tuo chilometraggio può variare.

Ora, dovrai trovare un modo per confezionare shtool con i tuoi script, ma non è un esercizio difficile. Puoi anche ricorrere all’output uname, anche.

MODIFICARE:

Ho perso il post di Teddy su config.guess (in qualche modo). Questi sono script molto simili, ma non uguali. Personalmente uso shtool anche per altri usi, e per me ha funzionato abbastanza bene.

Ho scritto questi zuccheri nel mio .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" ]]; } 

Quindi posso fare cose come:

 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" 

Questo dovrebbe essere sicuro da usare su tutte le distro.

 $ cat /etc/*release 

Questo produce qualcosa di simile.

  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/" 

Estrai / assegna alle variabili come desideri

Nota: in alcune configurazioni. Questo potrebbe anche darti degli errori che puoi ignorare.

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

Di seguito si tratta di un approccio per rilevare il SO Linux basato su Debian e RedHat facendo uso di / etc / lsb-release e / etc / os-release (a seconda dell’aspetto di Linux che si sta utilizzando) e adottare una semplice azione basata su di esso.

 #!/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 

Esempio di output per 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] ... 

È ansible utilizzare il seguente:

 OS=$(uname -s) 

allora puoi usare la variabile OS nel tuo script.

Facendo quanto segue è stato ansible eseguire correttamente il controllo per ubuntu:

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

Tendo a mantenere i miei .bashrc e .bash_alias su una condivisione file accessibile a tutte le piattaforms. In questo modo ho conquistato il problema nel mio .bash_alias:

 if [[ -f (name of share)/.bash_alias_$(uname) ]]; then . (name of share)/.bash_alias_$(uname) fi 

E ho ad esempio un .bash_alias_Linux con:

 alias ls='ls --color=auto' 

In questo modo tengo separato il codice specifico per piattaforma e portatile, puoi fare lo stesso per .bashrc

Puoi usare la seguente clausola if ed espanderla secondo necessità:

 if [ "${OSTYPE//[0-9.]/}" == "darwin" ] then aminute_ago="-v-1M" elif [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ] then aminute_ago="-d \"1 minute ago\"" fi 

Ho provato i messaggi sopra in alcune distribuzioni Linux e ho trovato quanto segue per funzionare al meglio per me. È una risposta breve, concisa e esatta che funziona anche per Bash su Windows.

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