我有一个包含此代码段的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。
答案 0 :(得分:12)
检查* .vbs文件中的代码。 system
函数在执行继续之前等待子进程完成。您的* .vbs文件似乎正在分配后台任务来执行FTP并立即返回。
答案 1 :(得分:6)
在完美的世界中,您的脚本会被重写以使用Net::SFTP::Foreign和Archive::Extract ..
一种丑陋的快速hackish方式可能是在你第一次系统调用之前创建一个触摸文件,改变你的sftp-fetching脚本,一旦完成就删除文件并且有一段时间这样
while(-e 'touch.file') {
sleep 5;
}
# foreach [...]
当然,如果你的.vbs失败并且没有删除触摸文件和许多其他不良副作用,你需要注意。这将是一个快速的解决方案(如果没有其他建议工作),直到你没有系统()调用重写时间。
答案 2 :(得分:4)
你需要一种方法让Perl等到SFTP传输完成,但是当你的脚本当前被写入时,Perl无法知道这一点。 (看起来你正在组合至少两种脚本语言和一个(GUI?)SFTP客户端;这可以工作,但它不完全可靠或健壮。为什么使用VBscript启动SFTP传输?)
我可以想到四个选项:
答案 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::SFTP和Archive::Extract Perl模块来下载和解压缩文件?
答案 6 :(得分:0)
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);