Jede Ausgabe von Terminal auslesen

Ich weiß leider nicht so genau wie ich diese Frage richtig stellen soll, deshalb hab ich darunter auch nichts gefunden.

Ich hab ein Programm geschrieben, in dem mehrere forks und system Befehle sind, jetzt möchte ich, im Prinzip ALLES was im Terminal bei Programmstart erscheint auslesen. Momentan wollte ich das ganze so regeln:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
	FILE*fd=popen("cd pfad/zur/datei && ./datei", "r");
	char buffer[200]="";
	
	while (fgets(buffer, 200, fd))
	{
		printf("*%s*", buffer);
	}
	
	return 0;
}

Das funktioniert auch. Aber leider nur bei den Ausgaben die ich selber verursache, also z.B. wenn ich einen Befehl (im Hauptprogramm) im fork prozess mit einem system Befehl ausführe und dieser z.B. ein Fehler verursacht, dass man nur als root Rechte dafür hat, dann bekomme ich diese Meldung nicht in meinen Buffer.

Also ich hoffe das kann man überhaupt verstehen so wie ich das geschrieben hab :D

Die Frage ist also nun mehr oder weniger, wie ich (egal wie), wirklich ALLES was ich im Terminal sehe in den buffer bekomme, also auslesen kann? Geht das überhaupt?

Danke für jede Hilfe
 
Also ich hoffe das kann man überhaupt verstehen so wie ich das geschrieben hab :D

Ich tu mir etwas hart :P

Du liest doch hier nur eine Datei aus. Wo werden denn die System-Befehle ausgeführt?

Es klingt aber so als würdest du nur alle stdout mitbekommen und nicht stderr. Die Ausgabe auf die Konsole kann über diese beiden Streams(?) von statten gehen.

Wenn du nen Befehl ausführst und beide Streams in einer Datei haben willst müsst das in etwa so aussehen:
Code:
befehl >/pfad/datei 2>/pfad/datei
(Wenn nicht findest du dazu bei Google mehr infos)
 
Code:
FILE*fd=popen("cd pfad/zur/datei && ./datei 2>&1", "r");

So müsste es bei dir genau heißen. Habs ausprobiert und es geht.

Jaja, die Pipes und Streams und wie sie alle heißen :P
 
Hey Jung super es klappt :P

Ich hätte vllt noch erwähnen können, das die Datei in meine Befehl keine gewöhnliche Datei ist, sondern eine weitere sehr komplexe C Datei. Und in der sind die system Befehle, mit "system" Befehle meinte ich

Code:
system ();

Aber es klappt, nebenbei versteh ich zwar rein technisch die Lösung nicht so ganz, aber das ist ja hin und wieder nicht so schlimm^^

Muss an dieser Stelle auch mal erwähnen, das man in diesem Forum echt immer in kürzester Zeit sehr produktive Antworten bekommt wobei es sich fast um jede Frage handeln kann.

THX
 
Hm, jetzt hätte ich vllt doch noch eine Frage zu diesem Thema:

Wie könnte ich jetzt genau den gleiche Effekt nur in der direkten C Datei erzielen?
Also anstatt das über diese extra Datei zu machen direkt in der C Datei die gestartet wird.

Das Endziel ist im Prinzip, das ich in dem Hauptprogramm ein GtkTextView hab worin die ganze Terminal Ausgabe angezeigt werden soll. Das Problem ist, das die Ausgaben sehr unterschiedlich sind

1. Hab ich öfters g_print drin, das soll auch im Textview erscheinen
2. berschieden system() prozesse die im fork gestartet werden und die auch manchmal Fehler verursachen könnten, diese sollen auch in der TextView stehen
3. Und eben noch Fehler odda Meldungen vom Programm an sich

Also praktisch alles, was man im Terminal sehen kann.
Mit der Lösung wie sie mir nun gegeben wurde geht das, aber dann kann ich von dem Hauptprogramm das TextView nicht ansteuern.
 
Nimm dir doch einfach mal den Source eines Terminal-Emulators (z.B. von Gnome-Terminal, xterm, konsole etc.) und schau dir an, wie es dort gelöst ist. Alternativ lässt du die via system() aufgerufenen Programme direkt in eine Pipe schreiben, die an dein Programm pipe't und liest dann direkt aus der Pipe.
 
was du suchst hat odigo bereits genannt ... popen()

popen() gibt dir einen filepointer den du lesen und ggf. beschreiben kannst, um die kommunikation mit dem aufgerufenen prozess durchzuführen ... beim aufruf des befehls, gelten wie odigo bereits erwähnte die normalen redirect möglichkeiten für die std streams ...

wenn du aus irgend einem grund die ausgabe eines bereits gestarteten programms umleiten musst, hilft dir nur noch ein debugger ...

