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:
script for 5.8.6 not working in 5.8.8 or 5.10.0

 



t0astbandit
Novice

Jan 23, 2009, 8:12 AM

Post #1 of 8 (985 views)
script for 5.8.6 not working in 5.8.8 or 5.10.0 Can't Post

I have a script on a slackware 9 box, using perl 5.8.6 (I know, these are oldballs, but i didn't set them up). The script works fine there, but there are 5 other servers using Debian Etch, with either 5.8.8 or 5.10.0 where it does not work. I've been racking my brain all week to figure out what was changed to make it stop working. I didn't write the script, set up the boxes or do the perl upgrade, so that's making it more difficult. Basically the script queries a database server, then checks to see if there were any changes and either dies or updates a file. I also tried to bundle the perl modules on the working server and import them to one of the others. I didn't have high hopes for it to work, and it didn't :( It's also not logging, but I'm not really concerned with that at the moment.

I'm wondering if someone has a couple minutes to give it a look and see if they notice something I've missed. I've tried everything I can think of and am coming up with nothing. Any help would be GREATLY appreciated!

Below is the script:

Code
#!/usr/bin/perl 

#
# use VI with ":set tabstop=3" to view/edit properly.
#

use strict;
use DBI;
use DBD::mysql;
my $debug = 0;
my $mysql_server = 'servername';
my $mysql_db = 'databasename';
my $mysql_user = 'uername';
my $mysql_pass = 'password';
my $timestamp_file = '/var/qmail/qpsmtpd/timestamp.update_recip_lists';
my $logfile = '/var/log/update_recip_lists.log';

open( STDOUT, ">$logfile" );
open( STDERR, ">>$logfile" );

&main();

close(STDOUT);
close(STDERR);

sub main() {
my $lastrun = &get_lastrun();
my $thisrun;
my $query = "select distinct domain, NOW()+0 from recip_lists where timestamp > $lastrun";
my $dbh = DBI->connect("DBI:mysql:$mysql_db:$mysql_server", $mysql_user, $mysql_pass);
$dbh->do("use $mysql_db");
my $sth = $dbh->prepare($query) || die print("DBI could not prepare sth in sub main: " . $dbh->errstr());
$sth->execute() || die print("DBI could not execute sth in sub main: " . $dbh->errstr());
while (my @ary = $sth->fetchrow_array()) {
$thisrun = $ary[1] if ($ary[1] > $thisrun);
print("Updating recipient lists for: $ary[0]");
&update_lists($ary[0]);
}
$sth->finish();
$dbh->disconnect();
if ($thisrun) {
system("echo -n $thisrun > $timestamp_file");
#system("/usr/local/bin/timuel_restart_everything");
} else {
print("no updates since $lastrun, nothing to do here.");
};

system("/usr/bin/touch $timestamp_file");
}



sub get_lastrun() {
my $l = shift();
open(STAMP, $timestamp_file);
$l = <STAMP>;
close(STAMP);
chomp($l);
if (!$l) {
my $query = "select NOW()+0";
my $dbh = DBI->connect("DBI:mysql:$mysql_db:$mysql_server", $mysql_user, $mysql_pass);
my $sth = $dbh->prepare($query) || die print("DBI could not prepare sth in sub get_lastrun: " . $dbh->errstr());
$sth->execute() || die print("DBI could not execute sth in sub get_lastrun: " . $dbh->errstr());
my @result = $sth->fetchrow_array;
$sth->finish();
$dbh->disconnect();
$l = $result[0];
print("$timestamp_file did not exist, using new value $l");
system("echo -n $l > $timestamp_file");
}
return($l);
}



sub update_lists() {
my (%sql_hashref, %file_hash, $configfile, $tempfile);
my $update_domain = lc($_[0]);
my $validation_pref;

my $dbh = DBI->connect("DBI:mysql:$mysql_db:$mysql_server", $mysql_user, $mysql_pass);
$dbh->do("use $mysql_db");
my $query = "select recip_validation from prefs where user = \"$update_domain\"";
my $sth = $dbh->prepare($query) || die print("DBI could not prepare sth in sub update_lists: " . $dbh->errstr());
$sth->execute() || die print("DBI could not execute sth in sub update_lists: " . $dbh->errstr());
while (my @ary = $sth->fetchrow_array()) {
$validation_pref = $ary[0];
}

print "$update_domain wishes to use $validation_pref recipient validation\n";

my $configfile = '/var/qmail/qpsmtpd/config/'.$update_domain.'/'.$validation_pref;
$tempfile = '/var/qmail/qpsmtpd/config/'.$update_domain.'/'.$validation_pref.'.TEMP';
print "DOMAIN configfile is $configfile\n" if ($debug);

if ($validation_pref eq "goodrcptto" || $validation_pref eq "badrcptto") {
open(TEMPFILE, ">$tempfile");
$query = "select uname from recip_lists where domain = \"$update_domain\" and $validation_pref = 1";
$sth = $dbh->prepare($query) || die print("DBI could not prepare sth in sub update_lists: " . $dbh->errstr());
$sth->execute() || die print("DBI could not execute sth in sub update_lists: " . $dbh->errstr());
while (my @ary = $sth->fetchrow_array()) {
#print("inserting $ary[0]".'@'."$update_domain into $configfile\n");
next if ($ary[0] eq "CCMDEFAULT");
die("refusing to create blank goodrcptto file") if ($validation_pref eq "goodrcptto" && !$ary[0]);
$ary[0] = lc($ary[0]);
print TEMPFILE $ary[0].'@'.$update_domain."\n";
};
};

my $existingupgoodrcptto= '/var/qmail/qpsmtpd/config/'.$update_domain.'/goodrcptto';
my $backupgoodrcptto = '/var/qmail/qpsmtpd/config/'.$update_domain.'/goodrcptto.BAK';
my $existingbadrcptto = '/var/qmail/qpsmtpd/config/'.$update_domain.'/badrcptto';
my $backupbadrcptto = '/var/qmail/qpsmtpd/config/'.$update_domain.'/badrcptto.BAK';

system("mv $existingupgoodrcptto $backupgoodrcptto") if (-f $existingupgoodrcptto);
system("mv $existingbadrcptto $backupbadrcptto") if (-f $existingbadrcptto);
system("mv $tempfile $configfile") if (-f $tempfile);
}



(This post was edited by t0astbandit on Jan 23, 2009, 8:19 AM)


FishMonger
Veteran / Moderator

Jan 23, 2009, 8:40 AM

Post #2 of 8 (979 views)
Re: [t0astbandit] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

That is some really bad Perl coding. When I have more free time I'll point out some of the problems.

What errors are you receiving?

Besides the logging failure, what else is it not doing?


Quote
I also tried to bundle the perl modules on the working server and import them to one of the others. I didn't have high hopes for it to work, and it didn't

Does that mean that the other servers are missing some modules? If so, then before doing anything else, you need to install those missing modules.


t0astbandit
Novice

Jan 23, 2009, 8:49 AM

Post #3 of 8 (977 views)
Re: [FishMonger] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

lol yeah, I'd like to throw the guy who wrote it down some stairs. I'm guessing I'll have to redo it completely eventually. If I add -w, the only thing I get is below. I'm not catching anything indicating it though:

"my" variable $configfile masks earlier declaration in same scope at ./update_recip_lists.pl.back2 line 92.

Regarding the modules, the servers have the same modules now. I was hoping it would be an easy fix. :)

Thanks again for looking it. I really appreciate it.


KevinR
Veteran


Jan 23, 2009, 9:32 AM

Post #4 of 8 (973 views)
Re: [t0astbandit] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

Read the DBI modules documentation and incorporate some error proper error checking in the database stuff.

I would also make sure the system() function calls all work properly acorss the various servers, they look like they will but you have to make sure otherwise thet could cause your script to hang.

Add a die check to operating system commands, like this line (#55):

open(STAMP, $timestamp_file);

should be:

open(STAMP, $timestamp_file) or die "Can't open $timestamp_file: $!";

Same with lines 18, 19, and 97.

The one warning you are getting is not significant but you could remove the "my" from line 92 and the code will work and the warning will go away.
-------------------------------------------------


t0astbandit
Novice

Jan 23, 2009, 10:14 AM

Post #5 of 8 (970 views)
Re: [KevinR] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

Good ideas. :) Thanks!

I forgot to mention that I removed the 'my' from line 92, which took care of the error.


FishMonger
Veteran / Moderator

Jan 23, 2009, 11:17 AM

Post #6 of 8 (964 views)
Re: [t0astbandit] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

Personally, I'd start over from scratch rather than fixing that script.

Here are a few recommendations.

Use the warnings pragma instead of the -w switch
use warnings;

Add proper error handling, as Kevin recommends.

Use lexical vars for the filehandles instead of the barewords and use the 3 arg form of open.

Don't use '&' when calling the subs, but if you do, you should know about and need its side-affects. The author of that script certainly didn't know anything about the side-affects (i.e., how does it affect prototypes and the use of the @_ array).

Don't use prototypes in the subroutines. i.e.,
sub get_lastrun() {
should be
sub get_lastrun {

$dbh->do("use $mysql_db"); is pointless because it's already part of the connect statement.

Doing a db call to get the current timestamp is utterly absurd; use the stftime function from the POSIX module

None of those system calls are needed. Perl has methods for accomplishing those tasks, some of which are already being used in other portions of the script.

For proper logging, you may want to look at Log::Log4perl
http://search.cpan.org/~mschilli/Log-Log4perl-1.20/lib/Log/Log4perl.pm
However, that might be overkill for this script.

There are other recommendations that I could make, but that should be enough to get you started.


t0astbandit
Novice

Jan 23, 2009, 12:17 PM

Post #7 of 8 (960 views)
Re: [FishMonger] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post

<3
Thanks again! I think you're right. I will be much faster and efficient if I don't waste anymore time trying to fix it.


(This post was edited by t0astbandit on Jan 23, 2009, 12:18 PM)


t0astbandit
Novice

Jan 23, 2009, 1:34 PM

Post #8 of 8 (953 views)
Re: [FishMonger] script for 5.8.6 not working in 5.8.8 or 5.10.0 [In reply to] Can't Post


Quote
Besides the logging failure, what else is it not doing?


I forgot to answer that. The it is not updating the "goodrcptto" file. When I connect manually to the DB server, getting the data works fine. I'm not sure if the problem is the system commands or not being able to compare the timestamps though.

 
 


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

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