April16
Instant Feedback When Running Shell Commands
I came across a need to see the output of a bash shell command in realtime. Usually when you use the backticks or system command you only see the output after the process has run. So in order to get realtime feedback I came up with this:
require 'pty'
def trace_output_for_command(command)
begin
PTY.spawn( command ) do |stdin, stdout, pid|
begin
stdin.each { |line| print line }
rescue Errno::EIO
puts "Output Finished"
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end
end
trace_output_for_command('ping -c 3 localhost')
When running with MRI / standard ruby this seems to work fine. But when running with jruby instead of exiting after the command has executed it just hung – so I made a small adjustment which fixed that:
When using Jruby:
require 'pty'
def trace_output_for_command(command)
begin
PTY.spawn( command ) do |stdin, stdout, pid|
begin
stdin.each do |line|
print line
break if stdin.eof?
end
rescue Errno::EIO
puts "Output Finished"
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end
end
trace_output_for_command('ping -c 3 localhost')
Finally here is another version which works on unix and returns the exit code of the last process that ran in the shell. Usually I would use $?.exitstatus but it doesn’t seem to be available when using PTY.spawn.
require 'pty'
class ShellCommand
attr_reader :return_value
def initialize(command)
@command = command
@return_value = 0
end
def run_with_trace
begin
PTY.spawn( @command + "; echo ${PIPESTATUS[0]}") do |stdin, stdout, pid|
begin
stdin.each do |line|
puts line
if stdin.eof?
@return_value = line.to_i
break
end
end
rescue Errno::EIO
puts "Output Finished"
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end
end
def ran_successfully?
@return_value == 0
end
end
shell = ShellCommand.new("la -al")
shell.run_with_trace
p shell.ran_successfully?
p shell.return_value
puts "hello this is cool"
A couple of interesting projects which are related to forking and such:
- Spoon: http://gist.github.com/321084
- Popen4 : http://popen4.rubyforge.org/
both installable as gems: gem install spoon open4
Latest Comments
"Very nice. Used to access
nick xidis / 20.Jul.2009 at 11:29pm
"Thanks Mark – I have put ..."
kingsley / 24.Jun.2009 at 11:10am
"Nice work! Could you publish th..."
mark yoon / 10.Jun.2009 at 05:03pm
"Totally! Ruby is a great freest..."
raymond barlow / 14.Feb.2009 at 03:08pm