CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Net::SSH2

 



ncalsmitty1369
Novice

Feb 11, 2008, 4:57 PM

Post #1 of 11 (756 views)
Net::SSH2 Can't Post

Hi,

I have been trying to find more information about the following error that I get when running some code to unlink a remote file using the Net::SSH2 module.

error message from die - "Usage: Net::SSH2::SFTP::unlink(sf, file) at get_bill_status.pl line 276." Line 276 is the the last line of the code below.

perldoc -m Net::SSH2 shows that the only parameter is "file". After looking at the libssh2 docs here - http://www.libssh2.org/wiki/index.php/Libssh2_sftp_unlink_ex

I am thinking that maybe there really is suppose to be another parameter. But what does "sf" reference?

Everything except for the unlink of the remote file is working.

Any help would be greatly appreciated!

Thanks.

some of the code -

my $ssh2 = Net::SSH2->new();
$ssh2->connect("$rem_host") or die "Could not connect to $rem_host: $!";
$ssh2->auth_password("$username","$password") or
die "Could not login to $rem_host: $!";

## uncomment line below to turn on debugging. ##

$ssh2->debug(1);

## open sftp object ##

my $get_xml = $ssh2->sftp();

## get list of files in the /Outbound dir ##

my $list = $get_xml->opendir($rem_dir) or die "Couldn't open
dir $rem_dir: $!";

while (my $ref = $list->read()) {
next if ( $ref->{name} =~ m/^\.\.?/ );
next if ( $ref->{size} =~ m/4096/ ); ## exclude dirs
v("name: $ref->{name}");
# v("size: $ref->{size}");
%xml_list->{$ref->{name}} = $ref->{size};
}

... some code ...

open WRITE_LOCAL_FILE,">$here" or
die "Couldn't open $here: $!";
sleep(1);

## read $rem_file and write locally ##

my $open_rem_file = $get_xml->open($there) or
die "Couldn't open $there: $!";
my $buff;
while ( $open_rem_file->read($buff,4096) ) {
print WRITE_LOCAL_FILE $buff;
}
close WRITE_LOCAL_FILE;

... some code ...

$get_xml->unlink("$rem_file") or die "Couldn't remove $rem_file: $!";

... some code ...


KevinR
Veteran


Feb 11, 2008, 10:08 PM

Post #2 of 11 (753 views)
Re: [ncalsmitty1369] Net::SSH2 [In reply to] Can't Post

what is $get_xml?

$get_xml->unlink

is it a Net::SSH2 object?
-------------------------------------------------


ncalsmitty1369
Novice

Feb 11, 2008, 10:44 PM

Post #3 of 11 (751 views)
Re: [KevinR] Net::SSH2 [In reply to] Can't Post

$get_xml is basically $ssh2->sftp

so I believe that the unlink line could be written as...

$ssh2->sftp->unlink("$rem_file") or die "Couldn't remove $rem_file: $!";

I guess that makes unlink a method of Net::SSH2::SFTP.

Please correct me if I am wrong.


KevinR
Veteran


Feb 11, 2008, 11:09 PM

Post #4 of 11 (750 views)
Re: [ncalsmitty1369] Net::SSH2 [In reply to] Can't Post

I'm not sure. Judging by that error message it must be an object of Net::SSH2::SFTP. Why is the error coming from Net::SSH2::SFTP when you don't appear to be using that module?
-------------------------------------------------


ncalsmitty1369
Novice

Feb 11, 2008, 11:16 PM

Post #5 of 11 (749 views)
Re: [KevinR] Net::SSH2 [In reply to] Can't Post

If I understood the module docs correctly the unlink functionality comes from Net::SSH2::SFTP.


KevinR
Veteran


Feb 11, 2008, 11:37 PM

Post #6 of 11 (748 views)
Re: [ncalsmitty1369] Net::SSH2 [In reply to] Can't Post

OK, it looks like Net::SSH2 does load Net::SSH2::SFTP.


Quote
sftp

Return SecureFTP interface object (see Net::SSH2::SFTP).


There is an example at the top of the script:


Code
  if ($ssh2->auth_keyboard('fizban')) { 
my $chan = $ssh2->channel();
$chan->exec('program');

my $sftp = $ssh2->sftp();
my $fh = $sftp->open('/etc/passwd') or die;
print $_ while <$fh>;
}


