概要
mysql -u
mysqlimp = "mysql -u #{mysqllocal['user']} "
mysqlimp << "-h #{mysqllocal['host']} "
mysqlimp << "-p#{mysqllocal['pass']} "
mysqlimp << "#{mysqllocal['db']}"
Open3.popen3(mysqlimp) do |stdin, stdout, stderr, wthr|
stdin.write "DROP DATABASE IF EXISTS #{mysqllocal['db']};\n"
stdin.write "CREATE DATABASE #{mysqllocal['db']};\n"
stdin.write "USE #{mysqllocal['db']};\n"
stdin.write mysqldump #a string containing the database data
stdin.close
stdout.each_line { |line| puts line }
stdout.close
stderr.each_line { |line| puts line }
stderr.close
end
これで実際にジョブが実行されますが、見たい出力に関して気になることが 1 つあります。
最初の行を次のように変更すると、
mysqlimp = "mysql -v -u #{mysqllocal['user']} " #note the -v
そうなると、スクリプト全体が永久にハングしてしまいます。
これは、読み取りストリームと書き込みストリームが相互にブロックしているためだと思います。また、stdin が消費され続けるように stdout を定期的にフラッシュする必要があるためだと思います。言い換えれば、標準出力のバッファがいっぱいである限り、プロセスはフラッシュされるまで待機しますが、これは最初に一番下で行われるため、フラッシュされることは決して起こりません。
誰かが私の理論を検証してくれることを願っています?標準出力からすべてを出力し、標準入力にもすべてを書き込むコードを作成するにはどうすればよいでしょうか?
解決策
例:
require 'open3'
cmd = 'sh'
Open3.popen2e(cmd) do |stdin, stdout_stderr, wait_thread|
Thread.new do
stdout_stderr.each {|l| puts l }
end
stdin.puts 'ls'
stdin.close
wait_thread.value
end
コード、修正されました:
require 'open3'
mysqldump = # ...
mysqlimp = "mysql -u #{mysqllocal['user']} "
mysqlimp << "-h #{mysqllocal['host']} "
mysqlimp << "-p#{mysqllocal['pass']} "
mysqlimp << "#{mysqllocal['db']}"
Open3.popen2e(mysqlimp) do |stdin, stdout_stderr, wait_thread|
Thread.new do
stdout_stderr.each {|l| puts l }
end
stdin.puts "DROP DATABASE IF EXISTS #{mysqllocal['db']};"
stdin.puts "CREATE DATABASE #{mysqllocal['db']};"
stdin.puts "USE #{mysqllocal['db']};"
stdin.close
wait_thread.value
end