0

I have some ruby code (a sidekiq job) which looks like this:

module WorkerJobs
  class MyJob < SidekiqWorker

    def perform country
      # Exec, ``, system, Spawn ... whatever?
      # ????
    end

  end
end

I would like to have the ruby code start a command like this (which takes several hours to complete):

"cd ~/my_dir/production && nohub Rscript --vanilla main.r --country #{country} > /home/deployer/my_dir/shared/log/log_#{country}.log 2>&1 &"

The goal is to get the script started and the sidekiq job to complete without waiting for anything (since the script takes hours to run), so sidekiq can move on and do other jobs. Sidekiq/ruby does not need to know any more details of the state of the job what so ever.

I tried using system() but that seems to not send the stdout/err to the specified log file for some reason? I tried reading about other ways of executing the script but I can't figure out which method is the right one to use in this case. Again, while the script runs the sidekiq process/thread that started it might stop/start/do-what-ever it should NOT influence the script

Niels Kristian
  • 8,661
  • 11
  • 59
  • 117
  • `exec` replaces your process with the command which is not what you want. `system` and `%x` (or backticks) wait for the command to finish. `spawn` however looks promising – it just returns the pid. – Stefan Nov 21 '17 at 09:53
  • Since you are using Sidekiq: wouldn't it make more sense to have the worker wait for the command to finish so you can handle failure (possibly restart), limit number of concurrent jobs etc? – Stefan Nov 21 '17 at 09:59
  • No, because the script is self-contained (handling errors by itself etc.). I just need to have it invoked by my webapp (a controller action enqueues a sidekiq job, which evokes the script ans some other stuff). – Niels Kristian Nov 21 '17 at 10:11
  • it seems that the command not quite correcly run, try it to run manually, use '&>' flow forward conbination instead of just '>' – Малъ Скрылевъ Nov 21 '17 at 12:59

1 Answers1

0

Okay so I ended up going with spawn:

module WorkerJobs
  class MyJob < SidekiqWorker

    def perform country
      logfile =  "/home/deployer/my_dir/shared/log/log_#{country}.log"
      pid = spawn("cd ~/my_dir/production && nohub Rscript --vanilla main.r --country #{country}", [:out, :err] => logfile)
      Process.detach(pid)
    end

  end
end

That worked as intended.

Update 1

However now this happens: How to debug R-script suddenly stopping at random point with no error? (related or unrelated I don't know?)

update 2

It actually seems to be related! When sidekiq restarts (get's a kill -15) then it also nukes the process. Strange... Investigating...

final update

It turns out, that since sidekiq was started by systemd, systemd was actually the one responsible for nuking any "child" processes (whether they were actually classical child processes or not). This is the default behaviour of systemd. An explanation can be found here: Can't detach child process when main process is started from systemd

Changing the killmode for system d to process fixed the problem.

Niels Kristian
  • 8,661
  • 11
  • 59
  • 117