заставляя программу сбрасывать свой стандартный вывод при перенаправлении - PullRequest
10 голосов
/ 13 января 2010

У меня есть программа с закрытым исходным кодом, которая печатает вывод на стандартный вывод. мне нужно разобрать вывод. поэтому я перенаправляю вывод в fifo (из которого я могу прочитать в родительском процессе, который разветвляется и исполняет двоичный файл), используя dup2, а затем выполнить программу. проблема в том, что вызовы fprintf в файле становятся буферизированными, потому что теперь он записывает в файл.

Я пытался вызвать setvbuf с _IONBF на stdout перед вызовом exec. но проблема все еще существует.

почему setvbuf не помогает в моем случае?

как я могу принудительно сбросить вывод?

Ответы [ 3 ]

6 голосов
/ 13 января 2010

setvbuf() не имеет значения, потому что он изменяет состояние части библиотеки времени выполнения C, а не части ОС. Когда новый процесс начнет работать, его библиотека времени выполнения C будет переинициализирована (если он вообще использует CRT!)

Единственный способ обойти это - как-то подделать терминал для процесса. Это связано с тем, что большинство библиотек CRT по умолчанию выполняют только буферизацию строк, если считают, что они подключены к интерактивному терминалу (в мире Unix: если isatty() возвращает true в дескрипторе файла), тогда как в противном случае они будут буферизоваться в больших блоках (обычно 8Kb или около того).

Эта утилита выглядит довольно неплохо для начала. (Заимствовано из комментария к Обманите приложение, думая, что его стандартный ввод интерактивный, а не канал , который имеет другую полезную информацию.)

2 голосов
/ 06 июня 2013

Инструмент unbuffer может помочь с этой проблемой:

Он является частью expect-dev и может быть установлен в Ubuntu с помощью

sudo apt-get install expect-dev

чтобы использовать это типа:

unbuffer ls > log.txt
2 голосов
/ 13 января 2010

Я полагаю, у вас есть что-то подобное в вашей программе (вы можете воспроизвести это для ваших тестов, я называю это isatty здесь)

#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);
}

например, если вы запустите его

$ ./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

Теперь, если вы создаете expect скрипт isatty.expect (установите expect для вашего дистрибутива, если не установлен)

#! /usr/bin/expect -f

spawn "./isatty"
expect

и запустите

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

или

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