Practice Exercise: Bash Script Debugging Techniques
Objectives
- Learn how to debug Bash shell scripts effectively.
- Explore various debugging techniques and tools available for Bash scripting.
- Practice identifying and resolving common scripting errors.
Scenario
Debugging is a crucial skill for any Linux user or system administrator. In this exercise, you will learn and practice debugging techniques specific to Bash shell scripting. You will use debugging tools and strategies to identify and fix errors in Bash scripts.
Tasks
Task 1: Basic Script Debugging
- Create a Bash script named
basic_debugging.sh
. - Write a simple script that contains intentional errors (e.g., syntax errors, undefined variables).
- Attempt to run the script and document the error messages.
- Use basic debugging techniques like adding
echo
statements to identify the issues. - Debug the script step by step until it runs without errors.
- Document the debugging process and the changes made to the script.
- Let's go back to the sales.csv
Device,Quantity,Price Smartphone-A,10,599.99 Tablet,12,399.99 Smartphone-B,8,599.99 Laptop,6,999.99 Headphones-A,3,199.99 Headphones-B,7,159.99
- Let's make a script that calculates the total sales of each product
[intern@intern-a1t-inf-lnx1 ~]$ cat basic_debugging.sh #!/bin/bash awk -F',' 'NR > 1 {sales[$3] += $2 * $1} END {for (product in sales) print "Product Name:", product, "Sales:", sales[product]}' sales.csv [intern@intern-a1t-inf-lnx1 ~]$ chmod +x basic_debugging.sh [intern@intern-a1t-inf-lnx1 ~]$ ./basic_debugging.sh Product Name: 199.99 Sales: 0 Product Name: 399.99 Sales: 0 Product Name: 599.99 Sales: 0 Product Name: 999.99 Sales: 0 Product Name: 159.99 Sales: 0
- As you can see if you look at the csv file closely the sales shouldn't be zero
- What you can do is echo the parameters to see if you have it in the correct order
[intern@intern-a1t-inf-lnx1 ~]$ cat basic_debugging.sh #!/bin/bash awk -F',' 'NR > 1 {print $1" "$2" "$3" "} {sales[$3] += $2 * $1} END {for (product in sales) print "Product Name:", product, "Sales:", sales[product]}' sales.csv [intern@intern-a1t-inf-lnx1 ~]$ ./basic_debugging.sh Smartphone-A 10 599.99 Tablet 12 399.99 Smartphone-B 8 599.99 Laptop 6 999.99 Headphones-A 3 199.99 Headphones-B 7 159.99 Product Name: 199.99 Sales: 0 Product Name: 399.99 Sales: 0 Product Name: 599.99 Sales: 0 Product Name: 999.99 Sales: 0 Product Name: 159.99 Sales: 0 Product Name: Price Sales: 0
- You can see here that the
$1
is the Product name,$2
is the quantity and$3
is the price - So we just need to swap the positions of our parameters
[intern@intern-a1t-inf-lnx1 ~]$ cat basic_debugging.sh #!/bin/bash # {print $1" "$2" "$3" "} awk -F',' 'NR > 1 {sales[$1] += $2 * $3} END {for (product in sales) print "Product Name:", product, "Sales:", sales[product]}' sales.csv [intern@intern-a1t-inf-lnx1 ~]$ ./basic_debugging.sh Product Name: Tablet Sales: 4799.88 Product Name: Smartphone-A Sales: 5999.9 Product Name: Smartphone-B Sales: 4799.92 Product Name: Headphones-A Sales: 599.97 Product Name: Headphones-B Sales: 1119.93 Product Name: Laptop Sales: 5999.94
Task 2: Debugging with set -x
- Create a Bash script named
debugging_setx.sh
. - Write a script that performs a series of calculations or operations.
- Use the
set -x
option at the beginning of the script to enable debugging mode. - Run the script and observe how it displays each executed command and its output.
- Analyze the debugging output to identify any issues or unexpected behavior.
- Make necessary adjustments to the script to resolve any problems.
#!/bin/bash # Enable debugging mode set -x # This script performs a series of calculations or operations. # Example 1: Performing some calculations result=$((5 * 3)) echo "Result of 5 * 3 is: $result" # Example 2: Concatenating strings name="John" greeting="Hello, $name!" echo $greeting # Example 3: Running a command ls /nonexistentfolder # Example 4: Using an undefined variable echo "The value of an undefined variable is: $undefined_var" # Disable debugging mode set +x # Continue with the rest of the script echo "Script execution completed."
[intern@intern-a1t-inf-lnx1 ~]$ chmod +x debugging_setx.sh
[intern@intern-a1t-inf-lnx1 ~]$ ./debugging_setx.sh
+ result=15
+ echo 'Result of 5 * 3 is: 15'
Result of 5 * 3 is: 15
+ name=John
+ greeting='Hello, John!'
+ echo Hello, 'John!'
Hello, John!
+ ls /nonexistentfolder
ls: /nonexistentfolder: No such file or directory
+ echo 'The value of an undefined variable is: '
The value of an undefined variable is:
+ set +x
Script execution completed.
Task 3: Debugging with set -e
- Create a Bash script named
debugging_sete.sh
. - Write a script that simulates a process with multiple commands.
- Use the
set -e
option at the beginning of the script to enable immediate exit on error. - Introduce intentional errors within the script (e.g., using a command that should fail).
- Run the script and observe how it terminates immediately upon encountering an error.
- Debug the script to handle errors gracefully without exiting.
#!/bin/bash # Enable immediate exit on error set -e # This script simulates a process with multiple commands. # Example 1: Valid command echo "This is a valid command." # Example 2: Intentional error (command that should fail) ls /nonexistentfolder # Example 3: This command will not be executed due to the error above. echo "This command won't run because of the error." # Disable immediate exit on error for the remaining part of the script set +e # Continue with the rest of the script echo "Script execution completed."
[intern@intern-a1t-inf-lnx1 ~]$ chmod +x debugging_sete.sh [intern@intern-a1t-inf-lnx1 ~]$ ./debugging_sete.sh This is a valid command. ls: /nonexistentfolder: No such file or directory
Task 4: Using trap
for Error Handling
- Create a Bash script named
debugging_trap.sh
. - Write a script that performs a specific task.
- Implement a
trap
command to capture errors or signals (e.g., SIGINT) within the script. - Trigger an error condition (e.g., sending SIGINT with Ctrl+C) while the script is running.
- Observe how the
trap
command handles the error or signal. - Modify the script to perform custom error handling and clean-up actions.
#!/bin/bash trap "{ echo 'There was an error, aborting...'; exit 255; }" ERR SIGINT SIGTERM # This script performs a specific task. echo "Starting the task..." # Simulate an error condition (e.g., dividing by zero) ls /notexistingdirectory # This command won't be executed due to the error above. echo "This command won't run because of the error." # The script will terminate immediately upon encountering the error. # Any subsequent commands will not be executed. echo "This line will never be reached." # Continue with the rest of the script (if the custom error handler allows it). echo "Script execution completed."
[intern@intern-a1t-inf-lnx1 ~]$ chmod +x debugging_trap.sh [intern@intern-a1t-inf-lnx1 ~]$ ./debugging_trap.sh Starting the task... ls: /notexistingdirectory: No such file or directory There was an error, aborting...
Task 5: Debugging with bash -n
and bash -x
- Create a Bash script named
debugging_bash_n_x.sh
. - Write a script that contains potential errors, such as unmatched quotes or missing fi statements in conditionals.
- Use
bash -n
to perform a syntax check on the script without executing it. - Use
bash -x
to run the script in debug mode to identify issues. - Document the errors found and fix them in the script.
- Run the script again to ensure it executes without errors.
#!/bin/bash # This is a Bash script with potential errors for debugging practice # Uncomment the line below to introduce a syntax error (unmatched quotes) # echo "This line has a missing closing quote. # Uncomment the line below to introduce a missing 'fi' in a conditional statement # if [ 1 -eq 1 # then # echo "This line should not run." # fi # Uncomment the line below to introduce an undefined variable error # echo "The value of undefined_variable is: $undefined_variable" # Uncomment the line below to introduce a command that fails # This assumes you have a non-existent command; you can replace it with an actual command that fails # non_existent_command # Uncomment the line below to introduce a division by zero error # result=$((10 / 0)) # Uncomment the line below to introduce a successful command # echo "This line will run successfully." # Uncomment the line below to introduce a successful conditional statement # if [ 1 -eq 1 ] # then # echo "This line will run." # fi
[intern@intern-a1t-inf-lnx1 ~]$ bash -x debugging_bash_n_x.sh [intern@intern-a1t-inf-lnx1 ~]$ bash -n debugging_bash_n_x.sh
- Ran each
bash -x
andbash -n
whenever you uncomment and fix errors in the script
Conclusion
In this exercise, you've practiced various debugging techniques for Bash shell scripting. Debugging is an essential skill for resolving scripting errors efficiently. Understanding how to use debugging tools and strategies will help you write more reliable Bash scripts.