diff --git a/cmd/tailscale/cli/diag.go b/cmd/tailscale/cli/diag.go new file mode 100644 index 000000000..253c8e875 --- /dev/null +++ b/cmd/tailscale/cli/diag.go @@ -0,0 +1,55 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux windows darwin + +package cli + +import ( + "fmt" + "path/filepath" + "runtime" + "strings" + + ps "github.com/mitchellh/go-ps" +) + +// fixTailscaledConnectError is called when the local tailscaled has +// been determined unreachable due to the provided origErr value. It +// returns either the same error or a better one to help the user +// understand why tailscaled isn't running for their platform. +func fixTailscaledConnectError(origErr error) error { + procs, err := ps.Processes() + if err != nil { + return fmt.Errorf("failed to connect to local Tailscaled process and failed to enumerate processes while looking for it") + } + found := false + for _, proc := range procs { + base := filepath.Base(proc.Executable()) + if base == "tailscaled" { + found = true + break + } + if runtime.GOOS == "darwin" && base == "IPNExtension" { + found = true + break + } + if runtime.GOOS == "windows" && strings.EqualFold(base, "tailscaled.exe") { + found = true + break + } + } + if !found { + switch runtime.GOOS { + case "windows": + return fmt.Errorf("failed to connect to local tailscaled process; is the Tailscale service running?") + case "darwin": + return fmt.Errorf("failed to connect to local Tailscale service; is Tailscale running?") + case "linux": + return fmt.Errorf("failed to connect to local tailscaled; it doesn't appear to be running (sudo systemctl start tailscaled ?)") + } + return fmt.Errorf("failed to connect to local tailscaled process; it doesn't appear to be running") + } + return fmt.Errorf("failed to connect to local tailscaled (which appears to be running). Got error: %w", origErr) +} diff --git a/cmd/tailscale/cli/diag_other.go b/cmd/tailscale/cli/diag_other.go new file mode 100644 index 000000000..bc67cbeee --- /dev/null +++ b/cmd/tailscale/cli/diag_other.go @@ -0,0 +1,16 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !linux,!windows,!darwin + +package cli + +import "fmt" + +// The github.com/mitchellh/go-ps package doesn't work on all platforms, +// so just don't diagnose connect failures. + +func fixTailscaledConnectError(origErr error) error { + return fmt.Errorf("failed to connect to local tailscaled process (is it running?); got: %w", origErr) +} diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index af887f427..9ae378350 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -57,7 +57,7 @@ var statusArgs struct { func runStatus(ctx context.Context, args []string) error { st, err := tailscale.Status(ctx) if err != nil { - return err + return fixTailscaledConnectError(err) } if statusArgs.json { if statusArgs.active { diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 8c39bbd44..c6f5909cd 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -294,7 +294,7 @@ func runUp(ctx context.Context, args []string) error { st, err := tailscale.Status(ctx) if err != nil { - fatalf("can't fetch status from tailscaled: %v", err) + return fixTailscaledConnectError(err) } origAuthURL := st.AuthURL diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 26a459de7..dfc160e37 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -4,6 +4,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep W github.com/alexbrainman/sspi/internal/common from github.com/alexbrainman/sspi/negotiate W 💣 github.com/alexbrainman/sspi/negotiate from tailscale.com/net/tshttpproxy github.com/kballard/go-shellquote from tailscale.com/cmd/tailscale/cli + 💣 github.com/mitchellh/go-ps from tailscale.com/cmd/tailscale/cli github.com/peterbourgon/ff/v2 from github.com/peterbourgon/ff/v2/ffcli github.com/peterbourgon/ff/v2/ffcli from tailscale.com/cmd/tailscale/cli github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck diff --git a/go.mod b/go.mod index 73725326d..6fa065348 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/mdlayher/netlink v1.4.1 github.com/mdlayher/sdnotify v0.0.0-20210228150836-ea3ec207d697 github.com/miekg/dns v1.1.42 + github.com/mitchellh/go-ps v1.0.0 github.com/pborman/getopt v1.1.0 github.com/peterbourgon/ff/v2 v2.0.0 github.com/pkg/sftp v1.13.0 diff --git a/go.sum b/go.sum index 61e3e9d89..e86c8ca28 100644 --- a/go.sum +++ b/go.sum @@ -418,6 +418,7 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=