我正在使用Java的ProcessBuilder来启动子进程,这是另一个必须在单独的JVM中运行的Java程序.
我启动两个Threads来从Process读取stdout和stderr流,这样如果流缓冲区已满,就没有挂起.对Process.waitFor的调用返回但流不会终止.
我使用的代码看起来像(命令是字符串列表):
ProcessBuilder pb = new ProcessBuilder(command);
final Process p = pb.start();
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
Thread outputThread = new Thread() {
@Override
public void run() {
try {
IOUtils.copy(p.getInputStream(), outStream);
} catch (IOException e) {
e.printStackTrace();
}
};
};
outputThread.start();
Thread errorThread = new Thread() {
@Override
public void run() {
try {
IOUtils.copy(p.getErrorStream(), errStream);
} catch (IOException e) {
e.printStackTrace();
}
};
};
errorThread.start();
int returncode = p.waitFor();
outputThread.join(); …Run Code Online (Sandbox Code Playgroud) 我在Java应用程序中使用ProcessBuilder创建进程.创建的进程执行一些FFMPEG命令,这些命令实际上将RTSP流复制到指定的目标媒体文件中.
ProcessBuilder builder = new ProcessBuilder("ffmpeg", "-i", RTSP_URL, "-f", fileFormat, destFilePath);
Process processToExecute = builder.start();
Run Code Online (Sandbox Code Playgroud)
我想在完成执行之前关闭该进程.因此,如果我直接在Windows CMD中运行此FFMPEG命令,然后在5秒后按"CTRL + C",则进程get终止,状态为"2".我可以播放到目前为止创建的媒体文件.
所以,如果我在Java应用程序中执行相同的操作:
process.destroy(); //I call this method after 5 sec
Run Code Online (Sandbox Code Playgroud)
我得到状态代码'1',这意味着异常终止.我通过以下方式获得状态:
processToExecute.destroy();
processToExecute.exitValue(); //This return me status '1'
Run Code Online (Sandbox Code Playgroud)
我无法播放媒体文件,我认为这是由于该过程的异常终止.
那么我如何终止使用ProcessBuilder创建的进程,就像我们在CMD中使用(CTRL + C)一样,以便我可以播放创建的媒体文件?
我想在Java应用程序中终止进程(使用ProcessBuilder创建),状态代码为'2',这是我在使用CMD终止进程时获得的.
因此,当我尝试在应用终止后删除该文件时,我收到以下错误:
The Action Can't be Performed Because File is Opened in FFMPEG.exe
Run Code Online (Sandbox Code Playgroud)
这意味着该进程不会终止它正在执行的命令.该命令仍然占用了这个文件,这就是为什么我无法播放它.当我打电话时,进程终止:
processToExecute.destroy();
Run Code Online (Sandbox Code Playgroud)
但是,它正在执行的任务(即执行命令)仍然有效.奇怪!!!!
实际上如果我在进程运行时直接在cmd中按'CTRL + C'或'q',那么它会成功终止进程,并且此进程在当前正在执行的进程列表中不再可见.
并以编程方式调用方法:
cmd> processToExecute.destroy();
Run Code Online (Sandbox Code Playgroud)
它终止了进程,但当我看到当前正在执行的进程列表时,我仍然可以在那里看到它们.
并存在相同的情况如果我尝试使用另一个CMD中的'taskkill'或'kill'命令终止此过程,方法是指定其进程异常终止的名称或pid.
PS我使用以下命令查看正在运行的进程:
tasklist
Run Code Online (Sandbox Code Playgroud)
因此,它证明了来自Application的destroy()方法和来自另一个CMD的'taskkill或kill'命令通常不会按"CTRL + C"和"q"来终止该过程.
我的问题是,JVM 是否共享某种与线程或进程相关的资源,这些资源可能会导致 ProcessBuilder 性能在正常使用一个月或更长时间后出现峰值?对所有应用程序使用 java 6 update 21。
在过去的几个月中,我们注意到数据中心中的单个服务器(运行 Solaris 10 的 Sparc M4000)可以运行大约 6-8 周而不会出现任何问题。然而,使用 ProcessBuilder 类运行脚本的应用程序的性能很快就会受到巨大的影响 - ProcessBuilder.start 有时需要一分钟多的时间才能返回。重新启动后,以及几周后,正常返回时间在 10 秒或可能 100 毫秒范围内。
我编写了一个单独的小应用程序,它创建了 5 个线程,每个线程使用 ProcessBuilder 连续运行“ls”命令 10 次,然后我从中收集统计信息以监控原始问题。该应用程序在每次运行后退出,并且每小时仅从 cron 运行一次。通常只需要一两秒钟。
昨晚,经过 45 天的正常运行时间和正常行为后,每次 ProcessBuilder.start 调用的 ProcessBuilder 时间再次飙升至一分钟多。
顶部显示没有内存或 CPU 占用。我确实尝试在测试应用程序上执行 jstack,但收到错误“无法创建 thread_db 代理”。
有任何想法吗?
我是Windows XP上Eclipse工作的新手程序员,我需要运行多个进程(这将是一个多计算机系统的模拟).我的初始hackup使用多个线程到多个类,但现在我正在尝试用进程替换线程.
从我的阅读中,我发现ProcessBuilder是最佳选择.我已经尝试了下面看到的许多版本的输入,但是在我的生活中无法弄清楚如何正确使用它.我试图运行我以前创建的.java文件作为类(我已修改).我最终只是制作了一个虚拟的test.java,以确保我的进程正常工作 - 它唯一的功能是打印它运行.
我的两个文件的代码如下.我正确使用ProcessBuilder吗?这是读取子进程输出的正确方法吗?任何帮助将非常感激.
编辑:解决方案是声明ProcessBuilder("java.exe"," - cp","bin","Broker.test");
主要过程
package Control;
import java.io.*;
import java.lang.*;
public class runSPARmatch {
/**
* @param args
*/
public static void main(String args[]) {
try {
ProcessBuilder broker = new ProcessBuilder("javac.exe","test.java","src\\Broker\\");
Process runBroker = broker.start();
Reader reader = new InputStreamReader(runBroker.getInputStream());
int ch;
while((ch = reader.read())!= -1)
System.out.println((char)ch);
reader.close();
runBroker.waitFor();
System.out.println("Program complete");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated …Run Code Online (Sandbox Code Playgroud) 我想编写一个运行外部"java myprog <input.txt> output.txt"命令的Java程序.最终目标是在两个不同的程序上运行此命令,并将它们的输出相似性与各自的输出文件进行比较.
我想我已经阅读了关于使用ProcessBuilder运行外部程序的所有相关文章,以及关于在该外部程序中处理用户输入的一些条目,但我仍然无法使其工作.根据我的阅读,我认为最好的方法是不运行上面的确切命令,而是读取input.txt文件并将其逐字节地提供给Process对象,然后收集输出并将其写入输出.txt ...我对其他选项100%开放.
我根据读数将下面的代码放在一起.它似乎正确地将input.txt中的输入提供给myprog,但是当我尝试将外部程序的输出打印到控制台进行验证时,程序会在myprog中预期(惊讶)用户输入的位置挂起.
无论有没有redirectErrorStream(true)行,我都会遇到同样的问题.
我真的希望这是Java,因为我打算与我将比较的程序输出的人共享源代码,他们主要只熟悉Java.
import java.io.*;
import java.util.*;
public class test7 {
public static void main(String args[]) {
try {
// WANT: "java myprog < input.txt > output.txt"
String inputFile = "input.txt";
String outputFile = "output.txt";
ProcessBuilder pb = new ProcessBuilder("java","myprog");
pb.redirectErrorStream(true); // merge stdout, stderr of process
Process p = pb.start();
// write input to the running program
OutputStream pos = p.getOutputStream();
InputStream fis = new FileInputStream(inputFile);
int read = 0;
while ( (read …Run Code Online (Sandbox Code Playgroud) 可能的重复:
ProcessBuilder 重定向输出
下面的代码:
ProcessBuilder pb = new ProcessBuilder(new String[] {"echo", "some text", ">", "test"});
Run Code Online (Sandbox Code Playgroud)
不断返回“ some text > test”。
我究竟做错了什么?
编辑:
这有效
ProcessBuilder pb = new ProcessBuilder(new String[] {"bash", "-c", "echo sometext > test"});
Run Code Online (Sandbox Code Playgroud) 如何让 Java 将ProcessBuilder数据附加到输出文件中?它现在所做的是,每次写入输出文件时,都会删除其中的所有内容,然后写入。
我正在使用 ProcessBuilder 运行 Windows 可执行文件...我需要运行的确切命令是:
"C:\Program Files\CCBU\CCBU.exe" -d"C:\My Data\projects\ccbu\ciccb-report.xls" -tf"C:\Program Files\CCBU\loss-billing-filters.txt"
Run Code Online (Sandbox Code Playgroud)
如果我从命令提示符运行上述命令,它工作正常。
如果我随后将命令和参数发出为 String [] 数组,如以下 StackOverflow 帖子(ProcessBuilder 在命令行中添加额外的引号)所示,则会失败,因为目录路径中的空格以某种方式破坏了 CCBU.exe 可执行文件的参数:
[log-snippet]
2015-08-31 10:39:08,937 [main] INFO rpd.primary - C:\Program Files\CCBU\CCBU.exe
logging to the given report's directory
Configuration file is: ./CCBUConfigFile.txt
Running with the following settings:
Report Filepath: C:\My
Search Terms FilePath: C:\Program
2015-08-31 10:39:08,948 [main] INFO rpd.primary - STDERR:--------------------
2015-08-31 10:39:08,961 [main] INFO rpd.primary -
Warning: parameter Data\projects\ccbu\ciccb-report.xls not recognized. Ignoring
Warning: parameter Files\CCBU\loss-billing-filters.txt not recognized. Ignoring
Error: …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 ProcessBuilder 加载二进制文件,将其保持在加载状态,然后偶尔放入数据并解析输出。
我现在所拥有的抛出一个异常,表示流已关闭。
Process我对 Java 的工作原理有误解吗?我尝试在此处运行的二进制文件接受来自标准输入的输入并将结果打印到标准输出。它应该有效。如果我通过 cmd 手动输入二进制文件,则该行为是预期的,但我想知道为什么在 Java 中调用时这不起作用。
我的代码如下所示:
public class Run {
public static void main(String [] args) throws IOException, InterruptedException{
List<String> cmd = new ArrayList<String>();
cmd.add("/path/to/binary");
cmd.add("/path/to/param.par");
Process process=null;
try {
process = new ProcessBuilder().inheritIO().command(cmd).start();
} catch (IOException e) {
e.printStackTrace();
}
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
writer.write("Hi\\nhow\\nare\\you\\n?\\n\\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
String l=null;
while((l=reader.readLine())!=null){
System.out.println(l);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的例外是这样的:读取参数文件...java.io.IOException:流在 java.lang.ProcessBuilder$NullOutputStream.write(ProcessBuilder.java:433) …
我尝试从 Java 程序切换Runtime.exec(command)到ProcessBuilder执行 ImageMagick 。convert转换的选项是从用户作为字符串传入的,因此我无法轻松地分离参数以将它们单独传递给 的ProcessBuilder构造函数。在(Unix)命令行上运行的实际命令是
convert -colorspace gray -enhance -density 300 in.pdf out.pdf
Run Code Online (Sandbox Code Playgroud)
我怎样才能让它工作:
public class Demo {
public static void main(String[] args) throws IOException, InterruptedException {
String convertOptions = "-colorspace gray -enhance -density 300"; // arguments passed in at runtime
ProcessBuilder bp = new ProcessBuilder(new String []{"convert",convertOptions,"in.pdf","out.pdf"});
Process process = bp.start();
process.waitFor();
}
}
Run Code Online (Sandbox Code Playgroud)
目前,代码只是运行
java ×10
processbuilder ×10
windows ×2
append ×1
ffmpeg ×1
file ×1
kill-process ×1
process ×1
solaris ×1
user-input ×1