Je cherche un moyen d'obtenir la sortie d'une commande lorsqu'elle est exécutée à partir d'un programme C ++. J'ai regardé en utilisant la system()
fonction, mais cela exécutera juste une commande. Voici un exemple de ce que je recherche:
std::string result = system("./some_command");
J'ai besoin d'exécuter une commande arbitraire et d'obtenir sa sortie. J'ai regardé boost.org , mais je n'ai rien trouvé qui puisse me donner ce dont j'ai besoin.
/programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
pour une extension de la grande réponse ci-dessous qui fournit des méthodes pour obtenir lereturn code
etstderr
ainsi questdout
que cette réponse explique déjàRéponses:
Version pré-C ++ 11:
Remplacez
popen
etpclose
par_popen
et_pclose
pour Windows.la source
result += buffer
, de sorte que le tuyau peut ne pas être correctement fermé.int main(){ puts("ERROR"); }
.Obtenir à la fois stdout et stderr (et aussi écrire dans stdin, non illustré ici) est facile avec mon en - tête pstreams , qui définit les classes iostream qui fonctionnent comme
popen
:la source
popen
vous oblige à utiliser l'API C stdio, je préfère l'API iostreams.popen
vous oblige à nettoyer manuellement laFILE
poignée, les pstreams le font automatiquement.popen
accepte uniquement unconst char*
pour l'argument, qui nécessite des précautions pour éviter les attaques par injection de shell, pstreams vous permet de passer un vecteur de chaînes similaire àexecv
, ce qui est plus sûr.popen
ne vous donne rien d'autre qu'un tuyau, pstreams vous indique le PID de l'enfant vous permettant d'envoyer des signaux, par exemple pour le tuer s'il est bloqué ou s'il ne sort pas. Ce sont tous des avantages même si vous ne souhaitez que des E / S unidirectionnelles.pstreambuf::in_avail()
, donc ne bloquera pas. Cela permet de démultiplexer les sorties standard et stderr du processus car chacun dispose de données.pstreambuf::in_avail()
ne fonctionne à 100% de manière fiable que si le système d'exploitation prend en charge l'ioctl FIONREAD non standard, mais qui est pris en charge sur (au moins) GNU / Linux et Solaris.J'utiliserais popen () (++ waqas) .
Mais parfois, il faut lire et écrire ...
Il semble que plus personne ne fasse les choses à la dure.
(En supposant un environnement Unix / Linux / Mac, ou peut-être Windows avec une couche de compatibilité POSIX ...)
Vous pouvez également vouloir jouer avec les lectures select () et non bloquantes.
la source
execlp
appel a un bug: le dernierarg
pointeur passé doit être(char *) NULL
pour terminer correctement la liste des arguments variadiques (voirexeclp(3)
pour référence).Pour Windows,
popen
fonctionne également, mais il ouvre une fenêtre de console - qui clignote rapidement sur votre application d'interface utilisateur. Si vous voulez être un professionnel, il est préférable de désactiver ce "clignotant" (surtout si l'utilisateur final peut l'annuler).Voici donc ma propre version pour Windows:
(Ce code est partiellement recombiné à partir d'idées écrites dans les exemples The Code Project et MSDN.)
la source
wchar_t
etCreateProcessW
comme une restriction inutile.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.
il est donc peut-être préférable de copier la ligne de commande dans un tampon séparé d'abord, pour empêcher l'appelant de changer son entrée d'origine.Deux approches possibles:
Je ne pense pas que cela
popen()
fasse partie de la norme C ++ (cela fait partie de POSIX de la mémoire), mais il est disponible sur tous les UNIX avec lesquels j'ai travaillé (et vous semblez viser UNIX depuis que votre commande l'est./some_command
).Au cas où il n'y en aurait pas
popen()
, vous pouvez utilisersystem("./some_command >/tmp/some_command.out");
, puis utiliser les fonctions d'E / S normales pour traiter le fichier de sortie.la source
Ce qui suit pourrait être une solution portable. Il suit les normes.
la source
tmpnam
est dangereuse, mieux vaut l'utilisermkstemp
"Je n'ai pas pu comprendre pourquoi popen / pclose est absent de Code :: Blocks / MinGW. J'ai donc contourné le problème en utilisant CreateProcess () et CreatePipe () à la place.
Voici la solution qui a fonctionné pour moi:
la source
CREATE_NO_WINDOW
truc?ListStdErr
n'est jamais utilisé.En supposant POSIX, un code simple pour capturer la sortie standard:
Les contributions de code sont les bienvenues pour plus de fonctionnalités:
https://github.com/ericcurtin/execxx
la source
Vous pouvez obtenir la sortie après avoir exécuté un script à l'aide d'un canal. Nous utilisons des tuyaux lorsque nous voulons la sortie du processus enfant.
Voici donc le script que vous souhaitez exécuter. Mettez-le dans une variable de commande avec les arguments pris par votre script (rien si aucun argument). Et le fichier où vous souhaitez capturer la sortie du script, placez-le dans copy_fp.
Ainsi, le popen exécute votre script et met la sortie dans fpipe, puis vous pouvez simplement tout copier de cela dans votre fichier de sortie.
De cette façon, vous pouvez capturer les sorties des processus enfants.
Et un autre processus consiste à mettre directement l'
>
opérateur dans la commande uniquement. Donc, si nous mettons tout dans un fichier pendant que nous exécutons la commande, vous n'aurez rien à copier.Dans ce cas, il n'est pas nécessaire d'utiliser des tuyaux. Vous pouvez utiliser simplement
system
, et il exécutera la commande et mettra la sortie dans ce fichier.Vous pouvez lire le tutoriel YoLinux: Fork, Exec et Process control pour plus d'informations.
la source
Notez que vous pouvez obtenir une sortie en redirigeant la sortie vers le fichier, puis en la lisant
Il a été montré dans la documentation de
std::system
Vous pouvez recevoir le code de sortie en appelant une
WEXITSTATUS
macro.la source