obligar a un programa a vaciar su salida estándar cuando se redirige

3 minutos de lectura

Tengo un programa de código cerrado que imprime la salida a la salida estándar. Necesito analizar la salida. entonces redirijo la salida a un fifo (desde el cual puedo leer en el proceso principal que bifurca y ejecuta el binario) usando dup2 y luego ejecuto el programa. el problema es que las llamadas fprintf en el archivo se almacenan en el búfer porque ahora está escribiendo en un archivo.

Traté de llamar a setvbuf con _IONBF en stdout antes de llamar a exec. pero el problema sigue existiendo.

¿Por qué setvbuf no ayuda en mi caso?

¿Cómo puedo forzar que la salida se enjuague?

avatar de usuario
j_random_hacker

setvbuf() no hace ninguna diferencia porque cambia el estado de parte de la biblioteca de tiempo de ejecución de C, no parte del sistema operativo. Cuando el nuevo proceso comience a ejecutarse, su biblioteca de tiempo de ejecución C se reiniciará (¡eso es si usa un CRT!)

La única forma que he oído para evitar esto es falsificar de alguna manera una terminal para el proceso. Esto se debe a que la mayoría de las bibliotecas CRT realizarán de forma predeterminada solo el almacenamiento en búfer de línea si creen que están conectadas a un terminal interactivo (en el mundo de Unix: si isatty() devuelve verdadero en el descriptor de archivo), mientras que, de lo contrario, se almacenarán en bloques más grandes (normalmente de 8 Kb o menos).

Esta utilidad parece un buen lugar para empezar. (Tomado de un comentario sobre Engañar a una aplicación para que piense que su entrada estándar es interactiva, no una canalización, que tiene otra información útil).

  • Extraigo un proceso, llamo a setvbuf en el proceso secundario y luego ejecuto un script de shell que ejecuta otro script de shell que finalmente ejecuta el binario. ¿Puedo cambiar el comando ejecutivo final (bash) para que deshabilite el almacenamiento en búfer de alguna manera?

    – Rohit Banga

    13 de enero de 2010 a las 12:15

  • Repito, es inútil llamar a setvbuf() antes de ejecutar: ¡ninguno de los estados de la biblioteca de tiempo de ejecución de C se conserva en exec()! El proceso final que exec() podría ni siquiera utilizar ¡la TRC! (Improbable pero posible).

    – j_random_hacker

    13 de enero de 2010 a las 12:37

  • ok, estoy probando el enfoque pty, consulte stackoverflow.com/questions/2056858/cannot-write-to-pty-linux

    – Rohit Banga

    13 de enero de 2010 a las 13:22

Supongo que tienes algo como esto en tu programa (puedes reproducir esto para tus pruebas, lo llamo isatty aquí)

#include <stdio.h>
#include <unistd.h>

const char* m1 = "%d: %s a TTY\n";

void isTty(FILE* f) {
    int fno = fileno(f);
    printf(m1, fno, (isatty(fno)) ? "is" : "is NOT");
}

int main(int argc, char* argv[]) {
    isTty(stdin);
    isTty(stdout);
}

por ejemplo si lo ejecuta

$ ./isatty
0: is a TTY
1: is a TTY

$ ./isatty > isatty.out
$ cat isatty.out 
0: is a TTY
1: is NOT a TTY

$ ./isatty > isatty.out < /dev/null
$ cat isatty.out 
0: is NOT a TTY
1: is NOT a TTY

Ahora bien, si creas un expect texto isatty.expect (Instalar en pc expect para su distribución si no está instalado)

#! /usr/bin/expect -f

spawn "./isatty"
expect

y ejecutarlo

$ ./isatty.expect 
spawn ./isatty
0: is a TTY
1: is a TTY

o

$ ./isatty.expect > isatty.out 
$ cat isatty.out 
spawn ./isatty
0: is a TTY
1: is a TTY

los unbuffer herramienta puede ayudar con este problema:

es parte de la expect-dev y se puede instalar en ubuntu usando

sudo apt-get install expect-dev

para usarlo escribe:

unbuffer ls > log.txt

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad