我有一个在外部进程中运行shell脚本的Thread,我使用Apache的IOUtils来读取来自此外部进程的stderr和stdout流,如下所示:
Thread t = new Thread(()-> {
ProcessBuilder pb = new ProcessBuilder("sh");
Process p = null;
try {
p = pb.start();
OutputStream os = p.getOutputStream();
os.write("sleep 30 ; echo test".getBytes());
os.flush();
os.close();
InputStream is = p.getInputStream();
InputStream es = p.getErrorStream();
String stdout = IOUtils.toString(is,"UTF-8");
String stderr = IOUtils.toString(es,"UTF-8");
int retval = p.waitFor();
} catch (Exception e) {
System.out.println("Got exception: "+e.toString());
} finally {
System.out.println("Done now!");
}
});
t.start();
Thread.sleep(7000);
t.interrupt();
出于某种原因,当我运行此测试用例时,永远不会抛出异常(catch
块永远不会运行),finally
块永远不会运行。我有什么问题没有抓到吗?是否应该通过不同的线程收集stdout和stderr?
答案 0 :(得分:3)
如果stderr的缓冲区填满你的程序将停止。除非你需要它们在不同的字符串中,否则我会将它们重定向到另一个字符串。
我会使用ProcessBuidler.redirectErrorStream来组合输出,因此您不需要额外的线程来阅读stderr
waitFor(long, TimeUnit)超时,因此您无需启动后台主题。
我建议你打印出你的stderr和stdout,这样你就可以看到它们,因为它们可能表明出了什么问题。
答案 1 :(得分:1)
看起来正确,除了线程在处理来自shell的任何输出之前被杀死(中断)的事实。问题是shell会休眠30秒,线程会在7秒内中断。
您可能无法看到来自catch或finally块的任何消息,这可能是因为{" shell"之前的main()
方法退出程序。线程实际上已激活。