Class Net::SSH::Connection::Channel
In: lib/net/ssh/connection/channel.rb
lib/net/ssh/connection/channel.rb
Parent: Object

The channel abstraction. Multiple "channels" can be multiplexed onto a single SSH channel, each operating independently and seemingly in parallel. This class represents a single such channel. Most operations performed with the Net::SSH library will involve using one or more channels.

Channels are intended to be used asynchronously. You request that one be opened (via Connection::Session#open_channel), and when it is opened, your callback is invoked. Then, you set various other callbacks on the newly opened channel, which are called in response to the corresponding events. Programming with Net::SSH works best if you think of your programs as state machines. Complex programs are best implemented as objects that wrap a channel. See Net::SCP and Net::SFTP for examples of how complex state machines can be built on top of the SSH protocol.

  ssh.open_channel do |channel|
    channel.exec("/invoke/some/command") do |ch, success|
      abort "could not execute command" unless success

      channel.on_data do |ch, data|
        puts "got stdout: #{data}"
        channel.send_data "something for stdin\n"
      end

      channel.on_extended_data do |ch, type, data|
        puts "got stderr: #{data}"
      end

      channel.on_close do |ch|
        puts "channel is closing!"
      end
    end
  end

  ssh.loop

Channels also have a basic hash-like interface, that allows programs to store arbitrary state information on a channel object. This helps simplify the writing of state machines, especially when you may be juggling multiple open channels at the same time.

Note that data sent across SSH channels are governed by maximum packet sizes and maximum window sizes. These details are managed internally by Net::SSH::Connection::Channel, so you may remain blissfully ignorant if you so desire, but you can always inspect the current maximums, as well as the remaining window size, using the reader attributes for those values.

Methods

Included Modules

Constants Loggable Constants Loggable

Constants

VALID_PTY_OPTIONS = { :term => "xterm", :chars_wide => 80, :chars_high => 24, :pixels_wide => 640, :pixels_high => 480, :modes => {} }   A hash of the valid PTY options (see request_pty).
VALID_PTY_OPTIONS = { :term => "xterm", :chars_wide => 80, :chars_high => 24, :pixels_wide => 640, :pixels_high => 480, :modes => {} }   A hash of the valid PTY options (see request_pty).

Attributes

connection  [R]  The underlying Net::SSH::Connection::Session instance that supports this channel.
connection  [R]  The underlying Net::SSH::Connection::Session instance that supports this channel.
local_id  [R]  The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
local_id  [R]  The local id for this channel, assigned by the Net::SSH::Connection::Session instance.
local_maximum_packet_size  [R]  The maximum packet size that the local host can receive.
local_maximum_packet_size  [R]  The maximum packet size that the local host can receive.
local_maximum_window_size  [R]  The maximum amount of data that the local end of this channel can receive. This is a total, not per-packet.
local_maximum_window_size  [R]  The maximum amount of data that the local end of this channel can receive. This is a total, not per-packet.
local_window_size  [R]  This is the remaining window size on the local end of this channel. When this reaches zero, no more data can be received.
local_window_size  [R]  This is the remaining window size on the local end of this channel. When this reaches zero, no more data can be received.
properties  [R]  A hash of properties for this channel. These can be used to store state information about this channel. See also #[] and #[]=.
properties  [R]  A hash of properties for this channel. These can be used to store state information about this channel. See also #[] and #[]=.
remote_id  [R]  The remote id for this channel, assigned by the remote host.
remote_id  [R]  The remote id for this channel, assigned by the remote host.
remote_maximum_packet_size  [R]  The maximum packet size that the remote host can receive.
remote_maximum_packet_size  [R]  The maximum packet size that the remote host can receive.
remote_maximum_window_size  [R]  The maximum amount of data that the remote end of this channel can receive. This is a total, not per-packet.
remote_maximum_window_size  [R]  The maximum amount of data that the remote end of this channel can receive. This is a total, not per-packet.
remote_window_size  [R]  This is the remaining window size on the remote end of this channel. When this reaches zero, no more data can be sent.
remote_window_size  [R]  This is the remaining window size on the remote end of this channel. When this reaches zero, no more data can be sent.
type  [R]  The type of this channel, usually "session".
type  [R]  The type of this channel, usually "session".

Public Class methods

Instantiates a new channel on the given connection, of the given type, and with the given id. If a block is given, it will be remembered until the channel is confirmed open by the server, and will be invoked at that time (see do_open_confirmation).

This also sets the default maximum packet size and maximum window size.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 110
110:     def initialize(connection, type, local_id, &on_confirm_open)
111:       self.logger = connection.logger
112: 
113:       @connection = connection
114:       @type       = type
115:       @local_id   = local_id
116: 
117:       @local_maximum_packet_size = 0x10000
118:       @local_window_size = @local_maximum_window_size = 0x20000
119: 
120:       @on_confirm_open = on_confirm_open
121: 
122:       @output = Buffer.new
123: 
124:       @properties = {}
125: 
126:       @pending_requests = []
127:       @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
128:       @on_request = {}
129:       @closing = @eof = false
130:     end

Instantiates a new channel on the given connection, of the given type, and with the given id. If a block is given, it will be remembered until the channel is confirmed open by the server, and will be invoked at that time (see do_open_confirmation).

This also sets the default maximum packet size and maximum window size.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 110
110:     def initialize(connection, type, local_id, &on_confirm_open)
111:       self.logger = connection.logger
112: 
113:       @connection = connection
114:       @type       = type
115:       @local_id   = local_id
116: 
117:       @local_maximum_packet_size = 0x10000
118:       @local_window_size = @local_maximum_window_size = 0x20000
119: 
120:       @on_confirm_open = on_confirm_open
121: 
122:       @output = Buffer.new
123: 
124:       @properties = {}
125: 
126:       @pending_requests = []
127:       @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
128:       @on_request = {}
129:       @closing = @eof = false
130:     end

Public Instance methods

A shortcut for accessing properties of the channel (see properties).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 133
133:     def [](name)
134:       @properties[name]
135:     end

A shortcut for accessing properties of the channel (see properties).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 133
133:     def [](name)
134:       @properties[name]
135:     end

A shortcut for setting properties of the channel (see properties).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 138
138:     def []=(name, value)
139:       @properties[name] = value
140:     end

A shortcut for setting properties of the channel (see properties).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 138
138:     def []=(name, value)
139:       @properties[name] = value
140:     end

Returns true if the channel exists in the channel list of the session, and false otherwise. This can be used to determine whether a channel has been closed or not.

  ssh.loop { channel.active? }

[Source]

     # File lib/net/ssh/connection/channel.rb, line 259
259:     def active?
260:       connection.channels.key?(local_id)
261:     end

Returns true if the channel exists in the channel list of the session, and false otherwise. This can be used to determine whether a channel has been closed or not.

  ssh.loop { channel.active? }

[Source]

     # File lib/net/ssh/connection/channel.rb, line 259
259:     def active?
260:       connection.channels.key?(local_id)
261:     end

Requests that the channel be closed. If the channel is already closing, this does nothing, nor does it do anything if the channel has not yet been confirmed open (see do_open_confirmation). Otherwise, it sends a CHANNEL_CLOSE message and marks the channel as closing.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 284
284:     def close
285:       return if @closing
286:       if remote_id
287:         @closing = true
288:         connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
289:       end
290:     end

Requests that the channel be closed. If the channel is already closing, this does nothing, nor does it do anything if the channel has not yet been confirmed open (see do_open_confirmation). Otherwise, it sends a CHANNEL_CLOSE message and marks the channel as closing.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 284
284:     def close
285:       return if @closing
286:       if remote_id
287:         @closing = true
288:         connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
289:       end
290:     end

Returns true if the channel is currently closing, but not actually closed. A channel is closing when, for instance, close has been invoked, but the server has not yet responded with a CHANNEL_CLOSE packet of its own.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 276
276:     def closing?
277:       @closing
278:     end

Returns true if the channel is currently closing, but not actually closed. A channel is closing when, for instance, close has been invoked, but the server has not yet responded with a CHANNEL_CLOSE packet of its own.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 276
276:     def closing?
277:       @closing
278:     end

Invokes the on_close callback when the server closes a channel. The channel is the only argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 584
584:       def do_close
585:         @on_close.call(self) if @on_close
586:       end

Invokes the on_close callback when the server closes a channel. The channel is the only argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 584
584:       def do_close
585:         @on_close.call(self) if @on_close
586:       end

Invokes the on_eof callback when the server indicates that no further data is forthcoming. The callback is invoked with the channel as the argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 578
578:       def do_eof
579:         @on_eof.call(self) if @on_eof
580:       end

Invokes the on_eof callback when the server indicates that no further data is forthcoming. The callback is invoked with the channel as the argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 578
578:       def do_eof
579:         @on_eof.call(self) if @on_eof
580:       end

Invokes the on_extended_data callback when the server sends extended data to the channel. This will reduce the available window size on the local end. The callback is invoked with the channel, type, and data.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 570
570:       def do_extended_data(type, data)
571:         update_local_window_size(data.length)
572:         @on_extended_data.call(self, type, data) if @on_extended_data
573:       end

Invokes the on_extended_data callback when the server sends extended data to the channel. This will reduce the available window size on the local end. The callback is invoked with the channel, type, and data.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 570
570:       def do_extended_data(type, data)
571:         update_local_window_size(data.length)
572:         @on_extended_data.call(self, type, data) if @on_extended_data
573:       end

Invokes the next pending request callback with false as the second argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 590
590:       def do_failure
591:         if callback = pending_requests.shift
592:           callback.call(self, false)
593:         else
594:           error { "channel failure recieved with no pending request to handle it (bug?)" }
595:         end
596:       end

Invokes the next pending request callback with false as the second argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 590
590:       def do_failure
591:         if callback = pending_requests.shift
592:           callback.call(self, false)
593:         else
594:           error { "channel failure recieved with no pending request to handle it (bug?)" }
595:         end
596:       end

Invoked when the server failed to open the channel. If an on_open_failed callback was specified, it will be invoked with the channel, reason code, and description as arguments. Otherwise, a ChannelOpenFailed exception will be raised.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 515
515:       def do_open_failed(reason_code, description)
516:         if @on_open_failed
517:           @on_open_failed.call(self, reason_code, description)
518:         else
519:           raise ChannelOpenFailed.new(reason_code, description)
520:         end          
521:       end

Invoked when the server failed to open the channel. If an on_open_failed callback was specified, it will be invoked with the channel, reason code, and description as arguments. Otherwise, a ChannelOpenFailed exception will be raised.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 515
515:       def do_open_failed(reason_code, description)
516:         if @on_open_failed
517:           @on_open_failed.call(self, reason_code, description)
518:         else
519:           raise ChannelOpenFailed.new(reason_code, description)
520:         end          
521:       end

Invokes the next pending request callback with true as the second argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 600
600:       def do_success
601:         if callback = pending_requests.shift
602:           callback.call(self, true)
603:         else
604:           error { "channel success recieved with no pending request to handle it (bug?)" }
605:         end
606:       end

Invokes the next pending request callback with true as the second argument.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 600
600:       def do_success
601:         if callback = pending_requests.shift
602:           callback.call(self, true)
603:         else
604:           error { "channel success recieved with no pending request to handle it (bug?)" }
605:         end
606:       end

Syntactic sugar for setting an environment variable in the remote process’ environment. Note that for security reasons, the server may refuse to set certain environment variables, or all, at the server‘s discretion. If you are connecting to an OpenSSH server, you will need to update the AcceptEnv setting in the sshd_config to include the environment variables you want to send.

  channel.env "PATH", "/usr/local/bin"

[Source]

     # File lib/net/ssh/connection/channel.rb, line 187
187:     def env(variable_name, variable_value, &block)
188:       send_channel_request("env", :string, variable_name, :string, variable_value, &block)
189:     end

Syntactic sugar for setting an environment variable in the remote process’ environment. Note that for security reasons, the server may refuse to set certain environment variables, or all, at the server‘s discretion. If you are connecting to an OpenSSH server, you will need to update the AcceptEnv setting in the sshd_config to include the environment variables you want to send.

  channel.env "PATH", "/usr/local/bin"

[Source]

     # File lib/net/ssh/connection/channel.rb, line 187
187:     def env(variable_name, variable_value, &block)
188:       send_channel_request("env", :string, variable_name, :string, variable_value, &block)
189:     end

Tells the remote end of the channel that no more data is forthcoming from this end of the channel. The remote end may still send data.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 301
301:     def eof!
302:       return if eof?
303:       @eof = true
304:       connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
305:     end

Tells the remote end of the channel that no more data is forthcoming from this end of the channel. The remote end may still send data.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 301
301:     def eof!
302:       return if eof?
303:       @eof = true
304:       connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
305:     end

Returns true if the local end of the channel has declared that no more data is forthcoming (see eof!). Trying to send data via send_data when this is true will result in an exception being raised.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 295
295:     def eof?
296:       @eof
297:     end

Returns true if the local end of the channel has declared that no more data is forthcoming (see eof!). Trying to send data via send_data when this is true will result in an exception being raised.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 295
295:     def eof?
296:       @eof
297:     end

Syntactic sugar for executing a command. Sends a channel request asking that the given command be invoked. If the block is given, it will be called when the server responds. The first parameter will be the channel, and the second will be true or false, indicating whether the request succeeded or not. In this case, success means that the command is being executed, not that it has completed, and failure means that the command altogether failed to be executed.

  channel.exec "ls -l /home" do |ch, success|
    if success
      puts "command has begun executing..."
      # this is a good place to hang callbacks like #on_data...
    else
      puts "alas! the command could not be invoked!"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 158
158:     def exec(command, &block)
159:       send_channel_request("exec", :string, command, &block)
160:     end

Syntactic sugar for executing a command. Sends a channel request asking that the given command be invoked. If the block is given, it will be called when the server responds. The first parameter will be the channel, and the second will be true or false, indicating whether the request succeeded or not. In this case, success means that the command is being executed, not that it has completed, and failure means that the command altogether failed to be executed.

  channel.exec "ls -l /home" do |ch, success|
    if success
      puts "command has begun executing..."
      # this is a good place to hang callbacks like #on_data...
    else
      puts "alas! the command could not be invoked!"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 158
158:     def exec(command, &block)
159:       send_channel_request("exec", :string, command, &block)
160:     end

Registers a callback to be invoked when the server acknowledges that a channel is closed. This is invoked with the channel as the sole argument.

  channel.on_close do |ch|
    puts "remote end is closing!"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 378
378:     def on_close(&block)
379:       old, @on_close = @on_close, block
380:       old
381:     end

Registers a callback to be invoked when the server acknowledges that a channel is closed. This is invoked with the channel as the sole argument.

  channel.on_close do |ch|
    puts "remote end is closing!"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 378
378:     def on_close(&block)
379:       old, @on_close = @on_close, block
380:       old
381:     end

Registers a callback to be invoked when data packets are received by the channel. The callback is called with the channel as the first argument, and the data as the second.

  channel.on_data do |ch, data|
    puts "got data: #{data.inspect}"
  end

Data received this way is typically the data written by the remote process to its stdout stream.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 325
325:     def on_data(&block)
326:       old, @on_data = @on_data, block
327:       old
328:     end

Registers a callback to be invoked when data packets are received by the channel. The callback is called with the channel as the first argument, and the data as the second.

  channel.on_data do |ch, data|
    puts "got data: #{data.inspect}"
  end

Data received this way is typically the data written by the remote process to its stdout stream.

[Source]

     # File lib/net/ssh/connection/channel.rb, line 325
325:     def on_data(&block)
326:       old, @on_data = @on_data, block
327:       old
328:     end

Registers a callback to be invoked when the server indicates that no more data will be sent to the channel (although the channel can still send data to the server). The channel is the sole argument to the callback.

  channel.on_eof do |ch|
    puts "remote end is done sending data"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 390
390:     def on_eof(&block)
391:       old, @on_eof = @on_eof, block
392:       old
393:     end

Registers a callback to be invoked when the server indicates that no more data will be sent to the channel (although the channel can still send data to the server). The channel is the sole argument to the callback.

  channel.on_eof do |ch|
    puts "remote end is done sending data"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 390
390:     def on_eof(&block)
391:       old, @on_eof = @on_eof, block
392:       old
393:     end

Registers a callback to be invoked when extended data packets are received by the channel. The callback is called with the channel as the first argument, the data type (as an integer) as the second, and the data as the third. Extended data is almost exclusively used to send stderr data (type == 1). Other extended data types are not defined by the SSH protocol.

  channel.on_extended_data do |ch, type, data|
    puts "got stderr: #{data.inspect}"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 340
340:     def on_extended_data(&block)
341:       old, @on_extended_data = @on_extended_data, block
342:       old
343:     end

Registers a callback to be invoked when extended data packets are received by the channel. The callback is called with the channel as the first argument, the data type (as an integer) as the second, and the data as the third. Extended data is almost exclusively used to send stderr data (type == 1). Other extended data types are not defined by the SSH protocol.

  channel.on_extended_data do |ch, type, data|
    puts "got stderr: #{data.inspect}"
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 340
340:     def on_extended_data(&block)
341:       old, @on_extended_data = @on_extended_data, block
342:       old
343:     end

Registers a callback to be invoked when the server was unable to open the requested channel. The channel itself will be passed to the block, along with the integer "reason code" for the failure, and a textual description of the failure from the server.

  channel = session.open_channel do |ch|
    # ..
  end

  channel.on_open_failed { |ch, code, desc| ... }

[Source]

     # File lib/net/ssh/connection/channel.rb, line 405
405:     def on_open_failed(&block)
406:       old, @on_open_failed = @on_open_failed, block
407:       old
408:     end

Registers a callback to be invoked when the server was unable to open the requested channel. The channel itself will be passed to the block, along with the integer "reason code" for the failure, and a textual description of the failure from the server.

  channel = session.open_channel do |ch|
    # ..
  end

  channel.on_open_failed { |ch, code, desc| ... }

[Source]

     # File lib/net/ssh/connection/channel.rb, line 405
405:     def on_open_failed(&block)
406:       old, @on_open_failed = @on_open_failed, block
407:       old
408:     end

Registers a callback to be invoked for each pass of the event loop for this channel. There are no guarantees on timeliness in the event loop, but it will be called roughly once for each packet received by the connection (not the channel). This callback is invoked with the channel as the sole argument.

Here‘s an example that accumulates the channel data into a variable on the channel itself, and displays individual lines in the input one at a time when the channel is processed:

  channel[:data] = ""

  channel.on_data do |ch, data|
    channel[:data] << data
  end

  channel.on_process do |ch|
    if channel[:data] =~ /^.*?\n/
      puts $&
      channel[:data] = $'
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 367
367:     def on_process(&block)
368:       old, @on_process = @on_process, block
369:       old
370:     end

Registers a callback to be invoked for each pass of the event loop for this channel. There are no guarantees on timeliness in the event loop, but it will be called roughly once for each packet received by the connection (not the channel). This callback is invoked with the channel as the sole argument.

Here‘s an example that accumulates the channel data into a variable on the channel itself, and displays individual lines in the input one at a time when the channel is processed:

  channel[:data] = ""

  channel.on_data do |ch, data|
    channel[:data] << data
  end

  channel.on_process do |ch|
    if channel[:data] =~ /^.*?\n/
      puts $&
      channel[:data] = $'
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 367
367:     def on_process(&block)
368:       old, @on_process = @on_process, block
369:       old
370:     end

Registers a callback to be invoked when a channel request of the given type is received. The callback will receive the channel as the first argument, and the associated (unparsed) data as the second. The data will be a Net::SSH::Buffer that you will need to parse, yourself, according to the kind of request you are watching.

By default, if the request wants a reply, Net::SSH will send a CHANNEL_SUCCESS response for any request that was handled by a registered callback, and CHANNEL_FAILURE for any that wasn‘t, but if you want your registered callback to result in a CHANNEL_FAILURE response, just raise Net::SSH::ChannelRequestFailed.

Some common channel requests that your programs might want to listen for are:

  • "exit-status" : the exit status of the remote process will be reported as a long integer in the data buffer, which you can grab via data.read_long.
  • "exit-signal" : if the remote process died as a result of a signal being sent to it, the signal will be reported as a string in the data, via data.read_string. (Not all SSH servers support this channel request type.)

    channel.on_request "exit-status" do |ch, data|

      puts "process terminated with exit status: #{data.read_long}"
    

    end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 436
436:     def on_request(type, &block)
437:       old, @on_request[type] = @on_request[type], block
438:       old
439:     end

Registers a callback to be invoked when a channel request of the given type is received. The callback will receive the channel as the first argument, and the associated (unparsed) data as the second. The data will be a Net::SSH::Buffer that you will need to parse, yourself, according to the kind of request you are watching.

By default, if the request wants a reply, Net::SSH will send a CHANNEL_SUCCESS response for any request that was handled by a registered callback, and CHANNEL_FAILURE for any that wasn‘t, but if you want your registered callback to result in a CHANNEL_FAILURE response, just raise Net::SSH::ChannelRequestFailed.

Some common channel requests that your programs might want to listen for are:

  • "exit-status" : the exit status of the remote process will be reported as a long integer in the data buffer, which you can grab via data.read_long.
  • "exit-signal" : if the remote process died as a result of a signal being sent to it, the signal will be reported as a string in the data, via data.read_string. (Not all SSH servers support this channel request type.)

    channel.on_request "exit-status" do |ch, data|

      puts "process terminated with exit status: #{data.read_long}"
    

    end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 436
436:     def on_request(type, &block)
437:       old, @on_request[type] = @on_request[type], block
438:       old
439:     end

If an on_process handler has been set up, this will cause it to be invoked (passing the channel itself as an argument). It also causes all pending output to be enqueued as CHANNEL_DATA packets (see enqueue_pending_output).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 310
310:     def process
311:       @on_process.call(self) if @on_process
312:       enqueue_pending_output
313:     end

If an on_process handler has been set up, this will cause it to be invoked (passing the channel itself as an argument). It also causes all pending output to be enqueued as CHANNEL_DATA packets (see enqueue_pending_output).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 310
310:     def process
311:       @on_process.call(self) if @on_process
312:       enqueue_pending_output
313:     end

Requests that a pseudo-tty (or "pty") be made available for this channel. This is useful when you want to invoke and interact with some kind of screen-based program (e.g., vim, or some menuing system).

Note, that without a pty some programs (e.g. sudo, or subversion) on some systems, will not be able to run interactively, and will error instead of prompt if they ever need some user interaction.

Note, too, that when a pty is requested, user‘s shell configuration scripts (.bashrc and such) are not run by default, whereas they are run when a pty is not present.

  channel.request_pty do |ch, success|
    if success
      puts "pty successfully obtained"
    else
      puts "could not obtain pty"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 218
218:     def request_pty(opts={}, &block)
219:       extra = opts.keys - VALID_PTY_OPTIONS.keys
220:       raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any?
221: 
222:       opts = VALID_PTY_OPTIONS.merge(opts)
223: 
224:       modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)|
225:         memo.write_byte(mode).write_long(data)
226:       end
227:       # mark the end of the mode opcode list with a 0 byte
228:       modes.write_byte(0)
229: 
230:       send_channel_request("pty-req", :string, opts[:term],
231:         :long, opts[:chars_wide], :long, opts[:chars_high],
232:         :long, opts[:pixels_wide], :long, opts[:pixels_high],
233:         :string, modes.to_s, &block)
234:     end

