1

I got the following code that starts a minecraft server:

public class App {

    public static void main(String...args) throws Exception {
        final ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.directory(new File("C:/Users/trudler/Desktop/New folder (4)/"));
        processBuilder.command("java", "-jar", "server.jar");
        Process process = processBuilder.start();

        InputStream is = process.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line;

        System.out.printf("Output of running %s is:", Arrays.toString(args));

        while ((line = br.readLine()) != null) {
          System.out.println(line);
        }
    }
}

I want to do daily backups, so I need to send a "stop" command everyday, to be sure that the files won't be touched while I do the backup (and "start" the server again afterwards).

How can I do this?

I tried it using processBuilder.command("stop"); but that doesn't seem to work.

codepleb
  • 10,086
  • 14
  • 69
  • 111

1 Answers1

4

I think you want to send commands to an existing process, so I think this is what you are looking for:

Execute external program using ProcessBuilder and provide input

public class App{

   public static void main(String... args) throws Exception {
      while (true) {
         Process process = Example.startMinecraft(args);
         // Stops for sixty seconds
         Thread.sleep(1000 * 60);

         BufferedWriter out = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
         out.write("stop");

         // Wait for the process to stop
         process.waitFor();

         // Now start your Backup
         Process backupProcess = Example.startBackup();
         backupProcess.waitFor();

         // After your backup completed your minecraft server will start again
      }

   }

   private static Process startMinecraft(String... args) throws IOException {
      final ProcessBuilder processBuilder = new ProcessBuilder();
      processBuilder.directory(new File("C:/Users/trudler/Desktop/New folder (4)/"));
      processBuilder.command("java", "-jar", "server.jar");
      Process process = processBuilder.start();

      InputStream is = process.getInputStream();
      InputStreamReader isr = new InputStreamReader(is);
      BufferedReader br = new BufferedReader(isr);

      Thread t1 = new Thread(() -> {
         try {
            String line;
            System.out.printf("Output of running %s is:", Arrays.toString(args));
            while ((line = br.readLine()) != null) {
               System.out.println(line);
            }
         } catch (IOException e) {
            // Do something when the Exception is thrown
         }
      });
      t1.start();

      return process;
   }

   private static Process startBackup(){
      // Here you have to build your backup process
   }
}

If you are on a linux machine I would advise to use some script in /etc/init.d/ instead and use a restart command using this script in a cron job.

Community
  • 1
  • 1
oli-ver
  • 362
  • 1
  • 13
  • This looks good, but it doesn't seem to work. :/ There won't be anything printed to the console, nor does the server stop. – codepleb Feb 07 '16 at 17:06
  • Did you try this with two seperate threads, one for the outputs of the process and one for the input? Your while loop will not end until you close the server. – oli-ver Feb 07 '16 at 17:41
  • You should really not do this using Java at all. You want to start minecraft, stop it and then start a backup and then start minecraft again. This is standard operating system business and nothing you need a Java program for. Windows: http://corey.degrandchamp.com/2011/03/26/minecraft-server-stop-backup-restart/ Linux: https://wiki.natenom.de/minecraft/mcontrol – oli-ver Feb 07 '16 at 17:58
  • I edited the answer for the sake of a working example how to do this in Java. But I still think you should'nt :-) – oli-ver Feb 07 '16 at 18:25
  • Hi and thank you very much for the effort. I know that with the threads, I already tried it before, but it didn't work. I used `System.out.println()` and the debug mode to assert that the code actually runs, but it didn't work for some reason. How I do it doesn't really matter, but I need to be able to monitor the server. – codepleb Feb 07 '16 at 18:34
  • I understand, so you want to have the server run by Java to do other things later. So, did my example work then? If the process exits after the "stop" commando, it should. Perhaps you need "stop\n". I will try myself later. – oli-ver Feb 07 '16 at 18:40
  • Ah wait, I made a mistake... I thought you actually SEND the command in a separate thread and do not listen to it. Problem solved, it works now. Thanks so much! :) But just for interest: Why is this a bad design? If you do it using java, you can run the program on linux AND windows if not mistaken. – codepleb Feb 07 '16 at 18:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102848/discussion-between-oli-ver-and-trudler). – oli-ver Feb 07 '16 at 18:49
  • I did not reach you in chat: I don't think it's bad design, I just did not understand the advantage at first. I like the idea of a java wrapper that automatically stops the server and makes backups. If you start this as a github project, I will stop by :-). I am curious what else you want to do (you said you want to monitor the server somehow). – oli-ver Feb 07 '16 at 19:27
  • Sry, I was away. I can surely put this thing on github. I'm not really an experct when it comes to this, but this could surely be a good practice. – codepleb Feb 07 '16 at 19:33