English 中文(简体)
Importing Mysql database using Ruby/Chef Recipe for Vagrant
原标题:

I am writing a chef script to automate setting dev environments. I can get a database created and grant privileges but I am trying to find out a way to import a mysql dump file into the database that has just been created.

My code for granting the access is

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

and I was hoping I would be able to do the following query #m.query("-u root -p root db_name < /project/db/import.sql")

but is just gives me an error.

I haven t done much Ruby so finding it hard to figure out. Anybody know how I can do this?

问题回答

If it s a file path error, and you re using chef solo, try using the path specified within solo.rb, like:

/tmp/chef-solo/site-cookbooks/path_to_file.sql

As a general note, consider using the database cookbook for mysql user and database management tasks. Once you setup the necessary cookbook dependencies, you can put code like this into your main recipe s 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

Haven t tested that last one because storing a database file within the chef directory really slows things down.

See also: Import SQL file into mysql

You can create a backup from the MySQL command line client, but not from within a SQL query. You need to execute the command from the shell. I believe the execute resource might do the trick for you:

http://wiki.opscode.com/display/chef/Resources#Resources-Execute

I m not really a Ruby guy, but I managed to get Chef to import a large .sql file by leveraging the mysql command line tool. Challenges I needed to solve:

  • Import a .sql file in the 100 s of MB range (YMMV if you need GBs or TBs)
  • Idempotentcy — only run the import if the .sql file has changed
  • Not pass credentials to MySQL as command parameters (a security concern)

First I created a .my.cnf file template to pass the credentials:

templates/default/.my.cnf.erb

[client]
host=<%= @host %>
user=<%= @user %>
password="<%= @password %>"

Then I added a resource to my recipe that would populate the template:

recipes/import-db.rb

template  /root/.my.cnf  do
  mode 0600
  variables({
    :host =>  localhost ,
    :user =>  root ,
    :password => node[:your_cookbook][:db][:root_password],
  })
end

(Where node[:your_cookbook][:db][:root_password] is an attribute that contains the MySQL root password)

Security Note: for simplicity I m doing the import as the root user. If the .sql file to be imported is not from a trusted source, you will want to run mysql as a limited user and connect to MySQL with a limited db user that only has access to the database in question.

Finally, I added another resource to the recipe that actually executes the import:

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

(Where node[:your_cookbook][:db][:name] is the name of the MySQL database that will be restored.)





相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

php return a specific row from query

Is it possible in php to return a specific row of data from a mysql query? None of the fetch statements that I ve found return a 2 dimensional array to access specific rows. I want to be able to ...

Character Encodings in PHP and MySQL

Our website was developed with a meta tag set to... <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> This works fine for M-dashes and special quotes, etc. However, I ...

Pagination Strategies for Complex (slow) Datasets

What are some of the strategies being used for pagination of data sets that involve complex queries? count(*) takes ~1.5 sec so we don t want to hit the DB for every page view. Currently there are ~...

Averaging a total in mySQL

My table looks like person_id | car_id | miles ------------------------------ 1 | 1 | 100 1 | 2 | 200 2 | 3 | 1000 2 | 4 | 500 I need to ...

热门标签