Jak wykryć system operacyjny ze skryptu Bash?

Chciałbym zachować moje pliki .bashrc i .bash_login w kontroli wersji, aby móc używać ich pomiędzy wszystkimi komputerami, z których korzystam. Problem w tym, że mam pewne aliasy specyficzne dla systemu operacyjnego, więc szukałem sposobu, aby określić, czy skrypt działa na Mac OS X, Linux lub Cygwin .

Jaki jest właściwy sposób wykrywania systemu operacyjnego w skrypcie Bash ?

21 answers

Myślę, że to powinno zadziałać. Nie jestem jednak pewien co do win32.

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        # ...
elif [[ "$OSTYPE" == "darwin"* ]]; then
        # Mac OSX
elif [[ "$OSTYPE" == "cygwin" ]]; then
        # POSIX compatibility layer and Linux environment emulation for Windows
elif [[ "$OSTYPE" == "msys" ]]; then
        # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
elif [[ "$OSTYPE" == "win32" ]]; then
        # I'm not sure this can happen.
elif [[ "$OSTYPE" == "freebsd"* ]]; then
        # ...
else
        # Unknown.
fi
 625
Author: Timmmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-05 12:08:57

Dla mojego .bashrc, używam następującego kodu:

platform='unknown'
unamestr=`uname`
if [[ "$unamestr" == 'Linux' ]]; then
   platform='linux'
elif [[ "$unamestr" == 'FreeBSD' ]]; then
   platform='freebsd'
fi

Potem robię coś takiego jak:

if [[ $platform == 'linux' ]]; then
   alias ls='ls --color=auto'
elif [[ $platform == 'freebsd' ]]; then
   alias ls='ls -G'
fi
Jest brzydki, ale działa. Jeśli wolisz, możesz użyć case zamiast if.
 300
Author: Nicolas Martyanoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 22:37:33

Strona podręcznika bash mówi, że zmienna OSTYPE przechowuje nazwę systemu operacyjnego:

OSTYPE automatycznie ustawia się na ciąg opisujący system operacyjny, na którym bash jest wykonywany. Domyślną wartością jest system- zależny.

Jest ustawiony na linux-gnu tutaj. jio

 283
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-15 18:11:31

$OSTYPE

Możesz po prostu użyć predefiniowanej zmiennej $OSTYPE np.:

case "$OSTYPE" in
  solaris*) echo "SOLARIS" ;;
  darwin*)  echo "OSX" ;; 
  linux*)   echo "LINUX" ;;
  bsd*)     echo "BSD" ;;
  msys*)    echo "WINDOWS" ;;
  *)        echo "unknown: $OSTYPE" ;;
esac

Jednak nie są rozpoznawane przez starsze muszle (takie jak Bourne shell).


uname

Inną metodą jest wykrywanie platformy na podstawie polecenia uname.

Patrz następujący skrypt (gotowy do włączenia w ."bashrc"): {]}

# Detect the platform (similar to $OSTYPE)
OS="`uname`"
case $OS in
  'Linux')
    OS='Linux'
    alias ls='ls --color=auto'
    ;;
  'FreeBSD')
    OS='FreeBSD'
    alias ls='ls -G'
    ;;
  'WindowsNT')
    OS='Windows'
    ;;
  'Darwin') 
    OS='Mac'
    ;;
  'SunOS')
    OS='Solaris'
    ;;
  'AIX') ;;
  *) ;;
esac

Praktyczny przykład znajdziesz w moim .bashrc.


Oto podobna wersja użyta na Travis CI :

case $(uname | tr '[:upper:]' '[:lower:]') in
  linux*)
    export TRAVIS_OS_NAME=linux
    ;;
  darwin*)
    export TRAVIS_OS_NAME=osx
    ;;
  msys*)
    export TRAVIS_OS_NAME=windows
    ;;
  *)
    export TRAVIS_OS_NAME=notset
    ;;
esac
 184
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-09 09:16:21

Wykrywanie systemu operacyjnego i typu procesora nie jest tak łatwe do zrobienia przenośnie . Mam skrypt sh składający się z około 100 linii, który działa na bardzo różnych platformach Unix: dowolnym systemie używanym od 1988 roku.

Kluczowymi elementami są

  • uname -p jest typem procesora, ale zazwyczaj jest unknown na współczesnych platformach Unix.

  • uname -m poda "nazwę sprzętu komputerowego" na jakimś Uniksie systemy.

  • /bin/arch, jeśli istnieje, zwykle podaje Typ procesora.

  • uname bez argumentów nazwa systemu operacyjnego.

