Godzilla74 Godzilla74 - 1 year ago 97
Ruby Question

Ruby spawn an object method

I'm trying to figure out a way to track the status of a process that I've created. In my script I start out by creating my object:

ov = OpenVASOMP::OpenVASOMP.new({"host" => "localhost", "port" => "9390", "user" => "admin", "password" => "#{ENV["OV"]}"})

Which creates an

ov
object and exposes a bunch of other methods. In particular:
ov.task_start
.

I need to be able to track the process and perform other actions while it's running, such as sending a status update to a remote server.

My initial thought was to wrap this in a
Process.spawn
and track the PID, but that's throwing an error:

TypeError: no implicit conversion of REXML::Element into String


and the stack trace points to this line:
pid = Process.spawn(ov.task_start(taskid))


So, I guess you can't pass objects and their methods into
spawn
?

Here's my whole block of code in case there is something else that I'm missing:

ov = OpenVASOMP::OpenVASOMP.new({"host" => "localhost", "port" => "9390", "user" => "admin", "password" => "#{ENV["OV"]}"})
taskid = ov.task_create({"name" => timestamp, "target" => target, "config" => config})
running = true
pid = Process.spawn(ov.task_start(taskid))
Signal.trap("HUP") { log("#{results_dir}/events.log", "[!] Stop triggered by user!"); exit }
until running == false
begin
running = Process.getpgid(pid)
log("#{results_dir}/events.log", "Scan PID: #{pid}")
stat = ov.task_get_byid(taskid)
update_ov_status(stat['progress'])
log("#{results_dir}/events.log", "[+] Sending progress to server: #{stat['progress']}%")

scan_status = get_scan_status

if scan_status == "Stopped"
ov.task_stop(taskid)
ov.task_delete(taskid)
ov.target_delete(target)
Process.kill("HUP", pid)
Process.wait
update_task_id("")
update_ov_status(0)
update_scan_status("Idle")
end

sleep 60

rescue Errno::ESRCH
running = false
puts "PID: #{pid} done!"
log("#{results_dir}/events.log", "[!] Scan complete")
end
end


And
task_start
looks like:

def task_start (task_id)
xmlreq=xml_attr("start_task",{"task_id" => task_id}).to_s()
begin
xr=omp_request_xml(xmlreq)
rescue
raise OMPResponseError
end
return xr
end


Am I going about this all wrong?

Answer Source

Just repeating what I said in the comment in an answer, for closure.

since task_start is not a shell script string, but rather a block of code that should be executed asynchronously, use Process.fork { ov.task_start taskid } instead of Process.spawn.

The Process.fork call returns a PID which can be used to stop the process, for example:

# in one terminal
ruby -e "puts Process.fork { loop { puts("tick"); sleep 1 } }"
# it then prints a PID like 20626
# then in another terminal:
kill -9 20626
# the "tick" will stop getting printed every second.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download