如何在Perl中捕获rsync进度消息?

如何在Perl中捕获rsync进度消息?,perl,rsync,Perl,Rsync,我想从Perl脚本中捕获rsync进程发出的所有进度消息。在某些情况下,这是行不通的 下面是我使用的典型rsync命令行: rsync -aL --verbose --progress --bwlimit=100 \ --include-from=/tmp/78hJ2eDCs1 \ --include '*/' --exclude '*' \ /srcdir/* \ hostname:/target/ 2>&1 如果在bash shell中运行此命令,我将看到如下

我想从Perl脚本中捕获rsync进程发出的所有进度消息。在某些情况下,这是行不通的

下面是我使用的典型rsync命令行:

rsync -aL --verbose --progress --bwlimit=100 \
  --include-from=/tmp/78hJ2eDCs1 \
  --include '*/' --exclude '*' \
  /srcdir/* \
  hostname:/target/ 2>&1
如果在bash shell中运行此命令,我将看到如下内容:

Building file list ...
1600 files...
1700 files...
and so on
如果我在Perl中尝试相同的命令,我会得到“buildingfilelist”输出OK,但不会得到状态更新。下面是我如何测试捕获的

my $pid = open(OUTPUT, "$cmd |")  or die "Couldn't fork: $!\n";

my $ch;
while(read(OUTPUT, $ch, 1)==1)
{
    print $ch;
}
close(OUTPUT);
我的猜测是,要么rsync感觉到输出句柄不是一个典型的控制台,要么以某种不寻常的方式输出,而我没有捕捉到。然而,更奇怪的是,如果省略--include和--exclude过滤器,我就可以很好地捕获状态消息


有人知道发生了什么吗?

perl会缓冲管道的输出吗?如果是这样的话,如果在打开输出句柄之后,您使用OUTPUT->autoflush(1)关闭缓冲,那么您可能能够让它工作

您可以使用类似PTY的,可以为您提供所需的输出


如果做不到这一点,您可以尝试或选项。

结果表明,解决方案很简单-我只需使用
$\124;=1解除脚本中的IO缓冲


我仍然对我如何观察到一些rsync选项而不是其他选项的问题感到困惑。感谢Paul Tomblin和dsm给了我一些想法。

您可能还想使用IPC::Run及其对stdout/stderr上数据的回调。

是迄今为止我发现的关于缓冲效果的最好解释。值得花时间去阅读和理解


不要忘记缓冲是有原因的,所以不要盲目地针对每个可能出现的问题关闭它。

我尝试过,但没有效果-奇怪的是,如果我不使用--include/exclude选项,我可以捕获所有输出。我不确定我是否可以用Expect迭代地吃掉输出,但是模仿伪TTY的想法可能会很有成效……我们将对此进行探索。不,我尝试使用IO::Pty::Easy,我看到了完全相同的行为在已经提供了两个答案之后,我猜rsync正在做一些事情来缓冲输出。你在最后得到了所有的输出吗?有趣的是,我认为$|和->autoflush是等价的,这就是我建议它的原因。我猜autoflush作用于输出句柄,而$|作用于脚本STDOUT?i、 不知何故,我只是没有得到输出刷新?