在rails应用程序的前端获取实时日志

在rails 3.x应用程序中,我使用net :: ssh并运行一些命令到远程pc。我想将实时日志显示给用户的browser.like,如果两个命令在net :: ssh中运行执行即echo "Hello"echo "Bye"传递然后“Hello”应该在浏览器中显示,并在执行后立即完成。这是我用于ssh连接的代码,并在ruby on rails应用程序中运行命令

 Net::SSH.start( @servers['local'] , @machine_name, :password => @machine_pwd, :timeout => 30) do |ssh| ssh.open_channel do |channel| channel.request_pty channel.exec("echo 'ssh started'") channel.exec("ruby -v") channel.exec("rails -v") channel.exec("echo 'ssh Finished'") channel.on_close do |ch| puts "****shell terminated****" end channel.on_eof do |ch| puts "****remote end is done sending data****" end channel.on_extended_data do |ch, type, data| puts "****got stderr****: #{data.inspect}" end channel.on_data do |channel, data| puts "****ondata****: #{data} \n" puts "****channel****: #{channel} \n" $logs << data # this data to be sent immediately to browser in each go end ssh.loop end end 

这里on_data在每个命令执行中发送数据,我需要立即将这些数据发送到浏览器。有什么办法可以做到这一点。所以我可以在前端浏览器中实现实时日志。谢谢!

要实现“立即向浏览器发送数据”,您需要使用以下三种策略之一:

  • 短轮询
  • 长期民意调查

(在以下示例中,我假设$logs的类型为Queue

短轮询

短轮询是从服务器获取待处理信息的经典方法。 这意味着客户端每隔X秒询问服务器“你有新信息吗?”,服务器回答“否”,在这种情况下客户端再回到睡眠状态X秒,或服务器回答“是”,这是一些新的信息……’,客户端可以在睡眠前再播放X秒。

这个策略的主要优点是它受到所有浏览器和所有ruby版本(简单的AJAX调用)的支持。

这种策略的缺点是,在看到新数据之前,您将延迟最多X秒。 如果X太短 – 您将遭受大量网络开销(所有请求都有空响应)。

示例实现:

 def get_logs available_logs = [] while(line = $logs.pop(true) rescue nil) available_logs << line body available_logs.join($/) end 

流式策略是当客户端向服务器打开请求时,服务器开始向客户端发送响应,但是当可用信息结束时,它不会关闭连接,而是将其保持打开状态。 然后,当信息到来时,它继续在打开的套接字上传输信息。

在Rails 4.0中,有一个ActionController :: Live实现了这个策略。 对于Rails 3.2,您可以尝试查看以下答案: https : //stackoverflow.com/a/4320399/1120015

示例实现:

 def get_logs class LogConsumer def each while $channel.active? yield $logs.pop + $/ end end end self.response_body = LogConsumer.new end 

此解决方案与其他两个解决方案之间的主要区别在于客户端实现不是那么直接 - 客户端不能只等待响应返回然后呈现它(就像默认的jQuery用法一样)。 对于示例实现,很多地方都指向Ajax模式 ,目前显然不可用:-(。

我见过的另一个选择是使用门户插件*:

 portal.open("/get_logs", { inbound: function(data) { render_log_lines(data); } }); 

*我没有使用此插件的经验,所以这应该作为研究的方向,而不是作为一个工作的例子...

长轮询

长轮询意味着您的AJAX客户端请求服务器下一个日志行。 如果服务器有一个(或多个)要提供,它将它返回给客户端,客户端呈现行,并再次请求。 如果服务器没有要提供的行,则它不会返回空响​​应,而是挂起到请求,并等待直到一行可用。 只要新行可用,它就会返回给客户端。 客户端呈现该行,然后立即再次请求服务器。

选择此策略时,必须确保Web服务器或客户端中没有设置timeout ,也不确定中间的任何其他点(负载平衡器等)

示例实现:

 def get_logs available_logs = [] while(line = $logs.pop(true) rescue nil) available_logs << line if available_logs.empty? available_logs << $logs.pop end body available_logs.join($/) end