Ruby—Open3.popen3/如何打印输出 [英] Ruby—Open3.popen3 / how to print the output

查看:56
本文介绍了Ruby—Open3.popen3/如何打印输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小 ruby​​ 脚本,它以以下方式执行 mysql 导入:mysql -u -p<pass>-h <主机><db><file.sql,但使用 Open3.popen3 来做到这一点.这就是我到目前为止所拥有的:

I have a little ruby script which does a mysql import in the way: mysql -u <user> -p<pass> -h <host> <db> < file.sql, but utilizes Open3.popen3 to do so. That is what I have so far:

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

这实际上是在完成工作,但有一件事情让我感到困扰,即我希望看到的输出.

That is actually doing the Job, but there is one thing that bothers me, concerned to the output I would like to see.

如果我将第一行改为:

mysqlimp = "mysql -v -u #{mysqllocal['user']} " #note the -v

然后整个脚本永远挂起.

then the whole script hangs forever.

我猜,发生这种情况是因为读流和写流相互阻塞,而且我还猜想 stdout 需要定期刷新,以便 stdin 会去在被消耗.换句话说,只要 stdout 的缓冲区已满,进程就会等待直到它被刷新,但由于这是在最底部先完成的,所以永远不会发生.

I guess, that happens because the read- and write-stream block each other and I also guess that the stdout needs to be flushed regularly so that stdin will go on to be consumed. In other words, as long as the buffer of the stdout is full, the process will wait until its flushed, but since this is done at the very bottom first, that never happens.

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

I hope someone can verify my theory? How could I write code that does prints out everything from the stdout and writes everything to the stdin as well?

提前致谢!

推荐答案

  • 由于您只写入标准输出,您可以简单地使用 Open3#popen2estdoutstderr 合并到一个流中.
  • 要将换行符终止的字符串写入流,您可以像在简单的 hello world 程序中使用 $stdout 一样使用 puts.
  • 您必须使用 waith_thread.joinwait_thread.value 等待子进程终止.
  • 无论如何,如果您想立即查看结果,您必须启动一个单独的线程来从流中读取数据.
    • Since you are only writing to stdout, you can simply use Open3#popen2e which consolidates stdout and stderr into a single stream.
    • To write newline terminated strings to a stream, you can use puts as you would with $stdout in a simple hello world program.
    • You must use waith_thread.join or wait_thread.value to wait until the child process terminates.
    • In any case, you will have to start a separate thread for reading from the stream, if you want to see the results immediately.
    • 示例:

      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/如何打印输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