3

I have a third party .bat file (wso2server.bat) which start a server.

I'm starting it by

Process process = Runtime.getRuntime.exec(cmd /C start cmd /C  C:\wso\wso2esb-4.9.0\bin\wso2server.bat);

I tried to stop this

process.destroy();  
and
process.destroyForcibly();

The process.isAlive() returns "false" after destroy. But the server still running!

I also tried to run with

ProcessBuilder pb = new ProcessBuilder(params);
process = pb.start();   

and stop it, but it doesn't matter, how I start it, the java.exe - and the server - still running and I can not stop it. I think this is because .bat starts another process...

So, how can I stop this java.exe?

user2287094
  • 267
  • 4
  • 13
  • What's wrong with just using `Runtime.getRuntime().exec("cmd /c start C:\wso\wso2esb-4.9.0\bin\wso2server.bat");`? or possibly even `Runtime.getRuntime().exec("cmd /c C:\wso\wso2esb-4.9.0\bin\wso2server.bat");`? – Compo Mar 21 '17 at 12:09
  • cmd /c start : the server starts, but can not stop it (the same as above) But with cmd /c : the server doesn't start. The java.exe appears in Task Manager, but the Http Site unavailable. – user2287094 Mar 21 '17 at 12:20
  • start in this case is not an instruction to the server, it is an instruction to the batch file, I do not understand why `cmd /c file.bat` wouldn't start the server. What is the content of your bat file? – Compo Mar 21 '17 at 12:31
  • https://github.com/wso2/product-ss/blob/master/modules/distribution/src/main/bin/wso2server.bat – user2287094 Mar 21 '17 at 13:08
  • It is my understanding that in Windows you would start the server using `C:\wso\wso2esb-4.9.0\bin\wso2server.bat --run` and are required to excecute `Ctrl-C` in that cmd.exe window to stop that server. – Compo Mar 21 '17 at 15:52
  • Yes, but how can I send a Ctrl-c to that cmd.exe? I found this: http://stackoverflow.com/questions/1835885/send-ctrl-c-to-process-open-by-java but it doesn't work. – user2287094 Mar 22 '17 at 06:29

1 Answers1

3

start command does not wait for process completion, so you can not control the server process if the batch command just runs the server and exits.

Use start /wait ... command to run the batch file. start /wait will wait for process completion, so you will have a process tree like

cmd "start"
    cmd "batch"
        server

To kill the process tree use taskkill /pid N /t /f command.

To get the PID of the root cmd process

  • setup cmd title to root_cmd
  • get a process list
  • find the process with the window title root_cmd
  • extract the PID and save it to the %TEMP%/pid.txt

    title root_cmd
    for /f "tokens=2 delims=," %A in ('tasklist /v /fo csv ^| findstr root_cmd') do echo %~A>"%TEMP%/pid.txt"
    

Combine all together

  • run the server cmd /c "title root_cmd & (for /f "tokens=2 delims=," %A in ('tasklist /v /fo csv ^| findstr root_cmd') do echo %~A>"%TEMP%/pid.txt") & start /wait "" cmd /c wso2server.bat"
  • kill the server set /p PID=<"%TEMP%/pid.txt" & call taskkill /pid %PID% /t /f

Update.

For Java:

package com.example;

import java.io.IOException;
import java.lang.Runtime;

public class Main {
    public static void main (String args[]) {
        try {
            if (args.length < 1) {
                System.out.println("Start server");
                Runtime.getRuntime().exec(new String[]{ "cmd", "/c", "start /wait \"launcher_cmd\" s.bat"});
            } else {
                System.out.println("Stop server");
                Runtime.getRuntime().exec(new String[]{ "cmd", "/c", "taskkill /fi \"WINDOWTITLE eq launcher_cmd*\" /t /f"});
            }
        } catch(IOException e) {
            System.out.println(e);
        }
    }
}

For some reason for ..., echo ...>filename commands run by exec are not working as expected. So I have modified the method:

  • start /wait "title" command will setup cmd's title and run the batch file
  • taskkill /fi "WINDOWTITLE eq launcher_cmd*" /t /f will kill the cmd "title" process and its descendants
  • since we use cmd /c everywhere the root process will also exit after children will be killed
Dmitry Sokolov
  • 3,118
  • 1
  • 30
  • 35
  • Thanks for the reply. I tried this command: Runtime.getRuntime().exec("cmd /c \"title root_cmd & (for /f \"tokens=2 delims=,\" %A in ('tasklist /v /fo csv ^| findstr root_cmd') do echo %~A>\"%TEMP%/pid.txt\") & start /wait \"\" cmd /c C:\\wso\\wso2esb-4.9.0\\bin\\wso2server.bat"); Unfortunately, it starts 2 cmd window, but does not start the server. Print screen: https://ibb.co/mX9HWF – user2287094 Mar 22 '17 at 06:07
  • Added Java example. – Dmitry Sokolov Mar 23 '17 at 14:16