begin process at 2008 08 20 12:00:56
1 228 769 membres
141 nouveaux aujourd'hui
14 257 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

TRAITER LES ERREURS PHP GRAVES, NON INTERCEPTABLES


Information sur la source

Catégorie :Astuces Classé sous : erreur, fatale, configuration, logger, handler Niveau : Initié Date de création : 06/01/2008 Date de mise à jour : 07/01/2008 07:56:58 Vu : 3 009

Note :
Aucune note

Commentaire sur cette source (0)
Ajouter un commentaire et/ou une note

Description

Comment traiter les erreurs PHP qui ne peuvent être interceptées et gérées par script PHP? Impossible ? Pas si sûre !
• E_ERROR
• E_PARSE
• E_CORE_ERROR
• E_CORE_WARNING
• E_COMPILE_ERROR
• E_COMPILE_WARNING
• La plupart des E_STRICT
Attraper les erreurs de ce type est impossible dans un script PHP, puisque que l’interpréteur PHP est considéré instable et stoppé. PHP affiche par défaut un rapport d’erreur. Ces erreurs ne sont pas attrapables avec PHP.

Objectif :
• Comment être informer rapidement (mail par exemple) d'une erreur sur le site,
• Comment maitriser l'affichage du rapport d'erreur PHP, en pensant sécurité

Problématiques :
• La sécurité peut être compromise par l’affichage d’informations indésirables dans le rapport d’erreur de PHP.
• Pour l’aspect sécurité, la solution de désactiver le rapport d’erreur (display_errors = Off) est tout aussi risqué. Le client ne sera pas correctement informé qu’il y a une erreur. Soit la crédibilité du site en prend encor plus un coup que ce n’est déjà fait, soit il risque d’insister et provoquer plus de problèmes.
• Enfin, plus tôt on est informé de ce genre d’erreur, mieux c’est. Hors la configuration PHP propose uniquement un log des erreurs alors qu’un mail serait un minimum pour être informé rapidement.
• Le fichier php.ini peut être inaccessible (par exemple hébergement mutualisé)


Solution, résumé :
La solution que j’ai trouvé consiste à jouer sur la configuration des directives PHP (Rappel : le fichier php.ini, reconfigurable via htaccess ou script PHP), puis à l’aide d’une petite astuce HTML, poursuivre le traitement de l’erreur avec une redirection. Le système a ses limites mais fonctionne plus ou moins et ne demande qu’à être amélioré.


Note :
Il est fort possible que je puisse me tromper sur ces affirmations, et qu’il existe d’autres façons plus fiables et plus simples pour répondre à ces problèmes. Mais dans ce cas l’information est dure à trouver. N’hésitez pas à citer des références.

