使用 Ruby/Chef Recipe for Vagrant 导入 Mysql 数据库
Posted
技术标签:
【中文标题】使用 Ruby/Chef Recipe for Vagrant 导入 Mysql 数据库【英文标题】:Importing Mysql database using Ruby/Chef Recipe for Vagrant 【发布时间】:2011-08-25 22:39:41 【问题描述】:我正在编写一个厨师脚本来自动设置开发环境。我可以创建一个数据库并授予权限,但我正在尝试找到一种将 mysql 转储文件导入刚刚创建的数据库的方法。
我授予访问权限的代码是
ruby_block "Execute grants" do
block do
require 'rubygems'
Gem.clear_paths
require 'mysql'
m = Mysql.new('localhost', "root", node[:mysql][:server_root_password])
m.query("GRANT ALL ON *.* TO 'root'@'10.0.0.1' IDENTIFIED BY '#node[:mysql][:server_root_password]'")
m.query('FLUSH PRIVILEGES')
end
end
我希望我能够执行以下查询
#m.query("-u root -p root db_name < /project/db/import.sql")
但这只是给我一个错误。
我没有做过很多 Ruby,所以很难弄清楚。有人知道我该怎么做吗?
【问题讨论】:
【参考方案1】:如果是文件路径错误,并且您使用的是 chef solo,请尝试使用 solo.rb 中指定的路径,例如:
/tmp/chef-solo/site-cookbooks/path_to_file.sql
作为一般说明,请考虑将database cookbook 用于mysql 用户和数据库管理任务。一旦你设置了必要的说明书依赖项,你就可以把这样的代码放到你的主配方的 default.rb 中:
# externalize conection info in a ruby hash
mysql_connection_info =
:host => "localhost",
:username => 'root',
:password => node['mysql']['server_root_password']
# drop if exists, then create a mysql database named DB_NAME
mysql_database 'DB_NAME' do
connection mysql_connection_info
action [:drop, :create]
end
# query a database from a sql script on disk
mysql_database "DB_NAME" do
connection mysql_connection_info
sql ::File.open("/tmp/chef-solo/site-cookbooks/main/path/to/sql_script.sql").read
action :query
end
#or import from a dump file
mysql_database "DB_NAME" do
connection mysql_connection_info
sql "source /tmp/chef-solo/site-cookbooks/main/path/to/sql_dump.sql;"
end
没有测试最后一个,因为在 chef 目录中存储数据库文件确实会减慢速度。
另见:Import SQL file into mysql
【讨论】:
source
命令仅在 mysql
CLI 工具中实现 - 而不是 MySQL 本身,因此尝试从 Ruby 中使用它会导致语法错误。 File.open().read
解决方案适用于小型 .sql 文件,但 it throws an error if the file is larger than 1MB.【参考方案2】:
您可以从 MySQL 命令行客户端创建备份,但不能从 SQL 查询中创建。您需要从 shell 执行命令。我相信execute
资源可能会为您解决问题:
http://wiki.opscode.com/display/chef/Resources#Resources-Execute
【讨论】:
我想我现在有正确的代码,但我认为问题是在命令行中以下工作mysql -p -u root test_project < import.sql
但是你得到一个需要填写的密码提示,然后它执行命令。我正在使用具有相同命令的执行资源,但即使我使用 -p 指定密码它也会失败。
您可以在命令行中包含密码。 mysql -u root -pSecret test_project < import.sql
不会提示输入密码(假设您的密码正确。您必须在 chef 脚本中包含密码,但对于 dev vagrant vm config 这应该不是问题。
另一种方法是使用随机生成的密码,就像 wordpress 为其厨师食谱所做的那样:github.com/opscode/cookbooks/tree/master/wordpress【参考方案3】:
我并不是真正的 Ruby 人,但我设法让 Chef 通过利用 mysql
命令行工具导入了一个大的 .sql
文件。我需要解决的挑战:
.sql
文件(如果您需要 GB 或 TB,则为 YMMV)
幂等性 — 仅当 .sql
文件已更改时才运行导入
不将凭据作为命令参数传递给 MySQL(安全问题)
首先我创建了一个.my.cnf
文件模板来传递凭据:
模板/默认/.my.cnf.erb
[client]
host=<%= @host %>
user=<%= @user %>
password="<%= @password %>"
然后我在我的食谱中添加了一个资源来填充模板:
食谱/import-db.rb
template '/root/.my.cnf' do
mode 0600
variables(
:host => 'localhost',
:user => 'root',
:password => node[:your_cookbook][:db][:root_password],
)
end
(其中node[:your_cookbook][:db][:root_password]
是一个包含MySQL root密码的属性)
安全说明:为简单起见,我以root
用户身份进行导入。如果要导入的 .sql
文件不是来自受信任的来源,您将需要以受限用户身份运行 mysql
并使用只能访问相关数据库的受限 db 用户连接到 MySQL。
最后,我在实际执行导入的配方中添加了另一个资源:
backup_sql = '/path/to/the/db-backup.sql'
db_last_modified = "/etc/db-#node[:your_cookbook][:db][:name].lastmodified"
execute 'restore backup' do
command "mysql #node[:your_cookbook][:db][:name] <'#backup_sql' && touch '#db_last_modified'"
not_if FileUtils.uptodate?(db_last_modified, [backup_sql])
end
(其中node[:your_cookbook][:db][:name]
是要恢复的 MySQL 数据库的名称。)
【讨论】:
以上是关于使用 Ruby/Chef Recipe for Vagrant 导入 Mysql 数据库的主要内容,如果未能解决你的问题,请参考以下文章
makefile报错:warning: overriding recipe for target xxx
makefile报错:warning: overriding recipe for target xxx