Wie kann ich Lesen Sie die Ergebnisse der system () - Aufruf in C++?
Ich bin mit dem folgenden code zu versuchen, Lesen Sie die Ergebnisse einer df
Befehl in Linux mit popen
.
#include <iostream> //file and std I/O functions
int main(int argc, char** argv) {
FILE* fp;
char * buffer;
long bufSize;
size_t ret_code;
fp = popen("df", "r");
if(fp == NULL) { //head off errors reading the results
std::cerr << "Could not execute command: df" << std::endl;
exit(1);
}
//get the size of the results
fseek(fp, 0, SEEK_END);
bufSize = ftell(fp);
rewind(fp);
//allocate the memory to contain the results
buffer = (char*)malloc( sizeof(char) * bufSize );
if(buffer == NULL) {
std::cerr << "Memory error." << std::endl;
exit(2);
}
//read the results into the buffer
ret_code = fread(buffer, 1, sizeof(buffer), fp);
if(ret_code != bufSize) {
std::cerr << "Error reading output." << std::endl;
exit(3);
}
//print the results
std::cout << buffer << std::endl;
//clean up
pclose(fp);
free(buffer);
return (EXIT_SUCCESS);
}
Dieser code gibt mir ein "Memory Fehler" mit einem exit-status '2', so kann ich sehen wo es fehlschlägt, ich verstehe einfach nicht warum.
Lege ich diese zusammen aus der Beispiel-code den ich gefunden habe auf Ubuntu-Foren und C++ - Referenz, also ich bin nicht verheiratet. Wenn jemand vorschlagen kann, einen besseren Weg, um Lesen Sie die Ergebnisse der system () - Aufruf, ich bin offen für neue Ideen.
BEARBEITEN, um das original: Okay, bufSize
wird, kommen negative, und jetzt verstehe ich, warum. Sie können nicht zufällig Zugriff auf ein Rohr, wie ich naiverweise versucht, das zu tun.
Kann ich nicht die erste person, um zu versuchen, dies zu tun. Kann jemand (oder zeigen Sie mir ein Beispiel dafür zu Lesen, die Ergebnisse von einem system () - Aufruf in eine variable in C++?
Danke. Ich bearbeitet die Frage, um zu versuchen und zu klären.
InformationsquelleAutor Bill the Lizard | 2008-11-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Warum würde
std::malloc()
scheitern?Der offensichtliche Grund ist, "weil
std::ftell()
zurückgegebenen negativen Zahl unterzeichnet, die wurde dann behandelt wie eine riesige Zahl ohne Vorzeichen".Laut die Dokumentation,
std::ftell()
gibt -1 bei einem Fehler. Ein offensichtlicher Grund wäre es fail ist, dass Sie nicht versuchen, in eine pipe oder FIFO.Gibt es kein entkommen; Sie können nicht wissen, die Länge der Ausgabe des Befehls, ohne es zu Lesen, und Sie können nur einmal gelesen. Sie Lesen müssen, um es in Stücke, die entweder das Wachstum Ihres Puffers als notwendig oder Analyse von on-the-fly.
Aber, natürlich, können Sie einfach vermeiden, die ganze Angelegenheit direkt mit dem system call
df
wahrscheinlich benutzt, um seine Informationen:statvfs()
.Akzeptiert, weil ich landete Verschrottung meine ursprüngliche Lösung und verwendet statvfs() für einen erheblichen Teil meines Problems statt. Danke. 🙂
InformationsquelleAutor CesarB
Du machst dieses alles zu schwer. popen(3) gibt eine regelmäßige alten
FILE *
für eine standard-pipe-Datei, was zu sagen ist, newline beendet Aufzeichnungen. Sie können es mit sehr hoher Effizienz durch die Verwendung von fgets(3) wie so in C:In C++ ist es sogar noch einfacher --
Es gibt einige weitere Fehler-handling gibt es, aber das ist die Idee. Der Punkt ist, dass Sie behandeln die
FILE *
aus popen wie alleFILE *
, und Lesen Sie es Zeile für Zeile.InformationsquelleAutor Charlie Martin
Ich bin mir nicht sicher, kann man fseek/ftell Rohr-streams wie dieses.
Haben Sie überprüft den Wert von bufSize ? Ein Grund malloc fehl werden, ist für wahnsinnig Größe Puffer.
Das Zurückspulen eines Rohres scheint nicht viel Sinn!
Das ist es, was ich für Sie versuchen zu kombinieren, zwei ausländische Stücke von code. 🙁
InformationsquelleAutor arul
(Ein Hinweis zur Terminologie: "system call" in Unix-und Linux-in der Regel bezieht sich auf den Aufruf einer kernel-Funktion aus der user-space-code. Sich auf ihn als "das Ergebnis einer
system()
call" oder "die Ergebnisse einersystem(3)
call" wäre klarer, aber es würde wohl besser sein, einfach zu sagen: "die Erfassung der output eines Prozesses.")Sowieso, Sie können Lesen, ein Prozess, der Ausgabe, so wie Sie sich Lesen Sie jede andere Datei. Speziell:
pipe()
,fork()
, undexec()
. Dies gibt Ihnen einen Datei-Deskriptor, dann können Sie eine Schleife verwenden, umread()
von der file-descriptor in einen Puffer undclose()
die den Datei-descriptor, wenn Sie fertig sind. Dies ist der niedrigste Wert der option und gibt Ihnen die meiste Kontrolle.popen()
, wie du tust. Dies gibt Ihnen eine Datei-stream. In einer Schleife, die Sie Lesen können verwenden, aus dem Datenstrom in eine temporäre variable oder Puffer mitfread()
,fgets()
oderfgetc()
als Zarawesome Antwort zeigt, dann Prozess -, Puffer-oder Anhängen einer C++ - string.popen()
, dann verwenden Sie die nicht-Standard - __gnu_cxx::stdio_filebuf zu wickeln, dann erstellen Sie einestd::istream
von derstdio_filebuf
und behandeln diese wie jede andere C++ - stream. Dies ist die C++-ähnlichen Ansatz. Hier ist Teil 1 und Teil 2 ein Beispiel für diesen Ansatz.InformationsquelleAutor Josh Kelley
Dank an alle, die sich die Zeit nahmen zu Antworten. Ein Kollege wies mich auf die ostringstream Klasse. Hier einige Beispiel-code, der tut im Grunde das, was ich versuchte zu tun, in der ursprünglichen Frage.
InformationsquelleAutor Bill the Lizard
Antwort auf die Frage im update:
Wäre dies genug?
"buffer[1024]" idiom heißt "C-Programmierer-Krankheit" und ist die Ursache für ungezählte Anzahl von Sicherheitslücken. Allerdings ist es sehr bequem, in einfachen Fällen.
InformationsquelleAutor Arkadiy
Erste Sache zu prüfen, ist der Wert von bufSize - wenn das passiert, werden <= 0, sind die Chancen, dass malloc eine NULL zurück, wie Sie versuchen zu reservieren eines Puffers der Größe 0 an diesem Punkt.
Andere Abhilfe wäre zu Fragen, malloc zu liefern, die Sie mit einem Puffer der Größe (bufSize + n) mit n >= 1, das sollte arbeiten, um dieses spezielle problem.
Davon abgesehen, ist der code, den Sie geschrieben ist reines C, kein C++, also darunter ist übertreiben es ein wenig.
InformationsquelleAutor Timo Geusch
überprüfen Sie Ihre bufSize.
ftell
zurückkehren können, -1 bei Fehler, und dies kann dazu führen, nonallocation von malloc mit Puffer mit einem NULL-Wert.Den Grund für die
ftell
zu Versagen ist, weil die popen. Kippe Sie suchen Rohre.InformationsquelleAutor flolo
Rohre sind nicht random-access. Sie sind sequentiell, was bedeutet, dass, sobald Sie Lesen ein byte, das Rohr wird nicht senden Sie es an Sie wieder. Was bedeutet, dass, offensichtlich, kann man nicht Zurückspulen.
Wenn Sie nur wollen, um die Ausgabe der Daten an den Benutzer ausgegeben werden, können Sie nur so etwas wie:
Diese ziehen bytes aus dem df-Rohr, eins nach dem anderen, und die Pumpe direkt in die Ausgabe.
Nun, wenn Sie wollen, um den Zugriff auf die df-Ausgabe als ganzes, können Sie entweder die pipe in eine Datei und diese Datei Lesen, oder verketten Sie die Ausgabe in ein Konstrukt wie ein C++ - String.
InformationsquelleAutor zaratustra