0Pricing
Linux Server Deployment & SSH Mastery · Lesson

Error Handling and Logging in Scripts

Implement robust error handling, redirect script output, and generate meaningful logs to monitor script execution and troubleshoot issues.

Error Handling and Logging in Scripts is a free Linux Server Deployment & SSH Mastery lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Linux Server Deployment & SSH Mastery learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Make Your Scripts Reliable

Imagine your script running on a server, doing important work. What happens if something goes wrong?

  • Does it fail silently?
  • Does it leave a mess behind?
  • Can you tell when and why it failed?

Robust scripts handle errors gracefully and provide clear logs. This lesson teaches you how!

Understanding Exit Codes

Every command and script in Linux returns an exit code (or exit status) when it finishes. This number tells you if it succeeded or failed.

  • 0: Means success! Everything went well.
  • 1-255: Means failure. A specific number might indicate the type of error.

Let's see this in action:

#!/bin/bash
# This script demonstrates exit codes

echo "Attempting a successful command..."
ls /tmp
echo "Exit code for 'ls /tmp': $?"

echo

echo "Attempting a failing command..."
ls /nonexistent_directory
echo "Exit code for 'ls /nonexistent_directory': $?"

Check Command Status

After any command runs, you can check its exit code using the special variable $?. This is super useful for making decisions in your script.

You can use an if statement to react to success or failure:

#!/bin/bash
# Check if a file exists before trying to read it

FILENAME="test_file.txt"
touch $FILENAME # Create it for success case

if [ -f "$FILENAME" ]; then
  echo "File '$FILENAME' exists. Processing..."
  # ... do something with the file ...
  rm $FILENAME # Clean up
else
  echo "Error: File '$FILENAME' not found!"
  exit 1
fi

echo "Script finished."

`set -e`: Exit on Error

For simple scripts, manually checking $? everywhere can be tedious. The command set -e changes your script's behavior:

  • If any command exits with a non-zero status (fails), the script immediately terminates.
  • This prevents your script from continuing with potentially corrupted data or an invalid state.

Try running this script. What happens if the cp command fails?

#!/bin/bash
set -e

echo "Starting important operations..."
mkdir my_temp_dir
cp /nonexistent_source my_temp_dir/target # This will fail

echo "This line will not be reached if cp fails."
rmdir my_temp_dir
echo "Script finished successfully."

`trap` for Cleanup

Sometimes, even if a script fails, you need to perform cleanup tasks, like removing temporary files. The trap command allows you to catch signals (like an exit or error) and run a command.

  • EXIT: Runs when the script exits, regardless of success or failure.
  • ERR: Runs when a command exits with a non-zero status (if set -e is active).

Here, we ensure a temporary directory is always removed:

#!/bin/bash

TEMP_DIR="/tmp/my_script_temp_$(date +%s)"

function cleanup {
  echo "Cleaning up temporary directory: $TEMP_DIR"
  rm -rf "$TEMP_DIR"
}

trap cleanup EXIT

mkdir "$TEMP_DIR"
echo "Working in $TEMP_DIR..."
# Simulate some work, maybe it fails
# cp /nonexistent_file "$TEMP_DIR/" # Uncomment to test failure

echo "Script completed."

Redirecting Output

When your script runs, it often prints messages. These come in two main types:

  • Standard Output (stdout): Normal messages (file descriptor 1).
  • Standard Error (stderr): Error messages (file descriptor 2).

You can redirect these streams to files instead of the screen:

  • command > file: Redirects stdout to file.
  • command 2> file: Redirects stderr to file.

Let's save the success and error messages separately.

#!/bin/bash
# Redirect stdout to success.log and stderr to error.log

echo "This is a success message." > success.log
ls /nonexistent_path 2> error.log

echo "Check success.log and error.log files."
# To view them after running:
# cat success.log
# cat error.log

All Output to One File

