Bash – How to make any program work with the tee command

bashbufferosxstdouttee

I wrote a program (in Ruby) and it worked well. It prints out a few lines of text and then pause for a minute and then repeats the above.

It works well (in Mac OS X's terminal), but I noted that if I wanted to keep a record of the output, by using

ruby myscript.rb | tee record.txt

then the output won't be shown on the screen, until the output reaches a certain amount, perhaps a few kb. However, this could mean 5 or 10 minutes with nothing on the screen (and nothing in the file either if I press CTRL-C).

I could modify the program to flush the output, but I thought an app should be agnostic as to what is being used with the output to STDOUT. So can tee be made to work well (perhaps with an option), or any other command could be used, or maybe it is an option of Bash or the Terminal app? Is there a way?

Best Answer

I thought an app should be agnostic as to what is being used with the output to STDOUT.

You thought wrongly. The runtime libraries of several programming languages, including the C and C++ languages, all share the semantics of changing the buffering according to whether they detect that the stream is attached to a terminal device.

This is a defined part of the language in many cases. The C language standard says, for example:

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.

The usual choice if a stream is not attached to a terminal device is to select unit buffering, line buffering, or full buffering. Unit buffering and line buffering are usual for standard error; full buffering for standard output. But this does vary by language.

So to get the output to be not fully buffered when the output stream is a pipe in such lanugages you have to

  • write your program to itself make standard output line buffered, smart buffered, or unbuffered;
  • use things that hook your particular programming language's runtime library, such as the stdbuf command if your programming language is C or uses (the I/O streams part of) the C runtime library as its base (which some programming languages do not); or
  • use tools such as ptybandage that make the program think that its standard output is a terminal, whilst taking that output and sending it to the write end of the pipe.

Further reading