Подтвердить что ты не робот

Запуск Ruby-программы в качестве службы Windows?

Можно ли запустить рубиновое приложение в качестве службы Windows? Я вижу, что есть связанный вопрос, который обсуждает запуск Java-приложения в качестве службы Windows, как вы можете это сделать с помощью приложения Ruby?

4b9b3361

Ответ 1

Посмотрите следующую библиотеку: Win32Utils. Вы можете создать простой сервис, который вы можете запустить/остановить/перезапустить в свободное время. В настоящее время я использую его для управления экземпляром Mongrel для Windows Rails, и он работает безупречно.

Ответ 2

При попытке Win32Utils действительно нужно изучить документ и просмотреть сеть, прежде чем найти какой-нибудь простой рабочий пример. Это похоже на работу сегодня 2008-10-02:

gem install win32-service

Обновление 2012-11-20: Согласно https://stackoverflow.com/users/1374569/paul register_bar.rb теперь должен быть

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

создать приложение/демон

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 - это сервис, но мы должны сначала создать и зарегистрироваться! это можно сделать с помощью sc create some_service

, но если мы будем использовать ruby ​​и win32utils, мы должны сделать

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'
   )

Обратите внимание, что существует пробел между c:\tmp\bar.rb в 'c:\usr\ruby ​​\ bin\rubyw.exe -C c:\tmp\bar.rb'

Выполнить ruby register_bar.rb и теперь можно запустить службу либо с панели управления услугами Windows, либо

sc start some_service

и посмотрите, как c: test.log заполняется Служба работает Чт Окт 02 22:06:47 +0200 2008

Для простого, с чем-то работать с ним, проще удалить служебный регистр и создать новый вместо изменения существующего

unregister_bar.rb

 require "rubygems"
    require "win32/service"
       include Win32

    Service.delete("some_service")

Кредиты для людей http://rubypane.blogspot.com/2008/05/windows-service-using-win32-service-and_29.html

http://rubyforge.org/docman/view.php/85/595/service.html

Ответ 3

Вот шаблон кода для создания 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

Ответ 4

Вы можете написать (или загрузить) службу обертки. Обертка может вызвать ruby.exe для выполнения вашей программы. Такой же трюк работает для Java, VB и т.д.

Ответ 5

Вы должны иметь возможность выполнить это в IronRuby, так как у вас будет платформа .NET.