Class: Shell::Executer

Inherits:
Object
  • Object
show all
Defined in:
lib/shell/executer.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Executer

Configuration options:

  • :mode - Specifies the output mode. Can be :chars or :lines. In lines-mode every line of the output is passed to the block. In chars-mode every char of the output is passed to the block. (default is: :lines)

  • :no_buffer - Specifies the output mode. Can be false or true. If true no output is collected, stdout and stderr properties are empty. (default is: false)



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/shell/executer.rb', line 34

def initialize(options={})
  @options = {
    :mode => :lines, # :chars|:lines <- output mode
    :no_buffer => false
  }.merge(options)

  @reader = (@options[:mode] == :chars) ? proc {|s| s.getc } : proc {|s| s.gets }
  @mutex = Mutex.new

  @stdout = ''
  @stderr = ''
  @success = nil
end

Instance Attribute Details

#stderrObject (readonly)

Holds last executed commands error output.



22
23
24
# File 'lib/shell/executer.rb', line 22

def stderr
  @stderr
end

#stdoutObject (readonly)

Holds last executed commands standard output.



19
20
21
# File 'lib/shell/executer.rb', line 19

def stdout
  @stdout
end

Instance Method Details

#execute(command, &block) ⇒ Object

:call-seq: execute(command) -> Shell::Executer

execute(command) {|stdout| ...} -> Shell::Executer
execute(command) {|stdout, stderr| ...} -> Shell::Executer

Executes command and returns after execution.

In the first form(execute(command)) the command ist executed and the stdout, stderr and success attributes are populated.

In the second form only the stdout is passed to the block.

In the third form either stdout or stderr is filled. The opposite is allways nil.

# Prefix output of rsync
Shell::Executer.new.execute('rsync -avz /source/ /dest/') do |stdout, stderr|
  if stderr
    print 'ERR> ' + stderr
  else
    print 'OUT> ' + stdout
  end
end


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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/shell/executer.rb', line 68

def execute(command, &block)
  @stdout = ''
  @stderr = ''
  @success = nil

  pid, stdin, stdout, stderr = Open4::popen4(command)

  status = nil
  Thread.start do
    status = Process.waitpid2(pid).last
  end

  streams = [stdout, stderr]
  until streams.empty?
    selected, = select(streams, nil, nil, 0.1)
    next if selected.nil? or selected.empty?
    selected.each do |stream|
      if stream.eof?
        streams.delete(stream) if status
        next
      end

      while data = @reader.call(stream)
        data = ((@options[:mode] == :chars) ? data.chr : data)
        if block_given?
          if block.arity == 2
            args = [nil, nil]
            if stream == stdout
              args[0] = data
            else
              args[1] = data
            end
            yield *args
          else
            if stream == stdout
              yield data
            end
          end
        end
        unless @options[:no_buffer]
          if stream == stdout
            @stdout += data
          else
            @stderr += data
          end
        end
      end
    end
  end

  @success = (status.exitstatus == 0)

  self
ensure
  stdin.close rescue nil
  stdout.close rescue nil
  stderr.close rescue nil
end

#execute!(command, &block) ⇒ Object

:call-seq: execute!(command) -> Shell::Executer

execute!(command) {|stdout| ...} -> Shell::Executer
execute!(command) {|stdout, stderr| ...} -> Shell::Executer

Same as execute, but throws RuntimeError containing stderr if command exited without success.



133
134
135
136
137
# File 'lib/shell/executer.rb', line 133

def execute!(command, &block)
  execute(command, &block)
  raise stderr unless success?
  self
end

#success?Boolean

Returns true if the last command was executed successfully.

Returns:

  • (Boolean)


140
141
142
# File 'lib/shell/executer.rb', line 140

def success?
  @success
end