command_exec 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +6 -2
- data/Gemfile.lock +42 -18
- data/README.md +707 -72
- data/RELEASE_NOTES.md +62 -0
- data/Rakefile +40 -9
- data/TODO.md +8 -2
- data/command_exec.gemspec +3 -2
- data/gemfiles/Gemfile.default +28 -0
- data/gemfiles/Gemfile.travis +16 -0
- data/gemfiles/Gemfile.travis.lock +48 -0
- data/lib/command_exec.rb +22 -2
- data/lib/command_exec/command.rb +307 -157
- data/lib/command_exec/exceptions.rb +16 -6
- data/lib/command_exec/field_helper.rb +263 -0
- data/lib/command_exec/formatter/array.rb +158 -0
- data/lib/command_exec/formatter/hash.rb +78 -0
- data/lib/command_exec/formatter/json.rb +22 -0
- data/lib/command_exec/formatter/string.rb +22 -0
- data/lib/command_exec/formatter/xml.rb +22 -0
- data/lib/command_exec/formatter/yaml.rb +22 -0
- data/lib/command_exec/logger.rb +9 -0
- data/lib/command_exec/process.rb +294 -0
- data/lib/command_exec/spec_helper_module.rb +52 -0
- data/lib/command_exec/version.rb +1 -1
- data/script/console +8 -0
- data/spec/command/command_spec.rb +413 -117
- data/spec/command/test_data/echo_test +3 -0
- data/spec/command/test_data/exit_status_test +2 -0
- data/spec/command/test_data/log_file_test +3 -0
- data/spec/command/test_data/logger_test +2 -0
- data/spec/command/test_data/not_raise_error_test +4 -0
- data/spec/command/test_data/not_throw_error_test +4 -0
- data/spec/command/test_data/output_test +6 -0
- data/spec/command/test_data/raise_error_test +6 -0
- data/spec/command/test_data/runner_open3_test +4 -0
- data/spec/command/test_data/runner_system_test +4 -0
- data/spec/command/test_data/stderr_test +4 -0
- data/spec/command/test_data/stdout_multiple_lines_test +4 -0
- data/spec/command/test_data/stdout_test +4 -0
- data/spec/command/test_data/throw_error_test +6 -0
- data/spec/command/test_data/true_test +2 -0
- data/spec/formatter/array_spec.rb +215 -0
- data/spec/formatter/hash_spec.rb +117 -0
- data/spec/formatter/json_spec.rb +21 -0
- data/spec/formatter/xml_spec.rb +33 -0
- data/spec/formatter/yaml_spec.rb +21 -0
- data/spec/process/process_spec.rb +329 -0
- data/spec/spec_helper.rb +15 -4
- metadata +79 -5
data/Gemfile
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in workplace-letter_generator.gemspec
|
4
|
-
gemspec
|
4
|
+
gemspec
|
5
5
|
|
6
6
|
group :test do
|
7
7
|
gem 'rake'
|
8
8
|
gem 'rspec'
|
9
|
-
gem 'tmrb'
|
10
9
|
gem 'simplecov'
|
11
10
|
gem 'aruba'
|
12
11
|
gem 'fuubar'
|
@@ -20,5 +19,10 @@ end
|
|
20
19
|
|
21
20
|
group :development do
|
22
21
|
gem 'tmrb'
|
22
|
+
gem 'debugger'
|
23
|
+
gem 'pry'
|
24
|
+
gem 'pry-doc'
|
25
|
+
gem 'awesome_print'
|
26
|
+
gem 'travis-lint'
|
23
27
|
gem 'activesupport'
|
24
28
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,18 +1,15 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
command_exec (0.1.
|
5
|
-
|
6
|
-
|
4
|
+
command_exec (0.1.3)
|
5
|
+
activesupport
|
6
|
+
smart_colored
|
7
|
+
xml-simple
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: http://rubygems.org/
|
10
11
|
specs:
|
11
|
-
|
12
|
-
Platform (>= 0.4.0)
|
13
|
-
open4
|
14
|
-
Platform (0.4.0)
|
15
|
-
activesupport (3.2.6)
|
12
|
+
activesupport (3.2.8)
|
16
13
|
i18n (~> 0.6)
|
17
14
|
multi_json (~> 1.0)
|
18
15
|
aruba (0.4.11)
|
@@ -20,28 +17,45 @@ GEM
|
|
20
17
|
cucumber (>= 1.1.1)
|
21
18
|
ffi (>= 1.0.11)
|
22
19
|
rspec (>= 2.7.0)
|
20
|
+
awesome_print (1.0.2)
|
23
21
|
builder (3.0.0)
|
24
|
-
childprocess (0.3.
|
22
|
+
childprocess (0.3.5)
|
25
23
|
ffi (~> 1.0, >= 1.0.6)
|
26
|
-
|
24
|
+
coderay (1.0.7)
|
25
|
+
columnize (0.3.6)
|
27
26
|
cucumber (1.2.1)
|
28
27
|
builder (>= 2.1.2)
|
29
28
|
diff-lcs (>= 1.1.3)
|
30
29
|
gherkin (~> 2.11.0)
|
31
30
|
json (>= 1.4.6)
|
31
|
+
debugger (1.2.0)
|
32
|
+
columnize (>= 0.3.1)
|
33
|
+
debugger-linecache (~> 1.1.1)
|
34
|
+
debugger-ruby_core_source (~> 1.1.3)
|
35
|
+
debugger-linecache (1.1.2)
|
36
|
+
debugger-ruby_core_source (>= 1.1.1)
|
37
|
+
debugger-ruby_core_source (1.1.3)
|
32
38
|
diff-lcs (1.1.3)
|
33
|
-
ffi (1.1.
|
39
|
+
ffi (1.1.5)
|
34
40
|
fuubar (1.0.0)
|
35
41
|
rspec (~> 2.0)
|
36
42
|
rspec-instafail (~> 0.2.0)
|
37
43
|
ruby-progressbar (~> 0.0.10)
|
38
|
-
gherkin (2.11.
|
44
|
+
gherkin (2.11.2)
|
39
45
|
json (>= 1.4.6)
|
40
46
|
github-markup (0.7.4)
|
41
|
-
|
42
|
-
|
47
|
+
hashr (0.0.22)
|
48
|
+
i18n (0.6.1)
|
49
|
+
json (1.7.5)
|
50
|
+
method_source (0.8)
|
43
51
|
multi_json (1.3.6)
|
44
|
-
|
52
|
+
pry (0.9.10)
|
53
|
+
coderay (~> 1.0.5)
|
54
|
+
method_source (~> 0.8)
|
55
|
+
slop (~> 3.3.1)
|
56
|
+
pry-doc (0.4.4)
|
57
|
+
pry (>= 0.9.9.6)
|
58
|
+
yard (~> 0.8.1)
|
45
59
|
rake (0.9.2.2)
|
46
60
|
redcarpet (2.1.1)
|
47
61
|
rspec (2.11.0)
|
@@ -49,18 +63,23 @@ GEM
|
|
49
63
|
rspec-expectations (~> 2.11.0)
|
50
64
|
rspec-mocks (~> 2.11.0)
|
51
65
|
rspec-core (2.11.1)
|
52
|
-
rspec-expectations (2.11.
|
66
|
+
rspec-expectations (2.11.3)
|
53
67
|
diff-lcs (~> 1.1.3)
|
54
68
|
rspec-instafail (0.2.4)
|
55
|
-
rspec-mocks (2.11.
|
69
|
+
rspec-mocks (2.11.2)
|
56
70
|
ruby-progressbar (0.0.10)
|
57
71
|
simplecov (0.6.4)
|
58
72
|
multi_json (~> 1.0)
|
59
73
|
simplecov-html (~> 0.5.3)
|
60
74
|
simplecov-html (0.5.3)
|
61
|
-
|
75
|
+
slop (3.3.3)
|
76
|
+
smart_colored (1.1.1)
|
77
|
+
thor (0.16.0)
|
62
78
|
tmrb (1.2.7)
|
63
79
|
thor
|
80
|
+
travis-lint (1.4.0)
|
81
|
+
hashr (>= 0.0.19)
|
82
|
+
xml-simple (1.1.1)
|
64
83
|
yard (0.8.2.1)
|
65
84
|
|
66
85
|
PLATFORMS
|
@@ -69,12 +88,17 @@ PLATFORMS
|
|
69
88
|
DEPENDENCIES
|
70
89
|
activesupport
|
71
90
|
aruba
|
91
|
+
awesome_print
|
72
92
|
command_exec!
|
93
|
+
debugger
|
73
94
|
fuubar
|
74
95
|
github-markup
|
96
|
+
pry
|
97
|
+
pry-doc
|
75
98
|
rake
|
76
99
|
redcarpet
|
77
100
|
rspec
|
78
101
|
simplecov
|
79
102
|
tmrb
|
103
|
+
travis-lint
|
80
104
|
yard
|
data/README.md
CHANGED
@@ -1,132 +1,752 @@
|
|
1
|
-
command-exec
|
2
|
-
===================================================
|
1
|
+
# command-exec -- execute shell commands with ease
|
3
2
|
|
4
|
-
|
3
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/maxmeyer/command_exec)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/maxmeyer/command_exec.png)](http://travis-ci.org/maxmeyer/command_exec)
|
5
5
|
|
6
|
-
|
6
|
+
## <a name="introduction">Introduction</a>
|
7
7
|
|
8
|
-
|
8
|
+
### Description
|
9
|
+
|
10
|
+
The name of the library is `command_exec`. It's helps you running programs and
|
11
|
+
check if the run was successful. It supports a vast amount of options you find
|
12
|
+
in the one of the following sections [usage](#usage).
|
13
|
+
|
14
|
+
`Example`:
|
9
15
|
|
10
16
|
```ruby
|
11
17
|
require 'command_exec'
|
12
18
|
|
13
|
-
#
|
14
|
-
command = CommandExec::Command.new( '
|
19
|
+
# command has to be in $PATH
|
20
|
+
command = CommandExec::Command.new( :echo , :parameter => 'hello world' )
|
15
21
|
command.run
|
22
|
+
p command.result
|
23
|
+
```
|
24
|
+
|
25
|
+
### Target "Group"
|
26
|
+
|
27
|
+
If you need a library to execute programs which do a job and then terminate,
|
28
|
+
`command_exec` is your friend.
|
29
|
+
|
30
|
+
If you need a library which supports error detection based on STDOUT, STDERR,
|
31
|
+
RETURN CODE and/or LOG FILE `command_exec` is the right choice.
|
32
|
+
|
33
|
+
### Limitations
|
34
|
+
|
35
|
+
The programs should NOT produce gigabytes of output (STDOUT, STDERR, LOG FILE)
|
36
|
+
to search for errors.
|
37
|
+
|
38
|
+
### Structure of documentation
|
39
|
+
|
40
|
+
<table>
|
41
|
+
<tr>
|
42
|
+
<th>Section</th>
|
43
|
+
<th>Description</th>
|
44
|
+
</tr>
|
45
|
+
<tr>
|
46
|
+
<td>Introduction</td>
|
47
|
+
<td>Metainformation</td>
|
48
|
+
</tr>
|
49
|
+
<tr>
|
50
|
+
<td>Usage</td>
|
51
|
+
<td>How to use the library</td>
|
52
|
+
</tr>
|
53
|
+
<tr>
|
54
|
+
<td>Options</td>
|
55
|
+
<td>Which options are available to parametrize the library</td>
|
56
|
+
</tr>
|
57
|
+
<tr>
|
58
|
+
<td>HowTo</td>
|
59
|
+
<td>How to do ... with library</td>
|
60
|
+
</tr>
|
61
|
+
<tr>
|
62
|
+
<td>Further reading</td>
|
63
|
+
<td>Other helpful information</td>
|
64
|
+
</tr>
|
65
|
+
</table>
|
66
|
+
|
67
|
+
## <a name="usage">Usage<a/>
|
68
|
+
|
69
|
+
### Gem versioning
|
70
|
+
|
71
|
+
This gem uses semantic versioning. The major version is increased when breaking
|
72
|
+
changes has been made. The minor version is increased if backward-compatiable
|
73
|
+
changes introduce new functionality. The patch version is increased if a bug
|
74
|
+
was fixed and the change is backward-compatible. Please see http://semver.org/
|
75
|
+
for more information.
|
76
|
+
|
77
|
+
### Ruby Version
|
78
|
+
|
79
|
+
This gem supports ruby up from 1.9.3.
|
80
|
+
|
81
|
+
### Install gem
|
82
|
+
|
83
|
+
Install the `command_exec`-gem via `rubygems` or whatever package manager (e.g. `bundler`) you like
|
84
|
+
to use.
|
85
|
+
|
86
|
+
```bash
|
87
|
+
gem install command_exec
|
88
|
+
```
|
89
|
+
|
90
|
+
### Include library
|
91
|
+
|
92
|
+
To include the library in your code, you could use this code snippet.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
require 'command_exec'
|
96
|
+
```
|
97
|
+
### Run command
|
98
|
+
|
99
|
+
There are two forms to execute a program. You could either use the long or the
|
100
|
+
short form. In both cases a `CommandExec::Command`-object will be returned.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
command = CommandExec::Command.new( :echo , :parameter => 'hello world' )
|
104
|
+
command.run
|
105
|
+
p command.result
|
106
|
+
```
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
command = CommandExec::Command.execute( :echo , :parameter => 'hello world' )
|
110
|
+
p command.result
|
111
|
+
```
|
112
|
+
|
113
|
+
### <a name="result_of_command_execution">Result of command execution</a>
|
114
|
+
|
115
|
+
That `result`-object can be used to inspect the result of the command execution. It
|
116
|
+
supports several different methods, but only some are from interest for
|
117
|
+
external use. If you want a full list, please see the API-documentation at
|
118
|
+
[rdoc.info](http://www.rdoc.info/github/maxmeyer/command_exec/CommandExec/Process).
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
result = command.result
|
122
|
+
|
123
|
+
# which executable was run
|
124
|
+
result.executable
|
125
|
+
|
126
|
+
# !!content!! of log file
|
127
|
+
result.log_file
|
128
|
+
|
129
|
+
# pid unter which the command was run
|
130
|
+
result.pid
|
16
131
|
|
17
|
-
#
|
18
|
-
|
132
|
+
#if failed, why
|
133
|
+
result.reason_for_failure
|
19
134
|
|
20
|
-
#
|
21
|
-
|
135
|
+
#return code of command
|
136
|
+
result.return_code
|
137
|
+
|
138
|
+
#status of command execution
|
139
|
+
result.status
|
140
|
+
|
141
|
+
#content of stderr
|
142
|
+
result.stderr
|
143
|
+
|
144
|
+
#content of stdout
|
145
|
+
result.stdout
|
146
|
+
```
|
147
|
+
|
148
|
+
### Serialize result of command execution
|
149
|
+
|
150
|
+
There are some methods which need a little more explanation. Those methods
|
151
|
+
return a string representation of the result.
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
#return an array of lines
|
155
|
+
result.to_a
|
156
|
+
|
157
|
+
#return a hash
|
158
|
+
result.to_h
|
159
|
+
|
160
|
+
#serialize data to json
|
161
|
+
result.to_json
|
162
|
+
|
163
|
+
#serialize data to string
|
164
|
+
result.to_s
|
165
|
+
|
166
|
+
#serialize data to xml
|
167
|
+
result.to_xml
|
168
|
+
|
169
|
+
#serialize data to yaml
|
170
|
+
result.to_yaml
|
171
|
+
```
|
172
|
+
|
173
|
+
One can tell those methods which data should be returned. There are different
|
174
|
+
fields available:
|
175
|
+
|
176
|
+
<table>
|
177
|
+
<tr>
|
178
|
+
<th>Field</th>
|
179
|
+
<th>Symbol</th>
|
180
|
+
</tr>
|
181
|
+
<tr>
|
182
|
+
<td>Status</td>
|
183
|
+
<td>:status</td>
|
184
|
+
</tr>
|
185
|
+
<tr>
|
186
|
+
<td>Return code</td>
|
187
|
+
<td>:return_code</td>
|
188
|
+
</tr>
|
189
|
+
<tr>
|
190
|
+
<td>STDERR</td>
|
191
|
+
<td>:stderr</td>
|
192
|
+
</tr>
|
193
|
+
<tr>
|
194
|
+
<td>STDOUT</td>
|
195
|
+
<td>:stdout</td>
|
196
|
+
</tr>
|
197
|
+
<tr>
|
198
|
+
<td>Log file</td>
|
199
|
+
<td>:log_file</td>
|
200
|
+
</tr>
|
201
|
+
<tr>
|
202
|
+
<td>Process identitfier (PID)</td>
|
203
|
+
<td>:pid</td>
|
204
|
+
</tr>
|
205
|
+
<tr>
|
206
|
+
<td>Reason for failure</td>
|
207
|
+
<td>reason_for_failure</td>
|
208
|
+
</tr>
|
209
|
+
</table>
|
210
|
+
|
211
|
+
Now, some small examples:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
#result.<method>(field1,field2, ... , fieldn)
|
215
|
+
#result.<method>([field1,field2, ... , fieldn])
|
216
|
+
|
217
|
+
#all fields
|
218
|
+
result.to_a
|
219
|
+
|
220
|
+
#stderr and stdout only
|
221
|
+
result.to_a(:stderr, :stdout)
|
222
|
+
|
223
|
+
#stderr and stdout only (parameters given as a single array)
|
224
|
+
result.to_a([:stderr, :stdout])
|
225
|
+
```
|
226
|
+
|
227
|
+
## Extended usage
|
228
|
+
|
229
|
+
There are multiple ways to tell `command_exec` about a command:
|
230
|
+
|
231
|
+
### Search command in PATH
|
232
|
+
|
233
|
+
If the first parameter of `run` and `execute` is a `Symbol` the library will
|
234
|
+
search for the command in the paths given in the $PATH-shell-variable.
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
command = CommandExec::Command.execute( :echo ,
|
238
|
+
:parameter => 'hello world',
|
239
|
+
)
|
240
|
+
p command.result
|
241
|
+
```
|
242
|
+
|
243
|
+
### Path to command
|
244
|
+
|
245
|
+
If you prefer to use a full qualified path, this is possible as well.
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
command = CommandExec::Command.execute( '/bin/echo' ,
|
249
|
+
:parameter => 'hello world',
|
250
|
+
)
|
251
|
+
p command.result
|
252
|
+
```
|
253
|
+
|
254
|
+
It also supports relative paths. But be aware to tell the library the correct
|
255
|
+
one. The base path for relative ones is the working directory of the *library*,
|
256
|
+
not the working directory of the command (see section "[Working
|
257
|
+
directory](#working_directory)" about that).
|
258
|
+
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
Dir.chdir('/tmp') do
|
262
|
+
command = CommandExec::Command.execute( '../bin/echo' ,
|
263
|
+
:parameter => 'hello world',
|
264
|
+
:logger => Logger.new($stderr)
|
265
|
+
)
|
266
|
+
p command.result
|
267
|
+
end
|
22
268
|
```
|
23
269
|
|
24
270
|
## Options
|
25
271
|
|
26
|
-
|
272
|
+
### Logging
|
273
|
+
|
274
|
+
`command_exec` makes use of the Ruby `Logger`-class. If you would like to use
|
275
|
+
another class/gem, nevermind, but it has to be compatible with the `Logger`-API.
|
276
|
+
|
277
|
+
To make it easier for you, `command_exec` provides a `:logger` option. It
|
278
|
+
defaults to `Logger.new($stderr)`.
|
27
279
|
|
28
280
|
```ruby
|
29
|
-
command = CommandExec::Command.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
command.
|
281
|
+
command = CommandExec::Command.execute( :echo ,
|
282
|
+
:parameter => 'hello world',
|
283
|
+
:logger => Logger.new($stderr),
|
284
|
+
)
|
285
|
+
p command.result
|
286
|
+
```
|
287
|
+
|
288
|
+
If you prefer more or less information you can make use of the
|
289
|
+
`:lib_log_level`-option. With one exception, those log levels are the same like in
|
290
|
+
the `Logger`-class. Additionally you can use `:silent` to suppress all output
|
291
|
+
of the library, if you use the `open3` and not the `system` runner. If you
|
292
|
+
choose to use the system runner, STDOUT from the command won't be captured.
|
293
|
+
|
294
|
+
|
295
|
+
<table>
|
296
|
+
<tr>
|
297
|
+
<td><strong>Option value</strong></td>
|
298
|
+
<td><strong>Logger loglevel</strong></td>
|
299
|
+
</tr>
|
300
|
+
<tr>
|
301
|
+
<td>:debug</td>
|
302
|
+
<td>Logger::DEBUG</td>
|
303
|
+
</tr>
|
304
|
+
<tr>
|
305
|
+
<td>:info</td>
|
306
|
+
<td>Logger::INFO</td>
|
307
|
+
</tr>
|
308
|
+
<tr>
|
309
|
+
<td>:warn</td>
|
310
|
+
<td>Logger::WARN</td>
|
311
|
+
</tr>
|
312
|
+
<tr>
|
313
|
+
<td>:error</td>
|
314
|
+
<td>Logger::ERROR</td>
|
315
|
+
</tr>
|
316
|
+
<tr>
|
317
|
+
<td>:fatal</td>
|
318
|
+
<td>Logger::FATAL</td>
|
319
|
+
</tr>
|
320
|
+
<tr>
|
321
|
+
<td>:unknown</td>
|
322
|
+
<td>Logger::UNKNOWN</td>
|
323
|
+
</tr>
|
324
|
+
<tr>
|
325
|
+
<td>:silent</td>
|
326
|
+
<td>no output (log device is set to nil)</td>
|
327
|
+
</tr>
|
328
|
+
</table>
|
329
|
+
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
command = CommandExec::Command.execute( :echo ,
|
333
|
+
:parameter => 'hello world' ,
|
334
|
+
:lib_log_level => :debug,
|
335
|
+
)
|
336
|
+
p command.result
|
34
337
|
```
|
35
338
|
|
36
|
-
|
339
|
+
### Command options and parameter
|
340
|
+
|
341
|
+
The next two options (command options and command parameters) are very similar.
|
342
|
+
Both will be used to build the command which should be executed. The main
|
343
|
+
difference is the position of given string in the command string.
|
344
|
+
|
345
|
+
|
346
|
+
```
|
347
|
+
<command> <options> <parameter>
|
348
|
+
```
|
349
|
+
|
350
|
+
So, if you don't want to use the `options`- and/or the `parameter`-option, you
|
351
|
+
don't need to do it. But may be there are situations, where you would like to
|
352
|
+
be as concise as possible.
|
353
|
+
|
354
|
+
|
355
|
+
Recommended:
|
37
356
|
|
38
357
|
```ruby
|
39
|
-
command = CommandExec::Command.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
command.
|
358
|
+
command = CommandExec::Command.execute( :ls ,
|
359
|
+
:options => '-al',
|
360
|
+
:parameter => '/bin',
|
361
|
+
)
|
362
|
+
p command.result
|
44
363
|
```
|
45
364
|
|
46
|
-
|
365
|
+
But also valid:
|
47
366
|
|
48
|
-
|
49
|
-
|
367
|
+
```ruby
|
368
|
+
command = CommandExec::Command.execute( :ls ,
|
369
|
+
:options => '-al /bin',
|
370
|
+
)
|
371
|
+
p command.result
|
372
|
+
```
|
373
|
+
|
374
|
+
Or:
|
50
375
|
|
51
376
|
```ruby
|
52
|
-
command = CommandExec::Command.
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
command.run
|
377
|
+
command = CommandExec::Command.execute( :ls ,
|
378
|
+
:parameter => '-al /bin',
|
379
|
+
)
|
380
|
+
p command.result
|
57
381
|
```
|
58
382
|
|
59
|
-
|
383
|
+
Please check if you use single or double quotes correctly! `command_exec` takes
|
384
|
+
the parameters and options as given. That's why
|
60
385
|
|
61
|
-
|
386
|
+
```ruby
|
387
|
+
#will succeed
|
388
|
+
#see debug output for reason
|
389
|
+
command = CommandExec::Command.execute( :echo ,
|
390
|
+
:options => '-e',
|
391
|
+
:parameter => "\"Thats a string\n with a newline\"",
|
392
|
+
:lib_log_level => :debug,
|
393
|
+
)
|
394
|
+
p command.result
|
395
|
+
```
|
396
|
+
|
397
|
+
isn't the same like
|
62
398
|
|
63
399
|
```ruby
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
400
|
+
#will fail
|
401
|
+
#see debug output for reason
|
402
|
+
command = CommandExec::Command.execute( :echo ,
|
403
|
+
:options => '-e',
|
404
|
+
:parameter => "Thats a string\n with a newline",
|
405
|
+
:lib_log_level => :debug,
|
406
|
+
)
|
407
|
+
p command.result
|
69
408
|
```
|
70
409
|
|
71
|
-
|
410
|
+
### <a name="log_file">Command log file</a>
|
72
411
|
|
73
|
-
|
74
|
-
|
412
|
+
If the command creates a log file, you can tell `command_exec` about that file
|
413
|
+
via the `:log_file`-option. Honestly, this option only makes sense if you
|
414
|
+
configure `command_exec`to search for errors in the file (please see the
|
415
|
+
chapter about [Error detection](#error_detection) for further information about
|
416
|
+
that).
|
75
417
|
|
76
418
|
```ruby
|
77
|
-
command = CommandExec::Command.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
command.
|
419
|
+
command = CommandExec::Command.execute( :ls ,
|
420
|
+
:options => '-al',
|
421
|
+
:log_file => '/path/to/log_file',
|
422
|
+
)
|
423
|
+
p command.result
|
82
424
|
```
|
83
425
|
|
84
|
-
|
426
|
+
### Command search path
|
85
427
|
|
86
|
-
|
87
|
-
|
88
|
-
output.
|
428
|
+
If you need to change the paths where a command can be found, you could use the
|
429
|
+
`:search_path`-option. It defaults to those paths found in $PATH.
|
89
430
|
|
431
|
+
It supports multiple values as `Array`:
|
90
432
|
|
91
433
|
```ruby
|
92
|
-
command = CommandExec::Command.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
command.run
|
434
|
+
command = CommandExec::Command.execute( :ls ,
|
435
|
+
:options => '-al',
|
436
|
+
:search_paths => [ '/bin' ],
|
437
|
+
)
|
438
|
+
p command.result
|
98
439
|
```
|
99
440
|
|
100
|
-
|
441
|
+
Or single values as `String`:
|
442
|
+
|
443
|
+
```ruby
|
444
|
+
command = CommandExec::Command.execute( :ls ,
|
445
|
+
:options => '-al',
|
446
|
+
:search_paths => '/bin',
|
447
|
+
)
|
448
|
+
p command.result
|
449
|
+
```
|
101
450
|
|
102
|
-
|
103
|
-
|
451
|
+
### <a name="error_detection">Error detection</a>
|
452
|
+
|
453
|
+
`command_exec` is capable of searching for errors. To enable error detection
|
454
|
+
you need to activate it via the `:error_detection_on`-option. It supports error
|
455
|
+
detection on:
|
456
|
+
|
457
|
+
<table>
|
458
|
+
<tr>
|
459
|
+
<td><strong>Search in...</strong></td>
|
460
|
+
<td><strong>Symbol</strong></td>
|
461
|
+
</tr>
|
462
|
+
<tr>
|
463
|
+
<td>Return code</td>
|
464
|
+
<td>:return_code</td>
|
465
|
+
</tr>
|
466
|
+
<tr>
|
467
|
+
<td>STDOUT</td>
|
468
|
+
<td>:stdout</td>
|
469
|
+
</tr>
|
470
|
+
<tr>
|
471
|
+
<td>STDERR</td>
|
472
|
+
<td>:stderr</td>
|
473
|
+
</tr>
|
474
|
+
<tr>
|
475
|
+
<td>Log file</td>
|
476
|
+
<td>:log_file</td>
|
477
|
+
</tr>
|
478
|
+
</table>
|
479
|
+
|
480
|
+
But you need to provide information, what item indicates an error.
|
481
|
+
|
482
|
+
<table>
|
483
|
+
<tr>
|
484
|
+
<td><strong>Indicator for...</strong></td>
|
485
|
+
<td><strong>Options</strong></td>
|
486
|
+
<td><strong>Type</strong></td>
|
487
|
+
</tr>
|
488
|
+
<tr>
|
489
|
+
<td>Return code</td>
|
490
|
+
<td>
|
491
|
+
:allowed_return_code<br/>
|
492
|
+
:forbidden_return_code
|
493
|
+
</td>
|
494
|
+
<td>
|
495
|
+
Array
|
496
|
+
</td>
|
497
|
+
</tr>
|
498
|
+
<tr>
|
499
|
+
<td>STDERR</td>
|
500
|
+
<td>
|
501
|
+
:allowed_words_in_stderr<br/>
|
502
|
+
:forbidden_words_in_stderr
|
503
|
+
</td>
|
504
|
+
<td>
|
505
|
+
Array
|
506
|
+
</td>
|
507
|
+
</tr>
|
508
|
+
<tr>
|
509
|
+
<td>STDOUT</td>
|
510
|
+
<td>
|
511
|
+
:allowed_words_in_stdout<br/>
|
512
|
+
:forbidden_words_in_stdout
|
513
|
+
</td>
|
514
|
+
<td>
|
515
|
+
Array
|
516
|
+
</td>
|
517
|
+
</tr>
|
518
|
+
<tr>
|
519
|
+
<td>Log file</td>
|
520
|
+
<td>
|
521
|
+
:allowed_words_in_log_file<br/>
|
522
|
+
:forbidden_words_in_log_file
|
523
|
+
</td>
|
524
|
+
<td>
|
525
|
+
Array
|
526
|
+
</td>
|
527
|
+
</tr>
|
528
|
+
</table>
|
529
|
+
|
530
|
+
*Return code*
|
531
|
+
|
532
|
+
If the command returns helpful return codes, those can be used to check if an
|
533
|
+
error occured. You can tell `command_exec` about allowed or forbidden return
|
534
|
+
codes.
|
104
535
|
|
105
|
-
### Successfull
|
106
536
|
|
537
|
+
```ruby
|
538
|
+
#All error codes except `0` will be detected as an error.
|
539
|
+
command = CommandExec::Command.execute( :false ,
|
540
|
+
:error_detection_on => [:return_code],
|
541
|
+
:error_indicators => {
|
542
|
+
:allowed_return_code => [0],
|
543
|
+
},
|
544
|
+
)
|
545
|
+
p command.result
|
546
|
+
|
547
|
+
#If the command exits with a return code of `1`, this will be detected as an
|
548
|
+
#error.
|
549
|
+
command = CommandExec::Command.execute( :false ,
|
550
|
+
:error_detection_on => [:return_code],
|
551
|
+
:error_indicators => {
|
552
|
+
:forbidden_return_code => [1],
|
553
|
+
},
|
554
|
+
)
|
555
|
+
p command.result
|
107
556
|
```
|
108
|
-
|
557
|
+
|
558
|
+
In the case of the detection of errors `command_exec`defaults to:
|
559
|
+
|
560
|
+
```ruby
|
561
|
+
:error_detection_on => [:return_code],
|
562
|
+
:allowed_return_code => [0],
|
109
563
|
```
|
110
564
|
|
111
|
-
|
565
|
+
*STDOUT*
|
112
566
|
|
567
|
+
`command_exec` can search for errors in STDOUT. To enable this functionality,
|
568
|
+
you need to set the `:error_detection_on`-option on ':stdout'. Furthermore you
|
569
|
+
need to tell the library, what strings are error indicators
|
570
|
+
(`forbidden_words_in_stdout`). If there are some strings which contain the
|
571
|
+
error string(s), but are no errors, you need to use the
|
572
|
+
`allowed_words_in_stdout`-option. The same is true, if the allowed word is in
|
573
|
+
the same line.
|
574
|
+
|
575
|
+
```ruby
|
576
|
+
#Simple error search
|
577
|
+
#will fail
|
578
|
+
command = CommandExec::Command.execute( :echo ,
|
579
|
+
:options => '-e',
|
580
|
+
:parameter => "\"wow, a test. That's great.\nBut an error occured in this line\"",
|
581
|
+
:error_detection_on => [:stdout],
|
582
|
+
:error_indicators => {
|
583
|
+
:forbidden_words_in_stdout => %w{ error }
|
584
|
+
},
|
585
|
+
)
|
586
|
+
p command.result
|
587
|
+
|
588
|
+
#error indicator in string, which is no error
|
589
|
+
#will succeed
|
590
|
+
command = CommandExec::Command.execute( :echo ,
|
591
|
+
:options => '-e',
|
592
|
+
:parameter => "\"wow, a test. That's great.\nBut no error occured in this line\"",
|
593
|
+
:error_detection_on => [:stdout],
|
594
|
+
:error_indicators => {
|
595
|
+
:forbidden_words_in_stdout => %w{ error },
|
596
|
+
:allowed_words_in_stdout => ["no error occured"] ,
|
597
|
+
},
|
598
|
+
)
|
599
|
+
p command.result
|
600
|
+
|
601
|
+
#error indicator in same line, which is no error
|
602
|
+
#will succeed
|
603
|
+
command = CommandExec::Command.execute( :echo ,
|
604
|
+
:options => '-e',
|
605
|
+
:parameter => "\"wow, a test. That's great.\nBut no error occured in this line because of some other string\"",
|
606
|
+
:error_detection_on => [:stdout],
|
607
|
+
:error_indicators => {
|
608
|
+
:forbidden_words_in_stdout => %w{ error },
|
609
|
+
:allowed_words_in_stdout => ["some other string"] ,
|
610
|
+
},
|
611
|
+
)
|
612
|
+
p command.result
|
113
613
|
```
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
[
|
119
|
-
|
120
|
-
[
|
614
|
+
|
615
|
+
*STDERR*
|
616
|
+
|
617
|
+
The same is true for STDERR. You need to activate the error detection via
|
618
|
+
`:error_detection_on => [:stderr]`. The error indicators can be given via
|
619
|
+
`:forbidden_words_in_stderr => %w{ error }` and `:allowed_words_in_stdout =>
|
620
|
+
["some other string"]`.
|
621
|
+
|
622
|
+
```ruby
|
623
|
+
#will fail
|
624
|
+
command = CommandExec::Command.execute( :echo ,
|
625
|
+
:options => '-e',
|
626
|
+
:parameter => "\"wow, a test. That's great.\nBut an error occured in this line\" >&2",
|
627
|
+
:error_detection_on => [:stderr],
|
628
|
+
:error_indicators => {
|
629
|
+
:forbidden_words_in_stderr => %w{ error },
|
630
|
+
},
|
631
|
+
)
|
632
|
+
p command.result
|
121
633
|
```
|
122
634
|
|
123
|
-
|
635
|
+
*LOG FILE*
|
636
|
+
|
637
|
+
To search for errors in the log file a command created during execution, you
|
638
|
+
need to provide the information where `command_exec` finds the log file (see
|
639
|
+
section [Command Log file](#log_file)).
|
124
640
|
|
641
|
+
The options are very similar to those for STDERR and STDOUT: To activate error
|
642
|
+
detection for log files use `:error_detection_on => [:log_file]`. The error
|
643
|
+
indicators can be given via `:forbidden_words_in_log_file => %w{ error }` and
|
644
|
+
`:allowed_words_in_log_file => ["some other string"]`.
|
645
|
+
|
646
|
+
```ruby
|
647
|
+
File.open('/tmp/test.log', 'w') do |f|
|
648
|
+
f.write "wow, a test. That's great.\nBut an error occured in this line"
|
649
|
+
end
|
650
|
+
|
651
|
+
#will fail
|
652
|
+
command = CommandExec::Command.execute( :echo ,
|
653
|
+
:error_detection_on => [:log_file],
|
654
|
+
:log_file => '/tmp/test.log',
|
655
|
+
:error_indicators => {
|
656
|
+
:forbidden_words_in_log_file => %w{ error },
|
657
|
+
},
|
658
|
+
)
|
659
|
+
p command.result
|
125
660
|
```
|
126
|
-
|
127
|
-
|
661
|
+
|
662
|
+
### <a name="working_directory">Working directory</a>
|
663
|
+
|
664
|
+
To change the working directory for the command you can use the `:working_directory`-option.
|
665
|
+
|
666
|
+
```ruby
|
667
|
+
command = CommandExec::Command.execute( :ls ,
|
668
|
+
:options => '-al',
|
669
|
+
:working_directory => '/tmp',
|
670
|
+
)
|
671
|
+
p command.result
|
128
672
|
```
|
129
673
|
|
674
|
+
### Error reaction
|
675
|
+
|
676
|
+
If an error occured, `command_exec` can raise an exception, 'throw' an error or
|
677
|
+
do nothing at all. Besides the configured option, on every run it returns the
|
678
|
+
result for the run (see [Result of command
|
679
|
+
execution](#result_of_command_execution) for more details).
|
680
|
+
|
681
|
+
*Raise an exception aka error*
|
682
|
+
|
683
|
+
If an error occured during command execution, you can tell `command_exec` to
|
684
|
+
raise an exception.
|
685
|
+
|
686
|
+
```ruby
|
687
|
+
begin
|
688
|
+
command = CommandExec::Command.execute( :false ,
|
689
|
+
:on_error_do => :raise_error,
|
690
|
+
)
|
691
|
+
rescue CommandExec::Exceptions::CommandExecutionFailed => e
|
692
|
+
puts e.message
|
693
|
+
end
|
694
|
+
```
|
695
|
+
|
696
|
+
*Throw error*
|
697
|
+
|
698
|
+
If you prefer not to use execptions, you can use ruby's
|
699
|
+
`throw`-`catch`-mechanism.
|
700
|
+
|
701
|
+
```ruby
|
702
|
+
catch :command_execution_failed do
|
703
|
+
command = CommandExec::Command.execute( :false ,
|
704
|
+
:on_error_do => :throw_error,
|
705
|
+
)
|
706
|
+
end
|
707
|
+
```
|
708
|
+
|
709
|
+
### Runner
|
710
|
+
|
711
|
+
Today there are two runners available: `:open3` and `system`. Use the first one
|
712
|
+
if you want `:stdout` and `:stderr` to be captured and searched for errors. If
|
713
|
+
you're only interested in the `:return_code` you could use the
|
714
|
+
`:system`-runner. Please be aware, that using the `system`-runner + error
|
715
|
+
detection on `stdout`, `stderr` is not working as you might expect.
|
716
|
+
|
717
|
+
```ruby
|
718
|
+
#will fail
|
719
|
+
command = CommandExec::Command.execute( :echo ,
|
720
|
+
:options => '-e',
|
721
|
+
:parameter => "\"wow, a test. That's great.\nBut an error occured in this line\"",
|
722
|
+
:error_detection_on => [:stdout],
|
723
|
+
:error_indicators => {
|
724
|
+
:forbidden_words_in_stdout => %w{ error }
|
725
|
+
},
|
726
|
+
:run_via => :open3,
|
727
|
+
)
|
728
|
+
p command.result
|
729
|
+
|
730
|
+
#will succeed, because stdout was not caputured
|
731
|
+
command = CommandExec::Command.execute( :echo ,
|
732
|
+
:options => '-e',
|
733
|
+
:parameter => "\"wow, a test. That's great.\nBut an error occured in this line\"",
|
734
|
+
:error_detection_on => [:stdout],
|
735
|
+
:error_indicators => {
|
736
|
+
:forbidden_words_in_stdout => %w{ error }
|
737
|
+
},
|
738
|
+
:run_via => :system,
|
739
|
+
)
|
740
|
+
p command.result
|
741
|
+
```
|
742
|
+
## HowTo
|
743
|
+
|
744
|
+
TBD
|
745
|
+
|
746
|
+
## Further Reading
|
747
|
+
|
748
|
+
* API-documentation: http://rdoc.info/github/maxmeyer/command_exec/frames
|
749
|
+
|
130
750
|
## Dependencies
|
131
751
|
|
132
752
|
Please see the gemspec for runtime dependencies and the 'Gemfile' for
|
@@ -136,6 +756,21 @@ development dependencies.
|
|
136
756
|
|
137
757
|
Please see TODO.md for enhancements which are planned for implementation.
|
138
758
|
|
759
|
+
## Development
|
760
|
+
|
761
|
+
1. Fork it
|
762
|
+
2. Create your remote (`git remote add <your_remote_repo> <path_to_repo>`)
|
763
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
764
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
765
|
+
4. Push to the branch (`git push <your_remote_repo> my-new-feature`)
|
766
|
+
5. Create new Pull Request
|
767
|
+
|
768
|
+
The API-documentation can be found at
|
769
|
+
http://rdoc.info/github/maxmeyer/command_exec/frames
|
770
|
+
|
771
|
+
Please see 'http://git-scm.com/book' first if you have further questions about
|
772
|
+
`git`.
|
773
|
+
|
139
774
|
## Copyright
|
140
775
|
|
141
776
|
(c) 2012-, Max Meyer
|