【问题标题】:How to Terminate a Process Normally Created using ProcessBuilder如何终止通常使用 ProcessBuilder 创建的进程
【发布时间】:2015-03-12 14:54:31
【问题描述】:

我正在我的 Java 应用程序中使用 ProcessBuilder 创建进程。创建的进程执行一些 FFMPEG 命令,这些命令实际上将 RTSP 流复制到指定的目标媒体文件中。

ProcessBuilder builder = new ProcessBuilder("ffmpeg", "-i", RTSP_URL, "-f", fileFormat, destFilePath);
Process processToExecute = builder.start();

我想在进程完成执行之前关闭它。因此,如果我直接在 Windows CMD 中运行此 FFMPEG 命令,然后在 5 秒后按“CTRL+C”,则进程会以状态“2”终止。我可以播放目前创建的媒体文件。

所以,如果我在我的 Java 应用程序中执行相同的操作:

 process.destroy(); //I call this method after 5 sec

我得到状态码“1”,表示异常终止。我通过以下方式获取状态:

 processToExecute.destroy();
 processToExecute.exitValue(); //This return me status '1'

我无法播放媒体文件,我认为这是由于进程异常终止。

那么,如何像在 CMD 中使用 (CTRL+C) 一样终止使用 ProcessBuilder 创建的进程,以便播放创建的媒体文件?

我想终止 Java 应用程序中的进程(使用 ProcessBuilder 创建),状态码为“2”,当我使用 CMD 终止进程时得到。

EDIT#01: --- 分享发现

所以,当我在应用程序终止后尝试删除该文件时,我收到以下错误:

The Action Can't be Performed Because File is Opened in FFMPEG.exe

这意味着进程没有终止它正在执行的命令。该命令仍然占用了这个文件,这就是我无法播放它的原因。当我调用时进程终止:

 processToExecute.destroy();

但是,它正在执行的任务(即执行命令)仍然处于活动状态。奇怪!!!!

EDIT#02:分享终极理由

实际上,如果我在进程运行时直接在 cmd 中按“CTRL+C”或“q”,则它会成功终止该进程,并且该进程在当前正在执行的进程列表中不再可见。

当我调用方法时以编程方式:

cmd> processToExecute.destroy();

它终止了进程,但是当我看到当前正在执行的进程列表时,我仍然可以在那里看到它们。

如果我尝试在另一个 CMD 中使用 'taskkill' 或 'kill' 命令通过指定它们的名称或 pid 来终止此进程,仍然会异常终止。

附:我使用以下命令查看正在运行的进程:

tasklist

由此证明,Application 中的 destroy() 方法和另一个 CMD 中的“taskkill 或 kill”命令不会像按“CTRL+C”和“q”那样正常终止进程。

【问题讨论】:

  • 我不知道你是否可以在Java中做到这一点,但根据你的描述,你需要向FFMPEG发送一个control-C信号。执行此操作的 Win32 API 调用是 GenerateConsoleCtrlEvent。顺便说一句,问题不在于状态码本身,这只是另一个症状;使用状态码 2 终止进程与使用状态码 1 终止进程没有什么不同。您必须要求它终止(而不是强制它这样做),以便它可以运行其清理例程。
  • 如果是 ffmpeg,也许给它发送一个 'q' 键告诉它退出...
  • 是的,如果我通过 cmd 发送“q”,它会正常终止进程。但我想从我的应用程序内部终止它。
  • @BilalAhmedYaseen:你找到解决方案了吗?我遇到了同样的问题。
  • 我创建了一个库来做视频导出 (github.com/hamoid/video_export_processing) 并在 Windows 上遇到了这个确切的问题。是否可以按照stackoverflow.com/questions/3240704/… 底部的建议向进程发送击键?

标签: java windows ffmpeg processbuilder kill-process


【解决方案1】:

也许可以试试……

builder.inheritIO();
System.exit(2);

或者您可以尝试写入进程的标准输入...

process.getInputStream().write(exitCode);

【讨论】:

  • Java 中的“Process”类没有这样的“inheritIO()”方法。 ProcessBuilder builder = new ProcessBuilder(command);处理 processToExecute = builder.start();
  • 亲爱的 InputStream 上再次没有“write()”方法。我们可以从 InputStream 中读取,而可以在 OutputStream 上写入。而且用 OutputStream 就没有意义了。
  • 他打印错了,他改了process.getOutputStream().write(exitCode)。因为getInputStream() 返回连接到子进程的STDOUT 的只读流。而getOutputStream() 返回连接到子进程的 STDIN 的流。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多