diff --git a/README.md b/README.md index 67d4c76..3eb3f6f 100644 --- a/README.md +++ b/README.md @@ -70,10 +70,12 @@ For detailed API documentation, please see [docs/api.md](docs/api.md) - [ ] Add per-proxy status display - [ ] Add proxy edit submit action - [ ] Add per-proxy status control -- [ ] Fix reboot failed when deployed as systemd service +- [x] Fix reboot failed when deployed as systemd service - [x] Enhance speed of listing instances - [x] Increase speed of fetching instance logs - [x] Refactor systemd service log output method to local file +- [ ] Fix no log output in instanceDetail view +- [ ] Add update frp binary function ## License diff --git a/sys/core.go b/sys/core.go index 969e590..330b41d 100644 --- a/sys/core.go +++ b/sys/core.go @@ -671,3 +671,21 @@ func RestartInitDService(instanceName string) error { } return nil } + +func GetSystemdServiceName() (string, error) { + data, err := os.ReadFile("/proc/self/cgroup") + if err == nil { + for _, line := range strings.Split(string(data), "\n") { + if !strings.Contains(line, ".service") { + continue + } + for _, part := range strings.Split(line, "/") { + part = strings.TrimSpace(part) + if strings.HasSuffix(part, ".service") { + return part, nil + } + } + } + } + return "", fmt.Errorf("could not determine systemd service name from cgroup") +} \ No newline at end of file diff --git a/utils/handlers.go b/utils/handlers.go index d6723a4..bce6d7a 100644 --- a/utils/handlers.go +++ b/utils/handlers.go @@ -170,6 +170,8 @@ func IsFileExist(filePath string) bool { return !os.IsNotExist(err) } +var pendingSystemdRestart string + func RestartHandler(w http.ResponseWriter, r *http.Request) { userID, err := Auth(w, r, http.MethodGet, "superuser", "admin") if err != nil { @@ -185,14 +187,34 @@ func RestartHandler(w http.ResponseWriter, r *http.Request) { } SendSuccessResponse(w, "Restarting server...", nil) postLog.Info(fmt.Sprintf("[RestartHandler] [%d] Restarting server", userID)) + + if pendingSystemdRestart != "" { + serviceName := pendingSystemdRestart + go func() { + time.Sleep(500 * time.Millisecond) + cmd := exec.Command("systemctl", "restart", serviceName) + if err := cmd.Run(); err != nil { + postLog.Error(fmt.Sprintf("[RestartHandler] [%d] failed to restart systemd service %s: %v", userID, serviceName, err)) + } + }() + } } func RestartProcess() error { + if getInitSystem() == "systemd" { + serviceName, err := getSystemdServiceName() + if err != nil { + return fmt.Errorf("failed to get systemd service name: %w", err) + } + pendingSystemdRestart = serviceName + return nil + } + executable, err := os.Executable() if err != nil { return fmt.Errorf("failed to get executable path: %w", err) } - cmd := exec.Command(executable) + cmd := exec.Command(executable, os.Args[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { diff --git a/utils/sys.go b/utils/sys.go new file mode 100644 index 0000000..3f3e225 --- /dev/null +++ b/utils/sys.go @@ -0,0 +1,41 @@ +package utils + +import ( + "fmt" + "os" + "strings" + "runtime" +) + +func getSystemdServiceName() (string, error) { + data, err := os.ReadFile("/proc/self/cgroup") + if err == nil { + for _, line := range strings.Split(string(data), "\n") { + if !strings.Contains(line, ".service") { + continue + } + for _, part := range strings.Split(line, "/") { + part = strings.TrimSpace(part) + if strings.HasSuffix(part, ".service") { + return part, nil + } + } + } + } + return "", fmt.Errorf("could not determine systemd service name from cgroup") +} + +func getInitSystem() string { + if runtime.GOOS == "windows" { + return "windows" + } + if runtime.GOOS == "linux" { + if _, err := os.Stat("/run/systemd/system"); err == nil { + return "systemd" + } + if _, err := os.Stat("/etc/init.d"); err == nil { + return "init.d" + } + } + return "unknown" +} \ No newline at end of file