Requests that a pseudo-tty (or "pty") be made available for this channel. This is useful when you want to invoke and interact with some kind of screen-based program (e.g., vim, or some menuing system).

Note, that without a pty some programs (e.g. sudo, or subversion) on some systems, will not be able to run interactively, and will error instead of prompt if they ever need some user interaction.

Note, too, that when a pty is requested, user‘s shell configuration scripts (.bashrc and such) are not run by default, whereas they are run when a pty is not present.

  channel.request_pty do |ch, success|
    if success
      puts "pty successfully obtained"
    else
      puts "could not obtain pty"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 218
218:     def request_pty(opts={}, &block)
219:       extra = opts.keys - VALID_PTY_OPTIONS.keys
220:       raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any?
221: 
222:       opts = VALID_PTY_OPTIONS.merge(opts)
223: 
224:       modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)|
225:         memo.write_byte(mode).write_long(data)
226:       end
227:       # mark the end of the mode opcode list with a 0 byte
228:       modes.write_byte(0)
229: 
230:       send_channel_request("pty-req", :string, opts[:term],
231:         :long, opts[:chars_wide], :long, opts[:chars_high],
232:         :long, opts[:pixels_wide], :long, opts[:pixels_high],
233:         :string, modes.to_s, &block)
234:     end

