SadServers
  • Scenarios
  • Labs
    All Labs Linux & Bash Web Servers Databases Data Processing Docker Kubernetes CI/CD Infrastructure as Code Tooling / Applications
  • Dashboard
  • Solutions
    For Individuals For Businesses
  • Ranking
  • Newsletter
  • Documentation
    FAQ Support Pro Accounts Pro+ Accounts Business Accounts Gift API CLI/TUI Privacy Troubleshooting Interviews
  • Blog
  • Pricing
  • Gift
    Gift Purchase Gift Redeem
  • About
Log In - Sign Up
  1. Labs
  2. Bash
  3. Troubleshooting

Guide

Concepts and learning path

Troubleshooting

Failure modes and fixes

Cheatsheet

Commands to keep handy

Bash troubleshooting

Set Bash "Strict Mode"

Use set -euo pipefail at the top of the script to exit the script if any command fails and treat references to unset/undefined variables as an error.

Script general check

Use ShellCheck to find bugs and errors in the script.

Script exits early or silently fails

Run bash -x script.sh. Verify shebang and chmod +x.

Command not found / wrong PATH

echo "$PATH", which , type -a . Cron and systemd use minimal PATH — use absolute paths.

Permission denied on redirect or script

Redirects run before the command — target file permissions matter.

Zombie or stuck background process

Use ps aux or pstreeto identify the parent process. Zombies cannot be killed directly; the parent must reap them or be restarted.

Debugging Output

Print variable state at failure points

echo "DEBUG: var=$var, status=$?" >&2

Send debug output to stderr so it doesn't pollute stdout or pipes.

Trace a specific section (not the whole script)

set -x # code you want to trace set +x

Better than running bash -x on the whole script when only one section is suspect.

Quoting & Whitespace

Unquoted variables break on spaces/globs

# Bad — breaks if $file has spaces cp $file /dest/ # Good cp "$file" /dest/

The majority of subtle bash bugs come down to missing quotes. When in doubt, quote it.

Exit Codes

Check $? immediately — it gets overwritten

some_command status=$? # capture right away if [[ $status -ne 0 ]]; then ...

Also remember $? reflects the last command, so a echo or [[ ]] check can clobber it.

Pipelines hide failures

# Only the last command's exit code is returned by default cat file | grep "x" | sort # Use pipefail or check PIPESTATUS echo "${PIPESTATUS[@]}"

Subshells & Scope

Variables set in subshells don't propagate up

# This won't work — the while loop runs in a subshell cat file | while read line; do result="$line" # lost after pipe ends done # Use process substitution instead while read -r line; do result="$line" done < cat file

This is a classic gotcha when piping into while read.

Conditionals & Test

[ vs [[ — use [[ in bash

[ "$var" == "x" ] # works in POSIX shells. [[ "$var" == "x" ]] # is Bash-specific and avoids word splitting and pathname expansion.

Check if a variable is empty vs unset

[[ -z "$var" ]] # true if empty OR unset [[ -v var ]] # true only if set (even if empty) [[ -n "$var" ]] # true if non-empty

File & Path Issues

Trailing newlines in command substitution

content=$(cat file) # strips trailing newlines silently

This is usually fine, but can surprise you with binary data or intentional blank lines.

Relative vs absolute paths in scripts

Scripts don't run from where you think — use this to anchor paths:

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" Anchors paths relative to the script location rather than the current working directory.

Functions & Return Values

Functions can't return strings — only exit codes (0–255)

# Wrong expectation get_name() { return "alice"; } # Correct pattern — use echo + capture get_name() { echo "alice"; } name=$(get_name)

IFS & Input Parsing

Unexpected field splitting from IFS

# If IFS contains space/tab/newline, variable expansion splits IFS=, read -r a b c <<< "one,two,three" # splits on comma # Reset when done IFS=$' \t\n'

Check IFS first when read or loops produce weird splits.

Reading lines safely

Without IFS= and -r, leading/trailing whitespace and backslashes may be modified unexpectedly.

# Correct usage while IFS= read -r line; do ... done < file

This is a common gotcha when reading lines from a file.

Heredocs

Indentation breaks heredocs unless you use <<-

# Fails — leading tabs/spaces are literal cat << EOF hello EOF # Use <<- to strip leading tabs (not spaces) cat <<- EOF hello EOF

Logging Pattern (General Best Practice)

A simple reusable logger saves a lot of echo noise:

log() { echo "[$(date +%T)] $*" >&2; } die() { log "ERROR: $*"; exit 1; } log "Starting backup..." [[ -d "$SRC" ]] || die "Source dir not found: $SRC"

Practice scenarios

Hands-on Bash scenarios on live Linux VMs: bash

Cheatsheet →
SadServersSadServers

Real-world Linux and DevOps scenarios for hands-on learning and technical assessment.

Uptime Robot ratio (30 days)
Product
  • Scenarios
  • For Individuals
  • For Businesses
  • Pricing
Resources
  • FAQ
  • Blog
  • Newsletter
Company
  • About Us
  • Support
  • Privacy Policy
  • Terms of Service
  • Contact
Connect With Us
info@sadservers.com

Made in Canada 🇨🇦
Updated: 2026-06-13 16:06 UTC – 2d2950a