Cygwin, Mac veya Linux'ta çalışıp çalışmadığını nasıl kontrol edebilirim?


334

Hem Windows / Cygwin hem de Mac ve Linux'ta kullanılan bir kabuk betiğim var. Her versiyon için biraz farklı değişkenlere ihtiyaç duyar.

Bir kabuk / bash betiği, Cygwin'de, Mac'te veya Linux'ta çalıştığını nasıl algılayabilir?

Yanıtlar:


322

Genellikle, unameçeşitli seçenekleriyle hangi ortamda çalıştığınızı söyler:

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

Ve, çok yararlı göre schot(yorumlarda), uname -sverir DarwinOSX için ve Linuxbenim Cygwin verir iken, Linux için CYGWIN_NT-5.1. Ancak her türlü farklı sürümü denemeniz gerekebilir.

Yani bashböyle bir kontrol yapmak için kod aşağıdaki satırlarda olacaktır:

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

Burada CygWin ( kabuğunun) içinde çalıştığınızı varsayıyorum bash, bu yüzden yollar zaten doğru şekilde ayarlanmalıdır. Bir yorumcunun belirttiği gibi, bashprogramı komut dosyasını geçirerek çalıştırabilirsiniz cmdve bu, yolların gerektiği gibi ayarlanmamasına neden olabilir.

Eğer varsa vardır yapıyor, bu (yani cygwin olanlar) olarak adlandırılan ediliyor doğru yürütülebilir sağlamak sizin sorumluluğunuzdur muhtemelen yolunu değiştirerek önceden veya tamamen (örneğin çalıştırılabilir yerleri belirtilerek var /c/cygwin/bin/uname).


11
Bazen daha azı daha fazladır;) BTW, Wikipedia'nın en.wikipedia.org/wiki/Uname
schot

Windows 7'deki Git Bash uname -s çıktısı MINGW32_NT-6.1. Ayrıca, hiçbir orada /cygdrivesadece, önek /ciçin C:.
ColinM

7
Git Bash Cygwin değil. MinGW, MS Windows için minimum GNU, bu yüzden davranış farklı.
Boyd Stephen Smith Jr.

Diğer cevabı teşvik ettim çünkü bu cevap OP kısmı ile ilgilenmiyor How can a shell/bash script detect ..., diğeri ise öyle.
Jesse Chisholm

"\ Cygwin64 \ bin \ bash -c scriptname" komutunu kullanarak cygwin altında bir script çalıştırırsam, bu mutlaka işe yaramaz. Bu durumda, cygwin yolu kurulmaz ve geçerli yolunuzda ilk olanı uname -sçağırır ve unamesistemimde gedametni döndüren sürüm olduğu ortaya çıkar WindowsNT. Yine de yukarıda tarif edildiği gibi MinGW versiyonu olabilir. Cygwin için güvenilir bir tespiti gerekir yol kullanan, IMO uygun ayarlanmıştır. Bu nedenle, cygwin tespit etmek $(uname -s)için değiştirilmelidir $(/bin/uname -s).
Jules

329

İşte üç farklı işletim sistemi türünü (GNU / Linux, Mac OS X, Windows NT) tespit etmek için kullandığım bash betiği

Çok dikkat

  • Sizin bash komut dosyasında, kullanmak #!/usr/bin/env bashyerine #!/bin/shneden olduğu sorunu önlemek için /bin/shfarklı platformlarda farklı varsayılan kabuk bağlı ya da benzeri bir hata olacaktır beklenmedik operatör bilgisayarımda ne en (Ubuntu 64 bit 12.04) olduğu,.
  • Mac OS X 10.6.8 (Snow Leopard) expryüklemediğiniz sürece programınız yok , bu yüzden sadece kullanıyorum uname.

tasarlamak

  1. unameSistem bilgilerini ( -sparametre) almak için kullanın .
  2. Dize ile başa çıkmak için exprve tuşlarını kullanın substr.
  3. if elif fiEşleşen işi yapmak için kullanın .
  4. İsterseniz daha fazla sistem desteği ekleyebilirsiniz, sadece uname -steknik özellikleri izleyin .

uygulama

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

