หน้าข้อผิดพลาดที่เป็นมิตรเพื่อแทนที่ 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.