refactor: simplify service installation process
This commit is contained in:
12
README.md
12
README.md
@ -116,16 +116,10 @@ ss service reload [--name <name>] # reload config via mihomo's API, no restart
|
||||
ss service status [--name <name>]
|
||||
```
|
||||
|
||||
Linux / macOS (installing the service needs root):
|
||||
```bash
|
||||
sudo env SF_CONFIG_DIR=$HOME/basicfiles/cli/ss ss service install
|
||||
```
|
||||
`install`/`uninstall`/`start`/`stop`/`restart` need root/admin privileges:
|
||||
|
||||
Windows (run from an elevated/Administrator shell):
|
||||
```powershell
|
||||
$env:SF_CONFIG_DIR = "$HOME\basicfiles\cli\ss"
|
||||
ss.exe service install
|
||||
```
|
||||
- **Linux / macOS**: just run the command directly — `ss` re-execs itself under `sudo` automatically, prompting for your password if needed.
|
||||
- **Windows**: run from an elevated/Administrator shell — `ss.exe service install`.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
57
internal/cli/elevate.go
Normal file
57
internal/cli/elevate.go
Normal file
@ -0,0 +1,57 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
"gitea.epss.net.cn/klesh/ss/internal/storage"
|
||||
)
|
||||
|
||||
// ensureRoot re-execs the current command under sudo if it isn't already
|
||||
// running as root. It resolves the config directory *before* elevating and
|
||||
// passes it through explicitly as SF_CONFIG_DIR, because sudo resets $HOME
|
||||
// to /root's — without this, the elevated process would silently resolve
|
||||
// the default config directory under /root instead of the invoking user's
|
||||
// home.
|
||||
//
|
||||
// Windows is handled separately: UAC elevation launches a new process that
|
||||
// can't transparently inherit the current console, so internal/service's
|
||||
// runAsAdmin instead prints manual elevation instructions rather than
|
||||
// auto-elevating.
|
||||
func ensureRoot() error {
|
||||
if runtime.GOOS == "windows" {
|
||||
return nil
|
||||
}
|
||||
if os.Geteuid() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
s, err := storage.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to resolve config directory: %w", err)
|
||||
}
|
||||
|
||||
self, err := os.Executable()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to determine executable path: %w", err)
|
||||
}
|
||||
|
||||
sudoPath, err := exec.LookPath("sudo")
|
||||
if err != nil {
|
||||
return fmt.Errorf("this command requires root privileges, but sudo was not found on PATH: %w", err)
|
||||
}
|
||||
|
||||
args := append([]string{"env", "SF_CONFIG_DIR=" + s.ConfigDir, self}, os.Args[1:]...)
|
||||
cmd := exec.Command(sudoPath, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
runErr := cmd.Run()
|
||||
if cmd.ProcessState != nil {
|
||||
os.Exit(cmd.ProcessState.ExitCode())
|
||||
}
|
||||
return fmt.Errorf("failed to re-exec under sudo: %w", runErr)
|
||||
}
|
||||
@ -40,6 +40,9 @@ func newServiceInstallCmd() *cobra.Command {
|
||||
Short: "Install mihomo as a system service",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := ensureRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := newManagers("", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -62,6 +65,9 @@ func newServiceUninstallCmd() *cobra.Command {
|
||||
Short: "Uninstall mihomo system service",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := ensureRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := newManagers("", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -83,6 +89,9 @@ func newServiceStartCmd() *cobra.Command {
|
||||
Short: "Start mihomo system service",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := ensureRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := newManagers("", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -104,6 +113,9 @@ func newServiceStopCmd() *cobra.Command {
|
||||
Short: "Stop mihomo system service",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := ensureRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := newManagers("", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -125,6 +137,9 @@ func newServiceRestartCmd() *cobra.Command {
|
||||
Short: "Restart mihomo system service",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := ensureRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
m, err := newManagers("", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user