@@ -2,6 +2,7 @@ package main
22
33import (
44 "context"
5+ "errors"
56 "flag"
67 "fmt"
78 "io"
@@ -67,14 +68,43 @@ func main() {
6768 logger .Error ("Unable to get stdin" , zap .Error (err ))
6869 }
6970
70- stdout , err := cmd .StdoutPipe ()
71- if err != nil {
72- logger .Error ("Unable to get stdout" , zap .Error (err ))
73- }
71+ if args .RemoteConsole {
72+ stdout , err := cmd .StdoutPipe ()
73+ if err != nil {
74+ logger .Error ("Unable to get stdout" , zap .Error (err ))
75+ }
7476
75- stderr , err := cmd .StderrPipe ()
76- if err != nil {
77- logger .Error ("Unable to get stderr" , zap .Error (err ))
77+ stderr , err := cmd .StderrPipe ()
78+ if err != nil {
79+ logger .Error ("Unable to get stderr" , zap .Error (err ))
80+ }
81+
82+ console := makeConsole (stdin , stdout , stderr )
83+
84+ // Relay stdin between outside and server
85+ if ! args .DetachStdin {
86+ go consoleInRoutine (os .Stdin , console , logger )
87+ }
88+
89+ go consoleOutRoutine (os .Stdout , console , stdOutTarget , logger )
90+ go consoleOutRoutine (os .Stderr , console , stdErrTarget , logger )
91+
92+ go runRemoteShellServer (console , logger )
93+
94+ logger .Info ("Running with remote console support" )
95+ } else {
96+ logger .Debug ("Directly assigning stdout/stderr" )
97+ // directly assign stdout/err to pass through terminal, if applicable
98+ cmd .Stdout = os .Stdout
99+ cmd .Stderr = os .Stderr
100+
101+ if hasRconCli () {
102+ logger .Debug ("Directly assigning stdin" )
103+ cmd .Stdin = os .Stdin
104+ stdin = os .Stdin
105+ } else {
106+ go relayStdin (logger , stdin )
107+ }
78108 }
79109
80110 err = cmd .Start ()
@@ -93,26 +123,11 @@ func main() {
93123 }
94124 }
95125
96- console := makeConsole (stdin , stdout , stderr )
97-
98- // Relay stdin between outside and server
99- if ! args .DetachStdin {
100- go consoleInRoutine (os .Stdin , console , logger )
101- }
102-
103- go consoleOutRoutine (os .Stdout , console , stdOutTarget , logger )
104- go consoleOutRoutine (os .Stderr , console , stdErrTarget , logger )
105-
106- // Start the remote server if intended
107- if args .RemoteConsole {
108- go startRemoteShellServer (console , logger )
109- }
110-
111126 ctx , cancel := context .WithCancel (context .Background ())
112- errors := make (chan error , 1 )
127+ errorChan := make (chan error , 1 )
113128
114129 if args .NamedPipe != "" {
115- err2 := handleNamedPipe (ctx , args .NamedPipe , stdin , errors )
130+ err2 := handleNamedPipe (ctx , args .NamedPipe , stdin , errorChan )
116131 if err2 != nil {
117132 logger .Fatal ("Failed to setup named pipe" , zap .Error (err2 ))
118133 }
@@ -123,14 +138,12 @@ func main() {
123138 go func () {
124139 waitErr := cmd .Wait ()
125140 if waitErr != nil {
126- if exitErr , ok := waitErr .(* exec.ExitError ); ok {
141+ var exitErr * exec.ExitError
142+ if errors .As (waitErr , & exitErr ) {
127143 exitCode := exitErr .ExitCode ()
128144 logger .Warn ("Minecraft server failed. Inspect logs above for errors that indicate cause. DO NOT report this line as an error." ,
129145 zap .Int ("exitCode" , exitCode ))
130146 cmdExitChan <- exitCode
131- } else {
132- logger .Error ("Command failed abnormally" , zap .Error (waitErr ))
133- cmdExitChan <- 1
134147 }
135148 return
136149 } else {
@@ -142,7 +155,7 @@ func main() {
142155 select {
143156 case <- signalChan :
144157 if args .StopServerAnnounceDelay > 0 {
145- announceStopViaConsole (logger , stdin , args .StopServerAnnounceDelay )
158+ announceStop (logger , stdin , args .StopServerAnnounceDelay )
146159 logger .Info ("Sleeping before server stop" , zap .Duration ("sleepTime" , args .StopServerAnnounceDelay ))
147160 time .Sleep (args .StopServerAnnounceDelay )
148161 }
@@ -168,7 +181,7 @@ func main() {
168181 })
169182 }
170183
171- case namedPipeErr := <- errors :
184+ case namedPipeErr := <- errorChan :
172185 logger .Error ("Error during named pipe handling" , zap .Error (namedPipeErr ))
173186
174187 case exitCode := <- cmdExitChan :
@@ -180,6 +193,13 @@ func main() {
180193
181194}
182195
196+ func relayStdin (logger * zap.Logger , stdin io.WriteCloser ) {
197+ _ , err := io .Copy (stdin , os .Stdin )
198+ if err != nil {
199+ logger .Error ("Failed to relay standard input" , zap .Error (err ))
200+ }
201+ }
202+
183203func hasRconCli () bool {
184204 if strings .ToUpper (os .Getenv ("ENABLE_RCON" )) == "TRUE" {
185205 _ , err := exec .LookPath ("rcon-cli" )
@@ -189,9 +209,7 @@ func hasRconCli() bool {
189209 }
190210}
191211
192- func stopWithRconCli () error {
193- log .Println ("Stopping with rcon-cli" )
194-
212+ func sendRconCommand (cmd ... string ) error {
195213 rconConfigFile := os .Getenv ("RCON_CONFIG_FILE" )
196214 if rconConfigFile == "" {
197215 port := os .Getenv ("RCON_PORT" )
@@ -204,23 +222,39 @@ func stopWithRconCli() error {
204222 password = "minecraft"
205223 }
206224
207- rconCliCmd := exec .Command ("rcon-cli" ,
208- "--port" , port ,
209- "--password" , password ,
210- "stop" )
225+ args := []string {"--port" , port ,
226+ "--password" , password }
227+ args = append (args , cmd ... )
228+
229+ rconCliCmd := exec .Command ("rcon-cli" , args ... )
211230
212231 return rconCliCmd .Run ()
213232 } else {
214- rconCliCmd := exec .Command ("rcon-cli" ,
215- "--config" , rconConfigFile ,
216- "stop" )
233+
234+ args := []string {"--config" , rconConfigFile }
235+ args = append (args , cmd ... )
236+
237+ rconCliCmd := exec .Command ("rcon-cli" , args ... )
217238
218239 return rconCliCmd .Run ()
219240 }
220241}
221242
222- func announceStopViaConsole (logger * zap.Logger , stdin io.Writer , shutdownDelay time.Duration ) {
243+ func stopWithRconCli () error {
244+ log .Println ("Stopping with rcon-cli" )
245+
246+ return sendRconCommand ("stop" )
247+ }
248+
249+ func announceStop (logger * zap.Logger , stdin io.Writer , shutdownDelay time.Duration ) {
223250 logger .Info ("Sending shutdown announce 'say' to Minecraft server" )
251+ if hasRconCli () {
252+ err := sendRconCommand ("say" , fmt .Sprintf ("Server shutting down in %0.f seconds" , shutdownDelay .Seconds ()))
253+ if err != nil {
254+ logger .Error ("Failed to send 'say' command" , zap .Error (err ))
255+ }
256+ }
257+
224258 _ , err := stdin .Write ([]byte (fmt .Sprintf ("say Server shutting down in %0.f seconds\n " , shutdownDelay .Seconds ())))
225259 if err != nil {
226260 logger .Error ("Failed to write say command to server console" , zap .Error (err ))
0 commit comments