Linux + screen + craftbucket +interaction from outside + autosave + stop

Discussion in 'Bukkit Help' started by ShivalWolf, Jan 25, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    ShivalWolf

    Hi All

    I have been looking for how to do this for days now. I have needed a way to interact with a running copy of craftbukkits's console that i have running inside a screen session. This can be used by web interfaces or command/control scripts outside of craftbukkit.
    My current init script force kills the process. I will be providing an update soon that will trigger a save and proper stop.

    Now to the meat of this post.
    You can not interact with a java -jar under linux using its /proc/(pid)/fd/0,1,2 interface due to the way java closes and then reopens its connection to stdin. The only way to interact with the console is to use a method to start your own manager which starts craftbukkit.jar The method outlined below allows you to send commands to the screen session running craftbukkit from a script as if you were typing them into the console.

    As the user you are running the screen session and craftbukkit as:

    Code:
    screen -S (name) -p(screen number) -X stuff "(command)^M"
    (name) = the PID of the screen session or the name of the screen session. I auto start my screen session and call it MineCraft

    (screen number) = If its the only process running inside the screen which it should be then this will always be "0"

    (command) = the command you want to run"save-all" "stop" (any command you could type in console)

    ^M = Enter/Return This can be generated by hitting Ctrl-v and then hitting enter.


    So that is all there is to it. Those making web interfaces or want to be able to get stats from outside the minecraft server without creating a plugin there's the commands you need.

    I hope this helps others running a linux server.
     
  2. Offline

    Chewi

    For my Gentoo Linux package, I used tmux instead because it's much easier to configure permissions. It's all done through the socket file so I just made it accessible to the games group.

    I thought about piping through "stop" when stopping the server to make sure it saves properly but someone else on this forum suggested using Apache Daemons to do this instead. I plan to do that but I'm waiting to see how Bukkit pans out first.
     
  3. Offline

    Kekec852

    I've create a wrapper around startup class using Apache Commons Daemon. And implements start and stop methods so when I restart server it sand stop command to server.

    Here is wrapper (NOTE: if Notch change stop method (a()) it will brake this wrapper):
    Code:
    public class MinecraftDaemon implements Daemon{
        private MinecraftServer server;
        private Thread mainProgram;
        public void init(DaemonContext dc) throws DaemonInitException, Exception {
            dc.getController();
            OptionParser parser = new OptionParser() {
    
                {
                    acceptsAll(asList("?", "help"), "Show the help");
    
                    acceptsAll(asList("c", "config"), "Properties file to use").withRequiredArg().ofType(File.class).defaultsTo(new File("server.properties")).describedAs("Properties file");
    
                    acceptsAll(asList("P", "plugins"), "Plugin directory to use").withRequiredArg().ofType(File.class).defaultsTo(new File("plugins")).describedAs("Plugin directory");
    
                    acceptsAll(asList("h", "host", "server-ip"), "Host to listen on").withRequiredArg().ofType(String.class).describedAs("Hostname or IP");
    
                    acceptsAll(asList("w", "world", "level-name"), "World directory").withRequiredArg().ofType(String.class).describedAs("World dir");
    
                    acceptsAll(asList("p", "port", "server-port"), "Port to listen on").withRequiredArg().ofType(Integer.class).describedAs("Port");
    
                    acceptsAll(asList("o", "online-mode"), "Whether to use online authentication").withRequiredArg().ofType(Boolean.class).describedAs("Authentication");
    
                    acceptsAll(asList("s", "size", "max-players"), "Maximum amount of players").withRequiredArg().ofType(Integer.class).describedAs("Server size");
                }
            };
            OptionSet optiotns = parser.parse(new String[]{});
            server = new MinecraftServer(options);
            mainProgram = new Thread(server)
        }
    
        public void start() throws Exception {
            mainProgram.start();
        }
    
        public void stop() throws Exception {
            server.a();
        }
    
        public void destroy() {
            mainProgram.stop();
        }
    }
    
    All you need to do is to comple jsvc from Apache Commons and create (init.d) startup scrip.

    Code:
    #!/bin/sh
    mc_start() {
          #only need this if you did't set it ...
          export JAVA_HOME=/path/to/java/bin/folder
          cd /path/to/your/mc/folder
          #
          jsvc -jvm server -pidfile /var/run/mc.pid -outfile /var/log/minecraft.stdout.log -errfile /var/log/minecraft.stderr.log -cp commons-daemon.jar:your-daemon-impl.jar:craftbukkit-0.0.1-SNAPSHOT.jar -Xms1024M -Xmx1024M your.package.Daemon
    }
    
    mc_stop() {
         jsvc -stop /var/run/mc.pid
    }
    
    mc_restart() {
      mc_stop
      sleep 1
      mc_start
    }
    
    case "$1" in
    'start')
      mc_start
      ;;
    'stop')
      mc_stop
      ;;
    'restart')
      mc_restart
      ;;
    *)
      mc_start
    esac
    
    I hope you understand some of this ... :p

    Edit: This script will do somthing like save-all and stop using that server.a(); method.
     
  4. Offline

    barghest

    Very awesome post. I've been posting this hint anytime someone talks about using screen to do this, because I was lucky to find this info out and it's very, very important:

    You cannot use screen -X stuff to send keystrokes to a screen session that has never been attached.

    So if you have a script to start your screen session with -d to immediately background screen while the server starts up, when your scripts try to stuff the screen session with commands later it will silently fail. Yes, silently. It won't do anything and it won't tell you that it's doing nothing, let alone why not. Yes, this is bogus as hell. Long-standing screen bug.

    The solution is to start the screen session attached, so you're actually watching the server output its "starting server..." messages, etc., and THEN detach from the session with ctrl-a-d. At that point, your screen -X stuff commands will actually work.
     
  5. Offline

    Chewi

    I just tried this with tmux and it doesn't have this problem. The output was a little squashed because it assumes a terminal width of 80 until the session is attached but this can be changed.
     
  6. Offline

    ShivalWolf

    I don't seem to have that issue either where it requires it to be attached.
    I will do some additional digging though and see what happens but it does seem odd it requires it to have been attached before.
    --- merged: Jan 25, 2011 9:36 PM ---
    Hmmm i have never used tmux before though i have heard of it. Sounds like a much nicer option given it gives an IO socket.
    Still looking for a screen option though but maybe tmux is a better way to go.
    --- merged: Jan 25, 2011 9:40 PM ---
    This is how i am starting screen as part of the init script.

    INTERFACE="/usr/bin/screen -A -m -d -S $NAME"

    I never open the screen session and commands are still accepted and processed. Maybe its the version of screen.

    >screen -v
    Screen version 4.00.03jw4 (FAU) 2-May-06

    >dpkg --list|grep screen
    ii screen 4.0.3-14 terminal multiplexor with VT100/ANSI terminal emulation
     
  7. Offline

    Chewi

    Don't get me wrong, I've used screen for years. I only tried tmux for the first time when trying to package Minecraft. Here's the init script I wrote. It's a bit Gentoo-specific though.
     
  8. Offline

    ShivalWolf

    I have always liked gentoo's init system and it would be alterable.
    I just modified my init system with the new commnad's and i am not having any issue. I wonder if its just a weird thing with screen on debian compared to screen on another platform.
     
  9. Offline

    Enclude

    If I use:
    screen -S smc -X stuff "save-all^M"

    In Atached screen i see: "save-all^M" not " [INFO] CONSOLE: Forcing save... ; [INFO] CONSOLE: Save complete." I must confirmed ths with enter,
    How can I skip this. Make automatically.

    Best Wishes.

    @ PS: I from Poland, an my English is very bad level :)
     
  10. Offline

    Chewi

    I'm not sure but try putting a space before ^M.
     
    sean.m.rice likes this.
  11. Offline

    Duendek86

    I have just run my server in a vnc session... If I want to interact just connect with vncviewer to my host. Even if my x crash, my server is fine :)
     
  12. Offline

    Chewi

    That will work of course but it's a bit silly for a console application. Especially Minecraft, you need all the RAM you can get!
     
  13. Offline

    ShivalWolf

    That looks like your ^M is being read as a string and not as a literal Enter character.
    In the 1st post it shows you how to make an enter character by hitting Ctrl-V and then Enter to get the special ^M character.
     
  14. Offline

    Chewi

    It may well be this but with tmux, you can literally type ^M and it works.
     
  15. Offline

    ShivalWolf

    I still need to get around to looking at tmux but in this case with screen if you just type ^M it will not work It needs to be entered as a special character.
    Its kinda stupid that it does not accept \n or other \ commands either.
     
  16. Even easier way of doing it: mkfifo minein; tail -f minein | java .... -jar craftbukkit.jar Then you can echo "whatevercommand" > minein on another shell process. Only downfall: you have to ctrl+c after the java process has finished because tail will not kill automatically (which is normal). Cat will NOT work this way, as end-of-file is sent to java which denies any more input. tail never sends an EOF.
     
Thread Status:
Not open for further replies.

Share This Page