Hilfe zur Fehlerbehandlung

In PHP intern gibt es verschiedene Schweregrade von Fehlermeldungen. Unterschieden werden diese in die Hauptkategorien Hinweis (E_NOTICE), Warnung (E_WARNING) und schwerwiegender Fehler (E_ERROR).
Das mit der Version 2.1 eingeführte error_reporting = E_ALL zeigte bei mir einige unsauber erstellte Scripte auf. Um Fehler schneller zu finden und nicht das Logfile von IPS durchsuchen zu müssen oder nach dem Neustart der Konsole schnell den Zugriff auf aufgetretende Dinge zu haben, möchte ich hier eine Möglichkeit zeigen dies im Konsolenausgabefenster, Dashbaord oder Webfront zu machen.
Dabei werden alle PHP Fehler in ein Logfile geschrieben. (Nur von PHP erzeugte Fehler!)

[b]1. folgende Einträge in der php.ini Kategorie

 hinzufügen:[/b]

log_errors = On
error_log = C:\IP-Symcon_Ver2\error.log


Der IPS Pfad ist natürlich entsprechend anzupassen.

[b]2. PHP Script anlegen+String Variable zur Ausgabe:[/b]

```php

<?

	//-------------------------------------- ID´s -------------------------------

	$id_log_ausgabe               = 12345; //ID der String Variable welche Fehler speichert

	//---------------------------------------------------------------------------
	
	$file =  IPS_GetKernelDir()."error.log";
    $logfile = file_get_contents($file); //Logfile in variable einlesen
    SetValueString($id_log_ausgabe, $logfile);
    echo $logfile; //Ausgabe in der Konsole
?>

Für die Ausgabe im Dashboard habe ich einfach ein Memofeld benutzt.

guter Ansatz - Alernative per eigenem error handler in einer autoprepend datei:

in php.ini z.B. folgendes einfügen:

auto_prepend_file = "d:/IPS2/scripts/autoprepend.php"

Hinweis: bei mir absoluter Pfad notwendig, da sonst webfront aussteigt

in der datei autoprepend.php dann folgendes:


function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) 
{
    $ce=error_reporting();
    if ($ce == 0) {return false;}   // sortiert fehlermeldungen, die eigentlich durch @ unterdrueckt werden sollten, aus

    $errortype = array (
                E_ERROR              => 'Error',
                E_WARNING            => 'Warning',
                E_PARSE              => 'Parsing Error',
                E_NOTICE             => 'Notice',
                E_CORE_ERROR         => 'Core Error',
                E_CORE_WARNING       => 'Core Warning',
                E_COMPILE_ERROR      => 'Compile Error',
                E_COMPILE_WARNING    => 'Compile Warning',
                E_USER_ERROR         => 'User Error',
                E_USER_WARNING       => 'User Warning',
                E_USER_NOTICE        => 'User Notice',
                E_STRICT             => 'Runtime Notice',
                //E_RECOVERABLE_ERROR  => 'Catchable Fatal Error'
                );

    $errname=$errortype[$errno];
    $dt = date("d.m.Y H:i:s");
    $err=$dt." | ".$errname." ".$errno." | ".$errmsg." | ".$filename." | line:".$linenum."
";

    $contents=$err.GetValueString(32407);  // hier id der IPS string variablen angeben, in der der log gespeichert werden soll
 
    if (substr_count($contents,"
") > 50) {  // wenn mehr als 50 zeilen, dann die letzten 10 loeschen
	$xx=explode("
",$contents);
	for ($i = 1; $i <= 10; $i++) {
    	array_pop($xx);
	} 
	$contents=implode("
", $xx);  // hier id der IPS string variablen angeben, in der der log gespeichert werden soll
    }
    SetValueString(32407,$contents);   
    error_log($err, 3,IPS_GetKernelDir()."errorlog/error.log");  // sepcihert error in log datei
    return false;
}
$old_error_handler = set_error_handler("userErrorHandler",6);

Die letzte Zeile, die wegen autoprepend von jedem script zuallererst ausgeführt wird, biegt den php error handler auf den eigenen „userErrorHandler“ um, in dem man dann auf den Fehler reagieren kann, wie man will.

„return false“ bewirkt, dass in jedem Fall danach noch an den php eigenen error handler weitergeleitet wird

Anzeige des Logs im Designer dann mit MemoFeld auf Stringvaraibale 32407 (ggf. ID ersetzen) - wie im vorherigen Beitrag gezeigt.

Der usererrorhandler kann z.B. dann auch genutzt werden, um Fehlerklassen zu filtern und bei kritischen Fehlern z.B. auch automatisch eine email zu versenden - siehe PHP Dokumentation

Viele Grüße
Dirk

hier noch mal eine Variante zum löschen der Logdatei.

[ul]
[li]DummyInstanz anlegen[/li][li]Stringvariable mit Profil ~HTML_Box anlegen[/li][li]Boolvariable mit eigenem Profil anlegen[/li][li]IPS-Dienst beenden[/li][li]php.ini anpassen und speichern, Dienst starten[/li][/ul]

register_globals = on
error_reporting = E_ALL
log_errors = On
error_log = C:\IP-Symcon\error.txt

Ids der Variablen im Script anpassen. Boolvariable dem Script zuweisen(Eigene Aktion). Script verstecken. Ereignis dem Script hinzufügen.

Bei klick auf die Boolvariable wird die Logdatei gelöscht und bei einem Fehler wieder neu angelegt und angezeigt.

<?
$logAusgabe = 31555 /*[System Error Logs\Meldungen]*/; //ID String HTML-Box Variable welche Fehler speichert
$reset = 35687 /*[System Error Logs\Log]*/; // ID Boolvariable Log

if(file_exists(IPS_GetKernelDir()."error.txt"))
{
   $file = IPS_GetKernelDir()."error.txt";
   $logfile = file($file);
   $log = "";
   foreach($logfile as $lines => $line)
    {
        $log .= "<p>"."Meldung ".$lines."<b style='color:#FF0000;'> ".$line."</b><br></p>";
   }
   SetValue($logAusgabe, $log);
    SetValue($reset, false);
}

if($IPS_SENDER == "WebFront")
{
    if(file_exists(IPS_GetKernelDir()."error.txt"))
    {
       unlink(IPS_GetKernelDir()."error.txt");
       SetValueString($logAusgabe, "");
        SetValue($reset, true);
    }
}

?>

Hallo Rainer,

wenn ich die Änderungen in der php.ini wie oben angegeben umsetze, gehen meine WebFronts nicht mehr?? :eek:
Hast Du ne Ahnung, was da los sein kann?

Gruß
dfhome

Wie sieht denn deine ini aus.

Die ini sollte nicht wie oben gezeigt aussehen, sondern ergänzen oder ändern.
Alles andere so lassen wie es ist.

Hi,
ja, natürlich hab ich nur ergänzt.
Hier mal meine ini ohne die Änderungen:

extension_dir=C:\IP-Symcon\ext\
extension=php_imap.dll

```php

