Это короткое выражение 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 находится внутри функции, то он не будет выполняться до тех пор, пока не будет вызвана функция.
Вы можете запустить perl cgi-script в терминале, используя следующую команду
$ perl filename.cgi
. Он интерпретирует код и предоставляет результат с кодом HTML. Он сообщит об ошибке, если таковой имеется.
perl -c filename
будет действительно проверять только синтаксис. Но perl filename
выводит вывод HTML. Это не гарантирует, что не будет ошибки 500 CGI, но это хороший первый тест.
– Nagev
18 May 2018 в 14:46
Я думаю, что CGI :: Debug стоит упомянуть.
Вероятно, стоит также упомянуть, что Perl всегда расскажет вам, в какой строке возникает ошибка при выполнении сценария Perl из командной строки. (Например, сеанс SSH)
Я обычно делаю это, если все остальное не работает. Я буду использовать SSH на сервере и вручную выполнить скрипт Perl. Например:
% perl myscript.cgi
Если возникла проблема, Perl расскажет вам об этом. Этот метод отладки устраняет любые проблемы с разрешением файла или проблемы с веб-браузером или веб-сервером.
Интересно, почему никто не упомянул вариант 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!
Используете ли вы обработчик ошибок во время отладки?
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, также является очень полезным и настраиваемым инструментом для этой цели.
<DATA>
- волшебный дескриптор файла, который читает текущий скрипт, начиная с __END__
. Join предоставляет контекст списка, поэтому & lt; fh & gt; возвращает массив, по одной строке на элемент. Затем объединение объединяет его (соединяет его с ''). Наконец, eval.
– derobert
9 September 2010 в 20:04
eval join(q{}, <DATA>);
– derobert
9 September 2010 в 20:06
Честно говоря, вы можете сделать все самое интересное над этим сообщением. ALTHOUGH, самое простое и наиболее проактивное решение, которое я нашел, это просто «распечатать его».
В примере: (Обычный код)
`$somecommand`;
Чтобы узнать, делает ли он то, что я действительно хочу, чтобы он делал: (Устранение неполадок)
print "$somecommand";
Для меня я использую 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");