Home > Software engineering >  Running `kubectl exec` script from file is not working
Running `kubectl exec` script from file is not working

Time:11-03

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"
  • Related