web-dev-qa-db-fra.com

Comment détecter le système d'exploitation à partir d'un script Bash?

Je souhaite conserver mes fichiers .bashrc et .bash_login dans le contrôle de version afin de pouvoir les utiliser sur tous les ordinateurs que j'utilise. Le problème est que j'ai des alias spécifiques à un système d'exploitation. Je cherchais donc un moyen de déterminer si le script s'exécutait sur Mac OS X, Linux ou Cygwin .

Quelle est la bonne façon de détecter le système d'exploitation dans un script Bash ?

396
csexton

Je pense que ce qui suit devrait fonctionner. Je ne suis cependant pas sûr 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
282
Timmmm

Pour mon .bashrc, j'utilise le code suivant:

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

Puis je fais des choses comme:

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

C'est moche, mais ça marche. Vous pouvez utiliser case au lieu de if si vous préférez.

279
Nicolas Martyanoff

La page de manuel bash indique que la variable OSTYPE stocke le nom du système d'exploitation:

OSTYPE Défini automatiquement sur une chaîne décrivant le système d'exploitation sur lequel bash s'exécute. La valeur par défaut est system - dépendant.

Il est défini sur linux-gnu ici.

264

Vous pouvez simplement utiliser une variable $ OSTYPE prédéfinie, à savoir:

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

Une autre méthode consiste à détecter une plateforme basée sur la commande uname.

Voir le script suivant (prêt à être inclus dans .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

Vous pouvez trouver quelques exemples pratiques dans mon .bashrc .

123
kenorb

Détecter le système d'exploitation et le type de CPU n'est pas si facile à faire de manière portable. J'ai un script sh d'environ 100 lignes qui fonctionne sur une très grande variété de plates-formes Unix: tous les systèmes que j'ai utilisés depuis 1988.

Les éléments clés sont

  • uname -p est type de processeur mais est généralement unknown sur les plates-formes Unix modernes.

  • uname -m donnera le "nom du matériel de la machine" sur certains systèmes Unix.

  • /bin/Arch, s'il existe, donnera généralement le type de processeur.

  • uname sans argument nommera le système d'exploitation.

Finalement, vous devrez réfléchir aux distinctions entre les plates-formes et à quel point vous voulez les améliorer. Par exemple, pour que les choses restent simples, je traite i386 à i686, tout "Pentium*" et tout "AMD*Athlon*", tous comme x86.

Mon ~/.profile exécute un script au démarrage qui définit une variable sur une chaîne indiquant la combinaison du processeur et du système d'exploitation. J'ai des répertoires bin, man, lib et include spécifiques à la plate-forme qui sont configurés en fonction de cela. Ensuite, je définis un bateau de variables d’environnement. Ainsi, par exemple, un script Shell pour reformater un courrier peut appeler, par exemple, $LIB/mailfmt, qui est un binaire exécutable spécifique à la plate-forme.

Si vous voulez prendre des raccourcis , uname -m et tout simplement uname vous dira ce que vous voulez savoir sur de nombreuses plateformes. Ajoutez d'autres choses quand vous en avez besoin. (Et utilisez case, pas imbriqué if!)

34
Norman Ramsey

Je recommande d'utiliser ce code bash complet

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

plus d'exemples exemples ici: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

30
coto

Dans bash, utilisez $OSTYPE et $HOSTTYPE, comme indiqué; c'est ce que je fais. Si cela ne suffit pas, et si même uname ou uname -a (ou d’autres options appropriées) ne donne pas assez d’informations, il ya toujours le script config.guess du projet GNU, créé exactement à cette fin.

9
Teddy

Je suggérerais d'éviter certaines de ces réponses. N'oubliez pas que vous pouvez choisir d'autres formes de comparaison de chaînes, qui effaceraient la plupart des variations ou le code laid proposé.

Une telle solution serait un simple contrôle, tel que:

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

Ce qui présente l’avantage supplémentaire de faire correspondre toute version de Darwin, malgré son suffixe de version. Cela fonctionne également pour toutes les variations de Linux auxquelles on peut s'attendre.

Vous pouvez voir quelques exemples supplémentaires dans mes fichiers de points ici

8
Akiva

Essayez d'utiliser "uname". Par exemple, sous Linux: "uname -a".

Selon la page de manuel, uname est conforme à SVr4 et POSIX, il devrait donc être disponible sur Mac OS X et Cygwin aussi, mais je ne peux pas le confirmer.

BTW: $ OSTYPE est également défini sur linux-gnu ici :)

