Skip to content

Debugging Techniques

Intermediate BASH scripts often require meticulous debugging to identify logical errors, unexpected behavior, or resource issues. While set -x provides immediate visibility into script execution, tools like strace and gdb offer deeper insights into system-level interactions and compiled code. This section explores advanced debugging techniques to diagnose and resolve complex issues.


Debugging with `set -

The set -x option enables debug mode in BASH, printing each command as it is executed. This is invaluable for tracing script flow and identifying syntax or logic errors. When enabled, BASH outputs lines like + command arguments to indicate executed commands.

Example: Tracing Script Execution

#!/bin/bash
set -x
echo "Starting script"
ls /nonexistent
echo "End of script"

Running this script would produce:

+ echo 'Starting script'
Starting script
+ ls /nonexistent
ls: cannot access '/nonexistent': No such file or directory
+ echo 'End of script'
End of script

Key behaviors: - Commands are prefixed with +. - Output from commands (e.g., error messages) is still displayed. - Use set +x to disable debug mode after tracing.


Using strace for System Call Tracing

strace monitors system calls and signals, revealing how a process interacts with the kernel. This is particularly useful for diagnosing file I/O, process creation, or resource access issues.

Example: Tracing a Script's System Calls

strace -f ./script.sh

This command traces all system calls made by script.sh, including: - open() for file access - execve() for process execution - read()/write() for I/O operations

Filtering Output: Use -e trace=execve to focus on specific system calls:

strace -e trace=execve ./script.sh

Use Case: If a script fails to read a file, strace can show whether open() is being called on the correct path or if permissions are denied.


Advanced Debugging with gdb

gdb (GNU Debugger) is a powerful tool for debugging compiled programs. While BASH scripts are interpreted, gdb is essential for debugging compiled binaries, C programs, or other low-level code.

Example: Debugging a C Program

#include <stdio.h>
int main() {
    int x = 5;
    printf("Value: %d\n", x);
    return 0;
}

Compile with debugging symbols:

gcc -g -o debug_example debug_example.c

Debug with gdb:

gdb ./debug_example
(gdb) break main
(gdb) run
(gdb) print x

Use Case: gdb can step through code, inspect variables, and analyze crashes in compiled programs. For BASH scripts, it’s less common but still useful for debugging tools or compiled components integrated into scripts.


Key takeaways

  • set -x is ideal for tracing script execution and identifying syntax/logic errors.
  • strace helps diagnose system call-related issues like file access or resource limits.
  • gdb is critical for debugging compiled programs, though less directly applicable to BASH scripts.
  • Combine these tools to isolate problems at the script, system, or binary level.