.cgi работает в командной строке, но не на веб-сайте ERROR 500 [дубликат]

Это означает, что вы пытаетесь манипулировать тем, что имеет ссылку, но еще не инициализировано. Первое, что нужно сделать, это проверить каждый созданный экземпляр. Используйте контрольные точки, часы, проверяйте свои значения varibale. Следить за трассировкой стека и искать точные строки и столбцы, которые создают проблему

96
задан 2 revs 29 January 2010 в 21:53
поделиться

8 ответов

120
ответ дан 15 revs, 7 users 79% 4 September 2018 в 10:10
поделиться

Вы можете запустить perl cgi-script в терминале, используя следующую команду

 $ perl filename.cgi

. Он интерпретирует код и предоставляет результат с кодом HTML. Он сообщит об ошибке, если таковой имеется.

0
ответ дан 2 revs, 2 users 83% 4 September 2018 в 10:10
поделиться
  • 1
    Извините, команда $ perl -c filename.cgi проверяет синтаксис кода и сообщает об ошибке, если таковая имеется. Он не будет предоставлять html-код cgi. – D.Karthikeyan 6 April 2016 в 04:07
  • 2
    Вызов perl -c filename будет действительно проверять только синтаксис. Но perl filename выводит вывод HTML. Это не гарантирует, что не будет ошибки 500 CGI, но это хороший первый тест. – Nagev 18 May 2018 в 14:46

Я думаю, что CGI :: Debug стоит упомянуть.

10
ответ дан 2 revs, 2 users 86% 4 September 2018 в 10:10
поделиться
  • 1
    Это сообщество wiki, поэтому wiki прочь :) – brian d foy 29 January 2010 в 21:52
  • 2
    К сожалению, я могу только отредактировать вопрос, а не ответы. – Mikael S 29 January 2010 в 22:31

Вероятно, стоит также упомянуть, что Perl всегда расскажет вам, в какой строке возникает ошибка при выполнении сценария Perl из командной строки. (Например, сеанс SSH)

Я обычно делаю это, если все остальное не работает. Я буду использовать SSH на сервере и вручную выполнить скрипт Perl. Например:

% perl myscript.cgi 

Если возникла проблема, Perl расскажет вам об этом. Этот метод отладки устраняет любые проблемы с разрешением файла или проблемы с веб-браузером или веб-сервером.

1
ответ дан 2 revs, 2 users 93% 4 September 2018 в 10:10
поделиться
  • 1
    Perl не всегда указывает номер строки, где возникает ошибка. Он сообщает вам номер строки, где он понимает, что что-то не так. Вероятно, ошибка уже произошла. – brian d foy 5 February 2014 в 17:10

Интересно, почему никто не упомянул вариант PERLDB_OPTS, названный RemotePort; хотя, по общему признанию, в Интернете мало рабочих примеров (RemotePort даже не упоминается в perldebug ) - и для меня было довольно проблематично придумать это, но здесь оно (это пример Linux).

Чтобы сделать правильный пример, сначала мне понадобилось что-то, что могло бы сделать очень простое моделирование веб-сервера CGI, желательно через одну командную строку. После нахождения Простой веб-сервер командной строки для запуска cgis. (perlmonks.org) , я нашел для этого теста IO :: All - A Tiny Web Server .

Здесь я буду работать в каталог /tmp; сценарий CGI будет /tmp/test.pl (см. ниже). Обратите внимание, что сервер IO::All будет обслуживать только исполняемые файлы в том же каталоге, что и CGI, поэтому здесь требуется chmod +x test.pl. Итак, чтобы выполнить обычный тестовый прогон CGI, я меняю каталог на /tmp в терминале и запускаю там один веб-сервер:

$ cd /tmp
$ perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

Команда webserver будет блокироваться в терминале, и в противном случае запустит веб-сервер локально (на 127.0.0.1 или localhost) - впоследствии я могу перейти в веб-браузер и запросить этот адрес:

http://127.0.0.1:8080/test.pl

... и я должен обратите внимание на print s, сделанные с помощью test.pl, загружаемых - и показаны - в веб-браузере.


