pdi 1.0.0.pre.alpha → 1.0.0.pre.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7934ad85a3ff2d1c40beb617ca4d1d0ad24aaa3b937bb09409836ef12b245f06
4
- data.tar.gz: d4a096374986562781a18905a8e9ea64039750f22e82e3b67d386143c31b2915
3
+ metadata.gz: e653f6aed9fd26cce60e4f84cfdf662e0be847f40828142dd28fcc6118150cc7
4
+ data.tar.gz: 6ab7d8da5c628dc867d0607bcb3a3db6a5b4c030f07d91adc3f47516a2b3350f
5
5
  SHA512:
6
- metadata.gz: c3f8ecf38e493e95100bfba8e92da5c344e629b89268c484ddb03834f32e8627e150e54705ca034176c63255c29db87c2b87b2ded8a5daf9033b161e57bdef5e
7
- data.tar.gz: 0b299a6e8466c26de5c9dfada312beaae2a171c913b35dcba06ad2d34fb7a5cb9a82f1d48bd972bc08912acffed6f4e4941ad2665ab5a80fe6add18bacb71d00
6
+ metadata.gz: 2e2688a153fea7a256e80a9e682b6488e71923d2752e32f37c23a39c7899f33faf2ffd99c91b5770e4e4279dd0af0ea9f3bdd6d52057b9780d6f798f7a44fedc
7
+ data.tar.gz: 66f618cc1203d313091cd849403501c127907a719f2b6503792cffe606f02062d0f2f31e179a45395e4460c47245de5461c1b78496208ad5ddf68437f7889558
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PDI
1
+ # Pdi
2
2
 
3
3
  ---
4
4
 
@@ -36,14 +36,14 @@ Pull Requests are welcome for:
36
36
 
37
37
  ## Examples
38
38
 
39
- All examples assume PDI has been installed to your home directory: `~/data-integration`.
39
+ All examples assume Pdi has been installed to your home directory: `~/data-integration`.
40
40
 
41
41
  ### Creating a Spoon Instance
42
42
 
43
- `PDI::Spoon` is the common interface you will use when interacting with PDI. It will use Pan and Kitchen for executing Spoon commands.
43
+ `Pdi::Spoon` is the common interface you will use when interacting with Pdi. It will use Pan and Kitchen for executing Spoon commands.
44
44
 
45
45
  ```ruby
46
- spoon = PDI::Spoon.new(dir: `~/data-integration`)
46
+ spoon = Pdi::Spoon.new(dir: `~/data-integration`)
47
47
  ```
48
48
 
49
49
  Note: You can also override the names of the scripts using the `kitchen` and `pan` constructor keyword arguments. The defaults are `kitchen.sh` and `pan.sh`, respectively.
@@ -52,7 +52,7 @@ Note: You can also override the names of the scripts using the `kitchen` and `pa
52
52
 
53
53
  ```ruby
