Search code examples
javaarpapache-commons-exec

Better way to run pipe command using apache commons exec


I am using apache commons exec to run command: arp | wc -l Below is my code:

 private String runCommand(String cmd, String params) {
        CommandLine commandLine = new CommandLine(cmd);
        commandLine.addArguments(params);
        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
        PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, stderr);
        ExecuteWatchdog watchdog = new ExecuteWatchdog(30000);  // 30s timeout
        DefaultExecutor executor = new DefaultExecutor();
        executor.setStreamHandler(pumpStreamHandler);
        executor.setWatchdog(watchdog);

        try {
            int retCode = executor.execute(commandLine);
            System.out.println("Executed '" + cmd + "'\n"
                    + "returnCode: " + retCode + "\n"
                    + "stdout:\n" + stdout.toString() + "\n"
                    + "stderr:\n" + stderr.toString());

            if (retCode == 0) {
                return stdout.toString();
            } else {
                throw new NonZeroExitStatusReturnedException(commandLine.toString(), retCode);
            }

        } catch (IOException e) {
            throw new RuntimeException("Could not run command "+ commandLine.toString(), e);
        }
}

Here the cmd is /bin/sh and params are -c arp|wc-l The code is giving following output:

Executed '/bin/sh'
returnCode: 0
stdout:
       54       71       4321

stderr:
usage: arp [-n] [-i interface] hostname
       arp [-n] [-i interface] [-l] -a
       arp -d hostname [pub] [ifscope interface]
       arp -d [-i interface] -a
       arp -s hostname ether_addr [temp] [reject] [blackhole] [pub [only]] [ifscope interface]
       arp -S hostname ether_addr [temp] [reject] [blackhole] [pub [only]] [ifscope interface]
       arp -f filename

I have two questions here:
Question 1. I cannot understand that why there are three numbers in my output (54 71 4321). Isnt it supposed to be only one number?

Question2. Is there any better way to run the same command using apache commons exec?


Solution

  • After reading the documentation carefully - https://commons.apache.org/proper/commons-exec/apidocs/org/apache/commons/exec/CommandLine.html.
    Here's the answer for Question2:

    private String runCommand(String cmd, String[] params) {
            CommandLine commandLine = new CommandLine(cmd);
            commandLine.addArguments(params, false);
            ByteArrayOutputStream stdout = new ByteArrayOutputStream();
            ByteArrayOutputStream stderr = new ByteArrayOutputStream();
            PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, stderr);
            ExecuteWatchdog watchdog = new ExecuteWatchdog(30000);  // 30s timeout
            DefaultExecutor executor = new DefaultExecutor();
            executor.setStreamHandler(pumpStreamHandler);
            executor.setWatchdog(watchdog);
    
            try {
                int retCode = executor.execute(commandLine);
                System.out.println("Executed '" + cmd + "'\n"
                        + "returnCode: " + retCode + "\n"
                        + "stdout:\n" + stdout.toString() + "\n"
                        + "stderr:\n" + stderr.toString());
    
                if (retCode == 0) {
                    return stdout.toString();
                } else {
                    throw new NonZeroExitStatusReturnedException(commandLine.toString(), retCode);
                }
    
            } catch (IOException e) {
                throw new RuntimeException("Could not run command "+ commandLine.toString(), e);
            }
    }
    

    Here cmd is: /bin/sh params is: new String[] { "-c", "arp|wc -l" }