I am building a javaFx application I am running a command using java process builder class.
ProcessBuilder builder = new ProcessBuilder(runCommand);
builder.redirectErrorStream(true);
Process process = builder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
I am trying to get the output from the process I have tried two different ways but I am not able to get it.
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
String line1=null;
while ((line1 = reader.readLine()) != null) {
System.out.println(line1);
}
BufferedReader errorred = new BufferedReader (new InputStreamReader(stderr));
while ((line1 = errorred.readLine()) != null) {
System.out.println(line1);
}
I tried also this:
ProcessBuilder builder = new ProcessBuilder(runCommand);
//String outputLogs = new VerboseProcess(new ProcessBuilder(""));
builder.redirectErrorStream(true);
builder.redirectOutput(Redirect.INHERIT);
builder.redirectError(Redirect.INHERIT);
builder.redirectInput(Redirect.INHERIT);
Process process = builder.start();
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
I believe the error is somewhere else. Following snippet is based on your posted code
ProcessBuilder builder = new ProcessBuilder("java.exe", "-version");
builder.redirectErrorStream(true);
Process process = builder.start();
process.waitFor();
int exitValue = process.exitValue();
System.out.println("exitValue = " + exitValue);
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
String line1 = null;
while ((line1 = reader.readLine()) != null) {
System.out.println(line1);
}
BufferedReader errorred = new BufferedReader(new InputStreamReader(stderr));
while ((line1 = errorred.readLine()) != null) {
System.out.println(line1);
}
and produces the following output on the console
exitValue = 0
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
If the command specified in new ProcessBuilder(command...) does not exists or is not in the PATH an IOException is thrown
Cannot run program "...": CreateProcess error=2, The system \
cannot find the file specified
If you don't get any output. Following could be the reason:
the process has not printed anything to stdout/stderr
your runcommand start the process in a background process, e.g. on Linux/OSX command & or on Windows start command.exe
Related
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();
My problem is, after opening cmd from java code, i want user to be able to input like in c++ ms dos applications. When user writes sth such as "dir" or "cd..", i want to execute these codes by java.
The problem is for every command java re-opens cmd again. Also i cannot execute commands. My cmd start code is below ;
final ArrayList<String> commands = new ArrayList<>();
commands.add("cmd.exe");
commands.add("/C");
commands.add("start");
ProcessBuilder pb = new ProcessBuilder(commands);
Process process = pb.start();
Here's some cleaned up code from How to open the command prompt and insert commands using Java?
public static void main(String[] args) {
try {
String ss = null;
Runtime obj = null;
Process p = Runtime.getRuntime().exec("cmd.exe");
//write a command to the output stream
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
writer.write("dir");
writer.flush();
//Get the input and stderror
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 ((ss = stdInput.readLine()) != null) {
System.out.println(ss);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((ss = stdError.readLine()) != null) {
System.out.println(ss);
}
} catch (IOException e) {
System.out.println("FROM CATCH" + e.toString());
}
}
Am calling a p = Runtime.getRuntime().exec(command) on Java 1.8.
The command calls a bash script as follows:
#!/bin/bash
args=("$#")
cat /home/user/Downloads/bigtext.txt | grep ${args[0]}
The above bash script works fine when called with the command line. When called within my Java application using exec() I get no CAT output back. it does not seem to get past p.waitFor(); Where am I going wrong?
If I run a command directly such as "ls -alF" every thing works as expected.
$ java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
String tmp = "/home/user/search "+input;
System.out.println(tmp); // /home/user/search sometextarg
String woa = executeCommand(tmp);
private String executeCommand(String command) {
StringBuilder output = new StringBuilder();
BufferedReader reader = null;
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
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();
}
Your Java process and your script are deadlocked waiting on each other: you are waiting for the process to exit, the process is waiting for you to read the output.
It happens to work for ls -alF and other commands with small outputs because they all fit in the pipe's buffer (64kib on my system).
Just move the p.waitFor() below the while loop, and you'll have more luck:
private String executeCommand(String command) {
StringBuilder output = new StringBuilder();
BufferedReader reader = null;
Process p;
try {
p = Runtime.getRuntime().exec(command);
reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
If you additionally want this to work correctly with values containing spaces and certain other characters, you have to:
Quote "${args[0]}" in your script.
Rewrite your executeCommand to use Runtime.exec(String[]) instead of Runtime.exec(String).
The uploaded Screenshot conatains the start_client.bat file content, viewed in notepad++ editor.
Currently am invoking start_client.bat on local machine it works fine but when the same bat file is invoked on server it pops up a window on server and it needs manual closure after execution. Any way to force bat file execution on server without window poppping up.
private void invokeSeagull(String flag) throws Exception
{
String path="";
if(flag.equals("Start"))
{
path="cmd /c start D:/Seagull/TIB/start_client.bat";
}
if(flag.equals("Stop"))
{
path="cmd /c start D:/Seagull/TIB/stop_client.bat";
}
try {
String line;
Process p = Runtime.getRuntime().exec(path);
p.waitFor();
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception err) {
err.printStackTrace();
}
}
This code snippet should run batch file, of course if you use Windows.
Runtime.getRuntime().exec("cmd /c start {pathToFile}");
As pointed out be ssedano the correct way to execute shell commands in Java is the Process-builder:
// Just the name of an executable is enough
final ProcessBuilder pb = new ProcessBuilder( "test.bat" );
pb.redirectError( Redirect.INHERIT );
pb.redirectOutput( Redirect.INHERIT );
System.out.println( String.format( "***** Running Process %s OUTPUT:", pb.command().toString() ) );
final Process process = pb.start();
process.getOutputStream().close();
final int returnCode = process.waitFor();
System.out.println( "***** Process Exited with Returncode: " + returnCode );
You can just redirect STDERR and STDOUT of the bat-file, so you will get all output in the Server-Output console. And you should close STDIN of the bat-file, so it will exit and not get stuck on the pause command at the end!
You could use the new in Java 7 ProcessBuilder
A simple example:
String[] command = {"CMD", "/C", "dir"};
ProcessBuilder probuilder = new ProcessBuilder(command);
// Set up your work directory
probuilder.directory(new File("c:\\stackoverflow"));
Process process = probuilder.start();
// Read output
try (InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);)
{
String line;
System.out.printf("Output of running %s is:\n", Arrays.toString(command));
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
// Wait to get exit value
int exitValue = process.waitFor();
}
catch (Exception e)
{
// Fail
}
This should run in the silent mode :
Runtime.getRuntime().exec(new String[] {"cmd", "/pathto/start_client.bat"});
We are trying to call a Powershell script via Java but it hangs when we try to read the output of that script. It hangs on "input.readLine()"
Here is a code we have tried:
String command = "cmd /c powershell C:\\_checkouts\\TestPowerShell\\passwordExpirationTime.ps1";
Process p = Runtime.getRuntime().exec(command);
new InputStreamReader(p.getInputStream());
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();;
for (String line = input.readLine(); line != null; line = input.readLine()) {
stringBuilder.append(line);
}
input.close();
String msg = stringBuilder.toString();
System.out.println("msg: " + msg);
We tried looking at this solution Java program hangs when trying to invoke powershell script
but none of those suggestions worked for us.
We also tried it without cmd /c and with cmd /k. We really want this as a generic class where any script could be called. i.e. BAT, BASH, SH, Powershell, etc.
Any ideas?
Thanks to the answer below here is the code that worked:
try{
final ProcessBuilder pb = new ProcessBuilder("powershell","C:\\psFile.ps1");
pb.redirectInput(Redirect.from(new File("NUL")));
final Process p = pb.start();
final int retcode = p.waitFor();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}catch (Exception e){
e.printStackTrace();
}
Here's some additional information. Our powershell was returning an error because it was restricted. That is why we needed all the Redirect to NUL. Once we fixed that and it wasn't returning an error we were able to simplify our code to this:
try{
final ProcessBuilder pb;
pb = new ProcessBuilder(args);
final Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}catch (Exception e){
e.printStackTrace();
}
Use a ProcessBuilder. Any process implying a modicum of I/O should outright refuse to run via Runtime.exec(), alas, it cannot detect that. And Oracle hasn't flagged it as #Deprecated which is a pity.
Anyway:
final File logFile = new File("/path/to/logfile");
final ProcessBuilder pb = new ProcessBuilder("powershell", "/path/to/the/ps1");
pb.redirectOutput(Redirect.to(logFile));
pb.redirectErrorStream(true);
final Process p = pb.start();
final int retcode = p.waitFor();
// deal with retcode
// read result from the log file