2017-02-16 34 views
2

我想获取远程位置中存在的文件名列表。如何在执行外部命令时在Perl中捕获较大的STDOUT输出

我在我的Perl脚本中使用了下面的代码片段。

my $command = "sftp -q -o${transferAuthMode}=yes -oPort=$sftpPort ${remoteUsername}\@${remoteHost} 2>\&1 <<EOF\n" . 
     "cd \"${remotePath}\"\n" . 
     "ls -l \n" . 
     "quit\n" . 
     "EOF\n"; 

my @files = `$command`; 

当文件在所述远程位置的数量大(> 500),则不是所有的文件名称以@files捕获。

当我手动执行SFTP并列出文件时,所有文件都列出来了,但我没有通过脚本得到相同的结果。每次获得@files大小不同。只有在存在大量文件时才会发生。

我无法找到背后的原因。能否请你帮忙?

+0

有多少个文件? 'perl -wE'@ar = qx {for((i = 1; i <= 10000000; i ++));做echo \ $ i;做};说scalar @ ar''对我来说正确返回10000000。 – choroba

+4

也许时间切换到[Net :: SFTP :: Foreign](http://p3rl.org/Net::SFTP::Foreign)? – choroba

+4

该号码不是“_huge_”(为此目的)。我想这是关于sftp/shell/Perl之间的接口。我也建议切换到一个好的模块,而不是通过系统。 – zdim

回答

2

这可以在不需要任何额外的封装模块的情况下实现。我在CentOS 7服务器(Windows VM)上测试了这一点。

我的远程主机详细信息:我在远程主机目录中得到了〜2000个文件。一个CentOS 6.8服务器。从本地主机

%[email protected][remotehost]:/home/gaurav/files/test> ls -lrth|head -3;echo;ls -lrth|tail -2 
total 7.9M 
-rw-rw-r--. 1 gaurav gaurav 35 Feb 16 23:51 File-0.txt 
-rw-rw-r--. 1 gaurav gaurav 35 Feb 16 23:51 File-1.txt 

-rw-rw-r--. 1 gaurav gaurav 38 Feb 16 23:51 File-1998.txt 
-rw-rw-r--. 1 gaurav gaurav 38 Feb 16 23:51 File-1999.txt 
%[email protected][remotehost]: /home/gaurav/files/test> 

脚本输出:请注意,我正在运行的命令SAN的o${transferAuthMode}=yes部分。如下所示,脚本能够收集数组中的所有结果,超过500个结果。

我正在推荐总条目,数组中的一些特定索引编号以显示结果,但试着用未注释的Dumper行来查看完整结果。

%[email protected] * /root/ga/study/pl> ./scp.pl 
Read 2003 lines from SCP command. 

ArrayIndex: 2,3,1999,2000 contain: 

[-rw-rw-r-- 0 501  501   36B Feb 16 23:51 File-58.txt] 
[-rw-rw-r-- 0 501  501   37B Feb 16 23:51 File-129.txt] 
[-rw-rw-r-- 0 501  501   38B Feb 16 23:51 File-1759.txt] 
[-rw-rw-r-- 0 501  501   38B Feb 16 23:51 File-1810.txt] 
%[email protected] * /root/ga/study/pl> 

脚本及其工作:

#!/usr/bin/perl 

use strict ; 
use warnings ; 
use Data::Dumper ; 

my $sftp_port=22 ; 
my ($user, $host) = ("gaurav","192.168.246.137") ; 
my $remote_path = '/home/gaurav/files/test' ; 

my @result ; # To store result 

my $command = "sftp -q -oPort=$sftp_port ${user}\@${host} 2>\&1 <<EOF\n"."cd $remote_path\nls -lrth\nquit\nEOF" ; 

# open the command as a file handle, read output and store it. 
open FH, "$command |" or die "Something went wrong!!\n" ; 
while (<FH>) { 
    tr/(?\r|\f|\n)//d ; # Removing any new line, carriage return or form feed. 
    push(@result,"\[$_\]") ; 
} 
close FH ; 

#print Dumper @result ; 

# Just for printing a little bit of results from 
# the array. Following lines can be deleted. 
my $total = scalar @result ; 
print "Read $total lines from SCP command.\n" ; 
print "\nArrayIndex: 2,3,1999,2000 contain:\n 
$result[2] 
$result[3] 
$result[1999] 
$result[2000] 
" ; 

另一种方式:人们还可以解决这个问题,通过使一个shell脚本和Perl脚本调用它,阅读它的输出。如下所示,我的shell脚本被perl脚本和最终输出调用。当没有足够的时间直接在perl中编写/制定命令时,这可以用作快速技术。 您可以在前面的脚本中使用qx样式(如下所示)以及

shell脚本 “scp.sh”

%[email protected] * /root/ga/study/pl> cat scp.sh 
#!/bin/bash 

sftp -oPort=${1} ${2}@${3} 2>&1 <<EOF 
cd ${4} 
ls -l 
quit 
EOF 

的Perl脚本 “2scp.pl”

%[email protected] * /root/ga/study/pl> cat 2scp.pl 
#!/usr/bin/perl 

use strict ; 
use warnings ; 
use Data::Dumper ; 

my $sftp_port=22 ; 
my ($user, $host) = ("gaurav","192.168.246.137") ; 
my $remote_path = '/home/gaurav/files/test' ; 

# Passing arguements to shell script using concatination. 
my $command = './scp.sh '." $sftp_port $user $host $remote_path" ; 

my @result = qx{$command} ;  # Runs the command and stores the result. 
my $total = scalar @result ; 
print "Read $total lines from SCP command.\n" ; 
# End. 

输出:

%[email protected] * /root/ga/study/pl> ./2scp.pl 
Read 2004 lines from SCP command. 
%[email protected] * /root/ga/study/pl> 

试试吧,让我们知道。 谢谢。

+1

感谢您的答案,尝试了第一种方法(使用文件处理程序),其工作正常,并列出所有文件。但与使用Net :: SFTP :: Foreign PERL模块的实现相比稍微慢一些。 – user1919581

+1

是的,它在制作系统调用时会比较慢,而且速度较慢。但请记住,这没有perl模块和系统命令 - 这可能是某人的要求或他们无法安装额外模块的情况。 – User9102d82

相关问题