I am trying to set up arbitrary pipelines from Perl, in much the same way as a shell might.
This has the desired effect, it's like "echo foo | sed s/oo/ar/":
#!/usr/bin/perl
use strict;
use IO::Handle;
$| = 1;
my ($first_prog, $second_prog) = ([qw(echo foo)], [qw(sed s/oo/ar/)]);
#$second_prog = ["less"];
pipe(my $second_prog_input, my $first_prog_output)
or die "problem setting up pipe: $!\n";
if (fork) {
STDOUT->fdopen(fileno($first_prog_output), 'w') or die;
exec(@$first_prog) or die;
}
else {
STDIN->fdopen(fileno($second_prog_input), 'r') or die;
exec(@$second_prog) or
die "couldn't exec: $!: command was @$first_prog\n";
}
However, when I make the second argument "less", my terminal flashes, and I don't see the output in the pager. Other than the brief flash, there is no sign of less running at all.
Now something I don't get at all is that the following does behave like "echo foo | less":
pipe(my $first_prog_output, STDIN) or die "problem setting up pipe: $!\n";
my ($first_prog, $second_prog) = ([qw(echo foo)], ["less"]);
open($first_prog_output, "-|", @$first_prog) or
die "$!: command was @$first_prog\n";
exec(@$second_prog) or
die "couldn't exec: $!: command was @$first_prog\n";
But I don't understand at all what that call to pipe() is doing. The first argument is supposed to be a "reader", and the second one a "writer". How is STDIN a "writer"?
I'm very confused by all this, and think there may be something fundamental about the underlying Unix API that I'm missing or I've forgotten.
It's an interesting timing issue:
perl
.perl
forks and execs less
.perl
execs echo
.echo
exits, shell believes job is done and sets itself as the terminal foreground process group once again.less
tries to acquire terminal. It is not in the terminal foreground process group. less
fails.The simplest solution: change fork
to !fork
(or equivalently, swap your if
and else
blocks). That way, the final stage of the pipeline defines the lifetime of the job. (If you watch carefully, the shell forks and execs processes in this same order when it runs a pipeline, too.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With