从文件中读取密码时使用 perl dbi 获取 "Access denied"

Getting "Access denied" with perl dbi when password is read from a file

我正在尝试编写一个简单的 perl 脚本来使用 DBIMySQL 数据库中提取 table 的全部内容。

我不想将数据库密码放在脚本中,所以我想设置一个密码变量,该变量从包含密码的文件中读取。

我已经设置了脚本,因此三个 DBI 参数(DSNuserpass)是变量。当我在脚本中明确指定密码时,它就起作用了。当我让它读取文件时,它失败了。

我什至构建了一个小测试来在调用 DBI 之前回显 $pass 变量并且效果很好。它显示了正确的密码。

我确定我在做一些愚蠢的事情。帮忙?

环境:


~/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

如您所见,在 mysql 语句中对密码使用命令扩展是有效的。

脚本(是的,部分内容不雅。稍后会修复):

#!/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();

运行它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.

如果我将第 9 行从

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

my $pass = "redacted_password";

发生这种情况:

~/mysql$ perl user_list.pl

*redacted_password*

barret

richard

dave

我用 Google 搜索并在此处进行了搜索,没有发现任何似乎涵盖我的用例的内容。我尝试用单引号和双引号将 $pass 包裹在 DBI 调用中,没有任何变化。

不要那样做。 MySQL 提供了一种使用他们所谓的 option files 来管理连接凭据的方法。例如:

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

确保您的文件不是全球可读的(*nix 上的 0600 权限)。您可以使用命令行客户端测试它是否正常工作:

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

要在 DBI 中使用选项文件,请执行:

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;

在脚本中添加 chomp 回答了我提出的问题。

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

工作得很好。

但是...我真正想要的解决方案是使用 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;

在选项文件中:

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

导致:

$ perl user_list.pl
barret
richard
dave