Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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).

share|improve this question
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 '12 at 11:30
    
I'm on RHEL 5.3 (Tikanga). –  Harry May 16 '12 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 '12 at 12:37

2 Answers 2

up vote 3 down vote accepted

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.

share|improve this answer
    
"Check p afterwards, it will be empty as well." p is a FIFO, so it will be empty anyway afterwards. –  Harry May 16 '12 at 14:34
    
Right, didn't see that line. Answer still applies. –  Kevin May 16 '12 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 '12 at 1:42

From FreeBSD's tee manpage:

DESCRIPTION
 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...)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.