W końcu będziesz musiał pomyśleć o rozróżnieniach między platformami i Jak Dobrze chcesz je zrobić. na przykład, dla uproszczenia, traktuję i386 przezi686 , dowolne "Pentium*" i dowolne "AMD*Athlon*" jako x86.

Mój ~/.profile uruchamia skrypt a przy starcie, który ustawia jedną zmienną na ciąg znaków wskazujący kombinację procesora i systemu operacyjnego. Mam konkretną platformębin, man, lib, i include katalogi, które są ustawiane na tej podstawie. Następnie ustawiłem boatload zmiennych środowiskowych. Na przykład skrypt powłoki do sformatowania poczty może wywołać, np. $LIB/mailfmt, który jest plikiem wykonywalnym specyficznym dla platformy.

Jeśli chcesz wyciąć rogi, uname -m a plain uname powie Ci to, co chcesz wiedzieć na wielu platformach. Dodaj inne rzeczy, kiedy tego potrzebujesz. (I używać case, nie zagnieżdżać if!)

 39
Author: Norman Ramsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 22:51:44

Zalecam użycie tego pełnego kodu bash

lowercase(){
    echo "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
}

OS=`lowercase \`uname\``
KERNEL=`uname -r`
MACH=`uname -m`

if [ "{$OS}" == "windowsnt" ]; then
    OS=windows
elif [ "{$OS}" == "darwin" ]; then
    OS=mac
else
    OS=`uname`
    if [ "${OS}" = "SunOS" ] ; then
        OS=Solaris
        ARCH=`uname -p`
        OSSTR="${OS} ${REV}(${ARCH} `uname -v`)"
    elif [ "${OS}" = "AIX" ] ; then
        OSSTR="${OS} `oslevel` (`oslevel -r`)"
    elif [ "${OS}" = "Linux" ] ; then
        if [ -f /etc/redhat-release ] ; then
            DistroBasedOn='RedHat'
            DIST=`cat /etc/redhat-release |sed s/\ release.*//`
            PSUEDONAME=`cat /etc/redhat-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/redhat-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/SuSE-release ] ; then
            DistroBasedOn='SuSe'
            PSUEDONAME=`cat /etc/SuSE-release | tr "\n" ' '| sed s/VERSION.*//`
            REV=`cat /etc/SuSE-release | tr "\n" ' ' | sed s/.*=\ //`
        elif [ -f /etc/mandrake-release ] ; then
            DistroBasedOn='Mandrake'
            PSUEDONAME=`cat /etc/mandrake-release | sed s/.*\(// | sed s/\)//`
            REV=`cat /etc/mandrake-release | sed s/.*release\ // | sed s/\ .*//`
        elif [ -f /etc/debian_version ] ; then
            DistroBasedOn='Debian'
            DIST=`cat /etc/lsb-release | grep '^DISTRIB_ID' | awk -F=  '{ print $2 }'`
            PSUEDONAME=`cat /etc/lsb-release | grep '^DISTRIB_CODENAME' | awk -F=  '{ print $2 }'`
            REV=`cat /etc/lsb-release | grep '^DISTRIB_RELEASE' | awk -F=  '{ print $2 }'`
        fi
        if [ -f /etc/UnitedLinux-release ] ; then
            DIST="${DIST}[`cat /etc/UnitedLinux-release | tr "\n" ' ' | sed s/VERSION.*//`]"
        fi
        OS=`lowercase $OS`
        DistroBasedOn=`lowercase $DistroBasedOn`
        readonly OS
        readonly DIST
        readonly DistroBasedOn
        readonly PSUEDONAME
        readonly REV
        readonly KERNEL
        readonly MACH
    fi

fi
echo $OS
echo $KERNEL
echo $MACH

Więcej przykładów przykłady tutaj: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

 39
Author: coto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-16 19:47:44

Sugerowałbym unikanie niektórych z tych odpowiedzi. Nie zapominaj, że możesz wybrać inne formy porównywania ciągów, które wyjaśniłyby większość wariantów lub oferowany brzydki kod.

Jednym z takich rozwiązań byłaby prosta kontrola, np.:

if [[ "$OSTYPE" =~ ^darwin ]]; then

Który ma dodatkową zaletę dopasowania dowolnej wersji Darwina, pomimo jego sufiksu wersji. Działa to również dla dowolnych odmian Linux, których można się spodziewać.

