/
cli.rb
120 lines (107 loc) · 3.87 KB
/
cli.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
require 'trollop'
require 'resque/pool'
require 'fileutils'
module Resque
class Pool
module CLI
extend self
def run
opts = parse_options
daemonize if opts[:daemon]
manage_pidfile opts[:pidfile]
redirect opts
setup_environment opts
start_pool
end
def parse_options
opts = Trollop::options do
version "resque-pool #{VERSION} (c) nicholas a. evans"
banner <<-EOS
resque-pool is the best way to manage a group (pool) of resque workers
When daemonized, stdout and stderr default to resque-pool.stdxxx.log files in
the log directory and pidfile defaults to resque-pool.pid in the current dir.
Usage:
resque-pool [options]
where [options] are:
EOS
opt :config, "Alternate path to config file", :type => String, :short => "-c"
opt :appname, "Alternate appname", :type => String, :short => "-a"
opt :daemon, "Run as a background daemon", :default => false, :short => "-d"
opt :stdout, "Redirect stdout to logfile", :type => String, :short => '-o'
opt :stderr, "Redirect stderr to logfile", :type => String, :short => '-e'
opt :nosync, "Don't sync logfiles on every write"
opt :pidfile, "PID file location", :type => String, :short => "-p"
opt :environment, "Set RAILS_ENV/RACK_ENV/RESQUE_ENV", :type => String, :short => "-E"
end
if opts[:daemon]
opts[:stdout] ||= "log/resque-pool.stdout.log"
opts[:stderr] ||= "log/resque-pool.stderr.log"
opts[:pidfile] ||= "tmp/pids/resque-pool.pid"
end
opts
end
def daemonize
raise 'First fork failed' if (pid = fork) == -1
exit unless pid.nil?
Process.setsid
raise 'Second fork failed' if (pid = fork) == -1
exit unless pid.nil?
end
def manage_pidfile(pidfile)
return unless pidfile
pid = Process.pid
if File.exist? pidfile
if process_still_running? pidfile
raise "Pidfile already exists at #{pidfile} and process is still running."
else
File.delete pidfile
end
else
FileUtils.mkdir_p File.dirname(pidfile)
end
File.open pidfile, "w" do |f|
f.write pid
end
at_exit do
if Process.pid == pid
File.delete pidfile
end
end
end
def process_still_running?(pidfile)
old_pid = open(pidfile).read.strip.to_i
Process.kill 0, old_pid
true
rescue Errno::ESRCH
false
rescue Errno::EPERM
true
rescue ::Exception => e
$stderr.puts "While checking if PID #{old_pid} is running, unexpected #{e.class}: #{e}"
true
end
def redirect(opts)
$stdin.reopen '/dev/null' if opts[:daemon]
# need to reopen as File, or else Resque::Pool::Logging.reopen_logs! won't work
out = File.new(opts[:stdout], "a") if opts[:stdout] && !opts[:stdout].empty?
err = File.new(opts[:stderr], "a") if opts[:stderr] && !opts[:stderr].empty?
$stdout.reopen out if out
$stderr.reopen err if err
$stdout.sync = $stderr.sync = true unless opts[:nosync]
end
def setup_environment(opts)
Resque::Pool.app_name = opts[:appname] if opts[:appname]
ENV["RACK_ENV"] = ENV["RAILS_ENV"] = ENV["RESQUE_ENV"] = opts[:environment] if opts[:environment]
Resque::Pool.log "Resque Pool running in #{ENV["RAILS_ENV"] || "development"} environment"
ENV["RESQUE_POOL_CONFIG"] = opts[:config] if opts[:config]
end
def start_pool
require 'rake'
require 'resque/pool/tasks'
Rake.application.init
Rake.application.load_rakefile
Rake.application["resque:pool"].invoke
end
end
end
end