Skip to content

Script Best Practices — Writing Professional Bash Scripts

Script Best Practices are a set of guidelines that help you write Bash scripts that are clean, readable, maintainable, secure, efficient, and reliable. While it is possible to write a script that simply works, production-quality scripts should also be easy to understand, debug, extend, and operate safely. Following best practices is essential for Linux administrators, DevOps engineers, Cloud Architects, Platform Engineers, and Site Reliability Engineers (SREs) who build automation for enterprise environments.


Learning Path

Linux Mastery → Module 10: Bash Scripting → Lesson 10

Difficulty: Beginner → Advanced

Reading Time: 90 Minutes

Course Progress

Course: Linux Mastery

Module: Bash Scripting

Lesson: 10 of 11


What You'll Learn

After completing this lesson, you'll be able to:

  • Write clean and readable scripts
  • Organize code effectively
  • Follow naming conventions
  • Validate user input
  • Handle errors gracefully
  • Improve script security
  • Optimize performance
  • Build production-ready Bash scripts

Prerequisites

Complete:

  • Modules 1–9
  • Module 10 Lessons 1–9

Why Follow Best Practices?

Imagine two administrators maintaining the same script.

Poorly written script:

a=$1

b=$2

c=$((a+b))

echo $c

Improved script:

FIRST_NUMBER=$1

SECOND_NUMBER=$2

SUM=$((FIRST_NUMBER + SECOND_NUMBER))

echo "$SUM"

The second script is easier to understand, maintain, and debug.


Write Readable Code

Use meaningful names.

Good:

BACKUP_DIR="/backup"

Poor:

b="/backup"

Readable scripts reduce maintenance effort.


Use Comments

Explain complex logic.

# Create a compressed backup

tar -czf backup.tar.gz /data

Avoid comments that simply repeat the code.

Poor:

# Echo hello

echo "Hello"

Use Consistent Naming

Variables:

BACKUP_DIR

LOG_FILE

SERVER_NAME

Functions:

create_backup()

check_disk_space()

restart_service()

Choose one naming style and use it consistently.


Use Strict Mode

Enable safer script execution.

#!/bin/bash

set -euo pipefail

Benefits:

  • Exit on command failures
  • Detect undefined variables
  • Detect pipeline failures

Quote Variables

Always quote variables unless unquoted expansion is specifically required.

Good:

cp "$SOURCE" "$DESTINATION"

Poor:

cp $SOURCE $DESTINATION

Quoting prevents unexpected word splitting and filename expansion.


Validate User Input

Check required values before using them.

