diff --git a/README.md b/README.md index e192aba..67d4c76 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ 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] Enhance speed of listing instances +- [x] Increase speed of fetching instance logs +- [x] Refactor systemd service log output method to local file ## License diff --git a/config/config.go b/config/config.go index 93bb1b8..2e9c72c 100644 --- a/config/config.go +++ b/config/config.go @@ -63,7 +63,9 @@ func LoadConfig(configPath string, getInitSystem func() string) error { global.CurrentConfig.ListenPort = fileConfig.ListenPort global.CurrentConfig.FrpcPath = fileConfig.FrpcPath global.CurrentConfig.InstancePath = fileConfig.InstancePath + global.CurrentConfig.LogsPath = fileConfig.LogsPath global.CurrentConfig.Debug = fileConfig.Debug + global.CurrentConfig.Status.IsLogrotateConfigured = fileConfig.Status.IsLogrotateConfigured global.CurrentConfig.Watchdog.Enabled = fileConfig.Watchdog.Enabled global.CurrentConfig.Notification.Enabled = fileConfig.Notification.Enabled global.CurrentConfig.Notification.Method = fileConfig.Notification.Method @@ -82,20 +84,28 @@ func LoadConfig(configPath string, getInitSystem func() string) error { if fileConfig.FrpcPath == "" { if getInitSystem() == "windows" { - global.CurrentConfig.FrpcPath = "frp_client/frpc.exe" + global.CurrentConfig.FrpcPath = global.CurrentPath + string(os.PathSeparator) + "frp_client" + string(os.PathSeparator) + "frpc.exe" } else { - global.CurrentConfig.FrpcPath = "/usr/bin/frpc" + global.CurrentConfig.FrpcPath = global.CurrentPath + string(os.PathSeparator) + "frp_client" + string(os.PathSeparator) + "frpc" } } if fileConfig.InstancePath == "" { - global.CurrentConfig.InstancePath = "./configs" + global.CurrentConfig.InstancePath = global.CurrentPath + string(os.PathSeparator) + "configs" + } + + if fileConfig.LogsPath == "" { + global.CurrentConfig.LogsPath = global.CurrentPath + string(os.PathSeparator) + "logs" } if err := os.MkdirAll(global.CurrentConfig.InstancePath, 0755); err != nil { return fmt.Errorf("failed to create config directory: %w", err) } + if err := os.MkdirAll(global.CurrentConfig.LogsPath, 0755); err != nil { + return fmt.Errorf("failed to create log directory: %w", err) + } + postLog.Debug(fmt.Sprintf("Loaded config: %v", global.CurrentConfig)) return nil diff --git a/global/global.go b/global/global.go index bd10d55..48a1a53 100644 --- a/global/global.go +++ b/global/global.go @@ -49,7 +49,11 @@ type Config struct { ListenPort string `json:"listenPort"` FrpcPath string `json:"frpcPath"` InstancePath string `json:"instancePath"` + LogsPath string `json:"logsPath"` Debug bool `json:"debug"` + Status struct { + IsLogrotateConfigured bool `json:"isLogrotateConfigured"` + } `json:"status"` Watchdog struct { Enabled bool `json:"enabled"` } `json:"watchdog"` @@ -70,7 +74,13 @@ var CurrentConfig = Config{ ListenPort: "7000", FrpcPath: "", InstancePath: "", + LogsPath: "", Debug: false, + Status: struct{ + IsLogrotateConfigured bool `json:"isLogrotateConfigured"` + }{ + IsLogrotateConfigured: false, + }, Watchdog: struct { Enabled bool `json:"enabled"` }{ @@ -94,4 +104,4 @@ var CurrentConfig = Config{ Headers: "Content-Type: application/json", Body: "", }, -} +} \ No newline at end of file diff --git a/main.go b/main.go index aabf3a1..f3a9546 100644 --- a/main.go +++ b/main.go @@ -64,6 +64,16 @@ func main() { postLog.Fatal(fmt.Sprintf("Failed to initialize frpc database: %v", err)) } + if global.CurrentConfig.LogsPath != "" && !global.CurrentConfig.Status.IsLogrotateConfigured { // Set up logrotate policy if LogsPath is configured + if err := sys.CreateLogrotatePolicy(); err != nil { + postLog.Fatal(fmt.Sprintf("Failed to create logrotate policy: %v", err)) + } else { + global.CurrentConfig.Status.IsLogrotateConfigured = true + config.SaveConfig() + postLog.Info("Logrotate policy has been configured successfully.") + } + } + frpLogger.SetDatabase(global.ConfigDB, global.FrpcDB) frpLogger.SetDebugMode(global.CurrentConfig.Debug) diff --git a/sys/core.go b/sys/core.go index f923586..969e590 100644 --- a/sys/core.go +++ b/sys/core.go @@ -78,10 +78,12 @@ ExecStart=%s -c %s User=%s Restart=on-failure RestartSec=5 +StandardOutput=append:%s/superfrpc_%d.log +StandardError=append:%s/superfrpc_%d.log [Install] WantedBy=multi-user.target -`, instanceID, frpcPath, configPath, runUser) +`, instanceID, frpcPath, configPath, runUser, global.CurrentConfig.LogsPath, instanceID, global.CurrentConfig.LogsPath, instanceID) servicePath := filepath.Join("/etc/systemd/system", serviceName+".service") if err := os.WriteFile(servicePath, []byte(serviceContent), 0644); err != nil { @@ -102,6 +104,27 @@ WantedBy=multi-user.target return nil } +func CreateLogrotatePolicy() error { + logrotatePath := "/etc/logrotate.d/superfrpc_frpclog" + policyContent := fmt.Sprintf(`%s/superfrpc_*.log { + daily + rotate 7 + compress + delaycompress + missingok + notifempty +} +`, global.CurrentConfig.LogsPath) + if err := os.WriteFile(logrotatePath, []byte(policyContent), 0644); err != nil { + return fmt.Errorf("failed to create logrotate policy file: %w", err) + } + + if err := exec.Command("logrotate", "-f", logrotatePath).Run(); err != nil { + return fmt.Errorf("failed to apply logrotate policy: %w", err) + } + return nil +} + func createInitDService(instanceID int, configPath, runUser string) error { frpcPath, err := GetFrpcPath() if err != nil {