Как я могу приостановить обработку Perl без жесткого кодирования продолжительности? - PullRequest
1 голос
/ 19 мая 2009

У меня есть сценарий Perl, который содержит этот фрагмент кода, который вызывает системную оболочку для получения некоторых файлов по SFTP и разархивирования их с помощью WinZip:

#  Run script to get files from remote server
system "exec_SFTP.vbs";

#  Unzip any files that were retrieved
foreach $zipFile (<*.zip>) {
    system "wzunzip $zipFile";
}

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

Мое краткосрочное исправление - вставить

sleep(60);

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

Есть ли более разумный способ заставить Perl приостановить работу, пока SFTP-соединение не будет закрыто, прежде чем приступить к операции распаковки?

Редактировать: Ответчики подвергли сомнению (и вполне обоснованно) использование сценария VB вместо того, чтобы Perl выполнял передачу файла. Это связано с безопасностью - скрипт VB поддерживается другими пользователями и имеет право выполнять SFTP.

Ответы [ 8 ]

12 голосов
/ 19 мая 2009

Проверьте код в вашем * .vbs файле. Функция system ожидает завершения дочернего процесса перед продолжением выполнения. Похоже, что ваш * .vbs файл разветвляется на фоновую задачу для выполнения FTP и немедленно возвращается.

6 голосов
/ 20 мая 2009

В идеальном мире ваш скрипт будет переписан для использования Net :: SFTP :: Foreign и Archive :: Extract ..

Уродливый способ быстрого взлома может состоять в том, чтобы создать сенсорный файл перед вашим первым системным вызовом, изменить скрипт извлечения sftp, чтобы удалить файл, как только он будет сделан, и какое-то время так делать

while(-e 'touch.file') {
    sleep 5;
}

# foreach [...]

Конечно, вам нужно будет позаботиться, если ваш .vbs выходит из строя и оставляет сенсорный файл невостребованным и многие другие плохие побочные эффекты. Это было бы для быстрого решения (если ни одно из других предложений не работает), пока вы не получите время переписать без системных вызовов ().

4 голосов
/ 19 мая 2009

Вам нужен способ для Perl ждать, пока передача SFTP не будет выполнена, но, поскольку ваш сценарий в настоящее время написан, Perl не может этого знать. (Похоже, вы объединяете как минимум два языка сценариев и SFTP-клиент (GUI?); Это может работать, но оно не совсем надежно или надежно. Зачем использовать VBscript для запуска передачи SFTP?)

Я могу придумать четыре варианта:

  1. Ваш Perl-скрипт может сам выполнять передачу SFTP, используя что-то вроде Net :: SFTP модуля CPAN, вместо того, чтобы создавать внешнее задание, состояние которого он не может отслеживать.
  2. Ваш сценарий Perl может порождать служебную программу SFTP из командной строки (например, PSFTP ), которая не возвращается до завершения передачи.
  3. Или измените сценарий exec_SFTP.vbs, чтобы он не возвращался до тех пор, пока передача не будет завершена.
  4. Если вы в настоящее время используете графический SFTP-клиент и по какой-либо причине не можете переключиться, я бы рекомендовал использовать язык сценариев, например AutoIt вместо Perl. В AutoIt есть функции, позволяющие ожидать изменения состояния окон и т. Д., Чтобы упростить отслеживание завершения операции.

Варианты 1 или 2 будут наиболее надежными и надежными.

3 голосов
/ 19 мая 2009

Лучшее, что я могу предложить, - это изменить exec_SFTP.vbs так, чтобы он выходил только после завершения передачи файла. system ожидает завершения программы, вызвавшей ее, чтобы решить вашу проблему:

       system LIST
       system PROGRAM LIST
               Does exactly the same thing as "exec LIST", except
               that a fork is done first, <b>and the parent process
               waits for the child process to complete</b>.
2 голосов
/ 20 мая 2009

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

Win32 :: Process :: Info позволяет получить идентификаторы подпроцесса из запущенного процесса.

1 голос
/ 20 мая 2009

Может быть, это глупый вопрос, но почему бы просто не использовать модули Perl Net :: SFTP и Archive :: Extract для загрузки и распаковки файлов?

0 голосов
/ 20 мая 2009

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

Смотрите, если какая-либо из следующих справок?

system('cscript exec_SFTP.vbs');

use Win32::Process;
use Win32;
Win32::Process::Create(my $proc, 'wscript.exe',
        'wscript exec_SFTP.vbs', 0, NORMAL_PRIORITY_CLASS, '.');
$proc->Wait(INFINITE);
0 голосов
/ 19 мая 2009

Посмотрите на IPC :: Open3

IPC :: Open3 - открыть процесс для чтения, записи и обработки ошибок с использованием open3 ()

...