2017-02-16 3 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 ++)); do echo \ $ i;完了};スカラー@ ar''は私のために10000000を正しく返します。 – choroba

+4

たぶん[Net :: SFTP :: Foreign](http://p3rl.org/Net::SFTP::Foreign)に切り替える時間はありますか? – choroba

+4

その番号は(この目的のために) "_huge_"ではありません。私はそれがsftp/shell/Perlの間のインターフェースだと思います。私はまた、システムを通過する代わりに、良いモジュールに切り替えることをお勧めします。 – zdim

答えて

2

これは、追加のパッケージモジュールを必要とすることなく達成できます。私はこれをCentOS 7 Server(Windows VM)でテストしました。

私のリモートホストの詳細:リモートホストディレクトリに〜2000個のファイルがあります。 CentOS 6.8サーバー。 LocalHostというの

%[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> 

スクリプトの出力:私はあなたのコマンドサンセリフo${transferAuthMode}=yes一部を実行していますのでご注意ください。以下に示すように、スクリプトはすべての結果を500個以上の結果として集めることができます。

私は結果を表示するために配列からいくつかの特定のインデックス番号をprntingしていますが、完全な結果を見るために非コメントダンパーラインで試してみてください。

%[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] 
" ; 

別の方法:一つは、シェルスクリプトを作成し、perlスクリプトからそれを呼び出すことによって、この問題を回避し、その出力を読むことができました。以下に示すように、私のシェルスクリプトはperlスクリプトと最終出力によって呼び出されます。 perlで直接コマンドを書いたり書いたりする時間があまりないときは、これは簡単なテクニックとして使うことができます。 以前のスクリプトでもqx形式(下に表示)を使用することができます。

シェルスクリプト "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

関連する問題