Java – You cannot run the bash shell using Java

You cannot run the bash shell using Java… here is a solution to the problem.

You cannot run the bash shell using Java

Why doesn’t this code give me the bash prompt? I tried BufferedReader, but it didn’t work. I also can’t enter any commands in the console, such as “help”.

  • Commands such as ‘ls’ and ‘ps’ work fine.
  • Running bash with incorrect parameters or “–help” produces output.
  • Running Java as a super user doesn’t help.

Any ideas?

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) {
        try {
            Process p = Runtime.getRuntime().exec("bash");
            InputStream o = p.getInputStream();
            InputStream e = p.getErrorStream();
            OutputStream i = p.getOutputStream();
            while (true) {
                if (o.available() > 0) {
                    System.out.write(o.read());
                }
                if (e.available() > 0) {
                    System.out.write(e.read());
                }
                if(System.in.available() > 0) {
                    i.write((char)System.in.read());
                }
                if(o.available() == 0 && e.available() == 0 && !p.isAlive()) {
                    return;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Solution

Why doesn’t this code give me the bash prompt?

It’s not clear what “bash prompt” means… But I’m assuming you expect to see the bash hint character in the shell’s standard output/error stream.

Anyway, the reason is that the shell is not interactive.

The bash manual entry says this:

An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.

Note that when you launch commands from Java on Linux/Unix (your way), their standard I/O streams will be pipes and isatty will not recognize them as “terminals”.

So, if you want to force the shell to be “interactive”, you need to include the “-i” option in the bash command line. For example:

Process p = Runtime.getRuntime().exec(new String[]{"bash", "-i"});

Related Problems and Solutions