Тайм-аут соединения?

У меня простой объект подключения

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

У меня есть это в сценарии, который прослушивает файлы, помещаемые в папку. Файлы собираются и загружаются на удаленный сервер sfpt. Все работает нормально, но кажется, что после того, как скрипт останется запущенным достаточно долго, он сломается и выдаст эту ошибку:

exception while processing events: Write to the server failed

Я могу только предположить, что это происходит, потому что простое соединение отключается через определенное время. Есть ли возможность держать соединение открытым на неопределенный срок? или это ограничение?

Если это невозможно, могу ли я справиться с ошибкой? Что-то вроде:

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

Не уверен, что 7 - правильный код ошибки, или как я могу повторно подключить объект подключения.

2 ответа

Так как при этом используется SFTP, то есть он проксируется по SSH, может быть возможно отправлять "ping" каждые X секунд, чтобы сохранить соединение открытым. Вы можете сделать это с ServerAliveInterval в ~/.ssh/config или же /etc/ssh/sshd_config, например:

Host *
  ServerAliveInterval 240

Также обратите внимание, что любые параметры переданы Net::SFTP.start передаются в Net::SSH.start так что вы можете использовать такие параметры, как verbose: :debug чтобы получить больше информации о том, что происходит.

Другой вариант - сделать что-то вроде списка файлов в некотором каталоге внутри цикла, который ожидает загрузки файла, чтобы сохранить соединение активным. Это также может быть возможно сделать в отдельном потоке, если SSH-соединения с одним и тем же хостом являются общими.

Ruby net/sftp имеет собственный параметр поддержания активности соединения.

  • Keepalive : установите значение +true+ для отправки пакета поддержки активности на SSH-сервер, когда между SSH-сервером и клиентом Net::SSH нет трафика в течение Keepalive_interval секунд. По умолчанию +false+.
  • Keepalive_interval : интервал в секундах для поддержания активности. По умолчанию +300+ секунд.
  • Keepalive_maxcount : максимальное разрешенное количество промахов пакетов поддержки активности. По умолчанию 3

Пример кода

      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

Вывод журнала

      [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 keepalive@openssh.com
Другие вопросы по тегам