this post was submitted on 29 Aug 2023
17 points (100.0% liked)

Linux

48212 readers
657 users here now

From Wikipedia, the free encyclopedia

Linux is a family of open source Unix-like operating systems based on the Linux kernel, an operating system kernel first released on September 17, 1991 by Linus Torvalds. Linux is typically packaged in a Linux distribution (or distro for short).

Distributions include the Linux kernel and supporting system software and libraries, many of which are provided by the GNU Project. Many Linux distributions use the word "Linux" in their name, but the Free Software Foundation uses the name GNU/Linux to emphasize the importance of GNU software, causing some controversy.

Rules

Related Communities

Community icon by Alpár-Etele Méder, licensed under CC BY 3.0

founded 5 years ago
MODERATORS
 

Note: Still trying to navigate communities here on Lemmy to replace those from Reddit. If there is a better place such a question, I would welcome the suggestion.

I'm running a Synology NAS, which uses some flavor of Linux distribution. From there, among everything else running, I have a docker container hosting a Minecraft Bedrock Server. The MCBE server is great for fun, but not so great for resource usage. To handle this, most folks setup something to schedule the server to restart.

Within Synology, there is a task scheduler where I can run a user-defined script to restart the whole container: docker restart mcbe-world

This works, but it's a dirty reboot though. I worried about corrupting the world (which I do regularly backup). From within the Minecraft server terminal, the /stop command will gracefully shut it down.

I can't update the container with another application, like screen, because each MCBE update means replacing the entire container (and so destroying the changes). I am looking to somehow redirect a command to the server if possible.

Using docker exec -it mcbe-world , I can execute what I want within the container.

The person here said, one can "inject commands by running the command as the appropriate account and redirecting it into the server" and they gave the example sudo su -s /bin/bash -c "echo say foobar > /run/service@name" Unfortunately, this isn't so clear and straight forward to me.

Would anyone here be able to articulate this more clearly for me or have an idea as to how I might issue that /stop command from the Synology scheduled script BEFORE restarting the container?

Thanks!

UPDATE: Solution here: https://beehaw.org/comment/1088961

top 15 comments
sorted by: hot top controversial new old
[–] unique_hemp@discuss.tchncs.de 5 points 1 year ago (1 children)

Check this out: https://stackoverflow.com/a/62142025

So adapted for your requirements:

echo '/stop' | socat EXEC:"docker attach mcbe-world",pty STDIN
[–] GlassHalfHopeful@beehaw.org 2 points 1 year ago* (last edited 1 year ago) (1 children)

YEEEESSS!!!! THIS!!! Thank you! I've been able to hobble together a script now that I have a Synology automated task calling early each morning after world backups are complete. I'm so very grateful to you all. I've learned a lot. A proper "stop" is being issues now which reduces the chance of world corruption which would make my family very very grumpy.

Here's the script just in case someone finds themselves in a similar situation as me. This is not my wheelhouse and it's not pretty. I know it can be better, but I've spent too much time on this as it is and need to go fix a washing machine now. Ugh...


#!/bin/bash

# Define the countdown duration in seconds
countdown_duration=20

# Function to send a message to the Docker container
send_cmd() {
  cmd="$1"
  sudo sh -c "echo '$cmd' | socat EXEC:'docker attach mcbe-world',pty STDIN"
}

# Announce
announce_text="Daily server restart commencing in $countdown_duration seconds..."
send_cmd "say $announce_text"

# Perform the countdown
for ((i = $countdown_duration; i >= 1; i--)); do
  #echo "Restaring in $i seconds"
  countdown_text="Restarting in $i seconds"
  send_cmd "say $countdown_text"
  sleep 1
done

# Gracefully shutdown server
#  Note: stopping forces the mcbe container to restart on it's own. 
#  Not sure why that's the case, but it's the end result I want...
send_cmd "stop"

P.S. I really need to figure out how to get the RCON solution working because that would be a more elegant way to handle things.

P.P.S Example run (yes, the timing and spelling were updated after this screenshot 😁)

[–] unique_hemp@discuss.tchncs.de 2 points 1 year ago (1 children)

Nice, glad to help!

As for the automatic restarting, the whole Docker container exits, if the main process (specified as CMD in the Dockerfile) exits (in this case the minecraft server) and Synology probably auto-restarts the containers on exit by default.

[–] GlassHalfHopeful@beehaw.org 2 points 1 year ago

Good to know about the main proc. I wasn't aware. And it is indeed set to auto restart. I just hadn't realized the stop alone would trigger that. I had figured I would need to take the additional step.

