Est-il possible d'exécuter une application ruby comme un service Windows ? Je vois qu'il y a une question connexe qui traite de l'exécution d'une application ruby en tant que service Windows. Application Java en tant que service Windows comment faire cela avec une application Ruby ?
Réponses
Trop de publicités?Consultez la bibliothèque suivante : Win32Utils . Vous pouvez créer un service simple que vous pouvez démarrer/arrêter/redémarrer à votre guise. Je l'utilise actuellement pour gérer une instance Mongrel pour une application Rails hébergée sous Windows et cela fonctionne parfaitement.
Vous pouvez également utiliser cet exemple comme une méthode pour permettre à votre application Ruby d'agir comme un service Windows : Exécution en tant que service Windows .
Bonne chance.
Lorsqu'on essaie les Win32Utils, il faut vraiment étudier la documentation et chercher sur le net avant de trouver un exemple simple et fonctionnel. Cela semble fonctionner aujourd'hui 2008-10-02 :
gem install win32-service
Mise à jour 2012-11-20 : Selon http://stackoverflow.com/users/1374569/paul le fichier register_bar.rb devrait maintenant être
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
créer l'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 est le service mais nous devons d'abord le créer et l'enregistrer ! ceci peut être fait avec sc create some_service
mais si nous voulons utiliser ruby et win32utils, nous devrions faire une
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'
)
Notez qu'il y a un espace entre les c : \tmp\ bar.rb dans 'c : \usr\ruby\bin\rubyw.exe -C c : \tmp\ bar.rb
Exécuter ruby register_bar.rb
et maintenant on peut démarrer le service soit à partir du panneau de contrôle des services de Windows, soit
sc start some_service
et regardez c:test.log se remplir avec Le service fonctionne Thu Oct 02 22:06:47 +0200 2008
Pour le simple fait d'avoir quelque chose sur lequel travailler, il est plus facile de supprimer le registre de service et d'en créer un nouveau plutôt que de modifier un registre existant.
unregister_bar.rb
require "rubygems"
require "win32/service"
include Win32
Service.delete("some_service")
Crédits aux personnes http://rubypane.blogspot.com/2008/05/Windows-service-using-win32-service-and_29.html
Voici un modèle de code pour faire du 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