Source

  • <?php
  • /******************************************
  • Mise en place de la solution :
  • /******************************************
  • 1) La configuration
  • *******************************************/
  • ?>
  • Modifier les directives PHP : Un fichier .htaccess est utilisable si php.ini n’est pas accessible. On peut garder sous la main deux versions de .htaccess : une pour l’environnement de développement et l’autre pour la production.
  • • display_errors = On : Il est indispensable de signaler l’erreur et, un rapport est nécessaire pour la redirection avec HTML.
  • • log_errors= On : Toujours écrire les messages d'erreur
  • • error_prepend_string et error_append_string : Pas d’influence sur le Log. C’est là, la clé de l’astuce : il faut fournir suffisamment de contenu (X)HTML pour obtenir une page qui convienne. La balise <meta http-equiv="refresh" content="0;URL=/err500.htm" /> redirige vers la page erreur.
  • • error_log : Indiquer un fichier commençant par « .ht » rend le fichier inaccessible
  • <?php /** Exemple .htaccess pour l’environnement « production » : */ ?>
  • php_value error_reporting 2147483647
  • php_flag display_errors on
  • php_flag display_startup_errors on
  • php_flag log_errors on
  • php_flag ignore_repeated_errors off
  • php_flag ignore_repeated_source off
  • php_flag report_memleaks on
  • php_flag html_errors off
  • php_flag track_errors on
  • php_value log_errors_max_len 4096
  • php_value docref_root off
  • php_value docref_ext off
  • php_value error_prepend_string '<html><head><meta http-equiv="refresh" content="0;URL=/err500.php" /></head><body>Erreur Critique.<div style="visibility:hidden">'
  • php_value error_append_string '</div></body></html>'
  • php_value error_log ./.ht_log_err_php.log
  • # // On peut éventuellement complèter avec :
  • ErrorDocument 500 ./ err500.php
  • <?php /** Exemple .htaccess pour l’environnement « développement » : */ ?>
  • php_value error_reporting 2147483647
  • php_flag display_errors on
  • php_flag display_startup_errors on
  • php_flag log_errors on
  • php_flag ignore_repeated_errors off
  • php_flag ignore_repeated_source off
  • php_flag report_memleaks on
  • php_flag html_errors on
  • php_flag track_errors on
  • php_value log_errors_max_len 4096
  • php_value docref_root http://www.php.net/manual/fr/
  • php_value docref_ext .php
  • php_value error_prepend_string '<html><body>'
  • php_value error_append_string '</body></html>'
  • php_value error_log ./log_err_php.log
  • <?php
  • /******************************************
  • 2) la page err500.php
  • *******************************************/
  • ?>
  • Puisque PHP avait stoppé l’exécution du script après l’erreur, il était impossible d’envoyer un mail par exemple. C’est avec la page err500.php que l’on va pouvoir le faire.
  • Exemple page de traitement :
  • <?php
  • header('HTTP/1.1 500 Internal Server Error');
  • // …. Tout traitement pour l’erreur
  • //@mail('webmaster@localhost', 'Erreur critique sur site en prod', 'Must see the log');
  • ?>
  • <html><head>
  • <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  • <title>Internal Server Error</title></head><body>
  • <H1>Internal Server Error</H1>
  • <p>The server encountered an internal error or misconfiguration and was unable to complete your request.</p>
  • <p>Please contact the server administrator, webmaster@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.</p>
  • <p>More information about this error may be available in the server error log.</p>
  • </body></html>
<?php
/******************************************
  Mise en place de la solution :
/******************************************
         1) La configuration
*******************************************/
?>
Modifier les directives PHP : Un fichier .htaccess est utilisable si php.ini n’est pas accessible. On peut garder sous la main deux versions de .htaccess : une pour l’environnement de développement et l’autre pour la production.

• display_errors = On : Il est indispensable de signaler l’erreur et, un rapport est nécessaire pour la redirection avec HTML.
• log_errors= On : Toujours écrire les messages d'erreur
• error_prepend_string et error_append_string : Pas d’influence sur le Log. C’est là, la clé de l’astuce : il faut fournir suffisamment de contenu (X)HTML pour obtenir une page qui convienne. La balise <meta http-equiv="refresh" content="0;URL=/err500.htm" /> redirige vers la page erreur.
• error_log : Indiquer un fichier commençant par « .ht » rend le fichier inaccessible



<?php /** Exemple .htaccess pour l’environnement « production » : */ ?>
php_value   error_reporting             2147483647
php_flag    display_errors              on
php_flag    display_startup_errors      on
php_flag    log_errors                  on
php_flag    ignore_repeated_errors      off
php_flag    ignore_repeated_source      off
php_flag    report_memleaks             on
php_flag    html_errors                 off
php_flag    track_errors                on
php_value   log_errors_max_len          4096
php_value   docref_root                 off
php_value   docref_ext                  off
php_value   error_prepend_string        '<html><head><meta http-equiv="refresh" content="0;URL=/err500.php" /></head><body>Erreur Critique.<div style="visibility:hidden">'
php_value   error_append_string         '</div></body></html>'
php_value   error_log                   ./.ht_log_err_php.log

# // On peut éventuellement complèter avec :
ErrorDocument 500 ./ err500.php

