¿Cómo configurar una aplicación Rails (redmine) para que se ejecute como un servicio en Windows?
-
22-08-2019 - |
Pregunta
Estoy usando redmine como administrador de tickets y me gustaría configurarlo para que se ejecute automáticamente cuando se inicia Windows.
¿Cómo puedo configurarlo para que se ejecute como un servicio?
--
Solo hice la pregunta para documentarla, espero que alguien pueda encontrarla útil...
Solución
1.usando webrick:
árbitro: http://www.redmine.org/boards/1/topics/4123
Descargue e instale el kit de recursos de Windows NT desdehttp://www.microsoft.com/downloads/details.aspx?familyid=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
Cree el servicio ejecutando este comando:
path\INSTSRV.EXE your_service_name path\SRVANY.EXE
en mi caso
path
es:"C:\Program Files\Windows NT Resource Kit\INSTSRV.EXE" redmine_webrick "C:\Program Files\Windows NT Resource Kit\SRVANY.EXE"
podría ser también
C:\Program Files\Windows Resource Kits\Tools\
.Ejecute regedit (Inicio -> Ejecutar -> regedit)
Agregue la siguiente clave de registro si aún no está allí:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\su_nombre_servicio
Haga clic derecho en esta clave de registro y seleccione Nuevo -> Clave.Nombralo
Parameters
.Suma dos valores a la
Parameters
llave.Haga clic derecho en la clave de parámetros, Nuevo -> Valor de cadena.NombraloApplication
.Ahora crea otro llamadoAppParameters
.Dales los siguientes valores:- Solicitud:
PathToRuby.exe
, p.ej.C:\ruby\bin\Ruby.exe
- Parámetros de la aplicación:
C:\RUBYAPP\script\server -e production
, dóndeRUBYAPP
es el directorio que contiene el sitio web de redmine.
Ejemplo:
C:\redmine\script\server -p 2000 -e production
(-p indica el puerto que escuchará el webrick y -e el entorno utilizado)- Solicitud:
Ahora puedes ir a Herramientas administrativas -> Servicios.Allí podrás iniciar tu servicio (el que tiene nombre your_service_name
) y compruebe si funciona correctamente o no.Cabe señalar que el servicio se marcará como iniciado antes de que WEBrick finalice su procedimiento de inicio.Debes esperar aproximadamente 1 minuto antes de intentar acceder al servicio para verificar que esté funcionando correctamente.
2.usando mestizo:
árbitro: http://mongrel.rubyforge.org/wikiárbitro: http://mongrel.rubyforge.org/wiki/Win32
Primero instale mongrel y mongrel_service gem
gem install mongrel
gem install mongrel_service
luego crea el servicio
mongrel_rails service::install -N redmine_mongrel -c c:\redmine -p 3000 -e production
3.usando delgado:
Referencias:
- http://code.macournoyer.com/thin/
- http://www.astarbe.com/es/trucos/windows/srvany_convierte_una_aplicacion_en_servicio
Instrucciones:
Primer instalación delgada (necesitará instalar gema de rack, si aún no está instalada)
gem install rack gem install thin
Siga los mismos pasos indicados para webrick, pero agregue otro valor llamado "AppDirectory".Esto es necesario para evitar el uso de c: uby\bin hin.bat. Si solo señalara el archivo bat, no podría detener el servicio.
En
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\redmine_thin\Parameters
agregue las siguientes claves:Solicitud:c: uby\bin uby.exe
Directorio de aplicaciones:c: edmine
Parámetros de la aplicación:c: uby\bin hin start -p 4000 -e producción
------------------------------------------------------------------------------------------
Puede controlar cualquiera de sus servicios con los siguientes comandos:
inicio neto redmine_xxx
parada neta redmine_xxx
sc config redmine_xxx inicio = automático
sc config redmine_xxx inicio = dependencia automática = MySql
borrar sc redmine_xxx
Otros consejos
Para aplicaciones Rails 3.0.x (probadas en 3.0.10 y Windows 7)
demo_daemon_ctl.rb
############################################################################
# demo_daemon_ctl.rb
#
# This is a command line script for installing and/or running a small
# Ruby program as a service. The service will simply write a small bit
# of text to a file every 20 seconds. It will also write some text to the
# file during the initialization (service_init) step.
#
# It should take about 10 seconds to start, which is intentional - it's a test
# of the service_init hook, so don't be surprised if you see "one moment,
# start pending" about 10 times on the command line.
#
# The file in question is C:\test.log. Feel free to delete it when finished.
#
# To run the service, you must install it first.
#
# Usage: ruby demo_daemon_ctl.rb <option>
#
# Note that you *must* pass this program an option
#
# Options:
# install - Installs the service. The service name is "DemoSvc"
# and the display name is "Demo".
# start - Starts the service. Make sure you stop it at some point or
# you will eventually fill up your filesystem!.
# stop - Stops the service.
# pause - Pauses the service.
# resume - Resumes the service.
# uninstall - Uninstalls the service.
# delete - Same as uninstall.
#
# You can also used the Windows Services GUI to start and stop the service.
#
# To get to the Windows Services GUI just follow:
# Start -> Control Panel -> Administrative Tools -> Services
############################################################################
require 'win32/service'
require 'rbconfig'
include Win32
include Config
# Make sure you're using the version you think you're using.
puts 'VERSION: ' + Service::VERSION
SERVICE_NAME = 'DemoSvc'
SERVICE_DISPLAYNAME = 'Demo'
# Quote the full path to deal with possible spaces in the path name.
ruby = File.join(CONFIG['bindir'], 'ruby').tr('/', '\\')
path = ' "' + File.dirname(File.expand_path($0)).tr('/', '\\')
path += '\demo_daemon.rb"'
cmd = ruby + path
# You must provide at least one argument.
raise ArgumentError, 'No argument provided' unless ARGV[0]
case ARGV[0].downcase
when 'install'
Service.new(
:service_name => SERVICE_NAME,
:display_name => SERVICE_DISPLAYNAME,
:description => 'Sample Ruby service',
:binary_path_name => cmd
)
puts 'Service ' + SERVICE_NAME + ' installed'
when 'start'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.start(SERVICE_NAME, nil, 'hello', 'world')
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' started'
else
puts 'Already running'
end
when 'stop'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' stopped'
else
puts 'Already stopped'
end
when 'uninstall', 'delete'
if Service.status(SERVICE_NAME).current_state != 'stopped'
Service.stop(SERVICE_NAME)
end
while Service.status(SERVICE_NAME).current_state != 'stopped'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
Service.delete(SERVICE_NAME)
puts 'Service ' + SERVICE_NAME + ' deleted'
when 'pause'
if Service.status(SERVICE_NAME).current_state != 'paused'
Service.pause(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'paused'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' paused'
else
puts 'Already paused'
end
when 'resume'
if Service.status(SERVICE_NAME).current_state != 'running'
Service.resume(SERVICE_NAME)
while Service.status(SERVICE_NAME).current_state != 'running'
puts 'One moment...' + Service.status(SERVICE_NAME).current_state
sleep 1
end
puts 'Service ' + SERVICE_NAME + ' resumed'
else
puts 'Already running'
end
else
raise ArgumentError, 'unknown option: ' + ARGV[0]
end
demo_daemon.rb
APP_ROOT_CUSTOM = 'your app root dir'
LOG_FILE = APP_ROOT_CUSTOM + 'log/win32_daemon_test.log'
APP_PATH = File.expand_path( APP_ROOT_CUSTOM + 'config/application', APP_ROOT_CUSTOM + 'script/rails')
begin
require 'rubygems'
require 'win32/daemon'
include Win32
require File.expand_path( APP_ROOT_CUSTOM + 'config/boot', APP_ROOT_CUSTOM + 'script/rails')
require 'rails/commands/server'
module ::Rails
class Server
def default_options
super.merge({
:Port => 3000,
:environment => (ENV['RAILS_ENV'] || "development").dup,
:daemonize => false,
:debugger => false,
:pid => File.expand_path( APP_ROOT_CUSTOM + "tmp/pids/server.pid" ),
:config => File.expand_path( APP_ROOT_CUSTOM + "config.ru" )
})
end
end
end
class DemoDaemon < Daemon
# This method fires off before the +service_main+ mainloop is entered.
# Any pre-setup code you need to run before your service's mainloop
# starts should be put here. Otherwise the service might fail with a
# timeout error when you try to start it.
#
def service_init
end
# This is the daemon's mainloop. In other words, whatever runs here
# is the code that runs while your service is running. Note that the
# loop is not implicit.
#
# You must setup a loop as I've done here with the 'while running?'
# code, or setup your own loop. Otherwise your service will exit and
# won't be especially useful.
#
# In this particular case, I've setup a loop to append a short message
# and timestamp to a file on your C: drive every 20 seconds. Be sure
# to stop the service when you're done!
#
def service_main(*args)
Rails::Server.new.tap { |server|
require APP_PATH
Dir.chdir( APP_ROOT_CUSTOM )
server.start
}
msg = 'application started at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f|
f.puts msg
f.puts "Args: " + args.join(',')
}
# While we're in here the daemon is running.
while running?
if state == RUNNING
sleep 20
msg = 'Service is running as of: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
else # PAUSED or IDLE
sleep 0.5
end
end
# We've left the loop, the daemon is about to exit.
File.open(LOG_FILE, 'a'){ |f| f.puts "STATE: #{state}" }
msg = 'service_main left at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
# This event triggers when the service receives a signal to stop. I've
# added an explicit "exit!" here to ensure that the Ruby interpreter exits
# properly. I use 'exit!' instead of 'exit' because otherwise Ruby will
# raise a SystemExitError, which I don't want.
#
def service_stop
msg = 'Received stop signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
exit!
end
# This event triggers when the service receives a signal to pause.
#
def service_pause
msg = 'Received pause signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
# This event triggers when the service receives a signal to resume
# from a paused state.
#
def service_resume
msg = 'Received resume signal at: ' + Time.now.to_s
File.open(LOG_FILE, 'a'){ |f| f.puts msg }
end
end
# Create an instance of the Daemon and put it into a loop. I borrowed the
# method name 'mainloop' from Tk, btw.
#
DemoDaemon.mainloop
rescue Exception => err
File.open(LOG_FILE, 'a'){ |fh| fh.puts 'Daemon failure: ' + err }
raise
end
Coloque ambos archivos en el mismo Dir y ejecute
ruby demo_daemon_ctl.rb install
Hace algún tiempo, intenté instalar Redmine en Windows también. Pero no pude hacer que funcionara, probablemente Debido a la falta de conocimiento de los rieles.
Entonces descubrí Pila de Bitnami Redmine. Tienen un instalador de Windows, que instala RedMine con todas las dependencias necesarias, y simplemente funciona.
Para las aplicaciones Rails 4.0.X, según lo sugerido por Bohdan, tenemos que reemplazar
Config ['bindir'] con rbconfig :: config ['bindir'
Remmber a: Gem Install Win32-Service
gem install win32-service
- coloque debajo del código Ruby en un archivo service.rb y actualice la ruta REDMINE_DIR para que se ajuste a su instalación de Redmine
- crear el servicio, por ejemplo con
sc create redmine binPath= "C:\Ruby23-x64\bin\rubyw -C E:\www\redmine-3.3.2\ service.rb"
dóndeE:\www\redmine-3.3.2\
es la ruta del directorio donde se encuentra el archivo service.rb yC:\Ruby23-x64\bin\rubyw
su ruta de instalación de Ruby
Comenzar requerir 'win32/demonio' incluye win32
class RedmineService < Daemon
def service_init
File.open(LOG_FILE, 'a'){ |f| f.puts "Initializing service #{Time.now}" }
#@server_pid = Process.spawn 'ruby script/rails s -e production', :chdir => REDMINE_DIR, :err => [LOG_FILE, 'a']
# use full path
@server_pid = Process.spawn 'C:\Ruby23-x64\bin\ruby E:\www\redmine-3.3.2\bin\rails s -e production -p 3000', :chdir => REDMINE_DIR, :err => [LOG_FILE, 'a']
end
def service_main
File.open(LOG_FILE, 'a'){ |f| f.puts "Service is running #{Time.now} with pid #{@server_pid}" }
while running?
sleep 10
end
end
def service_stop
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopping server thread #{Time.now}" }
system "taskkill /PID #{@server_pid} /T /F"
Process.waitall
File.open(LOG_FILE, 'a'){ |f| f.puts "Service stopped #{Time.now}" }
exit!
end
end
RedmineService.mainloop
rescue Exception => e
File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} exception=#{e.inspect}\n#{e.backtrace.join($/)}" }
raise
end
- Tenga en cuenta que Process.spawn en service.rb usa la ruta completa.
Espero que esto ayude a cualquiera. Definí el servicio de Windows que inicia el RedMine con el servidor delgado.
Usar http://nssm.cc/usage para la creación de servicios de Windows. Establezca la ruta en Ruby.exe, el directorio de trabajo de su Redmine y defina los parámetros iniciales:
Path: C:\RailsInstaller\Ruby2.3.3\bin\ruby.exe
Startup directory: C:\Program Files\redmine-3.4.6
Arguments: C:\RailsInstaller\Ruby2.3.3\bin\thin start -e production -p 3000