Scripting Best Practices & Linting
Learn about coding conventions, commenting, and using tools like ShellCheck to write clean, readable, and error-free Bash scripts.
Scripting Best Practices & Linting is a free DevOps Bootcamp 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 DevOps Bootcamp learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Scripting Best Practices?
Writing Bash scripts is powerful, but without good habits, scripts can become hard to understand, maintain, and debug.
Best practices are guidelines that help you write clean, robust, and readable code. They make your scripts:
- Easier to Read: For yourself and others.
- More Maintainable: Simpler to update or fix.
- Less Error-Prone: Preventing common mistakes.
- Better for Collaboration: Standardizing how code looks and behaves.
Commenting for Clarity
Comments are crucial for explaining why your code does something, not just what it does. They act as notes for future you or other developers.
Use comments to:
- Describe the script's overall purpose at the top.
- Explain complex logic or tricky sections.
- Document functions: their purpose, arguments, and return values.
Start a comment with a # (hash) symbol.
#!/bin/bash
# This script demonstrates commenting best practices.
# Author: CoddyKit
# Date: 2023-10-27
# Function: greet_user
# Description: Prints a greeting message to the console.
# Arguments:
# $1 - The name of the user to greet.
greet_user() {
local name="$1" # Store the first argument in a local variable.
echo "Hello, ${name}!" # Output the greeting message.
}
# Main script execution starts here.
echo "Script execution started."
greet_user "CoddyKit Learner" # Call the function with a specific name.
echo "Script execution finished."Clear Naming Conventions
Meaningful names make your script easier to follow. Avoid single-letter variables unless they're common loop counters (like i or j).
General conventions:
- Variables: Use descriptive names (e.g.,
user_name,log_file). UseUPPERCASEfor environment variables or global constants. Uselowercase_with_underscoresfor local script variables. - Functions: Use
lowercase_with_underscores, often starting with a verb (e.g.,process_data,check_status). - Scripts: Use
lowercase_with_hyphens(e.g.,backup-script.sh).
Consistent Formatting & Indentation
Consistent formatting, like indentation and spacing, dramatically improves readability. Imagine reading a book with inconsistent paragraph indents!
Key points:
- Use 2 or 4 spaces for indentation (tabs are often discouraged).
- Keep lines short (under 80 characters is a good rule of thumb for terminals).
- Use blank lines to separate logical blocks of code.
- Align related elements where it makes sense.
Consistency is more important than the specific style you choose.
Robustness: 'set -u' (nounset)
The set -u (or set -o nounset) option is a lifesaver for preventing bugs caused by typos or accidentally unset variables. If your script tries to use a variable that hasn't been assigned a value, set -u will immediately exit the script with an error.
This helps catch errors early, preventing unexpected behavior later in your script.
Try running the code below. It's designed to exit early because UNSET_NAME is not defined.
#!/bin/bash
# Demonstrating 'set -u' (nounset)
set -u # Exit if an unset variable is used
MY_GREETING="Hello"
echo "${MY_GREETING}, CoddyKit!"
# This variable is NOT set. With 'set -u', the script will exit here.
echo "Your name is: ${UNSET_NAME}"
echo "This line will NOT be reached if 'set -u' is active and UNSET_NAME is indeed unset."Robustness: 'set -o pipefail'
When you pipe commands (e.g., cmd1 | cmd2 | cmd3), Bash normally only reports the exit status of the last command in the pipe. This means if cmd1 fails, but cmd2 and cmd3 succeed, the pipe might still report success!
set -o pipefail changes this behavior. If any command in a pipe fails (returns a non-zero exit status), the entire pipe's exit status will be that non-zero status.
This makes your pipelines more reliable by immediately signaling if an early command failed.
#!/bin/bash
# Demonstrating 'set -o pipefail'
set -o pipefail # Ensures pipe's exit status is the last non-zero command
echo "Running a failing command in a pipe:"
echo "---"
# 'false' command always fails (exit status 1).
# 'cat /dev/null' always succeeds (exit status 0).
# With 'set -o pipefail', the pipe's overall exit status will be 1 from 'false'.
false | cat /dev/null
# This line will only be reached if the pipe above succeeds.
echo "---"
echo "Script finished successfully (this line won't show if pipe failed with set -o pipefail)."Introducing ShellCheck
Even with best practices, it's easy to overlook small syntax errors or common pitfalls. That's where ShellCheck comes in!
ShellCheck is a static analysis tool (a 'linter') for shell scripts. It reads your script and points out:
- Syntax errors.
- Common beginner mistakes.
- Subtle semantic problems.
- Portable issues across different shells.
It gives you helpful suggestions, often with links to more detailed explanations.
ShellCheck in Action: Bad Script
Let's look at a script with a few common issues. These might not cause the script to crash immediately, but they are bad practices or potential bugs.
Imagine you have this script saved as bad_script.sh. To run ShellCheck on it, you'd type: shellcheck bad_script.sh
See if you can spot the issues before running ShellCheck!
#!/bin/bash
# A script with some common issues
MY_NAME=coddykit # Variable assignment needs no space, but quoting is good for values
echo "Hello $MY_NAME!" # Missing quotes around variable expansion
if [ $1 = "admin" ]; then # Missing quotes around $1
echo "Welcome, administrator."
fi
# A simple loop with potential issues
for file in *.txt; do # Unquoted glob could expand to multiple arguments
echo File: $file # Missing quotes around $file
doneFixing ShellCheck Warnings
ShellCheck would provide output like: SC2086: Double quotes missing around "$MY_NAME". It often gives a specific code (like SC2086) that you can look up for more details.
Here's the previous script, fixed according to ShellCheck's recommendations and general best practices:
Notice the use of double quotes "" around variable expansions and command substitutions to prevent word splitting and globbing, which are common sources of bugs.
#!/bin/bash
# A script with issues fixed by ShellCheck
MY_NAME="CoddyKit" # Quote variable assignment values
echo "Hello ${MY_NAME}!" # Always quote variable expansions
if [ "$1" = "admin" ]; then # Quote positional parameters like $1
echo "Welcome, administrator."
fi
# A simple loop with corrected quoting
for file in *.txt; do
echo "File: ${file}" # Quote variable expansions, especially in loops
doneBest Practices Check
Which of the following are considered good practices when writing Bash scripts?
Recap: Professional Scripting
Congratulations! You've learned how to elevate your Bash scripts from functional to professional.
We covered:
- The importance of best practices for readability and maintainability.
- Using comments and naming conventions for clarity.
- Making scripts robust with
set -uandset -o pipefail. - The power of ShellCheck to automatically find issues and improve your code.
By applying these principles, you'll write more reliable, understandable, and collaborative Bash scripts. Keep practicing!
Frequently asked questions
Is the “Scripting Best Practices & Linting” lesson free?
Yes — the full text of “Scripting Best Practices & Linting” is free to read here on the web, and the DevOps Bootcamp 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 DevOps Bootcamp course, upgrade to CoddyKit PRO.
What will I learn in “Scripting Best Practices & Linting”?
Learn about coding conventions, commenting, and using tools like ShellCheck to write clean, readable, and error-free Bash scripts. You practise DevOps Bootcamp 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 DevOps Bootcamp?
No prior experience is required. DevOps Bootcamp 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 “Scripting Best Practices & Linting” 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 DevOps Bootcamp lesson?
Yes. Every DevOps Bootcamp 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
- Debugging Bash Scripts (set -x, trap)
- Error Handling & Exit Status
- Scripting Best Practices & Linting
- Testing Bash Scripts with Bats