user2287094
user2287094

Reputation: 277

Kill process which was started from Java from a batch file

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?

Upvotes: 3

Views: 3592

Answers (1)

Dmitry Sokolov
Dmitry Sokolov

Reputation: 3180

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

Upvotes: 3

Related Questions