it-swarm.com.de

Wie erkennt man das Betriebssystem von einem Bash-Skript?

Ich möchte meine .bashrc- und .bash_login-Dateien in der Versionskontrolle behalten, damit ich sie zwischen allen Computern verwenden kann, die ich verwende. Das Problem ist, dass ich einige OS-spezifische Aliasnamen habe, also suchte ich nach einer Möglichkeit, festzustellen, ob das Skript unter Mac OS X, Linux oder Cygwin ausgeführt wird.

Wie kann ich das Betriebssystem in einem Bash - Skript richtig erkennen?

396
csexton

Ich denke, das Folgende sollte funktionieren. Ich bin nicht sicher über 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
282
Timmmm

Für meine .bashrc verwende ich den folgenden Code:

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

Dann mache ich etwas wie:

if [[ $platform == 'linux' ]]; then
   alias ls='ls --color=auto'
Elif [[ $platform == 'freebsd' ]]; then
   alias ls='ls -G'
fi

Es ist hässlich, aber es funktioniert. Sie können case anstelle von if verwenden, wenn Sie möchten.

279

Die bash-Manpage sagt, dass die Variable OSTYPE den Namen des Betriebssystems speichert:

OSTYPE Wird automatisch auf eine Zeichenfolge gesetzt, die das Betriebssystem beschreibt, auf dem Bash ausgeführt wird. Der Standard ist system - abhängig.

Hier ist linux-gnu eingestellt.

264

Sie können einfach die vordefinierte $ OSTYPE-Variable verwenden, dh:

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

Eine andere Methode ist das Erkennen einer Plattform basierend auf dem Befehl uname.

Siehe das folgende Skript (bereit zum Einbinden in .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

Sie finden ein praktisches Beispiel in meinem .bashrc .

123
kenorb

Das Erkennen von Betriebssystem und CPU-Typ ist nicht so einfach portabel. Ich habe ein sh-Skript mit etwa 100 Zeilen, das für eine Vielzahl von Unix-Plattformen geeignet ist: jedes System, das ich seit 1988 verwendet habe.

Die Schlüsselelemente sind

  • uname -p ist Prozessortyp , ist aber auf modernen Unix-Plattformen normalerweise unknown.

  • uname -m gibt auf einigen Unix-Systemen den "Hardware-Namen der Maschine" an.

  • Falls vorhanden, gibt /bin/Arch normalerweise den Typ des Prozessors an.

  • uname ohne Argumente benennt das Betriebssystem.

Irgendwann müssen Sie über die Unterschiede zwischen Plattformen nachdenken und wie gut Sie diese machen wollen. Um einfach zu bleiben, behandele ich beispielsweise i386 durch i686, jeden "Pentium*" und jeden "AMD*Athlon*" als x86.

Mein ~/.profile führt beim Start ein Skript aus, das eine Variable auf einen String setzt, der die Kombination aus CPU und Betriebssystem angibt. Ich habe plattformspezifische Verzeichnisse bin, man, lib und include, die darauf basierend eingerichtet werden. Dann setze ich eine Bootload von Umgebungsvariablen. So kann beispielsweise ein Shell-Skript zum Neuformatieren von E-Mails aufgerufen werden, z. B. $LIB/mailfmt, das eine plattformspezifische ausführbare Binärdatei ist.

Wenn Sie Ecken schneiden wollen , uname -m und plain_uname sagt Ihnen, was Sie auf vielen Plattformen wissen möchten. Fügen Sie anderes Material hinzu, wenn Sie es brauchen. (Und verwenden Sie case, nicht verschachtelt if!)

34
Norman Ramsey

Ich empfehle, diesen vollständigen Bash-Code zu verwenden

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

weitere Beispiele Beispiele hier: https://github.com/coto/server-easy-install/blob/master/lib/core.sh

30
coto

Verwenden Sie in der Bash $OSTYPE und $HOSTTYPE, wie dokumentiert; das ist was ich mache. Wenn das nicht genug ist und wenn auch uname oder uname -a (oder andere geeignete Optionen) nicht genügend Informationen liefert, gibt es immer das config.guess - Skript des GNU - Projekts, das genau für diesen Zweck erstellt wurde.

9
Teddy

Ich würde vorschlagen, einige dieser Antworten zu vermeiden. Vergessen Sie nicht, dass Sie andere Formen des Zeichenkettenvergleichs wählen können, wodurch die meisten Variationen oder hässlicher Code behoben werden.

Eine solche Lösung wäre eine einfache Überprüfung, z.

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

Dies hat den zusätzlichen Vorteil, dass jede Darwin-Version trotz des Versions-Suffix angepasst wird. Dies funktioniert auch für alle Variationen von Linux, die man erwarten kann.

Einige weitere Beispiele finden Sie in meinen dotfiles hier

8
Akiva

Versuchen Sie es mit "uname". Zum Beispiel in Linux: "uname -a".

Laut der Handbuchseite entspricht uname SVr4 und POSIX, daher sollte es auch unter Mac OS X und Cygwin verfügbar sein, aber ich kann das nicht bestätigen.

BTW: $ OSTYPE ist auch hier auf linux-gnu gesetzt :)