Often, it's useful to have both standard output and standard error in a single log file for easier review. There are a couple of ways to do this:

  • command > file 2>&1: Redirects stdout to file, then redirects stderr to wherever stdout is going (the file).
  • command &> file: A shorter, more modern syntax for the same thing.

This is great for creating a comprehensive log of your script's execution.

#!/bin/bash
# Redirect both stdout and stderr to a single log file

LOG_FILE="combined_script.log"

echo "Starting script..." &> "$LOG_FILE"
echo "This message goes to stdout." &>> "$LOG_FILE"
ls /nonexistent_dir 2>&1 | tee -a "$LOG_FILE"
echo "Script finished." &>> "$LOG_FILE"

echo "Check the '$LOG_FILE' file for all output."

Timestamp Your Logs

When debugging, knowing when an event happened is critical. Adding timestamps to your log messages makes them much more useful.

You can prepend the current date and time to each log entry using the date command. This helps trace events in chronological order.

#!/bin/bash

LOG_FILE="timestamped_script.log"

function log_message {
  echo "$(date +%Y-%m-%d_%H:%M:%S) - $1" &>> "$LOG_FILE"
}

log_message "Script started."
sleep 1
log_message "Performing task A..."
# Simulate an error
ls /no_such_place || log_message "Error: Command failed."
sleep 1
log_message "Script finished."

echo "Check '$LOG_FILE' for timestamped entries."

Send to System Logs with `logger`

For important events, you might want to send messages directly to the system's logging facility (syslog). The logger command does exactly this.

  • System logs are often managed by tools like journalctl (on systemd systems).
  • This centralizes your script's important messages with other system events.
  • It's useful for critical errors or audit trails.

Messages sent with logger can be found using journalctl -f or tail -f /var/log/syslog (depending on your system).

#!/bin/bash
# Send a message to system logs

SCRIPT_NAME="MyBackupScript"

logger -t "$SCRIPT_NAME" "Starting daily backup operation."

# Simulate a task
sleep 2
if [ $(($RANDOM % 2)) -eq 0 ]; then
  logger -t "$SCRIPT_NAME" -p user.info "Backup successful."
else
  logger -t "$SCRIPT_NAME" -p user.err "Backup failed: Disk full."
fi

echo "Messages sent to system logs. Check with 'journalctl -t $SCRIPT_NAME'."

Error Handling Check

You've written a Bash script to process some files. You want the script to exit immediately if any command within it fails, and you also want to ensure a temporary directory is cleaned up no matter how the script exits.

Which two Bash commands would you primarily use to achieve this?

Recap & Next Steps

You've learned how to make your Bash scripts more robust and easier to debug!

  • Exit Codes: Understand command success/failure.
  • set -e: Automatically exit on error.
  • trap: Perform cleanup actions on script exit.
  • Output Redirection: Control where stdout and stderr go.
  • Timestamps: Add context to your logs.
  • logger: Integrate with system-wide logging.

By applying these techniques, your automated tasks will be more reliable and manageable. Keep practicing to build truly resilient automation!

Frequently asked questions

Is the “Error Handling and Logging in Scripts” lesson free?

Yes — the full text of “Error Handling and Logging in Scripts” is free to read here on the web, and the Linux Server Deployment & SSH Mastery course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Linux Server Deployment & SSH Mastery course, upgrade to CoddyKit PRO.

What will I learn in “Error Handling and Logging in Scripts”?

Implement robust error handling, redirect script output, and generate meaningful logs to monitor script execution and troubleshoot issues. You practise Linux Server Deployment & SSH Mastery with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Linux Server Deployment & SSH Mastery?

No prior experience is required. Linux Server Deployment & SSH Mastery on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Error Handling and Logging in Scripts” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Linux Server Deployment & SSH Mastery lesson?

Yes. Every Linux Server Deployment & SSH Mastery lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Introduction to Bash Scripting
  2. Automating Server Tasks
  3. Error Handling and Logging in Scripts
  4. Functions, Arguments, and Reusable Scripts
← Back to Linux Server Deployment & SSH Mastery