【问题标题】:Importing Mysql database using Ruby/Chef Recipe for Vagrant使用 Ruby/Chef Recipe for Vagrant 导入 Mysql 数据库
【发布时间】: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,所以很难弄清楚。有人知道我该怎么做吗?

【问题讨论】:

    标签: mysql ruby chef-infra recipe vagrant


    【解决方案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 数据库的名称。)

    【讨论】:

      猜你喜欢
      • 2014-01-09
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-01
      • 1970-01-01
      相关资源
      最近更新 更多