Sends a new channel request with the given name. The extra data parameter must either be empty, or consist of an even number of arguments. See Net::SSH::Buffer.from for a description of their format. If a block is given, it is registered as a callback for a pending request, and the packet will be flagged so that the server knows a reply is required. If no block is given, the server will send no response to this request. Responses, where required, will cause the callback to be invoked with the channel as the first argument, and either true or false as the second, depending on whether the request succeeded or not. The meaning of "success" and "failure" in this context is dependent on the specific request that was sent.

  channel.send_channel_request "shell" do |ch, success|
    if success
      puts "user shell started successfully"
    else
      puts "could not start user shell"
    end
  end

Most channel requests you‘ll want to send are already wrapped in more convenient helper methods (see exec and subsystem).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 463
463:     def send_channel_request(request_name, *data, &callback)
464:       info { "sending channel request #{request_name.inspect}" }
465:       msg = Buffer.from(:byte, CHANNEL_REQUEST,
466:         :long, remote_id, :string, request_name,
467:         :bool, !callback.nil?, *data)
468:       connection.send_message(msg)
469:       pending_requests << callback if callback
470:     end

Sends a new channel request with the given name. The extra data parameter must either be empty, or consist of an even number of arguments. See Net::SSH::Buffer.from for a description of their format. If a block is given, it is registered as a callback for a pending request, and the packet will be flagged so that the server knows a reply is required. If no block is given, the server will send no response to this request. Responses, where required, will cause the callback to be invoked with the channel as the first argument, and either true or false as the second, depending on whether the request succeeded or not. The meaning of "success" and "failure" in this context is dependent on the specific request that was sent.

  channel.send_channel_request "shell" do |ch, success|
    if success
      puts "user shell started successfully"
    else
      puts "could not start user shell"
    end
  end

