2

I have a couple of C programs sending messages back and forth through FIFO named pipes in Unix, and I want to see what's going through the pipes using an external program. The problem is that if I use cat, it stops after the next time my program calls write() and closes the pipe, breaking the communication between the programs... and then bad things happen. I don't understand why cat is closing my pipe. EDIT: Actually, I did the exact same thing today, and instead of closing the pipe, it just made the process stop reading from it.

So is there something like cat except that it won't interfere with the pipes at all, just print whatever it sees going through?

In case it's relevant, I create the pipes like this in C:

outs[i2/2] = open("/tmp/pipe_w", O_WRONLY);
ins[i2/2] = open("/tmp/pipe_r", O_RDONLY);

Update: Here's a terminal example.

My processes print this output as they open the pipes:

Opened in pipe at /tmp/ai1In
Opened out pipe at /tmp/ai1Out

Then I do this in a separate shell:

admin$ cat /tmp/ai1Out
ai1

It sees the message "ai1" go through and then nothing. The process reading that pipe ends up waiting forever. I kill cat, but the pipe still ends up not being read from.

Update 2:

cat [path] | tee [path] works in some cases. It doesn't interfere noticeably with my ai1Out pipe, but it interferes with ai1In. The difference must be due to my code. Regardless, this means that running this command has some effect on the other processes using the pipes, which I don't want. When I try to read ai1Out, I just see this, then the process writing to that pipe gets an error on its next write() call:

admin$ cat /tmp/ai1In | tee /tmp/ai1In
]2,15,43,66,65,61,53,20,30,27,40,16,50,41,48[[[[[[[[
3

The definition of a pipe is that data written into it is read at the other end. A pipe doesn't duplicate data. Reading on a pipe is a destructive operation. If there are two readers on a pipe, each byte will be read by only one of the readers.

If you want to spy on the communication between two programs via a pipe, you can do it by inserting tee between the programs. There are then two pipes: one from the writer to tee and one from tee to the reader.

mkfifo pipe_w pipe_r
writer >pipe_w
reader <pipe_r
<pipe_w tee pipe_r

The pipe naming scheme in your question is inconsistent, so I don't know exactly what you tried. It appears that you tried to feed data from a pipe back into itself. That won't work: you're created a closed loop where some of the data goes back into the pipe forever (only some of the data, because it's unpredictable which bytes will go back into the pipe and which bytes will go to the original reader).

If there's a pipe between two processes and you can't change the plumbing, the easiest way to spy on it is to trace either the writer or the reader process. For example, if the writer process has PID 123 and has the pipe open on file descriptor 4, under Linux, you can use

strace -p123 -e write=4
  • Thanks for clearing up my misunderstanding of pipes. I tried it using intermediate pipes as you described, and it's working. I was going to try to use strace, but OS X doesn't have it (being non-Linux), and I couldn't find an equivalent command. – sudo Apr 19 '15 at 1:47
  • @9000 The OSX equivalent is dtrace, but I don't know what options to use. – Gilles Apr 19 '15 at 12:26
  • @Giles I looked at dtrace just now, and it wants some kind of script as input... Too complicated. For me at least, the intermediate pipe is good enough. – sudo Apr 20 '15 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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