A version of Shell::Shell that acts synchronously, allowing clients to execute a command via a shell, wait for it to finish, and then inspect both the stdout and stderr from the command, as well as the exit status.
CommandOutput | = | Struct.new( :stdout, :stderr, :status ) |
A struct representing the result of executing a command. | ||
CONFIRMATION | = | "2357foobarbazzabraboof7532" |
The unique confirmation string that is used to recognize the end of a command’s execution. |
Create a new SyncShell that uses the given shell factory to obtain a shell to wrap. The other parameters are used
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 39 39: def initialize( shell, log, pty_opts ) 40: @log = log 41: @shell = shell.call( pty_opts ) 42: end
Reinterprets missing methods as requests to execute commands. The parameters to the method are concatenated together with spaces and sent to the shell via send_command.
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 103 103: def method_missing( sym, *args ) 104: cmd = sym.to_s 105: cmd << " " << args.join( " " ) unless args.empty? 106: send_command cmd 107: end
Delegates to Shell::Shell.open?
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 45 45: def open? 46: @shell.open? 47: end
Attempts to invoke the given command, which must not be terminated with a newline. If stdin is not nil, it will be sent to the shell immediately after sending the request to execute the command. It is expected that this will be used by the program that was just executed somehow, but this is not (cannot) be enforced.
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 54 54: def send_command( cmd, stdin=nil ) 55: @log.debug "executing #{cmd.inspect}" if @log.debug? 56: send_data "#{cmd}; echo -n #{CONFIRMATION} $?\n" 57: send_data stdin if stdin 58: 59: out = "" 60: err = "" 61: 62: @log.debug "waiting for #{cmd.inspect}" if @log.debug? 63: loop do 64: sleep 0.01 65: out << @shell.stdout while @shell.open? && @shell.stdout? 66: err << @shell.stderr while @shell.open? && @shell.stderr? 67: 68: break if !@shell.open? || out.index( CONFIRMATION + " " ) 69: end 70: 71: if @log.debug? 72: @log.debug "#{cmd.inspect} finished" 73: @log.debug " stdout --> #{out.inspect}" 74: @log.debug " stderr --> #{err.inspect}" 75: end 76: 77: if @shell.open? 78: match = out.match( /#{CONFIRMATION} /o ) 79: out = match.pre_match 80: status = match.post_match.strip.to_i 81: else 82: status = 0 83: end 84: 85: CommandOutput.new( out, ( err.empty? ? nil : err ), status ) 86: end
Sends the given string directly to the shell, without waiting for any response.
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 90 90: def send_data( data ) 91: @shell.send_data data 92: end
Dends the given string directly to the shell as the given type of data, without waiting for any response.
[ show source ]
# File lib/net/ssh/service/shell/sync.rb, line 96 96: def send_extended_data( type, data ) 97: @shell.send_extended_data type, data 98: end