8
Joao da Silva

J'ai écrit ces sucres dans mon .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" ]];
}

Donc, je peux faire des choses comme:

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"
7
kfix
uname

ou 

uname -a

si vous voulez plus d'informations

6
Federico A. Ramponi

J'ai écrit une bibliothèque Bash personnelle et un framework de script qui utilise GNU shtool pour effectuer une détection de plateforme plutôt précise.

GNU shtool est un ensemble de scripts très portable qui contient, entre autres choses utiles, la commande 'shtool platform'. Voici le résultat de:

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

sur quelques machines différentes:

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)

Cela donne des résultats assez satisfaisants, comme vous pouvez le constater. GNU shtool est un peu lent, je stocke donc et mets à jour l'identification de la plate-forme dans un fichier sur le système appelé par mes scripts. C'est mon cadre, donc cela fonctionne pour moi, mais votre kilométrage peut varier.

Maintenant, vous devrez trouver un moyen d’empaqueter shtool avec vos scripts, mais ce n’est pas un exercice difficile. Vous pouvez également toujours utiliser la sortie uname.

MODIFIER:

J'ai raté le message de Teddy à propos de config.guess (en quelque sorte). Ce sont des scripts très similaires, mais pas les mêmes. Personnellement, j'utilise shtool pour d'autres usages également, et cela fonctionne assez bien pour moi.

6
guns

Cela devrait être sûr d'utiliser sur toutes les distributions.

$ cat /etc/*release

Cela produit quelque chose comme ça.

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

Extraire/assigner aux variables comme bon vous semble

Remarque: sur certaines configurations. Cela peut aussi vous donner des erreurs que vous pouvez ignorer.

     cat: /etc/upstream-release: Is a directory
5
R J

Vous pouvez utiliser les éléments suivants:

OS=$(uname -s)

alors vous pouvez utiliser la variable de système d'exploitation dans votre script.

5
Chetan kapoor

Ci-dessous, une approche pour détecter les systèmes Debian et RedHat Linux OS en utilisant le/ etc/lsb-releaseet/ etc/os-release( en fonction de la version de Linux que vous utilisez) et effectuez une action simple en fonction de celle-ci. 

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

Exemple de sortie pour 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] 
...            
3
Exequiel Rafaela

Vous pouvez utiliser la clause suivante if et la développer au besoin:

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

2
Tahsin Turkoz

J'ai tendance à conserver mes fichiers .bashrc et .bash_alias sur un partage de fichiers auquel toutes les plates-formes peuvent accéder. Voici comment j'ai vaincu le problème dans mon .bash_alias:

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

Et j'ai par exemple un .bash_alias_Linux avec:

alias ls='ls --color=auto'

De cette façon, je garde le code spécifique à la plate-forme et au code portable séparé, vous pouvez faire de même pour .bashrc

1
ericcurtin

Effectuer les opérations suivantes a permis d’effectuer correctement la vérification pour Ubuntu:

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

Ceci vérifie un groupe de fichiers known pour identifier si la distribution linux est Debian ou Ubunu, puis la valeur par défaut est 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"
0
Kuzeko

J’ai essayé les messages ci-dessus sur plusieurs distributions Linux et j’ai trouvé ce qui suit le mieux pour moi. C’est une réponse exacte et concise de Word qui fonctionne également pour Bash sous Windows.

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

essaye ça:

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