Shell Befehle mit Java aufrufen

Status
Nicht offen für weitere Antworten.

Katzwinkel

Mitglied
Ich habe ein Problem mit dem Aufrufen von Bash-Shell-Befehlen aus einem Java-Programm heraus.
Eigentlich erscheint es ja recht einfach, und klappt meistens auch:
Code:
RunTime rt=Runtige.getRuntime();
    Process p=rt.exec("Shell Befehl");
    p.waitFor();
Bei manchen Shell Befehlen scheint das Programm dann allerdings ewig auf das ende des Prozesses zu warten(Sprich: Es reagiert überhauptnicht mehr; in meinem Fall beim Aufruf des Programms gcphrap) obwohl der Prozess, wenn über die Shell aufgerufen, eigentlich nur wenige sekunden dauert.
Und was mich besonders verwirrt, der einfache "cat"-Befehl wird auf diese weise garnicht ausgeführt. Ich erhalte keine Fehlermeldung, der Rest des Programms läuft auch einwandfrei aber der cat-Befehl scheint einfach ignoriert worden zu sein. Lösen konnte ich das problem nur indem ich statt p.waitFor() Thread.sleep(2000) eingesetzt habe. Das erscheint mir aber extrem unlogisch und unschön. Kann mir jemand sagen woran das liegt?

hier mein versuch die Shell-Befehle aufzurufen der nicht klappt(obwohl es bei anderen Shell befehlen klappt):
Code:
public static void machfofn(String datei, File verz){

		System.out.println("fuehre gcphrap aus fuer Contig ./"+verz+"/"+datei+"...");
		Runtime rt = Runtime.getRuntime();
		try{
			Process p=rt.exec("gcphrap -exp ./"+verz+" -minmatch 20 ./"+verz+"/"+datei);
			p.waitFor();
			System.out.println("OK");
		}
		catch(Exception ex){
			System.out.println("gescheitert");
			ex.printStackTrace();
		}
		try{
			System.out.println("fuege exp-Liste zu fofn hinzu");
			System.out.println("cat ./"+verz+"/"+datei+".ph >>./"+verz+"/fofn");
			Process p=rt.exec("cat ./"+verz+"/"+datei+".ph >>./"+verz+"/fofn");
			p.waitFor();
			
		}
		catch(Exception ex){
			System.out.println("Fehler beim zusammenfuegen der fofn-Datei");
			ex.printStackTrace();
		}
	}
und hier die variante die funktioniert:
Code:
public static void machfofn(String datei, File verz){

		System.out.println("fuehre gcphrap aus fuer Contig ./"+verz+"/"+datei+"...");
		Runtime rt = Runtime.getRuntime();
		try{
			rt.exec("gcphrap -exp ./"+verz+" -minmatch 20 ./"+verz+"/"+datei);
			Thread.sleep(40000);
			System.out.println("OK");
		}
		catch(Exception ex){
			System.out.println("gescheitert");
			ex.printStackTrace();
		}
		try{
			System.out.println("fuege exp-Liste zu fofn hinzu");
			System.out.println("cat ./"+verz+"/"+datei+".ph >>./"+verz+"/fofn");
			rt.exec("cat ./"+verz+"/"+datei+".ph >>./"+verz+"/fofn");
			Thread.sleep(10000);
			
		}
		catch(Exception ex){
			System.out.println("Fehler beim zusammenfuegen der fofn-Datei");
			ex.printStackTrace();
		}
	}
 
Du musst Dir vom Prozess stdout und stderr holen und auslesen. Wenn Beispielsweise "cat" seine Ausgabe macht, schreibt es in den stdout bis der Puffer voll ist. Danach wartet es, bis der Puffer wieder Platz hat. Das passiert aber nie, da ja keine Konsole den Strom ausliest. Also muss das Dein Programm machen.

[ edit ] Alternativ kannst Du natürlich auch alle Befehle mit "2>&1 > /dev/null" aufrufen oder ähnliches.

Verstanden?
 
Danke, daran wirds liegen. Nur wie mach ich das am besten? (Bin echt noch totaler Anfänger im Programmieren).
Könnt das so aussehen:
Code:
BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
buf.flush()
Wie mache ich es wenn ich den inhalt des Puffers in eine art Log-Datei schreiben möchte?
Dann muesste ich doch den BufferedWriter der bereits mit dem OutputStreamwriter verkettet ist noch mit einem FileWriter veketten oder?
[/code]
 
im fall des cat befehls habe ich doch stdout berits umgeleitet oder? mein Befehl lautet ja vereinfacht:
cat Datei >>fofn-Datei
Wie kann da Ausgabe den Puffer blockieren? Oder ist der Puffer vielleicht durch die Ausgaben der vorher aufgerufenen Shell-Befehle blockiert und muss geflusht werden noch bevor ich den cat-Befehl aufrufe?
 
Katzwinkel hat gesagt.:
im fall des cat befehls habe ich doch stdout berits umgeleitet oder? mein Befehl lautet ja vereinfacht:
cat Datei >>fofn-Datei
Wie kann da Ausgabe den Puffer blockieren? Oder ist der Puffer vielleicht durch die Ausgaben der vorher aufgerufenen Shell-Befehle blockiert und muss geflusht werden noch bevor ich den cat-Befehl aufrufe?
Weiß ich auch nicht recht. Aber versuch doch erstmal bei allen Aufrufen stdout und stderr nach /dev/null zu leiten. Dann teste nochmal, ob's hängen bleibt. Wenn's immer noch hängen bleibt, gibt's noch nen anderen Fehler.

Ebenius
 
Katzwinkel hat gesagt.:
Danke, daran wirds liegen. Nur wie mach ich das am besten? (Bin echt noch totaler Anfänger im Programmieren).
Könnt das so aussehen:
Code:
BufferedWriter buf = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
buf.flush()
Wie mache ich es wenn ich den inhalt des Puffers in eine art Log-Datei schreiben möchte?
Dann muesste ich doch den BufferedWriter der bereits mit dem OutputStreamwriter verkettet ist noch mit einem FileWriter veketten oder?
[/code]

Da hast Du einen Denkfehler. Process.getOutputStream() gibt dir stdin. stdout bekommst Du mit Process.getInputStream() und stderr bekommst Du mit Process.getErrorStream(). Klingt logisch, wenn man darüber nachdenkt (obwohl die Benennung trotzdem besser sein könnte).

Ebenius
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben