Pertanyaan Menjalankan Program Ruby sebagai Layanan Windows?


Apakah mungkin untuk menjalankan aplikasi ruby ​​sebagai Layanan Windows? Saya melihat bahwa ada pertanyaan terkait yang membahas menjalankan Aplikasi Java sebagai Layanan Windows, bagaimana Anda bisa melakukan ini dengan aplikasi Ruby?


32
2017-10-02 17:14


asal


Jawaban:


Lihat pustaka berikut: Win32Utils. Anda dapat membuat layanan sederhana yang dapat Anda mulai / hentikan / mulai ulang di waktu senggang Anda. Saat ini saya menggunakannya untuk mengelola instance Mongrel untuk aplikasi Rails yang di-host Windows dan bekerja dengan sempurna.


25
2017-10-02 17:23



Saat mencoba Win32Utils, Anda harus benar-benar memeriksa dokumen dan melihat ke internet sebelum menemukan contoh kerja sederhana. Ini sepertinya berfungsi hari ini 2008-10-02:

gem install win32-service

Perbarui 2012-11-20: Menurut https://stackoverflow.com/users/1374569/paul register_bar.rb seharusnya sekarang

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

buat aplikasi / 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 adalah layanannya tetapi kita harus membuat dan mendaftar terlebih dahulu! ini bisa dilakukan dengan sc create some_service

tetapi jika kita akan menggunakan ruby ​​dan win32utils, kita harus melakukan

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

Catatan, ada spasi di antara c: \ tmp \ bar.rb di 'c: \ usr \ ruby ​​\ bin \ rubyw.exe -C c: \ tmp \ bar.rb'

Menjalankan ruby register_bar.rb dan sekarang satu dapat memulai layanan baik dari panel kontrol layanan windows atau

sc start some_service

dan perhatikan c: test.log diisi dengan Layanan sedang berjalan Kamis 2 Oktober 22:06:47 +0200 2008

Untuk mudah memiliki sesuatu untuk bekerja dengan itu lebih mudah untuk menghapus register layanan dan membuat yang baru, bukan memodifikasi yang sudah ada

unregister_bar.rb

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

    Service.delete("some_service")

Kredit untuk rakyat http://rubypane.blogspot.com/2008/05/windows-service-using-win32-service-and_29.html

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


16
2017-10-02 20:17



Berikut ini adalah template kode untuk melakukan 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
2018-01-23 11:54



Anda dapat menulis (atau mengunduh) layanan pembungkus. Pembungkus dapat memanggil ruby.exe untuk menjalankan program Anda. Trik yang sama berlaku untuk Java, VB, dll.


0
2017-10-02 17:18



Anda harus dapat mencapai ini di IronRuby karena Anda akan memiliki kerangka NET di belakang Anda.


0
2017-10-02 17:19