หน้าข้อผิดพลาดที่เป็นมิตรเพื่อแทนที่ WSOD


10

นี่ควรเป็นสิ่งที่ง่ายที่สุดที่จะทำ แต่ด้วยเหตุผลบางอย่างที่ฉันทำไม่ได้

ฉันพยายามรับหน้าข้อผิดพลาดแบบคงที่ที่เป็นมิตรเพื่อแทนที่สถานการณ์ที่น่ารังเกียจ 500 รายการ สำหรับตอนนี้ฉันแค่พยายามทำซ้ำสถานการณ์ 500 บนเครื่องท้องถิ่นของฉัน (Drupal 7 ทำงานบน MAMP) โดยการขว้างตัวละครอึที่ด้านบนสุดของ template.php ในธีมของฉันซึ่งทำให้เกิดสถานการณ์ 500 แต่สำหรับ เหตุผลข้อผิดพลาดคำสั่ง ErrorDocument ใน.htaccessไฟล์ config ของฉันหรือ Apache ไม่มีผล

สิ่งที่ฉันทำอยู่นี้ค่อนข้างง่าย:

ErrorDocument 500 /500.html

และฉันมีหน้า html คงที่ที่ง่ายที่สุดในรูทของไซต์ของฉันด้วยชื่อของ 500.html

ยังเมื่อฉันตั้งใจทำลาย template.php ฉันได้รับ White Screen Of Death แทนหน้าข้อผิดพลาดที่เป็นมิตรดีของฉัน

ฉันทำอะไรผิดที่นี่ ฉันได้ทำสิ่งนี้ไปพันล้านครั้งในการตั้งค่าที่ไม่ใช่ Drupal แต่ไม่สามารถไปรอบ ๆ สิ่งนี้ได้


UPDATE : ดูเหมือนว่าคำถามนี้ค่อนข้างซ้ำซ้อนในกรณีการใช้งานเฉพาะของฉันในขณะนี้เป็น Dev Cloud ของ Acquia ที่เราใช้ในการเรียกใช้แอปพลิเคชันที่มีปัญหาไม่สนับสนุนการกำหนดหน้าข้อผิดพลาด 500 ชุดในขณะนี้ หวังว่าพวกเขาจะใช้การสนับสนุนในเร็ว ๆ นี้


จะเกิดอะไรขึ้นถ้าคุณเพิ่มdrupal_add_http_header('Status', '503 Service Unavailable');ไปที่ 500.html ของคุณ
บาริสต้ามือสมัครเล่น

คำตอบ:


2

500 หน้าข้อผิดพลาดเป็นหน้าข้อผิดพลาดเซิร์ฟเวอร์อย่างเคร่งครัด เมื่อเซิร์ฟเวอร์ทำการประมวลผล PHP, Drupal / PHP มีหน้าที่รับผิดชอบในการแสดงหน้าข้อผิดพลาดของตนเอง คุณอาจลองบอก Drupal ให้เปลี่ยนเส้นทางผู้ใช้ไปยังหน้าข้อผิดพลาดที่กำหนดเองพร้อมกับส่วนหัวสถานะ HTTP 500 เมื่อได้รับข้อผิดพลาดบางอย่างภายในtry...catchบล็อก

อย่างไรก็ตามโปรดทราบว่า WSOD บางอย่างสามารถเกิดขึ้นได้ที่ระดับระบบและอาจทำให้เกิดข้อผิดพลาดร้ายแรงที่หยุดการทำงานทันทีและอาจทำให้ไม่catchสามารถดำเนินการได้ ตัวอย่างหนึ่งคือเมื่อฐานข้อมูลของคุณไม่ได้รับการปรับอย่างเหมาะสมเพื่อจัดการคิวรีที่มีขนาดที่กำหนด (เช่นเมื่อทำการฟีเจอร์เปลี่ยนการดำเนินการทั้งหมด) - ฐานข้อมูลอาจทำให้เกิดปัญหาขึ้นโดยให้ insta-WSOD

ฉันจะบอกว่าสิ่งที่ดีที่สุดที่ควรทำคือตรวจสอบ apache, MySQL และ PHP error log ของคุณและพยายามแยกสาเหตุของ WSOD เป็นกรณี ๆ ไปแทนที่จะพยายามปกปิดพวกมันด้วย หน้าข้อผิดพลาด ในขณะที่ข้อผิดพลาดที่ทำให้หน้าผิดพลาดของเซิร์ฟเวอร์ 500 ทั่วไปบางครั้งไม่สามารถหลีกเลี่ยงได้และการมีหน้าข้อผิดพลาดของเซิร์ฟเวอร์ที่กำหนดเองในการผลิตเป็นไปได้มี WSODs เกิดขึ้นจริงไม่

