Use Process.getInputStream() to get an InputStream that represents the stdout of the newly created process.

Note that starting/running external processes from Java can be very tricky and has quite a few pitfalls.

They are described in this excellent article, which also describes ways around them.

Answer from Joachim Sauer on Stack Overflow
🌐
Coderanch
coderanch.com › t › 751548 › java › Execute-Linux-Command-Return-Output
Execute Linux Command and Return Output (Java in General forum at Coderanch)
May 9, 2022 - Incidentally, in Linux, an SMB shared file path is in the form "//hostname/sharename/dirname/dirname/filename". Even outside of Java, since backslashes are perilous to Unix-style users. Yes, there is a Java library for working with CIFS file sharing. And no, I don't recommend using Runtime.exec() to execute a series of commands and especially not with redirects.
🌐
Baeldung
baeldung.com › home › java › core java › how to run a shell command in java
How to Run a Shell Command in Java | Baeldung
January 8, 2024 - @Test public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { List<ProcessBuilder> builders = Arrays.asList( new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), new ProcessBuilder("wc", "-l")); List<Process> processes = ProcessBuilder.startPipeline(builders); Process last = processes.get(processes.size() - 1); List<String> output = readOutput(last.getInputStream()); assertThat("Results should not be empty", output, is(not(empty()))); } In the above example, we’re searching for all the java files inside the src directory and piping the results into another process to count them. To learn about other improvements made to the Process API in Java 9, check out our great article on Java 9 Process API Improvements. As we’ve seen in this quick tutorial, we can execute a shell command in Java in two distinct ways.
🌐
Crunchify
crunchify.com › macos tutorials › how to run windows, linux, macos terminal commands in java and return complete result
How to Run Windows, Linux, macOS terminal commands in Java and return complete Result • Crunchify
February 26, 2019 - package crunchify.com.tutorials; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * @author Crunchify.com * Execute Linux commands using Java. We are executing mkdir, ls -ltra and ping in this tutorial */ public class CrunchifyCommandJava { public printOutput getStreamWrapper(InputStream is, String type) { return new printOutput(is, type); } public static void main(String[] args) { Runtime rt = Runtime.getRuntime(); CrunchifyCommandJava rte = new CrunchifyCommandJava(); printOutput errorReported, outputMessage; try { P
🌐
Mkyong
mkyong.com › home › java › how to execute shell command from java
How to execute shell command from Java - Mkyong.com
January 3, 2019 - try { // -- Linux -- // Run a shell command // Process process = Runtime.getRuntime().exec("ls /home/mkyong/"); // Run a shell script // Process process = Runtime.getRuntime().exec("path/to/hello.sh"); // -- Windows -- // Run a command //Process process = Runtime.getRuntime().exec("cmd /c dir C:\\Users\\mkyong"); //Run a bat file Process process = Runtime.getRuntime().exec( "cmd /c hello.bat", null, new File("C:\\Users\\mkyong\\")); StringBuilder output = new StringBuilder(); BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream())); String line; while ((line
Top answer
1 of 2
14

The primary reason why this doesn't work is that `$2` is not the same as `ls -1 | tail -1`, even when $2 is set to that string.

If your script accepts a literal string with a command to execute, you can use eval to do so.

I created a complete example. Please copy-paste it and verify that it works before you try applying any of it to your own code. Here's Test.java:

Copyimport java.io.*;

public class Test {
  public static void main(String[] args) throws Exception {
    String[] command = { "./myscript", "key", "ls -t | tail -n 1" };
    Process process = Runtime.getRuntime().exec(command);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
        process.getInputStream()));
    String s;
    while ((s = reader.readLine()) != null) {
      System.out.println("Script output: " + s);
    }
  }
}

And myscript:

Copy#!/bin/bash
key="$1"
value=$(eval "$2")
echo "The command  $2  evaluated to: $value"

Here's how we can run myscript separately:

Copy$ ls -t | tail -n 1
Templates

$ ./myscript foo 'ls -t | tail -n 1'
The command  ls -t | tail -n 1  evaluated to: Templates

And here's the result of running the Java code:

Copy$ javac Test.java && java Test
Script output: The command  ls -t | tail -n 1  evaluated to: Templates 
2 of 2
0

As other posters pointed out already, the sub-process is not started in a shell, so the she-bang is not interpreted.

I got your example to work by explicitly starting the evaluation of the second parameter in a shell in jj.sh:

Copyvalue=`sh -c "$2"` 

Not nice, but works.

Other option may be to start the script in a shell explicitly, emulating the sh-bang:

CopyString[] cmd = { "/bin/sh", "jj.sh" , key,value};
Find elsewhere
🌐
Java2s
java2s.com › example › java › native-os › execute-shell-command-and-get-output.html
execute Shell Command And Get Output - Java Native OS
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class Main{ public static void main(String[] argv) throws Exception{ String command = "java2s.com"; System.out.println(executeCommandAndGetOutput(command)); }//from www . j av a2s .c o m public static String executeCommandAndGetOutput(String command) throws Exception { Process proc = createAndExecuteProcess(command); logForProc(proc); return getOuputMessageOfCommand(proc.getInputStream()); } private static Process createAndExecuteProcess(String co
🌐
Medium
beknazarsuranchiyev.medium.com › run-terminal-commands-from-java-da4be2b1dc09
Run terminal commands from Java. In this article, we will discuss how to… | by Beknazar | Medium
April 24, 2022 - It’s quite helpful to know how to run the operating system processes via Java code. The ProcessBuilder class is used to build Process object. We specify the commands and other configurations in the ProcessBuilder. We work on actual execution with Process instance. For example to get the status code from the process, to get its id, to see the output, to wait, and to kill the process.
🌐
GeeksforGeeks
geeksforgeeks.org › java › how-to-execute-native-shell-commands-from-java-program
How to Execute Native Shell Commands from Java Program? - GeeksforGeeks
March 3, 2021 - For example, a Java program running specifically Linux shell commands cannot run as-is on a Windows machine mainly because Windows has a different folder structure and shell commands. ... The first three examples will look at implementing the ProcessBuilder class to run shell commands in Java. The following example is for the RunTime class. Example 1: Loss of portability. This example shows what happens if we execute a Java program meant for the Linux/Unix operating system on a Windows operating system.
🌐
Code Explosion
codexplo.wordpress.com › 2013 › 04 › 13 › executing-linux-command-from-java
Executing Linux command from Java – Code Explosion
April 13, 2013 - public static void main(String[] args) {</pre> String output = CommandExecutor.execute("ps aux | head -3"); System.out.println(output); } ... USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 24600 2212 ?
🌐
GitHub
gist.github.com › padcom › a5831bea701ef08ce944
Running a process and reading its output in Java · GitHub
Running a process and reading its output in Java · Raw · Execute.java · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
🌐
Princeton CS
introcs.cs.princeton.edu › java › 15inout › linux-cmd.html
Java and the Linux Command Line
You will use the java command to execute your program. From the shell, type the java command below. [wayne] ~/introcs/hello> java HelloWorld Hello, World If all goes well, you should see the output of the program - Hello, World. If your program gets stuck in an infinite loop, type Ctrl-c to break out.
🌐
GitHub
gist.github.com › 4283217
Executing a linux bash command from a java program and reading the response of it which spans multiple lines · GitHub
Executing a linux bash command from a java program and reading the response of it which spans multiple lines
🌐
Alvin Alexander
alvinalexander.com › java › java-exec-system-command-pipeline-pipe
Java exec: How to execute a system command pipeline in Java | alvinalexander.com
Jumping right in, let's imagine that you want to run the following Unix/Linux command from your Java application: ... package com.devdaily.system; import java.io.IOException; import java.util.*; public class ProcessBuilderExample { public static void main(String[] args) throws IOException, InterruptedException { // you need a shell to execute a command pipeline List<String> commands = new ArrayList<String>(); commands.add("/bin/sh"); commands.add("-c"); commands.add("ls -l /var/tmp | grep foo"); SystemCommandExecutor commandExecutor = new SystemCommandExecutor(commands); int result = commandExecutor.executeCommand(); StringBuilder stdout = commandExecutor.getStandardOutputFromCommand(); StringBuilder stderr = commandExecutor.getStandardErrorFromCommand(); System.out.println("STDOUT"); System.out.println(stdout); System.out.println("STDERR"); System.out.println(stderr); } }
Top answer
1 of 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);
🌐
Stack Abuse
stackabuse.com › executing-shell-commands-with-java
Executing Shell Commands with Java
May 18, 2020 - The Runtime class in Java is a high-level class, present in every single Java application. Through it, the application itself communicates with the environment it's in. By extracting the runtime associated with our application via the getRuntime() method, we can use the exec() method to execute ...
🌐
CodeJava
codejava.net › java-se › file-io › execute-operating-system-commands-using-runtime-exec-methods
How to Execute Operating System Commands in Java
July 27, 2019 - Throughout this tutorial, you will learn how to execute a native command from within a Java program, including sending inputs to and getting outputs from the command.Basically, to execute a system command, pass the command string to the exec() method of the Runtime class.
🌐
JavaPointers
javapointers.com › java › java-core › how-to-run-a-command-using-java-in-linux-or-windows
How To Run a Command using Java in Linux or Windows - JavaPointers
May 24, 2020 - public static void main(String... args) { Main main = new Main(); //test command in linux main.runCommand("pwd"); main.runCommand("ifconfig", "-a"); } Here, we try to print the current working directory and the network configurations available. Here’s a sample output: You can even run a shell script by just putting the script file location and starting with a forward slash eg., “/home/your-script.sh”. That’s it for this guide. You have learned how to execute or run a command using Java in Windows or Linux systems.