2023-01-27 13:37:20 -08:00
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
2021-07-08 07:53:32 -07:00
2021-08-05 15:42:39 -07:00
//go:build linux || windows || darwin
2021-07-08 07:53:32 -07:00
package cli
import (
"fmt"
2023-01-21 12:47:57 -08:00
"os/exec"
2021-07-08 07:53:32 -07:00
"path/filepath"
"runtime"
"strings"
ps "github.com/mitchellh/go-ps"
2023-01-21 12:47:57 -08:00
"tailscale.com/version/distro"
2021-07-08 07:53:32 -07:00
)
// 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" )
}
2021-12-03 10:29:51 -08:00
var foundProc ps . Process
2021-07-08 07:53:32 -07:00
for _ , proc := range procs {
base := filepath . Base ( proc . Executable ( ) )
if base == "tailscaled" {
2021-12-03 10:29:51 -08:00
foundProc = proc
2021-07-08 07:53:32 -07:00
break
}
if runtime . GOOS == "darwin" && base == "IPNExtension" {
2021-12-03 10:29:51 -08:00
foundProc = proc
2021-07-08 07:53:32 -07:00
break
}
if runtime . GOOS == "windows" && strings . EqualFold ( base , "tailscaled.exe" ) {
2021-12-03 10:29:51 -08:00
foundProc = proc
2021-07-08 07:53:32 -07:00
break
}
}
2021-12-03 10:29:51 -08:00
if foundProc == nil {
2021-07-08 07:53:32 -07:00
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" :
2023-01-21 12:47:57 -08:00
var hint string
if isSystemdSystem ( ) {
hint = " (sudo systemctl start tailscaled ?)"
}
return fmt . Errorf ( "failed to connect to local tailscaled; it doesn't appear to be running%s" , hint )
2021-07-08 07:53:32 -07:00
}
return fmt . Errorf ( "failed to connect to local tailscaled process; it doesn't appear to be running" )
}
2021-12-03 10:29:51 -08:00
return fmt . Errorf ( "failed to connect to local tailscaled (which appears to be running as %v, pid %v). Got error: %w" , foundProc . Executable ( ) , foundProc . Pid ( ) , origErr )
2021-07-08 07:53:32 -07:00
}
2023-01-21 12:47:57 -08:00
// isSystemdSystem reports whether the current machine uses systemd
// and in particular whether the systemctl command is available.
func isSystemdSystem ( ) bool {
if runtime . GOOS != "linux" {
return false
}
switch distro . Get ( ) {
case distro . QNAP , distro . Gokrazy , distro . Synology :
return false
}
_ , err := exec . LookPath ( "systemctl" )
return err == nil
}