Basic Bash Commands for CKA
Essential commands for navigating and manipulating output during CKA exam. Master these to solve problems faster and more efficiently.
1. Text Processing – The Power Tools
grep – Search/Filter (Your First Line of Defense)
What it does: Searches for patterns in text. Think of it as Ctrl+F for the terminal.
Core Concepts:
- Regular Expressions: grep supports regex for complex pattern matching
- Context Lines: Show surrounding lines for better debugging
- Pipeline Integration: Works perfectly with kubectl output
# Basic search
kubectl get pods | grep nginx
# Case insensitive (-i flag)
kubectl get pods | grep -i NGINX
# Invert match (exclude lines with pattern using -v)
kubectl get pods | grep -v Running # Show only non-Running pods
# Context lines (critical for debugging Events/Logs)
kubectl describe pod nginx | grep -A5 "Events" # 5 lines AFTER match
kubectl describe pod nginx | grep -B3 "Error" # 3 lines BEFORE match
kubectl logs nginx | grep -C2 "error" # 2 lines before AND after (Context)
# Count matches (-c flag)
kubectl get pods -A | grep -c Running # How many Running pods?
# Multiple patterns (Extended regex with -E)
kubectl get pods | grep -E "nginx|apache|tomcat"
# Regular expressions
kubectl get pods | grep "nginx-[0-9]\+" # Match nginx-1, nginx-2, etc.
kubectl get pods | grep "^nginx" # Starts with nginx
kubectl get pods | grep "nginx$" # Ends with nginx
# Quiet mode (just exit code, no output - useful in scripts)
if kubectl get pods | grep -q "nginx"; then
echo "Found nginx pod"
fi
# Show only matching part (-o flag)
kubectl get pods -o wide | grep -oP '\d+\.\d+\.\d+\.\d+' # Extract IPs onlyPro Tips:
- Use
-Aand-Bto grab Events sections indescribeoutput -vis perfect for filtering out headers or unwanted states- Combine with
wc -lto count matches:kubectl get pods | grep -c Running
awk – The Swiss Army Knife of Column Extraction
What it does: Processes text line-by-line and extracts/transforms columns. Your go-to for parsing kubectl tabular output.
Core Concepts:
- Field Separator: By default, whitespace. Change with
-F - Built-in Variables:
$1,$2,$NF(last field),NR(line number),NF(number of fields) - Pattern Matching: Filter rows based on conditions
# Print specific columns
kubectl get pods | awk '{print $1}' # Column 1: Pod name
kubectl get pods | awk '{print $3}' # Column 3: Status
kubectl get pods | awk '{print $1, $3}' # Multiple columns with space
# Skip header (NR = Number of Records/Lines)
kubectl get pods | awk 'NR>1 {print $1}' # Start from line 2
# Conditional filtering
kubectl get pods | awk '$3=="Running" {print $1}' # Only Running pods
kubectl get pods | awk '$3!="Running" {print $1, $3}' # Non-Running with status
kubectl get pods -o wide | awk '$7=="node-1" {print $1}' # Pods on specific node
# Custom field separator (handle multiple spaces)
# Custom field separator (handle multiple spaces)
kubectl get pods -o wide | awk -F' +' '{print $7}' # Node column
echo "name:value:other" | awk -F':' '{print $2}' # Use colon as separator
# Print last field ($NF = Number of Fields)
echo "a b c d e" | awk '{print $NF}' # Prints "e"
# Formatted output
kubectl get pods | awk '{printf "%-30s %s\n", $1, $3}' # Aligned columns
# Math operations
kubectl top pods | awk 'NR>1 {print $1, $2, $3; sum+=$2} END {print "Total CPU:", sum}'
# BEGIN and END blocks
kubectl get pods | awk 'BEGIN {print "=== POD LIST ==="} NR>1 {print $1} END {print "=== END ==="}'Pro Tips:
$NFalways gets the last column (useful when column count varies)- Use
printffor aligned, readable output NR==1to process only the header,NR>1to skip it- Combine with
grep:kubectl get pods | grep Running | awk '{print $1}'
sed – Stream Editor for Text Transformation
What it does: Edits text streams (search/replace, delete, insert). Essential for quick YAML edits and text manipulation.
Core Concepts:
- Substitution:
s/pattern/replacement/flags - Deletion:
dcommand - In-place Editing:
-iflag modifies files directly - Address Ranges: Specify which lines to operate on
# Basic substitution (replaces FIRST occurrence per line)
echo "app=nginx" | sed 's/nginx/apache/' # app=apache
# Global replace (all occurrences using /g flag)
echo "nginx nginx nginx" | sed 's/nginx/apache/g' # apache apache apache
# Case-insensitive replace
echo "NGINX nginx Nginx" | sed 's/nginx/apache/gi' # apache apache apache
# Delete lines
kubectl get pods | sed '1d' # Delete first line (header)
kubectl get pods | sed '/Running/d' # Delete all lines containing "Running"
kubectl get pods | sed '/^$/d' # Delete empty lines
# Delete line ranges
sed '1,5d' file.yaml # Delete lines 1-5
sed '10,$d' file.yaml # Delete from line 10 to end
# In-place file editing (DANGEROUS - make backups!)
sed -i 's/replicas: 1/replicas: 3/' deployment.yaml # Edit file directly
sed -i.bak 's/old/new/' file.txt # Create backup as file.txt.bak
# Multiple operations (-e flag or semicolon separator)
sed 's/nginx/apache/; s/port: 80/port: 8080/' pod.yaml
sed -e 's/nginx/apache/' -e 's/80/8080/' pod.yaml
# Insert/Append lines
sed '2i\ replicas: 5' deployment.yaml # Insert before line 2
sed '2a\ replicas: 5' deployment.yaml # Append after line 2
# Replace specific line number
sed '5s/.*/ replicas: 10/' deployment.yaml # Replace entire line 5
# Advanced: Extract between patterns
sed -n '/Events:/,/Conditions:/p' pod-describe.txt # Print from Events to ConditionsPro Tips:
- Always test without
-ifirst! Pipe to| heador redirect to a new file - Use
sed -i.bakto create backups automatically - Combine with kubectl:
kubectl get deploy nginx -o yaml | sed 's/replicas: 1/replicas: 3/' | kubectl apply -f -
cut – Simple Field Extraction
What it does: Extracts columns from delimited text. Simpler than awk for straightforward tasks.
Core Concepts:
- Delimiter-based:
-dsets delimiter,-fspecifies field number - Character-based:
-cextracts by character position - Zero-indexed: Fields start at 1 (not 0)
# By delimiter
echo "name:value:other" | cut -d':' -f1 # Get "name"
echo "name:value:other" | cut -d':' -f2 # Get "value"
echo "name:value:other" | cut -d':' -f1,3 # Get "name:other"
# Character position
echo "hello world" | cut -c1-5 # "hello"
echo "kubernetes" | cut -c1,3,5 # "kbr"
# With kubectl (extract namespace from full pod name)
kubectl get pods -A -o name | cut -d'/' -f2 # pod/nginx-xxx -> nginx-xxx
# Extract IPs from CSV-like output
echo "10.0.1.5,nginx,Running" | cut -d',' -f1 # 10.0.1.5
# Multiple fields with different output delimiter
echo "a:b:c:d" | cut -d':' -f1,3 --output-delimiter=' ' # "a c"When to use cut vs awk:
- cut: Simple, single delimiter, fixed columns
- awk: Complex filtering, multiple conditions, math operations
sort & uniq – Data Organization
What it does: Sorts lines and removes duplicates. Critical for analyzing resource distributions.
# Basic sort
kubectl get pods | sort # Alphabetical
kubectl get pods | sort -r # Reverse
# Numeric sort (-n flag - CRITICAL for numbers!)
kubectl top pods | sort -k2 -n # Sort by CPU (column 2, numeric)
kubectl top pods | sort -k3 -nr # Sort by Memory, descending
# Sort by specific column (-k flag)
kubectl get pods -o wide | sort -k7 # Sort by Node name (column 7)
# Unique values
kubectl get pods -A -o jsonpath='{.items[*].spec.nodeName}' | tr ' ' '\n' | sort -u
# Count occurrences of unique values (classic pattern)
kubectl get pods -A | awk '{print $3}' | sort | uniq -c
# Output:
# 45 Running
# 3 Pending
# 2 CrashLoopBackOff
# Remove adjacent duplicates (requires sort first!)
kubectl get pods -A -o jsonpath='{.items[*].spec.nodeName}' | tr ' ' '\n' | sort | uniq
# Case-insensitive unique
sort -u -f file.txtPro Tips:
- Always use
-nfor numeric sorts! Otherwise "10" < "2" alphabetically uniqonly removes adjacent duplicates - alwayssortfirstsort -k2,2sorts by column 2 only (not from column 2 to end)
2. kubectl Output Formatting – Precision Extraction
JSONPath – The Query Language
What it does: Extracts specific fields from JSON output. Most powerful kubectl output method.
Core Concepts:
- Dot Notation:
.field.subfield - Array Access:
[*]for all items,[0]for first - Filters:
[?(@.field=="value")]for conditional selection - Range: Iterate over arrays
# Single field from single resource
kubectl get pod nginx -o jsonpath='{.status.phase}' # Running
kubectl get pod nginx -o jsonpath='{.spec.containers[0].image}' # nginx:latest
# All items (note the .items[*])
kubectl get pods -o jsonpath='{.items[*].metadata.name}' # space-separated names
# With newlines (critical for readability!)
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'
# Multiple fields per line
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
# Nested array access
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
# Conditional filtering
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
kubectl get pods -o jsonpath='{.items[?(@.spec.nodeName=="node-1")].metadata.name}'
# Complex example: Get all container images from all pods
kubectl get pods -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}'
# Array length
kubectl get pods -o jsonpath='{.items[*].metadata.name}' | wc -w # Count podsAdvanced Patterns:
# Get pod name and all container names
kubectl get pod nginx -o jsonpath='{.metadata.name}: {.spec.containers[*].name}'
# Node IPs
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'
# All pod IPs in namespace
kubectl get pods -n kube-system -o jsonpath='{.items[*].status.podIP}'Pro Tips:
- Use
{range...}{end}for clean line-by-line output {"\n"}for newline,{"\t"}for tab- Test with
| headto avoid overwhelming output - Wrap in quotes to handle spaces:
jsonpath='{.items[*].metadata.name}'
Custom Columns – Human-Readable Tables
What it does: Creates formatted tables with only the fields you need.
# Basic syntax
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase
# Multiple columns (comma-separated)
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP
# With custom headers
kubectl get pods -o custom-columns="POD NAME":.metadata.name,"CURRENT STATUS":.status.phase
# Complex nested fields
kubectl get pods -o custom-columns=NAME:.metadata.name,IMAGE:.spec.containers[0].image,STATUS:.status.phase
# All namespaces
kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase
# From file (reusable templates!)
cat > columns.txt << EOF
NAME:.metadata.name
STATUS:.status.phase
NODE:.spec.nodeName
IP:.status.podIP
EOF
kubectl get pods -o custom-columns-file=columns.txtWhen to use:
- Need formatted output for humans (not for parsing)
- Want column headers
- Prefer readability over scriptability
3. File Operations – Working with Manifests
cat/head/tail – File Reading
# View entire file
cat pod.yaml
# First 10 lines (default) or N lines
head pod.yaml
head -n 5 pod.yaml # First 5 lines
# Last 10 lines or N lines
tail pod.yaml
tail -n 20 pod.yaml # Last 20 lines
# Skip first N lines (useful to remove headers)
tail -n +2 file.txt # Start from line 2
# Follow file in real-time (-f flag - CRITICAL for logs!)
tail -f /var/log/syslog
kubectl logs -f nginx # Built-in follow
kubectl logs --tail=50 -f nginx # Last 50 lines, then follow
# Combine with grep for filtered real-time logs
kubectl logs -f nginx | grep ERRORwc – Word/Line/Character Count
# Count lines (-l flag)
kubectl get pods | wc -l # Total lines (includes header!)
kubectl get pods --no-headers | wc -l # Accurate pod count
# Count words (-w flag)
echo "hello world test" | wc -w # 3
# Count characters/bytes (-c flag)
echo "hello" | wc -c # 6 (includes newline!)
# Count without newline
echo -n "hello" | wc -c # 5
# Practical: How many Running pods?
kubectl get pods | grep Running | wc -lfind – File System Search
# Find by name
find /etc -name "*.conf" # All .conf files in /etc
find /var/log -name "*.log" # All log files
# Find by type
find /tmp -type f # Files only
find /tmp -type d # Directories only
# Find and execute command on results
find /etc -name "*.yaml" -exec grep "apiVersion" {} \; # Grep in all YAML files
find . -name "*.yaml" -exec kubectl apply -f {} \; # Apply all YAMLs
# Find modified in last N days
find /var/log -mtime -7 # Modified in last 7 days
find /tmp -mtime +30 # Modified more than 30 days ago
# Find by size
find / -type f -size +100M # Files larger than 100MB
find /var/log -type f -size +1G -delete # Delete files > 1GB
# Practical: Find all Kubernetes manifests
find /etc/kubernetes -name "*.yaml" -o -name "*.conf"4. Redirection & Pipes – Data Flow Control
Understanding File Descriptors:
0= stdin (standard input)1= stdout (standard output)2= stderr (standard error)
# Overwrite file (>)
kubectl get pods > pods.txt
# Output to file (append)
kubectl get pods >> pods.txt
# Redirect stderr
kubectl get badresource 2> error.txt
# Redirect both stdout and stderr
kubectl get pods &> all.txt
# Pipe to another command
kubectl get pods | grep nginx
# Here document
cat << EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
EOF5. Variables
# Set variable
NAME="nginx"
kubectl get pod $NAME
# Command substitution
POD=$(kubectl get pods -o jsonpath='{.items[0].metadata.name}')
kubectl exec $POD -- ls
# Get node name
NODE=$(kubectl get nodes -o name | head -1 | cut -d'/' -f2)6. Loops
# For loop
for pod in $(kubectl get pods -o name); do
kubectl describe $pod
done
# Delete all pods with pattern
for pod in $(kubectl get pods | grep test | awk '{print $1}'); do
kubectl delete pod $pod
done
# While read
kubectl get pods -o name | while read pod; do
echo "Processing $pod"
done7. Conditions
# Check if command succeeded
if kubectl get pod nginx; then
echo "Pod exists"
else
echo "Pod not found"
fi
# Check string equality
STATUS=$(kubectl get pod nginx -o jsonpath='{.status.phase}')
if [ "$STATUS" == "Running" ]; then
echo "Pod is running"
fi8. Quick CKA Patterns
Get Pod Names Only
kubectl get pods -o name
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods --no-headers | awk '{print $1}'Get Node Names
kubectl get nodes -o name | cut -d'/' -f2
kubectl get nodes -o jsonpath='{.items[*].metadata.name}'Get Pod IPs
kubectl get pods -o wide | awk '{print $6}'
kubectl get pods -o jsonpath='{.items[*].status.podIP}'Get Image Names
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
kubectl get pod nginx -o jsonpath='{.spec.containers[0].image}'Filter by Status
kubectl get pods --field-selector=status.phase=Running
kubectl get pods | awk '$3=="Running"'Count Resources
kubectl get pods --no-headers | wc -l
kubectl get pods -A --no-headers | wc -lExport YAML
kubectl get pod nginx -o yaml > nginx.yaml
kubectl get pod nginx -o yaml --export > nginx-clean.yaml # deprecatedDry Run
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deploy.yaml9. Base64 (for Secrets)
# Encode
echo -n "password" | base64
# Decode
echo "cGFzc3dvcmQ=" | base64 -d
# Decode secret
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d10. Quick Reference
| Task | Command |
|---|---|
| Filter lines | grep pattern |
| Extract column | awk '{print $N}' |
| Replace text | sed 's/old/new/g' |
| Skip header | tail -n +2 or awk 'NR>1' |
| Count lines | wc -l |
| Sort output | sort |
| Unique values | sort -u or sort | uniq |
| First N lines | head -n N |
| Last N lines | tail -n N |
| JSONPath | -o jsonpath='{.field}' |