[–] CAPSLOCKFTW@feddit.de 4 points 1 year ago (2 children)

what about the minecraft rcon console? Or op'ing yourself and issuing /stop from ingame?

[–] GlassHalfHopeful@beehaw.org 4 points 1 year ago* (last edited 1 year ago)

Ooh. I was not aware of the RCON protocol. Looking into now. This may be the exact thing I need. Thanks for the lead.

[–] GlassHalfHopeful@beehaw.org 3 points 1 year ago

Well,RCON has not fared well. Afaik, I've set things up correctly but the client I'm using (mcrcon) keep returning Error 111: Connection refused.

  • This post got me to direct things to the right IP which I could get with docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mcbe-world.
  • docker port mcbe-world shows that the rcon port is open
  • the server.properties files for the mc server has the relevant rcon lines
[–] partizan@lemm.ee 3 points 1 year ago (2 children)

just run docker exec mcbe-world /stop then just wait a bit till it shuts down cleanly and then start it again...

[–] unique_hemp@discuss.tchncs.de 3 points 1 year ago

AFAIK /stop is not just a shell command, it needs to be given to stdin of the minecraft process. The broader question here is how to pass something to stdin of a running process.

[–] GlassHalfHopeful@beehaw.org 1 points 1 year ago (1 children)

docker exec mcbe-world just gives access to the container so commands can be executed. /stop is a specific command for the MC server running in that container. The process is already running and I am trying to figure out how to issue a command to it... and the other comment in this post referencing "rcon" might be a solution...

[–] partizan@lemm.ee 1 points 1 year ago

yes, and that command I pasted will run that /stop command inside the docker container. The same way you can list files or do any other commands on a running container:

# docker exec heimdall ls -la /
total 148
drwxr-xr-x   1 root root  4096 Jul 14 07:09 .
drwxr-xr-x   1 root root  4096 Jul 14 07:09 ..
-rwxr-xr-x   1 root root     0 Jul 14 07:09 .dockerenv
drwxr-xr-x   1 abc  abc   4096 Jul 14 07:09 app
drwxr-xr-x   1 root root  4096 Jun 17 15:30 bin
drwxr-xr-x   2 root root 12288 Jun 17 15:30 command
drwxr-xr-x   7 abc  abc   4096 Dec  3  2022 config
drwxr-xr-x   1 abc  abc   4096 Jun 23 20:35 defaults
drwxr-xr-x   5 root root   340 Aug 19 04:52 dev
-rwxr--r--   1 root root 18257 Jan  1  1970 docker-mods
drwxr-xr-x   1 root root  4096 Aug 19 04:52 etc
drwxr-xr-x   2 root root  4096 Jun 23 20:35 heimdall
[–] gammarays@lemm.ee 1 points 1 year ago (1 children)

Are you able to docker attach to the container?

[–] GlassHalfHopeful@beehaw.org 1 points 1 year ago* (last edited 1 year ago) (2 children)

This looked so promising.

Via SSH, I can indeed use docker attach and from within I can issue a stop for MC server. Works fine.

However, the Synology task scheduler via DSM doesn't seem to be able to similarly attach and then issue the stop command. I get this back via email (for when a scheduled task fails):

Task Scheduler has completed a scheduled task.

Task: MC Graceful Restart Start time: Tue, 29 Aug 2023 17:19:41 -0500 Stop time: Tue, 29 Aug 2023 17:19:42 -0500 Current status: 127 (Interrupted) Standard output/error:

the input device is not a TTY /bin/bash: line 1: stop: command not found

[–] gammarays@lemm.ee 2 points 1 year ago* (last edited 1 year ago)

If you aren't starting your container with the -it options (for docker run), try setting them so that it allocates a tty. The fact that it works with SSH however makes me think that perhaps the Synology task runner can't run interactive commands like docker attach because it has no stdin. In that case you'll need to do something like this: https://serverfault.com/questions/885765/how-to-send-text-to-stdin-of-docker-container/947763#947763 to pipe the stop command into the stdin of the bedrock server.

[–] gammarays@lemm.ee 1 points 1 year ago* (last edited 1 year ago)

If you aren't starting your container with the -it options, try setting it so that it allocates a tty. The fact that it works with SSH however makes me think that perhaps the Synology task runner can't run interactive commands like docker attach because it has no stdin. In that case you'll need to do something like this: https://serverfault.com/questions/885765/how-to-send-text-to-stdin-of-docker-container/947763#947763 to pipe the stop command into the stdin of the bedrock server.