Kubernetes how-to

kubectl exec: Run Commands and Open a Shell in a Pod

kubectl exec runs a command inside a running container. Add -it and a shell opens in the pod, which is the quickest way to check a file, an environment variable or a network route from inside the workload. If the image has no shell, the command fails, and the fix is an ephemeral debug container.

By , Founder at SeaGit

·

Key takeaways

  • Syntax: kubectl exec POD -c CONTAINER -- COMMAND. The -- separates kubectl flags from the command you run in the pod.
  • Use -i -t for an interactive shell. Without them the command runs once and prints the output.
  • A distroless or minimal image often has no sh. The error is "executable file not found in $PATH". Use kubectl debug with a busybox container instead of installing tools into a production image.
  • Exec runs in the container filesystem. Anything you change is lost when the container restarts, so exec is for inspection, not for fixing the image.

Syntax, the -- separator, and container selection

The reference gives the form kubectl exec (POD or TYPE/NAME) with a container flag, other flags, and then -- COMMAND. The double dash is not optional when the command has its own flags. Without it, kubectl reads ls -t as its own flag.

bash
# Run one command in the first container of a pod
kubectl exec my-api-7c9f -n prod -- date

# Pick a container in a multi-container pod
kubectl exec my-api-7c9f -n prod -c ruby-container -- date

# Interactive shell (-i keeps stdin open, -t allocates a terminal)
kubectl exec -it my-api-7c9f -n prod -c my-api -- sh

# Target a Deployment or Service: kubectl picks one pod
kubectl exec -it deploy/my-api -n prod -- sh
Examples follow the kubectl exec reference. The shell can be sh, bash or whatever the image ships.

Use the deploy/ form when you do not care which replica answers. Use the pod name when you are comparing replicas, because a random pick hides a bad node or a stale pod.

The image has no shell: the exact error and the fix

The Kubernetes debugging page demonstrates this with a minimal image. Trying to exec a shell into it fails like this:

text
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
The text is from the official debugging example. The same failure happens with distroless and scratch-based images.

The fix in the official page is an ephemeral debug container. kubectl debug adds a container to the running pod, with its own tools, and --target shares the process namespace of the container you are debugging. It does not restart the pod.

bash
# Attach a busybox debug container targeting the app container
kubectl debug -it my-api-7c9f -n prod --image=busybox:1.28 --target=my-api

# Inside it, look at the app's processes and files
ps aux
ls /proc/1/root/
--target shares the namespace of the app container so ps and /proc show its processes. The official example uses busybox with the target flag.

Do not patch the image in production to add a shell

Adding curl or bash to a production image to make exec work changes what runs in prod and the next build will remove it. An ephemeral container leaves the image alone and goes away with the pod.

Useful patterns for inspection

Most exec sessions are checks: is the config file the one I expect, does the process resolve the right hostname, is the disk full. These one-liners answer those questions without an interactive shell, so they are easy to put in a runbook.

bash
# What environment does the app see?
kubectl exec deploy/my-api -n prod -- env | sort

# Can the pod resolve and reach a dependency?
kubectl exec deploy/my-api -n prod -- getent hosts db.internal

# Disk use inside the container
kubectl exec deploy/my-api -n prod -- df -h
Each command needs the tool it calls inside the image. If getent or df is missing, use kubectl debug.
  • env inside exec shows the variables the container runs with. Compare it with the manifest when a value looks stale.
  • Exec into a crash-looping pod fails because the container is not running. Use kubectl logs --previous or kubectl debug on a copy of the pod instead.
  • Writing files with exec is a change to a running container, which the next restart erases. Use it to test a fix, then put the fix in the manifest.

Access control: exec is a powerful permission

A user who can exec into a pod can read its secrets from the environment and its mounted volumes, and can reach its network. Treat the exec permission as production access. In Kubernetes RBAC the permission is granted on the pods/exec subresource, so check which roles and service accounts hold it before you hand out cluster-wide read access.

On a shared cluster, pair exec permissions with an audit log, and use a namespace-scoped role for developers rather than a cluster role.

Frequently asked questions

kubectl exec: Run Commands and Open a Shell in a Pod: FAQ

What is the difference between kubectl exec and kubectl run?

kubectl exec runs a command inside a container that already exists. kubectl run creates a new pod. Use exec to inspect a running workload and run to start a separate pod for testing.

Why do I get "executable file not found in $PATH"?

The container image does not contain the program you asked for. The shell is missing or the command is not installed. Use kubectl debug with a debug image, or run the command from a pod that has the tool.

Does kubectl exec restart the pod or lose my changes?

No, exec does not restart the pod. But any file you write inside the container is lost when the container restarts, because the container filesystem is not persistent.

How do I exec into a specific container in a multi-container pod?

Add -c CONTAINER with the container name, for example kubectl exec -it my-api-7c9f -c sidecar -- sh. Without -c, kubectl uses the first container in the pod.

Sources

Checked 11 October 2026.

  1. Kubernetes: kubectl exec reference — Synopsis with -c and the -- separator, plus the examples for pods, deployments and services.
  2. Kubernetes: Debug Running Pods — The exact exec failure on an image with no shell, and the ephemeral debug container with --target.
  3. Kubernetes: kubectl logs reference — The --previous flag, used when a pod is crash-looping and exec cannot reach it.

Read next