Most channel requests you‘ll want to send are already wrapped in more convenient helper methods (see exec and subsystem).

[Source]

     # File lib/net/ssh/connection/channel.rb, line 463
463:     def send_channel_request(request_name, *data, &callback)
464:       info { "sending channel request #{request_name.inspect}" }
465:       msg = Buffer.from(:byte, CHANNEL_REQUEST,
466:         :long, remote_id, :string, request_name,
467:         :bool, !callback.nil?, *data)
468:       connection.send_message(msg)
469:       pending_requests << callback if callback
470:     end

Sends data to the channel‘s remote endpoint. This usually has the effect of sending the given string to the remote process’ stdin stream. Note that it does not immediately send the data across the channel, but instead merely appends the given data to the channel‘s output buffer, preparatory to being packaged up and sent out the next time the connection is accepting data. (A connection might not be accepting data if, for instance, it has filled its data window and has not yet been resized by the remote end-point.)

This will raise an exception if the channel has previously declared that no more data will be sent (see eof!).

  channel.send_data("the password\n")

[Source]

     # File lib/net/ssh/connection/channel.rb, line 249
249:     def send_data(data)
250:       raise EOFError, "cannot send data if channel has declared eof" if eof?
251:       output.append(data.to_s)
252:     end

Sends data to the channel‘s remote endpoint. This usually has the effect of sending the given string to the remote process’ stdin stream. Note that it does not immediately send the data across the channel, but instead merely appends the given data to the channel‘s output buffer, preparatory to being packaged up and sent out the next time the connection is accepting data. (A connection might not be accepting data if, for instance, it has filled its data window and has not yet been resized by the remote end-point.)