Możesz zobaczyć kilka dodatkowych przykładów w moich plikach dotfiles tutaj

 12
Author: Akiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-03 21:59:43

W bashu używaj $OSTYPE i $HOSTTYPE, zgodnie z dokumentacją; tym się zajmuję. Jeśli to nie wystarczy, a nawet uname lub uname -a (lub inne odpowiednie opcje) nie daje wystarczającej ilości informacji, zawsze jest config.zgadnijcie skrypt projektu GNU, zrobiony dokładnie w tym celu.

 10
Author: Teddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-14 11:24:37

Spróbuj użyć "uname". Na przykład w Linuksie: "uname-a".

Zgodnie ze stroną podręcznika, uname jest zgodny z SVr4 i POSIX, więc powinien być dostępny również na Mac OS X i Cygwin, ale nie mogę tego potwierdzić.

BTW: $OSTYPE jest też ustawione na linux-gnu tutaj:)

 10
Author: Joao da Silva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-19 15:38:33

Napisałem te cukry w moim .bashrc:

if_os () { [[ $OSTYPE == *$1* ]]; }
if_nix () { 
    case "$OSTYPE" in
        *linux*|*hurd*|*msys*|*cygwin*|*sua*|*interix*) sys="gnu";;
        *bsd*|*darwin*) sys="bsd";;
        *sunos*|*solaris*|*indiana*|*illumos*|*smartos*) sys="sun";;
    esac
    [[ "${sys}" == "$1" ]];
}

Więc mogę robić takie rzeczy jak:

if_nix gnu && alias ls='ls --color=auto' && export LS_COLORS="..."
if_nix bsd && export CLICOLORS=on && export LSCOLORS="..."
if_os linux && alias psg="ps -FA | grep" #alternative to pgrep
if_nix bsd && alias psg="ps -alwx | grep -i" #alternative to pgrep
if_os darwin && alias finder="open -R"
 8
Author: kfix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 18:00:19
uname

Lub

uname -a

Jeśli chcesz więcej informacji

 7
Author: Federico A. Ramponi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-26 20:33:45

Napisałemosobistą bibliotekę Bash i Framework skryptowy , który używaGNU shtool do dość dokładnego wykrywania platformy.

GNU SHTOOL jest bardzo przenośnym zestawem skryptów, który zawiera między innymi polecenie 'shtool platform'. Oto wynik:

shtool platform -v -F "%sc (%ac) %st (%at) %sp (%ap)"

Na kilku różnych maszynach:

Mac OS X Leopard: 
    4.4BSD/Mach3.0 (iX86) Apple Darwin 9.6.0 (i386) Apple Mac OS X 10.5.6 (iX86)

Ubuntu Jaunty server:
    LSB (iX86) GNU/Linux 2.9/2.6 (i686) Ubuntu 9.04 (iX86)

Debian Lenny:
    LSB (iX86) GNU/Linux 2.7/2.6 (i686) Debian GNU/Linux 5.0 (iX86)

To daje całkiem zadowalające wyniki, jak widać. GNU shtool jest trochę powolny, więc faktycznie przechowuję i aktualizuję platformę Identyfikacja w pliku w systemie, który wywołują moje Skrypty. To mój framework, więc działa dla mnie, ale twój przebieg może się różnić.

Teraz będziesz musiał znaleźć sposób, aby spakować shtool ze swoimi skryptami, ale to nie jest trudne ćwiczenie. Zawsze możesz wrócić na wyjście uname.

EDIT:

Przegapiłem post misia o config.guess (jakoś). Są to bardzo podobne Skrypty, ale nie te same. Osobiście używam shtool również do innych zastosowań i działa całkiem dobrze dla mnie.

 7
Author: guns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-19 15:41:42

Możesz użyć:

OS=$(uname -s)

Następnie możesz użyć zmiennej OS w swoim skrypcie.

 7
Author: Chetan kapoor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-23 11:42:13

To powinno być bezpieczne w użyciu na wszystkich dystrybucjach.

$ cat /etc/*release
To produkuje coś takiego.
     DISTRIB_ID=LinuxMint
     DISTRIB_RELEASE=17
     DISTRIB_CODENAME=qiana
     DISTRIB_DESCRIPTION="Linux Mint 17 Qiana"
     NAME="Ubuntu"
     VERSION="14.04.1 LTS, Trusty Tahr"
     ID=ubuntu
     ID_LIKE=debian
     PRETTY_NAME="Ubuntu 14.04.1 LTS"
     VERSION_ID="14.04"
     HOME_URL="http://www.ubuntu.com/"
     SUPPORT_URL="http://help.ubuntu.com/"
     BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

Wyodrębnij / Przypisz do zmiennych zgodnie z życzeniem

Uwaga: na niektórych ustawieniach. Może to również spowodować błędy, które można zignorować.

     cat: /etc/upstream-release: Is a directory
 6
Author: R J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-21 01:10:35

Poniżej znajduje się podejście do wykrywania bazujących na Debianie i Redhacie Linux OS wykorzystujących/etc / LSB-release oraz /etc / os-release (w zależności od używanego Linuksa) i podjąć prostą akcję na jego podstawie.

#!/bin/bash
set -e

YUM_PACKAGE_NAME="python python-devl python-pip openssl-devel"
DEB_PACKAGE_NAME="python2.7 python-dev python-pip libssl-dev"

 if cat /etc/*release | grep ^NAME | grep CentOS; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on CentOS"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Red; then
    echo "==============================================="
    echo "Installing packages $YUM_PACKAGE_NAME on RedHat"
    echo "==============================================="
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Fedora; then
    echo "================================================"
    echo "Installing packages $YUM_PACKAGE_NAME on Fedorea"
    echo "================================================"
    yum install -y $YUM_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Ubuntu; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Ubuntu"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Debian ; then
    echo "==============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Debian"
    echo "==============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Mint ; then
    echo "============================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Mint"
    echo "============================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 elif cat /etc/*release | grep ^NAME | grep Knoppix ; then
    echo "================================================="
    echo "Installing packages $DEB_PACKAGE_NAME on Kanoppix"
    echo "================================================="
    apt-get update
    apt-get install -y $DEB_PACKAGE_NAME
 else
    echo "OS NOT DETECTED, couldn't install package $PACKAGE"
    exit 1;
 fi

exit 0

Przykład Wyjścia dla Ubuntu Linux:

delivery@delivery-E5450$ sudo sh detect_os.sh
[sudo] password for delivery: 
NAME="Ubuntu"
===============================================
Installing packages python2.7 python-dev python-pip libssl-dev on Ubuntu
===============================================
Ign http://dl.google.com stable InRelease
Get:1 http://dl.google.com stable Release.gpg [916 B]                          
Get:2 http://dl.google.com stable Release [1.189 B] 
...            
 6
Author: Exequiel Barrirero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-20 12:36:45

Spróbuj tego:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
 3
Author: Alexander Nekrasov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-08 10:04:54

Możesz użyć następującej klauzuli if I rozwinąć ją w razie potrzeby:

if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
    aminute_ago="-v-1M"
elif  [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
    aminute_ago="-d \"1 minute ago\""
fi
 3
Author: Tahsin Turkoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-30 04:19:30

Zachowuję swoje .bashrc i .bash_alias na współdzielenie plików, do których mają dostęp wszystkie platformy. W ten sposób pokonuję problem w moim .bash_alias:

if [[ -f (name of share)/.bash_alias_$(uname) ]]; then
    . (name of share)/.bash_alias_$(uname)
fi

I mam na przykład a .bash_alias_Linux with:

alias ls='ls --color=auto'

W ten sposób zachowam oddzielny kod specyficzny dla platformy i przenośny, możesz zrobić to samo .bashrc

 2
Author: ericcurtin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-15 17:36:42

Wypróbowałem powyższe wiadomości w kilku dystrybucjach Linuksa i okazało się, że poniższe działają najlepiej dla mnie. Jest to krótka, zwięzła, dokładna odpowiedź słowa, która działa również w Bash w systemie Windows.

OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
 2
Author: intellilogic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 18:55:48

To sprawdza kilka plików known do identyfikowania, jeśli dystrybucja Linuksa to Debian lub Ubunu, to domyślnie jest to zmienna $OSTYPE.

os='Uknown'
unamestr="${OSTYPE//[0-9.]/}"
os=$( compgen -G "/etc/*release" > /dev/null  && cat /etc/*release | grep ^NAME | tr -d 'NAME="'  ||  echo "$unamestr")

echo "$os"
 1
Author: Kuzeko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-02 19:24:42

Wykonanie następujących czynności pomogło w poprawnym sprawdzeniu ubuntu:

if [[ "$OSTYPE" =~ ^linux ]]; then
    sudo apt-get install <some-package>
fi
 -1
Author: sandman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-21 01:53:56