PHP: Auslesen der Logs des Apachen (mehrere)

edit | delete

Autor: Ralf v.d.Mark

eingetragen: Mittwoch, 12. August 2020 um 12:49 Uhr (33/2020 Kalenderwoche)

geändert: Montag, 22. Januar 2024 um 16:43 Uhr (4/2024 Kalenderwoche)

Keywords: Error logdatei apache access debugging reporting Fehlermeldungen

Kategorien: PHP,

Text:

Den Inhalt aus dem Feld Quellcode in eine neue Datei "/php_show_errorlog.php" im public-Ordner speichern führt zum Lesen der Logs (Error/Access) eines jeden ANGEBOTs.


/var/log/httpd/ANGEBOTSNAME.dev.as.ble.de-ssl-error.log
/var/log/httpd/ANGEBOTSNAME.dev.as.ble.de-ssl-access.log


[Thu Mar 26 12:19:57.350770 2020]...


siehe auch "PHP-Error-Meldungen ausgeben"


alte Version "Apache-Error-Log ausgeben"


Und ganz nebenbei zeigt sie auch noch die PHP-Info (phpinfo()) und die Server-Parameter ($_SERVER) an.

Quellcode:  

<?php
/**
 * Diese Datei liest die Error-Logs aus, zeigt PHP-Info und Server-Variablen an.
 *
 * Der Aufruf sollte standardmäßig
 * https://ANGEBOTSNAME.dev.se.ble.de/php_show_errorlog.php
 *
 * PHP version 8
 *
 * @name       php_show_errorlog.php
 *             mit Pfad: php_show_errorlog.php
 * @author     Ralf von der Mark (vdM), Ref. 223 (Entwicklung), BLE <Ralf.vonderMark@BLE.de>
 * @copyright  2024, BLE
 * @version    siehe Konstante VERSION_UND_DATUM, GIT: Yes
 */

define('VERSION_UND_DATUM', '*1.0.4* vom 22.01.2024');

define('VERZNS_LOG_FILES', '/var/log/httpd/');
define('VHOST', $_SERVER['HTTP_HOST']);
define('STANDRD_DATEI_1', VHOST . '-ssl-error.log');
define('STANDRD_DATEI_2', VHOST . '-error.log');
define('NAME_DIESER_DATEI', basename($_SERVER['PHP_SELF']));
define('LOG_TAGE_ZURUECK', 30);

//-- Änderung von Macky Deutsche Uhrzeit setzten
date_default_timezone_set('Europe/Berlin');
setlocale (LC_TIME, "de_DE");

function DownloadGrosseDatei($dateiUndPfad)
{
    //Header manipulieren
    header('Content-Type: application/octet-stream; charset=UTF-8');
    //Jetzt noch Dateiname und Typ festlegen:
    header('Content-Disposition: attachment; filename="' . basename($dateiUndPfad) . '"');
    //Datei als Stream ausgeben
    downloadStueckweise($dateiUndPfad);
    exit();//Stopp!!
}//ENDE: function DownloadGrosseDatei(...)

define('STUECK_GROESSE', 1024 * 1024);//Größe (in bytes) eines Stücks
//Große Datei als Stream byte für byte auslesen
//https://stackoverflow.com/questions/6914912/streaming-a-large-file-using-php
function downloadStueckweise($filename, $retbytes = true)
{
    $buffer = '';
    $cnt = 0;
    $handle = fopen($filename, 'rb');

    if ($handle === false) {
        return false;
    }

    while (!feof($handle)) {
        $buffer = fread($handle, STUECK_GROESSE);
        echo $buffer;
        ob_flush();
        flush();

        if ($retbytes) {
            $cnt += strlen($buffer);
        }
    }

    $status = fclose($handle);

    if ($retbytes && $status) {
        return $cnt; // return num. bytes delivered like readfile() does.
    }

    return $status;
}
if (isset($_GET['submitDownload']) && !empty($_GET['logFile'])) {
    $pfadUndDatei = VERZNS_LOG_FILES . strip_tags($_GET['logFile']);
    if (file_exists($pfadUndDatei)) {
        //Datei vorhanden!
        DownloadGrosseDatei($pfadUndDatei);
    } else {
        //Wenn die Datei nicht vorhanden ist, dann...
        exit('<h1>Sie haben einen Fehler verursacht!</h1>');
    }//ENDE: else ==> if (file_exists())
}//ENDE: if (!empty($_GET['download']))

