Como verificar se está a correr em Cygwin, Mac ou Linux?

Eu tenho um script de shell que é usado tanto no Windows/Cygwin e Mac e Linux. Ele precisa de variáveis ligeiramente diferentes para cada versão.

Como é que um script shell/bash pode detectar se está a correr no Cygwin, num Mac ou no Linux?

Author: bastibe, 2010-08-12

10 answers

Normalmente, unamecom as suas várias opções dir-lhe-á em que Ambiente está a correr:

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

E, de acordo com o muito útil schot (nos comentários), uname -s dá - Darwin para OSX e Linux para o Linux, enquanto o meu Cygwin dá - CYGWIN_NT-5.1. Mas você pode ter que experimentar com todos os tipos de versões diferentes.

Então o código bash para fazer tal verificação seria de acordo com:

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

Note que estou a assumir que está mesmo a fugir. dentro de CygWin (a concha bash dele) assim os caminhos já devem ser configurados corretamente. Como nota um comentarista, você pode executar o programa bash, passando o script, a partir do próprio cmd e isso pode resultar em que os caminhos não estão sendo configurados conforme necessário.

Se você está fazendo isso, é sua responsabilidade assegurar que os executáveis corretos (ou seja, os CygWin) estão sendo chamados, possivelmente modificando o caminho de antemão ou especificando completamente os locais executáveis (e.g., /c/cygwin/bin/uname).

 187
Author: paxdiablo, 2017-11-21 01:26:53

Aqui está o script bash que usei para detectar três tipos diferentes de SO (GNU/Linux, Mac OS X, Windows NT)

Presta atenção

  • Em seu bash script, use #!/usr/bin/env bash em vez de #!/bin/sh, para evitar o problema causado por /bin/sh ligadas a diferentes shell padrão em diferentes plataformas, ou haverá erro como inesperado operador, que é o que aconteceu no meu computador (Ubuntu 12.04 64 bits).
  • o Mac OS X 10.6.8 (Leopardo das Neves) não tem expr Programa a menos que você instale, então eu só uso uname.

Design

  1. utilize uname para obter a informação do sistema (parâmetro-s).
  2. Use expr e substr para lidar com o texto.
  3. Uso if elif fi para fazer o trabalho a condizer.
  4. pode adicionar mais suporte ao sistema se quiser, basta seguir a especificação uname -s.

Execução

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

Teste

  • o Linux (Ubuntu 12. 04 LTS, Kernel 3. 2. 0) foi testado BEM.
  • OS X (10.6.8 Leopardo das Neves) testaram OK.
  • as janelas (Windows 7 64 bit) foram testadas OK.
O que aprendi
    Verifique as aspas de abertura e fecho.
  1. verifique se faltam parêntesis e chavetas {}

Referências

 266
Author: Albert, 2017-05-23 11:54:59

Usar uname -s (--kernel-name) porque uname -o (--operating-system) não é suportada em alguns Sistemas Operacionais, como Mac OS, Solaris. Pode também utilizar apenas uname sem argumento como o argumento padrão é -s (--kernel-name).

O trecho abaixo não exige bash (isto é, não exige #!/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

O abaixo {[10] } é inspirado no projecto 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
...

Ver também esta resposta completa sobre uname -s e Makefile.

A tabela de correspondência na parte inferior desta resposta é de Artigo da Wikipédia sobre uname. Por favor, contribua para mantê-lo atualizado (edite a resposta ou publique um comentário). Você também pode atualizar o Artigo da Wikipédia e postar um comentário para me notar sobre sua contribuição ;-)

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

 81
Author: olibre, 2018-10-01 07:05:30

Bash define a variável shell OSTYPE. De man bash:

Configura automaticamente uma cadeia de caracteres que descreve o sistema operativo em que o bash está a executar.

Isto tem uma pequena vantagem sobre {[[2]} na medida em que não requer o lançamento de um novo processo, por isso será mais rápido de executar.

No entanto, não consigo encontrar uma lista autorizada de valores esperados. Para mim no Ubuntu 14.04 está definido para 'linux-gnu'. Raspei a teia para outro. valores. Assim:
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

Os asteriscos são importantes em alguns casos-por exemplo, o OSX adiciona um número de versão do sistema operacional após o 'darwin'. O valor " win "é na verdade "win32", disseram - me-talvez haja um "win64"?

Talvez pudéssemos trabalhar juntos para popularizar uma tabela de valores verificados aqui:
  • Linux Ubuntu (incl. WSL): linux-gnu
  • Cygwin 64-bit: cygwin
  • Msys / MINGW (Git Bash para o Windows): msys

(por favor adicione o seu valor se for diferente dos itens existentes)

 43
Author: Jonathan Hartley, 2018-03-23 17:47:48
Para desenvolver a resposta do Albert, gosto de usar $COMSPECpara detectar janelas:
#!/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

Isto evita analisar variantes dos nomes do Windows para $OS, e analisar variantes de uname como o MINGW, Cygwin, etc.

fundo: %COMSPEC% é uma variável ambiental do Windows que especifica a localização completa do processador de comandos (aka shell do Windows). O valor desta variável é tipicamente %SystemRoot%\system32\cmd.exe, que normalmente avalia em C:\Windows\system32\cmd.exe .

 9
Author: Steve Jansen, 2013-09-13 16:14:32
# This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
    echo Cygwin rulez
else 
    echo Unix is king
fi

Se os 6 primeiros caracteres do comando uname-s forem "CYGWIN", um sistema cygwin é assumido

 8
Author: Jan Helge, 2018-09-20 09:34:45

Http://en.wikipedia.org/wiki/Uname

Toda a informação que precisar. O Google é seu amigo.

Utilize uname -s para consultar o nome do sistema.

  • Mac: Darwin
  • Cygwin: CYGWIN_...
  • Linux: vários, LINUX para a maioria
 4
Author: rubenvb, 2015-07-21 08:21:14
Ok, aqui está a minha maneira.
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 ^ $? ))
}

Por exemplo

osis Darwin &&
{
    log_debug Detect mac osx
}
osis Linux &&
{
    log_debug Detect linux
}
osis -n Cygwin &&
{
    log_debug Not Cygwin
}

Uso isto nos meus ficheiros

 1
Author: wener, 2015-02-13 06:46:43

Use apenas isto da linha de comandos funciona muito bem, graças ao Justin.

#!/bin/bash

################################################## #########
# Bash script to find which OS
################################################## #########

OS=`uname`
echo "$OS"

Origem

 0
Author: lizardhr, 2014-07-25 21:17:41
Acho que a resposta inamovível é imbatível, principalmente em termos de limpeza.

Embora demore um tempo ridículo para executar, eu descobri que testar para a presença de arquivos específicos também me dá bons e mais rápidos resultados, uma vez que eu não estou invocando um executável:

Então,

[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running

Só usa uma verificação rápida da presença do ficheiro Bash. Como estou no Windows agora, não posso dizer nenhum arquivo específico para Linuxes e Mac OS X da minha cabeça, mas tenho certeza que eles existem. :-)

 0
Author: Charles Roberto Canato, 2015-08-12 00:12:49