diff --git a/cmd/frpc/gssh_runner.go b/cmd/frpc/gssh_runner.go index 7f26331..050d6a0 100644 --- a/cmd/frpc/gssh_runner.go +++ b/cmd/frpc/gssh_runner.go @@ -18,7 +18,9 @@ package main import ( + "context" "sync" + "time" "github.com/gofrp/tiny-frpc/pkg/config" v1 "github.com/gofrp/tiny-frpc/pkg/config/v1" @@ -103,3 +105,36 @@ func (gr *GoSSHRun) Close() error { } return nil } + +func (gr *GoSSHRun) retryConnection(ctx context.Context, cmd config.GoSSHParam, idx int) { + backoff := 1 * time.Second + for { + select { + case <-ctx.Done(): + return + default: + tc, err := gssh.NewTunnelClient(cmd.LocalAddr, cmd.ServerAddr, cmd.SSHExtraCmd) + if err != nil { + log.Errorf("retry new ssh tunnel client error: %v", err) + continue + } + + err = tc.Start() + if err != nil { + log.Errorf("retry cmd: %v run error: %v", cmd, err) + time.Sleep(backoff) + if backoff < 30*time.Second { + backoff *= 2 + } + continue + } + + gr.mu.Lock() + gr.tcs[idx] = tc + gr.mu.Unlock() + + gr.wg.Done() + return + } + } +} diff --git a/cmd/frpc/nssh_runner.go b/cmd/frpc/nssh_runner.go index f08ad49..5b78049 100644 --- a/cmd/frpc/nssh_runner.go +++ b/cmd/frpc/nssh_runner.go @@ -20,6 +20,7 @@ package main import ( "context" "sync" + "time" "github.com/gofrp/tiny-frpc/pkg/config" v1 "github.com/gofrp/tiny-frpc/pkg/config/v1" @@ -79,6 +80,32 @@ func (nr *NativeSSHRun) Run() error { nr.mu.Unlock() cmdWrapper.ExecuteCommand(nr.ctx) + + // Retry logic with exponential backoff + backoff := 1 * time.Second + for { + select { + case <-nr.ctx.Done(): + return + default: + cmdWrapper := nssh.NewCmdWrapper(nr.ctx, cmd) + cmdWrapper.ExecuteCommand(nr.ctx) + if cmdWrapper.cmd.ProcessState.Success() { + log.Infof("Command %v executed successfully after retry", cmd) + nr.mu.Lock() + nr.cws[idx] = cmdWrapper + nr.mu.Unlock() + nr.wg.Done() + return + } else { + log.Errorf("Retry command %v failed, retrying in %v seconds", cmd, backoff) + time.Sleep(backoff) + if backoff < 30*time.Second { + backoff *= 2 + } + } + } + } }(cmd, i) }