You have to make an sftp object as shown above. Your script does that:


Code
my $get_xml = $ssh2->sftp();


What is the value of $rem_file here:


Code
$get_xml->unlink("$rem_file") or die "Couldn't remove $rem_file: $!";


print it to the screen before that line is executed and make sure it is defined. You should not quote single-scalars like that, remove the double-quotes around $rem_file, maybe you did that to see if it would help, but that is a bad coding habit to get into with perl.
-------------------------------------------------


ncalsmitty1369
Novice

Feb 12, 2008, 11:37 AM

Post #7 of 11 (741 views)
Re: [KevinR] Net::SSH2 [In reply to] Can't Post

Hi Kevin,

Sorry that I didn't back to you sooner, went off line for a bit.

To answer your last question about whether or not $rem_file is defined correctly, yes it is. I use it further up in the script and it returns what it is suppose to, which is basically a file name found on the remote server. I have included more of the code below to clear things up a bit more for you. This code sits in a fork and works up until the point of the unlink. Meaning... it connects to a remote server, opens a particular remote dir and checks for files to download, found files are put into a hash with the file name as a key and the file size as the value to that key, the key value are then checked against a local archive and if the file is not found locally it is downloaded, the downloaded file is checked for correct file size, and if everything appears to have gone correctly then the remote file is unlinked.

You were correct in that the quotes I used on that particular line were there for testing. Although I am sure that I could use some attention on my quoting habits!

Something that may or may not be helpful is that if I run the code as listed below I get the following die error from the unlink line:

Couldn't remove /tmp/ssh2_test/testing/test.txt: Invalid argument at ssh2_testing.pl

** That is a valid file in the correct location and with the proper permissions to be removed by the authenticated user. It is the invalid argument part that doesn't quite make sense.

However, if I change the unlink line to include two arguments like ('sf',$rem_name) then I get the following error:

Usage: Net::SSH2::SFTP::unlink(sf, file) at ssh2_testing.pl

Which is why I was asking if anyone could tell me what the 'sf' means. I was thinking that maybe the docs were incorrect and I needed to have two arguments passed?

Here is the section of code dealing with this... Sorry about the readability of the code but my spacing and indentation was lost in the copy and paste.

