em-process-buffer 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +22 -0
- data/README.md +28 -0
- data/Rakefile +2 -0
- data/bin/buffer-process +158 -0
- data/em-process-buffer.gemspec +22 -0
- data/examples/in-out +9 -0
- data/examples/simple.rb +32 -0
- data/examples/timer.rb +6 -0
- data/lib/core_ext/process.rb +10 -0
- data/lib/eventmachine/line_processor.rb +13 -0
- data/lib/eventmachine/pid_poller.rb +22 -0
- data/lib/eventmachine/process_buffer.rb +85 -0
- data/lib/eventmachine/process_buffer/version.rb +5 -0
- data/lib/eventmachine/process_buffer/watcher.rb +60 -0
- data/lib/eventmachine/profile.rb +16 -0
- metadata +97 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/eventmachine/eventmachine
|
3
|
+
revision: 9473a1b181ed1997e3156d960b2bb2783f508191
|
4
|
+
specs:
|
5
|
+
eventmachine (1.0.0.rc.4)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: .
|
9
|
+
specs:
|
10
|
+
em-process-buffer (0.0.1)
|
11
|
+
eventmachine (~> 1.0.0.rc.4)
|
12
|
+
posix-spawn (~> 0.3.6)
|
13
|
+
|
14
|
+
GEM
|
15
|
+
remote: https://rubygems.org/
|
16
|
+
specs:
|
17
|
+
posix-spawn (0.3.6)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
em-process-buffer!
|
24
|
+
eventmachine!
|
25
|
+
posix-spawn (= 0.3.6)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Dave Newman
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# EM Process Buffer
|
2
|
+
|
3
|
+
A restartable process watcher that buffers STDIN and STDOUT.
|
4
|
+
|
5
|
+
This is designed to watch long running processes. The watching process can be independently restarted without killing the watched process. In the mean time STDOUT is buffered in memory until the watching process is restarted so no output is missed.
|
6
|
+
|
7
|
+
Creates named pipes on disk for STDIN and STDOUT.
|
8
|
+
|
9
|
+
QUIT will gracefully stop the watching process. TERM will kill the watcher and the buffered process.
|
10
|
+
|
11
|
+
## Example
|
12
|
+
|
13
|
+
# In terminal 1 start the process and watcher
|
14
|
+
$ ruby examples/simple.rb
|
15
|
+
watcher started pid=7652
|
16
|
+
process started pid=7815
|
17
|
+
[7815] [STDIN 0.0] hello
|
18
|
+
[7815] [STDIN 0.99] hello
|
19
|
+
|
20
|
+
# In terminal 2 kill the watcher
|
21
|
+
$ kill 7652
|
22
|
+
|
23
|
+
# back in terminal 1 restart the watcher
|
24
|
+
$ ruby examples/simple.rb
|
25
|
+
watcher started pid=8418
|
26
|
+
found running process pid=7869 pid_file=tmp/simple.pid
|
27
|
+
[7869] [STDIN 5.34] hello
|
28
|
+
[7869] [STDIN 6.84] hello
|
data/Rakefile
ADDED
data/bin/buffer-process
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'posix/spawn'
|
5
|
+
|
6
|
+
module Process
|
7
|
+
def self.alive?(pid)
|
8
|
+
begin
|
9
|
+
Process.kill(0, pid)
|
10
|
+
true
|
11
|
+
rescue Errno::ESRCH
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.child command
|
17
|
+
POSIX::Spawn::Child.new command
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class IOBuffer
|
22
|
+
def buffer
|
23
|
+
@buffer ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def tick
|
27
|
+
# puts "[#{Process.pid}] [#{self.class.name}] tick"
|
28
|
+
|
29
|
+
if IO.select([io_in], nil, nil, 0.5)
|
30
|
+
begin
|
31
|
+
incoming = io_in.read_nonblock 1024
|
32
|
+
# p incoming
|
33
|
+
if incoming
|
34
|
+
buffer << incoming
|
35
|
+
end
|
36
|
+
rescue EOFError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
item = nil
|
42
|
+
while buffer.any?
|
43
|
+
item = buffer.shift
|
44
|
+
io_out.write item
|
45
|
+
end
|
46
|
+
rescue Errno::EPIPE
|
47
|
+
buffer.unshift item
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class IOBufferIn < IOBuffer
|
53
|
+
# named_pipe > IO
|
54
|
+
|
55
|
+
attr_reader :io_out
|
56
|
+
|
57
|
+
def initialize pipe_in_file, io_out
|
58
|
+
@pipe_in_file, @io_out = pipe_in_file, io_out
|
59
|
+
io_out.sync = true
|
60
|
+
|
61
|
+
system "mkfifo #{@pipe_in_file}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def io_in
|
65
|
+
@io_in ||= File.open(@pipe_in_file, File::NONBLOCK + File::RDONLY)
|
66
|
+
end
|
67
|
+
|
68
|
+
def cleanup
|
69
|
+
@io_in.close if @io_in
|
70
|
+
system "rm -f #{@pipe_in_file}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class IOBufferOut < IOBuffer
|
75
|
+
# IO > named pipe
|
76
|
+
|
77
|
+
attr_reader :io_in
|
78
|
+
attr_reader :io_out
|
79
|
+
|
80
|
+
def initialize io_in, pipe_out_file
|
81
|
+
@pipe_out_file, @io_in = pipe_out_file, io_in
|
82
|
+
|
83
|
+
system "mkfifo #{@pipe_out_file}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def io_out
|
87
|
+
@io_out ||= begin
|
88
|
+
io_out = File.open(@pipe_out_file, 'w+')
|
89
|
+
io_out.sync = true
|
90
|
+
io_out
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def cleanup
|
95
|
+
@io_out.close if @io_out
|
96
|
+
system "rm -f #{@pipe_out_file}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
pipe_directory = working_directory = Process.child('pwd').out.strip
|
102
|
+
pid_file = nil
|
103
|
+
|
104
|
+
opts = OptionParser.new do |opts|
|
105
|
+
opts.banner = "Usage: #{$0} [-d pipe_directory] [-C working_directory] [-p pid_file] command"
|
106
|
+
|
107
|
+
opts.separator ""
|
108
|
+
opts.on("-d", "--directory directory", "pipe directory") { |dir|
|
109
|
+
pipe_directory = File.expand_path(dir)
|
110
|
+
}
|
111
|
+
opts.on("-C", "--directory directory", "working directory") { |dir|
|
112
|
+
working_directory = File.expand_path(dir)
|
113
|
+
}
|
114
|
+
opts.on("-p", "--pid pid_file", "pid file") { |file|
|
115
|
+
pid_file = File.expand_path(file)
|
116
|
+
}
|
117
|
+
|
118
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
119
|
+
puts opts
|
120
|
+
abort
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
opts.parse!(ARGV)
|
125
|
+
|
126
|
+
command = ARGV.first
|
127
|
+
|
128
|
+
pipe_stdin_file, pipe_stdout_file = "#{pipe_directory}/pipe_stdin", "#{pipe_directory}/pipe_stdout"
|
129
|
+
|
130
|
+
pid, children, stdin_buffer, stdout_buffer = nil, nil, nil, nil
|
131
|
+
|
132
|
+
begin
|
133
|
+
Dir.chdir(working_directory) do
|
134
|
+
pid, stdin, stdout = POSIX::Spawn::popen4("exec #{command} 2>&1")
|
135
|
+
|
136
|
+
File.write(pid_file, pid) if pid_file
|
137
|
+
puts "process started with pid=#{pid}"
|
138
|
+
|
139
|
+
stdin_buffer = IOBufferIn.new(pipe_stdin_file, stdin)
|
140
|
+
stdout_buffer = IOBufferOut.new(stdout, pipe_stdout_file)
|
141
|
+
|
142
|
+
loop do
|
143
|
+
stdout_buffer.tick
|
144
|
+
stdin_buffer.tick
|
145
|
+
|
146
|
+
if Process.waitpid(pid, Process::WNOHANG)
|
147
|
+
puts "process exited pid=#{pid}"
|
148
|
+
break
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
ensure
|
153
|
+
puts "cleaning up"
|
154
|
+
stdin_buffer.cleanup if stdin_buffer
|
155
|
+
stdout_buffer.cleanup if stdout_buffer
|
156
|
+
|
157
|
+
Process.child "rm -f #{pid_file}" if pid_file
|
158
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'eventmachine/process_buffer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "em-process-buffer"
|
8
|
+
gem.version = EM::ProcessBuffer::VERSION
|
9
|
+
gem.authors = ["Dave Newman"]
|
10
|
+
gem.email = ["dave@whatupdave.com"]
|
11
|
+
gem.description = %q{A restartable process watcher that buffers STDIN and STDOUT}
|
12
|
+
gem.summary = %q{A restartable process watcher that buffers STDIN and STDOUT}
|
13
|
+
gem.homepage = "https://github.com/minefold/em-process-buffer"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = %w(bin lib)
|
19
|
+
|
20
|
+
gem.add_dependency "eventmachine", "~>1.0.0.rc.4"
|
21
|
+
gem.add_dependency "posix-spawn", "~>0.3.6"
|
22
|
+
end
|
data/examples/in-out
ADDED
data/examples/simple.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift File.join(__FILE__, '../../lib')
|
2
|
+
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'eventmachine/process_buffer'
|
5
|
+
require 'eventmachine/profile'
|
6
|
+
|
7
|
+
module Watcher
|
8
|
+
def post_init
|
9
|
+
started_at = Time.now
|
10
|
+
EM.add_periodic_timer(1) do
|
11
|
+
send_stdin 'hello'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_started
|
16
|
+
puts "process started pid=#{pid}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def process_exited
|
20
|
+
puts "process exited pid=#{pid}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def receive_stdout line
|
24
|
+
puts "[#{pid}] #{line}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
EM.run do
|
29
|
+
puts "watcher started pid=#{Process.pid}"
|
30
|
+
cmd = File.join(File.expand_path(File.dirname(__FILE__)), 'in-out')
|
31
|
+
EM.buffer_process 'tmp/simple.pid', 'tmp/simple', cmd, {}, Watcher
|
32
|
+
end
|
data/examples/timer.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module EM
|
2
|
+
module PidPoller
|
3
|
+
def self.on_exit pid, *a, &b
|
4
|
+
cb = EM::Callback *a, &b
|
5
|
+
poller = EM.add_periodic_timer(1) do
|
6
|
+
state = process_alive?(pid)
|
7
|
+
unless state
|
8
|
+
poller.cancel
|
9
|
+
cb.call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
cb
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.process_alive? pid
|
16
|
+
Process.kill(0, pid)
|
17
|
+
true
|
18
|
+
rescue Errno::ESRCH
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
require 'posix/spawn'
|
4
|
+
require 'core_ext/process'
|
5
|
+
require 'eventmachine/pid_poller'
|
6
|
+
require 'eventmachine/line_processor'
|
7
|
+
require 'eventmachine/process_buffer/watcher'
|
8
|
+
|
9
|
+
module EM
|
10
|
+
module ProcessBuffer
|
11
|
+
BIN = File.expand_path File.join(__FILE__, '../../../bin')
|
12
|
+
|
13
|
+
def self.spawn_detached cmd, environment = {}
|
14
|
+
begin
|
15
|
+
pid, stdin, stdout, stderr = POSIX::Spawn::popen4(environment, cmd)
|
16
|
+
Process.detach pid
|
17
|
+
return pid, stdin, stdout, stderr
|
18
|
+
rescue Errno::EAGAIN # Resource temporarily unavailable
|
19
|
+
retry
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.start_process pipe_directory, working_directory, pid_file, command, environment, handler, *args, &block
|
24
|
+
buffer_command = %Q{#{BIN}/buffer-process -d #{pipe_directory} -C #{working_directory} -p #{pid_file} "#{command}"}
|
25
|
+
buffer_pid, stdin, stdout, stderr = spawn_detached buffer_command, environment
|
26
|
+
Process.detach buffer_pid
|
27
|
+
|
28
|
+
wait = EM.add_periodic_timer(0.5) do
|
29
|
+
begin
|
30
|
+
if Process.waitpid(buffer_pid, Process::WNOHANG)
|
31
|
+
stdin.close
|
32
|
+
stdout.gets
|
33
|
+
wait.cancel
|
34
|
+
|
35
|
+
puts "process exited pid=#{buffer_pid}"
|
36
|
+
|
37
|
+
elsif File.exist?(pid_file)
|
38
|
+
stdin.close
|
39
|
+
stdout.gets
|
40
|
+
wait.cancel
|
41
|
+
|
42
|
+
c = Class.new(EM::ProcessBuffer::Watcher) { include handler }
|
43
|
+
watcher = c.new pid_file, pipe_directory, working_directory, *args
|
44
|
+
|
45
|
+
watcher.process_started
|
46
|
+
watcher.attach_to_process
|
47
|
+
|
48
|
+
block.call watcher if block_given?
|
49
|
+
end
|
50
|
+
rescue Errno::ECHILD
|
51
|
+
# waiting...
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.attach_to_process pid, pipe_directory, working_directory, pid_file, command, handler, *args
|
57
|
+
c = Class.new(EM::ProcessBuffer::Watcher) { include handler }
|
58
|
+
watcher = c.new pid_file, pipe_directory, working_directory, *args
|
59
|
+
watcher.attach_to_process
|
60
|
+
watcher.process_reattached
|
61
|
+
|
62
|
+
yield watcher if block_given?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.buffer_process pid_file, working_directory, command, environment, handler, *args, &block
|
67
|
+
pipe_directory = working_directory
|
68
|
+
|
69
|
+
FileUtils.mkdir_p working_directory
|
70
|
+
|
71
|
+
if File.exist?(pid_file)
|
72
|
+
pid = File.read(pid_file).strip.to_i
|
73
|
+
|
74
|
+
if Process.alive?(pid)
|
75
|
+
puts "found running process pid=#{pid} pid_file=#{pid_file}"
|
76
|
+
ProcessBuffer.attach_to_process pid, pipe_directory, working_directory, pid_file, command, handler, *args, &block
|
77
|
+
else
|
78
|
+
puts "found dead process pid=#{pid} pid_file=#{pid_file}"
|
79
|
+
ProcessBuffer.start_process pipe_directory, working_directory, pid_file, command, environment, handler, *args, &block
|
80
|
+
end
|
81
|
+
else
|
82
|
+
ProcessBuffer.start_process pipe_directory, working_directory, pid_file, command, environment, handler, *args, &block
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module EM
|
2
|
+
module ProcessBuffer
|
3
|
+
|
4
|
+
class Watcher
|
5
|
+
attr_reader :pid, :pid_file, :pipe_directory, :working_directory
|
6
|
+
|
7
|
+
def initialize pid_file, pipe_directory, working_directory, *args
|
8
|
+
@pid_file = pid_file
|
9
|
+
@pipe_directory = pipe_directory
|
10
|
+
@working_directory = working_directory
|
11
|
+
@pid = File.read(pid_file).strip.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_init
|
15
|
+
end
|
16
|
+
|
17
|
+
def receive_stdout line
|
18
|
+
puts ">> #{line}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_started
|
22
|
+
puts "watched process started"
|
23
|
+
end
|
24
|
+
|
25
|
+
def process_watched
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_exited
|
29
|
+
puts "watched process exited"
|
30
|
+
end
|
31
|
+
|
32
|
+
def pipe_stdin
|
33
|
+
File.join pipe_directory, 'pipe_stdin'
|
34
|
+
end
|
35
|
+
|
36
|
+
def pipe_stdout
|
37
|
+
File.join pipe_directory, 'pipe_stdout'
|
38
|
+
end
|
39
|
+
|
40
|
+
def attach_to_process
|
41
|
+
EM.attach(File.open(pipe_stdout, File::NONBLOCK + File::RDONLY), LineProcessor) do |lp|
|
42
|
+
lp.on_line = method(:receive_stdout)
|
43
|
+
end
|
44
|
+
|
45
|
+
EM::PidPoller.on_exit pid, method(:process_exited)
|
46
|
+
|
47
|
+
EM.next_tick {
|
48
|
+
post_init
|
49
|
+
process_watched
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def send_stdin line
|
54
|
+
File.open(pipe_stdin, 'w+') do |f|
|
55
|
+
f.write "#{line}\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module EM
|
2
|
+
def self.profile
|
3
|
+
started_at = Time.now
|
4
|
+
iterations = 0
|
5
|
+
iteration_started_at = Time.now
|
6
|
+
|
7
|
+
EM.add_periodic_timer(1) do
|
8
|
+
iterations += 1
|
9
|
+
total_delta = ((Time.now - started_at) - iterations)
|
10
|
+
iteration_delta = (Time.now - iteration_started_at) - 1
|
11
|
+
iteration_started_at = Time.now
|
12
|
+
|
13
|
+
puts "iteration: #{iteration_delta.round(4)} total:#{total_delta.round(4)}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em-process-buffer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dave Newman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.0.rc.4
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.0.rc.4
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: posix-spawn
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.3.6
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.3.6
|
46
|
+
description: A restartable process watcher that buffers STDIN and STDOUT
|
47
|
+
email:
|
48
|
+
- dave@whatupdave.com
|
49
|
+
executables:
|
50
|
+
- buffer-process
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- Gemfile
|
56
|
+
- Gemfile.lock
|
57
|
+
- LICENSE.txt
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- bin/buffer-process
|
61
|
+
- em-process-buffer.gemspec
|
62
|
+
- examples/in-out
|
63
|
+
- examples/simple.rb
|
64
|
+
- examples/timer.rb
|
65
|
+
- lib/core_ext/process.rb
|
66
|
+
- lib/eventmachine/line_processor.rb
|
67
|
+
- lib/eventmachine/pid_poller.rb
|
68
|
+
- lib/eventmachine/process_buffer.rb
|
69
|
+
- lib/eventmachine/process_buffer/version.rb
|
70
|
+
- lib/eventmachine/process_buffer/watcher.rb
|
71
|
+
- lib/eventmachine/profile.rb
|
72
|
+
homepage: https://github.com/minefold/em-process-buffer
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- bin
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.8.23
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: A restartable process watcher that buffers STDIN and STDOUT
|
97
|
+
test_files: []
|