Test yapmak

  • Linux (Ubuntu 12.04 LTS, Çekirdek 3.2.0) test edildi.
  • OS X (10.6.8 Kar Leoparı) test edildi.
  • Windows (Windows 7 64 bit) test edildi TAMAM.

Ne öğrendim

  1. Hem açılış hem de kapanış tekliflerini kontrol edin.
  2. Eksik parantez ve kaşlı ayraçları kontrol edin {}

Referanslar


MinGW için, kontrol etmek daha mantıklı olabilir: [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ].
Achal Dave

2
@ Albert: İfade "$(expr substr $(uname -s) 1 5)"biraz garip. Örneğin, bunu yapmak için daha güzel yolu vardır: if [ `uname -s` == CYGWIN* ]; then. Okuyun: CYGWINuname -s ile başlıyorsa ...
David Ferenczy Rogožan

10
@DawidFerenczy Bunun gibi çift parantez gerektireceğine inanıyorumif [[ $(uname -s) == CYGWIN* ]]; then
rogerdpack

1
Bu soruda sorulduğu gibi Cygwin'i algılamaz.
rmcclellan

2
Bu neden Linux için sadece ilk 5 karakteri kontrol ediyor? uname -s"Linux" dan başka bir şey getirecek modern Linux dağıtım örnekleri var mı?
ktbiz

127

Kullanım uname -s( --kernel-name) çünkü uname -o( --operating-system) gibi bazı işletim sistemleri üzerinde desteklenmez Mac OS ve Solaris . Varsayılan bağımsız değişken ( ) olduğu için unameherhangi bir bağımsız değişken olmadan da kullanabilirsiniz .-s--kernel-name

Aşağıdaki pasaj gerektirmez (yani gerektirmez #!/bin/bash)

#!/bin/sh

case "$(uname -s)" in

   Darwin)
     echo 'Mac OS X'
     ;;

   Linux)
     echo 'Linux'
     ;;

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

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

   *)
     echo 'Other OS' 
     ;;
esac

Aşağıdakiler Git projesinden ( )Makefile esinlenmiştir .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
...

Ayrıca bkz hakkındaki bu tam bir cevap uname -sveMakefile .

Bu cevabın altındaki yazışma tablosu hakkındaki Wikipedia makalesinden alınmıştıruname . Lütfen güncel tutmaya katkıda bulunun (cevabı düzenleyin veya yorum gönderin). Ayrıca Wikipedia makalesini güncelleyebilir ve katkınız hakkında beni bilgilendirmek için bir yorum gönderebilirsiniz ;-)

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
MSYS2 MSYS_NT-10.0-17763
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


3
Solaris için Yaşasın ve yukarıdaki araştırma.
okutane

Merhaba @okutane. Ne demek istediğini anlamıyorum. Lütfen daha fazla ayrıntı sağlayın. Bir şey önerir misin? Şerefe
olibre

3
Oy veriyorum, hepsi bu.
okutane

1
Bu tam olarak taşınabilir / çapraz platform yazmak için aradığım şeydi ~/.profile(çevre değişkenlerini ayarlamak $PATHiçin - posterity için arama anahtar kelimeleri sağlamak için yorum yapmak).
Braham Snyder

1
Buraya geldim çünkü WSL'yi özel olarak tespit etmek ve diğer Linux'lardan ayırmak istedim. Benim için işe yarayan şey, daha önce kontrol uname -sredip karşılaştırmaktır . Linux*Microsoft)Linux*)
einarmagnus

65

Bash kabuk değişkenini OSTYPE olarak ayarlar. Gönderen man bash:

Otomatik olarak bash'ın yürütüldüğü işletim sistemini tanımlayan bir dizeye ayarlanır.

Bunun, unameyeni bir işlem başlatmayı gerektirmediği için küçük bir avantajı vardır , bu nedenle yürütülmesi daha hızlı olacaktır.

Ancak, beklenen değerlerin yetkili bir listesini bulamıyorum. Benim için Ubuntu 14.04'te 'linux-gnu' olarak ayarlandı. Web'i başka değerler için kazıyordum. Dolayısıyla:

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

Yıldız işaretleri bazı durumlarda önemlidir - örneğin OSX, 'darwin' den sonra bir OS sürüm numarası ekler. 'Kazanma' değeri aslında 'win32', bana söylendi - belki bir 'win64' var mı?

