diff --git a/cmd/tailscale/cli/ssh.go b/cmd/tailscale/cli/ssh.go index 92bd42a10..0db6ebd51 100644 --- a/cmd/tailscale/cli/ssh.go +++ b/cmd/tailscale/cli/ssh.go @@ -11,7 +11,6 @@ import ( "fmt" "log" "os" - "os/exec" "os/user" "path/filepath" "runtime" @@ -63,7 +62,7 @@ func runSSH(ctx context.Context, args []string) error { hostForSSH = v } - ssh, err := exec.LookPath("ssh") + ssh, err := findSSH() if err != nil { // TODO(bradfitz): use Go's crypto/ssh client instead // of failing. But for now: diff --git a/cmd/tailscale/cli/ssh_exec.go b/cmd/tailscale/cli/ssh_exec.go index 02fbde61f..bee4d3242 100644 --- a/cmd/tailscale/cli/ssh_exec.go +++ b/cmd/tailscale/cli/ssh_exec.go @@ -10,9 +10,14 @@ package cli import ( "errors" "os" + "os/exec" "syscall" ) +func findSSH() (string, error) { + return exec.LookPath("ssh") +} + func execSSH(ssh string, argv []string) error { if err := syscall.Exec(ssh, argv, os.Environ()); err != nil { return err diff --git a/cmd/tailscale/cli/ssh_exec_js.go b/cmd/tailscale/cli/ssh_exec_js.go index bc1a97e7c..3dbbea6a2 100644 --- a/cmd/tailscale/cli/ssh_exec_js.go +++ b/cmd/tailscale/cli/ssh_exec_js.go @@ -8,6 +8,10 @@ import ( "errors" ) +func findSSH() (string, error) { + return "", errors.New("Not implemented") +} + func execSSH(ssh string, argv []string) error { return errors.New("Not implemented") } diff --git a/cmd/tailscale/cli/ssh_exec_windows.go b/cmd/tailscale/cli/ssh_exec_windows.go index 1905fff39..88722734f 100644 --- a/cmd/tailscale/cli/ssh_exec_windows.go +++ b/cmd/tailscale/cli/ssh_exec_windows.go @@ -8,8 +8,21 @@ import ( "errors" "os" "os/exec" + "path/filepath" ) +func findSSH() (string, error) { + // use C:\Windows\System32\OpenSSH\ssh.exe since unexpected behavior + // occured with ssh.exe provided by msys2/cygwin and other environments. + if systemRoot := os.Getenv("SystemRoot"); systemRoot != "" { + exe := filepath.Join(systemRoot, "System32", "OpenSSH", "ssh.exe") + if st, err := os.Stat(exe); err == nil && !st.IsDir() { + return exe, nil + } + } + return exec.LookPath("ssh") +} + func execSSH(ssh string, argv []string) error { // Don't use syscall.Exec on Windows, it's not fully implemented. cmd := exec.Command(ssh, argv[1:]...)