Wie kann ich einen Befehl ausführen und erhalten Sie die Ausgabe von Befehl in C++, POSIX?
Ich bin auf der Suche nach einem Weg, um die Ausgabe eines Befehls auf, wenn es von einem C++ - Programm. Ich habe mit dem system () - Funktion, aber das wird nur einen Befehl ausführen. Hier ist ein Beispiel was ich Suche:
std::string result = system("./some_command");
Muss ich laufen, einen beliebigen Befehl und seine Ausgabe. Habe ich mir angeschaut Boost.org aber ich habe nichts gefunden das wird mir geben, was ich brauche.
- Siehe auch die Antworten in dieser Frage:
https://stackoverflow.com/questions/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
für eine Erweiterung der großen Antwort unten stellt Methoden bereit, um diereturn code
undstderr
sowiestdout
dass diese Antwort bereits erklärt
Du musst angemeldet sein, um einen Kommentar abzugeben.
Pre-C++11 version:
Ersetzen
popen
undpclose
mit_popen
und_pclose
für Windows.result += buffer
, also das Rohr kann nicht richtig geschlossen werden.bad_alloc
.int main(){ puts("ERROR"); }
."ERROR"
.while (!feof(...))
und einif
Anweisung in der Schleife, wenn alles, was Sie tun müssen, istwhile (fgets(...) != NULL)
?popen
undpclose
in_pclose
und_popen
scheint nicht genug bekommen, dieser läuft unter Windows (Produktion, wie Sie Schätze es,"popen() failed!"
), in der Erwägung, dass TarmoPikaro Lösung funktioniert.constexpr
auf die buffer-Größe, und vermeiden Sie die Angabe ein literal zweimal.while (!feof())
ist immer falsch, undfgets
ist ebenso falsch, wenn man nicht wirklich Lesen Zeilen. Verwendenfread
und den Rückgabewert überprüfen.Immer sowohl stdout und stderr (und auch das schreiben auf stdin, hier nicht gezeigt) ist einfach kinderleicht mit meiner pstreams header definiert, die iostream-Klassen, die wie
popen
:popen
erfordert die Verwendung der C stdio-API, ich bevorzuge die iostreams-API.popen
erfordert, dass Sie manuell zu bereinigen, dieFILE
Griff, pstreams machen das automatisch.popen
akzeptiert nur eineconst char*
für das argument, das erfordert Sorgfalt, um zu vermeiden, shell-injection-Angriffe, pstreams können Sie übergeben einen Vektor von Zeichenketten ähnlichexecv
, der sicherer ist.popen
gibt Sie nichts anderes als ein Rohr, pstreams erzählt Sie dem Kind die PID so dass Sie Signale senden, z.B. um es zu töten, wenn es blockiert oder nicht verlassen. All das sind Vorteile, auch wenn Sie nur einseitig IO.std::string
, das kann natürlich sein, initialisiert von einemchar*
)pstreambuf::in_avail()
, also nicht blockieren. Das ermöglicht demultiplexing auf den Prozess' stdout und stderr wie die einzelnen Daten zur Verfügung hat.pstreambuf::in_avail()
funktioniert nur 100% zuverlässig, wenn das OS das unterstützt die nicht-standard-FIONREAD ioctl, aber das unterstützt (mindestens) GNU/Linux und Solaris.pstreams
hat die notwendige Unterstützung. BTW,FIONREAD
ist auch in Windows verfügbar, für diejenigen, die über es.pstream
oderopstream
(nichtipstream
) und schreiben Sie es wie Sie schreiben, mitostream
.Ich würde verwenden popen() (++waqas).
Aber manchmal müssen Sie Lesen und schreiben...
Scheint es wie niemand tut Dinge auf die harte Weise mehr.
(Ausgehend von einem Unix - /Linux - /Mac-Umgebung, oder vielleicht Windows mit einem POSIX-Kompatibilität layer...)
Vielleicht möchten Sie auch zu spielen, um mit select() und nicht-blockierend liest.
execlp
- Aufruf ein Fehler: der Letztearg
Zeiger übergeben werden müssen(char *) NULL
ordnungsgemäß zu beenden, die variadic-argument-Liste (sieheexeclp(3)
für Referenz).Für Windows
popen
funktioniert auch, aber es öffnet sich ein Konsole-Fenster, die schnell blinkt über die Benutzeroberfläche der Anwendung. Wenn Sie möchten, um eine professionelle, es ist besser Sie zum deaktivieren dieses "blinken" (vor allem, wenn der end-Benutzer kann Abbrechen).So, hier ist meine eigene version für Windows:
(Dieser code teilweise neu zusammengesetzt aus Ideen, geschrieben in Das Code-Projekt - und MSDN-samples)
wchar_t
undCreateProcessW
als eine unnötige Einschränkung.The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
So ist es vielleicht besser, kopieren Sie die command-Zeile in einem separaten Puffer ersten, um zu verhindern, dass den Anrufer aus den ursprünglichen Eingang geändert.Können Sie die Boost.Prozess Bibliothek. Es ist nicht offiziell Teil der Boost aber. Ich habe gesehen, es funktioniert gut für andere. Leider steigern.Prozess-Fortschritte offenbar ins stocken geraten. pstreams ist anderen (scheinbar aktive) Projekt. Sicherlich einen Versuch Wert würde ich sagen - aber es ist nur für POSIX-kompatible Betriebssysteme.
Zwei mögliche Ansätze:
Ich glaube nicht, dass
popen()
ist Teil der C++ - standard (es ist Teil der POSIX-aus dem Gedächtnis), aber es ist auf jedem UNIX mit denen ich gearbeitet habe (und Sie scheinen auf UNIX, da Ihr Befehl ist./some_command
).Auf dem off-chance, dass es keine
popen()
verwenden, können Siesystem("./some_command >/tmp/some_command.out");
dann mit den normalen I/O-Funktionen zur Verarbeitung der Ausgabe-Datei.Folgende könnte eine tragbare Lösung. Es folgt standards.
tmpnam
is dangerous, better usemkstemp
"Ich konnte nicht herausfinden, warum popen/pclose fehlt Codeblocks/MinGW. So arbeitete ich, um das problem mit CreateProcess() und CreatePipe() statt. Hier ist die Lösung, die für mich gearbeitet:
CREATE_NO_WINDOW
Dingens?ListStdErr
ist nie benutzt.Vorausgesetzt, POSIX, einfachen code zu erfassen stdout:
Code-Beiträge sind willkommen für mehr Funktionalität:
https://github.com/ericcurtin/execxx