Connection timing out?

235 Views Asked by At

I have simple connection object

require 'net/sftp'
@con = Net::SFTP.start(@@host, @@username, :password => @@password
...
@con.upload!(filepath, destination)

I have this in a script that listens for files being dropped into a folder. The files are collected, and uploaded to a remote sfpt server. It all works fine, but it seems after the script is left running for long enough, it will break and throw this error:

exception while processing events: Write to the server failed

I can only assume this happens because the idle connection is disconnecting after a certain amount of time. Is there away to keep the connection open indefinitely? or is that a limitation?

If thats not possible, is there away I can manage the error? Something like:

begin
    @con.upload!(filepath, destination)
rescue Net::SFTPStatusException => e
    if e.code == 7 //connection lost code
        @con.{reconnect}//Whatever this would look like
    end
    else
        raise
    end
end

Not sure if 7 is the right error code, or how I could reconnect the connection object.

2

There are 2 best solutions below

0
Kris On

Since this uses SFTP, i.e. it is proxied over SSH, it may be possible to send a 'ping' every X seconds to keep the connection open. You can do this with ServerAliveInterval in ~/.ssh/config or /etc/ssh/sshd_config, for example:

Host *
  ServerAliveInterval 240

Also note that any options passed to Net::SFTP.start are passed to the Net::SSH.start so you can use options such as verbose: :debug to get more information about what is happening.

Another option would be to do something like list files in some directory within the loop which waits for a file to be uploaded in order to keep the connection active. It might also be possible to do this in a separate thread if SSH connections to the same host are shared.

0
Octeny On

ruby net/sftp has it's own parameter of the connection keepalive

  • keepalive: set to +true+ to send a keepalive packet to the SSH server when there's no traffic between the SSH server and Net::SSH client for the keepalive_interval seconds. Defaults to +false+.
  • keepalive_interval: the interval seconds for keepalive. Defaults to +300+ seconds.
  • keepalive_maxcount: the maximun number of keepalive packet miss allowed. Defaults to 3

Example-Code

require 'net/ssh'
require 'net/sftp'
require 'net/sftp/constants'
require 'logger'

$SFTP_REMOTE_IP = '1.1.1.1'
$SFTP_REMOTE_USER = 'keepmealive'

sshlog = Logger.new(STDOUT)
sshlog.formatter = proc do |severity, datetime, progname, msg|
   "[RUBY SFTP-CLIENT] #{msg}\n"
end
sshlog.level = Logger::ERROR

sftp = Net::SFTP.start($SFTP_REMOTE_IP, $SFTP_REMOTE_USER, port: 22, timeout: 15, keepalive: true, keepalive_interval: 5, keepalive_maxcount: 2, logger: sshlog, verbose: 1)

# Wait to see keepalive
sleep 20

sftp.channel.eof! unless sftp.channel.nil? # Close SFTP channel
sftp.close_channel() unless sftp.nil? # Close SFTP

Log Output

[RUBY SFTP-CLIENT] sending lstat packet (10)
[RUBY SFTP-CLIENT] channel_data: 0 41b
[RUBY SFTP-CLIENT] sending keepalive 0
[RUBY SFTP-CLIENT] sending global request [email protected]