# # This script uses John Carter's RExpect module for Ruby; the original is # available at: # # http://www.rubygarden.org/ruby?RExpect # require 'pty' require 'thread' require 'timeout' $expect_verbose = false Thread.abort_on_exception = true class RExpect attr_reader :pid def RExpect.spawn(cmd) mutex = Mutex.new mutex.synchronize do resultResource = ConditionVariable.new result = nil Thread.new do pid = nil mutex.synchronize do inf, outf, pid, fileName = PTY.spawn(cmd) result = RExpect.new( inf, outf, pid, fileName) resultResource.signal end result.inputData end resultResource.wait( mutex) return result end end def log(a) @log.puts "#{caller(1)[0]}:#{a}" unless @log.nil? end def initialize(inf,outf,pid,fileName) @inf,@outf,@pid,@fileName = inf,outf,pid,fileName if $expect_verbose then @log = File.open( "rexpect.log.#{@pid}", "w") @log.sync = true else @log = nil end @outf.sync=true @buffer = '' @mutex = Mutex.new @bufferResource = ConditionVariable.new end def wait Process.waitpid(@pid,0) rescue end def kill kill( "SIGTERM", @pid) wait end def inputData while true data = @inf.sysread( 65536) @mutex.synchronize do log( "BUFFER:#{@buffer}\nNEWDATA:#{data}" ) @buffer << data if !@e_pat.nil? && @buffer =~ @e_pat then @result = [@buffer,$1,$2,$3,$4,$5,$6,$7,$8,$9] @buffer = $' log( "Buffer matched#{@e_pat.source}") @e_pat = nil @bufferResource.signal end end end rescue SystemCallError, EOFError => details log( details) log( details.backtrace.join("\n")) @mutex.synchronize do @bufferResource.signal end rescue RuntimeError => details raise details if details.to_s !~ /Child_changed/ ensure @log.close end def expect(pat,time_out=5) @result = nil @mutex.synchronize do case pat when String @e_pat = Regexp.new(Regexp.quote(pat)) when Regexp @e_pat = pat end log( @e_pat.source) if @buffer =~ @e_pat then @result = [@buffer,$1,$2,$3,$4,$5,$6,$7,$8,$9] @buffer = $' log( "Existing buffer matched#{@e_pat.source}") @e_pat = nil return @result end timeout( time_out) do @bufferResource.wait( @mutex) raise EOFError if @result.nil? end end return @result end def puts(str) log( str) @outf.puts str end end if __FILE__ == $0 PAUSE = 60 session = RExpect.spawn("ssh -l lyle fxruby.sourceforge.net") session.expect("-bash-2.05b$", PAUSE) session.puts("cd fxruby-htdocs/1.2") session.expect("-bash-2.05b$", PAUSE) session.puts("tar xzf ../doc.tar.gz") session.expect("-bash-2.05b$", PAUSE) session.puts("tar xzf ../examples.tar.gz") session.expect("-bash-2.05b$", PAUSE) # session.puts("tar xzf web.tar.gz") # session.expect("-bash-2.05b$", PAUSE) session.puts("exit") end