Estoy tratando de iniciar una aplicación externa a través de system()
- por ejemplo, system("ls")
. Me gustaría capturar su salida a medida que sucede, así puedo enviarla a otra función para su posterior procesamiento. ¿Cuál es la mejor manera de hacerlo en C/C++?Captura de stdout de un comando de sistema() de manera óptima
Respuesta
No estoy del todo seguro de que sea posible en el estándar C, ya que dos procesos diferentes normalmente no comparten espacio de memoria. La forma más sencilla en que se me ocurre hacerlo es hacer que el segundo programa redirija su salida a un archivo de texto (nombre de programa> archivo de texto.txt) y luego volver a leer ese archivo de texto para procesarlo. Sin embargo, esa puede no ser la mejor manera.
EDITAR: leyó mal la pregunta como querer pasar la salida a otro programa, no a otra función. popen() es casi seguramente lo que quieres.
El sistema le da acceso completo a la carcasa. Si desea continuar usándolo, puede redirigir su salida a un archivo temporal, por sistema ("ls> tempfile.txt"), pero elegir un archivo temporal seguro es un problema. O bien, puede incluso redirigirlo a través de otro programa: system ("ls | otherprogram");
Algunos pueden recomendar el comando popen(). Esto es lo que quiere si se puede procesar la salida de sí mismo:
FILE *output = popen("ls", "r");
que le dará un apuntador de archivo se puede leer en la salida del comando en él.
También puede utilizar la tubería() para crear una conexión en combinación con un tenedor() para crear nuevos procesos, dup2() para cambiar la entrada estándar y la salida de ellos, exec() para ejecutar los nuevos programas, y espere() en el programa principal para esperarlos. Esto simplemente está configurando la tubería de manera similar a como lo haría el caparazón. Consulte la página man de pipe() para obtener detalles y un ejemplo.
En Windows, en lugar de usar system(), use CreateProcess, redirija la salida a una tubería y conéctela a la tubería.
Supongo que esto también es posible de alguna manera POSIX?
Desde el manual popen:
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
ARCHIVO * stream = popen (comando const char *, tipo const char *); – Arpith
Me gustaría agregar que esto solo funcionará en los sistemas de Posix. En mi versión de Windows 7 no hay función popen, pero hay un _popen que funciona. – user1505520
Pruebe la función popen(). Ejecuta un comando, como system(), pero dirige el resultado a un nuevo archivo. Se devuelve un puntero a la secuencia.
FILE *lsofFile_p = popen("lsof", "r");
if (!lsofFile_p)
{
return -1;
}
char buffer[1024];
char *line_p = fgets(buffer, sizeof(buffer), lsofFile_p);
pclose(lsofFile_p);
Las funciones popen()
y pclose()
podría ser lo que estás buscando.
Eche un vistazo a glibc manual para un ejemplo.
Las funciones popen()
y tales no redireccionan stderr y tal; Escribí popen3()
para ese propósito.
En realidad, acabo de comprobar, y:
popen es problemático, ya que el proceso se bifurca. Entonces, si necesita esperar a que se ejecute el comando de shell, entonces está en peligro de perderlo. En mi caso, mi programa se cerró incluso antes de que la tubería hiciera su trabajo.
Terminé usando sistema de llamada con comando tar en Linux. El valor de retorno de sistema fue el resultado de tar.
Así: si necesita el valor de retorno, entonces no hay sólo no hay necesidad de utilizar popen, probablemente no va a hacer lo que quiere.
La pregunta solicita capturar la * salida *, no el * código de salida *. Entonces, no creo que surja el problema que mencionas. –
eso es para lo que la familia wait (...) de llamadas al sistema es para. Esperan a que finalice el proceso de su hijo, para que pueda obtener su resultado. "man -s2 wait" –
En esta página: capture_the_output_of_a_child_process_in_c describe las limitaciones del uso de popen frente al enfoque fork/exec/dup2/STDOUT_FILENO.
Tengo problemas capturing tshark output with popen.
y supongo que esta limitación podría ser mi problema:
Devuelve una corriente stdio en contraposición a un descriptor de archivo en bruto, que no es adecuado para el manejo de la salida de forma asíncrona.
Volveré a esta respuesta si tengo una solución con el otro enfoque.
La manera más eficaz es utilizar stdout
descriptor de archivo directamente, sin pasar por FILE
corriente:
pid_t popen2(const char *command, int * infp, int * outfp)
{
int p_stdin[2], p_stdout[2];
pid_t pid;
if (pipe(p_stdin) == -1)
return -1;
if (pipe(p_stdout) == -1) {
close(p_stdin[0]);
close(p_stdin[1]);
return -1;
}
pid = fork();
if (pid < 0) {
close(p_stdin[0]);
close(p_stdin[1]);
close(p_stdout[0]);
close(p_stdout[1]);
return pid;
} else if (pid == 0) {
close(p_stdin[1]);
dup2(p_stdin[0], 0);
close(p_stdout[0]);
dup2(p_stdout[1], 1);
dup2(::open("/dev/null", O_WRONLY), 2);
/// Close all other descriptors for the safety sake.
for (int i = 3; i < 4096; ++i) {
::close(i);
}
setsid();
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1);
}
close(p_stdin[0]);
close(p_stdout[1]);
if (infp == NULL) {
close(p_stdin[1]);
} else {
*infp = p_stdin[1];
}
if (outfp == NULL) {
close(p_stdout[0]);
} else {
*outfp = p_stdout[0];
}
return pid;
}
Para leer la salida de niño uso popen2()
así:
int child_stdout = -1;
pid_t child_pid = popen2("ls", 0, &child_stdout);
if (!child_pid) {
handle_error();
}
char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));
Para tanto de escritura y léase:
int child_stdin = -1;
int child_stdout = -1;
pid_t child_pid = popen2("grep 123", &child_stdin, &child_stdout);
if (!child_pid) {
handle_error();
}
const char text = "1\n2\n123\n3";
ssize_t bytes_written = write(child_stdin, text, sizeof(text) - 1);
char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));
¿Es correcto dup2 (:: open ("/ dev/null", O_RDONLY), 2) ;? Parece más lógica dup2 (:: open ("/ dev/null", O_WRONLY), 2); –
@MelVisoMartinez, sí, sería más válido. – GreenScape
- 1. Captura de stdout al llamar a Runtime.exec
- 2. ¿Captura/redirecciona internamente stdout?
- 3. Encajando rectángulos de manera óptima
- 4. Captura/secuestro de stdout en haskell
- 5. Cluster de datos unidimensionales de manera óptima?
- 6. óptima para snaplen PCAP captura en vivo
- 7. Obtener la salida de un comando del sistema desde stdout en C
- 8. Captura stdout y stderr de un programa externo * mientras * está ejecutando (Rubí)
- 9. lectura de entrada de un comando del sistema en Haskell
- 10. ¿Cómo transponer una matriz de manera óptima usando blas?
- 11. ¿Cómo se obtiene el resultado de un comando del sistema en Go?
- 12. ¿Cómo obtener STDOUT de un QProcess?
- 13. Python: captura Popen stdout AND display en la consola?
- 14. Estructura óptima del sistema de archivos para el lenguaje de script Aplicaciones MVC
- 15. ¿Captura el valor de salida de un comando de shell en VBA?
- 16. ¿Cómo captura stderr, stdout y el código de salida de una sola vez en Perl?
- 17. ¿Cómo obtengo el STDOUT de una llamada al sistema ruby () mientras se está ejecutando?
- 18. Ejecutando un comando del sistema en Haskell
- 19. Configuración óptima de MySQL (my.cnf)
- 20. convención de nomenclatura de clase extendida óptima?
- 21. Comparación de matrices de objetos, forma óptima
- 22. La manera más óptima de analizar la cadena de consulta dentro de una cadena en C#
- 23. ¿cuál es el algoritmo para llenar de manera óptima un DVD para grabar
- 24. ¿Manera óptima de obtener una cadena o char * en un istream?
- 25. Captura de salida de proceso externo
- 26. Cómo identificar un sistema Mac de manera única
- 27. La mejor manera de hacer un sistema "hashtag"
- 28. Cómo ejecutar y capturar stdout del comando externo en Ruby usando system() sin escape de shell?
- 29. grupos de captura de sed
- 30. ¿Cómo encontrar la orden de procesamiento óptima?
¿A qué te refieres de manera óptima? De mi respuesta, diría que de manera óptima puede depender de cada situación. El enfoque fork/exec/dup2/STDOUT_FILENO puede ser adecuado para casos especiales. – nephewtom