我有一个小的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中的代码?

谢谢你在前面!

最佳答案

  • 因为您只写到stdout,所以您可以简单地使用Open3#popen2estdoutstderr合并为一个流。
  • 要将换行符终止的字符串写入流,可以像在简单的hello world程序中使用puts一样使用$stdout
  • 您必须使用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
    

    您的代码已修复:
    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/

    10-16 14:32