Estoy buscando una manera de obtener la salida de un comando cuando se ejecuta desde un programa C ++. He visto el uso de la system()
función, pero eso solo ejecutará un comando. Aquí hay un ejemplo de lo que estoy buscando:
std::string result = system("./some_command");
Necesito ejecutar un comando arbitrario y obtener su salida. He visto boost.org , pero no he encontrado nada que me dé lo que necesito.
/programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
para una extensión de la gran respuesta siguiente que proporcione métodos para obtener elreturn code
ystderr
ademásstdout
que esta respuesta ya explicaRespuestas:
Versión anterior a C ++ 11:
Reemplazar
popen
ypclose
con_popen
y_pclose
para Windows.fuente
result += buffer
, por lo que es posible que la tubería no se cierre correctamente.int main(){ puts("ERROR"); }
.Obtener stdout y stderr (y también escribir en stdin, que no se muestra aquí) es fácil con mi encabezado pstreams , que define las clases iostream que funcionan como
popen
:fuente
popen
requiere que uses la API de C stdio, prefiero la API de iostreams.popen
requiere que limpie manualmente elFILE
controlador, pstreams lo hace automáticamente.popen
solo acepta unconst char*
argumento, que requiere cuidado para evitar ataques de inyección de shell, pstreams le permite pasar un vector de cadenas similar aexecv
, que es más seguro.popen
no le da más que una tubería, pstreams le dice el PID del niño que le permite enviar señales, por ejemplo, matarlo si está bloqueado o no sale. Todas esas son ventajas, incluso si solo desea IO unidireccional.pstreambuf::in_avail()
, por lo que no se bloquea. Eso permite la demultiplexación en stdout y stderr del proceso, ya que cada uno tiene datos disponibles.pstreambuf::in_avail()
solo funciona al 100% de manera confiable si el sistema operativo admite el ioctl no estándar de FIONREAD, pero eso es compatible con (al menos) GNU / Linux y Solaris.Yo usaría popen () (++ waqas) .
Pero a veces necesitas leer y escribir ...
Parece que ya nadie hace las cosas de la manera difícil.
(Suponiendo un entorno Unix / Linux / Mac, o tal vez Windows con una capa de compatibilidad POSIX ...)
También es posible que desee jugar con select () y lecturas sin bloqueo.
fuente
execlp
llamada tiene un error: el últimoarg
puntero pasado debe ser(char *) NULL
para terminar correctamente la lista de argumentos variables (verexeclp(3)
para referencia).Para Windows,
popen
también funciona, pero abre una ventana de consola, que parpadea rápidamente sobre su aplicación de IU. Si desea ser un profesional, es mejor deshabilitar este "parpadeo" (especialmente si el usuario final puede cancelarlo).Así que aquí está mi propia versión para Windows:
(Este código está parcialmente recombinado a partir de ideas escritas en The Code Project y muestras de MSDN).
fuente
wchar_t
yCreateProcessW
como una restricción innecesaria.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.
por lo tanto, tal vez sea mejor copiar la línea de comando en un búfer separado primero, para evitar que la persona que llama cambie su entrada original.Dos posibles enfoques:
No creo que
popen()
sea parte del estándar C ++ (es parte de POSIX de la memoria), pero está disponible en todos los UNIX con los que he trabajado (y parece que estás apuntando a UNIX ya que tu comando lo está./some_command
).En el caso de que no exista
popen()
, puede usarsystem("./some_command >/tmp/some_command.out");
, luego use las funciones normales de E / S para procesar el archivo de salida.fuente
Lo siguiente podría ser una solución portátil. Sigue los estándares.
fuente
tmpnam
es peligroso, mejor usomkstemp
"No pude entender por qué falta popen / pclose en Code :: Blocks / MinGW. Así que solucioné el problema usando CreateProcess () y CreatePipe () en su lugar.
Aquí está la solución que funcionó para mí:
fuente
CREATE_NO_WINDOW
cosita?ListStdErr
nunca se usaSuponiendo POSIX, código simple para capturar stdout:
Las contribuciones de código son bienvenidas para una mayor funcionalidad:
https://github.com/ericcurtin/execxx
fuente
Puede obtener el resultado después de ejecutar un script utilizando una tubería. Usamos tuberías cuando queremos la salida del proceso hijo.
Así que aquí está el script, que desea ejecutar. Póngalo en una variable de comando con los argumentos que toma su secuencia de comandos (nada si no hay argumentos). Y el archivo donde desea capturar la salida del script, póngalo en copy_fp.
Entonces, popen ejecuta su script y pone la salida en fpipe y luego puede copiar todo, desde eso a su archivo de salida.
De esta manera, puede capturar los resultados de los procesos secundarios.
Y otro proceso es que puedes poner directamente
>
operador solo en el comando. Entonces, si colocaremos todo en un archivo mientras ejecutamos el comando, no tendrá que copiar nada.En ese caso, no hay necesidad de usar tuberías. Puede usar just
system
, y ejecutará el comando y colocará la salida en ese archivo.Puede leer el Tutorial de YoLinux: Fork, Exec y Control de procesos para obtener más información.
fuente
Tenga en cuenta que puede obtener salida redirigiendo la salida al archivo y luego leyéndola
Se mostró en la documentación de
std::system
Puede recibir el código de salida llamando a
WEXITSTATUS
macro.fuente