0

I created the below method to execute a Linux command:

public void executeGetLogs(){
    try{
        Runtime rt = Runtime.getRuntime();
        String [] commands = {helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword()};
        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
        logger.debug("Standard output from execution of get_logs:\n");
        String s = null;
        while ((s = stdInput.readLine()) != null) {
            logger.debug(s);
        }

        // read any errors from the attempted command
        logger.debug("Standard error from execution of get_logs (if any):\n");
        while ((s = stdError.readLine()) != null) {
            logger.debug(s);
        }
    }
    catch(IOException e){
        logger.debug("Execution exception: " + e);
    }
}

The method appears to start working correctly but then fails.

The debug shows the following output:

2017-04-21 12:27:42,391 DEBUG  Standard output from execution of get_logs:

2017-04-21 12:27:44,360 DEBUG  411 new files found
2017-04-21 12:27:44,363 DEBUG  Downloading files...
2017-04-21 12:27:44,446 DEBUG  Standard error from execution of get_logs (if any):

What I would expect to see is

2017-04-21 12:27:44,360 DEBUG  411 new files found
2017-04-21 12:27:44,363 DEBUG  Downloading files...
Downloaded 10 of 447
Downloaded 20 of 447
Downloaded 30 of 447

and so on until Downloaded 447 of 447.

I can also see that nothing gets downloaded.

My command runs when I run it in a terminal.

Is it possible something in the Java causes it to exit? One thing is that it can take a few seconds to process each block of 10. Is it possible the

while ((s = stdInput.readLine()) != null) {
    logger.debug(s);
}

just sees a null because the stdInput hasn't appeared yet so it exits the loop? If so how can I fix this?

runnerpaul
  • 5,942
  • 8
  • 49
  • 118

2 Answers2

0

A much better way of executing code in java is ProcessBuilder. Example:

//Create the command.
ProcessBuilder command = new ProcessBuilder(helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword());
//Will show console output in java console.
command .inheritIO();
//Launches de command.
Process process= command .start();

Hope it helps.

MissingSemiColon
  • 346
  • 3
  • 14
  • I'll give that a go. Thanks – runnerpaul Apr 21 '17 at 12:41
  • I seem to be hitting the same problem when I use that. – runnerpaul Apr 21 '17 at 13:46
  • OK, here's a thought. The processing output has a count (Downloaded 10 of 447 etc). I'm thinking if I read the total. In this case 447 and loop through a count. Something along the lines of while(coint < 447){ keep processing;}. Obviously need to parse that so I can get the total and current count. Am I thinking alont the correct lines. I'll look into this a little unless I hear otherwise. – runnerpaul Apr 21 '17 at 21:23
  • 1
    Sorry for not answering. I see you had to wait for the script to end. If your process prints to the console each iterariton you should be able to read each of the lines in the stream (just tested it). I would still recommend you to use ProcessBuilder it corrects bugs from Runtime.getRuntime(), good explanation here: http://stackoverflow.com/questions/6856028/difference-between-processbuilder-and-runtime-exec. Happy you solved your problem, nice work! – MissingSemiColon Apr 27 '17 at 12:56
0

Got to the bottom of it. I need to wait for the process to end. This can be done with the below code:

proc.waitFor();

My method now looks like this:

public void executeGetLogs(){
    try{
        Runtime rt = Runtime.getRuntime();
        String [] commands = {helper.getPythonPath(), helper.getLogsMainScript(), helper.getLogsManagementUrl(), helper.getLogsManagementUrlPrefix(), helper.getLogsManagementUsername(), helper.getLogsManagementPassword(), helper.getLogsNet(), helper.getLogsStorageUrl(), helper.getLogStorageUsername(), helper.getLogStoragePassword()};
        Process proc = rt.exec(commands);

        BufferedReader stdInput = new BufferedReader(new 
            InputStreamReader(proc.getInputStream()));

        try{
            proc.waitFor();
        }
        catch(InterruptedException e){
            logger.debug("Interrupted Exception : " + e);
        }

        BufferedReader stdError = new BufferedReader(new 
            InputStreamReader(proc.getErrorStream()));

        // read the output from the command
        logger.debug("Standard output from execution of get_logs:\n");
        String s = null;
        while ((s = stdInput.readLine()) != null) {
            logger.debug(s);
        }

        // read any errors from the attempted command
        logger.debug("Standard error from execution of get_logs (if any):\n");
        while ((s = stdError.readLine()) != null) {
            logger.debug(s);
        }
    }
    catch(IOException e){
        logger.debug("Execution exception: " + e);
    }
}
runnerpaul
  • 5,942
  • 8
  • 49
  • 118