ProcessBuilder getOutputStream e interagire con i processi
Domanda
Ho problemi a interagire con un processo utilizzando getOutputStream.Ecco il mio codice:
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();
Ecco l'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 esegue semplicemente "gksudo apt-get install firefox"
Non so perché si interrompa e non riceva il mio input "Y", grazie.
Soluzione
Ci sono diversi problemi.
Primo : gksudo(1)
esegue alcuni trucchi sporchi e non standard con lo standard input e standard output dei comandi che avvia. Fallisce in modo orribile. Un buon esempio è questa riga di comando:
$ echo foo | gksudo -g cat
Mi aspetto qualsiasi output e la cessazione del cat
non appena il echo
ha consegnato i dati. No. Sia gksudo
che cat
restano in giro per sempre. Nessun output.
Il tuo caso d'uso sarebbe
echo y |gksudo apt-get install ....
e anche questo non funzionerà. Finché il problema non viene risolto, puoi dimenticare di eseguire qualsiasi controllo remoto se il programma avviato richiede l'input dell'utente.
Secondo : come già sottolineato da Roger waitFor()
attende la fine del comando. Questo non accadrà presto senza alcun input da parte dell'utente e con il problema di gksudo.
Terzo Dopo aver spinto waitFor
un po 'in basso, c'è il blocco successivo: aspetti l'output completo del processo fino all'EOF incluso. Ciò non accadrà presto (vedere "primo" e "secondo").
Quarto Solo dopo che il processo è già morto due volte (vedere "secondo" e "terzo") potrebbe ricevere un input: il tuo Y
(che potrebbe anche richiedere un \n
aggiuntivo).
Invece di risolvere questo mucchio di problemi, potrebbe esserci un modo migliore e molto più semplice: non provare a controllare apt-get install
con lo standard input. Dagli solo alcune opzioni appropriate che "rispondono" automaticamente alle tue domande. Un rapido man apt-get
mostra alcuni candidati:
-y, --yes, --assume-yes
--force-yes
--trivial-only
--no-remove
--no-upgrade
Vedere il manuale per i dettagli.
Penso che questo sia il modo migliore e più stabile.
PS: In questo momento sono un po 'più gksudo
, quindi scusa lo sfogo sopra.