Belki de burada doğrulanmış değerler tablosunu doldurmak için birlikte çalışabiliriz:

  • Linux Ubuntu ( WSL dahil ):linux-gnu
  • Cygwin 64 bit: cygwin
  • Msys / MINGW (Windows için Git Bash): msys

(Lütfen mevcut girişlerden farklıysa değerinizi ekleyin)


1
Cevabınızı benden daha çok beğendim, buna ihtiyacım olan nadir zamanlarda mükemmel uyuyor
Charles Roberto Canato

6
Teknik olarak, bir ortam değişkeni değil, bir kabuk değişkeni. Bu yüzden altında görmeyeceksin env | grep OSTYPE, ama altında göreceksinset | grep OSTYPE
wisbucky

4
İlgilenenler için, Bash OSTYPEdeğişkeni (conftypes.h) derleme zamanında automake OSdeğişkeninin (Makefile.in) tam kopyası kullanılarak yapılandırılır . Mevcut tüm tipler için automake 'nin lib / config.sub dosyasına bakılabilir .
jdknight

9

Albert'in cevabına dayanarak, $COMSPECWindows'u tespit etmek için kullanmayı seviyorum :

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

Windows isimlerin varyantlarını ayrıştırma Bu engeller $OSvaryantları ve ayrıştırma unamevb MinGW Cygwin, gibi

Arka plan: %COMSPEC%komut işlemcisinin (Windows kabuğu olarak da bilinir) tam yolunu belirten bir Windows ortam değişkenidir. Bu değişkenin değeri, tipik %SystemRoot%\system32\cmd.exeolarak değerlendirilen değerdir C:\Windows\system32\cmd.exe.


Windows UWS Bash ortamında çalışırken $ COMSPEC ayarlanmadığından artık düzeltilmiyor.
Julian Knight

9
# This script fragment emits Cygwin rulez under bash/cygwin
if [[ $(uname -s) == CYGWIN* ]];then
    echo Cygwin rulez
else 
    echo Unix is king
fi

Uname -s komutunun ilk 6 grafiği "CYGWIN" ise, bir cygwin sistemi olduğu varsayılır.


if [ `uname -s` == CYGWIN* ]; thendaha iyi görünüyor ve aynı şekilde çalışıyor.
David Ferenczy Rogožan

6
Evet, ancak çift parantez kullanın: [[ $(uname -s) == CYGWIN* ]]. Genişletilmiş düzenli ifadeler bizim durumumuzda daha hassas olduklarını da unutmayın: [[ $(uname -s) =~ ^CYGWIN* ]].
Andreas Spindler

Yukarıda daha iyi çalışır, çünkü expr substr $(uname -s) 1 6macOS'ta bir hata ( expr: syntax error) verir .
doekman

2

Tamam, işte benim yolum.

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 ^ $? ))
}

Örneğin

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

Bunu dotfiles dosyamda kullanıyorum



2

Bu soru sorulduğunda Linux için Windows Alt Sistemi yoktu. Testimde şu sonuçları verdi:

uname -s -> Linux
uname -o -> GNU/Linux
uname -r -> 4.4.0-17763-Microsoft

Bu, yerel Linux'tan ayırt etmek için uname -r'ye ihtiyacınız olduğu anlamına gelir.


1
Ne yazık ki, Mingw-w64 tamamen aynı şeyi veriyor.
Bir Sis

1

Sanırım uname cevap, özellikle temizlik açısından, rakipsiz.

Yürütmek gülünç bir zaman alsa da, belirli dosyaların varlığını test etmenin bana iyi ve daha hızlı sonuçlar verdiğini buldum, çünkü çalıştırılabilir bir dosyayı çağırmıyorum:

Yani,

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

sadece hızlı bir Bash dosya varlığı kontrolü kullanır. Şu anda Windows'ta olduğum için, Linuxes ve Mac OS X için kafamdan belirli bir dosya söyleyemem, ancak var olduklarından eminim. :-)


-3

Komut satırından sadece bunu kullan, Justin sayesinde çok iyi çalışıyor:

#!/bin/bash

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

OS=`uname`
echo "$OS"

kaynak


Senaryonuzdaki yenilikler neler?
mallaudin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.