Kubernetes
Readiness Probe
Pipe Character
Command Line
Troubleshooting

Kubernetes How to pass pipe character in readiness probe command

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In a Kubernetes exec readiness probe, the command field is not parsed by a shell unless you explicitly run one. That is why putting | into the argument list does not create a pipeline. Kubernetes simply passes each item as a literal argument to the process.

So if you need shell syntax such as pipes, redirection, or &&, you must invoke /bin/sh -c or another shell yourself. If you do not actually need shell features, a direct command is usually better and simpler.

Why the Pipe Character Does Not Work by Itself

This probe looks like shell syntax, but it is not:

yaml
1readinessProbe:
2  exec:
3    command:
4      - cat
5      - /tmp/status
6      - "|"
7      - grep
8      - ready

Kubernetes does not join those tokens into a shell command line. The probe process literally receives | as an argument. No shell sees it, so no pipeline exists.

That behavior is the same reason wildcard expansion, output redirection, and environment-variable interpolation do not happen automatically in a plain exec.command list.

Use a Shell When You Truly Need a Pipeline

If the container image contains /bin/sh, wrap the whole command in sh -c.

yaml
1readinessProbe:
2  exec:
3    command:
4      - /bin/sh
5      - -c
6      - "cat /tmp/status | grep -q ready"
7  initialDelaySeconds: 5
8  periodSeconds: 10

Now the shell interprets the pipe and returns an exit code based on the pipeline result. grep -q ready exits with status 0 when the expected text is present, which makes the readiness probe succeed.

Prefer a Direct Command When Possible

A shell is not free. It adds quoting complexity and assumes the image actually contains a shell. If one binary can perform the whole check, skip the pipe entirely.

For the earlier example, grep can read the file directly:

yaml
1readinessProbe:
2  exec:
3    command:
4      - grep
5      - -q
6      - ready
7      - /tmp/status

This version is better because it:

  • avoids shell quoting
  • works in smaller images
  • fails only on the actual readiness condition, not on shell availability

The same rule applies to many probe commands. Start with the simplest executable form first.

Use a Script for Complex Probe Logic

If the readiness check becomes long, put it in a script inside the container image and call the script from the probe.

bash
1#!/bin/sh
2set -eu
3
4grep -q ready /tmp/status
5curl -fsS http://127.0.0.1:8080/internal/health >/dev/null

Then reference it in the manifest:

yaml
1readinessProbe:
2  exec:
3    command:
4      - /app/bin/readiness-check.sh

This keeps the manifest readable and makes the readiness logic testable outside Kubernetes.

Ask Whether exec Is the Right Probe Type

A surprising number of exec probe questions are really application health questions that would be cleaner with httpGet or tcpSocket.

For example, if the application already exposes an HTTP health endpoint, this is often better than parsing files with shell commands:

yaml
1readinessProbe:
2  httpGet:
3    path: /health
4    port: 8080

Use exec when the health check genuinely depends on container-local state that another probe type cannot express.

Container Image Constraints Matter

Do not assume /bin/bash exists. Many minimal images only have /bin/sh, and some distroless images have no shell at all. If your probe relies on sh -c, that dependency becomes part of the image contract.

When a probe suddenly starts failing after an image change, this is one of the first things to check.

Common Pitfalls

The biggest mistake is treating exec.command as if Kubernetes were typing a line into a terminal. It is not. Another is reaching for sh -c even when a single command would do the job more reliably. Teams also break probes by depending on /bin/bash in images that only include /bin/sh, or by packing too much business logic into a readiness probe that should have been an application health endpoint. Simpler probes are easier to debug and less likely to fail for unrelated environmental reasons.

Summary

  • Kubernetes exec.command does not interpret | by default.
  • Use /bin/sh -c only when you genuinely need shell syntax.
  • Prefer direct command arguments when one executable can perform the check alone.
  • Move complicated checks into a script or an HTTP health endpoint.
  • Match the probe design to what actually exists in the container image.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.