Отсутствует ошибка в $@ для Perl Net::FTP

Выяснив (через SO, конечно), что ошибка для плохого $ftp = Net::FTP->new() вызова находится в $@, а последующие ошибки могут быть получены $ftp->message(), я столкнулся с небольшой проблемой.

Мой код в основном:

while (1) {
    # Wait for cycle start, then get file list into @filelist.

    foreach $file (@filelist) {
        my $ftp = Net::FTP->new ($host);
        if (! $ftp) {
            logError ("Could not connect to host [$host]: $@");
            return;
        }
        # More FTP stuff below with $ftp->message() error checking.
        $ftp->quit();
    }
}

В сторону: да, я знаю, что, вероятно, могу сделать это в одном FTP-сеансе, но на данный момент есть веские причины оставить это в отдельных сеансах.

Теперь это вызывается в цикле, один раз для каждого файла, все идет к одному и тому же хосту, но я получаю немного другое поведение с первой попытки в большинстве циклов. Сценарий является длительным, каждый цикл начинается через час и полчаса, поэтому это не проблема с первой попыткой после запуска программы, поскольку это происходит и в циклах, отличных от первого.

Теперь я знаю, что эти соединения не должны работать просто потому, что машины, к которым я пытаюсь получить доступ, недоступны в моей сети разработки.

Проблема в том, что ошибки, выходящие в файл журнала:

E 2012-02-05 18:00:13 Could not connect to host [example.com]: 
E 2012-02-05 18:00:13 Could not connect to host [example.com]:
    Net::FTP: connect: Connection refused
E 2012-02-05 18:00:14 Could not connect to host [example.com]:
    Net::FTP: connect: Connection refused

Как видите, переменная $@ кажется не заполненной в первом файле цикла. Я немного отредактировал этот вопрос, так как только что заметил, что в последнем цикле были все три строки с сообщением об ошибке. Вернемся к журналам с помощью команды:

grep refused logfile | awk '{print substr($3,1,5)}' | uniq -c

чтобы получить даты и подсчеты, появляется следующая статистика:

  3 11:00
  3 11:30
  3 12:00
  3 12:30
  3 13:00
  3 13:30
  2 14:00
  3 14:30
  3 15:00
  3 15:30
  3 16:00
  2 16:30
  2 17:00
  2 17:30
  2 18:00
  2 18:30
  2 19:00
  3 19:30

указывая на то, что некоторые из них имеют правильное количество сообщений об ошибках, но не все.

Мне интересно, если кто-нибудь знает, почему это может быть так.


person paxdiablo    schedule 05.02.2012    source источник


Ответы (2)


Попробуйте обновить http://cpansearch.perl.org/src/GBARR/libnet-1.22_01/Changes говорит

libnet 1.22_01 -- Mon May 31 09:40:25 CDT 2010
*Set $@ when ->new returns undef

Если вы используете версию libnet до 1.22_01, в ней была небольшая ошибка в функции new в отношении ответов, которые не начинались с кода.

Например, FTP.pm 2.77 из libnet 1.21 имеет следующий фрагмент:

unless ($ftp->response() == CMD_OK) {
    $ftp->close();
    $@ = $ftp->message;
    undef $ftp;
}

С FTP.pm 2.77_2 из libnet 1.22_01 это изменяется на:

unless ($ftp->response() == CMD_OK) {
    $ftp->close();
    # keep @$ if no message. Happens, when response did not start with a code.
    $@ = $ftp->message || $@;
    undef $ftp;
}
person obmib    schedule 05.02.2012

Происходит ли что-нибудь между вызовом ->new и печатью $@? Он может перезаписать значение $@, поэтому, если это необходимо, сохраните значение для последующего использования:

my $ftp = Net::FTP->new ($host);
my $potential_error = $@;

$whatever_that->can_call(eval => 'inside');

if (! $ftp) {
        logError ("Could not connect to host [$host]: $potential_error");
}
person choroba    schedule 05.02.2012
comment
Хорошая информация, но нет. В этом случае new, if и logError соответствуют точно тому, что показано в вопросе, без промежуточного кода. Есть обработчик сигнала, но он для TERM и устанавливает флаг для выхода, так что в данном случае этого не происходит (поскольку мы продолжаем работать). - person paxdiablo; 05.02.2012