3

It must be really simple but I can't catch it.

This is a trivial C program writing to stdout:

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

Now, if I want to write the output to my screen and a file:

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

it just do not work, I have empty screen and empty file.

if I do a program that exits, then it perfectly works, e.g.

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#

Is it some kind of buffering issue? And can someone help me to do tee on a continues program, please?

wick
  • 1,995
  • 2
  • 20
  • 31
  • 6
    And if you try to `fflush(stdout);`? – fredtantini Dec 31 '14 at 12:30
  • 1
    @fredtantini: then it works indeed. Was really simple one. Thanks - feel free to post it as an answer. – wick Dec 31 '14 at 12:36
  • 1
    There seem to be some useful answers [here](http://stackoverflow.com/questions/11337041/force-line-buffering-of-stdout-when-piping-to-tee). (I'm not on a Linux machine right now, so I can't try them out.) – M Oehm Dec 31 '14 at 12:38
  • By the way, I saw once that output of \n (i.e. printf("\n");) would make the flush happened automatically, or do I confuse it with Nagel algorithm? – wick Dec 31 '14 at 12:42
  • This may help: [How could I temporary redirect stdout to a file in a C program?](http://stackoverflow.com/q/4832603/2455888). – haccks Dec 31 '14 at 12:46
  • 1
    @fredtantini as the only answer to this question has been deleted, maybe you should post one. – Tom Fenech Dec 31 '14 at 14:46
  • 1
    Standard output is usually line buffered when it goes direct to a terminal. When it goes to a pipe, it is normally fully buffered. You can either use `fflush()` in each iteration, or call `setvbuf()` to make standard output line buffered explicitly. – Jonathan Leffler Dec 31 '14 at 15:34
  • http://mywiki.wooledge.org/BashFAQ/009 – tripleee Jan 02 '15 at 08:02

2 Answers2

2

Standard output stream is line buffered if the stream can be determined to refer to an interactive device (eg. terminal), otherwise it's fully buffered, therefore, there are cases where printf doesn't flush, even if it has a newline to print, like piped or redirected output;

> tst | tee file
> tst > file

Calling fflush(stdout) after the printf() will solve the problem.

Related text from C99 section 7.19.3 states that;

When a stream is unbuffered, characters are intended to appear from the source or at the destination as soon as possible. Otherwise characters may be accumulated and transmitted to or from the host environment as a block.

When a stream is fully buffered, characters are intended to be transmitted to or from the host environment as a block when a buffer is filled.

When a stream is line buffered, characters are intended to be transmitted to or from the host environment as a block when a new-line character is encountered.

As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

Alper
  • 12,860
  • 2
  • 31
  • 41
  • Your answer seems to contradict your quote. (**line buffered** in first sentence of answer, **fully buffered** in last sentence of quote) – user12205 Dec 31 '14 at 15:45
  • 1
    @ace, you are absolutely right, I fixed it. Thanks a lot! – Alper Dec 31 '14 at 16:47
0

It seems that your problem is that stdout is buffered and isn't displayed after the new line. You can force to display it by flushing it after your printf statement:

fflush(stdout); 

Alternatively, you can disable buffering with:

setbuf(stdout, NULL);

Also, note that stderr is not buffered, and you can check if the problem is a buffered one by printing to stderr instead of stdout.

As you have noticed, you can also use stdbuf (more info with this answer).

Community
  • 1
  • 1
fredtantini
  • 15,966
  • 8
  • 49
  • 55
  • if you edit your answer to include this: http://stackoverflow.com/a/11337109/2550808 I will accept it – wick Jan 01 '15 at 17:31