0


我试图使用 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 是由于分段错误,可能导致它失败。有什么建议吗?

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

4

2 回答 2

1

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

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

我会尝试将退出代码设置为 null,然后从执行的响应中自己检查 exitValue。我预计问题是您的 ByteArrayOutputStream 正在从异常中截断,击败标准输出,而不是完全刷新内容。

于 2012-11-26T20:05:47.173 回答
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());
于 2012-11-19T11:31:15.273 回答