Daemons do not get restarted? - ruby

I am trying to run the same script in multiple daemons.
myapp.rb looks like this:
loop do
sleep 5
1 / 0 # crash it
end
my myapp_controller.rb:
require 'rubygems'
require 'daemons'
options = {
:log_output => true,
:backtrace => true,
:monitor => true,
:multiple => true,
:log_dir => '/mnt/log/',
:hard_exit => true
}
Daemons.run(File.join(File.dirname(__FILE__), 'myapp.rb'), options)
When I run ruby myapp_controller.rb start several times in a row, it creates that many daemons, as I expect. But, after a while, due to an error in myapp.rb the daemons crash and the monitor restarts just one and not all. So I end up with a single running daemon.
Why? What am I doing wrong?

I was able to reproduce the behavior. It is not anything you are doing wrong; it is the way the daemons gem behaves.
Going through the code for the daemons gem, turns out the :multiple option doesn't work well with the :monitor option.
The :monitor option works only when the daemon is run in single mode.
I have created a bug report on the daemons project page referencing this question as the source.
More info about the reproduction of the issue:
Multiple daemon processes are created when :multiple => true. Each process has its own pid file in the format of <scriptname>.rb<number>.pid.
However, only one monitor process is created (with a single <scriptname>.rb_monitor.pid file.)
Here are the list of processes started when I start the daemon process 3 times:
$ ps -fe | grep my_server
501 1758 1 0 12:25PM ?? 0:00.63 my_server.rb
501 1759 1 0 12:25PM ?? 0:00.43 my_server.rb_monitor
501 1764 1 0 12:25PM ?? 0:00.54 my_server.rb
501 1834 1 0 12:51PM ?? 0:00.31 my_server.rb
The files in the pid/log folder:
$ ls /tmp/daemons-2013-01-25/
my_server.rb.log my_server.rb1.pid my_server.rb_monitor.pid
my_server.rb0.pid my_server.rb2.pid

Until the issue is resolved, you can change your code to something like this:
#myapp_controller.rb
require 'rubygems'
require 'daemons'
number = ARGV.fetch(1)
options = {
:app_name => "daemon-#{number}" # provide app_name
:log_output => true,
:backtrace => true,
:monitor => true,
:multiple => false, # disable multiple option
:log_dir => '/mnt/log/',
:hard_exit => true
}
Daemons.run(File.join(File.dirname(__FILE__), 'myapp.rb'), options)
And then start your daemons with these commands:
ruby myapp_controller.rb start 1
ruby myapp_controller.rb start 2
...
This slightly changes your startup code, but now you will have a monitor process for each of your daemon processes.

Related

Add logs in different directory using daemon in ruby

I am using daemon to wrap my script and has specified logs location into that :
Script looks like this :
#!/usr/local/bin/ruby
require 'rubygems'
require 'daemons'
Daemons.run_proc(
'script_test', # name of daemon
:log_output => true,
:output_logfilename => "script-test.log",
:logfilename => "script-test.log"
) do
exec 'ruby /opt/script-test/script-test.rb'
end
Problem is my logs are storing in same directory where my script is present. I have to add my logs to different directory such as /var/log/script-test and later have to rotate those logs weekly.
Provide me with a solution so that i can store the logs of script in /var/log directory.
Make sure you are using an absolute path instead of a relative path
For example:
:output_logfilename => "/var/log/script-test.log",
:logfilename => "/var/log/script-test.log"
In order to logrotate your logs, (assuming Linux) add the following to your logrotate config to rotate on a weekly basis:
/var/log/script-test.log {
weekly
missingok
compress
notifempty
copytruncate
}
It worked for me with this configuration as :
Daemons.run_proc(
'script-test', # name of daemon
:log_output => true,
:dir_mode => :normal,
:dir => "/var/log",
:output_logfilename => "script-test.log",
:logfilename => "script-test.log"
) do
exec 'ruby /opt/script-test/script-test.rb'
end

Ruby daemons soft stop