unless ($kid_pid) {
alarm(60);
v("The get xml billing status child PID of loop $get_xml_cnt is $$ ...\n");
open STDERR,">&ERRORS" or die "Couldn't open ERRORS for writing!";
open TL,">&LOG" or die "Couldn't open $xml_log!";

## connect to remote server with perl and ssh2 module ##

my $ssh2 = Net::SSH2->new();
$ssh2->connect($rem_host) or die "Could not connect to $rem_host: $!";
$ssh2->auth_password($username,$password) or
die "Could not login to $rem_host: $!";
alarm(0);

## uncomment line below to turn on debugging. ##

$ssh2->debug(1);

## open sftp object ##

my $get_xml = $ssh2->sftp();

## get list of files in the /Outbound dir ##

system "touch $work_temp/getting_file_list.sem";
my $list = $get_xml->opendir($rem_dir) or die "Couldn't open dir $rem_dir: $!";
my ($ls_exit, $ls_out, $ls_err) = $ssh2->error;
v("ls stdout is... $ls_out");
v("ls stderr is... $ls_err");
v("ls exit code is... $ls_exit");
if (! $ls_exit) {
v("There was no return code sent back, which means the list cmd ran successfully!\n");
}
else {
v("There seems to be a problem with the list command! The exit status code is: ");
v("-> $ls_exit , reason -> $ls_err.n");
}

while (my $ref = $list->read()) {
next if ( $ref->{name} =~ m/^\.\.?/ );
next if ( $ref->{size} =~ m/4096/ ); ## exclude dirs
v("name: $ref->{name}");
# v("size: $ref->{size}");
# v("uid: $ref->{uid}");
# v("gid: $ref->{gid}\n");
# v("mode: $ref->{mode}");
# v("mtime: $ref->{mtime}");
# v("atime: $ref->{atime}");
%xml_list->{$ref->{name}} = $ref->{size};
}

v("");
print "hash xml_list used ", scalar keys %xml_list, " buckets.\n\n" if ($v);

while( ($rem_name, $rem_size) = each %xml_list ) {
v("key: $rem_name, value: $rem_size.");
if (!-f "$archive_bm/$rem_name" ) {
my $set_unlink=0;
system "touch $work_temp/getting_$rem_name.sem";
my $there = "$rem_dir/$rem_name";
my $here = "$archive_bm/$rem_name";

open WRITE_LOCAL_FILE,">$here" or
die "Couldn't open $here: $!";
sleep(1);

## read $rem_file and write locally ##

my $open_rem_file = $get_xml->open($there) or
die "Couldn't open $there: $!";
my $buff;
while ( $open_rem_file->read($buff,4096) ) {
print WRITE_LOCAL_FILE $buff;
}
close WRITE_LOCAL_FILE;

stat("$archive_bm/$rem_name") or die "Couldn't stat $archive_bm/$rem_name: $!";
v("$archive_bm/$rem_name is $st_size bytes.");
$der_stat=$st_size;
if ( "$der_stat" == "$rem_size") {
v("$rem_name seems to have been copied intact to $archive_bm.\n");
print TL "$rem_name of $rem_size was downloaded at $time on $date.\n";
print STDERR "$rem_name of $rem_size was downloaded at $time on $date.\n";
unlink "$work_temp/getting_$rem_name.sem" or
die "Couldn't remove $work_temp/getting_$rem_name.sem: $!";
$set_unlink=1;
}
else {
v("There seems to have been a problem copying $rem_name to $archive_bm!");
print STDERR "There seems to have been a problem copying $rem_name to " .
"$archive_bm!\n";
}

## code to remove the downloaded file ##

if ( "$set_unlink" == 1 ) {
v("Removing $there after successful download.");
print STDERR "Removing $there after successful download.\n";
$get_xml->unlink($rem_name) or die "Couldn't remove $there: $!";
v("");
}
else {
v("Not removing $there after unsuccessful download attempt!");
print STDERR "Not removing $there after unsuccessful download attempt!\n";
}
sleep(1);
}
else {
v("It appears that this file has already been downloaded.\n");
}
}
v("");

## clean sem files ##

unlink "$work_temp/getting_file_list.sem" or
die "Couldn't remove $work_temp/getting_file_list.sem: $!";
unlink "$work_temp/xml_conn_to_srvr.sem" or
die "Couldn't remove $work_temp/xml_conn_to_srvr.sem: $!";

## exit to parent ##

v("Leaving child now...\n");
close STDERR;
$get_xml->disconnect() or die "Couldn't do disconnect on get_xml: $!";
exit;
}
waitpid($kid_pid,0);
v("The child PID was $kid_pid, back in the parent now...\n");
}


KevinR
Veteran


Feb 12, 2008, 1:12 PM

Post #8 of 11 (737 views)
Re: [ncalsmitty1369] Net::SSH2 [In reply to] Can't Post

I'm not trying to duck out on your question(s), but I simply do not know at this point what the problem is. To me your code looks like it should work, my only suggestion now is you ask on another forum where there are more active members, such as www.perlmonks.com
-------------------------------------------------


ncalsmitty1369
Novice

Feb 12, 2008, 1:41 PM

Post #9 of 11 (736 views)
Re: [KevinR] Net::SSH2 [In reply to] Can't Post

Thanks for you help Kevin! I am glad that at least one other person has come to see this as I have. haha... I too think that it should work. I was waiting to see what came of our conversation before heading to perlmonks.

Once again, thanks for your help and time.

-M


KevinR
Veteran


Feb 12, 2008, 3:52 PM

Post #10 of 11 (734 views)
Re: [ncalsmitty1369] Net::SSH2 [In reply to] Can't Post

If someone is able to determine the problem please post back with the explanation.

Thanks
-------------------------------------------------


ncalsmitty1369
Novice

Feb 13, 2008, 2:05 PM

Post #11 of 11 (726 views)
Re: [KevinR] Net::SSH2 [In reply to] Can't Post

Hi Kevin,

I figured out a few things that will at least let the script work as-is. However it didn't solve the problem enough to let it serve the purpose that I had intended it to. Will have to look at a shell script I guess.

Anyway, if I switch the target dir on the remote server to some other directory than /tmp the unlink works. That is using only one argument, the file name. The unlink also doesn't seem to work if you are dropped into a chrooted environment upon authentication to the remote server, even if you have the proper permissions to remove the files. At least that is what I have seen in my testing.

If someone finds something different please let me know!

-M

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives