【问题标题】:Capturing command-line output on win32 that hasn't been flushed yet在 win32 上捕获尚未刷新的命令行输出
【发布时间】:2010-02-11 03:10:26
【问题描述】:

(上下文:我正在尝试从 Perl CGI 脚本监视一个长时间运行的进程。它备份一个 MSSQL 数据库,然后对其进行 7-zip 压缩。到目前为止,备份部分(使用WITH STATS=1)输出到一个文件,我可以让浏览器查看它,每隔几秒刷新一次,它可以工作。)

我正在尝试使用 7zip 的命令行实用程序,但将进度条捕获到文件中。不幸的是,与 SQL 备份不同的是,每次完成另一个百分比时,它都会输出另一行,7zip 在输出新的进度数据之前会回退其输出,因此如果您只是正常使用它,它看起来会更好命令行。这是不幸的原因是使用>1>2> 的正常重定向只会创建一个空白文件,并且其中不会出现任何输出,除了>,它在作业完成之前没有输出完成,这对于进度条不是很有用。

我怎样才能捕获这种输出,或者通过使用命令行技巧(没有 Perl)以某种方式将 % 中的每个更改附加到日志文件(这样我就可以使用我现有的日志文件监控方法),或者通过调用system()后使用一些Perl代码直接捕获?

【问题讨论】:

  • 我不太确定 7za.exe 使用哪种方法来执行此操作。

标签: perl command-line winapi capture


【解决方案1】:

如果您需要一次捕获所有输出,那么这就是您想要的代码:

$var=`echo cmd`;

如果你想逐行读取输出,那么你需要这段代码:

#! perl -slw
use strict;
use threads qw[ yield async ];
use threads::shared;

my( $cmd, $file ) = @ARGV;
my $done : shared = 0;
my @lines : shared;

async {
    my $pid = open my $CMD, "$cmd |" or die "$cmd : $!";
    open my $fh, '>', $file or die "$file : $!";
    while( <$CMD> ) {
        chomp;
        print $fh $_;         ## output to the file
        push @lines, $_;    ## and push it to a shared array
    }
    $done = 1;
}->detach;

my $n = 0;
while( !$done ) {
    if( @lines ) {            ## lines to be processed
        print pop @lines;   ## process them
    }
    else {
        ## Else nothing to do but wait.
        yield;
    }
}

另一个选项是使用 Windows 创建过程。我知道 Windows C/C++ 创建过程将允许您重定向所有标准输出。 Perl 可以访问相同的 API 调用:请参阅 Win32::Process

【讨论】:

  • 当我尝试运行这个脚本时,我得到了threads: Unknown import option: async
  • (第一个代码sn-p我实际上并没有尝试,因为我很确定这不是我想要的:我需要不断捕获输出以获得进度条,因为由于这种“倒带”的事情,它一直在变化。即使对于 Perl 来说,完成这件事的一次性声明似乎也是相当黑暗的魔法......)
  • 是的,我不确定以太。要运行第二个片段,您可能必须使用 CPAN 安装一个库。我只知道 CreateProcess 可以捕获输出,我知道如何用 perl 来做到这一点。对不起,我是 *nix 程序员。
  • 我将async 放到threads::shared 行,它停止抱怨,但结果与&gt; 相同,直到最后没有输出。好吧,无论如何感谢您的尝试,我很感激。
【解决方案2】:

您可以尝试打开pipe 来读取 7zip 的输出。

【讨论】:

  • 我试过了,不幸的是,它的行为与命令行上的&gt; 完全一样:在程序完成之前没有输出。
【解决方案3】:

这并没有回答如何捕获被倒带的输出,但它是我最终使用的一种有用的方法。

对于恢复:

  1. 使用7za l 列出压缩文件中的文件及其大小
  2. fork 7za e 使用 open my $command
  3. 跟踪每个带有-s $filename 的文件并与列表进行比较
  4. 当所有输出文件都是完整大小时,您就完成了

对于备份:

  1. 在某处创建一个唯一目录
  2. 分叉7za a -w
  3. 在目录中找到.tmp 文件
  4. 跟踪其大小
  5. .tmp 文件不再存在时,您就完成了

对于恢复,您可以获得足够的数据来显示完成的百分比,但对于备份,您只能显示到目前为止的总文件大小,但如果您使用类似的数据来估算,您可以与历史比率进行比较。尽管如此,它还是比以前更多的反馈(没有)。

【讨论】:

    猜你喜欢
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 2017-02-26
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多