This simple daemon (written using ruby daemons gem) prints numbers from 0 up to 9 until I stop the daemon using the stop command line option:
require 'rubygems'
require 'daemons'
options = {
:multiple => false,
:ontop => false,
:backtrace => true,
:log_output => true,
:monitor => false
}
Daemons.run_proc('test.rb', options) do
loop do
10.times do |i|
puts "#{i}\n"
sleep(1)
end
end
end
I start the daemon with
ruby simple_daemon.rb start
and stop it with
ruby simple_daemon.rb stop
Is it possible to softly stop the daemon, letting it end its last loop before killing its process, so that I'm sure that it prints all the 10 numbers one last time?
You need to trap the TERM signal which is sent when you call stop and handle it yourself. Your code could be something like this :
Daemons.run_proc('test.rb', options) do
stopped = false
Signal.trap("TERM") do
stopped = true
end
while not stopped
10.times do |i|
puts "#{i}\n"
sleep(1)
end
end
end

Gem Daemons - How to run several different daemons

Basically I just want to run several daemons in my ruby script :
require 'daemons'
Daemons.run path_1, { :ARGV => ['start'], :app_name => 'app1', :multiple => true, ... }
Daemons.run path_2, { :ARGV => ['start'], :app_name => 'app2', :multiple => true, ... }
But the second Daemons.run is never called when ARGV[0] == 'start' (works perfectly with 'status'/'stop'). What is the right way to do it ?
from http://daemons.rubyforge.org
3- Control a bunch of daemons from another application
Layout: you have an application my_app.rb that wants to run a bunch of server tasks as daemon processes.
# this is my_app.rb
require 'rubygems' # if you use RubyGems
require 'daemons'
task1 = Daemons.call(:multiple => true) do
# first server task
loop {
conn = accept_conn()
serve(conn)
}
end
task2 = Daemons.call do
# second server task
loop {
something_different()
}
end
# the parent process continues to run
# we can even control our tasks, for example stop them
task1.stop
task2.stop
exit
does it fit?

Guard crashing Spork when using guard-spork

I've followd the "How I Test" screencast at RailsCasts, however I ran into a problem with spork
$ guard
Guard is now watching at '/Users/darth/projects/auth-before'
Starting Spork for Test::Unit & RSpec
Couldn't find a supported test framework that begins with 'testunit'
Supported test frameworks:
( ) Cucumber
(*) RSpec
Legend: ( ) - not detected in project (*) - detected
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
ERROR: Could not start Spork server for Test::Unit & RSpec. Make sure you can use it manually first.
# here I get growl notification "Test::Unit & RSpec NOT started
Guard::RSpec is running, with RSpec 2!
Running all specs
Running tests with args ["--color", "--format", "progress", "--format", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--require", "/Users/darth/.rvm/gems/ruby-1.9.2-p290/gems/guard-rspec-0.5.0/lib/guard/rspec/formatters/notification_rspec.rb", "spec"]...
.
Finished in 14.47 seconds
1 example, 0 failures
Done.
When I try to run spork in a separate terminal window, it doesn't help, as it gets killed instantly once I run guard
$ spork
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
Spork is ready and listening on 8989!
Killed: 9
If I just run spork and then try rspec . --drb, it works just fine. Here's link to gist with my Gemfile, Guardfile and spec_helper.rb
You should change:
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' },
:rspec_env => { 'RAILS_ENV' => 'test' },
:wait => 120
to:
guard 'spork', :rspec_env => { 'RAILS_ENV' => 'test' },
cucumber: false,
test_unit: false
This problem is actually caused by guard killing spork before it can even load, which is a problem on my slower MacBook pro.
The solution is to increase the wait time with :wait => 120 in the Guardfile, e.g.
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' },
:rspec_env => { 'RAILS_ENV' => 'test' }, :wait => 120
....

Ruby Daemons log rotation

When I'm setting logging parameters to the Daemons (1.1.0) gem, how would I achieve similar behavior to this line?
logger = Logger.new('foo.log', 10, 1024000)
Daemon options:
options = {
:ARGV => ['start'],
:dir_mode => :normal,
:dir => log_dir,
:multiple => false,
:ontop => false
:mode => :exec,
:backtrace => true,
:log_output => true
}
Unfortunately the Daemons gem does not use Logger. It redirects STDOUT and STDERR directly to a file.
You can see the details of how the redirection works here:
https://github.com/ghazel/daemons/blob/master/lib/daemons/daemonize.rb#L241-261
Because of this, you will have to use something like logrotate and restart the daemon if you want to do log file rotation.
If this is not acceptable, I would suggest using Logger directly like you provided in the question.

Resources