¿Cómo comprobar si se está ejecutando en Cygwin, Mac o Linux?

Resuelto bastibe asked hace 14 años • 10 respuestas

Tengo un script de shell que se usa tanto en Windows/Cygwin como en Mac y Linux. Necesita variables ligeramente diferentes para cada versión.

¿Cómo puede un script Shell/bash detectar si se está ejecutando en Cygwin, en una Mac o en Linux?

bastibe avatar Aug 12 '10 16:08 bastibe
Aceptado

Por lo general, unamecon sus diversas opciones te indicará en qué entorno estás ejecutando:

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

Y, según lo muy útil schot(en los comentarios), uname -sda Darwinpara OSX y Linuxpara Linux, mientras que mi Cygwin da CYGWIN_NT-5.1. Pero es posible que tengas que experimentar con todo tipo de versiones diferentes.

Entonces, el bashcódigo para realizar dicha verificación sería similar a:

unameOut="$(uname -s)"
case "${unameOut}" in
    Linux*)     machine=Linux;;
    Darwin*)    machine=Mac;;
    CYGWIN*)    machine=Cygwin;;
    MINGW*)     machine=MinGw;;
    MSYS_NT*)   machine=Git;;
    *)          machine="UNKNOWN:${unameOut}"
esac
echo ${machine}

Tenga en cuenta que asumo aquí que en realidad está ejecutando CygWin ( bashsu shell), por lo que las rutas ya deberían estar configuradas correctamente. Como señala un comentarista, puede ejecutar el bashprograma, pasando el script, desde cmdsí mismo y esto puede provocar que las rutas no se configuren según sea necesario.

Si está haciendo eso, es su responsabilidad asegurarse de que se llamen los ejecutables correctos (es decir, los de CygWin), posiblemente modificando la ruta de antemano o especificando completamente las ubicaciones de los ejecutables (por ejemplo, /c/cygwin/bin/uname).

paxdiablo avatar Aug 12 '2010 09:08 paxdiablo

Detecta tres tipos de sistemas operativos diferentes (GNU/Linux, Mac OS X, Windows NT)

Notas

  • En su script bash, utilícelo #!/usr/bin/env bashen lugar de #!/bin/shpara evitar el problema causado por /bin/shel vínculo a diferentes shells predeterminados en diferentes plataformas, o habrá un error como operador inesperado , eso es lo que sucedió en mi computadora (Ubuntu 64 bits 12.04).
  • Mac OS X 10.6.8 (Snow Leopard) no tiene exprprograma a menos que lo instales, así que solo uso uname.

Diseño

  1. Úselo unamepara obtener la información del sistema ( -sparámetro).
  2. Utilice expry substrpara lidiar con la cuerda.
  3. Úselo if elif fipara hacer el trabajo de combinación.
  4. Puede agregar más soporte del sistema si lo desea, simplemente siga las uname -sespecificaciones.

Implementación

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

Pruebas

  • Linux (Ubuntu 12.04 LTS, Kernel 3.2.0) probó bien.
  • OS X (10.6.8 Snow Leopard) probado correctamente.
  • Windows (Windows 7 de 64 bits) se probó correctamente.

Que aprendí

  1. Verifique las cotizaciones de apertura y cierre.
  2. Compruebe si faltan paréntesis y llaves {}

Referencias

  • [1] nombre - wikipedia
  • [2] error de sintaxis del script de shell: final inesperado del archivo
  • [3] Detectar el sistema operativo desde un script Bash
  • [4] Introducción a la programación BASH
Albert avatar Jun 12 '2013 17:06 Albert

Utilice uname -s( --kernel-name) porque uname -o( --operating-system) no es compatible con algunos sistemas operativos como Mac OS y Solaris . También puede utilizar just unamesin ningún argumento ya que el argumento predeterminado es -s( --kernel-name).

Para distinguir WSL de Linux, einarmagnus recomienda uname -sr( --kernel-name --kernel-release) como se propone en el siguiente script. 😉

