From c5ece2f21fd1ed882ae1a6521d4a70c327c18a3a Mon Sep 17 00:00:00 2001 From: Owen Date: Wed, 1 Oct 2025 10:30:45 -0700 Subject: [PATCH] Try to fix log rotation and service args --- main.go | 15 +++++- service_unix.go | 4 ++ service_windows.go | 122 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 128 insertions(+), 13 deletions(-) diff --git a/main.go b/main.go index 47e9a43..0401fba 100644 --- a/main.go +++ b/main.go @@ -145,16 +145,27 @@ func main() { os.Exit(1) } return + case "config": + if runtime.GOOS == "windows" { + showServiceConfig() + } else { + fmt.Println("Service configuration is only available on Windows") + } + return case "help", "--help", "-h": fmt.Println("Olm WireGuard VPN Client") fmt.Println("\nWindows Service Management:") fmt.Println(" install Install the service") fmt.Println(" remove Remove the service") - fmt.Println(" start Start the service") + fmt.Println(" start [args] Start the service with optional arguments") fmt.Println(" stop Stop the service") fmt.Println(" status Show service status") - fmt.Println(" debug Run service in debug mode") + fmt.Println(" debug [args] Run service in debug mode with optional arguments") fmt.Println(" logs Tail the service log file") + fmt.Println(" config Show current service configuration") + fmt.Println("\nExamples:") + fmt.Println(" olm start --enable-http --http-addr :9452") + fmt.Println(" olm debug --endpoint https://example.com --id myid --secret mysecret") fmt.Println("\nFor console mode, run without arguments or with standard flags.") return default: diff --git a/service_unix.go b/service_unix.go index c9f5fbf..ae09753 100644 --- a/service_unix.go +++ b/service_unix.go @@ -48,3 +48,7 @@ func setupWindowsEventLog() { func watchLogFile(end bool) error { return fmt.Errorf("watching log file is only available on Windows") } + +func showServiceConfig() { + fmt.Println("Service configuration is only available on Windows") +} diff --git a/service_windows.go b/service_windows.go index f4dd7ff..78b55c8 100644 --- a/service_windows.go +++ b/service_windows.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "path/filepath" + "strings" "syscall" "time" @@ -95,7 +96,7 @@ func (s *olmService) Execute(args []string, r <-chan svc.ChangeRequest, changes const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown changes <- svc.Status{State: svc.StartPending} - s.elog.Info(1, "Service Execute called, starting main logic") + s.elog.Info(1, fmt.Sprintf("Service Execute called with args: %v", args)) // Load saved service arguments savedArgs, err := loadServiceArgs() @@ -104,7 +105,24 @@ func (s *olmService) Execute(args []string, r <-chan svc.ChangeRequest, changes // Continue with empty args if loading fails savedArgs = []string{} } - s.args = savedArgs + + // Combine service start args with saved args, giving priority to service start args + finalArgs := []string{} + if len(args) > 0 { + // Skip the first arg which is typically the service name + if len(args) > 1 { + finalArgs = append(finalArgs, args[1:]...) + } + s.elog.Info(1, fmt.Sprintf("Using service start parameters: %v", finalArgs)) + } + + // If no service start parameters, use saved args + if len(finalArgs) == 0 && len(savedArgs) > 0 { + finalArgs = savedArgs + s.elog.Info(1, fmt.Sprintf("Using saved service args: %v", finalArgs)) + } + + s.args = finalArgs // Start the main olm functionality olmDone := make(chan struct{}) @@ -309,7 +327,7 @@ func removeService() error { } func startService(args []string) error { - // Save the service arguments before starting + // Save the service arguments as backup if len(args) > 0 { err := saveServiceArgs(args) if err != nil { @@ -329,7 +347,8 @@ func startService(args []string) error { } defer s.Close() - err = s.Start() + // Pass arguments directly to the service start call + err = s.Start(args...) if err != nil { return fmt.Errorf("failed to start service: %v", err) } @@ -379,17 +398,12 @@ func debugService(args []string) error { } } - // fmt.Printf("Starting service in debug mode...\n") - - // Start the service - err := startService([]string{}) // Pass empty args since we already saved them + // Start the service with the provided arguments + err := startService(args) if err != nil { return fmt.Errorf("failed to start service: %v", err) } - // fmt.Printf("Service started. Watching logs (Press Ctrl+C to stop watching)...\n") - // fmt.Printf("================================================================================\n") - // Watch the log file return watchLogFile(true) } @@ -509,11 +523,89 @@ func getServiceStatus() (string, error) { } } +// showServiceConfig displays current saved service configuration +func showServiceConfig() { + configPath := getServiceArgsPath() + fmt.Printf("Service configuration file: %s\n", configPath) + + args, err := loadServiceArgs() + if err != nil { + fmt.Printf("No saved configuration found or error loading: %v\n", err) + return + } + + if len(args) == 0 { + fmt.Println("No saved service arguments found") + } else { + fmt.Printf("Saved service arguments: %v\n", args) + } +} + func isWindowsService() bool { isWindowsService, err := svc.IsWindowsService() return err == nil && isWindowsService } +// rotateLogFile handles daily log rotation +func rotateLogFile(logDir string, logFile string) error { + // Get current log file info + info, err := os.Stat(logFile) + if err != nil { + if os.IsNotExist(err) { + return nil // No current log file to rotate + } + return fmt.Errorf("failed to stat log file: %v", err) + } + + // Check if log file is from today + now := time.Now() + fileTime := info.ModTime() + + // If the log file is from today, no rotation needed + if now.Year() == fileTime.Year() && now.YearDay() == fileTime.YearDay() { + return nil + } + + // Create rotated filename with date + rotatedName := fmt.Sprintf("olm-%s.log", fileTime.Format("2006-01-02")) + rotatedPath := filepath.Join(logDir, rotatedName) + + // Rename current log file to dated filename + err = os.Rename(logFile, rotatedPath) + if err != nil { + return fmt.Errorf("failed to rotate log file: %v", err) + } + + // Clean up old log files (keep last 30 days) + cleanupOldLogFiles(logDir, 30) + + return nil +} + +// cleanupOldLogFiles removes log files older than specified days +func cleanupOldLogFiles(logDir string, daysToKeep int) { + cutoff := time.Now().AddDate(0, 0, -daysToKeep) + + files, err := os.ReadDir(logDir) + if err != nil { + return + } + + for _, file := range files { + if !file.IsDir() && strings.HasPrefix(file.Name(), "olm-") && strings.HasSuffix(file.Name(), ".log") { + filePath := filepath.Join(logDir, file.Name()) + info, err := file.Info() + if err != nil { + continue + } + + if info.ModTime().Before(cutoff) { + os.Remove(filePath) + } + } + } +} + func setupWindowsEventLog() { // Create log directory if it doesn't exist logDir := filepath.Join(os.Getenv("PROGRAMDATA"), "olm", "logs") @@ -524,6 +616,14 @@ func setupWindowsEventLog() { } logFile := filepath.Join(logDir, "olm.log") + + // Rotate log file if needed + err = rotateLogFile(logDir, logFile) + if err != nil { + fmt.Printf("Failed to rotate log file: %v\n", err) + // Continue anyway to create new log file + } + file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { fmt.Printf("Failed to open log file: %v\n", err)