Estoy buscando un camino en C para programar (es decir, no usar la redirección de la línea de comandos) implementar la funcionalidad 'tee' de modo que mi stdout vaya tanto a stdout como a un archivo de registro. Esto debe funcionar tanto para mi código como para todas las bibliotecas vinculadas que dan salida a stdout. Alguna forma de hacer esto?¿Cómo puedo implementar 'tee' programáticamente en C?
Respuesta
Puede popen()
el programa de tee.
O puede fork()
y el tubo stdout
a través de un proceso hijo como este (adaptado de un verdadero programa en vivo que escribí, por lo que funciona!):
void tee(const char* fname) {
int pipe_fd[2];
check(pipe(pipe_fd));
const pid_t pid = fork();
check(pid);
if(!pid) { // our log child
close(pipe_fd[1]); // Close unused write end
FILE* logFile = fname? fopen(fname,"a"): NULL;
if(fname && !logFile)
fprintf(stderr,"cannot open log file \"%s\": %d (%s)\n",fname,errno,strerror(errno));
char ch;
while(read(pipe_fd[0],&ch,1) > 0) {
//### any timestamp logic or whatever here
putchar(ch);
if(logFile)
fputc(ch,logFile);
if('\n'==ch) {
fflush(stdout);
if(logFile)
fflush(logFile);
}
}
putchar('\n');
close(pipe_fd[0]);
if(logFile)
fclose(logFile);
exit(EXIT_SUCCESS);
} else {
close(pipe_fd[0]); // Close unused read end
// redirect stdout and stderr
dup2(pipe_fd[1],STDOUT_FILENO);
dup2(pipe_fd[1],STDERR_FILENO);
close(pipe_fd[1]);
}
}
+1 por no asumir nada (por ejemplo, el código anterior es fácilmente un adaptador para tomar un descriptor de archivo ya abierto en lugar de un nombre de archivo como argumento) – Michael
tee ("tee.txt "); sistema (" ftp "); -> no parece imprimir stdin o stdout alguna idea? – Victor
una vez que quité: if ('\ n' == ch) se imprime. Supongo que estaba esperando \ n. Ahora la función T parece estar atascada a menos que presione enter al final. – Victor
No hay manera trivial de hacer esto en C Sospecho que lo más fácil sería llamar a popen (3), con tee como el comando y el archivo de registro deseado como un arument, luego dup2 (2) el descriptor de archivo del FILE * recién abierto en fd 1.
Pero eso se ve feo y debo decir que NO lo he intentado.
Probé esto y causa condiciones de carrera. Un problema puede ser que el tee se imprima primero a veces. – PALEN
@PALEN Como dije, "no probado y se ve feo". Si está utilizando GNU libc, hay una funcionalidad para crear sus propios objetos similares a FILE * y podría usar eso, pero luego terminaría en unicability-land. – Vatine
Puede usar forkpty()
con exec()
para ejecutar el programa supervisado con sus parámetros. forkpty()
devuelve un descriptor de archivo que se redirige a los programas stdin y stdout. Lo que está escrito en el descriptor de archivo es la entrada del programa. Lo que está escrito por el programa se puede leer desde el descriptor de archivo.
La segunda parte es leer en un bucle la salida del programa y escribirlo en un archivo y también imprimirlo en stdout.
Ejemplo:
pid = forkpty(&fd, NULL, NULL, NULL);
if (pid<0)
return -1;
if (!pid) /* Child */
{
execl("/bin/ping", "/bin/ping", "-c", "1", "-W", "1", "192.168.3.19", NULL);
}
/* Parent */
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
Pero esto significa que ejecutar su programa desde otro programa no lo hace Presumiblemente, él quiere evitar esto, de lo contrario estaría dispuesto a usar tee. – Benj
Usted podría utilizar pipe(2)
y dup2(2)
para conectar la salida estándar a un descriptor de archivo se puede leer. Luego puede tener un hilo separado que monitorea ese descriptor de archivo, escribiendo todo lo que obtiene en un archivo de registro y el stdout original (aval guardado en otro descriptor de archivo por dup2
antes de conectar el conducto). Pero necesitarías un hilo de fondo.
En realidad, creo que el método popen tee sugerido por vatine es probablemente más simple y seguro (siempre que no necesite hacer nada adicional con el archivo de registro, como la marca de tiempo o codificación o algo así).
Las respuestas "popen()
tee" eran correctas. He aquí un ejemplo de programa que hace exactamente eso:
#include "stdio.h"
#include "unistd.h"
int main (int argc, const char * argv[])
{
printf("pre-tee\n");
if(dup2(fileno(popen("tee out.txt", "w")), STDOUT_FILENO) < 0) {
fprintf(stderr, "couldn't redirect output\n");
return 1;
}
printf("post-tee\n");
return 0;
}
Explicación:
popen()
devuelve un FILE*
, pero dup2()
espera un descriptor de archivo (fd), por lo que convierte la fileno()
FILE*
a un fd. Luego, dup2(..., STDOUT_FILENO)
dice que se reemplace la salida estándar con la fd desde popen()
.
Es decir, genera un proceso secundario (popen
) que copia toda su entrada en stdout y un archivo, luego transfiere su stdout a ese proceso.
- 1. ¿Cómo puedo implementar un generador en C++?
- 2. C++ "Hola mundo" Boost programa tee ejemplo
- 3. ¿Puedo usar T4 programáticamente desde C#?
- 4. cómo implementar interfaces en C++?
- 5. Cómo implementar glob en C#
- 6. ¿Cómo puedo crear un archivo PDF programáticamente con C?
- 7. ¿Cómo puedo implementar SlideShow en Android?
- 8. ¿Cómo puedo probar programáticamente las cookies?
- 9. Cómo abrir programáticamente Ejecutar C++?
- 10. Cómo encontrar año bisiesto programáticamente en C
- 11. ¿Cómo puedo implementar Unix grep en Perl?
- 12. ¿Cómo puedo implementar Ruby's Array.include? en JavaScript?
- 13. Haskell GStreamer tee elemento (1-N) problemas
- 14. Unix: uso confuso del Tee -command
- 15. ¿Cómo implementar el polimorfismo genérico en C#?
- 16. Crear una tubería que escriba en varios archivos (tee)
- 17. ¿cómo puedo activar el evento Onclick programáticamente en android?
- 18. ¿Cómo implementar correctamente los complementos en C#?
- 19. Cómo implementar un grapher en C#
- 20. Cómo implementar la encapsulación condicional en C#
- 21. ¿Cómo implementar una interfaz C# en F #?
- 22. ¿Cómo implementar una macro genérica en C?
- 23. C# - Cómo implementar IEnumerator en una clase
- 24. ¿Cómo implementar un singleton en C#?
- 25. Cómo implementar big int en C++
- 26. Cómo implementar una matriz enorme en C
- 27. Cómo implementar la serialización en C++
- 28. ¿Cómo implementar MapReduce en C# usando PLINQ?
- 29. Cómo implementar C# Rhino Security
- 30. Agregar metaetiqueta programáticamente en C#
¿Puedo pedir un detalle más específico de por qué necesita una solución de este tipo? ¿Es para ahorrar en la depuración ...? – lorenzog