/**
 * Funktion um eine Byte-Größe in KB, GB etc. umzurechnen
 *
 * @param $groesseRoh
 * @param $stellenHinterKomma
 *
 * @return string
 */
function lesbare_dateigroesse($groesseRoh,
                              $stellenHinterKomma = 2,
                              $htmlTagName = 'span',
                              $htmlTagZusatz = '')
{
    /* VORSICHT: (int) funktioniert auf 32Bit-Systeme nur bis 2.147.483.647 Byte */
    $groesseRoh = (float)$groesseRoh;
    if ($groesseRoh >= 1073741824) {
        $rueckg = round(($groesseRoh / 1073741824), $stellenHinterKomma) . ' GB';
    } elseif ($groesseRoh >= 1048576) {
        $rueckg = round(($groesseRoh / 1048576), $stellenHinterKomma) . ' MB';
    } elseif ($groesseRoh >= 1024) {
        $rueckg = round(($groesseRoh / 1024), $stellenHinterKomma) . ' KB';
    } else {
        $rueckg = $groesseRoh . " Byte";
    }
    return '<' . $htmlTagName . ' title="' . $groesseRoh . ' Bytes"' . $htmlTagZusatz
        . '>' . str_replace('.', ',', $rueckg) . '</' . $htmlTagName . '>';
}/* function lesbare_dateigroesse(...) */

/**
 * Produziert ein Array mit möglichen Dateinamen und Testet, ob diese vorhanden sind.
 * Rückgabe: Listet die gefundenen Dateien sortiert im Array auf!
 * Da das Verzeichnisauflisten für den User verboten ist, muss man es auf diese Weise probieren.
 *
 * PHP version 8
 *
 * @return array
 */
function gibtDateienImArray()
{
    if (!is_dir(VERZNS_LOG_FILES)) {
        echo '<h1 style="font-size: 3em; color: red; background-color: yellow;">
                Achtung: Das Verzeichnis "' . VERZNS_LOG_FILES
            . '" existiert nicht oder ist nicht lesebar!</h1>';
    }//ENDE: if (is_readable(VERZNS_LOG_FILES))
    $vorlageDateienArray = [
        VHOST . '-ssl-access.log',
        VHOST . '-ssl-access.log.1',
        VHOST . '-ssl-error.log',
        VHOST . '-ssl-error.log.1',
        'ssl-error.log',
        'ssl-error.log.1',
        'ssl-access.log',
        'ssl-access.log.1',
        'error_log',
        'error_log.1',
        'access_log',
        'access_log.1'
    ];
    for ($zaehlr = 2; $zaehlr <= LOG_TAGE_ZURUECK; $zaehlr++) {
        $vorlageDateienArray[] = 'ssl-access.log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = 'ssl-error.log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = VHOST . '-ssl-access.log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = VHOST . '-ssl-error.log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = 'access_log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = 'error_log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = VHOST . '-access_log.' . $zaehlr . '.gz';
        $vorlageDateienArray[] = VHOST . '-error_log.' . $zaehlr . '.gz';
    }//ENDE: for ($zaehlr = 1; $zaehlr <= 10; $zaehlr++)
    natsort($vorlageDateienArray);
    /* Dynamischer-Kommentar: Ersten Schraegen (/) der beiden wegloeschen bzw. hinschreiben!
    echo '<br style="display: inline;">
             [$vorlageDateienArray-Array-Count: '.count($vorlageDateienArray).']
         <br style="display: inline;">
             <pre style="display: inline;">Ausgabe des $vorlageDateienArray-'
        .print_r($vorlageDateienArray, true)
        . '</pre>
        <br style="display: inline;">ENDE der $vorlageDateienArray-Array-Ausgabe';
    exit('<br style="display: inline;">exit()');//*/

    $inhalt = [];
    foreach ($vorlageDateienArray as $eineDatei) {
        if (is_file(VERZNS_LOG_FILES . $eineDatei) && is_readable(VERZNS_LOG_FILES . $eineDatei)) {
            $filesize = filesize(VERZNS_LOG_FILES . $eineDatei);
            $filemtime = filemtime(VERZNS_LOG_FILES . $eineDatei);
            if (!defined('START_DATEI')
                && ($eineDatei == STANDRD_DATEI_1 || $eineDatei == STANDRD_DATEI_2)) {
                define('START_DATEI', $eineDatei);
                $standard = 1;
            } else {
                $standard = 0;
            }//ENDE: else ==> if ($eineDatei == STANDRD_DATEI_1 || $eineDatei == STANDRD_DATEI_2)
            $inhalt[$eineDatei] = ['name'      => $eineDatei,
                                   'size'      => $filesize,
                                   'groesse'   => lesbare_dateigroesse($filesize, 2),
                                   'time'      => $filemtime,
                                   'zeitpunkt' => date('d.m.Y H:i', $filemtime),
                                   'standard'  => $standard
            ];
        }//ENDE: if (is_file() && is_readable())
    }
    return $inhalt;
}//ENDE: function gibtDateienImArray(...)

