在外部进程执行时回显进度条并在完成时获取 STDOUT

Echo progress bar for while external process executing and take STDOUT when it done

如何仅使用标准模块在外部进程执行时回显进度条并在完成时捕获其 STDOUT。不使用叉子?

  1. 运行 外部进程,类似于:@array = `ls -l`;

  2. 执行的时候打印进度条,如:print '.';

  3. 完成后将进程的 STDOUT 捕获到数组中

  4. 继续工作主脚本

我正在阅读有关 IPC::Open2IPC::Open3 的内容,但我不明白如何将它们用于此任务。也许方向不对?

到目前为止你有什么?如果您在进程间通信方面遇到问题,请暂时忘记进度条并询问它。

你真的不能为有不确定结局的事情设置进度条。如果你不知道你将阅读多少输入,你就不知道你已经阅读了其中的多少部分。人们倾向于将进度条视为已完成工作的一部分,而不是 activity。也就是说,除非您使用 macOS 并了解“不到一分钟”意味着“超过三个小时”。 ;)

我倾向于做一些简单的事情,我经常输出一个点。我不知道我会看到多少点,但我知道我会看到新的点。

$|++; # unbuffer stdout to see dots as they are output

while( <$fh> ) {
    print '.' if $. % $chunk_size;  # $. is the line number
    print "\n[$.] " if $. % $chunk_size * $row_length;
    ...
    }

$fh 可以是您想要读取的任何内容,包括管道。 perlopentut 有从外部进程读取的示例。不过,那些正在做叉子。并且,其他模块也会分叉。是什么限制让您认为自己不能使用 fork?

你可以通过使用 curses 和其他东西来让你的显示更漂亮(马车 return 很方便:),但我不想把它们打出来。

也许 OP 正在寻找下一种只是为了表明外部进程正在 运行ning。

$SIG{ALRM} 定义一个处理程序,并每秒将 alarm 1 设置为 运行 处理程序。一旦过程完成重置 alarm 0 以关闭警报处理程序。

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $ls_l;      # variable to store output of external command
$| = 1;        # unbuffered output

$SIG{ALRM} = \&handler;
alarm 1;       # run handler every second

say 'Running sig_alarm_sleep';
$ls_l=`./sig_alarm_sleep`;
say ' done';

alarm 0;

my @fields = qw(rwx count user group size month day time name);
my @lines = split("\n",$ls_l);
my(@array);

for( @lines ) {
    my $x->@{@fields} = split(' ',$_);
    push @array, $x;
}

say Dumper(\@array);

exit 0;

sub handler {
    print '.';
    $SIG{ALRM} = \&handler;
    alarm 1;
}

Bash 脚本 sig_alarm_sleep 示例

#!/usr/bin/bash

sleep 20
ls -al