FTP in perl error? - perl

Is there anything wrong the script bewlow, because I just can't login.....
And I'm sure I'm using the right username and password.
(Cannot login Login incorrect.)
sub UploadToFTPServer()
{
my $filename = shift;
$ftp = Net::FTP->new($FTPSERVER, Debug => 0) ;
if ($ftp) {
eval {
$ftp->login($USERNAME,$PASSWORD) or warn "Cannot login ", $ftp->message;
$ftp->binary();
$ftp->putfile($filename) or warn "Cannot upload ($filename)", $ftp->message;
$ftp->quit();
};
}
else {
warn "Cannot connect to $FTPSERVER: $#";
}
}

Start your script off with this:
use strict;
use warnings;
Then make sure that perl doesn't try to interpolate anything in your un/pw.
my $USERNAME = 'myname#gmail.com'; ## notice the single quotes
my $PASSWORD = 'mypass';
Given your error, it should work with those changes. It would have been easier to catch if the strict and warnings pragmas were used from the start.

Are you sure your testing from the same IP?
Also, try printing the username & password with quotes around them, as gpojd suggested.

Use the module "Net::FTP::Simple"
#send = Net::FTP::Simple->send_files({
username => $user,
password => $pass,
server => $host,
remote_dir => $path,
debug_ftp => 0,
files => [
$file,
],
});
print "The following files were retrieved successfully:\n\t",
join("\n\t", #send), "\n"
if #send;

Try $ftp->put instead of $ftp->putfile. I don't see putfile in the documentation.

Related

How to die Correctly on Soap::Lite in perl

I have written a perl script that connects using Soap::Lite and collect data from a web-service and update a database. This works well, until the password gets locked out and I get a server 500 error which is where my question comes in. How do I let the Soap::Lite query die when it does not make a successful connection, so it does not continue with the rest of the script?
.....
my $host = "hostname";
my $user = "user";
my $pass = "pass";
$soap_proxy = "https://" . $user . ":" . $pass . "#" . $host . ":8090/services/ApiService";
$uri = "http://api.config.common.com";
$client = new SOAP::Lite
uri => $uri,
proxy => $soap_proxy,
autotype => 0;
my $soap_respons = $client->getSomething();
....
I have tried the usual or die $! but that does not die like other queries do and still continues with the remaining script.
according to the SOAP::Lite examples on CPAN, you could use:
if ($#) {
die $#;
}
But I do not know where to put this. I tried directly under my $soap_respons but still it does not die.
SOAP::Lite queries will give a fault with a faultstring result if errors occur, something like this should work.
die $soap_respons->faultstring if ($soap_respons->fault);
print $soap_respons->result, "\n";
You could set the on_fault callback. This way you wouldn't have to check every response.
$client->on_fault(sub { die($_[1]) });

Displaying a portion of the configuration (--More)

I have got this error when i try to connect to my switch !
use Net::OpenSSH;
use warnings;
use Expect;
my $password = 'admin';
my $enable = '';
my $ip = '192.16.25.39';
my $username='user';
my $ssh = Net::OpenSSH->new("$username:$password\#$ip", timeout => 200) ;
$ssh->error and die "unable to connect to remote host: ". $ssh->error;
my $output = $ssh->capture({stdin_data => "enable\n"."admin%\n"."show vlan"."\n"});
if ($output) {print $output . ' ';}
my $line;
print "\n";
# closes the ssh connection
$ssh->close();
I have tried this with the Expect module:
use Net::OpenSSH;
if ($output) {
print $output . ' ';
my $expect = Expect->init($output);
$expect->raw_pty(1);
#$expect->debug(2);
my $debug and $expect->log_stdout(1);
while(<$pty>) {
print "$. $_ "
}
}
which produces this error:
Can't bless non-reference value at /usr/local/share/perl5/Expect.pm line 202 (#1) (F) Only hard references may be blessed. This is how Perl "enforces" encapsulation of objects. See perlobj. Uncaught exception from user code: Can't bless non-reference value at /usr/local/share/perl5/Expect.pm line 202. at /usr/local/share/perl5/Expect.pm line 202. Expect::exp_init("Expect", "\x{d}\x{a}witch>enable\x{d}\x{a}password:\x{d}\x{a}switch#show vlan\x{d}\x{a}\x{d}\x{a}VLA"...) called at b.pl line 19 "
This might be a better approach to your problem. There is a Net::Telnet::Cisco module that simplifies a lot of the interaction with the remote router. Apparently you can first set up an encrypted SSH connection with Net::OpenSSH and then use the filehandle from that connection to start a Net::Telnet::Cisco session.
So I think something like this would be more promising than trying to use Net::OpenSSH directly:
use Net::OpenSSH;
use Net::Telnet::Cisco;
my $password = 'admin';
my $enable = '';
my $ip = '192.16.25.39';
my $username='user';
my $ssh = Net::OpenSSH->new("$username:$password\#$ip", timeout => 200) ;
my ($pty, $pid) = $ssh->open2pty({stderr_to_stdout => 1})
or die "unable to start remote shell: " . $ssh->error;
my $cisco = Net::Telnet::Cisco->new(
-fhopen => $pty,
-telnetmode => 0,
-cmd_remove_mode => 1,
-output_record_separator => "\r");
my #vlan = $cisco->cmd("show vlan");
I am not familiar with the ins and outs of configuring Cisco routers, so you'll have to take it up from here, but this looks to me like a much easier route to get what you need.

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.
The problem was ,the code was being run on windows with cygwin so one of the major errors were there was thread competition to the single VTY resource and the threads used to get TIMED OUT, So i resolved it using an expect script

Perl Net::SSH::Expect not printing out all expected output

I am using expect in perl to get interface information from my router. When I run the command on the remote router its missing about 10-15 lines that should be there. Not sure why its stopping, any ideas?
#!/usr/bin/perl -w
#use strict;
use warnings;
use Net::SSH::Expect;
my $ssh = Net::SSH::Expect->new (
host => "10.10.10.10",
user => 'user',
password => 'pass'
);
my $login_output = $ssh->login();
if ($login_output !~ /router#/) {
die "Login has failed. Login output was $login_output";
}
#$ssh->run_ssh() or die "SSH process couldn't start: $!";
$ssh->send("show int g2/1");
my $line;
while (defined ($line = $ssh->read_line()) ) {
print $line."\n";
}
Net::SSH::Expect is not reliable. Use other module as Net::OpenSSH, Net::SSH2, Net::SSH::Any or just Expect
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new("10.10.10.10",
user => 'user',
password => 'pass',
timeout => 60 );
my $output = $ssh->capture('show int g2/1');
# or for some non-conforming SSH server implementations rather
# common in network equipment you will have to do...
my $output = $ssh->capture({stdin_data => "show int g2/1\n"});
$ssh->error and die "unable to run remote command: " . $ssh->error;
I suspect since you are dealing with a router, you want to enable raw_pty => 1 like the Net::SSH::Expect documentation suggests. Also, it might be easier for you to use the ->exec calls instead of the ->send + read_line.
For debugging further, pass in the log_stdout to the Net::SSH::Expect constructor and see if you can detect anything awry happening. Why did you comment out 'use strict'? Always 'use strict' and 'use warnings'

How do I authenticate into Gmail using Perl?

I've installed this module to gain access and controls within a Gmail inbox. However, when I try to connect through a small Perl script and test the functionality, I get this error message.
Error: Could not login with those credentials - could not find final URL
Additionally, HTTP error: 200 OK
This is an error built within the Gmail.pm module.
I can ping the URL in question ( https://www.google.com/accounts/ServiceLoginBoxAuth ) so I feel that the trouble isn't finding the URL. Furthermore, I know the credentials are correct and work at that URL because I have tried them manually.
I'm using this script for testing. I have supplied my credentials in the appropriate places.
I've also installed this module with the same type of error.
Any idea why I'm getting blocked?
Use Mail::IMAPClient as shown below. To get pass SSL authentication through Mail::IMAPClient, you should have IO::Socket::SSL from Net::SSLeay installed. If so this works like a charm.
#!/usr/bin/env perl
use strict; use warnings;
use Mail::IMAPClient;
# Connect to IMAP server
my $client = Mail::IMAPClient->new(
Server => 'imap.gmail.com',
User => 'yourusername',
Password => 'yourp4a55w0r&',
Port => 993,
Ssl => 1,
)
or die "Cannot connect through IMAPClient: $!";
# List folders on remote server (see if all is ok)
if ( $client->IsAuthenticated() ) {
print "Folders:\n";
print "- ", $_, "\n" for #{ $client->folders() };
};
# Say so long
$client->logout();
I am successfully accessing a gmail account (google apps account to be precise) using Mail::POP3Client
If you cannot access gmail through normal POP3 or IMAP either, then you have a configuration problem rather than a programming problem.
I fetch my mail from gmail (actually Google Apps, which uses the same interface), using configuration details described here: http://download.gna.org/hpr/fetchmail/FAQ/gmail-pop-howto.html
(This answer is far more appropriate for Super User though!)
You can tried with the following module
Mail::Webmail::Gmail
You can use the following code also
use warnings;
use strict;
use Mail::POP3Client;
use IO::Socket::SSL;
use CGI qw(:standard);
my $cgi = new CGI;
my $LOG ;
open $LOG , ">>filename" ;
my $username = 'name#gmail.com';
my $password = '*******' ;
chomp($password);
my $mailhost = 'pop.gmail.com';
my $port = '995';
$cgi->header();
my $pop = new Mail::POP3Client(
USER => $username,
PASSWORD => $password,
HOST => $mailhost,
PORT => $port,
USESSL => 'true',
DEBUG => 0,
);
if (($pop->Count()) < 1) {
exit;
}
print $pop->Count() . " messages found!:$!\n";
for(my $i = 1; $i <= $pop->Count(); $i++) {
foreach($pop->Head($i)) {
/^(From|Subject|Email):\s+/i && print $_, "\n";
}
$pop->BodyToFile($LOG,$i);
}
$pop->Close();
exit;