我有很多TNS名称,我必须使用TNSPing实用程序从中获取主机名和端口号。
while (my $line = <$fh>) {
chomp $line;
print "TNS: $line\n";
my $output = `tnsping $line | grep -Eo "HOST=[A-Za-z0-9.\-]*com?|PORT=[0-9]+"`;
print "$output\n";
print "----------------\n\n";
}
tnsping
的输出看起来像这样
TNS Ping Utility for Linux: Version 11.1.0.0.2 on 15-FEB-2009 14:46:28 Copyright (c) 1997, 2009 Oracle Corporation. All rights reserved. Used parameter files: Used TNSNAMES adapter to resolve the alias Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = sampleserver.com)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = sales.us.example.com))) OK (10 msec)
该代码适用于大多数TNS条目,但对于某些条目,tnsping
命令未退出,因此受到攻击。我尝试手动运行其中一个条目,我发现它们正在打印到stdout但由于某种原因,tnsping实用程序没有退出。
现在我的问题是,无论tnsping
实用程序是否退出,我如何修改脚本以便在获取主机和端口数据后移动到下一个条目?
我目前的理解是,只有当tnsping
实用程序退出时,grep才会起作用(我,它不是连续的)。
我也对任何其他方法持开放态度。
答案 0 :(得分:4)
我建议使用IO::Select
和can_read
。我还建议 - 不要在perl中运行grep
。
这样的事情:
while ( my $line = <$fh> ) {
chomp $line;
print "TNS: $line\n";
my $pid = open( my $output, '-|', 'tnsping $line' );
my $select = IO::Select->new($output);
my $host;
my $port;
#check if the FH is readable, with a 5s timeout.
while ( $select->can_read(5) ) {
my $line = <$output>;
$line =~ m/HOST\s*=\s*([A-Za-z0-9.\-]*com?)/ and $host = $1;
$line =~ m/PORT\s*=\s*([0-9]+)/ and $port = $1;
}
close($output);
print $host, "\n";
print $port, "\n";
print "$output\n";
print "----------------\n\n";
}
我建议作为样式点 - $fh
不是一个很好的变量名。