Runtime.getRuntime().exec returns empty string - java

This is the code I use:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd /C cd C:/Users/ASUS/Desktop/semantics/semantics/bin");
process = runtime.exec("java test \"abc\" \"def\"");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = "", tmp;
while ((tmp = br.readLine()) != null) {
line += tmp;
}
System.out.println(line);
I tried to use commands such as "cmd /C dir" and i got a proper return value.
And this is my test application :
import semantics.Compare;
public class USAGE {
public static void main(String[] args) {
String a = args[0];
String b = args[1];
Compare c = new Compare(a,b);
System.out.println(c.getResult());
}
}

To set the working directory of a process you start with Runtime.exec, use the version that takes File as one of the parameters.
The working directory is private to the process, it cannot be changed by running a "cd" command in a different process.

Related

How to open a program in CMD and interact with it with Java

I am able to open some program, that can get instructions from cmd to do some stuff, like opening file with certain arguments, check if it's ready, etc...
That's how I open file through Java.
final String location = "C:\\Program";
final File dir = new File(location);
String cmd = "cmd.exe /c start my-program.exe";
Process process = Runtime.getRuntime().exec(cmd, null , dir);
How do I interact with it now, send commands like "check_status" or "do_some_stuff" and get it's output to Java.
If I try this:
String [] cmd = {"cmd.exe /c start my-program.exe", "do_stuff"};
Process process = Runtime.getRuntime().exec(cmd, null , dir);
I get error: "Cannot run program "cmd.exe /c start my-program.exe.exe" (in directory "C:\Program"): CreateProcess error=2, The system cannot find the file specified"
But it does finds file when I send single String as an argument.
I understand that I can get it's output to Java this way:
java.io.InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
EDIT: Solved by using getOutputStream.
Writer w = new OutputStreamWriter(process.getOutputStream());
w.write("custom_command");
w.close();
I started Wildfly server with standalone.bat file(similar .exe file)
public static void main(String[] args) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "cd D:\\Users\\turack\\Downloads\\wildfly-16.0.0.Final\\bin\\ && standalone.bat");
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while (true) {
line = bufferedReader.readLine();
if (line == null) { break; }
System.out.println(line);
}
bufferedReader.close();
}
Solved by using getOutputStream.
Writer w = new OutputStreamWriter(process.getOutputStream());
w.write("custom_command");
w.close();

Java runtime's .exec() wont open executable

I am trying to execute another file using Runtime and Process
try
{
Runtime run = Runtime.getRuntime();
Process pro = run.exec("C:\\Users\\user\\Desktop\\file.exe");
}
catch(Exception a)
{
a.printStackTrace();
}
I can enter this command in either run or cmd and am able to open the file but running it through my program it won't open. There are no errors, it just doesn't open.
To better understand what is going on (and it is actually a requirement of the Process class), you need to redirect the input and error streams of your process - and using a ProcessBuilder is the recommended way to start processes:
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("C:\\Users\\user\\Desktop\\file.exe");
runProcess(pb)
}
private static void runProcess(ProcessBuilder pb) throws IOException {
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
You must do
Process pro = run.exec("C:\\Users\\user\\Desktop\\file.exe",null,"C:\\Users\\user\\Desktop\\");
Please see Run .exe file from Java from file location
Try this way:
String []cmdarray = new String[4];
cmdarray[0] = "cmd";
cmdarray[1] = "/c";
cmdarray[2] = "start";
cmdarray[3] = "C:\\Users\\user\\Desktop\\file.exe";
Runtime.getRuntime().exec(cmdarray);
Try this one, create a batch file ,like start_file.bat.
The content like this:
cd C:\Users\user\Desktop ----- Goto this directory
C: ----- This line is very important
file.exe
Both the two approaches work well.
Runtime r = Runtime.getRuntime();
String []cmdarray = new String[4];
cmdarray[0] = "cmd";
cmdarray[1] = "/c";
cmdarray[2] = "start";
cmdarray[3] = "C:/users/desktop/start_file.bat";
r.exec(cmdarray);
And this one:
r.exec("C:/users/desktop/start_file.bat");
You can read the output from this new process.

put the output of the shell script into a variable in a Java program

Is there a way to get an output from a shell script program into a variable in Java program(not into the output file). The output of my shell script is the database query execution time and I need to assign that time value to a Java variable. (I am calling that shell script from Java program). And then I will need to do some other calculations on those values in Java.
Update to old question
Since Java 7 there is a new class which can easily deal with OS procecces: ProcessBuilder
.Let's assume we need to store the output of ip_conf.bat into a java String. Contents of c:\tmp\ip_conf.bat
#echo off
REM will go to standard output
ipconfig
REM will go to stadnard error
hey there!
You can read the input streams connected to the standard and error outputs of the subprocess:
ProcessBuilder pb = new ProcessBuilder("C:\\tmp\\ip_conf.bat");
Process p = pb.start();
String pOut = "";
try (InputStream stdOut = p.getInputStream();
BufferedInputStream bufferedStdOut = new BufferedInputStream(stdOut);
ByteArrayOutputStream result = new ByteArrayOutputStream()) {
int bytes = 0;
while ((bytes = bufferedStdOut.read()) != -1) {
result.write(bytes);
}
pOut = result.toString(Charset.defaultCharset().toString());
}
System.out.println(pOut);
InputStream stdErr = p.getErrorStream();
// same with the error stream ...
int exit = p.waitFor();
System.out.println("Subprocess exited with " + exit);
Below is the program that will help you store the full output of any script or any command into String object.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String output = obj.executeCommand("sh /opt/yourScriptLocation/Script.sh");
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();
}
}
I just google it and there is a nice tutorial, full of examples here : http://www.mkyong.com/java/how-to-execute-shell-command-from-java/
I know people prefere copy/paste but let's respect other people's work and go on their website :p

