How to read process builder input and error streams? - java

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();
}

Related

I'm writing a method using spring-boot that calls a.py file, and when I request this method, the code for py doesn't run

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.

How to understand why java process stuck

I have to launch console commands from java to publish to verdaccio.
So it works(pretty bad), but for few packages processes stucks. When I destroy them it returns code 137, witch means not enough memory. I watched in profiler, I have much more free heap, then used.
Maybe it's not because not enough memory.
How to understand why it stucks and how to fix it?
protected String execCommand(List<String> command) throws IOException, NpmAlreadyExistException{
ProcessBuilder pb = new ProcessBuilder(command);
File workingFolder = new File(System.getProperty("user.dir"));
pb.directory(workingFolder);
Process process = pb.start();
try {
boolean finished = process.waitFor(60, TimeUnit.SECONDS);
logger.info("PROC FINISHED: " + finished);
if (!finished) {
process.destroyForcibly();
int exitCode = process.waitFor();
logger.info("PROC EXIT CODE: " + exitCode);
return null;
}
} catch (InterruptedException e) {
logger.info("PROCESS WAS INTERRUPTED!!!");
logger.info(e.getMessage());
return null;
}
logger.info("PROC EXIT CODE: " + process.exitValue());
String s;
BufferedReader stdErr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
StringBuilder err = new StringBuilder();
while ((s = stdErr.readLine()) != null) {
err.append("\n").append(s);
}
stdErr.close();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder result = new StringBuilder();
while ((s = stdInput.readLine()) != null) {
result.append("\n").append(s);
}
stdInput.close();
process.destroy();
logger.info(String.format("execCommand response [stdin]: %s", result));
logger.info(String.format("execCommand response [stdErr]: %s", err));
if (err.length() != 0) {
if (err.toString().contains("Update the 'version' field in package.json and try again.")) {
throw new NpmAlreadyExistException("Пакет с таким именем и версией уже существует в репозитории.");
}
}
return result.toString();
}
Thank you!

Running a shell script using ProcessBuilder

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};

JAVA Concurrent stdInput and stdError with process.exec

I am trying to read the stdInput and stdError from a process while the process is running. I created a thread to run the process, and that works. In the constructor for the I pass a reference to a Process that is created so I can watch the output from the process. The problem is it does not seem to be linking the reference process leaving it set to null. The goal of all this is to be able to watch the output of the process while the process is still running, currently I am stuck with looking at the output after it is done. I figure this is due to the tread being run but I hope there is a way to do this.
try {
Process p = null;
Thread mythread = new Thread( new SJ(pathF.getText(), fileF.getText(), p, view) ) ;
mythread.start();
BufferedReader stdInput = null;
BufferedReader stdError = null;
String s = null;
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while (mythread.isAlive()) {
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
}
} catch ( IOException e ) {}
class SJ implements Runnable {
String Path = "";
String File = "";
public static viewering view;
Process p = null;
public SJ ( String arg1, String arg2, Process p1, viewering view ) {
Path = arg1;
File = arg2;
p = p1;
}
public void run() {
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/C";
command[2] = "compile";
command[3] = Path;
command[4] = File;
BufferedReader stdInput = null;
BufferedReader stdError = null;
String s = null;
try {
p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
} catch ( IOException e ) {}
}
}
Here is the code for the final working scenario
public void actionPerformed(ActionEvent ae) {
frame.setVisible( false );
final Thread mythread = new Thread( new SJ(pathF.getText(), fileF.getText(), view) ) ;
mythread.start();
final Timer ThreadTimer = new Timer( 1000, null );
ThreadTimer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!mythread.isAlive()) {
frame.setVisible( true );
ThreadTimer.stop();
}
}});
ThreadTimer.start();
}
class SJ implements Runnable {
String Path = "";
String File = "";
public static viewering view;
public SJ ( String arg1, String arg2, viewering view1 ) {
Path = arg1;
File = arg2;
view = view1;
}
public void run() {
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/C";
command[2] = "compile";
command[3] = Path;
command[4] = File;
BufferedReader stdInput = null;
BufferedReader stdError = null;
Process p = null;
String s = null;
try {
p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
} catch ( IOException e ) {}
}
}
Ok, that's a completly different problem. And now I understand your real problem. If you excute the first part of your code in the click listener of a button, Swings event loop which is running in an own thread hangs for a while. Then you have to use a Thread. ;-)
Look at the last answer in this question:
Printing a Java InputStream from a Process

Retrieve output of ProcessBuilder

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;

Categories