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 ?
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
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.
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.
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
.
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
!)
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
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.
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
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 :)
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"
uname
ou
uname -a
si vous voulez plus d'informations
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.
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
Vous pouvez utiliser les éléments suivants:
OS=$(uname -s)
alors vous pouvez utiliser la variable de système d'exploitation dans votre script.
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]
...
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
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
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
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"
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
essaye ça:
DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"