This will raise an exception if the channel has previously declared that no more data will be sent (see eof!).

  channel.send_data("the password\n")

[Source]

     # File lib/net/ssh/connection/channel.rb, line 249
249:     def send_data(data)
250:       raise EOFError, "cannot send data if channel has declared eof" if eof?
251:       output.append(data.to_s)
252:     end

Syntactic sugar for requesting that a subsystem be started. Subsystems are a way for other protocols (like SFTP) to be run, using SSH as the transport. Generally, you‘ll never need to call this directly unless you are the implementor of something that consumes an SSH subsystem, like SFTP.

  channel.subsystem("sftp") do |ch, success|
    if success
      puts "subsystem successfully started"
    else
      puts "subsystem could not be started"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 175
175:     def subsystem(subsystem, &block)
176:       send_channel_request("subsystem", :string, subsystem, &block)
177:     end

Syntactic sugar for requesting that a subsystem be started. Subsystems are a way for other protocols (like SFTP) to be run, using SSH as the transport. Generally, you‘ll never need to call this directly unless you are the implementor of something that consumes an SSH subsystem, like SFTP.

  channel.subsystem("sftp") do |ch, success|
    if success
      puts "subsystem successfully started"
    else
      puts "subsystem could not be started"
    end
  end

[Source]

     # File lib/net/ssh/connection/channel.rb, line 175
175:     def subsystem(subsystem, &block)
176:       send_channel_request("subsystem", :string, subsystem, &block)
177:     end

Runs the SSH event loop until the channel is no longer active. This is handy for blocking while you wait for some channel to finish.

  channel.exec("grep ...") { ... }
  channel.wait

[Source]

     # File lib/net/ssh/connection/channel.rb, line 268
268:     def wait
269:       connection.loop { active? }
270:     end

Runs the SSH event loop until the channel is no longer active. This is handy for blocking while you wait for some channel to finish.

  channel.exec("grep ...") { ... }
  channel.wait

[Source]

     # File lib/net/ssh/connection/channel.rb, line 268
268:     def wait
269:       connection.loop { active? }
270:     end

[Validate]