1

I am trying to write a simple perl script to pull the full contents of a table from a MySQL database using DBI.

I want to not have to put the database password in the script, so I'd like to set a password variable that reads from a file that contains the password.

I've got the script set up so that the three DBI parameters (DSN, user and pass) are variables. When I explicitly specify the password in the script, it works. When I have it read the file, it fails.

I even built in a small test to echo the $pass variable before calling DBI and that works great. It shows me the right password.

I'm certain that I'm doing something dumb. Help?

The environment:


~/mysql$ uname -a

Linux kbwm-radio-web 3.2.0-24-virtual #37-Ubuntu SMP Wed Apr 25 12:51:49 UTC 2012 i686 i686 i686 GNU/Linux

~/mysql$ perl --version

This is perl 5, version 18, subversion 2 (v5.18.2) built for i686-linux-gnu-thread-multi-64int
(with 41 registered patches, see perl -V for more detail)

~/mysql$ mysql -u phpuser -pcat ./phpuser.auth barret_test -e "status;"

mysql  Ver 14.14 Distrib 5.5.41, for debian-linux-gnu (i686) using readline 6.3

As you can see, using command expansion in the mysql statement for the password is functional.

The script (yes, parts of it are inelegant. That'll be fixed later):

#!/usr/bin/perl

use strict;
use warnings;
use DBI;

my $dsn = "dbi:mysql:barret_test:localhost:3306";
my $user = "phpuser";
my $pass = qx{cat /home/barret/mysql/phpuser.auth};

print "$pass\n";


my $dbh = DBI->connect(
    $dsn,
    $user,
    $pass,
    { RaiseError => 1 },
) or die $DBI::errstr;

my $all = $dbh->selectall_arrayref("select name from users;");

foreach my $row (@$all) {
        my ($name) = @$row;
        print "$name\n";
}

$dbh->disconnect();

Running it returns:

~/mysql$ perl user_list.pl

*redacted_password*


DBI connect('barret_test:localhost:3306','phpuser',...) failed: Access denied for user 'phpuser'@'localhost' (using password: YES) at user_list.pl line 14.

If I change line 9 from

my $pass = qx{cat /home/barret/mysql/phpuser.auth};

to

my $pass = "redacted_password";

This happens:

~/mysql$ perl user_list.pl

*redacted_password*

barret

richard

dave

I've Googled around and searched here, didn't see anything that seemed to cover my use case. I tried wrapping the $pass inside the DBI call in single and double quotes, no changes.

4

2 回答 2

2

Don't do it that way. MySQL provides a way to manage connection credentials using what they call option files. For example:

[client]
host = localhost
database = mydb
user = foo
password = bar

Make sure your file is not world-readable (0600 permissions on *nix). You can test that it's working using the command line client:

mysql --defaults-file=/path/to/file

To use an option file with DBI, do:

my $db_conf = '/path/to/file';
my $dsn = "DBI:mysql:;mysql_read_default_file=$db_conf";

my $dbh = DBI->connect($dsn, undef, undef, { RaiseError => 1 }) or
        die $DBI::errstr;
于 2015-04-09T00:29:15.370 回答
0

Adding a chomp to the script answered the question I asked.

my $pass = qx{cat /home/barret/mysql/phpuser.auth};
chomp ($pass);

Worked like a charm.

However... the solution I actually wanted was to use the mysql options_file.

my $db_conf = '/home/barret/mysql/phpuser.mysql';
my $dsn = "DBI:mysql:;mysql_read_default_file=$db_conf";

my $dbh = DBI->connect($dsn, undef, undef, { RaiseError => 1 }) or
    die $DBI::errstr;

And inside the options file:

~/mysql$ cat phpuser.mysql
[client]
host = localhost
database = barret_test
user = phpuser
password = *redacted_password*

Resulting in:

$ perl user_list.pl
barret
richard
dave
于 2015-04-09T01:09:47.310 回答