EDIT
Вы должны рассмотреть возможность интеграции с AnyTerm . Затем вы можете либо выставить AnyTerm напрямую, например, через Apache mod_proxy
или ваш контроллер Rails будет выступать в качестве обратного прокси-сервера (обрабатывает аутентификацию / проверку сеанса, затем воспроизводит controller.request
минус любые куки-файлы до 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