sproc 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/sproc/core.rb +54 -31
- data/lib/sproc/version.rb +1 -1
- data/sproc.gemspec +18 -17
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8938c9977d79ffd99b2526dc698d66f33c0afc225121307a7cbf79fe9284acdb
|
4
|
+
data.tar.gz: 0fcd34ab808b76a121a581443b0bf9c075e8bf92633a112c406b11b11691b9ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4da5cce84127eb2b3fda62ba9cb893b588ad1e68b173ad8ef558d8c7f4945c089c74dea20e7be62e7e685bd7efbcf91a6d0616bcc413a7fb4663731151c25da
|
7
|
+
data.tar.gz: 7abf027ed86e29fbc531698feec84c318fda64d3138fa3e22bce81c1f2ef7a79b73aa255274de5f0265453c8df59964a616b912cb41cb55b8e692cd36b0d1fae
|
data/Gemfile.lock
CHANGED
data/lib/sproc/core.rb
CHANGED
@@ -7,10 +7,8 @@ module SProc
|
|
7
7
|
# Defines the shell under which to invoke the sub-process
|
8
8
|
module ShellType
|
9
9
|
SHELL_TYPES = [
|
10
|
-
#
|
11
|
-
|
12
|
-
# - For current ubuntu, it seems to be 'dash'
|
13
|
-
NATIVE = 0,
|
10
|
+
# Start the process without any shell
|
11
|
+
NONE = 0,
|
14
12
|
# Will create a 'bash' instance and run the subprocess
|
15
13
|
# within that instance.
|
16
14
|
BASH = 1
|
@@ -58,10 +56,13 @@ module SProc
|
|
58
56
|
# from the process as it is running (default nil)
|
59
57
|
# @param stderr_callback a callback that will receive all stderr output
|
60
58
|
# from the process as it is running (default nil)
|
59
|
+
# @param env a hash containing key/value pairs of strings that
|
60
|
+
# set the environment variable 'key' to 'value'. If value
|
61
|
+
# is nil, that env variable is unset
|
61
62
|
#
|
62
63
|
# example callback signature: def my_stdout_cb(line)
|
63
|
-
def initialize(type
|
64
|
-
stderr_callback
|
64
|
+
def initialize(type: ShellType::NONE, stdout_callback: nil,
|
65
|
+
stderr_callback: nil, env: {})
|
65
66
|
@run_opts = {
|
66
67
|
type: type,
|
67
68
|
stdout_callback: stdout_callback,
|
@@ -69,10 +70,12 @@ module SProc
|
|
69
70
|
}
|
70
71
|
@runner = TaskRunner.new(@run_opts)
|
71
72
|
@execution_thread = nil
|
73
|
+
@env = env
|
72
74
|
end
|
73
75
|
|
74
76
|
# Return the execution state of this SubProcess. Note that it is not
|
75
77
|
# identical with the life-cycle of the underlying ProcessStatus object
|
78
|
+
#
|
76
79
|
# @return current ExecutionState
|
77
80
|
def execution_state
|
78
81
|
return ExecutionState::NOT_STARTED if @execution_thread.nil?
|
@@ -106,18 +109,25 @@ module SProc
|
|
106
109
|
raise RuntimeError("Unhandled process status: #{status.inspect}")
|
107
110
|
end
|
108
111
|
|
109
|
-
# Start the process
|
110
|
-
#
|
112
|
+
# Start the sub-process and block until it has completed.
|
113
|
+
#
|
114
|
+
#
|
115
|
+
# @cmd the command to execute
|
116
|
+
# @args an array with all arguments to the cmd
|
117
|
+
# @opts a hash with options that influence the spawned process
|
118
|
+
# the supported options are: chdir umask unsetenv_others
|
119
|
+
# See Process.spawn for definitions
|
120
|
+
#
|
111
121
|
# @return this SubProcess instance
|
112
122
|
def exec_sync(cmd, *args, **opts)
|
113
|
-
exec(true, cmd, *args, **opts)
|
123
|
+
exec(true, @env, cmd, *args, **opts)
|
114
124
|
end
|
115
125
|
|
116
126
|
# Start the process non-blocking. Use one of the wait... methods
|
117
127
|
# to later block on the process.
|
118
128
|
# @return this SubProcess instance
|
119
129
|
def exec_async(cmd, *args, **opts)
|
120
|
-
exec(false, cmd, *args, **opts)
|
130
|
+
exec(false, @env, cmd, *args, **opts)
|
121
131
|
end
|
122
132
|
|
123
133
|
# check if this process has completed with exit code 0
|
@@ -170,7 +180,7 @@ module SProc
|
|
170
180
|
# # start 3 processes asyncronously
|
171
181
|
# nof_processes = 3
|
172
182
|
# p_array = (1..nof_processes).collect do
|
173
|
-
# SubProcess.new(SubProcess::
|
183
|
+
# SubProcess.new(SubProcess::NONE).exec_async('ping', ['127.0.0.1'])
|
174
184
|
# end
|
175
185
|
#
|
176
186
|
# # block until a process completes and then immediately start a new process
|
@@ -218,13 +228,13 @@ module SProc
|
|
218
228
|
|
219
229
|
private
|
220
230
|
|
221
|
-
def exec(synch, cmd, *args, **opts)
|
222
|
-
raise
|
231
|
+
def exec(synch, env, cmd, *args, **opts)
|
232
|
+
raise 'Subprocess already running!' unless @execution_thread.nil? || !@execution_thread.alive?
|
223
233
|
|
224
234
|
# kick-off a fresh task runner and execution thread
|
225
235
|
@runner = TaskRunner.new(@run_opts)
|
226
236
|
@execution_thread = Thread.new do
|
227
|
-
@runner.execute(cmd, *args, **opts)
|
237
|
+
@runner.execute(env, cmd, *args, **opts)
|
228
238
|
end
|
229
239
|
@execution_thread.join if synch
|
230
240
|
self
|
@@ -238,8 +248,11 @@ module SProc
|
|
238
248
|
|
239
249
|
include ShellType
|
240
250
|
|
251
|
+
# Restrict the options to Process.spawn that we support to these
|
252
|
+
SUPPORTED_SPAWN_OPTS = %i[chdir umask unsetenv_others]
|
253
|
+
|
241
254
|
DEFAULT_OPTS = {
|
242
|
-
type:
|
255
|
+
type: NONE,
|
243
256
|
stdout_callback: nil,
|
244
257
|
stderr_callback: nil
|
245
258
|
}.freeze
|
@@ -250,12 +263,12 @@ module SProc
|
|
250
263
|
end
|
251
264
|
|
252
265
|
# Runs the process and blocks until it is completed or aborted.
|
253
|
-
# The stdout and stdin streams are continuously read in
|
266
|
+
# The stdout and stdin streams are continuously read in parallel with
|
254
267
|
# the process execution.
|
255
|
-
def execute(cmd, *args, **opts)
|
268
|
+
def execute(env, cmd, *args, **opts)
|
256
269
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
257
270
|
begin
|
258
|
-
shell_out_via_popen(cmd, *args, **opts)
|
271
|
+
shell_out_via_popen(env, cmd, *args, **opts)
|
259
272
|
rescue StandardError => e
|
260
273
|
@task_info[:exception] = e
|
261
274
|
end
|
@@ -266,14 +279,26 @@ module SProc
|
|
266
279
|
|
267
280
|
private
|
268
281
|
|
269
|
-
def
|
282
|
+
def valid_opts(**opts)
|
283
|
+
return opts if opts.nil? || opts.empty?
|
284
|
+
|
285
|
+
supported = {}
|
286
|
+
SUPPORTED_SPAWN_OPTS.each { |o| supported[o] = opts[o] if opts.has_key?(o) }
|
287
|
+
supported
|
288
|
+
end
|
289
|
+
|
290
|
+
def shell_out_via_popen(env, cmd, *args, **opts)
|
291
|
+
opts = valid_opts(**opts)
|
270
292
|
args = case @opts[:type]
|
271
|
-
when
|
272
|
-
when BASH
|
293
|
+
when NONE then get_args_native(cmd, *args, **opts)
|
294
|
+
when BASH then get_args_bash(cmd, *args, **opts)
|
273
295
|
else raise ArgumentError, "Unknown task type: #{@type}!!"
|
274
296
|
end
|
297
|
+
|
275
298
|
SProc.logger&.debug { "Start: #{task_info[:cmd_str]}" }
|
276
|
-
|
299
|
+
SProc.logger&.debug { "Supplying env: #{env}" } unless env.nil?
|
300
|
+
SProc.logger&.debug { "Spawn options: #{opts}" } unless opts.nil?
|
301
|
+
Open3.popen3(env, *args) do |stdin, stdout, stderr, thread|
|
277
302
|
@task_info[:popen_thread] = thread
|
278
303
|
threads = do_while_process_running(stdin, stdout, stderr)
|
279
304
|
@task_info[:process_status] = thread.value
|
@@ -306,16 +331,14 @@ module SProc
|
|
306
331
|
def process_output_stream(stream, stream_cache = nil,
|
307
332
|
process_callback = nil)
|
308
333
|
Thread.new do
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
stream_cache << raw_line unless stream_cache.nil?
|
313
|
-
end
|
314
|
-
rescue IOError => e
|
315
|
-
l = SProc.logger
|
316
|
-
l&.warn { 'Stream closed before all output were read!' }
|
317
|
-
l&.warn { e.message }
|
334
|
+
until (raw_line = stream.gets).nil?
|
335
|
+
process_callback&.call(raw_line)
|
336
|
+
stream_cache << raw_line unless stream_cache.nil?
|
318
337
|
end
|
338
|
+
rescue IOError => e
|
339
|
+
l = SProc.logger
|
340
|
+
l&.warn { 'Stream closed before all output were read!' }
|
341
|
+
l&.warn { e.message }
|
319
342
|
end
|
320
343
|
end
|
321
344
|
end
|
data/lib/sproc/version.rb
CHANGED
data/sproc.gemspec
CHANGED
@@ -1,39 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'lib/sproc/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
6
|
+
spec.name = 'sproc'
|
7
7
|
spec.version = SProc::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
8
|
+
spec.authors = ['Anders Rillbert']
|
9
|
+
spec.email = ['anders.rillbert@kutso.se']
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
|
14
|
-
spec.
|
15
|
-
spec.
|
11
|
+
spec.summary = 'Spawn commands as asynch/synch subprocesses.'
|
12
|
+
spec.description = 'Easier invokation of asynch/synch commands with '\
|
13
|
+
'a reasonable easy and flexible interface for processing stdout and stderr'
|
14
|
+
spec.homepage = 'https://github.com/rillbert/sproc'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
16
17
|
|
17
|
-
spec.metadata[
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
18
19
|
|
19
|
-
spec.metadata[
|
20
|
-
spec.metadata[
|
21
|
-
spec.metadata[
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
22
|
+
spec.metadata['changelog_uri'] = spec.homepage
|
22
23
|
|
23
24
|
# Specify which files should be added to the gem when it is released.
|
24
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
27
28
|
end
|
28
|
-
spec.bindir =
|
29
|
+
spec.bindir = 'exe'
|
29
30
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = [
|
31
|
+
spec.require_paths = ['lib']
|
31
32
|
|
32
33
|
# Developer dependencies
|
33
|
-
spec.add_development_dependency
|
34
|
+
spec.add_development_dependency 'minitest', '~> 5.1'
|
34
35
|
|
35
36
|
# Uncomment to register a new dependency of your gem
|
36
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
37
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
37
38
|
|
38
39
|
# For more information and examples about making a new gem, checkout our
|
39
40
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sproc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anders Rillbert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -24,7 +24,8 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.1'
|
27
|
-
description:
|
27
|
+
description: Easier invokation of asynch/synch commands with a reasonable easy and
|
28
|
+
flexible interface for processing stdout and stderr
|
28
29
|
email:
|
29
30
|
- anders.rillbert@kutso.se
|
30
31
|
executables: []
|
@@ -71,5 +72,5 @@ requirements: []
|
|
71
72
|
rubygems_version: 3.1.4
|
72
73
|
signing_key:
|
73
74
|
specification_version: 4
|
74
|
-
summary:
|
75
|
+
summary: Spawn commands as asynch/synch subprocesses.
|
75
76
|
test_files: []
|