2010-10-01 18 views
23

Mi piacerebbe essere in grado di catturare e die()exit() messaggi. È possibile? Spero in qualcosa di simile a set_error_handler e set_exception_handler. Ho guardato register_shutdown_function() ma sembra contenere alcun contesto per l'incriminato die() e exit() chiamate.Posso prendere i messaggi exit() e die()?

Mi rendo conto che die() e exit() sono metodi sbagliati per gestire gli errori. Non sto cercando di dirti di non farlo. :) Io sono la creazione di un sistema generico e voglio essere in grado di accedere con grazia exit() e die() se per qualche motivo qualcuno (non io) decide questa è una buona idea per fare.

risposta

4

Come meglio posso dire questo non è realmente possibile. Alcune delle soluzioni pubblicate qui potrebbero funzionare ma richiedono molto lavoro aggiuntivo o molte dipendenze. Non c'è modo di intrappolare facilmente e in modo affidabile i messaggi die() e exit().

+0

Bene, è possibile riscrivendo lo script mentre lo leggi. L'esempio seguente tokenizza l'input e riscrive exit ($ code) e die $ code a php_exit ($ code): EDIT: stackoverflow non mi consente di aggiungere codice qui, vedere questo post per l'ispirazione: http://stackoverflow.com/domande/31182968/gettone-get-all-back-to-php-source-how-to – user1135940

7

Secondo la PHP manual, funzioni di arresto deve ancora essere notificato quando die() o di uscita() viene chiamato.

Shutdown functions e object destructors verrà sempre eseguito anche se viene chiamato exit().

Non sembra possibile ottenere lo stato inviato in uscita (stato $). A meno che tu non possa utilizzare il buffering di output per catturarlo, ma non sono sicuro di sapere quando chiamare ob_start().

+3

Immagino che il problema dell'OP sia che vorrebbe essere in grado di recuperare il messaggio di errore dalla funzione di arresto. – casablanca

+0

Viene chiamata la funzione di spegnimento, ma non sono sicuro se/come posso ottenere il contesto exit/die in quel punto. Del resto, non era chiaro se potessi sapere se exit/die è la ragione per cui viene chiamata la funzione shutdown. (Sembra che la funzione shutdown venga chiamata su die, ma viene chiamata quando il processo termina anche dopo un'esecuzione corretta ...) –

5

Forse override_function() potrebbe essere interessante, se APD è disponibile

+0

Questa è un'idea interessante! Sperando in una soluzione migliore non APD, però. –

+0

Non penso che funzionerà. 'die' e' exit' sono costrutti di linguaggio, non funzioni. –

-2

sì: scrivere una funzione e l'uso che, invece.

function kill($msg){ 
    // Do your logging.. 
    exit($msg); 
} 
+7

Apprezzo la risposta, ma non è affatto utile. Voglio prendere exit() e die() nel caso in cui qualche codice che non ho scritto li chiami. –

+0

lo so ma è il più vicino possibile, solo una nuova funzione e una semplice ricerca e sostituzione da exit e die per uccidere .. –

0

Perché non utilizzare invece la gestione personalizzata degli errori? In caso contrario, potresti sempre usare LD_PRELOAD e C Code injection per catturarlo :) Oppure ricompilare php con le tue personalizzazioni: P

7

Sì, è possibile, ma è necessario ob_start, ob_get_contents, ob_end_clean e register_shutdown_function

function onDie(){ 
    $message = ob_get_contents(); // Capture 'Doh' 
    ob_end_clean(); // Cleans output buffer 
    callWhateverYouWant(); 
} 
register_shutdown_function('onDie'); 
//... 
ob_start(); // You need this to turn on output buffering before using die/exit 
@$dumbVar = 1000/0 or die('Doh'); // "@" prevent warning/error from php 
//... 
ob_end_clean(); // Remember clean your buffer before you need to use echo/print 
0

Se si utilizza l'unico punto di metodo di inserimento. (Index.php) posso consigliare questo per la vostra gestione degli errori:

Versione corta:

ob_start(); 
register_shutdown_function('shutdownHandler'); 

include('something'); 

define(CLEAN_EXIT, true); 

function shutdownHandler() { 
    if(!defined("CLEAN_EXIT") || !CLEAN_EXIT) { 
     $msg = "Script stopped unexpectedly: ".ob_get_contents(); 
     //Handle premature die()/exit() here 
    } 
} 

passi ulteriori e più dettagliate:

