system_run 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +3 -0
  4. data/Rakefile +25 -0
  5. data/lib/system_run.rb +105 -0
  6. data/system_run.gemspec +21 -0
  7. metadata +49 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f8880b54914f20294364a0bb3695c9a5fda5aa66
4
+ data.tar.gz: fb73e272798e02d8e1357a6a5f4ef942a455c670
5
+ SHA512:
6
+ metadata.gz: 3b7ec264ee01e09d5c9466eabb486d12dcdace8da23faf9f144ce8a32783ff8a4dc6a8a356a37cc65e5507e0a6e6f40c60df4eba2d5c919cf34ed48e8d6650bd
7
+ data.tar.gz: 69ea30062b708f6f69145f106b36e2c2634595cced51bad4b39804c075d9d294fc0dd8a9d7098fb20824a0e62bde45a8d5609edc47aab56e155dd4ffc6fac1a1
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Sonja Biedermann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # system_run
2
+ Tiny wrapper for running commands.
3
+ Inspired by systemu.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rubygems/package_task'
3
+
4
+ # require 'rake/testtask'
5
+ # Rake::TestTask.new do |t|
6
+ # t.libs << "test"
7
+ # t.test_files = FileList['./test/tc_*.rb']
8
+ # t.verbose = false
9
+ # end
10
+
11
+ spec = eval(File.read('system_run.gemspec'))
12
+ Gem::PackageTask.new(spec) do |pkg|
13
+ pkg.need_zip = true
14
+ pkg.need_tar = true
15
+ `rm pkg/* -rf`
16
+ `ln -sf #{pkg.name}.gem pkg/system_run.gem`
17
+ end
18
+
19
+ task :push => :gem do |r|
20
+ `gem push pkg/system_run.gem`
21
+ end
22
+
23
+ task :install => :gem do |r|
24
+ `sudo gem install pkg/system_run.gem`
25
+ end
data/lib/system_run.rb ADDED
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+ require 'timeout'
3
+ require 'tempfile'
4
+
5
+ module System
6
+ def self.run(cmd, *args, timeout: nil, env: {}, capture: :default, file: nil, cwd: '.', on_timeout: nil)
7
+ cmd = cmd.dup << ' ' << args.join(' ')
8
+ env = env.dup.map { |k, v| [k.to_s, v.to_s] }.to_h
9
+
10
+ raise ArgumentError, "file(s) must be instance of File or Tempfile" unless file.nil? || file.all? { |f| f.is_a?(File) || f.is_a?(Tempfile) }
11
+ out, err = case capture
12
+ when :default then
13
+ raise ArgumentError, "invalid file redirects for default capture, expected array of two" unless file.nil? || file.is_a?(Array) && file.size == 2
14
+ file ? [file.first, file.last] : [Tempfile.new('sysrun-out'), Tempfile.new('sysrun-err')]
15
+ when :out then [file || Tempfile.new('sysrun-out'), '/dev/null']
16
+ when :err then ['/dev/null', file || Tempfile.new('sysrun-err')]
17
+ when :both then [file || Tempfile.new('sysrun-outerr')] * 2
18
+ else raise ArgumentError, "unknown capture: #{capture}"
19
+ end
20
+
21
+ pid = spawn env, cmd, out: out, err: err, chdir: cwd
22
+ status = wait_or_kill pid, timeout, on_timeout
23
+ [out, err].each { |f| f.rewind if f.respond_to? :rewind }
24
+
25
+ file ? status : case capture
26
+ when :default then [status, out.read, err.read]
27
+ when :out, :both then [status, out.read]
28
+ when :err then [status, err.read]
29
+ end
30
+ ensure
31
+ [out, err].each { |f| f.unlink if f.is_a?(Tempfile) && f.path&.include?('sysrun') }
32
+ end
33
+
34
+ def self.wait_or_kill(pid, timeout=nil, on_timeout=nil)
35
+ begin
36
+ Timeout::timeout(timeout) do
37
+ Process.wait pid
38
+ end
39
+ rescue Timeout::Error
40
+ if on_timeout then
41
+ on_timeout.call pid
42
+ else
43
+ Process.kill 9, pid
44
+ end
45
+ Process.wait pid
46
+ end
47
+
48
+ $?
49
+ end
50
+
51
+ private_class_method :wait_or_kill
52
+ end
53
+
54
+ if __FILE__ == $0 then
55
+ date = %q(ruby -e "t = Time.now; STDOUT.puts t; STDERR.puts t")
56
+
57
+ # capture stdout and stderr separately.
58
+ status, stdout, stderr = System.run date
59
+ p [status, stdout, stderr]
60
+
61
+ # capture only stdout, discard stderr.
62
+ status, stdout = System.run date, capture: :out
63
+ p [status, stdout]
64
+
65
+ # capture stderr and discard stdout.
66
+ status, stderr = System.run date, capture: :err
67
+ p [status, stderr]
68
+
69
+ # capture both stdout and stderr.
70
+ status, all = System.run date, capture: :both
71
+ p [status, all]
72
+
73
+ # capture stderr. kill process after 2 seconds.
74
+ loop_time = %q(ruby -e "loop { STDERR.puts Time.now.to_i; sleep 2 }")
75
+ status, stderr = System.run loop_time, capture: :err, timeout: 2
76
+ p [status, stderr]
77
+
78
+ # set timeout to 2 seconds and provide an action for when timeout occurs. default
79
+ # action is to send signal 9. this will be overridden!
80
+ status, _, _ = System.run %q(ruby -e "sleep 10"), timeout: 2, on_timeout: ->(pid) do
81
+ puts 'oh no, request timed out'
82
+ Process.kill 9, pid
83
+ end
84
+ p status
85
+
86
+ # set environment variables.
87
+ env = %q(ruby -e "puts ENV['HELLO']")
88
+ status, stdout = System.run env, env: {'HELLO' => 'WORLD'}, capture: :out
89
+ p [status, stdout]
90
+
91
+ # switch to a different directory before executing the command.
92
+ dir = %q(ruby -e "puts Dir.pwd")
93
+ status, stdout = System.run dir, cwd: Dir.tmpdir, capture: :out
94
+ p [status, stdout]
95
+
96
+ # write to a file instead of loading output into a string.
97
+ out = File.open 'test_out.txt', 'w+'
98
+ err = File.open 'test_err.txt', 'w+'
99
+
100
+ hello = %q(ruby -e "STDERR.puts 'hello'; STDOUT.puts 'world'")
101
+ status = System.run hello, file: [out, err]
102
+ p [status, out.read, err.read]
103
+
104
+ [out, err].each { |f| f.close; File.unlink f.path }
105
+ end
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "system_run"
3
+ s.version = "1.0"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.license = "MIT"
6
+ s.summary = "Tiny wrapper for running commands. Inspired by systemu."
7
+
8
+ s.description = "see https://github.com/biederfrau/system_run"
9
+
10
+ s.files = Dir['{example/**/*,server/**/*,lib/**/*,cockpit/**/*,contrib/logo*,contrib/Screen*,log/**/*}'] + %w(LICENSE Rakefile system_run.gemspec README.md)
11
+ s.require_path = 'lib'
12
+ s.extra_rdoc_files = ['README.md']
13
+ s.test_files = []
14
+
15
+ s.required_ruby_version = '>=2.3.0'
16
+
17
+ s.authors = ['Sonja Biedermann']
18
+
19
+ s.email = 's.bdrmnn@gmail.com'
20
+ s.homepage = 'https://github.com/biederfrau/system_run'
21
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: system_run
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Sonja Biedermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-02 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: see https://github.com/biederfrau/system_run
14
+ email: s.bdrmnn@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files:
18
+ - README.md
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - Rakefile
23
+ - lib/system_run.rb
24
+ - system_run.gemspec
25
+ homepage: https://github.com/biederfrau/system_run
26
+ licenses:
27
+ - MIT
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 2.3.0
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.5.1
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Tiny wrapper for running commands. Inspired by systemu.
49
+ test_files: []