read the output from java exec

Hello i have some question about java.
here is my code:
public static void main(String[] args) throws Exception {
Process pr = Runtime.getRuntime().exec("java -version");
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
pr.waitFor();
System.out.println("ok!");
in.close();
System.exit(0);
}
in that code i'am trying to get a java version command execute is ok, but i can't read the output it just return null. Why?
Use getErrorStream().
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
EDIT:
You can use ProcessBuilder (and also read the documentation)
ProcessBuilder ps=new ProcessBuilder("java.exe","-version");
//From the DOC: Initially, this property is false, meaning that the
//standard output and error output of a subprocess are sent to two
//separate streams
ps.redirectErrorStream(true);
Process pr = ps.start();
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
pr.waitFor();
System.out.println("ok!");
in.close();
System.exit(0);
Note that we're reading the process output line by line into our StringBuilder. Due to the try-with-resources statement we don't need to close the stream manually. The ProcessBuilder class let's us submit the program name and the number of arguments to its constructor.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ProcessOutputExample
{
public static void main(String[] arguments) throws IOException,
InterruptedException
{
System.out.println(getProcessOutput());
}
public static String getProcessOutput() throws IOException, InterruptedException
{
ProcessBuilder processBuilder = new ProcessBuilder("java",
"-version");
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
StringBuilder processOutput = new StringBuilder();
try (BufferedReader processOutputReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));)
{
String readLine;
while ((readLine = processOutputReader.readLine()) != null)
{
processOutput.append(readLine + System.lineSeparator());
}
process.waitFor();
}
return processOutput.toString().trim();
}
}
Prints:
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
You already have the process-object (name pr). You can get the Input-, Output- and Errorstream. In your case you want pr.getInputStream(). Read from that, that is connected to the output of the process.
try this
public static final Pair<Integer,Integer> javaVersion(File file) throws IOException {
final ProcessBuilder pb = new ProcessBuilder("java", "-version");
pb.directory(new File(file.getCanonicalPath() + File.separator + "bin"));
pb.redirectErrorStream(true);
// Call the test target
final Process process = pb.start();
final InputStream in = process.getInputStream();
final InputStream err = process.getErrorStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
String s = bufferedReader.readLine();
int start = s.indexOf('\"');
int end = s.lastIndexOf('\"');
String substring = s.substring(start + 1, end);
String[] split = substring.split("\\.");
return new Pair<>(Integer.parseInt(split[0]),Integer.parseInt(split[1]));
}
I also suffered this issue because I didn't set $JAVA_HOME correctly. (I forgot Contents/Home).
After I edit $JAVA_HOME, update Gradle JVM, and remove .idea directory to re-build with gradle, It works well.

Java Runtime.getRuntime(): getting output from executing a command line program

