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 ?
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.