2011-08-03 162 views
0

我是新来的Perl,并试图在RHEL框中编写脚本,该脚本会自动配置我们在主机上创建的新站点的vanilla DB。我已经有连接语句工作,我能够连接并从脚本中创建一个数据库(使用$ dbh-> do(qq(CREATE DATABASE $ dbcreate));这是最好的方式???),但我有一对夫妇,我一直无法弄清楚如何让他们工作。执行mysql命令的Perl脚本?

这些是我有问题的mysql命令。有什么建议么?谢谢!

$dbh = DBI->connect("DBI:mysql:$db:$host", $user, $pass); 
$dbh->do(qq(CREATE DATABASE $dbcreate)); 
$dbh->do(qq(GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX , ALTER , CREATE TEMPORARY TABLES , CREATE VIEW , SHOW VIEW , CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON `$dbcreate` . * TO 'moodle'@'%'`)); 
$dbh->do(qq(FLUSH PRIVILEGES)); 
$dbh->do(qq($dbcreate < MySQL_pristine.sql)); 
$dbh->do(qq(USE $dbcreate)); 
$dbh->do(qq(UPDATE md1_label SET content = REPLACE(content, "pristine", "$dbcreate"))); 
$dbh->do(qq(UPDATE md1_label SET contents = REPLACE(contents, "pristine", "$dbcreate"))); 
$dbh->do(qq(UPDATE md1_label SET questiontext = REPLACE(questiontext, "pristine", "$dbcreate"))); 

DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GRANT SELECT , INSERT , UPDATE , DELETE , CREATE , DROP , INDEX ,�' at line 1 at create-auto-db.pl line 52. 
DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'test3 < MySQL_pristine.sql' at line 1 at create-auto-db.pl line 54. 
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 56. 
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 57. 
DBD::mysql::db do failed: Table 'test3.md1_label' doesn't exist at create-auto-db.pl line 58. 
+2

如果你使用的是DBI,你为什么还试图与mysql shell交互工作?你的问题的前半部分涉及Perl,后半部分涉及将文件重定向到命令行工具'mysql'。你的示例代码中没有Perl。此外,你还没有解释你有什么问题。我们应该猜测吗? – DavidO

+0

所有这些语句都可以在'DBI'中正常工作,并且可以从'$ dbh-> do()'执行。如果您收到错误消息,请将它们发布,然后再添加一些Perl。您发布的单个声明中存在一些风险,但没有任何我们可以在没有任何上下文的情况下提供帮助的风险。一个可能的问题是,如果你错误地引用了字符串(即用'qq {}'而不是'q {}'),则可能会插入'@'。 –

+0

@morungos我编辑了我的帖子,包括我试过的代码以及下面的错误。我认为你对@符号是正确的。 – Brandon

回答

0

您遇到的主要问题是插入包含符号的字符串。如果你有类似qq{Here is my email: [email protected]}的东西 - 这会失败,因为它会尝试放置一个不存在的列表变量@hotmail。使用反斜杠来转义它(即qq{Here is my email: test\@hotmail.com}),或者如果您不需要插入任何变量,请使用非插值报价q{...}

话虽如此,你需要对这些陈述中的一些小心。您将变量值放入这些SQL语句中,这是SQL注入攻击的风险。我使用$dbh->quote($dbcreate)获取字符串版本,并且$dbh->quote_identifier($dbcreate)获取$dbcreate值的标识符版本,并嵌入这些值。这更安全一些,因为它会避免某人在您身上执行Bobby Tables并给您一个数据库名称如:db'; DROP TABLE mysql.user; ';或类似的。 DBI提供了字符串和标识符引用,因此您可以根据需要获得正确的引用类型。例如:

my $quoted_id_dbcreate = $dbh->quote_identifier($dbcreate); 
$dbh->do(qq(USE $quoted_id_dbcreate)); 

占位符通常是更好的,但一些管理报表可能不会支持他们,所以用适当的引用注入的值很可能是必要的。

+0

谢谢,这现在按预期工作!我不会担心任何类型的注入,因为这将从非Web可访问目录中的命令行运行,并且只有root可以rwx该文件。我确定我的代码没有做得最好,但它完成了工作。再次感谢! – Brandon

0

两件事情对我而言非常重要。

$dbh->do(qq(GRANT SELECT , INSERT , (snip), EXECUTE ON '$dbcreate' . * TO 'moodle'@'%'`)); 

...你有一个你可能不打算的尾随反向信号。

$dbcreate < MySQL_pristine.sql 

...是不是你想要的。我想你要做的是在Perl中读取该文件,并遍历每个包含的SQL语句,并调用“$ dbh-> do()”。如果你非常幸运,那么.sql文件中的每条语句都有一行。