Last active 1 month ago

Revision 65d92c8ce74374a2e915919b96628b1c25eaa15b

swapon.sh Raw
1#!/usr/bin/env bash
2set -euo pipefail
3
4SWAPFILE="/swapfile"
5FSTAB="/etc/fstab"
6
7die() {
8 echo "ERROR: $*" >&2
9 exit 1
10}
11
12need_cmd() {
13 command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"
14}
15
16# Must be root
17if [[ "${EUID}" -ne 0 ]]; then
18 die "Run this script as root (e.g. sudo bash script.sh)"
19fi
20
21need_cmd awk
22need_cmd grep
23need_cmd chmod
24need_cmd mkswap
25need_cmd swapon
26need_cmd free
27
28# Refuse if any swap is already active
29if swapon --noheadings --show | grep -q .; then
30 echo "Swap is already active:"
31 swapon --show
32 die "Refusing to continue."
33fi
34
35# Refuse if fstab already has any non-comment swap entry
36if awk '
37 $0 !~ /^[[:space:]]*#/ && NF >= 3 && $3 == "swap" { found=1 }
38 END { exit(found ? 0 : 1) }
39' "$FSTAB"; then
40 echo "Existing swap entry found in $FSTAB:"
41 awk '$0 !~ /^[[:space:]]*#/ && NF >= 3 && $3 == "swap"' "$FSTAB"
42 die "Refusing to continue."
43fi
44
45# Refuse if /swapfile already exists
46if [[ -e "$SWAPFILE" ]]; then
47 die "$SWAPFILE already exists. Refusing to continue."
48fi
49
50# Read RAM from /proc/meminfo (kB)
51mem_kb="$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)"
52[[ -n "$mem_kb" ]] || die "Could not determine system RAM."
53
54mem_mb=$((mem_kb / 1024))
55mem_gb=$(((mem_mb + 1023) / 1024)) # rounded up
56
57# Sizing policy:
58# <=2GB => 2x RAM
59# <=8GB => 1x RAM
60# <=64GB => 0.5x RAM
61# >64GB => 8GB cap
62if (( mem_mb <= 2048 )); then
63 swap_mb=$((mem_mb * 2))
64elif (( mem_mb <= 8192 )); then
65 swap_mb=$mem_mb
66elif (( mem_mb <= 65536 )); then
67 swap_mb=$((mem_mb / 2))
68else
69 swap_mb=8192
70fi
71
72# Minimum 1GB
73if (( swap_mb < 1024 )); then
74 swap_mb=1024
75fi
76
77echo "Detected RAM: ${mem_mb} MB (~${mem_gb} GB)"
78echo "Will create swap: ${swap_mb} MB (~$(((swap_mb + 1023) / 1024)) GB)"
79echo
80
81# Ensure there is enough free disk space on /
82avail_kb="$(df --output=avail / | tail -n1 | tr -d ' ')"
83need_kb=$((swap_mb * 1024))
84if (( avail_kb < need_kb + 262144 )); then
85 die "Not enough free disk space on /. Need about ${swap_mb} MB plus some headroom."
86fi
87
88# Create swapfile
89if command -v fallocate >/dev/null 2>&1; then
90 fallocate -l "${swap_mb}M" "$SWAPFILE" || {
91 echo "fallocate failed, falling back to dd..."
92 dd if=/dev/zero of="$SWAPFILE" bs=1M count="$swap_mb" status=progress
93 }
94else
95 dd if=/dev/zero of="$SWAPFILE" bs=1M count="$swap_mb" status=progress
96fi
97
98chmod 600 "$SWAPFILE"
99mkswap "$SWAPFILE"
100swapon "$SWAPFILE"
101
102# Backup fstab before editing
103cp "$FSTAB" "${FSTAB}.bak.$(date +%Y%m%d%H%M%S)"
104
105echo "$SWAPFILE none swap sw 0 0" >> "$FSTAB"
106
107echo
108echo "Swap successfully created and enabled."
109echo
110echo "Current memory/swap:"
111free -h
112echo
113echo "Active swap:"
114swapon --show
115echo
116echo "fstab entry added:"
117tail -n 5 "$FSTAB"