Reputation: 2716
I have the below code that is sorting contents of my file based on timestamp but it's not working. If I pass the unix command directly, ie cat /var/test/mylog/output.txt | sort -n
, it works perfectly but it won't execute in my Java code.
private void writeResponseEntityToFile(List<String> response) throws IOException, InterruptedException {
Path out = Paths.get("/var/log/logstream/output.txt");
Files.write(out, response, Charset.defaultCharset());
Process process = Runtime.getRuntime().exec("cat /var/test/mylog/output.txt | sort -n");
process.waitFor();
}
Upvotes: 1
Views: 797
Reputation: 15196
You cannot run a SHELL command from Java, you need either to run bash
subprocess before cat | sort
as indicated by @k314159 or change your command to regular executable (assuming sort is on your path):
sort -n /var/test/mylog/output.txt
Note: you must handle stdout + stderr streams before process.waitFor()
as this can lead to the process freezing when the output of either stream is unread and exceeds the default buffer size. Streams are easier to control with ProcessBuilder
, you can redirect to file(s), or merge stderr to stdout (thus avoiding need for background thread reader) as in this example:
ProcessBuilder pb = new ProcessBuilder(new String[]{"sort","-n", "/var/test/mylog/output.txt"});
pb.redirectErrorStream(true);
Process process = pb.start();
process.getInputStream().transferTo(System.out);
int rc = process.waitFor();
if (rc != 0)
throw new RuntimeException("Sort failed rc="+rc);
Upvotes: 1
Reputation: 11266
This is because Runtime.exec
executes the given file (cat
) directly, without using the shell. When you type cat /var/test/mylog/output.txt | sort -n
into the shell, it is the shell that does the piping, i.e. it creates a pipe, executes cat /var/test/mylog/output.txt
sending its output to the pipe, and concurrently also executes sort -n
, giving it the pipe output as its input. You can execute a shell command like that from Java's Runtime
by executing bash
or a similar shell. You should use the form of exec
that takes an array of String, and pass the command bash
as the first argument:
Process process = Runtime.getRuntime().exec(
new String[]{"bash", "-c", "cat /var/test/mylog/output.txt | sort -n"});
The next thing to do is to think about what you want to do with the output of that command. Use Process.getInputStream()
for that; e.g.
Process process = Runtime.getRuntime().exec(
new String[]{"bash", "-c", "cat /var/test/mylog/output.txt | sort -n"});
if (process.waitFor() != 0) {
System.err.println("Something went wrong")
} else {
String output = new String(process.getInputStream().readAllBytes())
...
}
Upvotes: 1