class SftpWrapper::OpenSSH
The wrapper for OpenSSH's sftp command.
Constants
- DEFAULT_COMMAND_TIMEOUT
Default value of command timeout.
- DEFAULT_OPEN_TIMEOUT
Default value of open timeout.
- DEFAULT_READ_TIMEOUT
Default value of read timeout.
- DEFAULT_SSH_CONFIG
Default value of ssh config file path.
- DEFAULT_SSH_OPTIONS
Default value of ssh options
- PASSWORD_PROMPT_RE
pattern of password prompt.
- SFTP_PROMPT
sftp prompt.
- SFTP_PROMPT_RE
pattern of sftp prompt.
Attributes
Public Class Methods
Initialize SFTP wrapper.
@param host [String] host address of SFTP server @param port [Integer] port number of SFTP server @param username [String] user name of SFTP server @param password [String] password of SFTP server @param ssh_options
[Hash] SSH options (set as -o options) @param ssh_config
[String] path of SSH config file (set as -F option unless nil) @param open_timeout
[Integer, Float] @param read_timeout
[Integer, Float] @param command_timeout
[Integer, Float] @param debug [Boolean]
rubocop:disable Metrics/ParameterLists
# File lib/sftp_wrapper/open_ssh.rb, line 62 def initialize(host, port, username, password, ssh_options: {}, ssh_config: DEFAULT_SSH_CONFIG, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT, command_timeout: DEFAULT_COMMAND_TIMEOUT, debug: false) @host = host @port = port @username = username @password = password @ssh_options = DEFAULT_SSH_OPTIONS.merge(ssh_options) @ssh_config = ssh_config @open_timeout = open_timeout @read_timeout = read_timeout @command_timeout = command_timeout @debug = debug end
Public Instance Methods
Get remote file.
@param source [String] source file path @param destination [String] destination path @raise [SftpWrapper::Errors::ConnectionError] @raise [SftpWrapper::Errors::AuthenticationFailure] @raise [SftpWrapper::Errors::TimeoutError] @raise [SftpWrapper::Errors::CommandError]
# File lib/sftp_wrapper/open_ssh.rb, line 91 def download(source, destination) execute(%W[get #{source} #{destination}].shelljoin) end
Put local file.
@param source [String] source file path @param destination [String] destination path @raise [SftpWrapper::Errors::ConnectionError] @raise [SftpWrapper::Errors::AuthenticationFailure] @raise [SftpWrapper::Errors::TimeoutError] @raise [SftpWrapper::Errors::CommandError]
# File lib/sftp_wrapper/open_ssh.rb, line 104 def upload(source, destination) execute(%W[put #{source} #{destination}].shelljoin) end
Private Instance Methods
# File lib/sftp_wrapper/open_ssh.rb, line 146 def build_cli_args args = [] args << '-q' args += %W[-F #{ssh_config}] if ssh_config args += %W[-P #{port} -o User=#{username}] args += ssh_options.map { |k, v| %W[-o #{k}=#{v}] }.flatten args end
Execute sftp command.
@param command [String] SFTP command @raise [SftpWrapper::Errors::ConnectionError] @raise [SftpWrapper::Errors::AuthenticationFailure] @raise [SftpWrapper::Errors::TimeoutError] @raise [SftpWrapper::Errors::CommandError]
# File lib/sftp_wrapper/open_ssh.rb, line 118 def execute(command) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize cli = %w[sftp] + build_cli_args + [host] PTY.getpty(cli.shelljoin) do |r, w, _pid| w.sync = true unless safe_expect(r, PASSWORD_PROMPT_RE, open_timeout) raise SftpWrapper::Errors::ConnectionError, 'connection error.' end w.puts(password) unless safe_expect(r, SFTP_PROMPT_RE, read_timeout) raise SftpWrapper::Errors::AuthenticationFailure, 'authentication failure' end w.puts(command) res = safe_expect(r, SFTP_PROMPT_RE, command_timeout) raise SftpWrapper::Errors::TimeoutError, 'command timed out' unless res skip = command.bytesize + 2 error_message = res[0].byteslice(skip..-1).chomp.sub(/#{SFTP_PROMPT}\z/, '').chomp raise SftpWrapper::Errors::CommandError, error_message unless error_message.empty? w.puts('quit') end end
@see github.com/ruby/ruby/blob/13b692200dba1056fa9033f2c64c43453f6d6a98/ext/pty/pty.c#L716-L723
# File lib/sftp_wrapper/open_ssh.rb, line 156 def safe_expect(io, pattern, timeout) expect_verbose = $expect_verbose # rubocop:disable Style/GlobalVars $expect_verbose = debug # rubocop:disable Style/GlobalVars io.expect(pattern, timeout) rescue Errno::EIO nil ensure $expect_verbose = expect_verbose # rubocop:disable Style/GlobalVars end