register_globals=on
error_reporting=E_ALL
max_execution_time=30
extension_dir=C:\IP-Symcon\ext
extension = php_curl.dll
extension = php_gd2.dll
extension = php_gettext.dll
extension = php_imap.dll
extension = php_soap.dll
[DATE]
date.timezone="Europe/Berlin"

die stimmt doch auch schon nicht. Da ist etwas doppelt:

so sollte sie in etwa aussehen. entsprechend deiner Extension.


```php

extension_dir =C:\IP-Symcon\ext
max_execution_time = 180
register_globals = on
error_reporting = E_ALL
log_errors = On
error_log = C:\IP-Symcon\error.txt
extension = php_curl.dll
extension = php_gd2.dll
extension = php_gettext.dll
extension = php_http_ips.dll
extension = php_mbstring.dll
extension = php_mysql.dll
extension = php_pdo_sqlite.dll
extension = php_soap.dll
extension = php_sockets.dll
extension = php_sqlite.dll
[DATE]
date.timezone = "Europe/Berlin"

Grad nochmal weitergetestet: wenn ich die Pfadangabe weg lasse, funktioniert wieder alles…?

Nachtrag: wenn ich es so wie oben mache, klappt´s, Danke. Frag mich nur, wo das außerhalb der PHP-Deklaration herkommt…

Aber vielen Dank für die schnelle Hilfe! :slight_smile:

IDs anpassen. Sounddatei und Image anpassen.

<?
// IDs der Variablen/Instanzen/Timer anpassen!
$logID = 31555 /*[System Error Logs\Meldungen]*/; //ID String HTML-Box Variable welche Fehler speichert
$resetID = 35687 /*[System Error Logs\Log]*/; // ID Boolvariable Log
$timer = 32038 /*[System Error Logs\ErrorLogs\]*/;
$event = 46748 /*[System Error Logs\ErrorLogs\]*/;
$mpID = 34902 /*[.Sprachausgabe\Media Player]*/;
$wfcID = 43661 /*[WebFront Configurator]*/;
$ttsID = 28627 /*[.Sprachausgabe\Text To Speech]*/;

if($IPS_SENDER == "WebFront")
{
    if(file_exists(IPS_GetKernelDir()."error.txt"))
    {
       unlink(IPS_GetKernelDir()."error.txt");
       SetValue($logID, "");
        SetValue($resetID, true);
        IPS_SetScriptTimer($IPS_SELF, 0);
    }
}

if($IPS_SENDER == "TimerEvent")
{
    if($IPS_EVENT == $event)
    {
        if(file_exists(IPS_GetKernelDir()."error.txt"))
        {
           $logfile = file(IPS_GetKernelDir()."error.txt");
           $log = "";
           foreach($logfile as $lines => $line)
            {
                $log .= "<p>Meldung ".$lines."<b style='color:#FF0000;'> ".$line."</b></p>";
           }
           SetValue($logID, $log);
            SetValue($resetID, false);
            $time = date("H:i");
            if(($time > "23:00") || ($time < "05:00")) 
            {
               WFC_SendNotification($wfcID, "*** Systemmeldung ***", "PHP Fehler!", "File_Edit_32", 10);
            }
            else
            {
               IPS_SetScriptTimer($IPS_SELF, 3);
                WAC_SetVolume($mpID, 100);
                WAC_PlayFile($mpID, "media/Airport_Gong.mp3");
                WFC_SendNotification($wfcID, "*** Systemmeldung ***", "PHP Fehler!", "File_Edit_32", 10);
            }
        }
    }
    if($IPS_EVENT == $timer)
    {
       TTS_Speak($ttsID, "Systemmeldung", false);
       IPS_SetScriptTimer($IPS_SELF, 0);
    }
}

?>

Wer kein Bock hat das Skript von Post 1 wegen Faulheit zu installieren, der kann das hier nehmen. Aber nicht meckern, bin kein PHP Guru.

<?
if($IPS_SENDER == "Execute")

      echo "===========================================================
     Achtung, bitte PHP.INI anpassen.

					register_globals = on
					error_reporting = E_ALL
					log_errors = On
					error_log = C:\IP-Symcon\error.txt
";
{
		$DummyID = @IPS_GetInstanceIDByName("Error_Log", $parentID); // Überprüfung ob Dummy Modul schon vorhanden
		if ($DummyID === false){

		// Anlegen eines Dummy Moduls mit dem namen "Error_Log"
		$parentID = IPS_GetObject($IPS_SELF);
		$parentID = $parentID['ParentID'];

		$instancID = @IPS_GetInstanceIDByName("Error_Log", $parentID);
		if ($instancID === false) {
			$instancID = IPS_CreateInstance("{485D0419-BE97-4548-AA9C-C083EB82E61E}"); // UID vom Dummy Modul
			IPS_SetName($instancID, "Error_Log");
			IPS_SetParent($instancID, $parentID);
			IPS_SetParent($IPS_SELF, $instancID);
			IPS_SetName($IPS_SELF, "Startskript");
			IPS_SetHidden($IPS_SELF, true);
			echo "Dummy Modul wurde angelegt. die ID lautet: ". "$instancID
";

		// Anlegen der Bool Variablen mit Profil und Association
      $VarID = @IPS_GetInstanceIDByName("Fehlermeldung", $parentID);
      if ($VarID === false)  {
         $VarID = IPS_CreateVariable(0);
         IPS_SetName($VarID, "Fehlermeldung");
			IPS_SetParent($VarID, $instancID);
	      IPS_CreateVariableProfile("ErrorLog", 0);
			IPS_SetVariableProfileAssociation("ErrorLog", 1, "Keine Einräge", "");
			IPS_SetVariableProfileAssociation("ErrorLog",0, "Löschen", "");
			IPS_SetVariableCustomProfile($VarID, "ErrorLog");
			IPS_SetVariableCustomAction($VarID, $IPS_SELF);
         SetValue($VarID, true);
         echo "Profil ErrorLog wurde angelegt. die ID lautet: ". "$VarID
";

			// Anlegen der String Variable mit Profil ~HTMLBOX
      $meID = @IPS_GetInstanceIDByName("Log`s", $parentID);
      if ($meID === false)  {
         $meID = IPS_CreateVariable(3);
         IPS_SetName($meID, "Log");
			IPS_SetParent($meID, $instancID);
	      IPS_SetVariableCustomProfile($meID, "~HTMLBox");
	      echo "HTML Ausgabe wurde angelegt. die ID lautet: ". "$meID
";

		   $eid = IPS_CreateEvent(1);                         //Ausgelöstes Ereignis
         IPS_SetEventCyclic($eid, 0, 0, 0, 0, 2, 1);       //Jede Minute
         IPS_SetParent($eid, $IPS_SELF);                   //Eregnis zuordnen
         IPS_SetEventActive($eid, true);                  //Ereignis aktivieren
         echo "Minütliches Event wurde angelegt. die ID lautet: ". "$eid
";



		   }
	    }
	   }
    }
}


