Ciao,
uso la gem BJ (Background Job, http://codeforpeople.rubyforge.org/svn/bj/trunk/README) per gestire job
in background (ne manda uno alla volta) e ho necessità di interrompere
il processo in esecuzione.
Come posso fare?
Ora ho pensato di killare con il comando kill il processo utilizzando i
backticks: kill -9 #{bj.pid}
E’ una buona soluzione?
Se kill e’ una buona soluzione, quale è il segnale piu’ appropriato (qui
il 9)? Si tenga presente che sarebbe opportuno che i file aperti dal
processo in esecuzione vengano correttamente chiusi.
Ciao,
uso la gem BJ (Background Job, http://codeforpeople.rubyforge.org/svn/bj/trunk/README) per gestire job
in background (ne manda uno alla volta) e ho necessità di interrompere
il processo in esecuzione.
Come posso fare?
Ciao, do per scontato che tu stia parlando di un sistema operativo
POSIX (cioè non di Windows).
C’è il modulo Process, con il suo bravo metodo kill:
quale è il segnale piu’ appropriato (qui il 9)? Si tenga presente
che sarebbe opportuno che i file aperti dal processo in esecuzione
vengano correttamente chiusi.
Beh, allora certamente non KILL (9), ma TERM, che è quello di default,
cioè quello che viene inviato digitando kill .
Per controllare che un processo sia attivo e nel caso riattivarlo (a
volte mi muoiono e non tornano su…) uso questa before_filter nel
controller che mi elimina il pid e rilancia l’app:
def init_cron_active
if File.file?("#{RAILS_ROOT}/lib/cal_ticker.rb.pid")
pid = “”
begin
file = File.new("#{RAILS_ROOT}/lib/cal_ticker.rb.pid", “r”)
while (line = file.gets)
pid = line.to_i
if Process.nil? or !(Process.getpgid(pid).to_i > 0)
File.unlink("#{RAILS_ROOT}/lib/cal_ticker.rb.pid") start_ticker
end
end
file.close
rescue Exception => e
begin
File.unlink("#{RAILS_ROOT}/lib/cal_ticker.rb.pid")
Process.waitpid(pid, Process::WNOHANG) start_ticker
rescue Exception => e
end
end
end
end
Beh, allora certamente non KILL (9), ma TERM, che è quello di default,
cioè quello che viene inviato digitando kill .
aggiungo: usare TERM o KILL non cambia molto se non gestisce nel tuo
codice il segnale, c’è #trap per questo:
trap “INT” {
cleanup();
}
la differenza è solo che KILL non puoi trapparlo, ma se non metti un
handler per il segnale non ti serve a molto usare uno o l’altro
Prima di fare questo però cerca di pensare se puoi strutturare
l’applicazione in modo che sia crash-only, cioè che sia giusto
ammazzarla con SIGKILL o in qualunque altro modo.
Oltre a non dover gestire esplicitamente i segnali (con complicazioni
varie, variabili pseudo-globali etc) ti troverai con un processo che è
più resistente ad errori interni (eccezioni etc) ed esterni
(OOMKiller, fine spazio su disco, kill accidentale etc). E
probabilmente con meno codice
def kill_me_and_my_descendant(pid)
a = COMMAND_MODE=unix2003; ps -ef | awk '$3 == '#{pid}' { print $2 }'
a.chomp.split("\n").each do |child_pid|
kill_me_and_my_descendant(child_pid)
end
puts “>>>>>>>>>> Now killing #{pid}”
Process.kill(“KILL”, pid) # when a process is killed, his children
PPID are set to 1
# kill -9 #{pid}
end