We help IT Professionals succeed at work.

Can't locate DBI.pm in @INC

AlexAmbler
AlexAmbler asked
on
Hi,

I am trying to use scheduled tasks (cron) in plesk to send a daily reminder to an email address for birthdays in my office,
The code is below, when it runs I get the following error message.

Can't locate DBI.pm in @INC (@INC contains: C:/Program Files/Parallels/Plesk/Additional/Perl/lib C:/Program Files/Parallels/Plesk/Additional/Perl/site/lib .) at C:\inetpub\vhosts\httpdocs\testserver\email2.pl line 4.
BEGIN failed--compilation aborted at C:\inetpub\vhosts\httpdocs\testserver\email2.pl line 4.

I have checked to see if DBI is installed using the command perl –MCPAN –e “installed DBI”

I get the response DBI is up to date (1.611)

Can you please help?

#!/usr/local/bin/perl  

use strict;
use DBI;
use CGI;
use MIME::Lite;

use POSIX qw( strftime );
my $mmddyyyy = strftime("%m/%d/%Y", localtime);
my $mm = strftime("%m", localtime);
my $dd = strftime("%d", localtime);
my $yy = strftime("%Y", localtime);

 # Enter Database info
 my $USERNAME = "888";
 my $PASSWORD = "888";
 my $DATABASE = "888";

my $dbh = DBI->connect("dbi:mysql:$DATABASE:localhost:3306", "$USERNAME", "$PASSWORD");

# if ID is an int, this should be "ID = 0" but if it is a char or varchar, it is correct
my $settings1 = $dbh->prepare("select * From settings WHERE ID = '0'");  
$settings1->execute();  

# since you are selecting * that must include ID, but you don't have ID in this list.
# Assuming it is the first field in the row, I've added it
while (my ($ID, $Path, $Ops_Email, $From_Email, $Subject, $Monthly_Email, $Email_Reminders) = $settings1->fetchrow_array()) {

	# move on if we aren't doing anything
	next unless $Email_Reminders == 1 or $Monthly_Email == 1;

	# Daily Reminders
	if ($Email_Reminders == 1) {

		# We'll add the start and end of the body only if there were any birthdays today
		my ($dailycount,$body);
		$sth->execute();
		while(my ($Name, $Address, $City, $State, $Postal, $Country, $B_Date) = $sth->fetchrow_array()) {  
			# Add one to the $dailycount
			$dailycount++;

			# Get just the year of $B_Date by getting rid of everything after the first dash
			(my $B_Year = $B_Date) =~ s/-.*//;
			my $age = $yy - $B_Year;

			$body .= "     $Name (Turns $age!)\n";

		}
		$sth->finish;
		$body .= "\n";

		# don't send any if there are none
		if ($dailycount > 0) {
			$body = <<EOL;
Hello!,

This Is Your Automated Birthday Reminder.

The following people have their birthday TODAY:

$body
This is an automated message, please do not respond.
EOL

			# You are sending one email per row in the table "settings" so it must be within that loop
			my $msg = MIME::Lite->new(
				From     =>$From_Email,
				To       =>$To_Email,
				Subject  =>$Subject,
				Data     =>$body
			);
			### Send in the "best" way (the default is to use "sendmail"):
			$msg->send;
		}
	}
	# end Daily Reminders 

	# Do monthly reminders if it is the first of the month
	if ($dd == 1) {
		################  
		# MONTHLYEMAIL #  
		################  

		# prepare the query  
		my $sthMonthly = $dbh->prepare("select * From teamdates WHERE `B_Date` LIKE '%-$mm-%'");  

		# execute the query  
		$sthMonthly->execute();  

		# We'll add the start and end of the body only if there were any birthdays today
		my ($monthcount,$body);
		while(my ($Name, $B_Date) = $sthMonthly->fetchrow_array()) {
			$monthcount++;

			# Get just the year of $B_Date by getting rid of everything after the first dash
			(my $B_Year = $B_Date) =~ s/-.*//;
			my $age = $yy - $B_Year;
			$body .= "     $Name (Turns $age2!) $B_Date\n";
		};  
		if ($monthcount) {

			## Mail Body  
			my $body = <<EOL;
Hello!,  

This Is Your Automated Reminder.  

The following people have their birthday this MONTH:\n\n";  

$body
This is an automated message, please do not respond.
EOL

			my $msg = MIME::Lite->new(
				From     =>$From_Email,
				To       =>$Ops_Email,
				Subject  =>$Subject,
				Data     =>$body
			);
			### Send in the "best" way (the default is to use "sendmail"):
			$msg->send;
		}
	}
}

Open in new window

Comment
Watch Question

