Ať už si chceš v Ruby napsat webserver (jako třeba WEBRick), nebo automat na zpracování emailů, budeš potřebovat takzvaný proces na pozadí aneb démon. Démon je jednoduše proces, který nevlastní konzoli. Začněme nejdříve pracovní náplní takového démona. Jediné co následující funkce dělá je, že v nekonečné smyčce jednou za pět vteřin oznámí zápisem do souboru, že stále běží a pokud dojde k ukončení, slušně se rozloučí a soubor zavře.
# main.rb 1
def work(log_file)
i = 1
begin
file = File.open(log_file, "w+")
loop do
file.puts "Ti říkam po #{i+=1}té, že nespím!"
file.flush
sleep(5)
end
ensure
if file
file.puts "Já končím."
file.close
end
end
end
Tento kód samozřejmě nic nedělá, je potřeba najít vhodný soubor pro výstup a smyčku spustit.
# main.rb 2 log_file = File.join(File.dirname(__FILE__), "daemon.log") work(log_file)
Převedení víše uvedeného na démona je díky gemu daemons jednoduché asi takhle:
# main.rb 3 require 'rubygems' require 'daemons' Daemons.daemonize
Metoda Daemons.daemonize z aktuálního procesu udělá démona. K tomuto démonovi ale nemáš přístup a jediný způsob ukončení jeho činnosti je, že se ukončí sám (a nebo v horším případě kill). Jiná metoda Daemons.run_proc je daleko zajímavější. Použiješ ji takto:
# main.rb 4
require 'rubygems'
require 'daemons'
LOG_ROOT = File.dirname(File.expand_path(__FILE__))
def work(log_file)
i = 1
begin
file = File.open(log_file, "w+")
loop do
file.puts "Ti říkam po #{i+=1}té, že nespím!"
file.flush
sleep(5)
end
ensure
if file
file.puts "Já končím."
file.close
end
end
end
Daemons.run_proc("main.rb.daemon", :log_output => true) do
log_file = "#{LOG_ROOT}/daemon.log"
work(log_file)
end
Nejdříve vysvětlím proč jsem změnil cestu k souboru.
LOG_ROOT = File.dirname(File.expand_path(__FILE__))
log_file = "#{LOG_ROOT}/daemon.log"
Démon není stejný proces, jako ten, co jsme spustili z příkazové řádky. Je to samostatný proces, který má jako pracovní adresář nastavený kořen a proto je třeba k výstupnímu souboru zadat absolutní cestu.
Zatímco skripty používající Daemons.daemonize se spouští stejně jako každý jiný Ruby skript, s Daemons.run_proc dostáváš k dispozici celou řadu kouzel. V okamžiku se z našeho skriptu stal plnohodnotný démon s ovládacím rozhraním.
$ ruby main.rb start # spustí démona na pozadí $ ruby main.rb status # vypíše jaký je stav main.rb.daemon: running [pid 9423] $ ruby main.rb stop # vypne běžící proces $ ruby main.rb status # vypíše jaký je stav main.rb.daemon: no instances running
Gem daemons má spoustu dalších zajímavých možností a jak je dobrým zvykem, je velmi dobře dokumentován. Nainstaluješ ho jako každý jiný gem pomocí
gem install daemons
Kód k tomuto článku si můžeš stáhnout na githubu http://github.com/honzasterba/dobrykod/tree/master/demonicke-procesy-v-ruby