Question

I am having trouble interacting with a process using getOutputStream. Here is my code:

    Process p = null;
    ProcessBuilder pb = new ProcessBuilder("/home/eric/this.sh");
    pb.directory(new File("/home/eric/"));
    p = pb.start();

    InputStream in = null;
    OutputStream outS = null;

    StringBuffer commandResult = new StringBuffer();
    String line = null;
    int readInt;

    int returnVal = p.waitFor();

    in = p.getInputStream();

    while ((readInt = in.read()) != -1)
        commandResult.append((char)readInt);
    outS = (BufferedOutputStream) p.getOutputStream();
    outS.write("Y".getBytes());
    outS.close();

    System.out.println(commandResult.toString());
    in.close();

Here is the output:

Reading package lists...
Building dependency tree...
Reading state information...
The following packages were automatically installed and are no longer required:
  libmono2.0-cil libmono-data-tds2.0-cil libmono-system-data2.0-cil
  libdbus-glib1.0-cil librsvg2-2.18-cil libvncserver0 libsqlite0
  libmono-messaging2.0-cil libmono-system-messaging2.0-cil
  libmono-system-data-linq2.0-cil libmono-sqlite2.0-cil
  libmono-system-web2.0-cil libwnck2.20-cil libgnome-keyring1.0-cil
  libdbus1.0-cil libmono-wcf3.0-cil libgdiplus libgnomedesktop2.20-cil
Use 'apt-get autoremove' to remove them.
The following extra packages will be installed:
  firefox-globalmenu
Suggested packages:
  firefox-gnome-support firefox-kde-support latex-xft-fonts
The following NEW packages will be installed:
  firefox firefox-globalmenu
0 upgraded, 2 newly installed, 0 to remove and 5 not upgraded.
Need to get 15.2 MB of archives.
After this operation, 30.6 MB of additional disk space will be used.
Do you want to continue [Y/n]? Abort

this.sh simply runs "gksudo apt-get install firefox"

I don't know why it is Aborting and not taking my input "Y" thanks.

Was it helpful?

Solution

There are several problems.

First: gksudo(1) does some dirty, non-standard tricks with the standard input and standard output of the commands it starts. It fails horrible. A good example is this command line:

$ echo foo | gksudo -g cat

I would expect any output and the termination of the cat as soon as the echo has delivered the data. Nope. Both gksudo and cat hang around forever. No output.

Your usecase would be

echo y |gksudo apt-get install ....

and this will not work also. As long as this is not solved, you can forget to do any remote control if the started program requires any user input.

Second: As already pointed out by Roger waitFor() waits for the termination of the command. This will not happen any time soon without any user input and with the gksudo problem.

Third After shoving waitFor down a bit there is the next blocker: You wait for the complete output of the process up to and including the EOF. This will not happen anytime soon (see "first" and "second").

Fourth Only after the process is already dead twice (see "second" and "third") it might get some input - your Y (which might also need an additional \n).


Instead of solving this bunch of problems there might be a better and much easier way: Don't try to control apt-get install with standard input. Just give it some appropriate options which automatically "answers" your questions. A quick man apt-get turns up some candidates:

-y, --yes, --assume-yes
--force-yes
--trivial-only
--no-remove
--no-upgrade

See the manual for details.

I think this is the better and more stable way.

PS: Right now I'm pi*** o*** gksudo quite a bit, so excuse the rant above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top