package service import ( "bufio" "context" "fmt" "log" "os" "os/exec" "os/signal" "syscall" "github.com/spf13/viper" ) func RunService() { args := viper.GetStringSlice("java.args") args = append(args, "-jar") args = append(args, viper.GetString("server.jar")) args = append(args, "--nogui") log.Println("Java: ", viper.GetString("java.path"), " Args: ", args) cmd := exec.Command(viper.GetString("java.path"), args...) // Open all three pipes stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } stderr, err := cmd.StderrPipe() if err != nil { log.Fatal(err) } // Start process if err := cmd.Start(); err != nil { log.Fatal(err) } // forward stdout and stderr go func() { sc := bufio.NewScanner(stdout) for sc.Scan() { fmt.Fprintln(os.Stdout, sc.Text()) } }() go func() { sc := bufio.NewScanner(stderr) for sc.Scan() { fmt.Fprintln(os.Stderr, sc.Text()) } }() // Separate Channel for handling SIGHUP hupCh := make(chan os.Signal, 1) signal.Notify(hupCh, syscall.SIGHUP) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() <- ctx.Done() for { select { case <-hupCh: log.Println("Sending reload signal to Server Process") if _, err := stdin.Write([]byte("reload\n")); err != nil { log.Printf("write error: %v", err) } case <-ctx.Done(): log.Println("Sending stop signal to Server Process") if _, err := stdin.Write([]byte("stop\n")); err != nil { log.Printf("write error: %v", err) } if err := cmd.Wait(); err != nil { log.Printf("child exit: %v", err) } log.Println("Shutdown completed") return } } }