Now I’m not gonna go and tell you in this post how to set up a minecraft-server (such a long word!, ‘gonna use mcs as a short form from here onwards). Because that has been covered a million times. But what is a problem in general on Gentoo is setting up init-scripts for apps which are not available in the default portage and you don’t want to get them from some non default portage trees. Now especially programs like mcs are a problem as they rely on some kind of user-input on stdin, but as everyone knows who has set up a single init script for OpenRC’s runscript, knows that by default stdin, stdout and stderr get thrown away when daemonizing the program to the background. So the only way you can execute any mcs specific commands is by either logging in to the server as an admin via the client application (which is in my opinion a no-go) or by starting mcs capsulated in a screen session. The second approach might be acceptable for a lot of people but i didn’t want an extra screen session running just for mcs.
if you don’t care about why i’m doing things the way i do them, then just skip to “the final init script”
With current versions of start-stop-daemon you can in fact redirect stdout and stderr so these two are not a problem (for mcs they aren’t anyway as this is mostly done by a logfile residing in
logs/latest.log). But with stdin it’s a different story…
The Problem with stdin
Now what you could do is just create a fifo file (via
mkfifo <file>) and pipe it likewise
app_with_stdin_replaced_by_a_fifo < fifo_file but this will have the problem that the system matches up pairs of readers/writers. So once the first
echo cmd > fifo_file has been submitted the application will receive an EOF. And at least java will then stop listening on stdin, or in this case the fifo (I’m sure at least one other application will behave in a similar way… not. god f!#$ing da%& it JAVA >:$). An actual possible solution to this problem is the program
The magical program “tail”:
tail -f <file> has the (at least for this use-case-scenario) magical feature that it, to quote the man-page:
[…]output appended data as the file grows; […]
So it’ll ignore eof’s and basically keep running and posting stuff to stdout until it receives some terminating signal like SIGINT (ctrl + C), SIGTERM or SIGKILL.
Therefore we can use it’s output and pipe it to the application’s input. The connection between tail and the java-app will usually not break => java will not get an EOF. And tail will just ignore an eof and wait for further input. At this point you could just dump the fifo altogether by now, but then to ensure correct functioning of
tail -f you’d have to resort to only appending commands to the input file. While this could be thought of as a feature (somewhat similar to .bash_history), this will also take away some diskspace depending on the amount of commands you send to this stdin-file. Considering that we try to daemonize a server-program and uptime is everything this will eventually turn into a problem (and may it be after 50 years of uptime :P). So I’d suggest: stick to the fifo. (plus if you once do a
echo cmd > non_fifo, tail will behave buggy for the next 1 to 10 following commands)
Using this knowledge in an init-script for Gentoo with OpenRC
Now, finally the rest is a piece of cake, right?
Nope. The problem being start-stop-daemon: it can’t pipe.
and before anyone mentions it: yeah there are actually quite a few reasons why it doesn’t support pipes.
So a solution to this problem is starting an ordinary shell via start-stop-daemon and giving it tail and the program as an argument, then using some sort of quoting-hell-magic so it’ll not break and so on and so forth… you see where this is going. So i decided to write a nice little c-program which does most of all this for me :D.
syntax is as follows:
fi2sti <fifo_file> <prog> [prog_args]
fifo_file is a fifo file (duh)
prog is the program to launch (duh-duh)
prog_args are the arguments for prog (duh-duh-dumm)
prog_args is (depending on the program to launch) obviously optional.
Bevore i give you the link of this program’s github-page let me clear up one thing: My disclaimer on the github page might be a little frightning… the only thing i didn’t want to happen was me being sued because this program broke on someones system, so don’t be afraid. To my knowledge this program should be save to use. If you want to take a look at the source code and leave some feedback and/or suggestions feel free to do so, i’ll gladly appreciate it :). Without further ado here’s the github link.
the final init script
OK, now things are easy:
- Download and compile my program from github.
- Copy the executable (
fi2sti) to a folder which is in your PATH variable (like
- In this init script for minecraft server adjust the following variables:
SERVICEto the version of you minecraft_server (or just create a symlink like so:
ln -s minecraft_server.version.jar minecraft_server.latest.jar, where “version” is the version you’re using)
USERNAMEto the user which should run mcs.
MCPATHto the path where you minecraft_server.latest.jar resides.
Anything else does not have to be modified and should work out of the box. Besides, the variable names are pretty self explanatory (like
I think this is a nicer solution than using screen for it. But if you disagree, see a bug or just want to let me feel your hate for me doing [insert_insane_thing_i’ve_done_here], then leave a message in the comments below :).
Thanks for reading, hope you found some of it usefull.
PS: I’m not a native english speaker, so if you find any grammatical or spelling mistakes, feel free to show me the best side of your inner grammar nazi ;D.
Credits: Post Image: Larry the cow by Ethan Dunham and Matteo Pescarin, licensed under CC-BY-SA/2.5. Resized and copied into a Minecraft screenshot by me using paint.net v4.0.3. Minecraft by Mojang. Entire Picture licensed under the terms of the Creative Commons Attribution-ShareAlike 2.5 license.