3

Why do

$ ping -c 4 -W 1 127.0.0.1 | cat

and

$ ping -c 4 -W 1 1.1.1.1

print their output immediately, whereas

$ ping -c 4 -W 1 1.1.1.1 | cat

prints nothing for four seconds, then prints all output in one go?

N.B. the first command prints successful pings, the other two print timeouts, as expected.

  • 2
    It could be a buffering matter, maybe there is no explicit flushing after the first line, only for the replies and the summary. In this case, [http://unix.stackexchange.com/q/25372/3929] discusses approaches that might be applicable here. – Ulrich Schwarz Jan 04 '15 at 16:14
  • @UlrichSchwarz seems to be; using the script solution presented on that page it does work as expected! It'd be nice if you could make that into a proper answer. –  Jan 04 '15 at 18:30

3 Answers3

3

In the case where ping is outputting to a shell pipeline, the different behavior is explained by buffering. ping calls fflush() after reporting each successfully received echo packet, so those lines are sent immediately to cat, which outputs them without delay. ping does not call fflush() after writing out the lines that report timed out packets, so stdio buffers those lines until ping calls exit(), which then sends them all to cat, which outputs them.

In the case where ping is outputting to the terminal directly, you see both the success and failure output immediately because by default stdio line buffers all output to streams associated with ttys. So each output line is sent to the terminal immediately instead of being buffered by stdio.

In the spirit of teaching a man to fish, you can verify all this yourself by reading the OS X source code for ping and reading the OS X man page for stdio.

Kyle Jones
  • 15,015
0

I believe this is because of how cat is getting the input, the first command gives an exit status of 2, whereas the IP address that is pinging gives an exit status of 0.

This means that cat is displaying the output of STDOUT straight away whereas it is putting STDERR into it's buffer and then displaying it at the command termination.

0

It is either waiting for DNS or for ICMP echo reply packets. If it's DNS, try the -n option. If it's not, try the difference between hosts that answer ICMP echo requests and those who don't (or whose answers are filtered somewhere on the way).