2011-12-15 26 views
10

Tôi phải thiếu điều gì đó trong sự hiểu biết của mình về việc xử lý lỗi PHP, đặc biệt loại bỏ đầu ra của chúng. Khi một lỗi nghiêm trọng xảy ra, tôi mong đợi chức năng xử lý tắt máy của tôi xử lý nó một cách duyên dáng và chấm dứt thực thi tập lệnh. Điều này hoạt động như mong đợi. Tuy nhiên, tôi không thể ngăn chặn PHP xuất ra thông tin về lỗi nghiêm trọng.Ngăn chặn đầu ra traceback lỗi gây tử vong PHP khi sử dụng trình xử lý tắt tùy chỉnh

file php.ini của tôi chứa các chỉ dẫn sau:

error_reporting = E_ALL | E_STRICT 
display_errors = Off 

tôi đặt error_reporting báo cáo tất cả mọi thứ và tôi sử dụng một lỗi xử lý tùy chỉnh để ném ngoại lệ. Kỳ vọng của tôi là display_errors = Off sẽ ngăn chặn bất kỳ thông báo lỗi nào được hiển thị.

Dù sao, khi xảy ra lỗi nghiêm trọng, trình xử lý lỗi tùy chỉnh bị bỏ qua (vì thực thi tập lệnh dừng ngay lập tức) và trình xử lý tắt sẽ thực thi.

Bây giờ, trên mã đơn giản của tôi:

error_reporting(E_ALL | E_STRICT); 
ini_set('display_errors', 'Off'); 

function shutdown_handler() 
{ 
    $err = error_get_last(); 
    $fatal = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR); 
    if ($err && in_array($err['type'], $fatal)) { 
    echo "\n\ntest fatal error output\n\n"; 
    } 
    exit(); 
} 

register_shutdown_function('shutdown_handler'); 

Để kiểm tra nó, tôi tạo ra một "kích thước bộ nhớ phép kiệt sức" lỗi nghiêm trọng như vậy:

// max out available memory 
$data = ''; 
while(true) { 
    $data .= str_repeat('#', PHP_INT_MAX); 
} 

Bởi vì tôi có display_errors = Off Tôi hy vọng điều này để chỉ tạo ra kết quả sau (theo trình xử lý tắt máy):

test fatal error output 

Nhưng thay vào đó, tôi tiếp tục nhận được:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2147483648 bytes) in /home/daniel/mydev/php/test0.php on line 24 
PHP Stack trace: 
PHP 1. {main}() /home/daniel/mydev/php/test0.php:0 
PHP 2. str_repeat() /home/daniel/mydev/php/test0.php:24 

test fatal error output 

Tôi thiếu điều gì sẽ ngăn chặn lỗi này khi xuất ra?


KẾT LUẬN

Có vẻ như @Cthos sagely lưu ý, rằng "E_ERROR và display_errors không chơi độc đáo với nhau."

Đây cũng là trường hợp của E_PARSE (và tôi giả định E_CORE_ERROR/E_COMPILE_ERROR, nhưng tôi đã không ngắt cài đặt PHP của mình để kiểm tra nó). Tôi cho rằng nó có ý nghĩa rằng PHP sẽ buộc các traceback lỗi vào STDOUT trong những trường hợp này bởi vì nếu nó không bạn có thể không bao giờ biết nếu/tại sao mọi thứ đã đi sai.

Vì vậy, một giải pháp trong trường hợp này sẽ là:

  1. Như @Cthos gợi ý, im lặng E_ERROR thông báo trong php.ini: error_reporting = (E_ALL & ~ E_ERROR) hoặc khi chạy bằng error_reporting(E_ALL & ~ E_ERROR);
  2. Cập nhật xử lý tắt máy để kiểm tra xem cuối cùng lỗi là loại E_ERROR và thực hiện các hành động thích hợp nếu có.

Đối với các phần tử gây tử vong khác như E_PARSE, E_CORE_ERROR, v.v. bạn chỉ cần đảm bảo mã của bạn là chính xác và PHP của bạn hoạt động. Nếu bạn cố gắng im lặng E_PARSE lỗi và xử lý chúng trong chức năng tắt máy của bạn nó sẽ không hoạt động vì lỗi phân tích cú pháp ngăn chặn PHP từ bao giờ nhận được rằng đến nay.

Vì vậy, một cập nhật/xử lý tắt máy làm việc trông như thế này:

error_reporting(E_ALL & ~ E_ERROR); 

function shutdown_handler() 
{ 
    $err = error_get_last(); 
    if ($err && $err['type'] == E_ERROR) { 
    $msg = 'PHP Fatal Error: '.$err['message'].' in '.$err['file']. 
     ' on line '.$err['line']; 
    echo $msg, PHP_EOL; 
    } 
    exit(); 
} 
+0

Mayhap bạn nên có trình xử lý lỗi tùy chỉnh thay thế? http://www.php.net/manual/en/function.set-error-handler.php – Cthos

+0

@Cthos - khi trạng thái câu hỏi, tôi đã sử dụng trình xử lý lỗi tùy chỉnh. Khi một lỗi nghiêm trọng xảy ra, việc thực thi tập lệnh dừng ngay lập tức và trình xử lý lỗi tùy chỉnh không được gọi. Tuy nhiên, trình xử lý tắt máy tùy chỉnh vẫn có thể chạy. – rdlowrey

+0

Hrm, tôi đã thất bại trong việc đọc hiểu rồi, tuy nhiên tôi đã nghĩ Fatals vẫn sẽ đi đến xử lý nói. Thời gian thử nghiệm. – Cthos

Trả lời

3

các thông tin lỗi không mong muốn là do cấu hình lỗi đăng nhập (log_errorserror_log), và hoàn toàn không phụ thuộc vào Cấu hình display_errors. Cấu hình php.ini mặc định ghi nhật ký chi tiết lỗi thành stderr khi chạy tập lệnh từ dòng lệnh. Dưới Apache, chúng xuất hiện trong /etc/httpd/logs/error_log.

Khám phá chức năng php_error_cb trong main.c của nguồn PHP. Đặc biệt, dòng 1056 làm rõ rằng bất kỳ thông điệp nào có định dạng "PHP% s:% s trong% s trên dòng% d" là do cấu hình ghi nhật ký lỗi (thông tin lỗi do display_errors sẽ không có "PHP:" tiếp đầu ngữ).

+0

Cảm ơn một tấn . Điều này đã gây phiền toái cho tôi một thời gian. – rdlowrey

+0

Anh hùng ở đây! – sepehr

3

Couple của giải pháp khả thi, trả lời vì phần ý kiến ​​đã nhận được tức giận với tôi.

Chỉnh sửa # 3 với giải pháp:

Rõ ràng E_ERROR và display_errors không chơi độc đáo cùng

Bạn có thể thiết lập error_reporting để E_ALL & ~ E_ERROR, và chỉ cho phép xử lý tắt máy của bạn xử lý gây tử vong (vì nó là thứ cuối cùng nên được gọi là dù sao đi nữa).

Bên cạnh đó, E_ALL không bao gồm E_DEPRECATED trước PHP 5.4.0, vì vậy nếu bạn muốn bắt mà quá - sử dụng ~0 & ~E_ERROR


display_errors có thể được nghe trộm

Dưới đây là một ý chính trên làm thế nào bạn có thể làm cho nó nhổ ra các lỗi ngay cả khi bạn bảo nó không: https://gist.github.com/1483028

Nếu bạn đặt display_errors 0 qua ini_set() nó vẫn sẽ hiển thị lỗi Fatal

Mặc dù display_errors thể được thiết lập trong thời gian chạy (với ini_set()), nó sẽ không có bất kỳ ảnh hưởng nếu kịch bản có gây tử vong lỗi. Điều này là do hành động thời gian chạy mong muốn không được thực hiện.

Ngoài ra, bạn cũng có thể gửi nó đến stderr, vì vậy điều đó thật tuyệt vời.

http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors

Chỉnh sửa 2: Hãy chắc chắn rằng bạn đã thay đổi php.ini thích

Chỉ cần nghĩ về điều này, và nhận xét như vậy, nhưng có nhiều hơn một file php.ini . Nếu bạn đang làm điều này trên dòng lệnh, bạn sẽ cần phải chỉnh sửa một cli một (/etc/php5/cli/php.ini trên Ubuntu), và không phải là một web (/ etc/php5/apache2/php. ini)

tôi đoán bạn chỉ cần thiết lập php.ini có display_errors 0.

+0

Vâng - đó là những gì tôi đã suy nghĩ quá, nhưng tôi vẫn nhận được đầu ra lỗi (lạ) và đó là lý do tại sao tôi đã kết thúc đăng câu hỏi ... nó có thể là một lỗi? Tôi tự hỏi ... – rdlowrey

+0

Dù sao, +1 cho thời gian của bạn – rdlowrey

+0

Có thể. Bạn đang chỉnh sửa php.ini nào? Nếu bạn đang dùng ubuntu, có 2: /etc/php5/cli/php.ini và /etc/php5/apache2/php.ini. Nếu bạn chỉnh sửa một nhưng không phải là khác .. (Nhưng bạn có thể biết điều này, chỉ cần chạy qua các ý tưởng). – Cthos

Các vấn đề liên quan