ดูเหมือนว่าคุณมีการตั้งค่าหน้าข้อผิดพลาดของเซิร์ฟเวอร์อย่างถูกต้อง คุณต้องแยกความแตกต่างที่หน้าข้อผิดพลาดเซิร์ฟเวอร์ทั่วไป! = WSOD หน้าข้อผิดพลาดของเซิร์ฟเวอร์สามารถถูกเรียกใช้เนื่องจากปัญหาการรับส่งข้อมูลและคอขวดของทรัพยากรสูง แต่คุณไม่ควรให้ WSOD เกิดขึ้นจริงในช่วงเวลาที่ใช้งานจริง สิ่งเหล่านี้มักจะเกิดขึ้นเนื่องจากการเข้ารหัสการปรับให้เหมาะสมหรือการกำหนดค่าไม่ดี หากคุณยังคงเห็น WSOD ตรวจสอบให้แน่ใจว่าคุณพบ (และแก้ไข) สาเหตุของปัญหาเป็นอันดับแรกตรงข้ามกับการพยายามใช้การช่วยเหลือจากวงดนตรีกับมัน


4
ขอบคุณสำหรับคำตอบ. คุณถูกต้องอย่างแน่นอนเกี่ยวกับสาเหตุที่แท้จริง / อาการการรักษา อย่างไรก็ตามนี่ไม่เกี่ยวข้องกับความต้องการของหน้าข้อผิดพลาดที่ดีเนื่องจากเป็นความจริงที่ว่าในช่วงอายุการใช้งานของบริการข้อผิดพลาดจะเกิดขึ้นและในสถานการณ์เหล่านั้นมันจะดีกว่าเสมอในการสื่อสารสถานการณ์ให้กับผู้ใช้มากกว่าหน้าว่างหรือขาวดำทั่วไป หน้า "เซิร์ฟเวอร์ผิดพลาด" ตัวอย่าง Twitter ล้มเหลวเนื่องจากวาฬเป็นตัวอย่าง ไม่ได้ลบความจำเป็นในการรวบรวมโปรไฟล์ข้อผิดพลาดระดับมืออาชีพ แต่ในระหว่างนี้ผู้ใช้จะโกรธน้อยลง
Tommi Forsström

1
นอกจากนี้สำหรับกรณีนี้ไม่จำเป็นต้องแยกแยะความแตกต่างระหว่างเลเยอร์ที่เกิดข้อผิดพลาด (ตราบใดที่มันอยู่ใต้เซิร์ฟเวอร์ http) เนื่องจากฉันต้องการกลไกการดักจับข้อผิดพลาดทั้งหมดในแอปพลิเคชันเลเยอร์ไม่ว่าจะเป็นฐานข้อมูลล่มหรือไม่ บางคนยอมรับรหัสอึ (และผ่านการทดสอบของเรา) และสถานการณ์ข้อผิดพลาดอื่น ๆ ที่เป็นไปได้ แต่ไม่คาดคิด แต่ตามที่ได้รับการปรับปรุงในคำถามคำถามนี้ไม่เกี่ยวข้องกับฉันในขณะนี้เนื่องจากระบบคลาวด์ dev ของ Acquia ไม่สนับสนุนการแก้ไขหน้าข้อผิดพลาด 500 ชุดในขณะนี้
Tommi Forsström

"ระบบคลาวด์ dev ของ Acquia ไม่สนับสนุนการกำหนดหน้าข้อผิดพลาด 500 ชุดในขณะนี้" โอ้วววมันเป็นเรื่องดีที่จะรู้
บาริสต้ามือสมัครเล่น

แม้ว่ามันจะเป็นเพียงสิ่งเดียวที่บินได้ใน Dev Dev อันทรงพลังของ Acquia และพวกเขาก็อาจจะใช้มันในอนาคตอันใกล้ ฉันพูดไม่ดีพอสำหรับ Dev Cloud มันเป็นแพลตฟอร์มที่น่าทึ่งในการให้บริการ Drupal!
Tommi Forsström

1

