乐闻世界logo
搜索文章和话题

How to perform error handling and debugging in Shell scripts? What are the common techniques?

3月6日 23:38

Error handling and debugging techniques in Shell scripts are crucial for writing robust scripts.

Error Handling

Exit Status Codes

bash
# Check command execution status command if [ $? -eq 0 ]; then echo "Command succeeded" else echo "Command failed with exit code $?" fi # Use && and || for conditional execution command1 && command2 # command2 executes only if command1 succeeds command1 || command2 # command2 executes only if command1 fails

set Command Options

bash
# set -e: Exit immediately if any command fails set -e command1 command2 # Won't execute if command1 fails # set -u: Error when using undefined variables set -u echo $undefined_var # Error and exit # set -o pipefail: Return failure status if any command in pipe fails set -o pipefail command1 | command2 # Entire pipe fails if command1 fails # Combine options set -euo pipefail

Error Handling Functions

bash
# Error handling function error_exit() { echo "Error: $1" >&2 exit 1 } # Check if file exists check_file() { if [ ! -f "$1" ]; then error_exit "File $1 not found" fi } # Use function check_file "config.txt"

trap Command

bash
# Catch exit signals cleanup() { echo "Cleaning up..." rm -f /tmp/tempfile exit } # Catch EXIT signal trap cleanup EXIT # Catch INT signal (Ctrl+C) trap cleanup INT # Catch multiple signals trap cleanup EXIT INT TERM

Debugging Techniques

Debug Mode

bash
# Enable debug mode set -x # Print each command set -v # Print input lines # Disable debug mode set +x set +v # Combine usage set -xv command1 command2 set +xv

Debug Output

bash
# Use echo for debug output echo "Debug: variable = $variable" # Use printf for formatted output printf "Debug: %s = %s\n" "variable" "$variable" # Use >&2 to output to stderr echo "Debug info" >&2

Debug Functions

bash
# Debug function debug() { if [ "$DEBUG" = "true" ]; then echo "[DEBUG] $*" >&2 fi } # Use debug function DEBUG=true debug "Processing file: $filename"

Variable Tracing

bash
# Display variable values echo "var1 = $var1" echo "var2 = $var2" # Use declare to show variable information declare -p var1 declare -p var2 # Display all variables declare -p # Display all functions declare -f

Practical Application Examples

Robust Script Template

bash
#!/bin/bash # Set error handling set -euo pipefail # Define error handling function error_exit() { echo "Error: $1" >&2 exit 1 } # Define cleanup function cleanup() { echo "Cleaning up..." [ -n "$tempfile" ] && rm -f "$tempfile" } # Set traps trap cleanup EXIT INT TERM # Define debug function debug() { if [ "${DEBUG:-false}" = "true" ]; then echo "[DEBUG] $*" >&2 fi } # Main function main() { debug "Starting script" # Check parameters if [ $# -lt 1 ]; then error_exit "Usage: $0 <filename>" fi local filename="$1" debug "Processing file: $filename" # Check file if [ ! -f "$filename" ]; then error_exit "File not found: $filename" fi # Create temp file tempfile=$(mktemp) || error_exit "Failed to create temp file" debug "Created temp file: $tempfile" # Process file cp "$filename" "$tempfile" # Processing logic... debug "Script completed successfully" } # Execute main function main "$@"

File Operations with Error Checking

bash
#!/bin/bash # Safe file copy safe_copy() { local src="$1" local dst="$2" # Check source file if [ ! -f "$src" ]; then echo "Error: Source file not found: $src" >&2 return 1 fi # Check destination directory local dst_dir=$(dirname "$dst") if [ ! -d "$dst_dir" ]; then echo "Error: Destination directory not found: $dst_dir" >&2 return 1 fi # Check write permission if [ ! -w "$dst_dir" ]; then echo "Error: No write permission for: $dst_dir" >&2 return 1 fi # Execute copy if ! cp "$src" "$dst"; then echo "Error: Failed to copy $src to $dst" >&2 return 1 fi echo "Successfully copied $src to $dst" return 0 } # Use function safe_copy "source.txt" "destination.txt" || exit 1

Operations with Retry

bash
#!/bin/bash # Function with retry retry_command() { local max_attempts="$1" shift local command=("$@") local attempt=1 while [ $attempt -le $max_attempts ]; do echo "Attempt $attempt of $max_attempts" if "${command[@]}"; then echo "Command succeeded" return 0 fi attempt=$((attempt + 1)) sleep 2 done echo "Command failed after $max_attempts attempts" >&2 return 1 } # Use function retry_command 3 curl -s http://example.com || exit 1

Logging

bash
#!/bin/bash # Log function log() { local level="$1" shift local message="$*" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "[$timestamp] [$level] $message" | tee -a script.log } log_info() { log "INFO" "$@" } log_error() { log "ERROR" "$@" } log_debug() { if [ "${DEBUG:-false}" = "true" ]; then log "DEBUG" "$@" fi } # Use log functions log_info "Script started" log_debug "Debug information" log_error "An error occurred"

Debugging Best Practices

  1. Use set -euo pipefail: Improve script robustness
  2. Use trap for cleanup: Ensure resources are properly released
  3. Use debug functions: Easy to control debug output
  4. Log events: Facilitate problem tracking and debugging
  5. Check command status: Use $? or if statements
  6. Use meaningful error messages: Help quickly locate problems
  7. Test edge cases: Ensure script works in various scenarios
  8. Use variable defaults: ${VAR:-default} prevents undefined variable errors
标签:Shell