1

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?

Godzilla74
  • 2,358
  • 1
  • 31
  • 67
  • it's unclear what `ov.task_start(taskid)` returns. [Process.spawn](https://ruby-doc.org/core-2.2.0/Process.html#method-c-spawn) takes a shell command (string) as an argument. There's also Process.fork which accepts an arbitrary block (see [how-do-you-spawn-a-child-process-in-ruby](https://stackoverflow.com/questions/307070/how-do-you-spawn-a-child-process-in-ruby)) – max pleaner May 23 '17 at 01:29
  • @maxpleaner I updated the question with the contents of `task_start`. I haven't really used any process control ruby functions until now. Does `fork` allow me to track the PID as I need to? – Godzilla74 May 23 '17 at 01:32
  • It does. I just checked, and the pid returned from Process.fork can be passed to `kill -9` to stop it. So maybe using `pid = Process.fork { ov.task_start(taskid) }` would work for you. – max pleaner May 23 '17 at 01:44
  • Alright, refactoring some code and I'll let you know! – Godzilla74 May 23 '17 at 01:46
  • @maxpleaner worked like a charm! – Godzilla74 May 23 '17 at 02:29

1 Answers1

0

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.
max pleaner
  • 26,189
  • 9
  • 66
  • 118