Description
What happened
Attempted to use GNU/Bash command substitution to assign the output of a command to a variable:
% yo="$(kubectl get pods -n kube-public)"; echo "$yo" | cat -vte
No resources found in kube-public namespace.
$
This results in the message being printed to stdErr
and nothing being assigned to the variable yo
.
- the error prints to the terminal, then
- the empty variable prints to the terminal:
$
After redirecting stdErr
back to stdOut
the issue is resolved:
% yo="$(kubectl get pods -n kube-public 2>&1)"; echo "$yo" | cat -vte
No resources found in kube-public namespace.$
What you expected to happen:
The message to the user "No resources found in kube-public namespace." should be sent through stdOut
.
How to reproduce it (as minimally and precisely as possible):
See above.
Anything else we need to know?:
For reference, even given a similar command with a resulting failure, like searching for namespace foo
(and there is no namespace foo
) should even be sent to stdOut
(if there is a message) and accompanied by exit status:1
; kubectl
is telling the human something important.
If there is nothing to share with the user (no messages printed to the terminal) then simple exit with status:1
and move on.
For Reference:
The most programmatically friendly thing to do is:
- Send ALL
kubectl
messages (errors and everything) tostdOut
, and - Whenever
kubectl
has nothing to share with the human (rarely) THAT should exit withstatus:1
.
Example
Given these conditions:
% cat /tmp/yo
a1 b1 c1
a2 b2 c2
a3 b3 c3
grep
will indicate success with a message and exit status:
% grep b2 /tmp/yo; echo $?
a2 b2 c2 # information for user
0 # exit status: success
In this case the succeeding operation outputs a message to the user: a2 b2 c2
.
% grep foo /tmp/yo; echo $?
1 # exit status: fail (no message to user)
In this case there is nothing to share with the user; the purpose of the operation failed to return anything. But, given the exit status, we can make subsequent automation decisions on the exit status - simple.
Please see excerpts from our bible, The Linux Programming Interface. While this excerpt only explains the mechanics, the grep
example supports historic implementation.
I'd be interested in hearing from those with more gray hairs than me about the whys
behind the historic bits.
Environment:
- Kubernetes client and server versions (use
kubectl version
):Client Version: v1.31.0
- Cloud provider or hardware configuration: NA
- OS (e.g:
cat /etc/os-release
):macOS Sonoma/14.6.1