kurt2439 has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

I am trying to create a SFTP handle and then switch the working directory and put a file into that new directory. I am able to switch directories (at least it does not die) but the file does not get uploaded into that directory. When uploading to the root directory, it works as expected.

I am not very familiar with objects and references and am fairly new to perl. I did look through the example directory of the Net::SFTP module, but didn't find or understand my answer. Am I supposed to initiate a shell for this somehow? Here is the relevant code I am trying to get to work

sub connect_sftp { #Only takes 2 arguments, host scalar, and args my $host = shift @_; my %args; while (@_){ my $key = shift; my $value = shift; $args{$key}=$value; } print "Getting SFTP file handle for $host..." if ($debug); my $sftp_handle = Net::SFTP->new($host,%args); print "Success!\n" if ($debug); return $sftp_handle; } #LATER IN SCRIPT my $sftp_path = "incoming" if ("$sftp_path" ne "/"){ print "About to switch to $sftp_path d +irectory...\n" if ($debug); $sftp_handle->do_opendir("$sftp_path") + or die "Could not change cwd to $sftp_path\n"; } print "About to send $file_path$isbn.$type to +$distributor at $sftp_path$isbn.$type\n" if ($debug); $sftp_handle->put("$file_path$isbn.$type","$is +bn.$type") or die "SFTP Transfer Error: Tried to sen +d $file_path$isbn.$type to $distributor at $sftp_path$isbn.$type\n";

Replies are listed 'Best First'.
Re: question about objects / Net::SFTP
by zentara (Cardinal) on Jan 28, 2011 at 17:23 UTC
    Hi, with Sftp you have to be very careful about using full directory paths, or be very certain of your cwd on both ends of the connection. Try something like this. Notice the full file path in the put method.

    Finally, try connecting with the sftp program of your choice, like sftp, and watch what steps you must take, in changing directories and what your pwd is.

    #!/usr/bin/perl use warnings; use strict; use Net::SFTP; #Who am I and where am I going? my $user = 'z'; my $pass = 'zpass'; my $sftp; my $file = "test.txt"; my $put_to_dir = "/home/z/2"; my $put_from = $0; #upload this file my $host = '0.0.0.0'; my $result; #Where the real action takes place... $sftp = Net::SFTP->new($host, "user" => $user, "password" => $pass, ) or die "Can't login $!\n"; $sftp->put($put_from, "$put_to_dir/$file") || die "Can't open $!\n"; my @AOH = $sftp->ls($put_to_dir); foreach my $href(@AOH){ foreach my $key( %{$href} ){ if(defined ${$href}{$key}){ if( ${$href}{$key} =~ /-rwxr-xr-x(.*)$file$/ ){ $result = ${$href}{$key}; } } } } # Writting log files for transfers open LOGS, ">> $0.log" or die "Can't open file, $!\n"; # Get my dates my $date; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime) [0,1,2,3,4,5]; $year=$year+1900; $mon=$mon+1; $date = sprintf("%02d%02d%02d", $year,$mon,$mday); # # Write my logs so I can track myself print LOGS "Transfer date:$date, File transfered:$put_to_dir/$file\n$result\n"; close LOGS;
    Also, since you are new, why not try using Net::SSH2, as it has sftp built in. See A little demo for Net::SSH2

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: question about objects / Net::SFTP
by Khen1950fx (Canon) on Jan 28, 2011 at 19:35 UTC
    To follow zentara's advice, try this:
    #!/usr/bin/perl use strict; use warnings; use Net::SSH2; use Net::SFTP::Foreign; use Net::SFTP::Foreign::Backend::Net_SSH2; my $host = 'localhost'; my $user = 'user'; my $pass = 'pass'; my $ssh2 = Net::SSH2->new(); $ssh2->debug(1); $ssh2->connect($host) or die "Connect failed!\n"; $ssh2->auth_password($user, $pass) or die "password auth failed\n"; my $sftp = Net::SFTP::Foreign->new(ssh2 => $ssh2, backend => 'Net_SSH2'); $sftp->error and die "Unable to establish a SFTP connection: ", $sftp->error; $sftp->put('/null.txt', '/root/Desktop/null.txt');
      Using the Net::SSH2 backend for Net::SFTP::Foreign is very advisable on Windows systems, but under Linux/Unix, the default backend is usally a better option as it is more efficient and has been more extensively tested!
Re: question about objects / Net::SFTP
by salva (Canon) on Jan 28, 2011 at 20:49 UTC
    Net::SFTP does not support changing the working remote directory path so you have to handle the path resolution yourself locally (BTW, the do_opendir method is for reading directories).

    You can use Net::SFTP::Foreign instead that does support changing the default path.

      Thanks for the great responses guys. I read through Net::SFTP:Foreign and ended up using that one since it made sense to be able to implement the functionality and security of OpenSSH. the setcwd() command did what I needed it to and now my script works great! I thought I was using the correct full path for the Net::SFTP module but I guess I was doing something wrong...anways, now I don't have to deal with that.

      Thanks!