麻烦使用Apache Commons exec

时间:2012-11-19 11:27:29

标签: java apache-commons-exec


我尝试使用Apache commons来运行脚本,从终端运行的脚本看起来输出类似于以下内容的数据 -
编辑 - 编辑按照建议引入waitFor。

$./old-regress.sh


End with '*' as postcode !

            postcode:                 city:               street:         house number:              country:                 name:                  PDC: 
postcode           :      
city               : 
street             : 
house_num          : 
routing_code       : 
post_freight_centre: 
ic_c_err_code      : 0260
post_code_err_code : ----
city_error_code    : g---
street_error_code  : ---f
local_gov_number 1 : 
local_gov_number 2 : 
State              : 
admin. district    : 
district           : 
local gov. unit    : 
routing_code       : 
error_text_address : 
./old-regress.sh: line 2:  9722 Segmentation fault      ./ictest < /tmp/tmp_inp_file

预期分段错误就是二进制ictest(第三方)的工作方式。

现在,当我尝试使用Apache Commons exec通过我的应用程序执行相同的脚本时,它似乎只是打印错误而不是输出。 我尝试运行脚本的代码片段如下 -

public class Test {
public String execToString(String command) throws Exception {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    CommandLine commandline = CommandLine.parse(command);
    DefaultExecutor exec = new DefaultExecutor();
    exec.setWorkingDirectory(new File("/home/vigna"));
    PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
    exec.setStreamHandler(streamHandler);
    exec.setExitValue(139);
    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
    exec.execute(commandline,resultHandler);
    resultHandler.waitFor();
    return(outputStream.toString());
}
public static void main(String[] argv) throws Exception {
    Test test = new Test();
    System.out.println(test.execToString("./old-regress.sh"));
}

上述代码段返回的输出如下 -

./old-regress.sh: line 2: 15981 Segmentation fault      ./ictest < /tmp/tmp_inp_file

编辑2 - 我尝试使用ProcessBuilder。以下是我的代码 -

public class PBTest
{
    public static void main(String[] args) throws Exception
    {
        ProcessBuilder pb = new ProcessBuilder("./old-regress.sh");
        pb.directory(new File("/home/xxx/"));
        Process p = pb.start();
        String output = loadStream(p.getInputStream());
        String error  = loadStream(p.getErrorStream());
        int rc = p.waitFor();
        System.out.println("Process ended with rc=" + rc);
        System.out.println("\nStandard Output:\n");
        System.out.println(output);
        System.out.println("\nStandard Error:\n");
        System.out.println(error);
    }
    private static String loadStream(InputStream s) throws Exception
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(s));
        StringBuilder sb = new StringBuilder();
        String line;
        while((line=br.readLine()) != null)
            sb.append(line).append("\n");
        return sb.toString();
    }
}

使用ProcessBuilder的结果如下 -

Process ended with rc=139
Standard Output:


Standard Error:

./old-regress.sh: line 2:  3975 Segmentation fault      ./ictest < /tmp/tmp_inp_file

我认为139是因为分段错误而可能导致它失败。有什么建议吗?

任何关于我在这里做错了什么的指针?我如何捕获输出?

2 个答案:

答案 0 :(得分:1)

我建议使用org.apache.commons.exec.LogOutputStream而不是ByteArrayOutputStream。单个参数PumpStreamHandler构造函数捕获stdout和stderr - 所以你很擅长。创建LogOutputStream实例,并将其作为单个参数传递给PumpStreamHandler(就像您是BAOS一样)。

由于您只是在Handler上调用waitFor(),只需在DefaultExecutor上使用同步执行方法:int exitValue = exec.execute(commandline)

我会尝试将退出代码设置为null,然后从执行的响应中自己检查exitValue。我希望问题是你的ByteArrayOutputStream会从异常中截断,击败stdout,而不是完全刷新内容。

答案 1 :(得分:0)

你在做。

exec.execute(commandline);
// gives the program no time to start or run.
return(outputStream.toString());

你应该做一些像

这样的事情
exec.execute(commandline).waitFor();    
// get the output only after the program has finished.
return(outputStream.toString());