我有一个小的ruby脚本,它以一种方式导入mysql
:mysql -u <user> -p<pass> -h <host> <db> < file.sql
,但是利用Open3.popen3
来做到这一点。到目前为止,这就是我所拥有的:
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
那实际上是在做这份工作,但是有一件事困扰着我,涉及到我希望看到的输出。
如果我将第一行更改为:
mysqlimp = "mysql -v -u #{mysqllocal['user']} " #note the -v
然后整个脚本将永远挂起。
我猜想是因为读写流相互阻塞,而且还需要定期刷新
stdout
才能继续使用stdin
。换句话说,只要stdout
的缓冲区已满,进程将一直等待直到刷新为止,但是由于这是从最底部开始进行的,因此永远不会发生。我希望有人可以验证我的理论吗?如何编写能打印出
stdout
中所有内容并将所有内容都写入stdin
中的代码?谢谢你在前面!
最佳答案
Open3#popen2e
将stdout
和stderr
合并为一个流。 puts
一样使用$stdout
。 waith_thread.join
或wait_thread.value
来等待子进程终止。 例子:
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
关于Ruby — Open3.popen3/如何打印输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25325624/