//Loop des Verzeichnisses in Array packen für Selectbox und If-Prüfung
$verzeichnsArray = gibtDateienImArray();
/* Dynamischer-Kommentar: Ersten Schraegen (/) der beiden wegloeschen bzw. hinschreiben!
echo '<br style="display: inline;">
         [$verzeichnsArray-Array-Count: ' . count($verzeichnsArray) . ']
     <br style="display: inline;">
         <pre style="display: inline;">Ausgabe des $verzeichnsArray-'
    . print_r($verzeichnsArray, true)
    . '</pre>
    <br style="display: inline;">ENDE der $verzeichnsArray-Array-Ausgabe';
exit('<br style="display: inline;">exit()');//*/

//Mögliche Lodateien anzeigen
if (isset($_GET['logFile']) && array_key_exists($_GET['logFile'], $verzeichnsArray)) {
    //zum Beispiel: 'biosiegel-int.dev.as.ble.de-ssl-access.log.10.gz':
    define('DATEI_2_DISPLAY', strip_tags($_GET['logFile']));
} elseif (defined('START_DATEI')) {
    //Standardwert!
    define('DATEI_2_DISPLAY', START_DATEI);
} else {
    define('DATEI_2_DISPLAY', 'nix');
}//ENDE: else ==> if (!empty($_POST['logFile']))
$pfadUndDatei4Disply = VERZNS_LOG_FILES . DATEI_2_DISPLAY;

$selectBoxOptions = null;
foreach ($verzeichnsArray as $keyFileName => $werteArray) {
    if (!defined('LOGDATEI_GEFUNDN')
        && empty($_GET['logFile']) && $werteArray['standard'] == 1) {
        $selected = ' selected="selected"';
        $markiert = 'Standard =&gt; ';
    } elseif (!defined('LOGDATEI_GEFUNDN')
        && !empty($_GET['logFile']) && $_GET['logFile'] == $keyFileName) {
        $selected = ' selected="selected"';
        $markiert = '===&gt; ';
    } else {
        $selected = null;
        $markiert = null;
    }//ENDE: else ==> if (empty($_GET['']))
    if ($werteArray['standard'] == 1) {
        $markiert = 'Standard =&gt; ';
    }//ENDE: if ($werteArray['standard'] == 1)
    $selectBoxOptions .= '
        <option value="' . $keyFileName . '"' . $selected . '>' . $markiert
        . $werteArray['name'] . ' (' . $werteArray['zeitpunkt'] . ', ' . $werteArray['groesse']
        . ')</option>';
    if (!defined('LOGDATEI_GEFUNDN') && !empty($selected)) {
        define('LOGDATEI_GEFUNDN', $keyFileName);
    }//ENDE: if (!defined('LOGDATEI_GEFUNDN') && !empty($selected))
}//ENDE: foreach ($verzeichnsArray as $keyFileName => $werteArray)

