Reputation: 3121
I'm testing this example for programming with pipes and it seems pretty straightforward.
But I was wondering what happen if the first argument of first popen() call (the string containing a shell command) holds a 'while do' loop.
For example, if I execute this shell command for 3 seconds, I get this output:
tomas@ubuntu64:~$ while true; do ps -A; sleep 1; done | grep init
1 ? 00:00:03 init
1 ? 00:00:03 init
1 ? 00:00:03 init
so the grep is working in each iteration.
However, if I do it through the C language example, changing the popen() of the example by:
FILE* ps_pipe = popen("while true; do ps -A; sleep 1; done", "r");
I get no output result when executing the compiled C program.
Anyone can shed some light on this?
Upvotes: 3
Views: 1476
Reputation: 148890
Edit: As noticed by J.F. Sebastian, by default grep uses large buffers when output is not directed to a terminal. You need to use option --line-buffered
to get output immediately (after each line)
Well, I tried it and it works fine (thank to the fix of J.F. Sebastian). Here's full code on a FreeBSD 9 box :
#include <stdio.h>
int main() {
char buffer[256];
FILE *fd = popen("while true; do ps -A; sleep 1; done | grep --line-buffered init", "r");
while(NULL != fgets(buffer, sizeof(buffer), fd)) {
printf("GOT >%s<\n", buffer);
}
return 0;
}
And (as I did not remove the \n
at end of buffer
) the output is :
GOT > 1 ?? ILs 0:00:02 /sbin/init --
>
GOT >1334 v0 R+ 0:00:00 grep --line-buffered init
>
GOT > 1 ?? ILs 0:00:02 /sbin/init --
>
GOT >1334 v0 R+ 0:00:00 grep --line-buffered init
>
Upvotes: 2
Reputation: 414179
It is a block-buffering issue. When grep's stdout is not a terminal (tty) e.g., when it is a pipe (created by popen()
) as in your case; it uses block buffering instead of line buffering. You won't see anything until grep's stdout buffer overflows. Add --line-buffered
parameter to grep
and you'll see the output immediately (each second).
Upvotes: 1
Reputation: 142625
All you need to do is to write
the output to standard I/O, therefore change the popen()
parameters to the following:
FILE* ps_pipe = popen("while true; do ps -A; sleep 1; done", "w");
Upvotes: -1