[英]running “less” from perl pipeline
I am trying to set up arbitrary pipelines from Perl, in much the same way as a shell might. 我试图从Perl设置任意管道,就像shell一样。
This has the desired effect, it's like "echo foo | sed s/oo/ar/": 这有所期望的效果,就像“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. 但是,当我将第二个参数设置为“less”时,我的终端会闪烁,而我在寻呼机中看不到输出。 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": 现在我完全没有得到的是以下内容的行为类似于“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. 但我完全不了解对pipe()的调用。 The first argument is supposed to be a "reader", and the second one a "writer".
第一个论点应该是“读者”,第二个论点是“作家”。 How is STDIN a "writer"?
STDIN如何成为“作家”?
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. 我对这一切感到非常困惑,并认为可能存在一些基本的Unix API,我缺少或者我已经忘记了。
It's an interesting timing issue: 这是一个有趣的时间问题:
perl
. perl
。 perl
forks and execs less
. perl
forks和execs less
。 perl
execs echo
. perl
高管echo
。 echo
exits, shell believes job is done and sets itself as the terminal foreground process group once again. echo
退出,shell认为作业完成并再次将自己设置为终端前台进程组。 less
tries to acquire terminal. less
尝试获取终端。 It is not in the terminal foreground process group. less
fails. less
失败。 The simplest solution: change fork
to !fork
(or equivalently, swap your if
and else
blocks). 最简单的解决方案:将
fork
更改为!fork
(或等效地,交换if
和else
块)。 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.)
(如果仔细观察,shell在运行管道时也会以相同的顺序分叉和执行进程。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.