Ruby-Open3.popen3 /如何打印输出

phi*_*ipp 6 ruby popen3

我有一个小的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
Run Code Online (Sandbox Code Playgroud)

这实际上是在做这项工作,但是有一件事困扰着我,关心我希望看到的输出.

如果我将第一行更改为:

mysqlimp = "mysql -v -u #{mysqllocal['user']} " #note the -v
Run Code Online (Sandbox Code Playgroud)

然后整个脚本永远挂起.

我想,这是因为读取和写入流相互阻塞,我还猜测stdout需要定期刷新,以便stdin继续使用.换句话说,只要缓冲区stdout已满,进程将等待直到刷新,但由于这是在最底部完成的,所以永远不会发生.

我希望有人可以验证我的理论吗?我怎么能编写能够打印出所有内容的代码stdout并将所有内容写入其中stdin

提前谢谢!

Pat*_*ity 14

  • 由于您只写到标准输出,你可以简单地使用Open3#popen2e其整合stdoutstderr到一个单一的数据流.
  • 要将换行符终止的字符串写入流,您可以puts$stdout在简单的hello world程序中一样使用它.
  • 您必须使用waith_thread.joinwait_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
Run Code Online (Sandbox Code Playgroud)

你的代码,修复:

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
Run Code Online (Sandbox Code Playgroud)