3

I want to get total free E1 channels on media server in my java program. I used following code to get my desired result:

String command = "asterisk -rx " + '"' + "ss7 linestat " + '"' + " |grep " + '"' + "Idle" + '"' + " |wc -l";
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null)


    {
        freeE1s += line + "\n";
    }            

System.out.println(freeE1s);

When I execute above command in linux shell using kitty then it works fine and return count but when i use this jar then i get exception. I debugged code by logging and found buf.readLine() returns null.

Edit 1:

Don't worry about exception it's only parsing output to integer which caused exception actually the problematic thing is when I logged buf.readlin() it returned null which of course cannot be parsed to int.

2
  • Can you provide the exception you are receiving? Commented Jun 3, 2015 at 17:55
  • In fact exception is on parsing result to int because above command should returns int value so i am parsing result to int which causes exception but what about this thing 2015-06-03 23:06:51,419 DEBUG buf.readLine(): null Commented Jun 3, 2015 at 18:09

1 Answer 1

6

First, don't use Runtime.exec. Always use ProcessBuilder, which has much more reliable and predictable behavior.

Second, everything in your string is being passed as a single command, including the vertical bars. You are not passing it to a shell (like /bin/bash), so piping commands to one another won't work.

Third, you need to consume the command's output as it is running. If you call waitFor() and then try to read the output, it may work sometimes, but it will also fail much of the time. This behavior is highly operating system dependent, and can even vary among different Linux and Unix kernels and shells.

Finally, you don't need grep or wc. You have Java. Doing the same thing in Java is pretty easy (and probably easier than trying to invoke a shell so piping will work):

ProcessBuilder builder =
    new ProcessBuilder("asterisk", "-rx", "ss7 linestat");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process p = builder.start();

int freeE1s = 0;
try (BufferedReader buf =
        new BufferedReader(new InputStreamReader(p.getInputStream()))) {
    String line;
    while ((line = buf.readLine()) != null) {
        if (line.contains("Idle")) {    // No need for 'grep'
            freeE1s++;                  // No need for 'wc'
        }
    }
}

p.waitFor();

System.out.println(freeE1s);

As of Java 8, you can make it even shorter:

ProcessBuilder builder =
    new ProcessBuilder("asterisk", "-rx", "ss7 linestat");
builder.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process p = builder.start();

long freeE1s;
try (BufferedReader buf =
        new BufferedReader(new InputStreamReader(p.getInputStream()))) {
    freeE1s = buf.lines().filter(line -> line.contains("Idle")).count();
}

p.waitFor();

System.out.println(freeE1s);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.