Complete Guide to Creating Simple Shell Scripts

Learn shell scripting from basics to advanced topics. Master variables, control structures, functions, and best practices for automation.

Complete Guide to Creating Simple Shell Scripts

Table of Contents

1. [Introduction to Shell Scripting](#introduction) 2. [Shell Script Basics](#basics) 3. [Creating Your First Script](#first-script) 4. [Variables and Data Types](#variables) 5. [Input/Output Operations](#input-output) 6. [Control Structures](#control-structures) 7. [Functions](#functions) 8. [File Operations](#file-operations) 9. [Error Handling](#error-handling) 10. [Advanced Topics](#advanced-topics) 11. [Best Practices](#best-practices) 12. [Common Examples](#examples)

Introduction to Shell Scripting {#introduction}

Shell scripting is a powerful way to automate tasks in Unix-like operating systems. A shell script is a text file containing a series of commands that are executed sequentially by the shell interpreter.

What is a Shell Script?

A shell script is essentially a program written for the Unix shell. It allows you to: - Automate repetitive tasks - Combine multiple commands into a single executable file - Create custom utilities and tools - Perform system administration tasks - Process files and data

Types of Shells

| Shell Type | Description | Command | Features | |------------|-------------|---------|----------| | Bash | Bourne Again Shell | /bin/bash | Most common, feature-rich | | Sh | Bourne Shell | /bin/sh | POSIX compliant, basic | | Zsh | Z Shell | /bin/zsh | Advanced features, customizable | | Fish | Friendly Interactive Shell | /bin/fish | User-friendly, syntax highlighting | | Dash | Debian Almquist Shell | /bin/dash | Lightweight, fast |

Shell Script Basics {#basics}

Script Structure

Every shell script follows a basic structure:

`bash #!/bin/bash

This is a comment

Script description and author information

Variable declarations

variable_name="value"

Main script logic

command1 command2 command3

Exit status

exit 0 `

Shebang Line

The shebang (#!) line tells the system which interpreter to use:

| Shebang | Interpreter | Usage | |---------|-------------|-------| | #!/bin/bash | Bash shell | Most common for Linux | | #!/bin/sh | Bourne shell | POSIX compatibility | | #!/usr/bin/env bash | Bash via env | Portable across systems | | #!/bin/zsh | Z shell | Advanced features |

Comments

Comments are essential for documentation:

`bash

Single line comment

echo "Hello World" # Inline comment

Multi-line comment block

: ' This is a multi-line comment Everything between the quotes is ignored Useful for documentation blocks ' `

Creating Your First Script {#first-script}

Step-by-Step Process

1. Create the script file: `bash touch myscript.sh `

2. Edit the script: `bash nano myscript.sh

or

vim myscript.sh `

3. Add content: `bash #!/bin/bash echo "Hello, World!" echo "This is my first shell script" `

4. Make it executable: `bash chmod +x myscript.sh `

5. Run the script: `bash ./myscript.sh

or

bash myscript.sh `

File Permissions

Understanding file permissions is crucial:

| Permission | Numeric | Symbolic | Description | |------------|---------|----------|-------------| | Read | 4 | r | Can read file content | | Write | 2 | w | Can modify file | | Execute | 1 | x | Can run as program |

Common permission combinations: - 755 (rwxr-xr-x): Owner can read/write/execute, others can read/execute - 644 (rw-r--r--): Owner can read/write, others can read only - 700 (rwx------): Only owner has full access

Variables and Data Types {#variables}

Variable Declaration and Usage

`bash #!/bin/bash

Variable assignment (no spaces around =)

name="John Doe" age=25 pi=3.14159

Using variables

echo "Name: $name" echo "Age: ${age}" echo "Pi value: $pi"

Read-only variables

readonly PI=3.14159 declare -r CONSTANT="Cannot change"

Environment variables

export MY_VAR="Available to child processes" `

Variable Types

| Type | Declaration | Example | Description | |------|-------------|---------|-------------| | String | var="text" | name="Alice" | Text data | | Integer | var=123 | count=10 | Numeric data | | Array | var=(a b c) | fruits=(apple banana) | Multiple values | | Readonly | readonly var=value | readonly PI=3.14 | Immutable | | Environment | export var=value | export PATH=/usr/bin | Global scope |

Special Variables

`bash #!/bin/bash

echo "Script name: $0" echo "First argument: $1" echo "Second argument: $2" echo "All arguments: $@" echo "Number of arguments: $#" echo "Process ID: $" echo "Exit status of last command: $?" `

| Variable | Description | Example | |----------|-------------|---------| | $0 | Script name | ./script.sh | | $1, $2, ... | Positional parameters | First, second argument | | $@ | All arguments as separate words | "arg1" "arg2" "arg3" | | $* | All arguments as single word | "arg1 arg2 arg3" | | $# | Number of arguments | 3 | | $ | Current process ID | 1234 | | $? | Exit status of last command | 0 for success | | $! | Process ID of last background job | 5678 |

Input/Output Operations {#input-output}

Reading User Input

`bash #!/bin/bash

Simple input

echo "Enter your name:" read name echo "Hello, $name!"

Input with prompt

read -p "Enter your age: " age echo "You are $age years old"

Silent input (for passwords)

read -s -p "Enter password: " password echo echo "Password entered"

Reading multiple values

echo "Enter first and last name:" read first last echo "First: $first, Last: $last"

Reading with timeout

if read -t 10 -p "Enter something (10 seconds): " input; then echo "You entered: $input" else echo "Timeout occurred" fi `

Output Commands

| Command | Purpose | Example | Notes | |---------|---------|---------|-------| | echo | Display text | echo "Hello" | Adds newline by default | | printf | Formatted output | printf "%s\n" "Hello" | More control over formatting | | cat | Display file content | cat file.txt | Concatenate and display | | tee | Write to file and stdout | echo "text" \| tee file.txt | Useful for logging |

Printf Formatting

`bash #!/bin/bash

name="Alice" age=25 height=5.8

String formatting

printf "Name: %s\n" "$name"

Integer formatting

printf "Age: %d years\n" "$age"

Float formatting

printf "Height: %.1f feet\n" "$height"

Padding and alignment

printf "%-10s %5d\n" "$name" "$age"

Multiple values

printf "%s is %d years old and %.1f feet tall\n" "$name" "$age" "$height" `

Control Structures {#control-structures}

Conditional Statements

#### If-Then-Else

`bash #!/bin/bash

age=18

if [ $age -ge 18 ]; then echo "You are an adult" elif [ $age -ge 13 ]; then echo "You are a teenager" else echo "You are a child" fi

File testing

file="test.txt" if [ -f "$file" ]; then echo "File exists" else echo "File does not exist" fi

String comparison

name="Alice" if [ "$name" = "Alice" ]; then echo "Hello Alice!" fi `

#### Test Conditions

| Test | Description | Example | |------|-------------|---------| | -eq | Equal (numeric) | [ $a -eq $b ] | | -ne | Not equal (numeric) | [ $a -ne $b ] | | -lt | Less than | [ $a -lt $b ] | | -le | Less than or equal | [ $a -le $b ] | | -gt | Greater than | [ $a -gt $b ] | | -ge | Greater than or equal | [ $a -ge $b ] | | = | String equal | [ "$a" = "$b" ] | | != | String not equal | [ "$a" != "$b" ] | | -z | String is empty | [ -z "$string" ] | | -n | String is not empty | [ -n "$string" ] |

#### File Test Operators

| Test | Description | Example | |------|-------------|---------| | -f | Regular file | [ -f "file.txt" ] | | -d | Directory | [ -d "mydir" ] | | -e | File exists | [ -e "path" ] | | -r | Readable | [ -r "file.txt" ] | | -w | Writable | [ -w "file.txt" ] | | -x | Executable | [ -x "script.sh" ] | | -s | File not empty | [ -s "file.txt" ] |

Case Statements

`bash #!/bin/bash

read -p "Enter a grade (A-F): " grade

case $grade in A|a) echo "Excellent!" ;; B|b) echo "Good job!" ;; C|c) echo "Average" ;; D|d) echo "Below average" ;; F|f) echo "Failed" ;; *) echo "Invalid grade" ;; esac `

Loops

#### For Loops

`bash #!/bin/bash

Simple for loop

for i in 1 2 3 4 5; do echo "Number: $i" done

Range-based for loop

for i in {1..10}; do echo "Count: $i" done

Step increment

for i in {0..20..2}; do echo "Even number: $i" done

C-style for loop

for ((i=1; i<=5; i++)); do echo "Iteration: $i" done

Iterating over files

for file in *.txt; do echo "Processing: $file" done

Iterating over arrays

fruits=("apple" "banana" "orange") for fruit in "${fruits[@]}"; do echo "Fruit: $fruit" done `

#### While Loops

`bash #!/bin/bash

Simple while loop

counter=1 while [ $counter -le 5 ]; do echo "Counter: $counter" ((counter++)) done

Reading file line by line

while IFS= read -r line; do echo "Line: $line" done < "input.txt"

Infinite loop with break

while true; do read -p "Enter 'quit' to exit: " input if [ "$input" = "quit" ]; then break fi echo "You entered: $input" done `

#### Until Loops

`bash #!/bin/bash

counter=1 until [ $counter -gt 5 ]; do echo "Counter: $counter" ((counter++)) done `

Functions {#functions}

Function Declaration and Usage

`bash #!/bin/bash

Function definition

greet() { echo "Hello, $1!" }

Function with multiple parameters

calculate_area() { local length=$1 local width=$2 local area=$((length * width)) echo $area }

Function with return value

is_even() { local number=$1 if [ $((number % 2)) -eq 0 ]; then return 0 # true else return 1 # false fi }

Using functions

greet "Alice" area=$(calculate_area 5 3) echo "Area: $area"

if is_even 4; then echo "4 is even" fi `

Function Features

| Feature | Syntax | Example | Description | |---------|--------|---------|-------------| | Local variables | local var=value | local name="John" | Variable scope within function | | Parameters | $1, $2, ... | function_name param1 param2 | Access function arguments | | Return value | return n | return 0 | Exit status (0-255) | | Function call | function_name args | greet "Alice" | Execute function |

Advanced Function Example

`bash #!/bin/bash

Function with error handling and validation

backup_file() { local source_file=$1 local backup_dir=${2:-"./backup"} # Validate input if [ $# -lt 1 ]; then echo "Usage: backup_file [backup_directory]" >&2 return 1 fi # Check if source file exists if [ ! -f "$source_file" ]; then echo "Error: Source file '$source_file' does not exist" >&2 return 1 fi # Create backup directory if it doesn't exist if [ ! -d "$backup_dir" ]; then mkdir -p "$backup_dir" fi # Create backup with timestamp local timestamp=$(date +"%Y%m%d_%H%M%S") local backup_name="$(basename "$source_file")_$timestamp" if cp "$source_file" "$backup_dir/$backup_name"; then echo "Backup created: $backup_dir/$backup_name" return 0 else echo "Error: Failed to create backup" >&2 return 1 fi }

Usage

backup_file "important.txt" "/home/user/backups" `

File Operations {#file-operations}

Basic File Operations

`bash #!/bin/bash

File creation and manipulation

touch "newfile.txt" echo "Hello World" > "newfile.txt" echo "Second line" >> "newfile.txt"

File information

if [ -f "newfile.txt" ]; then echo "File size: $(stat -f%z "newfile.txt" 2>/dev/null || stat -c%s "newfile.txt")" echo "Last modified: $(stat -f%Sm "newfile.txt" 2>/dev/null || stat -c%y "newfile.txt")" fi

Directory operations

mkdir -p "test/subdirectory" cd "test" pwd ls -la cd ..

File copying and moving

cp "newfile.txt" "backup.txt" mv "backup.txt" "test/"

File deletion

rm "newfile.txt" rmdir "test/subdirectory" rm -rf "test" `

File Processing Examples

`bash #!/bin/bash

Count lines in a file

count_lines() { local file=$1 if [ -f "$file" ]; then wc -l < "$file" else echo "File not found: $file" >&2 return 1 fi }

Search and replace in file

search_replace() { local file=$1 local search=$2 local replace=$3 if [ -f "$file" ]; then sed -i.bak "s/$search/$replace/g" "$file" echo "Replaced '$search' with '$replace' in $file" else echo "File not found: $file" >&2 return 1 fi }

Extract file extension

get_extension() { local filename=$1 echo "${filename##*.}" }

Usage examples

echo "Lines in file: $(count_lines "data.txt")" search_replace "config.txt" "old_value" "new_value" echo "Extension: $(get_extension "document.pdf")" `

File Processing Commands

| Command | Purpose | Example | Description | |---------|---------|---------|-------------| | cat | Display file | cat file.txt | Show entire file | | head | Show first lines | head -n 10 file.txt | Display first 10 lines | | tail | Show last lines | tail -n 5 file.txt | Display last 5 lines | | grep | Search text | grep "pattern" file.txt | Find matching lines | | sed | Stream editor | sed 's/old/new/g' file.txt | Replace text | | awk | Text processing | awk '{print $1}' file.txt | Extract columns | | sort | Sort lines | sort file.txt | Alphabetical sorting | | uniq | Remove duplicates | uniq file.txt | Unique lines only | | wc | Word count | wc -l file.txt | Count lines/words | | find | Find files | find . -name "*.txt" | Locate files |

Error Handling {#error-handling}

Exit Status and Error Checking

`bash #!/bin/bash

Function to check command success

check_command() { if [ $? -eq 0 ]; then echo "Command succeeded" else echo "Command failed with exit code $?" exit 1 fi }

Error handling with conditional execution

mkdir test_directory && echo "Directory created successfully" || echo "Failed to create directory"

Comprehensive error handling

safe_copy() { local source=$1 local destination=$2 # Check if source exists if [ ! -f "$source" ]; then echo "Error: Source file '$source' does not exist" >&2 return 1 fi # Check if destination directory exists local dest_dir=$(dirname "$destination") if [ ! -d "$dest_dir" ]; then echo "Error: Destination directory '$dest_dir' does not exist" >&2 return 1 fi # Perform copy with error checking if cp "$source" "$destination"; then echo "Successfully copied '$source' to '$destination'" return 0 else echo "Error: Failed to copy '$source' to '$destination'" >&2 return 1 fi } `

Trap and Signal Handling

`bash #!/bin/bash

Cleanup function

cleanup() { echo "Cleaning up temporary files..." rm -f /tmp/script_temp_* echo "Cleanup completed" exit 0 }

Set trap for various signals

trap cleanup EXIT INT TERM

Create temporary file

temp_file="/tmp/script_temp_$" touch "$temp_file"

echo "Script running... Press Ctrl+C to test cleanup" echo "Temporary file created: $temp_file"

Simulate some work

for i in {1..10}; do echo "Working... $i" sleep 1 done

echo "Script completed normally" `

Error Logging

`bash #!/bin/bash

Logging configuration

LOG_FILE="/var/log/myscript.log" ERROR_LOG="/var/log/myscript_error.log"

Logging functions

log_info() { echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: $1" | tee -a "$LOG_FILE" }

log_error() { echo "$(date '+%Y-%m-%d %H:%M:%S') ERROR: $1" | tee -a "$ERROR_LOG" >&2 }

log_warning() { echo "$(date '+%Y-%m-%d %H:%M:%S') WARNING: $1" | tee -a "$LOG_FILE" }

Usage example

process_file() { local file=$1 log_info "Starting to process file: $file" if [ ! -f "$file" ]; then log_error "File not found: $file" return 1 fi if [ ! -r "$file" ]; then log_warning "File is not readable: $file" return 1 fi # Process file local line_count=$(wc -l < "$file") log_info "File processed successfully. Lines: $line_count" return 0 } `

Advanced Topics {#advanced-topics}

Arrays

`bash #!/bin/bash

Indexed arrays

fruits=("apple" "banana" "orange" "grape")

Accessing array elements

echo "First fruit: ${fruits[0]}" echo "All fruits: ${fruits[@]}" echo "Number of fruits: ${#fruits[@]}"

Adding elements

fruits+=("mango") fruits[5]="pineapple"

Iterating over array

for i in "${!fruits[@]}"; do echo "Index $i: ${fruits[i]}" done

Associative arrays (Bash 4+)

declare -A person person["name"]="John Doe" person["age"]="30" person["city"]="New York"

Accessing associative array

echo "Name: ${person["name"]}" echo "Age: ${person["age"]}"

Iterating over associative array

for key in "${!person[@]}"; do echo "$key: ${person[$key]}" done `

String Manipulation

`bash #!/bin/bash

text="Hello World Programming"

String length

echo "Length: ${#text}"

Substring extraction

echo "Substring: ${text:0:5}" # Hello echo "Substring: ${text:6:5}" # World

Pattern matching and replacement

echo "Replace first: ${text/o/0}" # Hell0 World Programming echo "Replace all: ${text//o/0}" # Hell0 W0rld Pr0gramming echo "Remove from beginning: ${text#Hello }" # World Programming echo "Remove from end: ${text% Programming}" # Hello World

Case conversion (Bash 4+)

echo "Uppercase: ${text^^}" echo "Lowercase: ${text,,}" echo "Title case: ${text^}" `

Command Line Arguments Processing

`bash #!/bin/bash

Advanced argument processing

usage() { echo "Usage: $0 [-h] [-v] [-f file] [-o output] [input_files...]" echo " -h Show this help message" echo " -v Verbose mode" echo " -f file Input file" echo " -o output Output file" exit 1 }

Default values

VERBOSE=false INPUT_FILE="" OUTPUT_FILE=""

Process command line options

while getopts "hvf:o:" opt; do case $opt in h) usage ;; v) VERBOSE=true ;; f) INPUT_FILE="$OPTARG" ;; o) OUTPUT_FILE="$OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2 usage ;; :) echo "Option -$OPTARG requires an argument" >&2 usage ;; esac done

Shift processed options

shift $((OPTIND-1))

Remaining arguments

REMAINING_ARGS=("$@")

Display configuration

if [ "$VERBOSE" = true ]; then echo "Verbose mode enabled" echo "Input file: ${INPUT_FILE:-"None"}" echo "Output file: ${OUTPUT_FILE:-"None"}" echo "Remaining arguments: ${REMAINING_ARGS[*]}" fi `

Best Practices {#best-practices}

Script Template

`bash #!/bin/bash

#===============================================================================

Script Name: script_template.sh

Description: Template for shell scripts with best practices

Author: Your Name

Version: 1.0

Date: $(date +%Y-%m-%d)

#===============================================================================

Exit on any error

set -e

Exit on undefined variable

set -u

Exit on pipe failure

set -o pipefail

Global variables

readonly SCRIPT_NAME=$(basename "$0") readonly SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) readonly LOG_FILE="/tmp/${SCRIPT_NAME%.sh}.log"

Color codes for output

readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly NC='\033[0m' # No Color

Logging functions

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE" }

error() { echo -e "${RED}ERROR: $*${NC}" >&2 log "ERROR: $*" }

warning() { echo -e "${YELLOW}WARNING: $*${NC}" >&2 log "WARNING: $*" }

info() { echo -e "${GREEN}INFO: $*${NC}" log "INFO: $*" }

Cleanup function

cleanup() { log "Script execution completed" # Add cleanup tasks here }

Set trap for cleanup

trap cleanup EXIT

Main function

main() { info "Starting script execution" # Script logic here info "Script completed successfully" }

Run main function with all arguments

main "$@" `

Code Style Guidelines

| Practice | Good Example | Bad Example | Reason | |----------|--------------|-------------|---------| | Variable naming | user_name="john" | un="john" | Descriptive names | | Quoting variables | echo "$variable" | echo $variable | Prevents word splitting | | Function naming | calculate_total() | calc() | Clear purpose | | Error checking | if command; then... | command | Handle failures | | Constants | readonly PI=3.14 | PI=3.14 | Prevent modification |

Security Considerations

`bash #!/bin/bash

Secure script practices

1. Validate input

validate_input() { local input=$1 local pattern='^[a-zA-Z0-9_-]+

Complete Guide to Creating Simple Shell Scripts

if [[ ! $input =~ $pattern ]]; then error "Invalid input: $input" return 1 fi }

2. Use full paths for commands

readonly RM="/bin/rm" readonly MKDIR="/bin/mkdir" readonly CHMOD="/bin/chmod"

3. Set secure permissions

umask 077

4. Avoid eval and shell injection

Bad: eval "command $user_input"

Good: Validate input first

5. Use temporary files securely

temp_file=$(mktemp) || { error "Cannot create temporary file" exit 1 }

6. Check file permissions before processing

check_file_security() { local file=$1 if [ -w "$file" ] && [ "$(stat -c %a "$file")" != "600" ]; then warning "File $file has insecure permissions" return 1 fi } `

Common Examples {#examples}

System Information Script

`bash #!/bin/bash

System information gathering script

print_header() { echo "==================================" echo "$1" echo "==================================" }

System information

print_header "SYSTEM INFORMATION" echo "Hostname: $(hostname)" echo "Operating System: $(uname -s)" echo "Kernel Version: $(uname -r)" echo "Architecture: $(uname -m)" echo "Uptime: $(uptime -p 2>/dev/null || uptime)"

CPU information

print_header "CPU INFORMATION" if command -v lscpu >/dev/null 2>&1; then lscpu | grep -E "Model name|CPU\(s\)|Architecture" else grep -E "processor|model name" /proc/cpuinfo | head -2 fi

Memory information

print_header "MEMORY INFORMATION" if command -v free >/dev/null 2>&1; then free -h else echo "Memory information not available" fi

Disk usage

print_header "DISK USAGE" df -h | head -1 df -h | grep -vE "^tmpfs|^udev|^/dev/loop"

Network interfaces

print_header "NETWORK INTERFACES" if command -v ip >/dev/null 2>&1; then ip addr show | grep -E "^[0-9]+:" | cut -d: -f2 | tr -d ' ' else ifconfig | grep -E "^[a-z]" | cut -d: -f1 fi `

File Backup Script

`bash #!/bin/bash

Automated backup script

Configuration

SOURCE_DIR="/home/user/documents" BACKUP_BASE="/backup" RETENTION_DAYS=30 DATE=$(date +%Y%m%d_%H%M%S) BACKUP_NAME="backup_$DATE" LOG_FILE="/var/log/backup.log"

Logging function

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE" }

Create backup

create_backup() { local source=$1 local destination=$2 log "Starting backup from $source to $destination" if [ ! -d "$source" ]; then log "ERROR: Source directory does not exist: $source" return 1 fi # Create backup directory mkdir -p "$destination" # Perform backup with tar if tar -czf "$destination/$BACKUP_NAME.tar.gz" -C "$(dirname "$source")" "$(basename "$source")"; then log "Backup completed successfully: $destination/$BACKUP_NAME.tar.gz" return 0 else log "ERROR: Backup failed" return 1 fi }

Clean old backups

cleanup_old_backups() { local backup_dir=$1 local days=$2 log "Cleaning up backups older than $days days" find "$backup_dir" -name "backup_*.tar.gz" -type f -mtime +$days -delete log "Cleanup completed" }

Calculate backup size

calculate_size() { local file=$1 if [ -f "$file" ]; then local size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file") local human_size=$(numfmt --to=iec-i --suffix=B "$size" 2>/dev/null || echo "$size bytes") echo "$human_size" fi }

Main execution

main() { log "Backup script started" if create_backup "$SOURCE_DIR" "$BACKUP_BASE"; then local backup_file="$BACKUP_BASE/$BACKUP_NAME.tar.gz" local backup_size=$(calculate_size "$backup_file") log "Backup size: $backup_size" cleanup_old_backups "$BACKUP_BASE" "$RETENTION_DAYS" log "Backup process completed successfully" else log "Backup process failed" exit 1 fi }

Run main function

main `

Log Analysis Script

`bash #!/bin/bash

Log analysis script

LOG_FILE="/var/log/access.log" REPORT_FILE="/tmp/log_report_$(date +%Y%m%d).txt"

Function to analyze log file

analyze_logs() { local logfile=$1 local report=$2 echo "Log Analysis Report - $(date)" > "$report" echo "======================================" >> "$report" echo >> "$report" # Total number of requests echo "Total Requests: $(wc -l < "$logfile")" >> "$report" echo >> "$report" # Top 10 IP addresses echo "Top 10 IP Addresses:" >> "$report" awk '{print $1}' "$logfile" | sort | uniq -c | sort -rn | head -10 >> "$report" echo >> "$report" # Top 10 requested pages echo "Top 10 Requested Pages:" >> "$report" awk '{print $7}' "$logfile" | sort | uniq -c | sort -rn | head -10 >> "$report" echo >> "$report" # HTTP status codes echo "HTTP Status Codes:" >> "$report" awk '{print $9}' "$logfile" | sort | uniq -c | sort -rn >> "$report" echo >> "$report" # Hourly request distribution echo "Hourly Request Distribution:" >> "$report" awk '{print substr($4, 14, 2)}' "$logfile" | sort | uniq -c | sort -n >> "$report" echo "Report generated: $report" }

Check if log file exists

if [ -f "$LOG_FILE" ]; then analyze_logs "$LOG_FILE" "$REPORT_FILE" else echo "Error: Log file not found: $LOG_FILE" exit 1 fi `

Process Monitor Script

`bash #!/bin/bash

Process monitoring script

PROCESS_NAME="$1" CHECK_INTERVAL=60 LOG_FILE="/var/log/process_monitor.log" PID_FILE="/tmp/process_monitor.pid"

usage() { echo "Usage: $0 " echo "Example: $0 nginx" exit 1 }

log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE" }

check_process() { local process=$1 if pgrep "$process" > /dev/null; then return 0 # Process is running else return 1 # Process is not running fi }

restart_process() { local process=$1 log "Attempting to restart $process" # Attempt to start the process (customize as needed) if systemctl start "$process" 2>/dev/null; then log "Successfully restarted $process using systemctl" elif service "$process" start 2>/dev/null; then log "Successfully restarted $process using service" else log "Failed to restart $process automatically" # Send alert (email, notification, etc.) send_alert "$process" fi }

send_alert() { local process=$1 local message="ALERT: Process $process is down and could not be restarted automatically" # Log the alert log "$message" # Send email if mail command is available if command -v mail >/dev/null 2>&1; then echo "$message" | mail -s "Process Alert: $process" admin@example.com fi }

monitor_loop() { local process=$1 log "Starting process monitor for: $process" while true; do if check_process "$process"; then log "$process is running normally" else log "WARNING: $process is not running" restart_process "$process" fi sleep "$CHECK_INTERVAL" done }

Main execution

if [ $# -ne 1 ]; then usage fi

Check if already running

if [ -f "$PID_FILE" ]; then if kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then echo "Process monitor is already running" exit 1 fi fi

Save PID

echo $ > "$PID_FILE"

Cleanup on exit

trap 'rm -f "$PID_FILE"; exit 0' EXIT INT TERM

Start monitoring

monitor_loop "$PROCESS_NAME" `

This comprehensive guide covers the essential aspects of creating shell scripts, from basic concepts to advanced techniques. The examples provided demonstrate real-world applications and best practices for writing maintainable, secure, and efficient shell scripts.

Tags

  • Automation
  • Linux
  • Unix
  • bash
  • shell-scripting

Related Articles

Popular Technical Articles & Tutorials

Explore our comprehensive collection of technical articles, programming tutorials, and IT guides written by industry experts:

Browse all 8+ technical articles | Read our IT blog

Complete Guide to Creating Simple Shell Scripts