1

I have a Perl script

for my $i (1..10) {
    print "How $i\n";
    sleep(1);
}

I want to run it from another perl script and capture its output. I know that I can use qx() or backticks, but they will return all the output simultaneously when the program exits.

But, what I instead want is to print the output of the first script from the second script as soon as they are available ie. for the example code the output of the first script is printed in ten steps from the second script and not in one go.

I looked at this question and wrote my second script as

my $cmd = "perl a.pl";
open my $cmd_fh, "$cmd |";

while(<$cmd_fh>) {
    print "Received: $_\n";
    STDOUT->flush();
}

close $cmd_fh;

However, the output is still being printed simultaneously. I wanted to know a way to get this done ?

him
  • 487
  • 3
  • 12
  • 2
    A simple and specific example of a pseudo-terminal with `IPC::Run` in [this post](https://stackoverflow.com/a/54547957/4653379). There's also an option to use the program `unbuffer`, if available; see the other answer at the linked page. – zdim Jun 13 '19 at 05:33

1 Answers1

3

The child sends output in chunks of 4 or KiB or 8 KiB rather than a line at a time. Perl programs, like most programs, flush STDOUT on linefeed, but only when connected to a terminal; they fully buffer the output otherwise. You can add $| = 1; to the child to disable buffering of STDOUT.

If you can't modify the child, such programs can be fooled by using pseudo-ttys instead of pipes. See IPC::Run. (Search its documentation for "pty".)

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Using `run \@cmdArr, '>pty>', sub { print "@_" }` solved the problem. But, suppose I also want to pass a string to the program I am running as input (the program prompts the user for an input), then how should I modify this statement ? – him Jun 19 '19 at 06:55
  • The command I'm trying to actually run is a `ssh` command. And the input I am trying to pass is the user password for remote login. I tried this - `run \@cmdArr, \$sshpwd, '>pty>', sub { print "@_" }` - but this doesn't seem to work, it still asks for the password. – him Jun 19 '19 at 07:47
  • I found my answer here - https://stackoverflow.com/questions/24454037/pass-a-password-to-ssh-in-pure-bash. Instead of using `ssh` to login into remote system use `sshpass`. – him Jun 20 '19 at 06:14