My first guess is an environment difference between your command line and web server.  I would suggest finding where DBI is installed and adding the appropriate path to 'use lib' prior to the 'use DBI' line.

I would also highly recommend adding 'use warnings' after 'use strict' as it will help to catch errors in the code (though this is not a code error).

Commented:
Your environment variables must not be set the same way when the application is run from the cron.
Here's what I suggest, create a cronjob that dumps the content of @INC into a file that would can inspect.
Compare the content of the file vs. the value of @INC when run by hand.
Then either add the missing paths to the env varaiable PERLLIB, or specify those paths using the "use lib qw(/my/path /my/other/path);' mechanism

Good luck!

Author

Commented:
hi,
How do I add the path using the use lib?

I think the path is C:\Perl\bin

Regards,
The path you need to add is the path to the DBI.pm which should be C:\Perl\lib.

I think it would be:
use lib 'C:\Perl\lib';

If that doesn't work, I'd try:
use lib 'C:/Perl/lib';

However, if your DBI is in a different directory, then you will need to 'use lib' where it is rather than C:\Perl\lib.
Commented:
Here's my favorite trick to determine where the Module.pm you need is located.

perl -MDBI -d -e0 and then type V at the debugger prompt, then locate the module and its associated path:

Look below for a transcript...



C:\Documents and Settings\jerome>perl -MDBI -d -e0

Loading DB routines from perl5db.pl version 1.3
Editor support available.

Enter h or `h h' for help, or `perldoc perldebug' for more help.

main::(-e:1):   0

  DB<1> v
1==>    0

  DB<1> V
$/ = '
'
FileHandle(stderr) => fileno(2)
%SIG = (
   'ABRT' => undef
   'ALRM' => undef
   'BREAK' => undef
   'BUS' => CODE(0x19e1504)
      -> &CODE(0x19e1504) in ???
   'CHLD' => undef
   'CLD' => undef
   'CONT' => undef
   'FPE' => undef
   'HUP' => undef
   'ILL' => undef
   'INT' => CODE(0x19beb34)
      -> &DB::catch in 0
   'KILL' => undef
   'NUM05' => undef
   'NUM06' => undef
   'NUM07' => undef
   'NUM10' => undef
   'NUM12' => undef
   'NUM16' => undef
   'NUM17' => undef
   'NUM18' => undef
   'NUM19' => undef
   'NUM24' => undef
   'PIPE' => undef
   'QUIT' => undef
   'SEGV' => CODE(0x19e1504)
      -> REUSED_ADDRESS
   'STOP' => undef
   'TERM' => undef
   'WINCH' => 'readline::get_window_size'
   '__DIE__' => CODE(0x19e1934)
      -> &DB::dbdie in 0
   '__WARN__' => CODE(0x19e1734)
      -> &DB::dbwarn in 0
)
$^L = "\cL"
$^ = 'OUT_TOP'
$$ = 16540
$\ = ''
$- = 0
@- = (
   0  empty slot
   1  empty slot
   2  empty slot
)
$! = 'No such file or directory'
$^X = 'C:\\Perl\\bin\\perl.exe'
$^UNICODE = 0
$^V = v5.10.0
$= = 60
$2 = ''
$^WARNING_BITS = "\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@"
FileHandle(stdin) => fileno(0)
@INC = (
   0  'C:/Perl/site/lib'
   1  'C:/Perl/lib'
   2  '.'
)
%INC = (
   'ActivePerl/Config.pm' => 'C:/Perl/lib/ActivePerl/Config.pm'
   'ActiveState/Path.pm' => 'C:/Perl/lib/ActiveState/Path.pm'
   'AutoLoader.pm' => 'C:/Perl/lib/AutoLoader.pm'
   'C:/Perl/site/lib/sitecustomize.pl' => 'C:/Perl/site/lib/sitecustomize.pl'
   'Carp.pm' => 'C:/Perl/lib/Carp.pm'
   'Carp/Heavy.pm' => 'C:/Perl/lib/Carp/Heavy.pm'
   'Config.pm' => 'C:/Perl/lib/Config.pm'
   'Config_heavy.pl' => 'C:/Perl/lib/Config_heavy.pl'
   'Cwd.pm' => 'C:/Perl/lib/Cwd.pm'
   'DBI.pm' => 'C:/Perl/lib/DBI.pm'  <---------------------

Open in new window

I prefer the simpler method:

perl -e 'use DBI; print $INC{"DBI.pm"}, "\n"'

That one-liner will print out the location where perl finds DBI.

Commented:
A good one! Thanks Wilcoxon!
That's what I like about Perl, no matter how long you have been usingit, there's always something new  to learn.