编辑
您应该考虑与AnyTerm集成。然后,您可以直接公开 AnyTerm,例如通过 Apache mod_proxy
,或者让您的 Rails 控制器充当反向代理(处理身份验证/会话验证,然后播放controller.request
减去任何 cookie 到localhost:<AnyTerm-daemon-port>
,并将 AnyTerm 回复的任何内容作为响应发送回。)
class ConsoleController < ApplicationController
# AnyTerm speaks via HTTP POST only
def update
# validate session
...
# forward request to AnyTerm
response = Net::HTTP.post_form(URI.parse('http://localhost:#{AnyTermPort}/', request.params))
headers['Content-Type'] = response['Content-Type']
render_text response.body, response.status
end
否则,您需要使用IO::Select或IO::read_noblock来了解何时可以读取数据(从网络或子进程),这样您就不会死锁。也看到这个。还要检查您的 Rails 是否在多线程环境中使用,或者您的 Ruby 版本不受此 IO::Select 错误的影响。
您可以从以下几方面着手:
status = POpen4::popen4("ping localhost") do |stdout, stderr, stdin, pid|
puts "PID #{pid}"
# our buffers
stdout_lines=""
stderr_lines=""
begin
loop do
# check whether stdout, stderr or both are
# ready to be read from without blocking
IO.select([stdout,stderr]).flatten.compact.each { |io|
# stdout, if ready, goes to stdout_lines
stdout_lines += io.readpartial(1024) if io.fileno == stdout.fileno
# stderr, if ready, goes to stdout_lines
stderr_lines += io.readpartial(1024) if io.fileno == stderr.fileno
}
break if stdout.closed? && stderr.closed?
# if we acumulated any complete lines (\n-terminated)
# in either stdout/err_lines, output them now
stdout_lines.sub!(/.*\n/m) { puts $& ; '' }
stderr_lines.sub!(/.*\n/m) { puts $& ; '' }
end
rescue EOFError
puts "Done"
end
end
要同时处理stdin
,请更改为:
IO.select([stdout,stderr],[stdin]).flatten.compact.each { |io|
# program ready to get stdin? do we have anything for it?
if io.fileno == stdin.fileno && <got data from client?>
<write a small chunk from client to stdin>
end
# stdout, if ready, goes to stdout_lines