This question already has an answer here:
- Turn off buffering in pipe 13 answers
The following produces nothing in bash:
while true ; do upower -d ; sleep 1 ; done | grep percentage | uniq
I've discovered that it doesn't matter what the last- or even the second to last- program are in this chain. The second-to-last program always produces expected output, and the last always fails to produce anything.
It also doesn't appear to matter if I wrap the while loop in a subshell (via
( while ... done ) ), or wrap everything but the last command in a subshell and pipe into that last command.
I am deeply confused by this behavior.
My gut tells me...
...that there's some sort of I/O deadlocking in the chain created by blocking reads and writes and the fact that the while loop isn't always producing output. But, on the other hand, I've done this kind of thing plenty of times before, with no issue. Besides, if it were that, wouldn't the problem exist between the while loop and the next command? So I'm flummoxed. Will provide bash version information if no one else can reproduce.
In case it isn't immediately obvious...
The point of this line of code is to print every change in battery percentage, but only print new battery levels. It uses polling. I suppose I could get the same behavior with simply running
upower --monitor-detail | grep percentage | uniq
But this is a one-off thing, and I didn't plan on expending more than 5 seconds of thought on this until the above started to fail. At which point it became an interesting problem. Plus, I don't know whether monitor-detail just does polling under the hood, anyway (and I'm not running an strace to check).
EDIT: Apparently, the above
--monitor-detail version also doesn't produce anything (or, at least, it seems to. The polling / update frequency is pretty low, so I might just not have waited long enough. Although I know I waited long enough for the original issue). Now I'm very, very confused. I guess I should run that strace after all...