9.3 KiB
Sure, here's a comprehensive shell (Bash) scripting standards document, aligned with the principles and structure we established for the HTML standards.
Shell (Bash) Scripting Standards Documentation
Introduction
This document outlines our conventions and best practices for writing Shell (Bash) scripts. Adhering to these standards ensures our scripts are consistent, readable, maintainable, and robust. By following these guidelines, we'll foster easier collaboration, reduce debugging time, and improve script reliability.
Script Structure and Headers
Consistent script structure and informative headers are crucial for immediate understanding and maintainability.
- Shebang Line: Always start with the shebang line specifying the interpreter.
- Description: Ensures the script runs with Bash, regardless of the user's default shell.
- Usage:
#!/bin/bash
- Script Header Comments: Include a standardized block at the top of each script.
- Description: Provides essential metadata for quick reference.
- Usage:
#!/bin/bash # Script Name: myscript.sh # Description: This script automates the backup of project files. # Author: Your Name <your.email@example.com> # Date: 2025-06-30 # Version: 1.0.0 # Usage: ./myscript.sh [--options] <arguments> # Dependencies: rsync, tar # License: MIT (or your chosen license)
- Error Handling (Immediate Exit):
- Description: Always include
set -eandset -u.set -e: Exit immediately if a command exits with a non-zero status. This prevents scripts from continuing in an error state.set -u: Treat unset variables as an error and exit immediately. This helps catch typos and uninitialized variables.set -o pipefail: (Optional but recommended) Causes a pipeline to return the exit status of the last command in the pipe that exited with a non-zero status, rather than just the last command.
- Usage:
#!/bin/bash set -euo pipefail # All three combined
- Description: Always include
Naming Conventions
Consistent naming makes variables, functions, and files easy to identify and understand.
1. Variables
- Lowercase with Underscores (snake_case):
- Description: For general script variables.
- Usage:
file_name,user_input,temp_directory
- Uppercase with Underscores (SCREAMING_SNAKE_CASE):
- Description: For constants (values that should not change) and environment variables.
- Usage:
MAX_RETRIES=5,LOG_FILE="/var/log/app.log",PATH
- Positional Parameters:
- Description: Refer to script arguments using
$1,$2, etc., and use$@for all arguments. - Usage:
echo "First arg: $1",for arg in "$@"; do ... done
- Description: Refer to script arguments using
2. Functions
- Lowercase with Underscores (snake_case):
- Description: For function names. Verb-noun structure is often helpful.
- Usage:
display_help,process_file,cleanup_temp_files
3. Files
- Lowercase with Hyphens (kebab-case):
- Description: For script filenames. Avoid spaces.
- Usage:
backup-database.sh,deploy-app.sh,monitor-logs.sh
Formatting and Readability
Clean formatting significantly improves readability and navigability.
1. Indentation
- Spaces over Tabs:
- Description: Use 4 spaces for indentation. Configure your editor to convert tabs to spaces.
- Consistent Indentation:
- Description: Indent blocks of code within
if,for,while,function, etc. consistently.
- Description: Indent blocks of code within
2. Spacing
- Operators and Assignments:
- Description: Use spaces around operators (
=,==,!=,<,>) and assignments. - Usage:
variable = "value",if [[ $a -eq $b ]],count=$((count + 1))
- Description: Use spaces around operators (
- Function Calls:
- Description: No space between function name and parentheses.
- Usage:
my_function arg1 arg2(notmy_function(arg1, arg2))
- Command Separators:
- Description: Use semicolons
;only for multiple commands on one line, or for simpleifstatements. Prefer new lines. - Usage:
command1; command2(less common),if [ "$1" == "--help" ]; then display_help; exit 0; fi
- Description: Use semicolons
3. Comments
- Descriptive Comments:
- Description: Use
#for single-line comments. Add comments to explain why a piece of code exists, not just what it does. Complex logic or non-obvious steps should be commented. - Usage:
# Validate that the log file exists before proceeding. if [[ ! -f "$LOG_FILE" ]]; then echo "Error: Log file not found at $LOG_FILE" >&2 exit 1 fi
- Description: Use
- Block Comments:
- Description: For larger explanations or section headers.
- Usage:
############################################# # Function: cleanup_old_backups # Description: Deletes backups older than N days. #############################################
Best Practices and Principles
These principles guide our overall approach to writing effective and maintainable Bash scripts.
1. Modularity and Functions
- Description: Break down complex scripts into smaller, focused functions. Each function should perform a single, well-defined task.
- Benefit: Improves readability, reusability, and makes debugging easier.
- Usage:
function validate_input() { if [[ -z "$1" ]]; then echo "Error: Argument is missing." >&2 exit 1 fi } validate_input "$@"
2. Argument Parsing
- Description: For scripts that accept options or arguments, use
getoptsfor simple options or manual parsing for more complex scenarios. Avoid simple positional checks for multiple options. - Benefit: Provides a user-friendly interface and robust argument handling.
- Usage (
getoptsexample):while getopts "hv:d:" opt; do case $opt in h) display_help; exit 0 ;; v) VERBOSE=true ;; d) DEST_DIR="$OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;; esac done shift $((OPTIND - 1)) # Shift positional parameters
3. Error Handling and Logging
- Description: Beyond
set -eandset -u, implement explicit error checks for critical commands. Redirect error messages tostderr(>&2) and informative messages tostdout. Consider logging to a file for long-running scripts. - Benefit: Makes scripts more robust and easier to diagnose issues.
- Usage:
# Command that might fail cp source_file.txt dest_dir/ || { echo "Error: Failed to copy file." >&2; exit 1; } log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" } log_message "Script started."
4. Quoting Variables
- Description: Always quote variables when they contain spaces or special characters to prevent word splitting and globbing. This is one of the most common Bash pitfalls.
- Benefit: Prevents unexpected behavior and ensures commands receive arguments as intended.
- Usage:
# BAD: May cause issues if file has spaces # rm $FILE_PATH # GOOD: Safely handles spaces rm "$FILE_PATH" # For arrays for item in "${my_array[@]}"; do echo "$item" done
5. Using [[ ... ]] over [ ... ] (where appropriate)
- Description: Prefer the
[[ ... ]](Bash's extended test command) for conditional expressions over the older[ ... ](POSIXtestcommand). - Benefit:
[[ ... ]]offers more features (like regex matching==~, logical operators&&,||), is less prone to word splitting issues, and provides better readability. - Usage:
if [[ "$variable" == "expected value" ]]; then ... fi if [[ "$string" =~ ^[0-9]+$ ]]; then echo "Is a number"; fi if [[ -f "$file" && -r "$file" ]]; then ... fi
6. Avoid ls Parsing
- Description: Do not parse the output of
ls(e.g., usinggreporawkonlsoutput) for processing filenames.lsoutput is for human readability, not programmatic use, and can be ambiguous with special characters. - Benefit: Prevents subtle bugs when dealing with filenames containing spaces, newlines, or other special characters.
- Instead: Use globbing or
find -print0 | xargs -0for safe file processing. - Usage:
# BAD: Don't do this! # for file in $(ls *.txt); do ... fi # GOOD: Use globbing for file in *.txt; do echo "Processing '$file'" done # GOOD: For complex find operations find . -name "*.log" -print0 | while IFS= read -r -d $'\0' file; do echo "Found log: $file" done
Conclusion
By diligently applying these Bash scripting standards, we ensure our scripts are not only functional but also highly readable, maintainable, and robust. This commitment to quality coding practices promotes a more efficient development workflow and strengthens the reliability of our automated tasks.