All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
Adds title, description, type, domain, and tags frontmatter to every doc for improved KB semantic search. The description field is prepended to every search chunk, and domain/type/tags enable filtered queries. Type values: context, guide, runbook, reference, troubleshooting Domain values match directory structure (networking, docker, etc.) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
253 lines
4.9 KiB
Markdown
253 lines
4.9 KiB
Markdown
---
|
|
title: "Bash Script Troubleshooting"
|
|
description: "Troubleshooting guide for bash scripts covering debug modes (set -x), error traps, variable/parameter validation, file permission checks, process management, string comparison, and system resource monitoring."
|
|
type: troubleshooting
|
|
domain: development
|
|
tags: [bash, troubleshooting, debugging, scripting, error-handling, shell]
|
|
---
|
|
|
|
# Bash Script Troubleshooting Reference
|
|
|
|
## Script Debugging
|
|
|
|
### Enable debugging modes
|
|
```bash
|
|
#!/bin/bash
|
|
set -euo pipefail # Exit on error, undefined vars, pipe failures
|
|
set -x # Print commands as they're executed (xtrace)
|
|
|
|
# Or run with debug flags
|
|
bash -x script.sh
|
|
bash -n script.sh # Check syntax without execution
|
|
```
|
|
|
|
### Common error handling
|
|
```bash
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Function to handle errors
|
|
error_handler() {
|
|
echo "Error occurred in script at line: $1" >&2
|
|
echo "Command that failed: $2" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Set error trap
|
|
trap 'error_handler ${LINENO} "$BASH_COMMAND"' ERR
|
|
|
|
# Example with error checking
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo "Error: docker is not installed" >&2
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
## Variable and Parameter Issues
|
|
|
|
### Check if variables are set
|
|
```bash
|
|
# Check if variable is set and not empty
|
|
if [[ -z "${VAR:-}" ]]; then
|
|
echo "VAR is not set or empty"
|
|
exit 1
|
|
fi
|
|
|
|
# Set default values
|
|
VAR="${VAR:-default_value}"
|
|
VAR="${1:-default_value}" # For parameters
|
|
|
|
# Required variables
|
|
: "${REQUIRED_VAR:?Error: REQUIRED_VAR must be set}"
|
|
```
|
|
|
|
### Array debugging
|
|
```bash
|
|
# Declare array properly
|
|
declare -a array_name
|
|
array_name=("item1" "item2" "item3")
|
|
|
|
# Check array contents
|
|
declare -p array_name
|
|
printf '%s\n' "${array_name[@]}"
|
|
|
|
# Array length
|
|
echo "Array length: ${#array_name[@]}"
|
|
```
|
|
|
|
## File and Directory Issues
|
|
|
|
### File existence and permissions
|
|
```bash
|
|
# Check file existence
|
|
if [[ ! -f "$filename" ]]; then
|
|
echo "File $filename does not exist"
|
|
exit 1
|
|
fi
|
|
|
|
# Check directory existence
|
|
if [[ ! -d "$dirname" ]]; then
|
|
echo "Directory $dirname does not exist"
|
|
mkdir -p "$dirname"
|
|
fi
|
|
|
|
# Check permissions
|
|
if [[ ! -r "$filename" ]]; then
|
|
echo "File $filename is not readable"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -w "$filename" ]]; then
|
|
echo "File $filename is not writable"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### Path issues
|
|
```bash
|
|
# Get absolute path
|
|
filename="$(realpath "$1")"
|
|
dirname="$(dirname "$filename")"
|
|
basename="$(basename "$filename")"
|
|
|
|
# Change to script directory
|
|
cd "$(dirname "$0")"
|
|
```
|
|
|
|
## Process and Command Issues
|
|
|
|
### Command existence checking
|
|
```bash
|
|
# Check if command exists
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo "docker is required but not installed"
|
|
exit 1
|
|
fi
|
|
|
|
# Alternative method
|
|
if ! which docker >/dev/null 2>&1; then
|
|
echo "docker not found in PATH"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### Process management
|
|
```bash
|
|
# Check if process is running
|
|
if pgrep -x "process_name" >/dev/null; then
|
|
echo "Process is running"
|
|
else
|
|
echo "Process is not running"
|
|
fi
|
|
|
|
# Kill process safely
|
|
if pgrep -x "process_name" >/dev/null; then
|
|
pkill -x "process_name"
|
|
sleep 2
|
|
if pgrep -x "process_name" >/dev/null; then
|
|
pkill -9 -x "process_name"
|
|
fi
|
|
fi
|
|
```
|
|
|
|
## String and Text Processing
|
|
|
|
### String comparison issues
|
|
```bash
|
|
# Safe string comparison
|
|
string1="test"
|
|
string2=""
|
|
|
|
# Always quote variables
|
|
if [[ "$string1" == "test" ]]; then
|
|
echo "Match"
|
|
fi
|
|
|
|
# Check for empty strings
|
|
if [[ -z "$string2" ]]; then
|
|
echo "String is empty"
|
|
fi
|
|
|
|
if [[ -n "$string1" ]]; then
|
|
echo "String is not empty"
|
|
fi
|
|
```
|
|
|
|
### Input validation
|
|
```bash
|
|
# Validate numeric input
|
|
if ! [[ "$input" =~ ^[0-9]+$ ]]; then
|
|
echo "Error: Input must be a number"
|
|
exit 1
|
|
fi
|
|
|
|
# Validate email format (basic)
|
|
if ! [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]; then
|
|
echo "Error: Invalid email format"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
## System Resource Issues
|
|
|
|
### Disk space checking
|
|
```bash
|
|
# Check available disk space
|
|
available=$(df / | awk 'NR==2 {print $4}')
|
|
if [[ $available -lt 1000000 ]]; then # Less than 1GB
|
|
echo "Warning: Low disk space"
|
|
fi
|
|
|
|
# Check if directory has enough space
|
|
required_space=1000000 # 1GB in KB
|
|
available=$(df "$directory" | awk 'NR==2 {print $4}')
|
|
if [[ $available -lt $required_space ]]; then
|
|
echo "Error: Not enough disk space"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### Memory checking
|
|
```bash
|
|
# Check available memory
|
|
available_mem=$(free | awk 'NR==2 {print $7}')
|
|
if [[ $available_mem -lt 1000000 ]]; then # Less than 1GB
|
|
echo "Warning: Low available memory"
|
|
fi
|
|
```
|
|
|
|
## Debugging Techniques
|
|
|
|
### Add debug output
|
|
```bash
|
|
# Debug function
|
|
debug() {
|
|
if [[ "${DEBUG:-}" == "1" ]]; then
|
|
echo "DEBUG: $*" >&2
|
|
fi
|
|
}
|
|
|
|
# Usage
|
|
debug "Processing file: $filename"
|
|
```
|
|
|
|
### Temporary file handling
|
|
```bash
|
|
# Create temporary file safely
|
|
tmpfile=$(mktemp)
|
|
trap 'rm -f "$tmpfile"' EXIT
|
|
|
|
# Create temporary directory
|
|
tmpdir=$(mktemp -d)
|
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
```
|
|
|
|
### Script execution tracing
|
|
```bash
|
|
# Trace specific functions
|
|
trace_function() {
|
|
set -x
|
|
your_function_here
|
|
set +x
|
|
}
|
|
``` |