คุณได้รับ WSOD เนื่องจากคุณปิดการรายงานข้อผิดพลาดใน php.ini นี่เป็นปัญหาด้านความปลอดภัย - หากคุณมีข้อผิดพลาดและแฮ็กเกอร์เห็นว่ามันคืออะไรเขาอาจใช้เพื่อแฮกเว็บไซต์

หากคุณต้องการดักจับข้อผิดพลาดคุณต้องเปิดใช้งานการแสดงข้อผิดพลาดในphp.ini (ตัวอย่างจะแสดงข้อผิดพลาดร้ายแรงเท่านั้น):

error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT

จากนั้นคุณสามารถตั้งค่าเอกสารข้อผิดพลาดในไฟล์ htaccess:

ErrorDocument 401 http://yourwebsite.com/error-401
ErrorDocument 403 http://yourwebsite.com/error-403
ErrorDocument 500 http://yourwebsite.com/error-500

หรือคุณสามารถระบุข้อผิดพลาดในไฟล์settings.phpของ Drupal

ใน NGINX:

error_page 403 = /error.php?code=403;   
error_page 404 = /error.php?code=404;
error_page 500 = /error.php?code=500;

เนื่องจากคุณใช้ Apache ใน MAMP ให้ตั้งเป็น. htaccess โปรดจำไว้ว่าAllowOverrideใน apache config ควรเปิดใช้งาน (โดยปกติคือ)


การกำหนดErrorDocumentคำสั่งสำหรับการตอบสนอง 500 ครั้งใน Drupal ไม่สามารถใช้ในการทดสอบได้
cdmo

500 ข้อผิดพลาดมักจะไม่สามารถตั้งค่าใน Drupal พวกเขาจะต้องตั้งค่าก่อน Drupal - in .htaccess หากใช้ Apache ใน NGINX - ดูตั๋วที่อัพเดทแล้ว
Alexei Rayu

นั่นคือสิ่งที่ฉันหมายถึง. คุณสามารถรับคำสั่ง ErrorDocument สำหรับข้อผิดพลาด 500 ข้อใน htaccess หรือ vhost กำหนดค่าให้ทำงานกับไซต์ Drupal ได้หรือไม่ คำสั่งเหล่านั้นถูกเพิกเฉยในประสบการณ์ของฉัน Drupal จัดการกับข้อผิดพลาด
cdmo

0

คุณได้เปิดการรายงานข้อผิดพลาดหรือไม่ (ผู้ดูแลระบบ / การกำหนดค่า / การพัฒนา / การบันทึก -> ตั้งค่าข้อความทั้งหมดสำหรับข้อความแสดงข้อผิดพลาดที่จะแสดง )

ตามค่าเริ่มต้น Drupal จะแสดง WSOD เป็นคุณสมบัติความปลอดภัย


ตลกดีพอเปิดอยู่และฉันยังได้รับ WSOD
Tommi Forsström

ในกรณีนั้นอาจเป็นปัญหา MAMP ไม่ใช่ปัญหา Drupal ลองเปิดการรายงานข้อผิดพลาดใน php.ini ( forum.mamp.info/viewtopic.php?f=2&t=8077 ) การแสดงข้อผิดพลาดถูกปิดใช้งานใน MAMP ตามค่าเริ่มต้น
Patrick Kenny

1
ฉันสามารถรับข้อผิดพลาด php แสดงได้ดี นั่นไม่ใช่ปัญหาจริงๆ ฉันต้องการที่จะแสดงสิ่งที่เป็นมิตรเมื่อเกิดข้อผิดพลาดเช่น Twitter's Fail Whale นั่นคือสิ่งที่ฉันไม่สามารถเกิดขึ้นได้: หน้าข้อผิดพลาดที่กำหนดเองสำหรับข้อผิดพลาด 500 ซีรี่ส์
Tommi Forsström

0

ฉันเดาคำตอบคือ "อ่านเอกสาร" ดูhttps://www.drupal.org/node/195435

ดังนั้นโดยทั่วไปคุณสามารถสร้างแฟ้มแม่แบบที่มีชื่อmaintenance-page.tpl.phpและรหัสยากที่การตั้งค่าบางอย่างในmaintenance-page--offline.tpl.phpsettings.php

แก้ไข:

