In trying to trace a simple HTTP GET request and its response with nc, I'm running into something strange.

This, for example, works fine: the in file ends up containing the HTTP GET request and the out file the response.

$ mkfifo p
$ (nc -l 4000 < p | tee in | nc web-server 80 | tee out p)&
[1] 8299
$ echo "GET /sample" | nc localhost 4000
This is contents of /sample...
$ cat out
This is contents of /sample...

However, if I replace the tee out p above with tee out >p, then the out file turns out to be empty.

$ (nc -l 4000 < p | tee in | nc web-server 80 | tee out > p)&
[1] 8312
$ echo "GET /sample" | nc localhost 4000
$ cat out

Why should this be so?

EDIT: I'm on RHEL 5.3 (Tikanga).

  • 2
    (At least FreeBSD's) tee doesn't buffer its output. The shell (i.e. >) possibly does, which could explain this, I suppose.
    – sr_
    May 16, 2012 at 11:30
  • I'm on RHEL 5.3 (Tikanga).
    – Harry
    May 16, 2012 at 11:40
  • @sr_ If you can re-post your above comment as an answer, I could consider making it final... as I think you have given me 'sufficient hope' that I'm not doing anything silly on my end.
    – Harry
    May 16, 2012 at 12:37

2 Answers 2


The problem is that you're using shell redirects to read from and write to the same file. Check p afterwards, it will be empty as well. The shell opens it in read mode, truncating the file, while it's setting up the pipeline before it runs the commands. However, using tee, since it opens the file itself, means that the file isn't truncated until after the contents have been read for the input. This is a well known and documented behavior and the reason you can't simply use redirects to make inline changes to files.

  • "Check p afterwards, it will be empty as well." p is a FIFO, so it will be empty anyway afterwards.
    – Harry
    May 16, 2012 at 14:34
  • Right, didn't see that line. Answer still applies.
    – Kevin
    May 16, 2012 at 14:39
  • 1
    I'm not satisfied with your explanation. There's nothing in p to start with, so we can leave the 'truncation' part out. The dataflow starts from the RHS of nc web-server 80 | . The web-server response gets fed to tee. Now, tee by definition would send its output to FILEs and to stdout. Now, here, there's just 1 FILEs out and the stdout instead of connected to the terminal is redirected to p. tee would copy the response to both. Only after p starts getting written to does the ` < p` start reading data off of p. So, would appreciate if you could clarify further.
    – Harry
    May 17, 2012 at 1:42

From FreeBSD's tee manpage:

 The tee utility copies standard input to standard output, making a copy
 in zero or more files.  The output is unbuffered.

unbuffered is the cue, Bash (or your shell's) output redirection (> p) is probably buffered, thus causing the different behavior.

(I'm sorry I can't be more certain with this, but I take the +1's on the comment as indicators for this being the right track...)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .