#!/usr/bin/env bash set -euo pipefail SWAPFILE="/swapfile" FSTAB="/etc/fstab" die() { echo "ERROR: $*" >&2 exit 1 } need_cmd() { command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1" } # Must be root if [[ "${EUID}" -ne 0 ]]; then die "Run this script as root (e.g. sudo bash script.sh)" fi need_cmd awk need_cmd grep need_cmd chmod need_cmd mkswap need_cmd swapon need_cmd free # Refuse if any swap is already active if swapon --noheadings --show | grep -q .; then echo "Swap is already active:" swapon --show die "Refusing to continue." fi # Refuse if fstab already has any non-comment swap entry if awk ' $0 !~ /^[[:space:]]*#/ && NF >= 3 && $3 == "swap" { found=1 } END { exit(found ? 0 : 1) } ' "$FSTAB"; then echo "Existing swap entry found in $FSTAB:" awk '$0 !~ /^[[:space:]]*#/ && NF >= 3 && $3 == "swap"' "$FSTAB" die "Refusing to continue." fi # Refuse if /swapfile already exists if [[ -e "$SWAPFILE" ]]; then die "$SWAPFILE already exists. Refusing to continue." fi # Read RAM from /proc/meminfo (kB) mem_kb="$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)" [[ -n "$mem_kb" ]] || die "Could not determine system RAM." mem_mb=$((mem_kb / 1024)) mem_gb=$(((mem_mb + 1023) / 1024)) # rounded up # Sizing policy: # <=2GB => 2x RAM # <=8GB => 1x RAM # <=64GB => 0.5x RAM # >64GB => 8GB cap if (( mem_mb <= 2048 )); then swap_mb=$((mem_mb * 2)) elif (( mem_mb <= 8192 )); then swap_mb=$mem_mb elif (( mem_mb <= 65536 )); then swap_mb=$((mem_mb / 2)) else swap_mb=8192 fi # Minimum 1GB if (( swap_mb < 1024 )); then swap_mb=1024 fi echo "Detected RAM: ${mem_mb} MB (~${mem_gb} GB)" echo "Will create swap: ${swap_mb} MB (~$(((swap_mb + 1023) / 1024)) GB)" echo # Ensure there is enough free disk space on / avail_kb="$(df --output=avail / | tail -n1 | tr -d ' ')" need_kb=$((swap_mb * 1024)) if (( avail_kb < need_kb + 262144 )); then die "Not enough free disk space on /. Need about ${swap_mb} MB plus some headroom." fi # Create swapfile if command -v fallocate >/dev/null 2>&1; then fallocate -l "${swap_mb}M" "$SWAPFILE" || { echo "fallocate failed, falling back to dd..." dd if=/dev/zero of="$SWAPFILE" bs=1M count="$swap_mb" status=progress } else dd if=/dev/zero of="$SWAPFILE" bs=1M count="$swap_mb" status=progress fi chmod 600 "$SWAPFILE" mkswap "$SWAPFILE" swapon "$SWAPFILE" # Backup fstab before editing cp "$FSTAB" "${FSTAB}.bak.$(date +%Y%m%d%H%M%S)" echo "$SWAPFILE none swap sw 0 0" >> "$FSTAB" echo echo "Swap successfully created and enabled." echo echo "Current memory/swap:" free -h echo echo "Active swap:" swapon --show echo echo "fstab entry added:" tail -n 5 "$FSTAB"