Назад | Перейти на главную страницу

Perl FTP-скрипт не работает из crontab, работает из cmd

У нас есть Perl-скрипт, который мы использовали (запущенный из crontab) в течение нескольких лет для загрузки изображений с помощью Net :: FTP. В последнее время мы начали замечать проблемы, когда изображения не загружались, а в логах появлялись ошибки.

При устранении неполадок я обнаружил, что в настоящее время программа работает нормально при запуске из строки cmd, но при запуске из crontab она постоянно выдает ошибки. На удаленном сервере я вижу в журнале FTP, что соединение все еще активно, клиент меняет каталоги, но команда STOR никогда не появляется, как при обычных обстоятельствах. На стороне клиента, когда выдается ftp-> put, ответ выглядит как «227 Entering Passive Mode».

Я пробовал все, что мог придумать, чтобы отследить причину (брандмауэры, эфемерные порты, утечки памяти), но пока мое единственное решение - запустить его вручную из строки cmd.

Кто-нибудь знает, в чем может быть причина этой проблемы?

Обновление: вот некоторые результаты Debug => 1:

При запуске из crontab и он не работает (последняя строка 'ERROR' берется из сценария perl и включает сообщение $ ftp->, которое является «Входом в пассивный режим»):

Net::FTP=GLOB(0xa004910)>>> CWD /images/shots
Net::FTP=GLOB(0xa004910)<<< 250 CWD command successful
Net::FTP=GLOB(0xa004910)>>> PASV
Net::FTP=GLOB(0xa004910)<<< 227 Entering Passive Mode (181,71,41,114,114,112).
ERROR: Couldn't put file /home/user/data/shot/212/212474.000078.jpg to f/4/f41891045708388275a0b1d1fe8a34fa.jpg on 127.0.0.1 because Entering Passive Mode (181,71,41,114,114,112).

При запуске из командной строки и успешно:

Net::FTP=GLOB(0x8619170)>>> CWD /images/shots
Net::FTP=GLOB(0x8619170)<<< 250 CWD command successful
Net::FTP=GLOB(0x8619170)>>> PASV
Net::FTP=GLOB(0x8619170)<<< 227 Entering Passive Mode (181,71,41,114,113,179).
Net::FTP=GLOB(0x8619170)>>> STOR 5/6/569e214479a6f99f5bdf920e75f8351e.jpg
Net::FTP=GLOB(0x8619170)<<< 150 Opening BINARY mode data connection for 5/6/569e214479a6f99f5bdf920e75f8351e.jpg
Net::FTP=GLOB(0x8619170)<<< 226 Transfer complete

И вот часть скрипта, которая это делает:

      if ( ! ( $ftp->put($src_file, $target_file) ) ) {
        print STDERR "ERROR: Couldn't put file $src_file to $target_file on $ftp_host because " . $ftp->message . "\n";
      } else {
        $mv_result = 1;
      }

Сервер запускает stunnel, поэтому FTP-соединение инициируется через порт на локальном хосте (127.0.0.1)

Обновление: хорошо, я понял, что происходит, есть аргумент, переданный от crontab, который сообщает ему, какую сеть использовать. Оказывается, модем в этой сети выходит из строя, и я по глупости не передавал этот аргумент в строке cmd, наша сеть по умолчанию работает отлично. нам просто нужен новый модем для нашей выделенной линии загрузки. Большое спасибо за помощь, Штеффен.

Сервер запускает stunnel, поэтому FTP-соединение инициируется через порт на локальном хосте (127.0.0.1)

Я сомневаюсь, что это сработает. FTP требуется управляющее соединение, которое можно туннелировать через stunnel. Но в дополнение к этому для каждой передачи данных необходимы соединения (STOR, RETR, LIST ...).

Вы действительно используете ту же настройку в рабочей командной строке?

<<< 227 Entering Passive Mode (181,71,41,114,114,112).

Это означает, что сервер хочет иметь соединение для передачи данных на IP 181.71.41.114, порт 28024 (114 * 245 + 112). Таким образом, Net :: FTP попытается подключиться к этому адресу напрямую, потому что он ничего не знает о туннеле и не сможет с ним справиться. Я предполагаю, что у вас есть stunnel, потому что прямое соединение с целевым сервером не работает, поэтому эта попытка подключения не удастся.