mirror of
https://github.com/rclone/rclone.git
synced 2025-01-24 12:56:36 +02:00
sftp: fix timeout on hashing large files by sending keepalives
Before this fix the SFTP sessions could timeout when doing hashes if they took longer than the --timeout parameter. This patch sends keepalive packets every minute while a shell command is running to keep the connection open. See: https://forum.rclone.org/t/rclone-check-over-sftp-failure-to-calculate-md5-hash-for-large-files/27487
This commit is contained in:
parent
099eff8891
commit
a351484997
@ -42,7 +42,8 @@ const (
|
|||||||
hashCommandNotSupported = "none"
|
hashCommandNotSupported = "none"
|
||||||
minSleep = 100 * time.Millisecond
|
minSleep = 100 * time.Millisecond
|
||||||
maxSleep = 2 * time.Second
|
maxSleep = 2 * time.Second
|
||||||
decayConstant = 2 // bigger for slower decay, exponential
|
decayConstant = 2 // bigger for slower decay, exponential
|
||||||
|
keepAliveInterval = time.Minute // send keepalives every this long while running commands
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -339,6 +340,32 @@ func (c *conn) wait() {
|
|||||||
c.err <- c.sshClient.Conn.Wait()
|
c.err <- c.sshClient.Conn.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send a keepalive over the ssh connection
|
||||||
|
func (c *conn) sendKeepAlive() {
|
||||||
|
_, _, err := c.sshClient.SendRequest("keepalive@openssh.com", true, nil)
|
||||||
|
if err != nil {
|
||||||
|
fs.Debugf(nil, "Failed to send keep alive: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send keepalives every interval over the ssh connection until done is closed
|
||||||
|
func (c *conn) sendKeepAlives(interval time.Duration) (done chan struct{}) {
|
||||||
|
done = make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(interval)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
c.sendKeepAlive()
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return done
|
||||||
|
}
|
||||||
|
|
||||||
// Closes the connection
|
// Closes the connection
|
||||||
func (c *conn) close() error {
|
func (c *conn) close() error {
|
||||||
sftpErr := c.sftpClient.Close()
|
sftpErr := c.sftpClient.Close()
|
||||||
@ -1098,6 +1125,9 @@ func (f *Fs) run(ctx context.Context, cmd string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
defer f.putSftpConnection(&c, err)
|
defer f.putSftpConnection(&c, err)
|
||||||
|
|
||||||
|
// Send keepalives while the connection is open
|
||||||
|
defer close(c.sendKeepAlives(keepAliveInterval))
|
||||||
|
|
||||||
session, err := c.sshClient.NewSession()
|
session, err := c.sshClient.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("run: get SFTP session: %w", err)
|
return nil, fmt.Errorf("run: get SFTP session: %w", err)
|
||||||
|
@ -620,7 +620,7 @@ issue](https://github.com/pkg/sftp/issues/156) is fixed.
|
|||||||
Note that since SFTP isn't HTTP based the following flags don't work
|
Note that since SFTP isn't HTTP based the following flags don't work
|
||||||
with it: `--dump-headers`, `--dump-bodies`, `--dump-auth`
|
with it: `--dump-headers`, `--dump-bodies`, `--dump-auth`
|
||||||
|
|
||||||
Note that `--timeout` isn't supported (but `--contimeout` is).
|
Note that `--timeout` and `--contimeout` are both supported.
|
||||||
|
|
||||||
|
|
||||||
## C14 {#c14}
|
## C14 {#c14}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user