command_exec 0.1.3 → 0.2.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.
Files changed (49) hide show
  1. data/Gemfile +6 -2
  2. data/Gemfile.lock +42 -18
  3. data/README.md +707 -72
  4. data/RELEASE_NOTES.md +62 -0
  5. data/Rakefile +40 -9
  6. data/TODO.md +8 -2
  7. data/command_exec.gemspec +3 -2
  8. data/gemfiles/Gemfile.default +28 -0
  9. data/gemfiles/Gemfile.travis +16 -0
  10. data/gemfiles/Gemfile.travis.lock +48 -0
  11. data/lib/command_exec.rb +22 -2
  12. data/lib/command_exec/command.rb +307 -157
  13. data/lib/command_exec/exceptions.rb +16 -6
  14. data/lib/command_exec/field_helper.rb +263 -0
  15. data/lib/command_exec/formatter/array.rb +158 -0
  16. data/lib/command_exec/formatter/hash.rb +78 -0
  17. data/lib/command_exec/formatter/json.rb +22 -0
  18. data/lib/command_exec/formatter/string.rb +22 -0
  19. data/lib/command_exec/formatter/xml.rb +22 -0
  20. data/lib/command_exec/formatter/yaml.rb +22 -0
  21. data/lib/command_exec/logger.rb +9 -0
  22. data/lib/command_exec/process.rb +294 -0
  23. data/lib/command_exec/spec_helper_module.rb +52 -0
  24. data/lib/command_exec/version.rb +1 -1
  25. data/script/console +8 -0
  26. data/spec/command/command_spec.rb +413 -117
  27. data/spec/command/test_data/echo_test +3 -0
  28. data/spec/command/test_data/exit_status_test +2 -0
  29. data/spec/command/test_data/log_file_test +3 -0
  30. data/spec/command/test_data/logger_test +2 -0
  31. data/spec/command/test_data/not_raise_error_test +4 -0
  32. data/spec/command/test_data/not_throw_error_test +4 -0
  33. data/spec/command/test_data/output_test +6 -0
  34. data/spec/command/test_data/raise_error_test +6 -0
  35. data/spec/command/test_data/runner_open3_test +4 -0
  36. data/spec/command/test_data/runner_system_test +4 -0
  37. data/spec/command/test_data/stderr_test +4 -0
  38. data/spec/command/test_data/stdout_multiple_lines_test +4 -0
  39. data/spec/command/test_data/stdout_test +4 -0
  40. data/spec/command/test_data/throw_error_test +6 -0
  41. data/spec/command/test_data/true_test +2 -0
  42. data/spec/formatter/array_spec.rb +215 -0
  43. data/spec/formatter/hash_spec.rb +117 -0
  44. data/spec/formatter/json_spec.rb +21 -0
  45. data/spec/formatter/xml_spec.rb +33 -0
  46. data/spec/formatter/yaml_spec.rb +21 -0
  47. data/spec/process/process_spec.rb +329 -0
  48. data/spec/spec_helper.rb +15 -4
  49. 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.0)
5
- POpen4
6
- colored
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
- POpen4 (0.1.4)
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.4)
22
+ childprocess (0.3.5)
25
23
  ffi (~> 1.0, >= 1.0.6)
26
- colored (1.2)
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.0)
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.1)
44
+ gherkin (2.11.2)
39
45
  json (>= 1.4.6)
40
46
  github-markup (0.7.4)
41
- i18n (0.6.0)
42
- json (1.7.3)
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
- open4 (1.3.0)
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.1)
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.1)
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
- thor (0.15.4)
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(1) -- execute shell commands with ease
2
- ===================================================
1
+ # command-exec -- execute shell commands with ease
3
2
 
4
- ## Description
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
- This gem brings command execution via POpen4 with all the bells and whistles.
6
+ ## <a name="introduction">Introduction</a>
7
7
 
8
- ## Usage
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
- #long form
14
- command = CommandExec::Command.new( 'command' )
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
- #short form
18
- command = CommandExec::Command.execute( 'command')
132
+ #if failed, why
133
+ result.reason_for_failure
19
134
 
20
- #full path to commadn
21
- command = CommandExec::Command.execute( 'path/to/command')
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
- * `:logger`: Logger for output of information
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.new(
30
- 'command',
31
- :logger => Logger.new($stderr),
32
- }
33
- command.run
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
- * `:options`: Commandline options for executed command
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.new(
40
- 'command',
41
- :options => '--command options',
42
- }
43
- command.run
358
+ command = CommandExec::Command.execute( :ls ,
359
+ :options => '-al',
360
+ :parameter => '/bin',
361
+ )
362
+ p command.result
44
363
  ```
45
364
 
46
- * `error_keywords`: Keywords which indicate error(s)
365
+ But also valid:
47
366
 
48
- Are there any keywords in stdout of the command which should be executed, which
49
- indicate errors?
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.new(
53
- 'command',
54
- :error_keywords => ['key words in', 'stdout with indicate errors' ],
55
- }
56
- command.run
377
+ command = CommandExec::Command.execute( :ls ,
378
+ :parameter => '-al /bin',
379
+ )
380
+ p command.result
57
381
  ```
58
382
 
59
- * `:working_directory`: Change working directory of command
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
- Change working directory to given one before command execution.
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
- command = CommandExec::Command.new(
65
- 'command',
66
- :working_directory => 'working/directory/where/the/command/should/be/executed/in',
67
- }
68
- command.run
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
- * `logfile`: Logfile of command
410
+ ### <a name="log_file">Command log file</a>
72
411
 
73
- The first 30 lines of the command-logfile will be output by logger if an error
74
- occured.
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.new(
78
- 'command',
79
- :logfile => 'path/to/logfile.log',
80
- }
81
- command.run
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
- * `:log_level`:
426
+ ### Command search path
85
427
 
86
- What should be put to logger? Available choices are :debug, :info, :warn,
87
- :error, :fatal, :unkonwn, :silent. If you choose :silent nothing will be
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.new(
93
- 'command',
94
- :logfile => 'path/to/logfile.log',
95
- :log_level => :debug
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
- ## Output
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
- After execute the command you get the following output. Today it's not possible
103
- to suppress that output, but it's on the roadmap.
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
- <timestamp> command: OK
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
- ### Failed with STDERR set
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
- <timestamp> command: FAILED
115
- ================== LOGFILE ==================
116
- [...]
117
- ================== STDOUT ==================
118
- [...]
119
- ================== STDERR ==================
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
- ### Failed with string in STDOUT indicating an error
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
- <timestamp> command: FAILED
127
- ================== STDOUT ==================
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