54
54
  options = {
55
- level: PDI::Spoon::Level::DETAILED,
55
+ level: Pdi::Spoon::Level::DETAILED,
56
56
  name: 'update_address',
57
57
  repository: 'transformations/demographics',
58
58
  params: {
@@ -66,12 +66,12 @@ result = spoon.run(options)
66
66
 
67
67
  `Spoon#run` will return:
68
68
 
69
- * `PDI::Spoon::Result` upon a successful run.
70
- * If a non-zero exit code was returned then a `PDI::Spoon::PanError` or `PDI::Spoon::KitchenError` will be raised.
69
+ * `Pdi::Spoon::Result` upon a successful run.
70
+ * If a non-zero exit code was returned then a `Pdi::Spoon::PanError` or `Pdi::Spoon::KitchenError` will be raised.
71
71
 
72
72
  You can access the raw command line results by tapping into the execution attribute of the result or error object.
73
73
 
74
- Note: Not all options are currently supported. See PDI's official references for [Pan](https://help.pentaho.com/Documentation/6.1/0L0/0Y0/070/000) and [Kitchen](https://help.pentaho.com/Documentation/6.1/0L0/0Y0/070/010) to see all options.
74
+ Note: Not all options are currently supported. See Pdi's official references for [Pan](https://help.pentaho.com/Documentation/6.1/0L0/0Y0/070/000) and [Kitchen](https://help.pentaho.com/Documentation/6.1/0L0/0Y0/070/010) to see all options.
75
75
 
76
76
  ## Contributing
77
77
 
@@ -7,20 +7,22 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ require_relative 'status'
11
+
12
+ module Pdi
11
13
  class Executor
12
14
  # General return object for an execution call result.
13
15
  class Result
14
- attr_reader :cmd,
15
- :code,
16
- :out_and_err,
17
- :pid
16
+ extend Forwardable
17
+ acts_as_hashable
18
+
19
+ attr_reader :args, :status
20
+
21
+ def_delegators :status, :code, :out, :err, :pid
18
22
 
19
- def initialize(cmd, code, out_and_err, pid)
20
- @cmd = cmd
21
- @code = code
22
- @out_and_err = out_and_err
23
- @pid = pid
23
+ def initialize(args:, status: {})
24
+ @args = args
25
+ @status = Status.make(status)
24
26
 
25
27
  freeze
26
28
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Pdi
11
+ class Executor
12
+ # General return object for describing the operating system return data.
13
+ class Status
14
+ acts_as_hashable
15
+
16
+ attr_reader :code, :out, :err, :pid
17
+
18
+ def initialize(code:, out: '', err: '', pid:)
19
+ @code = code
20
+ @out = out
21
+ @err = err
22
+ @pid = pid
23
+
24
+ freeze
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/pdi/executor.rb CHANGED
@@ -9,22 +9,24 @@
9
9
 
10
10
  require_relative 'executor/result'
11
11
 
12
- module PDI
12
+ module Pdi
13
13
  # This class is the library's "metal" layer, the one which actually makes the system call and
14
14
  # interacts with the operating system (through Ruby's standard library.)
15
15
  class Executor
16
- SPACE = ' '
16
+ def run(args)
17
+ args = Array(args).map(&:to_s)
17
18
 
18
- def run(*args)
19
- cmd = args.flatten.join(SPACE)
19
+ out, err, status = Open3.capture3(*args)
20
20
 
21
- Open3.popen2e(cmd) do |_stdin, stdout_and_stderr, wait_thr|
22
- pid = wait_thr.pid
23
- code = wait_thr.value.to_s.split(SPACE).last.to_i
24
- out_and_err = stdout_and_stderr.read
25
-
26
- Result.new(cmd, code, out_and_err, pid)
27
- end
21
+ Result.new(
22
+ args: args,
23
+ status: {
24
+ code: status.exitstatus,
25
+ out: out,
26
+ err: err,
27
+ pid: status.pid
28
+ }
29
+ )
28
30
  end
29
31
  end
30
32
  end
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
12
  # This class subclasses Ruby's StandardError and provides a mapping to custom Kitchen
13
13
  # specific error codes to messages.
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
12
  class Options
13
13
  # This class can form Pentaho-specific command-line arguments.
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
12
  class Options
13
13
  module Level
@@ -9,7 +9,7 @@
9
9
 
10
10
  require_relative 'arg'
11
11
 
12
- module PDI
12
+ module Pdi
13
13
  class Spoon
14
14
  class Options
15
15
  # This class sub-classes Arg and knows how to form param key-value pair arguments.
@@ -12,7 +12,7 @@ require_relative 'options/level'
12
12
  require_relative 'options/param'
13
13
  require_relative 'pan_error'
14
14
 
15
- module PDI
15
+ module Pdi
16
16
  class Spoon
17
17
  # This class serves as the input for executing a transformation or job through Pan or Kitchen.
18
18
  class Options
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
12
  # This class subclasses Ruby's StandardError and provides a mapping to custom Pan
13
13
  # specific error codes to messages.
@@ -7,9 +7,9 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
- # This class knows how to parse the output of a Pan#version call.
12
+ # This class knows how to parse feedback from Pentaho and make sense of it.
13
13
  class Parser
14
14
  NEW_LINE = "\n"
15
15
 
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
10
+ module Pdi
11
11
  class Spoon
12
12
  # General return object for wrapping up a execution call result (execution) and
13
13
  # a usable result (value)
data/lib/pdi/spoon.rb CHANGED
@@ -11,15 +11,16 @@ require_relative 'spoon/options'
11
11
  require_relative 'spoon/parser'
12
12
  require_relative 'spoon/result'
13
13
 
14
- module PDI
15
- # This class is the main wrapper for PDI's pan and kitchen scripts.
14
+ module Pdi
15
+ # This class is the main wrapper for Pdi's pan and kitchen scripts.
16
16
  class Spoon
17
17
  DEFAULT_KITCHEN = 'kitchen.sh'
18
18
  DEFAULT_PAN = 'pan.sh'
19
19
 
20
- attr_reader :dir, :kitchen, :pan
20
+ attr_reader :args, :dir, :kitchen, :pan
21
21
 
22
22
  def initialize(
23
+ args: [],
23
24
  dir:,
24
25
  kitchen: DEFAULT_KITCHEN,
25
26
  pan: DEFAULT_PAN
@@ -28,6 +29,7 @@ module PDI
28
29
  assert_required(:kitchen, kitchen)
29
30
  assert_required(:pan, pan)
30
31
 
32
+ @args = Array(args)
31
33
  @dir = dir.to_s
32
34
  @kitchen = kitchen.to_s
33
35
  @pan = pan.to_s
@@ -37,30 +39,28 @@ module PDI
37
39
  freeze
38
40
  end
39
41
 
42
+ # Returns a Spoon::Result instance when PDI returns error code 0 or else raises
43
+ # a KitchenError since Kitchen was used to run the version command.
40
44
  def version
41
- args = [
42
- kitchen_path,
43
- Options::Arg.new(Options::Arg::Key::VERSION)
44
- ]
45
+ final_args = [kitchen_path] + args + [Options::Arg.new(Options::Arg::Key::VERSION)]
45
46
 
46
- result = executor.run(args)
47
- version_line = parser.version(result.out_and_err)
47
+ result = executor.run(final_args)
48
+ version_line = parser.version(result.out)
49
+
50
+ raise(KitchenError, result) if result.code != 0
48
51
 
49
52
  Result.new(result, version_line)
50
53
  end
51
54
 
55
+ # Returns an Executor::Result instance when PDI returns error code 0 or else raises
56
+ # a PanError (transformation) or KitchenError (job).
52
57
  def run(options)
53
- options = Options.make(options)
54
-
55
- args = [
56
- pan_path
57
- ] + options.to_args
58
-
59
- result = executor.run(args)
60
-
61
- raise(options.error_constant, result) if result.code != 0
58
+ options = Options.make(options)
59
+ final_args = [pan_path] + args + options.to_args
62
60
 
63
- Result.new(result, result.code)
61
+ executor.run(final_args).tap do |result|
62
+ raise(options.error_constant, result) if result.code != 0
63
+ end
64
64
  end
65
65
 
66
66
  private
data/lib/pdi/version.rb CHANGED
@@ -7,6 +7,6 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- module PDI
11
- VERSION = '1.0.0-alpha'
10
+ module Pdi
11
+ VERSION = '1.0.0-alpha.1'
12
12
  end
data/lib/pdi.rb CHANGED
@@ -8,6 +8,7 @@
8
8
  #
9
9
 
10
10
  require 'acts_as_hashable'
11
+ require 'forwardable'
11
12
  require 'open3'
12
13
 
13
14
  require_relative 'pdi/executor'
data/pdi.gemspec CHANGED
@@ -4,11 +4,11 @@ require './lib/pdi/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'pdi'
7
- s.version = PDI::VERSION
8
- s.summary = 'Fill out summary'
7
+ s.version = Pdi::VERSION
8
+ s.summary = 'Ruby wrapper for invoking Pentaho Data Integration'
9
9
 
10
10
  s.description = <<-DESCRIPTION
11
- Fill out description.
11
+ Pentaho Data Integration allows for the creation of ETL transformation and jobs. This library allows those ETL tasks to be executed from Ruby.
12
12
  DESCRIPTION
13
13
 
14
14
  s.authors = ['Matthew Ruggio']
@@ -11,4 +11,4 @@ output(){
11
11
  output "output to stdout"
12
12
  error "output to sterr"
13
13
 
14
- exit 0
14
+ exit $1
@@ -9,19 +9,33 @@
9
9
 
10
10
  require 'spec_helper'
11
11
 
12
- describe PDI::Spoon::PanError do
12
+ describe Pdi::Spoon::PanError do
13
13
  describe 'initialization' do
14
14
  [1, 2, 3, 7, 8, 9].each do |code|
15
15
  specify "code #{code} should have message" do
16
- execution = PDI::Executor::Result.new('', code, '', 123)
17
- expect(described_class.new(execution).message).not_to eq('Unknown')
16
+ result = Pdi::Executor::Result.new(
17
+ args: [],
18
+ status: {
19
+ code: code,
20
+ pid: 123
21
+ }
22
+ )
23
+
24
+ expect(described_class.new(result).message).not_to eq('Unknown')
18
25
  end
19
26
  end
20
27
 
21
28
  [-1, 0, 4, 5, 6, 10, 11].each do |code|
22
29
  specify "code #{code} should not have message" do
23
- execution = PDI::Executor::Result.new('', code, '', 123)
24
- expect(described_class.new(execution).message).to eq('Unknown')
30
+ result = Pdi::Executor::Result.new(
31
+ args: [],
32
+ status: {
33
+ code: code,
34
+ pid: 123
35
+ }
36
+ )
37
+
38
+ expect(described_class.new(result).message).to eq('Unknown')
25
39
  end
26
40
  end
27
41
  end
@@ -9,7 +9,7 @@
9
9
 
10
10
  require 'spec_helper'
11
11
 
12
- describe PDI::Spoon::Options::Arg do
12
+ describe Pdi::Spoon::Options::Arg do
13
13
  let(:key) { :param }
14
14
  let(:value) { 'v1' }
15
15
  let(:value_with_space) { 'v 1' }
@@ -9,7 +9,7 @@
9
9
 
10
10
  require 'spec_helper'
11
11
 
12
- describe PDI::Spoon::Options::Param do
12
+ describe Pdi::Spoon::Options::Param do
13
13
  let(:key) { 'k1' }
14
14
  let(:value) { 'v1' }
15
15
  let(:value_with_space) { 'v 1' }
@@ -9,7 +9,7 @@
9
9
 
10
10
  require 'spec_helper'
11
11
 
12
- describe PDI::Spoon::Options do
12
+ describe Pdi::Spoon::Options do
13
13
  describe '#to_args' do
14
14
  let(:params) do
15
15
  {
@@ -9,7 +9,8 @@
9
9
 
10
10
  require 'spec_helper'
11
11
 
12
- describe PDI::Spoon do
12
+ describe Pdi::Spoon do
13
+ let(:script) { 'return_code.sh' }
13
14
  let(:mocks_dir) { %w[spec mocks spoon] }
14
15
  let(:dir) { File.join(*mocks_dir) }
15
16
 
@@ -25,9 +26,8 @@ describe PDI::Spoon do
25
26
 
26
27
  context 'when code is 0' do
27
28
  it 'returns correct stdout, stderr and code' do
28
- script = 'return_0.sh'
29
-
30
29
  subject = described_class.new(
30
+ args: 0,
31
31
  dir: dir,
32
32
  kitchen: script,
33
33
  pan: script
@@ -35,18 +35,17 @@ describe PDI::Spoon do
35
35
 
36
36
  result = subject.run(options)
37
37
 
38
- expect(result.execution.out_and_err).to eq("output to stdout\noutput to sterr\n")
39
- expect(result.value).to eq(0)
40
- expect(result.execution.code).to eq(0)
38
+ expect(result.out).to eq("output to stdout\n")
39
+ expect(result.err).to eq("output to sterr\n")
40
+ expect(result.code).to eq(0)
41
41
  end
42
42
  end
43
43
 
44
44
  [1, 2, 3, 7, 8, 9].each do |code|
45
45
  context "when code is #{code}" do
46
46
  specify 'returns correct stdout, stderr and code' do
47
- script = "return_#{code}.sh"
48
-
49
47
  subject = described_class.new(
48
+ args: code,
50
49
  dir: dir,
51
50
  kitchen: script,
52
51
  pan: script
@@ -73,9 +72,8 @@ describe PDI::Spoon do
73
72
 
74
73
  context 'when code is 0' do
75
74
  it 'returns correct stdout, stderr and code' do
76
- script = 'return_0.sh'
77
-
78
75
  subject = described_class.new(
76
+ args: 0,
79
77
  dir: dir,
80
78
  kitchen: script,
81
79
  pan: script
@@ -83,18 +81,17 @@ describe PDI::Spoon do
83
81
 
84
82
  result = subject.run(options)
85
83
 
86
- expect(result.execution.out_and_err).to eq("output to stdout\noutput to sterr\n")
87
- expect(result.value).to eq(0)
88
- expect(result.execution.code).to eq(0)
84
+ expect(result.out).to eq("output to stdout\n")
85
+ expect(result.err).to eq("output to sterr\n")
86
+ expect(result.code).to eq(0)
89
87
  end
90
88
  end
91
89
 
92
90
  [1, 2, 7, 8, 9].each do |code|
93
91
  context "when code is #{code}" do
94
92
  specify 'returns correct stdout, stderr and code' do
95
- script = "return_#{code}.sh"
96
-
97
93
  subject = described_class.new(
94
+ args: code,
98
95
  dir: dir,
99
96
  kitchen: script,
100
97
  pan: script
@@ -109,24 +106,40 @@ describe PDI::Spoon do
109
106
  end
110
107
 
111
108
  describe '#version' do
112
- let(:script) { 'version.sh' }
113
-
114
109
  subject do
115
110
  described_class.new(
111
+ args: args,
116
112
  dir: dir,
117
113
  kitchen: script,
118
114
  pan: script
119
115
  )
120
116
  end
121
117
 
122
- it 'returns parsed version line' do
123
- result = subject.version
124
- expected = [
125
- '2020/01/30 13:31:04 - Pan - Kettle version 6.1.0.1-196,',
126
- 'build 1, build date : 2016-04-07 12.08.49'
127
- ].join(' ')
118
+ context 'when code is 0' do
119
+ let(:script) { 'version.sh' }
120
+ let(:args) { 0 }
121
+
122
+ it 'returns parsed version line' do
123
+ result = subject.version
124
+
125
+ expected = [
126
+ '2020/01/30 13:31:04 - Pan - Kettle version 6.1.0.1-196,',
127
+ 'build 1, build date : 2016-04-07 12.08.49'
128
+ ].join(' ')
129
+
130
+ expect(result.value).to eq(expected)
131
+ end
132
+ end
133
+
134
+ context 'when code is not 0' do
135
+ let(:script) { 'return_code.sh' }
136
+ let(:args) { 1 }
137
+
138
+ it 'raises KitchenError' do
139
+ expected = described_class::KitchenError
128
140
 
129
- expect(result.value).to eq(expected)
141
+ expect { subject.version }.to raise_error(expected)
142
+ end
130
143
  end
131
144
  end
132
145
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.alpha
4
+ version: 1.0.0.pre.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-03 00:00:00.000000000 Z
11
+ date: 2020-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_hashable
@@ -122,7 +122,8 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.6.0
125
- description: " Fill out description.\n"
125
+ description: " Pentaho Data Integration allows for the creation of ETL transformation
126
+ and jobs. This library allows those ETL tasks to be executed from Ruby.\n"
126
127
  email:
127
128
  - mruggio@bluemarblepayroll.com
128
129
  executables:
@@ -146,6 +147,7 @@ files:
146
147
  - lib/pdi.rb
147
148
  - lib/pdi/executor.rb
148
149
  - lib/pdi/executor/result.rb
150
+ - lib/pdi/executor/status.rb
149
151
  - lib/pdi/spoon.rb
150
152
  - lib/pdi/spoon/kitchen_error.rb
151
153
  - lib/pdi/spoon/options.rb
@@ -157,13 +159,7 @@ files:
157
159
  - lib/pdi/spoon/result.rb
158
160
  - lib/pdi/version.rb
159
161
  - pdi.gemspec
160
- - spec/mocks/spoon/return_0.sh
161
- - spec/mocks/spoon/return_1.sh
162
- - spec/mocks/spoon/return_2.sh
163
- - spec/mocks/spoon/return_3.sh
164
- - spec/mocks/spoon/return_7.sh
165
- - spec/mocks/spoon/return_8.sh
166
- - spec/mocks/spoon/return_9.sh
162
+ - spec/mocks/spoon/return_code.sh
167
163
  - spec/mocks/spoon/version.sh
168
164
  - spec/pdi/spoon/error_spec.rb
169
165
  - spec/pdi/spoon/options/arg_spec.rb
@@ -193,15 +189,9 @@ requirements: []
193
189
  rubygems_version: 3.0.3
194
190
  signing_key:
195
191
  specification_version: 4
196
- summary: Fill out summary
192
+ summary: Ruby wrapper for invoking Pentaho Data Integration
197
193
  test_files:
198
- - spec/mocks/spoon/return_0.sh
199
- - spec/mocks/spoon/return_1.sh
200
- - spec/mocks/spoon/return_2.sh
201
- - spec/mocks/spoon/return_3.sh
202
- - spec/mocks/spoon/return_7.sh
203
- - spec/mocks/spoon/return_8.sh
204
- - spec/mocks/spoon/return_9.sh
194
+ - spec/mocks/spoon/return_code.sh
205
195
  - spec/mocks/spoon/version.sh
206
196
  - spec/pdi/spoon/error_spec.rb
207
197
  - spec/pdi/spoon/options/arg_spec.rb
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 1
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 2
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 3
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 7
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 8
@@ -1,14 +0,0 @@
1
- #!/bin/bash
2
-
3
- error(){
4
- echo "$1" >&2
5
- }
6
-
7
- output(){
8
- echo "$1"
9
- }
10
-
11
- output "output to stdout"
12
- error "output to sterr"
13
-
14
- exit 9