<?php /** Exemple .htaccess pour l’environnement « développement » : */ ?>
php_value   error_reporting             2147483647
php_flag    display_errors              on
php_flag    display_startup_errors      on
php_flag    log_errors                  on
php_flag    ignore_repeated_errors      off
php_flag    ignore_repeated_source      off
php_flag    report_memleaks             on
php_flag    html_errors                 on
php_flag    track_errors                on
php_value   log_errors_max_len          4096
php_value   docref_root                 http://www.php.net/manual/fr/
php_value   docref_ext                  .php
php_value   error_prepend_string        '<html><body>'
php_value   error_append_string         '</body></html>'
php_value   error_log                   ./log_err_php.log


<?php
/******************************************
         2) la page err500.php
*******************************************/
?>
Puisque PHP avait stoppé l’exécution du script après l’erreur, il était impossible d’envoyer un mail par exemple. C’est avec la page err500.php que l’on va pouvoir le faire.
Exemple page de traitement : 


<?php
header('HTTP/1.1 500 Internal Server Error');
// …. Tout traitement pour l’erreur
//@mail('webmaster@localhost', 'Erreur critique sur site en prod', 'Must see the log');
?>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Internal Server Error</title></head><body>
<H1>Internal Server Error</H1>
<p>The server encountered an internal error or misconfiguration and was unable   to complete your request.</p>
<p>Please contact the server administrator, webmaster@localhost and inform them   of the time the error occurred, and anything you might have done that may have   caused the error.</p>
<p>More information about this error may be available in the server error   log.</p>
</body></html>

Conclusion

-------------------------------------------------
Limitation de la solution :
-------------------------------------------------
Cette solution n’est absolument pas fiable et dépend fortement de la profondeur de l’erreur dans le code. La page renvoyée avec le rapport d’erreur n’est certainement pas conforme. L’astuce fonctionnera donc suivant l’interprétation du navigateur. En utilisant une bufferisation de sortie les chances sont fortement augmentées.

-------------------------------------------------
Appel à contribution :
-------------------------------------------------
Je n’ai pas poussé mes tests très loin, contribuez à cette source en signalant les navigateurs où la redirection ne fonctionne pas, ou en proposant d’autres idées de valeur pour error_prepend_string et error_append_string, d’autres traitement pour la page de traitement...


-------------------------------------------------
Annexe :.htaccess version production
-------------------------------------------------
Explication des autres choix Htaccess version production.
• error_reporting = 2147483647 : permet de notifier toute erreurs quel que soit la version de PHP, y compris celles à venir.
• display_startup_errors = On : Je ne sais pas comment provoquer cette erreur pour tester ! Malgré que fortement déconseillé en Prod, je mets On pour privilégier le fait d’être informé de l’erreur plutôt que la sécurité.
• log_errors_max_len=4096 : Test : La valeur minimum est 1 (0 ne fonctionne pas). Le réglage influence le rapport affiché autant que le Log J’ai mis à 4 fois la valeur par défaut pour encore une fois privilégier l’information sur la sécurité
• ignore_repeated_errors et ignore_repeated_source=Off : sinon un client qui insisterait en rafraichissant la page ne serait pas détecté
• report_memleaks= On : Valeur par défaut, il vaut mieux rapporter ce type d’erreur
• track_errors= On : Si pas utilisé dans script, Influence ? Ressources ? Je préfère mettre à On si jamais un script tiers utilise la variable globale.
• html_errors=Off : n’influence pas le log, ni les directives error_prepend_string et error_append_string. Seulement la mise en page du rapport d’erreur
• docref_root et docref_ext=Off : Ce n’est pas le but ici.
06 janvier 2008 14:46:19 :
Mise en page astuce
07 janvier 2008 07:56:58 :
partie objectif plus claire dans description
    Aucun commentaire pour le moment.

Ajouter un commentaire

Pub



Appels d'offres

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

Téléchargements

Boutique

Boutique de goodies CodeS-SourceS