使用 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 文件。我需要解决的挑战:

导入一个 100 MB 范围内的 .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 数据库的主要内容,如果未能解决你的问题,请参考以下文章

ruby Chef_kill_command.rb

ruby Chef-provisioning集群提供商

makefile报错:warning: overriding recipe for target xxx

makefile报错:warning: overriding recipe for target xxx

arch/arm/Makefile:331: recipe for target ‘uImage‘ failed

arch/arm/Makefile:331: recipe for target ‘uImage‘ failed