|
It was thus said that the Great Russell Haley once stated:
> Hello,
>
> Some months back I started running a Minecraft server (Java) on FreeBSD.
> There are two issues that I've run into:
> 1) The Minecraft client (game) automatically updates and will not run
> against servers of prior revisions without changing client settings.
> 2) The Minecraft 'server' jar uses stdin and stdout. That means (in my
> understanding) that the process must be kept in the foreground for
> interaction. The current solution I've found (on the Minecraft wiki)
> requires screen/tmux to allow one to run a server instance from ssh.
No, you can run the process as:
GenericUnixPrompt> java -jar BlahObjectThing </dev/null >/dev/null 2>/dev/null &
That will run your server in the background with stdin, stdout and stderr
all pointing to /dev/null (the bit bucket).
> The solution I now envision is to use lua-http and cqueues to create a
> 'controller' that updates the server.jar file and runs the application
> without the need for the process to be in the foreground. The parts I see
> needing are:
> - A routine that checks for updates and downloads the jar files
> - A 'thread' for running the minecraft server.jar file in java. This
> 'thread' would re-direct stdin and stdout. This 'thread' should also be
> able to stop and start the running jar file.
> - A websocket server to funnel the captured IO to a webpage for
> interactivity.
Avoid system level threads for this. Mixing system level threads
(pthreads) and running another process (via fork()) do not mix [1]. So
you'll end up with Lua coroutines and a sepearate process. Let's handle
that first.
function start_minecraft()
local pid,err = fork()
if pid then
if pid == 0 then -- child process
redirect(stdin,"/dev/null") -- or a file or a pipe
redirect(stdout,"/dev/null")
redirect(stderr,"/dev/null")
exec("java",{ "-jar" , "minecraft.jar" })
_exit(1) -- exec() failed, we exit
end
-- mindcraft has PID of child
-- it is running, and so are we.
return pid,err
end
stdin, stdout and stderr can be redirected to a file, a pipe, a named
pipe, what have you. I'm justing using "/dev/null" as an example for now.
You could use a file that you serve up through HTTP to see what happens; a
pipe to get the last N bytes of logging, etc. That's up to you.
I should note that the functions fork(), redirect(), exec() and _exit()
need to be adjusted to whatever module you use that provides such calls
(redirect() may be called dup() or dup2() or something like that).
The main process (as I would do it) would then use coroutines (or Lua
threads) to handle things. One coroutine to periodically check for an
updated jar file, and if so:
while true do
info = stat("myjarfile.jar")
if info.st_mtime ~= original.st_mtime then
raise(minecraft_pid,SIG_TERM)
status = wait(minecraft_pid)
minecraft_pid = start_minecraft()
original.st_mtime = info.st_mtime
end
wait_for(some_amount_of_time)
end
> So far, I have roughed in the server.jar checks and download, and the
> websocket server for communications. The code can be found here:
> https://github.com/RussellHaley/minecraft-runner/mc-runner.lua
>
> What I don't know/understand yet if it's possible to run/control a process
> from Lua so that I can grab stdin/stdout? I am hoping there is something in
> cqueues to do this, but once again thought I'd send out a general request
> for ideas.
>
> Any input would be grand.
You need something that handles networking, coroutines and some POSIX
functions (fork(), wait(), etc).
-spc
[1] It probably *can* be done, but it's certainly above my pay grade,
and I write servers for a living.