import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String className = "str.java";
String command = "javac " + className;
String output = obj.executeCommand(command);
System.out.println(output);// prints the output of the executed command
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
I am trying to compile a Java file (str.java) from another Java class(ExecuteShellComand.java). What I am trying to do is if "str.java" compiles successfully then I want to execute "java str" command, but if the compilation fails then proper stacktrace or errors should be printed. I am storing the stacktrace or the errors in output variable.
But when I execute this code although "str.java" has somes errors in it System.out.println(output) is not printing the errors.
If you want to capture the errors from a command then you shall capture error stream instead of Input stream
So replace
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
with
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
The Process class tries to mimetize OS process. It means, process keep different output stream for error and normal messages and one stream for input. In UNIX, should be:
wc < file > wc.count 2> wc.error
In Java...
abstract InputStream getErrorStream()
Gets the error stream of the subprocess.
abstract InputStream getInputStream()
Gets the input stream of the subprocess.
abstract OutputStream getOutputStream()
So, you should use getErrorStream() to get errors..
Refactoring your code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String className = "str.java";
String command = "javac " + className;
obj.executeCommand(command);
System.out.println(obj.output);
System.out.println(obj.errors);
}
private String errors;
private String output;
private void executeCommand(String command) {
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
errors = readStream(p.getErrorStream());
output = readStream(p.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
private String readStream(InputStream inputStream) throws IOException {
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
return output.toString();
}
}
Related
I am trying to read a file and then take the contents of that file and have it executed as user input. I am using Scanner for reading files and user input but I am not sure if this is the correct way to go about this since Scanner for input can only System.in and so I am not sure how to pass data from file into input scanner for it to execute in the console. This is my code below for reading class
public class readingFile {
Scanner fileReading = new Scanner(new File("somecontent.txt"));
Scanner input = new Scanner(System.in);
public readingFile() throws FileNotFoundException {
}
public void startReading()
{
System.out.println("reading file...");
while(fileReading.hasNextLine()){
String data = fileReading.nextLine();
System.out.println(data);
Scanner input = new Scanner(System.in);
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class readingFile {
static String javaFileFullPath = "D://myfolder/Program.java";
public static void main(String[] args) {
executeJavaFile();
}
public static void executeJavaFile() {
try {
System.out.println("executing java program from file....");
Process compileProcess = Runtime.getRuntime().exec("cmd /c javac "+javaFileFullPath);
Thread.sleep(5000);
System.out.println(compileProcess.exitValue());
BufferedReader inputReader = new BufferedReader(new InputStreamReader(compileProcess.getInputStream()));
String line = "";
while ((line = inputReader.readLine()) != null) {
System.out.println(line);
}
inputReader.close();
Process runProcess = Runtime.getRuntime().exec("cmd /c java "+javaFileFullPath);
Thread.sleep(5000);
System.out.println(runProcess.exitValue());
BufferedReader inReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
String lineStr = "";
while ((lineStr = inReader.readLine()) != null) {
System.out.println(lineStr);
}
inReader.close();
} catch (Exception ex) {
System.out.println("Exception:"+ex.getMessage());
}
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class readingFile {
static String javaFileFullPath = "D://myfolder/Program.java";
public static void main(String[] args) {
executeJavaFile();
}
public static void executeJavaFile() {
try {
System.out.println("executing java program from file....");
Process compileProcess = Runtime.getRuntime().exec("cmd /c javac "+javaFileFullPath);
Thread.sleep(5000);
System.out.println(compileProcess.exitValue());
BufferedReader inputReader = new BufferedReader(new InputStreamReader(compileProcess.getInputStream()));
String line = "";
while ((line = inputReader.readLine()) != null) {
System.out.println(line);
}
inputReader.close();
Process runProcess = Runtime.getRuntime().exec("cmd /c java "+javaFileFullPath);
Thread.sleep(5000);
System.out.println(runProcess.exitValue());
BufferedReader inReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
String lineStr = "";
while ((lineStr = inReader.readLine()) != null) {
System.out.println(lineStr);
}
inReader.close();
} catch (Exception ex) {
System.out.println("Exception:"+ex.getMessage());
}
}
}
A very simple code running in the debugging mode perfectly but not working after installation of exe, giving no response/result in return. even no errors to trace.
After building a .exe and installing on my PC its happening, very strange.
tried process builder but the same thing, anyway to check/trace it. maybe paths ?
StringBuilder b = new StringBuilder();
Process p = Runtime.getRuntime().exec("wmic diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
Please note: CMD /c before commands also return an empty response in actual env.
An internal windows command with arguments, like "wmic diskdrive ..."
can be executed easily by wrapping it up inside a cmd window.
Here is the working code snippet for running the wmic command encapsulated in a cmd window:
import java.io.*;
public class Wmic {
public static void main(String[] args) {
StringBuilder b = new StringBuilder();
try {
// Initialize a process object to run
// wmic command and its parameters
// inside a cmd window
Process process = Runtime.getRuntime()
.exec("cmd /c C:\\Windows\\System32\\wbem\\WMIC.exe diskdrive get signature");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
b.append(line);
}
} catch (Exception ex) {
b.append(ex.toString());
}
System.out.println("Output: \n" + b.toString());
}
}
Output:
>javac Wmic.java
>java Wmic
Output:
Signature
More information:
https://mkyong.com/java/how-to-execute-shell-command-from-java/
The ProcessBuilder constructor takes a list of strings. When using ProcessBuilder to run a command, I separate all the words in the command into separate strings.
I read the output of the process in a separate thread. And I always wait for the command, that I launched via ProcessBuilder, to terminate.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
public class PrcBldTs {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("wmic","diskdrive","get","signature");
try {
Process proc = pb.start();
StreamGobbler error = new StreamGobbler(proc.getErrorStream());
StreamGobbler output = new StreamGobbler(proc.getInputStream());
Thread stdout = new Thread(output);
Thread stderr = new Thread(error);
stdout.start();
stderr.start();
int result = proc.waitFor();
stdout.join();
stderr.join();
System.out.println("Exit status = " + result);
if (result != 0) {
System.out.println(error.getContents());
}
else {
System.out.println(output.getContents());
}
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
class StreamGobbler implements Runnable {
private BufferedReader reader;
private StringWriter sw;
public StreamGobbler(InputStream is) {
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
sw = new StringWriter();
}
public String getContents() {
return sw.toString();
}
public void run() {
try {
String line = reader.readLine();
while (line != null) {
sw.append(line);
sw.append(System.lineSeparator());
line = reader.readLine();
}
}
catch (IOException xIo) {
throw new RuntimeException(xIo);
}
}
}
Running the above code gave me the following output.
Exit status = 0
Signature
1145609371
I'm trying to run shell script by using ProcessBuilder. The script works but it can't run after the java code. And error stream doesn't output message. I'm running it on centOS 6.9 computer. Please find below my code.
public static ArrayList<String> runCommand(ArrayList<String> command)throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(command);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
ArrayList<String> commandOutput = new ArrayList<>();
String str;
while((str = reader.readLine()) != null) {
commandOutput.add(str);
}
StringBuilder errorBuilder = new StringBuilder();
while((str = errorReader.readLine()) != null) {
errorBuilder.append(str);
}
String errorMessage = errorBuilder.toString();
if(!errorMessage.equals("")) {
String message = LOG_TAG + ",[runCommand] error:" + errorMessage;
System.out.println(message);
}
reader.close();
errorReader.close();
process.destroy();
return commandOutput;
}
In your case, you are reading something from the output stream of the process, till you consume everything. Then, you try to read error stream.
If the process writes some considerable number of characters on the error stream, the other process will block till they are consumed. To consume both error stream and output stream at the same time, you need to use threads.
You may follow the StreamGobbler technique. You may get some details from that page: https://www.javaworld.com/article/2071275/when-runtime-exec---won-t.html?page=2
This is some code influenced from the page:
public class StreamGobbler extends Thread {
private static final String EOL = System.lineSeparator();
private final InputStream inputStream;
private final StringBuilder output = new StringBuilder();
public StreamGobbler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(inputStreamReader);
) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line);
output.append(EOL);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String getOutput() {
return output.toString();
}
}
In your code, you use StreamGobbler like this:
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream());
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream());
process.waitFor();
String commandOutput = outputGobbler.getOutput();
String errorMessage = errorGobbler.getOutput();
process.destroy();
Hi have written code for starting the server.
The code is as given below.
package javacode;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String command = "command to be executed to run the server(Path)";
String output = obj.executeCommand(command);
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
The server has started in background when i run the java code, but i am using the linux command to check weather the server has started.
I want to know what return value is stored in Process object when i run
Process pro=Runtime.getRuntime().exec(command)
You can use process.exitValue() to retrieve the return value of the command you have executed.
Please have also a look at the javadoc: http://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#exitValue--
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println("Command '"+command+"' finished with return code "+p.exitValue());
import java.io.BufferedReader;
import java.io.Console;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
public class logfile
{
public static void main(String[] args) throws FileNotFoundException
{
try
{
String[] commands = {"cmd","/c", "dir/p"};
final File outputFile = Paths.get("c://users//sihi//logfile.txt", args).toFile();
final ProcessBuilder pb =new PrrocessBuilder(commands).redirectOutput(outputFile).redirectErrorStream(true);
final Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String Error;
while ((Error = stdError.readLine()) != null) {
System.out.println(Error);
}
while ((Error = stdInput.readLine()) != null) {
System.out.println(Error);
}
} catch (Exception e) {
e.printStackTrace();
} } }
You use a ProcessBuilder and have already redirected your output to a file:
final File outputFile = Paths.get("c://users//sihi//logfile.txt", args).toFile();
final ProcessBuilder pb = new ProcessBuilder(commands)
.redirectOutput(outputFile).redirectErrorStream(true);
Just read from outputFile...
Also, you use Java 7, so:
for (final String line: Files.readAllLines(yourPath, StandardCharsets.UTF_8))
System.out.println(line);
And since this is Java 7, instead of creating a File for output, create a Path and use .toFile():
final Path path = Paths.get("c://users//sihi//logfile.txt", args);
final ProcessBuilder pb = new ProcessBuilder(commands)
.redirectOutput(path.toFile()).redirectErrorStream(true);
final Process p = pb.start();
p.waitFor(); // throws InterruptedException
for (final String line: Files.readAllLines(path, StandardCharsets.UTF_8))
System.out.println(line);