How to execute an interactive shell script using java runtime?

I am wondering if there is a way to execute the following shell script that is waiting for user input using the java Runtime class?

#!/bin/bash echo "Please enter your name:" read name echo "Welcome $name" 

I use the following java code to accomplish this task, but it just shows an empty console.

 public class TestShellScript { public static void main(String[] args) { File wd = new File("/mnt/client/"); System.out.println("Working Directory: " +wd); Process proc = null; try { proc = Runtime.getRuntime().exec("sudo ./test.sh", null, wd); } catch (Exception e) { e.printStackTrace(); } } 

}

The thing is, when I execute on the program, I believe that it will execute the shell script, and the shell script will wait for user input, but it just prints the current directory and then exits. Is there a way to do this, or is it not possible at all in java?

Thanks in advance

+6
source share
4 answers

The reason it prints the current directory and exits is because your java application is shutting down. You need to add a (threaded) listener to the input and error streams of your created process, and you probably want to add printStream to the process output

Example:

 proc = Runtime.getRuntime().exec(cmds); PrintStream pw = new PrintStream(proc.getOutputStream()); FetcherListener fl = new FetcherListener() { @Override public void fetchedMore(byte[] buf, int start, int end) { textOut.println(new String(buf, start, end - start)); } @Override public void fetchedAll(byte[] buf) { } }; IOUtils.loadDataASync(proc.getInputStream(), fl); IOUtils.loadDataASync(proc.getErrorStream(), fl); String home = System.getProperty("user.home"); //System.out.println("home: " + home); String profile = IOUtils.loadTextFile(new File(home + "/.profile")); pw.println(profile); pw.flush(); 

To run this, you need to download the sourceforge project: http://tus.sourceforge.net/ , but hopefully the code snippet is instructive that you can just adapt to J2SE and what you use.

+1
source

If you use Java ProcessBuilder, you will be able to get input, error, and output streams of the process you are creating.

These streams can be used to get information coming out of the process (for example, input hints), but they can also be recorded to directly enter information into the process. For instance:

 InputStream stdout = process.getInputStream (); BufferedReader reader = new BufferedReader (new InputStreamReader(stdout)); String line; while(true){ line = reader.readLine(); //... 

This will give you the result directly from the process. I did not do this myself, but I am sure that process.getOutputStream() gives you something that can be written directly to send input to the process.

+1
source

The problem with running interactive programs like sudo from Runtime.exec is that it attaches their stdin and stdout to the channels, and not to the console device they need. You can make it work by redirecting input and output to /dev/tty .

You can achieve the same behavior using the new ProcessBuilder class by setting up redirection using ProcessBuilder.Redirect.INHERIT .

+1
source

Please note that you can send input to your script from Java. However, I highly recommend taking a look at Commons Exec if you want to execute external scripts from Java:

Commons Exec Homepage

Commons Exec API

0
source

Source: https://habr.com/ru/post/911947/


All Articles