Celluloid 的非阻塞子进程
Non blocking subprocess with Celluloid
在不阻塞 actor 的情况下生成子进程的最佳方法是什么?
我的目标是 运行 多个命令,当它们完成时,获取输出和退出代码。
我试过了,但很明显,popen 调用被阻塞了:
#!/usr/bin/env ruby
require 'celluloid/current'
require 'celluloid/io'
class MyProcessLauncher
include Celluloid::IO
def run
every(1) { puts "tick" }
every(5) {
puts "Starting subprocess"
::IO.popen("sleep 10 && echo 'subprocess done'", :err=>[:child, :out]) { |io|
puts io.read
}
puts $?.exitstatus
}
end
end
MyProcessLauncher.new.run
sleep
输出为:
tick
tick
tick
tick
Starting subprocess
subprocess done
0
tick
Starting subprocess
但我希望每个 'Starting subprocess' 之间有五个 'tick'...
谢谢!
如果您想要 return 值,您需要 defer
或使用 future
。
defer
(如果不需要 return 就很简单)
在您的 every(5)
块中,要使用 defer
,请使用 defer {}
包装您的 popen
调用(包括退出状态显示调用)
future
(有点复杂)
有多种方法可以实现这种方法。我的建议是将 every(5)
的内容移动到它自己的方法中,并在启动 MyProcessLauncher
时初始化一个数组 @futures
或类似的...然后在 every(5)
中使用它通话:
@futures = future.new_method
此外,添加一个新循环来处理您的期货。在 every(5)
添加一个新的处理程序(另一个 every
循环,或者对递归的处理器方法的 async
调用)来处理您的值,基本上是这样做的:
value = @futures.pop.value if @futures.any?
如果您遇到问题并且找不到如何处理期货的示例,我会问一个关于期货的后续问题。否则,您有两种方法可以在不阻塞的情况下处理 popen
调用。
在不阻塞 actor 的情况下生成子进程的最佳方法是什么?
我的目标是 运行 多个命令,当它们完成时,获取输出和退出代码。 我试过了,但很明显,popen 调用被阻塞了:
#!/usr/bin/env ruby
require 'celluloid/current'
require 'celluloid/io'
class MyProcessLauncher
include Celluloid::IO
def run
every(1) { puts "tick" }
every(5) {
puts "Starting subprocess"
::IO.popen("sleep 10 && echo 'subprocess done'", :err=>[:child, :out]) { |io|
puts io.read
}
puts $?.exitstatus
}
end
end
MyProcessLauncher.new.run
sleep
输出为:
tick
tick
tick
tick
Starting subprocess
subprocess done
0
tick
Starting subprocess
但我希望每个 'Starting subprocess' 之间有五个 'tick'...
谢谢!
如果您想要 return 值,您需要 defer
或使用 future
。
defer
(如果不需要 return 就很简单)
在您的 every(5)
块中,要使用 defer
,请使用 defer {}
popen
调用(包括退出状态显示调用)
future
(有点复杂)
有多种方法可以实现这种方法。我的建议是将 every(5)
的内容移动到它自己的方法中,并在启动 MyProcessLauncher
时初始化一个数组 @futures
或类似的...然后在 every(5)
中使用它通话:
@futures = future.new_method
此外,添加一个新循环来处理您的期货。在 every(5)
添加一个新的处理程序(另一个 every
循环,或者对递归的处理器方法的 async
调用)来处理您的值,基本上是这样做的:
value = @futures.pop.value if @futures.any?
如果您遇到问题并且找不到如何处理期货的示例,我会问一个关于期货的后续问题。否则,您有两种方法可以在不阻塞的情况下处理 popen
调用。