Skip to content

Bash Scripting

Bash is the glue of Linux security work
It orchestrates commands , processes pipelines , and automates system tasks without needing compilation or dependencies

Script Structure

#!/bin/bash
# Script header with metadata
set -euo pipefail
# Best practice header
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

# -e: Exit on error
# -u: Treat unset variables as errors
# -o pipefail: Catch errors in piped commands
# IFS: Safe field separator

Variables

# Variable assignment
target="192.168.1.1"
port=80

# Variable usage
echo "Scanning $target:$port"
ping -c 4 "$target"

# Command substitution
results=$(nmap -sT "$target")
date=$(date '+%Y-%m-%d')

# Default values
output=${1:-"default.txt"}

Functions

# Define function
log_message() {
    local message="$1"
    local logfile="${2:-script.log}"
    echo "[$(date '+%H:%M:%S')] $message" >> "$logfile"
}

# Call function
log_message "Starting scan of $target"

Conditionals

# File checks
if [ -f "$file" ]; then
    echo "File exists"
fi

if [ -d "$dir" ]; then
    echo "Directory exists"
fi

# String comparison
if [ "$var" = "value" ]; then
    echo "Match"
fi

# Numerical comparison
if [ "$count" -gt 10 ]; then
    echo "Count exceeds 10"
fi

Loops

# For loop over list
for ip in 192.168.1.{1..254}; do
    ping -c 1 -W 1 "$ip" &>/dev/null && echo "$ip is up"
done

# While loop (read file line)
while read -r line; do
    echo "Processing: $line"
done < targets.txt

# For loop with command output
for user in $(cat /etc/passwd | cut -d: -f1); do
    echo "User: $user"
done

Arrays

# Array declaration
hosts=("web" "db" "mail")

# Array access
echo "${hosts[0]}"              # First element
echo "${hosts[@]}"              # All elements
echo "${#hosts[@]}"            # Array length

# Loop through array
for host in "${hosts[@]}"; do
    echo "Deploying to $host"
done

Practical Security Scripts

#!/bin/bash
# Port scanner using bash built-ins
set -euo pipefail

target="${1:-192.168.1.1}"
ports=(${2:-22 80 443 3306 8080})

echo "Scanning $target..."
for port in "${ports[@]}"; do
    (echo >/dev/tcp/$target/$port) 2>/dev/null \
        && echo "Port $port: OPEN" \
        || echo "Port $port: closed"
done