How to save a shell script's echo output withi

2020-03-31 07:03发布

问题:

I'm working on a Java program that calls several Shell scripts within JUnit tests (hence no output except .'s and E's) that manipulate files and SQL tables and then compares data in said tables to their expected values. Everything works in theory, however I'm encountering a strage bug where one type of test works as expected while the other type fails after a ten minute time-out. I've isolated the problem to be one of the Shell scripts, however I did not write this script and I'm unable to change it in any way. The best way I can troubleshoot this is saving the output of the script in question, which comes from a series of echo calls. Is there a somewhat straightforward/reliable way to save echo output? I've googled a bit but nothing's come up. I haven't tried to store the output yet so I don't have an attempt to show you, but the code I've already written that may be relevant is:

//Currently using BufferedWriter, File, FileWriter, IOException, and Writer
import java.io.*;

//Method to write to a log file
public void record(String input) throws IOException {
  writer = new BufferedWriter(new FileWriter(file,true));
  writer.write(input + "\n");
  writer.close();
}

Runtime rt = Runtime.getRuntime();

//Several of these since a lot of file manipulation/script running occurs
process = rt.exec("./shell.sh");
process.waitFor();

In another question I asked, someone recommended not using Runtime.exec() for several reasons. While I realize the advantages to not using exec(), I need to for this version of the program.

The tl;dr question: Can my Java program easily run shell scripts as well as save their echo'd output? If not, is there a tail -f equivalent for reading the output?

回答1:

To do this as painlessly as possible you should really use Asyncronous reading and writing of the output of the external process. That is what is probably blocking and causing the time outs, is the way the script is echoing it's contents back, and they are not being consumed.

I posted an answer to this exact same question a while ago, this works in all situations when reading from external processes, and is the why of why not to use Process.exec() anymore and use ProcessBuilder.



回答2:

How about use write a new script file, say scriptWithOutput.sh, to redirect the echoes to a log file

#!/bin/sh

log="someDir/someLog.log"

# This saves all you "echoes" to the log file
exec &> $log

# Your shell script
./shell.sh

And then in your Java code

process = rt.exec("./scriptWithOutput.sh");

Then try to read the someDir/someLog.log from Java?