Теперь, чтобы отладить этот скрипт с RemotePort, сначала нам понадобится слушателя в сети, через который мы будем взаимодействовать с отладчиком Perl; мы можем использовать инструмент командной строки netcat (nc, увиденный здесь: Perl 如何 удаленная отладка? ). Итак, сначала запустите прослушиватель netcat в одном терминале, где он будет блокировать и ждать подключения на порту 7234 (который будет нашим портом отладки):

$ nc -l 7234

Затем нам нужно perl для запуска в режиме отладки с RemotePort, когда test.pl был вызван (даже в режиме CGI, через сервер). Это можно сделать в Linux, используя следующий сценарий «shebang wrapper», который также должен находиться в /tmp, а должен быть выполнен :

cd /tmp

cat > perldbgcall.sh <<'EOF'
#!/bin/bash
PERLDB_OPTS="RemotePort=localhost:7234" perl -d -e "do '$@'"
EOF

chmod +x perldbgcall.sh

Это своего рода сложная вещь - см. Сценарий оболочки - Как я могу использовать переменные среды в моем shebang? - Unix & amp; Linux Stack Exchange . Но трюк здесь, кажется, не , чтобы развить интерпретатор perl, который обрабатывает test.pl - поэтому, как только мы его ударим, мы не exec, но вместо этого мы вызываем perl «прямо» и в основном «источник» нашего скрипта test.pl с использованием do (см. . Как запустить скрипт Perl из скрипта Perl? ).

Теперь что у нас есть perldbgcall.sh в /tmp - мы можем изменить файл test.pl, так что он ссылается на этот исполняемый файл на своей строке shebang (вместо обычного интерпретатора Perl) - здесь /tmp/test.pl изменено таким образом:

#!./perldbgcall.sh

# this is test.pl

use 5.10.1;
use warnings;
use strict;

my $b = '1';
my $a = sub { "hello $b there" };
$b = '2';
print "YEAH " . $a->() . " CMON\n";
$b = '3';
print "CMON " . &$a . " YEAH\n";

$DB::single=1;  # BREAKPOINT

$b = '4';
print "STEP " . &$a . " NOW\n";
$b = '5';
print "STEP " . &$a . " AGAIN\n";

Теперь оба test.pl и его новый обработчик shebang, perldbgcall.sh, находятся в /tmp; и мы nc слушаем отладочные соединения на порту 7234 - поэтому мы можем, наконец, открыть другое окно терминала, сменить каталог на /tmp и запустить веб-сервер с одним слоем (который будет прослушивать веб-соединения на порту 8080):

cd /tmp
perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

После этого мы можем перейти в наш веб-браузер и запросить тот же адрес, http://127.0.0.1:8080/test.pl. Однако теперь, когда веб-сервер пытается выполнить скрипт, он сделает это через perldbgcall.sh shebang - который запустит perl в режиме удаленного отладчика. Таким образом, выполнение скрипта приостанавливается - и поэтому веб-браузер блокируется, ожидая данных. Теперь мы можем переключиться на терминал netcat, и мы должны увидеть знакомый текст отладчика Perl, однако вывести его через nc:

$ nc -l 7234

Loading DB routines from perl5db.pl version 1.32
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   do './test.pl'
  DB<1> r
main::(./test.pl:29):   $b = '4';
  DB<1>

. Как показывает фрагмент, теперь мы в основном используем nc как «терминал», поэтому мы можем ввести r (и Enter) для «run» - и скрипт будет запускаться с помощью инструкции breakpoint (см. также В perl, в чем разница между $ DB: : single = 1 и 2? ), прежде чем снова остановиться (обратите внимание, что в этот момент браузер все равно заблокируется).

Итак, теперь мы можем, скажем, пройти через остальные test.pl через терминал nc:

....
main::(./test.pl:29):   $b = '4';
  DB<1> n
main::(./test.pl:30):   print "STEP " . &$a . " NOW\n";
  DB<1> n
main::(./test.pl:31):   $b = '5';
  DB<1> n
main::(./test.pl:32):   print "STEP " . &$a . " AGAIN\n";
  DB<1> n
Debugged program terminated.  Use q to quit or R to restart,
  use o inhibit_exit to avoid stopping after program termination,
  h q, h R or h o to get additional info.
  DB<1>

... однако, также в этот момент браузер блокирует и ждет данных. Только после выхода из отладчика с q:

  DB<1> q
