2011-08-03 208 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文件中的每條語句都有一行。