significa - Problema al redirigir una salida de programa C en bash
redirigir salida comando linux a fichero (5)
He codificado un programa en C que envía mensajes a la salida estándar utilizando printf y tengo problemas para redirigir la salida a un archivo (desde bash).
He intentado:
./program argument >> program.out
./program argument > program.out
./program >> program.out argument
./program > program.out argument
En cada caso, se crea el archivo program.out pero permanece vacío. Una vez que finaliza la ejecución, el tamaño del archivo es 0.
Si omito la redirección al ejecutar el programa:
./program argument
Luego, todos los mensajes enviados a stdout usando printf se muestran en la terminal.
Tengo otros programas en C para los cuales no tengo problemas para redirigir la salida de esta manera. ¿Tiene que ver con el programa en sí? con el argumento pasando? ¿Dónde debería buscar el problema?
Algunos detalles sobre el programa C:
- No lee nada de stdin
- Utiliza conectores de Dominio de Internet BSD
- Utiliza hilos POSIX
- Asigna una función de controlador especial para la señal SIGINT usando sigaction
- Envía muchas líneas nuevas a stdout (para aquellos de ustedes que piensen que debo enjuagar)
Cierto código:
int main(int argc, char** argv)
{
printf("Execution started/n");
do
{
/* lots of printf here */
} while (1);
/* Code never reached */
pthread_exit(EXIT_SUCCESS);
}
¿Ha finalizado el programa antes de que usted verifique el contenido del archivo redirigido? Si aún se está ejecutando, es posible que su salida se mantenga almacenada temporalmente en algún lugar de la cadena, para que no la vea en el archivo.
Aparte de eso, y de las otras respuestas proporcionadas hasta ahora, creo que es hora de mostrar un ejemplo representativo del código del problema. Hay demasiadas posibilidades esotéricas.
EDITAR
Por el aspecto del código de muestra, si tiene una cantidad relativamente pequeña de impresión, entonces queda atrapado en el búfer de salida. Enjuague después de cada escritura para asegurarse de que se haya ido al disco. Por lo general, puede tener hasta el tamaño de una página de datos no escritos que se encuentran de otra manera.
En ausencia de una descarga, la única vez que puede estar seguro de que tiene todo en el disco es cuando sale el programa . Incluso una terminación de subproceso no lo hará, ya que los búferes de salida como ese no son por subproceso, son por proceso.
Enfrentar los búfers normalmente se maneja mediante la función exit()
, que normalmente se llama implícitamente por un return
desde main (). Estás finalizando tu programa al generar SIGINT, y aparentemente el controlador SIGINT predeterminado no vacía los búferes.
Eche un vistazo a este artículo: Aplicación de patrones de diseño para simplificar el manejo de señales . El artículo es principalmente C ++, pero hay un ejemplo C útil en la segunda sección, que muestra cómo usar SIGINT para salir de su programa con elegancia.
En cuanto a por qué el comportamiento de un terminal difiere de un archivo, eche un vistazo a la Programación avanzada de Stevens en la Sección 5.4 del entorno de UNIX sobre almacenamiento en búfer. El dijo que:
La mayoría de las implementaciones predeterminan los siguientes tipos de almacenamiento en búfer. El error estándar siempre está sin búfer. El resto de las transmisiones se almacenan en línea si se refieren a un dispositivo terminal; de lo contrario, están completamente amortiguados. Las cuatro plataformas que se analizan en este libro siguen estas convenciones para el almacenamiento en búfer de E / S estándar: el error estándar no se almacena, las secuencias abiertas para los dispositivos terminales se almacenan en búfer de línea y todas las demás secuencias se almacenan en el búfer.
La limpieza después de las nuevas líneas solo funciona cuando se imprime en un terminal, pero no necesariamente cuando se imprime en un archivo. Una búsqueda rápida en Google reveló esta página con más información: http://www.pixelbeat.org/programming/stdio_buffering/
Vea la sección titulada "modos de almacenamiento en búfer predeterminados".
Es posible que deba agregar algunas llamadas a fflush (stdout), después de todo.
También puede establecer el tamaño y comportamiento del búfer usando setvbuf .
Sugerencias:
- Redirige stderr a un archivo también.
- Prueba tail -f tus archivos de salida.
- Abra un archivo y fprintf su registro (para ayudar a averiguar qué está pasando).
- Busque cualquier cierre / duplicación / tubería manual de los identificadores STD * FILE o 1-3 descriptores de archivos.
- Reducir la complejidad; corta grandes porciones de funcionalidad hasta que printfs funcione. Luego léalos hasta que se rompa nuevamente. Continúe hasta que identifique el código culpable.
Solo para el registro, en Perl usarías:
use IO::Handle;
flush STDOUT;
autoflush STDOUT;