如何在不对持续时间进行硬编码的情况下暂停Perl处理?

时间:2009-05-19 19:44:21

标签: perl dynamic duration

我有一个包含此代码段的Perl脚本,它调用系统shell以通过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 个答案:

答案 0 :(得分:12)

检查* .vbs文件中的代码。 system函数在执行继续之前等待子进程完成。您的* .vbs文件似乎正在分配后台任务来执行FTP并立即返回。

答案 1 :(得分:6)

在完美的世界中,您的脚本会被重写以使用Net::SFTP::ForeignArchive::Extract ..

一种丑陋的快速hackish方式可能是在你第一次系统调用之前创建一个触摸文件,改变你的sftp-fetching脚本,一旦完成就删除文件并且有一段时间这样

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

# foreach [...]

当然,如果你的.vbs失败并且没有删除触摸文件和许多其他不良副作用,你需要注意。这将是一个快速的解决方案(如果没有其他建议工作),直到你没有系统()调用重写时间。

答案 2 :(得分:4)

你需要一种方法让Perl等到SFTP传输完成,但是当你的脚本当前被写入时,Perl无法知道这一点。 (看起来你正在组合至少两种脚本语言和一个(GUI?)SFTP客户端;这可以工作,但它不完全可靠或健壮。为什么使用VBscript启动SFTP传输?)

我可以想到四个选项:

  1. 您的Perl脚本可以使用类似CPAN的Net::SFTP模块进行SFTP传输,而不是生成无法跟踪其状态的外部作业。
  2. 您的Perl脚本可能会生成一个命令行SFTP实用程序(如PSFTP),该实用程序在传输完成之前不会返回。
  3. 或者将exec_SFTP.vbs脚本更改为在传输完成之前不返回。
  4. 如果您当前正在使用图形SFTP客户端且由于某种原因无法切换,我建议使用像AutoIt这样的脚本语言而不是Perl。 AutoIt具有等待窗口更改状态等功能,因此可以更轻松地监视活动的完成情况。
  5. 选项1或2将是最强大和可靠的。

答案 3 :(得分:3)

我能建议的最好的方法是修改exec_SFTP.vbs,只有在文件传输完成后退出。 system等待它调用的程序完成,以便解决您的问题:

       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.

答案 4 :(得分:2)

如果您无法修改vbs脚本以便在它终止之前保持活动状态,则可以跟踪子进程创建。如果你得到子进程ID,你可以监视它们,从而知道vbs的各种后代何时终止。

Win32::Process::Info允许您从正在运行的进程中获取子进程ID。

答案 5 :(得分:1)

也许这是一个愚蠢的问题,但为什么不使用Net::SFTPArchive::Extract Perl模块来下载和解压缩文件?

答案 6 :(得分:0)

查看IPC::Open3

  

IPC :: Open3 - 使用open3()

打开读取,写入和错误处理的过程

答案 7 :(得分:0)

system在它运行命令的shell返回之前不会返回;这对于启动图形程序和文件关联可能是错误的。

看看是否有以下任何帮助?

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);