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?

8
  • 6
    And if you try to fflush(stdout);? Commented Dec 31, 2014 at 12:30
  • 1
    @fredtantini: then it works indeed. Was really simple one. Thanks - feel free to post it as an answer. Commented Dec 31, 2014 at 12:36
  • 1
    There seem to be some useful answers here. (I'm not on a Linux machine right now, so I can't try them out.) Commented Dec 31, 2014 at 12:38
  • 1
    @fredtantini as the only answer to this question has been deleted, maybe you should post one. Commented Dec 31, 2014 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. Commented Dec 31, 2014 at 15:34

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Your answer seems to contradict your quote. (line buffered in first sentence of answer, fully buffered in last sentence of quote)
@ace, you are absolutely right, I fixed it. Thanks a lot!
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).

1 Comment

if you edit your answer to include this: stackoverflow.com/a/11337109/2550808 I will accept it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.