8
Joao da Silva

Ich habe diese Zucker in meinen .bashrc geschrieben:

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" ]];
}

So kann ich Sachen machen wie:

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"
7
kfix
uname

oder 

uname -a

wenn Sie mehr Informationen wünschen

6

Ich habe eine persönliche Bash-Bibliothek und ein Skript-Framework geschrieben das GNU shtool verwendet, um eine ziemlich genaue Plattformerkennung durchzuführen.

GNU shtool ist ein sehr portabler Satz von Skripten, der unter anderem den Befehl 'shtool platform' enthält. Hier ist die Ausgabe von:

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

auf einigen verschiedenen Maschinen:

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)

Dies führt zu ziemlich zufriedenstellenden Ergebnissen, wie Sie sehen können. GNU shtool ist etwas langsam, also speichere und aktualisiere ich tatsächlich die Plattformkennung in einer Datei auf dem System, die meine Skripts aufrufen. Es ist mein Rahmen, das funktioniert für mich, aber Ihre Laufleistung kann variieren.

Jetzt müssen Sie einen Weg finden, shtool mit Ihren Skripten zu packen, aber es ist keine harte Übung. Sie können auch immer auf die uname-Ausgabe zurückgreifen.

BEARBEITEN:

Ich habe den Post von Teddy über config.guess (irgendwie) vermisst. Dies sind sehr ähnliche Skripte, aber nicht die gleichen. Ich persönlich benutze shtool auch für andere Zwecke, und es hat für mich ganz gut funktioniert.

6
guns

Dies sollte für alle Distros sicher sein.

$ cat /etc/*release

Das erzeugt so etwas.

     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/"

Extrahieren Sie die Variablen nach Belieben

Hinweis: Bei einigen Setups. Dies kann auch zu Fehlern führen, die Sie ignorieren können.

     cat: /etc/upstream-release: Is a directory
5
R J

Sie können Folgendes verwenden:

OS=$(uname -s)

dann können Sie die OS-Variable in Ihrem Skript verwenden.

5
Chetan kapoor

Nachfolgend ist ein Ansatz zur Erkennung von Debian und RedHat basierend auf Linux OS unter Verwendung von / etc/lsb-release und / etc/os-release) beschrieben (abhängig von der verwendeten Linux-Variante) und führen Sie darauf basierend eine einfache Aktion aus. 

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

Ausgabebeispiel für Ubuntu Linux:

[email protected]$ 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] 
...            
3

Sie können die folgende if-Klausel verwenden und bei Bedarf erweitern:

if [ "${OSTYPE//[0-9.]/}" == "darwin" ]
then
	aminute_ago="-v-1M"
Elif  [ "${OSTYPE//[0-9.]/}" == "linux-gnu" ]
then
	aminute_ago="-d \"1 minute ago\""
fi

2
Tahsin Turkoz

Ich neige dazu, meine .bashrc und .bash_alias auf einer Dateifreigabe zu behalten, auf die alle Plattformen zugreifen können. So besiege ich das Problem in meinem .bash_alias:

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

Und ich habe zum Beispiel eine .bash_alias_Linux mit:

alias ls='ls --color=auto'

Auf diese Weise halte ich plattformspezifischen und portablen Code getrennt. Sie können dasselbe für .bashrc tun

1
ericcurtin

Die folgenden Schritte haben geholfen, die Überprüfung für Ubuntu korrekt durchzuführen:

if [[ "$OSTYPE" =~ ^linux ]]; then
    Sudo apt-get install <some-package>
fi
1
sandman

Dies prüft eine Reihe von known-Dateien, um festzustellen, ob es sich bei der Linux-Distribution um Debian oder Ubunu handelt. Danach wird standardmäßig die Variable $OSTYPE verwendet.

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"
0
Kuzeko

Ich habe die obigen Meldungen in einigen Linux-Distributionen ausprobiert und festgestellt, dass die folgenden für mich am besten funktionieren. Es ist eine kurze, präzise Wortantwort, die auch für Bash unter Windows funktioniert.

OS=$(cat /etc/*release | grep ^NAME | tr -d 'NAME="') #$ echo $OS # Ubuntu
0
intellilogic

versuche dies:

DISTRO=$(cat /etc/*-release | grep -w NAME | cut -d= -f2 | tr -d '"')
echo "Determined platform: $DISTRO"
0