views:

60

answers:

1

I have the following script to update one of my FTP passwords every 15 days through a cronjob and e-mail the appropriate people after the attempt has been made. It randomly will fail and so I will run it again manually and it will work. I can't seem to find where it's going wrong.

The script is connecting to a local mysql database grabbing the login and password for an account and then changing that password on FTP. Everything is successful up until the changing the password part. Again it's random, sometimes it works, sometime it doesn't.

Thanks!

#!/usr/bin/perl -w
#

use DBI;
use Net::FTP;

our $dbh = DBI->connect('DBI:mysql:database:127.0.0.1','user','password') or die "Aargh $!\n";
$transquery=q{SELECT dest_login,dest_password FROM list where id=123};
$sth=$dbh->prepare($transquery);
$sth->execute();
while($co=$sth->fetchrow_hashref){
  $login=$co->{'dest_login'};
  $pass=$co->{'dest_password'};
}

$changeresult='FAIL';
$actionlog='';
$newstring='';
$upperchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lowerchars='abcdefghijklmnopqrstuvwxyz';
$allowedchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$';
$l=length($upperchars);
  $newstring.=substr($upperchars,int(rand($l)),1);
  $newstring.=substr($lowerchars,int(rand($l)),1);
$l=length($allowedchars);
for ($i=0;$i<6;$i++){
  $newstring.=substr($allowedchars,int(rand($l)),1);
}
print "$newstring\n";
$actionlog .= "Setting Password for $login from $pass to $newstring\n";
$username=
eval{
    $ftp=Net::FTP->new('x.x.x.x',Timeout=>480,Debug=>1) or die "Error connecting FTP $!\n";
    $changepassword="$pass/$newstring/$newstring";
    $ftp->login($login,$changepassword) or die "Error changing password $!\n";
    #If we are here, time to update the password
    $changeresult='SUCCESS';
    $actionlog .= "Password successfully updated\n";
    $transquery=q{UPDATE list set dest_password=(?) where id=123};
    $sth=$dbh->prepare($transquery);
    $sth->execute($newstring);
  };

  if ($@) {
    $actionlog = $actionlog . "$@\n";
  };
if($actionlog ne ""){
  #print $actionlog;

  #my $send_to  = "To: someone\@example.com\n";
  my $send_to  = "To: databaseusers\@example.com\n";
  my $sendmail = "/usr/sbin/sendmail -t";

  open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!";
  print SENDMAIL "Reply-to: databasepassword\@example.com\n";
  print SENDMAIL "Subject: Password Change Information [$changeresult]\n";
  print SENDMAIL $send_to;
  print SENDMAIL "Content-type: text/plain\n\n";
  print SENDMAIL $send_to;
  print SENDMAIL "Content-type: text/plain\n\n";
  print SENDMAIL $actionlog;
  close(SENDMAIL);
  $actionlog='';
}
else{
  #print "Nothing done this session\n";
+1  A: 

USUW might tell you something. ( use strict; use warnings; )

Does anything print?

You don't do much error checking in the DBI part at the beginning, perhaps you're getting a connect error. AIX boxes used to have this problem of getting a client port that the system was unsure about whether or not it was in use. When that happened, it would just fail to connect to the database.

I finally fixed that problem for our scripts by examining the $OS_ERROR ( aka $! ) for that particular code ( Errno::EADDRINUSE ) and then waiting and retrying, with an exponential falloff ( wait 2 seconds, then 4, then 8 ... ).

If your script "dies for some reason" then it's important the script can tell you that reason. I would investigate the topic of error reporting in the various modules you are using.

For example Net::FTP allows you to pass a Debug => 1 switch, and then you'll see the whole conversation.

And I know that there is a whole lot more with DBI where you can get error reporting.

Axeman