Vladutu Georgian
Vladutu Georgian

Reputation: 1

Runtime exec Process hangs

I'm trying to make a javafx application which displays the logs from kubernetes. I'm using Runtime.getRuntime().exec to get the output of kubetail servicename in the following way:

 Process exec = Runtime.getRuntime().exec(new String[]{"kubetail", "serviceName"});
        InputStream inputStream = exec.getInputStream();
        int read;
        try {
            while (((read = inputStream.read()) != -1)) {
                System.out.print((char) read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

The process starts normally and I see "Will tail 2 pods...". The problem appears when I make a request on that service and a lot of logs appears. The service returns a report and this report is archived and it is also logged. The report is quite big, 40K characters. The tail somehow hangs in the middle of the logged report and I don't get any more data, but if I send another request, it continues from where it hanged and stops again on the report of the second request.

I tried using buffered reader and also wrapped the inputstream with NIO, but the problem persist. I also tried to use kubectl logs and this works on but I don't have any identification for the line of log (I don't know which pod it belongs to). kubetail gives a stream of logs for all the pods in an application and these are identified by color and by pod name.

Thank you

Upvotes: 0

Views: 282

Answers (1)

DuncG
DuncG

Reputation: 15196

You are not consuming the stdout and stderr streams properly, they will cause process output to hang if one fills without you reading it. You could try setting stderr to go to stdout class when using ProcessBuilder

ProcessBuilder pb = new ProcessBuilder(new String[]{"kubetail", "serviceName"});
pb.redirectErrorStream(true);
Process exec = pb.start();
... Your reading code
int rc = exec.waitFor();

OR: add threads to consume both stdout and stderr streams:

Process exec = Runtime.getRuntime().exec(new String[]{"kubetail", "serviceName"});        
new Thread(() -> copy(exec.getInputStream(), System.out), "STDOUT").start();
new Thread(() -> copy(exec.getErrorStream(), System.err), "STDERR").start();
int rc = exec.waitFor();

with method:

static void copy(InputStream in, OutputStream out)
{
    try(var autoClose = in; var autoClose2 = out)
    {
        in.transferTo(out);
    }
    catch(IOException io)
    {
        throw new UncheckedIOException(io);
    }
}

Upvotes: 1

Related Questions