Freier Speicher (df -h) anzeigen via PHP!

  • Hi Leute ich habe ein "kleines" PHP-Script geschrieben was mir die Speicher Belegung auf meinen am RPI angeschlossenen Datenträger anzeigt.


    da ich noch nicht so viel Erfahrung mit PHP habe wollte ich 1-2 fragen los werden:


    1) sieht die Darstellung bei euch auch so aus? Sprich könnt ihr die Seite Mal ausprobieren.


    2) hat jemand Verbesserung vorschlägt?


    Vorschau Bild:


    Der PHP Code (Die Komplette Seite):


    das Script Separat (ohne HTML):


    :danke_ATDE:

    Rechtschreibfehler sind Special Effects meiner Tastatur
    [font="Arial"]Pater dimitte illis non enim sciunt quid faciunt![/font]
    @sagte der Pi bevor er in Rauch auf ging:@
    Vater, vergib ihnen den sie Wissen nicht was sie tun!

    Edited once, last by C.And ().

  • Auf den ersten Blick fällt mir der blendede Hintergrund auf, wenn man dann wieder auf weisse Fläche guckt dauerts nen bischen bis die Augen das auch wieder als "weiss" wahrnehmen :D Aber ansonsten siehts sehr gut aus


    Zum Code:


    anstatt shell_exec(); nutze ich immer exec(); da die Ausgabe gleich in ein Array zurück gegeben wird, also entweder
    $array = exec('df -h');
    oder
    exec('df -h', $array);


    ggf kannst du auch mit nur "df" arbeiten und die werte selber umrechnen lassen mit zB:
    [code=php]
    function get_size($size,$precision=2,$long_name=true,$real_size=true) {
    $base=$real_size?1024:1000;
    $pos=0;
    while ($size>$base) {
    $size/=$base;
    $pos++;
    }
    $prefix=get_size_prefix($pos);
    $size_name=$long_name?$prefix."bytes":$prefix[0].'B';
    return round($size,$precision).' '.ucfirst($size_name);
    }


    function get_size_prefix($pos) {
    switch ($pos) {
    case 00: return "";
    case 01: return "Kilo";
    case 02: return "Mega";
    case 03: return "Giga";
    case 04: return "Tera";
    case 05: return "Peta";
    case 06: return "Exa";
    case 07: return "Zetta";
    case 08: return "Yotta";
    case 09: return "Xenna";
    case 10: return "W-";
    case 11: return "Vendeka";
    case 12: return "u-";
    default: return "?-";
    }
    }
    [/php]
    Der Aufruf könnte dann zum Beispiel so aussehen:
    echo get_size(filesize("/var/log/syslog"));
    Wenn du nur eine Stelle hinterm Komma haben willst dann:
    echo get_size(filesize("/var/log/syslog"), 1);


    eregi_replace ist veraltet, das solltest du am besten nicht mehr benutzen, nimm stattdessen str_replace die Syntax kann so bleiben wobei du ggf Probleme kriegen könntest wenn sich die Position der Chars verändert das hast du ja leider zzt "hardcoded" ($START und $END)


    ereg ist ebenfals veraltet .. Siehe: http://www.php.net/manual/de/function.ereg.php


    Bei der Tabelle kannst du für die Überschrift auch " th " nutzen, das ist dafür eigentlich vorgesehen ;) Dann könnte vermutlich auch der style center wegfallen



    Btw: wenn oben mit <?php gestartet wird brauchst du eigentlich nicht 4 leerzeichen setzen und den html code brauchst auch nicht so weit rechts packen, aber das nur nebenbei, kannste auch ignorieren ;)

  • hauptsächlich geht es mir darum ob die Position der Chars bei jedem Stimmen!
    war mein erster versuch mit dem Parse der geklapt hat ;)
    der Style ist halt geschmacksache... ;) (Hilft mir dabei die Test Seiten [Himbeerfaben] & Fertigen Seiten zu unterscheiden [Dark])


    exec() gibt in einer Array aus ??? das erklärt warum ich dabei immer nur die Letzte Zeile bekam...
    weshalb ich dann die $var = `befehl` variante genommen habe!
    werde ich aber mal testen!

    Rechtschreibfehler sind Special Effects meiner Tastatur
    [font="Arial"]Pater dimitte illis non enim sciunt quid faciunt![/font]
    @sagte der Pi bevor er in Rauch auf ging:@
    Vater, vergib ihnen den sie Wissen nicht was sie tun!

    Edited once, last by C.And ().


  • exec() gibt in einer Array aus ??? das erklärt warum ich dabei immer nur die Letzte Zeile bekam...


    Ja das kannst du auf der Konsole folgendermassen testen:

    Code
    php -r 'exec("df", $array); foreach($array AS $a) { echo "$a\n"; }'


    Um die erste Zeile aus dem Array zu löschen:

    Code
    php -r 'exec("df", $array); array_shift($array); foreach($array AS $a) { echo "$a\n"; }'


    Über exec(); kann man sich auch einen möglichen Exit-Code ausgeben lassen, falls der Befehl nicht funktionierte oder nicht existiert - das wäre dann:

    Code
    php -r 'exec("hallo" ,$array, $return_var); if ($return_var) { echo "$return_var\n"; }'


    127 bedeutet "command not found"


    Mehr dazu steht hier: http://php.net/manual/de/function.exec.php


    [hr]


    Inspiriert durch dein Vorhaben hab ich das auch mal programmiert und komme mit weniger Code aus - denke auch das wäre so besser weil es dann keine Probleme mit den Chars gibt ( kein $START oder $END )

    [/spoiler]


    Mit HTML sieht das bei mir so aus:
    [code=php]
    # Display Free Space
    if (isset($DISPLAYfreespace) AND $DISPLAYfreespace == 1) {
    $FreeSpace ="<table id='FreeSpace' cellspacing='0' border='1px'>\n";
    $FreeSpace.="<tr><th colspan='6'>Free Space on: ".$_SERVER['SERVER_NAME']."</th></tr>\n";
    $FreeSpace.="<tr style='font-weight:bold; text-align:center;'>\n";
    $FreeSpace.="<td> Filesystem </td><td> Size </td><td> Used </td><td> Free </td><td> % Used </td><td> Mountpoint </td>\n";
    $FreeSpace.="</tr>\n";
    exec("df -h", $DiskFree);
    array_shift($DiskFree);
    foreach ($DiskFree AS $DFline) {
    $c=0;
    $FreeSpace.="<tr>\n";
    foreach(explode(" ",$DFline) AS $DFrow) {
    if (empty($DFrow) AND $DFrow !== "0") { continue; }
    ++$c;
    $DFrow = str_replace("B"," B",$DFrow);
    $DFrow = str_replace("K"," KB",$DFrow);
    $DFrow = str_replace("M"," MB",$DFrow);
    $DFrow = str_replace("G"," GB",$DFrow);
    if ($c >= "2" AND $c != "6") { $td="<td style='text-align:right;'>"; } else { $td="<td>"; }
    $FreeSpace.="".$td." ".$DFrow." </td>";
    }
    $FreeSpace.="\n</tr>\n";
    }
    $FreeSpace.="</table>\n";
    }
    [/php]


    Sieht dann so aus:


    [hr]


    Und noch eine kleine Anpassung weil mich das " 5.0 " gestört hat:
    [code=php]
    # Display Free Space
    if (isset($DISPLAYfreespace) AND $DISPLAYfreespace == 1) {
    $FreeSpace ="<table id='FreeSpace' cellspacing='0' border='1px'>\n";
    $FreeSpace.="<tr><th colspan='6'>Free Space on: ".$_SERVER['SERVER_NAME']."</th></tr>\n";
    $FreeSpace.="<tr style='font-weight:bold; text-align:center;'>\n";
    $FreeSpace.="<td> Filesystem </td><td> Size </td><td> Used </td><td> Free </td><td> % Used </td><td> Mountpoint </td>\n";
    $FreeSpace.="</tr>\n";
    exec("df -h", $DiskFree);
    array_shift($DiskFree);
    foreach ($DiskFree AS $DFline) {
    $c=0;
    $FreeSpace.="<tr>\n";
    foreach(explode(" ",$DFline) AS $DFrow) {
    if (empty($DFrow) AND $DFrow !== "0") { continue; }
    ++$c;
    if ($c > "1" AND $c != "6" AND $pos = strpos($DFrow,".0")) {
    $prefix = substr($DFrow,-1);
    $DFrow = "".substr($DFrow,0,$pos)."".$prefix."";
    }
    $DFrow = str_replace("B"," B",$DFrow);
    $DFrow = str_replace("K"," KB",$DFrow);
    $DFrow = str_replace("M"," MB",$DFrow);
    $DFrow = str_replace("G"," GB",$DFrow);
    if ($c >= "2" AND $c != "6") { $td="<td style='text-align:right;'>"; } else { $td="<td>"; }
    $FreeSpace.="".$td." ".$DFrow." </td>";
    }
    $FreeSpace.="\n</tr>\n";
    }
    $FreeSpace.="</table>\n";
    }
    [/php]


    Sieht dann so aus:

  • Quote


    Inspiriert durch dein Vorhaben....


    findet es jezt auch einzug in deine SYS INFO ?
    Ok jetzt habe ich (wieder) das Problem das bei Vielen meiner USB-Medien Lehrzeichen im Namen sind.


    wodurch die Tabelle unschön wird deshalb habe ich das Parse via $start - $end gemacht habe...


    Porblem no.2
    er macht aus GB-SB-WD -> GB B-S B-WD & aus Stick -> Stic kB
    werde aber heute Abend\Nacht auch mal gucken ob ich das selber mit DEINER $c Variabel gebacken kriege.



    PS. ein echo $FreeSpace; hätte mir eine 1/4 Stunde böhse Worte erspart! ;) #$&%!☼♫♠§$&# (Asterix :D)


    dafür weiß ich jetzt was es mit
    $FreeSpace.="Tri tra\n"; $FreeSpace.="bla bal\n"; $FreeSpace.="blub blub\n"; $FreeSpace.="li la lu\n";
    auf sich hat :D wieder was dazu gelernt :D

    Rechtschreibfehler sind Special Effects meiner Tastatur
    [font="Arial"]Pater dimitte illis non enim sciunt quid faciunt![/font]
    @sagte der Pi bevor er in Rauch auf ging:@
    Vater, vergib ihnen den sie Wissen nicht was sie tun!

    Edited once, last by C.And ().

  • Ich würde die Daten anders abfragen:


    Dein df dafür benutzen um nur die 1. Spalte mit dem Gerätenamen auszulesen und dann gezielt auf das Device abrufen und mit einem Array abfragen. Dann hast Du auch Leerzeichen im Namen in einem Feld und nicht gesplittet.



    PHP
    <?php 
    ...
    # Schleife durch Dein Array und dann das Device ausslesen
    foreach ..... # und dann $devicename füllen.
    $pipes = array(); 
    exec('df ' . $devicename , $pipes ); 
    var_dump( "<pre>", var_dump ( $pipes ), $pipes[1], "</pre>"); 
    ...
    ?>



    Wieso benutzt Du nichts fertiges?
    PHP: http://rk4an.github.io/phpsysinfo/
    Perl: http://www.coder-world.de/cw/s…pagewebdesignsysinfo.html

  • Code
    Wieso benutzt Du nichts fertiges?


    ganz einfach: ICH will PHP lernen und ICH will es selber machen. (Fertig kaufen kan jeder ;))

    Rechtschreibfehler sind Special Effects meiner Tastatur
    [font="Arial"]Pater dimitte illis non enim sciunt quid faciunt![/font]
    @sagte der Pi bevor er in Rauch auf ging:@
    Vater, vergib ihnen den sie Wissen nicht was sie tun!


  • findet es jezt auch einzug in deine SYS INFO ?


    ne in meine cpu.php :D



    Ok jetzt habe ich (wieder) das Problem das bei Vielen meiner USB-Medien Lehrzeichen im Namen sind.


    Leerzeichen sollte man tunlichst vermeiden, sowohl in Datei als auch Verzeichniss-Namen




    Porblem no.2
    er macht aus GB-SB-WD -> GB B-S B-WD & aus Stick -> Stic kB
    werde aber heute Abend\Nacht auch mal gucken ob ich das selber mit DEINER $c Variabel gebacken kriege.


    Jop, über $c kannst du das regeln, dass str_replace nur in row 2, 3 und 4 angewandt wird
    Aber ein kleingeschriebenes " k " dürfte er eigentlich nicht ersetzen, str_replace ist case-sensitiv - das kannst du so prüfen:

    Code
    php -r 'echo str_replace("k","k","KBytes");
    php -r 'echo str_ireplace("k","k","KBytes");'


    ersteres gibt
    " KBytes" aus
    aber das zweite
    " kBytes "





    PS. ein echo $FreeSpace; hätte mir eine 1/4 Stunde böhse Worte erspart! ;) #$&%!☼♫♠§$&# (Asterix :D)



    hehe - ooops :blush:




    Ich würde die Daten anders abfragen:


    Dein df dafür benutzen um nur die 1. Spalte mit dem Gerätenamen auszulesen und dann gezielt auf das Device abrufen und mit einem Array abfragen. Dann hast Du auch Leerzeichen im Namen in einem Feld und nicht gesplittet.


    Das ist zu umständlich, es gibt zwar die php Befehle ' disk_total_space ' und ' disk_free_space ' aber da fehlt dann weiterhin der Mountpoint und die prozentuale Berechnung - warum man das alles in PHP regeln sollte wenn man das auch über ein exec kriegt is halt gerade für Anfänger etwas übertrieben ;)
    Vorallem verursacht >5x "df" ausführen mehr Last als nur 1x

  • Das ist zu umständlich, es gibt zwar die php Befehle ' disk_total_space ' und ' disk_free_space ' aber da fehlt dann weiterhin der Mountpoint und die prozentuale Berechnung - warum man das alles in PHP regeln sollte wenn man das auch über ein exec kriegt is halt gerade für Anfänger etwas übertrieben ;)
    Vorallem verursacht >5x "df" ausführen mehr Last als nur 1x


    Das mag da dran liegen das ich mich eh an dem exec störe. Das Script wird irgendwann mal erweitert, z.B. man kann dann Mountpoints anklicken für weitere Infos und GET-Requests werden nicht geparsed (Unwissenheit oder Faulheit). Jemand kann dann weitere Befehle per Injection einschleusen.


    Dann doch lieber die PHP Funktionen benutzen und ein Dreisatz über total_space und free_space sollte ja nicht so das Hindernis sein.


    /paranoia :D


  • Das mag da dran liegen das ich mich eh an dem exec störe. Das Script wird irgendwann mal erweitert, z.B. man kann dann Mountpoints anklicken für weitere Infos und GET-Requests werden nicht geparsed (Unwissenheit oder Faulheit). Jemand kann dann weitere Befehle per Injection einschleusen.


    aha?
    ich seh da keine GET Requests - wenn du auch an sowas bastelst dann musst du das eben anders lösen wie zB über POST oder ansonsten kann man sowas natürlich auch filtern, aber dabei wär fraglich wieso man das in einem LAN machen sollte ;)



    Dann doch lieber die PHP Funktionen benutzen und ein Dreisatz über total_space und free_space sollte ja nicht so das Hindernis sein.


    Naja wie gesagt fehlt dann aber immernoch die Information des Dateisystems da man "disk_total_space" usw nur mit dem Mountpoint nutzen kann


    Sicherlich ist "natives" php besser bzw schneller als son gemischtes php script was haufenweise shellbefehle ausführt usw, aber man muss es nicht gleich von anfang an übertreiben ;)


  • aha?
    ich seh da keine GET Requests - wenn du auch an sowas bastelst dann musst du das eben anders lösen wie zB über POST oder ansonsten kann man sowas natürlich auch filtern, aber dabei wär fraglich wieso man das in einem LAN machen sollte ;)


    Ich habe nicht geschrieben das es in dem Script so gemacht wird. Aber es ist doch immer so, das Script ist da, man will noch mehr und erweitert es. Dann gibt es auf einmal die Möglichkeit per GET oder POST weitere Sachen abzufragen.


    Woher willst Du wissen das der Webserver auf dem das jetzt läuft nicht im Netz steht oder bald im Netz stehen wird. Da kommt dann noch etwas anderes drauf, das für alle erreichbar ist und keine denkt an dieses niedliche kleine SysStat-Script was dann auch auf einmal offen im Internet steht.


    Und ob GET oder POST ist mir reichlich schnuppe, curl + DATA-String schickt mir auch den POST mit urlencoded "?mount=/mnt/usb;rm -rf /" an den Webserver.


    Du wirst vielleicht allow, deny im Webserver konfigurieren, der nächste der sich das auch auf seinen PI kopiert macht vielleicht erst seit ein paar Tagen/Wochen mit Linux rum, der kennt das noch nicht.


    Darum geht es mir. Wieso nicht sauber und sicher programmieren?

  • Wieso nicht sauber und sicher programmieren?


    Was hier bischer gepostet wurde ist imho sicher :)


    Ich seh da aber auch kein Grund das jetzt noch wie in einem Dateimanager zum anklicken zu erweitern - mach mal nicht aus ner Mücke einen Elefanten ;)




    PS: Um solche Injections - wie sie ruedigerp erwähnt hat - zu verhindern, einfach die $_POST oder $_GET übergabe auf ";" oder "&&" prüfen und rausfiltern

  • Hi,
    Habe gerade mal alle neuen Posts überflogen!
    zur Info:
    • 1. Ja der Server ist aus dem Netz erreichbar, aber alle SYSTEM INFO Seiten nur aus dem Lokalem Netz. und kommen ohne GET o. POST aus!
    (Bin ja nicht "ganz" dumm ;) und zeige Gott und der weld was an meinem Server angeschlossen ist!)
    sirhe Code Beispiel:


    • 2. Die Seite soll NUR den Speicher verbrauch anzeigen! eine Seite Für Temperaturen und so weiter ...
    (also ist es sehr unwahrscheinlich das da was Kritisches verändert wird)


    • keine Lehrzeichen ich weiß .:angel:
    (Habe aber wenig Lust 13 Sticks, 4 USB-HDDs + x SD-Cards & xxx Filme Umzubenennen :no_sad:)
    Trotzdem danke für die Hinweise :heart:
    4. die Fertigen Lösungen sind mir zu Groß und zu langsam. (und nicht unbedingt vertrauenswürdig)

    Rechtschreibfehler sind Special Effects meiner Tastatur
    [font="Arial"]Pater dimitte illis non enim sciunt quid faciunt![/font]
    @sagte der Pi bevor er in Rauch auf ging:@
    Vater, vergib ihnen den sie Wissen nicht was sie tun!

    Edited once, last by C.And ().