มันดูเหมือนจะไม่สำคัญว่าสิ่งที่ระดับerror_reportingมีการตั้งค่าหรือไม่ว่าคุณได้ตั้งdisplay_errorsไปหรือon offเมื่อคุณมีmaintenance-page--offline.tpl.phpไฟล์ในสถานที่ Drupal จะแสดงหน้านี้เมื่อฐานข้อมูลหายไป นอกจากนี้ไม่สำคัญว่าคุณได้ตั้งค่าไว้อย่างไร/admin/config/development/loggingในด้านผู้ดูแลระบบ หากคุณเพิ่งมีข้อผิดพลาดทางไวยากรณ์ซึ่งเป็นสถานการณ์ของ OP ที่จะไม่เรียก 500 จริง ๆ แล้วมันเป็น 200 ที่มีข้อผิดพลาด PHP แสดงหรือซ่อนตามphp.ini display_errorชุด ไม่มีวิธีใดที่ฉันรู้นอกจากการเพิ่มตรรกะการจัดการข้อผิดพลาดที่กำหนดเองของคุณตลอดทั้งรหัสที่กำหนดเองของคุณ


ไม่แน่ใจว่าทำไมฉันลงคะแนนที่นี่นี่คือคำตอบที่ฉันกำลังมองหาเมื่อฉันตั้งค่าความโปรดปราน อีกอันหนึ่งไม่ใช่ OP คุณสามารถตั้ง error_prepend และผนวกกับข้อผิดพลาด PHP มาตรฐานได้เช่นกันหากคุณต้องการที่จะอธิบายรายละเอียดหน้าข้อผิดพลาดมาตรฐานเพิ่มเติม
cdmo

0

ในการแทนที่ WSOD ทั้งหมดด้วยสิ่งอื่นจะต้องมีการแฮ็กหลัก: คุณไม่ต้องการทำสิ่งนี้ Drupal กำหนดตัวจัดการข้อผิดพลาดของตัวเองใน bootstrap.inc และ errors.inc หากคุณต้องยุ่งกับโค้ดนั้นคุณจะต้องแน่ใจว่าคุณได้คิดทุกสิ่งที่อาจผิดเมื่อการประมวลผลมาถึงขั้นนี้ (ไม่มีฐานข้อมูลไม่มีเอ็นจิ้นธีมไม่มีธีมไม่มีการกำหนดค่า ฯลฯ )


เคยลองใช้ตัวเลือก error_append และ error_prepend ของ PHP หรือไม่ ในขณะที่ข้อความแสดงข้อผิดพลาดจะยังคงปรากฏเหมือนว่าคุณสามารถนำเสนอประสบการณ์ที่ดีกว่า 500 (ได้รับไม่ใช่ข้อผิดพลาด PHP ทั้งหมดที่ทำให้หน้าจอขาวเทคนิคก่อให้เกิดการตอบสนอง 500 เช่นข้อผิดพลาดทางไวยากรณ์จำนวนมาก)
cdmo

จริง ไม่ว่าจะด้วยวิธีใดก็ตามคุณจะได้รับจุดทั่วไป: คุณไม่สามารถทำได้
บัญชี

0

ฉันทำโครงการ sandboxเพื่อทำสิ่งนี้

ฉันสามารถทำได้โดยขยายHttpExceptionSubscriberBaseใน /src/EventSubscriber/fivehundredEventSubscriber.php

    <?php
namespace Drupal\five_hundred\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Serializer\SerializerInterface;

class five_hundredEventSubscriber extends HttpExceptionSubscriberBase {

      public function __construct($stack) {

        if(
          (
            null !== $stack->getCurrentRequest()->attributes->get('exception')->getCode()
            && $stack->getCurrentRequest()->attributes->get('exception')->getCode() == 500
          )||(
            null !== $stack->getCurrentRequest()->attributes->get('exception')->getStatusCode()
            && $stack->getCurrentRequest()->attributes->get('exception')->getStatusCode() == 500
          )
        ){
            $response = new Response();
            $errorDocumentHtml = 'html here';
            $response->setContent($errorDocumentHtml);
            $response->setStatusCode(500, '500 Internal Server Error');
            $response->send();
            die();
        }
      }

      /**
       * {@inheritdoc}
       */
      protected function getHandledFormats() {
        return array('html','');
      }


    }
?>

และคุณจะต้องเพิ่มบริการใน module.services.yml ของคุณ

services:
  five_hundred.:
    class: Drupal\five_hundred\EventSubscriber\five_hundredEventSubscriber
    arguments: ['@request_stack']
    tags:
      - { name: event_subscriber }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.