Perl双向管道IPC,如何避免输出缓冲
我试图通过一个互动的过程进行沟通。我希望我的perl脚本成为用户和进程之间的“模仿者”。该过程将文本放入标准输出,提示用户输入命令,将更多文本放入标准输出,提示用户输入命令。。。。。。。提供了基本图形:Perl双向管道IPC,如何避免输出缓冲,perl,ipc,pipe,output-buffering,tty,Perl,Ipc,Pipe,Output Buffering,Tty,我试图通过一个互动的过程进行沟通。我希望我的perl脚本成为用户和进程之间的“模仿者”。该过程将文本放入标准输出,提示用户输入命令,将更多文本放入标准输出,提示用户输入命令。。。。。。。提供了基本图形: User <----STDOUT---- interface.pl <-----STDOUT--- Process User -----STDIN----> interface.pl ------STDIN---> Process User <----STDO
User <----STDOUT---- interface.pl <-----STDOUT--- Process
User -----STDIN----> interface.pl ------STDIN---> Process
User <----STDOUT---- interface.pl <-----STDOUT--- Process
User -----STDIN----> interface.pl ------STDIN---> Process
User <----STDOUT---- interface.pl <-----STDOUT--- Process
User -----STDIN----> interface.pl ------STDIN---> Process
注意“cat-un”而不仅仅是“cat-n”-u关闭cat上的输出缓冲。当输出缓冲被关闭时,此功能将正常工作。我尝试与最有可能的缓冲区输出交互的过程,因为我面临与“cat-n”相同的问题。不幸的是,我无法在与之通信的进程上关闭输出缓冲,因此如何处理此问题
更新1(使用ptty):
#/usr/bin/perl
严格使用;
使用警告;
使用IO::Pty;
使用IPC::Open2;
my$reader=新IO::Pty;
my$writer=新IO::Pty;
my$pid=open2($reader,$writer,“cat-n”);
我的$got=“”;
我的$input=“”;
$writer->autoflush(1);
而($input ne“”){
chomp($input=);
$writer->print($input\n”);
$got=$reader->getline;
打印$got;
}
~有三种缓冲:
- 默认情况下,文件句柄是缓冲的。一个例外:默认情况下,STDERR没有缓冲
- 使用块缓冲。一个例外:STDOUT是行缓冲的,当且仅当它连接到终端时
- 从STDIN读取将刷新STDOUT的缓冲区
- 直到最近,Perl还使用4KB缓冲区。现在,默认值是8KB,但在构建Perl时可以更改
用户是一个人。他不缓冲每说,虽然这是一个非常缓慢的数据源正常User------>interface.pl
interface.pl-->Process
的输出是块缓冲的坏 通过将以下内容添加到interface.pl
中修复:interface.pl
use IO::Handle qw( ); WRITER->autoflush(1);
进程的输出是块缓冲的坏 通过将以下内容添加到Process-->interface.pl
过程中来修复:
现在,你们可能会告诉我你们不能改变这个过程。如果是这样的话,您将有三个选择:use IO::Handle qw( ); STDOUT->autoflush(1);
- 使用工具提供的命令行或配置选项更改其缓冲行为。我不知道有什么工具能提供这样的选择
- 通过使用替代管道,愚弄孩子使用行缓冲而不是块缓冲李>
- 退出
interface.pl------>用户
的输出是行缓冲的正常(对吗?)interface.pl
df
不会挂起等待输入,因为df
不接受任何输入。与您所说的相反,grep
确实挂起等待输入(因为df
的输出肯定是块缓冲的,但是df
完成得非常快,所以grep
只挂起一眨眼。那么为什么原始程序不工作呢?如果进程坐在那里等待输入和interface.pl通过stdout发送,那么进程不应该把它当作STDIN,做它的事情,然后输出吗(作为块、线或其他)退出STDOUT,让interface.pl在其stdin上接收数据?进程坐在那里等待输入,因为interface.pl目前没有发送任何数据。从stdin中没有任何数据可获取。如果有,它就会接收。interface.pl最终将4K或8K放入管道中,进程将在发生时立即开始读取数据。 open2总是打开它自己的管道,你不能给它Pty。有关使用IO::Pty::Easy
的简单示例,请参阅。
#!/usr/bin/perl
use strict;
use warnings;
use IO::Pty;
use IPC::Open2;
my $reader = new IO::Pty;
my $writer = new IO::Pty;
my $pid = open2( $reader, $writer, "cat -n" );
my $got = "";
my $input = " ";
$writer->autoflush(1);
while ($input ne "") {
chomp($input = <STDIN>);
$writer->print("$input \n");
$got = $reader->getline;
print $got;
}
use IO::Handle qw( );
WRITER->autoflush(1);
use IO::Handle qw( );
STDOUT->autoflush(1);