Jonathan.Brink
Jonathan.Brink

Reputation: 25373

How can Perl execute a shell script with no buffering?

I have a shell script (testScript.sh) that prints to stdout, waits a little bit, and then prints again:

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

I am trying to execute this sh script from a perl script like this:

#!/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");

If I run the shell script directly I immediately see "before", then a delay, and then "after".

But, when I run the script via perl I first get the delay and then "before" and "after" are printed.

I was thinking that this was because of Perl's I/O buffering, but the $| = 1 doesn't seem to be having any effect.

What am I missing here? How can execute the script via perl and still have it immediately write to stdout?

Upvotes: 1

Views: 433

Answers (1)

Borodin
Borodin

Reputation: 126722

The code you have written waits for all the input to be read from the command, then joins it and prints it. There is no way that you could get incremental output like that

You must print each line as it is retrieved, like this

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

And yes, you do need $| = 1, otherwise the output from the print calls will be buffered

Upvotes: 4

Related Questions