Frage

Ich habe den Eindruck, dass die Prozesse auf dem Betriebssystem drei Standard-Streams haben: stdin, stdout, and stderr. Ich habe auch gedacht, dass Text-Editoren wie Vim Arbeit durch Eingabe über stdin nehmen und ANSI-Escape-Zeichen über stdout senden. Allerdings ist nicht meine Ansicht, wie Kommandozeileninterpreter in diesem Fall hält:

Wenn ich den Befehl C:\cygwin\bin\bash.exe laufen, ich bin aufgefordert, mit:

Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\masson>C:\cygwin\bin\bash.exe
bash-3.2$ 

... aber wenn ich es in Java mit dem folgenden Ausschnitt laufe, der stdin-Stream ist leer:

ProcessBuilder pb = new ProcessBuilder("C:\\cygwin\\bin\\bash.exe");
pb.redirectErrorStream(true);
Process proc = pb.start();
final InputStream in = proc.getInputStream();

new Thread(new Runnable() {
  public void run() {
    // Blocks forever...
    in.read(new byte[1024]);
  }
}).start();

Was ist hier los? Mir wurde gesagt, dass bash.exe im interaktiven-Modus ausgeführt wird. Bedeutet dies die Standard-Streams nicht verwendet werden? Wie kann ich arbeiten noch Arbeit mit diesen Programmen, und schließlich, wie konnte ich meine eigene Version von cmd.exe implementieren? Ich glaube, ich bin nicht verstehen etwas Grundsätzliches wie Kommandozeileninterpreter arbeiten ...

(Alle Links zu den Artikeln verwandten Themen diskutieren würden sehr geschätzt. Ich habe nicht viel Glück gesucht hatte. Oh, und eine letzte Frage, sind Standard-Streams in Windows anders behandelt als in den meisten Unix-ähnlichen Betriebssystemen? )

War es hilfreich?

Lösung

im interaktiven Modus zu sein bedeutet nicht, dass der Standard-Streams nicht verwendet werden. Aber in diesem Fall ist Bash höchstwahrscheinlich laufen in nicht -interactive-Modus (es erfasst wird, dass es nicht spricht direkt mit dem Terminal-Anwendung, so nimmt es verwendet programmatisch ist, und daher nicht die nicht gedruckt werden begrüßen banner). In diesem Fall ist der Standard-Streams immer noch verwendet werden, es ist nur, dass nichts ausgegeben wird.

Wie ergosys ausgeführt hat, kann man nicht wirklich vertrauen auf in.read(new byte[1024]) Rückkehr, bevor es hat das volle 1024 Bytes lesen, obwohl es wahrscheinlich in Ordnung ist anzunehmen, dass es - aber es wird sicherlich nicht zurückkehren, bevor sie mindestens eine gelesen hat Byte, und ich denke, dass hier das Problem ist - du bist nicht einmal ein Byte Ausgang bekommen

.

Versuchen Sie, „i“ zu bash vorbei, um es im interaktiven Modus ausgeführt werden.

Andere Tipps

Jedes Programm, die c-Standard-Bibliothek sagen kann, ob es zu einem tty-Gerät spricht (a.k.a Kommandozeile) mit der Funktion isatty (). Bash erkennt wahrscheinlich, dass es zu einem Rohr spricht anstelle eines tty und nicht ausgibt eine Aufforderung.

Ich bin eher ein Python-Typ als ein Java-Typ (so alles, was ich Ihnen sagen, schnell Vermutungen von JavaDoc), aber es sieht aus wie Sie die Einrichtung einen Multi-Prozess-Deadlock auf.

in.read(new byte[1024]); wird nicht zurückkehren, bis es 1024 Bytes von Daten lesen und bash.exe nicht ausgibt ein ganzes 1024 Bytes vor für die Eingabe zu warten, zu stoppen. (Um das zu tun, verwendet proc.getOutputStream() und er einige Befehle zu reagieren.)

Als Ergebnis erhalten Sie Java warten auf bash zu reagieren und bash für Java zu reagieren warten und beide vollkommen zufrieden bis zum Tod des Universums zu warten, ohne dass es langweilig oder müde zu werden.

Mein Rat an Gebrauch ist in.available() vor jedem Anruf zu in.read() nicht blockiert. Auf diese Weise können Sie hin- und herschalten zwischen den Daten in der Fütterung und es, ohne stecken zu bleiben ziehen.

In der Tat wäre es wahrscheinlich viel einfacher und vernünftigere sein, nur es in wickeln BufferedReader .

Update von Kommentar: Auch wenn Tools wie bash, dass stdin erkennen ist kein Terminal (den isatty Systemaufruf sehen), puffern sie in großen (4K oder mehr) Stücke auf der Annahme, dass der Eingang nicht-interaktiven . Ich bin mir nicht sicher, ob es hilft, aber versuchen bash mit dem Flag -i starten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top