#!/bin/bash # # swapon — create, enable and persist an 8GB swap file. # # Runs on each managed server (Alpine/OpenRC). Deploy with ./update_sbin, then: # # rex doas /4server/sbin/swapon # # The script aborts if any swap is already active or if /swapfile already # exists, so it is safe to run against the whole fleet. # # Optional first argument: swap size in MiB (default 8192 = 8GB). set -euo pipefail SWAPFILE="/swapfile" SWAP_SIZE_MB="${1:-8192}" FSTAB="/etc/fstab" log() { echo "[$(hostname)] $*" } die() { echo "[$(hostname)] ERROR: $*" >&2 exit 1 } case "$SWAP_SIZE_MB" in ''|*[!0-9]*) die "swap size must be a positive integer in MiB" ;; esac [ "$SWAP_SIZE_MB" -gt 0 ] || die "swap size must be greater than zero" # Remove a partially created swap file if anything fails before it is enabled. CREATED=0 cleanup() { [ "$CREATED" -eq 1 ] || return 0 [ -e "$SWAPFILE" ] || return 0 if grep -q "^${SWAPFILE}[[:space:]]" /proc/swaps; then return 0 fi log "removing incomplete ${SWAPFILE}" rm -f "$SWAPFILE" } trap cleanup EXIT # --- must run as root --------------------------------------------------- [ "$(id -u)" -eq 0 ] || die "must be run as root (use: rex doas /4server/sbin/swapon)" # --- abort if swap is already active ------------------------------------ # /proc/swaps always has a header line; anything more means swap is in use. if [ "$(wc -l < /proc/swaps)" -gt 1 ]; then echo "[$(hostname)] ERROR: swap is already active:" >&2 cat /proc/swaps >&2 exit 1 fi # --- abort if the swap file already exists ------------------------------ if [ -e "$SWAPFILE" ]; then die "$SWAPFILE already exists; remove it manually before recreating swap" fi # --- persistence requires OpenRC's swap service -------------------------- [ -x /etc/init.d/swap ] || \ die "/etc/init.d/swap not found; cannot persist swap across reboots" # --- make sure there is enough room on / --------------------------------- AVAIL_KB=$(df -Pk / | awk 'NR==2 {print $4}') # Leave a 100MiB margin for filesystem metadata. REQUIRED_KB=$((SWAP_SIZE_MB * 1024 + 102400)) [ "$AVAIL_KB" -ge "$REQUIRED_KB" ] || \ die "not enough free space on / (need ${SWAP_SIZE_MB}MiB, have $((AVAIL_KB / 1024))MiB)" # --- create the swap file ----------------------------------------------- log "creating ${SWAP_SIZE_MB}MiB swap file at ${SWAPFILE}" CREATED=1 dd if=/dev/zero of="$SWAPFILE" bs=1M count="$SWAP_SIZE_MB" chmod 600 "$SWAPFILE" /sbin/mkswap "$SWAPFILE" # --- persist across reboots --------------------------------------------- # OpenRC's swap service runs `swapon -a`, which reads /etc/fstab. if ! grep -qE "^[[:space:]]*${SWAPFILE}[[:space:]]" "$FSTAB"; then # Terminate the last line first in case fstab has no trailing newline. [ -z "$(tail -c 1 "$FSTAB")" ] || echo >> "$FSTAB" echo "${SWAPFILE} none swap sw 0 0" >> "$FSTAB" log "added ${SWAPFILE} to ${FSTAB}" fi rc-update add swap boot >/dev/null 2>&1 || \ die "could not add the swap service to the boot runlevel" # --- enable it now ------------------------------------------------------- # Absolute path avoids recursing into this script if /4server/sbin is on PATH. /sbin/swapon "$SWAPFILE" log "swap enabled:" cat /proc/swaps