Get live logs in front of the rake app

Here, in the rails 3.x application, I use net :: ssh and run some commands for the remote pc.I would like to display live logs for the browser.like user if two :: ssh commands work on the network to execute, i.e. . echo "Hello" , echo "Bye" is passed, then "Hello" should be displayed in the browser, immediately ending after its execution. Here is the code I use to connect ssh and execute commands in ruby ​​on rails application

 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 

Here on_data sends data every time the command is executed, I need this data to be immediately sent to the browser. Is there any way to do this. So that I can achieve live logs in the front end browser. Thanks!

+6
source share
1 answer

To “send data to the browser immediately”, you need to use one of three strategies:

  • Short survey
  • Streaming
  • Long survey

(in the following examples, I assume $logs is of type Queue

Short survey

A short survey is a classic way to receive pending information from a server. This means that once every X seconds the client asks the server “do you have new information?”, The server answers either “no”, and in this case the client returns for another X seconds, or the server answers “yes”, here some new information ... "which the client can then display before sleeping for another X seconds.

The main drawback of this strategy is that it is supported by all browsers and all ruby ​​versions (simple AJAX calls).

The disadvantage of this strategy is that before you receive new data, you will have a delay of up to X seconds. If X is too short, you will suffer from a lot of network overhead (all requests with empty answers).

Implementation Example:

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

Streaming

A streaming strategy is when your client opens a request to the server, the server starts sending a response to the client, but when the available information ends, it does not close the connection, but leaves it open. Then it continues to receive information about the stream in the open socket as information arrives.

Rails 4.0 has an ActionController :: Live that implements this strategy. For Rails 3.2, you can try looking at this answer: fooobar.com/questions/120897 / ...

Implementation Example:

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

The main difference between this solution and the other two is that the client implementation is not so direct - the client cannot just wait for a response to return and then display it (for example, using jQuery by default). To implement the example, many places point to Ajax Patterns , which are currently unavailable: - (.

Another option I've seen is to use the portal plugin *:

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

* I have no experience using this plugin, so this should be considered as a research area, and not as a working example ...

Long survey

Long polling means your AJAX client is requesting a server for the next line of the log. If the server has one (or more) to provide, it returns it to the client, the client displays the rows (rows) and requests again. If the server does not have a string to provide, it does not return an empty response, but rather hangs with the request and waits until the line is available. As soon as a new line appears, it is returned to the client. The client displays a string and then immediately requests the server.

When choosing this strategy, you must make sure that there is not a single timeout on the web server or client, or at other points in the middle (load balancers, etc.)

Implementation Example:

 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 
+3
source

All Articles