processwanker 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Manifest +34 -0
- data/README +11 -0
- data/Rakefile +13 -0
- data/bin/pw +5 -0
- data/lib/config/config.rb +96 -0
- data/lib/config/config_auth.rb +208 -0
- data/lib/config/config_client.rb +75 -0
- data/lib/config/config_client_cluster.rb +66 -0
- data/lib/config/config_client_clusters.rb +62 -0
- data/lib/config/config_client_host.rb +152 -0
- data/lib/config/config_daemon.rb +94 -0
- data/lib/config/config_daemon_service.rb +84 -0
- data/lib/config/config_daemon_service_dependency.rb +59 -0
- data/lib/config/config_daemon_services.rb +89 -0
- data/lib/config/config_hook.rb +40 -0
- data/lib/config/config_node.rb +160 -0
- data/lib/config/config_smtp.rb +103 -0
- data/lib/events.rb +224 -0
- data/lib/log.rb +88 -0
- data/lib/net/net_api.rb +189 -0
- data/lib/net/net_client.rb +107 -0
- data/lib/net/net_connection.rb +167 -0
- data/lib/net/net_server.rb +232 -0
- data/lib/net/net_server_client.rb +84 -0
- data/lib/net/net_util.rb +205 -0
- data/lib/process_util.rb +216 -0
- data/lib/pw_app.rb +557 -0
- data/lib/service.rb +512 -0
- data/lib/service_classes/dummy_service.rb +88 -0
- data/lib/service_classes/pid_service.rb +126 -0
- data/lib/service_classes/process_service.rb +218 -0
- data/lib/service_classes/upstart_service.rb +103 -0
- data/lib/service_mgr.rb +226 -0
- data/lib/util.rb +31 -0
- data/processwanker.gemspec +36 -0
- data.tar.gz.sig +0 -0
- metadata +157 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,218 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# process_service.rb
|
4
|
+
#
|
5
|
+
# class representing a service that is a command-line launchable process
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'service'
|
10
|
+
require 'digest/md5'
|
11
|
+
require 'etc'
|
12
|
+
require 'net_util'
|
13
|
+
|
14
|
+
module ProcessWanker
|
15
|
+
|
16
|
+
class ProcessService < Service
|
17
|
+
|
18
|
+
include Log
|
19
|
+
|
20
|
+
############################################################################
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#
|
24
|
+
############################################################################
|
25
|
+
|
26
|
+
def self.nice_name
|
27
|
+
"process_service"
|
28
|
+
end
|
29
|
+
|
30
|
+
############################################################################
|
31
|
+
#
|
32
|
+
# iparams is a hash containing:
|
33
|
+
#
|
34
|
+
# :start_cmd
|
35
|
+
# :start_dir (optional)
|
36
|
+
# :stop_cmd (optional)
|
37
|
+
# :run_user (optional)
|
38
|
+
# :soft_kill_limit (optional)
|
39
|
+
#
|
40
|
+
# plus anything to be passed to Service
|
41
|
+
#
|
42
|
+
############################################################################
|
43
|
+
|
44
|
+
def initialize(iparams)
|
45
|
+
|
46
|
+
# extract parameters
|
47
|
+
extract_params(
|
48
|
+
iparams,
|
49
|
+
[
|
50
|
+
:start_cmd,
|
51
|
+
:start_dir,
|
52
|
+
:stop_cmd,
|
53
|
+
:run_user,
|
54
|
+
:soft_kill_limit,
|
55
|
+
])
|
56
|
+
|
57
|
+
# set defaults
|
58
|
+
@params=
|
59
|
+
{
|
60
|
+
:soft_kill_limit => 3,
|
61
|
+
:start_dir => "/"
|
62
|
+
}.merge(@params)
|
63
|
+
|
64
|
+
raise "service has no start_cmd" if(!@params[:start_cmd])
|
65
|
+
|
66
|
+
# determine run_user properties
|
67
|
+
if(@params[:run_user])
|
68
|
+
if(@params[:run_user].class == String)
|
69
|
+
@params[:run_user]=Etc.getpwnam(@params[:run_user])
|
70
|
+
elsif(@params[:run_user].class == Fixnum)
|
71
|
+
@params[:run_user]=Etc.getpwuid(@params[:run_user].to_i)
|
72
|
+
else
|
73
|
+
raise "bad run_user parameter for process_service"
|
74
|
+
end
|
75
|
+
|
76
|
+
# verify we can switch to this uid if necessary
|
77
|
+
current_uid=Process.euid()
|
78
|
+
if(current_uid != 0 && current_uid != @params[:run_user].uid)
|
79
|
+
raise "can't have a :run_user parameter unless we are running as root, or the uids match"
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
super(iparams)
|
85
|
+
end
|
86
|
+
|
87
|
+
############################################################################
|
88
|
+
#
|
89
|
+
# start
|
90
|
+
#
|
91
|
+
# fork() and exec() the start_cmd
|
92
|
+
#
|
93
|
+
############################################################################
|
94
|
+
|
95
|
+
def do_start(attempt_count)
|
96
|
+
info("do_start[#{attempt_count}] for #{self.name}")
|
97
|
+
|
98
|
+
Process.fork do
|
99
|
+
|
100
|
+
# close network descriptors
|
101
|
+
NetUtil::post_fork()
|
102
|
+
|
103
|
+
# start new session
|
104
|
+
Process.setsid()
|
105
|
+
|
106
|
+
# set environment cookie so we can be identified
|
107
|
+
hash=env_hash()
|
108
|
+
ENV[ ProcessUtil::ENVIRONMENT_KEY ] = hash if(hash)
|
109
|
+
|
110
|
+
# change user/group?
|
111
|
+
if(@params[:run_user])
|
112
|
+
|
113
|
+
current_uid=Process.euid()
|
114
|
+
current_user=Etc.getpwuid(current_uid)
|
115
|
+
|
116
|
+
if(current_uid != @params[:run_user].uid)
|
117
|
+
Process.uid=@params[:run_user].uid
|
118
|
+
Process.gid=@params[:run_user].gid
|
119
|
+
Process.euid=@params[:run_user].uid
|
120
|
+
Process.egid=@params[:run_user].gid
|
121
|
+
ENV["HOME"]=@params[:run_user].dir
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
# change directory?
|
127
|
+
Dir.chdir(@params[:start_dir])
|
128
|
+
|
129
|
+
# redirect inputs/outputs
|
130
|
+
STDIN.reopen("/dev/null") # - closing STDIN causes problems with apache
|
131
|
+
file=@params[:log_file] ? @params[:log_file] : "/dev/null"
|
132
|
+
STDOUT.reopen(file,"a")
|
133
|
+
STDERR.reopen(file,"a")
|
134
|
+
|
135
|
+
# run!
|
136
|
+
Process.exec(@params[:start_cmd])
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
############################################################################
|
143
|
+
#
|
144
|
+
# stop
|
145
|
+
#
|
146
|
+
# stop the process (either with -TERM or -KILL)
|
147
|
+
#
|
148
|
+
############################################################################
|
149
|
+
|
150
|
+
def do_stop(attempt_count)
|
151
|
+
|
152
|
+
kl=@params[:soft_kill_limit]
|
153
|
+
mode = (kl && attempt_count >= kl) ? :hard : :soft
|
154
|
+
|
155
|
+
info("do_stop[#{attempt_count}]->#{mode} for #{self.name}")
|
156
|
+
|
157
|
+
if(mode == :soft)
|
158
|
+
if(params[:stop_cmd])
|
159
|
+
system(params[:stop_cmd])
|
160
|
+
return
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# find all processes with matching hash
|
165
|
+
procs=ProcessUtil::processes[ env_hash ]
|
166
|
+
if(procs)
|
167
|
+
procs.each do |pid|
|
168
|
+
Process.kill({ :hard => "KILL", :soft => "TERM" }[mode],pid)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
############################################################################
|
175
|
+
#
|
176
|
+
# ping
|
177
|
+
#
|
178
|
+
# return run state of process
|
179
|
+
#
|
180
|
+
############################################################################
|
181
|
+
|
182
|
+
def do_ping
|
183
|
+
ProcessUtil::processes[env_hash] ? :up : :down
|
184
|
+
end
|
185
|
+
|
186
|
+
############################################################################
|
187
|
+
#
|
188
|
+
# env_hash
|
189
|
+
#
|
190
|
+
# returns magic environment cookie that identifies processes belonging to
|
191
|
+
# this service.
|
192
|
+
#
|
193
|
+
############################################################################
|
194
|
+
|
195
|
+
def env_hash()
|
196
|
+
Digest::MD5.hexdigest( name )
|
197
|
+
end
|
198
|
+
|
199
|
+
############################################################################
|
200
|
+
#
|
201
|
+
#
|
202
|
+
#
|
203
|
+
############################################################################
|
204
|
+
|
205
|
+
############################################################################
|
206
|
+
#
|
207
|
+
#
|
208
|
+
#
|
209
|
+
############################################################################
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
ServiceMgr::register_service_class(ProcessService)
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# upstart_service.rb
|
4
|
+
#
|
5
|
+
# class representing a service controlled by upstart
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'service'
|
10
|
+
require 'digest/md5'
|
11
|
+
require 'etc'
|
12
|
+
require 'process_service'
|
13
|
+
require 'process_util'
|
14
|
+
|
15
|
+
#<BRS> used to require dbus, but upstart doesn't seem to use it in Ubuntu Server
|
16
|
+
#require 'rubygems'
|
17
|
+
#gem 'ruby-dbus'
|
18
|
+
#require 'dbus'
|
19
|
+
|
20
|
+
module ProcessWanker
|
21
|
+
|
22
|
+
class UpstartService < Service
|
23
|
+
|
24
|
+
include Log
|
25
|
+
|
26
|
+
############################################################################
|
27
|
+
#
|
28
|
+
#
|
29
|
+
#
|
30
|
+
############################################################################
|
31
|
+
|
32
|
+
def self.nice_name
|
33
|
+
"upstart_service"
|
34
|
+
end
|
35
|
+
|
36
|
+
############################################################################
|
37
|
+
#
|
38
|
+
#
|
39
|
+
#
|
40
|
+
############################################################################
|
41
|
+
|
42
|
+
def initialize(iparams)
|
43
|
+
|
44
|
+
# extract parameters
|
45
|
+
extract_params(
|
46
|
+
iparams,
|
47
|
+
[
|
48
|
+
:job_name,
|
49
|
+
])
|
50
|
+
|
51
|
+
@job_name=@params[:job_name] || iparams[:name]
|
52
|
+
|
53
|
+
super(iparams)
|
54
|
+
end
|
55
|
+
|
56
|
+
############################################################################
|
57
|
+
#
|
58
|
+
# start
|
59
|
+
#
|
60
|
+
############################################################################
|
61
|
+
|
62
|
+
def do_start(attempt_count)
|
63
|
+
debug("do_start #{self.name}")
|
64
|
+
system("initctl start #{@job_name}")
|
65
|
+
end
|
66
|
+
|
67
|
+
############################################################################
|
68
|
+
#
|
69
|
+
# stop
|
70
|
+
#
|
71
|
+
############################################################################
|
72
|
+
|
73
|
+
def do_stop(attempt_count)
|
74
|
+
system("initctl stop #{@job_name}")
|
75
|
+
end
|
76
|
+
|
77
|
+
############################################################################
|
78
|
+
#
|
79
|
+
# ping
|
80
|
+
#
|
81
|
+
# return run state of process
|
82
|
+
#
|
83
|
+
############################################################################
|
84
|
+
|
85
|
+
def do_ping
|
86
|
+
status=`initctl status #{@job_name}`
|
87
|
+
status.include?("running") ? :up : :down
|
88
|
+
end
|
89
|
+
|
90
|
+
############################################################################
|
91
|
+
#
|
92
|
+
#
|
93
|
+
#
|
94
|
+
############################################################################
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
ServiceMgr::register_service_class(UpstartService)
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
|
data/lib/service_mgr.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# service_mgr.rb
|
4
|
+
#
|
5
|
+
# the core of the application
|
6
|
+
#
|
7
|
+
############################################################################
|
8
|
+
|
9
|
+
require 'process_util'
|
10
|
+
require 'config'
|
11
|
+
require 'service'
|
12
|
+
|
13
|
+
module ProcessWanker
|
14
|
+
class ServiceMgr
|
15
|
+
|
16
|
+
include Log
|
17
|
+
|
18
|
+
############################################################################
|
19
|
+
#
|
20
|
+
#
|
21
|
+
#
|
22
|
+
############################################################################
|
23
|
+
|
24
|
+
CLASS_SUBDIR = "service_classes"
|
25
|
+
CLASS_DIR = File.join(File.dirname(File.expand_path(__FILE__)),CLASS_SUBDIR)
|
26
|
+
|
27
|
+
############################################################################
|
28
|
+
#
|
29
|
+
#
|
30
|
+
#
|
31
|
+
############################################################################
|
32
|
+
|
33
|
+
attr_accessor :services_by_name
|
34
|
+
attr_accessor :tick_count
|
35
|
+
attr_accessor :service_classes
|
36
|
+
attr_accessor :reload_config
|
37
|
+
attr_accessor :terminate
|
38
|
+
|
39
|
+
############################################################################
|
40
|
+
#
|
41
|
+
#
|
42
|
+
#
|
43
|
+
############################################################################
|
44
|
+
|
45
|
+
class << self
|
46
|
+
def instance
|
47
|
+
@@instance
|
48
|
+
end
|
49
|
+
def register_service(service)
|
50
|
+
@@instance.register_service(service)
|
51
|
+
end
|
52
|
+
def register_service_class(service_class)
|
53
|
+
@@instance.register_service_class(service_class)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
############################################################################
|
58
|
+
#
|
59
|
+
# initialize
|
60
|
+
#
|
61
|
+
############################################################################
|
62
|
+
|
63
|
+
def initialize()
|
64
|
+
@@instance=self
|
65
|
+
@services_by_name={}
|
66
|
+
@service_classes={}
|
67
|
+
@tick_count=0
|
68
|
+
|
69
|
+
ProcessUtil::scan_processes()
|
70
|
+
load_classes()
|
71
|
+
end
|
72
|
+
|
73
|
+
############################################################################
|
74
|
+
#
|
75
|
+
#
|
76
|
+
#
|
77
|
+
############################################################################
|
78
|
+
|
79
|
+
def load_classes()
|
80
|
+
$LOAD_PATH << CLASS_DIR unless($LOAD_PATH.include?(CLASS_DIR))
|
81
|
+
Dir.glob( File.join(CLASS_DIR,"*.rb") ).each do |fn|
|
82
|
+
require( File.basename(fn,".rb") )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
############################################################################
|
87
|
+
#
|
88
|
+
#
|
89
|
+
#
|
90
|
+
############################################################################
|
91
|
+
|
92
|
+
def register_service(service)
|
93
|
+
raise "service is missing name" if(!service.name)
|
94
|
+
raise "service #{service.name} is multiply defined" if(@services_by_name[service.name])
|
95
|
+
@services_by_name[service.name]=service
|
96
|
+
end
|
97
|
+
|
98
|
+
############################################################################
|
99
|
+
#
|
100
|
+
#
|
101
|
+
#
|
102
|
+
############################################################################
|
103
|
+
|
104
|
+
def register_service_class(service_class)
|
105
|
+
@service_classes[ service_class.nice_name ]=service_class
|
106
|
+
end
|
107
|
+
|
108
|
+
############################################################################
|
109
|
+
#
|
110
|
+
# main tick function
|
111
|
+
#
|
112
|
+
############################################################################
|
113
|
+
|
114
|
+
def tick()
|
115
|
+
|
116
|
+
# scan processes... and kill anything we don't recognize
|
117
|
+
ProcessUtil::scan_processes()
|
118
|
+
ProcessUtil::kill_unknown()
|
119
|
+
ProcessUtil::reap()
|
120
|
+
|
121
|
+
# tick each service in turn
|
122
|
+
@services_by_name.values.each do |service|
|
123
|
+
service.tick()
|
124
|
+
end
|
125
|
+
|
126
|
+
@tick_count += 1
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
############################################################################
|
131
|
+
#
|
132
|
+
#
|
133
|
+
#
|
134
|
+
############################################################################
|
135
|
+
|
136
|
+
def match_services(spec)
|
137
|
+
matched={}
|
138
|
+
@services_by_name.each do |sn,s|
|
139
|
+
matched[sn]=s if(s.matches_spec(spec))
|
140
|
+
end
|
141
|
+
matched
|
142
|
+
end
|
143
|
+
|
144
|
+
############################################################################
|
145
|
+
#
|
146
|
+
#
|
147
|
+
#
|
148
|
+
############################################################################
|
149
|
+
|
150
|
+
def apply_config(cfg,notboot=true)
|
151
|
+
|
152
|
+
@services_by_name={}
|
153
|
+
|
154
|
+
cfg.daemon.services.each do |group_name,services|
|
155
|
+
services.services.each do |name,service|
|
156
|
+
params=service.params.merge({ :name => service.name, :group_name => group_name })
|
157
|
+
if(!notboot)
|
158
|
+
params[:initial_state]=:up
|
159
|
+
end
|
160
|
+
svc=service.klass.new(params)
|
161
|
+
|
162
|
+
# the service will register itself
|
163
|
+
# we must store its config block
|
164
|
+
svc.config_node=service
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
@services_by_name.each do |n,v|
|
170
|
+
v.resolve_dependencies()
|
171
|
+
end
|
172
|
+
|
173
|
+
ProcessUtil::build_known_hashes()
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
############################################################################
|
178
|
+
#
|
179
|
+
#
|
180
|
+
#
|
181
|
+
############################################################################
|
182
|
+
|
183
|
+
def run()
|
184
|
+
|
185
|
+
while(true)
|
186
|
+
|
187
|
+
tick()
|
188
|
+
sleep(1)
|
189
|
+
|
190
|
+
#
|
191
|
+
# check for requests
|
192
|
+
#
|
193
|
+
|
194
|
+
if(@reload_config)
|
195
|
+
info("reloading configuration")
|
196
|
+
ProcessWanker::with_logged_rescue("ServiceMgr - reloading configuration") do
|
197
|
+
c=Config::load_config(Config::get_config_path)
|
198
|
+
apply_config(c)
|
199
|
+
end
|
200
|
+
@reload_config=false
|
201
|
+
end
|
202
|
+
|
203
|
+
if(@terminate)
|
204
|
+
info("terminating")
|
205
|
+
break
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
############################################################################
|
213
|
+
#
|
214
|
+
#
|
215
|
+
#
|
216
|
+
############################################################################
|
217
|
+
|
218
|
+
############################################################################
|
219
|
+
#
|
220
|
+
#
|
221
|
+
#
|
222
|
+
############################################################################
|
223
|
+
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
data/lib/util.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
############################################################################
|
2
|
+
#
|
3
|
+
# util.rb
|
4
|
+
#
|
5
|
+
############################################################################
|
6
|
+
|
7
|
+
require 'log'
|
8
|
+
|
9
|
+
module ProcessWanker
|
10
|
+
|
11
|
+
############################################################################
|
12
|
+
#
|
13
|
+
#
|
14
|
+
#
|
15
|
+
############################################################################
|
16
|
+
|
17
|
+
def with_logged_rescue(context=nil,level=Log::ERROR)
|
18
|
+
|
19
|
+
begin
|
20
|
+
yield
|
21
|
+
rescue Exception => e
|
22
|
+
Log::log(context,level) if(context)
|
23
|
+
Log::log(e.message,level)
|
24
|
+
Log::log(e.backtrace.join("\n"),level)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
module_function :with_logged_rescue
|
29
|
+
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{processwanker}
|
5
|
+
s.version = "0.0.7"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Ben Stragnell"]
|
9
|
+
s.cert_chain = ["/Users/ben/gem_certs/gem-public_cert.pem"]
|
10
|
+
s.date = %q{2011-05-05}
|
11
|
+
s.default_executable = %q{pw}
|
12
|
+
s.description = %q{Process monitoring and remote control system}
|
13
|
+
s.email = %q{pw@codepuppies.com}
|
14
|
+
s.executables = ["pw"]
|
15
|
+
s.extra_rdoc_files = ["README", "bin/pw", "lib/config/config.rb", "lib/config/config_auth.rb", "lib/config/config_client.rb", "lib/config/config_client_cluster.rb", "lib/config/config_client_clusters.rb", "lib/config/config_client_host.rb", "lib/config/config_daemon.rb", "lib/config/config_daemon_service.rb", "lib/config/config_daemon_service_dependency.rb", "lib/config/config_daemon_services.rb", "lib/config/config_hook.rb", "lib/config/config_node.rb", "lib/config/config_smtp.rb", "lib/events.rb", "lib/log.rb", "lib/net/net_api.rb", "lib/net/net_client.rb", "lib/net/net_connection.rb", "lib/net/net_server.rb", "lib/net/net_server_client.rb", "lib/net/net_util.rb", "lib/process_util.rb", "lib/pw_app.rb", "lib/service.rb", "lib/service_classes/dummy_service.rb", "lib/service_classes/pid_service.rb", "lib/service_classes/process_service.rb", "lib/service_classes/upstart_service.rb", "lib/service_mgr.rb", "lib/util.rb"]
|
16
|
+
s.files = ["README", "Rakefile", "bin/pw", "lib/config/config.rb", "lib/config/config_auth.rb", "lib/config/config_client.rb", "lib/config/config_client_cluster.rb", "lib/config/config_client_clusters.rb", "lib/config/config_client_host.rb", "lib/config/config_daemon.rb", "lib/config/config_daemon_service.rb", "lib/config/config_daemon_service_dependency.rb", "lib/config/config_daemon_services.rb", "lib/config/config_hook.rb", "lib/config/config_node.rb", "lib/config/config_smtp.rb", "lib/events.rb", "lib/log.rb", "lib/net/net_api.rb", "lib/net/net_client.rb", "lib/net/net_connection.rb", "lib/net/net_server.rb", "lib/net/net_server_client.rb", "lib/net/net_util.rb", "lib/process_util.rb", "lib/pw_app.rb", "lib/service.rb", "lib/service_classes/dummy_service.rb", "lib/service_classes/pid_service.rb", "lib/service_classes/process_service.rb", "lib/service_classes/upstart_service.rb", "lib/service_mgr.rb", "lib/util.rb", "Manifest", "processwanker.gemspec"]
|
17
|
+
s.homepage = %q{http://codepuppies.com/~ben/pw}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Processwanker", "--main", "README"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{processwanker}
|
21
|
+
s.rubygems_version = %q{1.6.2}
|
22
|
+
s.signing_key = %q{/Users/ben/gem_certs/gem-private_key.pem}
|
23
|
+
s.summary = %q{Process monitoring and remote control system}
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
s.specification_version = 3
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<echoe>, [">= 0"])
|
30
|
+
else
|
31
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
35
|
+
end
|
36
|
+
end
|
data.tar.gz.sig
ADDED
Binary file
|