Jonathan.Brink Jonathan.Brink - 13 days ago 6
Perl Question

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
?

Answer

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

Comments