Spawn process thats loops and get stdout continuosly in ruby - ruby

i need to spwan a program in a ruby script.
This program periodically print a JSON and in the main script i need to intercept this and made calculation.
Thanks
Something like this:
MAIN:
Spawn a process
//This generates stdout periodically
//End call
Intercept its stdout
//REST of the code
How to?
I need to use eventmachine? Somewhat?
I clarify with this code
timer = EventMachine.add_periodic_timer POLLING_INTERVAL do
if memcached_is_running
ld 'reading from device'
begin
IO.popen("HostlinkPollerLight -p #{SERIAL_PORT} -v #{SERIAL_BAUDRATE} -r #{MODEL_CONFIG} 2> /dev/null") do |payload|
$_data = JSON.parse payload.readlines[0]
end
if $data['success']
memcache.set( MEMCACHE_DATA_KEY, _to_json( $data[ 'result' ], _mapping ))
timer.interval = POLLING_INTERVAL
else
log_this " read fault: error_code #{$data['fault']}"
timer.interval = FAULT_INTERVAL
end
rescue Errno::ENOENT
log_this 'Unable to read output'
rescue JSON::ParserError
log_this 'Malformed data'
end
else
timer.interval = FAULT_INTERVAL
system("on_red_led.sh 2")
end
log_this "elapsed time: #{Time.now.to_f - delta}"
ld "## end read: #{counter}"
counter += 1
end
I need to spwan only one time the program opened with popen and get the stdout every time its print stdout.

The way I do this is, that I create a class, which creates a new Thread with infinite loop, which alters object's instance variable. Then I can access those variables via its getters. Example:
class Stopwatch
def initialize
#seconds = 0
end
def start
#thread = Thread.new do
loop {
sleep(1)
#seconds += 1
}
end
end
def seconds
#seconds
end
def stop
#thread.kill
end
def reset
#seconds = 0
end
end
stoper = Stopwatch.new
stoper.start
sleep(5)
stoper.seconds #=> 5

Related

Kill linux command in ruby if timed-out

