I'm trying to create a script in order to run multiple kubectl exec
commands against multiple pods with multiple containers. The script seems to generate the command just fine but errors out when attempting to run it.
example command that is generated: kubectl -n <namespace> exec <pod_name> -c <container_name> -- openssl version
When I copy the generated command and run it directly it works fine, but if I try to run the command within the script I get an error.
OCI runtime exec failed: exec failed: unable to start container process: exec: "openssl version": executable file not found in $PATH: unknown
command terminated with exit code 126
snippet from .sh file:
for pod in $PODS; do
CONTAINERS=($(kubectl -n $NAMESPACE get pods $pod -o jsonpath='{.spec.containers[*].name}' | tr -s '[[:space:]]' '\n'))
header "{pod: \"$pod\", containers: \"$(echo $CONTAINERS | tr -d '\n')\"}"
if [ "$DRYRUN" != "true" ]; then
for container in $CONTAINERS; do
echo "COMMAND BEING RUN: \"kubectl -n $NAMESPACE exec $pod -c $container -- $COMMAND\""
kubectl -n $NAMESPACE exec $pod -c $container -- $COMMAND
done
fi
done
CodePudding user response:
Haha, this is exactly the problem I'm trying to solve. By any chance, are you trying to check OpenSSL versions on all containers due to the latest CVE's dropping yesterday? Because thats exactly what I'm trying to do.
Anyway, here is the solution - a problem in which I've had before and its down to the way sh/bash/zsh interprets strings.
It's hard to debug, as I'd need to see you're whole script instead of just the pod exec loop, but the underlying problem is: $COMMAND
cannot be placed into a string or used as a string, otherwise your shell script will wrap it into a string and kubectl will interpret that as the whole thing being a command instead of correctly forwarding the breakpoints.
This is evident by the error message, its trying to interpret openssl version
literally as a whole string that makes up the binary name you are trying to call, in which obviously openssl version
isn't a command that will be on your $PATH
, instead of correctly interpreting each command in the string and executing openssl
which is on your $PATH
with the version
argument against it.
As I'm not sure if I've explained that very well, so to assist, here are some visual/working examples.
This will not work:
# ./my-script.sh openssl version
# Will OCI error as "openssl version" cannot be found in the containers $PATH
kubectl exec "${pod}" -c "${container}" -- "${@:1}"
COMMAND="${@:1}"
kubectl exec "${pod}" -c "${container}" -- $COMMAND
COMMAND=${@:1}
kubectl exec "${pod}" -c "${container}" -- "${COMMAND}"
This will work:
# ./my-script.sh openssl version
# LibreSSL 3.3.6
kubectl exec "${pod}" -c "${container}" -- ${@:1}
COMMAND=${@:1}
kubectl exec "${pod}" -c "${container}" -- $COMMAND
Simply put, if the command that you wish to forward is used as a string, it will not work.
CodePudding user response:
The command provided with exec
will be executed without a shell. This means that environment variables will not be available. Thus the error specifying missing executable path in $PATH. Only executables installed in default $PATH
(like /bin/
) can be executed.
You can load the shell and provide $command
as a command to be executed;
kubectl exec -n $NAMESPACE --container $container -it $pod -- /bin/sh -c "$COMMAND"