How can I pause Perl processing without hardcoding?

I have a Perl script that contains this piece of code that calls the system shell to get some files over SFTP and unzip them using 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";
}

      

Even if some files are extracted, they are never unpacked, because by the time the files were restored and the SFTP interface closed, the Perl script had already completed the unzip stage, with the result that it could not find anything to unpack.

My short fix is ​​to insert

sleep(60);

      

before the decompression step, but the SFTP connection is assumed to complete within 60 seconds, which can sometimes be a gross over-estimate and other times an underestimate.

Is there a more reliable way to get Perl to suspend before closing the SFTP connection before continuing with the unzip step?

Edit: The respondents have questioned (and this is reasonable) using a VB script instead of Perl doing the file transfer. This is for security - the VB script is maintained by others and has the authority to do SFTP.

+1


a source to share


8 answers


Check the code in the * .vbs file. The function system

waits for the child process to finish before completing execution. It looks like your * .vbs file creates a focal task for FTP work and returns immediately.



+12


a source


In an ideal world, your script would be rewritten to use Net :: SFTP :: Foreign and Archive :: Extract ..

An ugly quick hacky way might be to create a touchfile before the first system call, change the sftp-fetching script to delete the file after it finishes, and do it something like this



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

# foreach [...]

      

Of course, you will need to take care that your .vbs fails and leaves the recovered touch file and many other bad side effects. This would be for a quick fix (if none of the other suggestions work), until you get time to rewrite without system () calls.

+6


a source


You need Perl to wait until the SFTP transfer is done, but since your script is currently being written, Perl is unaware of this. (It looks like you are combining at least two scripting languages ​​and (SFI-client GUI?) This might work, but it is not exactly reliable or reliable. Why use VBscript to trigger an SFTP transfer?)

I can imagine four options:

  • Your Perl script could send the SFTP transfer itself using something like CPAN Net :: SFTP , rather than creating an irregular job that it can't keep track of.
  • Your Perl script can invoke a command line SFTP utility (like PSFTP ), which doesn't return until the transfer is complete,
  • Or change the exec_SFTP.vbs script so that it doesn't return until the transfer is complete.
  • If you are using a graphical SFTP client and cannot switch for any reason, I would recommend using a scripting language like AutoIt instead of Perl. AutoIt has functions to wait for windows to change state, etc. so that it can more easily track the completion of an activity.

Options 1 or 2 will be the most reliable and reliable.

+4


a source


The best I can suggest is to modify exec_SFTP.vbs to only exit after the file transfer is complete. system

is waiting for the program it has called to terminate to solve your problem:

       system LIST
       system PROGRAM LIST
               Does exactly the same thing as "exec LIST", except
               that a fork is done first, and the parent process
               waits for the child process to complete .
+3


a source


If you cannot modify the vbs script to stay alive until after it finishes, you should be able to track the creation of the subprocess. If you get subprocess IDs, you can control them so you know when different vbs offspring will terminate.

Win32 :: Process :: Info allows you to get subprocess IDs from a running process.

+2


a source


This might be a silly question, but why not just use Net :: SFTP and Archive :: Extract Perl modules to download and decompress files?

+1


a source


Have a look at IPC :: Open3

IPC :: Open3 - open read, write and error handling with open3 ()

0


a source


system

will not return until the shell in which the command was run returns; it may not be correct to run graphics programs and file associations.

See if there is any of the following references:

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


a source







All Articles