Fetching errors after running grep command from java - java

I am running grep command via my Java program. Running grep on the command line sometimes writes an error on stderr of the kind: No such file or directory. I want to detect in my Java program whenever this error happens as a result of executing the grep command via the program. How can I achieve this goal of mine? This is what I've written so far:
Runtime rt = Runtime.getRuntime();
String[] cmd = {"/bin/sh", "-c", "grep -c 'Search_String' /path/to/file(s)/being/searched"};
Process proc = rt.exec(cmd);
BufferedReader is = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}

You can detect if the process returned with an error; as #Dakoda mentions, exitValue() won't have the exit value until the process ends, but using waitFor() will block until the process ends and returns the exit value:
int rv = rt.waitFor();
if (rv != 0) { ... }
Error output is usually on stderr rather than stdout, so to read errors you'd use:
BufferedReader is = new BufferedReader(
new InputStreamReader(proc.getErrorStream()));

Related

Sending 'exec' commands to Docker container using Java

I'm trying to send docker commands using Java Runtime.
Commands like docker cp works very nice with the below method as well as typing directly from the terminal.
First problem is that the docker exec command works only from the terminal, not with the Java Runtime. Other docker commands like docker cp works as expected. The only problem is that I can't run commands on the container, like echoing on the container's terminal.
Also the 2nd problem is that the System.out.println(...)method in the below method, doesn't actually print anything.
private static void runCommand() throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec(
new String[]{"/bin/sh",
"-c",
"docker exec -u 0 -it <CONTAINER_NAME> echo", "'abc'"});
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
proc.waitFor();
}
There is no need to run docker inside a shell. You can start the process directly.
As of Java 1.7 you can also use ProcessBuilder.inheritIO() to redirect the standard I/O of the subprocess
Below a working example that prints the output of the echo command:
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("docker", "exec" , "-it", "<CONTAINER_NAME_OR_ID>", "echo", "abc").inheritIO();
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (Exception e) {
e.printStackTrace();
}
Hope this helps.

Difference when executing linux command from terminal and java runtime process

I'm looking a way to write running log of python which is executed by java app via script.
Let's say my script is:
import time
for x in range(120):
print("Running ", x)
time.sleep(1)
Here is my current solution:
Trigger script using java
String cmd = "python script.py";
var process = Runtime.getRuntime().exec(cmd, null, new File(sandboxPath));
Write log to new file:
String traceLogCmd = String.format("strace -p %s -s 9999 -e trace=write -o output.txt", process.pid());
Runtime.getRuntime().exec(traceLogCmd, null, new File(sandboxPath));
Now the problem is output.txt only has content whenever the python script is done executing so that I cannot tailf the output file.
Meanwhile if I execute python script.py and strace command dirrectly from terminal, the output is exactly what I expected.
Can someone correct me if I did something wrong or have a another way to get python log?
Thanks in advance.
Use ProcessBuilder instead of Runtime.exec(). More details: When Runtime.exec() won't
The following code will append to StringBuilder object output of the script sb.append(line);. It would not be difficult to write that content to a file.
Process p = new ProcessBuilder("sh", "-c", "python", "path-to-your-script").start();
String result = getCommandResult(p.getInputStream());
private static String getCommandResult(InputStream stream) throws IOException {
StringBuilder sb = new StringBuilder();
try (InputStreamReader isr = new InputStreamReader(stream);
BufferedReader in = new BufferedReader(isr)) {
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
}
return sb.toString().trim();
}

Run shell script with Angular CLI commands from Java

I'm trying to run a shell script from Java (using Runtime.getRuntime().exec(cmd)). All commands in the script file seem to be running normally except the angular-cli (ng) commands.
My Java File:
System.out.println("Executing Script...");
final String[] cmd = new String[]{"/bin/bash", "test.sh"};
final Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
process.destroy();
System.out.println("Script Executed.");
test.sh:
#!/bin/bash
cd ~/ &&
ng new newAngularProject &&
Outout:
Executing Script...
Script Executed.
No errors are thrown. All other commands work but for some reason, I'm unable to run ng commands. Also, I've tested the file w/o running it from Java - When I run the same script directly on the console, it works perfectly and all commands (including ng commands) work neatly. I'm running on MacOS in case you wanted to know.
Also print the error stream. You will get the error message, if it is there.
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((s = errorReader.readLine()) != null) {
System.out.println("error: " + s);
}
Also you can try to use absolute path of ng in your test.sh e.g. /home/my/install/node-vxxx/ng, since the process spawn by java to run your command might not get the environment variable you set in your .bashrc /.bash_aliases

Why the following code doesn't work? [duplicate]

This question already has answers here:
Runtime's exec() method is not redirecting the output
(2 answers)
Closed 7 years ago.
i'm trying to run shell command in linux via java. most of the commands work, but when i run the following command i get an execption, although it works in the shell:
String command = "cat b.jpg f1.zip > pic2.jpg";
String s = null;
try {
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
i am getting the error in the console:
cat: >: No such file or directory
cat: pic2.jpg: No such file or directory
The problem is the redirection.
cat: >: No such file or directory
The way to interpret this error message:
the program cat is trying to tell you about a problem
the problem is that there is no file named >
Indeed, > is not a file. It's not intended as a file, at all. It's a shell operator to redirect output.
You need to use ProcessBuilder to redirect:
ProcessBuilder builder = new ProcessBuilder("cat", "b.jpg", "f1.zip");
builder.redirectOutput(new File("pic2.jpg"));
Process p = builder.start();
When you run a command it doesn't start a shell like bash unless you do this explicitly. This means you are running cat with four arguments b.jpg f1.zip > pic2.jpg The last two files names don't exist so you get an error.
What you are likely to have intended was the following.
String command = "sh -c 'cat b.jpg f1.zip > pic2.jpg'";
This will run sh which in sees > as a special character which redirects the output.
Because you need to start a shell (e.g. /bin/bash) which will execute your shell command, replace:
String command = "cat b.jpg f1.zip > pic2.jpg";
with
String command = "bash -c 'cat b.jpg f1.zip > pic2.jpg'";

Running Shell Script at the command line

I am running a Shell script using cygwin.
Process p;
InputStream in;
BufferedReader br;
String line;
String cmd;
cmd = "D:/cygwin/bin/bash -c '/bin/test/app.sh" +three_ltr_id+""+mon_code+""+year_code+""+part_no+""+version_no+" '";
System.out.println("EXECUTING: " + cmd);
p = Runtime.getRuntime().exec(cmd);
in = p.getInputStream();
p.waitFor();
br = new BufferedReader(new InputStreamReader(in));
System.out.println("OUT:");
while ((line = br.readLine()) != null) {
System.out.println(line);
System.out.println("SCRIPT EXECUTED PROPERLY");
This is showing EXECUTING and the commands that I passed to script.
If I go inside D:/cygwin/bin/test folder and run the same command it works.
When I run the same command at the command line it won't work.
You need to start reading the input from p.getInputStream() immediately, and keep reading it until there is no more. On Windows, there is little or no buffer in the pipe, and the process will hang once it is filled.
Same is true for the error stream. You could launch threads to read both streams, or there's an option in the way you launch processes to combine regular output and errors, and you can just read them from there.

Categories

Resources