Class: Gat::Action::ShellCommand
- Defined in:
- lib/gat/action/shell_command.rb,
lib/gatgets/dar_backup/dar_backup.rb
Instance Attribute Summary collapse
-
#arguments ⇒ Object
Returns the value of attribute arguments.
-
#childs ⇒ Object
readonly
Returns the value of attribute childs.
-
#pid ⇒ Object
Returns the value of attribute pid.
-
#status ⇒ Object
Returns the value of attribute status.
-
#syntax ⇒ Object
readonly
Returns the value of attribute syntax.
Attributes inherited from Base
#argument, #config, #description, #error, #errors, #exit_level, #flags, #name, #onfail, #onfail_callback, #onfail_message, #operation, #output, #parsed_syntax, #times
Instance Method Summary collapse
-
#exec(shell_command, multiple_name = '') ⇒ Object
Execute shell command with Open4.
-
#initialize(name, config, operation) ⇒ ShellCommand
constructor
A new instance of ShellCommand.
-
#reinterpret_output_and_error(output, error, status) ⇒ Object
dar mixes a little bit its stdout and stderr outputs.
- #run ⇒ Object
- #set_multiple_childs(multiples_parameters) ⇒ Object
Methods inherited from Base
#execute, #execute?, get_current_action
Methods included from Interpreter
#interpreter_parameter, #interpreter_parameters, #interpreter_shell_command
Constructor Details
#initialize(name, config, operation) ⇒ ShellCommand
Returns a new instance of ShellCommand.
13 14 15 16 17 |
# File 'lib/gat/action/shell_command.rb', line 13 def initialize(name, config, operation) super(name, config, operation) @syntax = config['syntax'] || raise(GatgetConfigException.new("Shell Command Action #{ name } has not a syntax attribute", "initialize_shell_command")) end |
Instance Attribute Details
#arguments ⇒ Object
Returns the value of attribute arguments.
8 9 10 |
# File 'lib/gat/action/shell_command.rb', line 8 def arguments @arguments end |
#childs ⇒ Object (readonly)
Returns the value of attribute childs.
7 8 9 |
# File 'lib/gat/action/shell_command.rb', line 7 def childs @childs end |
#pid ⇒ Object
Returns the value of attribute pid.
10 11 12 |
# File 'lib/gat/action/shell_command.rb', line 10 def pid @pid end |
#status ⇒ Object
Returns the value of attribute status.
11 12 13 |
# File 'lib/gat/action/shell_command.rb', line 11 def status @status end |
#syntax ⇒ Object (readonly)
Returns the value of attribute syntax.
6 7 8 |
# File 'lib/gat/action/shell_command.rb', line 6 def syntax @syntax end |
Instance Method Details
#exec(shell_command, multiple_name = '') ⇒ Object
Execute shell command with Open4
Open4 module is the next generation Ruby module for executing shell commands. Open4 works better thant the standard Open3 module, and has built inside the feature to return exit status through Process.status Class. Even it has some problems too. Open4 module has big problems when the stdout or the stderr comes with tons of information. For example, with a mysqldump output.
The solution presented here is a wrapper through Process.fork. We create a new fork, making and the output is not managed by the ruby script itself but by the fork process. IO.pipes are created to pass the stdout, stderr and stdin data through Gat proccess and Fork process
Some disccusion about this can be readed here: stackoverflow.com/questions/1076257/returning-data-from-forked-processes
Maybe, we could use Theread.new, and maybe it would be better, but… =)
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/gat/action/shell_command.rb', line 64 def exec(shell_command, multiple_name = '') trap_save = trap( 0, "IGNORE" ) self.operation.gatget.logger.log("trace", "action_syntax", "Action #{ self.name }#{ multiple_name } exec command syntax : #{ shell_command }" ) self.times['init'] ||= Time.now read_stdout, write_stdout = IO.pipe read_stderr, write_stderr = IO.pipe pid = fork do trap( 0, "IGNORE" ) read_stdout.close read_stderr.close pid_open4, stdin, stdout, stderr = Open4::popen4 "#{ shell_command }" write_stdout.puts stdout.read write_stderr.puts stderr.read ignored, status_open4 = Process::waitpid2 pid_open4 exit status_open4.exitstatus end trap( 0, trap_save ) write_stdout.close write_stderr.close result_stdout = read_stdout.read result_stderr = read_stderr.read pid, status = Process.wait2(pid) self.output, self.error, self.exit_level = reinterpret_output_and_error(result_stdout, result_stderr, status.exitstatus) self.pid = pid self.status = status self.times['end'] = Time.now end |
#reinterpret_output_and_error(output, error, status) ⇒ Object
dar mixes a little bit its stdout and stderr outputs
145 146 147 148 |
# File 'lib/gat/action/shell_command.rb', line 145 def reinterpret_output_and_error(output, error, status) return output == "\n" ? "" : output, error == "\n" ? "" : error, status end |
#run ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/gat/action/shell_command.rb', line 20 def run ret = nil # Shell Command can be multiple, that means the command will be execute over a foreach variable subtitutions. # That is usefull, for example, when you need to do the same actions with some variable subtition, like # a multiple files compression. @childs = (@config['multiple'] and @config['multiple'].any?) ? set_multiple_childs(@config['multiple']) : [ ] # If ShellCommand is multiple, then, we exec all of its childs # If not, we just execute ShellCommand instance if @childs.any? @childs.each { |child| if not child.exec ret = false end } else self.parsed_syntax = interpreter_parameters(self.syntax, self.operation.gatget) ret = exec(self.parsed_syntax) end if self.config['output'] self.operation.gatget.logger.log("direct", "action_output", self.output) end ret end |
#set_multiple_childs(multiples_parameters) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/gat/action/shell_command.rb', line 106 def set_multiple_childs(multiples_parameters) # get multiples values multiples_values = {} multiples_parameters.each do |parameter| values = interpreter_parameter(parameter, self.operation.gatget) multiples_values[parameter] = values end # all multiple values must have the same size for substitution last_multiple_vales_size = multiples_values.values.first.size multiples_values.values.each do |values| unless values.size == last_multiple_vales_size raise GatgetConfigException.new("Multiples values at Action #{ self.name } doesnt have the same size. Substitution cannot be interpreted", "set_multiple_chids") end last_multiple_vales_size == values.size end unless last_multiple_vales_size > 0 raise GatgetConfigException.new("Multiples values at Action #{ self.name } are empty", "set_multiple_chids") end # create childs objects childs = [] i = 0 last_multiple_vales_size.times do child_multiple_parameters = {} multiples_values.each_pair do |parameter, values| child_multiple_parameters[parameter] = values[i] end childs << ShellCommandChild.new(self, child_multiple_parameters) i += 1 end # return child childs end |