rexec 1.2.1 → 1.2.3
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/README.rdoc +59 -12
- data/bin/daemon-exec +17 -12
- data/lib/rexec.rb +22 -26
- data/lib/rexec/client.rb +2 -14
- data/lib/rexec/connection.rb +138 -146
- data/lib/rexec/daemon.rb +20 -20
- data/lib/rexec/daemon/base.rb +157 -142
- data/lib/rexec/daemon/controller.rb +18 -13
- data/lib/rexec/daemon/pidfile.rb +57 -52
- data/lib/rexec/environment.rb +24 -5
- data/lib/rexec/priviledges.rb +42 -23
- data/lib/rexec/reverse_io.rb +86 -67
- data/lib/rexec/server.rb +86 -53
- data/lib/rexec/task.rb +145 -49
- data/lib/rexec/version.rb +23 -18
- data/test/client.rb +17 -12
- data/test/daemon.rb +17 -12
- data/test/daemon_test.rb +17 -12
- data/test/listing_example.rb +17 -12
- data/test/remote_server_test.rb +18 -13
- data/test/server_test.rb +17 -12
- data/test/task.rb +17 -12
- data/test/task_test.rb +17 -12
- metadata +5 -4
data/lib/rexec/daemon.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
# Copyright (c) 2007, 2009 Samuel
|
2
|
-
#
|
3
|
-
# This program is free software: you can redistribute it and/or modify
|
4
|
-
# it under the terms of the GNU General Public License as published by
|
5
|
-
# the Free Software Foundation, either version 3 of the License, or
|
6
|
-
# (at your option) any later version.
|
1
|
+
# Copyright (c) 2007, 2009, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'rexec/daemon/base'
|
17
22
|
|
18
23
|
module RExec
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#def run_daemon(options = {}, &block)
|
23
|
-
#
|
24
|
-
#end
|
25
|
-
|
26
|
-
end
|
24
|
+
module Daemon
|
25
|
+
|
26
|
+
end
|
27
27
|
end
|
data/lib/rexec/daemon/base.rb
CHANGED
@@ -1,151 +1,166 @@
|
|
1
|
-
# Copyright (c) 2007, 2009 Samuel
|
2
|
-
#
|
3
|
-
# This program is free software: you can redistribute it and/or modify
|
4
|
-
# it under the terms of the GNU General Public License as published by
|
5
|
-
# the Free Software Foundation, either version 3 of the License, or
|
6
|
-
# (at your option) any later version.
|
1
|
+
# Copyright (c) 2007, 2009, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'fileutils'
|
17
22
|
require 'rexec/daemon/controller'
|
18
23
|
require 'rexec/reverse_io'
|
19
24
|
|
20
25
|
module RExec
|
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
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
26
|
+
module Daemon
|
27
|
+
# This class is the base daemon class. If you are writing a daemon, you should inherit from this class.
|
28
|
+
#
|
29
|
+
# The basic structure of a daemon is as follows:
|
30
|
+
#
|
31
|
+
# class Server < RExec::Daemon::Base
|
32
|
+
# def self.run
|
33
|
+
# # Long running process, e.g. web server, game server, etc.
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# Server.daemonize
|
38
|
+
class Base
|
39
|
+
@@var_directory = nil
|
40
|
+
@@log_directory = nil
|
41
|
+
@@pid_directory = nil
|
42
|
+
|
43
|
+
# Return the name of the daemon
|
44
|
+
def self.daemon_name
|
45
|
+
return name.gsub(/[^a-zA-Z0-9]+/, '-')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Base directory for daemon log files / run files
|
49
|
+
def self.var_directory
|
50
|
+
@@var_directory || File.join("", "var")
|
51
|
+
end
|
52
|
+
|
53
|
+
# The directory the daemon will run in (Dir.chdir)
|
54
|
+
def self.working_directory
|
55
|
+
var_directory
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return the directory to store log files in
|
59
|
+
def self.log_directory
|
60
|
+
@@log_directory || File.join(var_directory, "log", daemon_name)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Standard log file for errors
|
64
|
+
def self.err_fn
|
65
|
+
File.join(log_directory, "stderr.log")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Standard log file for normal output
|
69
|
+
def self.log_fn
|
70
|
+
File.join(log_directory, "stdout.log")
|
71
|
+
end
|
72
|
+
|
73
|
+
# Standard location of pid file
|
74
|
+
def self.pid_directory
|
75
|
+
@@pid_directory || File.join(var_directory, "run", daemon_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Standard pid file
|
79
|
+
def self.pid_fn
|
80
|
+
File.join(pid_directory, "#{daemon_name}.pid")
|
81
|
+
end
|
82
|
+
|
83
|
+
# Mark the error log
|
84
|
+
def self.mark_err_log
|
85
|
+
fp = File.open(err_fn, "a")
|
86
|
+
fp.puts "=== Error Log Opened @ #{Time.now.to_s} ==="
|
87
|
+
fp.close
|
88
|
+
end
|
89
|
+
|
90
|
+
# Prints some information relating to daemon startup problems
|
91
|
+
def self.tail_err_log(outp)
|
92
|
+
lines = []
|
93
|
+
|
94
|
+
File.open(err_fn, "r") do |fp|
|
95
|
+
fp.seek_end
|
96
|
+
|
97
|
+
fp.reverse_each_line do |line|
|
98
|
+
lines << line
|
99
|
+
break if line.match("=== Error Log") || line.match("=== Daemon Exception Backtrace")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
lines.reverse_each do |line|
|
104
|
+
outp.puts line
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Check the last few lines of the log file to find out if
|
109
|
+
# the daemon crashed.
|
110
|
+
def self.crashed?
|
111
|
+
File.open(err_fn, "r") do |fp|
|
112
|
+
fp.seek_end
|
113
|
+
|
114
|
+
count = 2
|
115
|
+
fp.reverse_each_line do |line|
|
116
|
+
return true if line.match("=== Daemon Crashed")
|
117
|
+
|
118
|
+
count -= 1
|
119
|
+
|
120
|
+
break if count == 0
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
return false
|
125
|
+
end
|
126
|
+
|
127
|
+
# Corresponds to controller method of the same name
|
128
|
+
def self.daemonize
|
129
|
+
Controller.daemonize(self)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Corresponds to controller method of the same name
|
133
|
+
def self.start
|
134
|
+
Controller.start(self)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Corresponds to controller method of the same name
|
138
|
+
def self.stop
|
139
|
+
Controller.stop(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Corresponds to controller method of the same name
|
143
|
+
def self.status
|
144
|
+
Controller.status(self)
|
145
|
+
end
|
146
|
+
|
147
|
+
# The main function to setup any environment required by the daemon
|
148
|
+
def self.prefork
|
149
|
+
@@var_directory = File.expand_path(@@var_directory) if @@var_directory
|
150
|
+
@@log_directory = File.expand_path(@@log_directory) if @@log_directory
|
151
|
+
@@pid_directory = File.expand_path(@@pid_directory) if @@pid_directory
|
152
|
+
|
153
|
+
FileUtils.mkdir_p(log_directory)
|
154
|
+
FileUtils.mkdir_p(pid_directory)
|
155
|
+
end
|
156
|
+
|
157
|
+
# The main function to start the daemon
|
158
|
+
def self.run
|
159
|
+
end
|
160
|
+
|
161
|
+
# The main function to stop the daemon
|
162
|
+
def self.shutdown
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
151
166
|
end
|
@@ -1,17 +1,22 @@
|
|
1
|
-
# Copyright (c) 2007, 2009 Samuel
|
2
|
-
#
|
3
|
-
# This program is free software: you can redistribute it and/or modify
|
4
|
-
# it under the terms of the GNU General Public License as published by
|
5
|
-
# the Free Software Foundation, either version 3 of the License, or
|
6
|
-
# (at your option) any later version.
|
1
|
+
# Copyright (c) 2007, 2009, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'rexec/daemon/pidfile'
|
17
22
|
require 'rexec/task'
|
@@ -24,7 +29,7 @@ module RExec
|
|
24
29
|
# This module contains functionality related to starting and stopping the daemon, and code for processing command line input.
|
25
30
|
module Controller
|
26
31
|
# This function is called from the daemon executable. It processes ARGV and checks whether the user is asking for
|
27
|
-
#
|
32
|
+
# +start+, +stop+, +restart+ or +status+.
|
28
33
|
def self.daemonize(daemon)
|
29
34
|
#puts "Running in #{WorkingDirectory}, logs in #{LogDirectory}"
|
30
35
|
case !ARGV.empty? && ARGV[0]
|
data/lib/rexec/daemon/pidfile.rb
CHANGED
@@ -1,64 +1,69 @@
|
|
1
|
-
# Copyright (c) 2007, 2009 Samuel
|
2
|
-
#
|
3
|
-
# This program is free software: you can redistribute it and/or modify
|
4
|
-
# it under the terms of the GNU General Public License as published by
|
5
|
-
# the Free Software Foundation, either version 3 of the License, or
|
6
|
-
# (at your option) any later version.
|
1
|
+
# Copyright (c) 2007, 2009, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
module RExec
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
module Daemon
|
23
|
+
# This module controls the storage and retrieval of process id files.
|
24
|
+
module PidFile
|
25
|
+
# Saves the pid for the given daemon
|
26
|
+
def self.store(daemon, pid)
|
27
|
+
File.open(daemon.pid_fn, 'w') {|f| f << pid}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Retrieves the pid for the given daemon
|
31
|
+
def self.recall(daemon)
|
32
|
+
IO.read(daemon.pid_fn).to_i rescue nil
|
33
|
+
end
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
35
|
+
# Removes the pid saved for a particular daemon
|
36
|
+
def self.clear(daemon)
|
37
|
+
if File.exist? daemon.pid_fn
|
38
|
+
FileUtils.rm(daemon.pid_fn)
|
39
|
+
end
|
40
|
+
end
|
29
41
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
FileUtils.rm(daemon.pid_fn)
|
34
|
-
end
|
35
|
-
end
|
42
|
+
# Checks whether the daemon is running by checking the saved pid and checking the corresponding process
|
43
|
+
def self.running(daemon)
|
44
|
+
pid = recall(daemon)
|
36
45
|
|
37
|
-
|
38
|
-
def self.running(daemon)
|
39
|
-
pid = recall(daemon)
|
46
|
+
return false if pid == nil
|
40
47
|
|
41
|
-
|
48
|
+
gpid = Process.getpgid(pid) rescue nil
|
42
49
|
|
43
|
-
|
50
|
+
return gpid != nil ? true : false
|
51
|
+
end
|
44
52
|
|
45
|
-
|
46
|
-
|
53
|
+
# Remove the pid file if the daemon is not running
|
54
|
+
def self.cleanup(daemon)
|
55
|
+
clear(daemon) unless running(daemon)
|
56
|
+
end
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
return :stopped
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
58
|
+
# This function returns the status of the daemon. This can be one of +:running+, +:unknown+ (pid file exists but no
|
59
|
+
# corresponding process can be found) or +:stopped+.
|
60
|
+
def self.status(daemon)
|
61
|
+
if File.exist? daemon.pid_fn
|
62
|
+
return PidFile.running(daemon) ? :running : :unknown
|
63
|
+
else
|
64
|
+
return :stopped
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
64
69
|
end
|