Update: This behavior is observed on Windows Subsystem for Linux. It seems there are two issues we are dealing with here:
Some bug/race condition internal to the system.This is incorrect, see answers.Default buffer size for
head.For (2), as @kusalanda mentioned,
headmay have some default buffer size that consumes the input up to a certain point. On ArchLinux, we can see that fori < 10, we consistently see no output fromtail. The same is true for Windows Subsystem for Linux (i.e. no inconsistent output fortail).For (1), it is possible that there is some bug internal to the Windows Subsystem for Linux itself that causes this race condition, as we do not observe such behavior in ArchLinux.This is incorrect, see answers. There is a "point 1", but it is different.
I am trying to run the following commands in bash version 4.4.19:
{ for ((i = 0; i < 1000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
Sometimes, I see the expected results:
$ ~ { for ((i = 0; i < 1000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
999
$ ~
However, more often than not, I see the following:
$ ~ { for ((i = 0; i < 1000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
$ ~
I suspect this is a race condition. However, if I add a sleep at the beginning of the second block of commands, the "race condition" still happens:
$ ~ { for ((i = 0; i < 1000; ++i)); do echo $i; done; } | { sleep 10; head -n 1; echo ...; tail -n 1; }
0
...
$ ~
Is this actually a race condition? What should I do to make the second block of code see the whole input? Note that if I use 10000 instead of 1000, then I do not see this issue (it is possible that these all just happen to be lucky cases though):
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~ { for ((i = 0; i < 10000; ++i)); do echo $i; done; } | { head -n 1; echo ...; tail -n 1; }
0
...
9999
$ ~
headimplementation buffers too much of the input data and leaves nothing fortailto work on (this is an error). This ought to be deterministic though.i < 1000on Windows Subsystem for Linux, andi < 10for ArchLinux. Now that you mention it, this might be a Windows Subsystem for Linux issue (with regards to the non-determinism). For ArchLinux, at least so far, the behavior seems deterministic. I will update the question with this information.foo | bar, how much a read(2) insidebarwill return is dependent not only on how muchfoois writing into the pipe, but also on how the kernel schedules thefooandbarprocesses to run. Notice that pipes on Unix are not message/boundary preserving; 5 writes infoomay result in a single read inbar.