lenguaje - ¿Ejecutando un programa de Ruby como un servicio de Windows?
ruby web (5)
¿Es posible ejecutar una aplicación de ruby como un servicio de Windows? Veo que hay una pregunta relacionada que analiza la ejecución de una aplicación Java como un servicio de Windows , ¿cómo se puede hacer esto con una aplicación de Ruby?
Al probar Win32Utils uno realmente necesita estudiar el documento y mirar por la red antes de encontrar un ejemplo de trabajo simple. Esto parece funcionar hoy en día 2008-10-02:
joya instalar win32-servicio
Actualización 2012-11-20: Según https://.com/users/1374569/paul, register_bar.rb debería ser ahora
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
crea la aplicación / 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 es el servicio pero debemos crear y registrar primero! esto se puede hacer con sc create some_service
pero si vamos a usar ruby y win32utils debemos hacer una
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''
)
Tenga en cuenta que hay un espacio entre c: / tmp / bar.rb en ''c: / usr / ruby / bin / rubyw.exe -C c: / tmp / bar.rb''
Ejecute ruby register_bar.rb
y ahora uno puede iniciar el servicio desde el panel de control del servicio de Windows o
sc start some_service
y mire c: test.log se complete con Servicio se está ejecutando Jue 02 Oct 22:06:47 +0200 2008
Para el simple de tener algo para trabajar, es más fácil eliminar el registro de servicio y crear uno nuevo en lugar de modificar uno existente
unregister_bar.rb
require "rubygems"
require "win32/service"
include Win32
Service.delete("some_service")
Créditos para la gente http://rubypane.blogspot.com/2008/05/windows-service-using-win32-service-and_29.html
Aquí hay una plantilla de código para hacer 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
Consulte la siguiente biblioteca: Win32Utils . Puede crear un servicio simple que puede iniciar / detener / reiniciar en su tiempo libre. Actualmente lo estoy usando para administrar una instancia de Mongrel para una aplicación Rails alojada en Windows y funciona sin problemas.
Debería poder lograr esto en IronRuby ya que tendría el framework .NET detrás de usted.
Puede escribir (o descargar) un servicio envoltorio. El contenedor puede llamar al ruby.exe para ejecutar su programa. El mismo truco funciona para Java, VB, etc.