J'ai un script Shell utilisé à la fois sous Windows/Cygwin, Mac et Linux. Il a besoin de variables légèrement différentes pour chaque version.
Comment un script Shell/bash peut-il détecter s’il s’exécute dans Cygwin, sur un Mac ou sous Linux?
Habituellement, uname
avec ses différentes options vous indiquera dans quel environnement vous vous trouvez:
pax> uname -a
CYGWIN_NT-5.1 IBM-L3F3936 1.5.25(0.156/4/2) 2008-06-12 19:34 i686 Cygwin
pax> uname -s
CYGWIN_NT-5.1
Et, selon le très utile schot
(dans les commentaires), uname -s
donne Darwin
pour OSX et Linux
pour Linux, tandis que mon Cygwin donne CYGWIN_NT-5.1
. Mais vous devrez peut-être expérimenter avec toutes sortes de versions différentes.
Ainsi, le code bash
permettant d'effectuer une telle vérification serait le suivant:
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) machine=Linux;;
Darwin*) machine=Mac;;
CYGWIN*) machine=Cygwin;;
MINGW*) machine=MinGw;;
*) machine="UNKNOWN:${unameOut}"
esac
echo ${machine}
Notez que je suppose ici que vous utilisez réellement dans CygWin (le bash
shell de celui-ci), donc les chemins doivent déjà être correctement installer. Comme l’a noté un intervenant, vous pouvez exécuter le programme bash
en transmettant le script à partir de cmd
lui-même, ce qui peut avoir pour conséquence que les chemins ne sont pas configurés comme il convient.
Si vous le faites , il vous incombe de vous assurer que les exécutables corrects (c'est-à-dire ceux de CygWin) sont appelés, éventuellement en modifiant le chemin au préalable ou en spécifiant complètement les emplacements des exécutables (par exemple, /c/cygwin/bin/uname
).
#!/usr/bin/env bash
au lieu de #!/bin/sh
pour éviter le problème causé par /bin/sh
lié à un autre shell par défaut sur différentes plates-formes, sinon une erreur du type opérateur inattendu , c'est ce qui s'est passé sur mon ordinateur (Ubuntu 64 bits 12.04).expr
à moins que vous ne l'installiez. J'utilise donc uname
.uname
pour obtenir les informations système (paramètre -s
).expr
et substr
pour gérer la chaîne.if
Elif
fi
pour effectuer le travail correspondant.uname -s
.#!/usr/bin/env bash
if [ "$(uname)" == "Darwin" ]; then
# Do something under Mac OS X platform
Elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
# Do something under GNU/Linux platform
Elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
# Do something under 32 bits Windows NT platform
Elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
# Do something under 64 bits Windows NT platform
fi
Utilisez uname -s
(_--kernel-name
_) car uname -o
(_--operating-system
_) n'est pas pris en charge sur certains systèmes d'exploitation en tant que Mac OS , Solaris . Vous pouvez également utiliser simplement uname
sans argument , car l'argument par défaut est _-s
_ (_--kernel-name
_).
L’extrait de code ci-dessous ne nécessite pas bash (c’est-à-dire qu’il n’est pas nécessaire que _#!/bin/bash
_)
_#!/bin/sh
case "$(uname -s)" in
Darwin)
echo 'Mac OS X'
;;
Linux)
echo 'Linux'
;;
CYGWIN*|MINGW32*|MSYS*)
echo 'MS Windows'
;;
# Add here more strings to compare
# See correspondence table at the bottom of this answer
*)
echo 'other OS'
;;
esac
_
Le Makefile
ci-dessous est inspiré de projet Git (_config.mak.uname
_) .
_ifdef MSVC # Avoid the MingW/Cygwin sections
uname_S := Windows
else # If uname not available => 'not'
uname_S := $(Shell sh -c 'uname -s 2>/dev/null || echo not')
endif
# Avoid nesting "if .. else if .. else .. endif endif"
# because maintenance of matching if/else/endif is a pain
ifeq ($(uname_S),Windows)
CC := cl
endif
ifeq ($(uname_S),OSF1)
CFLAGS += -D_OSF_SOURCE
endif
ifeq ($(uname_S),Linux)
CFLAGS += -DNDEBUG
endif
ifeq ($(uname_S),GNU/kFreeBSD)
CFLAGS += -D_BSD_ALLOC
endif
ifeq ($(uname_S),UnixWare)
CFLAGS += -Wextra
endif
...
_
Voir aussi cette réponse complète à propos de _uname -s
_ et Makefile
.
Le tableau de correspondance au bas de cette réponse provient de article de Wikipedia sur uname
. Merci de contribuer à le garder à jour (éditer la réponse ou poster un commentaire). Vous pouvez également mettre à jour l'article Wikipedia et poster un commentaire pour me signaler votre contribution ;-)
Operating System
uname -s
_Mac OS X
_Darwin
Cygwin 32-bit (Win-XP)
_CYGWIN_NT-5.1
_Cygwin 32-bit (Win-7 32-bit)
_CYGWIN_NT-6.1
_Cygwin 32-bit (Win-7 64-bit)
_CYGWIN_NT-6.1-WOW64
_Cygwin 64-bit (Win-7 64-bit)
_CYGWIN_NT-6.1
_MinGW (Windows 7 32-bit)
_MINGW32_NT-6.1
_MinGW (Windows 10 64-bit)
_MINGW64_NT-10.0
_Interix (Services for UNIX)
Interix
MSYS
_MSYS_NT-6.1
__Windows Subsystem for Linux
_Linux
Android
Linux
coreutils
Linux
CentOS
Linux
Fedora
Linux
Gentoo
Linux
_Red Hat Linux
_Linux
_Linux Mint
_Linux
openSUSE
Linux
Ubuntu
Linux
_Unity Linux
_Linux
_Manjaro Linux
_Linux
_OpenWRT r40420
_Linux
Debian (Linux)
Linux
Debian (GNU Hurd)
GNU
Debian (kFreeBSD)
_GNU/kFreeBSD
_FreeBSD
FreeBSD
NetBSD
NetBSD
DragonFlyBSD
DragonFly
Haiku
Haiku
NonStop
_NONSTOP_KERNEL
_QNX
QNX
ReliantUNIX
_ReliantUNIX-Y
_SINIX
_SINIX-Y
_
_Tru64
__OSF1
_Ultrix
ULTRIX
_IRIX 32 bits
_IRIX
_IRIX 64 bits
__IRIX64
_MINIX
Minix
Solaris
SunOS
UWIN (64-bit Windows 7)
_UWIN-W7
_
_SYS$UNIX:SH on OpenVMS
__IS/WB
_
_z/OS USS
__OS/390
_Cray
_sn5176
_
_(SCO) OpenServer
__SCO_SV
_
_(SCO) System V
__SCO_SV
_
_(SCO) UnixWare
_UnixWare
_IBM AIX
_AIX
_IBM i with QSH
__OS400
_
_HP-UX
__HP-UX
_
Bash définit la variable Shell OSTYPE. De man bash
:
Défini automatiquement sur une chaîne décrivant le système d'exploitation sur lequel bash s'exécute.
Cela présente un avantage minime par rapport à uname
en ce sens qu'il ne nécessite pas le lancement d'un nouveau processus, il sera donc plus rapide à exécuter.
Cependant, je ne parviens pas à trouver une liste de valeurs attendues faisant autorité. Pour moi sur Ubuntu 14.04, il est réglé sur 'linux-gnu'. J'ai parcouru le Web pour d'autres valeurs. Par conséquent:
_case "$OSTYPE" in
linux*) echo "Linux / WSL" ;;
darwin*) echo "Mac OS" ;;
win*) echo "Windows" ;;
msys*) echo "MSYS / MinGW / Git Bash" ;;
cygwin*) echo "Cygwin" ;;
bsd*) echo "BSD" ;;
solaris*) echo "Solaris" ;;
*) echo "unknown: $OSTYPE" ;;
esac
_
Les astérisques sont importants dans certains cas - par exemple, OSX ajoute un numéro de version du système d'exploitation après "darwin". La valeur 'win' est en réalité 'win32', m'a-t-on dit - peut-être existe-t-il un 'win64'?
Peut-être pourrions-nous travailler ensemble pour remplir un tableau de valeurs vérifiées ici:
linux-gnu
_cygwin
msys
(Veuillez ajouter votre valeur si elle diffère des entrées existantes)
Pour compléter la réponse d'Albert, j'aime bien utiliser $COMSPEC
pour détecter Windows:
#!/bin/bash
if [ "$(uname)" == "Darwin" ]
then
echo Do something under Mac OS X platform
Elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]
then
echo Do something under Linux platform
Elif [ -n "$COMSPEC" -a -x "$COMSPEC" ]
then
echo $0: this script does not support Windows \:\(
fi
Cela évite d'analyser les variantes de noms Windows pour $OS
, et d'analyser les variantes de uname
comme MINGW, Cygwin, etc.
Background: %COMSPEC%
est une variable d’environnement Windows spécifiant le chemin complet du processeur de commande (alias le shell Windows). La valeur de cette variable est généralement %SystemRoot%\system32\cmd.exe
, qui est généralement évaluée à C:\Windows\system32\cmd.exe
.
# This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
echo Cygwin rulez
else
echo Unix is king
fi
Si les 6 premiers caractères de la commande uname -s sont "CYGWIN", un système cygwin est supposé
http://en.wikipedia.org/wiki/Uname
Toutes les informations dont vous aurez besoin Google est ton ami.
Utilisez uname -s
pour interroger le nom du système.
Darwin
CYGWIN_...
LINUX
pour la plupartOk, voici mon chemin.
osis()
{
local n=0
if [[ "$1" = "-n" ]]; then n=1;shift; fi
# echo $OS|grep $1 -i >/dev/null
uname -s |grep -i "$1" >/dev/null
return $(( $n ^ $? ))
}
par exemple.
osis Darwin &&
{
log_debug Detect mac osx
}
osis Linux &&
{
log_debug Detect linux
}
osis -n Cygwin &&
{
log_debug Not Cygwin
}
J'utilise ceci dans mon dotfiles
Le sous-système Windows pour Linux n’existait pas lorsque cette question a été posée. Il a donné ces résultats dans mon test:
uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft
Cela signifie que vous avez besoin de uname -r pour le distinguer de Linux natif.
Je suppose que la réponse uname est imbattable, principalement en termes de propreté.
Bien que cela prenne un temps ridicule à exécuter, j’ai constaté que le fait de tester la présence de fichiers spécifiques me donnait également de bons résultats plus rapidement, car je n’appelais pas d’exécutable:
Alors,
[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running
utilise simplement une vérification rapide de la présence du fichier Bash. Étant donné que je suis sous Windows en ce moment, je ne peux vous dire aucun fichier spécifique pour Linux et Mac OS X, mais je suis à peu près sûr qu’ils existent. :-)