简体   繁体   中英

To upload multiple files in one Net::SFTP::Foreign session in perl

I am trying to upload a set of files to a remote machine in perl using Net::SFTP::Foreign module. The file names are stored in a text file .But all the files are not getting uploaded . Only one file is getting uploaded.

#!/usr/local/roadm/bin/perl
# This is compiled with threading support

use strict;
use warnings;
use threads;
use threads::shared;
use Net::SFTP::Foreign;
my $count=0;
my %args = (
user     => 'root',
password => 'Ht5h10N2',
more     => '-v',
autodisconnect => 0
);           
print "Starting main program\n";
open(fa ,"<file_list.txt");
my @con =<fa>;
close fa;
my $sftp = Net::SFTP::Foreign->new('hadoop-dev2', %args); 
foreach  (@con)
{
chomp $_;
$sftp->put($_,"$_");

}

You never check the status of your various operations! Did your initial constructor creating $sftp work? Was that file you opened really opened? Does that file exist on the remote system?

You must always check the status of your commands in Perl!

use strict;
use warnings;
use feature qw(say);
use File::Basename;

use threads;
use threads::shared;
use Net::SFTP::Foreign;

my %args = (
    user     => 'root',
    password => 'Ht5h10N2',
    more     => '-v',
    autodisconnect => 0
);           

# Where is `%args` coming from?
my $sftp = Net::SFTP::Foreign->new('hadoop-dev2', %args);   # Check whether succeeded or failed!
if ( $sftp->error ) {
    die qq(Could not establish the SFTP connection);
}

say "Starting main program";

open my $fh, "<", "file_list.txt"   # Check whether succeeded or failed!
    or die qq(Could not open file "file_list.txt");
}

while ( my $file = <$fh> ) {
    chomp $file;
    $sftp->put( $file, $file ) );   # Check whether succeeded or failed!
    if ( $sftp->error ) {
        warn qq(Could not download file "$file");
        my $remote_files_ref = $sftp->ls();  # Check whether succeeded or failed!
        if ( $sftp->error ) {
            warn qq(Cannot get stat or remote directory.);
        }
        else {
            say qq(List of files in "$remote_dir":);
            for my $remote_file ( @{ $remote_files_ref } ) {
                say "    $remote_file";
            }
        }
    }
}

Note I check whether my open worked, whether the constructor for $sftp worked, and every time I use a method from Net::SFTP::Foreign . For example, I can't download a file that doesn't exist. Maybe it doesn't exist, thus I do a $sftp->ls to see when it doesn't work.

You can use autodie which is a pragma for various file commands in Perl, and is a setting you can use for Net::SFTP::Foreign . Autodie is nice because it kills your program automatically upon an error, thus turning perl into more of an exception based language. This way, if there's an error, and you don't catch it, your program dies.

If you don't want you program to outright fail, you can use eval to test whether something worked or not:

$sftp->Net::SFTP::Foreign( yadda, yadda, { autodie => 1} ); #Autodie is now turned on:

eval {   # Checks whether the file exists
   $sftp->get( $file, $file );
}
if ( $@ ) {
   warn qq(ERROR: File "$file" is not found!);
} else {
   say qq(Downloaded "$file".);
}

Reply

Theres no error i ran your code, but i still cant upload :( Any help would be appreciated

So, you're saying that $sftp->get doesn't download the file, but neither sets $sftp->error ?

There are a few places in the code where I see that an undef is returned, but sftp->_set_error isn't be called. Let's just see if $sftp->get returns a true or undef . According to the source code, that's what it should be doing. If it's undef, we'll assume it failed.

while ( my $file = <$fh> ) {
    chomp $file;
    if ( not $sftp->put( $file, $file ) ) {  # Check whether succeeded or failed!
        warn qq(Could not download file "$file");
        my $remote_files_ref;
        if ( $remote_files_ref = $sftp->ls() ) {  # Check whether succeeded or failed!
            warn qq(Cannot get stat or remote directory.);
        }
        else {
            say qq(List of files in "$remote_dir":);
            for my $remote_file ( @{ $remote_files_ref } ) {
                say "    $remote_file";
            }
        }
    }
}

I'll bet that the problem is that you have some full paths to files in your file_list.txt and that the paths to the files do not exist on the FTP server. Remember that FTP doesn't create directories for you, so if you have

/etc/passwd

in your file_list.txt , you better have a directory called

/etc

on your FTP server.

问题是,该代码正在cygwin上在Windows上运行,因此主要错误之一是与单个VTY资源的线程竞争以及用于获取TIMED OUT的线程,因此我使用Expect脚本解决了该问题。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM