2010-01-18 6 views
6

Ich rufe Befehlszeilenprogramme auf, die über Pipes verbunden sind. All das funktioniert sicher unter Linux.Java exec() gibt das erwartete Ergebnis der verbundenen Befehle der Pipes nicht zurück

Meine Methode:

protected String execCommand(String command) throws IOException { 
    String line = null; 
    if (command.length() > 0) { 
     Process child = Runtime.getRuntime().exec(command); 
     InputStream lsOut = child.getInputStream(); 
     InputStreamReader r = new InputStreamReader(lsOut); 
     BufferedReader in = new BufferedReader(r); 

     String readline = null; 
     while ((readline = in.readLine()) != null) { 
      line = line + readline; 
     } 
    } 

    return line; 
} 

Wenn ich etwas Katze Aufruf der Datei | grep asd, ich bekomme das erwartete Ergebnis. Aber nicht alle Befehle funktionieren korrekt. Zum Beispiel mit diesem:

cat /proc/cpuinfo | wc -l 

oder dies:

cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr($2, 2, length($2))} 

die Methode null zurück. Ich vermute, dieses Problem hängt von der Ausgabe Formatierung Befehle wie Kopf, Schwanz, WC, etc. Wie kann ich umgehen dieses Problem und das Endergebnis der Ausgabe erhalten?

+1

Useless (verwendet * 3) von 'cat'. –

+0

@Dennis - tatsächlich. Gut beobachtet! –

+0

@Bobby Ich habe es versucht, das hilft nicht. – Pawka

Antwort

2

Noch keine richtige Lösung gefunden, pipeed Befehle mit Runtime.exec auszuführen, aber eine Umgehung gefunden. Ich habe diese Skripte einfach in separate Bash-Dateien geschrieben. Dann ruft Runtime.exec diese Bash-Skripte auf und erhält das erwartete Ergebnis.

+0

Dies ist die einzige Lösung, die ich über Google gefunden habe. Sie können Ihre eigene Antwort nicht akzeptieren? Wie auch immer, vielen Dank. –

+0

Sieht aus wie ich kann :-) – Pawka

8

Die Pipe (wie Umleitung, oder >) ist eine Funktion der Shell, und so wird die direkte Ausführung von Java nicht funktionieren. Sie tun müssen, um so etwas wie:

/bin/sh -c "your | piped | commands | here" 

, die mit der Befehlszeile ein Shell-Prozess ausführt (einschließlich Rohrleitungen) angegeben nach dem -c (in Anführungszeichen).

Beachten Sie auch, dass Sie stdout und stderrgleichzeitig, ansonsten wird ihr erzeugten Prozess für Ihren Prozess blockiert warten zu konsumieren haben die Ausgabe (oder Fehler) zu konsumieren. Weitere Informationen here.

+0

Thx für die Antwort, aber dies löst das Problem immer noch nicht. – Pawka

2

Jeder, der Runtime.exec verwendet, sollte this lesen.

0

Die schnelle und unsaubere Sache zu tun wäre:

command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'" 

Normalerweise werden Sie für Shell-Injektion achten müssen (das heißt jemand "; rm -rf /;" in den Befehl schleicht). Aber das ist nur ein Problem, wenn ein Teil des Befehls von einer anderen Benutzereingabe geliefert werden kann.

Der langsame und schmerzhafte Ansatz wäre, die Bash selbst in Java zu tun. Wenn Sie diesen Weg gehen, werden Sie alle wonderful things that Bash gives you finden, die nicht direkt von Process.exec (Pipes, Umleitung, Compound-Befehle, variable Erweiterung, arithmetische Auswertung, ...) verfügbar ist.

  1. Parsen Sie den Befehl für | Zeichen. Achte auf || und zitierte Strings.
  2. Spawn eine neue Process für jeden Piped-Befehl.
  3. Erstellen Sie Thread s, die die Ausgabe von einem Befehl lesen und sie an die Eingabe des nächsten Befehls schreiben.
0

Wahrscheinlich ein wenig zu spät, aber für andere nach einer Lösung suchen, versuchen Sie diese ...

String[] cmd = { 
         "/bin/sh", 
         "-c", 
         "cat /proc/cpuinfo | wc -l" 
        }; 

Process process = Runtime.getRuntime().exec(cmd); 

Alles Gute ..

Verwandte Themen