procemon 0.0.1
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/Gemfile +13 -0
- data/Gemfile.lock +72 -0
- data/LICENSE.txt +20 -0
- data/README.md +4 -0
- data/README.rdoc +19 -0
- data/Rakefile +170 -0
- data/VERSION +1 -0
- data/dump/macaddr.rb +95 -0
- data/dump/uuid.rb +324 -0
- data/lib/procemon.rb +55 -0
- data/lib/procemon/function/application.rb +20 -0
- data/lib/procemon/function/argv.rb +84 -0
- data/lib/procemon/function/daemon.rb +188 -0
- data/lib/procemon/function/documentation.rb +10 -0
- data/lib/procemon/function/eval.rb +76 -0
- data/lib/procemon/function/meta/inject_methods.rb +74 -0
- data/lib/procemon/function/name.rb +13 -0
- data/lib/procemon/function/port.rb +35 -0
- data/lib/procemon/function/require.rb +241 -0
- data/lib/procemon/function/str2duck.rb +85 -0
- data/lib/procemon/function/systemu.rb +360 -0
- data/lib/procemon/function/tmp_dir.rb +20 -0
- data/lib/procemon/mpatch/array.rb +59 -0
- data/lib/procemon/mpatch/class.rb +85 -0
- data/lib/procemon/mpatch/exception.rb +0 -0
- data/lib/procemon/mpatch/file.rb +48 -0
- data/lib/procemon/mpatch/hash.rb +82 -0
- data/lib/procemon/mpatch/kernel.rb +9 -0
- data/lib/procemon/mpatch/object.rb +172 -0
- data/lib/procemon/mpatch/process.rb +14 -0
- data/lib/procemon/mpatch/random.rb +43 -0
- data/lib/procemon/mpatch/string.rb +73 -0
- data/lib/procemon/mpatch/yml.rb +11 -0
- data/procemon.gemspec +58 -0
- data/test/test.rb +17 -0
- metadata +86 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module Procemon
|
2
|
+
class << self
|
3
|
+
|
4
|
+
def get_port(mint_port,max_port,host="0.0.0.0")
|
5
|
+
|
6
|
+
require 'socket'
|
7
|
+
mint_port= mint_port.to_i
|
8
|
+
begin
|
9
|
+
server = TCPServer.new(host, mint_port)
|
10
|
+
server.close
|
11
|
+
return mint_port
|
12
|
+
rescue Errno::EADDRINUSE
|
13
|
+
if mint_port < max_port
|
14
|
+
pmint_portort = (mint_port.to_i + 1)
|
15
|
+
retry
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def port_open?(port,host="0.0.0.0")
|
22
|
+
|
23
|
+
require 'socket'
|
24
|
+
begin
|
25
|
+
server = TCPServer.new(host, port.to_i)
|
26
|
+
server.close
|
27
|
+
return true
|
28
|
+
rescue Errno::EADDRINUSE
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,241 @@
|
|
1
|
+
module Kernel
|
2
|
+
|
3
|
+
# load meta-s
|
4
|
+
def meta_load
|
5
|
+
|
6
|
+
# find elements
|
7
|
+
begin
|
8
|
+
Dir.glob( File.join(Dir.pwd, "lib", "**","meta" ,"*.rb") ).each do |one_rb_file|
|
9
|
+
require one_rb_file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
# mount libs
|
16
|
+
def mount_libs
|
17
|
+
|
18
|
+
# load lib files
|
19
|
+
begin
|
20
|
+
Dir.glob(File.join(Dir.pwd, "lib","*.{rb,ru}")).uniq.each do |one_rb_file|
|
21
|
+
require one_rb_file
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# Offline repo activate
|
28
|
+
def mount_modules
|
29
|
+
|
30
|
+
Dir.glob(File.join(Dir.pwd, "{module,modules}","{gem,gems}","**","lib")).select{|f| File.directory?(f)}.each do |one_path|
|
31
|
+
$LOAD_PATH << one_path
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# #Return File_name:File_path
|
37
|
+
def get_files(folder)
|
38
|
+
|
39
|
+
# Pre def. variables
|
40
|
+
begin
|
41
|
+
files = Hash.new
|
42
|
+
end
|
43
|
+
|
44
|
+
# Validation
|
45
|
+
begin
|
46
|
+
# Check that does the folder is absolute or not
|
47
|
+
if folder != File.expand_path(folder)
|
48
|
+
folder = File.expand_path(folder)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get Files list
|
53
|
+
begin
|
54
|
+
Dir[File.join(folder,'**','*')].uniq.each do |file_path|
|
55
|
+
if !File.directory? file_path
|
56
|
+
files[file_path.split(File::SEPARATOR).last.to_sym]= file_path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return file_name:folder
|
62
|
+
return files
|
63
|
+
end
|
64
|
+
|
65
|
+
# require by absolute path directory's files
|
66
|
+
def require_directory(folder)
|
67
|
+
get_files(folder).each do |file_name,file_path|
|
68
|
+
puts "file will be loaded: #{file_name} from\n\t#{file_path}" if $DEBUG
|
69
|
+
if file_path.split('.').last == 'rb'
|
70
|
+
load file_path
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# require sender relative directory's files
|
76
|
+
def require_relative_directory(folder)
|
77
|
+
|
78
|
+
# pre format
|
79
|
+
begin
|
80
|
+
|
81
|
+
path= caller[0].split('.rb:').first.split(File::SEPARATOR)
|
82
|
+
path= path[0..(path.count-2)]
|
83
|
+
|
84
|
+
if !File.directory?(path.join(File::SEPARATOR))
|
85
|
+
path.pop
|
86
|
+
end
|
87
|
+
|
88
|
+
path= File.join(path.join(File::SEPARATOR))
|
89
|
+
|
90
|
+
if path != File.expand_path(path)
|
91
|
+
path= File.expand_path(path)
|
92
|
+
end
|
93
|
+
|
94
|
+
path= File.join(path,folder)
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
# find elements
|
99
|
+
begin
|
100
|
+
tmp_array = Array.new
|
101
|
+
get_files(path).sort.each do |file_name,file_path|
|
102
|
+
if file_path.split('.').last == 'rb'
|
103
|
+
tmp_array.push file_path
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# after format
|
109
|
+
begin
|
110
|
+
tmp_array.uniq!
|
111
|
+
tmp_array.sort!
|
112
|
+
tmp_array.each do |full_path_to_file|
|
113
|
+
require full_path_to_file
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
# generate config from yaml
|
120
|
+
def generate_config(target_config_hash= Application.config)
|
121
|
+
|
122
|
+
# defaults
|
123
|
+
begin
|
124
|
+
require "yaml"
|
125
|
+
if target_config_hash.class != Hash
|
126
|
+
target_config_hash= Hash.new()
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# find elements
|
131
|
+
begin
|
132
|
+
|
133
|
+
Dir.glob(File.join(Dir.pwd, "lib", "**","meta" ,"*.{yaml,yml}")).each do |config_object|
|
134
|
+
|
135
|
+
# defaults
|
136
|
+
begin
|
137
|
+
config_name_elements= config_object.split(File::SEPARATOR)
|
138
|
+
type= config_name_elements.pop.split('.')[0]
|
139
|
+
config_name_elements.pop
|
140
|
+
category= config_name_elements.pop
|
141
|
+
tmp_hash= Hash.new()
|
142
|
+
yaml_data= YAML.load(File.open(config_object))
|
143
|
+
end
|
144
|
+
|
145
|
+
# processing
|
146
|
+
begin
|
147
|
+
if target_config_hash[category].nil?
|
148
|
+
target_config_hash[category]= { type => yaml_data }
|
149
|
+
else
|
150
|
+
target_config_hash[category][type]= yaml_data
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
# update by config
|
159
|
+
begin
|
160
|
+
|
161
|
+
# get config files
|
162
|
+
begin
|
163
|
+
config_yaml_paths= Array.new()
|
164
|
+
Dir.glob(File.join(Dir.pwd, "{config,conf}","*.{yaml,yml}")).uniq.each do |one_path|
|
165
|
+
|
166
|
+
case true
|
167
|
+
|
168
|
+
when one_path.downcase.include?('default')
|
169
|
+
config_yaml_paths[0]= one_path
|
170
|
+
|
171
|
+
when one_path.downcase.include?('development')
|
172
|
+
config_yaml_paths[1]= one_path
|
173
|
+
|
174
|
+
when one_path.downcase.include?('test')
|
175
|
+
config_yaml_paths[2]= one_path
|
176
|
+
|
177
|
+
when one_path.downcase.include?('production')
|
178
|
+
config_yaml_paths[3]= one_path
|
179
|
+
|
180
|
+
else
|
181
|
+
config_yaml_paths[config_yaml_paths.count]= one_path
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
config_yaml_paths.select!{|x| x != nil }
|
187
|
+
end
|
188
|
+
|
189
|
+
# params config load
|
190
|
+
unless Application.config_file.nil?
|
191
|
+
begin
|
192
|
+
path= File.expand_path(Application.config_file,"r")
|
193
|
+
File.open(path)
|
194
|
+
config_yaml_paths.push(path)
|
195
|
+
rescue Exception
|
196
|
+
config_yaml_paths.push(Application.config_file)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# load to last lvl environment
|
201
|
+
begin
|
202
|
+
config_yaml_paths.each do |one_yaml_file_path|
|
203
|
+
begin
|
204
|
+
yaml_data= YAML.load(File.open(one_yaml_file_path))
|
205
|
+
Application.config.deep_merge!(yaml_data)
|
206
|
+
|
207
|
+
unless Application.environment.nil?
|
208
|
+
if one_yaml_file_path.include?(Application.environment.to_s)
|
209
|
+
break
|
210
|
+
end
|
211
|
+
end
|
212
|
+
rescue Exception
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
def generate_documentation(boolean= false,keyword= "generate")
|
222
|
+
boolean= false if boolean.nil?
|
223
|
+
if boolean == true
|
224
|
+
|
225
|
+
document_generators= Array.new
|
226
|
+
tmp_path_container= Dir.glob(File.join(Dir.pwd, "docs", "**", "*.{rb,ru}"))
|
227
|
+
tmp_path_container.each do |one_path|
|
228
|
+
if one_path.include? keyword
|
229
|
+
document_generators.push one_path
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
document_generators.each do |docs_file_path|
|
234
|
+
require docs_file_path
|
235
|
+
end
|
236
|
+
|
237
|
+
Process.exit!
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# duck typing
|
2
|
+
class String
|
3
|
+
def duck
|
4
|
+
|
5
|
+
begin
|
6
|
+
if self == self.to_f.to_s
|
7
|
+
return self.to_f
|
8
|
+
end
|
9
|
+
rescue NoMethodError
|
10
|
+
end
|
11
|
+
|
12
|
+
begin
|
13
|
+
if self == self.to_i.to_s
|
14
|
+
return self.to_i
|
15
|
+
end
|
16
|
+
rescue NoMethodError
|
17
|
+
end
|
18
|
+
|
19
|
+
begin
|
20
|
+
if self.gsub(":","") == self.to_datetime.to_s.gsub(
|
21
|
+
"T"," ").gsub("+"," +").gsub(":","")
|
22
|
+
return self.to_datetime
|
23
|
+
end
|
24
|
+
rescue Exception
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
if self == self.to_datetime.to_s
|
29
|
+
return self.to_datetime
|
30
|
+
end
|
31
|
+
rescue Exception
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
if self == self.to_date.to_s
|
36
|
+
return self.to_date
|
37
|
+
end
|
38
|
+
rescue Exception
|
39
|
+
end
|
40
|
+
|
41
|
+
begin
|
42
|
+
if self == "true"
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
rescue NoMethodError
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
begin
|
50
|
+
if self == "false"
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
rescue NoMethodError
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
string_input= self
|
58
|
+
contain= nil
|
59
|
+
["[", "]","^","$","*","/"].each do |one_sym|
|
60
|
+
if string_input.include? one_sym
|
61
|
+
contain ||= true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if contain == true
|
65
|
+
string_regexp= Regexp.new(string_input).inspect#.gsub('\\','')
|
66
|
+
string_regexp= string_regexp[1..(string_regexp.length-2)]
|
67
|
+
if string_input == string_regexp
|
68
|
+
return Regexp.new(string_input)
|
69
|
+
else
|
70
|
+
raise ArgumentError,"invalid input string"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
rescue ArgumentError
|
74
|
+
end
|
75
|
+
|
76
|
+
begin
|
77
|
+
if self == self.to_s.to_s
|
78
|
+
return self.to_s
|
79
|
+
end
|
80
|
+
rescue NoMethodError
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
alias_method :to_duck, :duck
|
85
|
+
end
|
@@ -0,0 +1,360 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'socket'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'rbconfig'
|
7
|
+
require 'thread'
|
8
|
+
|
9
|
+
class Object
|
10
|
+
def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end
|
11
|
+
end
|
12
|
+
|
13
|
+
class SystemUniversal
|
14
|
+
#
|
15
|
+
# constants
|
16
|
+
#
|
17
|
+
SystemUniversal::VERSION = '2.5.2' unless SystemUniversal.send(:const_defined?, :VERSION)
|
18
|
+
def SystemUniversal.version() SystemUniversal::VERSION end
|
19
|
+
def version() SystemUniversal::VERSION end
|
20
|
+
#
|
21
|
+
# class methods
|
22
|
+
#
|
23
|
+
|
24
|
+
@host = Socket.gethostname
|
25
|
+
@ppid = Process.ppid
|
26
|
+
@pid = Process.pid
|
27
|
+
@turd = ENV['SYSTEMU_TURD']
|
28
|
+
|
29
|
+
c = begin; ::RbConfig::CONFIG; rescue NameError; ::Config::CONFIG; end
|
30
|
+
ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
|
31
|
+
@ruby = if system('%s -e 42' % ruby)
|
32
|
+
ruby
|
33
|
+
else
|
34
|
+
system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG')
|
35
|
+
end
|
36
|
+
|
37
|
+
class << SystemUniversal
|
38
|
+
%w( host ppid pid ruby turd ).each{|a| attr_accessor a}
|
39
|
+
|
40
|
+
def quote(*words)
|
41
|
+
words.map{|word| word.inspect}.join(' ')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# instance methods
|
47
|
+
#
|
48
|
+
|
49
|
+
def initialize argv, opts = {}, &block
|
50
|
+
getopt = getopts opts
|
51
|
+
|
52
|
+
@argv = argv
|
53
|
+
@block = block
|
54
|
+
|
55
|
+
@stdin = getopt[ ['stdin', 'in', '0', 0] ]
|
56
|
+
@stdout = getopt[ ['stdout', 'out', '1', 1] ]
|
57
|
+
@stderr = getopt[ ['stderr', 'err', '2', 2] ]
|
58
|
+
@env = getopt[ 'env' ]
|
59
|
+
@cwd = getopt[ 'cwd' ]
|
60
|
+
|
61
|
+
@host = getopt[ 'host', self.class.host ]
|
62
|
+
@ppid = getopt[ 'ppid', self.class.ppid ]
|
63
|
+
@pid = getopt[ 'pid', self.class.pid ]
|
64
|
+
@ruby = getopt[ 'ruby', self.class.ruby ]
|
65
|
+
end
|
66
|
+
|
67
|
+
def systemu
|
68
|
+
tmpdir do |tmp|
|
69
|
+
c = child_setup tmp
|
70
|
+
status = nil
|
71
|
+
|
72
|
+
begin
|
73
|
+
thread = nil
|
74
|
+
|
75
|
+
quietly{
|
76
|
+
IO.popen "#{ quote(@ruby) } #{ quote(c['program']) }", 'r+' do |pipe|
|
77
|
+
line = pipe.gets
|
78
|
+
case line
|
79
|
+
when %r/^pid: \d+$/
|
80
|
+
cid = Integer line[%r/\d+/]
|
81
|
+
else
|
82
|
+
begin
|
83
|
+
buf = pipe.read
|
84
|
+
buf = "#{ line }#{ buf }"
|
85
|
+
e = Marshal.load buf
|
86
|
+
raise unless Exception === e
|
87
|
+
raise e
|
88
|
+
rescue
|
89
|
+
raise "systemu: Error - process interrupted!\n#{ buf }\n"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
thread = new_thread cid, @block if @block
|
93
|
+
pipe.read rescue nil
|
94
|
+
end
|
95
|
+
}
|
96
|
+
status = $?
|
97
|
+
ensure
|
98
|
+
if thread
|
99
|
+
begin
|
100
|
+
class << status
|
101
|
+
attr 'thread'
|
102
|
+
end
|
103
|
+
status.instance_eval{ @thread = thread }
|
104
|
+
rescue
|
105
|
+
42
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if @stdout or @stderr
|
111
|
+
open(c['stdout']){|f| relay f => @stdout} if @stdout
|
112
|
+
open(c['stderr']){|f| relay f => @stderr} if @stderr
|
113
|
+
status
|
114
|
+
else
|
115
|
+
[status, IO.read(c['stdout']), IO.read(c['stderr'])]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def quote *args, &block
|
121
|
+
SystemUniversal.quote(*args, &block)
|
122
|
+
end
|
123
|
+
|
124
|
+
def new_thread cid, block
|
125
|
+
q = Queue.new
|
126
|
+
Thread.new(cid) do |cid|
|
127
|
+
current = Thread.current
|
128
|
+
current.abort_on_exception = true
|
129
|
+
q.push current
|
130
|
+
block.call cid
|
131
|
+
end
|
132
|
+
q.pop
|
133
|
+
end
|
134
|
+
|
135
|
+
def child_setup tmp
|
136
|
+
stdin = File.expand_path(File.join(tmp, 'stdin'))
|
137
|
+
stdout = File.expand_path(File.join(tmp, 'stdout'))
|
138
|
+
stderr = File.expand_path(File.join(tmp, 'stderr'))
|
139
|
+
program = File.expand_path(File.join(tmp, 'program'))
|
140
|
+
config = File.expand_path(File.join(tmp, 'config'))
|
141
|
+
|
142
|
+
if @stdin
|
143
|
+
open(stdin, 'w'){|f| relay @stdin => f}
|
144
|
+
else
|
145
|
+
FileUtils.touch stdin
|
146
|
+
end
|
147
|
+
FileUtils.touch stdout
|
148
|
+
FileUtils.touch stderr
|
149
|
+
|
150
|
+
c = {}
|
151
|
+
c['argv'] = @argv
|
152
|
+
c['env'] = @env
|
153
|
+
c['cwd'] = @cwd
|
154
|
+
c['stdin'] = stdin
|
155
|
+
c['stdout'] = stdout
|
156
|
+
c['stderr'] = stderr
|
157
|
+
c['program'] = program
|
158
|
+
open(config, 'w'){|f| Marshal.dump(c, f)}
|
159
|
+
|
160
|
+
open(program, 'w'){|f| f.write child_program(config)}
|
161
|
+
|
162
|
+
c
|
163
|
+
end
|
164
|
+
|
165
|
+
def quietly
|
166
|
+
v = $VERBOSE
|
167
|
+
$VERBOSE = nil
|
168
|
+
yield
|
169
|
+
ensure
|
170
|
+
$VERBOSE = v
|
171
|
+
end
|
172
|
+
|
173
|
+
def child_program config
|
174
|
+
<<-program
|
175
|
+
# encoding: utf-8
|
176
|
+
|
177
|
+
PIPE = STDOUT.dup
|
178
|
+
begin
|
179
|
+
config = Marshal.load(IO.read('#{ config }'))
|
180
|
+
|
181
|
+
argv = config['argv']
|
182
|
+
env = config['env']
|
183
|
+
cwd = config['cwd']
|
184
|
+
stdin = config['stdin']
|
185
|
+
stdout = config['stdout']
|
186
|
+
stderr = config['stderr']
|
187
|
+
|
188
|
+
Dir.chdir cwd if cwd
|
189
|
+
env.each{|k,v| ENV[k.to_s] = v.to_s} if env
|
190
|
+
|
191
|
+
STDIN.reopen stdin
|
192
|
+
STDOUT.reopen stdout
|
193
|
+
STDERR.reopen stderr
|
194
|
+
|
195
|
+
PIPE.puts "pid: \#{ Process.pid }"
|
196
|
+
PIPE.flush # the process is ready yo!
|
197
|
+
PIPE.close
|
198
|
+
|
199
|
+
exec *argv
|
200
|
+
rescue Exception => e
|
201
|
+
PIPE.write Marshal.dump(e) rescue nil
|
202
|
+
exit 42
|
203
|
+
end
|
204
|
+
program
|
205
|
+
end
|
206
|
+
|
207
|
+
def relay srcdst
|
208
|
+
src, dst, ignored = srcdst.to_a.first
|
209
|
+
if src.respond_to? 'read'
|
210
|
+
while((buf = src.read(8192))); dst << buf; end
|
211
|
+
else
|
212
|
+
if src.respond_to?(:each_line)
|
213
|
+
src.each_line{|buf| dst << buf}
|
214
|
+
else
|
215
|
+
src.each{|buf| dst << buf}
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def tmpdir d = Dir.tmpdir, max = 42, &b
|
221
|
+
i = -1 and loop{
|
222
|
+
i += 1
|
223
|
+
|
224
|
+
tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
|
225
|
+
|
226
|
+
begin
|
227
|
+
Dir.mkdir tmp
|
228
|
+
rescue Errno::EEXIST
|
229
|
+
raise if i >= max
|
230
|
+
next
|
231
|
+
end
|
232
|
+
|
233
|
+
break(
|
234
|
+
if b
|
235
|
+
begin
|
236
|
+
b.call tmp
|
237
|
+
ensure
|
238
|
+
FileUtils.rm_rf tmp unless SystemU.turd
|
239
|
+
end
|
240
|
+
else
|
241
|
+
tmp
|
242
|
+
end
|
243
|
+
)
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
def getopts opts = {}
|
248
|
+
lambda do |*args|
|
249
|
+
keys, default, ignored = args
|
250
|
+
catch(:opt) do
|
251
|
+
[keys].flatten.each do |key|
|
252
|
+
[key, key.to_s, key.to_s.intern].each do |key|
|
253
|
+
throw :opt, opts[key] if opts.has_key?(key)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
default
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# some monkeypatching for JRuby
|
263
|
+
if defined? JRUBY_VERSION
|
264
|
+
require 'jruby'
|
265
|
+
java_import org.jruby.RubyProcess
|
266
|
+
|
267
|
+
class SystemUniversal
|
268
|
+
def systemu
|
269
|
+
split_argv = JRuby::PathHelper.smart_split_command @argv
|
270
|
+
process = java.lang.Runtime.runtime.exec split_argv.to_java(:string)
|
271
|
+
|
272
|
+
stdout, stderr = [process.input_stream, process.error_stream].map do |stream|
|
273
|
+
StreamReader.new(stream)
|
274
|
+
end
|
275
|
+
|
276
|
+
exit_code = process.wait_for
|
277
|
+
field = process.get_class.get_declared_field("pid")
|
278
|
+
field.set_accessible(true)
|
279
|
+
pid = field.get(process)
|
280
|
+
[
|
281
|
+
RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code, pid),
|
282
|
+
stdout.join,
|
283
|
+
stderr.join
|
284
|
+
]
|
285
|
+
end
|
286
|
+
|
287
|
+
class StreamReader
|
288
|
+
def initialize(stream)
|
289
|
+
@data = ""
|
290
|
+
@thread = Thread.new do
|
291
|
+
reader = java.io.BufferedReader.new java.io.InputStreamReader.new(stream)
|
292
|
+
|
293
|
+
while line = reader.read_line
|
294
|
+
@data << line << "\n"
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def join
|
300
|
+
@thread.join
|
301
|
+
@data
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
SystemU = SystemUniversal unless defined? SystemU
|
310
|
+
Systemu = SystemUniversal unless defined? Systemu
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
if $0 == __FILE__
|
325
|
+
#
|
326
|
+
# date
|
327
|
+
#
|
328
|
+
date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
|
329
|
+
|
330
|
+
status, stdout, stderr = systemu date
|
331
|
+
p [status, stdout, stderr]
|
332
|
+
|
333
|
+
status = systemu date, 1=>(stdout = '')
|
334
|
+
p [status, stdout]
|
335
|
+
|
336
|
+
status = systemu date, 2=>(stderr = '')
|
337
|
+
p [status, stderr]
|
338
|
+
#
|
339
|
+
# sleep
|
340
|
+
#
|
341
|
+
sleep = %q( ruby -e" p(sleep(1)) " )
|
342
|
+
status, stdout, stderr = systemu sleep
|
343
|
+
p [status, stdout, stderr]
|
344
|
+
|
345
|
+
sleep = %q( ruby -e" p(sleep(42)) " )
|
346
|
+
status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid}
|
347
|
+
p [status, stdout, stderr]
|
348
|
+
#
|
349
|
+
# env
|
350
|
+
#
|
351
|
+
env = %q( ruby -e" p ENV['A'] " )
|
352
|
+
status, stdout, stderr = systemu env, :env => {'A' => 42}
|
353
|
+
p [status, stdout, stderr]
|
354
|
+
#
|
355
|
+
# cwd
|
356
|
+
#
|
357
|
+
env = %q( ruby -e" p Dir.pwd " )
|
358
|
+
status, stdout, stderr = systemu env, :cwd => Dir.tmpdir
|
359
|
+
p [status, stdout, stderr]
|
360
|
+
end
|