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?
10 answers
Normalmente, uname
com 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
).
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ó usouname
.
Design
- utilize
uname
para obter a informação do sistema (parâmetro-s
). - Use
expr
esubstr
para lidar com o texto. - Uso
if
elif
fi
para fazer o trabalho a condizer. - 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.
-
Verifique as aspas de abertura e fecho.
- verifique se faltam parêntesis e chavetas {}
Referências
- [1] uname-wikipedia
- [2] erro de sintaxe do programa da consola: fim inesperado do ficheiro
- [3] detectar o SO a partir de um programa da Bash
- [4] Introdução da programação BASH HOW-TO
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
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)
$COMSPEC
para 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
.
# 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
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
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
}
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"
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. :-)