bash 从 Ruby 运行 shell 命令:在显示输出的同时捕获输出?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3682837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:37:27  来源:igfitidea点击:

Running a shell command from Ruby: capturing the output while displaying the output?

rubybash

提问by never_had_a_name

I have a problem.

我有个问题。

I want to run a ruby script from another ruby script and capture it's output information while letting it output to the screen too.

我想从另一个 ruby​​ 脚本运行一个 ruby​​ 脚本并捕获它的输出信息,同时让它也输出到屏幕上。

runner

赛跑者

#!/usr/bin/env ruby
print "Enter your password: "
password = gets.chomp
puts "Here is your password: #{password}"

The script file that I run:

我运行的脚本文件:

start.rb

启动文件

output = `runner`
puts output.match(/Here is your (password: .*)/).captures[0].to_s

As you see here there is a problem.

正如你在这里看到的,有一个问题。

In the first line of start.rb the screen is empty.

在 start.rb 的第一行,屏幕是空的。

I cannot see the "Enter your password: " in runner.

我在跑步者中看不到“输入您的密码:”。

Is there a way to display the output of the runner script before it's finished, and still let me capture it to a string so I can process the information, eg. using match like in this example?

有没有办法在运行脚本完成之前显示它的输出,并且仍然让我将它捕获到一个字符串中,以便我可以处理信息,例如。在这个例子中使用 match 吗?

回答by ma?ek

runner.rb

跑步者.rb

STDOUT.print "Enter your password: "
password = gets.chomp
puts "Here is your password: #{password}"

NoteSTDOUT.print

笔记STDOUT.print

start.rb

启动文件

require "stringio"

buffer = StringIO.new
$stdout = buffer

require "runner"

$stdout = STDOUT
buffer.rewind

puts buffer.read.match(/Here is your (password: .*)/).captures[0].to_s

output

输出

Enter your password: hello
password: hello


Read more...

阅读更多...

I recently did a write-up on this here: Output Buffering with Ruby

我最近在这里写了一篇文章:Output Buffering with Ruby

回答by tokland

Try this:

尝试这个:

rd, wr = IO::pipe
pid = Process.fork do  
  $stdout.reopen(wr)
  rd.close
  exec("command")
end
wr.close
rd.each do |line|  
  puts "line from command: #{line}"
end
Process.wait(pid)

Similar if you want to capture stderr. If you need to capture both it would a bit more difficult (Kernel.select?)

如果您想捕获stderr ,则类似。如果您需要同时捕获两者,那会有点困难(Kernel.select?)

Edit: Some explanation. This is an ancient Unix procedure: pipe + fork + calls to dup2 (reopen) depending on what you want. In a nutshell: you create a pipe as a means of communication between child and parent. After the fork, each peer close the pipe's endpoint it does not use, the child remaps (reopen) the channel you need to the write endpoint of the pipe and finally the parent reads on the read channel of the pipe.

编辑:一些解释。这是一个古老的 Unix 过程:管道 + fork + 调用 dup2(重新打开),具体取决于您想要什么。简而言之:您创建一个管道作为子级和父级之间的通信方式。在 fork 之后,每个对等方关闭它不使用的管道端点,子进程将您需要的通道重新映射(重新打开)到管道的写入端点,最后父进程在管道的读取通道上读取。

回答by usbdongle

For script independent output logging you might want to enable it from the terminal emulator (shell container). screen -L OR xterm -l This will capture all output produced by any shell or program running inside the emulator, including output generated by your ruby scripts.

对于独立于脚本的输出日志记录,您可能希望从终端模拟器(shell 容器)启用它。screen -L 或 xterm -l 这将捕获在模拟器内运行的任何 shell 或程序产生的所有输出,包括由您的 ruby​​ 脚本生成的输出。

回答by Dmitry Maksimov

io = IO.popen(<your command here>)
log = io.readlines
io.close

Now in log variable you have the output of executed command. Parse it, convert it, or do whatever you want.

现在在日志变量中你有执行命令的输出。解析它,转换它,或者做任何你想做的事。

回答by Sjoerd

You could use teeto write the contents to a file or a pipe, and read the file afterwards.

您可以使用tee将内容写入文件或管道,然后再读取文件。

回答by einarmagnus

Have a look at POpen4. It claims to be platform independent (but I do not think it works in jruby where you can use IO#popeninstead).

看看POpen4。它声称与平台无关(但我认为它不适用于您可以使用的 jruby IO#popen)。

回答by Paused until further notice.

Have your script do its prompt output to stderr.

让您的脚本将其提示输出到 stderr。

echo "Enter something" >&2
read answer
echo "output that will be captured"

This will be done for you if you use read -pto issue the prompt:

如果您read -p用来发出提示,这将为您完成:

read -p "Enter something" answer
echo "output that will be captured"