I need a solution how I can kill a system call in ruby and proceed, when this call takes too much time. If timed-out I want to set a mock. Timeout method in ruby doesn't help because it raises an error instead of moving to the end of the code.
Timeout::timeout(5) {
a = `sleep 30; echo 1`
}
puts a
Not sure if this illustrates it but for example 2 ruby files:
#slow_proceess.rb
puts 'starting.... waiting...'
10.times do
puts "slow process runing..."
sleep 1
end
puts 'done exiting'
#fast.rb
pid = Process.spawn('ruby slow_process.rb')
# after x seconds we can kill the process with
`kill -9 #{pid}`
Or in your example use instance variable to access it outside of the block and also rescue error (thanks #tadman):
begin
Timeout::timeout(5) {
#pid = Process.spawn('sleep 30; echo 1')
}
rescue Timeout::Error
puts "#{#pid} process has timed out"
end
# do stuff

Monitoring thread variables in ruby

I'm building a task runner where each task is built from a number of commands:
def run
begin
#Validating task params
set_progress "Validating params", "Validating params: #{#params}"
validate_params
#task_info["steps"].each do |step|
#log.info "Running command: #{step["description"]}"
set_progress step["description"]
command = Command.factory #params, step, #signature, #log
timeout = General.in_seconds step["timeout"]
command_res = Timeout.timeout(timeout) do
command.execute
end
end
set_progress "Completed"
rescue Exception => exception
#log.error exception.message + "\nBACK TRACE:\n" + exception.backtrace.join("\n")
set_progress #progress, "Failed, check logs. exception: #{exception.message}"
end
end
Now the command is ran by "command.execute", and there is a field inside the command class which is called "current_status" which i would like to monitor each X seconds and check the command status in order to update the user about the command status, how can i do it ? i probably need to run the command in a separate thread and then monitor it, but how can i monitor it ?
a quick and dirty methodology which might contain syntax errors :P
class JobManager
def initialize
#threads =[]
end
def registered_jobs
#registered_jobs ||= [Job1.new, Job2.new]
end
def start_jobs
registered_jobs.each {|j| #threads << Thread.new { j.run } }
end
def statuses?
registered_jobs.collect {|j| j.status? }
end
end
Usage:
manager = JobManager.new
manager.start_jobs
# elsewhere
manager.statuses? # returns [Job1.status?, Job2.status?]
This is the sort of idiom I'd use in my code. It's important to be aware that the status variables are subject to race conditions if they are not properly guarded against concurrent modification and access.

DB call terminates the program

I have a program written in Ruby with Sql Server 2008 on the back end. Right now I am confronting a problem which I am going to discuss under the following.
Consider I have functionA() and functionB(). fuctionA() and functionB() are being called in a loop. Of course it DB, connections are open and closed after each call inside these function.
I have a Rufus Scheduler scheduled after 1m which calls fuctionA() in its own thread by default. When functionA() in Rufus triggers the program terminates keeping in mind that functionA() and functionB() are being run constantly in a loop. When I comment out functionA() in Rufus the program executes smoothly. What could be the reason? Please guide.
class TestRufus
def initialize
#dps = nil
#mu = Mutex.new
end
def get_data()
victim_device = VictimDevice.new()
app_config = YAML.load_file("#{File.dirname(FILE)}/../../config/sa.gw.c.victim.yml")
scheduler = Rufus::Scheduler.new
scheduler.every "10s" do
handle_rufus
end
loop do
begin
#mu.synchronize {
#dps = victim_device.get_device_proximitysett(8)
}
puts "DeviceID : #{#dps.device_id} AlertDistance: #{#dps.victim_prox_alert_dist} VoilationDistance : #{#dps.victim_prox_viol_dist}"
rescue => e
time_of_error = Time.now.gmtime.to_s()
puts("Error occurred: #{time_of_error} - #{e.message}")
end
end
end #end of function
def handle_rufus()
puts 'In Rufus.'
begin
#mu.synchronize {
#dps = victim_device.get_device_proximitysett(8)
}
rescue => e
puts 'Error #{e.message}'
end
puts "Rufus got! #{#dps.device_id} "
puts 'Out Rufus.'
end
end # end of class
obj= TestRufus.new
obj.get_data()
Thank you in advance.

setInterval() equivalent for ruby

In JavaScript you can do:
setInterval(func,delay);
I can't seem to find anything on google for what I'm actually looking for.
Is there a ruby equivalent for this? Thanks in advance.
You can do something like it:
Thread.new do
loop do
sleep delay
# your code here
end
end
Or you can define a function:
# #return [Thread] return loop thread reference
def set_interval(delay)
Thread.new do
loop do
sleep delay
yield # call passed block
end
end
end
When you want to stop the set_interval, you just call any of these methods: exit, stop or kill.
You can test it into console (irb or pry):
t1 = Time.now; t = set_interval(2.5) {puts Time.now - t1}
> 2.500325
> 5.000641
> 7.500924
...
t.kill # stop the set_interval function
I use rufus-scheduler:
scheduler = Rufus::Scheduler.new
scheduler.every '5m' do
# Some Fancy Code Logic That Runs Every 5 Minutes
end

If nothing sent to STDOUT in last x minutes, how to raise an error

I wonder if this is possible, because if it is, it would help me implement what I need for a program I am making:
Is there a way to attach some kind of listener to STDOUT from within a Ruby program, so that if nothing is written (via puts) to STDOUT for a certain time interval, an error is raised?
Writing to STDOUT should otherwise work as expected.
Perhaps something like this:
def new_puts(what)
#time_th.kill if(#time_th)
puts what
#time_th = Thread.new() {
sleep(2)
raise "here"
}
#time_th.abort_on_exception = true
end
new_puts("test")
new_puts("test2")
sleep(10)
new_puts("test3") #too late
or with callback methods:
def callback
puts "Timeout!"
end
def new_puts(what)
#time_th.kill if(#time_th)
puts what
#time_th = Thread.new() {
sleep(2)
self.method(:callback).call
}
end
new_puts("test")
new_puts("test2")
sleep(10)
new_puts("test3") #too late

Resources