# Day-11 of #90DaysOfDevops : Error Handling in Shell Scripting: A Key Aspect of Robust DevOps Automation

In the world of DevOps, shell scripting plays an essential role in automating repetitive tasks. However, to ensure reliability and smooth execution, it's crucial to handle errors effectively within scripts. In this blog post, I’ll walk through some fundamental error handling techniques in Bash scripting, which will help you create more resilient automation scripts.

### **Why is Error Handling Important?**

In a real-world environment, scripts often interact with files, directories, and external systems. If an unexpected error occurs (e.g., missing files, permission issues), it could result in unexpected behavior. By anticipating potential failures and gracefully handling them, we can prevent scripts from crashing, create better logs, and improve troubleshooting.

### **1\. Understanding Exit Status**

Every command in Linux returns an **exit status**:

* **0** means success.
    
* **Non-zero** means failure (any non-zero value indicates an error).
    

In this section, we’ll look at how to check the exit status after a command to determine if it executed successfully.

**Example: Checking Exit Status**

```bash
#!/bin/bash

<<Info
Author      : Amitabh Soni
Date        : 6/12/24
Description : This script attempts to create a directory and checks if the command was successful. If not, it prints an error message.
Info

# Creating directory
mkdir -p task1

# Checking if the previous command got executed or not
if [[ $? -eq 0 ]]; then
    echo "Directory 'task1' successfully created."
else
    echo "ERROR: Failed to create directory 'task1'. Please check your permissions or try again."
fi
```

**What’s happening here?**

* The `mkdir` command tries to create a directory.
    
* `$?` holds the exit status of the last command.
    
* If the exit status is 0, the directory was created successfully; otherwise, an error occurred.
    

**Output:**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503458396/c0743fe3-1a6e-401c-96da-4de6145fb970.png align="center")

---

### **2\. Using** `if` Statements for Error Checking

It's common to execute multiple commands in a script, and it's crucial to check for errors at each step. Using `if` statements ensures that each command is checked for success before proceeding to the next.

**Example: File Creation with Error Checking**

```bash
#!/bin/bash

<<Info
Author      : Amitabh Soni
Date        : 6/12/24
Description : This is a script that attempts to create a directory and checks if the command was successful. If not, print an error message.
Info

# Task 1
# Creating directory
mkdir -p task1

# Checking if the previous command got executed or not
if [[ $? -eq 0 ]]; then
    echo "Directory 'task1' successfully created."
else
    echo "ERROR: Failed to create directory 'task1'. Please check your permissions or try again."
fi

# Task 2
# Checking if directory 'task1' exists
if [[ -d task1 ]]; then

    # Checking if file already exists
    if [[ -f task1/task1.txt ]]; then
        echo "File 'task1.txt' already exists in 'task1'."
    else

        # Create the file if it does not exist
        touch task1/task1.txt

        if [[ $? -eq 0 ]]; then
            echo "File 'task1.txt' successfully created in 'task1'."
        else
            echo "ERROR: Failed to create file 'task1.txt' in 'task1'."
        fi
    fi
else
    echo "ERROR: Directory 'task1' does not exist. Cannot create file."
fi
```

This script first creates a directory, then checks for the existence of a file inside it. If the file doesn’t exist, it creates the file, handling errors at every stage.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503645586/b7b0297c-1d59-46fb-9095-39c380acdb3d.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503661087/6d9f390c-2615-4885-9b5f-7d4e8865ea6e.png align="center")

---

### **3\. Using** `trap` for Cleanup

When scripts encounter errors, you might want to perform some **cleanup** (e.g., deleting temporary files or undoing changes). The `trap` command allows you to execute actions when a script exits unexpectedly.

**Example: Using** `trap` for Cleanup

```bash
#!/bin/bash

<<Info
Author      : Amitabh Soni
Date        : 6/12/24
Description : This script creates a temporary file and sets a trap to delete the file if the script exits unexpectedly.
Info

# Create a temporary directory
mkdir -p tmp

# Create a temporary file inside the directory
touch tmp/temp1.txt
echo "This is a temporary file." > tmp/temp1.txt

# Set a trap to delete the temporary file if the script exits unexpectedly (due to an error)
trap "rm -f tmp/temp1.txt; echo 'Temporary file deleted due to error.'" ERR

# Simulate script work here
echo "Script is running. The temporary file has been created."

# Uncomment the next line to simulate an error and test the trap
invalid_command  # This will trigger an error and activate the trap

# Check the exit status of the previous command to decide what happens next
if [[ $? -ne 0 ]]; then
    # Error occurred, file has been deleted by the trap
    echo "An error occurred, script exiting."
else
    # No error, continue execution
    echo "Script completed successfully. Temporary file will not be deleted."
fi
```

Here, the `trap` command ensures that the temporary file is deleted when an error occurs in the script, preventing unnecessary clutter on the filesystem.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503688449/cb166e07-1057-4e62-ac41-78c045990af8.png align="center")

---

### **4\. Redirecting Errors**

Sometimes, you may want to redirect error messages to a file for later review instead of displaying them on the terminal. You can achieve this using output redirection.

**Example: Redirecting Errors to a Log File**

```bash
#!/bin/bash

<<Info
Author      : Amitabh Soni
Date        : 6/12/24
Description : This script attempts to read a non-existent file and redirects the error message to a file called error.log.
Info

# Attempting to read a non-existent file
cat non_existent_file.txt 2> error.log

# Checking if error.log has been created and displaying the error message
if [[ -f error.log ]]; then
    echo "Error has been logged to error.log"
else
    echo "No error occurred."
fi
```

In this script, the error message generated by attempting to read a non-existent file is redirected to `error.log`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503714944/4bef998a-eb01-4a53-b6be-849ab94d183f.png align="center")

---

### **5\. Customizing Error Messages**

By adding custom error messages, we can make it easier for users or developers to understand the nature of a problem. This is particularly useful when debugging or reporting issues.

**Example: Custom Error Messages**

```bash
#!/bin/bash

<<Info
Author      : Amitabh Soni
Date        : 6/12/24
Description : This script attempts to read a non-existent file and redirects the error message to a file called error.log with custom error messages.
Info

# Attempting to read a non-existent file
echo "Attempting to read a non-existent file: non_existent_file.txt"
cat non_existent_file.txt 2> error.log

# Custom error message for failure
if [[ -f error.log ]]; then
    echo "Custom Error Message: The file 'non_existent_file.txt' does not exist or cannot be read." >> error.log
    echo "The error has been logged to error.log with more context."
else
    echo "No error occurred."
fi
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733503736114/a69a183b-cd03-4431-978d-64673550bbb2.png align="center")

---

### **Conclusion**

Handling errors gracefully is a critical skill for any DevOps practitioner. By using the right tools like exit status checks, `trap` for cleanup, error redirection, and custom messages, we can ensure that our shell scripts are robust and dependable. These techniques will help you write better automation scripts that handle unexpected failures effectively.

Happy Scripting!

---

**Don't forget to check out my DevOps learning journey:**

[LinkedIn](https://linkedin.com/in/amitabh-devops)

---

**Call to Action:**

* Let me know if you have any questions about error handling in shell scripting.
    
* Follow my #90DaysOfDevOps challenge on Hashnode to learn more DevOps tips!
