lib/sshake/session.rb
# The underlying net/ssh session
#
# @return [Net::SSH::Session]
The underlying net/ssh session
The underlying net / ssh session
def execute(commands, options = nil, &block)
      options = create_options(options, block)
      command_to_execute = prepare_commands(commands, options)
      response = Response.new
      response.command = command_to_execute
      connect unless connected?
      log :info, "Executing: #{command_to_execute}"
      log :debug, "Timeout: #{options.timeout}"
      begin
        channel = nil
        Timeout.timeout(options.timeout) do
          channel = @session.open_channel do |ch|
            response.start_time = Time.now
            channel.exec(command_to_execute) do |_, success|
              raise "Command \"#{command_to_execute}\" was unable to execute" unless success
              ch.send_data(options.stdin) if options.stdin
              if options.file_to_stream.nil? && options.sudo_password.nil?
                log :debug, 'Sending EOF to channel'
                ch.eof!
              end
              ch.on_data do |_, data|
                response.stdout += data
                options.stdout&.call(data)
                log :debug, data.gsub(/\r/, '')
              end
              ch.on_extended_data do |_, _, data|
                response.stderr += data.delete("\r")
                options.stderr&.call(data)
                log :debug, data
                if options.sudo_password && data =~ /^\[sshake-sudo-password\]:\s\z/
                  log :debug, 'Sending sudo password'
                  ch.send_data "#{options.sudo_password}\n"
                  if options.file_to_stream.nil?
                    log :debug, 'Sending EOF after sudo password because no file'
                    ch.eof!
                  end
                end
              end
              ch.on_request('exit-status') do |_, data|
                response.exit_code = data.read_long&.to_i
                log :debug, "Exit code: #{response.exit_code}"
              end
              ch.on_request('exit-signal') do |_, data|
                response.exit_signal = data.read_long
              end
              if options.file_to_stream
                ch.on_process do |_, data|
                  next if ch.eof?
                  if ch.output.length < 128 * 1024
                    if data = options.file_to_stream.read(1024 * 1024)
                      ch.send_data(data)
                      response.bytes_streamed += data.bytesize
                    else
                      ch.eof!
                    end
                  end
                end
              end
            end
          end
          channel.wait
        end
      rescue Timeout::Error
        log :debug, 'Got timeout error while executing command'
        kill!
        response.timeout!
      ensure
        response.finish_time = Time.now
      end
      handle_response(response, options)
    end
def execute ( commands , options = nil , & block ) options = create_options ( options , block ) command_to_execute = prepare_commands ( commands , options ) response = Response . new response . command = command_to_execute connect unless connected? log :info , "Executing: #{command_to_execute}" log :debug , "Timeout: #{options.timeout}" begin channel = nil Timeout . timeout ( options . timeout ) do channel = @session . open_channel do | ch | response . start_time = Time . now channel . exec ( command_to_execute ) do | _ , success | raise "Command \"#{command_to_execute}\" was unable to execute" unless success ch . send_data ( options . stdin ) if options . stdin if options . file_to_stream . nil? && options . sudo_password . nil? log :debug , 'Sending EOF to channel' ch . eof! end ch . on_data do | _ , data | response . stdout += data options . stdout &. call ( data ) log :debug , data . gsub ( / \r / , '' ) end ch . on_extended_data do | _ , _ , data | response . stderr += data . delete ( "\r" ) options . stderr &. call ( data ) log :debug , data if options . sudo_password && data =~ / ^ \[ sshake-sudo-password \] : \s \z / log :debug , 'Sending sudo password' ch . send_data "#{options.sudo_password}\n" if options . file_to_stream . nil? log :debug , 'Sending EOF after sudo password because no file' ch . eof! end end end ch . on_request ( 'exit-status' ) do | _ , data | response . exit_code = data . read_long &. to_i log :debug , "Exit code: #{response.exit_code}" end ch . on_request ( 'exit-signal' ) do | _ , data | response . exit_signal = data . read_long end if options . file_to_stream ch . on_process do | _ , data | next if ch . eof? if ch . output . length < 128 * 1024 if data = options . file_to_stream . read ( 1024 * 1024 ) ch . send_data ( data ) response . bytes_streamed += data . bytesize else ch . eof! end end end end end end channel . wait end rescue Timeout :: Error log :debug , 'Got timeout error while executing command' kill! response . timeout! ensure response . finish_time = Time . now end handle_response ( response , options ) end
The underlying net/ssh session
The underlying net / ssh session
# Execute the command # Log the command
None
Net::SSH::Session
commands
options
block