From 3c023582c23090a22202be10e18c7df57aae0fe5 Mon Sep 17 00:00:00 2001 From: Nick Goodall Date: Tue, 13 Jan 2026 12:37:10 +0000 Subject: [PATCH] persistant ssh --- deploy.go | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/deploy.go b/deploy.go index 79caad1..2db50b6 100644 --- a/deploy.go +++ b/deploy.go @@ -2,11 +2,13 @@ package main import ( "bytes" + "crypto/sha1" "errors" "fmt" "os" "os/exec" "path/filepath" + "runtime" "strings" "github.com/pelletier/go-toml/v2" @@ -55,6 +57,7 @@ func runDeploy() error { if serverIP == "" { return fmt.Errorf("pb.toml missing [server].ip") } + defer closeSSHControlMaster(serverIP) domain := cfg.Server.Domain if domain == "" { @@ -310,7 +313,8 @@ func syncLocalDirectories(server, remoteBase string, dirs []string) error { } remotePath := fmt.Sprintf("root@%s:%s/%s", server, remoteBase, dir) - cmd := exec.Command("rsync", "-e", "ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new", "-az", "--delete", localPath+"/", remotePath) + rsyncCmd := rsyncSSHCommand(server) + cmd := exec.Command("rsync", "-e", rsyncCmd, "-az", "--delete", localPath+"/", remotePath) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { @@ -320,10 +324,44 @@ func syncLocalDirectories(server, remoteBase string, dirs []string) error { return nil } +func rsyncSSHCommand(server string) string { + args := append([]string(nil), sshSharedArgs(server)...) + args = append(args, fmt.Sprintf("root@%s", server)) + return fmt.Sprintf("ssh %s", strings.Join(args, " ")) +} + func sshArgs(server string) []string { + args := append([]string(nil), sshSharedArgs(server)...) + return append(args, fmt.Sprintf("root@%s", server)) +} + +func sshSharedArgs(server string) []string { return []string{ "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", - fmt.Sprintf("root@%s", server), + "-o", "ControlMaster=auto", + "-o", fmt.Sprintf("ControlPath=%s", sshControlPath(server)), + "-o", "ControlPersist=5m", } } + +func sshControlPath(server string) string { + sum := sha1.Sum([]byte(server)) + return filepath.Join(sshControlDir(), fmt.Sprintf("pb-ssh-%x.sock", sum)) +} + +func sshControlDir() string { + if dir := os.Getenv("PB_SSH_CONTROL_DIR"); dir != "" { + return dir + } + if runtime.GOOS == "windows" { + return os.TempDir() + } + return "/tmp" +} + +func closeSSHControlMaster(server string) { + args := append([]string(nil), sshSharedArgs(server)...) + args = append(args, "-O", "exit", fmt.Sprintf("root@%s", server)) + _ = exec.Command("ssh", args...).Run() +}