PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Mit PHP das Server-Betriebssystem erkennen

with 5 comments

Häufig möchte man das Betriebssystem des Besuchers erkennen, um beispielsweise Statistiken zu führen. Noch häufiger wird natürlich der Browser abgefragt, aber das ist hier auch nicht gemeint.

In diesem Fall möchte ich das Betriebssystem erkennen, unter dem mein PHP-Script läuft. „Warum willst du das herausfinden, du weißt doch wohl, wo deine Scripte laufen!“ sagt ihr nun? Naja, meistens ja, aber manchmal auch nicht. Und wenn beispielsweise meine Scripte und Webseiten auf beiden Betriebsystemen laufen sollen, muß ich diese Information haben, um einige Dinge zu tun. Ich habe lang überlegt, und wirklich einfache und gebräuchliche Beispiele fallen mir nicht ein, denn zum Beispiel für den php.ini-Trenner bei der include_path-Variablen gibt es eine globale PHP-Konstante, man kann also einfach schreiben:

$include_path = get_include_path();
$include_path.= PATH_SEPARATOR . realpath(__DIR__ . '../'library');
set_include_path($include_path);

(Um im Folgenden alles zu vereinfachen, betrachte ich nur Windows und Linux)

Um Verzeichnisse zu trennen, kann man einfach „/“ nutzen, das funktioniert auch unter Windows (da ist ja eigentlich „\“ gebräuchlich). Oder man nutzt die Konstante DIRECTORY_SEPARATOR.Das Problem mit den unterschiedlichen Zeilenumbrüchen löst man mit PHP_EOL.

Ein Beispiel, wo wir aber betriebssystemspezifisch arbeiten müssen ist beispielsweise das Mapping von Netzlaufwerken via SMB. Macht man zwar nicht alle Tage, aber wenn man in der Firma mit vielen Servern und entfernten Verzeichnissen arbeitet, kommt das schonmal vor. Unter Windows muss man dazu „net use“ benutzen, unter Linux macht man das mit dem „smbclient“ (wenn man dynamisch mappen möchte, sonst verwendet man natürlich direkt einen „statischen“ Mountpoint).

Man benötigt außerdem Informationen über das Betriebssystem, falls man Linux- oder Windows-spezifische Funktionen nutzt wie beispielsweise alle PCNTL-Funktionen oder die win32service-Extension. Außerdem sollte man aufpassen sobald man exec() oder system() benutzt, häufig sind diese dann nicht portabel.

PHP bietet mehrere Möglichkeiten, die aber nicht alle zuverlässig funktionieren. Heute auf der Arbeit habe ich diese Zeile in einem Projekt gefunden:

if (isset($_SERVER['SERVER_SOFTWARE']) && is_numeric(stripos($_SERVER['SERVER_SOFTWARE'], 'linux'))) {

Das sieht nicht nur blöd aus, es funktioniert auch nicht immer, denn auf einigen Linux-Systemen gibt es diese Variable, auf anderen wiederum nicht.
Wenn man auf php.net etwas sucht, findet man die PHP-Konstante PHP_OS:

if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {

PHP_OS enthält das Betriebssystem, auf dem PHP gebuilded wurde (zumindestens wenn man den PHP-Entwicklern glaubt, ein User behauptet hier etwas anderes). Ich weiß nicht, was da zB rauskommt, wenn man PHP für Linux unter cygwin kompiliert. Also auch noch nicht ideal.

Die Funktion meiner Wahl ist derzeit

if (strtoupper(substr(php_uname('s'), 0, 3)) === 'WIN') {

Der Befehl „uname“ kennt man vielleicht schon von Linux, aber auch unter Windows funktioniert php_uname() und liefert die Informationen des Betriebssystems zurück. Genutzt wird diese Funktion auch beispielsweise von PEAR OS_Guess.php. Diese Klasse versucht auch noch weitere Informationen zu gewinnen. Genutzt habe ich sie allerdings noch nicht.

Manche Hoster verbieten jedoch diese Funktion. Also immer dran denken:

if (function_exists('php_uname')) {</code><code>

Man muss wohl doch PHP_OS nutzen.  Oder man schreibt sich eine Funktion, die zB anhand des DIRECTORY_SEPARATOR die Unterscheidung macht. Oder oder oder…

Warning: php_uname() has been disabled for security reasons in /usr/www/...

Mit PHP 5.3 kommen jetzt auch noch ein paar weitere globale Konstanten hinzu, die es wohl nur unter Windows gibt. Daran könnte man es dann auch festmachen. Dann braucht man aber Minimum 5.3, was man wohl in den nächsten Jahren noch nicht überall auf der Welt erwarten kann. Geht also auch nicht.

So oder so, das ganze Thema ist irgendwie konfus. Welchen Best-Practice habt ihr?

Written by Michael Kliewe

August 10th, 2009 at 6:17 pm

Posted in PHP

5 Responses to 'Mit PHP das Server-Betriebssystem erkennen'

Subscribe to comments with RSS or TrackBack to 'Mit PHP das Server-Betriebssystem erkennen'.

  1. Wenn du nur Windows und Linux betrachtest – wie wäre es mit:


    $isWindows = false;
    if ( '\' === PATH_SEPARATOR )
    {
    $isWindows = true;
    }

    Schneller als jedes uname()…

    Schöne Grüße

    Thomas

    Thomas

    10 Aug 09 at 22:40

  2. Man könnte theoretisch doch auch über phpinfo() das OS auslesen oder?

    Also die Ausgabe von phpinfo() in eine Variable schreiben …

    ob_start();
    phpinfo();
    $info = ob_get_contents();
    ob_end_clean();

    und dann Zeile für Zeile durchgehen und prüfen ob die „System“ Ausgabe gefunden wurde.

    Etwas umständlich, aber vermutlich eine Möglichkeit. Habs aber selbst noch nicht ausprobiert.

    Michael

    11 Aug 09 at 20:40

  3. @Thomas: Ja, ich habe in diesem Blog-Artikel nur Windows und Linux betrachtet.
    Deine Lösung dürfte so nicht funktionieren, denn der PATH_SEPARATOR ist entweder „;“ oder „:“. Er ist dafür da, den include_path zu ergänzen oder zu ersetzen.
    Du meinst den DIRECTORY_SEPARATOR, damit dürfte dein Code funktionieren. Aber irgendwie find ich das noch unschön ehrlich gesagt, es nur daran festzumachen…

    @Michael: Das geht sicherlich auch. Die meisten Informationen aus der phpinfo() stehen aber auch in den Superglobals: http://de2.php.net/manual/en/language.variables.superglobals.php

    Michael Kliewe

    12 Aug 09 at 17:32

  4. // get operatingsystem
    011 $agent=$_SERVER[‚HTTP_USER_AGENT‘];
    012 $os =“Unbekannt“;
    013
    014 if (strstr($agent, „Windows 98″)) $os=“Windows 98“;
    015 elseif (strstr($agent, „NT 4.0“)) $os=“Windows NT „;
    016 elseif (strstr($agent, „NT 5.1″)) $os=“Windows XP“;
    017 elseif (strstr($agent, „NT 6.0″)) $os=“Windows Vista“;
    018 elseif (strstr($agent, „NT 6.1″)) $os=“Windows 7“;
    019 elseif (strstr($agent, „NT 6.2″)) $os=“Windows 8“;
    020 elseif (strstr($agent, „Mac“)) $os=“Mac OS“;
    021 elseif (strstr($agent, „Linux“)) $os=“Linux“;
    022 elseif (strstr($agent, „Unix“)) $os=“Unix“;
    023

    Damit hat an wenigstens die Spezifischen Windowsversionen, nur bie linux und Mac OS bin ich noch nicht so weit ;/

    SpeeFak

    1 Feb 13 at 06:06

  5. mein Anwendungsfall:

    setlocale(„german“); //Linux: setlocale(„de_DE“);

    René

    11 Sep 16 at 22:36

Leave a Reply

You can add images to your comment by clicking here.