grep from super slow continuous streamed log and exit once string is found without buffer

1/24/2019

UPDATE:

With @Tanktalus 's answer, I realized that it was the left most kubectl command is buffered.

# will hang forever, because RHS pipe is broken, and LHS pipe need to send 
# the output to the pipe to realize the broken pipe, but as the buffer is 
# never filled, it's never broken
kubectl logs -f pod -n NAMESPACE | grep -q "Indicator"  

# put LHS to the background, because I don't care if it hang, I just need the log.
(kubectl logs -f pod -n NAMESPACE &) | grep -q "Indicator"  

But I have a new problem, the following now hang forever:
(kubectl logs -f pod -n NAMESPACE &)| tee log >(grep -q "Indicator")


ORIGINAL QUESTION:
First of all this is not repeated with other similar questions, I have read them all. The subtle difference is that my streamed log is inactive right after the string indicator I am trying to grep.

I have a continuous streamed log output from kubernetes pod. The indicator string "Indicator" will appear in the end of the log generator application, and the log generator goes sleep infinity. So the log will still be streamed, but gives no new output.

I am trying use a pipe | to redirect my kubernetes' streamed log, then grep each line of the log, until I find the "Indicator", then I want to (immediately) exit. The commands I have tried are like:

# none of them worked, they all show the Indicator line, and then hangs forever.
kubectl logs -f pod -n NAMESPACE | tee test.log >(grep -q "Indicator")  
stdbuf -o 0 kubectl logs -f pod -n NAMESPACE | tee test.log >(grep -m1 "Indicator")
stdbuf -o 0 kubectl logs -f pod -n NAMESPACE | tee test.log >(grep -q --line-buffered "Indicator")
stdbuf -o 0 kubectl logs -f pod -n NAMESPACE | grep -q --line-buffered "Indicator"

But because after the "Indicator", there will be only one more line of log "+ Sleep infinity". I guess the output buffer from the leftmost end of the pipe is not full, and thus it's not passed to grep?

Is there any way to solve this issue ?

-- Psyduck
bash
buffer
kubernetes
stdout
unix

1 Answer

1/24/2019

I suspect it's because kubectl hasn't exited that the shell doesn't continue on. If you look at the ps output, you'll notice that grep -m1 ... does actually exit, and doesn't exist anymore, but the rest of the pipe still exists.

So I suspect you'll need to invert this. In perl, for example, I would use open to open a pipe to kubectl, read the output until I found what I wanted, kill the child, and exit. In C, the same thing with popen. I'm not sure if bash gives quite that level of control.

For example:

 perl -E 'my $pid = open my $fh, "-|", qw(perl -E), q($|++; say for 1..10; say "BOOM"; say "Sleep Infinity"; sleep 50) or die "Cannot run: $!"; while(<$fh>) { if (/BOOM/) { say; kill "INT", $pid; exit 0 } }'

You'll have to replace the stuff in the open after "-|" with your own command, and the if (/BOOM/) with your own regex, but otherwise it should work.

-- Tanktalus
Source: StackOverflow