lib/ztk/command.rb in ztk-0.2.0 vs lib/ztk/command.rb in ztk-0.2.1
- old
+ new
@@ -43,10 +43,15 @@
def initialize(config={})
super(config)
end
+ def inspect
+ @hostname ||= %x(hostname -f).chomp
+ "#{ENV['USER']}@#{@hostname}"
+ end
+
# Executes a local command.
#
# @param [String] command The command to execute.
# @param [Hash] options The options hash for executing the command.
#
@@ -58,14 +63,17 @@
#
# cmd = ZTK::Command.new
# puts cmd.exec("hostname -f").inspect
def exec(command, options={})
options = OpenStruct.new({ :exit_code => 0, :silence => false }.merge(options))
- log(:debug) { "config(#{@config.inspect})" }
log(:debug) { "options(#{options.inspect})" }
log(:debug) { "command(#{command.inspect})" }
+ output = ""
+ stdout_header = false
+ stderr_header = false
+
parent_stdout_reader, child_stdout_writer = IO.pipe
parent_stderr_reader, child_stderr_writer = IO.pipe
pid = Process.fork do
parent_stdout_reader.close
@@ -81,17 +89,46 @@
Kernel.exec(command)
end
child_stdout_writer.close
child_stderr_writer.close
- Process.waitpid(pid)
+ reader_writer_key = {parent_stdout_reader => :stdout, parent_stderr_reader => :stderr}
+ reader_writer_map = {parent_stdout_reader => @config.stdout, parent_stderr_reader => @config.stderr}
- stdout = parent_stdout_reader.read
- stderr = parent_stderr_reader.read
- output = (stdout || '') + (stderr || '')
+ direct_log(:debug) { "===[STARTED]===[STARTED]===[#{self.inspect}]===[STARTED]===[STARTED]===\n" }
+ loop do
+ break if reader_writer_map.keys.all?{ |reader| reader.eof? }
- @config.stdout.write(stdout) unless options.silence
- @config.stderr.write(stderr) unless options.silence
+ sockets = IO.select(reader_writer_map.keys).first
+ sockets.each do |socket|
+ data = socket.read
+ next if (data.nil? || data.empty?)
+
+ case reader_writer_key[socket]
+ when :stdout then
+ if !stdout_header
+ direct_log(:debug) { "===[STDOUT]===[STDOUT]===[#{self.inspect}]===[STDOUT]===[STDOUT]===\n" }
+ stdout_header = true
+ stderr_header = false
+ end
+ reader_writer_map[socket].write(data) unless options.silence
+
+ when :stderr then
+ if !stderr_header
+ direct_log(:debug) { "===[STDERR]===[STDERR]===[#{self.inspect}]===[STDERR]===[STDERR]===\n" }
+ stderr_header = true
+ stdout_header = false
+ end
+ reader_writer_map[socket].write(data) unless options.silence
+ end
+
+ direct_log(:debug) { data }
+ output += data
+ end
+ end
+ direct_log(:debug) { "===[FINISHED]===[FINISHED]===[#{self.inspect}]===[FINISHED]===[FINISHED]===\n" }
+
+ Process.waitpid(pid)
parent_stdout_reader.close
parent_stderr_reader.close
log(:debug) { "exit_code(#{$?.inspect})" }