der debugger sollte dir erlauben einen aufruf wie dup2(*neuerFILEptr,2) im kontext des jeweiligen prozesses abzusetzen und somit hier beispielsweise stderr für den jeweiligen prozess auf den neuen filepointer umzubiegen...
unnötig zu erwähnen, dass sowas eigentlich nicht vorgesehen ist, und eher unter schwarz-, naja, sagen wir grau-magischen ritualen einzuordnen ist, und mitunter auch unerwartete folgen haben kann ... aber manchmal brauchts halt solche griffe in die trick kiste
 
Ja, die Sache ist nur, das ich das dup2 und verschiedene system Befehle schon ziemlich häufig benutzt hab, und ich das eig. nicht noch mal alles umschreiben wollte, das es einige befehle sind. Ich wollte es jetzt mit dem vte terminal probieren, das kann man ja super als Widget benutzen. Aber jetzt ist mir aufgefallen, dass in das Widget ja immer ein neues Terminal gemacht wird. Gibt es ein Befehl für vte, der im Prinzip das Terminal in dem das Programm gestartet wird, als vte Terminal im Widget anzeigt? Hab schon wie verrückt gegoogelt, aber über das vte allgemein findet man nicht so viel.
 
ja ... warum einfach, wenns auch kompliziert geht ...

gehen wir mal davon aus, das deine system() aufruf-ziele keine wirkliche interaktion erfordern...

wo liegt das problem jeden system() aufruf so wie er ist zu ersetzen?

was du dafür brauchst ist eine funktion die den jeweiligen parameter übernimmt, ggf. ein änhängsel baut wie "2>&1" und das ganze an popen() übergibt ... vom zurückgegebenen file handle ließt du alle anstehenden daten, und wirfst diese aus wo auch immer du willst ... die umbauten an deinem programm dürften sich dann im wesentlichen, abgesehen von besagter funktion und ggf. der ausgabe stelle, auf die ersetzung von system() aufrufen beschränken ... eine aufgabe für die regex engine deines vertrauens ...
 
gehen wir mal davon aus, das deine system() aufruf-ziele keine wirkliche interaktion erfordern...

Doch leider schon, es ist ganz bunt gemischt, ich hab teilweise ein paar ping befehle drin, die mal länger und mal kürzer abgerufen werden je nach Benutzereinstellung. Hab ein paar logging Funktionen die mal an und mal aus sind je nach Benutzereinstellungen und jede Menge forks die mal aus und wieder angeschalten werden, ich glaub es würde komplizierter werden das alles zu ersetzen, besonders da ich nicht nur system() befehle habe sondern auch execl und vieles mehr...

Gut nebenbei hätte ich mir vllt früher überlegen sollen, das ich das so haben will und gleich alles präparieren sollen, aber wäre super, wenn ich das jetzt noch irgendwie lösen könnte.

Ich fande Lösung ganz am Anfang das ich die gesammten Ausgaben über ein anderes erstes Programm dass dann das Hauptprogramm öffnet auslese und dann eben in ein ganz normales TextView schreibe. Das hat ja auch prinzipiell super geklappt nur das ich die ausgelesenen Ausgaben vom ersten Programm nicht mehr in das TextView vom Hauptprogramm rein bekomme.

Könnte man vllt bei diesem Weg ansetzen?

Schon mal Danke für jede Bemühung
 
ich weiß ja nicht was du unter interaktion verstehst, aber es geht um eingaben zur laufzeit ...


die aufgerufenen prozesse sollten vom aufrufenden prozess die std streams (fd 0 1 2) erben daher kannst du versuchen diese vor dem aufruf der anderen programme zu ändern ...
 
Hm, ich weiß noch nicht, ob ich jetzt alles verstanden habe^^

Ich weiß nicht ob das ein Problem ist, aber ich hab auch bei vielen system Befehlen schon ein dup2 davor, oder popen schon anderweitig benutzt, ist das ein Problem? Also gerade bei dem dup2?

Aber ich glaub ich versteh doch langsam, wie es gemint ist, es müsste ja jetzt eig. damit funktionieren, das ich die ausgelesenen Daten mit denen ich schon was anstelle einfach noch mal an eine Funktion schicke, die es dann in das GtkView schreibt...

Ich werden mal ein bisschen was testen...
 
es ist allgemein ratsam die funktionen die man verwendet auch zu kennen ...

"ich hab hier ein dup2 ..." ist eine herrlich kontext abhänige aussage, deren informationsgehalt ohne näheren zusammenhang von "mau" bis "nicht vorhanden" reicht ...

selbiges gilt für dein popen ...

grundsätzlich gilt: nur weil du eine funktion schonmal verwendet hast, schließt das die nochmalige verwendung nicht kategorisch aus ...
 
Zurück
Oben