#!/bin/sh

case "$(uname -sr)" in

   Darwin*)
     echo 'Mac OS X'
     ;;

   Linux*Microsoft*)
     echo 'WSL'  # Windows Subsystem for Linux
     ;;

   Linux*)
     echo 'Linux'
     ;;

   CYGWIN*|MINGW*|MINGW32*|MSYS*)
     echo 'MS Windows'
     ;;

   # Add here more strings to compare
   # See correspondence table at the bottom of this answer

   *)
     echo 'Other OS' 
     ;;
esac

Lo siguiente Makefileestá inspirado en el proyecto 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
...

Consulte también esta respuesta completa sobre uname -syMakefile .

La tabla de correspondencia al final de esta respuesta es de un artículo de Wikipedia sobreuname . Contribuya para mantenerlo actualizado (edite la respuesta o publique un comentario). También puedes actualizar el artículo de Wikipedia y publicar un comentario para notificarme sobre tu contribución ;-)

Sistema operativo nombre -s
Mac OS X Darwin
Cygwin de 32 bits (Win XP) CYGWIN_NT-5.1
Cygwin de 32 bits (Win-7 de 32 bits) CYGWIN_NT-6.1
Cygwin de 32 bits (Win-7 de 64 bits) CYGWIN_NT-6.1-WOW64
Cygwin de 64 bits (Win-7 de 64 bits) CYGWIN_NT-6.1
MinGW (Windows 7 de 32 bits) MINGW32_NT-6.1
MinGW (Windows 10 de 64 bits) MINGW64_NT-10.0
Interix (Servicios para UNIX) Interix
MSYS MSYS_NT-6.1
MSYS2 MSYS_NT-10.0-17763
Subsistema de Windows para Linux linux
Androide linux
coreutils linux
CentOS linux
sombrero linux
Gentoo linux
Red Hat Linux linux
menta linux linux
openSUSE linux
ubuntu linux
Unidad Linux linux
ManjaroLinux linux
OpenWRT r40420 linux
Debian (Linux) linux
Debian (GNU Hurd) ÑU
Debian (kFreeBSD) GNU/kFreeBSD
FreeBSD FreeBSD
NetBSD NetBSD
OpenBSD OpenBSD
DragonFlyBSD Libélula
haikus haikus
Sin escalas 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 (Windows 7 de 64 bits) UWIN-W7
SYS$UNIX:SH en OpenVMS IS/BM
z/OS USS OS/390
Cray sn5176
(SCO) Servidor abierto SCO_SV
(SCO) Sistema V SCO_SV
(SCO) UnixWare Unixware
IBM AIX AIX
IBM i con QSH OS400
HP-UX HP-UX
oHo avatar Jan 05 '2015 09:01 oHo

Bash establece la variable de shell OSTYPE. De man bash:

Se establece automáticamente en una cadena que describe el sistema operativo en el que se ejecuta bash.

Esto tiene una pequeña ventaja sobre unameel hecho de que no requiere iniciar un nuevo proceso, por lo que será más rápido de ejecutar.

Sin embargo, no puedo encontrar una lista autorizada de valores esperados. Para mí, en Ubuntu 14.04 está configurado en 'linux-gnu'. Busqué en la web algunos otros valores. Por eso:

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

Los asteriscos son importantes en algunos casos; por ejemplo, OSX agrega un número de versión del sistema operativo después de "darwin". Me dijeron que el valor 'win' es en realidad 'win32'. ¿Quizás haya un 'win64'?

Quizás podríamos trabajar juntos para completar una tabla de valores verificados aquí:

  • Linux Ubuntu (incluido WSL ):linux-gnu
  • Cygwin de 64 bits:cygwin
  • Msys/MINGW (Git Bash para Windows):msys
  • MacOS Venura:darwin22.0

(Adjunte su valor si difiere de las entradas existentes)

Jonathan Hartley avatar Nov 20 '2015 14:11 Jonathan Hartley