if(file_exists(IPS_GetKernelDir()."_error.txt"))
{
   $file = IPS_GetKernelDir()."_error.txt";
   $logfile = file($file);
   $log = "";

	IPS_Sleep(500);
	 $exsID = @IPS_GetVariableID("Fehlermeldung");
		if ($exsID === false)
	echo "Variabale Fehlermeldung nicht vorhanden";

    $logID = @IPS_GetVariableID("Log");
		if ($logID === false)
	echo "Variable für die Log`s nicht vorhanden";



   foreach($logfile as $lines => $line)
    {
        $log .= "<p>"."Meldung ".$lines."<b style='color:#FF2A55;'> ".$line."</b><br></p>";
   }

    $exsID = @IPS_GetVariableID("Fehlermeldung");
		if ($exsID === false)
		  echo "Variable Fehlermeldung nicht gefunden!";
		else
		  //echo "Die Variablen-ID lautet: ". $exsID;

		  	$logID = @IPS_GetVariableID("Log");
		if ($logID === false)
		  echo "Variable Logs nicht gefunden!";
	 else
		 // echo "Die Variablen-ID lautet: ". $logID;
	SetValue($logID, $log);
	SetValue($exsID, false);
}

if($IPS_SENDER == "WebFront")
{
    $exsID = @IPS_GetVariableID("Fehlermeldung");
		if ($exsID === false)
		  echo "Variable Fehlermeldung nicht gefunden!";
		else
		  //echo "Die Variablen-ID lautet: ". $exsID;

		  	$logID = @IPS_GetVariableID("Log");
		if ($logID === false)
		  echo "Variable Logs nicht gefunden!";
		else
		 // echo "Die Variablen-ID lautet: ". $logID;

    if(file_exists(IPS_GetKernelDir()."_error.txt"))
    {
       unlink(IPS_GetKernelDir()."_error.txt");
       SetValueString($logID, "");
       SetValue($exsID, true);

       // ID vom WebFront Configurator ermitteln
       $WFID = @IPS_GetInstanceIDByName("WebFront Configurator", $ParentID);
			if ($WFID === false)
			  echo "WebFront Configurator erstellen, oder Zeile 124-129 Löschen";
			else
        			 WFC_SendNotification($WFID , "Löschbestätigung", "Error.TXT erfolgreich gelöscht", "Information", 5);
    }
}

?>

Nur noch php.ini anpassen.

Hi,

bei mir erzeugt das Script irgendwie eine Schleife. Es werdenw ie verrückt Objekte autoamtisch angelegt doppelt und dreifach…

Bei euch auch?

Habe es 1:1 in ein Skript kopiert und ausgeführt…

Grüße

Habe es 1:1 in ein Skript kopiert und ausgeführt…

Wie oft?

Das Skript sollte nur einmal ausgeführt werden. Der Rest läuft automatisch.

Jedes mal wenn Du „Ausführen“ klickst legt es unterhalb die selbe Struktur nochmal an.

Hallo,

leider funktioniert das Script nicht wie beschrieben. Wenn ich auf die Boolean Variable klicke passiert nichts. Habe gesehen, dass dein Posting schon etwas älter ist. Gibt es da evtl. Probleme mit Version 2.5?

Grüße

Das Script funktioniert einwandfrei, so wie beschrieben. Du hast nicht richtig gelesen. Die Variable muss als Aktion dem Script zugewiesen werden!

ich gehe ins Bett - habe ich völlig übersehen… Danke.

Sorry