6

我想使用 spawn(用于多个并发子进程)在 Ruby 中执行一个外部进程,并将 stdout 或 stderr 收集到一个字符串中,这与使用 Python 的子进程 Popen.communicate() 可以完成的操作类似。

我尝试将 :out/:err 重定向到一个新的 StringIO 对象,但这会生成一个 ArgumentError,并且临时重新定义 $stdxxx 会混淆子进程的输出。

4

4 回答 4

7

如果你不喜欢 popen,这是我的方式:

r, w = IO.pipe
pid = Process.spawn(command, :out => w, :err => [:child, :out]) 
w.close

...

pid, status = Process.wait2
output = r.read
r.close

无论如何,您不能直接重定向到 String 对象。您最多可以将它指向一个 IO 对象,然后从中读取,就像上面的代码一样。

于 2015-03-17T10:11:53.917 回答
3

为什么需要spawn?除非您在 Windows 上,否则您可以使用popen*,例如popen4

require "open4"

pid, p_i, p_o, p_e = Open4.popen4("ls")
p_i.close
o, e = [p_o, p_e].map { |p| begin p.read ensure p.close end }
s = Process::waitpid2(pid).last
于 2012-05-02T13:33:35.110 回答
1

从 Ruby 文档看来你不能,但你可以这样做:

spawn("ls", 0 => ["/tmp/ruby_stdout_temp", "w"])
stdoutStr=File.read("/tmp/ruby_stdout_temp")

您也可以对标准错误执行相同的操作。或者,如果您不想这样做并且不介意popen

io=IO.popen("ls")
stdout=io.read
于 2012-05-02T13:11:57.870 回答
1

最简单直接的方法似乎

require 'open3'

out, err, ps = Open3.capture3("ls")

puts "Process failed with status #{ps.exitstatus}" unless ps.success?

在这里,我们将输出作为字符串。

于 2015-07-21T13:26:46.067 回答