我一直在尝试通过Java运行Perl脚本。我甚至发现脚本是如何做到的,但问题是我希望Perl抛出的异常在Java中返回。
import java.io.IOException;
public class Log {
public static void main(String[] args) throws IOException {
Process proc = null;
try
{
proc = Runtime.getRuntime().exec("perl C:\\Users\\myscript.pl");
int returncode = proc.exitValue();
System.out.println("Process Executed"+returncode);
}catch(Exception ae)
{
System.out.println("Exception is "+ae.toString());
}
finally
{
proc.destroy();
}
}
}
当我尝试运行此代码时,我收到的异常是:
Exception is java.lang.IllegalThreadStateException: process has not exited
有人可以帮助我吗?我做错了什么?
答案 0 :(得分:2)
您需要在exitValue()之前调用Process.waitFor()。另外,我强烈建议您阅读When Runtime.exec() won't,它有更多有用的信息,可以更加健壮地调用外部流程。
proc.waitFor(); // <======= blocks until process exit
int returncode = proc.exitValue();
System.out.println("Process Executed"+returncode)
的文档
如果需要,导致当前线程等待,直到进程 由此Process对象表示已终止。此方法返回 如果子进程已经终止,则立即执行。如果 子进程尚未终止,调用线程将被阻塞 直到子进程退出。
答案 1 :(得分:1)
每当您运行子进程时,需要确保以下两点:
a)父进程应监视子进程。 b)父进程应该等待子进程完成以检查其状态。
要实现第一个目标,您应该强制承诺同时使用子进程输出流和错误流。除此之外,父进程需要等待子进程在获取其退出代码之前完成其执行。
要使用输出和错误流,您可以创建一个可以同时读取这两个流的runnable,并将输出记录到文件中。
class StreamConsumer implements Runnable
{
private InputStream is;
private String outputFile;
StreamConsumer(InputStream is, String outputFile)
{
this.is = is;
this.outputFile = outputFile;
}
public void run()
{
InputStreamReader isr = null;
BufferedReader br = null;
FileOutputStream fos = null;
BufferedWriter bufferedWriter = null;
char[] characterBuffer = null;
try
{
characterBuffer = new char[1024];
isr = new InputStreamReader(is,"UTF-8");
br = new BufferedReader(isr);
fos = new FileOutputStream(outputFile);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos,"UTF-8"));
LOGGER.info("Writing to op file: "+ this.outputFile);
int readCharacters = -1;
while ((readCharacters = br.read(characterBuffer,0,1024)) != -1)
{
String sw = new String(characterBuffer,0,readCharacters);
/*
* To ignore empty chunks
*/
if(sw != null && sw.trim().length() > 0)
{
bufferedWriter.write(sw.toString());
}
characterBuffer = new char[1024];
}
LOGGER.info("Done Writing to op file: "+ this.outputFile);
}
catch (Exception ioe)
{
LOGGER.error("IOException ", ioe);
}
finally
{
if(br != null)
{
try {
br.close();
} catch (IOException e) {
LOGGER.error("IOException ", e);
}
}
if(bufferedWriter != null)
{
try {
bufferedWriter.close();
} catch (IOException e) {
LOGGER.error("IOException ", e);
}
}
}
}
}
消费使用:
StreamConsumer errorStreamConsumer = new StreamConsumer(proc.getErrorStream(),"errorfilepath");
StreamConsumer outputStreamConsumer = new StreamConsumer(proc.getInputStream(),"outputFilepath");
执行上述操作将确保子进程永不挂起并由父进程有效监视。
另见:
Process.waitFor(), threads, and InputStreams http://www.javaworld.com/article/2071275/core-javahen-runtime-exec---won-t/core-java/when-runtime-exec---won-t.html
要实现第二个,父进程需要等待子进程完成其执行:
proc.waitFor();
导致当前线程在必要时等待,直到进程 由此Process对象表示已终止。此方法返回 如果子进程已经终止,则立即执行。如果 子进程尚未终止,调用线程将被阻塞 直到子进程退出。
在您请求子进程返回代码之前,这是必需的。
int returncode = proc.exitValue();