Circa il modo di farlo mio. Ho anche più in corso, che vi mostro qui (manipolazione transazioni di database/rollback/l'invio di e-mail/scrittura logs/la visualizzazione di messaggi di errore amichevoli/segnalazione degli errori utente/etc), ma questa è l'idea di base dietro tutto questo).
Spero che aiuti qualcuno.

<?php 

    //Some initialization 

    //starting output buffering. (fatalErrorHandler is optional, but I recommend using it) 
    ob_start('fatalErrorHandler'); 

    //Execute code right at the end. Catch exit() and die() here. But also all other terminations inside PHPs control 
    register_shutdown_function('shutdownHandler'); 

    //handling other errors: Also optional 
    set_error_handler('errorHandler'); 



    try { 
     //Include of offensive code 
     include(...); 
    } 
    catch (Exception $ex) { 
     //Handling exception. Be careful to not raise exceptions here again. As you can end up in a cycle. 
    } 

    //Code reached this point, so it was a clean exit. 
    define(CLEAN_EXIT, true); 


    //Gets called when the script engine shuts down. 
    function shutdownHandler() { 

     $status = connection_status(); 

     $statusText = ""; 

     switch ($status) { 
      case 0: 
       if (!defined("CLEAN_EXIT") || !CLEAN_EXIT) { 
            $msg = "Script stopped unexpectedly: ".ob_get_contents(); 
        //Handle premature die()/exit() here 
       } 
       else { 
        //Clean exit. Just return 
        return; 
       } 
      case 1: $statusText = "ABORTED (1)"; break; 
      case 2: $statusText = "TIMEOUT (2)"; break; 
      case 3: $statusText = "ABORTED & TIMEOUT (3)"; break; 

      default : $statusText = "UNKNOWN ($status)"; break; 
     } 

     //Handle other exit variants saved in $statusText here 
    } 

    // error handler function (This is optional in your case) 
    function errorHandler($errno, $errstr, $errfile, $errline) { 

     $msg = "[$errno] $errstr\nOn line $errline in file $errfile"; 

     switch ($errno) { 
      case E_ERROR:    $msg = "[E_ERROR] ".$msg;    break; 
      case E_WARNING:    $msg = "[E_WARNING] ".$msg;    break; 
      case E_PARSE:    $msg = "[E_PARSE] ".$msg;    break; 
      case E_NOTICE:    $msg = "[E_NOTICE] ".$msg;    break; 
      case E_CORE_ERROR:   $msg = "[E_CORE_ERROR] ".$msg;   break; 
      case E_CORE_WARNING:  $msg = "[E_CORE_WARNING] ".$msg;  break; 
      case E_COMPILE_ERROR:  $msg = "[E_COMPILE_ERROR] ".$msg;  break; 
      case E_COMPILE_WARNING:  $msg = "[E_COMPILE_WARNING] ".$msg;  break; 
      case E_USER_ERROR:   $msg = "[E_USER_ERROR] ".$msg;   break; 
      case E_USER_WARNING:  $msg = "[E_USER_WARNING] ".$msg;  break; 
      case E_USER_NOTICE:   $msg = "[E_USER_NOTICE] ".$msg;   break; 
      case E_STRICT:    $msg = "[E_STRICT] ".$msg;    break; 
      case E_RECOVERABLE_ERROR: $msg = "[E_RECOVERABLE_ERROR] ".$msg; break; 
      case E_DEPRECATED:   $msg = "[E_DEPRECIATED] ".$msg;   break; 
      case E_USER_DEPRICIATED: $msg = "[E_USER_DEPRICIATED] ".$msg; break; 
      default:     $msg = "[UNKNOWN] ".$msg;    break; 
     } 

     //Handle Normal error/notice/warning here. 
     $handled = ... 

     if ($handled) 
      return true; //handled. Proceed execution 
     else 
      throw Exception($msg); //Be careful. this might quickly become cyclic. Be sure to have code that catches and handles exceptions. Else die() here after logging/reporting the error. 

    } 

    function fatalErrorHandler(&$buffer) { 

     $matches = null; 
     //Checking if the output contains a fatal error 
     if (preg_match('/<br \/>\s*<b>([^<>].*)error<\/b>:(.*)<br \/>$/', $buffer, $matches)) { 

      $msg = preg_replace('/<.*?>/','',$matches[2]); 

      //Handle Fatal error here 

      return "There was an unexpected situation that resulted in an error. We have been informed and will look into it." 
     } 

     //No fatal exception. Return buffer and continue 
     return $buffer; 
    } 
Problemi correlati