Is it possible to run a ruby application as a Windows Service? I see that there is a related question which discusses running a Java Application as a Windows Service, how can you do this with a Ruby application?
5 Answers
Check out the following library: Win32Utils. You can create a simple service that you can start/stop/restart at your leisure. I'm currently using it to manage a Mongrel instance for a Windows hosted Rails app and it works flawlessly.

- 232,980
- 40
- 330
- 338

- 9,946
- 13
- 50
- 71
-
1In regards to my comment, I stand corrected, I used a special Mongrel service gem and installed it like so: mongrel_rails service::install -N c:\web\AppName -p 4002 -e production But you should be able to accomplish what you need to with the above links. – mwilliams Oct 02 '08 at 17:25
-
For your second link 'Running asa a Windows Service' the site Insitiki is reporting the following 'This web is password-protected. Please enter the password.'. Do you have access to share or another way we can view this content? – Evolve Dec 14 '12 at 00:51
When trying the Win32Utils one really need to studie the doc and look over the net before finding some simple working example. This seems to work today 2008-10-02:
gem install win32-service
Update 2012-11-20: According to https://stackoverflow.com/users/1374569/paul the register_bar.rb should now be
Service.create( :service_name => 'some_service',
:host => nil,
:service_type => Service::WIN32_OWN_PROCESS,
:description => 'A custom service I wrote just for fun',
:start_type => Service::AUTO_START,
:error_control => Service::ERROR_NORMAL,
:binary_path_name => 'c:\usr\ruby\bin\rubyw.exe -C c:\tmp\ bar.rb',
:load_order_group => 'Network',
:dependencies => ['W32Time','Schedule'],
:display_name => 'This is some service' )
bar.rb
create the application/daemon
LOG_FILE = 'C:\\test.log'
begin
require "rubygems"
require 'win32/daemon'
include Win32
class DemoDaemon < Daemon
def service_main
while running?
sleep 10
File.open("c:\\test.log", "a"){ |f| f.puts "Service is running #{Time.now}" }
end
end
def service_stop
File.open("c:\\test.log", "a"){ |f| f.puts "***Service stopped #{Time.now}" }
exit!
end
end
DemoDaemon.mainloop
rescue Exception => err
File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} err=#{err} " }
raise
end
bar.rb is the service but we must create and register first! this can be done with sc create some_service
but if we are going to use ruby and win32utils we should do a
register_bar.rb
require "rubygems"
require "win32/service"
include Win32
# Create a new service
Service.create('some_service', nil,
:service_type => Service::WIN32_OWN_PROCESS,
:description => 'A custom service I wrote just for fun',
:start_type => Service::AUTO_START,
:error_control => Service::ERROR_NORMAL,
:binary_path_name => 'c:\usr\ruby\bin\rubyw.exe -C c:\tmp\ bar.rb',
:load_order_group => 'Network',
:dependencies => ['W32Time','Schedule'],
:display_name => 'This is some service'
)
Note, there is a space between c:\tmp\ bar.rb in 'c:\usr\ruby\bin\rubyw.exe -C c:\tmp\ bar.rb'
Run ruby register_bar.rb
and now one can start the service either from the windows service control panel or
sc start some_service
and watch c:test.log be filled with Service is running Thu Oct 02 22:06:47 +0200 2008
For the simple of have something to work with it is easier to remove the service register and create a new one instead of modifying a existing one
unregister_bar.rb
require "rubygems"
require "win32/service"
include Win32
Service.delete("some_service")
Credits to the people http://rubypane.blogspot.com/2008/05/windows-service-using-win32-service-and_29.html
-
1This doesn't work as written - I think it's based on an old version of win32/daemon. Try the example files here instead: http://rubyforge.org/frs/download.php/30036/win32-service-0.6.1.zip – Dave Nolan Mar 18 '09 at 11:02
-
This, as said, worked at the time recorded in the example. The win32 seems to change freq and I don't really feel the need to update this example every time. – Jonke Mar 19 '09 at 15:54
-
1No problem with the donwvote but i think I would have prefered an aswer with your link, or really good, an update strip down example here, based on that link. – Jonke Mar 23 '09 at 07:43
-
1This is a very nice and short tutorial on how to run Ruby service on Window, I will try it out later. It looks much easier than doing it with Python. Thanks for sharing it :) – Helen Neely Sep 16 '09 at 08:19
-
@Jonke In your first example, if you place the `begin` after the class definition, directly before the `DemoDaemon.mainloop`, would the script still operate the same? – Paul Hoffer Mar 22 '11 at 05:14
-
@phoffer: It was a long time since I wrote the example but I think a put everything in a begin rescue because that way I could track some really hard to understand errors that expose themself when you actually run the service as the local service account, there were some differences between XP, win 2003 server, win 2008 server, vista and differences between the gem of win32 versions. – Jonke Mar 22 '11 at 08:43
Here is a code template to do firedeamon :)
#####################################################################
# runneur.rb : service which run (continuously) a process
# 'do only one simple thing, but do it well'
#####################################################################
# Usage:
# .... duplicate this file : it will be the core-service....
# .... modify constantes in beginning of this script....
# .... modify stop_sub_process() at end of this script for clean stop of sub-application..
#
# > ruby runneur.rb install foo ; foo==name of service,
# > ruby runneur.rb uninstall foo
# > type d:\deamon.log" ; runneur traces
# > type d:\d.log ; service traces
#
#####################################################################
class String; def to_dos() self.tr('/','\\') end end
class String; def from_dos() self.tr('\\','/') end end
rubyexe="d:/usr/Ruby/ruby19/bin/rubyw.exe".to_dos
# example with spawn of a ruby process...
SERVICE_SCRIPT="D:/usr/Ruby/local/text.rb"
SERVICE_DIR="D:/usr/Ruby/local".to_dos
SERVICE_LOG="d:/d.log".to_dos # log of stdout/stderr of sub-process
RUNNEUR_LOG="d:/deamon.log" # log of runneur
LCMD=[rubyexe,SERVICE_SCRIPT] # service will do system('ruby text.rb')
SLEEP_INTER_RUN=4 # at each dead of sub-process, wait n seconds before rerun
################### Installation / Desintallation ###################
if ARGV[0]
require 'win32/service'
include Win32
name= ""+(ARGV[1] || $0.split('.')[0])
if ARGV[0]=="install"
path = "#{File.dirname(File.expand_path($0))}/#{$0}".tr('/', '\\')
cmd = rubyexe + " " + path
print "Service #{name} installed with\n cmd=#{cmd} ? " ; rep=$stdin.gets.chomp
exit! if rep !~ /[yo]/i
Service.new(
:service_name => name,
:display_name => name,
:description => "Run of #{File.basename(SERVICE_SCRIPT.from_dos)} at #{SERVICE_DIR}",
:binary_path_name => cmd,
:start_type => Service::AUTO_START,
:service_type => Service::WIN32_OWN_PROCESS | Service::INTERACTIVE_PROCESS
)
puts "Service #{name} installed"
Service.start(name, nil)
sleep(3)
while Service.status(name).current_state != 'running'
puts 'One moment...' + Service.status(name).current_state
sleep 1
end
while Service.status(name).current_state != 'running'
puts ' One moment...' + Service.status(name).current_state
sleep 1
end
puts 'Service ' + name+ ' started'
elsif ARGV[0]=="desinstall" || ARGV[0]=="uninstall"
if Service.status(name).current_state != 'stopped'
Service.stop(name)
while Service.status(name).current_state != 'stopped'
puts 'One moment...' + Service.status(name).current_state
sleep 1
end
end
Service.delete(name)
puts "Service #{name} stopped and uninstalled"
else
puts "Usage:\n > ruby #{$0} install|desinstall [service-name]"
end
exit!
end
#################################################################
# service runneur : service code
#################################################################
require 'win32/daemon'
include Win32
Thread.abort_on_exception=true
class Daemon
def initialize
@state='stopped'
super
log("******************** Runneur #{File.basename(SERVICE_SCRIPT)} Service start ***********************")
end
def log(*t)
txt= block_given?() ? (yield() rescue '?') : t.join(" ")
File.open(RUNNEUR_LOG, "a"){ |f| f.puts "%26s | %s" % [Time.now,txt] } rescue nil
end
def service_pause
#put activity in pause
@state='pause'
stop_sub_process
log { "service is paused" }
end
def service_resume
#quit activity from pause
@state='run'
log { "service is resumes" }
end
def service_interrogate
# respond to quistion status
log { "service is interogate" }
end
def service_shutdown
# stop activities before shutdown
log { "service is stoped for shutdown" }
end
def service_init
log { "service is starting" }
end
def service_main
@state='run'
while running?
begin
if @state=='run'
log { "starting subprocess #{LCMD.join(' ')} in #{SERVICE_DIR}" }
@pid=::Process.spawn(*LCMD,{
chdir: SERVICE_DIR,
out: SERVICE_LOG, err: :out
})
log { "sub-process is running : #{@pid}" }
a=::Process.waitpid(@pid)
@pid=nil
log { "sub-process is dead (#{a.inspect})" }
sleep(SLEEP_INTER_RUN) if @state=='run'
else
sleep 3
log { "service is sleeping" } if @state!='run'
end
rescue Exception => e
log { e.to_s + " " + e.backtrace.join("\n ")}
sleep 4
end
end
end
def service_stop
@state='stopped'
stop_sub_process
log { "service is stoped" }
exit!
end
def stop_sub_process
::Process.kill("KILL",@pid) if @pid
@pid=nil
end
end
Daemon.mainloop

- 423
- 3
- 6
You can write (or download) a wrapper service. The wrapper can call the ruby.exe to execute your program. Same trick works for Java, VB, etc.

- 2,092
- 1
- 19
- 16
You should be able to accomplish this in IronRuby since you would have the .NET framework behind you.

- 21,119
- 15
- 74
- 98