diff --git a/clientupdate/clientupdate.go b/clientupdate/clientupdate.go index 74942427e..76a849bf1 100644 --- a/clientupdate/clientupdate.go +++ b/clientupdate/clientupdate.go @@ -606,11 +606,11 @@ func (up *Updater) updateAlpineLike() (err error) { out, err := exec.Command("apk", "update").CombinedOutput() if err != nil { - return fmt.Errorf("failed refresh apk repository indexes: %w, output: %q", err, out) + return fmt.Errorf("failed refresh apk repository indexes: %w, output:\n%s", err, out) } out, err = exec.Command("apk", "info", "tailscale").CombinedOutput() if err != nil { - return fmt.Errorf("failed checking apk for latest tailscale version: %w, output: %q", err, out) + return fmt.Errorf("failed checking apk for latest tailscale version: %w, output:\n%s", err, out) } ver, err := parseAlpinePackageVersion(out) if err != nil { @@ -658,7 +658,7 @@ func (up *Updater) updateMacAppStore() error { out, err := exec.Command("open", "https://apps.apple.com/us/app/tailscale/id1475387142").CombinedOutput() if err != nil { - return fmt.Errorf("can't open the Tailscale page in App Store: %w, output: %q", err, string(out)) + return fmt.Errorf("can't open the Tailscale page in App Store: %w, output:\n%s", err, string(out)) } return nil } @@ -925,23 +925,29 @@ func (up *Updater) updateFreeBSD() (err error) { out, err := exec.Command("pkg", "update").CombinedOutput() if err != nil { - return fmt.Errorf("failed refresh pkg repository indexes: %w, output: %q", err, out) + return fmt.Errorf("failed refresh pkg repository indexes: %w, output:\n%s", err, out) } out, err = exec.Command("pkg", "rquery", "%v", "tailscale").CombinedOutput() if err != nil { - return fmt.Errorf("failed checking pkg for latest tailscale version: %w, output: %q", err, out) + return fmt.Errorf("failed checking pkg for latest tailscale version: %w, output:\n%s", err, out) } ver := string(bytes.TrimSpace(out)) if !up.confirm(ver) { return nil } - cmd := exec.Command("pkg", "upgrade", "tailscale") + cmd := exec.Command("pkg", "upgrade", "-y", "tailscale") cmd.Stdout = up.Stdout cmd.Stderr = up.Stderr if err := cmd.Run(); err != nil { return fmt.Errorf("failed tailscale update using pkg: %w", err) } + + // pkg does not automatically restart services after upgrade. + out, err = exec.Command("service", "tailscaled", "restart").CombinedOutput() + if err != nil { + return fmt.Errorf("failed to restart tailscaled after update: %w, output:\n%s", err, out) + } return nil } diff --git a/ipn/ipnlocal/c2n.go b/ipn/ipnlocal/c2n.go index 6b4aa094a..52184dc60 100644 --- a/ipn/ipnlocal/c2n.go +++ b/ipn/ipnlocal/c2n.go @@ -332,24 +332,33 @@ func findCmdTailscale() (string, error) { if err != nil { return "", err } + var ts string switch runtime.GOOS { case "linux": if self == "/usr/sbin/tailscaled" || self == "/usr/bin/tailscaled" { - return "/usr/bin/tailscale", nil + ts = "/usr/bin/tailscale" } if self == "/usr/local/sbin/tailscaled" || self == "/usr/local/bin/tailscaled" { - return "/usr/local/bin/tailscale", nil + ts = "/usr/local/bin/tailscale" } - return "", errors.New("tailscale not found in expected place") case "windows": - dir := filepath.Dir(self) - ts := filepath.Join(dir, "tailscale.exe") - if fi, err := os.Stat(ts); err == nil && fi.Mode().IsRegular() { - return ts, nil + ts = filepath.Join(filepath.Dir(self), "tailscale.exe") + case "freebsd": + if self == "/usr/local/bin/tailscaled" { + ts = "/usr/local/bin/tailscale" } - return "", errors.New("tailscale.exe not found in expected place") + default: + return "", fmt.Errorf("unsupported OS %v", runtime.GOOS) } - return "", fmt.Errorf("unsupported OS %v", runtime.GOOS) + if ts != "" && regularFileExists(ts) { + return ts, nil + } + return "", errors.New("tailscale executable not found in expected place") +} + +func regularFileExists(path string) bool { + fi, err := os.Stat(path) + return err == nil && fi.Mode().IsRegular() } func (b *LocalBackend) handleC2NWoL(w http.ResponseWriter, r *http.Request) {