500 на бинарный скомпилированный сценарий CGI после перехода на новые серверы [дубликат]

Это короткое выражение Immediately Invoked Function / или IIFE . Он выполняется сразу после его создания.

Он не имеет никакого отношения к любому обработчику событий для любых событий (например, document.onload). Рассмотрим часть в первой паре круглых скобок: (function(){})(); .... это регулярное объявление функции. Затем посмотрите на последнюю пару (function(){})();, это обычно добавляется к выражению для вызова функции; в этом случае наше предыдущее выражение.

Этот шаблон часто используется при попытке избежать загрязнения глобального пространства имен, поскольку все переменные, используемые внутри IIFE (как и в любом другом нормальном функция) не видны за пределами ее объема. Вот почему, может быть, вы путаете эту конструкцию с обработчиком событий для window.onload, потому что это часто используется как это:

(function(){
    // all your code here
    var foo = function() {};
    window.onload = foo;
    // ...
})();
// foo is unreachable here (it’s undefined)

Исправление, предложенное Guffa :

Функция выполняется сразу после ее создания, а не после ее анализа. Весь блок сценария анализируется до того, как будет выполнен любой его код. Кроме того, код разбора автоматически не означает, что он выполнен, если, например, IIFE находится внутри функции, то он не будет выполняться до тех пор, пока не будет вызвана функция.

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

8 ответов

120
ответ дан 14 revs, 7 users 78% 22 August 2018 в 18:18
поделиться

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

 $ perl filename.cgi

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

0
ответ дан 2 revs, 2 users 83% 22 August 2018 в 18:18
поделиться
  • 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% 22 August 2018 в 18:18
поделиться
  • 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% 22 August 2018 в 18:18
поделиться
  • 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!

7
ответ дан 3 revs 22 August 2018 в 18:18
поделиться

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

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% 22 August 2018 в 18:18
поделиться
  • 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 22 August 2018 в 18:18
поделиться

Для меня я использую 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");
4
ответ дан zawhtut 22 August 2018 в 18:18
поделиться
Другие вопросы по тегам:

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