if (!empty($_GET['php']) && $_GET['php'] === 'info') {
    //Um die PHP-Info anzuzeigen:
    phpinfo(INFO_ALL);
    exit();
}//ENDE: if (!empty($_GET['php']) && $_GET['php'] == 'info')
?><!DOCTYPE html>
<html lang="de">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <title>[Error-Log] <?= VHOST . ', ' . date('Y')
        . ' (Version ' . VERSION_UND_DATUM . ')'; ?></title>
    <style type="text/css">
        div.austausch {
            height: 44px;
            width: 100%;
            text-align: left;
            position: relative;
            padding-left: 22px !important;
            margin-bottom: 6px;
            background-color: #007342;
        }

        div.austausch span {
            display: block;
            overflow: hidden;
            transition: all 500ms ease-in-out;
            height: 44px;
        }

        div.austausch .default {
            color: black;
            background-color: aliceblue;
            /* ADDED */
            position: absolute;
            left: 22px;
            z-index: 10;
            top: 0;
            width: 100%;
            height: 100%;
            padding-left: 10px;
        }

        div.austausch .hover {
            height: 44px;
            color: white;
            background-color: #007342;
        }

        div.austausch:hover .default {
            height: 0px;
        }

        div.austausch a {
            color: white;
            background-color: #007342;
        }
    </style>
</head>
<body><a name="oben" id="oben"></a>
<div class="austausch" title="RELOAD - Datei neu laden...">
    <h1>
        <span class="default">Logdateien zu "<?= VHOST; ?>":</span>
        <span class="hover"><a href="<?= NAME_DIESER_DATEI; ?>"
            >Neustart: Aktuelle Log <?= VHOST; ?> laden...</a></span>
    </h1>
</div><!-- ENDE: <div class="austausch"> -->

<form action="<?= NAME_DIESER_DATEI; ?>" method="get" accept-charset="utf-8">
    <select name="logFile" id="logFile" onchange="this.form.submit();">
        <?= $selectBoxOptions; ?>
    </select>
    <button type="submit" name="submitAnzeign" style="cursor: pointer;">Anzeigen</button>
    &nbsp;
    <button type="submit" name="submitDownload" style="cursor: alias;">Download</button>
</form>
<?php
if (!empty($_GET['php']) && $_GET['php'] === 'server') {
    //Um die PHP-Server-Variablen/Parameter anzuzeigen:
    echo '<br style="display: inline;">
             [$_SERVER-Array-Count: ' . count($_SERVER) . ']
         <br style="display: inline;">
             <pre style="display: inline;">Ausgabe des $_SERVER-'
        . print_r($_SERVER, true)
        . '</pre>
        <br style="display: inline;">ENDE der $_SERVER-Array-Ausgabe';
    exit();
}//ENDE: if (!empty($_GET['php']) && $_GET['php'] == 'server')

if (file_exists($pfadUndDatei4Disply)) {
    echo '
        <h1 style="display: inline; padding-right: 2em;"
            >Error-Log: ' . htmlentities($pfadUndDatei4Disply) . '</h1>
        <a href="#unten" style="border: 2px outset crimson;
                            background-color: aliceblue;
                            margin-left: 3em;
                            padding: 0.3em 1em;
                            text-decoration: none;
                            cursor: ns-resize;"
            >&#11143; nach unten &#11143;</a>
        <hr style="display: inline-block; visibility: inherit; width: 100%;">
        <pre>';
    $fileSizeLog = filesize($pfadUndDatei4Disply);

    if ($fileSizeLog > 5000000) {
        //Wenn die Datei kleiner als x (500000 = 0,5 MB) ist, verarbeiten...
        echo '<h2>Achtung: Die Datei ist mit ' . lesbare_dateigroesse($fileSizeLog, 2) .
            ' zu groß!</h2>';

    } elseif (!defined('LOGDATEI_GEFUNDN')) {
        //da es nur weitergehen kann, wenn das vorhanden ist, wird hier noch mal geprüft.
        echo 'Die Konstante "LOGDATEI_GEFUNDN" ist nicht vorhanden!!';
    } elseif (substr(LOGDATEI_GEFUNDN, -3) === '.gz') {
        //Wenn die Datei kleiner als x (500000 = 0,5 MB) ist, verarbeiten...
        echo '<h2>Hinweis: Die Datei (' . lesbare_dateigroesse($fileSizeLog, 2) .
            ') ist als gzip gepackt und wurde geöffnet!</h2>';

        $gzOpen = gzopen(VERZNS_LOG_FILES . LOGDATEI_GEFUNDN, 'r');
        echo gzread($gzOpen, 5000000);
        gzclose($gzOpen);//Schließt eine geöffnete gz-Datei
    } else {
        $file_handle = fopen(VERZNS_LOG_FILES . LOGDATEI_GEFUNDN, 'rb');
        while (!feof($file_handle)) {
            echo fgets($file_handle);
        }
        fclose($file_handle);
    }//ENDE: else ==> if (!empty())
    echo '</pre>';
    $fund = 1;
}//if (file_exists($pfadUndDatei4Disply))

if (empty($fund)) {
    //Wenn $fund leer ist, wurde keine Datei gefunden!!
    echo '<h1 style="color: red; text-decoration: underline;"
            >Keine Error-Logs gefunden! </h1>
            <h2>Keine Datei gefunden! Auch nicht:
                <br> - <span style="color: blue;">' . VERZNS_LOG_FILES . STANDRD_DATEI_1 . '</span>
                <br> - <span style="color: blue;">' . VERZNS_LOG_FILES . STANDRD_DATEI_2 . '</span>
            </h2>';
}//ENDE: if (empty($fund))
//-- Änderung von Macky Datum auf Deutsch
//-- Vorher mit PHP Funktion: date -> date('D.\, d.m.Y \u\m H:i:s') . ' Uhr
echo '<hr style="display: inline-block; visibility: inherit; width: 100%;">
    <p>Seitenaufruf: ' . date('D, d.m.Y \u\m H:i') . ' Uhr
    <a href="#oben" id="unten" style="border: 2px outset crimson;
                                background-color: aliceblue;
                                margin-left: 2em;
                                padding: 0.3em 1em;
                                text-decoration: none;
                                cursor: ns-resize;"
            >&#11141; nach oben &#11141;</a>
    <a href="?logFile='
    . (defined('LOGDATEI_GEFUNDN') ? urlencode(LOGDATEI_GEFUNDN) : 'nix')
    . '&amp;a=' . time() . '#unten" style="border: 2px outset crimson;
                                background-color: aliceblue;
                                margin-left: 3em;
                                padding: 0.3em 1em;
                                text-decoration: none;
                                cursor: progress;"
            >&#11119; Reload &#11118;</a>
    <a href="' . NAME_DIESER_DATEI . '?php=info" style="border: 2px outset crimson;
                                background-color: blanchedalmond;
                                margin-left: 7em;
                                padding: 0.3em 0.2em;
                                text-decoration: none;
                                cursor: help;"
            >&#128519; PHP-Info anzeigen &#128565;</a>
    <a href="' . NAME_DIESER_DATEI . '?php=server" style="border: 2px outset crimson;
                                background-color: blanchedalmond;
                                margin-left: 3em;
                                padding: 0.3em 0.2em;
                                text-decoration: none;
                                cursor: progress;"
            >&#128519; $_SERVER-Params anzeigen &#128565;</a></p>
    <hr style="display: inline-block; visibility: inherit; width: 100%;">
        <p><strong>Version ' . VERSION_UND_DATUM . ' dieser Datei (' . $_SERVER["SCRIPT_FILENAME"] . ').</strong></p>';

/* Tauscht böse Wörter aus: */
function ripli($wert)
{
    return str_ireplace(chr(87) . chr(69) . chr(66)
        . chr(70) . chr(73)
        . chr(76) . chr(69) . chr(77)
        . chr(65) . chr(78)
        . chr(65) . chr(71) . chr(69)
        . chr(82), 'DATEI',
        str_ireplace(chr(87) . chr(70)
            . chr(77), 'DATEI',
            str_ireplace(chr(86) . chr(68)
                . chr(77), 'i',
                $wert)));
}//ENDE: function ripli(...)
?></body>
</html>