0

My problem is that: the outputs are different, when I run the program on the linux machine, and on a web browser of another machine.

When I run the program on the linux machine, the output is:

Content-type: text/plain
11
22
username password

But when I put the program on an Apache Server, and access it using a browser on another machine, the output is simply:

11

It is probably because the program fails to connect to the database file. As I have set all the files to mode 777, that I do not have the permission is unlikely a reason.

Anyone know what the problem is and how to fix it?

#!/usr/bin/perl -w

use DBI;

print ("Content-type: text/plain\n\n");

print "11\n";
my $dbh = DBI->connect("dbi:SQLite:dbname=4140.db","","",{RaiseError => 1},) or die $DBI::errstr;
print "22\n";

my $sth = $dbh -> prepare("SELECT * FROM Credential");
$sth -> execute();

($usrname, $password) = $sth -> fetchrow();

$sth -> finish();
$dbh->disconnect();

print "$usrname $password\n";
5
  • What's the error message? Commented Jan 23, 2013 at 12:15
  • I just got a page with “11”. There is no other message. Commented Jan 23, 2013 at 12:20
  • 2
    I'm not talking about the page. I mean the error message from your error log (also, you're missing use warnings; use strict;). Commented Jan 23, 2013 at 12:21
  • May I ask how to check the error log? I am a noob. Commented Jan 23, 2013 at 12:40
  • the problem is where the current path is. If you change the first print to this one: print $0, "\n"; it shows you where the script is... and you can use a ENV variable from the CGI specification to build the path (dbname=$ENV{---}/4140.db) Commented Jan 23, 2013 at 12:48

3 Answers 3

1

The die strings are sent to STDERR and so won't appear in the HTTP message that is sent. You can solve this several ways, one of the simplest being to write an error handler for DBI errors that prints the error message to STDOUT.

You should also always use strict and use warnings. That way Perl will highlight many simple errors that you could otherwise easily overlook. use warnings is far superior to -w on the command line.

Take a look at this code as an example. Note that if you enable RaiseError as well as providing an error handler then DBI will raise an exception only if your error handler returns a false value.

#!/usr/bin/perl

use strict;
use warnings;

use DBI;

print ("Content-type: text/plain\n\n");

print "11\n";

my $dbh = DBI->connect('dbi:SQLite:dbname=4140.db','','',
    {RaiseError => 1, PrintError => 0, HandleError => \&handle_error});

print "22\n";

my $sth = $dbh->prepare('SELECT * FROM Credential');
$sth->execute;

my ($usrname, $password) = $sth -> fetchrow();

print "$usrname $password\n";

sub handle_error {
  my ($msg, $dbh, $rv) = @_;
  print "DB Error: $msg\n";
  0;
}
Sign up to request clarification or add additional context in comments.

5 Comments

You are wrong. I have written a way for the OP to see the DB errors in his web client. They will still be sent to the error log as well, together with any other errors due to use strict violations or anything else.
[ok, I was mistaken on a side point. Fixed:] An exception handling scheme that only handles DB errors is useless. How ironic that you recommend the use of use strict; will produce errors your solution won't show.
@ikegami: This is debugging code targeted at finding a DBI error. Insisting that any error handler must be all-encompassing makes no more sense than requiring that there must be debugging print statements on every line of code.
This is the first time you mention that your answer should not be used except to debug. If that's true, it's still an awful answer for the same reason, not to mention it's rather intrusive. use CGI::Carp qw( fatalsToBrowser ); is way better.
@ikegami: Perhaps. The OP's problem is that he doesn't know what the problem is, and he may not be able to access the error log. If you had posted that alternative as your own answer instead of trying to pick holes in mine it would have been much more useful, and the community could have chosen between them. It may still not be too late.
1

Yo should specify the complete path to your database file in order to avoid this kind of problems. Try this (if your database is at the same path as your script):

use FindBin '$Bin';

my $dbfile = "$Bin/4140.db";
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","","",{RaiseError => 1},) or die $DBI::errstr;

#...

1 Comment

$RealBin is much better than $Bin since it handles symlinks. $RealBin is already being calculated, so it doesn't cost anything extra to use it.
1

Check your error log. You'll surely find that SQLite is failing to create 4140.db because of a permission error. You've made incorrect assumptions about the current directory.

2 Comments

If you try to open a handle to a database file that doesn't exist, then DBD::SQLite will create one for you. As far as I know the only way to avoid this is to do a separate -f check to ensure that the file is already there. It is entirely possible, of course, that the CGI directory isn't writeable so this create fails.
Updated. But you missed the point. 4140.db normally means /4140.db in CGI scripts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.