у меня есть программа с закрытым исходным кодом, которая печатает вывод к стандартному выводу. я должен проанализировать вывод. таким образом, я перенаправляю вывод к FIFO (из которого я могу читать в родительском процессе что ветвления и должностные лица двоичный файл), использующий dup2 и затем должностное лицо программа. проблема состоит в том, что вызовы fprintf в файле становятся буферизированными, потому что он теперь пишет в файл.
я пытался назвать setvbuf с _IONBF на stdout перед звонящим должностным лицом. но проблема все еще существует.
почему setvbuf не помогает в моем случае?
как я могу вынудить вывод быть сброшенным?
setvbuf()
не имеет значения, так как изменяет состояние части библиотеки времени исполнения С, а не части ОС. Когда новый процесс начнет выполняться, его библиотека времени исполнения на С будет заново инициализирована (то есть, если она вообще использует CRT!)
Единственный способ обойти это - как-то подделать терминал под процесс. Это потому, что большинство библиотек CRT по умолчанию будут выполнять только буферизацию строк, если они считают, что прикреплены к интерактивному терминалу (в мире Unix: если isatty()
возвращает true в файловом дескрипторе), в то время как в противном случае они будут буферизованы большими блоками (обычно 8Кб или около того).
Эта утилита выглядит довольно неплохим местом для начала. (Заимствованная из комментария к Хитрость приложения заключается в том, чтобы думать, что его stdin интерактивен, а не труба , в которой есть другая полезная информация)
. Я думаю, у вас есть что-то подобное в вашей программе (вы можете воспроизвести это для своих тестов, я звоню в это 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
Теперь, если вы создадите ожидаемый
Script isatty.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