【问题标题】:Kill process which was started from Java from a batch file从批处理文件中杀死从 Java 启动的进程
【发布时间】:2017-08-13 01:54:12
【问题描述】:

我有一个启动服务器的第三方 .bat 文件 (wso2server.bat)。

我是从

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

我试图阻止这个

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

process.isAlive() 在销毁后返回“false”。但是服务器还在运行!

我也尝试过运行

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

并停止它,但没关系,我如何启动它,java.exe - 和服务器 - 仍在运行,我无法停止它。 我认为这是因为 .bat 启动了另一个进程......

那么,我怎样才能停止这个 java.exe?

【问题讨论】:

  • 只使用Runtime.getRuntime().exec("cmd /c start C:\wso\wso2esb-4.9.0\bin\wso2server.bat"); 有什么问题?甚至可能是Runtime.getRuntime().exec("cmd /c C:\wso\wso2esb-4.9.0\bin\wso2server.bat");?
  • cmd /c start :服务器启动,但不能停止(同上) 但是使用 cmd /c :服务器不启动。 java.exe 出现在任务管理器中,但 Http 站点不可用。
  • 在这种情况下启动不是对服务器的指令,它是对批处理文件的指令,我不明白为什么cmd /c file.bat 不会启动服务器。你的bat文件内容是什么?
  • 据我了解,在 Windows 中,您将使用 C:\wso\wso2esb-4.9.0\bin\wso2server.bat --run 启动服务器,并且需要在该 cmd.exe 窗口中执行 Ctrl-C 才能停止该服务器。

标签: java windows batch-file cmd process


【解决方案1】:

start命令不等待进程完成,因此如果批处理命令只是运行服务器并退出,则无法控制服务器进程。

使用start /wait ... 命令运行批处理文件。 start /wait 将等待流程完成,因此您将拥有类似的流程树

cmd "start"
    cmd "batch"
        server

要杀死进程树,请使用taskkill /pid N /t /f 命令。

获取根cmd进程的PID

  • cmd 标题设置为root_cmd
  • 获取进程列表
  • 找到窗口标题为root_cmd的进程
  • 提取PID并将其保存到%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"
    

结合在一起

  • 运行服务器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"
  • 杀死服务器set /p PID=<"%TEMP%/pid.txt" & call taskkill /pid %PID% /t /f

更新。

对于 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);
        }
    }
}

由于某种原因,exec 运行的for ...echo ...&gt;filename 命令无法按预期工作。所以我修改了方法:

  • start /wait "title" command 将设置 cmd 的标题并运行批处理文件
  • taskkill /fi "WINDOWTITLE eq launcher_cmd*" /t /f 将杀死 cmd "title" 进程及其后代
  • 因为我们在任何地方都使用cmd /c,所以根进程也会在子进程被杀死后退出

【讨论】:

  • 感谢您的回复。我试过这个命令: Runtime.getRuntime().exec("cmd /c \"title root_cmd & (for /f \"tokens=2 delims=,\" %A in ('tasklist /v /fo csv ^| findstr root_cmd') 做 echo %~A>\"%TEMP%/pid.txt\") & start /wait \"\" cmd /c C:\\wso\\wso2esb-4.9.0\\bin\\wso2server .bat"); 不幸的是,它启动了 2 个 cmd 窗口,但没有启动服务器。打印屏幕:ibb.co/mX9HWF
  • 添加了 Java 示例。
猜你喜欢
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多