I'm using the runtime to run command prompt commands from my Java program. However, I'm not aware of how I can get the output the command returns.
Here is my code:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send" , argument};
Process proc = rt.exec(commands);
I tried doing System.out.println(proc); but that did not return anything. The execution of that command should return two numbers separated by a semicolon. How could I get this in a variable to print out?
Here is the code I'm using now:
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);
InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ((line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
But I'm not getting anything as my output, but when I run that command myself it works fine.
Here is the way to go:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// Read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// Read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
Read the Javadoc for more details here. ProcessBuilder would be a good choice to use.
A quicker way is this:
public static String execCmd(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
Which is basically a condensed version of this:
public static String execCmd(String cmd) throws java.io.IOException {
Process proc = Runtime.getRuntime().exec(cmd);
java.io.InputStream is = proc.getInputStream();
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
String val = "";
if (s.hasNext()) {
val = s.next();
}
else {
val = "";
}
return val;
}
I know this question is old but I am posting this answer because I think this may be quicker.
Edit (For Java 7 and above)
Need to close Streams and Scanners. Using AutoCloseable for neat code:
public static String execCmd(String cmd) {
String result = null;
try (InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
Scanner s = new Scanner(inputStream).useDelimiter("\\A")) {
result = s.hasNext() ? s.next() : null;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
If use are already have Apache commons-io available on the classpath, you may use:
Process p = new ProcessBuilder("cat", "/etc/something").start();
String stderr = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset());
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
At the time of this writing, all other answers that include code may result in deadlocks.
Processes have a limited buffer for stdout and stderr output. If you don't listen to them concurrently, one of them will fill up while you are trying reading the other. For example, you could be waiting to read from stdout while the process is waiting to write to stderr. You cannot read from the stdout buffer because it is empty and the process cannot write to the stderr buffer because it is full. You are each waiting on each other forever.
Here is a possible way to read the output of a process without a risk of deadlocks:
public final class Processes
{
private static final String NEWLINE = System.getProperty("line.separator");
/**
* #param command the command to run
* #return the output of the command
* #throws IOException if an I/O error occurs
*/
public static String run(String... command) throws IOException
{
ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
Process process = pb.start();
StringBuilder result = new StringBuilder(80);
try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())))
{
while (true)
{
String line = in.readLine();
if (line == null)
break;
result.append(line).append(NEWLINE);
}
}
return result.toString();
}
/**
* Prevent construction.
*/
private Processes()
{
}
}
The key is to use ProcessBuilder.redirectErrorStream(true) which will redirect stderr into the stdout stream. This allows you to read a single stream without having to alternate between stdout and stderr. If you want to implement this manually, you will have to consume the streams in two different threads to make sure you never block.
Also we can use streams for obtain command output:
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
String[] commands = {"free", "-h"};
Process process = runtime.exec(commands);
BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
lineReader.lines().forEach(System.out::println);
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
errorReader.lines().forEach(System.out::println);
}
#Senthil and #Arend answer (https://stackoverflow.com/a/5711150/2268559) mentioned ProcessBuilder. Here is the example using ProcessBuilder with specifying environment variables and working folder for the command:
ProcessBuilder pb = new ProcessBuilder("ls", "-a", "-l");
Map<String, String> env = pb.environment();
// If you want clean environment, call env.clear() first
//env.clear();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
File workingFolder = new File("/home/user");
pb.directory(workingFolder);
Process proc = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// Read the output from the command:
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null)
System.out.println(s);
// Read any errors from the attempted command:
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null)
System.out.println(s);
Create class :
public class Utils {
public static final String SHEL_EXECUTE_ERROR = "SHEL_EXECUTE_ERROR";
public static String shellExec(String cmdCommand) {
final StringBuilder stringBuilder = new StringBuilder();
try {
final Process process = Runtime.getRuntime().exec(cmdCommand);
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
} catch (Exception e) {
return SHEL_EXECUTE_ERROR;
}
return stringBuilder.toString();
}
}
and use:
final String shellExec = shellExec("cmd /c ver");
final String versionOS = shellExec.equals(SHEL_EXECUTE_ERROR) ? "empty" : shellExec;
If you write on Kotlin, you can use:
val firstProcess = ProcessBuilder("echo","hello world").start()
val firstError = firstProcess.errorStream.readBytes().decodeToString()
val firstResult = firstProcess.inputStream.readBytes().decodeToString()
Adapted from the previous answer:
public static String execCmdSync(String cmd, CmdExecResult callback) throws java.io.IOException, InterruptedException {
RLog.i(TAG, "Running command:", cmd);
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
//String[] commands = {"system.exe", "-get t"};
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
StringBuffer stdOut = new StringBuffer();
StringBuffer errOut = new StringBuffer();
// Read the output from the command:
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
stdOut.append(s);
}
// Read any errors from the attempted command:
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
errOut.append(s);
}
if (callback == null) {
return stdInput.toString();
}
int exitVal = proc.waitFor();
callback.onComplete(exitVal == 0, exitVal, errOut.toString(), stdOut.toString(), cmd);
return stdInput.toString();
}
public interface CmdExecResult{
void onComplete(boolean success, int exitVal, String error, String output, String originalCmd);
}
Pretty much the same as other snippets on this page but just organizing things up over an function, here we go...
String str=shell_exec("ls -l");
The Class function:
public String shell_exec(String cmd)
{
String o=null;
try
{
Process p=Runtime.getRuntime().exec(cmd);
BufferedReader b=new BufferedReader(new InputStreamReader(p.getInputStream()));
String r;
while((r=b.readLine())!=null)o+=r;
}catch(Exception e){o="error";}
return o;
}
Process p = Runtime.getRuntime().exec("ping google.com");
p.getInputStream().transferTo(System.out);
p.getErrorStream().transferTo(System.out);
Try reading the InputStream of the runtime:
Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-send", argument};
Process proc = rt.exec(commands);
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
You might also need to read the error stream (proc.getErrorStream()) if the process is printing error output. You can redirect the error stream to the input stream if you use ProcessBuilder.

Categories

Resources