Spawn a background process in Ruby
As long as you are working on a POSIX OS you can use fork
and exec
.
fork
= Create a subprocess
exec
= Replace current process with another process
You then need to inform that your main-process is not interested in the created subprocesses via Process.detach
.
job1 = fork do
exec "/path/to/daemon01"
end
Process.detach(job1)
...
Spawn a background process in Ruby on Windows?
The win32-process library, part of the Win32Utils suite, is probably what you're after.
http://win32utils.rubyforge.org/
The win32-process library adds the Process.create and Process.fork methods for MS Windows. In add addition, it provides different implementations of the wait, wait2, waitpid, and waitpid2 methods.
The Process.create method allows you to create native MS Windows processes using a variety of different configuration options.The Process.fork implementation should be considered experimental and not used in production code.
Installation: gem install win32-process
How do I start a background process in Ruby?
If you use run_proc
, the code that you want daemonized should go in the block. Starting another process with system
doesn't make sense (It will fork
the process (giving you yet another pid), and then exec
your jobs.rb script. Either move the code from jobs.rb
into the run_proc
block, or use Daemons.run
Create a background task that is always running
ActiveJob and Sidekiq are not what you need. Those are to perform finite jobs in the background. You need some kind of a daemon that starts independently of Rails app.
Take a look at this https://github.com/thuehlinger/daemons
how to controller (start/kill) a background process (server app) in ruby
The standard way is to use the system functions fork (to duplicate the current process), exec (to replace the current process by an executable file), and kill (to send a signal to a process to terminate it).
For example :
pid = fork do
# this code is run in the child process
# you can do anything here, like changing current directory or reopening STDOUT
exec "/path/to/executable"
end
# this code is run in the parent process
# do your stuffs
# kill it (other signals than TERM may be used, depending on the program you want
# to kill. The signal KILL will always work but the process won't be allowed
# to cleanup anything)
Process.kill "TERM", pid
# you have to wait for its termination, otherwise it will become a zombie process
# (or you can use Process.detach)
Process.wait pid
This should work on any Unix like system. Windows creates process in a different way.
What is the best way to run a background process in Rails 5?
Rails uses ActiveJob, which allow you to queue up an expensive tasks and run them in the background. They are quite simple to use.
Fist, you can use rails generator to create one:
rails generate job slow_algorithm
...which will create a job under app/jobs/slow_algorithm_job.rb
. There, you can implement your algorithm logic.
Queue up the job is just as easy, simply do it in your controller:
SlowAlgorithmJob.perform_later
Last thing you need to cover is setting up queuing backend that will actually run the jobs. Rails supports couple of them. Probably the simplest one to set up is delayed_job, but if you're looking for something more scalable, I'd recommend looking into Sidekiq.
EDIT: How to notify user that the job is done?
In order to do this, you clearly have to somehow track the progress of the task. One possible direction is to create a record, let's call it a Task
, which represents one invocation of your algorithm.
When user triggers the action that should queue up the job, Task record is created with status pending
, then before_perform
and after_perform
job hooks can be used to move the Task
status to running
and then to completed
.
after_perform
hook can be used to notify the customer. How the app is going to do it, is up to you. For example, Dropbox uses similar system when downloading large amount of files. They queue up the job, the zips ups the files and then send the email with download link once the job is finished.
Another approach would be using in-app notification system.
Lastly, to have the notification pop-up without requiring user to refresh the page, you'd have to use ActiveCable
and push the notification back to user, again, using after_perform
hook.
How can I trigger a shell script and run in background (async) in Ruby?
@TanzeebKhalili's answer works, but you might consider Kernel.spawn(), which doesn't wait for the process to return:
pid = spawn("./test.sh")
Process.detach(pid)
Note that, according to the documentation, whether you use spawn()
or manually fork()
and system()
, you should grab the PID and either Process.detach()
or Process.wait()
before exiting.
Regarding redirecting standard error and output, that's easy with spawn()
:
pid = spawn("./test.sh", :out => "test.out", :err => "test.err")
Process.detach(pid)
Related Topics
How to Generate a List of N Unique Random Numbers in Ruby
Sort Hash by Key, Return Hash in Ruby
What's the Best Way to Use Soap With Ruby
Accepts_Nested_Attributes_For With Belongs_To Polymorphic
Saving Enum from Select in Rails 4.1
Using Rails Serialize to Save Hash to Database
Understanding Private Methods in Ruby
In Ruby How to Overload the Initialize Constructor
Accessing Elements of Nested Hashes in Ruby
Rails 4: Assets Not Loading in Production
Natural Language Processing in Ruby
When Do Ruby Instance Variables Get Set