Say I have a function like this :
public String runCommand(parameters, boolean interactive)
{
Process p = null;
// some code
try
{
final ProcessBuilder pb = new ProcessBuilder(my_command);
pb.inheritIO(); // So the output is displayed on the console
p = pb.start();
p.waitFor();
}
catch( IOException | InterruptedException e )
{
e.printStackTrace();
}
if (interactive )
{
return p.exitValue() + "";
}
else
{
// return the stdout of the process p
}
}
What I'm trying to do is to return the standard output of the process I'm running through ProcessBuilder, only if the interactive boolean is set to false. However, I cannot figure how to redirect the standard output to a variable with ProcessBuilder. Please not that I used inheritIO() so when I use a function like adb shell, the shell is displayed in my console, which is the behaviour I want. So basically, as for now, I can see the standard output in the console, but I don't know how to return it in the function so I can use this value as a variable for future stuff.
try this
Process p = new ProcessBuilder(cmd).start();
Reader rdr = new InputStreamReader(p.getInputStream());
StringBuilder sb = new StringBuilder();
for(int i; (i = rdr.read()) !=-1;) {
sb.append((char)i);
}
String var = sb.toString();
What you can do is getting the output as and when the execution, like this:
pb.redirectErrorStream(true);
Process p;
try {
p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
String output = "";
while((line = in.readLine()) != null) {
log.info(line);
output += line + "\n";
}
return output;
} catch (IOException e) {
// ...
}
return null;
Related
I call the.py file in a basic java project and it takes about 30 seconds to run.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
Process proc;
String line ="";
BufferedReader in;
try {
proc = Runtime.getRuntime().exec("D:\\anaconda\\python.exe " +
"D:/2017/Python/pythonProject8/main.py " +
"D:\\2017\\Python\\pythonProject8\\flower1.jpg");
proc.waitFor();
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
result:
enter image description here
But this code is skipped when I use spring-boot.
#GetMapping("test")
public String test(){
System.out.println(1);
Process proc;
String line = "";
String result = "";
try {
proc = Runtime.getRuntime().exec("D:\\anaconda\\python.exe " +
"D:/2017/Python/pythonProject8/main.py " +
"D:\\2017\\Python\\pythonProject8\\flower3.jpg");// 执行py文件
proc.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line);
result += line;
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(2);
return result;
}
result:
enter image description here
I want to know how to run spring-boot properly.
thanks.
If your.py file takes a long time to run then you shouldn't use Process and use ProcessBuilder instead.
public ArrayList<String> getPasswords(String path) throws IOException {
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder("D:\\anaconda\\python.exe ", "D:\\2017\\Python\\pythonProject8\\main.py",path);
//The path here is me.py needs to be passed in
processBuilder.redirectErrorStream(true);
final Process process = processBuilder.start();
final BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s = null;
int i = 0;
while ((s = in.readLine()) != null)//This if is I need to ignore some of the output
{
i++;
if (i >6) {
result += s + '\n';
}
}
if (!result.equals("")){
return new ArrayList<String>(Arrays.asList(result.split("\n")));
}
return new ArrayList<String>();
}
You may run an error "DLL load failed while importing XXXX".
Please update the packages required for python.
I am executing a command which returns me the Revision number of a file; 'fileName'. But if there is some problem executing the command, then the application hangs up. What can I do to avoid that condition? Please find below my code.
String cmd= "cmd /C si viewhistory --fields=revision --project="+fileName;
Process p = Runtime.getRuntime().exec(cmd) ;
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
I guess the issue is that you are only reading InputStream and not reading ErrorStream. You also have to take care that both the streams are read in parallel. It may so happen that currently the data piped from the output stream fills up the OS buffer, your exec command will be automatically be suspended to give your reader a chance to empty the buffer. But the program will still be waiting for the output to process. Hence, the hang occurs.
You can create a separate class to handle both the Input and Error Stream as follows,
public class ReadStream implements Runnable {
String name;
InputStream is;
Thread thread;
public ReadStream(String name, InputStream is) {
this.name = name;
this.is = is;
}
public void start () {
thread = new Thread (this);
thread.start ();
}
public void run () {
try {
InputStreamReader isr = new InputStreamReader (is);
BufferedReader br = new BufferedReader (isr);
while (true) {
String s = br.readLine ();
if (s == null) break;
System.out.println ("[" + name + "] " + s);
}
is.close ();
} catch (Exception ex) {
System.out.println ("Problem reading stream " + name + "... :" + ex);
ex.printStackTrace ();
}
}
}
The way you use it is as follows,
String cmd= "cmd /C si viewhistory --fields=revision --project="+fileName;
Process p = Runtime.getRuntime().exec(cmd) ;
s1 = new ReadStream("stdin", p.getInputStream ());
s2 = new ReadStream("stderr", p.getErrorStream ());
s1.start ();
s2.start ();
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(p != null)
p.destroy();
}
This code is based on the same idea Arham's answer, but is implemented using a java 8 parallel stream, which makes it a little more concise.
public static String getOutputFromProgram(String program) throws IOException {
Process proc = Runtime.getRuntime().exec(program);
return Stream.of(proc.getErrorStream(), proc.getInputStream()).parallel().map((InputStream isForOutput) -> {
StringBuilder output = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(isForOutput))) {
String line;
while ((line = br.readLine()) != null) {
output.append(line);
output.append("\n");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return output;
}).collect(Collectors.joining());
}
You can call the method like this
getOutputFromProgram("cmd /C si viewhistory --fields=revision --project="+fileName);
Note that this method will hang if the program you are calling hangs, which will happen if it requires input.
I am trying to download image from server using CURL. Below is the code I am using.
private void executeCMD(String[] cmd) {
ProcessBuilder process = new ProcessBuilder(cmd);
Process p;
try
{
p = process.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ( (line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
String result = builder.toString();
System.out.print(result);
}
catch (IOException e)
{ System.out.print("error");
e.printStackTrace();
}
}
CMD is :
I can see the binary output(result) on the log files, but its not downloading as image on local drive.
I am trying to run a script using Java and ProcessBuilder. When I try to run, I receive the following message: error=2, No such file or directory.
I dont know what I am doing wrong but here is my code (ps: I tried to execute just the script without arguments and the error is the same:
String[] command = {"/teste/teste_back/script.sh, "+argument1+", "+argument+""};
ProcessBuilder p = new ProcessBuilder(command);
try {
// create a process builder to send a command and a argument
Process p2 = p.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p2.getInputStream()));
String line;
log.info("Output of running " + command + " is: ");
System.out.println("Output of running " + command + " is: ");
while ((line = br.readLine()) != null) {
log.info(line);
}
}
Try replacing
String[] command = {"/teste/teste_back/script.sh, "+argument1+", "+argument+""};
with
String[] command = {"/teste/teste_back/script.sh", argument1, argument};
Refer ProcessBuilder for more information.
ProcessBuilder(String... command)
Constructs a process builder with the specified operating system
program and arguments.
You can define a method with ProcessBuilder.
public static Map execCommand(String... str) {
Map<Integer, String> map = new HashMap<>();
ProcessBuilder pb = new ProcessBuilder(str);
pb.redirectErrorStream(true);
Process process = null;
try {
process = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader reader = null;
if (process != null) {
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
}
String line;
StringBuilder stringBuilder = new StringBuilder();
try {
if (reader != null) {
while ((line = reader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (process != null) {
process.waitFor();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if (process != null) {
map.put(0, String.valueOf(process.exitValue()));
}
try {
map.put(1, stringBuilder.toString());
} catch (StringIndexOutOfBoundsException e) {
if (stringBuilder.toString().length() == 0) {
return map;
}
}
return map;
}
You can call the function to execute shell command or script
String cmds = "ifconfig";
String[] callCmd = {"/bin/bash", "-c", cmds};
System.out.println("exit code:\n" + execCommand(callCmd).get(0).toString());
System.out.println();
System.out.println("command result:\n" + execCommand(callCmd).get(1).toString());
Unless your script.sh has a comma in its name, that is the mistake:
String[] command = {"/teste/teste_back/script.sh" , argument1, argument};
I tried to read a process'es std out and error using the solutions in How to redirect Process Builder's output to a string?, but it does not output anything.
Shouldn't there be a way to attach a stream reader to the process builder before starting the process?
/*
private String getInputAsString(InputStream is)
{
try(java.util.Scanner s = new java.util.Scanner(is))
{
return s.useDelimiter("\\A").hasNext() ? s.next() : "";
}
}
*/
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
List<String> args = new ArrayList<String>();
args.add ("cmd"); // command name
args.add ("/c");
args.add ("start");
args.add (fileName);
ProcessBuilder pb = new ProcessBuilder (args);
pb.directory(new File(Support.getJustThePathFromFile(file)));
Map<String, String> envs = pb.environment();
String path = envs.get("Path");
envs.put("Path", Paths.get(".").toAbsolutePath().normalize().toString() + ";" +path);
//pb.redirectOutput(new Redirect() {});
Process p = pb.start();
//String stdOut = getInputAsString(p.getInputStream());
//String stdErr = getInputAsString(p.getErrorStream());
//System.err.println("stdOut=" + stdOut);
//System.err.println("stdErr=" + stdErr);
try
{
p.waitFor();
BufferedReader output = getOutput(p);
BufferedReader error = getError(p);
String ligne = "";
while ((ligne = output.readLine()) != null) {
System.out.println(ligne);
}
while ((ligne = error.readLine()) != null) {
System.out.println(ligne);
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}