$

... блокирует блокировку браузера и, наконец, отображает (полный) вывод test.pl:

YEAH hello 2 there CMON
CMON hello 3 there YEAH
STEP hello 4 there NOW
STEP hello 5 there AGAIN

Конечно, такой отладочный процесс можно сделать даже без запуска веб-сервера, однако, в этом случае, мы не трогаем веб-сервер; мы запускаем выполнение «изначально» (для CGI) из веб-браузера - и единственным изменением, необходимым для самого скрипта CGI, является изменение shebang (и, конечно же, наличие скрипта оболочки shebang в качестве исполняемого файла в том же директория).

Ну, надеюсь, это поможет кому-то - я бы наверняка любил бы наткнуться на это, вместо того, чтобы писать сам :) Cheers!

8
ответ дан 3 revs 4 September 2018 в 10:10
поделиться

Используете ли вы обработчик ошибок во время отладки?

die операторы и другие фатальные ошибки времени выполнения и времени компиляции печатаются на STDERR, которые трудно найти и могут быть объединены с сообщениями с других веб-страниц вашего сайта. Хотя вы отлаживаете свой сценарий, неплохо было бы получить сообщения о фатальных ошибках для отображения в вашем браузере.

Один из способов сделать это - вызвать

   use CGI::Carp qw(fatalsToBrowser);

в верхней части вашего скрипта. Этот вызов установит обработчик $SIG{__DIE__} (см. perlvar ) отображает фатальные ошибки в вашем браузере, добавляя при необходимости допустимый заголовок. Другой трюк отладки CGI, который я использовал до того, как я когда-либо слышал о CGI::Carp, состоял в том, чтобы использовать eval с возможностями DATA и __END__ в скрипте для обнаружения ошибок времени компиляции:

   #!/usr/bin/perl
   eval join'', <DATA>;
   if ($@) { print "Content-type: text/plain:\n\nError in the script:\n$@\n; }
   __DATA__
   # ... actual CGI script starts here

Этот более подробный метод имеет небольшое преимущество перед CGI::Carp в том, что он будет ловить больше ошибок времени компиляции.

Обновление: я никогда не использовал его, но он выглядит как CGI::Debug , как предложил Mikael S, также является очень полезным и настраиваемым инструментом для этой цели.

7
ответ дан 4 revs, 2 users 98% 4 September 2018 в 10:10
поделиться
  • 1
    Я смотрю на этот фрагмент кода, пытаясь понять, как это работает ... – Ether 30 January 2010 в 05:18
  • 2
    @Ether: <DATA> - волшебный дескриптор файла, который читает текущий скрипт, начиная с __END__. Join предоставляет контекст списка, поэтому & lt; fh & gt; возвращает массив, по одной строке на элемент. Затем объединение объединяет его (соединяет его с ''). Наконец, eval. – derobert 9 September 2010 в 20:04
  • 3
    @Ether: более читаемым способом записи строки 2 будет: eval join(q{}, <DATA>); – derobert 9 September 2010 в 20:06
  • 4
    @derobert: на самом деле, __DATA__ - это токен, используемый для начала раздела данных, а не __END__ (я думаю, что это была моя путаница). – Ether 9 September 2010 в 20:17
  • 5
    @Ether: На самом деле, они оба работают в сценарии верхнего уровня (согласно man-странице perldata). Но поскольку DATA является предпочтительным, я изменил ответ. – derobert 10 September 2010 в 17:50

Честно говоря, вы можете сделать все самое интересное над этим сообщением. ALTHOUGH, самое простое и наиболее проактивное решение, которое я нашел, это просто «распечатать его».

В примере: (Обычный код)

`$somecommand`;

Чтобы узнать, делает ли он то, что я действительно хочу, чтобы он делал: (Устранение неполадок)

print "$somecommand";
1
ответ дан Ilan Kleiman 4 September 2018 в 10:10
поделиться

Для меня я использую log4perl . Это очень полезно и легко.

use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init( { level   => $DEBUG, file    => ">>d:\\tokyo.log" } );

my $logger = Log::Log4perl::get_logger();

$logger->debug("your log message");
5
ответ дан zawhtut 4 September 2018 в 10:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: