Câu trả lời này được thiết kế như một khuôn khổ chung để giải quyết các vấn đề với tập lệnh Perl CGI và ban đầu xuất hiện trên Perlmonks dưới dạng Khắc phục sự cố tập lệnh Perl CGI . Nó không phải là một hướng dẫn đầy đủ cho mọi vấn đề mà bạn có thể gặp phải, cũng không phải là một hướng dẫn về cách xử lý lỗi. Đó chỉ là đỉnh cao của kinh nghiệm gỡ lỗi tập lệnh CGI của tôi trong hai mươi (cộng!) Năm. Trang này dường như có nhiều ngôi nhà khác nhau và tôi dường như quên rằng nó tồn tại, vì vậy tôi đang thêm nó vào StackOverflow. Bạn có thể gửi bất kỳ nhận xét hoặc đề xuất nào cho tôi tại bdfoy@cpan.org. Nó cũng là wiki cộng đồng, nhưng đừng quá điên rồ. :)
Bạn có đang sử dụng các tính năng được tích hợp sẵn của Perl để giúp bạn tìm ra sự cố không?
Bật cảnh báo để Perl cảnh báo bạn về những phần có vấn đề trong mã của bạn. Bạn có thể thực hiện việc này từ dòng lệnh với -w
nút chuyển để không phải thay đổi bất kỳ mã nào hoặc thêm pragma vào mọi tệp:
% perl -w program.pl
Tuy nhiên, bạn nên buộc mình phải luôn xóa mã có vấn đề bằng cách thêm warnings
pragma vào tất cả các tệp của mình:
use warnings;
Nếu bạn cần thêm thông tin ngoài thông báo cảnh báo ngắn, hãy sử dụng diagnostics
pragma để có thêm thông tin hoặc xem trong tài liệu perldiag :
use diagnostics;
Bạn có xuất tiêu đề CGI hợp lệ trước không?
Máy chủ đang mong đợi đầu ra đầu tiên từ tập lệnh CGI là tiêu đề CGI. Thông thường, điều đó có thể đơn giản như print "Content-type: text/plain\n\n";
hoặc với CGI.pm và các dẫn xuất của nó print header()
,. Một số máy chủ nhạy cảm với đầu ra lỗi (bật STDERR
) hiển thị trước đầu ra chuẩn (bật STDOUT
).
Thử gửi lỗi tới trình duyệt
Thêm dòng này
use CGI::Carp 'fatalsToBrowser';
vào kịch bản của bạn. Điều này cũng gửi lỗi biên dịch đến cửa sổ trình duyệt. Hãy chắc chắn loại bỏ điều này trước khi chuyển sang môi trường sản xuất, vì thông tin bổ sung có thể là một rủi ro bảo mật.
Nhật ký lỗi đã nói gì?
Máy chủ lưu giữ nhật ký lỗi (hoặc ít nhất là chúng nên). Lỗi đầu ra từ máy chủ và từ tập lệnh của bạn sẽ hiển thị ở đó. Tìm nhật ký lỗi và xem nó nói gì. Không có một nơi tiêu chuẩn cho các tệp nhật ký. Tìm trong cấu hình máy chủ để biết vị trí của chúng hoặc hỏi quản trị viên máy chủ. Bạn cũng có thể sử dụng các công cụ như CGI :: Cá chép
để giữ các tệp nhật ký của riêng bạn.
Các quyền của tập lệnh là gì?
Nếu bạn thấy các lỗi như "Quyền bị từ chối" hoặc "Phương pháp không được triển khai", điều đó có thể có nghĩa là tập lệnh của bạn không thể đọc và thực thi được bởi người dùng máy chủ web. Về hương vị của Unix, thay đổi chế độ để 755 được đề nghị:
chmod 755 filename
. Không bao giờ đặt chế độ thành 777!
Bạn đang sử dụng use strict
?
Hãy nhớ rằng Perl tự động tạo các biến khi bạn sử dụng chúng lần đầu tiên. Đây là một tính năng, nhưng đôi khi có thể gây ra lỗi nếu bạn nhập sai tên biến. Pragma
use strict
sẽ giúp bạn tìm ra những lỗi đó. Thật khó chịu cho đến khi bạn quen với nó, nhưng lập trình của bạn sẽ cải thiện đáng kể sau một thời gian và bạn có thể thoải mái mắc các lỗi khác nhau.
Tập lệnh có biên dịch không?
Bạn có thể kiểm tra lỗi biên dịch bằng cách sử dụng công -c
tắc. Tập trung vào các lỗi đầu tiên được báo cáo. Rửa sạch, lặp lại. Nếu bạn gặp phải lỗi thực sự lạ, hãy kiểm tra để đảm bảo rằng tập lệnh của bạn có phần cuối dòng phù hợp. Nếu bạn FTP ở chế độ nhị phân, kiểm tra từ CVS hoặc thứ gì khác không xử lý bản dịch cuối dòng, máy chủ web có thể thấy tập lệnh của bạn là một dòng lớn. Chuyển các tập lệnh Perl ở chế độ ASCII.
Tập lệnh có phàn nàn về các phụ thuộc không an toàn không?
Nếu tập lệnh của bạn phàn nàn về các phụ thuộc không an toàn, có thể bạn đang sử dụng công -T
tắc để bật chế độ taint, đây là một điều tốt vì nó giúp bạn truyền dữ liệu chưa được kiểm tra vào trình bao. Nếu nó phàn nàn, nó đang làm công việc của mình để giúp chúng tôi viết những đoạn script an toàn hơn. Bất kỳ dữ liệu nào có nguồn gốc từ bên ngoài chương trình (tức là môi trường) được coi là bị ô nhiễm. Các biến môi trường như PATH
và
LD_LIBRARY_PATH
đặc biệt rắc rối. Bạn phải đặt chúng thành giá trị an toàn hoặc bỏ đặt chúng hoàn toàn, như tôi khuyên bạn nên. Dù sao thì bạn cũng nên sử dụng đường dẫn tuyệt đối. Nếu việc kiểm tra chất bẩn phàn nàn về điều gì khác, hãy đảm bảo rằng bạn đã gỡ bỏ dữ liệu. Xem
trang người đàn ông perlsec để biết chi tiết.
Điều gì xảy ra khi bạn chạy nó từ dòng lệnh?
Tập lệnh có xuất ra những gì bạn mong đợi khi chạy từ dòng lệnh không? Đầu ra tiêu đề có đầu tiên, theo sau là một dòng trống? Hãy nhớ rằng điều đó STDERR
có thể được hợp nhất với STDOUT
nếu bạn đang ở trên một thiết bị đầu cuối (ví dụ: một phiên tương tác) và do bộ đệm có thể hiển thị theo một thứ tự lộn xộn. Bật tính năng autoflush của Perl bằng cách đặt $|
thành giá trị true. Thông thường bạn có thể thấy $|++;
trong các chương trình CGI. Sau khi thiết lập, mọi bản in và ghi sẽ ngay lập tức được chuyển đến đầu ra chứ không phải được lưu vào bộ đệm. Bạn phải thiết lập điều này cho mỗi bộ xử lý tệp. Sử dụng select
để thay đổi xử lý tệp mặc định, như sau:
$|++; #sets $| for STDOUT
$old_handle = select( STDERR ); #change to STDERR
$|++; #sets $| for STDERR
select( $old_handle ); #change back to STDOUT
Dù bằng cách nào, đầu ra đầu tiên phải là tiêu đề CGI, theo sau là một dòng trống.
Điều gì xảy ra khi bạn chạy nó từ dòng lệnh với môi trường giống như CGI?
Môi trường máy chủ web thường hạn chế hơn nhiều so với môi trường dòng lệnh của bạn và có thêm thông tin về yêu cầu. Nếu tập lệnh của bạn chạy tốt từ dòng lệnh, bạn có thể thử mô phỏng môi trường máy chủ web. Nếu sự cố xuất hiện, bạn có sự cố về môi trường.
Bỏ đặt hoặc xóa các biến này
PATH
LD_LIBRARY_PATH
- tất cả các
ORACLE_*
biến
Đặt các biến này
REQUEST_METHOD
(thiết lập để GET
, HEAD
hoặc POST
nếu thích hợp)
SERVER_PORT
(thường đặt thành 80)
REMOTE_USER
(nếu bạn đang làm công cụ truy cập được bảo vệ)
Các phiên bản gần đây của CGI.pm
(> 2,75) yêu cầu -debug
cờ phải có hành vi cũ (hữu ích), vì vậy bạn có thể phải thêm nó vào mục CGI.pm
nhập của mình .
use CGI qw(-debug)
Bạn đang sử dụng die()
hoặc warn
?
Các hàm đó được in ra STDERR
trừ khi bạn đã định nghĩa lại chúng. Chúng cũng không xuất ra tiêu đề CGI. Bạn có thể nhận được chức năng tương tự với các gói như CGI :: Cá chép
Điều gì xảy ra sau khi bạn xóa bộ nhớ cache của trình duyệt?
Nếu bạn cho rằng tập lệnh của mình đang làm đúng và khi thực hiện yêu cầu theo cách thủ công, bạn nhận được đầu ra phù hợp, thì trình duyệt có thể là thủ phạm. Xóa bộ nhớ cache và đặt kích thước bộ nhớ cache thành 0 trong khi kiểm tra. Hãy nhớ rằng một số trình duyệt thực sự ngu ngốc và sẽ không thực sự tải lại nội dung mới ngay cả khi bạn yêu cầu nó làm như vậy. Điều này đặc biệt phổ biến trong trường hợp đường dẫn URL giống nhau, nhưng nội dung thay đổi (ví dụ: hình ảnh động).
Kịch bản có đúng như bạn nghĩ không?
Đường dẫn hệ thống tệp đến một tập lệnh không nhất thiết phải liên quan trực tiếp đến đường dẫn URL đến tập lệnh. Đảm bảo rằng bạn có đúng thư mục, ngay cả khi bạn phải viết một đoạn mã thử nghiệm ngắn để kiểm tra điều này. Hơn nữa, bạn có chắc chắn rằng bạn đang sửa đổi đúng tệp không? Nếu bạn không thấy bất kỳ tác dụng nào với các thay đổi của mình, có thể bạn đang sửa đổi một tệp khác hoặc tải tệp lên không đúng nơi. (Nhân tiện, đây là nguyên nhân thường xuyên nhất của tôi gây ra rắc rối như vậy;)
Bạn đang sử dụng CGI.pm
, hay một dẫn xuất của nó?
Nếu vấn đề của bạn có liên quan đến phân tích đầu vào CGI và bạn không sử dụng một mô-đun thử nghiệm rộng rãi như CGI.pm
, CGI::Request
,
CGI::Simple
hoặc CGI::Lite
, sử dụng các mô-đun và nhận được về với cuộc sống.
CGI.pm
có cgi-lib.pl
chế độ tương thích có thể giúp bạn giải quyết các vấn đề đầu vào do triển khai trình phân tích cú pháp CGI cũ hơn.
Bạn đã sử dụng đường dẫn tuyệt đối?
Nếu bạn đang chạy các lệnh bên ngoài với
system
, dấu tích quay lại hoặc các tiện ích IPC khác, bạn nên sử dụng một đường dẫn tuyệt đối đến chương trình bên ngoài. Bạn không chỉ biết chính xác những gì bạn đang chạy mà còn tránh được một số vấn đề về bảo mật. Nếu bạn đang mở tệp để đọc hoặc ghi, hãy sử dụng một đường dẫn tuyệt đối. Tập lệnh CGI có thể có ý tưởng khác về thư mục hiện tại với bạn. Ngoài ra, bạn có thể làm rõ ràng chdir()
để đưa bạn vào đúng vị trí.
Bạn đã kiểm tra các giá trị trả lại của mình chưa?
Hầu hết các hàm Perl sẽ cho bạn biết nếu chúng hoạt động hay không và sẽ đặt $!
khi thất bại. Bạn đã kiểm tra giá trị trả về và kiểm tra $!
thông báo lỗi chưa? Bạn đã kiểm tra
$@
xem mình đang sử dụng eval
chưa?
Bạn đang sử dụng phiên bản Perl nào?
Phiên bản ổn định mới nhất của Perl là 5.28 (hoặc không, tùy thuộc vào thời điểm điều này được chỉnh sửa lần cuối). Bạn đang sử dụng phiên bản cũ hơn? Các phiên bản khác nhau của Perl có thể có các ý tưởng cảnh báo khác nhau.
Bạn đang sử dụng máy chủ web nào?
Các máy chủ khác nhau có thể hoạt động khác nhau trong cùng một tình huống. Cùng một sản phẩm máy chủ có thể hoạt động khác nhau với các cấu hình khác nhau. Bao gồm càng nhiều thông tin này càng tốt trong bất kỳ yêu cầu trợ giúp nào.
Bạn đã kiểm tra tài liệu máy chủ chưa?
Các lập trình viên CGI nghiêm túc nên biết càng nhiều càng tốt về máy chủ - không chỉ bao gồm các tính năng và hành vi của máy chủ mà còn cả cấu hình cục bộ. Tài liệu về máy chủ của bạn có thể không có sẵn cho bạn nếu bạn đang sử dụng sản phẩm thương mại. Nếu không, tài liệu sẽ nằm trên máy chủ của bạn. Nếu không, hãy tìm nó trên web.
Việc sử dụng này rất hữu ích nhưng tất cả các áp phích tốt đều đã chết hoặc biến mất.
Có khả năng ai đó đã gặp vấn đề của bạn trước đây và ai đó (có thể là tôi) đã giải đáp vấn đề đó trong nhóm tin này. Mặc dù nhóm tin này đã qua thời kỳ hoàng kim, nhưng những thông thái thu thập được từ quá khứ đôi khi có thể hữu ích.
Bạn có thể tái tạo sự cố bằng một tập lệnh thử nghiệm ngắn không?
Trong các hệ thống lớn, có thể khó tìm ra lỗi vì có rất nhiều thứ đang xảy ra. Cố gắng tái tạo hành vi sự cố bằng tập lệnh ngắn nhất có thể. Biết được vấn đề là cách khắc phục hầu hết. Điều này chắc chắn tốn thời gian nhưng bạn vẫn chưa tìm ra vấn đề và sắp hết các lựa chọn. :)
Bạn đã quyết định đi xem một bộ phim?
Nghiêm túc. Đôi khi chúng ta có thể bị cuốn vào vấn đề đến mức chúng ta phát triển "thu hẹp tri giác" (tầm nhìn đường hầm). Nghỉ giải lao, uống một tách cà phê hoặc đánh bại một số kẻ xấu trong [Duke Nukem, Quake, Doom, Halo, COD] có thể cung cấp cho bạn góc nhìn mới mẻ mà bạn cần để tiếp cận lại vấn đề.
Bạn đã nói ra vấn đề chưa?
Nghiêm túc một lần nữa. Đôi khi giải thích vấn đề một cách to tiếng sẽ dẫn chúng ta đến câu trả lời của chính mình. Nói chuyện với chim cánh cụt (đồ chơi sang trọng) vì đồng nghiệp của bạn không lắng nghe. Nếu bạn quan tâm đến công cụ này như một công cụ gỡ lỗi nghiêm trọng (và tôi khuyên bạn nên sử dụng nó nếu bạn vẫn chưa tìm ra vấn đề ngay bây giờ), bạn cũng có thể thích đọc Tâm lý học của lập trình máy tính .