【问题标题】:How can Perl execute a shell script with no buffering?Perl 如何在没有缓冲的情况下执行 shell 脚本?
【发布时间】:2017-04-03 15:38:38
【问题描述】:

我有一个 shell 脚本 (testScript.sh),它打印到 stdout,稍等片刻,然后再次打印:

#!/bin/sh
echo "before"
sleep 2
echo "after"

我正在尝试从这样的 perl 脚本执行这个 sh 脚本:

#!/usr/bin/perl -w
use strict;

$| = 1; # do I need this?

sub runCommand($) {
    my ($command) = @_;
    open CMD, "$command |" || die "Unable to run $command: $!";
    my @output = <CMD>;
    close CMD;
    print join('',@output);
}

runCommand("./testScript.sh");

如果我直接运行 shell 脚本,我会立即看到“之前”,然后是延迟,然后是“之后”。

但是,当我通过 perl 运行脚本时,我首先得到延迟,然后打印“之前”和“之后”。

我以为这是因为Perl's I/O buffering,但$| = 1 似乎没有任何效果。

我在这里缺少什么?如何通过 perl 执行脚本并仍然让它立即写入stdout

【问题讨论】:

  • $| = 1; 仅在 Perl 脚本 的输出被重定向时才会有所不同,但没有提及这一点。 $| = 1; 因此无效。
  • @ikegami 正确,是的,在这个用例中 $| = 1; 是不必要的
  • 如果子程序确实在缓冲,可以使用伪 tty 试图欺骗它不缓冲。 IPC::Run 可以让这一切变得简单,expect 发行版中的unbuffer 实用程序也可以。

标签: perl shell sh stdout output-buffering


【解决方案1】:

您编写的代码等待从命令中读取所有输入,然后将其连接并打印出来。你不可能得到这样的增量输出

您必须在检索到的每一行时打印它,像这样

open CMD, "$command |" || die "Unable to run $command: $!";
print while <CMD>;
close CMD;

是的,您确实需要$| = 1,否则print 调用的输出将被缓冲

【讨论】:

  • 谢谢,现在明白了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多