if [ $# -lt 1 ]
then
    echo "Usage: ./backup.sh <directory>"

    exit 1
fi

Check Command Success

Prefer:

if cp file1 file2
then
    echo "Success"
else
    echo "Failed"
fi

Instead of assuming every command succeeds.


Use Functions

Organize scripts into reusable components.

backup() {

    tar -czf backup.tar.gz /data
}

Functions reduce duplicated code.


Keep Functions Small

Each function should perform one task.

Good:

create_backup()

send_notification()

cleanup()

Avoid one function performing many unrelated operations.


Handle Errors Properly

Display meaningful messages.

echo "Error: Backup directory not found."

exit 1

Log Important Events

Record significant operations.

echo "$(date '+%F %T') Backup Started" >> backup.log

Logs simplify troubleshooting.


Avoid Hardcoded Values

Poor:

cp file.txt /backup

Better:

BACKUP_DIR="/backup"

cp file.txt "$BACKUP_DIR"

Use Constants

Values that should not change can be defined once.

readonly LOG_FILE="/var/log/app.log"

Use Descriptive Exit Codes

exit 0

Success.

exit 1

General failure.

Document custom exit codes if they are used.


Clean Up Temporary Files

Use trap.

cleanup() {

    rm -f "$TEMP_FILE"
}

trap cleanup EXIT

Minimize Root Usage

Run scripts as a regular user whenever possible.

Use sudo only for operations requiring elevated privileges.


Never Store Secrets in Scripts

Avoid:

PASSWORD="mypassword"

Instead:

  • Read from environment variables
  • Prompt securely using read -s
  • Use a secrets management solution when appropriate

Use ShellCheck

Analyze scripts for common issues.

shellcheck script.sh

ShellCheck identifies syntax problems and recommends improvements.


Test Scripts

Test:

  • Valid input
  • Invalid input
  • Missing files
  • Permission errors
  • Network failures
  • Edge cases

Testing helps identify problems before deployment.


Common Commands

Analyze script.

shellcheck script.sh

Run script.

bash script.sh

Enable debugging.

bash -x script.sh

Check syntax.

bash -n script.sh

Real Production Examples

Validate input.

[ $# -lt 1 ] && exit 1

Log execution.

echo "$(date) Starting deployment" >> deploy.log

Handle cleanup.

trap cleanup EXIT

Use strict mode.

set -euo pipefail

Production Perspective

Best practices are essential for:

  • DevOps automation
  • CI/CD pipelines
  • Cloud infrastructure
  • Kubernetes administration
  • Backup systems
  • Monitoring solutions
  • Security automation
  • Enterprise operations

Following consistent standards improves reliability, maintainability, and team collaboration.


Hands-on Lab

Task 1

Enable strict mode.

set -euo pipefail

Task 2

Quote variables.

cp "$SOURCE" "$DESTINATION"

Task 3

Validate script arguments.

if [ $# -lt 1 ]
then
    exit 1
fi

Task 4

Create a reusable function.

backup() {

    echo "Backup Started"
}

Task 5

Log script execution.

echo "$(date) Running Script" >> app.log

Task 6

Check syntax.

bash -n script.sh

Task 7

Run ShellCheck.

shellcheck script.sh

Task 8

Run the script in debug mode.

bash -x script.sh

Command Deep Dive

Command Purpose Production Example
set -euo pipefail Enable strict mode Safe automation
shellcheck Analyze scripts Code quality
bash -n Syntax check Validation
bash -x Debug execution Troubleshooting
readonly Define constants Configuration
trap Cleanup resources Temporary file removal

Common Script Mistakes

Mistake Solution
Hardcoded values Use variables
No input validation Validate arguments
Ignoring errors Handle failures
No logging Record important events
Large monolithic scripts Use functions

Production Troubleshooting Scenario

Scenario

A deployment script occasionally fails, but no one knows why.

Problems:

  • No logging
  • No error handling
  • No input validation
  • Hardcoded values

Improved script:

#!/bin/bash

set -euo pipefail

log() {

    echo "$(date '+%F %T') $1"
}

log "Deployment Started"

if [ $# -lt 1 ]
then
    log "Missing deployment file."

    exit 1
fi

kubectl apply -f "$1"

log "Deployment Completed"

The script is now safer, easier to troubleshoot, and suitable for production use.


Best Practices

  • Write readable code.
  • Use meaningful variable and function names.
  • Enable set -euo pipefail.
  • Quote variables.
  • Validate all user input.
  • Handle errors gracefully.
  • Log important events.
  • Use functions to organize code.
  • Avoid hardcoded values.
  • Test scripts thoroughly.
  • Run ShellCheck before deployment.

Common Mistakes

❌ Hardcoding configuration values.

✅ Avoid this mistake: hardcoding configuration values.


❌ Ignoring command failures.

✅ Always review command failures.


❌ Writing scripts without comments or documentation.

✅ Avoid this mistake: writing scripts without comments or documentation.


❌ Forgetting to validate user input.

✅ Remember to to validate user input.


❌ Not testing scripts before production deployment.

✅ Always testing scripts before production deployment.


Interview Questions

Beginner

  1. Why are Bash scripting best practices important?
  2. Why should variables be quoted?
  3. What does set -euo pipefail do?
  4. Why should functions be used?

Intermediate

  1. Why should input always be validated?
  2. What is ShellCheck?
  3. How do logs improve troubleshooting?
  4. Why should scripts avoid hardcoded values?

Architect Level

  1. How would you define coding standards for Bash scripts in an enterprise?
  2. How would you ensure all automation scripts meet security and quality requirements?
  3. What practices improve the maintainability of large Bash automation projects?

Summary

In this lesson, you learned:

  • Readable scripting
  • Naming conventions
  • Comments and documentation
  • Strict mode
  • Variable quoting
  • Input validation
  • Error handling
  • Logging
  • Security practices
  • Performance considerations
  • Script testing

Following Bash scripting best practices produces automation that is reliable, secure, maintainable, and scalable. These practices reduce operational risks, simplify troubleshooting, and make scripts easier for teams to understand and maintain over time.


Key Takeaways

  • Write clean, readable, and well-organized scripts.
  • Use meaningful variable and function names.
  • Enable set -euo pipefail for safer execution.
  • Validate input and handle errors consistently.
  • Log important events for troubleshooting.
  • Test scripts thoroughly before production use.
  • Use tools such as shellcheck, bash -n, and bash -x to improve script quality.

What's Next?

Module 10 Summary — Bash Scripting

Review the module, then continue to Module 11 – Linux Security.