web-dev-qa-db-fra.com

Comment vérifier si vous utilisez Cygwin, Mac ou Linux?

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?

284
bastibe

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).

256
paxdiablo

Voici le script bash que j'ai utilisé pour détecter trois types de système d'exploitation différents (GNU/Linux, Mac OS X, Windows NT)

Faites attention

  • Dans votre script bash, utilisez #!/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).
  • Mac OS X 10.6.8 (Snow Leopard) ne dispose pas du programme expr à moins que vous ne l'installiez. J'utilise donc uname.

Conception

  1. Utilisez uname pour obtenir les informations système (paramètre -s).
  2. Utilisez expr et substr pour gérer la chaîne.
  3. Utilisez ifEliffi pour effectuer le travail correspondant.
  4. Vous pouvez ajouter davantage de support système si vous le souhaitez, suivez simplement la spécification uname -s.

La mise en oeuvre

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

Essai

  • Linux (Ubuntu 12.04 LTS, Kernel 3.2.0) testé correctement.
  • OS X (10.6.8 Snow Leopard) testé correctement.
  • Windows (Windows 7 64 bits) testé OK.

Ce que j'ai appris

  1. Vérifiez les citations d'ouverture et de fermeture.
  2. Recherchez les parenthèses et les accolades manquantes {}

Références

294
Albert

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 Systemuname -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)InterixMSYS_MSYS_NT-6.1__Windows Subsystem for Linux_Linux
AndroidLinux
coreutilsLinux
CentOSLinux
FedoraLinux
GentooLinux
_Red Hat Linux_Linux
_Linux Mint_Linux
openSUSELinux
UbuntuLinux
_Unity Linux_Linux
_Manjaro Linux_Linux
_OpenWRT r40420_Linux
Debian (Linux)Linux
Debian (GNU Hurd)GNU
Debian (kFreeBSD)_GNU/kFreeBSD_
FreeBSDFreeBSD
NetBSDNetBSD
DragonFlyBSDDragonFly
HaikuHaiku
NonStop_NONSTOP_KERNEL_
QNXQNX
ReliantUNIX_ReliantUNIX-Y_
SINIX_SINIX-Y_
_Tru64__OSF1_
UltrixULTRIX
_IRIX 32 bits_IRIX
_IRIX 64 bits__IRIX64_
MINIXMinix
SolarisSunOS
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_

103
olibre

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 Ubuntu (inclus WSL ): _linux-gnu_
  • Cygwin 64 bits: cygwin
  • Msys/MINGW (Git Bash pour Windows): msys

(Veuillez ajouter votre valeur si elle diffère des entrées existantes)

61
Jonathan Hartley

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.

8
Steve Jansen
# 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é

8
Jan Helge

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.

  • Mac: Darwin
  • Cygwin: CYGWIN_...
  • Linux: divers, LINUX pour la plupart
3
rubenvb

Ok, 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

1
wener

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.

0
A Fog

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. :-)

0