Тайм-аут соединения?
У меня простой объект подключения
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