Используя тройник с непрерывным выводом C-программы

Это должно быть действительно просто, но я не могу поймать это.

Это тривиальная программа на C, пишущая на стандартный вывод:

root@oceanLondon:~/tst# cat tst.c
#include <stdio.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
        for (; ;) {
                printf("Hello world!\n");
                sleep(1);
        }
        return 0;
}

Теперь, если я хочу записать вывод на мой экран и файл:

root@oceanLondon:~/tst# ./tst |tee file

это просто не работает, у меня пустой экран и пустой файл.

если я делаю программу, которая выходит, то она отлично работает, например,

root@oceanLondon:~/tst# ls |tee file
Makefile
file
qq
tst
tst.c
tst.o
root@oceanLondon:~/tst# cat file
Makefile
file
qq
tst
tst.c
tst.o
root@oceanLondon:~/tst#

Это какая-то проблема с буферизацией? И может кто-нибудь помочь мне сделать это в программе продолжения, пожалуйста?

2 ответа

Стандартный поток вывода является буферизованной строкой, если можно определить, что поток относится к интерактивному устройству (например, терминалу), в противном случае он полностью буферизован, поэтому существуют случаи, когда printf не сбрасывается, даже если для печати выводится новая строка, например, по конвейеру или с перенаправленным выводом;

> tst | tee file
> tst > file

призвание fflush(stdout) после printf() решит проблему.

Связанный текст от C99 раздел 7.19.3 говорится, что;

Когда поток не буферизован, символы должны появляться из источника или в месте назначения как можно скорее. В противном случае символы могут накапливаться и передаваться в среду хоста или из нее в виде блока.

Когда поток полностью буферизован, символы предназначены для передачи в или из среды хоста как блок, когда буфер заполнен.

Когда поток буферизуется строкой, символы предназначены для передачи в или из хост-среды в виде блока, когда встречается символ новой строки.

При первоначальном открытии стандартный поток ошибок не полностью буферизован; стандартные входные и стандартные выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не ссылается на интерактивное устройство.

Кажется, что ваша проблема в том, что stdout буферизируется и не отображается после новой строки. Вы можете принудительно отобразить его, сбросив его после выражения printf:

fflush(stdout); 

Кроме того, вы можете отключить буферизацию с помощью:

setbuf(stdout, NULL);

Также обратите внимание, что stderr не буферизируется, и вы можете проверить, является ли проблема буферизованной, распечатав stderr вместо stdout,

Как вы заметили, вы также можете использовать stdbuf (больше информации с этим ответом).

Другие вопросы по тегам