通过perl的open2执行时,telnet命令输出未完全打印

Posted

技术标签:

【中文标题】通过perl的open2执行时,telnet命令输出未完全打印【英文标题】:telnet command output not completely printed when executing through open2 of perl 【发布时间】:2017-02-26 08:10:28 【问题描述】:

我是 perl 的新手。

我的目标:执行 telnet 命令并捕获完整输出

我的代码:

use IPC::Open2;

open2(\*RDR, \*WTR, "telnet host_name 8000 2>&1") or die ("could not contact host_name");

print WTR "$command\n";

print WTR "quit\n";
foreach my $line (<RDR>)
   
      print $line."\n";
   
close RDR;

问题:通过putty执行telnet命令时,打印输出超过12行。但是通过这个 perl 脚本只打印了 3 行

解决尝试: 我试过Expect、Net::Telnet、IO::Pty。但由于安全原因,这些模块没有安装在我的刀片服务器中。

问题:那么,在不使用任何这些有用的魔法模块的情况下,如何使用 perl 获得任何 telnet 命令的完整输出?输出缓冲区的字符数有限制吗?

【问题讨论】:

【参考方案1】:

你没有说你的$command,但这对我有用。

use warnings 'all';
use strict;

use IPC::Open2;

my $host = 'google.com';

my $pid = open2(\*RDR, \*WTR, "telnet $host 80 2>&1") 
    or die "Can't contact $host: $!";

print WTR "GET\n";    
print WTR "quit\n";

while (my $line = <RDR>)

    print $line if $. <= 10;      # print only first 10 lines
   
close RDR;

waitpid($pid, 0);
my $child_exit_status = $? >> 8;  # check how it went

这会打印整个页面(没有if ...)。为方便起见,打印限制为 10 行。

请仔细阅读文档IPC::Open2,因为涉及到所有这些。

open2() 返回子进程的进程ID。 [...]open2() 在退出后不会等待并获取子进程。 [...] 这整个事件是非常危险的,因为你可能会永远阻止。 [...]

另见IPC::Open3。一个备受推崇的模块是IPC::Run,如果可能已经安装。同样出色的是Tiny::Capture,在this recent post 中使用它时看到一个非常相似的问题。两者都很有名,所以也许您的管理员可以接受它们。


我建议切换到词法文件句柄

my $pid = open2 my $read_fh, my $write_fh, "telnet $host 80 2>&1" 
    or die "Can't contact $host: $!";

并在整个过程中更改 RDRWTR


我不知道 Windows 环境如何影响上述情况。这些模块会给人一些信心,但我不确定open2 的票价如何。另一个可能的罪魁祸首可能是缓冲,即使我看不到它在您的代码中的情况。以防万一,你可以试试

use IO::Handle;
STDERR->autoflush(1);
STDOUT->autoflush(1);

IO::Handle 默认从 v5.16 开始加载。

还有关于此in perlfaq5 的讨论,以及进一步阅读的链接。

但是,如果您确实有缓冲问题,则很可能是在另一端,如果没有模块,这可能不容易解决。引用骆驼的话

如前所述,IO::PtyExpect 模块提供了一个伪 tty 设备,为您提供行缓冲,而无需在管道末端修改程序。

【讨论】:

以上是关于通过perl的open2执行时,telnet命令输出未完全打印的主要内容,如果未能解决你的问题,请参考以下文章

为啥 IO::Pty 和 Expect 模块可以帮助解决 open2 的障碍?

如何将命令发送到在 perl 的非标准端口上运行的 telnet

为啥 IPC::Open2::open2 返回父进程 ID?

如何使用 IPC::Open2 过滤大量数据?

为 Telnet 会话创建脚本?

通过 Bash 脚本通过 Telnet 发送命令