Class: Net::SSH::Proxy::Command
- Inherits:
- 
      Object
      
        - Object
- Net::SSH::Proxy::Command
 
- Defined in:
- lib/net/ssh/proxy/command.rb
Overview
An implementation of a command proxy. To use it, instantiate it, then pass the instantiated object via the :proxy key to Net::SSH.start:
require 'net/ssh/proxy/command'
proxy = Net::SSH::Proxy::Command.new('ssh relay nc %h %p')
Net::SSH.start('host', 'user', :proxy => proxy) do |ssh|
  ...
end
Direct Known Subclasses
Instance Attribute Summary collapse
- 
  
    
      #command_line  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The command line for the session. 
- 
  
    
      #command_line_template  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    The command line template. 
- 
  
    
      #timeout  ⇒ Object 
    
    
  
  
  
  
    
    
  
  
  
  
  
  
    Timeout in seconds in open, defaults to 60. 
Instance Method Summary collapse
- #close_on_error(io) ⇒ Object
- 
  
    
      #initialize(command_line_template)  ⇒ Command 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    Create a new socket factory that tunnels via a command executed with the user’s shell, which is composed from the given command template. 
- 
  
    
      #open(host, port, connection_options = nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated. 
Constructor Details
#initialize(command_line_template) ⇒ Command
Create a new socket factory that tunnels via a command executed with the user’s shell, which is composed from the given command template. In the command template, ‘%h’ will be substituted by the host name to connect and ‘%p’ by the port.
| 34 35 36 37 38 | # File 'lib/net/ssh/proxy/command.rb', line 34 def initialize(command_line_template) @command_line_template = command_line_template @command_line = nil @timeout = 60 end | 
Instance Attribute Details
#command_line ⇒ Object (readonly)
The command line for the session
| 25 26 27 | # File 'lib/net/ssh/proxy/command.rb', line 25 def command_line @command_line end | 
#command_line_template ⇒ Object (readonly)
The command line template
| 22 23 24 | # File 'lib/net/ssh/proxy/command.rb', line 22 def command_line_template @command_line_template end | 
#timeout ⇒ Object
Timeout in seconds in open, defaults to 60
| 28 29 30 | # File 'lib/net/ssh/proxy/command.rb', line 28 def timeout @timeout end | 
Instance Method Details
#close_on_error(io) ⇒ Object
| 117 118 119 120 | # File 'lib/net/ssh/proxy/command.rb', line 117 def close_on_error(io) Process.kill('TERM', io.pid) Thread.new { io.close } end | 
#open(host, port, connection_options = nil) ⇒ Object
Return a new socket connected to the given host and port via the proxy that was requested when the socket factory was instantiated.
| 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # File 'lib/net/ssh/proxy/command.rb', line 42 def open(host, port, = nil) command_line = @command_line_template.gsub(/%(.)/) { case $1 when 'h' host when 'p' port.to_s when 'r' remote_user = && [:remote_user] if remote_user remote_user else raise ArgumentError, "remote user name not available" end when '%' '%' else raise ArgumentError, "unknown key: #{$1}" end } begin io = IO.popen(command_line, "r+") begin if result = IO.select([io], nil, [io], @timeout) if result.last.any? || io.eof? raise "command failed" end else raise "command timed out" end rescue StandardError close_on_error(io) raise end rescue StandardError => e raise ConnectError, "#{e}: #{command_line}" end @command_line = command_line if Gem.win_platform? # read_nonblock and write_nonblock are not available on Windows # pipe. Use sysread and syswrite as a replacement works. def io.send(data, flag) syswrite(data) end def io.recv(size) sysread(size) end else def io.send(data, flag) begin result = write_nonblock(data) rescue IO::WaitWritable, Errno::EINTR IO.select(nil, [self]) retry end result end def io.recv(size) begin result = read_nonblock(size) rescue IO::WaitReadable, Errno::EINTR timeout_in_seconds = 20 if IO.select([self], nil, [self], timeout_in_seconds) == nil raise "Unexpected spurious read wakeup" end retry end result end end io end |